diff options
Diffstat (limited to 'src/machine/cgascr.rs')
| -rw-r--r-- | src/machine/cgascr.rs | 378 |
1 files changed, 188 insertions, 190 deletions
diff --git a/src/machine/cgascr.rs b/src/machine/cgascr.rs index a529b8b..3fa7b95 100644 --- a/src/machine/cgascr.rs +++ b/src/machine/cgascr.rs @@ -1,6 +1,6 @@ use crate::arch::x86_64::io_port::*; use crate::arch::x86_64::misc::*; -use core::{slice,ptr,str}; +use core::{ptr, slice, str}; // I would consider these cga parameters constant. // the scroll() and clear() works with the assumption @@ -10,203 +10,201 @@ use core::{slice,ptr,str}; // holds // For each character, it takes 2 byte in the buffer // (one for char and one for attribute) -// Therefore the MAX_COLS should be a multiple of 4 -const MAX_COLS:usize = 80; -const MAX_ROWS:usize = 25; -const CGA_BUFFER_START:*mut u8 = 0xb8000 as *mut u8; -const CGA_BUFFER_BYTE_SIZE:usize = MAX_COLS * MAX_ROWS *2; - +// Therefore the MAX_COLS should be a multiple of 4 +const MAX_COLS: usize = 80; +const MAX_ROWS: usize = 25; +const CGA_BUFFER_START: *mut u8 = 0xb8000 as *mut u8; +const CGA_BUFFER_BYTE_SIZE: usize = MAX_COLS * MAX_ROWS * 2; // THESE TWO ARE USED TO DO BATCH OPERATIONS ON CGA BUFFER // MEMORY, HOPEFULLY MAKE IT FASTER. // I.E. SETTING 4 CHARACTERS AT ONCE. -const CGA_BUFFER_START_64:*mut u64 = 0xb8000 as *mut u64; -const CGA_BUFFER_QWORD_SIZE:usize = CGA_BUFFER_BYTE_SIZE / 8; -const CGA_BUFFER_QWORDS_PER_ROW:usize = MAX_COLS / 4; +const CGA_BUFFER_START_64: *mut u64 = 0xb8000 as *mut u64; +const CGA_BUFFER_QWORD_SIZE: usize = CGA_BUFFER_BYTE_SIZE / 8; +const CGA_BUFFER_QWORDS_PER_ROW: usize = MAX_COLS / 4; -const IR_PORT:u16 = 0x3d4; -const DR_PORT:u16 = 0x3d5; +const IR_PORT: u16 = 0x3d4; +const DR_PORT: u16 = 0x3d5; #[allow(dead_code)] -pub struct CGAScreen <'a>{ - pub cga_mem:&'a mut [u8], - cursor_r: usize, - cursor_c: usize, - attr: u8 +pub struct CGAScreen<'a> { + pub cga_mem: &'a mut [u8], + cursor_r: usize, + cursor_c: usize, + attr: u8, } #[allow(dead_code)] -impl <'a> CGAScreen<'a>{ - pub fn new() -> Self { - Self {cga_mem: unsafe{slice::from_raw_parts_mut(CGA_BUFFER_START, 2*MAX_COLS*MAX_ROWS)}, - cursor_r:0, - cursor_c:0, - attr:0x0f - } - } - - #[inline(always)] - fn cal_offset(&self,row:usize, col:usize) -> usize{ - col + row*MAX_COLS - } - - pub fn show(&self, row:usize, col:usize, c:char, attr:u8){ - let index = self.cal_offset(row, col); - - unsafe{ - *CGA_BUFFER_START.offset(index as isize * 2) = c as u8; - *CGA_BUFFER_START.offset(index as isize * 2 + 1) = attr; - } - } - - pub fn putchar(&mut self, ch:char){ - if ch == '\n'{ - self.cursor_r += 1; - self.cursor_c = 0; - self._check_scroll(); - }else{ - self.show(self.cursor_r, self.cursor_c,ch,self.attr); - self.cursor_c += 1; - if self.cursor_c>= MAX_COLS { - self.cursor_c = 0; - self.cursor_r += 1; - self._check_scroll(); - } - } - - self.setpos(self.cursor_r, self.cursor_c); - } - - fn _check_scroll(&mut self ){ - if self.cursor_r >= MAX_ROWS { - self.scroll(1); - self.cursor_r -= 1; - } - } - - pub fn scroll(&self, lines: u32) { - // TODO - // sanity check - if lines >= MAX_COLS as u32{ - self.clear(); - } - - if lines == 0 { - return; - } - // behold the magic ... (oh fuck me) - let mut i:usize = lines as usize - 1; - loop{ - if i == MAX_ROWS {break;} - let offset_src = (i*CGA_BUFFER_QWORDS_PER_ROW) as isize; - let offset_dist = offset_src - (lines*CGA_BUFFER_QWORDS_PER_ROW as u32) as isize; - unsafe{ - ptr::copy_nonoverlapping( - CGA_BUFFER_START_64.offset(offset_src), - CGA_BUFFER_START_64.offset(offset_dist), - CGA_BUFFER_QWORDS_PER_ROW); - } - i += 1; - } - - i = MAX_ROWS - lines as usize; - loop{ - if i == MAX_ROWS {break;} - self.clearline(i); - i += 1; - } - // clear the remaining lines: - } - - pub fn clear(&self){ - // remember to swap the endian.. - let b : u8 = self.attr; - let mut base:u64 = (b as u64) << 8; - base += base << 16; - base += base << 32; - - - for i in 0..CGA_BUFFER_QWORD_SIZE{ - unsafe{*CGA_BUFFER_START_64.offset(i as isize) = base} - } - } - - fn clearline(&self, line:usize){ - - let b : u8 = self.attr; - let mut base:u64 = (b as u64) << 8; - base += base << 16; - base += base << 32; - let start_offset_qw:isize = (line as isize) * CGA_BUFFER_QWORDS_PER_ROW as isize; - let end_offset_qw:isize = start_offset_qw + CGA_BUFFER_QWORDS_PER_ROW as isize; - unsafe{ - for i in start_offset_qw..end_offset_qw{ - *CGA_BUFFER_START_64.offset(i) = base; - } - } - - } - - - pub fn setpos(&mut self, row:usize, col:usize){ - // io ports for instruction register and data register - let offset = self.cal_offset(row,col); - // set lower byte - outb(IR_PORT, 15 as u8); - delay(); - outb(DR_PORT, offset as u8); - delay(); - // set higher byte - outb(IR_PORT, 14 as u8); - delay(); - outb(DR_PORT, (offset >> 8) as u8); - delay(); - self.cursor_r = row; - self.cursor_c = col; - } - - pub fn getpos_xy(&self, row:& mut u32, col:& mut u32){ - let offset = Self::getpos_offset(); - *row = offset % MAX_COLS as u32; - *col = offset / MAX_COLS as u32; - } - - #[allow(arithmetic_overflow)] - pub fn getpos_offset() -> u32 { - // read higher byte - outb(IR_PORT, 14 as u8); - let mut offset = inb(DR_PORT); - offset = offset << 8; - // read lower byte - outb(IR_PORT, 15 as u8); - offset += inb(DR_PORT); - offset as u32 - } - - - // Sanity Check of the cgascreen - pub fn test(&self){ - // TODO - - } - - pub fn show_coners(&self){ - self.show(0,0,0xda as char,self.attr); - self.show(0,79,0xbf as char,self.attr); - self.show(24,0,0xc0 as char,self.attr); - self.show(24,79,0xd9 as char,self.attr); - } - - pub fn print(&mut self, s:&str){ - for c in s.bytes(){ - self.putchar(c as char); - } - - } - - pub fn setattr(&mut self, attr:u8){ - self.attr = attr; - - } - +impl<'a> CGAScreen<'a> { + pub fn new() -> Self { + Self { + cga_mem: unsafe { + slice::from_raw_parts_mut(CGA_BUFFER_START, 2 * MAX_COLS * MAX_ROWS) + }, + cursor_r: 0, + cursor_c: 0, + attr: 0x0f, + } + } + + #[inline(always)] + fn cal_offset(&self, row: usize, col: usize) -> usize { + col + row * MAX_COLS + } + + pub fn show(&self, row: usize, col: usize, c: char, attr: u8) { + let index = self.cal_offset(row, col); + + unsafe { + *CGA_BUFFER_START.offset(index as isize * 2) = c as u8; + *CGA_BUFFER_START.offset(index as isize * 2 + 1) = attr; + } + } + + pub fn putchar(&mut self, ch: char) { + if ch == '\n' { + self.cursor_r += 1; + self.cursor_c = 0; + self._check_scroll(); + } else { + self.show(self.cursor_r, self.cursor_c, ch, self.attr); + self.cursor_c += 1; + if self.cursor_c >= MAX_COLS { + self.cursor_c = 0; + self.cursor_r += 1; + self._check_scroll(); + } + } + + self.setpos(self.cursor_r, self.cursor_c); + } + + fn _check_scroll(&mut self) { + if self.cursor_r >= MAX_ROWS { + self.scroll(1); + self.cursor_r -= 1; + } + } + + pub fn scroll(&self, lines: u32) { + // TODO + // sanity check + if lines >= MAX_COLS as u32 { + self.clear(); + } + + if lines == 0 { + return; + } + // behold the magic ... (oh fuck me) + let mut i: usize = lines as usize - 1; + loop { + if i == MAX_ROWS { + break; + } + let offset_src = (i * CGA_BUFFER_QWORDS_PER_ROW) as isize; + let offset_dist = offset_src - (lines * CGA_BUFFER_QWORDS_PER_ROW as u32) as isize; + unsafe { + ptr::copy_nonoverlapping( + CGA_BUFFER_START_64.offset(offset_src), + CGA_BUFFER_START_64.offset(offset_dist), + CGA_BUFFER_QWORDS_PER_ROW, + ); + } + i += 1; + } + + i = MAX_ROWS - lines as usize; + loop { + if i == MAX_ROWS { + break; + } + self.clearline(i); + i += 1; + } + // clear the remaining lines: + } + + pub fn clear(&self) { + // remember to swap the endian.. + let b: u8 = self.attr; + let mut base: u64 = (b as u64) << 8; + base += base << 16; + base += base << 32; + + for i in 0..CGA_BUFFER_QWORD_SIZE { + unsafe { *CGA_BUFFER_START_64.offset(i as isize) = base } + } + } + + fn clearline(&self, line: usize) { + let b: u8 = self.attr; + let mut base: u64 = (b as u64) << 8; + base += base << 16; + base += base << 32; + let start_offset_qw: isize = (line as isize) * CGA_BUFFER_QWORDS_PER_ROW as isize; + let end_offset_qw: isize = start_offset_qw + CGA_BUFFER_QWORDS_PER_ROW as isize; + unsafe { + for i in start_offset_qw..end_offset_qw { + *CGA_BUFFER_START_64.offset(i) = base; + } + } + } + + pub fn setpos(&mut self, row: usize, col: usize) { + // io ports for instruction register and data register + let offset = self.cal_offset(row, col); + // set lower byte + outb(IR_PORT, 15 as u8); + delay(); + outb(DR_PORT, offset as u8); + delay(); + // set higher byte + outb(IR_PORT, 14 as u8); + delay(); + outb(DR_PORT, (offset >> 8) as u8); + delay(); + self.cursor_r = row; + self.cursor_c = col; + } + + pub fn getpos_xy(&self, row: &mut u32, col: &mut u32) { + let offset = Self::getpos_offset(); + *row = offset % MAX_COLS as u32; + *col = offset / MAX_COLS as u32; + } + + #[allow(arithmetic_overflow)] + pub fn getpos_offset() -> u32 { + // read higher byte + outb(IR_PORT, 14 as u8); + let mut offset = inb(DR_PORT); + offset = offset << 8; + // read lower byte + outb(IR_PORT, 15 as u8); + offset += inb(DR_PORT); + offset as u32 + } + + // Sanity Check of the cgascreen + pub fn test(&self) { + // TODO + } + + pub fn show_coners(&self) { + self.show(0, 0, 0xda as char, self.attr); + self.show(0, 79, 0xbf as char, self.attr); + self.show(24, 0, 0xc0 as char, self.attr); + self.show(24, 79, 0xd9 as char, self.attr); + } + + pub fn print(&mut self, s: &str) { + for c in s.bytes() { + self.putchar(c as char); + } + } + + pub fn setattr(&mut self, attr: u8) { + self.attr = attr; + } } |
