#!/usr/bin/env bash # verify-x68000-serial.sh - both-directions RS-232C gate for the X68000 port. # # Boots SERIAL.X under the patched MAME with SCC channel A wired to a null_modem # on a TCP socket, sends a probe string in, and checks the example echoes it # back. That exercises the full chain: elf2x68k -> .X -> xdftool image -> # Human68k -> JoeyLib serial HAL -> IOCS -> SCC -> host. # # Requires: ./install.sh install x68000 -- the patched MAME # (installer/patches/mame/0004-x68k-waitstates-rs232-mouse.patch) # and the Human68k template image it copies. set -uo pipefail repo=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) source "$repo/scripts/lib/joeyEnv.sh" joeyNeed MAME mame joeyNeed X68K_DIR x68kFirmware joeyNeedFile "$X68K_DIR/roms/x68000/cgrom.dat" x68kCgrom source "$repo/scripts/lib/x68kDisk.sh" ROMS="$X68K_DIR/roms" PORT="${X68K_SERIAL_PORT:-6800}" # SERTEST (no jlInit, banner then echo) passes the same probe/echo test. PROG="${X68K_SERIAL_PROG:-SERIAL}" # The host end's line, "BAUD DATABITS PARITY STOPBITS" (e.g. "4800 7 E 1"). # Empty keeps MAME's null_modem default, 9600 8 N 1. A guest that did not # apply its jlSerialConfigT would still be at the default, so running this # with a program built for another line proves the settings reach the SCC. # Build that program with the matching -DSERIAL_BAUD=... (and SERIAL_DATABITS, # SERIAL_PARITY, SERIAL_STOPBITS; see examples/serial/serial.c) and pass its # name in X68K_SERIAL_PROG. 19200 and 38400 need RSDRV.SYS, which the boot # disk loads (scripts/lib/x68kDisk.sh). LINE="${X68K_SERIAL_LINE:-}" PROBE="${X68K_SERIAL_PROBE:-JOEYLIB-X68K}" MAXWAIT="${X68K_SERIAL_TIMEOUT:-420}" for f in "$MAME" "$X68K_SYSTEM_DISK"; do [ -e "$f" ] || { echo "verify-x68000-serial: missing $f" >&2; exit 2; } done work=$(mktemp -d -t joey-x68ser.XXXXXX) peer="" mame="" cleanup() { joeyStop "$mame" "$peer" rm -rf "$work" } trap cleanup EXIT # Autorun the program. No ECHO OFF so a load failure is visible in a screenshot. x68kBootDisk "$work/serial.xdf" "A:\\$PROG.X" || exit 1 x68kXdf add "$work/serial.xdf" "$repo/build/x68000/bin/$PROG.X" "$PROG.X" >/dev/null || exit 1 # Host end of the link. MAME's null_modem socket form CONNECTS, so we listen. python3 "$repo/scripts/x68kSerialPeer.py" \ --port "$PORT" --probe "$PROBE" --timeout "$MAXWAIT" \ > "$work/peer.out" 2>&1 & peer=$! sleep 2 # From the work dir, so MAME's cfg/ and nvram/ land there, not in the caller's # cwd where the next run would read them back. cd "$work" || exit 1 if [ -n "$LINE" ]; then python3 - "$LINE" > "$work/x68000.cfg" <<'PY' || exit 2 import sys # MAME's RS232_* enum values (src/devices/bus/rs232/rs232.h). BAUD = {"300": 2, "600": 3, "1200": 4, "2400": 5, "4800": 6, "9600": 7, "19200": 9, "38400": 11} DATA = {"5": 0, "6": 1, "7": 2, "8": 3} PARITY = {"N": 0, "O": 1, "E": 2} STOP = {"1": 1, "2": 3} baud, data, parity, stop = sys.argv[1].split() tag = ":rs232c:null_modem:" ports = [("RS232_TXBAUD", 7, BAUD[baud]), ("RS232_RXBAUD", 7, BAUD[baud]), ("RS232_DATABITS", 3, DATA[data]), ("RS232_PARITY", 0, PARITY[parity.upper()]), ("RS232_STOPBITS", 1, STOP[stop])] print('\n\n \n ') for name, default, value in ports: print(f' ') print(' \n \n') PY mkdir -p "$work/cfg" mv "$work/x68000.cfg" "$work/cfg/x68000.cfg" fi # MAME runs until the peer has its verdict and is then stopped by PID: waiting # out a whole run once the probe has echoed cost minutes per gate. The peer's # own deadline (MAXWAIT) bounds the run, and MAME is started directly rather # than under timeout, so $! is MAME itself and stopping it orphans nothing. "$MAME" x68000 \ -bios ipl10 -rompath "$ROMS" \ -flop1 "$work/serial.xdf" \ -rs232c null_modem -bitb "socket.127.0.0.1:$PORT" \ -video none -sound none -nothrottle /dev/null 2>&1 & mame=$! wait "$peer" rc=$? peer="" joeyStop "$mame" mame="" cat "$work/peer.out" exit $rc