[피카츄배구 리버싱] 8

이제 키보드의 입력을 어디서 처리하는지 알아내야합니다. 맨 처음에는 게시글 3에서 본 TranslateMessage()에서 처리할거라고 생각했습니다. 만약 맞다면 실시간으로 키 입력을 감지해야하니 여기에 breakpoint를 걸어넣을 경우 매 순간마다 break이 걸릴 것입니다. 그런데 막상 해보니 그렇지 않았습니다. 뭐 그럴수있지라고 생각하며, all intermodular calls를 확인해보기로 했습니다.



그런데 제가 아는 범위에서 키보드 입력과 관련이 있는게 하나도 없었습니다. 망했습니다. 어쩔 수 없이 코드를 직접 전부 뒤지기로 했고



찾아냈습니다. 뭔가 좀 억울합니다. 저 GetKeyboardState가 왜 all intermodular calls에는 없는걸까요? 뭐 어찌됐던 개고생끝에 입력을 어떻게 처리하는지 알게 되었습니다. GetKeyboardState는 256개의 원소를 가지는 byte 배열의 포인터를 입력받아 각 칸에 키보드의 상태를 알려줍니다. 값은 0, 1, 128, 129중 하나입니다. 예를 들어 a[65]가 0이면 키보드 A가 한번 눌러졌음을 의미합니다. 다시 A를 누를 경우 1이 됩니다. 128와 129는 키보드 A가 눌려있는 상태를 의미합니다.(toggle 상태에 따라 128 혹은 129가 결정되지만 저희에겐 크게 중요한 것이 아닙니다.)
함수를 계속 타고 내려가다보면 sub_409D50에 도달합니다.


a2는 0~7까지의 값이고 v2[0~255]는 GetKeyboardState로 얻어온 상태의 값이 들어가있습니다. 그런데  v3 |= v2[*(&v2[32 * a2 + 256] + v4)] >> 7 << v4; 이라는 코드는 이해가 정말 어렵네요. 동적으로  보겠습니다. 아래의 메모리맵은 this부터 시작하는 메모리의 상태입니다. GetKeyboardState를 함수를 거친 후입니다.


a2가 0인 상황을 생각해보면 43CEB00~43CEB1F까지의 값들을 읽어들여 그 값이 가리키는 인덱스의 값의 최상위비트를 LSB부터 삽입합니다. (즉 GetKeyboardState의 값이 128혹은 129)
현재 43CEB00부분은 RFDGZX... 이렇게 진행되니까, 예를 들어 R, D, Z를 동시에 눌렀으면 리턴값은 0x05가 됩니다.(2진수로 101) 그리고 저포함 아무도 몰랐겠지만 X도 일단 입력 체크를 하고는 있고(X를 실제로 사용하는지는 직접 확인해봐야겠지만) 또 대부분의 사람들은 상하좌우를 RFDG로 쓰고 있지만 RVDF로도 쓸 수 있음을 알 수 있습니다. 제가 원하는 키 셋을 아래에 입력하면 그 키로도 플레이할 수 있겠네요.



실제로 상하좌우를 UJHK, 스파이크를 N으로 하고싶으면 이렇게 메모리값을 건들이면 됩니다. 그런데 지금 보면 1P의 값만 들어있는 것 처럼 보여서 의아할겁니다. 그럼 2P는 어디서 찾을 수 있냐, 바로 sub_401460에서 v3을 이용해 v3=2일 때와 1일 때 2번 루틴을 도는데 이 때 참조하는 주소가 다릅니다. 2P는 아래와 같은 영역을 가집니다.



보면 26 28 25 27 4E 4D(ARROW UP, DOWN, LEFT, RIGHT, N, M)과 68 62 64 66 0D 4D(숫자패드의 8, 숫자패드의 2, 숫자패드의 4, 숫자패드의 6, 엔터, M)입니다.
대부분 2P에서 키보드의 화살표 + 엔터로 게임을 하는데 사실 숫자패드와 N으로도 게임을 할 수 있었네요.


'컴퓨터과학 > 리버싱' 카테고리의 다른 글

[피카츄배구 리버싱] 최종  (8) 2018.03.11
[피카츄배구 리버싱] 7  (0) 2018.03.11
[피카츄배구 리버싱] 6  (0) 2018.03.11
[피카츄배구 리버싱] 5  (0) 2018.03.11
[피카츄배구 리버싱] 4  (0) 2018.03.10
[피카츄배구 리버싱] 3  (0) 2018.03.10
  Comments