Add screenshot capture via Joy-Con Capture button

- source/screenshot.c, screenshot.h: take_screenshot() saves framebuffer as BMP
- Path: sd:/switch/screenshot/omninx_installer_YYYYMMDD_HHMMSS.bmp (RTC timestamp)
- 3s cooldown, backlight flash on capture; TegraExplorer-style BGR flip
- main.c: call take_screenshot() when jc->cap in all joycon poll loops

Made-with: Cursor
This commit is contained in:
2026-03-01 14:43:58 +01:00
parent e71fb13bfc
commit 9a2307a8ee
3 changed files with 168 additions and 17 deletions

View File

@@ -35,6 +35,7 @@
#include "fs.h"
#include "version.h"
#include "install.h"
#include "screenshot.h"
// Configuration
#define PAYLOAD_PATH "sd:/bootloader/update.bin"
@@ -264,11 +265,15 @@ void ipl_main(void) {
break;
}
// Check joycon A button
// Check joycon A button; Capture = screenshot
jc_gamepad_rpt_t *jc = joycon_poll();
if (jc && jc->a) {
button_pressed = true;
break;
if (jc) {
if (jc->cap)
take_screenshot();
if (jc->a) {
button_pressed = true;
break;
}
}
msleep(50); // Small delay to avoid busy-waiting
@@ -345,6 +350,9 @@ void ipl_main(void) {
jc_gamepad_rpt_t *jc = joycon_poll();
u8 btn = btn_read();
if (jc && jc->cap)
take_screenshot();
// D-pad or Vol+ / Vol- for selection (Vol+ = up, Vol- = down)
bool cur_up = false, cur_down = false;
if (jc) {
@@ -402,9 +410,13 @@ void ipl_main(void) {
bool user_cancelled = false;
while (batt_pct < BATT_LOW_THRESHOLD && !bq24193_charger_connected() && !user_cancelled) {
jc_gamepad_rpt_t *jc = joycon_poll();
if (jc && jc->plus && jc->minus) {
user_cancelled = true;
break;
if (jc) {
if (jc->cap)
take_screenshot();
if (jc->plus && jc->minus) {
user_cancelled = true;
break;
}
}
if (max17050_get_property(MAX17050_RepSOC, &batt_raw) == 0) {
batt_pct = batt_raw >> 8;
@@ -468,7 +480,11 @@ void ipl_main(void) {
u8 btn_state = btn_read();
if (btn_state & BTN_POWER) acknowledged = true;
jc_gamepad_rpt_t *jc = joycon_poll();
if (jc && jc->a) acknowledged = true;
if (jc) {
if (jc->cap)
take_screenshot();
if (jc->a) acknowledged = true;
}
msleep(50);
}
// Wait for A and Power to be released so the same press doesn't start the install
@@ -530,9 +546,11 @@ void ipl_main(void) {
break;
}
// Check joycon buttons
// Check joycon buttons; Capture = screenshot
jc_gamepad_rpt_t *jc = joycon_poll();
if (jc) {
if (jc->cap)
take_screenshot();
if (jc->a) {
button_pressed = true;
break;
@@ -578,7 +596,8 @@ void ipl_main(void) {
// Wait 3 seconds before clearing screen to allow errors to be visible
msleep(3000);
// take_screenshot(); // Take a screenshot of the installation summary
// Clear screen for final summary to ensure it's visible
gfx_clear_grey(0x1B);
gfx_con_setpos(0, 0);
@@ -630,11 +649,15 @@ void ipl_main(void) {
break;
}
// Check joycon A button
// Check joycon A button; Capture = screenshot
jc_gamepad_rpt_t *jc = joycon_poll();
if (jc && jc->a) {
button_pressed = true;
break;
if (jc) {
if (jc->cap)
take_screenshot();
if (jc->a) {
button_pressed = true;
break;
}
}
msleep(50); // Small delay to avoid busy-waiting
@@ -672,9 +695,13 @@ void ipl_main(void) {
}
jc_gamepad_rpt_t *jc = joycon_poll();
if (jc && jc->a) {
button_pressed = true;
break;
if (jc) {
if (jc->cap)
take_screenshot();
if (jc->a) {
button_pressed = true;
break;
}
}
msleep(50);