Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //---------------------------------------- Include headers ----------------------------------------
- #include <stdint.h>
- #include <stddef.h>
- #include <stdbool.h>
- #include <stdlib.h>
- //-------------------------------------------------------------------------------------------------
- //---------------------------------------- Variables ----------------------------------------------
- static bool shift_pressed = false;
- static const size_t VGA_WIDTH = 80;
- static const size_t VGA_HEIGHT = 25;
- size_t terminal_column;
- size_t terminal_row;
- uint8_t terminal_color;
- uint16_t* terminal_buffer;
- //-------------------------------------------------------------------------------------------------
- //--------------------------------------- VGA colors ----------------------------------------------
- // Declare VGA colors
- enum vga_color {
- BLACK = 0,
- GREEN = 1,
- BLUE = 2,
- CYAN = 3,
- RED = 4,
- MAGENTA = 5,
- BROWN = 6,
- LIGHT_GREY = 7,
- GREY = 8,
- LIGHT_GREEN = 9,
- LIGHT_BLUE = 10,
- LIGHT_CYAN = 11,
- LIGHT_RED = 12,
- LIGHT_MAGENTA = 13,
- YELLOW = 14,
- WHITE = 15,
- };
- //-----------------------------------------------------------------------------------------------------
- //------------------------------------------ Keycode --------------------------------------------------
- // Define keyboard port
- #define KEYBOARD_PORT 0x60
- // Define keys
- #define KEY_A 0x1E
- #define KEY_B 0x30
- #define KEY_C 0x2E
- #define KEY_D 0x20
- #define KEY_E 0x12
- #define KEY_F 0x21
- #define KEY_G 0x22
- #define KEY_H 0x23
- #define KEY_I 0x17
- #define KEY_J 0x24
- #define KEY_K 0x25
- #define KEY_L 0x26
- #define KEY_M 0x32
- #define KEY_N 0x31
- #define KEY_O 0x18
- #define KEY_P 0x19
- #define KEY_Q 0x10
- #define KEY_R 0x13
- #define KEY_S 0x1F
- #define KEY_T 0x14
- #define KEY_U 0x16
- #define KEY_V 0x2F
- #define KEY_W 0x11
- #define KEY_X 0x2D
- #define KEY_Y 0x15
- #define KEY_Z 0x2C
- #define KEY_1 0x02
- #define KEY_2 0x03
- #define KEY_3 0x04
- #define KEY_4 0x05
- #define KEY_5 0x06
- #define KEY_6 0x07
- #define KEY_7 0x08
- #define KEY_8 0x09
- #define KEY_9 0x0A
- #define KEY_0 0x0B
- #define KEY_MINUS 0x0C
- #define KEY_EQUAL 0x0D
- #define KEY_SQUARE_OPEN_BRACKET 0x1A
- #define KEY_SQUARE_CLOSE_BRACKET 0x1B
- #define KEY_SEMICOLON 0x27
- #define KEY_BACKSLASH 0x2B
- #define KEY_COMMA 0x33
- #define KEY_DOT 0x34
- #define KEY_FORESLHASH 0x35
- #define KEY_F1 0x3B
- #define KEY_F2 0x3C
- #define KEY_F3 0x3D
- #define KEY_F4 0x3E
- #define KEY_F5 0x3F
- #define KEY_F6 0x40
- #define KEY_F7 0x41
- #define KEY_F8 0x42
- #define KEY_F9 0x43
- #define KEY_F10 0x44
- #define KEY_F11 0x85
- #define KEY_F12 0x86
- #define KEY_BACKSPACE 0x0E
- #define KEY_DELETE 0x53
- #define KEY_DOWN 0x50
- #define KEY_END 0x4F
- #define KEY_ENTER 0x1C
- #define KEY_ESC 0x01
- #define KEY_HOME 0x47
- #define KEY_INSERT 0x52
- #define KEY_KEYPAD_5 0x4C
- #define KEY_KEYPAD_MUL 0x37
- #define KEY_KEYPAD_Minus 0x4A
- #define KEY_KEYPAD_PLUS 0x4E
- #define KEY_KEYPAD_DIV 0x35
- #define KEY_LEFT 0x4B
- #define KEY_PAGE_DOWN 0x51
- #define KEY_PAGE_UP 0x49
- #define KEY_PRINT_SCREEN 0x37
- #define KEY_RIGHT 0x4D
- #define KEY_SPACE 0x39
- #define KEY_TAB 0x0F
- #define KEY_UP 0x48
- #define KEY_SHIFT_HOLD 0x2A
- #define KEY_SHIFT_RELEASE 0xAA
- #define LEFT_MOUSE_BUTTON 0x0001
- char get_ascii_char(uint8_t key_code)
- {
- switch(key_code){
- case KEY_A : return 'a';
- case KEY_B : return 'b';
- case KEY_C : return 'c';
- case KEY_D : return 'd';
- case KEY_E : return 'e';
- case KEY_F : return 'f';
- case KEY_G : return 'g';
- case KEY_H : return 'h';
- case KEY_I : return 'i';
- case KEY_J : return 'j';
- case KEY_K : return 'k';
- case KEY_L : return 'l';
- case KEY_M : return 'm';
- case KEY_N : return 'n';
- case KEY_O : return 'o';
- case KEY_P : return 'p';
- case KEY_Q : return 'q';
- case KEY_R : return 'r';
- case KEY_S : return 's';
- case KEY_T : return 't';
- case KEY_U : return 'u';
- case KEY_V : return 'v';
- case KEY_W : return 'w';
- case KEY_X : return 'x';
- case KEY_Y : return 'y';
- case KEY_Z : return 'z';
- case KEY_1 : return '1';
- case KEY_2 : return '2';
- case KEY_3 : return '3';
- case KEY_4 : return '4';
- case KEY_5 : return '5';
- case KEY_6 : return '6';
- case KEY_7 : return '7';
- case KEY_8 : return '8';
- case KEY_9 : return '9';
- case KEY_0 : return '0';
- case KEY_MINUS : return '-';
- case KEY_EQUAL : return '=';
- case KEY_SQUARE_OPEN_BRACKET : return '[';
- case KEY_SQUARE_CLOSE_BRACKET : return ']';
- case KEY_SEMICOLON : return ';';
- case KEY_BACKSLASH : return '\\';
- case KEY_COMMA : return ',';
- case KEY_DOT : return '.';
- case KEY_FORESLHASH : return '/';
- case KEY_SPACE : return ' ';
- case KEY_ENTER : return '\n';
- case KEY_BACKSPACE: return '\b';
- default : return 0;
- }
- }
- char get_ascii_shift_char(uint8_t key_code)
- {
- switch(key_code){
- case KEY_A : return 'A';
- case KEY_B : return 'B';
- case KEY_C : return 'C';
- case KEY_D : return 'D';
- case KEY_E : return 'E';
- case KEY_F : return 'F';
- case KEY_G : return 'G';
- case KEY_H : return 'H';
- case KEY_I : return 'I';
- case KEY_J : return 'J';
- case KEY_K : return 'K';
- case KEY_L : return 'L';
- case KEY_M : return 'M';
- case KEY_N : return 'N';
- case KEY_O : return 'O';
- case KEY_P : return 'P';
- case KEY_Q : return 'Q';
- case KEY_R : return 'R';
- case KEY_S : return 'S';
- case KEY_T : return 'T';
- case KEY_U : return 'U';
- case KEY_V : return 'V';
- case KEY_W : return 'W';
- case KEY_X : return 'X';
- case KEY_Y : return 'Y';
- case KEY_Z : return 'Z';
- case KEY_1 : return '!';
- case KEY_2 : return '@';
- case KEY_3 : return '#';
- case KEY_4 : return '$';
- case KEY_5 : return '%';
- case KEY_6 : return '^';
- case KEY_7 : return '&';
- case KEY_8 : return '*';
- case KEY_9 : return '(';
- case KEY_0 : return ')';
- case KEY_MINUS : return '_';
- case KEY_EQUAL : return '+';
- case KEY_SQUARE_OPEN_BRACKET : return '{';
- case KEY_SQUARE_CLOSE_BRACKET : return '}';
- case KEY_SEMICOLON : return ':';
- case KEY_BACKSLASH : return '|';
- case KEY_COMMA : return '<';
- case KEY_DOT : return '>';
- case KEY_FORESLHASH : return '/';
- case KEY_SPACE : return ' ';
- case KEY_ENTER : return '\n';
- case KEY_BACKSPACE: return '\b';
- default : return 0;
- }
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------- VGA ------------------------------------------------
- static inline uint8_t vga_entry_color(enum vga_color fg, enum vga_color bg)
- {
- return fg | bg << 4;
- }
- static inline uint16_t vga_entry(unsigned char uc, uint8_t color)
- {
- return (uint16_t) uc | (uint16_t) color << 8;
- }
- //----------------------------------------------------------------------------------------------------
- //-------------------------------------------- Sundry functions --------------------------------------
- size_t strlen(const char* data)
- {
- size_t len = 0;
- while (data[len])
- {
- len++;
- }
- return len;
- }
- void sleep(uint32_t time)
- {
- while (true)
- {
- asm volatile("nop");
- time--;
- if (time <= 0)
- break;
- }
- }
- //----------------------------------------------------------------------------------------------------
- //-------------------------------------------- Struct Stack -------------------------------------------------
- typedef uint16_t* item;
- typedef struct Stack
- {
- struct Node *Top;
- };
- struct Node
- {
- item Data;
- struct Node *Next;
- };
- void Init(struct Stack S);
- int Isempty(struct Stack S);
- int Len(struct Stack S);
- void Push(struct Stack S, item x);
- item Peak(struct Stack S);
- item Pop(struct Stack S);
- struct Node *MakeNode(item x);
- void Init(struct Stack S)
- {
- S.Top = NULL;
- }
- int Isempty(struct Stack S)
- {
- return (S.Top == NULL);
- }
- int Len(struct Stack S)
- {
- struct Node *P = S.Top;
- int i = 0;
- while (P != NULL)
- {
- i++;
- P = P -> Next;
- }
- return i;
- }
- struct Node *MakeNode(item x)
- {
- struct Node *P = (struct Node*) malloc(sizeof(struct Node));
- P->Next = NULL;
- P->Data = x;
- return P;
- }
- item Peak(struct Stack S)
- {
- return S.Top->Data;
- }
- item Pop(struct Stack S)
- {
- if (!Isempty(S))
- {
- item x = S.Top->Data;
- S.Top = S.Top->Next;
- return x;
- }
- }
- //----------------------------------------------------------------------------------------------------
- //-------------------------------------------- Screen ------------------------------------------------
- void init(void)
- {
- terminal_column = 0;
- terminal_row = 0;
- terminal_color = vga_entry_color(LIGHT_GREY, BLACK);
- terminal_buffer = (uint16_t*) 0xB8000;
- for (size_t y = 0; y < VGA_HEIGHT; y++) {
- for (size_t x = 0; x < VGA_WIDTH; x++) {
- const size_t index = y * VGA_WIDTH + x;
- terminal_buffer[index] = vga_entry(' ', terminal_color);
- }
- }
- }
- void clear_screen()
- {
- for (size_t y = 0; y < VGA_HEIGHT; y++) {
- for (size_t x = 0; x < VGA_WIDTH; x++) {
- const size_t index = y * VGA_WIDTH + x;
- terminal_buffer[index] = vga_entry(' ', terminal_color);
- }
- }
- }
- void set_color(uint8_t color)
- {
- terminal_color = color;
- }
- //-------------------------------------------------------------------------------------------------
- //--------------------------------------- Print --------------------------------------------------
- void putentryat(char c, uint8_t color, size_t x, size_t y)
- {
- const size_t index = y * VGA_WIDTH + x;
- terminal_buffer[index] = vga_entry(c, color);
- }
- void putchar(char c)
- {
- putentryat(c, terminal_color, terminal_column, terminal_row);
- if (++terminal_column == VGA_WIDTH) {
- terminal_column = 0;
- if (++terminal_row == VGA_HEIGHT) {
- screen_scrolling_up();
- }
- }
- }
- void write(const char* data, size_t len)
- {
- for (size_t i = 0; i < len; i++) {
- switch (data[i])
- {
- case '\n': {
- terminal_column = 0;
- terminal_row += 1;
- };
- case '\t': {
- terminal_column += 4;
- if (terminal_column > VGA_WIDTH) {
- size_t modulo = terminal_column % VGA_WIDTH;
- terminal_column = 0;
- terminal_column += modulo;
- terminal_row += 1;
- }
- };
- case '\0': putchar('0');
- case '\b': {
- const size_t index = terminal_row * VGA_WIDTH + terminal_column;
- terminal_buffer[index - 1] = vga_entry(' ', terminal_color);
- terminal_column -= 1;
- };
- default:
- putchar(data[i]);
- }
- }
- }
- void print(const char* data)
- {
- write(data, strlen(data));
- }
- //-------------------------------------------------------------------------------------------------
- //------------------------------------------- Scancode --------------------------------------------
- uint8_t inb(uint16_t port)
- {
- uint8_t ret;
- asm volatile("inb %1, %0" : "=a"(ret) : "d"(port));
- return ret;
- }
- void outb(uint16_t port, uint8_t data)
- {
- asm volatile("outb %0, %1" : "=a"(data) : "d"(port));
- }
- char get_input_keycode()
- {
- char ch = 0;
- while (( ch = inb(KEYBOARD_PORT)) != 0)
- if (ch > 0)
- return ch;
- return ch;
- }
- void shift_scancode()
- {
- char ch = 0;
- char keycode = 0;
- bool check = true;;
- do {
- keycode = get_input_keycode();
- if (keycode == KEY_ENTER){
- terminal_column = 0;
- terminal_row += 1;
- } else if (keycode == KEY_BACKSPACE) {
- const size_t index = terminal_row * VGA_WIDTH + terminal_column;
- terminal_buffer[index - 1] = vga_entry(' ', terminal_color);
- terminal_column -= 1;
- } else if (keycode == KEY_TAB) {
- terminal_column += 4;
- if (terminal_column > VGA_WIDTH) {
- size_t modulo = terminal_column % VGA_WIDTH;
- terminal_column = 0;
- terminal_column += modulo;
- terminal_row += 1;
- }
- } else if (keycode == KEY_SHIFT_RELEASE) {
- print("Release shift");
- } else if (keycode == KEY_UP) {
- screen_scrolling_down();
- } else if (keycode == KEY_DOWN) {
- screen_scrolling_up_when_press();
- } else {
- ch = get_ascii_shift_char(keycode);
- putchar(ch);
- check = false;
- }
- sleep(0x02FFFFFF);
- } while (check == true);
- }
- void test_input()
- {
- char ch = 0;
- char keycode = 0;
- do{
- keycode = get_input_keycode();
- if (keycode == KEY_ENTER){
- terminal_column = 0;
- terminal_row += 1;
- } else if (keycode == KEY_BACKSPACE) {
- const size_t index = terminal_row * VGA_WIDTH + terminal_column;
- terminal_buffer[index - 1] = vga_entry(' ', terminal_color);
- terminal_column -= 1;
- } else if (keycode == KEY_TAB) {
- terminal_column += 4;
- if (terminal_column > VGA_WIDTH) {
- size_t modulo = terminal_column % VGA_WIDTH;
- terminal_column = 0;
- terminal_column += modulo;
- terminal_row += 1;
- }
- } else if (keycode == KEY_SHIFT_HOLD) {
- shift_scancode();
- } else {
- ch = get_ascii_char(keycode);
- putchar(ch);
- }
- sleep(0x02FFFFFF);
- } while(keycode != KEY_ENTER);
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------- Screen handler -------------------------------------------
- static struct Stack stack_first_line;
- static struct Stack stack_last_line;
- void screen_scrolling_up();
- void screen_scrolling_down();
- void load_fisrt_line();
- void load_last_line();
- void screen_scrolling_up()
- {
- Init(stack_first_line);
- terminal_column = 0;
- terminal_row = 24;
- item new_buffer = (item) 0xB8000;
- for (size_t x = 0; x < VGA_WIDTH; x++)
- {
- new_buffer[x] = terminal_buffer[x];
- }
- Push(stack_first_line, new_buffer);
- for (size_t y = 1; y < VGA_HEIGHT; y++) {
- for (size_t x = 0; x < VGA_WIDTH; x++) {
- const size_t current_index = y * VGA_WIDTH + x;
- const size_t new_index = (y - 1) * VGA_WIDTH + x;
- terminal_buffer[new_index] = terminal_buffer[current_index];
- terminal_buffer[current_index] = vga_entry(' ', terminal_color);
- }
- }
- for (size_t x = 0; x < VGA_WIDTH; x++) {
- const size_t index = 24 * VGA_WIDTH + x;
- terminal_buffer[index] = vga_entry(' ', terminal_color);
- }
- }
- void screen_scrolling_up_when_press()
- {
- Init(stack_first_line);
- terminal_column = 0;
- terminal_row = 24;
- item new_buffer = (item) 0xB8000;
- for (size_t x = 0; x < VGA_WIDTH; x++)
- {
- new_buffer[x] = terminal_buffer[x];
- }
- Push(stack_first_line, new_buffer);
- for (size_t y = 1; y < VGA_HEIGHT; y++) {
- for (size_t x = 0; x < VGA_WIDTH; x++) {
- const size_t current_index = y * VGA_WIDTH + x;
- const size_t new_index = (y - 1) * VGA_WIDTH + x;
- terminal_buffer[new_index] = terminal_buffer[current_index];
- terminal_buffer[current_index] = vga_entry(' ', terminal_color);
- }
- }
- for (size_t x = 0; x < VGA_WIDTH; x++) {
- const size_t index = 24 * VGA_WIDTH + x;
- terminal_buffer[index] = vga_entry(' ', terminal_color);
- }
- load_last_line();
- }
- void screen_scrolling_down()
- {
- Init(stack_last_line);
- terminal_column = 0;
- terminal_row -= 1;
- item new_buffer = (item) 0xB8000;
- for (size_t column = 1920; column < 2000; column++)
- new_buffer[column] = terminal_buffer[column];
- Push(stack_last_line, new_buffer);
- for (size_t y = 0; y < VGA_HEIGHT - 1; y++) {
- for (size_t x = 0; x < VGA_WIDTH; x++) {
- const size_t current_index = y * VGA_WIDTH + x;
- const size_t new_index = (y + 1) * VGA_WIDTH + x;
- terminal_buffer[new_index] = terminal_buffer[current_index];
- terminal_buffer[current_index] = vga_entry(' ', terminal_color);
- }
- }
- for (size_t x = 0; x < VGA_WIDTH; x++) {
- const size_t index = 0 * VGA_WIDTH + x;
- terminal_buffer[index] = vga_entry(' ', terminal_color);
- }
- load_fisrt_line();
- }
- void load_first_line()
- {
- item new_buffer = (item) 0xB8000;
- new_buffer = Pop(stack_first_line);
- for (size_t index = 0; index < VGA_WIDTH; index++)
- terminal_buffer[index] = new_buffer[index];
- }
- void load_last_line()
- {
- item new_buffer = (item) 0xB8000;
- new_buffer = Pop(stack_last_line);
- for (size_t index = 1920; index < VGA_WIDTH * VGA_HEIGHT; index++)
- terminal_buffer[index] = new_buffer[index];
- }
- //-------------------------------------------------------------------------------------------------
- //------------------------------------------- Kernel ----------------------------------------------
- void kernel_main(void)
- {
- init();
- bool ch = false;
- print("Hello World!");
- test_input();
- print("Hello World!");
- while (ch == false) {
- print("I'm awesome");
- sleep(80000000);;
- }
- screen_scrolling_up();
- }
- //-------------------------------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment