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