port: EterLib/Input over host key events (DirectInput polling adapted)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
5d64311a4d
commit
32c5a09d6e
@@ -621,3 +621,4 @@
|
|||||||
{"date": "2026-09-30", "unit": "UserInterface/WiseLogicXTrap.cpp", "action": "port", "evidence": "verbatim non-XTRAP build; mapped PORTED"}
|
{"date": "2026-09-30", "unit": "UserInterface/WiseLogicXTrap.cpp", "action": "port", "evidence": "verbatim non-XTRAP build; mapped PORTED"}
|
||||||
{"date": "2026-09-30", "unit": "EterLib/MSWindow.cpp", "action": "port", "evidence": "verbatim over new winuser.h shim (platform/Win32User.cpp); 64-bit pointer casts ADAPTED; port.ms_window"}
|
{"date": "2026-09-30", "unit": "EterLib/MSWindow.cpp", "action": "port", "evidence": "verbatim over new winuser.h shim (platform/Win32User.cpp); 64-bit pointer casts ADAPTED; port.ms_window"}
|
||||||
{"date": "2026-09-30", "unit": "EterLib/MSApplication.cpp", "action": "port", "evidence": "verbatim over new winuser.h shim (platform/Win32User.cpp); 64-bit pointer casts ADAPTED; port.ms_window"}
|
{"date": "2026-09-30", "unit": "EterLib/MSApplication.cpp", "action": "port", "evidence": "verbatim over new winuser.h shim (platform/Win32User.cpp); 64-bit pointer casts ADAPTED; port.ms_window"}
|
||||||
|
{"date": "2026-09-30", "unit": "EterLib/Input.cpp", "action": "port", "evidence": "host key events instead of DirectInput polling; IsPressed/Reset verbatim; port.input"}
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
{
|
||||||
|
"reference": "EterLib/Input.cpp",
|
||||||
|
"reference_sha256": "c913c73d5146584cfb358a73eacca3cb372da1de25b130c72f134422c96682be",
|
||||||
|
"priority": "P4",
|
||||||
|
"contracts": [],
|
||||||
|
"functions": {
|
||||||
|
"CInputDevice::CInputDevice": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/Input.cpp:CInputDevice::CInputDevice"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_input_test.cpp"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"CInputDevice::~CInputDevice": {
|
||||||
|
"status": "ADAPTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/Input.cpp:CInputDevice::~CInputDevice"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_input_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "40250: SAFE_RELEASE(ms_lpDI). Port: no DirectInput object. Invariant: nothing to release."
|
||||||
|
},
|
||||||
|
"CInputDevice::CreateDevice": {
|
||||||
|
"status": "ADAPTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/Input.cpp:CInputDevice::CreateDevice"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_input_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "40250: DirectInput8Create (or AddRef) the shared object, S_OK unless it fails. Port: S_OK. Invariant: keyboard init succeeds."
|
||||||
|
},
|
||||||
|
"CInputKeyboard::CInputKeyboard": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/Input.cpp:CInputKeyboard::CInputKeyboard"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_input_test.cpp"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"CInputKeyboard::~CInputKeyboard": {
|
||||||
|
"status": "ADAPTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/Input.cpp:CInputKeyboard::~CInputKeyboard"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_input_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "40250: Unacquire + release the keyboard device. Port: no device. Invariant: nothing to release."
|
||||||
|
},
|
||||||
|
"CInputKeyboard::ResetKeyboard": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/Input.cpp:CInputKeyboard::ResetKeyboard"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_input_test.cpp"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"CInputKeyboard::InitializeKeyboard": {
|
||||||
|
"status": "ADAPTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/Input.cpp:CInputKeyboard::InitializeKeyboard"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_input_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "40250: create/SetDataFormat/SetCooperativeLevel(FOREGROUND|NONEXCLUSIVE)/Acquire the system keyboard, false on failure. Port: only CreateDevice. Invariant: true, state untouched."
|
||||||
|
},
|
||||||
|
"CInputKeyboard::UpdateKeyboard": {
|
||||||
|
"status": "ADAPTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/Input.cpp:CInputKeyboard::UpdateKeyboard"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_input_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "40250: per-frame GetDeviceState diff -> KeyDown/KeyUp. Port: empty; the host delivers key events (PythonBoot::UIKey) which call KeyDown/KeyUp at event time. Invariant: IsPressed reflects the host's key state."
|
||||||
|
},
|
||||||
|
"CInputKeyboard::KeyDown": {
|
||||||
|
"status": "ADAPTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/Input.cpp:CInputKeyboard::KeyDown"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_input_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "40250: ms_bPressedKey=true; virtual OnKeyDown. Port: records the key (+ ms_diks mirror), range-checked; PythonBoot::UIKey runs OnKeyDown's body (no constructed CPythonApplication to dispatch the virtual). Invariant: IsPressed true, then ESC/RunKeyDown as OnKeyDown."
|
||||||
|
},
|
||||||
|
"CInputKeyboard::KeyUp": {
|
||||||
|
"status": "ADAPTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/Input.cpp:CInputKeyboard::KeyUp"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_input_test.cpp"
|
||||||
|
],
|
||||||
|
"note": "40250: ms_bPressedKey=false; virtual OnKeyUp. Port: as KeyDown, UIKey runs RunKeyUp. Invariant: IsPressed false."
|
||||||
|
},
|
||||||
|
"CInputKeyboard::IsPressed": {
|
||||||
|
"status": "PORTED",
|
||||||
|
"impl": [
|
||||||
|
"src/platform/EterLib/Input.cpp:CInputKeyboard::IsPressed"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"tests/port/port_input_test.cpp"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,81 +1,86 @@
|
|||||||
// Platform skeleton for EterLib/Input.h (40250 EterLib/Input.cpp), generated by platform_stub.py.
|
// 40250 EterLib/Input.cpp without DirectInput. 40250 polls the DirectInput keyboard once per frame
|
||||||
// Every MT_PLATFORM_STUB() body is unimplemented: replace it with the platform implementation.
|
// (CPythonApplication::Process -> UpdateKeyboard), diffs the 256-byte device state against ms_bPressedKey
|
||||||
|
// and calls KeyDown/KeyUp, which record the key and call the virtual OnKeyDown/OnKeyUp.
|
||||||
|
//
|
||||||
|
// PORT: the host delivers key events instead (PythonBoot::UIKey). It calls KeyDown/KeyUp at event time and
|
||||||
|
// then runs the OnKeyDown/OnKeyUp body itself, since the platform has no constructed CPythonApplication to
|
||||||
|
// dispatch the virtual through. ms_diks mirrors the pressed state, as the device state 40250 read.
|
||||||
#include "EterLib/StdAfx.h"
|
#include "EterLib/StdAfx.h"
|
||||||
#include "EterLib/Input.h"
|
#include "EterLib/Input.h"
|
||||||
|
|
||||||
#include "../PlatformStub.h"
|
LPDIRECTINPUT8 CInputDevice::ms_lpDI = NULL;
|
||||||
|
LPDIRECTINPUTDEVICE8 CInputKeyboard::ms_lpKeyboard = NULL;
|
||||||
|
bool CInputKeyboard::ms_bPressedKey[256];
|
||||||
|
char CInputKeyboard::ms_diks[256];
|
||||||
|
|
||||||
CInputDevice::CInputDevice()
|
CInputDevice::CInputDevice()
|
||||||
{
|
{
|
||||||
MT_PLATFORM_STUB();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PORT: 40250 releases the shared DirectInput object; there is none.
|
||||||
CInputDevice::~CInputDevice()
|
CInputDevice::~CInputDevice()
|
||||||
{
|
{
|
||||||
MT_PLATFORM_STUB();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CInputDevice::CreateDevice(HWND) -> HRESULT
|
// PORT: 40250 creates (or AddRefs) the shared DirectInput8 object; the host keyboard needs none.
|
||||||
|
HRESULT CInputDevice::CreateDevice(HWND /*hWnd*/)
|
||||||
{
|
{
|
||||||
MT_PLATFORM_STUB();
|
return S_OK;
|
||||||
return mt_platform_stub_return<HRESULT>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
decltype(CInputDevice::ms_lpDI) CInputDevice::ms_lpDI{};
|
|
||||||
|
|
||||||
CInputKeyboard::CInputKeyboard()
|
CInputKeyboard::CInputKeyboard()
|
||||||
{
|
{
|
||||||
MT_PLATFORM_STUB();
|
ResetKeyboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PORT: 40250 unacquires and releases the keyboard device; there is none.
|
||||||
CInputKeyboard::~CInputKeyboard()
|
CInputKeyboard::~CInputKeyboard()
|
||||||
{
|
{
|
||||||
MT_PLATFORM_STUB();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CInputKeyboard::InitializeKeyboard(HWND) -> bool
|
void CInputKeyboard::ResetKeyboard()
|
||||||
{
|
{
|
||||||
ResetKeyboard();
|
memset(ms_diks, 0, sizeof(ms_diks));
|
||||||
|
memset(ms_bPressedKey, 0, sizeof(ms_bPressedKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
// PORT: 40250 creates the system keyboard device (c_dfDIKeyboard, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE)
|
||||||
|
// and acquires it; it fails only if DirectInput does.
|
||||||
|
bool CInputKeyboard::InitializeKeyboard(HWND hWnd)
|
||||||
|
{
|
||||||
|
if (FAILED(CreateDevice(hWnd)))
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CInputKeyboard::UpdateKeyboard() -> void
|
// PORT: no device state to poll; the host's key events have already called KeyDown/KeyUp.
|
||||||
|
void CInputKeyboard::UpdateKeyboard()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CInputKeyboard::ResetKeyboard() -> void
|
// PORT: 40250 sets ms_bPressedKey and calls OnKeyDown; the caller (PythonBoot::UIKey) runs OnKeyDown's body.
|
||||||
|
void CInputKeyboard::KeyDown(int iIndex)
|
||||||
{
|
{
|
||||||
memset(ms_bPressedKey, 0, sizeof(ms_bPressedKey));
|
if (iIndex < 0 || iIndex >= 256)
|
||||||
memset(ms_diks, 0, sizeof(ms_diks));
|
return;
|
||||||
|
|
||||||
|
ms_bPressedKey[iIndex] = true;
|
||||||
|
ms_diks[iIndex] = (char) 0x80;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CInputKeyboard::IsPressed(int iIndex) -> bool
|
// PORT: as KeyDown, for OnKeyUp.
|
||||||
|
void CInputKeyboard::KeyUp(int iIndex)
|
||||||
{
|
{
|
||||||
if (iIndex >= 0 && iIndex < 256)
|
if (iIndex < 0 || iIndex >= 256)
|
||||||
return (ms_diks[iIndex] & 0x80) != 0;
|
return;
|
||||||
return false;
|
|
||||||
|
ms_bPressedKey[iIndex] = false;
|
||||||
|
ms_diks[iIndex] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CInputKeyboard::KeyDown(int iIndex) -> void
|
bool CInputKeyboard::IsPressed(int iIndex)
|
||||||
{
|
{
|
||||||
if (iIndex >= 0 && iIndex < 256)
|
return ms_bPressedKey[iIndex];
|
||||||
{
|
|
||||||
ms_bPressedKey[iIndex] = true;
|
|
||||||
ms_diks[iIndex] = (char)0x80;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CInputKeyboard::KeyUp(int iIndex) -> void
|
|
||||||
{
|
|
||||||
if (iIndex >= 0 && iIndex < 256)
|
|
||||||
{
|
|
||||||
ms_bPressedKey[iIndex] = false;
|
|
||||||
ms_diks[iIndex] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
decltype(CInputKeyboard::ms_lpKeyboard) CInputKeyboard::ms_lpKeyboard{};
|
|
||||||
|
|
||||||
decltype(CInputKeyboard::ms_bPressedKey) CInputKeyboard::ms_bPressedKey{};
|
|
||||||
|
|
||||||
decltype(CInputKeyboard::ms_diks) CInputKeyboard::ms_diks{};
|
|
||||||
|
|||||||
@@ -205,6 +205,9 @@ if(BUILD_TESTING AND CMAKE_SYSTEM_NAME STREQUAL CMAKE_HOST_SYSTEM_NAME)
|
|||||||
add_executable(port_ms_window_test ${PROJECT_SOURCE_DIR}/tests/port/port_ms_window_test.cpp)
|
add_executable(port_ms_window_test ${PROJECT_SOURCE_DIR}/tests/port/port_ms_window_test.cpp)
|
||||||
target_link_libraries(port_ms_window_test PRIVATE port_platform)
|
target_link_libraries(port_ms_window_test PRIVATE port_platform)
|
||||||
add_test(NAME port.ms_window COMMAND $<TARGET_FILE:port_ms_window_test>)
|
add_test(NAME port.ms_window COMMAND $<TARGET_FILE:port_ms_window_test>)
|
||||||
|
add_executable(port_input_test ${PROJECT_SOURCE_DIR}/tests/port/port_input_test.cpp)
|
||||||
|
target_link_libraries(port_input_test PRIVATE port_platform)
|
||||||
|
add_test(NAME port.input COMMAND $<TARGET_FILE:port_input_test>)
|
||||||
|
|
||||||
# MilesLib: the 40250 sound managers over the Miles emulation (platform/MilesLib/MilesAil.cpp).
|
# MilesLib: the 40250 sound managers over the Miles emulation (platform/MilesLib/MilesAil.cpp).
|
||||||
add_executable(port_miles_test ${PROJECT_SOURCE_DIR}/tests/port/port_miles_test.cpp)
|
add_executable(port_miles_test ${PROJECT_SOURCE_DIR}/tests/port/port_miles_test.cpp)
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
// 40250 CInputKeyboard with host key events in place of DirectInput polling (platform/EterLib/Input.cpp).
|
||||||
|
#include "EterLib/StdAfx.h"
|
||||||
|
#include "EterLib/Input.h"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct Keyboard : CInputKeyboard
|
||||||
|
{
|
||||||
|
int downs = 0, ups = 0;
|
||||||
|
void OnKeyDown(int) override { ++downs; }
|
||||||
|
void OnKeyUp(int) override { ++ups; }
|
||||||
|
char Diks(int i) const { return ms_diks[i]; }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int failures = 0;
|
||||||
|
auto check = [&failures](bool ok, const char *name) {
|
||||||
|
if (!ok) {
|
||||||
|
std::fprintf(stderr, "FAIL %s\n", name);
|
||||||
|
++failures;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Keyboard kb;
|
||||||
|
check(kb.InitializeKeyboard(NULL), "InitializeKeyboard");
|
||||||
|
kb.KeyDown(DIK_LCONTROL);
|
||||||
|
check(kb.IsPressed(DIK_LCONTROL) && (kb.Diks(DIK_LCONTROL) & 0x80), "KeyDown records the key and the device byte");
|
||||||
|
kb.UpdateKeyboard();
|
||||||
|
check(kb.IsPressed(DIK_LCONTROL) && kb.downs == 0 && kb.ups == 0, "UpdateKeyboard neither polls nor dispatches");
|
||||||
|
kb.KeyUp(DIK_LCONTROL);
|
||||||
|
check(!kb.IsPressed(DIK_LCONTROL) && kb.Diks(DIK_LCONTROL) == 0, "KeyUp");
|
||||||
|
kb.KeyDown(-1);
|
||||||
|
kb.KeyDown(256);
|
||||||
|
kb.KeyDown(DIK_A);
|
||||||
|
Keyboard other; // the state is static: a new keyboard resets it, as in 40250
|
||||||
|
check(!kb.IsPressed(DIK_A), "constructor ResetKeyboard clears the shared state");
|
||||||
|
return failures ? 1 : 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user