Skip to content

Commit 290b72c

Browse files
committed
Use BIOS framebuffer API to write to screen.
1 parent e41f0b2 commit 290b72c

File tree

3 files changed

+120
-12
lines changed

3 files changed

+120
-12
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@ debug = true
1919
codegen-units = 1
2020
opt-level = "s"
2121

22-
[dependencies.neotron_common_bios]
22+
[dependencies.neotron-common-bios]
2323
path = "./common"

common

src/main.rs

Lines changed: 118 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,20 @@ use neotron_common_bios as common;
1212
#[used]
1313
pub static ENTRY_POINT: extern "C" fn(&'static common::Api) -> ! = entry_point;
1414

15+
/// The OS version string
16+
static OS_VERSION: &str = concat!("Neotron OS, version ", env!("CARGO_PKG_VERSION"), "\0");
17+
1518
static mut API: Option<&'static common::Api> = None;
1619

20+
#[derive(Debug)]
21+
struct VgaConsole {
22+
addr: *mut u8,
23+
width: u8,
24+
height: u8,
25+
row: u8,
26+
col: u8,
27+
}
28+
1729
struct SerialConsole;
1830

1931
impl core::fmt::Write for SerialConsole {
@@ -29,24 +41,120 @@ impl core::fmt::Write for SerialConsole {
2941
}
3042
}
3143

44+
impl VgaConsole {
45+
const DEFAULT_ATTR: u8 = (2 << 3) | (1 << 0);
46+
47+
fn move_char_right(&mut self) {
48+
self.col += 1;
49+
if self.col == self.width {
50+
self.col = 0;
51+
self.move_char_down();
52+
}
53+
}
54+
55+
fn move_char_down(&mut self) {
56+
self.row += 1;
57+
if self.row == self.height {
58+
self.scroll_page();
59+
self.row = self.height - 1;
60+
}
61+
}
62+
63+
fn read(&self) -> (u8, u8) {
64+
let offset =
65+
((isize::from(self.row) * isize::from(self.width)) + isize::from(self.col)) * 2;
66+
let glyph = unsafe { core::ptr::read_volatile(self.addr.offset(offset)) };
67+
let attr = unsafe { core::ptr::read_volatile(self.addr.offset(offset + 1)) };
68+
(glyph, attr)
69+
}
70+
71+
fn find_start_row(&mut self) {
72+
for row in 0..self.height {
73+
self.row = row;
74+
let g = self.read().0;
75+
if (g == b'\0') || (g == b' ') {
76+
// Found a line with nothing on it - start here!
77+
break;
78+
}
79+
}
80+
}
81+
82+
fn write(&mut self, glyph: u8, attr: Option<u8>) {
83+
let offset =
84+
((isize::from(self.row) * isize::from(self.width)) + isize::from(self.col)) * 2;
85+
unsafe { core::ptr::write_volatile(self.addr.offset(offset), glyph) };
86+
if let Some(a) = attr {
87+
unsafe { core::ptr::write_volatile(self.addr.offset(offset + 1), a) };
88+
}
89+
}
90+
91+
fn scroll_page(&mut self) {
92+
unsafe {
93+
core::ptr::copy(
94+
self.addr.offset(isize::from(self.width * 2)),
95+
self.addr,
96+
usize::from(self.width) * usize::from(self.height - 1) * 2,
97+
);
98+
// Blank bottom line
99+
for col in 0..self.width {
100+
self.col = col;
101+
self.write(b' ', Some(Self::DEFAULT_ATTR));
102+
}
103+
self.col = 0;
104+
}
105+
}
106+
}
107+
108+
impl core::fmt::Write for VgaConsole {
109+
fn write_str(&mut self, data: &str) -> core::fmt::Result {
110+
for ch in data.chars() {
111+
match ch {
112+
'\r' => {
113+
self.col = 0;
114+
}
115+
'\n' => {
116+
self.col = 0;
117+
self.move_char_down();
118+
}
119+
b if b <= '\u{00FF}' => {
120+
self.write(b as u8, None);
121+
self.move_char_right();
122+
}
123+
_ => {
124+
self.write(b'?', None);
125+
self.move_char_right();
126+
}
127+
}
128+
}
129+
Ok(())
130+
}
131+
}
132+
32133
#[no_mangle]
33134
extern "C" fn entry_point(api: &'static common::Api) -> ! {
34135
unsafe {
35136
API = Some(api);
36137
}
37-
writeln!(SerialConsole, "Neotron OS.").unwrap();
38-
writeln!(SerialConsole, "BIOS Version: {}", (api.bios_version_get)()).unwrap();
39-
writeln!(
40-
SerialConsole,
41-
"BIOS API Version: {}",
42-
(api.api_version_get)()
43-
)
44-
.unwrap();
138+
let mut addr: *mut u8 = core::ptr::null_mut();
139+
let mut width = 0;
140+
let mut height = 0;
141+
(api.video_memory_info_get)(&mut addr, &mut width, &mut height);
142+
let mut vga = VgaConsole {
143+
addr,
144+
width,
145+
height,
146+
row: 0,
147+
col: 0,
148+
};
149+
vga.find_start_row();
150+
writeln!(vga, "{}", OS_VERSION).unwrap();
151+
writeln!(vga, "BIOS Version: {}", (api.bios_version_get)()).unwrap();
152+
writeln!(vga, "BIOS API Version: {}", (api.api_version_get)()).unwrap();
45153
loop {
46-
for _ in 0..80_000_000 {
154+
for _ in 0..1_000_000 {
47155
let _ = (api.api_version_get)();
48156
}
49-
writeln!(SerialConsole, "tick...").unwrap();
157+
writeln!(vga, "tick...").unwrap();
50158
}
51159
}
52160

0 commit comments

Comments
 (0)