oh god oh god it hurts
This commit is contained in:
parent
f6592c109e
commit
a3e8265030
12
game/Makefile
Normal file
12
game/Makefile
Normal 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
|
197
game/main.c
Normal file
197
game/main.c
Normal 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;
|
||||
}
|
BIN
initrd/etc/DejaVuSansMono.ttf
Normal file
BIN
initrd/etc/DejaVuSansMono.ttf
Normal file
Binary file not shown.
@ -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;
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
118
loader/ld.c
118
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"
|
||||
|
Loading…
Reference in New Issue
Block a user