Updates for DOS driver from Daniel Borca.
[mesa.git] / src / glut / dos / PC_HW / pc_mouse.c
1 /*
2 * PC/HW routine collection v1.2 for DOS/DJGPP
3 *
4 * Copyright (C) 2002 - Borca Daniel
5 * Email : dborca@yahoo.com
6 * Web : http://www.geocities.com/dborca
7 */
8
9
10 #include <dpmi.h>
11
12 #include "pc_hw.h"
13
14
15
16 #define MOUSE_STACK_SIZE 16384
17
18 #define CLEAR_MICKEYS() \
19 do { \
20 __asm __volatile ("movw $0xb, %%ax; int $0x33":::"%eax", "%ecx", "%edx"); \
21 ox = oy = 0; \
22 } while (0)
23
24 extern void mouse_wrapper (void);
25 extern void mouse_wrapper_end (void);
26
27 static MFUNC mouse_func;
28 static void *mouse_stack;
29 static long mouse_callback;
30 static __dpmi_regs mouse_regs;
31
32 static volatile int pc_mouse_x, pc_mouse_y, pc_mouse_b;
33
34 static int minx = 0;
35 static int maxx = 319;
36 static int miny = 0;
37 static int maxy = 199;
38
39 static int sx = 2;
40 static int sy = 2;
41
42 static int emulat3 = FALSE;
43
44 static int ox, oy;
45
46 static void mouse (__dpmi_regs *r)
47 {
48 int nx = (signed short)r->x.si / sx;
49 int ny = (signed short)r->x.di / sy;
50 int dx = nx - ox;
51 int dy = ny - oy;
52 ox = nx;
53 oy = ny;
54
55 pc_mouse_b = r->x.bx;
56 pc_mouse_x = MID(minx, pc_mouse_x + dx, maxx);
57 pc_mouse_y = MID(miny, pc_mouse_y + dy, maxy);
58
59 if (emulat3) {
60 if ((pc_mouse_b&3)==3) {
61 pc_mouse_b = 4;
62 }
63 }
64
65 if (mouse_func) {
66 mouse_func(pc_mouse_x, pc_mouse_y, pc_mouse_b);
67 }
68 } ENDOFUNC(mouse)
69
70 void pc_remove_mouse (void)
71 {
72 if (mouse_callback) {
73 pc_clexit(pc_remove_mouse);
74 __asm("\n\
75 movl %%edx, %%ecx \n\
76 shrl $16, %%ecx \n\
77 movw $0x0304, %%ax \n\
78 int $0x31 \n\
79 movw $0x000c, %%ax \n\
80 xorl %%ecx, %%ecx \n\
81 int $0x33 \n\
82 "::"d"(mouse_callback):"%eax", "%ecx");
83
84 mouse_callback = 0;
85
86 free((void *)((unsigned long)mouse_stack-MOUSE_STACK_SIZE));
87 }
88 }
89
90 int pc_install_mouse (void)
91 {
92 int buttons;
93
94 /* fail if already call-backed */
95 if (mouse_callback) {
96 return 0;
97 }
98
99 /* reset mouse and get status */
100 __asm("\n\
101 xorl %%eax, %%eax \n\
102 int $0x33 \n\
103 andl %%ebx, %%eax \n\
104 movl %%eax, %0 \n\
105 ":"=g" (buttons)::"%eax", "%ebx");
106 if (!buttons) {
107 return 0;
108 }
109
110 /* lock wrapper */
111 LOCKDATA(mouse_func);
112 LOCKDATA(mouse_stack);
113 LOCKDATA(mouse_callback);
114 LOCKDATA(mouse_regs);
115 LOCKDATA(pc_mouse_x);
116 LOCKDATA(pc_mouse_y);
117 LOCKDATA(pc_mouse_b);
118 LOCKDATA(minx);
119 LOCKDATA(maxx);
120 LOCKDATA(miny);
121 LOCKDATA(maxy);
122 LOCKDATA(sx);
123 LOCKDATA(sy);
124 LOCKDATA(emulat3);
125 LOCKDATA(ox);
126 LOCKDATA(oy);
127 LOCKFUNC(mouse);
128 LOCKFUNC(mouse_wrapper);
129
130 /* grab a locked stack */
131 if ((mouse_stack=pc_malloc(MOUSE_STACK_SIZE))==NULL) {
132 return 0;
133 }
134
135 /* try to hook a call-back */
136 __asm("\n\
137 pushl %%ds \n\
138 pushl %%es \n\
139 movw $0x0303, %%ax \n\
140 pushl %%ds \n\
141 pushl %%cs \n\
142 popl %%ds \n\
143 popl %%es \n\
144 int $0x31 \n\
145 popl %%es \n\
146 popl %%ds \n\
147 jc 0f \n\
148 shll $16, %%ecx \n\
149 movw %%dx, %%cx \n\
150 movl %%ecx, %0 \n\
151 0: \n\
152 ":"=g"(mouse_callback)
153 :"S" (mouse_wrapper), "D"(&mouse_regs)
154 :"%eax", "%ecx", "%edx");
155 if (!mouse_callback) {
156 free(mouse_stack);
157 return 0;
158 }
159
160 /* adjust stack */
161 mouse_stack = (void *)((unsigned long)mouse_stack + MOUSE_STACK_SIZE);
162
163 /* install the handler */
164 mouse_regs.x.ax = 0x000c;
165 mouse_regs.x.cx = 0x007f;
166 mouse_regs.x.dx = mouse_callback&0xffff;
167 mouse_regs.x.es = mouse_callback>>16;
168 __dpmi_int(0x33, &mouse_regs);
169
170 CLEAR_MICKEYS();
171
172 emulat3 = buttons<3;
173 pc_atexit(pc_remove_mouse);
174 return buttons;
175 }
176
177 MFUNC pc_install_mouse_handler (MFUNC handler)
178 {
179 MFUNC old;
180
181 if (!mouse_callback && !pc_install_mouse()) {
182 return NULL;
183 }
184
185 old = mouse_func;
186 mouse_func = handler;
187 return old;
188 }
189
190 void pc_mouse_area (int x1, int y1, int x2, int y2)
191 {
192 minx = x1;
193 maxx = x2;
194 miny = y1;
195 maxy = y2;
196 }
197
198 void pc_mouse_speed (int xspeed, int yspeed)
199 {
200 DISABLE();
201
202 sx = MAX(1, xspeed);
203 sy = MAX(1, yspeed);
204
205 ENABLE();
206 }
207
208 int pc_query_mouse (int *x, int *y)
209 {
210 *x = pc_mouse_x;
211 *y = pc_mouse_y;
212 return pc_mouse_b;
213 }
214
215 void pc_show_mouse (void)
216 {
217 /* not implemented */
218 }
219 void pc_scare_mouse (void)
220 {
221 /* not implemented */
222 }
223 void pc_unscare_mouse (void)
224 {
225 /* not implemented */
226 }
227
228 __asm("\n\
229 .text \n\
230 .balign 4 \n\
231 .global _mouse_wrapper \n\
232 _mouse_wrapper: \n\
233 cld \n\
234 lodsl \n\
235 movl %eax, %es:42(%edi) \n\
236 addw $4, %es:46(%edi) \n\
237 pushl %es \n\
238 movl %ss, %ebx \n\
239 movl %esp, %esi \n\
240 movl %cs:___djgpp_ds_alias, %ss \n\
241 movl %cs:_mouse_stack, %esp \n\
242 pushl %ss \n\
243 pushl %ss \n\
244 popl %es \n\
245 popl %ds \n\
246 movl ___djgpp_dos_sel, %fs \n\
247 pushl %fs \n\
248 popl %gs \n\
249 pushl %edi \n\
250 call _mouse \n\
251 popl %edi \n\
252 movl %ebx, %ss \n\
253 movl %esi, %esp \n\
254 popl %es \n\
255 iret \n\
256 .balign 4 \n\
257 .global _mouse_wrapper_end \n\
258 _mouse_wrapper_end:");