- added a new libary libm containing procedural macros for the kernel.
these should be used to include external files and resources in the kernel binary
at compile time.
- libm currently supports loading psf-1 formatted fonts
- added two fonts that are included in the binary at compile time
- refactored libk to make the crate structure more organised and maintainable in future.
new structure:
- drivers (hardware interaction)
- resources (consts and statics included either manually or via macros)
- std (standard functions for higher level interaction with the os, for example creating windows)
- added geometry.rs
- provides the Vec2<T> struct for use with dimensions, coordinates etc.
- added window.rs
- provides the Window struct for rendering the state of an application to the screen
- added application.rs
- provides the Application trait for custom programs to implement in order to run
This commit is contained in:
Generated
+99
@@ -64,6 +64,47 @@ version = "0.8.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "foundry_os"
|
||||
version = "0.1.0"
|
||||
@@ -101,12 +142,19 @@ dependencies = [
|
||||
"pin-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "libk"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"crossbeam",
|
||||
"futures-util",
|
||||
"libm",
|
||||
"limine",
|
||||
"linked_list_allocator",
|
||||
"pc-keyboard",
|
||||
@@ -114,6 +162,16 @@ dependencies = [
|
||||
"x86_64",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "limine"
|
||||
version = "0.3.1"
|
||||
@@ -169,6 +227,24 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.93"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.19"
|
||||
@@ -205,6 +281,29 @@ dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00e2473a93778eb0bad35909dff6a10d28e63f792f16ed15e404fca9d5eeedbe"
|
||||
|
||||
[[package]]
|
||||
name = "volatile"
|
||||
version = "0.4.6"
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
[workspace]
|
||||
members = ["kernel", "libk"]
|
||||
members = ["kernel", "libk", "libm"]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
|
||||
Vendored
+1
-1
@@ -189,7 +189,7 @@
|
||||
"command-palette:Open command palette": false
|
||||
}
|
||||
},
|
||||
"active": "e1fb15cab546d0b6",
|
||||
"active": "add883d295e04659",
|
||||
"lastOpenFiles": [
|
||||
"Usage",
|
||||
"Welcome.md",
|
||||
|
||||
@@ -96,7 +96,7 @@ extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: InterruptStac
|
||||
let mut port = Port::new(0x60);
|
||||
|
||||
let scancode: u8 = unsafe { port.read() };
|
||||
libk::io::keyboard::add_scancode(scancode);
|
||||
libk::drivers::io::keyboard::add_scancode(scancode);
|
||||
|
||||
unsafe {
|
||||
PICS.lock()
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ extern crate alloc;
|
||||
use core::arch::asm;
|
||||
use limine::BaseRevision;
|
||||
|
||||
use libk::kalloc::init_heap;
|
||||
use libk::drivers::kalloc::allocator::init_heap;
|
||||
use libk::prelude::*;
|
||||
|
||||
use x86_64::VirtAddr;
|
||||
@@ -51,7 +51,7 @@ pub fn boot() -> Result<(), &'static str> {
|
||||
let memory_map = memmap::get_memory_map();
|
||||
|
||||
print_log!(" Initialising Serial... ");
|
||||
libk::io::serial::init()?;
|
||||
libk::drivers::io::serial::init()?;
|
||||
println_log!("[Success]");
|
||||
|
||||
print_log!(" Setting Up Global Descriptor Table... ");
|
||||
|
||||
+7
-6
@@ -4,10 +4,13 @@
|
||||
extern crate alloc;
|
||||
|
||||
use libk::{
|
||||
io::{self, keyboard},
|
||||
prelude::*,
|
||||
scheduling::task::{Executor, Task},
|
||||
// scheduling::task::{Executor, Task},
|
||||
drivers::{
|
||||
io::{self, ascii::WRITER, keyboard},
|
||||
scheduling::task::{Executor, Task},
|
||||
},
|
||||
prelude::*,
|
||||
resources::font::FONT_SPLEEN_8X16,
|
||||
};
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
@@ -20,7 +23,7 @@ extern "C" fn kmain() -> ! {
|
||||
println_log!("[ Kernel Initialised Successfully ] ");
|
||||
|
||||
let dimensions = io::ascii::screensize_chars();
|
||||
let dimensions2 = io::ascii::screensize_px();
|
||||
let dimensions2 = io::framebuffer::display::screensize_px();
|
||||
|
||||
println!("Dimensions: {}x{} (px)", dimensions2.0, dimensions2.1);
|
||||
println!("Dimensions: {}x{} (chars)", dimensions.0, dimensions.1);
|
||||
@@ -49,6 +52,4 @@ extern "C" fn kmain() -> ! {
|
||||
let mut executor = Executor::new();
|
||||
executor.spawn(Task::new(keyboard::print_keypresses()));
|
||||
executor.run();
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
@@ -19,3 +19,4 @@ futures-util = { version = "0.3.31", default-features = false, features = [
|
||||
"alloc",
|
||||
] }
|
||||
linked_list_allocator = "0.10.5"
|
||||
libm = { path = "../libm" }
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -2,11 +2,9 @@ use core::fmt;
|
||||
use spin::{Lazy, Mutex};
|
||||
use x86_64::instructions::interrupts;
|
||||
|
||||
pub use super::framebuffer::screensize_px;
|
||||
use super::framebuffer::{Colour, FRAMEBUFFER_WRITER};
|
||||
use super::framebuffer::{colour::Colour, display::FRAMEBUFFER_WRITER};
|
||||
|
||||
mod font;
|
||||
use font::FONT;
|
||||
use crate::resources::font::{FONT_CP850_8X16, Font};
|
||||
|
||||
static FONT_WIDTH: u32 = 8;
|
||||
static FONT_HEIGHT: u32 = 16;
|
||||
@@ -19,6 +17,7 @@ pub fn screensize_chars() -> (u32, u32) {
|
||||
}
|
||||
|
||||
pub struct Writer {
|
||||
font: &'static Font,
|
||||
/// Measured in chars not pixels.
|
||||
screen_width: u32,
|
||||
/// Measured in chars not pixels.
|
||||
@@ -48,6 +47,7 @@ impl Writer {
|
||||
panic!("Framebuffer writer not initialized.");
|
||||
},
|
||||
|writer| Self {
|
||||
font: &FONT_CP850_8X16,
|
||||
screen_width: writer.width() / 8,
|
||||
screen_height: writer.height() / 16,
|
||||
text_line: 0,
|
||||
@@ -60,6 +60,10 @@ impl Writer {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn set_font(&mut self, font: &'static Font) {
|
||||
self.font = font;
|
||||
}
|
||||
|
||||
pub fn write_glyph(&mut self, c: u16) {
|
||||
if c as u8 == b'\n' {
|
||||
self.newline();
|
||||
@@ -67,7 +71,7 @@ impl Writer {
|
||||
}
|
||||
|
||||
// get the character data from the font array. -- each byte is a row of pixels
|
||||
let data: &[u8] = &FONT[c as usize * 16..(c as usize + 1) * 16];
|
||||
let data: &[u8] = &self.font.0[c as usize];
|
||||
|
||||
if let Some(writer) = FRAMEBUFFER_WRITER.lock().as_mut() {
|
||||
for (row, line) in data.iter().enumerate().take(16) {
|
||||
@@ -190,7 +194,7 @@ macro_rules! println_log {
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! print_log {
|
||||
($($arg:tt)*) => ($crate::io::ascii::_print_log(format_args!($($arg)*)));
|
||||
($($arg:tt)*) => ($crate::_print_log(format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
@@ -201,7 +205,7 @@ macro_rules! println {
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! print {
|
||||
($($arg:tt)*) => ($crate::io::ascii::_print(format_args!($($arg)*)));
|
||||
($($arg:tt)*) => ($crate::_print(format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
@@ -4,9 +4,7 @@ use limine::request::FramebufferRequest;
|
||||
#[unsafe(link_section = ".requests")]
|
||||
static FRAMEBUFFER_REQUEST: FramebufferRequest = FramebufferRequest::new();
|
||||
|
||||
mod colour;
|
||||
|
||||
pub use colour::Colour;
|
||||
use super::colour::Colour;
|
||||
use core::panic;
|
||||
|
||||
use limine::framebuffer::Framebuffer;
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod colour;
|
||||
pub mod display;
|
||||
@@ -5,14 +5,14 @@ use core::{
|
||||
use spin::{Lazy, Mutex};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! serial_println {
|
||||
() => ($crate::serial_print!("\n"));
|
||||
($($arg:tt)*) => ($crate::io::serial_print!("{}\n", format_args!($($arg)*)));
|
||||
macro_rules! serial_print {
|
||||
($($arg:tt)*) => ($crate::_serial_write(format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! serial_print {
|
||||
($($arg:tt)*) => ($crate::io::serial::_serial_write(format_args!($($arg)*)));
|
||||
macro_rules! serial_println {
|
||||
() => ($crate::serial_print!("\n"));
|
||||
($($arg:tt)*) => (serial_print!("{}\n", format_args!($($arg)*)));
|
||||
}
|
||||
|
||||
use super::port::{inb, outb};
|
||||
@@ -0,0 +1 @@
|
||||
pub mod allocator;
|
||||
@@ -0,0 +1,3 @@
|
||||
pub mod io;
|
||||
pub mod kalloc;
|
||||
pub mod scheduling;
|
||||
@@ -1,10 +1,8 @@
|
||||
use alloc::boxed::Box;
|
||||
use alloc::collections::{BTreeMap, VecDeque};
|
||||
use alloc::sync::Arc;
|
||||
use alloc::task::Wake;
|
||||
use alloc::{boxed::Box, collections::BTreeMap, sync::Arc, task::Wake};
|
||||
|
||||
use core::sync::atomic::AtomicU64;
|
||||
use core::task::Waker;
|
||||
use core::task::{Context, Poll};
|
||||
use core::task::{RawWaker, Waker};
|
||||
use core::{future::Future, pin::Pin};
|
||||
use crossbeam::queue::ArrayQueue;
|
||||
use x86_64::instructions::interrupts::{self, enable_and_hlt};
|
||||
@@ -1,3 +0,0 @@
|
||||
pub mod allocator;
|
||||
|
||||
pub use self::allocator::init_heap;
|
||||
+16
-4
@@ -1,4 +1,5 @@
|
||||
#![no_std]
|
||||
#![allow(async_fn_in_trait)]
|
||||
#![warn(tail_expr_drop_order)]
|
||||
#![warn(clippy::correctness, clippy::perf, clippy::nursery)]
|
||||
// alloc
|
||||
@@ -8,11 +9,22 @@
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
pub mod io;
|
||||
pub mod kalloc;
|
||||
pub mod scheduling;
|
||||
pub mod drivers;
|
||||
pub mod resources;
|
||||
pub mod std;
|
||||
|
||||
/// Re-exports most of the IO macros.
|
||||
/// Re-exports most of the IO macros as well as standard allocation stuff
|
||||
pub mod prelude {
|
||||
pub use crate::drivers::io::ascii::{_print, _print_log};
|
||||
pub use crate::{print, print_log, println, println_log, serial_print, serial_println};
|
||||
pub use alloc::{
|
||||
boxed::Box,
|
||||
string::{String, ToString},
|
||||
vec::Vec,
|
||||
};
|
||||
}
|
||||
|
||||
pub use crate::drivers::io::{
|
||||
ascii::{_print, _print_log},
|
||||
serial::_serial_write,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
use libm::include_font;
|
||||
|
||||
pub mod ibm_vga_8x16;
|
||||
|
||||
pub static FONT_SPLEEN_8X16: Font = Font(include_font!(
|
||||
"/home/zxq5/Projects/OSDev/FoundryOS/libk/resources/font/spleen-8x16.psf"
|
||||
));
|
||||
pub static FONT_CP850_8X16: Font = Font(include_font!(
|
||||
"/home/zxq5/Projects/OSDev/FoundryOS/libk/resources/font/cp850-8x16.psf"
|
||||
));
|
||||
|
||||
pub struct Font(pub [[u8; 16]; 512]);
|
||||
@@ -0,0 +1 @@
|
||||
pub mod font;
|
||||
@@ -0,0 +1,14 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
pub trait Application {
|
||||
type Output;
|
||||
|
||||
async fn run(&mut self, args: Vec<String>) -> Result<Self::Output, Error>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
UnknownCommand(String),
|
||||
ApplicationFailed(String),
|
||||
KernelError(String),
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod application;
|
||||
pub mod window;
|
||||
@@ -0,0 +1,74 @@
|
||||
use crate::{prelude::*, std::maths::geometry::Vec2};
|
||||
|
||||
pub struct Window {
|
||||
dimensions: Vec2<usize>,
|
||||
position: Vec2<usize>,
|
||||
bordered: bool,
|
||||
opened: bool,
|
||||
title: String,
|
||||
}
|
||||
|
||||
impl Window {
|
||||
pub const fn new() -> Window {
|
||||
Window {
|
||||
dimensions: Vec2::new(0, 0),
|
||||
position: Vec2::new(0, 0),
|
||||
bordered: true,
|
||||
opened: false,
|
||||
title: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_bordered(&self) -> bool {
|
||||
self.bordered
|
||||
}
|
||||
|
||||
pub fn is_open(&self) -> bool {
|
||||
self.opened
|
||||
}
|
||||
|
||||
pub fn open(&mut self) {
|
||||
self.opened = true;
|
||||
}
|
||||
|
||||
pub fn close(&mut self) {
|
||||
self.opened = false;
|
||||
}
|
||||
|
||||
// some basic getters and setters for utility.
|
||||
pub fn title(&self) -> &str {
|
||||
&self.title
|
||||
}
|
||||
|
||||
pub fn dimensions(&self) -> Vec2<usize> {
|
||||
self.dimensions
|
||||
}
|
||||
|
||||
pub fn position(&self) -> Vec2<usize> {
|
||||
self.position
|
||||
}
|
||||
|
||||
pub fn set_title(&mut self, title: String) {
|
||||
self.title = title;
|
||||
}
|
||||
|
||||
pub fn move_window(&mut self, offset: Vec2<usize>) {
|
||||
self.position += offset;
|
||||
}
|
||||
|
||||
pub fn set_position(&mut self, position: Vec2<usize>) {
|
||||
self.position = position;
|
||||
}
|
||||
|
||||
pub fn set_dimensions(&mut self, dimensions: Vec2<usize>) {
|
||||
self.dimensions = dimensions;
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Window {
|
||||
fn drop(&mut self) {
|
||||
if self.opened {
|
||||
self.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
use core::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
|
||||
|
||||
pub trait Coordinate:
|
||||
Copy + Clone + PartialEq + AddAssign + MulAssign + SubAssign + DivAssign
|
||||
{
|
||||
}
|
||||
|
||||
impl Coordinate for usize {}
|
||||
impl Coordinate for isize {}
|
||||
impl Coordinate for u8 {}
|
||||
impl Coordinate for i8 {}
|
||||
impl Coordinate for u16 {}
|
||||
impl Coordinate for i16 {}
|
||||
impl Coordinate for u32 {}
|
||||
impl Coordinate for i32 {}
|
||||
impl Coordinate for u64 {}
|
||||
impl Coordinate for i64 {}
|
||||
impl Coordinate for u128 {}
|
||||
impl Coordinate for i128 {}
|
||||
impl Coordinate for f32 {}
|
||||
impl Coordinate for f64 {}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug)]
|
||||
pub struct Vec2<T: Coordinate> {
|
||||
x: T,
|
||||
y: T,
|
||||
}
|
||||
|
||||
impl<T: Coordinate> Vec2<T> {
|
||||
pub const fn new(x: T, y: T) -> Self {
|
||||
Self { x, y }
|
||||
}
|
||||
|
||||
pub fn into<S: Coordinate + From<T>>(&self) -> Vec2<S> {
|
||||
Vec2::new(self.x.clone().into(), self.y.clone().into())
|
||||
}
|
||||
|
||||
pub fn x(&self) -> T {
|
||||
self.x
|
||||
}
|
||||
|
||||
pub fn y(&self) -> T {
|
||||
self.y
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Coordinate> AddAssign for Vec2<T> {
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
self.x += rhs.x;
|
||||
self.y += rhs.y;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Coordinate> SubAssign for Vec2<T> {
|
||||
fn sub_assign(&mut self, rhs: Self) {
|
||||
self.x -= rhs.x;
|
||||
self.y -= rhs.y;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Coordinate> MulAssign<T> for Vec2<T> {
|
||||
fn mul_assign(&mut self, rhs: T) {
|
||||
self.x *= rhs;
|
||||
self.y *= rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Coordinate> DivAssign<T> for Vec2<T> {
|
||||
fn div_assign(&mut self, rhs: T) {
|
||||
self.x /= rhs;
|
||||
self.y /= rhs;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod geometry;
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod application;
|
||||
pub mod maths;
|
||||
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "libm"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
authors.workspace = true
|
||||
|
||||
[dependencies]
|
||||
darling = "0.20.10"
|
||||
proc-macro2 = "1.0.93"
|
||||
quote = "1.0.38"
|
||||
syn = "2.0.98"
|
||||
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
@@ -0,0 +1,69 @@
|
||||
use std::fs::File;
|
||||
use std::io::{Read, Seek, SeekFrom};
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{LitStr, parse_macro_input};
|
||||
|
||||
extern crate proc_macro;
|
||||
|
||||
#[proc_macro]
|
||||
pub fn include_font(item: TokenStream) -> TokenStream {
|
||||
let filename = parse_macro_input!(item as LitStr);
|
||||
let file_path = filename.value().to_string();
|
||||
|
||||
println!("Loading font: [{}]", file_path);
|
||||
|
||||
let font_data = match Font::new(load_file(file_path)) {
|
||||
Ok(font) => font.0,
|
||||
Err(e) => panic!("{}", e),
|
||||
};
|
||||
|
||||
quote!(
|
||||
[
|
||||
#(
|
||||
[#(#font_data),*]
|
||||
),*
|
||||
]
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
||||
struct Font([[u8; 16]; 512]);
|
||||
|
||||
impl Font {
|
||||
const MAGIC: u16 = 0x3604;
|
||||
|
||||
pub fn new(data: [u8; (32 + 2) * 512 + 4]) -> Result<Font, &'static str> {
|
||||
let magic: u16 = (data[0] as u16) << 8 | data[1] as u16;
|
||||
let mode = data[2];
|
||||
let size = data[3];
|
||||
|
||||
if magic != Self::MAGIC {
|
||||
return Err("Magic value is invalid!");
|
||||
}
|
||||
|
||||
let has_512_glyphs = (mode & 0x01) != 0;
|
||||
let mut glyphs = [[0; 16]; 512];
|
||||
let glyph_count = if has_512_glyphs { 512 } else { 256 };
|
||||
|
||||
for i in 0..(glyph_count as usize) {
|
||||
let mut buff: [u8; 16] = [0; 16];
|
||||
for j in 0..(size as usize) {
|
||||
buff[j] = data[4 + i * (size as usize) + j];
|
||||
}
|
||||
glyphs[i] = buff;
|
||||
}
|
||||
|
||||
Ok(Font(glyphs))
|
||||
}
|
||||
}
|
||||
|
||||
fn load_file(filename: String) -> [u8; (32 + 2) * 512 + 4] {
|
||||
let mut buf = [0; (32 + 2) * 512 + 4];
|
||||
let mut f = File::open(filename).unwrap();
|
||||
f.seek(SeekFrom::Start(0)).unwrap();
|
||||
f.read(&mut buf).unwrap();
|
||||
|
||||
return buf;
|
||||
}
|
||||
@@ -176,10 +176,13 @@ kvm_flag=""
|
||||
|
||||
trap 'check_test_res "tests completed"' ERR
|
||||
|
||||
# $build_dir/image.iso
|
||||
|
||||
|
||||
cd "$project_root"
|
||||
qemu-system-x86_64 -M q35 \
|
||||
${kvm_flag} \
|
||||
-cdrom "$build_dir/image.iso" \
|
||||
${kvm_flag} \
|
||||
-boot d \
|
||||
-m 2G \
|
||||
${serial_flags} \
|
||||
|
||||
Reference in New Issue
Block a user