Skip to main content
gamedev.net
🔒 Locked

Help with print function

Started by Afr0m@n 7 replies 900+ views
Original Post
Afr0m@n
Afr0m@n
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?
_______________________Afr0Games
LessBread
LessBread
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.
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
Afr0m@n
Afr0m@n
[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 :)
_______________________Afr0Games
Afr0m@n
Afr0m@n
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 :(
_______________________Afr0Games
ZQJ
ZQJ
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?
Afr0m@n
Afr0m@n
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?
_______________________Afr0Games
ZQJ
ZQJ
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.
Afr0m@n
Afr0m@n
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
_______________________Afr0Games
ZQJ
ZQJ
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.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.