windows-nt/Source/XPSP1/NT/base/ntos/init/anim.c
2020-09-26 16:20:57 +08:00

425 lines
10 KiB
C

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
anim.c
Abstract:
Animated logo module.
Notes:
There are two types of logo displayed when the system starts up.
1. The old one contains both progress bar and a rotation bar displayed over the logo bitmap.
The rotation bar is a blue-white line moving across the screen from left to right.
2. The new one (starting with Whistler) contains only a rotation bar and no progress bar.
The rotation bar in this case is a set of 5 dots (file dots.bmp) moving at the bottom
of the logo from left to right.
The rotation bars in both cases are updated on timer. The client of this module will use
global variables to chose an appropriate animation for workstation, server, full-scale bitmap.
header bitmap, etc. Here are the variables:
* RotBarSelection - specifies the rotation bar to display
* LogoSelection - specifies the logo to display: is it full screen or header logo
Two routines are used by other modules to display the animation. Both routines should be
called only after the glabal flags are set.
* InbvRotBarInit - initializes a rotation bar to be drawn; this routine must be called
immediately after the logo bitmap is shown on the screen.
* InbvRotateGuiBootDisplay - is a DPC routine for rotation bar update.
PIX_IN_DOTS ROTATION BAR
First, a logo bitmap shows up on the screen. There is a line of small "empty" circles under
the logo. The dots bitmap is moving from left to right along this line:
o o o O Q @ Q O o o o o o o o o o
-------->
To avoid appearance of dots trail left of the moving dots bitmap, an "empty" circle is copied
over the trail every time the dots bitmap moves right:
Before step #N:
o o o O Q @ Q O o o o o o o o o o
After step #N:
here the
"empty" circle
is placed ______ here is the
___ | dots bitmap
| ___v___
v | |
o o o o o O Q @ Q O o o o o o o o
When the dots show up on the beginning/end of rotation bar, only a part of it is displayed, e.g.:
Q @ Q O o o o o o o o o o o o o o
or
o o o o o o o o o o o o o o O Q @
To do this, the rotation bar area on the logo bitmap is put once to the off-screen memory and
any necessary parts of it are then being copied to the display:
____________
| |
| O Q @ Q O o o o o o o o o o o o o
| \_____/
| |________________________
|__________________________ |
| __V__
V / \
o o o o o o o o o o o o o O Q @ Q
The preparation work is performed in the call to RotBarDotsBmpInit (called via InbvRotBarInit).
The bitmap drawing operations are performed in RotBarDotsBmpUpdate (called from InbvRotateGuiBootDisplay).
BLUE LINE ROTATION BAR
Blue line data is captured from the logo bitmap, placed in a buffer, and then is displayed on each DPC call
over the logo bitmap. Every time RotBarBlueLineUpdate is called, the point of split is recalculated. The part
of the line which falls before the split is displayed at the end of line on the display; the part which falls
after the split is displayed on the beginning:
In the buffer (copy of original bitmap):
ooooooooooo*********************oooooooooooooo
|
split ______|
____ point of concatenation
Displayed image: |
V
******************ooooooooooooooooooooooooo***
Author:
Peter Alschitz (petera) 08-Aug-2000 (Blue Line code moved from init.c by Steve Wood)
Revision History:
--*/
#include "ntos.h"
#include "stdlib.h"
#include "stdio.h"
#include <string.h>
#include <inbv.h>
#include "anim.h"
#include <bootvid.h>
#include "vga.h"
// bitmap-specific data for rotation bar
ROT_BAR_TYPE RotBarSelection = RB_UNSPECIFIED;
// LOGO_TYPE LogoSelection = LOGO_UNSPECIFIED;
int AnimBarPos = 0;
LONG PaletteNum;
BOOLEAN FadingIn = TRUE;
typedef enum {
PLT_UNDEFINED,
PLT_START,
PLT_CYCLE,
PLT_COMPLETE
} PLT_RBAR_STATE;
PLT_RBAR_STATE PltRotBarStatus = PLT_UNDEFINED;
#define FADE_GRADES (20)
#define FULL_PALETTE_SIZE (16)
#define FULL_PALETTE_SIZE_BYTES (FULL_PALETTE_SIZE*sizeof(RGBQUAD))
UCHAR PaletteBmp [128]; // small bitmap
PRGBQUAD PalettePtr = (PRGBQUAD)(PaletteBmp + sizeof(BITMAPINFOHEADER));
PBITMAPINFOHEADER pbih = (PBITMAPINFOHEADER)PaletteBmp;
RGBQUAD MainPalette [FULL_PALETTE_SIZE] = { {0,0,0,0}, {21,26,32,0}, {70,70,70,0}, {210,62,45,0},
{1,101,83,0}, {5,53,178,0}, {126,126,126,0}, {0,146,137,0},
{252,127,94,0}, {32,107,247,0}, {255,166,141,0}, {4,220,142,0},
{27,188,243,0}, {188,188,188,0}, {252,252,252,0}, {255,255,255,0} };
#define COLOR_BLACK 0
#define COLOR_BLUE 2
#define COLOR_DARKGRAY 4
#define COLOR_GRAY 9
#define COLOR_WHITE 15
#define COLOR_FADE_TEXT 1
UCHAR Square1[36];
UCHAR Square2[36];
UCHAR Square3[36];
VOID
RotBarInit (VOID)
/*++
Routine Description:
This routine is called to initialize 4-color rotation bar
and fade-in/fade-out effect.
Return Value:
None.
Environment:
This routine is called during initialization when BOOTVID.DLL is loaded
and Logo bitmap is being displayed on the screen.
--*/
{
pbih->biSize = sizeof (BITMAPINFOHEADER);
pbih->biWidth = 1;
pbih->biHeight = 1;
pbih->biPlanes = 1;
pbih->biBitCount = 4;
pbih->biCompression = 0; // BI_RGB
pbih->biSizeImage = 4;
pbih->biXPelsPerMeter = 2834;
pbih->biYPelsPerMeter = 2834;
pbih->biClrUsed = 0;
pbih->biClrImportant = 0;
PltRotBarStatus = PLT_START;
PaletteNum = 0;
AnimBarPos = 0;
VidScreenToBufferBlt(Square1,0,0,6,9,4);
VidScreenToBufferBlt(Square2,2+6,0,6,9,4);
VidScreenToBufferBlt(Square3,2*(2+6),0,6,9,4);
VidSolidColorFill(0,0,22,9,COLOR_BLACK);
}
VOID
FadePalette (UCHAR factor)
{
int i;
for (i=0; i<FULL_PALETTE_SIZE; i++) {
PalettePtr[i].rgbBlue = (UCHAR)(factor * MainPalette[i].rgbBlue / FADE_GRADES);
PalettePtr[i].rgbGreen = (UCHAR)(factor * MainPalette[i].rgbGreen / FADE_GRADES);
PalettePtr[i].rgbRed = (UCHAR)(factor * MainPalette[i].rgbRed / FADE_GRADES);
PalettePtr[i].rgbReserved = 0;
}
}
VOID
FadePaletteColor (UCHAR factor, UCHAR color)
{
PalettePtr[color].rgbBlue = (UCHAR)(factor * MainPalette[color].rgbBlue / FADE_GRADES);
PalettePtr[color].rgbGreen = (UCHAR)(factor * MainPalette[color].rgbGreen / FADE_GRADES);
PalettePtr[color].rgbRed = (UCHAR)(factor * MainPalette[color].rgbRed / FADE_GRADES);
PalettePtr[color].rgbReserved = 0;
}
#define COLOR_BLACK 0
#define COLOR_BLUE 2
#define COLOR_DARKGRAY 4
#define COLOR_GRAY 9
#define COLOR_WHITE 15
#define BLACK_4CLR_BAR memset (PalettePtr+12, 0, CYCLE_PALETTE_SIZE_BYTES)
#define BAR_X (267-(8*3))
#define BAR_Y (354)
#define CELL_X(num) (BAR_X+8*(AnimBarPos+num-2))
#define DRAW_CELL(num) VidBufferToScreenBlt(Square##num,CELL_X(num),BAR_Y,6,9,4)
#define BLK_CELL VidSolidColorFill(BAR_X+8*((AnimBarPos+16)%18),BAR_Y,BAR_X+8*((AnimBarPos+16)%18)+6-1,BAR_Y+9-1,COLOR_BLACK)
VOID
RotBarUpdate (VOID)
/*++
Routine Description:
This routine is called periodically to update the 4-color rotation bar.
From call to call it starts with fade-in effect, proceeds to palette-based
rotation bar animation, and then goes to fade-out effect.
Return Value:
None.
Environment:
This routine is called from a DPC and cannot be paged.
--*/
{
UCHAR color;
switch (PltRotBarStatus) {
case PLT_START:
FadePalette ((UCHAR)(PaletteNum));
FadePaletteColor (0, COLOR_FADE_TEXT); // #1 - color of fading text
if ((++PaletteNum)>=FADE_GRADES) {
PltRotBarStatus = PLT_CYCLE;
FadingIn = TRUE;
PaletteNum = 1;
}
break;
case PLT_CYCLE:
switch (AnimBarPos) {
case 0:
BLK_CELL;
break;
case 1:
DRAW_CELL(3);
break;
case 2:
DRAW_CELL(2);
DRAW_CELL(3);
break;
case 16:
DRAW_CELL(1);
DRAW_CELL(2);
BLK_CELL;
break;
case 17:
DRAW_CELL(1);
BLK_CELL;
break;
default:
DRAW_CELL(1);
DRAW_CELL(2);
DRAW_CELL(3);
if (AnimBarPos>3)
BLK_CELL;
}
AnimBarPos++;
if ((AnimBarPos) > 17)
AnimBarPos = 0;
break;
case PLT_UNDEFINED:
case PLT_COMPLETE:
return;
}
if (InbvGetDisplayState() == INBV_DISPLAY_STATE_OWNED) {
VidBitBlt(PaletteBmp, 0, 480);
}
}
VOID
InbvRotBarInit ()
/*++
Routine Description:
This routine is called to initialize rotation bar.
The choice between rotation bar types is according to
global variable RotBarSelection.
Return Value:
None.
Environment:
This routine is called during initialization when BOOTVID.DLL
is loaded and Logo bitmap is being displayed on the screen.
--*/
{
switch (RotBarSelection) {
case RB_SQUARE_CELLS:
RotBarInit();
break;
case RB_UNSPECIFIED:
default:
break;
}
}
VOID
InbvRotateGuiBootDisplay(
IN PVOID Context
)
/*++
Routine Description:
This routine is called periodically to update the guiboot display.
It makes its choice between calling different rotation bar update
routines according to global variable RotBarSelection.
Return Value:
None.
Environment:
This routine is called from a DPC and cannot be paged.
--*/
{
LARGE_INTEGER Delay;
Delay.QuadPart = -10 * 1000 * 80; // 100 milliseconds
do {
KeDelayExecutionThread(KernelMode, FALSE, &Delay);
InbvAcquireLock();
if (InbvGetDisplayState() == INBV_DISPLAY_STATE_OWNED) {
switch(RotBarSelection) {
case RB_SQUARE_CELLS:
RotBarUpdate();
break;
case RB_UNSPECIFIED:
default:
break;
}
}
InbvReleaseLock();
} while (InbvCheckDisplayOwnership());
PsTerminateSystemThread(STATUS_SUCCESS);
}
VOID
FinalizeBootLogo(VOID)
{
InbvAcquireLock();
if (InbvGetDisplayState() == INBV_DISPLAY_STATE_OWNED)
VidSolidColorFill(0,0,639,479, COLOR_BLACK);
PltRotBarStatus = PLT_COMPLETE;
InbvReleaseLock();
}