diff --git a/Makefile b/Makefile index 13c723b..ef6deeb 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ VERSION ?= $(shell git describe --dirty --always) GITSHA ?= $(shell git rev-parse --short HEAD) KERNEL_FILENAME:= popcorn.bin -KERNEL_FONT := assets/fonts/tamsyn10x20r.psf +KERNEL_FONT := assets/fonts/tamsyn8x16r.psf MODULES := main diff --git a/assets/fonts/tamsyn8x16r.psf b/assets/fonts/tamsyn8x16r.psf new file mode 100644 index 0000000..6fd82c1 Binary files /dev/null and b/assets/fonts/tamsyn8x16r.psf differ diff --git a/src/modules/main/font.c b/src/modules/main/font.c new file mode 100644 index 0000000..44a8fce --- /dev/null +++ b/src/modules/main/font.c @@ -0,0 +1,81 @@ +#include "font.h" +#include "screen.h" + +/* PSF2 header format + * Taken from the Linux KBD documentation + * http://www.win.tue.nl/~aeb/linux/kbd/font-formats-1.html + */ + +const static uint8_t magic[] = {0x72, 0xb5, 0x4a, 0x86}; + +/* bits used in flags */ +enum psf2_flags { + psf2_has_unicode = 0x00000001 +}; + +/* max version recognized so far */ +#define PSF2_MAXVERSION 0 + +/* UTF8 separators */ +#define PSF2_SEPARATOR 0xFF +#define PSF2_STARTSEQ 0xFE + +struct psf2_header { + uint8_t magic[4]; + uint32_t version; + uint32_t header_size; // offset of bitmaps in file + uint32_t flags; + uint32_t length; // number of glyphs + uint32_t charsize; // number of bytes for each character + uint32_t height, width; // max dimensions of glyphs +}; + +int +font_init(void *header, struct font *font) +{ + struct psf2_header *psf2 = (struct psf2_header *)header; + for (int i = 0; i < sizeof(magic); ++i) { + if (psf2->magic[i] != magic[i]) { + return 1; + } + } + + if (font == 0) + return 2; + + font->height = psf2->height; + font->width = psf2->width; + font->charsize = psf2->charsize; + font->count = psf2->length; + font->data = (uint8_t *)header + psf2->header_size; + return 0; +} + +int +font_draw( + struct font *f, + struct screen *s, + uint32_t glyph, + uint32_t color, + uint32_t x, + uint32_t y) +{ + const uint32_t height = f->height; + const uint32_t width = f->width; + const uint32_t bwidth = (width+7)/8; + uint8_t *data = f->data + (glyph * f->charsize); + + for (int dy = 0; dy < f->height; ++dy) { + for (int dx = 0; dx < bwidth; ++dx) { + uint8_t byte = data[dy * bwidth + dx]; + for (int i = 0; i < 8; ++i) { + if (dx*8 + i >= width) continue; + const uint8_t mask = 1 << (7-i); + uint32_t c = (byte & mask) ? color : 0; + screen_pixel(s, x + dx*8 + i, y + dy, c); + } + } + } + return 0; +} + diff --git a/src/modules/main/font.h b/src/modules/main/font.h index 788c81b..00fb8c8 100644 --- a/src/modules/main/font.h +++ b/src/modules/main/font.h @@ -1,32 +1,22 @@ #pragma once #include -/* PSF2 header format - * Taken from the Linux KBD documentation - * http://www.win.tue.nl/~aeb/linux/kbd/font-formats-1.html - */ +struct screen; -#define PSF2_MAGIC0 0x72 -#define PSF2_MAGIC1 0xb5 -#define PSF2_MAGIC2 0x4a -#define PSF2_MAGIC3 0x86 - -/* bits used in flags */ -#define PSF2_HAS_UNICODE_TABLE 0x01 - -/* max version recognized so far */ -#define PSF2_MAXVERSION 0 - -/* UTF8 separators */ -#define PSF2_SEPARATOR 0xFF -#define PSF2_STARTSEQ 0xFE - -struct psf2_header { - uint8_t magic[4]; - uint32_t version; - uint32_t headersize; // offset of bitmaps in file - uint32_t flags; - uint32_t length; // number of glyphs - uint32_t charsize; // number of bytes for each character - uint32_t height, width; // max dimensions of glyphs +struct font { + uint16_t height; + uint16_t width; + uint16_t charsize; + uint16_t count; + uint8_t *data; }; + +int font_init(void *header, struct font *font); + +int font_draw( + struct font *f, + struct screen *s, + uint32_t glyph, + uint32_t color, + uint32_t x, + uint32_t y); diff --git a/src/modules/main/main.c b/src/modules/main/main.c index cfdb333..874a329 100644 --- a/src/modules/main/main.c +++ b/src/modules/main/main.c @@ -1,6 +1,9 @@ #include #include +#include "font.h" +#include "screen.h" + void do_the_set_registers(); #pragma pack(push, 1) @@ -38,9 +41,33 @@ __attribute__((aligned(8))); void kernel_main(struct popcorn_data *header) { - uint32_t *p = header->frame_buffer; - uint32_t *end = p + (header->frame_buffer_size / sizeof(uint32_t)); - while (p < end) *p++ = header->rmask; + struct screen screen; + struct font font; + int status = 0; + + status = font_init(header->font, &font); + + status = screen_init( + header->frame_buffer, + header->hres, + header->vres, + header->rmask, + header->gmask, + header->bmask, + &screen); + + uint32_t color = header->gmask; + uint32_t perline = header->hres / font.width; + const char message[] = "Hello, I am text rendered by the kernel! :-D "; + for (int i=0; ihres * s->vres; + for (size_t i = 0; i < len; ++i) + s->data[i] = 0; + return 0; +} + +int +screen_init( + void *frame_buffer, + uint32_t hres, + uint32_t vres, + uint32_t rmask, + uint32_t gmask, + uint32_t bmask, + struct screen *s) +{ + s->data = frame_buffer; + s->hres = hres; + s->vres = vres; + s->rmask = rmask; + s->gmask = gmask; + s->bmask = bmask; + + return screen_fill(s, 0); +} + +int +screen_pixel( + struct screen *s, + uint32_t x, + uint32_t y, + uint32_t color) +{ + s->data[x + y*s->hres] = color; + return 0; +} diff --git a/src/modules/main/screen.h b/src/modules/main/screen.h new file mode 100644 index 0000000..e5708f1 --- /dev/null +++ b/src/modules/main/screen.h @@ -0,0 +1,30 @@ +#pragma once +#include +#include + +struct screen { + uint32_t *data; + uint32_t hres; + uint32_t vres; + uint32_t rmask; + uint32_t gmask; + uint32_t bmask; +}; + +int screen_init( + void *frame_buffer, + uint32_t hres, + uint32_t vres, + uint32_t rmask, + uint32_t gmask, + uint32_t bmask, + struct screen *s); + +int screen_fill(struct screen *s, uint32_t color); + +int screen_pixel( + struct screen *s, + uint32_t x, + uint32_t y, + uint32_t color); +