1 /* 2 * Copyright 2004-2009, Axel Dörfler, axeld@pinc-software.de. 3 * Copyright 2008, Stephan Aßmus <superstippi@gmx.de> 4 * Copyright 2008, Philippe Saint-Pierre <stpere@gmail.com> 5 * Distributed under the terms of the MIT License. 6 */ 7 8 9 #include <arch/cpu.h> 10 #include <boot/stage2.h> 11 #include <boot/platform.h> 12 #include <boot/menu.h> 13 #include <boot/kernel_args.h> 14 #include <boot/platform/generic/video.h> 15 #include <boot/images.h> 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <string.h> 20 21 #include <zlib.h> 22 23 24 //#define TRACE_VIDEO 25 #ifdef TRACE_VIDEO 26 # define TRACE(x) dprintf x 27 #else 28 # define TRACE(x) ; 29 #endif 30 31 32 static status_t 33 uncompress(const uint8 compressed[], unsigned int compressedSize, 34 uint8* uncompressed, unsigned int uncompressedSize) 35 { 36 if (compressedSize == 0 || uncompressedSize == 0) 37 return B_BAD_VALUE; 38 39 // prepare zlib stream 40 z_stream zStream = { 41 (Bytef*)compressed, // next_in 42 compressedSize, // avail_in 43 0, // total_in 44 (Bytef*)uncompressed, // next_out 45 uncompressedSize, // avail_out 46 0, // total_out 47 0, // msg 48 0, // state 49 Z_NULL, // zalloc (kernel_args_malloc?) 50 Z_NULL, // zfree (kernel_args_free?) 51 Z_NULL, // opaque 52 0, // data_type 53 0, // adler 54 0 // reserved 55 }; 56 57 int zlibError = inflateInit(&zStream); 58 if (zlibError != Z_OK) 59 return B_ERROR; // TODO: translate zlibError 60 61 // inflate 62 status_t status = B_OK; 63 zlibError = inflate(&zStream, Z_FINISH); 64 if (zlibError != Z_STREAM_END) { 65 if (zlibError == Z_OK) 66 status = B_BUFFER_OVERFLOW; 67 else 68 status = B_ERROR; // TODO: translate zlibError 69 } 70 71 // clean up 72 zlibError = inflateEnd(&zStream); 73 if (zlibError != Z_OK && status == B_OK) 74 status = B_ERROR; // TODO: translate zlibError 75 76 if (status == B_OK && zStream.total_out != uncompressedSize) 77 status = B_ERROR; 78 79 return status; 80 } 81 82 83 extern "C" status_t 84 video_display_splash(addr_t frameBuffer) 85 { 86 if (!gKernelArgs.frame_buffer.enabled) 87 return B_NO_INIT; 88 89 // clear the video memory 90 memset((void*)frameBuffer, 0, 91 gKernelArgs.frame_buffer.physical_buffer.size); 92 93 uint8* uncompressedLogo = NULL; 94 unsigned int uncompressedSize = kSplashLogoWidth * kSplashLogoHeight; 95 switch (gKernelArgs.frame_buffer.depth) { 96 case 8: 97 platform_set_palette(k8BitPalette); 98 uncompressedLogo = (uint8*)kernel_args_malloc(uncompressedSize); 99 if (uncompressedLogo == NULL) 100 return B_NO_MEMORY; 101 102 uncompress(kSplashLogo8BitCompressedImage, 103 sizeof(kSplashLogo8BitCompressedImage), uncompressedLogo, 104 uncompressedSize); 105 break; 106 default: // 24 bits is assumed here 107 uncompressedSize *= 3; 108 uncompressedLogo = (uint8*)kernel_args_malloc(uncompressedSize); 109 if (uncompressedLogo == NULL) 110 return B_NO_MEMORY; 111 112 uncompress(kSplashLogo24BitCompressedImage, 113 sizeof(kSplashLogo24BitCompressedImage), uncompressedLogo, 114 uncompressedSize); 115 break; 116 } 117 118 // TODO: support 4-bit indexed version of the images! 119 120 // render splash logo 121 uint16 iconsHalfHeight = kSplashIconsHeight / 2; 122 123 int width = min_c(kSplashLogoWidth, gKernelArgs.frame_buffer.width); 124 int height = min_c(kSplashLogoHeight + iconsHalfHeight, 125 gKernelArgs.frame_buffer.height); 126 int placementX = max_c(0, min_c(100, kSplashLogoPlacementX)); 127 int placementY = max_c(0, min_c(100, kSplashLogoPlacementY)); 128 129 int x = (gKernelArgs.frame_buffer.width - width) * placementX / 100; 130 int y = (gKernelArgs.frame_buffer.height - height) * placementY / 100; 131 132 height = min_c(kSplashLogoHeight, gKernelArgs.frame_buffer.height); 133 switch (gKernelArgs.frame_buffer.depth) { 134 case 8: 135 break; 136 } 137 video_blit_image(frameBuffer, uncompressedLogo, width, height, 138 kSplashLogoWidth, x, y); 139 140 kernel_args_free(uncompressedLogo); 141 142 const uint8* lowerHalfIconImage; 143 uncompressedSize = kSplashIconsWidth * kSplashIconsHeight; 144 switch (gKernelArgs.frame_buffer.depth) { 145 case 8: 146 // pointer into the lower half of the icons image data 147 gKernelArgs.boot_splash 148 = (uint8*)kernel_args_malloc(uncompressedSize); 149 if (gKernelArgs.boot_splash == NULL) 150 return B_NO_MEMORY; 151 uncompress(kSplashIcons8BitCompressedImage, 152 sizeof(kSplashIcons8BitCompressedImage), 153 gKernelArgs.boot_splash, uncompressedSize); 154 lowerHalfIconImage = gKernelArgs.boot_splash 155 + (kSplashIconsWidth * iconsHalfHeight); 156 break; 157 default: // 24bits is assumed here 158 uncompressedSize *= 3; 159 // pointer into the lower half of the icons image data 160 gKernelArgs.boot_splash 161 = (uint8*)kernel_args_malloc(uncompressedSize); 162 if (gKernelArgs.boot_splash == NULL) 163 return B_NO_MEMORY; 164 uncompress(kSplashIcons24BitCompressedImage, 165 sizeof(kSplashIcons24BitCompressedImage), 166 gKernelArgs.boot_splash, uncompressedSize); 167 lowerHalfIconImage = gKernelArgs.boot_splash 168 + (kSplashIconsWidth * iconsHalfHeight) * 3; 169 break; 170 } 171 172 // render initial (grayed out) icons 173 // the grayed out version is the lower half of the icons image 174 175 width = min_c(kSplashIconsWidth, gKernelArgs.frame_buffer.width); 176 height = min_c(kSplashLogoHeight + iconsHalfHeight, 177 gKernelArgs.frame_buffer.height); 178 placementX = max_c(0, min_c(100, kSplashIconsPlacementX)); 179 placementY = max_c(0, min_c(100, kSplashIconsPlacementY)); 180 181 x = (gKernelArgs.frame_buffer.width - width) * placementX / 100; 182 y = kSplashLogoHeight + (gKernelArgs.frame_buffer.height - height) 183 * placementY / 100; 184 185 height = min_c(iconsHalfHeight, gKernelArgs.frame_buffer.height); 186 video_blit_image(frameBuffer, lowerHalfIconImage, width, height, 187 kSplashIconsWidth, x, y); 188 return B_OK; 189 } 190 191 192 193