Small fixes.
[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 0xef:  /* get video mode for hercules-compatables   */
296                     /* There's no reason to really support this  */
297                     /* is there?....................(A.C.)       */
298                 TRACE("Just report the video not hercules compatable\n");
299                 DX_reg(context) = 0xffff;
300                 break; 
301         case 0xff: /* Turn VESA ON/OFF */
302                 /* i dont know what to do */
303                 break;
304         default:
305                 FIXME("VESA Function (0x%x) - Not Supported\n", AH_reg(context));
306                 break;          
307         }
308 }
309 else {
310
311     switch(AH_reg(context)) {
312
313     case 0x00: /* SET VIDEO MODE */
314         /* Text Modes: */
315         /* (mode) (text rows/cols)
316             0x00 - 40x25 
317             0x01 - 40x25
318             0x02 - 80x25
319             0x03 - 80x25 or 80x43 or 80x50 (assume 80x25) 
320             0x07 - 80x25
321         */
322
323         switch (AL_reg(context)) {
324             case 0x00: /* 40x25 */
325             case 0x01:
326                 VGA_Exit();
327                 TRACE("Set Video Mode - Set to Text - 0x0%x\n",
328                    AL_reg(context));
329                 CONSOLE_ResizeScreen(40, 25);
330                 CONSOLE_ClearScreen();
331                 DOSMEM_BiosData()->VideoColumns = 40;
332                 break;                
333             case 0x02:
334             case 0x03:
335             case 0x07:
336                 VGA_Exit();
337                 TRACE("Set Video Mode - Set to Text - 0x0%x\n",
338                    AL_reg(context));
339                 CONSOLE_ResizeScreen(80, 25);
340                 CONSOLE_ClearScreen();
341                 DOSMEM_BiosData()->VideoColumns = 80;
342                 break;
343             case 0x0D:
344                 TRACE("Setting VGA 320x200 16-color mode\n");
345                 VGA_SetMode(320,200,4);
346                 break;
347             case 0x0E:
348                 TRACE("Setting VGA 640x200 16-color mode\n");
349                 VGA_SetMode(640,200,4); 
350                 break;
351             case 0x10:
352                 TRACE("Setting VGA 640x350 16-color mode\n");
353                 VGA_SetMode(640,350,4);
354                 break;
355             case 0x12:
356                 TRACE("Setting VGA 640x480 16-color mode\n");
357                 VGA_SetMode(640,480,4);
358                 break;
359             case 0x13:
360                 TRACE("Setting VGA 320x200 256-color mode\n");
361                 VGA_SetMode(320,200,8);
362                 break;
363             default:
364                 FIXME("Set Video Mode (0x%x) - Not Supported\n", 
365                    AL_reg(context));
366         }
367         DOSMEM_BiosData()->VideoMode = AL_reg(context);
368         break;
369
370     case 0x01: /* SET CURSOR SHAPE */
371         FIXME("Set Cursor Shape - Not Supported\n");
372         break;
373     
374     case 0x02: /* SET CURSOR POSITION */
375         /* BH = Page Number */ /* Not supported */
376         /* DH = Row */ /* 0 is left */
377         /* DL = Column */ /* 0 is top */
378         if (BH_reg(context))
379         {
380            FIXME("Set Cursor Position: Cannot set to page %d\n",
381               BH_reg(context));
382         }
383         else
384         {
385            CONSOLE_MoveCursor(DH_reg(context), DL_reg(context));
386            TRACE("Set Cursor Position: %d %d\n", DH_reg(context), 
387               DL_reg(context));
388         }
389         break;
390
391     case 0x03: /* GET CURSOR POSITION AND SIZE */
392         {
393           CHAR row, col;
394
395           FIXME("Get cursor position and size - partially supported\n");
396           CX_reg(context) = 0x0a0b; /* Bogus cursor data */
397           CONSOLE_GetCursorPosition(&row, &col);
398           DH_reg(context) = row;
399           DL_reg(context) = col;
400         }
401         break;
402
403     case 0x04: /* READ LIGHT PEN POSITION */
404         FIXME("Read Light Pen Position - Not Supported\n");
405         AH_reg(context) = 0x00; /* Not down */
406         break;
407
408     case 0x05: /* SELECT ACTIVE DISPLAY PAGE */
409         FIXME("Select Active Display Page - Not Supported\n");
410         break;
411
412     case 0x06: /* SCROLL UP WINDOW */
413         /* AL = Lines to scroll */
414         /* BH = Attribute */
415         /* CH,CL = row, col upper-left */
416         /* DH,DL = row, col lower-right */
417         scroll_window(SCROLL_UP, AL_reg(context), CH_reg(context), 
418            CL_reg(context), DH_reg(context), DL_reg(context), 
419            BH_reg(context));
420         TRACE("Scroll Up Window %d\n", AL_reg(context));
421         break;
422
423     case 0x07: /* SCROLL DOWN WINDOW */
424         /* AL = Lines to scroll */
425         /* BH = Attribute */
426         /* CH,CL = row, col upper-left */
427         /* DH,DL = row, col lower-right */
428         scroll_window(SCROLL_DOWN, AL_reg(context), CH_reg(context), 
429            CL_reg(context), DH_reg(context), DL_reg(context), 
430            BH_reg(context));
431         TRACE("Scroll Down Window %d\n", AL_reg(context));
432         break;
433
434     case 0x08: /* READ CHARACTER AND ATTRIBUTE AT CURSOR POSITION */
435         {
436             /* Note here that color data returned is bogus, will fix later. */
437             char ch;
438             int bg, fg, attr;
439             if (BH_reg(context)) /* Write to different page */
440             {
441                 FIXME("Read character and attribute at cursor position -"
442                       " Can't read from non-0 page\n");
443                 AL_reg(context) = ' '; /* That page is blank */
444                 AH_reg(context) = 7;
445             }
446             else
447             {
448                 TRACE(
449                       "Read Character and Attribute at Cursor Position\n");
450                 CONSOLE_GetCharacterAtCursor(&ch, &fg, &bg, &attr);
451                 AL_reg(context) = ch;
452                 AH_reg(context) = 7;    /* FIXME: We're assuming wh on bl */ 
453             }
454         }
455         break;
456
457     case 0x09: /* WRITE CHARACTER AND ATTRIBUTE AT CURSOR POSITION */
458        /* AL = Character to display. */
459        /* BH = Page Number */ /* We can't write to non-0 pages, yet. */
460        /* BL = Attribute / Color */
461        /* CX = Times to Write Char */
462        /* Note here that the cursor is not advanced. */
463        write_char_attribute_at_cursor(AL_reg(context), BH_reg(context), 
464           BL_reg(context), CX_reg(context));
465        if (CX_reg(context) > 1)
466           TRACE("Write Character and Attribute at Cursor Position "
467              "(Rep. %d) %c\n", CX_reg(context), AL_reg(context));
468        else
469           TRACE("Write Character and Attribute at Cursor"
470              "Position: %c\n", AL_reg(context));
471        break;
472
473     case 0x0a: /* WRITE CHARACTER ONLY AT CURSOR POSITION */ 
474        /* AL = Character to display. */
475        /* BH = Page Number */ /* We can't write to non-0 pages, yet. */
476        /* CX = Times to Write Char */
477        TRACE("Write Character at Cursor\n");
478        write_char_attribute_at_cursor(AL_reg(context), BH_reg(context), 
479           0, CX_reg(context));
480        break;
481
482     case 0x0b: 
483         switch BH_reg(context) {
484         case 0x00: /* SET BACKGROUND/BORDER COLOR */
485             /* In text modes, this sets only the border... */
486             /* According to the interrupt list and one of my books. */
487             /* Funny though that Beyond Zork seems to indicate that it 
488                also sets up the default background attributes for clears
489                and scrolls... */
490             /* Bear in mind here that we do not want to change,
491                apparantly, the foreground or attribute of the background
492                with this call, so we should check first to see what the
493                foreground already is... FIXME */
494             TRACE("Set Background/Border Color: %d\n", 
495                BL_reg(context));
496             CONSOLE_SetBackgroundColor(color_palette[0],
497                color_palette[BL_reg(context)]);   
498             break;
499         case 0x01: /* SET PALETTE */
500             FIXME("Set Palette - Not Supported\n");
501             break;
502         default:
503             FIXME("INT 10 AH = 0x0b BH = 0x%x - Unknown\n", 
504                BH_reg(context));
505             break;
506         }
507         break;
508
509     case 0x0c: /* WRITE GRAPHICS PIXEL */
510         /* Not in graphics mode, can ignore w/o error */
511         FIXME("Write Graphics Pixel - Not Supported\n");
512         break;
513         
514     case 0x0d: /* READ GRAPHICS PIXEL */
515         /* Not in graphics mode, can ignore w/o error */
516         FIXME("Read Graphics Pixel - Not Supported\n");
517         break;
518               
519     case 0x0e: /* TELETYPE OUTPUT */
520         TRACE("Teletype Output\n");
521         CONSOLE_Write(AL_reg(context), 0, 0, 0);
522         break;
523
524     case 0x0f: /* GET CURRENT VIDEO MODE */
525         TRACE("Get current video mode\n");
526         /* Note: This should not be a constant value. */
527         AL_reg(context) = DOSMEM_BiosData()->VideoMode;
528         AH_reg(context) = DOSMEM_BiosData()->VideoColumns;
529         BH_reg(context) = 0; /* Display page 0 */
530         break;
531
532     case 0x10: 
533         switch AL_reg(context) {
534         case 0x00: /* SET SINGLE PALETTE REGISTER */
535             FIXME("Set Single Palette Register - Not Supported\n");
536             break;
537         case 0x01: /* SET BORDER (OVERSCAN) */
538             /* Text terminals have no overscan */
539             TRACE("Set Border (Overscan) - Ignored\n");
540             break;
541         case 0x02: /* SET ALL PALETTE REGISTERS */
542             FIXME("Set all palette registers - Not Supported\n");
543             break;
544         case 0x03: /* TOGGLE INTENSITY/BLINKING BIT */
545             FIXME("Toggle Intensity/Blinking Bit - Not Supported\n");
546             break;
547         case 0x07: /* GET INDIVIDUAL PALETTE REGISTER */
548             FIXME("Get Individual Palette Register - Not Supported\n");
549             break;
550         case 0x08: /* READ OVERSCAN (BORDER COLOR) REGISTER */
551             FIXME(
552                "Read Overscan (Border Color) Register - Not Supported\n");
553             break;
554         case 0x09: /* READ ALL PALETTE REGISTERS AND OVERSCAN REGISTER */
555             FIXME(
556                "Read All Palette Registers and Overscan Register "
557                " - Not Supported\n");
558             break;
559         case 0x10: /* SET INDIVIDUAL DAC REGISTER */
560             FIXME("Set Individual DAC register - Not Supported\n");
561             break;
562         case 0x12: /* SET BLOCK OF DAC REGISTERS */
563             FIXME("Set Block of DAC registers - Not Supported\n");
564             break;
565         case 0x13: /* SELECT VIDEO DAC COLOR PAGE */
566             FIXME("Select video DAC color page - Not Supported\n");
567             break;
568         case 0x15: /* READ INDIVIDUAL DAC REGISTER */
569             FIXME("Read individual DAC register - Not Supported\n");
570             break;
571         case 0x17: /* READ BLOCK OF DAC REGISTERS */
572             FIXME("Read block of DAC registers - Not Supported\n");
573             break;
574         case 0x18: /* SET PEL MASK */
575             FIXME("Set PEL mask - Not Supported\n");
576             break;
577         case 0x19: /* READ PEL MASK */
578             FIXME("Read PEL mask - Not Supported\n");
579             break;
580         case 0x1a: /* GET VIDEO DAC COLOR PAGE STATE */
581             FIXME("Get video DAC color page state - Not Supported\n");
582             break;
583         case 0x1b: /* PERFORM GRAY-SCALE SUMMING */
584             FIXME("Perform Gray-scale summing - Not Supported\n");
585             break;
586         default:
587             FIXME("INT 10 AH = 0x10 AL = 0x%x - Unknown\n", 
588                AL_reg(context));
589             break;
590         }
591         break;
592
593     case 0x11: /* TEXT MODE CHARGEN */
594         /* Note that second subfunction is *almost* identical. */
595         /* See INTERRUPT.A for details. */
596         switch AL_reg(context) {
597         case 0x00: /* LOAD USER SPECIFIED PATTERNS */
598         case 0x10:
599             FIXME("Load User Specified Patterns - Not Supported\n");
600             break;
601         case 0x01: /* LOAD ROM MONOCHROME PATTERNS */
602         case 0x11:
603             FIXME("Load ROM Monochrome Patterns - Not Supported\n");
604             break;
605         case 0x02: /* LOAD ROM 8x8 DOUBLE-DOT PATTERNS */
606         case 0x12:
607             FIXME(
608                 "Load ROM 8x8 Double Dot Patterns - Not Supported\n");       
609             break;
610         case 0x03: /* SET BLOCK SPECIFIER */
611             FIXME("Set Block Specifier - Not Supported\n");
612             break;
613         case 0x04: /* LOAD ROM 8x16 CHARACTER SET */
614         case 0x14:
615             FIXME("Load ROM 8x16 Character Set - Not Supported\n");
616             break;
617         case 0x20: /* SET USER 8x16 GRAPHICS CHARS */
618             FIXME("Set User 8x16 Graphics Chars - Not Supported\n");
619             break;
620         case 0x21: /* SET USER GRAPICS CHARACTERS */
621             FIXME("Set User Graphics Characters - Not Supported\n");
622             break;
623         case 0x22: /* SET ROM 8x14 GRAPHICS CHARS */
624             FIXME("Set ROM 8x14 Graphics Chars - Not Supported\n");
625             break;
626         case 0x23: /* SET ROM 8x8 DBL DOT CHARS */
627             FIXME(
628                 "Set ROM 8x8 Dbl Dot Chars (Graphics) - Not Supported\n");
629             break;
630         case 0x24: /* LOAD 8x16 GRAPHIC CHARS */
631             FIXME("Load 8x16 Graphic Chars - Not Supported\n");
632             break;
633         case 0x30: /* GET FONT INFORMATION */
634             FIXME("Get Font Information - Not Supported\n");
635             break;
636         default:
637             FIXME("INT 10 AH = 0x11 AL = 0x%x - Unknown\n", 
638                AL_reg(context));
639             break;
640         }
641         break;
642         
643     case 0x12: /* ALTERNATE FUNCTION SELECT */
644         switch BL_reg(context) {
645         case 0x10: /* GET EGA INFO */
646             TRACE("EGA info requested\n");
647             BH_reg(context) = 0x00;   /* Color screen */
648             BL_reg(context) =
649                 DOSMEM_BiosData()->ModeOptions >> 5; /* EGA memory size */
650             CX_reg(context) =
651                 DOSMEM_BiosData()->FeatureBitsSwitches;
652             break;
653         case 0x20: /* ALTERNATE PRTSC */
654             FIXME("Install Alternate Print Screen - Not Supported\n");
655             break;
656         case 0x30: /* SELECT VERTICAL RESOULTION */
657             FIXME("Select vertical resolution - not supported\n");
658             break;
659         case 0x31: /* ENABLE/DISABLE DEFAULT PALETTE LOADING */
660             FIXME("Default palette loading - not supported\n");
661             DOSMEM_BiosData()->VGASettings =
662                 (DOSMEM_BiosData()->VGASettings & 0xf7) |
663                 ((AL_reg(context) == 1) << 3);
664             break;
665         case 0x32: /* ENABLE/DISABLE VIDEO ADDRERSSING */
666             FIXME("Video Addressing - Not Supported\n");
667             break;
668         case 0x33: /* ENABLE/DISABLE GRAY SCALE SUMMING */
669             FIXME("Gray Scale Summing - Not Supported\n");
670             break;
671         case 0x34: /* ENABLE/DISABLE CURSOR EMULATION */
672             TRACE("Set cursor emulation to %d\n", AL_reg(context));
673             DOSMEM_BiosData()->ModeOptions =
674                 (DOSMEM_BiosData()->ModeOptions & 0xfe)|(AL_reg(context) == 1);
675             break;
676         case 0x36: /* VIDEO ADDRESS CONTROL */
677             FIXME("Video Address Control - Not Supported\n");
678             break;
679         default:
680             FIXME("INT 10 AH = 0x11 AL = 0x%x - Unknown\n", 
681                AL_reg(context));
682             break;
683         }
684         break;
685
686     case 0x13: /* WRITE STRING */
687         /* This one does not imply that string be at cursor. */
688         FIXME("Write String - Not Supported\n");
689         break;
690                              
691     case 0x1a: 
692         switch AL_reg(context) {
693         case 0x00: /* GET DISPLAY COMBINATION CODE */
694             TRACE("Get Display Combination Code\n");
695             AX_reg(context) = 0x001a;
696             BL_reg(context) = 0x08; /* VGA w/ color analog display */
697             BH_reg(context) = 0x00; /* No secondary hardware */
698             break;
699         case 0x01: /* SET DISPLAY COMBINATION CODE */
700             FIXME("Set Display Combination Code - Not Supported\n");
701             break;
702         default:
703             FIXME("INT 10 AH = 0x1a AL = 0x%x - Unknown\n", 
704                AL_reg(context));
705             break;
706         }
707     break;
708
709     case 0x1b: /* FUNCTIONALITY/STATE INFORMATION */
710         FIXME("Get functionality/state information - partially implemented\n");
711         if (BX_reg(context) == 0x0)
712         {
713           AL_reg(context) = 0x1b;
714           if (ISV86(context)) /* real */
715             ES_reg(context) = 0xf000;
716           else
717             ES_reg(context) = DOSMEM_BiosSysSeg;
718           BX_reg(context) = 0xe000;
719         }
720         break;
721
722     case 0x1c: /* SAVE/RESTORE VIDEO STATE */
723         FIXME("Save/Restore Video State - Not Supported\n");
724         break;
725
726     case 0x4f: /* Get SuperVGA INFORMATION */
727         {
728           BYTE *p =
729                CTX_SEG_OFF_TO_LIN(context, ES_reg(context), EDI_reg(context));
730           /* BOOL16 vesa20 = (*(DWORD *)p == *(DWORD *)"VBE2"); */
731   
732           TRACE("Get SuperVGA information\n");
733           AH_reg(context) = 0;
734           *(DWORD *)p = *(DWORD *)"VESA";
735           *(WORD *)(p+0x04) = 0x0200; /* VESA 2.0 */
736           *(DWORD *)(p+0x06) = 0x00000000; /* pointer to OEM name */
737           *(DWORD *)(p+0x0a) = 0xfffffffd; /* capabilities flags :-) */
738         }
739         break;
740         case 0xef:  /* get video mode for hercules-compatables   */
741                     /* There's no reason to really support this  */
742                     /* is there?....................(A.C.)       */
743                 TRACE("Just report the video not hercules compatable\n");
744                 DX_reg(context) = 0xffff;
745                 break; 
746     default:
747         FIXME("Unknown - 0x%x\n", AH_reg(context));
748         INT_BARF( context, 0x10 );
749     }
750 }
751 }
752
753 static void write_char_attribute_at_cursor(char output, char page_num, 
754        char attribute, short times)
755 {
756     /* Contrary to the interrupt list, this routine should not advance
757        the cursor. To keep this logic simple, we won't use the
758        CONSOLE_Put() routine. 
759     */
760
761     int wattribute, fg_color, bg_color;
762     char x, y;
763
764     if (page_num) /* Only support one text page right now */
765     {
766        FIXME("Cannot write to alternate page %d", page_num);
767        return;
768     }  
769
770     conv_text_mode_attributes(attribute, &fg_color, &bg_color,
771         &wattribute);
772
773     TRACE("Fore: %d Back: %d\n", fg_color, bg_color);
774
775     CONSOLE_GetCursorPosition(&x, &y);
776
777     while (times)
778     {
779        CONSOLE_Write(output, fg_color, bg_color, attribute);           
780        times--;
781     }
782   
783     CONSOLE_MoveCursor(x, y);
784 }
785
786 static void conv_text_mode_attributes(char attribute, int *fg, int *bg,
787    int *wattribute)
788 {
789     /* This is a local function to convert the text-mode attributes
790        to Wine's color and attribute scheme */
791
792     /* Foreground Color is stored in bits 3 through 0 */
793     /* Background Color is stored in bits 6 through 4 */
794     /* If this has bit 7 set, then we need to blink */
795
796     *fg = color_palette[attribute & 15];
797     *bg = color_palette[(attribute & 112) / 16];
798     *wattribute = attribute & 128;
799
800 }
801
802 static void scroll_window(int direction, char lines, char row1, 
803    char col1, char row2, char col2, char attribute)
804 {
805    int wattribute, bg_color, fg_color;
806
807    conv_text_mode_attributes(attribute, &fg_color, &bg_color,
808       &wattribute);
809
810    if (!lines) /* Actually, clear the window */
811    {
812       CONSOLE_ClearWindow(row1, col1, row2, col2, bg_color, wattribute);
813    }
814    else if (direction == SCROLL_UP)
815    {
816       CONSOLE_ScrollUpWindow(row1, col1, row2, col2, lines, bg_color,
817          wattribute);
818    }
819    else
820    {
821       CONSOLE_ScrollDownWindow(row1, col1, row2, col2, lines, bg_color,
822          wattribute);
823    }
824 }
825