emulator: RIO panel click-to-press + lamp flash blink
Make the in-fork glass cockpit fully interactive and finish the lamp model. - Click-to-press: clicking a button's region in a VDB head window presses that RIO address into the game (lights white-hot while held, releases on mouse-up). vpxlog rt_wndproc hit-tests the click against the bezel geometry (MFD 4 top / 4 bottom, radar 6 left / 6 right; the radar bottom indicators are display-only, not clickable); head windows are tagged via GWLP_USERDATA. Clicks arrive on the VPX render thread, so the seam serialrio RIO_HostButton() queues them under a mutex and pollInput() drains them on the emu tick through the same incHold/ decHold path as the keyboard/pad -- so a click also lights the bezel. - Flash blink: decode the lamp byte's flash bits (RioLampState 1 slow / 2 med / 3 fast) -- an unpressed flashing lamp now toggles between its brightness level and off (half-periods 500/250/125ms); solid lamps unchanged, a press still wins. - Focus: head windows are WS_EX_NOACTIVATE so a button click never pulls foreground off DOSBox (which would demote the emu thread and stop SDL polling the pad); a click uses MA_NOACTIVATE too. Do NOT enable SDL background joystick events -- that raced the emu-thread controller poll against SDL's main-thread pump and crashed the process. Explode layout only, and only when a serial=rio port is present. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -217,6 +217,10 @@ bool RIO_GetPanelState(uint8_t lamps[72], uint8_t pressed[72]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void RIO_HostButton(int addr, bool down) {
|
||||
if (rio_instance) rio_instance->hostButton(addr, down);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
CSerialRio::CSerialRio(Bitu id, CommandLine* cmd) : CSerial(id, cmd) {
|
||||
@@ -584,6 +588,13 @@ void CSerialRio::getPanelState(uint8_t lampsOut[72], uint8_t pressedOut[72]) {
|
||||
}
|
||||
}
|
||||
|
||||
// panel click from the VPX render thread -- queue it; pollInput() (emu thread)
|
||||
// drains and applies it, so it composes with the keyboard/pad hold counts.
|
||||
void CSerialRio::hostButton(int addr, bool down) {
|
||||
std::lock_guard<std::mutex> lk(panelMx);
|
||||
panelQ.push_back(std::make_pair(addr, down));
|
||||
}
|
||||
|
||||
void CSerialRio::releaseAllKeys() {
|
||||
std::set<int> keys = heldKeys;
|
||||
heldKeys.clear();
|
||||
@@ -781,6 +792,11 @@ void CSerialRio::applyReset(uint8_t target) {
|
||||
|
||||
// ---- gamepad + axis input ----------------------------------------------------
|
||||
void CSerialRio::openPad() {
|
||||
// NOTE: do NOT enable SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS here -- it
|
||||
// makes SDL's main-thread event pump update the joystick concurrently with
|
||||
// our emu-thread SDL_GameControllerUpdate (not thread-safe -> process crash,
|
||||
// 2026-07-24). Keeping DOSBox focused (the head windows are WS_EX_NOACTIVATE
|
||||
// so a click can't steal foreground) is what keeps the pad polling.
|
||||
SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER);
|
||||
int n = SDL_NumJoysticks();
|
||||
for (int i = 0; i < n; i++) {
|
||||
@@ -815,6 +831,16 @@ void CSerialRio::pollInput() {
|
||||
if (dt < 0.0) dt = 0.0;
|
||||
if (dt > 0.1) dt = 0.1;
|
||||
|
||||
// apply panel clicks queued by the VPX window thread (RIO_HostButton) --
|
||||
// same hold-count path as the keyboard/pad, so a held click lights the bezel
|
||||
std::vector<std::pair<int,bool>> clicks;
|
||||
{ std::lock_guard<std::mutex> lk(panelMx); clicks.swap(panelQ); }
|
||||
for (size_t i = 0; i < clicks.size(); i++) {
|
||||
if (clicks[i].second) incHold(clicks[i].first);
|
||||
else decHold(clicks[i].first);
|
||||
logf("panel %s 0x%02X", clicks[i].second ? "click" : "release", clicks[i].first);
|
||||
}
|
||||
|
||||
// gamepad snapshot; everything rests at zero when absent/detached, so a
|
||||
// detach releases whatever the pad held (button edges below see btns=0)
|
||||
float src[6] = { 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
Reference in New Issue
Block a user