This repository has been archived on 2020-02-06. You can view files and clone it, but cannot push or open issues or pull requests.
Legacy-Sync/screen.c
Jenny Curle f6ba6aa117 Legacy OS files. Have an i686-elf-gcc & -ld in your PATH,
and the Makefile will take care of the rest.
2019-04-01 01:38:50 +01:00

278 lines
6.1 KiB
C

#include "headers/screen.h"
#include "headers/common.h"
#include <stdbool.h>
#include <stdarg.h>
#include <stdint.h>
#include <stddef.h>
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<j/2; i++) {
calc = string2[i];
string2[i] = string2[j-i-1];
string2[j-i-1] = calc;
}
}
// convert a number to a hex
void tohex(int val, char *string) {
zerostring(string);
uint8_t j = 8;
uint8_t temp = 0;
while(j != 0) {
j--; // decerment j
temp = val & 0xf; // get just nibble into temp
val = val >> 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;
}*/