Convert services to use pipes for RPC instead of shared memory.
[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 /*
81  * Structure for VBE Mode Info Block. See the VBE 3.0 standard for details.
82  * This structure must be correctly packed.
83  */
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 */
133 };
134
135 #include "poppack.h"
136
137 /*
138  * Wine internal information about video modes.
139  * If depth is zero, the mode is considered to
140  * be a text mode.
141  */
142 typedef struct {
143     WORD Mode;
144     WORD Width;
145     WORD Height;
146     WORD Depth;
147 } INT10_MODE;
148
149
150 /*
151  * List of supported video modes.
152  */
153 static const INT10_MODE INT10_modelist[] =
154 {
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}
195 };
196
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)
201
202 /* Forward declarations. */
203 static INT10_HEAP *INT10_GetHeap(void);
204 static void INT10_SetCursorPos(BIOSDATA*, unsigned, unsigned, unsigned);
205
206
207 /**********************************************************************
208  *         INT10_FindMode
209  */
210 static const INT10_MODE *INT10_FindMode( WORD mode )
211 {
212     const INT10_MODE *ptr = INT10_modelist;
213     
214     /*
215      * Filter out flags.
216      */
217     mode &= 0x17f;
218
219     while (ptr->Mode != 0xffff)
220     {
221         if (ptr->Mode == mode)
222             return ptr;
223         ptr++;
224     }
225
226     return NULL;
227 }
228
229
230 /**********************************************************************
231  *         INT10_FillControllerInformation
232  *
233  * Fill 256-byte (VBE1.x) or 512-byte buffer (VBE2.0+) with
234  * capabilities of the video controller.
235  */
236 static void INT10_FillControllerInformation( BYTE *buffer )
237 {
238     INT10_HEAP *heap = INT10_GetHeap();
239
240     /* 00 - BYTE[4]: signature */
241     memmove( buffer, "VESA", 4 );
242
243     /* 04 - WORD: version number */
244     *(WORD*)(buffer + 4) = 0x0300; /* version 3.0 */
245     
246     /* 06 - DWORD: pointer to OEM name */
247     *(SEGPTR*)(buffer + 6) = MAKESEGPTR( heap->WineHeapSegment,
248                                          offsetof(INT10_HEAP,
249                                                   VesaOEMName) );
250
251     /*
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)
264      */
265     *(DWORD*)(buffer + 10) = 0; /* FIXME */
266     
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) );
271
272     /* 18 - WORD: total amount of video memory in 64K blocks */
273     *(WORD*)(buffer + 18) = 16; /* FIXME */
274
275     /* 20 - WORD: OEM software version (BCD, high byte = major) */
276     *(WORD*)(buffer + 20) = 0x0100; /* version 1.0 */
277
278     /* 22 - DWORD: pointer to vendor name */
279     *(SEGPTR*)(buffer + 22) = MAKESEGPTR( heap->WineHeapSegment,
280                                           offsetof(INT10_HEAP,
281                                                    VesaVendorName) );
282
283     /* 26 - DWORD: pointer to product name */
284     *(SEGPTR*)(buffer + 26) = MAKESEGPTR( heap->WineHeapSegment,
285                                           offsetof(INT10_HEAP,
286                                                    VesaProductName) );
287
288     /* 30 - DWORD: pointer to product revision string */
289     *(SEGPTR*)(buffer + 30) = MAKESEGPTR( heap->WineHeapSegment,
290                                           offsetof(INT10_HEAP,
291                                                    VesaProductRev) );
292
293     /* 34 - WORD: VBE/AF version (if capabilities bit 3 set) */
294     *(WORD*)(buffer + 34) = 0;
295
296     /*
297      * 36 - DWORD: pointer to list of accelerated modes 
298      *             (if capabilities bit 3 set) 
299      */
300     *(SEGPTR*)(buffer + 36) = 0;
301
302     /* 40 - BYTE[216]: reserved for VBE implementation, set to zero */
303     memset( buffer + 40, 216, 0 );
304
305     /* 
306      * 256 - BYTE[256]: reserved for VBE3.0 implementation, 
307      *                  ignored in order to support older programs
308      */
309 }
310
311
312 /**********************************************************************
313  *         INT10_FillModeInformation
314  *
315  * Fill 256-byte buffer with extended information about display mode.
316  *
317  * Returns FALSE if mode is unknown and TRUE is mode is known
318  * even if it is not supported.
319  */
320 static BOOL INT10_FillModeInformation( struct _ModeInfoBlock *mib, WORD mode )
321 {
322     const INT10_MODE *ptr = INT10_FindMode( mode );
323     if (!ptr)
324         return FALSE;
325
326     /*
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.
345      */
346     {
347         WORD attr = 0x000a; /* color mode, optional info */
348
349         /*
350          * FIXME: Attribute handling is incomplete.
351          */
352
353         /* Mode supported? FIXME: correct value */
354         attr |= 0x0001;
355
356         /* Graphical mode? */
357         if (ptr->Depth) 
358             attr |= 0x0010;
359
360         /* Not VGA-compatible? */
361         if (IS_VESA_MODE(mode))
362             attr |= 0x0020;
363
364         mib->ModeAttributes = attr;
365     }
366
367     /*
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.
374      */
375     mib->WinAAttributes = 0x07; /* window A exists, readable and writable */
376     mib->WinBAttributes = 0x00; /* window B not supported */
377
378     /* 04 - WORD: window granularity in KB */
379     mib->WinGranularity = 64;
380
381     /* 06 - WORD: window size in KB */
382     mib->WinSize = 64;
383
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 */
387
388     /* 12 - DWORD: window positioning function */
389     mib->WinFuncPtr = 0; /* not supported */
390     
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);
394
395     /* 18 - WORD: width in pixels (graphics) or characters (text) */
396     mib->XResolution = ptr->Width;
397
398     /* 20 - WORD: height in pixels (graphics) or characters (text) */
399     mib->YResolution = ptr->Height;
400
401     /* 22 - BYTE: width of character cell in pixels */
402     mib->XCharSize = 0; /* FIXME */
403
404     /* 23 - BYTE: height of character cell in pixels */
405     mib->YCharSize = 0; /* FIXME */
406
407     /* 24 - BYTE: number of memory planes */
408     mib->NumberOfPlanes = 1; /* FIXME */
409
410     /* 25 - BYTE: number of bits per pixel */
411     mib->BitsPerPixel = ptr->Depth; /* FIXME: text modes? reserved bits? */
412
413     /* 26 - BYTE: number of banks */
414     mib->NumberOfBanks = 1; /* FIXME */
415
416     /*
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.
429      */
430     if (!ptr->Depth)
431         mib->MemoryModel = 0; /* text mode */
432     else
433         mib->MemoryModel = 3; /* FIXME */
434
435     /* 28 - BYTE: size of bank in KB */
436     mib->BankSize = 0; /* FIXME */
437
438     /* 29 - BYTE: number of image pages (less one) in video RAM */
439     mib->NumberOfImagePages = 0; /* FIXME */
440
441     /* 30 - BYTE: reserved (0x00 for VBE 1.0-2.0, 0x01 for VBE 3.0) */
442     mib->Reserved1 = 0x01;
443
444     /* 
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.
454      */
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;
496     }
497
498     /*
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.
503      */
504     mib->DirectColorModeInfo = 0; /* not supported */
505
506     /* 40 - DWORD: physical address of linear video buffer */
507     mib->PhysBasePtr = 0; /* not supported */
508
509     /* 44 - DWORD: reserved, always zero */
510     mib->Reserved2 = 0;
511
512     /* 48 - WORD: reserved, always zero */
513     mib->Reserved3 = 0;
514
515     /* 50 - WORD: bytes per scan line in linear modes */
516     mib->LinBytesPerScanLine = mib->BytesPerScanLine;
517
518     /* 52 - BYTE: number of images (less one) for banked video modes */
519     mib->BnkNumberOfImagePages = 0; /* FIXME */
520
521     /* 53 - BYTE: number of images (less one) for linear video modes */
522     mib->LinNumberOfImagePages = mib->BnkNumberOfImagePages;
523
524     /* 54 - BYTE: red mask size (linear modes) */
525     mib->LinRedMaskSize = mib->RedMaskSize;
526
527     /* 55 - BYTE: red field position (linear modes) */
528     mib->LinRedFieldPosition = mib->RedFieldPosition;
529
530     /* 56 - BYTE: green mask size (linear modes) */
531     mib->LinGreenMaskSize = mib->GreenMaskSize;
532
533     /* 57 - BYTE: green field size (linear modes) */
534     mib->LinGreenFieldPosition = mib->GreenFieldPosition;
535
536     /* 58 - BYTE: blue mask size (linear modes) */
537     mib->LinBlueMaskSize = mib->BlueMaskSize;
538
539     /* 59 - BYTE: blue field position (linear modes) */
540     mib->LinBlueFieldPosition = mib->BlueFieldPosition;
541
542     /* 60 - BYTE: reserved mask size (linear modes) */
543     mib->LinRsvdMaskSize = mib->RsvdMaskSize;
544
545     /* 61 - BYTE: reserved mask position (linear modes) */
546     mib->LinRsvdFieldPosition = mib->RsvdFieldPosition;
547
548     /* 62 - DWORD: maximum pixel clock for graphics video mode, in Hz */
549     mib->MaxPixelClock = 0; /* FIXME */
550
551     /* 66 - BYTE[190]: reserved, set to zero */
552     memset( &mib->Reserved4, 190, 0 );
553
554     return TRUE;
555 }
556
557
558 /**********************************************************************
559  *         INT10_FillStateInformation
560  *
561  * Fill 64-byte buffer with VGA state and functionality information.
562  */
563 static void INT10_FillStateInformation( BYTE *buffer, BIOSDATA *data )
564 {
565     INT10_HEAP *heap = INT10_GetHeap();
566
567     /* 00 - DWORD: address of static functionality table */
568     *(SEGPTR*)(buffer + 0) = MAKESEGPTR( heap->WineHeapSegment,
569                                          offsetof(INT10_HEAP, 
570                                                   StaticModeSupport) );
571
572     /* 04 - BYTE[30]: copy of BIOS data starting from 0x49 (VideoMode) */
573     memmove( buffer + 4, &data->VideoMode, 30 );
574
575     /* 34 - BYTE: number of rows - 1 */
576     buffer[34] = data->RowsOnScreenMinus1;
577
578     /* 35 - WORD: bytes/character */
579     *(WORD*)(buffer + 35) = data->BytesPerChar;
580
581     /* 37 - BYTE: display combination code of active display */
582     buffer[37] = INT10_DCC;
583
584     /* 38 - BYTE: DCC of alternate display */
585     buffer[38] = 0; /* no secondary display */
586
587     /* 39 - WORD: number of colors supported in current mode (0000h = mono) */
588     *(WORD*)(buffer + 39) = 16; /* FIXME */
589
590     /* 41 - BYTE: number of pages supported in current mode */
591     buffer[41] = 1; /* FIXME */
592
593     /*
594      * 42 - BYTE: number of scan lines active
595      * Values (hex):
596      * 00 = 200
597      * 01 = 350
598      * 02 = 400
599      * 03 = 480
600      */
601     buffer[42] = 3; /* FIXME */
602
603     /* 43 - BYTE: primary character block */
604     buffer[43] = 0; /* FIXME */
605
606     /* 44 - BYTE: secondary character block */
607     buffer[44] = 0; /* FIXME */
608
609     /*
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)
620      */
621     /* FIXME: Correct value? */
622     buffer[45] =
623         (data->VGASettings & 0x0f) |
624         ((data->ModeOptions & 1) << 4); /* cursor emulation */
625
626     /*
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
636      */
637      buffer[46] = 0; /* FIXME: correct value? */
638
639      /* 47 - BYTE[2]: reserved, set to zero */
640      memset( buffer + 47, 2, 0 );
641
642      /*
643       * 49 - BYTE: video memory available
644       * Values (hex):
645       * 00 - 64K
646       * 01 - 128K
647       * 02 - 192K
648       * 03 - 256K
649       */
650      buffer[49] = (data->ModeOptions & 0x60) >> 5; /* FIXME */
651
652      /*
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)
662       */
663      buffer[50] = heap->StaticSavePointerFlags;
664
665      /*
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
673       */
674      buffer[51] = 4; /* FIXME: correct value? */
675
676      /* 52 - BYTE[12]: reserved, set to zero */
677      memset( buffer + 52, 12, 0 );
678 }
679
680
681 /**********************************************************************
682  *         INT10_GetHeap
683  */
684 INT10_HEAP *INT10_GetHeap( void )
685 {
686     static INT10_HEAP *heap_pointer = 0;
687
688     if (!heap_pointer)
689     {
690         WORD segment;
691         int  i;
692
693         heap_pointer = DOSVM_AllocDataUMB( sizeof(INT10_HEAP), 
694                                            &segment,
695                                            0 );
696
697         for (i = 0; i < 7; i++)
698             heap_pointer->StaticModeSupport[i] = 0xff; /* FIXME */
699
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;
707
708         for (i=0; TRUE; i++)
709         {
710             heap_pointer->VesaModeList[i] = INT10_modelist[i].Mode;
711             if (INT10_modelist[i].Mode == 0xffff)
712                 break;
713         }
714
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" );
719         
720         heap_pointer->VesaCurrentMode = 0; /* Initialized later. */
721         heap_pointer->WineHeapSegment = segment;
722     }
723
724     return heap_pointer;
725 }
726
727
728 /**********************************************************************
729  *         INT10_SetVideoMode
730  *
731  * Change current video mode to any VGA or VESA mode.
732  * Returns TRUE if mode is supported.
733  *
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).
750  */
751 static BOOL INT10_SetVideoMode( BIOSDATA *data, WORD mode )
752 {
753     const INT10_MODE *ptr = INT10_FindMode( mode );
754     INT10_HEAP *heap = INT10_GetHeap();
755     BOOL clearScreen = TRUE;
756
757     if (!ptr)
758         return FALSE;
759
760     /*
761      * Linear framebuffer is not supported.
762      */
763     if (mode & 0x4000)
764         return FALSE;
765
766     /*
767      * Check for VGA and VESA preserve video memory flag.
768      */
769     if ((mode & 0x0080) || (mode & 0x8000))
770         clearScreen = FALSE;
771
772     /*
773      * Note that we do not mask out flags here on purpose.
774      */
775     heap->VesaCurrentMode = mode;
776     if (mode <= 0xff)
777         data->VideoMode = mode;
778     else
779         data->VideoMode = 0;
780
781     if (ptr->Depth == 0)
782     {
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" );
788
789         /*
790          * FIXME: We should check here if alpha mode could be set.
791          */
792         VGA_SetAlphaMode( ptr->Width, ptr->Height );
793
794         data->VideoColumns = ptr->Width;
795         data->RowsOnScreenMinus1 = ptr->Height - 1;
796
797         if (clearScreen)
798         {            
799             VGA_ClearText( 0, 0, ptr->Height-1, ptr->Width-1, 0x07 );
800             INT10_SetCursorPos( data, 0, 0, 0 );
801             VGA_SetCursorPos( 0, 0 );            
802         }
803     }
804     else
805     {
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" );
811
812         if (VGA_SetMode( ptr->Width, ptr->Height, ptr->Depth ))
813             return FALSE;
814     }
815
816     return TRUE;
817 }
818
819
820 /**********************************************************************
821  *         INT10_GetCursorPos
822  */
823 static void INT10_GetCursorPos(BIOSDATA*data,unsigned page,unsigned*X,unsigned*Y)
824 {
825     *X = data->VideoCursorPos[page*2];   /* column */
826     *Y = data->VideoCursorPos[page*2+1]; /* row */
827 }
828
829
830 /**********************************************************************
831  *         INT10_SetCursorPos
832  */
833 static void INT10_SetCursorPos(BIOSDATA*data,unsigned page,unsigned X,unsigned Y)
834 {
835     data->VideoCursorPos[page*2] = X;
836     data->VideoCursorPos[page*2+1] = Y;
837 }
838
839
840 /**********************************************************************
841  *         INT10_InitializeVideoMode
842  *
843  * The first time this function is called VGA emulation is set to the
844  * default text mode.
845  */
846 static void INT10_InitializeVideoMode( BIOSDATA *data )
847 {
848   static BOOL already_initialized = FALSE;
849   unsigned    width;
850   unsigned    height;
851
852   if(already_initialized)
853     return;
854   already_initialized = TRUE;
855
856   VGA_InitAlphaMode(&width, &height);
857
858   /*
859    * FIXME: Add more mappings between initial size and
860    *        text modes.
861    */
862   if (width >= 80 && height >= 25)
863       INT10_SetVideoMode( data, 0x03 );
864   else
865       INT10_SetVideoMode( data, 0x01 );
866 }
867
868
869 /**********************************************************************
870  *          INT10_HandleVESA
871  *
872  * Handler for VESA functions (int10 function 0x4f).
873  */
874 static void INT10_HandleVESA( CONTEXT86 *context )
875 {
876     BIOSDATA *data = DOSVM_BiosData();
877
878     switch(AL_reg(context)) {
879
880     case 0x00: /* RETURN CONTROLLER INFORMATION */
881         TRACE( "VESA RETURN CONTROLLER INFORMATION\n" );
882         {
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 */
889         }
890         break;
891
892     case 0x01: /* RETURN MODE INFORMATION */
893         TRACE( "VESA RETURN MODE INFORMATION %04x\n", CX_reg(context) );
894         {
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 */
903         }
904         break;
905
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;
914
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;
920
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;
927
928     case 0x05: /* VESA SuperVGA BIOS - CPU VIDEO MEMORY CONTROL */
929         /*
930          * This subfunction supports only Window A (BL_reg == 0) and
931          * is assumes that window granularity is 64k.
932          */
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 );
952         }
953         break;
954
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;
961
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;
968
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;
975
976     case 0x09: /* SET PALETTE ENTRIES */
977         FIXME("VESA Set palette entries - not implemented\n");
978         break;
979
980     case 0x0a: /* GET PROTECTED-MODE CODE */
981         FIXME("VESA Get protected-mode code - not implemented\n");
982         break;
983
984     case 0x10: /* Display Power Management Extensions */
985         FIXME("VESA Display Power Management Extensions - not implemented\n");
986         break;
987
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;
994
995     case 0xff: /* Turn VESA ON/OFF */
996         /* I don't know what to do */
997         break;
998
999     default:
1000         FIXME("VESA Function (0x%x) - Not Supported\n", AH_reg(context));
1001         break;
1002     }
1003 }
1004
1005
1006 /**********************************************************************
1007  *          DOSVM_Int10Handler
1008  *
1009  * Handler for int 10h (video).
1010  *
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.
1017  *
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:
1022  *
1023  *    MSHERC.COM - More functionality for Hercules cards.
1024  *    EGA.SYS (also MOUSE.COM) - More for EGA cards.
1025  *
1026  *    Yes, MS also added this support into their mouse driver. Don't
1027  *    ask me, I don't work for them.
1028  *
1029  * Joseph Pranevich - 9/98
1030  *
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.
1036  *
1037  *      Added additional vga graphic support - 3/99
1038  */
1039 void WINAPI DOSVM_Int10Handler( CONTEXT86 *context )
1040 {
1041     BIOSDATA *data = DOSVM_BiosData();
1042
1043     INT10_InitializeVideoMode( data );
1044
1045     switch(AH_reg(context)) {
1046
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;
1053
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;
1062
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))
1069         {
1070            FIXME("Set Cursor Position: Cannot set to page %d\n",
1071               BH_reg(context));
1072         }
1073         else
1074         {
1075            VGA_SetCursorPos(DL_reg(context), DH_reg(context));
1076            TRACE("Set Cursor Position: %d/%d\n", DL_reg(context),
1077               DH_reg(context));
1078         }
1079         break;
1080
1081     case 0x03: /* GET CURSOR POSITION AND SIZE */
1082         {
1083           unsigned row, col;
1084
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));
1091         }
1092         break;
1093
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;
1098
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;
1103
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));
1110
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;
1120
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));
1127
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;
1137
1138     case 0x08: /* READ CHARACTER AND ATTRIBUTE AT CURSOR POSITION */
1139         {
1140             if (BH_reg(context)) /* Write to different page */
1141             {
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 );
1146             }
1147             else
1148            {
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 );
1154             }
1155         }
1156         break;
1157
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. */
1165        {
1166            unsigned row, col;
1167
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));
1181        }
1182        break;
1183
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;
1206         }
1207         break;
1208
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;
1213
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;
1218
1219     case 0x0e: /* TELETYPE OUTPUT */
1220         TRACE("Teletype Output\n");
1221         DOSVM_PutChar(AL_reg(context));
1222         break;
1223
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;
1231
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 */
1272             {
1273                 PALETTEENTRY paldat;
1274
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);
1281             }
1282             break;
1283         case 0x12: /* SET BLOCK OF DAC REGISTERS */
1284             {
1285                 int i;
1286                 PALETTEENTRY paldat;
1287                 BYTE *pt;
1288
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++)
1292                 {
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);
1298                 }
1299             }
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;
1326         }
1327         break;
1328
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;
1376         }
1377         break;
1378
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;
1417         }
1418         break;
1419
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;
1424
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;
1440         }
1441     break;
1442
1443     case 0x1b: /* FUNCTIONALITY/STATE INFORMATION */
1444         TRACE("Get functionality/state information\n");
1445         if (BX_reg(context) == 0x0000)
1446         {
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 );
1452         }
1453         break;
1454
1455     case 0x1c: /* SAVE/RESTORE VIDEO STATE */
1456         FIXME("Save/Restore Video State - Not Supported\n");
1457         break;
1458
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;
1465
1466     case 0x4f: /* VESA */
1467         INT10_HandleVESA(context);
1468         break;
1469
1470     case 0xfe: /* GET SHADOW BUFFER */
1471         TRACE( "GET SHADOW BUFFER %lx:%x - ignored\n",
1472                context->SegEs, DI_reg(context) );
1473         break;
1474
1475     default:
1476         FIXME("Unknown - 0x%x\n", AH_reg(context));
1477         INT_BARF( context, 0x10 );
1478     }
1479 }
1480
1481
1482 /**********************************************************************
1483  *         DOSVM_PutChar
1484  *
1485  * Write single character to VGA console at the current 
1486  * cursor position and updates the BIOS cursor position.
1487  */
1488 void WINAPI DOSVM_PutChar( BYTE ascii )
1489 {
1490   BIOSDATA *data = DOSVM_BiosData();
1491   unsigned  xpos, ypos;
1492
1493   TRACE("char: 0x%02x(%c)\n", ascii, ascii);
1494
1495   INT10_InitializeVideoMode( data );
1496
1497   VGA_PutChar( ascii );
1498   VGA_GetCursorPos( &xpos, &ypos );
1499   INT10_SetCursorPos( data, 0, xpos, ypos );
1500 }