inital commit
This commit is contained in:
+21
@@ -0,0 +1,21 @@
|
|||||||
|
__pycache__
|
||||||
|
.venv/
|
||||||
|
build/
|
||||||
|
assets/
|
||||||
|
asm/
|
||||||
|
.ninja_log
|
||||||
|
.splache
|
||||||
|
build.ninja
|
||||||
|
permuter_settings.toml
|
||||||
|
Makefile.custom
|
||||||
|
config/**/*.ld
|
||||||
|
config/**/undefined_syms_auto.txt
|
||||||
|
config/**/expected/
|
||||||
|
config/**/include/
|
||||||
|
config/**/cc-src/
|
||||||
|
config/**/tmp_*/
|
||||||
|
config/**/objdiff.json
|
||||||
|
# ignore elf files, such as config/us/SLUS_203.88
|
||||||
|
config/**/[A-Z][A-Z][A-Z][A-Z]_[0-9][0-9][0-9].[0-9][0-9]
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2024 Mikompilation
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
# Disable printing "Entering/Leaving directory ..."
|
||||||
|
MAKEFLAGS += --no-print-directory
|
||||||
|
|
||||||
|
NUMPROC ?= $(shell nproc)
|
||||||
|
|
||||||
|
.PHONY: help \
|
||||||
|
.us-build-only .us-check-files-on-error us-configure us-build us-extract-data us-make-asm us-map-mismatch us-report clean \
|
||||||
|
.eu-build-only .eu-check-files-on-error eu-configure eu-build eu-extract-data eu-make-asm eu-map-mismatch eu-report clean
|
||||||
|
|
||||||
|
.DEFAULT_GOAL := help
|
||||||
|
|
||||||
|
# python script that parses makefiles and pretty-prints help messages
|
||||||
|
define PY_HELP_SCRIPT
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
CYAN = "\033[36m"
|
||||||
|
CRST = "\033[0m"
|
||||||
|
|
||||||
|
makefiles = sys.argv[1:]
|
||||||
|
target_max_len = 0
|
||||||
|
target_help_list = []
|
||||||
|
|
||||||
|
for file in makefiles:
|
||||||
|
with open(file, mode="r") as fh:
|
||||||
|
for line in fh:
|
||||||
|
if match := re.match(r"^([a-zA-Z0-9_-]+):\s*##\s*(.*)$$", line):
|
||||||
|
target, help_str = match.groups()
|
||||||
|
target_max_len = max(target_max_len, len(target))
|
||||||
|
target_help_list.append((target, help_str))
|
||||||
|
|
||||||
|
if match := re.match(r"^##\s*(.*)$$", line):
|
||||||
|
comment = match.group(1)
|
||||||
|
target_help_list.append((None, comment))
|
||||||
|
|
||||||
|
all_targets = [target for target, help_or_comment in target_help_list if target]
|
||||||
|
|
||||||
|
print(f"{CYAN}usage:{CRST} make <{CYAN}{f'{CRST}|{CYAN}'.join(all_targets)}{CRST}>")
|
||||||
|
print()
|
||||||
|
|
||||||
|
for target, help_or_comment in target_help_list:
|
||||||
|
if target:
|
||||||
|
print(f" {CYAN}{target:{target_max_len + 2}s}{CRST} {help_or_comment}")
|
||||||
|
else:
|
||||||
|
print(help_or_comment)
|
||||||
|
|
||||||
|
print()
|
||||||
|
endef
|
||||||
|
|
||||||
|
export PY_HELP_SCRIPT
|
||||||
|
PYHELP := python3 -c "$$PY_HELP_SCRIPT"
|
||||||
|
|
||||||
|
help: ## Show this help
|
||||||
|
@$(PYHELP) $(MAKEFILE_LIST)
|
||||||
|
##
|
||||||
|
## US Commands:
|
||||||
|
us-configure: ## Configure US project (needs SLUS_203.88)
|
||||||
|
@python3 configure.py config/us/ff1.us.yaml -c
|
||||||
|
|
||||||
|
.us-build-only:
|
||||||
|
@cd config/us; \
|
||||||
|
ninja -t clean; \
|
||||||
|
ninja -j$(NUMPROC)
|
||||||
|
|
||||||
|
.us-check-files-on-error:
|
||||||
|
ls -l config/us/build/SLUS_203.88 config/us/SLUS_203.88
|
||||||
|
|
||||||
|
us-build: ## Build US project
|
||||||
|
@$(MAKE) .us-build-only; status=$$?; [ $$status -eq 0 ] || { $(MAKE) .us-check-files-on-error; }; exit $$status
|
||||||
|
|
||||||
|
us-extract-data: ## Extract variables from .data in US config directory
|
||||||
|
@python3 tools/python/parse_data.py us
|
||||||
|
|
||||||
|
us-make-asm: ## Create expected asm folder in US config directory
|
||||||
|
@python3 configure.py config/us/ff1.us.yaml --make-asm
|
||||||
|
|
||||||
|
us-map-mismatch: ## Check for mismatches in US mapfile
|
||||||
|
@python3 tools/python/map_mismatch.py --language us
|
||||||
|
|
||||||
|
us-report: ## Create progress report in US config directory
|
||||||
|
@(stat config/us/expected/obj/ >/dev/null 2>&1 || (echo "Target objects do not exist, please run \`make us-make-asm\`"; false));
|
||||||
|
@(stat config/us/build/src/ >/dev/null 2>&1 || (echo "Base objects do not exist, please run \`make us-build\`"; false));
|
||||||
|
@tools/objdiff/objdiff-cli report generate -p config/us/ -o config/us/report.json -f json
|
||||||
|
@python3 tools/python/fix_report.py config/us/report.json
|
||||||
|
@python3 -c "import json;from pathlib import Path;report=json.loads(Path('config/us/report.json').read_text());print(f\"Progress: {report['measures']['fuzzy_match_percent']:.2f}%\")"
|
||||||
|
|
||||||
|
us-clean: ## Clean artifact in US config directory
|
||||||
|
@cd config/us; \
|
||||||
|
ninja -t clean
|
||||||
|
|
||||||
|
us-reset: ## Resets the US config directory to its original state
|
||||||
|
@python3 configure.py config/us/ff1.us.yaml --reset
|
||||||
|
|
||||||
|
##
|
||||||
|
## EU Commands:
|
||||||
|
eu-configure: ## Configure EU project (needs SLES_508.21)
|
||||||
|
@python3 configure.py config/eu/ff1.eu.yaml -c
|
||||||
|
|
||||||
|
.eu-build-only:
|
||||||
|
@cd config/eu; \
|
||||||
|
ninja -t clean; \
|
||||||
|
ninja -j$(NUMPROC)
|
||||||
|
|
||||||
|
.eu-check-files-on-error:
|
||||||
|
ls -l config/eu/build/SLES_508.21 config/eu/SLES_508.21
|
||||||
|
|
||||||
|
eu-build: ## Build EU project
|
||||||
|
@$(MAKE) .eu-build-only; status=$$?; [ $$status -eq 0 ] || { $(MAKE) .eu-check-files-on-error; }; exit $$status
|
||||||
|
|
||||||
|
eu-extract-data: ## Extract initialized variables from .data in EU config directory
|
||||||
|
@python3 tools/python/parse_data.py eu
|
||||||
|
|
||||||
|
eu-make-asm: ## Create expected asm folder in EU config directory
|
||||||
|
@python3 configure.py config/eu/ff1.eu.yaml --make-asm
|
||||||
|
|
||||||
|
eu-map-mismatch: ## Check for mismatches in EU mapfile
|
||||||
|
@python3 tools/python/map_mismatch.py --language eu
|
||||||
|
|
||||||
|
eu-report: ## Create progress report in EU config directory
|
||||||
|
@(stat config/eu/expected/obj/ >/dev/null 2>&1 || (echo "Target objects do not exist, please run \`make eu-make-asm\`"; false));
|
||||||
|
@(stat config/eu/build/src/ >/dev/null 2>&1 || (echo "Base objects do not exist, please run \`make eu-build\`"; false));
|
||||||
|
@tools/objdiff/objdiff-cli report generate -p config/eu/ -o config/eu/report.json -f json
|
||||||
|
@python3 tools/python/fix_report.py config/eu/report.json
|
||||||
|
@python3 -c "import json;from pathlib import Path;report=json.loads(Path('config/eu/report.json').read_text());print(f\"Progress: {report['measures']['fuzzy_match_percent']:.2f}%\")"
|
||||||
|
|
||||||
|
eu-clean: ## Clean artifact in US config directory
|
||||||
|
@cd config/eu; \
|
||||||
|
ninja -t clean
|
||||||
|
|
||||||
|
eu-reset: ## Resets the EU config directory to its original state
|
||||||
|
@python3 configure.py config/eu/ff1.eu.yaml --reset
|
||||||
|
|
||||||
|
# Include custom makefile for user-defined commands
|
||||||
|
-include Makefile.custom
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
# Himuro / ひむろ
|
||||||
|
## What is Himuro?
|
||||||
|
Himuro is a project that aims to have a matching source decompilation of the PS2 game Fatal Frame 1; Project Zero; <ruby>零<rt>ぜろ</rt></ruby>. Once we have a matching decompiled rom we want to port the game to modern hardware.
|
||||||
|
|
||||||
|
## Progress
|
||||||
|
| Name | Region | Game ID | Progress (powered by [decomp.dev](https://decomp.dev/))
|
||||||
|
|----------------|--------|-------------|--------------------------------
|
||||||
|
| Fatal Frame | US | SLUS_203.88 | [](https://decomp.dev/Mikompilation/Himuro/SLUS_203.88)⠀ [](https://decomp.dev/Mikompilation/Himuro/SLUS_203.88)
|
||||||
|
| Project Zero | EU | SLES_508.21 |[](https://decomp.dev/Mikompilation/Himuro/SLES_508.21)⠀ [](https://decomp.dev/Mikompilation/Himuro/SLES_508.21)
|
||||||
|
|
||||||
|
## Disclaimer
|
||||||
|
No game assets are hosted on this repository. You must provide them yourself, copying them from a legal copy.
|
||||||
|
|
||||||
|
|
||||||
|
## Getting Started & Building
|
||||||
|
Linux is required in order to build this project. It requires a compiler that is only available for Linux. You'll also need at least `python 3.8` to run any command. Your linux distribution should come with `python3` already installed. If not, please follow your distribution's instructions to install it. Python is a mandatory dependency, as many core tools are written in python. On Ubuntu, if necessary, python3 can be installed with the following command:
|
||||||
|
```bash
|
||||||
|
sudo apt install python3-full
|
||||||
|
```
|
||||||
|
|
||||||
|
### Add i386 architecture
|
||||||
|
The original GCC compiler is a 32-bit executable, so on a 64-bit system the `i386` architecture must be added in order for the system to run it. On Ubuntu you can use the following commands:
|
||||||
|
```bash
|
||||||
|
sudo dpkg --add-architecture i386
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install libc6:i386 libstdc++6:i386
|
||||||
|
```
|
||||||
|
|
||||||
|
### Install dependencies
|
||||||
|
```bash
|
||||||
|
sudo apt install make binutils-mips-linux-gnu gcc-mips-linux-gnu python3-venv
|
||||||
|
```
|
||||||
|
|
||||||
|
### Setup a Virtual Environment for Python
|
||||||
|
Python's virtual environments are the preferred way to use this software, as you may not be allowed to install packages globally.
|
||||||
|
```bash
|
||||||
|
python3 -m venv .venv
|
||||||
|
source .venv/bin/activate
|
||||||
|
python3 -m pip install -r requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### Copy assets from game DVD/ISO
|
||||||
|
The main executable is needed in order to perform the decompilation.
|
||||||
|
#### EU
|
||||||
|
Copy `SLES_508.21` from DVD/ISO into `config/eu/`. File **must** have the following sha1 hash:
|
||||||
|
```
|
||||||
|
cb36d4365e70be9e9dc5bb66e2aa083811a39f12
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### US
|
||||||
|
Copy `SLUS_203.88` from DVD/ISO into `config/us/`. File **must** have the following sha1 hash:
|
||||||
|
```
|
||||||
|
5ac4626e0d76218e977b01f4fae5948de9a1755e
|
||||||
|
```
|
||||||
|
|
||||||
|
### Extract data
|
||||||
|
NOTE: this operation needs to be performed only once.
|
||||||
|
#### EU
|
||||||
|
```bash
|
||||||
|
make eu-extract-data
|
||||||
|
```
|
||||||
|
|
||||||
|
#### US
|
||||||
|
```bash
|
||||||
|
make us-extract-data
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configure the project
|
||||||
|
NOTE: running these commands on an already configured project will reconfigure it.
|
||||||
|
#### EU
|
||||||
|
```bash
|
||||||
|
make eu-configure
|
||||||
|
```
|
||||||
|
|
||||||
|
#### US
|
||||||
|
```bash
|
||||||
|
make us-configure
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compile
|
||||||
|
#### EU
|
||||||
|
```bash
|
||||||
|
make eu-build
|
||||||
|
```
|
||||||
|
|
||||||
|
#### US
|
||||||
|
```bash
|
||||||
|
make us-build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Clean Artifacts
|
||||||
|
#### EU
|
||||||
|
```bash
|
||||||
|
make eu-clean
|
||||||
|
```
|
||||||
|
|
||||||
|
#### US
|
||||||
|
```bash
|
||||||
|
make us-clean
|
||||||
|
```
|
||||||
|
|
||||||
|
### Command Help
|
||||||
|
To have a list all available commands, run `make` without targets:
|
||||||
|
```bash
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
## Decompiling a TU
|
||||||
|
1. Add the decompiled code to the TU's `c` file in `src/`
|
||||||
|
2. Update `config/{region}/ff1.{region}.yaml`:
|
||||||
|
1. Replace `asm` with `c` for the TU you are decompiling
|
||||||
|
2. Add a leading dot (`.`) to the type (e.g., `rodata` -> `.rodata`) of each subsection that belongs to the TU
|
||||||
|
3. Reconfigure the project
|
||||||
|
4. Build the project
|
||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
5ac4626e0d76218e977b01f4fae5948de9a1755e build/SLUS_203.88
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,753 @@
|
|||||||
|
name: Kuon
|
||||||
|
sha1: 5ac4626e0d76218e977b01f4fae5948de9a1755e
|
||||||
|
options:
|
||||||
|
basename: SLUS_210.07
|
||||||
|
target_path: SLUS_210.07
|
||||||
|
base_path: .
|
||||||
|
asm_path: asm
|
||||||
|
src_path: ../../src
|
||||||
|
build_path: build
|
||||||
|
asset_path: assets
|
||||||
|
compiler: EEGCC
|
||||||
|
find_file_boundaries: False
|
||||||
|
platform: ps2
|
||||||
|
string_encoding: EUC-JP
|
||||||
|
create_undefined_funcs_auto: False
|
||||||
|
create_undefined_syms_auto: True
|
||||||
|
undefined_funcs_auto_path: undefined_funcs_auto.txt
|
||||||
|
undefined_syms_auto_path: undefined_syms_auto.txt
|
||||||
|
symbol_addrs_path: symbol_addrs.txt
|
||||||
|
extensions_path: ../../tools/splat_ext
|
||||||
|
section_order: [".text", ".vutext", ".data", ".vudata", ".rodata", ".lit4", ".sdata", ".sbss", ".bss", ".vubss"]
|
||||||
|
#auto_all_sections: [".data", ".sdata", ".sbss", ".lit4", ".rodata", ".bss"]
|
||||||
|
disasm_unknown: True
|
||||||
|
subalign: 4
|
||||||
|
named_regs_for_c_funcs: False
|
||||||
|
gp_value: 0x35d070
|
||||||
|
ld_bss_is_noload: true
|
||||||
|
# custom field used by fix_linkerscript.py to fix linkerscript alignments
|
||||||
|
_section_subalign:
|
||||||
|
elf_header: 8
|
||||||
|
main: 2
|
||||||
|
main_bss: 1
|
||||||
|
reg_info: 4
|
||||||
|
mips_debug: 4
|
||||||
|
rest: 4
|
||||||
|
segments:
|
||||||
|
- [0, databin, elf_header]
|
||||||
|
- name: main
|
||||||
|
type: code
|
||||||
|
start: 0x1000
|
||||||
|
vram: 0x100000
|
||||||
|
bss_size: 0x0b3024 # size of .sbss + size of .bss
|
||||||
|
align: 1
|
||||||
|
subalign: 2 # safe subalign value. proper values are applied by fix_linkerscript.py where necessary
|
||||||
|
# text has align 8 but other sections may have a different alignment ...
|
||||||
|
# explicit align correction is performed by fix_linkerscript.py during
|
||||||
|
# project configuration. vram address is used, when reported, in non text
|
||||||
|
# sections to calculate the correct align value.
|
||||||
|
subsegments:
|
||||||
|
- [0x1000, asm, crt0]
|
||||||
|
- [0x10c8, c, main/main]
|
||||||
|
- [0x1380, c, outgame/mode_slct]
|
||||||
|
- [0x4b30, c, outgame/memory_album]
|
||||||
|
- [0xbf68, c, main/gamemain]
|
||||||
|
- [0xc2f8, c, main/glob]
|
||||||
|
- [0xc2f8, c, os/system]
|
||||||
|
- [0xc938, c, os/fileload]
|
||||||
|
- [0xcaa0, c, os/key_cnf]
|
||||||
|
- [0xcc48, c, os/backup]
|
||||||
|
- [0xcee0, c, os/pad]
|
||||||
|
- [0xda68, c, os/eeiop/eeiop]
|
||||||
|
- [0xde20, c, os/eeiop/cdvd/eecdvd]
|
||||||
|
- [0xe308, c, os/eeiop/adpcm/ea_ctrl]
|
||||||
|
- [0xeec8, c, os/eeiop/adpcm/ea_cmd]
|
||||||
|
- [0xf308, c, os/eeiop/adpcm/ea_dat]
|
||||||
|
- [0xf358, c, os/eeiop/adpcm/ea_btlmode]
|
||||||
|
- [0xf658, c, os/eeiop/adpcm/ea_gameover]
|
||||||
|
- [0xf860, c, os/eeiop/adpcm/ea_scene]
|
||||||
|
- [0xfb10, c, os/eeiop/adpcm/ea_magatoki]
|
||||||
|
- [0xfe40, c, os/eeiop/adpcm/ea_shinkan]
|
||||||
|
- [0x10178, c, os/eeiop/adpcm/ea_puzzle]
|
||||||
|
- [0x10478, c, os/eeiop/adpcm/ea_soul]
|
||||||
|
- [0x10740, c, os/eeiop/adpcm/ea_tape]
|
||||||
|
- [0x10948, c, os/eeiop/adpcm/ea_gdead]
|
||||||
|
- [0x10b78, c, os/eeiop/adpcm/ea_event]
|
||||||
|
- [0x10f98, c, os/eeiop/adpcm/ea_ghost]
|
||||||
|
- [0x11400, c, os/eeiop/adpcm/ea_autog]
|
||||||
|
- [0x11958, c, os/eeiop/adpcm/ea_hiso]
|
||||||
|
- [0x11d18, c, os/eeiop/adpcm/ea_furn]
|
||||||
|
- [0x12218, c, os/eeiop/adpcm/ea_map]
|
||||||
|
- [0x12460, c, os/eeiop/eese]
|
||||||
|
- [0x14108, c, os/eeiop/se_cmd]
|
||||||
|
- [0x14788, c, os/eeiop/se_data]
|
||||||
|
- [0x14c88, c, os/eeiop/se_ev]
|
||||||
|
- [0x14fe8, c, os/eeiop/se_trans]
|
||||||
|
- [0x15420, c, os/eeiop/se_door]
|
||||||
|
- [0x15958, c, os/eeiop/se_foot]
|
||||||
|
- [0x15e10, c, os/eeiop/se_event]
|
||||||
|
- [0x16150, c, os/eeiop/se_srund]
|
||||||
|
- [0x16490, c, os/eeiop/sd_room]
|
||||||
|
- [0x16680, c, os/eeiop/se_plyr]
|
||||||
|
- [0x16cd0, c, common/ul_math]
|
||||||
|
- [0x16fc8, c, common/utility]
|
||||||
|
- [0x17028, c, graphics/graph2d/compress]
|
||||||
|
- [0x18a08, c, graphics/graph2d/effect]
|
||||||
|
- [0x1b160, c, graphics/graph2d/effect_sub]
|
||||||
|
- [0x21398, c, graphics/graph2d/effect_sub2]
|
||||||
|
- [0x28e40, c, graphics/graph2d/effect_scr]
|
||||||
|
- [0x32a70, c, graphics/graph2d/effect_obj]
|
||||||
|
- [0x37430, c, graphics/graph2d/effect_oth]
|
||||||
|
- [0x47330, c, graphics/graph2d/effect_rdr]
|
||||||
|
- [0x48ab8, c, graphics/graph2d/effect_ene]
|
||||||
|
- [0x53ed0, c, graphics/graph2d/g2d_debug]
|
||||||
|
- [0x55db8, c, graphics/graph2d/g2d_main]
|
||||||
|
- [0x56048, c, graphics/graph2d/message]
|
||||||
|
- [0x5a8a8, c, graphics/graph2d/number]
|
||||||
|
- [0x5ac98, c, graphics/graph2d/snapshot]
|
||||||
|
- [0x5af10, c, graphics/graph2d/tim2]
|
||||||
|
- [0x5eb40, c, graphics/graph2d/tim2_new]
|
||||||
|
- [0x5fd58, c, graphics/graph2d/rare_ene]
|
||||||
|
- [0x60b88, c, graphics/graph3d/gra3d]
|
||||||
|
- [0x65240, c, graphics/graph3d/leditor]
|
||||||
|
- [0x66580, c, graphics/graph3d/load3d]
|
||||||
|
- [0x676b0, c, graphics/motion/mdldat]
|
||||||
|
- [0x676b0, c, graphics/motion/mdlwork]
|
||||||
|
- [0x68d88, c, graphics/motion/mdlact]
|
||||||
|
- [0x69cc0, c, graphics/motion/mime]
|
||||||
|
- [0x6b7c8, c, graphics/motion/accessory]
|
||||||
|
- [0x6f4e0, c, graphics/motion/motion]
|
||||||
|
- [0x72508, c, graphics/motion/anicode]
|
||||||
|
- [0x72dc0, c, graphics/motion/mim_dat]
|
||||||
|
- [0x72dc0, c, graphics/motion/acs_dat]
|
||||||
|
- [0x72dc0, c, graphics/graph3d/object]
|
||||||
|
- [0x72df8, c, graphics/graph3d/sce_pp3]
|
||||||
|
- [0x73050, c, graphics/graph3d/sgsgd]
|
||||||
|
- [0x739e8, c, graphics/graph3d/sglib]
|
||||||
|
- [0x747f0, c, graphics/graph3d/sgsu]
|
||||||
|
- [0x75f60, c, graphics/graph3d/sgdma]
|
||||||
|
- [0x76aa0, c, graphics/graph3d/sglight]
|
||||||
|
- [0x79c48, c, graphics/graph3d/sgsup]
|
||||||
|
- [0x7a9c8, c, graphics/graph3d/sgcam]
|
||||||
|
- [0x7ba68, c, graphics/graph3d/shadow]
|
||||||
|
- [0x7e4d8, c, graphics/graph3d/mirror]
|
||||||
|
- [0x7fcc8, c, graphics/mov/movie]
|
||||||
|
- [0x83f30, c, graphics/scene/fod]
|
||||||
|
- [0x85960, c, graphics/scene/scene]
|
||||||
|
- [0x88800, c, graphics/scene/scene_dat]
|
||||||
|
- [0x88800, c, ingame/ingame]
|
||||||
|
- [0x89578, c, ingame/ig_init]
|
||||||
|
- [0x89ae0, c, ingame/ig_glob]
|
||||||
|
- [0x89ae0, c, ingame/camera/camera]
|
||||||
|
- [0x8e618, c, ingame/enemy/ene_ctl]
|
||||||
|
- [0x91ea8, c, ingame/enemy/move_ctl]
|
||||||
|
- [0x99728, c, ingame/entry/entry]
|
||||||
|
- [0x99910, c, ingame/plyr/time_ctl]
|
||||||
|
- [0x99cc0, c, ingame/entry/ap_bgost]
|
||||||
|
- [0x99fd8, c, ingame/entry/ap_dgost]
|
||||||
|
- [0x9a4e8, c, ingame/entry/ap_fgost]
|
||||||
|
- [0x9b190, c, ingame/entry/ap_ggost]
|
||||||
|
- [0x9b880, c, ingame/entry/ap_pgost]
|
||||||
|
- [0x9be50, c, ingame/entry/ap_rgost]
|
||||||
|
- [0x9cd50, c, ingame/entry/ap_sgost]
|
||||||
|
- [0x9dc18, c, ingame/entry/ap_zgost]
|
||||||
|
- [0x9e508, c, ingame/entry/fgst_dat]
|
||||||
|
- [0x9e508, c, ingame/entry/rgst_dat]
|
||||||
|
- [0x9e508, c, ingame/event/ev_main]
|
||||||
|
- [0xa07c0, c, ingame/event/ev_spcl]
|
||||||
|
- [0xb1cf0, c, ingame/event/ev_load]
|
||||||
|
- [0xb30f0, c, ingame/event/mv_cmnd]
|
||||||
|
- [0xb3250, c, ingame/info/inf_disp]
|
||||||
|
- [0xbaa00, c, ingame/map/map_ctrl]
|
||||||
|
- [0xbe398, c, ingame/map/map_area]
|
||||||
|
- [0xbece0, c, ingame/map/door_ctl]
|
||||||
|
- [0xc66d0, c, ingame/map/doortype]
|
||||||
|
- [0xc67f8, c, ingame/map/rotd_ctl]
|
||||||
|
- [0xc6d60, c, ingame/map/find_ctl]
|
||||||
|
- [0xc7118, c, ingame/map/find_dat]
|
||||||
|
- [0xc7118, c, ingame/map/furn_ctl]
|
||||||
|
- [0xc8b98, c, ingame/map/furn_dat]
|
||||||
|
- [0xc8bb8, c, ingame/map/furn_eff]
|
||||||
|
- [0xc9148, c, ingame/map/item_ctl]
|
||||||
|
- [0xc9ca8, c, ingame/map/map_htck]
|
||||||
|
- [0xca958, c, ingame/map/furn_spe/furn_spe]
|
||||||
|
- [0xce500, c, ingame/map/furn_spe/fsla_main]
|
||||||
|
- [0xcece8, c, ingame/map/furn_spe/fsla_dat]
|
||||||
|
- [0xcece8, c, ingame/map/furn_spe/fspe_acs]
|
||||||
|
- [0xced88, c, ingame/map/furn_spe/adj_valg]
|
||||||
|
- [0xcf0a0, c, ingame/menu/item]
|
||||||
|
- [0xd4a28, c, ingame/menu/gameover]
|
||||||
|
- [0xd5070, c, ingame/menu/pause]
|
||||||
|
- [0xd5a10, c, ingame/menu/ig_album]
|
||||||
|
- [0xdd1e8, c, ingame/menu/ig_camra]
|
||||||
|
- [0xe0cd0, c, ingame/menu/ig_menu]
|
||||||
|
- [0xe5538, c, ingame/menu/ig_spd_menu]
|
||||||
|
- [0xe5de0, c, ingame/menu/item_get]
|
||||||
|
- [0xe78b8, c, ingame/menu/ig_file]
|
||||||
|
- [0xee668, c, ingame/menu/ig_rank]
|
||||||
|
- [0xf1970, c, ingame/menu/ig_glst]
|
||||||
|
- [0xf3d78, c, ingame/menu/ig_map]
|
||||||
|
- [0xf7268, c, ingame/menu/ig_option]
|
||||||
|
- [0xfa1c8, c, ingame/menu/sp_menu]
|
||||||
|
- [0x100458, c, ingame/map/door_conte]
|
||||||
|
- [0x100838, c, ingame/photo/photo]
|
||||||
|
- [0x1012b8, c, ingame/photo/pht_main]
|
||||||
|
- [0x101af0, c, ingame/photo/pht_make]
|
||||||
|
- [0x1059a8, c, ingame/plyr/plyr_ctl]
|
||||||
|
- [0x10e5b0, c, ingame/plyr/unit_ctl]
|
||||||
|
- [0x10ed38, c, edit/test_2d]
|
||||||
|
- [0x10ef08, c, outgame/scn_test]
|
||||||
|
- [0x113ca8, c, outgame/title]
|
||||||
|
- [0x116dd0, c, graphics/graph2d/takep_pe]
|
||||||
|
- [0x117b58, c, mc/mc]
|
||||||
|
- [0x117b58, c, mc/mc_main]
|
||||||
|
- [0x119b60, c, mc/mc_acs]
|
||||||
|
- [0x11a4b8, c, mc/mc_album]
|
||||||
|
- [0x11b000, c, mc/mc_exec]
|
||||||
|
- [0x11c3d0, c, mc/mc_start]
|
||||||
|
- [0x11c998, c, mc/mc_icon]
|
||||||
|
- [0x11c998, c, mc/mc_disp]
|
||||||
|
- [0x11caa8, c, mc/mc_at]
|
||||||
|
- [0x11d260, c, outgame/outgame]
|
||||||
|
- [0x11d988, c, outgame/btl_mode/btl_menu]
|
||||||
|
- [0x11ed08, c, outgame/btl_mode/btl_mode]
|
||||||
|
- [0x11f5d0, c, outgame/btl_mode/btl_dat]
|
||||||
|
- [0x11f5d0, c, ingame/event/wan_soul]
|
||||||
|
- [0x121030, c, ingame/event/wan_dat]
|
||||||
|
- [0x121098, c, outgame/sound_test]
|
||||||
|
- [0x1225c0, textbin, text_rest]
|
||||||
|
- [0x1475b0, textbin, vutext]
|
||||||
|
# ######################## DATA (vram: 0x250180) #####################################
|
||||||
|
- { start: 0x151180, type: .data, vram: 0x250180, name: outgame/mode_slct }
|
||||||
|
- { start: 0x152ae0, type: .data, vram: 0x251ae0, name: outgame/memory_album }
|
||||||
|
- { start: 0x1532c0, type: .data, vram: 0x2522c0, name: main/glob }
|
||||||
|
- { start: 0x166eb0, type: .data, vram: 0x265eb0, name: os/system }
|
||||||
|
- { start: 0x1670e0, type: .data, vram: 0x2660e0, name: os/key_cnf }
|
||||||
|
- { start: 0x167200, type: .data, vram: 0x266200, name: os/pad }
|
||||||
|
- { start: 0x167240, type: .data, vram: 0x266240, name: os/eeiop/eeiop }
|
||||||
|
- { start: 0x167800, type: .data, vram: 0x266800, name: os/eeiop/adpcm/ea_ctrl }
|
||||||
|
- { start: 0x167c40, type: .data, vram: 0x266c40, name: os/eeiop/adpcm/ea_dat }
|
||||||
|
- { start: 0x1687c0, type: .data, vram: 0x2677c0, name: os/eeiop/eese }
|
||||||
|
- { start: 0x168838, type: .data, vram: 0x267838, name: os/eeiop/se_data }
|
||||||
|
- { start: 0x168870, type: .data, vram: 0x267870, name: os/eeiop/se_ev }
|
||||||
|
- { start: 0x168930, type: .data, vram: 0x267930, name: os/eeiop/se_trans }
|
||||||
|
- { start: 0x168960, type: .data, vram: 0x267960, name: os/eeiop/sd_room }
|
||||||
|
- { start: 0x169350, type: .data, vram: 0x268350, name: os/eeiop/se_plyr }
|
||||||
|
- { start: 0x169388, type: .data, vram: 0x268388, name: graphics/graph2d/compress }
|
||||||
|
- { start: 0x16ce40, type: .data, vram: 0x26be40, name: graphics/graph2d/effect }
|
||||||
|
- { start: 0x171e20, type: .data, vram: 0x270e20, name: graphics/graph2d/effect_sub }
|
||||||
|
- { start: 0x171e30, type: .data, vram: 0x270e30, name: graphics/graph2d/effect_sub2 }
|
||||||
|
- { start: 0x1819f0, type: .data, vram: 0x2809f0, name: graphics/graph2d/effect_scr }
|
||||||
|
- { start: 0x181a70, type: .data, vram: 0x280a70, name: graphics/graph2d/effect_obj }
|
||||||
|
- { start: 0x198440, type: .data, vram: 0x297440, name: graphics/graph2d/effect_oth }
|
||||||
|
- { start: 0x198ad0, type: .data, vram: 0x297ad0, name: graphics/graph2d/effect_rdr }
|
||||||
|
- { start: 0x1991f0, type: .data, vram: 0x2981f0, name: graphics/graph2d/effect_ene }
|
||||||
|
- { start: 0x1a8580, type: .data, vram: 0x2a7580, name: graphics/graph2d/g2d_debug }
|
||||||
|
- { start: 0x1aab58, type: .data, vram: 0x2a9b58, name: graphics/graph2d/message }
|
||||||
|
- { start: 0x1ac388, type: .data, vram: 0x2ab388, name: graphics/graph2d/number }
|
||||||
|
- { start: 0x1ac890, type: .data, vram: 0x2ab890, name: graphics/graph2d/tim2 }
|
||||||
|
- { start: 0x1f6890, type: .data, vram: 0x2f5890, name: graphics/graph2d/rare_ene }
|
||||||
|
- { start: 0x1f6d80, type: .data, vram: 0x2f5d80, name: graphics/graph3d/gra3d }
|
||||||
|
- { start: 0x1f9f40, type: .data, vram: 0x2f8f40, name: graphics/graph3d/leditor }
|
||||||
|
- { start: 0x1fa008, type: .data, vram: 0x2f9008, name: graphics/graph3d/load3d }
|
||||||
|
- { start: 0x1fb4e0, type: .data, vram: 0x2fa4e0, name: graphics/motion/mdldat }
|
||||||
|
- { start: 0x1fd8a8, type: .data, vram: 0x2fc8a8, name: graphics/motion/mdlwork }
|
||||||
|
- { start: 0x1fd8e8, type: .data, vram: 0x2fc8e8, name: graphics/motion/mdlact }
|
||||||
|
- { start: 0x1fda80, type: .data, vram: 0x2fca80, name: graphics/motion/accessory }
|
||||||
|
- { start: 0x2013f0, type: .data, vram: 0x3003f0, name: graphics/motion/motion }
|
||||||
|
- { start: 0x2034c0, type: .data, vram: 0x3024c0, name: graphics/motion/mim_dat }
|
||||||
|
- { start: 0x203640, type: .data, vram: 0x302640, name: graphics/motion/acs_dat }
|
||||||
|
- { start: 0x204810, type: .data, vram: 0x303810, name: graphics/graph3d/sglib }
|
||||||
|
- { start: 0x204d00, type: .data, vram: 0x303d00, name: graphics/graph3d/sgsu }
|
||||||
|
- { start: 0x204d10, type: .data, vram: 0x303d10, name: graphics/graph3d/sgdma }
|
||||||
|
- { start: 0x204d20, type: .data, vram: 0x303d20, name: graphics/graph3d/sgsup }
|
||||||
|
- { start: 0x204d40, type: .data, vram: 0x303d40, name: graphics/graph3d/sgcam }
|
||||||
|
- { start: 0x204d60, type: .data, vram: 0x303d60, name: graphics/graph3d/shadow }
|
||||||
|
- { start: 0x2054e0, type: .data, vram: 0x3044e0, name: graphics/graph3d/mirror }
|
||||||
|
- { start: 0x205640, type: .data, vram: 0x304640, name: graphics/mov/movie }
|
||||||
|
- { start: 0x205aa0, type: .data, vram: 0x304aa0, name: graphics/scene/fod }
|
||||||
|
- { start: 0x205bc0, type: .data, vram: 0x304bc0, name: graphics/scene/scene }
|
||||||
|
- { start: 0x20eab0, type: .data, vram: 0x30dab0, name: graphics/scene/scene_dat }
|
||||||
|
- { start: 0x20fa70, type: .data, vram: 0x30ea70, name: ingame/ig_glob }
|
||||||
|
- { start: 0x21b6c0, type: .data, vram: 0x31a6c0, name: ingame/camera/camera }
|
||||||
|
- { start: 0x221060, type: .data, vram: 0x320060, name: ingame/enemy/ene_ctl }
|
||||||
|
- { start: 0x223550, type: .data, vram: 0x322550, name: ingame/enemy/move_ctl }
|
||||||
|
- { start: 0x223778, type: .data, vram: 0x322778, name: ingame/entry/entry }
|
||||||
|
- { start: 0x2237d8, type: .data, vram: 0x3227d8, name: ingame/entry/ap_bgost }
|
||||||
|
- { start: 0x2237e8, type: .data, vram: 0x3227e8, name: ingame/entry/ap_dgost }
|
||||||
|
- { start: 0x223810, type: .data, vram: 0x322810, name: ingame/entry/ap_fgost }
|
||||||
|
- { start: 0x223840, type: .data, vram: 0x322840, name: ingame/entry/ap_ggost }
|
||||||
|
- { start: 0x223898, type: .data, vram: 0x322898, name: ingame/entry/ap_pgost }
|
||||||
|
- { start: 0x2238e0, type: .data, vram: 0x3228e0, name: ingame/entry/ap_rgost }
|
||||||
|
- { start: 0x223c60, type: .data, vram: 0x322c60, name: ingame/entry/ap_sgost }
|
||||||
|
- { start: 0x223f30, type: .data, vram: 0x322f30, name: ingame/entry/ap_zgost }
|
||||||
|
- { start: 0x223f60, type: .data, vram: 0x322f60, name: ingame/entry/fgst_dat }
|
||||||
|
- { start: 0x227220, type: .data, vram: 0x326220, name: ingame/entry/rgst_dat }
|
||||||
|
- { start: 0x227428, type: .data, vram: 0x326428, name: ingame/event/ev_main }
|
||||||
|
- { start: 0x227558, type: .data, vram: 0x326558, name: ingame/event/ev_spcl }
|
||||||
|
- { start: 0x229530, type: .data, vram: 0x328530, name: ingame/event/ev_load }
|
||||||
|
- { start: 0x22a870, type: .data, vram: 0x329870, name: ingame/info/inf_disp }
|
||||||
|
- { start: 0x2330e8, type: .data, vram: 0x3320e8, name: ingame/map/map_ctrl }
|
||||||
|
- { start: 0x233120, type: .data, vram: 0x332120, name: ingame/map/map_area }
|
||||||
|
- { start: 0x2336b0, type: .data, vram: 0x3326b0, name: ingame/map/door_ctl }
|
||||||
|
- { start: 0x234b40, type: .data, vram: 0x333b40, name: ingame/map/doortype }
|
||||||
|
- { start: 0x237c48, type: .data, vram: 0x336c48, name: ingame/map/find_ctl }
|
||||||
|
- { start: 0x237d68, type: .data, vram: 0x336d68, name: ingame/map/find_dat }
|
||||||
|
- { start: 0x238730, type: .data, vram: 0x337730, name: ingame/map/furn_dat }
|
||||||
|
- { start: 0x23af10, type: .data, vram: 0x339f10, name: ingame/map/furn_eff }
|
||||||
|
- { start: 0x23b130, type: .data, vram: 0x33a130, name: ingame/map/item_ctl }
|
||||||
|
- { start: 0x23c9e0, type: .data, vram: 0x33b9e0, name: ingame/map/furn_spe/furn_spe }
|
||||||
|
- { start: 0x23de10, type: .data, vram: 0x33ce10, name: ingame/map/furn_spe/fsla_main }
|
||||||
|
- { start: 0x23e0a0, type: .data, vram: 0x33d0a0, name: ingame/map/furn_spe/fsla_dat }
|
||||||
|
- { start: 0x23e2d8, type: .data, vram: 0x33d2d8, name: ingame/menu/item }
|
||||||
|
- { start: 0x23e870, type: .data, vram: 0x33d870, name: ingame/menu/ig_camra }
|
||||||
|
- { start: 0x23e8c8, type: .data, vram: 0x33d8c8, name: ingame/menu/ig_menu }
|
||||||
|
- { start: 0x23e950, type: .data, vram: 0x33d950, name: ingame/menu/item_get }
|
||||||
|
- { start: 0x23e998, type: .data, vram: 0x33d998, name: ingame/menu/ig_file }
|
||||||
|
- { start: 0x240270, type: .data, vram: 0x33f270, name: ingame/menu/ig_rank }
|
||||||
|
- { start: 0x240390, type: .data, vram: 0x33f390, name: ingame/menu/ig_glst }
|
||||||
|
- { start: 0x2407e0, type: .data, vram: 0x33f7e0, name: ingame/menu/ig_map }
|
||||||
|
- { start: 0x240ab0, type: .data, vram: 0x33fab0, name: ingame/photo/photo }
|
||||||
|
- { start: 0x240bd8, type: .data, vram: 0x33fbd8, name: ingame/photo/pht_make }
|
||||||
|
- { start: 0x242058, type: .data, vram: 0x341058, name: ingame/plyr/plyr_ctl }
|
||||||
|
- { start: 0x242128, type: .data, vram: 0x341128, name: edit/test_2d }
|
||||||
|
- { start: 0x242370, type: .data, vram: 0x341370, name: outgame/scn_test }
|
||||||
|
- { start: 0x243c90, type: .data, vram: 0x342c90, name: outgame/title }
|
||||||
|
- { start: 0x244080, type: .data, vram: 0x343080, name: graphics/graph2d/takep_pe }
|
||||||
|
- { start: 0x244140, type: .data, vram: 0x343140, name: mc/mc }
|
||||||
|
- { start: 0x244280, type: .data, vram: 0x343280, name: mc/mc_main }
|
||||||
|
- { start: 0x244f60, type: .data, vram: 0x343f60, name: mc/mc_acs }
|
||||||
|
- { start: 0x244f88, type: .data, vram: 0x343f88, name: mc/mc_start }
|
||||||
|
- { start: 0x244fa8, type: .data, vram: 0x343fa8, name: mc/mc_icon }
|
||||||
|
- { start: 0x244fc0, type: .data, vram: 0x343fc0, name: outgame/btl_mode/btl_menu }
|
||||||
|
- { start: 0x245670, type: .data, vram: 0x344670, name: outgame/btl_mode/btl_mode }
|
||||||
|
- { start: 0x245850, type: .data, vram: 0x344850, name: outgame/btl_mode/btl_dat }
|
||||||
|
- { start: 0x246750, type: .data, vram: 0x345750, name: ingame/event/wan_soul }
|
||||||
|
- { start: 0x246820, type: .data, vram: 0x345820, name: ingame/event/wan_dat }
|
||||||
|
- { start: 0x246de8, type: .data, vram: 0x345de8, name: outgame/sound_test }
|
||||||
|
- { start: 0x246e80, type: data, vram: 0x345e80, name: data_rest }
|
||||||
|
# ######################## VUDATA (vram: 0x349608) #####################################
|
||||||
|
- { start: 0x24a608, type: databin, vram: 0x349608, name: vudata }
|
||||||
|
# ######################## RODATA (vram: 0x349680) #####################################
|
||||||
|
- { start: 0x24a680, type: .rodata, vram: 0x349680, name: outgame/mode_slct }
|
||||||
|
- { start: 0x24a7e0, type: .rodata, vram: 0x3497e0, name: outgame/memory_album }
|
||||||
|
- { start: 0x24a8b0, type: .rodata, vram: 0x3498b0, name: main/gamemain }
|
||||||
|
- { start: 0x24a8d0, type: .rodata, vram: 0x3498d0, name: os/system }
|
||||||
|
- { start: 0x24a990, type: .rodata, vram: 0x349990, name: os/backup }
|
||||||
|
- { start: 0x24a9b0, type: .rodata, vram: 0x3499b0, name: os/pad }
|
||||||
|
- { start: 0x24a9c0, type: .rodata, vram: 0x3499c0, name: os/eeiop/eeiop }
|
||||||
|
- { start: 0x24a9f0, type: .rodata, vram: 0x3499f0, name: os/eeiop/adpcm/ea_ctrl }
|
||||||
|
- { start: 0x24aa30, type: .rodata, vram: 0x349a30, name: os/eeiop/adpcm/ea_btlmode }
|
||||||
|
- { start: 0x24aa50, type: .rodata, vram: 0x349a50, name: os/eeiop/adpcm/ea_scene }
|
||||||
|
- { start: 0x24aa70, type: .rodata, vram: 0x349a70, name: os/eeiop/adpcm/ea_magatoki }
|
||||||
|
- { start: 0x24aa90, type: .rodata, vram: 0x349a90, name: os/eeiop/adpcm/ea_shinkan }
|
||||||
|
- { start: 0x24aab0, type: .rodata, vram: 0x349ab0, name: os/eeiop/adpcm/ea_puzzle }
|
||||||
|
- { start: 0x24aad0, type: .rodata, vram: 0x349ad0, name: os/eeiop/adpcm/ea_soul }
|
||||||
|
- { start: 0x24aaf0, type: .rodata, vram: 0x349af0, name: os/eeiop/adpcm/ea_tape }
|
||||||
|
- { start: 0x24ab10, type: .rodata, vram: 0x349b10, name: os/eeiop/adpcm/ea_gdead }
|
||||||
|
- { start: 0x24ab30, type: .rodata, vram: 0x349b30, name: os/eeiop/adpcm/ea_event }
|
||||||
|
- { start: 0x24abc0, type: .rodata, vram: 0x349bc0, name: os/eeiop/adpcm/ea_ghost }
|
||||||
|
- { start: 0x24abe0, type: .rodata, vram: 0x349be0, name: os/eeiop/adpcm/ea_autog }
|
||||||
|
- { start: 0x24ac00, type: .rodata, vram: 0x349c00, name: os/eeiop/adpcm/ea_hiso }
|
||||||
|
- { start: 0x24ac80, type: .rodata, vram: 0x349c80, name: os/eeiop/adpcm/ea_furn }
|
||||||
|
- { start: 0x24ad10, type: .rodata, vram: 0x349d10, name: os/eeiop/eese }
|
||||||
|
- { start: 0x24af60, type: .rodata, vram: 0x349f60, name: os/eeiop/se_cmd }
|
||||||
|
- { start: 0x24af80, type: .rodata, vram: 0x349f80, name: os/eeiop/se_data }
|
||||||
|
- { start: 0x24b238, type: .rodata, vram: 0x34a238, name: os/eeiop/se_ev }
|
||||||
|
- { start: 0x24b270, type: .rodata, vram: 0x34a270, name: os/eeiop/se_plyr }
|
||||||
|
- { start: 0x24b280, type: .rodata, vram: 0x34a280, name: graphics/graph2d/effect }
|
||||||
|
- { start: 0x24b500, type: .rodata, vram: 0x34a500, name: graphics/graph2d/effect_sub }
|
||||||
|
- { start: 0x24b750, type: .rodata, vram: 0x34a750, name: graphics/graph2d/effect_sub2 }
|
||||||
|
- { start: 0x24b8c0, type: .rodata, vram: 0x34a8c0, name: graphics/graph2d/effect_scr }
|
||||||
|
- { start: 0x24c350, type: .rodata, vram: 0x34b350, name: graphics/graph2d/effect_obj }
|
||||||
|
- { start: 0x24c6a0, type: .rodata, vram: 0x34b6a0, name: graphics/graph2d/effect_oth }
|
||||||
|
- { start: 0x24cc70, type: .rodata, vram: 0x34bc70, name: graphics/graph2d/effect_rdr }
|
||||||
|
- { start: 0x24cd10, type: .rodata, vram: 0x34bd10, name: graphics/graph2d/effect_ene }
|
||||||
|
- { start: 0x24d390, type: .rodata, vram: 0x34c390, name: graphics/graph2d/g2d_debug }
|
||||||
|
- { start: 0x24da70, type: .rodata, vram: 0x34ca70, name: graphics/graph2d/message }
|
||||||
|
- { start: 0x24dcc8, type: .rodata, vram: 0x34ccc8, name: graphics/graph2d/number }
|
||||||
|
- { start: 0x24dcd8, type: .rodata, vram: 0x34ccd8, name: graphics/graph2d/snapshot }
|
||||||
|
- { start: 0x24dcf0, type: .rodata, vram: 0x34ccf0, name: graphics/graph2d/tim2 }
|
||||||
|
- { start: 0x24df70, type: .rodata, vram: 0x34cf70, name: graphics/graph2d/tim2_new }
|
||||||
|
- { start: 0x24dff0, type: .rodata, vram: 0x34cff0, name: graphics/graph2d/rare_ene }
|
||||||
|
- { start: 0x24e000, type: .rodata, vram: 0x34d000, name: graphics/graph3d/leditor }
|
||||||
|
- { start: 0x24e3c0, type: .rodata, vram: 0x34d3c0, name: graphics/graph3d/load3d }
|
||||||
|
- { start: 0x24e3e0, type: .rodata, vram: 0x34d3e0, name: graphics/motion/mdlwork }
|
||||||
|
- { start: 0x24e440, type: .rodata, vram: 0x34d440, name: graphics/motion/accessory }
|
||||||
|
- { start: 0x24e480, type: .rodata, vram: 0x34d480, name: graphics/motion/motion }
|
||||||
|
- { start: 0x24e6e0, type: .rodata, vram: 0x34d6e0, name: graphics/motion/anicode }
|
||||||
|
- { start: 0x24e718, type: .rodata, vram: 0x34d718, name: graphics/graph3d/sce_pp3 }
|
||||||
|
- { start: 0x24e730, type: .rodata, vram: 0x34d730, name: graphics/graph3d/sgsgd }
|
||||||
|
- { start: 0x24e780, type: .rodata, vram: 0x34d780, name: graphics/graph3d/sglib }
|
||||||
|
- { start: 0x24e7d0, type: .rodata, vram: 0x34d7d0, name: graphics/graph3d/sgsu }
|
||||||
|
- { start: 0x24e8b0, type: .rodata, vram: 0x34d8b0, name: graphics/graph3d/sgdma }
|
||||||
|
- { start: 0x24e980, type: .rodata, vram: 0x34d980, name: graphics/graph3d/sglight }
|
||||||
|
- { start: 0x24eaf0, type: .rodata, vram: 0x34daf0, name: graphics/graph3d/sgsup }
|
||||||
|
- { start: 0x24ecb8, type: .rodata, vram: 0x34dcb8, name: graphics/graph3d/sgcam }
|
||||||
|
- { start: 0x24ecf0, type: .rodata, vram: 0x34dcf0, name: graphics/graph3d/mirror }
|
||||||
|
- { start: 0x24ed20, type: .rodata, vram: 0x34dd20, name: graphics/mov/movie }
|
||||||
|
- { start: 0x24f2b0, type: .rodata, vram: 0x34e2b0, name: graphics/scene/fod }
|
||||||
|
- { start: 0x24f370, type: .rodata, vram: 0x34e370, name: ingame/ingame }
|
||||||
|
- { start: 0x24f400, type: .rodata, vram: 0x34e400, name: ingame/ig_init }
|
||||||
|
- { start: 0x24f430, type: .rodata, vram: 0x34e430, name: ingame/camera/camera }
|
||||||
|
- { start: 0x24f680, type: .rodata, vram: 0x34e680, name: ingame/enemy/ene_ctl }
|
||||||
|
- { start: 0x24f730, type: .rodata, vram: 0x34e730, name: ingame/enemy/move_ctl }
|
||||||
|
- { start: 0x24f750, type: .rodata, vram: 0x34e750, name: ingame/entry/ap_bgost }
|
||||||
|
- { start: 0x24f770, type: .rodata, vram: 0x34e770, name: ingame/entry/ap_dgost }
|
||||||
|
- { start: 0x24f790, type: .rodata, vram: 0x34e790, name: ingame/entry/ap_fgost }
|
||||||
|
- { start: 0x24f7c0, type: .rodata, vram: 0x34e7c0, name: ingame/entry/ap_ggost }
|
||||||
|
- { start: 0x24f7e0, type: .rodata, vram: 0x34e7e0, name: ingame/entry/ap_sgost }
|
||||||
|
- { start: 0x24f8c0, type: .rodata, vram: 0x34e8c0, name: ingame/entry/ap_zgost }
|
||||||
|
- { start: 0x24f8f0, type: .rodata, vram: 0x34e8f0, name: ingame/event/ev_main }
|
||||||
|
- { start: 0x24fd10, type: .rodata, vram: 0x34ed10, name: ingame/event/ev_spcl }
|
||||||
|
- { start: 0x2503d0, type: .rodata, vram: 0x34f3d0, name: ingame/event/ev_load }
|
||||||
|
- { start: 0x250440, type: .rodata, vram: 0x34f440, name: ingame/event/mv_cmnd }
|
||||||
|
- { start: 0x250470, type: .rodata, vram: 0x34f470, name: ingame/info/inf_disp }
|
||||||
|
- { start: 0x250558, type: .rodata, vram: 0x34f558, name: ingame/map/map_ctrl }
|
||||||
|
- { start: 0x2505b0, type: .rodata, vram: 0x34f5b0, name: ingame/map/map_area }
|
||||||
|
- { start: 0x2505e0, type: .rodata, vram: 0x34f5e0, name: ingame/map/door_ctl }
|
||||||
|
- { start: 0x250740, type: .rodata, vram: 0x34f740, name: ingame/map/doortype }
|
||||||
|
- { start: 0x250790, type: .rodata, vram: 0x34f790, name: ingame/map/furn_ctl }
|
||||||
|
- { start: 0x2507d0, type: .rodata, vram: 0x34f7d0, name: ingame/map/furn_spe/furn_spe }
|
||||||
|
- { start: 0x250bc0, type: .rodata, vram: 0x34fbc0, name: ingame/menu/item }
|
||||||
|
- { start: 0x250d00, type: .rodata, vram: 0x34fd00, name: ingame/menu/ig_album }
|
||||||
|
- { start: 0x250d40, type: .rodata, vram: 0x34fd40, name: ingame/menu/ig_camra }
|
||||||
|
- { start: 0x250db0, type: .rodata, vram: 0x34fdb0, name: ingame/menu/ig_menu }
|
||||||
|
- { start: 0x251830, type: .rodata, vram: 0x350830, name: ingame/menu/item_get }
|
||||||
|
- { start: 0x251a30, type: .rodata, vram: 0x350a30, name: ingame/menu/ig_file }
|
||||||
|
- { start: 0x251b40, type: .rodata, vram: 0x350b40, name: ingame/menu/ig_rank }
|
||||||
|
- { start: 0x251b80, type: .rodata, vram: 0x350b80, name: ingame/menu/ig_glst }
|
||||||
|
- { start: 0x251c30, type: .rodata, vram: 0x350c30, name: ingame/menu/ig_map }
|
||||||
|
- { start: 0x251ce0, type: .rodata, vram: 0x350ce0, name: ingame/menu/ig_option }
|
||||||
|
- { start: 0x2521a0, type: .rodata, vram: 0x3511a0, name: ingame/menu/sp_menu }
|
||||||
|
- { start: 0x2523d0, type: .rodata, vram: 0x3513d0, name: ingame/map/door_conte }
|
||||||
|
- { start: 0x2523f0, type: .rodata, vram: 0x3513f0, name: ingame/photo/pht_main }
|
||||||
|
- { start: 0x252420, type: .rodata, vram: 0x351420, name: ingame/photo/pht_make }
|
||||||
|
- { start: 0x2525f0, type: .rodata, vram: 0x3515f0, name: ingame/plyr/plyr_ctl }
|
||||||
|
- { start: 0x252800, type: .rodata, vram: 0x351800, name: outgame/scn_test }
|
||||||
|
- { start: 0x2532b0, type: .rodata, vram: 0x3522b0, name: outgame/title }
|
||||||
|
- { start: 0x253530, type: .rodata, vram: 0x352530, name: graphics/graph2d/takep_pe }
|
||||||
|
- { start: 0x253550, type: .rodata, vram: 0x352550, name: mc/mc_main }
|
||||||
|
- { start: 0x2537c0, type: .rodata, vram: 0x3527c0, name: mc/mc_acs }
|
||||||
|
- { start: 0x253800, type: .rodata, vram: 0x352800, name: mc/mc_album }
|
||||||
|
- { start: 0x253960, type: .rodata, vram: 0x352960, name: mc/mc_exec }
|
||||||
|
- { start: 0x253a48, type: .rodata, vram: 0x352a48, name: mc/mc_icon }
|
||||||
|
- { start: 0x253b80, type: .rodata, vram: 0x352b80, name: mc/mc_disp }
|
||||||
|
- { start: 0x253cb0, type: .rodata, vram: 0x352cb0, name: mc/mc_at }
|
||||||
|
- { start: 0x253e00, type: .rodata, vram: 0x352e00, name: outgame/outgame }
|
||||||
|
- { start: 0x253f28, type: .rodata, vram: 0x352f28, name: outgame/btl_mode/btl_menu }
|
||||||
|
- { start: 0x253f50, type: .rodata, vram: 0x352f50, name: outgame/btl_mode/btl_mode }
|
||||||
|
- { start: 0x253f80, type: .rodata, vram: 0x352f80, name: ingame/event/wan_soul }
|
||||||
|
- { start: 0x254010, type: .rodata, vram: 0x353010, name: outgame/sound_test }
|
||||||
|
- { start: 0x254048, type: rodata, vram: 0x353048, name: rodata_rest }
|
||||||
|
# ######################## LIT4 (vram: 0x355080) #####################################
|
||||||
|
- { start: 0x256080, type: .lit4, vram: 0x355080, name: outgame/mode_slct }
|
||||||
|
- { start: 0x256088, type: .lit4, vram: 0x355088, name: outgame/memory_album }
|
||||||
|
- { start: 0x256120, type: .lit4, vram: 0x355120, name: os/pad }
|
||||||
|
- { start: 0x25612c, type: .lit4, vram: 0x35512c, name: os/eeiop/adpcm/ea_cmd }
|
||||||
|
- { start: 0x256144, type: .lit4, vram: 0x355144, name: os/eeiop/se_cmd }
|
||||||
|
- { start: 0x256154, type: .lit4, vram: 0x355154, name: os/eeiop/se_plyr }
|
||||||
|
- { start: 0x256158, type: .lit4, vram: 0x355158, name: graphics/graph2d/compress }
|
||||||
|
- { start: 0x25615c, type: .lit4, vram: 0x35515c, name: graphics/graph2d/effect }
|
||||||
|
- { start: 0x256178, type: .lit4, vram: 0x355178, name: graphics/graph2d/effect_sub }
|
||||||
|
- { start: 0x2561e4, type: .lit4, vram: 0x3551e4, name: graphics/graph2d/effect_sub2 }
|
||||||
|
- { start: 0x25620c, type: .lit4, vram: 0x35520c, name: graphics/graph2d/effect_scr }
|
||||||
|
- { start: 0x256308, type: .lit4, vram: 0x355308, name: graphics/graph2d/effect_obj }
|
||||||
|
- { start: 0x2563b4, type: .lit4, vram: 0x3553b4, name: graphics/graph2d/effect_oth }
|
||||||
|
- { start: 0x256658, type: .lit4, vram: 0x355658, name: graphics/graph2d/effect_rdr }
|
||||||
|
- { start: 0x256688, type: .lit4, vram: 0x355688, name: graphics/graph2d/effect_ene }
|
||||||
|
- { start: 0x256874, type: .lit4, vram: 0x355874, name: graphics/graph2d/g2d_debug }
|
||||||
|
- { start: 0x256890, type: .lit4, vram: 0x355890, name: graphics/graph2d/message }
|
||||||
|
- { start: 0x256894, type: .lit4, vram: 0x355894, name: graphics/graph2d/tim2 }
|
||||||
|
- { start: 0x25689c, type: .lit4, vram: 0x35589c, name: graphics/graph2d/rare_ene }
|
||||||
|
- { start: 0x2568ac, type: .lit4, vram: 0x3558ac, name: graphics/graph3d/gra3d }
|
||||||
|
- { start: 0x25691c, type: .lit4, vram: 0x35591c, name: graphics/graph3d/leditor }
|
||||||
|
- { start: 0x256944, type: .lit4, vram: 0x355944, name: graphics/motion/mdlact }
|
||||||
|
- { start: 0x256990, type: .lit4, vram: 0x355990, name: graphics/motion/mime }
|
||||||
|
- { start: 0x256998, type: .lit4, vram: 0x355998, name: graphics/motion/accessory }
|
||||||
|
- { start: 0x2569fc, type: .lit4, vram: 0x3559fc, name: graphics/motion/motion }
|
||||||
|
- { start: 0x256a10, type: .lit4, vram: 0x355a10, name: graphics/motion/anicode }
|
||||||
|
- { start: 0x256a14, type: .lit4, vram: 0x355a14, name: graphics/graph3d/sglib }
|
||||||
|
- { start: 0x256a9c, type: .lit4, vram: 0x355a9c, name: graphics/graph3d/sglight }
|
||||||
|
- { start: 0x256aa0, type: .lit4, vram: 0x355aa0, name: graphics/graph3d/shadow }
|
||||||
|
- { start: 0x256ab0, type: .lit4, vram: 0x355ab0, name: graphics/graph3d/mirror }
|
||||||
|
- { start: 0x256ac0, type: .lit4, vram: 0x355ac0, name: graphics/scene/fod }
|
||||||
|
- { start: 0x256b08, type: .lit4, vram: 0x355b08, name: graphics/scene/scene }
|
||||||
|
- { start: 0x256b24, type: .lit4, vram: 0x355b24, name: ingame/ig_init }
|
||||||
|
- { start: 0x256b38, type: .lit4, vram: 0x355b38, name: ingame/camera/camera }
|
||||||
|
- { start: 0x256c04, type: .lit4, vram: 0x355c04, name: ingame/enemy/ene_ctl }
|
||||||
|
- { start: 0x256c38, type: .lit4, vram: 0x355c38, name: ingame/enemy/move_ctl }
|
||||||
|
- { start: 0x256cec, type: .lit4, vram: 0x355cec, name: ingame/entry/ap_dgost }
|
||||||
|
- { start: 0x256cf0, type: .lit4, vram: 0x355cf0, name: ingame/entry/ap_fgost }
|
||||||
|
- { start: 0x256cf4, type: .lit4, vram: 0x355cf4, name: ingame/entry/ap_zgost }
|
||||||
|
- { start: 0x256cf8, type: .lit4, vram: 0x355cf8, name: ingame/event/ev_main }
|
||||||
|
- { start: 0x256d04, type: .lit4, vram: 0x355d04, name: ingame/event/ev_spcl }
|
||||||
|
- { start: 0x256d3c, type: .lit4, vram: 0x355d3c, name: ingame/info/inf_disp }
|
||||||
|
- { start: 0x256d8c, type: .lit4, vram: 0x355d8c, name: ingame/map/map_ctrl }
|
||||||
|
- { start: 0x256d9c, type: .lit4, vram: 0x355d9c, name: ingame/map/door_ctl }
|
||||||
|
- { start: 0x256e30, type: .lit4, vram: 0x355e30, name: ingame/map/rotd_ctl }
|
||||||
|
- { start: 0x256e3c, type: .lit4, vram: 0x355e3c, name: ingame/map/find_ctl }
|
||||||
|
- { start: 0x256e44, type: .lit4, vram: 0x355e44, name: ingame/map/furn_ctl }
|
||||||
|
- { start: 0x256e48, type: .lit4, vram: 0x355e48, name: ingame/map/furn_eff }
|
||||||
|
- { start: 0x256e4c, type: .lit4, vram: 0x355e4c, name: ingame/map/item_ctl }
|
||||||
|
- { start: 0x256e54, type: .lit4, vram: 0x355e54, name: ingame/map/furn_spe/furn_spe }
|
||||||
|
- { start: 0x256ea0, type: .lit4, vram: 0x355ea0, name: ingame/map/furn_spe/fsla_main }
|
||||||
|
- { start: 0x256ea8, type: .lit4, vram: 0x355ea8, name: ingame/menu/item }
|
||||||
|
- { start: 0x256ed4, type: .lit4, vram: 0x355ed4, name: ingame/menu/pause }
|
||||||
|
- { start: 0x256ed8, type: .lit4, vram: 0x355ed8, name: ingame/menu/ig_album }
|
||||||
|
- { start: 0x256f04, type: .lit4, vram: 0x355f04, name: ingame/menu/ig_camra }
|
||||||
|
- { start: 0x256f24, type: .lit4, vram: 0x355f24, name: ingame/menu/item_get }
|
||||||
|
- { start: 0x256f28, type: .lit4, vram: 0x355f28, name: ingame/menu/ig_file }
|
||||||
|
- { start: 0x256f38, type: .lit4, vram: 0x355f38, name: ingame/menu/ig_rank }
|
||||||
|
- { start: 0x256f54, type: .lit4, vram: 0x355f54, name: ingame/menu/ig_glst }
|
||||||
|
- { start: 0x256f68, type: .lit4, vram: 0x355f68, name: ingame/menu/ig_map }
|
||||||
|
- { start: 0x256fa0, type: .lit4, vram: 0x355fa0, name: ingame/menu/ig_option }
|
||||||
|
- { start: 0x256fd4, type: .lit4, vram: 0x355fd4, name: ingame/menu/sp_menu }
|
||||||
|
- { start: 0x257014, type: .lit4, vram: 0x356014, name: ingame/photo/pht_make }
|
||||||
|
- { start: 0x257024, type: .lit4, vram: 0x356024, name: ingame/plyr/plyr_ctl }
|
||||||
|
- { start: 0x257208, type: .lit4, vram: 0x356208, name: ingame/plyr/unit_ctl }
|
||||||
|
- { start: 0x257238, type: .lit4, vram: 0x356238, name: outgame/scn_test }
|
||||||
|
- { start: 0x257284, type: .lit4, vram: 0x356284, name: outgame/title }
|
||||||
|
- { start: 0x257290, type: .lit4, vram: 0x356290, name: graphics/graph2d/takep_pe }
|
||||||
|
- { start: 0x257298, type: .lit4, vram: 0x356298, name: mc/mc_start }
|
||||||
|
- { start: 0x25729c, type: .lit4, vram: 0x35629c, name: ingame/event/wan_soul }
|
||||||
|
- { start: 0x2572d4, type: .lit4, vram: 0x3562d4, name: outgame/sound_test }
|
||||||
|
# ######################## SDATA (vram: 0x356300) #####################################
|
||||||
|
- { start: 0x257300, type: .sdata, vram: 0x356300, name: outgame/mode_slct }
|
||||||
|
- { start: 0x25731a, type: .sdata, vram: 0x35631a, name: outgame/memory_album }
|
||||||
|
- { start: 0x25731c, type: .sdata, vram: 0x35631c, name: main/gamemain }
|
||||||
|
- { start: 0x257328, type: .sdata, vram: 0x356328, name: main/glob }
|
||||||
|
- { start: 0x257338, type: .sdata, vram: 0x356338, name: os/system }
|
||||||
|
- { start: 0x257350, type: .sdata, vram: 0x356350, name: os/eeiop/adpcm/ea_ghost }
|
||||||
|
- { start: 0x257354, type: .sdata, vram: 0x356354, name: os/eeiop/adpcm/ea_autog }
|
||||||
|
- { start: 0x257358, type: .sdata, vram: 0x356358, name: os/eeiop/adpcm/ea_furn }
|
||||||
|
- { start: 0x257360, type: .sdata, vram: 0x356360, name: graphics/graph2d/compress }
|
||||||
|
- { start: 0x257368, type: .sdata, vram: 0x356368, name: graphics/graph2d/effect }
|
||||||
|
- { start: 0x2573c8, type: .sdata, vram: 0x3563c8, name: graphics/graph2d/effect_sub }
|
||||||
|
- { start: 0x2573e8, type: .sdata, vram: 0x3563e8, name: graphics/graph2d/effect_sub2 }
|
||||||
|
- { start: 0x257438, type: .sdata, vram: 0x356438, name: graphics/graph2d/effect_scr }
|
||||||
|
- { start: 0x257558, type: .sdata, vram: 0x356558, name: graphics/graph2d/effect_obj }
|
||||||
|
- { start: 0x257578, type: .sdata, vram: 0x356578, name: graphics/graph2d/effect_oth }
|
||||||
|
- { start: 0x257670, type: .sdata, vram: 0x356670, name: graphics/graph2d/effect_rdr }
|
||||||
|
- { start: 0x257678, type: .sdata, vram: 0x356678, name: graphics/graph2d/effect_ene }
|
||||||
|
- { start: 0x2576d0, type: .sdata, vram: 0x3566d0, name: graphics/graph2d/g2d_debug }
|
||||||
|
- { start: 0x257a80, type: .sdata, vram: 0x356a80, name: graphics/graph2d/g2d_main }
|
||||||
|
- { start: 0x257a88, type: .sdata, vram: 0x356a88, name: graphics/graph2d/message }
|
||||||
|
- { start: 0x257ac0, type: .sdata, vram: 0x356ac0, name: graphics/graph2d/snapshot }
|
||||||
|
- { start: 0x257ad0, type: .sdata, vram: 0x356ad0, name: graphics/graph2d/tim2 }
|
||||||
|
- { start: 0x257af0, type: .sdata, vram: 0x356af0, name: graphics/graph2d/tim2_new }
|
||||||
|
- { start: 0x257af4, type: .sdata, vram: 0x356af4, name: graphics/graph2d/rare_ene }
|
||||||
|
- { start: 0x257b08, type: .sdata, vram: 0x356b08, name: graphics/graph3d/gra3d }
|
||||||
|
- { start: 0x257b58, type: .sdata, vram: 0x356b58, name: graphics/graph3d/leditor }
|
||||||
|
- { start: 0x257b98, type: .sdata, vram: 0x356b98, name: graphics/graph3d/load3d }
|
||||||
|
- { start: 0x257bb0, type: .sdata, vram: 0x356bb0, name: graphics/motion/mdlwork }
|
||||||
|
- { start: 0x257bc0, type: .sdata, vram: 0x356bc0, name: graphics/motion/mdlact }
|
||||||
|
- { start: 0x257bcc, type: .sdata, vram: 0x356bcc, name: graphics/motion/mime }
|
||||||
|
- { start: 0x257bd0, type: .sdata, vram: 0x356bd0, name: graphics/motion/accessory }
|
||||||
|
- { start: 0x257bf0, type: .sdata, vram: 0x356bf0, name: graphics/motion/motion }
|
||||||
|
- { start: 0x257c10, type: .sdata, vram: 0x356c10, name: graphics/motion/acs_dat }
|
||||||
|
- { start: 0x257c40, type: .sdata, vram: 0x356c40, name: graphics/graph3d/object }
|
||||||
|
- { start: 0x257c54, type: .sdata, vram: 0x356c54, name: graphics/graph3d/sce_pp3 }
|
||||||
|
- { start: 0x257c64, type: .sdata, vram: 0x356c64, name: graphics/graph3d/sgsgd }
|
||||||
|
- { start: 0x257c68, type: .sdata, vram: 0x356c68, name: graphics/graph3d/sglib }
|
||||||
|
- { start: 0x257d14, type: .sdata, vram: 0x356d14, name: graphics/graph3d/sgsu }
|
||||||
|
- { start: 0x257d50, type: .sdata, vram: 0x356d50, name: graphics/graph3d/sgdma }
|
||||||
|
- { start: 0x257d60, type: .sdata, vram: 0x356d60, name: graphics/graph3d/sglight }
|
||||||
|
- { start: 0x257db0, type: .sdata, vram: 0x356db0, name: graphics/graph3d/sgsup }
|
||||||
|
- { start: 0x257dd0, type: .sdata, vram: 0x356dd0, name: graphics/graph3d/sgcam }
|
||||||
|
- { start: 0x257de0, type: .sdata, vram: 0x356de0, name: graphics/graph3d/shadow }
|
||||||
|
- { start: 0x257e04, type: .sdata, vram: 0x356e04, name: graphics/graph3d/mirror }
|
||||||
|
- { start: 0x257e08, type: .sdata, vram: 0x356e08, name: graphics/mov/movie }
|
||||||
|
- { start: 0x257ea8, type: .sdata, vram: 0x356ea8, name: graphics/scene/fod }
|
||||||
|
- { start: 0x257eb0, type: .sdata, vram: 0x356eb0, name: graphics/scene/scene }
|
||||||
|
- { start: 0x257ef0, type: .sdata, vram: 0x356ef0, name: ingame/ingame }
|
||||||
|
- { start: 0x257ef8, type: .sdata, vram: 0x356ef8, name: ingame/ig_init }
|
||||||
|
- { start: 0x257f00, type: .sdata, vram: 0x356f00, name: ingame/ig_glob }
|
||||||
|
- { start: 0x257f10, type: .sdata, vram: 0x356f10, name: ingame/camera/camera }
|
||||||
|
- { start: 0x257f68, type: .sdata, vram: 0x356f68, name: ingame/enemy/ene_ctl }
|
||||||
|
- { start: 0x257fa8, type: .sdata, vram: 0x356fa8, name: ingame/enemy/move_ctl }
|
||||||
|
- { start: 0x257fc0, type: .sdata, vram: 0x356fc0, name: ingame/entry/ap_dgost }
|
||||||
|
- { start: 0x257fc8, type: .sdata, vram: 0x356fc8, name: ingame/entry/ap_fgost }
|
||||||
|
- { start: 0x257fcc, type: .sdata, vram: 0x356fcc, name: ingame/entry/ap_ggost }
|
||||||
|
- { start: 0x257fd8, type: .sdata, vram: 0x356fd8, name: ingame/entry/ap_pgost }
|
||||||
|
- { start: 0x257fe8, type: .sdata, vram: 0x356fe8, name: ingame/entry/ap_sgost }
|
||||||
|
- { start: 0x257ff0, type: .sdata, vram: 0x356ff0, name: ingame/entry/ap_zgost }
|
||||||
|
- { start: 0x257ff8, type: .sdata, vram: 0x356ff8, name: ingame/event/ev_main }
|
||||||
|
- { start: 0x258018, type: .sdata, vram: 0x357018, name: ingame/event/ev_spcl }
|
||||||
|
- { start: 0x2580a8, type: .sdata, vram: 0x3570a8, name: ingame/event/ev_load }
|
||||||
|
- { start: 0x2580b8, type: .sdata, vram: 0x3570b8, name: ingame/event/mv_cmnd }
|
||||||
|
- { start: 0x2580c0, type: .sdata, vram: 0x3570c0, name: ingame/info/inf_disp }
|
||||||
|
- { start: 0x2580e0, type: .sdata, vram: 0x3570e0, name: ingame/map/map_ctrl }
|
||||||
|
- { start: 0x2580ec, type: .sdata, vram: 0x3570ec, name: ingame/map/map_area }
|
||||||
|
- { start: 0x2580f0, type: .sdata, vram: 0x3570f0, name: ingame/map/door_ctl }
|
||||||
|
- { start: 0x2580f4, type: .sdata, vram: 0x3570f4, name: ingame/map/furn_ctl }
|
||||||
|
- { start: 0x2580f8, type: .sdata, vram: 0x3570f8, name: ingame/map/furn_eff }
|
||||||
|
- { start: 0x258108, type: .sdata, vram: 0x357108, name: ingame/map/furn_spe/furn_spe }
|
||||||
|
- { start: 0x258140, type: .sdata, vram: 0x357140, name: ingame/menu/pause }
|
||||||
|
- { start: 0x258158, type: .sdata, vram: 0x357158, name: ingame/menu/ig_camra }
|
||||||
|
- { start: 0x258180, type: .sdata, vram: 0x357180, name: ingame/menu/ig_menu }
|
||||||
|
- { start: 0x258198, type: .sdata, vram: 0x357198, name: ingame/menu/ig_spd_menu }
|
||||||
|
- { start: 0x25819c, type: .sdata, vram: 0x35719c, name: ingame/menu/item_get }
|
||||||
|
- { start: 0x2581a8, type: .sdata, vram: 0x3571a8, name: ingame/menu/ig_file }
|
||||||
|
- { start: 0x2581c8, type: .sdata, vram: 0x3571c8, name: ingame/menu/ig_map }
|
||||||
|
- { start: 0x2581d8, type: .sdata, vram: 0x3571d8, name: ingame/menu/sp_menu }
|
||||||
|
- { start: 0x2581f8, type: .sdata, vram: 0x3571f8, name: ingame/map/door_conte }
|
||||||
|
- { start: 0x258200, type: .sdata, vram: 0x357200, name: ingame/photo/pht_main }
|
||||||
|
- { start: 0x258220, type: .sdata, vram: 0x357220, name: ingame/photo/pht_make }
|
||||||
|
- { start: 0x258260, type: .sdata, vram: 0x357260, name: ingame/plyr/plyr_ctl }
|
||||||
|
- { start: 0x258310, type: .sdata, vram: 0x357310, name: outgame/scn_test }
|
||||||
|
- { start: 0x2586a0, type: .sdata, vram: 0x3576a0, name: outgame/title }
|
||||||
|
- { start: 0x2586c8, type: .sdata, vram: 0x3576c8, name: graphics/graph2d/takep_pe }
|
||||||
|
- { start: 0x2586d0, type: .sdata, vram: 0x3576d0, name: mc/mc }
|
||||||
|
- { start: 0x2586e0, type: .sdata, vram: 0x3576e0, name: mc/mc_main }
|
||||||
|
- { start: 0x258708, type: .sdata, vram: 0x357708, name: mc/mc_album }
|
||||||
|
- { start: 0x258720, type: .sdata, vram: 0x357720, name: mc/mc_exec }
|
||||||
|
- { start: 0x258756, type: .sdata, vram: 0x357756, name: mc/mc_start }
|
||||||
|
- { start: 0x258758, type: .sdata, vram: 0x357758, name: outgame/outgame }
|
||||||
|
- { start: 0x258788, type: .sdata, vram: 0x357788, name: outgame/btl_mode/btl_menu }
|
||||||
|
- { start: 0x2587e8, type: .sdata, vram: 0x3577e8, name: outgame/btl_mode/btl_mode }
|
||||||
|
- { start: 0x258814, type: .sdata, vram: 0x357814, name: ingame/event/wan_soul }
|
||||||
|
- { start: 0x258830, type: .sdata, vram: 0x357830, name: outgame/sound_test }
|
||||||
|
- { start: 0x258834, type: sdata, vram: 0x357834, name: sdata_rest }
|
||||||
|
# ######################## SBSS (vram: 0x357880) #####################################
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357880, name: outgame/mode_slct }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357888, name: outgame/memory_album }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357894, name: os/system }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357898, name: os/eeiop/cdvd/eecdvd }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x35789b, name: os/eeiop/adpcm/ea_ctrl }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x35789c, name: os/eeiop/adpcm/ea_ghost }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x3578a0, name: os/eeiop/adpcm/ea_map }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x3578a4, name: graphics/graph2d/compress }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x3578c0, name: graphics/graph2d/effect }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x3578d0, name: graphics/graph2d/effect_sub }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x3578e4, name: graphics/graph2d/effect_scr }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357900, name: graphics/graph2d/effect_obj }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357904, name: graphics/graph2d/effect_oth }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357938, name: graphics/graph2d/effect_rdr }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357948, name: graphics/graph2d/g2d_debug }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x35794c, name: graphics/graph2d/tim2 }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357960, name: graphics/graph3d/gra3d }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x3579a4, name: graphics/graph3d/leditor }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x3579a8, name: graphics/graph3d/load3d }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x3579bc, name: graphics/motion/mdlwork }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x3579c0, name: graphics/motion/mdlact }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x3579c4, name: graphics/motion/accessory }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x3579c8, name: graphics/graph3d/sgsgd }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x3579d0, name: graphics/graph3d/sgsu }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x3579d8, name: graphics/graph3d/sgdma }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x3579e0, name: graphics/graph3d/sglight }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x3579e4, name: graphics/graph3d/sgsup }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x3579ec, name: graphics/graph3d/shadow }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x3579f4, name: graphics/graph3d/mirror }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357a0c, name: graphics/mov/movie }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357a18, name: graphics/scene/scene }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357a28, name: ingame/camera/camera }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357a40, name: ingame/enemy/ene_ctl }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357a58, name: ingame/enemy/move_ctl }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357a88, name: ingame/entry/ap_sgost }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357a90, name: ingame/event/ev_spcl }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357aa8, name: ingame/info/inf_disp }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357ac4, name: ingame/map/door_ctl }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357ad0, name: ingame/menu/item }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357af0, name: ingame/menu/gameover }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357af8, name: ingame/menu/pause }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357b02, name: ingame/menu/ig_camra }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357b08, name: ingame/menu/ig_menu }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357b28, name: ingame/menu/ig_spd_menu }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357b38, name: ingame/menu/item_get }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357b50, name: ingame/menu/ig_file }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357b60, name: ingame/menu/ig_rank }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357b70, name: ingame/menu/ig_glst }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357b78, name: ingame/menu/ig_map }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357b80, name: ingame/menu/ig_option }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357b90, name: ingame/menu/sp_menu }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357bb0, name: ingame/photo/pht_main }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357bb8, name: ingame/photo/pht_make }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357bba, name: ingame/plyr/plyr_ctl }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357bc0, name: outgame/scn_test }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357bc8, name: outgame/title }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357bec, name: graphics/graph2d/takep_pe }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357bf8, name: mc/mc_main }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357c08, name: mc/mc_album }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357c10, name: mc/mc_start }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357c18, name: mc/mc_at }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357c2c, name: outgame/outgame }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357c30, name: ingame/event/wan_soul }
|
||||||
|
- { start: 0x258880, type: .sbss, vram: 0x357c58, name: outgame/sound_test }
|
||||||
|
- { start: 0x258880, type: sbss, vram: 0x357c5f, name: sbss_rest }
|
||||||
|
# ######################## BSS (vram: 0x357c80) #####################################
|
||||||
|
- { start: 0x25888c, type: bss, vram: 0x357c80, name: bss_pre }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x357dc8, name: outgame/mode_slct }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x357df0, name: outgame/memory_album }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x357e40, name: os/fileload }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x357ea8, name: os/eeiop/cdvd/eecdvd }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x357ed0, name: os/eeiop/eese }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x358ad0, name: graphics/graph2d/compress }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x3599e0, name: graphics/graph2d/effect }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x359c30, name: graphics/graph2d/effect_sub }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x359f90, name: graphics/graph2d/effect_sub2 }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x365610, name: graphics/graph2d/effect_scr }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x379d40, name: graphics/graph2d/effect_obj }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x382580, name: graphics/graph2d/effect_oth }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x3b9220, name: graphics/graph2d/effect_rdr }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x3b9260, name: graphics/graph2d/effect_ene }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x3bb1a0, name: graphics/graph2d/message }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x3bb540, name: graphics/graph2d/tim2_new }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x3bd580, name: graphics/graph2d/rare_ene }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x3bd5c0, name: graphics/graph3d/gra3d }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x3f4180, name: graphics/graph3d/leditor }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x3f5540, name: graphics/graph3d/load3d }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x3f5680, name: graphics/motion/accessory }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x3f6a50, name: graphics/motion/motion }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x3f9390, name: graphics/graph3d/object }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x3fb390, name: graphics/graph3d/sce_pp3 }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x3fb620, name: graphics/graph3d/sgsu }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x3fb720, name: graphics/graph3d/sglight }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x3fb7b0, name: graphics/graph3d/sgsup }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x3fb8a0, name: graphics/graph3d/shadow }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x3fba80, name: graphics/mov/movie }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x4002c0, name: graphics/scene/fod }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x4007e0, name: graphics/scene/scene }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x401c40, name: ingame/camera/camera }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x401f20, name: ingame/enemy/ene_ctl }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x401fd0, name: ingame/enemy/move_ctl }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x402130, name: ingame/info/inf_disp }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x402740, name: ingame/map/door_ctl }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x402770, name: ingame/map/furn_eff }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x402810, name: ingame/map/furn_spe/adj_valg }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x402ae0, name: ingame/menu/item }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x402b10, name: ingame/menu/gameover }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x402b20, name: ingame/menu/ig_album }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x402b40, name: ingame/menu/ig_camra }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x402b60, name: ingame/menu/item_get }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x402b80, name: ingame/menu/ig_file }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x402ca0, name: ingame/menu/ig_glst }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x402cb0, name: ingame/menu/ig_map }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x402cc8, name: ingame/menu/sp_menu }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x402d58, name: ingame/map/door_conte }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x402d80, name: outgame/title }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x402e50, name: ingame/event/wan_soul }
|
||||||
|
- { start: 0x25888c, type: .bss, vram: 0x402ea0, name: outgame/sound_test }
|
||||||
|
- { start: 0x25888c, type: bss, vram: 0x402f00, name: bss_rest }
|
||||||
|
# ######################## VUBSS (vram: 0x40a8b0) #####################################
|
||||||
|
- { start: 0x25888c, type: bss, vram: 0x40a8b0, name: vubss_1 }
|
||||||
|
- [0x258880, databin, reg_info]
|
||||||
|
- [0x2588a4, databin, mips_debug]
|
||||||
|
- [0x71d5d4, databin, rest]
|
||||||
|
- [0x7775b8]
|
||||||
|
|
||||||
|
# Section Headers:
|
||||||
|
# [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
|
||||||
|
# [ 0] NULL 00000000 000000 000000 00 0 0 0
|
||||||
|
# [ 1] .text PROGBITS 00100000 001000 1465a4 00 AX 0 0 64
|
||||||
|
# [ 2] .vutext PROGBITS 002465b0 1475b0 009b80 00 AX 0 0 16
|
||||||
|
# [ 3] .reginfo MIPS_REGINFO 00250130 25888c 000018 01 0 0 4
|
||||||
|
# [ 4] .data PROGBITS 00250180 151180 0f9488 00 WA 0 0 64
|
||||||
|
# [ 5] .vudata PROGBITS 00349608 24a608 000000 00 WA 0 0 1
|
||||||
|
# [ 6] .rodata PROGBITS 00349680 24a680 00b9a8 00 A 0 0 16
|
||||||
|
# [ 7] .lit4 PROGBITS 00355080 256080 001268 00 WAp 0 0 4
|
||||||
|
# [ 8] .sdata PROGBITS 00356300 257300 001534 00 WAp 0 0 8
|
||||||
|
# [ 9] .sbss NOBITS 00357880 258880 0003f4 00 WAp 0 0 8
|
||||||
|
# [10] .bss NOBITS 00357c80 25888c 0b2c30 00 WA 0 0 64
|
||||||
|
# [11] .vubss NOBITS 0040a8b0 25888c 000000 00 WA 0 0 1
|
||||||
|
# [12] .mdebug MIPS_DEBUG 0040a8b0 2588a4 4c4d30 01 0 0 4
|
||||||
+45770
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Executable
+719
@@ -0,0 +1,719 @@
|
|||||||
|
#! /usr/bin/env python3
|
||||||
|
|
||||||
|
# pyright: reportUnknownMemberType=false, reportMissingTypeStubs=false
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import yaml
|
||||||
|
import copy
|
||||||
|
import splat
|
||||||
|
import shutil
|
||||||
|
import argparse
|
||||||
|
import tempfile
|
||||||
|
import subprocess
|
||||||
|
import ninja_syntax
|
||||||
|
|
||||||
|
from typing import Any, Union, Protocol, Literal, cast
|
||||||
|
from pathlib import Path
|
||||||
|
from contextlib import contextmanager
|
||||||
|
|
||||||
|
from splat.scripts import split
|
||||||
|
from splat.util.conf import load as splat_load_yaml
|
||||||
|
from splat.segtypes.linker_entry import LinkerEntry
|
||||||
|
|
||||||
|
# from tools.python.fix_gp import fix_gp
|
||||||
|
from tools.python.fix_assets import fix_assets
|
||||||
|
from tools.python.fix_linkerscript import fix_linkerscript
|
||||||
|
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def suppress_stdout_stderr():
|
||||||
|
null_fds = [os.open(os.devnull, os.O_RDWR) for _ in range(2)]
|
||||||
|
save_fds = [os.dup(1), os.dup(2)]
|
||||||
|
os.dup2(null_fds[0], 1)
|
||||||
|
os.dup2(null_fds[1], 2)
|
||||||
|
try:
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
os.dup2(save_fds[0], 1)
|
||||||
|
os.dup2(save_fds[1], 2)
|
||||||
|
for fd in null_fds + save_fds:
|
||||||
|
os.close(fd)
|
||||||
|
|
||||||
|
|
||||||
|
ROOT = Path(__file__).parent.resolve()
|
||||||
|
TOOLS_DIR = ROOT / "tools"
|
||||||
|
|
||||||
|
COMPILER = "ee-gcc2.9-991111-01"
|
||||||
|
COMPILER_FLAGS = "-DMATCHING_DECOMP -O2 -g2 -gstabs" # -malign-functions=3
|
||||||
|
|
||||||
|
LANGUAGES: dict[str, str] = {
|
||||||
|
"SLUS_203.88": "us",
|
||||||
|
"SLES_508.21": "eu",
|
||||||
|
}
|
||||||
|
|
||||||
|
# list of object file names (e.g., "tim2_new.c.o"), that have asm that needs
|
||||||
|
# to be patched. the respective c files (e.g. "tim2_new.c") will be compiled
|
||||||
|
# in two steps: c -> asm, then asm -> obj. in between, the intermediate
|
||||||
|
# asm will be passed to `tools/python/fix_asm_matching.py` for patching.
|
||||||
|
ASM_PATCH_LIST: list[str] = [
|
||||||
|
"effect_oth.c.o",
|
||||||
|
"photo.c.o",
|
||||||
|
"ig_camra.c.o",
|
||||||
|
]
|
||||||
|
|
||||||
|
BIN_PATH_LIST: list[str] = [
|
||||||
|
"photo.c.o",
|
||||||
|
]
|
||||||
|
|
||||||
|
EUC_JP_LIST = [
|
||||||
|
"title.c.o",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def get_compiler_command(command: str):
|
||||||
|
compiler_dir = Path("tools") / "cc" / COMPILER
|
||||||
|
ee_dir = compiler_dir / "lib" / "gcc-lib" / "ee"
|
||||||
|
ee_compiler_dirname = next(os.walk(ee_dir))[1][0]
|
||||||
|
|
||||||
|
commands = {
|
||||||
|
"ee-gcc": compiler_dir / "bin" / "ee-gcc",
|
||||||
|
"cc1": compiler_dir / "lib" / "gcc-lib" / "ee" / ee_compiler_dirname / "cc1",
|
||||||
|
"cc1plus": compiler_dir / "lib" / "gcc-lib" / "ee" / ee_compiler_dirname / "cc1plus",
|
||||||
|
"cpp": compiler_dir / "lib" / "gcc-lib" / "ee" / ee_compiler_dirname / "cpp",
|
||||||
|
"as": compiler_dir / "ee" / "bin" / "as",
|
||||||
|
}
|
||||||
|
|
||||||
|
return commands[command]
|
||||||
|
|
||||||
|
|
||||||
|
def make_compiler_cmd(config_dir: Path, src_path: Path, language: str):
|
||||||
|
rel_root = Path(os.path.relpath(ROOT, config_dir))
|
||||||
|
tools_dir = rel_root / "tools"
|
||||||
|
|
||||||
|
game_cc_dir = f"{tools_dir}/cc/{COMPILER}/bin"
|
||||||
|
lib_cc_dir = f"{tools_dir}/cc/{COMPILER}/bin"
|
||||||
|
|
||||||
|
language_define = ""
|
||||||
|
if language == "eu":
|
||||||
|
language_define = "-DBUILD_EU_VERSION"
|
||||||
|
|
||||||
|
compiler_includes = f"-I{src_path.parent / 'src'} -I{src_path.parent / 'include'} -Iinclude -isystem include/sdk/ee -isystem include/gcc"
|
||||||
|
assembler_includes = f"-Wa,-I{src_path.parent / 'include'} -Wa,-I{src_path.parent}"
|
||||||
|
common_includes = f"{compiler_includes} {assembler_includes} {language_define}"
|
||||||
|
game_compile_cmd = f"{game_cc_dir}/ee-gcc -c {common_includes} {COMPILER_FLAGS}"
|
||||||
|
lib_compile_cmd = f"{lib_cc_dir}/ee-gcc -c -isystem include/{COMPILER} {common_includes} {COMPILER_FLAGS}"
|
||||||
|
|
||||||
|
return game_compile_cmd, lib_compile_cmd, common_includes
|
||||||
|
|
||||||
|
|
||||||
|
WIBO_VER = "0.6.4"
|
||||||
|
|
||||||
|
|
||||||
|
def exec_shell(command: list[str]) -> str:
|
||||||
|
ret = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||||
|
return ret.stdout
|
||||||
|
|
||||||
|
|
||||||
|
def clean(config_dir: Path, config: dict[str, Any]):
|
||||||
|
"""
|
||||||
|
Removes all temporary files and folders.
|
||||||
|
"""
|
||||||
|
basename = Path(config["options"]["basename"])
|
||||||
|
|
||||||
|
asm_path = Path(config["options"]["asm_path"])
|
||||||
|
asset_path = Path(config["options"]["asset_path"])
|
||||||
|
build_path = Path(config["options"]["build_path"])
|
||||||
|
cc_str_path = Path("cc-src")
|
||||||
|
|
||||||
|
relative_asm_path = (config_dir / asm_path).resolve().relative_to(ROOT)
|
||||||
|
relative_asset_path = (config_dir / asset_path).resolve().relative_to(ROOT)
|
||||||
|
relative_build_path = (config_dir / build_path).resolve().relative_to(ROOT)
|
||||||
|
relative_cc_str_path = (config_dir / cc_str_path).resolve().relative_to(ROOT)
|
||||||
|
|
||||||
|
for file in (
|
||||||
|
".splache",
|
||||||
|
"build.ninja",
|
||||||
|
".ninja_log",
|
||||||
|
"permuter_settings.toml",
|
||||||
|
"undefined_syms_auto.txt",
|
||||||
|
f"{basename}.ld",
|
||||||
|
):
|
||||||
|
(config_dir / file).unlink(missing_ok=True)
|
||||||
|
|
||||||
|
shutil.rmtree(relative_asm_path, ignore_errors=True)
|
||||||
|
shutil.rmtree(relative_asset_path, ignore_errors=True)
|
||||||
|
shutil.rmtree(relative_build_path, ignore_errors=True)
|
||||||
|
shutil.rmtree(relative_cc_str_path, ignore_errors=True)
|
||||||
|
|
||||||
|
|
||||||
|
def write_permuter_settings(config_dir: Path, src_path: Path, language: str):
|
||||||
|
game_compile_cmd, _, _ = make_compiler_cmd(config_dir, src_path, language)
|
||||||
|
with open(config_dir / "permuter_settings.toml", "w") as f:
|
||||||
|
f.write(
|
||||||
|
f"""compiler_command = "{game_compile_cmd} -D__GNUC__"
|
||||||
|
assembler_command = "mips-linux-gnu-as -march=r5900 -mabi=eabi -Iinclude"
|
||||||
|
compiler_type = "gcc"
|
||||||
|
|
||||||
|
[preserve_macros]
|
||||||
|
|
||||||
|
[decompme.compilers]
|
||||||
|
"tools/build/cc/gcc/gcc" = "{COMPILER}"
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def build_stuff(
|
||||||
|
config_dir: Path,
|
||||||
|
config: dict[str, Any],
|
||||||
|
linker_entries: list[LinkerEntry],
|
||||||
|
language: str,
|
||||||
|
):
|
||||||
|
basename = Path(config["options"]["basename"]).name
|
||||||
|
ld_path = f"{basename}.ld"
|
||||||
|
elf_path = f"build/{basename}"
|
||||||
|
map_path = f"build/{basename}.map"
|
||||||
|
pre_elf_path = f"build/{basename}.elf"
|
||||||
|
|
||||||
|
src_path = Path(config["options"]["src_path"])
|
||||||
|
game_compile_cmd, lib_compile_cmd, common_includes = make_compiler_cmd(config_dir, src_path, language)
|
||||||
|
|
||||||
|
built_objects: set[Path] = set()
|
||||||
|
|
||||||
|
def build(
|
||||||
|
object_paths: Union[Path, list[Path]],
|
||||||
|
src_paths: list[Path],
|
||||||
|
task: str,
|
||||||
|
variables: dict[str, str] = {},
|
||||||
|
implicit_outputs: list[str] = [],
|
||||||
|
):
|
||||||
|
if not isinstance(object_paths, list):
|
||||||
|
object_paths = [object_paths]
|
||||||
|
|
||||||
|
# FIX: escape any $ sign with $$ as ninja_syntax
|
||||||
|
# doesn't seem to do any escaping
|
||||||
|
object_paths = [Path(str(entry).replace("$", "$$")) for entry in object_paths]
|
||||||
|
src_paths = [Path(str(entry).replace("$", "$$")) for entry in src_paths]
|
||||||
|
|
||||||
|
object_strs = [str(obj) for obj in object_paths]
|
||||||
|
|
||||||
|
for object_path in object_paths:
|
||||||
|
if object_path.suffix == ".o":
|
||||||
|
built_objects.add(object_path)
|
||||||
|
|
||||||
|
ninja.build(
|
||||||
|
outputs=object_strs,
|
||||||
|
rule=task,
|
||||||
|
inputs=[str(s) for s in src_paths],
|
||||||
|
variables=variables,
|
||||||
|
implicit_outputs=implicit_outputs,
|
||||||
|
)
|
||||||
|
|
||||||
|
ninja = ninja_syntax.Writer(open(str(ROOT / config_dir / "build.ninja"), "w"), width=9999)
|
||||||
|
|
||||||
|
# Rules
|
||||||
|
cross = "mips-linux-gnu-"
|
||||||
|
|
||||||
|
ld_args = "--no-warn-rwx-segments -EL -T undefined_syms.txt -T undefined_syms_auto.txt -T undefined_funcs_auto.txt -Map $mapfile -T $in -o $out"
|
||||||
|
|
||||||
|
cpp = Path("..", "..", get_compiler_command("cpp"))
|
||||||
|
|
||||||
|
ninja.rule(
|
||||||
|
"as",
|
||||||
|
description="as $in",
|
||||||
|
# NOTE: Japanese strings are EUC-JP encoded!!
|
||||||
|
# We need to convert them from (-f) UTF-8 to (-t) EUC-JP while compiling,
|
||||||
|
# otherwise Japanese strings will be compiled wrong!
|
||||||
|
command=f"{cpp} {common_includes} $in -o - | iconv -f=UTF-8 -t=EUC-JP $in | {cross}as -no-pad-sections -EL -march=5900 -mabi=eabi -I{src_path.parent / 'include'} -o $out",
|
||||||
|
)
|
||||||
|
|
||||||
|
ninja.rule(
|
||||||
|
"cc-s",
|
||||||
|
description="compile c source to object through assembly",
|
||||||
|
command=(
|
||||||
|
f"s_in=$$(echo $in.S | sed 's,^[^/]*/[^/]*/,cc-src/,') && " # .............. 1) remove ../../ from path + prefix with cc-src/ + suffix with .S and store it into s_in var: ../../src/file.c -> s_in=cc-src/src/file.c.S
|
||||||
|
f'mkdir -p $$(dirname "$$s_in") && ' # ..................................... 2) create directory from s_in var: s_in=cc-src/src/path/to/file.c.S -> mkdir -p cc-src/src/path/to/
|
||||||
|
f"{game_compile_cmd.replace(' -c ', ' -S ')} $in -o $$s_in && " # .......... 3) replace -c with -S in gcc command to generate intermediate assembly file instead of object
|
||||||
|
f"python3 {ROOT}/tools/python/fix_asm_matching.py {language} $$s_in && " # . 4) fix assembly file using known patterns with tools/python/fix_asm_matching.py
|
||||||
|
f"{game_compile_cmd} $$s_in -o $out && " # ................................. 5) compile assembly file into object
|
||||||
|
f"{cross}strip $out -N dummy-symbol-name" # ................................ 6) strip 'dummy-symbol-name' from object
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
ninja.rule(
|
||||||
|
"cc",
|
||||||
|
description="cc $in",
|
||||||
|
command=f"{game_compile_cmd} $in -o $out && {cross}strip $out -N dummy-symbol-name",
|
||||||
|
)
|
||||||
|
|
||||||
|
ninja.rule(
|
||||||
|
"cc-eucjp",
|
||||||
|
description="convert source to EUC-JP encoding and compile same as 'cc'",
|
||||||
|
command=(
|
||||||
|
f"eucjp_in=$$(echo $in.eucjp.c | sed 's,^[^/]*/[^/]*/,cc-src/,') && " # . 1) remove ../../ from path + prefix with cc-src/ + suffix with .eucjp.c and store it into eucjp_in var: ../../src/file.c -> eucjp_in=cc-src/src/file.c.eucjp.c
|
||||||
|
f'mkdir -p $$(dirname "$$eucjp_in") && ' # .............................. 2) create directory from eucjp_in var: s_in=cc-src/src/path/to/file.c.eucjp.c -> mkdir -p cc-src/src/path/to/
|
||||||
|
f"iconv -o $$eucjp_in -f=UTF-8 -t=EUC-JP $in && " # ..................... 3) convert source file to EUC-JP (save converted source to cc-src/src/file.c.eucjp.c)
|
||||||
|
f'{game_compile_cmd} -I$$(dirname "$in") $$eucjp_in -o $out && ' # ...... 4) compile converted source file into object (also add original source directory as include path to allow relative imports)
|
||||||
|
f"{cross}strip $out -N dummy-symbol-name" # ............................. 5) strip 'dummy-symbol-name' from object
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
ninja.rule(
|
||||||
|
"libcc",
|
||||||
|
description="cc $in",
|
||||||
|
command=f"{lib_compile_cmd} $in -o $out && {cross}strip $out -N dummy-symbol-name",
|
||||||
|
)
|
||||||
|
|
||||||
|
ninja.rule(
|
||||||
|
"ld",
|
||||||
|
description="link $out",
|
||||||
|
command=f"{cross}ld {ld_args}",
|
||||||
|
)
|
||||||
|
|
||||||
|
ninja.rule(
|
||||||
|
"sha1sum",
|
||||||
|
description="sha1sum $in",
|
||||||
|
command="sha1sum -c $in && touch $out",
|
||||||
|
)
|
||||||
|
|
||||||
|
ninja.rule(
|
||||||
|
"elf",
|
||||||
|
description="elf $out",
|
||||||
|
command=f"{cross}objcopy $in $out -O binary && python3 {ROOT}/tools/python/fix_bin_matching.py {language} $out",
|
||||||
|
)
|
||||||
|
|
||||||
|
for entry in linker_entries:
|
||||||
|
seg = entry.segment
|
||||||
|
|
||||||
|
if seg.type[0] == ".":
|
||||||
|
continue
|
||||||
|
|
||||||
|
if entry.object_path is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if isinstance(
|
||||||
|
seg,
|
||||||
|
(
|
||||||
|
splat.segtypes.common.asm.CommonSegAsm,
|
||||||
|
splat.segtypes.common.data.CommonSegData,
|
||||||
|
),
|
||||||
|
):
|
||||||
|
build(entry.object_path, entry.src_paths, "as")
|
||||||
|
|
||||||
|
elif isinstance(seg, splat.segtypes.common.c.CommonSegC):
|
||||||
|
entry.src_paths = [Path("../..") / Path(f"{src_path}") for src_path in entry.src_paths]
|
||||||
|
if any(str(src_path).startswith("src/lib/") for src_path in entry.src_paths):
|
||||||
|
build(entry.object_path, entry.src_paths, "libcc")
|
||||||
|
|
||||||
|
elif entry.object_path.name in ASM_PATCH_LIST:
|
||||||
|
build(entry.object_path, entry.src_paths, "cc-s")
|
||||||
|
|
||||||
|
elif entry.object_path.name in EUC_JP_LIST:
|
||||||
|
build(entry.object_path, entry.src_paths, "cc-eucjp")
|
||||||
|
|
||||||
|
else:
|
||||||
|
build(entry.object_path, entry.src_paths, "cc")
|
||||||
|
|
||||||
|
elif isinstance(seg, splat.segtypes.common.databin.CommonSegDatabin):
|
||||||
|
build(entry.object_path, entry.src_paths, "as")
|
||||||
|
|
||||||
|
elif isinstance(seg, splat.segtypes.common.rodatabin.CommonSegRodatabin):
|
||||||
|
build(entry.object_path, entry.src_paths, "as")
|
||||||
|
|
||||||
|
elif isinstance(seg, splat.segtypes.common.textbin.CommonSegTextbin):
|
||||||
|
build(entry.object_path, entry.src_paths, "as")
|
||||||
|
|
||||||
|
elif isinstance(seg, splat.segtypes.common.sbss.CommonSegSbss):
|
||||||
|
build(entry.object_path, entry.src_paths, "as")
|
||||||
|
|
||||||
|
else:
|
||||||
|
print(f"ERROR: Unsupported build segment type {seg.type}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
ninja.build(
|
||||||
|
pre_elf_path,
|
||||||
|
"ld",
|
||||||
|
ld_path,
|
||||||
|
implicit=[str(obj) for obj in built_objects],
|
||||||
|
variables={"mapfile": map_path},
|
||||||
|
)
|
||||||
|
|
||||||
|
ninja.build(
|
||||||
|
elf_path,
|
||||||
|
"elf",
|
||||||
|
pre_elf_path,
|
||||||
|
)
|
||||||
|
|
||||||
|
ninja.build(
|
||||||
|
elf_path + ".ok",
|
||||||
|
"sha1sum",
|
||||||
|
"checksum.sha1",
|
||||||
|
implicit=[elf_path],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def make_asm(config_path: Path, config: dict[str, Any]):
|
||||||
|
"""
|
||||||
|
Extracts assembly for each function into 'expected/asm/' subfolder.
|
||||||
|
|
||||||
|
The extraction is done following these steps:
|
||||||
|
1. create temporary directory in project folder
|
||||||
|
2. copy yaml to temporary directory
|
||||||
|
3. modify yaml to have c subsegments instead of asm subsegments
|
||||||
|
4. remove data, bss, etc., subsegments
|
||||||
|
5. run splat on the new config yaml
|
||||||
|
6. splat extracts assembly for each function into '<temp_dir>/asm/nonmatchings/'
|
||||||
|
7. copy '<temp_dir>/asm/nonmatchings/' to '<project_dir>/expected/asm/'
|
||||||
|
"""
|
||||||
|
with tempfile.TemporaryDirectory(dir=config_path, prefix="tmp_") as tmp_dir:
|
||||||
|
tmp_path = Path(tmp_dir)
|
||||||
|
|
||||||
|
yaml_path = tmp_path / "config.yaml"
|
||||||
|
asm_path = tmp_path / "asm" / "nonmatchings"
|
||||||
|
dst_path = tmp_path / ".." / "expected" / "asm"
|
||||||
|
dst_path = dst_path.resolve().relative_to(ROOT)
|
||||||
|
|
||||||
|
if dst_path.exists():
|
||||||
|
print(f"expected asm dir '{dst_path}' already exists")
|
||||||
|
return
|
||||||
|
|
||||||
|
config = copy.deepcopy(config)
|
||||||
|
config["options"]["target_path"] = "../" + config["options"]["target_path"]
|
||||||
|
config["options"]["asm_path"] = "asm"
|
||||||
|
config["options"]["src_path"] = "src"
|
||||||
|
config["options"]["build_path"] = "build"
|
||||||
|
config["options"]["asset_path"] = "assets"
|
||||||
|
config["options"]["undefined_funcs_auto_path"] = "../" + config["options"]["undefined_funcs_auto_path"]
|
||||||
|
config["options"]["undefined_syms_auto_path"] = "../" + config["options"]["undefined_syms_auto_path"]
|
||||||
|
config["options"]["symbol_addrs_path"] = "../" + config["options"]["symbol_addrs_path"]
|
||||||
|
config["options"]["extensions_path"] = "../" + config["options"]["extensions_path"]
|
||||||
|
|
||||||
|
new_segments: list[Any] = []
|
||||||
|
segments: list[Any] = config["segments"]
|
||||||
|
for segment in segments:
|
||||||
|
if isinstance(segment, list):
|
||||||
|
new_segments.append(segment)
|
||||||
|
elif isinstance(segment, dict) and segment["name"] == "main":
|
||||||
|
new_subsegments: list[Any] = []
|
||||||
|
subsegments = cast(list[Any], segment["subsegments"])
|
||||||
|
for subsegment in subsegments:
|
||||||
|
if isinstance(subsegment, list):
|
||||||
|
if subsegment[1] == "asm":
|
||||||
|
subsegment[1] = "c"
|
||||||
|
new_subsegments.append(subsegment)
|
||||||
|
elif isinstance(subsegment, dict):
|
||||||
|
subsegment["type"] = subsegment["type"].strip(".")
|
||||||
|
if subsegment["type"] == "rodata":
|
||||||
|
# splat now requires rodata to be always prefixed with a dot (.)
|
||||||
|
# for the rodata migration to work properly
|
||||||
|
subsegment["type"] = ".rodata"
|
||||||
|
new_subsegments.append(subsegment)
|
||||||
|
segment["subsegments"] = new_subsegments
|
||||||
|
new_segments.append(segment)
|
||||||
|
config["segments"] = new_segments
|
||||||
|
|
||||||
|
def rename_locals(base_path: Path):
|
||||||
|
for asm_file in base_path.rglob("*.s"):
|
||||||
|
data = asm_file.read_text()
|
||||||
|
data = re.sub(r"__local_\d+", "", data)
|
||||||
|
asm_file.write_text(data)
|
||||||
|
|
||||||
|
with yaml_path.open(mode="w") as yaml_file:
|
||||||
|
yaml.dump(config, yaml_file, default_flow_style=False)
|
||||||
|
|
||||||
|
with suppress_stdout_stderr():
|
||||||
|
split.main([yaml_path], modes=["all"], verbose=False)
|
||||||
|
|
||||||
|
# remove '__local_#' from asm
|
||||||
|
rename_locals(asm_path)
|
||||||
|
|
||||||
|
dst_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
shutil.copytree(asm_path, dst_path, dirs_exist_ok=True)
|
||||||
|
|
||||||
|
print(f"expected asm extracted to '{dst_path}'")
|
||||||
|
|
||||||
|
# make expected objs
|
||||||
|
|
||||||
|
for subseg in new_segments[1]["subsegments"]:
|
||||||
|
if isinstance(subseg, list) and subseg[1] == "c":
|
||||||
|
subseg[1] = "asm"
|
||||||
|
subseg[2] += ".c"
|
||||||
|
|
||||||
|
config["options"]["asm_jtbl_label_macro"] = "llabel"
|
||||||
|
|
||||||
|
with yaml_path.open(mode="w") as yaml_file:
|
||||||
|
yaml.dump(config, yaml_file, default_flow_style=False)
|
||||||
|
|
||||||
|
shutil.rmtree(tmp_path / "asm")
|
||||||
|
(tmp_path / ".splache").unlink()
|
||||||
|
|
||||||
|
with suppress_stdout_stderr():
|
||||||
|
split.main([yaml_path], modes=["all"], verbose=False)
|
||||||
|
|
||||||
|
# remove '__local_#' from asm
|
||||||
|
rename_locals(asm_path)
|
||||||
|
|
||||||
|
dst_path = dst_path.parent / "obj"
|
||||||
|
tmp_obj_path = tmp_path / "obj"
|
||||||
|
tmp_asm_dir = tmp_path / "asm"
|
||||||
|
|
||||||
|
cpp = Path("..", "..", "..", get_compiler_command("cpp"))
|
||||||
|
|
||||||
|
for asm_file in tmp_asm_dir.rglob("*.c.s"):
|
||||||
|
asm_file_rel = asm_file.relative_to(tmp_path)
|
||||||
|
obj_file_rel = Path("obj") / asm_file.relative_to(tmp_asm_dir).with_suffix(".o")
|
||||||
|
obj_file = tmp_obj_path / obj_file_rel.relative_to("obj")
|
||||||
|
obj_file.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
subprocess.run(
|
||||||
|
f"{cpp} -I../../../src -I../../../include -Iinclude -isystem include/sdk/ee -isystem include/gcc -Wa,-I../../../include -Wa,-I../../.. '{asm_file_rel}' -o - | "
|
||||||
|
f"iconv -f=UTF-8 -t=EUC-JP '{asm_file_rel}' | "
|
||||||
|
f"mips-linux-gnu-as -no-pad-sections -EL -march=5900 -mabi=eabi -I../../../include -o {obj_file_rel} {asm_file_rel}",
|
||||||
|
shell=True,
|
||||||
|
cwd=tmp_path,
|
||||||
|
)
|
||||||
|
|
||||||
|
shutil.copytree(tmp_obj_path, dst_path, dirs_exist_ok=True)
|
||||||
|
|
||||||
|
print(f"expected obj built to '{dst_path}'")
|
||||||
|
|
||||||
|
|
||||||
|
def generate_objdiff_configuration(config_path: Path, config: dict[str, Any], language: str):
|
||||||
|
"""
|
||||||
|
Generate `objdiff.json` configuration from splat YAML config.
|
||||||
|
|
||||||
|
Parse splat YAML config to get a list of the TUs that need to
|
||||||
|
be diffed and create appropriate `units` for objdiff to process.
|
||||||
|
|
||||||
|
Target objects need to be extracted separately (see the
|
||||||
|
`make <lang>-make-asm` command) in order for objdiff to find the
|
||||||
|
target files.
|
||||||
|
"""
|
||||||
|
segments: list[Any] = config["segments"]
|
||||||
|
|
||||||
|
tu_to_diff: list[tuple[Literal["asm", "c"], str]] = []
|
||||||
|
|
||||||
|
for segment in segments:
|
||||||
|
if not (isinstance(segment, dict) and segment["name"] == "main"):
|
||||||
|
# we are looking for the main segment
|
||||||
|
continue
|
||||||
|
|
||||||
|
subsegments = cast(list[Any], segment["subsegments"])
|
||||||
|
|
||||||
|
for subsegment in subsegments:
|
||||||
|
if isinstance(subsegment, list):
|
||||||
|
_, subs_type, subs_name = cast(tuple[int, str, str], subsegment)
|
||||||
|
|
||||||
|
elif isinstance(subsegment, dict):
|
||||||
|
subs_type = cast(int, subsegment["type"])
|
||||||
|
subs_name = cast(str, subsegment["name"])
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise RuntimeError("invalid subsegment type")
|
||||||
|
|
||||||
|
if subs_type in ("asm", "c"):
|
||||||
|
if subs_name in (
|
||||||
|
"crt0",
|
||||||
|
"main/glob",
|
||||||
|
"graphics/motion/mdldat",
|
||||||
|
"graphics/motion/mim_dat",
|
||||||
|
"graphics/motion/acs_dat",
|
||||||
|
"graphics/scene/scene_dat",
|
||||||
|
"ingame/ig_glob",
|
||||||
|
"mc/mc",
|
||||||
|
"mc/mc_icon",
|
||||||
|
"ingame/entry/fgst_dat",
|
||||||
|
"ingame/entry/rgst_dat",
|
||||||
|
"outgame/btl_mode/btl_dat",
|
||||||
|
"ingame/map/find_dat",
|
||||||
|
"ingame/map/furn_spe/fsla_dat",
|
||||||
|
):
|
||||||
|
# skip it as it's either not part of the game files or a data only TU
|
||||||
|
continue
|
||||||
|
|
||||||
|
tu_to_diff.append((subs_type, subs_name))
|
||||||
|
|
||||||
|
units: list[dict[str, Any]] = []
|
||||||
|
|
||||||
|
for tu_type, tu_name in tu_to_diff:
|
||||||
|
target_path = Path("expected", "obj", tu_name).with_suffix(".c.o")
|
||||||
|
|
||||||
|
# since we only compile fully decompiled TUs, the
|
||||||
|
# "c" type implies that the TU is complete
|
||||||
|
is_complete = tu_type == "c"
|
||||||
|
|
||||||
|
if is_complete:
|
||||||
|
# compose the build path as "build/src/path/of/tu.c.o"
|
||||||
|
base_path = Path("build", "src", tu_name).with_suffix(".c.o")
|
||||||
|
else:
|
||||||
|
# leave unset if the TU is not yet decompiled
|
||||||
|
base_path = None
|
||||||
|
|
||||||
|
unit: dict[str, Any] = {
|
||||||
|
"name": tu_name,
|
||||||
|
"target_path": str(target_path),
|
||||||
|
"base_path": str(base_path) if base_path else None,
|
||||||
|
"metadata": {"progress_categories": [language]},
|
||||||
|
}
|
||||||
|
|
||||||
|
if not base_path:
|
||||||
|
# remove base_path for not yet decompiled TUs
|
||||||
|
# (adding first and then removing if base_path is none allows
|
||||||
|
# for key ordering to be preserved, otherwise adding it later
|
||||||
|
# would put it after metadata)
|
||||||
|
del unit["base_path"]
|
||||||
|
|
||||||
|
units.append(unit)
|
||||||
|
|
||||||
|
category_name = {
|
||||||
|
"us": "Fatal Frame",
|
||||||
|
"eu": "Project Zero",
|
||||||
|
}
|
||||||
|
|
||||||
|
progress_categories = [
|
||||||
|
{"id": language, "name": category_name[language]},
|
||||||
|
]
|
||||||
|
|
||||||
|
objdiff_json: dict[str, Any] = {
|
||||||
|
"$schema": "https://raw.githubusercontent.com/encounter/objdiff/main/config.schema.json",
|
||||||
|
"custom_make": "true",
|
||||||
|
"custom_args": [],
|
||||||
|
"build_target": False,
|
||||||
|
"build_base": False,
|
||||||
|
"watch_patterns": [],
|
||||||
|
"units": units,
|
||||||
|
"progress_categories": progress_categories,
|
||||||
|
}
|
||||||
|
|
||||||
|
objdiff_path = config_path / "objdiff.json"
|
||||||
|
|
||||||
|
with objdiff_path.open(mode="w") as fw:
|
||||||
|
json.dump(objdiff_json, fw, indent=2)
|
||||||
|
|
||||||
|
print(f"Wrote objdiff configuration ({len(units)} units) to {objdiff_path}")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
class ArgsProtocol(Protocol):
|
||||||
|
YAML_FILE: Path
|
||||||
|
clean: bool
|
||||||
|
reset: bool
|
||||||
|
make_asm: bool
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="Configure the project")
|
||||||
|
parser.add_argument(
|
||||||
|
"YAML_FILE",
|
||||||
|
type=Path,
|
||||||
|
help="yaml file to configure the project",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-c",
|
||||||
|
"--clean",
|
||||||
|
help="Clean extraction and build artifacts",
|
||||||
|
action="store_true",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--make-asm",
|
||||||
|
help="Extract assembly for each function into 'expected/asm/' subfolder",
|
||||||
|
action="store_true",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-r",
|
||||||
|
"--reset",
|
||||||
|
help="Reset config dir to original state",
|
||||||
|
action="store_true",
|
||||||
|
)
|
||||||
|
args = cast(ArgsProtocol, parser.parse_args())
|
||||||
|
|
||||||
|
# try:
|
||||||
|
# exec_shell(["wibo"])
|
||||||
|
# except FileNotFoundError:
|
||||||
|
# print("ERROR: wibo does not appear to be accessible")
|
||||||
|
# print("To install it, please download it and put it in your PATH:")
|
||||||
|
# print(
|
||||||
|
# f" wget https://github.com/decompals/wibo/releases/download/{WIBO_VER}/wibo && "
|
||||||
|
# f"chmod +x wibo && sudo mv wibo /usr/bin/"
|
||||||
|
# )
|
||||||
|
# sys.exit(1)
|
||||||
|
|
||||||
|
cwd = Path(os.getcwd()).resolve()
|
||||||
|
if not ROOT.samefile(cwd):
|
||||||
|
print("ERROR: this script must be run from it's directory!")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
config = splat_load_yaml(
|
||||||
|
[args.YAML_FILE],
|
||||||
|
modes=["all"],
|
||||||
|
verbose=False,
|
||||||
|
disassemble_all=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
basename = config["options"]["basename"]
|
||||||
|
config_dir = Path(args.YAML_FILE).parent
|
||||||
|
|
||||||
|
if basename not in LANGUAGES:
|
||||||
|
supported_elfs = f"{set(f'{elf} ({lang})' for elf, lang in LANGUAGES.items())}".replace("'", "")
|
||||||
|
print(f"unsupported game ELF. Supported versions are: {supported_elfs}")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
language = LANGUAGES[basename]
|
||||||
|
|
||||||
|
if args.reset:
|
||||||
|
clean(config_dir, config)
|
||||||
|
return
|
||||||
|
|
||||||
|
if args.make_asm:
|
||||||
|
make_asm(config_dir, config)
|
||||||
|
return
|
||||||
|
|
||||||
|
if args.clean:
|
||||||
|
clean(config_dir, config)
|
||||||
|
|
||||||
|
split.main([args.YAML_FILE], modes=["all"], verbose=False)
|
||||||
|
|
||||||
|
src_path = Path(config["options"]["src_path"])
|
||||||
|
asm_path = Path(config["options"]["asm_path"])
|
||||||
|
asset_path = Path(config["options"]["asset_path"])
|
||||||
|
|
||||||
|
asm_data_path = (config_dir / asm_path).resolve().relative_to(ROOT) / "data"
|
||||||
|
asset_rel_path = (config_dir / asset_path).resolve().relative_to(ROOT)
|
||||||
|
assert asm_data_path.is_dir(), f"{asm_data_path} not found or not a directory"
|
||||||
|
assert asset_rel_path.is_dir(), f"{asset_rel_path} not found or not a directory"
|
||||||
|
|
||||||
|
# fix asset .incbin path from relative to root to relative to config dir:
|
||||||
|
# e.g., change:
|
||||||
|
# .incbin "config/us/assets/name.section.bin"
|
||||||
|
# to:
|
||||||
|
# .incbin "assets/name.section.bin"
|
||||||
|
fix_assets(asm_data_path, asset_rel_path)
|
||||||
|
|
||||||
|
linker_entries = split.linker_writer.entries
|
||||||
|
|
||||||
|
build_stuff(config_dir, split.config, linker_entries, language)
|
||||||
|
|
||||||
|
write_permuter_settings(config_dir, src_path, language)
|
||||||
|
|
||||||
|
# # replace gp_rel assembler macro with explicit offset as the gcc used
|
||||||
|
# # to compile the code does not support it
|
||||||
|
# gp_value = split.config["options"]["gp_value"]
|
||||||
|
# symbol_addrs_path = Path(split.config["options"]["symbol_addrs_path"])
|
||||||
|
# asm_rel_path = (config_dir / asm_path).resolve().relative_to(ROOT)
|
||||||
|
# symbol_addrs_rel_path = (config_dir / symbol_addrs_path).resolve().relative_to(ROOT)
|
||||||
|
# assert asm_rel_path.is_dir(), f"{asm_rel_path} not found or not a directory"
|
||||||
|
# assert symbol_addrs_rel_path.is_file(), f"{symbol_addrs_rel_path} not found"
|
||||||
|
# fix_gp(asm_rel_path, gp_value, symbol_addrs_rel_path)
|
||||||
|
|
||||||
|
# fix linkerscript by applying explicit alignments as
|
||||||
|
# specified in the config yaml
|
||||||
|
linkerscript_path = (config_dir / f"{basename}.ld").resolve().relative_to(ROOT)
|
||||||
|
assert linkerscript_path.is_file(), f"{linkerscript_path} not found"
|
||||||
|
fix_linkerscript(split.config, linkerscript_path)
|
||||||
|
|
||||||
|
generate_objdiff_configuration(config_dir, split.config, language)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
#ifndef COMMON_H
|
||||||
|
#define COMMON_H
|
||||||
|
|
||||||
|
#include "include_asm.h"
|
||||||
|
|
||||||
|
typedef char s8;
|
||||||
|
typedef short s16;
|
||||||
|
typedef int s32;
|
||||||
|
typedef long s64;
|
||||||
|
|
||||||
|
typedef volatile s8 vs8;
|
||||||
|
typedef volatile s16 vs16;
|
||||||
|
typedef volatile s32 vs32;
|
||||||
|
typedef volatile s64 vs64;
|
||||||
|
|
||||||
|
|
||||||
|
typedef unsigned char u8;
|
||||||
|
typedef unsigned short u16;
|
||||||
|
typedef unsigned int u32;
|
||||||
|
typedef unsigned long u64;
|
||||||
|
|
||||||
|
typedef volatile u8 vu8;
|
||||||
|
typedef volatile u16 vu16;
|
||||||
|
typedef volatile u32 vu32;
|
||||||
|
typedef volatile u64 vu64;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
vs8 s8;
|
||||||
|
vs16 s16;
|
||||||
|
vs32 s32;
|
||||||
|
vs64 s64;
|
||||||
|
vu8 u8;
|
||||||
|
vu16 u16;
|
||||||
|
vu32 u32;
|
||||||
|
vu64 u64;
|
||||||
|
} _VX;
|
||||||
|
|
||||||
|
typedef float f32;
|
||||||
|
|
||||||
|
#define UNK_TYPE s32
|
||||||
|
#define UNK_PTR void*
|
||||||
|
#define UNK_RET void
|
||||||
|
#define UNK_FUN_ARG void(*)(void)
|
||||||
|
#define UNK_FUN_PTR(name) void(*name)(void)
|
||||||
|
#define UNK_ARGS
|
||||||
|
|
||||||
|
#define NULL 0
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
#define b32 s32 // 32-bit boolean (TRUE/FALSE)
|
||||||
|
|
||||||
|
#define ARRAY_COUNT(arr) (s32)(sizeof(arr) / sizeof(arr[0]))
|
||||||
|
#define ARRAY_COUNTU(arr) (u32)(sizeof(arr) / sizeof(arr[0]))
|
||||||
|
|
||||||
|
// #define PI 3.1415928f
|
||||||
|
|
||||||
|
f32 cosf(f32);
|
||||||
|
f32 atan2f(f32, f32);
|
||||||
|
|
||||||
|
#define BSS __attribute__ ((section (".bss")))
|
||||||
|
|
||||||
|
#endif /* COMMON_H */
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
#ifndef EE_EEKERNEL_H
|
||||||
|
#define EE_EEKERNEL_H
|
||||||
|
|
||||||
|
#define WRITEBACK_DCACHE 0
|
||||||
|
#define INVALIDATE_DCACHE 1
|
||||||
|
#define INVALIDATE_ICACHE 2
|
||||||
|
#define INVALIDATE_CACHE 3
|
||||||
|
|
||||||
|
#define DMAC_VIF0 0
|
||||||
|
#define DMAC_VIF1 1
|
||||||
|
#define DMAC_GIF 2
|
||||||
|
#define DMAC_FROM_IPU 3
|
||||||
|
#define DMAC_TO_IPU 4
|
||||||
|
#define DMAC_FROM_SPR 8
|
||||||
|
#define DMAC_TO_SPR 9
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int status;
|
||||||
|
void *entry;
|
||||||
|
void *stack;
|
||||||
|
int stackSize;
|
||||||
|
void *gpReg;
|
||||||
|
int initPriority;
|
||||||
|
int currentPriority;
|
||||||
|
u_int attr;
|
||||||
|
u_int option;
|
||||||
|
int waitType;
|
||||||
|
int waitId;
|
||||||
|
int wakeupCount;
|
||||||
|
} ThreadParam;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int currentCount;
|
||||||
|
int maxCount;
|
||||||
|
int initCount;
|
||||||
|
int numWaitThreads;
|
||||||
|
u_int attr;
|
||||||
|
u_int option;
|
||||||
|
} SemaParam;
|
||||||
|
|
||||||
|
extern void *_gp;
|
||||||
|
|
||||||
|
#define ExitHandler() \
|
||||||
|
asm volatile("\n\
|
||||||
|
sync.l \n\
|
||||||
|
ei \n\
|
||||||
|
");
|
||||||
|
|
||||||
|
int CreateThread(ThreadParam *);
|
||||||
|
int StartThread(int, void *arg);
|
||||||
|
int GetThreadId(void);
|
||||||
|
int ChangeThreadPriority(int, int);
|
||||||
|
int RotateThreadReadyQueue(int);
|
||||||
|
|
||||||
|
int CreateSema(SemaParam *param);
|
||||||
|
int SignalSema(int);
|
||||||
|
int WaitSema(int);
|
||||||
|
int DeleteSema(int);
|
||||||
|
|
||||||
|
#endif // EE_EEKERNEL_H
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
#ifndef EE_EEREGS_H
|
||||||
|
#define EE_EEREGS_H
|
||||||
|
|
||||||
|
#define D_CTRL_RELE_M (0x01<<1)
|
||||||
|
|
||||||
|
#define REG_DMAC_CTRL (volatile u_int *)0x1000e000
|
||||||
|
#define REG_DMAC_STAT (volatile u_int *)0x1000e010
|
||||||
|
|
||||||
|
#define VU0_MICRO_ADDR ((u_int)(0x11000000))
|
||||||
|
#define VU0_MEM_ADDR ((u_int)(0x11004000))
|
||||||
|
#define VU1_MICRO_ADDR ((u_int)(0x11008000))
|
||||||
|
#define VU1_MEM_ADDR ((u_int)(0x1100c000))
|
||||||
|
|
||||||
|
#define IPU_CMD ((volatile u_int *)(0x10002000))
|
||||||
|
#define IPU_CTRL ((volatile u_int *)(0x10002010))
|
||||||
|
#define IPU_BP ((volatile u_int *)(0x10002020))
|
||||||
|
|
||||||
|
#define DGET_IPU_CTRL() (*IPU_CTRL)
|
||||||
|
#define DPUT_IPU_CMD(x) (*IPU_CMD = (x))
|
||||||
|
|
||||||
|
#define DGET_IPU_CTRL() (*IPU_CTRL)
|
||||||
|
#define DGET_IPU_BP() (*IPU_BP)
|
||||||
|
|
||||||
|
#define D_ENABLER ((volatile u_int *)(0x1000f520))
|
||||||
|
#define D_ENABLEW ((volatile u_int *)(0x1000f590))
|
||||||
|
#define D3_CHCR ((volatile u_int *)(0x1000b000))
|
||||||
|
#define D4_CHCR ((volatile u_int *)(0x1000b400))
|
||||||
|
|
||||||
|
#define D3_CHCR ((volatile u_int *)(0x1000b000))
|
||||||
|
#define D3_MADR ((volatile u_int *)(0x1000b010))
|
||||||
|
#define D3_QWC ((volatile u_int *)(0x1000b020))
|
||||||
|
|
||||||
|
#define D4_CHCR ((volatile u_int *)(0x1000b400))
|
||||||
|
#define D4_MADR ((volatile u_int *)(0x1000b410))
|
||||||
|
#define D4_QWC ((volatile u_int *)(0x1000b420))
|
||||||
|
#define D4_TADR ((volatile u_int *)(0x1000b430))
|
||||||
|
|
||||||
|
|
||||||
|
#define GS_CSR ((volatile u_long *)(0x12001000))
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned EN1:1;
|
||||||
|
unsigned EN2:1;
|
||||||
|
unsigned CRTMD:3;
|
||||||
|
unsigned MMOD:1;
|
||||||
|
unsigned AMOD:1;
|
||||||
|
unsigned SLBG:1;
|
||||||
|
unsigned ALP:8;
|
||||||
|
unsigned p0:16;
|
||||||
|
unsigned int p1;
|
||||||
|
} tGS_PMODE;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned INT:1;
|
||||||
|
unsigned FFMD:1;
|
||||||
|
unsigned DPMS:2;
|
||||||
|
unsigned p0:28;
|
||||||
|
unsigned int p1;
|
||||||
|
} tGS_SMODE2;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned FBP:9;
|
||||||
|
unsigned FBW:6;
|
||||||
|
unsigned PSM:5;
|
||||||
|
unsigned p0:12;
|
||||||
|
unsigned DBX:11;
|
||||||
|
unsigned DBY:11;
|
||||||
|
unsigned p1:10;
|
||||||
|
} tGS_DISPFB2;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned DX:12;
|
||||||
|
unsigned DY:11;
|
||||||
|
unsigned MAGH:4;
|
||||||
|
unsigned MAGV:2;
|
||||||
|
unsigned p0:3;
|
||||||
|
unsigned DW:12;
|
||||||
|
unsigned DH:11;
|
||||||
|
unsigned p1:9;
|
||||||
|
} tGS_DISPLAY2;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned R:8;
|
||||||
|
unsigned G:8;
|
||||||
|
unsigned B:8;
|
||||||
|
unsigned p0:8;
|
||||||
|
unsigned int p1;
|
||||||
|
} tGS_BGCOLOR;
|
||||||
|
|
||||||
|
#endif // EE_EEREGS_H
|
||||||
@@ -0,0 +1,445 @@
|
|||||||
|
#ifndef EE_EESTRUCT_H
|
||||||
|
#define EE_EESTRUCT_H
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
#define SCR_WIDTH 640
|
||||||
|
#define SCR_HEIGHT 224
|
||||||
|
|
||||||
|
#define DISP_WIDTH 640
|
||||||
|
#define DISP_HEIGHT 448
|
||||||
|
|
||||||
|
#define GS_X_COORD(x) ((2048 - (SCR_WIDTH / 2) + x) * 16)
|
||||||
|
#define GS_Y_COORD(y) ((2048 - (SCR_HEIGHT / 2) + y) * 16)
|
||||||
|
|
||||||
|
#define DMArefe (0<<28)
|
||||||
|
#define DMAcnt (1<<28)
|
||||||
|
#define DMAnext (2<<28)
|
||||||
|
#define DMAref (3<<28)
|
||||||
|
#define DMArefs (4<<28)
|
||||||
|
#define DMAcall (5<<28)
|
||||||
|
#define DMAret (6<<28)
|
||||||
|
#define DMAend (7<<28)
|
||||||
|
|
||||||
|
#define SCE_GS_FALSE (0)
|
||||||
|
#define SCE_GS_TRUE (1)
|
||||||
|
|
||||||
|
#define SCE_GS_REPEAT (0)
|
||||||
|
#define SCE_GS_CLAMP (1)
|
||||||
|
#define SCE_GS_REGION_CLAMP (2)
|
||||||
|
#define SCE_GS_REGION_REPEAT (3)
|
||||||
|
|
||||||
|
#define SCE_GS_ZNOUSE (0)
|
||||||
|
#define SCE_GS_ZALWAYS (1)
|
||||||
|
#define SCE_GS_ZGEQUAL (2)
|
||||||
|
#define SCE_GS_ZGREATER (3)
|
||||||
|
|
||||||
|
#define SCE_GS_PSMCT32 (0)
|
||||||
|
#define SCE_GS_PSMCT24 (1)
|
||||||
|
#define SCE_GS_PSMCT16 (2)
|
||||||
|
#define SCE_GS_PSMCT16S (10)
|
||||||
|
#define SCE_GS_PSMT8 (19)
|
||||||
|
#define SCE_GS_PSMT4 (20)
|
||||||
|
#define SCE_GS_PSMT8H (27)
|
||||||
|
#define SCE_GS_PSMT4HL (36)
|
||||||
|
#define SCE_GS_PSMT4HH (44)
|
||||||
|
#define SCE_GS_PSMZ32 (48)
|
||||||
|
#define SCE_GS_PSMZ24 (49)
|
||||||
|
#define SCE_GS_PSMZ16 (50)
|
||||||
|
#define SCE_GS_PSMZ16S (58)
|
||||||
|
|
||||||
|
#define SCE_GS_ALPHA_NEVER (0)
|
||||||
|
#define SCE_GS_ALPHA_ALWAYS (1)
|
||||||
|
#define SCE_GS_ALPHA_LESS (2)
|
||||||
|
#define SCE_GS_ALPHA_LEQUAL (3)
|
||||||
|
#define SCE_GS_ALPHA_EQUAL (4)
|
||||||
|
#define SCE_GS_ALPHA_GEQUAL (5)
|
||||||
|
#define SCE_GS_ALPHA_GREATER (6)
|
||||||
|
#define SCE_GS_ALPHA_NOTEQUAL (7)
|
||||||
|
|
||||||
|
#define SCE_GS_AFAIL_KEEP (0)
|
||||||
|
#define SCE_GS_AFAIL_FB_ONLY (1)
|
||||||
|
#define SCE_GS_AFAIL_ZB_ONLY (2)
|
||||||
|
#define SCE_GS_AFAIL_RGB_ONLY (3)
|
||||||
|
|
||||||
|
#define SCE_GS_DEPTH_NEVER (0)
|
||||||
|
#define SCE_GS_DEPTH_ALWAYS (1)
|
||||||
|
#define SCE_GS_DEPTH_GEQUAL (2)
|
||||||
|
#define SCE_GS_DEPTH_GREATER (3)
|
||||||
|
|
||||||
|
#define SCE_GS_ALPHA_CS (0)
|
||||||
|
#define SCE_GS_ALPHA_CD (1)
|
||||||
|
#define SCE_GS_ALPHA_ZERO (2)
|
||||||
|
|
||||||
|
#define SCE_GS_ALPHA_AS (0)
|
||||||
|
#define SCE_GS_ALPHA_AD (1)
|
||||||
|
#define SCE_GS_ALPHA_FIX (2)
|
||||||
|
|
||||||
|
#define SCE_GIF_PACKED (0)
|
||||||
|
#define SCE_GIF_REGLIST (1)
|
||||||
|
#define SCE_GIF_IMAGE (2)
|
||||||
|
#define SCE_GIF_PACKED_AD (14)
|
||||||
|
|
||||||
|
#define SCE_GS_NOCLEAR (0)
|
||||||
|
#define SCE_GS_CLEAR (1)
|
||||||
|
|
||||||
|
#define SCE_GS_MODULATE (0)
|
||||||
|
#define SCE_GS_DECAL (1)
|
||||||
|
#define SCE_GS_HILIGHT (2)
|
||||||
|
#define SCE_GS_GHLIGHT2 (3)
|
||||||
|
|
||||||
|
#define SCE_GS_NEAREST (0)
|
||||||
|
#define SCE_GS_LINEAR (1)
|
||||||
|
#define SCE_GS_NEAREST_MIPMAP_NEAREST (2)
|
||||||
|
#define SCE_GS_NEAREST_MIPMAP_LINEAR (3)
|
||||||
|
#define SCE_GS_LINEAR_MIPMAP_NEAREST (4)
|
||||||
|
#define SCE_GS_LINEAR_MIPMAP_LINEAR (5)
|
||||||
|
|
||||||
|
#define SCE_GS_PRIM_POINT (0)
|
||||||
|
#define SCE_GS_PRIM_LINE (1)
|
||||||
|
#define SCE_GS_PRIM_LINESTRIP (2)
|
||||||
|
#define SCE_GS_PRIM_TRI (3)
|
||||||
|
#define SCE_GS_PRIM_TRISTRIP (4)
|
||||||
|
#define SCE_GS_PRIM_TRIFAN (5)
|
||||||
|
#define SCE_GS_PRIM_SPRITE (6)
|
||||||
|
|
||||||
|
#define SCE_GS_PRIM 0x00
|
||||||
|
#define SCE_GS_RGBAQ 0x01
|
||||||
|
#define SCE_GS_ST 0x02
|
||||||
|
#define SCE_GS_UV 0x03
|
||||||
|
#define SCE_GS_XYZF2 0x04
|
||||||
|
#define SCE_GS_XYZ2 0x05
|
||||||
|
#define SCE_GS_FOG 0x0a
|
||||||
|
#define SCE_GS_XYZF3 0x0c
|
||||||
|
#define SCE_GS_XYZ3 0x0d
|
||||||
|
#define SCE_GS_XYOFFSET_1 0x18
|
||||||
|
#define SCE_GS_XYOFFSET_2 0x19
|
||||||
|
#define SCE_GS_PRMODECONT 0x1a
|
||||||
|
|
||||||
|
#define SCE_GS_PRMODE 0x1b
|
||||||
|
#define SCE_GS_TEX0_1 0x06
|
||||||
|
#define SCE_GS_TEX0_2 0x07
|
||||||
|
#define SCE_GS_TEX1_1 0x14
|
||||||
|
#define SCE_GS_TEX1_2 0x15
|
||||||
|
#define SCE_GS_TEX2_1 0x16
|
||||||
|
#define SCE_GS_TEX2_2 0x17
|
||||||
|
#define SCE_GS_TEXCLUT 0x1c
|
||||||
|
#define SCE_GS_SCANMSK 0x22
|
||||||
|
#define SCE_GS_MIPTBP1_1 0x34
|
||||||
|
#define SCE_GS_MIPTBP1_2 0x35
|
||||||
|
#define SCE_GS_MIPTBP2_1 0x36
|
||||||
|
#define SCE_GS_MIPTBP2_2 0x37
|
||||||
|
#define SCE_GS_CLAMP_1 0x08
|
||||||
|
#define SCE_GS_CLAMP_2 0x09
|
||||||
|
#define SCE_GS_TEXA 0x3b
|
||||||
|
#define SCE_GS_FOGCOL 0x3d
|
||||||
|
#define SCE_GS_TEXFLUSH 0x3f
|
||||||
|
|
||||||
|
#define SCE_GS_SCISSOR_1 0x40
|
||||||
|
#define SCE_GS_SCISSOR_2 0x41
|
||||||
|
#define SCE_GS_ALPHA_1 0x42
|
||||||
|
#define SCE_GS_ALPHA_2 0x43
|
||||||
|
#define SCE_GS_DIMX 0x44
|
||||||
|
#define SCE_GS_DTHE 0x45
|
||||||
|
#define SCE_GS_COLCLAMP 0x46
|
||||||
|
#define SCE_GS_TEST_1 0x47
|
||||||
|
#define SCE_GS_TEST_2 0x48
|
||||||
|
#define SCE_GS_PABE 0x49
|
||||||
|
#define SCE_GS_FBA_1 0x4a
|
||||||
|
#define SCE_GS_FBA_2 0x4b
|
||||||
|
|
||||||
|
#define SCE_GS_FRAME_1 0x4c
|
||||||
|
#define SCE_GS_FRAME_2 0x4d
|
||||||
|
#define SCE_GS_ZBUF_1 0x4e
|
||||||
|
#define SCE_GS_ZBUF_2 0x4f
|
||||||
|
|
||||||
|
#define SCE_GS_BITBLTBUF 0x50
|
||||||
|
#define SCE_GS_TRXPOS 0x51
|
||||||
|
#define SCE_GS_TRXREG 0x52
|
||||||
|
#define SCE_GS_TRXDIR 0x53
|
||||||
|
#define SCE_GS_HWREG 0x54
|
||||||
|
|
||||||
|
#define SCE_GS_SIGNAL 0x60
|
||||||
|
#define SCE_GS_FINISH 0x61
|
||||||
|
#define SCE_GS_LABEL 0x62
|
||||||
|
#define SCE_GS_NOP 0x7f
|
||||||
|
|
||||||
|
#define SCE_GS_SET_TEX0_1 SCE_GS_SET_TEX0
|
||||||
|
#define SCE_GS_SET_TEX0_2 SCE_GS_SET_TEX0
|
||||||
|
#define SCE_GS_SET_TEX0(tbp, tbw, psm, tw, th, tcc, tfx, cbp, cpsm, csm, csa, cld) \
|
||||||
|
((u_long)(tbp) | ((u_long)(tbw) << 14) | \
|
||||||
|
((u_long)(psm) << 20) | ((u_long)(tw) << 26) | \
|
||||||
|
((u_long)(th) << 30) | ((u_long)(tcc) << 34) | \
|
||||||
|
((u_long)(tfx) << 35) | ((u_long)(cbp) << 37) | \
|
||||||
|
((u_long)(cpsm) << 51) | ((u_long)(csm) << 55) | \
|
||||||
|
((u_long)(csa) << 56) | ((u_long)(cld) << 61))
|
||||||
|
|
||||||
|
#define SCE_GIF_SET_TAG(nloop, eop, pre, prim, flg, nreg) \
|
||||||
|
((u_long)(nloop) | ((u_long)(eop)<<15) | ((u_long)(pre) << 46) | \
|
||||||
|
((u_long)(prim)<<47) | ((u_long)(flg)<<58) | ((u_long)(nreg)<<60))
|
||||||
|
|
||||||
|
#define SCE_GIF_CLEAR_TAG(tp) \
|
||||||
|
(*(u_long128 *)(tp) = (u_long128)0)
|
||||||
|
|
||||||
|
#define SCE_GS_SET_ALPHA_1 SCE_GS_SET_ALPHA
|
||||||
|
#define SCE_GS_SET_ALPHA_2 SCE_GS_SET_ALPHA
|
||||||
|
#define SCE_GS_SET_ALPHA(a, b, c, d, fix) \
|
||||||
|
((u_long)(a) | ((u_long)(b) << 2) | ((u_long)(c) << 4) | \
|
||||||
|
((u_long)(d) << 6) | ((u_long)(fix) << 32))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_TEST_1 SCE_GS_SET_TEST
|
||||||
|
#define SCE_GS_SET_TEST_2 SCE_GS_SET_TEST
|
||||||
|
#define SCE_GS_SET_TEST(ate, atst, aref, afail, date, datm, zte, ztst) \
|
||||||
|
((u_long)(ate) | ((u_long)(atst) << 1) | \
|
||||||
|
((u_long)(aref) << 4) | ((u_long)(afail) << 12) | \
|
||||||
|
((u_long)(date) << 14) | ((u_long)(datm) << 15) | \
|
||||||
|
((u_long)(zte) << 16) | ((u_long)(ztst) << 17))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_ZBUF_1 SCE_GS_SET_ZBUF
|
||||||
|
#define SCE_GS_SET_ZBUF_2 SCE_GS_SET_ZBUF
|
||||||
|
#define SCE_GS_SET_ZBUF(zbp, psm, zmsk) \
|
||||||
|
((u_long)(zbp) | ((u_long)(psm) << 24) | \
|
||||||
|
((u_long)(zmsk) << 32))
|
||||||
|
|
||||||
|
#define SCE_VIF1_SET_FLUSH(irq) \
|
||||||
|
(((u_int)0x11 << 24) | ((u_int)(irq) << 31))
|
||||||
|
|
||||||
|
#define SCE_VIF1_SET_DIRECT(count, irq) \
|
||||||
|
((u_int)(count) | ((u_int)(0x50) << 24) | ((u_int)(irq) << 31))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_BITBLTBUF(sbp, sbw, spsm, dbp, dbw, dpsm) \
|
||||||
|
((u_long)(sbp) | ((u_long)(sbw) << 16) | \
|
||||||
|
((u_long)(spsm) << 24) | ((u_long)(dbp) << 32) | \
|
||||||
|
((u_long)(dbw) << 48) | ((u_long)(dpsm) << 56))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_TRXDIR(xdr) ((u_long)(xdr))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_TRXPOS(ssax, ssay, dsax, dsay, dir) \
|
||||||
|
((u_long)(ssax) | ((u_long)(ssay) << 16) | \
|
||||||
|
((u_long)(dsax) << 32) | ((u_long)(dsay) << 48) | \
|
||||||
|
((u_long)(dir) << 59))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_TRXREG(rrw, rrh) \
|
||||||
|
((u_long)(rrw) | ((u_long)(rrh) << 32))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_UV(u, v) ((u_long)(u) | ((u_long)(v) << 16))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_XYZF3 SCE_GS_SET_XYZF
|
||||||
|
#define SCE_GS_SET_XYZF2 SCE_GS_SET_XYZF
|
||||||
|
#define SCE_GS_SET_XYZF(x, y, z, f) \
|
||||||
|
((u_long)(x) | ((u_long)(y) << 16) | ((u_long)(z) << 32) | \
|
||||||
|
((u_long)(f) << 56))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_FRAME_1 SCE_GS_SET_FRAME
|
||||||
|
#define SCE_GS_SET_FRAME_2 SCE_GS_SET_FRAME
|
||||||
|
#define SCE_GS_SET_FRAME(fbp, fbw, psm, fbmask) \
|
||||||
|
((u_long)(fbp) | ((u_long)(fbw) << 16) | \
|
||||||
|
((u_long)(psm) << 24) | ((u_long)(fbmask) << 32))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_TEX1_1 SCE_GS_SET_TEX1
|
||||||
|
#define SCE_GS_SET_TEX1_2 SCE_GS_SET_TEX1
|
||||||
|
#define SCE_GS_SET_TEX1(lcm, mxl, mmag, mmin, mtba, l, k) \
|
||||||
|
((u_long)(lcm) | ((u_long)(mxl) << 2) | \
|
||||||
|
((u_long)(mmag) << 5) | ((u_long)(mmin) << 6) | \
|
||||||
|
((u_long)(mtba) << 9) | ((u_long)(l) << 19) | \
|
||||||
|
((u_long)(k) << 32))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_TEX0_1 SCE_GS_SET_TEX0
|
||||||
|
#define SCE_GS_SET_TEX0_2 SCE_GS_SET_TEX0
|
||||||
|
#define SCE_GS_SET_TEX0(tbp, tbw, psm, tw, th, tcc, tfx, cbp, cpsm, csm, csa, cld) \
|
||||||
|
((u_long)(tbp) | ((u_long)(tbw) << 14) | \
|
||||||
|
((u_long)(psm) << 20) | ((u_long)(tw) << 26) | \
|
||||||
|
((u_long)(th) << 30) | ((u_long)(tcc) << 34) | \
|
||||||
|
((u_long)(tfx) << 35) | ((u_long)(cbp) << 37) | \
|
||||||
|
((u_long)(cpsm) << 51) | ((u_long)(csm) << 55) | \
|
||||||
|
((u_long)(csa) << 56) | ((u_long)(cld) << 61))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_XYOFFSET_1 SCE_GS_SET_XYOFFSET
|
||||||
|
#define SCE_GS_SET_XYOFFSET_2 SCE_GS_SET_XYOFFSET
|
||||||
|
#define SCE_GS_SET_XYOFFSET(ofx, ofy) \
|
||||||
|
((u_long)(ofx) | ((u_long)(ofy) << 32))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_CLAMP_1 SCE_GS_SET_CLAMP
|
||||||
|
#define SCE_GS_SET_CLAMP_2 SCE_GS_SET_CLAMP
|
||||||
|
#define SCE_GS_SET_CLAMP(wms, wmt, minu, maxu, minv, maxv) \
|
||||||
|
((u_long)(wms) | ((u_long)(wmt) << 2) | \
|
||||||
|
((u_long)(minu) << 4) | ((u_long)(maxu) << 14) | \
|
||||||
|
((u_long)(minv) << 24) | ((u_long)(maxv) << 34))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_SCISSOR_1 SCE_GS_SET_SCISSOR
|
||||||
|
#define SCE_GS_SET_SCISSOR_2 SCE_GS_SET_SCISSOR
|
||||||
|
#define SCE_GS_SET_SCISSOR(scax0, scax1, scay0, scay1) \
|
||||||
|
((u_long)(scax0) | ((u_long)(scax1) << 16) | \
|
||||||
|
((u_long)(scay0) << 32) | ((u_long)(scay1) << 48))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_RGBAQ(r, g, b, a, q) \
|
||||||
|
((u_long)(r) | ((u_long)(g) << 8) | ((u_long)(b) << 16) | \
|
||||||
|
((u_long)(a) << 24) | ((u_long)(q) << 32))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_PRIM(prim, iip, tme, fge, abe, aa1, fst, ctxt, fix) \
|
||||||
|
((u_long)(prim) | ((u_long)(iip) << 3) | ((u_long)(tme) << 4) | \
|
||||||
|
((u_long)(fge) << 5) | ((u_long)(abe) << 6) | ((u_long)(aa1) << 7) | \
|
||||||
|
((u_long)(fst) << 8) | ((u_long)(ctxt) << 9) | ((u_long)(fix) << 10))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_DTHE(dthe) ((u_long)(dthe))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_TEXA(ta0, aem, ta1) \
|
||||||
|
((u_long)(ta0) | ((u_long)(aem) << 15) | ((u_long)(ta1) << 32))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_TEXCLUT(cbw, cou, cov) \
|
||||||
|
((u_long)(cbw) | ((u_long)(cou) << 6) | ((u_long)(cov) << 12))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_FOG(f) ((u_long)(f) << 56)
|
||||||
|
|
||||||
|
#define SCE_GS_SET_FOGCOL(fcr, fcg, fcb) \
|
||||||
|
((u_long)(fcr) | ((u_long)(fcg) << 8) | ((u_long)(fcb) << 16))
|
||||||
|
|
||||||
|
#define V4_32 0x6c
|
||||||
|
|
||||||
|
#define SCE_VIF1_SET_STCYCL(wl, cl, irq) \
|
||||||
|
((u_int)(cl) | ((u_int)(wl) << 8) | \
|
||||||
|
((u_int)0x01 << 24) | ((u_int)(irq) << 31))
|
||||||
|
|
||||||
|
#define SCE_VIF1_SET_NOP(irq) ((u_int)(irq) << 31)
|
||||||
|
|
||||||
|
#define SCE_VIF1_SET_UNPACK(vuaddr, num, cmd, irq) \
|
||||||
|
((u_int)(vuaddr) | ((u_int)(num) << 16) | \
|
||||||
|
((u_int)(0x60 | (cmd)) << 24) | ((u_int)(irq) << 31))
|
||||||
|
|
||||||
|
#define SCE_GS_SET_XYZ3 SCE_GS_SET_XYZ
|
||||||
|
#define SCE_GS_SET_XYZ2 SCE_GS_SET_XYZ
|
||||||
|
#define SCE_GS_SET_XYZ(x, y, z) \
|
||||||
|
((u_long)(x) | ((u_long)(y) << 16) | ((u_long)(z) << 32))
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned long CLAMP:1;
|
||||||
|
unsigned long pad01:63;
|
||||||
|
} sceGsColclamp;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned long DTHE:1;
|
||||||
|
unsigned long pad01:63;
|
||||||
|
} sceGsDthe;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned long FBP:9;
|
||||||
|
unsigned long pad09:7;
|
||||||
|
unsigned long FBW:6;
|
||||||
|
unsigned long pad22:2;
|
||||||
|
unsigned long PSM:6;
|
||||||
|
unsigned long pad30:2;
|
||||||
|
unsigned long FBMSK:32;
|
||||||
|
} sceGsFrame;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned long AC:1;
|
||||||
|
unsigned long pad01:63;
|
||||||
|
} sceGsPrmodecont;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned long SCAX0:11;
|
||||||
|
unsigned long pad11:5;
|
||||||
|
unsigned long SCAX1:11;
|
||||||
|
unsigned long pad27:5;
|
||||||
|
unsigned long SCAY0:11;
|
||||||
|
unsigned long pad43:5;
|
||||||
|
unsigned long SCAY1:11;
|
||||||
|
unsigned long pad59:5;
|
||||||
|
} sceGsScissor;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned long ATE:1;
|
||||||
|
unsigned long ATST:3;
|
||||||
|
unsigned long AREF:8;
|
||||||
|
unsigned long AFAIL:2;
|
||||||
|
unsigned long DATE:1;
|
||||||
|
unsigned long DATM:1;
|
||||||
|
unsigned long ZTE:1;
|
||||||
|
unsigned long ZTST:2;
|
||||||
|
unsigned long pad19:45;
|
||||||
|
} sceGsTest;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned long OFX:16;
|
||||||
|
unsigned long pad16:16;
|
||||||
|
unsigned long OFY:16;
|
||||||
|
unsigned long pad48:16;
|
||||||
|
} sceGsXyoffset;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned long ZBP:9;
|
||||||
|
unsigned long pad09:15;
|
||||||
|
unsigned long PSM:4;
|
||||||
|
unsigned long pad28:4;
|
||||||
|
unsigned long ZMSK:1;
|
||||||
|
unsigned long pad33:31;
|
||||||
|
} sceGsZbuf;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned long PRIM:3;
|
||||||
|
unsigned long IIP:1;
|
||||||
|
unsigned long TME:1;
|
||||||
|
unsigned long FGE:1;
|
||||||
|
unsigned long ABE:1;
|
||||||
|
unsigned long AA1:1;
|
||||||
|
unsigned long FST:1;
|
||||||
|
unsigned long CTXT:1;
|
||||||
|
unsigned long FIX:1;
|
||||||
|
unsigned long pad11:53;
|
||||||
|
} sceGsPrim;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u_int R:8;
|
||||||
|
u_int G:8;
|
||||||
|
u_int B:8;
|
||||||
|
u_int A:8;
|
||||||
|
float Q;
|
||||||
|
} sceGsRgbaq;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned long X:16;
|
||||||
|
unsigned long Y:16;
|
||||||
|
unsigned long Z:32;
|
||||||
|
} sceGsXyz;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
long unsigned int TBP0 : 14;
|
||||||
|
long unsigned int TBW : 6;
|
||||||
|
long unsigned int PSM : 6;
|
||||||
|
long unsigned int TW : 4;
|
||||||
|
long unsigned int TH : 4;
|
||||||
|
long unsigned int TCC : 1;
|
||||||
|
long unsigned int TFX : 2;
|
||||||
|
long unsigned int CBP : 14;
|
||||||
|
long unsigned int CPSM : 4;
|
||||||
|
long unsigned int CSM : 1;
|
||||||
|
long unsigned int CSA : 5;
|
||||||
|
long unsigned int CLD : 3;
|
||||||
|
} sceGsTex0;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned long LCM:1;
|
||||||
|
unsigned long pad01:1;
|
||||||
|
unsigned long MXL:3;
|
||||||
|
unsigned long MMAG:1;
|
||||||
|
unsigned long MMIN:3;
|
||||||
|
unsigned long MTBA:1;
|
||||||
|
unsigned long pad10:9;
|
||||||
|
unsigned long L:2;
|
||||||
|
unsigned long pad21:11;
|
||||||
|
unsigned long K:12;
|
||||||
|
unsigned long pad44:20;
|
||||||
|
} sceGsTex1;
|
||||||
|
|
||||||
|
#define SCE_DMA_VIF0 0
|
||||||
|
#define SCE_DMA_VIF1 1
|
||||||
|
#define SCE_DMA_GIF 2
|
||||||
|
#define SCE_DMA_fromIPU 3
|
||||||
|
#define SCE_DMA_toIPU 4
|
||||||
|
#define SCE_DMA_SIF0 5
|
||||||
|
#define SCE_DMA_SIF1 6
|
||||||
|
#define SCE_DMA_SIF2 7
|
||||||
|
#define SCE_DMA_fromSPR 8
|
||||||
|
#define SCE_DMA_toSPR 9
|
||||||
|
|
||||||
|
#endif // EE_EESTRUCT_H
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef EE_KERNEL_H
|
||||||
|
#define EE_KERNEL_H
|
||||||
|
|
||||||
|
void EiInit();
|
||||||
|
void FlushCache(int);
|
||||||
|
|
||||||
|
#endif // EE_KERNEL_H
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef EE_REGISTERS_H
|
||||||
|
#define EE_REGISTERS_H
|
||||||
|
|
||||||
|
#define REG_RCNT0_COUNT (volatile u_int *)0x10000000
|
||||||
|
#define REG_RCNT0_MODE (volatile u_int *)0x10000010
|
||||||
|
#define REG_RCNT1_COUNT (volatile u_int *)0x10000800
|
||||||
|
#define REG_RCNT1_MODE (volatile u_int *)0x10000810
|
||||||
|
#endif // EE_REGISTERS_H
|
||||||
+5565
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* This header takes the place of the original ctype.h which, along with
|
||||||
|
* other gcc's header, is missing since we are using a barebone gcc environment.
|
||||||
|
*/
|
||||||
|
#ifndef GCC_CTYPE_H
|
||||||
|
#define GCC_CTYPE_H
|
||||||
|
|
||||||
|
#define __IMPORT
|
||||||
|
#define _CONST const
|
||||||
|
extern __IMPORT _CONST char _ctype_[];
|
||||||
|
#define _L 02
|
||||||
|
#define islower(c) ((_ctype_+1)[(unsigned)(c)]&_L)
|
||||||
|
#ifdef __GNUC__
|
||||||
|
# define toupper(c) \
|
||||||
|
__extension__ ({ int __x = (c); islower(__x) ? (__x - 'a' + 'A') : __x;})
|
||||||
|
# define tolower(c) \
|
||||||
|
__extension__ ({ int __x = (c); isupper(__x) ? (__x - 'A' + 'a') : __x;})
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // GCC_CTYPE_H
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* This header takes the place of the original index.h which, along with
|
||||||
|
* other gcc's header, is missing since we are using a barebone gcc environment.
|
||||||
|
*/
|
||||||
|
#ifndef GCC_INDEX_H
|
||||||
|
#define GCC_INDEX_H
|
||||||
|
|
||||||
|
char* index(const char *s, int c);
|
||||||
|
|
||||||
|
#endif // GCC_INDEX_H
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* This header takes the place of the original stdarg.h which, along with
|
||||||
|
* other gcc's header, is missing since we are using a barebone gcc environment.
|
||||||
|
*/
|
||||||
|
#ifndef GCC_STDARG_H
|
||||||
|
#define GCC_STDARG_H
|
||||||
|
|
||||||
|
#define _STDARG_H
|
||||||
|
|
||||||
|
#include "va-mips.h"
|
||||||
|
|
||||||
|
typedef __gnuc_va_list va_list;
|
||||||
|
|
||||||
|
#endif // GCC_STDARG_H
|
||||||
@@ -0,0 +1,277 @@
|
|||||||
|
/* ---------------------------------------- */
|
||||||
|
/* VARARGS for MIPS/GNU CC */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* */
|
||||||
|
/* ---------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
/* These macros implement varargs for GNU C--either traditional or ANSI. */
|
||||||
|
|
||||||
|
/* Define __gnuc_va_list. */
|
||||||
|
|
||||||
|
#ifndef __GNUC_VA_LIST
|
||||||
|
#define __GNUC_VA_LIST
|
||||||
|
#if defined (__mips_eabi) && ! defined (__mips_soft_float) && ! defined (__mips_single_float)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* Pointer to FP regs. */
|
||||||
|
char *__fp_regs;
|
||||||
|
/* Number of FP regs remaining. */
|
||||||
|
int __fp_left;
|
||||||
|
/* Pointer to GP regs followed by stack parameters. */
|
||||||
|
char *__gp_regs;
|
||||||
|
} __gnuc_va_list;
|
||||||
|
|
||||||
|
#else /* ! (defined (__mips_eabi) && ! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
|
||||||
|
|
||||||
|
typedef char * __gnuc_va_list;
|
||||||
|
|
||||||
|
#endif /* ! (defined (__mips_eabi) && ! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
|
||||||
|
#endif /* not __GNUC_VA_LIST */
|
||||||
|
|
||||||
|
/* If this is for internal libc use, don't define anything but
|
||||||
|
__gnuc_va_list. */
|
||||||
|
#if defined (_STDARG_H) || defined (_VARARGS_H)
|
||||||
|
|
||||||
|
#ifndef _VA_MIPS_H_ENUM
|
||||||
|
#define _VA_MIPS_H_ENUM
|
||||||
|
enum {
|
||||||
|
__no_type_class = -1,
|
||||||
|
__void_type_class,
|
||||||
|
__integer_type_class,
|
||||||
|
__char_type_class,
|
||||||
|
__enumeral_type_class,
|
||||||
|
__boolean_type_class,
|
||||||
|
__pointer_type_class,
|
||||||
|
__reference_type_class,
|
||||||
|
__offset_type_class,
|
||||||
|
__real_type_class,
|
||||||
|
__complex_type_class,
|
||||||
|
__function_type_class,
|
||||||
|
__method_type_class,
|
||||||
|
__record_type_class,
|
||||||
|
__union_type_class,
|
||||||
|
__array_type_class,
|
||||||
|
__string_type_class,
|
||||||
|
__set_type_class,
|
||||||
|
__file_type_class,
|
||||||
|
__lang_type_class
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* In GCC version 2, we want an ellipsis at the end of the declaration
|
||||||
|
of the argument list. GCC version 1 can't parse it. */
|
||||||
|
|
||||||
|
#if __GNUC__ > 1
|
||||||
|
#define __va_ellipsis ...
|
||||||
|
#else
|
||||||
|
#define __va_ellipsis
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __mips64
|
||||||
|
#define __va_rounded_size(__TYPE) \
|
||||||
|
(((sizeof (__TYPE) + 8 - 1) / 8) * 8)
|
||||||
|
#else
|
||||||
|
#define __va_rounded_size(__TYPE) \
|
||||||
|
(((sizeof (__TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __mips64
|
||||||
|
#define __va_reg_size 8
|
||||||
|
#else
|
||||||
|
#define __va_reg_size 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Get definitions for _MIPS_SIM_ABI64 etc. */
|
||||||
|
#ifdef _MIPS_SIM
|
||||||
|
#include <sgidefs.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _STDARG_H
|
||||||
|
#if defined (__mips_eabi)
|
||||||
|
#if ! defined (__mips_soft_float) && ! defined (__mips_single_float)
|
||||||
|
#ifdef __mips64
|
||||||
|
#define va_start(__AP, __LASTARG) \
|
||||||
|
(__AP.__gp_regs = ((char *) __builtin_next_arg (__LASTARG) \
|
||||||
|
- (__builtin_args_info (2) < 8 \
|
||||||
|
? (8 - __builtin_args_info (2)) * __va_reg_size \
|
||||||
|
: 0)), \
|
||||||
|
__AP.__fp_left = 8 - __builtin_args_info (3), \
|
||||||
|
__AP.__fp_regs = __AP.__gp_regs - __AP.__fp_left * __va_reg_size)
|
||||||
|
#else /* ! defined (__mips64) */
|
||||||
|
#define va_start(__AP, __LASTARG) \
|
||||||
|
(__AP.__gp_regs = ((char *) __builtin_next_arg (__LASTARG) \
|
||||||
|
- (__builtin_args_info (2) < 8 \
|
||||||
|
? (8 - __builtin_args_info (2)) * __va_reg_size \
|
||||||
|
: 0)), \
|
||||||
|
__AP.__fp_left = (8 - __builtin_args_info (3)) / 2, \
|
||||||
|
__AP.__fp_regs = __AP.__gp_regs - __AP.__fp_left * 8, \
|
||||||
|
__AP.__fp_regs = (char *) ((int) __AP.__fp_regs & -8))
|
||||||
|
#endif /* ! defined (__mips64) */
|
||||||
|
#else /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float) ) */
|
||||||
|
#define va_start(__AP, __LASTARG) \
|
||||||
|
(__AP = ((__gnuc_va_list) __builtin_next_arg (__LASTARG) \
|
||||||
|
- (__builtin_args_info (2) >= 8 ? 0 \
|
||||||
|
: (8 - __builtin_args_info (2)) * __va_reg_size)))
|
||||||
|
#endif /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float) ) */
|
||||||
|
#else /* ! defined (__mips_eabi) */
|
||||||
|
#define va_start(__AP, __LASTARG) \
|
||||||
|
(__AP = (__gnuc_va_list) __builtin_next_arg (__LASTARG))
|
||||||
|
#endif /* ! (defined (__mips_eabi) && ! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
|
||||||
|
#else /* ! _STDARG_H */
|
||||||
|
#define va_alist __builtin_va_alist
|
||||||
|
#ifdef __mips64
|
||||||
|
/* This assumes that `long long int' is always a 64 bit type. */
|
||||||
|
#define va_dcl long long int __builtin_va_alist; __va_ellipsis
|
||||||
|
#else
|
||||||
|
#define va_dcl int __builtin_va_alist; __va_ellipsis
|
||||||
|
#endif
|
||||||
|
#if defined (__mips_eabi)
|
||||||
|
#if ! defined (__mips_soft_float) && ! defined (__mips_single_float)
|
||||||
|
#ifdef __mips64
|
||||||
|
#define va_start(__AP) \
|
||||||
|
(__AP.__gp_regs = ((char *) __builtin_next_arg () \
|
||||||
|
- (__builtin_args_info (2) < 8 \
|
||||||
|
? (8 - __builtin_args_info (2)) * __va_reg_size \
|
||||||
|
: __va_reg_size)), \
|
||||||
|
__AP.__fp_left = 8 - __builtin_args_info (3), \
|
||||||
|
__AP.__fp_regs = __AP.__gp_regs - __AP.__fp_left * __va_reg_size)
|
||||||
|
#else /* ! defined (__mips64) */
|
||||||
|
#define va_start(__AP) \
|
||||||
|
(__AP.__gp_regs = ((char *) __builtin_next_arg () \
|
||||||
|
- (__builtin_args_info (2) < 8 \
|
||||||
|
? (8 - __builtin_args_info (2)) * __va_reg_size \
|
||||||
|
: __va_reg_size)), \
|
||||||
|
__AP.__fp_left = (8 - __builtin_args_info (3)) / 2, \
|
||||||
|
__AP.__fp_regs = __AP.__gp_regs - __AP.__fp_left * 8, \
|
||||||
|
__AP.__fp_regs = (char *) ((int) __AP.__fp_regs & -8))
|
||||||
|
#endif /* ! defined (__mips64) */
|
||||||
|
#else /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
|
||||||
|
#define va_start(__AP) \
|
||||||
|
(__AP = ((__gnuc_va_list) __builtin_next_arg () \
|
||||||
|
- (__builtin_args_info (2) >= 8 ? __va_reg_size \
|
||||||
|
: (8 - __builtin_args_info (2)) * __va_reg_size)))
|
||||||
|
#endif /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
|
||||||
|
/* Need alternate code for _MIPS_SIM_ABI64. */
|
||||||
|
#elif defined(_MIPS_SIM) && (_MIPS_SIM == _MIPS_SIM_ABI64 || _MIPS_SIM == _MIPS_SIM_NABI32)
|
||||||
|
#define va_start(__AP) \
|
||||||
|
(__AP = (__gnuc_va_list) __builtin_next_arg () \
|
||||||
|
+ (__builtin_args_info (2) >= 8 ? -8 : 0))
|
||||||
|
#else
|
||||||
|
#define va_start(__AP) __AP = (char *) &__builtin_va_alist
|
||||||
|
#endif
|
||||||
|
#endif /* ! _STDARG_H */
|
||||||
|
|
||||||
|
#ifndef va_end
|
||||||
|
void va_end (__gnuc_va_list); /* Defined in libgcc.a */
|
||||||
|
#endif
|
||||||
|
#define va_end(__AP) ((void)0)
|
||||||
|
|
||||||
|
#if defined (__mips_eabi)
|
||||||
|
|
||||||
|
#if ! defined (__mips_soft_float) && ! defined (__mips_single_float)
|
||||||
|
#ifdef __mips64
|
||||||
|
#define __va_next_addr(__AP, __type) \
|
||||||
|
((__builtin_classify_type (*(__type *) 0) == __real_type_class \
|
||||||
|
&& __AP.__fp_left > 0) \
|
||||||
|
? (--__AP.__fp_left, (__AP.__fp_regs += 8) - 8) \
|
||||||
|
: (__AP.__gp_regs += __va_reg_size) - __va_reg_size)
|
||||||
|
#else
|
||||||
|
#define __va_next_addr(__AP, __type) \
|
||||||
|
((__builtin_classify_type (*(__type *) 0) == __real_type_class \
|
||||||
|
&& __AP.__fp_left > 0) \
|
||||||
|
? (--__AP.__fp_left, (__AP.__fp_regs += 8) - 8) \
|
||||||
|
: (((__builtin_classify_type (* (__type *) 0) < __record_type_class \
|
||||||
|
&& __alignof__ (__type) > 4) \
|
||||||
|
? __AP.__gp_regs = (char *) (((int) __AP.__gp_regs + 8 - 1) & -8) \
|
||||||
|
: (char *) 0), \
|
||||||
|
(__builtin_classify_type (* (__type *) 0) >= __record_type_class \
|
||||||
|
? (__AP.__gp_regs += __va_reg_size) - __va_reg_size \
|
||||||
|
: ((__AP.__gp_regs += __va_rounded_size (__type)) \
|
||||||
|
- __va_rounded_size (__type)))))
|
||||||
|
#endif
|
||||||
|
#else /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
|
||||||
|
#ifdef __mips64
|
||||||
|
#define __va_next_addr(__AP, __type) \
|
||||||
|
((__AP += __va_reg_size) - __va_reg_size)
|
||||||
|
#else
|
||||||
|
#define __va_next_addr(__AP, __type) \
|
||||||
|
(((__builtin_classify_type (* (__type *) 0) < __record_type_class \
|
||||||
|
&& __alignof__ (__type) > 4) \
|
||||||
|
? __AP = (char *) (((__PTRDIFF_TYPE__) __AP + 8 - 1) & -8) \
|
||||||
|
: (char *) 0), \
|
||||||
|
(__builtin_classify_type (* (__type *) 0) >= __record_type_class \
|
||||||
|
? (__AP += __va_reg_size) - __va_reg_size \
|
||||||
|
: ((__AP += __va_rounded_size (__type)) \
|
||||||
|
- __va_rounded_size (__type))))
|
||||||
|
#endif
|
||||||
|
#endif /* ! (! defined (__mips_soft_float) && ! defined (__mips_single_float)) */
|
||||||
|
|
||||||
|
#ifdef __MIPSEB__
|
||||||
|
#define va_arg(__AP, __type) \
|
||||||
|
((__va_rounded_size (__type) <= __va_reg_size) \
|
||||||
|
? *(__type *) (void *) (__va_next_addr (__AP, __type) \
|
||||||
|
+ __va_reg_size \
|
||||||
|
- sizeof (__type)) \
|
||||||
|
: (__builtin_classify_type (*(__type *) 0) >= __record_type_class \
|
||||||
|
? **(__type **) (void *) (__va_next_addr (__AP, __type) \
|
||||||
|
+ __va_reg_size \
|
||||||
|
- sizeof (char *)) \
|
||||||
|
: *(__type *) (void *) __va_next_addr (__AP, __type)))
|
||||||
|
#else
|
||||||
|
#define va_arg(__AP, __type) \
|
||||||
|
((__va_rounded_size (__type) <= __va_reg_size) \
|
||||||
|
? *(__type *) (void *) __va_next_addr (__AP, __type) \
|
||||||
|
: (__builtin_classify_type (* (__type *) 0) >= __record_type_class \
|
||||||
|
? **(__type **) (void *) __va_next_addr (__AP, __type) \
|
||||||
|
: *(__type *) (void *) __va_next_addr (__AP, __type)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* ! defined (__mips_eabi) */
|
||||||
|
|
||||||
|
/* We cast to void * and then to TYPE * because this avoids
|
||||||
|
a warning about increasing the alignment requirement. */
|
||||||
|
/* The __mips64 cases are reversed from the 32 bit cases, because the standard
|
||||||
|
32 bit calling convention left-aligns all parameters smaller than a word,
|
||||||
|
whereas the __mips64 calling convention does not (and hence they are
|
||||||
|
right aligned). */
|
||||||
|
#ifdef __mips64
|
||||||
|
#ifdef __MIPSEB__
|
||||||
|
#define va_arg(__AP, __type) \
|
||||||
|
((__type *) (void *) (__AP = (char *) \
|
||||||
|
((((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8) \
|
||||||
|
+ __va_rounded_size (__type))))[-1]
|
||||||
|
#else
|
||||||
|
#define va_arg(__AP, __type) \
|
||||||
|
((__AP = (char *) ((((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8) \
|
||||||
|
+ __va_rounded_size (__type))), \
|
||||||
|
*(__type *) (void *) (__AP - __va_rounded_size (__type)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* not __mips64 */
|
||||||
|
|
||||||
|
#ifdef __MIPSEB__
|
||||||
|
/* For big-endian machines. */
|
||||||
|
#define va_arg(__AP, __type) \
|
||||||
|
((__AP = (char *) ((__alignof__ (__type) > 4 \
|
||||||
|
? ((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8 \
|
||||||
|
: ((__PTRDIFF_TYPE__)__AP + 4 - 1) & -4) \
|
||||||
|
+ __va_rounded_size (__type))), \
|
||||||
|
*(__type *) (void *) (__AP - __va_rounded_size (__type)))
|
||||||
|
#else
|
||||||
|
/* For little-endian machines. */
|
||||||
|
#define va_arg(__AP, __type) \
|
||||||
|
((__type *) (void *) (__AP = (char *) ((__alignof__(__type) > 4 \
|
||||||
|
? ((__PTRDIFF_TYPE__)__AP + 8 - 1) & -8 \
|
||||||
|
: ((__PTRDIFF_TYPE__)__AP + 4 - 1) & -4) \
|
||||||
|
+ __va_rounded_size(__type))))[-1]
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif /* ! defined (__mips_eabi) */
|
||||||
|
|
||||||
|
/* Copy __gnuc_va_list into another variable of this type. */
|
||||||
|
#define __va_copy(dest, src) (dest) = (src)
|
||||||
|
|
||||||
|
#endif /* defined (_STDARG_H) || defined (_VARARGS_H) */
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
// #ifndef GLOBALS_H
|
||||||
|
// #define GLOBALS_H
|
||||||
|
//
|
||||||
|
// #include "typedefs.h"
|
||||||
|
//
|
||||||
|
// extern DSP_M_SLCT_WRK dsp_ms;
|
||||||
|
// extern INGAME_WRK ingame_wrk;
|
||||||
|
// extern SYS_WRK sys_wrk;
|
||||||
|
//
|
||||||
|
// extern EVENT_WRK ev_wrk;
|
||||||
|
// extern PLYR_WRK plyr_wrk;
|
||||||
|
// extern TIME_WRK time_wrk;
|
||||||
|
// extern OPTION_WRK opt_wrk;
|
||||||
|
//
|
||||||
|
// extern int msn0_wait_timer;
|
||||||
|
// extern u_char mc_msn_flg;
|
||||||
|
//
|
||||||
|
// extern u_char event_stts[250];
|
||||||
|
// extern u_char plyr_vib_time;
|
||||||
|
// extern int disp3d_furn_req;
|
||||||
|
// extern int disp3d_room_req;
|
||||||
|
// extern u_char poss_item[200];
|
||||||
|
// extern int black_time;
|
||||||
|
// extern int load_file_id;
|
||||||
|
// extern u_short hp_down_deg;
|
||||||
|
// extern int init_load_id;
|
||||||
|
// extern sceVu0FMATRIX SgWSMtx;
|
||||||
|
// extern char is_newdata_albmside;
|
||||||
|
// extern u_short *key_now[32];
|
||||||
|
// extern int ms_load_id;
|
||||||
|
// extern int cmn_tex_load;
|
||||||
|
// extern int title_bgm_no;
|
||||||
|
//
|
||||||
|
// extern u_char save_pht_in_game;
|
||||||
|
// extern u_int mc_photo_num;
|
||||||
|
// extern DSP_MEM_ALBM dm_albm;
|
||||||
|
// extern MC_ALBUM_SAVE album_save_dat[2];
|
||||||
|
// extern PFILE_WRK pfile_wrk;
|
||||||
|
// extern MC_ALBUM_SAVE mc_album_save;
|
||||||
|
// extern STR_DAT ig_menu_str;
|
||||||
|
// extern TITLE_WRK title_wrk;
|
||||||
|
//
|
||||||
|
// extern OUTGAME_WRK outgame_wrk;
|
||||||
|
// extern u_int realtime_scene_flg;
|
||||||
|
// extern int opening_movie_type;
|
||||||
|
// extern u_int scene_bg_color;
|
||||||
|
// extern u_char mc_start_flg;
|
||||||
|
//
|
||||||
|
// extern BTL_MODE_WRK btl_wrk;
|
||||||
|
// extern int battle_scr_effct[0];
|
||||||
|
// extern STAGE_WRK stage_wrk[20];
|
||||||
|
// extern STAGE_DAT stage_dat[0];
|
||||||
|
//
|
||||||
|
// #endif /* GLOBALS_H */
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef INCLUDE_ASM_H
|
||||||
|
#define INCLUDE_ASM_H
|
||||||
|
|
||||||
|
#if !defined(SPLAT) && !defined(M2CTX) && !defined(PERMUTER)
|
||||||
|
#ifndef INCLUDE_ASM
|
||||||
|
#define INCLUDE_ASM(TYPE, FOLDER, NAME) \
|
||||||
|
__asm__( \
|
||||||
|
".section .text\n" \
|
||||||
|
" .set noat\n" \
|
||||||
|
" .set noreorder\n" \
|
||||||
|
" .include \"asm/nonmatchings/" FOLDER "/" #NAME ".s\"\n" \
|
||||||
|
" .set reorder\n" \
|
||||||
|
" .set at\n" \
|
||||||
|
" .globl " #NAME ".NON_MATCHING\n" \
|
||||||
|
" " #NAME ".NON_MATCHING" " = " #NAME "\n" \
|
||||||
|
)
|
||||||
|
#endif
|
||||||
|
#ifndef INCLUDE_RODATA
|
||||||
|
#define INCLUDE_RODATA(TYPE, FOLDER, NAME) \
|
||||||
|
__asm__( \
|
||||||
|
".section .rodata\n" \
|
||||||
|
" .include \"asm/nonmatchings/" FOLDER "/" #NAME ".s\"\n" \
|
||||||
|
".section .text" \
|
||||||
|
)
|
||||||
|
#endif
|
||||||
|
__asm__(".include \"include/macro.inc\"\n");
|
||||||
|
#else
|
||||||
|
#ifndef INCLUDE_ASM
|
||||||
|
#define INCLUDE_ASM(FOLDER, NAME)
|
||||||
|
#endif
|
||||||
|
#ifndef INCLUDE_RODATA
|
||||||
|
#define INCLUDE_RODATA(FOLDER, NAME)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
.macro glabel label
|
||||||
|
.global \label
|
||||||
|
.type \label, @function
|
||||||
|
\label:
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro dlabel label
|
||||||
|
.global \label
|
||||||
|
\label:
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro jlabel label
|
||||||
|
.global \label
|
||||||
|
\label:
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro llabel label
|
||||||
|
.local \label
|
||||||
|
\label:
|
||||||
|
.endm
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef SCE_DEVVIF0_H
|
||||||
|
#define SCE_DEVVIF0_H
|
||||||
|
|
||||||
|
void sceDevVif0Reset();
|
||||||
|
|
||||||
|
#endif // SCE_DEVVIF0_H
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef SCE_DEVVIF1_H
|
||||||
|
#define SCE_DEVVIF1_H
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u_int row[4];
|
||||||
|
u_int col[4];
|
||||||
|
u_int mask;
|
||||||
|
u_int code;
|
||||||
|
u_int stat;
|
||||||
|
u_short itop;
|
||||||
|
u_short itops;
|
||||||
|
u_short base;
|
||||||
|
u_short offset;
|
||||||
|
u_short top;
|
||||||
|
u_short tops;
|
||||||
|
u_short mark;
|
||||||
|
u_short num;
|
||||||
|
u_char error;
|
||||||
|
u_char cl;
|
||||||
|
u_char wl;
|
||||||
|
u_char cmod;
|
||||||
|
u_char pad;
|
||||||
|
} sceDevVif1Cnd;
|
||||||
|
|
||||||
|
void sceDevVif1Reset(void);
|
||||||
|
int sceDevVif1Pause(int mode);
|
||||||
|
int sceDevVif1Continue(void);
|
||||||
|
u_int sceDevVif1PutErr(int interrupt, int miss1, int miss2);
|
||||||
|
u_int sceDevVif1GetErr(void);
|
||||||
|
int sceDevVif1GetCnd(sceDevVif1Cnd *);
|
||||||
|
int sceDevVif1PutFifo(u_long128 *addr, int n);
|
||||||
|
int sceDevVif1GetFifo(u_long128 *addr, int n);
|
||||||
|
|
||||||
|
#endif // SCE_DEVVIF1_H
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef SCE_DEVVU0_H
|
||||||
|
#define SCE_DEVVU0_H
|
||||||
|
|
||||||
|
void sceDevVu0Reset();
|
||||||
|
|
||||||
|
#endif // SCE_DEVVU0_H
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
#ifndef SCE_LIBCDVD_H
|
||||||
|
#define SCE_LIBCDVD_H
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
#define STMNBLK 0
|
||||||
|
#define STMBLK 1
|
||||||
|
|
||||||
|
#define SCECdINIT 0
|
||||||
|
#define SCECdINoD 1
|
||||||
|
#define SCECdEXIT 5
|
||||||
|
|
||||||
|
#define SCECdCD 1
|
||||||
|
#define SCECdDVD 2
|
||||||
|
|
||||||
|
#define SCECdSpinMax 0
|
||||||
|
#define SCECdSpinNom 1
|
||||||
|
#define SCECdSpinStm 0
|
||||||
|
#define SCECdSpinDvdDL0 0
|
||||||
|
#define SCECdSpinX1 2
|
||||||
|
|
||||||
|
#define SCECdSecS2048 0
|
||||||
|
#define SCECdSecS2328 1
|
||||||
|
#define SCECdSecS2340 2
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u_char stat;
|
||||||
|
u_char second;
|
||||||
|
u_char minute;
|
||||||
|
u_char hour;
|
||||||
|
u_char pad;
|
||||||
|
u_char day;
|
||||||
|
u_char month;
|
||||||
|
u_char year;
|
||||||
|
} sceCdCLOCK;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u_char trycount;
|
||||||
|
u_char spindlctrl;
|
||||||
|
u_char datapattern;
|
||||||
|
u_char pad;
|
||||||
|
} sceCdRMode;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u_int lsn;
|
||||||
|
u_int size;
|
||||||
|
char name[16];
|
||||||
|
u_char date[8];
|
||||||
|
u_int flag;
|
||||||
|
} sceCdlFILE;
|
||||||
|
|
||||||
|
int sceCdInit(int init_mode);
|
||||||
|
int sceCdMmode(int media);
|
||||||
|
int sceCdReadClock(sceCdCLOCK *rtc);
|
||||||
|
int sceCdStRead(u_int size, u_int *buf, u_int mode, u_int *err);
|
||||||
|
int sceCdStStop();
|
||||||
|
|
||||||
|
int sceCdDiskReady(int mode);
|
||||||
|
int sceCdStInit(u_int bufmax, u_int bankmax, u_int iop_bufaddr);
|
||||||
|
int sceCdSearchFile(sceCdlFILE *fp,const char *name);
|
||||||
|
int sceCdStStart(u_int lbn, sceCdRMode *mode);
|
||||||
|
|
||||||
|
#endif // SCE_LIBCDVD_H
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
#ifndef SCE_LIBDMA_H
|
||||||
|
#define SCE_LIBDMA_H
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u_char sts;
|
||||||
|
u_char std;
|
||||||
|
u_char mfd;
|
||||||
|
u_char rcycle;
|
||||||
|
u_short express;
|
||||||
|
u_short notify;
|
||||||
|
u_short sqwc;
|
||||||
|
u_short tqwc;
|
||||||
|
void *rbadr;
|
||||||
|
u_int rbmsk;
|
||||||
|
} sceDmaEnv;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned DIR: 1;
|
||||||
|
unsigned p0 : 1;
|
||||||
|
unsigned MOD: 2;
|
||||||
|
unsigned ASP: 2;
|
||||||
|
unsigned TTE: 1;
|
||||||
|
unsigned TIE: 1;
|
||||||
|
unsigned STR: 1;
|
||||||
|
unsigned p1 : 7;
|
||||||
|
unsigned TAG:16;
|
||||||
|
} tD_CHCR;
|
||||||
|
|
||||||
|
typedef struct _sceDmaTag {
|
||||||
|
u_short qwc;
|
||||||
|
u_char mark;
|
||||||
|
u_char id;
|
||||||
|
struct _sceDmaTag *next;
|
||||||
|
u_int p[2];
|
||||||
|
} sceDmaTag __attribute__ ((aligned(16)));
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
tD_CHCR chcr; u_int p0[3];
|
||||||
|
volatile void *madr; u_int p1[3];
|
||||||
|
volatile u_int qwc; u_int p2[3];
|
||||||
|
volatile sceDmaTag *tadr; u_int p3[3];
|
||||||
|
volatile void *as0; u_int p4[3];
|
||||||
|
volatile void *as1; u_int p5[3];
|
||||||
|
u_int p6[4];
|
||||||
|
u_int p7[4];
|
||||||
|
volatile void *sadr; u_int p8[3];
|
||||||
|
} sceDmaChan;
|
||||||
|
|
||||||
|
#define settag(t,i,a,q) (t)->id=(i),(t)->next=(sceDmaTag *)(a),(t)->qwc=(u_short)(q)
|
||||||
|
|
||||||
|
inline static void *sceDmaAddRef(sceDmaTag **tag, int qwc, void *addr)
|
||||||
|
{
|
||||||
|
settag(*tag,0x30,addr,qwc);
|
||||||
|
(*tag)++;
|
||||||
|
return(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static void *sceDmaAddEnd(sceDmaTag **tag, int qwc, void *addr)
|
||||||
|
{
|
||||||
|
void *ret;
|
||||||
|
settag(*tag,0x70,addr,qwc);
|
||||||
|
ret = *tag+1;
|
||||||
|
(*tag) += qwc+1;
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sceDmaReset(int mode);
|
||||||
|
sceDmaEnv *sceDmaGetEnv(sceDmaEnv *env);
|
||||||
|
int sceDmaPutEnv(sceDmaEnv *env);
|
||||||
|
sceDmaChan *sceDmaGetChan(int id);
|
||||||
|
void sceDmaSend(sceDmaChan *d, void *tag);
|
||||||
|
int sceDmaSync(sceDmaChan *d, int mode, int timeout);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SCE_LIBDMA_H
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef SCE_LIBGIFPK_H
|
||||||
|
#define SCE_LIBGIFPK_H
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u_int *pCurrent;
|
||||||
|
u_long128 *pBase;
|
||||||
|
u_long128 *pDmaTag;
|
||||||
|
u_long *pGifTag;
|
||||||
|
} sceGifPacket;
|
||||||
|
|
||||||
|
u_long128 *sceGifPkTerminate(sceGifPacket *pPacket);
|
||||||
|
void sceGifPkCloseGifTag(sceGifPacket *pPacket);
|
||||||
|
void sceGifPkOpenGifTag(sceGifPacket *pPacket, u_long128 gifTag);
|
||||||
|
void sceGifPkAddGsAD(sceGifPacket *pPacket, u_int addr, u_long data);
|
||||||
|
void sceGifPkEnd(sceGifPacket *pPacket, u_int opt1, u_int opt2, u_int flag);
|
||||||
|
void sceGifPkReset(sceGifPacket *pPacket);
|
||||||
|
void sceGifPkInit(sceGifPacket *pPacket, u_long128 *pBase);
|
||||||
|
void sceGifPkReset(sceGifPacket *pPacket);
|
||||||
|
void sceGifPkCnt(sceGifPacket *pPacket, u_int opt1, u_int opt2, u_int flag);
|
||||||
|
u_int *sceGifPkReserve(sceGifPacket *pPacket, u_int count);
|
||||||
|
void sceGifPkRef(sceGifPacket *pPacket, u_long128 *pRef, u_int size, u_int opt1, u_int opt2, u_int flag);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SCE_LIBGIFPK_H
|
||||||
@@ -0,0 +1,191 @@
|
|||||||
|
#ifndef SCE_LIBGRAPH_H
|
||||||
|
#define SCE_LIBGRAPH_H
|
||||||
|
|
||||||
|
#include "ee/eestruct.h"
|
||||||
|
#include "ee/eeregs.h"
|
||||||
|
|
||||||
|
#define SCE_GS_NOINTERLACE 0
|
||||||
|
#define SCE_GS_INTERLACE 1
|
||||||
|
|
||||||
|
#define SCE_GS_FIELD 0
|
||||||
|
#define SCE_GS_FRAME 1
|
||||||
|
|
||||||
|
#define SCE_GS_NTSC 2
|
||||||
|
#define SCE_GS_PAL 3
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
long unsigned int NLOOP : 15;
|
||||||
|
long unsigned int EOP : 1;
|
||||||
|
long unsigned int pad16 : 16;
|
||||||
|
long unsigned int id : 14;
|
||||||
|
long unsigned int PRE : 1;
|
||||||
|
long unsigned int PRIM : 11;
|
||||||
|
long unsigned int FLG : 2;
|
||||||
|
long unsigned int NREG : 4;
|
||||||
|
long unsigned int REGS0 : 4;
|
||||||
|
long unsigned int REGS1 : 4;
|
||||||
|
long unsigned int REGS2 : 4;
|
||||||
|
long unsigned int REGS3 : 4;
|
||||||
|
long unsigned int REGS4 : 4;
|
||||||
|
long unsigned int REGS5 : 4;
|
||||||
|
long unsigned int REGS6 : 4;
|
||||||
|
long unsigned int REGS7 : 4;
|
||||||
|
long unsigned int REGS8 : 4;
|
||||||
|
long unsigned int REGS9 : 4;
|
||||||
|
long unsigned int REGS10 : 4;
|
||||||
|
long unsigned int REGS11 : 4;
|
||||||
|
long unsigned int REGS12 : 4;
|
||||||
|
long unsigned int REGS13 : 4;
|
||||||
|
long unsigned int REGS14 : 4;
|
||||||
|
long unsigned int REGS15 : 4;
|
||||||
|
} sceGifTag __attribute__((aligned(16)));
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
long unsigned int SBP : 14;
|
||||||
|
long unsigned int pad14 : 2;
|
||||||
|
long unsigned int SBW : 6;
|
||||||
|
long unsigned int pad22 : 2;
|
||||||
|
long unsigned int SPSM : 6;
|
||||||
|
long unsigned int pad30 : 2;
|
||||||
|
long unsigned int DBP : 14;
|
||||||
|
long unsigned int pad46 : 2;
|
||||||
|
long unsigned int DBW : 6;
|
||||||
|
long unsigned int pad54 : 2;
|
||||||
|
long unsigned int DPSM : 6;
|
||||||
|
long unsigned int pad62 : 2;
|
||||||
|
} sceGsBitbltbuf;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
long unsigned int SSAX : 11;
|
||||||
|
long unsigned int pad11 : 5;
|
||||||
|
long unsigned int SSAY : 11;
|
||||||
|
long unsigned int pad27 : 5;
|
||||||
|
long unsigned int DSAX : 11;
|
||||||
|
long unsigned int pad43 : 5;
|
||||||
|
long unsigned int DSAY : 11;
|
||||||
|
long unsigned int DIR : 2;
|
||||||
|
long unsigned int pad61 : 3;
|
||||||
|
} sceGsTrxpos;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
long unsigned int RRW : 12;
|
||||||
|
long unsigned int pad12 : 20;
|
||||||
|
long unsigned int RRH : 12;
|
||||||
|
long unsigned int pad44 : 20;
|
||||||
|
} sceGsTrxreg;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
long unsigned int pad00;
|
||||||
|
} sceGsFinish;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
long unsigned int XDR : 2;
|
||||||
|
long unsigned int pad02 : 62;
|
||||||
|
} sceGsTrxdir;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
sceGifTag giftag0;
|
||||||
|
sceGsBitbltbuf bitbltbuf;
|
||||||
|
long bitbltbufaddr;
|
||||||
|
sceGsTrxpos trxpos;
|
||||||
|
long trxposaddr;
|
||||||
|
sceGsTrxreg trxreg;
|
||||||
|
long trxregaddr;
|
||||||
|
sceGsTrxdir trxdir;
|
||||||
|
long trxdiraddr;
|
||||||
|
sceGifTag giftag1;
|
||||||
|
} sceGsLoadImage __attribute__((aligned(16)));
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u_int vifcode[4];
|
||||||
|
sceGifTag giftag;
|
||||||
|
sceGsBitbltbuf bitbltbuf;
|
||||||
|
long bitbltbufaddr;
|
||||||
|
sceGsTrxpos trxpos;
|
||||||
|
long trxposaddr;
|
||||||
|
sceGsTrxreg trxreg;
|
||||||
|
long trxregaddr;
|
||||||
|
sceGsFinish finish;
|
||||||
|
long finishaddr;
|
||||||
|
sceGsTrxdir trxdir;
|
||||||
|
long trxdiraddr;
|
||||||
|
} sceGsStoreImage __attribute__((aligned(16)));
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
sceGsFrame frame1;
|
||||||
|
u_long frame1addr;
|
||||||
|
sceGsZbuf zbuf1;
|
||||||
|
long zbuf1addr;
|
||||||
|
sceGsXyoffset xyoffset1;
|
||||||
|
long xyoffset1addr;
|
||||||
|
sceGsScissor scissor1;
|
||||||
|
long scissor1addr;
|
||||||
|
sceGsPrmodecont prmodecont;
|
||||||
|
long prmodecontaddr;
|
||||||
|
sceGsColclamp colclamp;
|
||||||
|
long colclampaddr;
|
||||||
|
sceGsDthe dthe;
|
||||||
|
long dtheaddr;
|
||||||
|
sceGsTest test1;
|
||||||
|
long test1addr;
|
||||||
|
} sceGsDrawEnv1 __attribute__((aligned(16)));
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
sceGsTest testa;
|
||||||
|
long testaaddr;
|
||||||
|
sceGsPrim prim;
|
||||||
|
long primaddr;
|
||||||
|
sceGsRgbaq rgbaq;
|
||||||
|
long rgbaqaddr;
|
||||||
|
sceGsXyz xyz2a;
|
||||||
|
long xyz2aaddr;
|
||||||
|
sceGsXyz xyz2b;
|
||||||
|
long xyz2baddr;
|
||||||
|
sceGsTest testb;
|
||||||
|
long testbaddr;
|
||||||
|
} sceGsClear __attribute__((aligned(16)));
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
tGS_PMODE pmode;
|
||||||
|
tGS_SMODE2 smode2;
|
||||||
|
tGS_DISPFB2 dispfb;
|
||||||
|
tGS_DISPLAY2 display;
|
||||||
|
tGS_BGCOLOR bgcolor;
|
||||||
|
} sceGsDispEnv;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
sceGsDispEnv disp[2];
|
||||||
|
sceGifTag giftag0;
|
||||||
|
sceGsDrawEnv1 draw0;
|
||||||
|
sceGsClear clear0;
|
||||||
|
sceGifTag giftag1;
|
||||||
|
sceGsDrawEnv1 draw1;
|
||||||
|
sceGsClear clear1;
|
||||||
|
} sceGsDBuff;
|
||||||
|
|
||||||
|
typedef struct { // 0x10
|
||||||
|
/* 0x0 */ short int sceGsInterMode;
|
||||||
|
/* 0x2 */ short int sceGsOutMode;
|
||||||
|
/* 0x4 */ short int sceGsFFMode;
|
||||||
|
/* 0x6 */ short int sceGsVersion;
|
||||||
|
/* 0x8 */ int (*sceGsVSCfunc)(int);
|
||||||
|
/* 0xc */ int sceGsVSCid;
|
||||||
|
} sceGsGParam __attribute__((aligned(16)));
|
||||||
|
|
||||||
|
void sceGsSetDefDBuff(sceGsDBuff *dp, short psm, short w, short h, short ztest, short zpsm, short clear);
|
||||||
|
void sceGsResetPath();
|
||||||
|
void sceGsResetGraph(short mode, short inter, short omode, short ffmode);
|
||||||
|
void sceGsPutDispEnv(sceGsDispEnv *disp);
|
||||||
|
int sceGsPutDrawEnv(sceGifTag *giftag);
|
||||||
|
void sceGsSetHalfOffset(sceGsDrawEnv1 *draw, short centerx, short centery, short halfoff);
|
||||||
|
int sceGsSyncV(int mode);
|
||||||
|
int sceGsSwapDBuff(sceGsDBuff *db, int id);
|
||||||
|
int sceGsSetDefStoreImage(sceGsStoreImage *sp, short sbp, short sbw, short spsm, short x, short y, short w, short h);
|
||||||
|
int sceGsExecStoreImage(sceGsStoreImage *sp, u_long128 *dstaddr);
|
||||||
|
int sceGsSyncPath(int mode, u_short timeout);
|
||||||
|
int sceGsSetDefLoadImage(sceGsLoadImage *lp, short dbp, short dbw, short dpsm, short x, short y, short w, short h);
|
||||||
|
int sceGsExecLoadImage(sceGsLoadImage *lp, u_long128 *srcaddr);
|
||||||
|
int sceGsSetDefDrawEnv(sceGsDrawEnv1 *draw, short psm, short w, short h, short ztest, short zpsm);
|
||||||
|
sceGsGParam *sceGsGetGParam();
|
||||||
|
|
||||||
|
#endif // SCE_LIBGRAPH_H
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef SCE_LIBIPU_H
|
||||||
|
#define SCE_LIBIPU_H
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
#define SCE_IPU_BCLR 0x00000000
|
||||||
|
#define sceIpuIsBusy() ((int)((int)DGET_IPU_CTRL() < 0))
|
||||||
|
#define sceIpuBCLR(bp) DPUT_IPU_CMD(SCE_IPU_BCLR | (bp))
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u_int d4madr;
|
||||||
|
u_int d4tadr;
|
||||||
|
u_int d4qwc;
|
||||||
|
u_int d4chcr;
|
||||||
|
u_int d3madr;
|
||||||
|
u_int d3qwc;
|
||||||
|
u_int d3chcr;
|
||||||
|
u_int ipubp;
|
||||||
|
u_int ipuctrl;
|
||||||
|
} sceIpuDmaEnv;
|
||||||
|
|
||||||
|
#endif // SCE_LIBIPU_H
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
#ifndef SCE_LIBMC_H
|
||||||
|
#define SCE_LIBMC_H
|
||||||
|
|
||||||
|
typedef int _iconVu0IVECTOR[4];
|
||||||
|
typedef float _iconVu0FVECTOR[4];
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned char Head[4];
|
||||||
|
unsigned short Reserv1;
|
||||||
|
unsigned short OffsLF;
|
||||||
|
unsigned int Reserv2;
|
||||||
|
unsigned int TransRate;
|
||||||
|
_iconVu0IVECTOR BgColor[4];
|
||||||
|
_iconVu0FVECTOR LightDir[3];
|
||||||
|
_iconVu0FVECTOR LightColor[3];
|
||||||
|
_iconVu0FVECTOR Ambient;
|
||||||
|
unsigned char TitleName[68];
|
||||||
|
unsigned char FnameView[64];
|
||||||
|
unsigned char FnameCopy[64];
|
||||||
|
unsigned char FnameDel[64];
|
||||||
|
unsigned char Reserve3[512];
|
||||||
|
} sceMcIconSys;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned char Resv2,Sec,Min,Hour;
|
||||||
|
unsigned char Day,Month;
|
||||||
|
unsigned short Year;
|
||||||
|
} sceMcStDateTime;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
sceMcStDateTime _Create;
|
||||||
|
sceMcStDateTime _Modify;
|
||||||
|
unsigned int FileSizeByte;
|
||||||
|
unsigned short AttrFile;
|
||||||
|
unsigned short Reserve1;
|
||||||
|
unsigned int Reserve2;
|
||||||
|
unsigned int PdaAplNo;
|
||||||
|
unsigned char EntryName[32];
|
||||||
|
} sceMcTblGetDir __attribute__((aligned (64)));
|
||||||
|
|
||||||
|
int sceMcInit();
|
||||||
|
int sceMcSync(int mode, int *cmd, int *result);
|
||||||
|
int sceMcDelete(int port, int slot, const char *name);
|
||||||
|
int sceMcFormat(int port, int slot);
|
||||||
|
int sceMcMkdir(int port, int slot, const char *name);
|
||||||
|
int sceMcGetInfo(int port, int slot, int *type, int *free, int *format);
|
||||||
|
int sceMcWrite(int fd, const void *buffer, int size);
|
||||||
|
int sceMcRead(int fd, void *buffer, int size);
|
||||||
|
int sceMcClose(int fd);
|
||||||
|
int sceMcOpen(int port, int slot, const char *name, int mode);
|
||||||
|
int sceMcGetDir(int port, int slot, const char *name, unsigned mode, int maxent, sceMcTblGetDir *table);
|
||||||
|
int sceMcGetInfo(int port, int slot, int *type, int *free, int *format);
|
||||||
|
|
||||||
|
#endif // SCE_LIBMC_H
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#ifndef SCE_LIBPAD_H
|
||||||
|
#define SCE_LIBPAD_H
|
||||||
|
|
||||||
|
#define scePadDmaBufferMax (16)
|
||||||
|
|
||||||
|
int scePadPortOpen(int port, int slot, void* addr);
|
||||||
|
int scePadInit(int mode);
|
||||||
|
int scePadGetState(int port, int slot);
|
||||||
|
int scePadRead(int port, int slot, unsigned char* rdata);
|
||||||
|
int scePadGetState(int port, int slot);
|
||||||
|
int scePadInfoMode(int port, int slot, int term, int offs);
|
||||||
|
int scePadSetMainMode(int port, int slot, int offs, int lock);
|
||||||
|
int scePadInfoAct(int port, int slot, int actno, int term);
|
||||||
|
int scePadSetActAlign(int port, int slot, const unsigned char* data);
|
||||||
|
int scePadGetReqState(int port, int slot);
|
||||||
|
int scePadInfoPressMode(int port, int slot);
|
||||||
|
int scePadEnterPressMode(int port, int slot);
|
||||||
|
int scePadSetActDirect(int port, int slot, const unsigned char* data);
|
||||||
|
|
||||||
|
#define scePadStateDiscon (0)
|
||||||
|
#define scePadStateFindPad (1)
|
||||||
|
#define scePadStateFindCTP1 (2)
|
||||||
|
#define scePadStateExecCmd (5)
|
||||||
|
#define scePadStateStable (6)
|
||||||
|
#define scePadStateError (7)
|
||||||
|
#define scePadStateClosed (99)
|
||||||
|
|
||||||
|
#define scePadReqStateComplete (0)
|
||||||
|
#define scePadReqStateFaild (1)
|
||||||
|
#define scePadReqStateFailed (1)
|
||||||
|
#define scePadReqStateBusy (2)
|
||||||
|
|
||||||
|
#define InfoModeCurID (1)
|
||||||
|
#define InfoModeCurExID (2)
|
||||||
|
#define InfoModeCurExOffs (3)
|
||||||
|
#define InfoModeIdTable (4)
|
||||||
|
|
||||||
|
#endif // SCE_LIBPAD_H
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
#ifndef SCE_LIBPC_H
|
||||||
|
#define SCE_LIBPC_H
|
||||||
|
|
||||||
|
static inline int scePcGetCounter0(void) {
|
||||||
|
register int ctr0;
|
||||||
|
__asm__ volatile ("mfpc %0, 0": "=r" (ctr0));
|
||||||
|
return ctr0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SCE_PC0_RESERVED (0 << 5)
|
||||||
|
#define SCE_PC0_CPU_CYCLE (1 << 5)
|
||||||
|
#define SCE_PC0_SINGLE_ISSUE (2 << 5)
|
||||||
|
#define SCE_PC0_BRANCH_ISSUED (3 << 5)
|
||||||
|
#define SCE_PC0_BTAC_MISS (4 << 5)
|
||||||
|
#define SCE_PC0_ITLB_MISS (5 << 5)
|
||||||
|
#define SCE_PC0_ICACHE_MISS (6 << 5)
|
||||||
|
#define SCE_PC0_DTLB_ACCESSED (7 << 5)
|
||||||
|
#define SCE_PC0_NONBLOCK_LOAD (8 << 5)
|
||||||
|
#define SCE_PC0_WBB_SINGLE_REQ (9 << 5)
|
||||||
|
#define SCE_PC0_WBB_BURST_REQ (10 << 5)
|
||||||
|
#define SCE_PC0_ADDR_BUS_BUSY (11 << 5)
|
||||||
|
#define SCE_PC0_INST_COMP (12 << 5)
|
||||||
|
#define SCE_PC0_NON_BDS_COMP (13 << 5)
|
||||||
|
#define SCE_PC0_COP2_COMP (14 << 5)
|
||||||
|
#define SCE_PC0_LOAD_COMP (15 << 5)
|
||||||
|
#define SCE_PC0_NO_EVENT (16 << 5)
|
||||||
|
|
||||||
|
#define SCE_PC1_LOW_BRANCH_ISSUED (0 << 15)
|
||||||
|
#define SCE_PC1_CPU_CYCLE (1 << 15)
|
||||||
|
#define SCE_PC1_DUAL_ISSUE (2 << 15)
|
||||||
|
#define SCE_PC1_BRANCH_MISS_PREDICT (3 << 15)
|
||||||
|
#define SCE_PC1_TLB_MISS (4 << 15)
|
||||||
|
#define SCE_PC1_DTLB_MISS (5 << 15)
|
||||||
|
#define SCE_PC1_DCACHE_MISS (6 << 15)
|
||||||
|
#define SCE_PC1_WBB_SINGLE_UNAVAIL (7 << 15)
|
||||||
|
#define SCE_PC1_WBB_BURST_UNAVAIL (8 << 15)
|
||||||
|
#define SCE_PC1_WBB_BURST_ALMOST (9 << 15)
|
||||||
|
#define SCE_PC1_WBB_BURST_FULL (10 << 15)
|
||||||
|
#define SCE_PC1_DATA_BUS_BUSY (11 << 15)
|
||||||
|
#define SCE_PC1_INST_COMP (12 << 15)
|
||||||
|
#define SCE_PC1_NON_BDS_COMP (13 << 15)
|
||||||
|
#define SCE_PC1_COP1_COMP (14 << 15)
|
||||||
|
#define SCE_PC1_STORE_COMP (15 << 15)
|
||||||
|
#define SCE_PC1_NO_EVENT (16 << 15)
|
||||||
|
|
||||||
|
#define SCE_PC_EXL0 (1 << 1)
|
||||||
|
#define SCE_PC_K0 (1 << 2)
|
||||||
|
#define SCE_PC_S0 (1 << 3)
|
||||||
|
#define SCE_PC_U0 (1 << 4)
|
||||||
|
#define SCE_PC_EVENT0 (31 << 5)
|
||||||
|
#define SCE_PC_EXL1 (1 << 11)
|
||||||
|
#define SCE_PC_K1 (1 << 12)
|
||||||
|
#define SCE_PC_S1 (1 << 13)
|
||||||
|
#define SCE_PC_U1 (1 << 14)
|
||||||
|
#define SCE_PC_EVENT1 (31 << 15)
|
||||||
|
#define SCE_PC_CTE (1 << 31)
|
||||||
|
|
||||||
|
void scePcStart(int control, int counter0, int counter1);
|
||||||
|
void scePcStop();
|
||||||
|
|
||||||
|
#endif // SCE_LIBPC_H
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef SCE_LIBSDR_H
|
||||||
|
#define SCE_LIBSDR_H
|
||||||
|
|
||||||
|
int sceSdRemoteInit();
|
||||||
|
int sceSdRemote(int arg, ...);
|
||||||
|
|
||||||
|
#endif // SCE_LIBSDR_H
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
#ifndef SCE_LIBVU0_H
|
||||||
|
#define SCE_LIBVU0_H
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
void sceVu0ScaleVectorXYZ(sceVu0FVECTOR v0, sceVu0FVECTOR v1, float s);
|
||||||
|
void sceVu0AddVector(sceVu0FVECTOR v0, sceVu0FVECTOR v1, sceVu0FVECTOR v2);
|
||||||
|
void sceVu0SubVector(sceVu0FVECTOR v0, sceVu0FVECTOR v1, sceVu0FVECTOR v2);
|
||||||
|
void sceVu0MulVector(sceVu0FVECTOR v0, sceVu0FVECTOR v1, sceVu0FVECTOR v2);
|
||||||
|
void sceVu0CopyVector(sceVu0FVECTOR v0, sceVu0FVECTOR v1);
|
||||||
|
void sceVu0Normalize(sceVu0FVECTOR v0, sceVu0FVECTOR v1);
|
||||||
|
float sceVu0InnerProduct(sceVu0FVECTOR v0, sceVu0FVECTOR v1);
|
||||||
|
void sceVu0OuterProduct(sceVu0FVECTOR v0, sceVu0FVECTOR v1, sceVu0FVECTOR v2);
|
||||||
|
void sceVu0UnitMatrix(sceVu0FMATRIX m);
|
||||||
|
void sceVu0TransposeMatrix(sceVu0FMATRIX m0, sceVu0FMATRIX m1);
|
||||||
|
void sceVu0CameraMatrix(sceVu0FMATRIX m, sceVu0FVECTOR p, sceVu0FVECTOR zd, sceVu0FVECTOR yd);
|
||||||
|
void sceVu0MulMatrix(sceVu0FMATRIX m0, sceVu0FMATRIX m1, sceVu0FMATRIX m2);
|
||||||
|
void sceVu0InversMatrix(sceVu0FMATRIX m0, sceVu0FMATRIX m1);
|
||||||
|
void sceVu0CopyMatrix(sceVu0FMATRIX m0, sceVu0FMATRIX m1);
|
||||||
|
void sceVu0RotMatrixZ(sceVu0FMATRIX m0, sceVu0FMATRIX m1, float rz);
|
||||||
|
void sceVu0ApplyMatrix(sceVu0FVECTOR v0, sceVu0FMATRIX m, sceVu0FVECTOR v1);
|
||||||
|
void sceVu0RotMatrixX(sceVu0FMATRIX m0, sceVu0FMATRIX m1, float rx);
|
||||||
|
void sceVu0RotMatrixY(sceVu0FMATRIX m0, sceVu0FMATRIX m1, float ry);
|
||||||
|
void sceVu0RotMatrix(sceVu0FMATRIX m0, sceVu0FMATRIX m1, sceVu0FVECTOR rot);
|
||||||
|
void sceVu0TransMatrix(sceVu0FMATRIX m0, sceVu0FMATRIX m1, sceVu0FVECTOR tv);
|
||||||
|
void sceVu0MulMatrix(sceVu0FMATRIX m0, sceVu0FMATRIX m1, sceVu0FMATRIX m2);
|
||||||
|
void sceVu0RotTransPers(sceVu0IVECTOR v0, sceVu0FMATRIX m0, sceVu0FVECTOR v1, int mode);
|
||||||
|
void sceVu0SubVector(sceVu0FVECTOR v0, sceVu0FVECTOR v1, sceVu0FVECTOR v2);
|
||||||
|
void sceVu0ScaleVector(sceVu0FVECTOR v0, sceVu0FVECTOR v1, float s);
|
||||||
|
void sceVu0RotTransPers(sceVu0IVECTOR v0, sceVu0FMATRIX m0, sceVu0FVECTOR v1, int mode);
|
||||||
|
void sceVu0RotTransPersN(sceVu0IVECTOR *v0, sceVu0FMATRIX m0, sceVu0FVECTOR *v1, int n, int mode);
|
||||||
|
void sceVu0DivVector(sceVu0FVECTOR v0, sceVu0FVECTOR v1, float q);
|
||||||
|
void sceVu0DivVectorXYZ(sceVu0FVECTOR v0, sceVu0FVECTOR v1, float q);
|
||||||
|
void sceVu0ClampVector(sceVu0FVECTOR v0, sceVu0FVECTOR v1, float min, float max);
|
||||||
|
void sceVu0InterVector(sceVu0FVECTOR v0, sceVu0FVECTOR v1, sceVu0FVECTOR v2, float r);
|
||||||
|
|
||||||
|
#endif // SCE_LIBVU0_H
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#ifndef SCE_MISC_DIEI_H
|
||||||
|
#define SCE_MISC_DIEI_H
|
||||||
|
|
||||||
|
int EIntr();
|
||||||
|
int DIntr();
|
||||||
|
|
||||||
|
#endif // SCE_MISC_DIEI_H
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#ifndef SCE_MPEG_AUDIODEC_H
|
||||||
|
#define SCE_MPEG_AUDIODEC_H
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
#define VOLUME_MASTER_MAX 0x3fff
|
||||||
|
|
||||||
|
#define AU_STATE_INIT 0
|
||||||
|
#define AU_STATE_PRESET 1
|
||||||
|
#define AU_STATE_PLAY 2
|
||||||
|
#define AU_STATE_PAUSE 3
|
||||||
|
|
||||||
|
#define AUTODMA_CH 0
|
||||||
|
|
||||||
|
#define UNIT_SIZE 1024
|
||||||
|
|
||||||
|
typedef struct { // 0x20
|
||||||
|
/* 0x00 */ char id[4];
|
||||||
|
/* 0x04 */ int size;
|
||||||
|
/* 0x08 */ int type;
|
||||||
|
/* 0x0c */ int rate;
|
||||||
|
/* 0x10 */ int ch;
|
||||||
|
/* 0x14 */ int interSize;
|
||||||
|
/* 0x18 */ int loopStart;
|
||||||
|
/* 0x1c */ int loopEnd;
|
||||||
|
} SpuStreamHeader;
|
||||||
|
|
||||||
|
typedef struct { // 0x8
|
||||||
|
/* 0x0 */ char id[4];
|
||||||
|
/* 0x4 */ int size;
|
||||||
|
} SpuStreamBody;
|
||||||
|
|
||||||
|
typedef struct { // 0x5c
|
||||||
|
/* 0x00 */ int state;
|
||||||
|
/* 0x04 */ SpuStreamHeader sshd;
|
||||||
|
/* 0x24 */ SpuStreamBody ssbd;
|
||||||
|
/* 0x2c */ int hdrCount;
|
||||||
|
/* 0x30 */ u_char *data;
|
||||||
|
/* 0x34 */ int put;
|
||||||
|
/* 0x38 */ int count;
|
||||||
|
/* 0x3c */ int size;
|
||||||
|
/* 0x40 */ int totalBytes;
|
||||||
|
/* 0x44 */ int iopBuff;
|
||||||
|
/* 0x48 */ int iopBuffSize;
|
||||||
|
/* 0x4c */ int iopLastPos;
|
||||||
|
/* 0x50 */ int iopPausePos;
|
||||||
|
/* 0x54 */ int totalBytesSent;
|
||||||
|
/* 0x58 */ int iopZero;
|
||||||
|
} AudioDec;
|
||||||
|
|
||||||
|
#endif // SCE_MPEG_AUDIODEC_H
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#ifndef SCE_MPEG_DEFS_H
|
||||||
|
#define SCE_MPEG_DEFS_H
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
#ifdef BUILD_EU_VERSION
|
||||||
|
#define MAX_WIDTH 640
|
||||||
|
#define MAX_HEIGHT 448
|
||||||
|
#else
|
||||||
|
#define MAX_WIDTH 640
|
||||||
|
#define MAX_HEIGHT 480
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// these are the same for both US and EU versions of the game
|
||||||
|
#define MPEG_DISP_WIDTH 640
|
||||||
|
#define MPEG_DISP_HEIGHT 480
|
||||||
|
|
||||||
|
#define bound(val, x) ((((val) + (x) - 1) / (x))*(x))
|
||||||
|
|
||||||
|
#define N_VOBUF 2
|
||||||
|
|
||||||
|
#define N_LDTAGS (MAX_WIDTH/16 * MAX_HEIGHT/16 * 6 + 10)
|
||||||
|
|
||||||
|
#define TS_NONE -1
|
||||||
|
|
||||||
|
static inline void *DmaAddr(void *val)
|
||||||
|
{
|
||||||
|
return (void*)((u_int)val & 0x0fffffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void *UncAddr(void *val)
|
||||||
|
{
|
||||||
|
return (void*)(((u_int)val & 0x0fffffff) | 0x20000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearGsMem(int r, int g, int b, int disp_width, int disp_height);
|
||||||
|
|
||||||
|
#endif // SCE_MPEG_DEFS_H
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef SCE_MPEG_DISP_H
|
||||||
|
#define SCE_MPEG_DISP_H
|
||||||
|
|
||||||
|
void clearGsMem(int r, int g, int b, int disp_width, int disp_height);
|
||||||
|
|
||||||
|
#endif // SCE_MPEG_DISP_H
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
#ifndef SCE_MPEG_LIBMPEG_H
|
||||||
|
#define SCE_MPEG_LIBMPEG_H
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
#include "sce/mpeg/defs.h"
|
||||||
|
|
||||||
|
#define SCE_MPEG_BUFFER_SIZE(w, h) ((w)*(h)*9/2 + 512 + 24*64 + 8192)
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
sceMpegCbError = 0,
|
||||||
|
sceMpegCbNodata = 1,
|
||||||
|
sceMpegCbStopDMA = 2,
|
||||||
|
sceMpegCbRestartDMA = 3,
|
||||||
|
sceMpegCbBackground = 4,
|
||||||
|
sceMpegCbTimeStamp = 5,
|
||||||
|
sceMpegCbStr = 6,
|
||||||
|
} sceMpegCbType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
sceMpegStrM2V = 0,
|
||||||
|
sceMpegStrIPU = 1,
|
||||||
|
sceMpegStrPCM = 2,
|
||||||
|
sceMpegStrADPCM = 3,
|
||||||
|
sceMpegStrDATA = 4,
|
||||||
|
} sceMpegStrType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int frameCount;
|
||||||
|
long int pts;
|
||||||
|
long int dts;
|
||||||
|
u_long flags;
|
||||||
|
long int pts2nd;
|
||||||
|
long int dts2nd;
|
||||||
|
u_long flags2nd;
|
||||||
|
void *sys;
|
||||||
|
} sceMpeg;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
sceMpegCbType type;
|
||||||
|
char *errMessage;
|
||||||
|
} sceMpegCbDataError;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
sceMpegCbType type;
|
||||||
|
long int pts;
|
||||||
|
long int dts;
|
||||||
|
} sceMpegCbDataTimeStamp;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
sceMpegCbType type;
|
||||||
|
u_char *header;
|
||||||
|
u_char *data;
|
||||||
|
u_int len;
|
||||||
|
long int pts;
|
||||||
|
long int dts;
|
||||||
|
} sceMpegCbDataStr;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
sceMpegCbType type;
|
||||||
|
sceMpegCbDataError error;
|
||||||
|
sceMpegCbDataTimeStamp ts;
|
||||||
|
sceMpegCbDataStr str;
|
||||||
|
} sceMpegCbData;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u_int pix[256];
|
||||||
|
} sceIpuRGB32;
|
||||||
|
|
||||||
|
typedef int (*sceMpegCallback)(sceMpeg *mp, sceMpegCbData *cbData, void *anyData);
|
||||||
|
|
||||||
|
int sceMpegReset(sceMpeg *mp);
|
||||||
|
int sceMpegCreate(sceMpeg *mp, u_char *work_area, int work_area_size);
|
||||||
|
int sceMpegDelete(sceMpeg *mp);
|
||||||
|
int sceMpegGetPicture(sceMpeg *mp, sceIpuRGB32 *rgb32, int mbcount);
|
||||||
|
int sceMpegIsEnd(sceMpeg *mp);
|
||||||
|
int sceMpegIsRefBuffEmpty(sceMpeg *mp);
|
||||||
|
void sceMpegSetDecodeMode(sceMpeg *mp, int ni, int np, int nb);
|
||||||
|
sceMpegCallback sceMpegAddCallback(sceMpeg *mp, sceMpegCbType type, sceMpegCallback callback, void *anyData);
|
||||||
|
sceMpegCallback sceMpegAddStrCallback(sceMpeg *mp, sceMpegStrType strType, int ch, sceMpegCallback callback, void *anyData);
|
||||||
|
|
||||||
|
#endif // SCE_MPEG_LIBMPEG_H
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef SCE_MPEG_READBUF_H
|
||||||
|
#define SCE_MPEG_READBUF_H
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
#define READ_UNIT_SIZE (64*1024)
|
||||||
|
#define N_READ_UNIT 5
|
||||||
|
#define READBUF_BUFF_SIZE (N_READ_UNIT * READ_UNIT_SIZE)
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{ // 0x5000c
|
||||||
|
/* 0x00000 */ u_char data[N_READ_UNIT * READ_UNIT_SIZE];
|
||||||
|
/* 0x50000 */ int put;
|
||||||
|
/* 0x50004 */ int count;
|
||||||
|
/* 0x50008 */ int size;
|
||||||
|
} ReadBuf;
|
||||||
|
|
||||||
|
#endif // SCE_MPEG_READBUF_H
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
#ifndef SCE_MPEG_VIBUF_H
|
||||||
|
#define SCE_MPEG_VIBUF_H
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
#include "sce/libipu.h"
|
||||||
|
|
||||||
|
#define DMA_ID_REFE 0
|
||||||
|
#define DMA_ID_NEXT 2
|
||||||
|
#define DMA_ID_REF 3
|
||||||
|
|
||||||
|
#define VIBUF_ELM_SIZE 2048
|
||||||
|
#define VIBUF_SIZE 256
|
||||||
|
#define VIBUF_TS_SIZE (VIBUF_SIZE*2)
|
||||||
|
|
||||||
|
#define TAG_ADDR(i) ((u_int)DmaAddr(f->tag + i))
|
||||||
|
#define DATA_ADDR(i) ((u_int)f->data + VIBUF_ELM_SIZE * (i))
|
||||||
|
#define WRAP_ADDR(addr) ((u_int)(f->data) + (((u_int)(addr) - (u_int)(f->data)) % (VIBUF_ELM_SIZE * f->n)))
|
||||||
|
#define IsInRegion(i,start,len,n) ( (0 <= (((i) + (n) - (start)) % (n))) && ((((i) + (n) - (start)) % (n)) < (len)))
|
||||||
|
|
||||||
|
extern inline int IsPtsInRegion(int tgt, int pos, int len, int size)
|
||||||
|
{
|
||||||
|
int tgt1 = (tgt + size - pos) % size;
|
||||||
|
return tgt1 < len;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct { // 0x18
|
||||||
|
/* 0x00 */ long int pts;
|
||||||
|
/* 0x08 */ long int dts;
|
||||||
|
/* 0x10 */ int pos;
|
||||||
|
/* 0x14 */ int len;
|
||||||
|
} TimeStamp;
|
||||||
|
|
||||||
|
typedef struct { // 0x60
|
||||||
|
/* 0x00 */ u_long128 *data;
|
||||||
|
/* 0x04 */ u_long128 *tag;
|
||||||
|
/* 0x08 */ int n;
|
||||||
|
/* 0x0c */ int dmaStart;
|
||||||
|
/* 0x10 */ int dmaN;
|
||||||
|
/* 0x14 */ int readBytes;
|
||||||
|
/* 0x18 */ int buffSize;
|
||||||
|
/* 0x1c */ sceIpuDmaEnv env;
|
||||||
|
/* 0x40 */ int sema;
|
||||||
|
/* 0x44 */ int isActive;
|
||||||
|
/* 0x48 */ long int totalBytes;
|
||||||
|
/* 0x50 */ TimeStamp *ts;
|
||||||
|
/* 0x54 */ int n_ts;
|
||||||
|
/* 0x58 */ int count_ts;
|
||||||
|
/* 0x5c */ int wt_ts;
|
||||||
|
} ViBuf;
|
||||||
|
|
||||||
|
#endif // SCE_MPEG_VIBUF_H
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef SCE_MPEG_VIDEODEC_H
|
||||||
|
#define SCE_MPEG_VIDEODEC_H
|
||||||
|
|
||||||
|
#include "sce/mpeg/libmpeg.h"
|
||||||
|
#include "sce/mpeg/vibuf.h"
|
||||||
|
|
||||||
|
#define VD_STATE_NORMAL 0
|
||||||
|
#define VD_STATE_ABORT 1
|
||||||
|
#define VD_STATE_FLUSH 2
|
||||||
|
#define VD_STATE_END 3
|
||||||
|
|
||||||
|
typedef struct { // 0xb8
|
||||||
|
/* 0x00 */ sceMpeg mpeg;
|
||||||
|
/* 0x48 */ ViBuf vibuf;
|
||||||
|
/* 0xa8 */ u_int state;
|
||||||
|
/* 0xac */ int sema;
|
||||||
|
/* 0xb0 */ int hid_endimage;
|
||||||
|
/* 0xb4 */ int hid_vblank;
|
||||||
|
} VideoDec;
|
||||||
|
|
||||||
|
#endif // SCE_MPEG_VIDEODEC_H
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef SCE_MPEG_VOBUF_H
|
||||||
|
#define SCE_MPEG_VOBUF_H
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
#include "sce/mpeg/libmpeg.h"
|
||||||
|
|
||||||
|
#define N_GSBUF 2
|
||||||
|
|
||||||
|
#define VOBUF_STATUS_ 0
|
||||||
|
#define VOBUF_STATUS_TOPDONE 1
|
||||||
|
#define VOBUF_STATUS_FULL 2
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u_char v[MAX_WIDTH * MAX_HEIGHT * 4];
|
||||||
|
} VoData;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int status;
|
||||||
|
int dummy[15];
|
||||||
|
u_int v[N_VOBUF][bound((N_LDTAGS+100)*4, 64)];
|
||||||
|
} VoTag;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
VoData *data;
|
||||||
|
VoTag *tag;
|
||||||
|
volatile int write;
|
||||||
|
volatile int count;
|
||||||
|
int size;
|
||||||
|
} VoBuf;
|
||||||
|
|
||||||
|
#endif // SCE_MPEG_VOBUF_H
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef SCE_SDMACRO_H
|
||||||
|
#define SCE_SDMACRO_H
|
||||||
|
|
||||||
|
#define SD_INIT_COLD 0
|
||||||
|
|
||||||
|
#define SD_TRANS_MODE_WRITE 0
|
||||||
|
#define SD_TRANS_MODE_READ 1
|
||||||
|
#define SD_TRANS_MODE_STOP 2
|
||||||
|
#define SD_TRANS_MODE_WRITE_FROM 3
|
||||||
|
|
||||||
|
#define SD_TRANS_BY_DMA (0x0<<3)
|
||||||
|
#define SD_TRANS_BY_IO (0x1<<3)
|
||||||
|
|
||||||
|
#define SD_BLOCK_ONESHOT (0<<4)
|
||||||
|
#define SD_BLOCK_LOOP (1<<4)
|
||||||
|
#define SD_BLOCK_HANDLER (1<<7)
|
||||||
|
|
||||||
|
#endif // SCE_SDMACRO_H
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef SCE_SDRCMD_H
|
||||||
|
#define SCE_SDRCMD_H
|
||||||
|
|
||||||
|
#define rSdInit 0x8000
|
||||||
|
#define rSdVoiceTrans 0x80d0
|
||||||
|
#define rSdBlockTrans 0x80e0
|
||||||
|
|
||||||
|
#endif // SCE_SDRCMD_H
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef SCE_SIF_H
|
||||||
|
#define SCE_SIF_H
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int data;
|
||||||
|
unsigned int addr;
|
||||||
|
unsigned int size;
|
||||||
|
unsigned int mode;
|
||||||
|
} sceSifDmaData;
|
||||||
|
|
||||||
|
int sceSifDmaStat(unsigned int id);
|
||||||
|
unsigned int sceSifSetDma(sceSifDmaData *sdd, int len);
|
||||||
|
|
||||||
|
#endif // SCE_SIF_H
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
#ifndef SCE_SIFDEV_H
|
||||||
|
#define SCE_SIFDEV_H
|
||||||
|
|
||||||
|
#define SCE_RDONLY 0x0001
|
||||||
|
#define SCE_WRONLY 0x0002
|
||||||
|
#define SCE_RDWR 0x0003
|
||||||
|
#define SCE_NBLOCK 0x0010
|
||||||
|
#define SCE_APPEND 0x0100
|
||||||
|
#define SCE_CREAT 0x0200
|
||||||
|
#define SCE_TRUNC 0x0400
|
||||||
|
#define SCE_EXCL 0x0800
|
||||||
|
#define SCE_NOBUF 0x4000
|
||||||
|
#define SCE_NOWAIT 0x8000
|
||||||
|
|
||||||
|
#define SCE_SEEK_SET 0
|
||||||
|
#define SCE_SEEK_CUR 1
|
||||||
|
#define SCE_SEEK_END 2
|
||||||
|
|
||||||
|
int sceOpen(const char *filename, int flag, ...);
|
||||||
|
int sceClose(int fd);
|
||||||
|
int sceRead(int fd, void *buf, int nbyte);
|
||||||
|
int sceWrite(int fd, const void *buf, int nbyte);
|
||||||
|
int sceLseek(int fd, int offset, int where);
|
||||||
|
|
||||||
|
int sceFsReset();
|
||||||
|
|
||||||
|
int sceSifInitIopHeap();
|
||||||
|
int sceSifFreeIopHeap(void *);
|
||||||
|
void *sceSifAllocIopHeap(unsigned int);
|
||||||
|
int sceSifRebootIop(const char *img);
|
||||||
|
int sceSifSyncIop();
|
||||||
|
int sceSifLoadModule(const char *filename, int args, const char *argp);
|
||||||
|
|
||||||
|
#endif // SCE_SIFDEV_H
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#ifndef SCE_SIFRPC_H
|
||||||
|
#define SCE_SIFRPC_H
|
||||||
|
|
||||||
|
typedef struct _sif_rpc_data {
|
||||||
|
void *paddr;
|
||||||
|
unsigned int pid;
|
||||||
|
int tid;
|
||||||
|
unsigned int mode;
|
||||||
|
} sceSifRpcData;
|
||||||
|
|
||||||
|
typedef void (* sceSifEndFunc)(void *);
|
||||||
|
|
||||||
|
typedef struct _sif_client_data {
|
||||||
|
struct _sif_rpc_data rpcd;
|
||||||
|
unsigned int command;
|
||||||
|
void *buff;
|
||||||
|
void *gp;
|
||||||
|
sceSifEndFunc func;
|
||||||
|
void *para;
|
||||||
|
struct _sif_serve_data *serve;
|
||||||
|
} sceSifClientData;
|
||||||
|
|
||||||
|
void sceSifInitRpc(unsigned int mode);
|
||||||
|
int sceSifBindRpc(sceSifClientData *client, unsigned int rpc_number, unsigned int mode);
|
||||||
|
int sceSifCheckStatRpc(sceSifRpcData *cd);
|
||||||
|
int sceSifCallRpc(sceSifClientData *client, unsigned int rpc_number, unsigned int mode, void * send, int ssize, void * receive, int rsize, sceSifEndFunc end_function, void *end_param);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // SCE_SIFRPC_H
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
#ifndef STRUCTS_H
|
||||||
|
#define STRUCTS_H
|
||||||
|
|
||||||
|
#include "typedefs.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{ // 0x8
|
||||||
|
/* 0x0 */ u_char mode;
|
||||||
|
/* 0x1 */ u_char csr[6];
|
||||||
|
/* 0x7 */ u_char yn_mode;
|
||||||
|
} CAMERA_MENU_WRK;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{ // 0x4
|
||||||
|
/* 0x0 */ short int p;
|
||||||
|
/* 0x2 */ short int n;
|
||||||
|
} CSR_ADD;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{ // 0x20
|
||||||
|
/* 0x00 */ sceVu0FVECTOR stq;
|
||||||
|
/* 0x10 */ sceVu0FVECTOR vtw;
|
||||||
|
} SCRDEF;
|
||||||
|
|
||||||
|
#endif // STRUCTS_H
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
#ifndef TYPEDEFS_H
|
||||||
|
#define TYPEDEFS_H
|
||||||
|
|
||||||
|
typedef long s_long;
|
||||||
|
typedef short s_short;
|
||||||
|
typedef char s_char;
|
||||||
|
typedef int s_int;
|
||||||
|
typedef int s_long128 __attribute__ ((mode (TI)));
|
||||||
|
|
||||||
|
typedef unsigned long u_long;
|
||||||
|
typedef unsigned short u_short;
|
||||||
|
typedef unsigned char u_char;
|
||||||
|
typedef unsigned int u_int;
|
||||||
|
typedef unsigned int u_long128 __attribute__ ((mode (TI)));
|
||||||
|
|
||||||
|
typedef long int dword[2] __attribute__ ((aligned(16)));;
|
||||||
|
typedef int qword[4] __attribute__ ((aligned(16)));
|
||||||
|
typedef int sceVu0IVECTOR[4] __attribute__((aligned (16)));
|
||||||
|
typedef float sceVu0FVECTOR[4] __attribute__((aligned (16)));
|
||||||
|
typedef float sceVu0FMATRIX[4][4] __attribute__((aligned (16)));
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
int ui32;
|
||||||
|
float fl32;
|
||||||
|
} U32DATA;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
u_long128 ul128;
|
||||||
|
u_long ul64[2];
|
||||||
|
u_int ui32[4];
|
||||||
|
float fl32[4];
|
||||||
|
u_short us16[8];
|
||||||
|
u_char uc8[16];
|
||||||
|
sceVu0FVECTOR fv;
|
||||||
|
sceVu0IVECTOR iv;
|
||||||
|
} Q_WORDDATA;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
u_char *pu8;
|
||||||
|
u_short *pu16;
|
||||||
|
u_int *pu32;
|
||||||
|
u_long *pu64;
|
||||||
|
s_char *ps8;
|
||||||
|
s_short *ps16;
|
||||||
|
int *ps32;
|
||||||
|
s_long *ps64;
|
||||||
|
long int wrk;
|
||||||
|
} P_INT;
|
||||||
|
|
||||||
|
#endif /* TYPEDEFS_H */
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
ninja
|
||||||
|
ninja_syntax
|
||||||
|
rabbitizer==1.13.0
|
||||||
|
spimdisasm==1.35.0
|
||||||
|
splat64[mips]==0.34.1
|
||||||
|
pydantic>=2.0,<3.0
|
||||||
|
pyelftools
|
||||||
|
numpy
|
||||||
|
tqdm
|
||||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
+265
@@ -0,0 +1,265 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# SPDX-FileCopyrightText: Copyright 2025 karas84 (https://github.com/karas84)
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
#
|
||||||
|
# This script inserts source line debug information (.loc directives) into assembly files
|
||||||
|
# using data extracted from a JSON "stdump" file generated by the ccc tool (version 2.1),
|
||||||
|
# available at https://github.com/chaoticgd/ccc.
|
||||||
|
#
|
||||||
|
# Original concept by Mc-muffin (https://github.com/Mc-muffin).
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import re
|
||||||
|
import io
|
||||||
|
import sys
|
||||||
|
import json
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
from typing import Callable, Protocol, cast
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
class STDUMPJson:
|
||||||
|
def __init__(self, json_path: Path):
|
||||||
|
self._json = json.loads(json_path.read_text())
|
||||||
|
self._line_cache = self._build_line_cache()
|
||||||
|
self._validate_sub_source_files()
|
||||||
|
|
||||||
|
def _build_line_cache(self):
|
||||||
|
line_cache: dict[int, int] = {}
|
||||||
|
functions = self._json["functions"]
|
||||||
|
|
||||||
|
for fun in functions:
|
||||||
|
if "line_numbers" not in fun:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for addr, num in fun["line_numbers"]:
|
||||||
|
# there may be more lines for the same address. Ghidra seems to
|
||||||
|
# keep the last one, so that's what we are also doing
|
||||||
|
line_cache[addr] = num
|
||||||
|
|
||||||
|
return line_cache
|
||||||
|
|
||||||
|
def _validate_sub_source_files(self):
|
||||||
|
functions = self._json["functions"]
|
||||||
|
for fun in functions:
|
||||||
|
if (line_numbers := fun.get("line_numbers")) is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if (sub_source_files := fun.get("sub_source_files")) is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
line_numbers = cast(list[tuple[int, int]], line_numbers)
|
||||||
|
sub_source_files = cast(list[tuple[int, str]], sub_source_files)
|
||||||
|
|
||||||
|
# # some functions may have "unterminated" inlines, but they usually have just one line number
|
||||||
|
# if len(sub_source_files) % 2 != 0: # and len(line_numbers) != 1:
|
||||||
|
# print(fun["name"], len(line_numbers))
|
||||||
|
|
||||||
|
# for addr, source in sub_source_files:
|
||||||
|
|
||||||
|
def find_function(self, name: str):
|
||||||
|
functions = self._json["functions"]
|
||||||
|
fun = next((f for f in functions if f["name"] == name), None)
|
||||||
|
return fun
|
||||||
|
|
||||||
|
def get_line(self, addr: int):
|
||||||
|
return self._line_cache.get(addr)
|
||||||
|
|
||||||
|
|
||||||
|
def make_range_checker(lst: list[tuple[int, str]], delimiter: str) -> Callable[[int], bool]:
|
||||||
|
"""
|
||||||
|
Given a sorted list of (number, label) where number increases,
|
||||||
|
build a checker that returns True if x is in a valid interval.
|
||||||
|
|
||||||
|
Interpretation:
|
||||||
|
- Each entry (n, label) marks the interval starting at n and going
|
||||||
|
up to the next entry's n (exclusive). The last entry's interval
|
||||||
|
goes to +inf.
|
||||||
|
- An interval starting at n is valid iff label == delimiter.
|
||||||
|
- If the first entry's label != delimiter, everything before the first n is valid.
|
||||||
|
"""
|
||||||
|
if not lst:
|
||||||
|
# no markers -> everything valid
|
||||||
|
return lambda x: True
|
||||||
|
|
||||||
|
# ensure sorted by number
|
||||||
|
lst_sorted = sorted(lst, key=lambda t: t[0])
|
||||||
|
assert lst == lst_sorted
|
||||||
|
|
||||||
|
nums = [t[0] for t in lst_sorted]
|
||||||
|
labels = [t[1] for t in lst_sorted]
|
||||||
|
|
||||||
|
# Precompute intervals as (start, end_exclusive, is_valid)
|
||||||
|
intervals: list[tuple[int, int | None, bool]] = []
|
||||||
|
n_items = len(nums)
|
||||||
|
|
||||||
|
for i in range(n_items):
|
||||||
|
start = nums[i]
|
||||||
|
end_exclusive: int | None
|
||||||
|
|
||||||
|
if i + 1 < n_items:
|
||||||
|
end_exclusive = nums[i + 1]
|
||||||
|
else:
|
||||||
|
end_exclusive = None # means to +inf
|
||||||
|
|
||||||
|
is_valid = labels[i] == delimiter
|
||||||
|
intervals.append((start, end_exclusive, is_valid))
|
||||||
|
|
||||||
|
first_before_is_valid = labels[0] != delimiter
|
||||||
|
|
||||||
|
def is_valid_fn(x: int) -> bool:
|
||||||
|
# before first number
|
||||||
|
if x < nums[0]:
|
||||||
|
return first_before_is_valid
|
||||||
|
|
||||||
|
# find the interval that contains x
|
||||||
|
for start, end_exclusive, valid_flag in intervals:
|
||||||
|
if end_exclusive is None:
|
||||||
|
if x >= start:
|
||||||
|
return valid_flag
|
||||||
|
else:
|
||||||
|
if start <= x < end_exclusive:
|
||||||
|
return valid_flag
|
||||||
|
|
||||||
|
# fallback (shouldn't happen)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return is_valid_fn
|
||||||
|
|
||||||
|
|
||||||
|
def is_always_valid_fn(addr: int):
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def add_lines_to_asm(
|
||||||
|
asm_path: Path,
|
||||||
|
stdump_json_path: Path,
|
||||||
|
fun_start_offset: int,
|
||||||
|
keep_original_numbers: bool,
|
||||||
|
asm_out: Path | None,
|
||||||
|
):
|
||||||
|
stdump_json = STDUMPJson(stdump_json_path)
|
||||||
|
|
||||||
|
function_name = asm_path.stem
|
||||||
|
|
||||||
|
if (fun := stdump_json.find_function(function_name)) is None:
|
||||||
|
raise RuntimeError(f"Cannot find function '{function_name}' in ccc's JSON")
|
||||||
|
|
||||||
|
sub_source_files = fun.get("sub_source_files")
|
||||||
|
# print(len(sub_source_files) if sub_source_files is not None else None)
|
||||||
|
|
||||||
|
asm_lines = asm_path.read_text().splitlines()
|
||||||
|
re_instr = re.compile(r"^\s*\/\* [A-Z0-9]+ ([A-Z0-9]{8}) [A-Z0-9]{8} \*\/ .*$")
|
||||||
|
line_dict: dict[int, int] = {}
|
||||||
|
|
||||||
|
relative_path: str = fun["relative_path"]
|
||||||
|
non_func_addrs: list[int] = []
|
||||||
|
|
||||||
|
if sub_source_files:
|
||||||
|
checker = make_range_checker(sub_source_files, relative_path)
|
||||||
|
else:
|
||||||
|
checker = is_always_valid_fn
|
||||||
|
|
||||||
|
start_line_num: int = sys.maxsize
|
||||||
|
|
||||||
|
for line in asm_lines:
|
||||||
|
if m := re_instr.match(line):
|
||||||
|
instr_addr = int(m.group(1), 16)
|
||||||
|
line_num = stdump_json.get_line(instr_addr)
|
||||||
|
|
||||||
|
if line_num:
|
||||||
|
line_dict[instr_addr] = line_num
|
||||||
|
|
||||||
|
if not checker(instr_addr):
|
||||||
|
non_func_addrs.append(instr_addr)
|
||||||
|
elif line_num:
|
||||||
|
start_line_num = min(start_line_num, line_num)
|
||||||
|
|
||||||
|
if start_line_num == sys.maxsize:
|
||||||
|
start_line_num = 1
|
||||||
|
|
||||||
|
min_line_num = 0 if keep_original_numbers else start_line_num - 1
|
||||||
|
|
||||||
|
new_asm_lines: list[str] = []
|
||||||
|
asm_n: int = 0
|
||||||
|
|
||||||
|
for line in asm_lines:
|
||||||
|
if m := re_instr.match(line):
|
||||||
|
asm_n += 1
|
||||||
|
|
||||||
|
instr_addr = int(m.group(1), 16)
|
||||||
|
line_num = line_dict.get(instr_addr)
|
||||||
|
|
||||||
|
if line_num is not None and instr_addr in non_func_addrs:
|
||||||
|
new_asm_lines.append(f" .loc 1 {line_num} # inline")
|
||||||
|
new_asm_lines.append(line)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if asm_n == 1 and line_num is None:
|
||||||
|
# sometimes we don't have a number for the first line of assembly,
|
||||||
|
# so we reuse the first known line among the ones we have
|
||||||
|
line_num = start_line_num
|
||||||
|
|
||||||
|
if line_num is not None:
|
||||||
|
new_line_num = (line_num - min_line_num) + fun_start_offset
|
||||||
|
new_asm_lines.append(f" .loc 1 {new_line_num} ")
|
||||||
|
|
||||||
|
new_asm_lines.append(line)
|
||||||
|
|
||||||
|
stream = io.StringIO()
|
||||||
|
stream.write(""".section .debug
|
||||||
|
.previous
|
||||||
|
.text
|
||||||
|
.file 1 "source.c"
|
||||||
|
|
||||||
|
.set noat
|
||||||
|
.set noreorder
|
||||||
|
|
||||||
|
""")
|
||||||
|
stream.write("\n".join(new_asm_lines))
|
||||||
|
|
||||||
|
if asm_out is not None:
|
||||||
|
asm_out.write_text(stream.getvalue())
|
||||||
|
else:
|
||||||
|
print(stream.getvalue())
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
class ArgProtocol(Protocol):
|
||||||
|
asm_path: Path
|
||||||
|
stdump_json_path: Path
|
||||||
|
asm_out: Path | None
|
||||||
|
offset: int
|
||||||
|
keep_original: bool
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="Add line debug info to assembly files")
|
||||||
|
parser.add_argument("--asm-path", required=True, type=Path, help="Path to the assembly file to add lines to")
|
||||||
|
parser.add_argument("--stdump-json-path", required=True, type=Path, help="Path to ccc's json stdump")
|
||||||
|
parser.add_argument("--asm-out", type=Path, required=False, help="Path to output asm (defaults to stdout)")
|
||||||
|
parser.add_argument(
|
||||||
|
"--offset", type=int, required=False, default=0, help="Offset to apply to line numbers (default: 0)"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--keep-original",
|
||||||
|
action="store_true",
|
||||||
|
help="Don't start line numbers from 1 (+ offset) but keep the original line numbers (+offset) instead",
|
||||||
|
)
|
||||||
|
|
||||||
|
args = cast(ArgProtocol, parser.parse_args())
|
||||||
|
|
||||||
|
fun_start_num = args.offset
|
||||||
|
|
||||||
|
add_lines_to_asm(
|
||||||
|
args.asm_path,
|
||||||
|
args.stdump_json_path,
|
||||||
|
fun_start_num,
|
||||||
|
args.keep_original,
|
||||||
|
args.asm_out,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,351 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import pydantic
|
||||||
|
|
||||||
|
from typing import Optional, Literal, Any
|
||||||
|
|
||||||
|
|
||||||
|
class AddressRange(pydantic.BaseModel):
|
||||||
|
low: int
|
||||||
|
high: int
|
||||||
|
|
||||||
|
|
||||||
|
class ValueType(pydantic.BaseModel):
|
||||||
|
descriptor: Optional[str] = None
|
||||||
|
source: Optional[str] = None
|
||||||
|
type_name: Optional[str] = None
|
||||||
|
referenced_file_index: Optional[int] = None
|
||||||
|
referenced_stabs_type_number: Optional[int] = None
|
||||||
|
value_type: Optional[ValueType] = None
|
||||||
|
return_type: Optional[ReturnType] = None
|
||||||
|
modifier: Optional[str] = None
|
||||||
|
vtable_index: Optional[int] = None
|
||||||
|
is_constructor: Optional[bool] = None
|
||||||
|
element_type: Optional[ElementType] = None
|
||||||
|
element_count: Optional[int] = None
|
||||||
|
|
||||||
|
|
||||||
|
class DeduplicatedTypeValueType(pydantic.BaseModel):
|
||||||
|
descriptor: Literal["function_type", "type_name"]
|
||||||
|
source: Optional[str] = None
|
||||||
|
type_name: Optional[str] = None
|
||||||
|
referenced_file_index: Optional[int] = None
|
||||||
|
referenced_stabs_type_number: Optional[int] = None
|
||||||
|
value_type: Optional[ValueType] = None
|
||||||
|
return_type: Optional[ReturnType] = None
|
||||||
|
modifier: Optional[str] = None
|
||||||
|
vtable_index: Optional[int] = None
|
||||||
|
is_constructor: Optional[bool] = None
|
||||||
|
element_type: Optional[ElementType] = None
|
||||||
|
element_count: Optional[int] = None
|
||||||
|
|
||||||
|
|
||||||
|
class ParameterType(pydantic.BaseModel):
|
||||||
|
descriptor: str
|
||||||
|
source: Optional[str] = None
|
||||||
|
type_name: Optional[str] = None
|
||||||
|
referenced_file_index: Optional[int] = None
|
||||||
|
referenced_stabs_type_number: Optional[int] = None
|
||||||
|
value_type: Optional[ValueType] = None
|
||||||
|
|
||||||
|
|
||||||
|
class Parameter(pydantic.BaseModel):
|
||||||
|
descriptor: str
|
||||||
|
name: str
|
||||||
|
class_: str = pydantic.Field(..., alias="class")
|
||||||
|
storage: Storage
|
||||||
|
block_low: int
|
||||||
|
block_high: int
|
||||||
|
type: ParameterType
|
||||||
|
|
||||||
|
|
||||||
|
class ReturnType(pydantic.BaseModel):
|
||||||
|
descriptor: str
|
||||||
|
source: Optional[str] = None
|
||||||
|
type_name: Optional[str] = None
|
||||||
|
referenced_file_index: Optional[int] = None
|
||||||
|
referenced_stabs_type_number: Optional[int] = None
|
||||||
|
value_type: Optional[ValueType] = None
|
||||||
|
|
||||||
|
|
||||||
|
class FunctionType(pydantic.BaseModel):
|
||||||
|
descriptor: str
|
||||||
|
parameters: list[Parameter]
|
||||||
|
modifier: str
|
||||||
|
vtable_index: int
|
||||||
|
is_constructor: bool
|
||||||
|
return_type: Optional[ReturnType] = None
|
||||||
|
|
||||||
|
|
||||||
|
class Storage(pydantic.BaseModel):
|
||||||
|
type: str
|
||||||
|
register_: Optional[str] = pydantic.Field(None, alias="register")
|
||||||
|
register_class: Optional[str] = None
|
||||||
|
dbx_register_number: Optional[int] = None
|
||||||
|
register_index: Optional[int] = None
|
||||||
|
is_by_reference: Optional[bool] = None
|
||||||
|
stack_offset: Optional[int] = None
|
||||||
|
global_location: Optional[str] = None
|
||||||
|
global_address: Optional[int] = None
|
||||||
|
|
||||||
|
|
||||||
|
class Constant(pydantic.BaseModel):
|
||||||
|
value: int
|
||||||
|
name: str
|
||||||
|
|
||||||
|
|
||||||
|
class ElementType(pydantic.BaseModel):
|
||||||
|
descriptor: Literal["array", "pointer", "type_name", "enum"]
|
||||||
|
source: Optional[str] = None
|
||||||
|
type_name: Optional[str] = None
|
||||||
|
referenced_file_index: Optional[int] = None
|
||||||
|
referenced_stabs_type_number: Optional[int] = None
|
||||||
|
element_type: Optional[ElementType] = None
|
||||||
|
element_count: Optional[int] = None
|
||||||
|
value_type: Optional[ValueType] = None
|
||||||
|
constants: Optional[list[Constant]] = None
|
||||||
|
|
||||||
|
def parsed_size(self) -> tuple[int, str]:
|
||||||
|
if self.descriptor == "pointer":
|
||||||
|
return 1, "pointer"
|
||||||
|
|
||||||
|
elif self.descriptor == "array":
|
||||||
|
assert self.element_type
|
||||||
|
assert self.element_count is not None
|
||||||
|
if self.element_count == 0:
|
||||||
|
# implicit size array
|
||||||
|
_, type_name = self.element_type.parsed_size()
|
||||||
|
return 0, type_name
|
||||||
|
n, type_name = self.element_type.parsed_size()
|
||||||
|
return self.element_count * n, type_name
|
||||||
|
|
||||||
|
elif self.descriptor == "enum":
|
||||||
|
return 1, "enum"
|
||||||
|
|
||||||
|
else: # "type_name"
|
||||||
|
assert self.type_name
|
||||||
|
return 1, self.type_name
|
||||||
|
|
||||||
|
|
||||||
|
class Local(pydantic.BaseModel):
|
||||||
|
descriptor: str
|
||||||
|
name: str
|
||||||
|
class_: str = pydantic.Field(..., alias="class")
|
||||||
|
storage: Storage
|
||||||
|
block_low: int
|
||||||
|
block_high: int
|
||||||
|
type: ElementType
|
||||||
|
storage_class: Optional[str] = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def parsed_size(self) -> tuple[int, str]:
|
||||||
|
return self.type.parsed_size()
|
||||||
|
|
||||||
|
|
||||||
|
class SubSourceFile(pydantic.BaseModel):
|
||||||
|
address: int
|
||||||
|
path: str
|
||||||
|
|
||||||
|
|
||||||
|
class Function(pydantic.BaseModel):
|
||||||
|
descriptor: str
|
||||||
|
name: str
|
||||||
|
address_range: AddressRange
|
||||||
|
type: FunctionType
|
||||||
|
locals: list[Local]
|
||||||
|
line_numbers: list[list[int]]
|
||||||
|
sub_source_files: list[SubSourceFile]
|
||||||
|
storage_class: Optional[str] = None
|
||||||
|
relative_path: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
|
class Global(pydantic.BaseModel):
|
||||||
|
descriptor: str
|
||||||
|
name: str
|
||||||
|
class_: str = pydantic.Field(..., alias="class")
|
||||||
|
storage: Storage
|
||||||
|
block_low: int
|
||||||
|
block_high: int
|
||||||
|
type: ElementType
|
||||||
|
storage_class: Optional[str] = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def parsed_size(self) -> tuple[int, str]:
|
||||||
|
return self.type.parsed_size()
|
||||||
|
|
||||||
|
|
||||||
|
class File(pydantic.BaseModel):
|
||||||
|
descriptor: str
|
||||||
|
path: str
|
||||||
|
relative_path: str
|
||||||
|
text_address: int
|
||||||
|
types: list[Any]
|
||||||
|
functions: list[Function]
|
||||||
|
globals: list[Global]
|
||||||
|
stabs_type_number_to_deduplicated_type_index: dict[str, int]
|
||||||
|
|
||||||
|
|
||||||
|
class UnderlyingType(pydantic.BaseModel):
|
||||||
|
descriptor: str
|
||||||
|
source: str
|
||||||
|
type_name: str
|
||||||
|
referenced_file_index: int
|
||||||
|
referenced_stabs_type_number: int
|
||||||
|
|
||||||
|
|
||||||
|
class Field(pydantic.BaseModel):
|
||||||
|
descriptor: str
|
||||||
|
name: str
|
||||||
|
relative_offset_bytes: int
|
||||||
|
absolute_offset_bytes: int
|
||||||
|
size_bits: int
|
||||||
|
bitfield_offset_bits: Optional[int] = None
|
||||||
|
underlying_type: Optional[UnderlyingType] = None
|
||||||
|
source: Optional[str] = None
|
||||||
|
type_name: Optional[str] = None
|
||||||
|
referenced_file_index: Optional[int] = None
|
||||||
|
referenced_stabs_type_number: Optional[int] = None
|
||||||
|
value_type: Optional[ValueType] = None
|
||||||
|
base_classes: Optional[list[Any]] = None
|
||||||
|
fields: Optional[list[Field]] = None
|
||||||
|
member_functions: Optional[list[Any]] = None
|
||||||
|
element_type: Optional[ElementType] = None
|
||||||
|
element_count: Optional[int] = None
|
||||||
|
|
||||||
|
|
||||||
|
class FieldModel(pydantic.BaseModel):
|
||||||
|
descriptor: str
|
||||||
|
name: str
|
||||||
|
relative_offset_bytes: int
|
||||||
|
absolute_offset_bytes: int
|
||||||
|
size_bits: int
|
||||||
|
value_type: Optional[ValueType] = None
|
||||||
|
source: Optional[str] = None
|
||||||
|
type_name: Optional[str] = None
|
||||||
|
referenced_file_index: Optional[int] = None
|
||||||
|
referenced_stabs_type_number: Optional[int] = None
|
||||||
|
element_type: Optional[ElementType] = None
|
||||||
|
element_count: Optional[int] = None
|
||||||
|
bitfield_offset_bits: Optional[int] = None
|
||||||
|
underlying_type: Optional[UnderlyingType] = None
|
||||||
|
fields: Optional[list[Field]] = None
|
||||||
|
member_functions: Optional[list[Any]] = None
|
||||||
|
base_classes: Optional[list[Any]] = None
|
||||||
|
|
||||||
|
|
||||||
|
class DeduplicatedType(pydantic.BaseModel):
|
||||||
|
descriptor: Literal["array", "builtin", "enum", "pointer", "struct", "type_name", "union"]
|
||||||
|
name: Optional[str] = None
|
||||||
|
storage_class: Optional[Literal["typedef"]] = None
|
||||||
|
stabs_type_number: int
|
||||||
|
files: list[int]
|
||||||
|
class_: Optional[str] = pydantic.Field(None, alias="class")
|
||||||
|
size_bits: Optional[int] = None
|
||||||
|
base_classes: Optional[list[Any]] = None
|
||||||
|
fields: Optional[list[FieldModel]] = None
|
||||||
|
member_functions: Optional[list[Any]] = None
|
||||||
|
source: Optional[str] = None
|
||||||
|
type_name: Optional[str] = None
|
||||||
|
referenced_file_index: Optional[int] = None
|
||||||
|
referenced_stabs_type_number: Optional[int] = None
|
||||||
|
value_type: Optional[DeduplicatedTypeValueType] = None
|
||||||
|
conflict: Optional[bool] = None
|
||||||
|
element_type: Optional[ElementType] = None
|
||||||
|
element_count: Optional[int] = None
|
||||||
|
constants: Optional[list[Constant]] = None
|
||||||
|
|
||||||
|
|
||||||
|
class CCCJSONv7Model(pydantic.BaseModel):
|
||||||
|
version: Literal[7]
|
||||||
|
files: list[File]
|
||||||
|
deduplicated_types: list[DeduplicatedType]
|
||||||
|
|
||||||
|
|
||||||
|
# def test(stdump_json_path: str):
|
||||||
|
# import json
|
||||||
|
#
|
||||||
|
# with open(stdump_json_path, mode="r") as fh:
|
||||||
|
# json_data = fh.read()
|
||||||
|
#
|
||||||
|
# model = CCCJSONv7Model.model_validate_json(json_data)
|
||||||
|
#
|
||||||
|
# type_map: dict[str, int] = {}
|
||||||
|
#
|
||||||
|
# for n, dt in enumerate(model.deduplicated_types):
|
||||||
|
# if dt.descriptor == "builtin":
|
||||||
|
# assert dt.name and dt.name not in type_map
|
||||||
|
# assert dt.class_ is not None
|
||||||
|
# size_bits = int(dt.class_.split("-", maxsplit=1)[0])
|
||||||
|
# assert size_bits % 8 == 0
|
||||||
|
# type_map[dt.name] = size_bits // 8
|
||||||
|
#
|
||||||
|
# elif dt.descriptor == "type_name":
|
||||||
|
# assert dt.name is not None
|
||||||
|
# assert dt.type_name is not None
|
||||||
|
# if dt.name in type_map:
|
||||||
|
# if dt.size_bits:
|
||||||
|
# assert type_map[dt.name] == dt.size_bits // 8
|
||||||
|
# if dt.name == dt.type_name == "void":
|
||||||
|
# type_map["void"] = type_map["int"]
|
||||||
|
# continue
|
||||||
|
# assert dt.type_name in type_map, (n, dt.type_name)
|
||||||
|
# type_map[dt.name] = type_map[dt.type_name]
|
||||||
|
#
|
||||||
|
# elif dt.descriptor == "pointer":
|
||||||
|
# assert dt.name is not None
|
||||||
|
# assert dt.value_type is not None
|
||||||
|
# if dt.value_type.descriptor == "function_type":
|
||||||
|
# assert dt.name not in type_map
|
||||||
|
# type_map[dt.name] = type_map["int"]
|
||||||
|
# elif dt.value_type.descriptor == "type_name":
|
||||||
|
# assert dt.value_type.type_name
|
||||||
|
# assert dt.value_type.type_name in type_map
|
||||||
|
# type_map[dt.name] = type_map[dt.value_type.type_name]
|
||||||
|
#
|
||||||
|
# elif dt.descriptor == "struct":
|
||||||
|
# assert dt.name is not None
|
||||||
|
# if not dt.conflict:
|
||||||
|
# assert dt.name not in type_map, n
|
||||||
|
# else:
|
||||||
|
# if dt.name in type_map:
|
||||||
|
# continue
|
||||||
|
# assert dt.size_bits is not None
|
||||||
|
# assert dt.size_bits % 8 == 0
|
||||||
|
# type_map[dt.name] = dt.size_bits // 8
|
||||||
|
#
|
||||||
|
# elif dt.descriptor == "array":
|
||||||
|
# assert dt.name is not None
|
||||||
|
# element_count = 1
|
||||||
|
# element_type = dt.element_type
|
||||||
|
# type_name = None
|
||||||
|
# while element_type:
|
||||||
|
# if element_type.element_count is not None:
|
||||||
|
# element_count *= element_type.element_count
|
||||||
|
# if element_type.type_name is not None:
|
||||||
|
# type_name = element_type.type_name
|
||||||
|
# assert type_name in type_map
|
||||||
|
# element_count *= type_map[type_name]
|
||||||
|
# element_type = element_type.element_type
|
||||||
|
# assert type_name and type_name in type_map, n
|
||||||
|
# type_map[dt.name] = type_map[type_name] * element_count
|
||||||
|
#
|
||||||
|
# elif dt.descriptor == "enum":
|
||||||
|
# if dt.name:
|
||||||
|
# if not dt.conflict:
|
||||||
|
# assert dt.name not in type_map, n
|
||||||
|
# type_map[dt.name] = type_map["int"]
|
||||||
|
#
|
||||||
|
# elif dt.descriptor == "union":
|
||||||
|
# assert dt.name
|
||||||
|
# assert dt.size_bits
|
||||||
|
# assert dt.size_bits % 8 == 0
|
||||||
|
# type_map[dt.name] = dt.size_bits // 8
|
||||||
|
#
|
||||||
|
# else:
|
||||||
|
# assert False, f"unknown {n}"
|
||||||
|
#
|
||||||
|
# print(json.dumps(type_map, indent=2))
|
||||||
|
|
||||||
|
|
||||||
|
# if __name__ == "__main__":
|
||||||
|
# test(path-to-stdump-json)
|
||||||
@@ -0,0 +1,322 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import io
|
||||||
|
import sys
|
||||||
|
import math
|
||||||
|
import ctypes
|
||||||
|
import numpy as np
|
||||||
|
import numpy.typing as npt
|
||||||
|
from collections.abc import Sized, Sequence
|
||||||
|
from typing import Type, TypeVar, Any, cast, TextIO, BinaryIO, Optional
|
||||||
|
from ctypes import LittleEndianStructure, Union, Array, c_uint32
|
||||||
|
|
||||||
|
_G = TypeVar("_G")
|
||||||
|
|
||||||
|
CTypeType = (
|
||||||
|
type[ctypes.c_int8]
|
||||||
|
| type[ctypes.c_uint8]
|
||||||
|
| type[ctypes.c_int16]
|
||||||
|
| type[ctypes.c_uint16]
|
||||||
|
| type[ctypes.c_int32]
|
||||||
|
| type[ctypes.c_uint32]
|
||||||
|
| type[ctypes.c_float]
|
||||||
|
| type[ctypes.c_double]
|
||||||
|
)
|
||||||
|
|
||||||
|
ctypes_types: dict[str, CTypeType] = {
|
||||||
|
"char": ctypes.c_int8,
|
||||||
|
"u_char": ctypes.c_uint8,
|
||||||
|
"short": ctypes.c_int16,
|
||||||
|
"u_short": ctypes.c_uint16,
|
||||||
|
"int": ctypes.c_int32,
|
||||||
|
"u_int": ctypes.c_uint32,
|
||||||
|
"float": ctypes.c_float,
|
||||||
|
"double": ctypes.c_double,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class c_addr(c_uint32):
|
||||||
|
def __str__(self):
|
||||||
|
# if self.value == 0:
|
||||||
|
# return "NULL"
|
||||||
|
|
||||||
|
# return f"0x{self.value:08x}"
|
||||||
|
return f"0x{self.value:x}"
|
||||||
|
|
||||||
|
|
||||||
|
class c_str(c_uint32):
|
||||||
|
def to_str(self, elf: BinaryIO):
|
||||||
|
if self.value == 0:
|
||||||
|
return "NULL"
|
||||||
|
elf.seek(self.value)
|
||||||
|
buf = io.BytesIO()
|
||||||
|
while (c := elf.read(1)) != b"\0":
|
||||||
|
buf.write(c)
|
||||||
|
return '"' + buf.getvalue().decode("ASCII") + '"'
|
||||||
|
|
||||||
|
|
||||||
|
class c_addr_ptr(c_uint32):
|
||||||
|
_addresses: dict[int, str] | None = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def set_addresses(cls, addresses: dict[int, str] | None):
|
||||||
|
cls._addresses = addresses
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.value == 0:
|
||||||
|
return "NULL"
|
||||||
|
|
||||||
|
if self._addresses and self.value in self._addresses:
|
||||||
|
return self._addresses[self.value]
|
||||||
|
|
||||||
|
print(f"warning: no address for pointer 0x{self.value:x}")
|
||||||
|
|
||||||
|
return f"0x{self.value:x}"
|
||||||
|
|
||||||
|
|
||||||
|
def print_arr(arr: npt.NDArray[np.int_], lst: list[Any], file: TextIO):
|
||||||
|
if arr.ndim > 1:
|
||||||
|
for x in arr:
|
||||||
|
file.write("{")
|
||||||
|
print_arr(x, lst, file)
|
||||||
|
file.write("},")
|
||||||
|
else:
|
||||||
|
file.write(",".join(str(lst[i]) for i in arr))
|
||||||
|
|
||||||
|
|
||||||
|
def print_carr(arr: Sequence[Any], file: TextIO):
|
||||||
|
if hasattr(arr[0], "_length_"):
|
||||||
|
for a in arr:
|
||||||
|
file.write("{")
|
||||||
|
print_carr(a, file)
|
||||||
|
file.write("},")
|
||||||
|
else:
|
||||||
|
v = str(str([x for x in arr])).replace("[", "").replace("]", "")
|
||||||
|
file.write(v)
|
||||||
|
|
||||||
|
|
||||||
|
def chunks(lst: Sequence[_G], n: int):
|
||||||
|
"""Yield successive n-sized chunks from lst."""
|
||||||
|
for i in range(0, len(lst), n):
|
||||||
|
yield lst[i : i + n]
|
||||||
|
|
||||||
|
|
||||||
|
def format_array(lst: Sequence[_G], dims: Sequence[int], file: TextIO):
|
||||||
|
if len(dims) > 1:
|
||||||
|
for ll in chunks(lst, len(lst) // dims[0]):
|
||||||
|
file.write("{")
|
||||||
|
format_array(ll, dims[1:], file)
|
||||||
|
file.write("},")
|
||||||
|
else:
|
||||||
|
for n, x in enumerate(lst):
|
||||||
|
sep = ", " if n < len(lst) - 1 else ""
|
||||||
|
file.write(f"{x}{sep}")
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_annotations(namespace: dict[str, Any], annotations: dict[str, Any]):
|
||||||
|
module = sys.modules.get(namespace.get("__module__", ""))
|
||||||
|
globals_ = vars(module) if module else {}
|
||||||
|
resolved: dict[str, Any] = {}
|
||||||
|
|
||||||
|
for k, v in annotations.items():
|
||||||
|
if isinstance(v, str):
|
||||||
|
try:
|
||||||
|
resolved[k] = eval(v, globals_, namespace)
|
||||||
|
except Exception:
|
||||||
|
resolved[k] = v # keep as string if can't resolve
|
||||||
|
else:
|
||||||
|
resolved[k] = v
|
||||||
|
|
||||||
|
return resolved
|
||||||
|
|
||||||
|
|
||||||
|
class LittleEndianStructureFieldsFromTypeHints(type(LittleEndianStructure)): # pyright: ignore
|
||||||
|
def __new__(
|
||||||
|
cls: Type[type],
|
||||||
|
name: str,
|
||||||
|
bases: tuple[type, ...],
|
||||||
|
namespace: dict[str, Any],
|
||||||
|
/,
|
||||||
|
*,
|
||||||
|
align: Optional[int] = None,
|
||||||
|
pack: Optional[int] = None,
|
||||||
|
) -> LittleEndianStructureFieldsFromTypeHints:
|
||||||
|
annotations = namespace.get("__annotations__", {})
|
||||||
|
annotations = resolve_annotations(namespace, annotations)
|
||||||
|
if "__elf__" in annotations:
|
||||||
|
annotations.pop("__elf__")
|
||||||
|
if align is not None:
|
||||||
|
namespace["_align_"] = align
|
||||||
|
if pack is not None:
|
||||||
|
namespace["_pack_"] = pack
|
||||||
|
namespace["_layout_"] = "ms"
|
||||||
|
if fields := list(annotations.items()):
|
||||||
|
namespace["_fields_"] = fields
|
||||||
|
return type(LittleEndianStructure).__new__(cls, name, bases, namespace) # pyright: ignore
|
||||||
|
|
||||||
|
|
||||||
|
class CStructure(LittleEndianStructure, metaclass=LittleEndianStructureFieldsFromTypeHints):
|
||||||
|
__elf__: BinaryIO
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def sizeof(cls) -> int:
|
||||||
|
align = getattr(cls, "_align_", 0)
|
||||||
|
c_size = ctypes.sizeof(cls)
|
||||||
|
if align > 0:
|
||||||
|
rem = c_size % align
|
||||||
|
if rem:
|
||||||
|
rem = align - rem
|
||||||
|
return c_size + rem
|
||||||
|
|
||||||
|
return c_size
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def parse(cls, data: bytes):
|
||||||
|
cstruct_size = sizeof(cls)
|
||||||
|
assert len(data) % cstruct_size == 0, f"{len(data)}, {cstruct_size}"
|
||||||
|
cstruct_num = len(data) // cstruct_size
|
||||||
|
stream = io.BytesIO(data)
|
||||||
|
cstructs = [cls.from_buffer_copy(stream.read(cstruct_size)) for _ in range(cstruct_num)]
|
||||||
|
return cstructs
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def dumps(
|
||||||
|
cls,
|
||||||
|
name: str,
|
||||||
|
data: bytes,
|
||||||
|
numel: int | list[int],
|
||||||
|
static: bool = False,
|
||||||
|
nosize: bool = False,
|
||||||
|
noarray: bool = False,
|
||||||
|
):
|
||||||
|
cstructs = cls.parse(data)
|
||||||
|
stream = io.StringIO()
|
||||||
|
if static:
|
||||||
|
stream.write("static ")
|
||||||
|
stream.write(f"{cls.__name__} {name}") # pyright: ignore
|
||||||
|
assert not (noarray and isinstance(numel, list))
|
||||||
|
if not noarray:
|
||||||
|
if isinstance(numel, int):
|
||||||
|
assert len(cstructs) == numel, (len(cstructs), numel)
|
||||||
|
numel_str = f"{len(cstructs)}" if not nosize else ""
|
||||||
|
stream.write(f"[{numel_str}]")
|
||||||
|
else:
|
||||||
|
numel_str = "".join([f"[{num if n > 0 or not nosize else ''}]" for n, num in enumerate(numel)])
|
||||||
|
stream.write(numel_str)
|
||||||
|
tot_numel = max(1, numel) if isinstance(numel, int) else math.prod(numel)
|
||||||
|
# nmdim = 1 if isinstance(numel, int) else len(numel)
|
||||||
|
assert len(cstructs) == tot_numel, (len(cstructs), tot_numel)
|
||||||
|
|
||||||
|
stream.write(" = ")
|
||||||
|
if not noarray:
|
||||||
|
stream.write("{\n")
|
||||||
|
if isinstance(numel, int):
|
||||||
|
for n, s in enumerate(cstructs):
|
||||||
|
is_last = n == len(cstructs) - 1
|
||||||
|
if is_last and noarray:
|
||||||
|
stream.write(f"{s}\n")
|
||||||
|
else:
|
||||||
|
stream.write(f"{s},\n")
|
||||||
|
|
||||||
|
else:
|
||||||
|
idxs = np.arange(tot_numel).reshape(numel)
|
||||||
|
print_arr(idxs, cstructs, stream)
|
||||||
|
if not noarray:
|
||||||
|
stream.write("}")
|
||||||
|
stream.write(";\n\n")
|
||||||
|
return stream.getvalue()
|
||||||
|
|
||||||
|
# def to_str(self, elf: BinaryIO):
|
||||||
|
def __str__(self):
|
||||||
|
stream = io.StringIO()
|
||||||
|
stream.write(" {\n")
|
||||||
|
for f, *_ in self._fields_: # pyright: ignore
|
||||||
|
if f.startswith("_pad_"):
|
||||||
|
continue
|
||||||
|
v = getattr(self, f) # pyright: ignore
|
||||||
|
if f in ("_in", "_pass"):
|
||||||
|
f = f[1:] # pyright: ignore
|
||||||
|
if isinstance(v, c_str):
|
||||||
|
stream.write(f" .{f} = {v.to_str(self.__elf__)},\n")
|
||||||
|
elif not isinstance(v, Array):
|
||||||
|
stream.write(f" .{f} = {v},\n")
|
||||||
|
else:
|
||||||
|
arr = cast(Sized, v)
|
||||||
|
if len(arr) and isinstance(v[0], CStructure):
|
||||||
|
arr = cast(list[CStructure], arr)
|
||||||
|
stream.write(f" .{f} = {{\n")
|
||||||
|
for elem in arr:
|
||||||
|
stream.write(f" {elem},\n")
|
||||||
|
stream.write(" },\n")
|
||||||
|
else:
|
||||||
|
arr = cast(Sequence[Any], arr)
|
||||||
|
if isinstance(arr[0], Array):
|
||||||
|
# multidimensional ctypes array
|
||||||
|
stream.write(f" .{f} = {{")
|
||||||
|
print_carr(arr, stream)
|
||||||
|
stream.write("},\n")
|
||||||
|
else:
|
||||||
|
stream.write(f" .{f} = {{")
|
||||||
|
dims = [len(arr)]
|
||||||
|
format_array(arr, dims, stream)
|
||||||
|
|
||||||
|
stream.write("},\n")
|
||||||
|
stream.write(" }")
|
||||||
|
return stream.getvalue()
|
||||||
|
|
||||||
|
|
||||||
|
class UnionFieldsFromTypeHints(type(Union)): # pyright: ignore
|
||||||
|
def __new__(
|
||||||
|
cls: Type[type],
|
||||||
|
name: str,
|
||||||
|
bases: tuple[type, ...],
|
||||||
|
namespace: dict[str, Any],
|
||||||
|
/,
|
||||||
|
*,
|
||||||
|
align: Optional[int] = None,
|
||||||
|
pack: Optional[int] = None,
|
||||||
|
) -> UnionFieldsFromTypeHints:
|
||||||
|
annotations = namespace.get("__annotations__", {})
|
||||||
|
if align is not None:
|
||||||
|
namespace["_align_"] = align
|
||||||
|
if pack is not None:
|
||||||
|
namespace["_pack_"] = pack
|
||||||
|
if fields := list(annotations.items()):
|
||||||
|
namespace["_fields_"] = fields
|
||||||
|
return type(Union).__new__(cls, name, bases, namespace) # pyright: ignore
|
||||||
|
|
||||||
|
|
||||||
|
class CUnion(Union, metaclass=UnionFieldsFromTypeHints):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
_T = TypeVar("_T", bound=CStructure)
|
||||||
|
|
||||||
|
|
||||||
|
def sizeof(cstruct_type: Type[_T]) -> int:
|
||||||
|
align = getattr(cstruct_type, "_align_", 0)
|
||||||
|
c_size = ctypes.sizeof(cstruct_type)
|
||||||
|
if align > 0:
|
||||||
|
rem = c_size % align
|
||||||
|
if rem:
|
||||||
|
rem = align - rem
|
||||||
|
return c_size + rem
|
||||||
|
|
||||||
|
return c_size
|
||||||
|
|
||||||
|
|
||||||
|
def parse_cstruct(cstruct_type: Type[_T], data: bytes) -> list[_T]:
|
||||||
|
cstruct_size = sizeof(cstruct_type)
|
||||||
|
assert len(data) % cstruct_size == 0, f"{len(data)}, {cstruct_size}"
|
||||||
|
cstruct_num = len(data) // cstruct_size
|
||||||
|
stream = io.BytesIO(data)
|
||||||
|
cstructs = [cstruct_type.from_buffer_copy(stream.read(cstruct_size)) for _ in range(cstruct_num)]
|
||||||
|
return cstructs
|
||||||
|
|
||||||
|
|
||||||
|
def print_cstruct(name: str, cstruct_type: Type[CStructure], data: bytes):
|
||||||
|
cstructs = parse_cstruct(cstruct_type, data)
|
||||||
|
print(f"{cstruct_type.__name__} {name}[{len(cstructs)}] = {{") # pyright: ignore
|
||||||
|
for s in cstructs:
|
||||||
|
print(s)
|
||||||
|
print("};\n")
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import argparse
|
||||||
|
|
||||||
|
|
||||||
|
registers = {
|
||||||
|
"$0": "zero",
|
||||||
|
"$1": "at",
|
||||||
|
"$2": "v0",
|
||||||
|
"$3": "v1",
|
||||||
|
"$4": "a0",
|
||||||
|
"$5": "a1",
|
||||||
|
"$6": "a2",
|
||||||
|
"$7": "a3",
|
||||||
|
"$8": "t0",
|
||||||
|
"$9": "t1",
|
||||||
|
"$10": "t2",
|
||||||
|
"$11": "t3",
|
||||||
|
"$12": "t4",
|
||||||
|
"$13": "t5",
|
||||||
|
"$14": "t6",
|
||||||
|
"$15": "t7",
|
||||||
|
"$16": "s0",
|
||||||
|
"$17": "s1",
|
||||||
|
"$18": "s2",
|
||||||
|
"$19": "s3",
|
||||||
|
"$20": "s4",
|
||||||
|
"$21": "s5",
|
||||||
|
"$22": "s6",
|
||||||
|
"$23": "s7",
|
||||||
|
"$24": "t8",
|
||||||
|
"$25": "t9",
|
||||||
|
"$26": "k0",
|
||||||
|
"$27": "k1",
|
||||||
|
"$28": "gp",
|
||||||
|
"$29": "sp",
|
||||||
|
"$30": "fp",
|
||||||
|
"$31": "ra",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def fix_asm(asm_file: str):
|
||||||
|
with open(asm_file, mode="r") as fh:
|
||||||
|
for line in fh:
|
||||||
|
for reg_num, reg_mnem in reversed(registers.items()):
|
||||||
|
line = line.replace(reg_num, reg_mnem)
|
||||||
|
print(line, end="")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("asm_file", help="source assembly file path")
|
||||||
|
args = parser.parse_args()
|
||||||
|
fix_asm(args.asm_file)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
import os
|
||||||
|
import re
|
||||||
|
import argparse
|
||||||
|
import pydantic
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Protocol, cast
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_ROOT = Path(__file__).parent.parent.parent.resolve() / "config"
|
||||||
|
|
||||||
|
# enumerate languages from config dir
|
||||||
|
LANGUAGES = [Path(f.path).name for f in os.scandir(CONFIG_ROOT) if f.is_dir()]
|
||||||
|
|
||||||
|
RE_INSTR = re.compile(r"^\t(?:[^.]|\.p2align \d+)")
|
||||||
|
|
||||||
|
|
||||||
|
class InstructionPatch(pydantic.RootModel[tuple[int, str, str]]):
|
||||||
|
root: tuple[int, str, str]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def instr_no(self):
|
||||||
|
return self.root[0]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def instr_org(self):
|
||||||
|
return self.root[1]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def instr_patch(self):
|
||||||
|
return self.root[2]
|
||||||
|
|
||||||
|
|
||||||
|
class ASMPatch(pydantic.RootModel[dict[str, list[InstructionPatch]]]):
|
||||||
|
root: dict[str, list[InstructionPatch]]
|
||||||
|
|
||||||
|
|
||||||
|
class PatchDB(pydantic.RootModel[dict[str, ASMPatch]]):
|
||||||
|
root: dict[str, ASMPatch]
|
||||||
|
|
||||||
|
|
||||||
|
def fix_asm(asm_file: Path, asm_patch: ASMPatch):
|
||||||
|
lines = asm_file.read_text().splitlines()
|
||||||
|
|
||||||
|
def find_func(func: str):
|
||||||
|
for i, line in enumerate(lines):
|
||||||
|
if re.match(rf"^{func}:", line):
|
||||||
|
return i
|
||||||
|
|
||||||
|
return -1
|
||||||
|
|
||||||
|
def find_line(start: int, num: int):
|
||||||
|
offset = 0
|
||||||
|
instr_no = -1
|
||||||
|
for line in lines[start:]:
|
||||||
|
if RE_INSTR.match(line):
|
||||||
|
instr_no += 1
|
||||||
|
|
||||||
|
if instr_no == num:
|
||||||
|
return start + offset
|
||||||
|
|
||||||
|
offset += 1
|
||||||
|
|
||||||
|
raise RuntimeError("cannot find instruction!")
|
||||||
|
|
||||||
|
for func, patch_lst in asm_patch.root.items():
|
||||||
|
n = find_func(func)
|
||||||
|
|
||||||
|
if n == -1:
|
||||||
|
print(f"WARNING: cannot find function {func} in {asm_file.name}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
for patch in patch_lst:
|
||||||
|
line_no = find_line(n, patch.instr_no)
|
||||||
|
line_org = lines[line_no]
|
||||||
|
|
||||||
|
line_org_clean = re.sub(r"\s+", " ", line_org).strip()
|
||||||
|
instr_org_clean = re.sub(r"\s+", " ", patch.instr_org).strip()
|
||||||
|
instr_patch_clean = re.sub(r"\s+", " ", patch.instr_patch).strip()
|
||||||
|
|
||||||
|
if line_org_clean != instr_org_clean:
|
||||||
|
print(f"WARNING: wrong line: {asm_file.name}:{func}:{line_no + 1}: {line_org} != {patch.instr_org}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
lines[line_no] = f"\t{instr_patch_clean}"
|
||||||
|
|
||||||
|
asm_file.write_text("\n".join(lines))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
class ArgsProtocol(Protocol):
|
||||||
|
language: str
|
||||||
|
asm_file: Path
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="apply asm patches to assembly files")
|
||||||
|
parser.add_argument("language", type=str, choices=LANGUAGES, help="language of the asm that is being patched")
|
||||||
|
parser.add_argument("asm_file", type=Path, help="generated assembly file to patch (relative to build dir)")
|
||||||
|
|
||||||
|
args = cast(ArgsProtocol, parser.parse_args())
|
||||||
|
|
||||||
|
asm_file = CONFIG_ROOT / args.language / args.asm_file
|
||||||
|
|
||||||
|
if not asm_file.exists():
|
||||||
|
print(f"ERROR: cannot find assembly file {asm_file}")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
patch_db_path = CONFIG_ROOT / args.language / "asm_patches.json"
|
||||||
|
|
||||||
|
if not patch_db_path.exists():
|
||||||
|
print("ERROR: patch db file doesn't exist. aborting patching asm")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
patch_db = PatchDB.model_validate_json(patch_db_path.read_text())
|
||||||
|
|
||||||
|
if asm_file.name not in patch_db.root:
|
||||||
|
print(f"ERROR: no patches found for file {asm_file.name}")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
asm_patch = patch_db.root[asm_file.name]
|
||||||
|
|
||||||
|
fix_asm(asm_file, asm_patch)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import re
|
||||||
|
import glob
|
||||||
|
import tqdm
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
from typing import Protocol, cast
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def fix_assets(asm_data_path: Path, asset_rel_path: Path):
|
||||||
|
asm_files = glob.glob(str(asm_data_path / "**/*.s"), recursive=True)
|
||||||
|
for asm_file in tqdm.tqdm(asm_files, desc="Fixing data asm"):
|
||||||
|
n: int = 0
|
||||||
|
with open(asm_file, mode="r") as fh:
|
||||||
|
data_asm: str = fh.read()
|
||||||
|
data_asm, n = re.subn(rf'\.incbin "{asset_rel_path}/', '.incbin "assets/', data_asm)
|
||||||
|
|
||||||
|
if n > 0:
|
||||||
|
with open(asm_file, mode="w") as wh:
|
||||||
|
wh.write(data_asm)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
class ArgsProtocol(Protocol):
|
||||||
|
asm_data_path: Path
|
||||||
|
asset_rel_path: Path
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="fixes data asm include path")
|
||||||
|
parser.add_argument("asm_path", metavar="asm-path", type=Path, help="data path in assembly root to patch")
|
||||||
|
parser.add_argument("asset_rel_path", metavar="asset-path", type=Path, help="relative asset path")
|
||||||
|
|
||||||
|
args = cast(ArgsProtocol, parser.parse_args())
|
||||||
|
|
||||||
|
fix_assets(args.asm_data_path, args.asset_rel_path)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
import pydantic
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Protocol, cast
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_ROOT = Path(__file__).parent.parent.parent.resolve() / "config"
|
||||||
|
|
||||||
|
# enumerate languages from config dir
|
||||||
|
LANGUAGES = [Path(f.path).name for f in os.scandir(CONFIG_ROOT) if f.is_dir()]
|
||||||
|
|
||||||
|
|
||||||
|
class BytePatch(pydantic.RootModel[tuple[int, int]]):
|
||||||
|
root: tuple[int, int]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def address(self):
|
||||||
|
return self.root[0]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def size(self):
|
||||||
|
return self.root[1]
|
||||||
|
|
||||||
|
|
||||||
|
class BINPatch(pydantic.RootModel[dict[str, BytePatch]]):
|
||||||
|
root: dict[str, BytePatch]
|
||||||
|
|
||||||
|
|
||||||
|
class PatchDB(pydantic.RootModel[dict[str, BINPatch]]):
|
||||||
|
root: dict[str, BINPatch]
|
||||||
|
|
||||||
|
|
||||||
|
def fix_elf(orig_elf_path: Path, built_elf_path: Path, bin_patch: BytePatch):
|
||||||
|
with orig_elf_path.open("rb") as fh:
|
||||||
|
fh.seek(bin_patch.address)
|
||||||
|
data = fh.read(bin_patch.size)
|
||||||
|
|
||||||
|
with built_elf_path.open(mode="r+b") as wh:
|
||||||
|
wh.seek(bin_patch.address)
|
||||||
|
wh.write(data)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
class ArgsProtocol(Protocol):
|
||||||
|
language: str
|
||||||
|
elf_file: Path
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="apply asm patches to assembly files")
|
||||||
|
parser.add_argument("language", type=str, choices=LANGUAGES, help="language of the elf that is being patched")
|
||||||
|
parser.add_argument("elf_file", type=Path, help="elf file to patch (relative to build dir)")
|
||||||
|
|
||||||
|
args = cast(ArgsProtocol, parser.parse_args())
|
||||||
|
|
||||||
|
built_elf_file = CONFIG_ROOT / args.language / args.elf_file
|
||||||
|
|
||||||
|
if not built_elf_file.exists():
|
||||||
|
print(f"ERROR: cannot find elf file {built_elf_file}")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
orig_elf_path = CONFIG_ROOT / args.language / args.elf_file.name
|
||||||
|
|
||||||
|
patch_db_path = CONFIG_ROOT / args.language / "bin_patches.json"
|
||||||
|
|
||||||
|
if not patch_db_path.exists():
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
patch_db = PatchDB.model_validate_json(patch_db_path.read_text())
|
||||||
|
|
||||||
|
for _tu_name, bin_patch in patch_db.root.items():
|
||||||
|
for _func_name, byte_patch in bin_patch.root.items():
|
||||||
|
fix_elf(orig_elf_path, built_elf_file, byte_patch)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import re
|
||||||
|
import glob
|
||||||
|
import tqdm
|
||||||
|
import argparse
|
||||||
|
import functools
|
||||||
|
|
||||||
|
from typing import Protocol, cast
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
@functools.lru_cache(maxsize=1024) # pyright: ignore[reportUntypedFunctionDecorator]
|
||||||
|
def get_symbol_address(symbol_addrs: Path, symbol: str):
|
||||||
|
if match := re.match(r"^ *([^+ ]+) *\+ *(0x[0-9a-fA-F]+)$", symbol):
|
||||||
|
symbol = match.group(1)
|
||||||
|
offset = int(match.group(2), 16)
|
||||||
|
else:
|
||||||
|
offset = 0
|
||||||
|
|
||||||
|
with open(symbol_addrs, mode="r") as fh:
|
||||||
|
for line in fh:
|
||||||
|
if line.startswith(f"{symbol} "):
|
||||||
|
addr = int(line.split("=")[1].split(";")[0].strip(), 16)
|
||||||
|
return addr + offset
|
||||||
|
|
||||||
|
assert False, f"{symbol} not found"
|
||||||
|
|
||||||
|
|
||||||
|
def fix_gp(asm_path: Path, gp_value: int, symbol_addrs: Path):
|
||||||
|
if gp_value <= 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
asm_files = glob.glob(str(asm_path / "**/*.s"), recursive=True)
|
||||||
|
for asm_file in tqdm.tqdm(asm_files, desc="Fixing gp_rel"):
|
||||||
|
lines: list[str] = []
|
||||||
|
with open(asm_file, mode="r") as fh:
|
||||||
|
for line in fh:
|
||||||
|
if match := re.match(r"^(.*)%gp_rel\(([^)]+)\)(.*)$", line):
|
||||||
|
# ol = line
|
||||||
|
instr_pre = match.group(1)
|
||||||
|
instr_post = match.group(3)
|
||||||
|
address_str = match.group(2)
|
||||||
|
if address_str.startswith("D_"):
|
||||||
|
address_str = address_str.replace("D_", "0x")
|
||||||
|
res = eval(address_str)
|
||||||
|
address = res
|
||||||
|
else:
|
||||||
|
address = get_symbol_address(symbol_addrs, address_str)
|
||||||
|
gp_rel = address - gp_value
|
||||||
|
line = f"{instr_pre}{hex(gp_rel)}{instr_post}\n"
|
||||||
|
lines.append(line)
|
||||||
|
with open(asm_file, mode="w") as wh:
|
||||||
|
wh.writelines(lines)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
class ArgsProtocol(Protocol):
|
||||||
|
asm_path: Path
|
||||||
|
gp_value: int
|
||||||
|
symbol_addrs: Path
|
||||||
|
|
||||||
|
def hex_int(x: str):
|
||||||
|
return int(x, 16)
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="fixes asm removing gp_rel macro")
|
||||||
|
parser.add_argument("asm_path", metavar="asm-path", type=Path, help="assembly root path to patch")
|
||||||
|
parser.add_argument("gp_value", metavar="gp", type=hex_int, help="gp value in hex")
|
||||||
|
parser.add_argument("symbol_addrs", metavar="symbol-addrs", type=Path, help="path of symbol_addrs.txt")
|
||||||
|
|
||||||
|
args = cast(ArgsProtocol, parser.parse_args())
|
||||||
|
|
||||||
|
fix_gp(args.asm_path, args.gp_value, args.symbol_addrs)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import yaml
|
||||||
|
import tqdm
|
||||||
|
|
||||||
|
from typing import cast, Any
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
# e.g.: build/src/main/main.c.o(.text);
|
||||||
|
# build/asm/data/rodata_4.rodata.s.o(.rodata);
|
||||||
|
# ...
|
||||||
|
# NOTE: also account for optional '/data/' in path as chunks of data
|
||||||
|
# not belonging to a c file are put into 'build/asm/data/' folder.
|
||||||
|
re_subsegment_line = re.compile(
|
||||||
|
r"^(?P<indent> +)build/(?:asm|src)(?:/data)?/(?P<name>.*)\.[sc]\.o\(\.(?P<section>.+)\);$"
|
||||||
|
)
|
||||||
|
|
||||||
|
# e.g.: .main 0x100000 : AT(main_ROM_START) SUBALIGN(2)
|
||||||
|
# .main_bss (NOLOAD) : SUBALIGN(4)
|
||||||
|
# ...
|
||||||
|
re_section_line = re.compile(r"^(?P<indent> +)\.(?P<section>[^ ]+) .* SUBALIGN\((?P<subalign>[0-9]+)\)$")
|
||||||
|
|
||||||
|
|
||||||
|
def get_align(address: int):
|
||||||
|
return (
|
||||||
|
128 * ((address % 128) == 0)
|
||||||
|
or 64 * ((address % 64) == 0)
|
||||||
|
or 32 * ((address % 32) == 0)
|
||||||
|
or 16 * ((address % 16) == 0)
|
||||||
|
or 8 * ((address % 8) == 0)
|
||||||
|
or 4 * ((address % 4) == 0)
|
||||||
|
or 2 * ((address % 2) == 0)
|
||||||
|
or 1
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def make_align_map(config: dict[str, Any]):
|
||||||
|
segments = cast(list[dict[str, Any] | list[Any]] | None, config["segments"])
|
||||||
|
assert segments
|
||||||
|
main_segment = next(
|
||||||
|
(segment for segment in segments if isinstance(segment, dict) and segment.get("name") == "main"), None
|
||||||
|
)
|
||||||
|
assert main_segment, "cannot find main segment"
|
||||||
|
|
||||||
|
subsegments = cast(list[dict[str, Any] | list[Any]] | None, main_segment["subsegments"])
|
||||||
|
assert subsegments, "cannot find main subsegments"
|
||||||
|
|
||||||
|
align_map: dict[str, int] = {}
|
||||||
|
|
||||||
|
for subsegment in subsegments:
|
||||||
|
if not isinstance(subsegment, dict):
|
||||||
|
continue
|
||||||
|
|
||||||
|
s_type = cast(str | None, subsegment.get("type"))
|
||||||
|
vram = cast(int | None, subsegment.get("vram"))
|
||||||
|
name = cast(str | None, subsegment.get("name"))
|
||||||
|
if not s_type or not vram or not name:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if name.endswith("bin"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
align = get_align(vram)
|
||||||
|
|
||||||
|
if not s_type.startswith("."):
|
||||||
|
name = f"{s_type}#{name}.{s_type}"
|
||||||
|
else:
|
||||||
|
name = f"{s_type[1:]}#{name}"
|
||||||
|
|
||||||
|
align_map[name] = align
|
||||||
|
|
||||||
|
return align_map
|
||||||
|
|
||||||
|
|
||||||
|
def fix_linkerscript(config: dict[str, Any], linkerscript_path: Path):
|
||||||
|
align_map = make_align_map(config)
|
||||||
|
|
||||||
|
section_subalign = cast(dict[str, int], config["_section_subalign"])
|
||||||
|
|
||||||
|
line_count = 0
|
||||||
|
with open(linkerscript_path, mode="r") as fh:
|
||||||
|
for line in fh:
|
||||||
|
line_count += 1
|
||||||
|
|
||||||
|
patched_lines: list[str] = []
|
||||||
|
|
||||||
|
with open(linkerscript_path, mode="r") as fh:
|
||||||
|
for line in tqdm.tqdm(fh, desc="Fixing linker script", total=line_count):
|
||||||
|
if match := re_subsegment_line.match(line):
|
||||||
|
indent = cast(str, match["indent"])
|
||||||
|
name = cast(str, match["name"])
|
||||||
|
section = cast(str, match["section"])
|
||||||
|
|
||||||
|
# force each subsegment in the following sections to have align 8
|
||||||
|
if section == "text":
|
||||||
|
patched_lines.append(f"{indent}. = ALIGN(., 8);\n")
|
||||||
|
|
||||||
|
key = f"{section}#{name}"
|
||||||
|
if align := align_map.get(key):
|
||||||
|
patched_lines.append(f"{indent}. = ALIGN(., {align});\n")
|
||||||
|
|
||||||
|
if match := re_section_line.match(line):
|
||||||
|
indent = cast(str, match["indent"])
|
||||||
|
section = cast(str, match["section"])
|
||||||
|
subalign = cast(str, match["subalign"])
|
||||||
|
|
||||||
|
# force each section to have the subalign specified in the yaml
|
||||||
|
if section in section_subalign:
|
||||||
|
current_subalign = f"SUBALIGN({subalign})"
|
||||||
|
fixed_subalign = f"SUBALIGN({section_subalign[section]})"
|
||||||
|
line = line.replace(current_subalign, fixed_subalign)
|
||||||
|
|
||||||
|
patched_lines.append(line)
|
||||||
|
|
||||||
|
with open(linkerscript_path, mode="w") as fh:
|
||||||
|
fh.writelines(patched_lines)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) != 3:
|
||||||
|
print("usage: fix_linkerscript.py CONFIG_YAML_PATH LINKERSCRIPT_PATH")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
config_path = Path(sys.argv[1])
|
||||||
|
linkerscript_path = Path(sys.argv[2])
|
||||||
|
|
||||||
|
with open(config_path, mode="r") as fh:
|
||||||
|
try:
|
||||||
|
config = cast(dict[str, Any], yaml.safe_load(fh))
|
||||||
|
except yaml.YAMLError as e:
|
||||||
|
print(e)
|
||||||
|
raise e
|
||||||
|
|
||||||
|
fix_linkerscript(config, linkerscript_path)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,153 @@
|
|||||||
|
import json
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
from typing import Protocol, Iterable, Any, cast
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def fix_unit(unit: dict[str, Any]):
|
||||||
|
# name: str = unit["name"]
|
||||||
|
fuzzy_match_percent: float | None = unit["measures"].get("fuzzy_match_percent")
|
||||||
|
|
||||||
|
assert fuzzy_match_percent and 0 < fuzzy_match_percent < 100
|
||||||
|
|
||||||
|
text_section = next(section for section in unit["sections"] if section["name"] == ".text")
|
||||||
|
# text_size: int = int(text_section["size"])
|
||||||
|
text_section_fuzzy_match_percent: float = text_section["fuzzy_match_percent"]
|
||||||
|
|
||||||
|
if 0 < text_section_fuzzy_match_percent < 100:
|
||||||
|
# fix text section fuzzy match percent
|
||||||
|
text_section["fuzzy_match_percent"] = 100.0
|
||||||
|
|
||||||
|
text_fuzzy_match_percent: float = unit["measures"]["fuzzy_match_percent"]
|
||||||
|
|
||||||
|
assert text_fuzzy_match_percent == fuzzy_match_percent
|
||||||
|
|
||||||
|
functions = unit["functions"]
|
||||||
|
|
||||||
|
total_code: int = int(unit["measures"]["total_code"])
|
||||||
|
matched_code: int = int(unit["measures"]["matched_code"])
|
||||||
|
matched_functions = unit["measures"]["matched_functions"]
|
||||||
|
|
||||||
|
computed_total_code: int = 0
|
||||||
|
computed_matched_code: int = 0
|
||||||
|
computed_matched_functions: int = 0
|
||||||
|
|
||||||
|
duplicate_functions = (
|
||||||
|
"Tim2CalcBufWidth__2",
|
||||||
|
"_ftoi0__2",
|
||||||
|
"ItemGetMain__2",
|
||||||
|
"setD3_CHCR__2",
|
||||||
|
"setD4_CHCR__2",
|
||||||
|
"setD4_CHCR__3",
|
||||||
|
"_fpadd_parts__2",
|
||||||
|
)
|
||||||
|
|
||||||
|
for function in functions:
|
||||||
|
function_size: int = int(function["size"])
|
||||||
|
try:
|
||||||
|
function_fuzzy_match_percent: float = function["fuzzy_match_percent"]
|
||||||
|
except KeyError:
|
||||||
|
# fix known function duplicates
|
||||||
|
if function["name"] in duplicate_functions:
|
||||||
|
function["fuzzy_match_percent"] = 100.0
|
||||||
|
function_fuzzy_match_percent = 100.0
|
||||||
|
matched_code += function_size
|
||||||
|
matched_functions += 1
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
if function_fuzzy_match_percent == 100.0:
|
||||||
|
computed_matched_code += function_size
|
||||||
|
computed_matched_functions += 1
|
||||||
|
|
||||||
|
# fix function fuzzy match percent
|
||||||
|
function["fuzzy_match_percent"] = 100.0
|
||||||
|
|
||||||
|
computed_total_code += function_size
|
||||||
|
|
||||||
|
assert total_code == computed_total_code
|
||||||
|
assert matched_code == computed_matched_code
|
||||||
|
assert matched_functions == computed_matched_functions
|
||||||
|
|
||||||
|
# fix unit measures
|
||||||
|
unit["measures"]["fuzzy_match_percent"] = 100.0
|
||||||
|
unit["measures"]["matched_code"] = unit["measures"]["total_code"]
|
||||||
|
unit["measures"]["matched_code_percent"] = 100.0
|
||||||
|
unit["measures"]["matched_functions"] = unit["measures"]["total_functions"]
|
||||||
|
unit["measures"]["matched_functions_percent"] = 100.0
|
||||||
|
|
||||||
|
|
||||||
|
def fix_report(report_path: Path):
|
||||||
|
report = json.loads(report_path.read_text())
|
||||||
|
|
||||||
|
units: Iterable[Any] = report["units"]
|
||||||
|
|
||||||
|
computed_total_code: int = 0
|
||||||
|
computed_matched_code: int = 0
|
||||||
|
|
||||||
|
computed_total_functions: int = 0
|
||||||
|
computed_matched_functions: int = 0
|
||||||
|
|
||||||
|
total_code: int = int(report["measures"]["total_code"])
|
||||||
|
total_functions: int = report["measures"]["total_functions"]
|
||||||
|
|
||||||
|
for unit in units:
|
||||||
|
# name: str = unit["name"]
|
||||||
|
unit_total_code: int = int(unit["measures"]["total_code"])
|
||||||
|
unit_total_functions: int = unit["measures"]["total_functions"]
|
||||||
|
fuzzy_match_percent: float | None = unit["measures"].get("fuzzy_match_percent")
|
||||||
|
|
||||||
|
if fuzzy_match_percent and 0 < fuzzy_match_percent < 100:
|
||||||
|
fix_unit(unit)
|
||||||
|
|
||||||
|
if fuzzy_match_percent and fuzzy_match_percent > 0:
|
||||||
|
computed_matched_code += unit_total_code
|
||||||
|
computed_matched_functions += unit_total_functions
|
||||||
|
|
||||||
|
computed_total_functions += unit_total_functions
|
||||||
|
computed_total_code += unit_total_code
|
||||||
|
|
||||||
|
assert total_code == computed_total_code
|
||||||
|
assert total_functions == computed_total_functions
|
||||||
|
|
||||||
|
# fix report measures
|
||||||
|
report["measures"]["fuzzy_match_percent"] = 100.0 * computed_matched_code / computed_total_code
|
||||||
|
report["measures"]["matched_code"] = str(computed_matched_code)
|
||||||
|
report["measures"]["matched_code_percent"] = report["measures"]["fuzzy_match_percent"]
|
||||||
|
report["measures"]["matched_functions"] = computed_matched_functions
|
||||||
|
report["measures"]["matched_functions_percent"] = 100.0 * computed_matched_functions / computed_total_functions
|
||||||
|
|
||||||
|
categories = report["categories"]
|
||||||
|
assert len(categories) == 1
|
||||||
|
assert categories[0]["measures"]["total_code"] == report["measures"]["total_code"]
|
||||||
|
assert categories[0]["measures"]["total_units"] == report["measures"]["total_units"]
|
||||||
|
|
||||||
|
categories[0]["measures"]["fuzzy_match_percent"] = report["measures"]["fuzzy_match_percent"]
|
||||||
|
categories[0]["measures"]["matched_code"] = report["measures"]["matched_code"]
|
||||||
|
categories[0]["measures"]["matched_code_percent"] = report["measures"]["matched_code_percent"]
|
||||||
|
categories[0]["measures"]["matched_functions"] = report["measures"]["matched_functions"]
|
||||||
|
categories[0]["measures"]["matched_functions_percent"] = report["measures"]["matched_functions_percent"]
|
||||||
|
|
||||||
|
# /path/to/report.json -> /path/to/report_fixed.json
|
||||||
|
# fixed_report_path = report_path.with_name(f"{report_path.stem}_fixed{report_path.suffix}")
|
||||||
|
# fixed_report_path.write_text(json.dumps(report))
|
||||||
|
report_path.write_text(json.dumps(report))
|
||||||
|
|
||||||
|
print(f"Wrote fixed report to {report_path}")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
class ArgsProtocol(Protocol):
|
||||||
|
report_path: Path
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="fixes objdiff report")
|
||||||
|
parser.add_argument("report_path", metavar="report-path", type=Path, help="path to the report generated by objdiff")
|
||||||
|
|
||||||
|
args = cast(ArgsProtocol, parser.parse_args())
|
||||||
|
|
||||||
|
fix_report(args.report_path)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import re
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--language", required=True, choices=["us", "eu"])
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.language == "us":
|
||||||
|
map_path = Path("config/us/build/SLUS_203.88.map")
|
||||||
|
else:
|
||||||
|
map_path = Path("config/eu/build/SLES_508.21.map")
|
||||||
|
|
||||||
|
with open(map_path, mode="r") as fh:
|
||||||
|
for n, line in enumerate(fh):
|
||||||
|
line = line.rstrip("\n")
|
||||||
|
if match := re.match(r"^\s*0x([0-9a-fA-F]+)\s+[^ ]+?([0-9a-fA-F]{6,8})\s*$", line):
|
||||||
|
addr = match.group(1)
|
||||||
|
label = match.group(2)
|
||||||
|
if addr.upper() != label.upper():
|
||||||
|
print(f"{map_path}:{n+1} {line}")
|
||||||
|
return
|
||||||
|
|
||||||
|
print("no mismatches found")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,288 @@
|
|||||||
|
# pyright: reportUnknownMemberType=false
|
||||||
|
|
||||||
|
import re
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
from typing import cast
|
||||||
|
from pathlib import Path
|
||||||
|
from elftools.elf.elffile import ELFFile
|
||||||
|
from elftools.elf.sections import SymbolTableSection
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
matches variable declaration:
|
||||||
|
/* SECTION ADDRESS */ VAR_TYPE NAME[NUMEL];
|
||||||
|
"""
|
||||||
|
re_glob = re.compile(
|
||||||
|
r"^/\* (?P<section>.*?) (?P<address>.*?) \*/ (?P<var_type>[^(]*) (?P<name>.*?)(?:\[(?P<numel>.*?)\])?;"
|
||||||
|
)
|
||||||
|
|
||||||
|
"""
|
||||||
|
matches structs (or unions) with no typedef:
|
||||||
|
struct NAME { // SIZE
|
||||||
|
...
|
||||||
|
};
|
||||||
|
"""
|
||||||
|
re_struct = re.compile(
|
||||||
|
r"^(?:struct|union) (?P<name>.*?) \{ // (?P<size>0x[0-9a-f]+)\n.*?^\};", flags=re.MULTILINE | re.DOTALL
|
||||||
|
)
|
||||||
|
|
||||||
|
"""
|
||||||
|
matches structs (or unions) with typedef:
|
||||||
|
typedef struct { // SIZE
|
||||||
|
...
|
||||||
|
} NAME;
|
||||||
|
"""
|
||||||
|
re_typedef_struct = re.compile(
|
||||||
|
r"^typedef (?:struct|union) \{ // (?P<size>0x[0-9a-f]+)\n.*?^\} (?P<name>.*?);", flags=re.MULTILINE | re.DOTALL
|
||||||
|
)
|
||||||
|
|
||||||
|
sizes: dict[str, int] = {
|
||||||
|
"char": 1,
|
||||||
|
"u_char": 1,
|
||||||
|
"short": 2,
|
||||||
|
"short int": 2,
|
||||||
|
"u_short": 2,
|
||||||
|
"int": 4,
|
||||||
|
"u_int": 4,
|
||||||
|
"float": 4,
|
||||||
|
"u_long128": 8,
|
||||||
|
"sceVu0FMATRIX": 4 * 4 * 4,
|
||||||
|
"sceVu0FVECTOR": 4 * 4,
|
||||||
|
"sceSifClientData": 0x2C,
|
||||||
|
}
|
||||||
|
|
||||||
|
command_script_keywords = (
|
||||||
|
"VERSION",
|
||||||
|
"SECTIONS",
|
||||||
|
"ABSOLUTE",
|
||||||
|
"LOADADDR",
|
||||||
|
"ALIGN",
|
||||||
|
"DEFINED",
|
||||||
|
"NEXT",
|
||||||
|
"SIZEOF",
|
||||||
|
"SIZEOF_HEADERS",
|
||||||
|
"MAX",
|
||||||
|
"MIN",
|
||||||
|
"PHDRS",
|
||||||
|
"CREATE_OBJECT_SYMBOLS",
|
||||||
|
"BYTE",
|
||||||
|
"SHORT",
|
||||||
|
"LONG",
|
||||||
|
"SQUAD",
|
||||||
|
"FILL",
|
||||||
|
"BLOCK",
|
||||||
|
"NOLOAD",
|
||||||
|
"AT",
|
||||||
|
"OVERLAY",
|
||||||
|
"NOCROSSREFS",
|
||||||
|
"PT_NULL",
|
||||||
|
"PT_LOAD",
|
||||||
|
"PT_DYNAMIC",
|
||||||
|
"PT_INTERP",
|
||||||
|
"PT_NOTE",
|
||||||
|
"PT_SHLIB",
|
||||||
|
"PT_PHDR",
|
||||||
|
"ENTRY",
|
||||||
|
"FLOAT",
|
||||||
|
"NOFLOAT",
|
||||||
|
"FORCE_COMMON_ALLOCATION",
|
||||||
|
"INCLUDE",
|
||||||
|
"INPUT",
|
||||||
|
"GROUP",
|
||||||
|
"OUTPUT",
|
||||||
|
"OUTPUT_ARCH",
|
||||||
|
"OUTPUT_FORMAT",
|
||||||
|
"SEARCH_DIR",
|
||||||
|
"STARTUP",
|
||||||
|
"TARGET",
|
||||||
|
"NOCROSSREFS",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class GlobalVarLineMatch:
|
||||||
|
max_section_len: int = 0
|
||||||
|
max_address_len: int = 0
|
||||||
|
max_var_type_len: int = 0
|
||||||
|
max_name_len: int = 0
|
||||||
|
max_numel_len: int = 0
|
||||||
|
|
||||||
|
_name_cache: list[str] = []
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_unique_name(cls, name: str):
|
||||||
|
i = 1
|
||||||
|
unique_name = f"{name}__local_{i}"
|
||||||
|
while unique_name in cls._name_cache:
|
||||||
|
i += 1
|
||||||
|
unique_name = f"{name}__local_{i}"
|
||||||
|
cls._name_cache.append(unique_name)
|
||||||
|
return unique_name
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
symtab: SymbolTableSection,
|
||||||
|
/,
|
||||||
|
*,
|
||||||
|
section: str,
|
||||||
|
address: str | int,
|
||||||
|
var_type: str,
|
||||||
|
name: str,
|
||||||
|
numel: str | int | None = None,
|
||||||
|
):
|
||||||
|
self.symtab: SymbolTableSection = symtab
|
||||||
|
|
||||||
|
self.section: str = section
|
||||||
|
self.address: int = address if isinstance(address, int) else int(address, 16)
|
||||||
|
self.var_type: str = var_type
|
||||||
|
self.name: str = name
|
||||||
|
self.numel: int
|
||||||
|
|
||||||
|
while self.name.startswith("*"):
|
||||||
|
self.name = self.name[1:]
|
||||||
|
self.var_type += "*"
|
||||||
|
|
||||||
|
# resolve function pointers (e.g., 'void (*SpecialEventInitTbl[0])...')
|
||||||
|
if match := re.match(r"\(\*(.*?)\[.*?\]\).*", self.name):
|
||||||
|
self.name = match.group(1)
|
||||||
|
|
||||||
|
self.name = self.name.replace("*", "")
|
||||||
|
|
||||||
|
if numel is not None:
|
||||||
|
if isinstance(numel, int):
|
||||||
|
self.numel = numel
|
||||||
|
else:
|
||||||
|
prod_numel = 1
|
||||||
|
numels = numel.split("][")
|
||||||
|
for n in numels:
|
||||||
|
prod_numel *= int(n)
|
||||||
|
self.numel = prod_numel
|
||||||
|
|
||||||
|
if numel is None:
|
||||||
|
self.numel = 1
|
||||||
|
|
||||||
|
# get symbol
|
||||||
|
symbol = self.symtab.get_symbol_by_name(self.name)
|
||||||
|
|
||||||
|
assert isinstance(symbol, list)
|
||||||
|
|
||||||
|
symbol = next(
|
||||||
|
(sym for sym in symbol if sym.name == self.name and sym.entry["st_value"] == self.address),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert symbol
|
||||||
|
|
||||||
|
self.symbol = symbol
|
||||||
|
|
||||||
|
if not self.is_global:
|
||||||
|
self.name = self._get_unique_name(self.name)
|
||||||
|
|
||||||
|
escaped_name_len = len(str(self.name))
|
||||||
|
if self.name in command_script_keywords:
|
||||||
|
escaped_name_len += 2
|
||||||
|
|
||||||
|
GlobalVarLineMatch.max_section_len = max(GlobalVarLineMatch.max_section_len, len(str(self.section)))
|
||||||
|
GlobalVarLineMatch.max_address_len = max(GlobalVarLineMatch.max_address_len, len(str(self.address)))
|
||||||
|
GlobalVarLineMatch.max_var_type_len = max(GlobalVarLineMatch.max_var_type_len, len(str(self.var_type)))
|
||||||
|
GlobalVarLineMatch.max_name_len = max(GlobalVarLineMatch.max_name_len, escaped_name_len)
|
||||||
|
GlobalVarLineMatch.max_numel_len = max(GlobalVarLineMatch.max_numel_len, len(str(self.numel)))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_global(self):
|
||||||
|
return cast(str, self.symbol["st_info"]["bind"]) == "STB_GLOBAL"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_hidden(self):
|
||||||
|
return cast(str, self.symbol["st_other"]["visibility"]) == "STV_HIDDEN"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def size(self):
|
||||||
|
size = cast(int, self.symbol["st_size"])
|
||||||
|
if size == 0:
|
||||||
|
if "*" in self.var_type:
|
||||||
|
size = 4
|
||||||
|
elif self.var_type in sizes:
|
||||||
|
size = sizes[self.var_type] * self.numel
|
||||||
|
return size
|
||||||
|
|
||||||
|
def to_string(self, as_linker_command_file: bool):
|
||||||
|
name = self.name if self.name not in command_script_keywords else f'"{self.name}"'
|
||||||
|
cls_str = f"{name:{GlobalVarLineMatch.max_name_len}s} = 0x{self.address:08x};"
|
||||||
|
|
||||||
|
if not as_linker_command_file:
|
||||||
|
if self.size > 0:
|
||||||
|
cls_str = f"{cls_str} // size:0x{self.size:x}"
|
||||||
|
else:
|
||||||
|
cls_str = f"{cls_str} //0 {self.var_type} * {self.numel}"
|
||||||
|
|
||||||
|
# cls_str += f" bind:{'global' if self.is_global else 'local'}"
|
||||||
|
# cls_str += f" visibility:{'hidden' if self.is_hidden else 'visible'}"
|
||||||
|
|
||||||
|
return cls_str
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.to_string(as_linker_command_file=False)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_globals(elf_path: Path, globals_path: Path, types_path: Path, as_linker_command_file: bool):
|
||||||
|
with open(elf_path, mode="rb") as fh:
|
||||||
|
elf = ELFFile(fh)
|
||||||
|
|
||||||
|
# Find the symbol table.
|
||||||
|
symtab = elf.get_section_by_name(".symtab")
|
||||||
|
assert isinstance(symtab, SymbolTableSection)
|
||||||
|
|
||||||
|
with open(types_path, mode="r") as f:
|
||||||
|
types_data = f.read()
|
||||||
|
|
||||||
|
for struct_type, size_hex_str in re_struct.findall(types_data):
|
||||||
|
struct_type = cast(str, struct_type)
|
||||||
|
struct_size = int(cast(str, size_hex_str), 16)
|
||||||
|
# assert not (struct_type in sizes and sizes[struct_type] != struct_size)
|
||||||
|
sizes[struct_type] = struct_size
|
||||||
|
|
||||||
|
for size_hex_str, struct_type in re_typedef_struct.findall(types_data):
|
||||||
|
struct_type = cast(str, struct_type)
|
||||||
|
struct_size = int(cast(str, size_hex_str), 16)
|
||||||
|
# assert not (struct_type in sizes and sizes[struct_type] != struct_size), (
|
||||||
|
# struct_type,
|
||||||
|
# sizes[struct_type],
|
||||||
|
# struct_size,
|
||||||
|
# )
|
||||||
|
sizes[struct_type] = struct_size
|
||||||
|
|
||||||
|
if "tagSE_WRK" in sizes:
|
||||||
|
sizes["SE_WRK"] = sizes["tagSE_WRK"]
|
||||||
|
|
||||||
|
with open(globals_path, mode="r") as f:
|
||||||
|
lines = [line.strip() for line in f.readlines() if line.startswith("/*") and line.strip().endswith(";")]
|
||||||
|
|
||||||
|
matches = [GlobalVarLineMatch(symtab, **match.groupdict()) for line in lines if (match := re_glob.match(line))]
|
||||||
|
matches.sort(key=lambda match: match.address)
|
||||||
|
|
||||||
|
for match in matches:
|
||||||
|
print(match.to_string(as_linker_command_file=as_linker_command_file))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--language", required=True, choices=["us", "eu"])
|
||||||
|
parser.add_argument("--as-linker-command-file", action="store_true")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.language == "us":
|
||||||
|
elf_path = Path("config/us/SLUS_203.88")
|
||||||
|
globals_path = Path("ccc/SLUS_203.88/globals.h")
|
||||||
|
types_path = Path("ccc/SLUS_203.88/types.h")
|
||||||
|
else:
|
||||||
|
elf_path = Path("config/eu/SLES_508.21")
|
||||||
|
globals_path = Path("ccc/SLES_508.21/globals.h")
|
||||||
|
types_path = Path("ccc/SLES_508.21/types.h")
|
||||||
|
|
||||||
|
parse_globals(elf_path, globals_path, types_path, args.as_linker_command_file)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,378 @@
|
|||||||
|
# pyright: reportUnknownMemberType=false
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import re
|
||||||
|
import json
|
||||||
|
import argparse
|
||||||
|
import itertools
|
||||||
|
|
||||||
|
from typing import Protocol, TextIO, cast
|
||||||
|
from pathlib import Path
|
||||||
|
from elftools.elf.elffile import ELFFile
|
||||||
|
from elftools.elf.sections import SymbolTableSection, Symbol
|
||||||
|
|
||||||
|
import ccc_json_v7
|
||||||
|
|
||||||
|
Range = tuple[int, int]
|
||||||
|
|
||||||
|
command_script_keywords = (
|
||||||
|
"VERSION",
|
||||||
|
"SECTIONS",
|
||||||
|
"ABSOLUTE",
|
||||||
|
"LOADADDR",
|
||||||
|
"ALIGN",
|
||||||
|
"DEFINED",
|
||||||
|
"NEXT",
|
||||||
|
"SIZEOF",
|
||||||
|
"SIZEOF_HEADERS",
|
||||||
|
"MAX",
|
||||||
|
"MIN",
|
||||||
|
"PHDRS",
|
||||||
|
"CREATE_OBJECT_SYMBOLS",
|
||||||
|
"BYTE",
|
||||||
|
"SHORT",
|
||||||
|
"LONG",
|
||||||
|
"SQUAD",
|
||||||
|
"FILL",
|
||||||
|
"BLOCK",
|
||||||
|
"NOLOAD",
|
||||||
|
"AT",
|
||||||
|
"OVERLAY",
|
||||||
|
"NOCROSSREFS",
|
||||||
|
"PT_NULL",
|
||||||
|
"PT_LOAD",
|
||||||
|
"PT_DYNAMIC",
|
||||||
|
"PT_INTERP",
|
||||||
|
"PT_NOTE",
|
||||||
|
"PT_SHLIB",
|
||||||
|
"PT_PHDR",
|
||||||
|
"ENTRY",
|
||||||
|
"FLOAT",
|
||||||
|
"NOFLOAT",
|
||||||
|
"FORCE_COMMON_ALLOCATION",
|
||||||
|
"INCLUDE",
|
||||||
|
"INPUT",
|
||||||
|
"GROUP",
|
||||||
|
"OUTPUT",
|
||||||
|
"OUTPUT_ARCH",
|
||||||
|
"OUTPUT_FORMAT",
|
||||||
|
"SEARCH_DIR",
|
||||||
|
"STARTUP",
|
||||||
|
"TARGET",
|
||||||
|
"NOCROSSREFS",
|
||||||
|
)
|
||||||
|
|
||||||
|
skip_symbols = (
|
||||||
|
"_fbss",
|
||||||
|
"_gp",
|
||||||
|
)
|
||||||
|
|
||||||
|
size_exceptions = {
|
||||||
|
"dorcon": 0x1C,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def parse_types(ccc_model_v7: ccc_json_v7.CCCJSONv7Model):
|
||||||
|
type_map: dict[str, int] = {}
|
||||||
|
|
||||||
|
for n, dt in enumerate(ccc_model_v7.deduplicated_types):
|
||||||
|
if dt.descriptor == "builtin":
|
||||||
|
assert dt.name and dt.name not in type_map
|
||||||
|
assert dt.class_ is not None
|
||||||
|
size_bits = int(dt.class_.split("-", maxsplit=1)[0])
|
||||||
|
assert size_bits % 8 == 0
|
||||||
|
type_map[dt.name] = size_bits // 8
|
||||||
|
|
||||||
|
elif dt.descriptor == "type_name":
|
||||||
|
assert dt.name is not None
|
||||||
|
assert dt.type_name is not None
|
||||||
|
if dt.name in type_map:
|
||||||
|
if dt.size_bits:
|
||||||
|
assert type_map[dt.name] == dt.size_bits // 8
|
||||||
|
if dt.name == dt.type_name == "void":
|
||||||
|
type_map["void"] = type_map["int"]
|
||||||
|
continue
|
||||||
|
assert dt.type_name in type_map, (n, dt.type_name)
|
||||||
|
type_map[dt.name] = type_map[dt.type_name]
|
||||||
|
|
||||||
|
elif dt.descriptor == "pointer":
|
||||||
|
assert dt.name is not None
|
||||||
|
assert dt.value_type is not None
|
||||||
|
if dt.value_type.descriptor == "function_type":
|
||||||
|
assert dt.name not in type_map
|
||||||
|
type_map[dt.name] = type_map["int"]
|
||||||
|
elif dt.value_type.descriptor == "type_name":
|
||||||
|
assert dt.value_type.type_name
|
||||||
|
assert dt.value_type.type_name in type_map
|
||||||
|
type_map[dt.name] = type_map[dt.value_type.type_name]
|
||||||
|
|
||||||
|
elif dt.descriptor == "struct":
|
||||||
|
assert dt.name is not None
|
||||||
|
if not dt.conflict:
|
||||||
|
assert dt.name not in type_map, n
|
||||||
|
else:
|
||||||
|
if dt.name in type_map:
|
||||||
|
continue
|
||||||
|
assert dt.size_bits is not None
|
||||||
|
assert dt.size_bits % 8 == 0
|
||||||
|
type_map[dt.name] = dt.size_bits // 8
|
||||||
|
|
||||||
|
elif dt.descriptor == "array":
|
||||||
|
assert dt.name is not None
|
||||||
|
element_count = 1
|
||||||
|
element_type = dt.element_type
|
||||||
|
type_name = None
|
||||||
|
while element_type:
|
||||||
|
if element_type.element_count is not None:
|
||||||
|
element_count *= element_type.element_count
|
||||||
|
if element_type.type_name is not None:
|
||||||
|
type_name = element_type.type_name
|
||||||
|
assert type_name in type_map
|
||||||
|
element_count *= type_map[type_name]
|
||||||
|
element_type = element_type.element_type
|
||||||
|
assert type_name and type_name in type_map, n
|
||||||
|
type_map[dt.name] = type_map[type_name] * element_count
|
||||||
|
|
||||||
|
elif dt.descriptor == "enum":
|
||||||
|
if dt.name:
|
||||||
|
if not dt.conflict:
|
||||||
|
assert dt.name not in type_map, n
|
||||||
|
type_map[dt.name] = type_map["int"]
|
||||||
|
|
||||||
|
elif dt.descriptor == "union":
|
||||||
|
assert dt.name
|
||||||
|
assert dt.size_bits
|
||||||
|
assert dt.size_bits % 8 == 0
|
||||||
|
type_map[dt.name] = dt.size_bits // 8
|
||||||
|
|
||||||
|
else:
|
||||||
|
assert False, f"unknown {n}"
|
||||||
|
|
||||||
|
return type_map
|
||||||
|
|
||||||
|
|
||||||
|
def in_range(ranges: list[Range], address: int):
|
||||||
|
if not ranges:
|
||||||
|
return True
|
||||||
|
|
||||||
|
in_range = any((ra[0] <= address <= ra[1]) for ra in ranges)
|
||||||
|
|
||||||
|
return in_range
|
||||||
|
|
||||||
|
|
||||||
|
def parse_ccc_model_v7(ccc_model_v7: ccc_json_v7.CCCJSONv7Model, ranges: list[Range]):
|
||||||
|
type_sizes = parse_types(ccc_model_v7)
|
||||||
|
|
||||||
|
if "pointer" not in type_sizes:
|
||||||
|
type_sizes["pointer"] = type_sizes["int"]
|
||||||
|
|
||||||
|
static_locals: list[ccc_json_v7.Local] = []
|
||||||
|
global_vars: list[ccc_json_v7.Global] = []
|
||||||
|
|
||||||
|
for file in ccc_model_v7.files:
|
||||||
|
for global_var in file.globals:
|
||||||
|
assert global_var.storage.global_address
|
||||||
|
if in_range(ranges, global_var.storage.global_address):
|
||||||
|
global_vars.append(global_var)
|
||||||
|
|
||||||
|
for function in file.functions:
|
||||||
|
for local in function.locals:
|
||||||
|
if local.storage_class == "static":
|
||||||
|
assert local.storage.global_address
|
||||||
|
if in_range(ranges, local.storage.global_address):
|
||||||
|
static_locals.append(local)
|
||||||
|
|
||||||
|
return type_sizes, global_vars, static_locals
|
||||||
|
|
||||||
|
|
||||||
|
class SymbolWithNoNameException(Exception): ...
|
||||||
|
|
||||||
|
|
||||||
|
class ParsedSymbol:
|
||||||
|
_name_map: dict[str, list[ParsedSymbol]] = {}
|
||||||
|
_max_name_len: int = 0
|
||||||
|
|
||||||
|
def __init__(self, symtab: SymbolTableSection, symbol: Symbol) -> None:
|
||||||
|
self.symtab = symtab
|
||||||
|
self.symbol = symbol
|
||||||
|
|
||||||
|
if not self.name:
|
||||||
|
raise SymbolWithNoNameException
|
||||||
|
|
||||||
|
if self.name not in ParsedSymbol._name_map:
|
||||||
|
ParsedSymbol._name_map[self.name] = []
|
||||||
|
|
||||||
|
ParsedSymbol._name_map[self.name].append(self)
|
||||||
|
ParsedSymbol._max_name_len = max(ParsedSymbol._max_name_len, len(self.name))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self) -> str:
|
||||||
|
return re.sub(r"^(.*?)(\.\d+)?$", r"\1", self.symbol.name)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def size(self) -> int:
|
||||||
|
return cast(int, self.symbol["st_size"])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def address(self) -> int:
|
||||||
|
return cast(int, self.symbol.entry["st_value"])
|
||||||
|
|
||||||
|
def in_range(self, range: Range):
|
||||||
|
return range[0] <= self.address <= range[1]
|
||||||
|
|
||||||
|
def to_undefined_syms(self) -> str:
|
||||||
|
homonyms = ParsedSymbol._name_map[self.name]
|
||||||
|
assert len(homonyms) > 0
|
||||||
|
if len(homonyms) == 1:
|
||||||
|
assert homonyms[0] == self
|
||||||
|
name = self.name
|
||||||
|
else:
|
||||||
|
idx = homonyms.index(self)
|
||||||
|
name = f"{self.name}__local_{idx + 1}"
|
||||||
|
|
||||||
|
name = name if name not in command_script_keywords else f'"{name}"'
|
||||||
|
|
||||||
|
# name_len_fmt = ParsedSymbol._max_name_len + len("__local_9999")
|
||||||
|
name_len_fmt = 40
|
||||||
|
|
||||||
|
return f"{name:{name_len_fmt}s} = 0x{self.address:08x};"
|
||||||
|
|
||||||
|
def to_symbol_addrs(
|
||||||
|
self,
|
||||||
|
type_sizes: dict[str, int],
|
||||||
|
global_vars: list[ccc_json_v7.Global],
|
||||||
|
static_locals: list[ccc_json_v7.Local],
|
||||||
|
) -> str:
|
||||||
|
homonyms = ParsedSymbol._name_map[self.name]
|
||||||
|
assert len(homonyms) > 0
|
||||||
|
if len(homonyms) == 1:
|
||||||
|
assert homonyms[0] == self
|
||||||
|
name = self.name
|
||||||
|
else:
|
||||||
|
idx = homonyms.index(self)
|
||||||
|
name = f"{self.name}__local_{idx + 1}"
|
||||||
|
|
||||||
|
# name_len_fmt = ParsedSymbol._max_name_len + len("__local_9999")
|
||||||
|
name_len_fmt = 40
|
||||||
|
|
||||||
|
size = size_exceptions.get(self.name, self.size)
|
||||||
|
if size == 0:
|
||||||
|
var = next(
|
||||||
|
(global_ for global_ in global_vars if global_.storage.global_address == self.address), None
|
||||||
|
) or next((local for local in static_locals if local.storage.global_address == self.address), None)
|
||||||
|
|
||||||
|
if not var:
|
||||||
|
print(f"cannot find {self.name} with size 0 in json")
|
||||||
|
else:
|
||||||
|
element_count, type_name = var.parsed_size
|
||||||
|
type_size = type_sizes.get(type_name)
|
||||||
|
assert type_size is not None, type_name
|
||||||
|
size = element_count * type_size
|
||||||
|
|
||||||
|
if not size:
|
||||||
|
print(f"size of {self.name} is also 0 using json")
|
||||||
|
|
||||||
|
size_str = f"size:0x{size:x}" if size else ""
|
||||||
|
|
||||||
|
return f"{name:{name_len_fmt}s} = 0x{self.address:08x}; // {size_str}"
|
||||||
|
|
||||||
|
|
||||||
|
def parse_symbols_safe(elf_path: Path, dest_path: Path, json_path: Path, ranges: list[Range]):
|
||||||
|
if not dest_path.is_dir():
|
||||||
|
raise RuntimeError(f"{dest_path} is not a directory")
|
||||||
|
|
||||||
|
symbol_addrs_path = dest_path / "symbols_addrs.txt"
|
||||||
|
undefined_syms_path = dest_path / "undefined_syms.txt"
|
||||||
|
|
||||||
|
if symbol_addrs_path.exists() or undefined_syms_path.exists():
|
||||||
|
raise RuntimeError("symbols_addrs.txt or undefined_syms.txt already exist in dest folder")
|
||||||
|
|
||||||
|
with open(elf_path, mode="rb") as elf_fh, open(json_path, mode="r") as json_fh:
|
||||||
|
elf = ELFFile(elf_fh)
|
||||||
|
|
||||||
|
json_data = json.load(json_fh)
|
||||||
|
ccc_model_v7 = ccc_json_v7.CCCJSONv7Model.model_validate(json_data)
|
||||||
|
type_sizes, global_vars, static_locals = parse_ccc_model_v7(ccc_model_v7, ranges)
|
||||||
|
|
||||||
|
with open(symbol_addrs_path, mode="w") as symbol_addrs, open(undefined_syms_path, mode="w") as undefined_syms:
|
||||||
|
parse_symbols(elf, symbol_addrs, undefined_syms, ranges, type_sizes, global_vars, static_locals)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_symbols(
|
||||||
|
elf: ELFFile,
|
||||||
|
symbol_addrs: TextIO,
|
||||||
|
undefined_syms: TextIO,
|
||||||
|
ranges: list[Range],
|
||||||
|
type_sizes: dict[str, int],
|
||||||
|
global_vars: list[ccc_json_v7.Global],
|
||||||
|
static_locals: list[ccc_json_v7.Local],
|
||||||
|
):
|
||||||
|
# find symbol table
|
||||||
|
symtab = elf.get_section_by_name(".symtab")
|
||||||
|
assert isinstance(symtab, SymbolTableSection)
|
||||||
|
|
||||||
|
parsed_symbols: list[ParsedSymbol] = []
|
||||||
|
|
||||||
|
for symbol in symtab.iter_symbols():
|
||||||
|
try:
|
||||||
|
parsed_symbol = ParsedSymbol(symtab, symbol)
|
||||||
|
if parsed_symbol.name in skip_symbols:
|
||||||
|
continue
|
||||||
|
parsed_symbols.append(parsed_symbol)
|
||||||
|
except SymbolWithNoNameException:
|
||||||
|
pass
|
||||||
|
|
||||||
|
parsed_symbols.sort(key=lambda x: x.address)
|
||||||
|
|
||||||
|
for parsed_symbol in parsed_symbols:
|
||||||
|
if ranges:
|
||||||
|
in_range = any(parsed_symbol.in_range(ra) for ra in ranges)
|
||||||
|
if not in_range:
|
||||||
|
continue
|
||||||
|
|
||||||
|
parsed_symbol.address
|
||||||
|
symbol_addrs.write(parsed_symbol.to_symbol_addrs(type_sizes, global_vars, static_locals))
|
||||||
|
symbol_addrs.write("\n")
|
||||||
|
|
||||||
|
undefined_syms.write(parsed_symbol.to_undefined_syms())
|
||||||
|
undefined_syms.write("\n")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
class ArgsProtocol(Protocol):
|
||||||
|
elf_path: Path
|
||||||
|
dest_path: Path
|
||||||
|
json_path: Path
|
||||||
|
ranges: list[Range]
|
||||||
|
|
||||||
|
def range_type(arg: str) -> Range:
|
||||||
|
if m := re.match(r"^([0-9a-f]+)-([0-9a-f]+)$", arg):
|
||||||
|
range_start, range_end = int(m.group(1), 16), int(m.group(2), 16)
|
||||||
|
if not (range_end > range_start):
|
||||||
|
raise argparse.ArgumentTypeError("non monotonic range")
|
||||||
|
return range_start, range_end
|
||||||
|
raise argparse.ArgumentTypeError("invalid range")
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("elf_path", metavar="ELF", type=Path, help="path to ELF file")
|
||||||
|
parser.add_argument("--json", dest="json_path", type=Path, help="path to CCC json (v7)")
|
||||||
|
parser.add_argument(
|
||||||
|
"--dest",
|
||||||
|
dest="dest_path",
|
||||||
|
type=Path,
|
||||||
|
required=True,
|
||||||
|
help="folder where symbol_addrs.txt and undefined_syms.txt will be created "
|
||||||
|
"(existing files will not be overwritten)",
|
||||||
|
)
|
||||||
|
parser.add_argument("--range", action="append", dest="ranges", nargs="+", type=range_type)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
args.ranges = list(itertools.chain(*args.ranges))
|
||||||
|
args = cast(ArgsProtocol, args)
|
||||||
|
|
||||||
|
parse_symbols_safe(args.elf_path, args.dest_path, args.json_path, args.ranges)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,414 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Literal, Optional
|
||||||
|
from pydantic import RootModel, BaseModel, Field
|
||||||
|
|
||||||
|
|
||||||
|
class Compiler(BaseModel):
|
||||||
|
name: str
|
||||||
|
asm_function_macro: str = Field("glabel", description="")
|
||||||
|
asm_function_alt_macro: str = Field("glabel", description="")
|
||||||
|
asm_jtbl_label_macro: str = Field("glabel", description="")
|
||||||
|
asm_data_macro: str = Field("glabel", description="")
|
||||||
|
asm_end_label: str = Field("", description="")
|
||||||
|
c_newline: str = Field("\n", description="")
|
||||||
|
asm_inc_header: str = Field("", description="")
|
||||||
|
include_macro_inc: bool = Field(True, description="")
|
||||||
|
asm_emit_size_directive: Optional[bool] = Field(None, description="")
|
||||||
|
|
||||||
|
|
||||||
|
class SplatOpts(BaseModel):
|
||||||
|
# Debug / logging
|
||||||
|
verbose: Optional[bool] = Field(None, description="Verbose")
|
||||||
|
dump_symbols: Optional[bool] = Field(None, description="Dump symbols")
|
||||||
|
modes: Optional[list[str]] = Field(None, description="modes")
|
||||||
|
|
||||||
|
# Project configuration
|
||||||
|
base_path: Path = Field(
|
||||||
|
None, description="Determines the base path of the project. Everything is relative to this path"
|
||||||
|
)
|
||||||
|
target_path: Optional[Path] = Field(None, description="Determines the path to the target binary")
|
||||||
|
elf_path: Optional[Path] = Field(None, description="Path to the final elf target")
|
||||||
|
platform: Optional[str] = Field(None, description="Determines the platform of the target binary")
|
||||||
|
compiler: Optional[Compiler | str] = Field(
|
||||||
|
None, description="Determines the compiler used to compile the target binary"
|
||||||
|
)
|
||||||
|
endianness: Optional[Literal["big", "little"]] = Field(
|
||||||
|
None, description="Determines the endianness of the target binary"
|
||||||
|
)
|
||||||
|
section_order: Optional[list[str]] = Field(
|
||||||
|
None,
|
||||||
|
description="Determines the default section order of the target binary. This can be overridden per-segment",
|
||||||
|
)
|
||||||
|
generated_c_preamble: Optional[str] = Field(
|
||||||
|
None, description="Determines the code that is inserted by default in generated .c files"
|
||||||
|
)
|
||||||
|
generated_s_preamble: Optional[str] = Field(
|
||||||
|
None, description="Determines the code that is inserted by default in generated .s files"
|
||||||
|
)
|
||||||
|
use_o_as_suffix: Optional[bool] = Field(
|
||||||
|
None, description="Determines whether to use .o as the suffix for all binary files?... TODO document"
|
||||||
|
)
|
||||||
|
gp_value: Optional[int] = Field(
|
||||||
|
None, description="the value of the $gp register to correctly calculate offset to %gp_rel relocs"
|
||||||
|
)
|
||||||
|
check_consecutive_segment_types: Optional[bool] = Field(
|
||||||
|
None, description="Checks and errors if there are any non consecutive segment types"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Paths
|
||||||
|
asset_path: Optional[Path] = Field(None, description="")
|
||||||
|
symbol_addrs_paths: Optional[list[Path]] = Field(
|
||||||
|
None,
|
||||||
|
description="""Determines the path to the symbol addresses file(s)
|
||||||
|
A symbol_addrs file is to be updated/curated manually and contains addresses of symbols
|
||||||
|
as well as optional metadata such as rom address, type, and more
|
||||||
|
|
||||||
|
It's possible to use more than one file by supplying a list instead of a string""",
|
||||||
|
)
|
||||||
|
reloc_addrs_paths: Optional[list[Path]] = Field(None, description="")
|
||||||
|
build_path: Optional[Path] = Field(None, description="Determines the path to the project build directory")
|
||||||
|
src_path: Optional[Path] = Field(None, description="Determines the path to the source code directory")
|
||||||
|
asm_path: Optional[Path] = Field(None, description="Determines the path to the asm code directory")
|
||||||
|
data_path: Optional[Path] = Field(None, description="Determines the path to the asm data directory")
|
||||||
|
nonmatchings_path: Optional[Path] = Field(None, description="Determines the path to the asm nonmatchings directory")
|
||||||
|
cache_path: Optional[Path] = Field(
|
||||||
|
None, description="Determines the path to the cache file (used when supplied --use-cache via the CLI)"
|
||||||
|
)
|
||||||
|
hasm_in_src_path: Optional[bool] = Field(
|
||||||
|
None, description="Tells splat to consider `hasm` files to be relative to `src_path` instead of `asm_path`."
|
||||||
|
)
|
||||||
|
create_undefined_funcs_auto: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Determines whether to create an automatically-generated undefined functions fil. "
|
||||||
|
"This file stores all functions that are referenced in the code but are not defined as seen by splat",
|
||||||
|
)
|
||||||
|
undefined_funcs_auto_path: Optional[Path] = Field(
|
||||||
|
None, description="Determines the path to the undefined_funcs_auto file"
|
||||||
|
)
|
||||||
|
|
||||||
|
create_undefined_syms_auto: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Determines whether to create an automatically-generated undefined symbols file. "
|
||||||
|
"This file stores all symbols that are referenced in the code but are not defined as seen by splat",
|
||||||
|
)
|
||||||
|
undefined_syms_auto_path: Optional[Path] = Field(
|
||||||
|
None, description="Determines the path to the undefined_symbols_auto file"
|
||||||
|
)
|
||||||
|
|
||||||
|
extensions_path: Optional[Path] = Field(
|
||||||
|
None, description="Determines the path in which to search for custom splat extensions"
|
||||||
|
)
|
||||||
|
|
||||||
|
lib_path: Optional[Path] = Field(
|
||||||
|
None, description="Determines the path to library files that are to be linked into the target binary"
|
||||||
|
)
|
||||||
|
|
||||||
|
# TODO document
|
||||||
|
elf_section_list_path: Optional[Path] = Field(None, description="")
|
||||||
|
|
||||||
|
# Linker script
|
||||||
|
subalign: Optional[int] = Field(
|
||||||
|
None, description="Determines the default subalign value to be specified in the generated linker script"
|
||||||
|
)
|
||||||
|
|
||||||
|
auto_all_sections: Optional[list[str]] = Field(
|
||||||
|
None,
|
||||||
|
description="The following option determines whether to automatically configure the linker script to link "
|
||||||
|
'against specified sections for all "base" (asm/c) files when the yaml doesn\'t have manual configurations '
|
||||||
|
"for these sections.",
|
||||||
|
)
|
||||||
|
ld_script_path: Optional[Path] = Field(
|
||||||
|
None, description="Determines the desired path to the linker script that splat will generate"
|
||||||
|
)
|
||||||
|
ld_symbol_header_path: Optional[Path] = Field(
|
||||||
|
None,
|
||||||
|
description="Determines the desired path to the linker symbol header, which exposes externed definitions "
|
||||||
|
"for all segment ram/rom start/end locations",
|
||||||
|
)
|
||||||
|
ld_discard_section: Optional[bool] = Field(
|
||||||
|
None, description="Determines whether to add a discard section with a wildcard to the linker script"
|
||||||
|
)
|
||||||
|
ld_sections_allowlist: Optional[list[str]] = Field(
|
||||||
|
None,
|
||||||
|
description="A list of sections to preserve during link time. It can be useful to preserve debugging sections",
|
||||||
|
)
|
||||||
|
ld_sections_denylist: Optional[list[str]] = Field(
|
||||||
|
None,
|
||||||
|
description="A list of sections to discard during link time. It can be useful to avoid using the wildcard "
|
||||||
|
"discard. Note that this option does not turn off `ld_discard_section`",
|
||||||
|
)
|
||||||
|
ld_wildcard_sections: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Determines whether to add wildcards for section linking in the linker script "
|
||||||
|
"(.rodata* for example)",
|
||||||
|
)
|
||||||
|
ld_use_symbolic_vram_addresses: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Determines whether to use `follows_vram` (segment option) and `vram_symbol` / `follows_classes` "
|
||||||
|
"(vram_class options) to calculate vram addresses in the linker script. If disabled, this uses the plain "
|
||||||
|
"integer values for vram addresses defined in the yaml.",
|
||||||
|
)
|
||||||
|
ld_partial_linking: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Change linker script generation to allow partially linking segments. Requires both "
|
||||||
|
"`ld_partial_scripts_path` and `ld_partial_build_segments_path` to be set.",
|
||||||
|
)
|
||||||
|
ld_partial_scripts_path: Optional[Path] = Field(
|
||||||
|
None, description="Folder were each intermediary linker script will be written to."
|
||||||
|
)
|
||||||
|
ld_partial_build_segments_path: Optional[Path] = Field(
|
||||||
|
None, description="Folder where the built partially linked segments will be placed by the build system."
|
||||||
|
)
|
||||||
|
ld_dependencies: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Generate a dependency file for every linker script generated. Dependency files will have the "
|
||||||
|
"same path and name as the corresponding linker script, but changing the extension to `.d`. Requires "
|
||||||
|
"`elf_path` to be set.",
|
||||||
|
)
|
||||||
|
ld_legacy_generation: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Legacy linker script generation does not impose the section_order specified in the yaml "
|
||||||
|
"options or per-segment options.",
|
||||||
|
)
|
||||||
|
segment_end_before_align: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="If enabled, the end symbol for each segment will be placed before the alignment directive "
|
||||||
|
"for the segment",
|
||||||
|
)
|
||||||
|
segment_symbols_style: Optional[str] = Field(
|
||||||
|
None,
|
||||||
|
description="Controls the style of the auto-generated segment symbols in the linker script. "
|
||||||
|
"Possible values: Optional[splat, makerom",
|
||||||
|
)
|
||||||
|
ld_rom_start: Optional[int] = Field(
|
||||||
|
None, description="Specifies the starting offset for rom address symbols in the linker script."
|
||||||
|
)
|
||||||
|
ld_fill_value: Optional[int] = Field(
|
||||||
|
None,
|
||||||
|
description="The value passed to the FILL statement on each segment. `None` disables using FILL "
|
||||||
|
"statements on the linker script. Defaults to a fill value of 0.",
|
||||||
|
)
|
||||||
|
ld_bss_is_noload: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Allows to control if `bss` sections (and derivative sections) will be put on a `NOLOAD` "
|
||||||
|
"segment on the generated linker script or not.",
|
||||||
|
)
|
||||||
|
ld_align_segment_vram_end: Optional[bool] = Field(
|
||||||
|
None, description="Allows to toggle aligning the `*_VRAM_END` linker symbol for each segment."
|
||||||
|
)
|
||||||
|
ld_align_section_vram_end: Optional[bool] = Field(
|
||||||
|
None, description="Allows to toggle aligning the `*_END` linker symbol for each section of each section."
|
||||||
|
)
|
||||||
|
ld_generate_symbol_per_data_segment: Optional[bool] = Field(
|
||||||
|
None, description="If enabled, the generated linker script will have a linker symbol for each data file"
|
||||||
|
)
|
||||||
|
ld_bss_contains_common: Optional[bool] = Field(
|
||||||
|
None, description="Sets the default option for the `bss_contains_common` attribute of all segments."
|
||||||
|
)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# C file options
|
||||||
|
################################################################################
|
||||||
|
create_c_files: Optional[bool] = Field(
|
||||||
|
None, description="Determines whether to create new c files if they don't exist"
|
||||||
|
)
|
||||||
|
auto_decompile_empty_functions: Optional[bool] = Field(
|
||||||
|
None, description='Determines whether to "auto-decompile" empty functions'
|
||||||
|
)
|
||||||
|
do_c_func_detection: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Determines whether to detect matched/unmatched functions in existing c files so we can avoid "
|
||||||
|
"creating .s files for already-decompiled functions",
|
||||||
|
)
|
||||||
|
c_newline: Optional[str] = Field(None, description="Determines the newline char(s) to be used in c files")
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# (Dis)assembly-related options
|
||||||
|
################################################################################
|
||||||
|
symbol_name_format: Optional[str] = Field(
|
||||||
|
None, description="The following options determine the format that symbols should be named by default"
|
||||||
|
)
|
||||||
|
symbol_name_format_no_rom: Optional[str] = Field(
|
||||||
|
None, description="Same as above but for symbols with no rom address"
|
||||||
|
)
|
||||||
|
find_file_boundaries: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Determines whether to detect and hint to the user about likely file splits " "when disassembling",
|
||||||
|
)
|
||||||
|
pair_rodata_to_text: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Determines whether to detect and hint to the user about possible rodata sections "
|
||||||
|
"corresponding to a text section",
|
||||||
|
)
|
||||||
|
migrate_rodata_to_functions: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Determines whether to attempt to automatically migrate rodata into functions "
|
||||||
|
"(only works in certain circumstances)",
|
||||||
|
)
|
||||||
|
asm_inc_header: Optional[str] = Field(
|
||||||
|
None, description="Determines the header to be used in every asm file that's included from c files"
|
||||||
|
)
|
||||||
|
asm_function_macro: Optional[str] = Field(
|
||||||
|
None, description="Determines the macro used to declare functions in asm files"
|
||||||
|
)
|
||||||
|
asm_function_alt_macro: Optional[str] = Field(
|
||||||
|
None,
|
||||||
|
description="Determines the macro used to declare symbols in the middle of functions in asm files "
|
||||||
|
"(which may be alternative entries)",
|
||||||
|
)
|
||||||
|
asm_jtbl_label_macro: Optional[str] = Field(
|
||||||
|
None, description="Determines the macro used to declare jumptable labels in asm files"
|
||||||
|
)
|
||||||
|
asm_data_macro: Optional[str] = Field(
|
||||||
|
None, description="Determines the macro used to declare data symbols in asm files"
|
||||||
|
)
|
||||||
|
asm_end_label: Optional[str] = Field(
|
||||||
|
None, description="Determines the macro used at the end of a function, such as endlabel or .end"
|
||||||
|
)
|
||||||
|
asm_emit_size_directive: Optional[bool] = Field(
|
||||||
|
None, description="Toggles the .size directive emitted by the disassembler"
|
||||||
|
)
|
||||||
|
include_macro_inc: Optional[bool] = Field(
|
||||||
|
None, description="Determines including the macro.inc file on non-migrated rodata variables"
|
||||||
|
)
|
||||||
|
mnemonic_ljust: Optional[int] = Field(
|
||||||
|
None, description="Determines the number of characters to left align before the TODO finish documenting"
|
||||||
|
)
|
||||||
|
rom_address_padding: Optional[bool] = Field(None, description="Determines whether to pad the rom address")
|
||||||
|
mips_abi_gpr: Optional[str] = Field(
|
||||||
|
None, description="Determines which ABI names to use for general purpose registers"
|
||||||
|
)
|
||||||
|
mips_abi_float_regs: Optional[str] = Field(
|
||||||
|
None,
|
||||||
|
description="""Determines which ABI names to use for floating point registers
|
||||||
|
Valid values: 'numeric', 'o32', 'n32', 'n64'
|
||||||
|
o32 is highly recommended, as it provides logically named registers for floating point instructions
|
||||||
|
For more info, see https://gist.github.com/EllipticEllipsis/27eef11205c7a59d8ea85632bc49224d""",
|
||||||
|
)
|
||||||
|
named_regs_for_c_funcs: Optional[bool] = Field(
|
||||||
|
None, description="Determines whether functions inside c files should have named registers"
|
||||||
|
)
|
||||||
|
add_set_gp_64: Optional[bool] = Field(None, description='Determines whether to add ".set gp=64" to asm/hasm files')
|
||||||
|
create_asm_dependencies: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Generate .asmproc.d dependency files for each C file which still reference functions "
|
||||||
|
"in assembly files",
|
||||||
|
)
|
||||||
|
string_encoding: Optional[str] = Field(
|
||||||
|
None, description="Global option for rodata string encoding. This can be overridden per segment"
|
||||||
|
)
|
||||||
|
data_string_encoding: Optional[str] = Field(
|
||||||
|
None, description="Global option for data string encoding. This can be overridden per segment"
|
||||||
|
)
|
||||||
|
rodata_string_guesser_level: Optional[int] = Field(
|
||||||
|
None, description="Global option for the rodata string guesser. 0 disables the guesser completely."
|
||||||
|
)
|
||||||
|
data_string_guesser_level: Optional[int] = Field(
|
||||||
|
None, description="Global option for the data string guesser. 0 disables the guesser completely."
|
||||||
|
)
|
||||||
|
allow_data_addends: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Global option for allowing data symbols using addends on symbol references. "
|
||||||
|
"It can be overridden per symbol",
|
||||||
|
)
|
||||||
|
disasm_unknown: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Tells the disassembler to try disassembling functions with unknown instructions instead of "
|
||||||
|
"falling back to disassembling as raw data",
|
||||||
|
)
|
||||||
|
detect_redundant_function_end: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Tries to detect redundant and unreferenced functions ends and merge them together. "
|
||||||
|
"This option is ignored if the compiler is not set to IDO.",
|
||||||
|
)
|
||||||
|
disassemble_all: Optional[bool] = Field(
|
||||||
|
None, description="Don't skip disassembling already matched functions and migrated sections"
|
||||||
|
)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# N64-specific options
|
||||||
|
################################################################################
|
||||||
|
header_encoding: Optional[str] = Field(None, description="Determines the encoding of the header")
|
||||||
|
gfx_ucode: Optional[str] = Field(
|
||||||
|
None,
|
||||||
|
description="""Determines the type gfx ucode (used by gfx segments)
|
||||||
|
Valid options are ['f3d', 'f3db', 'f3dex', 'f3dexb', 'f3dex2']""",
|
||||||
|
)
|
||||||
|
libultra_symbols: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Use named libultra symbols by default. Those will need to be added to a linker script "
|
||||||
|
"manually by the user",
|
||||||
|
)
|
||||||
|
ique_symbols: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Use named libultra symbols by default. Those will need to be added to a linker script "
|
||||||
|
"manually by the user",
|
||||||
|
)
|
||||||
|
hardware_regs: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Use named hardware register symbols by default. Those will need to be added to a linker script "
|
||||||
|
"manually by the user",
|
||||||
|
)
|
||||||
|
image_type_in_extension: Optional[bool] = Field(
|
||||||
|
None, description="Append the image type to the output file extension"
|
||||||
|
)
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# Compiler-specific options
|
||||||
|
################################################################################
|
||||||
|
use_legacy_include_asm: Optional[bool] = Field(
|
||||||
|
None,
|
||||||
|
description="Determines whether to use a legacy INCLUDE_ASM macro "
|
||||||
|
"format in c files only applies to GCC/SN64",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class VramClass(BaseModel):
|
||||||
|
name: str = Field(..., description="")
|
||||||
|
vram: Optional[int] = Field(None, description="")
|
||||||
|
|
||||||
|
|
||||||
|
class DictSegment(BaseModel):
|
||||||
|
start: int = Field(None, description="")
|
||||||
|
rom_start: Optional[int] = Field(None, description="")
|
||||||
|
rom_start: Optional[int] = Field(None, description="")
|
||||||
|
rom_end: Optional[int] = Field(None, description="")
|
||||||
|
type: str = Field(..., description="")
|
||||||
|
name: str = Field(..., description="")
|
||||||
|
vram: Optional[int] = Field(None, description="")
|
||||||
|
vram_start: Optional[int] = Field(None, description="")
|
||||||
|
vram_symbol: Optional[str] = Field(None, description="")
|
||||||
|
vram_class: Optional[VramClass] = Field(None, description="")
|
||||||
|
follows_vram: Optional[str] = Field(None, description="")
|
||||||
|
align: Optional[int] = Field(None, description="")
|
||||||
|
subalign: Optional[int] = Field(None, description="")
|
||||||
|
section_order: Optional[list[str]] = Field(None, description="")
|
||||||
|
subsegments: Optional[list[Segment]] = Field(None, description="")
|
||||||
|
bss_size: Optional[int] = Field(None, description="")
|
||||||
|
args: Optional[list[str]] = Field(None, description="")
|
||||||
|
|
||||||
|
|
||||||
|
class ListSegment(RootModel[tuple[int, str, str] | tuple[int, str] | tuple[int]]): ...
|
||||||
|
|
||||||
|
|
||||||
|
Segment = DictSegment | ListSegment
|
||||||
|
|
||||||
|
|
||||||
|
class Config(BaseModel):
|
||||||
|
name: str
|
||||||
|
sha1: str
|
||||||
|
options: SplatOpts
|
||||||
|
segments: list[Segment]
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
import json
|
||||||
|
|
||||||
|
with open("../../.vscode/schema/splat_config.schema.json", "w") as fh:
|
||||||
|
fh.write(json.dumps(Config.model_json_schema(), indent=2))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user