push 9eb9af089d68d39110a91889d3a673043db63c4b
[wine/hacks.git] / dlls / winedos / int10.c
blobfbe04eb4c857a7058b8d1118001834b252cd7b05
1 /*
2 * BIOS interrupt 10h handler
4 * Copyright 1998 Ove Kåven
5 * Copyright 1998 Joseph Pranevich
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
24 #include <stdlib.h>
26 #include "vga.h"
27 #include "wine/debug.h"
28 #include "dosexe.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(int);
33 * Display combination code for active display.
35 * Values (hex):
36 * 00 - no display
37 * 01 - monochrome adapter w/ monochrome display
38 * 02 - CGA w/ color display
39 * 03 - reserved
40 * 04 - EGA w/ color display
41 * 05 - EGA w/ monochrome display
42 * 06 - PGA w/ color display
43 * 07 - VGA w/ monochrome analog display
44 * 08 - VGA w/ color analog display
45 * 09 - reserved
46 * 0A - MCGA w/ digital color display
47 * 0B - MCGA w/ monochrome analog display
48 * 0C - MCGA w/ color analog display
49 * FF - unknown display type
51 #define INT10_DCC 0x08
53 #include "pshpack1.h"
56 * Structure for DOS data that can be accessed directly from applications.
57 * This structure must be correctly packed.
59 typedef struct _INT10_HEAP {
60 BYTE StaticModeSupport[7]; /* modes supported 1..7 */
61 BYTE StaticScanlineSupport; /* scan lines supported */
62 BYTE StaticNumberCharBlocks; /* total number of char blocks */
63 BYTE StaticActiveCharBlocks; /* max number of active char blocks */
64 WORD StaticMiscFlags; /* misc function support flags */
65 WORD StaticReserved1; /* reserved */
66 BYTE StaticSavePointerFlags; /* save pointer function flags */
67 BYTE StaticReserved2; /* reserved */
69 WORD VesaCurrentMode;
70 WORD VesaModeList[64];
71 char VesaOEMName[32];
72 char VesaProductName[32];
73 char VesaProductRev[32];
74 char VesaVendorName[32];
76 WORD WineHeapSegment;
77 } INT10_HEAP;
80 * Structure for VBE Mode Info Block. See the VBE 3.0 standard for details.
81 * This structure must be correctly packed.
83 struct _ModeInfoBlock {
84 WORD ModeAttributes; /* 0x00 */
85 BYTE WinAAttributes; /* 0x02 */
86 BYTE WinBAttributes; /* 0x03 */
87 WORD WinGranularity; /* 0x04 */
88 WORD WinSize; /* 0x06 */
89 WORD WinASegment; /* 0x08 */
90 WORD WinBSegment; /* 0x0A */
91 DWORD WinFuncPtr; /* 0x0C */
92 WORD BytesPerScanLine; /* 0x10 */
93 /* mandatory for VBE 1.2+ */
94 WORD XResolution; /* 0x12 */
95 WORD YResolution; /* 0x14 */
96 BYTE XCharSize; /* 0x16 */
97 BYTE YCharSize; /* 0x17 */
98 BYTE NumberOfPlanes; /* 0x18 */
99 BYTE BitsPerPixel; /* 0x19 */
100 BYTE NumberOfBanks; /* 0x1A */
101 BYTE MemoryModel; /* 0x1B */
102 BYTE BankSize; /* 0x1C */
103 BYTE NumberOfImagePages; /* 0x1D */
104 BYTE Reserved1; /* 0x1E */
105 BYTE RedMaskSize; /* 0x1F */
106 BYTE RedFieldPosition; /* 0x20 */
107 BYTE GreenMaskSize; /* 0x21 */
108 BYTE GreenFieldPosition; /* 0x22 */
109 BYTE BlueMaskSize; /* 0x23 */
110 BYTE BlueFieldPosition; /* 0x24 */
111 BYTE RsvdMaskSize; /* 0x25 */
112 BYTE RsvdFieldPosition; /* 0x26 */
113 BYTE DirectColorModeInfo; /* 0x27 */
114 /* mandatory for VBE 2.0+ */
115 DWORD PhysBasePtr; /* 0x28 */
116 DWORD Reserved2; /* 0x2C */
117 WORD Reserved3; /* 0x30 */
118 /* mandatory for VBE 3.0+ */
119 WORD LinBytesPerScanLine; /* 0x32 */
120 BYTE BnkNumberOfImagePages;/* 0x34 */
121 BYTE LinNumberOfImagePages;/* 0x35 */
122 BYTE LinRedMaskSize; /* 0x36 */
123 BYTE LinRedFieldPosition; /* 0x37 */
124 BYTE LinGreenMaskSize; /* 0x38 */
125 BYTE LinGreenFieldPosition;/* 0x39 */
126 BYTE LinBlueMaskSize; /* 0x3A */
127 BYTE LinBlueFieldPosition; /* 0x3B */
128 BYTE LinRsvdMaskSize; /* 0x3C */
129 BYTE LinRsvdFieldPosition; /* 0x3D */
130 DWORD MaxPixelClock; /* 0x3E */
131 BYTE Reserved4[190]; /* 0x42 */
134 #include "poppack.h"
136 /* VGA VESA definitions */
137 enum modetype {TEXT=0, GRAPHIC=1};
139 * Wine internal information about video modes.
141 typedef struct {
142 WORD Mode;
143 BOOL ModeType;
144 WORD TextCols; /* columns of text in display */
145 WORD TextRows; /* rows of text in display */
146 WORD CharWidth;
147 WORD CharHeight;
148 WORD Width; /* width of display in pixels */
149 WORD Height; /* height of display in pixels */
150 WORD Depth; /* bits per pixel */
151 WORD Colors; /* total available colors */
152 WORD ScreenPages;
153 BOOL Supported;
154 } INT10_MODE;
158 * List of supported video modes.
160 * should be expanded to contain most or all information
161 * as required for SVGA VESA mode info block for VESA BIOS subsystem 1 (see _ModeInfoBlock)
162 * this will allow proper support for FIXME items in VGA/VESA mode configuration
164 * FIXME - verify and define support for VESA modes
165 * FIXME - add # bit planes, # video memory banks, & memory model
167 static const INT10_MODE INT10_modelist[] =
169 /* VGA modes */
170 {0x0000, TEXT, 40, 25, 9, 16, 360, 400, 0, 16, 8, TRUE}, /* VGA text mode 0 */
171 {0x0001, TEXT, 40, 25, 9, 16, 360, 400, 0, 16, 8, TRUE}, /* VGA text mode 1 */
172 {0x0002, TEXT, 80, 25, 9, 16, 360, 400, 0, 16, 8, TRUE}, /* VGA text mode 2 */
173 {0x0003, TEXT, 80, 25, 9, 16, 360, 400, 0, 16, 8, TRUE}, /* VGA text mode 3 */
174 {0x0004, GRAPHIC, 40, 25, 8, 8, 320, 200, 2, 4, 1, TRUE}, /* VGA graphics mode 4 */
175 {0x0005, GRAPHIC, 40, 25, 8, 8, 320, 200, 2, 4, 1, FALSE}, /* VGA graphics mode 5 */
176 {0x0006, GRAPHIC, 80, 25, 8, 8, 640, 200, 1, 2, 1, FALSE}, /* VGA graphics mode 6 */
177 {0x0007, TEXT, 80, 25, 9, 16, 720, 400, 0, 0, 8, FALSE}, /* VGA text mode 7 - FIXME bad default address */
178 {0x000d, GRAPHIC, 40, 25, 8, 8, 320, 200, 4, 16, 8, FALSE}, /* VGA graphics mode 13 */
179 {0x000e, GRAPHIC, 80, 25, 8, 8, 640, 200, 4, 16, 4, FALSE}, /* VGA graphics mode 14 */
180 {0x000f, GRAPHIC, 80, 25, 8, 14, 640, 350, 0, 0, 2, FALSE}, /* VGA graphics mode 15 */
181 {0x0010, GRAPHIC, 80, 25, 8, 14, 640, 350, 4, 16, 2, FALSE}, /* VGA graphics mode 16 */
182 {0x0012, GRAPHIC, 80, 30, 8, 16, 640, 480, 1, 2, 1, FALSE}, /* VGA graphics mode 17 */
183 {0x0012, GRAPHIC, 80, 30, 8, 16, 640, 480, 4, 16, 1, FALSE}, /* VGA graphics mode 18 */
184 {0x0013, GRAPHIC, 40, 25, 8, 8, 320, 200, 8, 256, 1, TRUE}, /* VGA graphics mode 19 */
185 /* VESA 7-bit modes */
186 {0x006a, GRAPHIC, 0, 0, 0, 0, 800, 600, 4, 16, 1, TRUE}, /* VESA graphics mode, same as 0x102 */
187 /* VESA 15-bit modes */
188 {0x0100, GRAPHIC, 0, 0, 0, 0, 640, 400, 8, 256, 1, TRUE}, /* VESA graphics mode */
189 {0x0101, GRAPHIC, 0, 0, 0, 0, 640, 480, 8, 256, 1, TRUE}, /* VESA graphics mode */
190 {0x0102, GRAPHIC, 0, 0, 0, 0, 800, 600, 4, 16, 1, TRUE}, /* VESA graphics mode */
191 {0x0103, GRAPHIC, 0, 0, 0, 0, 800, 600, 8, 256, 1, TRUE}, /* VESA graphics mode */
192 {0x0104, GRAPHIC, 0, 0, 0, 0, 1024, 768, 4, 16, 1, TRUE}, /* VESA graphics mode */
193 {0x0105, GRAPHIC, 0, 0, 0, 0, 1024, 768, 8, 256, 1, TRUE}, /* VESA graphics mode */
194 {0x0106, GRAPHIC, 0, 0, 0, 0, 1280, 1024, 4, 16, 1, TRUE}, /* VESA graphics mode */
195 {0x0107, GRAPHIC, 0, 0, 0, 0, 1280, 1024, 8, 256, 1, TRUE}, /* VESA graphics mode */
196 {0x0108, TEXT, 0, 0, 0, 0, 80, 60, 0, 0, 1, TRUE}, /* VESA text mode */
197 {0x0109, TEXT, 0, 0, 0, 0, 132, 25, 0, 0, 1, TRUE}, /* VESA text mode */
198 {0x010a, TEXT, 0, 0, 0, 0, 132, 43, 0, 0, 1, TRUE}, /* VESA text mode */
199 {0x010b, TEXT, 0, 0, 0, 0, 132, 50, 0, 0, 1, TRUE}, /* VESA text mode */
200 {0x010c, TEXT, 0, 0, 0, 0, 132, 60, 0, 0, 1, TRUE}, /* VESA text mode */
201 /* VESA 1.2 modes */
202 {0x010d, GRAPHIC, 0, 0, 0, 0, 320, 200, 15, 0, 1, TRUE}, /* VESA graphics mode, 32K colors */
203 {0x010e, GRAPHIC, 0, 0, 0, 0, 320, 200, 16, 0, 1, TRUE}, /* VESA graphics mode, 64K colors */
204 {0x010f, GRAPHIC, 0, 0, 0, 0, 320, 200, 24, 0, 1, TRUE}, /* VESA graphics mode, 16.8 Million colors */
205 {0x0110, GRAPHIC, 0, 0, 0, 0, 640, 480, 15, 0, 1, TRUE}, /* VESA graphics mode, 32K colors */
206 {0x0111, GRAPHIC, 0, 0, 0, 0, 640, 480, 16, 0, 1, TRUE}, /* VESA graphics mode, 64K colors */
207 {0x0112, GRAPHIC, 0, 0, 0, 0, 640, 480, 24, 0, 1, TRUE}, /* VESA graphics mode, 16.8 Million colors */
208 {0x0113, GRAPHIC, 0, 0, 0, 0, 800, 600, 15, 0, 1, TRUE}, /* VESA graphics mode, 32K colors */
209 {0x0114, GRAPHIC, 0, 0, 0, 0, 800, 600, 16, 0, 1, TRUE}, /* VESA graphics mode, 64K colors */
210 {0x0115, GRAPHIC, 0, 0, 0, 0, 800, 600, 24, 0, 1, TRUE}, /* VESA graphics mode, 16.8 Million colors */
211 {0x0116, GRAPHIC, 0, 0, 0, 0, 1024, 768, 15, 0, 1, TRUE}, /* VESA graphics mode, 32K colors */
212 {0x0117, GRAPHIC, 0, 0, 0, 0, 1024, 768, 16, 0, 1, TRUE}, /* VESA graphics mode, 64K colors */
213 {0x0118, GRAPHIC, 0, 0, 0, 0, 1024, 768, 24, 0, 1, TRUE}, /* VESA graphics mode, 16.8 Million colors */
214 {0x0119, GRAPHIC, 0, 0, 0, 0, 1280, 1024, 15, 0, 1, TRUE}, /* VESA graphics mode, 32K colors */
215 {0x011a, GRAPHIC, 0, 0, 0, 0, 1280, 1024, 16, 0, 1, TRUE}, /* VESA graphics mode, 64K colors */
216 {0x011b, GRAPHIC, 0, 0, 0, 0, 1280, 1024, 24, 0, 1, TRUE}, /* VESA graphics mode, 16.8 Million colors */
217 {0xffff, TEXT, 0, 0, 0, 0, 0, 0, 0, 0, 1, FALSE}
220 /* True if video mode is a vesa mode, false otherwise.
221 * More correct would be to use something like (x > 0xff || x == 0x6a)
222 * but as long as we have only the standard VGA and VESA modes this is ok too */
223 #define IS_VESA_MODE(x) ((x) >= 0x6a)
225 /* Forward declarations. */
226 static INT10_HEAP *INT10_GetHeap(void);
227 static void INT10_SetCursorPos(BIOSDATA*, unsigned, unsigned, unsigned);
230 /**********************************************************************
231 * INT10_FindMode
233 static const INT10_MODE *INT10_FindMode( WORD mode )
235 const INT10_MODE *ptr = INT10_modelist;
238 * Filter out flags.
240 mode &= 0x17f;
242 while (ptr->Mode != 0xffff)
244 if (ptr->Mode == mode)
245 return ptr;
246 ptr++;
249 return NULL;
253 /**********************************************************************
254 * INT10_FillControllerInformation
256 * Fill 256-byte (VBE1.x) or 512-byte buffer (VBE2.0+) with
257 * capabilities of the video controller.
259 static void INT10_FillControllerInformation( BYTE *buffer )
261 INT10_HEAP *heap = INT10_GetHeap();
263 /* 00 - BYTE[4]: signature */
264 memmove( buffer, "VESA", 4 );
266 /* 04 - WORD: version number */
267 *(WORD*)(buffer + 4) = 0x0300; /* version 3.0 */
269 /* 06 - DWORD: pointer to OEM name */
270 *(SEGPTR*)(buffer + 6) = MAKESEGPTR( heap->WineHeapSegment,
271 offsetof(INT10_HEAP,
272 VesaOEMName) );
275 * 10 - DWORD: capabilities flags
276 * Bits:
277 * 0 - DAC can be switched into 8-bit mode
278 * 1 - non-VGA controller
279 * 2 - programmed DAC with blank bit
280 * 3 - controller supports hardware stereoscopic signalling
281 * 4 - =0 stereo signalling via external VESA stereo connector
282 * =1 stereo signalling via VESA EVC connector
283 * 5 - controller supports hardware mouse cursor
284 * 6 - controller supports hardware clipping
285 * 7 - controller supports transparent BitBLT
286 * 8-31 - reserved (0)
288 *(DWORD*)(buffer + 10) = 0; /* FIXME */
290 /* 14 - DWORD: pointer to list of supported VESA and OEM video modes */
291 *(SEGPTR*)(buffer + 14) = MAKESEGPTR( heap->WineHeapSegment,
292 offsetof(INT10_HEAP,
293 VesaModeList) );
295 /* 18 - WORD: total amount of video memory in 64K blocks */
296 *(WORD*)(buffer + 18) = 16; /* FIXME */
298 /* 20 - WORD: OEM software version (BCD, high byte = major) */
299 *(WORD*)(buffer + 20) = 0x0100; /* version 1.0 */
301 /* 22 - DWORD: pointer to vendor name */
302 *(SEGPTR*)(buffer + 22) = MAKESEGPTR( heap->WineHeapSegment,
303 offsetof(INT10_HEAP,
304 VesaVendorName) );
306 /* 26 - DWORD: pointer to product name */
307 *(SEGPTR*)(buffer + 26) = MAKESEGPTR( heap->WineHeapSegment,
308 offsetof(INT10_HEAP,
309 VesaProductName) );
311 /* 30 - DWORD: pointer to product revision string */
312 *(SEGPTR*)(buffer + 30) = MAKESEGPTR( heap->WineHeapSegment,
313 offsetof(INT10_HEAP,
314 VesaProductRev) );
316 /* 34 - WORD: VBE/AF version (if capabilities bit 3 set) */
317 *(WORD*)(buffer + 34) = 0;
320 * 36 - DWORD: pointer to list of accelerated modes
321 * (if capabilities bit 3 set)
323 *(SEGPTR*)(buffer + 36) = 0;
325 /* 40 - BYTE[216]: reserved for VBE implementation, set to zero */
326 memset( buffer + 40, 0, 216 );
329 * 256 - BYTE[256]: reserved for VBE3.0 implementation,
330 * ignored in order to support older programs
335 /**********************************************************************
336 * INT10_FillModeInformation
338 * Fill 256-byte buffer with extended information about display mode.
340 * Returns FALSE if mode is unknown and TRUE is mode is known
341 * even if it is not supported.
343 static BOOL INT10_FillModeInformation( struct _ModeInfoBlock *mib, WORD mode )
345 const INT10_MODE *ptr = INT10_FindMode( mode );
346 if (!ptr)
347 return FALSE;
350 * 00 - WORD: mode attributes
351 * Bits:
352 * 0 - Mode supported by present hardware configuration.
353 * 1 - Optional information available. Must be =1 for VBE v1.2+.
354 * 2 - BIOS output supported.
355 * Int10 functions 01, 02, 06, 07, 09, 0a and 0e are supported.
356 * 3 - Set if color, clear if monochrome.
357 * 4 - Set if graphics mode, clear if text mode.
358 * 5 - Mode is not VGA-compatible if set.
359 * VGA-compatible modes support standard VGA I/O ports.
360 * 6 - Bank-switched (or windowed) mode is not supported if set.
361 * 7 - Linear framebuffer mode supported.
362 * 8 - Double scanning supported.
363 * 9 - Interlaced operation supported.
364 * 10 - Triple buffering supported.
365 * 11 - Stereoscopic display supported.
366 * 12 - Dual display start address supported.
367 * 13-15 - Reserved.
370 WORD attr = 0x0002; /* set optional info available */
371 /* Enable color mode - if both Colors & Depth are 0, then assume monochrome*/
372 if (ptr->Colors || ptr->Depth)
374 attr |= 0x0008;
378 * FIXME: Attribute handling is incomplete.
381 /* Mode supported? */
382 if (ptr->Supported)
384 attr |= 0x0001; /* set display mode supported */
387 /* Graphical mode? */
388 if (ptr->ModeType != TEXT)
390 attr |= 0x0010; /* set graphics mode on (text mode off) */
393 /* Not VGA-compatible? */
394 if (IS_VESA_MODE(mode))
395 attr |= 0x0020; /* disable VGA ports */
397 mib->ModeAttributes = attr;
401 * 02 - BYTE[2]: window attributes, window A and window B
402 * Bits:
403 * 0 - Window exists.
404 * 1 - Window is readable.
405 * 2 - Window is writable.
406 * 3-7 - Reserved.
408 mib->WinAAttributes = 0x07; /* window A exists, readable and writable */
409 mib->WinBAttributes = 0x00; /* window B not supported */
411 /* 04 - WORD: window granularity in KB */
412 mib->WinGranularity = 64;
414 /* 06 - WORD: window size in KB */
415 mib->WinSize = 64;
417 /* 08 - WORD[2]: start segments, window A and window B */
418 mib->WinASegment = 0xa000; /* window A segment */
419 mib->WinBSegment = 0x0000; /* window B not supported */
421 /* 12 - DWORD: window positioning function */
422 mib->WinFuncPtr = 0; /* not supported */
424 /* 16 - WORD: bytes per scan line */
425 /* FIXME: is this always correct? */
426 mib->BytesPerScanLine = ptr->Width * (ptr->Depth ? (ptr->Depth + 7) / 8 : 1);
428 /* 18 - WORD: width in pixels (graphics) or characters (text) */
429 if (ptr->ModeType == TEXT)
431 mib->XResolution = ptr->TextCols;
433 else
435 mib->XResolution = ptr->Width;
438 /* 20 - WORD: height in pixels (graphics) or characters (text) */
439 if (ptr->ModeType == TEXT)
441 mib->YResolution = ptr->TextRows;
443 else
445 mib->YResolution = ptr->Height;
448 /* 22 - BYTE: width of character cell in pixels */
449 mib->XCharSize = ptr->CharWidth;
451 /* 23 - BYTE: height of character cell in pixels */
452 mib->YCharSize = ptr->CharHeight;
454 /* 24 - BYTE: number of memory planes */
455 mib->NumberOfPlanes = 1; /* FIXME */
457 /* 25 - BYTE: number of bits per pixel */
458 mib->BitsPerPixel = ptr->Depth; /* FIXME: text modes? reserved bits? */
460 /* 26 - BYTE: number of banks */
461 mib->NumberOfBanks = 1; /* FIXME */
464 * 27 - BYTE: memory model type
465 * Values (hex):
466 * 00 - Text mode
467 * 01 - CGA graphics
468 * 02 - Hercules graphics
469 * 03 - Planar
470 * 04 - Packed pixel
471 * 05 - Non-chain 4, 256 color
472 * 06 - Direct color
473 * 07 - YUV
474 * 08-0F - Reserved for VESA.
475 * 10-FF - OEM memory models.
477 if (ptr->ModeType == TEXT)
478 mib->MemoryModel = 0; /* text mode */
479 else
480 mib->MemoryModel = 3; /* FIXME */
482 /* 28 - BYTE: size of bank in KB */
483 mib->BankSize = 0; /* FIXME */
485 /* 29 - BYTE: number of image pages (less one) in video RAM */
486 mib->NumberOfImagePages = (ptr->ScreenPages)-1;
488 /* 30 - BYTE: reserved (0x00 for VBE 1.0-2.0, 0x01 for VBE 3.0) */
489 mib->Reserved1 = 0x01;
492 * 31,33,35 - BYTE: red/green/blue mask size
493 * Size of red/green/blue color component in bits.
494 * 32,34,36 - BYTE: red/green/blue field position
495 * Bit position of the least significant bit of red/green/blue color
496 * component.
497 * Both should be only used when the memory model is direct color or YUV
498 * but "Imperium Romanum" uses this field even when the memory model is
499 * planar. So always fill this field when we have a depth bigger than 8,
500 * otherwise set them to zero.
502 switch (ptr->Depth) {
503 case 24:
504 mib->RedMaskSize = 8;
505 mib->GreenMaskSize = 8;
506 mib->BlueMaskSize = 8;
507 mib->RsvdMaskSize = 0;
508 mib->RedFieldPosition = 16;
509 mib->GreenFieldPosition = 8;
510 mib->BlueFieldPosition = 0;
511 mib->RsvdFieldPosition = 0;
512 break;
513 case 16:
514 mib->RedMaskSize = 5;
515 mib->GreenMaskSize = 6;
516 mib->BlueMaskSize = 5;
517 mib->RsvdMaskSize = 0;
518 mib->RedFieldPosition = 11;
519 mib->GreenFieldPosition = 5;
520 mib->BlueFieldPosition = 0;
521 mib->RsvdFieldPosition = 0;
522 break;
523 case 15:
524 mib->RedMaskSize = 5;
525 mib->GreenMaskSize = 5;
526 mib->BlueMaskSize = 5;
527 mib->RsvdMaskSize = 1;
528 mib->RedFieldPosition = 10;
529 mib->GreenFieldPosition = 5;
530 mib->BlueFieldPosition = 0;
531 mib->RsvdFieldPosition = 15;
532 break;
533 default:
534 mib->RedMaskSize = 0;
535 mib->GreenMaskSize = 0;
536 mib->BlueMaskSize = 0;
537 mib->RsvdMaskSize = 0;
538 mib->RedFieldPosition = 0;
539 mib->GreenFieldPosition = 0;
540 mib->BlueFieldPosition = 0;
541 mib->RsvdFieldPosition = 0;
542 break;
546 * 39 - BYTE: direct color mode info
547 * Bits:
548 * 0 - Set if color ramp is programmable.
549 * 1 - Set if bytes in reserved field may be used by application.
551 mib->DirectColorModeInfo = 0; /* not supported */
553 /* 40 - DWORD: physical address of linear video buffer */
554 mib->PhysBasePtr = 0; /* not supported */
556 /* 44 - DWORD: reserved, always zero */
557 mib->Reserved2 = 0;
559 /* 48 - WORD: reserved, always zero */
560 mib->Reserved3 = 0;
562 /* 50 - WORD: bytes per scan line in linear modes */
563 mib->LinBytesPerScanLine = mib->BytesPerScanLine;
565 /* 52 - BYTE: number of images (less one) for banked video modes */
566 mib->BnkNumberOfImagePages = 0; /* FIXME */
568 /* 53 - BYTE: number of images (less one) for linear video modes */
569 mib->LinNumberOfImagePages = mib->BnkNumberOfImagePages;
571 /* 54 - BYTE: red mask size (linear modes) */
572 mib->LinRedMaskSize = mib->RedMaskSize;
574 /* 55 - BYTE: red field position (linear modes) */
575 mib->LinRedFieldPosition = mib->RedFieldPosition;
577 /* 56 - BYTE: green mask size (linear modes) */
578 mib->LinGreenMaskSize = mib->GreenMaskSize;
580 /* 57 - BYTE: green field size (linear modes) */
581 mib->LinGreenFieldPosition = mib->GreenFieldPosition;
583 /* 58 - BYTE: blue mask size (linear modes) */
584 mib->LinBlueMaskSize = mib->BlueMaskSize;
586 /* 59 - BYTE: blue field position (linear modes) */
587 mib->LinBlueFieldPosition = mib->BlueFieldPosition;
589 /* 60 - BYTE: reserved mask size (linear modes) */
590 mib->LinRsvdMaskSize = mib->RsvdMaskSize;
592 /* 61 - BYTE: reserved mask position (linear modes) */
593 mib->LinRsvdFieldPosition = mib->RsvdFieldPosition;
595 /* 62 - DWORD: maximum pixel clock for graphics video mode, in Hz */
596 mib->MaxPixelClock = 0; /* FIXME */
598 /* 66 - BYTE[190]: reserved, set to zero */
599 memset( mib->Reserved4, 0, 190 );
601 return TRUE;
605 /**********************************************************************
606 * INT10_FillStateInformation
608 * Fill 64-byte buffer with VGA state and functionality information.
610 static void INT10_FillStateInformation( BYTE *buffer, BIOSDATA *data )
612 INT10_HEAP *heap = INT10_GetHeap();
614 /* 00 - DWORD: address of static functionality table */
615 *(SEGPTR*)(buffer + 0) = MAKESEGPTR( heap->WineHeapSegment,
616 offsetof(INT10_HEAP,
617 StaticModeSupport) );
619 /* 04 - BYTE[30]: copy of BIOS data starting from 0x49 (VideoMode) */
620 memmove( buffer + 4, &data->VideoMode, 30 );
622 /* 34 - BYTE: number of rows - 1 */
623 buffer[34] = data->RowsOnScreenMinus1;
625 /* 35 - WORD: bytes/character */
626 *(WORD*)(buffer + 35) = data->BytesPerChar;
628 /* 37 - BYTE: display combination code of active display */
629 buffer[37] = INT10_DCC;
631 /* 38 - BYTE: DCC of alternate display */
632 buffer[38] = 0; /* no secondary display */
634 /* 39 - WORD: number of colors supported in current mode (0000h = mono) */
635 *(WORD*)(buffer + 39) = 16; /* FIXME */
637 /* 41 - BYTE: number of pages supported in current mode */
638 buffer[41] = 1; /* FIXME */
641 * 42 - BYTE: number of scan lines active
642 * Values (hex):
643 * 00 = 200
644 * 01 = 350
645 * 02 = 400
646 * 03 = 480
648 buffer[42] = 3; /* FIXME */
650 /* 43 - BYTE: primary character block */
651 buffer[43] = 0; /* FIXME */
653 /* 44 - BYTE: secondary character block */
654 buffer[44] = 0; /* FIXME */
657 * 45 - BYTE: miscellaneous flags
658 * Bits:
659 * 0 - all modes on all displays on
660 * 1 - gray summing on
661 * 2 - monochrome display attached
662 * 3 - default palette loading disabled
663 * 4 - cursor emulation enabled
664 * 5 - 0 = intensity; 1 = blinking
665 * 6 - flat-panel display is active
666 * 7 - unused (0)
668 /* FIXME: Correct value? */
669 buffer[45] =
670 (data->VGASettings & 0x0f) |
671 ((data->ModeOptions & 1) << 4); /* cursor emulation */
674 * 46 - BYTE: non-VGA mode support
675 * Bits:
676 * 0 - BIOS supports information return for adapter interface
677 * 1 - adapter interface driver required
678 * 2 - 16-bit VGA graphics present
679 * 3 - =1 MFI attributes enabled
680 * =0 VGA attributes enabled
681 * 4 - 132-column mode supported
682 * 5-7 - reserved
684 buffer[46] = 0; /* FIXME: correct value? */
686 /* 47 - BYTE[2]: reserved, set to zero */
687 memset( buffer + 47, 0, 2 );
690 * 49 - BYTE: video memory available
691 * Values (hex):
692 * 00 - 64K
693 * 01 - 128K
694 * 02 - 192K
695 * 03 - 256K
697 buffer[49] = (data->ModeOptions & 0x60) >> 5; /* FIXME */
700 * 50 - BYTE: save pointer state flags
701 * Bits:
702 * 0 - 512 character set active
703 * 1 - dynamic save area present
704 * 2 - alpha font override active
705 * 3 - graphics font override active
706 * 4 - palette override active
707 * 5 - DCC override active
708 * 6-7 - unused (0)
710 buffer[50] = heap->StaticSavePointerFlags;
713 * 51 - BYTE: display information and status
714 * Bits:
715 * 0 - flat-panel display attached
716 * 1 - flat-panel display active
717 * 2 - color display
718 * 3-6 - reserved
719 * 7 - 640x480 flat-panel can be used simultaneously with CRT
721 buffer[51] = 4; /* FIXME: correct value? */
723 /* 52 - BYTE[12]: reserved, set to zero */
724 memset( buffer + 52, 0, 12 );
728 /**********************************************************************
729 * INT10_GetHeap
731 INT10_HEAP *INT10_GetHeap( void )
733 static INT10_HEAP *heap_pointer = 0;
735 if (!heap_pointer)
737 WORD segment;
738 int i;
740 heap_pointer = DOSVM_AllocDataUMB( sizeof(INT10_HEAP),
741 &segment,
742 0 );
744 for (i = 0; i < 7; i++)
745 heap_pointer->StaticModeSupport[i] = 0xff; /* FIXME */
747 heap_pointer->StaticScanlineSupport = 7; /* FIXME */
748 heap_pointer->StaticNumberCharBlocks = 0; /* FIXME */
749 heap_pointer->StaticActiveCharBlocks = 0; /* FIXME */
750 heap_pointer->StaticMiscFlags = 0x8ff; /* FIXME */
751 heap_pointer->StaticReserved1 = 0;
752 heap_pointer->StaticSavePointerFlags = 0x3f; /* FIXME */
753 heap_pointer->StaticReserved2 = 0;
755 for (i=0; TRUE; i++)
757 heap_pointer->VesaModeList[i] = INT10_modelist[i].Mode;
758 if (INT10_modelist[i].Mode == 0xffff)
759 break;
762 strcpy( heap_pointer->VesaOEMName, "WINE SVGA BOARD" );
763 strcpy( heap_pointer->VesaVendorName, "WINE" );
764 strcpy( heap_pointer->VesaProductName, "WINE SVGA" );
765 strcpy( heap_pointer->VesaProductRev, "2008" );
767 heap_pointer->VesaCurrentMode = 0; /* Initialized later. */
768 heap_pointer->WineHeapSegment = segment;
771 return heap_pointer;
775 /**********************************************************************
776 * INT10_SetVideoMode
778 * Change current video mode to any VGA or VESA mode.
779 * Returns TRUE if mode is supported.
781 * Mode bitfields:
782 * 0-6: .. Mode number (combined with bit 8).
783 * 7: =0 Clear screen.
784 * =1 Preserve display memory on mode change (VGA modes).
785 * 8: =0 VGA mode.
786 * =1 VESA mode.
787 * 9: .. Reserved, must be zero.
788 * 10: .. Reserved, must be zero.
789 * 11: =0 Use default refresh rate.
790 * =1 Use user specified refresh rate.
791 * 12: .. Reserved, must be zero.
792 * 13: .. Reserved, must be zero.
793 * 14: =0 Use windowed frame buffer model.
794 * =1 Use linear frame buffer model.
795 * 15: =0 Clear screen.
796 * =1 Preserve display memory on mode change (VESA modes).
798 static BOOL INT10_SetVideoMode( BIOSDATA *data, WORD mode )
800 const INT10_MODE *ptr = INT10_FindMode( mode );
801 INT10_HEAP *heap = INT10_GetHeap();
802 BOOL clearScreen = TRUE;
804 if (!ptr)
805 return FALSE;
808 * Linear framebuffer is not supported.
809 * FIXME - not sure this is valid since mode 19 is 256 color & linear
810 * of course only 1 window is addressable.
812 if (mode & 0x4000)
813 return FALSE;
816 * Check for VGA and VESA preserve video memory flag.
818 if ((mode & 0x0080) || (mode & 0x8000))
819 clearScreen = FALSE;
822 * Note that we do not mask out flags here on purpose.
824 heap->VesaCurrentMode = mode;
825 if (mode <= 0xff)
826 data->VideoMode = mode;
827 else
828 data->VideoMode = 0;
830 if (ptr->ModeType == TEXT)
832 /* Text mode. */
833 TRACE( "Setting %s %dx%d text mode (screen %s)\n",
834 IS_VESA_MODE(mode) ? "VESA" : "VGA",
835 ptr->TextCols, ptr->TextRows,
836 clearScreen ? "cleared" : "preserved" );
839 * FIXME: We should check here if alpha mode could be set.
841 VGA_SetAlphaMode( ptr->TextCols, ptr->TextRows );
843 data->VideoColumns = ptr->TextCols;
844 data->RowsOnScreenMinus1 = ptr->TextRows - 1;
846 if (clearScreen)
848 VGA_ClearText( 0, 0, ptr->TextCols-1, ptr->TextRows-1, 0x07 );
849 INT10_SetCursorPos( data, 0, 0, 0 );
850 VGA_SetCursorPos( 0, 0 );
853 else
855 /* Graphics mode. */
856 TRACE( "Setting %s %dx%dx%d graphics mode (screen %s)\n",
857 IS_VESA_MODE(mode) ? "VESA" : "VGA",
858 ptr->Width, ptr->Height, ptr->Depth,
859 clearScreen ? "cleared" : "preserved" );
861 if (VGA_SetMode( ptr->Width, ptr->Height, ptr->Depth ))
862 return FALSE;
865 return TRUE;
869 /**********************************************************************
870 * INT10_GetCursorPos
872 static void INT10_GetCursorPos(BIOSDATA*data,unsigned page,unsigned*X,unsigned*Y)
874 *X = data->VideoCursorPos[page*2]; /* column */
875 *Y = data->VideoCursorPos[page*2+1]; /* row */
879 /**********************************************************************
880 * INT10_SetCursorPos
882 static void INT10_SetCursorPos(BIOSDATA*data,unsigned page,unsigned X,unsigned Y)
884 data->VideoCursorPos[page*2] = X;
885 data->VideoCursorPos[page*2+1] = Y;
889 /**********************************************************************
890 * INT10_InitializeVideoMode
892 * The first time this function is called VGA emulation is set to the
893 * default text mode.
895 static void INT10_InitializeVideoMode( BIOSDATA *data )
897 static BOOL already_initialized = FALSE;
898 unsigned width;
899 unsigned height;
901 if(already_initialized)
902 return;
903 already_initialized = TRUE;
905 VGA_InitAlphaMode(&width, &height);
908 * FIXME: Add more mappings between initial size and
909 * text modes.
911 if (width >= 80 && height >= 25)
912 INT10_SetVideoMode( data, 0x03 );
913 else
914 INT10_SetVideoMode( data, 0x01 );
918 /**********************************************************************
919 * INT10_HandleVESA
921 * Handler for VESA functions (int10 function 0x4f).
923 static void INT10_HandleVESA( CONTEXT86 *context )
925 BIOSDATA *data = DOSVM_BiosData();
927 switch(AL_reg(context)) {
929 case 0x00: /* RETURN CONTROLLER INFORMATION */
930 TRACE( "VESA RETURN CONTROLLER INFORMATION\n" );
932 BYTE *ptr = CTX_SEG_OFF_TO_LIN(context,
933 context->SegEs,
934 context->Edi);
935 INT10_FillControllerInformation( ptr );
936 SET_AL( context, 0x4f );
937 SET_AH( context, 0x00 ); /* 0x00 = successful 0x01 = failed */
939 break;
941 case 0x01: /* RETURN MODE INFORMATION */
942 TRACE( "VESA RETURN MODE INFORMATION %04x\n", CX_reg(context) );
944 struct _ModeInfoBlock *ptr = CTX_SEG_OFF_TO_LIN(context,
945 context->SegEs,
946 context->Edi);
947 SET_AL( context, 0x4f );
948 if (INT10_FillModeInformation( ptr, CX_reg(context) ))
949 SET_AH( context, 0x00 ); /* status: success */
950 else
951 SET_AH( context, 0x01 ); /* status: failed */
953 break;
955 case 0x02: /* SET SuperVGA VIDEO MODE */
956 TRACE( "Set VESA video mode %04x\n", BX_reg(context) );
957 SET_AL( context, 0x4f ); /* function supported */
958 if (INT10_SetVideoMode( data, BX_reg(context) ))
959 SET_AH( context, 0x00 ); /* success */
960 else
961 SET_AH( context, 0x01 ); /* failed */
962 break;
964 case 0x03: /* VESA SuperVGA BIOS - GET CURRENT VIDEO MODE */
965 SET_AL( context, 0x4f );
966 SET_AH( context, 0x00 );
967 SET_BX( context, INT10_GetHeap()->VesaCurrentMode );
968 break;
970 case 0x04: /* VESA SuperVGA BIOS - SAVE/RESTORE SuperVGA VIDEO STATE */
971 ERR("VESA SAVE/RESTORE Video State - Not Implemented\n");
972 /* AL_reg(context) = 0x4f; = supported so not set since not implemented */
973 /* maybe we should do this instead ? */
974 /* AH_reg(context = 0x01; not implemented so just fail */
975 break;
977 case 0x05: /* VESA SuperVGA BIOS - CPU VIDEO MEMORY CONTROL */
979 * This subfunction supports only Window A (BL_reg == 0) and
980 * it assumes that window granularity is 64k.
982 switch(BH_reg(context)) {
983 case 0x00: /* select video memory window */
984 SET_AL( context, 0x4f ); /* function supported */
985 if(BL_reg(context) == 0) {
986 VGA_SetWindowStart(DX_reg(context) * 64 * 1024);
987 SET_AH( context, 0x00 ); /* status: successful */
988 } else
989 SET_AH( context, 0x01 ); /* status: failed */
990 break;
991 case 0x01: /* get video memory window */
992 SET_AL( context, 0x4f ); /* function supported */
993 if(BL_reg(context) == 0) {
994 SET_DX( context, VGA_GetWindowStart() / 64 / 1024 );
995 SET_AH( context, 0x00 ); /* status: successful */
996 } else
997 SET_AH( context, 0x01 ); /* status: failed */
998 break;
999 default:
1000 INT_BARF( context, 0x10 );
1002 break;
1004 case 0x06: /* VESA GET/SET LOGICAL SCAN LINE LENGTH */
1005 ERR("VESA GET/SET LOGICAL SCAN LINE LENGTH - Not Implemented\n");
1006 /* AL_reg(context) = 0x4f; = supported so not set since not implemented */
1007 /* maybe we should do this instead ? */
1008 /* AH_reg(context = 0x001; not implemented so just fail */
1009 break;
1011 case 0x07: /* GET/SET DISPLAY START */
1012 ERR("VESA GET/SET DISPLAY START - Not Implemented\n");
1013 /* AL_reg(context) = 0x4f; = supported so not set since not implemented */
1014 /* maybe we should do this instead ? */
1015 /* AH_reg(context = 0x001; not implemented so just fail */
1016 break;
1018 case 0x08: /* GET/SET DAC PALETTE CONTROL */
1019 ERR("VESA GET/SET DAC PALETTE CONTROL- Not Implemented\n");
1020 /* AL_reg(context) = 0x4f; = supported so not set since not implemented */
1021 /* maybe we should do this instead ? */
1022 /* AH_reg(context = 0x001; not implemented so just fail */
1023 break;
1025 case 0x09: /* SET PALETTE ENTRIES */
1026 FIXME("VESA Set palette entries - not implemented\n");
1027 break;
1029 case 0x0a: /* GET PROTECTED-MODE CODE */
1030 FIXME("VESA Get protected-mode code - not implemented\n");
1031 break;
1033 case 0x10: /* Display Power Management Extensions */
1034 FIXME("VESA Display Power Management Extensions - not implemented\n");
1035 break;
1037 case 0xef: /* get video mode for hercules-compatibles */
1038 /* There's no reason to really support this */
1039 /* is there?....................(A.C.) */
1040 TRACE("Just report the video not hercules compatible\n");
1041 SET_DX( context, 0xffff );
1042 break;
1044 case 0xff: /* Turn VESA ON/OFF */
1045 /* I don't know what to do */
1046 break;
1048 default:
1049 FIXME("VESA Function (0x%x) - Not Supported\n", AH_reg(context));
1050 break;
1055 /**********************************************************************
1056 * DOSVM_Int10Handler
1058 * Handler for int 10h (video).
1060 * NOTE:
1061 * Most INT 10 functions for text-mode, CGA, EGA, and VGA cards
1062 * are present in this list. (SVGA and XGA are not) That is not
1063 * to say that all these functions should be supported, but if
1064 * anyone is brain-damaged enough to want to emulate one of these
1065 * beasts then this should get you started.
1067 * NOTE:
1068 * Several common graphical extensions used by Microsoft hook
1069 * off of here. I have *not* added them to this list (yet). They
1070 * include:
1072 * MSHERC.COM - More functionality for Hercules cards.
1073 * EGA.SYS (also MOUSE.COM) - More for EGA cards.
1075 * Yes, MS also added this support into their mouse driver. Don't
1076 * ask me, I don't work for them.
1078 * Joseph Pranevich - 9/98
1080 * Jess Haas 2/99
1081 * Added support for Vesa. It is not complete but is a start.
1082 * NOTE: Im not sure if I did all this right or if any of it works.
1083 * Currently I don't have a program that uses Vesa that actually gets far
1084 * enough without crashing to do vesa stuff.
1086 * Added additional vga graphic support - 3/99
1088 void WINAPI DOSVM_Int10Handler( CONTEXT86 *context )
1090 BIOSDATA *data = DOSVM_BiosData();
1092 INT10_InitializeVideoMode( data );
1094 switch(AH_reg(context)) {
1096 case 0x00: /* SET VIDEO MODE */
1097 TRACE( "Set VGA video mode %02x\n", AL_reg(context) );
1098 if (!INT10_SetVideoMode( data, AL_reg(context) ))
1099 FIXME( "Unsupported VGA video mode requested: %#x\n",
1100 AL_reg(context) );
1101 break;
1103 case 0x01: /* SET CURSOR SHAPE */
1104 TRACE("Set Cursor Shape start %d end %d options %d\n",
1105 CH_reg(context) & 0x1f,
1106 CL_reg(context) & 0x1f,
1107 CH_reg(context) & 0xe0);
1108 data->VideoCursorType = CX_reg(context); /* direct copy */
1109 VGA_SetCursorShape(CH_reg(context), CL_reg(context));
1110 break;
1112 case 0x02: /* SET CURSOR POSITION */
1113 /* BH = Page Number */ /* Not supported */
1114 /* DH = Row */ /* 0 is left */
1115 /* DL = Column */ /* 0 is top */
1116 INT10_SetCursorPos(data,BH_reg(context),DL_reg(context),DH_reg(context));
1117 if (BH_reg(context))
1119 FIXME("Set Cursor Position: Cannot set to page %d\n",
1120 BH_reg(context));
1122 else
1124 VGA_SetCursorPos(DL_reg(context), DH_reg(context));
1125 TRACE("Set Cursor Position: %d/%d\n", DL_reg(context),
1126 DH_reg(context));
1128 break;
1130 case 0x03: /* GET CURSOR POSITION AND SIZE */
1132 unsigned row, col;
1134 TRACE("Get cursor position and size (page %d)\n", BH_reg(context));
1135 SET_CX( context, data->VideoCursorType );
1136 INT10_GetCursorPos(data,BH_reg(context),&col,&row);
1137 SET_DH( context, row );
1138 SET_DL( context, col );
1139 TRACE("Cursor Position: %d/%d\n", DL_reg(context), DH_reg(context));
1141 break;
1143 case 0x04: /* READ LIGHT PEN POSITION */
1144 FIXME("Read Light Pen Position - Not Supported\n");
1145 SET_AH( context, 0x00 ); /* Not down */
1146 break;
1148 case 0x05: /* SELECT ACTIVE DISPLAY PAGE */
1149 FIXME("Select Active Display Page (%d) - Not Supported\n", AL_reg(context));
1150 data->VideoCurPage = AL_reg(context);
1151 break;
1153 case 0x06: /* SCROLL UP WINDOW */
1154 /* AL = Lines to scroll */
1155 /* BH = Attribute */
1156 /* CH,CL = row, col upper-left */
1157 /* DH,DL = row, col lower-right */
1158 TRACE("Scroll Up Window %d\n", AL_reg(context));
1160 if (AL_reg(context) == 0)
1161 VGA_ClearText( CH_reg(context), CL_reg(context),
1162 DH_reg(context), DL_reg(context),
1163 BH_reg(context) );
1164 else
1165 VGA_ScrollUpText( CH_reg(context), CL_reg(context),
1166 DH_reg(context), DL_reg(context),
1167 AL_reg(context), BH_reg(context) );
1168 break;
1170 case 0x07: /* SCROLL DOWN WINDOW */
1171 /* AL = Lines to scroll */
1172 /* BH = Attribute */
1173 /* CH,CL = row, col upper-left */
1174 /* DH,DL = row, col lower-right */
1175 TRACE("Scroll Down Window %d\n", AL_reg(context));
1177 if (AL_reg(context) == 0)
1178 VGA_ClearText( CH_reg(context), CL_reg(context),
1179 DH_reg(context), DL_reg(context),
1180 BH_reg(context) );
1181 else
1182 VGA_ScrollDownText( CH_reg(context), CL_reg(context),
1183 DH_reg(context), DL_reg(context),
1184 AL_reg(context), BH_reg(context) );
1185 break;
1187 case 0x08: /* READ CHARACTER AND ATTRIBUTE AT CURSOR POSITION */
1189 if (BH_reg(context)) /* Write to different page */
1191 FIXME("Read character and attribute at cursor position -"
1192 " Can't read from non-0 page\n");
1193 SET_AL( context, ' ' ); /* That page is blank */
1194 SET_AH( context, 7 );
1196 else
1198 BYTE ascii, attr;
1199 TRACE("Read Character and Attribute at Cursor Position\n");
1200 VGA_GetCharacterAtCursor(&ascii, &attr);
1201 SET_AL( context, ascii );
1202 SET_AH( context, attr );
1205 break;
1207 case 0x09: /* WRITE CHARACTER AND ATTRIBUTE AT CURSOR POSITION */
1208 case 0x0a: /* WRITE CHARACTER ONLY AT CURSOR POSITION */
1209 /* AL = Character to display. */
1210 /* BH = Page Number */ /* We can't write to non-0 pages, yet. */
1211 /* BL = Attribute / Color */
1212 /* CX = Times to Write Char */
1213 /* Note here that the cursor is not advanced. */
1215 unsigned row, col;
1217 INT10_GetCursorPos(data,BH_reg(context),&col,&row);
1218 VGA_WriteChars(col, row,
1219 AL_reg(context),
1220 (AH_reg(context) == 0x09) ? BL_reg(context) : -1,
1221 CX_reg(context));
1222 if (CX_reg(context) > 1)
1223 TRACE("Write Character%s at Cursor Position (Rep. %d): %c\n",
1224 (AH_reg(context) == 0x09) ? " and Attribute" : "",
1225 CX_reg(context), AL_reg(context));
1226 else
1227 TRACE("Write Character%s at Cursor Position: %c\n",
1228 (AH_reg(context) == 0x09) ? " and Attribute" : "",
1229 AL_reg(context));
1231 break;
1233 case 0x0b:
1234 switch BH_reg(context) {
1235 case 0x00: /* SET BACKGROUND/BORDER COLOR */
1236 /* In text modes, this sets only the border... */
1237 /* According to the interrupt list and one of my books. */
1238 /* Funny though that Beyond Zork seems to indicate that it
1239 also sets up the default background attributes for clears
1240 and scrolls... */
1241 /* Bear in mind here that we do not want to change,
1242 apparently, the foreground or attribute of the background
1243 with this call, so we should check first to see what the
1244 foreground already is... FIXME */
1246 /* For CGA modes, background color change is the same as writing
1247 to I/O address 0x3d9 bit 4 */
1248 if(data->VideoMode >= 4 && data->VideoMode <= 6)
1250 VGA_SetBright((BL_reg(context) & 0x10) && 1);
1251 VGA_UpdatePalette();
1253 else FIXME("Set Background/Border Color: %d/%d\n",
1254 BH_reg(context), BL_reg(context));
1255 break;
1256 case 0x01: /* SET PALETTE */
1258 /* For CGA modes, palette color change is the same as writing
1259 to I/O address 0x3d9 bit 5 */
1260 if(data->VideoMode >= 4 && data->VideoMode <= 6)
1262 VGA_SetPaletteIndex(BL_reg(context) & 1);
1263 VGA_UpdatePalette();
1265 else FIXME("Set Palette - Not Supported: %02X\n", BL_reg(context));
1266 break;
1267 default:
1268 FIXME("INT 10 AH = 0x0b BH = 0x%x - Unknown\n",
1269 BH_reg(context));
1270 break;
1272 break;
1274 case 0x0c: /* WRITE GRAPHICS PIXEL */
1276 /* Only supported in CGA mode for now */
1277 if(data->VideoMode >= 4 && data->VideoMode <= 6)
1279 VGA_WritePixel(AL_reg(context), BH_reg(context), CX_reg(context), DX_reg(context));
1281 else FIXME("Write pixel not implemented for current mode\n");
1282 break;
1284 case 0x0d: /* READ GRAPHICS PIXEL */
1285 /* Not in graphics mode, can ignore w/o error */
1286 FIXME("Read Graphics Pixel - Not Supported\n");
1287 break;
1289 case 0x0e: /* TELETYPE OUTPUT */
1290 TRACE("Teletype Output\n");
1291 DOSVM_PutChar(AL_reg(context));
1292 break;
1294 case 0x0f: /* GET CURRENT VIDEO MODE */
1295 TRACE("Get current video mode: -> mode %d, columns %d\n", data->VideoMode, data->VideoColumns);
1296 /* Note: This should not be a constant value. */
1297 SET_AL( context, data->VideoMode );
1298 SET_AH( context, data->VideoColumns );
1299 SET_BH( context, 0 ); /* Display page 0 */
1300 break;
1302 case 0x10:
1303 switch AL_reg(context) {
1304 case 0x00: /* SET SINGLE PALETTE REGISTER - A.C. */
1305 TRACE("Set Single Palette Register - Reg 0x0%x Value 0x0%x\n",
1306 BL_reg(context),BH_reg(context));
1307 /* BH is the value BL is the register */
1308 VGA_SetColor16((int)BL_reg(context),(int)BH_reg(context));
1309 break;
1310 case 0x01: /* SET BORDER (OVERSCAN) */
1311 /* Text terminals have no overscan */
1312 /* I'm setting it anyway. - A.C. */
1313 TRACE("Set Border (Overscan) - Ignored but set.\n");
1314 VGA_SetColor16(16,(int)BH_reg(context));
1315 break;
1316 case 0x02: /* SET ALL PALETTE REGISTERS - A.C.*/
1317 TRACE("Set all palette registers\n");
1318 /* ES:DX points to a 17 byte table of colors */
1319 /* No return data listed */
1320 /* I'll have to update my table and the default palette */
1321 VGA_Set16Palette(CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edx));
1322 break;
1323 case 0x03: /* TOGGLE INTENSITY/BLINKING BIT */
1324 FIXME("Toggle Intensity/Blinking Bit - Not Supported\n");
1325 break;
1326 case 0x07: /* GET INDIVIDUAL PALETTE REGISTER - A.C.*/
1327 TRACE("Get Individual Palette Register 0x0%x\n",BL_reg(context));
1328 /* BL is register to read [ 0-15 ] BH is return value */
1329 SET_BH( context, VGA_GetColor16((int)BL_reg(context)) );
1330 break;
1331 case 0x08: /* READ OVERSCAN (BORDER COLOR) REGISTER - A.C. */
1332 TRACE("Read Overscan (Border Color) Register\n");
1333 SET_BH( context, VGA_GetColor16(16) );
1334 break;
1335 case 0x09: /* READ ALL PALETTE REGISTERS AND OVERSCAN REGISTER - A.C.*/
1336 TRACE("Read All Palette Registers and Overscan Register\n");
1337 /* ES:DX points to a 17 byte table where the results */
1338 /* of this call should be stored. */
1339 VGA_Get16Palette(CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edx));
1340 break;
1341 case 0x10: /* SET INDIVIDUAL DAC REGISTER */
1343 PALETTEENTRY paldat;
1345 TRACE("Set Individual DAC register\n");
1346 paldat.peRed = DH_reg(context);
1347 paldat.peGreen = CH_reg(context);
1348 paldat.peBlue = CL_reg(context);
1349 paldat.peFlags = 0;
1350 VGA_SetPalette(&paldat,BX_reg(context)&0xFF,1);
1352 break;
1353 case 0x12: /* SET BLOCK OF DAC REGISTERS */
1355 int i;
1356 PALETTEENTRY paldat;
1357 BYTE *pt;
1359 TRACE("Set Block of DAC registers\n");
1360 pt = (BYTE*)CTX_SEG_OFF_TO_LIN(context,context->SegEs,context->Edx);
1361 for (i=0;i<CX_reg(context);i++)
1363 paldat.peRed = (*(pt+i*3+0)) << 2;
1364 paldat.peGreen = (*(pt+i*3+1)) << 2;
1365 paldat.peBlue = (*(pt+i*3+2)) << 2;
1366 paldat.peFlags = 0;
1367 VGA_SetPalette(&paldat,(BX_reg(context)+i)&0xFF,1);
1370 break;
1371 case 0x13: /* SELECT VIDEO DAC COLOR PAGE */
1372 FIXME("Select video DAC color page - Not Supported\n");
1373 break;
1374 case 0x15: /* READ INDIVIDUAL DAC REGISTER */
1375 FIXME("Read individual DAC register - Not Supported\n");
1376 break;
1377 case 0x17: /* READ BLOCK OF DAC REGISTERS */
1378 FIXME("Read block of DAC registers - Not Supported\n");
1379 break;
1380 case 0x18: /* SET PEL MASK */
1381 FIXME("Set PEL mask - Not Supported\n");
1382 break;
1383 case 0x19: /* READ PEL MASK */
1384 FIXME("Read PEL mask - Not Supported\n");
1385 break;
1386 case 0x1a: /* GET VIDEO DAC COLOR PAGE STATE */
1387 FIXME("Get video DAC color page state - Not Supported\n");
1388 break;
1389 case 0x1b: /* PERFORM GRAY-SCALE SUMMING */
1390 FIXME("Perform Gray-scale summing - Not Supported\n");
1391 break;
1392 default:
1393 FIXME("INT 10 AH = 0x10 AL = 0x%x - Unknown\n",
1394 AL_reg(context));
1395 break;
1397 break;
1399 case 0x11: /* TEXT MODE CHARGEN */
1400 /* Note that second subfunction is *almost* identical. */
1401 /* See INTERRUPT.A for details. */
1402 switch AL_reg(context) {
1403 case 0x00: /* LOAD USER SPECIFIED PATTERNS */
1404 case 0x10:
1405 FIXME("Load User Specified Patterns - Not Supported\n");
1406 break;
1407 case 0x01: /* LOAD ROM MONOCHROME PATTERNS */
1408 case 0x11:
1409 FIXME("Load ROM Monochrome Patterns - Not Supported\n");
1410 break;
1411 case 0x02: /* LOAD ROM 8x8 DOUBLE-DOT PATTERNS */
1412 case 0x12:
1413 FIXME(
1414 "Load ROM 8x8 Double Dot Patterns - Not Supported\n");
1415 break;
1416 case 0x03: /* SET BLOCK SPECIFIER */
1417 FIXME("Set Block Specifier - Not Supported\n");
1418 break;
1419 case 0x04: /* LOAD ROM 8x16 CHARACTER SET */
1420 case 0x14:
1421 FIXME("Load ROM 8x16 Character Set - Not Supported\n");
1422 break;
1423 case 0x20: /* SET USER 8x16 GRAPHICS CHARS */
1424 FIXME("Set User 8x16 Graphics Chars - Not Supported\n");
1425 break;
1426 case 0x21: /* SET USER GRAPICS CHARACTERS */
1427 FIXME("Set User Graphics Characters - Not Supported\n");
1428 break;
1429 case 0x22: /* SET ROM 8x14 GRAPHICS CHARS */
1430 FIXME("Set ROM 8x14 Graphics Chars - Not Supported\n");
1431 break;
1432 case 0x23: /* SET ROM 8x8 DBL DOT CHARS */
1433 FIXME(
1434 "Set ROM 8x8 Dbl Dot Chars (Graphics) - Not Supported\n");
1435 break;
1436 case 0x24: /* LOAD 8x16 GRAPHIC CHARS */
1437 FIXME("Load 8x16 Graphic Chars - Not Supported\n");
1438 break;
1439 case 0x30: /* GET FONT INFORMATION */
1440 FIXME("Get Font Information - Not Supported\n");
1441 break;
1442 default:
1443 FIXME("INT 10 AH = 0x11 AL = 0x%x - Unknown\n",
1444 AL_reg(context));
1445 break;
1447 break;
1449 case 0x12: /* ALTERNATE FUNCTION SELECT */
1450 switch BL_reg(context) {
1451 case 0x10: /* GET EGA INFO */
1452 TRACE("EGA info requested\n");
1453 SET_BH( context, 0x00 ); /* Color screen */
1454 SET_BL( context, data->ModeOptions >> 5 ); /* EGA memory size */
1455 SET_CX( context, data->FeatureBitsSwitches );
1456 break;
1457 case 0x20: /* ALTERNATE PRTSC */
1458 FIXME("Install Alternate Print Screen - Not Supported\n");
1459 break;
1460 case 0x30: /* SELECT VERTICAL RESOLUTION */
1461 FIXME("Select vertical resolution - not supported\n");
1462 break;
1463 case 0x31: /* ENABLE/DISABLE DEFAULT PALETTE LOADING */
1464 FIXME("Default palette loading - not supported\n");
1465 data->VGASettings =
1466 (data->VGASettings & 0xf7) |
1467 ((AL_reg(context) == 1) << 3);
1468 break;
1469 case 0x32: /* ENABLE/DISABLE VIDEO ADDRESSING */
1470 FIXME("Video Addressing - Not Supported\n");
1471 break;
1472 case 0x33: /* ENABLE/DISABLE GRAY SCALE SUMMING */
1473 FIXME("Gray Scale Summing - Not Supported\n");
1474 break;
1475 case 0x34: /* ENABLE/DISABLE CURSOR EMULATION */
1476 TRACE("Set cursor emulation to %d\n", AL_reg(context));
1477 data->ModeOptions =
1478 (data->ModeOptions & 0xfe)|(AL_reg(context) == 1);
1479 break;
1480 case 0x36: /* VIDEO ADDRESS CONTROL */
1481 FIXME("Video Address Control - Not Supported\n");
1482 break;
1483 default:
1484 FIXME("INT 10 AH = 0x11 AL = 0x%x - Unknown\n",
1485 AL_reg(context));
1486 break;
1488 break;
1490 case 0x13: /* WRITE STRING */
1491 /* This one does not imply that string be at cursor. */
1492 FIXME("Write String - Not Supported\n");
1493 break;
1495 case 0x1a:
1496 switch AL_reg(context) {
1497 case 0x00: /* GET DISPLAY COMBINATION CODE */
1498 TRACE("Get Display Combination Code\n");
1499 SET_AL( context, 0x1a ); /* Function supported */
1500 SET_BL( context, INT10_DCC ); /* Active display */
1501 SET_BH( context, 0x00 ); /* No alternate display */
1502 break;
1503 case 0x01: /* SET DISPLAY COMBINATION CODE */
1504 FIXME("Set Display Combination Code - Not Supported\n");
1505 break;
1506 default:
1507 FIXME("INT 10 AH = 0x1a AL = 0x%x - Unknown\n",
1508 AL_reg(context));
1509 break;
1511 break;
1513 case 0x1b: /* FUNCTIONALITY/STATE INFORMATION */
1514 TRACE("Get functionality/state information\n");
1515 if (BX_reg(context) == 0x0000)
1517 BYTE *ptr = CTX_SEG_OFF_TO_LIN(context,
1518 context->SegEs,
1519 context->Edi);
1520 SET_AL( context, 0x1b ); /* Function is supported */
1521 INT10_FillStateInformation( ptr, data );
1523 break;
1525 case 0x1c: /* SAVE/RESTORE VIDEO STATE */
1526 FIXME("Save/Restore Video State - Not Supported\n");
1527 break;
1529 case 0xef: /* get video mode for hercules-compatibles */
1530 /* There's no reason to really support this */
1531 /* is there?....................(A.C.) */
1532 TRACE("Just report the video not hercules compatible\n");
1533 SET_DX( context, 0xffff );
1534 break;
1536 case 0x4f: /* VESA */
1537 INT10_HandleVESA(context);
1538 break;
1540 case 0xfe: /* GET SHADOW BUFFER */
1541 TRACE( "GET SHADOW BUFFER %x:%x - ignored\n",
1542 context->SegEs, DI_reg(context) );
1543 break;
1545 default:
1546 FIXME("Unknown - 0x%x\n", AH_reg(context));
1547 INT_BARF( context, 0x10 );
1552 /**********************************************************************
1553 * DOSVM_PutChar
1555 * Write single character to VGA console at the current
1556 * cursor position and updates the BIOS cursor position.
1558 void WINAPI DOSVM_PutChar( BYTE ascii )
1560 BIOSDATA *data = DOSVM_BiosData();
1561 unsigned xpos, ypos;
1563 TRACE("char: 0x%02x(%c)\n", ascii, ascii);
1565 INT10_InitializeVideoMode( data );
1567 VGA_PutChar( ascii );
1568 VGA_GetCursorPos( &xpos, &ypos );
1569 INT10_SetCursorPos( data, 0, xpos, ypos );