OSDev.org
https://forum.osdev.org/

[C]Print a character
https://forum.osdev.org/viewtopic.php?f=13&t=31109
Page 1 of 2

Author:  leosa99 [ Thu Dec 22, 2016 11:33 am ]
Post subject:  [C]Print a character

Hi !
I'm trying to print a character to the screen with this code :
Code:
#define RAMSCREEN 0xB8000 // Video address.

void printCharacter(char row, char column) // It print a character at the selected location.
{
unsigned char *res_location;
res_location = (unsigned char*)(RAMSCREEN + 2 * (row * 80 + column));
res_location[0]='W';
res_location[1]=0xd;
}

I call it with :
Code:
printCharacter(1,3);

It does not print the "W" at (1;3) but at an other place.

Author:  jojo [ Thu Dec 22, 2016 11:55 am ]
Post subject:  Re: [C]Print a character

Your math is alllll screwy. Remember that the general rule for placing a value at (x, y) is
Code:
bitmap_buffer[y * bitmap_width + x]


Also, C order of operations generally follows standard PEMDAS. But if you're not sure, use parens.

Author:  IanSeyler [ Thu Dec 22, 2016 12:03 pm ]
Post subject:  Re: [C]Print a character

Can you try the following?:

Code:
(RAMSCREEN + (2 * (row * 80 + column)))

Author:  leosa99 [ Thu Dec 22, 2016 12:29 pm ]
Post subject:  Re: [C]Print a character

In fact I already tried, it still doesn't work ...

Author:  hgoel [ Thu Dec 22, 2016 12:33 pm ]
Post subject:  Re: [C]Print a character

Just to make sure, what happens if you call it row and column set to 0?

Author:  leosa99 [ Thu Dec 22, 2016 12:41 pm ]
Post subject:  Re: [C]Print a character

If I call it row and column set to 0 the location of the "W" does not change.

Author:  hgoel [ Thu Dec 22, 2016 12:53 pm ]
Post subject:  Re: [C]Print a character

Does changing the parameters in any way change anything at all?

Author:  leosa99 [ Thu Dec 22, 2016 1:09 pm ]
Post subject:  Re: [C]Print a character

No it does not change anything.

Author:  Schol-R-LEA [ Thu Dec 22, 2016 3:52 pm ]
Post subject:  Re: [C]Print a character

Might I suggest that rather than trying to muck about with a pointer, you treat the buffer as two-dimensional array of a struct containing the two bytes?

Code:
typedef struct {
    uint8_t attrib;
    unsigned char glyph;
} TEXT_FRAME;

TEXT_FRAME *text_buffer = (TEXT_FRAME *) 0xb8000;

#define COLUMN_OFFSET 80

// ...

    text_buffer[(rows * COLUMN_OFFSET) + columns].glyph = 'W';
    text_buffer[(rows * COLUMN_OFFSET) + columns].attrib = 0xd;


Actually, given that there are several text modes, and you also need to bounds-check the text buffer (among other things), I would go with something more like:

Code:
#define DEFAULT_TEXT_MODE 0x03
#define DEFAULT_CODE_PAGE 437   // or set this to a page suited to your native language

struct {
    uint8_t total_rows, total_columns;
} TEXT_MODES[255] = {
    // populate this with a lookup table for the modes by mode #
};

typedef struct {
    uint16_t row, column;
} TEXT_CURSOR;

typedef struct {
    TEXT_MODE mode;
     uint16_t code_page;
    TEXT_CURSOR cursor;   
    TEXT_BUFFER buffer;
} TEXT_PAGE;

const TEXT_BUFFER buffers[] = {
    (TEXT_FRAME *) 0xB8000,
    // .. I can't seem to find the rest of the entry points for the other three
    // text pages ... anyone?
}; 

TEXT_PAGE pages[4];

void kinit_console()
{
    int i;

    for (i = 0; i < 4; i++)
    {
        pages[i].mode = DEFAULT_TEXT_MODE;
        pages[i].code_page = DEFAULT_CODE_PAGE;
        pages[i].cursor.row = 0;
        pages[i].cursor.column = 0;
        pages[i].buffer = buffers[i];
}

bool k_gotoxy(TEXT_BUFFER *page, uint8_t row, uint8_t col, bool reset_hw_cursor)
{
    if (row >= page ->text_mode.total_rows || col >= page ->text_mode.total_columns)
    {
        return false;
    }

    page ->cursor.row = row;
    page ->cursor.column = col;
    if (reset_hw_cursor)
    {
        set_vga_cursor(row, col);
    }

    return true;
}

void kputchar(TEXT_BUFFER *page, unsigned char ch)
{
    int *x = &page ->cursor.columns;
    int *y = &page ->cursor.rows;
    int x_offset = page ->text_mode.total_columns;
    int y_offset = page ->text_mode.total_rows;
    FRAME_BUFFER *buffer = page ->buffer;

    if (x <= x_offset)
    {
        x = 0;
        y++;
    }
    else
    {
        x++;
    }

    if (y <= y_offset)
    {
        // handle scrolling or clearing page as you choose
    }
   
    buffer[(y * x_offset) + x].glyph = ch;

    set_vga_cursor(x, y);
}


(Not tested code, just use this as a guide.)

Author:  Schol-R-LEA [ Thu Dec 22, 2016 4:00 pm ]
Post subject:  Re: [C]Print a character

Having said all that, it occurs to me I forgot to ask: just where is it writing the character to?

Author:  irvanherz [ Thu Dec 22, 2016 8:25 pm ]
Post subject:  Re: [C]Print a character

Does this will put X at the corner of your screen?
Code:
*((char*)0xB8000) = 'X';


If not, maybe you have initialized wrong GDT base address

Author:  leosa99 [ Fri Dec 23, 2016 4:05 am ]
Post subject:  Re: [C]Print a character

yes it put an X.
If i keep the previous code, the W keeps showing at (0;12).

Author:  iansjack [ Fri Dec 23, 2016 5:39 am ]
Post subject:  Re: [C]Print a character

You should

1. Inspect the generated code.

2. Then single-step through it in a debugger.

It should then be fairly obvious what is going wrong.

Author:  matt11235 [ Wed Dec 28, 2016 6:27 am ]
Post subject:  Re: [C]Print a character

Schol-R-LEA wrote:
Code:
typedef struct {
    uint8_t attrib;
    unsigned char glyph;
} TEXT_FRAME;


Shouldn't the character be before the attribute byte in the struct?

Author:  bauen1 [ Wed Dec 28, 2016 6:42 am ]
Post subject:  Re: [C]Print a character

zenzizenzicube wrote:
Schol-R-LEA wrote:
Code:
typedef struct {
    uint8_t attrib;
    unsigned char glyph;
} TEXT_FRAME;


Shouldn't the character be before the attribute byte in the struct?

Correct me if i'm wrong but should this have the packed attribute ?

Page 1 of 2 All times are UTC - 6 hours
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/