oh god oh god it hurts

This commit is contained in:
Kevin Lange 2011-04-29 19:54:07 -05:00
parent f6592c109e
commit a3e8265030
10 changed files with 285 additions and 118 deletions

12
game/Makefile Normal file
View File

@ -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

BIN
game/game Executable file

Binary file not shown.

197
game/main.c Normal file
View File

@ -0,0 +1,197 @@
/*
* The ToAru Sample Game
*/
#include <stdio.h>
#include <stdint.h>
#include <syscall.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#if 1
#include <ft2build.h>
#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;
}

Binary file not shown.

View File

@ -326,6 +326,13 @@ ext2_get_inode_block(
return ext2_get_block(inode->block[block]); return ext2_get_block(inode->block[block]);
} else if (block < 12 + (1024 << initrd_superblock->log_block_size) / sizeof(uint32_t)) { } 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))); 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; return NULL;
} }

View File

@ -133,6 +133,57 @@ static int sys_fork() {
return 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 * System Call Internals
*/ */
@ -150,8 +201,13 @@ static uintptr_t syscalls[] = {
(uintptr_t)&sys_fork, (uintptr_t)&sys_fork,
(uintptr_t)&getpid, (uintptr_t)&getpid,
(uintptr_t)&sys_sbrk, (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 void
syscalls_install() { syscalls_install() {

View File

@ -52,6 +52,11 @@ bochs_current_scroll() {
return current_scroll; return current_scroll;
} }
uintptr_t
bochs_get_address() {
return (uintptr_t)bochs_vid_memory;
}
void void
graphics_install_bochs() { graphics_install_bochs() {
outports(0x1CE, 0x00); outports(0x1CE, 0x00);

View File

@ -71,6 +71,11 @@ DECL_SYSCALL1(wait, int *);
DECL_SYSCALL1(sbrk, int); DECL_SYSCALL1(sbrk, int);
DECL_SYSCALL2(gettimeofday, void *, void *); 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 #endif

View File

@ -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_width();
extern int bochs_get_height(); extern int bochs_get_height();
extern void bochs_set_cell(int x, int y, char c); extern void bochs_set_cell(int x, int y, char c);
extern uintptr_t bochs_get_address();
/* ANSI Terminal Escape Processor */ /* ANSI Terminal Escape Processor */
void ansi_put(char c); void ansi_put(char c);

View File

@ -39,20 +39,14 @@ int main(int argc_, char ** argv_) {
/* ld stuff */ /* ld stuff */
uintptr_t END = (uintptr_t)sbrk(0); uintptr_t END = (uintptr_t)sbrk(0);
if (END > DESTINATION) { if (END > DESTINATION) {
printf("Oh. Welcome back. Uh. I'm just going to kill myself now.\n");
return 2; 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); sbrk(DESTINATION + (END - SOURCE) - SOURCE);
argc = argc_; argc = argc_;
argv = argv_; argv = argv_;
memcpy((void *)DESTINATION, (void *)SOURCE, END - SOURCE); 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); uintptr_t location = ((uintptr_t)&_main - SOURCE + DESTINATION);
__asm__ __volatile__ ("jmp *%0" : : "m"(location)); __asm__ __volatile__ ("jmp *%0" : : "m"(location));
@ -61,8 +55,6 @@ int main(int argc_, char ** argv_) {
int _main() { int _main() {
here: here:
printf("Oh, hello.\n");
printf("0x%x\n", &&here);
/* Process arguments */ /* Process arguments */
if (argc < 2) usage(argc,argv); if (argc < 2) usage(argc,argv);
@ -82,7 +74,6 @@ here:
while (fread((void *)&garbage, 1, 1, binary) != 0) { while (fread((void *)&garbage, 1, 1, binary) != 0) {
++binary_size; ++binary_size;
} }
printf("Binary is %u bytes.\n", binary_size);
fclose(binary); fclose(binary);
binary = fopen(argv[1], "r"); binary = fopen(argv[1], "r");
@ -98,131 +89,24 @@ here:
header->e_ident[1] != ELFMAG1 || header->e_ident[1] != ELFMAG1 ||
header->e_ident[2] != ELFMAG2 || header->e_ident[2] != ELFMAG2 ||
header->e_ident[3] != ELFMAG3) { 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; 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 */ /* 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) { for (uint32_t x = 0; x < header->e_shentsize * header->e_shnum; x += header->e_shentsize) {
if (header->e_shoff + x > binary_size) { if (header->e_shoff + x > binary_size) {
printf("Tried to read beyond the end of the file.\n");
return 1; return 1;
} }
Elf32_Shdr * shdr = (Elf32_Shdr *)((uintptr_t)binary_buf + (header->e_shoff + x)); 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) { 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); 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; uintptr_t argc_ = (uintptr_t)&argc;
__asm__ __volatile__ ( __asm__ __volatile__ (
"push $0\n"
"push $0\n"
"push %2\n" "push %2\n"
"push %1\n" "push %1\n"
"push $0\n" "push $0\n"