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) | ((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);
50 static inline void crtc_write_bits(int reg, unsigned char val, unsigned char mask);
52 extern int cursor_x, cursor_y;
53 static unsigned char txattr = 0x07;
54 static int start_line;
59 ser_open(0, 9600, SER_8N1);
65 crtc_cursor(cursor_x, cursor_y);
67 printf("curloc: %x %x\n", (unsigned int)crtc_read(CRTC_REG_CURLOC_H),
68 (unsigned int)crtc_read(CRTC_REG_CURLOC_L));
69 printf("curstart: %x\n", (unsigned int)crtc_read(CRTC_REG_CURSTART));
70 printf("curend: %x\n", (unsigned int)crtc_read(CRTC_REG_CUREND));
77 void con_show_cursor(int show)
80 unsigned char val = show ? 0 : 0x20;
82 crtc_write_bits(CRTC_REG_CURSTART, val, 0x20);
86 void con_cursor(int x, int y)
95 void con_fgcolor(int c)
97 txattr = (txattr & 0xf0) | c;
100 void con_bgcolor(int c)
102 txattr = (txattr & 0x0f) | (c << 4);
108 memset(TEXT_ADDR, 0, NCOLS * NROWS * 2);
113 cursor_x = cursor_y = 0;
118 static inline void linefeed(void)
120 if(++cursor_y >= NROWS) {
126 void con_putchar(int c)
136 crtc_cursor(cursor_x, cursor_y);
140 cursor_x = (cursor_x & 0x7) + 8;
141 if(cursor_x >= NCOLS) {
145 crtc_cursor(cursor_x, cursor_y);
149 con_putchar_scr(cursor_x, cursor_y, c);
151 if(++cursor_x >= NCOLS) {
155 crtc_cursor(cursor_x, cursor_y);
164 void con_putchar_scr(int x, int y, int c)
166 uint16_t *ptr = (uint16_t*)TEXT_ADDR;
167 ptr[(y + start_line) * NCOLS + x] = VMEM_CHAR(c, txattr);
170 void con_printf(int x, int y, const char *fmt, ...)
177 vsnprintf(buf, 80, fmt, ap);
180 while(*ptr && x < 80) {
181 con_putchar_scr(x++, y, *ptr++);
185 static void scroll(void)
189 if(++start_line > VIRT_ROWS - NROWS) {
190 /* The bottom of the visible range reached the end of our text buffer.
191 * Copy the rest of the lines to the top and reset start_line.
193 memcpy(TEXT_ADDR, TEXT_ADDR + start_line * NCOLS, (NROWS - 1) * NCOLS * 2);
197 /* clear the next line that will be revealed by scrolling */
198 new_line = start_line + NROWS - 1;
199 memset16(TEXT_ADDR + new_line * NCOLS * 2, VMEM_CHAR(' ', txattr), NCOLS);
200 crtc_setstart(start_line);
203 static void crtc_cursor(int x, int y)
207 addr = (y + start_line) * NCOLS + x;
209 crtc_write(CRTC_REG_CURLOC_L, addr);
210 crtc_write(CRTC_REG_CURLOC_H, addr >> 8);
213 static void crtc_setstart(int y)
215 unsigned int addr = y * NCOLS;
217 crtc_write(CRTC_REG_START_L, addr);
218 crtc_write(CRTC_REG_START_H, addr >> 8);
221 static inline unsigned char crtc_read(int reg)
223 outb(reg, CRTC_ADDR);
224 return inb(CRTC_DATA);
227 static inline void crtc_write(int reg, unsigned char val)
229 outb(reg, CRTC_ADDR);
230 outb(val, CRTC_DATA);
233 static inline void crtc_write_bits(int reg, unsigned char val, unsigned char mask)
236 outb(reg, CRTC_ADDR);
237 prev = inb(CRTC_DATA);
238 val = (prev & ~mask) | (val & mask);
239 outb(val, CRTC_DATA);