inital commit

This commit is contained in:
2026-07-12 15:06:31 -05:00
commit 75f1616cb3
77 changed files with 75469 additions and 0 deletions
+21
View File
@@ -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/
+21
View File
@@ -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.
+135
View File
@@ -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
+116
View File
@@ -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.svg?mode=shield&category=us&label=⠀  Code   ⠀&measure=matched_code_percent)](https://decomp.dev/Mikompilation/Himuro/SLUS_203.88)⠀ [![](https://decomp.dev/Mikompilation/Himuro/SLUS_203.88.svg?mode=shield&category=us&label=Functions&measure=matched_functions)](https://decomp.dev/Mikompilation/Himuro/SLUS_203.88)
| Project Zero | EU | SLES_508.21 |[![](https://decomp.dev/Mikompilation/Himuro/SLES_508.21.svg?mode=shield&category=eu&label=⠀  Code   ⠀&measure=matched_code_percent)](https://decomp.dev/Mikompilation/Himuro/SLES_508.21)⠀ [![](https://decomp.dev/Mikompilation/Himuro/SLES_508.21.svg?mode=shield&category=eu&label=Functions&measure=matched_functions)](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
+1
View File
@@ -0,0 +1 @@
5ac4626e0d76218e977b01f4fae5948de9a1755e build/SLUS_203.88
+1882
View File
File diff suppressed because it is too large Load Diff
+753
View File
@@ -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
View File
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
View File
@@ -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()
+62
View File
@@ -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 */
+60
View File
@@ -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
+90
View File
@@ -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
+445
View File
@@ -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
+7
View File
@@ -0,0 +1,7 @@
#ifndef EE_KERNEL_H
#define EE_KERNEL_H
void EiInit();
void FlushCache(int);
#endif // EE_KERNEL_H
+8
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+20
View File
@@ -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
+10
View File
@@ -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
+14
View File
@@ -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
+277
View File
@@ -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) */
+54
View File
@@ -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 */
+36
View File
@@ -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
+20
View File
@@ -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
+6
View File
@@ -0,0 +1,6 @@
#ifndef SCE_DEVVIF0_H
#define SCE_DEVVIF0_H
void sceDevVif0Reset();
#endif // SCE_DEVVIF0_H
+36
View File
@@ -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
+6
View File
@@ -0,0 +1,6 @@
#ifndef SCE_DEVVU0_H
#define SCE_DEVVU0_H
void sceDevVu0Reset();
#endif // SCE_DEVVU0_H
+63
View File
@@ -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
+77
View File
@@ -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
+26
View File
@@ -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
+191
View File
@@ -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
+22
View File
@@ -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
+57
View File
@@ -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
+38
View File
@@ -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
+61
View File
@@ -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
+7
View File
@@ -0,0 +1,7 @@
#ifndef SCE_LIBSDR_H
#define SCE_LIBSDR_H
int sceSdRemoteInit();
int sceSdRemote(int arg, ...);
#endif // SCE_LIBSDR_H
+37
View File
@@ -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
+7
View File
@@ -0,0 +1,7 @@
#ifndef SCE_MISC_DIEI_H
#define SCE_MISC_DIEI_H
int EIntr();
int DIntr();
#endif // SCE_MISC_DIEI_H
+51
View File
@@ -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
+38
View File
@@ -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
+6
View File
@@ -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
+84
View File
@@ -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
+18
View File
@@ -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
+52
View File
@@ -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
+21
View File
@@ -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
+32
View File
@@ -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
+18
View File
@@ -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
+8
View File
@@ -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
+14
View File
@@ -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
+34
View File
@@ -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
+29
View File
@@ -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
+25
View File
@@ -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
+50
View File
@@ -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 */
+9
View File
@@ -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
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
+265
View File
@@ -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()
+351
View File
@@ -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)
+322
View File
@@ -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")
+56
View File
@@ -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()
+125
View File
@@ -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()
+38
View File
@@ -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()
+79
View File
@@ -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()
+75
View File
@@ -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()
+139
View File
@@ -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()
+153
View File
@@ -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()
+32
View File
@@ -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
+288
View File
@@ -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()
+378
View File
@@ -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()
+414
View File
@@ -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()