Page 1 of 3

How do i fix my newline procedure?

Posted: Tue Dec 06, 2016 4:16 am
by NunoLava1998
I tried to add the support of newlines to my OS. I booted it using QEMU, and i got this result:
Image

I see that the newlines were indeed created, but the text ignored it, and got overlapped by a lot of things too.
Where i put \n in the text is Image for some reason (When i try to do I/O operations, i also get this character and a solid halt).

How do i fix this?

My terminal_putchar() is as follows:

Code: Select all

void terminal_putchar(char c) {
	terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
	if (++terminal_column == VGA_WIDTH) {
		terminal_column = 0;
		if (++terminal_row == VGA_HEIGHT)
			terminal_row = 0;
	}
	if (c == '\n') {
		terminal_row = terminal_row++;
		terminal_column = 0;
	}
}
Why is this happening, do i need to put the additional code somewhere else in terminal_putchar()? How can i fix this?

Re: How do i fix my newline procedure?

Posted: Tue Dec 06, 2016 4:30 am
by Ycep
terminal_row = terminal_row++;
Do not use code that you do not understand.
You could use:

Code: Select all

terminal_row++;
or

Code: Select all

terminal_row=++terminal_row;
Really, learn C before trying to create operating system.

Re: How do i fix my newline procedure?

Posted: Tue Dec 06, 2016 4:55 am
by NunoLava1998
Lukand wrote:
terminal_row = terminal_row++;
Do not use code that you do not understand.
You could use:

Code: Select all

terminal_row++;
or

Code: Select all

terminal_row=++terminal_row;
Really, learn C before trying to create operating system.
Removed the "possibly undefined" warning and now i got newlines. Except...
Image

Re: How do i fix my newline procedure?

Posted: Tue Dec 06, 2016 5:24 am
by iansjack
You told it to print the newline character on the screen, and it did. What did you expect?

Re: How do i fix my newline procedure?

Posted: Tue Dec 06, 2016 5:40 am
by NunoLava1998
iansjack wrote:You told it to print the newline character on the screen, and it did. What did you expect?
It is succesful, but the Image shouldn't appear. I never put that there, i still need to know how to get rid of it.

Re: How do i fix my newline procedure?

Posted: Tue Dec 06, 2016 6:06 am
by Schol-R-LEA
To clarify iansjack's comment: the actual 'newline character' - which isn't necessarily a single character, BTW - isn't a displayable character in the normal sense. You need to check for that character (or character sequence, depending on how you choose to represent newlines) and any other control characters such as tabs or the BEL character, before you write to the text video buffer, and handle them without actually putting the byte value into the buffer.

The reason I say that the newline isn't necessarily one character is because in the original ASCII character set, carriage return (the ASCII escape code called CR and with the value 0x0D, returning the writing head on the teletype to the zero column) and line feed (LF, 0x0A, advancing the paper roller by one line) were two separate operations. Note that these were explicitly defined in terms of controlling a teletype writing to a scroll of paper - this would come back to haunt everyone as the technology changed, as it meant that when CRT terminals and eventually graphical displays were developed, teletypes still had to be supported as a sort of lowest common denominator, meaning that if you wanted to write a program that worked everywhere, you couldn't make any assumptions about how the display worked.

Anyway, the 'standard' approach for a newline was to use a CR followed by a LF, which modeled the standard teletype mode. However, not every OS followed this. Unix, in particular, use a single LF as the newline character, while older Macintosh systems used a single CR. MS-DOS and Windows use the CR/LF sequence, in that order, and reversing them can cause some Windows programs to go haywire.

The practical upshot is that you will need to choose how you want to represent the newline.

Worse, these are control codes, which means you don't want to actually put them into the display buffer as there are no displayable glyphs for them - at least not standardized ones. The IBM console video buffer will treat those characters as representing glyphs, but the one it uses depend on the display page (the list of character glyphs used for a given character set), and in any case the character 'really is' a command rather than something you would display.

BTW, what do you expect the code snippet:

Code: Select all

      if (++terminal_row == VGA_HEIGHT)
         terminal_row = 0;
to do, and where will the cursor end up? What will the screen look like after the next character is displayed? What will be in the video buffer, and what will happen to the glyphs already being displayed?

As a final note, I would recommend defining a struct to represent the console state, rather than having separate terminal_row and terminal_column variables, if only because you will eventually have to handle different display modes and multiple virtual consoles. Something like this would be a start:

Code: Select all

struct TTY_CONSOLE 
{
    struct TEXT_VBUFFER *buffer;
    TEXT_VMODE mode;
    uint8_t row, column;
};
The implementation of the TEXT_VBUFFER struct, the TEXT_VMODE typedef, and the functions to operate on this struct, are left as an exercise :P

Re: How do i fix my newline procedure?

Posted: Tue Dec 06, 2016 6:11 am
by osdever
iansjack wrote:You told it to print the newline character on the screen, and it did. What did you expect?
+1

Nuno, your code does exactly what it should do. What's the problem?

Re: How do i fix my newline procedure?

Posted: Tue Dec 06, 2016 6:12 am
by osdever
Schol-R-LEA, thanks for last part of the post. I'll implement this now.

Re: How do i fix my newline procedure?

Posted: Tue Dec 06, 2016 6:13 am
by iansjack
NunoLava1998 wrote:the Image shouldn't appear. I never put that there
Oh yes, you did.

Re: How do i fix my newline procedure?

Posted: Tue Dec 06, 2016 6:20 am
by osdever
Nuno, your code first prints the character and only then checks for '\n', so it tries to print character corresponding to LF anyway.

Re: How do i fix my newline procedure?

Posted: Tue Dec 06, 2016 6:20 am
by Schol-R-LEA
If we seem a bit flippant here, it is because these bugs are like old, familiar friends, and making these mistakes is a rite of passage for almost any OS developer. We can see the order of events coming well in advance because we've all been there ourselves.

Re: How do i fix my newline procedure?

Posted: Tue Dec 06, 2016 6:52 am
by NunoLava1998
Schol-R-LEA wrote:To clarify iansjack's comment: the actual 'newline character' - which isn't necessarily a single character, BTW - isn't a displayable character in the normal sense. You need to check for that character (or character sequence, depending on how you choose to represent newlines) and any other control characters such as tabs or the BEL character, before you write to the text video buffer, and handle them without actually putting the byte value into the buffer.

The reason I say that the newline isn't necessarily one character is because in the original ASCII character set, carriage return (the ASCII escape code called CR and with the value 0x0D, returning the writing head on the teletype to the zero column) and line feed (LF, 0x0A, advancing the paper roller by one line) were two separate operations. Note that these were explicitly defined in terms of controlling a teletype writing to a scroll of paper - this would come back to haunt everyone as the technology changed, as it meant that when CRT terminals and eventually graphical displays were developed, teletypes still had to be supported as a sort of lowest common denominator, meaning that if you wanted to write a program that worked everywhere, you couldn't make any assumptions about how the display worked.

Anyway, the 'standard' approach for a newline was to use a CR followed by a LF, which modeled the standard teletype mode. However, not every OS followed this. Unix, in particular, use a single LF as the newline character, while older Macintosh systems used a single CR. MS-DOS and Windows use the CR/LF sequence, in that order, and reversing them can cause some Windows programs to go haywire.

The practical upshot is that you will need to choose how you want to represent the newline.

Worse, these are control codes, which means you don't want to actually put them into the display buffer as there are no displayable glyphs for them - at least not standardized ones. The IBM console video buffer will treat those characters as representing glyphs, but the one it uses depend on the display page (the list of character glyphs used for a given character set), and in any case the character 'really is' a command rather than something you would display.

BTW, what do you expect the code snippet:

Code: Select all

      if (++terminal_row == VGA_HEIGHT)
         terminal_row = 0;
to do, and where will the cursor end up? What will the screen look like after the next character is displayed? What will be in the video buffer, and what will happen to the glyphs already being displayed?

As a final note, I would recommend defining a struct to represent the console state, rather than having separate terminal_row and terminal_column variables, if only because you will eventually have to handle different display modes and multiple virtual consoles. Something like this would be a start:

Code: Select all

struct TTY_CONSOLE 
{
    struct TEXT_VBUFFER *buffer;
    TEXT_VMODE mode;
    uint8_t row, column;
};
The implementation of the TEXT_VBUFFER struct, the TEXT_VMODE typedef, and the functions to operate on this struct, are left as an exercise :P
BTW, what do you expect the code snippet:

Code: Select all

      if (++terminal_row == VGA_HEIGHT)
         terminal_row = 0;
to do, and where will the cursor end up? What will the screen look like after the next character is displayed? What will be in the video buffer, and what will happen to the glyphs already being displayed?
in a more human-favorable sense (i hope you know what i mean by that):

1: "if the variable terminal_row incremented equals the variable VGA_HEIGHT (25), set terminal_row to 0."
2: in the beginning of the line you just were in
3: the same but the first character is overwritten by what we tried to write
4: depends but the first should be different than what you wrote without the last character
5: nothing unless it gets overwritten

What i'm trying to achieve now is do newlines succesfully.

"oh yes, you did put that in"

Code: Select all

	/* Newline support is left as an exercise. */
	terminal_writestring("C mode succesful.\nThis should be a newline.\n");

	terminal_writestring("So there IS a newline after that text.\n Normal. Wait, new\n line?");
}
I want to see where's Image there. No, not trying to be mean or judge you or offend you.

Re: How do i fix my newline procedure?

Posted: Tue Dec 06, 2016 6:58 am
by Octocontrabass
NunoLava1998 wrote:I want to see where's Image there.
What is the ASCII value for '\n'? Which glyph has that value in code page 437?

It's not a coincidence that every time you put '\n' you get ◙.

Re: How do i fix my newline procedure?

Posted: Tue Dec 06, 2016 7:00 am
by NunoLava1998
Octocontrabass wrote:
NunoLava1998 wrote:I want to see where's Image there.
What is the ASCII value for '\n'? Which glyph has that value in code page 437?

It's not a coincidence that every time you put '\n' you get ◙.
But how do i hide that? It's just that i need to make newlines that are succesful (and not with glyphs or failing to do a instruction)

Re: How do i fix my newline procedure?

Posted: Tue Dec 06, 2016 7:08 am
by iansjack
Are you seriously asking how you don't display a character if you don't want it to appear? Just don't display it!