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