- New implementation of SendMessage, ReceiveMessage, ReplyMessage functions
[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 /* #define DEBUG_INT */
9 #include "debug.h"
10 #include "console.h"
11
12 static void conv_text_mode_attributes(char attribute, int *fg, int *bg,
13        int *wattribute);
14 static void write_char_attribute_at_cursor(char output, char page_num, 
15        char attribute, short times);
16 static void scroll_window(int direction, char lines, char row1, 
17    char col1, char row2, char col2, char attribute);
18
19 static int color_pallet[16];
20
21 #define SCROLL_UP 1
22 #define SCROLL_DOWN 2
23
24 /**********************************************************************
25  *          INT_Int10Handler
26  *
27  * Handler for int 10h (video).
28  * 
29  * NOTE:
30  *    Most INT 10 functions for text-mode, CGA, EGA, and VGA cards
31  *    are present in this list. (SVGA and XGA are not) That is not
32  *    to say that all these functions should be supported, but if
33  *    anyone is braindamaged enough to want to emulate one of these
34  *    beasts then this should get you started. 
35  *
36  * NOTE:
37  *    Several common graphical extensions used by Microsoft hook
38  *    off of here. I have *not* added them to this list (yet). They
39  *    include:
40  *
41  *    MSHERC.COM - More functionality for Hercules cards.
42  *    EGA.SYS (also MOUSE.COM) - More for EGA cards.
43  *    
44  *    Yes, MS also added this support into their mouse driver. Don't
45  *    ask me, I don't work for them.
46  *
47  * Joseph Pranevich - 9/98 
48  */
49
50 void WINAPI INT_Int10Handler( CONTEXT *context )
51 {
52     static int registered_colors = FALSE;
53     static int video_mode = 7;
54     static int video_columns = 80;
55
56     if (!registered_colors)
57     {
58         /* Colors:
59              0000b   black          1000b   dark gray
60              0001b   blue           1001b   light blue
61              0010b   green          1010b   light green
62              0011b   cyan           1011b   light cyan
63              0100b   red            1100b   light red
64              0101b   magenta        1101b   light magenta
65              0110b   brown          1110b   yellow
66              0111b   light gray     1111b   white
67         */
68         
69         /* These AllocColor calls have the side-effect of triggering 
70            ternimal initialization as xx_Init() is no longer called on
71            startup. Which is what we want anyway. */
72
73         color_pallet[0]  = CONSOLE_AllocColor(WINE_BLACK);
74         color_pallet[1]  = CONSOLE_AllocColor(WINE_BLUE);
75         color_pallet[2]  = CONSOLE_AllocColor(WINE_GREEN);
76         color_pallet[3]  = CONSOLE_AllocColor(WINE_CYAN);
77         color_pallet[4]  = CONSOLE_AllocColor(WINE_RED);
78         color_pallet[5]  = CONSOLE_AllocColor(WINE_MAGENTA);
79         color_pallet[6]  = CONSOLE_AllocColor(WINE_BROWN);
80         color_pallet[7]  = CONSOLE_AllocColor(WINE_LIGHT_GRAY);
81         color_pallet[8]  = CONSOLE_AllocColor(WINE_DARK_GRAY);
82         color_pallet[9]  = CONSOLE_AllocColor(WINE_LIGHT_BLUE);
83         color_pallet[10] = CONSOLE_AllocColor(WINE_LIGHT_GREEN);
84         color_pallet[11] = CONSOLE_AllocColor(WINE_LIGHT_CYAN);
85         color_pallet[12] = CONSOLE_AllocColor(WINE_LIGHT_RED);
86         color_pallet[13] = CONSOLE_AllocColor(WINE_LIGHT_MAGENTA);
87         color_pallet[14] = CONSOLE_AllocColor(WINE_YELLOW);
88         color_pallet[15] = CONSOLE_AllocColor(WINE_WHITE);
89     }
90
91     switch(AH_reg(context)) {
92
93     case 0x00: /* SET VIDEO MODE */
94         /* Text Modes: */
95         /* (mode) (text rows/cols)
96             0x00 - 40x25 
97             0x01 - 40x25
98             0x02 - 80x25
99             0x03 - 80x25 or 80x43 or 80x50 (assume 80x25) 
100             0x07 - 80x25
101         */
102
103         switch (AL_reg(context)) {
104             case 0x00: /* 40x25 */
105             case 0x01:
106                 VGA_Exit();
107                 TRACE(int10, "Set Video Mode - Set to Text - 0x0%x\n",
108                    AL_reg(context));
109                 CONSOLE_ResizeScreen(40, 25);
110                 CONSOLE_ClearScreen();
111                 video_mode = AL_reg(context);
112                 video_columns = 40;
113                 break;                
114             case 0x02:
115             case 0x03:
116             case 0x07:
117                 VGA_Exit();
118                 TRACE(int10, "Set Video Mode - Set to Text - 0x0%x\n",
119                    AL_reg(context));
120                 CONSOLE_ResizeScreen(80, 25);
121                 CONSOLE_ClearScreen();
122                 video_mode = AL_reg(context);
123                 video_columns = 80;
124                 break;
125             case 0x13:
126                 TRACE(int10, "Setting VGA 320x200 256-color mode\n");
127                 VGA_SetMode(320,200,8);
128                 video_mode = AL_reg(context);
129                 break;
130             default:
131                 FIXME(int10, "Set Video Mode (0x%x) - Not Supported\n", 
132                    AL_reg(context));
133         }
134         break;
135
136     case 0x01: /* SET CURSOR SHAPE */
137         FIXME(int10, "Set Cursor Shape - Not Supported\n");
138         break;
139     
140     case 0x02: /* SET CURSOR POSITION */
141         /* BH = Page Number */ /* Not supported */
142         /* DH = Row */ /* 0 is left */
143         /* DL = Column */ /* 0 is top */
144         if (BH_reg(context))
145         {
146            FIXME(int10, "Set Cursor Position: Cannot set to page %d\n",
147               BH_reg(context));
148         }
149         else
150         {
151            CONSOLE_MoveCursor(DH_reg(context), DL_reg(context));
152            TRACE(int10, "Set Cursor Position: %d %d\n", DH_reg(context), 
153               DL_reg(context));
154         }
155         break;
156
157     case 0x03: /* GET CURSOR POSITION AND SIZE */
158         FIXME(int10, "Get Cursor Position and Size - Not Supported\n");
159         CX_reg(context) = 0x0000; /* Bogus cursor data */
160         DX_reg(context) = 0x0000;
161         break;
162
163     case 0x04: /* READ LIGHT PEN POSITION */
164         FIXME(int10, "Read Light Pen Position - Not Supported\n");
165         AH_reg(context) = 0x00; /* Not down */
166         break;
167
168     case 0x05: /* SELECT ACTIVE DISPLAY PAGE */
169         FIXME(int10, "Select Active Display Page - Not Supported\n");
170         break;
171
172     case 0x06: /* SCROLL UP WINDOW */
173         /* AL = Lines to scroll */
174         /* BH = Attribute */
175         /* CH,CL = row, col upper-left */
176         /* DH,DL = row, col lower-right */
177         scroll_window(SCROLL_UP, AL_reg(context), CH_reg(context), 
178            CL_reg(context), DH_reg(context), DL_reg(context), 
179            BH_reg(context));
180         TRACE(int10, "Scroll Up Window %d\n", AL_reg(context));
181         break;
182
183     case 0x07: /* SCROLL DOWN WINDOW */
184         /* AL = Lines to scroll */
185         /* BH = Attribute */
186         /* CH,CL = row, col upper-left */
187         /* DH,DL = row, col lower-right */
188         scroll_window(SCROLL_DOWN, AL_reg(context), CH_reg(context), 
189            CL_reg(context), DH_reg(context), DL_reg(context), 
190            BH_reg(context));
191         TRACE(int10, "Scroll Down Window %d\n", AL_reg(context));
192         break;
193
194     case 0x08: /* READ CHARACTER AND ATTRIBUTE AT CURSOR POSITION */
195         {
196             /* Note here that color data returned is bogus, will fix later. */
197             char ch;
198             int bg, fg, attr;
199             if (BH_reg(context)) /* Write to different page */
200             {
201                 FIXME(int10, "Read Character and Attribute at Cursor Position -"
202                       " Can't read from non-0 page\n");
203                 AL_reg(context) = ' '; /* That page is blank */
204                 AH_reg(context) = 7;
205             }
206             else
207             {
208                 TRACE(int10, 
209                       "Read Character and Attribute at Cursor Position\n");
210                 CONSOLE_GetCharacterAtCursor(&ch, &fg, &bg, &attr);
211                 AL_reg(context) = ch;
212                 AH_reg(context) = 7;    /* FIXME: We're assuming wh on bl */ 
213             }
214         }
215         break;
216
217     case 0x09: /* WRITE CHARACTER AND ATTRIBUTE AT CURSOR POSITION */
218        /* AL = Character to display. */
219        /* BH = Page Number */ /* We can't write to non-0 pages, yet. */
220        /* BL = Attribute / Color */
221        /* CX = Times to Write Char */
222        /* Note here that the cursor is not advanced. */
223        write_char_attribute_at_cursor(AL_reg(context), BH_reg(context), 
224           BL_reg(context), CX_reg(context));
225        if (CX_reg(context) > 1)
226           TRACE(int10, "Write Character and Attribute at Cursor Position "
227              "(Rep. %d) %c\n", CX_reg(context), AL_reg(context));
228        else
229           TRACE(int10, "Write Character and Attribute at Cursor"
230              "Position: %c\n", AL_reg(context));
231        break;
232
233     case 0x0a: /* WRITE CHARACTER ONLY AT CURSOR POSITION */ 
234        /* AL = Character to display. */
235        /* BH = Page Number */ /* We can't write to non-0 pages, yet. */
236        /* CX = Times to Write Char */
237        TRACE(int10, "Write Character at Cursor\n");
238        write_char_attribute_at_cursor(AL_reg(context), BH_reg(context), 
239           0, CX_reg(context));
240        break;
241
242     case 0x0b: 
243         switch BH_reg(context) {
244         case 0x00: /* SET BACKGROUND/BORDER COLOR */
245             /* In text modes, this sets only the border */
246             TRACE(int10, "Set Background/Border Color - Ignored\n");
247             break;
248         case 0x01: /* SET PALETTE */
249             FIXME(int10, "Set Palette - Not Supported\n");
250             break;
251         default:
252             FIXME(int10, "INT 10 AH = 0x0b BH = 0x%x - Unknown\n", 
253                BH_reg(context));
254             break;
255         }
256         break;
257
258     case 0x0c: /* WRITE GRAPHICS PIXEL */
259         /* Not in graphics mode, can ignore w/o error */
260         FIXME(int10, "Write Graphics Pixel - Not Supported\n");
261         break;
262         
263     case 0x0d: /* READ GRAPHICS PIXEL */
264         /* Not in graphics mode, can ignore w/o error */
265         FIXME(int10, "Read Graphics Pixel - Not Supported\n");
266         break;
267               
268     case 0x0e: /* TELETYPE OUTPUT */
269         TRACE(int10, "Teletype Output\n");
270         CONSOLE_Write(AL_reg(context), 0, 0, 0);
271         break;
272
273     case 0x0f: /* GET CURRENT VIDEO MODE */
274         TRACE(int10, "Get Current Video Mode\n");
275         /* Note: This should not be a constant value. */
276         AL_reg(context) = video_mode;
277         AH_reg(context) = video_columns;
278         BH_reg(context) = 0; /* Display page 0 */
279         break;
280
281     case 0x10: 
282         switch AL_reg(context) {
283         case 0x00: /* SET SINGLE PALETTE REGISTER */
284             FIXME(int10, "Set Single Palette Register - Not Supported\n");
285             break;
286         case 0x01: /* SET BORDER (OVERSCAN) */
287             /* Text terminals have no overscan */
288             TRACE(int10, "Set Border (Overscan) - Ignored\n");
289             break;
290         case 0x02: /* SET ALL PALETTE REGISTERS */
291             FIXME(int10, "Set all palette registers - Not Supported\n");
292             break;
293         case 0x03: /* TOGGLE INTENSITY/BLINKING BIT */
294             FIXME(int10, "Toggle Intensity/Blinking Bit - Not Supported\n");
295             break;
296         case 0x07: /* GET INDIVIDUAL PALETTE REGISTER */
297             FIXME(int10, "Get Individual Palette Register - Not Supported\n");
298             break;
299         case 0x08: /* READ OVERSCAN (BORDER COLOR) REGISTER */
300             FIXME(int10, 
301                "Read Overscan (Border Color) Register - Not Supported\n");
302             break;
303         case 0x09: /* READ ALL PALETTE REGISTERS AND OVERSCAN REGISTER */
304             FIXME(int10, 
305                "Read All Palette Registers and Overscan Register "
306                " - Not Supported\n");
307             break;
308         case 0x10: /* SET INDIVIDUAL DAC REGISTER */
309             FIXME(int10, "Set Individual DAC register - Not Supported\n");
310             break;
311         case 0x12: /* SET BLOCK OF DAC REGISTERS */
312             FIXME(int10, "Set Block of DAC registers - Not Supported\n");
313             break;
314         case 0x13: /* SELECT VIDEO DAC COLOR PAGE */
315             FIXME(int10, "Select video DAC color page - Not Supported\n");
316             break;
317         case 0x15: /* READ INDIVIDUAL DAC REGISTER */
318             FIXME(int10, "Read individual DAC register - Not Supported\n");
319             break;
320         case 0x17: /* READ BLOCK OF DAC REGISTERS */
321             FIXME(int10, "Read block of DAC registers - Not Supported\n");
322             break;
323         case 0x18: /* SET PEL MASK */
324             FIXME(int10, "Set PEL mask - Not Supported\n");
325             break;
326         case 0x19: /* READ PEL MASK */
327             FIXME(int10, "Read PEL mask - Not Supported\n");
328             break;
329         case 0x1a: /* GET VIDEO DAC COLOR PAGE STATE */
330             FIXME(int10, "Get video DAC color page state - Not Supported\n");
331             break;
332         case 0x1b: /* PERFORM GRAY-SCALE SUMMING */
333             FIXME(int10, "Perform Gray-scale summing - Not Supported\n");
334             break;
335         default:
336             FIXME(int10, "INT 10 AH = 0x10 AL = 0x%x - Unknown\n", 
337                AL_reg(context));
338             break;
339         }
340         break;
341
342     case 0x11: /* TEXT MODE CHARGEN */
343         /* Note that second subfunction is *almost* identical. */
344         /* See INTERRUPT.A for details. */
345         switch AH_reg(context) {
346         case 0x00: /* LOAD USER SPECIFIED PATTERNS */
347         case 0x10:
348             FIXME(int10, "Load User Specified Patterns - Not Supported\n");
349             break;
350         case 0x01: /* LOAD ROM MONOCHROME PATTERNS */
351         case 0x11:
352             FIXME(int10, "Load ROM Monochrome Patterns - Not Supported\n");
353             break;
354         case 0x02: /* LOAD ROM 8x8 DOUBLE-DOT PATTERNS */
355         case 0x12:
356             FIXME(int10, 
357                 "Load ROM 8x8 Double Dot Patterns - Not Supported\n");       
358             break;
359         case 0x03: /* SET BLOCK SPECIFIER */
360             FIXME(int10, "Set Block Specifier - Not Supported\n");
361             break;
362         case 0x04: /* LOAD ROM 8x16 CHARACTER SET */
363         case 0x14:
364             FIXME(int10, "Load ROM 8x16 Character Set - Not Supported\n");
365             break;
366         case 0x20: /* SET USER 8x16 GRAPHICS CHARS */
367             FIXME(int10, "Set User 8x16 Graphics Chars - Not Supported\n");
368             break;
369         case 0x21: /* SET USER GRAPICS CHARACTERS */
370             FIXME(int10, "Set User Graphics Characters - Not Supported\n");
371             break;
372         case 0x22: /* SET ROM 8x14 GRAPHICS CHARS */
373             FIXME(int10, "Set ROM 8x14 Graphics Chars - Not Supported\n");
374             break;
375         case 0x23: /* SET ROM 8x8 DBL DOT CHARS */
376             FIXME(int10, 
377                 "Set ROM 8x8 Dbl Dot Chars (Graphics) - Not Supported\n");
378             break;
379         case 0x24: /* LOAD 8x16 GRAPHIC CHARS */
380             FIXME(int10, "Load 8x16 Graphic Chars - Not Supported\n");
381             break;
382         case 0x30: /* GET FONT INFORMATION */
383             FIXME(int10, "Get Font Information - Not Supported\n");
384             break;
385         default:
386             FIXME(int10, "INT 10 AH = 0x11 AL = 0x%x - Unknown\n", 
387                AL_reg(context));
388             break;
389         }
390         break;
391         
392     case 0x12: /* ALTERNATE FUNCTION SELECT */
393         switch BL_reg(context) {
394         case 0x10: /* GET EGA INFO */
395             TRACE(int10, "EGA Info Requested\n");
396             BH_reg(context) = 0x00;   /* Color screen */
397             BL_reg(context) = 0x03;   /* 256K EGA card */
398             CH_reg(context) = 0x00;   /* Switch settings?? */
399             CL_reg(context) = 0x09;   /* EGA+ card */
400             break;
401         case 0x20: /* ALTERNATE PRTSC */
402             FIXME(int10, "Install Alternate Print Screen - Not Supported\n");
403             break;
404         case 0x30: /* SELECT VERTICAL RESOULTION */
405             FIXME(int10, "Select Vertical Resoultion - Not Supported\n");
406             break;
407         case 0x31: /* ENABLE/DISABLE PALETTE LOADING */
408             FIXME(int10, "Palette Loading - Not Supported\n");
409             break;
410         case 0x32: /* ENABLE/DISABLE VIDEO ADDRERSSING */
411             FIXME(int10, "Video Addressing - Not Supported\n");
412             break;
413         case 0x33: /* ENABLE/DISABLE GRAY SCALE SUMMING */
414             FIXME(int10, "Gray Scale Summing - Not Supported\n");
415             break;
416         case 0x34: /* ENABLE/DISABLE CURSOR EMULATION */
417             FIXME(int10, "Cursor Emulation - Not Supported\n");
418             break;
419         case 0x36: /* VIDEO ADDRESS CONTROL */
420             FIXME(int10, "Video Address Control - Not Supported\n");
421             break;
422         default:
423             FIXME(int10, "INT 10 AH = 0x11 AL = 0x%x - Unknown\n", 
424                AL_reg(context));
425             break;
426         }
427         break;
428
429     case 0x13: /* WRITE STRING */
430         /* This one does not imply that string be at cursor. */
431         FIXME(int10, "Write String - Not Supported\n");
432         break;
433                              
434     case 0x1a: 
435         switch AL_reg(context) {
436         case 0x00: /* GET DISPLAY COMBINATION CODE */
437             TRACE(int10, "Get Display Combination Code\n");
438             AL_reg(context) = 0x1a;
439             BH_reg(context) = 0x08; /* VGA w/ color analog display */
440             BL_reg(context) = 0x00; /* No secondary hardware */
441             break;
442         case 0x01: /* SET DISPLAY COMBINATION CODE */
443             FIXME(int10, "Set Display Combination Code - Not Supported\n");
444             break;
445         default:
446             FIXME(int10, "INT 10 AH = 0x1a AL = 0x%x - Unknown\n", 
447                AL_reg(context));
448             break;
449         }
450     break;
451
452     case 0x1b: /* FUNCTIONALITY/STATE INFORMATION */
453         FIXME(int10, "Get Functionality/State Information - Not Supported\n");
454         break;
455
456     case 0x1c: /* SAVE/RESTORE VIDEO STATE */
457         FIXME(int10, "Save/Restore Video State - Not Supported\n");
458         break;
459
460     default:
461         FIXME(int10, "Unknown - 0x%x\n", AH_reg(context));
462         INT_BARF( context, 0x10 );
463     }
464 }
465
466 static void write_char_attribute_at_cursor(char output, char page_num, 
467        char attribute, short times)
468 {
469     /* Contrary to the interrupt list, this routine should not advance
470        the cursor. To keep this logic simple, we won't use the
471        CONSOLE_Put() routine. 
472     */
473
474     int wattribute, fg_color, bg_color;
475     char x, y;
476
477     if (page_num) /* Only support one text page right now */
478     {
479        FIXME(int10, "Cannot write to alternate page %d", page_num);
480        return;
481     }  
482
483     conv_text_mode_attributes(attribute, &fg_color, &bg_color,
484         &wattribute);
485
486     TRACE(int10, "Fore: %d Back: %d\n", fg_color, bg_color);
487
488     CONSOLE_GetCursorPosition(&x, &y);
489
490     while (times)
491     {
492        CONSOLE_Write(output, fg_color, bg_color, attribute);           
493        times--;
494     }
495   
496     CONSOLE_MoveCursor(x, y);
497 }
498
499 static void conv_text_mode_attributes(char attribute, int *fg, int *bg,
500    int *wattribute)
501 {
502     /* This is a local function to convert the text-mode attributes
503        to Wine's color and attribute scheme */
504
505     /* Foreground Color is stored in bits 3 through 0 */
506     /* Background Color is stored in bits 6 through 4 */
507     /* If this has bit 7 set, then we need to blink */
508
509     *fg = color_pallet[attribute & 15];
510     *bg = color_pallet[(attribute & 112) / 16];
511     *wattribute = attribute & 128;
512
513 }
514
515 static void scroll_window(int direction, char lines, char row1, 
516    char col1, char row2, char col2, char attribute)
517 {
518    int wattribute, bg_color, fg_color;
519
520    conv_text_mode_attributes(attribute, &fg_color, &bg_color,
521       &wattribute);
522
523    if (!lines) /* Actually, clear the window */
524    {
525       CONSOLE_ClearWindow(row1, col1, row2, col2, bg_color, wattribute);
526    }
527    else if (direction == SCROLL_UP)
528    {
529       CONSOLE_ScrollUpWindow(row1, col1, row2, col2, lines, bg_color,
530          wattribute);
531    }
532    else
533    {
534       CONSOLE_ScrollDownWindow(row1, col1, row2, col2, lines, bg_color,
535          wattribute);
536    }
537 }
538