From 8c51bd1aefa3153bdc54d2d6be182d62f4afef3d Mon Sep 17 00:00:00 2001
From: Eemeli Lehtonen <eemeli.o.lehtonen@utu.fi>
Date: Mon, 9 Jan 2023 21:51:27 +0200
Subject: [PATCH] unifont downloader

---
 build.rs                              | 35 +++++++++++++++++++-
 src/arch/x86_64/limine/framebuffer.rs |  6 ++--
 src/arch/x86_64/limine/term.rs        |  2 +-
 src/main.rs                           |  3 ++
 src/qemu.rs                           | 10 +++---
 src/video/font.rs                     | 46 ++++++++++++++++++++++++---
 src/video/framebuffer.rs              | 27 +++++++++++++---
 7 files changed, 111 insertions(+), 18 deletions(-)

diff --git a/build.rs b/build.rs
index b53fae9..14da3e8 100644
--- a/build.rs
+++ b/build.rs
@@ -1,4 +1,12 @@
-use std::{env::var, error::Error};
+use std::{
+    env::var,
+    error::Error,
+    fs::{self, File, OpenOptions},
+    io::Read,
+    io::Write,
+    path::PathBuf,
+    process::Command,
+};
 
 //
 
@@ -35,5 +43,30 @@ fn main() -> Result<(), Box<dyn Error>> {
         panic!();
     };
 
+    let unifont_path = "target/hyperion/unifont.bmp";
+    let read_unifont = || {
+        let mut file = OpenOptions::new()
+            .read(true)
+            .create(false)
+            .write(false)
+            .open(unifont_path)?;
+
+        let mut buf = Vec::new();
+        file.read_to_end(buf)?;
+        Ok::<_, Box<dyn Error>>(buf)
+    };
+
+    let unifont = if let Ok(file) = read_unifont() {
+        file
+    } else {
+        Command::new("wget")
+            .arg("http://unifoundry.com/pub/unifont/unifont-15.0.01/unifont-15.0.01.bmp")
+            .args(["-O", unifont_path])
+            .spawn()
+            .unwrap();
+
+        read_unifont().unwrap()
+    };
+
     Ok(())
 }
diff --git a/src/arch/x86_64/limine/framebuffer.rs b/src/arch/x86_64/limine/framebuffer.rs
index 70df236..8b53040 100644
--- a/src/arch/x86_64/limine/framebuffer.rs
+++ b/src/arch/x86_64/limine/framebuffer.rs
@@ -2,9 +2,9 @@ use crate::{
     println,
     video::framebuffer::{Framebuffer, FBO},
 };
-use core::{ops::Deref, slice};
-use limine::{LimineFramebuffer, LimineFramebufferRequest, LimineFramebufferResponse};
-use spin::{Lazy, Mutex, MutexGuard};
+use core::slice;
+use limine::LimineFramebufferRequest;
+use spin::Mutex;
 
 //
 
diff --git a/src/arch/x86_64/limine/term.rs b/src/arch/x86_64/limine/term.rs
index 97446b7..7840026 100644
--- a/src/arch/x86_64/limine/term.rs
+++ b/src/arch/x86_64/limine/term.rs
@@ -19,7 +19,7 @@ unsafe impl Send for Writer {}
 
 impl Write for Writer {
     fn write_str(&mut self, s: &str) -> fmt::Result {
-        let mut write = self.0.write().ok_or(fmt::Error)?;
+        let write = self.0.write().ok_or(fmt::Error)?;
 
         for term in self.0.terminals() {
             write(term, s);
diff --git a/src/main.rs b/src/main.rs
index 4d81da6..420484f 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -53,6 +53,8 @@ fn kernel_main() -> ! {
         fbo.fill(40, 40, 40, 40, Color::RED);
         fbo.fill(50, 50, 60, 40, Color::GREEN);
         fbo.fill(5, 15, 80, 20, Color::BLUE);
+
+        fbo.put_bytes(100, 100, b"ABABABAB\0", Color::WHITE, Color::BLACK);
     }
 
     #[cfg(test)]
@@ -61,6 +63,7 @@ fn kernel_main() -> ! {
     arch::done();
 }
 
+#[allow(unused)]
 fn stack_overflow(n: usize) {
     if n == 0 {
         return;
diff --git a/src/qemu.rs b/src/qemu.rs
index cb30c3a..f65d38d 100644
--- a/src/qemu.rs
+++ b/src/qemu.rs
@@ -1,7 +1,4 @@
-use core::{
-    fmt::{Arguments, Write},
-    sync::atomic::AtomicUsize,
-};
+use core::fmt::{Arguments, Write};
 use spin::{Lazy, Mutex};
 use uart_16550::SerialPort;
 
@@ -16,6 +13,9 @@ pub fn _print(args: Arguments) {
 }
 
 /// Unlocks the COM1 writer IF it is locked by this exact thread
+///
+/// SAFETY: this is unsafe unless called from the same thread, this is intended for double fault
+/// handling
 pub unsafe fn unlock() {
     // TODO: SMP
     // if COM1_LOCKER.load(Ordering::SeqCst) != crate::THREAD {
@@ -27,7 +27,7 @@ pub unsafe fn unlock() {
 
 //
 
-static COM1_LOCKER: AtomicUsize = AtomicUsize::new(0);
+// static COM1_LOCKER: AtomicUsize = AtomicUsize::new(0);
 static COM1: Lazy<Mutex<SerialPort>> = Lazy::new(|| {
     let mut port = unsafe { SerialPort::new(0x3f8) };
     port.init();
diff --git a/src/video/font.rs b/src/video/font.rs
index 9d16b72..25a6137 100644
--- a/src/video/font.rs
+++ b/src/video/font.rs
@@ -3,14 +3,13 @@
 //     bitmap: [u8; 16],
 // }
 
+#[allow(clippy::unusual_byte_groupings)]
 pub static FONT: [[u8; 16]; 256] = {
-    let mut font = [[0u8; 16]; 256];
-
-    font[b'a' as usize] = [
+    let default = [
         0b_11111111,
         0b_11111111,
         0b_11000011,
-        0b_11000011,
+        0b_11000011, //
         0b_11000011,
         0b_11000011,
         0b_11000011,
@@ -25,5 +24,44 @@ pub static FONT: [[u8; 16]; 256] = {
         0b_11111111,
     ];
 
+    let mut font = [default; 256];
+
+    font[b'A' as usize] = [
+        0b_00000000,
+        0b_00000000,
+        0b_00000000, //
+        0b_01111110,
+        0b_11111111,
+        0b_11100111,
+        0b_11000011,
+        0b_11111111,
+        0b_11111111,
+        0b_11000011,
+        0b_11000011,
+        0b_11000011,
+        0b_11000011,
+        0b_00000000, //
+        0b_00000000,
+        0b_00000000,
+    ];
+    font[b'B' as usize] = [
+        0b_00000000,
+        0b_00000000,
+        0b_00000000, //
+        0b_11111110,
+        0b_11111111,
+        0b_11000111,
+        0b_11000111,
+        0b_11111110,
+        0b_11111110,
+        0b_11000111,
+        0b_11000111,
+        0b_11111111,
+        0b_11111110,
+        0b_00000000, //
+        0b_00000000,
+        0b_00000000,
+    ];
+
     font
 };
diff --git a/src/video/framebuffer.rs b/src/video/framebuffer.rs
index 1f96c5c..e26a9cb 100644
--- a/src/video/framebuffer.rs
+++ b/src/video/framebuffer.rs
@@ -1,7 +1,5 @@
-use core::{
-    fmt,
-    ops::{Deref, DerefMut},
-};
+use super::font::FONT;
+use core::fmt;
 use spin::{Mutex, Once};
 
 //
@@ -40,10 +38,31 @@ impl Framebuffer {
             }
         }
     }
+
+    pub fn put_byte(&mut self, x: usize, y: usize, ch: u8, fg: Color, bg: Color) {
+        let map = FONT[ch as usize];
+
+        for (yd, row) in map.into_iter().enumerate() {
+            for xd in 0..8 {
+                self.set(
+                    x + xd,
+                    y + yd,
+                    if (row & 1 << (7 - xd)) != 0 { fg } else { bg },
+                );
+            }
+        }
+    }
+
+    pub fn put_bytes(&mut self, x: usize, y: usize, s: &[u8], fg: Color, bg: Color) {
+        for (offs, ch) in s.iter().enumerate() {
+            self.put_byte(x + 12 * offs, y, *ch, fg, bg)
+        }
+    }
 }
 
 impl Color {
     pub const WHITE: Color = Color::new(0xff, 0xff, 0xff);
+    pub const BLACK: Color = Color::new(0x00, 0x00, 0x00);
 
     pub const RED: Color = Color::new(0xff, 0x00, 0x00);
     pub const GREEN: Color = Color::new(0x00, 0xff, 0x00);
-- 
GitLab