@@ -66,7 +66,7 @@ struct RenderEngine {
6666pub struct TextConsole {
6767 current_col : AtomicU16 ,
6868 current_row : AtomicU16 ,
69- text_buffer : AtomicPtr < u8 > ,
69+ text_buffer : AtomicPtr < GlyphAttr > ,
7070}
7171
7272/// Describes one scan-line's worth of pixels, including the length word required by the Pixel FIFO.
@@ -133,6 +133,22 @@ pub struct RGBColour(u16);
133133#[ derive( Copy , Clone , PartialEq , Eq ) ]
134134pub struct RGBPair ( u32 ) ;
135135
136+ /// Represents a glyph in the current font.
137+ #[ repr( transparent) ]
138+ #[ derive( Copy , Clone , PartialEq , Eq ) ]
139+ pub struct Glyph ( u8 ) ;
140+
141+ /// Represents VGA format foreground/background attributes.
142+ #[ repr( transparent) ]
143+ #[ derive( Copy , Clone , PartialEq , Eq ) ]
144+ pub struct Attr ( u8 ) ;
145+
146+ /// Represents a glyph/attribute pair. This is what out text console is made
147+ /// out of. They work in exactly the same way as IBM PC VGA.
148+ #[ repr( transparent) ]
149+ #[ derive( Copy , Clone , PartialEq , Eq , Default ) ]
150+ pub struct GlyphAttr ( u16 ) ;
151+
136152// -----------------------------------------------------------------------------
137153// Static and Const Data
138154// -----------------------------------------------------------------------------
@@ -206,11 +222,12 @@ static mut PIXEL_DATA_BUFFER_ODD: LineBuffer = LineBuffer {
206222/// This is our text buffer.
207223///
208224/// This is arranged as `NUM_TEXT_ROWS` rows of `NUM_TEXT_COLS` columns. Each
209- /// item is an index into `font::FONT_DATA` (or a Code-Page 850 character).
225+ /// item is an index into `font::FONT_DATA` (or a Code-Page 850 character)
226+ /// plus an 8-bit attribute.
210227///
211228/// Written to by Core 0, and read from by `RenderEngine` running on Core 1.
212- pub static mut CHAR_ARRAY : [ u8 ; NUM_TEXT_COLS as usize * NUM_TEXT_ROWS as usize ] =
213- [ 0u8 ; NUM_TEXT_COLS as usize * NUM_TEXT_ROWS as usize ] ;
229+ pub static mut GLYPH_ATTR_ARRAY : [ GlyphAttr ; NUM_TEXT_COLS as usize * NUM_TEXT_ROWS as usize ] =
230+ [ GlyphAttr ( 0 ) ; NUM_TEXT_COLS as usize * NUM_TEXT_ROWS as usize ] ;
214231
215232/// Core 1 entry function.
216233///
@@ -740,7 +757,7 @@ impl RenderEngine {
740757 // state. At least our platform is fixed, so we can simply
741758 // test if it works, for some given version of the Rust compiler.
742759 let row_slice = unsafe {
743- & CHAR_ARRAY [ ( text_row * NUM_TEXT_COLS ) ..( ( text_row + 1 ) * NUM_TEXT_COLS ) ]
760+ & GLYPH_ATTR_ARRAY [ ( text_row * NUM_TEXT_COLS ) ..( ( text_row + 1 ) * NUM_TEXT_COLS ) ]
744761 } ;
745762 // Every font look-up we are about to do for this row will
746763 // involve offsetting by the row within each glyph. As this
@@ -754,14 +771,15 @@ impl RenderEngine {
754771 let mut px_idx = 0 ;
755772
756773 // Convert from characters to coloured pixels, using the font as a look-up table.
757- for ch in row_slice. iter ( ) {
758- let index = ( * ch as isize ) * 16 ;
774+ for glyphattr in row_slice. iter ( ) {
775+ let index = ( glyphattr . glyph ( ) . 0 as isize ) * 16 ;
759776 // Note (unsafe): We use pointer arithmetic here because we
760777 // can't afford a bounds-check on an array. This is safe
761778 // because the font is `256 * width` bytes long and we can't
762779 // index more than `255 * width` bytes into it.
763780 let mono_pixels = unsafe { * font_ptr. offset ( index) } as usize ;
764- // Convert from eight mono pixels in one byte to four RGB pairs
781+ // Convert from eight mono pixels in one byte to four RGB
782+ // pairs. Hopefully the `& 3` elides the panic calls.
765783 unsafe {
766784 core:: ptr:: write_volatile (
767785 scan_line_buffer_ptr. offset ( px_idx) ,
@@ -808,7 +826,10 @@ impl TextConsole {
808826 /// Update the text buffer we are using.
809827 ///
810828 /// Will reset the cursor. The screen is not cleared.
811- pub fn set_text_buffer ( & self , text_buffer : & ' static mut [ u8 ; NUM_TEXT_ROWS * NUM_TEXT_COLS ] ) {
829+ pub fn set_text_buffer (
830+ & self ,
831+ text_buffer : & ' static mut [ GlyphAttr ; NUM_TEXT_ROWS * NUM_TEXT_COLS ] ,
832+ ) {
812833 self . text_buffer
813834 . store ( text_buffer. as_mut_ptr ( ) , Ordering :: Relaxed )
814835 }
@@ -817,14 +838,14 @@ impl TextConsole {
817838 ///
818839 /// Adjusts the current row and column automatically. Also understands
819840 /// Carriage Return and New Line bytes.
820- pub fn write_font_glyph ( & self , font_glyph : u8 ) {
841+ pub fn write_font_glyph ( & self , glyph : Glyph ) {
821842 // Load from global state
822843 let mut row = self . current_row . load ( Ordering :: Relaxed ) ;
823844 let mut col = self . current_col . load ( Ordering :: Relaxed ) ;
824845 let buffer = self . text_buffer . load ( Ordering :: Relaxed ) ;
825846
826847 if !buffer. is_null ( ) {
827- self . write_at ( font_glyph , buffer, & mut row, & mut col) ;
848+ self . write_at ( glyph , buffer, & mut row, & mut col) ;
828849 // Push back to global state
829850 self . current_row . store ( row as u16 , Ordering :: Relaxed ) ;
830851 self . current_col . store ( col as u16 , Ordering :: Relaxed ) ;
@@ -848,10 +869,10 @@ impl TextConsole {
848869 /// Zero-width and modifier Unicode Scalar Values (e.g. `U+0301 COMBINING,
849870 /// ACCENT`) are not supported. Normalise your Unicode before calling
850871 /// this function.
851- fn map_char_to_glyph ( input : char ) -> u8 {
872+ fn map_char_to_glyph ( input : char ) -> Glyph {
852873 // This fixed table only works for the default font. When we support
853874 // changing font, we will need to plug-in a different table for each font.
854- match input {
875+ let index = match input {
855876 '\u{0000}' ..='\u{007F}' => input as u8 ,
856877 '\u{00A0}' => 255 , // NBSP
857878 '\u{00A1}' => 173 , // ¡
@@ -982,22 +1003,27 @@ impl TextConsole {
9821003 '\u{2593}' => 178 , // ▓
9831004 '\u{25A0}' => 254 , // ■
9841005 _ => b'?' ,
985- }
1006+ } ;
1007+ Glyph ( index)
9861008 }
9871009
9881010 /// Put a single character at a specified point on screen.
9891011 ///
9901012 /// The character is relative to the current font.
991- fn write_at ( & self , font_glyph : u8 , buffer : * mut u8 , row : & mut u16 , col : & mut u16 ) {
992- if font_glyph == b'\r' {
1013+ fn write_at ( & self , glyph : Glyph , buffer : * mut GlyphAttr , row : & mut u16 , col : & mut u16 ) {
1014+ if glyph . 0 == b'\r' {
9931015 * col = 0 ;
994- } else if font_glyph == b'\n' {
1016+ } else if glyph . 0 == b'\n' {
9951017 * col = 0 ;
9961018 * row += 1 ;
9971019 } else {
9981020 let offset = ( * col as usize ) + ( NUM_TEXT_COLS * ( * row as usize ) ) ;
9991021 // Note (safety): This is safe as we bound `col` and `row`
1000- unsafe { buffer. add ( offset) . write_volatile ( font_glyph) } ;
1022+ unsafe {
1023+ buffer
1024+ . add ( offset)
1025+ . write_volatile ( GlyphAttr :: new ( glyph, Attr ( 0 ) ) )
1026+ } ;
10011027 * col += 1 ;
10021028 }
10031029 if * col == ( NUM_TEXT_COLS as u16 ) {
@@ -1018,7 +1044,11 @@ impl TextConsole {
10181044
10191045 for blank_col in 0 ..NUM_TEXT_COLS {
10201046 let offset = ( blank_col as usize ) + ( NUM_TEXT_COLS * ( * row as usize ) ) ;
1021- unsafe { buffer. add ( offset) . write_volatile ( b' ' ) } ;
1047+ unsafe {
1048+ buffer
1049+ . add ( offset)
1050+ . write_volatile ( GlyphAttr :: new ( Glyph ( b' ' ) , Attr ( 0 ) ) )
1051+ } ;
10221052 }
10231053 }
10241054 }
@@ -1266,6 +1296,24 @@ impl RGBPair {
12661296 }
12671297}
12681298
1299+ impl GlyphAttr {
1300+ /// Make a new glyph/attribute pair.
1301+ pub const fn new ( glyph : Glyph , attr : Attr ) -> GlyphAttr {
1302+ let value: u16 = ( glyph. 0 as u16 ) + ( ( attr. 0 as u16 ) << 8 ) ;
1303+ GlyphAttr ( value)
1304+ }
1305+
1306+ /// Get the glyph component of this pair.
1307+ pub const fn glyph ( self ) -> Glyph {
1308+ Glyph ( self . 0 as u8 )
1309+ }
1310+
1311+ /// Get the attribute component of this pair.
1312+ pub const fn attr ( self ) -> Attr {
1313+ Attr ( ( self . 0 >> 8 ) as u8 )
1314+ }
1315+ }
1316+
12691317// -----------------------------------------------------------------------------
12701318// End of file
12711319// -----------------------------------------------------------------------------
0 commit comments