Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
abeb22eaab
|
|||
|
a8582ba343
|
|||
|
b3687d20ee
|
|||
|
27569fd5d8
|
@@ -59,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
|
||||
|
||||
|
||||
@@ -7,51 +7,9 @@
|
||||
#include "framebuffer.h"
|
||||
#include "serial.h"
|
||||
#include "../kernel/system.h"
|
||||
#include "../kernel/kheap.h"
|
||||
|
||||
extern char* framebuffer;
|
||||
|
||||
void psf_init()
|
||||
{
|
||||
uint16_t glyph = 0;
|
||||
PSF_font *font = (PSF_font*)&FONT_START;
|
||||
if (font->flags)
|
||||
{
|
||||
unicode = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
char* s = (char*)((unsigned char*)&FONT_START + font->headersize + font->numglyph * font->bytesperglyph);
|
||||
unicode = calloc(USHRT_MAX, 2);
|
||||
|
||||
while((uintptr_t)s>(uintptr_t)FONT_END){
|
||||
uint16_t uc = (uint16_t)((unsigned char)s[0]);
|
||||
if(uc == 0xFF) {
|
||||
glyph++;
|
||||
s++;
|
||||
continue;
|
||||
} else if(uc & 128) {
|
||||
/* UTF-8 to unicode */
|
||||
if((uc & 32) == 0 ) {
|
||||
uc = ((s[0] & 0x1F)<<6)+(s[1] & 0x3F);
|
||||
s++;
|
||||
} else
|
||||
if((uc & 16) == 0 ) {
|
||||
uc = ((((s[0] & 0xF)<<6)+(s[1] & 0x3F))<<6)+(s[2] & 0x3F);
|
||||
s+=2;
|
||||
} else
|
||||
if((uc & 8) == 0 ) {
|
||||
uc = ((((((s[0] & 0x7)<<6)+(s[1] & 0x3F))<<6)+(s[2] & 0x3F))<<6)+(s[3] & 0x3F);
|
||||
s+=3;
|
||||
} else
|
||||
uc = 0;
|
||||
}
|
||||
/* save translation */
|
||||
unicode[uc] = glyph;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
|
||||
void putpixel(uint32_t* fb, int pitch, int bpp, int x, int y, uint32_t color)
|
||||
{
|
||||
uint32_t* pixel_addr = (uint32_t*)((uint8_t*)fb + y * pitch + x *(bpp / 8));
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
@@ -25,8 +25,6 @@ extern void irq13();
|
||||
extern void irq14();
|
||||
extern void irq15();
|
||||
|
||||
extern void syscall_common_stub();
|
||||
|
||||
void *irq_routines[16] =
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -78,8 +76,6 @@ void irq_install()
|
||||
idt_set_gate(46, (unsigned)irq14, 0x08, 0x8E);
|
||||
idt_set_gate(47, (unsigned)irq15, 0x08, 0x8E);
|
||||
printf("[kernel] installed irq 0-15\n");
|
||||
|
||||
idt_set_gate(0x80, (unsigned long)syscall_common_stub, 0x08, 0x8E);
|
||||
}
|
||||
|
||||
void irq_handler(struct regs *r)
|
||||
@@ -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 "../utils/utils.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);
|
||||
}
|
||||
psf_init();
|
||||
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);
|
||||
@@ -112,12 +106,7 @@ void kmain(multiboot2_info *mb_info)
|
||||
irq_install();
|
||||
__asm__ __volatile__("sti");
|
||||
|
||||
init_alloc();
|
||||
|
||||
// usually the place where i do testing
|
||||
|
||||
timer_install();
|
||||
keyboard_install();
|
||||
printf("[kernel] spawning shell...\n");
|
||||
shell_install();
|
||||
printf("Nothing to do, halting...");
|
||||
asm("hlt");
|
||||
}
|
||||
@@ -210,37 +210,6 @@ irq_common_stub:
|
||||
add esp, 8
|
||||
iret
|
||||
|
||||
; we'll be placing the syscall_common_stub here.
|
||||
; push everything, then call syscall_handler (be sure to define it extern)
|
||||
; then pop back everything and iret
|
||||
extern syscall_handler
|
||||
|
||||
global syscall_common_stub
|
||||
syscall_common_stub:
|
||||
pusha
|
||||
push ds
|
||||
push es
|
||||
push fs
|
||||
push gs
|
||||
|
||||
mov eax, ds
|
||||
push eax ; save ds
|
||||
mov ax, 0x01 ; kernel segment YES I CHEATED I KNOW THIS SUCKS
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
|
||||
call syscall_handler
|
||||
|
||||
pop eax
|
||||
mov ds, eax ; restore ds
|
||||
|
||||
pop gs
|
||||
pop fs
|
||||
pop es
|
||||
pop ds
|
||||
popa
|
||||
iret
|
||||
|
||||
section .bss
|
||||
align 4
|
||||
|
||||
@@ -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
|
||||
44
makefile
44
makefile
@@ -1,27 +1,22 @@
|
||||
CC = i386-elf-7.5.0-Linux-x86_64/bin/i386-elf-gcc
|
||||
CFLAGS = -ffreestanding -g -Wall -Wextra -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
|
||||
UTILS_DIR = $(SRC_DIR)/utils
|
||||
DRIVERS_DIR = $(SRC_DIR)/drivers
|
||||
PROGRAMS_DIR = $(SRC_DIR)/programs
|
||||
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 $(UTILS_DIR)/*.c) $(wildcard $(DRIVERS_DIR)/*.c)
|
||||
ASM_SOURCES = $(wildcard $(KERNEL_DIR)/*.s) $(wildcard $(LIBC_DIR)/*.s) $(wildcard $(UTILS_DIR)/*.s) $(wildcard $(DRIVERS_DIR)/*.s)
|
||||
PROGRAM_SOURCES = $(wildcard $(PROGRAMS_DIR)/*.c)
|
||||
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))
|
||||
PROGRAM_OBJECTS = $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(PROGRAM_SOURCES:.c=.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
|
||||
@@ -29,26 +24,19 @@ TOOLCHAIN_FILE = i386-elf-7.5.0-Linux-x86_64.tar.xz
|
||||
FONT_OBJ = $(OBJ_DIR)/fonts/viscii10-8x16.o
|
||||
FONT_SRC = $(FONTS_DIR)/viscii10-8x16.psfu
|
||||
|
||||
all: $(OBJ_DIR) kernel.elf programs
|
||||
all: $(OBJ_DIR) kernel.elf
|
||||
|
||||
$(OBJ_DIR):
|
||||
mkdir -p $(OBJ_DIR)
|
||||
mkdir -p $(OBJ_DIR)/kernel $(OBJ_DIR)/libc $(OBJ_DIR)/utils $(OBJ_DIR)/drivers $(OBJ_DIR)/fonts $(OBJ_DIR)/programs
|
||||
mkdir -p $(OBJ_DIR)/kernel $(OBJ_DIR)/libk $(OBJ_DIR)/drivers $(OBJ_DIR)/fonts $(OBJ_DIR)/programs
|
||||
|
||||
kernel.elf: $(OBJECTS) $(FONT_OBJ)
|
||||
$(LD) $(LDFLAGS) $(OBJECTS) $(FONT_OBJ) -o kernel.elf
|
||||
|
||||
programs: $(PROGRAM_OBJECTS)
|
||||
@mkdir -p $(SRC_DIR)/initrd
|
||||
@for prog in $(PROGRAM_OBJECTS); do \
|
||||
base=$$(basename $$prog .o); \
|
||||
$(LD) -melf_i386 -T program.ld $$prog -o $(SRC_DIR)/initrd/$$base.bin; \
|
||||
done
|
||||
|
||||
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
|
||||
$(OBJ_DIR)/%.o: %.c
|
||||
$(CC) $(CFLAGS) $< -o $@
|
||||
|
||||
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.s
|
||||
$(OBJ_DIR)/%.o: %.s
|
||||
$(AS) $(ASFLAGS) $< -o $@
|
||||
|
||||
$(FONT_OBJ): $(FONT_SRC) | $(OBJ_DIR)/fonts
|
||||
@@ -61,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
|
||||
|
||||
@@ -78,5 +61,4 @@ debug:
|
||||
./debug.sh
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJ_DIR) kernel.elf blankos.iso $(TOOLCHAIN_FILE) $(SRC_DIR)/initrd/*.bin
|
||||
|
||||
rm -rf $(OBJ_DIR) kernel.elf blankos.iso $(TOOLCHAIN_FILE) initrd/*.bin
|
||||
|
||||
10
program.ld
10
program.ld
@@ -1,10 +0,0 @@
|
||||
OUTPUT_FORMAT(binary)
|
||||
ENTRY(main)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x1000;
|
||||
.text : { *(.text*) }
|
||||
.data : { *(.data*) }
|
||||
.bss : { *(.bss*) }
|
||||
}
|
||||
@@ -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: 732 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,250 +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"
|
||||
#include "kheap.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;
|
||||
}
|
||||
|
||||
uint32_t tar_get_size(tar_header_t* header)
|
||||
{
|
||||
uint32_t size = 0;
|
||||
char* size_str = header->size;
|
||||
|
||||
for (int i=0; i<11 && size_str[i] != '\0'; i++)
|
||||
{
|
||||
size = size*8 + (size_str[i]-'0');
|
||||
}
|
||||
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)
|
||||
{
|
||||
if (header->typeflag == '5')
|
||||
{
|
||||
colorprintf(cyan, black, "%s\n", header->filename);
|
||||
} else {
|
||||
printf("%s\n", header->filename);
|
||||
}
|
||||
} else {
|
||||
if (header->typeflag == '5')
|
||||
{
|
||||
printf("%7d\t%c\t", (int)header->size, header->typeflag);
|
||||
colorprintf(cyan, black, " %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;
|
||||
}
|
||||
|
||||
tar_header_t* tar_find(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)
|
||||
{
|
||||
return header;
|
||||
}
|
||||
|
||||
uint32_t file_size = tar_get_size(header);
|
||||
uint32_t file_blocks = (file_size + 511)/512;
|
||||
header = (tar_header_t*) ((uintptr_t)header+(file_blocks+1)*512);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* tar_get_file_content(tar_header_t* header)
|
||||
{
|
||||
return (void*) ((uintptr_t)header+512);
|
||||
}
|
||||
|
||||
void* load_file_from_initrd(uint8_t* initrd, const char* filename)
|
||||
{
|
||||
tar_header_t* file = tar_find(initrd, filename);
|
||||
if (file == NULL)
|
||||
{
|
||||
printf("'%s' not found\n", filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t file_size = tar_get_size(file);
|
||||
|
||||
void* file_data = malloc(file_size);
|
||||
if (file_data == NULL)
|
||||
{
|
||||
printf("Malloc error for file '%s'\n", filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* file_content = tar_get_file_content(file);
|
||||
memcpy(file_data, file_content, file_size);
|
||||
|
||||
printf("[initrd] Loaded '%s' at 0x%x, size=%u\n", filename, (unsigned int)file_data, file_size);
|
||||
|
||||
return file_data;
|
||||
}
|
||||
@@ -1,40 +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);
|
||||
void* load_file_from_initrd(uint8_t* initrd, const char* filename);
|
||||
|
||||
#endif
|
||||
@@ -1,83 +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"
|
||||
#include "../libc/stdio.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;
|
||||
printf("[kernel] initialized heap and allocator, start=0x%x\n", heap);
|
||||
}
|
||||
|
||||
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* calloc(size_t num, size_t size)
|
||||
{
|
||||
size_t total_size = num*size;
|
||||
void* ptr = malloc(total_size);
|
||||
|
||||
if (ptr != NULL)
|
||||
{
|
||||
uint8_t* byte_ptr = (uint8_t*)ptr;
|
||||
for (size_t i=0; i<total_size; i++)
|
||||
{
|
||||
byte_ptr[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
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);
|
||||
void* calloc(size_t num, size_t size);
|
||||
|
||||
#endif
|
||||
@@ -1,178 +0,0 @@
|
||||
// Basic shell and commands kernel module
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include "system.h"
|
||||
#include "../libc/stdio.h"
|
||||
#include "../libc/string.h"
|
||||
#include "../utils/utils.h"
|
||||
#include "../libc/crypto.h"
|
||||
#include <stdint.h>
|
||||
#include "../drivers/rtc.h"
|
||||
#include "kmain.h"
|
||||
|
||||
#define BUFFER_SIZE 256
|
||||
#define MAX_COMMANDS 64
|
||||
#define MAX_ARGS 64
|
||||
|
||||
// Splash screen: esthetic stuff.
|
||||
char* motd[] =
|
||||
{
|
||||
"I should be root, really.",
|
||||
"Not watching you!",
|
||||
"Now in 2D!",
|
||||
"Supercalifragilisticexpialidocious!",
|
||||
"Tylko jedno w glowie mam!",
|
||||
"Greetings, magic poppy!",
|
||||
"I'm stuck in this kernel's shell, get me out!",
|
||||
"And now, solve that equation!",
|
||||
"Powered by TCC Incorporated.",
|
||||
"Compiled at 69, CoquaineBaule Ave.",
|
||||
"Shouldn't we be, uh, doing something?",
|
||||
"We are the florists, we pick the plants!",
|
||||
"Lalalalala, I pick the plants!",
|
||||
"Woah, we're half-way there...",
|
||||
"The CROU will never die!",
|
||||
"Technoblade never dies!",
|
||||
"Hi. My name is Guitar.",
|
||||
"space station No. 9",
|
||||
"May the orange juice be with you !",
|
||||
"Bloody grated carrots!",
|
||||
"Good night, kiddos...",
|
||||
"I like trains",
|
||||
"I fear planes",
|
||||
"Bruteforce.exe",
|
||||
"Ohayogozaimasu!",
|
||||
};
|
||||
|
||||
int motd_size = sizeof(motd)/sizeof(motd[0]);
|
||||
|
||||
bool do_splash = true;
|
||||
|
||||
void splash()
|
||||
{
|
||||
int random = randint(time_seed());
|
||||
char* motd_pick = motd[random%motd_size];
|
||||
cowsay(motd_pick, red, black);
|
||||
puts(" ");
|
||||
colorputs("blankOS", black, white);
|
||||
puts(" ");
|
||||
colorputs(BLANK_VERSION, red, black);
|
||||
puts("\n");
|
||||
|
||||
|
||||
puts(" Time: ");
|
||||
rtc_time_t time;
|
||||
rtc_read_time(&time);
|
||||
print_time(&time);
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
typedef void (*command_func_t)(int argc, char *argv[]);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char* name;
|
||||
command_func_t function;
|
||||
} shell_command_t;
|
||||
|
||||
shell_command_t shell_commands[MAX_COMMANDS];
|
||||
int command_count = 0;
|
||||
|
||||
void register_command(const char* name, command_func_t function)
|
||||
{
|
||||
if (command_count < MAX_COMMANDS)
|
||||
{
|
||||
shell_commands[command_count].name = name;
|
||||
shell_commands[command_count].function = function;
|
||||
command_count++;
|
||||
}
|
||||
}
|
||||
|
||||
command_func_t find_command(const char* name)
|
||||
{
|
||||
for (int i=0; i < command_count; i++)
|
||||
{
|
||||
if (strcmp(name, shell_commands[i].name) == 0)
|
||||
return shell_commands[i].function;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_input(char* input, char* argv[], int max_args)
|
||||
{
|
||||
int argc = 0;
|
||||
char* token = strtok(input, " ");
|
||||
while (token != NULL && argc < max_args - 1)
|
||||
{
|
||||
argv[argc++] = token;
|
||||
token = strtok(NULL, " ");
|
||||
}
|
||||
argv[argc] = NULL;
|
||||
return argc;
|
||||
}
|
||||
|
||||
void shell_install()
|
||||
{
|
||||
if (do_splash == true)
|
||||
{
|
||||
do_splash = false;
|
||||
splash();
|
||||
}
|
||||
|
||||
register_command("help", program_help);
|
||||
register_command("panic", program_panic);
|
||||
register_command("words", program_words);
|
||||
register_command("primes", program_primes);
|
||||
register_command("rainbow", program_rainbow);
|
||||
register_command("clear", program_clear);
|
||||
register_command("math", program_math);
|
||||
register_command("bf", program_bf);
|
||||
register_command("uptime", program_uptime);
|
||||
register_command("echo", program_echo);
|
||||
register_command("sysinfo", program_sysinfo);
|
||||
register_command("conway", program_conway);
|
||||
register_command("rot13", program_rot13);
|
||||
register_command("morse", program_morse);
|
||||
register_command("cowsay", program_cowsay);
|
||||
register_command("time", program_time);
|
||||
register_command("read", program_read);
|
||||
register_command("reboot", program_reboot);
|
||||
register_command("pi", program_pi);
|
||||
register_command("ls", program_ls);
|
||||
register_command("cat", program_cat);
|
||||
register_command("bmp", program_bmp);
|
||||
register_command("lspci", program_lspci);
|
||||
register_command("naval", program_navalbattle);
|
||||
register_command("snake", program_snake);
|
||||
register_command("exec", program_exec);
|
||||
register_command("uhex", program_uhex);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
char input_buffer[BUFFER_SIZE];
|
||||
char* argv[MAX_ARGS];
|
||||
|
||||
// Prompt
|
||||
colorputs("root", blue, black);
|
||||
colorputs("@", white, black);
|
||||
colorputs("blankos", green, black);
|
||||
colorputs("~$ ", white, black);
|
||||
|
||||
get_input(input_buffer, BUFFER_SIZE);
|
||||
puts("\n");
|
||||
|
||||
int argc = parse_input(input_buffer, argv, MAX_ARGS);
|
||||
|
||||
if (argc == 0) continue;
|
||||
|
||||
command_func_t command = find_command(argv[0]);
|
||||
if (command)
|
||||
{
|
||||
command(argc, argv);
|
||||
} else {
|
||||
printf("Unknown command %s\n", argv[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
// System calls
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include "../libc/stdio.h"
|
||||
|
||||
void handle_syscall(int syscall_number)
|
||||
{
|
||||
switch(syscall_number)
|
||||
{
|
||||
case 1:
|
||||
puts("Here's the syscall 1\n");
|
||||
break;
|
||||
default:
|
||||
printf("[error] Invalid syscall number '%d'!\n", syscall_number);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void syscall_handler()
|
||||
{
|
||||
int syscall_number;
|
||||
void* arg;
|
||||
// mov eax, syscall_number
|
||||
// mov ebx, arg
|
||||
asm volatile("mov %%eax, %0" : "=r"(syscall_number));
|
||||
asm volatile("mov %%ebx, %0" : "=r"(arg));
|
||||
|
||||
printf("[syscall] syscall_number=%d, arg=%p\n", syscall_number, arg);
|
||||
|
||||
handle_syscall(syscall_number);
|
||||
}
|
||||
@@ -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,10 +0,0 @@
|
||||
void user_syscall(int syscall_no) {
|
||||
asm volatile ("mov %0, %%eax" : : "r"(syscall_no));
|
||||
asm volatile ("int $0x80");
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
user_syscall(1);
|
||||
return;
|
||||
}
|
||||
@@ -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]);
|
||||
}
|
||||
245
src/utils/math.c
245
src/utils/math.c
@@ -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);
|
||||
}
|
||||
176
src/utils/misc.c
176
src/utils/misc.c
@@ -1,176 +0,0 @@
|
||||
// Miscellaneous small programs
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include "../libc/stdio.h"
|
||||
#include "../kernel/system.h"
|
||||
#include "../libc/string.h"
|
||||
#include "../drivers/framebuffer.h"
|
||||
#include "../drivers/ata.h"
|
||||
#include "../drivers/rtc.h"
|
||||
#include "../kernel/io.h"
|
||||
#include "../drivers/pci.h"
|
||||
#include "../kernel/initrd.h"
|
||||
#include "../kernel/kmain.h"
|
||||
|
||||
// Print a rainbow colorful text for testing
|
||||
|
||||
#define BUF_SIZE 256
|
||||
#define COLORS 20
|
||||
|
||||
void program_rainbow(int argc, char* argv[])
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
printf("Usage: %s <string>\n", argv[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
char input_buffer[BUF_SIZE] = {0};
|
||||
for (int i=1; i<argc; i++)
|
||||
{
|
||||
strcat(input_buffer, argv[i]);
|
||||
if (i<argc-1)
|
||||
{
|
||||
strcat(input_buffer, " ");
|
||||
}
|
||||
}
|
||||
|
||||
enum Colors colors[] = {
|
||||
white, black, red, green, blue, yellow,
|
||||
cyan, magenta, orange, purple, brown,
|
||||
gray, pink, lime, navy, teal, maroon,
|
||||
olive, silver, gold, indigo, violet,
|
||||
coral, turquoise, salmon, chocolate,
|
||||
khaki, lavender, beige
|
||||
};
|
||||
int colors_count = sizeof(colors)/sizeof(colors[0]);
|
||||
|
||||
for (int i=0; i<colors_count-1; i++)
|
||||
{
|
||||
colorputs(input_buffer, colors[i], colors[i+1]);
|
||||
puts("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the terminal
|
||||
|
||||
#define ROWS 25
|
||||
|
||||
void program_clear()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
// Get uptime in ticks
|
||||
|
||||
void program_uptime()
|
||||
{
|
||||
int ticks = uptime();
|
||||
double seconds = ticks/18.2065; // PIT channel 0 freq
|
||||
printf("%d ticks\t%f seconds\n", ticks, seconds);
|
||||
}
|
||||
|
||||
// Get help
|
||||
|
||||
void program_help()
|
||||
{
|
||||
printf("help\tpanic\twords\tprimes\trainbow\tclear\nmath\tbf\t uptime echo\t sysinfo\tconway\nrot13 morse\tcowsay time\t read\t reboot\npi\t ls\t cat\t bmp\t lspci\t naval\nsnake exec\t uhex\n");
|
||||
}
|
||||
|
||||
// Panic
|
||||
|
||||
void program_panic()
|
||||
{
|
||||
asm volatile("int $0x13");
|
||||
}
|
||||
|
||||
// Output input
|
||||
|
||||
void program_echo(int argc, char* argv[])
|
||||
{
|
||||
for (int i=1; i<argc; i++)
|
||||
{
|
||||
puts(argv[i]);
|
||||
if (i < argc-1) {
|
||||
putc(' ');
|
||||
}
|
||||
}
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
// Get current RTC time
|
||||
|
||||
void program_time()
|
||||
{
|
||||
rtc_time_t time;
|
||||
rtc_read_time(&time);
|
||||
puts("Current RTC time: ");
|
||||
print_time(&time);
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
// Read a sector
|
||||
|
||||
void program_read(int argc, char* argv[])
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
printf("Usage: %s <sector>\n", argv[0]);
|
||||
} else if (argc == 2)
|
||||
{
|
||||
uint8_t buffer[512];
|
||||
ata_read_sector(atoi(argv[1]), buffer);
|
||||
|
||||
for (int i=0; i<512; i++)
|
||||
{
|
||||
if (i%50==0) puts("\n"); // hardcoded = bad
|
||||
printf("%02x ", buffer[i]);
|
||||
}
|
||||
puts("\n");
|
||||
} else
|
||||
{
|
||||
puts("Invalid argument number\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Reboots the machine (might just shutdown) (or do nothing if youre lucky)
|
||||
|
||||
void program_reboot()
|
||||
{
|
||||
puts("Rebooting...\n");
|
||||
|
||||
while(inb(0x64) & 0x02);
|
||||
outb(0x64, 0xFE);
|
||||
|
||||
while (1) asm volatile("hlt");
|
||||
}
|
||||
|
||||
// List PCI buses and devices
|
||||
|
||||
void program_lspci()
|
||||
{
|
||||
scan_pci_bus();
|
||||
}
|
||||
|
||||
// Executes binary file
|
||||
|
||||
void program_exec(int argc, char* argv[])
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
puts("Usage: exec <binary>\n");
|
||||
return;
|
||||
}
|
||||
void* binary_file = load_file_from_initrd((uint8_t*)initrd_addr, argv[1]);
|
||||
|
||||
if (binary_file == NULL)
|
||||
{
|
||||
printf("[exec] Failed to load program '%s'.\n", argv[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
void (*program_entry)() = (void (*)())binary_file;
|
||||
program_entry();
|
||||
}
|
||||
@@ -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,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,82 +0,0 @@
|
||||
// uhex (microhex) port for BlankOS; read-only version
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
// This version is the port of a hex viewer which already was not great,
|
||||
// and now by being here it is even worse because it is RO and will have
|
||||
// hardcoded stuff in it (no ioctl, STDOUT, or other stuff here...)
|
||||
|
||||
#define BYTES 1024
|
||||
#define round(x) (int)(x < 0 ? (x -0.5) : x + 0.5)
|
||||
|
||||
#include "../libc/stdio.h"
|
||||
#include "../kernel/kmain.h"
|
||||
#include "../kernel/initrd.h"
|
||||
#include "../libc/string.h"
|
||||
#include "../kernel/kheap.h"
|
||||
|
||||
int isprint(int c)
|
||||
{
|
||||
return (c >= 32 && c <= 126);
|
||||
}
|
||||
|
||||
void print_hex(unsigned char* buf, int byteno, int pos, int BYTES_PER_LINE)
|
||||
{
|
||||
for (int i=0; i<byteno; i++)
|
||||
{
|
||||
if (i%BYTES_PER_LINE == 0)
|
||||
{
|
||||
if (i != 0)
|
||||
{
|
||||
printf(" ");
|
||||
for (int j=i-BYTES_PER_LINE; j<i; j++)
|
||||
{
|
||||
if (isprint(buf[j])) colorprintf(salmon, black, "%c", buf[j]);
|
||||
else printf(".");
|
||||
}
|
||||
}
|
||||
puts("\n");
|
||||
|
||||
if (pos == 0) printf("%06d: ", i);
|
||||
else printf("%06d: ", pos);
|
||||
}
|
||||
printf("%2x ", buf[i]);
|
||||
}
|
||||
|
||||
int padding = BYTES_PER_LINE - (byteno % BYTES_PER_LINE);
|
||||
if (padding < BYTES_PER_LINE)
|
||||
{
|
||||
for (int i=0; i<padding; i++) printf(" ");
|
||||
printf(" ");
|
||||
}
|
||||
int start = byteno-(byteno%BYTES_PER_LINE);
|
||||
for (int j=start; j<byteno; j++)
|
||||
{
|
||||
if (isprint(buf[j])) {
|
||||
colorprintf(salmon, black, "%c", buf[j]);
|
||||
} else {
|
||||
printf(".");
|
||||
}
|
||||
}
|
||||
puts("\n");
|
||||
}
|
||||
|
||||
void program_uhex(int argc, char* argv[])
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
puts("Usage: uhex <file>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int BYTES_PER_LINE = 20;
|
||||
|
||||
//unsigned char buf[BYTES]; // malloc with file_size next?
|
||||
uint32_t file_size = tar_get_file_size((uint8_t*)initrd_addr, argv[1]);
|
||||
unsigned char* buf = (unsigned char*)malloc(file_size);
|
||||
tar_file_to_buffer((uint8_t*)initrd_addr, argv[1], (char*)buf);
|
||||
print_hex(buf, file_size, 0, BYTES_PER_LINE);
|
||||
|
||||
free(buf);
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
// Global program entry points header
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
void program_words();
|
||||
void program_primes();
|
||||
void program_math();
|
||||
void program_bf();
|
||||
void program_sysinfo();
|
||||
|
||||
void get_cpuid();
|
||||
void get_meminfo(unsigned int multiboot_info_address); // to be fixed: cannot get full memory map (sysinfo -v)
|
||||
void program_cowsay();
|
||||
void cowsay(); // Splash screen
|
||||
void program_pi();
|
||||
|
||||
// Ciphers
|
||||
void program_rot13();
|
||||
void program_morse();
|
||||
|
||||
// Misc
|
||||
void program_rainbow();
|
||||
void program_clear();
|
||||
void program_uptime();
|
||||
void program_panic();
|
||||
void program_help();
|
||||
void program_echo();
|
||||
void program_time();
|
||||
void program_read();
|
||||
void program_reboot();
|
||||
|
||||
// Filesystem (initrd)
|
||||
void program_ls();
|
||||
void program_cat();
|
||||
|
||||
void program_bmp();
|
||||
void program_lspci();
|
||||
|
||||
// Games
|
||||
void program_navalbattle();
|
||||
void program_conway();
|
||||
void program_snake();
|
||||
|
||||
// Binaries loading and execution
|
||||
void program_exec();
|
||||
|
||||
void program_uhex();
|
||||
|
||||
#endif
|
||||
@@ -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