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