mirror of
https://github.com/usatiuk/cardboy.git
synced 2025-10-28 23:27:49 +01:00
better controls
This commit is contained in:
@@ -25,14 +25,14 @@ using Framebuffer = typename AppContext::Framebuffer;
|
|||||||
using Clock = typename AppContext::Clock;
|
using Clock = typename AppContext::Clock;
|
||||||
|
|
||||||
struct TimeSnapshot {
|
struct TimeSnapshot {
|
||||||
bool hasWallTime = false;
|
bool hasWallTime = false;
|
||||||
int hour24 = 0;
|
int hour24 = 0;
|
||||||
int minute = 0;
|
int minute = 0;
|
||||||
int second = 0;
|
int second = 0;
|
||||||
int year = 0;
|
int year = 0;
|
||||||
int month = 0;
|
int month = 0;
|
||||||
int day = 0;
|
int day = 0;
|
||||||
int weekday = 0;
|
int weekday = 0;
|
||||||
std::uint64_t uptimeSeconds = 0;
|
std::uint64_t uptimeSeconds = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -42,8 +42,8 @@ public:
|
|||||||
|
|
||||||
void onStart() override {
|
void onStart() override {
|
||||||
cancelRefreshTimer();
|
cancelRefreshTimer();
|
||||||
lastSnapshot = {};
|
lastSnapshot = {};
|
||||||
dirty = true;
|
dirty = true;
|
||||||
const auto snap = captureTime();
|
const auto snap = captureTime();
|
||||||
renderIfNeeded(snap);
|
renderIfNeeded(snap);
|
||||||
lastSnapshot = snap;
|
lastSnapshot = snap;
|
||||||
@@ -69,8 +69,8 @@ private:
|
|||||||
Framebuffer& framebuffer;
|
Framebuffer& framebuffer;
|
||||||
Clock& clock;
|
Clock& clock;
|
||||||
|
|
||||||
bool use24Hour = true;
|
bool use24Hour = true;
|
||||||
bool dirty = false;
|
bool dirty = false;
|
||||||
cardboy::sdk::AppTimerHandle refreshTimer = cardboy::sdk::kInvalidAppTimer;
|
cardboy::sdk::AppTimerHandle refreshTimer = cardboy::sdk::kInvalidAppTimer;
|
||||||
|
|
||||||
TimeSnapshot lastSnapshot{};
|
TimeSnapshot lastSnapshot{};
|
||||||
@@ -199,7 +199,7 @@ private:
|
|||||||
drawCenteredText(framebuffer, timeY + font16x8::kGlyphHeight * scaleLarge + 28, dateLine, scaleSmall, 1);
|
drawCenteredText(framebuffer, timeY + font16x8::kGlyphHeight * scaleLarge + 28, dateLine, scaleSmall, 1);
|
||||||
|
|
||||||
if (!snap.hasWallTime) {
|
if (!snap.hasWallTime) {
|
||||||
char uptimeLine[32];
|
char uptimeLine[32];
|
||||||
const std::uint64_t days = snap.uptimeSeconds / 86400ULL;
|
const std::uint64_t days = snap.uptimeSeconds / 86400ULL;
|
||||||
const std::uint64_t hrs = (snap.uptimeSeconds / 3600ULL) % 24ULL;
|
const std::uint64_t hrs = (snap.uptimeSeconds / 3600ULL) % 24ULL;
|
||||||
const std::uint64_t mins = (snap.uptimeSeconds / 60ULL) % 60ULL;
|
const std::uint64_t mins = (snap.uptimeSeconds / 60ULL) % 60ULL;
|
||||||
@@ -225,7 +225,7 @@ private:
|
|||||||
|
|
||||||
class ClockAppFactory final : public cardboy::sdk::IAppFactory {
|
class ClockAppFactory final : public cardboy::sdk::IAppFactory {
|
||||||
public:
|
public:
|
||||||
const char* name() const override { return kClockAppName; }
|
const char* name() const override { return kClockAppName; }
|
||||||
std::unique_ptr<cardboy::sdk::IApp> create(cardboy::sdk::AppContext& context) override {
|
std::unique_ptr<cardboy::sdk::IApp> create(cardboy::sdk::AppContext& context) override {
|
||||||
return std::make_unique<ClockApp>(context);
|
return std::make_unique<ClockApp>(context);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "cardboy/apps/gameboy_app.hpp"
|
#include "cardboy/apps/gameboy_app.hpp"
|
||||||
#include "cardboy/apps/peanut_gb.h"
|
#include "cardboy/apps/peanut_gb.h"
|
||||||
|
|
||||||
|
#include "cardboy/apps/menu_app.hpp"
|
||||||
|
|
||||||
#include "cardboy/gfx/font16x8.hpp"
|
#include "cardboy/gfx/font16x8.hpp"
|
||||||
#include "cardboy/sdk/app_framework.hpp"
|
#include "cardboy/sdk/app_framework.hpp"
|
||||||
#include "cardboy/sdk/app_system.hpp"
|
#include "cardboy/sdk/app_system.hpp"
|
||||||
@@ -760,6 +762,11 @@ private:
|
|||||||
|
|
||||||
if (roms.empty())
|
if (roms.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (input.b && !prevInput.b) {
|
||||||
|
context.requestAppSwitchByName(apps::kMenuAppName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
const auto wrapDecrement = [&]() {
|
const auto wrapDecrement = [&]() {
|
||||||
if (selectedIndex == 0)
|
if (selectedIndex == 0)
|
||||||
selectedIndex = roms.size() - 1;
|
selectedIndex = roms.size() - 1;
|
||||||
@@ -822,7 +829,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
font16x8::drawText(framebuffer, 16, framebuffer.height() - 52, "A/START PLAY", 1, true, 1);
|
font16x8::drawText(framebuffer, 16, framebuffer.height() - 52, "A/START PLAY", 1, true, 1);
|
||||||
font16x8::drawText(framebuffer, 16, framebuffer.height() - 32, "SELECT RESCAN", 1, true, 1);
|
font16x8::drawText(framebuffer, 16, framebuffer.height() - 32, "B BACK SELECT RESCAN", 1, true, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!statusMessage.empty()) {
|
if (!statusMessage.empty()) {
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public:
|
|||||||
moveSelection(+1);
|
moveSelection(+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool launch = (current.a && !previous.a) || (current.select && !previous.select);
|
const bool launch = (current.a && !previous.a) || (current.start && !previous.start);
|
||||||
if (launch)
|
if (launch)
|
||||||
launchSelected();
|
launchSelected();
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ private:
|
|||||||
font16x8::drawText(framebuffer, topRightX, 20, indexLabel, 1, true, 0);
|
font16x8::drawText(framebuffer, topRightX, 20, indexLabel, 1, true, 0);
|
||||||
|
|
||||||
drawPagerDots();
|
drawPagerDots();
|
||||||
drawCenteredText(framebuffer, framebuffer.height() - 48, "A/SELECT START", 1, 1);
|
drawCenteredText(framebuffer, framebuffer.height() - 48, "A START APP", 1, 1);
|
||||||
drawCenteredText(framebuffer, framebuffer.height() - 28, "L/R CHOOSE", 1, 1);
|
drawCenteredText(framebuffer, framebuffer.height() - 28, "L/R CHOOSE", 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,7 +163,7 @@ private:
|
|||||||
|
|
||||||
class MenuAppFactory final : public cardboy::sdk::IAppFactory {
|
class MenuAppFactory final : public cardboy::sdk::IAppFactory {
|
||||||
public:
|
public:
|
||||||
const char* name() const override { return kMenuAppName; }
|
const char* name() const override { return kMenuAppName; }
|
||||||
std::unique_ptr<cardboy::sdk::IApp> create(cardboy::sdk::AppContext& context) override {
|
std::unique_ptr<cardboy::sdk::IApp> create(cardboy::sdk::AppContext& context) override {
|
||||||
return std::make_unique<MenuApp>(context);
|
return std::make_unique<MenuApp>(context);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,8 +64,8 @@ public:
|
|||||||
moved = true;
|
moved = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool togglePressed = (current.a && !previous.a) || (current.select && !previous.select) ||
|
const bool togglePressed = (current.a && !previous.a) || (current.start && !previous.start) ||
|
||||||
(current.start && !previous.start);
|
(current.select && !previous.select);
|
||||||
if (togglePressed)
|
if (togglePressed)
|
||||||
handleToggle();
|
handleToggle();
|
||||||
|
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ private:
|
|||||||
AppTimerHandle nextTimerId = 1;
|
AppTimerHandle nextTimerId = 1;
|
||||||
std::uint32_t currentGeneration = 0;
|
std::uint32_t currentGeneration = 0;
|
||||||
InputState lastInputState{};
|
InputState lastInputState{};
|
||||||
|
bool suppressInputs = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline AppTimerHandle AppContext::scheduleTimerInternal(std::uint32_t delay_ms, bool repeat) {
|
inline AppTimerHandle AppContext::scheduleTimerInternal(std::uint32_t delay_ms, bool repeat) {
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ namespace {
|
|||||||
a.select != b.select || a.start != b.start;
|
a.select != b.select || a.start != b.start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool anyButtonPressed(const InputState& state) {
|
||||||
|
return state.up || state.down || state.left || state.right || state.a || state.b || state.select || state.start;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr std::uint32_t kIdlePollMs = 16;
|
constexpr std::uint32_t kIdlePollMs = 16;
|
||||||
|
|
||||||
template<typename Framebuffer>
|
template<typename Framebuffer>
|
||||||
@@ -71,6 +75,7 @@ bool AppSystem::startAppByIndex(std::size_t index) {
|
|||||||
clearTimersForCurrentApp();
|
clearTimersForCurrentApp();
|
||||||
current = std::move(app);
|
current = std::move(app);
|
||||||
lastInputState = context.input.readState();
|
lastInputState = context.input.readState();
|
||||||
|
suppressInputs = true;
|
||||||
StatusBar::instance().setServices(context.services);
|
StatusBar::instance().setServices(context.services);
|
||||||
StatusBar::instance().setCurrentAppName(activeFactory ? activeFactory->name() : "");
|
StatusBar::instance().setCurrentAppName(activeFactory ? activeFactory->name() : "");
|
||||||
current->onStart();
|
current->onStart();
|
||||||
@@ -94,7 +99,11 @@ void AppSystem::run() {
|
|||||||
const InputState inputNow = context.input.readState();
|
const InputState inputNow = context.input.readState();
|
||||||
const bool consumedByStatusToggle = StatusBar::instance().handleToggleInput(inputNow, lastInputState);
|
const bool consumedByStatusToggle = StatusBar::instance().handleToggleInput(inputNow, lastInputState);
|
||||||
|
|
||||||
if (!consumedByStatusToggle && inputsDiffer(inputNow, lastInputState)) {
|
if (suppressInputs) {
|
||||||
|
lastInputState = inputNow;
|
||||||
|
if (!anyButtonPressed(inputNow))
|
||||||
|
suppressInputs = false;
|
||||||
|
} else if (!consumedByStatusToggle && inputsDiffer(inputNow, lastInputState)) {
|
||||||
AppEvent evt{};
|
AppEvent evt{};
|
||||||
evt.type = AppEventType::Button;
|
evt.type = AppEventType::Button;
|
||||||
evt.timestamp_ms = now;
|
evt.timestamp_ms = now;
|
||||||
|
|||||||
Reference in New Issue
Block a user