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