BigBerger
BigBerger

Reputation: 1803

32 bit C kernel - Weird continous redrawing when rendering to VGA

I am having trouble setting up any kind of functionality to my Kernel that I am writing in C. I have moved on from the steps of writing my boot loader in Assembly, and then compiling and loading my C Kernel into memory and running it.

The problem is, whenever I try to add any sort of backbone such as a VGA graphics class to easily organize methods to render to the VGA memory, my Kernel freaks out and the emulation just starts to continuously redraw itself and I don't see any resemblance to what I am trying to render to the VGA memory.

I have tried setting up a back bone in many different ways, by following countless tutorials online and I am content to use a sort of terminal interface one, if it would start working.

I have been uploading my code to a Bitbucket repository which includes my Makefile, Assembly boot loader, Assembly kernel entry point, and all of my Kernel C source files. I will keep it public and refrain from committing anything into it so you all can reference it until I find the answer I am looking for.

Here is my Bitbucket repository for my "Operating System" in the works.

I am running on Ubuntu 14.04 Desktop 64 Bit. If you need any other information or resources to help you come to an answer, please let me know and I will make an edit.

Thank you in advance for your help and consideration.

EDIT:

Apparently organizing my code to a Bitbucket repository for display is frowned upon, so I will try to give you a detailed jist of what exactly I am doing that might be causing a problem.

My boot loader runs and reads 15 sectors (15 * 512 bytes) of my Kernel into memory, although my Kernel may not have 15 sectors of data this doesn't seem to be causing a problem (Unless it is causing a problem and I don't know about it). I load my Kernel into the address offset of 0x0500 After that, I initialize my stack (Before jumping into my Kernel) to be located at address offset 0x9FBFF.

After that, I jump to my Kernel (Actually, I jump to my Assembly Kernel Entry file which calls the C Kernel's main function).

When my Kernel starts running, it attempts to use some back bone files that I have made to draw text graphics to the VGA memory address 0xB80000. I can do simple things such as this line of code.

unsigned char* vidmem = (unsigned char*) 0xB80000;
*vidmem = 'X';

And it works fine, I can see an X in the top left corner of my emulator along with the other graphics from the boot loader that haven't been overwritten yet.

The problem starts to come in when I try to do more complex things, such as call other back bone source files that attempt to draw text graphics to the screen at different columns and rows, store the last column and row printed to, handle scrolling, print entire strings and account for scrolling and new lines, etc.

I am completely stuck as to why this is happening and I have a moderate to beginner understanding of how this memory and assembly instruction interacts with the computer in a way that might be causing a problem.

Again, any help on this issue would be much appreciated.

Upvotes: 0

Views: 360

Answers (1)

user149341
user149341

Reputation:

The most obvious issue I see is that your logic for addressing VGA memory is wonky.

You declare a pointer to video memory as a unsigned char *:

unsigned char* terminal_buffer;
...
static unsigned char* const VGA_MEMORY = (unsigned char*) 0xB8000;
...
terminal_buffer = VGA_MEMORY;

However, you are then trying to write full VGA character values into each position, e.g. in terminal_init():

  const unsigned int index = r * VGA_WIDTH + c;
  terminal_buffer[index] = make_vga_entry(' ', terminal_color);

You aren't multiplying the index by 2, so this ends up writing the lower 8 bits of a VGA entry (in this case, 0x20) into each memory location in the VGA buffer. This causes strange results when you start writing text to the terminal, as every other byte ends up interpreted as an attribute pair instead of a character!

Thankfully, the solution is simple: declare terminal_buffer as an array of 16-bit elements:

uint16_t *terminal_buffer = VGA_MEMORY;
^^^^^^^^

(P.S: I recommend taking a look at the OSDev article on VGA hardware.)

Upvotes: 2

Related Questions