forked from redcode/SpecEmu
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathJoystick.asm
274 lines (218 loc) · 11.6 KB
/
Joystick.asm
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
PrintSysError PROTO :DWORD
Joy_Left_Press PROTO :PTR
Joy_Right_Press PROTO :PTR
Joy_Up_Press PROTO :PTR
Joy_Down_Press PROTO :PTR
Joy_Button1_Press PROTO :PTR
; ID1/2 defined in windows.inc
JOYSTICKID3 equ JOYSTICKID2+1
JOYSTICKID4 equ JOYSTICKID3+1
align 16
ResetJoystickStates proc
mov Joystick1.Connected, FALSE
mov Joystick2.Connected, FALSE
mov Joystick3.Connected, FALSE
mov Joystick4.Connected, FALSE
ret
ResetJoystickStates endp
align 16
GetJoystickStates proc
ifc keyboard_hasfocus eq FALSE then ret
; ifc ActiveState eq FALSE then ret
mov PORT_1F, 0
mov PORT_37, 0
invoke GetStickState, JOYSTICKID1, addr Joystick1
invoke GetStickState, JOYSTICKID2, addr Joystick2
invoke GetStickState, JOYSTICKID3, addr Joystick3
invoke GetStickState, JOYSTICKID4, addr Joystick4
ret
GetJoystickStates endp
align 16
GetStickState proc uses esi,
joyID: DWORD,
lpJoyInfo: PTR
mov esi, lpJoyInfo
assume esi: ptr JOYSTICKINFO
mov [esi].JoystickInfo.dwSize, sizeof JOYINFOEX
m2m [esi].JoystickInfo.dwFlags, [esi].JoyInfoEx_dwFlags
.if $fnc (joyGetPosEx, joyID, addr [esi].JoystickInfo) == JOYERR_NOERROR
.if [esi].Connected == FALSE
; if joystick wasn't connected during last pass then it's newly connected
; so initialise this joystick's capabilities and deadzones
invoke InitialiseJoystick, joyID, esi
; now mark this joystick as connected
mov [esi].Connected, TRUE
.endif
mov eax, [esi].JoystickInfo.dwXpos
.if eax <= [esi].LeftThreshold
invoke Joy_Left_Press, esi
.endif
mov eax, [esi].JoystickInfo.dwXpos
.if eax >= [esi].RightThreshold
invoke Joy_Right_Press, esi
.endif
mov eax, [esi].JoystickInfo.dwYpos
.if eax <= [esi].UpThreshold
invoke Joy_Up_Press, esi
.endif
mov eax, [esi].JoystickInfo.dwYpos
.if eax >= [esi].DownThreshold
invoke Joy_Down_Press, esi
.endif
test [esi].JoystickInfo.dwButtons, JOY_BUTTON1
.if !ZERO?
invoke Joy_Button1_Press, esi
.endif
switch [esi].Joy_POV_Type
case JOY_POV4DIR
switch [esi].JoystickInfo.dwPOV
case JOY_POVLEFT
invoke Joy_Left_Press, esi
case JOY_POVRIGHT
invoke Joy_Right_Press, esi
case JOY_POVFORWARD
invoke Joy_Up_Press, esi
case JOY_POVBACKWARD
invoke Joy_Down_Press, esi
endsw
case JOY_POVCTS
endsw
.else
mov [esi].Connected, FALSE
.endif
ret
assume esi: nothing
GetStickState endp
align 16
Joy_Left_Press proc lpJoyInfo: PTR
mov eax, lpJoyInfo
switch [eax].JOYSTICKINFO.Joystick_Type
case JOY_SINCLAIR_1
and PORT_EF, NOT (1 shl 4)
case JOY_SINCLAIR_2
and PORT_F7, NOT (1 shl 0)
case JOY_CURSOR
and PORT_F7, NOT (1 shl 4)
case JOY_KEMPSTON_1F
or PORT_1F, 2
case JOY_KEMPSTON_37
or PORT_37, 2
endsw
ret
Joy_Left_Press endp
align 16
Joy_Right_Press proc lpJoyInfo: PTR
mov eax, lpJoyInfo
switch [eax].JOYSTICKINFO.Joystick_Type
case JOY_SINCLAIR_1
and PORT_EF, NOT (1 shl 3)
case JOY_SINCLAIR_2
and PORT_F7, NOT (1 shl 1)
case JOY_CURSOR
and PORT_EF, NOT (1 shl 2)
case JOY_KEMPSTON_1F
or PORT_1F, 1
case JOY_KEMPSTON_37
or PORT_37, 1
endsw
ret
Joy_Right_Press endp
align 16
Joy_Down_Press proc lpJoyInfo: PTR
mov eax, lpJoyInfo
switch [eax].JOYSTICKINFO.Joystick_Type
case JOY_SINCLAIR_1
and PORT_EF, NOT (1 shl 2)
case JOY_SINCLAIR_2
and PORT_F7, NOT (1 shl 2)
case JOY_CURSOR
and PORT_EF, NOT (1 shl 4)
case JOY_KEMPSTON_1F
or PORT_1F, 4
case JOY_KEMPSTON_37
or PORT_37, 4
endsw
ret
Joy_Down_Press endp
align 16
Joy_Up_Press proc lpJoyInfo: PTR
mov eax, lpJoyInfo
switch [eax].JOYSTICKINFO.Joystick_Type
case JOY_SINCLAIR_1
and PORT_EF, NOT (1 shl 1)
case JOY_SINCLAIR_2
and PORT_F7, NOT (1 shl 3)
case JOY_CURSOR
and PORT_EF, NOT (1 shl 3)
case JOY_KEMPSTON_1F
or PORT_1F, 8
case JOY_KEMPSTON_37
or PORT_37, 8
endsw
ret
Joy_Up_Press endp
align 16
Joy_Button1_Press proc lpJoyInfo: PTR
mov eax, lpJoyInfo
switch [eax].JOYSTICKINFO.Joystick_Type
case JOY_SINCLAIR_1
and PORT_EF, NOT (1 shl 0)
case JOY_SINCLAIR_2
and PORT_F7, NOT (1 shl 4)
case JOY_CURSOR
and PORT_EF, NOT (1 shl 0)
case JOY_KEMPSTON_1F
or PORT_1F, 16
case JOY_KEMPSTON_37
or PORT_37, 16
endsw
ret
Joy_Button1_Press endp
align 16
InitialiseJoystick proc uses esi,
joyID: DWORD,
lpJoyInfo: PTR
local XCentre: DWORD,
YCentre: DWORD
mov esi, lpJoyInfo
assume esi: ptr JOYSTICKINFO
.if $fnc (joyGetDevCaps, joyID, addr [esi].joyCaps, sizeof JOYCAPS) == JOYERR_NOERROR
mov XCentre, @EVAL ([esi].joyCaps.wXmin + [esi].joyCaps.wXmax / 2)
mov YCentre, @EVAL ([esi].joyCaps.wYmin + [esi].joyCaps.wYmax / 2)
mov [esi].LeftThreshold, @EVAL ([esi].joyCaps.wXmin + XCentre / 2)
mov [esi].RightThreshold, @EVAL ([esi].joyCaps.wXmax + XCentre / 2)
mov [esi].UpThreshold, @EVAL ([esi].joyCaps.wYmin + YCentre / 2)
mov [esi].DownThreshold, @EVAL ([esi].joyCaps.wYmax + YCentre / 2)
; the info we want returned for this joystick on joyGetPosEx()
mov [esi].JoyInfoEx_dwFlags, JOY_RETURNBUTTONS or JOY_RETURNX or JOY_RETURNY
; see if joystick has a POV, and what type it is
mov [esi].Joy_POV_Type, JOY_POVNONE
test [esi].joyCaps.wCaps, JOYCAPS_HASPOV
.if !ZERO?
test [esi].joyCaps.wCaps, JOYCAPS_POVCTS
.if !ZERO?
mov [esi].Joy_POV_Type, JOY_POVCTS
or [esi].JoyInfoEx_dwFlags, JOY_RETURNPOVCTS ; we want continuous, one-hundredth degree units
.else
test [esi].joyCaps.wCaps, JOYCAPS_POV4DIR
.if !ZERO?
mov [esi].Joy_POV_Type, JOY_POV4DIR
or [esi].JoyInfoEx_dwFlags, JOY_RETURNPOV ; we want discrete units
.endif
.endif
.endif
.endif
ret
assume esi: nothing
InitialiseJoystick endp
align 16
PrintSysError proc error: DWORD
local lpMsgBuf: DWORD
local tstr[32]: byte
invoke FormatMessage, FORMAT_MESSAGE_ALLOCATE_BUFFER or FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, addr lpMsgBuf, 0, NULL
; print lpMsgBuf
invoke dwtoa, error, addr tstr
invoke ShowMessageBox, hWnd, addr tstr, SADD ("blah"), MB_OK or MB_ICONWARNING
invoke LocalFree, lpMsgBuf
ret
PrintSysError endp