Page 1 of 2
[C]Print a character
Posted: Thu Dec 22, 2016 11:33 am
by leosa99
Hi !
I'm trying to print a character to the screen with this code :
Code: Select all
#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 :
It does not print the "W" at (1;3) but at an other place.
Re: [C]Print a character
Posted: Thu Dec 22, 2016 11:55 am
by jojo
Your math is alllll screwy. Remember that the general rule for placing a value at (x, y) is
Code: Select all
bitmap_buffer[y * bitmap_width + x]
Also, C order of operations generally follows standard PEMDAS. But if you're not sure, use parens.
Re: [C]Print a character
Posted: Thu Dec 22, 2016 12:03 pm
by IanSeyler
Can you try the following?:
Code: Select all
(RAMSCREEN + (2 * (row * 80 + column)))
Re: [C]Print a character
Posted: Thu Dec 22, 2016 12:29 pm
by leosa99
In fact I already tried, it still doesn't work ...
Re: [C]Print a character
Posted: Thu Dec 22, 2016 12:33 pm
by hgoel
Just to make sure, what happens if you call it row and column set to 0?
Re: [C]Print a character
Posted: Thu Dec 22, 2016 12:41 pm
by leosa99
If I call it row and column set to 0 the location of the "W" does not change.
Re: [C]Print a character
Posted: Thu Dec 22, 2016 12:53 pm
by hgoel
Does changing the parameters in any way change anything at all?
Re: [C]Print a character
Posted: Thu Dec 22, 2016 1:09 pm
by leosa99
No it does not change anything.
Re: [C]Print a character
Posted: Thu Dec 22, 2016 3:52 pm
by Schol-R-LEA
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: Select all
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: Select all
#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.)
Re: [C]Print a character
Posted: Thu Dec 22, 2016 4:00 pm
by Schol-R-LEA
Having said all that, it occurs to me I forgot to ask: just where is it writing the character to?
Re: [C]Print a character
Posted: Thu Dec 22, 2016 8:25 pm
by irvanherz
Does this will put X at the corner of your screen?
If not, maybe you have initialized wrong GDT base address
Re: [C]Print a character
Posted: Fri Dec 23, 2016 4:05 am
by leosa99
yes it put an X.
If i keep the previous code, the W keeps showing at (0;12).
Re: [C]Print a character
Posted: Fri Dec 23, 2016 5:39 am
by iansjack
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.
Re: [C]Print a character
Posted: Wed Dec 28, 2016 6:27 am
by matt11235
Schol-R-LEA wrote:
Code: Select all
typedef struct {
uint8_t attrib;
unsigned char glyph;
} TEXT_FRAME;
Shouldn't the character be before the attribute byte in the struct?
Re: [C]Print a character
Posted: Wed Dec 28, 2016 6:42 am
by bauen1
zenzizenzicube wrote:Schol-R-LEA wrote:
Code: Select all
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 ?