|
@@ -14,6 +14,9 @@
|
|
|
#define STR(x) STR2(x)
|
|
#define STR(x) STR2(x)
|
|
|
#define STR2(x) #x
|
|
#define STR2(x) #x
|
|
|
|
|
|
|
|
|
|
+#define COLOR(r, g, b) \
|
|
|
|
|
+ (((r) & 0x1F) << 11 | ((g) & 0x1F) << 6 | ((b) & 0x1F) << 1)
|
|
|
|
|
+
|
|
|
typedef struct {
|
|
typedef struct {
|
|
|
i32 key;
|
|
i32 key;
|
|
|
i32 downTime;
|
|
i32 downTime;
|
|
@@ -32,15 +35,21 @@ static GLuint vba = 0;
|
|
|
static GLuint texture = 0;
|
|
static GLuint texture = 0;
|
|
|
static int width = 0;
|
|
static int width = 0;
|
|
|
static int height = 0;
|
|
static int height = 0;
|
|
|
-static u8 pixels[HEIGHT][WIDTH][3] = {};
|
|
|
|
|
|
|
+static u16 pixels[HEIGHT][WIDTH] = {};
|
|
|
|
|
|
|
|
static ButtonData buttons[] = {
|
|
static ButtonData buttons[] = {
|
|
|
- [LEFT] = {0, 0, 0, "Left"}, [RIGHT] = {0, 0, 0, "Right"},
|
|
|
|
|
- [UP] = {0, 0, 0, "Up"}, [DOWN] = {0, 0, 0, "Down"},
|
|
|
|
|
- [SELECT] = {0, 0, 0, "Select"}, [START] = {0, 0, 0, "Start"},
|
|
|
|
|
- [A] = {0, 0, 0, "A"}, [B] = {0, 0, 0, "B"},
|
|
|
|
|
- [X] = {0, 0, 0, "X"}, [Y] = {0, 0, 0, "Y"},
|
|
|
|
|
- [L] = {0, 0, 0, "L"}, [R] = {0, 0, 0, "R"}};
|
|
|
|
|
|
|
+ [LEFT] = {GLFW_KEY_LEFT, 0, 0, "Left"},
|
|
|
|
|
+ [RIGHT] = {GLFW_KEY_RIGHT, 0, 0, "Right"},
|
|
|
|
|
+ [UP] = {GLFW_KEY_UP, 0, 0, "Up"},
|
|
|
|
|
+ [DOWN] = {GLFW_KEY_DOWN, 0, 0, "Down"},
|
|
|
|
|
+ [SELECT] = {GLFW_KEY_Z, 0, 0, "Select"},
|
|
|
|
|
+ [START] = {GLFW_KEY_X, 0, 0, "Start"},
|
|
|
|
|
+ [A] = {GLFW_KEY_A, 0, 0, "A"},
|
|
|
|
|
+ [B] = {GLFW_KEY_S, 0, 0, "B"},
|
|
|
|
|
+ [X] = {GLFW_KEY_Q, 0, 0, "X"},
|
|
|
|
|
+ [Y] = {GLFW_KEY_W, 0, 0, "Y"},
|
|
|
|
|
+ [L] = {GLFW_KEY_1, 0, 0, "L"},
|
|
|
|
|
+ [R] = {GLFW_KEY_2, 0, 0, "R"}};
|
|
|
static constexpr size_t BUTTONS = sizeof(buttons) / sizeof(ButtonData);
|
|
static constexpr size_t BUTTONS = sizeof(buttons) / sizeof(ButtonData);
|
|
|
|
|
|
|
|
// clang-format off
|
|
// clang-format off
|
|
@@ -51,11 +60,12 @@ static const GLchar* VERTEX_SHADER_CODE =
|
|
|
"out vec2 tex;\n"
|
|
"out vec2 tex;\n"
|
|
|
"void main(void) {\n"
|
|
"void main(void) {\n"
|
|
|
" tex = pos;\n"
|
|
" tex = pos;\n"
|
|
|
- " vec2 w = vec2(" STR(WIDTH) ", " STR(HEIGHT) ");\n"
|
|
|
|
|
- " ivec2 f = ivec2(size / w);\n"
|
|
|
|
|
- " f = ivec2(min(f.x, f.y), min(f.x, f.y));\n"
|
|
|
|
|
- " vec2 f2 = (f * w) / size;\n"
|
|
|
|
|
- " gl_Position = vec4(pos * f2, 0.0, 1.0);\n"
|
|
|
|
|
|
|
+ //" vec2 w = vec2(" STR(WIDTH) ", " STR(HEIGHT) ");\n"
|
|
|
|
|
+ //" ivec2 f = ivec2(size / w);\n"
|
|
|
|
|
+ //" f = ivec2(min(f.x, f.y), min(f.x, f.y));\n"
|
|
|
|
|
+ //" vec2 f2 = (f * w) / size;\n"
|
|
|
|
|
+ //" gl_Position = vec4(pos * f2, 0.0, 1.0);\n"
|
|
|
|
|
+ " gl_Position = vec4(pos, 0.0, 1.0);\n"
|
|
|
"}\n";
|
|
"}\n";
|
|
|
// clang-format on
|
|
// clang-format on
|
|
|
|
|
|
|
@@ -65,8 +75,8 @@ static const GLchar* FRAGMENT_SHADER_CODE =
|
|
|
"in vec2 tex;\n"
|
|
"in vec2 tex;\n"
|
|
|
"out vec4 color;\n"
|
|
"out vec4 color;\n"
|
|
|
"void main(void) {\n"
|
|
"void main(void) {\n"
|
|
|
- " vec2 c = (tex + vec2(1)) * 0.5;\n"
|
|
|
|
|
- " color = texture(image, vec2(c.x, 1 - c.y));\n"
|
|
|
|
|
|
|
+ " vec2 c = (tex + vec2(1.0)) * 0.5;\n"
|
|
|
|
|
+ " color = texture(image, vec2(c.x, 1.0 - c.y));\n"
|
|
|
"}\n";
|
|
"}\n";
|
|
|
|
|
|
|
|
static void onKeyEvent(GLFWwindow*, int key, int, int action, int) {
|
|
static void onKeyEvent(GLFWwindow*, int key, int, int action, int) {
|
|
@@ -101,11 +111,11 @@ static void tickButtons() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
i32 isButtonDown(Button b) {
|
|
i32 isButtonDown(Button b) {
|
|
|
- return buttons[b].isDown;
|
|
|
|
|
|
|
+ return b >= 0 && b < BUTTONS ? buttons[b].isDown : false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
i32 getButtonDownTime(Button b) {
|
|
i32 getButtonDownTime(Button b) {
|
|
|
- return buttons[b].downTime;
|
|
|
|
|
|
|
+ return b >= 0 && b < BUTTONS ? buttons[b].downTime : 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static Error checkShaderErrors(const char* name, GLuint shader) {
|
|
static Error checkShaderErrors(const char* name, GLuint shader) {
|
|
@@ -202,48 +212,46 @@ Error windowInit(const WindowSettings* ws) {
|
|
|
|
|
|
|
|
glGenTextures(1, &texture);
|
|
glGenTextures(1, &texture);
|
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
|
- glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, WIDTH, HEIGHT);
|
|
|
|
|
|
|
+ glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGB5_A1, WIDTH, HEIGHT);
|
|
|
glTextureParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTextureParameteri(texture, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
glTextureParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTextureParameteri(texture, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
|
+ glTextureParameteri(texture, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
|
|
|
+ glTextureParameteri(texture, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
|
return e;
|
|
return e;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void windowDestroy() {
|
|
void windowDestroy() {
|
|
|
- glDeleteBuffers(1, &vbo);
|
|
|
|
|
- glDeleteVertexArrays(1, &vba);
|
|
|
|
|
- glDeleteShader(vShader);
|
|
|
|
|
- glDeleteShader(fShader);
|
|
|
|
|
- glDeleteProgram(program);
|
|
|
|
|
|
|
+ if(vbo != 0) {
|
|
|
|
|
+ glDeleteBuffers(1, &vbo);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(vba != 0) {
|
|
|
|
|
+ glDeleteVertexArrays(1, &vba);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(vShader != 0) {
|
|
|
|
|
+ glDeleteShader(vShader);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(fShader != 0) {
|
|
|
|
|
+ glDeleteShader(fShader);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(program != 0) {
|
|
|
|
|
+ glDeleteProgram(program);
|
|
|
|
|
+ }
|
|
|
glfwDestroyWindow(window);
|
|
glfwDestroyWindow(window);
|
|
|
glfwTerminate();
|
|
glfwTerminate();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+bool windowExists() {
|
|
|
|
|
+ return window != nullptr;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
void windowNextFrame() {
|
|
void windowNextFrame() {
|
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
glViewport(0, 0, width, height);
|
|
glViewport(0, 0, width, height);
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glActiveTexture(GL_TEXTURE0);
|
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
|
- pixels[5][5][0] = 255;
|
|
|
|
|
- pixels[5][5][1] = 255;
|
|
|
|
|
- pixels[5][5][2] = 255;
|
|
|
|
|
- for(int x = 0; x < WIDTH; x++) {
|
|
|
|
|
- for(int y = 0; y < HEIGHT; y++) {
|
|
|
|
|
- pixels[y][x][0] = 255;
|
|
|
|
|
- pixels[y][x][1] = 255;
|
|
|
|
|
- pixels[y][x][2] = 255;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- for(int y = 0; y < HEIGHT; y++) {
|
|
|
|
|
- pixels[y][WIDTH / 2][0] = 128;
|
|
|
|
|
- pixels[y][WIDTH / 2][1] = 0;
|
|
|
|
|
- pixels[y][WIDTH / 2][2] = 255;
|
|
|
|
|
- }
|
|
|
|
|
- pixels[0][0][0] = 0;
|
|
|
|
|
- pixels[0][0][1] = 0;
|
|
|
|
|
- pixels[0][0][2] = 255;
|
|
|
|
|
|
|
|
|
|
- glTexSubImage2D(
|
|
|
|
|
- GL_TEXTURE_2D, 0, 0, 0, WIDTH, HEIGHT, GL_RGB, GL_UNSIGNED_BYTE,
|
|
|
|
|
|
|
+ glTextureSubImage2D(
|
|
|
|
|
+ texture, 0, 0, 0, WIDTH, HEIGHT, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1,
|
|
|
pixels);
|
|
pixels);
|
|
|
|
|
|
|
|
GLint size = glGetUniformLocation(program, "size");
|
|
GLint size = glGetUniformLocation(program, "size");
|
|
@@ -258,10 +266,24 @@ void windowNextFrame() {
|
|
|
|
|
|
|
|
auto i = glGetError();
|
|
auto i = glGetError();
|
|
|
if(i != 0) {
|
|
if(i != 0) {
|
|
|
- printf("GL-Error: %u\n", i);
|
|
|
|
|
|
|
+ fprintf(stderr, "GL-Error: %u\n", i);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool windowShouldClose() {
|
|
bool windowShouldClose() {
|
|
|
return glfwWindowShouldClose(window);
|
|
return glfwWindowShouldClose(window);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+void windowClear(Color c) {
|
|
|
|
|
+ for(int x = 0; x < WIDTH; x++) {
|
|
|
|
|
+ for(int y = 0; y < HEIGHT; y++) {
|
|
|
|
|
+ pixels[y][x] = c;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void windowSetPixel(i32 x, i32 y, Color c) {
|
|
|
|
|
+ if(y >= 0 && x >= 0 && y < HEIGHT && x < WIDTH) {
|
|
|
|
|
+ pixels[y][x] = c;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|