#include <arch/cpu.h>
#include <boot/stage2.h>
#include <boot/platform.h>
#include <boot/menu.h>
#include <boot/kernel_args.h>
#include <boot/platform/generic/video.h>
#include <boot/platform/generic/video_blitter.h>
#include <boot/images.h>
#include <boot/platform/generic/video_splash.h>
#include <stdio.h>
#include <stdlib.h>
#include <zlib.h>
#ifdef TRACE_VIDEO
# define TRACE(x) dprintf x
#else
# define TRACE(x) ;
#endif
static status_t
uncompress(const uint8 compressed[], unsigned int compressedSize,
uint8* uncompressed, unsigned int uncompressedSize)
{
if (compressedSize == 0 || uncompressedSize == 0)
return B_BAD_VALUE;
z_stream zStream = {
(Bytef*)compressed,
compressedSize,
0,
(Bytef*)uncompressed,
uncompressedSize,
0,
0,
0,
Z_NULL,
Z_NULL,
Z_NULL,
0,
0,
0
};
int zlibError = inflateInit(&zStream);
if (zlibError != Z_OK)
return B_ERROR;
status_t status = B_OK;
zlibError = inflate(&zStream, Z_FINISH);
if (zlibError != Z_STREAM_END) {
if (zlibError == Z_OK)
status = B_BUFFER_OVERFLOW;
else
status = B_ERROR;
}
zlibError = inflateEnd(&zStream);
if (zlibError != Z_OK && status == B_OK)
status = B_ERROR;
if (status == B_OK && zStream.total_out != uncompressedSize)
status = B_ERROR;
return status;
}
extern "C" void
video_blit_image(addr_t frameBuffer, const uint8 *data,
uint16 width, uint16 height, uint16 imageWidth, uint16 left, uint16 top)
{
if (gKernelArgs.frame_buffer.depth == 4) {
platform_blit4(frameBuffer, data, width, height,
imageWidth, left, top);
} else {
BlitParameters params;
params.from = data;
params.fromWidth = imageWidth;
params.fromLeft = params.fromTop = 0;
params.fromRight = width;
params.fromBottom = height;
params.to = (uint8*)frameBuffer;
params.toBytesPerRow = gKernelArgs.frame_buffer.bytes_per_row;
params.toLeft = left;
params.toTop = top;
blit(params, gKernelArgs.frame_buffer.depth);
}
}
extern "C" status_t
video_display_splash(addr_t frameBuffer)
{
if (!gKernelArgs.frame_buffer.enabled)
return B_NO_INIT;
addr_t pos = 0;
addr_t size = min_c(gKernelArgs.frame_buffer.width
* gKernelArgs.frame_buffer.height * 4u,
gKernelArgs.frame_buffer.physical_buffer.size);
if (size >= 64) {
for (addr_t align = (8 - (frameBuffer & 7)) & 7; pos < align; pos++)
*(char*)(frameBuffer + pos) = 0;
for (addr_t alignSize = size - 8; pos < alignSize; pos +=8) {
*(uint32*)(frameBuffer + pos) = 0;
*(uint32*)(frameBuffer + pos + 4) = 0;
}
}
for (; pos < size; pos++)
*(char*)(frameBuffer + pos) = 0;
uint8* uncompressedLogo = NULL;
unsigned int uncompressedSize = kSplashLogoWidth * kSplashLogoHeight;
switch (gKernelArgs.frame_buffer.depth) {
case 8:
platform_set_palette(k8BitPalette);
uncompressedLogo = (uint8*)kernel_args_malloc(uncompressedSize);
if (uncompressedLogo == NULL)
return B_NO_MEMORY;
uncompress(kSplashLogo8BitCompressedImage,
sizeof(kSplashLogo8BitCompressedImage), uncompressedLogo,
uncompressedSize);
break;
default:
uncompressedSize *= 3;
uncompressedLogo = (uint8*)kernel_args_malloc(uncompressedSize);
if (uncompressedLogo == NULL)
return B_NO_MEMORY;
uncompress(kSplashLogo24BitCompressedImage,
sizeof(kSplashLogo24BitCompressedImage), uncompressedLogo,
uncompressedSize);
break;
}
int width, height, x, y;
compute_splash_logo_placement(gKernelArgs.frame_buffer.width, gKernelArgs.frame_buffer.height,
width, height, x, y);
video_blit_image(frameBuffer, uncompressedLogo, width, height,
kSplashLogoWidth, x, y);
kernel_args_free(uncompressedLogo);
const uint8* lowerHalfIconImage;
uncompressedSize = kSplashIconsWidth * kSplashIconsHeight;
const uint16 iconsHalfHeight = kSplashIconsHeight / 2;
switch (gKernelArgs.frame_buffer.depth) {
case 8:
gKernelArgs.boot_splash
= (uint8*)kernel_args_malloc(uncompressedSize);
if (gKernelArgs.boot_splash == NULL)
return B_NO_MEMORY;
uncompress(kSplashIcons8BitCompressedImage,
sizeof(kSplashIcons8BitCompressedImage),
gKernelArgs.boot_splash, uncompressedSize);
lowerHalfIconImage = (uint8 *)gKernelArgs.boot_splash
+ (kSplashIconsWidth * iconsHalfHeight);
break;
default:
uncompressedSize *= 3;
gKernelArgs.boot_splash
= (uint8*)kernel_args_malloc(uncompressedSize);
if (gKernelArgs.boot_splash == NULL)
return B_NO_MEMORY;
uncompress(kSplashIcons24BitCompressedImage,
sizeof(kSplashIcons24BitCompressedImage),
gKernelArgs.boot_splash, uncompressedSize);
lowerHalfIconImage = (uint8 *)gKernelArgs.boot_splash
+ (kSplashIconsWidth * iconsHalfHeight) * 3;
break;
}
compute_splash_icons_placement(gKernelArgs.frame_buffer.width, gKernelArgs.frame_buffer.height,
width, height, x, y);
video_blit_image(frameBuffer, lowerHalfIconImage, width, height,
kSplashIconsWidth, x, y);
return B_OK;
}