getting rid of shit to focus more on kernel, drivers, and real stuff

This commit is contained in:
2025-01-07 14:58:45 +01:00
parent 14a9bdad7d
commit 27569fd5d8
31 changed files with 6 additions and 2388 deletions

View File

@@ -9,19 +9,15 @@ AR = i386-elf-7.5.0-Linux-x86_64/bin/i386-elf-ar
SRC_DIR = src SRC_DIR = src
KERNEL_DIR = $(SRC_DIR)/kernel KERNEL_DIR = $(SRC_DIR)/kernel
LIBC_DIR = $(SRC_DIR)/libc LIBC_DIR = $(SRC_DIR)/libc
UTILS_DIR = $(SRC_DIR)/utils
DRIVERS_DIR = $(SRC_DIR)/drivers DRIVERS_DIR = $(SRC_DIR)/drivers
PROGRAMS_DIR = $(SRC_DIR)/programs
INCLUDE_DIR = include INCLUDE_DIR = include
FONTS_DIR = $(INCLUDE_DIR)/fonts FONTS_DIR = $(INCLUDE_DIR)/fonts
OBJ_DIR = build OBJ_DIR = build
C_SOURCES = $(wildcard $(KERNEL_DIR)/*.c) $(wildcard $(LIBC_DIR)/*.c) $(wildcard $(UTILS_DIR)/*.c) $(wildcard $(DRIVERS_DIR)/*.c) C_SOURCES = $(wildcard $(KERNEL_DIR)/*.c) $(wildcard $(LIBC_DIR)/*.c) $(wildcard $(DRIVERS_DIR)/*.c)
ASM_SOURCES = $(wildcard $(KERNEL_DIR)/*.s) $(wildcard $(LIBC_DIR)/*.s) $(wildcard $(UTILS_DIR)/*.s) $(wildcard $(DRIVERS_DIR)/*.s) ASM_SOURCES = $(wildcard $(KERNEL_DIR)/*.s) $(wildcard $(LIBC_DIR)/*.s) $(wildcard $(DRIVERS_DIR)/*.s)
PROGRAM_SOURCES = $(wildcard $(PROGRAMS_DIR)/*.c)
OBJECTS = $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(C_SOURCES:.c=.o) $(ASM_SOURCES:.s=.o)) OBJECTS = $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(C_SOURCES:.c=.o) $(ASM_SOURCES:.s=.o))
PROGRAM_OBJECTS = $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(PROGRAM_SOURCES:.c=.o))
TOOLCHAIN_SRC = https://newos.org/toolchains/i386-elf-7.5.0-Linux-x86_64.tar.xz TOOLCHAIN_SRC = https://newos.org/toolchains/i386-elf-7.5.0-Linux-x86_64.tar.xz
TOOLCHAIN_FILE = i386-elf-7.5.0-Linux-x86_64.tar.xz TOOLCHAIN_FILE = i386-elf-7.5.0-Linux-x86_64.tar.xz
@@ -29,22 +25,15 @@ TOOLCHAIN_FILE = i386-elf-7.5.0-Linux-x86_64.tar.xz
FONT_OBJ = $(OBJ_DIR)/fonts/viscii10-8x16.o FONT_OBJ = $(OBJ_DIR)/fonts/viscii10-8x16.o
FONT_SRC = $(FONTS_DIR)/viscii10-8x16.psfu FONT_SRC = $(FONTS_DIR)/viscii10-8x16.psfu
all: $(OBJ_DIR) kernel.elf programs all: $(OBJ_DIR) kernel.elf
$(OBJ_DIR): $(OBJ_DIR):
mkdir -p $(OBJ_DIR) mkdir -p $(OBJ_DIR)
mkdir -p $(OBJ_DIR)/kernel $(OBJ_DIR)/libc $(OBJ_DIR)/utils $(OBJ_DIR)/drivers $(OBJ_DIR)/fonts $(OBJ_DIR)/programs mkdir -p $(OBJ_DIR)/kernel $(OBJ_DIR)/libc $(OBJ_DIR)/drivers $(OBJ_DIR)/fonts $(OBJ_DIR)/programs
kernel.elf: $(OBJECTS) $(FONT_OBJ) kernel.elf: $(OBJECTS) $(FONT_OBJ)
$(LD) $(LDFLAGS) $(OBJECTS) $(FONT_OBJ) -o kernel.elf $(LD) $(LDFLAGS) $(OBJECTS) $(FONT_OBJ) -o kernel.elf
programs: $(PROGRAM_OBJECTS)
@mkdir -p $(SRC_DIR)/initrd
@for prog in $(PROGRAM_OBJECTS); do \
base=$$(basename $$prog .o); \
$(LD) -melf_i386 -T program.ld $$prog -o $(SRC_DIR)/initrd/$$base.bin; \
done
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CFLAGS) $< -o $@ $(CC) $(CFLAGS) $< -o $@

View File

@@ -1,10 +0,0 @@
OUTPUT_FORMAT(binary)
ENTRY(main)
SECTIONS
{
. = 0x1000;
.text : { *(.text*) }
.data : { *(.data*) }
.bss : { *(.bss*) }
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -1 +0,0 @@
-[------->+<]>-.-[->+++++<]>++.+++++++..+++.[--->+<]>-----.---[->+++<]>.-[--->+<]>---.+++.------.--------.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

View File

@@ -1,8 +0,0 @@
Subfolder support!
I am making a bit of scurity improvements but clearly it has no meaing here.
The real meanng is the tellin of the Genesis; a true work of art. So many
cool stuff here!! Look, there are functions, comands, bits and bytes, conditions,
and lgorithms. What a fantastic world! But after all it stays formless and empty.
1:5:1 1:1:1 7:8:1 1:7:3 1:4:3 2:1:2

View File

@@ -1,37 +0,0 @@
***********************
* Welcome to BlankOS! *
***********************
Congratulations, you've entered my small world!
You can try all the commands, try tweaking stuff like explained
in the DEVELOPERS.md file, and even contribute if you got the
guts. lol.
Don't look too much at the code, it's badly designed, but hey,
that's my first OS project so I find it kinda cool.
There's no paging, ring 3, processes... I am not smart enough
for all this modern stuff. Let's keep it simple and stay in
ring0, without processes, maybe one day there'll be more
advanced features, but not today.
** Why am I doing this?
I wanted to explore the world of low-level programing.
As I had only 1 year of experience in C, it was super challenging
especially at the beginning, and I needed much time to understand
even the most basic things around OSDev.
I'll backup the project on archival media once it'll be at a good
enough point; I think it's cool to leave a trace of my passage on
Earth.
** Easter eggs
To make the exploration a bit funnier, I hid some easter eggs
around. You can try to find them if you have time to lose.
** Ravtzn
Jub xabjf? Znlor fbzrguvat'f uvqqra va gurer...

View File

@@ -15,7 +15,6 @@
#include "multiboot2.h" #include "multiboot2.h"
#include "kheap.h" #include "kheap.h"
#include "initrd.h" #include "initrd.h"
#include "../utils/utils.h"
#include "../libc/crypto.h" #include "../libc/crypto.h"
void kmain(multiboot2_info *mb_info) void kmain(multiboot2_info *mb_info)
@@ -126,6 +125,6 @@ void kmain(multiboot2_info *mb_info)
timer_install(); timer_install();
keyboard_install(); keyboard_install();
printf("[kernel] spawning shell...\n"); printf("Nothing to do, halting...");
shell_install(); asm("hlt");
} }

View File

@@ -1,178 +0,0 @@
// Basic shell and commands kernel module
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#include "system.h"
#include "../libc/stdio.h"
#include "../libc/string.h"
#include "../utils/utils.h"
#include "../libc/crypto.h"
#include <stdint.h>
#include "../drivers/rtc.h"
#include "kmain.h"
#define BUFFER_SIZE 256
#define MAX_COMMANDS 64
#define MAX_ARGS 64
// Splash screen: esthetic stuff.
char* motd[] =
{
"I should be root, really.",
"Not watching you!",
"Now in 2D!",
"Supercalifragilisticexpialidocious!",
"Tylko jedno w glowie mam!",
"Greetings, magic poppy!",
"I'm stuck in this kernel's shell, get me out!",
"And now, solve that equation!",
"Powered by TCC Incorporated.",
"Compiled at 69, CoquaineBaule Ave.",
"Shouldn't we be, uh, doing something?",
"We are the florists, we pick the plants!",
"Lalalalala, I pick the plants!",
"Woah, we're half-way there...",
"The CROU will never die!",
"Technoblade never dies!",
"Hi. My name is Guitar.",
"space station No. 9",
"May the orange juice be with you !",
"Bloody grated carrots!",
"Good night, kiddos...",
"I like trains",
"I fear planes",
"Bruteforce.exe",
"Ohayogozaimasu!",
};
int motd_size = sizeof(motd)/sizeof(motd[0]);
bool do_splash = true;
void splash()
{
int random = randint(time_seed());
char* motd_pick = motd[random%motd_size];
cowsay(motd_pick, red, black);
puts(" ");
colorputs("blankOS", black, white);
puts(" ");
colorputs(BLANK_VERSION, red, black);
puts("\n");
puts(" Time: ");
rtc_time_t time;
rtc_read_time(&time);
print_time(&time);
puts("\n");
}
typedef void (*command_func_t)(int argc, char *argv[]);
typedef struct
{
const char* name;
command_func_t function;
} shell_command_t;
shell_command_t shell_commands[MAX_COMMANDS];
int command_count = 0;
void register_command(const char* name, command_func_t function)
{
if (command_count < MAX_COMMANDS)
{
shell_commands[command_count].name = name;
shell_commands[command_count].function = function;
command_count++;
}
}
command_func_t find_command(const char* name)
{
for (int i=0; i < command_count; i++)
{
if (strcmp(name, shell_commands[i].name) == 0)
return shell_commands[i].function;
}
return 0;
}
int parse_input(char* input, char* argv[], int max_args)
{
int argc = 0;
char* token = strtok(input, " ");
while (token != NULL && argc < max_args - 1)
{
argv[argc++] = token;
token = strtok(NULL, " ");
}
argv[argc] = NULL;
return argc;
}
void shell_install()
{
if (do_splash == true)
{
do_splash = false;
splash();
}
register_command("help", program_help);
register_command("panic", program_panic);
register_command("words", program_words);
register_command("primes", program_primes);
register_command("rainbow", program_rainbow);
register_command("clear", program_clear);
register_command("math", program_math);
register_command("bf", program_bf);
register_command("uptime", program_uptime);
register_command("echo", program_echo);
register_command("sysinfo", program_sysinfo);
register_command("conway", program_conway);
register_command("rot13", program_rot13);
register_command("morse", program_morse);
register_command("cowsay", program_cowsay);
register_command("time", program_time);
register_command("read", program_read);
register_command("reboot", program_reboot);
register_command("pi", program_pi);
register_command("ls", program_ls);
register_command("cat", program_cat);
register_command("bmp", program_bmp);
register_command("lspci", program_lspci);
register_command("naval", program_navalbattle);
register_command("snake", program_snake);
register_command("exec", program_exec);
register_command("uhex", program_uhex);
for (;;)
{
char input_buffer[BUFFER_SIZE];
char* argv[MAX_ARGS];
// Prompt
colorputs("root", blue, black);
colorputs("@", white, black);
colorputs("blankos", green, black);
colorputs("~$ ", white, black);
get_input(input_buffer, BUFFER_SIZE);
puts("\n");
int argc = parse_input(input_buffer, argv, MAX_ARGS);
if (argc == 0) continue;
command_func_t command = find_command(argv[0]);
if (command)
{
command(argc, argv);
} else {
printf("Unknown command %s\n", argv[0]);
}
}
}

View File

@@ -1,10 +0,0 @@
void user_syscall(int syscall_no) {
asm volatile ("mov %0, %%eax" : : "r"(syscall_no));
asm volatile ("int $0x80");
}
void main()
{
user_syscall(1);
return;
}

View File

@@ -1,74 +0,0 @@
// Simple brainfuck interpreter program
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#include "../kernel/system.h"
#include "../libc/stdio.h"
#include "../kernel/kmain.h"
#include "../kernel/initrd.h"
#define BUF_SIZE 256
void brainfuck(char* input)
{
unsigned char tape[30000] = {0};
unsigned char* ptr = tape;
char current_char;
size_t i;
size_t loop;
for (i=0; input[i] != 0; i++)
{
current_char = input[i];
if (current_char == '>') {
++ptr;
} else if (current_char == '<') {
--ptr;
} else if (current_char == '+') {
++*ptr;
} else if (current_char == '-') {
--*ptr;
} else if (current_char == '.') {
putc(*ptr);
} else if (current_char == ',') {
*ptr = keyboard_getchar();
} else if (current_char == '[') {
continue;
} else if (current_char == ']' && *ptr) {
loop = 1;
while (loop > 0)
{
current_char = input[--i];
if (current_char == '[') {
loop--;
} else if (current_char == ']') {
loop++;
}
}
}
}
}
void program_bf(int argc, char* argv[])
{
if (argc == 1)
{
char input_buffer[BUF_SIZE];
puts("Brainfuck code? ");
get_input(input_buffer, BUF_SIZE);
brainfuck(input_buffer);
puts("\n");
} else if (argc == 2) {
// Read file content into buffer, then interpret it
char input_buffer[BUF_SIZE];
int read = tar_file_to_buffer((uint8_t*)initrd_addr, argv[1], input_buffer);
if (read == 0)
{
brainfuck(input_buffer);
puts("\n");
} else {
printf("Could not find file '%s'\n", argv[1]);
}
}
}

View File

@@ -1,99 +0,0 @@
// Bitmap image renderer
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#include "../kernel/kmain.h"
#include <stdint.h>
#include "../kernel/initrd.h"
#include "../drivers/framebuffer.h"
#include "../libc/stdio.h"
#include "../drivers/serial.h"
#include "../kernel/kheap.h"
#pragma pack(push, 1)
typedef struct
{
uint16_t bfType;
uint32_t bfSize;
uint16_t bfReserved1;
uint16_t bfReserved2;
uint32_t bfOffBits;
} BMPHeader;
typedef struct
{
uint32_t biSize;
int32_t biWidth;
int32_t biHeight;
uint16_t biPlanes;
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
int32_t biXPelsPerMeter;
int32_t biYPelsPerMeter;
uint32_t biClrUsed;
uint32_t biClrImportant;
} BMPInfoHeader;
#pragma pack(pop)
void display_bmp(uint32_t* fb, int pitch, int bpp, uint8_t* initrd, const char* filename)
{
uint32_t buf_size = tar_get_file_size(initrd, filename);
char* buffer = (char*)malloc(buf_size);
int file_status = tar_file_to_buffer(initrd, filename, buffer);
if (file_status != 0)
{
printf("Error loading file '%s'\n", filename);
return;
}
BMPHeader* bmp_header = (BMPHeader*)buffer;
BMPInfoHeader* bmp_info = (BMPInfoHeader*) (buffer+sizeof(BMPHeader));
if (bmp_header->bfType != 0x4D42)
{
printf("'%s' is not a valid BMP file\n", filename);
return;
}
int width = bmp_info->biWidth;
int height = bmp_info->biHeight;
int pixel_offset = bmp_header->bfOffBits;
printf("%d-bit BMP, width: %d, height: %d, pixel offset: %d\n", bmp_info->biBitCount, bmp_info->biWidth, bmp_info->biHeight, (int)bmp_header->bfOffBits);
erase_cursor();
uint8_t* pixel_data = (uint8_t*)(buffer + pixel_offset);
int cursor_y = (get_cursor_y()+1)*16;
serial_printf(3, "cursor_y=%d\n", cursor_y);
for (int y=cursor_y; y<height+cursor_y; y++)
{
for (int x=0; x<width; x++)
{
int index = (x+(height-y-1+cursor_y)*width)*3;
uint8_t blue = pixel_data[index];
uint8_t green = pixel_data[index+1];
uint8_t red = pixel_data[index+2];
uint32_t color = (0xFF << 24) | (red << 16) | (green << 8) | blue;
putpixel(fb, pitch, bpp, x, y, color);
}
}
// Update cursor pos after image drawing
move_cursor(get_cursor_x(), get_cursor_y()+(height/16)+2);
free(buffer);
}
void program_bmp(int argc, char* argv[])
{
if (argc < 2)
{
puts("Usage: bmp <file>\n");
return;
}
display_bmp(framebuffer, pitch, bpp, (uint8_t*)initrd_addr, argv[1]);
}

View File

@@ -1,160 +0,0 @@
// Cipher programs
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#include "../libc/stdio.h"
#include "ciphers.h"
#include "../libc/string.h"
#include <stdint.h>
void rot13(char* input, char* output)
{
int i = 0;
while (input[i] != '\0')
{
char c = input[i];
if (c >= 'a' && c <= 'z') {
output[i] = ((c - 'a' + 13) % 26) + 'a';
} else if (c >= 'A' && c <= 'Z') {
output[i] = ((c - 'A' + 13) % 26) + 'A';
} else {
output[i] = c;
}
i++;
}
output[i] = '\0';
}
void program_rot13(int argc, char* argv[])
{
if (argc < 2)
{
printf("Usage: %s <string>\n", argv[0]);
return;
}
char input_buffer[BUFFER_SIZE] = {0};
char output[BUFFER_SIZE] = {0};
for (int i=1; i<argc; i++)
{
strcat(input_buffer, argv[i]);
if (i<argc-1)
{
strcat(input_buffer, " ");
}
}
rot13(input_buffer, output);
printf("%s\n", output);
}
const char* morse_alphabet[] = {
".-", // A
"-...", // B
"-.-.", // C
"-..", // D
".", // E
"..-.", // F
"--.", // G
"....", // H
"..", // I
".---", // J
"-.-", // K
".-..", // L
"--", // M
"-.", // N
"---", // O
".--.", // P
"--.-", // Q
".-.", // R
"...", // S
"-", // T
"..-", // U
"...-", // V
".--", // W
"-..-", // X
"-.--", // Y
"--.." // Z
};
const char* morse_digits[] = {
"-----", // 0
".----", // 1
"..---", // 2
"...--", // 3
"....-", // 4
".....", // 5
"-....", // 6
"--...", // 7
"---..", // 8
"----." // 9
};
void to_morse(const char* input, char* output) {
int i = 0;
int pos = 0;
while (input[i] != '\0') {
char c = input[i];
if (c >= 'a' && c <= 'z') {
const char* morse_code = morse_alphabet[c - 'a'];
int j = 0;
while (morse_code[j] != '\0') {
output[pos++] = morse_code[j++];
}
} else if (c >= 'A' && c <= 'Z') {
const char* morse_code = morse_alphabet[c - 'A'];
int j = 0;
while (morse_code[j] != '\0') {
output[pos++] = morse_code[j++];
}
} else if (c >= '0' && c <= '9') {
const char* morse_code = morse_digits[c - '0'];
int j = 0;
while (morse_code[j] != '\0') {
output[pos++] = morse_code[j++];
}
} else if (c == ' ') {
output[pos++] = ' ';
}
output[pos++] = ' ';
i++;
}
if (pos > 0) {
output[pos - 1] = '\0';
} else {
output[pos] = '\0';
}
}
void program_morse(int argc, char* argv[]) {
if (argc < 2)
{
printf("Usage: %s <string>\n", argv[0]);
return;
}
char output[512];
char message[BUFFER_SIZE];
for (int i=1; i<argc; i++)
{
strcat(message, argv[i]);
if (i < argc-1)
{
strcat(message, " ");
}
}
to_morse(message, output);
printf("%s\n", output);
}

View File

@@ -1,11 +0,0 @@
// Cipher programs header
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#ifndef CIPHERS_H
#define CIPHERS_H
#define BUFFER_SIZE 256
#endif

View File

@@ -1,136 +0,0 @@
// Conway's Game of Life program
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#include "conway.h"
#include "../libc/stdio.h"
#include "../kernel/system.h"
#include "../libc/crypto.h"
#include <stdint.h>
#include "../drivers/serial.h"
#include "../libc/string.h"
void print_grid(const unsigned char grid[X][Y])
{
clear();
for (int i=0; i<X; i++)
{
for (int j=0; j<Y; j++)
{
if (grid[i][j] == LIVE) {
putc(35);
} else {
putc(32);
}
}
}
}
int count_live_neighbors(const unsigned char grid[X][Y], int i, int j)
{
int live_neighbors = 0;
for (int x=-1; x<=1; x++)
{
for (int y=-1; y<=1; y++)
{
if (x==0 && y==0) continue;
int ni = i+x;
int nj = j+y;
if (ni >= 0 && ni < X && nj >= 0)
{
if (grid[ni][nj] == LIVE) live_neighbors++;
}
}
}
return live_neighbors;
}
void grid_new_generation(unsigned char grid[X][Y], unsigned char temp[X][Y])
{
for (int i=0; i<X; i++)
{
for (int j=0; j<Y; j++)
{
int cell = grid[i][j];
int live_neighbors = count_live_neighbors(grid, i, j);
if (cell == LIVE)
{
switch(live_neighbors)
{
case 2:
case 3:
temp[i][j] = LIVE;
break;
default:
temp[i][j] = DEAD;
break;
}
}
else if (cell == DEAD && live_neighbors == 3)
{
temp[i][j] = LIVE;
}
}
}
for (int i=0; i<X; i++)
{
for (int j=0; j<Y; j++)
{
grid[i][j] = temp[i][j];
temp[i][j] = DEAD;
}
}
}
void soup(unsigned char grid[X][Y])
{
srand(global_ticks);
for (int i=0; i<X; i++)
{
for (int j=0; j<Y; j++)
{
grid[i][j] = rand_float() > SOUP_PROB ? LIVE : DEAD;
}
}
}
void program_conway(int argc, char* argv[])
{
clear();
unsigned char grid[X][Y] = {0};
unsigned char temp[X][Y] = {0};
if (argc == 1)
{
soup(grid);
} else if (argc == 2 && strcmp(argv[1], "-g") == 0) {
grid[1][2] = LIVE;
grid[2][3] = LIVE;
grid[3][1] = LIVE;
grid[3][2] = LIVE;
grid[3][3] = LIVE;
} else if (argc == 2 && strcmp(argv[1], "-l") == 0) {
grid[10][3] = LIVE; grid[10][4] = LIVE; grid[10][5] = LIVE; grid[10][6] = LIVE;
grid[11][2] = LIVE; grid[11][6] = LIVE;
grid[12][6] = LIVE;
grid[13][2] = LIVE; grid[13][5] = LIVE;
}
print_grid(grid);
puts("generation 0");
for (int i=1; i<GENERATIONS; i++)
{
grid_new_generation(grid, temp);
delay(DELAY);
clear();
print_grid(grid);
printf("generation %d", i);
}
}

View File

@@ -1,23 +0,0 @@
// Conway's Game of Life program header
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#ifndef CONWAY_H
#define CONWAY_H
#define X 66
#define Y 240
#define GENERATIONS 100
#define DEAD 0
#define LIVE 1
#define SOUP_PROB 0.7
#define DELAY 10
void print_grid(const unsigned char grid[X][Y]);
int count_live_neighbors(const unsigned char grid[X][Y], int i, int j);
void grid_new_generation(unsigned char grid[X][Y], unsigned char temp[X][Y]);
void soup(unsigned char grid[X][Y]);
#endif

View File

@@ -1,72 +0,0 @@
// Cowsay-like program
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#include "../libc/stdio.h"
#include "../libc/string.h"
#define MAX_MSG_LEN 128
const char* cow =
" \\ ^__^\n"
" \\ (oo)\\_______\n"
" (__)\\ )\\/\\\n"
" ||----w |\n"
" || ||\n";
void print_bubble(const char* message)
{
int len = strlen(message);
puts(" ");
for (int i=0; i<len+2; i++)
{
puts("_");
}
puts("\n");
printf("< %s >\n", message);
puts(" ");
for (int i=0; i<len+2; i++)
{
puts("-");
}
puts("\n");
}
void cowsay(char* msg, uint32_t fg, uint32_t bg)
{
print_bubble(msg);
colorputs(cow, fg, bg);
}
void program_cowsay(int argc, char* argv[])
{
if (argc < 2)
{
printf("Usage: %s <message>\n", argv[0]);
return;
}
char message[MAX_MSG_LEN];
message[0] = '\0';
for (int i=1; i<argc; i++)
{
if (strlen(message) + strlen(argv[i]) + 1 < MAX_MSG_LEN)
{
strcat(message, argv[i]);
if (i < argc-1)
{
strcat(message, " ");
}
} else {
puts("Too long message.\n");
return;
}
}
print_bubble(message);
printf("%s", cow);
}

View File

@@ -1,30 +0,0 @@
// Filesystem utilities (for initrd)
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#include "../kernel/initrd.h"
#include "../kernel/kmain.h"
#include "../libc/stdio.h"
#include "../libc/string.h"
void program_ls(int argc, char* argv[])
{
if (argc == 1)
{
ls_initrd((uint8_t*)initrd_addr, 0);
} else if (argc == 2 && strcmp(argv[1], "-l") == 0) {
ls_initrd((uint8_t*)initrd_addr, 1);
}
}
// Basic cat just to read, no concatenation here
void program_cat(int argc, char* argv[])
{
if (argc != 2)
{
puts("Usage: cat <file>\n");
return;
}
cat_initrd((uint8_t*)initrd_addr, argv[1]);
}

View File

@@ -1,245 +0,0 @@
// Basic math expression lexer and parser program
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#include <stdint.h>
#include "../kernel/system.h"
#include "../libc/stdio.h"
#include "../libc/ctype.h"
#define BUFFER_SIZE 256
typedef enum
{
TOKEN_NUMBER,
TOKEN_PLUS,
TOKEN_MINUS,
TOKEN_MULTIPLY,
TOKEN_DIVIDE,
TOKEN_LPAREN,
TOKEN_RPAREN,
TOKEN_END
} TokenType;
typedef struct
{
TokenType type;
double value;
} Token;
typedef struct
{
const char *text;
size_t pos;
Token current_token;
} Lexer;
void lexer_init(Lexer *lexer, const char *text)
{
lexer->text = text;
lexer->pos = 0;
lexer->current_token.type = TOKEN_END;
lexer->current_token.value = 0;
}
void lexer_advance(Lexer *lexer)
{
lexer->pos++;
}
char lexer_peek(const Lexer *lexer)
{
return lexer->text[lexer->pos];
}
bool lexer_is_at_end(const Lexer *lexer)
{
return lexer->text[lexer->pos] == '\0';
}
Token lexer_get_next_token(Lexer *lexer)
{
while (!lexer_is_at_end(lexer))
{
char current_char = lexer_peek(lexer);
if (isspace(current_char)) {
lexer_advance(lexer);
continue;
}
if (isdigit(current_char)) {
double value = 0;
while (isdigit(current_char))
{
value = value * 10 + (current_char - '0');
lexer_advance(lexer);
current_char = lexer_peek(lexer);
}
if (current_char == '.')
{
lexer_advance(lexer);
double decimal_place = 0.1;
while (isdigit(lexer_peek(lexer)))
{
value += decimal_place * (lexer_peek(lexer)-'0');
decimal_place *= 0.1;
lexer_advance(lexer);
}
}
lexer->current_token.type = TOKEN_NUMBER;
lexer->current_token.value = value;
return lexer->current_token;
}
if (current_char == '+')
{
lexer_advance(lexer);
lexer->current_token.type = TOKEN_PLUS;
return lexer->current_token;
}
if (current_char == '-')
{
lexer_advance(lexer);
lexer->current_token.type = TOKEN_MINUS;
return lexer->current_token;
}
if (current_char == '*')
{
lexer_advance(lexer);
lexer->current_token.type = TOKEN_MULTIPLY;
return lexer->current_token;
}
if (current_char == '/')
{
lexer_advance(lexer);
lexer->current_token.type = TOKEN_DIVIDE;
return lexer->current_token;
}
if (current_char == '(')
{
lexer_advance(lexer);
lexer->current_token.type = TOKEN_LPAREN;
return lexer->current_token;
}
if (current_char == ')')
{
lexer_advance(lexer);
lexer->current_token.type = TOKEN_RPAREN;
return lexer->current_token;
}
printf("\nUnknown character %c\n", current_char);
shell_install();
}
lexer->current_token.type = TOKEN_END;
return lexer->current_token;
}
typedef struct
{
Lexer lexer;
Token current_token;
} Parser;
void parser_init(Parser *parser, const char *text)
{
lexer_init(&parser->lexer, text);
parser->current_token = lexer_get_next_token(&parser->lexer);
}
void parser_eat(Parser *parser, TokenType type)
{
if (parser->current_token.type == type)
{
parser->current_token = lexer_get_next_token(&parser->lexer);
} else {
printf("\nUnexpected token %d\n", parser->current_token.type);
shell_install();
}
}
double parser_factor(Parser *parser);
double parser_term(Parser *parser);
double parser_expression(Parser *parser);
double parser_factor(Parser *parser)
{
Token token = parser->current_token;
if (token.type == TOKEN_NUMBER)
{
parser_eat(parser, TOKEN_NUMBER);
return token.value;
} else if (token.type == TOKEN_LPAREN) {
parser_eat(parser, TOKEN_LPAREN);
double result = parser_expression(parser);
parser_eat(parser, TOKEN_RPAREN);
return result;
} else {
printf("\nUnexpected token in factor %d\n", token.type);
shell_install();
}
return -1;
}
double parser_term(Parser *parser)
{
double result = parser_factor(parser);
while (parser->current_token.type == TOKEN_MULTIPLY || parser->current_token.type == TOKEN_DIVIDE)
{
Token token = parser->current_token;
if (token.type == TOKEN_MULTIPLY)
{
parser_eat(parser, TOKEN_MULTIPLY);
result *= parser_factor(parser);
} else if (token.type == TOKEN_DIVIDE) {
parser_eat(parser, TOKEN_DIVIDE);
result /= parser_factor(parser);
}
}
return result;
}
double parser_expression(Parser *parser)
{
double result = parser_term(parser);
while (parser->current_token.type == TOKEN_PLUS || parser->current_token.type == TOKEN_MINUS)
{
Token token = parser->current_token;
if (token.type == TOKEN_PLUS)
{
parser_eat(parser, TOKEN_PLUS);
result += parser_term(parser);
} else if (token.type == TOKEN_MINUS) {
parser_eat(parser, TOKEN_MINUS);
result -= parser_term(parser);
}
}
return result;
}
double parse(const char* text)
{
Parser parser;
parser_init(&parser, text);
double result = parser_expression(&parser);
return result;
}
void program_math()
{
char input_buffer[BUFFER_SIZE];
puts("Expression? ");
get_input(input_buffer, BUFFER_SIZE);
double result = parse(input_buffer);
printf("\n%f\n", result);
}

View File

@@ -1,176 +0,0 @@
// Miscellaneous small programs
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#include "../libc/stdio.h"
#include "../kernel/system.h"
#include "../libc/string.h"
#include "../drivers/framebuffer.h"
#include "../drivers/ata.h"
#include "../drivers/rtc.h"
#include "../kernel/io.h"
#include "../drivers/pci.h"
#include "../kernel/initrd.h"
#include "../kernel/kmain.h"
// Print a rainbow colorful text for testing
#define BUF_SIZE 256
#define COLORS 20
void program_rainbow(int argc, char* argv[])
{
if (argc < 2)
{
printf("Usage: %s <string>\n", argv[0]);
return;
}
char input_buffer[BUF_SIZE] = {0};
for (int i=1; i<argc; i++)
{
strcat(input_buffer, argv[i]);
if (i<argc-1)
{
strcat(input_buffer, " ");
}
}
enum Colors colors[] = {
white, black, red, green, blue, yellow,
cyan, magenta, orange, purple, brown,
gray, pink, lime, navy, teal, maroon,
olive, silver, gold, indigo, violet,
coral, turquoise, salmon, chocolate,
khaki, lavender, beige
};
int colors_count = sizeof(colors)/sizeof(colors[0]);
for (int i=0; i<colors_count-1; i++)
{
colorputs(input_buffer, colors[i], colors[i+1]);
puts("\n");
}
}
// Clear the terminal
#define ROWS 25
void program_clear()
{
clear();
}
// Get uptime in ticks
void program_uptime()
{
int ticks = uptime();
double seconds = ticks/18.2065; // PIT channel 0 freq
printf("%d ticks\t%f seconds\n", ticks, seconds);
}
// Get help
void program_help()
{
printf("help\tpanic\twords\tprimes\trainbow\tclear\nmath\tbf\t uptime echo\t sysinfo\tconway\nrot13 morse\tcowsay time\t read\t reboot\npi\t ls\t cat\t bmp\t lspci\t naval\nsnake exec\t uhex\n");
}
// Panic
void program_panic()
{
asm volatile("int $0x13");
}
// Output input
void program_echo(int argc, char* argv[])
{
for (int i=1; i<argc; i++)
{
puts(argv[i]);
if (i < argc-1) {
putc(' ');
}
}
puts("\n");
}
// Get current RTC time
void program_time()
{
rtc_time_t time;
rtc_read_time(&time);
puts("Current RTC time: ");
print_time(&time);
puts("\n");
}
// Read a sector
void program_read(int argc, char* argv[])
{
if (argc < 2)
{
printf("Usage: %s <sector>\n", argv[0]);
} else if (argc == 2)
{
uint8_t buffer[512];
ata_read_sector(atoi(argv[1]), buffer);
for (int i=0; i<512; i++)
{
if (i%50==0) puts("\n"); // hardcoded = bad
printf("%02x ", buffer[i]);
}
puts("\n");
} else
{
puts("Invalid argument number\n");
}
}
// Reboots the machine (might just shutdown) (or do nothing if youre lucky)
void program_reboot()
{
puts("Rebooting...\n");
while(inb(0x64) & 0x02);
outb(0x64, 0xFE);
while (1) asm volatile("hlt");
}
// List PCI buses and devices
void program_lspci()
{
scan_pci_bus();
}
// Executes binary file
void program_exec(int argc, char* argv[])
{
if (argc < 2)
{
puts("Usage: exec <binary>\n");
return;
}
void* binary_file = load_file_from_initrd((uint8_t*)initrd_addr, argv[1]);
if (binary_file == NULL)
{
printf("[exec] Failed to load program '%s'.\n", argv[1]);
return;
}
void (*program_entry)() = (void (*)())binary_file;
program_entry();
}

View File

@@ -1,348 +0,0 @@
// Simplified naval battle game
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#include "navalbattle.h"
#include "../libc/stdio.h"
#include "../kernel/system.h"
#include "../kernel/kheap.h"
#include "../libc/string.h"
#include "../libc/crypto.h"
#include "../drivers/serial.h"
// Porting problems:
// - Color printf? (Need to implement ANSI escape sequences).
// - Scanf?
// - Malloc? (proof of concept)
void program_navalbattle()
{
clear();
grid_t* grid[SIZE][SIZE];
grid_t* enemyGrid[SIZE][SIZE];
init_battlefield(grid);
init_battlefield(enemyGrid);
placing_ally_ships(grid);
puts("Now, time for the enemies to prepare...\n");
placing_enemy_ships(enemyGrid);
delay((rand()%MAX_WAIT_TIME)+10);
puts("Here we go!\n");
show_game_stats(grid, enemyGrid);
do
{
ally_do_attack(enemyGrid);
enemy_do_attack(grid);
show_game_stats(grid, enemyGrid);
} while (check_victory(grid, enemyGrid) == 0);
free_grid(grid);
free_grid(enemyGrid);
return;
}
void init_battlefield(grid_t* grid[SIZE][SIZE])
{
for (size_t i=0; i<SIZE; i++)
{
for (size_t j=0; j<SIZE; j++)
{
grid[i][j] = (grid_t*)malloc(sizeof(grid_t));
grid[i][j]->x = i;
grid[i][j]->y = j;
grid[i][j]->role = 0;
grid[i][j]->state = -2;
}
}
}
// To avoid memory leaks..
void free_grid(grid_t* grid[SIZE][SIZE])
{
for (size_t i=0; i<SIZE; i++)
{
for (size_t j=0; j<SIZE; j++)
{
free(grid[i][j]);
}
}
}
void show_ally_battlefield(grid_t* grid[SIZE][SIZE])
{
puts("\n*** Ally grid ***\n");
puts(" 0 1 2 3 4 5\n");
for (size_t i=0; i<SIZE; i++)
{
printf("%d ", i);
for (size_t j=0; j<SIZE; j++)
{
char roleChar = 0;
switch(grid[i][j]->state)
{
case -2:
roleChar = 32; // space
break;
case -1:
roleChar = 120;
break;
case 0:
roleChar = 79;
break;
case 1:
roleChar = 88;
break;
default:
printf("Error: bad value in grid at x=%d y=%d\n", grid[i][j]->x, grid[i][j]->y);
shell_install();
break;
}
if (j == SIZE-1)
{
printf("%c]", roleChar);
} else if (j == 0) {
printf("[%c|", roleChar);
} else {
printf("%c|", roleChar);
}
}
puts("\n");
}
}
void placing_ally_ships(grid_t* grid[SIZE][SIZE])
{
puts("==== Allied preparation phase =====\nPlease enter the positions for your ships, sir.\n");
for (size_t i=0; i<BOATS; i++)
{
int posX = 0, posY = 0;
do
{
printf("Ship %d\n------\n", (int)i);
puts("X coord: ");
char input_buffer[BUFFER_SIZE];
get_input(input_buffer, BUFFER_SIZE);
posY = atoi(input_buffer);
puts("\nY coord: ");
char input_buffer2[BUFFER_SIZE];
get_input(input_buffer2, BUFFER_SIZE);
posX = atoi(input_buffer2);
puts("\n");
if (posX < 0 || posX >= SIZE || posY < 0 || posY >= SIZE)
{
printf("Invalid position x=%d y=%d, please retry.\n", posX, posY);
}
if (grid[posX][posY]->role == 1)
{
printf("A ship is already in x=%d y=%d, please retry.\n", posX, posY);
}
} while (posX < 0 || posX >= SIZE || posY < 0 || posY >= SIZE || grid[posX][posY]->role == 1);
grid[posX][posY]->role = 1;
grid[posX][posY]->state = 0;
}
}
void placing_enemy_ships(grid_t* grid[SIZE][SIZE])
{
for (size_t i=0; i<BOATS; i++)
{
int posX = 0, posY = 0;
do
{
posX = rand() % SIZE;
posY = rand() % SIZE;
} while (grid[posX][posY]->role != 0);
grid[posX][posY]->role = 1;
grid[posX][posY]->state = 0;
}
}
void show_enemy_battlefield(grid_t* grid[SIZE][SIZE])
{
puts("\n*** Enemy grid ***\n");
puts(" 0 1 2 3 4 5\n");
for (size_t i=0; i<SIZE; i++)
{
printf("%d ", (int)i);
for (size_t j=0; j<SIZE; j++)
{
char roleChar = 0;
switch(grid[i][j]->state)
{
case -2:
case 0:
roleChar = 32;
break;
case -1:
roleChar = 120;
break;
case 1:
roleChar = 88;
break;
default:
printf("Error: bad value in battlefield at x=%d y=%d\n", grid[i][j]->x, grid[i][j]->y);
shell_install();
break;
}
if (j == SIZE-1)
{
printf("%c]", roleChar);
} else if (j == 0) {
printf("[%c|", roleChar);
} else {
printf("%c|", roleChar);
}
}
puts("\n");
}
puts("\n");
}
void show_remaining_boats(grid_t* allyGrid[SIZE][SIZE], grid_t* enemyGrid[SIZE][SIZE])
{
int allyShips = 0;
int enemyShips = 0;
for (size_t i=0; i<SIZE; i++)
{
for (size_t j=0; j<SIZE; j++)
{
if (allyGrid[i][j]->state == 0)
{
allyShips++;
}
if (enemyGrid[i][j]->state == 0)
{
enemyShips++;
}
}
}
printf("%d ally ships and %d enemy ships remaining.\n", allyShips, enemyShips);
allyShips >= enemyShips ? colorputs("The allies are in a good posture.\n", yellow, black) : colorputs("The allies are losing terrain...\n", salmon, black);
}
void show_game_stats(grid_t* allyGrid[SIZE][SIZE], grid_t* enemyGrid[SIZE][SIZE])
{
clear();
colorputs("\n\n\nShowing known information:\n\n", cyan, black);
show_ally_battlefield(allyGrid);
show_enemy_battlefield(enemyGrid);
show_remaining_boats(allyGrid, enemyGrid);
}
void do_attack(grid_t* grid[SIZE][SIZE], int x, int y)
{
switch(grid[x][y]->state)
{
case -2: // Untouched ocean
colorputs("The torpedo explodes in water. Missed.\n", orange, black);
grid[x][y]->state = -1;
delay(30);
break;
case -1: // Already hit ocean
colorputs("We already striked here, sir... Too late.\n", orange, black);
break;
case 0: // Ship
colorputs("Hit! Well done!\n", green, black);
grid[x][y]->state = 1;
delay(30);
break;
case 1: // Already hit ship
colorputs("Sir, we already sunk that ship... (looser)\n", orange, black);
break;
}
}
void ally_do_attack(grid_t* enemyGrid[SIZE][SIZE])
{
int x = 0, y = 0;
colorputs("\n* Ally attack preparation *\n", blue, black);
do
{
// yes, x and y are inverted.
puts("X coord: ");
char input_buffer[BUFFER_SIZE];
get_input(input_buffer, BUFFER_SIZE);
y = atoi(input_buffer);
puts("\nY coord: ");
char input_buffer2[BUFFER_SIZE];
get_input(input_buffer2, BUFFER_SIZE);
x = atoi(input_buffer2);
puts("\n");
if (x < 0 || x >= SIZE || y < 0 || y >= SIZE)
{
puts("Sir, this zone is not in our operation area! Please retry.\n");
}
} while (x < 0 || x >= SIZE || y < 0 || y >= SIZE);
do_attack(enemyGrid, x, y);
}
void enemy_do_attack(grid_t* allyGrid[SIZE][SIZE])
{
int x = 0, y = 0;
colorputs("\n* Enemies are preparing for attack, everyone take shelter! *\n", blue, black);
do
{
x = rand() % SIZE;
y = rand() % SIZE;
} while (allyGrid[x][y]->state == -1 || allyGrid[x][y]->state == 1);
delay((rand()%MAX_WAIT_TIME)+10);
do_attack(allyGrid, x, y);
}
int check_victory(grid_t* allyGrid[SIZE][SIZE], grid_t* enemyGrid[SIZE][SIZE])
{
int allyShips = 0;
int enemyShips = 0;
for (size_t i=0; i<SIZE; i++)
{
for (size_t j=0; j<SIZE; j++)
{
if (allyGrid[i][j]->state == 0)
{
allyShips++;
}
if (enemyGrid[i][j]->state == 0)
{
enemyShips++;
}
}
}
if (allyShips > 0 && enemyShips == 0)
{
colorputs("The allies have won! Congratulations, chief!\n", green, black);
return 1;
} else if (enemyShips > 0 && allyShips == 0)
{
colorputs("The ennemies have won.. We must retreat.\n", red, black);
return 1;
}
return 0;
}

View File

@@ -1,37 +0,0 @@
// Simplified naval battle game header
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#ifndef NAVALBATTLE_H
#define NAVALBATTLE_H
#include "../drivers/framebuffer.h"
typedef struct
{
int x;
int y;
int role;
int state;
} grid_t;
#define SIZE 6
#define BOATS 5
#define MAX_WAIT_TIME 20
#define BUFFER_SIZE 16
void init_battlefield(grid_t* grid[SIZE][SIZE]);
void free_grid(grid_t* grid[SIZE][SIZE]);
void show_ally_battlefield(grid_t* grid[SIZE][SIZE]);
void placing_ally_ships(grid_t* grid[SIZE][SIZE]);
void placing_enemy_ships(grid_t* grid[SIZE][SIZE]);
void show_enemy_battlefield(grid_t* grid[SIZE][SIZE]);
void show_remaining_boats(grid_t* allyGrid[SIZE][SIZE], grid_t* enemyGrid[SIZE][SIZE]);
void show_game_stats(grid_t* allyGrid[SIZE][SIZE], grid_t* enemyGrid[SIZE][SIZE]);
void do_attack(grid_t* grid[SIZE][SIZE], int x, int y);
void ally_do_attack(grid_t* enemyGrid[SIZE][SIZE]);
void enemy_do_attack(grid_t* allyGrid[SIZE][SIZE]);
int check_victory(grid_t* allyGrid[SIZE][SIZE], grid_t* enemyGrid[SIZE][SIZE]);
#endif

View File

@@ -1,34 +0,0 @@
// Program for Pi computation using Leibniz series
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#include "../libc/stdio.h"
#include "../libc/string.h"
void program_pi(int argc, char* argv[])
{
if (argc < 2)
{
printf("Usage: %s <terms>\n", argv[0]);
return;
}
double pi = 0.0;
int terms = atoi(argv[1]);
for (int i=0; i<terms; i++)
{
double term = 1.0/(2*i+1);
if (i%2 == 0)
{
pi += term;
} else {
pi -= term;
}
}
pi *= 4;
printf("%f\n", pi);
}

View File

@@ -1,44 +0,0 @@
// Prime number computation program
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#include <stdint.h>
#include "../libc/stdio.h"
#include "../kernel/system.h"
#include "../libc/string.h"
#define PRIMES_MAX 1000000
bool isPrime(int n)
{
if (n == 1 || n == 0) return false;
for (int i=2; i<= n/2; i++) if (n%i == 0) return false;
return true;
}
void program_primes(int argc, char* argv[])
{
int primes_max;
if (argc == 1)
{
primes_max = PRIMES_MAX;
} else if (argc == 2)
{
primes_max = atoi(argv[1]);
}
for (long long x=0; x<primes_max; x++)
{
if (isPrime(x) && x != 3301)
{
printf("%d ", (int)x);
} else if(x == 3301)
{
colorputs("3301 ", red, black);
}
delay(1);
}
puts("\n");
}

View File

@@ -1,200 +0,0 @@
// Snake game
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#include "../kernel/system.h"
#include "../libc/stdio.h"
#include "../drivers/framebuffer.h"
#include "../drivers/kb.h"
#include "../libc/string.h"
#include "../libc/crypto.h"
#define WIDTH 25
#define HEIGHT 25
#define PIXEL_SIZE 20
#define MAX_SNAKE_LENGTH 256
// to add:
// sound
// optimization (shit)
typedef struct
{
int x;
int y;
} SnakeSegment;
typedef struct
{
SnakeSegment segments[MAX_SNAKE_LENGTH];
int length;
int dx;
int dy;
} Snake;
typedef struct
{
int x;
int y;
} Food;
Snake snake;
Food food;
int score = 0;
bool onSnake;
int is_snake(int x, int y);
void init_game()
{
snake.length = 1;
snake.segments[0].x = WIDTH/2;
snake.segments[0].y = HEIGHT/2;
snake.dx = 1;
snake.dy = 0;
food.x = rand() % (WIDTH-1);
food.y = rand() % (HEIGHT-1);
}
void draw_board()
{
for (int y=0; y<=HEIGHT; y++)
{
for (int x=0; x<=WIDTH; x++)
{
if (x == 0 || x == WIDTH || y == 0 || y == HEIGHT)
{
draw_square(x, y, white, PIXEL_SIZE);
}
else if (is_snake(x, y)) {
draw_square(x, y, green, PIXEL_SIZE);
} else if(x == food.x && y == food.y) {
draw_square(x, y, red, PIXEL_SIZE);
} else {
draw_square(x, y, black, PIXEL_SIZE);
}
}
}
move_cursor(WIDTH+42, 2);
colorputs("Snake Game!", black, green);
move_cursor(WIDTH+42, 4);
colorprintf(yellow, black, "Score: %d", score);
move_cursor(WIDTH+42, 5);
puts("Use WASD keys to move");
move_cursor(WIDTH+42, 6);
puts("Press Q to quit");
}
int is_snake(int x, int y)
{
for (int i=0; i<snake.length; i++)
{
if (snake.segments[i].x == x && snake.segments[i].y == y)
{
return 1;
}
}
return 0;
}
void move_snake()
{
for (int i=snake.length-1; i>0; i--)
{
snake.segments[i] = snake.segments[i-1];
}
snake.segments[0].x += snake.dx;
snake.segments[0].y += snake.dy;
if (snake.segments[0].x < 0) snake.segments[0].x = WIDTH-1;
if (snake.segments[0].x >= WIDTH) snake.segments[0].x = 0;
if (snake.segments[0].y < 0) snake.segments[0].y = HEIGHT-1;
if (snake.segments[0].y >= HEIGHT) snake.segments[0].y = 0;
if (snake.segments[0].x == food.x && snake.segments[0].y == food.y)
{
snake.length++;
score++;
do
{
onSnake = false;
food.x = rand() % (WIDTH-1) + 1;
food.y = rand() % (HEIGHT-1) + 1;
for (int i=0; i<snake.length; i++)
{
if (snake.segments[i].x == food.x && snake.segments[i].y == food.y)
{
onSnake = true;
break;
}
}
} while (onSnake);
}
for (int i=1; i<snake.length; i++)
{
if (snake.segments[0].x == snake.segments[i].x && snake.segments[0].y == snake.segments[i].y)
{
move_cursor(WIDTH+42, 8);
colorputs("Game Over!\n", white, red);
move_cursor(0, HEIGHT+10);
shell_install();
}
}
}
void handle_input(char key)
{
if (key == 'w' && snake.dy == 0) {
snake.dx = 0;
snake.dy = -1;
} else if (key == 's' && snake.dy == 0) {
snake.dx = 0;
snake.dy = 1;
} else if (key == 'a' && snake.dx == 0) {
snake.dx = -1;
snake.dy = 0;
} else if (key == 'd' && snake.dx == 0) {
snake.dx = 1;
snake.dy = 0;
} else if (key =='q') {
move_cursor(0, HEIGHT+10);
shell_install();
}
}
void program_snake(int argc, char* argv[])
{
int game_speed;
if (argc < 2)
{
game_speed = 4;
} else {
game_speed = atoi(argv[1]);
}
clear();
init_game();
for(;;)
{
char key = keyboard_getchar_non_blocking();
if (key)
{
handle_input(key);
}
move_snake();
draw_board();
delay(game_speed);
}
}

View File

@@ -1,85 +0,0 @@
// System information program
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#include "../kernel/sysinfo.h"
#include "../libc/stdio.h"
#include "../kernel/system.h"
#include "../libc/string.h"
extern unsigned int multiboot_info_address;
typedef struct multiboot_memory_map
{
unsigned int size;
unsigned int base_addr_low;
unsigned int base_addr_high;
unsigned int length_low;
unsigned int length_high;
unsigned int type;
} multiboot_memory_map_t;
void get_cpuid()
{
// CPUid
unsigned int eax, edx;
char vendor[13];
unsigned int* v = (unsigned int*)vendor;
asm volatile("cpuid"
: "=b"(v[0]), "=d"(v[1]), "=c"(v[2])
: "a"(0));
vendor[12] = '\0';
cpuid(1, &eax, &edx);
unsigned int model = (eax >> 4) & 0xF;
unsigned int family = (eax >> 8) & 0xF;
printf("CPU information\n\tvendor: %s\n\tfamily: %u\n\tmodel: %u\n\tfeatures: 0x%x\n", vendor, family, model, edx);
}
// Not really working anymore as it was made for multiboot1, now using multiboot2
void get_meminfo(unsigned int multiboot_info_address, int verbose)
{
// RAM
unsigned int mem_lower = *((unsigned int*)(multiboot_info_address + 4));
unsigned int mem_upper = *((unsigned int*)(multiboot_info_address + 8));
printf("RAM information\n\tLower memory: %u KB\n\tUpper memory: %u KB\n", mem_lower, mem_upper);
if (verbose)
{
multiboot_memory_map_t* mmap = (multiboot_memory_map_t*)*((unsigned int*)(multiboot_info_address + 44));
printf("Memory map:\nBase addr | Length | Type\n----------------------------------------------------\n");
while ((unsigned int)mmap < multiboot_info_address + *((unsigned int*)(multiboot_info_address + 40)))
{
/*
if (mmap->length_high != 0 && mmap->length_low != 0)
{*/
printf("0x%x%x | 0x%x%x | %u\n",
mmap->base_addr_high, mmap->base_addr_low,
mmap->length_high, mmap->length_low,
mmap->type);
//}
mmap = (multiboot_memory_map_t*)((unsigned int)mmap + mmap->size + sizeof(unsigned int));
}
}
}
void program_sysinfo(int argc, char* argv[])
{
if (argc == 1)
{
get_cpuid();
get_meminfo(g_multiboot_info_address, 0);
} else if (argc == 2 && strcmp(argv[1], "-v") == 0)
{
get_cpuid();
get_meminfo(g_multiboot_info_address, 1);
}
}

View File

@@ -1,82 +0,0 @@
// uhex (microhex) port for BlankOS; read-only version
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
// This version is the port of a hex viewer which already was not great,
// and now by being here it is even worse because it is RO and will have
// hardcoded stuff in it (no ioctl, STDOUT, or other stuff here...)
#define BYTES 1024
#define round(x) (int)(x < 0 ? (x -0.5) : x + 0.5)
#include "../libc/stdio.h"
#include "../kernel/kmain.h"
#include "../kernel/initrd.h"
#include "../libc/string.h"
#include "../kernel/kheap.h"
int isprint(int c)
{
return (c >= 32 && c <= 126);
}
void print_hex(unsigned char* buf, int byteno, int pos, int BYTES_PER_LINE)
{
for (int i=0; i<byteno; i++)
{
if (i%BYTES_PER_LINE == 0)
{
if (i != 0)
{
printf(" ");
for (int j=i-BYTES_PER_LINE; j<i; j++)
{
if (isprint(buf[j])) colorprintf(salmon, black, "%c", buf[j]);
else printf(".");
}
}
puts("\n");
if (pos == 0) printf("%06d: ", i);
else printf("%06d: ", pos);
}
printf("%2x ", buf[i]);
}
int padding = BYTES_PER_LINE - (byteno % BYTES_PER_LINE);
if (padding < BYTES_PER_LINE)
{
for (int i=0; i<padding; i++) printf(" ");
printf(" ");
}
int start = byteno-(byteno%BYTES_PER_LINE);
for (int j=start; j<byteno; j++)
{
if (isprint(buf[j])) {
colorprintf(salmon, black, "%c", buf[j]);
} else {
printf(".");
}
}
puts("\n");
}
void program_uhex(int argc, char* argv[])
{
if (argc < 2)
{
puts("Usage: uhex <file>\n");
return;
}
int BYTES_PER_LINE = 20;
//unsigned char buf[BYTES]; // malloc with file_size next?
uint32_t file_size = tar_get_file_size((uint8_t*)initrd_addr, argv[1]);
unsigned char* buf = (unsigned char*)malloc(file_size);
tar_file_to_buffer((uint8_t*)initrd_addr, argv[1], (char*)buf);
print_hex(buf, file_size, 0, BYTES_PER_LINE);
free(buf);
}

View File

@@ -1,53 +0,0 @@
// Global program entry points header
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#ifndef UTILS_H
#define UTILS_H
void program_words();
void program_primes();
void program_math();
void program_bf();
void program_sysinfo();
void get_cpuid();
void get_meminfo(unsigned int multiboot_info_address); // to be fixed: cannot get full memory map (sysinfo -v)
void program_cowsay();
void cowsay(); // Splash screen
void program_pi();
// Ciphers
void program_rot13();
void program_morse();
// Misc
void program_rainbow();
void program_clear();
void program_uptime();
void program_panic();
void program_help();
void program_echo();
void program_time();
void program_read();
void program_reboot();
// Filesystem (initrd)
void program_ls();
void program_cat();
void program_bmp();
void program_lspci();
// Games
void program_navalbattle();
void program_conway();
void program_snake();
// Binaries loading and execution
void program_exec();
void program_uhex();
#endif

View File

@@ -1,217 +0,0 @@
// Pseudo-random word generation program
// Author: xamidev
// Licensed under the Unlicense. See the repo below.
// https://github.com/xamidev/blankos
#include "../libc/stdio.h"
#include "../libc/crypto.h"
#include "../kernel/system.h"
#include "../libc/string.h"
// Small dictionary
char* words[] =
{
// A
"I", "us", "they", "my",
"a", "an", "is", "are", "for", "while", "not", "none", "yes", "no",
"absolutely", "addition", "additive", "afternoon", "architect", "ask",
"ability", "above", "absence", "academy", "account", "achieve", "acquire",
"adapt", "admit", "adventure", "affection", "agenda", "agreement", "airport",
"alert", "alibi", "alive", "allow", "almond", "alphabet", "always",
// B
"be", "blindfold", "brilliant", "boy", "bring", "buddy",
"balance", "bamboo", "band", "banjo", "bank", "banner", "barrel",
"basic", "battery", "beach", "beacon", "beard", "behavior", "believe",
"belt", "benefit", "berry", "bicycle", "bingo", "biology", "birthday",
"biscuit", "bitter", "blanket", "blizzard", "blossom", "blueprint", "board",
// C
"career", "caterpillar", "change", "cheeky", "chop",
"cabin", "cactus", "camera", "candle", "candy", "canoe", "canvas",
"capital", "captain", "caravan", "carbon", "carpet", "cartoon", "castle",
"casual", "catalog", "catch", "category", "celebrate", "ceremony", "certain",
"chain", "chair", "chamber", "charge", "charity", "cheese", "chef",
// D
"decide", "demonstrate", "draw", "druggist",
"daisy", "dance", "danger", "daring", "database", "debate", "decade",
"decline", "decorate", "decrease", "dedicate", "defeat", "defend", "define",
"degree", "delight", "delivery", "demand", "dentist", "deny", "depart",
"depth", "describe", "deserve", "desire", "destroy", "develop", "device",
// E
"eagle", "ear", "effort", "evening",
"early", "earn", "earth", "ease", "east", "easy", "echo",
"eclipse", "economy", "edge", "edit", "educate", "effect", "effort",
"egg", "eight", "either", "elder", "elect", "elegant", "element",
"elephant", "elevator", "elite", "embark", "embrace", "emerge", "emotion",
// F
"fabric", "famous", "fuse",
"face", "factor", "fail", "fair", "fall", "false", "fame",
"family", "fancy", "fantasy", "farewell", "farm", "fashion", "fast",
"fault", "favor", "feather", "feature", "federal", "feedback", "feeling",
"female", "fence", "festival", "fever", "fiber", "fiction", "field",
// G
"generation", "generous", "girl", "gypsy", "grip",
"gallery", "game", "garage", "garden", "garlic", "gas", "gate",
"gather", "general", "genius", "gentle", "genuine", "geography", "gesture",
"ghost", "giant", "gift", "giggle", "ginger", "giraffe", "glance",
"glass", "globe", "glory", "glove", "glue", "goal", "gold",
// H
"habit", "handsome", "helmet", "help", "horror",
"hair", "half", "hammer", "hand", "handle", "hang", "happen",
"harbor", "hard", "harm", "harvest", "hat", "hate", "have",
"head", "health", "heart", "heat", "heaven", "heavy", "hedge",
"height", "hello", "heritage", "hero", "hesitate", "hidden", "high",
// I
"insist", "inventor", "itself", "ivory",
"ice", "idea", "ideal", "identify", "ignore", "ill", "image",
"imagine", "impact", "import", "impress", "improve", "impulse", "inch",
"include", "income", "increase", "index", "industry", "infant", "inform",
"insect", "inside", "inspire", "install", "instead", "insult", "intact",
// J
"jog", "joint", "joke", "judge",
"jacket", "jaguar", "jail", "jam", "january", "jar", "jazz",
"jealous", "jeans", "jelly", "jewel", "job", "join", "journey",
"joy", "judge", "juice", "jump", "jungle", "junior", "justice",
"just", "justify", "juggle", "juice", "jumper", "junction", "jury",
// K
"karate", "kebab", "kitchen",
"kangaroo", "keen", "keep", "kettle", "key", "keyboard", "kick",
"kid", "kidney", "king", "kiss", "kite", "knee", "knife",
"knit", "knock", "knot", "know", "knowledge", "koala", "kudos",
"keen", "kernel", "kit", "kitten", "knack", "knight", "knock",
// L
"lamb", "lawnmower", "left", "lock",
"label", "labor", "lace", "ladder", "lady", "lake", "lamp",
"land", "language", "large", "laser", "last", "later", "laugh",
"launch", "law", "layer", "lead", "leaf", "learn", "least",
"leather", "leave", "lecture", "legal", "legend", "lemon", "length",
// M
"math", "medicine", "most",
"machine", "magnet", "mail", "main", "major", "make", "male",
"manage", "mango", "manner", "manual", "map", "marble", "march",
"mark", "market", "marriage", "master", "match", "material", "matter",
"maximum", "mayor", "meal", "mean", "measure", "media", "memory",
// N
"noodles", "nowadays", "nowhere",
"nail", "name", "narrow", "nation", "native", "nature", "navy",
"near", "neat", "necessary", "neck", "need", "negative", "neglect",
"neither", "nerve", "nest", "net", "network", "neutral", "never",
"new", "news", "next", "nice", "night", "noble", "noise",
// O
"ocean", "older", "ounce",
"object", "observe", "obtain", "occasion", "occupy", "occur", "ocean",
"offer", "office", "often", "oil", "old", "olive", "olympic",
"omit", "once", "one", "onion", "online", "only", "open",
"opera", "opinion", "oppose", "option", "orange", "orbit", "order",
// P
"part", "pathetic", "pastime",
"pace", "package", "page", "pain", "paint", "pair", "palm",
"panel", "panic", "paper", "parent", "park", "part", "party",
"pass", "path", "patient", "pattern", "pause", "peace", "peak",
"pen", "pencil", "people", "pepper", "perfect", "perform", "permit",
// Q
"quite", "quits", "quotation",
"quality", "quantity", "quarter", "queen", "query", "quest", "quick",
"quiet", "quilt", "quit", "quote", "quiz", "quota", "quiver",
"quirky", "quaint", "quake", "qualification", "qualify", "quark", "quartz",
"queue", "quench", "question", "quote", "quiver", "quorum", "quote",
// R
"race", "raise", "reality",
"rabbit", "race", "radio", "rain", "raise", "random", "range",
"rapid", "rare", "rate", "rather", "ratio", "reach", "react",
"read", "ready", "real", "reason", "rebel", "recall", "receive",
"recipe", "record", "recover", "reduce", "refer", "reflect", "reform",
// S
"safe", "scare", "screen",
"sack", "sail", "salad", "salt", "same", "sample", "sand",
"save", "scale", "scan", "scar", "scene", "school", "science",
"score", "scratch", "scream", "screen", "script", "search", "season",
"seat", "second", "secret", "section", "secure", "see", "seed",
// T
"taught", "temple", "that", "this",
"table", "tackle", "tail", "take", "tale", "talent", "talk",
"tank", "tape", "target", "task", "taste", "tax", "teach",
"team", "tear", "technology", "telephone", "television", "temperature", "tend",
"tennis", "tent", "term", "test", "text", "thank", "theory",
// U
"unable", "unkind", "usual",
"umbrella", "unable", "uncle", "under", "undo", "unfair", "unfold",
"union", "unique", "unit", "universe", "unknown", "unless", "unlike",
"unlock", "until", "unusual", "update", "upgrade", "upon", "upper",
"upset", "urban", "urge", "use", "usual", "utility", "utter",
// V
"velvet", "vivid", "vote",
"vacuum", "valid", "valley", "value", "vampire", "van", "vase",
"vast", "vault", "vector", "vehicle", "velvet", "vendor", "venture",
"verb", "verify", "version", "vessel", "veteran", "veto", "vibrate",
"victory", "video", "view", "village", "violin", "virtue", "virus",
// W
"we", "warm", "watch",
"wage", "wait", "walk", "wall", "wander", "want", "war",
"wash", "waste", "watch", "water", "wave", "way", "wealth",
"weapon", "wear", "weather", "weave", "wedding", "week", "weight",
"welcome", "well", "west", "wheel", "when", "whisper", "white",
// X
"xylophone",
"xenon", "xenophobia", "xerox", "xmas", "x-ray", "xylophone", "xylem",
// Y
"yolk", "young", "your",
"yard", "yarn", "year", "yell", "yellow", "yes", "yesterday",
"yet", "yield", "yogurt", "yoke", "youth", "yawn", "yearn",
"yacht", "yummy", "yogurt", "yoga", "yardstick", "yonder", "yummy",
// Z
"zebra", "zodiac", "zucchini",
"zero", "zone", "zoo", "zoom", "zeal", "zip", "zigzag",
"zenith", "zest", "zipper", "zombie", "zonal", "zinc", "zephyr"
};
int words_size = sizeof(words)/sizeof(words[0]);
// Generates random words
void program_words(int argc, char* argv[])
{
int amount;
if (argc == 1)
{
amount = 10;
} else if (argc == 2)
{
amount = atoi(argv[1]);
}
for (int i=0; i<amount; i++)
{
int random = randint(global_ticks);
char* word = words[random%words_size];
//printf("Global ticks: %d\nRandom integer: %d\nWord: %s\n", global_ticks, random, word);
printf("%s ", word);
delay(10);
}
puts("\n");
}