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