From f80dafd03d0de108d8724c4e21805ce9de0151ba Mon Sep 17 00:00:00 2001 From: AfonsoCMSousa Date: Wed, 5 Aug 2026 13:40:42 +0100 Subject: [PATCH] Feat: better screen formating & better project resstructure --- .../index/kernel.c.FE151BF4CBB915EA.idx | Bin 0 -> 938 bytes .../index/kernel.h.676073B795F16327.idx | Bin 0 -> 216 bytes .../clangd/index/stdio.c.7FE59D9FB18A0627.idx | Bin 0 -> 7542 bytes .../clangd/index/stdio.h.CF376A49F2DCDC41.idx | Bin 0 -> 3502 bytes .../index/stdmem.h.7AEBD514FE5F79BC.idx | Bin 0 -> 344 bytes .../clangd/index/types.h.5A82B4661D1C2FCC.idx | Bin 0 -> 888 bytes .gitignore | 1 + build.sh | 72 ++++++- kernel.h => include/kernel.h | 0 include/stdio.h | 126 +++++++++++ include/stdmem.h | 23 ++ types.h => include/types.h | 0 kernel.c | 23 +- stdio.h => src/stdio.c | 202 +++++------------- 14 files changed, 277 insertions(+), 170 deletions(-) create mode 100644 .cache/clangd/index/kernel.c.FE151BF4CBB915EA.idx create mode 100644 .cache/clangd/index/kernel.h.676073B795F16327.idx create mode 100644 .cache/clangd/index/stdio.c.7FE59D9FB18A0627.idx create mode 100644 .cache/clangd/index/stdio.h.CF376A49F2DCDC41.idx create mode 100644 .cache/clangd/index/stdmem.h.7AEBD514FE5F79BC.idx create mode 100644 .cache/clangd/index/types.h.5A82B4661D1C2FCC.idx rename kernel.h => include/kernel.h (100%) create mode 100644 include/stdio.h create mode 100644 include/stdmem.h rename types.h => include/types.h (100%) rename stdio.h => src/stdio.c (67%) diff --git a/.cache/clangd/index/kernel.c.FE151BF4CBB915EA.idx b/.cache/clangd/index/kernel.c.FE151BF4CBB915EA.idx new file mode 100644 index 0000000000000000000000000000000000000000..3a2477832e3863e8a7bbb9e44fa222ba21e6d1e0 GIT binary patch literal 938 zcmWIYbaPw8%)sEB;#rZKT9U}Zz`!5^#Kk2=nM#Zd424V#3>9I$_Cv)dftwnMTRq|L?l(uKqLobLnK~ zkDZBTmnPrreOvH`TQ{()+dg$4!|T91dy6Y`lV$@$jBk}gLE3K-ejWxX1_nuCR$(qM z0h9rQ2_iEz)`bZx^D)RWGDr&W35bFTnDo+Rc5%CXx-Iz_%}|t@R-6fpO_&=QrLek< zi3`O|Jdz?FBK|NvFc&g&p|}jFNL)k#rie#UUP)dX##^3M;Hjc>)0L4&Qc6+E5at}1 zXMom$d;${&n#3r=3e)?ilCdJ9=|U!>jHEJ?GCNH8{&Dfei!L0T02CHu6yt>n!vX;4 zIFRp=jMNpef++$z&Pv`L#YOv7tOiL`M$$~NnC~;#rZKT9U{DWQzcCaY<38E0DGa;)*$}2Oaqu6nI!1?3Pr2f8)-f z*BG&@h3)=(pH+7&7&D|?)_n?)TqrAPZa+&++(}!Wt3-dB{G+Euw{BkIzuYYLh@rSL zHwkDELs4p4G04>ASp}XdIyYSzxfq!_m?c0`ARzNZ_mf_Sd_GW^k%LhHBFMln{c)0s of8F|tKw%aR7Ezcm(6pRH5U02(xtJToV60zS=Co6N*E$9U0ACI{4gdfE literal 0 HcmV?d00001 diff --git a/.cache/clangd/index/stdio.c.7FE59D9FB18A0627.idx b/.cache/clangd/index/stdio.c.7FE59D9FB18A0627.idx new file mode 100644 index 0000000000000000000000000000000000000000..0201e82611893c351799e0fcc94c82b05f0105dc GIT binary patch literal 7542 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 a5*iR@Fb5d@Y^ETKHPGLe20s+yqy0bZOgD1? literal 0 HcmV?d00001 diff --git a/.cache/clangd/index/stdio.h.CF376A49F2DCDC41.idx b/.cache/clangd/index/stdio.h.CF376A49F2DCDC41.idx new file mode 100644 index 0000000000000000000000000000000000000000..68ac610625f26d3a9a61bde4ebb1eab11b94dc0f GIT binary patch literal 3502 zcmYM02{@H$8^@pbaE`+{$FV!-kbN0T_&VsNL}ZVH7)eY>D+!e)lN3e^lkE!WtI+nf zY8j-uMrEo&Y4Ck5^EHiWnaQQ)Ya40#?&sm@JlExa-s|uG-0$sv-{*Hk1qTEi5FzBZ zI5;;wbxo2gLP!sOve#rSzs^DEFb|>J#tYHuihC|vZ=ZbHI{u^D*1eIPqS<$V9V+pt=;-LFvZ(hJF^u5PR1 zKd$f9JllRTsQs(oJfw>%kqUVOK7 zdgRlGM_MZ*%EuUwr{lZjwzghbuChc?(9%NFb9M5%wT(U+4)cej`gzIwlV%!bu6l8G zx7o&uo{gC!+Y7D2TgI&4+%?^C+}pF+w)wtWX47=DF65*rxLp*gy>CUG@~+!%LDG1&+a4QFzMEQn;oS+ZZ6)>}K;+a<+yD+&_2vOl*>=YM>1)o!7l)P7h;s{z4`@tH7wXtdb}Tu&BBgTCy;tWuLT;tBTH60p zRx5q%ws5)Q%kA+zuMWM#JEt|bJUP{wB6l@W)HV7KZTq32d`Zg9&?{#KbB`UcwNjko zd%g2^@mksI?X81tN8>YQ6eW*83n0jxB)Aw6d`Qw-y zjlKP{s_(zq@T{_Aor_JWyk2aRS}K@*B;~KOp4B6zjWI&I*0cq}e|4{q-}vTLtz&Ij zV^G~%JHN-#eF-c6<2rKnde}(Mv#DcDN`>c4l%1EJ9Lz%DXNH!l}ki;)2Y6pTVhL>Wju^8S$b zQV%;3ngfAFdW(#RkU#*w#hHvd{>y%>rVt^4sW^}n>s-^C=jO#jCJ>lq zJIjFxk|Lyw5CppaZsC=rp7s(VKZItS;BZfHglsN1SBRwQTqe*FBJa;Nwfr*l*++zI zpoX#3*qjKtNf5rtx2=+j*I7{^B4iB#BdL)&5oJI{>#ejWv@cW>&9Xr3e9iefL=YcF z1bX2*4*O%pv1UZbe$r%fmPTHp1;HFNxF7PE-1(dOmkW_ELuihJcLQm*dN0 zu_(u_v#CESzq>qBjHW;z^O$*RM3jBZc&ek2uAQ+?jI<#T#)N4QQ3n2Z@y2jZ$?Y62 zGK0Vz(Huh}BtV9BvH9c{x6L-2#mEo>bD6mUBFYNR9Ftvwps!2CNDBf%Oc0ldG9a&a z>dGvwE)yYJ2*^xiPDDr`*d88u%>CED+PCPJi;(~V{)|75h_b?OR}Gt+`nz@rkrRwc z%9U!f8QctQq|W2vS+d-MyD4M4_nOseA{SG{`iOn>h|o78y3AN8`mnB6j3jV_C?-mi zi1G&9KTGuNA7$kAY;QJ8yv= zBV_X>`6l#8>XrU(c-b>uA2#apb>VOmDVuv7Rc@B&OM3S_V`jcHo@J5HHHy1otA`h0yjRTGQS8ElMZYEveIje$&U`N?Gu z+Di^QgDv4p@V`c6Q9y%@=}c{kWkxyy<4K>Q7}A)-H0}G|z2IT>z1e_nBP}Bd<*|@8 z)-smRJ=BH07}0buWi!|q%#_9S6Ko7*nx-TM8)KN-l)qqO_|m~q>Vl1tOKtjK;g2JP zovcFn3O1qYq)nL$MF>kLZAwzGF-B=^%1^K{JgH4T!N$m>edlaz`(V28>s+uIJ_9(M zSby|dj<23_=3B5e_!iIslPRQ*D6U=i4cd_y>e6N>^DY)o5vD~egLF=MGMpM)#e zn5?u2MJm{sr!@Wam0b6%3#tIyfN$`nZ^~B~72)b+6-re|W2Dk|i_#Qqj8a;gG8AkK zP-;_hf=!4yS)1|_Yz#}9&Is*HYU(gM4z`Fd0@6(^3Qw>xIcX;pnqXsM(jpXE=Eixha43e>Eux{r~^~ literal 0 HcmV?d00001 diff --git a/.cache/clangd/index/stdmem.h.7AEBD514FE5F79BC.idx b/.cache/clangd/index/stdmem.h.7AEBD514FE5F79BC.idx new file mode 100644 index 0000000000000000000000000000000000000000..6787354270705c99b584a5f93fe35ac9215d0e8e GIT binary patch literal 344 zcmWIYbaM+}WMFVk@vO*AElFfyU|V zFOK4ozvY!qb~LIe`w3}0+8_SP>BXkohb^aTzslPC(&^l(Yf8&~PiF1ScAhxd#z6m> zx4hNv8FAQw6j$aZDFWR#S%2{!K6d_lJPgbX z46Ljotg>K&fs=`mft`hsm6f3=HLchcs8a8!w$!p`?R(-@ma{{&aYd} z$i>RY!6*P!2nH}|Mk$DSF!7?)oJ0`2xG1?;9K>J)5fH$77DiF1B`kx6k|L3bzS;b!7lN28nBpl_xJ!0;< z$aT>&S9X3W^*#L7GRolbvHyk(zwS~{<+`hTuQO97^p(dy!;1YGzmwK%`(RU(B0KlU zt9iD@zbBU&)+^rLvuK6;vB)!8b{*%=PtPcI*}8EGv%_gw#%pg{O4Z-6DsEhJvFVIL z<7^*xSuX1rf%OT_Ot%(guaei?Wa2s5e8aLB>j_H}=4{)iG-2bce6L&gukF3;GOb$5 zq2hq}wD#&huRNP9W%k<~TBx(XrtK5&{}Wf=GZa_mCUGz_FetXLg*A#lW#R#ah@d~O zzaW@k;N)as;OAo$Wc@O6(Vv6YuPN{_2m=+k^STRy2?kDfCWwM{***zxjkhTBFo*#a z1oH+9f(e8P7iO9qHV;|Z&ch%CR1nS^E(j(VIN2B>CfJ)^whrWwo5aH)3RK|D>n#W- z5GIIu{xxsfbbcof120g40EDmA_&Y%AASlz*rIz|Bo0gwO$003t4|E~Z5 literal 0 HcmV?d00001 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