From 66fe15367b901cce3eda6de0c3a01b318c771f74 Mon Sep 17 00:00:00 2001 From: SDD Date: Fri, 16 Oct 2026 01:52:06 +0300 Subject: [PATCH] harness: per-window busy state machines for the big windows --- harness/mame/test_vt1200_board.cpp | 18 ++++++++++++++++++ harness/mame/vt1200_board.cpp | 15 +++++++++++---- harness/mame/vt1200_board.h | 20 +++++++++++++++++--- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/harness/mame/test_vt1200_board.cpp b/harness/mame/test_vt1200_board.cpp index bc31dcd..2d0a7b6 100644 --- a/harness/mame/test_vt1200_board.cpp +++ b/harness/mame/test_vt1200_board.cpp @@ -49,6 +49,23 @@ static void test_busy_bit_arms_on_write_and_clears(void) CHECK((b.read(status) & 0x0001) == 0x0000); // done } +static void test_windows_are_independent(void) +{ + vt1200_board b; + b.set_model_handshake(true); + b.set_window_busy_ticks(VT1200_WIN2, 1); + b.set_window_busy_ticks(VT1200_WIN3, 3); + + b.write(VT1200_WIN2 + VT1200_OFF_CMD, 0x0001); + b.write(VT1200_WIN3 + VT1200_OFF_CMD, 0x0001); + CHECK((b.read(VT1200_WIN2 + VT1200_OFF_STATUS) & 1) == 1); + CHECK((b.read(VT1200_WIN3 + VT1200_OFF_STATUS) & 1) == 1); + + b.tick(); + CHECK((b.read(VT1200_WIN2 + VT1200_OFF_STATUS) & 1) == 0); // WIN2 finished + CHECK((b.read(VT1200_WIN3 + VT1200_OFF_STATUS) & 1) == 1); // WIN3 still busy +} + static void test_monitor_switch_accepts_raw_bits_or_position(void) { vt1200_board raw; @@ -75,6 +92,7 @@ int main(void) test_override_read(); test_monitor_switch_is_mixed_with_latches(); test_busy_bit_arms_on_write_and_clears(); + test_windows_are_independent(); test_monitor_switch_accepts_raw_bits_or_position(); test_switch_mix_only_when_configured(); std::printf(failures ? "%d FAILURE(S)\n" : "all board tests passed\n", failures); diff --git a/harness/mame/vt1200_board.cpp b/harness/mame/vt1200_board.cpp index 89ae469..5a4560a 100644 --- a/harness/mame/vt1200_board.cpp +++ b/harness/mame/vt1200_board.cpp @@ -23,7 +23,8 @@ uint16_t vt1200_board::read(uint32_t addr) if (m_handshake && (addr & 0xffff) == VT1200_OFF_STATUS) { - if (m_busy_left > 0) + auto busy = m_busy_left.find(addr & 0xffff0000); + if (busy != m_busy_left.end() && busy->second > 0) value |= 0x0001; else value &= ~0x0001; @@ -35,11 +36,17 @@ void vt1200_board::write(uint32_t addr, uint16_t data) { m_store[addr] = data; if (m_handshake && (addr & 0xffff) == VT1200_OFF_CMD) - m_busy_left = m_busy_ticks; + { + const uint32_t win = addr & 0xffff0000; + auto ticks = m_busy_ticks_by_win.find(win); + m_busy_left[win] = (ticks != m_busy_ticks_by_win.end()) ? ticks->second : 0; + } } void vt1200_board::tick() { - if (m_busy_left > 0) - m_busy_left--; + // Advance every window's state machine, not just the one last touched. + for (auto &entry : m_busy_left) + if (entry.second > 0) + entry.second--; } diff --git a/harness/mame/vt1200_board.h b/harness/mame/vt1200_board.h index f0c1bc3..e4a8279 100644 --- a/harness/mame/vt1200_board.h +++ b/harness/mame/vt1200_board.h @@ -40,7 +40,18 @@ public: void set_default(uint16_t v) { m_default = v; } void set_override(uint32_t addr, uint16_t v) { m_override[addr] = v; } void set_model_handshake(bool on) { m_handshake = on; } - void set_busy_ticks(int n) { m_busy_ticks = n; } + + // Per-window busy counts. Each of the four windows owns its own count, so + // the two big windows (0x06200000 and 0x06400000) can be tuned + // independently. set_busy_ticks is shorthand that applies to every window. + void set_busy_ticks(int n) + { + m_busy_ticks_by_win[VT1200_WIN0] = n; + m_busy_ticks_by_win[VT1200_WIN1] = n; + m_busy_ticks_by_win[VT1200_WIN2] = n; + m_busy_ticks_by_win[VT1200_WIN3] = n; + } + void set_window_busy_ticks(uint32_t window_base, int n) { m_busy_ticks_by_win[window_base] = n; } // Monitor switch (bits 4-6 of the switch port). The argument is accepted // unambiguously as EITHER the raw register bits (e.g. 0x70) OR a small @@ -66,8 +77,11 @@ private: std::map m_override; // fixed values (experiments) uint16_t m_default = 0; bool m_handshake = false; - int m_busy_ticks = 0; - int m_busy_left = 0; + // Busy state machines, keyed by window base (addr & 0xffff0000): how many + // ticks each window stays busy after a command write, and the remaining + // count for the command currently in flight. + std::map m_busy_ticks_by_win; + std::map m_busy_left; bool m_switch_set = false; // set_monitor_switch was called uint16_t m_switch_bits = 0; };