Page 2 of 3

Re: How do i fix my newline procedure?

Posted: Tue Dec 06, 2016 7:24 am
by Octacone
Holy mother of God!!! Inside your put character function, you need to check if a specific character is equal to '\n' and if it is just ignore it and call your new line procedure.

Re: How do i fix my newline procedure?

Posted: Tue Dec 06, 2016 7:33 am
by Schol-R-LEA
As I said earlier, you need to process control characters such as newlines first, before you write to the text buffer, and if it is a non-displaying character, yo don't insert it into the buffer but instead take the action that it requires.

For example, if it is a TAB, rather than putting the value 0x09 into the buffer, you would put a sequence of spaces (0x20) equal equal to whatever you have tab set to (usually either 4 or 8, though it could be anything) and advance the cursor past those spaces.

Code: Select all

void terminal_putchar(tty_console term, char c) {
   switch(c) {
      case '\t':
         for (i = 0; i < term.tab_stop; ++i) {
             terminal_putentryat(' ', term.buffer, term.fgcolor, term.row, term.column);
             if (++term.column == VGA_WIDTH) {
                 term.column = 0;
                 break;                              /* don't wrap a tab past the end of the line */
             }
         }
         break;
     case 0x0D:                 /* carriage return - be explicit which one you use, don't just use '\n' */
         term.column = 0;
         break;
     case ox0A:                 /* line feed - again, if you are doing them as  a sequence, treat them as different values */
         advance_row(term);
         break;
     /* handle other cases here */
     default:
        terminal_putentryat(c, term.buffer, term.fgcolor, term.row, term.column);
        if (++term.column == VGA_WIDTH) {
           term.column = 0;
           if (++term.row == VGA_HEIGHT) {
              advance_row(term);
           }
       }
   }
}
This is just a quick sketch of what you could do; how you actually handle it is your call.

Re: How do i fix my newline procedure?

Posted: Tue Dec 06, 2016 1:46 pm
by Ycep
Dammit... There is your fix:

Code: Select all

void terminal_putchar(char c) {
   if (c == '\n') {
      terminal_row++;
      terminal_column = 0;
      if (terminal_row == VGA_HEIGHT)
         terminal_row = 0;
      return;
   }
   terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
   if (terminal_column == VGA_WIDTH) {
      terminal_column = 0;
      
   }
}
Operator ++ increments integer by one. integer++ is not same as integer+1 .

Re: How do i fix my newline procedure?

Posted: Tue Dec 06, 2016 10:19 pm
by SpyderTL
In case you weren't aware, your compiler will automatically convert escape characters, like \n into a single character before writing it to your compiled program. In this case, it turns every \n in your string into a hex byte 0x0A.

That 0x0A byte is then copied into your video card's memory by your OS, and the video card looks up that value in a built in font table, and finds that circle character in that location in the table, and it prints it to the screen.

Your OS code should not copy any 0x0A bytes to video memory. It should instead move the cursor to the beginning of the next line.

Hopefully that clears things up a bit.

Re: How do i fix my newline procedure?

Posted: Wed Dec 07, 2016 3:27 am
by NunoLava1998
Lukand wrote:Dammit... There is your fix:

Code: Select all

void terminal_putchar(char c) {
   if (c == '\n') {
      terminal_row++;
      terminal_column = 0;
      if (terminal_row == VGA_HEIGHT)
         terminal_row = 0;
      return;
   }
   terminal_putentryat(c, terminal_color, terminal_column, terminal_row);
   if (terminal_column == VGA_WIDTH) {
      terminal_column = 0;
      
   }
}
Operator ++ increments integer by one. integer++ is not same as integer+1 .
That code turned my semi-working (i don't want to print 0x0A but it does) newline function in terminal_putchar() to doing this...
Image

Re: How do i fix my newline procedure?

Posted: Wed Dec 07, 2016 4:49 am
by MichaelFarthing
NunoLava1998 wrote: That code turned my semi-working (i don't want to print 0x0A but it does) newline function in terminal_putchar() to doing this...
Well you'd best work out out what's wrong then...

Re: How do i fix my newline procedure?

Posted: Wed Dec 07, 2016 5:11 am
by Ycep
Try this:

Code: Select all

void terminal_putchar(char c) {
   if (c == '\n') {
      terminal_row++;
      terminal_column = 0;
      if (terminal_row == 25)
         terminal_row = 0;
      return;
   }
   terminal_putentryat(c, terminal_color, terminal_column++, terminal_row);
   if (terminal_column == 80) {
      terminal_column = 0; 
   }
}

Re: How do i fix my newline procedure?

Posted: Wed Dec 07, 2016 11:27 am
by Schol-R-LEA
Lukand wrote:Try this:

Code: Select all

void terminal_putchar(char c) {
   if (c == '\n') {
      terminal_row++;
      terminal_column = 0;
      if (terminal_row == 25)
         terminal_row = 0;
      return;
   }
   terminal_putentryat(c, terminal_color, terminal_column++, terminal_row);
   if (terminal_column == 80) {
      terminal_column = 0; 
   }
}
That code still has a serious problem, as I pointed out earlier: it has the effect of returning the cursor to the first column of the first row (which in English and other sinistrodextral languages means the upper left-hand corner), but does not clear the existing text from the buffer. Thus, to give a simplified example, if you had a page where you had 6 rows and 8 columns,

Code: Select all

This is |
a simple|
example |
of what |
I mean h|
ere.    |
With the code as it is, if you were the add the word 'fnord' to the last line, it would wrap back the beginning of the page:

Code: Select all

rdis is |
a simple|
example |
of what |
I mean h|
ere. Fno|
I assume for now that you can see the problem here (since the 'fnord' is broken up :) ), and why you probably want something a bit more complicated to handle the end-of-page scenario.

There are two common solutions: either clear the page, or scroll the page up by one line. Clearing is simpler, as you can just use a bulk move to copy a blank glyph over every character already on the screen, but it loses information; scrolling is a little trickier, as it requires you to copy all the lines after the first one to the line above them. Scrolling is probably the better solution in most cases, but having a clear routine is advisable as well, so I suggest writing one function for each of those operations and maybe having a flag as to which one to use in terminal_putchar().

Mind you too that you will probably want to use different text page modes eventually, so hardcoding the rows and columns is probably not a great idea. It works fine for now, but you might want to at least give some thought to how you will need to change it in the future.

Re: How do i fix my newline procedure?

Posted: Wed Dec 07, 2016 1:48 pm
by Ycep
The problem may disappear when he makes vga scrolling.

Re: How do i fix my newline procedure?

Posted: Wed Dec 07, 2016 2:22 pm
by Schol-R-LEA
Lukand wrote:The problem may disappear when he makes vga scrolling.
Isn't that what I was just discussing? In order for it to use scrolling... you have to implement scrolling. Even with hardware support, you need to set it up and use it - it is not automatic. Or am I missing something?

Re: How do i fix my newline procedure?

Posted: Wed Dec 07, 2016 3:09 pm
by Schol-R-LEA
It occurs to me that both NunoLava98 and Lukand are making a common mistake - one nearly everyone makes at first - because of a misunderstanding about how the text buffer works. They both seem to be thinking of it as a stream buffer, that is, a array with a pointer which is used in a first-in, first-out manner, where the data is added by the program on one end and then read out by something else on the other.

This is how the C standard I/O libraries work, and how INT 10h/AH=0Eh works. It is how the old teletype systems they emulate worked. It is not, however, how the VGA text buffer works.

The VGA video buffers are actual areas in memory - usually on the video adapter, and not readable by the system - which you in essence are drawing on, like a sketchpad. Once a cell in the buffer is set to a given value, it retains the value until it gets changed by something. If you write to a cell that is lower in memory than the one you had been writing to, the only thing changed is the cell you just wrote to - the rest of the screen stays the same as it was. It is not linear the way a stream buffer is.

The standard libraries all implement stream buffers, but that's solely because teletypes are a well understood and simple API that can be used with minimal understanding of the underlying hardware. The VGA adapter has no hardware support for it, though, and the libraries have to bend over backwards to make your 4K flatscreen monitor act like a 1967 vintage ASR-33 printing on a roll of fanfold paper because it is a universal interface that you don't have to think much about 99% of the time.

This is one of the 1% of the time where that model isn't going to help you. You don't have a stream I/O library to use yet. You need to understand what is actually happening, rather than coasting on the work of earlier developers.

Re: How do i fix my newline procedure?

Posted: Thu Dec 08, 2016 1:22 pm
by Schol-R-LEA
To further clarify: the video text buffer is linear in the sense that it is a buffer of (usually write-only) memory that can be stepped through with a pointer. However, the video hardware treats it as a 2-dimensional array of attribute-character pairs, where the number of horizontal columns, x, and the number of vertical rows, y, depends on the video text mode being used.

Since the original CGA/MDA text buffer was allocated with a bit less than 16K, which was divided into four such buffers for the pre-VGA standard 80x25 mode (a total of 2000 16-bit character cells) of 4000 bytes each, and switching between them was a common way both to avoid flicker and to handle virtual screens. The video display actually uses all 2000 on every refresh, regardless of what is in them; the buffer size used is constant, regardless, and the buffer had no built-in concept of a 'newline character' at all.

Re: How do i fix my newline procedure?

Posted: Thu Dec 08, 2016 2:21 pm
by jojo
> Check in on OSDev for the first time in something like a month
> Top two most recently active posts are Nuno asking asking easily googlable questions about trivially fixable issues

Never change. At least that cat picture is gone.

Re: How do i fix my newline procedure?

Posted: Thu Dec 08, 2016 2:31 pm
by Ycep
I'm not making any mistakes. I totally understand that terminal is just fake piece of memory made of 16-bit cells.
He is the one that doesn't understand VGA text-mode buffer.
You are making too long pointless posts. Couldn't you write just this:
- Putting newline (0x0A) inside text-mode video buffer would make video card display ASCII equivalent of 0x0A, which is his reason of seeing such strange signs on screen. You could not use carriage return + left tab on such terminal.

Re: How do i fix my newline procedure?

Posted: Thu Dec 08, 2016 3:40 pm
by jojo
Wow, sorry the guy is trying to be clear and verbose while he's being graciously helpful.