BrewOS 1.40 Beta

BrewOS 1.31 > BrewOS 1.40
Brewkernel 2.3.0 Alpha > Brewkernel 2.3.1 Beta

This update is a feature focused update. It features loads of quality of life and major UX improvements.
New features:
-Drag and drop for files and applications (shortcuts for apps can be made by dragging an app from the start menu into the desktop)
-Customizable desktop (auto align, snap to grid
-Recycle bin (rm in the CMD skips this)
This commit is contained in:
Chris 2026-02-07 21:03:50 +01:00
parent 8e3202f6d8
commit 4c21e732fc
72 changed files with 2365 additions and 488 deletions

View file

@ -1,4 +1,5 @@
# Brew OS 1.20 Alpha
# Brew OS 1.40 Beta
BrewOS is now in a Beta stage as i have brought over all apps from brewkernel and have made the DE a lot more usable and stable.
## 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,12 +10,16 @@ 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
- Drag and drop mouse centered UI
- Customizable UI
- Basic Networking Stack
- Brew WM
- Fat 32 FS
- 64-bit long mode support
- Multiboot2 compliant
- Text editor
- Markdown Viewer
- Minesweeper
- IDT
- Ability to run on actual x86_64 hardware
- CLI

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -35,8 +35,8 @@ static void about_paint(Window *win) {
// Version info
draw_string(offset_x, offset_y + 105, "BrewOS", COLOR_BLACK);
draw_string(offset_x, offset_y + 120, "BrewOS Version 1.30", COLOR_BLACK);
draw_string(offset_x, offset_y + 135, "Kernel Version 2.3.0", COLOR_BLACK);
draw_string(offset_x, offset_y + 120, "BrewOS Version 1.40", COLOR_BLACK);
draw_string(offset_x, offset_y + 135, "Kernel Version 2.3.1", COLOR_BLACK);
// Copyright
draw_string(offset_x, offset_y + 150, "(C) 2026 boreddevnl.", COLOR_BLACK);

View file

@ -2,6 +2,6 @@
void cli_cmd_brewver(char *args) {
(void)args;
cli_write("BrewOS v1.30 Alpha\n");
cli_write("BrewOS Kernel V2.3.0 Pre-Alpha\n");
cli_write("BrewOS v1.40 Beta\n");
cli_write("BrewOS Kernel V2.3.1 Beta\n");
}

View file

@ -158,8 +158,6 @@ static void cmd_set_line_content(const char *str) {
}
}
// Manual and license pages are now in the individual command files
// --- Terminal Emulation ---
static void cmd_scroll_up() {
@ -293,8 +291,8 @@ void pager_wrap_content(const char **lines, int count) {
int chunk_len = remaining;
if (chunk_len > CMD_COLS) chunk_len = CMD_COLS;
// If we are cutting a word, backtrack to last space
if (chunk_len < remaining) { // Only check if we are actually wrapping
// If cutting a word, backtrack to last space
if (chunk_len < remaining) { // Only check if actually wrapping
int split_point = chunk_len;
while (split_point > 0 && line[processed + split_point] != ' ') {
split_point--;
@ -328,6 +326,45 @@ void pager_set_mode(void) {
current_mode = MODE_PAGER;
}
// Internal LS command to avoid stack overflow in external module
static void internal_cmd_ls(char *args) {
char path[256];
if (args && *args) {
int i=0;
while(args[i] && i < 255) { path[i] = args[i]; i++; }
path[i] = 0;
} else {
path[0] = '.'; path[1] = 0;
}
int max_files = 64;
FAT32_FileInfo *files = (FAT32_FileInfo*)kmalloc(max_files * sizeof(FAT32_FileInfo));
if (!files) {
cmd_write("Error: Out of memory\n");
return;
}
int count = fat32_list_directory(path, files, max_files);
for (int i = 0; i < count; i++) {
if (files[i].is_directory) {
cmd_write("[DIR] ");
} else {
cmd_write("[FILE] ");
}
cmd_write(files[i].name);
if (!files[i].is_directory) {
cmd_write(" ");
cmd_write_int(files[i].size);
cmd_write("b");
}
cmd_write("\n");
}
kfree(files);
}
// --- Commands (now delegated to cli_apps/) ---
// Command dispatch table
@ -374,8 +411,8 @@ static const CommandEntry commands[] = {
{"cd", cli_cmd_cd},
{"PWD", cli_cmd_pwd},
{"pwd", cli_cmd_pwd},
{"LS", cli_cmd_ls},
{"ls", cli_cmd_ls},
{"LS", internal_cmd_ls},
{"ls", internal_cmd_ls},
{"MKDIR", cli_cmd_mkdir},
{"mkdir", cli_cmd_mkdir},
{"RM", cli_cmd_rm},
@ -895,12 +932,26 @@ void cmd_reset(void) {
}
static void create_test_files(void) {
fat32_mkdir("Documents");
fat32_mkdir("Projects");
fat32_mkdir("Documents/Important");
fat32_mkdir("Apps");
if (!fat32_exists("Documents")) fat32_mkdir("Documents");
if (!fat32_exists("Projects")) fat32_mkdir("Projects");
if (!fat32_exists("Documents/Important")) fat32_mkdir("Documents/Important");
if (!fat32_exists("Apps")) fat32_mkdir("Apps");
if (!fat32_exists("Desktop")) fat32_mkdir("Desktop");
if (!fat32_exists("RecycleBin")) fat32_mkdir("RecycleBin");
FAT32_FileHandle *fh = fat32_open("README.md", "w");
// Create Desktop Shortcuts
FAT32_FileHandle *fh;
fh = fat32_open("Desktop/Explorer.shortcut", "w"); if(fh) fat32_close(fh);
fh = fat32_open("Desktop/Notepad.shortcut", "w"); if(fh) fat32_close(fh);
fh = fat32_open("Desktop/Calculator.shortcut", "w"); if(fh) fat32_close(fh);
fh = fat32_open("Desktop/Minesweeper.shortcut", "w"); if(fh) fat32_close(fh);
fh = fat32_open("Desktop/Control Panel.shortcut", "w"); if(fh) fat32_close(fh);
fh = fat32_open("Desktop/Terminal.shortcut", "w"); if(fh) fat32_close(fh);
fh = fat32_open("Desktop/About.shortcut", "w"); if(fh) fat32_close(fh);
fh = fat32_open("Desktop/Recycle Bin.shortcut", "w"); if(fh) fat32_close(fh);
// Always try to write README to ensure content exists
fh = fat32_open("README.md", "w");
if (fh) {
const char *content =
"# Brew OS 1.01 Alpha\n\n"
@ -992,8 +1043,8 @@ static void create_test_files(void) {
"The above attribution requirements are informational and intended to\n"
"ensure proper credit is given. They do not alter or supersede the\n"
"terms of the GNU General Public License (GPL), which governs this work.\n";
fat32_write(fh, (void *)content, cmd_strlen(content));
fat32_close(fh);
fat32_write(fh, (void *)content, cmd_strlen(content));
fat32_close(fh);
}
fh = fat32_open("Apps/README.md", "w");
@ -1001,7 +1052,7 @@ static void create_test_files(void) {
const char *content =
"# All compiled C files in this directory are openable from any other directory by typing in the name of the compiled file by typing in the name of the compiled file.\n\n"
"The c file 'wordofgod.c' contains a C program similar to one in TempleOS, which Terry A. Davis (RIP) saw as 'words from god' telling him what to do with his kernel.\n"
"I made this file as a tribute to him, as he also inspired me to create this project in '24. If you want to run it you simply do cc (or compc) wordofgod.c and then run ./wordofgod \n";
"I made this file as a tribute to him, as he also inspired me to create this project in '24. If you want to run it you simply do cc (or compc) wordgod.c and then run ./wordgod \n";
fat32_write(fh, (void *)content, cmd_strlen(content));
fat32_close(fh);
}
@ -1024,74 +1075,60 @@ static void create_test_files(void) {
fh = fat32_open("Apps/wordofgod.c", "w");
if (fh) {
char *h = "int main(){int l;l=malloc(1200);";
fat32_write(fh, h, cmd_strlen(h));
char *w1 = "poke(l+0,\"In \");poke(l+4,\"the \");poke(l+8,\"beginning \");poke(l+12,\"God \");poke(l+16,\"created \");poke(l+20,\"heaven \");poke(l+24,\"and \");poke(l+28,\"earth \");poke(l+32,\"light \");poke(l+36,\"darkness \");";
fat32_write(fh, w1, cmd_strlen(w1));
char *w2 = "poke(l+40,\"day \");poke(l+44,\"night \");poke(l+48,\"waters \");poke(l+52,\"firmament \");poke(l+56,\"evening \");poke(l+60,\"morning \");poke(l+64,\"land \");poke(l+68,\"seas \");poke(l+72,\"grass \");poke(l+76,\"herb \");";
fat32_write(fh, w2, cmd_strlen(w2));
char *w3 = "poke(l+80,\"seed \");poke(l+84,\"fruit \");poke(l+88,\"tree \");poke(l+92,\"sun \");poke(l+96,\"moon \");poke(l+100,\"stars \");poke(l+104,\"signs \");poke(l+108,\"seasons \");poke(l+112,\"days \");poke(l+116,\"years \");";
fat32_write(fh, w3, cmd_strlen(w3));
char *w4 = "poke(l+120,\"creature \");poke(l+124,\"life \");poke(l+128,\"fowl \");poke(l+132,\"whales \");poke(l+136,\"cattle \");poke(l+140,\"creeping \");poke(l+144,\"beast \");poke(l+148,\"man \");poke(l+152,\"image \");poke(l+156,\"likeness \");";
fat32_write(fh, w4, cmd_strlen(w4));
char *w5 = "poke(l+160,\"dominion \");poke(l+164,\"fish \");poke(l+168,\"air \");poke(l+172,\"every \");poke(l+176,\"CIA \");poke(l+180,\"meat \");poke(l+184,\"holy \");poke(l+188,\"rest \");poke(l+192,\"dust \");poke(l+196,\"breath \");";
fat32_write(fh, w5, cmd_strlen(w5));
char *w6 = "poke(l+200,\"soul \");poke(l+204,\"garden \");poke(l+208,\"east \");poke(l+212,\"Eden \");poke(l+216,\"ground \");poke(l+220,\"sight \");poke(l+224,\"good \");poke(l+228,\"evil \");poke(l+232,\"river \");poke(l+236,\"gold \");";
fat32_write(fh, w6, cmd_strlen(w6));
char *w7 = "poke(l+240,\"stone \");poke(l+244,\"woman \");poke(l+248,\"wife \");poke(l+252,\"flesh \");poke(l+256,\"bone \");poke(l+260,\"naked \");poke(l+264,\"serpent \");poke(l+268,\"subtle \");poke(l+272,\"eat \");poke(l+276,\"eyes \");";
fat32_write(fh, w7, cmd_strlen(w7));
char *w8 = "poke(l+280,\"wise \");poke(l+284,\"cool \");poke(l+288,\"voice \");poke(l+292,\"fear \");poke(l+296,\"hid \");poke(l+300,\"cursed \");poke(l+304,\"belly \");poke(l+308,\"enmity \");poke(l+312,\"sorrow \");poke(l+316,\"conception \");";
fat32_write(fh, w8, cmd_strlen(w8));
char *w9 = "poke(l+320,\"children \");poke(l+324,\"desire \");poke(l+328,\"husband \");poke(l+332,\"thorns \");poke(l+336,\"thistles \");poke(l+340,\"sweat \");poke(l+344,\"bread \");poke(l+348,\"mother \");poke(l+352,\"skin \");poke(l+356,\"coats \");";
fat32_write(fh, w9, cmd_strlen(w9));
char *w10 = "poke(l+360,\"cherubims \");poke(l+364,\"sword \");poke(l+368,\"gate \");poke(l+372,\"offering \");poke(l+376,\"respect \");poke(l+380,\"sin \");poke(l+384,\"door \");poke(l+388,\"blood \");poke(l+392,\"brother \");poke(l+396,\"keeper \");";
fat32_write(fh, w10, cmd_strlen(w10));
char *w11 = "poke(l+400,\"voice \");poke(l+404,\"heard \");poke(l+408,\"walking \");poke(l+412,\"cool \");poke(l+416,\"day \");poke(l+420,\"where \");poke(l+424,\"art \");poke(l+428,\"thou \");poke(l+432,\"told \");poke(l+436,\"thee \");";
fat32_write(fh, w11, cmd_strlen(w11));
char *w12 = "poke(l+440,\"hast \");poke(l+444,\"eaten \");poke(l+448,\"tree \");poke(l+452,\"whereof \");poke(l+456,\"commanded \");poke(l+460,\"shouldest \");poke(l+464,\"not \");poke(l+468,\"eat \");poke(l+472,\"gave \");poke(l+476,\"me \");";
fat32_write(fh, w12, cmd_strlen(w12));
char *w13 = "poke(l+480,\"beguiled \");poke(l+484,\"belly \");poke(l+488,\"go \");poke(l+492,\"dust \");poke(l+496,\"shalt \");poke(l+500,\"eat \");poke(l+504,\"days \");poke(l+508,\"life \");poke(l+512,\"put \");poke(l+516,\"enmity \");";
fat32_write(fh, w13, cmd_strlen(w13));
char *w14 = "poke(l+520,\"between \");poke(l+524,\"seed \");poke(l+528,\"bruise \");poke(l+532,\"head \");poke(l+536,\"heel \");poke(l+540,\"multiply \");poke(l+544,\"sorrow \");poke(l+548,\"conception \");poke(l+552,\"forth \");poke(l+556,\"children \");";
fat32_write(fh, w14, cmd_strlen(w14));
char *w15 = "poke(l+560,\"desire \");poke(l+564,\"rule \");poke(l+568,\"over \");poke(l+572,\"sake \");poke(l+576,\"sweat \");poke(l+580,\"face \");poke(l+584,\"till \");poke(l+588,\"return \");poke(l+592,\"ground \");poke(l+596,\"taken \");";
fat32_write(fh, w15, cmd_strlen(w15));
char *w16 = "poke(l+600,\"mother \");poke(l+604,\"living \");poke(l+608,\"coats \");poke(l+612,\"skins \");poke(l+616,\"clothed \");poke(l+620,\"become \");poke(l+624,\"one \");poke(l+628,\"us \");poke(l+632,\"know \");poke(l+636,\"good \");";
fat32_write(fh, w16, cmd_strlen(w16));
char *w17 = "poke(l+640,\"evil \");poke(l+644,\"lest \");poke(l+648,\"put \");poke(l+652,\"hand \");poke(l+656,\"take \");poke(l+660,\"live \");poke(l+664,\"ever \");poke(l+668,\"sent \");poke(l+672,\"garden \");poke(l+676,\"eden \");";
fat32_write(fh, w17, cmd_strlen(w17));
char *w18 = "poke(l+680,\"flaming \");poke(l+684,\"sword \");poke(l+688,\"turned \");poke(l+692,\"way \");poke(l+696,\"knew \");poke(l+700,\"conceived \");poke(l+704,\"bare \");poke(l+708,\"cain \");poke(l+712,\"said \");poke(l+716,\"gotten \");";
fat32_write(fh, w18, cmd_strlen(w18));
char *w19 = "poke(l+720,\"lord \");poke(l+724,\"again \");poke(l+728,\"abel \");poke(l+732,\"sheep \");poke(l+736,\"tiller \");poke(l+740,\"process \");poke(l+744,\"time \");poke(l+748,\"pass \");poke(l+752,\"brought \");poke(l+756,\"fruit \");";
fat32_write(fh, w19, cmd_strlen(w19));
char *w20 = "poke(l+760,\"offering \");poke(l+764,\"firstlings \");poke(l+768,\"flock \");poke(l+772,\"fat \");poke(l+776,\"thereof \");poke(l+780,\"respect \");poke(l+784,\"wroth \");poke(l+788,\"countenance \");poke(l+792,\"fallen \");poke(l+796,\"well \");";
fat32_write(fh, w20, cmd_strlen(w20));
char *w21 = "poke(l+800,\"accepted \");poke(l+804,\"not \");poke(l+808,\"sin \");poke(l+812,\"lieth \");poke(l+816,\"door \");poke(l+820,\"unto \");poke(l+824,\"rule \");poke(l+828,\"talked \");poke(l+832,\"field \");poke(l+836,\"rose \");";
fat32_write(fh, w21, cmd_strlen(w21));
char *w22 = "poke(l+840,\"slew \");poke(l+844,\"done \");poke(l+848,\"crieth \");poke(l+852,\"mouth \");poke(l+856,\"receive \");poke(l+860,\"strength \");poke(l+864,\"fugitive \");poke(l+868,\"vagabond \");poke(l+872,\"punishment \");poke(l+876,\"greater \");";
fat32_write(fh, w22, cmd_strlen(w22));
char *w23 = "poke(l+880,\"bear \");poke(l+884,\"driven \");poke(l+888,\"hid \");poke(l+892,\"findeth \");poke(l+896,\"slay \");poke(l+900,\"vengeance \");poke(l+904,\"sevenfold \");poke(l+908,\"mark \");poke(l+912,\"finding \");poke(l+916,\"kill \");";
fat32_write(fh, w23, cmd_strlen(w23));
char *w24 = "poke(l+920,\"presence \");poke(l+924,\"dwelt \");poke(l+928,\"nod \");poke(l+932,\"enoch \");poke(l+936,\"city \");poke(l+940,\"irad \");poke(l+944,\"mehujael \");poke(l+948,\"methusael \");poke(l+952,\"lamech \");poke(l+956,\"adah \");";
fat32_write(fh, w24, cmd_strlen(w24));
char *w25 = "poke(l+960,\"zillah \");poke(l+964,\"jabal \");poke(l+968,\"tent \");poke(l+972,\"cattle \");poke(l+976,\"jubal \");poke(l+980,\"harp \");poke(l+984,\"organ \");poke(l+988,\"tubalcain \");poke(l+992,\"brass \");poke(l+996,\"iron \");";
fat32_write(fh, w25, cmd_strlen(w25));
char *w26 = "poke(l+1000,\"naamah \");poke(l+1004,\"wives \");poke(l+1008,\"hear \");poke(l+1012,\"speech \");poke(l+1016,\"hearken \");poke(l+1020,\"young \");poke(l+1024,\"hurt \");poke(l+1028,\"wounding \");poke(l+1032,\"avenged \");poke(l+1036,\"seventy \");";
fat32_write(fh, w26, cmd_strlen(w26));
char *w27 = "poke(l+1040,\"seth \");poke(l+1044,\"appointed \");poke(l+1048,\"enos \");poke(l+1052,\"began \");poke(l+1056,\"call \");poke(l+1060,\"name \");poke(l+1064,\"generations \");poke(l+1068,\"adam \");poke(l+1072,\"likeness \");poke(l+1076,\"blessed \");";
fat32_write(fh, w27, cmd_strlen(w27));
char *w28 = "poke(l+1080,\"begat \");poke(l+1084,\"sons \");poke(l+1088,\"daughters \");poke(l+1092,\"lived \");poke(l+1096,\"died \");poke(l+1100,\"cainan \");poke(l+1104,\"mahalaleel \");poke(l+1108,\"jared \");poke(l+1112,\"walked \");poke(l+1116,\"three \");";
fat32_write(fh, w28, cmd_strlen(w28));
char *w29 = "poke(l+1120,\"hundred \");poke(l+1124,\"sixty \");poke(l+1128,\"five \");poke(l+1132,\"methuselah \");poke(l+1136,\"lamech \");poke(l+1140,\"noah \");poke(l+1144,\"comfort \");poke(l+1148,\"work \");poke(l+1152,\"toil \");poke(l+1156,\"hands \");";
fat32_write(fh, w29, cmd_strlen(w29));
char *w30 = "poke(l+1160,\"shem \");poke(l+1164,\"ham \");poke(l+1168,\"japheth \");poke(l+1172,\"men \");poke(l+1176,\"daughters \");poke(l+1180,\"born \");poke(l+1184,\"fair \");poke(l+1188,\"chose \");poke(l+1192,\"spirit \");poke(l+1196,\"strive \");";
fat32_write(fh, w30, cmd_strlen(w30));
char *e = "int c;int r;r=abs(rand());r=r-(r/5)*5;c=14+r;int i;i=0;while(i<c){int x;x=abs(rand());x=x-(x/300)*300;int w;w=peek(l+x*4);print_str(w);i=i+1;}nl();}";
fat32_write(fh, e, cmd_strlen(e));
// Buffer the entire file content to write in one go
// This prevents issues with multiple small writes causing truncation
char *buf = (char*)kmalloc(8192);
if (buf) {
int p = 0;
const char *strs[] = {
"int main(){int l;l=malloc(1200);",
"poke(l+0,\"In \");poke(l+4,\"the \");poke(l+8,\"beginning \");poke(l+12,\"God \");poke(l+16,\"created \");poke(l+20,\"heaven \");poke(l+24,\"and \");poke(l+28,\"earth \");poke(l+32,\"light \");poke(l+36,\"darkness \");",
"poke(l+40,\"day \");poke(l+44,\"night \");poke(l+48,\"waters \");poke(l+52,\"firmament \");poke(l+56,\"evening \");poke(l+60,\"morning \");poke(l+64,\"land \");poke(l+68,\"seas \");poke(l+72,\"grass \");poke(l+76,\"herb \");",
"poke(l+80,\"seed \");poke(l+84,\"fruit \");poke(l+88,\"tree \");poke(l+92,\"sun \");poke(l+96,\"moon \");poke(l+100,\"stars \");poke(l+104,\"signs \");poke(l+108,\"seasons \");poke(l+112,\"days \");poke(l+116,\"years \");",
"poke(l+120,\"creature \");poke(l+124,\"life \");poke(l+128,\"fowl \");poke(l+132,\"whales \");poke(l+136,\"cattle \");poke(l+140,\"creeping \");poke(l+144,\"beast \");poke(l+148,\"man \");poke(l+152,\"image \");poke(l+156,\"likeness \");",
"poke(l+160,\"dominion \");poke(l+164,\"fish \");poke(l+168,\"air \");poke(l+172,\"every \");poke(l+176,\"CIA \");poke(l+180,\"meat \");poke(l+184,\"holy \");poke(l+188,\"rest \");poke(l+192,\"dust \");poke(l+196,\"breath \");",
"poke(l+200,\"soul \");poke(l+204,\"garden \");poke(l+208,\"east \");poke(l+212,\"Eden \");poke(l+216,\"ground \");poke(l+220,\"sight \");poke(l+224,\"good \");poke(l+228,\"evil \");poke(l+232,\"river \");poke(l+236,\"gold \");",
"poke(l+240,\"stone \");poke(l+244,\"woman \");poke(l+248,\"wife \");poke(l+252,\"flesh \");poke(l+256,\"bone \");poke(l+260,\"naked \");poke(l+264,\"serpent \");poke(l+268,\"subtle \");poke(l+272,\"eat \");poke(l+276,\"eyes \");",
"poke(l+280,\"wise \");poke(l+284,\"cool \");poke(l+288,\"voice \");poke(l+292,\"fear \");poke(l+296,\"hid \");poke(l+300,\"cursed \");poke(l+304,\"belly \");poke(l+308,\"enmity \");poke(l+312,\"sorrow \");poke(l+316,\"conception \");",
"poke(l+320,\"children \");poke(l+324,\"desire \");poke(l+328,\"husband \");poke(l+332,\"thorns \");poke(l+336,\"thistles \");poke(l+340,\"sweat \");poke(l+344,\"bread \");poke(l+348,\"mother \");poke(l+352,\"skin \");poke(l+356,\"coats \");",
"poke(l+360,\"cherubims \");poke(l+364,\"sword \");poke(l+368,\"gate \");poke(l+372,\"offering \");poke(l+376,\"respect \");poke(l+380,\"sin \");poke(l+384,\"door \");poke(l+388,\"blood \");poke(l+392,\"brother \");poke(l+396,\"keeper \");",
"poke(l+400,\"voice \");poke(l+404,\"heard \");poke(l+408,\"walking \");poke(l+412,\"cool \");poke(l+416,\"day \");poke(l+420,\"where \");poke(l+424,\"art \");poke(l+428,\"thou \");poke(l+432,\"told \");poke(l+436,\"thee \");",
"poke(l+440,\"hast \");poke(l+444,\"eaten \");poke(l+448,\"tree \");poke(l+452,\"whereof \");poke(l+456,\"commanded \");poke(l+460,\"shouldest \");poke(l+464,\"not \");poke(l+468,\"eat \");poke(l+472,\"gave \");poke(l+476,\"me \");",
"poke(l+480,\"beguiled \");poke(l+484,\"belly \");poke(l+488,\"go \");poke(l+492,\"dust \");poke(l+496,\"shalt \");poke(l+500,\"eat \");poke(l+504,\"days \");poke(l+508,\"life \");poke(l+512,\"put \");poke(l+516,\"enmity \");",
"poke(l+520,\"between \");poke(l+524,\"seed \");poke(l+528,\"bruise \");poke(l+532,\"head \");poke(l+536,\"heel \");poke(l+540,\"multiply \");poke(l+544,\"sorrow \");poke(l+548,\"conception \");poke(l+552,\"forth \");poke(l+556,\"children \");",
"poke(l+560,\"desire \");poke(l+564,\"rule \");poke(l+568,\"over \");poke(l+572,\"sake \");poke(l+576,\"sweat \");poke(l+580,\"face \");poke(l+584,\"till \");poke(l+588,\"return \");poke(l+592,\"ground \");poke(l+596,\"taken \");",
"poke(l+600,\"mother \");poke(l+604,\"living \");poke(l+608,\"coats \");poke(l+612,\"skins \");poke(l+616,\"clothed \");poke(l+620,\"become \");poke(l+624,\"one \");poke(l+628,\"us \");poke(l+632,\"know \");poke(l+636,\"good \");",
"poke(l+640,\"evil \");poke(l+644,\"lest \");poke(l+648,\"put \");poke(l+652,\"hand \");poke(l+656,\"take \");poke(l+660,\"live \");poke(l+664,\"ever \");poke(l+668,\"sent \");poke(l+672,\"garden \");poke(l+676,\"eden \");",
"poke(l+680,\"flaming \");poke(l+684,\"sword \");poke(l+688,\"turned \");poke(l+692,\"way \");poke(l+696,\"knew \");poke(l+700,\"conceived \");poke(l+704,\"bare \");poke(l+708,\"cain \");poke(l+712,\"said \");poke(l+716,\"gotten \");",
"poke(l+720,\"lord \");poke(l+724,\"again \");poke(l+728,\"abel \");poke(l+732,\"sheep \");poke(l+736,\"tiller \");poke(l+740,\"process \");poke(l+744,\"time \");poke(l+748,\"pass \");poke(l+752,\"brought \");poke(l+756,\"fruit \");",
"poke(l+760,\"offering \");poke(l+764,\"firstlings \");poke(l+768,\"flock \");poke(l+772,\"fat \");poke(l+776,\"thereof \");poke(l+780,\"respect \");poke(l+784,\"wroth \");poke(l+788,\"countenance \");poke(l+792,\"fallen \");poke(l+796,\"well \");",
"poke(l+800,\"accepted \");poke(l+804,\"not \");poke(l+808,\"sin \");poke(l+812,\"lieth \");poke(l+816,\"door \");poke(l+820,\"unto \");poke(l+824,\"rule \");poke(l+828,\"talked \");poke(l+832,\"field \");poke(l+836,\"rose \");",
"poke(l+840,\"slew \");poke(l+844,\"done \");poke(l+848,\"crieth \");poke(l+852,\"mouth \");poke(l+856,\"receive \");poke(l+860,\"strength \");poke(l+864,\"fugitive \");poke(l+868,\"vagabond \");poke(l+872,\"punishment \");poke(l+876,\"greater \");",
"poke(l+880,\"bear \");poke(l+884,\"driven \");poke(l+888,\"hid \");poke(l+892,\"findeth \");poke(l+896,\"slay \");poke(l+900,\"vengeance \");poke(l+904,\"sevenfold \");poke(l+908,\"mark \");poke(l+912,\"finding \");poke(l+916,\"kill \");",
"poke(l+920,\"presence \");poke(l+924,\"dwelt \");poke(l+928,\"nod \");poke(l+932,\"enoch \");poke(l+936,\"city \");poke(l+940,\"irad \");poke(l+944,\"mehujael \");poke(l+948,\"methusael \");poke(l+952,\"lamech \");poke(l+956,\"adah \");",
"poke(l+960,\"zillah \");poke(l+964,\"jabal \");poke(l+968,\"tent \");poke(l+972,\"cattle \");poke(l+976,\"jubal \");poke(l+980,\"harp \");poke(l+984,\"organ \");poke(l+988,\"tubalcain \");poke(l+992,\"brass \");poke(l+996,\"iron \");",
"poke(l+1000,\"naamah \");poke(l+1004,\"wives \");poke(l+1008,\"hear \");poke(l+1012,\"speech \");poke(l+1016,\"hearken \");poke(l+1020,\"young \");poke(l+1024,\"hurt \");poke(l+1028,\"wounding \");poke(l+1032,\"avenged \");poke(l+1036,\"seventy \");",
"poke(l+1040,\"seth \");poke(l+1044,\"appointed \");poke(l+1048,\"enos \");poke(l+1052,\"began \");poke(l+1056,\"call \");poke(l+1060,\"name \");poke(l+1064,\"generations \");poke(l+1068,\"adam \");poke(l+1072,\"likeness \");poke(l+1076,\"blessed \");",
"poke(l+1080,\"begat \");poke(l+1084,\"sons \");poke(l+1088,\"daughters \");poke(l+1092,\"lived \");poke(l+1096,\"died \");poke(l+1100,\"cainan \");poke(l+1104,\"mahalaleel \");poke(l+1108,\"jared \");poke(l+1112,\"walked \");poke(l+1116,\"three \");",
"poke(l+1120,\"hundred \");poke(l+1124,\"sixty \");poke(l+1128,\"five \");poke(l+1132,\"methuselah \");poke(l+1136,\"lamech \");poke(l+1140,\"noah \");poke(l+1144,\"comfort \");poke(l+1148,\"work \");poke(l+1152,\"toil \");poke(l+1156,\"hands \");",
"poke(l+1160,\"shem \");poke(l+1164,\"ham \");poke(l+1168,\"japheth \");poke(l+1172,\"men \");poke(l+1176,\"daughters \");poke(l+1180,\"born \");poke(l+1184,\"fair \");poke(l+1188,\"chose \");poke(l+1192,\"spirit \");poke(l+1196,\"strive \");",
"int c;int r;r=abs(rand());r=r-(r/5)*5;c=14+r;int i;i=0;while(i<c){int x;x=abs(rand());x=x-(x/300)*300;int w;w=peek(l+x*4);print_str(w);i=i+1;}nl();}",
NULL
};
for (int i = 0; strs[i]; i++) {
const char *s = strs[i];
while (*s && p < 8191) buf[p++] = *s++;
}
fat32_write(fh, buf, p);
kfree(buf);
}
fat32_close(fh);
}
}
void cmd_init(void) {
fat32_init(); // Init FAT32 filesystem
create_test_files();

View file

@ -17,6 +17,7 @@ Window win_control_panel;
#define VIEW_MAIN 0
#define VIEW_WALLPAPER 1
#define VIEW_NETWORK 2
#define VIEW_DESKTOP 3
static int current_view = VIEW_MAIN;
static char rgb_r[4] = "";
@ -197,6 +198,16 @@ static void control_panel_paint_main(Window *win) {
draw_rect(offset_x + 23, net_offset_y + 5, 1, 11, 0xFFFFFFFF);
draw_string(offset_x + 40, net_offset_y + 8, "Network", 0xFF000000);
// Draw Desktop Settings Icon
int desk_offset_y = net_offset_y + 35;
// Folder icon style
draw_rect(offset_x + 5, desk_offset_y + 2, 12, 4, COLOR_LTGRAY);
draw_rect(offset_x + 5, desk_offset_y + 2, 12, 1, COLOR_BLACK);
draw_rect(offset_x + 5, desk_offset_y + 6, 24, 14, 0xFFE0C060); // Tan folder
draw_rect(offset_x + 5, desk_offset_y + 6, 24, 1, COLOR_BLACK);
draw_rect(offset_x + 5, desk_offset_y + 6, 1, 14, COLOR_BLACK);
draw_string(offset_x + 40, desk_offset_y + 8, "Desktop", 0xFF000000);
}
static void control_panel_paint_wallpaper(Window *win) {
@ -409,6 +420,54 @@ static void control_panel_paint_network(Window *win) {
draw_button(offset_x, section_y, 80, 22, "Send", false);
}
static void control_panel_paint_desktop(Window *win) {
int offset_x = win->x + 8;
int offset_y = win->y + 30;
// Back button
draw_string(offset_x, offset_y, "< Back", 0xFF000080);
draw_string(offset_x, offset_y + 25, "Desktop Settings:", 0xFF000000);
int section_y = offset_y + 50;
// Snap to Grid
draw_rect(offset_x, section_y, 15, 15, 0xFFFFFFFF);
draw_rect(offset_x, section_y, 15, 1, COLOR_BLACK);
draw_rect(offset_x, section_y, 1, 15, COLOR_BLACK);
draw_rect(offset_x + 14, section_y, 1, 15, COLOR_BLACK);
draw_rect(offset_x, section_y + 14, 15, 1, COLOR_BLACK);
if (desktop_snap_to_grid) draw_string(offset_x + 3, section_y + 3, "X", COLOR_BLACK);
draw_string(offset_x + 25, section_y + 3, "Snap to Grid", COLOR_BLACK);
// Auto Align
section_y += 25;
draw_rect(offset_x, section_y, 15, 15, 0xFFFFFFFF);
draw_rect(offset_x, section_y, 15, 1, COLOR_BLACK);
draw_rect(offset_x, section_y, 1, 15, COLOR_BLACK);
draw_rect(offset_x + 14, section_y, 1, 15, COLOR_BLACK);
draw_rect(offset_x, section_y + 14, 15, 1, COLOR_BLACK);
if (desktop_auto_align) draw_string(offset_x + 3, section_y + 3, "X", COLOR_BLACK);
draw_string(offset_x + 25, section_y + 3, "Auto Align Icons", COLOR_BLACK);
// Max Rows
section_y += 25;
draw_string(offset_x, section_y + 3, "Apps per column:", COLOR_BLACK);
draw_button(offset_x + 130, section_y, 20, 20, "-", false);
char num[4]; num[0] = '0' + (desktop_max_rows_per_col / 10); num[1] = '0' + (desktop_max_rows_per_col % 10); num[2] = 0;
if (num[0] == '0') { num[0] = num[1]; num[1] = 0; }
draw_string(offset_x + 160, section_y + 5, num, COLOR_BLACK);
draw_button(offset_x + 180, section_y, 20, 20, "+", false);
// Max Cols
section_y += 25;
draw_string(offset_x, section_y + 3, "Columns:", COLOR_BLACK);
draw_button(offset_x + 130, section_y, 20, 20, "-", false);
char num_c[4]; num_c[0] = '0' + (desktop_max_cols / 10); num_c[1] = '0' + (desktop_max_cols % 10); num_c[2] = 0;
if (num_c[0] == '0') { num_c[0] = num_c[1]; num_c[1] = 0; }
draw_string(offset_x + 160, section_y + 5, num_c, COLOR_BLACK);
draw_button(offset_x + 180, section_y, 20, 20, "+", false);
}
static void control_panel_paint(Window *win) {
if (current_view == VIEW_MAIN) {
control_panel_paint_main(win);
@ -416,6 +475,8 @@ static void control_panel_paint(Window *win) {
control_panel_paint_wallpaper(win);
} else if (current_view == VIEW_NETWORK) {
control_panel_paint_network(win);
} else if (current_view == VIEW_DESKTOP) {
control_panel_paint_desktop(win);
}
}
@ -440,6 +501,13 @@ static void control_panel_handle_click(Window *win, int x, int y) {
current_view = VIEW_NETWORK;
focused_field = -1;
}
// Check desktop button
int desk_offset_y = net_offset_y + 35;
if (x >= offset_x + 5 && x < offset_x + 120 &&
y >= desk_offset_y && y < desk_offset_y + 25) {
current_view = VIEW_DESKTOP;
}
} else if (current_view == VIEW_WALLPAPER) {
int offset_x = 8;
int offset_y = 30;
@ -727,6 +795,73 @@ static void control_panel_handle_click(Window *win, int x, int y) {
}
return;
}
} else if (current_view == VIEW_DESKTOP) {
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;
return;
}
int section_y = offset_y + 50;
// Snap toggle
if (x >= offset_x && x < offset_x + 150 && y >= section_y && y < section_y + 20) {
desktop_snap_to_grid = !desktop_snap_to_grid;
// If Snap is turned OFF, Auto Align must be OFF
if (!desktop_snap_to_grid) {
desktop_auto_align = false;
}
wm_refresh_desktop();
return;
}
// Auto Align toggle
section_y += 25;
if (x >= offset_x && x < offset_x + 150 && y >= section_y && y < section_y + 20) {
desktop_auto_align = !desktop_auto_align;
// If Auto Align is turned ON, Snap must be ON
if (desktop_auto_align) {
desktop_snap_to_grid = true;
}
wm_refresh_desktop();
return;
}
// Rows adjust
section_y += 25;
if (x >= offset_x + 130 && x < offset_x + 150 && y >= section_y && y < section_y + 20) {
if (desktop_max_rows_per_col > 1) {
if (desktop_max_cols * (desktop_max_rows_per_col - 1) < wm_get_desktop_icon_count()) {
wm_show_message("Error", "Cannot reduce rows: too many files!");
} else {
desktop_max_rows_per_col--;
wm_refresh_desktop();
}
}
}
if (x >= offset_x + 180 && x < offset_x + 200 && y >= section_y && y < section_y + 20) {
if (desktop_max_rows_per_col < 15) desktop_max_rows_per_col++;
wm_refresh_desktop();
}
// Cols adjust
section_y += 25;
if (x >= offset_x + 130 && x < offset_x + 150 && y >= section_y && y < section_y + 20) {
if (desktop_max_cols > 1) {
if ((desktop_max_cols - 1) * desktop_max_rows_per_col < wm_get_desktop_icon_count()) {
wm_show_message("Error", "Cannot reduce cols: too many files!");
} else {
desktop_max_cols--;
wm_refresh_desktop();
}
}
}
if (x >= offset_x + 180 && x < offset_x + 200 && y >= section_y && y < section_y + 20) {
if (desktop_max_cols < 20) desktop_max_cols++;
wm_refresh_desktop();
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -12,5 +12,25 @@ extern Window win_markdown;
void explorer_init(void);
void explorer_reset(void);
void explorer_refresh(void);
void explorer_clear_click_state(void);
// Drag and Drop support
bool explorer_get_file_at(int screen_x, int screen_y, char *out_path, bool *is_dir);
void explorer_import_file(const char *source_path);
void explorer_import_file_to(const char *source_path, const char *dest_dir);
// Clipboard
void explorer_clipboard_copy(const char *path);
void explorer_clipboard_cut(const char *path);
void explorer_clipboard_paste(const char *dest_dir);
bool explorer_clipboard_has_content(void);
// File Operations
bool explorer_delete_permanently(const char *path);
bool explorer_delete_recursive(const char *path);
void explorer_create_shortcut(const char *target_path);
void explorer_open_directory(const char *path);
#endif

View file

@ -29,6 +29,7 @@ static FileEntry files[MAX_FILES];
static uint32_t next_cluster = 3; // Start after reserved clusters 0, 1, 2
static FAT32_FileHandle open_handles[MAX_OPEN_HANDLES];
static char current_dir[FAT32_MAX_PATH] = "/";
static int desktop_file_limit = -1;
// === Helper Functions ===
@ -208,6 +209,34 @@ static uint32_t allocate_cluster(void) {
return cluster;
}
// Check desktop limit
static bool check_desktop_limit(const char *normalized_path) {
if (desktop_file_limit < 0) return true;
// Check if path is directly in /Desktop (not subfolder)
// Path should start with /Desktop/ and have no other slashes
if (fs_strlen(normalized_path) > 9 &&
normalized_path[0] == '/' &&
normalized_path[1] == 'D' && normalized_path[2] == 'e' &&
normalized_path[3] == 's' && normalized_path[4] == 'k' &&
normalized_path[5] == 't' && normalized_path[6] == 'o' &&
normalized_path[7] == 'p' && normalized_path[8] == '/') {
// Check for subfolders
const char *p = normalized_path + 9;
while (*p) {
if (*p == '/') return true; // Subfolder, allow
p++;
}
// Count files in /Desktop
FAT32_FileInfo info[256]; // Temp buffer
int count = fat32_list_directory("/Desktop", info, 256);
if (count >= desktop_file_limit) return false;
}
return true;
}
// === Public API ===
void fat32_init(void) {
@ -235,6 +264,10 @@ void fat32_init(void) {
current_dir[1] = 0;
}
void fat32_set_desktop_limit(int limit) {
desktop_file_limit = limit;
}
FAT32_FileHandle* fat32_open(const char *path, const char *mode) {
char normalized[FAT32_MAX_PATH];
fat32_normalize_path(path, normalized);
@ -249,6 +282,10 @@ FAT32_FileHandle* fat32_open(const char *path, const char *mode) {
} else if (mode[0] == 'w' || (mode[0] == 'a')) {
// Write/append mode - create if not exists
if (!entry) {
if (!check_desktop_limit(normalized)) {
return NULL;
}
entry = find_free_entry();
if (!entry) return NULL;
@ -355,7 +392,7 @@ int fat32_write(FAT32_FileHandle *handle, const void *buffer, int size) {
int bytes_written = 0;
const uint8_t *buf = (const uint8_t *)buffer;
// Check if we are at a cluster boundary from a previous write
// Check for cluster boundary from a previous write
if (handle->position > 0 && (handle->position % FAT32_CLUSTER_SIZE) == 0) {
uint32_t next = fat_table[handle->cluster];
if (next >= 0xFFFFFFF8) {
@ -441,6 +478,10 @@ bool fat32_mkdir(const char *path) {
return false; // Already exists
}
if (!check_desktop_limit(normalized)) {
return false;
}
FileEntry *entry = find_free_entry();
if (!entry) return false;

View file

@ -83,6 +83,8 @@ typedef struct {
uint32_t size; // File size
uint32_t mode; // 0=read, 1=write, 2=append
bool valid; // Is this handle valid?
uint32_t dir_sector; // Sector containing the directory entry
uint32_t dir_offset; // Offset within that sector
} FAT32_FileHandle;
// Directory Entry Info (for listing)
@ -124,4 +126,7 @@ void fat32_get_current_dir(char *buffer, int size);
// Utilities
void fat32_normalize_path(const char *path, char *normalized);
// Desktop Limit
void fat32_set_desktop_limit(int limit);
#endif

View file

@ -14,12 +14,16 @@ static bool g_use_pattern = false;
static DirtyRect g_dirty = {0, 0, 0, 0, false};
// Double buffering - allocate a back buffer
// Max screen size: 2048x2048 @ 32bpp = 16MB, but we'll allocate for common sizes
// Max screen size: 2048x2048 @ 32bpp = 16MB, but allocate for common sizes
// Using a simple approach: allocate max size buffer
#define MAX_FB_WIDTH 2048
#define MAX_FB_HEIGHT 2048
static uint32_t g_back_buffer[MAX_FB_WIDTH * MAX_FB_HEIGHT] __attribute__((aligned(4096)));
// Clipping state
static int g_clip_x = 0, g_clip_y = 0, g_clip_w = 0, g_clip_h = 0;
static bool g_clip_enabled = false;
void graphics_init(struct limine_framebuffer *fb) {
g_fb = fb;
g_dirty.active = false;
@ -106,6 +110,13 @@ void put_pixel(int x, int y, uint32_t color) {
if (!g_fb) return;
if (x < 0 || x >= (int)g_fb->width || y < 0 || y >= (int)g_fb->height) return;
if (g_clip_enabled) {
if (x < g_clip_x || x >= g_clip_x + g_clip_w ||
y < g_clip_y || y >= g_clip_y + g_clip_h) {
return;
}
}
// Draw to back buffer
uint32_t pixel_offset = y * g_fb->width + x;
g_back_buffer[pixel_offset] = color;
@ -208,3 +219,15 @@ void graphics_flip_buffer(void) {
dst += g_fb->pitch;
}
}
void graphics_set_clipping(int x, int y, int w, int h) {
g_clip_x = x;
g_clip_y = y;
g_clip_w = w;
g_clip_h = h;
g_clip_enabled = true;
}
void graphics_clear_clipping(void) {
g_clip_enabled = false;
}

View file

@ -34,4 +34,8 @@ void graphics_clear_dirty(void);
void graphics_flip_buffer(void);
void graphics_clear_back_buffer(uint32_t color);
// Clipping
void graphics_set_clipping(int x, int y, int w, int h);
void graphics_clear_clipping(void);
#endif

View file

@ -47,10 +47,6 @@ static void pic_remap(void) {
outb(0x21, 0x01); io_wait();
outb(0xA1, 0x01); io_wait();
// Restore masks (but verify we don't mask IRQ 1 and 12)
// Actually, simple OSs often just mask everything except what they want.
// Let's unmask IRQ 1 (Keyboard) and IRQ 12 (Mouse) explicitly and mask others.
// 0xFD = 1111 1101 (IRQ 1 unmasked)
// 0xEF = 1110 1111 (IRQ 12 (4 on slave) unmasked)
outb(0x21, 0xF9); // Unmask Keyboard (IRQ1) and Cascade (IRQ2)

View file

@ -49,9 +49,6 @@ static void hcf(void) {
void kmain(void) {
platform_init();
// 1. Graphics Init
if (LIMINE_BASE_REVISION_SUPPORTED == false) {
// Warning
}
if (framebuffer_request.response == NULL || framebuffer_request.response->framebuffer_count < 1) {
hcf();

View file

@ -66,7 +66,6 @@ static int md_strncpy(char *dest, const char *src, int n) {
static int md_strcmp(const char *s1, const char *s2) {
(void)s1; // Suppress unused warning
(void)s2; // Suppress unused warning
// Reserved for future use
return 0;
}
@ -74,7 +73,6 @@ static int md_strcmp(const char *s1, const char *s2) {
static bool md_starts_with(const char *str, const char *pattern) {
(void)str; // Suppress unused warning
(void)pattern; // Suppress unused warning
// Reserved for future use
return false;
}

View file

@ -289,7 +289,7 @@ MemStats memory_get_stats(void) {
void memory_print_stats(void) {
MemStats stats = memory_get_stats();
// We need to use the CLI write functions - declare them as extern
// Use CLI write functions - declare as extern
extern void cmd_write(const char *str);
extern void cmd_write_int(int n);
extern void cmd_putchar(char c);

View file

@ -222,8 +222,6 @@ int ipv4_send_packet(const ipv4_address_t* dest_ip,uint8_t protocol,const void*
} else {
int ok=arp_lookup(&target_ip,&dest_mac);
if(ok!=0){
// ARP failed, maybe broadcast? Or fail?
// For now, keep existing behavior of broadcasting if ARP fails
for(int i=0;i<6;i++) dest_mac.bytes[i]=0xFF;
}
}

View file

@ -162,7 +162,7 @@ static void vm_syscall(int id) {
break;
}
case SYS_STRCAT: {
// Not implemented in cli_utils, skip
// Not implemented in cli_utils
pop(); pop(); push(0);
break;
}
@ -188,8 +188,7 @@ static void vm_syscall(int id) {
}
// Simplified Heap (using top of memory growing down?)
// For now, static allocation or mapped.
// Let's implement a dummy malloc that returns an index into memory
// Starting at 1024 (reserve first 1K for globals)
// Dummy malloc that returns an index into memory starting at 1024
case SYS_MALLOC: {
int size = pop();
int res = vm_heap_ptr;
@ -317,8 +316,8 @@ static void vm_syscall(int id) {
push(0);
break;
}
case SYS_EXEC: pop(); push(-1); break; // Not impl
case SYS_SYSTEM: pop(); push(-1); break; // Not impl
case SYS_EXEC: pop(); push(-1); break;
case SYS_SYSTEM: pop(); push(-1); break;
// --- New Builtins ---
case SYS_ISALNUM: {
@ -601,7 +600,6 @@ int vm_exec(const uint8_t *code, int code_size) {
break;
}
case OP_POP:
// cmd_write("DEBUG: POP\n");
pop();
break;
default:

File diff suppressed because it is too large Load diff

View file

@ -51,7 +51,10 @@ void wm_process_input(void);
void wm_mark_dirty(int x, int y, int w, int h);
void wm_refresh(void);
void wm_paint(void);
void wm_refresh_desktop(void);
void wm_timer_tick(void);
int wm_get_desktop_icon_count(void);
void wm_show_message(const char *title, const char *message);
// Hook for external rendering (e.g. VM overlay)
extern void (*wm_custom_paint_hook)(void);
@ -59,5 +62,21 @@ extern void (*wm_custom_paint_hook)(void);
// Drawing helpers
void draw_bevel_rect(int x, int y, int w, int h, bool sunken);
void draw_button(int x, int y, int w, int h, const char *text, bool pressed);
void draw_icon(int x, int y, const char *label);
void draw_folder_icon(int x, int y, const char *label);
void draw_document_icon(int x, int y, const char *label);
void draw_notepad_icon(int x, int y, const char *label);
void draw_calculator_icon(int x, int y, const char *label);
void draw_terminal_icon(int x, int y, const char *label);
void draw_minesweeper_icon(int x, int y, const char *label);
void draw_control_panel_icon(int x, int y, const char *label);
void draw_about_icon(int x, int y, const char *label);
void draw_recycle_bin_icon(int x, int y, const char *label);
// Desktop Settings
extern bool desktop_snap_to_grid;
extern bool desktop_auto_align;
extern int desktop_max_rows_per_col;
extern int desktop_max_cols;
#endif