mirror of
https://github.com/LumaTeam/Luma3DS.git
synced 2026-02-22 01:44:38 +00:00
rosalina: add ability to menu to take screenshot of itself (default combo: L+Up+Select)
Only for documentation purposes, via compile-time flag. And fix some resource leak bugs, etc.
This commit is contained in:
parent
7e4a106787
commit
ef1773ef4a
@ -23,7 +23,9 @@ Result IFile_OpenFromArchive(IFile *file, FS_Archive archive, FS_Path filePath,
|
|||||||
|
|
||||||
Result IFile_Close(IFile *file)
|
Result IFile_Close(IFile *file)
|
||||||
{
|
{
|
||||||
return FSFILE_Close(file->handle);
|
Result res = file->handle != 0 ? FSFILE_Close(file->handle) : 0;
|
||||||
|
file->handle = 0;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IFile_GetSize(IFile *file, u64 *size)
|
Result IFile_GetSize(IFile *file, u64 *size)
|
||||||
|
|||||||
@ -44,3 +44,5 @@ void RosalinaMenu_ShowSystemInfo();
|
|||||||
|
|
||||||
bool rosalinaMenuShouldShowDebugInfo(void);
|
bool rosalinaMenuShouldShowDebugInfo(void);
|
||||||
void RosalinaMenu_ShowDebugInfo(void);
|
void RosalinaMenu_ShowDebugInfo(void);
|
||||||
|
|
||||||
|
void menuTakeSelfScreenshot(void);
|
||||||
|
|||||||
@ -49,7 +49,9 @@ Result IFile_OpenFromArchive(IFile *file, FS_Archive archive, FS_Path filePath,
|
|||||||
|
|
||||||
Result IFile_Close(IFile *file)
|
Result IFile_Close(IFile *file)
|
||||||
{
|
{
|
||||||
return FSFILE_Close(file->handle);
|
Result res = file->handle != 0 ? FSFILE_Close(file->handle) : 0;
|
||||||
|
file->handle = 0;
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IFile_GetSize(IFile *file, u64 *size)
|
Result IFile_GetSize(IFile *file, u64 *size)
|
||||||
|
|||||||
@ -40,6 +40,8 @@
|
|||||||
#include "menus/screen_filters.h"
|
#include "menus/screen_filters.h"
|
||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
|
|
||||||
|
//#define ROSALINA_MENU_SELF_SCREENSHOT 1 // uncomment this to enable the feature
|
||||||
|
|
||||||
u32 menuCombo = 0;
|
u32 menuCombo = 0;
|
||||||
bool isHidInitialized = false;
|
bool isHidInitialized = false;
|
||||||
bool isQtmInitialized = false;
|
bool isQtmInitialized = false;
|
||||||
@ -61,10 +63,22 @@ bool hidShouldUseIrrst(void)
|
|||||||
|
|
||||||
static inline u32 convertHidKeys(u32 keys)
|
static inline u32 convertHidKeys(u32 keys)
|
||||||
{
|
{
|
||||||
// Nothing to do yet
|
// No actual conversion done
|
||||||
return keys;
|
return keys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void scanInputHook(void)
|
||||||
|
{
|
||||||
|
hidScanInput();
|
||||||
|
|
||||||
|
#ifdef ROSALINA_MENU_SELF_SCREENSHOT
|
||||||
|
// Ugly hack but should work. For self-documentation w/o capture card purposes only.
|
||||||
|
u32 selfScreenshotCombo = KEY_L | KEY_DUP | KEY_SELECT;
|
||||||
|
if ((hidKeysHeld() & selfScreenshotCombo) == selfScreenshotCombo && (hidKeysDown() & selfScreenshotCombo) != 0)
|
||||||
|
menuTakeSelfScreenshot();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
u32 waitInputWithTimeout(s32 msec)
|
u32 waitInputWithTimeout(s32 msec)
|
||||||
{
|
{
|
||||||
s32 n = 0;
|
s32 n = 0;
|
||||||
@ -82,7 +96,7 @@ u32 waitInputWithTimeout(s32 msec)
|
|||||||
}
|
}
|
||||||
n++;
|
n++;
|
||||||
|
|
||||||
hidScanInput();
|
scanInputHook();
|
||||||
keys = convertHidKeys(hidKeysDown()) | (convertHidKeys(hidKeysDownRepeat()) & DIRECTIONAL_KEYS);
|
keys = convertHidKeys(hidKeysDown()) | (convertHidKeys(hidKeysDownRepeat()) & DIRECTIONAL_KEYS);
|
||||||
Draw_Unlock();
|
Draw_Unlock();
|
||||||
} while (keys == 0 && !menuShouldExit && isHidInitialized && (msec < 0 || n < msec));
|
} while (keys == 0 && !menuShouldExit && isHidInitialized && (msec < 0 || n < msec));
|
||||||
@ -108,7 +122,7 @@ u32 waitInputWithTimeoutEx(u32 *outHeldKeys, s32 msec)
|
|||||||
}
|
}
|
||||||
n++;
|
n++;
|
||||||
|
|
||||||
hidScanInput();
|
scanInputHook();
|
||||||
keys = convertHidKeys(hidKeysDown()) | (convertHidKeys(hidKeysDownRepeat()) & DIRECTIONAL_KEYS);
|
keys = convertHidKeys(hidKeysDown()) | (convertHidKeys(hidKeysDownRepeat()) & DIRECTIONAL_KEYS);
|
||||||
*outHeldKeys = convertHidKeys(hidKeysHeld());
|
*outHeldKeys = convertHidKeys(hidKeysHeld());
|
||||||
Draw_Unlock();
|
Draw_Unlock();
|
||||||
@ -133,7 +147,7 @@ static u32 scanHeldKeys(void)
|
|||||||
keys = 0;
|
keys = 0;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
hidScanInput();
|
scanInputHook();
|
||||||
keys = convertHidKeys(hidKeysHeld());
|
keys = convertHidKeys(hidKeysHeld());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,7 +376,9 @@ void menuThreadMain(void)
|
|||||||
|
|
||||||
Cheat_ApplyCheats();
|
Cheat_ApplyCheats();
|
||||||
|
|
||||||
if(((scanHeldKeys() & menuCombo) == menuCombo) && !g_blockMenuOpen)
|
u32 kHeld = scanHeldKeys();
|
||||||
|
|
||||||
|
if(((kHeld & menuCombo) == menuCombo) && !g_blockMenuOpen)
|
||||||
{
|
{
|
||||||
menuEnter();
|
menuEnter();
|
||||||
if(isN3DS) N3DSMenu_UpdateStatus();
|
if(isN3DS) N3DSMenu_UpdateStatus();
|
||||||
@ -459,14 +475,7 @@ static void menuDraw(Menu *menu, u32 selected)
|
|||||||
int n = sprintf(ipBuffer, "%hhu.%hhu.%hhu.%hhu", addr[0], addr[1], addr[2], addr[3]);
|
int n = sprintf(ipBuffer, "%hhu.%hhu.%hhu.%hhu", addr[0], addr[1], addr[2], addr[3]);
|
||||||
Draw_DrawString(SCREEN_BOT_WIDTH - 10 - SPACING_X * n, 10, COLOR_WHITE, ipBuffer);
|
Draw_DrawString(SCREEN_BOT_WIDTH - 10 - SPACING_X * n, 10, COLOR_WHITE, ipBuffer);
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
else if (areScreenTypesInitialized)
|
|
||||||
{
|
|
||||||
char screenTypesBuffer[32];
|
|
||||||
int n = sprintf(screenTypesBuffer, "T: %s | B: %s", topScreenType, bottomScreenType);
|
|
||||||
Draw_DrawString(SCREEN_BOT_WIDTH - 10 - SPACING_X * n, 10, COLOR_WHITE, screenTypesBuffer);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else
|
else
|
||||||
Draw_DrawFormattedString(SCREEN_BOT_WIDTH - 10 - SPACING_X * 15, 10, COLOR_WHITE, "%15s", "");
|
Draw_DrawFormattedString(SCREEN_BOT_WIDTH - 10 - SPACING_X * 15, 10, COLOR_WHITE, "%15s", "");
|
||||||
|
|
||||||
|
|||||||
@ -302,7 +302,7 @@ static Result RosalinaMenu_WriteScreenshot(IFile *file, u32 width, bool top, boo
|
|||||||
|
|
||||||
void RosalinaMenu_TakeScreenshot(void)
|
void RosalinaMenu_TakeScreenshot(void)
|
||||||
{
|
{
|
||||||
IFile file;
|
IFile file = {0};
|
||||||
Result res = 0;
|
Result res = 0;
|
||||||
|
|
||||||
char filename[64];
|
char filename[64];
|
||||||
@ -340,6 +340,11 @@ void RosalinaMenu_TakeScreenshot(void)
|
|||||||
res = 0;
|
res = 0;
|
||||||
FSUSER_CloseArchive(archive);
|
FSUSER_CloseArchive(archive);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
archive = 0;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
dateTimeToString(dateTimeStr, osGetTime(), true);
|
dateTimeToString(dateTimeStr, osGetTime(), true);
|
||||||
|
|
||||||
@ -364,6 +369,9 @@ void RosalinaMenu_TakeScreenshot(void)
|
|||||||
end:
|
end:
|
||||||
IFile_Close(&file);
|
IFile_Close(&file);
|
||||||
|
|
||||||
|
if (archive != 0)
|
||||||
|
FSUSER_CloseArchive(archive);
|
||||||
|
|
||||||
if (R_FAILED(Draw_AllocateFramebufferCache(FB_BOTTOM_SIZE)))
|
if (R_FAILED(Draw_AllocateFramebufferCache(FB_BOTTOM_SIZE)))
|
||||||
__builtin_trap(); // We're f***ed if this happens
|
__builtin_trap(); // We're f***ed if this happens
|
||||||
|
|
||||||
@ -391,6 +399,91 @@ end:
|
|||||||
Draw_Unlock();
|
Draw_Unlock();
|
||||||
}
|
}
|
||||||
while(!(waitInput() & KEY_B) && !menuShouldExit);
|
while(!(waitInput() & KEY_B) && !menuShouldExit);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Result menuWriteSelfScreenshot(IFile *file)
|
||||||
|
{
|
||||||
|
u64 total;
|
||||||
|
Result res = 0;
|
||||||
|
|
||||||
|
u32 width = 320;
|
||||||
|
u32 lineSize = 3 * width;
|
||||||
|
|
||||||
|
u32 scaleFactorY = 1;
|
||||||
|
u32 numLinesScaled = 240 * scaleFactorY;
|
||||||
|
|
||||||
|
u32 addr = 0x0D800000; // keep this in check
|
||||||
|
u32 tmp;
|
||||||
|
|
||||||
|
u32 size = ((54 + lineSize * numLinesScaled * scaleFactorY) + 0xFFF) >> 12 << 12; // round-up
|
||||||
|
u8 *buffer = NULL;
|
||||||
|
|
||||||
|
TRY(svcControlMemoryEx(&tmp, addr, 0, size, MEMOP_ALLOC | MEMOP_REGION_SYSTEM, MEMPERM_READWRITE, true));
|
||||||
|
buffer = (u8 *)addr;
|
||||||
|
|
||||||
|
Draw_CreateBitmapHeader(buffer, width, numLinesScaled);
|
||||||
|
|
||||||
|
Draw_ConvertFrameBufferLines(buffer + 54, width, 0, numLinesScaled, scaleFactorY, false, false);
|
||||||
|
TRY(IFile_Write(file, &total, buffer, 54 + lineSize * numLinesScaled * scaleFactorY, 0)); // don't forget to write the header
|
||||||
|
|
||||||
|
end:
|
||||||
|
if (buffer)
|
||||||
|
svcControlMemoryEx(&tmp, addr, 0, size, MEMOP_FREE, MEMPERM_DONTCARE, false);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void menuTakeSelfScreenshot(void)
|
||||||
|
{
|
||||||
|
// Optimized for N3DS. May fail due to OOM.
|
||||||
|
|
||||||
|
IFile file = {0};
|
||||||
|
Result res = 0;
|
||||||
|
|
||||||
|
char filename[100];
|
||||||
|
char dateTimeStr[64];
|
||||||
|
|
||||||
|
FS_Archive archive;
|
||||||
|
FS_ArchiveID archiveId;
|
||||||
|
s64 out;
|
||||||
|
bool isSdMode;
|
||||||
|
|
||||||
|
timeSpentConvertingScreenshot = 0;
|
||||||
|
timeSpentWritingScreenshot = 0;
|
||||||
|
|
||||||
|
if(R_FAILED(svcGetSystemInfo(&out, 0x10000, 0x203))) svcBreak(USERBREAK_ASSERT);
|
||||||
|
isSdMode = (bool)out;
|
||||||
|
|
||||||
|
archiveId = isSdMode ? ARCHIVE_SDMC : ARCHIVE_NAND_RW;
|
||||||
|
Draw_Lock();
|
||||||
|
svcFlushEntireDataCache();
|
||||||
|
|
||||||
|
res = FSUSER_OpenArchive(&archive, archiveId, fsMakePath(PATH_EMPTY, ""));
|
||||||
|
if(R_SUCCEEDED(res))
|
||||||
|
{
|
||||||
|
res = FSUSER_CreateDirectory(archive, fsMakePath(PATH_ASCII, "/luma/screenshots"), 0);
|
||||||
|
if((u32)res == 0xC82044BE) // directory already exists
|
||||||
|
res = 0;
|
||||||
|
FSUSER_CloseArchive(archive);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
archive = 0;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
dateTimeToString(dateTimeStr, osGetTime(), true);
|
||||||
|
|
||||||
|
sprintf(filename, "/luma/screenshots/rosalina_menu_%s.bmp", dateTimeStr);
|
||||||
|
|
||||||
|
TRY(IFile_Open(&file, archiveId, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, filename), FS_OPEN_CREATE | FS_OPEN_WRITE));
|
||||||
|
TRY(menuWriteSelfScreenshot(&file));
|
||||||
|
|
||||||
|
end:
|
||||||
|
IFile_Close(&file);
|
||||||
|
|
||||||
|
if (archive != 0)
|
||||||
|
FSUSER_CloseArchive(archive);
|
||||||
|
}
|
||||||
|
|
||||||
#undef TRY
|
#undef TRY
|
||||||
}
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user