diff --git a/Makefile b/Makefile index a94d962..486c919 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ SOURCES = src/mem/heap/kheap.c src/mem/paging/vmm.c src/mem/paging/paging.c src/ build: rm -f *.o - x86_64-elf-gcc -g -c -Isrc $(SOURCES) -Wall -Wextra -std=gnu99 -nostdlib -ffreestanding -fno-stack-protector -fno-stack-check -fno-PIC -ffunction-sections -fdata-sections -mcmodel=kernel + x86_64-elf-gcc -g -c -Isrc $(SOURCES) -Wall -Wextra -std=gnu99 -nostdlib -ffreestanding -fno-stack-protector -fno-omit-frame-pointer -fno-stack-check -fno-PIC -ffunction-sections -fdata-sections -mcmodel=kernel objcopy -O elf64-x86-64 -B i386 -I binary zap-light16.psf zap-light16.o nasm -f elf64 src/idt/idt.S -o idt_stub.o x86_64-elf-ld -o pepperk -T linker.ld *.o diff --git a/src/idt/idt.c b/src/idt/idt.c index 7c59c64..c5094ce 100644 --- a/src/idt/idt.c +++ b/src/idt/idt.c @@ -185,13 +185,14 @@ struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context) break; case 32: - //DEBUG("Tick!"); + //DEBUG("Timer Interrupt"); ticks++; // Send an EOI so that we can continue having interrupts outb(0x20, 0x20); break; case 33: + DEBUG("Keyboard Interrupt"); keyboard_handler(); break; diff --git a/src/io/kbd/ps2.c b/src/io/kbd/ps2.c index d8b787a..df82811 100644 --- a/src/io/kbd/ps2.c +++ b/src/io/kbd/ps2.c @@ -201,12 +201,11 @@ void keyboard_handler() if (c) { + // Should probably have a keyboard buffer here... instead of this putchar(c); } } } - - skputs("key pressed!\n"); } // End of Interrupt (to master PIC) @@ -233,5 +232,11 @@ void keyboard_init(unsigned char layout) skputs("Unsupported layout."); return; } + + // Unmask IRQ1 + uint8_t mask = inb(0x21); + mask &= ~(1 << 1); + outb(0x21, mask); + DEBUG("PS/2 Keyboard initialized"); } \ No newline at end of file diff --git a/src/io/term/term.c b/src/io/term/term.c index 6ecb5b9..ae91835 100644 --- a/src/io/term/term.c +++ b/src/io/term/term.c @@ -23,71 +23,25 @@ uint8_t* glyphs = _binary_zap_light16_psf_start + sizeof(PSF1_Header); #define FONT_WIDTH 8 #define FONT_HEIGHT font->characterSize + + // Character cursor typedef struct { - unsigned int x; - unsigned int y; + size_t x; + size_t y; } Cursor; -Cursor cursor = {0}; +static Cursor cursor = {0, 0}; -unsigned char* fb; - -struct limine_framebuffer* framebuffer; +static uint8_t* fb; +static struct limine_framebuffer* framebuffer; uint8_t lines_length[MAX_LINES]; -int term_init() +static inline size_t term_max_cols(void) { - // Get framebuffer address from Limine struct - - if (boot_ctx.fb) - { - fb = boot_ctx.fb->address; - framebuffer = boot_ctx.fb; - DEBUG("terminal initialized, fb=0x%p (width=%u height=%u pitch=%u bpp=%u)", fb, framebuffer->width, framebuffer->height, framebuffer->pitch, framebuffer->bpp); - return 0; - } - return -ENOMEM; -} - -// These are marked "static" because we don't wanna expose them all around -// AKA they should just be seen here (kind of like private functions in cpp) -static void putpixel(int x, int y, int color) -{ - // Depth isn't part of limine_framebuffer attributes so it will be 4 - unsigned pos = x*4 + y*framebuffer->pitch; - fb[pos] = color & 255; // blue channel - fb[pos+1] = (color >> 8) & 255; // green - fb[pos+2] = (color >> 16) & 255; // blue -} - -static void draw_char(char c, int px, int py, int fg, int bg) -{ - uint8_t* glyph = glyphs + ((unsigned char)c * FONT_HEIGHT); - - for (size_t y=0; y> x)) ? fg : bg; - putpixel(px+x, py+y, color); - } - } -} - -static void erase_char(int px, int py) -{ - for (size_t y=0; ywidth / FONT_WIDTH; } static inline size_t term_max_lines(void) @@ -95,23 +49,80 @@ static inline size_t term_max_lines(void) return framebuffer->height / FONT_HEIGHT; } -void term_scroll() +int term_init() { - const size_t row_height = FONT_HEIGHT; - const size_t row_bytes = framebuffer->pitch; - const size_t screen_rows = framebuffer->height; - - // Move framebuffer up by one text row - //memmove(fb, fb + row_height * row_bytes, (screen_rows - row_height) * row_bytes); - - for (size_t i = 0; i < (screen_rows - row_height) * row_bytes; i++) + // Get framebuffer address from Limine struct + + if (!boot_ctx.fb) { - fb[i] = fb[i + row_height * row_bytes]; + return -ENOMEM; } - // Clear last text row - size_t clear_start = (screen_rows - row_height) * row_bytes; - memset(fb + clear_start, 0, row_height * row_bytes); + framebuffer = boot_ctx.fb; + fb = (uint8_t*)framebuffer->address; + + memset(lines_length, 0, sizeof(lines_length)); + + DEBUG("terminal initialized, fb=0x%p (width=%u height=%u pitch=%u bpp=%u)", fb, framebuffer->width, framebuffer->height, framebuffer->pitch, framebuffer->bpp); + return 0; +} + +// These are marked "static" because we don't wanna expose them all around +// AKA they should just be seen here (kind of like private functions in cpp) +static inline void putpixel(size_t x, size_t y, uint32_t color) +{ + // Guard so we don't write past fb boundaries + if (x >= framebuffer->width || y >= framebuffer->height) return; + // Depth isn't part of limine_framebuffer attributes so it will be 4 + size_t pos = x*4 + y*framebuffer->pitch; + fb[pos] = color & 255; // blue channel + fb[pos+1] = (color >> 8) & 255; // green + fb[pos+2] = (color >> 16) & 255; // blue +} + +static void draw_char(char c, size_t px, size_t py, uint32_t fg, uint32_t bg) +{ + // So we cannot write past fb + if (px+FONT_WIDTH > framebuffer->width || py+FONT_HEIGHT > framebuffer->height) return; + + uint8_t* glyph = glyphs + ((unsigned char)c * FONT_HEIGHT); + + for (size_t y=0; y> x)) ? fg : bg; + putpixel(px+x, py+y, color); + } + } +} + +static void erase_char(size_t px, size_t py) +{ + if (px+FONT_WIDTH > framebuffer->width || py+FONT_HEIGHT > framebuffer->height) return; + + for (size_t y=0; ypitch); + + // Move whole framebuffer up by one text line + memmove(fb, fb+(FONT_HEIGHT*framebuffer->pitch), (framebuffer->height-FONT_HEIGHT)*framebuffer->pitch); + + // Clear last text line + size_t clear_start = (framebuffer->height - FONT_HEIGHT) * framebuffer->pitch; + memset(fb + clear_start, 255, FONT_HEIGHT * framebuffer->pitch); // Shift line lengths by 1 (for backspace handling) size_t max_lines = term_max_lines(); @@ -119,73 +130,63 @@ void term_scroll() { lines_length[i - 1] = lines_length[i]; } - lines_length[max_lines - 1] = 0; - - if (cursor.y > 0) - { - cursor.y--; - } } - void putchar(char c) { - if ((c == '\n') && ((cursor.y+1)*FONT_HEIGHT >= framebuffer->height)) - { - term_scroll(); - return; - } + const size_t max_cols = term_max_cols(); + const size_t max_lines = term_max_lines(); - if (c == '\n') - { + if (c == '\n') { lines_length[cursor.y] = cursor.x; cursor.x = 0; - cursor.y++; + + if (cursor.y + 1 >= max_lines) + { + term_scroll(); + } + else + { + cursor.y++; + } return; } - // TODO: Improperly handled. - // When we're on an empty line it should get to the upper line's last character - // NOT just the last position possible; we would need to track the last line's character amount for that - if (c == '\b') + if (c == '\b') { - if (cursor.x == 0 && cursor.y == 0) + if (cursor.x > 0) + { + cursor.x--; + } + else if (cursor.y > 0) + { + cursor.y--; + cursor.x = lines_length[cursor.y]; + } + else { - // Top-left corner return; } - if (cursor.x == 0) - { - cursor.y--; - // cursor.x = (framebuffer->width / FONT_WIDTH) -1; // here - cursor.x = lines_length[cursor.y]; - } - else { - cursor.x--; - } - - int px = cursor.x * FONT_WIDTH; - int py = cursor.y * FONT_HEIGHT; - erase_char(px, py); + erase_char(cursor.x * FONT_WIDTH, cursor.y * FONT_HEIGHT); return; } - if ((cursor.x+1)*FONT_WIDTH >= framebuffer->width) + if (cursor.x >= max_cols) { cursor.x = 0; - cursor.y++; + if (cursor.y + 1 >= max_lines) + { + term_scroll(); + } + else + { + cursor.y++; + } } - if ((cursor.y+1)*FONT_HEIGHT >= framebuffer->height) - { - term_scroll(); - } - - int px = cursor.x * FONT_WIDTH; - int py = cursor.y * FONT_HEIGHT; - draw_char(c, px, py, WHITE, BLACK); + draw_char(c, cursor.x * FONT_WIDTH, cursor.y * FONT_HEIGHT, WHITE, BLACK); cursor.x++; } @@ -198,7 +199,7 @@ void _putchar(char character) // Debug-printing void kputs(const char* str) { - unsigned int i=0; + size_t i=0; while (str[i] != 0) { putchar(str[i]); diff --git a/src/io/term/term.h b/src/io/term/term.h index d525db4..e53981d 100644 --- a/src/io/term/term.h +++ b/src/io/term/term.h @@ -22,4 +22,7 @@ typedef struct uint8_t characterSize; // height } PSF1_Header; +// debug +void term_scroll(); + #endif diff --git a/src/kmain.c b/src/kmain.c index 73702df..a2b0812 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -118,11 +118,11 @@ void kmain() term_init(); kputs(splash); - for (int i=0; i<50; i++) + for (int i=0; i<10; i++) { printf("testing, attention please %d\n", i); - timer_wait(1000); } + // term_scroll(); hcf(); } diff --git a/src/time/timer.c b/src/time/timer.c index 07ede9e..a632a57 100644 --- a/src/time/timer.c +++ b/src/time/timer.c @@ -44,7 +44,7 @@ void pic_enable() // Enabling IRQ0 (unmasking it) but not the others uint8_t mask = inb(0x21); mask &= ~(1 << 0); // Set IRQ0 (timer, clear bit 0) - mask &= ~(1 << 1); // Set IRQ1 (PS/2 Keyboard, clear bit 1) + //mask &= ~(1 << 1); // Set IRQ1 (PS/2 Keyboard, clear bit 1) outb(0x21, mask); }