Compare commits

..

No commits in common. "07c0b102804e70264b5656b0c73a1c39f947eeff" and "49ce1a2d4579e698b5f850381c440980ac19979b" have entirely different histories.

54 changed files with 976 additions and 5210 deletions

View File

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

2
.gitignore vendored
View File

@ -9,11 +9,9 @@ tools/*
user/*
!user/*.*
user/*.o
snake/snake
.idea
cmake-build-debug
CMakeLists.txt
__pycache__
res.txt
vibing.txt

View File

@ -44,9 +44,7 @@ OBJECTS = ./kernel/kstart.o ./kernel.o ./console.o ./drivers/vga.o ./drivers/uar
./fs/fs.o ./drivers/ata.o ./lib/string.o ./proc.o ./drivers/pit.o ./kernel/vm.o
run: image.bin
qemu-system-i386 -drive format=raw,file=$< -serial mon:stdio -qmp unix:qemu-monitor-socket,server,nowait \
-audiodev pa,id=SAUND \
-machine pcspk-audiodev=SAUND
qemu-system-i386 -drive format=raw,file=$< -serial mon:stdio -qmp unix:qemu-monitor-socket,server,nowait
run-nox: image.bin
qemu-system-i386 -nographic -drive format=raw,file=$< -serial mon:stdio -qmp unix:qemu-monitor-socket,server,nowait
@ -108,7 +106,7 @@ debug-nox: image.bin
-ex "break _start" \
-ex "continue"
USERPROGS=./user/false ./user/greet ./user/div0 ./user/shout ./user/badputs ./user/bss ./user/player ./user/getc ./snake/snake
USERPROGS=./user/false ./user/greet ./user/div0 ./user/shout ./user/badputs ./user/bss
fs.img: ./kernel.bin ./tools/mkfs $(USERPROGS)
./tools/mkfs $@ $< $(USERPROGS)
@ -118,9 +116,6 @@ LDFLAGS=-m elf_i386
user/%: user/%.o user/crt.o
$(LD) $(LDFLAGS) -o $@ -Ttext 0x401000 $^
snake/snake: snake/snake.o user/crt.o
$(LD) $(LDFLAGS) -o $@ -Ttext 0x401000 $^
kernel.bin: $(OBJECTS)
$(LD) $(LDFLAGS) $(LDKERNELFLAGS) -o $@ -Ttext 0x80009000 $^

View File

@ -5,66 +5,74 @@
// bootmain() loads an ELF kernel image from the disk starting at
// sector 3 and then jumps to the kernel entry routine.
#include "drivers/port.h"
#include "elf.h"
#include "drivers/port.h"
#define SECTSIZE 512
typedef unsigned char uchar;
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");
}
void bootmain(void) {
void
bootmain(void)
{
Elf32_Ehdr *elf;
Elf32_Phdr *ph, *eph;
void (*entry)(void);
uchar *pa;
uchar* pa;
elf = (Elf32_Ehdr *)0x30000; // scratch space
elf = (Elf32_Ehdr*)0x30000; // scratch space
// Read 1st page off disk
readseg((uchar *)elf, 4096, 0);
readseg((uchar*)elf, 4096, 0);
// Is this an ELF executable?
if (elf->magic != ELF_MAGIC)
if(elf->magic != ELF_MAGIC)
return; // let bootasm.S handle error
// 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;
for (; ph < eph; ph++) {
pa = (uchar *)(ph->p_paddr & 0x0fffffff);
for(; ph < eph; ph++) {
pa = (uchar*)(ph->p_paddr & 0x0fffffff);
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);
}
// Call the entry point from the ELF header.
// Does not return!
entry = (void (*)(void))(elf->e_entry & 0x0fffffff);
entry = (void(*)(void))(elf->e_entry & 0x0fffffff);
entry();
}
void waitdisk(void) {
void
waitdisk(void)
{
// Wait for disk ready.
while ((port_byte_in(0x1F7) & 0xC0) != 0x40)
while((port_byte_in(0x1F7) & 0xC0) != 0x40)
;
}
static inline void insl(int port, void *addr, int cnt) {
asm volatile("cld; rep insl"
: "=D"(addr), "=c"(cnt)
: "d"(port), "0"(addr), "1"(cnt)
: "memory", "cc");
static inline void
insl(int port, void *addr, int cnt)
{
asm volatile("cld; rep insl" :
"=D" (addr), "=c" (cnt) :
"d" (port), "0" (addr), "1" (cnt) :
"memory", "cc");
}
// Read a single sector at offset into dst.
void readsect(void *dst, uint offset) {
void
readsect(void *dst, uint offset)
{
// Issue command.
waitdisk();
port_byte_out(0x1F2, 1); // count = 1
@ -76,13 +84,15 @@ void readsect(void *dst, uint offset) {
// Read data.
waitdisk();
insl(0x1F0, dst, SECTSIZE / 4);
insl(0x1F0, dst, SECTSIZE/4);
}
// Read 'count' bytes at 'offset' from kernel into physical address 'pa'.
// Might copy more than asked.
void readseg(uchar *pa, uint count, uint offset) {
uchar *epa;
void
readseg(uchar* pa, uint count, uint offset)
{
uchar* epa;
epa = pa + count;
@ -95,6 +105,6 @@ void readseg(uchar *pa, uint count, uint offset) {
// 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 load in increasing order.
for (; pa < epa; pa += SECTSIZE, offset++)
for(; pa < epa; pa += SECTSIZE, offset++)
readsect(pa, offset);
}

View File

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

View File

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

View File

@ -1,8 +1,8 @@
#include "gdt.h"
#include "x86.h"
#include "memlayout.h"
#include "../lib/string.h"
#include "kernel/mem.h"
#include "memlayout.h"
#include "x86.h"
#include <stdint.h>
@ -22,47 +22,27 @@ struct seg_desc_t {
uint8_t base_31_24; // High bits of segment base address
} __attribute__((packed));
#define SEG(type, base, lim, dpl) \
(struct seg_desc_t){((lim) >> 12) & 0xffff, \
(uint)(base) & 0xffff, \
((uint)(base) >> 16) & 0xff, \
type, \
1, \
dpl, \
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}
#define SEG(type, base, lim, dpl) (struct seg_desc_t) \
{ ((lim) >> 12) & 0xffff, (uint)(base) & 0xffff, \
((uint)(base) >> 16) & 0xff, type, 1, dpl, 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];
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_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);
}
struct gdt_desc_t {
uint16_t size;
void *ptr;
void* ptr;
} __attribute__((packed));
void load_gdt() {
@ -71,20 +51,20 @@ void load_gdt() {
struct gdt_desc_t gdt_desc;
gdt_desc.size = sizeof(seg_desc) - 1;
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));
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;
tss->ss0 = SEG_KDATA << 3;
tss->esp0 = (uint)esp;
// setting IOPL=0 in eflags *and* iomb beyond the tss segment limit
// 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));
}

View File

@ -19,9 +19,9 @@
#define SEG_UDATA 4
#define SEG_TSS 5
#define SEG_ASM(type, base, lim) \
.word(((lim) >> 12) & 0xffff), ((base) & 0xffff); \
.byte(((base) >> 16) & 0xff), (0x90 | (type)), \
#define SEG_ASM(type,base,lim) \
.word (((lim) >> 12) & 0xffff), ((base) & 0xffff); \
.byte (((base) >> 16) & 0xff), (0x90 | (type)), \
(0xC0 | (((lim) >> 28) & 0xf)), (((base) >> 24) & 0xff)
#define USER_BASE 0x400000 // 4 MB
@ -74,5 +74,5 @@ struct taskstate {
};
void load_gdt();
void switchuvm(struct taskstate *tss, void *esp, pde_t *pgdir);
void switchuvm(struct taskstate *tss, void* esp, pde_t *pgdir);
#endif

212
cpu/idt.c
View File

@ -1,13 +1,10 @@
#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 "gdt.h"
#include "memlayout.h"
#include "../syscall.h"
#include "../proc.h"
#include "../drivers/port.h"
#include "../console.h"
enum {
IDT_HANDLERS = 256,
@ -17,10 +14,10 @@ typedef struct {
uint16_t low_offset;
uint16_t selector;
uint8_t always0;
uint8_t type : 4;
uint8_t s : 1;
uint8_t dpl : 2;
uint8_t p : 1;
uint8_t type: 4;
uint8_t s: 1;
uint8_t dpl: 2;
uint8_t p: 1;
uint16_t high_offset;
} __attribute__((packed)) idt_gate_t;
@ -56,7 +53,7 @@ void init_idt() {
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",
[1] = "Debug",
[2] = "Non Maskable Interrupt",
@ -105,7 +102,7 @@ void trap(registers_t *r) {
}
if (r->int_no < 32) {
const char *msg = "Reserved";
const char* msg = "Reserved";
if (r->int_no < ARRLEN(exception_messages)) {
msg = exception_messages[r->int_no];
}
@ -121,139 +118,28 @@ void trap(registers_t *r) {
}
/* takes a ptr that is supposed to be from userspace. If it is not, we
* return 0, if it is a valid we return 1
* return 0, if it is a valid userspace pointer, we return the usable
* kernelspace pointer
*/
bool is_userspace_ptr_mapped(uint32_t ptr) {
if (ptr >= KERNBASE) {
return 0;
}
pde_t *pgdir = get_user_proc_page_directory();
if (!pgdir) {
return 0;
}
pde_t pde = pgdir[PDX(ptr)];
if ((pde & (PTE_P | PTE_U)) != (PTE_P | PTE_U)) {
return 0;
}
if (pde & PDE_PS) {
return 0;
}
pte_t *table = (pte_t *)P2V(PTE_ADDR(pde));
pte_t pte = table[PTX(ptr)];
if ((pte & (PTE_P | PTE_U)) != (PTE_P | PTE_U)) {
return 0;
}
return 1;
uint32_t is_userspace_ptr_mapped(uint32_t ptr) {
// todo: implement
return ptr;
}
static bool is_userspace_range_mapped(uint32_t ptr, uint32_t size) {
if (size == 0) {
return 1;
}
if (ptr >= KERNBASE) {
return 0;
}
uint32_t end = ptr + size - 1;
if (end < ptr || end >= KERNBASE) {
return 0;
}
uint32_t last_page = PGROUNDDOWN(end);
for (uint32_t addr = ptr;; addr = PGROUNDDOWN(addr) + PGSIZE) {
if (!is_userspace_ptr_mapped(addr)) {
return 0;
}
if (PGROUNDDOWN(addr) == last_page) {
return 1;
}
}
static void* get_userspace_cstr(uint32_t ptr) {
// todo: implement
return (void*)(ptr);
}
static bool is_userspace_cstr(uint32_t ptr) {
for (uint32_t addr = ptr;; addr++) {
if (addr == 0 || !is_userspace_ptr_mapped(addr)) {
return 0;
}
if (*(const char *)addr == '\0') {
return (void *)ptr;
}
}
}
static _Noreturn void userspace_panic(const char *msg) {
if (!vga_is_text_mode()) {
switch_to_text_mode();
vga_clear_screen();
}
printk(msg);
killproc();
}
static void handle_puts(uintptr_t s) {
if (!is_userspace_cstr(s)) {
userspace_panic("SYS_puts panic: page fault\n");
}
printk((const char *)s);
}
static void require_text_mode_for_userspace_text_syscall() {
if (!vga_is_text_mode()) {
userspace_panic("Userspace panic: text syscall in graphics mode\n");
}
}
static void handle_swap_frame(uintptr_t frame) {
enum {
VGA_GRAPHICS_FRAME_SIZE = VGA_GRAPHICS_WIDTH * VGA_GRAPHICS_HEIGHT,
};
if (vga_is_text_mode()) {
userspace_panic("Userspace panic: frame swap in text mode\n");
}
if (!is_userspace_range_mapped(frame, VGA_GRAPHICS_FRAME_SIZE)) {
userspace_panic("SYS_swap_frame panic: page fault\n");
}
uint8_t *video = (uint8_t *)(KERNBASE + 0xA0000);
uint8_t *user = (uint8_t *)frame;
for (uint32_t i = 0; i < VGA_GRAPHICS_FRAME_SIZE; i++) {
video[i] = user[i];
}
}
static void refill_keyboard_copy_buffer(void) {
size_t count = kbd_state_shrd.len;
if (count == 0) {
return;
}
cli();
size_t rem = KEYBOARD_INTERRUPT_BUF_CAP - kbd_state_shrd.copy_len;
size_t copying = rem < count ? rem : count;
memcpy(kbd_state_shrd.copy_buf, kbd_state_shrd.buf, copying);
kbd_state_shrd.len -= copying;
kbd_state_shrd.copy_len += copying;
sti();
}
static int handle_getc(void) {
if (kbd_can_take_from_copy_buffer()) {
return kbd_take_from_copy_buffer();
}
refill_keyboard_copy_buffer();
if (!kbd_can_take_from_copy_buffer()) {
static int handle_puts(const char* s) {
if (!s) {
return -1;
}
return kbd_take_from_copy_buffer();
printk(s);
return 0;
}
static void handle_syscall(registers_t *r) {
static void handle_syscall(registers_t* r) {
switch (r->eax) {
case SYS_exit:
if (r->ebx == 0) {
@ -263,51 +149,19 @@ static void handle_syscall(registers_t *r) {
}
killproc();
case SYS_greet:
require_text_mode_for_userspace_text_syscall();
printk("Hello world!\n");
r->eax = 0;
break;
case SYS_putc:
require_text_mode_for_userspace_text_syscall();
printk((const char[]){(char)r->ebx, '\0'});
printk((const char[]){r->ebx, '\0'});
r->eax = 0;
break;
case SYS_puts:
require_text_mode_for_userspace_text_syscall();
handle_puts(r->ebx);
r->eax = 0;
break;
case SYS_switch_to_text:
switch_to_text_mode();
r->eax = 0;
break;
case SYS_switch_to_graphics:
switch_to_graphics_mode();
r->eax = 0;
break;
case SYS_swap_frame:
handle_swap_frame(r->ebx);
r->eax = 0;
break;
case SYS_time_ms:
r->eax = get_uptime_ms();
break;
case SYS_halt:
asm volatile("hlt");
r->eax = 0;
break;
case SYS_getc:
r->eax = handle_getc();
break;
case SYS_set_beep:
if (r->ebx > MAX_BEEP_FREQUENCY_HZ) {
userspace_panic("Userspace panic: beep frequency out of range\n");
}
set_beep_frequency_hz(r->ebx);
r->eax = 0;
r->eax = handle_puts(get_userspace_cstr(r->ebx));
break;
default:
userspace_panic("Userspace panic: Unknown syscall\n");
printk("Unknown syscall\n");
r->eax = -1;
}
}
@ -335,7 +189,7 @@ static void init_pic() {
typedef struct {
uint16_t limit;
void *base;
void* base;
} __attribute__((packed)) idt_register_t;
static idt_register_t idt_reg;
@ -352,6 +206,10 @@ void load_idt() {
register_interrupt_handler(T_SYSCALL, handle_syscall);
}
void cli() { asm("cli"); }
void cli() {
asm("cli");
}
void sti() { asm("sti"); }
void sti() {
asm("sti");
}

View File

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

View File

@ -4,8 +4,8 @@
#define PGSIZE 0x1000
#define PHYSTOP 0x8000000 // 128 Mib
#define PGROUNDUP(sz) (((sz) + PGSIZE - 1) & ~(PGSIZE - 1))
#define PGROUNDDOWN(a) (((a)) & ~((uintptr_t)(PGSIZE - 1)))
#define PGROUNDUP(sz) (((sz)+PGSIZE-1) & ~(PGSIZE-1))
#define PGROUNDDOWN(a) (((a)) & ~((uintptr_t)(PGSIZE-1)))
#define NPDENTRIES 1024 // # directory entries per page directory
#define NPTENTRIES 1024 // # PTEs per page table
@ -17,8 +17,8 @@
#ifndef __ASSEMBLER__
#include <stdint.h>
#define V2P(a) (((uintptr_t)(a)) - KERNBASE)
#define P2V(a) ((void *)(((uintptr_t)(a)) + KERNBASE))
#define V2P(a) (((uintptr_t) (a)) - KERNBASE)
#define P2V(a) ((void *)(((uintptr_t) (a)) + KERNBASE))
// page directory index
#define PDX(va) (((uintptr_t)(va) >> PDXSHIFT) & PXMASK)

View File

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

View File

@ -19,8 +19,8 @@
static void ATA_wait_BSY();
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();
port_byte_out(0x1F6, 0xE0 | ((LBA >> 24) & 0xF));
port_byte_out(0x1F2, sector_count);
@ -31,7 +31,8 @@ void read_sectors_ATA_PIO(void *target_address, uint32_t LBA,
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_RDY();
for (int i = 0; i < 256; i++)
@ -40,8 +41,8 @@ void read_sectors_ATA_PIO(void *target_address, uint32_t LBA,
}
}
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();
port_byte_out(0x1F6, 0xE0 | ((LBA >> 24) & 0xF));
port_byte_out(0x1F2, sector_count);
@ -50,10 +51,12 @@ void write_sectors_ATA_PIO(uint32_t LBA, uint8_t sector_count,
port_byte_out(0x1F5, (uint8_t)(LBA >> 16));
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_RDY();
for (int i = 0; i < 256; i++) {
for (int i = 0; i < 256; i++)
{
port_long_out(0x1F0, bytes[i]);
}
}

View File

@ -1,5 +1,4 @@
#pragma once
#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);

View File

@ -4,420 +4,301 @@
borrowed bits from http://files.osdev.org/mirrors/geezer/osd/graphics/modes.c
*/
#include "cpu/memlayout.h"
#include "cpu/x86.h"
#include "cpu/memlayout.h"
#include "port.h"
#include "vga.h"
static vga_display_mode_t current_display_mode = VGA_DISPLAY_MODE_TEXT;
static inline char inb(int port) {
return port_byte_in(port);
}
static inline char inb(int port) { return port_byte_in(port); }
static inline void outb(int port, char data) {
port_byte_out(port, data);
}
static inline void outb(int port, char data) { port_byte_out(port, data); }
/* This is the standard 256-color palette, in 0xRRGGBB format. Of course the VGA
registers want 6 bits, not 8 per channel, so we do a bit of shifting when
setting the registers: much easier than writing down the values in 6-bit
form!
/* This is the standard 256-color palette, in 0xRRGGBB format. Of course the VGA registers want 6 bits, not 8 per channel, so we do a bit
of shifting when setting the registers: much easier than writing down the values in 6-bit form!
*/
int vga256_24bit[256] = {
0x000000, 0x0000a8, 0x00a800, 0x00a8a8, 0xa80000, 0xa800a8, 0xa85400,
0xa8a8a8, 0x545454, 0x5454fc, 0x54fc54, 0x54fcfc, 0xfc5454, 0xfc54fc,
0xfcfc54, 0xfcfcfc, 0x000000, 0x141414, 0x202020, 0x2c2c2c, 0x383838,
0x444444, 0x505050, 0x606060, 0x707070, 0x808080, 0x909090, 0xa0a0a0,
0xb4b4b4, 0xc8c8c8, 0xe0e0e0, 0xfcfcfc, 0x0000fc, 0x4000fc, 0x7c00fc,
0xbc00fc, 0xfc00fc, 0xfc00bc, 0xfc007c, 0xfc0040, 0xfc0000, 0xfc4000,
0xfc7c00, 0xfcbc00, 0xfcfc00, 0xbcfc00, 0x7cfc00, 0x40fc00, 0x00fc00,
0x00fc40, 0x00fc7c, 0x00fcbc, 0x00fcfc, 0x00bcfc, 0x007cfc, 0x0040fc,
0x7c7cfc, 0x9c7cfc, 0xbc7cfc, 0xdc7cfc, 0xfc7cfc, 0xfc7cdc, 0xfc7cbc,
0xfc7c9c, 0xfc7c7c, 0xfc9c7c, 0xfcbc7c, 0xfcdc7c, 0xfcfc7c, 0xdcfc7c,
0xbcfc7c, 0x9cfc7c, 0x7cfc7c, 0x7cfc9c, 0x7cfcbc, 0x7cfcdc, 0x7cfcfc,
0x7cdcfc, 0x7cbcfc, 0x7c9cfc, 0xb4b4fc, 0xc4b4fc, 0xd8b4fc, 0xe8b4fc,
0xfcb4fc, 0xfcb4e8, 0xfcb4d8, 0xfcb4c4, 0xfcb4b4, 0xfcc4b4, 0xfcd8b4,
0xfce8b4, 0xfcfcb4, 0xe8fcb4, 0xd8fcb4, 0xc4fcb4, 0xb4fcb4, 0xb4fcc4,
0xb4fcd8, 0xb4fce8, 0xb4fcfc, 0xb4e8fc, 0xb4d8fc, 0xb4c4fc, 0x000070,
0x1c0070, 0x380070, 0x540070, 0x700070, 0x700054, 0x700038, 0x70001c,
0x700000, 0x701c00, 0x703800, 0x705400, 0x707000, 0x547000, 0x387000,
0x1c7000, 0x007000, 0x00701c, 0x007038, 0x007054, 0x007070, 0x005470,
0x003870, 0x001c70, 0x383870, 0x443870, 0x543870, 0x603870, 0x703870,
0x703860, 0x703854, 0x703844, 0x703838, 0x704438, 0x705438, 0x706038,
0x707038, 0x607038, 0x547038, 0x447038, 0x387038, 0x387044, 0x387054,
0x387060, 0x387070, 0x386070, 0x385470, 0x384470, 0x505070, 0x585070,
0x605070, 0x685070, 0x705070, 0x705068, 0x705060, 0x705058, 0x705050,
0x705850, 0x706050, 0x706850, 0x707050, 0x687050, 0x607050, 0x587050,
0x507050, 0x507058, 0x507060, 0x507068, 0x507070, 0x506870, 0x506070,
0x505870, 0x000040, 0x100040, 0x200040, 0x300040, 0x400040, 0x400030,
0x400020, 0x400010, 0x400000, 0x401000, 0x402000, 0x403000, 0x404000,
0x304000, 0x204000, 0x104000, 0x004000, 0x004010, 0x004020, 0x004030,
0x004040, 0x003040, 0x002040, 0x001040, 0x202040, 0x282040, 0x302040,
0x382040, 0x402040, 0x402038, 0x402030, 0x402028, 0x402020, 0x402820,
0x403020, 0x403820, 0x404020, 0x384020, 0x304020, 0x284020, 0x204020,
0x204028, 0x204030, 0x204038, 0x204040, 0x203840, 0x203040, 0x202840,
0x2c2c40, 0x302c40, 0x342c40, 0x3c2c40, 0x402c40, 0x402c3c, 0x402c34,
0x402c30, 0x402c2c, 0x40302c, 0x40342c, 0x403c2c, 0x40402c, 0x3c402c,
0x34402c, 0x30402c, 0x2c402c, 0x2c4030, 0x2c4034, 0x2c403c, 0x2c4040,
0x2c3c40, 0x2c3440, 0x2c3040, 0x000000, 0x000000, 0x000000, 0x000000,
0x000000, 0x000000, 0x000000, 0x000000};
int vga256_24bit[256] = { 0x000000, 0x0000a8, 0x00a800, 0x00a8a8, 0xa80000, 0xa800a8, 0xa85400, 0xa8a8a8, 0x545454, 0x5454fc, 0x54fc54, 0x54fcfc, 0xfc5454, 0xfc54fc, 0xfcfc54, 0xfcfcfc, 0x000000, 0x141414, 0x202020, 0x2c2c2c, 0x383838, 0x444444, 0x505050, 0x606060, 0x707070, 0x808080, 0x909090, 0xa0a0a0, 0xb4b4b4, 0xc8c8c8, 0xe0e0e0, 0xfcfcfc, 0x0000fc, 0x4000fc, 0x7c00fc, 0xbc00fc, 0xfc00fc, 0xfc00bc, 0xfc007c, 0xfc0040, 0xfc0000, 0xfc4000, 0xfc7c00, 0xfcbc00, 0xfcfc00, 0xbcfc00, 0x7cfc00, 0x40fc00, 0x00fc00, 0x00fc40, 0x00fc7c, 0x00fcbc, 0x00fcfc, 0x00bcfc, 0x007cfc, 0x0040fc, 0x7c7cfc, 0x9c7cfc, 0xbc7cfc, 0xdc7cfc, 0xfc7cfc, 0xfc7cdc, 0xfc7cbc, 0xfc7c9c, 0xfc7c7c, 0xfc9c7c, 0xfcbc7c, 0xfcdc7c, 0xfcfc7c, 0xdcfc7c, 0xbcfc7c, 0x9cfc7c, 0x7cfc7c, 0x7cfc9c, 0x7cfcbc, 0x7cfcdc, 0x7cfcfc, 0x7cdcfc, 0x7cbcfc, 0x7c9cfc, 0xb4b4fc, 0xc4b4fc, 0xd8b4fc, 0xe8b4fc, 0xfcb4fc, 0xfcb4e8, 0xfcb4d8, 0xfcb4c4, 0xfcb4b4, 0xfcc4b4, 0xfcd8b4, 0xfce8b4, 0xfcfcb4, 0xe8fcb4, 0xd8fcb4, 0xc4fcb4, 0xb4fcb4, 0xb4fcc4, 0xb4fcd8, 0xb4fce8, 0xb4fcfc, 0xb4e8fc, 0xb4d8fc, 0xb4c4fc, 0x000070, 0x1c0070, 0x380070, 0x540070, 0x700070, 0x700054, 0x700038, 0x70001c, 0x700000, 0x701c00, 0x703800, 0x705400, 0x707000, 0x547000, 0x387000, 0x1c7000, 0x007000, 0x00701c, 0x007038, 0x007054, 0x007070, 0x005470, 0x003870, 0x001c70, 0x383870, 0x443870, 0x543870, 0x603870, 0x703870, 0x703860, 0x703854, 0x703844, 0x703838, 0x704438, 0x705438, 0x706038, 0x707038, 0x607038, 0x547038, 0x447038, 0x387038, 0x387044, 0x387054, 0x387060, 0x387070, 0x386070, 0x385470, 0x384470, 0x505070, 0x585070, 0x605070, 0x685070, 0x705070, 0x705068, 0x705060, 0x705058, 0x705050, 0x705850, 0x706050, 0x706850, 0x707050, 0x687050, 0x607050, 0x587050, 0x507050, 0x507058, 0x507060, 0x507068, 0x507070, 0x506870, 0x506070, 0x505870, 0x000040, 0x100040, 0x200040, 0x300040, 0x400040, 0x400030, 0x400020, 0x400010, 0x400000, 0x401000, 0x402000, 0x403000, 0x404000, 0x304000, 0x204000, 0x104000, 0x004000, 0x004010, 0x004020, 0x004030, 0x004040, 0x003040, 0x002040, 0x001040, 0x202040, 0x282040, 0x302040, 0x382040, 0x402040, 0x402038, 0x402030, 0x402028, 0x402020, 0x402820, 0x403020, 0x403820, 0x404020, 0x384020, 0x304020, 0x284020, 0x204020, 0x204028, 0x204030, 0x204038, 0x204040, 0x203840, 0x203040, 0x202840, 0x2c2c40, 0x302c40, 0x342c40, 0x3c2c40, 0x402c40, 0x402c3c, 0x402c34, 0x402c30, 0x402c2c, 0x40302c, 0x40342c, 0x403c2c, 0x40402c, 0x3c402c, 0x34402c, 0x30402c, 0x2c402c, 0x2c4030, 0x2c4034, 0x2c403c, 0x2c4040, 0x2c3c40, 0x2c3440, 0x2c3040, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000 };
/* VGA fonts aren't actually stored in the graphics card, they disappear when you change modes,
so we have to keep one here to restore when we switch back to text mode. */
static unsigned char g_8x16_font[4096] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD, 0x99, 0x81, 0x81, 0x7E, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7E, 0xFF, 0xDB, 0xFF, 0xFF, 0xC3, 0xE7, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7C, 0xFE, 0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0xE7, 0xE7, 0xE7, 0x99, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x99, 0xBD, 0xBD, 0x99, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x1E, 0x0E, 0x1A, 0x32, 0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x30, 0x30, 0x70, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7F, 0x63, 0x7F, 0x63, 0x63, 0x63, 0x63, 0x67, 0xE7, 0xE6, 0xC0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0xDB, 0x3C, 0xE7, 0x3C, 0xDB, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFE, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x06, 0x0E, 0x1E, 0x3E, 0xFE, 0x3E, 0x1E, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7F, 0xDB, 0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7C, 0xC6, 0x60, 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x6C, 0xFE, 0x6C, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7C, 0x7C, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x7C, 0x7C, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x7C, 0xC6, 0xC2, 0xC0, 0x7C, 0x06, 0x86, 0xC6, 0x7C, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xC2, 0xC6, 0x0C, 0x18, 0x30, 0x60, 0xC6, 0x86, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6C, 0x6C, 0x38, 0x76, 0xDC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xCE, 0xD6, 0xD6, 0xE6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7C, 0xC6, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0C, 0x1C, 0x3C, 0x6C, 0xCC, 0xFE, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0xFC, 0x0E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x60, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFE, 0xC6, 0x06, 0x06, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x0C, 0x78, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x0C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xDE, 0xDE, 0xDE, 0xDC, 0xC0, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0, 0xC0, 0xC2, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xF8, 0x6C, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xDE, 0xC6, 0xC6, 0x66, 0x3A, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xE6, 0x66, 0x6C, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xC6, 0xEE, 0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xDE, 0x7C, 0x0C, 0x0E, 0x00, 0x00,
0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x6C, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x60, 0x38, 0x0C, 0x06, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x6C, 0x38, 0x38, 0x6C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFE, 0xC6, 0x86, 0x0C, 0x18, 0x30, 0x60, 0xC2, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00,
0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xE0, 0x60, 0x60, 0x78, 0x6C, 0x66, 0x66, 0x66, 0x66, 0xDC, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1C, 0x0C, 0x0C, 0x3C, 0x6C, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xCC, 0x78, 0x00,
0x00, 0x00, 0xE0, 0x60, 0x60, 0x6C, 0x76, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x06, 0x00, 0x0E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, 0x00,
0x00, 0x00, 0xE0, 0x60, 0x60, 0x66, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFE, 0xD6, 0xD6, 0xD6, 0xD6, 0xD6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0x0C, 0x1E, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x76, 0x62, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x60, 0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x30, 0x30, 0xFC, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, 0xFE, 0x6C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0xF8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xCC, 0x18, 0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0E, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0E, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0E, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0, 0xC2, 0x66, 0x3C, 0x0C, 0x06, 0x7C, 0x00, 0x00,
0x00, 0x00, 0xCC, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0C, 0x18, 0x30, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6C, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xCC, 0xCC, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6C, 0x38, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x60, 0x60, 0x66, 0x3C, 0x0C, 0x06, 0x3C, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xC6, 0xC6, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x3C, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x00, 0xC6, 0xC6, 0x10, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
0x38, 0x6C, 0x38, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
0x18, 0x30, 0x60, 0x00, 0xFE, 0x66, 0x60, 0x7C, 0x60, 0x60, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x76, 0x36, 0x7E, 0xD8, 0xD8, 0x6E, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3E, 0x6C, 0xCC, 0xCC, 0xFE, 0xCC, 0xCC, 0xCC, 0xCC, 0xCE, 0x00, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xC6, 0xC6, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x30, 0x78, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xC6, 0xC6, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0x78, 0x00,
0x00, 0xC6, 0xC6, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00,
0x00, 0xC6, 0xC6, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x18, 0x3C, 0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60, 0x60, 0x60, 0xE6, 0xFC, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0xF8, 0xCC, 0xCC, 0xF8, 0xC4, 0xCC, 0xDE, 0xCC, 0xCC, 0xCC, 0xC6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0E, 0x1B, 0x18, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0x70, 0x00, 0x00,
0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0C, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x30, 0x60, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x30, 0x60, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x76, 0xDC, 0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
0x76, 0xDC, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xC0, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30, 0x60, 0xCE, 0x93, 0x06, 0x0C, 0x1F, 0x00, 0x00,
0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30, 0x66, 0xCE, 0x9A, 0x3F, 0x06, 0x0F, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0xF6, 0x06, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0xD8, 0xD8, 0xD8, 0xDC, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xC6, 0xFC, 0xC6, 0xC6, 0xFC, 0xC0, 0xC0, 0xC0, 0x00, 0x00,
0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0xFE, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFE, 0xC6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xD8, 0xD8, 0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xC0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7E, 0x18, 0x3C, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x6C, 0x6C, 0x6C, 0xEE, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1E, 0x30, 0x18, 0x0C, 0x3E, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xDB, 0xDB, 0xDB, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x06, 0x7E, 0xCF, 0xDB, 0xF3, 0x7E, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1C, 0x30, 0x60, 0x60, 0x7C, 0x60, 0x60, 0x60, 0x30, 0x1C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6C, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0F, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00,
0x00, 0xD8, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x70, 0x98, 0x30, 0x60, 0xC8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
/* VGA fonts aren't actually stored in the graphics card, they disappear when
you change modes, so we have to keep one here to restore when we switch back
to text mode. */
static unsigned char g_8x16_font[4096] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x81, 0xA5, 0x81, 0x81, 0xBD,
0x99, 0x81, 0x81, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xFF,
0xDB, 0xFF, 0xFF, 0xC3, 0xE7, 0xFF, 0xFF, 0x7E, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x6C, 0xFE, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7C, 0xFE,
0x7C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
0x3C, 0x3C, 0xE7, 0xE7, 0xE7, 0x99, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x3C, 0x7E, 0xFF, 0xFF, 0x7E, 0x18, 0x18, 0x3C,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C,
0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xE7, 0xC3, 0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x42, 0x42, 0x66, 0x3C, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x99, 0xBD,
0xBD, 0x99, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x1E, 0x0E,
0x1A, 0x32, 0x78, 0xCC, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3C, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x33, 0x3F, 0x30, 0x30, 0x30,
0x30, 0x70, 0xF0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x63,
0x7F, 0x63, 0x63, 0x63, 0x63, 0x67, 0xE7, 0xE6, 0xC0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0xDB, 0x3C, 0xE7, 0x3C, 0xDB, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFE, 0xF8,
0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0E,
0x1E, 0x3E, 0xFE, 0x3E, 0x1E, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xDB,
0xDB, 0xDB, 0x7B, 0x1B, 0x1B, 0x1B, 0x1B, 0x1B, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7C, 0xC6, 0x60, 0x38, 0x6C, 0xC6, 0xC6, 0x6C, 0x38, 0x0C, 0xC6,
0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFE, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C,
0x7E, 0x18, 0x18, 0x18, 0x18, 0x7E, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3C, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x7E, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x0C, 0xFE, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xFE, 0x60, 0x30, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0,
0xC0, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x28, 0x6C, 0xFE, 0x6C, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7C, 0x7C, 0xFE, 0xFE, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0x7C, 0x7C,
0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C,
0x6C, 0xFE, 0x6C, 0x6C, 0x6C, 0xFE, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x7C, 0xC6, 0xC2, 0xC0, 0x7C, 0x06, 0x86, 0xC6, 0x7C, 0x18,
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC2, 0xC6, 0x0C, 0x18,
0x30, 0x60, 0xC6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6C,
0x6C, 0x38, 0x76, 0xDC, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18,
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E,
0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x02, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xCE, 0xD6, 0xD6, 0xE6, 0xC6, 0xC6, 0x7C,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6,
0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7C, 0xC6, 0x06, 0x06, 0x3C, 0x06, 0x06, 0x06, 0xC6, 0x7C,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x1C, 0x3C, 0x6C, 0xCC, 0xFE,
0x0C, 0x0C, 0x0C, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC0,
0xC0, 0xC0, 0xFC, 0x0E, 0x06, 0x06, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x60, 0xC0, 0xC0, 0xFC, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC6, 0x06, 0x06, 0x0C, 0x18,
0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6,
0xC6, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x06, 0x06, 0x0C, 0x78,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00,
0x00, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
0x30, 0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0x0C, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xDE, 0xDE,
0xDE, 0xDC, 0xC0, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38,
0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x66, 0x66, 0x66, 0x66, 0xFC,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0xC2, 0xC0, 0xC0, 0xC0,
0xC0, 0xC2, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x6C,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6C, 0xF8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xFE,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x66, 0x62, 0x68, 0x78, 0x68,
0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66,
0xC2, 0xC0, 0xC0, 0xDE, 0xC6, 0xC6, 0x66, 0x3A, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x0C,
0x0C, 0x0C, 0x0C, 0x0C, 0xCC, 0xCC, 0xCC, 0x78, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xE6, 0x66, 0x6C, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0x66, 0xE6,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x60, 0x60, 0x60, 0x60, 0x60,
0x60, 0x62, 0x66, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xEE,
0xFE, 0xFE, 0xD6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0xC6, 0xC6,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xC6,
0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x66,
0x66, 0x66, 0x7C, 0x60, 0x60, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xDE, 0x7C,
0x0C, 0x0E, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x66, 0x66, 0x66, 0x7C, 0x6C,
0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6,
0xC6, 0x60, 0x38, 0x0C, 0x06, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7E, 0x7E, 0x5A, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6,
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6,
0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, 0xFE, 0x6C, 0x6C,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0x6C, 0x6C, 0x38, 0x38,
0x6C, 0x6C, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66,
0x66, 0x66, 0x3C, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFE, 0xC6, 0x86, 0x0C, 0x18, 0x30, 0x60, 0xC2, 0xC6, 0xFE,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x3C,
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00,
0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0C, 0x7C,
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x60,
0x60, 0x78, 0x6C, 0x66, 0x66, 0x66, 0x66, 0xDC, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x0C, 0x0C, 0x3C, 0x6C, 0xCC,
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60, 0x60, 0x60, 0xF0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xCC, 0xCC,
0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0xCC, 0x78, 0x00, 0x00, 0x00, 0xE0, 0x60,
0x60, 0x6C, 0x76, 0x66, 0x66, 0x66, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0E, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00, 0xE0, 0x60,
0x60, 0x66, 0x6C, 0x78, 0x78, 0x6C, 0x66, 0xE6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFE, 0xD6,
0xD6, 0xD6, 0xD6, 0xD6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x66, 0x66,
0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x76, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x7C, 0x0C, 0x0C, 0x1E, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xDC, 0x76, 0x62, 0x60, 0x60, 0x60, 0xF0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0xC6, 0x60,
0x38, 0x0C, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30,
0x30, 0xFC, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66,
0x66, 0x66, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xC6, 0xC6, 0xC6, 0xD6, 0xD6, 0xFE, 0x6C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0x6C, 0x38, 0x38, 0x38, 0x6C, 0xC6,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0xC6,
0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xFE, 0xCC, 0x18, 0x30, 0x60, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0E, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0E,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18,
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18,
0x18, 0x18, 0x0E, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 0xC6,
0xC6, 0xC6, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x66,
0xC2, 0xC0, 0xC0, 0xC0, 0xC2, 0x66, 0x3C, 0x0C, 0x06, 0x7C, 0x00, 0x00,
0x00, 0x00, 0xCC, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x00, 0x7C, 0xC6, 0xFE,
0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C,
0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xCC, 0xCC, 0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76,
0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0C, 0x7C,
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6C, 0x38,
0x00, 0x78, 0x0C, 0x7C, 0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3C, 0x66, 0x60, 0x60, 0x66, 0x3C, 0x0C, 0x06,
0x3C, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xFE,
0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6,
0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x7C, 0xC6, 0xFE, 0xC0, 0xC0, 0xC6, 0x7C,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18,
0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3C, 0x66,
0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C,
0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0x10, 0x38, 0x6C, 0xC6, 0xC6,
0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6C, 0x38, 0x00,
0x38, 0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
0x18, 0x30, 0x60, 0x00, 0xFE, 0x66, 0x60, 0x7C, 0x60, 0x60, 0x66, 0xFE,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x76, 0x36,
0x7E, 0xD8, 0xD8, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x6C,
0xCC, 0xCC, 0xFE, 0xCC, 0xCC, 0xCC, 0xCC, 0xCE, 0x00, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6C, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0x00, 0x7C, 0xC6, 0xC6,
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18,
0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x30, 0x78, 0xCC, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x76,
0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xCC, 0xCC, 0xCC,
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6,
0x00, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7E, 0x06, 0x0C, 0x78, 0x00,
0x00, 0xC6, 0xC6, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0xC6, 0x6C, 0x38,
0x00, 0x00, 0x00, 0x00, 0x00, 0xC6, 0xC6, 0x00, 0xC6, 0xC6, 0xC6, 0xC6,
0xC6, 0xC6, 0xC6, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x3C,
0x66, 0x60, 0x60, 0x60, 0x66, 0x3C, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6C, 0x64, 0x60, 0xF0, 0x60, 0x60, 0x60, 0x60, 0xE6, 0xFC,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x3C, 0x18, 0x7E, 0x18,
0x7E, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xCC, 0xCC,
0xF8, 0xC4, 0xCC, 0xDE, 0xCC, 0xCC, 0xCC, 0xC6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0E, 0x1B, 0x18, 0x18, 0x18, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18,
0xD8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0C, 0x7C,
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x18, 0x30,
0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x30, 0x60, 0x00, 0x7C, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x7C,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xCC, 0xCC, 0xCC,
0xCC, 0xCC, 0xCC, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC,
0x00, 0xDC, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
0x76, 0xDC, 0x00, 0xC6, 0xE6, 0xF6, 0xFE, 0xDE, 0xCE, 0xC6, 0xC6, 0xC6,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x6C, 0x6C, 0x3E, 0x00, 0x7E, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6C, 0x6C,
0x38, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xC0, 0xC6, 0xC6, 0x7C,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC0,
0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFE, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30, 0x60, 0xCE, 0x93, 0x06,
0x0C, 0x1F, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC2, 0xC6, 0xCC, 0x18, 0x30,
0x66, 0xCE, 0x9A, 0x3F, 0x06, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18,
0x00, 0x18, 0x18, 0x18, 0x3C, 0x3C, 0x3C, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x66, 0x33,
0x66, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44,
0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA,
0x55, 0xAA, 0x55, 0xAA, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77,
0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0xDD, 0x77, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x18, 0xF8,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
0x36, 0xF6, 0x06, 0xF6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x06, 0xF6,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0xF6, 0x06, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFE, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8, 0x18, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x37, 0x30, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xF7, 0x00, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xFF, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36,
0x36, 0xF7, 0x00, 0xF7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xFF, 0x00, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3F,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
0x18, 0x1F, 0x18, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x18, 0x1F, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0xFF, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1F, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0,
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x76, 0xDC, 0xD8, 0xD8, 0xD8, 0xDC, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xC6, 0xFC, 0xC6, 0xC6, 0xFC, 0xC0,
0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xC6, 0xC6, 0xC0, 0xC0, 0xC0,
0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0xFE, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFE, 0xC6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xC6, 0xFE,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0xD8, 0xD8,
0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x66, 0x66, 0x66, 0x66, 0x66, 0x7C, 0x60, 0x60, 0xC0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x18, 0x3C, 0x66, 0x66,
0x66, 0x3C, 0x18, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
0x6C, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0x6C, 0x38, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6C, 0xC6, 0xC6, 0xC6, 0x6C, 0x6C, 0x6C, 0x6C, 0xEE,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x30, 0x18, 0x0C, 0x3E, 0x66,
0x66, 0x66, 0x66, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7E, 0xDB, 0xDB, 0xDB, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x06, 0x7E, 0xCF, 0xDB, 0xF3, 0x7E, 0x60, 0xC0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x30, 0x60, 0x60, 0x7C, 0x60,
0x60, 0x60, 0x30, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C,
0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7E, 0x18,
0x18, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
0x18, 0x0C, 0x06, 0x0C, 0x18, 0x30, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0C, 0x00, 0x7E,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x1B, 0x1B, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0xD8, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDC, 0x00,
0x76, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6C, 0x6C,
0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0C, 0x0C,
0x0C, 0x0C, 0x0C, 0xEC, 0x6C, 0x6C, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00,
0x00, 0xD8, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x98, 0x30, 0x60, 0xC8, 0xF8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};
#define VGA 0x3C0
void write3C0(unsigned char index, unsigned char value) {
// get VGA port into index mode
inb(VGA + 0x1A);
// get VGA port into index mode
inb(VGA+0x1A);
outb(0x3C0, index);
outb(0x3C0, value);
}
void write3C2(unsigned char value) { outb(0x3C2, value); }
void write3C2(unsigned char value) {
outb(0x3C2, value);
}
void write3C4(unsigned char index, unsigned char value) {
outb(0x3C4, index);
@ -434,7 +315,9 @@ void write3D4(unsigned char index, unsigned char value) {
outb(0x3D5, value);
}
void write3C6(unsigned char value) { outb(0x3C6, value); }
void write3C6(unsigned char value) {
outb(0x3C6,value);
}
void vgaSetPalette(int index, int r, int g, int b) {
outb(0x3C8, index);
@ -444,10 +327,12 @@ void vgaSetPalette(int index, int r, int g, int b) {
}
void setdefaultVGApalette() {
for (int index = 0; index < 256; index++) {
for(int index=0;index<256;index++) {
int value = vga256_24bit[index];
vgaSetPalette(index, (value >> 18) & 0x3f, (value >> 10) & 0x3f,
(value >> 2) & 0x3f);
vgaSetPalette(index,
(value>>18)&0x3f,
(value>>10)&0x3f,
(value>>2)&0x3f);
}
}
@ -466,6 +351,7 @@ void vgaMode13() {
// see http://www.osdever.net/FreeVGA/vga/crtcreg.htm#11
write3D4(0x11, 0x0E);
write3D4(0x00, 0x5F);
write3D4(0x01, 0x4F);
write3D4(0x02, 0x50);
@ -520,11 +406,10 @@ void vgaMode13() {
write3C0(0x14, 0x00);
// enable display??
inb(VGA + 0x1A);
inb(VGA+0x1A);
outb(0x3C0, 0x20);
setdefaultVGApalette();
current_display_mode = VGA_DISPLAY_MODE_GRAPHICS;
}
void vgaMode3() {
@ -550,6 +435,7 @@ void vgaMode3() {
write3D4(0x06, 0xBF);
write3D4(0x07, 0x1F);
write3D4(0x08, 0x00);
write3D4(0x09, 0x4F);
write3D4(0x0A, 0x20);
@ -579,7 +465,7 @@ void vgaMode3() {
write3CE(0x07, 0x00);
write3CE(0x08, 0xFF);
inb(VGA + 0x1A);
inb(VGA+0x1A);
write3C0(0x00, 0x00);
write3C0(0x01, 0x01);
@ -603,6 +489,7 @@ void vgaMode3() {
write3C0(0x13, 0x08);
write3C0(0x14, 0x00);
write3C4(0x00, 0x01); // seq reset
write3C4(0x02, 0x04); // image plane 2
write3C4(0x04, 0x07); // disable odd/even in sequencer
@ -613,9 +500,9 @@ void vgaMode3() {
write3CE(0x05, 0x00); // odd/even disabled
write3CE(0x06, 0x00); // memory map select A0000h-BFFFFh
for (int i = 0; i < 4096; i += 16)
for (int j = 0; j < 16; j++)
((char *)KERNBASE + 0xa0000)[2 * i + j] = g_8x16_font[i + j];
for(int i=0;i<4096;i+=16)
for(int j=0;j<16;j++)
((char*)KERNBASE+0xa0000)[2*i+j] = g_8x16_font[i+j];
write3C4(0x00, 0x01); // seq reset
write3C4(0x02, 0x03); // image planes 0 and 1
@ -629,17 +516,6 @@ void vgaMode3() {
write3CE(0x05, 0x10); // odd/even enable
write3CE(0x06, 0x0E); // memory map select: 0xb8000
inb(VGA + 0x1A);
inb(VGA+0x1A);
outb(0x3C0, 0x20);
current_display_mode = VGA_DISPLAY_MODE_TEXT;
}
void switch_to_graphics_mode() { vgaMode13(); }
void switch_to_text_mode() { vgaMode3(); }
vga_display_mode_t vga_get_display_mode() { return current_display_mode; }
bool vga_is_text_mode() {
return current_display_mode == VGA_DISPLAY_MODE_TEXT;
}

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
#include "pit.h"
#include "../cpu/isr.h"
#include "port.h"
#include "../cpu/isr.h"
enum {
PIT_CRYSTAL_HZ = 1193182,
@ -23,18 +23,10 @@ enum {
PIT_MODES_SQUARE_WAVE_GENERATOR = 0x3,
PIT_MODES_SW_TRIGGERRED_STROBE = 0x4,
PIT_MODES_HW_TRIGGERRED_STROBE = 0x5,
PIT_COMMAND_PORT = 0x43,
PIT_CHANNEL0_DATA_PORT = 0x40,
PIT_CHANNEL2_DATA_PORT = 0x42,
PC_SPEAKER_PORT = 0x61,
};
// Wtf is that O_o
static timer_callback callbacks[100];
static int registered_callbacks = 0;
static volatile uint32_t uptime_ms = 0;
static volatile uint32_t speaker_frequency_hz = 0;
void add_timer_callback(timer_callback tc) {
callbacks[registered_callbacks++] = tc;
@ -53,7 +45,7 @@ struct pit_command_t {
unsigned char select_channel : 2;
} __attribute__((packed));
static void timer_int_callback(void);
static void dec_sleep_counter(void);
void init_pit() {
struct pit_command_t cmd = {
@ -62,60 +54,20 @@ void init_pit() {
.operating_mode = PIT_MODES_SQUARE_WAVE_GENERATOR,
.bcd = 0,
};
port_byte_out(PIT_COMMAND_PORT, *(unsigned char *)(&cmd));
port_byte_out(PIT_CHANNEL0_DATA_PORT, PIT_PROGRAM_REG & 0xff);
port_byte_out(PIT_CHANNEL0_DATA_PORT, (PIT_PROGRAM_REG & 0xff00) >> 8);
port_byte_out(0x43, *(unsigned char *)(&cmd));
port_byte_out(0x40, PIT_PROGRAM_REG & 0xff);
port_byte_out(0x40, (PIT_PROGRAM_REG & 0xff00) >> 8);
register_interrupt_handler(IRQ0, timer_interrupt_handler);
add_timer_callback(timer_int_callback);
add_timer_callback(dec_sleep_counter);
}
static volatile int sleep_counter = 0;
static void timer_int_callback(void) {
uptime_ms += 1000 / CLOCK_PRECISION_HZ;
static void dec_sleep_counter(void) {
sleep_counter--;
}
uint32_t get_uptime_ms(void) { return uptime_ms; }
void set_beep_frequency_hz(uint32_t frequency_hz) {
if (frequency_hz == 0) {
disable_beep();
return;
}
uint32_t divisor = PIT_CRYSTAL_HZ / frequency_hz;
if (divisor == 0) {
divisor = 1;
}
if (divisor > 0xffff) {
divisor = 0xffff;
}
struct pit_command_t cmd = {
.select_channel = PIT_SELECT_CHANNEL2,
.access_mode = PIT_ACCESS_MODE_LOHIBYTE,
.operating_mode = PIT_MODES_SQUARE_WAVE_GENERATOR,
.bcd = 0,
};
port_byte_out(PIT_COMMAND_PORT, *(unsigned char *)(&cmd));
port_byte_out(PIT_CHANNEL2_DATA_PORT, divisor & 0xff);
port_byte_out(PIT_CHANNEL2_DATA_PORT, (divisor & 0xff00) >> 8);
uint8_t speaker = port_byte_in(PC_SPEAKER_PORT);
port_byte_out(PC_SPEAKER_PORT, speaker | 0x03);
speaker_frequency_hz = frequency_hz;
}
void disable_beep(void) {
uint8_t speaker = port_byte_in(PC_SPEAKER_PORT);
port_byte_out(PC_SPEAKER_PORT, speaker & 0xfc);
speaker_frequency_hz = 0;
}
uint32_t get_beep_frequency_hz(void) { return speaker_frequency_hz; }
void msleep(int ms) {
sleep_counter = ms / 10;
while (sleep_counter > 0) {

View File

@ -1,16 +1,8 @@
#pragma once
#include <stdint.h>
#define MAX_BEEP_FREQUENCY_HZ 44100u
typedef void (*timer_callback)(void);
void init_pit(void);
void add_timer_callback(timer_callback tc);
uint32_t get_uptime_ms(void);
void set_beep_frequency_hz(uint32_t frequency_hz);
void disable_beep(void);
uint32_t get_beep_frequency_hz(void);
void msleep(int ms);

View File

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

View File

@ -9,35 +9,37 @@ enum {
void uartinit() {
// 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.
port_byte_out(COM1 + 3, 0x80); // Unlock divisor
port_byte_out(COM1 + 0, 115200 / 9600);
port_byte_out(COM1 + 1, 0);
port_byte_out(COM1 + 3, 0x03); // Lock divisor, 8 data bits.
port_byte_out(COM1 + 4, 0);
port_byte_out(COM1 + 1, 0x01); // Enable receive interrupts.
port_byte_out(COM1+3, 0x80); // Unlock divisor
port_byte_out(COM1+0, 115200/9600);
port_byte_out(COM1+1, 0);
port_byte_out(COM1+3, 0x03); // Lock divisor, 8 data bits.
port_byte_out(COM1+4, 0);
port_byte_out(COM1+1, 0x01); // Enable receive interrupts.
// If status is 0xFF, no serial port.
if (port_byte_in(COM1 + 5) == 0xFF)
if(port_byte_in(COM1+5) == 0xFF)
return;
uart = 1;
// Acknowledge pre-existing interrupt conditions;
// enable interrupts.
port_byte_in(COM1 + 2);
port_byte_in(COM1 + 0);
port_byte_in(COM1+2);
port_byte_in(COM1+0);
}
void uartputc(char c) {
void
uartputc(char c)
{
int i;
if (!uart)
return;
/* 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");
}
port_byte_out(COM1 + 0, c);
port_byte_out(COM1+0, c);
}

View File

@ -1,9 +1,9 @@
#include "vga.h"
#include "port.h"
#include "../lib/string.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 {
black = 0,
@ -32,13 +32,15 @@ unsigned vga_get_offset(unsigned col, unsigned row) {
return row * VGA_COLS + col;
}
unsigned vga_get_row_from_offset(unsigned offset) { return offset / VGA_COLS; }
unsigned vga_get_row_from_offset(unsigned offset) {
return offset / VGA_COLS;
}
void vga_set_cursor(unsigned offset) {
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_DATA_REGISTER, (unsigned char)(offset & 0xff));
port_byte_out(VGA_DATA_REGISTER, (unsigned char) (offset & 0xff));
}
unsigned vga_get_cursor() {
@ -62,15 +64,14 @@ void vga_clear_screen() {
}
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++) {
vga_set_char(vga_get_offset(col, 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();
while (*s != 0) {
if (*s == '\n') {

View File

@ -1,6 +1,5 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
enum {
@ -13,6 +12,8 @@ enum {
VGA_OFFSET_HIGH = 0x0e,
};
unsigned vga_get_cursor();
unsigned vga_get_row_from_offset(unsigned offset);
unsigned vga_get_offset(unsigned col, unsigned row);
@ -20,19 +21,7 @@ void vga_set_cursor(unsigned offset);
void vga_clear_screen();
void vga_set_char(unsigned offset, char c);
void vga_print_string(const char *s);
#define VGA_GRAPHICS_WIDTH 320
#define VGA_GRAPHICS_HEIGHT 200
typedef enum {
VGA_DISPLAY_MODE_TEXT = 0,
VGA_DISPLAY_MODE_GRAPHICS = 1,
} vga_display_mode_t;
void vga_print_string(const char* s);
void vgaMode13();
void vgaMode3();
void switch_to_graphics_mode();
void switch_to_text_mode();
vga_display_mode_t vga_get_display_mode();
bool vga_is_text_mode();

View File

@ -1,12 +1,12 @@
#include "fs.h"
#include "../drivers/ata.h"
#include "../lib/string.h"
#include "../drivers/ata.h"
enum {
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;
read_sectors_ATA_PIO(&dir, fs_start, 1);
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.
* At most (bufsize & -512) bytes will be read.
* 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 bytes_read = 0;
uint32_t file_sectors = (statbuf->size + sector_size - 1) / sector_size;

View File

@ -45,9 +45,9 @@ struct stat {
/* Find file by name and fill information in buf.
* 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.
* At most (bufsize & ~511) bytes will be read.
* Return number of bytes read or -1 on failure. */
int read_file(const struct stat *statbuf, void *buf, uint32_t bufsize);
int read_file(const struct stat *statbuf, void* buf, uint32_t bufsize);

View File

@ -1,36 +1,36 @@
#include "console.h"
#include "cpu/gdt.h"
#include "cpu/isr.h"
#include "cpu/gdt.h"
#include "cpu/memlayout.h"
#include "drivers/ata.h"
#include "drivers/keyboard.h"
#include "drivers/vga.h"
#include "drivers/ata.h"
#include "drivers/misc.h"
#include "drivers/pit.h"
#include "drivers/uart.h"
#include "drivers/vga.h"
#include "fs/fs.h"
#include "kernel/mem.h"
#include "lib/string.h"
#include "proc.h"
#include "kernel/mem.h"
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;
}
void graphtest() {
switch_to_graphics_mode();
vgaMode13();
for (int i = 0; i < 320; ++i) {
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);
switch_to_text_mode();
vgaMode3();
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;
while (1) {
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--;
}
} else if (keycode < keycodes) {
char ch = shift_pressed ? keysym_mapped_ascii_upper[keycode]
: keysym_mapped_ascii_lower[keycode];
char ch = shift_pressed ? keysym_mapped_ascii_upper[keycode] :
keysym_mapped_ascii_lower[keycode];
if (ch != 0) {
char haha[2] = {ch, 0};
printk(haha);
@ -76,15 +76,16 @@ void read_line_input(char *buf, size_t *ret_len, size_t cap) {
sti();
}
}
end:
end:
printk("\n");
*ret_len = len;
}
void kmain() {
freerange(P2V(3u << 20), P2V(4u << 20));
freerange(P2V(3u<<20), P2V(4u<<20));
kvmalloc(); // map all of physical memory at KERNBASE
freerange(P2V(4u << 20), P2V(PHYSTOP));
freerange(P2V(4u<<20), P2V(PHYSTOP));
load_gdt();
init_keyboard();
@ -105,9 +106,7 @@ void kmain() {
input[input_len] = 0;
printk(input);
printk("\n");
if (cstr_equal(input, "")) {
run_elf("snake");
} else if (cstr_equal(input, "halt")) {
if (cstr_equal(input, "halt")) {
printk("Bye\n");
qemu_shutdown();
} else if (cstr_equal(input, "work")) {
@ -118,7 +117,7 @@ void kmain() {
} else if (cstr_equal(input, "graphtest")) {
graphtest();
} else if (cstr_starts_with(input, "run ")) {
const char *cmd = input + 4;
const char* cmd = input + 4;
run_elf(cmd);
} else {
printk("unknown command, try: halt | run CMD\n");

View File

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

View File

@ -5,11 +5,11 @@
typedef uintptr_t pde_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 *kalloc(void);
void kfree(void *);
void* kalloc(void);
void kfree(void*);
pde_t *setupkvm();
void kvmalloc();

View File

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

View File

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

View File

@ -4,8 +4,8 @@
typedef unsigned size_t;
void memcpy(void *dst, const void *src, size_t size);
void kmemmove(char *dst, char *src, size_t size);
int strncmp(const char *s1, const char *s2, size_t size);
bool cstr_equal(const char *s1, const char *s2);
void memcpy(void*dst, const void *src, size_t size);
void kmemmove(char* dst, char* src, 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_starts_with(const char *A, const char *B);

29
proc.c
View File

@ -1,6 +1,4 @@
#include "proc.h"
#include "drivers/pit.h"
#include "drivers/vga.h"
struct context {
// matches the behavior of swtch()
@ -27,16 +25,13 @@ struct vm {
} vm;
void trapret();
void swtch(void **oldstack, void *newstack);
void swtch(void** oldstack, void* newstack);
pde_t *get_user_proc_page_directory() {
if (!vm.user_task) {
return 0;
}
return vm.user_task->pgdir;
}
void run_elf(const char *name) {
void run_elf(const char* name) {
struct stat statbuf;
if (stat(name, &statbuf) != 0) {
printk(name);
@ -47,27 +42,24 @@ void run_elf(const char *name) {
vm.user_task = kalloc();
}
// 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();
if (allocuvm(vm.user_task->pgdir, USER_BASE, USER_BASE + statbuf.size)) {
printk("Fail: out of memory\n");
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");
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(": file not found\n");
return;
}
Elf32_Ehdr *hdr = (void *)USER_BASE;
Elf32_Ehdr *hdr = (void*)USER_BASE;
struct kstack *u = &vm.user_task->stack;
memset(u, 0, sizeof(*u));
@ -91,12 +83,7 @@ void run_elf(const char *name) {
}
_Noreturn void killproc() {
void *task_stack;
disable_beep();
if (!vga_is_text_mode()) {
switch_to_text_mode();
vga_clear_screen();
}
void* task_stack;
switchkvm();
freevm(vm.user_task->pgdir);
sti();

11
proc.h
View File

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

View File

@ -1,39 +0,0 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
/* We still have beef with keyboard, even in userspace */
#define KEYCODE_SHIFT 42
#define KEYCODE_ENTER 28
#define KEYCODE_BACKSPACE 14
#define KEYCODE_SPACE 57
#define KEYCODE_ESCAPE 1
#define KEYCODE_A 30
#define KEYCODE_S 31
#define KEYCODE_D 32
#define KEYCODE_W 17
#define KEYCODE_Q 16
#define KEYCODE_ENTER 28
#define KEYCODE_LEFT 75
#define KEYCODE_RIGHT 77
#define KEYCODE_UP 72
#define KEYCODE_DOWN 80
#define KEYCODE_1 2
#define KEYCODE_2 3
bool is_keycode_for_press_left(uint8_t keycode) {
return keycode == KEYCODE_LEFT || keycode == KEYCODE_A;
}
bool is_keycode_for_press_right(uint8_t keycode) {
return keycode == KEYCODE_RIGHT || keycode == KEYCODE_D;
}
bool is_keycode_for_press_up(uint8_t keycode) {
return keycode == KEYCODE_UP || keycode == KEYCODE_W;
}
bool is_keycode_for_press_down(uint8_t keycode) {
return keycode == KEYCODE_DOWN || keycode == KEYCODE_S;
}

View File

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

View File

@ -1,72 +0,0 @@
#pragma once
#include "misc_utils.h"
typedef enum {
tile_empty = 0,
tile_apple = 1,
tile_wall = 2,
tile_wall_lr = 3,
tile_wall_l = 4,
tile_wall_r = 5,
tile_wall_lrt = 6,
tile_wall_lt = 7,
tile_wall_rt = 8,
tile_wall_lrb = 9,
tile_wall_lb = 10,
tile_wall_rb = 11,
tile_wall_lrtb = 12,
tile_wall_ltb = 13,
tile_wall_rtb = 14,
tile_wall_t = 15,
tile_wall_b = 16,
tile_wall_tb = 17,
tile_snake_l = 18,
tile_snake_r = 19,
tile_snake_t = 20,
tile_snake_b = 21,
tile_snake_bl = 22,
tile_snake_br = 23,
tile_snake_lb = 24,
tile_snake_rb = 25,
tile_snake_tl = 26,
tile_snake_tr = 27,
tile_snake_lt = 28,
tile_snake_rt = 29,
tile_pupa_m2_l = 30,
tile_pupa_m2_r = 31,
tile_pupa_m1_l = 32,
tile_pupa_m1_r = 33,
tile_pupa_0_l = 34,
tile_pupa_0_r = 35,
tile_pupa_p1_l = 36,
tile_pupa_p1_r = 37,
tile_pupa_p2_l = 38,
tile_pupa_p2_r = 39,
tile_pupa_m2_t = 40,
tile_pupa_m1_t = 41,
tile_pupa_0_t = 42,
tile_pupa_p1_t = 43,
tile_pupa_p2_t = 44,
tile_pupa_m2_b = 45,
tile_pupa_m1_b = 46,
tile_pupa_0_b = 47,
tile_pupa_p1_b = 48,
tile_pupa_p2_b = 49,
} tile_t;
#define WORLD_WIDTH 16
#define WORLD_HEIGHT 10
typedef struct {
const char *name;
tile_t map[WORLD_WIDTH][WORLD_HEIGHT];
} MapConfig;
#define PLAYABLE_MAPS_COUNT 8
typedef struct {
MapConfig maps[PLAYABLE_MAPS_COUNT];
} MapList;

View File

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

View File

@ -1,22 +0,0 @@
#pragma once
#include <stdint.h>
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, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 18, 19, 21, 22, 23, 23,
23, 22, 22, 24, 26, 28, 30, 29, 28, 27, 26, 27, 27, 27, 28, 26, 23, 21, 26,
26, 27, 27, 28, 28, 27, 27, 27, 28, 29, 30, 30, 30, 30, 29, 29, 29, 29, 29,
30, 29, 28, 27, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 30, 30, 31, 30, 30,
30, 30, 30, 30, 30, 30, 30, 29, 29, 17, 17, 18, 18, 19, 19, 19, 18, 18, 19,
21, 22, 23, 23, 22, 21, 21, 21, 21, 22, 22, 21, 19, 18, 20, 21, 21, 21, 22,
22, 22, 21, 21, 22, 23, 23, 24, 23, 23, 23, 22, 23, 23, 23, 23, 22, 22, 21,
22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 23, 23, 23, 23, 23,
23, 23, 23, 23, 22, 16, 17, 17, 17, 18, 17, 17, 17, 17, 18, 18, 19, 20, 20,
19, 19, 18, 19, 19, 19, 19, 18, 17, 17, 18, 18, 19, 19, 19, 19, 19, 19, 19,
19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 19, 19, 19, 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) { return VGA_GRAY_LUT[color]; }

View File

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

View File

@ -1,807 +0,0 @@
#include "../drivers/vga.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 <stdbool.h>
#include <stdint.h>
#define FRAME_SIZE (VGA_GRAPHICS_WIDTH * VGA_GRAPHICS_HEIGHT)
#define HUD_OFFSET 3
#define GLYPH_SPACING 3
#define FONT_SPACE_INDEX 0
#define FONT_DIGIT_BASE 1
#define FONT_LETTER_BASE (FONT_DIGIT_BASE + 10)
uint8_t frame[FRAME_SIZE] = {1};
#define SNAKE_GAMEMODE_MAX_APPLES 10
#define SNAKE_GAMEMODE_DEFAULT_APPLES 5
typedef enum {
game_screen_gaming,
game_screen_pause,
game_screen_select_map,
game_screen_select_apple_count,
} game_screen_t;
#define SNAKE_START_Y 2
#define SNAKE_START_HEAD_X 4
#define SNAKE_START_PUPA_X 6
typedef enum {
snake_direction_left = 0,
snake_direction_right = 1,
snake_direction_top = 2,
snake_direction_bottom = 3,
} snake_direction_t;
#define WALKING_ANIM_TIME_VERY_SLOW 600
#define HATCHING_ANIM_TIME_VERY_SLOW 400
#define WALKING_ANIM_TIME_SLOW 450
#define HATCHING_ANIM_TIME_SLOW 150
#define WALKING_ANIM_TIME_FAST 200
#define HATCHING_ANIM_TIME_FAST 40
#define WEIRD_SOUND 400
typedef enum {
waiting_reason_step,
waiting_reason_p1,
waiting_reason_p2,
waiting_reason_cross,
/* we go from cross pupa state to m1 pupa state through 'step',
* not through a separate animation target */
waiting_reason_m1,
waiting_reason_zero_pupa,
waiting_reason_postmortum,
} waiting_reason_t;
struct Snake {
bool is_space_pressed;
bool is_shift_pressed;
game_screen_t game_screen;
bool have_game;
/* from 0 to PLAYABLE_MAPS_COUNT - 1 */
int selected_map_index;
/* from 1 to SNAKE_GAMEMODE_MAX_APPLES, default is
* SNAKE_GAMEMODE_DEFAULT_APPLES */
int gamemode_apples_count;
RandomEngine r_eng;
tile_t world[WORLD_WIDTH][WORLD_HEIGHT];
uint8_t ghost_apples[WORLD_WIDTH][WORLD_HEIGHT];
ivec2 snake_head;
ivec2 snake_tail;
snake_direction_t cur_snake_direction;
snake_direction_t new_snake_direction;
/* 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
* just disappears after walking, moving back.
* When the pupa disappears this way, we enter 'awaiting postmortum' state,
* where nothing moves. If we are about to hit ourselves, we don't even
* move, we immediately draw one small splash and enter 'awaiting
* postmortum' state. There is no winning state, you just raise your score
* until you are dead.
*/
bool is_dying;
int score;
/* from -1 to PUDDLE_SPRITES - 1 (where -1 means there is no puddle) */
int puddle_sprite;
ivec2 puddle_center;
/* This stuff regulates game flow and animation progress */
waiting_reason_t waiting_reason;
uint32_t waiting_time; // Measures how much time we already accumulated
int animation_speed_boost;
} snake = {1};
void init_snake() {
snake.is_space_pressed = false;
snake.is_shift_pressed = false;
snake.game_screen = game_screen_pause;
snake.have_game = false;
snake.selected_map_index = 6;
snake.gamemode_apples_count = SNAKE_GAMEMODE_DEFAULT_APPLES;
snake.r_eng = (RandomEngine){.state = time_ms()};
/* snake_head and snake_pupa and snake.world
* and other gameplay-related variables will be initialized during
* map loading */
}
bool place_random_apple() {
for (int t = 0; t < 50; t++) {
uint32_t i = RandomEngine_rnd_interval(&snake.r_eng, 0,
WORLD_WIDTH * WORLD_HEIGHT);
if ((&snake.world[0][0])[i] == tile_empty) {
(&snake.world[0][0])[i] = tile_apple;
return true;
}
}
/* I had enough */
for (uint32_t i = 0; i < WORLD_WIDTH * WORLD_HEIGHT; i++) {
if ((&snake.world[0][0])[i] == tile_empty) {
(&snake.world[0][0])[i] = tile_apple;
return true;
}
}
return false;
}
void start_snake_game() {
snake.have_game = true;
snake.game_screen = game_screen_gaming;
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);
memset(&snake.ghost_apples, 0, sizeof(snake.ghost_apples));
for (int tx = SNAKE_START_HEAD_X; tx < SNAKE_START_PUPA_X; tx++) {
snake.world[tx][SNAKE_START_Y] = tile_snake_l;
}
snake.world[SNAKE_START_PUPA_X][SNAKE_START_Y] = tile_pupa_0_l;
snake.snake_head = (ivec2){SNAKE_START_HEAD_X, SNAKE_START_Y};
snake.snake_tail = (ivec2){SNAKE_START_PUPA_X, SNAKE_START_Y};
for (int app = 0; app < snake.gamemode_apples_count; app++) {
place_random_apple();
}
snake.new_snake_direction = snake.cur_snake_direction =
snake_direction_left;
snake.is_dying = false;
snake.score = 0;
snake.waiting_reason = waiting_reason_step;
snake.waiting_time = 0;
snake.animation_speed_boost = 0;
snake.puddle_sprite = -1;
}
void set_tile(ivec2 pos, tile_t val) {
check(0 <= pos.x && pos.x < WORLD_WIDTH && 0 <= pos.y &&
pos.y < WORLD_HEIGHT);
snake.world[pos.x][pos.y] = val;
}
tile_t get_tile(ivec2 pos) {
check(0 <= pos.x && pos.x < WORLD_WIDTH && 0 <= pos.y &&
pos.y < WORLD_HEIGHT);
return snake.world[pos.x][pos.y];
}
snake_direction_t get_opposite_direction(snake_direction_t x) {
if (x == snake_direction_left) {
return snake_direction_right;
} else if (x == snake_direction_right) {
return snake_direction_left;
} else if (x == snake_direction_top) {
return snake_direction_bottom;
} else {
return snake_direction_top;
}
}
ivec2 world_walk_direction(ivec2 v, snake_direction_t dir) {
if (dir == snake_direction_left) {
return (ivec2){v.x == 0 ? WORLD_WIDTH - 1 : v.x - 1, v.y};
} else if (dir == snake_direction_right) {
return (ivec2){v.x + 1 == WORLD_WIDTH ? 0 : v.x + 1, v.y};
} else if (dir == snake_direction_top) {
return (ivec2){v.x, v.y == 0 ? WORLD_HEIGHT - 1 : v.y - 1};
} else {
return (ivec2){v.x, v.y + 1 == WORLD_HEIGHT ? 0 : v.y + 1};
}
}
ivec2 get_puddle_center_for_contact(ivec2 head, snake_direction_t dir) {
ivec2 tile_pos = (ivec2){TILE_WIDTH * head.x, TILE_WIDTH * head.y};
if (dir == snake_direction_left || dir == snake_direction_right) {
tile_pos.y += TILE_WIDTH / 2;
} else if (dir == snake_direction_bottom) {
tile_pos.y += TILE_WIDTH;
}
if (dir == snake_direction_top || dir == snake_direction_bottom) {
tile_pos.x += TILE_WIDTH / 2;
} else if (dir == snake_direction_right) {
tile_pos.x += TILE_WIDTH;
}
return tile_pos;
}
/* takes snake tile, returns cardinal direction of snake origin */
snake_direction_t get_snake_origin_dir(tile_t tile) {
switch (tile) {
case tile_snake_l:
return snake_direction_right;
case tile_snake_r:
return snake_direction_left;
case tile_snake_t:
return snake_direction_bottom;
case tile_snake_b:
return snake_direction_top;
case tile_snake_bl:
return snake_direction_bottom;
case tile_snake_br:
return snake_direction_bottom;
case tile_snake_lb:
return snake_direction_left;
case tile_snake_rb:
return snake_direction_right;
case tile_snake_tl:
return snake_direction_top;
case tile_snake_tr:
return snake_direction_top;
case tile_snake_lt:
return snake_direction_left;
case tile_snake_rt:
return snake_direction_right;
default:
check(false);
}
}
tile_t construct_snake_tile(snake_direction_t from, snake_direction_t to) {
check(from != to);
if (from == snake_direction_left) {
if (to == snake_direction_right)
return tile_snake_r;
if (to == snake_direction_top)
return tile_snake_lt;
/* to bottom */
return tile_snake_lb;
}
if (from == snake_direction_right) {
if (to == snake_direction_left)
return tile_snake_l;
if (to == snake_direction_top)
return tile_snake_rt;
/* to bottom */
return tile_snake_rb;
}
if (from == snake_direction_top) {
if (to == snake_direction_left)
return tile_snake_tl;
if (to == snake_direction_right)
return tile_snake_tr;
/* to bottom */
return tile_snake_b;
}
if (from == snake_direction_bottom) {
if (to == snake_direction_left)
return tile_snake_bl;
if (to == snake_direction_right)
return tile_snake_br;
/* to top */
return tile_snake_t;
}
check(false);
}
tile_t construct_straight_snake_tile(snake_direction_t to) {
return construct_snake_tile(get_opposite_direction(to), to);
}
tile_t construct_zero_pupa(snake_direction_t to) {
if (to == snake_direction_left)
return tile_pupa_0_l;
if (to == snake_direction_right)
return tile_pupa_0_r;
if (to == snake_direction_top)
return tile_pupa_0_t;
if (to == snake_direction_bottom)
return tile_pupa_0_b;
check(false);
}
/* takes snake tile, returns it's target direction*/
snake_direction_t get_snake_destination(tile_t tile) {
switch (tile) {
case tile_snake_l:
return snake_direction_left;
case tile_snake_r:
return snake_direction_right;
case tile_snake_t:
return snake_direction_top;
case tile_snake_b:
return snake_direction_bottom;
case tile_snake_bl:
return snake_direction_left;
case tile_snake_br:
return snake_direction_right;
case tile_snake_lb:
return snake_direction_bottom;
case tile_snake_rb:
return snake_direction_bottom;
case tile_snake_tl:
return snake_direction_left;
case tile_snake_tr:
return snake_direction_right;
case tile_snake_lt:
return snake_direction_top;
case tile_snake_rt:
return snake_direction_top;
default:
check(false);
}
}
snake_direction_t get_zero_pupa_destination(tile_t tile) {
if (tile == tile_pupa_0_r)
return snake_direction_right;
if (tile == tile_pupa_0_l)
return snake_direction_left;
if (tile == tile_pupa_0_t)
return snake_direction_top;
if (tile == tile_pupa_0_b)
return snake_direction_bottom;
check(false);
}
bool is_tile_pupa(tile_t tile) {
if (tile == tile_pupa_0_r || tile == tile_pupa_0_l ||
tile == tile_pupa_0_b || tile == tile_pupa_0_t) {
return true;
}
return false;
}
void clear_frame(uint8_t color) {
for (uint32_t i = 0; i < FRAME_SIZE; i++) {
frame[i] = color;
}
}
void put_pixel(int x, int y, uint8_t color) {
if (x < 0 || x >= VGA_GRAPHICS_WIDTH || y < 0 || y >= VGA_GRAPHICS_HEIGHT) {
return;
}
frame[y * VGA_GRAPHICS_WIDTH + x] = color;
}
void draw_sprite(int dst_x, int dst_y, int sprite_width, int sprite_height,
const uint8_t *sprite) {
for (int x = 0; x < sprite_width; x++) {
for (int y = 0; y < sprite_height; y++) {
uint8_t color = sprite[x * sprite_height + y];
if (color != TRANSPARENCY_COLOR) {
put_pixel(dst_x + x, dst_y + y, color);
}
}
}
}
bool font_index_for_char(char ch, int *out_index) {
if (ch == ' ') {
*out_index = FONT_SPACE_INDEX;
return true;
}
if (ch >= '0' && ch <= '9') {
*out_index = FONT_DIGIT_BASE + (ch - '0');
return true;
}
if (ch >= 'A' && ch <= 'Z') {
*out_index = FONT_LETTER_BASE + (ch - 'A');
return true;
}
return false;
}
void draw_hud(const char *text) {
// int lines_count = 1;
int y0 = HUD_OFFSET;
for (const char *line_start = text; *line_start;) {
int glyph_count = 0;
const char *p = line_start;
for (; *p != '\n' && *p != 0; p++) {
glyph_count++;
}
if (glyph_count > 0) {
const int text_width =
glyph_count * FONT_WIDTH + (glyph_count - 1) * GLYPH_SPACING;
int x0 = VGA_GRAPHICS_WIDTH - HUD_OFFSET - text_width;
for (const char *q = line_start; q != p; q++) {
int glyph_index;
check(font_index_for_char(*q, &glyph_index));
draw_sprite(x0, y0, FONT_WIDTH, FONT_HEIGHT,
&sprite_data.font[glyph_index].tex[0][0]);
x0 += FONT_WIDTH + GLYPH_SPACING;
}
}
if (*p == 0) {
break;
}
line_start = p + 1;
y0 += FONT_HEIGHT + GLYPH_SPACING;
}
}
/* You see, we never store pupa hatching stage in world array.
* Instead, we store pupa 0 in world matrix and deduce the correct tile
* in draw_game_world using snake.waiting_reason
*/
tile_t correct_game_tile(tile_t x) {
/* waiting for p2 => we are in p1 */
if (snake.waiting_reason == waiting_reason_p2) {
if (x == tile_pupa_0_l)
return tile_pupa_p1_l;
if (x == tile_pupa_0_r)
return tile_pupa_p1_r;
if (x == tile_pupa_0_t)
return tile_pupa_p1_t;
if (x == tile_pupa_0_b)
return tile_pupa_p1_b;
}
/* waiting for cross => we are in p2 */
if (snake.waiting_reason == waiting_reason_cross) {
if (x == tile_pupa_0_l)
return tile_pupa_p2_l;
if (x == tile_pupa_0_r)
return tile_pupa_p2_r;
if (x == tile_pupa_0_t)
return tile_pupa_p2_t;
if (x == tile_pupa_0_b)
return tile_pupa_p2_b;
}
/* waiting for m1 => we are in m2 */
if (snake.waiting_reason == waiting_reason_m1) {
if (x == tile_pupa_0_l)
return tile_pupa_m2_l;
if (x == tile_pupa_0_r)
return tile_pupa_m2_r;
if (x == tile_pupa_0_t)
return tile_pupa_m2_t;
if (x == tile_pupa_0_b)
return tile_pupa_m2_b;
}
/* waiting for zero_pupa => we are in m1 */
if (snake.waiting_reason == waiting_reason_zero_pupa) {
if (x == tile_pupa_0_l)
return tile_pupa_m1_l;
if (x == tile_pupa_0_r)
return tile_pupa_m1_r;
if (x == tile_pupa_0_t)
return tile_pupa_m1_t;
if (x == tile_pupa_0_b)
return tile_pupa_m1_b;
}
/* When waiting postmortum, step or p1, pupa looks exactly the same
* (default is zero pupa) */
return x;
}
void draw_game_world() {
for (int tx = 0; tx < WORLD_WIDTH; tx++) {
for (int ty = 0; ty <= WORLD_HEIGHT; ty++) {
int iy = ty < WORLD_HEIGHT ? ty : 0;
tile_t tt = correct_game_tile(snake.world[tx][iy]);
if (tt == tile_empty)
continue;
check((uint8_t)tt < TILE_SPRITES);
draw_sprite(TILE_WIDTH * tx, TILE_WIDTH * ty - TILE_HEIGHT_OFFSET,
TILE_WIDTH, TILE_HEIGHT,
&sprite_data.tile[tt].tex[0][0]);
}
}
if (snake.game_screen != game_screen_gaming) {
for (uint32_t pix = 0; pix < FRAME_SIZE; pix++) {
frame[pix] = vga_to_gray(frame[pix]);
}
}
}
void draw_game_text() {
StringBuilder hud = {0};
if (snake.game_screen == game_screen_gaming) {
if (snake.waiting_reason == waiting_reason_postmortum) {
StringBuilder_append_cstr(&hud, "YOU DIED ");
} else if (snake.is_dying) {
StringBuilder_append_cstr(&hud, "LOL ");
}
// StringBuilder_append_u32(&hud, snake.animation_speed_boost);
// StringBuilder_append_cstr(&hud, " ");
StringBuilder_append_u32(&hud, snake.score);
} else if (snake.game_screen == game_screen_pause) {
if (snake.have_game) {
StringBuilder_append_cstr(&hud, "PAUSED\n");
}
StringBuilder_append_cstr(&hud, "PRESS 1 FOR NEW GAME\n");
if (snake.have_game) {
StringBuilder_append_cstr(&hud, "PRESS ESC TO CONTINUE\n");
}
StringBuilder_append_cstr(&hud, "PRESS Q TO QUIT\n");
} else if (snake.game_screen == game_screen_select_map) {
StringBuilder_append_cstr(&hud, "SELECT LEVEL\nCURRENTLY SELECTED\n");
check(snake.selected_map_index < PLAYABLE_MAPS_COUNT);
StringBuilder_append_cstr(&hud,
map_list.maps[snake.selected_map_index].name);
} else if (snake.game_screen == game_screen_select_apple_count) {
StringBuilder_append_cstr(&hud,
"SELECT DIFFICULTY\n"
"HOW MANY APPLES\nCURRENTLY SELECTED\n");
StringBuilder_append_u32(&hud, snake.gamemode_apples_count);
}
draw_hud(StringBuilder_get_cstr(&hud));
}
void draw_game_puddles() {
if (snake.puddle_sprite >= 0) {
const PuddleSprite *sprite = &sprite_data.puddle[snake.puddle_sprite];
draw_sprite(snake.puddle_center.x - PUDDLE_WIDTH / 2,
snake.puddle_center.y - PUDDLE_WIDTH / 2, PUDDLE_WIDTH,
PUDDLE_WIDTH, (&sprite->tex[0][0]));
}
}
void draw_frame() {
clear_frame(226);
if (snake.have_game) {
draw_game_puddles();
draw_game_world();
}
draw_game_text();
}
/* Called when game_screen is game_screen_gaming */
void handle_gaming_keycode(uint8_t keycode) {
if (keycode == KEYCODE_ESCAPE) {
snake.game_screen = game_screen_pause;
}
if (!snake.is_dying) {
if (is_keycode_for_press_left(keycode) &&
snake.cur_snake_direction != snake_direction_right) {
snake.new_snake_direction = snake_direction_left;
} else if (is_keycode_for_press_right(keycode) &&
snake.cur_snake_direction != snake_direction_left) {
snake.new_snake_direction = snake_direction_right;
} else if (is_keycode_for_press_up(keycode) &&
snake.cur_snake_direction != snake_direction_bottom) {
snake.new_snake_direction = snake_direction_top;
} else if (is_keycode_for_press_down(keycode) &&
snake.cur_snake_direction != snake_direction_top) {
snake.new_snake_direction = snake_direction_bottom;
}
}
}
/* return 1 if we are quitting */
int handle_incoming_keycode_after_halt(uint8_t keycode) {
if (keycode == KEYCODE_SPACE) {
snake.is_space_pressed = true;
} else if (keycode == (KEYCODE_SPACE | 0x80)) {
snake.is_space_pressed = false;
}
if (keycode == KEYCODE_SHIFT) {
snake.is_shift_pressed = true;
} else if (keycode == (KEYCODE_SHIFT | 0x80)) {
snake.is_shift_pressed = false;
}
if (keycode == KEYCODE_Q && snake.game_screen != game_screen_gaming) {
return 1;
}
if (snake.game_screen == game_screen_gaming) {
handle_gaming_keycode(keycode);
} else if (snake.game_screen == game_screen_pause) {
if (keycode == KEYCODE_1 ||
(keycode == KEYCODE_ENTER && !snake.have_game)) {
snake.game_screen = game_screen_select_map;
} else if (keycode == KEYCODE_ESCAPE && snake.have_game) {
snake.game_screen = game_screen_gaming;
}
} else if (snake.game_screen == game_screen_select_map) {
if (keycode == KEYCODE_ESCAPE) {
snake.game_screen = game_screen_pause;
} else if (is_keycode_for_press_left(keycode)) {
snake.selected_map_index--;
if (snake.selected_map_index < 0)
snake.selected_map_index = PLAYABLE_MAPS_COUNT - 1;
} else if (is_keycode_for_press_right(keycode)) {
snake.selected_map_index++;
if (snake.selected_map_index >= PLAYABLE_MAPS_COUNT)
snake.selected_map_index = 0;
} else if (keycode == KEYCODE_ENTER) {
snake.game_screen = game_screen_select_apple_count;
}
} else if (snake.game_screen == game_screen_select_apple_count) {
if (keycode == KEYCODE_ESCAPE) {
snake.game_screen = game_screen_select_map;
} else if (is_keycode_for_press_left(keycode)) {
if (snake.gamemode_apples_count > 1)
snake.gamemode_apples_count--;
} else if (is_keycode_for_press_right(keycode)) {
if (snake.gamemode_apples_count < SNAKE_GAMEMODE_MAX_APPLES)
snake.gamemode_apples_count++;
} else if (keycode == KEYCODE_ENTER) {
start_snake_game();
}
}
return 0;
}
/* Time flows only in gaming mode. This function can call frame drawing */
void handle_time_difference(uint32_t time_diff) {
if (snake.game_screen != game_screen_gaming)
return;
if (snake.waiting_reason == waiting_reason_postmortum)
return;
snake.waiting_time += time_diff;
uint32_t target_required_time;
if (snake.animation_speed_boost == 1) {
if (snake.waiting_reason == waiting_reason_step) {
target_required_time = WALKING_ANIM_TIME_FAST;
} else {
target_required_time = HATCHING_ANIM_TIME_FAST;
}
} else if (snake.animation_speed_boost == 0) {
if (snake.waiting_reason == waiting_reason_step) {
target_required_time = WALKING_ANIM_TIME_SLOW;
} else {
target_required_time = HATCHING_ANIM_TIME_SLOW;
}
} else {
if (snake.waiting_reason == waiting_reason_step) {
target_required_time = WALKING_ANIM_TIME_VERY_SLOW;
} else {
target_required_time = HATCHING_ANIM_TIME_VERY_SLOW;
}
}
if (snake.waiting_time > target_required_time) {
snake.waiting_time -= target_required_time;
if (snake.waiting_reason == waiting_reason_step) {
ivec2 tile_pos_ahead = world_walk_direction(
snake.snake_head, snake.new_snake_direction);
tile_t tile_ahead = get_tile(tile_pos_ahead);
/* Processing collisions */
if (tile_ahead == tile_apple) {
snake.ghost_apples[tile_pos_ahead.x][tile_pos_ahead.y] = 1;
snake.score += 5;
} else if (18 <= tile_ahead && tile_ahead <= 49) {
snake.waiting_reason = waiting_reason_postmortum;
snake.puddle_center = get_puddle_center_for_contact(
snake.snake_head, snake.new_snake_direction);
snake.puddle_sprite = 0;
return;
} else if (2 <= tile_ahead && tile_ahead <= 17) {
snake.is_dying = true;
snake.puddle_center = get_puddle_center_for_contact(
snake.snake_head, snake.new_snake_direction);
if (snake.puddle_sprite + 1 < PUDDLE_SPRITES) {
snake.puddle_sprite++;
}
}
/* normal stuff */
/* Step 1 */
ivec2 old_head_pos = snake.snake_head;
if (tile_ahead == tile_empty || tile_ahead == tile_apple) {
set_tile(tile_pos_ahead, construct_straight_snake_tile(
snake.new_snake_direction));
snake.snake_head = tile_pos_ahead;
}
/* Step 2 */
set_tile(old_head_pos,
construct_snake_tile(
get_opposite_direction(snake.cur_snake_direction),
snake.new_snake_direction));
snake.cur_snake_direction = snake.new_snake_direction;
/* Steps 3... */
if (is_tile_pupa(get_tile(snake.snake_tail))) {
/* Step 3a */
snake_direction_t 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);
/* Step 4a */
snake_direction_t 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;
/* WARNING: we updated snake_tail by moving pupa forward, we
* 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 we check for ghost apples. Clear ghost
// apples and enter p1-waiting state (instead of remaining in
// step awaiting state)
if (snake.snake_tail.x == snake.snake_head.x &&
snake.snake_tail.y == snake.snake_head.y) {
snake.waiting_reason = waiting_reason_postmortum;
return;
}
if (snake.ghost_apples[penultimate_pos.x][penultimate_pos.y]) {
snake.ghost_apples[penultimate_pos.x][penultimate_pos.y] =
0;
syscall(SYS_set_beep, WEIRD_SOUND);
snake.waiting_reason = waiting_reason_p1;
/* Nothing changed on screen because we need to wait even
* for the first stage of hatching.
* We could go to p1 immediately, though */
}
} else {
snake_direction_t tail_dir =
get_snake_destination(get_tile(snake.snake_tail));
set_tile(snake.snake_tail, construct_zero_pupa(tail_dir));
syscall(SYS_set_beep, WEIRD_SOUND);
snake.waiting_reason = waiting_reason_m1;
}
/* If we went with route 3a, pupa has moved and we definitely can
* place an apple. But if it had not and we went through route 3b,
* well, okay, we just won't have a free space for apple */
if (tile_ahead == tile_apple) {
place_random_apple();
}
} /* But there are more animation
targets that can finish, other than 'step' */
else if (snake.waiting_reason == waiting_reason_p1) {
snake.waiting_reason = waiting_reason_p2;
} else if (snake.waiting_reason == waiting_reason_p2) {
snake.waiting_reason = waiting_reason_cross;
} else if (snake.waiting_reason == waiting_reason_cross) {
/* Finished pupa hatching */
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));
syscall(SYS_set_beep, 0);
snake.waiting_reason = waiting_reason_step;
} else if (snake.waiting_reason == waiting_reason_m1) {
snake.waiting_reason = waiting_reason_zero_pupa;
} else if (snake.waiting_reason == waiting_reason_zero_pupa) {
/* Finished pupa regrowing */
syscall(SYS_set_beep, 0);
snake.waiting_reason = waiting_reason_step;
}
}
}
void after_awake_action(uint32_t time_diff) {
handle_time_difference(time_diff);
snake.animation_speed_boost = 0;
draw_frame();
syscall(SYS_swap_frame, (uintptr_t)frame);
}
int main(void) {
init_snake();
syscall(SYS_switch_to_graphics, 0);
uint32_t prev_time = time_ms();
while (1) {
/* Returned from halt, we can enjoy keyboard input and animation
* progress*/
for (int ch; (ch = syscall(SYS_getc, 0)) >= 0;) {
int ret = handle_incoming_keycode_after_halt((uint8_t)ch);
if (ret == 1)
goto quit;
}
/* As an additional benefit, we can check if is_space_pressed here */
if (snake.is_space_pressed) {
snake.animation_speed_boost = 1;
} else if (snake.is_shift_pressed) {
snake.animation_speed_boost = -1;
}
/* snake.is_time_sped_up will be relevant when checking animation end */
uint32_t current_time = time_ms();
after_awake_action(current_time - prev_time);
prev_time = current_time;
syscall(SYS_halt, 0);
}
quit:
syscall(SYS_switch_to_text, 0);
syscall(SYS_puts, (uintptr_t)"Quit from game\n");
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,37 +0,0 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
#define TRANSPARENCY_COLOR 47
#define TILE_WIDTH 20
#define TILE_HEIGHT 32
#define TILE_HEIGHT_OFFSET 12
typedef struct {
uint8_t tex[TILE_WIDTH][TILE_HEIGHT];
} TileSprite;
#define FONT_WIDTH 12
#define FONT_HEIGHT 21
typedef struct {
uint8_t tex[FONT_WIDTH][FONT_HEIGHT];
} FontSprite;
#define PUDDLE_WIDTH 40
typedef struct {
uint8_t tex[PUDDLE_WIDTH][PUDDLE_WIDTH];
} PuddleSprite;
#define TILE_SPRITES 50
#define FONT_SPRITES (1 + 10 + 26)
#define PUDDLE_SPRITES 5
typedef struct {
TileSprite tile[TILE_SPRITES];
FontSprite font[FONT_SPRITES];
PuddleSprite puddle[PUDDLE_SPRITES];
} SpriteData;

View File

@ -8,13 +8,6 @@ enum {
SYS_greet = 1,
SYS_putc = 2,
SYS_puts = 3,
SYS_switch_to_text = 4,
SYS_switch_to_graphics = 5,
SYS_swap_frame = 6,
SYS_time_ms = 7,
SYS_halt = 8,
SYS_getc = 9,
SYS_set_beep = 10,
};
int syscall(int call, uintptr_t arg);

View File

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

View File

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

View File

@ -2,7 +2,7 @@
#include <stdint.h>
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, 0x1bad1dea);
return 0;

View File

@ -3,13 +3,16 @@
int main();
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;
}
_Noreturn void _exit(int exit_status) {
_Noreturn
void _exit(int exit_status) {
syscall(SYS_exit, exit_status);
__builtin_unreachable();
}
void _start() { _exit(main()); }
void _start() {
_exit(main());
}

View File

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

View File

@ -1,18 +0,0 @@
#include "../snake/misc_utils.h"
#include "../syscall.h"
#include <stdint.h>
int main(void) {
while (1) {
int keycode = syscall(SYS_getc, 0);
if (keycode == -1) {
syscall(SYS_halt, 0);
continue;
}
StringBuilder sb = {0};
StringBuilder_append_u32(&sb, (uint32_t)keycode);
StringBuilder_putc(&sb, '\n');
syscall(SYS_puts, (uintptr_t)StringBuilder_get_cstr(&sb));
}
}

View File

@ -1,22 +0,0 @@
#include "../syscall.h"
#include <stdint.h>
static uint32_t time_ms(void) { return (uint32_t)syscall(SYS_time_ms, 0); }
static void wait_ms(uint32_t duration_ms) {
uint32_t start = time_ms();
while ((uint32_t)(time_ms() - start) < duration_ms) {
syscall(SYS_halt, 0);
}
}
int main(void) {
syscall(SYS_set_beep, 10000);
wait_ms(1000);
syscall(SYS_set_beep, 15000);
wait_ms(1000);
// syscall(SYS_set_beep, 0);
return 0;
}

View File

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