248 lines
5.9 KiB
C
248 lines
5.9 KiB
C
#include "color32.h"
|
|
#include "error.h"
|
|
#include "gl.h"
|
|
#include "image8.h"
|
|
#include "renderer.h"
|
|
#include "shader.h"
|
|
#include "skip.h"
|
|
#include "types.h"
|
|
#include "vertex_buffer.h"
|
|
#include "window.h"
|
|
#include <gl/gl.h>
|
|
#include <string.h>
|
|
#define GSA_NOMAIN
|
|
#include "gsa.h"
|
|
#include "gsa_input.h"
|
|
|
|
struct gsa_sprite sprites[256];
|
|
|
|
struct sw_image8 *_gfx;
|
|
struct sw_window *_win;
|
|
|
|
static struct sw_shaderprogram program;
|
|
|
|
static u32 vbo, vao;
|
|
|
|
struct render_vert {
|
|
f32 x, y, tx, ty;
|
|
};
|
|
|
|
sw_color32 palette[GSA_PALETTE_SIZE];
|
|
static f32 palette_gl[1024];
|
|
static u32 tex;
|
|
|
|
#define GSA_LOOP_STACK_SIZE 16
|
|
|
|
static bool (*loop_stack[GSA_LOOP_STACK_SIZE])();
|
|
static i8 loop_stack_i;
|
|
|
|
static struct sw_vertex_buffer *vertex_buffer;
|
|
|
|
int gsa_main(int argc, char *argv[]) {
|
|
(void)argc;
|
|
(void)argv;
|
|
i32 max_components;
|
|
u32 size;
|
|
u8 *data, *frag_data, *vert_data;
|
|
|
|
sw_log("Initialising GameSkunkAdvance v0.0");
|
|
sw_init(argc, argv);
|
|
|
|
sw_log("Grab data");
|
|
data = sw_skip_get(sw_skip_self, "gfx.png", &size);
|
|
_gfx = sw_image8_load_png_data(data, size);
|
|
|
|
vertex_buffer = sw_vertex_buffer_create(sizeof(struct render_vert));
|
|
|
|
memset(loop_stack, 0, sizeof(loop_stack));
|
|
loop_stack_i = -1;
|
|
|
|
_win = sw_window_create(sw_vec2i(304, 176), "Game Skunk Advance v0.0", 0);
|
|
|
|
glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &max_components);
|
|
sw_log("GL_MAX_VERTEX_UNIFORM_COMPONENTS: %i", max_components);
|
|
glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &max_components);
|
|
sw_log("GL_NUM_PROGRAM_BINARY_FORMATS: %i", max_components);
|
|
|
|
frag_data = sw_skip_get_string(sw_skip_self, "gsa_frag.glsl");
|
|
vert_data = sw_skip_get_string(sw_skip_self, "gsa_vert.glsl");
|
|
program = sw_shaderprogram_create(vert_data, 0, frag_data, 0, false);
|
|
|
|
memcpy(palette, _gfx->palette, sizeof(_gfx->palette));
|
|
glGenTextures(1, &tex);
|
|
glBindTexture(GL_TEXTURE_2D, tex);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTexImage2D(
|
|
GL_TEXTURE_2D,
|
|
0,
|
|
GL_R8,
|
|
4096,
|
|
4096,
|
|
0,
|
|
GL_RED,
|
|
GL_UNSIGNED_BYTE,
|
|
_gfx->_data
|
|
);
|
|
|
|
sw_log("setup gsa vao");
|
|
glGenVertexArrays(1, &vao);
|
|
glBindVertexArray(vao);
|
|
|
|
sw_log("setup gsa vbo");
|
|
glGenBuffers(1, &vbo);
|
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
glVertexAttribPointer(
|
|
glGetAttribLocation(program._program, "pos"),
|
|
2,
|
|
GL_FLOAT,
|
|
GL_FALSE,
|
|
sizeof(struct render_vert),
|
|
0
|
|
);
|
|
glVertexAttribPointer(
|
|
glGetAttribLocation(program._program, "tex_coord"),
|
|
2,
|
|
GL_FLOAT,
|
|
GL_FALSE,
|
|
sizeof(struct render_vert),
|
|
(void *)(2 * sizeof(float))
|
|
);
|
|
glEnableVertexAttribArray(glGetAttribLocation(program._program, "pos"));
|
|
glEnableVertexAttribArray(glGetAttribLocation(program._program, "tex_coord")
|
|
);
|
|
glBindVertexArray(0);
|
|
|
|
sw_log("gsa setup done");
|
|
init();
|
|
sw_window_add_renderer(_win, sw_renderer_create(0, 0, 0), _gsa_tick);
|
|
sw_window_run(_win);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void gsa_copy_palette_to(sw_color32 *dst) {
|
|
memcpy(dst, palette, sizeof(palette));
|
|
}
|
|
|
|
void gsa_copy_palette_from(sw_color32 *src) {
|
|
memcpy(palette, src, sizeof(palette));
|
|
}
|
|
|
|
void gsa_run_loop(bool (*loopfun)()) {
|
|
++loop_stack_i;
|
|
if(loop_stack_i >= GSA_LOOP_STACK_SIZE) {
|
|
sw_error("exceeded loop stack size");
|
|
}
|
|
loop_stack[loop_stack_i] = loopfun;
|
|
}
|
|
|
|
static void add_render_vert(f32 x, f32 y, f32 tx, f32 ty) {
|
|
struct render_vert v;
|
|
v.x = x;
|
|
v.y = y;
|
|
v.tx = tx;
|
|
v.ty = ty;
|
|
sw_vertex_buffer_add(vertex_buffer, &v);
|
|
}
|
|
|
|
static void rect(f32 x, f32 y, f32 w, f32 h, i16 tile, bool half) {
|
|
f32 tx, ty, ts;
|
|
f32 tilesize = half ? 8.f : 16.f;
|
|
|
|
tx = ((tile % 256) * tilesize) / 4096.f;
|
|
ty = ((tile / 256) * tilesize) / 4096.f;
|
|
ts = 1.f / (4096.f / tilesize);
|
|
|
|
add_render_vert(x, y, tx, ty);
|
|
add_render_vert(x + w, y, tx + ts, ty);
|
|
add_render_vert(x, y + h, tx, ty + ts);
|
|
add_render_vert(x + w, y, tx + ts, ty);
|
|
add_render_vert(x, y + h, tx, ty + ts);
|
|
add_render_vert(x + w, y + h, tx + ts, ty + ts);
|
|
}
|
|
|
|
static void update_palette_gl() {
|
|
int i;
|
|
for(i = 0; i < 256; ++i) {
|
|
palette_gl[i * 4 + 0] = sw_color32_get_rf(palette[i]);
|
|
palette_gl[i * 4 + 1] = sw_color32_get_gf(palette[i]);
|
|
palette_gl[i * 4 + 2] = sw_color32_get_bf(palette[i]);
|
|
palette_gl[i * 4 + 3] = sw_color32_get_af(palette[i]);
|
|
}
|
|
}
|
|
|
|
void _gsa_tick() {
|
|
i32 i, x, y, startx, starty, endx, endy, tcmult, tilesize;
|
|
|
|
_gsa_input_tick();
|
|
|
|
if(loop_stack_i == -1) {
|
|
tick();
|
|
} else {
|
|
if(!loop_stack[loop_stack_i]()) {
|
|
--loop_stack_i;
|
|
}
|
|
}
|
|
|
|
sw_vertex_buffer_clear(vertex_buffer);
|
|
|
|
for(i = 0; i < MAX_TILEMAPS; ++i) {
|
|
tcmult = maps[i].half_tile ? 2 : 1;
|
|
tilesize = maps[i].half_tile ? 8 : 16;
|
|
startx = maps[i].scrollx / tilesize;
|
|
starty = maps[i].scrolly / tilesize;
|
|
endx = i32_min(TILEMAP_MAX_SIZE, startx + 20 * tcmult);
|
|
endy = i32_min(TILEMAP_MAX_SIZE, starty + 12 * tcmult);
|
|
startx = i32_max(0, startx);
|
|
starty = i32_max(0, starty);
|
|
|
|
for(x = startx; x <= endx; ++x) {
|
|
for(y = starty; y <= endy; ++y) {
|
|
u16 tile = maps[i].tiles[x][y];
|
|
if(tile) {
|
|
rect(
|
|
x * tilesize - maps[i].scrollx,
|
|
y * tilesize - maps[i].scrolly,
|
|
tilesize,
|
|
tilesize,
|
|
tile,
|
|
maps[i].half_tile
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for(i = 0; i < MAX_SPRITES; ++i) {
|
|
if(sprites[i].tile > 0) {
|
|
rect(sprites[i].x, sprites[i].y, 16, 16, sprites[i].tile, false);
|
|
}
|
|
}
|
|
glClearColor(
|
|
sw_color32_get_rf(palette[0]),
|
|
sw_color32_get_gf(palette[0]),
|
|
sw_color32_get_bf(palette[0]),
|
|
sw_color32_get_af(palette[0])
|
|
);
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
glBindVertexArray(vao);
|
|
sw_shaderprogram_use(program);
|
|
glBindTexture(GL_TEXTURE_2D, tex);
|
|
|
|
/* TODO: only do when palette changed */
|
|
update_palette_gl();
|
|
glUniform4fv(
|
|
glGetUniformLocation(program._program, "palette"), 256, palette_gl
|
|
);
|
|
glBufferData(
|
|
GL_ARRAY_BUFFER,
|
|
sizeof(struct render_vert) * vertex_buffer->elem_count,
|
|
vertex_buffer->data,
|
|
GL_DYNAMIC_DRAW
|
|
);
|
|
glDrawArrays(GL_TRIANGLES, 0, vertex_buffer->elem_count);
|
|
glBindVertexArray(0);
|
|
/* glEnd(); */
|
|
}
|