diff --git a/game/Makefile b/game/Makefile new file mode 100644 index 00000000..9f884f90 --- /dev/null +++ b/game/Makefile @@ -0,0 +1,12 @@ +CC = i686-pc-toaru-gcc +CFLAGS = -march=core2 -std=c99 -O0 -I/afs/acm.uiuc.edu/user/lange7/toaru-toolchain/local/i686-pc-toaru/include/freetype2 + +.PHONY: all + +all: ../initrd/bin/game + +../initrd/bin/game: game + cp game ../initrd/bin/game + +game: main.c + ${CC} ${CFLAGS} -o game main.c ~/toaru-toolchain/local/i686-pc-toaru/lib/libfreetype.a diff --git a/game/game b/game/game new file mode 100755 index 00000000..1d9d12eb Binary files /dev/null and b/game/game differ diff --git a/game/main.c b/game/main.c new file mode 100644 index 00000000..b6936cad --- /dev/null +++ b/game/main.c @@ -0,0 +1,197 @@ +/* + * The ToAru Sample Game + */ + +#include +#include +#include +#include +#include +#include + +#if 1 +#include +#include FT_FREETYPE_H + + +FT_Library library; +FT_Face face; +#endif + +DEFN_SYSCALL0(getgraphicsaddress, 11); +DEFN_SYSCALL1(kbd_mode, 12, int); +DEFN_SYSCALL0(kbd_get, 13); + +typedef struct sprite { + uint16_t width; + uint16_t height; + uint32_t * bitmap; + uint32_t blank; +} sprite_t; + +#define GFX_W 1024 +#define GFX_H 768 +#define GFX_B 4 +#define GFX(x,y) frame_mem[GFX_W * (y) + (x)] +#define SPRITE(sprite,x,y) sprite->bitmap[sprite->width * (y) + (x)] + +uint32_t * gfx_mem; +uint32_t * frame_mem; +uint32_t gfx_size = GFX_B * GFX_H * GFX_W; +sprite_t * sprites[128]; + + +uint32_t rgb(uint8_t r, uint8_t g, uint8_t b) { + return (r * 0x10000) + (g * 0x100) + (b * 0x1); +} + +void flip() { + memcpy(gfx_mem, frame_mem, gfx_size); + memset(frame_mem, 0, gfx_size); +} + +void +load_sprite(sprite_t * sprite, char * filename) { + /* Open the requested binary */ + FILE * image = fopen(filename, "r"); + size_t image_size= 0; + + fseek(image, 0, SEEK_END); + image_size = ftell(image); + fseek(image, 0, SEEK_SET); + + /* Alright, we have the length */ + char * bufferb = malloc(image_size); + fread(bufferb, image_size, 1, image); + uint16_t x = 0; /* -> 212 */ + uint16_t y = 0; /* -> 68 */ + /* Get the width / height of the image */ + signed int *bufferi = (signed int *)((uintptr_t)bufferb + 2); + uint32_t width = bufferi[4]; + uint32_t height = bufferi[5]; + uint32_t row_width = (24 * width + 31) / 32 * 4; + /* Skip right to the important part */ + size_t i = bufferi[2]; + + sprite->width = width; + sprite->height = height; + sprite->bitmap = malloc(sizeof(uint32_t) * width * height); + printf("%d x %d\n", width, height); + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + if (i > image_size) return; + /* Extract the color */ + uint32_t color = bufferb[i + 3 * x] + + bufferb[i+1 + 3 * x] * 0x100 + + bufferb[i+2 + 3 * x] * 0x10000; + /* Set our point */ + sprite->bitmap[(height - y) * width + x] = color; + } + i += row_width; + } + free(bufferb); +} + +void draw_sprite(sprite_t * sprite, uint16_t x, uint16_t y) { + for (uint16_t _y = 0; _y < sprite->height; ++_y) { + for (uint16_t _x = 0; _x < sprite->width; ++_x) { + if (SPRITE(sprite,_x,_y) != sprite->blank) { + GFX(x + _x, y + _y) = SPRITE(sprite, _x, _y); + } + } + } +} + +void waitabit() { + int x = time(NULL); + while (time(NULL) < x + 1) { + // Do nothing. + } +} + +void draw_line(uint16_t x0, uint16_t x1, uint16_t y0, uint16_t y1, uint32_t color) { + int deltax = abs(x1 - x0); + int deltay = abs(y1 - y0); + int sx = (x0 < x1) ? 1 : -1; + int sy = (y0 < y1) ? 1 : -1; + int error = deltax - deltay; + while (1) { + GFX(x0, y0) = color; + if (x0 == x1 && y0 == y1) break; + int e2 = 2 * error; + if (e2 > -deltay) { + error -= deltay; + x0 += sx; + } + if (e2 < deltax) { + error += deltax; + y0 += sy; + } + } +} + + +int main(int argc, char ** argv) { + gfx_mem = (void *)syscall_getgraphicsaddress(); + frame_mem = malloc(sizeof(uint32_t) * 1024 * 768); + printf("Graphics memory is at %p, backbuffer is at %p.\n", gfx_mem, frame_mem); + + printf("Loading sprites...\n"); + sprites[0] = malloc(sizeof(sprite_t)); + load_sprite(sprites[0], "/bs.bmp"); + sprites[0]->blank = 0x0; + printf("Sprite is %d by %d\n", sprites[0]->width, sprites[0]->height); + printf("%x\n", sprites[0]->bitmap); + +#if 1 + printf("Initialzing Freetype...\n"); + int error = FT_Init_FreeType(&library); + if (error) { + printf("FreeType initialization returned %d.\n"); + return error; + } + printf("Loading DejaVu Sans font.\n"); + error = FT_New_Face(library, + "/etc/DejaVuSansMono.ttf", + 0, + &face); + if (error == FT_Err_Unknown_File_Format) { + printf("FT: Unknown format (%d).\n", FT_Err_Unknown_File_Format); + return error; + } else { + printf("FT: Something else went wrong. (%d)\n", error); + } +#endif + + + printf("\033[J\n"); + + syscall_kbd_mode(1); + + int playing = 1; + + while (playing) { + uint32_t c = 0; //0x72A0CF; /* A nice sky blue */ + for (uint16_t x = 0; x < 1024; ++x) { + for (uint16_t y = 0; y < 768; ++y) { + GFX(x,y) = c; + } + } + draw_sprite(sprites[0], rand() % 1000, rand() % 700); + flip(); + char ch = 0; + if ((ch = syscall_kbd_get())) { + switch (ch) { + case 113: + playing = 0; + default: + break; + } + } + } + + syscall_kbd_mode(0); + + return 0; +} diff --git a/initrd/etc/DejaVuSansMono.ttf b/initrd/etc/DejaVuSansMono.ttf new file mode 100644 index 00000000..899c7c1b Binary files /dev/null and b/initrd/etc/DejaVuSansMono.ttf differ diff --git a/kernel/core/fs/ext2_initrd.c b/kernel/core/fs/ext2_initrd.c index f396b0b2..1efd5850 100644 --- a/kernel/core/fs/ext2_initrd.c +++ b/kernel/core/fs/ext2_initrd.c @@ -326,6 +326,13 @@ ext2_get_inode_block( return ext2_get_block(inode->block[block]); } else if (block < 12 + (1024 << initrd_superblock->log_block_size) / sizeof(uint32_t)) { return ext2_get_block(*(uint32_t*)((uintptr_t)ext2_get_block(inode->block[12]) + (block - 12) * sizeof(uint32_t))); + } else if (block < 12 + 256 + 256 * 256) { + uint32_t a = block - 12; + uint32_t b = a - 256; + uint32_t c = b / 256; + uint32_t d = b - c * 256; + void * c_block = ext2_get_block(*(uint32_t *)((uintptr_t)ext2_get_block(inode->block[13]) + (c) * sizeof(uint32_t))); + return ext2_get_block(*(uint32_t *)((uintptr_t)c_block + (d) * sizeof(uint32_t))); } return NULL; } diff --git a/kernel/core/syscall.c b/kernel/core/syscall.c index a5f5326c..9fdee521 100644 --- a/kernel/core/syscall.c +++ b/kernel/core/syscall.c @@ -133,6 +133,57 @@ static int sys_fork() { return fork(); } +static int getgraphicsaddress() { + return (int)bochs_get_address(); +} + +static volatile char kbd_last = 0; + +static void kbd_direct_handler(char ch) { + kbd_last = ch; +} + +static int kbd_mode(int mode) { + if (mode == 0) { + if (keyboard_buffer_handler) { + keyboard_buffer_handler = NULL; + } + } else { + keyboard_buffer_handler = kbd_direct_handler; + } + return 0; +} + +static int kbd_get() { + char x = kbd_last; + kbd_last = 0; + return (int)x; +} + +static int seek(int fd, int offset, int whence) { + kprintf("[call from %d to seek %d to %d type %d]\n", getpid(), fd, offset, whence); + if (fd >= current_task->next_fd || fd < 0) { + return -1; + } + if (fd < 3) { + return 0; + } + kprintf("[current is %x]\n", current_task->descriptors[fd]->offset); + if (whence == 0) { + current_task->descriptors[fd]->offset = offset; + } else if (whence == 1) { + current_task->descriptors[fd]->offset += offset; + } else if (whence == 2) { + current_task->descriptors[fd]->offset = current_task->descriptors[fd]->length + offset; + } + kprintf("[now at %x]\n", current_task->descriptors[fd]->offset); + return current_task->descriptors[fd]->offset; +} + +static int stat(int fd, uint32_t * st) { + return 0; +} + /* * System Call Internals */ @@ -150,8 +201,13 @@ static uintptr_t syscalls[] = { (uintptr_t)&sys_fork, (uintptr_t)&getpid, (uintptr_t)&sys_sbrk, + (uintptr_t)&getgraphicsaddress, + (uintptr_t)&kbd_mode, + (uintptr_t)&kbd_get, + (uintptr_t)&seek, + (uintptr_t)&stat, }; -uint32_t num_syscalls = 11; +uint32_t num_syscalls = 16; void syscalls_install() { diff --git a/kernel/core/video/bochs.c b/kernel/core/video/bochs.c index 4fb35b90..9cc54d46 100644 --- a/kernel/core/video/bochs.c +++ b/kernel/core/video/bochs.c @@ -52,6 +52,11 @@ bochs_current_scroll() { return current_scroll; } +uintptr_t +bochs_get_address() { + return (uintptr_t)bochs_vid_memory; +} + void graphics_install_bochs() { outports(0x1CE, 0x00); diff --git a/kernel/include/syscall.h b/kernel/include/syscall.h index 75a6237f..770bcb09 100644 --- a/kernel/include/syscall.h +++ b/kernel/include/syscall.h @@ -71,6 +71,11 @@ DECL_SYSCALL1(wait, int *); DECL_SYSCALL1(sbrk, int); DECL_SYSCALL2(gettimeofday, void *, void *); +DECL_SYSCALL0(getgraphicsaddress); +DECL_SYSCALL1(kbd_mode, int); +DECL_SYSCALL0(kbd_get); +DECL_SYSCALL3(lseek, int, int, int); +DECL_SYSCALL2(fstat, int, void *); #endif diff --git a/kernel/include/system.h b/kernel/include/system.h index 762119d6..68c88a2e 100644 --- a/kernel/include/system.h +++ b/kernel/include/system.h @@ -287,6 +287,7 @@ extern void bochs_draw_line(uint16_t,uint16_t,uint16_t,uint16_t,uint32_t); extern int bochs_get_width(); extern int bochs_get_height(); extern void bochs_set_cell(int x, int y, char c); +extern uintptr_t bochs_get_address(); /* ANSI Terminal Escape Processor */ void ansi_put(char c); diff --git a/loader/ld.c b/loader/ld.c index 123b5fba..94b06957 100644 --- a/loader/ld.c +++ b/loader/ld.c @@ -39,20 +39,14 @@ int main(int argc_, char ** argv_) { /* ld stuff */ uintptr_t END = (uintptr_t)sbrk(0); if (END > DESTINATION) { - printf("Oh. Welcome back. Uh. I'm just going to kill myself now.\n"); return 2; } - printf("End of memory is 0x%x\n", END); - printf("We are, therefore, 0x%x bytes long.\n", END - SOURCE); - printf("I am moving myself to 0x%x", DESTINATION); - printf("So I want to sbrk(0x%x)\n", DESTINATION + (END - SOURCE) - SOURCE); sbrk(DESTINATION + (END - SOURCE) - SOURCE); argc = argc_; argv = argv_; memcpy((void *)DESTINATION, (void *)SOURCE, END - SOURCE); - printf("Jumping to 0x%x\n", (uintptr_t)&_main - SOURCE + DESTINATION); uintptr_t location = ((uintptr_t)&_main - SOURCE + DESTINATION); __asm__ __volatile__ ("jmp *%0" : : "m"(location)); @@ -61,8 +55,6 @@ int main(int argc_, char ** argv_) { int _main() { here: - printf("Oh, hello.\n"); - printf("0x%x\n", &&here); /* Process arguments */ if (argc < 2) usage(argc,argv); @@ -82,7 +74,6 @@ here: while (fread((void *)&garbage, 1, 1, binary) != 0) { ++binary_size; } - printf("Binary is %u bytes.\n", binary_size); fclose(binary); binary = fopen(argv[1], "r"); @@ -98,131 +89,24 @@ here: header->e_ident[1] != ELFMAG1 || header->e_ident[2] != ELFMAG2 || header->e_ident[3] != ELFMAG3) { - printf("Header magic is wrong!\n"); - printf("Are you sure this is a 32-bit ELF binary or object file?\n"); return 1; } - /* Let's print out some of the header information, shall we? */ - printf("\033[1mELF Header\033[0m\n"); - - /* File type */ - printf("[Type %d] ", header->e_type); - switch (header->e_type) { - case ET_NONE: - printf("No file type.\n"); - break; - case ET_REL: - printf("Relocatable file.\n"); - break; - case ET_EXEC: - printf("Executable file.\n"); - break; - case ET_DYN: - printf("Shared object file.\n"); - break; - case ET_CORE: - printf("Core file.\n"); - break; - default: - printf("(Unknown file type)\n"); - break; - } - - /* Machine Type */ - switch (header->e_machine) { - case EM_386: - printf("Intel x86\n"); - break; - default: - printf("Unknown machine: %d\n", header->e_machine); - break; - } - - /* Version == EV_CURRENT? */ - if (header->e_version == EV_CURRENT) { - printf("ELF version is 1, as it should be.\n"); - } - - /* Entry point in memory */ - printf("Binary entry point in virtual memory is at 0x%x\n", header->e_entry); - - /* Program header table offset */ - printf("Program header table is at +0x%x and one entry is 0x%x bytes.\n" - "There are %d total program headers.\n", - header->e_phoff, header->e_phentsize, header->e_phnum); - - /* Section header table offset */ - printf("Section header table is at +0x%x and one entry is 0x%x bytes.\n" - "There are %d total section headers.\n", - header->e_shoff, header->e_shentsize, header->e_shnum); - - /* Read the program headers */ - printf("\033[1mProgram Headers\033[0m\n"); - for (uint32_t x = 0; x < header->e_phentsize * header->e_phnum; x += header->e_phentsize) { - if (header->e_phoff + x > binary_size) { - printf("Tried to read beyond the end of the file.\n"); - return 1; - } - /* Grab the program header */ - Elf32_Phdr * phdr = (Elf32_Phdr *)((uintptr_t)binary_buf + (header->e_phoff + x)); - - /* Print the header type */ - switch (phdr->p_type) { - case PT_LOAD: - printf("[Loadable Segment]\n"); - break; - case PT_DYNAMIC: - printf("[Dynamic Loading Information]\n"); - break; - case PT_INTERP: - printf("[Interpreter Path]\n"); - break; - default: - printf("[Unused Segement]\n"); - break; - } - } - - /* Find the (hopefully two) string tables */ - printf("\033[1mString Tables\033[0m\n"); - uint32_t i = 0; - for (uint32_t x = 0; x < header->e_shentsize * header->e_shnum; x += header->e_shentsize) { - if (header->e_shoff + x > binary_size) { - printf("Tried to read beyond the end of the file.\n"); - return 1; - } - Elf32_Shdr * shdr = (Elf32_Shdr *)((uintptr_t)binary_buf + (header->e_shoff + x)); - if (shdr->sh_type != SHT_STRTAB) continue; - string_table[i] = (char *)((uintptr_t)binary_buf + shdr->sh_offset); - printf("Found a string table at 0x%x\n", shdr->sh_offset); - ++i; - if (i == 5) break; - } - /* Read the section headers */ - printf("\033[1mSection Headers\033[0m\n"); for (uint32_t x = 0; x < header->e_shentsize * header->e_shnum; x += header->e_shentsize) { if (header->e_shoff + x > binary_size) { - printf("Tried to read beyond the end of the file.\n"); return 1; } Elf32_Shdr * shdr = (Elf32_Shdr *)((uintptr_t)binary_buf + (header->e_shoff + x)); - printf("[%d] %s\n", shdr->sh_type, (char *)((uintptr_t)string_table[0] + shdr->sh_name)); - printf("Section starts at 0x%x and is 0x%x bytes long.\n", shdr->sh_offset, shdr->sh_size); if (shdr->sh_addr) { - printf("It [0x%x] should be loaded at 0x%x.\n", ((uintptr_t)header + shdr->sh_offset), shdr->sh_addr); memcpy((void *)shdr->sh_addr,(void *)((uintptr_t)header + shdr->sh_offset), shdr->sh_size); } } - printf("Done.\n"); - uintptr_t location = SOURCE; + uintptr_t location = header->e_entry; uintptr_t argc_ = (uintptr_t)&argc; __asm__ __volatile__ ( - "push $0\n" - "push $0\n" "push %2\n" "push %1\n" "push $0\n"