diff --git a/sysmodules/rosalina/include/draw.h b/sysmodules/rosalina/include/draw.h index 4a7b0b6..426fd31 100644 --- a/sysmodules/rosalina/include/draw.h +++ b/sysmodules/rosalina/include/draw.h @@ -57,7 +57,7 @@ #define FB_BOTTOM_VRAM_ADDR ((void *)0x1F48F000) // cached #define FB_BOTTOM_VRAM_PA 0x1848F000 #define FB_BOTTOM_SIZE (320 * 240 * 2) -#define FB_SCREENSHOT_SIZE (52 + 400 * 240 * 2) +#define FB_SCREENSHOT_SIZE (52 + 400 * 240 * 3) #define SCREEN_BOT_WIDTH 320 diff --git a/sysmodules/rosalina/source/draw.c b/sysmodules/rosalina/source/draw.c index 67d23db..94260aa 100644 --- a/sysmodules/rosalina/source/draw.c +++ b/sysmodules/rosalina/source/draw.c @@ -164,7 +164,7 @@ void *Draw_GetFramebufferCache(void) return framebufferCache; } -u32 Draw_GetFramebufferSize(void) +u32 Draw_GetFramebufferCacheSize(void) { return framebufferCacheSize; } diff --git a/sysmodules/rosalina/source/menus.c b/sysmodules/rosalina/source/menus.c index b5496dd..9e843b1 100644 --- a/sysmodules/rosalina/source/menus.c +++ b/sysmodules/rosalina/source/menus.c @@ -151,14 +151,52 @@ void RosalinaMenu_PowerOff(void) // Soft shutdown. while(!terminationRequest); } -void RosalinaMenu_TakeScreenshot(void) -{ - u8 *framebufferCache = (u8 *)Draw_GetFramebufferCache(); + #define TRY(expr) if(R_FAILED(res = (expr))) goto end; +static s64 timeSpentConvertingScreenshot = 0; +static s64 timeSpentWritingScreenshot = 0; + +static Result RosalinaMenu_WriteScreenshot(IFile *file, bool top, bool left) +{ u64 total; + Result res = 0; + u32 dimX = top ? 400 : 320; + u32 lineSize = 3 * dimX; + u32 remaining = lineSize * 240; + u8 *framebufferCache = (u8 *)Draw_GetFramebufferCache(); + u8 *framebufferCacheEnd = framebufferCache + Draw_GetFramebufferCacheSize(); + + u8 *buf = framebufferCache; + Draw_CreateBitmapHeader(framebufferCache, dimX, 240); + buf += 54; + + u32 n = 0; + // Our buffer might be smaller than the size of the screenshot... + while (remaining != 0) + { + s64 t0 = svcGetSystemTick(); + u32 available = (u32)(framebufferCacheEnd - buf); + u32 size = available < remaining ? available : remaining; + u32 nlines = size / lineSize; + for (u32 y = 0; y < nlines; y++) + Draw_ConvertFrameBufferLine(buf + lineSize * y, top, left, y); + + s64 t1 = svcGetSystemTick(); + timeSpentConvertingScreenshot += t1 - t0; + TRY(IFile_Write(file, &total, framebufferCache, (n == 0 ? 54 : 0) + lineSize * nlines, 0)); // don't forget to write the header + timeSpentWritingScreenshot += svcGetSystemTick() - t1; + + remaining -= lineSize * nlines; + buf = framebufferCache; + } + end: return res; +} + +void RosalinaMenu_TakeScreenshot(void) +{ IFile file; - Result res; + Result res = 0; char filename[64]; @@ -167,6 +205,9 @@ void RosalinaMenu_TakeScreenshot(void) s64 out; bool isSdMode; + timeSpentConvertingScreenshot = 0; + timeSpentWritingScreenshot = 0; + if(R_FAILED(svcGetSystemInfo(&out, 0x10000, 0x203))) svcBreak(USERBREAK_ASSERT); isSdMode = (bool)out; @@ -230,49 +271,19 @@ void RosalinaMenu_TakeScreenshot(void) sprintf(filename, "/luma/screenshots/%04lu-%02lu-%02lu_%02lu-%02lu-%02lu.%03llu_top.bmp", year, month, days, hours, minutes, seconds, milliseconds); TRY(IFile_Open(&file, archiveId, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, filename), FS_OPEN_CREATE | FS_OPEN_WRITE)); - Draw_CreateBitmapHeader(framebufferCache, 400, 240); - - for(u32 y = 0; y < 120; y++) - Draw_ConvertFrameBufferLine(framebufferCache + 54 + 3 * 400 * y, true, true, y); - - TRY(IFile_Write(&file, &total, framebufferCache, 54 + 3 * 400 * 120, 0)); - - for(u32 y = 120; y < 240; y++) - Draw_ConvertFrameBufferLine(framebufferCache + 3 * 400 * (y - 120), true, true, y); - - TRY(IFile_Write(&file, &total, framebufferCache, 3 * 400 * 120, 0)); + TRY(RosalinaMenu_WriteScreenshot(&file, true, true)); TRY(IFile_Close(&file)); sprintf(filename, "/luma/screenshots/%04lu-%02lu-%02lu_%02lu-%02lu-%02lu.%03llu_bot.bmp", year, month, days, hours, minutes, seconds, milliseconds); TRY(IFile_Open(&file, archiveId, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, filename), FS_OPEN_CREATE | FS_OPEN_WRITE)); - Draw_CreateBitmapHeader(framebufferCache, 320, 240); - - for(u32 y = 0; y < 120; y++) - Draw_ConvertFrameBufferLine(framebufferCache + 54 + 3 * 320 * y, false, true, y); - - TRY(IFile_Write(&file, &total, framebufferCache, 54 + 3 * 320 * 120, 0)); - - for(u32 y = 120; y < 240; y++) - Draw_ConvertFrameBufferLine(framebufferCache + 3 * 320 * (y - 120), false, true, y); - - TRY(IFile_Write(&file, &total, framebufferCache, 3 * 320 * 120, 0)); + TRY(RosalinaMenu_WriteScreenshot(&file, false, true)); TRY(IFile_Close(&file)); - if((GPU_FB_TOP_FMT & 0x20) && (Draw_GetCurrentFramebufferAddress(true, true) != Draw_GetCurrentFramebufferAddress(true, false))) + if(false && (GPU_FB_TOP_FMT & 0x20) && (Draw_GetCurrentFramebufferAddress(true, true) != Draw_GetCurrentFramebufferAddress(true, false))) { sprintf(filename, "/luma/screenshots/%04lu-%02lu-%02lu_%02lu-%02lu-%02lu.%03llu_top_right.bmp", year, month, days, hours, minutes, seconds, milliseconds); TRY(IFile_Open(&file, archiveId, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, filename), FS_OPEN_CREATE | FS_OPEN_WRITE)); - Draw_CreateBitmapHeader(framebufferCache, 400, 240); - - for(u32 y = 0; y < 120; y++) - Draw_ConvertFrameBufferLine(framebufferCache + 54 + 3 * 400 * y, true, false, y); - - TRY(IFile_Write(&file, &total, framebufferCache, 54 + 3 * 400 * 120, 0)); - - for(u32 y = 120; y < 240; y++) - Draw_ConvertFrameBufferLine(framebufferCache + 3 * 400 * (y - 120), true, false, y); - - TRY(IFile_Write(&file, &total, framebufferCache, 3 * 400 * 120, 0)); + TRY(RosalinaMenu_WriteScreenshot(&file, true, false)); TRY(IFile_Close(&file)); } @@ -289,7 +300,14 @@ end: if(R_FAILED(res)) Draw_DrawFormattedString(10, 30, COLOR_WHITE, "Operation failed (0x%08lx).", (u32)res); else - Draw_DrawString(10, 30, COLOR_WHITE, "Operation succeeded."); + { + u32 t1 = (u32)(1000 * timeSpentConvertingScreenshot / SYSCLOCK_ARM11); + u32 t2 = (u32)(1000 * timeSpentWritingScreenshot / SYSCLOCK_ARM11); + u32 posY = 30; + posY = Draw_DrawString(10, posY, COLOR_WHITE, "Operation succeeded.\n\n"); + posY = Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Time spent converting: %5lums\n", t1); + posY = Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Time spent writing files: %5lums\n", t2); + } Draw_FlushFramebuffer(); Draw_Unlock();