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