@@ -438,6 +438,14 @@ extern "C" fn video_is_valid_mode(mode: common::video::Mode) -> bool {
438438 0 => true ,
439439 // 640x480 80x60 text mode
440440 1 => true ,
441+ // 640x480, 8-bpp bitmap mode
442+ 4 => true ,
443+ // 640x480, 4-bpp bitmap mode
444+ 5 => true ,
445+ // 640x480, 2-bpp bitmap mode
446+ 6 => true ,
447+ // 640x480, 1-bpp bitmap mode
448+ 7 => true ,
441449 // nothing else will work
442450 _ => false ,
443451 } ;
@@ -450,29 +458,9 @@ extern "C" fn video_is_valid_mode(mode: common::video::Mode) -> bool {
450458/// The contents of the screen are undefined after a call to this function.
451459extern "C" fn video_set_mode ( mode : common:: video:: Mode , fb : * mut u32 ) -> common:: ApiResult < ( ) > {
452460 info ! ( "video_set_mode({:?})" , mode) ;
453- match mode. timing ( ) {
454- common:: video:: Timing :: T640x480 => {
455- // OK
456- }
457- common:: video:: Timing :: T640x400 => {
458- // OK
459- }
460- _ => {
461- return common:: ApiResult :: Err ( common:: Error :: UnsupportedConfiguration ) ;
462- }
463- }
464- match mode. format ( ) {
465- common:: video:: Format :: Text8x16 => {
466- // OK
467- }
468- common:: video:: Format :: Text8x8 => {
469- // OK
470- }
471- _ => {
472- return common:: ApiResult :: Err ( common:: Error :: UnsupportedConfiguration ) ;
473- }
461+ if !video_is_valid_mode ( mode) {
462+ return common:: ApiResult :: Err ( common:: Error :: UnsupportedConfiguration ) ;
474463 }
475-
476464 // We know this is a valid video mode because it was set with `video_set_mode`.
477465 let mode_value = mode. as_u8 ( ) ;
478466 VIDEO_MODE . store ( mode_value, Ordering :: Relaxed ) ;
@@ -499,7 +487,7 @@ extern "C" fn video_get_mode() -> common::video::Mode {
499487/// allowed to write to, is a function of the current video mode (see
500488/// `video_get_mode`).
501489extern "C" fn video_get_framebuffer ( ) -> * mut u32 {
502- let p = FRAMEBUFFER . get_pointer ( ) as * mut u32 ;
490+ let p = FRAMEBUFFER . get_pointer ( ) ;
503491 debug ! ( "video_get_framebuffer() -> {:p}" , p) ;
504492 p
505493}
@@ -535,10 +523,10 @@ extern "C" fn memory_get_region(region: u8) -> common::FfiOption<common::MemoryR
535523 match region {
536524 0 => {
537525 if unsafe { MEMORY_BLOCK . 0 . is_null ( ) } {
538- // Allocate 256 KiB of storage space for the OS to use
539- let mut data = Box :: new ( [ 0u8 ; 256 * 1024 ] ) ;
526+ // Allocate 1 MiB of storage space for the OS to use
527+ let mut data = Box :: new ( [ 0u8 ; 1024 * 1024 ] ) ;
540528 unsafe {
541- MEMORY_BLOCK . 0 = data. as_mut_ptr ( ) as * mut u8 ;
529+ MEMORY_BLOCK . 0 = data. as_mut_ptr ( ) ;
542530 MEMORY_BLOCK . 1 = std:: mem:: size_of_val ( & * data) ;
543531 }
544532 std:: mem:: forget ( data) ;
@@ -1101,6 +1089,86 @@ impl MyApp {
11011089 Self :: render_font ( & font:: font8:: FONT , & mut self . font8x8 , s) ?;
11021090 Ok ( ( ) )
11031091 }
1092+
1093+ fn render_text (
1094+ & self ,
1095+ font : & [ pix_engine:: texture:: TextureId ] ,
1096+ font_height : u16 ,
1097+ s : & mut PixState ,
1098+ ) -> PixResult < ( ) > {
1099+ let num_cols = self . mode . text_width ( ) . unwrap ( ) ;
1100+ let num_rows = self . mode . text_height ( ) . unwrap ( ) ;
1101+ let mut bg_idx = 0 ;
1102+ let mut bg_rgb = {
1103+ let bg = RGBColour :: from_packed ( PALETTE [ usize:: from ( bg_idx) ] . load ( Ordering :: Relaxed ) ) ;
1104+ rgb ! ( bg. red( ) , bg. green( ) , bg. blue( ) )
1105+ } ;
1106+ s. stroke ( None ) ;
1107+ // FRAMEBUFFER is an num_cols x num_rows size array of (u8_glyph, u8_attr).
1108+ for row in 0 ..num_rows {
1109+ let y = row * font_height;
1110+ for col in 0 ..num_cols {
1111+ let cell_no = ( row * num_cols) + col;
1112+ let byte_offset = usize:: from ( cell_no) * 2 ;
1113+ let x = col * 8 ;
1114+ let glyph = FRAMEBUFFER . get_at ( byte_offset) ;
1115+ let attr = common:: video:: Attr ( FRAMEBUFFER . get_at ( byte_offset + 1 ) ) ;
1116+ let fg_idx = attr. fg ( ) . make_ffi_safe ( ) . 0 ;
1117+ let new_bg_idx = attr. bg ( ) . make_ffi_safe ( ) . 0 ;
1118+ if new_bg_idx != bg_idx {
1119+ bg_idx = new_bg_idx;
1120+ let bg = RGBColour :: from_packed (
1121+ PALETTE [ usize:: from ( bg_idx) ] . load ( Ordering :: Relaxed ) ,
1122+ ) ;
1123+ bg_rgb = rgb ! ( bg. red( ) , bg. green( ) , bg. blue( ) ) ;
1124+ }
1125+ let glyph_box = rect ! ( i32 :: from( x) , i32 :: from( y) , 8i32 , font_height as i32 , ) ;
1126+ s. fill ( bg_rgb) ;
1127+ s. rect ( glyph_box) ?;
1128+ let slot = ( usize:: from ( glyph) * Self :: NUM_FG ) + usize:: from ( fg_idx) ;
1129+ s. texture ( font[ slot] , None , Some ( glyph_box) ) ?;
1130+ }
1131+ }
1132+ Ok ( ( ) )
1133+ }
1134+
1135+ fn render_chunky < const BPP : usize > ( & self , s : & mut PixState ) -> PixResult < ( ) > {
1136+ let shift = 8 - BPP ;
1137+ let num_colours = 1 << BPP ;
1138+ let pixels_per_byte = 8 / BPP ;
1139+ let num_col_bytes = self . mode . line_size_bytes ( ) ;
1140+ let num_rows = self . mode . vertical_lines ( ) as usize ;
1141+ let colours = Self :: make_colours ( num_colours) ;
1142+ for y in 0 ..num_rows {
1143+ let y_bytes = y * num_col_bytes;
1144+ for x_byte in 0 ..num_col_bytes {
1145+ let byte_offset = y_bytes + x_byte;
1146+ let mut data = FRAMEBUFFER . get_at ( byte_offset) ;
1147+ let x_start = x_byte * pixels_per_byte;
1148+ for x in 0 ..pixels_per_byte {
1149+ let bit = ( data >> shift) as usize ;
1150+ s. stroke ( colours[ bit] ) ;
1151+ let p = point ! ( ( x_start + x) as i32 , y as i32 ) ;
1152+ s. point ( p) ?;
1153+ data <<= BPP ;
1154+ }
1155+ }
1156+ }
1157+ Ok ( ( ) )
1158+ }
1159+
1160+ fn make_colours ( count : usize ) -> Vec < pix_engine:: color:: Color > {
1161+ let mut result = vec ! [ ] ;
1162+ for palette_entry in PALETTE . iter ( ) . take ( count) {
1163+ let rgb = RGBColour :: from_packed ( palette_entry. load ( Ordering :: Relaxed ) ) ;
1164+ result. push ( rgb ! ( rgb. red( ) , rgb. green( ) , rgb. blue( ) ) ) ;
1165+ }
1166+ if count == 2 {
1167+ // special case - use black/white for 2 colour mode, not black/blue
1168+ result[ 1 ] = rgb ! ( 0xFF , 0xFF , 0xFF ) ;
1169+ }
1170+ result
1171+ }
11041172}
11051173
11061174impl PixEngine for MyApp {
@@ -1168,39 +1236,21 @@ impl PixEngine for MyApp {
11681236 info ! ( "Window set to {} x {}" , width, height) ;
11691237 s. set_window_dimensions ( ( width as u32 , height as u32 ) ) ?;
11701238 s. scale ( SCALE_FACTOR , SCALE_FACTOR ) ?;
1239+ s. background ( rgb ! ( 0 , 0 , 0 ) ) ;
1240+ s. clear ( ) ?;
11711241 }
11721242
11731243 s. blend_mode ( BlendMode :: Blend ) ;
11741244
1175- let ( font, font_height) = match self . mode . format ( ) {
1176- common:: video:: Format :: Text8x16 => ( & self . font8x16 , 16 ) ,
1177- common:: video:: Format :: Text8x8 => ( & self . font8x8 , 8 ) ,
1245+ match self . mode . format ( ) {
1246+ common:: video:: Format :: Text8x16 => self . render_text ( & self . font8x16 , 16 , s) ?,
1247+ common:: video:: Format :: Text8x8 => self . render_text ( & self . font8x8 , 8 , s) ?,
1248+ common:: video:: Format :: Chunky1 => self . render_chunky :: < 1 > ( s) ?,
1249+ common:: video:: Format :: Chunky2 => self . render_chunky :: < 2 > ( s) ?,
1250+ common:: video:: Format :: Chunky4 => self . render_chunky :: < 4 > ( s) ?,
1251+ common:: video:: Format :: Chunky8 => self . render_chunky :: < 8 > ( s) ?,
11781252 _ => {
11791253 // Unknown mode - do nothing
1180- return Ok ( ( ) ) ;
1181- }
1182- } ;
1183-
1184- let num_cols = self . mode . text_width ( ) . unwrap ( ) ;
1185- let num_rows = self . mode . text_height ( ) . unwrap ( ) ;
1186- // FRAMEBUFFER is an num_cols x num_rows size array of (u8_glyph, u8_attr).
1187- for row in 0 ..num_rows {
1188- let y = row * font_height;
1189- for col in 0 ..num_cols {
1190- let cell_no = ( row * num_cols) + col;
1191- let byte_offset = usize:: from ( cell_no) * 2 ;
1192- let x = col * 8 ;
1193- let glyph = FRAMEBUFFER . get_at ( byte_offset) ;
1194- let attr = common:: video:: Attr ( FRAMEBUFFER . get_at ( byte_offset + 1 ) ) ;
1195- let fg_idx = attr. fg ( ) . make_ffi_safe ( ) . 0 ;
1196- let bg_idx = attr. bg ( ) . make_ffi_safe ( ) . 0 ;
1197- let bg =
1198- RGBColour :: from_packed ( PALETTE [ usize:: from ( bg_idx) ] . load ( Ordering :: Relaxed ) ) ;
1199- let glyph_box = rect ! ( i32 :: from( x) , i32 :: from( y) , 8i32 , font_height as i32 , ) ;
1200- s. fill ( rgb ! ( bg. red( ) , bg. green( ) , bg. blue( ) ) ) ;
1201- s. rect ( glyph_box) ?;
1202- let slot = ( usize:: from ( glyph) * Self :: NUM_FG ) + usize:: from ( fg_idx) ;
1203- s. texture ( font[ slot] , None , Some ( glyph_box) ) ?;
12041254 }
12051255 }
12061256
0 commit comments