219 lines
4.7 KiB
C
219 lines
4.7 KiB
C
|
int x = 0;
|
||
|
int y = 0;
|
||
|
int lc = 0;
|
||
|
int VGA_WIDTH = 24;
|
||
|
char *line = 0x00;
|
||
|
|
||
|
void clear() {
|
||
|
char *mem = (char*)0xb8000;
|
||
|
int i = 0;
|
||
|
while (i < 4096) {
|
||
|
mem[i++] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* We will use this later on for reading from the I/O ports to get data
|
||
|
* from devices such as the keyboard. We are using what is called
|
||
|
* 'inline assembly' in these routines to actually do the work */
|
||
|
unsigned char inportb (unsigned short _port)
|
||
|
{
|
||
|
unsigned char rv;
|
||
|
__asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port));
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
/* We will use this to write to I/O ports to send bytes to devices. This
|
||
|
* will be used in the next tutorial for changing the textmode cursor
|
||
|
* position. Again, we use some inline assembly for the stuff that simply
|
||
|
* cannot be done in C */
|
||
|
void outportb (unsigned short _port, unsigned char _data)
|
||
|
{
|
||
|
__asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
|
||
|
}
|
||
|
|
||
|
// This is the x86's VGA textmode buffer. To display text, we write data to this memory location
|
||
|
volatile uint16_t* vga_buffer = (uint16_t*)0xB8000;
|
||
|
// By default, the VGA textmode buffer has a size of 80x25 characters
|
||
|
const int VGA_COLS = 80;
|
||
|
const int VGA_ROWS = 25;
|
||
|
|
||
|
// We start displaying text in the top-left of the screen (column = 0, row = 0)
|
||
|
int term_col = 0;
|
||
|
int term_row = 0;
|
||
|
uint8_t term_color = 0x0F; // Black background, White foreground
|
||
|
|
||
|
// This function initiates the terminal by clearing it
|
||
|
void term_init()
|
||
|
{
|
||
|
// Clear the textmode buffer
|
||
|
for (int col = 0; col < VGA_COLS; col ++)
|
||
|
{
|
||
|
for (int row = 0; row < VGA_ROWS; row ++)
|
||
|
{
|
||
|
// The VGA textmode buffer has size (VGA_COLS * VGA_ROWS).
|
||
|
// Given this, we find an index into the buffer for our character
|
||
|
const size_t index = (VGA_COLS * row) + col;
|
||
|
// Entries in the VGA buffer take the binary form BBBBFFFFCCCCCCCC, where:
|
||
|
// - B is the background color
|
||
|
// - F is the foreground color
|
||
|
// - C is the ASCII character
|
||
|
vga_buffer[index] = ((uint16_t)term_color << 8) | ' '; // Set the character to blank (a space character)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// This function places a single character onto the screen
|
||
|
void printc(char c)
|
||
|
{
|
||
|
// Remember - we don't want to display ALL characters!
|
||
|
switch (c)
|
||
|
{
|
||
|
case '\n': // Newline characters should return the column to 0, and increment the row
|
||
|
{
|
||
|
term_col = 0;
|
||
|
term_row ++;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
default: // Normal characters just get displayed and then increment the column
|
||
|
{
|
||
|
const size_t index = (VGA_COLS * term_row) + term_col; // Like before, calculate the buffer index
|
||
|
vga_buffer[index] = ((uint16_t)term_color << 8) | c;
|
||
|
term_col ++;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// What happens if we get past the last column? We need to reset the column to 0, and increment the row to get to a new line
|
||
|
if (term_col >= VGA_COLS)
|
||
|
{
|
||
|
term_col = 0;
|
||
|
term_row ++;
|
||
|
}
|
||
|
|
||
|
// What happens if we get past the last row? We need to reset both column and row to 0 in order to loop back to the top of the screen
|
||
|
if (term_row >= VGA_ROWS)
|
||
|
{
|
||
|
term_col = 0;
|
||
|
term_row = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// This function prints an entire string onto the screen
|
||
|
void print(const char* str)
|
||
|
{
|
||
|
if (str == 0x07) {
|
||
|
beep();
|
||
|
} else {
|
||
|
for (size_t i = 0; str[i] != '\0'; i ++) // Keep placing characters until we hit the null-terminating character ('\0')
|
||
|
printc(str[i]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
char int2str(int num) {
|
||
|
//convert int to string without common libraries
|
||
|
char str[10];
|
||
|
int i = 0;
|
||
|
while (num > 0) {
|
||
|
str[i] = num % 10 + '0';
|
||
|
num /= 10;
|
||
|
i++;
|
||
|
}
|
||
|
str[i] = '\0';
|
||
|
char *p = str;
|
||
|
while (*p != '\0') {
|
||
|
p++;
|
||
|
}
|
||
|
p--;
|
||
|
char c = *p;
|
||
|
*p = '\0';
|
||
|
return c;
|
||
|
}
|
||
|
|
||
|
|
||
|
void printint(int num)
|
||
|
{
|
||
|
char str = int2str(num); //Make number a string.
|
||
|
print(str); //print it.
|
||
|
}
|
||
|
|
||
|
//DO NOT USE
|
||
|
void vgaprint(char *text, int color) {
|
||
|
lc = color;
|
||
|
char *mem = (char*)0xb8000;
|
||
|
if (y == 23) {
|
||
|
clear(lc);
|
||
|
y = 0;
|
||
|
}
|
||
|
while (*text != 0) {
|
||
|
if (x > 78) {
|
||
|
int i = 0;
|
||
|
while (i < x){
|
||
|
mem[i++] = 0;
|
||
|
}
|
||
|
x = 0;
|
||
|
y = y + 1;
|
||
|
}
|
||
|
x = x + 1;
|
||
|
if (*text == "\n") {
|
||
|
int i = 0;
|
||
|
while (i < x) {
|
||
|
mem[i++] = 0;
|
||
|
}
|
||
|
x = 0;
|
||
|
y = y + 1;
|
||
|
} else {
|
||
|
*mem++ = *text++;
|
||
|
*mem++ = color;
|
||
|
}
|
||
|
int i = 0;
|
||
|
while (i < x) {
|
||
|
mem[i++] = 0;
|
||
|
}
|
||
|
x = 0;
|
||
|
y = y + 1;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
int lastVGATextColor() {
|
||
|
return lc;
|
||
|
}
|
||
|
|
||
|
void setTermColor(uint8_t color) {
|
||
|
term_color = color;
|
||
|
}
|
||
|
|
||
|
uint8_t termColor() {
|
||
|
return term_color;
|
||
|
}
|
||
|
|
||
|
//create malloc function without standard libs
|
||
|
char malloc(int size) {
|
||
|
char *mem = (char*)0xb8000;
|
||
|
int i = 0;
|
||
|
while (i < size) {
|
||
|
mem[i++] = 0;
|
||
|
}
|
||
|
return (char)mem;
|
||
|
}
|
||
|
|
||
|
//create free function without standard libs
|
||
|
void free(char *mem) {
|
||
|
int i = 0;
|
||
|
while (mem[i] != 0) {
|
||
|
mem[i++] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void basickeys() {
|
||
|
register char *ptr asm("ax");; //pointer var
|
||
|
//do something
|
||
|
while(*ptr != '\0') {
|
||
|
*line = *ptr;
|
||
|
print(ptr); //try to print what's in memory
|
||
|
ptr++; //add 1 to ptr
|
||
|
}
|
||
|
}
|