2 pcboot - bootable PC demo/game kernel
3 Copyright (C) 2018 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_setstart(int y);
48 static inline unsigned char crtc_read(int reg);
49 static inline void crtc_write(int reg, unsigned char val);
51 extern int cursor_x, cursor_y;
52 static unsigned char txattr = 0x07;
53 static int start_line;
54 static unsigned char cy0, cy1;
56 static int scr_on = 1;
61 ser_open(0, 9600, SER_8N1);
65 cy0 = crtc_read(CRTC_REG_CURSTART);
66 curvis = cy0 & 0x20 ? 1 : 0;
68 cy1 = crtc_read(CRTC_REG_CUREND) & 0x1f;
72 crtc_cursor(cursor_x, cursor_y);
79 void con_scr_enable(void)
84 void con_scr_disable(void)
89 void con_show_cursor(int show)
92 unsigned char val = cy0 & 0x1f;
96 crtc_write(CRTC_REG_CURSTART, val);
101 void con_cursor(int x, int y)
110 void con_curattr(int shape, int blink)
114 cy0 = (shape == CON_CURSOR_LINE) ? 0xd : 0;
122 crtc_write(CRTC_REG_CURSTART, start);
123 crtc_write(CRTC_REG_CUREND, cy0);
127 void con_fgcolor(int c)
129 txattr = (txattr & 0xf0) | c;
132 void con_bgcolor(int c)
134 txattr = (txattr & 0x0f) | (c << 4);
137 void con_setattr(unsigned char attr)
142 unsigned char con_getattr(void)
150 memset16(TEXT_ADDR, VMEM_CHAR(' ', txattr), NCOLS * NROWS);
155 cursor_x = cursor_y = 0;
160 static inline void linefeed(void)
162 if(++cursor_y >= NROWS) {
168 void con_putchar(int c)
177 crtc_cursor(cursor_x, cursor_y);
181 cursor_x = (cursor_x & 0x7) + 8;
182 if(cursor_x >= NCOLS) {
186 crtc_cursor(cursor_x, cursor_y);
190 if(cursor_x > 0) cursor_x--;
191 con_putchar_scr(cursor_x, cursor_y, ' ');
192 crtc_cursor(cursor_x, cursor_y);
196 con_putchar_scr(cursor_x, cursor_y, c);
198 if(++cursor_x >= NCOLS) {
202 crtc_cursor(cursor_x, cursor_y);
212 void con_putchar_scr(int x, int y, int c)
215 uint16_t *ptr = (uint16_t*)TEXT_ADDR;
216 ptr[(y + start_line) * NCOLS + x] = VMEM_CHAR(c, txattr);
220 int con_printf(int x, int y, const char *fmt, ...)
228 vsnprintf(buf, 80, fmt, ap);
231 while(*ptr && x < 80) {
232 con_putchar_scr(x++, y, *ptr++);
240 static void scroll(void)
244 if(++start_line > VIRT_ROWS - NROWS) {
245 /* The bottom of the visible range reached the end of our text buffer.
246 * Copy the rest of the lines to the top and reset start_line.
248 memcpy(TEXT_ADDR, TEXT_ADDR + start_line * NCOLS, (NROWS - 1) * NCOLS * 2);
252 /* clear the next line that will be revealed by scrolling */
253 new_line = start_line + NROWS - 1;
254 memset16(TEXT_ADDR + new_line * NCOLS * 2, VMEM_CHAR(' ', txattr), NCOLS);
255 crtc_setstart(start_line);
258 static void crtc_cursor(int x, int y)
262 addr = (y + start_line) * NCOLS + x;
264 crtc_write(CRTC_REG_CURLOC_L, addr);
265 crtc_write(CRTC_REG_CURLOC_H, addr >> 8);
268 static void crtc_setstart(int y)
270 unsigned int addr = y * NCOLS;
272 crtc_write(CRTC_REG_START_L, addr);
273 crtc_write(CRTC_REG_START_H, addr >> 8);
276 static inline unsigned char crtc_read(int reg)
278 outb(reg, CRTC_ADDR);
279 return inb(CRTC_DATA);
282 static inline void crtc_write(int reg, unsigned char val)
284 outb(reg, CRTC_ADDR);
285 outb(val, CRTC_DATA);