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