more cleanup

This commit is contained in:
2025-10-11 15:04:28 +02:00
parent fa2715a60a
commit 23400d817b
10 changed files with 36 additions and 254 deletions

View File

@@ -12,4 +12,9 @@ target_include_directories(cardboy_backend_interface
target_sources(cardboy_backend_interface
INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/include/cardboy/backend/backend_interface.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/cardboy/sdk/backend.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/cardboy/sdk/display_spec.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/cardboy/sdk/input_state.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/cardboy/sdk/platform.hpp
${CMAKE_CURRENT_SOURCE_DIR}/include/cardboy/sdk/services.hpp
)

View File

@@ -1,9 +1,9 @@
#pragma once
#include "platform.hpp"
#include <cardboy/sdk/platform.hpp>
#include "cardboy/backend/backend_impl.hpp"
#include "cardboy/backend/backend_interface.hpp"
#include <cardboy/backend/backend_impl.hpp>
#include <cardboy/backend/backend_interface.hpp>
namespace cardboy::backend {
static_assert(BackendInterface<ActiveBackend>, "ActiveBackend must provide Framebuffer, Input, Clock types");

View File

@@ -6,4 +6,3 @@ inline constexpr int kDisplayWidth = 400;
inline constexpr int kDisplayHeight = 240;
} // namespace cardboy::sdk

View File

@@ -14,4 +14,3 @@ struct InputState {
};
} // namespace cardboy::sdk

View File

@@ -20,8 +20,8 @@ public:
virtual void beepLevelUp(int /*level*/) {}
virtual void beepGameOver() {}
virtual void setMuted(bool /*muted*/) {}
virtual void toggleMuted() {}
virtual void setMuted(bool /*muted*/) {}
virtual void toggleMuted() {}
[[nodiscard]] virtual bool isMuted() const { return false; }
};
@@ -29,17 +29,17 @@ class IBatteryMonitor {
public:
virtual ~IBatteryMonitor() = default;
[[nodiscard]] virtual bool hasData() const { return false; }
[[nodiscard]] virtual float voltage() const { return 0.0f; }
[[nodiscard]] virtual float charge() const { return 0.0f; }
[[nodiscard]] virtual float current() const { return 0.0f; }
[[nodiscard]] virtual bool hasData() const { return false; }
[[nodiscard]] virtual float voltage() const { return 0.0f; }
[[nodiscard]] virtual float charge() const { return 0.0f; }
[[nodiscard]] virtual float current() const { return 0.0f; }
};
class IStorage {
public:
virtual ~IStorage() = default;
[[nodiscard]] virtual bool readUint32(std::string_view ns, std::string_view key, std::uint32_t& out) = 0;
[[nodiscard]] virtual bool readUint32(std::string_view ns, std::string_view key, std::uint32_t& out) = 0;
virtual void writeUint32(std::string_view ns, std::string_view key, std::uint32_t value) = 0;
};
@@ -61,27 +61,27 @@ class IPowerManager {
public:
virtual ~IPowerManager() = default;
virtual void setSlowMode(bool enable) = 0;
[[nodiscard]] virtual bool isSlowMode() const = 0;
virtual void setSlowMode(bool enable) = 0;
[[nodiscard]] virtual bool isSlowMode() const = 0;
};
class IFilesystem {
public:
virtual ~IFilesystem() = default;
virtual bool mount() = 0;
virtual bool mount() = 0;
[[nodiscard]] virtual bool isMounted() const = 0;
[[nodiscard]] virtual std::string basePath() const = 0;
};
struct Services {
IBuzzer* buzzer = nullptr;
IBuzzer* buzzer = nullptr;
IBatteryMonitor* battery = nullptr;
IStorage* storage = nullptr;
IRandom* random = nullptr;
IHighResClock* highResClock = nullptr;
IPowerManager* powerManager = nullptr;
IFilesystem* filesystem = nullptr;
IStorage* storage = nullptr;
IRandom* random = nullptr;
IHighResClock* highResClock = nullptr;
IPowerManager* powerManager = nullptr;
IFilesystem* filesystem = nullptr;
};
} // namespace cardboy::sdk

View File

@@ -25,8 +25,6 @@ set_target_properties(cardboy_backend_desktop PROPERTIES
target_include_directories(cardboy_backend_desktop
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/../../include
)
target_link_libraries(cardboy_backend_desktop

View File

@@ -1,186 +0,0 @@
#pragma once
#include "cardboy/sdk/platform.hpp"
#include "cardboy/sdk/services.hpp"
#include <SFML/Graphics.hpp>
#include <SFML/Window/Keyboard.hpp>
#include <chrono>
#include <cstdint>
#include <filesystem>
#include <limits>
#include <random>
#include <string>
#include <string_view>
#include <thread>
#include <unordered_map>
#include <vector>
namespace cardboy::backend::desktop {
constexpr int kPixelScale = 2;
class DesktopRuntime;
class DesktopBuzzer final : public cardboy::sdk::IBuzzer {
public:
void tone(std::uint32_t, std::uint32_t, std::uint32_t) override {}
void beepRotate() override {}
void beepMove() override {}
void beepLock() override {}
void beepLines(int) override {}
void beepLevelUp(int) override {}
void beepGameOver() override {}
};
class DesktopBattery final : public cardboy::sdk::IBatteryMonitor {
public:
[[nodiscard]] bool hasData() const override { return false; }
};
class DesktopStorage final : public cardboy::sdk::IStorage {
public:
[[nodiscard]] bool readUint32(std::string_view ns, std::string_view key, std::uint32_t& out) override;
void writeUint32(std::string_view ns, std::string_view key, std::uint32_t value) override;
private:
std::unordered_map<std::string, std::uint32_t> data;
static std::string composeKey(std::string_view ns, std::string_view key);
};
class DesktopRandom final : public cardboy::sdk::IRandom {
public:
DesktopRandom();
[[nodiscard]] std::uint32_t nextUint32() override;
private:
std::mt19937 rng;
std::uniform_int_distribution<std::uint32_t> dist;
};
class DesktopHighResClock final : public cardboy::sdk::IHighResClock {
public:
DesktopHighResClock();
[[nodiscard]] std::uint64_t micros() override;
private:
const std::chrono::steady_clock::time_point start;
};
class DesktopPowerManager final : public cardboy::sdk::IPowerManager {
public:
void setSlowMode(bool enable) override { slowMode = enable; }
[[nodiscard]] bool isSlowMode() const override { return slowMode; }
private:
bool slowMode = false;
};
class DesktopFilesystem final : public cardboy::sdk::IFilesystem {
public:
DesktopFilesystem();
bool mount() override;
[[nodiscard]] bool isMounted() const override { return mounted; }
[[nodiscard]] std::string basePath() const override { return basePathPath.string(); }
private:
std::filesystem::path basePathPath;
bool mounted = false;
};
class DesktopFramebuffer final : public cardboy::sdk::FramebufferFacade<DesktopFramebuffer> {
public:
explicit DesktopFramebuffer(DesktopRuntime& runtime);
[[nodiscard]] int width_impl() const;
[[nodiscard]] int height_impl() const;
void drawPixel_impl(int x, int y, bool on);
void clear_impl(bool on);
void frameReady_impl();
void sendFrame_impl(bool clearAfterSend);
[[nodiscard]] bool frameInFlight_impl() const { return false; }
private:
DesktopRuntime& runtime;
};
class DesktopInput final : public cardboy::sdk::InputFacade<DesktopInput> {
public:
explicit DesktopInput(DesktopRuntime& runtime);
cardboy::sdk::InputState readState_impl();
void handleKey(sf::Keyboard::Key key, bool pressed);
private:
DesktopRuntime& runtime;
cardboy::sdk::InputState state{};
};
class DesktopClock final : public cardboy::sdk::ClockFacade<DesktopClock> {
public:
explicit DesktopClock(DesktopRuntime& runtime);
std::uint32_t millis_impl();
void sleep_ms_impl(std::uint32_t ms);
private:
DesktopRuntime& runtime;
const std::chrono::steady_clock::time_point start;
};
class DesktopRuntime {
public:
DesktopRuntime();
cardboy::sdk::Services& serviceRegistry();
void processEvents();
void presentIfNeeded();
void sleepFor(std::uint32_t ms);
[[nodiscard]] bool isRunning() const { return running; }
DesktopFramebuffer framebuffer;
DesktopInput input;
DesktopClock clock;
private:
friend class DesktopFramebuffer;
friend class DesktopInput;
friend class DesktopClock;
void setPixel(int x, int y, bool on);
void clearPixels(bool on);
sf::RenderWindow window;
sf::Texture texture;
sf::Sprite sprite;
std::vector<std::uint8_t> pixels;
bool dirty = true;
bool running = true;
bool clearNextFrame = true;
DesktopBuzzer buzzerService;
DesktopBattery batteryService;
DesktopStorage storageService;
DesktopRandom randomService;
DesktopHighResClock highResService;
DesktopPowerManager powerService;
DesktopFilesystem filesystemService;
cardboy::sdk::Services services{};
};
struct Backend {
using Framebuffer = DesktopFramebuffer;
using Input = DesktopInput;
using Clock = DesktopClock;
};
} // namespace cardboy::backend::desktop
namespace cardboy::backend {
using DesktopBackend = desktop::Backend;
} // namespace cardboy::backend

View File

@@ -1,33 +0,0 @@
#include "cardboy/apps/clock_app.hpp"
#include "cardboy/apps/gameboy_app.hpp"
#include "cardboy/apps/menu_app.hpp"
#include "cardboy/apps/tetris_app.hpp"
#include "cardboy/backend/desktop_backend.hpp"
#include "cardboy/sdk/app_system.hpp"
#include <cstdio>
#include <exception>
using cardboy::backend::desktop::DesktopRuntime;
int main() {
try {
DesktopRuntime runtime;
cardboy::sdk::AppContext context(runtime.framebuffer, runtime.input, runtime.clock);
context.services = &runtime.serviceRegistry();
cardboy::sdk::AppSystem system(context);
system.registerApp(apps::createMenuAppFactory());
system.registerApp(apps::createClockAppFactory());
system.registerApp(apps::createGameboyAppFactory());
system.registerApp(apps::createTetrisAppFactory());
system.run();
} catch (const std::exception& ex) {
std::fprintf(stderr, "Cardboy desktop runtime failed: %s\n", ex.what());
return 1;
}
return 0;
}

View File

@@ -1,8 +1,8 @@
#pragma once
#include "backend.hpp"
#include "platform.hpp"
#include "services.hpp"
#include <cardboy/sdk/backend.hpp>
#include <cardboy/sdk/platform.hpp>
#include <cardboy/sdk/services.hpp>
#include <cstdint>
#include <memory>
@@ -14,7 +14,7 @@ namespace cardboy::sdk {
class AppSystem;
using AppTimerHandle = std::uint32_t;
using AppTimerHandle = std::uint32_t;
constexpr AppTimerHandle kInvalidAppTimer = 0;
enum class AppEventType {
@@ -51,18 +51,18 @@ struct AppContext {
Framebuffer& framebuffer;
Input& input;
Clock& clock;
AppSystem* system = nullptr;
Services* services = nullptr;
AppSystem* system = nullptr;
Services* services = nullptr;
[[nodiscard]] Services* getServices() const { return services; }
[[nodiscard]] IBuzzer* buzzer() const { return services ? services->buzzer : nullptr; }
[[nodiscard]] IBuzzer* buzzer() const { return services ? services->buzzer : nullptr; }
[[nodiscard]] IBatteryMonitor* battery() const { return services ? services->battery : nullptr; }
[[nodiscard]] IStorage* storage() const { return services ? services->storage : nullptr; }
[[nodiscard]] IRandom* random() const { return services ? services->random : nullptr; }
[[nodiscard]] IHighResClock* highResClock() const { return services ? services->highResClock : nullptr; }
[[nodiscard]] IPowerManager* powerManager() const { return services ? services->powerManager : nullptr; }
[[nodiscard]] IFilesystem* filesystem() const { return services ? services->filesystem : nullptr; }
[[nodiscard]] IStorage* storage() const { return services ? services->storage : nullptr; }
[[nodiscard]] IRandom* random() const { return services ? services->random : nullptr; }
[[nodiscard]] IHighResClock* highResClock() const { return services ? services->highResClock : nullptr; }
[[nodiscard]] IPowerManager* powerManager() const { return services ? services->powerManager : nullptr; }
[[nodiscard]] IFilesystem* filesystem() const { return services ? services->filesystem : nullptr; }
void requestAppSwitchByIndex(std::size_t index) {
pendingAppIndex = index;