diff --git a/src/xenia/hid/file/file_input_driver.h b/src/xenia/hid/file/file_input_driver.h index 7e4eacb81..bb8cf333b 100644 --- a/src/xenia/hid/file/file_input_driver.h +++ b/src/xenia/hid/file/file_input_driver.h @@ -139,16 +139,31 @@ class FileInputDriver final : public InputDriver { private: // Re-parse only when the file actually changed: `GetState` is polled every // frame and a stat is far cheaper than a read+parse. + // + // The change test uses **nanosecond** mtime, not `st_mtime`. Whole-second + // granularity plus size looked sufficient and is not: a script that steps a + // menu writes several same-length states per second (`press=A` then `press=B`, + // both 8 bytes), and every one of those after the first would be silently + // dropped. That failure is invisible — the emulator just does not react — so + // it is worth the extra field. void Refresh() { struct stat st; if (::stat(cvars::pad_file.c_str(), &st) != 0) { - Neutral(); + if (present_) { + present_ = false; + Neutral(); + ++packet_; + XELOGI("[file-pad] {} gone -> neutral", cvars::pad_file); + } return; } - if (st.st_mtime == mtime_ && st.st_size == size_) { + if (present_ && st.st_mtim.tv_sec == mtime_sec_ && + st.st_mtim.tv_nsec == mtime_nsec_ && st.st_size == size_) { return; } - mtime_ = st.st_mtime; + present_ = true; + mtime_sec_ = st.st_mtim.tv_sec; + mtime_nsec_ = st.st_mtim.tv_nsec; size_ = st.st_size; std::FILE* f = std::fopen(cvars::pad_file.c_str(), "rb"); if (!f) { @@ -161,6 +176,10 @@ class FileInputDriver final : public InputDriver { buf[n] = '\0'; Parse(buf); ++packet_; + // One line per change (not per frame): with no display to watch, this log is + // the only proof that a scripted press was actually picked up. + XELOGI("[file-pad] #{} buttons={:04X} lt={} rt={} lx={} ly={} rx={} ry={}", + packet_, buttons_, lt_, rt_, lx_, ly_, rx_, ry_); } void Neutral() { @@ -230,7 +249,9 @@ class FileInputDriver final : public InputDriver { uint8_t lt_ = 0, rt_ = 0; int16_t lx_ = 0, ly_ = 0, rx_ = 0, ry_ = 0; uint32_t packet_ = 1; - time_t mtime_ = 0; + bool present_ = false; + time_t mtime_sec_ = 0; + long mtime_nsec_ = -1; off_t size_ = -1; };