From 39cad904b16ad7c0377212aa5c99939a23c2cab3 Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Mon, 26 May 2025 19:42:18 +0200 Subject: [PATCH 1/8] wii vc fix --- .gitignore | 1 + .make_wii-vc.mk | 100 ++++++++++++ Makefile | 74 +-------- gzi/JP.gzi | 6 + gzi/US.gzi | 6 + gzi/controller.gzi | 9 + include/config/config_safeguards.h | 10 +- src/libultra/os/exceptasm.s | 2 +- src/libultra/os/thread.c | 10 +- src/makerom/rom_header.s | 6 +- .../{gc_utility.py => generate_dma_config.py} | 70 ++++---- tools/generate_lib_config.py | 154 ++++++++++++++++++ 12 files changed, 326 insertions(+), 122 deletions(-) create mode 100644 .make_wii-vc.mk create mode 100644 gzi/JP.gzi create mode 100644 gzi/US.gzi create mode 100644 gzi/controller.gzi rename tools/{gc_utility.py => generate_dma_config.py} (54%) mode change 100755 => 100644 create mode 100644 tools/generate_lib_config.py diff --git a/.gitignore b/.gitignore index e49807cbb4..6931c83c00 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ docs/doxygen/ *.iso *.bin *.blend1 +*.dol F3DEX3/*.code F3DEX3/*.data wadextract/ diff --git a/.make_wii-vc.mk b/.make_wii-vc.mk new file mode 100644 index 0000000000..8bf23bc720 --- /dev/null +++ b/.make_wii-vc.mk @@ -0,0 +1,100 @@ +# 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 ?= gzinject + +COPY ?= cp -v + +# 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 + +# 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 + +## Files + +BASEWAD := baseroms/baserom-$(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),) +CFLAGS += -fno-reorder-blocks -fno-optimize-sibling-calls -fno-toplevel-reorder +CPPFLAGS += -fno-reorder-blocks -fno-optimize-sibling-calls -fno-toplevel-reorder + +# Disables `.set gp=64` in exceptasm.s +CCASFLAGS += -DTARGET_GC + +$(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 -r 1 -t "HackerOoT" -i NHOE -k $(COMMON_KEY) -m $(ROMC) -w $(BASEWAD) -o $(WAD) -p gzi/$(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 aa243111c6..4786d98883 100644 --- a/Makefile +++ b/Makefile @@ -183,20 +183,14 @@ else ifeq ($(VERSION),ique-cn) BUILD_TIME := 16:23:19 REVISION := 0 else ifeq ($(VERSION),hackeroot-mq) - REGION := NULL + REGION ?= JP PLATFORM := GC DEBUG := 1 DEBUG_FEATURES ?= 1 BUILD_CREATOR := none BUILD_DATE := none BUILD_TIME := none -ifeq ($(TARGET),iso) - REVISION := 0 -else ifeq ($(TARGET),wad) - REVISION := 0 -else REVISION := 15 -endif else $(error Unsupported version $(VERSION)) endif @@ -449,13 +443,10 @@ else ROM := $(BUILD_DIR)/oot-$(VERSION).z64 endif ROMC := $(ROM:.z64=-compressed-$(COMPRESSION).z64) -WAD := $(ROM:.z64=.wad) -ISO := $(ROM:.z64=.iso) BPS := $(ROM:.z64=.bps) ELF := $(ROM:.z64=.elf) MAP := $(ROM:.z64=.map) LDSCRIPT := $(ROM:.z64=.ld) -DMA_CONFIG_FILE := dma_config.txt # description of ROM segments SPEC := spec/spec @@ -599,43 +590,10 @@ 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 - - $(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 for Gamecube -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 +-include .make_wii-vc.mk + #### Main Targets ### all: rom @@ -653,29 +611,6 @@ compress: $(V)$(MAKE) $(ROMC) $(call print_no_args,Success!) -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!) - -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!) - clean: $(V)$(RM) -r $(BUILD_DIR) $(call print_no_args,Success!) @@ -749,7 +684,7 @@ verify: $(V)$(MAKE) rom @md5sum $(ROM) -.PHONY: all rom compress clean assetclean distclean venv setup run wad iso patch create_f3dex3_patches verify +.PHONY: all rom compress clean assetclean distclean venv setup run patch create_f3dex3_patches verify .DEFAULT_GOAL := rom @@ -777,6 +712,7 @@ $(ROM): $(ELF) @$(PRINT) "${GREEN}Code Version: $(BLUE)$(PACKAGE_VERSION)$(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" $(ROMC): $(ROM) $(ELF) $(BUILD_DIR)/compress_ranges.txt ifeq ($(USE_WRAPPER),0) 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 5e91095084..60b1fb0169 100644 --- a/include/config/config_safeguards.h +++ b/include/config/config_safeguards.h @@ -146,19 +146,11 @@ * config_graphics.h */ //! TODO: implement better Wii VC compatibility -#ifdef CONSOLE_WIIVC - #undef ENABLE_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 -#endif - /** * Default settings if not using HackerOoT mode diff --git a/src/libultra/os/exceptasm.s b/src/libultra/os/exceptasm.s index 3a3919061c..009db82db0 100644 --- a/src/libultra/os/exceptasm.s +++ b/src/libultra/os/exceptasm.s @@ -1,4 +1,4 @@ -#ifdef __GNUC__ +#if (defined __GNUC__) && !(defined TARGET_GC) .set gp=64 #endif #include "ultra64/asm.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 54% rename from tools/gc_utility.py rename to tools/generate_dma_config.py index c6d1943abe..007ab1bd40 --- 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 @@ -32,26 +34,24 @@ class DmaEntry: if __name__ == "__main__": parser = argparse.ArgumentParser(description="gamecube utility") - parser.add_argument("-v", "--version", help="OoT Version", default="hackeroot-mq") + parser.add_argument("-v", "--version", help="OoT Version", default="gc-jp") parser.add_argument("-c", "--codec", help="Compression Codec", default="yaz") args = parser.parse_args() VERSION = args.version - DMATABLE_PATH = f"build/{VERSION}/dmadata_table_spec.h" - ROM_PATH = f"build/{VERSION}/{'oot-' if VERSION != 'hackeroot-mq' else ''}{VERSION}-compressed{'-' + args.codec if VERSION == 'hackeroot-mq' else ''}.z64" + DMATABLE_PATH = Path(f"build/{VERSION}/dmadata_table_spec.h").resolve() + ROM_PATH = f"build/{VERSION}/oot-{VERSION}-compressed.z64" 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 +65,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..a3d34c04f4 --- /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="hackeroot-mq") + parser.add_argument("-c", "--codec", help="Compression Codec", default="yaz") + args = parser.parse_args() + + VERSION = args.version + map_file = f"hackeroot-mq.map" if VERSION == "hackeroot-mq" else f"oot-{VERSION}.map" + ROM_PATH = Path(f"build/{VERSION}/hackeroot-mq.z64" if VERSION == "hackeroot-mq" else f"build/{VERSION}/oot-{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) From 59a293467b836d07b0894e2d1a73e7fee234162c Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Mon, 26 May 2025 20:00:09 +0200 Subject: [PATCH 2/8] build issues --- .make_wii-vc.mk | 2 +- Makefile | 15 +++------------ 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/.make_wii-vc.mk b/.make_wii-vc.mk index 8bf23bc720..552fff80a2 100644 --- a/.make_wii-vc.mk +++ b/.make_wii-vc.mk @@ -63,7 +63,7 @@ CPPFLAGS += -fno-reorder-blocks -fno-optimize-sibling-calls -fno-toplevel-reorde # Disables `.set gp=64` in exceptasm.s CCASFLAGS += -DTARGET_GC -$(BUILD_DIR)/src/audio/internal/seqplayer.o: OPTFLAGS := -O1 +$(BUILD_DIR)/src/audio/lib/seqplayer.o: OPTFLAGS := -O1 endif endif diff --git a/Makefile b/Makefile index 4786d98883..69ca823422 100644 --- a/Makefile +++ b/Makefile @@ -59,11 +59,6 @@ N64_EMULATOR ?= # This may also be used to disable debug features on debug ROMs by setting DEBUG_FEATURES to 0 # DEBUG_FEATURES ?= 1 -CFLAGS ?= -CPPFLAGS ?= -CFLAGS_IDO ?= -CPP_DEFINES ?= - # Version-specific settings REGIONAL_CHECKSUM := 0 ifeq ($(VERSION),ntsc-1.0) @@ -284,7 +279,6 @@ ifeq ($(VERSION),hackeroot-mq) ifeq ($(RELEASE),1) CPP_DEFINES += -DRELEASE_ROM=1 -DDEBUG_FEATURES=0 -DNDEBUG - CFLAGS_IDO += -DDEBUG_FEATURES=0 else CPP_DEFINES += -DRELEASE_ROM=0 -DDEBUG_FEATURES=1 endif @@ -381,7 +375,6 @@ FADO := tools/fado/fado.elf PYTHON ?= $(VENV)/bin/python3 FLIPS := tools/Flips/flips GZINJECT := tools/gzinject/gzinject -CC_IDO := tools/ido_recomp/$(DETECTED_OS)/5.3/cc # Command to replace $(BUILD_DIR) in some files with the build path. # We can't use the C preprocessor for this because it won't substitute inside string literals. @@ -401,10 +394,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) @@ -582,7 +571,9 @@ $(shell mkdir -p $(foreach dir, \ endif $(BUILD_DIR)/src/boot/build.o: CPP_DEFINES += -DBUILD_CREATOR="\"$(BUILD_CREATOR)\"" -DBUILD_DATE="\"$(BUILD_DATE)\"" -DBUILD_TIME="\"$(BUILD_TIME)\"" -$(BUILD_DIR)/src/audio/lib/seqplayer.o: CPP_DEFINES += -DMML_VERSION=MML_VERSION_OOT + +$(BUILD_DIR)/src/audio/lib/seqplayer.o: CFLAGS += -DMML_VERSION=MML_VERSION_OOT +$(BUILD_DIR)/src/audio/lib/seqplayer.o: CPPFLAGS += -DMML_VERSION=MML_VERSION_OOT ifeq ($(COMPILER),gcc) # Note that if adding additional assets directories for modding reasons these flags must also be used there From bca473998aaff01416dfb12bd91a4fba6e399ad9 Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Tue, 27 May 2025 17:41:24 +0200 Subject: [PATCH 3/8] fix audio lag!!! --- .make_wii-vc.mk | 3 ++- src/code/audio_thread_manager.c | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.make_wii-vc.mk b/.make_wii-vc.mk index 552fff80a2..70558d49f7 100644 --- a/.make_wii-vc.mk +++ b/.make_wii-vc.mk @@ -60,7 +60,8 @@ ifneq ($(TARGET),) CFLAGS += -fno-reorder-blocks -fno-optimize-sibling-calls -fno-toplevel-reorder CPPFLAGS += -fno-reorder-blocks -fno-optimize-sibling-calls -fno-toplevel-reorder -# Disables `.set gp=64` in exceptasm.s +# Disables `.set gp=64` in exceptasm.s and the 3ms audio delay in `audio_thread_manager.c` +CFLAGS += -DTARGET_GC CCASFLAGS += -DTARGET_GC $(BUILD_DIR)/src/audio/lib/seqplayer.o: OPTFLAGS := -O1 diff --git a/src/code/audio_thread_manager.c b/src/code/audio_thread_manager.c index a6dfe341d0..90da4001a3 100644 --- a/src/code/audio_thread_manager.c +++ b/src/code/audio_thread_manager.c @@ -28,7 +28,9 @@ void AudioMgr_NotifyTaskDone(AudioMgr* audioMgr) { void AudioMgr_HandleRetrace(AudioMgr* audioMgr) { AudioTask* rspTask; - // Delay the audio update by 3ms so that gfx has time to get going before it has to yield + // Delay the audio update by 3ms so that gfx has time to get going before it has to yield. + // On the N64 Emulator for the GameCube and the Wii it causes severe audio lag. +#ifndef TARGET_GC OSTimer timer; OSMesgQueue mq; OSMesg mbuf; @@ -36,6 +38,7 @@ void AudioMgr_HandleRetrace(AudioMgr* audioMgr) { osSetTimer(&timer, OS_USEC_TO_CYCLES(3000), 0, &mq, NULL); osRecvMesg(&mq, NULL, OS_MESG_BLOCK); osStopTimer(&timer); +#endif if (R_AUDIOMGR_DEBUG_LEVEL > AUDIOMGR_DEBUG_LEVEL_NONE) { // Inhibit audio rsp task processing From 4dda3269b3882b91fda21e85093bc0986f9088dc Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Tue, 27 May 2025 17:52:54 +0200 Subject: [PATCH 4/8] remove useless stuff --- .make_hackeroot.mk | 11 ----------- src/audio/lib/heap.c | 2 +- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/.make_hackeroot.mk b/.make_hackeroot.mk index f42de8bd0c..6fa560aa1a 100644 --- a/.make_hackeroot.mk +++ b/.make_hackeroot.mk @@ -33,17 +33,6 @@ RELEASE := 0 COMPRESSION ?= yaz COMPRESSION_TYPE ?= $(shell echo $(COMPRESSION) | tr '[:lower:]' '[:upper:]') -# Platform compatibility flags -TARGET ?= - -ifeq ($(TARGET),wad) -CFLAGS := -DCONSOLE_WIIVC -fno-reorder-blocks -fno-optimize-sibling-calls -CPPFLAGS := -DCONSOLE_WIIVC -else ifeq ($(TARGET),iso) -CFLAGS := -DCONSOLE_GC -fno-reorder-blocks -fno-optimize-sibling-calls -CPPFLAGS := -DCONSOLE_GC -endif - ### SummerCart64 Settings ### # path to the deployer program diff --git a/src/audio/lib/heap.c b/src/audio/lib/heap.c index e00d80ec83..2c3213a0e8 100644 --- a/src/audio/lib/heap.c +++ b/src/audio/lib/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)); From 6aa4ed8e168907fc3ddce76a6996adadd4adbe49 Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Wed, 2 Jul 2025 14:53:34 +0200 Subject: [PATCH 5/8] oopsies --- .make_hackeroot.mk | 41 +---------------------------------------- 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/.make_hackeroot.mk b/.make_hackeroot.mk index a9b2676ba7..7ac4914f4c 100644 --- a/.make_hackeroot.mk +++ b/.make_hackeroot.mk @@ -119,45 +119,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 @@ -200,7 +161,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 From a8bf02526d28ed696977058a9b916b75a29c6eb5 Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Wed, 2 Jul 2025 15:12:07 +0200 Subject: [PATCH 6/8] oopsies 2 --- tools/generate_lib_config.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/generate_lib_config.py b/tools/generate_lib_config.py index a3d34c04f4..a7bfbd1f45 100644 --- a/tools/generate_lib_config.py +++ b/tools/generate_lib_config.py @@ -102,13 +102,13 @@ def get_sym_info(map_path: Path, symbol: str): if __name__ == "__main__": parser = argparse.ArgumentParser(description="gamecube utility") - parser.add_argument("-v", "--version", help="OoT Version", default="hackeroot-mq") + 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-mq.map" if VERSION == "hackeroot-mq" else f"oot-{VERSION}.map" - ROM_PATH = Path(f"build/{VERSION}/hackeroot-mq.z64" if VERSION == "hackeroot-mq" else f"build/{VERSION}/oot-{VERSION}.z64").resolve() + map_file = f"hackeroot-{VERSION}.map" + ROM_PATH = Path(f"build/{VERSION}/hackeroot-{VERSION}.z64").resolve() BUILTMAP = Path("build") / VERSION / map_file # header From 5e5814cbc1c092f6fdf507d151015a4be7fca344 Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Thu, 11 Dec 2025 00:55:58 +0100 Subject: [PATCH 7/8] fix build issues --- .make_wii-vc.mk | 10 ++++------ Makefile | 3 +-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/.make_wii-vc.mk b/.make_wii-vc.mk index 70558d49f7..06abe0532e 100644 --- a/.make_wii-vc.mk +++ b/.make_wii-vc.mk @@ -57,12 +57,10 @@ TARGET ?= ifeq ($(COMPILER),gcc) ifneq ($(TARGET),) -CFLAGS += -fno-reorder-blocks -fno-optimize-sibling-calls -fno-toplevel-reorder -CPPFLAGS += -fno-reorder-blocks -fno-optimize-sibling-calls -fno-toplevel-reorder - -# Disables `.set gp=64` in exceptasm.s and the 3ms audio delay in `audio_thread_manager.c` -CFLAGS += -DTARGET_GC -CCASFLAGS += -DTARGET_GC +# TARGET_GC disables `.set gp=64` in exceptasm.s and the 3ms audio delay in `audio_thread_manager.c` +# TODO: implement better Wii VC compatibility for F3DEX3 +CFLAGS += -fno-reorder-blocks -fno-optimize-sibling-calls -fno-toplevel-reorder -DTARGET_GC +CPPFLAGS += -fno-reorder-blocks -fno-optimize-sibling-calls -fno-toplevel-reorder -DTARGET_GC $(BUILD_DIR)/src/audio/lib/seqplayer.o: OPTFLAGS := -O1 endif diff --git a/Makefile b/Makefile index 80e449e15a..a69d40cae4 100644 --- a/Makefile +++ b/Makefile @@ -382,6 +382,7 @@ 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) @@ -520,8 +521,6 @@ ifeq ($(COMPILER),gcc) $(BUILD_DIR)/src/overlays/%.o: CFLAGS += -fno-merge-constants -mno-explicit-relocs -mno-split-addresses endif --include .make_wii-vc.mk - #### Main Targets ### all: rom From eb238245323ff8cae2f63ba3961a61628cc8f07d Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Thu, 11 Dec 2025 14:39:03 +0100 Subject: [PATCH 8/8] fixed boot issues and improvements --- .make_wii-vc.mk | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/.make_wii-vc.mk b/.make_wii-vc.mk index 06abe0532e..2d6536da82 100644 --- a/.make_wii-vc.mk +++ b/.make_wii-vc.mk @@ -8,15 +8,17 @@ ## Tools # You can get gzinject here https://github.com/PracticeROM/gzinject -GZINJECT ?= 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. @@ -26,9 +28,14 @@ GEN_DMA_CONFIG := tools/generate_dma_config.py # 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-$(REGION).wad +BASEWAD := baseroms/baserom-$(WAD_REGION).wad COMMON_KEY := baseroms/common-key.bin WAD := $(ROM:.z64=.wad) @@ -58,11 +65,11 @@ 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` -# TODO: implement better Wii VC compatibility for F3DEX3 -CFLAGS += -fno-reorder-blocks -fno-optimize-sibling-calls -fno-toplevel-reorder -DTARGET_GC -CPPFLAGS += -fno-reorder-blocks -fno-optimize-sibling-calls -fno-toplevel-reorder -DTARGET_GC +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/lib/seqplayer.o: OPTFLAGS := -O1 +$(BUILD_DIR)/src/audio/internal/seqplayer.o: OPTFLAGS := -O1 endif endif @@ -74,7 +81,7 @@ endif wad: $(V)$(MAKE) compress TARGET=wad - $(V)$(GZINJECT) -a inject -r 1 -t "HackerOoT" -i NHOE -k $(COMMON_KEY) -m $(ROMC) -w $(BASEWAD) -o $(WAD) -p gzi/$(REGION).gzi -p gzi/controller.gzi + $(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