@@ -12,8 +12,20 @@ use neotron_common_bios as common;
1212#[ used]
1313pub 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+
1518static 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+
1729struct SerialConsole ;
1830
1931impl 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]
33134extern "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