//----------------------------------------------------------------------------// // OS on Kaleid // // // // Desc: VGA terminal functions // // // // // // Copyright © 2018-2020 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 . // //----------------------------------------------------------------------------// #include #include #include #include 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", }; // // 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; static int bfg = VGA_COLOR_LIGHT_GREY; static int bbg = VGA_COLOR_BLACK; static int cursorOffset = 0; // // VGA Buffer Flusher // error_t bvgaflusher(Buffer_t *buf) { ushort *fbp = BtVideoInfo.framebufferAddr; uint color = VGA_ComputeColorCode(bfg, bbg), cols = 0; uint oldfg = bfg, skip, rem = BStdOut->lineLen; uchar *currentLine = buf->wp - buf->lastLF; uchar *bufStart = (uchar *)lmax((size_t)buf->buf, (size_t)currentLine - (buf->nLines - 1 + bscroll) * buf->lineLen); uchar *ptr = bufStart; for (skip = 0; ptr < buf->wp ; ptr++) { // Handle color codes if (*ptr >= RtlColorToChar(VGA_COLOR_BLACK) && *ptr <= RtlColorToChar(VGA_COLOR_WHITE)) { skip++; cols++; // 'cols' (colors) is for scrolling 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 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 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; } bfg = oldfg; return EOK; } int IoGetCursorOffset(void) { return cursorOffset; } void IoSetCursorOffset(int ins) { cursorOffset = ins; } uint IoGetScroll(void) { return bscroll; } void IoSetScroll(uint value) { bscroll = 0; } void IoScrollDown(void) { BLockBuf(BStdOut); if (bscroll > 0) bscroll--; bvgaflusher(BStdOut); BUnlockBuf(BStdOut); } void IoScrollUp(void) { BLockBuf(BStdOut); uchar *currentLine = BStdOut->wp - BStdOut->lastLF; // Scrollable lines uint scrabble = max(0, (currentLine-BStdOut->buf)/BStdOut->lineLen - BStdOut->nLines + 1); if (bscroll < scrabble) bscroll++; bvgaflusher(BStdOut); BUnlockBuf(BStdOut); } 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; } // // Initialize VGA buffer // error_t IoInitVGABuffer(void) { static char bvgabufsrc[1 * MB]; static Buffer_t bvgabufstruct; static char bdbgbufsrc[1 * MB]; static Buffer_t bdbgbufstruct; BStdOut = &bvgabufstruct; BOpenTermBufEx(&BStdOut, bvgabufsrc, BS_WRONLY, BtVideoInfo.framebufferWidth, BtVideoInfo.framebufferHeight, 10, bvgaflusher); BEnableAutoScroll(BStdOut); #ifndef NDEBUG BStdDbg = &bdbgbufstruct; BOpenTermBufEx(&BStdDbg, bdbgbufsrc, BS_WRONLY, BtVideoInfo.framebufferWidth, BtVideoInfo.framebufferHeight, 10, NULL); BEnableAutoScroll(BStdDbg); #else BStdDbg = NULL; #endif return EOK; }