Skip to content

Commit 8dad0ec

Browse files
authored
Merge pull request #29 from Neotron-Compute/colour-screen-fill-command
Colour screen fill command
2 parents 2726b78 + 67b43f4 commit 8dad0ec

File tree

3 files changed

+84
-25
lines changed

3 files changed

+84
-25
lines changed

build.sh

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,18 @@ mkdir -p ${RELEASE_DIR}
88

99
# Build the embedded binaries for each core type and each flash layout
1010
for TARGET_ARCH in thumbv6m-none-eabi thumbv7m-none-eabi thumbv7em-none-eabi; do
11+
echo "TARGET is ${TARGET_ARCH}"
1112
for BINARY in flash0002 flash0802 flash1002; do
12-
# objcopy will do the build for us first
13+
echo "BINARY is ${BINARY}"
14+
cargo build --verbose --release --target=${TARGET_ARCH} --bin ${BINARY}
15+
# objcopy would do the build for us first, but it doesn't have good build output
1316
cargo objcopy --verbose --release --target=${TARGET_ARCH} --bin ${BINARY} -- -O binary ${RELEASE_DIR}/${TARGET_ARCH}-${BINARY}-libneotron_os.bin
1417
# Keep the ELF file too (for debugging)
1518
cp ./target/${TARGET_ARCH}/release/${BINARY} ${RELEASE_DIR}/${TARGET_ARCH}-${BINARY}-libneotron_os.elf
1619
done
1720
done
1821

1922
# Build the host version
23+
echo "Building HOST"
2024
cargo build --verbose --lib --release --target=x86_64-unknown-linux-gnu
2125
cp ./target/x86_64-unknown-linux-gnu/release/libneotron_os.so ${RELEASE_DIR}/x86_64-unknown-linux-gnu-libneotron_os.so

src/commands/screen.rs

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! Screen-related commands for Neotron OS
22
3-
use crate::{print, println, Ctx, API, VGA_CONSOLE};
3+
use neotron_common_bios::video::{Attr, TextBackgroundColour, TextForegroundColour};
4+
5+
use crate::{println, Ctx, API, VGA_CONSOLE};
46

57
pub static CLEAR_ITEM: menu::Item<Ctx> = menu::Item {
68
item_type: menu::ItemType::Callback {
@@ -31,19 +33,39 @@ fn clear(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, _args: &[&str], _ctx:
3133
fn fill(_menu: &menu::Menu<Ctx>, _item: &menu::Item<Ctx>, _args: &[&str], _ctx: &mut Ctx) {
3234
if let Some(ref mut console) = unsafe { &mut VGA_CONSOLE } {
3335
console.clear();
34-
}
35-
let api = API.get();
36-
let mode = (api.video_get_mode)();
37-
let (Some(width), Some(height)) = (mode.text_width(), mode.text_height()) else {
38-
println!("Unable to get console size");
39-
return;
40-
};
41-
// A range of printable ASCII compatible characters
42-
let mut char_cycle = (' '..='~').cycle();
43-
// Scroll two screen fulls
44-
for _row in 0..height * 2 {
45-
for _col in 0..width {
46-
print!("{}", char_cycle.next().unwrap());
36+
let api = API.get();
37+
let mode = (api.video_get_mode)();
38+
let (Some(width), Some(height)) = (mode.text_width(), mode.text_height()) else {
39+
println!("Unable to get console size");
40+
return;
41+
};
42+
// A range of printable ASCII compatible characters
43+
let mut char_cycle = (b' '..=b'~').cycle();
44+
let mut remaining = height * width;
45+
46+
// Scroll two screen fulls
47+
'outer: for bg in (0..=7).cycle() {
48+
let bg_colour = TextBackgroundColour::new(bg).unwrap();
49+
for fg in 1..=15 {
50+
if fg == bg {
51+
continue;
52+
}
53+
let fg_colour = TextForegroundColour::new(fg).unwrap();
54+
remaining -= 1;
55+
if remaining == 0 {
56+
break 'outer;
57+
}
58+
let attr = Attr::new(fg_colour, bg_colour, false);
59+
let glyph = char_cycle.next().unwrap();
60+
console.set_attr(attr);
61+
console.write_bstr(&[glyph]);
62+
}
4763
}
64+
let attr = Attr::new(
65+
TextForegroundColour::WHITE,
66+
TextBackgroundColour::BLACK,
67+
false,
68+
);
69+
console.set_attr(attr);
4870
}
4971
}

src/vgaconsole.rs

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
66
use neotron_common_bios::video::{Attr, TextBackgroundColour, TextForegroundColour};
77

8-
#[derive(Debug)]
98
pub struct VgaConsole {
109
addr: *mut u8,
1110
width: isize,
1211
height: isize,
1312
row: isize,
1413
col: isize,
14+
attr: Attr,
1515
}
1616

1717
impl VgaConsole {
@@ -29,6 +29,7 @@ impl VgaConsole {
2929
height,
3030
row: 0,
3131
col: 0,
32+
attr: Self::DEFAULT_ATTR,
3233
}
3334
}
3435

@@ -60,24 +61,56 @@ impl VgaConsole {
6061
pub fn clear(&mut self) {
6162
for row in 0..self.height {
6263
for col in 0..self.width {
63-
self.write_at(row, col, b' ', Some(Self::DEFAULT_ATTR));
64+
self.write_at(row, col, b' ');
6465
}
6566
}
6667
self.reset_cursor();
6768
}
6869

69-
fn write(&mut self, glyph: u8, attr: Option<Attr>) {
70-
self.write_at(self.row, self.col, glyph, attr);
70+
pub fn write_bstr(&mut self, bstr: &[u8]) {
71+
for b in bstr {
72+
self.scroll_as_required();
73+
match b {
74+
0x08 => {
75+
// This is a backspace, so we go back one character (if we
76+
// can). We expect the caller to provide "\u{0008} \u{0008}"
77+
// to actually erase the char then move the cursor over it.
78+
if self.col > 0 {
79+
self.col -= 1;
80+
}
81+
}
82+
b'\r' => {
83+
self.col = 0;
84+
}
85+
b'\n' => {
86+
self.col = 0;
87+
self.move_char_down();
88+
}
89+
_ => {
90+
self.write(*b);
91+
self.move_char_right();
92+
}
93+
}
94+
}
7195
}
7296

73-
fn write_at(&mut self, row: isize, col: isize, glyph: u8, attr: Option<Attr>) {
97+
/// Set the default attribute for any future text.
98+
pub fn set_attr(&mut self, attr: Attr) {
99+
self.attr = attr;
100+
}
101+
102+
/// Put a glyph at the next position on the screen.
103+
fn write(&mut self, glyph: u8) {
104+
self.write_at(self.row, self.col, glyph);
105+
}
106+
107+
/// Put a glyph at a given position on the screen.
108+
fn write_at(&mut self, row: isize, col: isize, glyph: u8) {
74109
assert!(row < self.height, "{} >= {}?", row, self.height);
75110
assert!(col < self.width, "{} => {}?", col, self.width);
76111
let offset = ((row * self.width) + col) * 2;
77112
unsafe { core::ptr::write_volatile(self.addr.offset(offset), glyph) };
78-
if let Some(a) = attr {
79-
unsafe { core::ptr::write_volatile(self.addr.offset(offset + 1), a.0) };
80-
}
113+
unsafe { core::ptr::write_volatile(self.addr.offset(offset + 1), self.attr.as_u8()) };
81114
}
82115

83116
fn scroll_page(&mut self) {
@@ -91,7 +124,7 @@ impl VgaConsole {
91124
);
92125
// Blank the bottom line of the screen (rows[height-1]).
93126
for col in 0..self.width {
94-
self.write_at(self.height - 1, col, b' ', Some(Self::DEFAULT_ATTR));
127+
self.write_at(self.height - 1, col, b' ');
95128
}
96129
}
97130
}
@@ -260,7 +293,7 @@ impl core::fmt::Write for VgaConsole {
260293
self.move_char_down();
261294
}
262295
_ => {
263-
self.write(Self::map_char_to_glyph(ch), None);
296+
self.write(Self::map_char_to_glyph(ch));
264297
self.move_char_right();
265298
}
266299
}

0 commit comments

Comments
 (0)