- Log messages, script output, test labels, Makefile errors and comments are English. Red log lines start with "[RED] " (was 【红】). - Shader map stage column: vertex / pixel / compute / geometry / hull / domain (generators, dmsh_build / dmsh_facts and nvn_mtl.m stage_of follow). - The NSP script's regexes match the new shader_split.py / dmsh_build.py summary lines; patch_nso cut scopes are all / host-only. - Host UI text table (dm_i18n_tab.h) is English only; dm_lang_zh() removed. - Text that matches game data (t_swkbd.c, t_textbox.c) is written as \x escapes. - Shader chain: the chain files lose their bilingual comments, so every profile has a new chain version. dmsh_xlate.dll rebuilt from the translated Program.cs (SPIR-V byte-identical on 4,500 shaders of Wonder, TOTK and Age of Calamity), lock and dmsh_chain.h headers regenerated. c1_full.tsv restamped for Dread, 13 Sentinels and Wonder; the other profiles follow when their rebuild finishes. - AGENTS.md and docs/agents: the language rule now covers logs; quoted log lines updated.
52 lines
3.3 KiB
Python
52 lines
3.3 KiB
Python
# Independent registration check of the new rule's build output; does not execute the game and does not trust the rewriter's own digest.
|
|
import sys,struct,hashlib
|
|
from pathlib import Path
|
|
D=Path(sys.argv[1]); b=(D/'main.patched.bin').read_bytes(); orig=Path(sys.argv[2]).read_bytes()
|
|
headers={};blocks=[]
|
|
try:
|
|
for line in (D/'main.rules.tsv').read_text().splitlines():
|
|
if line.startswith('# '):k,v=line[2:].split('\t',1);headers[k]=v
|
|
else:blocks.append(line.split('\t'))
|
|
assert headers['RULESET']=='touch-run-v4'
|
|
assert headers['BUILD_ID']=='db0507f36b84200ac05f75d76ed5026f'
|
|
assert headers['ORIGINAL_SHA256']==hashlib.sha256(orig).hexdigest()=='6843ab6909f96e1558b4b73b0fa807f3873409120cf3e1ef8a86dbebb275ee27'
|
|
assert headers['IMAGE_SHA256']==hashlib.sha256(b).hexdigest()
|
|
expected={0x2c620c:0x52800029,0x2c6210:0xb90e5109,0x369a90:None,0x369980:0xd503201f,0x2b2c74:0xd503201f,0x2b2dc0:0xd503201f,0x2b30fc:0x52800021,0x2b3104:0x52800021,0x6dc2c4:0x52800062,0x6dce90:0xd503201f,0x6dcec0:None,0x6c6648:None,0x6c6290:None,0x4ac368:None,0x6c6580:None}
|
|
cuts={}
|
|
for line in (D/'main.cuts.tsv').read_text().splitlines():
|
|
if line.startswith('#'):continue
|
|
off,old,new,scope,why=line.split('\t',4)
|
|
if why.startswith('touch-run-v4: '):cuts[int(off,16)]=(old,new,scope)
|
|
assert set(cuts)==set(expected),('cut set',set(cuts)^set(expected))
|
|
def w(at):return struct.unpack_from('<I',b,at)[0]
|
|
def branch(at):
|
|
v=w(at);assert v&0xfc000000==0x14000000;imm=v&0x3ffffff
|
|
return at+4*((imm^0x2000000)-0x2000000)
|
|
for off,newword in expected.items():
|
|
old,new,scope=cuts[off];assert scope=='all';assert orig[off:off+4]==bytes.fromhex(old);assert b[off:off+4]==bytes.fromhex(new)
|
|
if newword is not None:assert w(off)==newword
|
|
assert branch(0x369a90)==0x369900 and branch(0x6dcec0)==0x6dce50
|
|
assert len(blocks)==4
|
|
fixheaders={}
|
|
for line in (D/'main.fixups.tsv').read_text().splitlines():
|
|
if line.startswith('# '):k,v=line[2:].split('\t');fixheaders[k]=int(v,0)
|
|
po=fixheaders['PATCH_OFF'];seen=set()
|
|
for off,raw,sha,why in blocks:
|
|
off=int(off,16);body=bytes.fromhex(raw);assert po<=off<len(b) and off+len(body)<=len(b);assert b[off:off+len(body)]==body;assert hashlib.sha256(body).hexdigest()==sha
|
|
src=next(s for s in [0x6c6648,0x6c6290,0x4ac368,0x6c6580] if branch(s)==off);assert src not in seen;seen.add(src)
|
|
if src==0x6c6580:
|
|
assert len(body)==24 and w(off)==0x35000088 and w(off+4)==0x51000849 and w(off+8)==0x35000049 and w(off+12)==0x52800062 and w(off+16)==0x51000849 and branch(off+20)==0x6c6584
|
|
continue
|
|
assert w(off)==0xb9400268
|
|
assert w(off+4)==(0x34000048 if src==0x4ac368 else 0x35000048)
|
|
if src==0x6c6648:
|
|
assert len(body)==24 and branch(off+8)==0x6c664c and w(off+12)==0x34000040 and branch(off+16)==0x6c664c and branch(off+20)==0x6c6654
|
|
elif src==0x6c6290:
|
|
assert len(body)==20 and branch(off+8)==0x6c62ec and w(off+12)==0x710006df and branch(off+16)==0x6c6294
|
|
else:
|
|
assert len(body)==28 and branch(off+8)==off+16 and branch(off+12)==0x4ac3f4 and w(off+16)==0x34000040 and branch(off+20)==0x4ac3f4 and branch(off+24)==0x4ac36c
|
|
assert seen=={0x6c6648,0x6c6290,0x4ac368,0x6c6580}
|
|
print('RUN_MANIFEST OK original/image hash, buildid, 15-cut whitelist, 4 trampolines hash/range/structure/entry B')
|
|
except (AssertionError,KeyError,OSError,ValueError,StopIteration) as e:
|
|
print('RUN_MANIFEST FAIL',type(e).__name__,str(e));sys.exit(1)
|