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