user32/tests: Add a regression test for CreateIconFromResource.
[wine] / dlls / winedos / int10.c
index 720fc53..94ea6ff 100644 (file)
  *
  * 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
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
 #include "config.h"
 
 #include <stdlib.h>
 
-#include "miscemu.h"
 #include "vga.h"
 #include "wine/debug.h"
 #include "dosexe.h"
@@ -77,6 +76,61 @@ typedef struct _INT10_HEAP {
     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"
 
 /*
@@ -107,6 +161,7 @@ static const INT10_MODE INT10_modelist[] =
     {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},
@@ -138,6 +193,11 @@ static const INT10_MODE INT10_modelist[] =
     {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);
@@ -239,7 +299,7 @@ static void INT10_FillControllerInformation( BYTE *buffer )
     *(SEGPTR*)(buffer + 36) = 0;
 
     /* 40 - BYTE[216]: reserved for VBE implementation, set to zero */
-    memset( buffer + 40, 216, 0 );
+    memset( buffer + 40, 0, 216 );
 
     /* 
      * 256 - BYTE[256]: reserved for VBE3.0 implementation, 
@@ -256,7 +316,7 @@ static void INT10_FillControllerInformation( BYTE *buffer )
  * Returns FALSE if mode is unknown and TRUE is mode is known
  * even if it is not supported.
  */
-static BOOL INT10_FillModeInformation( BYTE *buffer, WORD mode )
+static BOOL INT10_FillModeInformation( struct _ModeInfoBlock *mib, WORD mode )
 {
     const INT10_MODE *ptr = INT10_FindMode( mode );
     if (!ptr)
@@ -297,10 +357,10 @@ static BOOL INT10_FillModeInformation( BYTE *buffer, WORD mode )
             attr |= 0x0010;
 
         /* Not VGA-compatible? */
-        if (mode > 0xff)
+        if (IS_VESA_MODE(mode))
             attr |= 0x0020;
 
-        *(WORD*)(buffer + 0) = attr;
+        mib->ModeAttributes = attr;
     }
 
     /*
@@ -311,45 +371,46 @@ static BOOL INT10_FillModeInformation( BYTE *buffer, WORD mode )
      *   2 - Window is writable.
      * 3-7 - Reserved.
      */
-    buffer[2] = 0x07; /* window A exists, readable and writable */
-    buffer[3] = 0x00; /* window B not supported */
+    mib->WinAAttributes = 0x07; /* window A exists, readable and writable */
+    mib->WinBAttributes = 0x00; /* window B not supported */
 
     /* 04 - WORD: window granularity in KB */
-    *(WORD*)(buffer + 4) = 64;
+    mib->WinGranularity = 64;
 
     /* 06 - WORD: window size in KB */
-    *(WORD*)(buffer + 6) = 64;
+    mib->WinSize = 64;
 
     /* 08 - WORD[2]: start segments, window A and window B */
-    *(WORD*)(buffer +  8) = 0xa000; /* window A segment */
-    *(WORD*)(buffer + 10) = 0x0000; /* window B not supported */
+    mib->WinASegment = 0xa000; /* window A segment */
+    mib->WinBSegment = 0x0000; /* window B not supported */
 
     /* 12 - DWORD: window positioning function */
-    *(DWORD*)(buffer + 12) = 0; /* not supported */
+    mib->WinFuncPtr = 0; /* not supported */
     
     /* 16 - WORD: bytes per scan line */
-    *(WORD*)(buffer + 16) = 0; /* FIXME */
+    /* 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) */
-    *(WORD*)(buffer + 18) = ptr->Width;
+    mib->XResolution = ptr->Width;
 
     /* 20 - WORD: height in pixels (graphics) or characters (text) */
-    *(WORD*)(buffer + 20) = ptr->Height;
+    mib->YResolution = ptr->Height;
 
     /* 22 - BYTE: width of character cell in pixels */
-    buffer[22] = 0; /* FIXME */
+    mib->XCharSize = 0; /* FIXME */
 
     /* 23 - BYTE: height of character cell in pixels */
-    buffer[23] = 0; /* FIXME */
+    mib->YCharSize = 0; /* FIXME */
 
     /* 24 - BYTE: number of memory planes */
-    buffer[24] = 1; /* FIXME */
+    mib->NumberOfPlanes = 1; /* FIXME */
 
     /* 25 - BYTE: number of bits per pixel */
-    buffer[25] = ptr->Depth; /* FIXME: text modes? reserved bits? */
+    mib->BitsPerPixel = ptr->Depth; /* FIXME: text modes? reserved bits? */
 
     /* 26 - BYTE: number of banks */
-    buffer[26] = 1; /* FIXME */
+    mib->NumberOfBanks = 1; /* FIXME */
 
     /*
      * 27 - BYTE: memory model type
@@ -366,50 +427,72 @@ static BOOL INT10_FillModeInformation( BYTE *buffer, WORD mode )
      * 10-FF - OEM memory models.
      */
     if (!ptr->Depth)
-        buffer[27] = 0; /* text mode */
+        mib->MemoryModel = 0; /* text mode */
     else
-        buffer[27] = 3; /* FIXME */
+        mib->MemoryModel = 3; /* FIXME */
 
     /* 28 - BYTE: size of bank in KB */
-    buffer[28] = 0; /* FIXME */
+    mib->BankSize = 0; /* FIXME */
 
     /* 29 - BYTE: number of image pages (less one) in video RAM */
-    buffer[29] = 0; /* FIXME */
+    mib->NumberOfImagePages = 0; /* FIXME */
 
     /* 30 - BYTE: reserved (0x00 for VBE 1.0-2.0, 0x01 for VBE 3.0) */
-    buffer[30] = 0x01;
+    mib->Reserved1 = 0x01;
 
     /* 
-     * 31 - BYTE: red mask size 
-     * Size of red color component in bits.
-     * Used only when memory model is direct color, otherwise set to zero.
+     * 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 the memory model is direct color or YUV
+     * but "Imperium Romanum" uses this field even when the memory model is
+     * planar. So always fill this field when we have a depth bigger than 8,
+     * otherwise set them to zero.
      */
-    buffer[31] = 0; /* FIXME */
-
-    /*
-     * 32 - BYTE: red field position 
-     * Bit position of the least significant bit of red color component.
-     * Used only when memory model is direct color, otherwise set to zero.
-     */
-    buffer[32] = 0; /* FIXME */
-
-    /* 33 - BYTE: green mask size */
-    buffer[33] = 0; /* FIXME */
-
-    /* 34 - BYTE: green field position */
-    buffer[34] = 0; /* FIXME */
-
-    /* 35 - BYTE: blue mask size */
-    buffer[35] = 0; /* FIXME */
-    
-    /* 36 - BYTE: blue field position */
-    buffer[36] = 0;
-
-    /* 37 - BYTE: reserved mask size */
-    buffer[37] = 0;
-
-    /* 38 - BYTE: reserved mask position */
-    buffer[38] = 0;
+    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 
@@ -417,55 +500,55 @@ static BOOL INT10_FillModeInformation( BYTE *buffer, WORD mode )
      * 0 - Set if color ramp is programmable.
      * 1 - Set if bytes in reserved field may be used by application.
      */
-    buffer[39] = 0; /* not supported */
+    mib->DirectColorModeInfo = 0; /* not supported */
 
     /* 40 - DWORD: physical address of linear video buffer */
-    *(DWORD*)(buffer + 40) = 0; /* not supported */
+    mib->PhysBasePtr = 0; /* not supported */
 
     /* 44 - DWORD: reserved, always zero */
-    *(DWORD*)(buffer + 44) = 0;
+    mib->Reserved2 = 0;
 
     /* 48 - WORD: reserved, always zero */
-    *(WORD*)(buffer + 48) = 0;
+    mib->Reserved3 = 0;
 
     /* 50 - WORD: bytes per scan line in linear modes */
-    *(WORD*)(buffer + 50) = *(WORD*)(buffer + 16);
+    mib->LinBytesPerScanLine = mib->BytesPerScanLine;
 
     /* 52 - BYTE: number of images (less one) for banked video modes */
-    buffer[52] = 0; /* FIXME */
+    mib->BnkNumberOfImagePages = 0; /* FIXME */
 
     /* 53 - BYTE: number of images (less one) for linear video modes */
-    buffer[53] = buffer[52];
+    mib->LinNumberOfImagePages = mib->BnkNumberOfImagePages;
 
     /* 54 - BYTE: red mask size (linear modes) */
-    buffer[54] = buffer[31];
+    mib->LinRedMaskSize = mib->RedMaskSize;
 
     /* 55 - BYTE: red field position (linear modes) */
-    buffer[55] = buffer[32];
+    mib->LinRedFieldPosition = mib->RedFieldPosition;
 
     /* 56 - BYTE: green mask size (linear modes) */
-    buffer[56] = buffer[33];
+    mib->LinGreenMaskSize = mib->GreenMaskSize;
 
     /* 57 - BYTE: green field size (linear modes) */
-    buffer[57] = buffer[34];
+    mib->LinGreenFieldPosition = mib->GreenFieldPosition;
 
     /* 58 - BYTE: blue mask size (linear modes) */
-    buffer[58] = buffer[35];
+    mib->LinBlueMaskSize = mib->BlueMaskSize;
 
     /* 59 - BYTE: blue field position (linear modes) */
-    buffer[59] = buffer[36];
+    mib->LinBlueFieldPosition = mib->BlueFieldPosition;
 
     /* 60 - BYTE: reserved mask size (linear modes) */
-    buffer[60] = buffer[37];
+    mib->LinRsvdMaskSize = mib->RsvdMaskSize;
 
     /* 61 - BYTE: reserved mask position (linear modes) */
-    buffer[61] = buffer[38];
+    mib->LinRsvdFieldPosition = mib->RsvdFieldPosition;
 
     /* 62 - DWORD: maximum pixel clock for graphics video mode, in Hz */
-    *(DWORD*)(buffer + 62) = 0; /* FIXME */
+    mib->MaxPixelClock = 0; /* FIXME */
 
     /* 66 - BYTE[190]: reserved, set to zero */
-    memset( buffer + 66, 190, 0 );
+    memset( mib->Reserved4, 0, 190 );
 
     return TRUE;
 }
@@ -553,7 +636,7 @@ static void INT10_FillStateInformation( BYTE *buffer, BIOSDATA *data )
      buffer[46] = 0; /* FIXME: correct value? */
 
      /* 47 - BYTE[2]: reserved, set to zero */
-     memset( buffer + 47, 2, 0 );
+     memset( buffer + 47, 0, 2 );
 
      /*
       * 49 - BYTE: video memory available
@@ -590,7 +673,7 @@ static void INT10_FillStateInformation( BYTE *buffer, BIOSDATA *data )
      buffer[51] = 4; /* FIXME: correct value? */
 
      /* 52 - BYTE[12]: reserved, set to zero */
-     memset( buffer + 52, 12, 0 );
+     memset( buffer + 52, 0, 12 );
 }
 
 
@@ -607,8 +690,8 @@ INT10_HEAP *INT10_GetHeap( void )
         int  i;
 
         heap_pointer = DOSVM_AllocDataUMB( sizeof(INT10_HEAP), 
-                                           0,
-                                           &segment );
+                                           &segment,
+                                           0 );
 
         for (i = 0; i < 7; i++)
             heap_pointer->StaticModeSupport[i] = 0xff; /* FIXME */
@@ -698,7 +781,7 @@ static BOOL INT10_SetVideoMode( BIOSDATA *data, WORD mode )
     {
         /* Text mode. */
         TRACE( "Setting %s %dx%d text mode (screen %s)\n", 
-               mode <= 0xff ? "VGA" : "VESA", 
+               IS_VESA_MODE(mode) ? "VESA" : "VGA", 
                ptr->Width, ptr->Height, 
                clearScreen ? "cleared" : "preserved" );
 
@@ -721,7 +804,7 @@ static BOOL INT10_SetVideoMode( BIOSDATA *data, WORD mode )
     {
         /* Graphics mode. */
         TRACE( "Setting %s %dx%dx%d graphics mode (screen %s)\n", 
-               mode <= 0xff ? "VGA" : "VESA", 
+               IS_VESA_MODE(mode) ? "VESA" : "VGA", 
                ptr->Width, ptr->Height, ptr->Depth,
                clearScreen ? "cleared" : "preserved" );
 
@@ -789,7 +872,7 @@ static void INT10_InitializeVideoMode( BIOSDATA *data )
  */
 static void INT10_HandleVESA( CONTEXT86 *context )
 {
-    BIOSDATA *data = BIOS_DATA;
+    BIOSDATA *data = DOSVM_BiosData();
 
     switch(AL_reg(context)) {
 
@@ -808,9 +891,9 @@ static void INT10_HandleVESA( CONTEXT86 *context )
     case 0x01: /* RETURN MODE INFORMATION */
         TRACE( "VESA RETURN MODE INFORMATION %04x\n", CX_reg(context) );
         {
-            BYTE *ptr = CTX_SEG_OFF_TO_LIN(context,
-                                           context->SegEs, 
-                                           context->Edi);
+            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 */
@@ -844,7 +927,7 @@ static void INT10_HandleVESA( CONTEXT86 *context )
     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.
+         * it assumes that window granularity is 64k.
          */
         switch(BH_reg(context)) {
         case 0x00: /* select video memory window */
@@ -909,7 +992,7 @@ static void INT10_HandleVESA( CONTEXT86 *context )
         break;
 
     case 0xff: /* Turn VESA ON/OFF */
-        /* i dont know what to do */
+        /* I don't know what to do */
         break;
 
     default:
@@ -946,15 +1029,15 @@ static void INT10_HandleVESA( CONTEXT86 *context )
  *
  *  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 eny of it works.
- *     Currently i dont have a program that uses Vesa that actually gets far
+ *     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 = BIOS_DATA;
+    BIOSDATA *data = DOSVM_BiosData();
 
     INT10_InitializeVideoMode( data );
 
@@ -963,7 +1046,7 @@ void WINAPI DOSVM_Int10Handler( CONTEXT86 *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: %d\n", 
+            FIXME( "Unsupported VGA video mode requested: %#x\n", 
                    AL_reg(context) );
         break;
 
@@ -1175,11 +1258,11 @@ void WINAPI DOSVM_Int10Handler( CONTEXT86 *context )
                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");
+            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");
+            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));
@@ -1303,7 +1386,7 @@ void WINAPI DOSVM_Int10Handler( CONTEXT86 *context )
         case 0x20: /* ALTERNATE PRTSC */
             FIXME("Install Alternate Print Screen - Not Supported\n");
             break;
-        case 0x30: /* SELECT VERTICAL RESOULTION */
+        case 0x30: /* SELECT VERTICAL RESOLUTION */
             FIXME("Select vertical resolution - not supported\n");
             break;
         case 0x31: /* ENABLE/DISABLE DEFAULT PALETTE LOADING */
@@ -1312,7 +1395,7 @@ void WINAPI DOSVM_Int10Handler( CONTEXT86 *context )
                 (data->VGASettings & 0xf7) |
                 ((AL_reg(context) == 1) << 3);
             break;
-        case 0x32: /* ENABLE/DISABLE VIDEO ADDRERSSING */
+        case 0x32: /* ENABLE/DISABLE VIDEO ADDRESSING */
             FIXME("Video Addressing - Not Supported\n");
             break;
         case 0x33: /* ENABLE/DISABLE GRAY SCALE SUMMING */
@@ -1384,7 +1467,7 @@ void WINAPI DOSVM_Int10Handler( CONTEXT86 *context )
         break;
 
     case 0xfe: /* GET SHADOW BUFFER */
-        TRACE( "GET SHADOW BUFFER %lx:%x - ignored\n",
+        TRACE( "GET SHADOW BUFFER %x:%x - ignored\n",
                context->SegEs, DI_reg(context) );
         break;
 
@@ -1403,7 +1486,7 @@ void WINAPI DOSVM_Int10Handler( CONTEXT86 *context )
  */
 void WINAPI DOSVM_PutChar( BYTE ascii )
 {
-  BIOSDATA *data = BIOS_DATA;
+  BIOSDATA *data = DOSVM_BiosData();
   unsigned  xpos, ypos;
 
   TRACE("char: 0x%02x(%c)\n", ascii, ascii);