rudimentary console
[3sys] / sys1 / kern / src / con.c
diff --git a/sys1/kern/src/con.c b/sys1/kern/src/con.c
new file mode 100644 (file)
index 0000000..b110272
--- /dev/null
@@ -0,0 +1,90 @@
+#include <string.h>
+#include "con.h"
+#include "vga.h"
+
+#define NCOLS                  80
+#define NROWS                  25
+
+/* must be pow2 */
+#define TEXTBUF_SIZE   256
+
+static char textbuf[TEXTBUF_SIZE][NCOLS];
+static int tbuf_first, tbuf_last;
+
+static int curx, cury, scroll;
+
+
+static void newline(void);
+
+
+void con_init(void)
+{
+       con_reset();
+}
+
+void con_reset(void)
+{
+       vga_reset();
+
+       curx = cury = scroll = 0;
+       tbuf_first = tbuf_last = 0;
+       memset(textbuf[0], 0, sizeof textbuf[0]);
+}
+
+void con_putchar(int c)
+{
+       switch(c) {
+       case '\t':
+               curx = (curx + 8) & 0xfffffff8;
+               if(curx >= NCOLS) {
+                       newline();
+               }
+               break;
+
+       case '\r':
+               curx = 0;
+               break;
+
+       case '\n':
+               newline();
+               break;
+
+       case '\b':
+               if(curx > 0) {
+                       textbuf[tbuf_last][--curx] = 0;
+                       vga_drawchar(curx, cury, 0);
+               }
+               break;
+
+       default:
+               textbuf[tbuf_last][curx] = c;
+               vga_drawchar(curx, cury, c);
+               if(++curx >= NCOLS) {
+                       newline();
+               }
+               break;
+       }
+
+       if(cury >= NROWS) {
+               cury--;
+               vga_scroll(++scroll);
+               vga_clearline(NROWS - 1);
+       }
+
+       vga_setcursor(curx, cury);
+}
+
+static void newline(void)
+{
+       int num;
+
+       curx = 0;
+       cury++;
+
+       num = (tbuf_last + 1) & (TEXTBUF_SIZE - 1);
+
+       if(tbuf_last == tbuf_first) {
+               tbuf_first = num;
+       }
+       tbuf_last = num;
+}