# Help with print function

This topic is 4667 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Ok, I have this function that prints text to the video buffer (0xB8000). However, I can't seem to figure out how to stack data on top of each other so that I can use the command as many times as I'd like without clearing the screen first :(
// in: char *text [The text to write to the screen.]
// out: Nothing.
void k_print( char *text ) {

static unsigned int line_number = 0;
static unsigned int column_number = 0;
char *video_memory = (char *) VIDEO_MEMORY;

while( *text != 0 ) {
if( *text == '\n' ) {
text++;
column_number = 0;
line_number++;
video_memory = (char *) ( VIDEO_MEMORY + ( line_number * SCREEN_WIDTH * 2 ) + ( column_number * 2 ) );
} else {
*video_memory = *text;
text++;
column_number++;
video_memory++;
*video_memory = WHITE_TEXT;
video_memory++;
}
}
}

Basically, what I want is I want to add a new line beneath a textstring when I use the command, so that when I use it again, the new text gets printed beneath the old one. Can anyone please help?

##### Share on other sites
I would say that you need to append the new text to the old text in the buffer and then send the buffer to print again. In other words, you have to overwrite the earlier screen text, but since it's saved in the buffer, it gets written again just before the new text is written.

##### Share on other sites
[source lang = "c"]void k_print( char *text ) {static unsigned int line_number = 0;static unsigned int column_number = 0;char *video_memory = (char *) VIDEO_MEMORY;	while( *text != 0 ) {		if( *text == '\n' ) {			text++;			column_number = 0;			line_number++;			video_memory = (char *) ( VIDEO_MEMORY + ( line_number * SCREEN_WIDTH * 2 ) + ( column_number * 2 ) );		} else {			VIDEO_MEMORY = (char*) *video_memory;			*video_memory = *text;			text++;			column_number++;			video_memory++;			*video_memory = WHITE_TEXT;			video_memory++;		}	}}

Like so? I have to reboot my machine to run this code, so I'd really like to know :) Thanks btw :)

##### Share on other sites
Nevermind. Tried this:

[source lang = "c"]// in: char *text [The text to write to the screen.]// out: Nothing.void k_print( char *text ) {static unsigned int line_number = 0;static unsigned int column_number = 0;char *video_memory = (char *) VIDEO_MEMORY;	while( *text != 0 ) {		if( *text == '\n' ) {			text++;			column_number = 0;			line_number++;			video_memory = (char *) ( VIDEO_MEMORY + ( line_number * SCREEN_WIDTH * 2 ) + ( column_number * 2 ) );		} else {			VIDEO_MEMORY = (char*) *video_memory;			*video_memory = *text;			text++;			column_number++;			video_memory++;			*video_memory = WHITE_TEXT;			video_memory++;		}	}}

But it still doesn't work :(

##### Share on other sites
Wow, a question about text mode. Well, you have two options - when you want to scroll a line down you either have to copy all of the lines on the screen up one, or you can move the video base address down a line. The second one's probably considerably more work because you only have a certain number of video pages so eventually you have to have a way to get back to the start and modern computers are far too fast to be slowed down by moving 4kb or so of data. The second trick used to be used for VGA side scrolling games when computers weren't fast enough to redraw the entire screen, so you moved the video base address by one row/column and only had to redraw one row/column and the characters.

There is actually a third option if you're in real mode or can run vm86 mode (that's what it's called on Linux - I've forgotten the official name - it's emulated 16 bit mode) - you can call the BIOS and get it to do your text output for you. That might well be slow though.

What are you writing anyway, something for DOS or a toy OS?

##### Share on other sites
I'm writing a toy os :)

I'm not sure how to do what you said, but I've figured that if I could make an if statement to find the "\0" character, I could add a new line just like with the "\n" character. I tried writing "if (*text == '\0')", but that didn't work :( Any ideas?

##### Share on other sites
Off the top of my head:

void k_print(const char *text){  static unsigned line_no = 0, col_no = 0;  static char *video_memory_ptr = VIDEO_MEMORY;  int i;  for (i = 0; text != '\0'; ++i) {    if (text == '\n') {      video_memory_ptr += (SCREEN_WIDTH - col_no)*2;      line_no++;      col_no = 0;    } else {      video_memory_ptr[0] = text;      video_memory_ptr[1] = WHITE_TEXT;      video_memory_ptr += 2;      col_no++;      if (col_no == SCREEN_WIDTH) {        col_no = 0;        line_no++;      }    }    if (line_no == SCREEN_HEIGHT) {      memmove(VIDEO_MEMORY, VIDEO_MEMORY + (SCREEN_HEIGHT*2),              SCREEN_WIDTH*(SCREEN_HEIGHT-1)*2);      line_no--;      video_memory_ptr = VIDEO_MEMORY + SCREEN_WIDTH*(SCREEN_HEIGHT-1)*2;    }  }}

The pointer arithmatic probably won't work without some adjustment but otherwise I think that's correct. I was messing about with this myself recently using GRUB for a bootloader to escape the really nasty bootstrap stuff (and QEMU for testing). I remember sorting out memory layout being pretty nasty.

##### Share on other sites
Thanks alot :) This seems like it should work :)

Oh and btw do you think that you've seen "nasty" bootloading code? Well, then you should take a look at this . XD First time I saw it, I laughed my ass off, and I still do frequently when reading through the code. :D

##### Share on other sites
Well, yeah. Since it's impossible to fit anything resembling a modern OS into one sector all the bootloaders I know of employ some kind of blindly loading more from a set sector on the disk with no regard to the file system. It's an ugly system and I for one will not be sorry to see the x86 architecture die (it's got more baggage than you could fit on a jumbo jet), and I think it's only got a few years left.

• 36
• 12
• 10
• 10
• 9
• ### Forum Statistics

• Total Topics
631359
• Total Posts
2999545
×