diff --git a/ableos/src/graphics/mod.rs b/ableos/src/graphics/mod.rs index 0a96ad609..59fd69db8 100644 --- a/ableos/src/graphics/mod.rs +++ b/ableos/src/graphics/mod.rs @@ -7,8 +7,8 @@ use vga::writers::GraphicsWriter; #[derive(Debug)] pub struct ScreenSize { - pub x: usize, - pub y: usize, + pub x: usize, + pub y: usize, } const FONT_SCALE: f32 = 1.6; @@ -21,240 +21,245 @@ lazy_static::lazy_static! { } impl ScreenSize { - pub fn new(x: usize, y: usize) -> Self { - Self { x, y } - } + pub fn new(x: usize, y: usize) -> Self { + Self { x, y } + } } pub enum GraphicsReturn { - Ok, - ImproperScreenSize, + Ok, + ImproperScreenSize, } pub struct ScreenBuffer { - pub size: ScreenSize, - pub clear_color: Rgba64, - pub buff: Box<[Rgba64]>, // Vec, + pub size: ScreenSize, + pub clear_color: Rgba64, + pub buff: Box<[Rgba64]>, // Vec, } impl ScreenBuffer { - // Add optional size later - pub fn new(x: usize, y: usize) -> Self { - Self { - size: ScreenSize::new(x, y), - clear_color: 0, - buff: vec![0u64; x * y].into_boxed_slice(), - } - } - pub fn draw_filled_circle(&mut self, cx: i32, cy: i32, radius: usize, color: Rgba64) { - let r = radius as i32 * 2; - for y in 0..640 { - for x in 0..480 { - let dx = cx - x as i32 * 2 - 1; - let dy = cy - y as i32 * 2 - 1; + // Add optional size later + pub fn new(x: usize, y: usize) -> Self { + Self { + size: ScreenSize::new(x, y), + clear_color: 0, + buff: vec![0u64; x * y].into_boxed_slice(), + } + } + pub fn draw_filled_circle(&mut self, cx: i32, cy: i32, radius: usize, color: Rgba64) { + let r = radius as i32 * 2; + for y in 0..640 { + for x in 0..480 { + let dx = cx - x as i32 * 2 - 1; + let dy = cy - y as i32 * 2 - 1; - if dx * dx + dy * dy <= r * r { - self.set_pixel(x, y, color); - }; - } - } - } - - #[inline] - pub fn set_pixel(&mut self, x: usize, y: usize, color: Rgba64) { - self.buff[y * self.size.x + x] = color; - } - - pub fn clear(&mut self) { - self.buff = vec![0u64; self.buff.len()].into_boxed_slice(); - } - - pub fn blit(&mut self, _width: usize, _height: usize) {} - pub fn draw_filled_rect(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, color: Rgba64) { - for y in y1..y2 { - for x in x1..x2 { - self.set_pixel(x, y, color); - } - } - } - pub fn draw_unfilled_rect(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, color: Rgba64) { - // x1 y1 => x2 y1 => x2 y2 => x1 y2 => x1 y1 - self.draw_line(x1, y1, x2, y1, color); - self.draw_line(x2, y1, x2, y2, color); - self.draw_line(x2, y2, x1, y2, color); - self.draw_line(x1, y2, x1, y1, color); - } - - #[inline] - pub fn draw_line(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, color: Rgba64) { - let x = crate::graphics::get_coordinates( - x1.try_into().unwrap(), - y1.try_into().unwrap(), - x2.try_into().unwrap(), - y2.try_into().unwrap(), - ); - - for coord in x { - self.set_pixel(coord.0, coord.1, color); - } - } - - pub fn shade(&mut self) { - for y in 0..100 { - for x in 0..100 { - let rgba_ret = evaluate_shader(x, y, self.buff[y * self.size.x + x]); - match rgba_ret { - Ok(pixel) => { - // info!("{:?}", pixel); - self.set_pixel(x, y, pixel); - } - - Err(err) => error!("{}", err), + if dx * dx + dy * dy <= r * r { + self.set_pixel(x, y, color); + }; } - } - } + } + } - info!("Shaders done"); - } + #[inline] + pub fn set_pixel(&mut self, x: usize, y: usize, color: Rgba64) { + self.buff[y * self.size.x + x] = color; + } - // TODO force clear - pub fn force_redraw(&mut self) { - use shadeable::pixel_format::into_vga_16; - VGAE.lock().clear_screen(into_vga_16(self.clear_color)); - } + pub fn clear(&mut self) { + self.buff = vec![0u64; self.buff.len()].into_boxed_slice(); + } - /// Draw a glyph on the screen at the given position - /// - /// # Arguments - /// * `x` - the x position of the glyph - /// * `y` - the y position of the glyph - /// * `glyph` - the glyph to draw - /// * `color` - the color of the glyph - pub fn draw_char(&mut self, mut x: u32, mut y: u32, character: char, color: Rgba64) { - // trace!["Judy Hopps is thicc af"]; - // let mode = *VGAE.lock(); - // trace!["She got them bouncy bunny buns"]; - - let basic_multingual_plane = FontRef::try_from_slice(include_bytes!( - "../../../ableos/assets/fonts/unifont-14.0.01.ttf" - )) - .unwrap(); - - let supplementary_multilingual_plane = FontRef::try_from_slice(include_bytes!( - "../../../ableos/assets/fonts/unifont_upper-14.0.01.ttf" - )) - .unwrap(); - - // let mut has_char = false; - // for x in font.codepoint_ids() { - // if x.1 == character { - // has_char = true; - // break; - // } - // } - - let in_supp_plane = character as u32 > 0xffff; - - let plane = match in_supp_plane { - false => basic_multingual_plane, - true => supplementary_multilingual_plane, - }; - - match character { - '\n' => { - // x = 0; - // y += (GLYPH_HEIGHT * FONT_SCALE) as u32; - } - _ => { - let q_glyph: Glyph = plane.glyph_id(character).with_scale_and_position( - 20.0 * FONT_SCALE, - ab_glyph::point(GLYPH_WIDTH * FONT_SCALE, GLYPH_HEIGHT * FONT_SCALE), - ); - - // elf: I don't know if GLYPH_HEIGHT is in the right units here. I'm just guessing. - if x as usize > self.size.x { - x = 0; - y += (GLYPH_HEIGHT * FONT_SCALE) as u32; + pub fn blit(&mut self, _width: usize, _height: usize) {} + pub fn draw_filled_rect(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, color: Rgba64) { + for y in y1..y2 { + for x in x1..x2 { + self.set_pixel(x, y, color); } + } + } + pub fn draw_unfilled_rect( + &mut self, + x1: usize, + y1: usize, + x2: usize, + y2: usize, + color: Rgba64, + ) { + // x1 y1 => x2 y1 => x2 y2 => x1 y2 => x1 y1 + self.draw_line(x1, y1, x2, y1, color); + self.draw_line(x2, y1, x2, y2, color); + self.draw_line(x2, y2, x1, y2, color); + self.draw_line(x1, y2, x1, y1, color); + } - if let Some(q) = plane.outline_glyph(q_glyph) { - q.draw(|gx, gy, c| { - if c > 0.015 { - let corner = q.px_bounds().min; - self.set_pixel( - gx as usize + corner.x as usize + x as usize, - gy as usize + corner.y as usize + y as usize, - color, - ); - } - }); + #[inline] + pub fn draw_line(&mut self, x1: usize, y1: usize, x2: usize, y2: usize, color: Rgba64) { + let x = crate::graphics::get_coordinates( + x1.try_into().unwrap(), + y1.try_into().unwrap(), + x2.try_into().unwrap(), + y2.try_into().unwrap(), + ); + + for coord in x { + self.set_pixel(coord.0, coord.1, color); + } + } + + pub fn shade(&mut self) { + for y in 0..100 { + for x in 0..100 { + let rgba_ret = evaluate_shader(x, y, self.buff[y * self.size.x + x]); + match rgba_ret { + Ok(pixel) => { + // info!("{:?}", pixel); + self.set_pixel(x, y, pixel); + } + + Err(err) => error!("{}", err), + } } - } - } - } + } + + info!("Shaders done"); + } + + // TODO force clear + pub fn force_redraw(&mut self) { + use shadeable::pixel_format::into_vga_16; + VGAE.lock().clear_screen(into_vga_16(self.clear_color)); + } + + /// Draw a glyph on the screen at the given position + /// + /// # Arguments + /// * `x` - the x position of the glyph + /// * `y` - the y position of the glyph + /// * `glyph` - the glyph to draw + /// * `color` - the color of the glyph + pub fn draw_char(&mut self, mut x: u32, mut y: u32, character: char, color: Rgba64) { + // trace!["Judy Hopps is thicc af"]; + // let mode = *VGAE.lock(); + // trace!["She got them bouncy bunny buns"]; + + let basic_multingual_plane = FontRef::try_from_slice(include_bytes!( + "../../../ableos/assets/fonts/unifont-14.0.01.ttf" + )) + .unwrap(); + + let supplementary_multilingual_plane = FontRef::try_from_slice(include_bytes!( + "../../../ableos/assets/fonts/unifont_upper-14.0.01.ttf" + )) + .unwrap(); + + // let mut has_char = false; + // for x in font.codepoint_ids() { + // if x.1 == character { + // has_char = true; + // break; + // } + // } + + let in_supp_plane = character as u32 > 0xffff; + + let plane = match in_supp_plane { + false => basic_multingual_plane, + true => supplementary_multilingual_plane, + }; + + match character { + '\n' => { + // x = 0; + // y += (GLYPH_HEIGHT * FONT_SCALE) as u32; + } + _ => { + let q_glyph: Glyph = plane.glyph_id(character).with_scale_and_position( + 20.0 * FONT_SCALE, + ab_glyph::point(GLYPH_WIDTH * FONT_SCALE, GLYPH_HEIGHT * FONT_SCALE), + ); + + // elf: I don't know if GLYPH_HEIGHT is in the right units here. I'm just guessing. + if x as usize > self.size.x { + x = 0; + y += (GLYPH_HEIGHT * FONT_SCALE) as u32; + } + + if let Some(q) = plane.outline_glyph(q_glyph) { + q.draw(|gx, gy, c| { + if c > 0.015 { + let corner = q.px_bounds().min; + self.set_pixel( + gx as usize + corner.x as usize + x as usize, + gy as usize + corner.y as usize + y as usize, + color, + ); + } + }); + } + } + } + } } pub trait VgaBuffer { - fn copy_to_buffer(&self) -> GraphicsReturn; + fn copy_to_buffer(&self) -> GraphicsReturn; } impl VgaBuffer for ScreenBuffer { - fn copy_to_buffer(&self) -> GraphicsReturn { - let mode = VGAE.lock(); - for y in 0..self.size.y { - for x in 0..self.size.x { - use shadeable::pixel_format::into_vga_16; - // let vga_color = get_color16(self.buff[y * self.size.x + x]); + fn copy_to_buffer(&self) -> GraphicsReturn { + let mode = VGAE.lock(); + for y in 0..self.size.y { + for x in 0..self.size.x { + use shadeable::pixel_format::into_vga_16; + let vga_color = into_vga_16(self.buff[y * self.size.x + x]); - let vga_color = into_vga_16(self.buff[y * self.size.x + x]); - - if into_vga_16(self.clear_color) != vga_color { - mode.set_pixel(x, y, vga_color); + if into_vga_16(self.clear_color) != vga_color { + mode.set_pixel(x, y, vga_color); + } } - } - } + } - GraphicsReturn::Ok - } + GraphicsReturn::Ok + } } pub fn get_coordinates(x1: i32, y1: i32, x2: i32, y2: i32) -> Vec<(usize, usize)> { - let mut coordinates: Vec<(usize, usize)> = vec![]; - let dx: i32 = i32::abs(x2 - x1); - let dy: i32 = i32::abs(y2 - y1); - let sx: i32 = { - if x1 < x2 { - 1 - } else { - -1 - } - }; - let sy: i32 = { - if y1 < y2 { - 1 - } else { - -1 - } - }; - let mut error: i32 = (if dx > dy { dx } else { -dy }) / 2; - let mut current_x: i32 = x1; - let mut current_y: i32 = y1; - loop { - coordinates.push((current_x as usize, current_y as usize)); - // info!("0 {:?}", (current_x, current_y)); + let mut coordinates: Vec<(usize, usize)> = vec![]; + let dx: i32 = i32::abs(x2 - x1); + let dy: i32 = i32::abs(y2 - y1); + let sx: i32 = { + if x1 < x2 { + 1 + } else { + -1 + } + }; + let sy: i32 = { + if y1 < y2 { + 1 + } else { + -1 + } + }; + let mut error: i32 = (if dx > dy { dx } else { -dy }) / 2; + let mut current_x: i32 = x1; + let mut current_y: i32 = y1; + loop { + coordinates.push((current_x as usize, current_y as usize)); + // info!("0 {:?}", (current_x, current_y)); - if current_x == x2 && current_y == y2 { - break; - } + if current_x == x2 && current_y == y2 { + break; + } - let error2: i32 = error; + let error2: i32 = error; - if error2 > -dx { - error -= dy; - current_x += sx; - } - if error2 < dy { - error += dx; - current_y += sy; - } - } - coordinates + if error2 > -dx { + error -= dy; + current_x += sx; + } + if error2 < dy { + error += dx; + current_y += sy; + } + } + coordinates } diff --git a/ableos/src/kmain.rs b/ableos/src/kmain.rs index 1db66d805..9fca2ed05 100644 --- a/ableos/src/kmain.rs +++ b/ableos/src/kmain.rs @@ -1,5 +1,11 @@ #![allow(clippy::empty_loop)] +use alloc::{format, string::String}; +use shadeable::pixel_format::from_vga_16; +use vga::colors::Color16; + +use crate::{ScreenBuffer, VgaBuffer, SCREEN_BUFFER}; + // use crate::scheduler; use { @@ -17,10 +23,7 @@ use { relib::network::socket::Socket, scheduler::SCHEDULER, }, - alloc::{ - string::{String, ToString}, - vec, - }, + alloc::{string::ToString, vec}, core::sync::atomic::{AtomicU64, Ordering::*}, lazy_static::lazy_static, log::*, @@ -57,30 +60,6 @@ pub fn kernel_main() -> ! { use crate::proto_filetable::file::FileLocations; let mut file_table = FILE_TABLE.lock(); - /* - let mut new_file = File::new(FileLocations::Bin, "test".to_string(), "txt".to_string()); - - new_file.write_bytes(b"Hello, world!"); - file_table.add_file("test", new_file); - - - - - let file = file_table.get_file("test"); - - match file { - Some(file) => { - let file_bytes = &file.data_pointer; - let file_string = String::from_utf8(file_bytes.to_vec()).unwrap(); - info!("{}", file_string); - } - None => { - info!("File not found"); - } - } - - - */ let mut new_file = File::new(FileLocations::Bin, "test".to_string(), "txt".to_string()); new_file.write_bytes(&[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00]); @@ -101,7 +80,15 @@ pub fn kernel_main() -> ! { } } - log_version_data(); + let mut abcde = SCREEN_BUFFER.lock(); + abcde.force_redraw(); + + abcde.draw_filled_circle(100, 100, 300, 0x0000ffff); + abcde.draw_unfilled_rect(100, 100, 400, 200, 0xff0000ff); + abcde.draw_filled_rect(300, 300, 400, 400, 0xff0000ff); + abcde.draw_line(100, 100, 400, 200, 0xff0000ff); + abcde.copy_to_buffer(); + sloop() } diff --git a/ableos/src/syscalls.rs b/ableos/src/syscalls.rs deleted file mode 100644 index a0d6cb5df..000000000 --- a/ableos/src/syscalls.rs +++ /dev/null @@ -1,37 +0,0 @@ -use crate::proc::PID; - -#[repr(C)] -/// Signals that can be sent to a process -pub enum Signals { - /// Terminate the process - Terminate, - /// Shutdown the process and allow it to shutdown cleanly - Quit, -} - -#[repr(C)] -pub enum SystemCall { - /// Sleep the calling process for the given number of milliseconds - /// - /// # Arguments - /// - /// * `ticks` - The number of ticks to sleep for - Sleep(u64), - - /// Send a signal to a process - /// - /// # Arguments - /// - /// * `pid` - The PID of the process to send the signal to - /// * `signal` - The signal to send - SendSignal(PID, Signals), -} - -#[no_mangle] -pub extern "C" fn syscall(call: SystemCall) { - // Handle the system call - match call { - SystemCall::Sleep(ms) => todo!("Sleep for {} ms", ms), - SystemCall::SendSignal(process_id, signal) => todo!(), - } -} diff --git a/ableos/src/syscalls/file_calls.rs b/ableos/src/syscalls/file_calls.rs new file mode 100644 index 000000000..d4cb49216 --- /dev/null +++ b/ableos/src/syscalls/file_calls.rs @@ -0,0 +1,40 @@ +//! File system related system calls. + +/// Temporary representation of a file path +pub type Path = *const u8; + +/// Remove a Directory from the filesystem +/// +/// # Arguments +/// * `full_path` - The full path of the directory to remove +/// * `force` - Whether to remove the directory even if it is not empty +#[no_mangle] +pub extern "C" fn remove_directory(path: Path, force_delete: bool) { + unimplemented!(); +} + +/// Create a new directory at the given path +/// +/// # Arguments +/// * `full_path` - The full path of the directory to create +#[no_mangle] +pub extern "C" fn create_directory(path: Path) -> Result<(), FileErrors> { + unimplemented!(); +} + +#[repr(C)] +/// Errors that can occur when messing with files +pub enum FileErrors { + /// The directory can not be created + DirectoryCouldNotBeCreated, + /// The directory could not be removed + DirectoryCouldNotBeRemoved, + /// + FileCouldNotBeCreated, + /// + FileCouldNotBeRemoved, + /// The file could not be opened + FileCouldNotBeOpened, + /// + FileCouldNotBeClosed, +} diff --git a/ableos/src/syscalls/mod.rs b/ableos/src/syscalls/mod.rs new file mode 100644 index 000000000..cf5d394ea --- /dev/null +++ b/ableos/src/syscalls/mod.rs @@ -0,0 +1,25 @@ +#![deny(missing_docs)] +//! The module of syscalls. + +use crate::proc::PID; + +pub mod file_calls; +pub mod time_calls; + +#[repr(C)] +/// Signals that can be sent to a process +pub enum Signals { + /// Terminate the process + Terminate, + /// Shutdown the process and allow it to shutdown cleanly + Quit, +} + +/// Send a signal to a process +/// +/// # Arguments +/// +/// * `pid` - The PID of the process to send the signal to +/// * `signal` - The signal to send +#[no_mangle] +pub extern "C" fn send_signal(pid: PID, signal: Signals) {} diff --git a/ableos/src/syscalls/time_calls.rs b/ableos/src/syscalls/time_calls.rs new file mode 100644 index 000000000..4465b86ff --- /dev/null +++ b/ableos/src/syscalls/time_calls.rs @@ -0,0 +1,28 @@ +//! Time related system calls. + +use core::panic; + +/// Seconds and milliseconds since the Unix epoch. +#[repr(C)] +pub struct SecondsTime { + seconds: u64, + milliseconds: u64, +} + +/// Sleep the calling process for the given number of milliseconds +#[no_mangle] +pub extern "C" fn sleep(time: SecondsTime) { + panic!("sleep is not implemented yet"); +} + +#[no_mangle] +/// Get the current time in seconds, milliseconds +pub extern "C" fn get_time() -> SecondsTime { + panic!("get_time not implemented"); +} + +#[no_mangle] +/// Set the current time in seconds, milliseconds +pub extern "C" fn set_time(time: SecondsTime) { + panic!("set_time not implemented"); +} diff --git a/ableos/src/virtio/mod.rs b/ableos/src/virtio/mod.rs index 2a5ff3fdc..6506e9ebe 100644 --- a/ableos/src/virtio/mod.rs +++ b/ableos/src/virtio/mod.rs @@ -3,7 +3,7 @@ //! This module contains the virtio device structural code. //! //! # Notes -//! https://docs.oasis-open.org/virtio/virtio/v1.1/csprd01/virtio-v1.1-csprd01.html#x1-20001 +//! pub struct VirtioDevice { status: VirtioDeviceStatus, diff --git a/ableos/src/wasm/mod.rs b/ableos/src/wasm/mod.rs index 436ad2f84..58c4ca0c9 100644 --- a/ableos/src/wasm/mod.rs +++ b/ableos/src/wasm/mod.rs @@ -92,7 +92,7 @@ impl WasmProgram { /// # Examples /// ``` /// use wasm_loader::wasm::WasmProgram; - /// let wasm_program = WasmProgram::new_from_bytes(b"\0\0\0\0\1\0\0\0"); + /// let wasm_program = WasmProgram::new_from_bytes(b"\0\0\0\01\0\0\0"); /// assert_eq!(wasm_program.is_valid(), (true, false)); /// ``` pub fn validate_header(self) -> (bool, bool) {