diff --git a/Makefile b/Makefile index 25aec03f..87fa1e93 100644 --- a/Makefile +++ b/Makefile @@ -91,12 +91,13 @@ LDFLAGS := -T $(LD_SCRIPT) \ --no-check-sections \ -Map $(ELF:.elf=.map) -### Output files ### - -### Collect source files ### -# Assembly sources (header + data segments) -ASM_SRCS := $(wildcard $(ASM_DIR)/*.s) $(wildcard $(ASM_DIR)/data/*.s) -ASM_OBJS := $(patsubst $(ASM_DIR)/%.s,$(BUILD_DIR)/$(ASM_DIR)/%.o,$(ASM_SRCS)) +### Object lists ### +# The object list is splat's, not ours: `ld_dependencies` makes it write a make +# rule naming every object in the link. Including that rule gives the ELF its +# prerequisites directly, so nothing here has to know which objects exist or +# what kind each one is -- only how to build one, via the pattern rules below. +MAIN_DEP := $(basename $(LD_SCRIPT)).d +-include $(MAIN_DEP) # Overlay binaries (.ovl menu overlays + .bin code overlays). MENU_OVERLAYS := menumain menucfg menupty menusts menuabl menushop menuext \ @@ -106,48 +107,6 @@ CODE_OVERLAYS := field_init intro field \ tripletriad battle_render battle world OVERLAYS := $(MENU_OVERLAYS) $(CODE_OVERLAYS) -# Per-overlay C source files. Each overlay points to its own source location. -menumain_C_SRCS := $(wildcard src/menu/menumain/*.c) -menucfg_C_SRCS := $(wildcard src/menu/menucfg/*.c) -menupty_C_SRCS := $(wildcard src/menu/menupty/*.c) -menusts_C_SRCS := $(wildcard src/menu/menusts/*.c) -menuabl_C_SRCS := $(wildcard src/menu/menuabl/*.c) -menushop_C_SRCS := $(wildcard src/menu/menushop/*.c) -menuext_C_SRCS := $(wildcard src/menu/menuext/*.c) -menuitem_C_SRCS := $(wildcard src/menu/menuitem/*.c) -menumgc_C_SRCS := $(wildcard src/menu/menumgc/*.c) -menugf_C_SRCS := $(wildcard src/menu/menugf/*.c) -menujnc2_C_SRCS := $(wildcard src/menu/menujnc2/*.c) -menusav_C_SRCS := $(wildcard src/menu/menusav/*.c) -menucrd_C_SRCS := $(wildcard src/menu/menucrd/*.c) -menututo_C_SRCS := $(wildcard src/menu/menututo/*.c) -menutmag_C_SRCS := $(wildcard src/menu/menutmag/*.c) -menutips_C_SRCS := $(wildcard src/menu/menutips/*.c) -menutest_C_SRCS := $(wildcard src/menu/menutest/*.c) -field_init_C_SRCS := $(wildcard src/ovl/field_init/*.c) -intro_C_SRCS := src/intro.c src/intro_assets.c src/intro_state.c -intro_DIR := build/intro -intro_ASM_DIR := asm/intro -field_C_SRCS := $(wildcard src/field/*.c) -field_DIR := build/field -field_ASM_DIR := asm/field -tripletriad_C_SRCS := $(wildcard src/tripletriad/*.c) -battle_render_C_SRCS := $(wildcard src/ovl/battle_render/*.c) -battle_C_SRCS := $(wildcard src/battle/*.c) -world_C_SRCS := $(wildcard src/world/*.c) - -# C sources (compiled via cpp → cc1 → maspsx → GAS). -# Main-binary sources = everything under src/ except files claimed by an overlay. -ALL_OVERLAY_C_SRCS := $(foreach ovl,$(OVERLAYS),$($(ovl)_C_SRCS)) -C_SRCS := $(filter-out $(ALL_OVERLAY_C_SRCS), \ - $(wildcard $(SRC_DIR)/*.c) \ - $(wildcard $(SRC_DIR)/psxsdk/*.c) \ - $(wildcard $(SRC_DIR)/psxsdk/*/*.c)) -C_OBJS := $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/$(SRC_DIR)/%.o,$(C_SRCS)) - -# All objects for linking -ALL_OBJS := $(ASM_OBJS) $(C_OBJS) - ### Targets ### # Default: build and verify everything @@ -161,14 +120,14 @@ full: $(MAKE) verify # Assemble: .s -> .o -$(BUILD_DIR)/$(ASM_DIR)/%.o: $(ASM_DIR)/%.s +$(BUILD_DIR)/%.o: %.s @mkdir -p $(dir $@) $(AS) $(ASFLAGS) -o $@ $< # Compile C: cpp → cc1 → maspsx → GAS → .o # PsyQ 4.1 uses gcc-2.7.2-cdk (cygnus-2.7.2-970404 SN32.3.7) # PsyQ 4.3 uses gcc-2.8.0-psx (gcc 2.8.0) -$(BUILD_DIR)/$(SRC_DIR)/%.o: $(SRC_DIR)/%.c +$(BUILD_DIR)/%.o: %.c @mkdir -p $(dir $@) $(CPP) -E -lang-c -nostdinc -Iinclude $(NON_MATCHING_FLAGS) $< -o $(BUILD_DIR)/$(*F).i && \ $(if $(filter $<,$(PSYQ43_SRCS)), \ @@ -178,9 +137,9 @@ $(BUILD_DIR)/$(SRC_DIR)/%.o: $(SRC_DIR)/%.c cat $(BUILD_DIR)/$(*F).s | $(MASPSX) $(if $(filter $<,$(O0_EXPAND_LI_SRCS)),,$(if $(filter $<,$(O0_SRCS)),$(PSYQ40_MASPSXFLAGS),$(PSYQ41_MASPSXFLAGS))) --run-assembler $(ASFLAGS) -o $@) # Link: all .o files -> ELF -$(ELF): $(ALL_OBJS) $(LD_SCRIPT) +$(ELF): $(LD_SCRIPT) @mkdir -p $(dir $@) - $(LD) $(LDFLAGS) -o $@ $(ALL_OBJS) + $(LD) $(LDFLAGS) -o $@ $(filter %.o,$^) # Convert: ELF -> raw binary (the PS-EXE) $(BUILT_EXE): $(ELF) @@ -247,18 +206,14 @@ endif ./permute.sh $(FUNC) ### Overlays ### -# Template for overlay build rules — $(1) = overlay name, $(2) = file extension +# Template for overlay build rules — $(1) = overlay name define OVERLAY_TEMPLATE -$(1)_DIR ?= build/ovl/$(1) -$(1)_ASM_DIR ?= asm/ovl/$(1) -$(1)_BIN := $$($(1)_DIR)/$$(notdir $$($(1)_TARGET)) +# $(1)_DIR is splat's build_path, from binaries.mk. +$(1)_BIN := $$($(1)_DIR)/$$(notdir $$($(1)_TARGET)) -$(1)_ASM_SRCS := $$(wildcard $$($(1)_ASM_DIR)/*.s) $$(wildcard $$($(1)_ASM_DIR)/data/*.s) -$(1)_ASM_OBJS := $$(patsubst $$($(1)_ASM_DIR)/%.s,$$($(1)_DIR)/$$($(1)_ASM_DIR)/%.o,$$($(1)_ASM_SRCS)) -$(1)_C_OBJS := $$(foreach src,$$($(1)_C_SRCS),$$($(1)_DIR)/$$(src:.c=.o)) -$(1)_BIN_SRCS := $$(wildcard assets/*.bin) -$(1)_BIN_OBJS := $$(patsubst assets/%.bin,$$($(1)_DIR)/assets/%.o,$$($(1)_BIN_SRCS)) -$(1)_ALL_OBJS := $$($(1)_ASM_OBJS) $$($(1)_C_OBJS) $$($(1)_BIN_OBJS) +# Same as the main binary: take the object list from splat's dependency file. +$(1)_DEP := $$(basename $$($(1)_LD)).d +-include $$($(1)_DEP) $(1)_LDFLAGS := -T $$($(1)_LD) \ -T $$(SPLAT_GEN)/undefined_funcs_auto.$(1).txt \ @@ -270,7 +225,9 @@ $(1)_LDFLAGS := -T $$($(1)_LD) \ split-$(1): splat-config $$(SPLAT) split $$($(1)_YAML) -$$($(1)_DIR)/$$($(1)_ASM_DIR)/%.o: $$($(1)_ASM_DIR)/%.s +# An object's path is the binary's build_path plus the source path, whatever +# directory that source lives in -- so these two rules need no per-overlay paths. +$$($(1)_DIR)/%.o: %.s @mkdir -p $$(dir $$@) $$(AS) $$(ASFLAGS) -o $$@ $$< @@ -287,9 +244,9 @@ $$($(1)_DIR)/assets/%.o: assets/%.bin @mkdir -p $$(dir $$@) $$(OBJCOPY) -I binary -O elf32-tradlittlemips -B mips --rename-section .data=.data $$< $$@ -$$($(1)_ELF): $$($(1)_ALL_OBJS) $$($(1)_LD) +$$($(1)_ELF): $$($(1)_LD) @mkdir -p $$(dir $$@) - $$(LD) $$($(1)_LDFLAGS) -o $$@ $$($(1)_ALL_OBJS) + $$(LD) $$($(1)_LDFLAGS) -o $$@ $$(filter %.o,$$^) $$($(1)_BIN): $$($(1)_ELF) $$(OBJCOPY) -O binary $$< $$@ @@ -311,7 +268,13 @@ verify-$(1): $$($(1)_BIN) endef +# binaries.mk supplies every _DIR/_LD/_ELF, so there is nothing to build +# rules from until it has been read -- on the first parse after a clean the +# template would expand its paths to bare "/". Make regenerates binaries.mk +# above and re-executes, and the rules get defined on that second pass. +ifneq ($(wildcard $(BINARIES_MK)),) $(foreach ovl,$(OVERLAYS),$(eval $(call OVERLAY_TEMPLATE,$(ovl)))) +endif # field_init: extract font TIM from overlay binary during split FIELD_INIT_TIM := assets/field_init_font.tim diff --git a/config/ff8.yaml b/config/ff8.yaml index a553348e..3a0e7a05 100644 --- a/config/ff8.yaml +++ b/config/ff8.yaml @@ -29,6 +29,7 @@ defaults: - config/symbols.{name}.txt undefined_funcs_auto_path: build/splat/undefined_funcs_auto.{name}.txt undefined_syms_auto_path: build/splat/undefined_syms_auto.{name}.txt + disassemble_all: true # String detection string_encoding: ASCII data_string_encoding: ASCII @@ -65,7 +66,7 @@ binaries: - [0xF90, .rodata, bc_object6] - [0x14C0, .rodata, bc_object7] - [0x14E8, .rodata, bc_object8] - - [0x1520, rodata] + - [0x1520, .rodata, bc_object9] - [0x156C, .rodata, bc_object11] - [0x15EC, .rodata, bc_object12] - [0x1888, .rodata, bc_object13] @@ -238,7 +239,6 @@ binaries: options: target_path: original/menucrd.ovl src_path: src/menu/menucrd - disassemble_all: true segments: - name: menucrd type: code @@ -246,7 +246,8 @@ binaries: vram: 0x801E5800 subsegments: - [0x0, c, menucrd] - - [0x14A8, rodata] + - [0x14A8, .rodata, menucrd] + - [0x14F8, rodata] - [0x2164, data] - [0x2564] - name: menuext @@ -304,7 +305,6 @@ binaries: options: target_path: original/menujnc2.ovl src_path: src/menu/menujnc2 - disassemble_all: true symbol_addrs_path: [config/symbols.menujnc2.txt] ld_bss_is_noload: true section_order: [.text, .rodata, .data, .bss] @@ -321,7 +321,7 @@ binaries: subsegments: - [0x0, c, menujnc2] - [0x9110, .rodata, menujnc2] - - [0x923C, rodata] + - [0x9284, rodata] - [0x9450, bss, menujnc2_bss] - [0x9450] - name: menumain @@ -368,15 +368,13 @@ binaries: vram: 0x801E5800 subsegments: - [0x0, c, menupty] - - [0x3C7C, rodata] - - [0x3D38, .rodata, menupty] + - [0x3C7C, .rodata, menupty] - [0x3D40] - name: menusav sha1: 11db278b2b7d0bf82d49003a789c316c8db78517 options: target_path: original/menusav.ovl src_path: src/menu/menusav - disassemble_all: true segments: - name: menusav type: code @@ -483,7 +481,6 @@ binaries: sha1: accfe3831595f26c5d6de6f3891736521736f8ef options: target_path: original/tripletriad.bin - disassemble_all: true section_order: [.rodata, .text, .data, .bss] ld_bss_is_noload: true segments: @@ -531,7 +528,7 @@ binaries: - [0x11C, rodata] - [0x120, .rodata, we_object4] - [0x15C, rodata] - - [0x3F0, .rodata, we_object6] + - [0x178, .rodata, we_object6] - [0x760, .rodata, we_object7] - [0x770, .rodata, we_object9] - [0x784, .rodata, we_object11] @@ -565,14 +562,6 @@ binaries: reloc_addrs_path: [config/reloc_addrs.txt] undefined_funcs_auto_path: build/splat/undefined_funcs_auto.txt undefined_syms_auto_path: build/splat/undefined_syms_auto.txt - # Off is also splat's default; it is spelled out here as a guard, because - # turning it on silently breaks the rodata pairing below. With it ON, splat force-emits a - # standalone .s for every dot-prefixed .rodata *and* migrates the symbols - # into their functions (data.py should_self_split), which duplicates every - # migrated symbol at link time. The two data blobs that used to need this - # flag (func_8003F414, func_80047C34) are now declared type:func in - # config/symbols.main.txt, so splat emits them on their own. - disassemble_all: false section_order: [.rodata, .text, .data, .bss] subalign: 4 segments: @@ -584,10 +573,6 @@ binaries: start: 0x800 vram: 0x80010000 subsegments: - # Each rodata block is named after the C unit that owns it, which pairs it - # for migrate_rodata_to_functions. Undotted blocks hold data that does not - # migrate (no single owning function in nonmatchings/), so it stays - # standalone. This only works with disassemble_all off — see that option. - [0x800, .rodata, main] - [0x840, .rodata, snd_note] - [0x918, .rodata, gf_curve] @@ -606,7 +591,7 @@ binaries: - [0x119C, .rodata, psxsdk/libspu] - [0x120C, .rodata, psxsdk/libetc] - [0x12BC, rodata] - - [0x14B0, .rodata, psxsdk/libcd] + - [0x149C, .rodata, psxsdk/libcd] - [0x179C, .rodata, psxsdk/libpress] - [0x17EC, rodata] - [0x1814, .rodata, psxsdk/libc] diff --git a/include/menupty.h b/include/menupty.h new file mode 100644 index 00000000..6b311c6a --- /dev/null +++ b/include/menupty.h @@ -0,0 +1,13 @@ +/** + * @file menupty.h + * @brief Symbols and types owned by the menupty overlay unit. + * + * The menupty overlay draws the party-formation screen: the character + * roster, the three active-party slots and the swap cursor. + */ +#ifndef MENUPTY_H +#define MENUPTY_H + +#include "common.h" + +#endif /* MENUPTY_H */ diff --git a/src/menu/menupty/menupty.c b/src/menu/menupty/menupty.c index 420e2adb..8ae99c6d 100644 --- a/src/menu/menupty/menupty.c +++ b/src/menu/menupty/menupty.c @@ -1,7 +1,8 @@ #include "common.h" +#include "menupty.h" -extern u8 D_801E9528[]; -extern u8 D_801E9530[]; +static const s16 D_801E9528[4]; +static const s16 D_801E9530[4]; extern u8 D_801E9540; extern u8 D_80077808[]; @@ -297,6 +298,10 @@ INCLUDE_ASM("asm/ovl/menupty/nonmatchings/menupty", func_801E7A6C); INCLUDE_ASM("asm/ovl/menupty/nonmatchings/menupty", func_801E7B9C); +/* Party slot coordinate tables */ +static const s16 D_801E9528[4] = {2, 3, -1, 0}; +static const s16 D_801E9530[4] = {1, 3, -1, 0}; + INCLUDE_ASM("asm/ovl/menupty/nonmatchings/menupty", func_801E88B4); INCLUDE_ASM("asm/ovl/menupty/nonmatchings/menupty", func_801E8964); diff --git a/tools/gen_splat_config.py b/tools/gen_splat_config.py index dbab1396..d87f723c 100644 --- a/tools/gen_splat_config.py +++ b/tools/gen_splat_config.py @@ -28,8 +28,9 @@ --out where to write each generated config, as a path template containing {name}, for example build/splat/{name}.yaml --make also write a make fragment defining _TARGET, _YAML, - _LD and _ELF for each binary, so a Makefile can use the - same paths this config gives splat instead of deriving its own + _LD, _ELF and _DIR for each binary, so a Makefile + can use the same paths this config gives splat instead of deriving + its own --check regenerate and exit non-zero if any output file would change """ import argparse @@ -92,6 +93,7 @@ def main(): f"{entry['name']}_YAML := {args.out.format(name=entry['name'])}", f"{entry['name']}_LD := {opts['ld_script_path']}", f"{entry['name']}_ELF := {opts['elf_path']}", + f"{entry['name']}_DIR := {opts['build_path']}", ] out_path = args.out.format(name=entry["name"]) os.makedirs(os.path.dirname(out_path) or ".", exist_ok=True)