1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519 |
- /*++
- Copyright (c) 2013 Minoca Corp. All Rights Reserved
- Module Name:
- textvid.c
- Abstract:
- This module implements a fake firmware interface for ARM systems that have
- no firmware services layer.
- Author:
- Evan Green 30-Jan-2013
- Environment:
- Boot and Kernel
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include "basevidp.h"
- //
- // --------------------------------------------------------------------- Macros
- //
- //
- // This routine converts a color value from software form into its physical
- // form.
- //
- #define TRANSLATE_COLOR(_Value, _Translation) \
- (((SHIFT_COLOR(_Value, _Translation.RedShift) & _Translation.RedMask)) | \
- ((SHIFT_COLOR(_Value, _Translation.GreenShift) & \
- _Translation.GreenMask)) | \
- ((SHIFT_COLOR(_Value, _Translation.BlueShift) & _Translation.BlueMask)))
- //
- // This routine shifts a value left by the given amount (right if the shift is
- // negative).
- //
- #define SHIFT_COLOR(_Value, _Shift) \
- (((_Shift) >= 0) ? ((_Value) << (_Shift)) : ((_Value) >> -(_Shift)))
- //
- // This macro just flips red and blue.
- //
- #define SWIZZLE_RED_BLUE(_Value) \
- ((((_Value) & 0x000000FF) << 16) | (((_Value) & 0x00FF0000) >> 16) | \
- ((_Value) & 0x0000FF00))
- //
- // This macro converts a foreground and background color into attributes
- // (upper 8 of 16 bits) for BIOS text mode.
- //
- #define BIOS_TEXT_ATTRIBUTES(_Foreground, _Background) \
- ((((_Foreground) & 0xF) << 8) | (((_Background) & 0x7) << 12))
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- VOID
- VidpConvertPalette (
- PBASE_VIDEO_CONTEXT Context,
- PBASE_VIDEO_PALETTE Palette,
- PBASE_VIDEO_PALETTE PhysicalPalette
- );
- VOID
- VidpPrintCharacter (
- PBASE_VIDEO_CONTEXT Context,
- ULONG XCoordinate,
- ULONG YCoordinate,
- PBASE_VIDEO_CHARACTER Character
- );
- VOID
- VidpConvertIntegerToString (
- LONG Integer,
- PSTR String,
- ULONG Base
- );
- ULONG
- VidpFindHighestBitSet (
- ULONG Value
- );
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- typedef struct _COLOR_TRANSLATION {
- LONG RedShift;
- ULONG RedMask;
- LONG GreenShift;
- ULONG GreenMask;
- LONG BlueShift;
- ULONG BlueMask;
- } COLOR_TRANSLATION, *PCOLOR_TRANSLATION;
- //
- // -------------------------------------------------------------------- Globals
- //
- //
- // Store the default palette to use.
- //
- BASE_VIDEO_PALETTE VidDefaultPalette = {
- {
- BASE_VIDEO_COLOR_RGB(255, 240, 165),
- BASE_VIDEO_COLOR_RGB(0, 0, 0),
- BASE_VIDEO_COLOR_RGB(134, 37, 23),
- BASE_VIDEO_COLOR_RGB(37, 188, 36),
- BASE_VIDEO_COLOR_RGB(173, 173, 39),
- BASE_VIDEO_COLOR_RGB(50, 27, 184),
- BASE_VIDEO_COLOR_RGB(134, 30, 134),
- BASE_VIDEO_COLOR_RGB(47, 204, 197),
- BASE_VIDEO_COLOR_RGB(203, 204, 206),
- },
- {
- BASE_VIDEO_COLOR_RGB(255, 255, 170),
- BASE_VIDEO_COLOR_RGB(142, 145, 149),
- BASE_VIDEO_COLOR_RGB(255, 120, 100),
- BASE_VIDEO_COLOR_RGB(49, 231, 34),
- BASE_VIDEO_COLOR_RGB(234, 236, 35),
- BASE_VIDEO_COLOR_RGB(70, 160, 255),
- BASE_VIDEO_COLOR_RGB(240, 100, 240),
- BASE_VIDEO_COLOR_RGB(20, 240, 240),
- BASE_VIDEO_COLOR_RGB(233, 235, 237),
- },
- BASE_VIDEO_COLOR_RGB(19, 119, 61),
- BASE_VIDEO_COLOR_RGB(19, 119, 61),
- BASE_VIDEO_COLOR_RGB(255, 240, 165),
- BASE_VIDEO_COLOR_RGB(142, 40, 0),
- };
- //
- // Store a pointer to the default font to use.
- //
- PBASE_VIDEO_FONT VidDefaultFont = &VidFontPs2Thin48x16;
- //
- // Store the conversion between ANSI colors and BIOS text attribute numbers.
- //
- const UCHAR VidTextModeColors[AnsiColorCount] = {7, 0, 4, 2, 6, 1, 5, 3, 7};
- //
- // ------------------------------------------------------------------ Functions
- //
- KSTATUS
- VidInitialize (
- PBASE_VIDEO_CONTEXT Context,
- PSYSTEM_RESOURCE_FRAME_BUFFER FrameBuffer
- )
- /*++
- Routine Description:
- This routine initializes the base video library.
- Arguments:
- Context - Supplies a pointer to the video context to initialize.
- FrameBuffer - Supplies a pointer to the frame buffer parameters.
- Return Value:
- Status code.
- --*/
- {
- KSTATUS Status;
- Context->Mode = FrameBuffer->Mode;
- Context->FrameBuffer = FrameBuffer->Header.VirtualAddress;
- Context->Width = FrameBuffer->Width;
- Context->Height = FrameBuffer->Height;
- Context->PixelsPerScanLine = FrameBuffer->PixelsPerScanLine;
- Context->BitsPerPixel = FrameBuffer->BitsPerPixel;
- Context->RedMask = FrameBuffer->RedMask;
- Context->GreenMask = FrameBuffer->GreenMask;
- Context->BlueMask = FrameBuffer->BlueMask;
- ASSERT((Context->Mode != BaseVideoInvalidMode) &&
- (Context->FrameBuffer != NULL) &&
- (Context->Width != 0) &&
- (Context->Height != 0) &&
- (Context->PixelsPerScanLine >= Context->Width) &&
- (Context->BitsPerPixel != 0));
- ASSERT((Context->Mode != BaseVideoModeFrameBuffer) ||
- ((Context->RedMask != 0) &&
- (Context->GreenMask != 0) &&
- (Context->BlueMask != 0)));
- RtlCopyMemory(&(Context->Palette),
- &VidDefaultPalette,
- sizeof(BASE_VIDEO_PALETTE));
- VidpConvertPalette(Context, &VidDefaultPalette, &Context->PhysicalPalette);
- Context->Font = VidDefaultFont;
- ASSERT(Context->Font != NULL);
- if (Context->Mode == BaseVideoModeBiosText) {
- Context->Columns = Context->Width;
- Context->Rows = Context->Height;
- } else {
- Context->Columns = Context->Width / Context->Font->CellWidth;
- Context->Rows = Context->Height / Context->Font->CellHeight;
- }
- Status = STATUS_SUCCESS;
- return Status;
- }
- VOID
- VidClearScreen (
- PBASE_VIDEO_CONTEXT Context,
- ULONG MinimumX,
- ULONG MinimumY,
- ULONG MaximumX,
- ULONG MaximumY
- )
- /*++
- Routine Description:
- This routine clears a region of the screen, filling it with the default
- fill character. If no frame buffer is present, this is a no-op.
- Arguments:
- Context - Supplies a pointer to the initialized base video context.
- MinimumX - Supplies the minimum X coordinate of the rectangle to clear,
- inclusive.
- MinimumY - Supplies the minimum Y coordinate of the rectangle to clear,
- inclusive.
- MaximumX - Supplies the maximum X coordinate of the rectangle to clear,
- exclusive.
- MaximumY - Supplies the maximum Y coordinate of the rectangle to clear,
- exclusive.
- Return Value:
- None.
- --*/
- {
- BASE_VIDEO_CHARACTER Character;
- ULONG Color;
- ULONG HorizontalIndex;
- PULONG Pixel;
- PUSHORT Pixel16;
- PUCHAR Pixel8;
- ULONG VerticalIndex;
- if (Context->FrameBuffer == NULL) {
- return;
- }
- //
- // If either minimum value is off the screen, exit.
- //
- if (MinimumX >= Context->Width) {
- return;
- }
- if (MinimumY >= Context->Height) {
- return;
- }
- //
- // Truncate the maximum values.
- //
- if (MaximumX > Context->Width) {
- MaximumX = Context->Width;
- }
- if (MaximumY > Context->Height) {
- MaximumY = Context->Height;
- }
- //
- // Handle text mode by running around printing spaces.
- //
- if (Context->Mode == BaseVideoModeBiosText) {
- Character.Data.Character = ' ';
- Character.Data.Attributes = 0;
- for (VerticalIndex = MinimumY;
- VerticalIndex < MaximumY;
- VerticalIndex += 1) {
- for (HorizontalIndex = MinimumX;
- HorizontalIndex < MaximumX;
- HorizontalIndex += 1) {
- VidpPrintCharacter(Context,
- HorizontalIndex,
- VerticalIndex,
- &Character);
- }
- }
- return;
- }
- Color = Context->PhysicalPalette.DefaultBackground;
- //
- // Switch on the bits per pixel outside the hot inner loop.
- //
- switch (Context->BitsPerPixel) {
- case 8:
- for (VerticalIndex = MinimumY;
- VerticalIndex < MaximumY;
- VerticalIndex += 1) {
- Pixel = (PULONG)(Context->FrameBuffer +
- (((VerticalIndex *
- Context->PixelsPerScanLine) +
- MinimumX) *
- (Context->BitsPerPixel / BITS_PER_BYTE)));
- Pixel8 = (PUCHAR)Pixel;
- for (HorizontalIndex = MinimumX;
- HorizontalIndex < MaximumX;
- HorizontalIndex += 1) {
- *Pixel8 = (UCHAR)Color;
- Pixel8 += 1;
- }
- }
- break;
- case 16:
- for (VerticalIndex = MinimumY;
- VerticalIndex < MaximumY;
- VerticalIndex += 1) {
- Pixel = (PULONG)(Context->FrameBuffer +
- (((VerticalIndex *
- Context->PixelsPerScanLine) +
- MinimumX) *
- (Context->BitsPerPixel / BITS_PER_BYTE)));
- Pixel16 = (PUSHORT)Pixel;
- for (HorizontalIndex = MinimumX;
- HorizontalIndex < MaximumX;
- HorizontalIndex += 1) {
- *Pixel16 = (USHORT)Color;
- Pixel16 += 1;
- }
- }
- break;
- case 24:
- for (VerticalIndex = MinimumY;
- VerticalIndex < MaximumY;
- VerticalIndex += 1) {
- Pixel = (PULONG)(Context->FrameBuffer +
- (((VerticalIndex *
- Context->PixelsPerScanLine) +
- MinimumX) *
- (Context->BitsPerPixel / BITS_PER_BYTE)));
- Pixel8 = (PUCHAR)Pixel;
- for (HorizontalIndex = MinimumX;
- HorizontalIndex < MaximumX;
- HorizontalIndex += 1) {
- *Pixel8 = (UCHAR)Color;
- *(Pixel8 + 1) = (UCHAR)(Color >> 8);
- *(Pixel8 + 2) = (UCHAR)(Color >> 16);
- Pixel8 += 3;
- }
- }
- break;
- case 32:
- for (VerticalIndex = MinimumY;
- VerticalIndex < MaximumY;
- VerticalIndex += 1) {
- Pixel = (PULONG)(Context->FrameBuffer +
- (((VerticalIndex *
- Context->PixelsPerScanLine) +
- MinimumX) *
- (Context->BitsPerPixel / BITS_PER_BYTE)));
- for (HorizontalIndex = MinimumX;
- HorizontalIndex < MaximumX;
- HorizontalIndex += 1) {
- *Pixel = Color;
- Pixel += 1;
- }
- }
- break;
- default:
- ASSERT(FALSE);
- break;
- }
- return;
- }
- VOID
- VidPrintString (
- PBASE_VIDEO_CONTEXT Context,
- ULONG XCoordinate,
- ULONG YCoordinate,
- PSTR String
- )
- /*++
- Routine Description:
- This routine prints a null-terminated string to the screen at the
- specified location.
- Arguments:
- Context - Supplies a pointer to the initialized base video context.
- XCoordinate - Supplies the X coordinate of the location on the screen
- to write to.
- YCoordinate - Supplies the Y cooordinate of the location on the screen
- to write to.
- String - Supplies the string to print.
- Return Value:
- None.
- --*/
- {
- BASE_VIDEO_CHARACTER Character;
- ULONG Columns;
- ULONG Rows;
- if (Context->FrameBuffer == NULL) {
- return;
- }
- Columns = Context->Columns;
- Rows = Context->Rows;
- Character.AsUint32 = 0;
- while (*String != '\0') {
- Character.Data.Character = *String;
- VidpPrintCharacter(Context, XCoordinate, YCoordinate, &Character);
- XCoordinate += 1;
- if (XCoordinate >= Columns) {
- XCoordinate = 0;
- YCoordinate += 1;
- }
- if (YCoordinate >= Rows) {
- YCoordinate = 0;
- }
- String += 1;
- }
- return;
- }
- VOID
- VidPrintHexInteger (
- PBASE_VIDEO_CONTEXT Context,
- ULONG XCoordinate,
- ULONG YCoordinate,
- ULONG Number
- )
- /*++
- Routine Description:
- This routine prints an integer to the screen in the specified location.
- Arguments:
- Context - Supplies a pointer to the initialized base video context.
- XCoordinate - Supplies the X coordinate of the location on the screen
- to write to.
- YCoordinate - Supplies the Y cooordinate of the location on the screen
- to write to.
- Number - Supplies the signed integer to print.
- Return Value:
- None.
- --*/
- {
- CHAR StringBuffer[30];
- VidpConvertIntegerToString(Number, StringBuffer, 16);
- VidPrintString(Context, XCoordinate, YCoordinate, StringBuffer);
- return;
- }
- VOID
- VidPrintInteger (
- PBASE_VIDEO_CONTEXT Context,
- ULONG XCoordinate,
- ULONG YCoordinate,
- LONG Number
- )
- /*++
- Routine Description:
- This routine prints an integer to the screen in the specified location.
- Arguments:
- Context - Supplies a pointer to the initialized base video context.
- XCoordinate - Supplies the X coordinate of the location on the screen
- to write to.
- YCoordinate - Supplies the Y cooordinate of the location on the screen
- to write to.
- Number - Supplies the signed integer to print.
- Return Value:
- None.
- --*/
- {
- CHAR StringBuffer[30];
- VidpConvertIntegerToString(Number, StringBuffer, 10);
- VidPrintString(Context, XCoordinate, YCoordinate, StringBuffer);
- return;
- }
- VOID
- VidPrintCharacters (
- PBASE_VIDEO_CONTEXT Context,
- ULONG XCoordinate,
- ULONG YCoordinate,
- PBASE_VIDEO_CHARACTER Characters,
- ULONG Count
- )
- /*++
- Routine Description:
- This routine prints a set of characters.
- Arguments:
- Context - Supplies a pointer to the initialized base video context.
- XCoordinate - Supplies the X coordinate of the location on the screen
- to write to.
- YCoordinate - Supplies the Y cooordinate of the location on the screen
- to write to.
- Characters - Supplies a pointer to the array of characters to write.
- Count - Supplies the number of characters in the array.
- Return Value:
- None.
- --*/
- {
- ULONG Columns;
- ULONG Index;
- ULONG Rows;
- Columns = Context->Columns;
- Rows = Context->Rows;
- for (Index = 0; Index < Count; Index += 1) {
- VidpPrintCharacter(Context,
- XCoordinate,
- YCoordinate,
- Characters + Index);
- XCoordinate += 1;
- if (XCoordinate >= Columns) {
- XCoordinate = 0;
- YCoordinate += 1;
- }
- if (YCoordinate >= Rows) {
- YCoordinate = 0;
- }
- }
- return;
- }
- VOID
- VidSetPalette (
- PBASE_VIDEO_CONTEXT Context,
- PBASE_VIDEO_PALETTE Palette,
- PBASE_VIDEO_PALETTE OldPalette
- )
- /*++
- Routine Description:
- This routine sets the current video palette. It is the caller's
- responsibility to synchronize both with printing and clearing the screen.
- Arguments:
- Context - Supplies a pointer to the initialized base video context.
- Palette - Supplies a pointer to the palette to set. This memory will be
- copied.
- OldPalette - Supplies an optional pointer where the old palette data will
- be returned.
- Return Value:
- None.
- --*/
- {
- if (OldPalette != NULL) {
- RtlCopyMemory(OldPalette,
- &(Context->Palette),
- sizeof(BASE_VIDEO_PALETTE));
- }
- RtlCopyMemory(&(Context->Palette), Palette, sizeof(BASE_VIDEO_PALETTE));
- VidpConvertPalette(Context,
- &(Context->Palette),
- &(Context->PhysicalPalette));
- return;
- }
- VOID
- VidSetPartialPalette (
- PBASE_VIDEO_CONTEXT Context,
- PBASE_VIDEO_PARTIAL_PALETTE PartialPalette
- )
- /*++
- Routine Description:
- This routine sets the current video palette. It is the caller's
- responsibility to synchronize both with printing and clearing the screen.
- Arguments:
- Context - Supplies a pointer to the initialized base video context.
- PartialPalette - Supplies a pointer to the palette to set. This memory will
- be copied. Values in the palette not specified here will be left
- unchanged.
- Return Value:
- None.
- --*/
- {
- BASE_VIDEO_PALETTE Palette;
- VidGetPalette(Context, &Palette);
- Palette.AnsiColor[AnsiColorDefault] = PartialPalette->DefaultForeground;
- Palette.BoldAnsiColor[AnsiColorDefault] =
- PartialPalette->DefaultBoldForeground;
- Palette.DefaultBackground = PartialPalette->DefaultBackground;
- Palette.DefaultBoldBackground = PartialPalette->DefaultBoldBackground;
- Palette.CursorText = PartialPalette->CursorText;
- Palette.CursorBackground = PartialPalette->CursorBackground;
- VidSetPalette(Context, &Palette, NULL);
- return;
- }
- VOID
- VidGetPalette (
- PBASE_VIDEO_CONTEXT Context,
- PBASE_VIDEO_PALETTE Palette
- )
- /*++
- Routine Description:
- This routine gets the current video palette. It is the caller's
- responsibility to synchronize with anyone else that might be changing the
- palette.
- Arguments:
- Context - Supplies a pointer to the initialized base video context.
- Palette - Supplies a pointer where the palette will be returned.
- Return Value:
- None.
- --*/
- {
- RtlCopyMemory(Palette, &(Context->Palette), sizeof(BASE_VIDEO_PALETTE));
- return;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- VOID
- VidpConvertPalette (
- PBASE_VIDEO_CONTEXT Context,
- PBASE_VIDEO_PALETTE Palette,
- PBASE_VIDEO_PALETTE PhysicalPalette
- )
- /*++
- Routine Description:
- This routine converts the given palette into a physical palette that uses
- the native pixel format.
- Arguments:
- Context - Supplies a pointer to the initialized base video context.
- Palette - Supplies the natural palette to convert.
- PhysicalPalette - Supplies a pointer where the palette in native pixel
- format will be returned.
- Return Value:
- None.
- --*/
- {
- ULONG BlueBit;
- ULONG BlueMask;
- ULONG ColorIndex;
- ULONG GreenBit;
- ULONG GreenMask;
- ULONG RedBit;
- ULONG RedMask;
- COLOR_TRANSLATION Translation;
- if (Context->Mode == BaseVideoModeBiosText) {
- for (ColorIndex = 0; ColorIndex < AnsiColorCount; ColorIndex += 1) {
- PhysicalPalette->AnsiColor[ColorIndex] =
- VidTextModeColors[ColorIndex];
- PhysicalPalette->BoldAnsiColor[ColorIndex] =
- VidTextModeColors[ColorIndex] + 8;
- }
- PhysicalPalette->DefaultBackground = VidTextModeColors[AnsiColorBlack];
- PhysicalPalette->DefaultBoldBackground =
- VidTextModeColors[AnsiColorWhite];
- PhysicalPalette->CursorText = PhysicalPalette->DefaultBackground;
- PhysicalPalette->CursorBackground =
- PhysicalPalette->AnsiColor[AnsiColorDefault];
- goto ConvertPaletteEnd;
- }
- ASSERT(Context->Mode == BaseVideoModeFrameBuffer);
- RedMask = Context->RedMask;
- GreenMask = Context->GreenMask;
- BlueMask = Context->BlueMask;
- ASSERT((RedMask != 0) && (GreenMask != 0) && (BlueMask != 0));
- //
- // Handle some common cases.
- //
- if ((RedMask == 0x00FF0000) && (GreenMask == 0x0000FF00) &&
- (BlueMask == 0x000000FF)) {
- RtlCopyMemory(PhysicalPalette, Palette, sizeof(BASE_VIDEO_PALETTE));
- return;
- } else if ((RedMask == 0x000000FF) && (GreenMask == 0x0000FF00) &&
- (BlueMask == 0x00FF0000)) {
- for (ColorIndex = 0; ColorIndex < AnsiColorCount; ColorIndex += 1) {
- PhysicalPalette->AnsiColor[ColorIndex] =
- SWIZZLE_RED_BLUE(Palette->AnsiColor[ColorIndex]);
- PhysicalPalette->BoldAnsiColor[ColorIndex] =
- SWIZZLE_RED_BLUE(Palette->BoldAnsiColor[ColorIndex]);
- }
- PhysicalPalette->DefaultBackground =
- SWIZZLE_RED_BLUE(Palette->DefaultBackground);
- PhysicalPalette->DefaultBoldBackground =
- SWIZZLE_RED_BLUE(Palette->DefaultBoldBackground);
- PhysicalPalette->CursorText = SWIZZLE_RED_BLUE(Palette->CursorText);
- PhysicalPalette->CursorBackground =
- SWIZZLE_RED_BLUE(Palette->CursorBackground);
- return;
- }
- //
- // Create the translation shift and mask.
- //
- Translation.RedMask = RedMask;
- Translation.GreenMask = GreenMask;
- Translation.BlueMask = BlueMask;
- RedBit = VidpFindHighestBitSet(Translation.RedMask) + 1;
- GreenBit = VidpFindHighestBitSet(Translation.GreenMask) + 1;
- BlueBit = VidpFindHighestBitSet(Translation.BlueMask) + 1;
- Translation.RedShift = RedBit - (3 * BITS_PER_BYTE);
- Translation.GreenShift = GreenBit - (2 * BITS_PER_BYTE);
- Translation.BlueShift = BlueBit - BITS_PER_BYTE;
- //
- // Translate all the colors in the palette.
- //
- for (ColorIndex = 0; ColorIndex < AnsiColorCount; ColorIndex += 1) {
- PhysicalPalette->AnsiColor[ColorIndex] =
- TRANSLATE_COLOR(Palette->AnsiColor[ColorIndex], Translation);
- PhysicalPalette->BoldAnsiColor[ColorIndex] =
- TRANSLATE_COLOR(Palette->BoldAnsiColor[ColorIndex], Translation);
- }
- PhysicalPalette->DefaultBackground =
- TRANSLATE_COLOR(Palette->DefaultBackground, Translation);
- PhysicalPalette->DefaultBoldBackground =
- TRANSLATE_COLOR(Palette->DefaultBoldBackground, Translation);
- PhysicalPalette->CursorText =
- TRANSLATE_COLOR(Palette->CursorText, Translation);
- PhysicalPalette->CursorBackground =
- TRANSLATE_COLOR(Palette->CursorBackground, Translation);
- ConvertPaletteEnd:
- return;
- }
- VOID
- VidpPrintCharacter (
- PBASE_VIDEO_CONTEXT Context,
- ULONG XCoordinate,
- ULONG YCoordinate,
- PBASE_VIDEO_CHARACTER Character
- )
- /*++
- Routine Description:
- This routine prints a character to the screen in the specified location.
- Arguments:
- Context - Supplies a pointer to the initialized base video context.
- XCoordinate - Supplies the column to write to.
- YCoordinate - Supplies the row to write to.
- Character - Supplies a pointer to the character to print.
- Return Value:
- None.
- --*/
- {
- USHORT Attributes;
- ANSI_COLOR BackgroundAnsiColor;
- ULONG BitIndex;
- ULONG ByteIndex;
- ULONG ColorOff;
- ULONG ColorOn;
- ULONG ColumnIndex;
- PUCHAR Data;
- PUSHORT Destination16;
- PULONG Destination32;
- PBYTE Destination8;
- PBASE_VIDEO_FONT Font;
- ANSI_COLOR ForegroundAnsiColor;
- ULONG HorizontalIndex;
- ULONG LineSize;
- PVOID LineStart;
- UCHAR RotateBuffer[8];
- ULONG RowIndex;
- BYTE Source;
- ULONG SourceIndex;
- ULONG SwapColor;
- ULONG VerticalIndex;
- ULONG YPixel;
- //
- // Get the colors to use.
- //
- ColorOn = Context->PhysicalPalette.AnsiColor[AnsiColorDefault];
- ColorOff = Context->PhysicalPalette.DefaultBackground;
- if (Character->Data.Attributes != 0) {
- Attributes = Character->Data.Attributes;
- if ((Attributes & BASE_VIDEO_CURSOR) != 0) {
- ColorOn = Context->PhysicalPalette.CursorText;
- ColorOff = Context->PhysicalPalette.CursorBackground;
- } else {
- BackgroundAnsiColor = (Attributes >> BASE_VIDEO_BACKGROUND_SHIFT) &
- BASE_VIDEO_COLOR_MASK;
- ForegroundAnsiColor = Attributes & BASE_VIDEO_COLOR_MASK;
- ColorOn = Context->PhysicalPalette.AnsiColor[ForegroundAnsiColor];
- if ((Attributes & BASE_VIDEO_FOREGROUND_BOLD) != 0) {
- ColorOn =
- Context->PhysicalPalette.BoldAnsiColor[ForegroundAnsiColor];
- }
- if (BackgroundAnsiColor != AnsiColorDefault) {
- ColorOff =
- Context->PhysicalPalette.AnsiColor[BackgroundAnsiColor];
- }
- if ((Attributes & BASE_VIDEO_BACKGROUND_BOLD) != 0) {
- ColorOff =
- Context->PhysicalPalette.BoldAnsiColor[BackgroundAnsiColor];
- if (BackgroundAnsiColor == AnsiColorDefault) {
- ColorOff = Context->PhysicalPalette.DefaultBoldBackground;
- }
- }
- if ((Attributes & BASE_VIDEO_NEGATIVE) != 0) {
- SwapColor = ColorOn;
- ColorOn = ColorOff;
- ColorOff = SwapColor;
- }
- }
- }
- //
- // Handle text mode differently.
- //
- if (Context->Mode == BaseVideoModeBiosText) {
- Destination16 = Context->FrameBuffer;
- Destination16 += (YCoordinate * Context->Width) + XCoordinate;
- *Destination16 = BIOS_TEXT_ATTRIBUTES(ColorOn, ColorOff) |
- (UCHAR)(Character->Data.Character);
- return;
- }
- //
- // Get the glyph data for that character.
- //
- Font = Context->Font;
- if ((Character->Data.Character < Font->FirstAsciiCode) ||
- (Character->Data.Character >=
- Font->FirstAsciiCode + Font->GlyphCount)) {
- ASSERT(Font->FirstAsciiCode <= ' ');
- SourceIndex = ' ' - Font->FirstAsciiCode;
- } else {
- SourceIndex = Character->Data.Character - Font->FirstAsciiCode;
- }
- //
- // Rotate the character if needed. For those wondering, this code takes
- // about 185 bytes on x86, and the rotated data storage saves about 192
- // bytes for the 5x7 and 4x6 fonts each.
- //
- if ((Font->Flags & BASE_VIDEO_FONT_ROTATED) != 0) {
- SourceIndex *= Font->GlyphBytesWidth * Font->GlyphWidth;
- Data = (PUCHAR)&(Font->Data[SourceIndex]);
- ASSERT((Font->GlyphWidth < sizeof(RotateBuffer)) &&
- (Font->GlyphHeight < sizeof(RotateBuffer)) &&
- (sizeof(RotateBuffer) <= BITS_PER_BYTE));
- //
- // The normal data format runs horizontally. Build it a horizontal
- // row at a time (assuming there will be left than 8).
- //
- for (RowIndex = 0; RowIndex < Font->GlyphHeight; RowIndex += 1) {
- Source = 0;
- //
- // The row's data is spread out since the data is stored a column
- // at a time. It's always the same bit (row) for each column.
- //
- for (ColumnIndex = 0;
- ColumnIndex < Font->GlyphWidth;
- ColumnIndex += 1) {
- BitIndex = RowIndex;
- if ((Data[ColumnIndex] & (1 << BitIndex)) != 0) {
- Source |= 1 << (BITS_PER_BYTE - 1 - ColumnIndex);
- }
- }
- RotateBuffer[RowIndex] = Source;
- }
- Data = RotateBuffer;
- } else {
- SourceIndex *= Font->GlyphBytesWidth * Font->GlyphHeight;
- Data = (PUCHAR)&(Font->Data[SourceIndex]);
- }
- //
- // Compute the starting address on the frame buffer.
- //
- YPixel = (YCoordinate * Font->CellHeight) * Context->PixelsPerScanLine;
- LineStart = Context->FrameBuffer +
- ((YPixel + (XCoordinate * Font->CellWidth)) *
- (Context->BitsPerPixel / BITS_PER_BYTE));
- LineSize = Context->PixelsPerScanLine *
- (Context->BitsPerPixel / BITS_PER_BYTE);
- //
- // Separate write loops for different pixel widths does mean more code,
- // but it skips conditionals in the inner loops, which are very hot.
- //
- switch (Context->BitsPerPixel) {
- case 8:
- for (VerticalIndex = 0;
- VerticalIndex < Font->GlyphHeight;
- VerticalIndex += 1) {
- Destination8 = LineStart;
- HorizontalIndex = 0;
- for (ByteIndex = 0;
- ByteIndex < Font->GlyphBytesWidth;
- ByteIndex += 1) {
- Source = *Data;
- BitIndex = 0;
- while ((BitIndex < BITS_PER_BYTE) &&
- (HorizontalIndex < Font->GlyphWidth)) {
- if ((Source & 0x80) != 0) {
- *Destination8 = (UCHAR)ColorOn;
- } else {
- *Destination8 = (UCHAR)ColorOff;
- }
- Destination8 += 1;
- HorizontalIndex += 1;
- Source <<= 1;
- BitIndex += 1;
- }
- Data += 1;
- }
- while (HorizontalIndex < Font->CellWidth) {
- *Destination8 = (UCHAR)ColorOff;
- Destination8 += 1;
- HorizontalIndex += 1;
- }
- LineStart += LineSize;
- }
- while (VerticalIndex < Font->CellHeight) {
- Destination8 = LineStart;
- for (HorizontalIndex = 0;
- HorizontalIndex < Font->CellWidth;
- HorizontalIndex += 1) {
- *Destination8 = (UCHAR)ColorOff;
- Destination8 += 1;
- }
- LineStart += LineSize;
- VerticalIndex += 1;
- }
- break;
- case 16:
- for (VerticalIndex = 0;
- VerticalIndex < Font->GlyphHeight;
- VerticalIndex += 1) {
- Destination16 = LineStart;
- HorizontalIndex = 0;
- for (ByteIndex = 0;
- ByteIndex < Font->GlyphBytesWidth;
- ByteIndex += 1) {
- Source = *Data;
- BitIndex = 0;
- while ((BitIndex < BITS_PER_BYTE) &&
- (HorizontalIndex < Font->GlyphWidth)) {
- if ((Source & 0x80) != 0) {
- *Destination16 = (USHORT)ColorOn;
- } else {
- *Destination16 = (USHORT)ColorOff;
- }
- Destination16 += 1;
- HorizontalIndex += 1;
- Source <<= 1;
- BitIndex += 1;
- }
- Data += 1;
- }
- while (HorizontalIndex < Font->CellWidth) {
- *Destination16 = (USHORT)ColorOff;
- Destination16 += 1;
- HorizontalIndex += 1;
- }
- LineStart += LineSize;
- }
- while (VerticalIndex < Font->CellHeight) {
- Destination16 = LineStart;
- for (HorizontalIndex = 0;
- HorizontalIndex < Font->CellWidth;
- HorizontalIndex += 1) {
- *Destination16 = (USHORT)ColorOff;
- Destination16 += 1;
- }
- LineStart += LineSize;
- VerticalIndex += 1;
- }
- break;
- case 24:
- for (VerticalIndex = 0;
- VerticalIndex < Font->GlyphHeight;
- VerticalIndex += 1) {
- Destination8 = LineStart;
- HorizontalIndex = 0;
- for (ByteIndex = 0;
- ByteIndex < Font->GlyphBytesWidth;
- ByteIndex += 1) {
- Source = *Data;
- BitIndex = 0;
- while ((BitIndex < BITS_PER_BYTE) &&
- (HorizontalIndex < Font->GlyphWidth)) {
- if ((Source & 0x80) != 0) {
- *Destination8 = (UCHAR)ColorOn;
- *(Destination8 + 1) = (UCHAR)(ColorOn >> 8);
- *(Destination8 + 2) = (UCHAR)(ColorOn >> 16);
- } else {
- *Destination8 = (UCHAR)ColorOff;
- *(Destination8 + 1) = (UCHAR)(ColorOff >> 8);
- *(Destination8 + 2) = (UCHAR)(ColorOff >> 16);
- }
- Destination8 += 3;
- HorizontalIndex += 1;
- Source <<= 1;
- BitIndex += 1;
- }
- Data += 1;
- }
- while (HorizontalIndex < Font->CellWidth) {
- *Destination8 = (UCHAR)ColorOff;
- *(Destination8 + 1) = (UCHAR)(ColorOff >> 8);
- *(Destination8 + 2) = (UCHAR)(ColorOff >> 16);
- Destination8 += 3;
- HorizontalIndex += 1;
- }
- LineStart += LineSize;
- }
- while (VerticalIndex < Font->CellHeight) {
- Destination8 = LineStart;
- for (HorizontalIndex = 0;
- HorizontalIndex < Font->CellWidth;
- HorizontalIndex += 1) {
- *Destination8 = (UCHAR)ColorOff;
- *(Destination8 + 1) = (UCHAR)(ColorOff >> 8);
- *(Destination8 + 2) = (UCHAR)(ColorOff >> 16);
- Destination8 += 3;
- }
- LineStart += LineSize;
- VerticalIndex += 1;
- }
- break;
- case 32:
- for (VerticalIndex = 0;
- VerticalIndex < Font->GlyphHeight;
- VerticalIndex += 1) {
- Destination32 = LineStart;
- HorizontalIndex = 0;
- for (ByteIndex = 0;
- ByteIndex < Font->GlyphBytesWidth;
- ByteIndex += 1) {
- Source = *Data;
- BitIndex = 0;
- while ((BitIndex < BITS_PER_BYTE) &&
- (HorizontalIndex < Font->GlyphWidth)) {
- if ((Source & 0x80) != 0) {
- *Destination32 = ColorOn;
- } else {
- *Destination32 = ColorOff;
- }
- Destination32 += 1;
- HorizontalIndex += 1;
- Source <<= 1;
- BitIndex += 1;
- }
- Data += 1;
- }
- while (HorizontalIndex < Font->CellWidth) {
- *Destination32 = ColorOff;
- Destination32 += 1;
- HorizontalIndex += 1;
- }
- LineStart += LineSize;
- }
- while (VerticalIndex < Font->CellHeight) {
- Destination32 = LineStart;
- for (HorizontalIndex = 0;
- HorizontalIndex < Font->CellWidth;
- HorizontalIndex += 1) {
- *Destination32 = ColorOff;
- Destination32 += 1;
- }
- LineStart += LineSize;
- VerticalIndex += 1;
- }
- break;
- default:
- ASSERT(FALSE);
- break;
- }
- return;
- }
- VOID
- VidpConvertIntegerToString (
- LONG Integer,
- PSTR String,
- ULONG Base
- )
- /*++
- Routine Description:
- This routine converts an integer to a string.
- Arguments:
- Integer - Supplies the signed integer to convert to string format.
- String - Supplies a pointer to the allocated buffer where the string
- will be written.
- Base - Supplies the base of the number to print, from 2 to 16.
- Return Value:
- None.
- --*/
- {
- ULONG CurrentPosition;
- BOOL Positive;
- CurrentPosition = 0;
- Positive = TRUE;
- //
- // Parameter checking.
- //
- if (String == NULL) {
- return;
- }
- if ((Base < 2) || (Base > 16)) {
- *String = '\0';
- return;
- }
- //
- // Only deal with positive numbers, but remember if the number was negative.
- //
- if ((Integer < 0) && (Base == 10)) {
- Positive = FALSE;
- Integer = -Integer;
- }
- //
- // Loop over the integer, getting the least significant digit each
- // iteration. Note that this causes the string to come out backwards, which
- // is why the string is reversed before it is returned.
- //
- do {
- String[CurrentPosition] = (Integer % Base) + '0';
- if (String[CurrentPosition] > '9') {
- String[CurrentPosition] = (Integer % Base) - 10 + 'A';
- }
- CurrentPosition += 1;
- Integer = Integer / Base;
- } while (Integer > 0);
- //
- // Print out the negative sign at the end.
- //
- if (Positive == FALSE) {
- String[CurrentPosition] = '-';
- CurrentPosition += 1;
- }
- //
- // Pad spaces to at least 8.
- //
- while (CurrentPosition < 8) {
- String[CurrentPosition] = ' ';
- CurrentPosition += 1;
- }
- //
- // Null terminate and reverse the string.
- //
- String[CurrentPosition] = '\0';
- RtlStringReverse(String, String + CurrentPosition);
- return;
- }
- ULONG
- VidpFindHighestBitSet (
- ULONG Value
- )
- /*++
- Routine Description:
- This routine finds the highest bit set in the given 32-bit integer.
- Arguments:
- Value - Supplies the value to find the highest bit number of.
- Return Value:
- Returns the index of the highest bit set.
- --*/
- {
- ULONG Index;
- Index = (sizeof(ULONG) * BITS_PER_BYTE) - 1;
- while (TRUE) {
- if ((Value & (1 << Index)) != 0) {
- return Index;
- }
- if (Index == 0) {
- break;
- }
- Index -= 1;
- }
- return Index;
- }
|