aboutsummaryrefslogtreecommitdiffstats
path: root/tools/warp.py
diff options
context:
space:
mode:
authorgbc dev <gbc@localhost>2026-07-15 00:37:04 +0200
committergbc dev <gbc@localhost>2026-07-15 00:37:04 +0200
commit12e67588053160d2f9599a09ef932f9b37b1b873 (patch)
treef1db2e3e8fb585bc76610995d2437aeb6ee9e51a /tools/warp.py
parentcontrol: socket-based debug channel + gbctl CLI driver (diff)
downloadsl0pboy-12e67588053160d2f9599a09ef932f9b37b1b873.tar.gz
sl0pboy-12e67588053160d2f9599a09ef932f9b37b1b873.tar.xz
sl0pboy-12e67588053160d2f9599a09ef932f9b37b1b873.zip
apu: register-level emulation of 0xFF10-0xFF3F (fixes music fades)
The APU was a black hole: reads returned 0xFF, writes were dropped. That hangs any game that fades music out by decrementing the NR50/rAUDVOL volume register until it reads 0 (Pokemon's StopMusic spin-wait) - the write never stuck, the read never hit 0, infinite loop. Store the 48 sound registers and return them with the standard hardware read-back OR-masks (NR50 mask 0x00 = exact readback). No synthesis, just correct register behavior.
Diffstat (limited to 'tools/warp.py')
-rw-r--r--tools/warp.py29
1 files changed, 29 insertions, 0 deletions
diff --git a/tools/warp.py b/tools/warp.py
new file mode 100644
index 0000000..71e4a1c
--- /dev/null
+++ b/tools/warp.py
@@ -0,0 +1,29 @@
+#!/usr/bin/env python3
+"""warp.py <sock> <mapid_hex> — Phase-A RAM-poke fly-warp to any map id.
+Sets wDestinationMap + BIT_FLY_WARP, then releases the music-fade spin-wait by
+zeroing wAudioFadeOutControl until the map actually changes."""
+import socket, sys, time
+
+WDEST=0xD719; WFLAGS=0xD731; WAUDIO=0xCFC6; WCURMAP=0xD35D
+
+def main():
+ sock=sys.argv[1]; dest=int(sys.argv[2],16)
+ c=socket.socket(socket.AF_UNIX,socket.SOCK_STREAM);c.settimeout(4);c.connect(sock);c.recv(200)
+ def cmd(l):
+ c.sendall((l+"\n").encode()); b=b""
+ while b"\n" not in b: b+=c.recv(65536)
+ return b.split(b"\n",1)[0].decode()
+ rd=lambda a:int(cmd(f"read 0x{a:04X} 1").split()[-1],16)
+ before=rd(WCURMAP)
+ cmd(f"write 0x{WDEST:04X} {dest:02X}")
+ cmd(f"write 0x{WFLAGS:04X} {rd(WFLAGS)|0x08:02X}")
+ ok=False
+ for _ in range(25):
+ cmd(f"write 0x{WAUDIO:04X} 00") # release spin-wait if the game entered it
+ time.sleep(0.25)
+ if rd(WCURMAP)!=before: ok=True; break
+ time.sleep(1.2)
+ m=rd(WCURMAP); y=rd(0xD360); x=rd(0xD361)
+ print(f"warp -> map 0x{m:02X} pos ({y},{x}) {'OK' if ok and m==dest else 'CHECK'}")
+
+if __name__=="__main__": main()