fdopen: don't rewind the file after creating the FILE* handle. Added
[wine] / dlls / winedos / int10.c
1 /*
2  * BIOS interrupt 10h handler
3  *
4  * Copyright 1998 Ove Kåven
5  * Copyright 1998 Joseph Pranevich
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include "config.h"
23
24 #include <stdlib.h>
25
26 #include "miscemu.h"
27 #include "vga.h"
28 #include "wine/debug.h"
29 #include "dosexe.h"
30
31 WINE_DEFAULT_DEBUG_CHANNEL(int);
32
33 static void scroll_window(int direction, char lines, char row1,
34    char col1, char row2, char col2, char attribute);
35
36 #define SCROLL_UP 1
37 #define SCROLL_DOWN 2
38
39 static void BIOS_GetCursorPos(BIOSDATA*data,unsigned page,unsigned*X,unsigned*Y)
40 {
41   *X = data->VideoCursorPos[page*2];   /* column */
42   *Y = data->VideoCursorPos[page*2+1]; /* row */
43 }
44
45 static void BIOS_SetCursorPos(BIOSDATA*data,unsigned page,unsigned X,unsigned Y)
46 {
47   data->VideoCursorPos[page*2] = X;
48   data->VideoCursorPos[page*2+1] = Y;
49 }
50
51
52 /**********************************************************************
53  *         DOSVM_InitializeVideoMode
54  *
55  * The first time this function is called VGA emulation is set to the
56  * default text mode.
57  */
58 static void DOSVM_InitializeVideoMode( BIOSDATA *data )
59 {
60   static BOOL already_initialized = FALSE;
61   unsigned    width;
62   unsigned    height;
63
64   if(already_initialized)
65     return;
66   already_initialized = TRUE;
67
68   VGA_InitAlphaMode(&width, &height);
69
70   /*
71    * FIXME: Add more mappings between initial size and
72    *        text modes.
73    */
74   if (width >= 80 && height >= 25) {
75     VGA_SetAlphaMode(80, 25);
76     data->VideoColumns = 80;
77     data->VideoMode = 0x03;
78   } else {
79     VGA_SetAlphaMode(40, 25);
80     data->VideoColumns = 40;
81     data->VideoMode = 0x01;
82   }
83 }
84
85
86 /**********************************************************************
87  *          DOSVM_Int10Handler (WPROCS.116)
88  *          DOSVM_Int10Handler (WINEDOS16.116)
89  *
90  * Handler for int 10h (video).
91  *
92  * NOTE:
93  *    Most INT 10 functions for text-mode, CGA, EGA, and VGA cards
94  *    are present in this list. (SVGA and XGA are not) That is not
95  *    to say that all these functions should be supported, but if
96  *    anyone is brain-damaged enough to want to emulate one of these
97  *    beasts then this should get you started.
98  *
99  * NOTE:
100  *    Several common graphical extensions used by Microsoft hook
101  *    off of here. I have *not* added them to this list (yet). They
102  *    include:
103  *
104  *    MSHERC.COM - More functionality for Hercules cards.
105  *    EGA.SYS (also MOUSE.COM) - More for EGA cards.
106  *
107  *    Yes, MS also added this support into their mouse driver. Don't
108  *    ask me, I don't work for them.
109  *
110  * Joseph Pranevich - 9/98
111  *
112  *  Jess Haas 2/99
113  *      Added support for Vesa. It is not complete but is a start.
114  *      NOTE: Im not sure if i did all this right or if eny of it works.
115  *      Currently i dont have a program that uses Vesa that actually gets far
116  *      enough without crashing to do vesa stuff.
117  *
118  *      Added additional vga graphic support - 3/99
119  */
120
121 static void DOSVM_Int10Handler_VESA( CONTEXT86 *context )
122 {
123     BIOSDATA *data = BIOS_DATA;
124
125     switch(AL_reg(context)) {
126
127     case 0x00: /* GET SuperVGA INFORMATION */
128         TRACE("VESA GET SuperVGA INFORMATION\n");
129         memcpy(CTX_SEG_OFF_TO_LIN(context,context->SegEs,context->Edi),
130                &BIOS_EXTRA_PTR->vesa_info, sizeof(VESAINFO));
131         SET_AL( context, 0x4f );
132         SET_AH( context, 0x00 ); /* 0x00 = successful 0x01 = failed */
133         break;
134
135     case 0x01: /* GET SuperVGA MODE INFORMATION */
136         FIXME("VESA GET SuperVGA Mode Information - Not supported\n");
137         SET_AL( context, 0x4f );
138         SET_AH( context, 0x01 ); /* 0x00 = successful 0x01 = failed */
139         break;
140
141     case 0x02: /* SET SuperVGA VIDEO MODE */
142         switch(BX_reg(context)) {
143             /* OEM Video Modes */
144         case 0x00: /* 40x25 */
145         case 0x01:
146             TRACE("Set VESA Text Mode - 0x0%x\n",
147                   BX_reg(context));
148             VGA_SetAlphaMode(40, 25);
149             data->VideoColumns = 40;
150             break;
151         case 0x02:
152         case 0x03:
153         case 0x07:
154             TRACE("Set VESA Text Mode - 0x0%x\n",
155                   BX_reg(context));
156             VGA_SetAlphaMode(80, 25);
157             data->VideoColumns = 80;
158             break;
159         case 0x0D:
160             TRACE("Setting VESA 320x200 16-color mode\n");
161             VGA_SetMode(320,200,4);
162             break;
163         case 0x0E:
164             TRACE("Setting VESA 640x200 16-color mode\n");
165             VGA_SetMode(640,200,4);
166             break;
167         case 0x10:
168             TRACE("Setting VESA 640x350 16-color mode\n");
169             VGA_SetMode(640,350,4);
170             break;
171         case 0x12:
172             TRACE("Setting VESA 640x480 16-color mode\n");
173             VGA_SetMode(640,480,4);
174             break;
175         case 0x13:
176             TRACE("Setting VESA 320x200 256-color mode\n");
177             VGA_SetMode(320,200,8);
178             break;
179             /* VBE Modes */
180         case 0x100:
181             TRACE("Setting VESA 640x400 256-color mode\n");
182             VGA_SetMode(640,400,8);
183             break;
184         case 0x101:
185             TRACE("Setting VESA 640x480 256-color mode\n");
186             VGA_SetMode(640,480,8);
187             break;
188         case 0x102:
189             TRACE("Setting VESA 800x600 16-color mode\n");
190             VGA_SetMode(800,600,4);
191             break;
192         case 0x103:
193             TRACE("Setting VESA 800x600 256-color mode\n");
194             VGA_SetMode(800,600,8);
195             break;
196         case 0x104:
197             TRACE("Setting VESA 1024x768 16-color mode\n");
198             VGA_SetMode(1024,768,4);
199             break;
200         case 0x105:
201             TRACE("Setting VESA 1024x768 256-color mode\n");
202             VGA_SetMode(1024,768,8);
203             break;
204         case 0x106:
205             TRACE("Setting VESA 1280x1024 16-color mode\n");
206             VGA_SetMode(1280,1024,4);
207             break;
208         case 0x107:
209             TRACE("Setting VESA 1280x1024 256-color mode\n");
210             VGA_SetMode(1280,1024,8);
211             break;
212             /* 108h - 10Ch are text modes and im lazy so :p */
213             /* VBE v1.2+ */
214         case 0x10D:
215             TRACE("Setting VESA 320x200 15bpp\n");
216             VGA_SetMode(320,200,15);
217             break;
218         case 0x10E:
219             TRACE("Setting VESA 320x200 16bpp\n");
220             VGA_SetMode(320,200,16);
221             break;
222         case 0x10F:
223             TRACE("Setting VESA 320x200 24bpp\n");
224             VGA_SetMode(320,200,24);
225             break;
226         case 0x110:
227             TRACE("Setting VESA 640x480 15bpp\n");
228             VGA_SetMode(640,480,15);
229             break;
230         case 0x111:
231             TRACE("Setting VESA 640x480 16bpp\n");
232             VGA_SetMode(640,480,16);
233             break;
234         case 0x112:
235             TRACE("Setting VESA 640x480 24bpp\n");
236             VGA_SetMode(640,480,24);
237             break;
238         case 0x113:
239             TRACE("Setting VESA 800x600 15bpp\n");
240             VGA_SetMode(800,600,15);
241             break;
242         case 0x114:
243             TRACE("Setting VESA 800x600 16bpp\n");
244             VGA_SetMode(800,600,16);
245             break;
246         case 0x115:
247             TRACE("Setting VESA 800x600 24bpp\n");
248             VGA_SetMode(800,600,24);
249             break;
250         case 0x116:
251             TRACE("Setting VESA 1024x768 15bpp\n");
252             VGA_SetMode(1024,768,15);
253             break;
254         case 0x117:
255             TRACE("Setting VESA 1024x768 16bpp\n");
256             VGA_SetMode(1024,768,16);
257             break;
258         case 0x118:
259             TRACE("Setting VESA 1024x768 24bpp\n");
260             VGA_SetMode(1024,768,24);
261             break;
262         case 0x119:
263             TRACE("Setting VESA 1280x1024 15bpp\n");
264             VGA_SetMode(1280,1024,15);
265             break;
266         case 0x11A:
267             TRACE("Setting VESA 1280x1024 16bpp\n");
268             VGA_SetMode(1280,1024,16);
269             break;
270         case 0x11B:
271             TRACE("Setting VESA 1280x1024 24bpp\n");
272             VGA_SetMode(1280,1024,24);
273             break;
274         default:
275             FIXME("VESA Set Video Mode (0x%x) - Not Supported\n", BX_reg(context));
276         }
277         data->VideoMode = BX_reg(context);
278         SET_AL( context, 0x4f );
279         SET_AH( context, 0x00 );
280         break;
281
282     case 0x03: /* VESA SuperVGA BIOS - GET CURRENT VIDEO MODE */
283         SET_AL( context, 0x4f );
284         SET_AH( context, 0x00 ); /* should probly check if a vesa mode has ben set */
285         SET_BX( context, data->VideoMode );
286         break;
287
288     case 0x04: /* VESA SuperVGA BIOS - SAVE/RESTORE SuperVGA VIDEO STATE */
289         ERR("VESA SAVE/RESTORE Video State - Not Implemented\n");
290         /* AL_reg(context) = 0x4f; = supported so not set since not implemented */
291         /* maybe we should do this instead ? */
292         /* AH_reg(context = 0x01;  not implemented so just fail */
293         break;
294
295     case 0x05: /* VESA SuperVGA BIOS - CPU VIDEO MEMORY CONTROL */
296         /*
297          * This subfunction supports only Window A (BL_reg == 0) and
298          * is assumes that window granularity is 64k.
299          */
300         switch(BH_reg(context)) {
301         case 0x00: /* select video memory window */
302             SET_AL( context, 0x4f ); /* function supported */
303             if(BL_reg(context) == 0) {
304                 VGA_SetWindowStart(DX_reg(context) * 64 * 1024);
305                 SET_AH( context, 0x00 ); /* status: successful */
306             } else
307                 SET_AH( context, 0x01 ); /* status: failed */
308             break;
309         case 0x01: /* get video memory window */
310             SET_AL( context, 0x4f ); /* function supported */
311             if(BL_reg(context) == 0) {
312                 SET_DX( context, VGA_GetWindowStart() / 64 / 1024 );
313                 SET_AH( context, 0x00 ); /* status: successful */
314             } else
315                 SET_AH( context, 0x01 ); /* status: failed */
316             break;
317         default:
318             INT_BARF( context, 0x10 );
319         }
320         break;
321
322     case 0x06: /* VESA GET/SET LOGICAL SCAN LINE LENGTH */
323         ERR("VESA GET/SET LOGICAL SCAN LINE LENGTH - Not Implemented\n");
324         /* AL_reg(context) = 0x4f; = supported so not set since not implemented */
325         /* maybe we should do this instead ? */
326         /* AH_reg(context = 0x001; not implemented so just fail */
327         break;
328
329     case 0x07: /* GET/SET DISPLAY START */
330         ERR("VESA GET/SET DISPLAY START - Not Implemented\n");
331         /* AL_reg(context) = 0x4f; = supported so not set since not implemented */
332         /* maybe we should do this instead ? */
333         /* AH_reg(context = 0x001; not implemented so just fail */
334         break;
335
336     case 0x08: /* GET/SET DAC PALETTE CONTROL */
337         ERR("VESA GET/SET DAC PALETTE CONTROL- Not Implemented\n");
338         /* AL_reg(context) = 0x4f; = supported so not set since not implemented */
339         /* maybe we should do this instead ? */
340         /* AH_reg(context = 0x001; not implemented so just fail */
341         break;
342
343     case 0x09: /* SET PALETTE ENTRIES */
344         FIXME("VESA Set palette entries - not implemented\n");
345         break;
346
347     case 0x0a: /* GET PROTECTED-MODE CODE */
348         FIXME("VESA Get protected-mode code - not implemented\n");
349         break;
350
351     case 0x10: /* Display Power Management Extensions */
352         FIXME("VESA Display Power Management Extensions - not implemented\n");
353         break;
354
355     case 0xef:  /* get video mode for hercules-compatibles   */
356         /* There's no reason to really support this  */
357         /* is there?....................(A.C.)       */
358         TRACE("Just report the video not hercules compatible\n");
359         SET_DX( context, 0xffff );
360         break;
361
362     case 0xff: /* Turn VESA ON/OFF */
363         /* i dont know what to do */
364         break;
365
366     default:
367         FIXME("VESA Function (0x%x) - Not Supported\n", AH_reg(context));
368         break;
369     }
370 }
371
372 /**********************************************************************/
373
374 void WINAPI DOSVM_Int10Handler( CONTEXT86 *context )
375 {
376     BIOSDATA *data = BIOS_DATA;
377
378     DOSVM_InitializeVideoMode( data );
379
380     switch(AH_reg(context)) {
381
382     case 0x00: /* SET VIDEO MODE */
383         /* Text Modes: */
384         /* (mode) (text rows/cols)
385             0x00 - 40x25
386             0x01 - 40x25
387             0x02 - 80x25
388             0x03 - 80x25 or 80x43 or 80x50 (assume 80x25)
389             0x07 - 80x25
390         */
391
392         /* Bit 7 of AH = 0 -> Clean the video memory
393                          1 -> Don't clean it
394         */
395         if (!(AL_reg(context)&0x80)) {
396             /* FIXME: Do something which cleans the video memory */
397         }
398
399         /* FIXME: Should we keep the bit 7 in the Bios Data memory? */
400         context->Eax &= ~0x80;
401
402         switch (AL_reg(context)) {
403             case 0x00: /* 40x25 */
404             case 0x01:
405                 TRACE("Set Video Mode - Set to Text - 0x0%x\n",
406                    AL_reg(context));
407                 VGA_SetAlphaMode(40, 25);
408                 data->VideoColumns = 40;
409                 break;
410             case 0x02:
411             case 0x03:
412             case 0x07:
413                 TRACE("Set Video Mode - Set to Text - 0x0%x\n",
414                    AL_reg(context));
415                 VGA_SetAlphaMode(80, 25);
416                 data->VideoColumns = 80;
417                 break;
418             case 0x0D:
419                 TRACE("Setting VGA 320x200 16-color mode\n");
420                 VGA_SetMode(320,200,4);
421                 break;
422             case 0x0E:
423                 TRACE("Setting VGA 640x200 16-color mode\n");
424                 VGA_SetMode(640,200,4);
425                 break;
426             case 0x10:
427                 TRACE("Setting VGA 640x350 16-color mode\n");
428                 VGA_SetMode(640,350,4);
429                 break;
430             case 0x12:
431                 TRACE("Setting VGA 640x480 16-color mode\n");
432                 VGA_SetMode(640,480,4);
433                 break;
434             case 0x13:
435                 TRACE("Setting VGA 320x200 256-color mode\n");
436                 VGA_SetMode(320,200,8);
437                 break;
438             default:
439                 FIXME("Set Video Mode (0x%x) - Not Supported\n",
440                    AL_reg(context));
441         }
442         data->VideoMode = AL_reg(context);
443         break;
444
445     case 0x01: /* SET CURSOR SHAPE */
446         TRACE("Set Cursor Shape start %d end %d options %d\n",
447               CH_reg(context) & 0x1f,
448               CL_reg(context) & 0x1f,
449               CH_reg(context) & 0xe0);
450         data->VideoCursorType = CX_reg(context); /* direct copy */
451         VGA_SetCursorShape(CH_reg(context), CL_reg(context));
452         break;
453
454     case 0x02: /* SET CURSOR POSITION */
455         /* BH = Page Number */ /* Not supported */
456         /* DH = Row */ /* 0 is left */
457         /* DL = Column */ /* 0 is top */
458         BIOS_SetCursorPos(data,BH_reg(context),DL_reg(context),DH_reg(context));
459         if (BH_reg(context))
460         {
461            FIXME("Set Cursor Position: Cannot set to page %d\n",
462               BH_reg(context));
463         }
464         else
465         {
466            VGA_SetCursorPos(DL_reg(context), DH_reg(context));
467            TRACE("Set Cursor Position: %d/%d\n", DL_reg(context),
468               DH_reg(context));
469         }
470         break;
471
472     case 0x03: /* GET CURSOR POSITION AND SIZE */
473         {
474           unsigned row, col;
475
476           TRACE("Get cursor position and size (page %d)\n", BH_reg(context));
477           SET_CX( context, data->VideoCursorType );
478           BIOS_GetCursorPos(data,BH_reg(context),&col,&row);
479           SET_DH( context, row );
480           SET_DL( context, col );
481           TRACE("Cursor Position: %d/%d\n", DL_reg(context), DH_reg(context));
482         }
483         break;
484
485     case 0x04: /* READ LIGHT PEN POSITION */
486         FIXME("Read Light Pen Position - Not Supported\n");
487         SET_AH( context, 0x00 ); /* Not down */
488         break;
489
490     case 0x05: /* SELECT ACTIVE DISPLAY PAGE */
491         FIXME("Select Active Display Page (%d) - Not Supported\n", AL_reg(context));
492         data->VideoCurPage = AL_reg(context);
493         break;
494
495     case 0x06: /* SCROLL UP WINDOW */
496         /* AL = Lines to scroll */
497         /* BH = Attribute */
498         /* CH,CL = row, col upper-left */
499         /* DH,DL = row, col lower-right */
500         scroll_window(SCROLL_UP, AL_reg(context), CH_reg(context),
501            CL_reg(context), DH_reg(context), DL_reg(context),
502            BH_reg(context));
503         TRACE("Scroll Up Window %d\n", AL_reg(context));
504         break;
505
506     case 0x07: /* SCROLL DOWN WINDOW */
507         /* AL = Lines to scroll */
508         /* BH = Attribute */
509         /* CH,CL = row, col upper-left */
510         /* DH,DL = row, col lower-right */
511         scroll_window(SCROLL_DOWN, AL_reg(context), CH_reg(context),
512            CL_reg(context), DH_reg(context), DL_reg(context),
513            BH_reg(context));
514         TRACE("Scroll Down Window %d\n", AL_reg(context));
515         break;
516
517     case 0x08: /* READ CHARACTER AND ATTRIBUTE AT CURSOR POSITION */
518         {
519             if (BH_reg(context)) /* Write to different page */
520             {
521                 FIXME("Read character and attribute at cursor position -"
522                       " Can't read from non-0 page\n");
523                 SET_AL( context, ' ' ); /* That page is blank */
524                 SET_AH( context, 7 );
525             }
526             else
527            {
528                 BYTE ascii, attr;
529                 TRACE("Read Character and Attribute at Cursor Position\n");
530                 VGA_GetCharacterAtCursor(&ascii, &attr);
531                 SET_AL( context, ascii );
532                 SET_AH( context, attr );
533             }
534         }
535         break;
536
537     case 0x09: /* WRITE CHARACTER AND ATTRIBUTE AT CURSOR POSITION */
538     case 0x0a: /* WRITE CHARACTER ONLY AT CURSOR POSITION */
539        /* AL = Character to display. */
540        /* BH = Page Number */ /* We can't write to non-0 pages, yet. */
541        /* BL = Attribute / Color */
542        /* CX = Times to Write Char */
543        /* Note here that the cursor is not advanced. */
544        {
545            unsigned row, col;
546
547            BIOS_GetCursorPos(data,BH_reg(context),&col,&row);
548            VGA_WriteChars(col, row,
549                           AL_reg(context),
550                           (AH_reg(context) == 0x09) ? BL_reg(context) : -1,
551                           CX_reg(context));
552            if (CX_reg(context) > 1)
553               TRACE("Write Character%s at Cursor Position (Rep. %d): %c\n",
554                     (AH_reg(context) == 0x09) ? " and Attribute" : "",
555                  CX_reg(context), AL_reg(context));
556            else
557               TRACE("Write Character%s at Cursor Position: %c\n",
558                     (AH_reg(context) == 0x09) ? " and Attribute" : "",
559                 AL_reg(context));
560        }
561        break;
562
563     case 0x0b:
564         switch BH_reg(context) {
565         case 0x00: /* SET BACKGROUND/BORDER COLOR */
566             /* In text modes, this sets only the border... */
567             /* According to the interrupt list and one of my books. */
568             /* Funny though that Beyond Zork seems to indicate that it
569                also sets up the default background attributes for clears
570                and scrolls... */
571             /* Bear in mind here that we do not want to change,
572                apparently, the foreground or attribute of the background
573                with this call, so we should check first to see what the
574                foreground already is... FIXME */
575             FIXME("Set Background/Border Color: %d/%d\n",
576                BH_reg(context), BL_reg(context));
577             break;
578         case 0x01: /* SET PALETTE */
579             FIXME("Set Palette - Not Supported\n");
580             break;
581         default:
582             FIXME("INT 10 AH = 0x0b BH = 0x%x - Unknown\n",
583                BH_reg(context));
584             break;
585         }
586         break;
587
588     case 0x0c: /* WRITE GRAPHICS PIXEL */
589         /* Not in graphics mode, can ignore w/o error */
590         FIXME("Write Graphics Pixel - Not Supported\n");
591         break;
592
593     case 0x0d: /* READ GRAPHICS PIXEL */
594         /* Not in graphics mode, can ignore w/o error */
595         FIXME("Read Graphics Pixel - Not Supported\n");
596         break;
597
598     case 0x0e: /* TELETYPE OUTPUT */
599         TRACE("Teletype Output\n");
600         DOSVM_PutChar(AL_reg(context));
601         break;
602
603     case 0x0f: /* GET CURRENT VIDEO MODE */
604         TRACE("Get current video mode: -> mode %d, columns %d\n", data->VideoMode, data->VideoColumns);
605         /* Note: This should not be a constant value. */
606         SET_AL( context, data->VideoMode );
607         SET_AH( context, data->VideoColumns );
608         SET_BH( context, 0 ); /* Display page 0 */
609         break;
610
611     case 0x10:
612         switch AL_reg(context) {
613         case 0x00: /* SET SINGLE PALETTE REGISTER - A.C. */
614             TRACE("Set Single Palette Register - Reg 0x0%x Value 0x0%x\n",
615                 BL_reg(context),BH_reg(context));
616                 /* BH is the value  BL is the register */
617                 VGA_SetColor16((int)BL_reg(context),(int)BH_reg(context));
618             break;
619         case 0x01: /* SET BORDER (OVERSCAN) */
620             /* Text terminals have no overscan */
621             /* I'm setting it anyway. - A.C.   */
622             TRACE("Set Border (Overscan) - Ignored but set.\n");
623             VGA_SetColor16(16,(int)BH_reg(context));
624             break;
625         case 0x02: /* SET ALL PALETTE REGISTERS - A.C.*/
626             TRACE("Set all palette registers\n");
627                 /* ES:DX points to a 17 byte table of colors */
628                 /* No return data listed */
629                 /* I'll have to update my table and the default palette */
630                VGA_Set16Palette(CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edx));
631             break;
632         case 0x03: /* TOGGLE INTENSITY/BLINKING BIT */
633             FIXME("Toggle Intensity/Blinking Bit - Not Supported\n");
634             break;
635         case 0x07: /* GET INDIVIDUAL PALETTE REGISTER  - A.C.*/
636             TRACE("Get Individual Palette Register 0x0%x\n",BL_reg(context));
637                 /* BL is register to read [ 0-15 ] BH is return value */
638                 SET_BH( context, VGA_GetColor16((int)BL_reg(context)) );
639             break;
640         case 0x08: /* READ OVERSCAN (BORDER COLOR) REGISTER  - A.C. */
641             TRACE("Read Overscan (Border Color) Register \n");
642                 SET_BH( context, VGA_GetColor16(16) );
643             break;
644         case 0x09: /* READ ALL PALETTE REGISTERS AND OVERSCAN REGISTER - A.C.*/
645             TRACE("Read All Palette Registers and Overscan Register \n");
646                 /* ES:DX points to a 17 byte table where the results */
647                 /*  of this call should be stored.                   */
648                VGA_Get16Palette(CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edx));
649             break;
650         case 0x10: /* SET INDIVIDUAL DAC REGISTER */
651             {
652                 PALETTEENTRY paldat;
653
654                 TRACE("Set Individual DAC register\n");
655                 paldat.peRed   = DH_reg(context);
656                 paldat.peGreen = CH_reg(context);
657                 paldat.peBlue  = CL_reg(context);
658                 paldat.peFlags = 0;
659                 VGA_SetPalette(&paldat,BX_reg(context)&0xFF,1);
660             }
661             break;
662         case 0x12: /* SET BLOCK OF DAC REGISTERS */
663             {
664                 int i;
665                 PALETTEENTRY paldat;
666                 BYTE *pt;
667
668                 TRACE("Set Block of DAC registers\n");
669                 pt = (BYTE*)CTX_SEG_OFF_TO_LIN(context,context->SegEs,context->Edx);
670                 for (i=0;i<CX_reg(context);i++)
671                 {
672                     paldat.peRed   = (*(pt+i*3+0)) << 2;
673                     paldat.peGreen = (*(pt+i*3+1)) << 2;
674                     paldat.peBlue  = (*(pt+i*3+2)) << 2;
675                     paldat.peFlags = 0;
676                     VGA_SetPalette(&paldat,(BX_reg(context)+i)&0xFF,1);
677                 }
678             }
679             break;
680         case 0x13: /* SELECT VIDEO DAC COLOR PAGE */
681             FIXME("Select video DAC color page - Not Supported\n");
682             break;
683         case 0x15: /* READ INDIVIDUAL DAC REGISTER */
684             FIXME("Read individual DAC register - Not Supported\n");
685             break;
686         case 0x17: /* READ BLOCK OF DAC REGISTERS */
687             FIXME("Read block of DAC registers - Not Supported\n");
688             break;
689         case 0x18: /* SET PEL MASK */
690             FIXME("Set PEL mask - Not Supported\n");
691             break;
692         case 0x19: /* READ PEL MASK */
693             FIXME("Read PEL mask - Not Supported\n");
694             break;
695         case 0x1a: /* GET VIDEO DAC COLOR PAGE STATE */
696             FIXME("Get video DAC color page state - Not Supported\n");
697             break;
698         case 0x1b: /* PERFORM GRAY-SCALE SUMMING */
699             FIXME("Perform Gray-scale summing - Not Supported\n");
700             break;
701         default:
702             FIXME("INT 10 AH = 0x10 AL = 0x%x - Unknown\n",
703                AL_reg(context));
704             break;
705         }
706         break;
707
708     case 0x11: /* TEXT MODE CHARGEN */
709         /* Note that second subfunction is *almost* identical. */
710         /* See INTERRUPT.A for details. */
711         switch AL_reg(context) {
712         case 0x00: /* LOAD USER SPECIFIED PATTERNS */
713         case 0x10:
714             FIXME("Load User Specified Patterns - Not Supported\n");
715             break;
716         case 0x01: /* LOAD ROM MONOCHROME PATTERNS */
717         case 0x11:
718             FIXME("Load ROM Monochrome Patterns - Not Supported\n");
719             break;
720         case 0x02: /* LOAD ROM 8x8 DOUBLE-DOT PATTERNS */
721         case 0x12:
722             FIXME(
723                 "Load ROM 8x8 Double Dot Patterns - Not Supported\n");
724             break;
725         case 0x03: /* SET BLOCK SPECIFIER */
726             FIXME("Set Block Specifier - Not Supported\n");
727             break;
728         case 0x04: /* LOAD ROM 8x16 CHARACTER SET */
729         case 0x14:
730             FIXME("Load ROM 8x16 Character Set - Not Supported\n");
731             break;
732         case 0x20: /* SET USER 8x16 GRAPHICS CHARS */
733             FIXME("Set User 8x16 Graphics Chars - Not Supported\n");
734             break;
735         case 0x21: /* SET USER GRAPICS CHARACTERS */
736             FIXME("Set User Graphics Characters - Not Supported\n");
737             break;
738         case 0x22: /* SET ROM 8x14 GRAPHICS CHARS */
739             FIXME("Set ROM 8x14 Graphics Chars - Not Supported\n");
740             break;
741         case 0x23: /* SET ROM 8x8 DBL DOT CHARS */
742             FIXME(
743                 "Set ROM 8x8 Dbl Dot Chars (Graphics) - Not Supported\n");
744             break;
745         case 0x24: /* LOAD 8x16 GRAPHIC CHARS */
746             FIXME("Load 8x16 Graphic Chars - Not Supported\n");
747             break;
748         case 0x30: /* GET FONT INFORMATION */
749             FIXME("Get Font Information - Not Supported\n");
750             break;
751         default:
752             FIXME("INT 10 AH = 0x11 AL = 0x%x - Unknown\n",
753                AL_reg(context));
754             break;
755         }
756         break;
757
758     case 0x12: /* ALTERNATE FUNCTION SELECT */
759         switch BL_reg(context) {
760         case 0x10: /* GET EGA INFO */
761             TRACE("EGA info requested\n");
762             SET_BH( context, 0x00 );   /* Color screen */
763             SET_BL( context, data->ModeOptions >> 5 ); /* EGA memory size */
764             SET_CX( context, data->FeatureBitsSwitches );
765             break;
766         case 0x20: /* ALTERNATE PRTSC */
767             FIXME("Install Alternate Print Screen - Not Supported\n");
768             break;
769         case 0x30: /* SELECT VERTICAL RESOULTION */
770             FIXME("Select vertical resolution - not supported\n");
771             break;
772         case 0x31: /* ENABLE/DISABLE DEFAULT PALETTE LOADING */
773             FIXME("Default palette loading - not supported\n");
774             data->VGASettings =
775                 (data->VGASettings & 0xf7) |
776                 ((AL_reg(context) == 1) << 3);
777             break;
778         case 0x32: /* ENABLE/DISABLE VIDEO ADDRERSSING */
779             FIXME("Video Addressing - Not Supported\n");
780             break;
781         case 0x33: /* ENABLE/DISABLE GRAY SCALE SUMMING */
782             FIXME("Gray Scale Summing - Not Supported\n");
783             break;
784         case 0x34: /* ENABLE/DISABLE CURSOR EMULATION */
785             TRACE("Set cursor emulation to %d\n", AL_reg(context));
786             data->ModeOptions =
787                 (data->ModeOptions & 0xfe)|(AL_reg(context) == 1);
788             break;
789         case 0x36: /* VIDEO ADDRESS CONTROL */
790             FIXME("Video Address Control - Not Supported\n");
791             break;
792         default:
793             FIXME("INT 10 AH = 0x11 AL = 0x%x - Unknown\n",
794                AL_reg(context));
795             break;
796         }
797         break;
798
799     case 0x13: /* WRITE STRING */
800         /* This one does not imply that string be at cursor. */
801         FIXME("Write String - Not Supported\n");
802         break;
803
804     case 0x1a:
805         switch AL_reg(context) {
806         case 0x00: /* GET DISPLAY COMBINATION CODE */
807             TRACE("Get Display Combination Code\n");
808             SET_AX( context, 0x001a );
809             SET_BL( context, 0x08 ); /* VGA w/ color analog display */
810             SET_BH( context, 0x00 ); /* No secondary hardware */
811             break;
812         case 0x01: /* SET DISPLAY COMBINATION CODE */
813             FIXME("Set Display Combination Code - Not Supported\n");
814             break;
815         default:
816             FIXME("INT 10 AH = 0x1a AL = 0x%x - Unknown\n",
817                AL_reg(context));
818             break;
819         }
820     break;
821
822     case 0x1b: /* FUNCTIONALITY/STATE INFORMATION */
823         TRACE("Get functionality/state information\n");
824         if (BX_reg(context) == 0x0)
825         {
826           SET_AL( context, 0x1b );
827           /* Copy state information structure to ES:DI */
828           memcpy(CTX_SEG_OFF_TO_LIN(context,context->SegEs,context->Edi),
829                  &BIOS_EXTRA_PTR->vid_state,sizeof(VIDEOSTATE));
830         }
831         break;
832
833     case 0x1c: /* SAVE/RESTORE VIDEO STATE */
834         FIXME("Save/Restore Video State - Not Supported\n");
835         break;
836
837         case 0xef:  /* get video mode for hercules-compatibles   */
838                     /* There's no reason to really support this  */
839                     /* is there?....................(A.C.)       */
840                 TRACE("Just report the video not hercules compatible\n");
841                 SET_DX( context, 0xffff );
842                 break;
843
844     case 0x4f: /* VESA */
845         DOSVM_Int10Handler_VESA(context);
846         break;
847
848     default:
849         FIXME("Unknown - 0x%x\n", AH_reg(context));
850         INT_BARF( context, 0x10 );
851     }
852 }
853
854 static void scroll_window(int direction, char lines, char row1,
855    char col1, char row2, char col2, char attribute)
856 {
857    if (!lines) /* Actually, clear the window */
858    {
859        VGA_ClearText(row1, col1, row2, col2, attribute);
860    }
861    else if (direction == SCROLL_UP)
862    {
863        VGA_ScrollUpText(row1, col1, row2, col2, lines, attribute);
864    }
865    else
866    {
867        VGA_ScrollDownText(row1, col1, row2, col2, lines, attribute);
868    }
869 }
870
871 /**********************************************************************
872  *         DOSVM_PutChar
873  *
874  * Write single character to VGA console at the current 
875  * cursor position and updates the BIOS cursor position.
876  */
877 void WINAPI DOSVM_PutChar( BYTE ascii )
878 {
879   BIOSDATA *data = BIOS_DATA;
880   unsigned  xpos, ypos;
881
882   TRACE("char: 0x%02x(%c)\n", ascii, ascii);
883
884   DOSVM_InitializeVideoMode( data );
885
886   VGA_PutChar( ascii );
887   VGA_GetCursorPos( &xpos, &ypos );
888   BIOS_SetCursorPos( data, 0, xpos, ypos );
889 }