#![warn(clippy::arithmetic)]
+mod vga;
+
use core::arch::asm;
-use core::ops::{Add, Mul};
use core::panic::PanicInfo;
-static HELLO: &[u8] = b"Hello Stage2!";
-
#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
#[no_mangle]
pub extern "C" fn _start() -> ! {
- let vga_buffer = 0xb8000 as *mut u8;
- let vga_max = 0xf9e;
-
- // Clear the screen
- for i in 0..vga_max {
- unsafe {
- *vga_buffer.offset((i as isize).mul(2)) = 0x00;
- *vga_buffer.offset((i as isize).mul(2).add(1)) = 0x07;
- }
- }
-
- // Print welcome message
- for (i, &byte) in HELLO.iter().enumerate() {
- unsafe {
- *vga_buffer.offset((i as isize).mul(2)) = byte;
- *vga_buffer.offset((i as isize).mul(2).add(1)) = 0x07;
- }
- }
+ vga::test_print();
unsafe {
loop {
--- /dev/null
+use core::ops::{AddAssign, Shl};
+
+#[allow(dead_code)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[repr(u8)]
+pub enum Color {
+ Black = 0,
+ Blue = 1,
+ Green = 2,
+ Cyan = 3,
+ Red = 4,
+ Magenta = 5,
+ Brown = 6,
+ LightGray = 7,
+ DarkGray = 8,
+ LightBlue = 9,
+ LightGreen = 10,
+ LightCyan = 11,
+ LightRed = 12,
+ Pink = 13,
+ Yellow = 14,
+ White = 15,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[repr(transparent)]
+pub struct ColorCode(u8);
+
+impl ColorCode {
+ pub fn new(foreground: Color, background: Color) -> ColorCode {
+ ColorCode((background as u8).shl(4) | (foreground as u8))
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+#[repr(C)]
+struct ScreenChar {
+ ascii_character: u8,
+ color_code: ColorCode,
+}
+
+const BUFFER_WIDTH: usize = 80;
+const BUFFER_HEIGHT: usize = 25;
+
+#[repr(transparent)]
+struct Buffer {
+ chars: [[ScreenChar; BUFFER_WIDTH]; BUFFER_HEIGHT],
+}
+
+pub struct Writer {
+ row_position: usize,
+ column_position: usize,
+ color_code: ColorCode,
+ buffer: &'static mut Buffer,
+}
+
+impl Writer {
+ pub fn write_byte(&mut self, byte: u8) {
+ match byte {
+ b'\n' => self.new_line(),
+ byte => {
+ if self.column_position >= BUFFER_WIDTH {
+ self.new_line();
+ }
+
+ let row = self.row_position;
+ let col = self.column_position;
+
+ let color_code = self.color_code;
+ self.buffer.chars[row][col] = ScreenChar {
+ ascii_character: byte,
+ color_code,
+ };
+
+ self.column_position.add_assign(1);
+ },
+ }
+ }
+
+ pub fn write_string(&mut self, s: &str) {
+ for byte in s.bytes() {
+ match byte {
+ // Printable ASCII character or \n
+ 0x20..=0x7e | b'\n' => self.write_byte(byte),
+ // Not printable, write error char instead
+ _ => self.write_byte(0xfe),
+ }
+ }
+ }
+
+ fn new_line(&mut self) {
+
+ }
+}
+
+pub fn test_print() {
+ let mut writer = Writer {
+ row_position: 1,
+ column_position: 0,
+ color_code: ColorCode::new(Color::Yellow, Color::Black),
+ buffer: unsafe { &mut *(0xb8000 as *mut Buffer) },
+ };
+
+ writer.write_string("Hello Stage2!");
+}