Fix frame update logic and emulator support

- Fix basic1.cpp loop to handle set_frame_updates(true) correctly with sleep
- Update emulator loop for concurrent input and frame updates
- Update emulator for SFML 3.0 compatibility
- Add INPUT.FRAME_TICK constant to Lua bindings
- Enable frame updates in snake.lua example
This commit is contained in:
Adolfo Reyna
2026-02-10 23:27:31 -05:00
parent fe5d58b663
commit 47fc02f05c
5 changed files with 65 additions and 38 deletions

View File

@@ -552,8 +552,21 @@ int main()
uint32_t game_start_time = 0;
while (1) {
// Sleep until interrupt wakes us up (very power efficient!)
__wfi(); // Wait For Interrupt - CPU sleeps until any interrupt occurs
// Determine if we should sleep or stay awake for updates
bool stay_awake = false;
if (pending_refresh) stay_awake = true;
if (launcher.is_game_selected()) {
Game* g = launcher.get_selected_game();
if (g && g->wants_frame_updates()) {
stay_awake = true;
}
}
if (!stay_awake) {
// Sleep until interrupt wakes us up (very power efficient!)
__wfi(); // Wait For Interrupt - CPU sleeps until any interrupt occurs
}
InputEvent input = {INPUT_NONE, 0, 0, 0, 0, 0, false};
bool needs_refresh = false;
@@ -639,41 +652,45 @@ int main()
}
needs_refresh = true;
}
} else if (launcher.is_game_selected()) {
}
if (launcher.is_game_selected()) {
// No input, but check if game wants continuous updates
current_game = launcher.get_selected_game();
if (current_game->wants_frame_updates()) {
// Send frame tick event for animation/physics updates
InputEvent frame_tick = {INPUT_FRAME_TICK, 0, 0, 0, 0, 0, true};
needs_refresh = current_game->update(frame_tick);
// Only send frame tick if we're ready to draw the next frame
if (!is_refresh_in_progress()) {
InputEvent frame_tick = {INPUT_FRAME_TICK, 0, 0, 0, 0, 0, true};
needs_refresh = current_game->update(frame_tick) || needs_refresh;
}
}
}
// 4. Redraw and queue async refresh on Core 1
if (needs_refresh || pending_refresh) {
// Clear buffer and redraw entire UI with updated state
memset(bit_buffer, 0, V_WIDTH * V_HEIGHT / 8);
if (launcher.is_game_selected()) {
current_game = launcher.get_selected_game();
current_game->draw();
} else {
launcher.draw();
}
// Request async refresh (non-blocking - handled by Core 1)
bool refresh_started = refresh_screen_async(bit_buffer, display);
if (refresh_started) {
pending_refresh = false; // Refresh queued successfully
} else {
pending_refresh = true; // Core 1 busy, retry next iteration
if (config.debug_verbose) {
printf("Refresh pending - Core 1 still busy\n");
// Only draw if Core 1 is finished with the buffer
if (!is_refresh_in_progress()) {
// Clear buffer and redraw entire UI with updated state
memset(bit_buffer, 0, V_WIDTH * V_HEIGHT / 8);
if (launcher.is_game_selected()) {
current_game = launcher.get_selected_game();
current_game->draw();
} else {
launcher.draw();
}
// Request async refresh (non-blocking - handled by Core 1)
bool refresh_started = refresh_screen_async(bit_buffer, display);
if (refresh_started) {
pending_refresh = false; // Refresh queued successfully
} else {
pending_refresh = true;
}
} else {
pending_refresh = true;
}
// Core 0 continues immediately, Core 1 handles the refresh
}
// 5. Check if display should be dimmed due to inactivity