diff --git a/include/glerminal.h b/include/glerminal.h index 97c9a1e..9d86275 100644 --- a/include/glerminal.h +++ b/include/glerminal.h @@ -35,7 +35,7 @@ void glerminal_flush(); * @param layer layer of the cell in the range [0, 8) * @param sprite sprite's index in the range [0, 256) */ -void glerminal_set(unsigned char x, unsigned char y, unsigned char layer, unsigned char sprite); +void glerminal_set(unsigned char x, unsigned char y, unsigned char layer, unsigned short sprite); /** * @brief Get a cell's sprite * @param x position of the cell in the range [0, 40) @@ -43,7 +43,7 @@ void glerminal_set(unsigned char x, unsigned char y, unsigned char layer, unsign * @param layer layer of the cell in the range [0, 8) * @return sprite index currently assigned to the cell */ -unsigned char glerminal_get(unsigned char x, unsigned char y, unsigned char layer); +unsigned char glerminal_get(unsigned char x, unsigned char y, unsigned short layer); /** * @brief Set a cell's offset * @param x position of the cell in the range [0, 40) diff --git a/source/glerminal-main.cpp b/source/glerminal-main.cpp index ed4ba79..233c798 100644 --- a/source/glerminal-main.cpp +++ b/source/glerminal-main.cpp @@ -41,7 +41,7 @@ namespace const unsigned char x = luaL_checkinteger(L, 1) - 1; const unsigned char y = luaL_checkinteger(L, 2) - 1; const unsigned char layer = luaL_checkinteger(L, 3) - 1; - const unsigned char sprite = luaL_checkinteger(L, 4) - 1; + const unsigned short sprite = luaL_checkinteger(L, 4) - 1; glerminal_set(x, y, layer, sprite); return 0; @@ -108,31 +108,50 @@ namespace { nullptr, nullptr } }; + int message_handler(lua_State* L) + { + const char* error_message = lua_tostring(L, -1); + + luaL_traceback(L, L, error_message, 0); + + const char* err = lua_tostring(L, -1); + + lua_remove(L, -2); + + return true; + } + lua_State* L; void init() { + lua_pushcfunction(L, message_handler); + const int handler = lua_gettop(L); lua_getglobal(L, "glerminal"); lua_getfield(L, -1, "init"); lua_remove(L, -2); - if (lua_pcall(L, 0, 0, 0) != LUA_OK) + if (lua_pcall(L, 0, 0, handler) != LUA_OK) { - // ignore error for now + std::cout << lua_tostring(L, -1) << std::endl; lua_pop(L, 1); } + lua_remove(L, handler); } void mainloop(float dt) { + lua_pushcfunction(L, message_handler); + const int handler = lua_gettop(L); lua_getglobal(L, "glerminal"); lua_getfield(L, -1, "main"); lua_remove(L, -2); lua_pushnumber(L, dt); - if (lua_pcall(L, 1, 0, 0) != LUA_OK) + if (lua_pcall(L, 1, 0, handler) != LUA_OK) { - // ignore error for now + std::cout << lua_tostring(L, -1) << std::endl; lua_pop(L, 1); } + lua_remove(L, handler); } void pressed(int key) @@ -140,15 +159,18 @@ namespace const char* const name = glfwGetKeyName(key, 0); if (name) { + lua_pushcfunction(L, message_handler); + const int handler = lua_gettop(L); lua_getglobal(L, "glerminal"); lua_getfield(L, -1, "pressed"); lua_remove(L, -2); lua_pushstring(L, name); - if (lua_pcall(L, 1, 0, 0) != LUA_OK) + if (lua_pcall(L, 1, 0, handler) != LUA_OK) { - // ignore error for now + std::cout << lua_tostring(L, -1) << std::endl; lua_pop(L, 1); } + lua_remove(L, handler); } } @@ -157,15 +179,18 @@ namespace const char* const name = glfwGetKeyName(key, 0); if (name) { + lua_pushcfunction(L, message_handler); + const int handler = lua_gettop(L); lua_getglobal(L, "glerminal"); lua_getfield(L, -1, "released"); lua_remove(L, -2); lua_pushstring(L, name); - if (lua_pcall(L, 1, 0, 0) != LUA_OK) + if (lua_pcall(L, 1, 0, handler) != LUA_OK) { - // ignore error for now + std::cout << lua_tostring(L, -1) << std::endl; lua_pop(L, 1); } + lua_remove(L, handler); } } } diff --git a/source/glerminal-private.h b/source/glerminal-private.h index 088c382..c8c84ef 100644 --- a/source/glerminal-private.h +++ b/source/glerminal-private.h @@ -41,8 +41,8 @@ namespace glerminal void flush(); - void set(unsigned char x, unsigned char y, unsigned char layer, unsigned char sprite); - unsigned char get(unsigned char x, unsigned char y, unsigned char layer) const; + void set(unsigned char x, unsigned char y, unsigned char layer, unsigned short sprite); + unsigned short get(unsigned char x, unsigned char y, unsigned char layer) const; void offset(unsigned char x, unsigned char y, unsigned char layer, float x_offset, float y_offset); void layer_color(unsigned char layer, unsigned int color); void layer_scale(unsigned char layer, float scale); @@ -84,7 +84,7 @@ namespace glerminal // library state - unsigned int m_sprites[CELL_SIZE * CELL_SIZE * MAX_SPRITES]; + unsigned int m_sprites[(CELL_SIZE + 2) * (CELL_SIZE + 2) * MAX_SPRITES]; glerminal_main_cb m_main; glerminal_keys_cb m_pressed, m_released; diff --git a/source/glerminal.cpp b/source/glerminal.cpp index 939b350..1217679 100644 --- a/source/glerminal.cpp +++ b/source/glerminal.cpp @@ -54,7 +54,7 @@ namespace " vs_out.sprite = sprite;\n" " vs_out.layer = layer;\n" " vs_out.layer_color = lcs.colors[layer];\n" - " vs_out.texcoord = (vec2((sprite + int(position.x + 1)) % " ATLAS_WIDTH_UNIFORM_NAME ", (sprite / " ATLAS_WIDTH_UNIFORM_NAME ") - position.y) + vec2((position.x + 0.5) / -32, (position.y + 0.5) / 32)) / vec2(" ATLAS_WIDTH_UNIFORM_NAME ");\n" + " vs_out.texcoord = vec2(sprite % " ATLAS_WIDTH_UNIFORM_NAME " + position.x + 1, (sprite / " ATLAS_WIDTH_UNIFORM_NAME ") - position.y) / vec2(" ATLAS_WIDTH_UNIFORM_NAME ") + vec2(-(2 * position.x + 1) * " GRID_SIZE_UNIFORM_NAME ".z / 16, (2 * position.y + 1) * " GRID_SIZE_UNIFORM_NAME ".z / 16);\n" " vec2 cell_position = vec2(lss.scales[layer] + (gl_InstanceID % int(" GRID_SIZE_UNIFORM_NAME ".y)) - " GRID_SIZE_UNIFORM_NAME ".x * floor((gl_InstanceID % int(" GRID_SIZE_UNIFORM_NAME ".y)) * " GRID_SIZE_UNIFORM_NAME ".z), -floor((gl_InstanceID % int(" GRID_SIZE_UNIFORM_NAME ".y)) * " GRID_SIZE_UNIFORM_NAME ".z));\n" " vec2 temp = ((position + vec2(-0.5, 0.5)) * lss.scales[layer] + cell_position + vec2(0.5, -0.5)) * " GRID_SIZE_UNIFORM_NAME ".zw * 2 + vec2(-1, 1);\n" " gl_Position = vec4(scaled_offset.x + temp.x, scaled_offset.y - temp.y, 0, 1);\n" @@ -89,7 +89,7 @@ namespace " gl_Layer = layer;\n" " vec2 scaled_offset = 2 * offset * " GRID_SIZE_UNIFORM_NAME ".zw;\n" " vs_out.sprite = sprite;\n" - " vs_out.texcoord = (vec2((sprite + int(position.x + 1)) % " ATLAS_WIDTH_UNIFORM_NAME ", (sprite / " ATLAS_WIDTH_UNIFORM_NAME ") - position.y) + vec2((position.x + 0.5) / -32, (position.y + 0.5) / 32)) / vec2(" ATLAS_WIDTH_UNIFORM_NAME ");\n" + " vs_out.texcoord = vec2(sprite % " ATLAS_WIDTH_UNIFORM_NAME " + position.x + 1, (sprite / " ATLAS_WIDTH_UNIFORM_NAME ") - position.y) / vec2(" ATLAS_WIDTH_UNIFORM_NAME ") + vec2(-(2 * position.x + 1) * " GRID_SIZE_UNIFORM_NAME ".z / 16, (2 * position.y + 1) * " GRID_SIZE_UNIFORM_NAME ".z / 16);\n" " vs_out.layer_color = lcs.colors[layer];\n" " vec2 cell_position = vec2(lss.scales[layer] + (gl_InstanceID % int(" GRID_SIZE_UNIFORM_NAME ".y)) - " GRID_SIZE_UNIFORM_NAME ".x * floor((gl_InstanceID % int(" GRID_SIZE_UNIFORM_NAME ".y)) * " GRID_SIZE_UNIFORM_NAME ".z), -floor((gl_InstanceID % int(" GRID_SIZE_UNIFORM_NAME ".y)) * " GRID_SIZE_UNIFORM_NAME ".z));\n" " vec2 temp = ((position + vec2(-0.5, 0.5)) * lss.scales[layer] + cell_position + vec2(0.5, -0.5)) * " GRID_SIZE_UNIFORM_NAME ".zw * 2 + vec2(-1, 1);\n" @@ -294,10 +294,13 @@ namespace glerminal glBlitNamedFramebuffer(m_screen_framebuffer, 0, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glfwSwapInterval(0); + glfwSwapBuffers(m_window); + glfwSwapInterval(1); glfwSwapBuffers(m_window); } - void glerminal::set(unsigned char x, unsigned char y, unsigned char layer, unsigned char sprite) + void glerminal::set(unsigned char x, unsigned char y, unsigned char layer, unsigned short sprite) { if (x < GRID_WIDTH && y < GRID_HEIGHT && layer < LAYER_COUNT) { @@ -305,7 +308,7 @@ namespace glerminal } } - unsigned char glerminal::get(unsigned char x, unsigned char y, unsigned char layer) const + unsigned short glerminal::get(unsigned char x, unsigned char y, unsigned char layer) const { if (x < GRID_WIDTH && y < GRID_HEIGHT && layer < LAYER_COUNT) { @@ -341,21 +344,25 @@ namespace glerminal void glerminal::load_atlas(unsigned char w, unsigned char h, const unsigned int* data) { - // each row of the atlas - for (int j = 0; j < h; j++) + for (int src_atlas_row = 0; src_atlas_row < h; src_atlas_row++) { - // each column of the atlas - for (int i = 0; i < w; i++) + for (int src_atlas_col = 0; src_atlas_col < w; src_atlas_col++) { - // each row of the individual sprite - for (int k = 0; k < CELL_SIZE; k++) + for (int sprite_row = 0; sprite_row < CELL_SIZE; sprite_row++) { - // offset from base address in source atlas layout - const unsigned int src_offset = i + k * w + j * w * CELL_SIZE; - // offset from base address in glerminal atlas layout - const unsigned int dst_offset = i + k * MAX_SPRITES_ROW + j * MAX_SPRITES_ROW * CELL_SIZE; + const unsigned int sprite_index = src_atlas_col + src_atlas_row * w; + const unsigned int dst_atlas_row = sprite_index / MAX_SPRITES_ROW; + const unsigned int dst_atlas_col = sprite_index % MAX_SPRITES_ROW; - memcpy(m_sprites + CELL_SIZE * dst_offset, data + CELL_SIZE * src_offset, CELL_SIZE * sizeof(unsigned int)); + // offset from base address in source atlas layout + const unsigned int src_offset = CELL_SIZE * (src_atlas_col + sprite_row * w + src_atlas_row * w * CELL_SIZE); + + const unsigned int dst_column = dst_atlas_col * (CELL_SIZE + 2) + 1; + const unsigned int dst_row = MAX_SPRITES_ROW * (CELL_SIZE + 2) * ((sprite_row + 1) + dst_atlas_row * (CELL_SIZE + 2)); + // offset from base address in glerminal atlas layout + const unsigned int dst_offset = dst_column + dst_row; + + memcpy(m_sprites + dst_offset, data + src_offset, CELL_SIZE * sizeof(unsigned int)); } } } @@ -365,7 +372,6 @@ namespace glerminal { glfwInit(); - glfwWindowHint(GLFW_DOUBLEBUFFER, GLFW_TRUE); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); @@ -691,7 +697,7 @@ namespace glerminal glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); - glTextureStorage2D(m_sprites_texture, 1, GL_RGBA8, MAX_SPRITES_ROW * CELL_SIZE, MAX_SPRITES_ROW * CELL_SIZE); + glTextureStorage2D(m_sprites_texture, 1, GL_RGBA8, MAX_SPRITES_ROW * (CELL_SIZE + 2), MAX_SPRITES_ROW * (CELL_SIZE + 2)); update_sprites(); @@ -765,7 +771,7 @@ namespace glerminal void glerminal::update_sprites() { - glTextureSubImage2D(m_sprites_texture, 0, 0, 0, CELL_SIZE * MAX_SPRITES_ROW, CELL_SIZE * MAX_SPRITES_ROW, GL_RGBA, GL_UNSIGNED_BYTE, m_sprites); + glTextureSubImage2D(m_sprites_texture, 0, 0, 0, (CELL_SIZE + 2) * MAX_SPRITES_ROW, (CELL_SIZE + 2) * MAX_SPRITES_ROW, GL_RGBA, GL_UNSIGNED_BYTE, m_sprites); } void glerminal::update_layer_colors() @@ -822,14 +828,14 @@ void glerminal_flush() GLERMINAL_G->flush(); } -void glerminal_set(unsigned char x, unsigned char y, unsigned char layer, unsigned char sprite) +void glerminal_set(unsigned char x, unsigned char y, unsigned char layer, unsigned short sprite) { if (!GLERMINAL_G) { return; } GLERMINAL_G->set(x, y, layer, sprite); } -unsigned char glerminal_get(unsigned char x, unsigned char y, unsigned char layer) +unsigned char glerminal_get(unsigned char x, unsigned char y, unsigned short layer) { if (!GLERMINAL_G) { return 0; }