Fix alignment (#421)

* git subrepo pull (merge) tools/splat

subrepo:
  subdir:   "tools/splat"
  merged:   "0f6b99498e"
upstream:
  origin:   "https://github.com/ethteck/splat.git"
  branch:   "master"
  commit:   "a889d905d9"
git-subrepo:
  version:  "0.4.3"
  origin:   "https://github.com/ingydotnet/git-subrepo"
  commit:   "2f68596"

* OK

* git subrepo pull (merge) --force tools/splat

subrepo:
  subdir:   "tools/splat"
  merged:   "7eb5744b2a"
upstream:
  origin:   "https://github.com/ethteck/splat.git"
  branch:   "master"
  commit:   "7eb5744b2a"
git-subrepo:
  version:  "0.4.3"
  origin:   "https://github.com/ingydotnet/git-subrepo"
  commit:   "2f68596"
This commit is contained in:
Ethan Roseman 2021-09-22 20:09:51 +09:00 committed by GitHub
parent 0989f8daa0
commit ac5b75763c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 157 additions and 43 deletions

View File

@ -517,6 +517,8 @@ s32* func_80055EB4(s32 arg0) {
return ret; return ret;
} }
static const f32 padding[] = {0.0f};
s32 func_80055F58(s32 arg0, u32 arg1, u32 arg2) { s32 func_80055F58(s32 arg0, u32 arg1, u32 arg2) {
s32* subroutine_arg4; s32* subroutine_arg4;
s32* subroutine_arg5; s32* subroutine_arg5;

13
src/9D650.c Normal file
View File

@ -0,0 +1,13 @@
#include "common.h"
Gfx D_801041A0[] = {
gsSPEndDisplayList(),
};
#include "ui/stat_heart.png.inc.c"
Gfx D_801045A8[] = {
gsSPEndDisplayList(),
};
#include "ui/stat_flower.png.inc.c"

View File

@ -1,5 +1,70 @@
#include "machi.h" #include "machi.h"
static char* STR01 = "GSW MAP";
static char* STR02 = "GSW DOKAN";
static char* STR03 = "GSW FBTL";
static char* STR04 = "GSW BTL";
static char* STR05 = "GSW NPC";
static char* STR06 = "GSW BAT";
static char* STR07 = "GSW OSR";
static char* STR08 = "GSW END";
static char* STR09 = "GSW KPA";
static char* STR10 = "GSW PRA";
static char* STR11 = "GSW SAM";
static char* STR12 = "GSW FLO";
static char* STR13 = "GSW KZN";
static char* STR14 = "GSW JAN";
static char* STR15 = "GSW OMO";
static char* STR16 = "GSW DGB";
static char* STR17 = "GSW ARN";
static char* STR18 = "GSW OBK";
static char* STR19 = "GSW MIM";
static char* STR20 = "GSW ISK";
static char* STR21 = "GSW SBK";
static char* STR22 = "GSW DRO";
static char* STR23 = "GSW IWA";
static char* STR24 = "GSW TRD";
static char* STR25 = "GSW NOK";
static char* STR26 = "GSW HOS";
static char* STR27 = "GSW KKJ";
static char* STR28 = "GSW KGR";
static char* STR29 = "GSW TIK";
static char* STR30 = "GSW MAC";
static char* STR31 = "GSW KMR";
static char* STR32 = "GSW EVT";
static char* STR33 = "GSWF MAP";
static char* STR34 = "GSWF DOKAN";
static char* STR35 = "GSWF FBTL";
static char* STR36 = "GSWF BTL";
static char* STR37 = "GSWF NPC";
static char* STR38 = "GSWF BAT";
static char* STR39 = "GSWF OSR";
static char* STR40 = "GSWF END";
static char* STR41 = "GSWF KPA";
static char* STR42 = "GSWF PRA";
static char* STR43 = "GSWF SAM";
static char* STR44 = "GSWF FLO";
static char* STR45 = "GSWF KZN";
static char* STR46 = "GSWF JAN";
static char* STR47 = "GSWF OMO";
static char* STR48 = "GSWF DGB";
static char* STR49 = "GSWF ARN";
static char* STR50 = "GSWF OBK";
static char* STR51 = "GSWF MIM";
static char* STR52 = "GSWF ISK";
static char* STR53 = "GSWF SBK";
static char* STR54 = "GSWF DRO";
static char* STR55 = "GSWF IWA";
static char* STR56 = "GSWF TRD";
static char* STR57 = "GSWF NOK";
static char* STR58 = "GSWF HOS";
static char* STR59 = "GSWF KKJ";
static char* STR60 = "GSWF KGR";
static char* STR61 = "GSWF TIK";
static char* STR62 = "GSWF MAC";
static char* STR63 = "GSWF KMR";
static char* STR64 = "GSWF EVT";
static char* N(exit_str_0) = "kmr_09"; static char* N(exit_str_0) = "kmr_09";
static char* N(exit_str_1) = "nok_10"; static char* N(exit_str_1) = "nok_10";
static char* N(exit_str_2) = "iwa_00"; static char* N(exit_str_2) = "iwa_00";

View File

@ -10,6 +10,18 @@ jobs:
mypy: mypy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: mypy
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v1
- uses: jpetrucciani/mypy-check@master - name: Set up Python 3.9
uses: actions/setup-python@v1
with:
python-version: 3.9
- name: Install Dependencies
run: |
pip install mypy
pip install -r requirements.txt
pip install types-PyYAML
- name: mypy
run: |
mypy --show-column-numbers --hide-error-context .

View File

@ -6,7 +6,7 @@
[subrepo] [subrepo]
remote = https://github.com/ethteck/splat.git remote = https://github.com/ethteck/splat.git
branch = master branch = master
commit = 5d7a6c0813c5045876718d0c61a153e90bf16d2b commit = 7eb5744b2a3a5e2a4253996f587b7666db597c57
parent = 015151cbfbe09820d5f71aeae7a255ede7cbe4c6 parent = 31629ad772cbb4cda8df2a96ce9d91b74883f752
method = merge method = merge
cmdver = 0.4.3 cmdver = 0.4.3

View File

@ -1,5 +1,18 @@
# splat Release Notes # splat Release Notes
### 0.7.9
* Finally removed the dumb linker section alignment hack
* Added version number to output on execution
### 0.7.8
* Fixed a bug relating to a linker section alignment hack (thanks Wiseguy!)
* Fixed a bug in linker_entry.py's clean_up_path that should make this function more versatile (thanks Wiseguy!)
### 0.7.7
* Disassembly now reads the `size` property of a function in symbol_addrs.txt to disassemble `size / 4` number of instructions. Feel free to specify the size of your functions in your symbol_addrs file if splat's disassembly is chopping a function too short or making a function too long.
### 0.7.6 ### 0.7.6
* Fixed a bug involving detection of defined functions in c files for GLOBAL_ASM-using projects * Fixed a bug involving detection of defined functions in c files for GLOBAL_ASM-using projects

View File

@ -2,11 +2,27 @@ from typing import Union, List
from pathlib import Path from pathlib import Path
from util import options from util import options
from segtypes.segment import Segment from segtypes.segment import Segment
import os
import re import re
# clean 'foo/../bar' to 'bar' # clean 'foo/../bar' to 'bar'
def clean_up_path(path: Path) -> Path: def clean_up_path(path: Path) -> Path:
return path.resolve().relative_to(options.get_base_path().resolve()) path_resolved = path.resolve()
base_resolved = options.get_base_path().resolve()
try:
return path_resolved.relative_to(base_resolved)
except ValueError:
pass
# If the path wasn't relative to the splat file, use the working directory instead
cwd = Path(os.getcwd())
try:
return path_resolved.relative_to(cwd)
except ValueError:
pass
# If it wasn't relative to that too, then just return the path as-is
return path
def path_to_object_path(path: Path) -> Path: def path_to_object_path(path: Path) -> Path:
path = clean_up_path(path) path = clean_up_path(path)
@ -70,7 +86,6 @@ class LinkerWriter():
self._write_symbol(f"{seg_name}_TEXT_START", ".") self._write_symbol(f"{seg_name}_TEXT_START", ".")
do_next = False
text_ended = False text_ended = False
data_started = False data_started = False
data_ended = False data_ended = False
@ -107,17 +122,6 @@ class LinkerWriter():
bss_started = True bss_started = True
self._write_symbol(f"{seg_name}_BSS_START", ".") self._write_symbol(f"{seg_name}_BSS_START", ".")
start = entry.segment.rom_start
if isinstance(start, int):
# Create new sections for non-0x10 alignment (hack)
if start % 0x10 != 0 and i != 0 or do_next:
self._end_block()
self._begin_segment(entry.segment, mid_segment=True)
do_next = False
if start % 0x10 != 0 and i != 0:
do_next = True
if entry.object_path and cur_section == ".data": if entry.object_path and cur_section == ".data":
path_cname = re.sub(r"[^0-9a-zA-Z_]", "_", str(entry.segment.dir / entry.segment.name) + ".".join(entry.object_path.suffixes[:-1])) path_cname = re.sub(r"[^0-9a-zA-Z_]", "_", str(entry.segment.dir / entry.segment.name) + ".".join(entry.object_path.suffixes[:-1]))
self._write_symbol(path_cname, ".") self._write_symbol(path_cname, ".")

View File

@ -5,7 +5,7 @@ import os
import re import re
from pathlib import Path from pathlib import Path
from util import options from util import log, options
class N64SegC(N64SegCodeSubsegment): class N64SegC(N64SegCodeSubsegment):
@ -175,4 +175,4 @@ class N64SegC(N64SegCodeSubsegment):
Path(c_path).parent.mkdir(parents=True, exist_ok=True) Path(c_path).parent.mkdir(parents=True, exist_ok=True)
with open(c_path, "w") as f: with open(c_path, "w") as f:
f.write("\n".join(c_lines)) f.write("\n".join(c_lines))
print(f"Wrote {self.name} to {c_path}") log.write(f"Wrote {self.name} to {c_path}")

View File

@ -77,6 +77,12 @@ class N64SegCodeSubsegment(Segment):
op_str = insn.op_str op_str = insn.op_str
func_addr = insn.address if len(func) == 0 else func[0][0].address func_addr = insn.address if len(func) == 0 else func[0][0].address
# If this is non-zero, disasm size insns
hard_size = 0
func_sym = self.parent.get_symbol(func_addr, type="func")
if func_sym and func_sym.size > 4:
hard_size = func_sym.size / 4
if mnemonic == "move": if mnemonic == "move":
# Let's get the actual instruction out # Let's get the actual instruction out
opcode = insn.bytes[3] & 0b00111111 opcode = insn.bytes[3] & 0b00111111
@ -116,6 +122,8 @@ class N64SegCodeSubsegment(Segment):
func.append((insn, mnemonic, op_str, rom_addr)) func.append((insn, mnemonic, op_str, rom_addr))
rom_addr += 4 rom_addr += 4
size_remaining = hard_size - len(func) if hard_size > 0 else 0
if mnemonic == "jr": if mnemonic == "jr":
# Record potential jtbl jumps # Record potential jtbl jumps
if op_str != "$ra": if op_str != "$ra":
@ -126,10 +134,14 @@ class N64SegCodeSubsegment(Segment):
if (label[0] > insn.address and label[1] <= insn.address) or (label[0] <= insn.address and label[1] > insn.address): if (label[0] > insn.address and label[1] <= insn.address) or (label[0] <= insn.address and label[1] > insn.address):
keep_going = True keep_going = True
break break
if not keep_going: if not keep_going and not size_remaining:
end_func = True end_func = True
continue continue
# Stop here if a size was specified and we have disassembled up to the size
if hard_size > 0 and size_remaining == 0:
end_func = True
if i < len(insns) - 1 and self.parent.get_symbol(insns[i + 1].address, local_only=True, type="func", dead=False): if i < len(insns) - 1 and self.parent.get_symbol(insns[i + 1].address, local_only=True, type="func", dead=False):
end_func = True end_func = True

View File

@ -157,8 +157,7 @@ class N64SegGroup(N64Segment):
end = self.get_next_seg_start(i, segment_yaml["subsegments"]) end = self.get_next_seg_start(i, segment_yaml["subsegments"])
if isinstance(start, int) and isinstance(prev_start, int) and start < prev_start: if isinstance(start, int) and isinstance(prev_start, int) and start < prev_start:
print(f"Error: Code segment {self.name} contains subsegments which are out of ascending rom order (0x{prev_start:X} followed by 0x{start:X})") log.error(f"Error: Code segment {self.name} contains subsegments which are out of ascending rom order (0x{prev_start:X} followed by 0x{start:X})")
sys.exit(1)
vram = None vram = None
if start != "auto": if start != "auto":

View File

@ -139,8 +139,7 @@ class Segment:
if isinstance(self.rom_start, int) and isinstance(self.rom_end, int): if isinstance(self.rom_start, int) and isinstance(self.rom_end, int):
if self.rom_start > self.rom_end: if self.rom_start > self.rom_end:
print(f"Error: segments out of order - ({self.name} starts at 0x{self.rom_start:X}, but next segment starts at 0x{self.rom_end:X})") log.error(f"Error: segments out of order - ({self.name} starts at 0x{self.rom_start:X}, but next segment starts at 0x{self.rom_end:X})")
sys.exit(1)
@staticmethod @staticmethod
def from_yaml(cls: Type["Segment"], yaml: Union[dict, list], rom_start: RomAddr, rom_end: RomAddr, vram=None): def from_yaml(cls: Type["Segment"], yaml: Union[dict, list], rom_start: RomAddr, rom_end: RomAddr, vram=None):

View File

@ -14,6 +14,8 @@ from util import options
from util import symbols from util import symbols
from util import palettes from util import palettes
VERSION = "0.7.9"
parser = argparse.ArgumentParser(description="Split a rom given a rom, a config, and output directory") parser = argparse.ArgumentParser(description="Split a rom given a rom, a config, and output directory")
parser.add_argument("config", help="path to a compatible config .yaml file") parser.add_argument("config", help="path to a compatible config .yaml file")
parser.add_argument("--target", help="path to a file to split (.z64 rom)") parser.add_argument("--target", help="path to a file to split (.z64 rom)")
@ -110,6 +112,8 @@ def do_statistics(seg_sizes, rom_bytes, seg_split, seg_cached):
def main(config_path, base_dir, target_path, modes, verbose, use_cache=True): def main(config_path, base_dir, target_path, modes, verbose, use_cache=True):
global config global config
log.write(f"splat {VERSION}")
# Load config # Load config
with open(config_path) as f: with open(config_path) as f:
config = yaml.load(f.read(), Loader=yaml.SafeLoader) config = yaml.load(f.read(), Loader=yaml.SafeLoader)

View File

@ -20,7 +20,7 @@ def setup_lib():
lib = cdll.LoadLibrary(os.path.dirname(os.path.realpath(__file__)) + "/Yay0decompress") lib = cdll.LoadLibrary(os.path.dirname(os.path.realpath(__file__)) + "/Yay0decompress")
return True return True
except Exception: except Exception:
print(f"Failed to load Yay0decompress, falling back to python method") print(f"Failed to load C library; falling back to python method")
tried_loading = True tried_loading = True
return False return False

View File

@ -1,6 +0,0 @@
.include "macro.inc"
.section .data
glabel D_801041A0
.word 0xDF000000, 0x00000000

View File

@ -1,6 +0,0 @@
.include "macro.inc"
.section .data
glabel D_801045A8
.word 0xDF000000, 0x00000000

View File

@ -682,10 +682,14 @@ segments:
- [0x9D410, ci4, ui/orb_red, 32, 32] - [0x9D410, ci4, ui/orb_red, 32, 32]
- [0x9D610, palette, ui/orb_red] - [0x9D610, palette, ui/orb_red]
- [0x9D630, palette, ui/orb_red.disabled] - [0x9D630, palette, ui/orb_red.disabled]
- [0x9D650, data] - start: 0x9D650 # TODO: The images before this (just above) should probably be with these in c
- [0x9D658, rgba32, ui/stat_heart, 16, 16] type: .data
- [0x9DA58, data] name: 9D650
- [0x9DA60, rgba32, ui/stat_flower, 16, 16] subsegments:
- [0x9D650, .data, 9D650]
- [0x9D658, rgba32, ui/stat_heart, 16, 16]
- [0x9DA58]
- [0x9DA60, rgba32, ui/stat_flower, 16, 16]
- [0x9DE60, data] - [0x9DE60, data]
- [0xA5100] # bss at 8010C920 - [0xA5100] # bss at 8010C920
- type: code - type: code
@ -5021,8 +5025,7 @@ segments:
- [0x7E7A30, data] - [0x7E7A30, data]
- [0x7E8470, data] - [0x7E8470, data]
- [0x7EA340, data] - [0x7EA340, data]
- [0x7EAA50, data] - [0x7EAA50, .rodata, 7E73A0]
- [0x7EACD8, .rodata, 7E73A0]
- [0x7EAD00, .rodata, 7E7850] - [0x7EAD00, .rodata, 7E7850]
- name: mac_00 - name: mac_00
dir: world/area_mac/mac_00 dir: world/area_mac/mac_00