# DirectInput Notes

`Hwanse2.exe` imports `DINPUT.dll!DirectInputCreateA`. The import thunk is at
`0x00435da4`, and the confirmed call site is `0x0042eed0`.

This file records the current static trace of the original input setup and the
fixed addresses used by the browser-port input work.

## Import And Entry

`out/exe_imports.json` confirms:

| import | thunk | call site |
| --- | --- | --- |
| `DirectInputCreateA` | `0x00435da4` | `0x0042eed0` |

The call at `0x0042eed0` passes:

```text
push 0
push 0x00526f58
push 0x00000500
push [ebp+0x08]
call DirectInputCreateA
```

`0x00526f58` is the global `IDirectInputA*` output pointer. The version value
`0x0500` indicates DirectInput 5 style APIs.

## Device Setup

The setup routine at `0x0042ef9e` creates two devices from the DirectInput
object at `0x00526f58`.

| address | object | vtable offset | likely method | output |
| --- | --- | ---: | --- | --- |
| `0x0042f0d9` | `IDirectInputA*` | `0x0c` | `CreateDevice` | `0x00526f5c` |
| `0x0042f11d` | `IDirectInputDeviceA*` | `0x2c` | `SetDataFormat` | keyboard/device A |
| `0x0042f154` / `0x0042f174` | `IDirectInputDeviceA*` | `0x34` | `SetCooperativeLevel` | keyboard/device A |
| `0x0042f1a1` | `IDirectInputA*` | `0x0c` | `CreateDevice` | `0x00526f60` |
| `0x0042f1c8` | `IDirectInputDeviceA*` | `0x2c` | `SetDataFormat` | keyboard/device B |
| `0x0042f1f2` | `IDirectInputDeviceA*` | `0x34` | `SetCooperativeLevel` | keyboard/device B |
| `0x0042f214` | `IDirectInputDeviceA*` | `0x1c` | `Acquire` | device B |

The release path uses vtable offset `0x08` and unacquires devices first through
offset `0x20`, which matches `Release` and `Unacquire`.

## Polling

The polling routine starts at `0x0042f4ee`.

For DirectInput mode (`0x0055ba38 == 1`), it reads:

```text
0x0042f51d: device 0x00526f5c GetDeviceState(0x10, 0x0055b9c8)
0x0042f537: device 0x00526f60 GetDeviceState(0x100, 0x0055b868)
```

`0x0055b868` is the 256-byte keyboard state buffer. The code later tests the
high bit (`0x80`) of entries, which is the standard DirectInput pressed-key
convention.

If `GetDeviceState` returns `0x8007001e`, the code attempts to reacquire device
B at `0x0042f56e` and marks `0x0055b9d8` as acquired on success.

For non-DirectInput fallback mode, the same routine calls `GetKeyboardState`
and folds the `0x80` high bit into `0x0055b868`.

## Action Packing

The action packer starts at `0x0042f6d2`. It scans 16 action groups with 8
16-bit entries per group. A zero entry terminates a group early. If any listed
state offset is nonzero, the routine ORs that action bit into the returned
16-bit mask.

The two observed tables are:

| table | VA | generated summary |
| --- | --- | --- |
| primary | `0x00526d58` | `out/input_keymap.md` |
| alternate | `0x00526e58` | `out/input_keymap.md` |

Primary table action bits 0-3 match directional input:

| action | bit | direction | keys |
| ---: | --- | --- | --- |
| 0 | `0x0001` | left | `LEFT`, `NUMPAD_LEFT`, `state+0x110` |
| 1 | `0x0002` | right | `RIGHT`, `NUMPAD_RIGHT`, `state+0x111` |
| 2 | `0x0004` | up | `UP`, `NUMPAD_UP`, `state+0x112` |
| 3 | `0x0008` | down | `DOWN`, `NUMPAD_DOWN`, `state+0x113` |

The remaining action bits line up with the gameplay key notes collected in
`docs/BATTLE_SYSTEM_REFERENCE.md`:

| action | bit | gameplay meaning | keys |
| ---: | --- | --- | --- |
| 4/6/8 | `0x0010` / `0x0040` / `0x0100` | select/confirm variants | `RETURN`, `SPACE`, `Z`, `NUMPAD_ENTER`, extended states |
| 5/7/9 | `0x0020` / `0x0080` / `0x0200` | cancel/back variants | `ESCAPE`, `X`, `NUMPAD_INSERT` (`Numpad 0`), extended states |
| 10 | `0x0400` | skill description/help | `C`, extended state |
| 14 | `0x4000` | battle mode change previous | `PRIOR` (`PageUp`), extended state |
| 15 | `0x8000` | battle mode change next | `NEXT` (`PageDown`), extended state |

Values below `0x0100` are DirectInput DIK offsets into the 256-byte keyboard
state. Values at or above `0x0100` are preserved as raw offsets into the same
combined input state area until the producer routine is named.

## Web Runtime Implications

- The current browser `keydown`/`keyup` set is structurally close to the
  original keyboard state model because both track a pressed/not-pressed bit.
- The original direction/action DIK mapping is now extracted in
  `out/input_keymap.md`; remaining work is naming the `0x0100+` extended state
  offsets and matching the action mask consumers.
- The original code already distinguishes held state from one-shot events, so
  the web runtime's continuous held-key tile stepping is the right direction.
