diff options
| author | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-27 17:04:06 -0400 |
|---|---|---|
| committer | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-27 17:04:06 -0400 |
| commit | dce3adbc4cae486e2f3c080b995669d6db5ef58f (patch) | |
| tree | 638ec3ffef50441c7229160ee20b0fd9423ee271 /tools | |
| parent | 2835fec7fc66e1a1659710de8eddf2dfe67e20f9 (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.py | 83 |
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() |
