typedef unsigned char uint8_t; typedef signed char int8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; typedef unsigned long long uint64_t; struct multiboot_info { uint32_t flags; uint32_t mem_lower; uint32_t mem_upper; uint32_t boot_device; uint32_t cmdline; uint32_t mods_count; uint32_t mods_addr; uint32_t syms[4]; uint32_t mmap_length; uint32_t mmap_addr; uint32_t drives_length; uint32_t drives_addr; uint32_t config_table; uint32_t boot_loader_name; uint32_t apm_table; uint32_t vbe_control_info; uint32_t vbe_mode_info; uint16_t vbe_mode; uint16_t vbe_interface_seg; uint16_t vbe_interface_off; uint16_t vbe_interface_len; uint64_t framebuffer_addr; uint32_t framebuffer_pitch; uint32_t framebuffer_width; uint32_t framebuffer_height; uint8_t framebuffer_bpp; uint8_t framebuffer_type; } __attribute__((packed)); uint8_t inb(uint16_t p) { uint8_t r; __asm__("in %%dx, %%al":"=a"(r):"d"(p)); return r; } void outb(uint16_t p, uint8_t d) { __asm__("out %%al, %%dx"::"a"(d),"d"(p)); } uint32_t* vram = 0; int scr_w=0, scr_h=0, pitch=0; int mx=400, my=300; uint32_t mouse_bg[100]; // Save buffer for mouse uint8_t mouse_cycle = 0; int8_t mouse_byte[3]; uint8_t mouse_btn_left = 0; struct Window { int x, y, w, h; int dragging; int resizing; int drag_off_x, drag_off_y; }; struct Window win = {100, 100, 400, 300, 0, 0, 0, 0}; uint8_t font8x8[96][8] = { {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // Space {0x18,0x3C,0x3C,0x18,0x18,0x00,0x18,0x00}, // ! {0x66,0x66,0x22,0x00,0x00,0x00,0x00,0x00}, // " {0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00}, // # {0x18,0x7E,0xC0,0x3C,0x06,0x7E,0x18,0x00}, // $ {0x00,0xC6,0xCC,0x18,0x30,0x66,0xC6,0x00}, // % {0x38,0x6C,0x38,0x76,0xDC,0xCC,0x76,0x00}, // & {0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00}, // ' {0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00}, // ( {0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00}, // ) {0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00}, // * {0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00}, // + {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30}, // , {0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00}, // - {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00}, // . {0x00,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00}, // / {0x3C,0x66,0x66,0x66,0x66,0x66,0x3C,0x00}, // 0 {0x18,0x38,0x18,0x18,0x18,0x18,0x7E,0x00}, // 1 {0x3C,0x66,0x06,0x0C,0x30,0x60,0x7E,0x00}, // 2 {0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00}, // 3 {0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x00}, // 4 {0x7E,0xC0,0xFC,0x06,0x06,0x66,0x3C,0x00}, // 5 {0x3C,0x60,0xC0,0xFC,0x66,0x66,0x3C,0x00}, // 6 {0x7E,0x06,0x0C,0x18,0x30,0x30,0x30,0x00}, // 7 {0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00}, // 8 {0x3C,0x66,0x66,0x3E,0x06,0x06,0x3C,0x00}, // 9 {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00}, // : {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30}, // ; {0x06,0x0C,0x18,0x30,0x18,0x0C,0x06,0x00}, // < {0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00}, // = {0x60,0x30,0x18,0x0C,0x18,0x30,0x60,0x00}, // > {0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00}, // ? {0x3C,0x66,0x6E,0x6E,0x60,0x62,0x3C,0x00}, // @ {0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00}, // A {0x7C,0x66,0x66,0x7C,0x66,0x66,0x7C,0x00}, // B {0x3C,0x66,0x60,0x60,0x60,0x66,0x3C,0x00}, // C {0x78,0x6C,0x66,0x66,0x66,0x6C,0x78,0x00}, // D {0x7E,0x60,0x60,0x78,0x60,0x60,0x7E,0x00}, // E {0x7E,0x60,0x60,0x78,0x60,0x60,0x60,0x00}, // F {0x3C,0x66,0x60,0x6E,0x66,0x66,0x3C,0x00}, // G {0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00}, // H {0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // I {0x1E,0x0C,0x0C,0x0C,0xCC,0xCC,0x78,0x00}, // J {0xE6,0x66,0x6C,0x78,0x6C,0x66,0xE6,0x00}, // K {0xF0,0x60,0x60,0x60,0x62,0x66,0xFE,0x00}, // L {0xC6,0xEE,0xFE,0xD6,0xC6,0xC6,0xC6,0x00}, // M {0xC6,0xE6,0xF6,0xDE,0xCE,0xC6,0xC6,0x00}, // N {0x3C,0x66,0x66,0x66,0x66,0x66,0x3C,0x00}, // O {0xFC,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00}, // P {0x7C,0xC6,0xC6,0xC6,0xD6,0x7C,0x0E,0x00}, // Q {0xFC,0x66,0x66,0x7C,0x6C,0x66,0xE6,0x00}, // R {0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00}, // S {0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00}, // T {0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x78,0x00}, // U {0xCC,0xCC,0xCC,0xCC,0xCC,0x78,0x30,0x00}, // V {0xC6,0xC6,0xC6,0xD6,0xFE,0xEE,0xC6,0x00}, // W {0xC6,0xC6,0x6C,0x38,0x38,0x6C,0xC6,0x00}, // X {0xCC,0xCC,0xCC,0x78,0x30,0x30,0x78,0x00}, // Y {0xFE,0x06,0x0C,0x18,0x30,0x60,0xFE,0x00}, // Z {0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00}, // [ {0xC0,0x60,0x30,0x18,0x0C,0x06,0x03,0x00}, // Backslash {0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00}, // ] {0x10,0x38,0x7C,0xFE,0x00,0x00,0x00,0x00}, // ^ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF}, // _ {0x30,0x18,0x0C,0x00,0x00,0x00,0x00,0x00}, // ` {0x00,0x00,0x78,0x0C,0x7C,0xCC,0x76,0x00}, // a {0xE0,0x60,0x60,0x7C,0x66,0x66,0x7C,0x00}, // b {0x00,0x00,0x3C,0x60,0x60,0x60,0x3C,0x00}, // c {0x1C,0x0C,0x0C,0x7C,0xCC,0xCC,0x76,0x00}, // d {0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00}, // e {0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00}, // f {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C}, // g {0xE0,0x60,0x60,0x6C,0x66,0x66,0xE6,0x00}, // h {0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00}, // i {0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C}, // j {0xE0,0x60,0x66,0x6C,0x78,0x6C,0xE6,0x00}, // k {0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // l {0x00,0x00,0xEC,0xFE,0xD6,0xD6,0xC6,0x00}, // m {0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x00}, // n {0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00}, // o {0x00,0x00,0xDC,0x66,0x66,0x7C,0x60,0xF0}, // p {0x00,0x00,0x76,0xCC,0xCC,0x7C,0x0C,0x1E}, // q {0x00,0x00,0xDC,0x66,0x60,0x60,0xF0,0x00}, // r {0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00}, // s {0x30,0x30,0x7C,0x30,0x30,0x36,0x1C,0x00}, // t {0x00,0x00,0xCC,0xCC,0xCC,0xCC,0x76,0x00}, // u {0x00,0x00,0xCC,0xCC,0xCC,0x78,0x30,0x00}, // v {0x00,0x00,0xC6,0xD6,0xFE,0xEE,0xC6,0x00}, // w {0x00,0x00,0xC6,0x6C,0x38,0x6C,0xC6,0x00}, // x {0x00,0x00,0xCC,0xCC,0xCC,0x7C,0x0C,0xF8}, // y {0x00,0x00,0xFC,0x98,0x30,0x64,0xFC,0x00}, // z {0x1C,0x30,0x30,0xE0,0x30,0x30,0x1C,0x00}, // { {0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00}, // | {0xE0,0x30,0x30,0x1C,0x30,0x30,0xE0,0x00}, // } {0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00} // ~ }; void put_pixel(int x, int y, uint32_t color) { if(x>=0 && x=0 && y=0 && x=0 && y95) idx=0; for(int r=0; r<8; r++) { for(int col=0; col<8; col++) { if((font8x8[idx][r] >> (7-col)) & 1) put_pixel(x+col, y+r, fg); else if(bg != 0xFFFFFFFF) put_pixel(x+col, y+r, bg); } } } void draw_text(int x, int y, char* s, uint32_t fg, uint32_t bg) { while(*s) { draw_char(x, y, *s, fg, bg); x+=8; s++; } } char term_buf[64]; int term_idx = 0; char history[4][64]; char* prompt = "root@tiwut:~$ "; void str_cpy(char* d, char* s) { int i=0; while(s[i] && i<63) { d[i]=s[i]; i++; } d[i]=0; } void clear_buffer() { for(int i=0;i<64;i++) term_buf[i]=0; term_idx=0; } void refresh_term() { int tx = win.x + 5; int ty = win.y + 30; if(win.w < 20 || win.h < 50) return; draw_rect(tx, ty, win.w - 10, win.h - 40, 0); for(int i=0; i<4; i++) draw_text(tx + 5, ty + 5 +(i*10), history[i], 0xAAAAAA, 0); int py = ty + 50; draw_text(tx + 5, py, prompt, 0x00FF00, 0); draw_text(tx + 5 + (14*8), py, term_buf, 0xFFFFFF, 0); draw_char(tx + 5 + (14*8) + (term_idx*8), py, '_', 0xFFFFFF, 0); } void add_history(char* msg) { str_cpy(history[0], history[1]); str_cpy(history[1], history[2]); str_cpy(history[2], history[3]); str_cpy(history[3], msg); } void draw_window() { draw_rect(win.x, win.y, win.w, win.h, 0xFFFFFF); draw_rect(win.x, win.y, win.w, 25, 0x000080); draw_text(win.x + 5, win.y + 8, "Terminal", 0xFFFFFF, 0x000080); draw_rect(win.x + win.w - 15, win.y + win.h - 15, 15, 15, 0xFF0000); refresh_term(); } void redraw_scene() { draw_rect(0, 0, 800, 600, 0x003A6EA5); draw_rect(0, 560, 800, 40, 0xC0C0C0); draw_rect(5, 565, 60, 30, 0x008000); draw_window(); } void mouse_save() { for(int y=0;y<10;y++) for(int x=0;x<10;x++) mouse_bg[y*10+x] = get_pixel(mx+x, my+y); } void mouse_restore() { for(int y=0;y<10;y++) for(int x=0;x<10;x++) put_pixel(mx+x, my+y, mouse_bg[y*10+x]); } void mouse_draw() { for(int y=0;y<10;y++) for(int x=0;x<10;x++) { if(x==0||y==0||x==9||y==9||x==y) put_pixel(mx+x, my+y, 0); else put_pixel(mx+x, my+y, 0xFFFFFF); } } void init_mouse_hw() { uint32_t t=10000; while(t--) if((inb(0x64)&2)==0) break; outb(0x64, 0xA8); while(t--) if((inb(0x64)&2)==0) break; outb(0x64, 0x20); while(t--) if((inb(0x64)&1)==1) break; uint8_t s=(inb(0x60)|2); while(t--) if((inb(0x64)&2)==0) break; outb(0x64, 0x60); while(t--) if((inb(0x64)&2)==0) break; outb(0x60, s); outb(0x64, 0xD4); outb(0x60, 0xF4); inb(0x60); } void kernel_main(uint32_t magic, struct multiboot_info* mb) { if(mb->framebuffer_addr == 0) return; vram = (uint32_t*)(uint32_t)mb->framebuffer_addr; scr_w = mb->framebuffer_width; scr_h = mb->framebuffer_height; pitch = mb->framebuffer_pitch; init_mouse_hw(); str_cpy(history[0], "TiwutOS"); str_cpy(history[1], "v1.3"); str_cpy(history[2], "Copyright (c) 2025 Tiwut"); str_cpy(history[3], "Tiwut Basic Desktop Environment"); redraw_scene(); mouse_save(); mouse_draw(); char kbd[] = {0,0,'1','2','3','4','5','6','7','8','9','0','-','=','\b','\t','q','w','e','r','t','y','u','i','o','p','[',']','\n',0,'a','s','d','f','g','h','j','k','l',';','\'','`',0,'\\','z','x','c','v','b','n','m',',','.','/',0,'*',0,' '}; while(1) { uint8_t status = inb(0x64); if(status & 1) { uint8_t scancode = inb(0x60); if(status & 0x20) { if(mouse_cycle==0 && (scancode & 0x08)) { mouse_byte[0]=scancode; mouse_cycle++; } else if(mouse_cycle==1) { mouse_byte[1]=scancode; mouse_cycle++; } else if(mouse_cycle==2) { mouse_byte[2]=scancode; mouse_cycle=0; int left_btn = mouse_byte[0] & 1; if(left_btn) { if(!win.dragging && !win.resizing) { if(mx >= win.x && mx <= win.x+win.w && my >= win.y && my <= win.y+25) { win.dragging = 1; win.drag_off_x = mx - win.x; win.drag_off_y = my - win.y; } else if(mx >= win.x+win.w-15 && mx <= win.x+win.w && my >= win.y+win.h-15 && my <= win.y+win.h) { win.resizing = 1; } } } else { win.dragging = 0; win.resizing = 0; } mouse_restore(); mx += mouse_byte[1]; my -= mouse_byte[2]; if(mx<0) mx=0; if(mx>790) mx=790; if(my<0) my=0; if(my>590) my=590; int need_redraw = 0; if(win.dragging) { win.x = mx - win.drag_off_x; win.y = my - win.drag_off_y; need_redraw = 1; } if(win.resizing) { win.w = mx - win.x; win.h = my - win.y; if(win.w < 150) win.w = 150; if(win.h < 100) win.h = 100; need_redraw = 1; } if(need_redraw) redraw_scene(); mouse_save(); mouse_draw(); } } else if((scancode & 0x80) == 0) { char c = kbd[scancode]; if(c) { if(c == '\b') { if(term_idx > 0) { term_buf[--term_idx] = 0; refresh_term(); } } else if(c == '\n') { if(term_buf[0]=='h') add_history("Cmds: help, clear"); else if(term_buf[0]=='c') { clear_buffer(); add_history("Cleared."); } else add_history("Unknown Command"); clear_buffer(); refresh_term(); } else if(term_idx < 60) { term_buf[term_idx++] = c; term_buf[term_idx] = 0; refresh_term(); } } } } } }