fix problems with msgbuf struct not being defined (d1x r1.4)
[btb/d2x.git] / arch / dos / joy2.asm
1 ;THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
2 ;SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
3 ;END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
4 ;ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
5 ;IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
6 ;SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
7 ;FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
8 ;CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
9 ;AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
10 ;COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
11 ;
12 ; $Source: /cvs/cvsroot/d2x/arch/dos/joy2.asm,v $
13 ; $Revision: 1.3 $
14 ; $Author: bradleyb $
15 ; $Date: 2001-10-24 09:25:05 $
16 ;
17 ; Contains routines for joystick interface.
18 ;
19 ; $Log: not supported by cvs2svn $
20 ; Revision 1.1.1.1  2001/01/19 03:33:43  bradleyb
21 ; Import of d2x-0.0.9-pre1
22 ;
23 ; Revision 1.1.1.1  1999/06/14 21:57:53  donut
24 ; Import of d1x 1.37 source.
25 ;
26 ; Revision 1.17  1995/10/07  13:22:11  john
27 ; Added new method of reading joystick that allows higher-priority
28 ; interrupts to go off.
29
30 ; Revision 1.16  1995/03/30  11:03:30  john
31 ; Made -JoyBios read buttons using BIOS.
32
33 ; Revision 1.15  1995/02/14  11:39:36  john
34 ; Added polled/bios joystick readers..
35
36 ; Revision 1.14  1995/01/29  18:36:00  john
37 ; Made timer count in mode 2 instead of mode 3.
38
39 ; Revision 1.13  1994/12/28  15:32:21  john
40 ; Added code to read joystick axis not all at one time.
41
42 ; Revision 1.12  1994/12/27  15:44:59  john
43 ; Made the joystick timeout be at 1/100th of a second, 
44 ; regardless of CPU speed.
45
46 ; Revision 1.11  1994/11/15  12:04:40  john
47 ; Cleaned up timer code a bit... took out unused functions
48 ; like timer_get_milliseconds, etc.
49
50 ; Revision 1.10  1994/07/01  10:55:54  john
51 ; Fixed some bugs... added support for 4 axis.
52
53 ; Revision 1.9  1994/06/30  20:36:54  john
54 ; Revamped joystick code.
55
56 ; Revision 1.8  1994/04/22  12:52:06  john
57
58 [BITS 32]
59
60 [SECTION .data]
61
62         LastTick        dd      0
63         TotalTicks      dd      0
64
65         global  _joy_bogus_reading
66         global  _joy_retries
67         extern _JOY_PORT
68         _joy_bogus_reading      dd      0
69         _joy_retries            dd      0
70         RetryCount              dd      0
71
72         
73 [SECTION .text]
74
75 ;        JOY_PORT        EQU     0209h
76         TDATA           EQU     40h
77         TCOMMAND        EQU     43h
78
79 joy_get_timer:
80         xor     al, al                  ; Latch timer 0 command
81         out     TCOMMAND, al            ; Latch timer
82         in      al, TDATA               ; Read lo byte
83         mov     ah, al
84         in      al, TDATA               ; Read hi byte
85         xchg    ah, al
86         and     eax, 0ffffh
87         ret     
88
89
90
91
92 global _joy_read_stick_friendly2
93 _joy_read_stick_friendly2:
94                 push    ebx
95                 push    edi
96
97                 mov     ebx,[esp+12]
98                 mov     edi,[esp+16]
99                 mov     ecx,[esp+20]
100
101                 ; ebx = read mask
102                 ; edi = pointer to event buffer
103                 ; ecx = timeout value
104                 ; returns in eax the number of events
105
106                 mov     dword [RetryCount], 0
107                 mov     dword [_joy_bogus_reading], 0
108
109 _joy_read_stick_friendly_retry:
110                 inc     dword [RetryCount]
111                 cmp     dword [RetryCount], 3
112                 jbe     @@f1
113                 mov     dword [_joy_bogus_reading], 1
114                 inc     dword [_joy_retries]
115                 mov     eax, 0
116                 pop     edi
117                 pop     ebx
118                 ret
119
120 @@f1:
121                 push    ecx
122                 push    ebx
123                 push    edi
124
125                 and     ebx, 01111b             ; Make sure we only check the right values                                                                              
126                                                 ; number of events we found will be in bh, so this also clears it to zero.
127
128                 mov     dx, [_JOY_PORT]
129
130                 cli                             ; disable interrupts while reading time...
131                 call    joy_get_timer           ; Returns counter in EAX
132                 sti                             ; enable interrupts after reading time...
133                 mov     dword [LastTick], eax
134
135 waitforstable_f:        in      al, dx
136                 and     al, bl
137                 jz      ready_f                         ; Wait for the port in question to be done reading...
138                 
139                 cli                             ; disable interrupts while reading time...
140                 call    joy_get_timer           ; Returns counter in EAX
141                 sti                             ; enable interrupts after reading time...
142                 xchg    eax, dword [LastTick]
143                 cmp     eax, dword [LastTick]
144                 jb      @@f2
145                 sub     eax, dword [LastTick]
146 @@f2:           ; Higher...
147                 add     dword [TotalTicks], eax
148                 cmp     dword [TotalTicks], ecx         ; Timeout at 1/200'th of a second
149                 jae     ready_f
150                 jmp     waitforstable_f
151                 
152 ready_f:
153                 cli                     
154                 mov     al, 0ffh
155                 out     dx, al                  ; Start joystick a readin'
156
157                 call    joy_get_timer           ; Returns counter in EAX
158                 mov     dword [LastTick], eax
159                 mov     dword [TotalTicks], 0
160                 
161                 mov     [edi], eax              ; Store initial count
162                 add     edi, 4          
163
164 again_f:        in      al, dx                  ; Read Joystick port
165                 not     al
166                 and     al, bl                  ; Mask off channels we don't want to read
167                 jnz     flip_f                  ; See if any of the channels flipped
168
169                 ; none flipped -- check any interrupts...
170                 mov     al, 0Ah
171                 out     20h, al
172                 in      al, 20h         ; Get interrupts pending
173                 cmp     al, 0
174                 je      NoInts
175
176                 ; Need to do an interrupt
177                 sti
178                 nop     ; let the interrupt go on...
179                 cli
180                 
181                 ; See if any axis turned
182                 in      al, dx
183                 not     al
184                 and     al, bl
185                 jz      NoInts
186
187                 ; At this point, an interrupt occured, making one or more
188                 ; of the axis values bogus.  So, we will restart this process...
189
190                 pop     edi
191                 pop     ebx
192                 pop     ecx
193
194                 jmp     _joy_read_stick_friendly_retry
195
196 NoInts:
197                 call    joy_get_timer           ; Returns counter in EAX
198                 
199                 xchg    eax, dword [LastTick]
200                 cmp     eax, dword [LastTick]
201                 jb      @@f3
202                 sub     eax, dword [LastTick]
203 @@f3:           ; Higher...
204                 add     dword [TotalTicks], eax
205                 cmp     dword [TotalTicks], ecx         ; Timeout at 1/200'th of a second
206                 jae     timed_out_f
207                 jmp     again_f
208
209         flip_f: and     eax, 01111b             ; Only care about axis values
210                 mov     [edi], eax              ; Record what channel(s) flipped
211                 add     edi, 4  
212                 xor     bl, al                  ; Unmark the channels that just tripped
213
214                 call    joy_get_timer           ; Returns counter in EAX
215                 mov     [edi], eax              ; Record the time this channel flipped
216                 add     edi, 4          
217                 inc     bh                      ; Increment number of events
218
219                 cmp     bl, 0   
220                 jne     again_f                 ; If there are more channels to read, keep looping
221
222         timed_out_f:
223                 sti
224
225                 movzx   eax, bh                 ; Return number of events
226
227                 pop     edi
228                 pop     ebx
229                 pop     ecx
230
231                 pop     edi
232                 pop     ebx
233                 ret
234
235
236
237 global _joy_read_stick_asm2
238
239 _joy_read_stick_asm2:
240                 push    ebx
241                 push    edi
242
243                 mov     ebx,[esp+12]
244                 mov     edi,[esp+16]
245                 mov     ecx,[esp+20]
246
247                 ; ebx = read mask
248                 ; edi = pointer to event buffer
249                 ; ecx = timeout value
250                 ; returns in eax the number of events
251                 mov     dword [_joy_bogus_reading], 0
252
253                 and     ebx, 01111b             ; Make sure we only check the right values                                                                              
254                                                 ; number of events we found will be in bh, so this also clears it to zero.
255
256                 mov     dx, [_JOY_PORT]
257
258                 cli                             ; disable interrupts while reading time...
259                 call    joy_get_timer           ; Returns counter in EAX
260                 sti                             ; enable interrupts after reading time...
261                 mov     dword [LastTick], eax
262
263 waitforstable:  in      al, dx
264                 and     al, bl
265                 jz      ready                   ; Wait for the port in question to be done reading...
266                 
267                 cli                             ; disable interrupts while reading time...
268                 call    joy_get_timer           ; Returns counter in EAX
269                 sti                             ; enable interrupts after reading time...
270                 xchg    eax, dword [LastTick]
271                 cmp     eax, dword [LastTick]
272                 jb      @@f4
273                 sub     eax, dword [LastTick]
274 @@f4:             ; Higher...
275                 add     dword [TotalTicks], eax
276                 cmp     dword [TotalTicks], ecx         ; Timeout at 1/200'th of a second
277                 jae     ready
278                 jmp     waitforstable
279                 
280 ready:
281                 cli
282                 mov     al, 0ffh
283                 out     dx, al                  ; Start joystick a readin'
284
285                 call    joy_get_timer           ; Returns counter in EAX
286                 mov     dword [LastTick], eax
287                 mov     dword [TotalTicks], 0
288                 
289                 mov     [edi], eax              ; Store initial count
290                 add     edi, 4          
291
292         again:  in      al, dx                  ; Read Joystick port
293                 not     al
294                 and     al, bl                  ; Mask off channels we don't want to read
295                 jnz     flip                    ; See if any of the channels flipped
296
297                 call    joy_get_timer           ; Returns counter in EAX
298                 
299                 xchg    eax, dword [LastTick]
300                 cmp     eax, dword [LastTick]
301                 jb      @@f5
302                 sub     eax, dword [LastTick]
303 @@f5:             ; Higher...
304                 add     dword [TotalTicks], eax
305                 cmp     dword [TotalTicks], ecx         ; Timeout at 1/200'th of a second
306                 jae     timedout
307                 jmp     again
308
309         flip:   and     eax, 01111b             ; Only care about axis values
310                 mov     [edi], eax              ; Record what channel(s) flipped
311                 add     edi, 4  
312                 xor     bl, al                  ; Unmark the channels that just tripped
313
314                 call    joy_get_timer           ; Returns counter in EAX
315                 mov     [edi], eax              ; Record the time this channel flipped
316                 add     edi, 4          
317                 inc     bh                      ; Increment number of events
318
319                 cmp     bl, 0   
320                 jne     again                   ; If there are more channels to read, keep looping
321
322         timedout:
323                 movzx   eax, bh                 ; Return number of events
324
325                 sti
326                 pop     edi
327                 pop     ebx
328                 ret
329
330
331 global _joy_read_stick_polled2
332
333 _joy_read_stick_polled2:
334                 push    ebx
335                 push    edi
336
337                 mov     ebx,[esp+12]
338                 mov     edi,[esp+16]
339                 mov     ecx,[esp+20]
340
341                 ; ebx = read mask
342                 ; edi = pointer to event buffer
343                 ; ecx = timeout value
344                 ; returns in eax the number of events
345                 mov     dword [_joy_bogus_reading], 0
346
347                 and     ebx, 01111b             ; Make sure we only check the right values                                                                              
348                                                 ; number of events we found will be in bh, so this also clears it to zero.
349
350                 mov     dx, [_JOY_PORT]
351
352                 mov     dword [TotalTicks], 0
353
354 waitforstable1: in      al, dx
355                 and     al, bl
356                 jz      ready1                  ; Wait for the port in question to be done reading...
357                 
358                 inc     dword [TotalTicks]
359                 cmp     dword [TotalTicks], ecx         ; Timeout at 1/200'th of a second
360                 jae     ready1
361                 jmp     waitforstable1
362 ready1:
363                 cli
364                 mov     al, 0ffh
365                 out     dx, al                  ; Start joystick a readin'
366
367                 mov     dword [TotalTicks], 0
368
369                 mov     dword [edi], 0              ; Store initial count
370                 add     edi, 4          
371
372         again1: in      al, dx                  ; Read Joystick port
373                 not     al
374                 and     al, bl                  ; Mask off channels we don't want to read
375                 jnz     flip1                   ; See if any of the channels flipped
376
377                 inc     dword [TotalTicks]
378                 cmp     dword [TotalTicks], ecx         ; Timeout at 1/200'th of a second
379                 jae     timedout1
380                 jmp     again1
381
382         flip1:  and     eax, 01111b             ; Only care about axis values
383                 mov     [edi], eax              ; Record what channel(s) flipped
384                 add     edi, 4  
385                 xor     bl, al                  ; Unmark the channels that just tripped
386
387                 mov     eax, dword [TotalTicks]
388                 mov     [edi], eax              ; Record the time this channel flipped
389                 add     edi, 4          
390                 inc     bh                      ; Increment number of events
391
392                 cmp     bl, 0   
393                 jne     again1                  ; If there are more channels to read, keep looping
394
395         timedout1:
396                 movzx   eax, bh                 ; Return number of events
397
398                 sti
399                 pop     edi
400                 pop     ebx
401                 ret
402
403 global _joy_read_stick_bios2
404
405 _joy_read_stick_bios2:
406                 push    ebx
407                 push    edi
408
409                 mov     ebx,[esp+12]
410                 mov     edi,[esp+16]
411                 mov     ecx,[esp+20]
412                 ; ebx = read mask
413                 ; edi = pointer to event buffer
414                 ; ecx = timeout value
415                 ; returns in eax the number of events
416
417                 mov     dword [_joy_bogus_reading], 0
418                 
419                 pusha
420
421                 mov     dword [edi], 0
422                         
423                 mov     eax, 08400h
424                 mov     edx, 1
425                 cli
426                 int     15h
427                 sti
428         
429                 mov     dword [edi+4], 1    ;       Axis 1
430                 and     eax, 0ffffh
431                 mov     [edi+8], eax            ;       Axis 1 value
432
433                 mov     dword [edi+12], 2   ;       Axis 2
434                 and     ebx, 0ffffh
435                 mov     [edi+16], ebx           ;       Axis 2 value
436
437                 mov     dword [edi+20], 4   ;       Axis 3
438                 and     ecx, 0ffffh
439                 mov     [edi+24], ecx           ;       Axis 3 value
440
441                 mov     dword [edi+28], 8   ;       Axis 3
442                 and     edx, 0ffffh
443                 mov     [edi+32], edx           ;       Axis 3 value
444
445                 popa
446                 mov     eax, 4                  ; 4 events
447
448                 pop     edi
449                 pop     ebx
450                 ret
451
452
453 global _joy_read_buttons_bios2
454
455 _joy_read_buttons_bios2:
456                 ; returns in eax the button settings
457                 
458                 push    ebx
459                 push    ecx
460                 push    edx
461                 mov     eax, 08400h
462                 mov     edx, 0  ; Read switches
463                 int     15h
464                 pop     edx
465                 pop     ecx
466                 pop     ebx
467                 
468                 shr     eax, 4
469                 not     eax
470                 and     eax, 01111b
471                 ret
472 global _joy_read_buttons_bios_end2
473 _joy_read_buttons_bios_end2: ; to calculate _joy_read_buttons_bios size
474