#include "headers/screen.h" #include "headers/common.h" #include #include #include #include volatile uint16_t* vga_buffer = (uint16_t*) 0xB8000; uint8_t current_color; void set_current_color(enum vga_colors color) { current_color = color; } /* Entries of the VGA Buffer take the form BBBBFFFFCCCCCCCC * BBBB = Background Color * FFFF = Foreground Color * CCCCCCCC = Character code */ //Get the 8 color bits from the above enumerator static inline uint8_t vga_entry_color(enum vga_colors fg, enum vga_colors bg) { return fg | bg << 4; //Shift the background to the left, then OR with fg to add them together. } //Apply the color bits to make a printed character static inline uint16_t vga_entry(unsigned char uc, uint8_t color) { return (uint16_t) uc | (uint16_t) color << 8; //Same here - shift the color to the left, then OR with the character to append. } int i; // offset to framebuffer uint8_t row; // current row between 1-25 uint8_t col; // current col between 1-80 short calc = 0; // random var for various calcs must be initialized or cleaned after func calls // ^ attempt at packing may need calc to be an int however... // simple printf style function(needs testing with errenous data) // add tab support and %p specifier // also add support for printing the register state void kprintf(const char *string, ...) // look up how this is properly done { int j = 0; int num = 0; // number to hold our stuff :) char string2[11] = {0}; // string for printing ints :) /* list stuff :) */ va_list ap; // find how many things we are parsing va_start(ap, string); while(string[j] != 0) { if(string[j] == '%') // if a format specifier { if(string[j+1] == 'd') // print a decimal { num = va_arg(ap, int); itoa(num, string2); // account for negatives... print(string2); zerostring(string2); j += 2; } else if(string[j+1] == 'x') // print as hex { num = va_arg(ap, int); tohex(num, string2); print(string2); zerostring(string2); j += 2; } else if(string[j+1] == 's') // print a string { print(va_arg(ap, char*)); j += 2; } else if(string[j+1] == 'c') // print a char { char c = va_arg(ap,int); printchar(c); j += 2; } else // unknown format string { //serial_printf("[ERROR]attempted to parse unknown format string\n"); return; // prevent undefined behaviour } } else // is a regular character { printchar(string[j]); j++; } } va_end(ap); // clean up variable length list } void printchar(char character) { switch (character) { case '\n': { //For newline, move to next row and focus on the first character. col = 0; row++; break; } default: { // All other characters simply get written to the buffer. const size_t i = (row * 80) + col; //i = index vga_buffer[i] = ((uint16_t) current_color << 8) | character; col++; } } if(col > 79) // keep track of row and column for scrolling and newlines { col = 0; row++; } if(row > 25) { handle_scrolling(); } } void print(const char *string) { unsigned int len = strlen(string); // may be better to pass len as an arg unsigned int j = 0; while(j < len) { printchar(string[j]); j++; } } // Fill screen with spaces, effectively clearing the screen. void clear() { unsigned char *vga_memory = (unsigned char *) vga_buffer; for(int j = 0; j < 4001; j = j + 2) // 80 * 25 * 2 =4000(end of framebuffer) { vga_memory[j] = 0x20; // assign a space to current pos vga_memory[j + 1] = 0x00; // clear the attribute } row = 0; col = 0; i = 0; } // note learn how inline asm works properly void set_cursor(int row, int col) { unsigned short position=(row*80) + col; outb(0x3D4, 0X0F); outb(0x3D5, (unsigned char)(position&0xff)); outb(0x3D4, 0x0E); outb(0x3D5, (unsigned char)((position>>8)&0xFF)); } // scroll the screen when it gets to the last line void handle_scrolling(){ int x = 160; // start of 2nd line unsigned char *vga_memory = (unsigned char *) vga_buffer; while(x < 4001) { // max each char is 2 apart vga_memory[x-160] = vga_memory[x]; //Move every character up a line vga_memory[x-159] = vga_memory[x+1]; //Move the character attributes too x += 2; //Move to next character } x = 3840; //Start of the last line for(i = 1920; i < 2001; i++) { // Memory locations for the characters in the last line vga_memory[x] = 0; //Set current character to 0 (null) x += 2; // Move to next character } i = 3840; // set i to start of last line row = 24; // set row to 25 so when a \n is printed the screen will scroll } void itoa(int num, char *string2) {// convert from int to ascii eqiv int j = 0; // counter calc = 0; //Result of a calculation bool flag_negative = false; if(num == 0) { // catch 0 string2[0] = '0'; string2[1] = '\0'; // null term return; } if(num < 0) { flag_negative = true; num = -num; //invert it so it calcs } while(num != 0) {// while we can still divide calc = num % 10; // get raminder in calc num = num / 10; // div by 10 calc += 48; // convert to ascii //printchar(calc); string2[j] = calc; j++; // inc amount of chars to print } if(flag_negative) { string2[j] = '-'; j += 1; } for(int i=0; i> 4; // shr val four so that it loses char if(temp >= 10) { temp += 7; // if higher than 10 convert to letter } temp += 48; //convert to ascii string[j] = temp; } } // Fill the string pointer with 0 (null) characters void zerostring(char *string) { unsigned int len = strlen(string); for(unsigned int i = 0; i <= len; i++) { string[i] = '\0'; } } unsigned int strlen(const char *string) { unsigned int len = 0; while(string[len]) { len++; } return len; } // print out registers for debugging /*void writeregs(void) { unsigned int Register = 0; }*/