/* * Screenshot support for OmniNX Installer Payload * Based on TegraExplorer (AllgemeinerProblemLoeser) TakeScreenshot implementation. */ #include "screenshot.h" #include "gfx.h" #include "nx_sd.h" #include #include #include #include #include #include #include /* BMP file header (54 bytes), matching TegraExplorer tools.h */ typedef struct __attribute__((packed)) _bmp_hdr_t { u16 magic; u32 size; u32 rsvd; u32 data_off; u32 hdr_size; u32 width; u32 height; u16 planes; u16 pxl_bits; u32 comp; u32 img_size; u32 res_h; u32 res_v; u64 rsvd2; } bmp_hdr_t; #define BMP_HEADER_SIZE 0x36 #define FB_SIZE 0x384000 /* 1280 * 720 * 4 */ #define SCREEN_W 1280 #define SCREEN_H 720 void take_screenshot(void) { static u32 last_timer = 0; if (!sd_get_card_mounted()) return; /* 3-second cooldown (same as TegraExplorer) */ u32 now = get_tmr_s(); if (last_timer != 0 && now < last_timer + 3) return; last_timer = now; const char basepath[] = "sd:/switch/screenshot"; char name[48]; char path[80]; rtc_time_t rtc; max77620_rtc_get_time(&rtc); s_printf(name, "omninx_installer_%04d%02d%02d_%02d%02d%02d.bmp", (u32)rtc.year, (u32)rtc.month, (u32)rtc.day, (u32)rtc.hour, (u32)rtc.min, (u32)rtc.sec); s_printf(path, "%s/%s", basepath, name); f_mkdir("sd:/switch"); f_mkdir(basepath); const u32 file_size = BMP_HEADER_SIZE + FB_SIZE; u8 *bitmap = (u8 *)malloc(file_size); u32 *fb_copy = (u32 *)malloc(FB_SIZE); if (!bitmap || !fb_copy) { if (bitmap) free(bitmap); if (fb_copy) free(fb_copy); return; } /* Copy framebuffer with same coordinate flip as TegraExplorer (BGR layout) */ u32 *fb_ptr = gfx_ctxt.fb; for (int x = SCREEN_W - 1; x >= 0; x--) { for (int y = SCREEN_H - 1; y >= 0; y--) fb_copy[y * SCREEN_W + x] = *fb_ptr++; } memcpy(bitmap + BMP_HEADER_SIZE, fb_copy, FB_SIZE); bmp_hdr_t *bmp = (bmp_hdr_t *)bitmap; bmp->magic = 0x4D42; bmp->size = file_size; bmp->rsvd = 0; bmp->data_off = BMP_HEADER_SIZE; bmp->hdr_size = 40; bmp->width = SCREEN_W; bmp->height = SCREEN_H; bmp->planes = 1; bmp->pxl_bits = 32; bmp->comp = 0; bmp->img_size = FB_SIZE; bmp->res_h = 2834; bmp->res_v = 2834; bmp->rsvd2 = 0; sd_save_to_file(bitmap, file_size, path); free(bitmap); free(fb_copy); /* Brief backlight flash (same as TegraExplorer) */ display_backlight_brightness(255, 1000); msleep(100); display_backlight_brightness(100, 1000); }