mirror of
https://github.com/usatiuk/cardboy.git
synced 2025-10-28 15:17:48 +01:00
fps counter
This commit is contained in:
@@ -40,6 +40,7 @@ public:
|
||||
void onStart() override {
|
||||
prevInput = {};
|
||||
statusMessage.clear();
|
||||
resetFpsStats();
|
||||
ensureFilesystemReady();
|
||||
refreshRomList();
|
||||
mode = Mode::Browse;
|
||||
@@ -63,6 +64,7 @@ public:
|
||||
browserDirty = true;
|
||||
break;
|
||||
}
|
||||
DispTools::draw_to_display_async_wait();
|
||||
gb_run_frame(&gb);
|
||||
renderGameFrame();
|
||||
break;
|
||||
@@ -94,14 +96,16 @@ private:
|
||||
InputState prevInput{};
|
||||
|
||||
// Emulator state
|
||||
struct gb_s gb{};
|
||||
bool gbReady = false;
|
||||
std::vector<uint8_t> romData;
|
||||
std::vector<uint8_t> cartRam;
|
||||
std::array<uint8_t, LCD_WIDTH * LCD_HEIGHT> frameBuffer{};
|
||||
bool frameDirty = false;
|
||||
std::string activeRomName;
|
||||
std::string activeRomSavePath;
|
||||
struct gb_s gb{};
|
||||
bool gbReady = false;
|
||||
std::vector<uint8_t> romData;
|
||||
std::vector<uint8_t> cartRam;
|
||||
bool frameDirty = false;
|
||||
uint32_t fpsLastSampleMs = 0;
|
||||
uint32_t fpsFrameCounter = 0;
|
||||
uint32_t fpsCurrent = 0;
|
||||
std::string activeRomName;
|
||||
std::string activeRomSavePath;
|
||||
|
||||
bool ensureFilesystemReady() {
|
||||
esp_err_t err = FsHelper::get().mount();
|
||||
@@ -233,7 +237,6 @@ private:
|
||||
browserDirty = false;
|
||||
|
||||
DispTools::draw_to_display_async_wait();
|
||||
framebuffer.clear(false);
|
||||
|
||||
const std::string_view title = "GAME BOY";
|
||||
const int titleWidth = font16x8::measureText(title, 2, 1);
|
||||
@@ -334,6 +337,9 @@ private:
|
||||
activeRomSavePath = buildSavePath(rom.fullPath);
|
||||
loadSaveFile();
|
||||
|
||||
resetFpsStats();
|
||||
fpsLastSampleMs = context.clock.millis();
|
||||
|
||||
gbReady = true;
|
||||
mode = Mode::Running;
|
||||
frameDirty = true;
|
||||
@@ -345,6 +351,7 @@ private:
|
||||
|
||||
void unloadRom() {
|
||||
if (!gbReady) {
|
||||
resetFpsStats();
|
||||
romData.clear();
|
||||
cartRam.clear();
|
||||
activeRomName.clear();
|
||||
@@ -353,6 +360,7 @@ private:
|
||||
}
|
||||
|
||||
maybeSaveRam();
|
||||
resetFpsStats();
|
||||
|
||||
gbReady = false;
|
||||
romData.clear();
|
||||
@@ -401,27 +409,27 @@ private:
|
||||
return;
|
||||
frameDirty = false;
|
||||
|
||||
DispTools::draw_to_display_async_wait();
|
||||
framebuffer.clear(false);
|
||||
|
||||
const int offsetX = (framebuffer.width() - LCD_WIDTH) / 2;
|
||||
const int offsetY = (framebuffer.height() - LCD_HEIGHT) / 2;
|
||||
|
||||
for (int y = 0; y < LCD_HEIGHT; ++y) {
|
||||
const int dstY = offsetY + y;
|
||||
if (dstY < 0 || dstY >= framebuffer.height())
|
||||
continue;
|
||||
for (int x = 0; x < LCD_WIDTH; ++x) {
|
||||
const int dstX = offsetX + x;
|
||||
if (dstX < 0 || dstX >= framebuffer.width())
|
||||
continue;
|
||||
const bool on = frameBuffer[static_cast<std::size_t>(y) * LCD_WIDTH + x] != 0;
|
||||
framebuffer.drawPixel(dstX, dstY, on);
|
||||
}
|
||||
++fpsFrameCounter;
|
||||
const uint32_t nowMs = context.clock.millis();
|
||||
if (fpsLastSampleMs == 0)
|
||||
fpsLastSampleMs = nowMs;
|
||||
const uint32_t elapsed = nowMs - fpsLastSampleMs;
|
||||
if (elapsed >= 1000U) {
|
||||
const uint64_t scaledFrames = static_cast<uint64_t>(fpsFrameCounter) * 1000ULL;
|
||||
fpsCurrent = static_cast<uint32_t>(scaledFrames / elapsed);
|
||||
fpsFrameCounter = 0;
|
||||
fpsLastSampleMs = nowMs;
|
||||
}
|
||||
|
||||
char fpsBuf[16];
|
||||
std::snprintf(fpsBuf, sizeof(fpsBuf), "%u FPS", static_cast<unsigned>(fpsCurrent));
|
||||
const std::string fpsText(fpsBuf);
|
||||
const int fpsWidth = font16x8::measureText(fpsText, 1, 1);
|
||||
const int fpsX = std::max(16, framebuffer.width() - fpsWidth - 16);
|
||||
|
||||
if (!activeRomName.empty())
|
||||
font16x8::drawText(framebuffer, 16, 16, activeRomName, 1, true, 1);
|
||||
font16x8::drawText(framebuffer, fpsX, 16, fpsText, 1, true, 1);
|
||||
font16x8::drawText(framebuffer, 16, framebuffer.height() - 24, "START+SELECT BACK", 1, true, 1);
|
||||
|
||||
DispTools::draw_to_display_async_start();
|
||||
@@ -464,6 +472,12 @@ private:
|
||||
browserDirty = true;
|
||||
}
|
||||
|
||||
void resetFpsStats() {
|
||||
fpsLastSampleMs = 0;
|
||||
fpsFrameCounter = 0;
|
||||
fpsCurrent = 0;
|
||||
}
|
||||
|
||||
static std::string buildSavePath(const std::string& romPath) {
|
||||
std::string result = romPath;
|
||||
const auto dot = result.find_last_of('.');
|
||||
@@ -516,11 +530,20 @@ private:
|
||||
if (!self || line >= LCD_HEIGHT)
|
||||
return;
|
||||
|
||||
const std::size_t offset = static_cast<std::size_t>(line) * LCD_WIDTH;
|
||||
const int offsetX = (self->framebuffer.width() - LCD_WIDTH) / 2;
|
||||
const int offsetY = (self->framebuffer.height() - LCD_HEIGHT) / 2;
|
||||
const int dstY = offsetY + static_cast<int>(line);
|
||||
if (dstY < 0 || dstY >= self->framebuffer.height())
|
||||
return;
|
||||
|
||||
for (int x = 0; x < LCD_WIDTH; ++x) {
|
||||
// Collapse 2-bit colour into monochrome.
|
||||
const uint8_t shade = pixels[x] & 0x03u;
|
||||
self->frameBuffer[offset + static_cast<std::size_t>(x)] = (shade >= 2) ? 1 : 0;
|
||||
const uint8_t shade = pixels[x] & 0x03u;
|
||||
const bool on = (shade >= 2);
|
||||
const int dstX = offsetX + x;
|
||||
if (dstX < 0 || dstX >= self->framebuffer.width())
|
||||
continue;
|
||||
self->framebuffer.drawPixel(dstX, dstY, on);
|
||||
}
|
||||
self->frameDirty = true;
|
||||
}
|
||||
|
||||
@@ -102,13 +102,13 @@ void SMD::async_draw_start() {
|
||||
_tx.tx_buffer = dma_buf;
|
||||
_tx.length = SMD::kLineDataBytes * 8;
|
||||
dma_buf[0] = 0b10000000 | (_vcom << 6);
|
||||
_inFlight = true;
|
||||
_inFlight = true;
|
||||
ESP_ERROR_CHECK(spi_device_queue_trans(_spi, &_tx, 0));
|
||||
}
|
||||
|
||||
void SMD::async_draw_wait() {
|
||||
if (uxSemaphoreGetCount(s_clearSem) || !_inFlight) {
|
||||
assert((uxSemaphoreGetCount(s_clearSem) == 0) == _inFlight);
|
||||
if (!_inFlight || uxSemaphoreGetCount(s_clearSem)) {
|
||||
// assert((uxSemaphoreGetCount(s_clearSem) == 0) == _inFlight);
|
||||
return;
|
||||
}
|
||||
if (!xSemaphoreTake(s_clearSem, portMAX_DELAY))
|
||||
|
||||
Reference in New Issue
Block a user