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)
|
||||
{
|
||||
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)
|
||||
|
||||
@ -44,3 +44,5 @@ void RosalinaMenu_ShowSystemInfo();
|
||||
|
||||
bool rosalinaMenuShouldShowDebugInfo(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)
|
||||
{
|
||||
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)
|
||||
|
||||
@ -40,6 +40,8 @@
|
||||
#include "menus/screen_filters.h"
|
||||
#include "shell.h"
|
||||
|
||||
//#define ROSALINA_MENU_SELF_SCREENSHOT 1 // uncomment this to enable the feature
|
||||
|
||||
u32 menuCombo = 0;
|
||||
bool isHidInitialized = false;
|
||||
bool isQtmInitialized = false;
|
||||
@ -61,10 +63,22 @@ bool hidShouldUseIrrst(void)
|
||||
|
||||
static inline u32 convertHidKeys(u32 keys)
|
||||
{
|
||||
// Nothing to do yet
|
||||
// No actual conversion done
|
||||
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)
|
||||
{
|
||||
s32 n = 0;
|
||||
@ -82,7 +96,7 @@ u32 waitInputWithTimeout(s32 msec)
|
||||
}
|
||||
n++;
|
||||
|
||||
hidScanInput();
|
||||
scanInputHook();
|
||||
keys = convertHidKeys(hidKeysDown()) | (convertHidKeys(hidKeysDownRepeat()) & DIRECTIONAL_KEYS);
|
||||
Draw_Unlock();
|
||||
} while (keys == 0 && !menuShouldExit && isHidInitialized && (msec < 0 || n < msec));
|
||||
@ -108,7 +122,7 @@ u32 waitInputWithTimeoutEx(u32 *outHeldKeys, s32 msec)
|
||||
}
|
||||
n++;
|
||||
|
||||
hidScanInput();
|
||||
scanInputHook();
|
||||
keys = convertHidKeys(hidKeysDown()) | (convertHidKeys(hidKeysDownRepeat()) & DIRECTIONAL_KEYS);
|
||||
*outHeldKeys = convertHidKeys(hidKeysHeld());
|
||||
Draw_Unlock();
|
||||
@ -133,7 +147,7 @@ static u32 scanHeldKeys(void)
|
||||
keys = 0;
|
||||
else
|
||||
{
|
||||
hidScanInput();
|
||||
scanInputHook();
|
||||
keys = convertHidKeys(hidKeysHeld());
|
||||
}
|
||||
|
||||
@ -362,7 +376,9 @@ void menuThreadMain(void)
|
||||
|
||||
Cheat_ApplyCheats();
|
||||
|
||||
if(((scanHeldKeys() & menuCombo) == menuCombo) && !g_blockMenuOpen)
|
||||
u32 kHeld = scanHeldKeys();
|
||||
|
||||
if(((kHeld & menuCombo) == menuCombo) && !g_blockMenuOpen)
|
||||
{
|
||||
menuEnter();
|
||||
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]);
|
||||
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
|
||||
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)
|
||||
{
|
||||
IFile file;
|
||||
IFile file = {0};
|
||||
Result res = 0;
|
||||
|
||||
char filename[64];
|
||||
@ -340,6 +340,11 @@ void RosalinaMenu_TakeScreenshot(void)
|
||||
res = 0;
|
||||
FSUSER_CloseArchive(archive);
|
||||
}
|
||||
else
|
||||
{
|
||||
archive = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
dateTimeToString(dateTimeStr, osGetTime(), true);
|
||||
|
||||
@ -364,6 +369,9 @@ void RosalinaMenu_TakeScreenshot(void)
|
||||
end:
|
||||
IFile_Close(&file);
|
||||
|
||||
if (archive != 0)
|
||||
FSUSER_CloseArchive(archive);
|
||||
|
||||
if (R_FAILED(Draw_AllocateFramebufferCache(FB_BOTTOM_SIZE)))
|
||||
__builtin_trap(); // We're f***ed if this happens
|
||||
|
||||
@ -391,6 +399,91 @@ end:
|
||||
Draw_Unlock();
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user