Handle properly the requested video mode in Int10h SET VIDEO MODE
[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 static void scroll_window(int direction, char lines, char row1, 
34    char col1, char row2, char col2, char attribute);
35
36 #define SCROLL_UP 1
37 #define SCROLL_DOWN 2
38
39 /* FIXME: is row or column first? */
40 static void BIOS_GetCursorPos(BIOSDATA*data,unsigned page,unsigned*X,unsigned*Y)
41 {
42   *X = data->VideoCursorPos[page*2];
43   *Y = data->VideoCursorPos[page*2+1];
44 }
45
46 static void BIOS_SetCursorPos(BIOSDATA*data,unsigned page,unsigned X,unsigned Y)
47 {
48   data->VideoCursorPos[page*2] = X;
49   data->VideoCursorPos[page*2+1] = Y;
50 }
51
52 /**********************************************************************
53  *          DOSVM_Int10Handler (WPROCS.116)
54  *
55  * Handler for int 10h (video).
56  * 
57  * NOTE:
58  *    Most INT 10 functions for text-mode, CGA, EGA, and VGA cards
59  *    are present in this list. (SVGA and XGA are not) That is not
60  *    to say that all these functions should be supported, but if
61  *    anyone is brain-damaged enough to want to emulate one of these
62  *    beasts then this should get you started. 
63  *
64  * NOTE:
65  *    Several common graphical extensions used by Microsoft hook
66  *    off of here. I have *not* added them to this list (yet). They
67  *    include:
68  *
69  *    MSHERC.COM - More functionality for Hercules cards.
70  *    EGA.SYS (also MOUSE.COM) - More for EGA cards.
71  *    
72  *    Yes, MS also added this support into their mouse driver. Don't
73  *    ask me, I don't work for them.
74  *
75  * Joseph Pranevich - 9/98 
76  *
77  *  Jess Haas 2/99
78  *      Added support for Vesa. It is not complete but is a start. 
79  *      NOTE: Im not sure if i did all this right or if eny of it works.
80  *      Currently i dont have a program that uses Vesa that actually gets far 
81  *      enough without crashing to do vesa stuff.
82  * 
83  *      Added additional vga graphic support - 3/99
84  */
85
86 void WINAPI DOSVM_Int10Handler( CONTEXT86 *context )
87 {
88     BIOSDATA *data = DOSMEM_BiosData();
89
90     if(AL_reg(context) == 0x4F) { /* VESA functions */
91         switch(AH_reg(context)) {
92
93         case 0x00: /* GET SuperVGA INFORMATION */
94             FIXME("Vesa Get SuperVGA Info STUB!\n");
95             AL_reg(context) = 0x4f;
96             AH_reg(context) = 0x01; /* 0x01=failed 0x00=succesful */
97             break;
98         case 0x01: /* GET SuperVGA MODE INFORMATION */
99             FIXME("VESA GET SuperVGA Mode Information - Not supported\n");
100             AL_reg(context) = 0x4f;
101             AH_reg(context) = 0x01; /* 0x00 = successful 0x01 = failed */
102             break;
103         case 0x02: /* SET SuperVGA VIDEO MODE */
104             switch(BX_reg(context)) {
105                 /* OEM Video Modes */
106                 case 0x00: /* 40x25 */
107                 case 0x01:
108                         TRACE("Set VESA Text Mode - 0x0%x\n",
109                            BX_reg(context));
110                         VGA_SetAlphaMode(40, 25);
111                         data->VideoColumns = 40;
112                         break;                
113                 case 0x02:
114                 case 0x03:
115                 case 0x07:
116                     TRACE("Set VESA Text Mode - 0x0%x\n",
117                        BX_reg(context));
118                     VGA_SetAlphaMode(80, 25);
119                     data->VideoColumns = 80;
120                     break;
121                 case 0x0D:
122                     TRACE("Setting VESA 320x200 16-color mode\n");
123                     VGA_SetMode(320,200,4);
124                     break;
125                 case 0x0E:
126                     TRACE("Setting VESA 640x200 16-color mode\n");
127                     VGA_SetMode(640,200,4); 
128                     break;
129                 case 0x10:
130                     TRACE("Setting VESA 640x350 16-color mode\n");
131                     VGA_SetMode(640,350,4);
132                     break;
133                 case 0x12:
134                     TRACE("Setting VESA 640x480 16-color mode\n");
135                     VGA_SetMode(640,480,4);
136                     break;
137                 case 0x13:
138                     TRACE("Setting VESA 320x200 256-color mode\n");
139                     VGA_SetMode(320,200,8);
140                     break;
141                 /* VBE Modes */
142                 case 0x100:
143                     TRACE("Setting VESA 640x400 256-color mode\n");
144                     VGA_SetMode(640,400,8);
145                     break;
146                 case 0x101:
147                     TRACE("Setting VESA 640x480 256-color mode\n");
148                     VGA_SetMode(640,480,8);
149                     break;
150                 case 0x102:
151                     TRACE("Setting VESA 800x600 16-color mode\n");
152                     VGA_SetMode(800,600,4);
153                     break;
154                 case 0x103:
155                     TRACE("Setting VESA 800x600 256-color mode\n");
156                     VGA_SetMode(800,600,8);
157                     break;
158                 case 0x104:
159                     TRACE("Setting VESA 1024x768 16-color mode\n");
160                     VGA_SetMode(1024,768,4);
161                     break;
162                 case 0x105:
163                     TRACE("Setting VESA 1024x768 256-color mode\n");
164                     VGA_SetMode(1024,768,8);
165                     break;
166                 case 0x106:
167                     TRACE("Setting VESA 1280x1024 16-color mode\n");
168                     VGA_SetMode(1280,1024,4);
169                     break;
170                 case 0x107:
171                     TRACE("Setting VESA 1280x1024 256-color mode\n");
172                     VGA_SetMode(1280,1024,8);
173                     break;
174                 /* 108h - 10Ch are text modes and im lazy so :p */
175                 /* VBE v1.2+ */
176                 case 0x10D:
177                     TRACE("Setting VESA 320x200 15bpp\n");
178                     VGA_SetMode(320,200,15);
179                     break;
180                 case 0x10E:
181                     TRACE("Setting VESA 320x200 16bpp\n");
182                     VGA_SetMode(320,200,16);
183                     break;
184                 case 0x10F:
185                     TRACE("Setting VESA 320x200 24bpp\n");
186                     VGA_SetMode(320,200,24);
187                     break;
188                 case 0x110:
189                     TRACE("Setting VESA 640x480 15bpp\n");
190                     VGA_SetMode(640,480,15);
191                     break;
192                 case 0x111:
193                     TRACE("Setting VESA 640x480 16bpp\n");
194                     VGA_SetMode(640,480,16);
195                     break;
196                 case 0x112:
197                     TRACE("Setting VESA 640x480 24bpp\n");
198                     VGA_SetMode(640,480,24);
199                     break;
200                 case 0x113:
201                     TRACE("Setting VESA 800x600 15bpp\n");
202                     VGA_SetMode(800,600,15);
203                     break;
204                 case 0x114:
205                     TRACE("Setting VESA 800x600 16bpp\n");
206                     VGA_SetMode(800,600,16);
207                     break;
208                 case 0x115:
209                     TRACE("Setting VESA 800x600 24bpp\n");
210                     VGA_SetMode(800,600,24);
211                     break;
212                 case 0x116:
213                     TRACE("Setting VESA 1024x768 15bpp\n");
214                     VGA_SetMode(1024,768,15);
215                     break;
216                 case 0x117:
217                     TRACE("Setting VESA 1024x768 16bpp\n");
218                     VGA_SetMode(1024,768,16);
219                     break;
220                 case 0x118:
221                     TRACE("Setting VESA 1024x768 24bpp\n");
222                     VGA_SetMode(1024,768,24);
223                     break;
224                 case 0x119:
225                     TRACE("Setting VESA 1280x1024 15bpp\n");
226                     VGA_SetMode(1280,1024,15);
227                     break;
228                 case 0x11A:
229                     TRACE("Setting VESA 1280x1024 16bpp\n");
230                     VGA_SetMode(1280,1024,16);
231                     break;
232                 case 0x11B:
233                     TRACE("Setting VESA 1280x1024 24bpp\n");
234                     VGA_SetMode(1280,1024,24);
235                     break;
236                 default:
237                     FIXME("VESA Set Video Mode (0x%x) - Not Supported\n", BX_reg(context));
238             }
239             data->VideoMode = BX_reg(context);
240             AL_reg(context) = 0x4f;
241             AH_reg(context) = 0x00;
242             break;      
243         case 0x03: /* VESA SuperVGA BIOS - GET CURRENT VIDEO MODE */
244                 AL_reg(context) = 0x4f;
245                 AH_reg(context) = 0x00; /* should probly check if a vesa mode has ben set */
246                 BX_reg(context) = data->VideoMode;
247                 break;
248         case 0x04: /* VESA SuperVGA BIOS - SAVE/RESTORE SuperVGA VIDEO STATE */
249                 ERR("VESA SAVE/RESTORE Video State - Not Implemented\n");
250                 /* AL_reg(context) = 0x4f; = supported so not set since not implemented */      
251                 /* maybe we should do this instead ? */
252                 /* AH_reg(context = 0x01;  not implemented so just fail */
253                 break;
254         case 0x05: /* VESA SuperVGA BIOS - CPU VIDEO MEMORY CONTROL */
255                 ERR("VESA CPU VIDEO MEMORY CONTROL\n");
256                 /* AL_reg(context) = 0x4f; = supported so not set since not implemented */      
257                 /* maybe we should do this instead ? */
258                 /* AH_reg(context = 0x001; not implemented so just fail */
259                 break;
260         case 0x06: /* VESA GET/SET LOGICAL SCAN LINE LENGTH */
261                 ERR("VESA GET/SET LOGICAL SCAN LINE LENGTH - Not Implemented\n");
262                 /* AL_reg(context) = 0x4f; = supported so not set since not implemented */      
263                 /* maybe we should do this instead ? */
264                 /* AH_reg(context = 0x001; not implemented so just fail */
265                 break;
266         case 0x07: /* GET/SET DISPLAY START */
267                 ERR("VESA GET/SET DISPLAY START - Not Implemented\n");
268                 /* AL_reg(context) = 0x4f; = supported so not set since not implemented */      
269                 /* maybe we should do this instead ? */
270                 /* AH_reg(context = 0x001; not implemented so just fail */
271                 break;
272         case 0x08: /* GET/SET DAC PALETTE CONTROL */
273                 ERR("VESA GET/SET DAC PALETTE CONTROL- Not Implemented\n");
274                 /* AL_reg(context) = 0x4f; = supported so not set since not implemented */      
275                 /* maybe we should do this instead ? */
276                 /* AH_reg(context = 0x001; not implemented so just fail */
277                 break;
278         case 0x09: /* SET PALETTE ENTRIES */
279                 FIXME("VESA Set palette entries - not implemented\n");
280                 break;
281         case 0xef:  /* get video mode for hercules-compatibles   */
282                     /* There's no reason to really support this  */
283                     /* is there?....................(A.C.)       */
284                 TRACE("Just report the video not hercules compatible\n");
285                 DX_reg(context) = 0xffff;
286                 break; 
287         case 0xff: /* Turn VESA ON/OFF */
288                 /* i dont know what to do */
289                 break;
290         default:
291                 FIXME("VESA Function (0x%x) - Not Supported\n", AH_reg(context));
292                 break;          
293         }
294     }
295     else {
296
297     switch(AH_reg(context)) {
298
299     case 0x00: /* SET VIDEO MODE */
300         /* Text Modes: */
301         /* (mode) (text rows/cols)
302             0x00 - 40x25 
303             0x01 - 40x25
304             0x02 - 80x25
305             0x03 - 80x25 or 80x43 or 80x50 (assume 80x25) 
306             0x07 - 80x25
307         */
308
309         /* Bit 7 of AH = 0 -> Clean the video memory
310                          1 -> Don't clean it
311         */  
312         if (!(AL_reg(context)&0x80)) {
313             /* FIXME: Do something which cleans the video memory */ 
314         }
315
316         /* FIXME: Should we keep the bit 7 in the Bios Data memory? */ 
317         AL_reg(context) &= ~0x80;
318
319         switch (AL_reg(context)) {
320             case 0x00: /* 40x25 */
321             case 0x01:
322                 VGA_Exit();
323                 TRACE("Set Video Mode - Set to Text - 0x0%x\n",
324                    AL_reg(context));
325                 VGA_SetAlphaMode(40, 25);
326                 data->VideoColumns = 40;
327                 break;                
328             case 0x02:
329             case 0x03:
330             case 0x07:
331                 VGA_Exit();
332                 TRACE("Set Video Mode - Set to Text - 0x0%x\n",
333                    AL_reg(context));
334                 VGA_SetAlphaMode(80, 25);
335                 data->VideoColumns = 80;
336                 break;
337             case 0x0D:
338                 TRACE("Setting VGA 320x200 16-color mode\n");
339                 VGA_SetMode(320,200,4);
340                 break;
341             case 0x0E:
342                 TRACE("Setting VGA 640x200 16-color mode\n");
343                 VGA_SetMode(640,200,4); 
344                 break;
345             case 0x10:
346                 TRACE("Setting VGA 640x350 16-color mode\n");
347                 VGA_SetMode(640,350,4);
348                 break;
349             case 0x12:
350                 TRACE("Setting VGA 640x480 16-color mode\n");
351                 VGA_SetMode(640,480,4);
352                 break;
353             case 0x13:
354                 TRACE("Setting VGA 320x200 256-color mode\n");
355                 VGA_SetMode(320,200,8);
356                 break;
357             default:
358                 FIXME("Set Video Mode (0x%x) - Not Supported\n", 
359                    AL_reg(context));
360         }
361         data->VideoMode = AL_reg(context);
362         break;
363
364     case 0x01: /* SET CURSOR SHAPE */
365         FIXME("Set Cursor Shape - Not Supported\n");
366         break;
367     
368     case 0x02: /* SET CURSOR POSITION */
369         /* BH = Page Number */ /* Not supported */
370         /* DH = Row */ /* 0 is left */
371         /* DL = Column */ /* 0 is top */
372         BIOS_SetCursorPos(data,BH_reg(context),DL_reg(context),DH_reg(context));
373         if (BH_reg(context))
374         {
375            FIXME("Set Cursor Position: Cannot set to page %d\n",
376               BH_reg(context));
377         }
378         else
379         {
380            VGA_SetCursorPos(DL_reg(context), DH_reg(context));
381            TRACE("Set Cursor Position: %d %d\n", DH_reg(context), 
382               DL_reg(context));
383         }
384         break;
385
386     case 0x03: /* GET CURSOR POSITION AND SIZE */
387         {
388           unsigned row, col;
389
390           TRACE("Get cursor position and size (page %d)\n", BH_reg(context));
391           CX_reg(context) = data->VideoCursorType;
392           BIOS_GetCursorPos(data,BH_reg(context),&col,&row);
393           DH_reg(context) = row;
394           DL_reg(context) = col;
395           TRACE("Cursor Position: %d %d\n", DH_reg(context), DL_reg(context));
396         }
397         break;
398
399     case 0x04: /* READ LIGHT PEN POSITION */
400         FIXME("Read Light Pen Position - Not Supported\n");
401         AH_reg(context) = 0x00; /* Not down */
402         break;
403
404     case 0x05: /* SELECT ACTIVE DISPLAY PAGE */
405         FIXME("Select Active Display Page - Not Supported\n");
406         data->VideoCurPage = AL_reg(context);
407         break;
408
409     case 0x06: /* SCROLL UP WINDOW */
410         /* AL = Lines to scroll */
411         /* BH = Attribute */
412         /* CH,CL = row, col upper-left */
413         /* DH,DL = row, col lower-right */
414         scroll_window(SCROLL_UP, AL_reg(context), CH_reg(context), 
415            CL_reg(context), DH_reg(context), DL_reg(context), 
416            BH_reg(context));
417         TRACE("Scroll Up Window %d\n", AL_reg(context));
418         break;
419
420     case 0x07: /* SCROLL DOWN WINDOW */
421         /* AL = Lines to scroll */
422         /* BH = Attribute */
423         /* CH,CL = row, col upper-left */
424         /* DH,DL = row, col lower-right */
425         scroll_window(SCROLL_DOWN, AL_reg(context), CH_reg(context), 
426            CL_reg(context), DH_reg(context), DL_reg(context), 
427            BH_reg(context));
428         TRACE("Scroll Down Window %d\n", AL_reg(context));
429         break;
430
431     case 0x08: /* READ CHARACTER AND ATTRIBUTE AT CURSOR POSITION */
432         {
433             if (BH_reg(context)) /* Write to different page */
434             {
435                 FIXME("Read character and attribute at cursor position -"
436                       " Can't read from non-0 page\n");
437                 AL_reg(context) = ' '; /* That page is blank */
438                 AH_reg(context) = 7;
439             }
440             else
441            {
442                 TRACE("Read Character and Attribute at Cursor Position\n");
443                 VGA_GetCharacterAtCursor(&AL_reg(context), &AH_reg(context));
444             }
445         }
446         break;
447
448     case 0x09: /* WRITE CHARACTER AND ATTRIBUTE AT CURSOR POSITION */
449     case 0x0a: /* WRITE CHARACTER ONLY AT CURSOR POSITION */ 
450        /* AL = Character to display. */
451        /* BH = Page Number */ /* We can't write to non-0 pages, yet. */
452        /* BL = Attribute / Color */
453        /* CX = Times to Write Char */
454        /* Note here that the cursor is not advanced. */
455        {
456            unsigned row, col;
457
458            BIOS_GetCursorPos(data,BH_reg(context),&col,&row);
459            VGA_WriteChars(col, row,
460                           AL_reg(context),
461                           (AH_reg(context) == 0x09) ? BL_reg(context) : -1,
462                           CX_reg(context));
463            if (CX_reg(context) > 1)
464               TRACE("Write Character%s at Cursor Position (Rep. %d): %c\n",
465                     (AH_reg(context) == 0x09) ? " and Attribute" : "",
466                  CX_reg(context), AL_reg(context));
467            else
468               TRACE("Write Character%s at Cursor Position: %c\n",
469                     (AH_reg(context) == 0x09) ? " and Attribute" : "",
470                 AL_reg(context));
471        }
472        break;
473
474     case 0x0b: 
475         switch BH_reg(context) {
476         case 0x00: /* SET BACKGROUND/BORDER COLOR */
477             /* In text modes, this sets only the border... */
478             /* According to the interrupt list and one of my books. */
479             /* Funny though that Beyond Zork seems to indicate that it 
480                also sets up the default background attributes for clears
481                and scrolls... */
482             /* Bear in mind here that we do not want to change,
483                apparantly, the foreground or attribute of the background
484                with this call, so we should check first to see what the
485                foreground already is... FIXME */
486             FIXME("Set Background/Border Color: %d\n", 
487                BL_reg(context));
488             break;
489         case 0x01: /* SET PALETTE */
490             FIXME("Set Palette - Not Supported\n");
491             break;
492         default:
493             FIXME("INT 10 AH = 0x0b BH = 0x%x - Unknown\n", 
494                BH_reg(context));
495             break;
496         }
497         break;
498
499     case 0x0c: /* WRITE GRAPHICS PIXEL */
500         /* Not in graphics mode, can ignore w/o error */
501         FIXME("Write Graphics Pixel - Not Supported\n");
502         break;
503         
504     case 0x0d: /* READ GRAPHICS PIXEL */
505         /* Not in graphics mode, can ignore w/o error */
506         FIXME("Read Graphics Pixel - Not Supported\n");
507         break;
508               
509     case 0x0e: /* TELETYPE OUTPUT */
510         TRACE("Teletype Output\n");
511         DOSVM_PutChar(AL_reg(context));
512         break;
513
514     case 0x0f: /* GET CURRENT VIDEO MODE */
515         TRACE("Get current video mode\n");
516         /* Note: This should not be a constant value. */
517         AL_reg(context) = data->VideoMode;
518         AH_reg(context) = data->VideoColumns;
519         BH_reg(context) = 0; /* Display page 0 */
520         break;
521
522     case 0x10: 
523         switch AL_reg(context) {
524         case 0x00: /* SET SINGLE PALETTE REGISTER - A.C. */
525             TRACE("Set Single Palette Register - Reg 0x0%x Value 0x0%x\n",
526                 BL_reg(context),BH_reg(context));
527                 /* BH is the value  BL is the register */
528                 VGA_SetColor16((int)BL_reg(context),(int)BH_reg(context));
529             break;
530         case 0x01: /* SET BORDER (OVERSCAN) */
531             /* Text terminals have no overscan */
532             /* I'm setting it anyway. - A.C.   */       
533             TRACE("Set Border (Overscan) - Ignored but set.\n");
534             VGA_SetColor16(16,(int)BH_reg(context));
535             break;
536         case 0x02: /* SET ALL PALETTE REGISTERS - A.C.*/
537             TRACE("Set all palette registers\n");
538                 /* ES:DX points to a 17 byte table of colors */
539                 /* No return data listed */
540                 /* I'll have to update my table and the default palette */
541                VGA_Set16Palette(CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edx));
542             break;
543         case 0x03: /* TOGGLE INTENSITY/BLINKING BIT */
544             FIXME("Toggle Intensity/Blinking Bit - Not Supported\n");
545             break;
546         case 0x07: /* GET INDIVIDUAL PALETTE REGISTER  - A.C.*/
547             TRACE("Get Individual Palette Register 0x0%x\n",BL_reg(context));
548                 /* BL is register to read [ 0-15 ] BH is return value */
549                 BH_reg(context) = VGA_GetColor16((int)BL_reg(context));
550             break;
551         case 0x08: /* READ OVERSCAN (BORDER COLOR) REGISTER  - A.C. */
552             TRACE("Read Overscan (Border Color) Register \n");
553                 BH_reg(context) = VGA_GetColor16(16);
554             break;
555         case 0x09: /* READ ALL PALETTE REGISTERS AND OVERSCAN REGISTER - A.C.*/
556             TRACE("Read All Palette Registers and Overscan Register \n");
557                 /* ES:DX points to a 17 byte table where the results */
558                 /*  of this call should be stored.                   */
559                VGA_Get16Palette(CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edx));
560             break;
561         case 0x10: /* SET INDIVIDUAL DAC REGISTER */
562             {
563                 PALETTEENTRY paldat;
564
565                 TRACE("Set Individual DAC register\n");
566                 paldat.peRed   = DH_reg(context);
567                 paldat.peGreen = CH_reg(context);
568                 paldat.peBlue  = CL_reg(context);
569                 paldat.peFlags = 0;
570                 VGA_SetPalette(&paldat,BX_reg(context)&0xFF,1);
571             }
572             break;
573         case 0x12: /* SET BLOCK OF DAC REGISTERS */
574             {
575                 int i;
576                 PALETTEENTRY paldat;
577                 BYTE *pt;
578
579                 TRACE("Set Block of DAC registers\n");
580                 pt = (BYTE*)CTX_SEG_OFF_TO_LIN(context,context->SegEs,context->Edx);
581                 for (i=0;i<CX_reg(context);i++)
582                 {
583                     paldat.peRed   = (*(pt+i*3+0)) << 2;
584                     paldat.peGreen = (*(pt+i*3+1)) << 2;
585                     paldat.peBlue  = (*(pt+i*3+2)) << 2;
586                     paldat.peFlags = 0;
587                     VGA_SetPalette(&paldat,(BX_reg(context)+i)&0xFF,1);
588                 }
589             }
590             break;
591         case 0x13: /* SELECT VIDEO DAC COLOR PAGE */
592             FIXME("Select video DAC color page - Not Supported\n");
593             break;
594         case 0x15: /* READ INDIVIDUAL DAC REGISTER */
595             FIXME("Read individual DAC register - Not Supported\n");
596             break;
597         case 0x17: /* READ BLOCK OF DAC REGISTERS */
598             FIXME("Read block of DAC registers - Not Supported\n");
599             break;
600         case 0x18: /* SET PEL MASK */
601             FIXME("Set PEL mask - Not Supported\n");
602             break;
603         case 0x19: /* READ PEL MASK */
604             FIXME("Read PEL mask - Not Supported\n");
605             break;
606         case 0x1a: /* GET VIDEO DAC COLOR PAGE STATE */
607             FIXME("Get video DAC color page state - Not Supported\n");
608             break;
609         case 0x1b: /* PERFORM GRAY-SCALE SUMMING */
610             FIXME("Perform Gray-scale summing - Not Supported\n");
611             break;
612         default:
613             FIXME("INT 10 AH = 0x10 AL = 0x%x - Unknown\n", 
614                AL_reg(context));
615             break;
616         }
617         break;
618
619     case 0x11: /* TEXT MODE CHARGEN */
620         /* Note that second subfunction is *almost* identical. */
621         /* See INTERRUPT.A for details. */
622         switch AL_reg(context) {
623         case 0x00: /* LOAD USER SPECIFIED PATTERNS */
624         case 0x10:
625             FIXME("Load User Specified Patterns - Not Supported\n");
626             break;
627         case 0x01: /* LOAD ROM MONOCHROME PATTERNS */
628         case 0x11:
629             FIXME("Load ROM Monochrome Patterns - Not Supported\n");
630             break;
631         case 0x02: /* LOAD ROM 8x8 DOUBLE-DOT PATTERNS */
632         case 0x12:
633             FIXME(
634                 "Load ROM 8x8 Double Dot Patterns - Not Supported\n");       
635             break;
636         case 0x03: /* SET BLOCK SPECIFIER */
637             FIXME("Set Block Specifier - Not Supported\n");
638             break;
639         case 0x04: /* LOAD ROM 8x16 CHARACTER SET */
640         case 0x14:
641             FIXME("Load ROM 8x16 Character Set - Not Supported\n");
642             break;
643         case 0x20: /* SET USER 8x16 GRAPHICS CHARS */
644             FIXME("Set User 8x16 Graphics Chars - Not Supported\n");
645             break;
646         case 0x21: /* SET USER GRAPICS CHARACTERS */
647             FIXME("Set User Graphics Characters - Not Supported\n");
648             break;
649         case 0x22: /* SET ROM 8x14 GRAPHICS CHARS */
650             FIXME("Set ROM 8x14 Graphics Chars - Not Supported\n");
651             break;
652         case 0x23: /* SET ROM 8x8 DBL DOT CHARS */
653             FIXME(
654                 "Set ROM 8x8 Dbl Dot Chars (Graphics) - Not Supported\n");
655             break;
656         case 0x24: /* LOAD 8x16 GRAPHIC CHARS */
657             FIXME("Load 8x16 Graphic Chars - Not Supported\n");
658             break;
659         case 0x30: /* GET FONT INFORMATION */
660             FIXME("Get Font Information - Not Supported\n");
661             break;
662         default:
663             FIXME("INT 10 AH = 0x11 AL = 0x%x - Unknown\n", 
664                AL_reg(context));
665             break;
666         }
667         break;
668         
669     case 0x12: /* ALTERNATE FUNCTION SELECT */
670         switch BL_reg(context) {
671         case 0x10: /* GET EGA INFO */
672             TRACE("EGA info requested\n");
673             BH_reg(context) = 0x00;   /* Color screen */
674             BL_reg(context) =
675                 data->ModeOptions >> 5; /* EGA memory size */
676             CX_reg(context) =
677                 data->FeatureBitsSwitches;
678             break;
679         case 0x20: /* ALTERNATE PRTSC */
680             FIXME("Install Alternate Print Screen - Not Supported\n");
681             break;
682         case 0x30: /* SELECT VERTICAL RESOULTION */
683             FIXME("Select vertical resolution - not supported\n");
684             break;
685         case 0x31: /* ENABLE/DISABLE DEFAULT PALETTE LOADING */
686             FIXME("Default palette loading - not supported\n");
687             data->VGASettings =
688                 (data->VGASettings & 0xf7) |
689                 ((AL_reg(context) == 1) << 3);
690             break;
691         case 0x32: /* ENABLE/DISABLE VIDEO ADDRERSSING */
692             FIXME("Video Addressing - Not Supported\n");
693             break;
694         case 0x33: /* ENABLE/DISABLE GRAY SCALE SUMMING */
695             FIXME("Gray Scale Summing - Not Supported\n");
696             break;
697         case 0x34: /* ENABLE/DISABLE CURSOR EMULATION */
698             TRACE("Set cursor emulation to %d\n", AL_reg(context));
699             data->ModeOptions =
700                 (data->ModeOptions & 0xfe)|(AL_reg(context) == 1);
701             break;
702         case 0x36: /* VIDEO ADDRESS CONTROL */
703             FIXME("Video Address Control - Not Supported\n");
704             break;
705         default:
706             FIXME("INT 10 AH = 0x11 AL = 0x%x - Unknown\n", 
707                AL_reg(context));
708             break;
709         }
710         break;
711
712     case 0x13: /* WRITE STRING */
713         /* This one does not imply that string be at cursor. */
714         FIXME("Write String - Not Supported\n");
715         break;
716                              
717     case 0x1a: 
718         switch AL_reg(context) {
719         case 0x00: /* GET DISPLAY COMBINATION CODE */
720             TRACE("Get Display Combination Code\n");
721             AX_reg(context) = 0x001a;
722             BL_reg(context) = 0x08; /* VGA w/ color analog display */
723             BH_reg(context) = 0x00; /* No secondary hardware */
724             break;
725         case 0x01: /* SET DISPLAY COMBINATION CODE */
726             FIXME("Set Display Combination Code - Not Supported\n");
727             break;
728         default:
729             FIXME("INT 10 AH = 0x1a AL = 0x%x - Unknown\n", 
730                AL_reg(context));
731             break;
732         }
733     break;
734
735     case 0x1b: /* FUNCTIONALITY/STATE INFORMATION */
736         TRACE("Get functionality/state information\n");
737         if (BX_reg(context) == 0x0)
738         {
739           AL_reg(context) = 0x1b;
740           /* Copy state information structure to ES:DI */
741           memcpy(CTX_SEG_OFF_TO_LIN(context,context->SegEs,context->Edi),
742               DOSMEM_BiosSys()+0xe010,sizeof(VIDEOSTATE));
743         }
744         break;
745
746     case 0x1c: /* SAVE/RESTORE VIDEO STATE */
747         FIXME("Save/Restore Video State - Not Supported\n");
748         break;
749
750     case 0x4f: /* Get SuperVGA INFORMATION */
751         {
752           BYTE *p =
753                CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edi);
754           /* BOOL16 vesa20 = (*(DWORD *)p == *(DWORD *)"VBE2"); */
755   
756           TRACE("Get SuperVGA information\n");
757           AH_reg(context) = 0;
758           *(DWORD *)p = *(DWORD *)"VESA";
759           *(WORD *)(p+0x04) = 0x0200; /* VESA 2.0 */
760           *(DWORD *)(p+0x06) = 0x00000000; /* pointer to OEM name */
761           *(DWORD *)(p+0x0a) = 0xfffffffd; /* capabilities flags :-) */
762         }
763         break;
764         case 0xef:  /* get video mode for hercules-compatibles   */
765                     /* There's no reason to really support this  */
766                     /* is there?....................(A.C.)       */
767                 TRACE("Just report the video not hercules compatible\n");
768                 DX_reg(context) = 0xffff;
769                 break; 
770     default:
771         FIXME("Unknown - 0x%x\n", AH_reg(context));
772         INT_BARF( context, 0x10 );
773     }
774     }
775 }
776
777 static void scroll_window(int direction, char lines, char row1, 
778    char col1, char row2, char col2, char attribute)
779 {
780    if (!lines) /* Actually, clear the window */
781    {
782        VGA_ClearText(row1, col1, row2, col2, attribute);
783    }
784    else if (direction == SCROLL_UP)
785    {
786        VGA_ScrollUpText(row1, col1, row2, col2, lines, attribute);
787    }
788    else
789    {
790        VGA_ScrollDownText(row1, col1, row2, col2, lines, attribute);
791    }
792 }
793    
794
795 /**********************************************************************
796  *         DOSVM_PutChar
797  *
798  */
799
800 void WINAPI DOSVM_PutChar(BYTE ascii)
801 {
802   BIOSDATA *data = DOSMEM_BiosData();
803   unsigned  xpos, ypos;
804
805   TRACE("char: 0x%02x\n", ascii);
806
807   VGA_PutChar(ascii);
808   VGA_GetCursorPos(&xpos, &ypos);
809   BIOS_SetCursorPos(data, 0, xpos, ypos);
810 }