From d726c9e50a096d9f87affae5ebabfd34dae23333 Mon Sep 17 00:00:00 2001
From: Bensong Liu <bensl@microsoft.com>
Date: Mon, 2 Nov 2020 18:18:55 +0800
Subject: [PATCH] println working

---
 kernel/include/stdlib.hpp | 22 +++++++++++++++++
 kernel/include/vga.hpp    | 52 ++++++++++++++++++++++++++++++++-------
 kernel/kernel.cc          |  5 ++++
 3 files changed, 70 insertions(+), 9 deletions(-)
 create mode 100644 kernel/include/stdlib.hpp

diff --git a/kernel/include/stdlib.hpp b/kernel/include/stdlib.hpp
new file mode 100644
index 0000000..dfeffc2
--- /dev/null
+++ b/kernel/include/stdlib.hpp
@@ -0,0 +1,22 @@
+#ifndef ROS_KERN_STDLIB_HPP
+#define ROS_KERN_STDLIB_HPP
+
+#include "stdint.hpp"
+
+template <typename T>
+inline void memcpy(T *dst, const T *src, size_t count) {
+    for(auto i = 0; i < count; ++i) {
+        dst[i] = src[i];
+    }
+}
+template <typename T>
+inline void memset(T *dst, const T &data_to_set, size_t count) {
+    char *cdst = reinterpret_cast<char *>(dst);
+
+    for(auto i = 0; i < count; ++i) {
+        cdst[i] = data_to_set;
+    }
+}
+
+
+#endif
diff --git a/kernel/include/vga.hpp b/kernel/include/vga.hpp
index b6925ed..ffebbc3 100644
--- a/kernel/include/vga.hpp
+++ b/kernel/include/vga.hpp
@@ -1,17 +1,51 @@
 #ifndef ROS_KERN_VGA_HPP
 #define ROS_KERN_VGA_HPP
 
-inline char *vga_begin = (char *)0xb8000;
-void push_char(char c, char color) {
-    static int pos = 0;
-    vga_begin[pos++] = c;
-    vga_begin[pos++] = color;
+#include "stdint.hpp"
+#include "stdlib.hpp"
+
+#define VGA_BEGIN_ADDR ((uint16_t *)0xb8000)
+constexpr uint16_t VGA_WIDTH = 80;
+constexpr uint16_t VGA_HEIGHT = 25;
+constexpr uint16_t VGA_MAKE_CHAR(char c, uint8_t color) {
+    return (color << 8) + uint8_t(c);
+}
+constexpr uint8_t default_color = 0x0f;
+
+
+inline void trigger_scroll(uint16_t *pos) {
+    for(uint16_t row = 1; row < VGA_HEIGHT; ++row) {
+        memcpy(VGA_BEGIN_ADDR + (row-1)*VGA_WIDTH, VGA_BEGIN_ADDR + row*VGA_WIDTH, VGA_WIDTH);
+    }
+    memset(VGA_BEGIN_ADDR + (VGA_HEIGHT-1)*VGA_WIDTH, VGA_MAKE_CHAR(0, 0), VGA_WIDTH);
+    (*pos) -= VGA_WIDTH;
+}
+
+inline void set_char(uint16_t x, uint16_t y, char c, char color) {
+    VGA_BEGIN_ADDR[y*VGA_WIDTH + x] = VGA_MAKE_CHAR(c, color);
+}
+
+inline void put_char(char c, uint8_t color) {
+    static uint16_t pos = 0;
+    if(pos >= VGA_WIDTH * VGA_HEIGHT)
+        trigger_scroll(&pos);
+
+    switch(c) {
+    case '\n':
+        pos += VGA_WIDTH;
+        [[fallthrough]]; // unix \n implies \r.
+    case '\r':
+        pos -= pos % VGA_WIDTH;
+        break;
+    default:
+        VGA_BEGIN_ADDR[pos++] = VGA_MAKE_CHAR(c, color);
+    }
 }
 
-void set_char(int x, int y, char c, char color) {
-    auto pos = x + 80 * y;
-    vga_begin[pos*2] = c;
-    vga_begin[pos*2+1] = color;
+inline void print(const char *cstr, uint8_t color = default_color) {
+    while(*cstr != '\0') {
+        put_char(*(cstr++), color);
+    }
 }
 
 #endif
\ No newline at end of file
diff --git a/kernel/kernel.cc b/kernel/kernel.cc
index d1c4e40..5419de6 100644
--- a/kernel/kernel.cc
+++ b/kernel/kernel.cc
@@ -17,5 +17,10 @@ void main() {
             set_char(x, y, c, color);
         }
     }
+    print("Hello world!\n");
+    print("Hello world!\n", 0xb1);
+    print("Hello world!\n", 0xae);
+    print("Hello world!\n", 0x5c);
+    print("Hello world!\n");
 }
 
-- 
GitLab