forked from opencode.energia.arti.ee/vt1200
fix(termtris): review pass -- seed, focus/pause, expose, test assertions
- seed the game from the raw 0x1E93C0 counter (now_ms() returns 0 on its
first call, so the old seed was always zero)
- track pause ourselves: FocusOut pauses once, FocusIn resumes only what we
paused (game_input('p') is a toggle)
- select ExposureMask so the Expose redraw path actually fires
- play.sh/play_keys.sh rebuild the COFF (OUTNAME=termtris) and assert the
run: status=0, tick>0, loops/events/quit per mode; render.sh asserts the
renderer finished; map symbol lookup is column-order independent
- run.sh passes -lightgun -lightgun_device mouse so the pointer drives the
tablet
- docs: link map addresses, monochrome/reverse wording, honest caption and
limits text
Verified here: play.sh and input.sh pass. Still open: the MAME driver in the
tree is newer than the installed binary (Oct 30 build, VR150-era geometry),
so the acceptance suite must be re-run after a rebuild.
This commit is contained in:
1 parent
eb896f7b8c
commit
7a2cef56ad
19 files changed
+183
-134
No files matched your search
@@ -73,7 +73,6 @@ tools/tms34010-sdk/1991-07 TIGA Promo Kit and Art Software/
|
||||
# termtris build scratch (TI tools + 2ine libs)
|
||||
apps/termtris/work/
|
||||
apps/termtris/build/*.log
|
||||
apps/termtris/build/*.log
|
||||
apps/termtris/build/smoke.*
|
||||
apps/termtris/build/fmt.*
|
||||
apps/termtris/build/render.*
|
||||
|
||||
+10
-7
@@ -40,7 +40,7 @@ Link map (relevant addresses are **bit** addresses, like everything the
|
||||
TMS34010 sees):
|
||||
|
||||
```
|
||||
.text 018A0000 .data 018A0000 .cinit 018B4730
|
||||
.text 018A0000 .data 018A0000 .cinit 018B4B10
|
||||
.bss 01A00000
|
||||
ENTRY POINT SYMBOL: "_start" address: 018a0000
|
||||
```
|
||||
@@ -63,8 +63,9 @@ untouched. With that in place the smoke test receives a real
|
||||
|
||||
The frame is an 80×24 grid of 6×13 cells (the default GC font, baseline +10),
|
||||
so the window is 480×312. The VT1200 raster is **one bit deep**, so the backend
|
||||
follows the game's own monochrome convention (`ansi.c -m`): colour is dropped
|
||||
and the bold bit (`0x80`) reverses a cell. The playfield is therefore black
|
||||
renders like the game's monochrome mode (colour is dropped) and uses the bold
|
||||
bit (`0x80`) as reverse video for emphasis — a choice of this backend, not the
|
||||
upstream ANSI convention (which emits SGR bold and leaves the colours alone). The playfield is therefore black
|
||||
spaces and the tetrominoes are the `[`/`]` tiles, exactly what a 1-bit terminal
|
||||
can show.
|
||||
|
||||
@@ -123,8 +124,9 @@ panels DIAG: loops=323 events=12 focus=00400001 quit=0
|
||||
quit DIAG: loops=277 events=10 focus=00400001 quit=1
|
||||
```
|
||||
|
||||
`focus=00400001` is the termtris window, so the key events really were
|
||||
delivered to it, and `quit=1` is the game's own global after `q`.
|
||||
`focus=00400001` is the window this process created (it is the only one in the
|
||||
run), so the key events were delivered to it, and `quit=1` is the game's own
|
||||
global after `q`.
|
||||
|
||||
## Limits, stated plainly
|
||||
|
||||
@@ -136,8 +138,9 @@ delivered to it, and `quit=1` is the game's own global after `q`.
|
||||
display server is still settling, `main()` retries up to 40 times with a
|
||||
50 ms sleep before giving up. Observed as an intermittent early exit.
|
||||
* **`q` ends the game loop but the window stays on screen.** `quit=1` is
|
||||
observable in RAM; the created process does not tear down its X connection,
|
||||
so the server keeps the window.
|
||||
observable in RAM and `main()` returns; the frame captured about a second
|
||||
later still shows the window, so the X connection is not torn down by process
|
||||
exit in this OS. Treat that as an observation, not a designed behaviour.
|
||||
* **The board is text.** Tetrominoes are `[`/`]` tiles, not filled blocks — the
|
||||
only thing a 1-bit cell can show without a custom font.
|
||||
|
||||
|
||||
@@ -103,11 +103,6 @@ compile_asm() {
|
||||
run "$base.obj" ./gspa.exe "$base.ASM"
|
||||
}
|
||||
|
||||
for base in $OBJS; do
|
||||
case " $* " in
|
||||
*" $base "*) ;; # handled below by extension scan
|
||||
esac
|
||||
done
|
||||
|
||||
# Compile every collected object exactly once, in the order given.
|
||||
for arg in "$@"; do
|
||||
|
||||
Binary file not shown.
+107
-106
@@ -1,7 +1,7 @@
|
||||
*****************************************************
|
||||
TMS340 COFF Linker Version 5.01
|
||||
*****************************************************
|
||||
Tue Nov 03 20:09:24 2026
|
||||
Wed Nov 11 17:58:44 2026
|
||||
|
||||
OUTPUT FILE NAME: <MAIN.out>
|
||||
ENTRY POINT SYMBOL: "_start" address: 018a0000
|
||||
@@ -20,38 +20,38 @@ SECTION ALLOCATION MAP
|
||||
output attributes/
|
||||
section page origin length input sections
|
||||
-------- ---- ---------- ---------- ----------------
|
||||
.text 0 018a0000 00014940
|
||||
.text 0 018a0000 00014b10
|
||||
018a0000 00000150 ENTRY.obj (.text)
|
||||
018a0150 00001c90 MAIN.obj (.text)
|
||||
018a1de0 0000ce50 GAME.obj (.text)
|
||||
018aec30 00000d20 SCOREDB.obj (.text)
|
||||
018af950 00002a40 X11.obj (.text)
|
||||
018b2390 00001640 COMPAT.obj (.text)
|
||||
018b39d0 00000210 XGFIX.obj (.text)
|
||||
018b3be0 00000450 rts.lib (.text)
|
||||
018b4030 000001a0 rts.lib (.text)
|
||||
018b41d0 00000230 rts.lib (.text)
|
||||
018b4400 00000150 rts.lib (.text)
|
||||
018b4550 00000120 rts.lib (.text)
|
||||
018b4670 00000110 rts.lib (.text)
|
||||
018b4780 000001c0 rts.lib (.text)
|
||||
018a0150 00001e60 MAIN.obj (.text)
|
||||
018a1fb0 0000ce50 GAME.obj (.text)
|
||||
018aee00 00000d20 SCOREDB.obj (.text)
|
||||
018afb20 00002a40 X11.obj (.text)
|
||||
018b2560 00001640 COMPAT.obj (.text)
|
||||
018b3ba0 00000210 XGFIX.obj (.text)
|
||||
018b3db0 00000450 rts.lib (.text)
|
||||
018b4200 000001a0 rts.lib (.text)
|
||||
018b43a0 00000230 rts.lib (.text)
|
||||
018b45d0 00000150 rts.lib (.text)
|
||||
018b4720 00000120 rts.lib (.text)
|
||||
018b4840 00000110 rts.lib (.text)
|
||||
018b4950 000001c0 rts.lib (.text)
|
||||
|
||||
.cinit 0 018b4940 000012d0
|
||||
018b4940 00000050 MAIN.obj (.cinit)
|
||||
018b4990 00001190 GAME.obj (.cinit)
|
||||
018b5b20 00000050 SCOREDB.obj (.cinit)
|
||||
018b5b70 00000050 X11.obj (.cinit)
|
||||
018b5bc0 00000050 rts.lib (.cinit)
|
||||
.cinit 0 018b4b10 000012d0
|
||||
018b4b10 00000050 MAIN.obj (.cinit)
|
||||
018b4b60 00001190 GAME.obj (.cinit)
|
||||
018b5cf0 00000050 SCOREDB.obj (.cinit)
|
||||
018b5d40 00000050 X11.obj (.cinit)
|
||||
018b5d90 00000050 rts.lib (.cinit)
|
||||
|
||||
.bss 0 01a00000 0001ec00 UNINITIALIZED
|
||||
.bss 0 01a00000 0001ec20 UNINITIALIZED
|
||||
01a00000 00008000 ENTRY.obj (.bss)
|
||||
01a08000 00000400 MAIN.obj (.bss)
|
||||
01a08400 00004a40 GAME.obj (.bss)
|
||||
01a0ce40 00000b80 SCOREDB.obj (.bss)
|
||||
01a0d9c0 0000f200 X11.obj (.bss)
|
||||
01a1cbc0 00000020 COMPAT.obj (.bss)
|
||||
01a1cbe0 00002000 XGFIX.obj (.bss)
|
||||
01a1ebe0 00000020 rts.lib (.bss)
|
||||
01a08000 00000420 MAIN.obj (.bss)
|
||||
01a08420 00004a40 GAME.obj (.bss)
|
||||
01a0ce60 00000b80 SCOREDB.obj (.bss)
|
||||
01a0d9e0 0000f200 X11.obj (.bss)
|
||||
01a1cbe0 00000020 COMPAT.obj (.bss)
|
||||
01a1cc00 00002000 XGFIX.obj (.bss)
|
||||
01a1ec00 00000020 rts.lib (.bss)
|
||||
|
||||
.data 0 018a0000 00000000 UNINITIALIZED
|
||||
|
||||
@@ -60,81 +60,82 @@ GLOBAL SYMBOLS
|
||||
|
||||
address name address name
|
||||
-------- ---- -------- ----
|
||||
01a00000 .bss 018a0000 .text
|
||||
018a0000 .data 018a0000 .data
|
||||
018a0000 .text 018a0000 edata
|
||||
01a08a00 _blackpf 018a0000 _start
|
||||
018a2f40 _cleanup_game 018a0150 _now_ms
|
||||
01a08380 _dbg_events 018a03d0 _sleep_ms
|
||||
01a083c0 _dbg_focus 018a0530 _vt_poll_event
|
||||
01a083a0 _dbg_last 018a0ea0 _vt_handle_event
|
||||
01a08360 _dbg_loops 018a1700 _wait_display
|
||||
01a083e0 _dbg_rev 018a1740 _main
|
||||
018b2390 _fflush 018a1de0 _init_game
|
||||
018a84e0 _game_input 018a2f40 _cleanup_game
|
||||
018a1de0 _init_game 018a3130 _update
|
||||
018a1740 _main 018a84e0 _game_input
|
||||
018b3be0 _memcpy 018aef90 _read_scores
|
||||
018b3d80 _memmove 018af310 _save_score
|
||||
018b4030 _memset 018af8a0 _print_scores
|
||||
01a089a0 _monochrome 018af950 _vt_root_window
|
||||
018a0150 _now_ms 018afa30 _vt_x11_init
|
||||
01a089e0 _onlyascii 018b01e0 _x11_clearscr
|
||||
018af8a0 _print_scores 018b03a0 _x11_reset
|
||||
018b2400 _putchar 018b03e0 _x11_cursor
|
||||
01a08940 _quit 018b0440 _x11_setcolor
|
||||
018b41d0 _rand 018b0560 _x11_setcursor
|
||||
018aef90 _read_scores 018b07b0 _x11_ibmchar
|
||||
01a08a20 _rotstep 018b0c30 _term_putstr
|
||||
018af310 _save_score 018b0dd0 _vt_x11_flush
|
||||
01a08a80 _scr 018b2000 _vt_x11_term_init
|
||||
018a03d0 _sleep_ms 018b2320 _term_init
|
||||
018b2c10 _sprintf 018b2390 _fflush
|
||||
018b4330 _srand 018b2400 _putchar
|
||||
018a0000 _start 018b2c10 _sprintf
|
||||
01a1cbc0 _stdout 018b39d0 _vt_install_xg
|
||||
018b4400 _strcmp 018b3be0 _memcpy
|
||||
018b4550 _strcpy 018b3d80 _memmove
|
||||
018b4670 _strlen 018b4030 _memset
|
||||
018b4780 _strncpy 018b41d0 _rand
|
||||
01a1cae0 _term_clearscr 018b4330 _srand
|
||||
01a1cb20 _term_cursor 018b4400 _strcmp
|
||||
01a08a60 _term_height 018b4550 _strcpy
|
||||
01a1cb60 _term_ibmchar 018b4670 _strlen
|
||||
018b2320 _term_init 018b4780 _strncpy
|
||||
018b0c30 _term_putstr 018b4940 cinit
|
||||
01a1cac0 _term_reset 018b4940 etext
|
||||
01a1cb40 _term_setcolor 01a00000 .bss
|
||||
01a1cb00 _term_setcursor 01a08360 _dbg_loops
|
||||
01a1cba0 _term_type 01a08380 _dbg_events
|
||||
01a08a40 _term_width 01a083a0 _dbg_last
|
||||
01a1cb80 _termenv 01a083c0 _dbg_focus
|
||||
01a08960 _tick_interval 01a083e0 _dbg_rev
|
||||
018a3130 _update 01a08940 _quit
|
||||
01a08980 _use_bell 01a08960 _tick_interval
|
||||
01a089c0 _use_gfxchar 01a08980 _use_bell
|
||||
01a0ce40 _username 01a089a0 _monochrome
|
||||
01a1ca40 _vt_dpy 01a089c0 _use_gfxchar
|
||||
01a1ca80 _vt_gc 01a089e0 _onlyascii
|
||||
018a0ea0 _vt_handle_event 01a08a00 _blackpf
|
||||
018b39d0 _vt_install_xg 01a08a20 _rotstep
|
||||
018a0530 _vt_poll_event 01a08a40 _term_width
|
||||
018af950 _vt_root_window 01a08a60 _term_height
|
||||
01a1ca60 _vt_win 01a08a80 _scr
|
||||
018b0dd0 _vt_x11_flush 01a0ce40 _username
|
||||
018afa30 _vt_x11_init 01a1ca40 _vt_dpy
|
||||
01a1caa0 _vt_x11_progress 01a1ca60 _vt_win
|
||||
018b2000 _vt_x11_term_init 01a1ca80 _vt_gc
|
||||
018a1700 _wait_display 01a1caa0 _vt_x11_progress
|
||||
018b01e0 _x11_clearscr 01a1cac0 _term_reset
|
||||
018b03e0 _x11_cursor 01a1cae0 _term_clearscr
|
||||
018b07b0 _x11_ibmchar 01a1cb00 _term_setcursor
|
||||
018b03a0 _x11_reset 01a1cb20 _term_cursor
|
||||
018b0440 _x11_setcolor 01a1cb40 _term_setcolor
|
||||
018b0560 _x11_setcursor 01a1cb60 _term_ibmchar
|
||||
018b4940 cinit 01a1cb80 _termenv
|
||||
018a0000 edata 01a1cba0 _term_type
|
||||
01a1ec00 end 01a1cbc0 _stdout
|
||||
018b4940 etext 01a1ec00 end
|
||||
01a00000 .bss 018a0000 .data
|
||||
018a0000 .data 018a0000 .text
|
||||
018a0000 .text 018a0000 _start
|
||||
01a08a20 _blackpf 018a0000 edata
|
||||
018a3110 _cleanup_game 018a0150 _now_ms
|
||||
01a083a0 _dbg_events 018a03d0 _vt_rand_seed
|
||||
01a083e0 _dbg_focus 018a0420 _sleep_ms
|
||||
01a083c0 _dbg_last 018a0580 _vt_poll_event
|
||||
01a08380 _dbg_loops 018a0ef0 _vt_handle_event
|
||||
01a08400 _dbg_rev 018a18d0 _wait_display
|
||||
018b2560 _fflush 018a1910 _main
|
||||
018a86b0 _game_input 018a1fb0 _init_game
|
||||
018a1fb0 _init_game 018a3110 _cleanup_game
|
||||
018a1910 _main 018a3300 _update
|
||||
018b3db0 _memcpy 018a86b0 _game_input
|
||||
018b3f50 _memmove 018af160 _read_scores
|
||||
018b4200 _memset 018af4e0 _save_score
|
||||
01a089c0 _monochrome 018afa70 _print_scores
|
||||
018a0150 _now_ms 018afb20 _vt_root_window
|
||||
01a08a00 _onlyascii 018afc00 _vt_x11_init
|
||||
018afa70 _print_scores 018b03b0 _x11_clearscr
|
||||
018b25d0 _putchar 018b0570 _x11_reset
|
||||
01a08960 _quit 018b05b0 _x11_cursor
|
||||
018b43a0 _rand 018b0610 _x11_setcolor
|
||||
018af160 _read_scores 018b0730 _x11_setcursor
|
||||
01a08a40 _rotstep 018b0980 _x11_ibmchar
|
||||
018af4e0 _save_score 018b0e00 _term_putstr
|
||||
01a08aa0 _scr 018b0fa0 _vt_x11_flush
|
||||
018a0420 _sleep_ms 018b21d0 _vt_x11_term_init
|
||||
018b2de0 _sprintf 018b24f0 _term_init
|
||||
018b4500 _srand 018b2560 _fflush
|
||||
018a0000 _start 018b25d0 _putchar
|
||||
01a1cbe0 _stdout 018b2de0 _sprintf
|
||||
018b45d0 _strcmp 018b3ba0 _vt_install_xg
|
||||
018b4720 _strcpy 018b3db0 _memcpy
|
||||
018b4840 _strlen 018b3f50 _memmove
|
||||
018b4950 _strncpy 018b4200 _memset
|
||||
01a1cb00 _term_clearscr 018b43a0 _rand
|
||||
01a1cb40 _term_cursor 018b4500 _srand
|
||||
01a08a80 _term_height 018b45d0 _strcmp
|
||||
01a1cb80 _term_ibmchar 018b4720 _strcpy
|
||||
018b24f0 _term_init 018b4840 _strlen
|
||||
018b0e00 _term_putstr 018b4950 _strncpy
|
||||
01a1cae0 _term_reset 018b4b10 cinit
|
||||
01a1cb60 _term_setcolor 018b4b10 etext
|
||||
01a1cb20 _term_setcursor 01a00000 .bss
|
||||
01a1cbc0 _term_type 01a08380 _dbg_loops
|
||||
01a08a60 _term_width 01a083a0 _dbg_events
|
||||
01a1cba0 _termenv 01a083c0 _dbg_last
|
||||
01a08980 _tick_interval 01a083e0 _dbg_focus
|
||||
018a3300 _update 01a08400 _dbg_rev
|
||||
01a089a0 _use_bell 01a08960 _quit
|
||||
01a089e0 _use_gfxchar 01a08980 _tick_interval
|
||||
01a0ce60 _username 01a089a0 _use_bell
|
||||
01a1ca60 _vt_dpy 01a089c0 _monochrome
|
||||
01a1caa0 _vt_gc 01a089e0 _use_gfxchar
|
||||
018a0ef0 _vt_handle_event 01a08a00 _onlyascii
|
||||
018b3ba0 _vt_install_xg 01a08a20 _blackpf
|
||||
018a0580 _vt_poll_event 01a08a40 _rotstep
|
||||
018a03d0 _vt_rand_seed 01a08a60 _term_width
|
||||
018afb20 _vt_root_window 01a08a80 _term_height
|
||||
01a1ca80 _vt_win 01a08aa0 _scr
|
||||
018b0fa0 _vt_x11_flush 01a0ce60 _username
|
||||
018afc00 _vt_x11_init 01a1ca60 _vt_dpy
|
||||
01a1cac0 _vt_x11_progress 01a1ca80 _vt_win
|
||||
018b21d0 _vt_x11_term_init 01a1caa0 _vt_gc
|
||||
018a18d0 _wait_display 01a1cac0 _vt_x11_progress
|
||||
018b03b0 _x11_clearscr 01a1cae0 _term_reset
|
||||
018b05b0 _x11_cursor 01a1cb00 _term_clearscr
|
||||
018b0980 _x11_ibmchar 01a1cb20 _term_setcursor
|
||||
018b0570 _x11_reset 01a1cb40 _term_cursor
|
||||
018b0610 _x11_setcolor 01a1cb60 _term_setcolor
|
||||
018b0730 _x11_setcursor 01a1cb80 _term_ibmchar
|
||||
018b4b10 cinit 01a1cba0 _termenv
|
||||
018a0000 edata 01a1cbc0 _term_type
|
||||
01a1ec20 end 01a1cbe0 _stdout
|
||||
018b4b10 etext 01a1ec20 end
|
||||
|
||||
[76 symbols]
|
||||
[77 symbols]
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
@@ -36,4 +36,5 @@ exec env VT1200_SKIP_LEVEL1=1 \
|
||||
LOADER_BIN="$LOADER" LOADER_COFF="$COFF" LOADER_OUT="$DIR/build" \
|
||||
"$M" vt1200 -rompath "$ROOT/harness/mame/roms" \
|
||||
-skip_gameinfo -debug -debugger none \
|
||||
-lightgun -lightgun_device mouse \
|
||||
-autoboot_script "$DIR/tests/play.lua" -autoboot_delay 0
|
||||
@@ -25,7 +25,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#include "term.h"
|
||||
#include "scoredb.h"
|
||||
|
||||
extern long now_ms(void);
|
||||
extern unsigned vt_rand_seed(void);
|
||||
|
||||
|
||||
int quit;
|
||||
@@ -192,7 +192,7 @@ int init_game(void)
|
||||
scores = read_scores(0, 10);
|
||||
memset(&cur_score, 0, sizeof cur_score);
|
||||
|
||||
srand((unsigned)now_ms());
|
||||
srand(vt_rand_seed());
|
||||
|
||||
pause = 0;
|
||||
gameover = 0;
|
||||
|
||||
@@ -18,6 +18,7 @@ static vt_u32 evbuf[24];
|
||||
static long ms_base;
|
||||
static int ms_last = -1;
|
||||
static int focused;
|
||||
static int vt_paused;
|
||||
volatile vt_u32 dbg_loops, dbg_events, dbg_last, dbg_focus, dbg_rev;
|
||||
|
||||
long now_ms(void)
|
||||
@@ -34,6 +35,16 @@ long now_ms(void)
|
||||
return ms_base;
|
||||
}
|
||||
|
||||
/*
|
||||
* Seed for the game's PRNG. now_ms() returns 0 on its first call (it only
|
||||
* latches the counter there), so seeding from it gives a constant; read the
|
||||
* free-running 16-bit tick directly instead.
|
||||
*/
|
||||
unsigned vt_rand_seed(void)
|
||||
{
|
||||
return (unsigned)*(volatile unsigned short *)0x001E93C0UL;
|
||||
}
|
||||
|
||||
void sleep_ms(int ms)
|
||||
{
|
||||
if(ms < 1) ms = 1;
|
||||
@@ -105,8 +116,15 @@ void vt_handle_event(void)
|
||||
game_input('`');
|
||||
} else if(evbuf[0] == 9) { /* FocusIn */
|
||||
focused = 1;
|
||||
if(vt_paused) { /* resume only what we paused */
|
||||
game_input('p');
|
||||
vt_paused = 0;
|
||||
}
|
||||
} else if(evbuf[0] == 10) { /* FocusOut */
|
||||
if(focused) game_input('p');
|
||||
if(focused && !vt_paused) {
|
||||
game_input('p'); /* 'p' toggles pause in game_input */
|
||||
vt_paused = 1;
|
||||
}
|
||||
focused = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ int vt_x11_init(void)
|
||||
if(!vt_win)
|
||||
return -1;
|
||||
vt_x11_progress = 14;
|
||||
VT_XSELECT(vt_dpy, vt_win, 0x22000FUL);
|
||||
VT_XSELECT(vt_dpy, vt_win, 0x22800FUL); /* + ExposureMask */
|
||||
vt_gc = VT_XGC(vt_dpy, vt_win, 0, 0);
|
||||
if(!vt_gc)
|
||||
return -1;
|
||||
|
||||
@@ -12,7 +12,7 @@ LOG="$APP/build/fmt.log"
|
||||
mkdir -p "$APP/build"
|
||||
"$APP/build.sh" "$DIR/fmt.c" "$APP/src/vt1200/compat.c" >"$APP/build/fmt-build.log" 2>&1
|
||||
|
||||
FMT=$(awk '/_out/ {print $1; exit}' "$APP/build/fmt.map")
|
||||
FMT=$(awk '{for(i=2;i<=NF;i++) if($i=="_out") print $(i-1)}' "$APP/build/fmt.map" | head -1)
|
||||
VT1200_SKIP_LEVEL1=1 FMT_MARK="0x$FMT" \
|
||||
LOADER_AT=2500 LOADER_END=2700 \
|
||||
LOADER_BIN="$ROOT/dwt/loader/build/loader.bin" \
|
||||
|
||||
@@ -36,6 +36,7 @@ local key_zero = ports[":lk401:K10"].fields["0 )"]
|
||||
local key_ret = ports[":lk401:K68"].fields["Return"]
|
||||
local key_del = ports[":lk401:K67"].fields["Delete"]
|
||||
local key_q = ports[":lk401:K13"].fields["Q"]
|
||||
local key_p = ports[":lk401:K22"].fields["P"]
|
||||
local tabx = ports[":tablet:TABLET_X"].fields["Tablet X"]
|
||||
local taby = ports[":tablet:TABLET_Y"].fields["Tablet Y"]
|
||||
local tabb = ports[":tablet:TABLET_BTN"].fields["P1 Button 1"]
|
||||
@@ -154,6 +155,8 @@ local function key_step(frames, key)
|
||||
if frames == 3250 then key_del:set_value(0) end
|
||||
if frames == 3260 then key_q:set_value(1) end
|
||||
if frames == 3270 then key_q:set_value(0) end
|
||||
if frames == 3280 then key_p:set_value(1) end
|
||||
if frames == 3290 then key_p:set_value(0) end
|
||||
end
|
||||
|
||||
local function r32(a)
|
||||
|
||||
@@ -8,7 +8,7 @@ M=${MAME:-/home/arti/code/k-space/mame0289/vt1200}
|
||||
LOG="$APP/build/input.log"
|
||||
mkdir -p "$APP/build"
|
||||
"$APP/build.sh" "$DIR/input.c" "$APP/src/vt1200/main.c" "$APP/src/vt1200/x11.c" "$APP/src/vt1200/xgfix.c" >"$APP/build/input-build.log" 2>&1
|
||||
MARK=$(awk '/_mark/ {print $1; exit}' "$APP/build/input.map")
|
||||
MARK=$(awk '{for(i=2;i<=NF;i++) if($i=="_mark") print $(i-1)}' "$APP/build/input.map" | head -1)
|
||||
VT1200_SKIP_LEVEL1=1 INPUT_MARK="0x$MARK" \
|
||||
LOADER_AT=2500 LOADER_END=3400 \
|
||||
LOADER_BIN="$ROOT/dwt/loader/build/loader.bin" \
|
||||
@@ -20,7 +20,7 @@ LOADER_OUT="$APP/build" \
|
||||
-autoboot_script "$DIR/input.lua" -autoboot_delay 0 \
|
||||
>"$LOG" 2>&1 || true
|
||||
grep 'INPUT:' "$LOG" | tail -3
|
||||
grep -q 'INPUT: .*bytes=.*61 9B 41 9B 42 9B 44 9B 43 30 0A 7F 71' "$LOG" || {
|
||||
grep -q 'INPUT: .*bytes=.*61 9B 41 9B 42 9B 44 9B 43 30 0A 7F 71 70' "$LOG" || {
|
||||
echo "input.sh: mapped key sequence missing (see $LOG)" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
local function hex(v, w) return string.format("%0" .. (w or 8) .. "X", v) end
|
||||
|
||||
local machine = manager.machine
|
||||
local PTICK = tonumber(os.getenv("DIAG_TICK") or "0")
|
||||
local PQUIT = tonumber(os.getenv("DIAG_QUIT") or "0")
|
||||
local ports = machine.ioport.ports
|
||||
local tabx = ports[":tablet:TABLET_X"].fields["Tablet X"]
|
||||
local taby = ports[":tablet:TABLET_Y"].fields["Tablet Y"]
|
||||
@@ -274,6 +276,9 @@ local function inspect()
|
||||
r32(0x01890140), r32(0x01890160), hex(r32(0x01890100)),
|
||||
hex(r32(0x01890110)), hex(r32(0x01890120)), hex(r32(0x01890130))))
|
||||
end
|
||||
if PTICK ~= 0 or PQUIT ~= 0 then
|
||||
print(string.format("DIAG: tick=%d quit=%d", PTICK ~= 0 and r32(PTICK) or -1, PQUIT ~= 0 and r32(PQUIT) or -1))
|
||||
end
|
||||
print(string.format("LOADER: PC at inspection = %s", hex(cpu.state['PC'].value)))
|
||||
end
|
||||
|
||||
|
||||
@@ -8,8 +8,13 @@ M=${MAME:-/home/arti/code/k-space/mame0289/vt1200}
|
||||
EV="$APP/evidence"
|
||||
LOG="$APP/build/play.log"
|
||||
mkdir -p "$EV" "$APP/build"
|
||||
OUTNAME=termtris "$APP/build.sh" "$APP/src/vt1200/main.c" "$APP/src/game.c" "$APP/src/vt1200/scoredb.c" \
|
||||
"$APP/src/vt1200/x11.c" "$APP/src/vt1200/compat.c" "$APP/src/vt1200/xgfix.c" \
|
||||
>"$APP/build/play-build.log" 2>&1
|
||||
rm -f "$EV/loader_frame3300.png"
|
||||
VT1200_SKIP_LEVEL1=1 LOADER_SNAP=1 \
|
||||
TICK=$(awk '{for(i=2;i<=NF;i++) if($i=="_tick_interval") print $(i-1)}' "$APP/build/termtris.map" | head -1)
|
||||
QUIT=$(awk '{for(i=2;i<=NF;i++) if($i=="_quit") print $(i-1)}' "$APP/build/termtris.map" | head -1)
|
||||
VT1200_SKIP_LEVEL1=1 LOADER_SNAP=1 DIAG_TICK="0x$TICK" DIAG_QUIT="0x$QUIT" \
|
||||
LOADER_AT=2500 LOADER_END=3300 \
|
||||
LOADER_BIN="$ROOT/dwt/loader/build/loader.bin" \
|
||||
LOADER_COFF="$APP/build/termtris.coff" \
|
||||
@@ -19,7 +24,14 @@ LOADER_OUT="$EV" \
|
||||
-debug -debugger none \
|
||||
-autoboot_script "$DIR/play.lua" -autoboot_delay 0 \
|
||||
>"$LOG" 2>&1 || true
|
||||
grep -E 'PLAY:|LOADER: result|LOADER: snapshot' "$LOG" | tail -6
|
||||
grep -E 'PLAY:|DIAG:|LOADER: result|LOADER: snapshot' "$LOG" | tail -6
|
||||
grep -q 'LOADER: result status=0' "$LOG" || { echo "play.sh: the game did not start (see $LOG)" >&2; exit 1; }
|
||||
DIAG=$(grep -a 'DIAG: tick=' "$LOG" | head -1)
|
||||
[ -n "$DIAG" ] || { echo "play.sh: no DIAG line (see $LOG)" >&2; exit 1; }
|
||||
TICKVAL=$(printf '%s' "$DIAG" | sed -n 's/.*tick=\([-0-9]*\).*/\1/p')
|
||||
QUITVAL=$(printf '%s' "$DIAG" | sed -n 's/.*quit=\([-0-9]*\).*/\1/p')
|
||||
[ "$TICKVAL" -gt 0 ] || { echo "play.sh: init_game never ran (tick=$TICKVAL)" >&2; exit 1; }
|
||||
[ "$QUITVAL" = 0 ] || { echo "play.sh: game quit by itself" >&2; exit 1; }
|
||||
[ -s "$EV/loader_frame3300.png" ] || { echo "play.sh: no snapshot (see $LOG)" >&2; exit 1; }
|
||||
cp "$EV/loader_frame3300.png" "$EV/termtris_frame3300.png"
|
||||
echo "play: $EV/termtris_frame3300.png"
|
||||
@@ -7,6 +7,9 @@ ROOT=$(cd "$APP/../.." && pwd)
|
||||
M=${MAME:-/home/arti/code/k-space/mame0289/vt1200}
|
||||
EV="$APP/evidence"
|
||||
mkdir -p "$EV" "$APP/build"
|
||||
OUTNAME=termtris "$APP/build.sh" "$APP/src/vt1200/main.c" "$APP/src/game.c" "$APP/src/vt1200/scoredb.c" \
|
||||
"$APP/src/vt1200/x11.c" "$APP/src/vt1200/compat.c" "$APP/src/vt1200/xgfix.c" \
|
||||
>"$APP/build/play_keys-build.log" 2>&1
|
||||
for mode in ${MODES:-move panels quit}; do
|
||||
LOG="$APP/build/play_$mode.log"
|
||||
rm -f "$EV/loader_frame3200.png"
|
||||
|
||||
@@ -11,8 +11,8 @@ LOG="$APP/build/render.log"
|
||||
mkdir -p "$EV" "$APP/build"
|
||||
"$APP/build.sh" "$DIR/render.c" "$APP/src/vt1200/x11.c" "$APP/src/vt1200/xgfix.c" >"$APP/build/render-build.log" 2>&1
|
||||
rm -f "$EV/loader_frame3400.png"
|
||||
MARK=$(awk '/_mark/ {print $1; exit}' "$APP/build/render.map")
|
||||
PROG=$(awk '/_vt_x11_progress/ {print $1; exit}' "$APP/build/render.map")
|
||||
MARK=$(awk '{for(i=2;i<=NF;i++) if($i=="_mark") print $(i-1)}' "$APP/build/render.map" | head -1)
|
||||
PROG=$(awk '{for(i=2;i<=NF;i++) if($i=="_vt_x11_progress") print $(i-1)}' "$APP/build/render.map" | head -1)
|
||||
VT1200_SKIP_LEVEL1=1 LOADER_SNAP=1 RENDER_MARK="0x$MARK" X11_PROGRESS="0x$PROG" \
|
||||
LOADER_AT=2500 LOADER_END=3400 \
|
||||
LOADER_BIN="$ROOT/dwt/loader/build/loader.bin" \
|
||||
@@ -24,6 +24,14 @@ LOADER_OUT="$EV" \
|
||||
-autoboot_script "$DIR/render.lua" -autoboot_delay 0 \
|
||||
>"$LOG" 2>&1 || true
|
||||
grep -E 'LOADER: snapshot|LOADER: result' "$LOG" | tail -4
|
||||
grep -q 'RENDER: magic=524E4452 .*flus=464C5553' "$LOG" || {
|
||||
echo "render.sh: the renderer did not finish (see $LOG)" >&2
|
||||
exit 1
|
||||
}
|
||||
grep -q 'RENDER: .*progress=00FFFFFF' "$LOG" || {
|
||||
echo "render.sh: flush did not complete (see $LOG)" >&2
|
||||
exit 1
|
||||
}
|
||||
[ -s "$EV/loader_frame3400.png" ] || { echo "render.sh: no snapshot (see $LOG)" >&2; exit 1; }
|
||||
cp "$EV/loader_frame3400.png" "$EV/render_frame3400.png"
|
||||
echo "render: $EV/render_frame3400.png"
|
||||
@@ -13,7 +13,7 @@ LOG="$APP/build/smoke.log"
|
||||
mkdir -p "$APP/build"
|
||||
"$APP/build.sh" "$DIR/smoke.c" "$APP/src/vt1200/xgfix.c" >"$APP/build/smoke-build.log" 2>&1
|
||||
|
||||
MARK=$(awk '/_mark/ {print $1; exit}' "$APP/build/smoke.map")
|
||||
MARK=$(awk '{for(i=2;i<=NF;i++) if($i=="_mark") print $(i-1)}' "$APP/build/smoke.map" | head -1)
|
||||
VT1200_SKIP_LEVEL1=1 SMOKE_MARK="0x$MARK" \
|
||||
LOADER_AT=2500 LOADER_END=3400 \
|
||||
LOADER_BIN="$ROOT/dwt/loader/build/loader.bin" \
|
||||
|
||||
@@ -30,7 +30,7 @@ file as success and retries a missing one. Two quirks are handled there:
|
||||
Result (map):
|
||||
|
||||
```
|
||||
.text 018A0000 .cinit 018B4730 .bss 01A00000
|
||||
.text 018A0000 .cinit 018B4B10 .bss 01A00000
|
||||
ENTRY POINT SYMBOL: "_start" address: 018a0000
|
||||
```
|
||||
|
||||
@@ -51,8 +51,9 @@ Smoke test evidence (`apps/termtris/tests/smoke.sh`):
|
||||
## Rendering and the flush deadlock
|
||||
|
||||
80×24 cells of 6×13 px (the default GC font, baseline +10) → a 480×312 window.
|
||||
The raster is 1 bit deep, so the backend follows the game's own monochrome
|
||||
convention: colour is dropped and bold (`0x80`) reverses a cell. The playfield
|
||||
The raster is 1 bit deep, so the backend drops colour (like the game's `-m`
|
||||
monochrome mode) and treats the bold bit (`0x80`) as reverse video. That
|
||||
reversal is this backend's choice; upstream `ansi.c -m` only emits SGR bold. The playfield
|
||||
is black spaces; tetrominoes are the `[`/`]` tiles.
|
||||
|
||||
`vt_x11_flush()` repaints **whole rows** — one fill for the row background, one
|
||||
|
||||
Reference in new issue
Block a user