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.)
Rev. First Speaker Schol-R-LEA;2 LCF ELF JAM POEE KoR KCO PPWMTF
Ordo OS Project
Lisp programmers tend to seem very odd to outsiders, just like anyone else who has had a religious experience they can't quite explain to others.