dwt: visual injection experiments via the returning rdebug jump

This commit is contained in:
SDD committed 2026-10-18 03:22:59 +03:00
1 parent 1e5c095b72
commit 05f1895bf5
80 files changed
+3252

No files matched your search

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

+48
View File
@@ -0,0 +1,48 @@
vt1200: screen_update#1 frame=0 clip_y=0..0 screen=1280x901
vt1200: screen_update#2 frame=0 clip_y=1..900 screen=1280x901
vt1200: guard#1 frame=0 dump_frame=-1 dump_ram=-1
vt1200: screen_update#3 frame=0 clip_y=0..900 screen=1280x901
vt1200: scanline#1 line=0 enabled=1
vt1200: guard#2 frame=0 dump_frame=-1 dump_ram=-1
vt1200: screen_update#4 frame=1 clip_y=0..0 screen=1280x901
vt1200: scanline#2 line=0 enabled=1
vt1200: scanline#3 line=1 enabled=1
vt1200: scanline#4 line=2 enabled=1
vt1200: dumped frame 3400 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3400.ppm (1280x901, 458414 lit = 39.7487%)
vt1200: dumped frame 3410 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3410.ppm (1280x901, 458611 lit = 39.7658%)
vt1200: dumped frame 3420 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3420.ppm (1280x901, 459086 lit = 39.8070%)
vt1200: dumped frame 3430 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3430.ppm (1280x901, 459086 lit = 39.8070%)
vt1200: dumped frame 3440 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3440.ppm (1280x901, 459086 lit = 39.8070%)
vt1200: dumped frame 3450 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3450.ppm (1280x901, 459086 lit = 39.8070%)
vt1200: dumped frame 3460 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3460.ppm (1280x901, 459086 lit = 39.8070%)
vt1200: dumped frame 3470 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3470.ppm (1280x901, 459086 lit = 39.8070%)
vt1200: dumped frame 3480 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3480.ppm (1280x901, 459086 lit = 39.8070%)
vt1200: dumped frame 3490 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3490.ppm (1280x901, 459086 lit = 39.8070%)
vt1200: dumped frame 3500 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3500.ppm (1280x901, 459086 lit = 39.8070%)
vt1200: dumped frame 3510 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3510.ppm (1280x901, 458079 lit = 39.7197%)
vt1200: dumped frame 3520 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3520.ppm (1280x901, 458516 lit = 39.7576%)
vt1200: dumped frame 3530 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3530.ppm (1280x901, 458516 lit = 39.7576%)
vt1200: dumped frame 3540 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3540.ppm (1280x901, 458516 lit = 39.7576%)
vt1200: dumped frame 3550 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3550.ppm (1280x901, 458516 lit = 39.7576%)
vt1200: dumped frame 3560 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3560.ppm (1280x901, 458516 lit = 39.7576%)
vt1200: dumped frame 3570 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3570.ppm (1280x901, 458516 lit = 39.7576%)
vt1200: dumped frame 3580 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3580.ppm (1280x901, 458516 lit = 39.7576%)
vt1200: dumped frame 3590 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3590.ppm (1280x901, 458516 lit = 39.7576%)
vt1200: dumped frame 3600 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3600.ppm (1280x901, 458516 lit = 39.7576%)
vt1200: dumped frame 3610 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3610.ppm (1280x901, 458746 lit = 39.7775%)
vt1200: dumped frame 3620 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3620.ppm (1280x901, 458118 lit = 39.7231%)
vt1200: dumped frame 3630 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3630.ppm (1280x901, 458118 lit = 39.7231%)
vt1200: dumped frame 3640 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3640.ppm (1280x901, 458118 lit = 39.7231%)
vt1200: dumped frame 3650 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3650.ppm (1280x901, 458118 lit = 39.7231%)
vt1200: dumped frame 3660 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3660.ppm (1280x901, 458118 lit = 39.7231%)
vt1200: dumped frame 3670 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3670.ppm (1280x901, 458118 lit = 39.7231%)
vt1200: dumped frame 3680 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3680.ppm (1280x901, 458118 lit = 39.7231%)
vt1200: dumped frame 3690 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3690.ppm (1280x901, 458118 lit = 39.7231%)
vt1200: dumped frame 3700 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3700.ppm (1280x901, 458118 lit = 39.7231%)
vt1200: dumped frame 3750 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3750.ppm (1280x901, 458565 lit = 39.7618%)
vt1200: dumped frame 3800 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3800.ppm (1280x901, 458565 lit = 39.7618%)
vt1200: dumped frame 3900 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-3900.ppm (1280x901, 458565 lit = 39.7618%)
vt1200: dumped frame 4000 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-4000.ppm (1280x901, 457962 lit = 39.7095%)
vt1200: dumped frame 4200 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames9/vt1200-frame-4200.ppm (1280x901, 457962 lit = 39.7095%)
frame_clock: stopping at frame 4300
Average speed: 325.30% (59 seconds)
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

@@ -0,0 +1,21 @@
install blinkev at frame 3396
[+] challenge ee bc de 08 00 00 db bd 02 63 a8 c0 ee b4 de 09
[+] reply a4 05 87 aa bd 84 96 24 5c b3 bf b0 6d 7a 1c 04
opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00')
poke-file dwt/visual/build/blinkev.bin: 252 bytes at 0x01840000: ok
[.] jump returned 0x00000000 (0)
jump 0x01840000: returned 0x00000000 (0) payload=00 00 00 00
post-jump opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00')
after-peek 0x01840800 (32) -> 0b 00 00 00 80 13 70 3f 21 00 20 00 00 00 00 00 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55
install done at frame 3437
--- query at 3450 ---
[+] challenge ff fc df 0f 00 00 de fe 02 63 a8 c0 ff fc df 10
[+] reply 51 20 c7 45 f0 45 2d 0f 3b d6 a6 3f 19 83 25 da
error: timed out
now 3560
--- query at 3470 ---
error: [Errno 113] No route to host
now 3560
--- query at 3500 ---
error: [Errno 113] No route to host
now 3560
+29
View File
@@ -0,0 +1,29 @@
vt1200: screen_update#1 frame=0 clip_y=0..0 screen=1280x901
vt1200: screen_update#2 frame=0 clip_y=1..900 screen=1280x901
vt1200: guard#1 frame=0 dump_frame=-1 dump_ram=-1
vt1200: screen_update#3 frame=0 clip_y=0..900 screen=1280x901
vt1200: scanline#1 line=0 enabled=1
vt1200: guard#2 frame=0 dump_frame=-1 dump_ram=-1
vt1200: screen_update#4 frame=1 clip_y=0..0 screen=1280x901
vt1200: scanline#2 line=0 enabled=1
vt1200: scanline#3 line=1 enabled=1
vt1200: scanline#4 line=2 enabled=1
vt1200: dumped frame 3440 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live3/frames/vt1200-frame-3440.ppm (1280x901, 459086 lit = 39.8070%)
vt1200: dumped frame 3445 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live3/frames/vt1200-frame-3445.ppm (1280x901, 468046 lit = 40.5839%)
vt1200: dumped frame 3450 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live3/frames/vt1200-frame-3450.ppm (1280x901, 459086 lit = 39.8070%)
vt1200: dumped frame 3455 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live3/frames/vt1200-frame-3455.ppm (1280x901, 463950 lit = 40.2287%)
vt1200: dumped frame 3460 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live3/frames/vt1200-frame-3460.ppm (1280x901, 454990 lit = 39.4518%)
vt1200: dumped frame 3465 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live3/frames/vt1200-frame-3465.ppm (1280x901, 463950 lit = 40.2287%)
vt1200: dumped frame 3470 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live3/frames/vt1200-frame-3470.ppm (1280x901, 454990 lit = 39.4518%)
vt1200: dumped frame 3475 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live3/frames/vt1200-frame-3475.ppm (1280x901, 463950 lit = 40.2287%)
vt1200: dumped frame 3480 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live3/frames/vt1200-frame-3480.ppm (1280x901, 454990 lit = 39.4518%)
vt1200: dumped frame 3485 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live3/frames/vt1200-frame-3485.ppm (1280x901, 463950 lit = 40.2287%)
vt1200: dumped frame 3490 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live3/frames/vt1200-frame-3490.ppm (1280x901, 454990 lit = 39.4518%)
vt1200: dumped frame 3495 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live3/frames/vt1200-frame-3495.ppm (1280x901, 463950 lit = 40.2287%)
vt1200: dumped frame 3500 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live3/frames/vt1200-frame-3500.ppm (1280x901, 454990 lit = 39.4518%)
vt1200: dumped frame 3505 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live3/frames/vt1200-frame-3505.ppm (1280x901, 463950 lit = 40.2287%)
vt1200: dumped frame 3510 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live3/frames/vt1200-frame-3510.ppm (1280x901, 454990 lit = 39.4518%)
vt1200: dumped frame 3515 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live3/frames/vt1200-frame-3515.ppm (1280x901, 463950 lit = 40.2287%)
vt1200: dumped frame 3520 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live3/frames/vt1200-frame-3520.ppm (1280x901, 454990 lit = 39.4518%)
frame_clock: stopping at frame 3560
Average speed: 322.76% (49 seconds)
@@ -0,0 +1,15 @@
install at frame 3398
[+] challenge f9 14 dc bd 00 00 db bd 02 63 a8 c0 f9 14 dc bd
[+] reply 50 5d c9 c1 fa e3 89 ad 63 a8 65 c9 1e 16 1b b9
opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00')
poke-file dwt/visual/build/blink.bin: 172 bytes at 0x01840000: ok
[.] jump returned 0x00000000 (0)
jump 0x01840000: returned 0x00000000 (0) payload=00 00 00 00
post-jump opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00')
after-peek 0x0186f000 (16) -> 0a 00 54 55 55 55 55 55 55 55 55 55 55 55 55 55
install done at frame 3433
frame~3500: post-jump opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00') | after-peek 0x0186f000 (8) -> 62 00 54 55 55 55 55 55 now 3524
frame~3600: post-jump opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00') | after-peek 0x0186f000 (8) -> c7 00 54 55 55 55 55 55 now 3623
frame~3700: post-jump opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00') | after-peek 0x0186f000 (8) -> 28 01 54 55 55 55 55 55 now 3727
frame~3900: post-jump opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00') | after-peek 0x0186f000 (8) -> ec 01 54 55 55 55 55 55 now 3925
frame~4200: post-jump opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00') | after-peek 0x0186f000 (8) -> 19 03 54 55 55 55 55 55 now 4227
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

@@ -0,0 +1,7 @@
inject at frame 3400
[+] challenge ef bc dd d7 00 00 db ac 02 63 a8 c0 ef b4 dd d8
[+] reply 2d ec e8 aa c8 72 a2 ac c0 66 b6 ef 05 b8 35 97
opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00')
poke-file dwt/visual/build/drawspin.bin: 118 bytes at 0x01840000: ok
jump 0x01840000: NO RETURN within 0.01s
client done at frame 3415
+29
View File
@@ -0,0 +1,29 @@
vt1200: screen_update#1 frame=0 clip_y=0..0 screen=1280x901
vt1200: screen_update#2 frame=0 clip_y=1..900 screen=1280x901
vt1200: guard#1 frame=0 dump_frame=-1 dump_ram=-1
vt1200: screen_update#3 frame=0 clip_y=0..900 screen=1280x901
vt1200: scanline#1 line=0 enabled=1
vt1200: guard#2 frame=0 dump_frame=-1 dump_ram=-1
vt1200: screen_update#4 frame=1 clip_y=0..0 screen=1280x901
vt1200: scanline#2 line=0 enabled=1
vt1200: scanline#3 line=1 enabled=1
vt1200: scanline#4 line=2 enabled=1
END f=3480 PC=3F579870 SP=000053A0 ST=00200010 counter=0001 state=0000 orig=3F800250 box=00000000
END f=3490 PC=3F579870 SP=000053A0 ST=00200010 counter=0001 state=0000 orig=3F760250 box=00000000
END f=3500 PC=3F579870 SP=000053A0 ST=00200010 counter=0001 state=0000 orig=3F6C0250 box=00000000
END f=3510 PC=3F579870 SP=000053A0 ST=00200010 counter=0001 state=0000 orig=3F620250 box=00000000
END f=3520 PC=3F579870 SP=000053A0 ST=00200010 counter=0001 state=0000 orig=3F580250 box=00000000
END f=3530 PC=3F579870 SP=000053A0 ST=00200010 counter=0001 state=0000 orig=3F4E0250 box=00000000
END f=3540 PC=3F579870 SP=000053A0 ST=00200010 counter=0001 state=0000 orig=3F440250 box=00000000
END f=3550 PC=3F579870 SP=000053A0 ST=00200010 counter=0001 state=0000 orig=3F3A0250 box=00000000
END f=3560 PC=3F579870 SP=000053A0 ST=00200010 counter=0001 state=0000 orig=3F300250 box=00000000
END f=3570 PC=3F579870 SP=000053A0 ST=00200010 counter=0001 state=0000 orig=3F260250 box=00000000
END f=3580 PC=3F579870 SP=000053A0 ST=00200010 counter=0001 state=0000 orig=3F1C0250 box=00000000
END f=3590 PC=3F579870 SP=000053A0 ST=00200010 counter=0001 state=0000 orig=3F120250 box=00000000
END f=3600 PC=3F579870 SP=000053A0 ST=00200010 counter=0001 state=0000 orig=3F080250 box=00000000
END f=3610 PC=3F579870 SP=000053A0 ST=00200010 counter=0001 state=0000 orig=3EFE0250 box=00000000
END f=3620 PC=3F579870 SP=000053A0 ST=00200010 counter=0001 state=0000 orig=3EF40250 box=00000000
END f=3630 PC=3F579870 SP=000053A0 ST=00200010 counter=0001 state=0000 orig=3EEA0250 box=00000000
END f=3640 PC=3F579870 SP=000053A0 ST=00200010 counter=0001 state=0000 orig=3EE00250 box=00000000
END f=3650 PC=3F579870 SP=000053A0 ST=00200010 counter=0001 state=0000 orig=3ED60250 box=00000000
Average speed: 321.26% (50 seconds)
+73
View File
@@ -0,0 +1,73 @@
MAME debugger version 0.289 (mame0289-dirty)
Currently targeting vt1200 (VT1200 X terminal (v2.2 firmware))
Breakpoint 1 set
Breakpoint 2 set
Breakpoint 3 set
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=006C31F0 st=00000010 a0=007A6860
HOOK OSH pc=3F7146D0 sp=0049E5F0 st=00000010 a0=00000000
HOOK OSH pc=3F7146D0 sp=007C8630 st=00000010 a0=00000000
HOOK OSH pc=3F7146D0 sp=00476690 st=00000010 a0=00000046
HOOK OSH pc=3F7146D0 sp=004764B0 st=00000010 a0=0038AD90
HOOK OSH pc=3F7146D0 sp=007C8230 st=00000010 a0=00000FF5
HOOK ENTRY pc=01840190 sp=00005360 st=00000010 a0=00000606
HOOK OSH pc=3F7146D0 sp=00005360 st=00000010 a0=0003F579
HOOK RET pc=018402D0 sp=000053A0 st=00200010 a0=0003F579
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

@@ -0,0 +1,15 @@
install at frame 3399
[+] challenge e8 6c df 05 00 00 db f0 02 63 a8 c0 e8 64 df 06
[+] reply e5 72 87 43 9c 19 e7 32 be d8 22 91 8e c3 69 85
opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00')
poke-file dwt/visual/build/blinkpc.bin: 300 bytes at 0x01840000: ok
[.] jump returned 0x00000000 (0)
jump 0x01840000: returned 0x00000000 (0) payload=00 00 00 00
post-jump opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00')
after-peek 0x01841000 (32) -> 00 00 00 00 55 55 00 00 55 55 55 55 00 00 00 00 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55
install done at frame 3439
frame~3500: post-jump opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00') | after-peek 0x01841000 (32) -> 01 00 00 00 20 5f 19 3f 10 00 00 00 00 00 00 00 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 now 3524
frame~3600: post-jump opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00') | after-peek 0x01841000 (32) -> 01 00 00 00 20 5f b4 3e 10 00 00 00 00 00 00 00 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 now 3624
frame~3700: post-jump opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00') | after-peek 0x01841000 (32) -> 01 00 00 00 20 5f 56 3e 10 00 00 00 00 00 00 00 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 now 3724
frame~3800: post-jump opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00') | after-peek 0x01841000 (32) -> 01 00 00 00 20 5f ea 3d 10 00 00 00 10 b3 35 00 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 now 3834
frame~4000: post-jump opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00') | after-peek 0x01841000 (32) -> 01 00 00 00 20 5f 26 3d 10 00 00 00 00 00 00 00 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 now 4033
+45
View File
@@ -0,0 +1,45 @@
vt1200: screen_update#1 frame=0 clip_y=0..0 screen=1280x901
vt1200: screen_update#2 frame=0 clip_y=1..900 screen=1280x901
vt1200: guard#1 frame=0 dump_frame=-1 dump_ram=-1
vt1200: screen_update#3 frame=0 clip_y=0..900 screen=1280x901
vt1200: scanline#1 line=0 enabled=1
vt1200: guard#2 frame=0 dump_frame=-1 dump_ram=-1
vt1200: screen_update#4 frame=1 clip_y=0..0 screen=1280x901
vt1200: scanline#2 line=0 enabled=1
vt1200: scanline#3 line=1 enabled=1
vt1200: scanline#4 line=2 enabled=1
vt1200: dumped frame 3440 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3440.ppm (1280x901, 454990 lit = 39.4518%)
vt1200: dumped frame 3450 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3450.ppm (1280x901, 454990 lit = 39.4518%)
vt1200: dumped frame 3460 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3460.ppm (1280x901, 454990 lit = 39.4518%)
vt1200: dumped frame 3470 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3470.ppm (1280x901, 454990 lit = 39.4518%)
vt1200: dumped frame 3480 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3480.ppm (1280x901, 454990 lit = 39.4518%)
vt1200: dumped frame 3490 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3490.ppm (1280x901, 454990 lit = 39.4518%)
vt1200: dumped frame 3500 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3500.ppm (1280x901, 454990 lit = 39.4518%)
vt1200: dumped frame 3510 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3510.ppm (1280x901, 455181 lit = 39.4684%)
vt1200: dumped frame 3520 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3520.ppm (1280x901, 454420 lit = 39.4024%)
vt1200: dumped frame 3530 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3530.ppm (1280x901, 454420 lit = 39.4024%)
vt1200: dumped frame 3540 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3540.ppm (1280x901, 454420 lit = 39.4024%)
vt1200: dumped frame 3550 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3550.ppm (1280x901, 454420 lit = 39.4024%)
vt1200: dumped frame 3560 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3560.ppm (1280x901, 454420 lit = 39.4024%)
vt1200: dumped frame 3570 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3570.ppm (1280x901, 454420 lit = 39.4024%)
vt1200: dumped frame 3580 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3580.ppm (1280x901, 454420 lit = 39.4024%)
vt1200: dumped frame 3590 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3590.ppm (1280x901, 454420 lit = 39.4024%)
vt1200: dumped frame 3600 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3600.ppm (1280x901, 454420 lit = 39.4024%)
vt1200: dumped frame 3610 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3610.ppm (1280x901, 454361 lit = 39.3973%)
vt1200: dumped frame 3620 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3620.ppm (1280x901, 454022 lit = 39.3679%)
vt1200: dumped frame 3630 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3630.ppm (1280x901, 454022 lit = 39.3679%)
vt1200: dumped frame 3640 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3640.ppm (1280x901, 454022 lit = 39.3679%)
vt1200: dumped frame 3650 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3650.ppm (1280x901, 454022 lit = 39.3679%)
vt1200: dumped frame 3660 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3660.ppm (1280x901, 454022 lit = 39.3679%)
vt1200: dumped frame 3670 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3670.ppm (1280x901, 454022 lit = 39.3679%)
vt1200: dumped frame 3680 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3680.ppm (1280x901, 454022 lit = 39.3679%)
vt1200: dumped frame 3690 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3690.ppm (1280x901, 454022 lit = 39.3679%)
vt1200: dumped frame 3700 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3700.ppm (1280x901, 454022 lit = 39.3679%)
vt1200: dumped frame 3710 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3710.ppm (1280x901, 454664 lit = 39.4236%)
vt1200: dumped frame 3720 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3720.ppm (1280x901, 454469 lit = 39.4066%)
vt1200: dumped frame 3730 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3730.ppm (1280x901, 454469 lit = 39.4066%)
vt1200: dumped frame 3740 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3740.ppm (1280x901, 454469 lit = 39.4066%)
vt1200: dumped frame 3750 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3750.ppm (1280x901, 454469 lit = 39.4066%)
vt1200: dumped frame 3760 -> /home/arti/code/k-space/vt1200/dwt/evidence/visual/live/frames24/vt1200-frame-3760.ppm (1280x901, 454469 lit = 39.4066%)
frame_clock: stopping at frame 4200
Average speed: 325.09% (58 seconds)
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

@@ -0,0 +1,10 @@
inject at frame 3398
[+] challenge ff fc db b7 00 00 db 9b 02 63 a8 c0 ff fc db b8
[+] reply 47 21 6e f9 03 f9 82 cb b8 09 8f 65 eb 79 b5 ce
opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00')
poke-file dwt/visual/build/drawal.bin: 122 bytes at 0x01840000: ok
[.] jump returned 0x00000000 (0)
jump 0x01840000: returned 0x00000000 (0) payload=00 00 00 00
post-jump opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00')
after-peek 0x0400c030 (64) -> 00 00 00 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
client done at frame 3423
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

+16
View File
@@ -0,0 +1,16 @@
install ret_test at frame 3399
[+] challenge f6 a4 dd 1c 00 00 db ce 02 63 a8 c0 f6 9c dd 1d
[+] reply 64 cc 17 6d 41 c9 c8 07 65 36 c9 28 f2 e2 98 13
opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00')
poke-file dwt/visual/build/ret_test.bin: 30 bytes at 0x01840000: ok
[.] jump returned 0x00000000 (0)
jump 0x01840000: returned 0x00000000 (0) payload=00 00 00 00
post-jump opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00')
after-peek 0x01850000 (32) -> de c0 07 b0 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55
client done at frame 3438
[+] challenge f5 ec e3 b5 00 00 e2 50 02 63 a8 c0 f5 ec e3 b5
[+] reply b2 0c 80 4f 1b f7 ad 56 37 44 53 12 d4 70 72 d8
opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00')
post-jump opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00')
after-peek 0x01850000 (16) -> de c0 07 b0 55 55 55 55 55 55 55 55 55 55 55 55
second liveness at frame 3526
@@ -0,0 +1,21 @@
install blinkev at frame 3396
[+] challenge ee bc de 08 00 00 db bd 02 63 a8 c0 ee b4 de 09
[+] reply a4 05 87 aa bd 84 96 24 5c b3 bf b0 6d 7a 1c 04
opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00')
poke-file dwt/visual/build/blinkev.bin: 252 bytes at 0x01840000: ok
[.] jump returned 0x00000000 (0)
jump 0x01840000: returned 0x00000000 (0) payload=00 00 00 00
post-jump opcode 7 -> flag=0x00 payload=44 6f 6e 65 0a 00 (b'Done\n\x00')
after-peek 0x01840800 (32) -> 0b 00 00 00 80 13 70 3f 21 00 20 00 00 00 00 00 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55
install done at frame 3437
--- query at 3450 ---
[+] challenge ff fc df 0f 00 00 de fe 02 63 a8 c0 ff fc df 10
[+] reply 51 20 c7 45 f0 45 2d 0f 3b d6 a6 3f 19 83 25 da
error: timed out
now 3560
--- query at 3470 ---
error: [Errno 113] No route to host
now 3560
--- query at 3500 ---
error: [Errno 113] No route to host
now 3560
+95
View File
@@ -0,0 +1,95 @@
Visual injection on the running VT1200 OS -- key numbers
=========================================================
ROM md5 b46a3e442ccb86134d2356bd70d22fd2 (unchanged). No driver edits.
OS path: VT1200_SKIP_LEVEL1=1 (documented divergence), private -nvram_directory,
rdebug over TCP 771 with the computed challenge (dwt/solve.py chain).
1. `jump` is a call and returns; the OS stays alive
---------------------------------------------------
dwt/visual/build/ret_test.bin = 30 bytes, linked at bit 01840000h.
Step1 log: dwt/evidence/visual/step1_ret_test.log
jump 0x01840000: returned 0x00000000
after-peek 0x01850000 -> de c0 07 b0 (0xC0DE, 0xB007)
post-jump opcode 7 -> Done
second connection at frame 3526: opcode 7 -> Done; markers still de c0 07 b0
Frame at 3500 (step1_alive_3500.png) is the live Terminal Manager.
So the loader is a real call: stack/return are intact, and the TCP session is
usable before and after.
2. Static VRAM draw lands, but the OS repaints it
--------------------------------------------------
drawal.bin: three word-aligned black 32x32 boxes at (48,48), (256,400),
(928,752). Client log: dwt/evidence/visual/static_draw_client.log
after-peek 0x0400C030 (64) -> 00 00 00 00 ff ff ... (the writes are in VRAM)
jump returned; TCP Done; markers D2A0/B0C0.
Frames 3420 (before) and 3430 (after) are byte-identical
(static_before_3420.png / static_after_3430.png; md5 e98b9b4a38 both), and the
box regions do not change in any of 3420..3600. The OS repaints before the
next scanout.
Control (CPU frozen after the same draw): control_spin_box_3480.png shows the
black box, and the hello-world 256x64 block appears (control_hello_3480.png),
so the coordinates/renderer mapping are right.
3. Resident display-interrupt hook
----------------------------------
DI vector: RLONG(0xFFFFFEA0) = 00000DB0h. RAM stub there is 6 bytes:
80 c0 d0 46 71 3f = JA 3F7146D0h (stock OS display handler)
install rewrites the 32-bit target only:
80 c0 90 01 84 01 = JA 01840190h (our entry)
(both read from dwt/evidence/visual/live/runpc/vt1200-ram-3440.bin; the dump
itself is not committed -- see di_one_shot_state.log for the same stub read
through the running system.)
(a) draw before the stock handler: handler runs (counter 0x0A,0x62,...), but
no box ever appears -- the handler repaints after the draw.
(b) return-PC trampoline (draw after the handler's `reti`): visible blink.
Payload `dwt/visual/build/blinkev.bin` (252 bytes; the post-handler
trampoline with scratch at 01840800h). Two runs:
run A (blink_resident_client.log), frames 15:
frame 3450 box region 56.2% lit (black box ON)
frame 3480 box region 100.0% (box OFF, white body)
frame 3500 box region 56.2% (box ON again)
TCP answered at 3450 and at 3500 (post-jump opcode 7 -> Done).
run B (blink_repeat_client.log), frames live3, 5-frame dumps:
3440/3450 OFF, 3455..3520 ON (10-frame pairs):
blink2_off_3450.png, blink2_on_3460.png, blink2_on_3500.png.
The install returned and its post-jump opcode 7 -> Done, but a new
connection at 3450 got the challenge then timed out, and by 3470 the
terminal's IP stack was gone ("No route to host"). So the blink is
reproducible, TCP survival is flaky.
LIMIT: only the first trampoline entry draws. The stock handler's full
path (0x3F579880) stops returning through the patched saved PC; the
counter sticks at 1 (di_one_shot_state.log). So this is a real but
short-lived blink, not a durable one. Breakpoint log: hook_breakpoints.log
(ENTRY 1, RET 1, stock handler 34+).
(c) with the settle/IE work, the one-shot post-handler draw persists: frames
24/25 show the black box at (448..511, 400..463) for 600+ frames, and the
OS answers TCP at 3500/3600/3700/3800/4000
(settled_hook_client.log; settled_hook_mame.log). It does not toggle.
(d) INT2 hook (stub 0F30h, handler 3F714530h) was tried; at idle the handler
never takes the trampoline (counter 0), so it is not a blink source here.
4. Window
---------
Port 6000 is OPEN on 192.168.99.2 (xcheck.log); 6001 is closed. An ordinary
X client is rejected:
xdpyinfo -display 192.168.99.2:0 -> "Client is not authorized to access server"
So a normal X client cannot open a window without the server's auth cookie.
Injection of a window was NOT attempted: it needs the X server's window
structures, resource IDs and callbacks; that is a project, not an experiment.
Evidence files
--------------
step1_ret_test.log, step1_alive_3500.png
static_draw_client.log, static_before_3420.png, static_after_3430.png
control_spin_client.log, control_spin_box_3480.png, control_hello_3480.png
blink_resident_client.log, blink_on_3450(_crop).png, blink_off_3480(_crop).png,
blink_on_3500.png, blink_mame.log
blink_repeat_client.log, blink_repeat_mame.log, blink2_off_3450.png,
blink2_on_3460.png, blink2_on_3500.png, step3_blink_client.log
settled_hook_client.log, settled_hook_mame.log, posthandler_persist_3600.png
di_one_shot_state.log, hook_breakpoints.log
xcheck.log, xcheck_mame.log
+4
View File
@@ -0,0 +1,4 @@
771: OPEN (0.00s)
6000: OPEN (0.01s)
6001: closed/failed: [Errno 111] Connection refused
frame 1068
+12
View File
@@ -0,0 +1,12 @@
vt1200: screen_update#1 frame=0 clip_y=0..0 screen=1280x901
vt1200: screen_update#2 frame=0 clip_y=1..900 screen=1280x901
vt1200: guard#1 frame=0 dump_frame=-1 dump_ram=-1
vt1200: screen_update#3 frame=0 clip_y=0..900 screen=1280x901
vt1200: scanline#1 line=0 enabled=1
vt1200: guard#2 frame=0 dump_frame=-1 dump_ram=-1
vt1200: screen_update#4 frame=1 clip_y=0..0 screen=1280x901
vt1200: scanline#2 line=0 enabled=1
vt1200: scanline#3 line=1 enabled=1
vt1200: scanline#4 line=2 enabled=1
frame_clock: stopping at frame 3700
Average speed: 336.39% (51 seconds)
+25
View File
@@ -285,3 +285,28 @@ Files: `dwt/challenge.py`, `dwt/solve.py`, `dwt/notes/CHALLENGE_REVERSE.md`,
`dwt/evidence/oracle-*.log`, `dwt/evidence/VALIDATION.txt`,
`dwt/evidence/live-run{,2}/`, `dwt/evidence/scripts/{oracle_call,live_verify,live_check}.lua`.
`dwt/exploit.py` and `dwt/mop_console.py` were not modified.
## 2026-10-18 — visual injection via the returning rdebug `jump`
**`jump` is a real `call`.** A 30-byte `rets` payload writes markers, returns
`0`, and the same TCP session plus a later connection still answer opcode 7
(`dwt/evidence/visual/step1_ret_test.log`).
* **Static VRAM draw lands but is repainted.** A three-box payload's writes are
visible in an immediate `peek` but frames before/after are identical; a
spinning control shows the same boxes, so the coordinates are right.
* **Resident DI hook:** `RLONG(0xFFFFFEA0) = 00000DB0h`, stub `JA 3F7146D0h`.
Patching the stub works (pre-handler draw is repainted). A return-PC
trampoline (draw after the handler's `reti`) produced a visible blink:
frames 3450 (box on) / 3480 (off) / 3500 (on), TCP answered at 3450 and 3500.
It is **not durable** — only the first entry takes the `reti` path; later
entries take the `jauc 3F579880` full path and stop using the patched PC
(counter sticks at 1). A one-shot post-handler box persists for 600+ frames.
* **Window:** port 6000 is open, but `xdpyinfo` is rejected (“Client is not
authorized”). Opening a window by injection was not attempted; it is an
X-structure project.
Details, addresses, frames and limits: `dwt/notes/VISUAL_INJECTION.md`,
`dwt/evidence/visual/`. ROM md5 unchanged; no driver edits; only
`VT1200_SKIP_LEVEL1=1` (documented divergence) and a private nvram.
+164
View File
@@ -0,0 +1,164 @@
# Visual injection through the rdebug loader
Status: **the loader returns, a one-shot post-handler draw persists, and a
resident display-interrupt hook produced a visible blink** (black box on at
frames 3450/3500, off at 3480; a repeat run gives off at 3440/3450 and on from
3455). The blink is **not durable and TCP survival is flaky**: in the best run
the OS answered TCP at 3450 and 3500, in the repeat run it had lost TCP by
3450. The stock display handler's full path stops returning through the
patched saved PC, so the resident hook draws once and then only the box stays.
A durable blink needs the full display path (or an X-level callback).
ROM untouched (`md5 b46a3e442ccb86134d2356bd70d22fd2`). No driver edits.
Emulator only; private `-nvram_directory`; `VT1200_SKIP_LEVEL1=1` is the
documented harness divergence that makes the OS reach the GUI and TCP.
All payloads are GSPA/GSPLNK output, built by `dwt/visual/build.sh`
(the `harness/hello-world` flow). The host driver is `dwt/visual/inject.py`,
which imports `dwt/exploit.py` and patches `answer_challenge` with
`dwt/challenge.respond` exactly like `dwt/solve.py`; it adds `--jump-wait`,
post-jump liveness and peek, so a return can be observed.
## 1. `jump` is a call, and it returns
`ret_test.asm` (30 bytes) writes `0xC0DE`/`0xB007` at bit `01850000h` and `rets`.
```
jump 0x01840000: returned 0x00000000
after-peek 0x01850000 -> de c0 07 b0
post-jump opcode 7 -> Done
second connection at frame 3526 -> Done, markers still de c0 07 b0
```
So the stub table's `call *a13` has a real return address, our `rets` returns to
the dispatcher, and the same TCP connection (and a new one 88 frames later)
still works. Evidence: `dwt/evidence/visual/step1_ret_test.log`,
`step1_alive_3500.png`.
Two bit-address traps were found here and are worth remembering:
* A 32-bit cell is **+0x20 bits**, not +4. Early payloads put scratch cells at
+2/+4 bits and they overlapped, which looked like an OS crash.
* A 16-bit store to VRAM at x not a multiple of 16 does not produce the pixels
you expect. Word-aligned x (multiple of 16) works; the hello-world block and
`control_spin_box_3480.png` prove it.
## 2. Static VRAM draws are repainted
`drawal.asm` draws three black 32x32 boxes at frame-buffer (48,48), (256,400)
and (928,752), then returns. The writes land — an immediate `peek` of
`0400C030h` returns `00 00 00 00 ff ff ...` — but frames 3420 (before the draw)
and 3430 (after it) are byte-identical, and the three box regions never change
through 3600. The OS re-composites the screen before scanout.
Control: `boxalign.asm` draws the same kind of box and then spins. The next
frame shows the black box (`control_spin_box_3480.png`), and the stock
hello-world payload run at OS time shows its 256x64 block
(`control_hello_3480.png`). So the draw and the renderer mapping are correct;
persistence is what fails.
## 3. Resident display interrupt
### The vector and stub
The CPU vector table is in ROM, but the DI entry is a pointer to low RAM:
```
RLONG(0xFFFFFEA0) = 00000DB0h
00000DB0h: 80 c0 d0 46 71 3f = JA 3F7146D0h (stock OS DI handler)
```
`install` rewrites only the 32-bit target:
```
00000DB0h: 80 c0 90 01 84 01 = JA 01840190h (our entry)
```
The opcode word stays `C080h` (`jauc`); the target is written as one 32-bit
store under `dint`, so no interrupt can see a half-updated address.
### Why the draw has to be after the handler
* `blink.asm` (draw at handler entry, then `jauc 3F7146D0h`) ran: its counter
incremented, the TCP session stayed usable, but **no box ever appeared**.
* The stock handler tail-calls `3F579880` (the display work) and returns with
`reti`. A **return-PC trampoline** gets control after that:
`entry` reads the interrupt frame's saved PC at `SP+0x20`, stores it, replaces
it with `ret_hook`, and tail-jumps to `3F7146D0h`; `ret_hook` draws and returns
to the original PC with `rets 2` (the `2` skips the temporary a0 slot so the
interrupted stack is exactly balanced). `ret_hook` saves/restores a0-a5 and
ST, and `dint` is its first instruction.
This produced the blink. The payload kept for the evidence is
`dwt/visual/build/blinkev.bin` (252 bytes; same return-PC trampoline, scratch
at `01840800h`):
| frame | box region (fb 256..319 x 400..463) | state |
|---|---|---|
| 3450 | 56.2% lit | black box ON |
| 3480 | 100.0% lit | OFF (white body) |
| 3500 | 56.2% lit | black box ON |
TCP answered at 3450 and 3500 in that run (`post-jump opcode 7 -> Done`).
The region is 56.2% rather than 0% because the box overlaps the Memory bar; the
crops show the black square clearly (`blink_on_3450_crop.png`,
`blink_off_3480_crop.png`).
A repeat run with the same binary reproduces the visual blink (5-frame dumps:
3440/3450 OFF, 3455..3520 ON) but **loses TCP**: a new connection at 3450 got
the challenge and then timed out, and by 3470 the terminal's IP stack was gone.
So the blink is reproducible; keeping the OS fully alive with it is not yet.
**The limit:** only the first trampoline entry draws. A breakpoint log shows
`ENTRY 1`, `RET 1`, then the stock handler continues 34+ times
(`hook_breakpoints.log`), and the counter sticks at 1
(`di_one_shot_state.log`). The handler's depth counter at `0x1e9420` makes the
first entry take the `reti` path and later entries take the `jauc 0x3F579880`
full path, whose return does not use our patched saved PC. The one-shot draw
does persist (the OS does not repaint that box while idle):
`posthandler_persist_3600.png` and the settled run answer TCP through frame
4000 with the box still there (`settled_hook_client.log`).
What would close this: hook `0x3F579880` (or its return) instead of the vector,
or hook a RAM function pointer the X server calls each frame. Both need the
full display path's calling convention; that is the next experiment.
INT2 was tried as a faster periodic source (stub `0F30h`, handler `3F714530h`):
at idle the handler never takes the trampoline (counter 0), so it does not help.
## 4. Windows
* Port **6000 is open**; `6001` is closed (`dwt/evidence/visual/xcheck.log`).
* `xdpyinfo -display 192.168.99.2:0` is rejected: **“Client is not authorized
to access server.”** An ordinary X client cannot connect without the
server's auth cookie, so a legitimate window is not reachable in this setup
(this is a baseline, not injection).
* Creating a window by injection was **not attempted**: it needs the X
server's screen/window structures, resource IDs and callbacks. That is a
project, not an experiment.
## 5. Caveats
* The blink evidence is a **short-lived resident blink**, not a durable one.
The durable result is a persistent one-shot box.
* `VT1200_SKIP_LEVEL1=1` is required for the OS/TCP; the level-1 POST path is
not involved.
* The DI stub address (`00000DB0h`) and handler (`3F7146D0h`) are properties of
**this firmware image**. A different image must read `RLONG(0xFFFFFEA0)` and
the stub bytes first.
* The real unit would need the rdebug service reachable (the challenge is
solved offline by `dwt/challenge.py`) and the same RAM patch. On real
hardware the display interrupt timing and the RAM vector page should be
verified before writing; the patch itself is RAM-only and survives until
reset.
## 6. Files
| path | contents |
|---|---|
| `dwt/visual/*.asm` | `ret_test`, `drawal`, `draw_box`/`drawspin`, `boxalign`, `blink` (pre-handler), `blinkev` (return-PC trampoline, blink evidence), `blinkpc` (settled one-shot), `blink2` (INT2), `probe_*` |
| `dwt/visual/build.sh` | GSPA/GSPLNK build wrapper (same flow as hello-world) |
| `dwt/visual/build/` | linked `.bin` + maps/listings |
| `dwt/visual/inject.py` | challenge-solving client with `--jump-wait`, liveness, peek |
| `dwt/visual/*.lua` | frame clock / interrupt probe / PC and hook probes |
| `dwt/evidence/visual/` | frames, crops, client and MAME logs, `summary.txt` |
+73
View File
@@ -0,0 +1,73 @@
; blink.asm -- resident blink hooked on the display interrupt via the firmware's
; own RAM trampoline at bit 00000DB0h (RLONG(0xFFFFFEA0) = 00000DB0h).
;
; `install` (called by rdebug `jump`, returns) rewrites the 6-byte
; `JA 3F7146D0h` stub to `JA handler`. `handler` runs on every display
; interrupt, toggles a 64x64 box on the Terminal Manager's white body every
; 0600h invocations, then tail-jumps to the stock OS display handler.
;
; This is the "draw before the OS handler" variant. If the OS handler repaints
; afterwards, the box will not survive; that is what the frames decide.
;
; Linked at bit 01840000h by dwt/visual/build.sh.
.text
_start:
pushst
dint
setf 32, 0, 0
movi handler, a0, L
move a0, @00000DC0h, 0 ; stub target
setf 16, 0, 0
movi 0C080h, a0, L
move a0, @00000DB0h, 0 ; JA opcode
sub a0, a0
move a0, @0186F000h, 0 ; counter
move a0, @0186F002h, 0 ; state (0 = black)
popst
rets
handler:
mmtm sp, a0,a1,a2,a3,a4,a5
setf 16, 0, 0
setf 32, 0, 1
move @0186F000h, a0, 0
inc a0
move a0, @0186F000h, 0
cmpi 0600h, a0
jrne draw
sub a0, a0
move a0, @0186F000h, 0
move @0186F002h, a1, 0
cmpi 0, a1
jrne was_white
movk 1, a1
jruc set_state
was_white:
sub a1, a1
set_state:
move a1, @0186F002h, 0
draw:
move @0186F002h, a1, 0
cmpi 0, a1
jrne pat_white
sub a2, a2
jruc pat_ready
pat_white:
movi 0FFFFh, a2, L
pat_ready:
movi 04064100h, a3, L ; 04000000h + 400*1024 + 256
movi 64, a4, L
movi 4, a5, L
drow:
move a5, a1
dword:
move a2, *a3+, 0
dsjs a1, dword
addi 03C0h, a3
dsjs a4, drow
mmfm sp, a0,a1,a2,a3,a4,a5
jauc 3F7146D0h ; stock OS display handler
.end
+119
View File
@@ -0,0 +1,119 @@
; blinkpc.asm -- resident blink that draws AFTER the stock display handler.
;
; Hook: the firmware's DI RAM trampoline at bit 00000DB0h
; (RLONG(0xFFFFFEA0) = 00000DB0h, stub `JA 3F714530h`).
;
; entry saves the interrupt's saved PC, replaces it with ret_hook, then
; tail-jumps to the stock handler 3F714530h;
; ret_hook runs when the stock handler `reti`s, draws the box, and returns
; to the original PC with `rets 2` (the 2 skips the temporary a0
; slot and keeps the interrupted stack balanced).
;
; Drawing after the handler matters: a draw before it is wiped by the handler's
; own screen work (measured: blink.asm counter runs, no box in any frame).
;
; Box: framebuffer (256,400), 64x64, white Terminal Manager body.
; State toggles every 0014h invocations (~20 frames at ~1 DI/frame idle).
;
; Linked at bit 01840000h by dwt/visual/build.sh.
.text
_start: ; install, called by rdebug `jump`
pushst
dint
setf 32, 0, 0
movi entry, a0, L
move a0, @00000F40h, 0
setf 16, 0, 0
movi 0C080h, a0, L
move a0, @00000F30h, 0
sub a0, a0
move a0, @01840E00h, 0 ; counter
move a0, @01840E10h, 0 ; state (0 = black)
movi 0Ah, a0, L
move a0, @01840E30h, 0 ; skip the first 10 DI entries
popst
rets
; ---- entry: point the interrupt's return at ret_hook, run stock handler ---
entry:
move a0, @01840E60h, 1 ; save interrupted a0
setf 16, 0, 0
move @01840E30h, a0, 0 ; settle counter
cmpi 0, a0
jreq active
dec a0
move a0, @01840E30h, 0
setf 32, 0, 1
move @01840E60h, a0, 1
jauc 3F714530h ; still settling: stock handler only
active:
setf 32, 0, 1
move *sp(020h), a0, 1 ; saved PC (SP -> ST, +20h -> PC)
move a0, @01840E20h, 1 ; orig_pc
movi ret_hook, a0, L
move a0, *sp(020h), 1
move @01840E60h, a0, 1
jauc 3F714530h ; stock OS display handler
; ---- ret_hook: after the stock handler, draw, then resume -----------------
ret_hook:
dint ; first instruction: close the reti->hook race
mmtm sp, a0,a1,a2,a3,a4,a5 ; field-independent A-reg save
getst a0
setf 32, 0, 1
move a0, @01840E40h, 1 ; interrupted ST
setf 16, 0, 0
setf 32, 0, 1
move @01840E00h, a0, 0
inc a0
move a0, @01840E00h, 0
cmpi 0014h, a0
jrne draw
sub a0, a0
move a0, @01840E00h, 0
move @01840E10h, a1, 0
cmpi 0, a1
jrne was_white
movk 1, a1
jruc set_state
was_white:
sub a1, a1
set_state:
move a1, @01840E10h, 0
draw:
move @01840E10h, a1, 0
cmpi 0, a1
jrne pat_white
sub a2, a2
jruc pat_ready
pat_white:
movi 0FFFFh, a2, L
pat_ready:
movi 04064100h, a3, L
movi 64, a4, L
movi 4, a5, L
drow:
move a5, a1
dword:
move a2, *a3+, 0
dsjs a1, dword
addi 03C0h, a3
dsjs a4, drow
; restore the A registers (field 1 is still 32)
mmfm sp, a0,a1,a2,a3,a4,a5
; leave with [ST][orig_pc] and the temporary a0 slot skipped by rets 2
setf 32, 0, 1
mmtm sp, a0 ; a0 slot at S-20h
move @01840E20h, a0, 1 ; orig_pc
move a0, -*sp, 1 ; orig_pc at S-40h
move *sp(020h), a0, 1 ; restore a0 from S-20h
move @01840E40h, a0, 1 ; interrupted ST (temporarily in a0)
move a0, -*sp, 1 ; ST at S-60h
move *sp(040h), a0, 1 ; restore a0 from S-20h
popst ; restore interrupted ST/IE
rets 2 ; pop orig_pc, skip the a0 slot
.end
+117
View File
@@ -0,0 +1,117 @@
; blinkdi.asm -- resident blink hooked on the display interrupt, via the
; firmware's own RAM trampoline at bit 00000DB0h.
;
; HOW IT HOOKS
; The CPU vector table lives in ROM, but RLONG(0xFFFFFEA0) = 00000DB0h and
; that RAM word is a 6-byte `JA <handler>` stub. `install` rewrites the
; stub's 32-bit target to `entry` (the opcode C080h is unchanged). The
; original target 3F7146D0h is the OS display handler.
;
; WHY THE RETURN-PC TRAMPOLINE
; A one-shot VRAM draw is repainted before it reaches the screen. Drawing
; inside the handler *before* the OS handler runs is also wiped by the
; handler's own full-screen work. So:
; entry (runs first) saves the interrupt's return PC, replaces it with
; `ret_hook`, then tail-jumps to the stock OS handler;
; ret_hook (runs after the OS handler's `reti`) draws the box and jumps
; back to the saved PC. The draw is therefore after the repaint.
;
; The box is at framebuffer (256,400), 64x64, on the Terminal Manager's white
; body. State toggles every 0600h invocations (~48 frames at the measured
; ~32 display interrupts/frame): black <-> white.
;
; Linked at bit 01840000h by dwt/visual/build.sh.
.text
_start: ; install, called by rdebug `jump`
pushst
dint
setf 32, 0, 0
movi entry, a0, L
move a0, @00000DC0h, 0 ; stub target (32 bits, two words)
setf 16, 0, 0
movi 0C080h, a0, L ; JA opcode (unchanged value)
move a0, @00000DB0h, 0
sub a0, a0
move a0, @0186F000h, 0 ; invocation counter = 0
move a0, @0186F002h, 0 ; state = 0 (black)
popst
rets
; ---- entry hook: save return PC, install ret_hook, run stock handler ------
entry:
move a0, @0186F010h, 1 ; save interrupted a0
setf 32, 0, 1
move *sp(020h), a0, 1 ; saved PC (SP -> ST, +20h -> PC)
move a0, @0186F004h, 1 ; orig_pc
movi ret_hook, a0, L
move a0, *sp(020h), 1 ; return via ret_hook instead
move @0186F010h, a0, 1 ; restore a0
ja 3F7146D0h ; stock OS display handler
; ---- ret hook: after the OS handler, draw, then go back -----------------
ret_hook:
move a0, @0186F010h, 1
getst a0
move a0, @0186F014h, 1 ; save interrupted ST
dint
move a1, @0186F020h, 1
move a2, @0186F024h, 1
move a3, @0186F028h, 1
move a4, @0186F02Ch, 1
move a5, @0186F030h, 1
move b0, @0186F034h, 1
setf 16, 0, 0
setf 32, 0, 1
move @0186F000h, a0, 0 ; counter
inc a0
move a0, @0186F000h, 0
cmpi 0600h, a0
jrne draw ; only flip state on wrap
sub a0, a0
move a0, @0186F000h, 0
move @0186F002h, a1, 0 ; current state
cmpi 0, a1
jrne was_white
movk 1, a1 ; 0 -> 1 (white)
jruc set_state
was_white:
sub a1, a1 ; 1 -> 0 (black)
set_state:
move a1, @0186F002h, 0
draw:
move @0186F002h, a1, 0
cmpi 0, a1
jrne pat_white
sub a2, a2 ; black
jruc pat_ready
pat_white:
movi 0FFFFh, a2, L ; white
pat_ready:
movi 04064100h, a3, L ; 04000000h + 400*1024 + 256
movi 64, a4, L ; 64 rows
movi 4, a5, L ; 4 words = 64 px
drow:
move a5, a1
dword:
move a2, *a3+, 0
dsjs a1, dword
addi 03C0h, a3 ; 1024 - 64 bits
dsjs a4, drow
move @0186F030h, a5, 1
move @0186F02Ch, a4, 1
move @0186F028h, a3, 1
move @0186F024h, a2, 1
move @0186F020h, a1, 1
; leave with orig_pc on the stack and every touched register restored
move @0186F004h, a0, 1 ; orig_pc
move a0, -*sp, 1 ; push return PC for `rets`
move @0186F010h, a0, 1 ; restore interrupted a0
move @0186F014h, b0, 1 ; interrupted ST
putst b0 ; restore IE/fields
move @0186F034h, b0, 1 ; restore interrupted b0
rets ; pop orig_pc and resume
.end
+107
View File
@@ -0,0 +1,107 @@
; blinkpc.asm -- resident blink that draws AFTER the stock display handler.
;
; Hook: the firmware's DI RAM trampoline at bit 00000DB0h
; (RLONG(0xFFFFFEA0) = 00000DB0h, stub `JA 3F7146D0h`).
;
; entry saves the interrupt's saved PC, replaces it with ret_hook, then
; tail-jumps to the stock handler 3F7146D0h;
; ret_hook runs when the stock handler `reti`s, draws the box, and returns
; to the original PC with `rets 2` (the 2 skips the temporary a0
; slot and keeps the interrupted stack balanced).
;
; Drawing after the handler matters: a draw before it is wiped by the handler's
; own screen work (measured: blink.asm counter runs, no box in any frame).
;
; Box: framebuffer (256,400), 64x64, white Terminal Manager body.
; State toggles every 0014h invocations (~20 frames at ~1 DI/frame idle).
;
; Linked at bit 01840000h by dwt/visual/build.sh.
.text
_start: ; install, called by rdebug `jump`
pushst
dint
setf 32, 0, 0
movi entry, a0, L
move a0, @00000DC0h, 0
setf 16, 0, 0
movi 0C080h, a0, L
move a0, @00000DB0h, 0
sub a0, a0
move a0, @01840800h, 0 ; counter
move a0, @01840810h, 0 ; state (0 = black)
popst
rets
; ---- entry: point the interrupt's return at ret_hook, run stock handler ---
entry:
move a0, @01840860h, 1 ; save interrupted a0
setf 32, 0, 1
move *sp(020h), a0, 1 ; saved PC (SP -> ST, +20h -> PC)
move a0, @01840820h, 1 ; orig_pc
movi ret_hook, a0, L
move a0, *sp(020h), 1
move @01840860h, a0, 1
jauc 3F7146D0h ; stock OS display handler
; ---- ret_hook: after the stock handler, draw, then resume -----------------
ret_hook:
mmtm sp, a0,a1,a2,a3,a4,a5 ; field-independent A-reg save
getst a0
setf 32, 0, 1
move a0, @01840840h, 1 ; interrupted ST
dint
setf 16, 0, 0
setf 32, 0, 1
move @01840800h, a0, 0
inc a0
move a0, @01840800h, 0
cmpi 0014h, a0
jrne draw
sub a0, a0
move a0, @01840800h, 0
move @01840810h, a1, 0
cmpi 0, a1
jrne was_white
movk 1, a1
jruc set_state
was_white:
sub a1, a1
set_state:
move a1, @01840810h, 0
draw:
move @01840810h, a1, 0
cmpi 0, a1
jrne pat_white
sub a2, a2
jruc pat_ready
pat_white:
movi 0FFFFh, a2, L
pat_ready:
movi 04064100h, a3, L
movi 64, a4, L
movi 4, a5, L
drow:
move a5, a1
dword:
move a2, *a3+, 0
dsjs a1, dword
addi 03C0h, a3
dsjs a4, drow
; restore the A registers (field 1 is still 32)
mmfm sp, a0,a1,a2,a3,a4,a5
; leave with [ST][orig_pc] and the temporary a0 slot skipped by rets 2
setf 32, 0, 1
mmtm sp, a0 ; a0 slot at S-20h
move @01840820h, a0, 1 ; orig_pc
move a0, -*sp, 1 ; orig_pc at S-40h
move *sp(020h), a0, 1 ; restore a0 from S-20h
move @01840840h, a0, 1 ; interrupted ST (temporarily in a0)
move a0, -*sp, 1 ; ST at S-60h
move *sp(040h), a0, 1 ; restore a0 from S-20h
popst ; restore interrupted ST/IE
rets 2 ; pop orig_pc, skip the a0 slot
.end
+119
View File
@@ -0,0 +1,119 @@
; blinkpc.asm -- resident blink that draws AFTER the stock display handler.
;
; Hook: the firmware's DI RAM trampoline at bit 00000DB0h
; (RLONG(0xFFFFFEA0) = 00000DB0h, stub `JA 3F7146D0h`).
;
; entry saves the interrupt's saved PC, replaces it with ret_hook, then
; tail-jumps to the stock handler 3F7146D0h;
; ret_hook runs when the stock handler `reti`s, draws the box, and returns
; to the original PC with `rets 2` (the 2 skips the temporary a0
; slot and keeps the interrupted stack balanced).
;
; Drawing after the handler matters: a draw before it is wiped by the handler's
; own screen work (measured: blink.asm counter runs, no box in any frame).
;
; Box: framebuffer (256,400), 64x64, white Terminal Manager body.
; State toggles every 0014h invocations (~20 frames at ~1 DI/frame idle).
;
; Linked at bit 01840000h by dwt/visual/build.sh.
.text
_start: ; install, called by rdebug `jump`
pushst
dint
setf 32, 0, 0
movi entry, a0, L
move a0, @00000DC0h, 0
setf 16, 0, 0
movi 0C080h, a0, L
move a0, @00000DB0h, 0
sub a0, a0
move a0, @01840E00h, 0 ; counter
move a0, @01840E10h, 0 ; state (0 = black)
movi 0Ah, a0, L
move a0, @01840E30h, 0 ; skip the first 10 DI entries
popst
rets
; ---- entry: point the interrupt's return at ret_hook, run stock handler ---
entry:
move a0, @01840E60h, 1 ; save interrupted a0
setf 16, 0, 0
move @01840E30h, a0, 0 ; settle counter
cmpi 0, a0
jreq active
dec a0
move a0, @01840E30h, 0
setf 32, 0, 1
move @01840E60h, a0, 1
jauc 3F7146D0h ; still settling: stock handler only
active:
setf 32, 0, 1
move *sp(020h), a0, 1 ; saved PC (SP -> ST, +20h -> PC)
move a0, @01840E20h, 1 ; orig_pc
movi ret_hook, a0, L
move a0, *sp(020h), 1
move @01840E60h, a0, 1
jauc 3F7146D0h ; stock OS display handler
; ---- ret_hook: after the stock handler, draw, then resume -----------------
ret_hook:
dint ; first instruction: close the reti->hook race
mmtm sp, a0,a1,a2,a3,a4,a5 ; field-independent A-reg save
getst a0
setf 32, 0, 1
move a0, @01840E40h, 1 ; interrupted ST
setf 16, 0, 0
setf 32, 0, 1
move @01840E00h, a0, 0
inc a0
move a0, @01840E00h, 0
cmpi 0014h, a0
jrne draw
sub a0, a0
move a0, @01840E00h, 0
move @01840E10h, a1, 0
cmpi 0, a1
jrne was_white
movk 1, a1
jruc set_state
was_white:
sub a1, a1
set_state:
move a1, @01840E10h, 0
draw:
move @01840E10h, a1, 0
cmpi 0, a1
jrne pat_white
sub a2, a2
jruc pat_ready
pat_white:
movi 0FFFFh, a2, L
pat_ready:
movi 04064100h, a3, L
movi 64, a4, L
movi 4, a5, L
drow:
move a5, a1
dword:
move a2, *a3+, 0
dsjs a1, dword
addi 03C0h, a3
dsjs a4, drow
; restore the A registers (field 1 is still 32)
mmfm sp, a0,a1,a2,a3,a4,a5
; leave with [ST][orig_pc] and the temporary a0 slot skipped by rets 2
setf 32, 0, 1
mmtm sp, a0 ; a0 slot at S-20h
move @01840E20h, a0, 1 ; orig_pc
move a0, -*sp, 1 ; orig_pc at S-40h
move *sp(020h), a0, 1 ; restore a0 from S-20h
move @01840E40h, a0, 1 ; interrupted ST (temporarily in a0)
move a0, -*sp, 1 ; ST at S-60h
move *sp(040h), a0, 1 ; restore a0 from S-20h
popst ; restore interrupted ST/IE
rets 2 ; pop orig_pc, skip the a0 slot
.end
+30
View File
@@ -0,0 +1,30 @@
; boxalign.asm -- CONTROL: one word-aligned solid black 64x64 box, then spin.
;
; Box at framebuffer (512,416): x is a multiple of 16 (word-aligned), which is
; what the TMS34010 16-bit field store needs. Inside the Terminal Manager's
; white body, so a black box is unmistakable.
;
; Linked at bit 01840000h by dwt/visual/build.sh.
.text
_start:
setf 16, 0, 0
setf 32, 0, 1
sub a0, a0 ; pattern = 0000 (black)
movi 04068200h, a2, L ; 04000000h + 416*1024 + 512
movi 64, a3, L ; 64 rows
movi 4, a4, L ; 4 words = 64 px
row:
move a4, a5
word:
move a0, *a2+, 0
dsjs a5, word
addi 03C0h, a2 ; 1024 - 64 bits
dsjs a3, row
movi 0A11Ah, a0, L
move a0, @01850020h, 0 ; ALIGN_MARK = A11A
dint
spin:
nop
jruc spin
.end
+78
View File
@@ -0,0 +1,78 @@
#!/bin/sh
# Build a VT1200 payload with the 1987 TI TMS34010 SDK (GSPA/GSPLNK under
# DOSBox), the same flow as harness/hello-world/build.sh.
#
# dwt/visual/build.sh SOURCE.asm [ORIGIN_BITS]
#
# Outputs dwt/visual/build/<name>.bin (linked bytes) and <name>.map.
# Nothing outside dwt/visual/ is written.
set -eu
ROOT=$(cd "$(dirname "$0")/../.." && pwd)
DIR=$(cd "$(dirname "$0")" && pwd)
SRC=${1:?usage: build.sh SOURCE.asm [ORIGIN_BITS]}
ORIGIN=${2:-01800000}
NAME=$(basename "$SRC" .asm)
# DOS's 8.3 filesystem uppercases names; the tools write <NAME>.OUT etc.
BASE=$(printf '%s' "$NAME" | tr 'a-z' 'A-Z')
WORK="$DIR/work"
OUT="$DIR/build"
IMG="$ROOT/tools/tms34010-sdk/1987-05 TMS34010 SDK/1987-11-06 TMS34010 Simulator-C Tools-ASM Tools.img"
DOSBOX_CONF="$ROOT/harness/sdk-scratch/dosbox-bench.conf"
mkdir -p "$WORK" "$OUT"
if [ ! -x "$WORK/GSPA.EXE" ]; then
mcopy -s -n -i "$IMG" "::/A2/*" "$WORK/"
mcopy -s -n -i "$IMG" "::/C2/*" "$WORK/"
fi
cp "$SRC" "$WORK/$BASE.ASM"
# TI hex constants must begin with a decimal digit.
case "$ORIGIN" in
[0-9]*) ;;
*) ORIGIN="0$ORIGIN" ;;
esac
printf '%s\n' \
'-a' \
"-o $BASE.out" \
"-m $BASE.map" \
"$BASE.obj" \
'SECTIONS' \
'{' \
" .text ${ORIGIN}h: {}" \
'}' > "$WORK/$BASE.CMD"
sed -i 's/$/\r/' "$WORK/$BASE.CMD"
rm -f "$WORK/$BASE.OBJ" "$WORK/$BASE.OUT" "$WORK/$BASE.LST" \
"$WORK/$BASE.MAP" "$WORK/$BASE.HI" "$WORK/$BASE.LO"
SDL_VIDEODRIVER=dummy SDL_AUDIODRIVER=dummy \
timeout 180 dosbox -conf "$DOSBOX_CONF" -noprimaryconf -nolocalconf \
-c "mount c $WORK" -c "c:" \
-c "gspa $BASE $BASE.obj $BASE.lst -l" \
-c "gsplnk $BASE.cmd" \
-c "exit" -exit >/dev/null 2>&1
if [ ! -f "$WORK/$BASE.OUT" ]; then
echo "build.sh: GSPLNK produced no $BASE.OUT" >&2
exit 1
fi
if [ ! -f "$WORK/$BASE.OBJ" ]; then
echo "build.sh: GSPA produced no $BASE.OBJ" >&2
grep -n '\*\*\*\*\*' "$WORK/$BASE.LST" >&2 || true
exit 1
fi
if grep -q '\*\*\*\*\*' "$WORK/$BASE.LST"; then
echo "build.sh: assembler diagnostics:" >&2
grep -n '\*\*\*\*\*' "$WORK/$BASE.LST" >&2
exit 1
fi
python3 "$ROOT/harness/hello-world/cofextract.py" "$WORK/$BASE.OUT" "$OUT/$NAME.bin"
sed 's/\r$//' "$WORK/$BASE.MAP" > "$OUT/$NAME.map"
# Keep the listing too: it is the assembler's own record, addresses in bits.
cp "$WORK/$BASE.LST" "$OUT/$NAME.lst"
echo "build.sh: $OUT/$NAME.bin ($(wc -c < "$OUT/$NAME.bin") bytes) at bit $ORIGIN"
Binary file not shown.
+108
View File
@@ -0,0 +1,108 @@
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 02:56:54 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 1
0001 ; blink.asm -- resident blink hooked on the display int
0002 ; own RAM trampoline at bit 00000DB0h (RLONG(0xFFFFFEA0
0003 ;
0004 ; `install` (called by rdebug `jump`, returns) rewrites
0005 ; `JA 3F7146D0h` stub to `JA handler`. `handler` runs
0006 ; interrupt, toggles a 64x64 box on the Terminal Manage
0007 ; 0600h invocations, then tail-jumps to the stock OS di
0008 ;
0009 ; This is the "draw before the OS handler" variant. If
0010 ; afterwards, the box will not survive; that is what th
0011 ;
0012 ; Linked at bit 01840000h by dwt/visual/build.sh.
0013
0014 00000000 .text
0015 00000000 _start:
0016 00000000 01E0 pushst
0017 00000010 0360 dint
0018 00000020 0540 setf 32, 0, 0
0019 00000030 09E0 movi handler, a0, L
00000040 00000190'
0020 00000060 0580 move a0, @00000DC0h, 0 ; stub target
00000070 00000DC0
0021 00000090 0550 setf 16, 0, 0
0022 000000A0 09E0 movi 0C080h, a0, L
000000B0 0000C080
0023 000000D0 0580 move a0, @00000DB0h, 0 ; JA opcode
000000E0 00000DB0
0024 00000100 4400 sub a0, a0
0025 00000110 0580 move a0, @0186F000h, 0 ; counter
00000120 0186F000
0026 00000140 0580 move a0, @0186F002h, 0 ; state (0 = black)
00000150 0186F002
0027 00000170 01C0 popst
0028 00000180 0960 rets
0029
0030 00000190 handler:
0031 00000190 098F mmtm sp, a0,a1,a2,a3,a4,a5
000001A0 FC00
0032 000001B0 0550 setf 16, 0, 0
0033 000001C0 0740 setf 32, 0, 1
0034 000001D0 05A0 move @0186F000h, a0, 0
000001E0 0186F000
0035 00000200 1020 inc a0
0036 00000210 0580 move a0, @0186F000h, 0
00000220 0186F000
0037 00000240 0B40 cmpi 0600h, a0
00000250 F9FF
0038 00000260 CB10 jrne draw
0039 00000270 4400 sub a0, a0
0040 00000280 0580 move a0, @0186F000h, 0
00000290 0186F000
0041 000002B0 05A1 move @0186F002h, a1, 0
000002C0 0186F002
0042 000002E0 0B41 cmpi 0, a1
000002F0 FFFF
0043 00000300 CB02 jrne was_white
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 02:56:54 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 2
0044 00000310 1821 movk 1, a1
0045 00000320 C001 jruc set_state
0046 00000330 was_white:
0047 00000330 4421 sub a1, a1
0048 00000340 set_state:
0049 00000340 0581 move a1, @0186F002h, 0
00000350 0186F002
0050
0051 00000370 draw:
0052 00000370 05A1 move @0186F002h, a1, 0
00000380 0186F002
0053 000003A0 0B41 cmpi 0, a1
000003B0 FFFF
0054 000003C0 CB02 jrne pat_white
0055 000003D0 4442 sub a2, a2
0056 000003E0 C003 jruc pat_ready
0057 000003F0 pat_white:
0058 000003F0 09E2 movi 0FFFFh, a2, L
00000400 0000FFFF
0059 00000420 pat_ready:
0060 00000420 09E3 movi 04064100h, a3, L ; 04000000h + 400*1024 + 256
00000430 04064100
0061 00000450 09E4 movi 64, a4, L
00000460 00000040
0062 00000480 09E5 movi 4, a5, L
00000490 00000004
0063 000004B0 drow:
0064 000004B0 4CA1 move a5, a1
0065 000004C0 dword:
0066 000004C0 9043 move a2, *a3+, 0
0067 000004D0 3C41 dsjs a1, dword
0068 000004E0 0B03 addi 03C0h, a3
000004F0 03C0
0069 00000500 3CC4 dsjs a4, drow
0070
0071 00000510 09AF mmfm sp, a0,a1,a2,a3,a4,a5
00000520 003F
0072 00000530 C080 jauc 3F7146D0h ; stock OS display handler
00000540 3F7146D0
0073 .end
No Errors, No Warnings
+34
View File
@@ -0,0 +1,34 @@
*****************************************************
GSP COFF Linker, Version 2.00, 87.300
*****************************************************
Sun Oct 18 02:56:54 2026
OUTPUT FILE NAME: <BLINK.out>
ENTRY POINT SYMBOL: 0
SECTION ALLOCATION MAP
output attributes/
section page origin length input sections
-------- ---- ---------- ---------- ----------------
.data 0 00000000 00000000
.bss 0 00000000 00000000 UNINITIALIZED
.text 0 01840000 00000560
01840000 00000560 BLINK.obj (.text)
GLOBAL SYMBOLS
address name address name
-------- ---- -------- ----
00000000 .bss 00000000 edata
00000000 .data 00000000 .bss
01840000 .text 00000000 end
00000000 edata 00000000 .data
00000000 end 01840000 .text
01840560 etext 01840560 etext
[6 symbols]
Binary file not shown.
+178
View File
@@ -0,0 +1,178 @@
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 03:16:09 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 1
0001 ; blinkpc.asm -- resident blink that draws AFTER the st
0002 ;
0003 ; Hook: the firmware's DI RAM trampoline at bit 00000DB
0004 ; (RLONG(0xFFFFFEA0) = 00000DB0h, stub `JA 3F714530h`).
0005 ;
0006 ; entry saves the interrupt's saved PC, replaces i
0007 ; tail-jumps to the stock handler 3F714530h;
0008 ; ret_hook runs when the stock handler `reti`s, draws
0009 ; to the original PC with `rets 2` (the 2 sk
0010 ; slot and keeps the interrupted stack balan
0011 ;
0012 ; Drawing after the handler matters: a draw before it i
0013 ; own screen work (measured: blink.asm counter runs, no
0014 ;
0015 ; Box: framebuffer (256,400), 64x64, white Terminal Man
0016 ; State toggles every 0014h invocations (~20 frames at
0017 ;
0018 ; Linked at bit 01840000h by dwt/visual/build.sh.
0019
0020 00000000 .text
0021 00000000 _start: ; install, called by rdebug `jump`
0022 00000000 01E0 pushst
0023 00000010 0360 dint
0024 00000020 0540 setf 32, 0, 0
0025 00000030 09E0 movi entry, a0, L
00000040 000001F0'
0026 00000060 0580 move a0, @00000F40h, 0
00000070 00000F40
0027 00000090 0550 setf 16, 0, 0
0028 000000A0 09E0 movi 0C080h, a0, L
000000B0 0000C080
0029 000000D0 0580 move a0, @00000F30h, 0
000000E0 00000F30
0030 00000100 4400 sub a0, a0
0031 00000110 0580 move a0, @01840E00h, 0 ; counter
00000120 01840E00
0032 00000140 0580 move a0, @01840E10h, 0 ; state (0 = black)
00000150 01840E10
0033 00000170 09E0 movi 0Ah, a0, L
00000180 0000000A
0034 000001A0 0580 move a0, @01840E30h, 0 ; skip the first 10 DI entries
000001B0 01840E30
0035 000001D0 01C0 popst
0036 000001E0 0960 rets
0037
0038 ; ---- entry: point the interrupt's return at ret_hook,
0039 000001F0 entry:
0040 000001F0 0780 move a0, @01840E60h, 1 ; save interrupted a0
00000200 01840E60
0041 00000220 0550 setf 16, 0, 0
0042 00000230 05A0 move @01840E30h, a0, 0 ; settle counter
00000240 01840E30
0043 00000260 0B40 cmpi 0, a0
00000270 FFFF
0044 00000280 CA0B jreq active
0045 00000290 1420 dec a0
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 03:16:09 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 2
0046 000002A0 0580 move a0, @01840E30h, 0
000002B0 01840E30
0047 000002D0 0740 setf 32, 0, 1
0048 000002E0 07A0 move @01840E60h, a0, 1
000002F0 01840E60
0049 00000310 C080 jauc 3F714530h ; still settling: stock handler only
00000320 3F714530
0050 00000340 active:
0051 00000340 0740 setf 32, 0, 1
0052 00000350 B7E0 move *sp(020h), a0, 1 ; saved PC (SP -> ST, +20h -> PC
00000360 0020
0053 00000370 0780 move a0, @01840E20h, 1 ; orig_pc
00000380 01840E20
0054 000003A0 09E0 movi ret_hook, a0, L
000003B0 00000450'
0055 000003D0 B20F move a0, *sp(020h), 1
000003E0 0020
0056 000003F0 07A0 move @01840E60h, a0, 1
00000400 01840E60
0057 00000420 C080 jauc 3F714530h ; stock OS display handler
00000430 3F714530
0058
0059 ; ---- ret_hook: after the stock handler, draw, then re
0060 00000450 ret_hook:
0061 00000450 0360 dint ; first instruction: close the reti->hook race
0062 00000460 098F mmtm sp, a0,a1,a2,a3,a4,a5 ; field-independent A-reg s
00000470 FC00
0063 00000480 0180 getst a0
0064 00000490 0740 setf 32, 0, 1
0065 000004A0 0780 move a0, @01840E40h, 1 ; interrupted ST
000004B0 01840E40
0066
0067 000004D0 0550 setf 16, 0, 0
0068 000004E0 0740 setf 32, 0, 1
0069 000004F0 05A0 move @01840E00h, a0, 0
00000500 01840E00
0070 00000520 1020 inc a0
0071 00000530 0580 move a0, @01840E00h, 0
00000540 01840E00
0072 00000560 0B40 cmpi 0014h, a0
00000570 FFEB
0073 00000580 CB10 jrne draw
0074 00000590 4400 sub a0, a0
0075 000005A0 0580 move a0, @01840E00h, 0
000005B0 01840E00
0076 000005D0 05A1 move @01840E10h, a1, 0
000005E0 01840E10
0077 00000600 0B41 cmpi 0, a1
00000610 FFFF
0078 00000620 CB02 jrne was_white
0079 00000630 1821 movk 1, a1
0080 00000640 C001 jruc set_state
0081 00000650 was_white:
0082 00000650 4421 sub a1, a1
0083 00000660 set_state:
0084 00000660 0581 move a1, @01840E10h, 0
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 03:16:09 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 3
00000670 01840E10
0085
0086 00000690 draw:
0087 00000690 05A1 move @01840E10h, a1, 0
000006A0 01840E10
0088 000006C0 0B41 cmpi 0, a1
000006D0 FFFF
0089 000006E0 CB02 jrne pat_white
0090 000006F0 4442 sub a2, a2
0091 00000700 C003 jruc pat_ready
0092 00000710 pat_white:
0093 00000710 09E2 movi 0FFFFh, a2, L
00000720 0000FFFF
0094 00000740 pat_ready:
0095 00000740 09E3 movi 04064100h, a3, L
00000750 04064100
0096 00000770 09E4 movi 64, a4, L
00000780 00000040
0097 000007A0 09E5 movi 4, a5, L
000007B0 00000004
0098 000007D0 drow:
0099 000007D0 4CA1 move a5, a1
0100 000007E0 dword:
0101 000007E0 9043 move a2, *a3+, 0
0102 000007F0 3C41 dsjs a1, dword
0103 00000800 0B03 addi 03C0h, a3
00000810 03C0
0104 00000820 3CC4 dsjs a4, drow
0105
0106 ; restore the A registers (field 1 is still 32)
0107 00000830 09AF mmfm sp, a0,a1,a2,a3,a4,a5
00000840 003F
0108 ; leave with [ST][orig_pc] and the temporary a0 slot s
0109 00000850 0740 setf 32, 0, 1
0110 00000860 098F mmtm sp, a0 ; a0 slot at S-20h
00000870 8000
0111 00000880 07A0 move @01840E20h, a0, 1 ; orig_pc
00000890 01840E20
0112 000008B0 A20F move a0, -*sp, 1 ; orig_pc at S-40h
0113 000008C0 B7E0 move *sp(020h), a0, 1 ; restore a0 from S-20h
000008D0 0020
0114 000008E0 07A0 move @01840E40h, a0, 1 ; interrupted ST (temporarily i
000008F0 01840E40
0115 00000910 A20F move a0, -*sp, 1 ; ST at S-60h
0116 00000920 B7E0 move *sp(040h), a0, 1 ; restore a0 from S-20h
00000930 0040
0117 00000940 01C0 popst ; restore interrupted ST/IE
0118 00000950 0962 rets 2 ; pop orig_pc, skip the a0 slot
0119 .end
No Errors, No Warnings
+34
View File
@@ -0,0 +1,34 @@
*****************************************************
GSP COFF Linker, Version 2.00, 87.300
*****************************************************
Sun Oct 18 03:16:09 2026
OUTPUT FILE NAME: <BLINK2.out>
ENTRY POINT SYMBOL: 0
SECTION ALLOCATION MAP
output attributes/
section page origin length input sections
-------- ---- ---------- ---------- ----------------
.data 0 00000000 00000000
.bss 0 00000000 00000000 UNINITIALIZED
.text 0 01840000 00000960
01840000 00000960 BLINK2.obj (.text)
GLOBAL SYMBOLS
address name address name
-------- ---- -------- ----
00000000 .bss 00000000 edata
00000000 .data 00000000 .bss
01840000 .text 00000000 end
00000000 edata 00000000 .data
00000000 end 01840000 .text
01840960 etext 01840960 etext
[6 symbols]
Binary file not shown.
+159
View File
@@ -0,0 +1,159 @@
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 03:19:02 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 1
0001 ; blinkpc.asm -- resident blink that draws AFTER the st
0002 ;
0003 ; Hook: the firmware's DI RAM trampoline at bit 00000DB
0004 ; (RLONG(0xFFFFFEA0) = 00000DB0h, stub `JA 3F7146D0h`).
0005 ;
0006 ; entry saves the interrupt's saved PC, replaces i
0007 ; tail-jumps to the stock handler 3F7146D0h;
0008 ; ret_hook runs when the stock handler `reti`s, draws
0009 ; to the original PC with `rets 2` (the 2 sk
0010 ; slot and keeps the interrupted stack balan
0011 ;
0012 ; Drawing after the handler matters: a draw before it i
0013 ; own screen work (measured: blink.asm counter runs, no
0014 ;
0015 ; Box: framebuffer (256,400), 64x64, white Terminal Man
0016 ; State toggles every 0014h invocations (~20 frames at
0017 ;
0018 ; Linked at bit 01840000h by dwt/visual/build.sh.
0019
0020 00000000 .text
0021 00000000 _start: ; install, called by rdebug `jump`
0022 00000000 01E0 pushst
0023 00000010 0360 dint
0024 00000020 0540 setf 32, 0, 0
0025 00000030 09E0 movi entry, a0, L
00000040 00000190'
0026 00000060 0580 move a0, @00000DC0h, 0
00000070 00000DC0
0027 00000090 0550 setf 16, 0, 0
0028 000000A0 09E0 movi 0C080h, a0, L
000000B0 0000C080
0029 000000D0 0580 move a0, @00000DB0h, 0
000000E0 00000DB0
0030 00000100 4400 sub a0, a0
0031 00000110 0580 move a0, @01840800h, 0 ; counter
00000120 01840800
0032 00000140 0580 move a0, @01840810h, 0 ; state (0 = black)
00000150 01840810
0033 00000170 01C0 popst
0034 00000180 0960 rets
0035
0036 ; ---- entry: point the interrupt's return at ret_hook,
0037 00000190 entry:
0038 00000190 0780 move a0, @01840860h, 1 ; save interrupted a0
000001A0 01840860
0039 000001C0 0740 setf 32, 0, 1
0040 000001D0 B7E0 move *sp(020h), a0, 1 ; saved PC (SP -> ST, +20h -> PC
000001E0 0020
0041 000001F0 0780 move a0, @01840820h, 1 ; orig_pc
00000200 01840820
0042 00000220 09E0 movi ret_hook, a0, L
00000230 000002D0'
0043 00000250 B20F move a0, *sp(020h), 1
00000260 0020
0044 00000270 07A0 move @01840860h, a0, 1
00000280 01840860
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 03:19:02 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 2
0045 000002A0 C080 jauc 3F7146D0h ; stock OS display handler
000002B0 3F7146D0
0046
0047 ; ---- ret_hook: after the stock handler, draw, then re
0048 000002D0 ret_hook:
0049 000002D0 098F mmtm sp, a0,a1,a2,a3,a4,a5 ; field-independent A-reg s
000002E0 FC00
0050 000002F0 0180 getst a0
0051 00000300 0740 setf 32, 0, 1
0052 00000310 0780 move a0, @01840840h, 1 ; interrupted ST
00000320 01840840
0053 00000340 0360 dint
0054
0055 00000350 0550 setf 16, 0, 0
0056 00000360 0740 setf 32, 0, 1
0057 00000370 05A0 move @01840800h, a0, 0
00000380 01840800
0058 000003A0 1020 inc a0
0059 000003B0 0580 move a0, @01840800h, 0
000003C0 01840800
0060 000003E0 0B40 cmpi 0014h, a0
000003F0 FFEB
0061 00000400 CB10 jrne draw
0062 00000410 4400 sub a0, a0
0063 00000420 0580 move a0, @01840800h, 0
00000430 01840800
0064 00000450 05A1 move @01840810h, a1, 0
00000460 01840810
0065 00000480 0B41 cmpi 0, a1
00000490 FFFF
0066 000004A0 CB02 jrne was_white
0067 000004B0 1821 movk 1, a1
0068 000004C0 C001 jruc set_state
0069 000004D0 was_white:
0070 000004D0 4421 sub a1, a1
0071 000004E0 set_state:
0072 000004E0 0581 move a1, @01840810h, 0
000004F0 01840810
0073
0074 00000510 draw:
0075 00000510 05A1 move @01840810h, a1, 0
00000520 01840810
0076 00000540 0B41 cmpi 0, a1
00000550 FFFF
0077 00000560 CB02 jrne pat_white
0078 00000570 4442 sub a2, a2
0079 00000580 C003 jruc pat_ready
0080 00000590 pat_white:
0081 00000590 09E2 movi 0FFFFh, a2, L
000005A0 0000FFFF
0082 000005C0 pat_ready:
0083 000005C0 09E3 movi 04064100h, a3, L
000005D0 04064100
0084 000005F0 09E4 movi 64, a4, L
00000600 00000040
0085 00000620 09E5 movi 4, a5, L
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 03:19:02 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 3
00000630 00000004
0086 00000650 drow:
0087 00000650 4CA1 move a5, a1
0088 00000660 dword:
0089 00000660 9043 move a2, *a3+, 0
0090 00000670 3C41 dsjs a1, dword
0091 00000680 0B03 addi 03C0h, a3
00000690 03C0
0092 000006A0 3CC4 dsjs a4, drow
0093
0094 ; restore the A registers (field 1 is still 32)
0095 000006B0 09AF mmfm sp, a0,a1,a2,a3,a4,a5
000006C0 003F
0096 ; leave with [ST][orig_pc] and the temporary a0 slot s
0097 000006D0 0740 setf 32, 0, 1
0098 000006E0 098F mmtm sp, a0 ; a0 slot at S-20h
000006F0 8000
0099 00000700 07A0 move @01840820h, a0, 1 ; orig_pc
00000710 01840820
0100 00000730 A20F move a0, -*sp, 1 ; orig_pc at S-40h
0101 00000740 B7E0 move *sp(020h), a0, 1 ; restore a0 from S-20h
00000750 0020
0102 00000760 07A0 move @01840840h, a0, 1 ; interrupted ST (temporarily i
00000770 01840840
0103 00000790 A20F move a0, -*sp, 1 ; ST at S-60h
0104 000007A0 B7E0 move *sp(040h), a0, 1 ; restore a0 from S-20h
000007B0 0040
0105 000007C0 01C0 popst ; restore interrupted ST/IE
0106 000007D0 0962 rets 2 ; pop orig_pc, skip the a0 slot
0107 .end
No Errors, No Warnings
+34
View File
@@ -0,0 +1,34 @@
*****************************************************
GSP COFF Linker, Version 2.00, 87.300
*****************************************************
Sun Oct 18 03:19:02 2026
OUTPUT FILE NAME: <BLINKEV.out>
ENTRY POINT SYMBOL: 0
SECTION ALLOCATION MAP
output attributes/
section page origin length input sections
-------- ---- ---------- ---------- ----------------
.data 0 00000000 00000000
.bss 0 00000000 00000000 UNINITIALIZED
.text 0 01840000 000007E0
01840000 000007E0 BLINKEV.obj (.text)
GLOBAL SYMBOLS
address name address name
-------- ---- -------- ----
00000000 .bss 00000000 edata
00000000 .data 00000000 .bss
01840000 .text 00000000 end
00000000 edata 00000000 .data
00000000 end 01840000 .text
018407E0 etext 018407E0 etext
[6 symbols]
Binary file not shown.
+178
View File
@@ -0,0 +1,178 @@
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 03:15:05 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 1
0001 ; blinkpc.asm -- resident blink that draws AFTER the st
0002 ;
0003 ; Hook: the firmware's DI RAM trampoline at bit 00000DB
0004 ; (RLONG(0xFFFFFEA0) = 00000DB0h, stub `JA 3F7146D0h`).
0005 ;
0006 ; entry saves the interrupt's saved PC, replaces i
0007 ; tail-jumps to the stock handler 3F7146D0h;
0008 ; ret_hook runs when the stock handler `reti`s, draws
0009 ; to the original PC with `rets 2` (the 2 sk
0010 ; slot and keeps the interrupted stack balan
0011 ;
0012 ; Drawing after the handler matters: a draw before it i
0013 ; own screen work (measured: blink.asm counter runs, no
0014 ;
0015 ; Box: framebuffer (256,400), 64x64, white Terminal Man
0016 ; State toggles every 0014h invocations (~20 frames at
0017 ;
0018 ; Linked at bit 01840000h by dwt/visual/build.sh.
0019
0020 00000000 .text
0021 00000000 _start: ; install, called by rdebug `jump`
0022 00000000 01E0 pushst
0023 00000010 0360 dint
0024 00000020 0540 setf 32, 0, 0
0025 00000030 09E0 movi entry, a0, L
00000040 000001F0'
0026 00000060 0580 move a0, @00000DC0h, 0
00000070 00000DC0
0027 00000090 0550 setf 16, 0, 0
0028 000000A0 09E0 movi 0C080h, a0, L
000000B0 0000C080
0029 000000D0 0580 move a0, @00000DB0h, 0
000000E0 00000DB0
0030 00000100 4400 sub a0, a0
0031 00000110 0580 move a0, @01840E00h, 0 ; counter
00000120 01840E00
0032 00000140 0580 move a0, @01840E10h, 0 ; state (0 = black)
00000150 01840E10
0033 00000170 09E0 movi 0Ah, a0, L
00000180 0000000A
0034 000001A0 0580 move a0, @01840E30h, 0 ; skip the first 10 DI entries
000001B0 01840E30
0035 000001D0 01C0 popst
0036 000001E0 0960 rets
0037
0038 ; ---- entry: point the interrupt's return at ret_hook,
0039 000001F0 entry:
0040 000001F0 0780 move a0, @01840E60h, 1 ; save interrupted a0
00000200 01840E60
0041 00000220 0550 setf 16, 0, 0
0042 00000230 05A0 move @01840E30h, a0, 0 ; settle counter
00000240 01840E30
0043 00000260 0B40 cmpi 0, a0
00000270 FFFF
0044 00000280 CA0B jreq active
0045 00000290 1420 dec a0
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 03:15:05 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 2
0046 000002A0 0580 move a0, @01840E30h, 0
000002B0 01840E30
0047 000002D0 0740 setf 32, 0, 1
0048 000002E0 07A0 move @01840E60h, a0, 1
000002F0 01840E60
0049 00000310 C080 jauc 3F7146D0h ; still settling: stock handler only
00000320 3F7146D0
0050 00000340 active:
0051 00000340 0740 setf 32, 0, 1
0052 00000350 B7E0 move *sp(020h), a0, 1 ; saved PC (SP -> ST, +20h -> PC
00000360 0020
0053 00000370 0780 move a0, @01840E20h, 1 ; orig_pc
00000380 01840E20
0054 000003A0 09E0 movi ret_hook, a0, L
000003B0 00000450'
0055 000003D0 B20F move a0, *sp(020h), 1
000003E0 0020
0056 000003F0 07A0 move @01840E60h, a0, 1
00000400 01840E60
0057 00000420 C080 jauc 3F7146D0h ; stock OS display handler
00000430 3F7146D0
0058
0059 ; ---- ret_hook: after the stock handler, draw, then re
0060 00000450 ret_hook:
0061 00000450 0360 dint ; first instruction: close the reti->hook race
0062 00000460 098F mmtm sp, a0,a1,a2,a3,a4,a5 ; field-independent A-reg s
00000470 FC00
0063 00000480 0180 getst a0
0064 00000490 0740 setf 32, 0, 1
0065 000004A0 0780 move a0, @01840E40h, 1 ; interrupted ST
000004B0 01840E40
0066
0067 000004D0 0550 setf 16, 0, 0
0068 000004E0 0740 setf 32, 0, 1
0069 000004F0 05A0 move @01840E00h, a0, 0
00000500 01840E00
0070 00000520 1020 inc a0
0071 00000530 0580 move a0, @01840E00h, 0
00000540 01840E00
0072 00000560 0B40 cmpi 0014h, a0
00000570 FFEB
0073 00000580 CB10 jrne draw
0074 00000590 4400 sub a0, a0
0075 000005A0 0580 move a0, @01840E00h, 0
000005B0 01840E00
0076 000005D0 05A1 move @01840E10h, a1, 0
000005E0 01840E10
0077 00000600 0B41 cmpi 0, a1
00000610 FFFF
0078 00000620 CB02 jrne was_white
0079 00000630 1821 movk 1, a1
0080 00000640 C001 jruc set_state
0081 00000650 was_white:
0082 00000650 4421 sub a1, a1
0083 00000660 set_state:
0084 00000660 0581 move a1, @01840E10h, 0
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 03:15:05 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 3
00000670 01840E10
0085
0086 00000690 draw:
0087 00000690 05A1 move @01840E10h, a1, 0
000006A0 01840E10
0088 000006C0 0B41 cmpi 0, a1
000006D0 FFFF
0089 000006E0 CB02 jrne pat_white
0090 000006F0 4442 sub a2, a2
0091 00000700 C003 jruc pat_ready
0092 00000710 pat_white:
0093 00000710 09E2 movi 0FFFFh, a2, L
00000720 0000FFFF
0094 00000740 pat_ready:
0095 00000740 09E3 movi 04064100h, a3, L
00000750 04064100
0096 00000770 09E4 movi 64, a4, L
00000780 00000040
0097 000007A0 09E5 movi 4, a5, L
000007B0 00000004
0098 000007D0 drow:
0099 000007D0 4CA1 move a5, a1
0100 000007E0 dword:
0101 000007E0 9043 move a2, *a3+, 0
0102 000007F0 3C41 dsjs a1, dword
0103 00000800 0B03 addi 03C0h, a3
00000810 03C0
0104 00000820 3CC4 dsjs a4, drow
0105
0106 ; restore the A registers (field 1 is still 32)
0107 00000830 09AF mmfm sp, a0,a1,a2,a3,a4,a5
00000840 003F
0108 ; leave with [ST][orig_pc] and the temporary a0 slot s
0109 00000850 0740 setf 32, 0, 1
0110 00000860 098F mmtm sp, a0 ; a0 slot at S-20h
00000870 8000
0111 00000880 07A0 move @01840E20h, a0, 1 ; orig_pc
00000890 01840E20
0112 000008B0 A20F move a0, -*sp, 1 ; orig_pc at S-40h
0113 000008C0 B7E0 move *sp(020h), a0, 1 ; restore a0 from S-20h
000008D0 0020
0114 000008E0 07A0 move @01840E40h, a0, 1 ; interrupted ST (temporarily i
000008F0 01840E40
0115 00000910 A20F move a0, -*sp, 1 ; ST at S-60h
0116 00000920 B7E0 move *sp(040h), a0, 1 ; restore a0 from S-20h
00000930 0040
0117 00000940 01C0 popst ; restore interrupted ST/IE
0118 00000950 0962 rets 2 ; pop orig_pc, skip the a0 slot
0119 .end
No Errors, No Warnings
+34
View File
@@ -0,0 +1,34 @@
*****************************************************
GSP COFF Linker, Version 2.00, 87.300
*****************************************************
Sun Oct 18 03:15:05 2026
OUTPUT FILE NAME: <BLINKPC.out>
ENTRY POINT SYMBOL: 0
SECTION ALLOCATION MAP
output attributes/
section page origin length input sections
-------- ---- ---------- ---------- ----------------
.data 0 00000000 00000000
.bss 0 00000000 00000000 UNINITIALIZED
.text 0 01840000 00000960
01840000 00000960 BLINKPC.obj (.text)
GLOBAL SYMBOLS
address name address name
-------- ---- -------- ----
00000000 .bss 00000000 edata
00000000 .data 00000000 .bss
01840000 .text 00000000 end
00000000 edata 00000000 .data
00000000 end 01840000 .text
01840960 etext 01840960 etext
[6 symbols]
Binary file not shown.
+43
View File
@@ -0,0 +1,43 @@
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 02:53:14 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 1
0001 ; boxalign.asm -- CONTROL: one word-aligned solid black
0002 ;
0003 ; Box at framebuffer (512,416): x is a multiple of 16 (
0004 ; what the TMS34010 16-bit field store needs. Inside t
0005 ; white body, so a black box is unmistakable.
0006 ;
0007 ; Linked at bit 01840000h by dwt/visual/build.sh.
0008
0009 00000000 .text
0010 00000000 _start:
0011 00000000 0550 setf 16, 0, 0
0012 00000010 0740 setf 32, 0, 1
0013 00000020 4400 sub a0, a0 ; pattern = 0000 (black)
0014 00000030 09E2 movi 04068200h, a2, L ; 04000000h + 416*1024 + 512
00000040 04068200
0015 00000060 09E3 movi 64, a3, L ; 64 rows
00000070 00000040
0016 00000090 09E4 movi 4, a4, L ; 4 words = 64 px
000000A0 00000004
0017 000000C0 row:
0018 000000C0 4C85 move a4, a5
0019 000000D0 word:
0020 000000D0 9002 move a0, *a2+, 0
0021 000000E0 3C45 dsjs a5, word
0022 000000F0 0B02 addi 03C0h, a2 ; 1024 - 64 bits
00000100 03C0
0023 00000110 3CC3 dsjs a3, row
0024 00000120 09E0 movi 0A11Ah, a0, L
00000130 0000A11A
0025 00000150 0580 move a0, @01850020h, 0 ; ALIGN_MARK = A11A
00000160 01850020
0026 00000180 0360 dint
0027 00000190 spin:
0028 00000190 0300 nop
0029 000001A0 C0FE jruc spin
0030 .end
No Errors, No Warnings
+34
View File
@@ -0,0 +1,34 @@
*****************************************************
GSP COFF Linker, Version 2.00, 87.300
*****************************************************
Sun Oct 18 02:53:14 2026
OUTPUT FILE NAME: <BOXALIGN.out>
ENTRY POINT SYMBOL: 0
SECTION ALLOCATION MAP
output attributes/
section page origin length input sections
-------- ---- ---------- ---------- ----------------
.data 0 00000000 00000000
.bss 0 00000000 00000000 UNINITIALIZED
.text 0 01840000 000001B0
01840000 000001B0 BOXALIGN.obj (.text)
GLOBAL SYMBOLS
address name address name
-------- ---- -------- ----
00000000 .bss 00000000 edata
00000000 .data 00000000 .bss
01840000 .text 00000000 end
00000000 edata 00000000 .data
00000000 end 01840000 .text
018401B0 etext 018401B0 etext
[6 symbols]
Binary file not shown.
+90
View File
@@ -0,0 +1,90 @@
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 02:49:28 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 1
0001 ; draw_box.asm -- one-shot static VRAM injection, then
0002 ;
0003 ; Draws three 32x32 solid-white boxes at framebuffer (x
0004 ; A (50,50) -- root weave, outside every window
0005 ; B (250,400) -- inside the Terminal Manager window b
0006 ; C (930,750) -- root weave, lower right
0007 ; Writes marker words and returns with `rets`, so the r
0008 ;
0009 ; Framebuffer model (harness/mame/RENDER_REPORT.md): ba
0010 ; 1024 bits per row, bit 0 = leftmost pixel, LSB-first
0011 ;
0012 ; Linked at bit 01840000h by dwt/visual/build.sh.
0013
0014 00000000 .text
0015 00000000 _start:
0016 00000000 0550 setf 16, 0, 0
0017 00000010 0740 setf 32, 0, 1
0018 00000020 09E0 movi 0FFFFh, a0, L ; pattern
00000030 0000FFFF
0019
0020 ; ---- box A: (50,50), 32 rows x 2 words = 32x32 px --
0021 00000050 09E2 movi 0400C832h, a2, L ; 04000000h + 50*1024 + 50
00000060 0400C832
0022 00000080 09E3 movi 32, a3, L
00000090 00000020
0023 000000B0 09E4 movi 2, a4, L
000000C0 00000002
0024 000000E0 rowA:
0025 000000E0 4C85 move a4, a5
0026 000000F0 wordA:
0027 000000F0 9002 move a0, *a2+, 0
0028 00000100 3C45 dsjs a5, wordA
0029 00000110 0B02 addi 03E0h, a2 ; 1024 - 32 bits
00000120 03E0
0030 00000130 3CC3 dsjs a3, rowA
0031
0032 ; ---- box B: (250,400) ------------------------------
0033 00000140 09E2 movi 040640FAh, a2, L ; 04000000h + 400*1024 + 250
00000150 040640FA
0034 00000170 09E3 movi 32, a3, L
00000180 00000020
0035 000001A0 09E4 movi 2, a4, L
000001B0 00000002
0036 000001D0 rowB:
0037 000001D0 4C85 move a4, a5
0038 000001E0 wordB:
0039 000001E0 9002 move a0, *a2+, 0
0040 000001F0 3C45 dsjs a5, wordB
0041 00000200 0B02 addi 03E0h, a2
00000210 03E0
0042 00000220 3CC3 dsjs a3, rowB
0043
0044 ; ---- box C: (930,750) ------------------------------
0045 00000230 09E2 movi 040BBBA2h, a2, L ; 04000000h + 750*1024 + 930
00000240 040BBBA2
0046 00000260 09E3 movi 32, a3, L
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 02:49:28 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 2
00000270 00000020
0047 00000290 09E4 movi 2, a4, L
000002A0 00000002
0048 000002C0 rowC:
0049 000002C0 4C85 move a4, a5
0050 000002D0 wordC:
0051 000002D0 9002 move a0, *a2+, 0
0052 000002E0 3C45 dsjs a5, wordC
0053 000002F0 0B02 addi 03E0h, a2
00000300 03E0
0054 00000310 3CC3 dsjs a3, rowC
0055
0056 00000320 09E0 movi 0D2A0h, a0, L
00000330 0000D2A0
0057 00000350 0580 move a0, @01850020h, 0 ; DRAW_MARK = D2A0
00000360 01850020
0058 00000380 09E0 movi 0B0C0h, a0, L
00000390 0000B0C0
0059 000003B0 0580 move a0, @01850030h, 0 ; DRAW_MARK2 = B0C0
000003C0 01850030
0060 000003E0 0960 rets
0061 .end
No Errors, No Warnings
+34
View File
@@ -0,0 +1,34 @@
*****************************************************
GSP COFF Linker, Version 2.00, 87.300
*****************************************************
Sun Oct 18 02:49:28 2026
OUTPUT FILE NAME: <DRAW_BOX.out>
ENTRY POINT SYMBOL: 0
SECTION ALLOCATION MAP
output attributes/
section page origin length input sections
-------- ---- ---------- ---------- ----------------
.data 0 00000000 00000000
.bss 0 00000000 00000000 UNINITIALIZED
.text 0 01840000 000003F0
01840000 000003F0 DRAW_BOX.obj (.text)
GLOBAL SYMBOLS
address name address name
-------- ---- -------- ----
00000000 .bss 00000000 edata
00000000 .data 00000000 .bss
01840000 .text 00000000 end
00000000 edata 00000000 .data
00000000 end 01840000 .text
018403F0 etext 018403F0 etext
[6 symbols]
Binary file not shown.
+87
View File
@@ -0,0 +1,87 @@
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 02:53:46 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 1
0001 ; drawal.asm -- one-shot static VRAM draw at word-align
0002 ;
0003 ; Three solid-black 32x32 boxes:
0004 ; A (48,48) root weave, outside every window
0005 ; B (256,400) inside the Terminal Manager white body
0006 ; C (928,752) root weave, lower right
0007 ; All x are multiples of 16, which the TMS34010 16-bit
0008 ; Writes marker words, then `rets` so the rdebug sessio
0009 ;
0010 ; Linked at bit 01840000h by dwt/visual/build.sh.
0011
0012 00000000 .text
0013 00000000 _start:
0014 00000000 0550 setf 16, 0, 0
0015 00000010 0740 setf 32, 0, 1
0016 00000020 4400 sub a0, a0 ; 0000 = black
0017
0018 ; box A (48,48)
0019 00000030 09E2 movi 0400C030h, a2, L
00000040 0400C030
0020 00000060 09E3 movi 32, a3, L
00000070 00000020
0021 00000090 09E4 movi 2, a4, L
000000A0 00000002
0022 000000C0 rowA:
0023 000000C0 4C85 move a4, a5
0024 000000D0 wordA:
0025 000000D0 9002 move a0, *a2+, 0
0026 000000E0 3C45 dsjs a5, wordA
0027 000000F0 0B02 addi 03E0h, a2
00000100 03E0
0028 00000110 3CC3 dsjs a3, rowA
0029
0030 ; box B (256,400)
0031 00000120 09E2 movi 04064100h, a2, L
00000130 04064100
0032 00000150 09E3 movi 32, a3, L
00000160 00000020
0033 00000180 09E4 movi 2, a4, L
00000190 00000002
0034 000001B0 rowB:
0035 000001B0 4C85 move a4, a5
0036 000001C0 wordB:
0037 000001C0 9002 move a0, *a2+, 0
0038 000001D0 3C45 dsjs a5, wordB
0039 000001E0 0B02 addi 03E0h, a2
000001F0 03E0
0040 00000200 3CC3 dsjs a3, rowB
0041
0042 ; box C (928,752)
0043 00000210 09E2 movi 040BC3A0h, a2, L
00000220 040BC3A0
0044 00000240 09E3 movi 32, a3, L
00000250 00000020
0045 00000270 09E4 movi 2, a4, L
00000280 00000002
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 02:53:46 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 2
0046 000002A0 rowC:
0047 000002A0 4C85 move a4, a5
0048 000002B0 wordC:
0049 000002B0 9002 move a0, *a2+, 0
0050 000002C0 3C45 dsjs a5, wordC
0051 000002D0 0B02 addi 03E0h, a2
000002E0 03E0
0052 000002F0 3CC3 dsjs a3, rowC
0053
0054 00000300 09E0 movi 0D2A0h, a0, L
00000310 0000D2A0
0055 00000330 0580 move a0, @01850020h, 0 ; DRAW_MARK = D2A0
00000340 01850020
0056 00000360 09E0 movi 0B0C0h, a0, L
00000370 0000B0C0
0057 00000390 0580 move a0, @01850030h, 0 ; DRAW_MARK2 = B0C0
000003A0 01850030
0058 000003C0 0960 rets
0059 .end
No Errors, No Warnings
+34
View File
@@ -0,0 +1,34 @@
*****************************************************
GSP COFF Linker, Version 2.00, 87.300
*****************************************************
Sun Oct 18 02:53:46 2026
OUTPUT FILE NAME: <DRAWAL.out>
ENTRY POINT SYMBOL: 0
SECTION ALLOCATION MAP
output attributes/
section page origin length input sections
-------- ---- ---------- ---------- ----------------
.data 0 00000000 00000000
.bss 0 00000000 00000000 UNINITIALIZED
.text 0 01840000 000003D0
01840000 000003D0 DRAWAL.obj (.text)
GLOBAL SYMBOLS
address name address name
-------- ---- -------- ----
00000000 .bss 00000000 edata
00000000 .data 00000000 .bss
01840000 .text 00000000 end
00000000 edata 00000000 .data
00000000 end 01840000 .text
018403D0 etext 018403D0 etext
[6 symbols]
Binary file not shown.
+85
View File
@@ -0,0 +1,85 @@
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 02:51:11 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 1
0001 ; draw_spin.asm -- CONTROL payload: draw the same three
0002 ;
0003 ; It proves the coordinates and the renderer mapping (t
0004 ; next dumped frame). It deliberately does NOT return,
0005 ; this point. Compare with draw_box.asm, which returns
0006 ; and whose boxes are gone by the next dumped frame: th
0007 ;
0008 ; Linked at bit 01840000h by dwt/visual/build.sh.
0009
0010 00000000 .text
0011 00000000 _start:
0012 00000000 0550 setf 16, 0, 0
0013 00000010 0740 setf 32, 0, 1
0014 00000020 09E0 movi 0FFFFh, a0, L
00000030 0000FFFF
0015
0016 ; box A (50,50)
0017 00000050 09E2 movi 0400C832h, a2, L
00000060 0400C832
0018 00000080 09E3 movi 32, a3, L
00000090 00000020
0019 000000B0 09E4 movi 2, a4, L
000000C0 00000002
0020 000000E0 rowA:
0021 000000E0 4C85 move a4, a5
0022 000000F0 wordA:
0023 000000F0 9002 move a0, *a2+, 0
0024 00000100 3C45 dsjs a5, wordA
0025 00000110 0B02 addi 03E0h, a2
00000120 03E0
0026 00000130 3CC3 dsjs a3, rowA
0027
0028 ; box B (250,400)
0029 00000140 09E2 movi 040640FAh, a2, L
00000150 040640FA
0030 00000170 09E3 movi 32, a3, L
00000180 00000020
0031 000001A0 09E4 movi 2, a4, L
000001B0 00000002
0032 000001D0 rowB:
0033 000001D0 4C85 move a4, a5
0034 000001E0 wordB:
0035 000001E0 9002 move a0, *a2+, 0
0036 000001F0 3C45 dsjs a5, wordB
0037 00000200 0B02 addi 03E0h, a2
00000210 03E0
0038 00000220 3CC3 dsjs a3, rowB
0039
0040 ; box C (930,750)
0041 00000230 09E2 movi 040BBBA2h, a2, L
00000240 040BBBA2
0042 00000260 09E3 movi 32, a3, L
00000270 00000020
0043 00000290 09E4 movi 2, a4, L
000002A0 00000002
0044 000002C0 rowC:
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 02:51:11 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 2
0045 000002C0 4C85 move a4, a5
0046 000002D0 wordC:
0047 000002D0 9002 move a0, *a2+, 0
0048 000002E0 3C45 dsjs a5, wordC
0049 000002F0 0B02 addi 03E0h, a2
00000300 03E0
0050 00000310 3CC3 dsjs a3, rowC
0051
0052 00000320 09E0 movi 05B5Bh, a0, L
00000330 00005B5B
0053 00000350 0580 move a0, @01850020h, 0 ; SPIN_MARK = 5B5B
00000360 01850020
0054 00000380 0360 dint
0055 00000390 spin:
0056 00000390 0300 nop
0057 000003A0 C0FE jruc spin
0058 .end
No Errors, No Warnings
+34
View File
@@ -0,0 +1,34 @@
*****************************************************
GSP COFF Linker, Version 2.00, 87.300
*****************************************************
Sun Oct 18 02:51:11 2026
OUTPUT FILE NAME: <DRAWSPIN.out>
ENTRY POINT SYMBOL: 0
SECTION ALLOCATION MAP
output attributes/
section page origin length input sections
-------- ---- ---------- ---------- ----------------
.data 0 00000000 00000000
.bss 0 00000000 00000000 UNINITIALIZED
.text 0 01840000 000003B0
01840000 000003B0 DRAWSPIN.obj (.text)
GLOBAL SYMBOLS
address name address name
-------- ---- -------- ----
00000000 .bss 00000000 edata
00000000 .data 00000000 .bss
01840000 .text 00000000 end
00000000 edata 00000000 .data
00000000 end 01840000 .text
018403B0 etext 018403B0 etext
[6 symbols]
Binary file not shown.
+30
View File
@@ -0,0 +1,30 @@
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 02:48:35 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 1
0001 ; ret_test.asm -- smallest payload that proves `jump` i
0002 ;
0003 ; It writes two marker words and returns with `rets`.
0004 ; stub really used `call`, control comes back to the di
0005 ; session stays usable; if it used a plain jump, there
0006 ; this would fault or wander.
0007 ;
0008 ; Linked at bit 01840000h (byte 00308000h) by dwt/visua
0009
0010 00000000 .text
0011 00000000 _start:
0012 00000000 0550 setf 16, 0, 0 ; field 0 = 16 bits, zero-extended
0013 00000010 0740 setf 32, 0, 1 ; field 1 = 32 bits, zero-extended
0014 00000020 09E0 movi 0C0DEh, a0, L
00000030 0000C0DE
0015 00000050 0580 move a0, @01850000h, 0 ; MARK1 = C0DE
00000060 01850000
0016 00000080 09E0 movi 0B007h, a0, L
00000090 0000B007
0017 000000B0 0580 move a0, @01850010h, 0 ; MARK2 = B007 (proves the seco
000000C0 01850010
0018 000000E0 0960 rets
0019 .end
No Errors, No Warnings
+34
View File
@@ -0,0 +1,34 @@
*****************************************************
GSP COFF Linker, Version 2.00, 87.300
*****************************************************
Sun Oct 18 02:48:35 2026
OUTPUT FILE NAME: <ret_test.out>
ENTRY POINT SYMBOL: 0
SECTION ALLOCATION MAP
output attributes/
section page origin length input sections
-------- ---- ---------- ---------- ----------------
.data 0 00000000 00000000
.bss 0 00000000 00000000 UNINITIALIZED
.text 0 01840000 000000F0
01840000 000000F0 ret_test.obj (.text)
GLOBAL SYMBOLS
address name address name
-------- ---- -------- ----
00000000 .bss 00000000 edata
00000000 .data 00000000 .bss
01840000 .text 00000000 end
00000000 edata 00000000 .data
00000000 end 01840000 .text
018400F0 etext 018400F0 etext
[6 symbols]
Binary file not shown.
+74
View File
@@ -0,0 +1,74 @@
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 03:03:04 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 1
0001 ; retprobe.asm -- MINIMAL test of the DI return-PC tram
0002 ;
0003 ; Installs `entry` on the DI RAM stub (00000DB0h). `en
0004 ; interrupt frame's saved PC with `ret_hook` and runs t
0005 ; `ret_hook` bumps a marker and returns to the saved PC
0006 ; NOT preserve registers, so TCP liveness tells us whet
0007 ; itself is sound. Scratch is in the payload's own pag
0008 ;
0009 ; Linked at bit 01840000h by dwt/visual/build.sh.
0010
0011 00000000 .text
0012 00000000 _start:
0013 00000000 01E0 pushst
0014 00000010 0360 dint
0015 00000020 0540 setf 32, 0, 0
0016 00000030 09E0 movi entry, a0, L
00000040 00000160'
0017 00000060 0580 move a0, @00000DC0h, 0
00000070 00000DC0
0018 00000090 0550 setf 16, 0, 0
0019 000000A0 09E0 movi 0C080h, a0, L
000000B0 0000C080
0020 000000D0 0580 move a0, @00000DB0h, 0
000000E0 00000DB0
0021 00000100 4400 sub a0, a0
0022 00000110 0580 move a0, @01840800h, 0 ; marker
00000120 01840800
0023 00000140 01C0 popst
0024 00000150 0960 rets
0025
0026 00000160 entry:
0027 00000160 0780 move a0, @01840810h, 1
00000170 01840810
0028 00000190 0740 setf 32, 0, 1
0029 000001A0 B7E0 move *sp(020h), a0, 1
000001B0 0020
0030 000001C0 0780 move a0, @01840804h, 1 ; orig_pc
000001D0 01840804
0031 000001F0 09E0 movi ret_hook, a0, L
00000200 000002A0'
0032 00000220 B20F move a0, *sp(020h), 1
00000230 0020
0033 00000240 07A0 move @01840810h, a0, 1
00000250 01840810
0034 00000270 C080 jauc 3F7146D0h
00000280 3F7146D0
0035
0036 000002A0 ret_hook:
0037 000002A0 05A0 move @01840800h, a0, 0
000002B0 01840800
0038 000002D0 1020 inc a0
0039 000002E0 0580 move a0, @01840800h, 0
000002F0 01840800
0040 00000310 0740 setf 32, 0, 1
0041 00000320 07A0 move @01840804h, a0, 1 ; orig_pc
00000330 01840804
GSP COFF Assembler, Version 2.00, 87.300 Sun Oct 18 03:03:04 2026
(c) Copyright 1985, 1987, Texas Instruments Inc.
PAGE 2
0042 00000350 A20F move a0, -*sp, 1
0043 00000360 0180 getst a0 ; (clobbers a0 on purpose)
0044 00000370 A20F move a0, -*sp, 1
0045 00000380 01C0 popst
0046 00000390 0960 rets
0047 .end
No Errors, No Warnings
+34
View File
@@ -0,0 +1,34 @@
*****************************************************
GSP COFF Linker, Version 2.00, 87.300
*****************************************************
Sun Oct 18 03:03:04 2026
OUTPUT FILE NAME: <RETPROBE.out>
ENTRY POINT SYMBOL: 0
SECTION ALLOCATION MAP
output attributes/
section page origin length input sections
-------- ---- ---------- ---------- ----------------
.data 0 00000000 00000000
.bss 0 00000000 00000000 UNINITIALIZED
.text 0 01840000 000003A0
01840000 000003A0 RETPROBE.obj (.text)
GLOBAL SYMBOLS
address name address name
-------- ---- -------- ----
00000000 .bss 00000000 edata
00000000 .data 00000000 .bss
01840000 .text 00000000 end
00000000 edata 00000000 .data
00000000 end 01840000 .text
018403A0 etext 018403A0 etext
[6 symbols]
+61
View File
@@ -0,0 +1,61 @@
; draw_box.asm -- one-shot static VRAM injection, then return.
;
; Draws three 32x32 solid-white boxes at framebuffer (x,y):
; A (50,50) -- root weave, outside every window
; B (250,400) -- inside the Terminal Manager window body (white area)
; C (930,750) -- root weave, lower right
; Writes marker words and returns with `rets`, so the rdebug session survives.
;
; Framebuffer model (harness/mame/RENDER_REPORT.md): base bit 04000000h,
; 1024 bits per row, bit 0 = leftmost pixel, LSB-first in each 16-bit word.
;
; Linked at bit 01840000h by dwt/visual/build.sh.
.text
_start:
setf 16, 0, 0
setf 32, 0, 1
movi 0FFFFh, a0, L ; pattern
; ---- box A: (50,50), 32 rows x 2 words = 32x32 px -------------
movi 0400C832h, a2, L ; 04000000h + 50*1024 + 50
movi 32, a3, L
movi 2, a4, L
rowA:
move a4, a5
wordA:
move a0, *a2+, 0
dsjs a5, wordA
addi 03E0h, a2 ; 1024 - 32 bits
dsjs a3, rowA
; ---- box B: (250,400) ----------------------------------------
movi 040640FAh, a2, L ; 04000000h + 400*1024 + 250
movi 32, a3, L
movi 2, a4, L
rowB:
move a4, a5
wordB:
move a0, *a2+, 0
dsjs a5, wordB
addi 03E0h, a2
dsjs a3, rowB
; ---- box C: (930,750) ----------------------------------------
movi 040BBBA2h, a2, L ; 04000000h + 750*1024 + 930
movi 32, a3, L
movi 2, a4, L
rowC:
move a4, a5
wordC:
move a0, *a2+, 0
dsjs a5, wordC
addi 03E0h, a2
dsjs a3, rowC
movi 0D2A0h, a0, L
move a0, @01850020h, 0 ; DRAW_MARK = D2A0
movi 0B0C0h, a0, L
move a0, @01850030h, 0 ; DRAW_MARK2 = B0C0
rets
.end
+59
View File
@@ -0,0 +1,59 @@
; drawal.asm -- one-shot static VRAM draw at word-aligned coordinates, return.
;
; Three solid-black 32x32 boxes:
; A (48,48) root weave, outside every window
; B (256,400) inside the Terminal Manager white body
; C (928,752) root weave, lower right
; All x are multiples of 16, which the TMS34010 16-bit field store requires.
; Writes marker words, then `rets` so the rdebug session and the OS survive.
;
; Linked at bit 01840000h by dwt/visual/build.sh.
.text
_start:
setf 16, 0, 0
setf 32, 0, 1
sub a0, a0 ; 0000 = black
; box A (48,48)
movi 0400C030h, a2, L
movi 32, a3, L
movi 2, a4, L
rowA:
move a4, a5
wordA:
move a0, *a2+, 0
dsjs a5, wordA
addi 03E0h, a2
dsjs a3, rowA
; box B (256,400)
movi 04064100h, a2, L
movi 32, a3, L
movi 2, a4, L
rowB:
move a4, a5
wordB:
move a0, *a2+, 0
dsjs a5, wordB
addi 03E0h, a2
dsjs a3, rowB
; box C (928,752)
movi 040BC3A0h, a2, L
movi 32, a3, L
movi 2, a4, L
rowC:
move a4, a5
wordC:
move a0, *a2+, 0
dsjs a5, wordC
addi 03E0h, a2
dsjs a3, rowC
movi 0D2A0h, a0, L
move a0, @01850020h, 0 ; DRAW_MARK = D2A0
movi 0B0C0h, a0, L
move a0, @01850030h, 0 ; DRAW_MARK2 = B0C0
rets
.end
+58
View File
@@ -0,0 +1,58 @@
; draw_spin.asm -- CONTROL payload: draw the same three boxes, then freeze.
;
; It proves the coordinates and the renderer mapping (the boxes appear in the
; next dumped frame). It deliberately does NOT return, so the OS is dead from
; this point. Compare with draw_box.asm, which returns and leaves the OS alive
; and whose boxes are gone by the next dumped frame: the OS repaints.
;
; Linked at bit 01840000h by dwt/visual/build.sh.
.text
_start:
setf 16, 0, 0
setf 32, 0, 1
movi 0FFFFh, a0, L
; box A (50,50)
movi 0400C832h, a2, L
movi 32, a3, L
movi 2, a4, L
rowA:
move a4, a5
wordA:
move a0, *a2+, 0
dsjs a5, wordA
addi 03E0h, a2
dsjs a3, rowA
; box B (250,400)
movi 040640FAh, a2, L
movi 32, a3, L
movi 2, a4, L
rowB:
move a4, a5
wordB:
move a0, *a2+, 0
dsjs a5, wordB
addi 03E0h, a2
dsjs a3, rowB
; box C (930,750)
movi 040BBBA2h, a2, L
movi 32, a3, L
movi 2, a4, L
rowC:
move a4, a5
wordC:
move a0, *a2+, 0
dsjs a5, wordC
addi 03E0h, a2
dsjs a3, rowC
movi 05B5Bh, a0, L
move a0, @01850020h, 0 ; SPIN_MARK = 5B5B
dint
spin:
nop
jruc spin
.end
+25
View File
@@ -0,0 +1,25 @@
-- frame_clock.lua -- read-only frame counter side channel for host-driven tests.
--
-- Writes the current frame number to $FRAME_CLOCK once per frame so a host
-- client can align an injection with a known emulated frame (and therefore with
-- the driver's VT1200_DUMP_FRAMES schedule). No breakpoints, no memory writes
-- except this file. Optionally exits at $FRAME_STOP.
local machine = manager.machine
local path = os.getenv("FRAME_CLOCK")
local stop = tonumber(os.getenv("FRAME_STOP") or "0")
local f = 0
emu.register_frame_done(function()
f = f + 1
if path then
local fh = io.open(path, "w")
if fh then
fh:write(string.format("%d\n", f))
fh:close()
end
end
if stop > 0 and f >= stop then
print(string.format("frame_clock: stopping at frame %d", f))
machine:exit()
end
end, "vt1200-frame-clock")
+130
View File
@@ -0,0 +1,130 @@
#!/usr/bin/env python3
"""Host-side rdebug driver for the visual-injection experiments.
Same challenge bypass as dwt/solve.py (it imports the same client and patches
``answer_challenge`` with dwt/challenge.respond). The difference is that this
tool is built for a *sequence* on one TCP connection and can wait for ``jump``
to return:
python3 dwt/visual/inject.py --poke-file 0x01840000 --file ... \\
--jump 0x01840000 --jump-wait 5 --liveness 7
It prints the jump return value, so it can distinguish `call` semantics from a
one-way jump. It never modifies the firmware or the ROM.
"""
from __future__ import annotations
import argparse
import os
import sys
import time
HERE = os.path.dirname(os.path.abspath(__file__))
DWT = os.path.dirname(HERE)
sys.path.insert(0, DWT)
import challenge # noqa: E402
import exploit # noqa: E402
_orig_answer = exploit.RDebug.answer_challenge
def _answer(self, challenge_bytes: bytes) -> None:
self.challenge_raw = challenge.respond(challenge_bytes)
print(f"[+] challenge {challenge_bytes.hex(' ')}", flush=True)
print(f"[+] reply {self.challenge_raw.hex(' ')}", flush=True)
return _orig_answer(self, challenge_bytes)
exploit.RDebug.answer_challenge = _answer
def main(argv: list[str]) -> int:
ap = argparse.ArgumentParser(description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
ap.add_argument("--host", default="192.168.99.2")
ap.add_argument("--port", type=int, default=771)
ap.add_argument("--timeout", type=float, default=10.0)
ap.add_argument("--poke-file", type=exploit.parse_int)
ap.add_argument("--file")
ap.add_argument("--poke", type=exploit.parse_int)
ap.add_argument("--hex")
ap.add_argument("--peek", type=exploit.parse_int)
ap.add_argument("--len", type=int, default=16)
ap.add_argument("--jump", type=exploit.parse_int)
ap.add_argument("--arg", type=exploit.parse_int, action="append", default=[])
ap.add_argument("--jump-wait", type=float, default=5.0,
help="seconds to wait for jump to return (0 = don't wait)")
ap.add_argument("--settle", type=float, default=1.0,
help="seconds to wait after a non-waiting jump")
ap.add_argument("--liveness", type=int, action="append", default=[],
help="send opcode N after the jump (repeatable)")
ap.add_argument("--liveness-wait", type=float, default=1.0)
ap.add_argument("--after-peek", type=exploit.parse_int)
ap.add_argument("--after-len", type=int, default=16)
ap.add_argument("--sleep", type=float, default=0.0, help="sleep before closing")
a = ap.parse_args(argv[1:])
rd = exploit.RDebug(a.host, a.port, a.timeout, False)
try:
rd.connect()
# Establish the challenge with a liveness opcode, then stay on the
# connection. (opcode 7 is >= 2, so it triggers dwt_prf once.)
flag, payload = rd.liveness(7)
print(f"opcode 7 -> flag={flag:#04x} payload={payload.hex(' ')} "
f"({payload!r})", flush=True)
if a.poke is not None:
data = exploit.parse_hex(a.hex or "")
rd.poke(a.poke, data)
print(f"poke {a.poke:#010x} <- {data.hex(' ')}: ok", flush=True)
if a.poke_file is not None:
data = open(a.file, "rb").read()
off = 0
while off < len(data):
chunk = data[off:off + exploit.MAX_XFER]
rd.poke(a.poke_file + off * 8, chunk)
off += len(chunk)
print(f"poke-file {a.file}: {len(data)} bytes at "
f"{a.poke_file:#010x}: ok", flush=True)
if a.peek is not None:
data = rd.peek(a.peek, a.len)
print(f"peek {a.peek:#010x} ({a.len}) -> {data.hex(' ')}", flush=True)
if a.jump is not None:
if a.jump_wait > 0:
res = rd.jump(a.jump, a.arg, wait=True,
wait_timeout=a.jump_wait)
if res is None:
print(f"jump {a.jump:#010x}: NO RETURN within "
f"{a.jump_wait}s", flush=True)
else:
print(f"jump {a.jump:#010x}: returned {res[0]:#010x} "
f"({res[0]}) payload={res[1].hex(' ')}", flush=True)
else:
rd.jump(a.jump, a.arg, wait=False)
print(f"jump {a.jump:#010x}: sent (no wait)", flush=True)
time.sleep(a.settle)
for op in a.liveness:
try:
flag, payload = rd.liveness(op)
print(f"post-jump opcode {op} -> flag={flag:#04x} "
f"payload={payload.hex(' ')} ({payload!r})", flush=True)
except Exception as exc: # noqa: BLE001 - report, don't hide
print(f"post-jump opcode {op}: FAILED: {exc}", flush=True)
return 3
if a.after_peek is not None:
data = rd.peek(a.after_peek, a.after_len)
print(f"after-peek {a.after_peek:#010x} ({a.after_len}) -> "
f"{data.hex(' ')}", flush=True)
if a.sleep:
time.sleep(a.sleep)
return 0
except (OSError, exploit.ProtocolError, ValueError) as exc:
print(f"error: {exc}", file=sys.stderr)
return 2
finally:
rd.close()
if __name__ == "__main__":
raise SystemExit(main(sys.argv))
+24
View File
@@ -0,0 +1,24 @@
-- probe_end.lua -- frame clock + PC/SP/ST and hook-state sampler.
local machine = manager.machine
local cpu = machine.devices[':maincpu']
local prog = cpu.spaces['program']
local clock = os.getenv("FRAME_CLOCK")
local stop = tonumber(os.getenv("FRAME_STOP") or "0")
local f = 0
local function rw(b) return prog:read_u16(b) end
local function rl(b) return prog:read_u32(b) end
emu.register_frame_done(function()
f = f + 1
if clock then
local fh = io.open(clock, "w")
if fh then fh:write(f .. "\n"); fh:close() end
end
if f >= 3480 and f % 10 == 0 then
print(string.format(
"END f=%d PC=%08X SP=%08X ST=%08X counter=%04X state=%04X orig=%08X box=%04X%04X",
f, cpu.state['PC'].value, cpu.state['SP'].value, cpu.state['ST'].value,
rw(0x01840E00), rw(0x01840E10), rl(0x01840E20),
rw(0x04064100), rw(0x04064110)))
end
if stop > 0 and f >= stop then machine:exit() end
end, "vt1200-probe-end")
+40
View File
@@ -0,0 +1,40 @@
-- probe_hook.lua -- investigation only: log the DI hook stages of blinkpc.
-- Sets breakpoints at entry / ret_hook / the stock OS handler after the hook is
-- installed, prints PC/SP/ST, and resumes. Never writes memory.
local machine = manager.machine
local cpu = machine.devices[':maincpu']
local dbg = machine.debugger
if not dbg then print("ERROR: no debugger"); machine:exit(); return end
local ARM = tonumber(os.getenv("HOOK_ARM") or "3450")
local STOP = tonumber(os.getenv("HOOK_STOP") or "3520")
local f = 0
local armed = false
local clock = os.getenv("FRAME_CLOCK")
local function bp(addr, tag)
dbg:command(string.format(
'bpset %s,,{ printf "HOOK %s pc=%%08X sp=%%08X st=%%08X a0=%%08X\\n", pc, sp, st, a0 ; g }',
addr, tag))
end
emu.register_frame_done(function()
f = f + 1
if clock then
local fh = io.open(clock, "w")
if fh then fh:write(f .. "\n"); fh:close() end
end
if f == ARM and not armed then
armed = true
bp("1840190", "ENTRY")
bp("18402d0", "RET")
bp("3f7146d0", "OSH")
print(string.format("probe_hook: armed at frame %d", f))
end
if f >= STOP then
print("probe_hook: stopping")
machine:exit()
end
end, "vt1200-probe-hook")
dbg.visible_cpu = cpu
dbg.execution_state = 'run'
+58
View File
@@ -0,0 +1,58 @@
-- probe_irq.lua -- which periodic interrupt can a payload hook?
--
-- Boot the OS (VT1200_SKIP_LEVEL1=1), then count entries to the handlers that
-- the firmware's RAM trampolines point at. The trampolines are the 6-byte
-- `JA target` stubs at the low-RAM vector page (see dwt/notes/VISUAL_INJECTION.md).
--
-- Investigation only: this script uses breakpoints to count. The resident-hook
-- acceptance run does not.
--
-- VT1200_SKIP_LEVEL1=1 <mame> vt1200 ... -autoboot_script dwt/visual/probe_irq.lua
local machine = manager.machine
local cpu = machine.devices[':maincpu']
local dbg = machine.debugger
local prog = cpu.spaces['program']
if not dbg then print("ERROR: no debugger"); machine:exit(); return end
local START = tonumber(os.getenv("IRQ_START") or "3200")
local STOP = tonumber(os.getenv("IRQ_STOP") or "3500")
local EVERY = tonumber(os.getenv("IRQ_EVERY") or "50")
local hits = { di = 0, int1 = 0, int2 = 0 }
local function bp(addr, key)
dbg:command(string.format(
'bpset %s,,{ %s = %s + 1 ; g }', addr, key, key))
end
bp("3f7146d0", "hits.di")
bp("3f7144c0", "hits.int1")
bp("3f714530", "hits.int2")
local rd = function(a) return prog:read_u16(a) end
local f = 0
local armed = false
local last = { di = 0, int1 = 0, int2 = 0 }
emu.register_frame_done(function()
f = f + 1
if f == START then
armed = true
print(string.format("probe_irq: armed at frame %d (DI handler 3F7146D0, INT1 3F7144C0, INT2 3F714530)", f))
end
if armed and (f % EVERY == 0) then
print(string.format(
"f%4d DI=%d(+%d) INT1=%d(+%d) INT2=%d(+%d) DPYCTL=%04X DPYINT=%04X INTENB=%04X INTPEND=%04X VCOUNT=%04X",
f, hits.di, hits.di - last.di, hits.int1, hits.int1 - last.int1,
hits.int2, hits.int2 - last.int2,
rd(0xc0000080), rd(0xc00000a0), rd(0xc0000110), rd(0xc0000120), rd(0xc00001d0)))
last.di, last.int1, last.int2 = hits.di, hits.int1, hits.int2
end
if f >= STOP then
print(string.format("probe_irq: totals DI=%d INT1=%d INT2=%d over %d frames",
hits.di, hits.int1, hits.int2, STOP - START))
machine:exit()
end
end, "vt1200-probe-irq")
dbg.visible_cpu = cpu
dbg.execution_state = 'run'
+41
View File
@@ -0,0 +1,41 @@
-- probe_irq2.lua -- count periodic interrupt handler entries with printf bpsets.
-- Same investigation as probe_irq.lua, but the breakpoint action is a debugger
-- command string (the Lua bpset API takes debugger commands, not Lua closures).
local machine = manager.machine
local cpu = machine.devices[':maincpu']
local dbg = machine.debugger
local prog = cpu.spaces['program']
if not dbg then print("ERROR: no debugger"); machine:exit(); return end
local START = tonumber(os.getenv("IRQ_START") or "3200")
local STOP = tonumber(os.getenv("IRQ_STOP") or "3400")
local function bp(addr, tag)
dbg:command(string.format(
'bpset %s,,{ printf "IRQHIT %s pc=%%08X\\n", pc ; g }', addr, tag))
end
bp("3f7146d0", "DI")
bp("3f7144c0", "INT1")
bp("3f714530", "INT2")
-- The trampolines themselves, to tell "never entered" from "wrong handler".
bp("0db0", "TRAMP-DI")
bp("0f60", "TRAMP-INT1")
bp("0f30", "TRAMP-INT2")
local rd = function(a) return prog:read_u16(a) end
local f = 0
emu.register_frame_done(function()
f = f + 1
if f == START then print("probe_irq2: armed") end
if f % 25 == 0 and f >= START then
print(string.format("f%4d DPYCTL=%04X DPYINT=%04X INTENB=%04X INTPEND=%04X VCOUNT=%04X",
f, rd(0xc0000080), rd(0xc00000a0), rd(0xc0000110), rd(0xc0000120), rd(0xc00001d0)))
end
if f >= STOP then
print("probe_irq2: stopping")
machine:exit()
end
end, "vt1200-probe-irq2")
dbg.visible_cpu = cpu
dbg.execution_state = 'run'
+46
View File
@@ -0,0 +1,46 @@
-- probe_pc.lua -- sample PC/ST (IE flag) in the idle OS, and check that a
-- bpset on a sampled address actually fires. Investigation only.
local machine = manager.machine
local cpu = machine.devices[':maincpu']
local dbg = machine.debugger
local prog = cpu.spaces['program']
if not dbg then print("ERROR: no debugger"); machine:exit(); return end
local IE = 0x200000
local START = tonumber(os.getenv("PC_START") or "3200")
local STOP = tonumber(os.getenv("PC_STOP") or "3300")
local f = 0
local armed = false
local hist = {}
local first = {}
local rd = function(a) return prog:read_u16(a) end
emu.register_frame_done(function()
f = f + 1
local pc = cpu.state['PC'].value
local st = cpu.state['ST'].value
hist[pc] = (hist[pc] or 0) + 1
if not first[pc] then first[pc] = f end
if f >= START and f <= STOP and f % 10 == 0 then
print(string.format("f%4d PC=%08X ST=%08X IE=%d DPYINT=%04X INTENB=%04X INTPEND=%04X",
f, pc, st, (st & IE) ~= 0 and 1 or 0, rd(0xc00000a0), rd(0xc0000110), rd(0xc0000120)))
end
if f == START and not armed then
armed = true
dbg:command(string.format('bpset %08X,,{ printf "PCHIT pc=%%08X\\n", pc ; g }', pc))
dbg:command('bpset 3F579870,,{ printf "PCHIT2 pc=%08X\\n", pc ; g }')
print(string.format("probe_pc: bpset on sampled idle PC %08X", pc))
end
if f >= STOP then
print("--- hottest PCs in window ---")
local list = {}
for k, c in pairs(hist) do list[#list + 1] = {k, c} end
table.sort(list, function(a, b) return a[2] > b[2] end)
for i = 1, math.min(10, #list) do
print(string.format(" PC=%08X samples=%d first=%d", list[i][1], list[i][2], first[list[i][1]]))
end
machine:exit()
end
end, "vt1200-probe-pc")
dbg.visible_cpu = cpu
dbg.execution_state = 'run'
+19
View File
@@ -0,0 +1,19 @@
; ret_test.asm -- smallest payload that proves `jump` is a real call.
;
; It writes two marker words and returns with `rets`. If the rdebug `jump`
; stub really used `call`, control comes back to the dispatcher and the TCP
; session stays usable; if it used a plain jump, there is no return address and
; this would fault or wander.
;
; Linked at bit 01840000h (byte 00308000h) by dwt/visual/build.sh.
.text
_start:
setf 16, 0, 0 ; field 0 = 16 bits, zero-extended
setf 32, 0, 1 ; field 1 = 32 bits, zero-extended
movi 0C0DEh, a0, L
move a0, @01850000h, 0 ; MARK1 = C0DE
movi 0B007h, a0, L
move a0, @01850010h, 0 ; MARK2 = B007 (proves the second store ran)
rets
.end
+47
View File
@@ -0,0 +1,47 @@
; retprobe.asm -- MINIMAL test of the DI return-PC trampoline, no drawing.
;
; Installs `entry` on the DI RAM stub (00000DB0h). `entry` replaces the
; interrupt frame's saved PC with `ret_hook` and runs the stock handler.
; `ret_hook` bumps a marker and returns to the saved PC. It deliberately does
; NOT preserve registers, so TCP liveness tells us whether the frame/PC dance
; itself is sound. Scratch is in the payload's own page (01840800h).
;
; Linked at bit 01840000h by dwt/visual/build.sh.
.text
_start:
pushst
dint
setf 32, 0, 0
movi entry, a0, L
move a0, @00000DC0h, 0
setf 16, 0, 0
movi 0C080h, a0, L
move a0, @00000DB0h, 0
sub a0, a0
move a0, @01840800h, 0 ; marker
popst
rets
entry:
move a0, @01840810h, 1
setf 32, 0, 1
move *sp(020h), a0, 1
move a0, @01840804h, 1 ; orig_pc
movi ret_hook, a0, L
move a0, *sp(020h), 1
move @01840810h, a0, 1
jauc 3F7146D0h
ret_hook:
move @01840800h, a0, 0
inc a0
move a0, @01840800h, 0
setf 32, 0, 1
move @01840804h, a0, 1 ; orig_pc
move a0, -*sp, 1
getst a0 ; (clobbers a0 on purpose)
move a0, -*sp, 1
popst
rets
.end