Whoops, I think I just accidentally (no) foramtted the entire project with clang

This commit is contained in:
Андреев Григорий 2026-04-07 23:07:51 +03:00
parent d76095ca85
commit 1794df45f4
50 changed files with 1953 additions and 1324 deletions

6
.clang-format Normal file
View File

@ -0,0 +1,6 @@
BasedOnStyle: LLVM
IndentWidth: 4
ContinuationIndentWidth: 4
TabWidth: 4
UseTab: Never
BreakBeforeBraces: Attach

View File

@ -5,106 +5,96 @@
// bootmain() loads an ELF kernel image from the disk starting at // bootmain() loads an ELF kernel image from the disk starting at
// sector 3 and then jumps to the kernel entry routine. // sector 3 and then jumps to the kernel entry routine.
#include "elf.h"
#include "drivers/port.h" #include "drivers/port.h"
#include "elf.h"
#define SECTSIZE 512 #define SECTSIZE 512
typedef unsigned char uchar; typedef unsigned char uchar;
typedef unsigned int uint; typedef unsigned int uint;
void readseg(uchar*, uint, uint); void readseg(uchar *, uint, uint);
inline void stosb(uchar* addr, uchar byte, uint count) { inline void stosb(uchar *addr, uchar byte, uint count) {
asm volatile("cld; rep stosb" : "+D"(addr), "+a"(byte) : "c"(count) : "cc"); asm volatile("cld; rep stosb" : "+D"(addr), "+a"(byte) : "c"(count) : "cc");
} }
void void bootmain(void) {
bootmain(void) Elf32_Ehdr *elf;
{ Elf32_Phdr *ph, *eph;
Elf32_Ehdr *elf; void (*entry)(void);
Elf32_Phdr *ph, *eph; uchar *pa;
void (*entry)(void);
uchar* pa;
elf = (Elf32_Ehdr*)0x30000; // scratch space elf = (Elf32_Ehdr *)0x30000; // scratch space
// Read 1st page off disk // Read 1st page off disk
readseg((uchar*)elf, 4096, 0); readseg((uchar *)elf, 4096, 0);
// Is this an ELF executable? // Is this an ELF executable?
if(elf->magic != ELF_MAGIC) if (elf->magic != ELF_MAGIC)
return; // let bootasm.S handle error return; // let bootasm.S handle error
// Load each program segment (ignores ph flags). // Load each program segment (ignores ph flags).
ph = (Elf32_Phdr*)((uchar*)elf + elf->e_phoff); ph = (Elf32_Phdr *)((uchar *)elf + elf->e_phoff);
eph = ph + elf->e_phnum; eph = ph + elf->e_phnum;
for(; ph < eph; ph++) { for (; ph < eph; ph++) {
pa = (uchar*)(ph->p_paddr & 0x0fffffff); pa = (uchar *)(ph->p_paddr & 0x0fffffff);
readseg(pa, ph->p_filesz, ph->p_offset); readseg(pa, ph->p_filesz, ph->p_offset);
if(ph->p_memsz > ph->p_filesz) if (ph->p_memsz > ph->p_filesz)
stosb(pa + ph->p_filesz, 0, ph->p_memsz - ph->p_filesz); stosb(pa + ph->p_filesz, 0, ph->p_memsz - ph->p_filesz);
} }
// Call the entry point from the ELF header. // Call the entry point from the ELF header.
// Does not return! // Does not return!
entry = (void(*)(void))(elf->e_entry & 0x0fffffff); entry = (void (*)(void))(elf->e_entry & 0x0fffffff);
entry(); entry();
} }
void void waitdisk(void) {
waitdisk(void) // Wait for disk ready.
{ while ((port_byte_in(0x1F7) & 0xC0) != 0x40)
// Wait for disk ready. ;
while((port_byte_in(0x1F7) & 0xC0) != 0x40)
;
} }
static inline void static inline void insl(int port, void *addr, int cnt) {
insl(int port, void *addr, int cnt) asm volatile("cld; rep insl"
{ : "=D"(addr), "=c"(cnt)
asm volatile("cld; rep insl" : : "d"(port), "0"(addr), "1"(cnt)
"=D" (addr), "=c" (cnt) : : "memory", "cc");
"d" (port), "0" (addr), "1" (cnt) :
"memory", "cc");
} }
// Read a single sector at offset into dst. // Read a single sector at offset into dst.
void void readsect(void *dst, uint offset) {
readsect(void *dst, uint offset) // Issue command.
{ waitdisk();
// Issue command. port_byte_out(0x1F2, 1); // count = 1
waitdisk(); port_byte_out(0x1F3, offset);
port_byte_out(0x1F2, 1); // count = 1 port_byte_out(0x1F4, offset >> 8);
port_byte_out(0x1F3, offset); port_byte_out(0x1F5, offset >> 16);
port_byte_out(0x1F4, offset >> 8); port_byte_out(0x1F6, (offset >> 24) | 0xE0);
port_byte_out(0x1F5, offset >> 16); port_byte_out(0x1F7, 0x20); // cmd 0x20 - read sectors
port_byte_out(0x1F6, (offset >> 24) | 0xE0);
port_byte_out(0x1F7, 0x20); // cmd 0x20 - read sectors
// Read data. // Read data.
waitdisk(); waitdisk();
insl(0x1F0, dst, SECTSIZE/4); insl(0x1F0, dst, SECTSIZE / 4);
} }
// Read 'count' bytes at 'offset' from kernel into physical address 'pa'. // Read 'count' bytes at 'offset' from kernel into physical address 'pa'.
// Might copy more than asked. // Might copy more than asked.
void void readseg(uchar *pa, uint count, uint offset) {
readseg(uchar* pa, uint count, uint offset) uchar *epa;
{
uchar* epa;
epa = pa + count; epa = pa + count;
// Round down to sector boundary. // Round down to sector boundary.
pa -= offset % SECTSIZE; pa -= offset % SECTSIZE;
// Translate from bytes to sectors; kernel starts at sector 3. // Translate from bytes to sectors; kernel starts at sector 3.
offset = (offset / SECTSIZE) + 2; offset = (offset / SECTSIZE) + 2;
// If this is too slow, we could read lots of sectors at a time. // If this is too slow, we could read lots of sectors at a time.
// We'd write more to memory than asked, but it doesn't matter -- // We'd write more to memory than asked, but it doesn't matter --
// we load in increasing order. // we load in increasing order.
for(; pa < epa; pa += SECTSIZE, offset++) for (; pa < epa; pa += SECTSIZE, offset++)
readsect(pa, offset); readsect(pa, offset);
} }

View File

@ -1,15 +1,15 @@
#include "console.h" #include "console.h"
#include "drivers/vga.h"
#include "drivers/uart.h" #include "drivers/uart.h"
#include "drivers/vga.h"
void printk(const char* msg) { void printk(const char *msg) {
vga_print_string(msg); vga_print_string(msg);
for (; *msg; ++msg) { for (; *msg; ++msg) {
uartputc(*msg); uartputc(*msg);
} }
} }
void panic(const char* msg) { void panic(const char *msg) {
printk("\nKernel panic: "); printk("\nKernel panic: ");
printk(msg); printk(msg);
asm("cli"); asm("cli");

View File

@ -1,6 +1,10 @@
#pragma once #pragma once
void printk(const char* msg); void printk(const char *msg);
_Noreturn void panic(const char* msg); _Noreturn void panic(const char *msg);
#define check(expr) if (!(expr)) { panic("Assertion failed at " __FILE__ " : " " : " #expr "\n"); } #define check(expr) \
if (!(expr)) { \
panic("Assertion failed at " __FILE__ " : " \
" : " #expr "\n"); \
}

View File

@ -1,48 +1,68 @@
#include "gdt.h" #include "gdt.h"
#include "x86.h"
#include "memlayout.h"
#include "../lib/string.h" #include "../lib/string.h"
#include "kernel/mem.h" #include "kernel/mem.h"
#include "memlayout.h"
#include "x86.h"
#include <stdint.h> #include <stdint.h>
struct seg_desc_t { struct seg_desc_t {
uint16_t lim_15_0; // Low bits of segment limit uint16_t lim_15_0; // Low bits of segment limit
uint16_t base_15_0; // Low bits of segment base address uint16_t base_15_0; // Low bits of segment base address
uint8_t base_23_16; // Middle bits of segment base address uint8_t base_23_16; // Middle bits of segment base address
uint8_t type : 4; // Segment type (see STA_ constants) uint8_t type : 4; // Segment type (see STA_ constants)
uint8_t s : 1; // 0 = system, 1 = application uint8_t s : 1; // 0 = system, 1 = application
uint8_t dpl : 2; // Descriptor Privilege Level uint8_t dpl : 2; // Descriptor Privilege Level
uint8_t p : 1; // Present uint8_t p : 1; // Present
uint8_t lim_19_16 : 4; // High bits of segment limit uint8_t lim_19_16 : 4; // High bits of segment limit
uint8_t avl : 1; // Unused (available for software use) uint8_t avl : 1; // Unused (available for software use)
uint8_t rsv1 : 1; // Reserved uint8_t rsv1 : 1; // Reserved
uint8_t db : 1; // 0 = 16-bit segment, 1 = 32-bit segment uint8_t db : 1; // 0 = 16-bit segment, 1 = 32-bit segment
uint8_t g : 1; // Granularity: limit scaled by 4K when set uint8_t g : 1; // Granularity: limit scaled by 4K when set
uint8_t base_31_24; // High bits of segment base address uint8_t base_31_24; // High bits of segment base address
} __attribute__((packed)); } __attribute__((packed));
#define SEG(type, base, lim, dpl) (struct seg_desc_t) \ #define SEG(type, base, lim, dpl) \
{ ((lim) >> 12) & 0xffff, (uint)(base) & 0xffff, \ (struct seg_desc_t){((lim) >> 12) & 0xffff, \
((uint)(base) >> 16) & 0xff, type, 1, dpl, 1, \ (uint)(base) & 0xffff, \
(uint)(lim) >> 28, 0, 0, 1, 1, (uint)(base) >> 24 } ((uint)(base) >> 16) & 0xff, \
#define SEG16(type, base, lim, dpl) (struct seg_desc_t) \ type, \
{ (lim) & 0xffff, (uint)(base) & 0xffff, \ 1, \
((uint)(base) >> 16) & 0xff, type, 1, dpl, 1, \ dpl, \
(uint)(lim) >> 16, 0, 0, 1, 0, (uint)(base) >> 24 } 1, \
(uint)(lim) >> 28, \
0, \
0, \
1, \
1, \
(uint)(base) >> 24}
#define SEG16(type, base, lim, dpl) \
(struct seg_desc_t){(lim) & 0xffff, \
(uint)(base) & 0xffff, \
((uint)(base) >> 16) & 0xff, \
type, \
1, \
dpl, \
1, \
(uint)(lim) >> 16, \
0, \
0, \
1, \
0, \
(uint)(base) >> 24}
struct seg_desc_t seg_desc[6]; struct seg_desc_t seg_desc[6];
void init_seg_desc() { void init_seg_desc() {
seg_desc[SEG_KCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, 0); seg_desc[SEG_KCODE] = SEG(STA_X | STA_R, 0, 0xffffffff, 0);
seg_desc[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0); seg_desc[SEG_KDATA] = SEG(STA_W, 0, 0xffffffff, 0);
seg_desc[SEG_UCODE] = SEG(STA_X|STA_R, 0, 0xffffffff, DPL_USER); seg_desc[SEG_UCODE] = SEG(STA_X | STA_R, 0, 0xffffffff, DPL_USER);
seg_desc[SEG_UDATA] = SEG(STA_W, 0, 0xffffffff, DPL_USER); seg_desc[SEG_UDATA] = SEG(STA_W, 0, 0xffffffff, DPL_USER);
} }
struct gdt_desc_t { struct gdt_desc_t {
uint16_t size; uint16_t size;
void* ptr; void *ptr;
} __attribute__((packed)); } __attribute__((packed));
void load_gdt() { void load_gdt() {
@ -51,20 +71,20 @@ void load_gdt() {
struct gdt_desc_t gdt_desc; struct gdt_desc_t gdt_desc;
gdt_desc.size = sizeof(seg_desc) - 1; gdt_desc.size = sizeof(seg_desc) - 1;
gdt_desc.ptr = seg_desc; gdt_desc.ptr = seg_desc;
asm("lgdt %0": : "m"(gdt_desc)); asm("lgdt %0" : : "m"(gdt_desc));
} }
void switchuvm(struct taskstate *tss, void* esp, pde_t *pgdir) { void switchuvm(struct taskstate *tss, void *esp, pde_t *pgdir) {
memset(tss, 0, sizeof(*tss)); memset(tss, 0, sizeof(*tss));
seg_desc[SEG_TSS] = SEG16(STS_T32A, tss, sizeof(*tss)-1, 0); seg_desc[SEG_TSS] = SEG16(STS_T32A, tss, sizeof(*tss) - 1, 0);
seg_desc[SEG_TSS].s = 0; seg_desc[SEG_TSS].s = 0;
tss->ss0 = SEG_KDATA << 3; tss->ss0 = SEG_KDATA << 3;
tss->esp0 = (uint)esp; tss->esp0 = (uint)esp;
// setting IOPL=0 in eflags *and* iomb beyond the tss segment limit // setting IOPL=0 in eflags *and* iomb beyond the tss segment limit
// forbids I/O instructions (e.g., inb and outb) from user space // forbids I/O instructions (e.g., inb and outb) from user space
tss->iomb = (ushort) 0xFFFF; tss->iomb = (ushort)0xFFFF;
asm("ltr %0": : "r"((ushort)(SEG_TSS << 3))); asm("ltr %0" : : "r"((ushort)(SEG_TSS << 3)));
lcr3(V2P(pgdir)); lcr3(V2P(pgdir));
} }

View File

@ -1,32 +1,32 @@
#pragma once #pragma once
#define STA_X 0x8 // Executable segment #define STA_X 0x8 // Executable segment
#define STA_W 0x2 // Writeable (non-executable segments) #define STA_W 0x2 // Writeable (non-executable segments)
#define STA_R 0x2 // Readable (executable segments) #define STA_R 0x2 // Readable (executable segments)
// System segment type bits // System segment type bits
#define STS_T32A 0x9 // Available 32-bit TSS #define STS_T32A 0x9 // Available 32-bit TSS
#define STS_IG32 0xE // 32-bit Interrupt Gate #define STS_IG32 0xE // 32-bit Interrupt Gate
#define STS_TG32 0xF // 32-bit Trap Gate #define STS_TG32 0xF // 32-bit Trap Gate
#define DPL_USER 3 #define DPL_USER 3
#define FL_IF 0x00000200 #define FL_IF 0x00000200
#define SEG_KCODE 1 #define SEG_KCODE 1
#define SEG_KDATA 2 #define SEG_KDATA 2
#define SEG_UCODE 3 #define SEG_UCODE 3
#define SEG_UDATA 4 #define SEG_UDATA 4
#define SEG_TSS 5 #define SEG_TSS 5
#define SEG_ASM(type,base,lim) \ #define SEG_ASM(type, base, lim) \
.word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \ .word(((lim) >> 12) & 0xffff), ((base) & 0xffff); \
.byte (((base) >> 16) & 0xff), (0x90 | (type)), \ .byte(((base) >> 16) & 0xff), (0x90 | (type)), \
(0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff) (0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff)
#define USER_BASE 0x400000 // 4 MB #define USER_BASE 0x400000 // 4 MB
#define USER_STACK_BASE 0xf00000 // 15 MB #define USER_STACK_BASE 0xf00000 // 15 MB
#define KERN_STACK_BASE 0x90000 #define KERN_STACK_BASE 0x90000
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__
#include "kernel/mem.h" #include "kernel/mem.h"
@ -34,9 +34,9 @@ typedef unsigned uint;
typedef unsigned short ushort; typedef unsigned short ushort;
struct taskstate { struct taskstate {
uint link; // Old ts selector uint link; // Old ts selector
uint esp0; // Stack pointers and segment selectors uint esp0; // Stack pointers and segment selectors
ushort ss0; // after an increase in privilege level ushort ss0; // after an increase in privilege level
ushort padding1; ushort padding1;
uint *esp1; uint *esp1;
ushort ss1; ushort ss1;
@ -44,10 +44,10 @@ struct taskstate {
uint *esp2; uint *esp2;
ushort ss2; ushort ss2;
ushort padding3; ushort padding3;
void *cr3; // Page directory base void *cr3; // Page directory base
uint *eip; // Saved state from last task switch uint *eip; // Saved state from last task switch
uint eflags; uint eflags;
uint eax; // More saved state (registers) uint eax; // More saved state (registers)
uint ecx; uint ecx;
uint edx; uint edx;
uint ebx; uint ebx;
@ -55,7 +55,7 @@ struct taskstate {
uint *ebp; uint *ebp;
uint esi; uint esi;
uint edi; uint edi;
ushort es; // Even more saved state (segment selectors) ushort es; // Even more saved state (segment selectors)
ushort padding4; ushort padding4;
ushort cs; ushort cs;
ushort padding5; ushort padding5;
@ -69,10 +69,10 @@ struct taskstate {
ushort padding9; ushort padding9;
ushort ldt; ushort ldt;
ushort padding10; ushort padding10;
ushort t; // Trap on task switch ushort t; // Trap on task switch
ushort iomb; // I/O map base address ushort iomb; // I/O map base address
}; };
void load_gdt(); void load_gdt();
void switchuvm(struct taskstate *tss, void* esp, pde_t *pgdir); void switchuvm(struct taskstate *tss, void *esp, pde_t *pgdir);
#endif #endif

166
cpu/idt.c
View File

@ -1,13 +1,13 @@
#include "isr.h"
#include "gdt.h"
#include "memlayout.h"
#include "../syscall.h"
#include "../proc.h"
#include "../drivers/keyboard.h"
#include "../drivers/port.h"
#include "../drivers/pit.h"
#include "../drivers/vga.h"
#include "../console.h" #include "../console.h"
#include "../drivers/keyboard.h"
#include "../drivers/pit.h"
#include "../drivers/port.h"
#include "../drivers/vga.h"
#include "../proc.h"
#include "../syscall.h"
#include "gdt.h"
#include "isr.h"
#include "memlayout.h"
enum { enum {
IDT_HANDLERS = 256, IDT_HANDLERS = 256,
@ -17,10 +17,10 @@ typedef struct {
uint16_t low_offset; uint16_t low_offset;
uint16_t selector; uint16_t selector;
uint8_t always0; uint8_t always0;
uint8_t type: 4; uint8_t type : 4;
uint8_t s: 1; uint8_t s : 1;
uint8_t dpl: 2; uint8_t dpl : 2;
uint8_t p: 1; uint8_t p : 1;
uint16_t high_offset; uint16_t high_offset;
} __attribute__((packed)) idt_gate_t; } __attribute__((packed)) idt_gate_t;
@ -29,8 +29,8 @@ idt_gate_t idt[IDT_HANDLERS];
#define low_16(address) (uint16_t)((address) & 0xFFFF) #define low_16(address) (uint16_t)((address) & 0xFFFF)
#define high_16(address) (uint16_t)(((address) >> 16) & 0xFFFF) #define high_16(address) (uint16_t)(((address) >> 16) & 0xFFFF)
#define STS_IG32 0xE // 32-bit Interrupt Gate #define STS_IG32 0xE // 32-bit Interrupt Gate
#define STS_TG32 0xF // 32-bit Trap Gate #define STS_TG32 0xF // 32-bit Trap Gate
void set_idt_gate(int n, _Bool istrap, uint32_t handler, uint8_t dpl) { void set_idt_gate(int n, _Bool istrap, uint32_t handler, uint8_t dpl) {
idt[n].low_offset = low_16(handler); idt[n].low_offset = low_16(handler);
@ -56,7 +56,7 @@ void init_idt() {
set_idt_gate(T_SYSCALL, 1, default_handlers[T_SYSCALL], DPL_USER); set_idt_gate(T_SYSCALL, 1, default_handlers[T_SYSCALL], DPL_USER);
} }
const char * const exception_messages[] = { const char *const exception_messages[] = {
[0] = "Division By Zero", [0] = "Division By Zero",
[1] = "Debug", [1] = "Debug",
[2] = "Non Maskable Interrupt", [2] = "Non Maskable Interrupt",
@ -105,7 +105,7 @@ void trap(registers_t *r) {
} }
if (r->int_no < 32) { if (r->int_no < 32) {
const char* msg = "Reserved"; const char *msg = "Reserved";
if (r->int_no < ARRLEN(exception_messages)) { if (r->int_no < ARRLEN(exception_messages)) {
msg = exception_messages[r->int_no]; msg = exception_messages[r->int_no];
} }
@ -141,7 +141,7 @@ bool is_userspace_ptr_mapped(uint32_t ptr) {
return 0; return 0;
} }
pte_t *table = (pte_t*)P2V(PTE_ADDR(pde)); pte_t *table = (pte_t *)P2V(PTE_ADDR(pde));
pte_t pte = table[PTX(ptr)]; pte_t pte = table[PTX(ptr)];
if ((pte & (PTE_P | PTE_U)) != (PTE_P | PTE_U)) { if ((pte & (PTE_P | PTE_U)) != (PTE_P | PTE_U)) {
return 0; return 0;
@ -179,13 +179,13 @@ static bool is_userspace_cstr(uint32_t ptr) {
if (addr == 0 || !is_userspace_ptr_mapped(addr)) { if (addr == 0 || !is_userspace_ptr_mapped(addr)) {
return 0; return 0;
} }
if (*(const char*)addr == '\0') { if (*(const char *)addr == '\0') {
return (void*)ptr; return (void *)ptr;
} }
} }
} }
static _Noreturn void userspace_panic(const char* msg) { static _Noreturn void userspace_panic(const char *msg) {
if (!vga_is_text_mode()) { if (!vga_is_text_mode()) {
switch_to_text_mode(); switch_to_text_mode();
vga_clear_screen(); vga_clear_screen();
@ -198,7 +198,7 @@ static void handle_puts(uintptr_t s) {
if (!is_userspace_cstr(s)) { if (!is_userspace_cstr(s)) {
userspace_panic("SYS_puts panic: page fault\n"); userspace_panic("SYS_puts panic: page fault\n");
} }
printk((const char*)s); printk((const char *)s);
} }
static void require_text_mode_for_userspace_text_syscall() { static void require_text_mode_for_userspace_text_syscall() {
@ -219,8 +219,8 @@ static void handle_swap_frame(uintptr_t frame) {
userspace_panic("SYS_swap_frame panic: page fault\n"); userspace_panic("SYS_swap_frame panic: page fault\n");
} }
uint8_t *video = (uint8_t*)(KERNBASE + 0xA0000); uint8_t *video = (uint8_t *)(KERNBASE + 0xA0000);
uint8_t *user = (uint8_t*)frame; uint8_t *user = (uint8_t *)frame;
for (uint32_t i = 0; i < VGA_GRAPHICS_FRAME_SIZE; i++) { for (uint32_t i = 0; i < VGA_GRAPHICS_FRAME_SIZE; i++) {
video[i] = user[i]; video[i] = user[i];
} }
@ -253,61 +253,61 @@ static int handle_getc(void) {
return kbd_take_from_copy_buffer(); return kbd_take_from_copy_buffer();
} }
static void handle_syscall(registers_t* r) { static void handle_syscall(registers_t *r) {
switch (r->eax) { switch (r->eax) {
case SYS_exit: case SYS_exit:
if (r->ebx == 0) { if (r->ebx == 0) {
printk("* success\n"); printk("* success\n");
} else { } else {
printk("* failure\n"); printk("* failure\n");
} }
killproc(); killproc();
case SYS_greet: case SYS_greet:
require_text_mode_for_userspace_text_syscall(); require_text_mode_for_userspace_text_syscall();
printk("Hello world!\n"); printk("Hello world!\n");
r->eax = 0; r->eax = 0;
break; break;
case SYS_putc: case SYS_putc:
require_text_mode_for_userspace_text_syscall(); require_text_mode_for_userspace_text_syscall();
printk((const char[]){(char)r->ebx, '\0'}); printk((const char[]){(char)r->ebx, '\0'});
r->eax = 0; r->eax = 0;
break; break;
case SYS_puts: case SYS_puts:
require_text_mode_for_userspace_text_syscall(); require_text_mode_for_userspace_text_syscall();
handle_puts(r->ebx); handle_puts(r->ebx);
r->eax = 0; r->eax = 0;
break; break;
case SYS_switch_to_text: case SYS_switch_to_text:
switch_to_text_mode(); switch_to_text_mode();
r->eax = 0; r->eax = 0;
break; break;
case SYS_switch_to_graphics: case SYS_switch_to_graphics:
switch_to_graphics_mode(); switch_to_graphics_mode();
r->eax = 0; r->eax = 0;
break; break;
case SYS_swap_frame: case SYS_swap_frame:
handle_swap_frame(r->ebx); handle_swap_frame(r->ebx);
r->eax = 0; r->eax = 0;
break; break;
case SYS_time_ms: case SYS_time_ms:
r->eax = get_uptime_ms(); r->eax = get_uptime_ms();
break; break;
case SYS_halt: case SYS_halt:
asm volatile("hlt"); asm volatile("hlt");
r->eax = 0; r->eax = 0;
break; break;
case SYS_getc: case SYS_getc:
r->eax = handle_getc(); r->eax = handle_getc();
break; break;
case SYS_set_beep: case SYS_set_beep:
if (r->ebx > MAX_BEEP_FREQUENCY_HZ) { if (r->ebx > MAX_BEEP_FREQUENCY_HZ) {
userspace_panic("Userspace panic: beep frequency out of range\n"); userspace_panic("Userspace panic: beep frequency out of range\n");
} }
set_beep_frequency_hz(r->ebx); set_beep_frequency_hz(r->ebx);
r->eax = 0; r->eax = 0;
break; break;
default: default:
userspace_panic("Userspace panic: Unknown syscall\n"); userspace_panic("Userspace panic: Unknown syscall\n");
} }
} }
@ -335,7 +335,7 @@ static void init_pic() {
typedef struct { typedef struct {
uint16_t limit; uint16_t limit;
void* base; void *base;
} __attribute__((packed)) idt_register_t; } __attribute__((packed)) idt_register_t;
static idt_register_t idt_reg; static idt_register_t idt_reg;
@ -352,10 +352,6 @@ void load_idt() {
register_interrupt_handler(T_SYSCALL, handle_syscall); register_interrupt_handler(T_SYSCALL, handle_syscall);
} }
void cli() { void cli() { asm("cli"); }
asm("cli");
}
void sti() { void sti() { asm("sti"); }
asm("sti");
}

View File

@ -29,9 +29,11 @@ enum {
*/ */
typedef struct { typedef struct {
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; /* Pushed by pusha. */ uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; /* Pushed by pusha. */
uint32_t gs, fs, es, ds; /* Data segment selector */ uint32_t gs, fs, es, ds; /* Data segment selector */
uint32_t int_no, err_code; /* Interrupt number and error code (if applicable) */ uint32_t int_no,
uint32_t eip, cs, eflags, useresp, ss; /* Pushed by the processor automatically */ err_code; /* Interrupt number and error code (if applicable) */
uint32_t eip, cs, eflags, useresp,
ss; /* Pushed by the processor automatically */
} registers_t; } registers_t;
void isr_install(); void isr_install();

View File

@ -1,42 +1,42 @@
#pragma once #pragma once
#define KERNBASE 0x80000000 #define KERNBASE 0x80000000
#define PGSIZE 0x1000 #define PGSIZE 0x1000
#define PHYSTOP 0x8000000 // 128 Mib #define PHYSTOP 0x8000000 // 128 Mib
#define PGROUNDUP(sz) (((sz)+PGSIZE-1) & ~(PGSIZE-1)) #define PGROUNDUP(sz) (((sz) + PGSIZE - 1) & ~(PGSIZE - 1))
#define PGROUNDDOWN(a) (((a)) & ~((uintptr_t)(PGSIZE-1))) #define PGROUNDDOWN(a) (((a)) & ~((uintptr_t)(PGSIZE - 1)))
#define NPDENTRIES 1024 // # directory entries per page directory #define NPDENTRIES 1024 // # directory entries per page directory
#define NPTENTRIES 1024 // # PTEs per page table #define NPTENTRIES 1024 // # PTEs per page table
#define PTXSHIFT 12 // offset of PTX in a linear address #define PTXSHIFT 12 // offset of PTX in a linear address
#define PDXSHIFT 22 // offset of PDX in a linear address #define PDXSHIFT 22 // offset of PDX in a linear address
#define PXMASK 0x3FF #define PXMASK 0x3FF
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__
#include <stdint.h> #include <stdint.h>
#define V2P(a) (((uintptr_t) (a)) - KERNBASE) #define V2P(a) (((uintptr_t)(a)) - KERNBASE)
#define P2V(a) ((void *)(((uintptr_t) (a)) + KERNBASE)) #define P2V(a) ((void *)(((uintptr_t)(a)) + KERNBASE))
// page directory index // page directory index
#define PDX(va) (((uintptr_t)(va) >> PDXSHIFT) & PXMASK) #define PDX(va) (((uintptr_t)(va) >> PDXSHIFT) & PXMASK)
// page table index // page table index
#define PTX(va) (((uintptr_t)(va) >> PTXSHIFT) & PXMASK) #define PTX(va) (((uintptr_t)(va) >> PTXSHIFT) & PXMASK)
// Address in page table or page directory entry // Address in page table or page directory entry
#define PTE_ADDR(pte) ((uintptr_t)(pte) & ~0xFFF) #define PTE_ADDR(pte) ((uintptr_t)(pte) & ~0xFFF)
#endif #endif
// Page table/directory entry flags. // Page table/directory entry flags.
#define PTE_P 0x001 // Present #define PTE_P 0x001 // Present
#define PTE_W 0x002 // Writeable #define PTE_W 0x002 // Writeable
#define PTE_U 0x004 // User #define PTE_U 0x004 // User
#define PTE_PWT 0x008 // Write-Through #define PTE_PWT 0x008 // Write-Through
#define PTE_PCD 0x010 // Cache-Disable #define PTE_PCD 0x010 // Cache-Disable
#define PTE_A 0x020 // Accessed #define PTE_A 0x020 // Accessed
#define PTE_D 0x040 // Dirty #define PTE_D 0x040 // Dirty
// entries of page tables don't have PS // entries of page tables don't have PS
#define PDE_PS 0x080 // Page Size #define PDE_PS 0x080 // Page Size

View File

@ -1,20 +1,20 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
static inline void static inline void stosl(void *addr, int data, int cnt) {
stosl(void *addr, int data, int cnt) asm volatile("cld; rep stosl"
{ :
asm volatile("cld; rep stosl" : : "D"(addr), "c"(cnt), "a"(data) : "memory"); : "D"(addr), "c"(cnt), "a"(data)
: "memory");
} }
static inline void static inline void stosb(void *addr, unsigned char data, int cnt) {
stosb(void *addr, unsigned char data, int cnt) asm volatile("cld; rep stosb"
{ :
asm volatile("cld; rep stosb" : : "D"(addr), "c"(cnt), "a"(data) : "memory"); : "D"(addr), "c"(cnt), "a"(data)
: "memory");
} }
static inline void static inline void lcr3(uint32_t val) {
lcr3(uint32_t val) asm volatile("mov %0,%%cr3" : : "r"(val));
{
asm volatile("mov %0,%%cr3" : : "r" (val));
} }

View File

@ -10,7 +10,7 @@
#define STATUS_BSY 0x80 #define STATUS_BSY 0x80
#define STATUS_RDY 0x40 #define STATUS_RDY 0x40
#define STATUS_DRQ 0x08 #define STATUS_DRQ 0x08
#define STATUS_DF 0x20 #define STATUS_DF 0x20
#define STATUS_ERR 0x01 #define STATUS_ERR 0x01
// This is really specific to our OS now, assuming ATA bus 0 master // This is really specific to our OS now, assuming ATA bus 0 master
@ -19,8 +19,8 @@
static void ATA_wait_BSY(); static void ATA_wait_BSY();
static void ATA_wait_RDY(); static void ATA_wait_RDY();
void read_sectors_ATA_PIO(void* target_address, uint32_t LBA, uint8_t sector_count) void read_sectors_ATA_PIO(void *target_address, uint32_t LBA,
{ uint8_t sector_count) {
ATA_wait_BSY(); ATA_wait_BSY();
port_byte_out(0x1F6, 0xE0 | ((LBA >> 24) & 0xF)); port_byte_out(0x1F6, 0xE0 | ((LBA >> 24) & 0xF));
port_byte_out(0x1F2, sector_count); port_byte_out(0x1F2, sector_count);
@ -31,8 +31,7 @@ void read_sectors_ATA_PIO(void* target_address, uint32_t LBA, uint8_t sector_cou
uint16_t *target = (uint16_t *)target_address; uint16_t *target = (uint16_t *)target_address;
for (int j = 0; j < sector_count; j++) for (int j = 0; j < sector_count; j++) {
{
ATA_wait_BSY(); ATA_wait_BSY();
ATA_wait_RDY(); ATA_wait_RDY();
for (int i = 0; i < 256; i++) for (int i = 0; i < 256; i++)
@ -41,8 +40,8 @@ void read_sectors_ATA_PIO(void* target_address, uint32_t LBA, uint8_t sector_cou
} }
} }
void write_sectors_ATA_PIO(uint32_t LBA, uint8_t sector_count, uint32_t *bytes) void write_sectors_ATA_PIO(uint32_t LBA, uint8_t sector_count,
{ uint32_t *bytes) {
ATA_wait_BSY(); ATA_wait_BSY();
port_byte_out(0x1F6, 0xE0 | ((LBA >> 24) & 0xF)); port_byte_out(0x1F6, 0xE0 | ((LBA >> 24) & 0xF));
port_byte_out(0x1F2, sector_count); port_byte_out(0x1F2, sector_count);
@ -51,12 +50,10 @@ void write_sectors_ATA_PIO(uint32_t LBA, uint8_t sector_count, uint32_t *bytes)
port_byte_out(0x1F5, (uint8_t)(LBA >> 16)); port_byte_out(0x1F5, (uint8_t)(LBA >> 16));
port_byte_out(0x1F7, 0x30); // Send the write command port_byte_out(0x1F7, 0x30); // Send the write command
for (int j = 0; j < sector_count; j++) for (int j = 0; j < sector_count; j++) {
{
ATA_wait_BSY(); ATA_wait_BSY();
ATA_wait_RDY(); ATA_wait_RDY();
for (int i = 0; i < 256; i++) for (int i = 0; i < 256; i++) {
{
port_long_out(0x1F0, bytes[i]); port_long_out(0x1F0, bytes[i]);
} }
} }

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include <stdint.h> #include <stdint.h>
void read_sectors_ATA_PIO(void* target_address, uint32_t LBA, uint8_t sector_count); void read_sectors_ATA_PIO(void *target_address, uint32_t LBA,
uint8_t sector_count);

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,9 @@
#include "keyboard.h" #include "keyboard.h"
#include "console.h"
#include "cpu/isr.h" #include "cpu/isr.h"
#include "cpu/memlayout.h" #include "cpu/memlayout.h"
#include "console.h"
#include "port.h"
#include "kernel/mem.h" #include "kernel/mem.h"
#include "port.h"
keyboard_interrupt_shared_t kbd_state_shrd; keyboard_interrupt_shared_t kbd_state_shrd;
@ -14,12 +14,11 @@ static void kbd_interrupt_handler(registers_t *r) {
} }
} }
void init_keyboard() { void init_keyboard() {
kbd_state_shrd.len = 0; kbd_state_shrd.len = 0;
kbd_state_shrd.buf = (uint8_t*)kalloc(); kbd_state_shrd.buf = (uint8_t *)kalloc();
kbd_state_shrd.copy_len = 0; kbd_state_shrd.copy_len = 0;
kbd_state_shrd.copy_buf = (uint8_t*)kalloc(); kbd_state_shrd.copy_buf = (uint8_t *)kalloc();
/* 128/8 actually we need only 16 bytes for that */ /* 128/8 actually we need only 16 bytes for that */
memset(kbd_state_shrd.copy_pressed, 0, 16); memset(kbd_state_shrd.copy_pressed, 0, 16);
@ -32,16 +31,17 @@ uint8_t kbd_take_from_copy_buffer() {
uint8_t key_event_code = kbd_state_shrd.copy_buf[--kbd_state_shrd.copy_len]; uint8_t key_event_code = kbd_state_shrd.copy_buf[--kbd_state_shrd.copy_len];
uint8_t keycode = (key_event_code & 0x7f); uint8_t keycode = (key_event_code & 0x7f);
if (key_event_code & 0x80) { if (key_event_code & 0x80) {
kbd_state_shrd.copy_pressed[keycode >> 3] = kbd_state_shrd.copy_pressed[keycode >> 3] & (~(1u << (keycode & 0x7))); kbd_state_shrd.copy_pressed[keycode >> 3] =
kbd_state_shrd.copy_pressed[keycode >> 3] &
(~(1u << (keycode & 0x7)));
} else { } else {
kbd_state_shrd.copy_pressed[keycode >> 3] = kbd_state_shrd.copy_pressed[keycode >> 3] | (1u << (keycode & 0x7)); kbd_state_shrd.copy_pressed[keycode >> 3] =
kbd_state_shrd.copy_pressed[keycode >> 3] | (1u << (keycode & 0x7));
} }
return key_event_code; return key_event_code;
} }
bool kbd_can_take_from_copy_buffer() { bool kbd_can_take_from_copy_buffer() { return kbd_state_shrd.copy_len > 0; }
return kbd_state_shrd.copy_len > 0;
}
bool kbd_is_pressed(uint8_t code) { bool kbd_is_pressed(uint8_t code) {
check(code < 128); check(code < 128);
return kbd_state_shrd.copy_pressed[code >> 3] & (1u << (code & 0x7)); return kbd_state_shrd.copy_pressed[code >> 3] & (1u << (code & 0x7));

View File

@ -6,12 +6,12 @@
#define KEYBOARD_INTERRUPT_BUF_CAP 100 #define KEYBOARD_INTERRUPT_BUF_CAP 100
typedef struct { typedef struct {
volatile uint32_t len; volatile uint32_t len;
uint8_t *buf; uint8_t *buf;
uint32_t copy_len; uint32_t copy_len;
uint8_t *copy_buf; uint8_t *copy_buf;
uint8_t copy_pressed[16]; uint8_t copy_pressed[16];
} keyboard_interrupt_shared_t; } keyboard_interrupt_shared_t;
#define KEYCODE_SHIFT 42 #define KEYCODE_SHIFT 42
@ -20,22 +20,22 @@ typedef struct {
/* decoding */ /* decoding */
static const char keysym_mapped_ascii_lower[] = { static const char keysym_mapped_ascii_lower[] = {
0 , 0 , '1', '2', '3', '4', '5', '6', 0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0,
'7', '8', '9', '0', '-', '=', 0 , 0 , 'q', 'w', 'e', 'r', 't', 'y', 0, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', 0,
'u', 'i', 'o', 'p', '[', ']', '\n', 0 , 'a', 's', 'd', 'f', 'g', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z',
'h', 'j', 'k', 'l', ';', '\'', '`', 0 , '\\', 'z', 'x', 'c', 'v', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, 0, 0, ' ',
'b', 'n', 'm', ',', '.', '/', 0 , 0 , 0 , ' ',
}; };
static const char keysym_mapped_ascii_upper[] = { static const char keysym_mapped_ascii_upper[] = {
0 , 0 , '!', '@', '#', '$', '%', '^', 0, 0, '!', '@', '#', '$', '%', '^', '&',
'&', '*', '(', ')', '_', '+', 0 , 0 , 'Q', 'W', 'E', 'R', 'T', 'Y', '*', '(', ')', '_', '+', 0, 0, 'Q', 'W',
'U', 'I', 'O', 'P', '{', '}', '\n', 0 , 'A', 'S', 'D', 'F', 'G', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{',
'H', 'J', 'K', 'L', ':', '"', '~', 0 , '\\', 'Z', 'X', 'C', 'V', '}', '\n', 0, 'A', 'S', 'D', 'F', 'G', 'H',
'B', 'N', 'M', '<', '>', '?' /* an actual question mark */, 0 , 0 , 0 , ' ', 'J', 'K', 'L', ':', '"', '~', 0, '\\', 'Z',
'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?' /* an actual question mark */,
0, 0, 0, ' ',
}; };
extern keyboard_interrupt_shared_t kbd_state_shrd; extern keyboard_interrupt_shared_t kbd_state_shrd;
void init_keyboard(); void init_keyboard();

View File

@ -1,8 +1,7 @@
#pragma once #pragma once
#include "port.h" #include "port.h"
__attribute__((noreturn)) __attribute__((noreturn)) static inline void qemu_shutdown() {
static inline void qemu_shutdown() { port_word_out(0x604, 0x2000);
port_word_out(0x604, 0x2000); __builtin_unreachable();
__builtin_unreachable();
} }

View File

@ -1,6 +1,6 @@
#include "pit.h" #include "pit.h"
#include "port.h"
#include "../cpu/isr.h" #include "../cpu/isr.h"
#include "port.h"
enum { enum {
PIT_CRYSTAL_HZ = 1193182, PIT_CRYSTAL_HZ = 1193182,
@ -30,7 +30,6 @@ enum {
PC_SPEAKER_PORT = 0x61, PC_SPEAKER_PORT = 0x61,
}; };
// Wtf is that O_o // Wtf is that O_o
static timer_callback callbacks[100]; static timer_callback callbacks[100];
static int registered_callbacks = 0; static int registered_callbacks = 0;
@ -78,9 +77,7 @@ static void timer_int_callback(void) {
sleep_counter--; sleep_counter--;
} }
uint32_t get_uptime_ms(void) { uint32_t get_uptime_ms(void) { return uptime_ms; }
return uptime_ms;
}
void set_beep_frequency_hz(uint32_t frequency_hz) { void set_beep_frequency_hz(uint32_t frequency_hz) {
if (frequency_hz == 0) { if (frequency_hz == 0) {
@ -117,9 +114,7 @@ void disable_beep(void) {
speaker_frequency_hz = 0; speaker_frequency_hz = 0;
} }
uint32_t get_beep_frequency_hz(void) { uint32_t get_beep_frequency_hz(void) { return speaker_frequency_hz; }
return speaker_frequency_hz;
}
void msleep(int ms) { void msleep(int ms) {
sleep_counter = ms / 10; sleep_counter = ms / 10;

View File

@ -2,25 +2,25 @@
static inline unsigned char port_byte_in(unsigned short port) { static inline unsigned char port_byte_in(unsigned short port) {
unsigned char result; unsigned char result;
asm volatile("in %%dx, %%al" : "=a" (result) : "d" (port)); asm volatile("in %%dx, %%al" : "=a"(result) : "d"(port));
return result; return result;
} }
static inline unsigned short port_word_in(unsigned short port) { static inline unsigned short port_word_in(unsigned short port) {
unsigned short result; unsigned short result;
asm volatile("in %%dx, %%ax" : "=a" (result) : "d" (port)); asm volatile("in %%dx, %%ax" : "=a"(result) : "d"(port));
return result; return result;
} }
static inline void port_byte_out(unsigned short port, unsigned char data) { static inline void port_byte_out(unsigned short port, unsigned char data) {
asm volatile("outb %%al, %%dx" : : "a" (data), "d" (port)); asm volatile("outb %%al, %%dx" : : "a"(data), "d"(port));
} }
static inline void port_word_out(unsigned short port, unsigned short data) { static inline void port_word_out(unsigned short port, unsigned short data) {
asm volatile("outw %%ax, %%dx" : : "a" (data), "d" (port)); asm volatile("outw %%ax, %%dx" : : "a"(data), "d"(port));
} }
/* assembler-long, not c-long */ /* assembler-long, not c-long */
static inline void port_long_out(unsigned short port, unsigned int data) { static inline void port_long_out(unsigned short port, unsigned int data) {
asm volatile("outl %%eax, %%dx" : : "a" (data), "d" (port)); asm volatile("outl %%eax, %%dx" : : "a"(data), "d"(port));
} }

View File

@ -9,37 +9,35 @@ enum {
void uartinit() { void uartinit() {
// Turn off the FIFO // Turn off the FIFO
port_byte_out(COM1+2, 0); port_byte_out(COM1 + 2, 0);
// 9600 baud, 8 data bits, 1 stop bit, parity off. // 9600 baud, 8 data bits, 1 stop bit, parity off.
port_byte_out(COM1+3, 0x80); // Unlock divisor port_byte_out(COM1 + 3, 0x80); // Unlock divisor
port_byte_out(COM1+0, 115200/9600); port_byte_out(COM1 + 0, 115200 / 9600);
port_byte_out(COM1+1, 0); port_byte_out(COM1 + 1, 0);
port_byte_out(COM1+3, 0x03); // Lock divisor, 8 data bits. port_byte_out(COM1 + 3, 0x03); // Lock divisor, 8 data bits.
port_byte_out(COM1+4, 0); port_byte_out(COM1 + 4, 0);
port_byte_out(COM1+1, 0x01); // Enable receive interrupts. port_byte_out(COM1 + 1, 0x01); // Enable receive interrupts.
// If status is 0xFF, no serial port. // If status is 0xFF, no serial port.
if(port_byte_in(COM1+5) == 0xFF) if (port_byte_in(COM1 + 5) == 0xFF)
return; return;
uart = 1; uart = 1;
// Acknowledge pre-existing interrupt conditions; // Acknowledge pre-existing interrupt conditions;
// enable interrupts. // enable interrupts.
port_byte_in(COM1+2); port_byte_in(COM1 + 2);
port_byte_in(COM1+0); port_byte_in(COM1 + 0);
} }
void void uartputc(char c) {
uartputc(char c)
{
int i; int i;
if (!uart) if (!uart)
return; return;
/* What is that *skeleton emoji*? */ /* What is that *skeleton emoji*? */
for (i = 0; i < 128 && !(port_byte_in(COM1+5) & 0x20); i++) { for (i = 0; i < 128 && !(port_byte_in(COM1 + 5) & 0x20); i++) {
asm("pause"); asm("pause");
} }
port_byte_out(COM1+0, c); port_byte_out(COM1 + 0, c);
} }

View File

@ -1,9 +1,9 @@
#include "vga.h" #include "vga.h"
#include "port.h"
#include "../lib/string.h" #include "../lib/string.h"
#include "cpu/memlayout.h" #include "cpu/memlayout.h"
#include "port.h"
static char* const video_memory = (char*) (KERNBASE + 0xb8000); static char *const video_memory = (char *)(KERNBASE + 0xb8000);
enum colors16 : unsigned char { enum colors16 : unsigned char {
black = 0, black = 0,
@ -32,15 +32,13 @@ unsigned vga_get_offset(unsigned col, unsigned row) {
return row * VGA_COLS + col; return row * VGA_COLS + col;
} }
unsigned vga_get_row_from_offset(unsigned offset) { unsigned vga_get_row_from_offset(unsigned offset) { return offset / VGA_COLS; }
return offset / VGA_COLS;
}
void vga_set_cursor(unsigned offset) { void vga_set_cursor(unsigned offset) {
port_byte_out(VGA_CTRL_REGISTER, VGA_OFFSET_HIGH); port_byte_out(VGA_CTRL_REGISTER, VGA_OFFSET_HIGH);
port_byte_out(VGA_DATA_REGISTER, (unsigned char) (offset >> 8)); port_byte_out(VGA_DATA_REGISTER, (unsigned char)(offset >> 8));
port_byte_out(VGA_CTRL_REGISTER, VGA_OFFSET_LOW); port_byte_out(VGA_CTRL_REGISTER, VGA_OFFSET_LOW);
port_byte_out(VGA_DATA_REGISTER, (unsigned char) (offset & 0xff)); port_byte_out(VGA_DATA_REGISTER, (unsigned char)(offset & 0xff));
} }
unsigned vga_get_cursor() { unsigned vga_get_cursor() {
@ -64,14 +62,15 @@ void vga_clear_screen() {
} }
static unsigned scroll() { static unsigned scroll() {
kmemmove(video_memory, video_memory + 2 * VGA_COLS, 2 * VGA_COLS * (VGA_ROWS-1)); kmemmove(video_memory, video_memory + 2 * VGA_COLS,
2 * VGA_COLS * (VGA_ROWS - 1));
for (int col = 0; col < VGA_COLS; col++) { for (int col = 0; col < VGA_COLS; col++) {
vga_set_char(vga_get_offset(col, VGA_ROWS - 1), ' '); vga_set_char(vga_get_offset(col, VGA_ROWS - 1), ' ');
} }
return vga_get_offset(0, VGA_ROWS - 1); return vga_get_offset(0, VGA_ROWS - 1);
} }
void vga_print_string(const char* s) { void vga_print_string(const char *s) {
unsigned offset = vga_get_cursor(); unsigned offset = vga_get_cursor();
while (*s != 0) { while (*s != 0) {
if (*s == '\n') { if (*s == '\n') {

View File

@ -4,17 +4,15 @@
#include <stdint.h> #include <stdint.h>
enum { enum {
VGA_ROWS = 25, VGA_ROWS = 25,
VGA_COLS = 80, VGA_COLS = 80,
VGA_CTRL_REGISTER = 0x3d4, VGA_CTRL_REGISTER = 0x3d4,
VGA_DATA_REGISTER = 0x3d5, VGA_DATA_REGISTER = 0x3d5,
VGA_OFFSET_LOW = 0x0f, VGA_OFFSET_LOW = 0x0f,
VGA_OFFSET_HIGH = 0x0e, VGA_OFFSET_HIGH = 0x0e,
}; };
unsigned vga_get_cursor(); unsigned vga_get_cursor();
unsigned vga_get_row_from_offset(unsigned offset); unsigned vga_get_row_from_offset(unsigned offset);
unsigned vga_get_offset(unsigned col, unsigned row); unsigned vga_get_offset(unsigned col, unsigned row);
@ -22,14 +20,14 @@ void vga_set_cursor(unsigned offset);
void vga_clear_screen(); void vga_clear_screen();
void vga_set_char(unsigned offset, char c); void vga_set_char(unsigned offset, char c);
void vga_print_string(const char* s); void vga_print_string(const char *s);
#define VGA_GRAPHICS_WIDTH 320 #define VGA_GRAPHICS_WIDTH 320
#define VGA_GRAPHICS_HEIGHT 200 #define VGA_GRAPHICS_HEIGHT 200
typedef enum { typedef enum {
VGA_DISPLAY_MODE_TEXT = 0, VGA_DISPLAY_MODE_TEXT = 0,
VGA_DISPLAY_MODE_GRAPHICS = 1, VGA_DISPLAY_MODE_GRAPHICS = 1,
} vga_display_mode_t; } vga_display_mode_t;
void vgaMode13(); void vgaMode13();

50
elf.h
View File

@ -3,39 +3,39 @@
#include <stdint.h> #include <stdint.h>
enum { enum {
EI_NIDENT = 16, EI_NIDENT = 16,
}; };
typedef uint32_t Elf32_Addr; typedef uint32_t Elf32_Addr;
typedef uint32_t Elf32_Off; typedef uint32_t Elf32_Off;
#define ELF_MAGIC 0x464C457FU // "\x7FELF" in little endian #define ELF_MAGIC 0x464C457FU // "\x7FELF" in little endian
typedef struct { typedef struct {
uint32_t magic; uint32_t magic;
unsigned char e_ident[EI_NIDENT - 4]; unsigned char e_ident[EI_NIDENT - 4];
uint16_t e_type; uint16_t e_type;
uint16_t e_machine; uint16_t e_machine;
uint32_t e_version; uint32_t e_version;
Elf32_Addr e_entry; Elf32_Addr e_entry;
Elf32_Off e_phoff; Elf32_Off e_phoff;
Elf32_Off e_shoff; Elf32_Off e_shoff;
uint32_t e_flags; uint32_t e_flags;
uint16_t e_ehsize; uint16_t e_ehsize;
uint16_t e_phentsize; uint16_t e_phentsize;
uint16_t e_phnum; uint16_t e_phnum;
uint16_t e_shentsize; uint16_t e_shentsize;
uint16_t e_shnum; uint16_t e_shnum;
uint16_t e_shstrndx; uint16_t e_shstrndx;
} Elf32_Ehdr; } Elf32_Ehdr;
typedef struct { typedef struct {
uint32_t p_type; uint32_t p_type;
Elf32_Off p_offset; Elf32_Off p_offset;
Elf32_Addr p_vaddr; Elf32_Addr p_vaddr;
Elf32_Addr p_paddr; Elf32_Addr p_paddr;
uint32_t p_filesz; uint32_t p_filesz;
uint32_t p_memsz; uint32_t p_memsz;
uint32_t p_flags; uint32_t p_flags;
uint32_t p_align; uint32_t p_align;
} Elf32_Phdr; } Elf32_Phdr;

View File

@ -1,12 +1,12 @@
#include "fs.h" #include "fs.h"
#include "../lib/string.h"
#include "../drivers/ata.h" #include "../drivers/ata.h"
#include "../lib/string.h"
enum { enum {
fs_start = 1, // sector where the FS starts fs_start = 1, // sector where the FS starts
}; };
int stat(const char* name, struct stat *buf) { int stat(const char *name, struct stat *buf) {
struct dir dir; struct dir dir;
read_sectors_ATA_PIO(&dir, fs_start, 1); read_sectors_ATA_PIO(&dir, fs_start, 1);
for (int i = 0; i < ents_in_dir; ++i) { for (int i = 0; i < ents_in_dir; ++i) {
@ -23,7 +23,7 @@ int stat(const char* name, struct stat *buf) {
/* Find file by name and read it into buffer with size bufsize. /* Find file by name and read it into buffer with size bufsize.
* At most (bufsize & -512) bytes will be read. * At most (bufsize & -512) bytes will be read.
* Return number of bytes read or -1 on failure. */ * Return number of bytes read or -1 on failure. */
int read_file(const struct stat *statbuf, void* buf, uint32_t bufsize) { int read_file(const struct stat *statbuf, void *buf, uint32_t bufsize) {
uint32_t sector = fs_start + statbuf->start_sector; uint32_t sector = fs_start + statbuf->start_sector;
uint32_t bytes_read = 0; uint32_t bytes_read = 0;
uint32_t file_sectors = (statbuf->size + sector_size - 1) / sector_size; uint32_t file_sectors = (statbuf->size + sector_size - 1) / sector_size;

26
fs/fs.h
View File

@ -20,34 +20,34 @@ size is in bytes, name is 0-terminated.
*/ */
enum { enum {
sector_size = 512, sector_size = 512,
ents_in_dir = 15, ents_in_dir = 15,
}; };
struct dirent { struct dirent {
uint32_t offset_sectors; uint32_t offset_sectors;
uint32_t size_bytes; uint32_t size_bytes;
uint32_t reserved; uint32_t reserved;
char name[20]; char name[20];
}; };
/* This way we have 512 bytes (1 sector) per dir */ /* This way we have 512 bytes (1 sector) per dir */
struct dir { struct dir {
char reserved[32]; char reserved[32];
struct dirent entries[ents_in_dir]; struct dirent entries[ents_in_dir];
}; };
struct stat { struct stat {
uint32_t size; uint32_t size;
uint32_t start_sector; uint32_t start_sector;
uint32_t reserved1, reserved2; uint32_t reserved1, reserved2;
}; };
/* Find file by name and fill information in buf. /* Find file by name and fill information in buf.
* Returns zero on success, nonzero on failure. */ * Returns zero on success, nonzero on failure. */
int stat(const char* name, struct stat *buf); int stat(const char *name, struct stat *buf);
/* Find file by name and read it into buffer with size bufsize. /* Find file by name and read it into buffer with size bufsize.
* At most (bufsize & ~511) bytes will be read. * At most (bufsize & ~511) bytes will be read.
* Return number of bytes read or -1 on failure. */ * Return number of bytes read or -1 on failure. */
int read_file(const struct stat *statbuf, void* buf, uint32_t bufsize); int read_file(const struct stat *statbuf, void *buf, uint32_t bufsize);

View File

@ -1,20 +1,20 @@
#include "console.h" #include "console.h"
#include "cpu/isr.h"
#include "cpu/gdt.h" #include "cpu/gdt.h"
#include "cpu/isr.h"
#include "cpu/memlayout.h" #include "cpu/memlayout.h"
#include "drivers/keyboard.h"
#include "drivers/vga.h"
#include "drivers/ata.h" #include "drivers/ata.h"
#include "drivers/keyboard.h"
#include "drivers/misc.h" #include "drivers/misc.h"
#include "drivers/pit.h" #include "drivers/pit.h"
#include "drivers/uart.h" #include "drivers/uart.h"
#include "drivers/vga.h"
#include "fs/fs.h" #include "fs/fs.h"
#include "kernel/mem.h"
#include "lib/string.h" #include "lib/string.h"
#include "proc.h" #include "proc.h"
#include "kernel/mem.h"
void vga_set_pixel(int x, int y, int color) { void vga_set_pixel(int x, int y, int color) {
unsigned char* pixel = (unsigned char*) (KERNBASE + 0xA0000 + 320 * y + x); unsigned char *pixel = (unsigned char *)(KERNBASE + 0xA0000 + 320 * y + x);
*pixel = color; *pixel = color;
} }
@ -22,7 +22,7 @@ void graphtest() {
switch_to_graphics_mode(); switch_to_graphics_mode();
for (int i = 0; i < 320; ++i) { for (int i = 0; i < 320; ++i) {
for (int j = 0; j < 200; ++j) { for (int j = 0; j < 200; ++j) {
vga_set_pixel(i, j, (i+j)/2); vga_set_pixel(i, j, (i + j) / 2);
} }
} }
msleep(5000); msleep(5000);
@ -30,7 +30,7 @@ void graphtest() {
vga_clear_screen(); vga_clear_screen();
} }
void read_line_input(char* buf, size_t* ret_len, size_t cap) { void read_line_input(char *buf, size_t *ret_len, size_t cap) {
size_t len = 0; size_t len = 0;
while (1) { while (1) {
while (kbd_can_take_from_copy_buffer()) { while (kbd_can_take_from_copy_buffer()) {
@ -50,8 +50,8 @@ void read_line_input(char* buf, size_t* ret_len, size_t cap) {
len--; len--;
} }
} else if (keycode < keycodes) { } else if (keycode < keycodes) {
char ch = shift_pressed ? keysym_mapped_ascii_upper[keycode] : char ch = shift_pressed ? keysym_mapped_ascii_upper[keycode]
keysym_mapped_ascii_lower[keycode]; : keysym_mapped_ascii_lower[keycode];
if (ch != 0) { if (ch != 0) {
char haha[2] = {ch, 0}; char haha[2] = {ch, 0};
printk(haha); printk(haha);
@ -76,16 +76,15 @@ void read_line_input(char* buf, size_t* ret_len, size_t cap) {
sti(); sti();
} }
} }
end: end:
printk("\n"); printk("\n");
*ret_len = len; *ret_len = len;
} }
void kmain() { void kmain() {
freerange(P2V(3u<<20), P2V(4u<<20)); freerange(P2V(3u << 20), P2V(4u << 20));
kvmalloc(); // map all of physical memory at KERNBASE kvmalloc(); // map all of physical memory at KERNBASE
freerange(P2V(4u<<20), P2V(PHYSTOP)); freerange(P2V(4u << 20), P2V(PHYSTOP));
load_gdt(); load_gdt();
init_keyboard(); init_keyboard();
@ -119,7 +118,7 @@ void kmain() {
} else if (cstr_equal(input, "graphtest")) { } else if (cstr_equal(input, "graphtest")) {
graphtest(); graphtest();
} else if (cstr_starts_with(input, "run ")) { } else if (cstr_starts_with(input, "run ")) {
const char* cmd = input + 4; const char *cmd = input + 4;
run_elf(cmd); run_elf(cmd);
} else { } else {
printk("unknown command, try: halt | run CMD\n"); printk("unknown command, try: halt | run CMD\n");

View File

@ -2,69 +2,62 @@
// memory for user processes, kernel stacks, page table pages, // memory for user processes, kernel stacks, page table pages,
// and pipe buffers. Allocates 4096-byte pages. // and pipe buffers. Allocates 4096-byte pages.
#include <stdint.h>
#include "mem.h" #include "mem.h"
#include "console.h" #include "console.h"
#include "cpu/memlayout.h" #include "cpu/memlayout.h"
#include "cpu/x86.h" #include "cpu/x86.h"
#include <stdint.h>
struct run { struct run {
struct run *next; struct run *next;
}; };
struct { struct {
struct run *freelist; struct run *freelist;
} kmem; } kmem;
void void freerange(void *vstart, void *vend) {
freerange(void *vstart, void *vend) char *p;
{ p = (char *)PGROUNDUP((uintptr_t)vstart);
char *p; for (; p + PGSIZE <= (char *)vend; p += PGSIZE)
p = (char*)PGROUNDUP((uintptr_t)vstart); kfree(p);
for(; p + PGSIZE <= (char*)vend; p += PGSIZE)
kfree(p);
} }
void* void *memset(void *dst, unsigned c, uint64_t n) {
memset(void *dst, unsigned c, uint64_t n) if ((uintptr_t)dst % 4 == 0 && n % 4 == 0) {
{ c &= 0xFF;
if ((uintptr_t)dst%4 == 0 && n%4 == 0){ stosl(dst, (c << 24) | (c << 16) | (c << 8) | c, n / 4);
c &= 0xFF; } else
stosl(dst, (c<<24)|(c<<16)|(c<<8)|c, n/4); stosb(dst, c, n);
} else return dst;
stosb(dst, c, n);
return dst;
} }
// Free the page of physical memory pointed at by v, // Free the page of physical memory pointed at by v,
// which normally should have been returned by a // which normally should have been returned by a
// call to kalloc(). (The exception is when // call to kalloc(). (The exception is when
// initializing the allocator; see kinit above.) // initializing the allocator; see kinit above.)
void void kfree(void *v) {
kfree(void *v) struct run *r;
{
struct run *r;
if((uintptr_t)v % PGSIZE || V2P(v) >= PHYSTOP) if ((uintptr_t)v % PGSIZE || V2P(v) >= PHYSTOP)
panic("kfree"); panic("kfree");
// Fill with junk to catch dangling refs. // Fill with junk to catch dangling refs.
memset(v, 1, PGSIZE); memset(v, 1, PGSIZE);
r = v; r = v;
r->next = kmem.freelist; r->next = kmem.freelist;
kmem.freelist = r; kmem.freelist = r;
} }
// Allocate one 4096-byte page of physical memory. // Allocate one 4096-byte page of physical memory.
// Returns a pointer that the kernel can use. // Returns a pointer that the kernel can use.
// Returns 0 if the memory cannot be allocated. // Returns 0 if the memory cannot be allocated.
void* kalloc(void) void *kalloc(void) {
{ struct run *r;
struct run *r;
r = kmem.freelist; r = kmem.freelist;
if(r) if (r)
kmem.freelist = r->next; kmem.freelist = r->next;
return (char*)r; return (char *)r;
} }

View File

@ -5,11 +5,11 @@
typedef uintptr_t pde_t; typedef uintptr_t pde_t;
typedef uintptr_t pte_t; typedef uintptr_t pte_t;
void* memset(void *dst, unsigned c, uint64_t n); void *memset(void *dst, unsigned c, uint64_t n);
void freerange(void *vstart, void *vend); void freerange(void *vstart, void *vend);
void* kalloc(void); void *kalloc(void);
void kfree(void*); void kfree(void *);
pde_t *setupkvm(); pde_t *setupkvm();
void kvmalloc(); void kvmalloc();

View File

@ -1,7 +1,7 @@
#include "mem.h" #include "console.h"
#include "cpu/memlayout.h" #include "cpu/memlayout.h"
#include "cpu/x86.h" #include "cpu/x86.h"
#include "console.h" #include "mem.h"
pde_t *kvm; pde_t *kvm;
@ -22,8 +22,7 @@ void kvmalloc() {
switchkvm(); switchkvm();
} }
void switchkvm(void) void switchkvm(void) {
{
lcr3(V2P(kvm)); // switch to the kernel page table lcr3(V2P(kvm)); // switch to the kernel page table
} }
@ -33,9 +32,7 @@ void switchkvm(void)
// Return the address of the PTE in page table pgdir // Return the address of the PTE in page table pgdir
// that corresponds to virtual address va. If alloc!=0, // that corresponds to virtual address va. If alloc!=0,
// create any required page table pages. // create any required page table pages.
static pte_t * static pte_t *walkpgdir(pde_t *pgdir, const void *va, int alloc) {
walkpgdir(pde_t *pgdir, const void *va, int alloc)
{
pde_t *pde; pde_t *pde;
pte_t *pgtab; pte_t *pgtab;
@ -59,19 +56,19 @@ walkpgdir(pde_t *pgdir, const void *va, int alloc)
// entries, if necessary. // entries, if necessary.
*pde = V2P(pgtab) | PTE_P | PTE_W | PTE_U; *pde = V2P(pgtab) | PTE_P | PTE_W | PTE_U;
} }
return &pgtab[PTX(va)]; return &pgtab[PTX(va)];
} }
// Create PTEs for virtual addresses starting at va that refer to // Create PTEs for virtual addresses starting at va that refer to
// physical addresses starting at pa. // physical addresses starting at pa.
// size might not be page-aligned. // size might not be page-aligned.
static int static int mappages(pde_t *pgdir, void *va, uintptr_t size, uintptr_t pa,
mappages(pde_t *pgdir, void *va, uintptr_t size, uintptr_t pa, int perm){ int perm) {
if ((uintptr_t)va % PGSIZE != 0) if ((uintptr_t)va % PGSIZE != 0)
panic("Why??"); panic("Why??");
char* a = va; char *a = va;
char* last = (char *)PGROUNDDOWN(((uintptr_t)va) + size - 1); char *last = (char *)PGROUNDDOWN(((uintptr_t)va) + size - 1);
for (;;){ for (;;) {
pte_t *pte = walkpgdir(pgdir, a, 1); pte_t *pte = walkpgdir(pgdir, a, 1);
if (pte == 0) if (pte == 0)
return -1; return -1;
@ -82,8 +79,8 @@ mappages(pde_t *pgdir, void *va, uintptr_t size, uintptr_t pa, int perm){
break; break;
a += PGSIZE; a += PGSIZE;
pa += PGSIZE; pa += PGSIZE;
} }
return 0; return 0;
} }
// top may be not page-aligned // top may be not page-aligned
@ -96,7 +93,7 @@ int allocuvm(pde_t *pgdir, uintptr_t base, uintptr_t top) {
return -1; return -1;
} }
memset(pa, 0, PGSIZE); memset(pa, 0, PGSIZE);
if (mappages(pgdir, (void*)a, PGSIZE, V2P(pa), PTE_W | PTE_U) < 0) { if (mappages(pgdir, (void *)a, PGSIZE, V2P(pa), PTE_W | PTE_U) < 0) {
kfree(pa); kfree(pa);
return -1; return -1;
} }
@ -107,16 +104,16 @@ int allocuvm(pde_t *pgdir, uintptr_t base, uintptr_t top) {
static void freept(pte_t *pt) { static void freept(pte_t *pt) {
for (int i = 0; i < NPTENTRIES; i++) { for (int i = 0; i < NPTENTRIES; i++) {
if (pt[i] & PTE_P) { if (pt[i] & PTE_P) {
kfree((char*)P2V(PTE_ADDR(pt[i]))); kfree((char *)P2V(PTE_ADDR(pt[i])));
} }
} }
kfree((char*)pt); kfree((char *)pt);
} }
void freevm(pde_t *pgdir) { void freevm(pde_t *pgdir) {
for (int i = 0; i < NPDENTRIES / 2; i++) { for (int i = 0; i < NPDENTRIES / 2; i++) {
if (pgdir[i] & PTE_P) { if (pgdir[i] & PTE_P) {
freept((pte_t*)P2V(PTE_ADDR(pgdir[i]))); freept((pte_t *)P2V(PTE_ADDR(pgdir[i])));
} }
} }
kfree(pgdir); kfree(pgdir);

View File

@ -5,17 +5,17 @@
/* Bribki are stored here */ /* Bribki are stored here */
typedef struct { typedef struct {
char chars[5]; char chars[5];
} DebugBribka; } DebugBribka;
DebugBribka byte_to_string_bribka(uint8_t byte) { DebugBribka byte_to_string_bribka(uint8_t byte) {
DebugBribka res = {.chars = {' ', ' ', ' ', ' ', 0}}; DebugBribka res = {.chars = {' ', ' ', ' ', ' ', 0}};
int p = 3; int p = 3;
while (byte > 0) { while (byte > 0) {
uint8_t d = byte % 10; uint8_t d = byte % 10;
byte /= 10; byte /= 10;
res.chars[p] = (char)(d) + '0'; res.chars[p] = (char)(d) + '0';
p--; p--;
} }
return res; return res;
} }

View File

@ -1,28 +1,28 @@
#include "string.h" #include "string.h"
void memcpy(void *dst, const void *src, size_t size) {
void memcpy(void*dst, const void *src, size_t size) {
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
((char*)dst)[i] = ((const char*)src)[i]; ((char *)dst)[i] = ((const char *)src)[i];
} }
} }
void kmemmove(char* dst, char* src, size_t size) { void kmemmove(char *dst, char *src, size_t size) {
if (dst == src) return; if (dst == src)
if (dst > src && dst < src + size) { // s d return;
// copy right-to-left if (dst > src && dst < src + size) { // s d
for (; size != 0; size--) { // copy right-to-left
dst[size - 1] = src[size - 1]; for (; size != 0; size--) {
} dst[size - 1] = src[size - 1];
} else { }
// copy left-to-right } else {
for (size_t i = 0; i < size; ++i) { // copy left-to-right
dst[i] = src[i]; for (size_t i = 0; i < size; ++i) {
} dst[i] = src[i];
} }
}
} }
int strncmp(const char* s1, const char* s2, size_t size) { int strncmp(const char *s1, const char *s2, size_t size) {
while (size && *s1 && *s2 && *s1 == *s2) { while (size && *s1 && *s2 && *s1 == *s2) {
size--; size--;
s1++; s1++;
@ -34,7 +34,7 @@ int strncmp(const char* s1, const char* s2, size_t size) {
return (unsigned char)(*s1) - (unsigned char)(*s2); return (unsigned char)(*s1) - (unsigned char)(*s2);
} }
bool cstr_equal(const char* s1, const char* s2) { bool cstr_equal(const char *s1, const char *s2) {
while (*s1 && *s2 && *s1 == *s2) { while (*s1 && *s2 && *s1 == *s2) {
s1++; s1++;
s2++; s2++;
@ -42,7 +42,6 @@ bool cstr_equal(const char* s1, const char* s2) {
return *s1 == 0 && *s2 == 0; return *s1 == 0 && *s2 == 0;
} }
bool cstr_starts_with(const char *A, const char *B) { bool cstr_starts_with(const char *A, const char *B) {
while (*A && *B) { while (*A && *B) {
if (*A != *B) if (*A != *B)

View File

@ -4,8 +4,8 @@
typedef unsigned size_t; typedef unsigned size_t;
void memcpy(void*dst, const void *src, size_t size); void memcpy(void *dst, const void *src, size_t size);
void kmemmove(char* dst, char* src, size_t size); void kmemmove(char *dst, char *src, size_t size);
int strncmp(const char* s1, const char* s2, size_t size); int strncmp(const char *s1, const char *s2, size_t size);
bool cstr_equal(const char* s1, const char* s2); bool cstr_equal(const char *s1, const char *s2);
bool cstr_starts_with(const char *A, const char *B); bool cstr_starts_with(const char *A, const char *B);

19
proc.c
View File

@ -27,7 +27,7 @@ struct vm {
} vm; } vm;
void trapret(); void trapret();
void swtch(void** oldstack, void* newstack); void swtch(void **oldstack, void *newstack);
pde_t *get_user_proc_page_directory() { pde_t *get_user_proc_page_directory() {
if (!vm.user_task) { if (!vm.user_task) {
@ -36,7 +36,7 @@ pde_t *get_user_proc_page_directory() {
return vm.user_task->pgdir; return vm.user_task->pgdir;
} }
void run_elf(const char* name) { void run_elf(const char *name) {
struct stat statbuf; struct stat statbuf;
if (stat(name, &statbuf) != 0) { if (stat(name, &statbuf) != 0) {
printk(name); printk(name);
@ -47,24 +47,27 @@ void run_elf(const char* name) {
vm.user_task = kalloc(); vm.user_task = kalloc();
} }
// todo: this code contains 9999 memory leaks but I don't care // todo: this code contains 9999 memory leaks but I don't care
// todo: yabloko is fucking shit made my monkeys, I want to forget this fucking nightmare // todo: yabloko is fucking shit made my monkeys, I want to forget this
// fucking nightmare
vm.user_task->pgdir = setupkvm(); vm.user_task->pgdir = setupkvm();
if (allocuvm(vm.user_task->pgdir, USER_BASE, USER_BASE + statbuf.size)) { if (allocuvm(vm.user_task->pgdir, USER_BASE, USER_BASE + statbuf.size)) {
printk("Fail: out of memory\n"); printk("Fail: out of memory\n");
return; return;
} }
if (allocuvm(vm.user_task->pgdir, USER_STACK_BASE - 2 * PGSIZE, USER_STACK_BASE)) { if (allocuvm(vm.user_task->pgdir, USER_STACK_BASE - 2 * PGSIZE,
USER_STACK_BASE)) {
printk("Fail: out of memory\n"); printk("Fail: out of memory\n");
return; return;
} }
switchuvm(&vm.user_task->tss, vm.user_task->stack.bottom, vm.user_task->pgdir); switchuvm(&vm.user_task->tss, vm.user_task->stack.bottom,
vm.user_task->pgdir);
if (read_file(&statbuf, (void*)USER_BASE, 100 << 20) <= 0) { if (read_file(&statbuf, (void *)USER_BASE, 100 << 20) <= 0) {
printk(name); printk(name);
printk(": file not found\n"); printk(": file not found\n");
return; return;
} }
Elf32_Ehdr *hdr = (void*)USER_BASE; Elf32_Ehdr *hdr = (void *)USER_BASE;
struct kstack *u = &vm.user_task->stack; struct kstack *u = &vm.user_task->stack;
memset(u, 0, sizeof(*u)); memset(u, 0, sizeof(*u));
@ -88,7 +91,7 @@ void run_elf(const char* name) {
} }
_Noreturn void killproc() { _Noreturn void killproc() {
void* task_stack; void *task_stack;
disable_beep(); disable_beep();
if (!vga_is_text_mode()) { if (!vga_is_text_mode()) {
switch_to_text_mode(); switch_to_text_mode();

11
proc.h
View File

@ -1,16 +1,15 @@
#pragma once #pragma once
#include "elf.h" #include "console.h"
#include "fs/fs.h"
#include "cpu/gdt.h" #include "cpu/gdt.h"
#include "cpu/isr.h" #include "cpu/isr.h"
#include "cpu/memlayout.h" #include "cpu/memlayout.h"
#include "elf.h"
#include "fs/fs.h"
#include "kernel/mem.h" #include "kernel/mem.h"
#include "lib/string.h" #include "lib/string.h"
#include "console.h"
pde_t *get_user_proc_page_directory();
pde_t* get_user_proc_page_directory(); void run_elf(const char *name);
void run_elf(const char* name);
_Noreturn void killproc(); _Noreturn void killproc();

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h>
/* We still have beef with keyboard, even in userspace */ /* We still have beef with keyboard, even in userspace */
#define KEYCODE_SHIFT 42 #define KEYCODE_SHIFT 42
@ -23,17 +23,17 @@
#define KEYCODE_2 3 #define KEYCODE_2 3
bool is_keycode_for_press_left(uint8_t keycode) { bool is_keycode_for_press_left(uint8_t keycode) {
return keycode == KEYCODE_LEFT || keycode == KEYCODE_A; return keycode == KEYCODE_LEFT || keycode == KEYCODE_A;
} }
bool is_keycode_for_press_right(uint8_t keycode) { bool is_keycode_for_press_right(uint8_t keycode) {
return keycode == KEYCODE_RIGHT || keycode == KEYCODE_D; return keycode == KEYCODE_RIGHT || keycode == KEYCODE_D;
} }
bool is_keycode_for_press_up(uint8_t keycode) { bool is_keycode_for_press_up(uint8_t keycode) {
return keycode == KEYCODE_UP || keycode == KEYCODE_W; return keycode == KEYCODE_UP || keycode == KEYCODE_W;
} }
bool is_keycode_for_press_down(uint8_t keycode) { bool is_keycode_for_press_down(uint8_t keycode) {
return keycode == KEYCODE_DOWN || keycode == KEYCODE_S; return keycode == KEYCODE_DOWN || keycode == KEYCODE_S;
} }

View File

@ -2,183 +2,713 @@
#include "maps.h" #include "maps.h"
static const MapList map_list = { static const MapList
.maps = { map_list = {.maps =
/* CLUSTERTRACT.png */ {
[0] = { /* CLUSTERTRACT.png */
.name = "CLUSTERTRACT", [0] =
.map = { {
[0] = { tile_wall_t, tile_wall_lr, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_wall_lr, tile_wall_b }, .name = "CLUSTERTRACT",
[1] = { tile_wall_rb, tile_wall_lt, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_wall_lb, tile_wall_rt }, .map =
[2] = { tile_wall_lr, tile_wall_rb, tile_wall_lt, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lb, tile_wall_rt, tile_wall_lr }, {
[3] = { tile_wall_lr, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_wall_lr }, [0] = {tile_wall_t, tile_wall_lr,
[4] = { tile_wall_lr, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_wall_lr }, tile_wall_lr, tile_empty,
[5] = { tile_wall_lr, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_b, tile_wall_lrt, tile_wall_lr }, tile_empty, tile_empty,
[6] = { tile_wall_lr, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_wall_lr }, tile_empty, tile_wall_lr,
[7] = { tile_wall_lr, tile_wall_lrb, tile_wall_rt, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_wall_lr }, tile_wall_lr, tile_wall_b},
[8] = { tile_wall_lr, tile_wall_lrb, tile_wall_lt, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_rb, tile_wall_lrt, tile_wall_lr }, [1] = {tile_wall_rb, tile_wall_lt,
[9] = { tile_wall_lr, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lb, tile_wall_lrt, tile_wall_lr }, tile_wall_lr, tile_empty,
[10] = { tile_wall_lr, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_wall_lr }, tile_empty, tile_empty,
[11] = { tile_wall_lr, tile_wall_lrb, tile_wall_t, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_wall_lr }, tile_empty, tile_wall_lr,
[12] = { tile_wall_lr, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_wall_lr }, tile_wall_lb, tile_wall_rt},
[13] = { tile_wall_lr, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_wall_lr }, [2] =
[14] = { tile_wall_lr, tile_wall_lb, tile_wall_rt, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_rb, tile_wall_lt, tile_wall_lr }, {tile_wall_lr,
[15] = { tile_wall_lb, tile_wall_rt, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_wall_rb, tile_wall_lt }, tile_wall_rb, tile_wall_lt, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lb, tile_wall_rt, tile_wall_lr},
}, [3] =
}, {tile_wall_lr,
/* EMPTY.png */ tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_wall_lr},
[1] = { [4] =
.name = "EMPTY", {tile_wall_lr,
.map = { tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_wall_lr},
[0] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, [5] =
[1] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, {tile_wall_lr,
[2] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_b, tile_wall_lrt, tile_wall_lr},
[3] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, [6] =
[4] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, {tile_wall_lr,
[5] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_wall_lr},
[6] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, [7] =
[7] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, {tile_wall_lr,
[8] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_wall_lrb, tile_wall_rt, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_wall_lr},
[9] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, [8] =
[10] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, {tile_wall_lr,
[11] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_wall_lrb, tile_wall_lt, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_rb, tile_wall_lrt, tile_wall_lr},
[12] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, [9] =
[13] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, {tile_wall_lr,
[14] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lb, tile_wall_lrt, tile_wall_lr},
[15] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, [10] =
}, {tile_wall_lr,
}, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr,
/* GREEN DAYS.png */ tile_wall_lr},
[2] = { [11] =
.name = "GREEN DAYS", {tile_wall_lr,
.map = { tile_wall_lrb, tile_wall_t, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr,
[0] = { tile_wall_rb, tile_wall_tb, tile_wall_tb, tile_wall_t, tile_empty, tile_empty, tile_wall_b, tile_wall_tb, tile_wall_tb, tile_wall_rt }, tile_wall_lr},
[1] = { tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr }, [12] =
[2] = { tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr }, {tile_wall_lr, tile_wall_lr,
[3] = { tile_wall_l, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_l }, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr,
[4] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_wall_lr},
[5] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, [13] =
[6] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, {tile_wall_lr, tile_wall_lr,
[7] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr,
[8] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_wall_lr},
[9] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, [14] =
[10] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, {tile_wall_lr, tile_wall_lb,
[11] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_wall_rt,
[12] = { tile_wall_r, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_r }, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_rb,
[13] = { tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr }, tile_wall_lt, tile_wall_lr},
[14] = { tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr }, [15] =
[15] = { tile_wall_lb, tile_wall_tb, tile_wall_tb, tile_wall_t, tile_empty, tile_empty, tile_wall_b, tile_wall_tb, tile_wall_tb, tile_wall_lt }, {tile_wall_lb, tile_wall_rt,
}, tile_wall_lr,
}, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr,
/* QUARTERHOUSE.png */ tile_wall_rb, tile_wall_lt},
[3] = { },
.name = "QUARTERHOUSE", },
.map = { /* EMPTY.png */
[0] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, [1] =
[1] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, {
[2] = { tile_empty, tile_empty, tile_empty, tile_wall_b, tile_wall_rtb, tile_wall_tb, tile_wall_t, tile_empty, tile_empty, tile_empty }, .name = "EMPTY",
[3] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_wall, tile_empty, tile_empty, tile_empty, tile_empty }, .map =
[4] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_wall, tile_empty, tile_empty, tile_empty, tile_empty }, {
[5] = { tile_wall_rt, tile_empty, tile_empty, tile_empty, tile_wall_lb, tile_wall_rt, tile_empty, tile_empty, tile_empty, tile_wall_rb }, [0] = {tile_empty, tile_empty,
[6] = { tile_wall_lrt, tile_empty, tile_empty, tile_empty, tile_wall, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_wall_lrb }, tile_empty, tile_empty,
[7] = { tile_wall_lrt, tile_wall, tile_wall_rb, tile_wall_tb, tile_wall_rtb, tile_wall_lrtb, tile_wall_tb, tile_wall_rt, tile_wall, tile_wall_lrb }, tile_empty, tile_empty,
[8] = { tile_wall_lrtb, tile_wall_tb, tile_wall_lt, tile_wall, tile_wall_lrb, tile_wall_lt, tile_wall, tile_wall_lb, tile_wall_tb, tile_wall_lrtb }, tile_empty, tile_empty,
[9] = { tile_wall_lrt, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_wall, tile_empty, tile_empty, tile_empty, tile_wall_lrb }, tile_empty, tile_empty},
[10] = { tile_wall_lt, tile_empty, tile_empty, tile_empty, tile_wall_lb, tile_wall_rt, tile_empty, tile_empty, tile_empty, tile_wall_lb }, [1] = {tile_empty, tile_empty,
[11] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_wall, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty,
[12] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_wall, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty,
[13] = { tile_empty, tile_empty, tile_empty, tile_wall_b, tile_wall_tb, tile_wall_ltb, tile_wall_t, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty,
[14] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty},
[15] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, [2] = {tile_empty, tile_empty,
}, tile_empty, tile_empty,
}, tile_empty, tile_empty,
/* SERPENTINE STRUTS.png */ tile_empty, tile_empty,
[4] = { tile_empty, tile_empty},
.name = "SERPENTINE STRUTS", [3] = {tile_empty, tile_empty,
.map = { tile_empty, tile_empty,
[0] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty,
[1] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_r, tile_empty, tile_empty, tile_wall_r, tile_empty, tile_empty }, tile_empty, tile_empty,
[2] = { tile_empty, tile_empty, tile_empty, tile_wall_b, tile_wall_lrtb, tile_wall_tb, tile_wall_tb, tile_wall_lrtb, tile_wall_t, tile_empty }, tile_empty, tile_empty},
[3] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_l, tile_empty, tile_empty, tile_wall_l, tile_empty, tile_empty }, [4] = {tile_empty, tile_empty,
[4] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty,
[5] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty,
[6] = { tile_empty, tile_empty, tile_empty, tile_wall_r, tile_empty, tile_empty, tile_wall_r, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty,
[7] = { tile_empty, tile_empty, tile_wall_b, tile_wall_lrtb, tile_wall_tb, tile_wall_tb, tile_wall_lrtb, tile_wall_t, tile_empty, tile_empty }, tile_empty, tile_empty},
[8] = { tile_empty, tile_empty, tile_empty, tile_wall_l, tile_empty, tile_empty, tile_wall_l, tile_empty, tile_empty, tile_empty }, [5] = {tile_empty, tile_empty,
[9] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty,
[10] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty,
[11] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty,
[12] = { tile_empty, tile_empty, tile_wall_r, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_r, tile_empty, tile_empty }, tile_empty, tile_empty},
[13] = { tile_empty, tile_wall_b, tile_wall_lrtb, tile_wall_tb, tile_wall_tb, tile_wall_tb, tile_wall_tb, tile_wall_lrtb, tile_wall_t, tile_empty }, [6] = {tile_empty, tile_empty,
[14] = { tile_empty, tile_empty, tile_wall_l, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_l, tile_empty, tile_empty }, tile_empty, tile_empty,
[15] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty,
}, tile_empty, tile_empty,
}, tile_empty, tile_empty},
/* SHEER GIRTH.png */ [7] = {tile_empty, tile_empty,
[5] = { tile_empty, tile_empty,
.name = "SHEER GIRTH", tile_empty, tile_empty,
.map = { tile_empty, tile_empty,
[0] = { tile_empty, tile_wall_rb, tile_wall_rtb, tile_wall_rtb, tile_wall_rtb, tile_wall_rtb, tile_wall_rtb, tile_wall_rtb, tile_wall_rt, tile_empty }, tile_empty, tile_empty},
[1] = { tile_empty, tile_wall_lrb, tile_wall_lrtb, tile_wall_lrtb, tile_wall_lrtb, tile_wall_lrtb, tile_wall_lrtb, tile_wall_lrtb, tile_wall_lrt, tile_empty }, [8] = {tile_empty, tile_empty,
[2] = { tile_empty, tile_wall_lb, tile_wall_ltb, tile_wall_ltb, tile_wall_ltb, tile_wall_ltb, tile_wall_ltb, tile_wall_ltb, tile_wall_lt, tile_empty }, tile_empty, tile_empty,
[3] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty,
[4] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty,
[5] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty},
[6] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, [9] = {tile_empty, tile_empty,
[7] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty,
[8] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty,
[9] = { tile_empty, tile_wall_rb, tile_wall_rtb, tile_wall_rt, tile_empty, tile_empty, tile_wall_rb, tile_wall_rtb, tile_wall_rt, tile_empty }, tile_empty, tile_empty,
[10] = { tile_empty, tile_wall_lrb, tile_wall_lrtb, tile_wall_lrt, tile_empty, tile_empty, tile_wall_lrb, tile_wall_lrtb, tile_wall_lrt, tile_empty }, tile_empty, tile_empty},
[11] = { tile_empty, tile_wall_lrb, tile_wall_lrtb, tile_wall_lrt, tile_empty, tile_empty, tile_wall_lrb, tile_wall_lrtb, tile_wall_lrt, tile_empty }, [10] =
[12] = { tile_empty, tile_wall_lrb, tile_wall_lrtb, tile_wall_lrt, tile_empty, tile_empty, tile_wall_lrb, tile_wall_lrtb, tile_wall_lrt, tile_empty }, {tile_empty, tile_empty, tile_empty,
[13] = { tile_empty, tile_wall_lb, tile_wall_ltb, tile_wall_lt, tile_empty, tile_empty, tile_wall_lb, tile_wall_ltb, tile_wall_lt, tile_empty }, tile_empty, tile_empty, tile_empty,
[14] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty, tile_empty,
[15] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty},
}, [11] =
}, {tile_empty, tile_empty, tile_empty,
/* VAULT.png */ tile_empty, tile_empty, tile_empty,
[6] = { tile_empty, tile_empty, tile_empty,
.name = "VAULT", tile_empty},
.map = { [12] =
[0] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, {tile_empty, tile_empty, tile_empty,
[1] = { tile_empty, tile_empty, tile_empty, tile_wall_rb, tile_wall_tb, tile_wall_tb, tile_wall_tb, tile_wall_tb, tile_wall_rt, tile_empty }, tile_empty, tile_empty, tile_empty,
[2] = { tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_empty }, tile_empty, tile_empty, tile_empty,
[3] = { tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_empty }, tile_empty},
[4] = { tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_empty }, [13] =
[5] = { tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_empty }, {tile_empty, tile_empty, tile_empty,
[6] = { tile_empty, tile_empty, tile_empty, tile_wall_lb, tile_wall_t, tile_empty, tile_empty, tile_wall_b, tile_wall_lrt, tile_empty }, tile_empty, tile_empty, tile_empty,
[7] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_empty }, tile_empty, tile_empty, tile_empty,
[8] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_empty }, tile_empty},
[9] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_empty }, [14] =
[10] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_empty }, {tile_empty, tile_empty, tile_empty,
[11] = { tile_empty, tile_empty, tile_wall_rb, tile_wall_t, tile_empty, tile_empty, tile_wall_b, tile_wall_tb, tile_wall_lrt, tile_empty }, tile_empty, tile_empty, tile_empty,
[12] = { tile_empty, tile_empty, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_empty }, tile_empty, tile_empty, tile_empty,
[13] = { tile_empty, tile_empty, tile_wall_lr, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_wall_lr, tile_empty }, tile_empty},
[14] = { tile_empty, tile_empty, tile_wall_lb, tile_wall_tb, tile_wall_tb, tile_wall_tb, tile_wall_tb, tile_wall_tb, tile_wall_lt, tile_empty }, [15] =
[15] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, {tile_empty, tile_empty, tile_empty,
}, tile_empty, tile_empty, tile_empty,
}, tile_empty, tile_empty, tile_empty,
/* WALLS.png */ tile_empty},
[7] = { },
.name = "WALLS", },
.map = { /* GREEN DAYS.png */
[0] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, [2] =
[1] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, {
[2] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, .name = "GREEN DAYS",
[3] = { tile_wall_tb, tile_wall_t, tile_empty, tile_empty, tile_wall_b, tile_wall_tb, tile_wall_tb, tile_wall_tb, tile_wall_tb, tile_wall_tb }, .map =
[4] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, {
[5] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, [0] = {tile_wall_rb, tile_wall_tb,
[6] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_wall_tb, tile_wall_t,
[7] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty,
[8] = { tile_wall_tb, tile_wall_tb, tile_wall_tb, tile_wall_tb, tile_wall_t, tile_empty, tile_empty, tile_wall_b, tile_wall_tb, tile_wall_tb }, tile_wall_b, tile_wall_tb,
[9] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_wall_tb, tile_wall_rt},
[10] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, [1] = {tile_wall_lr, tile_empty,
[11] = { tile_wall_t, tile_empty, tile_empty, tile_wall_b, tile_wall_tb, tile_wall_tb, tile_wall_tb, tile_wall_tb, tile_wall_tb, tile_wall_tb }, tile_empty, tile_empty,
[12] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty,
[13] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, tile_empty, tile_empty,
[14] = { tile_wall_tb, tile_wall_tb, tile_wall_tb, tile_wall_tb, tile_wall_tb, tile_wall_tb, tile_wall_t, tile_empty, tile_empty, tile_wall_b }, tile_empty, tile_wall_lr},
[15] = { tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty, tile_empty }, [2] = {tile_wall_lr, tile_empty,
}, tile_empty, tile_empty,
}, tile_empty, tile_empty,
} tile_empty, tile_empty,
}; tile_empty, tile_wall_lr},
[3] = {tile_wall_l, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_wall_l},
[4] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[5] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[6] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[7] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[8] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[9] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[10] =
{tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty},
[11] =
{tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty},
[12] =
{tile_wall_r, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_wall_r},
[13] =
{tile_wall_lr, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_wall_lr},
[14] =
{tile_wall_lr, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_wall_lr},
[15] =
{tile_wall_lb, tile_wall_tb,
tile_wall_tb, tile_wall_t,
tile_empty, tile_empty,
tile_wall_b, tile_wall_tb,
tile_wall_tb, tile_wall_lt},
},
},
/* QUARTERHOUSE.png */
[3] =
{
.name = "QUARTERHOUSE",
.map =
{
[0] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[1] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[2] = {tile_empty, tile_empty,
tile_empty, tile_wall_b,
tile_wall_rtb, tile_wall_tb,
tile_wall_t, tile_empty,
tile_empty, tile_empty},
[3] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_wall_lr,
tile_wall, tile_empty,
tile_empty, tile_empty,
tile_empty},
[4] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_wall_lr,
tile_wall, tile_empty,
tile_empty, tile_empty,
tile_empty},
[5] = {tile_wall_rt, tile_empty,
tile_empty, tile_empty,
tile_wall_lb, tile_wall_rt,
tile_empty, tile_empty,
tile_empty, tile_wall_rb},
[6] = {tile_wall_lrt, tile_empty,
tile_empty, tile_empty,
tile_wall, tile_wall_lr,
tile_empty, tile_empty,
tile_empty, tile_wall_lrb},
[7] = {tile_wall_lrt,
tile_wall, tile_wall_rb,
tile_wall_tb, tile_wall_rtb,
tile_wall_lrtb, tile_wall_tb,
tile_wall_rt,
tile_wall, tile_wall_lrb},
[8] = {tile_wall_lrtb, tile_wall_tb,
tile_wall_lt,
tile_wall, tile_wall_lrb,
tile_wall_lt,
tile_wall, tile_wall_lb,
tile_wall_tb, tile_wall_lrtb},
[9] = {tile_wall_lrt, tile_empty,
tile_empty, tile_empty,
tile_wall_lr,
tile_wall, tile_empty,
tile_empty, tile_empty,
tile_wall_lrb},
[10] =
{tile_wall_lt, tile_empty,
tile_empty, tile_empty,
tile_wall_lb, tile_wall_rt,
tile_empty, tile_empty, tile_empty,
tile_wall_lb},
[11] =
{tile_empty, tile_empty, tile_empty,
tile_empty, tile_wall,
tile_wall_lr, tile_empty,
tile_empty, tile_empty,
tile_empty},
[12] =
{tile_empty, tile_empty, tile_empty,
tile_empty, tile_wall,
tile_wall_lr, tile_empty,
tile_empty, tile_empty,
tile_empty},
[13] =
{tile_empty, tile_empty, tile_empty,
tile_wall_b, tile_wall_tb,
tile_wall_ltb, tile_wall_t,
tile_empty, tile_empty,
tile_empty},
[14] =
{tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty},
[15] =
{tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty},
},
},
/* SERPENTINE STRUTS.png */
[4] =
{
.name = "SERPENTINE STRUTS",
.map =
{
[0] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[1] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_wall_r, tile_empty,
tile_empty, tile_wall_r,
tile_empty, tile_empty},
[2] = {tile_empty, tile_empty,
tile_empty, tile_wall_b,
tile_wall_lrtb, tile_wall_tb,
tile_wall_tb, tile_wall_lrtb,
tile_wall_t, tile_empty},
[3] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_wall_l, tile_empty,
tile_empty, tile_wall_l,
tile_empty, tile_empty},
[4] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[5] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[6] = {tile_empty, tile_empty,
tile_empty, tile_wall_r,
tile_empty, tile_empty,
tile_wall_r, tile_empty,
tile_empty, tile_empty},
[7] = {tile_empty, tile_empty,
tile_wall_b, tile_wall_lrtb,
tile_wall_tb, tile_wall_tb,
tile_wall_lrtb, tile_wall_t,
tile_empty, tile_empty},
[8] = {tile_empty, tile_empty,
tile_empty, tile_wall_l,
tile_empty, tile_empty,
tile_wall_l, tile_empty,
tile_empty, tile_empty},
[9] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[10] =
{tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty},
[11] =
{tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty},
[12] =
{tile_empty, tile_empty,
tile_wall_r, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_wall_r, tile_empty,
tile_empty},
[13] = {tile_empty, tile_wall_b,
tile_wall_lrtb, tile_wall_tb,
tile_wall_tb, tile_wall_tb,
tile_wall_tb, tile_wall_lrtb,
tile_wall_t, tile_empty},
[14] =
{tile_empty, tile_empty,
tile_wall_l, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_wall_l, tile_empty,
tile_empty},
[15] =
{tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty},
},
},
/* SHEER GIRTH.png */
[5] =
{
.name = "SHEER GIRTH",
.map =
{
[0] = {tile_empty, tile_wall_rb,
tile_wall_rtb, tile_wall_rtb,
tile_wall_rtb, tile_wall_rtb,
tile_wall_rtb, tile_wall_rtb,
tile_wall_rt, tile_empty},
[1] = {tile_empty, tile_wall_lrb,
tile_wall_lrtb, tile_wall_lrtb,
tile_wall_lrtb, tile_wall_lrtb,
tile_wall_lrtb, tile_wall_lrtb,
tile_wall_lrt, tile_empty},
[2] = {tile_empty, tile_wall_lb,
tile_wall_ltb, tile_wall_ltb,
tile_wall_ltb, tile_wall_ltb,
tile_wall_ltb, tile_wall_ltb,
tile_wall_lt, tile_empty},
[3] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[4] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[5] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[6] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[7] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[8] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[9] = {tile_empty, tile_wall_rb,
tile_wall_rtb, tile_wall_rt,
tile_empty, tile_empty,
tile_wall_rb, tile_wall_rtb,
tile_wall_rt, tile_empty},
[10] =
{tile_empty, tile_wall_lrb,
tile_wall_lrtb, tile_wall_lrt,
tile_empty, tile_empty,
tile_wall_lrb, tile_wall_lrtb,
tile_wall_lrt, tile_empty},
[11] =
{tile_empty, tile_wall_lrb,
tile_wall_lrtb, tile_wall_lrt,
tile_empty, tile_empty,
tile_wall_lrb, tile_wall_lrtb,
tile_wall_lrt, tile_empty},
[12] =
{tile_empty, tile_wall_lrb,
tile_wall_lrtb, tile_wall_lrt,
tile_empty, tile_empty,
tile_wall_lrb, tile_wall_lrtb,
tile_wall_lrt, tile_empty},
[13] =
{tile_empty, tile_wall_lb,
tile_wall_ltb, tile_wall_lt,
tile_empty, tile_empty,
tile_wall_lb, tile_wall_ltb,
tile_wall_lt, tile_empty},
[14] =
{tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty},
[15] =
{tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty},
},
},
/* VAULT.png */
[6] =
{
.name = "VAULT",
.map =
{
[0] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[1] = {tile_empty, tile_empty,
tile_empty, tile_wall_rb,
tile_wall_tb, tile_wall_tb,
tile_wall_tb, tile_wall_tb,
tile_wall_rt, tile_empty},
[2] = {tile_empty, tile_empty,
tile_empty, tile_wall_lr,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_wall_lr, tile_empty},
[3] = {tile_empty, tile_empty,
tile_empty, tile_wall_lr,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_wall_lr, tile_empty},
[4] = {tile_empty, tile_empty,
tile_empty, tile_wall_lr,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_wall_lr, tile_empty},
[5] = {tile_empty, tile_empty,
tile_empty, tile_wall_lr,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_wall_lr, tile_empty},
[6] = {tile_empty, tile_empty,
tile_empty, tile_wall_lb,
tile_wall_t, tile_empty,
tile_empty, tile_wall_b,
tile_wall_lrt, tile_empty},
[7] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_wall_lr, tile_empty},
[8] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_wall_lr, tile_empty},
[9] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_wall_lr, tile_empty},
[10] =
{tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty,
tile_wall_lr, tile_empty},
[11] =
{tile_empty, tile_empty,
tile_wall_rb, tile_wall_t,
tile_empty, tile_empty,
tile_wall_b, tile_wall_tb,
tile_wall_lrt, tile_empty},
[12] =
{tile_empty, tile_empty,
tile_wall_lr, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_wall_lr,
tile_empty},
[13] =
{tile_empty, tile_empty,
tile_wall_lr, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_wall_lr,
tile_empty},
[14] =
{tile_empty, tile_empty,
tile_wall_lb, tile_wall_tb,
tile_wall_tb, tile_wall_tb,
tile_wall_tb, tile_wall_tb,
tile_wall_lt, tile_empty},
[15] =
{tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty},
},
},
/* WALLS.png */
[7] =
{
.name = "WALLS",
.map =
{
[0] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[1] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[2] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[3] = {tile_wall_tb, tile_wall_t,
tile_empty, tile_empty,
tile_wall_b, tile_wall_tb,
tile_wall_tb, tile_wall_tb,
tile_wall_tb, tile_wall_tb},
[4] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[5] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[6] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[7] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[8] = {tile_wall_tb, tile_wall_tb,
tile_wall_tb, tile_wall_tb,
tile_wall_t, tile_empty,
tile_empty, tile_wall_b,
tile_wall_tb, tile_wall_tb},
[9] = {tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty,
tile_empty, tile_empty},
[10] =
{tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty},
[11] =
{tile_wall_t, tile_empty,
tile_empty, tile_wall_b,
tile_wall_tb, tile_wall_tb,
tile_wall_tb, tile_wall_tb,
tile_wall_tb, tile_wall_tb},
[12] =
{tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty},
[13] =
{tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty},
[14] =
{tile_wall_tb, tile_wall_tb,
tile_wall_tb, tile_wall_tb,
tile_wall_tb, tile_wall_tb,
tile_wall_t, tile_empty,
tile_empty, tile_wall_b},
[15] =
{tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty, tile_empty, tile_empty,
tile_empty},
},
},
}};

View File

@ -61,7 +61,7 @@ typedef enum {
#define WORLD_HEIGHT 10 #define WORLD_HEIGHT 10
typedef struct { typedef struct {
const char* name; const char *name;
tile_t map[WORLD_WIDTH][WORLD_HEIGHT]; tile_t map[WORLD_WIDTH][WORLD_HEIGHT];
} MapConfig; } MapConfig;

View File

@ -4,30 +4,33 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
void _Noreturn panic(const char* message) { void _Noreturn panic(const char *message) {
syscall(SYS_switch_to_text, 0); // ??? syscall(SYS_switch_to_text, 0); // ???
syscall(SYS_puts, (uintptr_t)message); syscall(SYS_puts, (uintptr_t)message);
syscall(SYS_exit, 1); syscall(SYS_exit, 1);
__builtin_unreachable(); __builtin_unreachable();
} }
#define check(expr) if (!(expr)){ panic( "Assertion failed at " __FILE__ ": " #expr "\n"); } #define check(expr) \
if (!(expr)) { \
panic("Assertion failed at " __FILE__ ": " #expr "\n"); \
}
typedef struct { typedef struct {
int x, y; int x, y;
} ivec2; } ivec2;
void* memcpy(void* dst, const void* src, uint32_t size) { void *memcpy(void *dst, const void *src, uint32_t size) {
uint8_t* d = (uint8_t*)dst; uint8_t *d = (uint8_t *)dst;
const uint8_t* s = (const uint8_t*)src; const uint8_t *s = (const uint8_t *)src;
for (uint32_t i = 0; i < size; i++) { for (uint32_t i = 0; i < size; i++) {
d[i] = s[i]; d[i] = s[i];
} }
return dst; return dst;
} }
void* memset(void* dst, int value, uint32_t size) { void *memset(void *dst, int value, uint32_t size) {
uint8_t* d = (uint8_t*)dst; uint8_t *d = (uint8_t *)dst;
uint8_t byte = (uint8_t)value; uint8_t byte = (uint8_t)value;
for (uint32_t i = 0; i < size; i++) { for (uint32_t i = 0; i < size; i++) {
d[i] = byte; d[i] = byte;
@ -42,20 +45,20 @@ typedef struct {
int len; int len;
} StringBuilder; } StringBuilder;
void StringBuilder_putc(StringBuilder* self, char ch) { void StringBuilder_putc(StringBuilder *self, char ch) {
if (self->len + 1 > STRING_BUILDER_CAPACITY) { if (self->len + 1 > STRING_BUILDER_CAPACITY) {
panic("string builder\n"); panic("string builder\n");
} }
self->buf[self->len++] = ch; self->buf[self->len++] = ch;
} }
void StringBuilder_append_cstr(StringBuilder* self, const char* str) { void StringBuilder_append_cstr(StringBuilder *self, const char *str) {
for (const char* p = str; *p; p++) { for (const char *p = str; *p; p++) {
StringBuilder_putc(self, *p); StringBuilder_putc(self, *p);
} }
} }
void StringBuilder_append_u32(StringBuilder* self, uint32_t x) { void StringBuilder_append_u32(StringBuilder *self, uint32_t x) {
char b[11]; char b[11];
int len = 0; int len = 0;
@ -80,11 +83,9 @@ void StringBuilder_append_u32(StringBuilder* self, uint32_t x) {
StringBuilder_append_cstr(self, b); StringBuilder_append_cstr(self, b);
} }
const char* StringBuilder_get_cstr(StringBuilder* self) { const char *StringBuilder_get_cstr(StringBuilder *self) {
StringBuilder_putc(self, 0); StringBuilder_putc(self, 0);
return self->buf; return self->buf;
} }
uint32_t time_ms(void) { uint32_t time_ms(void) { return (uint32_t)syscall(SYS_time_ms, 0); }
return (uint32_t)syscall(SYS_time_ms, 0);
}

View File

@ -3,24 +3,20 @@
#include <stdint.h> #include <stdint.h>
static const uint8_t VGA_GRAY_LUT[256] = { static const uint8_t VGA_GRAY_LUT[256] = {
16, 17, 23, 24, 20, 21, 23, 27, 22, 23, 28, 29, 25, 27, 30, 31, 16, 17, 23, 24, 20, 21, 23, 27, 22, 23, 28, 29, 25, 27, 30, 31, 16, 17, 18,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 18, 19, 21, 22, 23, 23,
18, 19, 21, 22, 23, 23, 23, 22, 22, 24, 26, 28, 30, 29, 28, 27, 23, 22, 22, 24, 26, 28, 30, 29, 28, 27, 26, 27, 27, 27, 28, 26, 23, 21, 26,
26, 27, 27, 27, 28, 26, 23, 21, 26, 26, 27, 27, 28, 28, 27, 27, 26, 27, 27, 28, 28, 27, 27, 27, 28, 29, 30, 30, 30, 30, 29, 29, 29, 29, 29,
27, 28, 29, 30, 30, 30, 30, 29, 29, 29, 29, 29, 30, 29, 28, 27, 30, 29, 28, 27, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 31, 30, 30,
28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 31, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 29, 29, 17, 17, 18, 18, 19, 19, 19, 18, 18, 19,
30, 30, 30, 30, 30, 30, 29, 29, 17, 17, 18, 18, 19, 19, 19, 18, 21, 22, 23, 23, 22, 21, 21, 21, 21, 22, 22, 21, 19, 18, 20, 21, 21, 21, 22,
18, 19, 21, 22, 23, 23, 22, 21, 21, 21, 21, 22, 22, 21, 19, 18, 22, 22, 21, 21, 22, 23, 23, 24, 23, 23, 23, 22, 23, 23, 23, 23, 22, 22, 21,
20, 21, 21, 21, 22, 22, 22, 21, 21, 22, 23, 23, 24, 23, 23, 23, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 23, 23, 23, 23, 23,
22, 23, 23, 23, 23, 22, 22, 21, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 22, 16, 17, 17, 17, 18, 17, 17, 17, 17, 18, 18, 19, 20, 20,
23, 23, 23, 23, 24, 24, 23, 23, 23, 23, 23, 23, 23, 23, 23, 22, 19, 19, 18, 19, 19, 19, 19, 18, 17, 17, 18, 18, 19, 19, 19, 19, 19, 19, 19,
16, 17, 17, 17, 18, 17, 17, 17, 17, 18, 18, 19, 20, 20, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 19, 19, 19, 19, 19, 19, 20,
18, 19, 19, 19, 19, 18, 17, 17, 18, 18, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20, 19, 20, 20, 20, 21, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 19, 19, 19, 19, 16, 16, 16, 16, 16, 16, 16, 16,
19, 19, 19, 20, 20, 20, 20, 20, 19, 20, 20, 20, 21, 20, 20, 20,
20, 20, 20, 20, 20, 20, 20, 19, 16, 16, 16, 16, 16, 16, 16, 16,
}; };
static inline uint8_t vga_to_gray(uint8_t color){ static inline uint8_t vga_to_gray(uint8_t color) { return VGA_GRAY_LUT[color]; }
return VGA_GRAY_LUT[color];
}

View File

@ -1,17 +1,15 @@
#pragma once #pragma once
#include <stdint.h>
#include "misc_utils.h" #include "misc_utils.h"
#include <stdint.h>
typedef struct { typedef struct {
uint32_t state; uint32_t state;
} RandomEngine; } RandomEngine;
static void RandomEngine_init(RandomEngine* self) { static void RandomEngine_init(RandomEngine *self) { self->state = 0x6d2b79f5u; }
self->state = 0x6d2b79f5u;
}
static uint32_t RandomEngine_rnd(RandomEngine* self) { static uint32_t RandomEngine_rnd(RandomEngine *self) {
uint32_t x = self->state; uint32_t x = self->state;
if (x == 0) { if (x == 0) {
@ -27,8 +25,8 @@ static uint32_t RandomEngine_rnd(RandomEngine* self) {
return x; return x;
} }
static uint32_t RandomEngine_rnd_interval( static uint32_t RandomEngine_rnd_interval(RandomEngine *self, uint32_t from,
RandomEngine* self, uint32_t from, uint32_t until) { uint32_t until) {
check(from < until); check(from < until);
return from + RandomEngine_rnd(self) % (until - from); return from + RandomEngine_rnd(self) % (until - from);
} }

View File

@ -1,17 +1,16 @@
#include "../drivers/vga.h" #include "../drivers/vga.h"
#include "../syscall.h" #include "../syscall.h"
#include "keymapping.h"
#include "map_data.h"
#include "maps.h"
#include "misc_utils.h"
#include "pause_effect.h"
#include "random.h"
#include "sprite_data.h"
#include "sprites.h" #include "sprites.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "misc_utils.h"
#include "keymapping.h"
#include "pause_effect.h"
#include "random.h"
#include "sprites.h"
#include "sprite_data.h"
#include "maps.h"
#include "map_data.h"
#define FRAME_SIZE (VGA_GRAPHICS_WIDTH * VGA_GRAPHICS_HEIGHT) #define FRAME_SIZE (VGA_GRAPHICS_WIDTH * VGA_GRAPHICS_HEIGHT)
@ -22,7 +21,7 @@
#define FONT_DIGIT_BASE 1 #define FONT_DIGIT_BASE 1
#define FONT_LETTER_BASE (FONT_DIGIT_BASE + 10) #define FONT_LETTER_BASE (FONT_DIGIT_BASE + 10)
uint8_t frame[FRAME_SIZE] = { 1 }; uint8_t frame[FRAME_SIZE] = {1};
#define SNAKE_GAMEMODE_MAX_APPLES 10 #define SNAKE_GAMEMODE_MAX_APPLES 10
#define SNAKE_GAMEMODE_DEFAULT_APPLES 5 #define SNAKE_GAMEMODE_DEFAULT_APPLES 5
@ -34,8 +33,7 @@ typedef enum {
game_screen_select_apple_count, game_screen_select_apple_count,
} game_screen_t; } game_screen_t;
#define SNAKE_START_Y 2
#define SNAKE_START_Y 2
#define SNAKE_START_HEAD_X 4 #define SNAKE_START_HEAD_X 4
#define SNAKE_START_PUPA_X 6 #define SNAKE_START_PUPA_X 6
@ -77,7 +75,8 @@ struct Snake {
bool have_game; bool have_game;
/* from 0 to PLAYABLE_MAPS_COUNT - 1 */ /* from 0 to PLAYABLE_MAPS_COUNT - 1 */
int selected_map_index; int selected_map_index;
/* from 1 to SNAKE_GAMEMODE_MAX_APPLES, default is SNAKE_GAMEMODE_DEFAULT_APPLES */ /* from 1 to SNAKE_GAMEMODE_MAX_APPLES, default is
* SNAKE_GAMEMODE_DEFAULT_APPLES */
int gamemode_apples_count; int gamemode_apples_count;
RandomEngine r_eng; RandomEngine r_eng;
@ -90,11 +89,11 @@ struct Snake {
/* If we are about to make a step into a wall, we start dying, /* If we are about to make a step into a wall, we start dying,
* we enter into dying mode, where we keep making steps, but the head * we enter into dying mode, where we keep making steps, but the head
* just disappears after walking, moving back. * just disappears after walking, moving back.
* When the pupa disappears this way, we enter 'awaiting postmortum' state, where * When the pupa disappears this way, we enter 'awaiting postmortum' state,
* nothing moves. * where nothing moves. If we are about to hit ourselves, we don't even
* If we are about to hit ourselves, we don't even move, * move, we immediately draw one small splash and enter 'awaiting
* we immediately draw one small splash and enter 'awaiting postmortum' state. * postmortum' state. There is no winning state, you just raise your score
* There is no winning state, you just raise your score until you are dead. * until you are dead.
*/ */
bool is_dying; bool is_dying;
int score; int score;
@ -102,10 +101,9 @@ struct Snake {
int puddle_sprite; int puddle_sprite;
ivec2 puddle_center; ivec2 puddle_center;
/* This stuff regulates game flow and animation progress */ /* This stuff regulates game flow and animation progress */
waiting_reason_t waiting_reason; waiting_reason_t waiting_reason;
uint32_t waiting_time; // Measures how much time we already accumulated uint32_t waiting_time; // Measures how much time we already accumulated
int animation_speed_boost; int animation_speed_boost;
} snake = {1}; } snake = {1};
@ -124,7 +122,8 @@ void init_snake() {
bool place_random_apple() { bool place_random_apple() {
for (int t = 0; t < 50; t++) { for (int t = 0; t < 50; t++) {
uint32_t i = RandomEngine_rnd_interval(&snake.r_eng, 0, WORLD_WIDTH * WORLD_HEIGHT); uint32_t i = RandomEngine_rnd_interval(&snake.r_eng, 0,
WORLD_WIDTH * WORLD_HEIGHT);
if ((&snake.world[0][0])[i] == tile_empty) { if ((&snake.world[0][0])[i] == tile_empty) {
(&snake.world[0][0])[i] = tile_apple; (&snake.world[0][0])[i] = tile_apple;
return true; return true;
@ -143,8 +142,9 @@ bool place_random_apple() {
void start_snake_game() { void start_snake_game() {
snake.have_game = true; snake.have_game = true;
snake.game_screen = game_screen_gaming; snake.game_screen = game_screen_gaming;
const MapConfig* map_config = &map_list.maps[snake.selected_map_index]; const MapConfig *map_config = &map_list.maps[snake.selected_map_index];
memcpy(&snake.world[0][0], &map_config->map[0][0], sizeof(tile_t) * WORLD_WIDTH * WORLD_HEIGHT); memcpy(&snake.world[0][0], &map_config->map[0][0],
sizeof(tile_t) * WORLD_WIDTH * WORLD_HEIGHT);
memset(&snake.ghost_apples, 0, sizeof(snake.ghost_apples)); memset(&snake.ghost_apples, 0, sizeof(snake.ghost_apples));
for (int tx = SNAKE_START_HEAD_X; tx < SNAKE_START_PUPA_X; tx++) { for (int tx = SNAKE_START_HEAD_X; tx < SNAKE_START_PUPA_X; tx++) {
snake.world[tx][SNAKE_START_Y] = tile_snake_l; snake.world[tx][SNAKE_START_Y] = tile_snake_l;
@ -155,7 +155,8 @@ void start_snake_game() {
for (int app = 0; app < snake.gamemode_apples_count; app++) { for (int app = 0; app < snake.gamemode_apples_count; app++) {
place_random_apple(); place_random_apple();
} }
snake.new_snake_direction = snake.cur_snake_direction = snake_direction_left; snake.new_snake_direction = snake.cur_snake_direction =
snake_direction_left;
snake.is_dying = false; snake.is_dying = false;
snake.score = 0; snake.score = 0;
@ -166,12 +167,14 @@ void start_snake_game() {
} }
void set_tile(ivec2 pos, tile_t val) { void set_tile(ivec2 pos, tile_t val) {
check(0 <= pos.x && pos.x < WORLD_WIDTH && 0 <= pos.y && pos.y < WORLD_HEIGHT); check(0 <= pos.x && pos.x < WORLD_WIDTH && 0 <= pos.y &&
pos.y < WORLD_HEIGHT);
snake.world[pos.x][pos.y] = val; snake.world[pos.x][pos.y] = val;
} }
tile_t get_tile(ivec2 pos) { tile_t get_tile(ivec2 pos) {
check(0 <= pos.x && pos.x < WORLD_WIDTH && 0 <= pos.y && pos.y < WORLD_HEIGHT); check(0 <= pos.x && pos.x < WORLD_WIDTH && 0 <= pos.y &&
pos.y < WORLD_HEIGHT);
return snake.world[pos.x][pos.y]; return snake.world[pos.x][pos.y];
} }
@ -364,9 +367,8 @@ void put_pixel(int x, int y, uint8_t color) {
frame[y * VGA_GRAPHICS_WIDTH + x] = color; frame[y * VGA_GRAPHICS_WIDTH + x] = color;
} }
void draw_sprite( void draw_sprite(int dst_x, int dst_y, int sprite_width, int sprite_height,
int dst_x, int dst_y, int sprite_width, int sprite_height, const uint8_t *sprite) {
const uint8_t* sprite) {
for (int x = 0; x < sprite_width; x++) { for (int x = 0; x < sprite_width; x++) {
for (int y = 0; y < sprite_height; y++) { for (int y = 0; y < sprite_height; y++) {
uint8_t color = sprite[x * sprite_height + y]; uint8_t color = sprite[x * sprite_height + y];
@ -396,20 +398,21 @@ bool font_index_for_char(char ch, int *out_index) {
void draw_hud(const char *text) { void draw_hud(const char *text) {
// int lines_count = 1; // int lines_count = 1;
int y0 = HUD_OFFSET; int y0 = HUD_OFFSET;
for (const char* line_start = text; *line_start;) { for (const char *line_start = text; *line_start;) {
int glyph_count = 0; int glyph_count = 0;
const char* p = line_start; const char *p = line_start;
for (; *p != '\n' && *p != 0; p++) { for (; *p != '\n' && *p != 0; p++) {
glyph_count++; glyph_count++;
} }
if (glyph_count > 0) { if (glyph_count > 0) {
const int text_width = glyph_count * FONT_WIDTH + (glyph_count - 1) * GLYPH_SPACING; const int text_width =
glyph_count * FONT_WIDTH + (glyph_count - 1) * GLYPH_SPACING;
int x0 = VGA_GRAPHICS_WIDTH - HUD_OFFSET - text_width; int x0 = VGA_GRAPHICS_WIDTH - HUD_OFFSET - text_width;
for (const char* q = line_start; q != p; q++) { for (const char *q = line_start; q != p; q++) {
int glyph_index; int glyph_index;
check(font_index_for_char(*q, &glyph_index)); check(font_index_for_char(*q, &glyph_index));
draw_sprite(x0, y0, FONT_WIDTH, FONT_HEIGHT, draw_sprite(x0, y0, FONT_WIDTH, FONT_HEIGHT,
&sprite_data.font[glyph_index].tex[0][0]); &sprite_data.font[glyph_index].tex[0][0]);
x0 += FONT_WIDTH + GLYPH_SPACING; x0 += FONT_WIDTH + GLYPH_SPACING;
} }
} }
@ -484,7 +487,8 @@ void draw_game_world() {
continue; continue;
check((uint8_t)tt < TILE_SPRITES); check((uint8_t)tt < TILE_SPRITES);
draw_sprite(TILE_WIDTH * tx, TILE_WIDTH * ty - TILE_HEIGHT_OFFSET, draw_sprite(TILE_WIDTH * tx, TILE_WIDTH * ty - TILE_HEIGHT_OFFSET,
TILE_WIDTH, TILE_HEIGHT, &sprite_data.tile[tt].tex[0][0]); TILE_WIDTH, TILE_HEIGHT,
&sprite_data.tile[tt].tex[0][0]);
} }
} }
if (snake.game_screen != game_screen_gaming) { if (snake.game_screen != game_screen_gaming) {
@ -495,7 +499,7 @@ void draw_game_world() {
} }
void draw_game_text() { void draw_game_text() {
StringBuilder hud = { 0 }; StringBuilder hud = {0};
if (snake.game_screen == game_screen_gaming) { if (snake.game_screen == game_screen_gaming) {
if (snake.waiting_reason == waiting_reason_postmortum) { if (snake.waiting_reason == waiting_reason_postmortum) {
StringBuilder_append_cstr(&hud, "YOU DIED "); StringBuilder_append_cstr(&hud, "YOU DIED ");
@ -517,10 +521,12 @@ void draw_game_text() {
} else if (snake.game_screen == game_screen_select_map) { } else if (snake.game_screen == game_screen_select_map) {
StringBuilder_append_cstr(&hud, "SELECT LEVEL\nCURRENTLY SELECTED\n"); StringBuilder_append_cstr(&hud, "SELECT LEVEL\nCURRENTLY SELECTED\n");
check(snake.selected_map_index < PLAYABLE_MAPS_COUNT); check(snake.selected_map_index < PLAYABLE_MAPS_COUNT);
StringBuilder_append_cstr(&hud, map_list.maps[snake.selected_map_index].name); StringBuilder_append_cstr(&hud,
map_list.maps[snake.selected_map_index].name);
} else if (snake.game_screen == game_screen_select_apple_count) { } else if (snake.game_screen == game_screen_select_apple_count) {
StringBuilder_append_cstr(&hud, "SELECT DIFFICULTY\n" StringBuilder_append_cstr(&hud,
"HOW MANY APPLES\nCURRENTLY SELECTED\n"); "SELECT DIFFICULTY\n"
"HOW MANY APPLES\nCURRENTLY SELECTED\n");
StringBuilder_append_u32(&hud, snake.gamemode_apples_count); StringBuilder_append_u32(&hud, snake.gamemode_apples_count);
} }
draw_hud(StringBuilder_get_cstr(&hud)); draw_hud(StringBuilder_get_cstr(&hud));
@ -528,11 +534,10 @@ void draw_game_text() {
void draw_game_puddles() { void draw_game_puddles() {
if (snake.puddle_sprite >= 0) { if (snake.puddle_sprite >= 0) {
const PuddleSprite* sprite = &sprite_data.puddle[snake.puddle_sprite]; const PuddleSprite *sprite = &sprite_data.puddle[snake.puddle_sprite];
draw_sprite( draw_sprite(snake.puddle_center.x - PUDDLE_WIDTH / 2,
snake.puddle_center.x - PUDDLE_WIDTH / 2, snake.puddle_center.y - PUDDLE_WIDTH / 2, PUDDLE_WIDTH,
snake.puddle_center.y - PUDDLE_WIDTH / 2, PUDDLE_WIDTH, (&sprite->tex[0][0]));
PUDDLE_WIDTH, PUDDLE_WIDTH, (&sprite->tex[0][0]));
} }
} }
@ -555,13 +560,13 @@ void handle_gaming_keycode(uint8_t keycode) {
snake.cur_snake_direction != snake_direction_right) { snake.cur_snake_direction != snake_direction_right) {
snake.new_snake_direction = snake_direction_left; snake.new_snake_direction = snake_direction_left;
} else if (is_keycode_for_press_right(keycode) && } else if (is_keycode_for_press_right(keycode) &&
snake.cur_snake_direction != snake_direction_left) { snake.cur_snake_direction != snake_direction_left) {
snake.new_snake_direction = snake_direction_right; snake.new_snake_direction = snake_direction_right;
} else if (is_keycode_for_press_up(keycode) && } else if (is_keycode_for_press_up(keycode) &&
snake.cur_snake_direction != snake_direction_bottom) { snake.cur_snake_direction != snake_direction_bottom) {
snake.new_snake_direction = snake_direction_top; snake.new_snake_direction = snake_direction_top;
} else if (is_keycode_for_press_down(keycode) && } else if (is_keycode_for_press_down(keycode) &&
snake.cur_snake_direction != snake_direction_top) { snake.cur_snake_direction != snake_direction_top) {
snake.new_snake_direction = snake_direction_bottom; snake.new_snake_direction = snake_direction_bottom;
} }
} }
@ -585,7 +590,8 @@ int handle_incoming_keycode_after_halt(uint8_t keycode) {
if (snake.game_screen == game_screen_gaming) { if (snake.game_screen == game_screen_gaming) {
handle_gaming_keycode(keycode); handle_gaming_keycode(keycode);
} else if (snake.game_screen == game_screen_pause) { } else if (snake.game_screen == game_screen_pause) {
if (keycode == KEYCODE_1 || (keycode == KEYCODE_ENTER && !snake.have_game)) { if (keycode == KEYCODE_1 ||
(keycode == KEYCODE_ENTER && !snake.have_game)) {
snake.game_screen = game_screen_select_map; snake.game_screen = game_screen_select_map;
} else if (keycode == KEYCODE_ESCAPE && snake.have_game) { } else if (keycode == KEYCODE_ESCAPE && snake.have_game) {
snake.game_screen = game_screen_gaming; snake.game_screen = game_screen_gaming;
@ -675,38 +681,45 @@ void handle_time_difference(uint32_t time_diff) {
/* Step 1 */ /* Step 1 */
ivec2 old_head_pos = snake.snake_head; ivec2 old_head_pos = snake.snake_head;
if (tile_ahead == tile_empty || tile_ahead == tile_apple) { if (tile_ahead == tile_empty || tile_ahead == tile_apple) {
set_tile(tile_pos_ahead, set_tile(tile_pos_ahead, construct_straight_snake_tile(
construct_straight_snake_tile(snake.new_snake_direction)); snake.new_snake_direction));
snake.snake_head = tile_pos_ahead; snake.snake_head = tile_pos_ahead;
} }
/* Step 2 */ /* Step 2 */
set_tile(old_head_pos, construct_snake_tile( set_tile(old_head_pos,
get_opposite_direction(snake.cur_snake_direction), snake.new_snake_direction)); construct_snake_tile(
get_opposite_direction(snake.cur_snake_direction),
snake.new_snake_direction));
snake.cur_snake_direction = snake.new_snake_direction; snake.cur_snake_direction = snake.new_snake_direction;
/* Steps 3... */ /* Steps 3... */
if (is_tile_pupa(get_tile(snake.snake_tail))) { if (is_tile_pupa(get_tile(snake.snake_tail))) {
/* Step 3a */ /* Step 3a */
snake_direction_t pupa_dir = get_zero_pupa_destination(get_tile(snake.snake_tail)); snake_direction_t pupa_dir =
ivec2 penultimate_pos = world_walk_direction(snake.snake_tail, pupa_dir); get_zero_pupa_destination(get_tile(snake.snake_tail));
ivec2 penultimate_pos =
world_walk_direction(snake.snake_tail, pupa_dir);
set_tile(snake.snake_tail, tile_empty); set_tile(snake.snake_tail, tile_empty);
/* Step 4a */ /* Step 4a */
snake_direction_t penultimate_part_dir = get_snake_destination(get_tile(penultimate_pos)); snake_direction_t penultimate_part_dir =
set_tile(penultimate_pos, construct_zero_pupa(penultimate_part_dir)); get_snake_destination(get_tile(penultimate_pos));
set_tile(penultimate_pos,
construct_zero_pupa(penultimate_part_dir));
snake.snake_tail = penultimate_pos; snake.snake_tail = penultimate_pos;
/* WARNING: we updated snake_tail by moving pupa forward, we /* WARNING: we updated snake_tail by moving pupa forward, we
* WARNING: should check if we moved onto a ghost apple */ * WARNING: should check if we moved onto a ghost apple */
// check, this is important. This is the only place where we move pupa to a new pos // check, this is important. This is the only place where we
// we check for ghost apples. Clear ghost apples and enter // move pupa to a new pos we check for ghost apples. Clear ghost
// p1-waiting state (instead of remaining in step awaiting state) // apples and enter p1-waiting state (instead of remaining in
// step awaiting state)
if (snake.snake_tail.x == snake.snake_head.x && if (snake.snake_tail.x == snake.snake_head.x &&
snake.snake_tail.y == snake.snake_head.y snake.snake_tail.y == snake.snake_head.y) {
) {
snake.waiting_reason = waiting_reason_postmortum; snake.waiting_reason = waiting_reason_postmortum;
return; return;
} }
if (snake.ghost_apples[penultimate_pos.x][penultimate_pos.y]) { if (snake.ghost_apples[penultimate_pos.x][penultimate_pos.y]) {
snake.ghost_apples[penultimate_pos.x][penultimate_pos.y] = 0; snake.ghost_apples[penultimate_pos.x][penultimate_pos.y] =
0;
syscall(SYS_set_beep, WEIRD_SOUND); syscall(SYS_set_beep, WEIRD_SOUND);
snake.waiting_reason = waiting_reason_p1; snake.waiting_reason = waiting_reason_p1;
@ -716,7 +729,8 @@ void handle_time_difference(uint32_t time_diff) {
} }
} else { } else {
snake_direction_t tail_dir = get_snake_destination(get_tile(snake.snake_tail)); snake_direction_t tail_dir =
get_snake_destination(get_tile(snake.snake_tail));
set_tile(snake.snake_tail, construct_zero_pupa(tail_dir)); set_tile(snake.snake_tail, construct_zero_pupa(tail_dir));
syscall(SYS_set_beep, WEIRD_SOUND); syscall(SYS_set_beep, WEIRD_SOUND);
@ -737,7 +751,8 @@ void handle_time_difference(uint32_t time_diff) {
snake.waiting_reason = waiting_reason_cross; snake.waiting_reason = waiting_reason_cross;
} else if (snake.waiting_reason == waiting_reason_cross) { } else if (snake.waiting_reason == waiting_reason_cross) {
/* Finished pupa hatching */ /* Finished pupa hatching */
snake_direction_t tail_dir = get_zero_pupa_destination(get_tile(snake.snake_tail)); snake_direction_t tail_dir =
get_zero_pupa_destination(get_tile(snake.snake_tail));
set_tile(snake.snake_tail, construct_straight_snake_tile(tail_dir)); set_tile(snake.snake_tail, construct_straight_snake_tile(tail_dir));
syscall(SYS_set_beep, 0); syscall(SYS_set_beep, 0);
snake.waiting_reason = waiting_reason_step; snake.waiting_reason = waiting_reason_step;
@ -764,8 +779,9 @@ int main(void) {
uint32_t prev_time = time_ms(); uint32_t prev_time = time_ms();
while (1) { while (1) {
/* Returned from halt, we can enjoy keyboard input and animation progress*/ /* Returned from halt, we can enjoy keyboard input and animation
for (int ch;(ch = syscall(SYS_getc, 0)) >= 0;) { * progress*/
for (int ch; (ch = syscall(SYS_getc, 0)) >= 0;) {
int ret = handle_incoming_keycode_after_halt((uint8_t)ch); int ret = handle_incoming_keycode_after_halt((uint8_t)ch);
if (ret == 1) if (ret == 1)
goto quit; goto quit;
@ -783,9 +799,8 @@ int main(void) {
prev_time = current_time; prev_time = current_time;
syscall(SYS_halt, 0); syscall(SYS_halt, 0);
} }
quit: quit:
syscall(SYS_switch_to_text, 0); syscall(SYS_switch_to_text, 0);
syscall(SYS_puts, (uintptr_t)"Quit from game\n"); syscall(SYS_puts, (uintptr_t)"Quit from game\n");
return 0; return 0;

View File

@ -2,7 +2,6 @@
#include "sprites.h" #include "sprites.h"
static const SpriteData sprite_data = { static const SpriteData sprite_data = {
.tile = { .tile = {
[0] = { /* slot 0: zero-filled */ [0] = { /* slot 0: zero-filled */

View File

@ -27,7 +27,7 @@ typedef struct {
} PuddleSprite; } PuddleSprite;
#define TILE_SPRITES 50 #define TILE_SPRITES 50
#define FONT_SPRITES (1+10+26) #define FONT_SPRITES (1 + 10 + 26)
#define PUDDLE_SPRITES 5 #define PUDDLE_SPRITES 5
typedef struct { typedef struct {
@ -35,4 +35,3 @@ typedef struct {
FontSprite font[FONT_SPRITES]; FontSprite font[FONT_SPRITES];
PuddleSprite puddle[PUDDLE_SPRITES]; PuddleSprite puddle[PUDDLE_SPRITES];
} SpriteData; } SpriteData;

View File

@ -3,18 +3,18 @@
#include <stdint.h> #include <stdint.h>
enum { enum {
T_SYSCALL = 0x84, T_SYSCALL = 0x84,
SYS_exit = 0, SYS_exit = 0,
SYS_greet = 1, SYS_greet = 1,
SYS_putc = 2, SYS_putc = 2,
SYS_puts = 3, SYS_puts = 3,
SYS_switch_to_text = 4, SYS_switch_to_text = 4,
SYS_switch_to_graphics = 5, SYS_switch_to_graphics = 5,
SYS_swap_frame = 6, SYS_swap_frame = 6,
SYS_time_ms = 7, SYS_time_ms = 7,
SYS_halt = 8, SYS_halt = 8,
SYS_getc = 9, SYS_getc = 9,
SYS_set_beep = 10, SYS_set_beep = 10,
}; };
int syscall(int call, uintptr_t arg); int syscall(int call, uintptr_t arg);

View File

@ -1,19 +1,19 @@
#include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#include <unistd.h>
enum { enum {
MBR_END = 510, MBR_END = 510,
}; };
int main(int argc, char* argv[]) { int main(int argc, char *argv[]) {
if (argc != 3) { if (argc != 3) {
fprintf(stderr, "Usage: %s mbr.bin fs.img\n", argv[0]); fprintf(stderr, "Usage: %s mbr.bin fs.img\n", argv[0]);
return 1; return 1;
} }
const char* filename = argv[1]; const char *filename = argv[1];
const char* fsimg_path = argv[2]; const char *fsimg_path = argv[2];
int fd = open(filename, O_RDWR); int fd = open(filename, O_RDWR);
off_t length = lseek(fd, 0, SEEK_END); off_t length = lseek(fd, 0, SEEK_END);
if (length > MBR_END) { if (length > MBR_END) {

View File

@ -3,15 +3,15 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
char* basename(char* path) { char *basename(char *path) {
char* c = strrchr(path, '/'); char *c = strrchr(path, '/');
if (c && *c) { if (c && *c) {
return c + 1; return c + 1;
} }
return path; return path;
} }
int main(int argc, char* argv[]) { int main(int argc, char *argv[]) {
char sector[sector_size]; char sector[sector_size];
struct dir dir = {{0}}; struct dir dir = {{0}};
@ -20,7 +20,7 @@ int main(int argc, char* argv[]) {
return 1; return 1;
} }
FILE* image = fopen(argv[1], "wb"); FILE *image = fopen(argv[1], "wb");
if (!image) { if (!image) {
perror(argv[1]); perror(argv[1]);
return 1; return 1;
@ -33,12 +33,12 @@ int main(int argc, char* argv[]) {
uint32_t sector_offset = 1; uint32_t sector_offset = 1;
for (int i = 2; i < argc; ++i) { for (int i = 2; i < argc; ++i) {
char* name = argv[i]; char *name = argv[i];
struct dirent *dirent = &dir.entries[i-2]; struct dirent *dirent = &dir.entries[i - 2];
dirent->offset_sectors = sector_offset; dirent->offset_sectors = sector_offset;
dirent->size_bytes = 0; dirent->size_bytes = 0;
FILE* file = fopen(name, "rb"); FILE *file = fopen(name, "rb");
if (!file) { if (!file) {
perror(name); perror(name);
return 1; return 1;

View File

@ -2,7 +2,7 @@
#include <stdint.h> #include <stdint.h>
int main() { int main() {
const char* message = "I hope the kernel does not panic...\n"; const char *message = "I hope the kernel does not panic...\n";
syscall(SYS_puts, (uint32_t)message); syscall(SYS_puts, (uint32_t)message);
syscall(SYS_puts, 0x1bad1dea); syscall(SYS_puts, 0x1bad1dea);
return 0; return 0;

View File

@ -3,16 +3,13 @@
int main(); int main();
int syscall(int call, uintptr_t arg) { int syscall(int call, uintptr_t arg) {
asm volatile("int $0x84": "+a"(call) : "b"(arg)); asm volatile("int $0x84" : "+a"(call) : "b"(arg));
return call; return call;
} }
_Noreturn _Noreturn void _exit(int exit_status) {
void _exit(int exit_status) {
syscall(SYS_exit, exit_status); syscall(SYS_exit, exit_status);
__builtin_unreachable(); __builtin_unreachable();
} }
void _start() { void _start() { _exit(main()); }
_exit(main());
}

View File

@ -1,3 +1 @@
int main() { int main() { return 1; }
return 1;
}

View File

@ -1,9 +1,7 @@
#include "../syscall.h" #include "../syscall.h"
#include <stdint.h> #include <stdint.h>
static uint32_t time_ms(void) { static uint32_t time_ms(void) { return (uint32_t)syscall(SYS_time_ms, 0); }
return (uint32_t)syscall(SYS_time_ms, 0);
}
static void wait_ms(uint32_t duration_ms) { static void wait_ms(uint32_t duration_ms) {
uint32_t start = time_ms(); uint32_t start = time_ms();

View File

@ -1,7 +1,7 @@
#include "../syscall.h" #include "../syscall.h"
#include <stdint.h> #include <stdint.h>
void userspace_puts(const char* s) { void userspace_puts(const char *s) {
char c; char c;
while ((c = *s++)) { while ((c = *s++)) {
syscall(SYS_putc, c); syscall(SYS_putc, c);
@ -9,9 +9,9 @@ void userspace_puts(const char* s) {
} }
int main() { int main() {
const char* spell = "cra cra trif traf not sgnieflet\n"; const char *spell = "cra cra trif traf not sgnieflet\n";
const char* spell2 = "Pam pam pam pam parapapapapam\n"; const char *spell2 = "Pam pam pam pam parapapapapam\n";
const char* spell3 = "Zhopu podotri\n"; const char *spell3 = "Zhopu podotri\n";
// userspace_puts(spell); // userspace_puts(spell);
syscall(SYS_puts, (uintptr_t)spell); syscall(SYS_puts, (uintptr_t)spell);
syscall(SYS_puts, (uint32_t)spell2); syscall(SYS_puts, (uint32_t)spell2);