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