mirror of
https://github.com/JannisHeydemann/BoredOS.git
synced 2026-05-30 10:26:59 +00:00
Compare commits
20 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e738041020 | ||
|
|
9830b6ad96 | ||
|
|
a09103e40d | ||
|
|
aff3e99ab2 | ||
|
|
93bf2e1734 | ||
|
|
eaa02c9a5d | ||
|
|
0ad151d7fc | ||
|
|
b54e371f3f | ||
|
|
79eeaa73d9 | ||
|
|
481eb42268 | ||
|
|
feb0d6ffbf | ||
|
|
67ebcb98d1 | ||
|
|
957c74365c | ||
|
|
31b6f48a2c | ||
|
|
67b7bb1a97 | ||
|
|
e05ff65f92 | ||
|
|
40f63097e1 | ||
|
|
d677d37b1c | ||
|
|
9b6297c917 | ||
|
|
dd6cbf1fe0 |
10
README.md
10
README.md
@@ -7,13 +7,14 @@
|
|||||||
[](https://www.gnu.org/licenses/gpl-3.0)
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
||||||

|

|
||||||

|

|
||||||
|
[](https://buymeacoffee.com/boreddevhq)
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
BoredOS is a x86_64 operating system featuring a custom Desktop Environment (DE), a dedicated Window Manager (BoredWM), and a FAT32 filesystem. It balances low-level kernel exploration with a surprisingly capable userspace.
|
BoredOS is a x86_64 operating system featuring a custom Desktop Environment (DE), a dedicated Window Manager (BoredWM), and a FAT32 filesystem. It balances low-level kernel exploration with a surprisingly capable userspace.
|
||||||
|
|
||||||

|

|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> *The screenshot above may represent a previous build and is subject to change as the UI evolves.*
|
> *The screenshot above may represent a previous build and is subject to change as the UI evolves.*
|
||||||
|
|
||||||
@@ -34,7 +35,7 @@ BoredOS is a x86_64 operating system featuring a custom Desktop Environment (DE)
|
|||||||
### Graphical User Interface
|
### Graphical User Interface
|
||||||
* **BoredWM:** A custom Window Manager with drag-and-drop, mouse-centered interaction.
|
* **BoredWM:** A custom Window Manager with drag-and-drop, mouse-centered interaction.
|
||||||
* **Customization:** Adjustable UI to suit your aesthetic.
|
* **Customization:** Adjustable UI to suit your aesthetic.
|
||||||
* **Media Support:** Built-in image decoding.
|
* **Media Support:** Built-in image decoding. (PNG, GIF, JPEG, TGA, BMP)
|
||||||
|
|
||||||
### Included Applications
|
### Included Applications
|
||||||
* **Productivity:** GUI Text Editor calculator, Markdown Viewer, a simple browser and BoredWord.
|
* **Productivity:** GUI Text Editor calculator, Markdown Viewer, a simple browser and BoredWord.
|
||||||
@@ -77,6 +78,11 @@ While BrewKernel served as the foundational learning ground for this OS, it has
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
- **boreddevnl** — Project creator and lead maintainer.
|
||||||
|
- **Lluciocc** — Contributor.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
**Copyright (C) 2024-2026 boreddevnl**
|
**Copyright (C) 2024-2026 boreddevnl**
|
||||||
|
|||||||
13
docs/build/usage.md
vendored
13
docs/build/usage.md
vendored
@@ -33,14 +33,21 @@ To run BoredOS successfully (either in emulation or on bare metal), your target
|
|||||||
|
|
||||||
To test the generated ISO quickly without real hardware, use the QEMU emulator:
|
To test the generated ISO quickly without real hardware, use the QEMU emulator:
|
||||||
|
|
||||||
|
For MacOS:
|
||||||
```sh
|
```sh
|
||||||
make run
|
make run-mac
|
||||||
|
```
|
||||||
|
For Linux:
|
||||||
|
```sh
|
||||||
|
make run-linux
|
||||||
|
```
|
||||||
|
For Windows:
|
||||||
|
```sh
|
||||||
|
make run-windows
|
||||||
```
|
```
|
||||||
|
|
||||||
This command invokes QEMU with specific arguments:
|
This command invokes QEMU with specific arguments:
|
||||||
- `-m 4G`: Allocates 4 Gigabytes of RAM.
|
- `-m 4G`: Allocates 4 Gigabytes of RAM.
|
||||||
- `-cdrom boredos.iso`: Mounts the built OS image as a CD-ROM.
|
- `-cdrom boredos.iso`: Mounts the built OS image as a CD-ROM.
|
||||||
- `-netdev user...`: Sets up a basic NAT network interface for the OS's networking stack.
|
|
||||||
- `-smp 4`: Enables 4 CPU cores.
|
- `-smp 4`: Enables 4 CPU cores.
|
||||||
- `-drive file=disk.img...`: Attaches a raw disk image included in this release of BoredOS.
|
- `-drive file=disk.img...`: Attaches a raw disk image included in this release of BoredOS.
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ Bsh loads its configuration from:
|
|||||||
|
|
||||||
`/Library/bsh/bshrc`
|
`/Library/bsh/bshrc`
|
||||||
|
|
||||||
This file is similar to `.zshrc` and can define:
|
This file is similar to `.zshrc` or `.bashrc` and can define:
|
||||||
- `PATH` for command lookup
|
- `PATH` for command lookup
|
||||||
- `STARTUP` for interactive shell startup scripts
|
- `STARTUP` for interactive shell startup scripts
|
||||||
- `BOOT_SCRIPT` for a once-per-boot script
|
- `BOOT_SCRIPT` for a once-per-boot script
|
||||||
|
|||||||
BIN
screenshot.jpg
BIN
screenshot.jpg
Binary file not shown.
|
Before Width: | Height: | Size: 342 KiB |
BIN
screenshot.png
Executable file
BIN
screenshot.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 988 KiB |
@@ -279,6 +279,11 @@ void kmain(void) {
|
|||||||
fat32_mkdir("/Library/DOOM");
|
fat32_mkdir("/Library/DOOM");
|
||||||
fat32_mkdir("/Library/bsh");
|
fat32_mkdir("/Library/bsh");
|
||||||
fat32_mkdir("/docs");
|
fat32_mkdir("/docs");
|
||||||
|
fat32_mkdir("/root");
|
||||||
|
fat32_mkdir("/root/Desktop");
|
||||||
|
fat32_mkdir("/root/Pictures");
|
||||||
|
fat32_mkdir("/root/Documents");
|
||||||
|
fat32_mkdir("/root/Downloads");
|
||||||
|
|
||||||
sysfs_init_subsystems();
|
sysfs_init_subsystems();
|
||||||
vfs_mount("/sys", "sysfs", "sysfs", sysfs_get_ops(), NULL);
|
vfs_mount("/sys", "sysfs", "sysfs", sysfs_get_ops(), NULL);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ void get_os_info(os_info_t *info) {
|
|||||||
for (size_t i = 0; i < sizeof(os_info_t); i++) p[i] = 0;
|
for (size_t i = 0; i < sizeof(os_info_t); i++) p[i] = 0;
|
||||||
|
|
||||||
const char *os_name = "BoredOS";
|
const char *os_name = "BoredOS";
|
||||||
const char *os_version = "26.4.2";
|
const char *os_version = "26.4.2.1";
|
||||||
const char *os_codename = "Voyager";
|
const char *os_codename = "Voyager";
|
||||||
const char *kernel_name = "Boredkernel";
|
const char *kernel_name = "Boredkernel";
|
||||||
const char *kernel_version = "4.1.0-stable";
|
const char *kernel_version = "4.1.0-stable";
|
||||||
|
|||||||
@@ -1248,7 +1248,8 @@ static int read_line(char *out, int max_len, const char *prompt) {
|
|||||||
char ch = 0;
|
char ch = 0;
|
||||||
int got = sys_tty_read_in(&ch, 1);
|
int got = sys_tty_read_in(&ch, 1);
|
||||||
if (got <= 0) {
|
if (got <= 0) {
|
||||||
sys_yield();
|
// Throttle idle input polling to avoid pegging the CPU at 100%
|
||||||
|
sleep(1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "libc/syscall.h"
|
#include "libc/syscall.h"
|
||||||
#include "libc/libui.h"
|
#include "libc/libui.h"
|
||||||
#include "libc/stdlib.h"
|
#include "libc/stdlib.h"
|
||||||
|
#include "libc/input.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -399,44 +400,26 @@ static void game_paint(ui_window_t win) {
|
|||||||
draw_status(win);
|
draw_status(win);
|
||||||
|
|
||||||
draw_board(win);
|
draw_board(win);
|
||||||
/* Not recommended to use
|
|
||||||
draw_button(win, 18, 352, 86, 30, "Restart", COLOR_ACCENT);
|
|
||||||
draw_button(win, 123, 352, BTN_W, BTN_H, "Left", COLOR_BORDER);
|
|
||||||
draw_button(win, 186, 352, BTN_W, BTN_H, "Right", COLOR_BORDER);
|
|
||||||
draw_button(win, 92, 390, BTN_W, BTN_H, "Up", COLOR_BORDER);
|
|
||||||
draw_button(win, 155, 390, BTN_W, BTN_H, "Down", COLOR_BORDER);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool point_in_rect(int px, int py, int x, int y, int w, int h) {
|
static bool point_in_rect(int px, int py, int x, int y, int w, int h) {
|
||||||
return px >= x && px < x + w && py >= y && py < y + h;
|
return px >= x && px < x + w && py >= y && py < y + h;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
37 = left arrow
|
|
||||||
38 = up arrow
|
|
||||||
39 = right arrow
|
|
||||||
40 = down arrow
|
|
||||||
72 = numpad 8
|
|
||||||
75 = numpad 4
|
|
||||||
77 = numpad 6
|
|
||||||
80 = numpad 2
|
|
||||||
key = letter
|
|
||||||
*/
|
|
||||||
static bool is_left_key(int key) {
|
static bool is_left_key(int key) {
|
||||||
return key == 'a' || key == 'A' || key == 37 || key == 75;
|
return key == 'a' || key == 'A' || key == KEY_LEFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_right_key(int key) {
|
static bool is_right_key(int key) {
|
||||||
return key == 'd' || key == 'D' || key == 39 || key == 77;
|
return key == 'd' || key == 'D' || key == KEY_RIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_up_key(int key) {
|
static bool is_up_key(int key) {
|
||||||
return key == 'w' || key == 'W' || key == 38 || key == 72;
|
return key == 'w' || key == 'W' || key == KEY_UP;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_down_key(int key) {
|
static bool is_down_key(int key) {
|
||||||
return key == 's' || key == 'S' || key == 40 || key == 80;
|
return key == 's' || key == 'S' || key == KEY_DOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_click(int x, int y) {
|
static void handle_click(int x, int y) {
|
||||||
|
|||||||
390
src/userland/games/snake.c
Normal file
390
src/userland/games/snake.c
Normal file
@@ -0,0 +1,390 @@
|
|||||||
|
#include "libc/syscall.h"
|
||||||
|
#include "libc/libui.h"
|
||||||
|
#include "libc/stdlib.h"
|
||||||
|
#include "libc/input.h"
|
||||||
|
#include "libc/string.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/* @Lluciocc Snake for BoredOS
|
||||||
|
Controls:
|
||||||
|
- WASD keys or arrow keys or numpad keys to move
|
||||||
|
- R key to restart
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WINDOW_W 340
|
||||||
|
#define WINDOW_H 420
|
||||||
|
|
||||||
|
#define GRID_W 18
|
||||||
|
#define GRID_H 18
|
||||||
|
#define CELL_SIZE 16
|
||||||
|
|
||||||
|
#define BOARD_X 26
|
||||||
|
#define BOARD_Y 70
|
||||||
|
#define BOARD_W (GRID_W * CELL_SIZE)
|
||||||
|
#define BOARD_H (GRID_H * CELL_SIZE)
|
||||||
|
|
||||||
|
#define MAX_SNAKE_LEN (GRID_W * GRID_H)
|
||||||
|
|
||||||
|
#define GAME_TICK_DELAY 6
|
||||||
|
|
||||||
|
#define COLOR_BG 0xFF121212
|
||||||
|
#define COLOR_PANEL 0xFF202020
|
||||||
|
#define COLOR_PANEL_2 0xFF2A2A2A
|
||||||
|
#define COLOR_BORDER 0xFF3D3D3D
|
||||||
|
#define COLOR_TEXT 0xFFEAEAEA
|
||||||
|
#define COLOR_MUTED 0xFFBBBBBB
|
||||||
|
#define COLOR_ACCENT 0xFF6EA8FE
|
||||||
|
#define COLOR_GREEN 0xFF69DB7C
|
||||||
|
#define COLOR_RED 0xFFFF6B6B
|
||||||
|
#define COLOR_FOOD 0xFFFF8FA3
|
||||||
|
#define COLOR_SNAKE_HEAD 0xFF7CFC8A
|
||||||
|
#define COLOR_SNAKE_BODY 0xFF43C463
|
||||||
|
#define COLOR_GRID_CELL 0xFF262626
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
} point_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DIR_UP,
|
||||||
|
DIR_RIGHT,
|
||||||
|
DIR_DOWN,
|
||||||
|
DIR_LEFT
|
||||||
|
} direction_t;
|
||||||
|
|
||||||
|
static point_t snake[MAX_SNAKE_LEN];
|
||||||
|
static int snake_len = 0;
|
||||||
|
|
||||||
|
static point_t food;
|
||||||
|
|
||||||
|
static direction_t current_dir = DIR_RIGHT;
|
||||||
|
static direction_t next_dir = DIR_RIGHT;
|
||||||
|
|
||||||
|
static bool game_over = false;
|
||||||
|
static bool game_started = false;
|
||||||
|
|
||||||
|
static int score = 0;
|
||||||
|
static int best_score = 0;
|
||||||
|
|
||||||
|
/* poor-man timer */
|
||||||
|
static uint32_t tick_counter = 0;
|
||||||
|
static int game_speed_ms = 80; // default (milliseconds per move)
|
||||||
|
|
||||||
|
static uint32_t random_seed = 0x1234ABCDu;
|
||||||
|
|
||||||
|
static uint32_t random_next(void) {
|
||||||
|
random_seed = random_seed * 1664525u + 1013904223u;
|
||||||
|
return random_seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int max_int(int a, int b) {
|
||||||
|
return (a > b) ? a : b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool point_equals(point_t a, point_t b) {
|
||||||
|
return a.x == b.x && a.y == b.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool snake_occupies_cell(int x, int y) {
|
||||||
|
for (int i = 0; i < snake_len; i++) {
|
||||||
|
if (snake[i].x == x && snake[i].y == y) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void spawn_food(void) {
|
||||||
|
int free_count = 0;
|
||||||
|
|
||||||
|
for (int y = 0; y < GRID_H; y++) {
|
||||||
|
for (int x = 0; x < GRID_W; x++) {
|
||||||
|
if (!snake_occupies_cell(x, y)) {
|
||||||
|
free_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (free_count <= 0) {
|
||||||
|
game_over = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pick = (int)(random_next() % (uint32_t)free_count);
|
||||||
|
|
||||||
|
for (int y = 0; y < GRID_H; y++) {
|
||||||
|
for (int x = 0; x < GRID_W; x++) {
|
||||||
|
if (!snake_occupies_cell(x, y)) {
|
||||||
|
if (pick == 0) {
|
||||||
|
food.x = x;
|
||||||
|
food.y = y;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pick--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_game(void) {
|
||||||
|
snake_len = 3;
|
||||||
|
|
||||||
|
snake[0].x = GRID_W / 2;
|
||||||
|
snake[0].y = GRID_H / 2;
|
||||||
|
|
||||||
|
snake[1].x = snake[0].x - 1;
|
||||||
|
snake[1].y = snake[0].y;
|
||||||
|
|
||||||
|
snake[2].x = snake[0].x - 2;
|
||||||
|
snake[2].y = snake[0].y;
|
||||||
|
|
||||||
|
current_dir = DIR_RIGHT;
|
||||||
|
next_dir = DIR_RIGHT;
|
||||||
|
|
||||||
|
score = 0;
|
||||||
|
game_over = false;
|
||||||
|
game_started = true;
|
||||||
|
|
||||||
|
tick_counter = 0;
|
||||||
|
|
||||||
|
spawn_food();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_opposite_direction(direction_t a, direction_t b) {
|
||||||
|
return (a == DIR_UP && b == DIR_DOWN) ||
|
||||||
|
(a == DIR_DOWN && b == DIR_UP) ||
|
||||||
|
(a == DIR_LEFT && b == DIR_RIGHT) ||
|
||||||
|
(a == DIR_RIGHT && b == DIR_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void request_direction(direction_t dir) {
|
||||||
|
if (snake_len > 1 && is_opposite_direction(current_dir, dir)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
next_dir = dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void move_snake_step(void) {
|
||||||
|
if (!game_started || game_over) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_dir = next_dir;
|
||||||
|
|
||||||
|
point_t new_head = snake[0];
|
||||||
|
|
||||||
|
if (current_dir == DIR_UP) new_head.y--;
|
||||||
|
else if (current_dir == DIR_RIGHT) new_head.x++;
|
||||||
|
else if (current_dir == DIR_DOWN) new_head.y++;
|
||||||
|
else if (current_dir == DIR_LEFT) new_head.x--;
|
||||||
|
|
||||||
|
if (new_head.x < 0 || new_head.x >= GRID_W ||
|
||||||
|
new_head.y < 0 || new_head.y >= GRID_H) {
|
||||||
|
game_over = true;
|
||||||
|
best_score = max_int(best_score, score);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool grows = point_equals(new_head, food);
|
||||||
|
int collision_check_len = grows ? snake_len : (snake_len - 1);
|
||||||
|
|
||||||
|
for (int i = 0; i < collision_check_len; i++) {
|
||||||
|
if (point_equals(new_head, snake[i])) {
|
||||||
|
game_over = true;
|
||||||
|
best_score = max_int(best_score, score);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int old_len = snake_len;
|
||||||
|
|
||||||
|
if (grows && snake_len < MAX_SNAKE_LEN) {
|
||||||
|
snake_len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = snake_len - 1; i > 0; i--) {
|
||||||
|
if (i - 1 < old_len) {
|
||||||
|
snake[i] = snake[i - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
snake[0] = new_head;
|
||||||
|
|
||||||
|
if (grows) {
|
||||||
|
score++;
|
||||||
|
best_score = max_int(best_score, score);
|
||||||
|
spawn_food();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void int_to_text(int value, char *out) {
|
||||||
|
itoa(value, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool point_in_rect(int px, int py, int x, int y, int w, int h) {
|
||||||
|
return px >= x && px < x + w && py >= y && py < y + h;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Input helpers */
|
||||||
|
|
||||||
|
static bool is_left_key(int key) {
|
||||||
|
return key == 'a' || key == 'A' || key == KEY_LEFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_right_key(int key) {
|
||||||
|
return key == 'd' || key == 'D' || key == KEY_RIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_up_key(int key) {
|
||||||
|
return key == 'w' || key == 'W' || key == KEY_UP;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_down_key(int key) {
|
||||||
|
return key == 's' || key == 'S' || key == KEY_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void draw_board(ui_window_t win) {
|
||||||
|
ui_draw_rounded_rect_filled(
|
||||||
|
win,
|
||||||
|
BOARD_X - 6,
|
||||||
|
BOARD_Y - 6,
|
||||||
|
BOARD_W + 12,
|
||||||
|
BOARD_H + 12,
|
||||||
|
8,
|
||||||
|
COLOR_PANEL_2
|
||||||
|
);
|
||||||
|
|
||||||
|
for (int y = 0; y < GRID_H; y++) {
|
||||||
|
for (int x = 0; x < GRID_W; x++) {
|
||||||
|
int px = BOARD_X + x * CELL_SIZE;
|
||||||
|
int py = BOARD_Y + y * CELL_SIZE;
|
||||||
|
|
||||||
|
ui_draw_rect(win, px, py, CELL_SIZE - 1, CELL_SIZE - 1, COLOR_GRID_CELL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int fx = BOARD_X + food.x * CELL_SIZE;
|
||||||
|
int fy = BOARD_Y + food.y * CELL_SIZE;
|
||||||
|
|
||||||
|
ui_draw_rounded_rect_filled(win, fx + 2, fy + 2, CELL_SIZE - 5, CELL_SIZE - 5, 4, COLOR_FOOD);
|
||||||
|
|
||||||
|
for (int i = snake_len - 1; i >= 0; i--) {
|
||||||
|
int px = BOARD_X + snake[i].x * CELL_SIZE;
|
||||||
|
int py = BOARD_Y + snake[i].y * CELL_SIZE;
|
||||||
|
|
||||||
|
uint32_t color = (i == 0) ? COLOR_SNAKE_HEAD : COLOR_SNAKE_BODY;
|
||||||
|
|
||||||
|
ui_draw_rounded_rect_filled(win, px + 1, py + 1, CELL_SIZE - 3, CELL_SIZE - 3, 4, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void snake_paint(ui_window_t win) {
|
||||||
|
char score_buf[16] = {0};
|
||||||
|
char best_buf[16] = {0};
|
||||||
|
|
||||||
|
ui_draw_rect(win, 0, 0, WINDOW_W, WINDOW_H, COLOR_BG);
|
||||||
|
|
||||||
|
ui_draw_string(win, 16, 14, "Snake", COLOR_TEXT);
|
||||||
|
ui_draw_string(win, 16, 34, "WASD or Arrow Keys", COLOR_MUTED);
|
||||||
|
|
||||||
|
int_to_text(score, score_buf);
|
||||||
|
int_to_text(best_score, best_buf);
|
||||||
|
|
||||||
|
ui_draw_rounded_rect_filled(win, 190, 12, 56, 24, 6, COLOR_PANEL);
|
||||||
|
ui_draw_string(win, 198, 20, "Score", COLOR_MUTED);
|
||||||
|
ui_draw_string(win, 250, 20, score_buf, COLOR_TEXT);
|
||||||
|
|
||||||
|
ui_draw_rounded_rect_filled(win, 250, 12, 64, 24, 6, COLOR_PANEL);
|
||||||
|
ui_draw_string(win, 258, 20, "Best", COLOR_MUTED);
|
||||||
|
ui_draw_string(win, 292, 20, best_buf, COLOR_TEXT);
|
||||||
|
|
||||||
|
if (game_over) {
|
||||||
|
ui_draw_string(win, 16, 52, "Game Over - Press R to restart", COLOR_RED);
|
||||||
|
} else {
|
||||||
|
ui_draw_string(win, 16, 52, "Eat food and avoid walls and yourself", COLOR_MUTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_board(win);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_click(int x, int y) {
|
||||||
|
if (point_in_rect(x, y, 16, 370, 72, 28)) {
|
||||||
|
init_game();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_key(int key) {
|
||||||
|
if (key == 'r' || key == 'R') {
|
||||||
|
init_game();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (game_over) return;
|
||||||
|
|
||||||
|
if (is_left_key(key)) request_direction(DIR_LEFT);
|
||||||
|
else if (is_right_key(key)) request_direction(DIR_RIGHT);
|
||||||
|
else if (is_up_key(key)) request_direction(DIR_UP);
|
||||||
|
else if (is_down_key(key)) request_direction(DIR_DOWN);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
int game_speed_ms = 80;
|
||||||
|
|
||||||
|
// Parse arguments
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
|
if (strcmp(argv[i], "-speed") == 0 && i + 1 < argc) {
|
||||||
|
int val = atoi(argv[i + 1]);
|
||||||
|
|
||||||
|
// Clamp to safe range
|
||||||
|
if (val < 20) val = 20;
|
||||||
|
if (val > 500) val = 500;
|
||||||
|
|
||||||
|
game_speed_ms = val;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_window_t win = ui_window_create("Snake", 220, 120, WINDOW_W, WINDOW_H);
|
||||||
|
if (!win) return 1;
|
||||||
|
|
||||||
|
ui_window_set_resizable(win, false);
|
||||||
|
|
||||||
|
init_game();
|
||||||
|
|
||||||
|
snake_paint(win);
|
||||||
|
ui_mark_dirty(win, 0, 0, WINDOW_W, WINDOW_H);
|
||||||
|
|
||||||
|
gui_event_t ev;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
while (ui_get_event(win, &ev)) {
|
||||||
|
if (ev.type == GUI_EVENT_PAINT) {
|
||||||
|
snake_paint(win);
|
||||||
|
ui_mark_dirty(win, 0, 0, WINDOW_W, WINDOW_H);
|
||||||
|
|
||||||
|
} else if (ev.type == GUI_EVENT_CLICK) {
|
||||||
|
handle_click(ev.arg1, ev.arg2);
|
||||||
|
|
||||||
|
} else if (ev.type == GUI_EVENT_KEY) {
|
||||||
|
handle_key(ev.arg1);
|
||||||
|
|
||||||
|
} else if (ev.type == GUI_EVENT_CLOSE) {
|
||||||
|
sys_exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
move_snake_step();
|
||||||
|
|
||||||
|
snake_paint(win);
|
||||||
|
ui_mark_dirty(win, 0, 0, WINDOW_W, WINDOW_H);
|
||||||
|
|
||||||
|
sleep(game_speed_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
62
src/userland/gui/keylog.c
Normal file
62
src/userland/gui/keylog.c
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#include "libc/syscall.h"
|
||||||
|
#include "libc/libui.h"
|
||||||
|
#include "libc/stdlib.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
@Lluciocc
|
||||||
|
The most SIMPLE keylogger for debug
|
||||||
|
FEAT:
|
||||||
|
- Log every key pressed in the terminal and gives their keycode
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define WINDOW_W 400
|
||||||
|
#define WINDOW_H 200
|
||||||
|
|
||||||
|
static int last_key = -1;
|
||||||
|
|
||||||
|
static void draw(ui_window_t win) {
|
||||||
|
ui_draw_rect(win, 0, 0, WINDOW_W, WINDOW_H, 0xFF121212);
|
||||||
|
|
||||||
|
ui_draw_string(win, 20, 20, "Key Logger", 0xFFFFFFFF);
|
||||||
|
|
||||||
|
if (last_key >= 0) {
|
||||||
|
char buf[32];
|
||||||
|
itoa(last_key, buf);
|
||||||
|
|
||||||
|
ui_draw_string(win, 20, 60, "Last key:", 0xFFAAAAAA);
|
||||||
|
ui_draw_string(win, 20, 90, buf, 0xFF6EA8FE);
|
||||||
|
} else {
|
||||||
|
ui_draw_string(win, 20, 60, "Press any key...", 0xFFAAAAAA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
ui_window_t win = ui_window_create("keylog", 100, 100, WINDOW_W, WINDOW_H);
|
||||||
|
if (!win) return 1;
|
||||||
|
|
||||||
|
gui_event_t ev;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
if (ui_get_event(win, &ev)) {
|
||||||
|
|
||||||
|
if (ev.type == GUI_EVENT_KEY) {
|
||||||
|
last_key = ev.arg1;
|
||||||
|
|
||||||
|
printf("Key pressed: %d\n", ev.arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ev.type == GUI_EVENT_CLOSE) {
|
||||||
|
sys_exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
draw(win);
|
||||||
|
ui_mark_dirty(win, 0, 0, WINDOW_W, WINDOW_H);
|
||||||
|
} else {
|
||||||
|
sys_yield();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -27,8 +27,8 @@ static int cpu_history[GRAPH_POINTS];
|
|||||||
static int mem_history[GRAPH_POINTS];
|
static int mem_history[GRAPH_POINTS];
|
||||||
static int history_idx = 0;
|
static int history_idx = 0;
|
||||||
|
|
||||||
static uint64_t uptime_prev = 0;
|
static uint64_t user_ticks_prev = 0;
|
||||||
static uint64_t kernel_ticks_prev = 0;
|
static uint64_t total_ticks_prev = 0;
|
||||||
static uint64_t total_mem_system = 0;
|
static uint64_t total_mem_system = 0;
|
||||||
static uint64_t used_mem_system = 0;
|
static uint64_t used_mem_system = 0;
|
||||||
static char cpu_model_name[64] = "Unknown CPU";
|
static char cpu_model_name[64] = "Unknown CPU";
|
||||||
@@ -76,6 +76,7 @@ static void update_proc_list(void) {
|
|||||||
|
|
||||||
proc_count = 0;
|
proc_count = 0;
|
||||||
uint64_t user_ticks_now = 0;
|
uint64_t user_ticks_now = 0;
|
||||||
|
uint64_t total_ticks_now = 0;
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
if (entries[i].is_directory) {
|
if (entries[i].is_directory) {
|
||||||
@@ -107,6 +108,7 @@ static void update_proc_list(void) {
|
|||||||
proc_list[proc_count].used_memory = (size_t)find_value(buf, "Memory") * 1024;
|
proc_list[proc_count].used_memory = (size_t)find_value(buf, "Memory") * 1024;
|
||||||
uint64_t ticks = (uint64_t)find_value(buf, "Ticks");
|
uint64_t ticks = (uint64_t)find_value(buf, "Ticks");
|
||||||
proc_list[proc_count].ticks = ticks;
|
proc_list[proc_count].ticks = ticks;
|
||||||
|
total_ticks_now += ticks;
|
||||||
|
|
||||||
proc_list[proc_count].is_idle = find_value(buf, "Idle") == 1;
|
proc_list[proc_count].is_idle = find_value(buf, "Idle") == 1;
|
||||||
|
|
||||||
@@ -118,32 +120,19 @@ static void update_proc_list(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Global stats
|
if (total_ticks_prev > 0) {
|
||||||
int fd_u = sys_open("/proc/uptime", "r");
|
uint64_t total_delta = total_ticks_now - total_ticks_prev;
|
||||||
uint64_t uptime_now = 0;
|
|
||||||
if (fd_u >= 0) {
|
|
||||||
char buf[256];
|
|
||||||
int bytes = sys_read(fd_u, buf, 255);
|
|
||||||
sys_close(fd_u);
|
|
||||||
if (bytes > 0) {
|
|
||||||
buf[bytes] = 0;
|
|
||||||
uptime_now = (uint64_t)find_value(buf, "Raw_Ticks");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uptime_prev > 0) {
|
|
||||||
uint64_t total_delta = uptime_now - uptime_prev;
|
|
||||||
if (total_delta > 0) {
|
if (total_delta > 0) {
|
||||||
uint64_t used_delta = user_ticks_now - kernel_ticks_prev;
|
uint64_t used_delta = user_ticks_now - user_ticks_prev;
|
||||||
int cores = cpu_cores > 0 ? cpu_cores : 1;
|
int usage = (int)((used_delta * 100) / total_delta);
|
||||||
int usage = (int)((used_delta * 100) / (total_delta * cores));
|
|
||||||
if (usage > 100) usage = 100;
|
if (usage > 100) usage = 100;
|
||||||
|
if (usage < 0) usage = 0;
|
||||||
cpu_history[history_idx] = usage;
|
cpu_history[history_idx] = usage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uptime_prev = uptime_now;
|
user_ticks_prev = user_ticks_now;
|
||||||
kernel_ticks_prev = user_ticks_now;
|
total_ticks_prev = total_ticks_now;
|
||||||
|
|
||||||
int fd_m = sys_open("/proc/meminfo", "r");
|
int fd_m = sys_open("/proc/meminfo", "r");
|
||||||
if (fd_m >= 0) {
|
if (fd_m >= 0) {
|
||||||
|
|||||||
@@ -885,7 +885,8 @@ int main(void) {
|
|||||||
draw_tabs();
|
draw_tabs();
|
||||||
draw_session(&g_tabs[g_active_tab]);
|
draw_session(&g_tabs[g_active_tab]);
|
||||||
} else {
|
} else {
|
||||||
sys_yield();
|
// Avoid a tight poll loop when idle; sleep yields to the scheduler.
|
||||||
|
sleep(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
19
src/userland/libc/input.h
Normal file
19
src/userland/libc/input.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef INPUT_H
|
||||||
|
#define INPUT_H
|
||||||
|
|
||||||
|
// Arrow keys
|
||||||
|
#define KEY_UP 17
|
||||||
|
#define KEY_DOWN 18
|
||||||
|
#define KEY_LEFT 19
|
||||||
|
#define KEY_RIGHT 20
|
||||||
|
|
||||||
|
// controls
|
||||||
|
#define KEY_ENTER 10
|
||||||
|
#define KEY_BACKSPACE 8
|
||||||
|
#define KEY_ESCAPE 27
|
||||||
|
#define KEY_SPACE 32
|
||||||
|
#define KEY_ALT 22
|
||||||
|
#define KEY_CTRL_L 21
|
||||||
|
#define KEY_TAB 9
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user