aboutsummaryrefslogtreecommitdiff
path: root/src/machine/cgascr.rs
diff options
context:
space:
mode:
authorTianhao Wang <wth@riseup.net>2024-01-30 02:33:26 +0100
committerTianhao Wang <wth@riseup.net>2024-01-30 02:33:26 +0100
commit5232a899ca7537a4493a7fbd1bd8e03287ff1e26 (patch)
tree87ded44101daa8832ad264996bde74160ab2db93 /src/machine/cgascr.rs
parent553657a0b527ae8ce09ac628da6122fbdd57157b (diff)
formatting code, use tab identation -- before it's too late
Diffstat (limited to 'src/machine/cgascr.rs')
-rw-r--r--src/machine/cgascr.rs378
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;
+ }
}