diff --git a/.gitignore b/.gitignore index 4e9e089b2d..c49eca8df2 100644 --- a/.gitignore +++ b/.gitignore @@ -28,7 +28,6 @@ docs/doxygen/ *.png~ *.dol *.Identifier -*.dol F3DEX3/*/*.code F3DEX3/*/*.data wadextract/ diff --git a/.make_hackeroot.mk b/.make_hackeroot.mk index f754df3983..15cf7138d4 100644 --- a/.make_hackeroot.mk +++ b/.make_hackeroot.mk @@ -31,21 +31,6 @@ endif COMPRESSION ?= yaz COMPRESSION_TYPE ?= $(shell echo $(COMPRESSION) | tr '[:lower:]' '[:upper:]') -# Platform compatibility flags -# Default value: (nothing) -TARGET ?= -ifeq ($(TARGET),wad) -CFLAGS := -fno-reorder-blocks -fno-optimize-sibling-calls -CPP_DEFINES := -DCONSOLE_WIIVC -REVISION := 0 -REVISION := 0 -else ifeq ($(TARGET),iso) -CFLAGS := -fno-reorder-blocks -fno-optimize-sibling-calls -CPP_DEFINES := -DCONSOLE_GC -else -REVISION := 15 -endif - # Set PACKAGE_NAME define for printing commit name ifeq ($(origin PACKAGE_NAME), undefined) PACKAGE_NAME := "$(shell git log -1 --pretty=%s | tr -d '()`"\n' | tr -d "'" | sed 's/\"/\\\"/g')" @@ -127,11 +112,6 @@ F3DEX3_DIR = F3DEX3/$(F3DEX3_BASE_DIR) FLIPS := tools/Flips/flips GZINJECT := tools/gzinject/gzinject -# Temporary measure to avoid issues on ISO builds (same for `CFLAGS_IDO`). -# The real fix would be having the proper fixes in the N64 emulator itself -# but this requires some time to figure it out. -CC_IDO := tools/ido_recomp/$(DETECTED_OS)/5.3/cc - #### Files #### # Config file used for building ISOs. @@ -142,45 +122,6 @@ BASEROM_PATCH ?= baseroms/$(VERSION)/baserom.z64 #### Build Rules #### -# Build the codebase to inject in a WAD file (for Wii VC) -# Steps: -# - check if there's the common-key.bin file -# - build and compress the rom -# - inject the binary in the wad file (and apply patches) -# - remove temporary folders -wad: - $(call print_no_args,Patching WAD...) -ifeq ("$(wildcard baseroms/$(VERSION)/common-key.bin)", "") - $(error Please provide the common-key.bin file.) -endif - $(V)$(MAKE) compress TARGET=wad - $(V)$(GZINJECT) -a inject -r 1 -k baseroms/$(VERSION)/common-key.bin -w baseroms/$(VERSION)/basewad.wad -m $(ROMC) -o $(WAD) -t "HackerOoT" -i NHOE -p tools/gzinject/patches/NACE.gzi -p tools/gzinject/patches/gz_default_remap.gzi - $(V)$(RM) -r wadextract/ - $(call print_no_args,Success!) - -# Build the codebase to inject in a ISO file (for GameCube) -# Steps: -# - build and compress the rom -# - create the dma config file -# - extract the iso -# - copy the rom and dma config file to the extracted iso folder -# - remove any unnecessary files -# - apply the modifications on the emulator binary -# - pack the iso -# - remove temporary folders -iso: - $(V)$(MAKE) compress TARGET=iso - $(call print_no_args,Patching ISO...) - $(V)$(PYTHON) tools/gc_utility.py -v $(VERSION) -c $(COMPRESSION) - $(V)$(GZINJECT) -a extract -s baseroms/$(VERSION)/baseiso.iso - $(V)cp $(BUILD_DIR)/$(DMA_CONFIG_FILE) isoextract/zlj_f.tgc/$(DMA_CONFIG_FILE) - $(V)cp $(ROMC) isoextract/zlj_f.tgc/zlj_f.n64 - $(V)$(RM) -r isoextract/S_*.tgc/ isoextract/zlj_f.tgc/*.thp - $(V)$(FLIPS) --apply tools/gamecube.bps isoextract/zlj_f.tgc/main.dol isoextract/zlj_f.tgc/main.dol - $(V)$(GZINJECT) -a pack -s $(ISO) - $(V)$(RM) -r isoextract/ - $(call print_no_args,Success!) - # Create a BPS patch for the built rom # Steps: # - run Flips and create the patch @@ -223,7 +164,7 @@ verify: $(V)$(MAKE) rom @md5sum $(ROM) -.PHONY: wad iso patch create_f3dex3_patches verify +.PHONY: patch create_f3dex3_patches verify $(F3DEX3_DIR)/f3dzex2.code: $(V)dd bs=1 if=$(BASEROM_DIR)/baserom-decompressed.z64 of=$@ skip=$(UCODE_CODE_OFFSET) count=$(UCODE_CODE_SIZE) status=none @@ -236,6 +177,7 @@ $(F3DEX3_DIR)/F3DEX3%.code: $(F3DEX3_DIR)/F3DEX3%.code.bps $(F3DEX3_DIR)/f3dzex2 $(F3DEX3_DIR)/F3DEX3%.data: $(F3DEX3_DIR)/F3DEX3%.data.bps $(F3DEX3_DIR)/f3dzex2.data $(V)$(FLIPS) --apply $(F3DEX3_DIR)/F3DEX3$*.data.bps $(F3DEX3_DIR)/f3dzex2.data $@ + ### SummerCart64 Settings ### # path to the deployer program diff --git a/.make_wii-vc.mk b/.make_wii-vc.mk new file mode 100644 index 0000000000..2d6536da82 --- /dev/null +++ b/.make_wii-vc.mk @@ -0,0 +1,106 @@ +# Example usage: +# - make wad VERSION=ntsc-1.2 +# - make iso VERSION=ntsc-1.2 +# +# if building a mod for the GameCube, you will need to build this: https://github.com/Yanis002/oot-gc/tree/oot_gcc_compat +# and place the build in the baseroms folder (see `DOL` below) + +## Tools + +# You can get gzinject here https://github.com/PracticeROM/gzinject +GZINJECT ?= tools/gzinject/gzinject + +COPY ?= cp -v + +# GameCube: +# This tool generates a file that the (modified) emulator can read +# to figure out which parts of the rom to cache. +# It outputs file indices from the rom and the location and the size of `gDmaDataTable`. +GEN_DMA_CONFIG := tools/generate_dma_config.py + +# GameCube: +# This tool generates a file that the (modified) emulator can read +# to figure out where some of the N64 functions are to apply the proper hacks +# to make the game run properly. +# By default, the emulator will compute a checksum and it tries to find functions based on +# the calculated checksum and the size of the function, though this can fail completely +# since other compilers like GCC can change these values, this system is a workaround for that. +# Note: this is only useful when building with GCC. +GEN_LIB_CONFIG := tools/generate_lib_config.py + +# Wii +WAD_NAME ?= "HackerOoT" +WAD_ID ?= NHOE +WAD_REGION ?= $(REGION) + +## Files + +BASEWAD := baseroms/baserom-$(WAD_REGION).wad +COMMON_KEY := baseroms/common-key.bin +WAD := $(ROM:.z64=.wad) + +# for ISOs we pick the MQ-JP one for all versions and instead patch the emulator +BASEISO := baseroms/baserom.iso +ISO := $(ROM:.z64=.iso) +DMA_CONFIG_FILE := dma_config.bin +LIB_CONFIG_FILE := lib_config.bin + +# set to 1 to inject in MQ +MQ_INJECT ?= 0 + +ifeq ($(MQ_INJECT),1) +ROM_NAME := urazlj_f +else +ROM_NAME := zlj_f +endif + +# the emulator replacement dol, can be empty skip this step +DOL := baseroms/oot-gc.dol + +## Flags + +# wad or iso to make a compatible gcc build +TARGET ?= + +ifeq ($(COMPILER),gcc) +ifneq ($(TARGET),) +# TARGET_GC disables `.set gp=64` in exceptasm.s and the 3ms audio delay in `audio_thread_manager.c` +CFLAGS += -fno-reorder-blocks -fno-optimize-sibling-calls -fno-toplevel-reorder -DTARGET_GC -DWAD_REGION=REGION_$(WAD_REGION) +CPPFLAGS += -fno-reorder-blocks -fno-optimize-sibling-calls -fno-toplevel-reorder -DTARGET_GC -DWAD_REGION=REGION_$(WAD_REGION) +CCASFLAGS += -DTARGET_GC -DWAD_REGION=$(WAD_REGION) + +$(BUILD_DIR)/src/audio/internal/seqplayer.o: OPTFLAGS := -O1 +endif +endif + +ifeq ($(TARGET),) +TARGET := n64 +endif + +## Targets + +wad: + $(V)$(MAKE) compress TARGET=wad + $(V)$(GZINJECT) -a inject -t $(WAD_NAME) -i $(WAD_ID) -k $(COMMON_KEY) -m $(ROMC) -w $(BASEWAD) -o $(WAD) -p gzi/$(WAD_REGION).gzi -p gzi/controller.gzi + $(V)$(RM) -r wadextract/ + +# for ISOs we need to do things manually since we want to remove +# the useless files that increase the size of the file by a lot +iso: + $(V)$(MAKE) compress TARGET=iso + $(V)$(GZINJECT) -a extract -s $(BASEISO) + $(V)$(PYTHON) $(GEN_DMA_CONFIG) -v $(VERSION) + $(V)$(COPY) $(BUILD_DIR)/$(DMA_CONFIG_FILE) isoextract/zlj_f.tgc/$(DMA_CONFIG_FILE) +ifneq ($(COMPILER),ido) + $(V)$(PYTHON) $(GEN_LIB_CONFIG) -v $(VERSION) + $(V)$(COPY) $(BUILD_DIR)/$(LIB_CONFIG_FILE) isoextract/zlj_f.tgc/$(LIB_CONFIG_FILE) +endif + $(V)$(COPY) $(ROMC) isoextract/zlj_f.tgc/$(ROM_NAME).n64 +ifneq ($(DOL),) + $(V)$(COPY) $(DOL) isoextract/zlj_f.tgc/main.dol +endif + $(V)$(RM) -r isoextract/S_*.tgc/ isoextract/zlj_f.tgc/*.thp + $(V)$(GZINJECT) -a pack -s $(ISO) + $(V)$(RM) -r isoextract/ + +.PHONY: wad iso diff --git a/Makefile b/Makefile index 8a90a5c3e5..a69d40cae4 100644 --- a/Makefile +++ b/Makefile @@ -324,10 +324,6 @@ SEQ_CPPFLAGS := -D_LANGUAGE_ASEQ -DMML_VERSION=MML_VERSION_OOT $(CPP_DEFINES) - SBCFLAGS := --matching SFCFLAGS := --matching -CFLAGS += $(CPP_DEFINES) -CPPFLAGS += $(CPP_DEFINES) -CFLAGS_IDO += $(CPP_DEFINES) - # Extra debugging steps ifeq ($(DEBUG_OBJECTS),1) OBJDUMP_CMD = @$(OBJDUMP) $(OBJDUMP_FLAGS) $@ > $(@:.o=.s) @@ -382,12 +378,11 @@ SPEC := spec/spec SPEC_INCLUDES := $(wildcard spec/*.inc) # HackerOoT files -WAD := $(ROM:.z64=.wad) -ISO := $(ROM:.z64=.iso) BPS := $(ROM:.z64=.bps) UCODE_PATCHES := $(wildcard $(F3DEX3_DIR)/*.bps) UCODE_FILES := $(foreach f,$(UCODE_PATCHES:.bps=),$f) UCODE_O_FILES := $(foreach f,$(UCODE_FILES),$(BUILD_DIR)/$f.o) +-include .make_wii-vc.mk SRC_DIRS := $(shell find src -type d) UNDECOMPILED_DATA_DIRS := $(shell find data -type d) @@ -524,44 +519,6 @@ ifeq ($(COMPILER),gcc) $(BUILD_DIR)/src/%.o: CFLAGS += -fexec-charset=utf-8 $(BUILD_DIR)/src/libultra/libc/ll.o: OPTFLAGS := -Ofast $(BUILD_DIR)/src/overlays/%.o: CFLAGS += -fno-merge-constants -mno-explicit-relocs -mno-split-addresses - -## HackerOoT overrides ## - - $(BUILD_DIR)/src/overlays/actors/ovl_Item_Shield/%.o: OPTFLAGS := -O2 - $(BUILD_DIR)/src/overlays/actors/ovl_En_Part/%.o: OPTFLAGS := -O2 - $(BUILD_DIR)/src/overlays/actors/ovl_Item_B_Heart/%.o: OPTFLAGS := -O0 - $(BUILD_DIR)/src/overlays/actors/ovl_Bg_Mori_Hineri/%.o: OPTFLAGS := -O0 - -# library overrides -ifeq ($(TARGET),iso) - MIPS_VERSION_IDO := -mips2 - CFLAGS_IDO += -G 0 -non_shared -fullwarn -verbose -Xcpluscomm $(INC) -Wab,-r4300_mul -woff 516,609,649,838,712 - $(BUILD_DIR)/src/libultra/io/viswapbuf.o: OPTFLAGS := -O2 - $(BUILD_DIR)/src/libultra/io/viswapbuf.o: MIPS_VERSION := $(MIPS_VERSION_IDO) - $(BUILD_DIR)/src/libultra/io/viswapbuf.o: CFLAGS := $(CFLAGS_IDO) - $(BUILD_DIR)/src/libultra/io/viswapbuf.o: CC := $(CC_IDO) - $(BUILD_DIR)/src/libultra/gu/sinf.o: OPTFLAGS := -O2 - $(BUILD_DIR)/src/libultra/gu/sinf.o: MIPS_VERSION := $(MIPS_VERSION_IDO) - $(BUILD_DIR)/src/libultra/gu/sinf.o: CFLAGS := $(CFLAGS_IDO) - $(BUILD_DIR)/src/libultra/gu/sinf.o: CC := $(CC_IDO) - $(BUILD_DIR)/src/libultra/gu/cosf.o: OPTFLAGS := -O2 - $(BUILD_DIR)/src/libultra/gu/cosf.o: MIPS_VERSION := $(MIPS_VERSION_IDO) - $(BUILD_DIR)/src/libultra/gu/cosf.o: CFLAGS := $(CFLAGS_IDO) - $(BUILD_DIR)/src/libultra/gu/cosf.o: CC := $(CC_IDO) - $(BUILD_DIR)/src/libultra/gu/perspective.o: OPTFLAGS := -O2 - $(BUILD_DIR)/src/libultra/gu/perspective.o: MIPS_VERSION := $(MIPS_VERSION_IDO) - $(BUILD_DIR)/src/libultra/gu/perspective.o: CFLAGS := $(CFLAGS_IDO) - $(BUILD_DIR)/src/libultra/gu/perspective.o: CC := $(CC_IDO) - $(BUILD_DIR)/src/libultra/os/getmemsize.o: OPTFLAGS := -O1 - $(BUILD_DIR)/src/libultra/os/getmemsize.o: MIPS_VERSION := $(MIPS_VERSION_IDO) - $(BUILD_DIR)/src/libultra/os/getmemsize.o: CFLAGS := $(CFLAGS_IDO) - $(BUILD_DIR)/src/libultra/os/getmemsize.o: CC := $(CC_IDO) - $(BUILD_DIR)/src/libultra/os/aisetnextbuf.o: OPTFLAGS := -O1 - $(BUILD_DIR)/src/libultra/os/aisetnextbuf.o: MIPS_VERSION := $(MIPS_VERSION_IDO) - $(BUILD_DIR)/src/libultra/os/aisetnextbuf.o: CFLAGS := $(CFLAGS_IDO) - $(BUILD_DIR)/src/libultra/os/aisetnextbuf.o: CC := $(CC_IDO) -endif - endif #### Main Targets ### @@ -654,6 +611,7 @@ $(ROM): $(ELF) @$(PRINT) "${GREEN}Rom Path: $(BLUE)$(ROM)$(NO_COL)\n" @$(PRINT) "${GREEN}Build Author: $(BLUE)$(PACKAGE_AUTHOR)$(NO_COL)\n" @$(PRINT) "${GREEN}Commit Author: $(BLUE)$(PACKAGE_COMMIT_AUTHOR)$(NO_COL)\n" + @$(PRINT) "${GREEN}Target: $(BLUE)$(TARGET)$(NO_COL)\n" ifeq ($(TESTSUITE_MODE),1) @$(PRINT) "${GREEN}Made with HackerTestSuite$(NO_COL)\n" endif diff --git a/gzi/JP.gzi b/gzi/JP.gzi new file mode 100644 index 0000000000..28415cb8f8 --- /dev/null +++ b/gzi/JP.gzi @@ -0,0 +1,6 @@ +# default gz patches for NACJ +0000 00000000 00000001 +# use 8MB memory +0304 00002EB0 60000000 +# allocate 32MB for rom +0304 0005BF44 3C807200 diff --git a/gzi/US.gzi b/gzi/US.gzi new file mode 100644 index 0000000000..30ab26f558 --- /dev/null +++ b/gzi/US.gzi @@ -0,0 +1,6 @@ +# default gz patches for NACE +0000 00000000 00000001 +# use 8MB memory +0304 00002EB0 60000000 +# allocate 32MB for rom +0304 0005BFD4 3C807200 diff --git a/gzi/controller.gzi b/gzi/controller.gzi new file mode 100644 index 0000000000..22b857ac4e --- /dev/null +++ b/gzi/controller.gzi @@ -0,0 +1,9 @@ +# gz standard remapping for NACE and NACJ +0000 00000000 00000001 +# apply d-pad remappings +0302 0016BAF0 00000800 +0302 0016BAF4 00000400 +0302 0016BAF8 00000200 +0302 0016BAFC 00000100 +# apply c-stick remapping +0302 0016BB04 00000020 diff --git a/include/config/config_safeguards.h b/include/config/config_safeguards.h index 4ee725797c..4be7ff944b 100644 --- a/include/config/config_safeguards.h +++ b/include/config/config_safeguards.h @@ -141,18 +141,16 @@ /***************** * config_graphics.h */ -//! TODO: implement better Wii VC compatibility -#ifdef CONSOLE_WIIVC - #undef ENABLE_F3DEX3 +//! TODO: implement better Wii VC compatibility for Motion Blur and F3DEX3 +#ifdef TARGET_GC #undef ENABLE_MOTION_BLUR - - #define ENABLE_F3DEX3 false #define ENABLE_MOTION_BLUR false -#endif -#ifdef CONSOLE_GC #undef ENABLE_F3DEX3 #define ENABLE_F3DEX3 false + + #undef AUDIO_DELAY + #define AUDIO_DELAY false #endif #if ENABLE_PROFILER && !ENABLE_HACKER_DEBUG diff --git a/src/audio/internal/heap.c b/src/audio/internal/heap.c index d91ccf0405..43cff692be 100644 --- a/src/audio/internal/heap.c +++ b/src/audio/internal/heap.c @@ -732,7 +732,7 @@ void AudioHeap_LoadFilter(s16* filter, s32 lowPassCutoff, s32 highPassCutoff) { } // Write back the cache line for this filter -#if defined(CONSOLE_WIIVC) || defined(CONSOLE_GC) +#ifdef TARGET_GC osWritebackDCache(filter, 8 * sizeof(s16)); #else asm("cache %0, (%1)" ::"i"(CACH_PD | C_HWBINV), "r"(filter)); diff --git a/src/libultra/os/exceptasm.s b/src/libultra/os/exceptasm.s index 7f46a70497..2b5a009d83 100644 --- a/src/libultra/os/exceptasm.s +++ b/src/libultra/os/exceptasm.s @@ -1,3 +1,6 @@ +#if (defined __GNUC__) && !(defined TARGET_GC) +.set gp=64 +#endif #include "ultra64/asm.h" #include "ultra64/regdef.h" #include "ultra64/R4300.h" diff --git a/src/libultra/os/thread.c b/src/libultra/os/thread.c index 83d924cc96..b864c9a703 100644 --- a/src/libultra/os/thread.c +++ b/src/libultra/os/thread.c @@ -1,11 +1,11 @@ #include "ultra64.h" #include "attributes.h" -NO_REORDER __OSThreadTail __osThreadTail = { NULL, OS_PRIORITY_THREADTAIL }; -NO_REORDER OSThread* __osRunQueue = (OSThread*)&__osThreadTail; -NO_REORDER OSThread* __osActiveQueue = (OSThread*)&__osThreadTail; -NO_REORDER OSThread* __osRunningThread = NULL; -NO_REORDER OSThread* __osFaultedThread = NULL; +SECTION_DATA NO_REORDER __OSThreadTail __osThreadTail = { NULL, OS_PRIORITY_THREADTAIL }; +SECTION_DATA NO_REORDER OSThread* __osRunQueue = (OSThread*)&__osThreadTail; +SECTION_DATA NO_REORDER OSThread* __osActiveQueue = (OSThread*)&__osThreadTail; +SECTION_DATA NO_REORDER OSThread* __osRunningThread = NULL; +SECTION_DATA NO_REORDER OSThread* __osFaultedThread = NULL; void __osDequeueThread(register OSThread** queue, register OSThread* thread) { register OSThread* pred = (OSThread*)queue; diff --git a/src/makerom/rom_header.s b/src/makerom/rom_header.s index b5f23de499..4a441a94c6 100644 --- a/src/makerom/rom_header.s +++ b/src/makerom/rom_header.s @@ -15,15 +15,13 @@ /* 0x18 */ PADDING(8) /* 0x20 */ ROM_NAME("THE LEGEND OF ZELDA") /* 0x34 */ PADDING(7) -#if OOT_NTSC || ((defined CONSOLE_WIIVC) || (defined CONSOLE_GC)) +#if OOT_NTSC || (defined TARGET_GC) /* 0x3B */ MEDIUM(CARTRIDGE_EXPANDABLE) #else /* 0x3B */ MEDIUM(CARTRIDGE) #endif /* 0x3C */ GAME_ID("ZL") -#if (defined CONSOLE_WIIVC) || (defined CONSOLE_GC) -/* 0x3E */ REGION(US) -#elif OOT_REGION == REGION_NULL +#if OOT_REGION == REGION_NULL /* 0x3E */ REGION(FREE) #elif OOT_REGION == REGION_US /* 0x3E */ REGION(US) diff --git a/tools/gc_utility.py b/tools/generate_dma_config.py old mode 100755 new mode 100644 similarity index 56% rename from tools/gc_utility.py rename to tools/generate_dma_config.py index 31f341c5ed..890c4e2cd0 --- a/tools/gc_utility.py +++ b/tools/generate_dma_config.py @@ -3,6 +3,8 @@ import argparse import mapfile_parser import sys +import struct + from io import StringIO from pathlib import Path from dataclasses import dataclass @@ -37,21 +39,18 @@ class DmaEntry: args = parser.parse_args() VERSION = args.version - DMATABLE_PATH = f"build/{VERSION}/dmadata_table_spec.h" - ROM_PATH = f"build/{VERSION}/hackeroot-{VERSION}-compressed-{args.codec}.z64" + DMATABLE_PATH = Path(f"build/{VERSION}/dmadata_table_spec.h").resolve() sceneFiles: list[DmaInfo] = [] otherFiles: list[DmaInfo] = [] allFiles: list[DmaInfo] = [] - with open(DMATABLE_PATH, "r") as file: - dmaTable = file.readlines() - + dmaTable = DMATABLE_PATH.read_text().split("\n") for i, dmaEntry in enumerate(dmaTable): entryName = dmaEntry.removeprefix("DEFINE_DMA_ENTRY(").removesuffix(")").split(", ")[0] allFiles.append(DmaInfo(entryName, i)) if entryName.endswith("_scene"): sceneFiles.append(DmaInfo(entryName, i)) - if entryName in { "code", "ovl_title", "vr_fine1_static", "elf_message_field", "elf_message_ydan"}: + if entryName in { "code", "ovl_title", "vr_holy0_static", "elf_message_field", "ydan_scene"}: otherFiles.append(DmaInfo(entryName, i)) i = sceneFiles[-1].index @@ -65,35 +64,37 @@ class DmaEntry: ret = mapfile_parser.frontends.sym_info.doSymInfo(mapPath, "gDmaDataTable") assert ret == 0 split = stdout[0].removesuffix(")").split("(")[1].split(", ") - dmaVrom = split[1] - dmaSize = split[2] + table_offset = int(split[1].removeprefix('VROM: '), 16) + table_size = int(split[2].removeprefix('SIZE: '), 16) - with open(ROM_PATH, "rb") as file: - file.seek(int(dmaVrom.removeprefix('VROM: '), 16)) - rom_data = bytearray(file.read(int(dmaSize.removeprefix('SIZE: '), 16))) + dbg_output = "--- Debug Informations ---\n" + files = otherFiles + sceneFiles + data = [] + for info in files: + data.append(struct.pack(">H", info.index)) + dbg_output += f"- {info.index:04}; {repr(info.name)}\n" - temp: list[bytearray] = [] - for i in range(0, len(rom_data), 16): - temp.append(rom_data[i:i + 16]) + data_bytes = b"".join(data) + while len(data_bytes) % 32: + data_bytes += b"".join([struct.pack(">x")]) - dmaTable: list[DmaEntry] = [] - for data in temp: - dmaTable.append( - DmaEntry( - f"0x{int.from_bytes(data[:4], byteorder='big', signed=False):08X}", - f"0x{int.from_bytes(data[4:8], byteorder='big', signed=False):08X}", - f"0x{int.from_bytes(data[8:12], byteorder='big', signed=False):08X}", - f"0x{int.from_bytes(data[12:16], byteorder='big', signed=False):08X}", - ) - ) + # header + output = b"".join( + [ + "DMAC".encode("utf-8"), + struct.pack(">I", table_offset), + struct.pack(">H", table_size), + struct.pack(">H", len(data_bytes)), + struct.pack(">H", len(data)), + ] + ) + while len(output) % 32: + output += b"".join([struct.pack(">x")]) - output = f"{(len(otherFiles) + 1) * 16:016}" # scene offset - for info in otherFiles: - entry = dmaTable[info.index] - output += f"{int(entry.romStart, 16):016}" - for info in sceneFiles: - entry = dmaTable[info.index] - output += f"{int(entry.romStart, 16):016}" + # data + output += data_bytes + while len(output) % 32: + output += b"".join([struct.pack(">x")]) - with open("build/" + VERSION + "/dma_config.txt", "w") as file: - file.write(output) + out = Path("build/" + VERSION + "/dma_config.bin").resolve() + out.write_bytes(output) diff --git a/tools/generate_lib_config.py b/tools/generate_lib_config.py new file mode 100644 index 0000000000..a7bfbd1f45 --- /dev/null +++ b/tools/generate_lib_config.py @@ -0,0 +1,154 @@ +#!/usr/bin/env python3 + +import argparse +import mapfile_parser +import sys +import struct + +from io import StringIO +from pathlib import Path +from dataclasses import dataclass + +# from https://stackoverflow.com/a/16571630 +class Capturing(list): + def __enter__(self): + self._stdout = sys.stdout + sys.stdout = self._stringio = StringIO() + return self + def __exit__(self, *args): + self.extend(self._stringio.getvalue().splitlines()) + del self._stringio # free up some memory + sys.stdout = self._stdout + +# - function name +# - function address +# - function size + +@dataclass +class SymInfo: + name: str + vram: int + vrom: int + size: int + o_path: Path + +def get_sym_info(map_path: Path, symbol: str): + with Capturing() as stdout: + ret = mapfile_parser.frontends.sym_info.doSymInfo(map_path, symbol) + assert ret == 0, f"failed with {symbol}" + + split = stdout[0].removesuffix(")").split("(") + split2 = split[1].split(", ") + + return SymInfo( + split[0].split(" ")[1].removeprefix("'").removesuffix("'"), + int(split2[0].split(" ")[1], 16), + int(split2[1].split(" ")[1], 16), + int(split2[2].split(" ")[1], 16), + Path(split2[3]).resolve(), + ) + +funcs_to_process = [ + # "send_mesg", + # "__osEnqueueAndYield", + # "__osEnqueueThread", + # "__osPopThread", + # "__osDispatchThread", + "osGetMemSize", + "osInvalDCache", + "osInvalICache", + "osWritebackDCache", + "osWritebackDCacheAll", + "__osDisableInt", + "__osRestoreInt", + "__osSpSetStatus", + "cosf", + "sinf", + "bzero", + "bcopy", + "memcpy", + "osVirtualToPhysical", + # "osPhysicalToVirtual", + "guMtxF2L", + # "guMtxCatF", + "guMtxIdentF", + "guMtxIdent", + "guOrthoF", + "guOrtho", + "guPerspectiveF", + "guPerspective", + # "guScaleF", + "guScale", + "guRotateF", + "guRotate", + # "guTranslateF", + "guTranslate", + "guLookAtF", + "guLookAt", + "guLookAtHiliteF", + "guLookAtHilite", + # "guLookAtReflectF", + # "guLookAtReflect", + "osAiSetFrequency", + "osAiSetNextBuffer", + # "__osEepStatus", + # "osEepromRead", + # "osEepromWrite", + # "osEepromLongRead", + # "osEepromLongWrite", + "osGetCount", + "osViSwapBuffer", +] + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="gamecube utility") + parser.add_argument("-v", "--version", help="OoT Version", default="ntsc-1.2") + parser.add_argument("-c", "--codec", help="Compression Codec", default="yaz") + args = parser.parse_args() + + VERSION = args.version + map_file = f"hackeroot-{VERSION}.map" + ROM_PATH = Path(f"build/{VERSION}/hackeroot-{VERSION}.z64").resolve() + BUILTMAP = Path("build") / VERSION / map_file + + # header + output = b"".join( + [ + "LIBC".encode("utf-8"), + struct.pack(">H", len(funcs_to_process)), + ] + ) + while len(output) % 32: + output += b"".join([struct.pack(">x")]) + + for func in funcs_to_process: + sym_info = get_sym_info(BUILTMAP, func) + + with ROM_PATH.open("rb") as file: + file.seek(sym_info.vrom) + rom_data = file.read(sym_info.size) + + name = sym_info.name + + match name: + case "cosf": + name = "__cosf" + case "sinf": + name = "__sinf" + case "osViSwapBuffer": + name = "osViSwapBuffer_Entry" + + entry = b"".join( + [ + struct.pack(">I", sym_info.vram), + struct.pack(">I", sym_info.size), + name.encode("utf-8"), + ] + ) + while len(entry) % 0x20: + entry += b"".join([struct.pack(">x")]) + + output += entry + + out = Path("build/" + VERSION + "/lib_config.bin").resolve() + out.write_bytes(output)