diff --git a/conanfile.py b/conanfile.py index 96ac238c7..c5e3caef8 100644 --- a/conanfile.py +++ b/conanfile.py @@ -1,9 +1,8 @@ from conans import ConanFile, CMake class NostalgiaConan(ConanFile): - settings = "os", "compiler", "build_type", "arch" - requires = "jsoncpp/1.9.4", "sdl2/2.0.14@bincrafters/stable" - generators = "cmake", "cmake_find_package", "cmake_paths" - #default_options = { - # "sdl2:nas": False - #} + settings = 'os', 'compiler', 'build_type', 'arch' + requires = 'jsoncpp/1.9.4', 'glfw/3.3.4' + generators = 'cmake', 'cmake_find_package', 'cmake_paths' + default_options = { + } diff --git a/src/nostalgia/core/CMakeLists.txt b/src/nostalgia/core/CMakeLists.txt index cfd340139..1982b985b 100644 --- a/src/nostalgia/core/CMakeLists.txt +++ b/src/nostalgia/core/CMakeLists.txt @@ -15,7 +15,7 @@ target_link_libraries( add_subdirectory(gba) if(NOSTALGIA_BUILD_TYPE STREQUAL "Native") - add_subdirectory(sdl) + add_subdirectory(glfw) add_subdirectory(userland) endif() if(NOSTALGIA_BUILD_STUDIO) diff --git a/src/nostalgia/core/core.hpp b/src/nostalgia/core/core.hpp index c989d6e31..b790d0a43 100644 --- a/src/nostalgia/core/core.hpp +++ b/src/nostalgia/core/core.hpp @@ -25,11 +25,11 @@ ox::Error run(Context *ctx) noexcept; // Sets event handler that sleeps for the time given in the return value. The // sleep time is a minimum of ~16 milliseconds. -void setEventHandler(event_handler) noexcept; +void setEventHandler(Context *ctx, event_handler) noexcept; // Returns the number of milliseconds that have passed since the start of the // program. [[nodiscard]] -uint64_t ticksMs() noexcept; +uint64_t ticksMs(Context *ctx) noexcept; } diff --git a/src/nostalgia/core/gba/core.cpp b/src/nostalgia/core/gba/core.cpp index 24cb0f1bd..52773b566 100644 --- a/src/nostalgia/core/gba/core.cpp +++ b/src/nostalgia/core/gba/core.cpp @@ -47,11 +47,11 @@ ox::Error init(Context *ctx) noexcept { return OxError(0); } -void setEventHandler(event_handler h) noexcept { +void setEventHandler(Context*, event_handler h) noexcept { g_eventHandler = h; } -uint64_t ticksMs() noexcept { +uint64_t ticksMs(Context*) noexcept { return g_timerMs; } diff --git a/src/nostalgia/core/glfw/CMakeLists.txt b/src/nostalgia/core/glfw/CMakeLists.txt new file mode 100644 index 000000000..70bb2ae1c --- /dev/null +++ b/src/nostalgia/core/glfw/CMakeLists.txt @@ -0,0 +1,21 @@ +add_library( + NostalgiaCore-GLFW + core.cpp + gfx.cpp +) + +find_package(glfw3 REQUIRED) + +target_link_libraries( + NostalgiaCore-GLFW PUBLIC + glfw::glfw + NostalgiaCore-Userspace +) + +install( + TARGETS + NostalgiaCore-GLFW + DESTINATION + LIBRARY DESTINATION lib/nostalgia + ARCHIVE DESTINATION lib/nostalgia +) diff --git a/src/nostalgia/core/glfw/core.cpp b/src/nostalgia/core/glfw/core.cpp new file mode 100644 index 000000000..5e1ebea58 --- /dev/null +++ b/src/nostalgia/core/glfw/core.cpp @@ -0,0 +1,91 @@ +/* + * Copyright 2016 - 2021 gary@drinkingtea.net + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include +#include + +#include "core.hpp" + +namespace nostalgia::core { + +static event_handler g_eventHandler = nullptr; +static uint64_t g_wakeupTime; + +void draw(Context *ctx); + +ox::Error init(Context *ctx) noexcept { + const auto id = new GlfwImplData; + ctx->setWindowerData(id); + using namespace std::chrono; + id->startTime = duration_cast(system_clock::now().time_since_epoch()).count(); + glfwInit(); + oxReturnError(initGfx(ctx)); + return OxError(0); +} + +static void handleGlfwKeyEvent(GLFWwindow *window, int key, int, int action, int) { + const auto ctx = ox::bit_cast(glfwGetWindowUserPointer(window)); + const auto id = ctx->windowerData(); + switch (action) { + case GLFW_PRESS: + switch (key) { + case GLFW_KEY_Q: + id->running = false; + break; + } + break; + } +} + +ox::Error run(Context *ctx) noexcept { + const auto id = ctx->windowerData(); + id->running = true; + // try adaptive vsync + //if (SDL_GL_SetSwapInterval(config::SdlVsyncOption) < 0) { + // oxTrace("nostalgia::core::sdl", "Could not enable adaptive vsync, falling back on vsync"); + // SDL_GL_SetSwapInterval(1); // fallback on normal vsync + //} + glfwSetKeyCallback(id->window, handleGlfwKeyEvent); + while (id->running && !glfwWindowShouldClose(id->window)) { + glfwPollEvents(); + const auto ticks = ticksMs(ctx); + if (g_wakeupTime <= ticks && g_eventHandler) { + auto sleepTime = g_eventHandler(ctx); + if (sleepTime >= 0) { + g_wakeupTime = ticks + static_cast(sleepTime); + } else { + g_wakeupTime = ~uint64_t(0); + } + } + draw(ctx); + glfwSwapBuffers(id->window); + } + return OxError(0); +} + +void setEventHandler(Context *ctx, event_handler h) noexcept { + const auto id = ctx->windowerData(); + id->eventHandler = h; +} + +uint64_t ticksMs(Context *ctx) noexcept { + using namespace std::chrono; + const auto id = ctx->windowerData(); + const auto now = duration_cast(system_clock::now().time_since_epoch()).count(); + return static_cast(now - id->startTime); +} + +bool buttonDown(Key) noexcept { + return false; +} + +} diff --git a/src/nostalgia/core/glfw/core.hpp b/src/nostalgia/core/glfw/core.hpp new file mode 100644 index 000000000..2226e46e9 --- /dev/null +++ b/src/nostalgia/core/glfw/core.hpp @@ -0,0 +1,22 @@ +/* + * Copyright 2016 - 2021 gary@drinkingtea.net + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include + +namespace nostalgia::core { + +struct GlfwImplData { + class GLFWwindow *window = nullptr; + int64_t startTime = 0; + bool running = false; + event_handler eventHandler = nullptr; +}; + +} diff --git a/src/nostalgia/core/glfw/gfx.cpp b/src/nostalgia/core/glfw/gfx.cpp new file mode 100644 index 000000000..09e7649f0 --- /dev/null +++ b/src/nostalgia/core/glfw/gfx.cpp @@ -0,0 +1,74 @@ +/* + * Copyright 2016 - 2021 gary@drinkingtea.net + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include + +#include +#include + +#include "core.hpp" + +namespace nostalgia::core { + +constexpr auto Scale = 5; + +static void handleGlfwError(int err, const char *desc) { + oxErrf("GLFW error ({}): {}", err, desc); +} + +ox::Error initGfx(Context *ctx) noexcept { + auto id = ctx->windowerData(); + glfwSetErrorCallback(handleGlfwError); + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); + glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); + id->window = glfwCreateWindow(240 * Scale, 160 * Scale, "nostalgia", nullptr, nullptr); + if (id->window == nullptr) { + return OxError(1, "Could not open GLFW window"); + } + glfwSetWindowUserPointer(id->window, ctx); + glfwMakeContextCurrent(id->window); + oxReturnError(renderer::init(ctx)); + return OxError(0); +} + +ox::Error shutdownGfx(Context *ctx) noexcept { + oxReturnError(renderer::shutdown(ctx)); + auto id = ctx->windowerData(); + glfwDestroyWindow(id->window); + ctx->setWindowerData(nullptr); + delete id; + return OxError(0); +} + +int getScreenWidth(Context *ctx) noexcept { + auto id = ctx->windowerData(); + int w = 0, h = 0; + glfwGetFramebufferSize(id->window, &w, &h); + return w; +} + +int getScreenHeight(Context *ctx) noexcept { + auto id = ctx->windowerData(); + int w = 0, h = 0; + glfwGetFramebufferSize(id->window, &w, &h); + return h; +} + +common::Size getScreenSize(Context *ctx) noexcept { + auto id = ctx->windowerData(); + int w = 0, h = 0; + glfwGetFramebufferSize(id->window, &w, &h); + return {w, h}; +} + +} diff --git a/src/nostalgia/player/CMakeLists.txt b/src/nostalgia/player/CMakeLists.txt index faff4d196..f5676528a 100644 --- a/src/nostalgia/player/CMakeLists.txt +++ b/src/nostalgia/player/CMakeLists.txt @@ -22,7 +22,7 @@ target_link_libraries( nostalgia NostalgiaWorld $<$:NostalgiaCore-GBA> - $<$:NostalgiaCore-SDL> + $<$:NostalgiaCore-GLFW> ) install( diff --git a/src/nostalgia/player/app.cpp b/src/nostalgia/player/app.cpp index 6684bf169..784812c80 100644 --- a/src/nostalgia/player/app.cpp +++ b/src/nostalgia/player/app.cpp @@ -41,7 +41,7 @@ ox::Error run(ox::FileSystem *fs) noexcept { oxReturnError(core::loadSpriteTileSheet(&ctx, 0, TileSheetAddr, PaletteAddr)); oxReturnError(core::initConsole(&ctx)); core::puts(&ctx, 10, 9, "DOPENESS!!!"); - core::setEventHandler(eventHandler); + core::setEventHandler(&ctx, eventHandler); oxReturnError(core::run(&ctx)); oxReturnError(core::shutdownGfx(&ctx)); return OxError(0);