| /* |
| * BIOS interrupt 10h handler |
| * |
| * Copyright 1998 Ove Kåven |
| * 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 |
| */ |
| |
| #include "config.h" |
| |
| #include <stdlib.h> |
| |
| #include "miscemu.h" |
| #include "vga.h" |
| #include "wine/debug.h" |
| #include "dosexe.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(int); |
| |
| /* |
| * 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; |
| |
| /* |
| * 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 */ |
| }; |
| |
| #include "poppack.h" |
| |
| /* |
| * 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}, |
| {0x006a, 800, 600, 4}, /* VESA mode, same as 0x102 */ |
| {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} |
| }; |
| |
| /* 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) |
| |
| /* Forward declarations. */ |
| static INT10_HEAP *INT10_GetHeap(void); |
| static void INT10_SetCursorPos(BIOSDATA*, unsigned, unsigned, unsigned); |
| |
| |
| /********************************************************************** |
| * 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; |
| } |
| |
| |
| /********************************************************************** |
| * 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 ) |
| { |
| 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) ); |
| |
| /* |
| * 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 |
| */ |
| } |
| |
| |
| /********************************************************************** |
| * 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. |
| */ |
| static BOOL INT10_FillModeInformation( struct _ModeInfoBlock *mib, WORD mode ) |
| { |
| 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? */ |
| if (IS_VESA_MODE(mode)) |
| attr |= 0x0020; |
| |
| mib->ModeAttributes = attr; |
| } |
| |
| /* |
| * 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. |
| */ |
| mib->WinAAttributes = 0x07; /* window A exists, readable and writable */ |
| mib->WinBAttributes = 0x00; /* window B not supported */ |
| |
| /* 04 - WORD: window granularity in KB */ |
| mib->WinGranularity = 64; |
| |
| /* 06 - WORD: window size in KB */ |
| mib->WinSize = 64; |
| |
| /* 08 - WORD[2]: start segments, window A and window B */ |
| mib->WinASegment = 0xa000; /* window A segment */ |
| mib->WinBSegment = 0x0000; /* window B not supported */ |
| |
| /* 12 - DWORD: window positioning function */ |
| mib->WinFuncPtr = 0; /* not supported */ |
| |
| /* 16 - WORD: bytes per scan line */ |
| /* FIXME: is this always correct? */ |
| mib->BytesPerScanLine = ptr->Width * (ptr->Depth ? (ptr->Depth + 7) / 8 : 1); |
| |
| /* 18 - WORD: width in pixels (graphics) or characters (text) */ |
| mib->XResolution = ptr->Width; |
| |
| /* 20 - WORD: height in pixels (graphics) or characters (text) */ |
| mib->YResolution = ptr->Height; |
| |
| /* 22 - BYTE: width of character cell in pixels */ |
| mib->XCharSize = 0; /* FIXME */ |
| |
| /* 23 - BYTE: height of character cell in pixels */ |
| mib->YCharSize = 0; /* FIXME */ |
| |
| /* 24 - BYTE: number of memory planes */ |
| mib->NumberOfPlanes = 1; /* FIXME */ |
| |
| /* 25 - BYTE: number of bits per pixel */ |
| mib->BitsPerPixel = ptr->Depth; /* FIXME: text modes? reserved bits? */ |
| |
| /* 26 - BYTE: number of banks */ |
| mib->NumberOfBanks = 1; /* FIXME */ |
| |
| /* |
| * 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) |
| mib->MemoryModel = 0; /* text mode */ |
| else |
| mib->MemoryModel = 3; /* FIXME */ |
| |
| /* 28 - BYTE: size of bank in KB */ |
| mib->BankSize = 0; /* FIXME */ |
| |
| /* 29 - BYTE: number of image pages (less one) in video RAM */ |
| mib->NumberOfImagePages = 0; /* FIXME */ |
| |
| /* 30 - BYTE: reserved (0x00 for VBE 1.0-2.0, 0x01 for VBE 3.0) */ |
| mib->Reserved1 = 0x01; |
| |
| /* |
| * 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. |
| */ |
| 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; |
| } |
| |
| /* |
| * 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. |
| */ |
| mib->DirectColorModeInfo = 0; /* not supported */ |
| |
| /* 40 - DWORD: physical address of linear video buffer */ |
| mib->PhysBasePtr = 0; /* not supported */ |
| |
| /* 44 - DWORD: reserved, always zero */ |
| mib->Reserved2 = 0; |
| |
| /* 48 - WORD: reserved, always zero */ |
| mib->Reserved3 = 0; |
| |
| /* 50 - WORD: bytes per scan line in linear modes */ |
| mib->LinBytesPerScanLine = mib->BytesPerScanLine; |
| |
| /* 52 - BYTE: number of images (less one) for banked video modes */ |
| mib->BnkNumberOfImagePages = 0; /* FIXME */ |
| |
| /* 53 - BYTE: number of images (less one) for linear video modes */ |
| mib->LinNumberOfImagePages = mib->BnkNumberOfImagePages; |
| |
| /* 54 - BYTE: red mask size (linear modes) */ |
| mib->LinRedMaskSize = mib->RedMaskSize; |
| |
| /* 55 - BYTE: red field position (linear modes) */ |
| mib->LinRedFieldPosition = mib->RedFieldPosition; |
| |
| /* 56 - BYTE: green mask size (linear modes) */ |
| mib->LinGreenMaskSize = mib->GreenMaskSize; |
| |
| /* 57 - BYTE: green field size (linear modes) */ |
| mib->LinGreenFieldPosition = mib->GreenFieldPosition; |
| |
| /* 58 - BYTE: blue mask size (linear modes) */ |
| mib->LinBlueMaskSize = mib->BlueMaskSize; |
| |
| /* 59 - BYTE: blue field position (linear modes) */ |
| mib->LinBlueFieldPosition = mib->BlueFieldPosition; |
| |
| /* 60 - BYTE: reserved mask size (linear modes) */ |
| mib->LinRsvdMaskSize = mib->RsvdMaskSize; |
| |
| /* 61 - BYTE: reserved mask position (linear modes) */ |
| mib->LinRsvdFieldPosition = mib->RsvdFieldPosition; |
| |
| /* 62 - DWORD: maximum pixel clock for graphics video mode, in Hz */ |
| mib->MaxPixelClock = 0; /* FIXME */ |
| |
| /* 66 - BYTE[190]: reserved, set to zero */ |
| memset( &mib->Reserved4, 190, 0 ); |
| |
| return TRUE; |
| } |
| |
| |
| /********************************************************************** |
| * INT10_FillStateInformation |
| * |
| * Fill 64-byte buffer with VGA state and functionality information. |
| */ |
| static void INT10_FillStateInformation( BYTE *buffer, BIOSDATA *data ) |
| { |
| 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 */ |
| |
| /* |
| * 42 - BYTE: number of scan lines active |
| * Values (hex): |
| * 00 = 200 |
| * 01 = 350 |
| * 02 = 400 |
| * 03 = 480 |
| */ |
| 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), |
| &segment, |
| 0 ); |
| |
| 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; |
| } |
| |
| |
| /********************************************************************** |
| * 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 ); |
| INT10_HEAP *heap = INT10_GetHeap(); |
| BOOL clearScreen = TRUE; |
| |
| if (!ptr) |
| return FALSE; |
| |
| /* |
| * Linear framebuffer is not supported. |
| */ |
| if (mode & 0x4000) |
| return FALSE; |
| |
| /* |
| * Check for VGA and VESA preserve video memory flag. |
| */ |
| if ((mode & 0x0080) || (mode & 0x8000)) |
| clearScreen = FALSE; |
| |
| /* |
| * Note that we do not mask out flags here on purpose. |
| */ |
| heap->VesaCurrentMode = mode; |
| if (mode <= 0xff) |
| data->VideoMode = mode; |
| else |
| data->VideoMode = 0; |
| |
| if (ptr->Depth == 0) |
| { |
| /* Text mode. */ |
| TRACE( "Setting %s %dx%d text mode (screen %s)\n", |
| IS_VESA_MODE(mode) ? "VESA" : "VGA", |
| ptr->Width, ptr->Height, |
| clearScreen ? "cleared" : "preserved" ); |
| |
| /* |
| * FIXME: We should check here if alpha mode could be set. |
| */ |
| VGA_SetAlphaMode( ptr->Width, ptr->Height ); |
| |
| data->VideoColumns = ptr->Width; |
| 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 ); |
| } |
| } |
| else |
| { |
| /* Graphics mode. */ |
| TRACE( "Setting %s %dx%dx%d graphics mode (screen %s)\n", |
| IS_VESA_MODE(mode) ? "VESA" : "VGA", |
| ptr->Width, ptr->Height, ptr->Depth, |
| clearScreen ? "cleared" : "preserved" ); |
| |
| if (VGA_SetMode( ptr->Width, ptr->Height, ptr->Depth )) |
| return FALSE; |
| } |
| |
| return TRUE; |
| } |
| |
| |
| /********************************************************************** |
| * INT10_GetCursorPos |
| */ |
| static void INT10_GetCursorPos(BIOSDATA*data,unsigned page,unsigned*X,unsigned*Y) |
| { |
| *X = data->VideoCursorPos[page*2]; /* column */ |
| *Y = data->VideoCursorPos[page*2+1]; /* row */ |
| } |
| |
| |
| /********************************************************************** |
| * INT10_SetCursorPos |
| */ |
| static void INT10_SetCursorPos(BIOSDATA*data,unsigned page,unsigned X,unsigned Y) |
| { |
| data->VideoCursorPos[page*2] = X; |
| data->VideoCursorPos[page*2+1] = Y; |
| } |
| |
| |
| /********************************************************************** |
| * INT10_InitializeVideoMode |
| * |
| * The first time this function is called VGA emulation is set to the |
| * default text mode. |
| */ |
| static void INT10_InitializeVideoMode( BIOSDATA *data ) |
| { |
| 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. |
| */ |
| if (width >= 80 && height >= 25) |
| INT10_SetVideoMode( data, 0x03 ); |
| else |
| INT10_SetVideoMode( data, 0x01 ); |
| } |
| |
| |
| /********************************************************************** |
| * INT10_HandleVESA |
| * |
| * Handler for VESA functions (int10 function 0x4f). |
| */ |
| static void INT10_HandleVESA( CONTEXT86 *context ) |
| { |
| BIOSDATA *data = DOSVM_BiosData(); |
| |
| switch(AL_reg(context)) { |
| |
| 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 */ |
| } |
| break; |
| |
| case 0x01: /* RETURN MODE INFORMATION */ |
| TRACE( "VESA RETURN MODE INFORMATION %04x\n", CX_reg(context) ); |
| { |
| struct _ModeInfoBlock *ptr = CTX_SEG_OFF_TO_LIN(context, |
| context->SegEs, |
| context->Edi); |
| SET_AL( context, 0x4f ); |
| if (INT10_FillModeInformation( ptr, CX_reg(context) )) |
| SET_AH( context, 0x00 ); /* status: success */ |
| else |
| SET_AH( context, 0x01 ); /* status: failed */ |
| } |
| break; |
| |
| case 0x02: /* SET SuperVGA VIDEO MODE */ |
| 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 */ |
| break; |
| |
| case 0x03: /* VESA SuperVGA BIOS - GET CURRENT VIDEO MODE */ |
| SET_AL( context, 0x4f ); |
| SET_AH( context, 0x00 ); |
| SET_BX( context, INT10_GetHeap()->VesaCurrentMode ); |
| 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 */ |
| SET_AL( context, 0x4f ); /* function supported */ |
| if(BL_reg(context) == 0) { |
| VGA_SetWindowStart(DX_reg(context) * 64 * 1024); |
| SET_AH( context, 0x00 ); /* status: successful */ |
| } else |
| SET_AH( context, 0x01 ); /* status: failed */ |
| break; |
| case 0x01: /* get video memory window */ |
| SET_AL( context, 0x4f ); /* function supported */ |
| if(BL_reg(context) == 0) { |
| SET_DX( context, VGA_GetWindowStart() / 64 / 1024 ); |
| SET_AH( context, 0x00 ); /* status: successful */ |
| } else |
| SET_AH( context, 0x01 ); /* status: failed */ |
| break; |
| default: |
| INT_BARF( context, 0x10 ); |
| } |
| 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"); |
| SET_DX( context, 0xffff ); |
| break; |
| |
| case 0xff: /* Turn VESA ON/OFF */ |
| /* I don't know what to do */ |
| break; |
| |
| default: |
| FIXME("VESA Function (0x%x) - Not Supported\n", AH_reg(context)); |
| break; |
| } |
| } |
| |
| |
| /********************************************************************** |
| * 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. |
| * 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 |
| * enough without crashing to do vesa stuff. |
| * |
| * Added additional vga graphic support - 3/99 |
| */ |
| void WINAPI DOSVM_Int10Handler( CONTEXT86 *context ) |
| { |
| BIOSDATA *data = DOSVM_BiosData(); |
| |
| INT10_InitializeVideoMode( data ); |
| |
| switch(AH_reg(context)) { |
| |
| case 0x00: /* SET VIDEO MODE */ |
| TRACE( "Set VGA video mode %02x\n", AL_reg(context) ); |
| if (!INT10_SetVideoMode( data, AL_reg(context) )) |
| FIXME( "Unsupported VGA video mode requested: %#x\n", |
| AL_reg(context) ); |
| break; |
| |
| case 0x01: /* SET CURSOR SHAPE */ |
| TRACE("Set Cursor Shape start %d end %d options %d\n", |
| CH_reg(context) & 0x1f, |
| CL_reg(context) & 0x1f, |
| CH_reg(context) & 0xe0); |
| data->VideoCursorType = CX_reg(context); /* direct copy */ |
| VGA_SetCursorShape(CH_reg(context), CL_reg(context)); |
| break; |
| |
| case 0x02: /* SET CURSOR POSITION */ |
| /* BH = Page Number */ /* Not supported */ |
| /* DH = Row */ /* 0 is left */ |
| /* DL = Column */ /* 0 is top */ |
| INT10_SetCursorPos(data,BH_reg(context),DL_reg(context),DH_reg(context)); |
| if (BH_reg(context)) |
| { |
| FIXME("Set Cursor Position: Cannot set to page %d\n", |
| BH_reg(context)); |
| } |
| else |
| { |
| VGA_SetCursorPos(DL_reg(context), DH_reg(context)); |
| TRACE("Set Cursor Position: %d/%d\n", DL_reg(context), |
| DH_reg(context)); |
| } |
| break; |
| |
| case 0x03: /* GET CURSOR POSITION AND SIZE */ |
| { |
| unsigned row, col; |
| |
| TRACE("Get cursor position and size (page %d)\n", BH_reg(context)); |
| SET_CX( context, data->VideoCursorType ); |
| INT10_GetCursorPos(data,BH_reg(context),&col,&row); |
| SET_DH( context, row ); |
| SET_DL( context, col ); |
| TRACE("Cursor Position: %d/%d\n", DL_reg(context), DH_reg(context)); |
| } |
| break; |
| |
| case 0x04: /* READ LIGHT PEN POSITION */ |
| FIXME("Read Light Pen Position - Not Supported\n"); |
| SET_AH( context, 0x00 ); /* Not down */ |
| break; |
| |
| case 0x05: /* SELECT ACTIVE DISPLAY PAGE */ |
| FIXME("Select Active Display Page (%d) - Not Supported\n", AL_reg(context)); |
| data->VideoCurPage = AL_reg(context); |
| break; |
| |
| case 0x06: /* SCROLL UP WINDOW */ |
| /* AL = Lines to scroll */ |
| /* BH = Attribute */ |
| /* CH,CL = row, col upper-left */ |
| /* DH,DL = row, col lower-right */ |
| TRACE("Scroll Up Window %d\n", AL_reg(context)); |
| |
| 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) ); |
| break; |
| |
| case 0x07: /* SCROLL DOWN WINDOW */ |
| /* AL = Lines to scroll */ |
| /* BH = Attribute */ |
| /* CH,CL = row, col upper-left */ |
| /* DH,DL = row, col lower-right */ |
| TRACE("Scroll Down Window %d\n", AL_reg(context)); |
| |
| 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) ); |
| break; |
| |
| case 0x08: /* READ CHARACTER AND ATTRIBUTE AT CURSOR POSITION */ |
| { |
| if (BH_reg(context)) /* Write to different page */ |
| { |
| FIXME("Read character and attribute at cursor position -" |
| " Can't read from non-0 page\n"); |
| SET_AL( context, ' ' ); /* That page is blank */ |
| SET_AH( context, 7 ); |
| } |
| else |
| { |
| BYTE ascii, attr; |
| TRACE("Read Character and Attribute at Cursor Position\n"); |
| VGA_GetCharacterAtCursor(&ascii, &attr); |
| SET_AL( context, ascii ); |
| SET_AH( context, attr ); |
| } |
| } |
| break; |
| |
| case 0x09: /* WRITE CHARACTER AND ATTRIBUTE AT CURSOR POSITION */ |
| case 0x0a: /* WRITE CHARACTER ONLY AT CURSOR POSITION */ |
| /* AL = Character to display. */ |
| /* BH = Page Number */ /* We can't write to non-0 pages, yet. */ |
| /* BL = Attribute / Color */ |
| /* CX = Times to Write Char */ |
| /* Note here that the cursor is not advanced. */ |
| { |
| unsigned row, col; |
| |
| INT10_GetCursorPos(data,BH_reg(context),&col,&row); |
| VGA_WriteChars(col, row, |
| AL_reg(context), |
| (AH_reg(context) == 0x09) ? BL_reg(context) : -1, |
| CX_reg(context)); |
| if (CX_reg(context) > 1) |
| TRACE("Write Character%s at Cursor Position (Rep. %d): %c\n", |
| (AH_reg(context) == 0x09) ? " and Attribute" : "", |
| CX_reg(context), AL_reg(context)); |
| else |
| TRACE("Write Character%s at Cursor Position: %c\n", |
| (AH_reg(context) == 0x09) ? " and Attribute" : "", |
| AL_reg(context)); |
| } |
| break; |
| |
| case 0x0b: |
| switch BH_reg(context) { |
| case 0x00: /* SET BACKGROUND/BORDER COLOR */ |
| /* In text modes, this sets only the border... */ |
| /* According to the interrupt list and one of my books. */ |
| /* Funny though that Beyond Zork seems to indicate that it |
| also sets up the default background attributes for clears |
| and scrolls... */ |
| /* Bear in mind here that we do not want to change, |
| apparently, the foreground or attribute of the background |
| with this call, so we should check first to see what the |
| foreground already is... FIXME */ |
| FIXME("Set Background/Border Color: %d/%d\n", |
| BH_reg(context), BL_reg(context)); |
| break; |
| case 0x01: /* SET PALETTE */ |
| FIXME("Set Palette - Not Supported\n"); |
| break; |
| default: |
| FIXME("INT 10 AH = 0x0b BH = 0x%x - Unknown\n", |
| BH_reg(context)); |
| break; |
| } |
| break; |
| |
| case 0x0c: /* WRITE GRAPHICS PIXEL */ |
| /* Not in graphics mode, can ignore w/o error */ |
| FIXME("Write Graphics Pixel - Not Supported\n"); |
| break; |
| |
| case 0x0d: /* READ GRAPHICS PIXEL */ |
| /* Not in graphics mode, can ignore w/o error */ |
| FIXME("Read Graphics Pixel - Not Supported\n"); |
| break; |
| |
| case 0x0e: /* TELETYPE OUTPUT */ |
| TRACE("Teletype Output\n"); |
| DOSVM_PutChar(AL_reg(context)); |
| break; |
| |
| case 0x0f: /* GET CURRENT VIDEO MODE */ |
| TRACE("Get current video mode: -> mode %d, columns %d\n", data->VideoMode, data->VideoColumns); |
| /* Note: This should not be a constant value. */ |
| SET_AL( context, data->VideoMode ); |
| SET_AH( context, data->VideoColumns ); |
| SET_BH( context, 0 ); /* Display page 0 */ |
| break; |
| |
| case 0x10: |
| switch AL_reg(context) { |
| 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)); |
| /* BH is the value BL is the register */ |
| VGA_SetColor16((int)BL_reg(context),(int)BH_reg(context)); |
| break; |
| case 0x01: /* SET BORDER (OVERSCAN) */ |
| /* Text terminals have no overscan */ |
| /* I'm setting it anyway. - A.C. */ |
| TRACE("Set Border (Overscan) - Ignored but set.\n"); |
| VGA_SetColor16(16,(int)BH_reg(context)); |
| break; |
| case 0x02: /* SET ALL PALETTE REGISTERS - A.C.*/ |
| TRACE("Set all palette registers\n"); |
| /* ES:DX points to a 17 byte table of colors */ |
| /* No return data listed */ |
| /* I'll have to update my table and the default palette */ |
| VGA_Set16Palette(CTX_SEG_OFF_TO_LIN(context, context->SegEs, context->Edx)); |
| break; |
| case 0x03: /* TOGGLE INTENSITY/BLINKING BIT */ |
| FIXME("Toggle Intensity/Blinking Bit - Not Supported\n"); |
| break; |
| case 0x07: /* GET INDIVIDUAL PALETTE REGISTER - A.C.*/ |
| TRACE("Get Individual Palette Register 0x0%x\n",BL_reg(context)); |
| /* BL is register to read [ 0-15 ] BH is return value */ |
| SET_BH( context, VGA_GetColor16((int)BL_reg(context)) ); |
| break; |
| case 0x08: /* READ OVERSCAN (BORDER COLOR) REGISTER - A.C. */ |
| TRACE("Read Overscan (Border Color) Register \n"); |
| SET_BH( context, VGA_GetColor16(16) ); |
| break; |
| 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)); |
| break; |
| case 0x10: /* SET INDIVIDUAL DAC REGISTER */ |
| { |
| 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); |
| } |
| break; |
| case 0x12: /* SET BLOCK OF DAC REGISTERS */ |
| { |
| 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); |
| } |
| } |
| break; |
| case 0x13: /* SELECT VIDEO DAC COLOR PAGE */ |
| FIXME("Select video DAC color page - Not Supported\n"); |
| break; |
| case 0x15: /* READ INDIVIDUAL DAC REGISTER */ |
| FIXME("Read individual DAC register - Not Supported\n"); |
| break; |
| case 0x17: /* READ BLOCK OF DAC REGISTERS */ |
| FIXME("Read block of DAC registers - Not Supported\n"); |
| break; |
| case 0x18: /* SET PEL MASK */ |
| FIXME("Set PEL mask - Not Supported\n"); |
| break; |
| case 0x19: /* READ PEL MASK */ |
| FIXME("Read PEL mask - Not Supported\n"); |
| break; |
| case 0x1a: /* GET VIDEO DAC COLOR PAGE STATE */ |
| FIXME("Get video DAC color page state - Not Supported\n"); |
| break; |
| case 0x1b: /* PERFORM GRAY-SCALE SUMMING */ |
| FIXME("Perform Gray-scale summing - Not Supported\n"); |
| break; |
| default: |
| FIXME("INT 10 AH = 0x10 AL = 0x%x - Unknown\n", |
| AL_reg(context)); |
| break; |
| } |
| break; |
| |
| case 0x11: /* TEXT MODE CHARGEN */ |
| /* Note that second subfunction is *almost* identical. */ |
| /* See INTERRUPT.A for details. */ |
| switch AL_reg(context) { |
| case 0x00: /* LOAD USER SPECIFIED PATTERNS */ |
| case 0x10: |
| FIXME("Load User Specified Patterns - Not Supported\n"); |
| break; |
| case 0x01: /* LOAD ROM MONOCHROME PATTERNS */ |
| case 0x11: |
| FIXME("Load ROM Monochrome Patterns - Not Supported\n"); |
| break; |
| case 0x02: /* LOAD ROM 8x8 DOUBLE-DOT PATTERNS */ |
| case 0x12: |
| FIXME( |
| "Load ROM 8x8 Double Dot Patterns - Not Supported\n"); |
| break; |
| case 0x03: /* SET BLOCK SPECIFIER */ |
| FIXME("Set Block Specifier - Not Supported\n"); |
| break; |
| case 0x04: /* LOAD ROM 8x16 CHARACTER SET */ |
| case 0x14: |
| FIXME("Load ROM 8x16 Character Set - Not Supported\n"); |
| break; |
| case 0x20: /* SET USER 8x16 GRAPHICS CHARS */ |
| FIXME("Set User 8x16 Graphics Chars - Not Supported\n"); |
| break; |
| case 0x21: /* SET USER GRAPICS CHARACTERS */ |
| FIXME("Set User Graphics Characters - Not Supported\n"); |
| break; |
| case 0x22: /* SET ROM 8x14 GRAPHICS CHARS */ |
| FIXME("Set ROM 8x14 Graphics Chars - Not Supported\n"); |
| break; |
| case 0x23: /* SET ROM 8x8 DBL DOT CHARS */ |
| FIXME( |
| "Set ROM 8x8 Dbl Dot Chars (Graphics) - Not Supported\n"); |
| break; |
| case 0x24: /* LOAD 8x16 GRAPHIC CHARS */ |
| FIXME("Load 8x16 Graphic Chars - Not Supported\n"); |
| break; |
| case 0x30: /* GET FONT INFORMATION */ |
| FIXME("Get Font Information - Not Supported\n"); |
| break; |
| default: |
| FIXME("INT 10 AH = 0x11 AL = 0x%x - Unknown\n", |
| AL_reg(context)); |
| break; |
| } |
| break; |
| |
| case 0x12: /* ALTERNATE FUNCTION SELECT */ |
| switch BL_reg(context) { |
| case 0x10: /* GET EGA INFO */ |
| TRACE("EGA info requested\n"); |
| SET_BH( context, 0x00 ); /* Color screen */ |
| SET_BL( context, data->ModeOptions >> 5 ); /* EGA memory size */ |
| SET_CX( context, data->FeatureBitsSwitches ); |
| break; |
| case 0x20: /* ALTERNATE PRTSC */ |
| FIXME("Install Alternate Print Screen - Not Supported\n"); |
| break; |
| case 0x30: /* SELECT VERTICAL RESOULTION */ |
| FIXME("Select vertical resolution - not supported\n"); |
| break; |
| case 0x31: /* ENABLE/DISABLE DEFAULT PALETTE LOADING */ |
| FIXME("Default palette loading - not supported\n"); |
| data->VGASettings = |
| (data->VGASettings & 0xf7) | |
| ((AL_reg(context) == 1) << 3); |
| break; |
| case 0x32: /* ENABLE/DISABLE VIDEO ADDRERSSING */ |
| FIXME("Video Addressing - Not Supported\n"); |
| break; |
| case 0x33: /* ENABLE/DISABLE GRAY SCALE SUMMING */ |
| FIXME("Gray Scale Summing - Not Supported\n"); |
| break; |
| case 0x34: /* ENABLE/DISABLE CURSOR EMULATION */ |
| TRACE("Set cursor emulation to %d\n", AL_reg(context)); |
| data->ModeOptions = |
| (data->ModeOptions & 0xfe)|(AL_reg(context) == 1); |
| break; |
| case 0x36: /* VIDEO ADDRESS CONTROL */ |
| FIXME("Video Address Control - Not Supported\n"); |
| break; |
| default: |
| FIXME("INT 10 AH = 0x11 AL = 0x%x - Unknown\n", |
| AL_reg(context)); |
| break; |
| } |
| break; |
| |
| case 0x13: /* WRITE STRING */ |
| /* This one does not imply that string be at cursor. */ |
| FIXME("Write String - Not Supported\n"); |
| break; |
| |
| case 0x1a: |
| switch AL_reg(context) { |
| case 0x00: /* GET DISPLAY COMBINATION CODE */ |
| TRACE("Get Display Combination Code\n"); |
| SET_AL( context, 0x1a ); /* Function supported */ |
| SET_BL( context, INT10_DCC ); /* Active display */ |
| SET_BH( context, 0x00 ); /* No alternate display */ |
| break; |
| case 0x01: /* SET DISPLAY COMBINATION CODE */ |
| FIXME("Set Display Combination Code - Not Supported\n"); |
| break; |
| default: |
| FIXME("INT 10 AH = 0x1a AL = 0x%x - Unknown\n", |
| AL_reg(context)); |
| break; |
| } |
| break; |
| |
| case 0x1b: /* FUNCTIONALITY/STATE INFORMATION */ |
| TRACE("Get functionality/state information\n"); |
| if (BX_reg(context) == 0x0000) |
| { |
| BYTE *ptr = CTX_SEG_OFF_TO_LIN(context, |
| context->SegEs, |
| context->Edi); |
| SET_AL( context, 0x1b ); /* Function is supported */ |
| INT10_FillStateInformation( ptr, data ); |
| } |
| break; |
| |
| case 0x1c: /* SAVE/RESTORE VIDEO STATE */ |
| FIXME("Save/Restore Video State - Not Supported\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"); |
| SET_DX( context, 0xffff ); |
| break; |
| |
| case 0x4f: /* VESA */ |
| INT10_HandleVESA(context); |
| break; |
| |
| case 0xfe: /* GET SHADOW BUFFER */ |
| TRACE( "GET SHADOW BUFFER %lx:%x - ignored\n", |
| context->SegEs, DI_reg(context) ); |
| break; |
| |
| default: |
| FIXME("Unknown - 0x%x\n", AH_reg(context)); |
| INT_BARF( context, 0x10 ); |
| } |
| } |
| |
| |
| /********************************************************************** |
| * DOSVM_PutChar |
| * |
| * Write single character to VGA console at the current |
| * cursor position and updates the BIOS cursor position. |
| */ |
| void WINAPI DOSVM_PutChar( BYTE ascii ) |
| { |
| BIOSDATA *data = DOSVM_BiosData(); |
| unsigned xpos, ypos; |
| |
| TRACE("char: 0x%02x(%c)\n", ascii, ascii); |
| |
| INT10_InitializeVideoMode( data ); |
| |
| VGA_PutChar( ascii ); |
| VGA_GetCursorPos( &xpos, &ypos ); |
| INT10_SetCursorPos( data, 0, xpos, ypos ); |
| } |