os-k/kaleid/kernel/io/vga.c

120 lines
3.9 KiB
C

//----------------------------------------------------------------------------//
// GNU GPL OS/K //
// //
// Desc: VGA terminal functions //
// //
// //
// Copyright © 2018-2019 The OS/K Team //
// //
// This file is part of OS/K. //
// //
// OS/K is free software: you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation, either version 3 of the License, or //
// any later version. //
// //
// OS/K is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY//without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with OS/K. If not, see <https://www.gnu.org/licenses/>. //
//----------------------------------------------------------------------------//
#include <lib/buf.h>
#include <init/boot.h>
#include <io/cursor.h>
//
// VGA-related macros
//
#define VGA_ComputeColorCode(fg, bg) ((fg) | (bg) << 4)
#define VGA_ComputeOffset(term, x, y) ((y) * (term)->width + (x))
#define VGA_ComputeEntry(ch, cl) (((ushort)(ch)) | (ushort)(cl) << 8)
static uint bscroll = 0;
//
// VGA Buffer Flusher
//
error_t bvgaflusher(Buffer_t *buf)
{
ushort *fbp = BtVideoInfo.framebufferAddr;
uchar color = 0xf;
uchar *currentLine = buf->wp - buf->lineLen - buf->lastLF;
uchar *bufStart = (uchar *)lmax((size_t)buf->buf,
(size_t)currentLine
- (buf->nLines - 2 + bscroll) * buf->lineLen);
uchar *ptr = bufStart;
// Writes the buffer's content
for (; ptr < buf->wp ; ptr++) {
*fbp++ = VGA_ComputeEntry(*ptr, color);
}
// Update the cursor
size_t curX = ((size_t)ptr - (size_t)bufStart) % buf->lineLen;
size_t curY = ((size_t)ptr - (size_t)bufStart) / buf->lineLen;
IoUpdateCursor(curX, curY);
// Empty the rest of the buffer
const size_t bufSize = buf->nLines * buf->lineLen;
ushort *fbe = BtVideoInfo.framebufferAddr
+ (bufSize * sizeof(ushort));
if (fbp < fbe) {
const ushort filler = VGA_ComputeEntry(' ', color);
while (fbp < fbe) *fbp++ = filler;
}
return EOK;
}
void IoScrollDown(void)
{
if (bscroll > 0)
bscroll--;
bvgaflusher(BStdOut);
}
void IoScrollUp(void)
{
// Keep the 8 below the 10 given to BOpenTermBufEx
if (bscroll < BtVideoInfo.framebufferHeight * 8) /* XXX */
bscroll++;
bvgaflusher(BStdOut);
}
//
// Initialize VGA buffer
//
error_t IoInitVGABuffer(void)
{
static char bvgabufsrc[1 * MB];
static Buffer_t bvgabufstruct;
BStdOut = &bvgabufstruct;
BOpenTermBufEx(&BStdOut,
bvgabufsrc, BS_WRONLY,
BtVideoInfo.framebufferWidth,
BtVideoInfo.framebufferHeight,
10, bvgaflusher);
BEnableAutoScroll(BStdOut);
BStdDbg = BStdOut;
return EOK;
}