Page 1 of 1

no vga output

Posted: Mon Sep 26, 2005 3:20 pm
by yukito
hi!

I tried to write a kernel to test some of the stuff I read about, but it doesn't seem to do anything :( Just a black screen and then nothing :(

I just call

Code: Select all

   cls();
   puts("foobar!");
in main() :(

Here's the VGA code:

Code: Select all

#include "system.h"

unsigned short *videomem = (unsigned short *)0xB8000;;
unsigned int cursor_x = 0, cursor_y = 0;
unsigned char color = 0x0F, clearcolor = 0x0F;

void update_cursor()
{
    unsigned temp;

    /* The equation for finding the index in a linear
    *  chunk of memory can be represented by:
    *  Index = [(y * width) + x] */
    temp = cursor_y * 80 + cursor_x;

    /* This sends a command to indicies 14 and 15 in the
    *  CRT 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 */
    outportb(0x3D4, 14);
    outportb(0x3D5, temp >> 8);
    outportb(0x3D4, 15);
    outportb(0x3D5, temp);
}

// Clears the screen
void cls() {
   unsigned short blank = 0x20 | (clearcolor << 8);   // A blank character
   int i;
   for(i = 0; i < 25; i++)            // Loop through all rows
      memsetw(videomem + i*80, blank, 80);   // Clear one row
   cursor_x = 0;   // Move the cursor
   cursor_y = 0;
   update_cursor();
}

// These functions set your output color. Top four bytes are background, last for are foreground (text) color
void setClearColor(int fg, int bg) {
   clearcolor = (bg << 4) | (fg & 0x0F);
}

void setColor(int fg, int bg) {
   color = (bg << 4) | (fg & 0x0F);
}

void scroll(){
   if(cursor_y > 24) {
      unsigned short blank = 0x20 | (clearcolor << 8);   // A blank character   
      memcpy(videomem, videomem + 80, 80 * 24);
      memsetw(videomem + 24*80, blank, 80);
      cursor_y = 24;
      update_cursor();
   }
}

void putch(unsigned char c) {
   unsigned short *where = videomem + (80 * cursor_y + cursor_x);
   if(c == '\b') {   // Backspace character, clear the previous character if we're not at the beginning of the line
      if(cursor_x != 0) {
         cursor_x--;
         *where = 0x20 | (clearcolor << 8);
      }
   } else if (c == '\t') {   // A tab character, move the cursor to a point where cursor_x is divisible by 8
      cursor_x = (cursor_x + 8) & ~(8 - 1);
      if(cursor_x >= 79) { // end of line
         cursor_x = 7;
         cursor_y++;
         scroll();
      }
   } else if (c == '\n') {   // Newline, go to the beginning of the next line.
      cursor_x = 0;
      cursor_y++;
      scroll();
   } else if (c == '\r') {
      cursor_x = 0;
   } else if (c >= ' ') {
      *where = c | (color << 8);
      
      if(cursor_x >= 79) {
         cursor_x = 0;
         cursor_y++;
         scroll();
      } else {
         cursor_x++;
      }
   }
   update_cursor();
}

void puts(unsigned char *text) {
   int i;
   for(i = 0; i < strlen(text); i++)
      putch(text[i]);
}

void initvga() {
   videomem = (unsigned short *)0xB8000;
   cls();
}

Re:no vga output

Posted: Mon Sep 26, 2005 5:49 pm
by GLneo
what about your boot loader??? mabey it is broke???

Re:no vga output

Posted: Mon Sep 26, 2005 5:55 pm
by yukito
I use grub as a bootloader, I rewrote my strlen function and now it works. Probably something really stupid.

Re:no vga output

Posted: Tue Sep 27, 2005 7:56 am
by bluecode
hi,

if you're using paging you should set the page of the video ram as write-through (bit 3).

Re:no vga output

Posted: Sat Oct 01, 2005 4:01 am
by Pype.Clicker
maybe the FAQ do help ...

But if it works be rewriting strlen, then there was certainly something odd with that function that made it return "0" when it shouldn't have did so.

Re:no vga output

Posted: Wed Oct 05, 2005 6:34 pm
by Lazy Neuromancer
First of all, in function cls:

Code: Select all

   for(i = 0; i < 25; i++)            // Loop through all rows
      memsetw(videomem + i*80, blank, 80);   // Clear one row
should be:

Code: Select all

   for(i = 0; i < 25; i++)            // Loop through all rows
      memsetw(videomem + i*160, blank, 80);   // Clear one row
because each line is 160 bytes long (a byte for the character + a byte for the color 80 times).

And in function putch:

Code: Select all

   unsigned short *where = videomem + (80 * cursor_y + cursor_x);
should be:

Code: Select all

   unsigned short *where = videomem + (160 * cursor_y + cursor_x);
for the reason stated above.

I don't think this will change much, but they are bugs.
Correct me if I'm wrong, it's 2:30 AM and I'm tired ::)

Re:no vga output

Posted: Thu Oct 06, 2005 3:45 am
by yukito
my memsetw copies 16bit values, and I'm using one value for color & character (2byte short int), so it should copy the data correctly. Same goes for the putch function: C knows it's working with 16bit values and automatically adds 2 bytes instead of just 1 per unit added to a pointer in the calculation of *where :)

Re:no vga output

Posted: Thu Oct 06, 2005 9:20 am
by Lazy Neuromancer
yea, but the address is calculated as a byte address, not a word address, line 2 of the framebuffer @ 0xB8000 starts at 0xB8000 + 160, not 0xB8000 + 80 ;)

Re:no vga output

Posted: Thu Oct 06, 2005 10:11 am
by AR
Lazy Neuromancer wrote:yea, but the address is calculated as a byte address, not a word address, line 2 of the framebuffer @ 0xB8000 starts at 0xB8000 + 160, not 0xB8000 + 80 ;)
No, it isn't. Here's a simple test:

Code: Select all

#include <stdio.h>

int main()
{
   int intArr[] = { 1, 2, 3, 4 }; /* Each number is 4bytes */
   int *ptr = intArr;
   ++ptr;
   printf("%d\n", *ptr);
   ptr += 1;
   printf("%d\n", *ptr);
   ptr = ptr + 1;
   printf("%d\n", *ptr);

   return 0;
}
The output is:
2
3
4

Re:no vga output

Posted: Thu Oct 06, 2005 10:39 am
by Lazy Neuromancer
The code you have shown works because the compiler add 4 to the address when you do a increment, it does not add 1, just try to disassemble the object file.
Pype, Brendan, someone please tell me if I'm wrong ;D

Re:no vga output

Posted: Thu Oct 06, 2005 10:42 am
by Lazy Neuromancer
I know my english is bad.

Code: Select all

memsetw(videomem + i*80, blank, 80);
What I want to say is that the 80 bytes count is OK, because 80 * 2 bytes/word = 160. But the address has to be calculated as a byte address.

Line 1 starts at 0xb8000, line 2 at 0xb8000 + 160, you can't say I am wrong ;)

Re:no vga output

Posted: Thu Oct 06, 2005 10:46 am
by Neuromancer
:-\ :-\ damn, 80 word count :-\ :-\
next time i'll log in before posting, so I can change my mistakes :-[

Re:no vga output

Posted: Thu Oct 06, 2005 10:58 am
by AR
Yes the second line does start at 0xB8000 + 160, I am trying to point out that your pointer arithmetic is wrong, "videomem" is a "short pointer", a short is 2 bytes, therefore all integer addition and subtraction operations on that pointer will all be multipled by 2.

The code:

Code: Select all

memsetw(videomem + i*80, blank, 80);
is interpreted by the compiler as:

Code: Select all

memsetw(
(unsigned short*) ( (uintptr_t)videomem + ( i * 80 * sizeof(unsigned short) ) ),
blank, 80);

Re:no vga output

Posted: Thu Oct 06, 2005 11:01 am
by Neuromancer
:o really? everyday I learn something new, though I started coding in C 5 years ago ::)

Thanks man!