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

209 lines
5.9 KiB
C
Raw Normal View History

2019-01-14 14:31:49 +01:00
//----------------------------------------------------------------------------//
2020-09-27 17:33:48 +02:00
// OS on Kaleid //
2019-01-14 14:31:49 +01:00
// //
2019-02-06 14:07:38 +01:00
// Desc: VGA terminal functions //
2019-02-16 23:36:33 +01:00
// //
// //
// Copyright © 2018-2020 The OS/K Team //
2019-02-16 23:36:33 +01:00
// //
// 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/>. //
2019-01-14 14:31:49 +01:00
//----------------------------------------------------------------------------//
2020-02-19 22:19:58 +01:00
#include <libbuf.h>
2019-05-13 23:22:27 +02:00
#include <init/boot.h>
#include <io/cursor.h>
2019-05-18 22:02:16 +02:00
#include <io/vga.h>
const char *RtlColorNames[VGA_COLOR_WHITE+1] =
{
"Black", "Blue", "Green", "Cyan", "Red",
"Magenta", "Brown", "Light Grey", "Dark Grey",
"Light Blue", "Light Green", "Light Cyan",
"Light Red", "Light Magenta", "Light Brown", "White",
};
2019-01-14 14:31:49 +01:00
//
// 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)
2019-05-08 00:00:45 +02:00
static uint bscroll = 0;
2019-05-18 22:02:16 +02:00
static int bfg = VGA_COLOR_LIGHT_GREY;
static int bbg = VGA_COLOR_BLACK;
2019-05-08 00:00:45 +02:00
static int cursorOffset = 0;
2019-01-14 14:31:49 +01:00
//
// VGA Buffer Flusher
2019-01-14 14:31:49 +01:00
//
error_t bvgaflusher(Buffer_t *buf)
2019-01-14 14:31:49 +01:00
{
2019-04-06 07:53:58 +02:00
ushort *fbp = BtVideoInfo.framebufferAddr;
2019-05-18 22:02:16 +02:00
uint color = VGA_ComputeColorCode(bfg, bbg), cols = 0;
uint oldfg = bfg, skip, rem = BStdOut->lineLen;
2019-01-14 14:31:49 +01:00
2019-05-18 19:56:10 +02:00
uchar *currentLine = buf->wp - buf->lastLF;
uchar *bufStart = (uchar *)lmax((size_t)buf->buf,
(size_t)currentLine
2019-05-18 19:56:10 +02:00
- (buf->nLines - 1 + bscroll) * buf->lineLen);
2019-05-11 10:42:34 +02:00
uchar *ptr = bufStart;
2019-05-18 22:02:16 +02:00
for (skip = 0; ptr < buf->wp ; ptr++) {
// Handle color codes
if (*ptr >= RtlColorToChar(VGA_COLOR_BLACK)
&& *ptr <= RtlColorToChar(VGA_COLOR_WHITE)) {
2020-01-09 12:55:19 +01:00
skip++; cols++; // 'cols' (colors) is for scrolling
2019-05-18 22:02:16 +02:00
bfg = RtlCharToColor(*ptr);
}
// Write regular characters
else {
color = VGA_ComputeColorCode(bfg, bbg);
*fbp++ = VGA_ComputeEntry(*ptr, color);
}
// End of line?
if (--rem == 0) {
rem = BStdOut->lineLen;
cols = 0;
while (skip > 0) {
skip--;
*fbp++ = VGA_ComputeEntry(' ', color);
}
}
}
// Update the cursor
2019-05-18 22:02:16 +02:00
size_t curX = ((size_t)ptr - (size_t)bufStart - cols) % buf->lineLen;
size_t curY = ((size_t)ptr - (size_t)bufStart) / buf->lineLen;
IoUpdateCursor(max(min(curX + cursorOffset, buf->lineLen), 0), curY);
// Empty the rest of the buffer
2019-01-14 14:31:49 +01:00
const size_t bufSize = buf->nLines * buf->lineLen;
2019-04-06 07:53:58 +02:00
ushort *fbe = BtVideoInfo.framebufferAddr
2019-04-05 10:20:10 +02:00
+ (bufSize * sizeof(ushort));
2019-01-14 14:31:49 +01:00
if (fbp < fbe) {
const ushort filler = VGA_ComputeEntry(' ', color);
while (fbp < fbe) *fbp++ = filler;
}
2019-05-18 22:02:16 +02:00
bfg = oldfg;
2019-01-14 14:31:49 +01:00
2019-03-19 13:37:23 +01:00
return EOK;
2019-01-14 14:31:49 +01:00
}
int IoGetCursorOffset(void) {
return cursorOffset;
}
void IoSetCursorOffset(int ins) {
cursorOffset = ins;
}
2019-05-20 20:28:18 +02:00
uint IoGetScroll(void)
{
return bscroll;
}
2020-01-09 18:19:49 +01:00
void IoSetScroll(uint value)
{
bscroll = 0;
}
2019-05-08 00:00:45 +02:00
void IoScrollDown(void)
{
2019-05-18 19:57:57 +02:00
BLockBuf(BStdOut);
2019-05-08 00:00:45 +02:00
if (bscroll > 0)
bscroll--;
bvgaflusher(BStdOut);
2019-05-18 19:57:57 +02:00
BUnlockBuf(BStdOut);
2019-05-08 00:00:45 +02:00
}
void IoScrollUp(void)
{
2019-05-18 19:56:10 +02:00
BLockBuf(BStdOut);
uchar *currentLine = BStdOut->wp - BStdOut->lastLF;
2019-05-18 19:56:35 +02:00
2019-05-18 19:56:10 +02:00
// Scrollable lines
uint scrabble = max(0, (currentLine-BStdOut->buf)/BStdOut->lineLen
- BStdOut->nLines + 1);
if (bscroll < scrabble)
2019-05-08 00:00:45 +02:00
bscroll++;
2019-05-18 19:56:10 +02:00
2019-05-08 00:00:45 +02:00
bvgaflusher(BStdOut);
2019-05-18 19:56:10 +02:00
BUnlockBuf(BStdOut);
2019-05-08 00:00:45 +02:00
}
2019-05-18 22:02:16 +02:00
void IoChangeTermColor(int fg, int bg)
{
if (fg < 0) fg = bfg;
if (bg < 0) bg = bbg;
assert(fg <= VGA_COLOR_WHITE);
assert(bg <= VGA_COLOR_WHITE);
bfg = fg;
bbg = bg;
}
2019-05-08 00:00:45 +02:00
2019-01-14 14:31:49 +01:00
//
// Initialize VGA buffer
2019-02-06 14:07:38 +01:00
//
error_t IoInitVGABuffer(void)
2019-02-06 14:07:38 +01:00
{
2019-04-23 11:32:45 +02:00
static char bvgabufsrc[1 * MB];
static Buffer_t bvgabufstruct;
2020-02-06 13:18:22 +01:00
static char bdbgbufsrc[1 * MB];
static Buffer_t bdbgbufstruct;
2019-04-23 11:32:45 +02:00
BStdOut = &bvgabufstruct;
2019-05-07 22:32:17 +02:00
BOpenTermBufEx(&BStdOut,
2019-04-23 11:32:45 +02:00
bvgabufsrc, BS_WRONLY,
2019-04-06 07:53:58 +02:00
BtVideoInfo.framebufferWidth,
BtVideoInfo.framebufferHeight,
2019-05-08 00:00:45 +02:00
10, bvgaflusher);
2019-04-23 11:32:45 +02:00
BEnableAutoScroll(BStdOut);
2019-02-06 14:07:38 +01:00
2020-02-06 15:01:37 +01:00
#ifndef NDEBUG
2020-02-06 13:18:22 +01:00
BStdDbg = &bdbgbufstruct;
BOpenTermBufEx(&BStdDbg,
bdbgbufsrc, BS_WRONLY,
BtVideoInfo.framebufferWidth,
BtVideoInfo.framebufferHeight,
10, NULL);
BEnableAutoScroll(BStdDbg);
2020-02-06 15:01:37 +01:00
#else
BStdDbg = NULL;
#endif
2019-03-23 23:52:18 +01:00
return EOK;
2019-02-06 14:07:38 +01:00
}