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