1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use super::ScreenCharacter;
use crate::{
colors::{Color16Bit, TextModeColor},
vga::{Vga, VideoMode, VGA},
};
use spinning_top::SpinlockGuard;
const WIDTH: usize = 40;
const HEIGHT: usize = 25;
const SCREEN_SIZE: usize = WIDTH * HEIGHT;
static BLANK_CHARACTER: ScreenCharacter = ScreenCharacter {
character: b' ',
color: TextModeColor::new(Color16Bit::Yellow, Color16Bit::Black),
};
#[derive(Default)]
pub struct Text40x25;
impl Text40x25 {
pub fn new() -> Text40x25 {
Text40x25 {}
}
pub fn clear_screen(&self) {
let (_vga, frame_buffer) = self.get_frame_buffer();
for i in 0..SCREEN_SIZE {
unsafe {
frame_buffer.add(i).write_volatile(BLANK_CHARACTER);
}
}
}
pub fn write_character(&self, x: usize, y: usize, character: u8, color: TextModeColor) {
assert!(x < WIDTH, "x >= {}", WIDTH);
assert!(y < HEIGHT, "y >= {}", HEIGHT);
let (_vga, frame_buffer) = self.get_frame_buffer();
let offset = WIDTH * y + x;
unsafe {
frame_buffer
.add(offset)
.write_volatile(ScreenCharacter { character, color });
}
}
pub fn set_mode(&self) {
VGA.lock().set_video_mode(VideoMode::Mode40x25);
}
fn get_frame_buffer(&self) -> (SpinlockGuard<Vga>, *mut ScreenCharacter) {
let mut vga = VGA.lock();
let frame_buffer = vga.get_frame_buffer();
(vga, u32::from(frame_buffer) as *mut ScreenCharacter)
}
}