int10.c 50.2 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2
/*
 * BIOS interrupt 10h handler
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * Copyright 1998 Ove Kven
 * Copyright 1998 Joseph Pranevich
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Alexandre Julliard's avatar
Alexandre Julliard committed
20 21
 */

22 23
#include "config.h"

Alexandre Julliard's avatar
Alexandre Julliard committed
24
#include <stdlib.h>
25

Alexandre Julliard's avatar
Alexandre Julliard committed
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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
/*
 * Display combination code for active display.
 *
 * Values (hex):
 * 00 - no display
 * 01 - monochrome adapter w/ monochrome display
 * 02 - CGA w/ color display
 * 03 - reserved
 * 04 - EGA w/ color display
 * 05 - EGA w/ monochrome display
 * 06 - PGA w/ color display
 * 07 - VGA w/ monochrome analog display
 * 08 - VGA w/ color analog display
 * 09 - reserved
 * 0A - MCGA w/ digital color display
 * 0B - MCGA w/ monochrome analog display
 * 0C - MCGA w/ color analog display
 * FF - unknown display type
 */
#define INT10_DCC 0x08

#include "pshpack1.h"

/*
 * Structure for DOS data that can be accessed directly from applications.
 * This structure must be correctly packed.
 */
typedef struct _INT10_HEAP {
    BYTE  StaticModeSupport[7];     /* modes supported 1..7 */
    BYTE  StaticScanlineSupport;    /* scan lines supported */
    BYTE  StaticNumberCharBlocks;   /* total number of char blocks */
    BYTE  StaticActiveCharBlocks;   /* max number of active char blocks */
    WORD  StaticMiscFlags;          /* misc function support flags */
    WORD  StaticReserved1;          /* reserved */
    BYTE  StaticSavePointerFlags;   /* save pointer function flags */
    BYTE  StaticReserved2;          /* reserved */

    WORD  VesaCurrentMode;
    WORD  VesaModeList[64];
    char  VesaOEMName[32];
    char  VesaProductName[32];
    char  VesaProductRev[32];
    char  VesaVendorName[32];

    WORD  WineHeapSegment;
} INT10_HEAP;

80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
/*
 * Structure for VBE Mode Info Block. See the VBE 3.0 standard for details.
 * This structure must be correctly packed.
 */
struct _ModeInfoBlock {
    WORD  ModeAttributes;       /* 0x00 */
    BYTE  WinAAttributes;       /* 0x02 */
    BYTE  WinBAttributes;       /* 0x03 */
    WORD  WinGranularity;       /* 0x04 */
    WORD  WinSize;              /* 0x06 */
    WORD  WinASegment;          /* 0x08 */
    WORD  WinBSegment;          /* 0x0A */
    DWORD WinFuncPtr;           /* 0x0C */
    WORD  BytesPerScanLine;     /* 0x10 */
    /* mandatory for VBE 1.2+ */
    WORD  XResolution;          /* 0x12 */
    WORD  YResolution;          /* 0x14 */
    BYTE  XCharSize;            /* 0x16 */
    BYTE  YCharSize;            /* 0x17 */
    BYTE  NumberOfPlanes;       /* 0x18 */
    BYTE  BitsPerPixel;         /* 0x19 */
    BYTE  NumberOfBanks;        /* 0x1A */
    BYTE  MemoryModel;          /* 0x1B */
    BYTE  BankSize;             /* 0x1C */
    BYTE  NumberOfImagePages;   /* 0x1D */
    BYTE  Reserved1;            /* 0x1E */
    BYTE  RedMaskSize;          /* 0x1F */
    BYTE  RedFieldPosition;     /* 0x20 */
    BYTE  GreenMaskSize;        /* 0x21 */
    BYTE  GreenFieldPosition;   /* 0x22 */
    BYTE  BlueMaskSize;         /* 0x23 */
    BYTE  BlueFieldPosition;    /* 0x24 */
    BYTE  RsvdMaskSize;         /* 0x25 */
    BYTE  RsvdFieldPosition;    /* 0x26 */
    BYTE  DirectColorModeInfo;  /* 0x27 */
    /* mandatory for VBE 2.0+ */
    DWORD PhysBasePtr;          /* 0x28 */
    DWORD Reserved2;            /* 0x2C */
    WORD  Reserved3;            /* 0x30 */
    /* mandatory for VBE 3.0+ */
    WORD  LinBytesPerScanLine;  /* 0x32 */
    BYTE  BnkNumberOfImagePages;/* 0x34 */
    BYTE  LinNumberOfImagePages;/* 0x35 */
    BYTE  LinRedMaskSize;       /* 0x36 */
    BYTE  LinRedFieldPosition;  /* 0x37 */
    BYTE  LinGreenMaskSize;     /* 0x38 */
    BYTE  LinGreenFieldPosition;/* 0x39 */
    BYTE  LinBlueMaskSize;      /* 0x3A */
    BYTE  LinBlueFieldPosition; /* 0x3B */
    BYTE  LinRsvdMaskSize;      /* 0x3C */
    BYTE  LinRsvdFieldPosition; /* 0x3D */
    DWORD MaxPixelClock;        /* 0x3E */
    BYTE  Reserved4[190];       /* 0x42 */
};

135
#include "poppack.h"
136

137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
/*
 * Wine internal information about video modes.
 * If depth is zero, the mode is considered to
 * be a text mode.
 */
typedef struct {
    WORD Mode;
    WORD Width;
    WORD Height;
    WORD Depth;
} INT10_MODE;


/*
 * List of supported video modes.
 */
static const INT10_MODE INT10_modelist[] =
{
    {0x0000,   40,   25,  0},
    {0x0001,   40,   25,  0},
    {0x0002,   80,   25,  0},
    {0x0003,   80,   25,  0},
    {0x0007,   80,   25,  0},
    {0x000d,  320,  200,  4},
    {0x000e,  640,  200,  4},
    {0x0010,  640,  350,  4},
    {0x0012,  640,  480,  4},
    {0x0013,  320,  200,  8},
165
    {0x006a,  800,  600,  4},   /* VESA mode, same as 0x102 */
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
    {0x0100,  640,  400,  8},
    {0x0101,  640,  480,  8},
    {0x0102,  800,  600,  4},
    {0x0103,  800,  600,  8},
    {0x0104, 1024,  768,  4},
    {0x0105, 1024,  768,  8},
    {0x0106, 1280, 1024,  4},
    {0x0107, 1280, 1024,  8},
    {0x0108,   80,   60,  0},
    {0x0109,  132,   25,  0},
    {0x010a,  132,   43,  0},
    {0x010b,  132,   50,  0},
    {0x010c,  132,   60,  0},
    {0x010d,  320,  200, 15},
    {0x010e,  320,  200, 16},
    {0x010f,  320,  200, 24},
    {0x0110,  640,  480, 15},
    {0x0111,  640,  480, 16},
    {0x0112,  640,  480, 24},
    {0x0113,  800,  600, 15},
    {0x0114,  800,  600, 16},
    {0x0115,  800,  600, 24},
    {0x0116, 1024,  768, 15},
    {0x0117, 1024,  768, 16},
    {0x0118, 1024,  768, 24},
    {0x0119, 1280, 1024, 15},
    {0x011a, 1280, 1024, 16},
    {0x011b, 1280, 1024, 24},
    {0xffff,    0,    0,  0}
};

197 198 199 200 201
/* True if video mode is a vesa mode, false otherwise.
 * More correct would be to use something like (x > 0xff || x == 0x6a)
 * but as long as we have only the standard VGA and VESA modes this is ok too */
#define IS_VESA_MODE(x)         ((x) >= 0x6a)

202 203
/* Forward declarations. */
static INT10_HEAP *INT10_GetHeap(void);
204 205
static void INT10_SetCursorPos(BIOSDATA*, unsigned, unsigned, unsigned);

206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229

/**********************************************************************
 *         INT10_FindMode
 */
static const INT10_MODE *INT10_FindMode( WORD mode )
{
    const INT10_MODE *ptr = INT10_modelist;
    
    /*
     * Filter out flags.
     */
    mode &= 0x17f;

    while (ptr->Mode != 0xffff)
    {
        if (ptr->Mode == mode)
            return ptr;
        ptr++;
    }

    return NULL;
}


230 231 232 233 234 235 236 237
/**********************************************************************
 *         INT10_FillControllerInformation
 *
 * Fill 256-byte (VBE1.x) or 512-byte buffer (VBE2.0+) with
 * capabilities of the video controller.
 */
static void INT10_FillControllerInformation( BYTE *buffer )
{
238 239 240 241 242 243 244 245 246 247 248 249 250
    INT10_HEAP *heap = INT10_GetHeap();

    /* 00 - BYTE[4]: signature */
    memmove( buffer, "VESA", 4 );

    /* 04 - WORD: version number */
    *(WORD*)(buffer + 4) = 0x0300; /* version 3.0 */
    
    /* 06 - DWORD: pointer to OEM name */
    *(SEGPTR*)(buffer + 6) = MAKESEGPTR( heap->WineHeapSegment,
                                         offsetof(INT10_HEAP,
                                                  VesaOEMName) );

251
    /*
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
     * 10 - DWORD: capabilities flags 
     * Bits:
     *    0 - DAC can be switched into 8-bit mode
     *    1 - non-VGA controller
     *    2 - programmed DAC with blank bit
     *    3 - controller supports hardware stereoscopic signalling
     *    4 - =0 stereo signalling via external VESA stereo connector
     *        =1 stereo signalling via VESA EVC connector
     *    5 - controller supports hardware mouse cursor
     *    6 - controller supports hardware clipping
     *    7 - controller supports transparent BitBLT
     * 8-31 - reserved (0)
     */
    *(DWORD*)(buffer + 10) = 0; /* FIXME */
    
    /* 14 - DWORD: pointer to list of supported VESA and OEM video modes */
    *(SEGPTR*)(buffer + 14) = MAKESEGPTR( heap->WineHeapSegment,
                                          offsetof(INT10_HEAP,
                                                   VesaModeList) );

    /* 18 - WORD: total amount of video memory in 64K blocks */
    *(WORD*)(buffer + 18) = 16; /* FIXME */

    /* 20 - WORD: OEM software version (BCD, high byte = major) */
    *(WORD*)(buffer + 20) = 0x0100; /* version 1.0 */

    /* 22 - DWORD: pointer to vendor name */
    *(SEGPTR*)(buffer + 22) = MAKESEGPTR( heap->WineHeapSegment,
                                          offsetof(INT10_HEAP,
                                                   VesaVendorName) );

    /* 26 - DWORD: pointer to product name */
    *(SEGPTR*)(buffer + 26) = MAKESEGPTR( heap->WineHeapSegment,
                                          offsetof(INT10_HEAP,
                                                   VesaProductName) );

    /* 30 - DWORD: pointer to product revision string */
    *(SEGPTR*)(buffer + 30) = MAKESEGPTR( heap->WineHeapSegment,
                                          offsetof(INT10_HEAP,
                                                   VesaProductRev) );

    /* 34 - WORD: VBE/AF version (if capabilities bit 3 set) */
    *(WORD*)(buffer + 34) = 0;

    /*
     * 36 - DWORD: pointer to list of accelerated modes 
     *             (if capabilities bit 3 set) 
     */
    *(SEGPTR*)(buffer + 36) = 0;

    /* 40 - BYTE[216]: reserved for VBE implementation, set to zero */
    memset( buffer + 40, 216, 0 );

    /* 
     * 256 - BYTE[256]: reserved for VBE3.0 implementation, 
     *                  ignored in order to support older programs
308 309 310 311 312 313 314 315 316 317 318 319
     */
}


/**********************************************************************
 *         INT10_FillModeInformation
 *
 * Fill 256-byte buffer with extended information about display mode.
 *
 * Returns FALSE if mode is unknown and TRUE is mode is known
 * even if it is not supported.
 */
320
static BOOL INT10_FillModeInformation( struct _ModeInfoBlock *mib, WORD mode )
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
{
    const INT10_MODE *ptr = INT10_FindMode( mode );
    if (!ptr)
        return FALSE;

    /*
     * 00 - WORD: mode attributes
     * Bits:
     *     0 - Mode supported by present hardware configuration.
     *     1 - Optional information available. Must be =1 for VBE v1.2+.
     *     2 - BIOS output supported.
     *         Int10 functions 01, 02, 06, 07, 09, 0a and 0e are supported.
     *     3 - Set if color, clear if monochrome.
     *     4 - Set if graphics mode, clear if text mode.
     *     5 - Mode is not VGA-compatible if set.
     *         VGA-compatible modes support standard VGA I/O ports.
     *     6 - Bank-switched (or windowed) mode is not supported if set.
     *     7 - Linear framebuffer mode supported.
     *     8 - Double scanning supported.
     *     9 - Interlaced operation supported.
     *    10 - Triple buffering supported.
     *    11 - Stereoscopic display supported.
     *    12 - Dual display start address supported.
     * 13-15 - Reserved.
     */
    {
        WORD attr = 0x000a; /* color mode, optional info */

        /*
         * FIXME: Attribute handling is incomplete.
         */

        /* Mode supported? FIXME: correct value */
        attr |= 0x0001;

        /* Graphical mode? */
        if (ptr->Depth) 
            attr |= 0x0010;

        /* Not VGA-compatible? */
361
        if (IS_VESA_MODE(mode))
362 363
            attr |= 0x0020;

364
        mib->ModeAttributes = attr;
365 366 367 368 369 370 371 372 373 374
    }

    /*
     * 02 - BYTE[2]: window attributes, window A and window B
     * Bits:
     *   0 - Window exists.
     *   1 - Window is readable.
     *   2 - Window is writable.
     * 3-7 - Reserved.
     */
375 376
    mib->WinAAttributes = 0x07; /* window A exists, readable and writable */
    mib->WinBAttributes = 0x00; /* window B not supported */
377 378

    /* 04 - WORD: window granularity in KB */
379
    mib->WinGranularity = 64;
380 381

    /* 06 - WORD: window size in KB */
382
    mib->WinSize = 64;
383 384

    /* 08 - WORD[2]: start segments, window A and window B */
385 386
    mib->WinASegment = 0xa000; /* window A segment */
    mib->WinBSegment = 0x0000; /* window B not supported */
387 388

    /* 12 - DWORD: window positioning function */
389
    mib->WinFuncPtr = 0; /* not supported */
390 391
    
    /* 16 - WORD: bytes per scan line */
392
    /* FIXME: is this always correct? */
393
    mib->BytesPerScanLine = ptr->Width * (ptr->Depth ? (ptr->Depth + 7) / 8 : 1);
394 395

    /* 18 - WORD: width in pixels (graphics) or characters (text) */
396
    mib->XResolution = ptr->Width;
397 398

    /* 20 - WORD: height in pixels (graphics) or characters (text) */
399
    mib->YResolution = ptr->Height;
400 401

    /* 22 - BYTE: width of character cell in pixels */
402
    mib->XCharSize = 0; /* FIXME */
403 404

    /* 23 - BYTE: height of character cell in pixels */
405
    mib->YCharSize = 0; /* FIXME */
406 407

    /* 24 - BYTE: number of memory planes */
408
    mib->NumberOfPlanes = 1; /* FIXME */
409 410

    /* 25 - BYTE: number of bits per pixel */
411
    mib->BitsPerPixel = ptr->Depth; /* FIXME: text modes? reserved bits? */
412 413

    /* 26 - BYTE: number of banks */
414
    mib->NumberOfBanks = 1; /* FIXME */
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430

    /*
     * 27 - BYTE: memory model type
     * Values (hex):
     *    00 - Text mode
     *    01 - CGA graphics
     *    02 - Hercules graphics
     *    03 - Planar
     *    04 - Packed pixel
     *    05 - Non-chain 4, 256 color
     *    06 - Direct color
     *    07 - YUV
     * 08-0F - Reserved for VESA.
     * 10-FF - OEM memory models.
     */
    if (!ptr->Depth)
431
        mib->MemoryModel = 0; /* text mode */
432
    else
433
        mib->MemoryModel = 3; /* FIXME */
434 435

    /* 28 - BYTE: size of bank in KB */
436
    mib->BankSize = 0; /* FIXME */
437 438

    /* 29 - BYTE: number of image pages (less one) in video RAM */
439
    mib->NumberOfImagePages = 0; /* FIXME */
440 441

    /* 30 - BYTE: reserved (0x00 for VBE 1.0-2.0, 0x01 for VBE 3.0) */
442
    mib->Reserved1 = 0x01;
443 444

    /* 
445 446 447 448 449 450 451 452 453
     * 31,33,35 - BYTE: red/green/blue mask size 
     * Size of red/green/blue color component in bits.
     * 32,34,36 - BYTE: red/green/blue field position 
     * Bit position of the least significant bit of red/green/blue color
     * component.
     * Both should be only used when memory model is direct color or YUV but
     * "Imperium Romanum" uses this fields even when memory model is planar.
     * So always fill this fields when we have a depth bigger then 8, otherwise
     * set them to zero.
454
     */
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496
    switch (ptr->Depth) {
        case 24:
            mib->RedMaskSize = 8;
            mib->GreenMaskSize = 8;
            mib->BlueMaskSize = 8;
            mib->RsvdMaskSize = 0;
            mib->RedFieldPosition = 16;
            mib->GreenFieldPosition = 8;
            mib->BlueFieldPosition = 0;
            mib->RsvdFieldPosition = 0;
            break;
        case 16:
            mib->RedMaskSize = 5;
            mib->GreenMaskSize = 6;
            mib->BlueMaskSize = 5;
            mib->RsvdMaskSize = 0;
            mib->RedFieldPosition = 11;
            mib->GreenFieldPosition = 5;
            mib->BlueFieldPosition = 0;
            mib->RsvdFieldPosition = 0;
            break;
        case 15:
            mib->RedMaskSize = 5;
            mib->GreenMaskSize = 5;
            mib->BlueMaskSize = 5;
            mib->RsvdMaskSize = 1;
            mib->RedFieldPosition = 10;
            mib->GreenFieldPosition = 5;
            mib->BlueFieldPosition = 0;
            mib->RsvdFieldPosition = 15;
            break;
        default:
            mib->RedMaskSize = 0;
            mib->GreenMaskSize = 0;
            mib->BlueMaskSize = 0;
            mib->RsvdMaskSize = 0;
            mib->RedFieldPosition = 0;
            mib->GreenFieldPosition = 0;
            mib->BlueFieldPosition = 0;
            mib->RsvdFieldPosition = 0;
            break;
    }
497 498 499 500 501 502 503

    /*
     * 39 - BYTE: direct color mode info 
     * Bits:
     * 0 - Set if color ramp is programmable.
     * 1 - Set if bytes in reserved field may be used by application.
     */
504
    mib->DirectColorModeInfo = 0; /* not supported */
505 506

    /* 40 - DWORD: physical address of linear video buffer */
507
    mib->PhysBasePtr = 0; /* not supported */
508 509

    /* 44 - DWORD: reserved, always zero */
510
    mib->Reserved2 = 0;
511 512

    /* 48 - WORD: reserved, always zero */
513
    mib->Reserved3 = 0;
514 515

    /* 50 - WORD: bytes per scan line in linear modes */
516
    mib->LinBytesPerScanLine = mib->BytesPerScanLine;
517 518

    /* 52 - BYTE: number of images (less one) for banked video modes */
519
    mib->BnkNumberOfImagePages = 0; /* FIXME */
520 521

    /* 53 - BYTE: number of images (less one) for linear video modes */
522
    mib->LinNumberOfImagePages = mib->BnkNumberOfImagePages;
523 524

    /* 54 - BYTE: red mask size (linear modes) */
525
    mib->LinRedMaskSize = mib->RedMaskSize;
526 527

    /* 55 - BYTE: red field position (linear modes) */
528
    mib->LinRedFieldPosition = mib->RedFieldPosition;
529 530

    /* 56 - BYTE: green mask size (linear modes) */
531
    mib->LinGreenMaskSize = mib->GreenMaskSize;
532 533

    /* 57 - BYTE: green field size (linear modes) */
534
    mib->LinGreenFieldPosition = mib->GreenFieldPosition;
535 536

    /* 58 - BYTE: blue mask size (linear modes) */
537
    mib->LinBlueMaskSize = mib->BlueMaskSize;
538 539

    /* 59 - BYTE: blue field position (linear modes) */
540
    mib->LinBlueFieldPosition = mib->BlueFieldPosition;
541 542

    /* 60 - BYTE: reserved mask size (linear modes) */
543
    mib->LinRsvdMaskSize = mib->RsvdMaskSize;
544 545

    /* 61 - BYTE: reserved mask position (linear modes) */
546
    mib->LinRsvdFieldPosition = mib->RsvdFieldPosition;
547 548

    /* 62 - DWORD: maximum pixel clock for graphics video mode, in Hz */
549
    mib->MaxPixelClock = 0; /* FIXME */
550

551
    /* 66 - BYTE[190]: reserved, set to zero */
552
    memset( &mib->Reserved4, 190, 0 );
553

554 555 556 557 558 559 560 561 562 563 564
    return TRUE;
}


/**********************************************************************
 *         INT10_FillStateInformation
 *
 * Fill 64-byte buffer with VGA state and functionality information.
 */
static void INT10_FillStateInformation( BYTE *buffer, BIOSDATA *data )
{
565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
    INT10_HEAP *heap = INT10_GetHeap();

    /* 00 - DWORD: address of static functionality table */
    *(SEGPTR*)(buffer + 0) = MAKESEGPTR( heap->WineHeapSegment,
                                         offsetof(INT10_HEAP, 
                                                  StaticModeSupport) );

    /* 04 - BYTE[30]: copy of BIOS data starting from 0x49 (VideoMode) */
    memmove( buffer + 4, &data->VideoMode, 30 );

    /* 34 - BYTE: number of rows - 1 */
    buffer[34] = data->RowsOnScreenMinus1;

    /* 35 - WORD: bytes/character */
    *(WORD*)(buffer + 35) = data->BytesPerChar;

    /* 37 - BYTE: display combination code of active display */
    buffer[37] = INT10_DCC;

    /* 38 - BYTE: DCC of alternate display */
    buffer[38] = 0; /* no secondary display */

    /* 39 - WORD: number of colors supported in current mode (0000h = mono) */
    *(WORD*)(buffer + 39) = 16; /* FIXME */

    /* 41 - BYTE: number of pages supported in current mode */
    buffer[41] = 1; /* FIXME */

593
    /*
594 595 596 597 598 599
     * 42 - BYTE: number of scan lines active
     * Values (hex):
     * 00 = 200
     * 01 = 350
     * 02 = 400
     * 03 = 480
600
     */
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693
    buffer[42] = 3; /* FIXME */

    /* 43 - BYTE: primary character block */
    buffer[43] = 0; /* FIXME */

    /* 44 - BYTE: secondary character block */
    buffer[44] = 0; /* FIXME */

    /*
     * 45 - BYTE: miscellaneous flags
     * Bits:
     * 0 - all modes on all displays on
     * 1 - gray summing on
     * 2 - monochrome display attached
     * 3 - default palette loading disabled
     * 4 - cursor emulation enabled
     * 5 - 0 = intensity; 1 = blinking
     * 6 - flat-panel display is active
     * 7 - unused (0)
     */
    /* FIXME: Correct value? */
    buffer[45] =
        (data->VGASettings & 0x0f) |
        ((data->ModeOptions & 1) << 4); /* cursor emulation */

    /*
     * 46 - BYTE: non-VGA mode support 
     * Bits:
     *   0 - BIOS supports information return for adapter interface
     *   1 - adapter interface driver required
     *   2 - 16-bit VGA graphics present
     *   3 - =1 MFI attributes enabled
     *       =0 VGA attributes enabled
     *   4 - 132-column mode supported
     * 5-7 - reserved
     */
     buffer[46] = 0; /* FIXME: correct value? */

     /* 47 - BYTE[2]: reserved, set to zero */
     memset( buffer + 47, 2, 0 );

     /*
      * 49 - BYTE: video memory available
      * Values (hex):
      * 00 - 64K
      * 01 - 128K
      * 02 - 192K
      * 03 - 256K
      */
     buffer[49] = (data->ModeOptions & 0x60) >> 5; /* FIXME */

     /*
      * 50 - BYTE: save pointer state flags
      * Bits:
      *   0 - 512 character set active
      *   1 - dynamic save area present
      *   2 - alpha font override active
      *   3 - graphics font override active
      *   4 - palette override active
      *   5 - DCC override active
      * 6-7 - unused (0)
      */
     buffer[50] = heap->StaticSavePointerFlags;

     /*
      * 51 - BYTE: display information and status 
      * Bits:
      *   0 - flat-panel display attached
      *   1 - flat-panel display active
      *   2 - color display
      * 3-6 - reserved
      *   7 - 640x480 flat-panel can be used simultaneously with CRT
      */
     buffer[51] = 4; /* FIXME: correct value? */

     /* 52 - BYTE[12]: reserved, set to zero */
     memset( buffer + 52, 12, 0 );
}


/**********************************************************************
 *         INT10_GetHeap
 */
INT10_HEAP *INT10_GetHeap( void )
{
    static INT10_HEAP *heap_pointer = 0;

    if (!heap_pointer)
    {
        WORD segment;
        int  i;

        heap_pointer = DOSVM_AllocDataUMB( sizeof(INT10_HEAP), 
694 695
                                           &segment,
                                           0 );
696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724

        for (i = 0; i < 7; i++)
            heap_pointer->StaticModeSupport[i] = 0xff; /* FIXME */

        heap_pointer->StaticScanlineSupport = 7;  /* FIXME */
        heap_pointer->StaticNumberCharBlocks = 0; /* FIXME */
        heap_pointer->StaticActiveCharBlocks = 0; /* FIXME */
        heap_pointer->StaticMiscFlags = 0x8ff;    /* FIXME */
        heap_pointer->StaticReserved1 = 0;
        heap_pointer->StaticSavePointerFlags = 0x3f; /* FIXME */
        heap_pointer->StaticReserved2 = 0;

        for (i=0; TRUE; i++)
        {
            heap_pointer->VesaModeList[i] = INT10_modelist[i].Mode;
            if (INT10_modelist[i].Mode == 0xffff)
                break;
        }

        strcpy( heap_pointer->VesaOEMName, "WINE SVGA BOARD" );
        strcpy( heap_pointer->VesaVendorName, "WINE" );
        strcpy( heap_pointer->VesaProductName, "WINE SVGA" );
        strcpy( heap_pointer->VesaProductRev, "2003" );
        
        heap_pointer->VesaCurrentMode = 0; /* Initialized later. */
        heap_pointer->WineHeapSegment = segment;
    }

    return heap_pointer;
725 726 727
}


728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753
/**********************************************************************
 *         INT10_SetVideoMode
 *
 * Change current video mode to any VGA or VESA mode.
 * Returns TRUE if mode is supported.
 *
 * Mode bitfields:
 * 0-6: .. Mode number (combined with bit 8).
 *   7: =0 Clear screen.
 *      =1 Preserve display memory on mode change (VGA modes).
 *   8: =0 VGA mode.
 *      =1 VESA mode.
 *   9: .. Reserved, must be zero.
 *  10: .. Reserved, must be zero.
 *  11: =0 Use default refresh rate.
 *      =1 Use user specified refresh rate.
 *  12: .. Reserved, must be zero.
 *  13: .. Reserved, must be zero.
 *  14: =0 Use windowed frame buffer model.
 *      =1 Use linear frame buffer model.
 *  15: =0 Clear screen.
 *      =1 Preserve display memory on mode change (VESA modes).
 */
static BOOL INT10_SetVideoMode( BIOSDATA *data, WORD mode )
{
    const INT10_MODE *ptr = INT10_FindMode( mode );
754
    INT10_HEAP *heap = INT10_GetHeap();
755
    BOOL clearScreen = TRUE;
756 757 758 759 760 761 762 763 764 765

    if (!ptr)
        return FALSE;

    /*
     * Linear framebuffer is not supported.
     */
    if (mode & 0x4000)
        return FALSE;

766 767 768 769 770 771
    /*
     * Check for VGA and VESA preserve video memory flag.
     */
    if ((mode & 0x0080) || (mode & 0x8000))
        clearScreen = FALSE;

772 773 774
    /*
     * Note that we do not mask out flags here on purpose.
     */
775
    heap->VesaCurrentMode = mode;
776 777 778 779 780 781 782 783
    if (mode <= 0xff)
        data->VideoMode = mode;
    else
        data->VideoMode = 0;

    if (ptr->Depth == 0)
    {
        /* Text mode. */
784
        TRACE( "Setting %s %dx%d text mode (screen %s)\n", 
785
               IS_VESA_MODE(mode) ? "VESA" : "VGA", 
786 787 788
               ptr->Width, ptr->Height, 
               clearScreen ? "cleared" : "preserved" );

789 790 791 792
        /*
         * FIXME: We should check here if alpha mode could be set.
         */
        VGA_SetAlphaMode( ptr->Width, ptr->Height );
793

794
        data->VideoColumns = ptr->Width;
795 796 797 798 799 800 801 802
        data->RowsOnScreenMinus1 = ptr->Height - 1;

        if (clearScreen)
        {            
            VGA_ClearText( 0, 0, ptr->Height-1, ptr->Width-1, 0x07 );
            INT10_SetCursorPos( data, 0, 0, 0 );
            VGA_SetCursorPos( 0, 0 );            
        }
803 804 805 806
    }
    else
    {
        /* Graphics mode. */
807
        TRACE( "Setting %s %dx%dx%d graphics mode (screen %s)\n", 
808
               IS_VESA_MODE(mode) ? "VESA" : "VGA", 
809 810 811
               ptr->Width, ptr->Height, ptr->Depth,
               clearScreen ? "cleared" : "preserved" );

812 813 814 815 816 817 818 819
        if (VGA_SetMode( ptr->Width, ptr->Height, ptr->Depth ))
            return FALSE;
    }

    return TRUE;
}


820 821 822 823
/**********************************************************************
 *         INT10_GetCursorPos
 */
static void INT10_GetCursorPos(BIOSDATA*data,unsigned page,unsigned*X,unsigned*Y)
824
{
825 826
    *X = data->VideoCursorPos[page*2];   /* column */
    *Y = data->VideoCursorPos[page*2+1]; /* row */
827 828
}

829 830 831 832 833

/**********************************************************************
 *         INT10_SetCursorPos
 */
static void INT10_SetCursorPos(BIOSDATA*data,unsigned page,unsigned X,unsigned Y)
834
{
835 836
    data->VideoCursorPos[page*2] = X;
    data->VideoCursorPos[page*2+1] = Y;
837 838
}

839 840

/**********************************************************************
841
 *         INT10_InitializeVideoMode
842 843 844 845
 *
 * The first time this function is called VGA emulation is set to the
 * default text mode.
 */
846
static void INT10_InitializeVideoMode( BIOSDATA *data )
847 848 849 850 851 852 853 854 855 856 857 858 859 860 861
{
  static BOOL already_initialized = FALSE;
  unsigned    width;
  unsigned    height;

  if(already_initialized)
    return;
  already_initialized = TRUE;

  VGA_InitAlphaMode(&width, &height);

  /*
   * FIXME: Add more mappings between initial size and
   *        text modes.
   */
862 863 864 865
  if (width >= 80 && height >= 25)
      INT10_SetVideoMode( data, 0x03 );
  else
      INT10_SetVideoMode( data, 0x01 );
866 867 868
}


Alexandre Julliard's avatar
Alexandre Julliard committed
869
/**********************************************************************
870
 *          INT10_HandleVESA
871
 *
872
 * Handler for VESA functions (int10 function 0x4f).
873
 */
874
static void INT10_HandleVESA( CONTEXT86 *context )
Alexandre Julliard's avatar
Alexandre Julliard committed
875
{
876
    BIOSDATA *data = DOSVM_BiosData();
877

878 879
    switch(AL_reg(context)) {

880 881 882 883 884 885 886 887 888 889
    case 0x00: /* RETURN CONTROLLER INFORMATION */
        TRACE( "VESA RETURN CONTROLLER INFORMATION\n" );
        {
            BYTE *ptr = CTX_SEG_OFF_TO_LIN(context,
                                           context->SegEs, 
                                           context->Edi);
            INT10_FillControllerInformation( ptr );
            SET_AL( context, 0x4f );
            SET_AH( context, 0x00 ); /* 0x00 = successful 0x01 = failed */
        }
890 891
        break;

892 893 894
    case 0x01: /* RETURN MODE INFORMATION */
        TRACE( "VESA RETURN MODE INFORMATION %04x\n", CX_reg(context) );
        {
895 896 897
            struct _ModeInfoBlock *ptr = CTX_SEG_OFF_TO_LIN(context,
                                                            context->SegEs, 
                                                            context->Edi);
898 899 900 901 902 903
            SET_AL( context, 0x4f );
            if (INT10_FillModeInformation( ptr, CX_reg(context) ))
                SET_AH( context, 0x00 ); /* status: success */
            else
                SET_AH( context, 0x01 ); /* status: failed */
        }
904 905 906
        break;

    case 0x02: /* SET SuperVGA VIDEO MODE */
907 908 909 910 911 912
        TRACE( "Set VESA video mode %04x\n", BX_reg(context) );
        SET_AL( context, 0x4f ); /* function supported */
        if (INT10_SetVideoMode( data, BX_reg(context) ))
            SET_AH( context, 0x00 ); /* success */
        else
            SET_AH( context, 0x01 ); /* failed */
913 914 915
        break;

    case 0x03: /* VESA SuperVGA BIOS - GET CURRENT VIDEO MODE */
916
        SET_AL( context, 0x4f );
917 918
        SET_AH( context, 0x00 );
        SET_BX( context, INT10_GetHeap()->VesaCurrentMode );
919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934
        break;

    case 0x04: /* VESA SuperVGA BIOS - SAVE/RESTORE SuperVGA VIDEO STATE */
        ERR("VESA SAVE/RESTORE Video State - Not Implemented\n");
        /* AL_reg(context) = 0x4f; = supported so not set since not implemented */
        /* maybe we should do this instead ? */
        /* AH_reg(context = 0x01;  not implemented so just fail */
        break;

    case 0x05: /* VESA SuperVGA BIOS - CPU VIDEO MEMORY CONTROL */
        /*
         * This subfunction supports only Window A (BL_reg == 0) and
         * is assumes that window granularity is 64k.
         */
        switch(BH_reg(context)) {
        case 0x00: /* select video memory window */
935
            SET_AL( context, 0x4f ); /* function supported */
936 937
            if(BL_reg(context) == 0) {
                VGA_SetWindowStart(DX_reg(context) * 64 * 1024);
938
                SET_AH( context, 0x00 ); /* status: successful */
939
            } else
940
                SET_AH( context, 0x01 ); /* status: failed */
941 942
            break;
        case 0x01: /* get video memory window */
943
            SET_AL( context, 0x4f ); /* function supported */
944
            if(BL_reg(context) == 0) {
945 946
                SET_DX( context, VGA_GetWindowStart() / 64 / 1024 );
                SET_AH( context, 0x00 ); /* status: successful */
947
            } else
948
                SET_AH( context, 0x01 ); /* status: failed */
949
            break;
950
	default:
951
            INT_BARF( context, 0x10 );
952
	}
953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991
        break;

    case 0x06: /* VESA GET/SET LOGICAL SCAN LINE LENGTH */
        ERR("VESA GET/SET LOGICAL SCAN LINE LENGTH - Not Implemented\n");
        /* AL_reg(context) = 0x4f; = supported so not set since not implemented */
        /* maybe we should do this instead ? */
        /* AH_reg(context = 0x001; not implemented so just fail */
        break;

    case 0x07: /* GET/SET DISPLAY START */
        ERR("VESA GET/SET DISPLAY START - Not Implemented\n");
        /* AL_reg(context) = 0x4f; = supported so not set since not implemented */
        /* maybe we should do this instead ? */
        /* AH_reg(context = 0x001; not implemented so just fail */
        break;

    case 0x08: /* GET/SET DAC PALETTE CONTROL */
        ERR("VESA GET/SET DAC PALETTE CONTROL- Not Implemented\n");
        /* AL_reg(context) = 0x4f; = supported so not set since not implemented */
        /* maybe we should do this instead ? */
        /* AH_reg(context = 0x001; not implemented so just fail */
        break;

    case 0x09: /* SET PALETTE ENTRIES */
        FIXME("VESA Set palette entries - not implemented\n");
        break;

    case 0x0a: /* GET PROTECTED-MODE CODE */
        FIXME("VESA Get protected-mode code - not implemented\n");
        break;

    case 0x10: /* Display Power Management Extensions */
        FIXME("VESA Display Power Management Extensions - not implemented\n");
        break;

    case 0xef:  /* get video mode for hercules-compatibles   */
        /* There's no reason to really support this  */
        /* is there?....................(A.C.)       */
        TRACE("Just report the video not hercules compatible\n");
992
        SET_DX( context, 0xffff );
993 994 995
        break;

    case 0xff: /* Turn VESA ON/OFF */
996
        /* I don't know what to do */
997 998 999 1000 1001
        break;

    default:
        FIXME("VESA Function (0x%x) - Not Supported\n", AH_reg(context));
        break;
1002
    }
1003 1004
}

1005

1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032
/**********************************************************************
 *	    DOSVM_Int10Handler
 *
 * Handler for int 10h (video).
 *
 * NOTE:
 *    Most INT 10 functions for text-mode, CGA, EGA, and VGA cards
 *    are present in this list. (SVGA and XGA are not) That is not
 *    to say that all these functions should be supported, but if
 *    anyone is brain-damaged enough to want to emulate one of these
 *    beasts then this should get you started.
 *
 * NOTE:
 *    Several common graphical extensions used by Microsoft hook
 *    off of here. I have *not* added them to this list (yet). They
 *    include:
 *
 *    MSHERC.COM - More functionality for Hercules cards.
 *    EGA.SYS (also MOUSE.COM) - More for EGA cards.
 *
 *    Yes, MS also added this support into their mouse driver. Don't
 *    ask me, I don't work for them.
 *
 * Joseph Pranevich - 9/98
 *
 *  Jess Haas 2/99
 *	Added support for Vesa. It is not complete but is a start.
1033 1034
 *	NOTE: Im not sure if I did all this right or if any of it works.
 *	Currently I don't have a program that uses Vesa that actually gets far
1035 1036 1037 1038
 *	enough without crashing to do vesa stuff.
 *
 *      Added additional vga graphic support - 3/99
 */
1039 1040
void WINAPI DOSVM_Int10Handler( CONTEXT86 *context )
{
1041
    BIOSDATA *data = DOSVM_BiosData();
1042

1043
    INT10_InitializeVideoMode( data );
1044

1045
    switch(AH_reg(context)) {
Alexandre Julliard's avatar
Alexandre Julliard committed
1046

1047
    case 0x00: /* SET VIDEO MODE */
1048 1049
        TRACE( "Set VGA video mode %02x\n", AL_reg(context) );
        if (!INT10_SetVideoMode( data, AL_reg(context) ))
1050
            FIXME( "Unsupported VGA video mode requested: %#x\n", 
1051
                   AL_reg(context) );
Alexandre Julliard's avatar
Alexandre Julliard committed
1052 1053 1054
        break;

    case 0x01: /* SET CURSOR SHAPE */
1055 1056 1057 1058
        TRACE("Set Cursor Shape start %d end %d options %d\n",
              CH_reg(context) & 0x1f,
              CL_reg(context) & 0x1f,
              CH_reg(context) & 0xe0);
1059 1060
        data->VideoCursorType = CX_reg(context); /* direct copy */
	VGA_SetCursorShape(CH_reg(context), CL_reg(context));
Alexandre Julliard's avatar
Alexandre Julliard committed
1061
        break;
1062

Alexandre Julliard's avatar
Alexandre Julliard committed
1063
    case 0x02: /* SET CURSOR POSITION */
1064 1065 1066
        /* BH = Page Number */ /* Not supported */
        /* DH = Row */ /* 0 is left */
        /* DL = Column */ /* 0 is top */
1067
        INT10_SetCursorPos(data,BH_reg(context),DL_reg(context),DH_reg(context));
1068 1069
        if (BH_reg(context))
        {
1070
           FIXME("Set Cursor Position: Cannot set to page %d\n",
1071 1072 1073 1074
              BH_reg(context));
        }
        else
        {
1075
           VGA_SetCursorPos(DL_reg(context), DH_reg(context));
Andreas Mohr's avatar
Andreas Mohr committed
1076 1077
           TRACE("Set Cursor Position: %d/%d\n", DL_reg(context),
              DH_reg(context));
1078
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
1079 1080 1081
        break;

    case 0x03: /* GET CURSOR POSITION AND SIZE */
1082
        {
1083
          unsigned row, col;
1084

1085
          TRACE("Get cursor position and size (page %d)\n", BH_reg(context));
1086
          SET_CX( context, data->VideoCursorType );
1087
          INT10_GetCursorPos(data,BH_reg(context),&col,&row);
1088 1089
          SET_DH( context, row );
          SET_DL( context, col );
Andreas Mohr's avatar
Andreas Mohr committed
1090
          TRACE("Cursor Position: %d/%d\n", DL_reg(context), DH_reg(context));
1091
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
1092
        break;
Alexandre Julliard's avatar
Alexandre Julliard committed
1093

Alexandre Julliard's avatar
Alexandre Julliard committed
1094
    case 0x04: /* READ LIGHT PEN POSITION */
1095
        FIXME("Read Light Pen Position - Not Supported\n");
1096
        SET_AH( context, 0x00 ); /* Not down */
Alexandre Julliard's avatar
Alexandre Julliard committed
1097 1098 1099
        break;

    case 0x05: /* SELECT ACTIVE DISPLAY PAGE */
Andreas Mohr's avatar
Andreas Mohr committed
1100
        FIXME("Select Active Display Page (%d) - Not Supported\n", AL_reg(context));
1101
        data->VideoCurPage = AL_reg(context);
Alexandre Julliard's avatar
Alexandre Julliard committed
1102 1103 1104
        break;

    case 0x06: /* SCROLL UP WINDOW */
1105 1106 1107 1108
        /* AL = Lines to scroll */
        /* BH = Attribute */
        /* CH,CL = row, col upper-left */
        /* DH,DL = row, col lower-right */
1109
        TRACE("Scroll Up Window %d\n", AL_reg(context));
1110 1111 1112 1113 1114 1115 1116 1117 1118

        if (AL_reg(context) == 0)
            VGA_ClearText( CH_reg(context), CL_reg(context),
                           DH_reg(context), DL_reg(context),
                           BH_reg(context) );
        else
            VGA_ScrollUpText( CH_reg(context), CL_reg(context),
                              DH_reg(context), DL_reg(context),
                              AL_reg(context), BH_reg(context) );
Alexandre Julliard's avatar
Alexandre Julliard committed
1119 1120 1121
        break;

    case 0x07: /* SCROLL DOWN WINDOW */
1122 1123 1124 1125
        /* AL = Lines to scroll */
        /* BH = Attribute */
        /* CH,CL = row, col upper-left */
        /* DH,DL = row, col lower-right */
1126
        TRACE("Scroll Down Window %d\n", AL_reg(context));
1127 1128 1129 1130 1131 1132 1133 1134 1135

        if (AL_reg(context) == 0)
            VGA_ClearText( CH_reg(context), CL_reg(context),
                           DH_reg(context), DL_reg(context),
                           BH_reg(context) );
        else
            VGA_ScrollDownText( CH_reg(context), CL_reg(context),
                                DH_reg(context), DL_reg(context),
                                AL_reg(context), BH_reg(context) );
Alexandre Julliard's avatar
Alexandre Julliard committed
1136 1137 1138
        break;

    case 0x08: /* READ CHARACTER AND ATTRIBUTE AT CURSOR POSITION */
1139
        {
1140 1141
            if (BH_reg(context)) /* Write to different page */
            {
1142
                FIXME("Read character and attribute at cursor position -"
1143
                      " Can't read from non-0 page\n");
1144 1145
                SET_AL( context, ' ' ); /* That page is blank */
                SET_AH( context, 7 );
1146 1147
            }
            else
1148
           {
1149
                BYTE ascii, attr;
1150
                TRACE("Read Character and Attribute at Cursor Position\n");
1151
                VGA_GetCharacterAtCursor(&ascii, &attr);
1152 1153
                SET_AL( context, ascii );
                SET_AH( context, attr );
1154
            }
1155
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
1156 1157 1158
        break;

    case 0x09: /* WRITE CHARACTER AND ATTRIBUTE AT CURSOR POSITION */
1159
    case 0x0a: /* WRITE CHARACTER ONLY AT CURSOR POSITION */
1160 1161 1162 1163
       /* AL = Character to display. */
       /* BH = Page Number */ /* We can't write to non-0 pages, yet. */
       /* BL = Attribute / Color */
       /* CX = Times to Write Char */
1164
       /* Note here that the cursor is not advanced. */
1165 1166 1167
       {
           unsigned row, col;

1168
           INT10_GetCursorPos(data,BH_reg(context),&col,&row);
1169 1170 1171 1172 1173
           VGA_WriteChars(col, row,
                          AL_reg(context),
                          (AH_reg(context) == 0x09) ? BL_reg(context) : -1,
                          CX_reg(context));
           if (CX_reg(context) > 1)
1174 1175
              TRACE("Write Character%s at Cursor Position (Rep. %d): %c\n",
                    (AH_reg(context) == 0x09) ? " and Attribute" : "",
1176 1177
                 CX_reg(context), AL_reg(context));
           else
1178 1179
              TRACE("Write Character%s at Cursor Position: %c\n",
                    (AH_reg(context) == 0x09) ? " and Attribute" : "",
1180 1181
                AL_reg(context));
       }
1182
       break;
Alexandre Julliard's avatar
Alexandre Julliard committed
1183

1184
    case 0x0b:
Alexandre Julliard's avatar
Alexandre Julliard committed
1185 1186
        switch BH_reg(context) {
        case 0x00: /* SET BACKGROUND/BORDER COLOR */
1187 1188
            /* In text modes, this sets only the border... */
            /* According to the interrupt list and one of my books. */
1189
            /* Funny though that Beyond Zork seems to indicate that it
1190 1191 1192
               also sets up the default background attributes for clears
               and scrolls... */
            /* Bear in mind here that we do not want to change,
Andreas Mohr's avatar
Andreas Mohr committed
1193
               apparently, the foreground or attribute of the background
1194 1195
               with this call, so we should check first to see what the
               foreground already is... FIXME */
Andreas Mohr's avatar
Andreas Mohr committed
1196 1197
            FIXME("Set Background/Border Color: %d/%d\n",
               BH_reg(context), BL_reg(context));
Alexandre Julliard's avatar
Alexandre Julliard committed
1198 1199
            break;
        case 0x01: /* SET PALETTE */
1200
            FIXME("Set Palette - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1201 1202
            break;
        default:
1203
            FIXME("INT 10 AH = 0x0b BH = 0x%x - Unknown\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
1204 1205 1206 1207 1208 1209 1210
               BH_reg(context));
            break;
        }
        break;

    case 0x0c: /* WRITE GRAPHICS PIXEL */
        /* Not in graphics mode, can ignore w/o error */
1211
        FIXME("Write Graphics Pixel - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1212
        break;
1213

Alexandre Julliard's avatar
Alexandre Julliard committed
1214 1215
    case 0x0d: /* READ GRAPHICS PIXEL */
        /* Not in graphics mode, can ignore w/o error */
1216
        FIXME("Read Graphics Pixel - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1217
        break;
1218

Alexandre Julliard's avatar
Alexandre Julliard committed
1219
    case 0x0e: /* TELETYPE OUTPUT */
1220
        TRACE("Teletype Output\n");
1221
        DOSVM_PutChar(AL_reg(context));
Alexandre Julliard's avatar
Alexandre Julliard committed
1222 1223 1224
        break;

    case 0x0f: /* GET CURRENT VIDEO MODE */
Andreas Mohr's avatar
Andreas Mohr committed
1225
        TRACE("Get current video mode: -> mode %d, columns %d\n", data->VideoMode, data->VideoColumns);
1226
        /* Note: This should not be a constant value. */
1227 1228 1229
        SET_AL( context, data->VideoMode );
        SET_AH( context, data->VideoColumns );
        SET_BH( context, 0 ); /* Display page 0 */
Alexandre Julliard's avatar
Alexandre Julliard committed
1230 1231
        break;

1232
    case 0x10:
Alexandre Julliard's avatar
Alexandre Julliard committed
1233
        switch AL_reg(context) {
1234 1235 1236
        case 0x00: /* SET SINGLE PALETTE REGISTER - A.C. */
            TRACE("Set Single Palette Register - Reg 0x0%x Value 0x0%x\n",
		BL_reg(context),BH_reg(context));
1237 1238
		/* BH is the value  BL is the register */
		VGA_SetColor16((int)BL_reg(context),(int)BH_reg(context));
Alexandre Julliard's avatar
Alexandre Julliard committed
1239 1240
            break;
        case 0x01: /* SET BORDER (OVERSCAN) */
1241
            /* Text terminals have no overscan */
1242
	    /* I'm setting it anyway. - A.C.   */
1243 1244
            TRACE("Set Border (Overscan) - Ignored but set.\n");
	    VGA_SetColor16(16,(int)BH_reg(context));
Alexandre Julliard's avatar
Alexandre Julliard committed
1245
            break;
1246 1247 1248
        case 0x02: /* SET ALL PALETTE REGISTERS - A.C.*/
            TRACE("Set all palette registers\n");
		/* ES:DX points to a 17 byte table of colors */
1249 1250
		/* No return data listed */
		/* I'll have to update my table and the default palette */
1251
               VGA_Set16Palette(CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edx));
Alexandre Julliard's avatar
Alexandre Julliard committed
1252 1253
            break;
        case 0x03: /* TOGGLE INTENSITY/BLINKING BIT */
1254
            FIXME("Toggle Intensity/Blinking Bit - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1255
            break;
1256 1257
        case 0x07: /* GET INDIVIDUAL PALETTE REGISTER  - A.C.*/
            TRACE("Get Individual Palette Register 0x0%x\n",BL_reg(context));
1258
		/* BL is register to read [ 0-15 ] BH is return value */
1259
	        SET_BH( context, VGA_GetColor16((int)BL_reg(context)) );
Alexandre Julliard's avatar
Alexandre Julliard committed
1260
            break;
1261 1262
        case 0x08: /* READ OVERSCAN (BORDER COLOR) REGISTER  - A.C. */
            TRACE("Read Overscan (Border Color) Register \n");
1263
	        SET_BH( context, VGA_GetColor16(16) );
Alexandre Julliard's avatar
Alexandre Julliard committed
1264
            break;
1265 1266 1267 1268 1269
        case 0x09: /* READ ALL PALETTE REGISTERS AND OVERSCAN REGISTER - A.C.*/
            TRACE("Read All Palette Registers and Overscan Register \n");
		/* ES:DX points to a 17 byte table where the results */
		/*  of this call should be stored.                   */
               VGA_Get16Palette(CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edx));
Alexandre Julliard's avatar
Alexandre Julliard committed
1270 1271
            break;
        case 0x10: /* SET INDIVIDUAL DAC REGISTER */
1272 1273 1274 1275 1276 1277 1278 1279 1280 1281
            {
                PALETTEENTRY paldat;

                TRACE("Set Individual DAC register\n");
                paldat.peRed   = DH_reg(context);
                paldat.peGreen = CH_reg(context);
                paldat.peBlue  = CL_reg(context);
                paldat.peFlags = 0;
                VGA_SetPalette(&paldat,BX_reg(context)&0xFF,1);
            }
Alexandre Julliard's avatar
Alexandre Julliard committed
1282 1283
            break;
        case 0x12: /* SET BLOCK OF DAC REGISTERS */
1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299
            {
                int i;
                PALETTEENTRY paldat;
                BYTE *pt;

                TRACE("Set Block of DAC registers\n");
		pt = (BYTE*)CTX_SEG_OFF_TO_LIN(context,context->SegEs,context->Edx);
		for (i=0;i<CX_reg(context);i++)
                {
                    paldat.peRed   = (*(pt+i*3+0)) << 2;
                    paldat.peGreen = (*(pt+i*3+1)) << 2;
                    paldat.peBlue  = (*(pt+i*3+2)) << 2;
                    paldat.peFlags = 0;
                    VGA_SetPalette(&paldat,(BX_reg(context)+i)&0xFF,1);
                }
            }
Alexandre Julliard's avatar
Alexandre Julliard committed
1300 1301
            break;
        case 0x13: /* SELECT VIDEO DAC COLOR PAGE */
1302
            FIXME("Select video DAC color page - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1303 1304
            break;
        case 0x15: /* READ INDIVIDUAL DAC REGISTER */
1305
            FIXME("Read individual DAC register - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1306 1307
            break;
        case 0x17: /* READ BLOCK OF DAC REGISTERS */
1308
            FIXME("Read block of DAC registers - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1309 1310
            break;
        case 0x18: /* SET PEL MASK */
1311
            FIXME("Set PEL mask - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1312 1313
            break;
        case 0x19: /* READ PEL MASK */
1314
            FIXME("Read PEL mask - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1315 1316
            break;
        case 0x1a: /* GET VIDEO DAC COLOR PAGE STATE */
1317
            FIXME("Get video DAC color page state - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1318 1319
            break;
        case 0x1b: /* PERFORM GRAY-SCALE SUMMING */
1320
            FIXME("Perform Gray-scale summing - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1321 1322
            break;
        default:
1323
            FIXME("INT 10 AH = 0x10 AL = 0x%x - Unknown\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
1324 1325 1326 1327 1328 1329 1330 1331
               AL_reg(context));
            break;
        }
        break;

    case 0x11: /* TEXT MODE CHARGEN */
        /* Note that second subfunction is *almost* identical. */
        /* See INTERRUPT.A for details. */
Jess Haas's avatar
Jess Haas committed
1332
        switch AL_reg(context) {
Alexandre Julliard's avatar
Alexandre Julliard committed
1333 1334
        case 0x00: /* LOAD USER SPECIFIED PATTERNS */
        case 0x10:
1335
            FIXME("Load User Specified Patterns - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1336 1337 1338
            break;
        case 0x01: /* LOAD ROM MONOCHROME PATTERNS */
        case 0x11:
1339
            FIXME("Load ROM Monochrome Patterns - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1340 1341 1342
            break;
        case 0x02: /* LOAD ROM 8x8 DOUBLE-DOT PATTERNS */
        case 0x12:
1343
            FIXME(
1344
                "Load ROM 8x8 Double Dot Patterns - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1345 1346
            break;
        case 0x03: /* SET BLOCK SPECIFIER */
1347
            FIXME("Set Block Specifier - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1348 1349 1350
            break;
        case 0x04: /* LOAD ROM 8x16 CHARACTER SET */
        case 0x14:
1351
            FIXME("Load ROM 8x16 Character Set - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1352 1353
            break;
        case 0x20: /* SET USER 8x16 GRAPHICS CHARS */
1354
            FIXME("Set User 8x16 Graphics Chars - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1355 1356
            break;
        case 0x21: /* SET USER GRAPICS CHARACTERS */
1357
            FIXME("Set User Graphics Characters - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1358 1359
            break;
        case 0x22: /* SET ROM 8x14 GRAPHICS CHARS */
1360
            FIXME("Set ROM 8x14 Graphics Chars - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1361 1362
            break;
        case 0x23: /* SET ROM 8x8 DBL DOT CHARS */
1363
            FIXME(
Alexandre Julliard's avatar
Alexandre Julliard committed
1364 1365 1366
                "Set ROM 8x8 Dbl Dot Chars (Graphics) - Not Supported\n");
            break;
        case 0x24: /* LOAD 8x16 GRAPHIC CHARS */
1367
            FIXME("Load 8x16 Graphic Chars - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1368 1369
            break;
        case 0x30: /* GET FONT INFORMATION */
1370
            FIXME("Get Font Information - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1371 1372
            break;
        default:
1373
            FIXME("INT 10 AH = 0x11 AL = 0x%x - Unknown\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
1374 1375 1376 1377
               AL_reg(context));
            break;
        }
        break;
1378

Alexandre Julliard's avatar
Alexandre Julliard committed
1379 1380 1381
    case 0x12: /* ALTERNATE FUNCTION SELECT */
        switch BL_reg(context) {
        case 0x10: /* GET EGA INFO */
1382
            TRACE("EGA info requested\n");
1383 1384 1385
            SET_BH( context, 0x00 );   /* Color screen */
            SET_BL( context, data->ModeOptions >> 5 ); /* EGA memory size */
            SET_CX( context, data->FeatureBitsSwitches );
Alexandre Julliard's avatar
Alexandre Julliard committed
1386 1387
            break;
        case 0x20: /* ALTERNATE PRTSC */
1388
            FIXME("Install Alternate Print Screen - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1389 1390
            break;
        case 0x30: /* SELECT VERTICAL RESOULTION */
1391
            FIXME("Select vertical resolution - not supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1392
            break;
1393
        case 0x31: /* ENABLE/DISABLE DEFAULT PALETTE LOADING */
1394
            FIXME("Default palette loading - not supported\n");
1395 1396
            data->VGASettings =
                (data->VGASettings & 0xf7) |
1397
                ((AL_reg(context) == 1) << 3);
Alexandre Julliard's avatar
Alexandre Julliard committed
1398 1399
            break;
        case 0x32: /* ENABLE/DISABLE VIDEO ADDRERSSING */
1400
            FIXME("Video Addressing - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1401 1402
            break;
        case 0x33: /* ENABLE/DISABLE GRAY SCALE SUMMING */
1403
            FIXME("Gray Scale Summing - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1404 1405
            break;
        case 0x34: /* ENABLE/DISABLE CURSOR EMULATION */
1406
            TRACE("Set cursor emulation to %d\n", AL_reg(context));
1407 1408
            data->ModeOptions =
                (data->ModeOptions & 0xfe)|(AL_reg(context) == 1);
Alexandre Julliard's avatar
Alexandre Julliard committed
1409 1410
            break;
        case 0x36: /* VIDEO ADDRESS CONTROL */
1411
            FIXME("Video Address Control - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1412 1413
            break;
        default:
1414
            FIXME("INT 10 AH = 0x11 AL = 0x%x - Unknown\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
1415 1416
               AL_reg(context));
            break;
Alexandre Julliard's avatar
Alexandre Julliard committed
1417 1418
        }
        break;
Alexandre Julliard's avatar
Alexandre Julliard committed
1419 1420 1421

    case 0x13: /* WRITE STRING */
        /* This one does not imply that string be at cursor. */
1422
        FIXME("Write String - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1423
        break;
1424 1425

    case 0x1a:
Alexandre Julliard's avatar
Alexandre Julliard committed
1426 1427
        switch AL_reg(context) {
        case 0x00: /* GET DISPLAY COMBINATION CODE */
1428
            TRACE("Get Display Combination Code\n");
1429 1430 1431
            SET_AL( context, 0x1a );      /* Function supported */
            SET_BL( context, INT10_DCC ); /* Active display */
            SET_BH( context, 0x00 );      /* No alternate display */
Alexandre Julliard's avatar
Alexandre Julliard committed
1432 1433
            break;
        case 0x01: /* SET DISPLAY COMBINATION CODE */
1434
            FIXME("Set Display Combination Code - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1435 1436
            break;
        default:
1437
            FIXME("INT 10 AH = 0x1a AL = 0x%x - Unknown\n",
Alexandre Julliard's avatar
Alexandre Julliard committed
1438 1439 1440 1441 1442 1443
               AL_reg(context));
            break;
        }
    break;

    case 0x1b: /* FUNCTIONALITY/STATE INFORMATION */
1444
        TRACE("Get functionality/state information\n");
1445
        if (BX_reg(context) == 0x0000)
1446
        {
1447 1448 1449 1450 1451
            BYTE *ptr = CTX_SEG_OFF_TO_LIN(context,
                                           context->SegEs, 
                                           context->Edi);
            SET_AL( context, 0x1b ); /* Function is supported */
            INT10_FillStateInformation( ptr, data );
1452
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
1453 1454 1455
        break;

    case 0x1c: /* SAVE/RESTORE VIDEO STATE */
1456
        FIXME("Save/Restore Video State - Not Supported\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
1457
        break;
Alexandre Julliard's avatar
Alexandre Julliard committed
1458

1459
        case 0xef:  /* get video mode for hercules-compatibles   */
1460 1461
                    /* There's no reason to really support this  */
                    /* is there?....................(A.C.)       */
1462
                TRACE("Just report the video not hercules compatible\n");
1463
                SET_DX( context, 0xffff );
1464
                break;
1465 1466

    case 0x4f: /* VESA */
1467
        INT10_HandleVESA(context);
1468 1469
        break;

1470
    case 0xfe: /* GET SHADOW BUFFER */
1471
        TRACE( "GET SHADOW BUFFER %lx:%x - ignored\n",
1472 1473 1474
               context->SegEs, DI_reg(context) );
        break;

Alexandre Julliard's avatar
Alexandre Julliard committed
1475
    default:
1476
        FIXME("Unknown - 0x%x\n", AH_reg(context));
Alexandre Julliard's avatar
Alexandre Julliard committed
1477
        INT_BARF( context, 0x10 );
Alexandre Julliard's avatar
Alexandre Julliard committed
1478
    }
1479
}
1480

1481

1482 1483 1484
/**********************************************************************
 *         DOSVM_PutChar
 *
1485 1486
 * Write single character to VGA console at the current 
 * cursor position and updates the BIOS cursor position.
1487
 */
1488
void WINAPI DOSVM_PutChar( BYTE ascii )
1489
{
1490
  BIOSDATA *data = DOSVM_BiosData();
1491 1492
  unsigned  xpos, ypos;

1493
  TRACE("char: 0x%02x(%c)\n", ascii, ascii);
1494

1495
  INT10_InitializeVideoMode( data );
1496 1497 1498

  VGA_PutChar( ascii );
  VGA_GetCursorPos( &xpos, &ypos );
1499
  INT10_SetCursorPos( data, 0, xpos, ypos );
1500
}