introduce printf for screen text memory
This commit is contained in:
parent
e8cef8bd59
commit
3ef9be01ae
2
Makefile
2
Makefile
|
@ -33,7 +33,7 @@ $(BUILD_DIR)/%.asm.o: $(SRC_DIR)/%.asm
|
|||
|
||||
$(BUILD_DIR)/%.c.o: $(SRC_DIR)/%.c
|
||||
@mkdir -p "$(@D)"
|
||||
$(CC) -c $< -o $@ -I$(INCLUDE_DIR) -std=gnu99 -ffreestanding -O2 -Wall -Wextra
|
||||
$(CC) -c $< -o $@ -I$(INCLUDE_DIR) -std=gnu99 -ffreestanding -O2 -Wall -Wextra -Wformat
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR)/*
|
||||
|
|
|
@ -36,4 +36,7 @@ void tsinit(void);
|
|||
void tsputch(char ch, uint8_t color);
|
||||
void tsputs(const char* str, uint8_t color);
|
||||
|
||||
void tsprintf(const char* format, ...)
|
||||
__attribute__((format (printf, 1, 2)));
|
||||
|
||||
#endif // _CLIPPER_TEXT_SCREEN_H_
|
||||
|
|
|
@ -16,8 +16,10 @@
|
|||
void kmain(void) {
|
||||
tsinit();
|
||||
|
||||
const char* msg = "Clipper set sail!\n~~~~~~~~~~~~~~~~~";
|
||||
const char* msg = "Clipper set sail!\n~~~~~~~~~~~~~~~~~\n";
|
||||
tsputs(msg, TEXT_SCREEN_BG_BLACK | TEXT_SCREEN_FG_LIGHT_CYAN);
|
||||
|
||||
tsprintf("Test | Integers: %d, Unsigned: %u, Hexadecimal: %x\n", -48, 28493, 28493);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#include "internal/text_screen.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "internal/io.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
struct text_screen_char {
|
||||
char character;
|
||||
|
@ -13,6 +16,13 @@ static uint8_t cursor_y = 0;
|
|||
#define SCREEN_WIDTH 80
|
||||
#define SCREEN_HEIGHT 25
|
||||
|
||||
enum printf_format_specifier {
|
||||
FORMAT_SPECIFIER_INT,
|
||||
FORMAT_SPECIFIER_UNSIGNED,
|
||||
FORMAT_SPECIFIER_HEXADECIMAL,
|
||||
FORMAT_SPEFICIER_UNKNOWN
|
||||
};
|
||||
|
||||
void tsinit(void) {
|
||||
outb(0x3D4, 0x0A);
|
||||
outb(0x3D5, 0x20);
|
||||
|
@ -23,7 +33,8 @@ void tsputch(char ch, uint8_t color) {
|
|||
tsputs(tmp, color);
|
||||
}
|
||||
|
||||
static void handle_special_char(char c) {
|
||||
static
|
||||
void handle_special_char(char c) {
|
||||
switch (c) {
|
||||
case '\n': {
|
||||
cursor_x = 0;
|
||||
|
@ -66,3 +77,93 @@ void tsputs(const char* ch, uint8_t color) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
const char* decode_format_spefifier(const char* str, enum printf_format_specifier* data) {
|
||||
switch (*str) {
|
||||
case 'd':
|
||||
case 'i':
|
||||
*data = FORMAT_SPECIFIER_INT;
|
||||
return str+1;
|
||||
|
||||
case 'o':
|
||||
case 'u':
|
||||
*data = FORMAT_SPECIFIER_UNSIGNED;
|
||||
return str+1;
|
||||
|
||||
case 'x':
|
||||
case 'X':
|
||||
*data = FORMAT_SPECIFIER_HEXADECIMAL;
|
||||
return str+1;
|
||||
}
|
||||
|
||||
*data = FORMAT_SPEFICIER_UNKNOWN;
|
||||
return str;
|
||||
}
|
||||
|
||||
static
|
||||
const char* handle_format_specifier(const char* str, va_list* args) {
|
||||
str++;
|
||||
char tmp[16];
|
||||
|
||||
enum printf_format_specifier specifier;
|
||||
str = decode_format_spefifier(str, &specifier);
|
||||
switch (specifier) {
|
||||
case FORMAT_SPECIFIER_INT: {
|
||||
int value = va_arg(*args, int);
|
||||
tsputs(itoa(value, tmp, 10), TEXT_SCREEN_BG_BLACK | TEXT_SCREEN_FG_WHITE);
|
||||
} break;
|
||||
|
||||
case FORMAT_SPECIFIER_UNSIGNED: {
|
||||
unsigned int value = va_arg(*args, unsigned int);
|
||||
tsputs(utoa(value, tmp, 10), TEXT_SCREEN_BG_BLACK | TEXT_SCREEN_FG_WHITE);
|
||||
} break;
|
||||
|
||||
|
||||
case FORMAT_SPECIFIER_HEXADECIMAL: {
|
||||
unsigned int value = va_arg(*args, unsigned int);
|
||||
tsputs(utoa(value, tmp, 16), TEXT_SCREEN_BG_BLACK | TEXT_SCREEN_FG_WHITE);
|
||||
} break;
|
||||
default: return str;
|
||||
}
|
||||
|
||||
return str-1;
|
||||
}
|
||||
|
||||
void tsprintf(const char* format, ...) {
|
||||
struct text_screen_char tsch = {
|
||||
.character = '\0',
|
||||
.attribute = TEXT_SCREEN_BG_BLACK | TEXT_SCREEN_FG_GRAY
|
||||
};
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
for (const char* c = format; *c != '\0'; c++) {
|
||||
if (*c == '%') {
|
||||
c = handle_format_specifier(c, &args);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((uint8_t)(*c) < 0x20) {
|
||||
handle_special_char(*c);
|
||||
continue;
|
||||
}
|
||||
|
||||
tsch.character = *c;
|
||||
|
||||
videomem[cursor_y * SCREEN_WIDTH + cursor_x] = tsch;
|
||||
|
||||
cursor_x++;
|
||||
if (cursor_x >= SCREEN_WIDTH) {
|
||||
cursor_y++;
|
||||
cursor_x = 0;
|
||||
|
||||
if (cursor_y >= SCREEN_HEIGHT) {
|
||||
cursor_y = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue