diff --git a/dwt/evidence/visual/blink2_off_3450.png b/dwt/evidence/visual/blink2_off_3450.png new file mode 100644 index 0000000..04aab1c Binary files /dev/null and b/dwt/evidence/visual/blink2_off_3450.png differ diff --git a/dwt/evidence/visual/blink2_on_3460.png b/dwt/evidence/visual/blink2_on_3460.png new file mode 100644 index 0000000..f9136e5 Binary files /dev/null and b/dwt/evidence/visual/blink2_on_3460.png differ diff --git a/dwt/evidence/visual/blink2_on_3500.png b/dwt/evidence/visual/blink2_on_3500.png new file mode 100644 index 0000000..f9136e5 Binary files /dev/null and b/dwt/evidence/visual/blink2_on_3500.png differ diff --git a/dwt/evidence/visual/blink_mame.log b/dwt/evidence/visual/blink_mame.log new file mode 100644 index 0000000..340965f --- /dev/null +++ b/dwt/evidence/visual/blink_mame.log @@ -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) diff --git a/dwt/evidence/visual/blink_off_3480.png b/dwt/evidence/visual/blink_off_3480.png new file mode 100644 index 0000000..004015a Binary files /dev/null and b/dwt/evidence/visual/blink_off_3480.png differ diff --git a/dwt/evidence/visual/blink_off_3480_crop.png b/dwt/evidence/visual/blink_off_3480_crop.png new file mode 100644 index 0000000..a2b4aa7 Binary files /dev/null and b/dwt/evidence/visual/blink_off_3480_crop.png differ diff --git a/dwt/evidence/visual/blink_on_3450.png b/dwt/evidence/visual/blink_on_3450.png new file mode 100644 index 0000000..bef0c75 Binary files /dev/null and b/dwt/evidence/visual/blink_on_3450.png differ diff --git a/dwt/evidence/visual/blink_on_3450_crop.png b/dwt/evidence/visual/blink_on_3450_crop.png new file mode 100644 index 0000000..8ce252f Binary files /dev/null and b/dwt/evidence/visual/blink_on_3450_crop.png differ diff --git a/dwt/evidence/visual/blink_on_3500.png b/dwt/evidence/visual/blink_on_3500.png new file mode 100644 index 0000000..e1fea01 Binary files /dev/null and b/dwt/evidence/visual/blink_on_3500.png differ diff --git a/dwt/evidence/visual/blink_repeat_client.log b/dwt/evidence/visual/blink_repeat_client.log new file mode 100644 index 0000000..2088f77 --- /dev/null +++ b/dwt/evidence/visual/blink_repeat_client.log @@ -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 diff --git a/dwt/evidence/visual/blink_repeat_mame.log b/dwt/evidence/visual/blink_repeat_mame.log new file mode 100644 index 0000000..6f7a573 --- /dev/null +++ b/dwt/evidence/visual/blink_repeat_mame.log @@ -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) diff --git a/dwt/evidence/visual/blink_resident_client.log b/dwt/evidence/visual/blink_resident_client.log new file mode 100644 index 0000000..437d5e5 --- /dev/null +++ b/dwt/evidence/visual/blink_resident_client.log @@ -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 diff --git a/dwt/evidence/visual/control_hello_3480.png b/dwt/evidence/visual/control_hello_3480.png new file mode 100644 index 0000000..60d8883 Binary files /dev/null and b/dwt/evidence/visual/control_hello_3480.png differ diff --git a/dwt/evidence/visual/control_spin_box_3480.png b/dwt/evidence/visual/control_spin_box_3480.png new file mode 100644 index 0000000..1ab4f31 Binary files /dev/null and b/dwt/evidence/visual/control_spin_box_3480.png differ diff --git a/dwt/evidence/visual/control_spin_client.log b/dwt/evidence/visual/control_spin_client.log new file mode 100644 index 0000000..4a48700 --- /dev/null +++ b/dwt/evidence/visual/control_spin_client.log @@ -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 diff --git a/dwt/evidence/visual/di_one_shot_state.log b/dwt/evidence/visual/di_one_shot_state.log new file mode 100644 index 0000000..74ac72b --- /dev/null +++ b/dwt/evidence/visual/di_one_shot_state.log @@ -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) diff --git a/dwt/evidence/visual/hook_breakpoints.log b/dwt/evidence/visual/hook_breakpoints.log new file mode 100644 index 0000000..338fd50 --- /dev/null +++ b/dwt/evidence/visual/hook_breakpoints.log @@ -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 + diff --git a/dwt/evidence/visual/posthandler_persist_3600.png b/dwt/evidence/visual/posthandler_persist_3600.png new file mode 100644 index 0000000..e1fea01 Binary files /dev/null and b/dwt/evidence/visual/posthandler_persist_3600.png differ diff --git a/dwt/evidence/visual/settled_hook_client.log b/dwt/evidence/visual/settled_hook_client.log new file mode 100644 index 0000000..45cad7f --- /dev/null +++ b/dwt/evidence/visual/settled_hook_client.log @@ -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 diff --git a/dwt/evidence/visual/settled_hook_mame.log b/dwt/evidence/visual/settled_hook_mame.log new file mode 100644 index 0000000..f7b892f --- /dev/null +++ b/dwt/evidence/visual/settled_hook_mame.log @@ -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) diff --git a/dwt/evidence/visual/static_after_3430.png b/dwt/evidence/visual/static_after_3430.png new file mode 100644 index 0000000..7d84a5b Binary files /dev/null and b/dwt/evidence/visual/static_after_3430.png differ diff --git a/dwt/evidence/visual/static_before_3420.png b/dwt/evidence/visual/static_before_3420.png new file mode 100644 index 0000000..7d84a5b Binary files /dev/null and b/dwt/evidence/visual/static_before_3420.png differ diff --git a/dwt/evidence/visual/static_draw_client.log b/dwt/evidence/visual/static_draw_client.log new file mode 100644 index 0000000..2d9bb85 --- /dev/null +++ b/dwt/evidence/visual/static_draw_client.log @@ -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 diff --git a/dwt/evidence/visual/step1_alive_3500.png b/dwt/evidence/visual/step1_alive_3500.png new file mode 100644 index 0000000..4c4989c Binary files /dev/null and b/dwt/evidence/visual/step1_alive_3500.png differ diff --git a/dwt/evidence/visual/step1_ret_test.log b/dwt/evidence/visual/step1_ret_test.log new file mode 100644 index 0000000..f658bf8 --- /dev/null +++ b/dwt/evidence/visual/step1_ret_test.log @@ -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 diff --git a/dwt/evidence/visual/step3_blink_client.log b/dwt/evidence/visual/step3_blink_client.log new file mode 100644 index 0000000..2088f77 --- /dev/null +++ b/dwt/evidence/visual/step3_blink_client.log @@ -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 diff --git a/dwt/evidence/visual/summary.txt b/dwt/evidence/visual/summary.txt new file mode 100644 index 0000000..742e3cf --- /dev/null +++ b/dwt/evidence/visual/summary.txt @@ -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 diff --git a/dwt/evidence/visual/xcheck.log b/dwt/evidence/visual/xcheck.log new file mode 100644 index 0000000..3bcde43 --- /dev/null +++ b/dwt/evidence/visual/xcheck.log @@ -0,0 +1,4 @@ +771: OPEN (0.00s) +6000: OPEN (0.01s) +6001: closed/failed: [Errno 111] Connection refused +frame 1068 diff --git a/dwt/evidence/visual/xcheck_mame.log b/dwt/evidence/visual/xcheck_mame.log new file mode 100644 index 0000000..2cdb3e9 --- /dev/null +++ b/dwt/evidence/visual/xcheck_mame.log @@ -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) diff --git a/dwt/notes/CROSS.md b/dwt/notes/CROSS.md index f010bfb..65ea844 100644 --- a/dwt/notes/CROSS.md +++ b/dwt/notes/CROSS.md @@ -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. + diff --git a/dwt/notes/VISUAL_INJECTION.md b/dwt/notes/VISUAL_INJECTION.md new file mode 100644 index 0000000..b097541 --- /dev/null +++ b/dwt/notes/VISUAL_INJECTION.md @@ -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` | diff --git a/dwt/visual/blink.asm b/dwt/visual/blink.asm new file mode 100644 index 0000000..fe2ab82 --- /dev/null +++ b/dwt/visual/blink.asm @@ -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 diff --git a/dwt/visual/blink2.asm b/dwt/visual/blink2.asm new file mode 100644 index 0000000..9174c21 --- /dev/null +++ b/dwt/visual/blink2.asm @@ -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 diff --git a/dwt/visual/blinkdi.asm b/dwt/visual/blinkdi.asm new file mode 100644 index 0000000..a951b88 --- /dev/null +++ b/dwt/visual/blinkdi.asm @@ -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 ` 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 diff --git a/dwt/visual/blinkev.asm b/dwt/visual/blinkev.asm new file mode 100644 index 0000000..27a09da --- /dev/null +++ b/dwt/visual/blinkev.asm @@ -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 diff --git a/dwt/visual/blinkpc.asm b/dwt/visual/blinkpc.asm new file mode 100644 index 0000000..b801f38 --- /dev/null +++ b/dwt/visual/blinkpc.asm @@ -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 diff --git a/dwt/visual/boxalign.asm b/dwt/visual/boxalign.asm new file mode 100644 index 0000000..971ea45 --- /dev/null +++ b/dwt/visual/boxalign.asm @@ -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 diff --git a/dwt/visual/build.sh b/dwt/visual/build.sh new file mode 100755 index 0000000..8299f99 --- /dev/null +++ b/dwt/visual/build.sh @@ -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/.bin (linked bytes) and .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 .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" diff --git a/dwt/visual/build/blink.bin b/dwt/visual/build/blink.bin new file mode 100644 index 0000000..d483bb2 Binary files /dev/null and b/dwt/visual/build/blink.bin differ diff --git a/dwt/visual/build/blink.lst b/dwt/visual/build/blink.lst new file mode 100644 index 0000000..8436279 --- /dev/null +++ b/dwt/visual/build/blink.lst @@ -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 diff --git a/dwt/visual/build/blink.map b/dwt/visual/build/blink.map new file mode 100644 index 0000000..68d859f --- /dev/null +++ b/dwt/visual/build/blink.map @@ -0,0 +1,34 @@ +***************************************************** +GSP COFF Linker, Version 2.00, 87.300 +***************************************************** +Sun Oct 18 02:56:54 2026 + +OUTPUT FILE NAME: +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] diff --git a/dwt/visual/build/blink2.bin b/dwt/visual/build/blink2.bin new file mode 100644 index 0000000..03f817e Binary files /dev/null and b/dwt/visual/build/blink2.bin differ diff --git a/dwt/visual/build/blink2.lst b/dwt/visual/build/blink2.lst new file mode 100644 index 0000000..76d4dba --- /dev/null +++ b/dwt/visual/build/blink2.lst @@ -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 diff --git a/dwt/visual/build/blink2.map b/dwt/visual/build/blink2.map new file mode 100644 index 0000000..6fbf789 --- /dev/null +++ b/dwt/visual/build/blink2.map @@ -0,0 +1,34 @@ +***************************************************** +GSP COFF Linker, Version 2.00, 87.300 +***************************************************** +Sun Oct 18 03:16:09 2026 + +OUTPUT FILE NAME: +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] diff --git a/dwt/visual/build/blinkev.bin b/dwt/visual/build/blinkev.bin new file mode 100644 index 0000000..bcae040 Binary files /dev/null and b/dwt/visual/build/blinkev.bin differ diff --git a/dwt/visual/build/blinkev.lst b/dwt/visual/build/blinkev.lst new file mode 100644 index 0000000..649d0f0 --- /dev/null +++ b/dwt/visual/build/blinkev.lst @@ -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 diff --git a/dwt/visual/build/blinkev.map b/dwt/visual/build/blinkev.map new file mode 100644 index 0000000..ce58c5f --- /dev/null +++ b/dwt/visual/build/blinkev.map @@ -0,0 +1,34 @@ +***************************************************** +GSP COFF Linker, Version 2.00, 87.300 +***************************************************** +Sun Oct 18 03:19:02 2026 + +OUTPUT FILE NAME: +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] diff --git a/dwt/visual/build/blinkpc.bin b/dwt/visual/build/blinkpc.bin new file mode 100644 index 0000000..6323e96 Binary files /dev/null and b/dwt/visual/build/blinkpc.bin differ diff --git a/dwt/visual/build/blinkpc.lst b/dwt/visual/build/blinkpc.lst new file mode 100644 index 0000000..a564d4f --- /dev/null +++ b/dwt/visual/build/blinkpc.lst @@ -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 diff --git a/dwt/visual/build/blinkpc.map b/dwt/visual/build/blinkpc.map new file mode 100644 index 0000000..219ec6c --- /dev/null +++ b/dwt/visual/build/blinkpc.map @@ -0,0 +1,34 @@ +***************************************************** +GSP COFF Linker, Version 2.00, 87.300 +***************************************************** +Sun Oct 18 03:15:05 2026 + +OUTPUT FILE NAME: +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] diff --git a/dwt/visual/build/boxalign.bin b/dwt/visual/build/boxalign.bin new file mode 100644 index 0000000..8daf535 Binary files /dev/null and b/dwt/visual/build/boxalign.bin differ diff --git a/dwt/visual/build/boxalign.lst b/dwt/visual/build/boxalign.lst new file mode 100644 index 0000000..cd2ff1d --- /dev/null +++ b/dwt/visual/build/boxalign.lst @@ -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 diff --git a/dwt/visual/build/boxalign.map b/dwt/visual/build/boxalign.map new file mode 100644 index 0000000..507efb6 --- /dev/null +++ b/dwt/visual/build/boxalign.map @@ -0,0 +1,34 @@ +***************************************************** +GSP COFF Linker, Version 2.00, 87.300 +***************************************************** +Sun Oct 18 02:53:14 2026 + +OUTPUT FILE NAME: +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] diff --git a/dwt/visual/build/draw_box.bin b/dwt/visual/build/draw_box.bin new file mode 100644 index 0000000..2d5317a Binary files /dev/null and b/dwt/visual/build/draw_box.bin differ diff --git a/dwt/visual/build/draw_box.lst b/dwt/visual/build/draw_box.lst new file mode 100644 index 0000000..76f60b2 --- /dev/null +++ b/dwt/visual/build/draw_box.lst @@ -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 diff --git a/dwt/visual/build/draw_box.map b/dwt/visual/build/draw_box.map new file mode 100644 index 0000000..3fe62dd --- /dev/null +++ b/dwt/visual/build/draw_box.map @@ -0,0 +1,34 @@ +***************************************************** +GSP COFF Linker, Version 2.00, 87.300 +***************************************************** +Sun Oct 18 02:49:28 2026 + +OUTPUT FILE NAME: +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] diff --git a/dwt/visual/build/drawal.bin b/dwt/visual/build/drawal.bin new file mode 100644 index 0000000..6c47015 Binary files /dev/null and b/dwt/visual/build/drawal.bin differ diff --git a/dwt/visual/build/drawal.lst b/dwt/visual/build/drawal.lst new file mode 100644 index 0000000..a9f22fa --- /dev/null +++ b/dwt/visual/build/drawal.lst @@ -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 diff --git a/dwt/visual/build/drawal.map b/dwt/visual/build/drawal.map new file mode 100644 index 0000000..6d78fea --- /dev/null +++ b/dwt/visual/build/drawal.map @@ -0,0 +1,34 @@ +***************************************************** +GSP COFF Linker, Version 2.00, 87.300 +***************************************************** +Sun Oct 18 02:53:46 2026 + +OUTPUT FILE NAME: +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] diff --git a/dwt/visual/build/drawspin.bin b/dwt/visual/build/drawspin.bin new file mode 100644 index 0000000..c08cf07 Binary files /dev/null and b/dwt/visual/build/drawspin.bin differ diff --git a/dwt/visual/build/drawspin.lst b/dwt/visual/build/drawspin.lst new file mode 100644 index 0000000..a4ab17b --- /dev/null +++ b/dwt/visual/build/drawspin.lst @@ -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 diff --git a/dwt/visual/build/drawspin.map b/dwt/visual/build/drawspin.map new file mode 100644 index 0000000..b2cb455 --- /dev/null +++ b/dwt/visual/build/drawspin.map @@ -0,0 +1,34 @@ +***************************************************** +GSP COFF Linker, Version 2.00, 87.300 +***************************************************** +Sun Oct 18 02:51:11 2026 + +OUTPUT FILE NAME: +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] diff --git a/dwt/visual/build/ret_test.bin b/dwt/visual/build/ret_test.bin new file mode 100644 index 0000000..b446ad1 Binary files /dev/null and b/dwt/visual/build/ret_test.bin differ diff --git a/dwt/visual/build/ret_test.lst b/dwt/visual/build/ret_test.lst new file mode 100644 index 0000000..0ce6e8d --- /dev/null +++ b/dwt/visual/build/ret_test.lst @@ -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 diff --git a/dwt/visual/build/ret_test.map b/dwt/visual/build/ret_test.map new file mode 100644 index 0000000..b479a1c --- /dev/null +++ b/dwt/visual/build/ret_test.map @@ -0,0 +1,34 @@ +***************************************************** +GSP COFF Linker, Version 2.00, 87.300 +***************************************************** +Sun Oct 18 02:48:35 2026 + +OUTPUT FILE NAME: +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] diff --git a/dwt/visual/build/retprobe.bin b/dwt/visual/build/retprobe.bin new file mode 100644 index 0000000..d9f6cef Binary files /dev/null and b/dwt/visual/build/retprobe.bin differ diff --git a/dwt/visual/build/retprobe.lst b/dwt/visual/build/retprobe.lst new file mode 100644 index 0000000..321b755 --- /dev/null +++ b/dwt/visual/build/retprobe.lst @@ -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 diff --git a/dwt/visual/build/retprobe.map b/dwt/visual/build/retprobe.map new file mode 100644 index 0000000..7af8608 --- /dev/null +++ b/dwt/visual/build/retprobe.map @@ -0,0 +1,34 @@ +***************************************************** +GSP COFF Linker, Version 2.00, 87.300 +***************************************************** +Sun Oct 18 03:03:04 2026 + +OUTPUT FILE NAME: +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] diff --git a/dwt/visual/draw_box.asm b/dwt/visual/draw_box.asm new file mode 100644 index 0000000..78df5f0 --- /dev/null +++ b/dwt/visual/draw_box.asm @@ -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 diff --git a/dwt/visual/drawal.asm b/dwt/visual/drawal.asm new file mode 100644 index 0000000..7b11153 --- /dev/null +++ b/dwt/visual/drawal.asm @@ -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 diff --git a/dwt/visual/drawspin.asm b/dwt/visual/drawspin.asm new file mode 100644 index 0000000..8650258 --- /dev/null +++ b/dwt/visual/drawspin.asm @@ -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 diff --git a/dwt/visual/frame_clock.lua b/dwt/visual/frame_clock.lua new file mode 100644 index 0000000..a049f55 --- /dev/null +++ b/dwt/visual/frame_clock.lua @@ -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") diff --git a/dwt/visual/inject.py b/dwt/visual/inject.py new file mode 100644 index 0000000..114a39e --- /dev/null +++ b/dwt/visual/inject.py @@ -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)) diff --git a/dwt/visual/probe_end.lua b/dwt/visual/probe_end.lua new file mode 100644 index 0000000..d9101f1 --- /dev/null +++ b/dwt/visual/probe_end.lua @@ -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") diff --git a/dwt/visual/probe_hook.lua b/dwt/visual/probe_hook.lua new file mode 100644 index 0000000..882646c --- /dev/null +++ b/dwt/visual/probe_hook.lua @@ -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' diff --git a/dwt/visual/probe_irq.lua b/dwt/visual/probe_irq.lua new file mode 100644 index 0000000..237c9de --- /dev/null +++ b/dwt/visual/probe_irq.lua @@ -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 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' diff --git a/dwt/visual/probe_irq2.lua b/dwt/visual/probe_irq2.lua new file mode 100644 index 0000000..9240aae --- /dev/null +++ b/dwt/visual/probe_irq2.lua @@ -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' diff --git a/dwt/visual/probe_pc.lua b/dwt/visual/probe_pc.lua new file mode 100644 index 0000000..9cca09e --- /dev/null +++ b/dwt/visual/probe_pc.lua @@ -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' diff --git a/dwt/visual/ret_test.asm b/dwt/visual/ret_test.asm new file mode 100644 index 0000000..1daed53 --- /dev/null +++ b/dwt/visual/ret_test.asm @@ -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 diff --git a/dwt/visual/retprobe.asm b/dwt/visual/retprobe.asm new file mode 100644 index 0000000..949c142 --- /dev/null +++ b/dwt/visual/retprobe.asm @@ -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