6 posts
Day 17 Keyboard Error on WM_KEYUP
Edited by kurorah on Reason: Mistyped
Hello, I've been trying to find this bug in my code to no avail. I found another thread with a similar issue but no real outcome.

My assert is going off on Win32ProcessKeyboardMessage. Casey's code runs fine, mine will run fine only with the debugger when stepping through, any normal run without stepping through throws the exception from the ASSERT macro. Code:
Win32ProcessKeyboardMessage():
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 // ... case WM_SYSKEYDOWN: case WM_SYSKEYUP: case WM_KEYDOWN: case WM_KEYUP: { // 24th bit is extended keys, numpad, right alt & ctrl // 29th bit is context code - alt key down // 30th bit is Previous key state - reapeated keydown is 1 // 31st bit is Transistion state - 0 for down uint32 VKCode = (uint32)Message.wParam; bool32 WasDown = ((Message.lParam & (1 << 30)) != 0); bool32 IsDown = ((Message.lParam & (1 << 31)) == 0); // Ignore duplicate input if (WasDown != IsDown) { //Win32AssignKeyboard(keyboard, VKCode, IsDown); if (VKCode == 'W') { Win32ProcessKeyboardMessage(&keyboard->MoveUp, IsDown); OutputDebugStringA("KEYDOWN\n"); } else if (VKCode == 'A') { Win32ProcessKeyboardMessage(&keyboard->MoveLeft, IsDown); } else if (VKCode == 'S') { Win32ProcessKeyboardMessage(&keyboard->MoveDown, IsDown); } else if (VKCode == 'D') { Win32ProcessKeyboardMessage(&keyboard->MoveRight, IsDown); } } // ... 

WinMain():
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 // ... game_input Input[2] = {}; game_input *NewInput = &Input[0]; game_input *OldInput = &Input[1]; // ... while (Running) { // I've copied Caseys code here and it produces the same error with Old/NewKeyboardController game_controller *Keyboard = &NewInput->Controllers[0]; *Keyboard = {}; Keyboard->IsConnected = true; for (int KeyIndex = 0; KeyIndex < ArrayCount(Keyboard->Buttons); ++KeyIndex) { Keyboard->Buttons[KeyIndex].IsDown = OldInput->Controllers[0].Buttons[KeyIndex].IsDown; } Win32ProcessPendingMessages(Keyboard); // ... game_input *Temp = NewInput; NewInput = OldInput; OldInput = Temp; } 

Any ideas would be greatly appreciated!
Simon Anciaux
1204 posts
Day 17 Keyboard Error on WM_KEYUP
Edited by Simon Anciaux on Reason: typo
There is no assert in the code you shared. Could you share a more complete example ? What is the exact assert that is triggering ?

Debugging keyboard inputs is a bit hard, because when you step in the debugger your application doesn't have the focus and will not get some messages.

A way to debug that is to use a lot of logging to "draw" the path the code takes. Output a string at the start of a frame, at the start of handling messages, after each if involved in that code to make sure it runs as you expected. Also log which message you get, as there are 4 messages going through the same path, and log which key is pressed/released and the value of WasDown, IsDown...
6 posts
Day 17 Keyboard Error on WM_KEYUP
Apologies, this is the assert triggered.
I've added lots of these outputs in the code to diagnose, I left most out of OG post to cut clutter. In the below example (With the Assert in question) the output on a trigger is always 0, 0\n and is always on a WM_KEYUP message. From what I can tell the issue is in the main loop in WinMain() and is initializing my keyboardcontroller incorrectly, causing the MoveUp->IsDown (EndedDown in Caseys) to always be 0.
Somehow the OldInput is always being completely zeroed at the end of my while(Running) loop. I created the same Temp pointer Casey had and still being zeroed. I don't have controller code in my code because I don't have a gamepad to test with, so there is literally nothing else in the program that touches is at this point in time. Any of the code dealing that ever touches my Game_Controller *Keyboard is in main post. Thoughts?
  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 internal void Win32ProcessKeyboardMessage(game_button_state *NewState, bool32 IsDown) { If (NewState->IsDown) OutputDebugStringA("1, "); else OutputDebugStringA("0, "); If (IsDown) OutputDebugStringA("1\n"); else OutputDebugStringA("0\n"); Assert(NewState->IsDown != IsDown); NewState->IsDown = IsDown; ++NewState->HalfTransitionCount; } 
Simon Anciaux
1204 posts
Day 17 Keyboard Error on WM_KEYUP
Why are the ifs in that code capitalized ? Is it a macro ? If so what is it ?

Could it be that your game code modifies the keyboard state instead of just reading it ? You can add something like this to test that (just test 1 key):

 1 2 3 4 5 6 7 /* Just after Win32ProcessPendingMessages */ b32 is_pressed = Keyboard->MoveUp.IsDown; /* Game code here */ /* Just before swapping NewInput and OldInput */ Assert( is_pressed == Keyboard->MoveUp.IsDown ); 

If that triggers, than you need to find which part of the game code modifies the keyboard state. You can do that by setting a data breakpoint on Keyboard->MoveUp.IsDown. You could also comment all the code in the main loop except for the message handling and see if the assert still triggers.

Apart from that, if you can share the whole code, or a striped down version that still has the issues I could take a look.
6 posts
Day 17 Keyboard Error on WM_KEYUP
zip file with code I've removed most of the debug string for this issue to move on for time being and come back to it with a fresh mind after a day or two.
Simon Anciaux
1204 posts
Day 17 Keyboard Error on WM_KEYUP
I tried compiling and testing your code and the assert doesn't trigger. Do you need to do something before for it to trigger or does it always trigger ? Do you use a particular keyboard, or keyboard layout ?

I compiled with Visual Studio 2019, on Windows 7 64bit. Here is the compiled exe if you want to test it on your machine.
6 posts
Day 17 Keyboard Error on WM_KEYUP
Sorry it took me a few days, but I came back to it and found it complies just fine with the build script on its own. I had debugged the project on vscode as opposed to my visual studio 2017 enterprise. The issue was only when using the build task in the .vscode folder which should literally just launch my build.bat then launch the program.