Skip to content

Commit 8c94dc8

Browse files
authored
Add hacks to fix PCH .data causing fake mismatches with decompctx (#2606)
1 parent abf5f59 commit 8c94dc8

File tree

8 files changed

+99
-7
lines changed

8 files changed

+99
-7
lines changed

configure.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,13 @@
220220
# Can be overridden in libraries or objects
221221
config.scratch_preset_id = 69 # Twilight Princess (DOL)
222222

223+
# Globs to exclude from context files
224+
# *.mch excludes precompiled header output (which cannot be parsed)
225+
config.context_exclude_globs = ["*.mch"]
226+
227+
# Macro definitions to inject into context files
228+
config.context_defines = ["DECOMPCTX"]
229+
223230
# Base flags, common to most GC/Wii games.
224231
# Generally leave untouched, with overrides added below.
225232
cflags_base = [

include/JSystem/J3DGraphBase/J3DMatBlock.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,12 @@ inline u16 calcColorChanID(u16 enable, u8 matSrc, u8 lightMask, u8 diffuseFn, u8
103103
return reg;
104104
}
105105

106+
#ifdef DECOMPCTX
107+
// Hack to mitigate fake mismatches when building from decompctx output -
108+
// see comment in sqrtf in math.h
109+
static u8 AttnArr[] = {2, 0, 2, 1};
110+
#endif
111+
106112
/**
107113
* @ingroup jsystem-j3d
108114
*
@@ -138,7 +144,9 @@ struct J3DColorChan {
138144
u8 getMatSrc() const { return (GXColorSrc)(mColorChanID & 1); }
139145
u8 getDiffuseFn() const { return ((u32)(mColorChanID & (3 << 7)) >> 7); }
140146
u8 getAttnFn() const {
147+
#ifndef DECOMPCTX
141148
u8 AttnArr[] = {2,0,2,1};
149+
#endif
142150
return AttnArr[(u32)(mColorChanID & (3 << 9)) >> 9];
143151
}
144152

include/Z2AudioLib/Z2Calc.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@
55
#include "m_Do/m_Do_lib.h"
66

77
namespace Z2Calc {
8-
// hack for f_op_actor, having this present breaks its weak func ordering
8+
#ifdef DECOMPCTX
9+
// Hack to mitigate fake mismatches when building from decompctx output -
10+
// see comment in sqrtf in math.h
11+
static Vec cNullVec = {0.0f, 0.0f, 0.0f};
12+
#else
913
static const Vec cNullVec = {0.0f, 0.0f, 0.0f};
14+
#endif
1015

1116
enum CurveSign {
1217
CURVE_SIGN_0 = 0,

include/d/dolzel.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#ifndef DOLZEL_H
22
#define DOLZEL_H
33

4-
#if __MWERKS__
4+
#if __MWERKS__ && !defined(DECOMPCTX)
55
#include "d/dolzel.mch"
66
#else
77
#include "d/dolzel.pch"

include/d/dolzel_rel.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#ifndef DOLZEL_REL_H
22
#define DOLZEL_REL_H
33

4-
#if __MWERKS__
4+
#if __MWERKS__ && !defined(DECOMPCTX)
55
#include "d/dolzel_rel.mch"
66
#else
77
#include "d/dolzel_rel.pch"

src/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/math.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,24 @@ inline float sqrtf(float mag) {
7474
return sqrt(mag);
7575
}
7676
#else
77+
#ifdef DECOMPCTX
78+
// Hack to mitigate fake mismatches when building from decompctx output
79+
// (which doesn't support precompiled headers).
80+
//
81+
// When built without a PCH, these constants would end up .rodata instead of .data
82+
// which causes a variety of knock-on effects in individual functions' assembly.
83+
//
84+
// Making them into globals is a bit of a hack, but it generally fixes later
85+
// .data and .rodata offsets and allows individual functions to match.
86+
static double _half = 0.5;
87+
static double _three = 3.0;
88+
#endif
7789
inline float sqrtf(float mag) {
90+
#ifndef DECOMPCTX
91+
// part of the same hack, these are defined outside of the function when using decompctx
7892
static const double _half = 0.5;
7993
static const double _three = 3.0;
94+
#endif
8095
if (mag > 0.0f) {
8196
double tmpd = __frsqrte(mag);
8297
tmpd = tmpd * _half * (_three - mag * (tmpd * tmpd));

tools/decompctx.py

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
###
1212

1313
import argparse
14+
import fnmatch
1415
import os
1516
import re
1617
from typing import List
@@ -19,6 +20,7 @@
1920
root_dir = os.path.abspath(os.path.join(script_dir, ".."))
2021
src_dir = os.path.join(root_dir, "src")
2122
include_dirs: List[str] = [] # Set with -I flag
23+
exclude_globs: List[str] = [] # Set with -x flag
2224

2325
include_pattern = re.compile(r'^#\s*include\s*[<"](.+?)[>"]')
2426
guard_pattern = re.compile(r"^#\s*ifndef\s+(.*)$")
@@ -28,6 +30,23 @@
2830
deps = []
2931

3032

33+
def generate_prelude(defines) -> str:
34+
if len(defines) == 0:
35+
return ""
36+
37+
out_text = "/* decompctx prelude */\n"
38+
for define in defines:
39+
parts = define.split("=", 1)
40+
if len(parts) == 2:
41+
macro_name, macro_val = parts
42+
out_text += f"#define {macro_name} {macro_val}\n"
43+
else:
44+
out_text += f"#define {parts[0]}\n"
45+
out_text += "/* end decompctx prelude */\n\n"
46+
47+
return out_text
48+
49+
3150
def import_h_file(in_file: str, r_path: str) -> str:
3251
rel_path = os.path.join(root_dir, r_path, in_file)
3352
if os.path.exists(rel_path):
@@ -73,8 +92,17 @@ def process_file(in_file: str, lines: List[str]) -> str:
7392
print("Processing file", in_file)
7493
include_match = include_pattern.match(line.strip())
7594
if include_match and not include_match[1].endswith(".s"):
95+
excluded = False
96+
for glob in exclude_globs:
97+
if fnmatch.fnmatch(include_match[1], glob):
98+
excluded = True
99+
break
100+
76101
out_text += f'/* "{in_file}" line {idx} "{include_match[1]}" */\n'
77-
out_text += import_h_file(include_match[1], os.path.dirname(in_file))
102+
if excluded:
103+
out_text += "/* Skipped excluded file */\n"
104+
else:
105+
out_text += import_h_file(include_match[1], os.path.dirname(in_file))
78106
out_text += f'/* end "{include_match[1]}" */\n'
79107
else:
80108
out_text += line
@@ -111,13 +139,29 @@ def main():
111139
help="""Include directory""",
112140
action="append",
113141
)
142+
parser.add_argument(
143+
"-x",
144+
"--exclude",
145+
help="""Excluded file name glob""",
146+
action="append",
147+
)
148+
parser.add_argument(
149+
"-D",
150+
"--define",
151+
help="""Macro definition""",
152+
action="append",
153+
)
114154
args = parser.parse_args()
115155

116156
if args.include is None:
117157
exit("No include directories specified")
118158
global include_dirs
119159
include_dirs = args.include
120-
output = import_c_file(args.c_file)
160+
global exclude_globs
161+
exclude_globs = args.exclude or []
162+
prelude_defines = args.define or []
163+
output = generate_prelude(prelude_defines)
164+
output += import_c_file(args.c_file)
121165

122166
with open(os.path.join(root_dir, args.output), "w", encoding="utf-8") as f:
123167
f.write(output)

tools/project.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,12 @@ def __init__(self) -> None:
198198
self.link_order_callback: Optional[Callable[[int, List[str]], List[str]]] = (
199199
None # Callback to add/remove/reorder units within a module
200200
)
201+
self.context_exclude_globs: List[str] = (
202+
[] # Globs to exclude from context files
203+
)
204+
self.context_defines: List[str] = (
205+
[] # Macros to define at the top of context files
206+
)
201207

202208
# Progress output and report.json config
203209
self.progress = True # Enable report.json generation and CLI progress output
@@ -492,7 +498,7 @@ def generate_build_ninja(
492498
decompctx = config.tools_dir / "decompctx.py"
493499
n.rule(
494500
name="decompctx",
495-
command=f"$python {decompctx} $in -o $out -d $out.d $includes",
501+
command=f"$python {decompctx} $in -o $out -d $out.d $includes $excludes $defines",
496502
description="CTX $in",
497503
depfile="$out.d",
498504
deps="gcc",
@@ -1048,12 +1054,19 @@ def c_build(obj: Object, src_path: Path) -> Optional[Path]:
10481054
):
10491055
include_dirs.append(flag[3:])
10501056
includes = " ".join([f"-I {d}" for d in include_dirs])
1057+
excludes = " ".join([f"-x {d}" for d in config.context_exclude_globs])
1058+
defines = " ".join([f"-D {d}" for d in config.context_defines])
1059+
10511060
n.build(
10521061
outputs=obj.ctx_path,
10531062
rule="decompctx",
10541063
inputs=src_path,
10551064
implicit=decompctx,
1056-
variables={"includes": includes},
1065+
variables={
1066+
"includes": includes,
1067+
"excludes": excludes,
1068+
"defines": defines,
1069+
},
10571070
)
10581071
n.newline()
10591072

0 commit comments

Comments
 (0)