aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-27 17:04:06 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-27 17:04:06 -0400
commitdce3adbc4cae486e2f3c080b995669d6db5ef58f (patch)
tree638ec3ffef50441c7229160ee20b0fd9423ee271 /tools
parent2835fec7fc66e1a1659710de8eddf2dfe67e20f9 (diff)
Switch 2: window image sizes, queue semaphores, built-in fonts, memory budget
- gsv 1510 CalculateRequirements: block-linear size/alignment for window images. - nvhost-gpu: Switch 2 channel event 7 is a real (unsignalled) event. - Puller mirrors NVN2 queue semaphore releases into the page the CPU and GPU wait on (the first two-page nx2:gpu region); EDEN_NX2_METHOD_TRACE logs methods. - pl:u 2000/2010 GetBuiltInFontSharedMemory/GetBuiltInFontData serve plain TTF copies of the shared fonts. - Switch 2 processes count the alias region in their max memory, so the game's nninitStartup heap (total - 6.3 GiB) has room for its sound heap. - gdbrsp.py: interrupt, threads, selthread, hits, continue_async, sleep.
Diffstat (limited to 'tools')
-rw-r--r--tools/nx2/gdbrsp.py83
1 files changed, 83 insertions, 0 deletions
diff --git a/tools/nx2/gdbrsp.py b/tools/nx2/gdbrsp.py
index 9b3b2d8b37..f0acd2aebd 100644
--- a/tools/nx2/gdbrsp.py
+++ b/tools/nx2/gdbrsp.py
@@ -131,6 +131,10 @@ def main():
break
elif op == "continue":
print("stop:", rsp.cmd("c"))
+ elif op == "continue_async":
+ # Resume without waiting for a stop reply (pair with interrupt).
+ pkt = b"c"
+ rsp.s.sendall(b"$" + pkt + b"#" + f"{sum(pkt) & 0xff:02x}".encode())
elif op == "x0":
r = rsp.regs()
regs = r
@@ -156,6 +160,85 @@ def main():
if nfp <= fp:
break
fp = nfp
+ elif op == "interrupt":
+ # Stop a running target (Ctrl-C) and print the stop reply.
+ rsp.s.sendall(b"")
+ print("interrupt:", rsp._read_packet())
+ elif op == "threads":
+ # threads [frames]: every thread's pc, lr and frame-pointer chain.
+ ids = []
+ r = rsp.cmd("qfThreadInfo")
+ while r.startswith("m"):
+ ids += [t for t in r[1:].split(",") if t]
+ r = rsp.cmd("qsThreadInfo")
+ depth = int(parts[1]) if len(parts) > 1 else 16
+ for t in ids:
+ rsp.cmd(f"Hg{t}")
+ r = rsp.regs()
+ chain = []
+ fp = r.get("x29", 0)
+ for _ in range(depth):
+ d = rsp.mem(fp, 16)
+ if len(d) < 16:
+ break
+ nfp, ret = struct.unpack("<QQ", d)
+ chain.append(ret & 0xFFFFFFFFFFFF)
+ if nfp <= fp:
+ break
+ fp = nfp
+ print(f"thread {t} pc={r.get('pc', 0):#x} lr={r.get('x30', 0) & 0xFFFFFFFFFFFF:#x} "
+ f"x0={r.get('x0', 0):#x} x1={r.get('x1', 0):#x} chain=" + ",".join(f"{c:#x}" for c in chain))
+ elif op == "selthread":
+ # selthread <lo> <hi>: select the first thread whose pc, lr or frame chain falls in
+ # [lo, hi); later regs/mem ops then read that thread.
+ lo, hi = int(parts[1], 16), int(parts[2], 16)
+ ids = []
+ r = rsp.cmd("qfThreadInfo")
+ while r.startswith("m"):
+ ids += [t for t in r[1:].split(",") if t]
+ r = rsp.cmd("qsThreadInfo")
+ for t in ids:
+ rsp.cmd(f"Hg{t}")
+ r = rsp.regs()
+ cands = [r.get("pc", 0), r.get("x30", 0) & 0xFFFFFFFFFFFF]
+ fp = r.get("x29", 0)
+ for _ in range(8):
+ d = rsp.mem(fp, 16)
+ if len(d) < 16:
+ break
+ nfp, ret = struct.unpack("<QQ", d)
+ cands.append(ret & 0xFFFFFFFFFFFF)
+ if nfp <= fp:
+ break
+ fp = nfp
+ if any(lo <= c < hi for c in cands):
+ regs = r
+ print("selthread", t)
+ break
+ else:
+ print("selthread: none")
+ elif op == "hits":
+ # hits <addr> <n> [memreg]: stop at addr n times, printing x0/x1/lr (and 16 bytes at
+ # memreg) each time; steps off the breakpoint before resuming.
+ addr, n = int(parts[1], 16), int(parts[2])
+ memreg = parts[3] if len(parts) > 3 else None
+ for i in range(n):
+ rsp.cmd(f"Z0,{addr:x},4")
+ rsp.cmd("c")
+ r = rsp.regs()
+ regs = r
+ extra = ""
+ if memreg and memreg in r:
+ extra = " mem=" + rsp.mem(r[memreg], 16).hex()
+ print(f" hit {i} pc={r.get('pc', 0):#x} x0={r.get('x0', 0):#x} x1={r.get('x1', 0):#x} "
+ f"x19={r.get('x19', 0):#x} x20={r.get('x20', 0):#x}" + extra)
+ if r.get("pc") != addr:
+ break
+ rsp.cmd(f"z0,{addr:x},4")
+ rsp.cmd("s")
+ elif op == "sleep":
+ import time
+ time.sleep(float(parts[1]))
elif op == "quit":
break
rsp.s.close()