logo.c revision 173b1a4f06b7825a2704180c17b7ee0f1f7658f9
#define COMPRESS_NONE 0
#define COMPRESS_RLE8 1
#define COMPRESS_RLE4 2
#define BMP_HEADER_OS21 12
#define BMP_HEADER_OS22 64
#define BMP_HEADER_WIN3 40
#define WAIT_HZ 64
#define WAIT_MS 16
#define F12_SCAN_CODE 0x86
typedef struct
{
} RGBPAL;
/* BMP File Format Bitmap Header. */
typedef struct
{
} BMPINFO;
/* OS/2 1.x Information Header Format. */
typedef struct
{
} OS2HDR;
/* OS/2 2.0 Information Header Format. */
typedef struct
{
} OS22HDR;
/* Windows 3.x Information Header Format. */
typedef struct
{
} WINHDR;
// Logo settings header
typedef struct
{
} LOGOHDR;
// Width and height of the "Press F12 to select boot device." bitmap. Anything
// that exceeds the limit of F12BootText below is filled with background.
#define F12BOOTTEXTWIDTH 284
#define F12BOOTTEXTHEIGHT 13
// "Press F12 to select boot device." bitmap.
Bit8u F12BootText[] = {
0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0x0C, 0x3E, 0x00, 0x20, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x20, 0x00, 0x70, 0x00, 0x00, 0x00,
0x04, 0x00, 0x70, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00,
0x00, 0x00, 0x00, 0x98, 0xE1, 0x30, 0x06, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
0xC0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x06, 0x00, 0x00, 0x60, 0x00, 0x00, 0x06,
0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0x11, 0x0F, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00,
0x30, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x60, 0x66, 0x87, 0x0F, 0x1F, 0x3E, 0x00, 0x58, 0xC0, 0x00, 0x03,
0xC0, 0x0F, 0x1F, 0x00, 0x7C, 0xF8, 0xC0, 0xE0, 0xC3, 0xC7, 0x0F, 0x00, 0x1E,
0x7C, 0xF8, 0xF8, 0x01, 0x80, 0x87, 0x8F, 0x61, 0x1C, 0x7C, 0xF8, 0x00, 0x3E,
0xDC, 0x8C, 0x19, 0x33, 0x06, 0x80, 0x07, 0x0C, 0x18, 0x00, 0x30, 0x18, 0x03,
0x60, 0xCC, 0x18, 0x0C, 0x63, 0xC6, 0x30, 0x00, 0x60, 0x63, 0xCC, 0x18, 0x06,
0x00, 0x6C, 0x8C, 0x19, 0x86, 0x61, 0xCC, 0x18, 0x60, 0xC0, 0xCC, 0x1F, 0x03,
0x06, 0x00, 0x58, 0xC0, 0xC0, 0x00, 0x00, 0x83, 0x31, 0x00, 0x0C, 0xFC, 0xC1,
0xF0, 0x67, 0x00, 0x03, 0x00, 0x66, 0xC6, 0x8C, 0x61, 0x00, 0x60, 0xC6, 0x9F,
0x61, 0x18, 0x06, 0xFC, 0x01, 0x06, 0x0C, 0x0C, 0xE0, 0xC0, 0x01, 0x80, 0x01,
0x0C, 0x06, 0x00, 0x30, 0x18, 0x03, 0x80, 0xC3, 0x00, 0x0C, 0x03, 0x06, 0x30,
0x00, 0x60, 0x66, 0xCC, 0x18, 0x06, 0x00, 0x66, 0x0C, 0x18, 0x86, 0x61, 0xC0,
0x00, 0x60, 0xC0, 0xC0, 0x00, 0x18, 0x30, 0x00, 0x18, 0xC0, 0x30, 0x00, 0x00,
0x83, 0x31, 0x00, 0x60, 0x0C, 0xC0, 0x30, 0x60, 0x00, 0x03, 0x00, 0x66, 0xC6,
0x8C, 0x61, 0x00, 0x60, 0xC6, 0x00, 0x33, 0x18, 0x06, 0x0C, 0x00, 0x06, 0x0C,
0x8C, 0x19, 0x33, 0x06, 0x80, 0x01, 0x0C, 0x63, 0x00, 0xB0, 0x19, 0x03, 0x60,
0xCC, 0x18, 0x0C, 0x63, 0xC6, 0xB0, 0x01, 0x60, 0x66, 0xCC, 0x18, 0x36, 0x00,
0x66, 0x8C, 0xE1, 0x81, 0x61, 0xCC, 0x18, 0xFC, 0xE0, 0x81, 0x0F, 0x1F, 0x3E,
0x00, 0x3C, 0xF0, 0xF3, 0x07, 0x00, 0x0E, 0x1F, 0x00, 0x7C, 0xF8, 0xE0, 0xE1,
0xC3, 0x07, 0x0E, 0x00, 0x3E, 0x7C, 0xF8, 0xC0, 0x01, 0xC0, 0x8D, 0x0F, 0x0C,
0x3C, 0x7C, 0xF8, 0xC0
};
static unsigned char get_mode();
static void set_mode();
static void write_pixel();
/**
* Get current video mode (VGA).
* @returns Video mode.
*/
unsigned char get_mode()
{
int #0x10
}
/**
* Set video mode (VGA).
* @params New video mode.
*/
{
int #0x10
}
/**
* Set VESA video mode.
* @params New video mode.
*/
{
int #0x10
}
/**
* Check for keystroke.
* @returns True if keystroke available, False if not.
*/
{
int #0x16
done:
}
/**
* Get keystroke.
* @returns BIOS scan code.
*/
{
int #0x16
}
void wait_init()
{
// The default is 18.2 ticks per second (~55ms tick interval).
// Set the timer to 16ms ticks (64K / (Hz / (PIT_HZ / 64K)) = count).
// 0x10000 / (1000 / (1193182 / 0x10000)) = 1193 (0x04a9)
// 0x10000 / ( 128 / (1193182 / 0x10000)) = 9321 (0x2469)
// 0x10000 / ( 64 / (1193182 / 0x10000)) = 18643 (0x48d3)
}
void wait_uninit()
{
/* Restore the timer to the default 18.2Hz. */
/*
* Reinitialize the tick and rollover counts since we've
* screwed them up by running the timer at WAIT_HZ for a while.
*/
}
/**
* Waits (sleeps) for the given number of ticks.
* Checks for keystroke.
*
* @returns BIOS scan code if available, 0 if not.
* @param ticks Number of ticks to sleep.
* @param stop_on_key Whether to stop immediately upon keypress.
*/
{
long ticks_to_wait, delta;
Bit32u prev_ticks, t;
/*
* The 0:046c wraps around at 'midnight' according to a 18.2Hz clock.
* We also have to be careful about interrupt storms.
*/
do
{
if (t > prev_ticks)
{
ticks_to_wait -= delta;
}
else if (t < prev_ticks)
ticks_to_wait -= t; /* wrapped */
prev_ticks = t;
if (check_for_keystroke())
{
scan_code = get_keystroke();
if (stop_on_key)
return scan_code;
}
} while (ticks_to_wait > 0);
return scan_code;
}
void write_pixel(x,y,color)
unsigned short x;
unsigned short y;
unsigned char color;
{
int #0x10
}
{
Bit16u i;
palette = 0;
for (i = 0; i < size; i++)
{
bmp_off++;
bmp_off++;
bmp_off++;
if (type != BMP_HEADER_OS21)
{
// Skip 4th byte
bmp_off++;
}
*palette++;
}
}
void set_dark_palette(palette_size)
{
Bit16u i;
// Set bitmap palette (dark)
for (i = 0; i < palette_size; i++)
{
outb(0x03c8, i);
outb(0x03c9, 0);
outb(0x03c9, 0);
outb(0x03c9, 0);
}
}
{
Bit16u i;
palette = 0;
for (i = 0; i < palette_size; i++)
{
Bit8u b;
outb(0x03c8, i);
*palette++;
}
}
/**
* Fade in and check for keystroke.
* @returns BIOS scan code if available, 0 if not.
*/
{
Bit16u i, j;
// Fade in
for (i = 0; i < 0x3F; i++)
{
palette = 0;
for (j = 0; j < palette_size; j++)
{
Bit8u r, g, b;
if (r > 0 && r >= i) r = i;
if (g > 0 && g >= i) g = i;
if (b > 0 && b >= i) b = i;
outb(0x03c8, j);
outb(0x03c9, r);
outb(0x03c9, g);
outb(0x03c9, b);
*palette++;
}
if (scode)
}
return scan_code;
}
/**
* Fade out and check for keystroke.
* @returns BIOS scan code if available, 0 if not.
*/
{
Bit16u i, j;
// Fade out
for (i = 0x3F; i > 0; i--)
{
palette = 0;
for (j = 0; j < palette_size; j++)
{
Bit8u r, g, b;
if (r > 0 && r >= i) r = i;
if (g > 0 && g >= i) g = i;
if (b > 0 && b >= i) b = i;
outb(0x03c8, j);
outb(0x03c9, r);
outb(0x03c9, g);
outb(0x03c9, b);
*palette++;
}
if (scode)
}
return scan_code;
}
void vesa_set_bank(bank)
{
int #0x10
}
#define VID_SEG 0xA000
#define ROM_SEG 0xD000
#define TMP_SEG 0x1000
void show_logo()
{
Bit8u c;
// Set PIT to 1ms ticks
wait_init();
is_logo_failed = 0;
// Switch to ROM bank 0
logo_hdr = 0;
logo_hdr_size = sizeof(LOGOHDR);
// Get main signature
if (tmp != 0x66BB)
goto done;
// Get options
// Is Logo disabled?
goto done;
// Set offset of bitmap header
// Check bitmap ID
{
goto error;
}
else
{
int x, y;
// Check the size of the information header that indicates
// the structure type
{
clr_used = 0;
}
else
{
}
else
{
}
else
goto error;
// Test some bitmap fields
goto error;
if (planes != 1)
goto error;
goto error;
if (clr_used > 256)
goto error;
// Bitmap processing
if (compr != COMPRESS_NONE)
goto error;
// Screen size
scr_width = 640;
scr_height = 480;
// Center of screen
// Read palette
if (hdr_size == BMP_HEADER_OS21)
{
}
else
{
if (clr_used)
else
}
// Get current video mode
// Set video mode #0x101 640x480x8bpp
vesa_set_mode(0x101);
if (is_fade_in)
else
// 0 bank
vesa_set_bank(0);
// Show bitmap
switch(depth)
{
case 4:
// Compute padding bytes
pad_bytes = 0;
pad_bytes = 3;
pad_bytes = 2;
else
pad_bytes = 1;
// For 4 bits per pixel, each byte is two pixels.
// The upper half go to the first pixel,
// and the lower half to the second.
for (y = height; y > 0; y--)
{
Bit8u z;
for (x = 0; x < width; x += 2)
{
Bit8u c;
if (bmp_data == 0xffff)
{
bmp_data = 0;
}
for (z = 0; z < 2; z++)
{
offset = (((Bit32u)start_y + (Bit32u)y) * (Bit32u)scr_width) + ((Bit32u)start_x + (Bit32u)x + (Bit32u)z);
{
}
if (z & 1)
color = c & 0xF;
else
}
}
for (z = 0; z < pad_bytes; z++)
{
if (++bmp_data == 0xffff)
{
bmp_data = 0;
}
}
}
break;
case 8:
// Compute padding bytes
// For 8 bits per pixel, each byte is one pixel.
for (y = height; y > 0; y--)
{
Bit8u z;
for (x = 0; x < width; x++)
{
Bit8u c, z;
if (bmp_data == 0xffff)
{
bmp_data = 0;
}
{
}
}
for (z = 0; z < pad_bytes; z++)
{
if (++bmp_data == 0xffff)
{
bmp_data = 0;
}
}
}
break;
#if 0 // 24bpp bitmaps are unsupported
case 24:
// Compute padding bytes
// For 24 bits per pixel it's RGB structure.
for (y = height; y > 0; y--)
{
Bit8u z;
for (x = 0; x < width; x++)
{
for (z = 0; z < 3; z++)
{
if (bmp_data == 0xffff)
{
bmp_data = 0;
}
offset = (((Bit32u)start_y + (Bit32u)y) * (Bit32u)scr_width*3) + (((Bit32u)start_x + (Bit32u)x) * (Bit32u)3 + z);
{
}
}
}
for (z = 0; z < pad_bytes; z++)
{
if (++bmp_data == 0xffff)
{
bmp_data = 0;
}
}
}
break;
#endif
}
// If Setup menu enabled
{
// Get the brightest and the darkest palette indexes
for (i = 0; i < palette_size; i++)
{
Bit8u r, g, b;
*palette++;
}
// 0 bank
vesa_set_bank(0);
// Top-left corner of screen
start_x = 340;
start_y = 450;
// Image size
bmp_data = j = 0;
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x++)
{
if (!j)
{
if (bmp_data < sizeof(F12BootText))
else
c = 0;
}
{
}
pix_idx = c & 1;
c >>= 1;
if (pix_idx)
else
if (j++ >= 7) j = 0;
}
}
}
// Fade in
if (is_fade_in)
{
}
// Wait (interval in milliseconds)
// Fade out
if (is_fade_out)
{
}
}
// Clear video memory
#if 0 // Really need to clear VESA memory?
for (i = 0; i < 0x9600; i += 2)
{
write_word(VID_SEG, i, 0);
}
#endif
goto done;
if (!is_logo_failed)
{
is_logo_failed = 1;
logo_hdr_size = 0;
// Switch to ROM bank 255 (default logo)
goto show_bmp;
}
done:
// Clear forced boot drive setting.
// Don't restore previous video mode
// The default text mode should be set up. (defect #1235)
set_mode(0x0003);
// If Setup menu enabled
if (uBootMenu)
{
// If the graphics logo disabled
{
int i;
if (uBootMenu == 2)
printf("Press F12 to select boot device.");
// if the user has pressed F12 don't wait here
if ( scan_code != F12_SCAN_CODE )
{
// Wait for timeout or keystroke
}
}
// If F12 pressed, show boot menu
if (scan_code == F12_SCAN_CODE)
{
// Hide cursor, clear screen and move cursor to starting position
int #0x10
int #0x10
int #0x10
// Show menu
printf("\n");
printf("VirtualBox temporary boot device selection\n");
printf("\n");
printf(" 1) Floppy\n");
printf(" 2) Hard Disk\n");
printf(" 3) CD-ROM\n");
printf(" 4) LAN\n\n");
printf(" 0) Continue booting\n");
// Wait for keystroke
do
{
} while (scan_code == 0);
// Change first boot device code to selected one
{
}
// Switch to text mode. Clears screen and enables cursor again.
set_mode(0x0003);
}
}
// Restore PIT ticks
wait_uninit();
return;
}
void delay_boot(secs)
{
Bit16u i;
if (!secs)
return;
// Set PIT to 1ms ticks
wait_init();
for (i = secs; i > 0; i--)
{
printf(" %d", i);
}
printf("\n");
// Restore PIT ticks
wait_uninit();
}