diff --git a/boot/freeldr/freeldr/arch/i386/xbox/xboxcons.c b/boot/freeldr/freeldr/arch/i386/xbox/xboxcons.c index 18869cc6078..4f7a763655b 100644 --- a/boot/freeldr/freeldr/arch/i386/xbox/xboxcons.c +++ b/boot/freeldr/freeldr/arch/i386/xbox/xboxcons.c @@ -36,7 +36,7 @@ XboxConsPutChar(int c) NeedScroll = (CurrentCursorY >= Height); if (NeedScroll) { - VidFbScrollUp(CurrentAttr); + FbConsScrollUp(CurrentAttr); --CurrentCursorY; } diff --git a/boot/freeldr/freeldr/arch/i386/xbox/xboxvideo.c b/boot/freeldr/freeldr/arch/i386/xbox/xboxvideo.c index ffdceaf399e..928c6068444 100644 --- a/boot/freeldr/freeldr/arch/i386/xbox/xboxvideo.c +++ b/boot/freeldr/freeldr/arch/i386/xbox/xboxvideo.c @@ -36,13 +36,13 @@ extern multiboot_info_t * MultibootInfoPtr; VOID XboxVideoClearScreen(UCHAR Attr) { - VidFbClearScreen(Attr); + FbConsClearScreen(Attr); } VOID XboxVideoPutChar(int Ch, UCHAR Attr, unsigned X, unsigned Y) { - VidFbPutChar(Ch, Attr, X, Y); + FbConsPutChar(Ch, Attr, X, Y); } static UCHAR @@ -149,13 +149,13 @@ XboxVideoSetDisplayMode(PCSTR DisplayMode, BOOLEAN Init) VOID XboxVideoGetDisplaySize(PULONG Width, PULONG Height, PULONG Depth) { - VidFbGetDisplaySize(Width, Height, Depth); + FbConsGetDisplaySize(Width, Height, Depth); } ULONG XboxVideoGetBufferSize(VOID) { - return VidFbGetBufferSize(); + return FbConsGetBufferSize(); } VOID @@ -179,7 +179,7 @@ XboxVideoHideShowTextCursor(BOOLEAN Show) VOID XboxVideoCopyOffScreenBufferToVRAM(PVOID Buffer) { - VidFbCopyOffScreenBufferToVRAM(Buffer); + FbConsCopyOffScreenBufferToVRAM(Buffer); } BOOLEAN diff --git a/boot/freeldr/freeldr/arch/uefi/ueficon.c b/boot/freeldr/freeldr/arch/uefi/ueficon.c index dd15c392ee0..18ba8d8ab3b 100644 --- a/boot/freeldr/freeldr/arch/uefi/ueficon.c +++ b/boot/freeldr/freeldr/arch/uefi/ueficon.c @@ -34,7 +34,7 @@ UefiConsPutChar(int c) NeedScroll = (CurrentCursorY >= Height); if (NeedScroll) { - VidFbScrollUp(CurrentAttr); + FbConsScrollUp(CurrentAttr); --CurrentCursorY; } if (c == '\r') diff --git a/boot/freeldr/freeldr/arch/uefi/uefivid.c b/boot/freeldr/freeldr/arch/uefi/uefivid.c index 2d5ddd16585..95304babe95 100644 --- a/boot/freeldr/freeldr/arch/uefi/uefivid.c +++ b/boot/freeldr/freeldr/arch/uefi/uefivid.c @@ -73,19 +73,19 @@ UefiInitializeVideo(VOID) VOID UefiVideoClearScreen(UCHAR Attr) { - VidFbClearScreen(Attr); + FbConsClearScreen(Attr); } VOID UefiVideoPutChar(int Ch, UCHAR Attr, unsigned X, unsigned Y) { - VidFbPutChar(Ch, Attr, X, Y); + FbConsPutChar(Ch, Attr, X, Y); } VOID UefiVideoGetDisplaySize(PULONG Width, PULONG Height, PULONG Depth) { - VidFbGetDisplaySize(Width, Height, Depth); + FbConsGetDisplaySize(Width, Height, Depth); } VIDEODISPLAYMODE @@ -98,13 +98,13 @@ UefiVideoSetDisplayMode(PCSTR DisplayMode, BOOLEAN Init) ULONG UefiVideoGetBufferSize(VOID) { - return VidFbGetBufferSize(); + return FbConsGetBufferSize(); } VOID UefiVideoCopyOffScreenBufferToVRAM(PVOID Buffer) { - VidFbCopyOffScreenBufferToVRAM(Buffer); + FbConsCopyOffScreenBufferToVRAM(Buffer); } VOID diff --git a/boot/freeldr/freeldr/arch/vidfb.c b/boot/freeldr/freeldr/arch/vidfb.c index 034a6e8aa03..72d50e15d32 100644 --- a/boot/freeldr/freeldr/arch/vidfb.c +++ b/boot/freeldr/freeldr/arch/vidfb.c @@ -13,8 +13,6 @@ #include DBG_DEFAULT_CHANNEL(UI); -#define VGA_CHAR_SIZE 2 - /* This is used to introduce artificial symmetric borders at the top and bottom */ #define TOP_BOTTOM_LINES 0 @@ -62,7 +60,7 @@ VidFbPrintFramebufferInfo(VOID) /** * @brief - * Initializes internal framebuffer data based on the given parameters. + * Initializes internal framebuffer information based on the given parameters. * * @param[in] BaseAddress * The framebuffer physical base address. @@ -119,30 +117,6 @@ VidFbInitializeVideo( return TRUE; } -static inline -UINT32 -VidFbAttrToSingleColor( - _In_ UCHAR Attr) -{ - UCHAR Intensity; - Intensity = (0 == (Attr & 0x08) ? 127 : 255); - - return 0xff000000 | - (0 == (Attr & 0x04) ? 0 : (Intensity << 16)) | - (0 == (Attr & 0x02) ? 0 : (Intensity << 8)) | - (0 == (Attr & 0x01) ? 0 : Intensity); -} - -static VOID -VidFbAttrToColors( - _In_ UCHAR Attr, - _Out_ PUINT32 FgColor, - _Out_ PUINT32 BgColor) -{ - *FgColor = VidFbAttrToSingleColor(Attr & 0x0F); - *BgColor = VidFbAttrToSingleColor((Attr >> 4) & 0x0F); -} - VOID VidFbClearScreenColor( _In_ UINT32 Color, @@ -161,15 +135,11 @@ VidFbClearScreenColor( } } -VOID -VidFbClearScreen( - _In_ UCHAR Attr) -{ - UINT32 FgColor, BgColor; - VidFbAttrToColors(Attr, &FgColor, &BgColor); - VidFbClearScreenColor(BgColor, FALSE); -} - +/** + * @brief + * Displays a character at a given pixel position with specific foreground + * and background colors. + **/ VOID VidFbOutputChar( _In_ UCHAR Char, @@ -183,9 +153,16 @@ VidFbOutputChar( UCHAR Mask; ULONG Line, Col; + /* Don't display outside of the screen, nor partial characters */ + if ((X + CHAR_WIDTH >= framebufInfo.ScreenWidth) || + (Y + CHAR_HEIGHT >= (framebufInfo.ScreenHeight - 2 * TOP_BOTTOM_LINES))) + { + return; + } + FontPtr = BitmapFont8x16 + Char * CHAR_HEIGHT; Pixel = (PUINT32)((PUCHAR)framebufInfo.BaseAddress + - (Y * CHAR_HEIGHT + TOP_BOTTOM_LINES) * framebufInfo.Delta + X * CHAR_WIDTH * 4); + (Y + TOP_BOTTOM_LINES) * framebufInfo.Delta + X * sizeof(UINT32)); for (Line = 0; Line < CHAR_HEIGHT; Line++) { @@ -199,70 +176,48 @@ VidFbOutputChar( } } -VOID -VidFbPutChar( - _In_ UCHAR Char, - _In_ UCHAR Attr, - _In_ ULONG X, - _In_ ULONG Y) -{ - UINT32 FgColor, BgColor; - VidFbAttrToColors(Attr, &FgColor, &BgColor); - VidFbOutputChar(Char, X, Y, FgColor, BgColor); -} - +/** + * @brief + * Returns the width and height in pixels, of the whole visible area + * of the graphics framebuffer. + **/ VOID VidFbGetDisplaySize( _Out_ PULONG Width, _Out_ PULONG Height, _Out_ PULONG Depth) { - *Width = framebufInfo.ScreenWidth / CHAR_WIDTH; - *Height = (framebufInfo.ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT; + *Width = framebufInfo.ScreenWidth; + *Height = framebufInfo.ScreenHeight - 2 * TOP_BOTTOM_LINES; *Depth = framebufInfo.BitsPerPixel; } +/** + * @brief + * Returns the size in bytes, of a full graphics pixel buffer rectangle + * that can fill the whole visible area of the graphics framebuffer. + **/ ULONG VidFbGetBufferSize(VOID) { - return ((framebufInfo.ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT * - (framebufInfo.ScreenWidth / CHAR_WIDTH) * VGA_CHAR_SIZE); -} - -VOID -VidFbCopyOffScreenBufferToVRAM( - _In_ PVOID Buffer) -{ - PUCHAR OffScreenBuffer = (PUCHAR)Buffer; - ULONG Line, Col; - - for (Line = 0; Line < (framebufInfo.ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT; Line++) - { - for (Col = 0; Col < framebufInfo.ScreenWidth / CHAR_WIDTH; Col++) - { - VidFbPutChar(OffScreenBuffer[0], OffScreenBuffer[1], Col, Line); - OffScreenBuffer += VGA_CHAR_SIZE; - } - } + return ((framebufInfo.ScreenHeight - 2 * TOP_BOTTOM_LINES) * + framebufInfo.ScreenWidth * framebufInfo.BytesPerPixel); } VOID VidFbScrollUp( - _In_ UCHAR Attr) + _In_ UINT32 Color, + _In_ ULONG Scroll) { - UINT32 BgColor, Dummy; - ULONG PixelCount = framebufInfo.ScreenWidth * CHAR_HEIGHT * - (((framebufInfo.ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT) - 1); - PUINT32 Src = (PUINT32)((PUCHAR)framebufInfo.BaseAddress + (CHAR_HEIGHT + TOP_BOTTOM_LINES) * framebufInfo.Delta); PUINT32 Dst = (PUINT32)((PUCHAR)framebufInfo.BaseAddress + TOP_BOTTOM_LINES * framebufInfo.Delta); - - VidFbAttrToColors(Attr, &Dummy, &BgColor); + PUINT32 Src = (PUINT32)((PUCHAR)framebufInfo.BaseAddress + (TOP_BOTTOM_LINES + Scroll) * framebufInfo.Delta); + ULONG PixelCount = framebufInfo.ScreenWidth * ((framebufInfo.ScreenHeight - 2 * TOP_BOTTOM_LINES) - Scroll); while (PixelCount--) *Dst++ = *Src++; - for (PixelCount = 0; PixelCount < framebufInfo.ScreenWidth * CHAR_HEIGHT; PixelCount++) - *Dst++ = BgColor; + for (PixelCount = 0; PixelCount < framebufInfo.ScreenWidth * Scroll; PixelCount++) + *Dst++ = Color; } #if 0 @@ -300,3 +255,156 @@ VidFbGetPaletteColor( /* Not supported */ } #endif + + + +/* + * PROJECT: FreeLoader + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * or MIT (https://spdx.org/licenses/MIT) + * PURPOSE: Linear framebuffer based console support + * COPYRIGHT: Copyright 2025 Hermès Bélusca-Maïto + */ + +#define VGA_CHAR_SIZE 2 + +#define FBCONS_WIDTH (framebufInfo.ScreenWidth / CHAR_WIDTH) +#define FBCONS_HEIGHT ((framebufInfo.ScreenHeight - 2 * TOP_BOTTOM_LINES) / CHAR_HEIGHT) + +static inline +UINT32 +FbConsAttrToSingleColor( + _In_ UCHAR Attr) +{ + UCHAR Intensity; + Intensity = (0 == (Attr & 0x08) ? 127 : 255); + + return 0xff000000 | + (0 == (Attr & 0x04) ? 0 : (Intensity << 16)) | + (0 == (Attr & 0x02) ? 0 : (Intensity << 8)) | + (0 == (Attr & 0x01) ? 0 : Intensity); +} + +/** + * @brief + * Maps a text-mode CGA-style character attribute to separate + * foreground and background ARGB colors. + **/ +static VOID +FbConsAttrToColors( + _In_ UCHAR Attr, + _Out_ PUINT32 FgColor, + _Out_ PUINT32 BgColor) +{ + *FgColor = FbConsAttrToSingleColor(Attr & 0x0F); + *BgColor = FbConsAttrToSingleColor((Attr >> 4) & 0x0F); +} + +VOID +FbConsClearScreen( + _In_ UCHAR Attr) +{ + UINT32 FgColor, BgColor; + FbConsAttrToColors(Attr, &FgColor, &BgColor); + VidFbClearScreenColor(BgColor, FALSE); +} + +/** + * @brief + * Displays a character at a given position with specific foreground + * and background colors. + **/ +VOID +FbConsOutputChar( + _In_ UCHAR Char, + _In_ ULONG Column, + _In_ ULONG Row, + _In_ UINT32 FgColor, + _In_ UINT32 BgColor) +{ + /* Don't display outside of the screen */ + if ((Column >= FBCONS_WIDTH) || (Row >= FBCONS_HEIGHT)) + return; + VidFbOutputChar(Char, Column * CHAR_WIDTH, Row * CHAR_HEIGHT, FgColor, BgColor); +} + +/** + * @brief + * Displays a character with specific text attributes at a given position. + **/ +VOID +FbConsPutChar( + _In_ UCHAR Char, + _In_ UCHAR Attr, + _In_ ULONG Column, + _In_ ULONG Row) +{ + UINT32 FgColor, BgColor; + FbConsAttrToColors(Attr, &FgColor, &BgColor); + FbConsOutputChar(Char, Column, Row, FgColor, BgColor); +} + +/** + * @brief + * Returns the width and height in number of CGA characters/attributes, of a + * full text-mode CGA-style character buffer rectangle that can fill the whole console. + **/ +VOID +FbConsGetDisplaySize( + _Out_ PULONG Width, + _Out_ PULONG Height, + _Out_ PULONG Depth) +{ + // VidFbGetDisplaySize(Width, Height, Depth); + // *Width /= CHAR_WIDTH; + // *Height /= CHAR_HEIGHT; + *Width = FBCONS_WIDTH; + *Height = FBCONS_HEIGHT; + *Depth = framebufInfo.BitsPerPixel; +} + +/** + * @brief + * Returns the size in bytes, of a full text-mode CGA-style + * character buffer rectangle that can fill the whole console. + **/ +ULONG +FbConsGetBufferSize(VOID) +{ + return (FBCONS_HEIGHT * FBCONS_WIDTH * VGA_CHAR_SIZE); +} + +/** + * @brief + * Copies a full text-mode CGA-style character buffer rectangle to the console. + **/ +// TODO: Write a VidFb "BitBlt" equivalent. +VOID +FbConsCopyOffScreenBufferToVRAM( + _In_ PVOID Buffer) +{ + PUCHAR OffScreenBuffer = (PUCHAR)Buffer; + ULONG Row, Col; + + // ULONG Width, Height, Depth; + // FbConsGetDisplaySize(&Width, &Height, &Depth); + ULONG Width = FBCONS_WIDTH, Height = FBCONS_HEIGHT; + + for (Row = 0; Row < Height; ++Row) + { + for (Col = 0; Col < Width; ++Col) + { + FbConsPutChar(OffScreenBuffer[0], OffScreenBuffer[1], Col, Row); + OffScreenBuffer += VGA_CHAR_SIZE; + } + } +} + +VOID +FbConsScrollUp( + _In_ UCHAR Attr) +{ + UINT32 BgColor, Dummy; + FbConsAttrToColors(Attr, &Dummy, &BgColor); + VidFbScrollUp(BgColor, CHAR_HEIGHT); +} diff --git a/boot/freeldr/freeldr/arch/vidfb.h b/boot/freeldr/freeldr/arch/vidfb.h index 1aca5ae78fe..b409692da7d 100644 --- a/boot/freeldr/freeldr/arch/vidfb.h +++ b/boot/freeldr/freeldr/arch/vidfb.h @@ -21,10 +21,6 @@ VidFbClearScreenColor( _In_ UINT32 Color, _In_ BOOLEAN FullScreen); -VOID -VidFbClearScreen( - _In_ UCHAR Attr); - VOID VidFbOutputChar( _In_ UCHAR Char, @@ -33,13 +29,6 @@ VidFbOutputChar( _In_ UINT32 FgColor, _In_ UINT32 BgColor); -VOID -VidFbPutChar( - _In_ UCHAR Char, - _In_ UCHAR Attr, - _In_ ULONG X, - _In_ ULONG Y); - VOID VidFbGetDisplaySize( _Out_ PULONG Width, @@ -49,13 +38,10 @@ VidFbGetDisplaySize( ULONG VidFbGetBufferSize(VOID); -VOID -VidFbCopyOffScreenBufferToVRAM( - _In_ PVOID Buffer); - VOID VidFbScrollUp( - _In_ UCHAR Attr); + _In_ UINT32 Color, + _In_ ULONG Scroll); #if 0 VOID @@ -77,3 +63,51 @@ VidFbGetPaletteColor( _In_ UCHAR Color, _Out_ PUCHAR Red, _Out_ PUCHAR Green, _Out_ PUCHAR Blue); #endif + + + +/* + * PROJECT: FreeLoader + * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) + * or MIT (https://spdx.org/licenses/MIT) + * PURPOSE: Linear framebuffer based console support + * COPYRIGHT: Copyright 2025 Hermès Bélusca-Maïto + */ + +#pragma once + +VOID +FbConsClearScreen( + _In_ UCHAR Attr); + +VOID +FbConsOutputChar( + _In_ UCHAR Char, + _In_ ULONG Column, + _In_ ULONG Row, + _In_ UINT32 FgColor, + _In_ UINT32 BgColor); + +VOID +FbConsPutChar( + _In_ UCHAR Char, + _In_ UCHAR Attr, + _In_ ULONG Column, + _In_ ULONG Row); + +VOID +FbConsGetDisplaySize( + _Out_ PULONG Width, + _Out_ PULONG Height, + _Out_ PULONG Depth); + +ULONG +FbConsGetBufferSize(VOID); + +VOID +FbConsCopyOffScreenBufferToVRAM( + _In_ PVOID Buffer); + +VOID +FbConsScrollUp( + _In_ UCHAR Attr);