diff --git a/Makefile b/Makefile index c5fb472..4dd07fa 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,8 @@ LDFLAGS = DISK_IMG_FILES = build/kernel/kernel.bin hello.txt alpha.txt KERNEL_OBJS = build/kernel/entry.o build/kernel/screenstuff.o build/kernel/io.o build/kernel/idt.o build/kernel/keyboard.o \ build/kernel/strings.o build/kernel/atapio.o build/kernel/kernel.o build/kernel/paging.o build/kernel/allocate.o \ - build/kernel/gdt.o build/kernel/memory.o build/kernel/process.o build/kernel/datatypes/hash.o + build/kernel/gdt.o build/kernel/memory.o build/kernel/process.o build/kernel/datatypes/hash.o \ + build/kernel/terminal.o STAGE2_OBS = build/c_code_entry.o build/boot_stage2/io.o build/boot_stage2/atapio.o build/boot_stage2/strings.o build/boot_stage2/screenstuff.o build/boot_stage2/stage2.o build/boot_stage2/paging.o run: disk.img diff --git a/src/kernel/kernel.cpp b/src/kernel/kernel.cpp index 497ebbc..281f63d 100644 --- a/src/kernel/kernel.cpp +++ b/src/kernel/kernel.cpp @@ -12,6 +12,7 @@ #include "process.h" #include "global.h" #include "datatypes/hashtable.h" +#include "terminal.h" int main() { init_gdt(); @@ -24,17 +25,24 @@ int main() { PageMap phys_pm(0xc0600000); PageMap virt_pm(0xc0620000); - Allocator kernel_allocator = Allocator(&kernel_pd, &phys_pm, &virt_pm, 0xd0000000); - Global::allocator = &kernel_allocator; + Kernel kernel = Kernel(&kernel_pd, &phys_pm, &virt_pm, 0xd0000000); + Global::allocator = &kernel; - Process kernel_process = Process(0, &kernel_pd, &phys_pm, &virt_pm, 0xd0000000); - Global::allocator = &kernel_process; + Terminal* current_term; + + TextModeTerminal* term = new TextModeTerminal(0xc0501000); + current_term = term; init_idt(); - printf("Hello, World!\n\nWe are running XnoeOS Code in C++ now, Protected Mode has been achieved (as well as Virtual Memory / Paging!!!) and everything is working super nicely!\n\nHow wonderful!\n\nNow I just need to hope my print function works properly too~~\n"); + term->clear_screen(); + + term->printf("Hello, World!\n\nWe are running XnoeOS Code in C++ now, Protected Mode has been achieved (as well as Virtual Memory / Paging!!!) and everything is working super nicely!\n\nHow wonderful!\n\nNow I just need to hope my print function works properly too~~\n"); - printf("KERNEL OK!\n"); + term->printf("KERNEL OK!\n"); + term->activate(); + + while (1); init_keyboard(); diff --git a/src/kernel/screenstuff.cpp b/src/kernel/screenstuff.cpp index 4c7ab3c..0a75ed6 100644 --- a/src/kernel/screenstuff.cpp +++ b/src/kernel/screenstuff.cpp @@ -54,38 +54,6 @@ void set_curpos(int x, int y) { cursor_y = y; } -int int_to_decimal(unsigned int number, char* string_buffer) { - for (int i=0; i<11; i++) - string_buffer[i] = 0; - - int index = 9; - unsigned int acc = number; - if (acc == 0) - string_buffer[index--] = '0'; - while (acc != 0) { - string_buffer[index--] = 0x30+(acc%10); - acc /= 10; - } - return (index+1); -} - -char dec_to_hex[17] = "0123456789abcdef"; -int int_to_hex(unsigned int number, char* string_buffer) { - for (int i=0; i<8; i++) - string_buffer[i] = '0'; - string_buffer[8] = 0; - - int index = 7; - unsigned int acc = number; - if (acc == 0) - string_buffer[index--] = '0'; - while (acc != 0) { - string_buffer[index--] = dec_to_hex[acc%0x10]; - acc /= 0x10; - } - return (index+1); -} - void printf(const char* string, ...) { va_list ptr; va_start(ptr, string); diff --git a/src/kernel/screenstuff.h b/src/kernel/screenstuff.h index 15276fc..4042533 100644 --- a/src/kernel/screenstuff.h +++ b/src/kernel/screenstuff.h @@ -4,6 +4,7 @@ #include #include "types.h" #include "io.h" +#include "strings.h" uint16_t get_curpos(); void init_term(); @@ -11,8 +12,6 @@ void clear_screen(); void clear_line(int line); void set_curpos_raw(int curpos); void set_curpos(int x, int y); -int int_to_decimal(unsigned int number, char* string_buffer); -int int_to_hex(unsigned int number, char* string_buffer); void printf(const char* string, ...); void non_moving_put(char chr); diff --git a/src/kernel/strings.cpp b/src/kernel/strings.cpp index cc48b9f..3d4b851 100644 --- a/src/kernel/strings.cpp +++ b/src/kernel/strings.cpp @@ -66,4 +66,36 @@ void decode_filename(char* nice_name, char* filenamebuffer) { else filenamebuffer[fbIndex++] = nice_name[i]; } -} \ No newline at end of file +} + +int int_to_decimal(unsigned int number, char* string_buffer) { + for (int i=0; i<11; i++) + string_buffer[i] = 0; + + int index = 9; + unsigned int acc = number; + if (acc == 0) + string_buffer[index--] = '0'; + while (acc != 0) { + string_buffer[index--] = 0x30+(acc%10); + acc /= 10; + } + return (index+1); +} + +char dec_to_hex[17] = "0123456789abcdef"; +int int_to_hex(unsigned int number, char* string_buffer) { + for (int i=0; i<8; i++) + string_buffer[i] = '0'; + string_buffer[8] = 0; + + int index = 7; + unsigned int acc = number; + if (acc == 0) + string_buffer[index--] = '0'; + while (acc != 0) { + string_buffer[index--] = dec_to_hex[acc%0x10]; + acc /= 0x10; + } + return (index+1); +} diff --git a/src/kernel/strings.h b/src/kernel/strings.h index baf7c5c..8b9b051 100644 --- a/src/kernel/strings.h +++ b/src/kernel/strings.h @@ -8,4 +8,7 @@ char* split_on_first(char delimeter, char* string); int string_split(char delimeter, char* string, char** pointer_array); void decode_filename(char* nice_name, char* filenamebuffer); +int int_to_decimal(unsigned int number, char* string_buffer); +int int_to_hex(unsigned int number, char* string_buffer); + #endif \ No newline at end of file diff --git a/src/kernel/terminal.cpp b/src/kernel/terminal.cpp new file mode 100644 index 0000000..4170597 --- /dev/null +++ b/src/kernel/terminal.cpp @@ -0,0 +1,172 @@ +#include "terminal.h" + +void Terminal::scroll_up() { + // Scroll the entire buffer up. + for (int y = 0; y < (height * pages); y++) { + uint16_t* cline = y * width; + uint16_t* nline = (y+1) * width; + for (int x = 0; x < width; x++) { + cline[x] = nline[x]; + } + } + // Clear the last line + uint16_t* last_line = (height * pages - 1) * width; + for (int x = 0; x < width; x++) { + last_line[x] = 0x0720; + } + this->cur_y--; +} + +void Terminal::putchar(uint32_t ptr, uint8_t c, uint8_t edata) { + // All modifications to the screen are done to the last page. + last_page_pointer[ptr] = c | (edata<<8); + + if (active) + putchar_internal(ptr, c, edata); +} + +void Terminal::update(){} +void Terminal::update_cur(){} +void Terminal::putchar_internal(uint32_t ptr, uint8_t c, uint8_t edata) {} + +Terminal::Terminal(uint32_t width, uint32_t height, uint32_t pages) { + this->width = width; + this->height = height; + this->pages = pages; + this->buffer = new uint16_t[width * height * pages]; + this->last_page_pointer = buffer + (width * height * pages) - (width * height); + this->current_page_pointer = last_page_pointer; + + this->cur_x = 0; + this->cur_y = 0; + + this->active = false; +} + +void Terminal::printf(const char* string, ...) { + va_list ptr; + va_start(ptr, string); + + int index = 0; + char current; + + while (current=string[index++]) { + if (current == '\n') { + this->cur_x = 0; + this->cur_y++; + } + + if (this->cur_x == this->width) { + this->cur_x = 0; + this->cur_y++; + } + + if (this->cur_y == this->height) + this->scroll_up(); + + if (current == '%') { + int type = string[index++]; + int offset; + switch (type) { + case 'd': { + char decimal_buffer[11]; + offset = int_to_decimal(va_arg(ptr, int), decimal_buffer); + printf(decimal_buffer + offset); + break; + } + case 'x': { + char hex_buffer[8]; + offset = int_to_hex(va_arg(ptr, int), hex_buffer); + printf(hex_buffer); + break; + } + case 's': { + printf(va_arg(ptr, const char*)); + break; + } + case 'c': { + int mem_pos = this->cur_y * this->width + this->cur_x++; + int promoted = va_arg(ptr, int); + char charred = promoted; + + this->putchar(mem_pos, charred); + break; + } + } + continue; + } + + if (current != '\n') { + int mem_pos = this->cur_y * this->width + this->cur_x++; + + this->putchar(mem_pos, current); + } + } + + this->set_curpos(this->cur_x, this->cur_y); + + va_end(ptr); +} + +void Terminal::clear_screen() { + for (int i=0; i < width * height * pages; i++) { + buffer[i] = 0; + } + this->cur_x = 0; + this->cur_y = 0; + + if (active) + this->update(); +} + +void Terminal::set_curpos(int x, int y) { + this->cur_x = x; + this->cur_y = y; + + if (active) + this->update_cur(); +} + +uint32_t Terminal::get_cur_x() { + return this->cur_x; +} + +uint32_t Terminal::get_cur_y() { + return this->cur_y; +} + +void Terminal::activate() { + update(); + this->active = true; +} + +void Terminal::deactivate() { + this->active = false; +} + +void TextModeTerminal::update() { + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + text_mode_pointer[y * width + x] = current_page_pointer[y * width + x]; + } + } + + this->update_cur(); +} + +void TextModeTerminal::update_cur() { + int cursor_position = this->cur_y * this->width + this->cur_x; + uint8_t* cursor_position_split = (uint8_t*)&cursor_position; + outb(0x3D4, 0x0F); + outb(0x3D5, cursor_position_split[0]); + outb(0x3D4, 0x0E); + outb(0x3D5, cursor_position_split[1]); +} + +void TextModeTerminal::putchar_internal(uint32_t ptr, uint8_t c, uint8_t edata) { + text_mode_pointer[ptr] = c | (edata << 8); +} + +TextModeTerminal::TextModeTerminal(uint16_t* text_mode_pointer): Terminal(80, 25, 1) { + this->text_mode_pointer = text_mode_pointer; +} \ No newline at end of file diff --git a/src/kernel/terminal.h b/src/kernel/terminal.h new file mode 100644 index 0000000..4f8ecd2 --- /dev/null +++ b/src/kernel/terminal.h @@ -0,0 +1,60 @@ +#ifndef TERMINAL_H +#define TERMINAL_H + +#include + +#include "datatypes/tuple.h" +#include "types.h" +#include "strings.h" +#include "io.h" + +class Terminal { +private: + virtual void update(); + virtual void update_cur(); + virtual void putchar_internal(uint32_t ptr, uint8_t c, uint8_t edata=0x07); + + void scroll_up(); + + void putchar(uint32_t ptr, uint8_t c, uint8_t edata=0x07); + +protected: + uint16_t* buffer; + uint32_t width; + uint32_t height; + uint32_t pages; + + uint32_t cur_x; + uint32_t cur_y; + + uint16_t* current_page_pointer; + uint16_t* last_page_pointer; + + bool active; +public: + Terminal(uint32_t width, uint32_t height, uint32_t pages); + + void printf(const char* string, ...); + + void clear_screen(); + void set_curpos(int x, int y); + + uint32_t get_cur_x(); + uint32_t get_cur_y(); + + void activate(); + void deactivate(); +}; + +class TextModeTerminal : public Terminal { +private: + void update() override; + void update_cur() override; + void putchar_internal(uint32_t ptr, uint8_t c, uint8_t edata=0x07) override; + + uint16_t* text_mode_pointer; +public: + TextModeTerminal(uint16_t* text_mode_pointer); +}; + +#endif \ No newline at end of file