Fixed a couple of crashes.
[wine.git] / dlls / winedos / int10.c
blobd387097874835c135e4b23f073001e591dd2525b
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "config.h"
24 #include <stdlib.h>
26 #include "miscemu.h"
27 #include "vga.h"
28 #include "wine/debug.h"
29 #include "dosexe.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(int);
34 * Display combination code for active display.
36 * Values (hex):
37 * 00 - no display
38 * 01 - monochrome adapter w/ monochrome display
39 * 02 - CGA w/ color display
40 * 03 - reserved
41 * 04 - EGA w/ color display
42 * 05 - EGA w/ monochrome display
43 * 06 - PGA w/ color display
44 * 07 - VGA w/ monochrome analog display
45 * 08 - VGA w/ color analog display
46 * 09 - reserved
47 * 0A - MCGA w/ digital color display
48 * 0B - MCGA w/ monochrome analog display
49 * 0C - MCGA w/ color analog display
50 * FF - unknown display type
52 #define INT10_DCC 0x08
54 #include "pshpack1.h"
57 * Structure for DOS data that can be accessed directly from applications.
58 * This structure must be correctly packed.
60 typedef struct _INT10_HEAP {
61 BYTE StaticModeSupport[7]; /* modes supported 1..7 */
62 BYTE StaticScanlineSupport; /* scan lines supported */
63 BYTE StaticNumberCharBlocks; /* total number of char blocks */
64 BYTE StaticActiveCharBlocks; /* max number of active char blocks */
65 WORD StaticMiscFlags; /* misc function support flags */
66 WORD StaticReserved1; /* reserved */
67 BYTE StaticSavePointerFlags; /* save pointer function flags */
68 BYTE StaticReserved2; /* reserved */
70 WORD VesaCurrentMode;
71 WORD VesaModeList[64];
72 char VesaOEMName[32];
73 char VesaProductName[32];
74 char VesaProductRev[32];
75 char VesaVendorName[32];
77 WORD WineHeapSegment;
78 } INT10_HEAP;
81 * Structure for VBE Mode Info Block. See the VBE 3.0 standard for details.
82 * This structure must be correctly packed.
84 struct _ModeInfoBlock {
85 WORD ModeAttributes; /* 0x00 */
86 BYTE WinAAttributes; /* 0x02 */
87 BYTE WinBAttributes; /* 0x03 */
88 WORD WinGranularity; /* 0x04 */
89 WORD WinSize; /* 0x06 */
90 WORD WinASegment; /* 0x08 */
91 WORD WinBSegment; /* 0x0A */
92 DWORD WinFuncPtr; /* 0x0C */
93 WORD BytesPerScanLine; /* 0x10 */
94 /* mandatory for VBE 1.2+ */
95 WORD XResolution; /* 0x12 */
96 WORD YResolution; /* 0x14 */
97 BYTE XCharSize; /* 0x16 */
98 BYTE YCharSize; /* 0x17 */
99 BYTE NumberOfPlanes; /* 0x18 */
100 BYTE BitsPerPixel; /* 0x19 */
101 BYTE NumberOfBanks; /* 0x1A */
102 BYTE MemoryModel; /* 0x1B */
103 BYTE BankSize; /* 0x1C */
104 BYTE NumberOfImagePages; /* 0x1D */
105 BYTE Reserved1; /* 0x1E */
106 BYTE RedMaskSize; /* 0x1F */
107 BYTE RedFieldPosition; /* 0x20 */
108 BYTE GreenMaskSize; /* 0x21 */
109 BYTE GreenFieldPosition; /* 0x22 */
110 BYTE BlueMaskSize; /* 0x23 */
111 BYTE BlueFieldPosition; /* 0x24 */
112 BYTE RsvdMaskSize; /* 0x25 */
113 BYTE RsvdFieldPosition; /* 0x26 */
114 BYTE DirectColorModeInfo; /* 0x27 */
115 /* mandatory for VBE 2.0+ */
116 DWORD PhysBasePtr; /* 0x28 */
117 DWORD Reserved2; /* 0x2C */
118 WORD Reserved3; /* 0x30 */
119 /* mandatory for VBE 3.0+ */
120 WORD LinBytesPerScanLine; /* 0x32 */
121 BYTE BnkNumberOfImagePages;/* 0x34 */
122 BYTE LinNumberOfImagePages;/* 0x35 */
123 BYTE LinRedMaskSize; /* 0x36 */
124 BYTE LinRedFieldPosition; /* 0x37 */
125 BYTE LinGreenMaskSize; /* 0x38 */
126 BYTE LinGreenFieldPosition;/* 0x39 */
127 BYTE LinBlueMaskSize; /* 0x3A */
128 BYTE LinBlueFieldPosition; /* 0x3B */
129 BYTE LinRsvdMaskSize; /* 0x3C */
130 BYTE LinRsvdFieldPosition; /* 0x3D */
131 DWORD MaxPixelClock; /* 0x3E */
132 BYTE Reserved4[190]; /* 0x42 */
135 #include "poppack.h"
138 * Wine internal information about video modes.
139 * If depth is zero, the mode is considered to
140 * be a text mode.
142 typedef struct {
143 WORD Mode;
144 WORD Width;
145 WORD Height;
146 WORD Depth;
147 } INT10_MODE;
151 * List of supported video modes.
153 static const INT10_MODE INT10_modelist[] =
155 {0x0000, 40, 25, 0},
156 {0x0001, 40, 25, 0},
157 {0x0002, 80, 25, 0},
158 {0x0003, 80, 25, 0},
159 {0x0007, 80, 25, 0},
160 {0x000d, 320, 200, 4},
161 {0x000e, 640, 200, 4},
162 {0x0010, 640, 350, 4},
163 {0x0012, 640, 480, 4},
164 {0x0013, 320, 200, 8},
165 {0x006a, 800, 600, 4}, /* VESA mode, same as 0x102 */
166 {0x0100, 640, 400, 8},
167 {0x0101, 640, 480, 8},
168 {0x0102, 800, 600, 4},
169 {0x0103, 800, 600, 8},
170 {0x0104, 1024, 768, 4},
171 {0x0105, 1024, 768, 8},
172 {0x0106, 1280, 1024, 4},
173 {0x0107, 1280, 1024, 8},
174 {0x0108, 80, 60, 0},
175 {0x0109, 132, 25, 0},
176 {0x010a, 132, 43, 0},
177 {0x010b, 132, 50, 0},
178 {0x010c, 132, 60, 0},
179 {0x010d, 320, 200, 15},
180 {0x010e, 320, 200, 16},
181 {0x010f, 320, 200, 24},
182 {0x0110, 640, 480, 15},
183 {0x0111, 640, 480, 16},
184 {0x0112, 640, 480, 24},
185 {0x0113, 800, 600, 15},
186 {0x0114, 800, 600, 16},
187 {0x0115, 800, 600, 24},
188 {0x0116, 1024, 768, 15},
189 {0x0117, 1024, 768, 16},
190 {0x0118, 1024, 768, 24},
191 {0x0119, 1280, 1024, 15},
192 {0x011a, 1280, 1024, 16},
193 {0x011b, 1280, 1024, 24},
194 {0xffff, 0, 0, 0}
197 /* True if video mode is a vesa mode, false otherwise.
198 * More correct would be to use something like (x > 0xff || x == 0x6a)
199 * but as long as we have only the standard VGA and VESA modes this is ok too */
200 #define IS_VESA_MODE(x) ((x) >= 0x6a)
202 /* Forward declarations. */
203 static INT10_HEAP *INT10_GetHeap(void);
204 static void INT10_SetCursorPos(BIOSDATA*, unsigned, unsigned, unsigned);
207 /**********************************************************************
208 * INT10_FindMode
210 static const INT10_MODE *INT10_FindMode( WORD mode )
212 const INT10_MODE *ptr = INT10_modelist;
215 * Filter out flags.
217 mode &= 0x17f;
219 while (ptr->Mode != 0xffff)
221 if (ptr->Mode == mode)
222 return ptr;
223 ptr++;
226 return NULL;
230 /**********************************************************************
231 * INT10_FillControllerInformation
233 * Fill 256-byte (VBE1.x) or 512-byte buffer (VBE2.0+) with
234 * capabilities of the video controller.
236 static void INT10_FillControllerInformation( BYTE *buffer )
238 INT10_HEAP *heap = INT10_GetHeap();
240 /* 00 - BYTE[4]: signature */
241 memmove( buffer, "VESA", 4 );
243 /* 04 - WORD: version number */
244 *(WORD*)(buffer + 4) = 0x0300; /* version 3.0 */
246 /* 06 - DWORD: pointer to OEM name */
247 *(SEGPTR*)(buffer + 6) = MAKESEGPTR( heap->WineHeapSegment,
248 offsetof(INT10_HEAP,
249 VesaOEMName) );
252 * 10 - DWORD: capabilities flags
253 * Bits:
254 * 0 - DAC can be switched into 8-bit mode
255 * 1 - non-VGA controller
256 * 2 - programmed DAC with blank bit
257 * 3 - controller supports hardware stereoscopic signalling
258 * 4 - =0 stereo signalling via external VESA stereo connector
259 * =1 stereo signalling via VESA EVC connector
260 * 5 - controller supports hardware mouse cursor
261 * 6 - controller supports hardware clipping
262 * 7 - controller supports transparent BitBLT
263 * 8-31 - reserved (0)
265 *(DWORD*)(buffer + 10) = 0; /* FIXME */
267 /* 14 - DWORD: pointer to list of supported VESA and OEM video modes */
268 *(SEGPTR*)(buffer + 14) = MAKESEGPTR( heap->WineHeapSegment,
269 offsetof(INT10_HEAP,
270 VesaModeList) );
272 /* 18 - WORD: total amount of video memory in 64K blocks */
273 *(WORD*)(buffer + 18) = 16; /* FIXME */
275 /* 20 - WORD: OEM software version (BCD, high byte = major) */
276 *(WORD*)(buffer + 20) = 0x0100; /* version 1.0 */
278 /* 22 - DWORD: pointer to vendor name */
279 *(SEGPTR*)(buffer + 22) = MAKESEGPTR( heap->WineHeapSegment,
280 offsetof(INT10_HEAP,
281 VesaVendorName) );
283 /* 26 - DWORD: pointer to product name */
284 *(SEGPTR*)(buffer + 26) = MAKESEGPTR( heap->WineHeapSegment,
285 offsetof(INT10_HEAP,
286 VesaProductName) );
288 /* 30 - DWORD: pointer to product revision string */
289 *(SEGPTR*)(buffer + 30) = MAKESEGPTR( heap->WineHeapSegment,
290 offsetof(INT10_HEAP,
291 VesaProductRev) );
293 /* 34 - WORD: VBE/AF version (if capabilities bit 3 set) */
294 *(WORD*)(buffer + 34) = 0;
297 * 36 - DWORD: pointer to list of accelerated modes
298 * (if capabilities bit 3 set)
300 *(SEGPTR*)(buffer + 36) = 0;
302 /* 40 - BYTE[216]: reserved for VBE implementation, set to zero */
303 memset( buffer + 40, 216, 0 );
306 * 256 - BYTE[256]: reserved for VBE3.0 implementation,
307 * ignored in order to support older programs
312 /**********************************************************************
313 * INT10_FillModeInformation
315 * Fill 256-byte buffer with extended information about display mode.
317 * Returns FALSE if mode is unknown and TRUE is mode is known
318 * even if it is not supported.
320 static BOOL INT10_FillModeInformation( struct _ModeInfoBlock *mib, WORD mode )
322 const INT10_MODE *ptr = INT10_FindMode( mode );
323 if (!ptr)
324 return FALSE;
327 * 00 - WORD: mode attributes
328 * Bits:
329 * 0 - Mode supported by present hardware configuration.
330 * 1 - Optional information available. Must be =1 for VBE v1.2+.
331 * 2 - BIOS output supported.
332 * Int10 functions 01, 02, 06, 07, 09, 0a and 0e are supported.
333 * 3 - Set if color, clear if monochrome.
334 * 4 - Set if graphics mode, clear if text mode.
335 * 5 - Mode is not VGA-compatible if set.
336 * VGA-compatible modes support standard VGA I/O ports.
337 * 6 - Bank-switched (or windowed) mode is not supported if set.
338 * 7 - Linear framebuffer mode supported.
339 * 8 - Double scanning supported.
340 * 9 - Interlaced operation supported.
341 * 10 - Triple buffering supported.
342 * 11 - Stereoscopic display supported.
343 * 12 - Dual display start address supported.
344 * 13-15 - Reserved.
347 WORD attr = 0x000a; /* color mode, optional info */
350 * FIXME: Attribute handling is incomplete.
353 /* Mode supported? FIXME: correct value */
354 attr |= 0x0001;
356 /* Graphical mode? */
357 if (ptr->Depth)
358 attr |= 0x0010;
360 /* Not VGA-compatible? */
361 if (IS_VESA_MODE(mode))
362 attr |= 0x0020;
364 mib->ModeAttributes = attr;
368 * 02 - BYTE[2]: window attributes, window A and window B
369 * Bits:
370 * 0 - Window exists.
371 * 1 - Window is readable.
372 * 2 - Window is writable.
373 * 3-7 - Reserved.
375 mib->WinAAttributes = 0x07; /* window A exists, readable and writable */
376 mib->WinBAttributes = 0x00; /* window B not supported */
378 /* 04 - WORD: window granularity in KB */
379 mib->WinGranularity = 64;
381 /* 06 - WORD: window size in KB */
382 mib->WinSize = 64;
384 /* 08 - WORD[2]: start segments, window A and window B */
385 mib->WinASegment = 0xa000; /* window A segment */
386 mib->WinBSegment = 0x0000; /* window B not supported */
388 /* 12 - DWORD: window positioning function */
389 mib->WinFuncPtr = 0; /* not supported */
391 /* 16 - WORD: bytes per scan line */
392 /* FIXME: is this always correct? */
393 mib->BytesPerScanLine = ptr->Width * (ptr->Depth ? (ptr->Depth + 7) / 8 : 1);
395 /* 18 - WORD: width in pixels (graphics) or characters (text) */
396 mib->XResolution = ptr->Width;
398 /* 20 - WORD: height in pixels (graphics) or characters (text) */
399 mib->YResolution = ptr->Height;
401 /* 22 - BYTE: width of character cell in pixels */
402 mib->XCharSize = 0; /* FIXME */
404 /* 23 - BYTE: height of character cell in pixels */
405 mib->YCharSize = 0; /* FIXME */
407 /* 24 - BYTE: number of memory planes */
408 mib->NumberOfPlanes = 1; /* FIXME */
410 /* 25 - BYTE: number of bits per pixel */
411 mib->BitsPerPixel = ptr->Depth; /* FIXME: text modes? reserved bits? */
413 /* 26 - BYTE: number of banks */
414 mib->NumberOfBanks = 1; /* FIXME */
417 * 27 - BYTE: memory model type
418 * Values (hex):
419 * 00 - Text mode
420 * 01 - CGA graphics
421 * 02 - Hercules graphics
422 * 03 - Planar
423 * 04 - Packed pixel
424 * 05 - Non-chain 4, 256 color
425 * 06 - Direct color
426 * 07 - YUV
427 * 08-0F - Reserved for VESA.
428 * 10-FF - OEM memory models.
430 if (!ptr->Depth)
431 mib->MemoryModel = 0; /* text mode */
432 else
433 mib->MemoryModel = 3; /* FIXME */
435 /* 28 - BYTE: size of bank in KB */
436 mib->BankSize = 0; /* FIXME */
438 /* 29 - BYTE: number of image pages (less one) in video RAM */
439 mib->NumberOfImagePages = 0; /* FIXME */
441 /* 30 - BYTE: reserved (0x00 for VBE 1.0-2.0, 0x01 for VBE 3.0) */
442 mib->Reserved1 = 0x01;
445 * 31,33,35 - BYTE: red/green/blue mask size
446 * Size of red/green/blue color component in bits.
447 * 32,34,36 - BYTE: red/green/blue field position
448 * Bit position of the least significant bit of red/green/blue color
449 * component.
450 * Both should be only used when memory model is direct color or YUV but
451 * "Imperium Romanum" uses this fields even when memory model is planar.
452 * So always fill this fields when we have a depth bigger then 8, otherwise
453 * set them to zero.
455 switch (ptr->Depth) {
456 case 24:
457 mib->RedMaskSize = 8;
458 mib->GreenMaskSize = 8;
459 mib->BlueMaskSize = 8;
460 mib->RsvdMaskSize = 0;
461 mib->RedFieldPosition = 16;
462 mib->GreenFieldPosition = 8;
463 mib->BlueFieldPosition = 0;
464 mib->RsvdFieldPosition = 0;
465 break;
466 case 16:
467 mib->RedMaskSize = 5;
468 mib->GreenMaskSize = 6;
469 mib->BlueMaskSize = 5;
470 mib->RsvdMaskSize = 0;
471 mib->RedFieldPosition = 11;
472 mib->GreenFieldPosition = 5;
473 mib->BlueFieldPosition = 0;
474 mib->RsvdFieldPosition = 0;
475 break;
476 case 15:
477 mib->RedMaskSize = 5;
478 mib->GreenMaskSize = 5;
479 mib->BlueMaskSize = 5;
480 mib->RsvdMaskSize = 1;
481 mib->RedFieldPosition = 10;
482 mib->GreenFieldPosition = 5;
483 mib->BlueFieldPosition = 0;
484 mib->RsvdFieldPosition = 15;
485 break;
486 default:
487 mib->RedMaskSize = 0;
488 mib->GreenMaskSize = 0;
489 mib->BlueMaskSize = 0;
490 mib->RsvdMaskSize = 0;
491 mib->RedFieldPosition = 0;
492 mib->GreenFieldPosition = 0;
493 mib->BlueFieldPosition = 0;
494 mib->RsvdFieldPosition = 0;
495 break;
499 * 39 - BYTE: direct color mode info
500 * Bits:
501 * 0 - Set if color ramp is programmable.
502 * 1 - Set if bytes in reserved field may be used by application.
504 mib->DirectColorModeInfo = 0; /* not supported */
506 /* 40 - DWORD: physical address of linear video buffer */
507 mib->PhysBasePtr = 0; /* not supported */
509 /* 44 - DWORD: reserved, always zero */
510 mib->Reserved2 = 0;
512 /* 48 - WORD: reserved, always zero */
513 mib->Reserved3 = 0;
515 /* 50 - WORD: bytes per scan line in linear modes */
516 mib->LinBytesPerScanLine = mib->BytesPerScanLine;
518 /* 52 - BYTE: number of images (less one) for banked video modes */
519 mib->BnkNumberOfImagePages = 0; /* FIXME */
521 /* 53 - BYTE: number of images (less one) for linear video modes */
522 mib->LinNumberOfImagePages = mib->BnkNumberOfImagePages;
524 /* 54 - BYTE: red mask size (linear modes) */
525 mib->LinRedMaskSize = mib->RedMaskSize;
527 /* 55 - BYTE: red field position (linear modes) */
528 mib->LinRedFieldPosition = mib->RedFieldPosition;
530 /* 56 - BYTE: green mask size (linear modes) */
531 mib->LinGreenMaskSize = mib->GreenMaskSize;
533 /* 57 - BYTE: green field size (linear modes) */
534 mib->LinGreenFieldPosition = mib->GreenFieldPosition;
536 /* 58 - BYTE: blue mask size (linear modes) */
537 mib->LinBlueMaskSize = mib->BlueMaskSize;
539 /* 59 - BYTE: blue field position (linear modes) */
540 mib->LinBlueFieldPosition = mib->BlueFieldPosition;
542 /* 60 - BYTE: reserved mask size (linear modes) */
543 mib->LinRsvdMaskSize = mib->RsvdMaskSize;
545 /* 61 - BYTE: reserved mask position (linear modes) */
546 mib->LinRsvdFieldPosition = mib->RsvdFieldPosition;
548 /* 62 - DWORD: maximum pixel clock for graphics video mode, in Hz */
549 mib->MaxPixelClock = 0; /* FIXME */
551 /* 66 - BYTE[190]: reserved, set to zero */
552 memset( &mib->Reserved4, 190, 0 );
554 return TRUE;
558 /**********************************************************************
559 * INT10_FillStateInformation
561 * Fill 64-byte buffer with VGA state and functionality information.
563 static void INT10_FillStateInformation( BYTE *buffer, BIOSDATA *data )
565 INT10_HEAP *heap = INT10_GetHeap();
567 /* 00 - DWORD: address of static functionality table */
568 *(SEGPTR*)(buffer + 0) = MAKESEGPTR( heap->WineHeapSegment,
569 offsetof(INT10_HEAP,
570 StaticModeSupport) );
572 /* 04 - BYTE[30]: copy of BIOS data starting from 0x49 (VideoMode) */
573 memmove( buffer + 4, &data->VideoMode, 30 );
575 /* 34 - BYTE: number of rows - 1 */
576 buffer[34] = data->RowsOnScreenMinus1;
578 /* 35 - WORD: bytes/character */
579 *(WORD*)(buffer + 35) = data->BytesPerChar;
581 /* 37 - BYTE: display combination code of active display */
582 buffer[37] = INT10_DCC;
584 /* 38 - BYTE: DCC of alternate display */
585 buffer[38] = 0; /* no secondary display */
587 /* 39 - WORD: number of colors supported in current mode (0000h = mono) */
588 *(WORD*)(buffer + 39) = 16; /* FIXME */
590 /* 41 - BYTE: number of pages supported in current mode */
591 buffer[41] = 1; /* FIXME */
594 * 42 - BYTE: number of scan lines active
595 * Values (hex):
596 * 00 = 200
597 * 01 = 350
598 * 02 = 400
599 * 03 = 480
601 buffer[42] = 3; /* FIXME */
603 /* 43 - BYTE: primary character block */
604 buffer[43] = 0; /* FIXME */
606 /* 44 - BYTE: secondary character block */
607 buffer[44] = 0; /* FIXME */
610 * 45 - BYTE: miscellaneous flags
611 * Bits:
612 * 0 - all modes on all displays on
613 * 1 - gray summing on
614 * 2 - monochrome display attached
615 * 3 - default palette loading disabled
616 * 4 - cursor emulation enabled
617 * 5 - 0 = intensity; 1 = blinking
618 * 6 - flat-panel display is active
619 * 7 - unused (0)
621 /* FIXME: Correct value? */
622 buffer[45] =
623 (data->VGASettings & 0x0f) |
624 ((data->ModeOptions & 1) << 4); /* cursor emulation */
627 * 46 - BYTE: non-VGA mode support
628 * Bits:
629 * 0 - BIOS supports information return for adapter interface
630 * 1 - adapter interface driver required
631 * 2 - 16-bit VGA graphics present
632 * 3 - =1 MFI attributes enabled
633 * =0 VGA attributes enabled
634 * 4 - 132-column mode supported
635 * 5-7 - reserved
637 buffer[46] = 0; /* FIXME: correct value? */
639 /* 47 - BYTE[2]: reserved, set to zero */
640 memset( buffer + 47, 2, 0 );
643 * 49 - BYTE: video memory available
644 * Values (hex):
645 * 00 - 64K
646 * 01 - 128K
647 * 02 - 192K
648 * 03 - 256K
650 buffer[49] = (data->ModeOptions & 0x60) >> 5; /* FIXME */
653 * 50 - BYTE: save pointer state flags
654 * Bits:
655 * 0 - 512 character set active
656 * 1 - dynamic save area present
657 * 2 - alpha font override active
658 * 3 - graphics font override active
659 * 4 - palette override active
660 * 5 - DCC override active
661 * 6-7 - unused (0)
663 buffer[50] = heap->StaticSavePointerFlags;
666 * 51 - BYTE: display information and status
667 * Bits:
668 * 0 - flat-panel display attached
669 * 1 - flat-panel display active
670 * 2 - color display
671 * 3-6 - reserved
672 * 7 - 640x480 flat-panel can be used simultaneously with CRT
674 buffer[51] = 4; /* FIXME: correct value? */
676 /* 52 - BYTE[12]: reserved, set to zero */
677 memset( buffer + 52, 12, 0 );
681 /**********************************************************************
682 * INT10_GetHeap
684 INT10_HEAP *INT10_GetHeap( void )
686 static INT10_HEAP *heap_pointer = 0;
688 if (!heap_pointer)
690 WORD segment;
691 int i;
693 heap_pointer = DOSVM_AllocDataUMB( sizeof(INT10_HEAP),
694 &segment,
695 0 );
697 for (i = 0; i < 7; i++)
698 heap_pointer->StaticModeSupport[i] = 0xff; /* FIXME */
700 heap_pointer->StaticScanlineSupport = 7; /* FIXME */
701 heap_pointer->StaticNumberCharBlocks = 0; /* FIXME */
702 heap_pointer->StaticActiveCharBlocks = 0; /* FIXME */
703 heap_pointer->StaticMiscFlags = 0x8ff; /* FIXME */
704 heap_pointer->StaticReserved1 = 0;
705 heap_pointer->StaticSavePointerFlags = 0x3f; /* FIXME */
706 heap_pointer->StaticReserved2 = 0;
708 for (i=0; TRUE; i++)
710 heap_pointer->VesaModeList[i] = INT10_modelist[i].Mode;
711 if (INT10_modelist[i].Mode == 0xffff)
712 break;
715 strcpy( heap_pointer->VesaOEMName, "WINE SVGA BOARD" );
716 strcpy( heap_pointer->VesaVendorName, "WINE" );
717 strcpy( heap_pointer->VesaProductName, "WINE SVGA" );
718 strcpy( heap_pointer->VesaProductRev, "2003" );
720 heap_pointer->VesaCurrentMode = 0; /* Initialized later. */
721 heap_pointer->WineHeapSegment = segment;
724 return heap_pointer;
728 /**********************************************************************
729 * INT10_SetVideoMode
731 * Change current video mode to any VGA or VESA mode.
732 * Returns TRUE if mode is supported.
734 * Mode bitfields:
735 * 0-6: .. Mode number (combined with bit 8).
736 * 7: =0 Clear screen.
737 * =1 Preserve display memory on mode change (VGA modes).
738 * 8: =0 VGA mode.
739 * =1 VESA mode.
740 * 9: .. Reserved, must be zero.
741 * 10: .. Reserved, must be zero.
742 * 11: =0 Use default refresh rate.
743 * =1 Use user specified refresh rate.
744 * 12: .. Reserved, must be zero.
745 * 13: .. Reserved, must be zero.
746 * 14: =0 Use windowed frame buffer model.
747 * =1 Use linear frame buffer model.
748 * 15: =0 Clear screen.
749 * =1 Preserve display memory on mode change (VESA modes).
751 static BOOL INT10_SetVideoMode( BIOSDATA *data, WORD mode )
753 const INT10_MODE *ptr = INT10_FindMode( mode );
754 INT10_HEAP *heap = INT10_GetHeap();
755 BOOL clearScreen = TRUE;
757 if (!ptr)
758 return FALSE;
761 * Linear framebuffer is not supported.
763 if (mode & 0x4000)
764 return FALSE;
767 * Check for VGA and VESA preserve video memory flag.
769 if ((mode & 0x0080) || (mode & 0x8000))
770 clearScreen = FALSE;
773 * Note that we do not mask out flags here on purpose.
775 heap->VesaCurrentMode = mode;
776 if (mode <= 0xff)
777 data->VideoMode = mode;
778 else
779 data->VideoMode = 0;
781 if (ptr->Depth == 0)
783 /* Text mode. */
784 TRACE( "Setting %s %dx%d text mode (screen %s)\n",
785 IS_VESA_MODE(mode) ? "VESA" : "VGA",
786 ptr->Width, ptr->Height,
787 clearScreen ? "cleared" : "preserved" );
790 * FIXME: We should check here if alpha mode could be set.
792 VGA_SetAlphaMode( ptr->Width, ptr->Height );
794 data->VideoColumns = ptr->Width;
795 data->RowsOnScreenMinus1 = ptr->Height - 1;
797 if (clearScreen)
799 VGA_ClearText( 0, 0, ptr->Height-1, ptr->Width-1, 0x07 );
800 INT10_SetCursorPos( data, 0, 0, 0 );
801 VGA_SetCursorPos( 0, 0 );
804 else
806 /* Graphics mode. */
807 TRACE( "Setting %s %dx%dx%d graphics mode (screen %s)\n",
808 IS_VESA_MODE(mode) ? "VESA" : "VGA",
809 ptr->Width, ptr->Height, ptr->Depth,
810 clearScreen ? "cleared" : "preserved" );
812 if (VGA_SetMode( ptr->Width, ptr->Height, ptr->Depth ))
813 return FALSE;
816 return TRUE;
820 /**********************************************************************
821 * INT10_GetCursorPos
823 static void INT10_GetCursorPos(BIOSDATA*data,unsigned page,unsigned*X,unsigned*Y)
825 *X = data->VideoCursorPos[page*2]; /* column */
826 *Y = data->VideoCursorPos[page*2+1]; /* row */
830 /**********************************************************************
831 * INT10_SetCursorPos
833 static void INT10_SetCursorPos(BIOSDATA*data,unsigned page,unsigned X,unsigned Y)
835 data->VideoCursorPos[page*2] = X;
836 data->VideoCursorPos[page*2+1] = Y;
840 /**********************************************************************
841 * INT10_InitializeVideoMode
843 * The first time this function is called VGA emulation is set to the
844 * default text mode.
846 static void INT10_InitializeVideoMode( BIOSDATA *data )
848 static BOOL already_initialized = FALSE;
849 unsigned width;
850 unsigned height;
852 if(already_initialized)
853 return;
854 already_initialized = TRUE;
856 VGA_InitAlphaMode(&width, &height);
859 * FIXME: Add more mappings between initial size and
860 * text modes.
862 if (width >= 80 && height >= 25)
863 INT10_SetVideoMode( data, 0x03 );
864 else
865 INT10_SetVideoMode( data, 0x01 );
869 /**********************************************************************
870 * INT10_HandleVESA
872 * Handler for VESA functions (int10 function 0x4f).
874 static void INT10_HandleVESA( CONTEXT86 *context )
876 BIOSDATA *data = DOSVM_BiosData();
878 switch(AL_reg(context)) {
880 case 0x00: /* RETURN CONTROLLER INFORMATION */
881 TRACE( "VESA RETURN CONTROLLER INFORMATION\n" );
883 BYTE *ptr = CTX_SEG_OFF_TO_LIN(context,
884 context->SegEs,
885 context->Edi);
886 INT10_FillControllerInformation( ptr );
887 SET_AL( context, 0x4f );
888 SET_AH( context, 0x00 ); /* 0x00 = successful 0x01 = failed */
890 break;
892 case 0x01: /* RETURN MODE INFORMATION */
893 TRACE( "VESA RETURN MODE INFORMATION %04x\n", CX_reg(context) );
895 struct _ModeInfoBlock *ptr = CTX_SEG_OFF_TO_LIN(context,
896 context->SegEs,
897 context->Edi);
898 SET_AL( context, 0x4f );
899 if (INT10_FillModeInformation( ptr, CX_reg(context) ))
900 SET_AH( context, 0x00 ); /* status: success */
901 else
902 SET_AH( context, 0x01 ); /* status: failed */
904 break;
906 case 0x02: /* SET SuperVGA VIDEO MODE */
907 TRACE( "Set VESA video mode %04x\n", BX_reg(context) );
908 SET_AL( context, 0x4f ); /* function supported */
909 if (INT10_SetVideoMode( data, BX_reg(context) ))
910 SET_AH( context, 0x00 ); /* success */
911 else
912 SET_AH( context, 0x01 ); /* failed */
913 break;
915 case 0x03: /* VESA SuperVGA BIOS - GET CURRENT VIDEO MODE */
916 SET_AL( context, 0x4f );
917 SET_AH( context, 0x00 );
918 SET_BX( context, INT10_GetHeap()->VesaCurrentMode );
919 break;
921 case 0x04: /* VESA SuperVGA BIOS - SAVE/RESTORE SuperVGA VIDEO STATE */
922 ERR("VESA SAVE/RESTORE Video State - Not Implemented\n");
923 /* AL_reg(context) = 0x4f; = supported so not set since not implemented */
924 /* maybe we should do this instead ? */
925 /* AH_reg(context = 0x01; not implemented so just fail */
926 break;
928 case 0x05: /* VESA SuperVGA BIOS - CPU VIDEO MEMORY CONTROL */
930 * This subfunction supports only Window A (BL_reg == 0) and
931 * is assumes that window granularity is 64k.
933 switch(BH_reg(context)) {
934 case 0x00: /* select video memory window */
935 SET_AL( context, 0x4f ); /* function supported */
936 if(BL_reg(context) == 0) {
937 VGA_SetWindowStart(DX_reg(context) * 64 * 1024);
938 SET_AH( context, 0x00 ); /* status: successful */
939 } else
940 SET_AH( context, 0x01 ); /* status: failed */
941 break;
942 case 0x01: /* get video memory window */
943 SET_AL( context, 0x4f ); /* function supported */
944 if(BL_reg(context) == 0) {
945 SET_DX( context, VGA_GetWindowStart() / 64 / 1024 );
946 SET_AH( context, 0x00 ); /* status: successful */
947 } else
948 SET_AH( context, 0x01 ); /* status: failed */
949 break;
950 default:
951 INT_BARF( context, 0x10 );
953 break;
955 case 0x06: /* VESA GET/SET LOGICAL SCAN LINE LENGTH */
956 ERR("VESA GET/SET LOGICAL SCAN LINE LENGTH - Not Implemented\n");
957 /* AL_reg(context) = 0x4f; = supported so not set since not implemented */
958 /* maybe we should do this instead ? */
959 /* AH_reg(context = 0x001; not implemented so just fail */
960 break;
962 case 0x07: /* GET/SET DISPLAY START */
963 ERR("VESA GET/SET DISPLAY START - Not Implemented\n");
964 /* AL_reg(context) = 0x4f; = supported so not set since not implemented */
965 /* maybe we should do this instead ? */
966 /* AH_reg(context = 0x001; not implemented so just fail */
967 break;
969 case 0x08: /* GET/SET DAC PALETTE CONTROL */
970 ERR("VESA GET/SET DAC PALETTE CONTROL- Not Implemented\n");
971 /* AL_reg(context) = 0x4f; = supported so not set since not implemented */
972 /* maybe we should do this instead ? */
973 /* AH_reg(context = 0x001; not implemented so just fail */
974 break;
976 case 0x09: /* SET PALETTE ENTRIES */
977 FIXME("VESA Set palette entries - not implemented\n");
978 break;
980 case 0x0a: /* GET PROTECTED-MODE CODE */
981 FIXME("VESA Get protected-mode code - not implemented\n");
982 break;
984 case 0x10: /* Display Power Management Extensions */
985 FIXME("VESA Display Power Management Extensions - not implemented\n");
986 break;
988 case 0xef: /* get video mode for hercules-compatibles */
989 /* There's no reason to really support this */
990 /* is there?....................(A.C.) */
991 TRACE("Just report the video not hercules compatible\n");
992 SET_DX( context, 0xffff );
993 break;
995 case 0xff: /* Turn VESA ON/OFF */
996 /* I don't know what to do */
997 break;
999 default:
1000 FIXME("VESA Function (0x%x) - Not Supported\n", AH_reg(context));
1001 break;
1006 /**********************************************************************
1007 * DOSVM_Int10Handler
1009 * Handler for int 10h (video).
1011 * NOTE:
1012 * Most INT 10 functions for text-mode, CGA, EGA, and VGA cards
1013 * are present in this list. (SVGA and XGA are not) That is not
1014 * to say that all these functions should be supported, but if
1015 * anyone is brain-damaged enough to want to emulate one of these
1016 * beasts then this should get you started.
1018 * NOTE:
1019 * Several common graphical extensions used by Microsoft hook
1020 * off of here. I have *not* added them to this list (yet). They
1021 * include:
1023 * MSHERC.COM - More functionality for Hercules cards.
1024 * EGA.SYS (also MOUSE.COM) - More for EGA cards.
1026 * Yes, MS also added this support into their mouse driver. Don't
1027 * ask me, I don't work for them.
1029 * Joseph Pranevich - 9/98
1031 * Jess Haas 2/99
1032 * Added support for Vesa. It is not complete but is a start.
1033 * NOTE: Im not sure if I did all this right or if any of it works.
1034 * Currently I don't have a program that uses Vesa that actually gets far
1035 * enough without crashing to do vesa stuff.
1037 * Added additional vga graphic support - 3/99
1039 void WINAPI DOSVM_Int10Handler( CONTEXT86 *context )
1041 BIOSDATA *data = DOSVM_BiosData();
1043 INT10_InitializeVideoMode( data );
1045 switch(AH_reg(context)) {
1047 case 0x00: /* SET VIDEO MODE */
1048 TRACE( "Set VGA video mode %02x\n", AL_reg(context) );
1049 if (!INT10_SetVideoMode( data, AL_reg(context) ))
1050 FIXME( "Unsupported VGA video mode requested: %#x\n",
1051 AL_reg(context) );
1052 break;
1054 case 0x01: /* SET CURSOR SHAPE */
1055 TRACE("Set Cursor Shape start %d end %d options %d\n",
1056 CH_reg(context) & 0x1f,
1057 CL_reg(context) & 0x1f,
1058 CH_reg(context) & 0xe0);
1059 data->VideoCursorType = CX_reg(context); /* direct copy */
1060 VGA_SetCursorShape(CH_reg(context), CL_reg(context));
1061 break;
1063 case 0x02: /* SET CURSOR POSITION */
1064 /* BH = Page Number */ /* Not supported */
1065 /* DH = Row */ /* 0 is left */
1066 /* DL = Column */ /* 0 is top */
1067 INT10_SetCursorPos(data,BH_reg(context),DL_reg(context),DH_reg(context));
1068 if (BH_reg(context))
1070 FIXME("Set Cursor Position: Cannot set to page %d\n",
1071 BH_reg(context));
1073 else
1075 VGA_SetCursorPos(DL_reg(context), DH_reg(context));
1076 TRACE("Set Cursor Position: %d/%d\n", DL_reg(context),
1077 DH_reg(context));
1079 break;
1081 case 0x03: /* GET CURSOR POSITION AND SIZE */
1083 unsigned row, col;
1085 TRACE("Get cursor position and size (page %d)\n", BH_reg(context));
1086 SET_CX( context, data->VideoCursorType );
1087 INT10_GetCursorPos(data,BH_reg(context),&col,&row);
1088 SET_DH( context, row );
1089 SET_DL( context, col );
1090 TRACE("Cursor Position: %d/%d\n", DL_reg(context), DH_reg(context));
1092 break;
1094 case 0x04: /* READ LIGHT PEN POSITION */
1095 FIXME("Read Light Pen Position - Not Supported\n");
1096 SET_AH( context, 0x00 ); /* Not down */
1097 break;
1099 case 0x05: /* SELECT ACTIVE DISPLAY PAGE */
1100 FIXME("Select Active Display Page (%d) - Not Supported\n", AL_reg(context));
1101 data->VideoCurPage = AL_reg(context);
1102 break;
1104 case 0x06: /* SCROLL UP WINDOW */
1105 /* AL = Lines to scroll */
1106 /* BH = Attribute */
1107 /* CH,CL = row, col upper-left */
1108 /* DH,DL = row, col lower-right */
1109 TRACE("Scroll Up Window %d\n", AL_reg(context));
1111 if (AL_reg(context) == 0)
1112 VGA_ClearText( CH_reg(context), CL_reg(context),
1113 DH_reg(context), DL_reg(context),
1114 BH_reg(context) );
1115 else
1116 VGA_ScrollUpText( CH_reg(context), CL_reg(context),
1117 DH_reg(context), DL_reg(context),
1118 AL_reg(context), BH_reg(context) );
1119 break;
1121 case 0x07: /* SCROLL DOWN WINDOW */
1122 /* AL = Lines to scroll */
1123 /* BH = Attribute */
1124 /* CH,CL = row, col upper-left */
1125 /* DH,DL = row, col lower-right */
1126 TRACE("Scroll Down Window %d\n", AL_reg(context));
1128 if (AL_reg(context) == 0)
1129 VGA_ClearText( CH_reg(context), CL_reg(context),
1130 DH_reg(context), DL_reg(context),
1131 BH_reg(context) );
1132 else
1133 VGA_ScrollDownText( CH_reg(context), CL_reg(context),
1134 DH_reg(context), DL_reg(context),
1135 AL_reg(context), BH_reg(context) );
1136 break;
1138 case 0x08: /* READ CHARACTER AND ATTRIBUTE AT CURSOR POSITION */
1140 if (BH_reg(context)) /* Write to different page */
1142 FIXME("Read character and attribute at cursor position -"
1143 " Can't read from non-0 page\n");
1144 SET_AL( context, ' ' ); /* That page is blank */
1145 SET_AH( context, 7 );
1147 else
1149 BYTE ascii, attr;
1150 TRACE("Read Character and Attribute at Cursor Position\n");
1151 VGA_GetCharacterAtCursor(&ascii, &attr);
1152 SET_AL( context, ascii );
1153 SET_AH( context, attr );
1156 break;
1158 case 0x09: /* WRITE CHARACTER AND ATTRIBUTE AT CURSOR POSITION */
1159 case 0x0a: /* WRITE CHARACTER ONLY AT CURSOR POSITION */
1160 /* AL = Character to display. */
1161 /* BH = Page Number */ /* We can't write to non-0 pages, yet. */
1162 /* BL = Attribute / Color */
1163 /* CX = Times to Write Char */
1164 /* Note here that the cursor is not advanced. */
1166 unsigned row, col;
1168 INT10_GetCursorPos(data,BH_reg(context),&col,&row);
1169 VGA_WriteChars(col, row,
1170 AL_reg(context),
1171 (AH_reg(context) == 0x09) ? BL_reg(context) : -1,
1172 CX_reg(context));
1173 if (CX_reg(context) > 1)
1174 TRACE("Write Character%s at Cursor Position (Rep. %d): %c\n",
1175 (AH_reg(context) == 0x09) ? " and Attribute" : "",
1176 CX_reg(context), AL_reg(context));
1177 else
1178 TRACE("Write Character%s at Cursor Position: %c\n",
1179 (AH_reg(context) == 0x09) ? " and Attribute" : "",
1180 AL_reg(context));
1182 break;
1184 case 0x0b:
1185 switch BH_reg(context) {
1186 case 0x00: /* SET BACKGROUND/BORDER COLOR */
1187 /* In text modes, this sets only the border... */
1188 /* According to the interrupt list and one of my books. */
1189 /* Funny though that Beyond Zork seems to indicate that it
1190 also sets up the default background attributes for clears
1191 and scrolls... */
1192 /* Bear in mind here that we do not want to change,
1193 apparently, the foreground or attribute of the background
1194 with this call, so we should check first to see what the
1195 foreground already is... FIXME */
1196 FIXME("Set Background/Border Color: %d/%d\n",
1197 BH_reg(context), BL_reg(context));
1198 break;
1199 case 0x01: /* SET PALETTE */
1200 FIXME("Set Palette - Not Supported\n");
1201 break;
1202 default:
1203 FIXME("INT 10 AH = 0x0b BH = 0x%x - Unknown\n",
1204 BH_reg(context));
1205 break;
1207 break;
1209 case 0x0c: /* WRITE GRAPHICS PIXEL */
1210 /* Not in graphics mode, can ignore w/o error */
1211 FIXME("Write Graphics Pixel - Not Supported\n");
1212 break;
1214 case 0x0d: /* READ GRAPHICS PIXEL */
1215 /* Not in graphics mode, can ignore w/o error */
1216 FIXME("Read Graphics Pixel - Not Supported\n");
1217 break;
1219 case 0x0e: /* TELETYPE OUTPUT */
1220 TRACE("Teletype Output\n");
1221 DOSVM_PutChar(AL_reg(context));
1222 break;
1224 case 0x0f: /* GET CURRENT VIDEO MODE */
1225 TRACE("Get current video mode: -> mode %d, columns %d\n", data->VideoMode, data->VideoColumns);
1226 /* Note: This should not be a constant value. */
1227 SET_AL( context, data->VideoMode );
1228 SET_AH( context, data->VideoColumns );
1229 SET_BH( context, 0 ); /* Display page 0 */
1230 break;
1232 case 0x10:
1233 switch AL_reg(context) {
1234 case 0x00: /* SET SINGLE PALETTE REGISTER - A.C. */
1235 TRACE("Set Single Palette Register - Reg 0x0%x Value 0x0%x\n",
1236 BL_reg(context),BH_reg(context));
1237 /* BH is the value BL is the register */
1238 VGA_SetColor16((int)BL_reg(context),(int)BH_reg(context));
1239 break;
1240 case 0x01: /* SET BORDER (OVERSCAN) */
1241 /* Text terminals have no overscan */
1242 /* I'm setting it anyway. - A.C. */
1243 TRACE("Set Border (Overscan) - Ignored but set.\n");
1244 VGA_SetColor16(16,(int)BH_reg(context));
1245 break;
1246 case 0x02: /* SET ALL PALETTE REGISTERS - A.C.*/
1247 TRACE("Set all palette registers\n");
1248 /* ES:DX points to a 17 byte table of colors */
1249 /* No return data listed */
1250 /* I'll have to update my table and the default palette */
1251 VGA_Set16Palette(CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edx));
1252 break;
1253 case 0x03: /* TOGGLE INTENSITY/BLINKING BIT */
1254 FIXME("Toggle Intensity/Blinking Bit - Not Supported\n");
1255 break;
1256 case 0x07: /* GET INDIVIDUAL PALETTE REGISTER - A.C.*/
1257 TRACE("Get Individual Palette Register 0x0%x\n",BL_reg(context));
1258 /* BL is register to read [ 0-15 ] BH is return value */
1259 SET_BH( context, VGA_GetColor16((int)BL_reg(context)) );
1260 break;
1261 case 0x08: /* READ OVERSCAN (BORDER COLOR) REGISTER - A.C. */
1262 TRACE("Read Overscan (Border Color) Register \n");
1263 SET_BH( context, VGA_GetColor16(16) );
1264 break;
1265 case 0x09: /* READ ALL PALETTE REGISTERS AND OVERSCAN REGISTER - A.C.*/
1266 TRACE("Read All Palette Registers and Overscan Register \n");
1267 /* ES:DX points to a 17 byte table where the results */
1268 /* of this call should be stored. */
1269 VGA_Get16Palette(CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edx));
1270 break;
1271 case 0x10: /* SET INDIVIDUAL DAC REGISTER */
1273 PALETTEENTRY paldat;
1275 TRACE("Set Individual DAC register\n");
1276 paldat.peRed = DH_reg(context);
1277 paldat.peGreen = CH_reg(context);
1278 paldat.peBlue = CL_reg(context);
1279 paldat.peFlags = 0;
1280 VGA_SetPalette(&paldat,BX_reg(context)&0xFF,1);
1282 break;
1283 case 0x12: /* SET BLOCK OF DAC REGISTERS */
1285 int i;
1286 PALETTEENTRY paldat;
1287 BYTE *pt;
1289 TRACE("Set Block of DAC registers\n");
1290 pt = (BYTE*)CTX_SEG_OFF_TO_LIN(context,context->SegEs,context->Edx);
1291 for (i=0;i<CX_reg(context);i++)
1293 paldat.peRed = (*(pt+i*3+0)) << 2;
1294 paldat.peGreen = (*(pt+i*3+1)) << 2;
1295 paldat.peBlue = (*(pt+i*3+2)) << 2;
1296 paldat.peFlags = 0;
1297 VGA_SetPalette(&paldat,(BX_reg(context)+i)&0xFF,1);
1300 break;
1301 case 0x13: /* SELECT VIDEO DAC COLOR PAGE */
1302 FIXME("Select video DAC color page - Not Supported\n");
1303 break;
1304 case 0x15: /* READ INDIVIDUAL DAC REGISTER */
1305 FIXME("Read individual DAC register - Not Supported\n");
1306 break;
1307 case 0x17: /* READ BLOCK OF DAC REGISTERS */
1308 FIXME("Read block of DAC registers - Not Supported\n");
1309 break;
1310 case 0x18: /* SET PEL MASK */
1311 FIXME("Set PEL mask - Not Supported\n");
1312 break;
1313 case 0x19: /* READ PEL MASK */
1314 FIXME("Read PEL mask - Not Supported\n");
1315 break;
1316 case 0x1a: /* GET VIDEO DAC COLOR PAGE STATE */
1317 FIXME("Get video DAC color page state - Not Supported\n");
1318 break;
1319 case 0x1b: /* PERFORM GRAY-SCALE SUMMING */
1320 FIXME("Perform Gray-scale summing - Not Supported\n");
1321 break;
1322 default:
1323 FIXME("INT 10 AH = 0x10 AL = 0x%x - Unknown\n",
1324 AL_reg(context));
1325 break;
1327 break;
1329 case 0x11: /* TEXT MODE CHARGEN */
1330 /* Note that second subfunction is *almost* identical. */
1331 /* See INTERRUPT.A for details. */
1332 switch AL_reg(context) {
1333 case 0x00: /* LOAD USER SPECIFIED PATTERNS */
1334 case 0x10:
1335 FIXME("Load User Specified Patterns - Not Supported\n");
1336 break;
1337 case 0x01: /* LOAD ROM MONOCHROME PATTERNS */
1338 case 0x11:
1339 FIXME("Load ROM Monochrome Patterns - Not Supported\n");
1340 break;
1341 case 0x02: /* LOAD ROM 8x8 DOUBLE-DOT PATTERNS */
1342 case 0x12:
1343 FIXME(
1344 "Load ROM 8x8 Double Dot Patterns - Not Supported\n");
1345 break;
1346 case 0x03: /* SET BLOCK SPECIFIER */
1347 FIXME("Set Block Specifier - Not Supported\n");
1348 break;
1349 case 0x04: /* LOAD ROM 8x16 CHARACTER SET */
1350 case 0x14:
1351 FIXME("Load ROM 8x16 Character Set - Not Supported\n");
1352 break;
1353 case 0x20: /* SET USER 8x16 GRAPHICS CHARS */
1354 FIXME("Set User 8x16 Graphics Chars - Not Supported\n");
1355 break;
1356 case 0x21: /* SET USER GRAPICS CHARACTERS */
1357 FIXME("Set User Graphics Characters - Not Supported\n");
1358 break;
1359 case 0x22: /* SET ROM 8x14 GRAPHICS CHARS */
1360 FIXME("Set ROM 8x14 Graphics Chars - Not Supported\n");
1361 break;
1362 case 0x23: /* SET ROM 8x8 DBL DOT CHARS */
1363 FIXME(
1364 "Set ROM 8x8 Dbl Dot Chars (Graphics) - Not Supported\n");
1365 break;
1366 case 0x24: /* LOAD 8x16 GRAPHIC CHARS */
1367 FIXME("Load 8x16 Graphic Chars - Not Supported\n");
1368 break;
1369 case 0x30: /* GET FONT INFORMATION */
1370 FIXME("Get Font Information - Not Supported\n");
1371 break;
1372 default:
1373 FIXME("INT 10 AH = 0x11 AL = 0x%x - Unknown\n",
1374 AL_reg(context));
1375 break;
1377 break;
1379 case 0x12: /* ALTERNATE FUNCTION SELECT */
1380 switch BL_reg(context) {
1381 case 0x10: /* GET EGA INFO */
1382 TRACE("EGA info requested\n");
1383 SET_BH( context, 0x00 ); /* Color screen */
1384 SET_BL( context, data->ModeOptions >> 5 ); /* EGA memory size */
1385 SET_CX( context, data->FeatureBitsSwitches );
1386 break;
1387 case 0x20: /* ALTERNATE PRTSC */
1388 FIXME("Install Alternate Print Screen - Not Supported\n");
1389 break;
1390 case 0x30: /* SELECT VERTICAL RESOULTION */
1391 FIXME("Select vertical resolution - not supported\n");
1392 break;
1393 case 0x31: /* ENABLE/DISABLE DEFAULT PALETTE LOADING */
1394 FIXME("Default palette loading - not supported\n");
1395 data->VGASettings =
1396 (data->VGASettings & 0xf7) |
1397 ((AL_reg(context) == 1) << 3);
1398 break;
1399 case 0x32: /* ENABLE/DISABLE VIDEO ADDRERSSING */
1400 FIXME("Video Addressing - Not Supported\n");
1401 break;
1402 case 0x33: /* ENABLE/DISABLE GRAY SCALE SUMMING */
1403 FIXME("Gray Scale Summing - Not Supported\n");
1404 break;
1405 case 0x34: /* ENABLE/DISABLE CURSOR EMULATION */
1406 TRACE("Set cursor emulation to %d\n", AL_reg(context));
1407 data->ModeOptions =
1408 (data->ModeOptions & 0xfe)|(AL_reg(context) == 1);
1409 break;
1410 case 0x36: /* VIDEO ADDRESS CONTROL */
1411 FIXME("Video Address Control - Not Supported\n");
1412 break;
1413 default:
1414 FIXME("INT 10 AH = 0x11 AL = 0x%x - Unknown\n",
1415 AL_reg(context));
1416 break;
1418 break;
1420 case 0x13: /* WRITE STRING */
1421 /* This one does not imply that string be at cursor. */
1422 FIXME("Write String - Not Supported\n");
1423 break;
1425 case 0x1a:
1426 switch AL_reg(context) {
1427 case 0x00: /* GET DISPLAY COMBINATION CODE */
1428 TRACE("Get Display Combination Code\n");
1429 SET_AL( context, 0x1a ); /* Function supported */
1430 SET_BL( context, INT10_DCC ); /* Active display */
1431 SET_BH( context, 0x00 ); /* No alternate display */
1432 break;
1433 case 0x01: /* SET DISPLAY COMBINATION CODE */
1434 FIXME("Set Display Combination Code - Not Supported\n");
1435 break;
1436 default:
1437 FIXME("INT 10 AH = 0x1a AL = 0x%x - Unknown\n",
1438 AL_reg(context));
1439 break;
1441 break;
1443 case 0x1b: /* FUNCTIONALITY/STATE INFORMATION */
1444 TRACE("Get functionality/state information\n");
1445 if (BX_reg(context) == 0x0000)
1447 BYTE *ptr = CTX_SEG_OFF_TO_LIN(context,
1448 context->SegEs,
1449 context->Edi);
1450 SET_AL( context, 0x1b ); /* Function is supported */
1451 INT10_FillStateInformation( ptr, data );
1453 break;
1455 case 0x1c: /* SAVE/RESTORE VIDEO STATE */
1456 FIXME("Save/Restore Video State - Not Supported\n");
1457 break;
1459 case 0xef: /* get video mode for hercules-compatibles */
1460 /* There's no reason to really support this */
1461 /* is there?....................(A.C.) */
1462 TRACE("Just report the video not hercules compatible\n");
1463 SET_DX( context, 0xffff );
1464 break;
1466 case 0x4f: /* VESA */
1467 INT10_HandleVESA(context);
1468 break;
1470 case 0xfe: /* GET SHADOW BUFFER */
1471 TRACE( "GET SHADOW BUFFER %lx:%x - ignored\n",
1472 context->SegEs, DI_reg(context) );
1473 break;
1475 default:
1476 FIXME("Unknown - 0x%x\n", AH_reg(context));
1477 INT_BARF( context, 0x10 );
1482 /**********************************************************************
1483 * DOSVM_PutChar
1485 * Write single character to VGA console at the current
1486 * cursor position and updates the BIOS cursor position.
1488 void WINAPI DOSVM_PutChar( BYTE ascii )
1490 BIOSDATA *data = DOSVM_BiosData();
1491 unsigned xpos, ypos;
1493 TRACE("char: 0x%02x(%c)\n", ascii, ascii);
1495 INT10_InitializeVideoMode( data );
1497 VGA_PutChar( ascii );
1498 VGA_GetCursorPos( &xpos, &ypos );
1499 INT10_SetCursorPos( data, 0, xpos, ypos );