Better implementation of GetCalendarInfo{A,W}, not perfect.
[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         switch (AL_reg(context)) {
310             case 0x00: /* 40x25 */
311             case 0x01:
312                 VGA_Exit();
313                 TRACE("Set Video Mode - Set to Text - 0x0%x\n",
314                    AL_reg(context));
315                 VGA_SetAlphaMode(40, 25);
316                 data->VideoColumns = 40;
317                 break;                
318             case 0x02:
319             case 0x03:
320             case 0x07:
321                 VGA_Exit();
322                 TRACE("Set Video Mode - Set to Text - 0x0%x\n",
323                    AL_reg(context));
324                 VGA_SetAlphaMode(80, 25);
325                 data->VideoColumns = 80;
326                 break;
327             case 0x0D:
328                 TRACE("Setting VGA 320x200 16-color mode\n");
329                 VGA_SetMode(320,200,4);
330                 break;
331             case 0x0E:
332                 TRACE("Setting VGA 640x200 16-color mode\n");
333                 VGA_SetMode(640,200,4); 
334                 break;
335             case 0x10:
336                 TRACE("Setting VGA 640x350 16-color mode\n");
337                 VGA_SetMode(640,350,4);
338                 break;
339             case 0x12:
340                 TRACE("Setting VGA 640x480 16-color mode\n");
341                 VGA_SetMode(640,480,4);
342                 break;
343             case 0x13:
344                 TRACE("Setting VGA 320x200 256-color mode\n");
345                 VGA_SetMode(320,200,8);
346                 break;
347             default:
348                 FIXME("Set Video Mode (0x%x) - Not Supported\n", 
349                    AL_reg(context));
350         }
351         data->VideoMode = AL_reg(context);
352         break;
353
354     case 0x01: /* SET CURSOR SHAPE */
355         FIXME("Set Cursor Shape - Not Supported\n");
356         break;
357     
358     case 0x02: /* SET CURSOR POSITION */
359         /* BH = Page Number */ /* Not supported */
360         /* DH = Row */ /* 0 is left */
361         /* DL = Column */ /* 0 is top */
362         BIOS_SetCursorPos(data,BH_reg(context),DL_reg(context),DH_reg(context));
363         if (BH_reg(context))
364         {
365            FIXME("Set Cursor Position: Cannot set to page %d\n",
366               BH_reg(context));
367         }
368         else
369         {
370            VGA_SetCursorPos(DL_reg(context), DH_reg(context));
371            TRACE("Set Cursor Position: %d %d\n", DH_reg(context), 
372               DL_reg(context));
373         }
374         break;
375
376     case 0x03: /* GET CURSOR POSITION AND SIZE */
377         {
378           unsigned row, col;
379
380           TRACE("Get cursor position and size (page %d)\n", BH_reg(context));
381           CX_reg(context) = data->VideoCursorType;
382           BIOS_GetCursorPos(data,BH_reg(context),&col,&row);
383           DH_reg(context) = row;
384           DL_reg(context) = col;
385           TRACE("Cursor Position: %d %d\n", DH_reg(context), DL_reg(context));
386         }
387         break;
388
389     case 0x04: /* READ LIGHT PEN POSITION */
390         FIXME("Read Light Pen Position - Not Supported\n");
391         AH_reg(context) = 0x00; /* Not down */
392         break;
393
394     case 0x05: /* SELECT ACTIVE DISPLAY PAGE */
395         FIXME("Select Active Display Page - Not Supported\n");
396         data->VideoCurPage = AL_reg(context);
397         break;
398
399     case 0x06: /* SCROLL UP WINDOW */
400         /* AL = Lines to scroll */
401         /* BH = Attribute */
402         /* CH,CL = row, col upper-left */
403         /* DH,DL = row, col lower-right */
404         scroll_window(SCROLL_UP, AL_reg(context), CH_reg(context), 
405            CL_reg(context), DH_reg(context), DL_reg(context), 
406            BH_reg(context));
407         TRACE("Scroll Up Window %d\n", AL_reg(context));
408         break;
409
410     case 0x07: /* SCROLL DOWN WINDOW */
411         /* AL = Lines to scroll */
412         /* BH = Attribute */
413         /* CH,CL = row, col upper-left */
414         /* DH,DL = row, col lower-right */
415         scroll_window(SCROLL_DOWN, AL_reg(context), CH_reg(context), 
416            CL_reg(context), DH_reg(context), DL_reg(context), 
417            BH_reg(context));
418         TRACE("Scroll Down Window %d\n", AL_reg(context));
419         break;
420
421     case 0x08: /* READ CHARACTER AND ATTRIBUTE AT CURSOR POSITION */
422         {
423             if (BH_reg(context)) /* Write to different page */
424             {
425                 FIXME("Read character and attribute at cursor position -"
426                       " Can't read from non-0 page\n");
427                 AL_reg(context) = ' '; /* That page is blank */
428                 AH_reg(context) = 7;
429             }
430             else
431            {
432                 TRACE("Read Character and Attribute at Cursor Position\n");
433                 VGA_GetCharacterAtCursor(&AL_reg(context), &AH_reg(context));
434             }
435         }
436         break;
437
438     case 0x09: /* WRITE CHARACTER AND ATTRIBUTE AT CURSOR POSITION */
439     case 0x0a: /* WRITE CHARACTER ONLY AT CURSOR POSITION */ 
440        /* AL = Character to display. */
441        /* BH = Page Number */ /* We can't write to non-0 pages, yet. */
442        /* BL = Attribute / Color */
443        /* CX = Times to Write Char */
444        /* Note here that the cursor is not advanced. */
445        {
446            unsigned row, col;
447
448            BIOS_GetCursorPos(data,BH_reg(context),&col,&row);
449            VGA_WriteChars(col, row,
450                           AL_reg(context),
451                           (AH_reg(context) == 0x09) ? BL_reg(context) : -1,
452                           CX_reg(context));
453            if (CX_reg(context) > 1)
454               TRACE("Write Character%s at Cursor Position (Rep. %d): %c\n",
455                     (AH_reg(context) == 0x09) ? " and Attribute" : "",
456                  CX_reg(context), AL_reg(context));
457            else
458               TRACE("Write Character%s at Cursor Position: %c\n",
459                     (AH_reg(context) == 0x09) ? " and Attribute" : "",
460                 AL_reg(context));
461        }
462        break;
463
464     case 0x0b: 
465         switch BH_reg(context) {
466         case 0x00: /* SET BACKGROUND/BORDER COLOR */
467             /* In text modes, this sets only the border... */
468             /* According to the interrupt list and one of my books. */
469             /* Funny though that Beyond Zork seems to indicate that it 
470                also sets up the default background attributes for clears
471                and scrolls... */
472             /* Bear in mind here that we do not want to change,
473                apparantly, the foreground or attribute of the background
474                with this call, so we should check first to see what the
475                foreground already is... FIXME */
476             FIXME("Set Background/Border Color: %d\n", 
477                BL_reg(context));
478             break;
479         case 0x01: /* SET PALETTE */
480             FIXME("Set Palette - Not Supported\n");
481             break;
482         default:
483             FIXME("INT 10 AH = 0x0b BH = 0x%x - Unknown\n", 
484                BH_reg(context));
485             break;
486         }
487         break;
488
489     case 0x0c: /* WRITE GRAPHICS PIXEL */
490         /* Not in graphics mode, can ignore w/o error */
491         FIXME("Write Graphics Pixel - Not Supported\n");
492         break;
493         
494     case 0x0d: /* READ GRAPHICS PIXEL */
495         /* Not in graphics mode, can ignore w/o error */
496         FIXME("Read Graphics Pixel - Not Supported\n");
497         break;
498               
499     case 0x0e: /* TELETYPE OUTPUT */
500         TRACE("Teletype Output\n");
501         DOSVM_PutChar(AL_reg(context));
502         break;
503
504     case 0x0f: /* GET CURRENT VIDEO MODE */
505         TRACE("Get current video mode\n");
506         /* Note: This should not be a constant value. */
507         AL_reg(context) = data->VideoMode;
508         AH_reg(context) = data->VideoColumns;
509         BH_reg(context) = 0; /* Display page 0 */
510         break;
511
512     case 0x10: 
513         switch AL_reg(context) {
514         case 0x00: /* SET SINGLE PALETTE REGISTER - A.C. */
515             TRACE("Set Single Palette Register - Reg 0x0%x Value 0x0%x\n",
516                 BL_reg(context),BH_reg(context));
517                 /* BH is the value  BL is the register */
518                 VGA_SetColor16((int)BL_reg(context),(int)BH_reg(context));
519             break;
520         case 0x01: /* SET BORDER (OVERSCAN) */
521             /* Text terminals have no overscan */
522             /* I'm setting it anyway. - A.C.   */       
523             TRACE("Set Border (Overscan) - Ignored but set.\n");
524             VGA_SetColor16(16,(int)BH_reg(context));
525             break;
526         case 0x02: /* SET ALL PALETTE REGISTERS - A.C.*/
527             TRACE("Set all palette registers\n");
528                 /* ES:DX points to a 17 byte table of colors */
529                 /* No return data listed */
530                 /* I'll have to update my table and the default palette */
531                VGA_Set16Palette(CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edx));
532             break;
533         case 0x03: /* TOGGLE INTENSITY/BLINKING BIT */
534             FIXME("Toggle Intensity/Blinking Bit - Not Supported\n");
535             break;
536         case 0x07: /* GET INDIVIDUAL PALETTE REGISTER  - A.C.*/
537             TRACE("Get Individual Palette Register 0x0%x\n",BL_reg(context));
538                 /* BL is register to read [ 0-15 ] BH is return value */
539                 BH_reg(context) = VGA_GetColor16((int)BL_reg(context));
540             break;
541         case 0x08: /* READ OVERSCAN (BORDER COLOR) REGISTER  - A.C. */
542             TRACE("Read Overscan (Border Color) Register \n");
543                 BH_reg(context) = VGA_GetColor16(16);
544             break;
545         case 0x09: /* READ ALL PALETTE REGISTERS AND OVERSCAN REGISTER - A.C.*/
546             TRACE("Read All Palette Registers and Overscan Register \n");
547                 /* ES:DX points to a 17 byte table where the results */
548                 /*  of this call should be stored.                   */
549                VGA_Get16Palette(CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edx));
550             break;
551         case 0x10: /* SET INDIVIDUAL DAC REGISTER */
552             {
553                 PALETTEENTRY paldat;
554
555                 TRACE("Set Individual DAC register\n");
556                 paldat.peRed   = DH_reg(context);
557                 paldat.peGreen = CH_reg(context);
558                 paldat.peBlue  = CL_reg(context);
559                 paldat.peFlags = 0;
560                 VGA_SetPalette(&paldat,BX_reg(context)&0xFF,1);
561             }
562             break;
563         case 0x12: /* SET BLOCK OF DAC REGISTERS */
564             {
565                 int i;
566                 PALETTEENTRY paldat;
567                 BYTE *pt;
568
569                 TRACE("Set Block of DAC registers\n");
570                 pt = (BYTE*)CTX_SEG_OFF_TO_LIN(context,context->SegEs,context->Edx);
571                 for (i=0;i<CX_reg(context);i++)
572                 {
573                     paldat.peRed   = (*(pt+i*3+0)) << 2;
574                     paldat.peGreen = (*(pt+i*3+1)) << 2;
575                     paldat.peBlue  = (*(pt+i*3+2)) << 2;
576                     paldat.peFlags = 0;
577                     VGA_SetPalette(&paldat,(BX_reg(context)+i)&0xFF,1);
578                 }
579             }
580             break;
581         case 0x13: /* SELECT VIDEO DAC COLOR PAGE */
582             FIXME("Select video DAC color page - Not Supported\n");
583             break;
584         case 0x15: /* READ INDIVIDUAL DAC REGISTER */
585             FIXME("Read individual DAC register - Not Supported\n");
586             break;
587         case 0x17: /* READ BLOCK OF DAC REGISTERS */
588             FIXME("Read block of DAC registers - Not Supported\n");
589             break;
590         case 0x18: /* SET PEL MASK */
591             FIXME("Set PEL mask - Not Supported\n");
592             break;
593         case 0x19: /* READ PEL MASK */
594             FIXME("Read PEL mask - Not Supported\n");
595             break;
596         case 0x1a: /* GET VIDEO DAC COLOR PAGE STATE */
597             FIXME("Get video DAC color page state - Not Supported\n");
598             break;
599         case 0x1b: /* PERFORM GRAY-SCALE SUMMING */
600             FIXME("Perform Gray-scale summing - Not Supported\n");
601             break;
602         default:
603             FIXME("INT 10 AH = 0x10 AL = 0x%x - Unknown\n", 
604                AL_reg(context));
605             break;
606         }
607         break;
608
609     case 0x11: /* TEXT MODE CHARGEN */
610         /* Note that second subfunction is *almost* identical. */
611         /* See INTERRUPT.A for details. */
612         switch AL_reg(context) {
613         case 0x00: /* LOAD USER SPECIFIED PATTERNS */
614         case 0x10:
615             FIXME("Load User Specified Patterns - Not Supported\n");
616             break;
617         case 0x01: /* LOAD ROM MONOCHROME PATTERNS */
618         case 0x11:
619             FIXME("Load ROM Monochrome Patterns - Not Supported\n");
620             break;
621         case 0x02: /* LOAD ROM 8x8 DOUBLE-DOT PATTERNS */
622         case 0x12:
623             FIXME(
624                 "Load ROM 8x8 Double Dot Patterns - Not Supported\n");       
625             break;
626         case 0x03: /* SET BLOCK SPECIFIER */
627             FIXME("Set Block Specifier - Not Supported\n");
628             break;
629         case 0x04: /* LOAD ROM 8x16 CHARACTER SET */
630         case 0x14:
631             FIXME("Load ROM 8x16 Character Set - Not Supported\n");
632             break;
633         case 0x20: /* SET USER 8x16 GRAPHICS CHARS */
634             FIXME("Set User 8x16 Graphics Chars - Not Supported\n");
635             break;
636         case 0x21: /* SET USER GRAPICS CHARACTERS */
637             FIXME("Set User Graphics Characters - Not Supported\n");
638             break;
639         case 0x22: /* SET ROM 8x14 GRAPHICS CHARS */
640             FIXME("Set ROM 8x14 Graphics Chars - Not Supported\n");
641             break;
642         case 0x23: /* SET ROM 8x8 DBL DOT CHARS */
643             FIXME(
644                 "Set ROM 8x8 Dbl Dot Chars (Graphics) - Not Supported\n");
645             break;
646         case 0x24: /* LOAD 8x16 GRAPHIC CHARS */
647             FIXME("Load 8x16 Graphic Chars - Not Supported\n");
648             break;
649         case 0x30: /* GET FONT INFORMATION */
650             FIXME("Get Font Information - Not Supported\n");
651             break;
652         default:
653             FIXME("INT 10 AH = 0x11 AL = 0x%x - Unknown\n", 
654                AL_reg(context));
655             break;
656         }
657         break;
658         
659     case 0x12: /* ALTERNATE FUNCTION SELECT */
660         switch BL_reg(context) {
661         case 0x10: /* GET EGA INFO */
662             TRACE("EGA info requested\n");
663             BH_reg(context) = 0x00;   /* Color screen */
664             BL_reg(context) =
665                 data->ModeOptions >> 5; /* EGA memory size */
666             CX_reg(context) =
667                 data->FeatureBitsSwitches;
668             break;
669         case 0x20: /* ALTERNATE PRTSC */
670             FIXME("Install Alternate Print Screen - Not Supported\n");
671             break;
672         case 0x30: /* SELECT VERTICAL RESOULTION */
673             FIXME("Select vertical resolution - not supported\n");
674             break;
675         case 0x31: /* ENABLE/DISABLE DEFAULT PALETTE LOADING */
676             FIXME("Default palette loading - not supported\n");
677             data->VGASettings =
678                 (data->VGASettings & 0xf7) |
679                 ((AL_reg(context) == 1) << 3);
680             break;
681         case 0x32: /* ENABLE/DISABLE VIDEO ADDRERSSING */
682             FIXME("Video Addressing - Not Supported\n");
683             break;
684         case 0x33: /* ENABLE/DISABLE GRAY SCALE SUMMING */
685             FIXME("Gray Scale Summing - Not Supported\n");
686             break;
687         case 0x34: /* ENABLE/DISABLE CURSOR EMULATION */
688             TRACE("Set cursor emulation to %d\n", AL_reg(context));
689             data->ModeOptions =
690                 (data->ModeOptions & 0xfe)|(AL_reg(context) == 1);
691             break;
692         case 0x36: /* VIDEO ADDRESS CONTROL */
693             FIXME("Video Address Control - Not Supported\n");
694             break;
695         default:
696             FIXME("INT 10 AH = 0x11 AL = 0x%x - Unknown\n", 
697                AL_reg(context));
698             break;
699         }
700         break;
701
702     case 0x13: /* WRITE STRING */
703         /* This one does not imply that string be at cursor. */
704         FIXME("Write String - Not Supported\n");
705         break;
706                              
707     case 0x1a: 
708         switch AL_reg(context) {
709         case 0x00: /* GET DISPLAY COMBINATION CODE */
710             TRACE("Get Display Combination Code\n");
711             AX_reg(context) = 0x001a;
712             BL_reg(context) = 0x08; /* VGA w/ color analog display */
713             BH_reg(context) = 0x00; /* No secondary hardware */
714             break;
715         case 0x01: /* SET DISPLAY COMBINATION CODE */
716             FIXME("Set Display Combination Code - Not Supported\n");
717             break;
718         default:
719             FIXME("INT 10 AH = 0x1a AL = 0x%x - Unknown\n", 
720                AL_reg(context));
721             break;
722         }
723     break;
724
725     case 0x1b: /* FUNCTIONALITY/STATE INFORMATION */
726         TRACE("Get functionality/state information\n");
727         if (BX_reg(context) == 0x0)
728         {
729           AL_reg(context) = 0x1b;
730           /* Copy state information structure to ES:DI */
731           memcpy(CTX_SEG_OFF_TO_LIN(context,context->SegEs,context->Edi),
732               DOSMEM_BiosSys()+0xe010,sizeof(VIDEOSTATE));
733         }
734         break;
735
736     case 0x1c: /* SAVE/RESTORE VIDEO STATE */
737         FIXME("Save/Restore Video State - Not Supported\n");
738         break;
739
740     case 0x4f: /* Get SuperVGA INFORMATION */
741         {
742           BYTE *p =
743                CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edi);
744           /* BOOL16 vesa20 = (*(DWORD *)p == *(DWORD *)"VBE2"); */
745   
746           TRACE("Get SuperVGA information\n");
747           AH_reg(context) = 0;
748           *(DWORD *)p = *(DWORD *)"VESA";
749           *(WORD *)(p+0x04) = 0x0200; /* VESA 2.0 */
750           *(DWORD *)(p+0x06) = 0x00000000; /* pointer to OEM name */
751           *(DWORD *)(p+0x0a) = 0xfffffffd; /* capabilities flags :-) */
752         }
753         break;
754         case 0xef:  /* get video mode for hercules-compatibles   */
755                     /* There's no reason to really support this  */
756                     /* is there?....................(A.C.)       */
757                 TRACE("Just report the video not hercules compatible\n");
758                 DX_reg(context) = 0xffff;
759                 break; 
760     default:
761         FIXME("Unknown - 0x%x\n", AH_reg(context));
762         INT_BARF( context, 0x10 );
763     }
764     }
765 }
766
767 static void scroll_window(int direction, char lines, char row1, 
768    char col1, char row2, char col2, char attribute)
769 {
770    if (!lines) /* Actually, clear the window */
771    {
772        VGA_ClearText(row1, col1, row2, col2, attribute);
773    }
774    else if (direction == SCROLL_UP)
775    {
776        VGA_ScrollUpText(row1, col1, row2, col2, lines, attribute);
777    }
778    else
779    {
780        VGA_ScrollDownText(row1, col1, row2, col2, lines, attribute);
781    }
782 }
783    
784
785 /**********************************************************************
786  *         DOSVM_PutChar
787  *
788  */
789
790 void WINAPI DOSVM_PutChar(BYTE ascii)
791 {
792   BIOSDATA *data = DOSMEM_BiosData();
793   unsigned  xpos, ypos;
794
795   TRACE("char: 0x%02x\n", ascii);
796
797   VGA_PutChar(ascii);
798   VGA_GetCursorPos(&xpos, &ypos);
799   BIOS_SetCursorPos(data, 0, xpos, ypos);
800 }