/* File: Console.C Author: R. Bettati Department of Computer Science Texas A&M University Date : 09/02/2009 */ /*--------------------------------------------------------------------------*/ /* DEFINES */ /*--------------------------------------------------------------------------*/ #define CONSOLE_START_ADDRESS (unsigned short *)0xB8000 /*--------------------------------------------------------------------------*/ /* INCLUDES */ /*--------------------------------------------------------------------------*/ #include "console.H" #include "utils.H" #include "machine.H" /*--------------------------------------------------------------------------*/ /* DATA STRUCTURES */ /*--------------------------------------------------------------------------*/ /* -- (none) -- */ /*--------------------------------------------------------------------------*/ /* CONSTANTS */ /*--------------------------------------------------------------------------*/ /* -- (none) -- */ /*--------------------------------------------------------------------------*/ /* FORWARDS */ /*--------------------------------------------------------------------------*/ /* -- (none) -- */ /*--------------------------------------------------------------------------*/ /* METHODS FOR CLASS C o n s o l e */ /*--------------------------------------------------------------------------*/ /* -- GLOBAL VARIABLES -- */ int Console::attrib; /* background and foreground color */ int Console::csr_x; /* position of cursor */ int Console::csr_y; unsigned short * Console::textmemptr; /* text pointer */ /* -- CONSTRUCTOR -- */ void Console::init(unsigned char _fore_color, unsigned char _back_color) { set_TextColor(_fore_color, _back_color); csr_x = 0; csr_y = 0; textmemptr = CONSOLE_START_ADDRESS; cls(); } void Console::scroll() { /* A blank is defined as a space... we need to give it * backcolor too */ unsigned blank = 0x20 | (attrib << 8); /* Row 25 is the end, this means we need to scroll up */ if(csr_y >= 25) { /* Move the current text chunk that makes up the screen * back in the buffer by a line */ unsigned temp = csr_y - 25 + 1; memcpy ((char*)textmemptr, (char*)(textmemptr + temp * 80), (25 - temp) * 80 * 2); /* Finally, we set the chunk of memory that occupies * the last line of text to our 'blank' character */ memsetw (textmemptr + (25 - temp) * 80, blank, 80); csr_y = 25 - 1; } } void Console::move_cursor() { /* The equation for finding the index in a linear * chunk of memory can be represented by: * Index = [(y * width) + x] */ unsigned temp = csr_y * 80 + csr_x; /* This sends a command to indicies 14 and 15 in the * Console Control Register of the VGA controller. These * are the high and low bytes of the index that show * where the hardware cursor is to be 'blinking'. To * learn more, you should look up some VGA specific * programming documents. A great start to graphics: * http://www.brackeen.com/home/vga */ Machine::outportb(0x3D4, (char)14); //outportb(0x3D5, temp >> 8); Machine::outportb(0x3D4, 15); //outportb(0x3D5, (char)temp); } /* Clear the screen */ void Console::cls() { /* Again, we need the 'short' that will be used to * represent a space with color */ unsigned blank = 0x20 | (attrib << 8); /* Sets the entire screen to spaces in our current * color */ for(int i = 0; i < 25; i++) memsetw (textmemptr + i * 80, blank, 80); /* Update out virtual cursor, and then move the * hardware cursor */ csr_x = 0; csr_y = 0; move_cursor(); } /* Puts a single character on the screen */ void Console::putch(const char _c){ /* Handle a backspace, by moving the cursor back one space */ if(_c == 0x08) { if(csr_x != 0) csr_x--; } /* Handles a tab by incrementing the cursor's x, but only * to a point that will make it divisible by 8 */ else if(_c == 0x09) { csr_x = (csr_x + 8) & ~(8 - 1); } /* Handles a 'Carriage Return', which simply brings the * cursor back to the margin */ else if(_c == '\r') { csr_x = 0; } /* We handle our newlines the way DOS and the BIOS do: we * treat it as if a 'CR' was also there, so we bring the * cursor to the margin and we increment the 'y' value */ else if(_c == '\n') { csr_x = 0; csr_y++; } /* Any character greater than and including a space, is a * printable character. The equation for finding the index * in a linear chunk of memory can be represented by: * Index = [(y * width) + x] */ else if(_c >= ' ') { unsigned short * where = textmemptr + (csr_y * 80 + csr_x); *where = _c | (attrib << 8); /* Character AND attributes: color */ csr_x++; } /* If the cursor has reached the edge of the screen's width, we * insert a new line in there */ if(csr_x >= 80) { csr_x = 0; csr_y++; } /* Scroll the screen if needed, and finally move the cursor */ scroll(); move_cursor(); } /* Uses the above routine to output a string... */ void Console::puts(const char * _s) { for (int i = 0; i < strlen(_s); i++) { putch(_s[i]); } } void Console::puti(const int _n) { char foostr[15]; int2str(_n, foostr); puts(foostr); } void Console::putui(const unsigned int _n) { char foostr[15]; uint2str(_n, foostr); putch('<'); puts(foostr); putch('>'); } /* -- COLOR CONTROL -- */ void Console::set_TextColor(const unsigned char _forecolor, const unsigned char _backcolor) { /* Top 4 bytes are the background, bottom 4 bytes * are the foreground color */ attrib = (_backcolor << 4) | (_forecolor & 0x0F); }