Got rid of columns and rows in VGA driver

This commit is contained in:
Mattia Giambirtone 2022-11-20 17:28:42 +01:00
parent 2b13f87f62
commit 4fe70142f6
3 changed files with 25 additions and 95 deletions

View File

@ -36,7 +36,7 @@ operation the high bits are cancelled out. Neat huh?
*/
#define LOW8(x) (u8)(x & 0xff)
#define HIGH8(x) (u8)(x >> 8)
#define HIGH8(x) (u8)(LOW8(x >> 8))

View File

@ -120,7 +120,7 @@ load_kernel:
; Loads the kernel into memory
mov bx, kernel_offset
mov cl, reserved_sectors + 1
mov dh, 5
mov dh, 3
mov dl, [boot_drive]
call load_disk
mov si, kernel_loaded_msg

View File

@ -22,13 +22,9 @@ limitations under the License.
#include <stdarg.h>
u16 getCursorOffset(void);
void setCursorOffset(u16 offset);
u16 putchar(char ch, u8 row, u8 col, char attr);
u16 getOffset(u8 row, u8 col);
u8 getRow(u16 offset);
u8 getColumn(u16 offset);
void printc(char c);
u32 getCursorOffset(void);
void setCursorOffset(u32 offset);
void putchar(char ch, char attr);
@ -39,21 +35,14 @@ void kprint(const char* message) {
Prints a null-terminated string to the VGA
text buffer
*/
i32 offset = getCursorOffset();
i32 row = getRow(offset), col = getColumn(offset);
while (*message) {
offset = putchar(*(message++), row, col, 0);
// We compute the new row and column for the
// next iteration. Hopefully the compiler inlines
// these two calls
row = getRow(offset);
col = getColumn(offset);
putchar(*(message++), 0);
}
setCursorOffset(getOffset(row, col));
}
// TODO
void kprintf(const char *fmt, ...) {
/*
A simple reimplementation of printf in
@ -69,13 +58,9 @@ void kprintf(const char *fmt, ...) {
char* sbuf; /* Used to print strings */
char ibuf[12]; /* Used as input to itoa. 12 is the number of
digits of 2 ** 32 + 2 (for the sign and null byte)*/
u32 offset = getCursorOffset();
u32 row = getRow(offset), col = getColumn(offset);
memset(ibuf, '0', 12);
while (*fmt) {
offset = putchar(*(fmt++), row, col, 0);
row = getRow(offset);
col = getColumn(offset);
putchar(*(fmt++), 0);
}
va_end(args);
}
@ -93,45 +78,28 @@ void inline kprintln(const char* message) {
// Private API below
u16 putchar(char ch, u8 row, u8 col, char attr) {
void putchar(char ch, char attr) {
/*
Writes a single character to the VGA text buffer
at the given row and column and returns the new
location of the cursor. If the attr byte is zero,
its value is the result of the expansion of the
LIGHT_GREY_ON_BLACK macro. If both row and col
are equal to -1, the cursor location is retrieved
from the VGA controller using I/O ports. The following
escape sequences are handled:
If the attr byte is zero, its value is the result
of the expansion of the LIGHT_GREY_ON_BLACK macro.
The following escape sequences are handled:
- '\n' -> Goes to the next line
- '\t' -> Prints VGA_TABSIZE spaces
- '\r' -> Resets the cursor's column, but not the row
Upon error, a negative value is returned; The possible
errors are codes are
- -1 -> Column out of bounds
- -2 -> Row out of bounds
- '\r' -> Goes to the beginning of the line
*/
if (!attr) {
// No color data provided? We supply our own
attr = LIGHT_GREY_ON_BLACK;
}
if (col >= MAX_COLS) {
return -1;
}
if (row >= MAX_ROWS) {
return -2;
}
u16 offset = getOffset(row, col);
u32 offset = getCursorOffset();
switch (ch) {
// Note the difference between a carriage return (which
// only brings the write head back at 0 without changing
// the row) and the newline (which increases the row as well)
case '\r':
offset = getOffset(getRow(offset), 0);
offset -= offset % MAX_COLS;
break;
case '\n':
offset = getOffset(getRow(offset) + 1, 0);
offset += MAX_COLS - offset % MAX_COLS;
break;
case '\t':
for (i32 i = 0; i < VGA_TABSIZE; i++) {
@ -146,6 +114,7 @@ u16 putchar(char ch, u8 row, u8 col, char attr) {
offset += 2;
break;
}
/*
// We check if we reached the end of the screen, in which
// case we scroll
if (offset >= SCREEN_SIZE * 2) {
@ -165,12 +134,13 @@ u16 putchar(char ch, u8 row, u8 col, char attr) {
offset -= 2 * MAX_COLS;
}
*/
setCursorOffset(offset);
return offset;
}
u16 getCursorOffset(void) {
u32 getCursorOffset(void) {
/*
Returns the current offset of
the VGA text cursor
@ -183,22 +153,17 @@ u16 getCursorOffset(void) {
// Memory-mapped I/O is great, isn't it?
writeByte(REG_SCREEN_CTRL, 14);
// And we read it
u16 offset = readByte(REG_SCREEN_DATA);
// Since we requested the high byte
// (i.e. the 8 most significant bits)
// we now want to move them up by 8 places.
// Conveniently, that's exactly what a
// left shift is for :)
u32 offset = readByte(REG_SCREEN_DATA);
offset <<= 8;
// Now we request the low byte of the cursor
// position
writeByte(REG_SCREEN_CTRL, 15);
offset += readByte(REG_SCREEN_DATA);
return offset * 2; // Times 2 because VGA cells are 2 bytes long
return offset * 2; // Times 2 because VGA cells are 2 bytes long
}
void setCursorOffset(u16 offset) {
void setCursorOffset(u32 offset) {
/*
Sets the offset of the VGA text
cursor to the desired value. Note
@ -229,48 +194,13 @@ void setCursorOffset(u16 offset) {
void clearScreen(void) {
/*
Clears the screen and resets
the cursor position to 0, 0
the cursor position to 0
*/
for (i32 i = 0; i < SCREEN_SIZE; i++) {
VMEM_BUF[i * 2] = ' '; // The screen is actually never "empty", just filled with spaces
VMEM_BUF[i * 2 + 1] = LIGHT_GREY_ON_BLACK;
}
setCursorOffset(getOffset(0, 0));
setCursorOffset(0);
}
u16 inline getOffset(u8 row, u8 col) {
/*
Converts a column, row pair into
an absolute offset into the VGA
text buffer
*/
// We multiply by 2 because each VGA
// character cell is 2 bytes long
return (row * MAX_COLS + col) * 2;
}
u8 inline getRow(u16 offset) {
/*
Converts an absolute offset into
the VGA text buffer into a row
*/
// Conversely, we divide by two
// when converting back from the
// raw offset to columns/rows
return offset / (2 * MAX_COLS);
}
u8 inline getColumn(u16 offset) {
/*
Converts an absolute offset into
the VGA text buffer into a column
*/
return (offset - (getRow(offset) * 2 * MAX_COLS)) / 2;
}