msi/tests: Avoid a TRUE:FALSE conditional expression.
[wine/multimedia.git] / dlls / krnl386.exe16 / int10.c
blob0edfbd7668d17416b0beb7bf13cf3b3328cf66d1
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 /* True if video mode is a vesa mode, false otherwise.
137 * More correct would be to use something like (x > 0xff || x == 0x6a)
138 * but as long as we have only the standard VGA and VESA modes this is ok too */
139 #define IS_VESA_MODE(x) ((x) >= 0x6a)
141 /* Forward declarations. */
142 static INT10_HEAP *INT10_GetHeap(void);
143 static void INT10_SetCursorPos(BIOSDATA*, unsigned, unsigned, unsigned);
145 /**********************************************************************
146 * INT10_FillControllerInformation
148 * Fill 256-byte (VBE1.x) or 512-byte buffer (VBE2.0+) with
149 * capabilities of the video controller.
151 static void INT10_FillControllerInformation( BYTE *buffer )
153 INT10_HEAP *heap = INT10_GetHeap();
155 /* 00 - BYTE[4]: signature */
156 memmove( buffer, "VESA", 4 );
158 /* 04 - WORD: version number */
159 *(WORD*)(buffer + 4) = 0x0300; /* version 3.0 */
161 /* 06 - DWORD: pointer to OEM name */
162 *(SEGPTR*)(buffer + 6) = MAKESEGPTR( heap->WineHeapSegment,
163 offsetof(INT10_HEAP,
164 VesaOEMName) );
167 * 10 - DWORD: capabilities flags
168 * Bits:
169 * 0 - DAC can be switched into 8-bit mode
170 * 1 - non-VGA controller
171 * 2 - programmed DAC with blank bit
172 * 3 - controller supports hardware stereoscopic signalling
173 * 4 - =0 stereo signalling via external VESA stereo connector
174 * =1 stereo signalling via VESA EVC connector
175 * 5 - controller supports hardware mouse cursor
176 * 6 - controller supports hardware clipping
177 * 7 - controller supports transparent BitBLT
178 * 8-31 - reserved (0)
180 *(DWORD*)(buffer + 10) = 0; /* FIXME */
182 /* 14 - DWORD: pointer to list of supported VESA and OEM video modes */
183 *(SEGPTR*)(buffer + 14) = MAKESEGPTR( heap->WineHeapSegment,
184 offsetof(INT10_HEAP,
185 VesaModeList) );
187 /* 18 - WORD: total amount of video memory in 64K blocks */
188 *(WORD*)(buffer + 18) = 16; /* FIXME */
190 /* 20 - WORD: OEM software version (BCD, high byte = major) */
191 *(WORD*)(buffer + 20) = 0x0100; /* version 1.0 */
193 /* 22 - DWORD: pointer to vendor name */
194 *(SEGPTR*)(buffer + 22) = MAKESEGPTR( heap->WineHeapSegment,
195 offsetof(INT10_HEAP,
196 VesaVendorName) );
198 /* 26 - DWORD: pointer to product name */
199 *(SEGPTR*)(buffer + 26) = MAKESEGPTR( heap->WineHeapSegment,
200 offsetof(INT10_HEAP,
201 VesaProductName) );
203 /* 30 - DWORD: pointer to product revision string */
204 *(SEGPTR*)(buffer + 30) = MAKESEGPTR( heap->WineHeapSegment,
205 offsetof(INT10_HEAP,
206 VesaProductRev) );
208 /* 34 - WORD: VBE/AF version (if capabilities bit 3 set) */
209 *(WORD*)(buffer + 34) = 0;
212 * 36 - DWORD: pointer to list of accelerated modes
213 * (if capabilities bit 3 set)
215 *(SEGPTR*)(buffer + 36) = 0;
217 /* 40 - BYTE[216]: reserved for VBE implementation, set to zero */
218 memset( buffer + 40, 0, 216 );
221 * 256 - BYTE[256]: reserved for VBE3.0 implementation,
222 * ignored in order to support older programs
227 /**********************************************************************
228 * INT10_FillModeInformation
230 * Fill 256-byte buffer with extended information about display mode.
232 * Returns FALSE if mode is unknown and TRUE is mode is known
233 * even if it is not supported.
235 static BOOL INT10_FillModeInformation( struct _ModeInfoBlock *mib, WORD mode )
237 const VGA_MODE *ptr = VGA_GetModeInfo( mode );
238 if (!ptr)
239 return FALSE;
242 * 00 - WORD: mode attributes
243 * Bits:
244 * 0 - Mode supported by present hardware configuration.
245 * 1 - Optional information available. Must be =1 for VBE v1.2+.
246 * 2 - BIOS output supported.
247 * Int10 functions 01, 02, 06, 07, 09, 0a and 0e are supported.
248 * 3 - Set if color, clear if monochrome.
249 * 4 - Set if graphics mode, clear if text mode.
250 * 5 - Mode is not VGA-compatible if set.
251 * VGA-compatible modes support standard VGA I/O ports.
252 * 6 - Bank-switched (or windowed) mode is not supported if set.
253 * 7 - Linear framebuffer mode supported.
254 * 8 - Double scanning supported.
255 * 9 - Interlaced operation supported.
256 * 10 - Triple buffering supported.
257 * 11 - Stereoscopic display supported.
258 * 12 - Dual display start address supported.
259 * 13-15 - Reserved.
262 WORD attr = 0x0002; /* set optional info available */
263 /* Enable color mode - if both Colors & Depth are 0, then assume monochrome*/
264 if (ptr->Colors || ptr->Depth)
266 attr |= 0x0008;
270 * FIXME: Attribute handling is incomplete.
273 /* Mode supported? */
274 if (ptr->Supported)
276 attr |= 0x0001; /* set display mode supported */
279 /* Graphical mode? */
280 if (ptr->ModeType != TEXT)
282 attr |= 0x0010; /* set graphics mode on (text mode off) */
285 /* Not VGA-compatible? */
286 if (IS_VESA_MODE(mode))
287 attr |= 0x0020; /* disable VGA ports */
289 mib->ModeAttributes = attr;
293 * 02 - BYTE[2]: window attributes, window A and window B
294 * Bits:
295 * 0 - Window exists.
296 * 1 - Window is readable.
297 * 2 - Window is writable.
298 * 3-7 - Reserved.
300 mib->WinAAttributes = 0x07; /* window A exists, readable and writable */
301 mib->WinBAttributes = 0x00; /* window B not supported */
303 /* 04 - WORD: window granularity in KB */
304 mib->WinGranularity = 64;
306 /* 06 - WORD: window size in KB */
307 mib->WinSize = 64;
309 /* 08 - WORD[2]: start segments, window A and window B */
310 mib->WinASegment = 0xa000; /* window A segment */
311 mib->WinBSegment = 0x0000; /* window B not supported */
313 /* 12 - DWORD: window positioning function */
314 mib->WinFuncPtr = 0; /* not supported */
316 /* 16 - WORD: bytes per scan line */
317 /* FIXME: is this always correct? */
318 mib->BytesPerScanLine = ptr->Width * (ptr->Depth ? (ptr->Depth + 7) / 8 : 1);
320 /* 18 - WORD: width in pixels (graphics) or characters (text) */
321 if (ptr->ModeType == TEXT)
323 mib->XResolution = ptr->TextCols;
325 else
327 mib->XResolution = ptr->Width;
330 /* 20 - WORD: height in pixels (graphics) or characters (text) */
331 if (ptr->ModeType == TEXT)
333 mib->YResolution = ptr->TextRows;
335 else
337 mib->YResolution = ptr->Height;
340 /* 22 - BYTE: width of character cell in pixels */
341 mib->XCharSize = ptr->CharWidth;
343 /* 23 - BYTE: height of character cell in pixels */
344 mib->YCharSize = ptr->CharHeight;
346 /* 24 - BYTE: number of memory planes */
347 mib->NumberOfPlanes = 1; /* FIXME */
349 /* 25 - BYTE: number of bits per pixel */
350 mib->BitsPerPixel = ptr->Depth; /* FIXME: text modes? reserved bits? */
352 /* 26 - BYTE: number of banks */
353 mib->NumberOfBanks = 1; /* FIXME */
356 * 27 - BYTE: memory model type
357 * Values (hex):
358 * 00 - Text mode
359 * 01 - CGA graphics
360 * 02 - Hercules graphics
361 * 03 - Planar
362 * 04 - Packed pixel
363 * 05 - Non-chain 4, 256 color
364 * 06 - Direct color
365 * 07 - YUV
366 * 08-0F - Reserved for VESA.
367 * 10-FF - OEM memory models.
369 if (ptr->ModeType == TEXT)
370 mib->MemoryModel = 0; /* text mode */
371 else
372 mib->MemoryModel = 3; /* FIXME */
374 /* 28 - BYTE: size of bank in KB */
375 mib->BankSize = 0; /* FIXME */
377 /* 29 - BYTE: number of image pages (less one) in video RAM */
378 mib->NumberOfImagePages = (ptr->ScreenPages)-1;
380 /* 30 - BYTE: reserved (0x00 for VBE 1.0-2.0, 0x01 for VBE 3.0) */
381 mib->Reserved1 = 0x01;
384 * 31,33,35 - BYTE: red/green/blue mask size
385 * Size of red/green/blue color component in bits.
386 * 32,34,36 - BYTE: red/green/blue field position
387 * Bit position of the least significant bit of red/green/blue color
388 * component.
389 * Both should be only used when the memory model is direct color or YUV
390 * but "Imperium Romanum" uses this field even when the memory model is
391 * planar. So always fill this field when we have a depth bigger than 8,
392 * otherwise set them to zero.
394 switch (ptr->Depth) {
395 case 24:
396 mib->RedMaskSize = 8;
397 mib->GreenMaskSize = 8;
398 mib->BlueMaskSize = 8;
399 mib->RsvdMaskSize = 0;
400 mib->RedFieldPosition = 16;
401 mib->GreenFieldPosition = 8;
402 mib->BlueFieldPosition = 0;
403 mib->RsvdFieldPosition = 0;
404 break;
405 case 16:
406 mib->RedMaskSize = 5;
407 mib->GreenMaskSize = 6;
408 mib->BlueMaskSize = 5;
409 mib->RsvdMaskSize = 0;
410 mib->RedFieldPosition = 11;
411 mib->GreenFieldPosition = 5;
412 mib->BlueFieldPosition = 0;
413 mib->RsvdFieldPosition = 0;
414 break;
415 case 15:
416 mib->RedMaskSize = 5;
417 mib->GreenMaskSize = 5;
418 mib->BlueMaskSize = 5;
419 mib->RsvdMaskSize = 1;
420 mib->RedFieldPosition = 10;
421 mib->GreenFieldPosition = 5;
422 mib->BlueFieldPosition = 0;
423 mib->RsvdFieldPosition = 15;
424 break;
425 default:
426 mib->RedMaskSize = 0;
427 mib->GreenMaskSize = 0;
428 mib->BlueMaskSize = 0;
429 mib->RsvdMaskSize = 0;
430 mib->RedFieldPosition = 0;
431 mib->GreenFieldPosition = 0;
432 mib->BlueFieldPosition = 0;
433 mib->RsvdFieldPosition = 0;
434 break;
438 * 39 - BYTE: direct color mode info
439 * Bits:
440 * 0 - Set if color ramp is programmable.
441 * 1 - Set if bytes in reserved field may be used by application.
443 mib->DirectColorModeInfo = 0; /* not supported */
445 /* 40 - DWORD: physical address of linear video buffer */
446 mib->PhysBasePtr = 0; /* not supported */
448 /* 44 - DWORD: reserved, always zero */
449 mib->Reserved2 = 0;
451 /* 48 - WORD: reserved, always zero */
452 mib->Reserved3 = 0;
454 /* 50 - WORD: bytes per scan line in linear modes */
455 mib->LinBytesPerScanLine = mib->BytesPerScanLine;
457 /* 52 - BYTE: number of images (less one) for banked video modes */
458 mib->BnkNumberOfImagePages = 0; /* FIXME */
460 /* 53 - BYTE: number of images (less one) for linear video modes */
461 mib->LinNumberOfImagePages = mib->BnkNumberOfImagePages;
463 /* 54 - BYTE: red mask size (linear modes) */
464 mib->LinRedMaskSize = mib->RedMaskSize;
466 /* 55 - BYTE: red field position (linear modes) */
467 mib->LinRedFieldPosition = mib->RedFieldPosition;
469 /* 56 - BYTE: green mask size (linear modes) */
470 mib->LinGreenMaskSize = mib->GreenMaskSize;
472 /* 57 - BYTE: green field size (linear modes) */
473 mib->LinGreenFieldPosition = mib->GreenFieldPosition;
475 /* 58 - BYTE: blue mask size (linear modes) */
476 mib->LinBlueMaskSize = mib->BlueMaskSize;
478 /* 59 - BYTE: blue field position (linear modes) */
479 mib->LinBlueFieldPosition = mib->BlueFieldPosition;
481 /* 60 - BYTE: reserved mask size (linear modes) */
482 mib->LinRsvdMaskSize = mib->RsvdMaskSize;
484 /* 61 - BYTE: reserved mask position (linear modes) */
485 mib->LinRsvdFieldPosition = mib->RsvdFieldPosition;
487 /* 62 - DWORD: maximum pixel clock for graphics video mode, in Hz */
488 mib->MaxPixelClock = 0; /* FIXME */
490 /* 66 - BYTE[190]: reserved, set to zero */
491 memset( mib->Reserved4, 0, 190 );
493 return TRUE;
497 /**********************************************************************
498 * INT10_FillStateInformation
500 * Fill 64-byte buffer with VGA state and functionality information.
502 static void INT10_FillStateInformation( BYTE *buffer, BIOSDATA *data )
504 INT10_HEAP *heap = INT10_GetHeap();
506 /* 00 - DWORD: address of static functionality table */
507 *(SEGPTR*)(buffer + 0) = MAKESEGPTR( heap->WineHeapSegment,
508 offsetof(INT10_HEAP,
509 StaticModeSupport) );
511 /* 04 - BYTE[30]: copy of BIOS data starting from 0x49 (VideoMode) */
512 memmove( buffer + 4, &data->VideoMode, 30 );
514 /* 34 - BYTE: number of rows - 1 */
515 buffer[34] = data->RowsOnScreenMinus1;
517 /* 35 - WORD: bytes/character */
518 *(WORD*)(buffer + 35) = data->BytesPerChar;
520 /* 37 - BYTE: display combination code of active display */
521 buffer[37] = INT10_DCC;
523 /* 38 - BYTE: DCC of alternate display */
524 buffer[38] = 0; /* no secondary display */
526 /* 39 - WORD: number of colors supported in current mode (0000h = mono) */
527 *(WORD*)(buffer + 39) = 16; /* FIXME */
529 /* 41 - BYTE: number of pages supported in current mode */
530 buffer[41] = 1; /* FIXME */
533 * 42 - BYTE: number of scan lines active
534 * Values (hex):
535 * 00 = 200
536 * 01 = 350
537 * 02 = 400
538 * 03 = 480
540 buffer[42] = 3; /* FIXME */
542 /* 43 - BYTE: primary character block */
543 buffer[43] = 0; /* FIXME */
545 /* 44 - BYTE: secondary character block */
546 buffer[44] = 0; /* FIXME */
549 * 45 - BYTE: miscellaneous flags
550 * Bits:
551 * 0 - all modes on all displays on
552 * 1 - gray summing on
553 * 2 - monochrome display attached
554 * 3 - default palette loading disabled
555 * 4 - cursor emulation enabled
556 * 5 - 0 = intensity; 1 = blinking
557 * 6 - flat-panel display is active
558 * 7 - unused (0)
560 /* FIXME: Correct value? */
561 buffer[45] =
562 (data->VGASettings & 0x0f) |
563 ((data->ModeOptions & 1) << 4); /* cursor emulation */
566 * 46 - BYTE: non-VGA mode support
567 * Bits:
568 * 0 - BIOS supports information return for adapter interface
569 * 1 - adapter interface driver required
570 * 2 - 16-bit VGA graphics present
571 * 3 - =1 MFI attributes enabled
572 * =0 VGA attributes enabled
573 * 4 - 132-column mode supported
574 * 5-7 - reserved
576 buffer[46] = 0; /* FIXME: correct value? */
578 /* 47 - BYTE[2]: reserved, set to zero */
579 memset( buffer + 47, 0, 2 );
582 * 49 - BYTE: video memory available
583 * Values (hex):
584 * 00 - 64K
585 * 01 - 128K
586 * 02 - 192K
587 * 03 - 256K
589 buffer[49] = (data->ModeOptions & 0x60) >> 5; /* FIXME */
592 * 50 - BYTE: save pointer state flags
593 * Bits:
594 * 0 - 512 character set active
595 * 1 - dynamic save area present
596 * 2 - alpha font override active
597 * 3 - graphics font override active
598 * 4 - palette override active
599 * 5 - DCC override active
600 * 6-7 - unused (0)
602 buffer[50] = heap->StaticSavePointerFlags;
605 * 51 - BYTE: display information and status
606 * Bits:
607 * 0 - flat-panel display attached
608 * 1 - flat-panel display active
609 * 2 - color display
610 * 3-6 - reserved
611 * 7 - 640x480 flat-panel can be used simultaneously with CRT
613 buffer[51] = 4; /* FIXME: correct value? */
615 /* 52 - BYTE[12]: reserved, set to zero */
616 memset( buffer + 52, 0, 12 );
620 /**********************************************************************
621 * INT10_GetHeap
623 static INT10_HEAP *INT10_GetHeap( void )
625 static INT10_HEAP *heap_pointer = 0;
627 if (!heap_pointer)
629 WORD segment;
630 int i;
632 heap_pointer = DOSVM_AllocDataUMB( sizeof(INT10_HEAP),
633 &segment,
634 0 );
636 for (i = 0; i < 7; i++)
637 heap_pointer->StaticModeSupport[i] = 0xff; /* FIXME */
639 heap_pointer->StaticScanlineSupport = 7; /* FIXME */
640 heap_pointer->StaticNumberCharBlocks = 0; /* FIXME */
641 heap_pointer->StaticActiveCharBlocks = 0; /* FIXME */
642 heap_pointer->StaticMiscFlags = 0x8ff; /* FIXME */
643 heap_pointer->StaticReserved1 = 0;
644 heap_pointer->StaticSavePointerFlags = 0x3f; /* FIXME */
645 heap_pointer->StaticReserved2 = 0;
647 for (i=0; TRUE; i++)
649 heap_pointer->VesaModeList[i] = VGA_modelist[i].Mode;
650 if (VGA_modelist[i].Mode == 0xffff)
651 break;
654 strcpy( heap_pointer->VesaOEMName, "WINE SVGA BOARD" );
655 strcpy( heap_pointer->VesaVendorName, "WINE" );
656 strcpy( heap_pointer->VesaProductName, "WINE SVGA" );
657 strcpy( heap_pointer->VesaProductRev, "2008" );
659 heap_pointer->VesaCurrentMode = 0; /* Initialized later. */
660 heap_pointer->WineHeapSegment = segment;
663 return heap_pointer;
667 /**********************************************************************
668 * INT10_SetVideoMode
670 * Change current video mode to any VGA or VESA mode.
671 * Returns TRUE if mode is supported.
673 * Mode bitfields:
674 * 0-6: .. Mode number (combined with bit 8).
675 * 7: =0 Clear screen.
676 * =1 Preserve display memory on mode change (VGA modes).
677 * 8: =0 VGA mode.
678 * =1 VESA mode.
679 * 9: .. Reserved, must be zero.
680 * 10: .. Reserved, must be zero.
681 * 11: =0 Use default refresh rate.
682 * =1 Use user specified refresh rate.
683 * 12: .. Reserved, must be zero.
684 * 13: .. Reserved, must be zero.
685 * 14: =0 Use windowed frame buffer model.
686 * =1 Use linear frame buffer model.
687 * 15: =0 Clear screen.
688 * =1 Preserve display memory on mode change (VESA modes).
690 static BOOL INT10_SetVideoMode( BIOSDATA *data, WORD mode )
692 const VGA_MODE *ptr = VGA_GetModeInfo( mode );
693 INT10_HEAP *heap = INT10_GetHeap();
694 BOOL clearScreen = TRUE;
696 if (!ptr)
697 return FALSE;
700 * Linear framebuffer is not supported.
701 * FIXME - not sure this is valid since mode 19 is 256 color & linear
702 * of course only 1 window is addressable.
704 if (mode & 0x4000)
705 return FALSE;
708 * Check for VGA and VESA preserve video memory flag.
710 if ((mode & 0x0080) || (mode & 0x8000))
711 clearScreen = FALSE;
714 * Note that we do not mask out flags here on purpose.
716 heap->VesaCurrentMode = mode;
717 if (mode <= 0xff)
718 data->VideoMode = mode;
719 else
720 data->VideoMode = 0;
722 if (ptr->ModeType == TEXT)
724 /* Text mode. */
725 TRACE( "Setting %s %dx%d text mode (screen %s)\n",
726 IS_VESA_MODE(mode) ? "VESA" : "VGA",
727 ptr->TextCols, ptr->TextRows,
728 clearScreen ? "cleared" : "preserved" );
731 * FIXME: We should check here if alpha mode could be set.
733 VGA_SetAlphaMode( ptr->TextCols, ptr->TextRows );
735 data->VideoColumns = ptr->TextCols;
736 data->RowsOnScreenMinus1 = ptr->TextRows - 1;
738 if (clearScreen)
740 VGA_ClearText( 0, 0, ptr->TextCols-1, ptr->TextRows-1, 0x07 );
741 INT10_SetCursorPos( data, 0, 0, 0 );
742 VGA_SetCursorPos( 0, 0 );
745 else
747 /* Graphics mode. */
748 TRACE( "Setting %s %dx%dx%d graphics mode (screen %s)\n",
749 IS_VESA_MODE(mode) ? "VESA" : "VGA",
750 ptr->Width, ptr->Height, ptr->Depth,
751 clearScreen ? "cleared" : "preserved" );
753 if ( VGA_SetMode(mode) )
754 return FALSE;
757 return TRUE;
761 /**********************************************************************
762 * INT10_GetCursorPos
764 static void INT10_GetCursorPos(BIOSDATA*data,unsigned page,unsigned*X,unsigned*Y)
766 *X = data->VideoCursorPos[page*2]; /* column */
767 *Y = data->VideoCursorPos[page*2+1]; /* row */
771 /**********************************************************************
772 * INT10_SetCursorPos
774 static void INT10_SetCursorPos(BIOSDATA*data,unsigned page,unsigned X,unsigned Y)
776 data->VideoCursorPos[page*2] = X;
777 data->VideoCursorPos[page*2+1] = Y;
781 /**********************************************************************
782 * INT10_InitializeVideoMode
784 * The first time this function is called VGA emulation is set to the
785 * default text mode.
787 static void INT10_InitializeVideoMode( BIOSDATA *data )
789 static BOOL already_initialized = FALSE;
790 unsigned width;
791 unsigned height;
793 if(already_initialized)
794 return;
795 already_initialized = TRUE;
797 VGA_InitAlphaMode(&width, &height);
800 * FIXME: Add more mappings between initial size and
801 * text modes.
803 if (width >= 80 && height >= 25)
804 INT10_SetVideoMode( data, 0x03 );
805 else
806 INT10_SetVideoMode( data, 0x01 );
810 /**********************************************************************
811 * INT10_HandleVESA
813 * Handler for VESA functions (int10 function 0x4f).
815 static void INT10_HandleVESA( CONTEXT *context )
817 BIOSDATA *data = DOSVM_BiosData();
819 switch(AL_reg(context)) {
821 case 0x00: /* RETURN CONTROLLER INFORMATION */
822 TRACE( "VESA RETURN CONTROLLER INFORMATION\n" );
824 BYTE *ptr = CTX_SEG_OFF_TO_LIN(context,
825 context->SegEs,
826 context->Edi);
827 INT10_FillControllerInformation( ptr );
828 SET_AL( context, 0x4f );
829 SET_AH( context, 0x00 ); /* 0x00 = successful 0x01 = failed */
831 break;
833 case 0x01: /* RETURN MODE INFORMATION */
834 TRACE( "VESA RETURN MODE INFORMATION %04x\n", CX_reg(context) );
836 struct _ModeInfoBlock *ptr = CTX_SEG_OFF_TO_LIN(context,
837 context->SegEs,
838 context->Edi);
839 SET_AL( context, 0x4f );
840 if (INT10_FillModeInformation( ptr, CX_reg(context) ))
841 SET_AH( context, 0x00 ); /* status: success */
842 else
843 SET_AH( context, 0x01 ); /* status: failed */
845 break;
847 case 0x02: /* SET SuperVGA VIDEO MODE */
848 TRACE( "Set VESA video mode %04x\n", BX_reg(context) );
849 SET_AL( context, 0x4f ); /* function supported */
850 if (INT10_SetVideoMode( data, BX_reg(context) ))
851 SET_AH( context, 0x00 ); /* success */
852 else
853 SET_AH( context, 0x01 ); /* failed */
854 break;
856 case 0x03: /* VESA SuperVGA BIOS - GET CURRENT VIDEO MODE */
857 SET_AL( context, 0x4f );
858 SET_AH( context, 0x00 );
859 SET_BX( context, INT10_GetHeap()->VesaCurrentMode );
860 break;
862 case 0x04: /* VESA SuperVGA BIOS - SAVE/RESTORE SuperVGA VIDEO STATE */
863 ERR("VESA SAVE/RESTORE Video State - Not Implemented\n");
864 /* AL_reg(context) = 0x4f; = supported so not set since not implemented */
865 /* maybe we should do this instead ? */
866 /* AH_reg(context = 0x01; not implemented so just fail */
867 break;
869 case 0x05: /* VESA SuperVGA BIOS - CPU VIDEO MEMORY CONTROL */
871 * This subfunction supports only Window A (BL_reg == 0) and
872 * it assumes that window granularity is 64k.
874 switch(BH_reg(context)) {
875 case 0x00: /* select video memory window */
876 SET_AL( context, 0x4f ); /* function supported */
877 if(BL_reg(context) == 0) {
878 VGA_SetWindowStart(DX_reg(context) * 64 * 1024);
879 SET_AH( context, 0x00 ); /* status: successful */
880 } else
881 SET_AH( context, 0x01 ); /* status: failed */
882 break;
883 case 0x01: /* get video memory window */
884 SET_AL( context, 0x4f ); /* function supported */
885 if(BL_reg(context) == 0) {
886 SET_DX( context, VGA_GetWindowStart() / 64 / 1024 );
887 SET_AH( context, 0x00 ); /* status: successful */
888 } else
889 SET_AH( context, 0x01 ); /* status: failed */
890 break;
891 default:
892 INT_BARF( context, 0x10 );
894 break;
896 case 0x06: /* VESA GET/SET LOGICAL SCAN LINE LENGTH */
897 ERR("VESA GET/SET LOGICAL SCAN LINE LENGTH - Not Implemented\n");
898 /* AL_reg(context) = 0x4f; = supported so not set since not implemented */
899 /* maybe we should do this instead ? */
900 /* AH_reg(context = 0x001; not implemented so just fail */
901 break;
903 case 0x07: /* GET/SET DISPLAY START */
904 ERR("VESA GET/SET DISPLAY START - Not Implemented\n");
905 /* AL_reg(context) = 0x4f; = supported so not set since not implemented */
906 /* maybe we should do this instead ? */
907 /* AH_reg(context = 0x001; not implemented so just fail */
908 break;
910 case 0x08: /* GET/SET DAC PALETTE CONTROL */
911 ERR("VESA GET/SET DAC PALETTE CONTROL- Not Implemented\n");
912 /* AL_reg(context) = 0x4f; = supported so not set since not implemented */
913 /* maybe we should do this instead ? */
914 /* AH_reg(context = 0x001; not implemented so just fail */
915 break;
917 case 0x09: /* SET PALETTE ENTRIES */
918 FIXME("VESA Set palette entries - not implemented\n");
919 break;
921 case 0x0a: /* GET PROTECTED-MODE CODE */
922 FIXME("VESA Get protected-mode code - not implemented\n");
923 break;
925 case 0x10: /* Display Power Management Extensions */
926 FIXME("VESA Display Power Management Extensions - not implemented\n");
927 break;
929 case 0xef: /* get video mode for hercules-compatibles */
930 /* There's no reason to really support this */
931 /* is there?....................(A.C.) */
932 TRACE("Just report the video not hercules compatible\n");
933 SET_DX( context, 0xffff );
934 break;
936 case 0xff: /* Turn VESA ON/OFF */
937 /* I don't know what to do */
938 break;
940 default:
941 FIXME("VESA Function (0x%x) - Not Supported\n", AH_reg(context));
942 break;
947 /**********************************************************************
948 * DOSVM_Int10Handler
950 * Handler for int 10h (video).
952 * NOTE:
953 * Most INT 10 functions for text-mode, CGA, EGA, and VGA cards
954 * are present in this list. (SVGA and XGA are not) That is not
955 * to say that all these functions should be supported, but if
956 * anyone is brain-damaged enough to want to emulate one of these
957 * beasts then this should get you started.
959 * NOTE:
960 * Several common graphical extensions used by Microsoft hook
961 * off of here. I have *not* added them to this list (yet). They
962 * include:
964 * MSHERC.COM - More functionality for Hercules cards.
965 * EGA.SYS (also MOUSE.COM) - More for EGA cards.
967 * Yes, MS also added this support into their mouse driver. Don't
968 * ask me, I don't work for them.
970 * Joseph Pranevich - 9/98
972 * Jess Haas 2/99
973 * Added support for Vesa. It is not complete but is a start.
974 * NOTE: Im not sure if I did all this right or if any of it works.
975 * Currently I don't have a program that uses Vesa that actually gets far
976 * enough without crashing to do vesa stuff.
978 * Added additional vga graphic support - 3/99
980 void WINAPI DOSVM_Int10Handler( CONTEXT *context )
982 BIOSDATA *data = DOSVM_BiosData();
984 INT10_InitializeVideoMode( data );
986 switch(AH_reg(context)) {
988 case 0x00: /* SET VIDEO MODE */
989 TRACE( "Set VGA video mode %02x\n", AL_reg(context) );
990 if (!INT10_SetVideoMode( data, AL_reg(context) ))
991 FIXME( "Unsupported VGA video mode requested: %#x\n",
992 AL_reg(context) );
993 break;
995 case 0x01: /* SET CURSOR SHAPE */
996 TRACE("Set Cursor Shape start %d end %d options %d\n",
997 CH_reg(context) & 0x1f,
998 CL_reg(context) & 0x1f,
999 CH_reg(context) & 0xe0);
1000 data->VideoCursorType = CX_reg(context); /* direct copy */
1001 VGA_SetCursorShape(CH_reg(context), CL_reg(context));
1002 break;
1004 case 0x02: /* SET CURSOR POSITION */
1005 /* BH = Page Number */ /* Not supported */
1006 /* DH = Row */ /* 0 is left */
1007 /* DL = Column */ /* 0 is top */
1008 INT10_SetCursorPos(data,BH_reg(context),DL_reg(context),DH_reg(context));
1009 if (BH_reg(context))
1011 FIXME("Set Cursor Position: Cannot set to page %d\n",
1012 BH_reg(context));
1014 else
1016 VGA_SetCursorPos(DL_reg(context), DH_reg(context));
1017 TRACE("Set Cursor Position: %d/%d\n", DL_reg(context),
1018 DH_reg(context));
1020 break;
1022 case 0x03: /* GET CURSOR POSITION AND SIZE */
1024 unsigned row, col;
1026 TRACE("Get cursor position and size (page %d)\n", BH_reg(context));
1027 SET_CX( context, data->VideoCursorType );
1028 INT10_GetCursorPos(data,BH_reg(context),&col,&row);
1029 SET_DH( context, row );
1030 SET_DL( context, col );
1031 TRACE("Cursor Position: %d/%d\n", DL_reg(context), DH_reg(context));
1033 break;
1035 case 0x04: /* READ LIGHT PEN POSITION */
1036 FIXME("Read Light Pen Position - Not Supported\n");
1037 SET_AH( context, 0x00 ); /* Not down */
1038 break;
1040 case 0x05: /* SELECT ACTIVE DISPLAY PAGE */
1041 FIXME("Select Active Display Page (%d) - Not Supported\n", AL_reg(context));
1042 data->VideoCurPage = AL_reg(context);
1043 break;
1045 case 0x06: /* SCROLL UP WINDOW */
1046 /* AL = Lines to scroll */
1047 /* BH = Attribute */
1048 /* CH,CL = row, col upper-left */
1049 /* DH,DL = row, col lower-right */
1050 TRACE("Scroll Up Window %d\n", AL_reg(context));
1052 if (AL_reg(context) == 0)
1053 VGA_ClearText( CH_reg(context), CL_reg(context),
1054 DH_reg(context), DL_reg(context),
1055 BH_reg(context) );
1056 else
1057 VGA_ScrollUpText( CH_reg(context), CL_reg(context),
1058 DH_reg(context), DL_reg(context),
1059 AL_reg(context), BH_reg(context) );
1060 break;
1062 case 0x07: /* SCROLL DOWN WINDOW */
1063 /* AL = Lines to scroll */
1064 /* BH = Attribute */
1065 /* CH,CL = row, col upper-left */
1066 /* DH,DL = row, col lower-right */
1067 TRACE("Scroll Down Window %d\n", AL_reg(context));
1069 if (AL_reg(context) == 0)
1070 VGA_ClearText( CH_reg(context), CL_reg(context),
1071 DH_reg(context), DL_reg(context),
1072 BH_reg(context) );
1073 else
1074 VGA_ScrollDownText( CH_reg(context), CL_reg(context),
1075 DH_reg(context), DL_reg(context),
1076 AL_reg(context), BH_reg(context) );
1077 break;
1079 case 0x08: /* READ CHARACTER AND ATTRIBUTE AT CURSOR POSITION */
1081 if (BH_reg(context)) /* Write to different page */
1083 FIXME("Read character and attribute at cursor position -"
1084 " Can't read from non-0 page\n");
1085 SET_AL( context, ' ' ); /* That page is blank */
1086 SET_AH( context, 7 );
1088 else
1090 BYTE ascii, attr;
1091 TRACE("Read Character and Attribute at Cursor Position\n");
1092 VGA_GetCharacterAtCursor(&ascii, &attr);
1093 SET_AL( context, ascii );
1094 SET_AH( context, attr );
1097 break;
1099 case 0x09: /* WRITE CHARACTER AND ATTRIBUTE AT CURSOR POSITION */
1100 case 0x0a: /* WRITE CHARACTER ONLY AT CURSOR POSITION */
1101 /* AL = Character to display. */
1102 /* BH = Page Number */ /* We can't write to non-0 pages, yet. */
1103 /* BL = Attribute / Color */
1104 /* CX = Times to Write Char */
1105 /* Note here that the cursor is not advanced. */
1107 unsigned row, col;
1109 INT10_GetCursorPos(data,BH_reg(context),&col,&row);
1110 VGA_WriteChars(col, row,
1111 AL_reg(context),
1112 (AH_reg(context) == 0x09) ? BL_reg(context) : -1,
1113 CX_reg(context));
1114 if (CX_reg(context) > 1)
1115 TRACE("Write Character%s at Cursor Position (Rep. %d): %c\n",
1116 (AH_reg(context) == 0x09) ? " and Attribute" : "",
1117 CX_reg(context), AL_reg(context));
1118 else
1119 TRACE("Write Character%s at Cursor Position: %c\n",
1120 (AH_reg(context) == 0x09) ? " and Attribute" : "",
1121 AL_reg(context));
1123 break;
1125 case 0x0b:
1126 switch BH_reg(context) {
1127 case 0x00: /* SET BACKGROUND/BORDER COLOR */
1128 /* In text modes, this sets only the border... */
1129 /* According to the interrupt list and one of my books. */
1130 /* Funny though that Beyond Zork seems to indicate that it
1131 also sets up the default background attributes for clears
1132 and scrolls... */
1133 /* Bear in mind here that we do not want to change,
1134 apparently, the foreground or attribute of the background
1135 with this call, so we should check first to see what the
1136 foreground already is... FIXME */
1138 /* For CGA modes, background color change is the same as writing
1139 to I/O address 0x3d9 bit 4 */
1140 if(data->VideoMode >= 4 && data->VideoMode <= 6)
1142 VGA_SetBright((BL_reg(context) & 0x10) != 0);
1143 VGA_UpdatePalette();
1145 else FIXME("Set Background/Border Color: %d/%d\n",
1146 BH_reg(context), BL_reg(context));
1147 break;
1148 case 0x01: /* SET PALETTE */
1150 /* For CGA modes, palette color change is the same as writing
1151 to I/O address 0x3d9 bit 5 */
1152 if(data->VideoMode >= 4 && data->VideoMode <= 6)
1154 VGA_SetPaletteIndex(BL_reg(context) & 1);
1155 VGA_UpdatePalette();
1157 else FIXME("Set Palette - Not Supported: %02X\n", BL_reg(context));
1158 break;
1159 default:
1160 FIXME("INT 10 AH = 0x0b BH = 0x%x - Unknown\n",
1161 BH_reg(context));
1162 break;
1164 break;
1166 case 0x0c: /* WRITE GRAPHICS PIXEL */
1168 /* Only supported in CGA mode for now */
1169 if(data->VideoMode >= 4 && data->VideoMode <= 6)
1171 VGA_WritePixel(AL_reg(context), BH_reg(context), CX_reg(context), DX_reg(context));
1173 else FIXME("Write pixel not implemented for current mode\n");
1174 break;
1176 case 0x0d: /* READ GRAPHICS PIXEL */
1177 /* Not in graphics mode, can ignore w/o error */
1178 FIXME("Read Graphics Pixel - Not Supported\n");
1179 break;
1181 case 0x0e: /* TELETYPE OUTPUT */
1182 TRACE("Teletype Output\n");
1183 DOSVM_PutChar(AL_reg(context));
1184 break;
1186 case 0x0f: /* GET CURRENT VIDEO MODE */
1187 TRACE("Get current video mode: -> mode %d, columns %d\n", data->VideoMode, data->VideoColumns);
1188 /* Note: This should not be a constant value. */
1189 SET_AL( context, data->VideoMode );
1190 SET_AH( context, data->VideoColumns );
1191 SET_BH( context, 0 ); /* Display page 0 */
1192 break;
1194 case 0x10:
1195 switch AL_reg(context) {
1196 case 0x00: /* SET SINGLE PALETTE REGISTER - A.C. */
1197 TRACE("Set Single Palette Register - Reg 0x0%x Value 0x0%x\n",
1198 BL_reg(context),BH_reg(context));
1199 /* BH is the value BL is the register */
1200 VGA_SetColor16((int)BL_reg(context),(int)BH_reg(context));
1201 break;
1202 case 0x01: /* SET BORDER (OVERSCAN) */
1203 /* Text terminals have no overscan */
1204 /* I'm setting it anyway. - A.C. */
1205 TRACE("Set Border (Overscan) - Ignored but set.\n");
1206 VGA_SetColor16(16,(int)BH_reg(context));
1207 break;
1208 case 0x02: /* SET ALL PALETTE REGISTERS - A.C.*/
1209 TRACE("Set all palette registers\n");
1210 /* ES:DX points to a 17 byte table of colors */
1211 /* No return data listed */
1212 /* I'll have to update my table and the default palette */
1213 VGA_Set16Palette(CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edx));
1214 break;
1215 case 0x03: /* TOGGLE INTENSITY/BLINKING BIT */
1216 FIXME("Toggle Intensity/Blinking Bit - Not Supported\n");
1217 break;
1218 case 0x07: /* GET INDIVIDUAL PALETTE REGISTER - A.C.*/
1219 TRACE("Get Individual Palette Register 0x0%x\n",BL_reg(context));
1220 /* BL is register to read [ 0-15 ] BH is return value */
1221 SET_BH( context, VGA_GetColor16((int)BL_reg(context)) );
1222 break;
1223 case 0x08: /* READ OVERSCAN (BORDER COLOR) REGISTER - A.C. */
1224 TRACE("Read Overscan (Border Color) Register\n");
1225 SET_BH( context, VGA_GetColor16(16) );
1226 break;
1227 case 0x09: /* READ ALL PALETTE REGISTERS AND OVERSCAN REGISTER - A.C.*/
1228 TRACE("Read All Palette Registers and Overscan Register\n");
1229 /* ES:DX points to a 17 byte table where the results */
1230 /* of this call should be stored. */
1231 VGA_Get16Palette(CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edx));
1232 break;
1233 case 0x10: /* SET INDIVIDUAL DAC REGISTER */
1235 PALETTEENTRY paldat;
1237 TRACE("Set Individual DAC register\n");
1238 paldat.peRed = DH_reg(context);
1239 paldat.peGreen = CH_reg(context);
1240 paldat.peBlue = CL_reg(context);
1241 paldat.peFlags = 0;
1242 VGA_SetPalette(&paldat,BX_reg(context)&0xFF,1);
1244 break;
1245 case 0x12: /* SET BLOCK OF DAC REGISTERS */
1247 int i;
1248 PALETTEENTRY paldat;
1249 BYTE *pt;
1251 TRACE("Set Block of DAC registers\n");
1252 pt = CTX_SEG_OFF_TO_LIN(context,context->SegEs,context->Edx);
1253 for (i=0;i<CX_reg(context);i++)
1255 paldat.peRed = (*(pt+i*3+0)) << 2;
1256 paldat.peGreen = (*(pt+i*3+1)) << 2;
1257 paldat.peBlue = (*(pt+i*3+2)) << 2;
1258 paldat.peFlags = 0;
1259 VGA_SetPalette(&paldat,(BX_reg(context)+i)&0xFF,1);
1262 break;
1263 case 0x13: /* SELECT VIDEO DAC COLOR PAGE */
1264 FIXME("Select video DAC color page - Not Supported\n");
1265 break;
1266 case 0x15: /* READ INDIVIDUAL DAC REGISTER */
1267 FIXME("Read individual DAC register - Not Supported\n");
1268 break;
1269 case 0x17: /* READ BLOCK OF DAC REGISTERS */
1270 FIXME("Read block of DAC registers - Not Supported\n");
1271 break;
1272 case 0x18: /* SET PEL MASK */
1273 FIXME("Set PEL mask - Not Supported\n");
1274 break;
1275 case 0x19: /* READ PEL MASK */
1276 FIXME("Read PEL mask - Not Supported\n");
1277 break;
1278 case 0x1a: /* GET VIDEO DAC COLOR PAGE STATE */
1279 FIXME("Get video DAC color page state - Not Supported\n");
1280 break;
1281 case 0x1b: /* PERFORM GRAY-SCALE SUMMING */
1282 FIXME("Perform Gray-scale summing - Not Supported\n");
1283 break;
1284 default:
1285 FIXME("INT 10 AH = 0x10 AL = 0x%x - Unknown\n",
1286 AL_reg(context));
1287 break;
1289 break;
1291 case 0x11: /* TEXT MODE CHARGEN */
1292 /* Note that second subfunction is *almost* identical. */
1293 /* See INTERRUPT.A for details. */
1294 switch AL_reg(context) {
1295 case 0x00: /* LOAD USER SPECIFIED PATTERNS */
1296 case 0x10:
1297 FIXME("Load User Specified Patterns - Not Supported\n");
1298 break;
1299 case 0x01: /* LOAD ROM MONOCHROME PATTERNS */
1300 case 0x11:
1301 FIXME("Load ROM Monochrome Patterns - Not Supported\n");
1302 break;
1303 case 0x02: /* LOAD ROM 8x8 DOUBLE-DOT PATTERNS */
1304 case 0x12:
1305 FIXME(
1306 "Load ROM 8x8 Double Dot Patterns - Not Supported\n");
1307 break;
1308 case 0x03: /* SET BLOCK SPECIFIER */
1309 FIXME("Set Block Specifier - Not Supported\n");
1310 break;
1311 case 0x04: /* LOAD ROM 8x16 CHARACTER SET */
1312 case 0x14:
1313 FIXME("Load ROM 8x16 Character Set - Not Supported\n");
1314 break;
1315 case 0x20: /* SET USER 8x16 GRAPHICS CHARS */
1316 FIXME("Set User 8x16 Graphics Chars - Not Supported\n");
1317 break;
1318 case 0x21: /* SET USER GRAPICS CHARACTERS */
1319 FIXME("Set User Graphics Characters - Not Supported\n");
1320 break;
1321 case 0x22: /* SET ROM 8x14 GRAPHICS CHARS */
1322 FIXME("Set ROM 8x14 Graphics Chars - Not Supported\n");
1323 break;
1324 case 0x23: /* SET ROM 8x8 DBL DOT CHARS */
1325 FIXME(
1326 "Set ROM 8x8 Dbl Dot Chars (Graphics) - Not Supported\n");
1327 break;
1328 case 0x24: /* LOAD 8x16 GRAPHIC CHARS */
1329 FIXME("Load 8x16 Graphic Chars - Not Supported\n");
1330 break;
1331 case 0x30: /* GET FONT INFORMATION */
1332 FIXME("Get Font Information - Not Supported\n");
1333 break;
1334 default:
1335 FIXME("INT 10 AH = 0x11 AL = 0x%x - Unknown\n",
1336 AL_reg(context));
1337 break;
1339 break;
1341 case 0x12: /* ALTERNATE FUNCTION SELECT */
1342 switch BL_reg(context) {
1343 case 0x10: /* GET EGA INFO */
1344 TRACE("EGA info requested\n");
1345 SET_BH( context, 0x00 ); /* Color screen */
1346 SET_BL( context, data->ModeOptions >> 5 ); /* EGA memory size */
1347 SET_CX( context, data->FeatureBitsSwitches );
1348 break;
1349 case 0x20: /* ALTERNATE PRTSC */
1350 FIXME("Install Alternate Print Screen - Not Supported\n");
1351 break;
1352 case 0x30: /* SELECT VERTICAL RESOLUTION */
1353 FIXME("Select vertical resolution - not supported\n");
1354 break;
1355 case 0x31: /* ENABLE/DISABLE DEFAULT PALETTE LOADING */
1356 FIXME("Default palette loading - not supported\n");
1357 data->VGASettings =
1358 (data->VGASettings & 0xf7) |
1359 ((AL_reg(context) == 1) << 3);
1360 break;
1361 case 0x32: /* ENABLE/DISABLE VIDEO ADDRESSING */
1362 FIXME("Video Addressing - Not Supported\n");
1363 break;
1364 case 0x33: /* ENABLE/DISABLE GRAY SCALE SUMMING */
1365 FIXME("Gray Scale Summing - Not Supported\n");
1366 break;
1367 case 0x34: /* ENABLE/DISABLE CURSOR EMULATION */
1368 TRACE("Set cursor emulation to %d\n", AL_reg(context));
1369 data->ModeOptions =
1370 (data->ModeOptions & 0xfe)|(AL_reg(context) == 1);
1371 break;
1372 case 0x36: /* VIDEO ADDRESS CONTROL */
1373 FIXME("Video Address Control - Not Supported\n");
1374 break;
1375 default:
1376 FIXME("INT 10 AH = 0x11 AL = 0x%x - Unknown\n",
1377 AL_reg(context));
1378 break;
1380 break;
1382 case 0x13: /* WRITE STRING */
1383 /* This one does not imply that string be at cursor. */
1384 FIXME("Write String - Not Supported\n");
1385 break;
1387 case 0x1a:
1388 switch AL_reg(context) {
1389 case 0x00: /* GET DISPLAY COMBINATION CODE */
1390 TRACE("Get Display Combination Code\n");
1391 SET_AL( context, 0x1a ); /* Function supported */
1392 SET_BL( context, INT10_DCC ); /* Active display */
1393 SET_BH( context, 0x00 ); /* No alternate display */
1394 break;
1395 case 0x01: /* SET DISPLAY COMBINATION CODE */
1396 FIXME("Set Display Combination Code - Not Supported\n");
1397 break;
1398 default:
1399 FIXME("INT 10 AH = 0x1a AL = 0x%x - Unknown\n",
1400 AL_reg(context));
1401 break;
1403 break;
1405 case 0x1b: /* FUNCTIONALITY/STATE INFORMATION */
1406 TRACE("Get functionality/state information\n");
1407 if (BX_reg(context) == 0x0000)
1409 BYTE *ptr = CTX_SEG_OFF_TO_LIN(context,
1410 context->SegEs,
1411 context->Edi);
1412 SET_AL( context, 0x1b ); /* Function is supported */
1413 INT10_FillStateInformation( ptr, data );
1415 break;
1417 case 0x1c: /* SAVE/RESTORE VIDEO STATE */
1418 FIXME("Save/Restore Video State - Not Supported\n");
1419 break;
1421 case 0xef: /* get video mode for hercules-compatibles */
1422 /* There's no reason to really support this */
1423 /* is there?....................(A.C.) */
1424 TRACE("Just report the video not hercules compatible\n");
1425 SET_DX( context, 0xffff );
1426 break;
1428 case 0x4f: /* VESA */
1429 INT10_HandleVESA(context);
1430 break;
1432 case 0xfe: /* GET SHADOW BUFFER */
1433 TRACE( "GET SHADOW BUFFER %x:%x - ignored\n",
1434 context->SegEs, DI_reg(context) );
1435 break;
1437 default:
1438 FIXME("Unknown - 0x%x\n", AH_reg(context));
1439 INT_BARF( context, 0x10 );
1444 /**********************************************************************
1445 * DOSVM_PutChar
1447 * Write single character to VGA console at the current
1448 * cursor position and updates the BIOS cursor position.
1450 void DOSVM_PutChar( BYTE ascii )
1452 BIOSDATA *data = DOSVM_BiosData();
1453 unsigned xpos, ypos;
1455 TRACE("char: 0x%02x(%c)\n", ascii, ascii);
1457 INT10_InitializeVideoMode( data );
1459 VGA_PutChar( ascii );
1460 VGA_GetCursorPos( &xpos, &ypos );
1461 INT10_SetCursorPos( data, 0, xpos, ypos );