forked from Mirror/GodMode9
Allow screenshots (almost) everywhere
This commit is contained in:
parent
0ddb5c49d5
commit
67e19ad574
@ -1,7 +1,8 @@
|
|||||||
#include "hid.h"
|
#include "hid.h"
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "power.h"
|
#include "power.h" // for brightness slider
|
||||||
|
#include "screenshot.h" // for screenshots
|
||||||
|
|
||||||
u32 InputWait(u32 timeout_sec) {
|
u32 InputWait(u32 timeout_sec) {
|
||||||
static u64 delay = 0;
|
static u64 delay = 0;
|
||||||
@ -42,8 +43,11 @@ u32 InputWait(u32 timeout_sec) {
|
|||||||
// make sure the key is pressed
|
// make sure the key is pressed
|
||||||
u32 t_pressed = 0;
|
u32 t_pressed = 0;
|
||||||
for(; (t_pressed < 0x13000) && (pad_state == HID_STATE); t_pressed++);
|
for(; (t_pressed < 0x13000) && (pad_state == HID_STATE); t_pressed++);
|
||||||
if (t_pressed >= 0x13000)
|
if (t_pressed >= 0x13000) {
|
||||||
|
if ((pad_state & BUTTON_ANY) == (BUTTON_R1 | BUTTON_L1))
|
||||||
|
CreateScreenshot(); // screenshot handling
|
||||||
return pad_state;
|
return pad_state;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
50
arm9/source/common/screenshot.c
Normal file
50
arm9/source/common/screenshot.c
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#include "common.h"
|
||||||
|
#include "ui.h"
|
||||||
|
#include "vff.h"
|
||||||
|
|
||||||
|
|
||||||
|
void CreateScreenshot() {
|
||||||
|
const u32 snap_size = 54 + (SCREEN_SIZE_TOP * 2);
|
||||||
|
const u8 bmp_header[54] = {
|
||||||
|
0x42, 0x4D, 0x36, 0xCA, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
|
||||||
|
0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0xCA, 0x08, 0x00, 0x12, 0x0B, 0x00, 0x00, 0x12, 0x0B, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
char filename[64];
|
||||||
|
static u32 n = 0;
|
||||||
|
|
||||||
|
fvx_rmkdir(OUTPUT_PATH);
|
||||||
|
for (; n < 1000; n++) {
|
||||||
|
snprintf(filename, 64, OUTPUT_PATH "/snap%03i.bmp", (int) n);
|
||||||
|
if (fvx_stat(filename, NULL) != FR_OK) break;
|
||||||
|
}
|
||||||
|
if (n >= 1000) return;
|
||||||
|
|
||||||
|
u8* buffer = (u8*) malloc(snap_size);
|
||||||
|
if (!buffer) return;
|
||||||
|
|
||||||
|
u8* buffer_b = buffer + 54;
|
||||||
|
u8* buffer_t = buffer_b + (400 * 240 * 3);
|
||||||
|
|
||||||
|
memset(buffer, 0x1F, snap_size); // gray background
|
||||||
|
memcpy(buffer, bmp_header, 54);
|
||||||
|
for (u32 x = 0; x < 400; x++)
|
||||||
|
for (u32 y = 0; y < 240; y++)
|
||||||
|
memcpy(buffer_t + (y*400 + x) * 3, TOP_SCREEN + (x*240 + y) * 3, 3);
|
||||||
|
for (u32 x = 0; x < 320; x++)
|
||||||
|
for (u32 y = 0; y < 240; y++)
|
||||||
|
memcpy(buffer_b + (y*400 + x + 40) * 3, BOT_SCREEN + (x*240 + y) * 3, 3);
|
||||||
|
fvx_qwrite(filename, buffer, 0, snap_size, NULL);
|
||||||
|
|
||||||
|
// "snap effect"
|
||||||
|
memcpy(buffer_b, BOT_SCREEN, SCREEN_SIZE_BOT);
|
||||||
|
memcpy(buffer_t, TOP_SCREEN, SCREEN_SIZE_TOP);
|
||||||
|
memset(BOT_SCREEN, 0, SCREEN_SIZE_BOT);
|
||||||
|
memset(TOP_SCREEN, 0, SCREEN_SIZE_TOP);
|
||||||
|
memcpy(BOT_SCREEN, buffer_b, SCREEN_SIZE_BOT);
|
||||||
|
memcpy(TOP_SCREEN, buffer_t, SCREEN_SIZE_TOP);
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
}
|
3
arm9/source/common/screenshot.h
Normal file
3
arm9/source/common/screenshot.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
void CreateScreenshot();
|
@ -851,41 +851,3 @@ bool FileSelector(char* result, const char* text, const char* path, const char*
|
|||||||
free(buffer);
|
free(buffer);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateScreenshot() {
|
|
||||||
const u32 snap_size = 54 + (400 * 240 * 3 * 2);
|
|
||||||
const u8 bmp_header[54] = {
|
|
||||||
0x42, 0x4D, 0x36, 0xCA, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
|
|
||||||
0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xCA, 0x08, 0x00, 0x12, 0x0B, 0x00, 0x00, 0x12, 0x0B, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
char filename[64];
|
|
||||||
static u32 n = 0;
|
|
||||||
|
|
||||||
fvx_rmkdir(OUTPUT_PATH);
|
|
||||||
for (; n < 1000; n++) {
|
|
||||||
snprintf(filename, 64, OUTPUT_PATH "/snap%03i.bmp", (int) n);
|
|
||||||
if (fa_stat(filename, NULL) != FR_OK) break;
|
|
||||||
}
|
|
||||||
if (n >= 1000) return;
|
|
||||||
|
|
||||||
u8* buffer = (u8*) malloc(snap_size);
|
|
||||||
if (!buffer) return;
|
|
||||||
|
|
||||||
u8* buffer_b = buffer + 54;
|
|
||||||
u8* buffer_t = buffer_b + (400 * 240 * 3);
|
|
||||||
|
|
||||||
memset(buffer, 0x1F, snap_size); // gray background
|
|
||||||
memcpy(buffer, bmp_header, 54);
|
|
||||||
for (u32 x = 0; x < 400; x++)
|
|
||||||
for (u32 y = 0; y < 240; y++)
|
|
||||||
memcpy(buffer_t + (y*400 + x) * 3, TOP_SCREEN + (x*240 + y) * 3, 3);
|
|
||||||
for (u32 x = 0; x < 320; x++)
|
|
||||||
for (u32 y = 0; y < 240; y++)
|
|
||||||
memcpy(buffer_b + (y*400 + x + 40) * 3, BOT_SCREEN + (x*240 + y) * 3, 3);
|
|
||||||
FileSetData(filename, buffer, snap_size, 0, true);
|
|
||||||
|
|
||||||
free(buffer);
|
|
||||||
}
|
|
||||||
|
@ -85,6 +85,3 @@ bool PathAttr(const char* path, u8 attr, u8 mask);
|
|||||||
|
|
||||||
/** Select a file **/
|
/** Select a file **/
|
||||||
bool FileSelector(char* result, const char* text, const char* path, const char* pattern, u32 flags);
|
bool FileSelector(char* result, const char* text, const char* path, const char* pattern, u32 flags);
|
||||||
|
|
||||||
/** Create a screenshot of the current framebuffer **/
|
|
||||||
void CreateScreenshot();
|
|
||||||
|
@ -434,7 +434,7 @@ u32 FileGraphicsViewer(const char* path) {
|
|||||||
ClearScreenF(true, true, COLOR_STD_BG);
|
ClearScreenF(true, true, COLOR_STD_BG);
|
||||||
DrawBitmap(ALT_SCREEN, -1, -1, w, h, bitmap);
|
DrawBitmap(ALT_SCREEN, -1, -1, w, h, bitmap);
|
||||||
ShowString("Press <A> to continue");
|
ShowString("Press <A> to continue");
|
||||||
InputWait(0);
|
while(!(InputWait(0) & (BUTTON_A | BUTTON_B)));
|
||||||
ClearScreenF(true, true, COLOR_STD_BG);
|
ClearScreenF(true, true, COLOR_STD_BG);
|
||||||
} else ret = 1;
|
} else ret = 1;
|
||||||
|
|
||||||
@ -639,8 +639,7 @@ u32 FileHexViewer(const char* path) {
|
|||||||
|
|
||||||
// handle user input
|
// handle user input
|
||||||
u32 pad_state = InputWait(0);
|
u32 pad_state = InputWait(0);
|
||||||
if ((pad_state & BUTTON_R1) && (pad_state & BUTTON_L1)) CreateScreenshot();
|
if (!edit_mode) { // standard viewer mode
|
||||||
else if (!edit_mode) { // standard viewer mode
|
|
||||||
u32 step_ud = (pad_state & BUTTON_R1) ? (0x1000 - (0x1000 % cols)) : cols;
|
u32 step_ud = (pad_state & BUTTON_R1) ? (0x1000 - (0x1000 % cols)) : cols;
|
||||||
u32 step_lr = (pad_state & BUTTON_R1) ? (0x10000 - (0x10000 % cols)) : total_shown;
|
u32 step_lr = (pad_state & BUTTON_R1) ? (0x10000 - (0x10000 % cols)) : total_shown;
|
||||||
if (pad_state & BUTTON_DOWN) offset += step_ud;
|
if (pad_state & BUTTON_DOWN) offset += step_ud;
|
||||||
@ -2244,8 +2243,7 @@ u32 GodMode(int entrypoint) {
|
|||||||
for (u32 c = 1; c < current_dir->n_entries; c++) current_dir->entry[c].marked = 0;
|
for (u32 c = 1; c < current_dir->n_entries; c++) current_dir->entry[c].marked = 0;
|
||||||
mark_next = 0;
|
mark_next = 0;
|
||||||
} else if (switched && (pad_state & BUTTON_L1)) { // switched L -> screenshot
|
} else if (switched && (pad_state & BUTTON_L1)) { // switched L -> screenshot
|
||||||
CreateScreenshot();
|
// this is handled in hid.h
|
||||||
ClearScreenF(true, true, COLOR_STD_BG);
|
|
||||||
} else if (*current_path && (pad_state & BUTTON_L1) && (curr_entry->type != T_DOTDOT)) {
|
} else if (*current_path && (pad_state & BUTTON_L1) && (curr_entry->type != T_DOTDOT)) {
|
||||||
// unswitched L - mark/unmark single entry
|
// unswitched L - mark/unmark single entry
|
||||||
if (mark_next < -1) mark_next = -1;
|
if (mark_next < -1) mark_next = -1;
|
||||||
|
@ -1684,7 +1684,7 @@ u32 ShowSmdhTitleInfo(Smdh* smdh) {
|
|||||||
WordWrapString(desc_s, lwrap);
|
WordWrapString(desc_s, lwrap);
|
||||||
WordWrapString(pub, lwrap);
|
WordWrapString(pub, lwrap);
|
||||||
ShowIconString(icon, SMDH_DIM_ICON_BIG, SMDH_DIM_ICON_BIG, "%s\n%s\n%s", desc_l, desc_s, pub);
|
ShowIconString(icon, SMDH_DIM_ICON_BIG, SMDH_DIM_ICON_BIG, "%s\n%s\n%s", desc_l, desc_s, pub);
|
||||||
InputWait(0);
|
while(!(InputWait(0) & (BUTTON_A | BUTTON_B)));
|
||||||
ClearScreenF(true, false, COLOR_STD_BG);
|
ClearScreenF(true, false, COLOR_STD_BG);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1698,7 +1698,7 @@ u32 ShowTwlIconTitleInfo(TwlIconData* twl_icon) {
|
|||||||
return 1;
|
return 1;
|
||||||
WordWrapString(desc, lwrap);
|
WordWrapString(desc, lwrap);
|
||||||
ShowIconString(icon, TWLICON_DIM_ICON, TWLICON_DIM_ICON, "%s", desc);
|
ShowIconString(icon, TWLICON_DIM_ICON, TWLICON_DIM_ICON, "%s", desc);
|
||||||
InputWait(0);
|
while(!(InputWait(0) & (BUTTON_A | BUTTON_B)));
|
||||||
ClearScreenF(true, false, COLOR_STD_BG);
|
ClearScreenF(true, false, COLOR_STD_BG);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1708,7 +1708,7 @@ u32 ShowGbaFileTitleInfo(const char* path) {
|
|||||||
if ((fvx_qread(path, &agb, 0, sizeof(AgbHeader), NULL) != FR_OK) ||
|
if ((fvx_qread(path, &agb, 0, sizeof(AgbHeader), NULL) != FR_OK) ||
|
||||||
(ValidateAgbHeader(&agb) != 0)) return 1;
|
(ValidateAgbHeader(&agb) != 0)) return 1;
|
||||||
ShowString("%.12s (AGB-%.4s)\n%s", agb.game_title, agb.game_code, AGB_DESTSTR(agb.game_code));
|
ShowString("%.12s (AGB-%.4s)\n%s", agb.game_title, agb.game_code, AGB_DESTSTR(agb.game_code));
|
||||||
InputWait(0);
|
while(!(InputWait(0) & (BUTTON_A | BUTTON_B)));
|
||||||
ClearScreenF(true, false, COLOR_STD_BG);
|
ClearScreenF(true, false, COLOR_STD_BG);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -1461,38 +1461,35 @@ bool MemTextViewer(const char* text, u32 len, u32 start, bool as_script) {
|
|||||||
|
|
||||||
// handle user input
|
// handle user input
|
||||||
u32 pad_state = InputWait(0);
|
u32 pad_state = InputWait(0);
|
||||||
if ((pad_state & BUTTON_R1) && (pad_state & BUTTON_L1)) CreateScreenshot();
|
char* line0_next = line0;
|
||||||
else { // standard viewer mode
|
u32 step_ud = (pad_state & BUTTON_R1) ? TV_NLIN_DISP : 1;
|
||||||
char* line0_next = line0;
|
u32 step_lr = (pad_state & BUTTON_R1) ? TV_LLEN_DISP : 1;
|
||||||
u32 step_ud = (pad_state & BUTTON_R1) ? TV_NLIN_DISP : 1;
|
bool switched = (pad_state & BUTTON_R1);
|
||||||
u32 step_lr = (pad_state & BUTTON_R1) ? TV_LLEN_DISP : 1;
|
if (pad_state & BUTTON_DOWN) line0_next = line_seek(text, len, ww, line0, step_ud);
|
||||||
bool switched = (pad_state & BUTTON_R1);
|
else if (pad_state & BUTTON_UP) line0_next = line_seek(text, len, ww, line0, -step_ud);
|
||||||
if (pad_state & BUTTON_DOWN) line0_next = line_seek(text, len, ww, line0, step_ud);
|
else if (pad_state & BUTTON_RIGHT) off_disp += step_lr;
|
||||||
else if (pad_state & BUTTON_UP) line0_next = line_seek(text, len, ww, line0, -step_ud);
|
else if (pad_state & BUTTON_LEFT) off_disp -= step_lr;
|
||||||
else if (pad_state & BUTTON_RIGHT) off_disp += step_lr;
|
else if (switched && (pad_state & BUTTON_X)) {
|
||||||
else if (pad_state & BUTTON_LEFT) off_disp -= step_lr;
|
u64 lnext64 = ShowNumberPrompt(lcurr, "Current line: %i\nEnter new line below.", lcurr);
|
||||||
else if (switched && (pad_state & BUTTON_X)) {
|
if (lnext64 && (lnext64 != (u64) -1)) line0_next = line_seek(text, len, 0, line0, (int) lnext64 - lcurr);
|
||||||
u64 lnext64 = ShowNumberPrompt(lcurr, "Current line: %i\nEnter new line below.", lcurr);
|
ShowString(instr);
|
||||||
if (lnext64 && (lnext64 != (u64) -1)) line0_next = line_seek(text, len, 0, line0, (int) lnext64 - lcurr);
|
} else if (switched && (pad_state & BUTTON_Y)) {
|
||||||
ShowString(instr);
|
ww = ww ? 0 : TV_LLEN_DISP;
|
||||||
} else if (switched && (pad_state & BUTTON_Y)) {
|
line0_next = line_seek(text, len, ww, line0, 0);
|
||||||
ww = ww ? 0 : TV_LLEN_DISP;
|
} else if (pad_state & (BUTTON_B|BUTTON_START)) break;
|
||||||
line0_next = line_seek(text, len, ww, line0, 0);
|
|
||||||
} else if (pad_state & (BUTTON_B|BUTTON_START)) break;
|
// check for problems, apply changes
|
||||||
|
if (!ww && (line0_next > llast_nww)) line0_next = llast_nww;
|
||||||
// check for problems, apply changes
|
else if (ww && (line0_next > llast_ww)) line0_next = llast_ww;
|
||||||
if (!ww && (line0_next > llast_nww)) line0_next = llast_nww;
|
if (line0_next < line0) { // fix line number for decrease
|
||||||
else if (ww && (line0_next > llast_ww)) line0_next = llast_ww;
|
do if (*(--line0) == '\n') lcurr--;
|
||||||
if (line0_next < line0) { // fix line number for decrease
|
while (line0 > line0_next);
|
||||||
do if (*(--line0) == '\n') lcurr--;
|
} else { // fix line number for increase / same
|
||||||
while (line0 > line0_next);
|
for (; line0_next > line0; line0++)
|
||||||
} else { // fix line number for increase / same
|
if (*line0 == '\n') lcurr++;
|
||||||
for (; line0_next > line0; line0++)
|
|
||||||
if (*line0 == '\n') lcurr++;
|
|
||||||
}
|
|
||||||
if (off_disp + TV_LLEN_DISP > llen_max) off_disp = llen_max - TV_LLEN_DISP;
|
|
||||||
if ((off_disp < 0) || ww) off_disp = 0;
|
|
||||||
}
|
}
|
||||||
|
if (off_disp + TV_LLEN_DISP > llen_max) off_disp = llen_max - TV_LLEN_DISP;
|
||||||
|
if ((off_disp < 0) || ww) off_disp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear screens
|
// clear screens
|
||||||
|
Loading…
x
Reference in New Issue
Block a user