Added beginnings of server-side file handling.
[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 (0x0%x)\n", AL_reg(context));
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             BX_reg(context) = 0x0003;
338             CX_reg(context) = 0x0009;
339             break;
340         case 0x20: /* ALTERNATE PRTSC */
341             FIXME(int10, "Install Alternate Print Screen - Not Supported\n");
342             break;
343         case 0x30: /* SELECT VERTICAL RESOULTION */
344             FIXME(int10, "Select Vertical Resoultion - Not Supported\n");
345             break;
346         case 0x31: /* ENABLE/DISABLE PALETTE LOADING */
347             FIXME(int10, "Palette Loading - Not Supported\n");
348             break;
349         case 0x32: /* ENABLE/DISABLE VIDEO ADDRERSSING */
350             FIXME(int10, "Video Addressing - Not Supported\n");
351             break;
352         case 0x33: /* ENABLE/DISABLE GRAY SCALE SUMMING */
353             FIXME(int10, "Gray Scale Summing - Not Supported\n");
354             break;
355         case 0x34: /* ENABLE/DISABLE CURSOR EMULATION */
356             FIXME(int10, "Cursor Emulation - Not Supported\n");
357             break;
358         case 0x36: /* VIDEO ADDRESS CONTROL */
359             FIXME(int10, "Video Address Control - Not Supported\n");
360             break;
361         default:
362             FIXME(int10, "INT 10 AH = 0x11 AL = 0x%x - Unknown\n", 
363                AL_reg(context));
364             break;
365         }
366         break;
367
368     case 0x13: /* WRITE STRING */
369         /* This one does not imply that string be at cursor. */
370         FIXME(int10, "Write String - Not Supported\n");
371         break;
372                              
373     case 0x1a: 
374         switch AL_reg(context) {
375         case 0x00: /* GET DISPLAY COMBINATION CODE */
376             TRACE(int10, "Get Display Combination Code\n");
377             /* Why are we saying this? */
378             /* Do we need to check if we are in a windows or text app? */
379             BX_reg(context) = 0x0008; /* VGA w/ color analog display */
380             break;
381         case 0x01: /* SET DISPLAY COMBINATION CODE */
382             FIXME(int10, "Set Display Combination Code - Not Supported\n");
383             break;
384         default:
385             FIXME(int10, "INT 10 AH = 0x1a AL = 0x%x - Unknown\n", 
386                AL_reg(context));
387             break;
388         }
389     break;
390
391     case 0x1b: /* FUNCTIONALITY/STATE INFORMATION */
392         FIXME(int10, "Get Functionality/State Information - Not Supported\n");
393         break;
394
395     case 0x1c: /* SAVE/RESTORE VIDEO STATE */
396         FIXME(int10, "Save/Restore Video State - Not Supported\n");
397         break;
398
399     default:
400         FIXME(int10, "Unknown - 0x%x\n", AH_reg(context));
401         INT_BARF( context, 0x10 );
402     }
403 }
404
405 static void write_char_attribute_at_cursor(char output, char page_num, 
406        char attribute, short times)
407 {
408     /* !NOTE!: */
409     /* It appears that the cursor should not be advanced if times > 1 */
410     /* I will triple check this later but bzork.exe definately points this */
411     /* way */
412     int wattribute, fg_color, bg_color;
413     char x, y;
414     int must_reset = 0;
415
416     if (page_num) /* Only support one text page right now */
417     {
418        FIXME(int10, "Cannot write to alternate page %d", page_num);
419        return;
420     }  
421
422     wattribute = conv_text_mode_attribute_attribute(attribute);
423     fg_color = conv_text_mode_attribute_fg_color(attribute);
424     bg_color = conv_text_mode_attribute_bg_color(attribute);
425
426     if (times > 1)
427     {
428        must_reset = 1;
429        CONSOLE_GetCursorPosition(&x, &y);
430     }
431
432     while (times)
433     {
434        CONSOLE_Write(output, fg_color, bg_color, attribute);           
435        times--;
436     }
437   
438     if (must_reset)
439        CONSOLE_MoveCursor(x, y);
440 }
441
442 static int conv_text_mode_attribute_fg_color(char attribute)
443 {
444     /* This is a local function to convert the color values 
445        in text-mode attributes to Wine's scheme */
446     
447     /* Foreground Color is stored in bits 3 through 0 */
448
449     /* Colors:
450           0000b   black          1000b   dark gray
451           0001b   blue           1001b   light blue
452           0010b   green          1010b   light green
453           0011b   cyan           1011b   light cyan
454           0100b   red            1100b   light red
455           0101b   magenta        1101b   light magenta
456           0110b   brown          1110b   yellow
457           0111b   light gray     1111b   white
458     */
459
460     /* FIXME - We need color values for those and some generic constants */
461
462     return 0; /* Bogus, temporary data. */
463 }
464
465 static int conv_text_mode_attribute_bg_color(char attribute)
466 {
467     /* This is a local function to convert the color values 
468        in text-mode attributes to Wine's scheme */
469     
470     /* Background Color is stored in bits 6 through 4 */
471     
472     /* Colors same as above, but only the left column */
473
474     /* FIXME - We need color values for those and some generic constants */
475
476     return 0; /* Bogus, temporary data. */
477 }
478
479 static int conv_text_mode_attribute_attribute(char attribute)
480 {
481     /* This is a local function to convert the attribute values 
482        in text-mode attributes to Wine's scheme */
483     
484     /* If this has bit 7 set, then we need to blink */
485
486     if (255 && attribute)
487     {
488         /* return TEXT_ATTRIBUTE_BLINK; */
489     }
490     
491     return 0; /* Bogus data */
492 }
493
494 static void scroll_window(int direction, char lines, char row1, 
495    char col1, char row2, char col2, char attribute)
496 {
497    int wattribute, bg_color;
498
499    wattribute = conv_text_mode_attribute_attribute(attribute);
500    bg_color = conv_text_mode_attribute_bg_color(attribute);
501
502    if (!lines) /* Actually, clear the window */
503    {
504       CONSOLE_ClearWindow(row1, col1, row2, col2, bg_color, wattribute);
505    }
506    else if (direction == SCROLL_UP)
507    {
508       CONSOLE_ScrollUpWindow(row1, col1, row2, col2, lines, bg_color,
509          wattribute);
510    }
511    else
512    {
513       CONSOLE_ScrollDownWindow(row1, col1, row2, col2, lines, bg_color,
514          wattribute);
515    }
516 }
517