Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
abeb22eaab
|
|||
|
a8582ba343
|
|||
|
b3687d20ee
|
|||
|
27569fd5d8
|
|||
|
|
14a9bdad7d | ||
|
|
756dc638e8 | ||
|
|
903188a543 | ||
|
|
8a68cf3b30 | ||
|
|
1085222d98 | ||
|
|
68a4be55ce | ||
|
|
cee509f6a1 | ||
|
|
c104657d52 | ||
|
|
1fa4b5c70a | ||
|
|
7071b4788b | ||
|
|
5ad32d3ee1 | ||
|
|
d02b3d62cb | ||
|
|
af716cb2ec | ||
|
|
e6f119236b | ||
|
|
c885e69be4 | ||
|
|
03b712ace0 | ||
|
|
87bb1d96fd | ||
|
|
8bac95890a |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,3 +5,4 @@ blankos.iso
|
||||
iso/
|
||||
i386-elf-7.5.0-Linux-x86_64/
|
||||
i386-elf-7.5.0-Linux-x86_64.tar.xz
|
||||
src/initrd/*.bin
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||

|
||||
|
||||
> [!WARNING]
|
||||
> The project is currently paused, after months of work around the subject. I've had enough for now, and I'll surely come back in some time to implement the more advanced stuff I had planned. For now, enjoy the latest alpha version.
|
||||
> This is a hobbyist operating system, and it comes without any warranty whatsoever! See the license for more info. Feedback and contributions are highly appreciated.
|
||||
> This is free and unencumbered software released into the public domain. Many things might be (are) broken.
|
||||
> The project is a hobbyist operating system, and it comes without any warranty whatsoever! See the license for more info. Feedback and contributions are highly appreciated.
|
||||
|
||||
# BlankOS
|
||||
|
||||
|
||||
@@ -42,9 +42,11 @@ sudo qemu-system-i386 -drive if=pflash,format=raw,readonly=on,file=/usr/share/OV
|
||||
|
||||
Be warned, these are not actual programs in the sense you'd expect. These are indeed functions that are called from the shell, and embedded in the kernel ELF binary. Real programs apart from the kernel are not yet a thing here, but might be one day.
|
||||
|
||||
(Now, there is a 'beginning' of something that we could call real programs, but I still suck at making the syscalls work. One day, one day...)
|
||||
|
||||
### Step 1 - Making the program and the entry point
|
||||
|
||||
To make a program for the OS, first create the appropriate C source file and header file in the `src/programs` subfolder. Name it appropriately, for example `myprogram.c`.
|
||||
To make a program for the OS, first create the appropriate C source file and header file in the `src/utils` subfolder. Name it appropriately, for example `myprogram.c`.
|
||||
|
||||
In this file, you will put the functions your program will use. The entry point for the program should be a void function named `program_<PROGRAM_NAME>`. The entry point can either take no arguments, or use the classic argc/argv structure.
|
||||
|
||||
@@ -57,7 +59,7 @@ void program_myprogram(int argc, char* argv[])
|
||||
```
|
||||
|
||||
Then, code your stuff freely. The entry point function will basically be the "main" function of your program, like in a regular C file. You can make your own header file too, for example `myprogram.h`.
|
||||
Keep in mind that the standard C library is not available here, so you'll have to use functions from the BlankOS C library, which is located in `src/libc`. Also feel free to look at the header files in `src/drivers` and `src/kernel`, there might be interesting functions in there too (managing input/output devices, the timer, etc..)
|
||||
Keep in mind that the standard C library is not available here, so you'll have to use functions from the BlankOS C library, which is located in `src/libk`. Also feel free to look at the header files in `src/drivers` and `src/kernel`, there might be interesting functions in there too (managing input/output devices, the timer, etc..)
|
||||
|
||||
### Step 2 - Registering the program
|
||||
|
||||
@@ -65,7 +67,7 @@ Now that your program is done, you will need to make it a part of the OS.
|
||||
|
||||
#### General program header file registering
|
||||
|
||||
To make the entry point function reachable from the shell, you first have to include it in the general programs header file located in `src/programs/programs.h`.
|
||||
To make the entry point function reachable from the shell, you first have to include it in the general programs header file located in `src/utils/programs.h`.
|
||||
|
||||
Put the entry point function prototype in that file. A valid example might be:
|
||||
|
||||
@@ -87,7 +89,7 @@ Don't make your command name too long, preferably a few characters, like the oth
|
||||
|
||||
#### Help utility registering (optional)
|
||||
|
||||
Finally, you can add your command to the list of available commands by adding it to the `printf` call in the `src/programs/misc.c` source file, in the function `program_help()`.
|
||||
Finally, you can add your command to the list of available commands by adding it to the `printf` call in the `src/utils/misc.c` source file, in the function `program_help()`.
|
||||
|
||||
If possible make sure that the new command name is aligned with the other ones.
|
||||
|
||||
|
||||
@@ -143,3 +143,11 @@ Starts a simplified and buggy snake game. You can choose the speed by setting th
|
||||
Controls:
|
||||
- `q` to quit
|
||||
- `wasd` to move
|
||||
|
||||
#### `exec <binary>`
|
||||
|
||||
Executes a binary file. Warning: this is highly broken and syscalls aren't working. It's written in a childish manner. Help is always appreciated (lol).
|
||||
|
||||
#### `uhex <file>`
|
||||
|
||||
Prints the hex and ASCII contents of a file.
|
||||
|
||||
@@ -18,13 +18,13 @@ void putpixel(uint32_t* fb, int pitch, int bpp, int x, int y, uint32_t color)
|
||||
|
||||
void draw_char(unsigned short int c, int cx, int cy, uint32_t fg, uint32_t bg)
|
||||
{
|
||||
PSF_font *font = (PSF_font*)&_binary_include_fonts_UniCyr_8x16_psf_start;
|
||||
PSF_font *font = (PSF_font*)&FONT_START;
|
||||
int bytesperline=(font->width+7)/8;
|
||||
if (unicode != NULL) {
|
||||
c = unicode[c];
|
||||
}
|
||||
|
||||
unsigned char* glyph = (unsigned char*)&_binary_include_fonts_UniCyr_8x16_psf_start + font->headersize + (c>0&&c<font->numglyph?c:0)*font->bytesperglyph;
|
||||
unsigned char* glyph = (unsigned char*)&FONT_START + font->headersize + (c>0&&c<font->numglyph?c:0)*font->bytesperglyph;
|
||||
|
||||
int offs =
|
||||
(cy * font->height * scanline) +
|
||||
@@ -54,7 +54,7 @@ void scroll()
|
||||
{
|
||||
serial_printf(3, "Scrolling...\r");
|
||||
uint32_t bg_color = 0x00000000;
|
||||
PSF_font *font = (PSF_font*)&_binary_include_fonts_UniCyr_8x16_psf_start;
|
||||
PSF_font *font = (PSF_font*)&FONT_START;
|
||||
|
||||
int line_size = font->height * scanline;
|
||||
int framebuffer_size = scanline * font->height * (1080/font->height);
|
||||
@@ -9,11 +9,16 @@
|
||||
#include <stdint.h>
|
||||
|
||||
extern int scanline;
|
||||
extern char _binary_include_fonts_UniCyr_8x16_psf_start;
|
||||
uint16_t* unicode;
|
||||
|
||||
#define FONT_START _binary_include_fonts_viscii10_8x16_psfu_start
|
||||
#define FONT_END _binary_include_fonts_viscii10_8x16_psfu_start
|
||||
|
||||
extern char FONT_START;
|
||||
extern char FONT_END;
|
||||
uint16_t* unicode;
|
||||
#define PIXEL uint32_t
|
||||
|
||||
#define USHRT_MAX 10000
|
||||
#define PSF1_FONT_MAGIC 0x0436
|
||||
|
||||
typedef struct {
|
||||
@@ -38,5 +43,6 @@ typedef struct {
|
||||
void putpixel(uint32_t* fb, int pitch, int bpp, int x, int y, uint32_t color);
|
||||
void draw_char(unsigned short int c, int cx, int cy, uint32_t fg, uint32_t bg);
|
||||
void scroll();
|
||||
void psf_init();
|
||||
|
||||
#endif
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "../kernel/io.h"
|
||||
#include "serial.h"
|
||||
#include "../libc/stdio.h"
|
||||
#include "../libk/stdio.h"
|
||||
|
||||
int init_serial()
|
||||
{
|
||||
@@ -4,7 +4,7 @@
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include "../kernel/system.h"
|
||||
#include "../libc/stdio.h"
|
||||
#include "../libk/stdio.h"
|
||||
|
||||
volatile unsigned long global_ticks = 0;
|
||||
|
||||
Binary file not shown.
BIN
include/fonts/viscii10-8x16.psfu
Normal file
BIN
include/fonts/viscii10-8x16.psfu
Normal file
Binary file not shown.
@@ -4,7 +4,7 @@
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include "gdt.h"
|
||||
#include "../libc/stdio.h"
|
||||
#include "../libk/stdio.h"
|
||||
|
||||
struct gdt_entry gdt[3];
|
||||
struct gdt_ptr gp;
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include "idt.h"
|
||||
#include "system.h"
|
||||
#include "../libc/stdio.h"
|
||||
#include "../libk/stdio.h"
|
||||
|
||||
struct idt_entry idt[256];
|
||||
struct idt_ptr idtp;
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "system.h"
|
||||
#include "io.h"
|
||||
#include "idt.h"
|
||||
#include "../libc/stdio.h"
|
||||
#include "../libk/stdio.h"
|
||||
|
||||
extern void irq0();
|
||||
extern void irq1();
|
||||
@@ -4,7 +4,7 @@
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include "system.h"
|
||||
#include "../libc/stdio.h"
|
||||
#include "../libk/stdio.h"
|
||||
#include "idt.h"
|
||||
|
||||
extern void isr0();
|
||||
@@ -3,20 +3,15 @@
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include "../libc/stdio.h"
|
||||
#include "../libk/stdio.h"
|
||||
#include "../drivers/serial.h"
|
||||
#include "gdt.h"
|
||||
#include "idt.h"
|
||||
#include "system.h"
|
||||
#include "../drivers/ata.h"
|
||||
#include <stdint.h>
|
||||
#include "../drivers/framebuffer.h"
|
||||
#include "kmain.h"
|
||||
#include "multiboot2.h"
|
||||
#include "kheap.h"
|
||||
#include "initrd.h"
|
||||
#include "../programs/programs.h"
|
||||
#include "../libc/crypto.h"
|
||||
|
||||
void kmain(multiboot2_info *mb_info)
|
||||
{
|
||||
@@ -63,7 +58,6 @@ void kmain(multiboot2_info *mb_info)
|
||||
serial_printf(3, "Framebuffer Pitch: %u", fb_info->framebuffer_pitch);
|
||||
serial_printf(3, "Framebuffer BPP: %u", fb_info->framebuffer_bpp);
|
||||
}
|
||||
|
||||
printf("[kernel] multiboot2 info at 0x%x, size=%u\n", mb_info, mb_info->total_size);
|
||||
printf("[kernel] framebuffer discovered at 0x%x\n", (unsigned int)fb_info->framebuffer_addr);
|
||||
printf("[kernel] fb0: width=%u, height=%u, pitch=%u, bpp=%u\n", fb_info->framebuffer_width, fb_info->framebuffer_height, fb_info->framebuffer_pitch, fb_info->framebuffer_bpp);
|
||||
@@ -78,14 +72,14 @@ void kmain(multiboot2_info *mb_info)
|
||||
|
||||
if (mmap->addr != 0)
|
||||
{
|
||||
|
||||
/*
|
||||
serial_printf(3, "base addr=0x%x%x, length=0x%x%x, type=%u",
|
||||
(uint32_t) (mmap->addr >> 32),
|
||||
(uint32_t) (mmap->addr & 0xFFFFFFFF),
|
||||
(uint32_t) (mmap->len >> 32),
|
||||
(uint32_t) (mmap->len & 0xFFFFFFFF),
|
||||
mmap->type);
|
||||
|
||||
*/
|
||||
}
|
||||
|
||||
mmap = (struct multiboot_mmap_entry*) ((uint8_t*)mmap + mmap_tag->entry_size);
|
||||
@@ -112,14 +106,7 @@ void kmain(multiboot2_info *mb_info)
|
||||
irq_install();
|
||||
__asm__ __volatile__("sti");
|
||||
|
||||
init_alloc();
|
||||
void* ptr1 = malloc(256);
|
||||
void* ptr2 = malloc(512);
|
||||
printf("[debug] malloc test ptr1=0x%x, ptr2=0x%x\n", (unsigned int)ptr1, (unsigned int)ptr2);
|
||||
free(ptr1); free(ptr2);
|
||||
|
||||
timer_install();
|
||||
keyboard_install();
|
||||
printf("[kernel] spawning shell...\n");
|
||||
shell_install();
|
||||
printf("Nothing to do, halting...");
|
||||
asm("hlt");
|
||||
}
|
||||
@@ -213,5 +213,5 @@ irq_common_stub:
|
||||
section .bss
|
||||
align 4
|
||||
|
||||
resb KERNEL_STACK_SIZE
|
||||
kernel_stack:
|
||||
resb KERNEL_STACK_SIZE
|
||||
@@ -39,5 +39,7 @@ extern volatile unsigned long global_ticks;
|
||||
|
||||
extern unsigned int g_multiboot_info_address;
|
||||
|
||||
void syscall_handler();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Ctype implementation for blankos/libc
|
||||
// Ctype implementation for blankos/libk
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
@@ -1,4 +1,4 @@
|
||||
// Ctype implementation for blankos/libc header
|
||||
// Ctype implementation for blankos/libk header
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
@@ -1,4 +1,4 @@
|
||||
// Standard input/output implementation for blankos/libc
|
||||
// Standard input/output implementation for blankos/libk
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
@@ -482,7 +482,7 @@ int* printf_number(int* argp, int length, bool sign, int radix, int width, char
|
||||
|
||||
return argp;
|
||||
}
|
||||
|
||||
/*
|
||||
int getch()
|
||||
{
|
||||
return keyboard_getchar();
|
||||
@@ -511,6 +511,7 @@ void get_input(char *buffer, int size) {
|
||||
}
|
||||
buffer[index] = '\0';
|
||||
}
|
||||
*/
|
||||
|
||||
void colorprintf(uint32_t fg, uint32_t bg, const char* fmt, ...)
|
||||
{
|
||||
@@ -1,4 +1,4 @@
|
||||
// Standard input/output implementation for blankos/libc header
|
||||
// Standard input/output implementation for blankos/libk header
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
@@ -1,4 +1,4 @@
|
||||
// String operations implementation for blankos/libc
|
||||
// String operations implementation for blankos/libk
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
@@ -1,4 +1,4 @@
|
||||
// String operations implementation for blankos/libc header
|
||||
// String operations implementation for blankos/libk header
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
42
makefile
42
makefile
@@ -1,42 +1,42 @@
|
||||
CC = i386-elf-7.5.0-Linux-x86_64/bin/i386-elf-gcc
|
||||
CFLAGS = -ffreestanding -g -Wall -Wextra -Wno-builtin-declaration-mismatch -mno-sse -mno-mmx -mno-avx -march=i386 -c -I src/
|
||||
CFLAGS = -ffreestanding -g -Wall -Wextra -mno-sse -mno-mmx -mno-avx -march=i386 -c -I .
|
||||
LD = ld
|
||||
LDFLAGS = -T link.ld -melf_i386
|
||||
AS = nasm
|
||||
ASFLAGS = -f elf
|
||||
AR = i386-elf-7.5.0-Linux-x86_64/bin/i386-elf-ar
|
||||
|
||||
SRC_DIR = src
|
||||
KERNEL_DIR = $(SRC_DIR)/kernel
|
||||
LIBC_DIR = $(SRC_DIR)/libc
|
||||
PROGRAMS_DIR = $(SRC_DIR)/programs
|
||||
DRIVERS_DIR = $(SRC_DIR)/drivers
|
||||
KERNEL_DIR = kernel
|
||||
libk_DIR = libk
|
||||
DRIVERS_DIR = drivers
|
||||
INCLUDE_DIR = include
|
||||
FONTS_DIR = $(INCLUDE_DIR)/fonts
|
||||
OBJ_DIR = build
|
||||
|
||||
C_SOURCES = $(wildcard $(KERNEL_DIR)/*.c) $(wildcard $(LIBC_DIR)/*.c) $(wildcard $(PROGRAMS_DIR)/*.c) $(wildcard $(DRIVERS_DIR)/*.c)
|
||||
ASM_SOURCES = $(wildcard $(KERNEL_DIR)/*.s) $(wildcard $(LIBC_DIR)/*.s) $(wildcard $(PROGRAMS_DIR)/*.s) $(wildcard $(DRIVERS_DIR)/*.s)
|
||||
C_SOURCES = $(wildcard $(KERNEL_DIR)/*.c) $(wildcard $(libk_DIR)/*.c) $(wildcard $(DRIVERS_DIR)/*.c)
|
||||
ASM_SOURCES = $(wildcard $(KERNEL_DIR)/*.s) $(wildcard $(libk_DIR)/*.s) $(wildcard $(DRIVERS_DIR)/*.s)
|
||||
|
||||
OBJECTS = $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(C_SOURCES:.c=.o) $(ASM_SOURCES:.s=.o))
|
||||
OBJECTS = $(patsubst %, $(OBJ_DIR)/%, $(C_SOURCES:.c=.o) $(ASM_SOURCES:.s=.o))
|
||||
|
||||
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
|
||||
|
||||
FONT_OBJ = $(OBJ_DIR)/fonts/UniCyr_8x16.o
|
||||
FONT_SRC = $(FONTS_DIR)/UniCyr_8x16.psf
|
||||
FONT_OBJ = $(OBJ_DIR)/fonts/viscii10-8x16.o
|
||||
FONT_SRC = $(FONTS_DIR)/viscii10-8x16.psfu
|
||||
|
||||
all: $(OBJ_DIR) kernel.elf
|
||||
|
||||
$(OBJ_DIR):
|
||||
mkdir -p $(OBJ_DIR)
|
||||
mkdir -p $(OBJ_DIR)/kernel $(OBJ_DIR)/libc $(OBJ_DIR)/programs $(OBJ_DIR)/drivers $(OBJ_DIR)/fonts
|
||||
|
||||
mkdir -p $(OBJ_DIR)/kernel $(OBJ_DIR)/libk $(OBJ_DIR)/drivers $(OBJ_DIR)/fonts $(OBJ_DIR)/programs
|
||||
|
||||
kernel.elf: $(OBJECTS) $(FONT_OBJ)
|
||||
ld $(LDFLAGS) $(OBJECTS) $(FONT_OBJ) -o kernel.elf
|
||||
$(LD) $(LDFLAGS) $(OBJECTS) $(FONT_OBJ) -o kernel.elf
|
||||
|
||||
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
|
||||
$(OBJ_DIR)/%.o: %.c
|
||||
$(CC) $(CFLAGS) $< -o $@
|
||||
|
||||
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.s
|
||||
$(OBJ_DIR)/%.o: %.s
|
||||
$(AS) $(ASFLAGS) $< -o $@
|
||||
|
||||
$(FONT_OBJ): $(FONT_SRC) | $(OBJ_DIR)/fonts
|
||||
@@ -49,16 +49,11 @@ toolchain:
|
||||
wget $(TOOLCHAIN_SRC)
|
||||
tar xf $(TOOLCHAIN_FILE)
|
||||
|
||||
iso: kernel.elf initrd
|
||||
iso: kernel.elf
|
||||
cp kernel.elf iso/boot/kernel.elf
|
||||
cp grub.cfg iso/boot/grub/grub.cfg
|
||||
grub-mkrescue iso -o blankos.iso
|
||||
|
||||
initrd:
|
||||
mkdir -p iso/boot/grub
|
||||
tar -cf $(OBJ_DIR)/initrd.tar -C $(SRC_DIR)/initrd .
|
||||
cp $(OBJ_DIR)/initrd.tar iso/boot
|
||||
|
||||
run: iso
|
||||
qemu-system-i386 -drive file=blankos.iso,format=raw
|
||||
|
||||
@@ -66,5 +61,4 @@ debug:
|
||||
./debug.sh
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJ_DIR) kernel.elf blankos.iso $(TOOLCHAIN_FILE)
|
||||
|
||||
rm -rf $(OBJ_DIR) kernel.elf blankos.iso $(TOOLCHAIN_FILE) initrd/*.bin
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
// ATA PIO driver implementation
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include <stdint.h>
|
||||
#include "../kernel/io.h"
|
||||
#include "../libc/stdio.h"
|
||||
#include "ata.h"
|
||||
|
||||
static inline uint16_t inw(uint16_t port) {
|
||||
uint16_t result;
|
||||
asm volatile("inw %1, %0" : "=a"(result) : "dN"(port));
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void outw(uint16_t port, uint16_t data) {
|
||||
asm volatile("outw %1, %0" : : "dN"(port), "a"(data));
|
||||
}
|
||||
|
||||
void ata_wait_bsy() {
|
||||
while (inb(ATA_PRIMARY_IO + ATA_REG_STATUS) & ATA_SR_BSY);
|
||||
}
|
||||
|
||||
void ata_wait_drq() {
|
||||
while (!(inb(ATA_PRIMARY_IO + ATA_REG_STATUS) & ATA_SR_DRQ));
|
||||
}
|
||||
|
||||
void ata_select_drive(uint8_t drive) {
|
||||
outb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xE0 | (drive << 4));
|
||||
}
|
||||
|
||||
void ata_read_sector(uint32_t lba, uint8_t* buffer) {
|
||||
ata_wait_bsy();
|
||||
ata_select_drive(0);
|
||||
|
||||
outb(ATA_PRIMARY_IO + ATA_REG_SECCOUNT0, 1);
|
||||
outb(ATA_PRIMARY_IO + ATA_REG_LBA0, (uint8_t)lba);
|
||||
outb(ATA_PRIMARY_IO + ATA_REG_LBA1, (uint8_t)(lba >> 8));
|
||||
outb(ATA_PRIMARY_IO + ATA_REG_LBA2, (uint8_t)(lba >> 16));
|
||||
outb(ATA_PRIMARY_IO + ATA_REG_HDDEVSEL, 0xE0 | ((lba >> 24) & 0x0F));
|
||||
|
||||
outb(ATA_PRIMARY_IO + ATA_REG_COMMAND, ATA_CMD_READ_PIO);
|
||||
|
||||
ata_wait_bsy();
|
||||
ata_wait_drq();
|
||||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
((uint16_t*)buffer)[i] = inw(ATA_PRIMARY_IO + ATA_REG_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
// Works only w/o paging
|
||||
void test_read_sector() {
|
||||
uint8_t buffer[512];
|
||||
ata_read_sector(0, buffer);
|
||||
|
||||
for (int i = 0; i < 512; i++) {
|
||||
if (i%25==0) puts("\n");
|
||||
printf("%02x ", buffer[i]);
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
// ATA PIO driver implementation header
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#ifndef ATA_H
|
||||
#define ATA_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define ATA_PRIMARY_IO 0x1F0
|
||||
#define ATA_PRIMARY_CTRL 0x3F6
|
||||
#define ATA_CMD_READ_PIO 0x20
|
||||
#define ATA_CMD_WRITE_PIO 0x30
|
||||
#define ATA_IDENTIFY 0xEC
|
||||
|
||||
#define ATA_REG_DATA 0x00
|
||||
#define ATA_REG_ERROR 0x01
|
||||
#define ATA_REG_SECCOUNT0 0x02
|
||||
#define ATA_REG_LBA0 0x03
|
||||
#define ATA_REG_LBA1 0x04
|
||||
#define ATA_REG_LBA2 0x05
|
||||
#define ATA_REG_HDDEVSEL 0x06
|
||||
#define ATA_REG_COMMAND 0x07
|
||||
#define ATA_REG_STATUS 0x07
|
||||
|
||||
#define ATA_SR_BSY 0x80
|
||||
#define ATA_SR_DRDY 0x40
|
||||
#define ATA_SR_DRQ 0x08
|
||||
#define ATA_SR_ERR 0x01
|
||||
|
||||
void ata_read_sector(uint32_t lba, uint8_t* buffer);
|
||||
void test_read_sector();
|
||||
|
||||
#endif
|
||||
158
src/drivers/kb.c
158
src/drivers/kb.c
@@ -1,158 +0,0 @@
|
||||
// Keyboard driver
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include "../kernel/io.h"
|
||||
#include "../libc/stdio.h"
|
||||
#include "../kernel/system.h"
|
||||
#include "kb.h"
|
||||
|
||||
unsigned char kbdus[128] =
|
||||
{
|
||||
0, 27, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */
|
||||
'9', '0', '-', '=', '\b', /* Backspace */
|
||||
'\t', /* Tab */
|
||||
'q', 'w', 'e', 'r', /* 19 */
|
||||
't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */
|
||||
0, /* 29 - Control */
|
||||
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */
|
||||
'\'', '`', 0, /* Left shift */
|
||||
'\\', 'z', 'x', 'c', 'v', 'b', 'n', /* 49 */
|
||||
'm', ',', '.', '/', 0, /* Right shift */
|
||||
'*',
|
||||
0, /* Alt */
|
||||
' ', /* Space bar */
|
||||
0, /* Caps lock */
|
||||
0, /* 59 - F1 key ... > */
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, /* < ... F10 */
|
||||
0, /* 69 - Num lock*/
|
||||
0, /* Scroll Lock */
|
||||
0, /* Home key */
|
||||
0, /* Up Arrow */
|
||||
0, /* Page Up */
|
||||
'-',
|
||||
0, /* Left Arrow */
|
||||
0,
|
||||
0, /* Right Arrow */
|
||||
'+',
|
||||
0, /* 79 - End key*/
|
||||
0, /* Down Arrow */
|
||||
0, /* Page Down */
|
||||
0, /* Insert Key */
|
||||
0, /* Delete Key */
|
||||
0, 0, 0,
|
||||
0, /* F11 Key */
|
||||
0, /* F12 Key */
|
||||
0, /* All other keys are undefined */
|
||||
};
|
||||
|
||||
unsigned char kbdus_shift[128] =
|
||||
{
|
||||
0, 27, '!', '@', '#', '$', '%', '^', '&', '*', /* 9 */
|
||||
'(', ')', '_', '+', '\b', /* Backspace */
|
||||
'\t', /* Tab */
|
||||
'Q', 'W', 'E', 'R', /* 19 */
|
||||
'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '\n', /* Enter key */
|
||||
0, /* 29 - Control */
|
||||
'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* 39 */
|
||||
'"', '~', 0, /* Left shift */
|
||||
'|', 'Z', 'X', 'C', 'V', 'B', 'N', /* 49 */
|
||||
'M', '<', '>', '?', 0, /* Right shift */
|
||||
'*',
|
||||
0, /* Alt */
|
||||
' ', /* Space bar */
|
||||
0, /* Caps lock */
|
||||
0, /* 59 - F1 key ... > */
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, /* < ... F10 */
|
||||
0, /* 69 - Num lock*/
|
||||
0, /* Scroll Lock */
|
||||
0, /* Home key */
|
||||
0, /* Up Arrow */
|
||||
0, /* Page Up */
|
||||
'-',
|
||||
0, /* Left Arrow */
|
||||
0,
|
||||
0, /* Right Arrow */
|
||||
'+',
|
||||
0, /* 79 - End key*/
|
||||
0, /* Down Arrow */
|
||||
0, /* Page Down */
|
||||
0, /* Insert Key */
|
||||
0, /* Delete Key */
|
||||
0, 0, 0,
|
||||
0, /* F11 Key */
|
||||
0, /* F12 Key */
|
||||
0, /* All other keys are undefined */
|
||||
};
|
||||
|
||||
static char keyboard_buffer[KEYBOARD_BUFFER_SIZE];
|
||||
static unsigned int keyboard_buffer_start = 0;
|
||||
static unsigned int keyboard_buffer_end = 0;
|
||||
static int shift_pressed = 0;
|
||||
|
||||
void keyboard_handler()
|
||||
{
|
||||
unsigned char scancode;
|
||||
|
||||
scancode = inb(0x60);
|
||||
|
||||
if (scancode & 0x80)
|
||||
{
|
||||
if (scancode == LEFT_SHIFT_RELEASED || scancode == RIGHT_SHIFT_RELEASED) {
|
||||
shift_pressed = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (scancode == LEFT_SHIFT_PRESSED || scancode == RIGHT_SHIFT_PRESSED) {
|
||||
shift_pressed = 1;
|
||||
} else {
|
||||
char c;
|
||||
if (shift_pressed) {
|
||||
c = kbdus_shift[scancode];
|
||||
} else {
|
||||
c = kbdus[scancode];
|
||||
}
|
||||
|
||||
if (c)
|
||||
{
|
||||
keyboard_buffer[keyboard_buffer_end] = c;
|
||||
keyboard_buffer_end = (keyboard_buffer_end+1) % KEYBOARD_BUFFER_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void keyboard_install()
|
||||
{
|
||||
irq_install_handler(1, keyboard_handler);
|
||||
printf("[keyboard] installed irq handler\n");
|
||||
}
|
||||
|
||||
char keyboard_getchar()
|
||||
{
|
||||
while (keyboard_buffer_start == keyboard_buffer_end);
|
||||
|
||||
char c = keyboard_buffer[keyboard_buffer_start];
|
||||
keyboard_buffer_start = (keyboard_buffer_start+1) % KEYBOARD_BUFFER_SIZE;
|
||||
return c;
|
||||
}
|
||||
|
||||
int keyboard_has_input()
|
||||
{
|
||||
return keyboard_buffer_start != keyboard_buffer_end;
|
||||
}
|
||||
|
||||
char keyboard_getchar_non_blocking()
|
||||
{
|
||||
if (keyboard_has_input())
|
||||
{
|
||||
char c = keyboard_buffer[keyboard_buffer_start];
|
||||
keyboard_buffer_start = (keyboard_buffer_start+1)%KEYBOARD_BUFFER_SIZE;
|
||||
return c;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
// Keyboard driver header
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#ifndef KB_H
|
||||
#define KB_H
|
||||
|
||||
#define KEYBOARD_BUFFER_SIZE 256
|
||||
|
||||
#define LEFT_SHIFT_PRESSED 0x2A
|
||||
#define RIGHT_SHIFT_PRESSED 0x36
|
||||
#define LEFT_SHIFT_RELEASED 0xAA
|
||||
#define RIGHT_SHIFT_RELEASED 0xB6
|
||||
|
||||
char keyboard_getchar();
|
||||
int keyboard_has_input();
|
||||
char keyboard_getchar_non_blocking();
|
||||
|
||||
#endif
|
||||
@@ -1,103 +0,0 @@
|
||||
// PCI bus driver implementation
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include <stdint.h>
|
||||
#include "pci.h"
|
||||
#include "../libc/stdio.h"
|
||||
|
||||
static inline void outl(uint16_t port, uint32_t value)
|
||||
{
|
||||
__asm__ volatile ("outl %0, %1" : : "a"(value), "Nd"(port));
|
||||
}
|
||||
|
||||
static inline uint32_t inl(uint16_t port)
|
||||
{
|
||||
uint32_t ret;
|
||||
__asm__ volatile ("inl %1, %0" : "=a"(ret) : "Nd"(port));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void pci_write_config_address(uint32_t address)
|
||||
{
|
||||
outl(PCI_CONFIG_ADDRESS, address);
|
||||
}
|
||||
|
||||
uint32_t pci_read_config_data()
|
||||
{
|
||||
return inl(PCI_CONFIG_DATA);
|
||||
}
|
||||
|
||||
uint32_t pci_config_address(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset)
|
||||
{
|
||||
return (1 << 31) | (bus << 16) | (device << 11) | (function << 8) | (offset & 0xFC);
|
||||
}
|
||||
|
||||
uint32_t pci_read(uint8_t bus, uint8_t device, uint8_t function, uint8_t offset)
|
||||
{
|
||||
uint32_t address = pci_config_address(bus, device, function, offset);
|
||||
pci_write_config_address(address);
|
||||
return pci_read_config_data();
|
||||
}
|
||||
|
||||
pci_device_t pci_get_device(uint8_t bus, uint8_t device, uint8_t function)
|
||||
{
|
||||
pci_device_t dev;
|
||||
|
||||
uint32_t reg0 = pci_read(bus, device, function, 0x00); // Vendor ID, Device ID
|
||||
uint32_t reg2 = pci_read(bus, device, function, 0x08); // Class, Subclass, Prog IF, Revision
|
||||
|
||||
dev.vendor_id = reg0 & 0xFFFF;
|
||||
dev.device_id = (reg0 >> 16) & 0xFFFF;
|
||||
dev.class_code = (reg2 >> 24) & 0xFF;
|
||||
dev.subclass = (reg2 >> 16) & 0xFF;
|
||||
dev.prog_if = (reg2 >> 8) & 0xFF;
|
||||
dev.revision_id = reg2 & 0xFF;
|
||||
dev.bus = bus;
|
||||
dev.device = device;
|
||||
dev.function = function;
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
void scan_pci_bus()
|
||||
{
|
||||
for (uint16_t bus = 0; bus < 256; bus++) {
|
||||
for (uint8_t device = 0; device < 32; device++) {
|
||||
for (uint8_t function = 0; function < 8; function++) {
|
||||
pci_device_t dev = pci_get_device(bus, device, function);
|
||||
|
||||
if (dev.vendor_id != 0xFFFF) {
|
||||
|
||||
// Maybe put that in a database in initrd.tar?
|
||||
char* vendor_string;
|
||||
switch(dev.vendor_id)
|
||||
{
|
||||
case 0x8086:
|
||||
vendor_string = "Intel Corporation";
|
||||
break;
|
||||
case 0x1234:
|
||||
vendor_string = "Brain Actuated Technologies";
|
||||
break;
|
||||
default:
|
||||
vendor_string = "Unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
char* device_string;
|
||||
switch(dev.device_id)
|
||||
{
|
||||
default:
|
||||
device_string = "Unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
printf("PCI Device found: Bus %u, Device %u, Function %u, Vendor ID: 0x%x (%s), Device ID: 0x%x (%s), Class: 0x%x\n",
|
||||
dev.bus, dev.device, dev.function, dev.vendor_id, vendor_string, dev.device_id, device_string, dev.class_code);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
// PCI bus driver implementation header
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#ifndef PCI_H
|
||||
#define PCI_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define PCI_CONFIG_ADDRESS 0xCF8
|
||||
#define PCI_CONFIG_DATA 0xCFC
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t vendor_id;
|
||||
uint16_t device_id;
|
||||
uint8_t class_code;
|
||||
uint8_t subclass;
|
||||
uint8_t prog_if;
|
||||
uint8_t revision_id;
|
||||
uint8_t bus;
|
||||
uint8_t device;
|
||||
uint8_t function;
|
||||
} pci_device_t;
|
||||
|
||||
void scan_pci_bus();
|
||||
|
||||
#endif
|
||||
@@ -1,64 +0,0 @@
|
||||
// Real-time clock driver implementation for better PRNG
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include <stdint.h>
|
||||
#include "rtc.h"
|
||||
#include "../kernel/io.h"
|
||||
#include "../libc/stdio.h"
|
||||
|
||||
uint8_t rtc_read_register(uint8_t reg)
|
||||
{
|
||||
outb(0x70, reg);
|
||||
return inb(0x71);
|
||||
}
|
||||
|
||||
uint8_t bcd_to_bin(uint8_t bcd)
|
||||
{
|
||||
return ((bcd/16)*10) + (bcd%16);
|
||||
}
|
||||
|
||||
int rtc_is_updating()
|
||||
{
|
||||
outb(0x70, 0x0A);
|
||||
return (inb(0x71) & 0x80);
|
||||
}
|
||||
|
||||
void rtc_read_time(rtc_time_t *time)
|
||||
{
|
||||
while (rtc_is_updating());
|
||||
|
||||
time->seconds = rtc_read_register(0x00);
|
||||
time->minutes = rtc_read_register(0x02);
|
||||
time->hours = rtc_read_register(0x04);
|
||||
time->day = rtc_read_register(0x06);
|
||||
time->month = rtc_read_register(0x07);
|
||||
time->year = rtc_read_register(0x08);
|
||||
|
||||
outb(0x70, 0x0B);
|
||||
uint8_t registerB = inb(0x71);
|
||||
|
||||
if (!(registerB & 0x04))
|
||||
{
|
||||
time->seconds = bcd_to_bin(time->seconds);
|
||||
time->minutes = bcd_to_bin(time->minutes);
|
||||
time->hours = bcd_to_bin(time->hours);
|
||||
time->day = bcd_to_bin(time->day);
|
||||
time->month = bcd_to_bin(time->month);
|
||||
time->year = bcd_to_bin(time->year);
|
||||
}
|
||||
}
|
||||
|
||||
void print_time(const rtc_time_t *time)
|
||||
{
|
||||
printf("%02d/%02d/%02d %02d:%02d:%02d\n", time->day, time->month, time->year, time->hours, time->minutes, time->seconds);
|
||||
}
|
||||
|
||||
long time_seed()
|
||||
{
|
||||
rtc_time_t* time = {0};
|
||||
rtc_read_time(time);
|
||||
|
||||
return time->day + time->month + time->year + time->hours + time->minutes + time->seconds;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
// Real-time clock driver implementation header for better PRNG
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#ifndef RTC_H
|
||||
#define RTC_H
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t seconds;
|
||||
uint8_t minutes;
|
||||
uint8_t hours;
|
||||
uint8_t day;
|
||||
uint8_t month;
|
||||
uint8_t year;
|
||||
} rtc_time_t;
|
||||
|
||||
void rtc_read_time(rtc_time_t *time);
|
||||
long time_seed();
|
||||
void print_time(const rtc_time_t *time);
|
||||
|
||||
#endif
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 29 KiB |
@@ -1 +0,0 @@
|
||||
-[------->+<]>-.-[->+++++<]>++.+++++++..+++.[--->+<]>-----.---[->+++<]>.-[--->+<]>---.+++.------.--------.
|
||||
@@ -1 +0,0 @@
|
||||
hello, ramdisk world!
|
||||
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 |
@@ -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
|
||||
@@ -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...
|
||||
@@ -1,176 +0,0 @@
|
||||
// Initial TAR ramdisk kernel module
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include "../libc/stdio.h"
|
||||
#include <stdint.h>
|
||||
#include "../libc/string.h"
|
||||
#include "initrd.h"
|
||||
#include "system.h"
|
||||
|
||||
static unsigned int octal_to_int(const char* str, size_t size)
|
||||
{
|
||||
unsigned int result = 0;
|
||||
while (*str && size-- > 0)
|
||||
{
|
||||
result = (result << 3) | (*str - '0');
|
||||
str++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t tar_parse_size(const char* in)
|
||||
{
|
||||
uint32_t size = 0;
|
||||
while (*in >= '0' && *in <= '7')
|
||||
{
|
||||
size = (size*8) + (*in - '0');
|
||||
in++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void tar_find_file(uint8_t *tar_start, const char* filename)
|
||||
{
|
||||
uint8_t *ptr = tar_start;
|
||||
|
||||
while (1)
|
||||
{
|
||||
tar_header_t *header = (tar_header_t*)ptr;
|
||||
|
||||
if (header->filename[0] == '\0')
|
||||
{
|
||||
puts("[tar] EOF\n");
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned int filesize = octal_to_int(header->size, 11);
|
||||
|
||||
if (strcmp(header->filename, filename) == 0)
|
||||
{
|
||||
printf("[tar] found file '%s', size=%u bytes\n", header->filename, filesize);
|
||||
|
||||
uint8_t *file_data = ptr+TAR_BLOCK_SIZE;
|
||||
printf("[tar] content of '%s':\n", filename);
|
||||
for (unsigned int i=0; i<filesize; i++)
|
||||
{
|
||||
putc(file_data[i]);
|
||||
}
|
||||
puts("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ptr += TAR_BLOCK_SIZE + ((filesize + TAR_BLOCK_SIZE-1) / TAR_BLOCK_SIZE) * TAR_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
printf("[tar] file '%s' not found\n", filename);
|
||||
}
|
||||
|
||||
void ls_initrd(uint8_t* initrd, int verbose)
|
||||
{
|
||||
tar_header_t *header = (tar_header_t*)initrd;
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
puts("Size Type Filename\n");
|
||||
}
|
||||
|
||||
while (header->filename[0] != '\0')
|
||||
{
|
||||
if (!verbose)
|
||||
{
|
||||
printf("%s\n", header->filename);
|
||||
} else {
|
||||
printf("%7d\t%c\t %s\n", (int)header->size, header->typeflag, header->filename);
|
||||
}
|
||||
|
||||
uint32_t size = tar_parse_size(header->size);
|
||||
uint32_t next_file_offset = ((size+TAR_BLOCK_SIZE-1)/TAR_BLOCK_SIZE)*TAR_BLOCK_SIZE;
|
||||
header = (tar_header_t*)((uint8_t*)header + next_file_offset + TAR_BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
void cat_initrd(uint8_t* initrd, const char* filename)
|
||||
{
|
||||
tar_header_t *header = (tar_header_t*)initrd;
|
||||
|
||||
while (header->filename[0] != '\0')
|
||||
{
|
||||
if (strcmp(header->filename, filename) == 0)
|
||||
{
|
||||
uint32_t size = tar_parse_size(header->size);
|
||||
uint8_t* file_content = (uint8_t*)header + 512;
|
||||
|
||||
for (uint32_t i=0; i<size; i++) putc(file_content[i]);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t next_file_offset = ((tar_parse_size(header->size)+TAR_BLOCK_SIZE-1)/TAR_BLOCK_SIZE)*TAR_BLOCK_SIZE;
|
||||
header = (tar_header_t*)((uint8_t*)header + next_file_offset + TAR_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
printf("File '%s' not found\n", filename);
|
||||
}
|
||||
|
||||
int tar_file_to_buffer(uint8_t* initrd, const char* filename, char* buffer)
|
||||
{
|
||||
uint8_t* current_block = initrd;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (current_block[0] == '\0')
|
||||
{
|
||||
//puts("[tar] EOF\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char* file_name = (const char*)current_block;
|
||||
uint32_t file_size = tar_parse_size((const char*)(current_block+124));
|
||||
|
||||
if (strcmp(file_name, filename) == 0)
|
||||
{
|
||||
uint8_t* file_data = current_block + TAR_BLOCK_SIZE;
|
||||
if (sizeof(buffer) >= sizeof(file_data))
|
||||
{
|
||||
memcpy(buffer, file_data, file_size);
|
||||
buffer[file_size] = '\0';
|
||||
return 0;
|
||||
} else {
|
||||
printf("Invalid destination buffer size %d bytes < %d bytes\n", sizeof(buffer), sizeof(file_data));
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t total_size = ((file_size + TAR_BLOCK_SIZE - 1) / TAR_BLOCK_SIZE) * TAR_BLOCK_SIZE;
|
||||
current_block += TAR_BLOCK_SIZE + total_size;
|
||||
}
|
||||
printf("[tar] file '%s' not found\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t tar_get_file_size(uint8_t* initrd, const char* filename)
|
||||
{
|
||||
uint8_t* current_block = initrd;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (current_block[0] == '\0')
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char* file_name = (const char*)current_block;
|
||||
uint32_t file_size = tar_parse_size((const char*)(current_block+124));
|
||||
|
||||
if (strcmp(file_name, filename) == 0)
|
||||
{
|
||||
return file_size;
|
||||
}
|
||||
|
||||
uint32_t total_size = ((file_size + TAR_BLOCK_SIZE - 1) / TAR_BLOCK_SIZE) * TAR_BLOCK_SIZE;
|
||||
current_block += TAR_BLOCK_SIZE + total_size;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
// Initial TAR ramdisk kernel module header
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#ifndef INITRD_H
|
||||
#define INITRD_H
|
||||
|
||||
#define TAR_BLOCK_SIZE 512
|
||||
|
||||
#include "system.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char filename[100];
|
||||
char mode[8];
|
||||
char owner[8];
|
||||
char group[8];
|
||||
char size[12];
|
||||
char mtime[12];
|
||||
char checksum[8];
|
||||
char typeflag;
|
||||
char linkname[100];
|
||||
char magic[6];
|
||||
char version[2];
|
||||
char uname[32];
|
||||
char gname[32];
|
||||
char devmajor[8];
|
||||
char devminor[8];
|
||||
char prefix[155];
|
||||
} tar_header_t;
|
||||
|
||||
void tar_find_file(uint8_t *tar_start, const char* filename);
|
||||
void ls_initrd(uint8_t* initrd, int verbose);
|
||||
void cat_initrd(uint8_t* initrd, const char* filename);
|
||||
int tar_file_to_buffer(uint8_t* initrd, const char* filename, char* buffer);
|
||||
uint32_t tar_get_file_size(uint8_t* initrd, const char* filename);
|
||||
|
||||
#endif
|
||||
@@ -1,64 +0,0 @@
|
||||
// Kernel heap management
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include "kheap.h"
|
||||
#include <stdint.h>
|
||||
#include "system.h"
|
||||
|
||||
// Free list allocator
|
||||
|
||||
static uint8_t heap[HEAP_SIZE];
|
||||
static block_t* free_list = NULL;
|
||||
|
||||
void init_alloc()
|
||||
{
|
||||
free_list = (block_t*)heap;
|
||||
free_list->size = HEAP_SIZE-sizeof(block_t);
|
||||
free_list->next = NULL;
|
||||
}
|
||||
|
||||
void* malloc(size_t size)
|
||||
{
|
||||
block_t* prev = NULL;
|
||||
block_t* curr = free_list;
|
||||
|
||||
while (curr != NULL)
|
||||
{
|
||||
if (curr->size >= size)
|
||||
{
|
||||
if (curr->size > (size_t)(size + sizeof(block_t)))
|
||||
{
|
||||
block_t* new_block = (block_t*)((uint8_t*)curr + sizeof(block_t) + size);
|
||||
new_block->size = curr->size - size - sizeof(block_t);
|
||||
new_block->next = curr->next;
|
||||
curr->size = size;
|
||||
curr->next = new_block;
|
||||
}
|
||||
|
||||
if (prev == NULL)
|
||||
{
|
||||
free_list = curr->next;
|
||||
} else {
|
||||
prev->next = curr->next;
|
||||
}
|
||||
|
||||
return (void*)((uint8_t*)curr + sizeof(block_t));
|
||||
}
|
||||
|
||||
prev = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void free(void* ptr)
|
||||
{
|
||||
if (ptr == NULL) return;
|
||||
|
||||
block_t* block_to_free = (block_t*)((uint8_t*)ptr - sizeof(block_t));
|
||||
block_to_free->next = free_list;
|
||||
free_list = block_to_free;
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
// Kernel heap management header
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#ifndef KHEAP_H
|
||||
#define KHEAP_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "system.h"
|
||||
|
||||
typedef struct block
|
||||
{
|
||||
size_t size;
|
||||
struct block* next;
|
||||
} block_t;
|
||||
|
||||
#define HEAP_SIZE 1024*1024 // 1MB malloc-able
|
||||
|
||||
|
||||
void init_alloc();
|
||||
void* malloc(size_t size);
|
||||
void free(void* ptr);
|
||||
|
||||
#endif
|
||||
@@ -1,176 +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 "../programs/programs.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);
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
// System information kernel module
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include "../libc/stdio.h"
|
||||
#include "../libc/string.h"
|
||||
|
||||
void cpuid(int code, unsigned int* a, unsigned int* d)
|
||||
{
|
||||
asm volatile("cpuid"
|
||||
: "=a"(*a), "=d"(*d)
|
||||
: "a"(code)
|
||||
: "ecx", "ebx");
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
// System information kernel module header
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#ifndef SYSINFO_H
|
||||
#define SYSINFO_H
|
||||
|
||||
void cpuid(int code, unsigned int* a, unsigned int* d);
|
||||
|
||||
#endif
|
||||
@@ -1,48 +0,0 @@
|
||||
// Cryptography routines for blankos/libc
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include "crypto.h"
|
||||
#include <stdint.h>
|
||||
|
||||
int lcg(int seed)
|
||||
{
|
||||
int x = seed;
|
||||
|
||||
// Constants (ZX81 LCG)
|
||||
int a = 75;
|
||||
int c = 74;
|
||||
long m = 65537;
|
||||
|
||||
for (int i=0; i<10; i++)
|
||||
{
|
||||
x = (a*x + c) % m;
|
||||
}
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
int randint(int seed)
|
||||
{
|
||||
int x = lcg(seed);
|
||||
return x;
|
||||
}
|
||||
|
||||
static uint32_t next = 1;
|
||||
|
||||
uint32_t rand()
|
||||
{
|
||||
next = next * 1103515245 + 12345;
|
||||
return (next/65536) % 32768;
|
||||
}
|
||||
|
||||
float rand_float()
|
||||
{
|
||||
return rand() / 32767.0f;
|
||||
}
|
||||
|
||||
void srand(uint32_t seed)
|
||||
{
|
||||
next = seed;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
// Cryptography routines for blankos/libc header
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#ifndef CRYPTO_H
|
||||
#define CRYPTO_H
|
||||
|
||||
#define RAND_MAX 1024
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int lcg(int seed);
|
||||
int randint(int seed);
|
||||
uint32_t rand();
|
||||
float rand_float();
|
||||
void srand(uint32_t seed);
|
||||
|
||||
#endif
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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]);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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]);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1,153 +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"
|
||||
|
||||
// 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\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)
|
||||
|
||||
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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
// Global program entry points header
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#ifndef PROGRAMS_H
|
||||
#define PROGRAMS_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();
|
||||
|
||||
#endif
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
Reference in New Issue
Block a user