diff --git a/source/frontend/gui.c b/source/frontend/gui.c new file mode 100644 index 0000000..da5525a --- /dev/null +++ b/source/frontend/gui.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2018-2021 CTCaer + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "../gfx/gfx.h" +#include +#include +#include +#include + +#include + +int save_fb_to_bmp() +{ + // Disallow screenshots if less than 2s passed. + static u32 timer = 0; + if (get_tmr_ms() < timer) + return 1; + + const u32 file_size = 0x384000 + 0x36; + u8 *bitmap = malloc(file_size); + u32 *fb = malloc(0x384000); + u32 *fb_ptr = gfx_ctxt.fb; + + // Reconstruct FB for bottom-top, portrait bmp. + for (int y = 1279; y > -1; y--) + { + for (u32 x = 0; x < 720; x++) + fb[y * 720 + x] = *fb_ptr++; + } + + memcpy(bitmap + 0x36, fb, 0x384000); + + typedef struct _bmp_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; + } __attribute__((packed)) bmp_t; + + bmp_t *bmp = (bmp_t *)bitmap; + + bmp->magic = 0x4D42; + bmp->size = file_size; + bmp->rsvd = 0; + bmp->data_off = 0x36; + bmp->hdr_size = 40; + bmp->width = 720; + bmp->height = 1280; + bmp->planes = 1; + bmp->pxl_bits = 32; + bmp->comp = 0; + bmp->img_size = 0x384000; + bmp->res_h = 2834; + bmp->res_v = 2834; + bmp->rsvd2 = 0; + + sd_mount(); + + f_mkdir("sd:/switch"); + + char path[0x80] = "sd:/switch/lockpick_rcm.bmp"; + + // Save screenshot and log. + int res = sd_save_to_file(bitmap, file_size, path); + + // sd_unmount(); + + free(bitmap); + free(fb); + + // Set timer to 2s. + timer = get_tmr_ms() + 2000; + + return res; +} diff --git a/source/frontend/gui.h b/source/frontend/gui.h new file mode 100644 index 0000000..b6c45aa --- /dev/null +++ b/source/frontend/gui.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2018-2021 CTCaer + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +int save_fb_to_bmp(); diff --git a/source/gfx/gfx.c b/source/gfx/gfx.c index db57ec1..55b41c8 100644 --- a/source/gfx/gfx.c +++ b/source/gfx/gfx.c @@ -224,7 +224,7 @@ void gfx_putc(char c) cbuf++; } gfx_con.x += 16; - if (gfx_con.x >= gfx_ctxt.width - 16) + if (gfx_con.x > gfx_ctxt.width - 16) { gfx_con.x = 0; gfx_con.y += 16; @@ -233,7 +233,7 @@ void gfx_putc(char c) else if (c == '\n') { gfx_con.x = 0; - gfx_con.y +=16; + gfx_con.y += 16; if (gfx_con.y > gfx_ctxt.height - 16) gfx_con.y = 0; } @@ -259,7 +259,7 @@ void gfx_putc(char c) fb += gfx_ctxt.stride - 8; } gfx_con.x += 8; - if (gfx_con.x >= gfx_ctxt.width - 8) + if (gfx_con.x > gfx_ctxt.width - 8) { gfx_con.x = 0; gfx_con.y += 8; diff --git a/source/keys/keys.c b/source/keys/keys.c index fdf2761..f800566 100644 --- a/source/keys/keys.c +++ b/source/keys/keys.c @@ -900,8 +900,18 @@ void dump_keys() { } minerva_change_freq(FREQ_800); - gfx_printf("\n%kPress a button to return to the menu.", colors[(color_idx) % 6], colors[(color_idx + 1) % 6], colors[(color_idx + 2) % 6]); - btn_wait(); + gfx_printf("\n%kPress VOL+ to save a screenshot\n or another button to return to the menu.\n\n", colors[(color_idx++) % 6]); + u8 btn = btn_wait(); + if (btn == BTN_VOL_UP) { + int res = save_fb_to_bmp(); + if (!res) { + gfx_printf("%kScreenshot sd:/switch/lockpick_rcm.bmp saved.", colors[(color_idx++) % 6]); + } else { + EPRINTF("Screenshot failed."); + } + gfx_printf("\n%kPress a button to return to the menu.", colors[(color_idx++) % 6]); + btn_wait(); + } gfx_clear_grey(0x1B); }