--- /dev/null
+RELEASE=0
+
+OBJ_FILES=\
+ build/sim.o
+
+ifeq (, $(shell which tcc))
+ CC=gcc
+else
+ifeq ($(RELEASE), 0)
+ CC=gcc
+else
+ CC=tcc
+endif
+endif
+
+INCLUDES=-I./include
+LIBS=-lGL -lglfw
+TARGET=./sim
+
+ifeq ($(RELEASE), 1)
+ FLAGS=-O3
+else
+ FLAGS=-g3
+endif
+
+build/%.o: src/%.c
+ $(CC) $(TIMEFLAG) $(FLAGS) -c $< -o $@ $(INCLUDES)
+
+$(TARGET): $(OBJ_FILES)
+ $(CC) $(TIMEFLAG) $(FLAGS) $(OBJ_FILES) -o $@ $(LIBS)
+
+clean:
+ rm -f $(OBJ_FILES) 2>&1 >/dev/null
+
+all: ./sim
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#include <GLES3/gl3.h>
+#include <GLFW/glfw3.h>
+
+#define WINDOW_WIDTH 1600
+#define WINDOW_HEIGHT 900
+#define WINDOW_TITLE "N-Body Simulation"
+
+void __attribute__((noreturn)) panic_and_die(char* msg, ...) {
+ puts("************ PANIC ************");
+
+ va_list va;
+ va_start(va, msg);
+ vprintf(msg, va);
+ va_end(va);
+
+ exit(1);
+}
+
+void glfw_key_handler(GLFWwindow* window, int key, int scancode, int action, int mods) {
+ if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
+ glfwSetWindowShouldClose(window, 1);
+}
+
+GLFWwindow* window;
+void init_opengl() {
+ if (!glfwInit()) panic_and_die("Failed to initalize GLFW.");
+
+ window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_TITLE, NULL, NULL);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
+ glfwMakeContextCurrent(window);
+
+ glfwSetKeyCallback(window, glfw_key_handler);
+}
+
+void deinit_opengl() {
+ glfwDestroyWindow(window);
+}
+
+void draw() {
+ glClearColor(1.0, 0.0, 1.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glfwSwapBuffers(window);
+}
+
+void loop() {
+ while (!glfwWindowShouldClose(window)) {
+ glfwPollEvents();
+
+ draw();
+ }
+}
+
+int main(int argc, char* argv[]) {
+ init_opengl();
+ loop();
+ deinit_opengl();
+}
\ No newline at end of file