diff --git a/brewos.iso b/brewos.iso index 6b0170e..eccc901 100644 Binary files a/brewos.iso and b/brewos.iso differ diff --git a/build/about.o b/build/about.o index db989db..189d10b 100644 Binary files a/build/about.o and b/build/about.o differ diff --git a/build/brewos.elf b/build/brewos.elf index eacafee..3c8bbd1 100755 Binary files a/build/brewos.elf and b/build/brewos.elf differ diff --git a/build/cli_apps/about.o b/build/cli_apps/about.o index 7b7e9c6..34cc8ac 100644 Binary files a/build/cli_apps/about.o and b/build/cli_apps/about.o differ diff --git a/build/control_panel.o b/build/control_panel.o index e729340..69017e7 100644 Binary files a/build/control_panel.o and b/build/control_panel.o differ diff --git a/build/graphics.o b/build/graphics.o index 493e0c2..1ae1932 100644 Binary files a/build/graphics.o and b/build/graphics.o differ diff --git a/build/network.o b/build/network.o index ed2877f..dbc2f6a 100644 Binary files a/build/network.o and b/build/network.o differ diff --git a/iso_root/README.md b/iso_root/README.md index 2aed983..2b02f66 100644 --- a/iso_root/README.md +++ b/iso_root/README.md @@ -1,4 +1,4 @@ -# Brew OS 1.03 Pre-Alpha +# Brew OS 1.10 Alpha ## Brewkernel is now BrewOS! Brewkernel will from now on be deprecated as it's core became too messy. I have built a less bloated kernel and wrote a DE above it, which is why it is now an OS instead of a kernel (in my opinion). @@ -9,6 +9,7 @@ Brew Kernel is a simple x86_64 hobbyist operating system. It features a DE (and WM), a FAT32 filesystem, customizable UI and much much more! ## Features +- Basic Networking Stack - Brew WM - Fat 32 FS - 64-bit long mode support diff --git a/iso_root/brewos.elf b/iso_root/brewos.elf index eacafee..3c8bbd1 100755 Binary files a/iso_root/brewos.elf and b/iso_root/brewos.elf differ diff --git a/src/kernel/control_panel.c b/src/kernel/control_panel.c index c59dd0c..3afe1ed 100644 --- a/src/kernel/control_panel.c +++ b/src/kernel/control_panel.c @@ -2,6 +2,7 @@ #include "graphics.h" #include #include "wm.h" +#include "network.h" Window win_control_panel; @@ -15,14 +16,101 @@ Window win_control_panel; // Control panel state #define VIEW_MAIN 0 #define VIEW_WALLPAPER 1 +#define VIEW_NETWORK 2 static int current_view = VIEW_MAIN; static char rgb_r[4] = ""; static char rgb_g[4] = ""; static char rgb_b[4] = ""; -static int focused_field = -1; // -1=none, 0=R, 1=G, 2=B +static int focused_field = -1; static int input_cursor = 0; +// Network panel state +static char ip_1[4] = ""; +static char ip_2[4] = ""; +static char ip_3[4] = ""; +static char ip_4[4] = ""; +static char dest_ip_1[4] = ""; +static char dest_ip_2[4] = ""; +static char dest_ip_3[4] = ""; +static char dest_ip_4[4] = ""; +static char udp_port[6] = ""; +static char udp_message[128] = ""; +static char net_status[64] = ""; + +// Pattern buffers (128x128) +#define PATTERN_SIZE 128 +static uint32_t pattern_lumberjack[PATTERN_SIZE * PATTERN_SIZE]; +static uint32_t pattern_blue_diamond[PATTERN_SIZE * PATTERN_SIZE]; + +static void generate_lumberjack_pattern(void) { + // Lumberjack pattern: 3x3 repeating cell + // Red corners, dark grey cross (top/left/right/bottom), black center + uint32_t red = 0xFFDC143C; + uint32_t dark_grey = 0xFF404040; + uint32_t black = 0xFF000000; + + // Fill entire pattern with the 3x3 repeating cell + for (int y = 0; y < PATTERN_SIZE; y++) { + for (int x = 0; x < PATTERN_SIZE; x++) { + int cell_x = x % 3; + int cell_y = y % 3; + + uint32_t color; + + // Determine color based on position in 3x3 cell + if (cell_x == 1 && cell_y == 1) { + // Center: black + color = black; + } else if (cell_x == 1 || cell_y == 1) { + // Cross (top, left, right, bottom): dark grey + color = dark_grey; + } else { + // Corners: red + color = red; + } + + pattern_lumberjack[y * PATTERN_SIZE + x] = color; + } + } +} + +static void generate_blue_diamond_pattern(void) { + // Blue diamond pattern on light blue background + uint32_t bg_color = 0xFFADD8E6; // Light blue + uint32_t diamond_color = 0xFF0000CD; // Medium blue + + for (int y = 0; y < PATTERN_SIZE; y++) { + for (int x = 0; x < PATTERN_SIZE; x++) { + pattern_blue_diamond[y * PATTERN_SIZE + x] = bg_color; + } + } + + // Draw diamonds (centered at 32, 32 and 96, 96) + for (int dy = -24; dy <= 24; dy++) { + for (int dx = -24; dx <= 24; dx++) { + // Diamond shape: |dx| + |dy| <= 24 + int abs_dx = dx < 0 ? -dx : dx; + int abs_dy = dy < 0 ? -dy : dy; + if (abs_dx + abs_dy <= 24) { + // Top-left diamond + int x1 = 32 + dx; + int y1 = 32 + dy; + if (x1 >= 0 && x1 < PATTERN_SIZE && y1 >= 0 && y1 < PATTERN_SIZE) { + pattern_blue_diamond[y1 * PATTERN_SIZE + x1] = diamond_color; + } + + // Bottom-right diamond + int x2 = 96 + dx; + int y2 = 96 + dy; + if (x2 >= 0 && x2 < PATTERN_SIZE && y2 >= 0 && y2 < PATTERN_SIZE) { + pattern_blue_diamond[y2 * PATTERN_SIZE + x2] = diamond_color; + } + } + } + } +} + static uint32_t parse_rgb_separate(const char *r, const char *g, const char *b) { int rv = 0, gv = 0, bv = 0; @@ -59,21 +147,55 @@ static void control_panel_paint_main(Window *win) { int offset_x = win->x + 8; int offset_y = win->y + 30; - // Draw wallpaper folder icon - // Folder icon - draw_rect(offset_x + 5, offset_y, 15, 6, COLOR_LTGRAY); - draw_rect(offset_x + 5, offset_y, 15, 1, COLOR_BLACK); - draw_rect(offset_x + 5, offset_y, 1, 6, COLOR_BLACK); - draw_rect(offset_x + 19, offset_y, 1, 6, COLOR_BLACK); + // Draw wallpaper painting icon + // Frame + draw_rect(offset_x + 5, offset_y + 2, 28, 20, 0xFF8B4513); // Brown frame + draw_rect(offset_x + 6, offset_y + 3, 26, 18, 0xFFFFFFFF); // White canvas - draw_rect(offset_x + 5, offset_y + 6, 25, 15, COLOR_LTGRAY); - draw_rect(offset_x + 5, offset_y + 6, 25, 1, COLOR_BLACK); - draw_rect(offset_x + 5, offset_y + 6, 1, 15, COLOR_BLACK); - draw_rect(offset_x + 29, offset_y + 6, 1, 15, COLOR_BLACK); - draw_rect(offset_x + 5, offset_y + 20, 25, 1, COLOR_BLACK); + // Paint strokes (simple landscape) + draw_rect(offset_x + 8, offset_y + 5, 22, 7, 0xFF87CEEB); // Sky blue + draw_rect(offset_x + 8, offset_y + 12, 22, 5, 0xFF90EE90); // Light green grass + draw_rect(offset_x + 15, offset_y + 8, 3, 4, 0xFF8B4513); // Tree trunk + draw_rect(offset_x + 13, offset_y + 5, 7, 4, 0xFF228B22); // Tree leaves + draw_rect(offset_x + 24, offset_y + 6, 4, 3, 0xFFFFFF00); // Sun - // Label draw_string(offset_x + 40, offset_y + 8, "Wallpaper", 0xFF000000); + + // Draw network globe icon + int net_offset_y = offset_y + 35; + + // Globe circle (approximate with rectangles for filled circle) + uint32_t globe_color = 0xFF4169E1; // Royal blue + + // Draw filled circle using rectangles (simplified) + draw_rect(offset_x + 11, net_offset_y + 3, 12, 1, globe_color); + draw_rect(offset_x + 9, net_offset_y + 4, 16, 1, globe_color); + draw_rect(offset_x + 8, net_offset_y + 5, 18, 1, globe_color); + draw_rect(offset_x + 7, net_offset_y + 6, 20, 1, globe_color); + draw_rect(offset_x + 6, net_offset_y + 7, 22, 1, globe_color); + draw_rect(offset_x + 6, net_offset_y + 8, 22, 1, globe_color); + draw_rect(offset_x + 6, net_offset_y + 9, 22, 1, globe_color); + draw_rect(offset_x + 6, net_offset_y + 10, 22, 1, globe_color); + draw_rect(offset_x + 6, net_offset_y + 11, 22, 1, globe_color); + draw_rect(offset_x + 6, net_offset_y + 12, 22, 1, globe_color); + draw_rect(offset_x + 6, net_offset_y + 13, 22, 1, globe_color); + draw_rect(offset_x + 7, net_offset_y + 14, 20, 1, globe_color); + draw_rect(offset_x + 8, net_offset_y + 15, 18, 1, globe_color); + draw_rect(offset_x + 9, net_offset_y + 16, 16, 1, globe_color); + draw_rect(offset_x + 11, net_offset_y + 17, 12, 1, globe_color); + + // Latitude lines (white) + draw_rect(offset_x + 7, net_offset_y + 8, 20, 1, 0xFFFFFFFF); + draw_rect(offset_x + 7, net_offset_y + 12, 20, 1, 0xFFFFFFFF); + + // Longitude line (vertical, white) + draw_rect(offset_x + 17, net_offset_y + 6, 1, 9, 0xFFFFFFFF); + + // Curved longitude lines + draw_rect(offset_x + 11, net_offset_y + 5, 1, 11, 0xFFFFFFFF); + draw_rect(offset_x + 23, net_offset_y + 5, 1, 11, 0xFFFFFFFF); + + draw_string(offset_x + 40, net_offset_y + 8, "Network", 0xFF000000); } static void control_panel_paint_wallpaper(Window *win) { @@ -114,6 +236,47 @@ static void control_panel_paint_wallpaper(Window *win) { draw_button(button_x + 200, button_y, 60, 20, "Grey", false); draw_rect(button_x + 265, button_y + 5, 20, 10, COLOR_GREY); + // Pattern section + button_y += 40; + draw_string(offset_x, button_y, "Patterns:", 0xFF000000); + + button_y += 20; + + // Lumberjack pattern button + draw_button(button_x, button_y, 100, 20, "Lumberjack", false); + // Draw small pattern preview (3x3 repeating) + for (int py = 0; py < 12; py++) { + for (int px = 0; px < 18; px++) { + int cell_x = px % 3; + int cell_y = py % 3; + uint32_t color; + + if (cell_x == 1 && cell_y == 1) { + color = 0xFF000000; // Black center + } else if (cell_x == 1 || cell_y == 1) { + color = 0xFF404040; // Dark grey cross + } else { + color = 0xFFDC143C; // Red corners + } + + draw_rect(button_x + 110 + px, button_y + 4 + py, 1, 1, color); + } + } + + // Blue Diamond pattern button + draw_button(button_x + 145, button_y, 115, 20, "Blue Diamond", false); + // Draw small diamond preview + for (int py = 0; py < 10; py++) { + for (int px = 0; px < 20; px++) { + int cx = px - 10; + int cy = py - 5; + int abs_cx = cx < 0 ? -cx : cx; + int abs_cy = cy < 0 ? -cy : cy; + uint32_t color = (abs_cx + abs_cy <= 5) ? 0xFF0000CD : 0xFFADD8E6; + draw_rect(button_x + 270 + px, button_y + 5 + py, 1, 1, color); + } + } + // Custom color section button_y += 40; draw_string(offset_x, button_y, "Or something custom", 0xFF000000); @@ -166,25 +329,115 @@ static void control_panel_paint_wallpaper(Window *win) { draw_button(button_x, button_y + 25, 70, 20, "Apply", false); } +static void draw_input_box(int x, int y, int width, const char *text, bool focused, int cursor_pos) { + // Draw box + draw_rect(x, y, width, 18, 0xFFFFFFFF); + draw_rect(x, y, width, 1, COLOR_BLACK); + draw_rect(x, y, 1, 18, COLOR_BLACK); + draw_rect(x + width - 1, y, 1, 18, COLOR_BLACK); + draw_rect(x, y + 17, width, 1, COLOR_BLACK); + + // Draw text + uint32_t text_color = focused ? 0xFF0000FF : COLOR_BLACK; + draw_string(x + 3, y + 4, text, text_color); + + // Draw cursor if focused + if (focused) { + int cursor_x = x + 3 + cursor_pos * 8; + draw_rect(cursor_x, y + 4, 1, 9, 0xFF0000FF); + } +} + +static void control_panel_paint_network(Window *win) { + int offset_x = win->x + 8; + int offset_y = win->y + 30; + + // Back button + draw_string(offset_x, offset_y, "< Back", 0xFF000080); + + // Network Init Button + draw_string(offset_x, offset_y + 25, "Network:", 0xFF000000); + draw_button(offset_x, offset_y + 45, 100, 22, "Init Network", false); + + // Status message + if (net_status[0] != '\0') { + draw_string(offset_x + 110, offset_y + 50, net_status, 0xFF008000); + } + + // Set IP Section + int section_y = offset_y + 80; + draw_string(offset_x, section_y, "Set Static IP:", 0xFF000000); + + section_y += 20; + // IP input boxes (4 octets) + draw_input_box(offset_x, section_y, 40, ip_1, focused_field == 0, input_cursor); + draw_string(offset_x + 42, section_y + 4, ".", COLOR_BLACK); + draw_input_box(offset_x + 50, section_y, 40, ip_2, focused_field == 1, input_cursor); + draw_string(offset_x + 92, section_y + 4, ".", COLOR_BLACK); + draw_input_box(offset_x + 100, section_y, 40, ip_3, focused_field == 2, input_cursor); + draw_string(offset_x + 142, section_y + 4, ".", COLOR_BLACK); + draw_input_box(offset_x + 150, section_y, 40, ip_4, focused_field == 3, input_cursor); + + // Apply IP button + draw_button(offset_x + 200, section_y, 70, 18, "Apply", false); + + // Send UDP Section + section_y += 35; + draw_string(offset_x, section_y, "Send UDP Message:", 0xFF000000); + + section_y += 20; + draw_string(offset_x, section_y + 4, "IP:", COLOR_BLACK); + draw_input_box(offset_x + 25, section_y, 40, dest_ip_1, focused_field == 4, input_cursor); + draw_string(offset_x + 67, section_y + 4, ".", COLOR_BLACK); + draw_input_box(offset_x + 75, section_y, 40, dest_ip_2, focused_field == 5, input_cursor); + draw_string(offset_x + 117, section_y + 4, ".", COLOR_BLACK); + draw_input_box(offset_x + 125, section_y, 40, dest_ip_3, focused_field == 6, input_cursor); + draw_string(offset_x + 167, section_y + 4, ".", COLOR_BLACK); + draw_input_box(offset_x + 175, section_y, 40, dest_ip_4, focused_field == 7, input_cursor); + + section_y += 25; + draw_string(offset_x, section_y + 4, "Port:", COLOR_BLACK); + draw_input_box(offset_x + 40, section_y, 60, udp_port, focused_field == 8, input_cursor); + + section_y += 25; + draw_string(offset_x, section_y + 4, "Msg:", COLOR_BLACK); + draw_input_box(offset_x + 40, section_y, 260, udp_message, focused_field == 9, input_cursor); + + // Send button + section_y += 25; + draw_button(offset_x, section_y, 80, 22, "Send", false); +} + static void control_panel_paint(Window *win) { if (current_view == VIEW_MAIN) { control_panel_paint_main(win); } else if (current_view == VIEW_WALLPAPER) { control_panel_paint_wallpaper(win); + } else if (current_view == VIEW_NETWORK) { + control_panel_paint_network(win); } } static void control_panel_handle_click(Window *win, int x, int y) { - (void)win; // Unused parameter + (void)win; if (current_view == VIEW_MAIN) { int offset_x = 8; int offset_y = 30; - // Check wallpaper folder click - if (x >= offset_x + 5 && x < offset_x + 35 && + // Check wallpaper button click (icon + text) + if (x >= offset_x + 5 && x < offset_x + 120 && y >= offset_y && y < offset_y + 25) { current_view = VIEW_WALLPAPER; + focused_field = -1; + } + + // Check network button click (icon + text) + int net_offset_y = offset_y + 35; + if (x >= offset_x + 5 && x < offset_x + 120 && + y >= net_offset_y && y < net_offset_y + 25) { + current_view = VIEW_NETWORK; + focused_field = -1; } } else if (current_view == VIEW_WALLPAPER) { int offset_x = 8; @@ -236,6 +489,22 @@ static void control_panel_handle_click(Window *win, int x, int y) { return; } + // Pattern section + button_y += 40; + button_y += 20; + + // Check Lumberjack pattern button + if (x >= button_x && x < button_x + 100 && y >= button_y && y < button_y + 20) { + graphics_set_bg_pattern(pattern_lumberjack); + return; + } + + // Check Blue Diamond pattern button + if (x >= button_x + 145 && x < button_x + 260 && y >= button_y && y < button_y + 20) { + graphics_set_bg_pattern(pattern_blue_diamond); + return; + } + // Custom RGB section button_y += 40; button_y += 20; @@ -275,43 +544,278 @@ static void control_panel_handle_click(Window *win, int x, int y) { graphics_set_bg_color(parse_rgb_separate(rgb_r, rgb_g, rgb_b)); return; } + } else if (current_view == VIEW_NETWORK) { + int offset_x = 8; + int offset_y = 30; + + // Back button + if (x >= offset_x && x < offset_x + 40 && y >= offset_y && y < offset_y + 15) { + current_view = VIEW_MAIN; + focused_field = -1; + return; + } + + // Init Network button + if (x >= offset_x && x < offset_x + 100 && y >= offset_y + 45 && y < offset_y + 67) { + int result = network_init(); + if (result == 0) { + net_status[0] = 'I'; net_status[1] = 'n'; net_status[2] = 'i'; + net_status[3] = 't'; net_status[4] = 'e'; net_status[5] = 'd'; + net_status[6] = '\0'; + } else { + net_status[0] = 'F'; net_status[1] = 'a'; net_status[2] = 'i'; + net_status[3] = 'l'; net_status[4] = 'e'; net_status[5] = 'd'; + net_status[6] = '\0'; + } + return; + } + + int section_y = offset_y + 80 + 20; + + // IP octet 1 + if (x >= offset_x && x < offset_x + 40 && y >= section_y && y < section_y + 18) { + focused_field = 0; + input_cursor = 0; + return; + } + // IP octet 2 + if (x >= offset_x + 50 && x < offset_x + 90 && y >= section_y && y < section_y + 18) { + focused_field = 1; + input_cursor = 0; + return; + } + // IP octet 3 + if (x >= offset_x + 100 && x < offset_x + 140 && y >= section_y && y < section_y + 18) { + focused_field = 2; + input_cursor = 0; + return; + } + // IP octet 4 + if (x >= offset_x + 150 && x < offset_x + 190 && y >= section_y && y < section_y + 18) { + focused_field = 3; + input_cursor = 0; + return; + } + + // Apply IP button + if (x >= offset_x + 200 && x < offset_x + 270 && y >= section_y && y < section_y + 18) { + ipv4_address_t ip; + ip.bytes[0] = 0; ip.bytes[1] = 0; ip.bytes[2] = 0; ip.bytes[3] = 0; + + // Parse IP octets + for (int i = 0; ip_1[i] && i < 3; i++) { + if (ip_1[i] >= '0' && ip_1[i] <= '9') { + ip.bytes[0] = ip.bytes[0] * 10 + (ip_1[i] - '0'); + } + } + for (int i = 0; ip_2[i] && i < 3; i++) { + if (ip_2[i] >= '0' && ip_2[i] <= '9') { + ip.bytes[1] = ip.bytes[1] * 10 + (ip_2[i] - '0'); + } + } + for (int i = 0; ip_3[i] && i < 3; i++) { + if (ip_3[i] >= '0' && ip_3[i] <= '9') { + ip.bytes[2] = ip.bytes[2] * 10 + (ip_3[i] - '0'); + } + } + for (int i = 0; ip_4[i] && i < 3; i++) { + if (ip_4[i] >= '0' && ip_4[i] <= '9') { + ip.bytes[3] = ip.bytes[3] * 10 + (ip_4[i] - '0'); + } + } + + network_set_ipv4_address(&ip); + net_status[0] = 'I'; net_status[1] = 'P'; net_status[2] = ' '; + net_status[3] = 's'; net_status[4] = 'e'; net_status[5] = 't'; + net_status[6] = '\0'; + return; + } + + section_y += 35 + 20; + + // Dest IP octets + if (x >= offset_x + 25 && x < offset_x + 65 && y >= section_y && y < section_y + 18) { + focused_field = 4; + input_cursor = 0; + return; + } + if (x >= offset_x + 75 && x < offset_x + 115 && y >= section_y && y < section_y + 18) { + focused_field = 5; + input_cursor = 0; + return; + } + if (x >= offset_x + 125 && x < offset_x + 165 && y >= section_y && y < section_y + 18) { + focused_field = 6; + input_cursor = 0; + return; + } + if (x >= offset_x + 175 && x < offset_x + 215 && y >= section_y && y < section_y + 18) { + focused_field = 7; + input_cursor = 0; + return; + } + + section_y += 25; + + // Port field + if (x >= offset_x + 40 && x < offset_x + 100 && y >= section_y && y < section_y + 18) { + focused_field = 8; + input_cursor = 0; + return; + } + + section_y += 25; + + // Message field + if (x >= offset_x + 40 && x < offset_x + 300 && y >= section_y && y < section_y + 18) { + focused_field = 9; + input_cursor = 0; + return; + } + + section_y += 25; + + // Send button + if (x >= offset_x && x < offset_x + 80 && y >= section_y && y < section_y + 22) { + ipv4_address_t dest_ip; + dest_ip.bytes[0] = 0; dest_ip.bytes[1] = 0; dest_ip.bytes[2] = 0; dest_ip.bytes[3] = 0; + + // Parse dest IP + for (int i = 0; dest_ip_1[i] && i < 3; i++) { + if (dest_ip_1[i] >= '0' && dest_ip_1[i] <= '9') { + dest_ip.bytes[0] = dest_ip.bytes[0] * 10 + (dest_ip_1[i] - '0'); + } + } + for (int i = 0; dest_ip_2[i] && i < 3; i++) { + if (dest_ip_2[i] >= '0' && dest_ip_2[i] <= '9') { + dest_ip.bytes[1] = dest_ip.bytes[1] * 10 + (dest_ip_2[i] - '0'); + } + } + for (int i = 0; dest_ip_3[i] && i < 3; i++) { + if (dest_ip_3[i] >= '0' && dest_ip_3[i] <= '9') { + dest_ip.bytes[2] = dest_ip.bytes[2] * 10 + (dest_ip_3[i] - '0'); + } + } + for (int i = 0; dest_ip_4[i] && i < 3; i++) { + if (dest_ip_4[i] >= '0' && dest_ip_4[i] <= '9') { + dest_ip.bytes[3] = dest_ip.bytes[3] * 10 + (dest_ip_4[i] - '0'); + } + } + + // Parse port + int port = 0; + for (int i = 0; udp_port[i] && i < 5; i++) { + if (udp_port[i] >= '0' && udp_port[i] <= '9') { + port = port * 10 + (udp_port[i] - '0'); + } + } + + // Get message length + int msg_len = 0; + while (udp_message[msg_len] && msg_len < 127) msg_len++; + + if (msg_len > 0 && port > 0) { + int result = udp_send_packet(&dest_ip, (uint16_t)port, 54321, udp_message, (size_t)msg_len); + if (result == 0) { + net_status[0] = 'S'; net_status[1] = 'e'; net_status[2] = 'n'; + net_status[3] = 't'; net_status[4] = '\0'; + } else { + net_status[0] = 'F'; net_status[1] = 'a'; net_status[2] = 'i'; + net_status[3] = 'l'; net_status[4] = '\0'; + } + } + return; + } } } static void control_panel_handle_key(Window *win, char c) { - (void)win; // Unused parameter + (void)win; - if (current_view != VIEW_WALLPAPER) return; - if (focused_field < 0) return; // No field focused + if (focused_field < 0) return; - // Get the currently focused field buffer - char *focused_buffer = NULL; - int max_len = 3; // RGB values are 0-255, max 3 digits - - if (focused_field == 0) { - focused_buffer = rgb_r; - } else if (focused_field == 1) { - focused_buffer = rgb_g; - } else if (focused_field == 2) { - focused_buffer = rgb_b; - } else { - return; - } - - if (c == '\b') { // Backspace - if (input_cursor > 0) { - input_cursor--; - focused_buffer[input_cursor] = '\0'; + if (current_view == VIEW_WALLPAPER) { + // Get the currently focused field buffer + char *focused_buffer = NULL; + int max_len = 3; // RGB values are 0-255, max 3 digits + + if (focused_field == 0) { + focused_buffer = rgb_r; + } else if (focused_field == 1) { + focused_buffer = rgb_g; + } else if (focused_field == 2) { + focused_buffer = rgb_b; + } else { + return; } - } else if (c >= '0' && c <= '9') { // Digits only - if (input_cursor < max_len) { - focused_buffer[input_cursor] = c; - input_cursor++; - focused_buffer[input_cursor] = '\0'; + + if (c == '\b') { // Backspace + if (input_cursor > 0) { + input_cursor--; + focused_buffer[input_cursor] = '\0'; + } + } else if (c >= '0' && c <= '9') { // Digits only + if (input_cursor < max_len) { + focused_buffer[input_cursor] = c; + input_cursor++; + focused_buffer[input_cursor] = '\0'; + } + } else if (c == '\t') { // Tab - switch to next field + focused_field = (focused_field + 1) % 3; + input_cursor = 0; + } + } else if (current_view == VIEW_NETWORK) { + char *focused_buffer = NULL; + int max_len = 3; // Default for IP octets + + // Select the focused field + if (focused_field == 0) { + focused_buffer = ip_1; + } else if (focused_field == 1) { + focused_buffer = ip_2; + } else if (focused_field == 2) { + focused_buffer = ip_3; + } else if (focused_field == 3) { + focused_buffer = ip_4; + } else if (focused_field == 4) { + focused_buffer = dest_ip_1; + } else if (focused_field == 5) { + focused_buffer = dest_ip_2; + } else if (focused_field == 6) { + focused_buffer = dest_ip_3; + } else if (focused_field == 7) { + focused_buffer = dest_ip_4; + } else if (focused_field == 8) { + focused_buffer = udp_port; + max_len = 5; // Ports up to 65535 + } else if (focused_field == 9) { + focused_buffer = udp_message; + max_len = 127; // Message max length + } else { + return; + } + + if (c == '\b') { // Backspace + if (input_cursor > 0) { + input_cursor--; + focused_buffer[input_cursor] = '\0'; + } + } else if (focused_field <= 8 && c >= '0' && c <= '9') { // Digits only for IP/port + if (input_cursor < max_len) { + focused_buffer[input_cursor] = c; + input_cursor++; + focused_buffer[input_cursor] = '\0'; + } + } else if (focused_field == 9 && c >= 32 && c <= 126) { // All printable chars for message + if (input_cursor < max_len) { + focused_buffer[input_cursor] = c; + input_cursor++; + focused_buffer[input_cursor] = '\0'; + } + } else if (c == '\t') { // Tab - switch to next field + focused_field = (focused_field + 1) % 10; + input_cursor = 0; } - } else if (c == '\t') { // Tab - switch to next field - focused_field = (focused_field + 1) % 3; - input_cursor = 0; } } @@ -330,6 +834,10 @@ void control_panel_init(void) { win_control_panel.handle_right_click = NULL; win_control_panel.buf_len = 0; win_control_panel.cursor_pos = 0; + + // Generate patterns + generate_lumberjack_pattern(); + generate_blue_diamond_pattern(); } void control_panel_reset(void) { diff --git a/src/kernel/graphics.c b/src/kernel/graphics.c index 3688bf6..be4d413 100644 --- a/src/kernel/graphics.c +++ b/src/kernel/graphics.c @@ -5,6 +5,11 @@ static struct limine_framebuffer *g_fb = NULL; static uint32_t g_bg_color = 0xFF696969; // Dark gray background +// Pattern support +#define PATTERN_SIZE 128 +static uint32_t g_bg_pattern[PATTERN_SIZE * PATTERN_SIZE]; +static bool g_use_pattern = false; + // Dirty rectangle tracking static DirtyRect g_dirty = {0, 0, 0, 0, false}; @@ -145,11 +150,36 @@ void draw_string(int x, int y, const char *s, uint32_t color) { void draw_desktop_background(void) { if (!g_fb) return; - draw_rect(0, 0, g_fb->width, g_fb->height, g_bg_color); + + if (g_use_pattern) { + // Draw tiled pattern + for (int y = 0; y < (int)g_fb->height; y++) { + for (int x = 0; x < (int)g_fb->width; x++) { + int px = x % PATTERN_SIZE; + int py = y % PATTERN_SIZE; + uint32_t color = g_bg_pattern[py * PATTERN_SIZE + px]; + put_pixel(x, y, color); + } + } + } else { + // Draw solid color + draw_rect(0, 0, g_fb->width, g_fb->height, g_bg_color); + } } void graphics_set_bg_color(uint32_t color) { g_bg_color = color; + g_use_pattern = false; +} + +void graphics_set_bg_pattern(const uint32_t *pattern) { + if (!pattern) return; + + // Copy pattern to internal buffer + for (int i = 0; i < PATTERN_SIZE * PATTERN_SIZE; i++) { + g_bg_pattern[i] = pattern[i]; + } + g_use_pattern = true; } // Double buffering functions diff --git a/src/kernel/graphics.h b/src/kernel/graphics.h index c802943..6f34c76 100644 --- a/src/kernel/graphics.h +++ b/src/kernel/graphics.h @@ -18,6 +18,7 @@ void draw_char(int x, int y, char c, uint32_t color); void draw_string(int x, int y, const char *s, uint32_t color); void draw_desktop_background(void); void graphics_set_bg_color(uint32_t color); +void graphics_set_bg_pattern(const uint32_t *pattern); // 128x128 pattern // Get screen dimensions int get_screen_width(void); diff --git a/src/kernel/network.c b/src/kernel/network.c index c9a779d..abacd03 100644 --- a/src/kernel/network.c +++ b/src/kernel/network.c @@ -6,7 +6,7 @@ static int network_initialized = 0; static mac_address_t our_mac; -static ipv4_address_t our_ip = {{0,0,0,0}}; +static ipv4_address_t ip_address = {{0,0,0,0}}; static uint16_t ipv4_id_counter = 0; typedef struct { ipv4_address_t ip; mac_address_t mac; uint32_t timestamp; int valid; } arp_cache_entry_t; @@ -63,8 +63,8 @@ int network_get_mac_address(mac_address_t* mac){ return 0; } -int network_get_ipv4_address(ipv4_address_t* ip){ if(!network_initialized) return -1; *ip=our_ip; return 0; } -int network_set_ipv4_address(const ipv4_address_t* ip){ if(!network_initialized) return -1; our_ip=*ip; return 0; } +int network_get_ipv4_address(ipv4_address_t* ip){ if(!network_initialized) return -1; *ip=ip_address; return 0; } +int network_set_ipv4_address(const ipv4_address_t* ip){ if(!network_initialized) return -1; ip_address=*ip; return 0; } int network_send_frame(const void* data,size_t length){ if(!network_initialized) return -1; if(length>ETH_FRAME_MAX_SIZE) return -1; return e1000_send_packet(data,length); } @@ -102,7 +102,7 @@ void network_process_frames(void){ ip->checksum=checksum; if(checksum==calc){ int for_our_ip=1; - for(int i=0;i<4;i++){ if(ip->dest_ip[i]!=our_ip.bytes[i]) { for_our_ip=0; break; } } + for(int i=0;i<4;i++){ if(ip->dest_ip[i]!=ip_address.bytes[i]) { for_our_ip=0; break; } } if(for_our_ip || ip->dest_ip[0]==255){ mac_address_t src_mac; kmemcpy(src_mac.bytes,eth->src_mac,6); @@ -128,7 +128,7 @@ int arp_send_request(const ipv4_address_t* target_ip){ arp->proto_len=4; arp->opcode=htons(ARP_OP_REQUEST); kmemcpy(arp->sender_mac,our_mac.bytes,6); - kmemcpy(arp->sender_ip,our_ip.bytes,4); + kmemcpy(arp->sender_ip,ip_address.bytes,4); for(int i=0;i<6;i++) arp->target_mac[i]=0; kmemcpy(arp->target_ip,target_ip->bytes,4); size_t frame_length=sizeof(eth_header_t)+sizeof(arp_header_t); @@ -153,7 +153,7 @@ void arp_process_packet(const arp_header_t* arp,size_t length){ arp_cache_add(&sender_ip,&sender_mac); if(opcode==ARP_OP_REQUEST){ int is_for_us=1; - for(int i=0;i<4;i++){ if(arp->target_ip[i]!=our_ip.bytes[i]) { is_for_us=0; break; } } + for(int i=0;i<4;i++){ if(arp->target_ip[i]!=ip_address.bytes[i]) { is_for_us=0; break; } } if(is_for_us){ uint8_t frame[ETH_FRAME_MAX_SIZE]; eth_header_t* eth=(eth_header_t*)frame; @@ -167,7 +167,7 @@ void arp_process_packet(const arp_header_t* arp,size_t length){ r->proto_len=4; r->opcode=htons(ARP_OP_REPLY); kmemcpy(r->sender_mac,our_mac.bytes,6); - kmemcpy(r->sender_ip,our_ip.bytes,4); + kmemcpy(r->sender_ip,ip_address.bytes,4); kmemcpy(r->target_mac,arp->sender_mac,6); kmemcpy(r->target_ip,arp->sender_ip,4); size_t frame_length=sizeof(eth_header_t)+sizeof(arp_header_t); @@ -197,7 +197,7 @@ int ipv4_send_packet(const ipv4_address_t* dest_ip,uint8_t protocol,const void* ip->ttl=64; ip->protocol=protocol; ip->checksum=0; - kmemcpy(ip->src_ip,our_ip.bytes,4); + kmemcpy(ip->src_ip,ip_address.bytes,4); kmemcpy(ip->dest_ip,dest_ip->bytes,4); ip->checksum=ipv4_checksum(ip); kmemcpy(ip_payload,data,data_length); @@ -222,7 +222,7 @@ int ipv4_send_packet_to_mac(const ipv4_address_t* dest_ip,const mac_address_t* d ip->ttl=64; ip->protocol=protocol; ip->checksum=0; - kmemcpy(ip->src_ip,our_ip.bytes,4); + kmemcpy(ip->src_ip,ip_address.bytes,4); kmemcpy(ip->dest_ip,dest_ip->bytes,4); ip->checksum=ipv4_checksum(ip); kmemcpy(ip_payload,data,data_length); @@ -405,10 +405,10 @@ static void dhcp_udp_callback(const ipv4_address_t* src_ip,uint16_t src_port,con if(dhcp_server_id!=0) dhcp_state=1; } else if(mtype==DHCP_MSG_ACK){ uint32_t yi_host=ntohl32(pkt->yiaddr); - our_ip.bytes[0]=(uint8_t)((yi_host>>24)&0xFF); - our_ip.bytes[1]=(uint8_t)((yi_host>>16)&0xFF); - our_ip.bytes[2]=(uint8_t)((yi_host>>8)&0xFF); - our_ip.bytes[3]=(uint8_t)(yi_host&0xFF); + ip_address.bytes[0]=(uint8_t)((yi_host>>24)&0xFF); + ip_address.bytes[1]=(uint8_t)((yi_host>>16)&0xFF); + ip_address.bytes[2]=(uint8_t)((yi_host>>8)&0xFF); + ip_address.bytes[3]=(uint8_t)(yi_host&0xFF); dhcp_state=2; } else if(mtype==DHCP_MSG_NAK){ dhcp_state=-1;