[NTVDM]
[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 break;
134 }
135
136 /* Show Mouse Cursor */
137 case 0x01:
138 {
139 DriverState.ShowCount++;
140 if (DriverState.ShowCount > 0) PaintMouseCursor();
141
142 break;
143 }
144
145 /* Hide Mouse Cursor */
146 case 0x02:
147 {
148 DriverState.ShowCount--;
149 if (DriverState.ShowCount <= 0) EraseMouseCursor();
150
151 break;
152 }
153
154 /* Return Position And Button Status */
155 case 0x03:
156 {
157 setBX(DriverState.ButtonState);
158 setCX(DriverState.Position.X);
159 setDX(DriverState.Position.Y);
160
161 break;
162 }
163
164 /* Position Mouse Cursor */
165 case 0x04:
166 {
167 POINT Point;
168
169 Point.x = getCX();
170 Point.y = getDX();
171
172 ClientToScreen(GetConsoleWindow(), &Point);
173 SetCursorPos(Point.x, Point.y);
174
175 break;
176 }
177
178 /* Return Button Press Data */
179 case 0x05:
180 {
181 WORD Button = getBX();
182
183 setAX(DriverState.ButtonState);
184 setBX(DriverState.PressCount[Button]);
185 setCX(DriverState.LastPress[Button].X);
186 setDX(DriverState.LastPress[Button].Y);
187
188 /* Reset the counter */
189 DriverState.PressCount[Button] = 0;
190
191 break;
192 }
193
194 /* Return Button Release Data */
195 case 0x06:
196 {
197 WORD Button = getBX();
198
199 setAX(DriverState.ButtonState);
200 setBX(DriverState.ReleaseCount[Button]);
201 setCX(DriverState.LastRelease[Button].X);
202 setDX(DriverState.LastRelease[Button].Y);
203
204 /* Reset the counter */
205 DriverState.ReleaseCount[Button] = 0;
206
207 break;
208
209 }
210
211 /* Define Graphics Cursor */
212 case 0x09:
213 {
214 PWORD MaskBitmap = (PWORD)SEG_OFF_TO_PTR(getES(), getDX());
215
216 DriverState.GraphicsCursor.HotSpot.X = getBX();
217 DriverState.GraphicsCursor.HotSpot.Y = getCX();
218
219 RtlMoveMemory(DriverState.GraphicsCursor.ScreenMask,
220 MaskBitmap,
221 sizeof(DriverState.GraphicsCursor.ScreenMask));
222
223 RtlMoveMemory(DriverState.GraphicsCursor.CursorMask,
224 &MaskBitmap[16],
225 sizeof(DriverState.GraphicsCursor.CursorMask));
226
227 break;
228 }
229
230 /* Define Text Cursor */
231 case 0x0A:
232 {
233 DriverState.TextCursor.ScreenMask = getCX();
234 DriverState.TextCursor.CursorMask = getDX();
235
236 break;
237 }
238
239 /* Return Driver Storage Requirements */
240 case 0x15:
241 {
242 setBX(sizeof(MOUSE_DRIVER_STATE));
243 break;
244 }
245
246 /* Save Driver State */
247 case 0x16:
248 {
249 *((PMOUSE_DRIVER_STATE)SEG_OFF_TO_PTR(getES(), getDX())) = DriverState;
250 break;
251 }
252
253 /* Restore Driver State */
254 case 0x17:
255 {
256 DriverState = *((PMOUSE_DRIVER_STATE)SEG_OFF_TO_PTR(getES(), getDX()));
257 break;
258 }
259
260 /* Disable Mouse Driver */
261 case 0x1F:
262 {
263 setES(0x0000);
264 setBX(0x0000);
265
266 DriverEnabled = FALSE;
267 break;
268 }
269
270 /* Enable Mouse Driver */
271 case 0x20:
272 {
273 DriverEnabled = TRUE;
274 break;
275 }
276
277 default:
278 {
279 DPRINT1("BIOS Function INT 33h, AX = 0x%04X NOT IMPLEMENTED\n", getAX());
280 }
281 }
282 }
283
284 /* PUBLIC FUNCTIONS ***********************************************************/
285
286 VOID MouseBiosUpdatePosition(PCOORD NewPosition)
287 {
288 if (DriverEnabled && (DriverState.ShowCount > 0))
289 {
290 EraseMouseCursor();
291 DriverState.Position = *NewPosition;
292 PaintMouseCursor();
293 }
294 }
295
296 VOID MouseBiosUpdateButtons(WORD ButtonState)
297 {
298 WORD i;
299
300 if (!DriverEnabled) return;
301
302 for (i = 0; i < NUM_MOUSE_BUTTONS; i++)
303 {
304 BOOLEAN OldState = (DriverState.ButtonState >> i) & 1;
305 BOOLEAN NewState = (ButtonState >> i) & 1;
306
307 if (NewState > OldState)
308 {
309 /* Mouse press */
310 DriverState.PressCount[i]++;
311 DriverState.LastPress[i] = DriverState.Position;
312 }
313 else if (NewState < OldState)
314 {
315 /* Mouse release */
316 DriverState.ReleaseCount[i]++;
317 DriverState.LastRelease[i] = DriverState.Position;
318 }
319 }
320
321 DriverState.ButtonState = ButtonState;
322 }
323
324 BOOLEAN MouseBios32Initialize(VOID)
325 {
326 /* Clear the state */
327 ZeroMemory(&DriverState, sizeof(DriverState));
328
329 /* Initialize the interrupt handler */
330 RegisterBiosInt32(BIOS_MOUSE_INTERRUPT, BiosMouseService);
331
332 return TRUE;
333 }
334
335 VOID MouseBios32Cleanup(VOID)
336 {
337 if (DriverState.ShowCount > 0) EraseMouseCursor();
338 }