YeXo - een kernel programmeren

25 maart 2006

De print functie voor de kernel

Nu de voorbereidingen voor de print functie zijn gebeurd (zie "Voorbereiding voor en print functie") kunnen we echt beginnen. De functie void kprintf(char *str) is eigenlijk heel eenvoudig. Het enige wat die hoeft te doen is de string doorlopen en elk teken doorgeven aan de functie putch die het eigenlijke werk doet. Let erop dat deze kprintf nog geen extra argumenten accepteert, dingen zoals kprintf("een getal: %d",getalVar); zijn dus niet mogelijk.


//Eerste een paar globale variabelen, het doel lijkt me duidelijk
char attribute;
unsigned short *videoMem;
unsigned int cursorX,cursorY;
unsigned int lines, columns;

/*Het attribuut bevat de voor- en achtergrondkleur van de tekst.
Dit is opgebouwd met behulp van de definities in scrn.h
Het is een heel simpele functie geimplementeerd als definitie waardoor
het een soort inline functie wordt.*/
#define setAttribute(a); attribute=a;

/* putch(char) print een teken op het scherm op de positie die door cursorX en cursorY aangegeven wordt.
Op dit moment worden nog maar een paar speciale tekens ondersteunt, namelijk: 0x08 (backspace), 0x09 (tab)
en '\n' (nieuwe regel).
*/
void putch(char c){
switch(c){
case 0x08: //backspace
if( cursorX==0 && cursorY > 0){
*(videoMem+cursorY*columns-1) = ' '|(attribute<<8);
cursorX = columns-1;
cursorY--;
}
if( cursorX > 0 ){
*(videoMem+cursorY*columns+cursorX-1) = ' '|(attribute<<8);
cursorX--;
}
break;
case 0x09: // tab: Vermeerder cursorX tot het volgende punt dat deelbaar is door 8
cursorX = (cursorX + 8) & ~(8-1);
if( cursorX == columns ){
cursorX = 0;
cursorY++;
}
break;
case '\n': // We doen alsof hier \n\r staat, net zoals dos en het bios
cursorX = 0;
cursorY++;
break;
}
if( c >= ' ' ){ // We kunnen deze char printen op het scherm.
*(videoMem+cursorY*columns+cursorX) = c|(attribute<<8);
cursorX++;
if( cursorX >= columns ){
cursorX = 0;
cursorY++;
}
}
// Als cursorY naar de regel wijst die net niet meer op het scherm pas, schuif dan het hele scherm
// een regel omhoog.
if( cursorY == lines ){
scroll();
}
// Zorg dat de cursor (het knipperende streepje) op de goede positie komt
setHardwareCursor();
}

// setHardwareCursor zorgt ervoor dat de cursor (het knipperende streepje) op de goede positie komt
void setHardwareCursor(){
unsigned short cursorPosition = (cursorY*columns) + cursorX;
outportb(0x3D4, 14);
outportb(0x3D5, cursorPosition >> 8);
outportb(0x3D4, 15);
outportb(0x3D5, cursorPosition & 0xFF);
}

/*De functie scroll schuift het hele scherm omhoog.*/
void scroll(){
memcpy(videoMem,videoMem+columns,lines*columns*2);
memsetw(videoMem+(lines-1)*columns,' '|(attribute<<8),columns);
cursorY--;
}

/*Print eens string.*/
void kprintf(char *text){
char *tp = text;
while( *tp != '\0' ){
//TODO: check for %
putch(*tp);
*tp++;
}
}

/*Leeg het hele scherm door het scherm vol te printen met spaties.*/
void clearScreen(){
memsetw(videoMem,' '|(attribute<<8),lines*columns);
cursorX = 0;
cursorY = 0;
}


void videoInit(){
int i = 0;
videoMem = (unsigned short *)0xC00B8000;
setAttribute(KLEUR(ZWART,LICHTGRIJS));
clearScreen();
cursorY = 0;
cursorX = 0;
lines = 25; //standaard schermmodus: 25x80
columns = 80;
}