Whoops, I think I just accidentally (no) foramtted the entire project with clang
This commit is contained in:
parent
d76095ca85
commit
1794df45f4
6
.clang-format
Normal file
6
.clang-format
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
BasedOnStyle: LLVM
|
||||||
|
IndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
TabWidth: 4
|
||||||
|
UseTab: Never
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
132
bootmain.c
132
bootmain.c
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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");
|
||||||
|
|||||||
10
console.h
10
console.h
@ -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"); \
|
||||||
|
}
|
||||||
86
cpu/gdt.c
86
cpu/gdt.c
@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
48
cpu/gdt.h
48
cpu/gdt.h
@ -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
166
cpu/idt.c
@ -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");
|
|
||||||
}
|
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
24
cpu/x86.h
24
cpu/x86.h
@ -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));
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
1041
drivers/graphics.c
1041
drivers/graphics.c
File diff suppressed because it is too large
Load Diff
@ -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));
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
@ -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();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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') {
|
||||||
|
|||||||
@ -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
50
elf.h
@ -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;
|
||||||
|
|||||||
6
fs/fs.c
6
fs/fs.c
@ -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
26
fs/fs.h
@ -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);
|
||||||
|
|||||||
29
kernel.c
29
kernel.c
@ -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");
|
||||||
|
|||||||
67
kernel/mem.c
67
kernel/mem.c
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
35
kernel/vm.c
35
kernel/vm.c
@ -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);
|
||||||
|
|||||||
20
lib/bribki.h
20
lib/bribki.h
@ -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;
|
||||||
}
|
}
|
||||||
37
lib/string.c
37
lib/string.c
@ -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)
|
||||||
|
|||||||
@ -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
19
proc.c
@ -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
11
proc.h
@ -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();
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
890
snake/map_data.h
890
snake/map_data.h
@ -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},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}};
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
|
||||||
}
|
|
||||||
|
|||||||
@ -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];
|
|
||||||
}
|
|
||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
149
snake/snake.c
149
snake/snake.c
@ -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;
|
||||||
|
|||||||
@ -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 */
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
24
syscall.h
24
syscall.h
@ -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);
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
14
tools/mkfs.c
14
tools/mkfs.c
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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());
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,3 +1 @@
|
|||||||
int main() {
|
int main() { return 1; }
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user