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