diff --git a/.cache/clangd/index/kernel.c.FE151BF4CBB915EA.idx b/.cache/clangd/index/kernel.c.FE151BF4CBB915EA.idx new file mode 100644 index 0000000..3a24778 Binary files /dev/null and b/.cache/clangd/index/kernel.c.FE151BF4CBB915EA.idx differ diff --git a/.cache/clangd/index/kernel.h.676073B795F16327.idx b/.cache/clangd/index/kernel.h.676073B795F16327.idx new file mode 100644 index 0000000..2ebc287 Binary files /dev/null and b/.cache/clangd/index/kernel.h.676073B795F16327.idx differ diff --git a/.cache/clangd/index/stdio.c.7FE59D9FB18A0627.idx b/.cache/clangd/index/stdio.c.7FE59D9FB18A0627.idx new file mode 100644 index 0000000..0201e82 Binary files /dev/null and b/.cache/clangd/index/stdio.c.7FE59D9FB18A0627.idx differ diff --git a/.cache/clangd/index/stdio.h.CF376A49F2DCDC41.idx b/.cache/clangd/index/stdio.h.CF376A49F2DCDC41.idx new file mode 100644 index 0000000..68ac610 Binary files /dev/null and b/.cache/clangd/index/stdio.h.CF376A49F2DCDC41.idx differ diff --git a/.cache/clangd/index/stdmem.h.7AEBD514FE5F79BC.idx b/.cache/clangd/index/stdmem.h.7AEBD514FE5F79BC.idx new file mode 100644 index 0000000..6787354 Binary files /dev/null and b/.cache/clangd/index/stdmem.h.7AEBD514FE5F79BC.idx differ diff --git a/.cache/clangd/index/types.h.5A82B4661D1C2FCC.idx b/.cache/clangd/index/types.h.5A82B4661D1C2FCC.idx new file mode 100644 index 0000000..dca9d35 Binary files /dev/null and b/.cache/clangd/index/types.h.5A82B4661D1C2FCC.idx differ diff --git a/.gitignore b/.gitignore index 819a294..5ed3a9f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ *.elf *.map +compile_commands.json diff --git a/build.sh b/build.sh index cbd4ccc..b6603f6 100755 --- a/build.sh +++ b/build.sh @@ -14,6 +14,32 @@ BLUE='\033[0;34m' YELLOW='\033[1;33m' NC='\033[0m' +# Shared compiler flags (single source of truth for both real compiles AND compile_commands.json) +CFLAGS="-ffreestanding -mcmodel=large -mno-red-zone -fno-pic -fno-pie -static -fno-stack-protector -nostdlib -mno-mmx -mno-sse -mno-sse2 -m64" +INCLUDE="-I./include" + +# compile_commands.json setup (for clangd/nvim LSP support) +CCJ_OUTPUT="compile_commands.json" +PROJECT_DIR="$(pwd)" + +append_ccj_entry() { + local src_file="$1" + local full_cmd="$2" + if [ "$ccj_first" = true ]; then + ccj_first=false + else + echo "," >> "$CCJ_OUTPUT" + fi + printf ' {\n' >> "$CCJ_OUTPUT" + printf ' "directory": "%s",\n' "$PROJECT_DIR" >> "$CCJ_OUTPUT" + printf ' "file": "%s",\n' "$src_file" >> "$CCJ_OUTPUT" + printf ' "command": "%s"\n' "$full_cmd" >> "$CCJ_OUTPUT" + printf ' }' >> "$CCJ_OUTPUT" +} + +echo "[" > "$CCJ_OUTPUT" +ccj_first=true + # Prepare build environment echo -e "Preparing build environment...${NC}" echo -e "Creating Folders${NC}" @@ -21,22 +47,45 @@ mkdir -p bin obj boot include echo -e "${GREEN}✓${NC} Folders created.${NC}" # Step 1: Assemble Stage 1 bootloader (MBR - 512 bytes) -echo -e "${BLUE}[1/6]${NC} Assembling Stage 1 bootloader (MBR)..." +echo -e "${BLUE}[1/7]${NC} Assembling Stage 1 bootloader (MBR)..." nasm -f bin ./boot/boot.asm -o ./bin/boot.bin +# Step 1.5: Compile C source files +echo -e "${BLUE}[2/7]${NC} Compiling C source files..." +COUNT=$(ls src/*.c 2>/dev/null | wc -l) +if [ "$COUNT" -eq 0 ]; then + echo -e "${YELLOW}No C source files found in src/. Skipping compilation.${NC}" +else +COUNTER=1 + for file in src/*.c; do + echo -e "${BLUE}[$COUNTER/$COUNT]${NC} Compiling $file..." + ((COUNTER++)) + name=$(basename "$file") + gcc $CFLAGS $INCLUDE -c "$file" -o "obj/${name}.o" + append_ccj_entry "$file" "gcc $CFLAGS $INCLUDE -c $file -o obj/${name}.o" + done + echo -e "${GREEN}✓${NC} C source files compiled.${NC}" +fi + + # Step 2: Compile kernel C code -echo -e "${BLUE}[2/6]${NC} Compiling kernel..." -gcc -ffreestanding -c kernel.c -o ./obj/kernel.c.o -mcmodel=large -mno-red-zone -fno-pic -fno-pie -static -fno-stack-protector -nostdlib -mno-mmx -mno-sse -mno-sse2 -m64 +echo -e "${BLUE}[3/7]${NC} Compiling kernel..." +gcc $CFLAGS $INCLUDE -c kernel.c -o ./obj/kernel.c.o +append_ccj_entry "kernel.c" "gcc $CFLAGS $INCLUDE -c kernel.c -o ./obj/kernel.c.o" + +# Close compile_commands.json now that all C compiling is done +echo "" >> "$CCJ_OUTPUT" +echo "]" >> "$CCJ_OUTPUT" # Step 3: Assemble kernel entry point -echo -e "${BLUE}[3/6]${NC} Assembling kernel entry..." +echo -e "${BLUE}[4/7]${NC} Assembling kernel entry..." nasm -f elf64 ./boot/kernel.asm -o ./obj/kernel.asm.o # Step 4: Link kernel -echo -e "${BLUE}[4/6]${NC} Linking kernel..." -ld -T linker.ld -o ./bin/kernel.bin ./obj/kernel.asm.o ./obj/kernel.c.o --oformat binary --nostdlib +echo -e "${BLUE}[5/7]${NC} Linking kernel..." +ld -T linker.ld -o ./bin/kernel.bin ./obj/*.o --oformat binary --nostdlib # Debug build (optional) -ld -T linker.ld -o ./bin/kernel_debug.elf ./obj/kernel.asm.o ./obj/kernel.c.o --oformat elf64-x86-64 --nostdlib +ld -T linker.ld -o ./bin/kernel_debug.elf ./obj/*.o --oformat elf64-x86-64 --nostdlib # Step 4.5: Calculate kernel size in sectors KERNEL_SIZE=$(stat -f%z ./bin/kernel.bin 2>/dev/null || stat -c%s ./bin/kernel.bin 2>/dev/null) @@ -44,16 +93,18 @@ SECTORS=$(( (KERNEL_SIZE + 511) / 512 )) #Round up to nearest sector echo -e "${YELLOW}Kernel size: ${KERNEL_SIZE} bytes, which is ${SECTORS} sectors.${NC}" # Step 5: Assemble Stage 2 bootloader (extended loader) -echo -e "${BLUE}[5/6]${NC} Assembling Stage 2 bootloader..." +echo -e "${BLUE}[6/7]${NC} Assembling Stage 2 bootloader..." nasm -f bin ./boot/elevator.asm -D KERNEL_SECTORS=$SECTORS -o ./bin/elevator.bin # Step 6: Create OS image -echo -e "${BLUE}[6/6]${NC} Creating OS image..." +echo -e "${BLUE}[7/7]${NC} Creating OS image..." cat ./bin/boot.bin ./bin/elevator.bin ./bin/kernel.bin > os.bin # Pad to floppy size (1.44MB) # FIX: Uncomment the line below if you want to ensure the image is exactly 1.44MB -#truncate -s 1440K os.bin +truncate -s 1440K os.bin + + echo "" echo -e "${GREEN}✓ Build complete!${NC}" @@ -83,5 +134,4 @@ echo "" qemu-system-x86_64 -drive format=raw,file=os.bin -no-reboot - echo -e "${GREEN}Done!${NC}" diff --git a/kernel.h b/include/kernel.h similarity index 100% rename from kernel.h rename to include/kernel.h diff --git a/include/stdio.h b/include/stdio.h new file mode 100644 index 0000000..8077ad2 --- /dev/null +++ b/include/stdio.h @@ -0,0 +1,126 @@ +#ifndef COLORS_H +#define COLORS_H + +#include "stdmem.h" +#include "types.h" + +#include +#include +#include + +#define VGA_WIDTH 80 +#define VGA_HEIGHT 25 + +#define VGA_MEMORY_ADDRESS 0xB8000 + +/* + * FOR INPUT + */ + +#define KEYBOARD_BUFFER_SIZE 256 + +#define SCANCODE_LSHIFT 0x2A +#define SCANCODE_RSHIFT 0x36 +#define SCANCODE_CAPSLOCK 0x3A +#define RELEASE_MASK 0x80 + +static volatile unsigned char _keyboard_buffer[KEYBOARD_BUFFER_SIZE]; +static volatile uint16_t _kb_head = 0; +static volatile uint16_t _kb_tail = 0; + +static char __g_shift_pressed = 0; +static char __g_caps_lock_active = 0; + +// C99 Designated Initializers for Unshifted ASCII Characters +static const char scancode_ascii_unshifted[128] = { + [0x01] = 27, // ESC + [0x02] = '1', [0x03] = '2', [0x04] = '3', [0x05] = '4', [0x06] = '5', [0x07] = '6', [0x08] = '7', [0x09] = '8', [0x0A] = '9', [0x0B] = '0', [0x0C] = '-', + [0x0D] = '=', [0x0E] = '\b', // Backspace + [0x0F] = '\t', // Tab + [0x10] = 'q', [0x11] = 'w', [0x12] = 'e', [0x13] = 'r', [0x14] = 't', [0x15] = 'y', [0x16] = 'u', [0x17] = 'i', [0x18] = 'o', [0x19] = 'p', [0x1A] = '[', + [0x1B] = ']', [0x1C] = '\n', // Enter + [0x1E] = 'a', [0x1F] = 's', [0x20] = 'd', [0x21] = 'f', [0x22] = 'g', [0x23] = 'h', [0x24] = 'j', [0x25] = 'k', [0x26] = 'l', [0x27] = ';', [0x28] = '\'', + [0x29] = '`', [0x2C] = 'z', [0x2D] = 'x', [0x2E] = 'c', [0x2F] = 'v', [0x30] = 'b', [0x31] = 'n', [0x32] = 'm', [0x33] = ',', [0x34] = '.', [0x35] = '/', + [0x39] = ' ' // Spacebar +}; + +// C99 Designated Initializers for Shifted ASCII Characters +static const char scancode_ascii_shifted[128] = { + [0x01] = 27, // ESC + [0x02] = '!', [0x03] = '@', [0x04] = '#', [0x05] = '$', [0x06] = '%', [0x07] = '^', [0x08] = '&', [0x09] = '*', [0x0A] = '(', [0x0B] = ')', + [0x0C] = '_', [0x0D] = '+', [0x0E] = '\b', [0x0F] = '\t', [0x10] = 'Q', [0x11] = 'W', [0x12] = 'E', [0x13] = 'R', [0x14] = 'T', [0x15] = 'Y', + [0x16] = 'U', [0x17] = 'I', [0x18] = 'O', [0x19] = 'P', [0x1A] = '{', [0x1B] = '}', [0x1C] = '\n', [0x1E] = 'A', [0x1F] = 'S', [0x20] = 'D', + [0x21] = 'F', [0x22] = 'G', [0x23] = 'H', [0x24] = 'J', [0x25] = 'K', [0x26] = 'L', [0x27] = ':', [0x28] = '"', [0x29] = '~', [0x2C] = 'Z', + [0x2D] = 'X', [0x2E] = 'C', [0x2F] = 'V', [0x30] = 'B', [0x31] = 'N', [0x32] = 'M', [0x33] = '<', [0x34] = '>', [0x35] = '?', [0x39] = ' '}; + +/* IN VGA - Video Memory Arrya: + * short + * 1s byte (left most) -> TEXT COLOR + * 2s byte -> BACK COLOR + * 3rd and 4rt byte -> TEXT (unsigned char) AKA CodePoint + */ + +typedef struct __attribute__((packed)) _VGA { + unsigned char codepoint; // 3rd and 4th byte + unsigned char color; // 1st byte: text color, 2nd byte: background color + // LAST BIT IS BLINKING FLAG +} _VGA; + +typedef enum _VGA_COLOR { + BLACK = 0x0, + BLUE = 0x1, + GREEN = 0x2, + CYAN = 0x3, + RED = 0x4, + MAGENTA = 0x5, + BROWN = 0x6, + LIGHT_GREY = 0x7, + DARK_GREY = 0x8, + LIGHT_BLUE = 0x9, + LIGHT_GREEN = 0xA, + LIGHT_CYAN = 0xB, + LIGHT_RED = 0xC, + LIGHT_MAGENTA = 0xD, + YELLOW = 0xE, + WHITE = 0xF +} _VGA_COLOR; + +typedef struct _VGA_screen_space { + unsigned int line; + unsigned int column; + +} _VGA_screen_space; + +static _VGA_screen_space cursor_pos = {0, 0}; +static _VGA_screen_space text_pos = {0, 0}; + +static unsigned int tab_pos = 0; + +#define DEFAULT_BG BLUE +#define DEFAULT_FG WHITE + +/* + * END OF DECLARATIONS + */ + +/* + * START OF OUTPUT FUNCTIONS + */ + +int printf(const char *fmt, ...); + +void clear_screen(); + +/* + * END OF OUTPUT FUNCTIONS + */ + +/* + * START OF INPUT FUNCTIONS + */ +void scursor(unsigned int column, unsigned int line); + +void gets(char *buffer, size_t max_length); + +int scanf(const char *fmt, ...); +#endif diff --git a/include/stdmem.h b/include/stdmem.h new file mode 100644 index 0000000..ca3e313 --- /dev/null +++ b/include/stdmem.h @@ -0,0 +1,23 @@ +#ifndef STDMEM_H +#define STDMEM_H + +#include "types.h" + +static inline void *__memmove(void *dest, const void *src, uint64_t n) { + unsigned char *__d = (unsigned char *)dest; + const unsigned char *__s = (const unsigned char *)src; + + if (__d < __s) { + for (unsigned long long i = 0; i < n; i++) { + __d[i] = __s[i]; + } + } else { + for (unsigned long long i = n; i > 0; i--) { + __d[i - 1] = __s[i - 1]; + } + } + + return dest; +} + +#endif // STDMEM_H diff --git a/types.h b/include/types.h similarity index 100% rename from types.h rename to include/types.h diff --git a/kernel.c b/kernel.c index 91b7689..a9a7e1b 100644 --- a/kernel.c +++ b/kernel.c @@ -20,28 +20,23 @@ typedef struct { void kmain(void) { user current_user = {.user_name = "admin", .user_hostname = "soraos", .user_id = 0}; - __clear_screen(); + clear_screen(); printf("SoraOS Kernel Initialized\n"); printf("\tWelcome to SoraOS\n"); printf("\tKernel Version %s\n", __KERNEL_VERSION); printf("\tCompiled on: %s at %s\n\n", __DATE__, __TIME__); - // TODO: CLI IDEA - int _count = printf("%s@%s:>", current_user.user_name, current_user.user_hostname); - scursor(_count, text_pos.line); + while (1) { + // TODO: CLI IDEA + printf("%s@%s:$ ", current_user.user_name, current_user.user_hostname); - // TODO: Enable user input handling - char input_buffer[256] = {0}; - scanf("%s", input_buffer); - printf("You entered: %s\n", input_buffer); + // TODO: Enable user input handling + char input_buffer[256] = {0}; + scanf("%s", input_buffer); + printf("echo: %s\n", input_buffer); + } - int num1, num2; - printf("Enter num1: "); - scanf("%d", &num1); - printf("Enter num2: "); - scanf("%d", &num2); - printf("You entered: %d and %d\n", num1, num2); // Infinite loop while (1) { __asm__ volatile("hlt"); diff --git a/stdio.h b/src/stdio.c similarity index 67% rename from stdio.h rename to src/stdio.c index 422284f..febe61d 100644 --- a/stdio.h +++ b/src/stdio.c @@ -1,111 +1,4 @@ -#ifndef COLORS_H -#define COLORS_H - -#include "types.h" -#include -#include -#include - -#define VGA_WIDTH 80 -#define VGA_HEIGHT 25 - -#define VGA_MEMORY_ADDRESS 0xB8000 - -/* - * FOR INPUT - */ - -#define KEYBOARD_BUFFER_SIZE 256 - -#define SCANCODE_LSHIFT 0x2A -#define SCANCODE_RSHIFT 0x36 -#define SCANCODE_CAPSLOCK 0x3A -#define RELEASE_MASK 0x80 - -static volatile unsigned char _keyboard_buffer[KEYBOARD_BUFFER_SIZE]; -static volatile uint16_t _kb_head = 0; -static volatile uint16_t _kb_tail = 0; - -static char __g_shift_pressed = 0; -static char __g_caps_lock_active = 0; - -// C99 Designated Initializers for Unshifted ASCII Characters -static const char scancode_ascii_unshifted[128] = { - [0x01] = 27, // ESC - [0x02] = '1', [0x03] = '2', [0x04] = '3', [0x05] = '4', [0x06] = '5', [0x07] = '6', [0x08] = '7', [0x09] = '8', [0x0A] = '9', [0x0B] = '0', [0x0C] = '-', - [0x0D] = '=', [0x0E] = '\b', // Backspace - [0x0F] = '\t', // Tab - [0x10] = 'q', [0x11] = 'w', [0x12] = 'e', [0x13] = 'r', [0x14] = 't', [0x15] = 'y', [0x16] = 'u', [0x17] = 'i', [0x18] = 'o', [0x19] = 'p', [0x1A] = '[', - [0x1B] = ']', [0x1C] = '\n', // Enter - [0x1E] = 'a', [0x1F] = 's', [0x20] = 'd', [0x21] = 'f', [0x22] = 'g', [0x23] = 'h', [0x24] = 'j', [0x25] = 'k', [0x26] = 'l', [0x27] = ';', [0x28] = '\'', - [0x29] = '`', [0x2C] = 'z', [0x2D] = 'x', [0x2E] = 'c', [0x2F] = 'v', [0x30] = 'b', [0x31] = 'n', [0x32] = 'm', [0x33] = ',', [0x34] = '.', [0x35] = '/', - [0x39] = ' ' // Spacebar -}; - -// C99 Designated Initializers for Shifted ASCII Characters -static const char scancode_ascii_shifted[128] = { - [0x01] = 27, // ESC - [0x02] = '!', [0x03] = '@', [0x04] = '#', [0x05] = '$', [0x06] = '%', [0x07] = '^', [0x08] = '&', [0x09] = '*', [0x0A] = '(', [0x0B] = ')', - [0x0C] = '_', [0x0D] = '+', [0x0E] = '\b', [0x0F] = '\t', [0x10] = 'Q', [0x11] = 'W', [0x12] = 'E', [0x13] = 'R', [0x14] = 'T', [0x15] = 'Y', - [0x16] = 'U', [0x17] = 'I', [0x18] = 'O', [0x19] = 'P', [0x1A] = '{', [0x1B] = '}', [0x1C] = '\n', [0x1E] = 'A', [0x1F] = 'S', [0x20] = 'D', - [0x21] = 'F', [0x22] = 'G', [0x23] = 'H', [0x24] = 'J', [0x25] = 'K', [0x26] = 'L', [0x27] = ':', [0x28] = '"', [0x29] = '~', [0x2C] = 'Z', - [0x2D] = 'X', [0x2E] = 'C', [0x2F] = 'V', [0x30] = 'B', [0x31] = 'N', [0x32] = 'M', [0x33] = '<', [0x34] = '>', [0x35] = '?', [0x39] = ' '}; - -/* IN VGA - Video Memory Arrya: - * short - * 1s byte (left most) -> TEXT COLOR - * 2s byte -> BACK COLOR - * 3rd and 4rt byte -> TEXT (unsigned char) AKA CodePoint - */ - -typedef struct __attribute__((packed)) _VGA { - unsigned char codepoint; // 3rd and 4th byte - unsigned char color; // 1st byte: text color, 2nd byte: background color - // LAST BIT IS BLINKING FLAG -} _VGA; - -typedef enum _VGA_COLOR { - BLACK = 0x0, - BLUE = 0x1, - GREEN = 0x2, - CYAN = 0x3, - RED = 0x4, - MAGENTA = 0x5, - BROWN = 0x6, - LIGHT_GREY = 0x7, - DARK_GREY = 0x8, - LIGHT_BLUE = 0x9, - LIGHT_GREEN = 0xA, - LIGHT_CYAN = 0xB, - LIGHT_RED = 0xC, - LIGHT_MAGENTA = 0xD, - YELLOW = 0xE, - WHITE = 0xF -} _VGA_COLOR; - -typedef struct _VGA_screen_space { - unsigned int line; - unsigned int column; - -} _VGA_screen_space; - -static _VGA_screen_space cursor_pos = {0, 0}; -static _VGA_screen_space text_pos = {0, 0}; - -static unsigned int tab_pos = 0; - -#define DEFAULT_BG BLUE -#define DEFAULT_FG WHITE - -/* - * END OF DECLARATIONS - */ - -/* - * START OF OUTPUT FUNCTIONS - */ - -int printf(const char *fmt, ...); +#include "stdio.h" // Convert _VGA_COLOR to color byte static inline unsigned char __vga_color_byte(_VGA_COLOR fg, _VGA_COLOR bg, int blink) { @@ -130,6 +23,27 @@ static inline void __clear_screen() { } } +void clear_screen(void) { + __clear_screen(); +} + +static inline void __clear_screen_line(unsigned int line) { + if (line >= VGA_HEIGHT) + return; + + volatile _VGA *vga = __vga_memory(); + for (int i = 0; i < VGA_WIDTH; i++) { + vga[line * VGA_WIDTH + i].codepoint = ' '; + vga[line * VGA_WIDTH + i].color = __vga_color_byte(DEFAULT_FG, DEFAULT_BG, 0); + } +} + +static inline void __scroll_screen() { + volatile _VGA *vga = __vga_memory(); + __memmove((void *)vga, (const void *)(vga + VGA_WIDTH), (VGA_HEIGHT - 1) * VGA_WIDTH * sizeof(_VGA)); + __clear_screen_line(VGA_HEIGHT - 1); +} + static inline void __clear_screen_colored(_VGA_COLOR background) { volatile _VGA *vga = __vga_memory(); for (int i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++) { @@ -145,7 +59,13 @@ static inline int __put_char_VGA_POS(_VGA _c, _VGA_screen_space _position, int _ volatile _VGA *vga = __vga_memory(); if (_c.codepoint == '\n') { - text_pos.line++; + if (_position.line == VGA_HEIGHT - 1) { + __scroll_screen(); + _position.line = VGA_HEIGHT - 1; + } else { + _position.line++; + } + text_pos.line = _position.line; text_pos.column = 0; return 1; } @@ -162,6 +82,8 @@ static inline int __put_char_VGA_POS(_VGA _c, _VGA_screen_space _position, int _ _position.line++; if (_position.line >= VGA_HEIGHT) { // TODO: scroll or wrap + __scroll_screen(); + _position.line = VGA_HEIGHT - 1; // Keep the cursor on the last line after scrolling break; } } @@ -178,16 +100,16 @@ static inline int __put_char_VGA_POS(_VGA _c, _VGA_screen_space _position, int _ return written; } - if (_c.codepoint == '\b') { - if (_position.column > 0) { - _position.column--; - vga[(_position.line * VGA_WIDTH) + _position.column].codepoint = ' '; - vga[(_position.line * VGA_WIDTH) + _position.column].color = _c.color; - } - text_pos.line = _position.line; - text_pos.column = _position.column; - return 1; - } + if (_c.codepoint == '\b') { + if (_position.column > 0) { + _position.column--; + vga[(_position.line * VGA_WIDTH) + _position.column].codepoint = ' '; + vga[(_position.line * VGA_WIDTH) + _position.column].color = _c.color; + } + text_pos.line = _position.line; + text_pos.column = _position.column; + return 1; + } vga[(_position.line * VGA_WIDTH) + _position.column].codepoint = _c.codepoint; vga[(_position.line * VGA_WIDTH) + _position.column].color = _c.color; @@ -218,6 +140,8 @@ static inline int __put_string(int column, int line, const char *__args, _VGA_CO if (line >= VGA_HEIGHT) { // TODO: SCROLL OR LOOP... + __scroll_screen(); + line = VGA_HEIGHT - 1; // Keep the cursor on the last line after scrolling } } @@ -238,6 +162,8 @@ static inline int __print_string(const char *__args, _VGA_COLOR foreground, _VGA if (text_pos.line >= VGA_HEIGHT) { // TODO: SCROLL OR LOOP... + __scroll_screen(); + text_pos.line = VGA_HEIGHT - 1; // Keep the cursor on the last line after scrolling } } @@ -344,14 +270,6 @@ int printf(const char *fmt, ...) { return result; } -/* - * END OF OUTPUT FUNCTIONS - */ - -/* - * START OF INPUT FUNCTIONS - */ - static inline void outb(unsigned short port, unsigned char val) { __asm__ volatile("outb %0, %1" : : "a"(val), "Nd"(port)); } @@ -383,11 +301,6 @@ static void __VGA_set_cursor_VGA_pos(_VGA_screen_space pos) { __VGA_set_cursor_internal(pos.column, pos.line); } -static _VGA_screen_space get_cursor_pos() { - _VGA_screen_space __temp = {cursor_pos.column, cursor_pos.line}; - return __temp; -} - void scursor(unsigned int column, unsigned int line) { __VGA_set_cursor_internal(column, line); } @@ -466,22 +379,22 @@ static inline char __gets_internal(char *buffer, size_t max_length) { } if (__c == '\n' || __c == '\r') { - printf("\n"); + printf("\n"); buffer[index] = '\0'; break; } - if (__c == '\b') { - if (index > 0) { - index--; - printf("\b \b"); - scursor(text_pos.column, text_pos.line); - } - continue; - } + if (__c == '\b') { + if (index > 0) { + index--; + printf("\b \b"); + scursor(text_pos.column, text_pos.line); + } + continue; + } - printf("%c", __c); - scursor(text_pos.column, text_pos.line); + printf("%c", __c); + scursor(text_pos.column, text_pos.line); buffer[index++] = __c; } @@ -494,7 +407,7 @@ void gets(char *buffer, size_t max_length) { } static inline int __scanf_internal(const char *fmt, va_list args) { - scursor(text_pos.column, text_pos.line); + scursor(text_pos.column, text_pos.line); char buffer[256]; __gets_internal(buffer, sizeof(buffer)); @@ -560,4 +473,3 @@ int scanf(const char *fmt, ...) { return result; } -#endif