diff --git a/Makefile b/Makefile index 631447b..b72fd24 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -USER_PROGRAMS := pedicel.raw apex.raw -USER_FILES := wow.txt +USER_PROGRAMS := pedicel.raw apex.raw doom.raw +USER_FILES := wow.txt doom1.wad BUILDDIR := build ELFFILE := pepperk diff --git a/user/Makefile b/user/Makefile index 5844db3..3c9d766 100644 --- a/user/Makefile +++ b/user/Makefile @@ -1,18 +1,28 @@ CC := x86_64-elf-gcc CC_FLAGS := -ffreestanding -nostdlib -fno-pic -mno-red-zone -Ilibc +DOOM_CC_FLAGS := $(CC_FLAGS) -std=gnu11 LD := x86_64-elf-ld BUILDDIR := ../build LIBDIR := libc -all: pedicel apex +all: pedicel apex doom +.PHONY: pedicel pedicel: nasm -f bin pedicel.S -o $(BUILDDIR)/pedicel.raw +.PHONY: apex apex: $(CC) $(CC_FLAGS) -c apex.c -o $(BUILDDIR)/apex.o nasm -f elf64 $(LIBDIR)/crt0.S -o $(BUILDDIR)/crt0.o $(LD) -T $(LIBDIR)/linker.ld $(BUILDDIR)/crt0.o $(BUILDDIR)/apex.o -o $(BUILDDIR)/apex.elf - objcopy -O binary $(BUILDDIR)/apex.elf $(BUILDDIR)/apex.raw \ No newline at end of file + objcopy -O binary $(BUILDDIR)/apex.elf $(BUILDDIR)/apex.raw + +.PHONY: doom +doom: + $(CC) $(DOOM_CC_FLAGS) -c doom.c -o $(BUILDDIR)/doom.o + nasm -f elf64 $(LIBDIR)/crt0.S -o $(BUILDDIR)/crt0.o + $(LD) -T $(LIBDIR)/linker.ld $(BUILDDIR)/crt0.o $(BUILDDIR)/doom.o -o $(BUILDDIR)/doom.elf + objcopy -O binary $(BUILDDIR)/doom.elf $(BUILDDIR)/doom.raw \ No newline at end of file diff --git a/user/doom.c b/user/doom.c new file mode 100644 index 0000000..0b78dc5 --- /dev/null +++ b/user/doom.c @@ -0,0 +1,147 @@ +#define DOOM_IMPLEMENTATION +#include "PureDOOM.h" +#include +#include + +//We use a separate heap because malloc is not yet available in userspace. +#define DOOM_HEAP_START ((unsigned char*)0x00500000) +#define DOOM_HEAP_SIZE (24 * 1024 * 1024) //24mb + +static unsigned char* doom_heap_curr = DOOM_HEAP_START; +static unsigned char* doom_heap_end = DOOM_HEAP_START + DOOM_HEAP_SIZE; + +// The following functions are wrappers for system calls made for +// compatibility with puredoom's function signatures +static int doom_cstr_len(const char* str) +{ + int len = 0; + while (str && str[len]) len++; + return len; +} + +static void doom_print_cb(const char* str) +{ + int len = doom_cstr_len(str); + if (len > 0) { + write(1, str, len); + } +} + +static void* doom_open_cb(const char* filename, const char* mode) +{ + (void)mode; // open doesn't support flags/mode (yet) + int fd = open(filename, 0); + if (fd < 0) return 0; + return (void*)(intptr_t)(fd); +} + +static void doom_close_cb(void* handle) +{ + int fd = (int)(intptr_t)handle; + if (fd >= 0) { + close(fd); + } +} + +static int doom_read_cb(void* handle, void* buf, int count) +{ + int fd = (int)(intptr_t)handle; + if (fd < 0) return -1; + return read(fd, (char*)buf, count); +} + +static int doom_write_cb(void* handle, const void* buf, int count) +{ + int fd = (int)(intptr_t)handle; + if (fd < 0) return -1; + return (int)write(fd, (const char*)buf, count); +} + +static int doom_seek_cb(void* handle, int offset, doom_seek_t origin) +{ + int fd = (int)(intptr_t)handle; + if (fd < 0) return -1; + return seek(fd, offset, (int)origin); +} + +static int doom_tell_cb(void* handle) +{ + int fd = (int)(intptr_t)handle; + if (fd < 0) return -1; + return tell(fd); +} + +static int doom_eof_cb(void* handle) +{ + int fd = (int)(intptr_t)handle; + if (fd < 0) return 1; + return eof(fd); +} + +// Bump allocator (bump ptr until we're out of heap memory) +static void* doom_malloc_cb(int size) +{ + if (size <= 0) return 0; + + uintptr_t curr = (uintptr_t)doom_heap_curr; + + // 16-byte align allocated blocks + curr = (curr + 15ULL) & ~15ULL; + + if (curr + (uintptr_t)size > (uintptr_t)doom_heap_end) { + return 0; + } + + doom_heap_curr = (unsigned char*)(curr + (uintptr_t)size); + return (void*)curr; +} + +// No free +static void doom_free_cb(void* ptr) +{ + (void)ptr; +} + +static void doom_exit_cb(int code) +{ + exit(code); +} + +// To get path for the WAD file +static char* doom_getenv_cb(const char* var) +{ + static char home[] = "/"; + static char waddir[] = "/"; + + if (!var) return 0; + if (doom_strcmp(var, "HOME") == 0) return home; + if (doom_strcmp(var, "DOOMWADDIR") == 0) return waddir; + return 0; +} + +int main() +{ + char* argv[2] = {"doom", 0}; + + // Override default implementations + doom_set_print(doom_print_cb); + doom_set_malloc(doom_malloc_cb, doom_free_cb); + doom_set_file_io(doom_open_cb, + doom_close_cb, + doom_read_cb, + doom_write_cb, + doom_seek_cb, + doom_tell_cb, + doom_eof_cb); + doom_set_exit(doom_exit_cb); + doom_set_getenv(doom_getenv_cb); + + doom_init(1, argv, 0); + + while (true) + { + doom_force_update(); + const uint8_t* framebuffer = doom_get_framebuffer(4); + draw(framebuffer, 320, 200, 4); + } +} \ No newline at end of file