From 3ef95940a706206f4f4472414dd10492e00872b2 Mon Sep 17 00:00:00 2001 From: csd4ni3l Date: Sun, 29 Mar 2026 14:38:43 +0200 Subject: [PATCH] Remove micromath dependency, improve primitive drawing speed by 300x, add mouse support and interrupts on x86_64 using a ps2 mouse which needed pic unmasking, add span filling to framebuffer, add back without_interrupts to serial console and framebuffer, add a mouse rectangle which tracks the mouse position and test the performance of the drawing. --- kernel/Cargo.lock | 7 - kernel/Cargo.toml | 1 - kernel/src/arch/x86_64/init.rs | 17 +- kernel/src/arch/x86_64/interrupts.rs | 30 ++- kernel/src/arch/x86_64/mod.rs | 1 + kernel/src/arch/x86_64/mouse.rs | 230 ++++++++++++++++++++++ kernel/src/driver/graphics/framebuffer.rs | 25 ++- kernel/src/driver/graphics/primitives.rs | 79 ++++++-- kernel/src/driver/mod.rs | 1 + kernel/src/driver/mouse.rs | 67 +++++++ kernel/src/driver/serial.rs | 10 +- kernel/src/main.rs | 78 ++++++-- kernel/src/util.rs | 4 + 13 files changed, 494 insertions(+), 56 deletions(-) create mode 100644 kernel/src/arch/x86_64/mouse.rs create mode 100644 kernel/src/driver/mouse.rs diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 3c015d6..fbd9c05 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -9,7 +9,6 @@ dependencies = [ "font8x8", "lazy_static", "limine", - "micromath", "pc-keyboard", "pic8259", "spin 0.10.0", @@ -67,12 +66,6 @@ dependencies = [ "scopeguard", ] -[[package]] -name = "micromath" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c8dda44ff03a2f238717214da50f65d5a53b45cd213a7370424ffdb6fae815" - [[package]] name = "pc-keyboard" version = "0.8.0" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 2051cf7..c033120 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -12,7 +12,6 @@ bench = false font8x8 = { version = "0.3.1", default-features = false } lazy_static = { version = "1.5.0", features = ["spin_no_std"] } limine = "0.5" -micromath = "2.1.0" pc-keyboard = "0.8.0" pic8259 = "0.11.0" spin = "0.10.0" diff --git a/kernel/src/arch/x86_64/init.rs b/kernel/src/arch/x86_64/init.rs index da773f0..9298c1c 100644 --- a/kernel/src/arch/x86_64/init.rs +++ b/kernel/src/arch/x86_64/init.rs @@ -1,5 +1,11 @@ -use crate::arch::x86_64::gdt::load_gdt_x86_64; -use crate::arch::x86_64::interrupts::{InterruptIndex, PICS, init_idt_x86_64}; +use crate::{ + arch::x86_64::{ + gdt::load_gdt_x86_64, + interrupts::{PICS, init_idt_x86_64}, + mouse::setup_mouse, + }, + driver::mouse::MOUSE, +}; use limine::response::{HhdmResponse, MemoryMapResponse}; use x86_64::instructions::interrupts::without_interrupts; use x86_64::instructions::{interrupts, port::Port}; @@ -49,9 +55,12 @@ pub fn init_x86_64<'a>( unsafe { let mut pics = PICS.lock(); pics.initialize(); - pics.write_masks(0xFC, 0xFF); + let master_mask = 0xF8; // unmask cascade to slave + let slave_mask = 0xEF; // unmask mouse interrupt (clear bit 4) + pics.write_masks(master_mask, slave_mask); } + let mouse_status = setup_mouse(); set_pit_interval(); interrupts::enable(); @@ -63,5 +72,7 @@ pub fn init_x86_64<'a>( .ok() .expect("Failed to initalize heap"); + MOUSE.set_status(mouse_status); + return (mapper, frame_allocator); } diff --git a/kernel/src/arch/x86_64/interrupts.rs b/kernel/src/arch/x86_64/interrupts.rs index 9a653e0..ee00621 100644 --- a/kernel/src/arch/x86_64/interrupts.rs +++ b/kernel/src/arch/x86_64/interrupts.rs @@ -1,3 +1,5 @@ +use crate::arch::x86_64::mouse::mouse_interrupt; +use crate::driver::mouse::MOUSE; use crate::driver::timer::TIMER; use crate::{arch::x86_64::gdt, driver::keyboard::keyboard_interrupt_handler, println}; use lazy_static::lazy_static; @@ -20,16 +22,16 @@ pub static PICS: Mutex = pub enum InterruptIndex { Timer = PIC_1_OFFSET, Keyboard = PIC_1_OFFSET + 1, + Mouse = PIC_2_OFFSET + 4, + // RTC = PIC_2_OFFSET, + // ATA_primary = PIC_2_OFFSET + 7 + // ATA_secondary = PIC_2_OFFSET + 8 } impl InterruptIndex { pub fn as_u8(self) -> u8 { self as u8 } - - fn as_usize(self) -> usize { - usize::from(self.as_u8()) - } } lazy_static! { @@ -45,6 +47,7 @@ lazy_static! { idt.page_fault.set_handler_fn(page_fault_handler); idt.general_protection_fault.set_handler_fn(gpf_handler); idt[InterruptIndex::Keyboard.as_u8()].set_handler_fn(keyboard_interrupt_handler); + idt[InterruptIndex::Mouse.as_u8()].set_handler_fn(mouse_interrupt_handler); idt }; } @@ -91,3 +94,22 @@ extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFr .notify_end_of_interrupt(InterruptIndex::Timer.as_u8()); } } + +extern "x86-interrupt" fn mouse_interrupt_handler(_stack_frame: InterruptStackFrame) { + let interrupt_result = mouse_interrupt(); + + if let Some(interrupt_result) = interrupt_result { + MOUSE.interrupt( + interrupt_result.0, + interrupt_result.1, + interrupt_result.2, + interrupt_result.3, + interrupt_result.4, + ); + } + + unsafe { + PICS.lock() + .notify_end_of_interrupt(InterruptIndex::Mouse.as_u8()); + } +} diff --git a/kernel/src/arch/x86_64/mod.rs b/kernel/src/arch/x86_64/mod.rs index fcb0d9d..1bc740e 100644 --- a/kernel/src/arch/x86_64/mod.rs +++ b/kernel/src/arch/x86_64/mod.rs @@ -2,4 +2,5 @@ pub mod gdt; pub mod heap; pub mod init; pub mod interrupts; +pub mod mouse; pub mod paging; diff --git a/kernel/src/arch/x86_64/mouse.rs b/kernel/src/arch/x86_64/mouse.rs new file mode 100644 index 0000000..2199a04 --- /dev/null +++ b/kernel/src/arch/x86_64/mouse.rs @@ -0,0 +1,230 @@ +// Comment to self: WHY IS THIS SOO HARD + +use crate::util::get_bit; +use core::sync::atomic::{AtomicU8, Ordering}; + +use x86_64::instructions::{interrupts::without_interrupts, port::Port}; + +static CURRENTLY_RECEIVING_STATE: AtomicU8 = AtomicU8::new(0); +static FLAGS_BYTE: AtomicU8 = AtomicU8::new(0); +static X_DELTA_BYTE: AtomicU8 = AtomicU8::new(0); +static Y_DELTA_BYTE: AtomicU8 = AtomicU8::new(0); + +fn wait_input_buffer_clear(command_port: &mut Port) { + unsafe { + loop { + let status = command_port.read(); + // IBF is bit 1: clear means we can write + if (status & 0b10) == 0 { + break; + } + } + } +} + +fn wait_output_buffer_full(command_port: &mut Port) { + unsafe { + loop { + let status = command_port.read(); + // OBF is bit 0: 1 = data available to read + if (status & 0b1) != 0 { + break; + } + } + } +} + +fn read_ccb(command_port: &mut Port, data_port: &mut Port) -> u8 { + unsafe { + wait_input_buffer_clear(command_port); + command_port.write(0x20); + wait_output_buffer_full(command_port); + return data_port.read(); + } +} +fn write_ccb(command_port: &mut Port, data_port: &mut Port, value: u8) { + unsafe { + wait_input_buffer_clear(command_port); + command_port.write(0x60); + wait_input_buffer_clear(command_port); + data_port.write(value); + } +} + +fn check_clear_and_write(command_port: &mut Port, inst: u8) { + unsafe { + wait_input_buffer_clear(command_port); + command_port.write(inst); + } +} + +fn write_and_expect_output( + command_port: &mut Port, + data_port: &mut Port, + inst: u8, + expected_output: u8, +) -> bool { + unsafe { + check_clear_and_write(command_port, inst); + wait_output_buffer_full(command_port); + return data_port.read() == expected_output; + } +} + +fn clear_and_expect_output( + command_port: &mut Port, + data_port: &mut Port, + expected_output: u8, +) -> bool { + unsafe { + wait_input_buffer_clear(command_port); + wait_output_buffer_full(command_port); + return data_port.read() == expected_output; + } +} + +pub fn setup_mouse() -> u8 { + without_interrupts(|| { + let mut command_port: Port = Port::new(0x64); + let mut data_port: Port = Port::new(0x60); + + unsafe { + check_clear_and_write(&mut command_port, 0xAD); // disable port 1 + check_clear_and_write(&mut command_port, 0xA7); // disable port 2 + + let mut ccb = read_ccb(&mut command_port, &mut data_port); + + ccb = ccb | 0b00000001; // enable keyboard IRQ + ccb = ccb | 0b00000010; // enable mouse IRQ + ccb = ccb & 0b11011111; // disable mouse gating + ccb = ccb & 0b10111111; // disable scancode translation + + write_ccb(&mut command_port, &mut data_port, ccb); + + check_clear_and_write(&mut command_port, 0xAE); // enable port 1 + check_clear_and_write(&mut command_port, 0xA8); // enable port 2 + + if !write_and_expect_output(&mut command_port, &mut data_port, 0xA9, 0x00) { + // mouse test reply doesnt work! + return 1; + } + + // Reset Mouse + wait_input_buffer_clear(&mut command_port); + command_port.write(0xD4); + wait_input_buffer_clear(&mut command_port); + data_port.write(0xFF); + + if !clear_and_expect_output(&mut command_port, &mut data_port, 0xFA) { + // ACK + return 2; + } + if !clear_and_expect_output(&mut command_port, &mut data_port, 0xAA) { + // Self-test passed + return 3; + } + if !clear_and_expect_output(&mut command_port, &mut data_port, 0x00) { + // Mouse ID + return 4; + } + + // Enable data reporting + wait_input_buffer_clear(&mut command_port); + command_port.write(0xD4); + wait_input_buffer_clear(&mut command_port); + data_port.write(0xF4); + + if !clear_and_expect_output(&mut command_port, &mut data_port, 0xFA) { + return 5; // ACK + } + + return 6; + } + }) +} + +fn reset_state() { + CURRENTLY_RECEIVING_STATE.store(0, Ordering::Relaxed); + FLAGS_BYTE.store(0, Ordering::Relaxed); + X_DELTA_BYTE.store(0, Ordering::Relaxed); + Y_DELTA_BYTE.store(0, Ordering::Relaxed); +} + +pub fn mouse_interrupt() -> Option<(u8, u8, u8, i16, i16)> { + let mut command_port: Port = Port::new(0x64); + let mut data_port: Port = Port::new(0x60); + unsafe { + if (command_port.read() & 0x20) == 0 { + // if this interrupt is not for the mouse, return + return None; + } + + let byte = data_port.read(); + + let state_idx = CURRENTLY_RECEIVING_STATE.fetch_add(1, Ordering::Relaxed); + + if state_idx == 0 { + if (byte & 0x08) == 0 { + // if sync bit unset, return + reset_state(); + return None; + } + + if (byte & 0b0100_0000) != 0 { + // if x overflow set, return + reset_state(); + return None; + } + + if (byte & 0b1000_0000) != 0 { + // if y overflow set, return + reset_state(); + return None; + } + + FLAGS_BYTE.store(byte, Ordering::Relaxed); + None + } else if state_idx == 1 { + X_DELTA_BYTE.store(byte, Ordering::Relaxed); + None + } else if state_idx == 2 { + Y_DELTA_BYTE.store(byte, Ordering::Relaxed); + let flags = FLAGS_BYTE.load(Ordering::Relaxed); + let left_button_pressed = get_bit(flags, 0); + let right_button_pressed = get_bit(flags, 1); + let middle_button_pressed = get_bit(flags, 2); + let x_delta_sign = get_bit(flags, 4); + let y_delta_sign = get_bit(flags, 5); + + let x_delta: i16 = { + let x_delta = X_DELTA_BYTE.load(Ordering::Relaxed); + if x_delta_sign == 1 { + (x_delta as i16) - 256 + } else { + x_delta as i16 + } + }; + + let y_delta: i16 = -{ + let y_delta = Y_DELTA_BYTE.load(Ordering::Relaxed); + if y_delta_sign == 1 { + (y_delta as i16) - 256 + } else { + y_delta as i16 + } + }; + + reset_state(); + + Some(( + left_button_pressed, + right_button_pressed, + middle_button_pressed, + x_delta, + y_delta, + )) + } else { + None + } + } +} diff --git a/kernel/src/driver/graphics/framebuffer.rs b/kernel/src/driver/graphics/framebuffer.rs index 81199a6..7a3e344 100644 --- a/kernel/src/driver/graphics/framebuffer.rs +++ b/kernel/src/driver/graphics/framebuffer.rs @@ -32,6 +32,7 @@ impl Framebuffer { } } + #[inline(always)] pub fn put_pixel(&mut self, x: usize, y: usize, color: u32) { if x >= self.width || y >= self.height { return; @@ -45,6 +46,20 @@ impl Framebuffer { self.back_buffer[idx] = color; } + #[inline(always)] + pub fn fill_span(&mut self, x: usize, y: usize, len: usize, color: u32) { + if y >= self.height || x >= self.width || len == 0 { + return; + } + let max_len = self.width - x; + let len = core::cmp::min(len, max_len); + let start = y * self.pitch + x; + let end = start + len; + unsafe { + self.back_buffer.get_unchecked_mut(start..end).fill(color); + } + } + pub fn swap(&mut self) { unsafe { core::ptr::copy_nonoverlapping( @@ -69,8 +84,10 @@ pub fn init_framebuffer(raw: &LimineFramebuffer) { } pub fn with_framebuffer(f: F) { - let mut guard = FRAMEBUFFER.lock(); - if let Some(fb) = guard.as_mut() { - f(fb); - } + without_interrupts(|| { + let mut guard = FRAMEBUFFER.lock(); + if let Some(fb) = guard.as_mut() { + f(fb); + } + }) } diff --git a/kernel/src/driver/graphics/primitives.rs b/kernel/src/driver/graphics/primitives.rs index 1e195e7..d0f7a6e 100644 --- a/kernel/src/driver/graphics/primitives.rs +++ b/kernel/src/driver/graphics/primitives.rs @@ -1,9 +1,19 @@ -use crate::driver::graphics::{base::rgb, font_render::render_text, framebuffer::Framebuffer}; -use alloc::{format, string::ToString}; -use core::f32::consts::PI; -use micromath::F32Ext; +use crate::driver::graphics::framebuffer::Framebuffer; pub fn line(framebuffer: &mut Framebuffer, x0: usize, y0: usize, x1: usize, y1: usize, color: u32) { + if y0 == y1 { + let (xa, xb) = if x0 <= x1 { (x0, x1) } else { (x1, x0) }; + framebuffer.fill_span(xa, y0, xb - xa + 1, color); + return; + } + if x0 == x1 { + let (ya, yb) = if y0 <= y1 { (y0, y1) } else { (y1, y0) }; + for yy in ya..=yb { + framebuffer.put_pixel(x0, yy, color); + } + return; + } + let mut x0 = x0 as isize; let mut y0 = y0 as isize; let x1 = x1 as isize; @@ -58,23 +68,58 @@ pub fn triangle_outline( line(framebuffer, x2, y2, x3, y3, color); } -pub fn circle_outline(framebuffer: &mut Framebuffer, x: usize, y: usize, radius: f32, color: u32) { - let mut i: f32 = 0.0; +pub fn circle_outline( + framebuffer: &mut Framebuffer, + cx: usize, + cy: usize, + radius: usize, + color: u32, +) { + let mut x = radius as isize; + let mut y: isize = 0; + let mut d = 1 - x; + let cx = cx as isize; + let cy = cy as isize; - loop { - i += 0.1; + #[inline(always)] + fn plot_points( + framebuffer: &mut Framebuffer, + cx: isize, + cy: isize, + x: isize, + y: isize, + color: u32, + ) { + framebuffer.put_pixel((cx + x) as usize, (cy + y) as usize, color); + framebuffer.put_pixel((cx + y) as usize, (cy + x) as usize, color); + framebuffer.put_pixel((cx - y) as usize, (cy + x) as usize, color); + framebuffer.put_pixel((cx - x) as usize, (cy + y) as usize, color); + framebuffer.put_pixel((cx - x) as usize, (cy - y) as usize, color); + framebuffer.put_pixel((cx - y) as usize, (cy - x) as usize, color); + framebuffer.put_pixel((cx + y) as usize, (cy - x) as usize, color); + framebuffer.put_pixel((cx + x) as usize, (cy - y) as usize, color); + } - let x1: f32 = radius * (i * core::f32::consts::PI / 180.0).cos(); - let y1: f32 = radius * (i * PI / 180.0).sin(); - framebuffer.put_pixel((x as f32 + x1) as usize, (y as f32 + y1) as usize, color); + while y <= x { + plot_points(framebuffer, cx, cy, x, y, color); + y += 1; - if i >= 360.0 { - break; + if d <= 0 { + d += 2 * y + 1; + } else { + x -= 1; + d += 2 * (y - x) + 1; } } } -pub fn circle_filled(framebuffer: &mut Framebuffer, x0: usize, y0: usize, radius: f32, color: u32) { +pub fn circle_filled( + framebuffer: &mut Framebuffer, + x0: usize, + y0: usize, + radius: usize, + color: u32, +) { let mut x = radius as isize; let mut y: isize = 0; let mut x_change: isize = 1 - (radius as isize * 2); @@ -113,10 +158,8 @@ pub fn rectangle_filled( height: usize, color: u32, ) { - for fb_x in x..x + width { - for fb_y in y..y + height { - framebuffer.put_pixel(fb_x, fb_y, color); - } + for yy in y..y + height { + framebuffer.fill_span(x, yy, width, color); } } diff --git a/kernel/src/driver/mod.rs b/kernel/src/driver/mod.rs index d18d51b..e3c804d 100644 --- a/kernel/src/driver/mod.rs +++ b/kernel/src/driver/mod.rs @@ -1,4 +1,5 @@ pub mod graphics; pub mod keyboard; +pub mod mouse; pub mod serial; pub mod timer; diff --git a/kernel/src/driver/mouse.rs b/kernel/src/driver/mouse.rs new file mode 100644 index 0000000..06a51ce --- /dev/null +++ b/kernel/src/driver/mouse.rs @@ -0,0 +1,67 @@ +use core::sync::atomic::{AtomicI16, AtomicU8, Ordering}; + +use spin::Mutex; + +pub struct Mouse { + left_button_pressed: AtomicU8, + right_button_pressed: AtomicU8, + middle_button_pressed: AtomicU8, + x_delta: AtomicI16, + y_delta: AtomicI16, + status: AtomicU8, +} + +impl Mouse { + const fn new() -> Mouse { + Mouse { + left_button_pressed: AtomicU8::new(0), + right_button_pressed: AtomicU8::new(0), + middle_button_pressed: AtomicU8::new(0), + x_delta: AtomicI16::new(0), + y_delta: AtomicI16::new(0), + status: AtomicU8::new(0), + } + } + + pub fn interrupt( + &self, + left_button_pressed: u8, + right_button_pressed: u8, + middle_button_pressed: u8, + x_delta: i16, + y_delta: i16, + ) { + self.left_button_pressed + .store(left_button_pressed, Ordering::Relaxed); + self.right_button_pressed + .store(right_button_pressed, Ordering::Relaxed); + self.middle_button_pressed + .store(middle_button_pressed, Ordering::Relaxed); + self.x_delta.fetch_add(x_delta, Ordering::Relaxed); + self.y_delta.fetch_add(y_delta, Ordering::Relaxed); + } + + pub fn is_left_button_pressed(&self) -> u8 { + self.left_button_pressed.load(Ordering::Relaxed) + } + pub fn is_right_button_pressed(&self) -> u8 { + self.right_button_pressed.load(Ordering::Relaxed) + } + pub fn is_middle_button_pressed(&self) -> u8 { + self.middle_button_pressed.load(Ordering::Relaxed) + } + pub fn get_x_delta(&self) -> i16 { + self.x_delta.swap(0, Ordering::Relaxed) + } + pub fn get_y_delta(&self) -> i16 { + self.y_delta.swap(0, Ordering::Relaxed) + } + pub fn set_status(&self, status: u8) { + self.status.store(status, Ordering::Relaxed); + } + pub fn get_status(&self) -> u8 { + self.status.load(Ordering::Relaxed) + } +} + +pub static MOUSE: Mouse = Mouse::new(); diff --git a/kernel/src/driver/serial.rs b/kernel/src/driver/serial.rs index b9e486c..9d09d72 100644 --- a/kernel/src/driver/serial.rs +++ b/kernel/src/driver/serial.rs @@ -73,8 +73,10 @@ pub fn init_serial_console(start_x: usize, start_y: usize) { } pub fn with_serial_console(f: F) { - let mut guard = SERIAL_CONSOLE.lock(); - if let Some(fb) = guard.as_mut() { - f(fb); - } + without_interrupts(|| { + let mut guard = SERIAL_CONSOLE.lock(); + if let Some(fb) = guard.as_mut() { + f(fb); + } + }); } diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 5526e0a..e5e7aec 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -10,6 +10,7 @@ use limine::request::{ DateAtBootRequest, FramebufferRequest, HhdmRequest, MemoryMapRequest, MpRequest, RequestsEndMarker, RequestsStartMarker, }; +use x86_64::instructions::interrupts::without_interrupts; pub mod arch; pub mod driver; pub mod util; @@ -20,6 +21,7 @@ use crate::driver::graphics::framebuffer::{init_framebuffer, with_framebuffer}; use crate::driver::graphics::primitives::{ circle_filled, circle_outline, rectangle_filled, rectangle_outline, triangle_outline, }; +use crate::driver::mouse::MOUSE; use crate::driver::serial::{ConsoleWriter, init_serial_console, with_serial_console}; use crate::driver::timer::TIMER; use crate::util::test_performance; @@ -89,7 +91,6 @@ pub fn _print(args: core::fmt::Arguments) { }; let _ = writer.write_fmt(args); }); - fb.swap(); }); } @@ -99,9 +100,12 @@ unsafe extern "C" fn kmain() -> ! { // removed by the linker. assert!(BASE_REVISION.is_supported()); + let mapper; + let frame_allocator; + if let Some(hhdm_response) = HHDM_REQUEST.get_response() { if let Some(memory_map_response) = MEMORY_MAP_REQUEST.get_response() { - let (mapper, frame_allocator) = init(hhdm_response, memory_map_response); + (mapper, frame_allocator) = init(hhdm_response, memory_map_response); } else { kernel_crash(); // Could not get required info from Limine's memory map. } @@ -134,25 +138,67 @@ unsafe extern "C" fn kmain() -> ! { sleep(500); + let mut current_mouse_x: usize = 100; + let mut current_mouse_y: usize = 100; + let mut mouse_status = 0; + let mut width = 0; + let mut height = 0; + let mut x_delta = 0; + let mut y_delta = 0; + loop { with_serial_console(|serial_console| serial_console.clear(0, 0)); + with_framebuffer(|fb| fb.clear(rgb(253, 129, 0))); + test_performance(|| { + with_framebuffer(|mut fb| { + width = fb.width; + height = fb.height; - with_framebuffer(|mut fb| { - fb.clear(rgb(253, 129, 0)); + rectangle_filled(&mut fb, 700, 400, 200, 200, rgb(0, 0, 0)); + rectangle_outline(&mut fb, 400, 400, 100, 100, rgb(0, 0, 0)); + circle_filled(&mut fb, 200, 200, 100, rgb(0, 0, 0)); + circle_outline(&mut fb, 400, 200, 100, rgb(0, 0, 0)); + triangle_outline(&mut fb, 100, 400, 200, 400, 150, 600, rgb(0, 0, 0)); + }); - // rectangle_filled(&mut fb, 700, 400, 200, 200, rgb(0, 0, 0)); - // rectangle_outline(&mut fb, 400, 400, 100, 100, rgb(0, 0, 0)); - // circle_filled(&mut fb, 200, 200, 100.0, rgb(0, 0, 0)); + let (hours, minutes, seconds) = + unix_to_hms(TIMER.get_date_at_boot() + (TIMER.now().elapsed()) / 1000); - circle_outline(&mut fb, 400, 200, 100.0, rgb(0, 0, 0)); - triangle_outline(&mut fb, 100, 400, 200, 400, 150, 600, rgb(0, 0, 0)); + mouse_status = MOUSE.get_status(); + x_delta = MOUSE.get_x_delta() / 5; + y_delta = MOUSE.get_y_delta() / 5; + if x_delta != 0 { + current_mouse_x = (current_mouse_x as isize + x_delta as isize).max(0) as usize; + } + + if y_delta != 0 { + current_mouse_y = (current_mouse_y as isize + y_delta as isize).max(0) as usize; + } + + if current_mouse_x > width { + current_mouse_x = width - 15; + } + + if current_mouse_y > height { + current_mouse_y = height - 15; + } + + print!( + "{:?}:{:?}:{:?}\n{:?} {:?} {:?} {:?} {:?}", + hours, + minutes, + seconds, + mouse_status, + current_mouse_x, + current_mouse_y, + x_delta, + y_delta + ); + }); + with_framebuffer(|fb| { + rectangle_filled(fb, current_mouse_x, current_mouse_y, 15, 15, rgb(0, 255, 0)); + fb.swap(); }); - - let (hours, minutes, seconds) = - unix_to_hms(TIMER.get_date_at_boot() + (TIMER.now().elapsed()) / 1000); - - print!("{:?}:{:?}:{:?}", hours, minutes, seconds); - sleep(16); } } @@ -183,6 +229,8 @@ fn boot_animation() { i += 1; + with_framebuffer(|fb| fb.swap()); + sleep(200); } diff --git a/kernel/src/util.rs b/kernel/src/util.rs index c5debe5..2eef58f 100644 --- a/kernel/src/util.rs +++ b/kernel/src/util.rs @@ -42,3 +42,7 @@ pub fn test_performance(function: F) { println!("took {} ms", (TIMER.now() - start).elapsed()); ret } + +pub fn get_bit(value: u8, position: u8) -> u8 { + (value >> position) & 1 +}