]> git.saurik.com Git - apple/boot.git/blobdiff - i386/boot2/graphics.c
boot-132.tar.gz
[apple/boot.git] / i386 / boot2 / graphics.c
index d5359b9a4a4d43dbe80aef7888ca2fb85ed8f7f1..466f0ad5b16be69313a133dbef01a3fa340d780e 100644 (file)
@@ -1,12 +1,12 @@
 /*
- * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
+ * Portions Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights
  * Reserved.  This file contains Original Code and/or Modifications of
  * Original Code as defined in and that are subject to the Apple Public
- * Source License Version 1.1 (the "License").  You may not use this file
+ * Source License Version 2.0 (the "License").  You may not use this file
  * except in compliance with the License.  Please obtain a copy of the
  * License at http://www.apple.com/publicsource and read it before using
  * this file.
@@ -40,20 +40,29 @@ static int currentIndicator = 0;
 static unsigned long lookUpCLUTIndex( unsigned char index,
                                       unsigned char depth );
 
-static void drawColorRectangle( unsigned short x,
+void drawColorRectangle( unsigned short x,
                                 unsigned short y,
                                 unsigned short width,
                                 unsigned short height,
                                 unsigned char  colorIndex );
 
-static void drawDataRectangle( unsigned short  x,
+void drawDataRectangle( unsigned short  x,
                                unsigned short  y,
                                unsigned short  width,
                                unsigned short  height,
-                               unsigned char * data );
+                        unsigned char * data );
 
-#define VIDEO(x) (bootArgs->video.v_ ## x)
+static void setBorderColor( unsigned char colorIndex );
 
+int
+convertImage( unsigned short width,
+              unsigned short height,
+              const unsigned char *imageData,
+              unsigned char **newImageData );
+
+#define VIDEO(x) (bootArgs->Video.v_ ## x)
+
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
 
 //==========================================================================
 // printVBEInfo
@@ -62,6 +71,7 @@ void printVBEInfo()
 {
     VBEInfoBlock vbeInfo;
     int          err;
+    int          small;
 
     // Fetch VBE Controller Info.
 
@@ -72,18 +82,82 @@ void printVBEInfo()
 
     // Check presence of VESA signature.
 
-    if ( strncmp( vbeInfo.VESASignature, "VESA", 4 ) )
+    if ( strncmp( (char *)vbeInfo.VESASignature, "VESA", 4 ) )
         return;
 
     // Announce controller properties.
 
-    printf("VESA v%d.%d %dMB (%s)\n",
+    small = (vbeInfo.TotalMemory < 16);
+
+    printf("VESA v%d.%d %d%s (%s)\n",
            vbeInfo.VESAVersion >> 8,
            vbeInfo.VESAVersion & 0xf,
-           vbeInfo.TotalMemory / 16,
+           small ? (vbeInfo.TotalMemory * 64) : (vbeInfo.TotalMemory / 16),
+           small ? "KB" : "MB",
            VBEDecodeFP(const char *, vbeInfo.OEMStringPtr) );
 }
 
+//==========================================================================
+//
+
+void 
+printVBEModeInfo()
+{
+    VBEInfoBlock     vbeInfo;
+    unsigned short * modePtr;
+    VBEModeInfoBlock modeInfo;
+    int              err;
+    int              line;
+
+    err = getVBEInfo( &vbeInfo );
+    if ( err != errSuccess )
+        return;
+
+    line = 0;
+
+    // Activate and clear page 1
+    setActiveDisplayPage(1);
+    clearScreenRows(0, 24);
+    setCursorPosition( 0, 0, 1 );
+
+    printVBEInfo();
+    printf("Video modes supported:\n", VBEDecodeFP(const char *, vbeInfo.OEMStringPtr));
+
+   // Loop through the mode list, and find the matching mode.
+
+    for ( modePtr = VBEDecodeFP( unsigned short *, vbeInfo.VideoModePtr );
+          *modePtr != modeEndOfList; modePtr++ )
+    {
+        // Get mode information.
+
+        bzero( &modeInfo, sizeof(modeInfo) );
+        err = getVBEModeInfo( *modePtr, &modeInfo );
+        if ( err != errSuccess )
+        {
+            continue;
+        }
+
+        printf("Mode %x: %dx%dx%d mm:%d attr:%x\n",
+               *modePtr, modeInfo.XResolution, modeInfo.YResolution,
+               modeInfo.BitsPerPixel, modeInfo.MemoryModel,
+               modeInfo.ModeAttributes);
+
+        if (line++ >= 20) {
+            printf("(Press a key to continue...)");
+            getc();
+            line = 0;
+            clearScreenRows(0, 24);
+            setCursorPosition( 0, 0, 1 );
+        }
+    }    
+    if (line != 0) {
+        printf("(Press a key to continue...)");
+        getc();
+    }
+    setActiveDisplayPage(0);
+}
+
+
 //==========================================================================
 // getVESAModeWithProperties
 //
@@ -137,7 +211,7 @@ getVESAModeWithProperties( unsigned short     width,
             continue;
         }
 
-#if 0   // debug
+#if DEBUG
         printf("Mode %x: %dx%dx%d mm:%d attr:%x\n",
                *modePtr, modeInfo.XResolution, modeInfo.YResolution,
                modeInfo.BitsPerPixel, modeInfo.MemoryModel,
@@ -215,7 +289,7 @@ getVESAModeWithProperties( unsigned short     width,
         }
         if ( modeInfo.XResolution < outModeInfo->XResolution ||
              modeInfo.YResolution < outModeInfo->YResolution ||
-             modeBitsPerPixel     < 16 )
+             modeBitsPerPixel     < outModeInfo->BitsPerPixel )
         {
             continue;  // Saved mode has more resolution.
         }
@@ -247,7 +321,7 @@ static void setupPalette( VBEPalette * p, const unsigned char * g )
 //==========================================================================
 // Simple decompressor for boot images encoded in RLE format.
 
-static char * decodeRLE( const void * rleData, int rleBlocks, int outBytes )
+char * decodeRLE( const void * rleData, int rleBlocks, int outBytes )
 {
     char *out, *cp;
 
@@ -355,56 +429,74 @@ setVESAGraphicsMode( unsigned short width,
         // Update KernBootStruct using info provided by the selected
         // VESA mode.
 
-        bootArgs->graphicsMode     = GRAPHICS_MODE;
-        bootArgs->video.v_width    = minfo.XResolution;
-        bootArgs->video.v_height   = minfo.YResolution;
-        bootArgs->video.v_depth    = minfo.BitsPerPixel;
-        bootArgs->video.v_rowBytes = minfo.BytesPerScanline;
-        bootArgs->video.v_baseAddr = VBEMakeUInt32(minfo.PhysBasePtr);
+        bootArgs->Video.v_display  = GRAPHICS_MODE;
+        bootArgs->Video.v_width    = minfo.XResolution;
+        bootArgs->Video.v_height   = minfo.YResolution;
+        bootArgs->Video.v_depth    = minfo.BitsPerPixel;
+        bootArgs->Video.v_rowBytes = minfo.BytesPerScanline;
+        bootArgs->Video.v_baseAddr = VBEMakeUInt32(minfo.PhysBasePtr);
+
     }
     while ( 0 );
 
     return err;
 }
 
+int
+convertImage( unsigned short width,
+              unsigned short height,
+              const unsigned char *imageData,
+              unsigned char **newImageData )
+{
+    int cnt;
+    unsigned char *img = 0;
+    unsigned short *img16;
+    unsigned long *img32;
+
+    switch ( VIDEO(depth) ) {
+    case 16 :
+        img16 = malloc(width * height * 2);
+        if ( !img16 ) break;
+        for (cnt = 0; cnt < (width * height); cnt++)
+            img16[cnt] = lookUpCLUTIndex(imageData[cnt], 16);
+        img = (unsigned char *)img16;
+        break;
+    
+    case 32 :
+        img32 = malloc(width * height * 4);
+        if ( !img32 ) break;
+        for (cnt = 0; cnt < (width * height); cnt++)
+            img32[cnt] = lookUpCLUTIndex(imageData[cnt], 32);
+        img = (unsigned char *)img32;
+        break;
+    
+    default :
+        img = malloc(width * height);
+        bcopy(imageData, img, width * height);
+        break;
+    }
+    *newImageData = img;
+    return 0;
+}
+
 //==========================================================================
 // drawBootGraphics
 
-static int
-drawBootGraphics( unsigned short width,
-                  unsigned short height,
-                  unsigned char  bitsPerPixel,
-                  unsigned short refreshRate )
+void
+drawBootGraphics( void )
 {
-    VBEModeInfoBlock  minfo;
-    unsigned short    mode;
-    unsigned short    vesaVersion;
-    int               err = errFuncNotSupported;
-
-    char  * appleBoot = 0;
-    short * appleBoot16;
-    long  * appleBoot32;
-    long    cnt, x, y;
+    unsigned char  * imageData = 0;
+    long    x, y;
     char  * appleBootPict;
 
     do {
-        mode = getVESAModeWithProperties( width, height, bitsPerPixel,
-                                          maColorModeBit             |
-                                          maModeIsSupportedBit       |
-                                          maGraphicsModeBit          |
-                                          maLinearFrameBufferAvailBit,
-                                          0,
-                                          &minfo, &vesaVersion );
-        if ( mode == modeEndOfList )
-        {
-            break;
-        }
-
         // Fill the background to 75% grey (same as BootX).
 
-        drawColorRectangle( 0, 0, minfo.XResolution, minfo.YResolution,
+        drawColorRectangle( 0, 0, VIDEO(width), VIDEO(height),
                             0x01 /* color index */ );
 
+        setBorderColor( 0x01 /* color index */ );
+
         appleBootPict = decodeRLE( gAppleBootPictRLE, kAppleBootRLEBlocks,
                                    kAppleBootWidth * kAppleBootHeight );
 
@@ -412,45 +504,24 @@ drawBootGraphics( unsigned short width,
 
         if ( appleBootPict )
         {
-            switch ( VIDEO(depth) )
-            {
-                case 16 :
-                    appleBoot16 = malloc(kAppleBootWidth * kAppleBootHeight * 2);
-                    if ( !appleBoot16 ) break;
-                    for (cnt = 0; cnt < (kAppleBootWidth * kAppleBootHeight); cnt++)
-                        appleBoot16[cnt] = lookUpCLUTIndex(appleBootPict[cnt], 16);
-                    appleBoot = (char *) appleBoot16;
-                    break;
-    
-                case 32 :
-                    appleBoot32 = malloc(kAppleBootWidth * kAppleBootHeight * 4);
-                    if ( !appleBoot32 ) break;
-                    for (cnt = 0; cnt < (kAppleBootWidth * kAppleBootHeight); cnt++)
-                        appleBoot32[cnt] = lookUpCLUTIndex(appleBootPict[cnt], 32);
-                    appleBoot = (char *) appleBoot32;
-                    break;
-    
-                default :
-                    appleBoot = (char *) appleBootPict;
-                    break;
-            }
+            convertImage(kAppleBootWidth, kAppleBootHeight,
+                         (unsigned char *)appleBootPict, &imageData);
 
             x = ( VIDEO(width) - kAppleBootWidth ) / 2;
             y = ( VIDEO(height) - kAppleBootHeight ) / 2 + kAppleBootOffset;
     
             // Draw the happy mac in the center of the display.
             
-            if ( appleBoot )
+            if ( imageData )
             {
                 drawDataRectangle( x, y, kAppleBootWidth, kAppleBootHeight,
-                                   appleBoot );
+                                   imageData );
+                free( imageData );
             }
-
             free( appleBootPict );
         }
-    } while (0);
 
-    return err;
+    } while (0);
 }
 
 //==========================================================================
@@ -491,7 +562,7 @@ static unsigned long lookUpCLUTIndex( unsigned char index,
 
 static void * stosl(void * dst, long val, long len)
 {
-    asm( "rep; stosl"
+    asm volatile ( "rep; stosl"
        : "=c" (len), "=D" (dst)
        : "0" (len), "1" (dst), "a" (val)
        : "memory" );
@@ -499,7 +570,7 @@ static void * stosl(void * dst, long val, long len)
     return dst;
 }
 
-static void drawColorRectangle( unsigned short x,
+void drawColorRectangle( unsigned short x,
                                 unsigned short y,
                                 unsigned short width,
                                 unsigned short height,
@@ -513,6 +584,9 @@ static void drawColorRectangle( unsigned short x,
     vram       = (char *) VIDEO(baseAddr) +
                  VIDEO(rowBytes) * y + pixelBytes * x;
 
+    width = MIN(width, VIDEO(width) - x);
+    height = MIN(height, VIDEO(height) - y);
+
     while ( height-- )
     {
         int rem = ( pixelBytes * width ) % 4;
@@ -525,24 +599,49 @@ static void drawColorRectangle( unsigned short x,
 //==========================================================================
 // drawDataRectangle
 
-static void drawDataRectangle( unsigned short  x,
-                               unsigned short  y,
-                               unsigned short  width,
-                               unsigned short  height,
-                               unsigned char * data )
+void drawDataRectangle( unsigned short  x,
+                        unsigned short  y,
+                        unsigned short  width,
+                        unsigned short  height,
+                        unsigned char * data )
 {
+    unsigned short drawWidth;
     long   pixelBytes = VIDEO(depth) / 8;
-    char * vram       = (char *) VIDEO(baseAddr) +
-                        VIDEO(rowBytes) * y + pixelBytes * x;
+    unsigned char * vram   = (unsigned char *) VIDEO(baseAddr) +
+        VIDEO(rowBytes) * y + pixelBytes * x;
 
-    while ( height-- )
-    {
-        bcopy( data, vram, width * pixelBytes );
+    drawWidth = MIN(width, VIDEO(width) - x);
+    height = MIN(height, VIDEO(height) - y);
+    while ( height-- ) {
+        bcopy( data, vram, drawWidth * pixelBytes );
         vram += VIDEO(rowBytes);
         data += width * pixelBytes;
     }
 }
 
+
+//==========================================================================
+// setBorderColor
+
+static void
+setBorderColor( unsigned char  colorIndex )
+{
+    long   color = lookUpCLUTIndex( colorIndex, 32 );
+    VBEInfoBlock     vbeInfo;
+    int              err;
+
+    // Get VBE controller info.
+
+    bzero( &vbeInfo, sizeof(vbeInfo) );
+    err = getVBEInfo( &vbeInfo );
+    if ( err != errSuccess )
+    {
+        return;
+    }
+
+}
+
+
 //==========================================================================
 // setVESATextMode
 
@@ -573,12 +672,12 @@ setVESATextMode( unsigned short cols,
     // Update KernBootStruct using info provided by the selected
     // VESA mode.
 
-    bootArgs->graphicsMode     = TEXT_MODE;
-    bootArgs->video.v_baseAddr = 0xb8000;
-    bootArgs->video.v_width    = minfo.XResolution;
-    bootArgs->video.v_height   = minfo.YResolution;
-    bootArgs->video.v_depth    = 8;
-    bootArgs->video.v_rowBytes = 0x8000;
+    bootArgs->Video.v_display  = VGA_TEXT_MODE;
+    bootArgs->Video.v_baseAddr = 0xb8000;
+    bootArgs->Video.v_width    = minfo.XResolution;
+    bootArgs->Video.v_height   = minfo.YResolution;
+    bootArgs->Video.v_depth    = 8;
+    bootArgs->Video.v_rowBytes = 0x8000;
 
     return errSuccess;  // always return success
 }
@@ -623,7 +722,7 @@ getNumberArrayFromProperty( const char *  propKey,
 //==========================================================================
 // setVideoMode
 //
-// Set the video mode to TEXT_MODE or GRAPHICS_MODE.
+// Set the video mode to VGA_TEXT_MODE or GRAPHICS_MODE.
 
 void
 setVideoMode( int mode )
@@ -638,9 +737,9 @@ setVideoMode( int mode )
         count = getNumberArrayFromProperty( kGraphicsModeKey, params, 4 );
         if ( count < 3 )
         {
-            params[0] = 1024;  // Default graphics mode is 1024x768x16.
+            params[0] = 1024;  // Default graphics mode is 1024x768x32.
             params[1] = 768;
-            params[2] = 16;
+            params[2] = 32;
         }
 
         // Map from pixel format to bits per pixel.
@@ -652,19 +751,17 @@ setVideoMode( int mode )
         err = setVESAGraphicsMode( params[0], params[1], params[2], params[3] );
         if ( err == errSuccess )
         {
-            // If this boolean is set to true, then the console driver
-            // in the kernel will show the animated color wheel on the
-            // upper left corner.
-
-            bootArgs->video.v_display = !gVerboseMode;
-            
-            if (!gVerboseMode) {
-                drawBootGraphics( params[0], params[1], params[2], params[3] );
+            if (gVerboseMode) {
+                // Tell the kernel to use text mode on a linear frame buffer display
+                bootArgs->Video.v_display = FB_TEXT_MODE;
+            } else {
+                bootArgs->Video.v_display = GRAPHICS_MODE;
+                drawBootGraphics();
             }
         }
     }
 
-    if ( (mode == TEXT_MODE) || (err != errSuccess) )
+    if ( (mode == VGA_TEXT_MODE) || (err != errSuccess) )
     {
         count = getNumberArrayFromProperty( kTextModeKey, params, 2 );
         if ( count < 2 )
@@ -674,24 +771,25 @@ setVideoMode( int mode )
         }
 
         setVESATextMode( params[0], params[1], 4 );
-        bootArgs->video.v_display = 0;
+        bootArgs->Video.v_display = VGA_TEXT_MODE;
     }
 
     currentIndicator = 0;
 }
 
 //==========================================================================
-// Return the current video mode, TEXT_MODE or GRAPHICS_MODE.
+// Return the current video mode, VGA_TEXT_MODE or GRAPHICS_MODE.
 
 int getVideoMode(void)
 {
-    return bootArgs->graphicsMode;
+    return bootArgs->Video.v_display;
 }
 
 //==========================================================================
 // Display and clear the activity indicator.
 
 static char indicator[] = {'-', '\\', '|', '/', '-', '\\', '|', '/', '\0'};
+#define kNumIndicators (sizeof(indicator) - 1)
 
 // To prevent a ridiculously fast-spinning indicator,
 // ensure a minimum of 1/9 sec between animation frames.
@@ -709,20 +807,20 @@ spinActivityIndicator( void )
     else
         lastTickTime = currentTickTime;
 
-    if ( getVideoMode() == TEXT_MODE )
+    if ( getVideoMode() == VGA_TEXT_MODE )
     {
-        string[0] = indicator[currentIndicator];
+        if (currentIndicator >= kNumIndicators) currentIndicator = 0;
+        string[0] = indicator[currentIndicator++];
         printf(string);
-        if (indicator[++currentIndicator] == 0)
-            currentIndicator = 0;
     }
 }
 
 void
 clearActivityIndicator( void )
 {
-    if ( getVideoMode() == TEXT_MODE )
+    if ( getVideoMode() == VGA_TEXT_MODE )
     {
         printf(" \b");
     }
 }
+