Added a framework for testing CreateProcess and a few tests.
[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 */
515             FIXME("Set Single Palette Register - Not tested\n");
516                 /* BH is the value  BL is the register */
517                 VGA_SetColor16((int)BL_reg(context),(int)BH_reg(context));
518             break;
519         case 0x01: /* SET BORDER (OVERSCAN) */
520             /* Text terminals have no overscan */
521             TRACE("Set Border (Overscan) - Ignored\n");
522             break;
523         case 0x02: /* SET ALL PALETTE REGISTERS */
524             FIXME("Set all palette registers - Not Supported\n");
525                 /* DX:ES points to a 17 byte table of colors */
526                 /* No return data listed */
527                 /* I'll have to update my table and the default palette */
528             break;
529         case 0x03: /* TOGGLE INTENSITY/BLINKING BIT */
530             FIXME("Toggle Intensity/Blinking Bit - Not Supported\n");
531             break;
532         case 0x07: /* GET INDIVIDUAL PALETTE REGISTER */
533             FIXME("Get Individual Palette Register - Not Supported\n");
534                 /* BL is register to read [ 0-15 ] BH is return value */
535             break;
536         case 0x08: /* READ OVERSCAN (BORDER COLOR) REGISTER */
537             FIXME(
538                "Read Overscan (Border Color) Register - Not Supported\n");
539             break;
540         case 0x09: /* READ ALL PALETTE REGISTERS AND OVERSCAN REGISTER */
541             FIXME(
542                "Read All Palette Registers and Overscan Register "
543                " - Not Supported\n");
544             break;
545         case 0x10: /* SET INDIVIDUAL DAC REGISTER */
546             {
547                 PALETTEENTRY paldat;
548
549                 TRACE("Set Individual DAC register\n");
550                 paldat.peRed   = DH_reg(context);
551                 paldat.peGreen = CH_reg(context);
552                 paldat.peBlue  = CL_reg(context);
553                 paldat.peFlags = 0;
554                 VGA_SetPalette(&paldat,BX_reg(context)&0xFF,1);
555             }
556             break;
557         case 0x12: /* SET BLOCK OF DAC REGISTERS */
558             {
559                 int i;
560                 PALETTEENTRY paldat;
561                 BYTE *pt;
562
563                 TRACE("Set Block of DAC registers\n");
564                 pt = (BYTE*)CTX_SEG_OFF_TO_LIN(context,context->SegEs,context->Edx);
565                 for (i=0;i<CX_reg(context);i++)
566                 {
567                     paldat.peRed   = (*(pt+i*3+0)) << 2;
568                     paldat.peGreen = (*(pt+i*3+1)) << 2;
569                     paldat.peBlue  = (*(pt+i*3+2)) << 2;
570                     paldat.peFlags = 0;
571                     VGA_SetPalette(&paldat,(BX_reg(context)+i)&0xFF,1);
572                 }
573             }
574             break;
575         case 0x13: /* SELECT VIDEO DAC COLOR PAGE */
576             FIXME("Select video DAC color page - Not Supported\n");
577             break;
578         case 0x15: /* READ INDIVIDUAL DAC REGISTER */
579             FIXME("Read individual DAC register - Not Supported\n");
580             break;
581         case 0x17: /* READ BLOCK OF DAC REGISTERS */
582             FIXME("Read block of DAC registers - Not Supported\n");
583             break;
584         case 0x18: /* SET PEL MASK */
585             FIXME("Set PEL mask - Not Supported\n");
586             break;
587         case 0x19: /* READ PEL MASK */
588             FIXME("Read PEL mask - Not Supported\n");
589             break;
590         case 0x1a: /* GET VIDEO DAC COLOR PAGE STATE */
591             FIXME("Get video DAC color page state - Not Supported\n");
592             break;
593         case 0x1b: /* PERFORM GRAY-SCALE SUMMING */
594             FIXME("Perform Gray-scale summing - Not Supported\n");
595             break;
596         default:
597             FIXME("INT 10 AH = 0x10 AL = 0x%x - Unknown\n", 
598                AL_reg(context));
599             break;
600         }
601         break;
602
603     case 0x11: /* TEXT MODE CHARGEN */
604         /* Note that second subfunction is *almost* identical. */
605         /* See INTERRUPT.A for details. */
606         switch AL_reg(context) {
607         case 0x00: /* LOAD USER SPECIFIED PATTERNS */
608         case 0x10:
609             FIXME("Load User Specified Patterns - Not Supported\n");
610             break;
611         case 0x01: /* LOAD ROM MONOCHROME PATTERNS */
612         case 0x11:
613             FIXME("Load ROM Monochrome Patterns - Not Supported\n");
614             break;
615         case 0x02: /* LOAD ROM 8x8 DOUBLE-DOT PATTERNS */
616         case 0x12:
617             FIXME(
618                 "Load ROM 8x8 Double Dot Patterns - Not Supported\n");       
619             break;
620         case 0x03: /* SET BLOCK SPECIFIER */
621             FIXME("Set Block Specifier - Not Supported\n");
622             break;
623         case 0x04: /* LOAD ROM 8x16 CHARACTER SET */
624         case 0x14:
625             FIXME("Load ROM 8x16 Character Set - Not Supported\n");
626             break;
627         case 0x20: /* SET USER 8x16 GRAPHICS CHARS */
628             FIXME("Set User 8x16 Graphics Chars - Not Supported\n");
629             break;
630         case 0x21: /* SET USER GRAPICS CHARACTERS */
631             FIXME("Set User Graphics Characters - Not Supported\n");
632             break;
633         case 0x22: /* SET ROM 8x14 GRAPHICS CHARS */
634             FIXME("Set ROM 8x14 Graphics Chars - Not Supported\n");
635             break;
636         case 0x23: /* SET ROM 8x8 DBL DOT CHARS */
637             FIXME(
638                 "Set ROM 8x8 Dbl Dot Chars (Graphics) - Not Supported\n");
639             break;
640         case 0x24: /* LOAD 8x16 GRAPHIC CHARS */
641             FIXME("Load 8x16 Graphic Chars - Not Supported\n");
642             break;
643         case 0x30: /* GET FONT INFORMATION */
644             FIXME("Get Font Information - Not Supported\n");
645             break;
646         default:
647             FIXME("INT 10 AH = 0x11 AL = 0x%x - Unknown\n", 
648                AL_reg(context));
649             break;
650         }
651         break;
652         
653     case 0x12: /* ALTERNATE FUNCTION SELECT */
654         switch BL_reg(context) {
655         case 0x10: /* GET EGA INFO */
656             TRACE("EGA info requested\n");
657             BH_reg(context) = 0x00;   /* Color screen */
658             BL_reg(context) =
659                 data->ModeOptions >> 5; /* EGA memory size */
660             CX_reg(context) =
661                 data->FeatureBitsSwitches;
662             break;
663         case 0x20: /* ALTERNATE PRTSC */
664             FIXME("Install Alternate Print Screen - Not Supported\n");
665             break;
666         case 0x30: /* SELECT VERTICAL RESOULTION */
667             FIXME("Select vertical resolution - not supported\n");
668             break;
669         case 0x31: /* ENABLE/DISABLE DEFAULT PALETTE LOADING */
670             FIXME("Default palette loading - not supported\n");
671             data->VGASettings =
672                 (data->VGASettings & 0xf7) |
673                 ((AL_reg(context) == 1) << 3);
674             break;
675         case 0x32: /* ENABLE/DISABLE VIDEO ADDRERSSING */
676             FIXME("Video Addressing - Not Supported\n");
677             break;
678         case 0x33: /* ENABLE/DISABLE GRAY SCALE SUMMING */
679             FIXME("Gray Scale Summing - Not Supported\n");
680             break;
681         case 0x34: /* ENABLE/DISABLE CURSOR EMULATION */
682             TRACE("Set cursor emulation to %d\n", AL_reg(context));
683             data->ModeOptions =
684                 (data->ModeOptions & 0xfe)|(AL_reg(context) == 1);
685             break;
686         case 0x36: /* VIDEO ADDRESS CONTROL */
687             FIXME("Video Address Control - Not Supported\n");
688             break;
689         default:
690             FIXME("INT 10 AH = 0x11 AL = 0x%x - Unknown\n", 
691                AL_reg(context));
692             break;
693         }
694         break;
695
696     case 0x13: /* WRITE STRING */
697         /* This one does not imply that string be at cursor. */
698         FIXME("Write String - Not Supported\n");
699         break;
700                              
701     case 0x1a: 
702         switch AL_reg(context) {
703         case 0x00: /* GET DISPLAY COMBINATION CODE */
704             TRACE("Get Display Combination Code\n");
705             AX_reg(context) = 0x001a;
706             BL_reg(context) = 0x08; /* VGA w/ color analog display */
707             BH_reg(context) = 0x00; /* No secondary hardware */
708             break;
709         case 0x01: /* SET DISPLAY COMBINATION CODE */
710             FIXME("Set Display Combination Code - Not Supported\n");
711             break;
712         default:
713             FIXME("INT 10 AH = 0x1a AL = 0x%x - Unknown\n", 
714                AL_reg(context));
715             break;
716         }
717     break;
718
719     case 0x1b: /* FUNCTIONALITY/STATE INFORMATION */
720         TRACE("Get functionality/state information\n");
721         if (BX_reg(context) == 0x0)
722         {
723           AL_reg(context) = 0x1b;
724           /* Copy state information structure to ES:DI */
725           memcpy(CTX_SEG_OFF_TO_LIN(context,context->SegEs,context->Edi),
726               DOSMEM_BiosSys()+0xe010,sizeof(VIDEOSTATE));
727         }
728         break;
729
730     case 0x1c: /* SAVE/RESTORE VIDEO STATE */
731         FIXME("Save/Restore Video State - Not Supported\n");
732         break;
733
734     case 0x4f: /* Get SuperVGA INFORMATION */
735         {
736           BYTE *p =
737                CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edi);
738           /* BOOL16 vesa20 = (*(DWORD *)p == *(DWORD *)"VBE2"); */
739   
740           TRACE("Get SuperVGA information\n");
741           AH_reg(context) = 0;
742           *(DWORD *)p = *(DWORD *)"VESA";
743           *(WORD *)(p+0x04) = 0x0200; /* VESA 2.0 */
744           *(DWORD *)(p+0x06) = 0x00000000; /* pointer to OEM name */
745           *(DWORD *)(p+0x0a) = 0xfffffffd; /* capabilities flags :-) */
746         }
747         break;
748         case 0xef:  /* get video mode for hercules-compatibles   */
749                     /* There's no reason to really support this  */
750                     /* is there?....................(A.C.)       */
751                 TRACE("Just report the video not hercules compatible\n");
752                 DX_reg(context) = 0xffff;
753                 break; 
754     default:
755         FIXME("Unknown - 0x%x\n", AH_reg(context));
756         INT_BARF( context, 0x10 );
757     }
758     }
759 }
760
761 static void scroll_window(int direction, char lines, char row1, 
762    char col1, char row2, char col2, char attribute)
763 {
764    if (!lines) /* Actually, clear the window */
765    {
766        VGA_ClearText(row1, col1, row2, col2, attribute);
767    }
768    else if (direction == SCROLL_UP)
769    {
770        VGA_ScrollUpText(row1, col1, row2, col2, lines, attribute);
771    }
772    else
773    {
774        VGA_ScrollDownText(row1, col1, row2, col2, lines, attribute);
775    }
776 }
777    
778
779 /**********************************************************************
780  *         DOSVM_PutChar
781  *
782  */
783
784 void WINAPI DOSVM_PutChar(BYTE ascii)
785 {
786   BIOSDATA *data = DOSMEM_BiosData();
787   unsigned  xpos, ypos;
788
789   TRACE("char: 0x%02x\n", ascii);
790
791   VGA_PutChar(ascii);
792   VGA_GetCursorPos(&xpos, &ypos);
793   BIOS_SetCursorPos(data, 0, xpos, ypos);
794 }