[NTVDM]: Return mouse information for INT 33h, AX=00h. Needed for apps that check...
[reactos.git] / reactos / subsystems / ntvdm / bios / bios32 / moubios32.c
1 /*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: moubios32.c
5 * PURPOSE: VDM Mouse 32-bit BIOS
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #define NDEBUG
12
13 #include "emulator.h"
14 #include "callback.h"
15
16 #include "moubios32.h"
17 #include "bios32p.h"
18
19 #include "io.h"
20 #include "hardware/mouse.h"
21
22 /* PRIVATE VARIABLES **********************************************************/
23
24 static BOOLEAN DriverEnabled = TRUE;
25 static MOUSE_DRIVER_STATE DriverState;
26
27 /* PRIVATE FUNCTIONS **********************************************************/
28
29 static VOID PaintMouseCursor(VOID)
30 {
31 if (Bda->VideoMode <= 3)
32 {
33 WORD Character;
34 DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Bda->VideoPage * Bda->VideoPageSize);
35
36 EmulatorReadMemory(&EmulatorContext,
37 VideoAddress
38 + (DriverState.Position.Y * Bda->ScreenColumns
39 + DriverState.Position.X) * sizeof(WORD),
40 (LPVOID)&Character,
41 sizeof(WORD));
42
43 DriverState.Character = Character;
44 Character &= DriverState.TextCursor.ScreenMask;
45 Character ^= DriverState.TextCursor.CursorMask;
46
47 EmulatorWriteMemory(&EmulatorContext,
48 VideoAddress
49 + (DriverState.Position.Y * Bda->ScreenColumns
50 + DriverState.Position.X) * sizeof(WORD),
51 (LPVOID)&Character,
52 sizeof(WORD));
53 }
54 else
55 {
56 // TODO: NOT IMPLEMENTED
57 UNIMPLEMENTED;
58 }
59 }
60
61 static VOID EraseMouseCursor(VOID)
62 {
63 if (Bda->VideoMode <= 3)
64 {
65 DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Bda->VideoPage * Bda->VideoPageSize);
66
67 EmulatorWriteMemory(&EmulatorContext,
68 VideoAddress
69 + (DriverState.Position.Y * Bda->ScreenColumns
70 + DriverState.Position.X) * sizeof(WORD),
71 (LPVOID)&DriverState.Character,
72 sizeof(WORD));
73 }
74 else
75 {
76 // TODO: NOT IMPLEMENTED
77 UNIMPLEMENTED;
78 }
79 }
80
81 static VOID WINAPI BiosMouseService(LPWORD Stack)
82 {
83 switch (getAX())
84 {
85 /* Reset Driver */
86 case 0x00:
87 {
88 DriverEnabled = TRUE;
89 DriverState.ShowCount = 0;
90
91 /* Set the default text cursor */
92 DriverState.TextCursor.ScreenMask = 0xFFFF; /* Display everything */
93 DriverState.TextCursor.CursorMask = 0xFF00; /* ... but with inverted attributes */
94
95 /* Set the default graphics cursor */
96 DriverState.GraphicsCursor.HotSpot.X = 3;
97 DriverState.GraphicsCursor.HotSpot.Y = 1;
98
99 DriverState.GraphicsCursor.ScreenMask[0] = 0xC3FF; // 1100001111111111
100 DriverState.GraphicsCursor.ScreenMask[1] = 0xC0FF; // 1100000011111111
101 DriverState.GraphicsCursor.ScreenMask[2] = 0xC07F; // 1100000001111111
102 DriverState.GraphicsCursor.ScreenMask[3] = 0xC01F; // 1100000000011111
103 DriverState.GraphicsCursor.ScreenMask[4] = 0xC00F; // 1100000000001111
104 DriverState.GraphicsCursor.ScreenMask[5] = 0xC007; // 1100000000000111
105 DriverState.GraphicsCursor.ScreenMask[6] = 0xC003; // 1100000000000011
106 DriverState.GraphicsCursor.ScreenMask[7] = 0xC007; // 1100000000000111
107 DriverState.GraphicsCursor.ScreenMask[8] = 0xC01F; // 1100000000011111
108 DriverState.GraphicsCursor.ScreenMask[9] = 0xC01F; // 1100000000011111
109 DriverState.GraphicsCursor.ScreenMask[10] = 0xC00F; // 1100000000001111
110 DriverState.GraphicsCursor.ScreenMask[11] = 0xC60F; // 1100011000001111
111 DriverState.GraphicsCursor.ScreenMask[12] = 0xFF07; // 1111111100000111
112 DriverState.GraphicsCursor.ScreenMask[13] = 0xFF07; // 1111111100000111
113 DriverState.GraphicsCursor.ScreenMask[14] = 0xFF87; // 1111111110000111
114 DriverState.GraphicsCursor.ScreenMask[15] = 0xFFCF; // 1111111111001111
115
116 DriverState.GraphicsCursor.CursorMask[0] = 0x0000; // 0000000000000000
117 DriverState.GraphicsCursor.CursorMask[1] = 0x1C00; // 0001110000000000
118 DriverState.GraphicsCursor.CursorMask[2] = 0x1F00; // 0001111100000000
119 DriverState.GraphicsCursor.CursorMask[3] = 0x1F80; // 0001111110000000
120 DriverState.GraphicsCursor.CursorMask[4] = 0x1FE0; // 0001111111100000
121 DriverState.GraphicsCursor.CursorMask[5] = 0x1FF0; // 0001111111110000
122 DriverState.GraphicsCursor.CursorMask[6] = 0x1FF8; // 0001111111111000
123 DriverState.GraphicsCursor.CursorMask[7] = 0x1FE0; // 0001111111100000
124 DriverState.GraphicsCursor.CursorMask[8] = 0x1FC0; // 0001111111000000
125 DriverState.GraphicsCursor.CursorMask[9] = 0x1FC0; // 0001111111000000
126 DriverState.GraphicsCursor.CursorMask[10] = 0x19E0; // 0001100111100000
127 DriverState.GraphicsCursor.CursorMask[11] = 0x00E0; // 0000000011100000
128 DriverState.GraphicsCursor.CursorMask[12] = 0x0070; // 0000000001110000
129 DriverState.GraphicsCursor.CursorMask[13] = 0x0070; // 0000000001110000
130 DriverState.GraphicsCursor.CursorMask[14] = 0x0030; // 0000000000110000
131 DriverState.GraphicsCursor.CursorMask[15] = 0x0000; // 0000000000000000
132
133 /* Return mouse information */
134 setAX(0xFFFF); // Hardware & driver installed
135 setBX(NUM_MOUSE_BUTTONS);
136
137 break;
138 }
139
140 /* Show Mouse Cursor */
141 case 0x01:
142 {
143 DriverState.ShowCount++;
144 if (DriverState.ShowCount > 0) PaintMouseCursor();
145
146 break;
147 }
148
149 /* Hide Mouse Cursor */
150 case 0x02:
151 {
152 DriverState.ShowCount--;
153 if (DriverState.ShowCount <= 0) EraseMouseCursor();
154
155 break;
156 }
157
158 /* Return Position And Button Status */
159 case 0x03:
160 {
161 setBX(DriverState.ButtonState);
162 setCX(DriverState.Position.X);
163 setDX(DriverState.Position.Y);
164
165 break;
166 }
167
168 /* Position Mouse Cursor */
169 case 0x04:
170 {
171 POINT Point;
172
173 Point.x = getCX();
174 Point.y = getDX();
175
176 ClientToScreen(GetConsoleWindow(), &Point);
177 SetCursorPos(Point.x, Point.y);
178
179 break;
180 }
181
182 /* Return Button Press Data */
183 case 0x05:
184 {
185 WORD Button = getBX();
186
187 setAX(DriverState.ButtonState);
188 setBX(DriverState.PressCount[Button]);
189 setCX(DriverState.LastPress[Button].X);
190 setDX(DriverState.LastPress[Button].Y);
191
192 /* Reset the counter */
193 DriverState.PressCount[Button] = 0;
194
195 break;
196 }
197
198 /* Return Button Release Data */
199 case 0x06:
200 {
201 WORD Button = getBX();
202
203 setAX(DriverState.ButtonState);
204 setBX(DriverState.ReleaseCount[Button]);
205 setCX(DriverState.LastRelease[Button].X);
206 setDX(DriverState.LastRelease[Button].Y);
207
208 /* Reset the counter */
209 DriverState.ReleaseCount[Button] = 0;
210
211 break;
212
213 }
214
215 /* Define Graphics Cursor */
216 case 0x09:
217 {
218 PWORD MaskBitmap = (PWORD)SEG_OFF_TO_PTR(getES(), getDX());
219
220 DriverState.GraphicsCursor.HotSpot.X = getBX();
221 DriverState.GraphicsCursor.HotSpot.Y = getCX();
222
223 RtlMoveMemory(DriverState.GraphicsCursor.ScreenMask,
224 MaskBitmap,
225 sizeof(DriverState.GraphicsCursor.ScreenMask));
226
227 RtlMoveMemory(DriverState.GraphicsCursor.CursorMask,
228 &MaskBitmap[16],
229 sizeof(DriverState.GraphicsCursor.CursorMask));
230
231 break;
232 }
233
234 /* Define Text Cursor */
235 case 0x0A:
236 {
237 DriverState.TextCursor.ScreenMask = getCX();
238 DriverState.TextCursor.CursorMask = getDX();
239
240 break;
241 }
242
243 /* Return Driver Storage Requirements */
244 case 0x15:
245 {
246 setBX(sizeof(MOUSE_DRIVER_STATE));
247 break;
248 }
249
250 /* Save Driver State */
251 case 0x16:
252 {
253 *((PMOUSE_DRIVER_STATE)SEG_OFF_TO_PTR(getES(), getDX())) = DriverState;
254 break;
255 }
256
257 /* Restore Driver State */
258 case 0x17:
259 {
260 DriverState = *((PMOUSE_DRIVER_STATE)SEG_OFF_TO_PTR(getES(), getDX()));
261 break;
262 }
263
264 /* Disable Mouse Driver */
265 case 0x1F:
266 {
267 setES(0x0000);
268 setBX(0x0000);
269
270 DriverEnabled = FALSE;
271 break;
272 }
273
274 /* Enable Mouse Driver */
275 case 0x20:
276 {
277 DriverEnabled = TRUE;
278 break;
279 }
280
281 default:
282 {
283 DPRINT1("BIOS Function INT 33h, AX = 0x%04X NOT IMPLEMENTED\n", getAX());
284 }
285 }
286 }
287
288 /* PUBLIC FUNCTIONS ***********************************************************/
289
290 VOID MouseBiosUpdatePosition(PCOORD NewPosition)
291 {
292 if (DriverEnabled && (DriverState.ShowCount > 0))
293 {
294 EraseMouseCursor();
295 DriverState.Position = *NewPosition;
296 PaintMouseCursor();
297 }
298 }
299
300 VOID MouseBiosUpdateButtons(WORD ButtonState)
301 {
302 WORD i;
303
304 if (!DriverEnabled) return;
305
306 for (i = 0; i < NUM_MOUSE_BUTTONS; i++)
307 {
308 BOOLEAN OldState = (DriverState.ButtonState >> i) & 1;
309 BOOLEAN NewState = (ButtonState >> i) & 1;
310
311 if (NewState > OldState)
312 {
313 /* Mouse press */
314 DriverState.PressCount[i]++;
315 DriverState.LastPress[i] = DriverState.Position;
316 }
317 else if (NewState < OldState)
318 {
319 /* Mouse release */
320 DriverState.ReleaseCount[i]++;
321 DriverState.LastRelease[i] = DriverState.Position;
322 }
323 }
324
325 DriverState.ButtonState = ButtonState;
326 }
327
328 BOOLEAN MouseBios32Initialize(VOID)
329 {
330 /* Clear the state */
331 ZeroMemory(&DriverState, sizeof(DriverState));
332
333 /* Initialize the interrupt handler */
334 RegisterBiosInt32(BIOS_MOUSE_INTERRUPT, BiosMouseService);
335
336 return TRUE;
337 }
338
339 VOID MouseBios32Cleanup(VOID)
340 {
341 if (DriverState.ShowCount > 0) EraseMouseCursor();
342 }