2 pcboot - bootable PC demo/game kernel
3 Copyright (C) 2018-2023 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY, without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
30 #define TEXT_ADDR ((char*)0xb8000)
32 #define CRTC_ADDR 0x3d4
33 #define CRTC_DATA 0x3d5
35 #define CRTC_REG_CURSTART 0x0a
36 #define CRTC_REG_CUREND 0x0b
37 #define CRTC_REG_START_H 0x0c
38 #define CRTC_REG_START_L 0x0d
39 #define CRTC_REG_CURLOC_H 0x0e
40 #define CRTC_REG_CURLOC_L 0x0f
42 #define VMEM_CHAR(c, attr) \
43 (((uint16_t)(c) & 0xff) | ((uint16_t)(attr) << 8))
45 static void scroll(void);
46 static void crtc_cursor(int x, int y);
47 static void crtc_getcursor(int *x, int *y);
48 static void crtc_setstart(int y);
49 static inline unsigned char crtc_read(int reg);
50 static inline void crtc_write(int reg, unsigned char val);
52 static int cursor_x, cursor_y;
53 static unsigned char txattr = 0x07;
54 static int start_line;
55 static unsigned char cy0, cy1;
57 static int scr_on = 1;
62 ser_open(1, 9600, SER_8N1);
66 cy0 = crtc_read(CRTC_REG_CURSTART);
67 curvis = cy0 & 0x20 ? 1 : 0;
69 cy1 = crtc_read(CRTC_REG_CUREND) & 0x1f;
71 crtc_getcursor(&cursor_x, &cursor_y);
80 void con_scr_enable(void)
85 void con_scr_disable(void)
90 void con_show_cursor(int show)
93 unsigned char val = cy0 & 0x1f;
97 crtc_write(CRTC_REG_CURSTART, val);
102 void con_cursor(int x, int y)
111 void con_curattr(int shape, int blink)
115 cy0 = (shape == CON_CURSOR_LINE) ? 0xd : 0;
123 crtc_write(CRTC_REG_CURSTART, start);
124 crtc_write(CRTC_REG_CUREND, cy0);
128 void con_fgcolor(int c)
130 txattr = (txattr & 0xf0) | c;
133 void con_bgcolor(int c)
135 txattr = (txattr & 0x0f) | (c << 4);
138 void con_setattr(unsigned char attr)
143 unsigned char con_getattr(void)
151 memset16(TEXT_ADDR, VMEM_CHAR(' ', txattr), NCOLS * NROWS);
156 cursor_x = cursor_y = 0;
161 static inline void linefeed(void)
163 if(++cursor_y >= NROWS) {
169 void con_putchar(int c)
178 crtc_cursor(cursor_x, cursor_y);
182 cursor_x = (cursor_x & 0x7) + 8;
183 if(cursor_x >= NCOLS) {
187 crtc_cursor(cursor_x, cursor_y);
191 if(cursor_x > 0) cursor_x--;
192 con_putchar_scr(cursor_x, cursor_y, ' ');
193 crtc_cursor(cursor_x, cursor_y);
197 con_putchar_scr(cursor_x, cursor_y, c);
199 if(++cursor_x >= NCOLS) {
203 crtc_cursor(cursor_x, cursor_y);
213 void con_putchar_scr(int x, int y, int c)
216 uint16_t *ptr = (uint16_t*)TEXT_ADDR;
217 ptr[(y + start_line) * NCOLS + x] = VMEM_CHAR(c, txattr);
221 int con_printf(int x, int y, const char *fmt, ...)
229 vsnprintf(buf, 80, fmt, ap);
232 while(*ptr && x < 80) {
233 con_putchar_scr(x++, y, *ptr++);
241 static void scroll(void)
245 if(++start_line > VIRT_ROWS - NROWS) {
246 /* The bottom of the visible range reached the end of our text buffer.
247 * Copy the rest of the lines to the top and reset start_line.
249 memcpy(TEXT_ADDR, TEXT_ADDR + start_line * NCOLS, (NROWS - 1) * NCOLS * 2);
253 /* clear the next line that will be revealed by scrolling */
254 new_line = start_line + NROWS - 1;
255 memset16(TEXT_ADDR + new_line * NCOLS * 2, VMEM_CHAR(' ', txattr), NCOLS);
256 crtc_setstart(start_line);
259 static void crtc_cursor(int x, int y)
263 addr = (y + start_line) * NCOLS + x;
265 crtc_write(CRTC_REG_CURLOC_L, addr);
266 crtc_write(CRTC_REG_CURLOC_H, addr >> 8);
269 static void crtc_getcursor(int *x, int *y)
273 addr = crtc_read(CRTC_REG_CURLOC_L);
274 addr |= (unsigned int)crtc_read(CRTC_REG_CURLOC_H) << 8;
276 *y = addr / NCOLS - start_line;
280 static void crtc_setstart(int y)
282 unsigned int addr = y * NCOLS;
284 crtc_write(CRTC_REG_START_L, addr);
285 crtc_write(CRTC_REG_START_H, addr >> 8);
288 static inline unsigned char crtc_read(int reg)
290 outp(CRTC_ADDR, reg);
291 return inp(CRTC_DATA);
294 static inline void crtc_write(int reg, unsigned char val)
296 outp(CRTC_ADDR, reg);
297 outp(CRTC_DATA, val);