From 9411a8c186be78bcbbe20409219861421d1d4bb9 Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Sun, 5 Jul 2020 18:44:22 +0100 Subject: [PATCH 1/2] rosalina: implement 800px top-screen screenshot, etc. Fixes #1443 --- sysmodules/rosalina/include/draw.h | 7 +++- sysmodules/rosalina/source/draw.c | 63 ++++++++++++++++++++++-------- sysmodules/rosalina/source/menu.c | 6 +-- sysmodules/rosalina/source/menus.c | 36 ++++++++++++----- 4 files changed, 81 insertions(+), 31 deletions(-) diff --git a/sysmodules/rosalina/include/draw.h b/sysmodules/rosalina/include/draw.h index 2b75375..5a5ef10 100644 --- a/sysmodules/rosalina/include/draw.h +++ b/sysmodules/rosalina/include/draw.h @@ -90,7 +90,8 @@ u32 Draw_DrawFormattedString(u32 posX, u32 posY, u32 color, const char *fmt, ... void Draw_FillFramebuffer(u32 value); void Draw_ClearFramebuffer(void); -u32 Draw_AllocateFramebufferCache(void); +Result Draw_AllocateFramebufferCache(u32 size); +Result Draw_AllocateFramebufferCacheForScreenshot(u32 size); void Draw_FreeFramebufferCache(void); void *Draw_GetFramebufferCache(void); u32 Draw_GetFramebufferCacheSize(void); @@ -98,6 +99,8 @@ u32 Draw_SetupFramebuffer(void); void Draw_RestoreFramebuffer(void); void Draw_FlushFramebuffer(void); u32 Draw_GetCurrentFramebufferAddress(bool top, bool left); +// Width is actually height as the 3ds screen is rotated 90 degrees +void Draw_GetCurrentScreenInfo(u32 *width, bool *is3d, bool top); void Draw_CreateBitmapHeader(u8 *dst, u32 width, u32 heigth); -void Draw_ConvertFrameBufferLines(u8 *buf, u32 startingLine, u32 numLines, bool top, bool left); +void Draw_ConvertFrameBufferLines(u8 *buf, u32 width, u32 startingLine, u32 numLines, bool top, bool left); diff --git a/sysmodules/rosalina/source/draw.c b/sysmodules/rosalina/source/draw.c index 6becdac..f8ee672 100644 --- a/sysmodules/rosalina/source/draw.c +++ b/sysmodules/rosalina/source/draw.c @@ -129,18 +129,19 @@ void Draw_ClearFramebuffer(void) Draw_FillFramebuffer(0); } -u32 Draw_AllocateFramebufferCache(void) +Result Draw_AllocateFramebufferCache(u32 size) { - // Try to see how much we can allocate... // Can't use fbs in FCRAM when Home Menu is active (AXI config related maybe?) u32 addr = 0x0D000000; u32 tmp; - u32 minSize = (FB_BOTTOM_SIZE + 0xFFF) & ~0xFFF; - u32 maxSize = (FB_SCREENSHOT_SIZE + 0xFFF) & ~0xFFF; - u32 remaining = (u32)osGetMemRegionFree(MEMREGION_SYSTEM); - u32 size = remaining < maxSize ? remaining : maxSize; - - if (size < minSize || R_FAILED(svcControlMemoryEx(&tmp, addr, 0, size, MEMOP_ALLOC, MEMREGION_SYSTEM | MEMPERM_READ | MEMPERM_WRITE, true))) + + size = (size + 0xFFF) >> 12 << 12; // round-up + + if (framebufferCache != NULL) + __builtin_trap(); + + Result res = svcControlMemoryEx(&tmp, addr, 0, size, MEMOP_ALLOC, MEMREGION_SYSTEM | MEMPERM_READWRITE, true); + if (R_FAILED(res)) { framebufferCache = NULL; framebufferCacheSize = 0; @@ -151,13 +152,21 @@ u32 Draw_AllocateFramebufferCache(void) framebufferCacheSize = size; } - return framebufferCacheSize; + return res; +} + +Result Draw_AllocateFramebufferCacheForScreenshot(u32 size) +{ + u32 remaining = (u32)osGetMemRegionFree(MEMREGION_SYSTEM); + u32 sz = remaining < size ? remaining : size; + return Draw_AllocateFramebufferCache(sz); } void Draw_FreeFramebufferCache(void) { u32 tmp; - svcControlMemory(&tmp, (u32)framebufferCache, 0, framebufferCacheSize, MEMOP_FREE, 0); + if (framebufferCache != NULL) + svcControlMemory(&tmp, (u32)framebufferCache, 0, framebufferCacheSize, MEMOP_FREE, 0); framebufferCacheSize = 0; framebufferCache = NULL; } @@ -180,13 +189,19 @@ u32 Draw_SetupFramebuffer(void) memcpy(framebufferCache, FB_BOTTOM_VRAM_ADDR, FB_BOTTOM_SIZE); Draw_ClearFramebuffer(); Draw_FlushFramebuffer(); + + u32 format = GPU_FB_BOTTOM_FMT; + gpuSavedFramebufferAddr1 = GPU_FB_BOTTOM_ADDR_1; gpuSavedFramebufferAddr2 = GPU_FB_BOTTOM_ADDR_2; - gpuSavedFramebufferFormat = GPU_FB_BOTTOM_FMT; + gpuSavedFramebufferFormat = format; gpuSavedFramebufferStride = GPU_FB_BOTTOM_STRIDE; + format = (format & ~7) | GSP_RGB565_OES; + format |= 3 << 8; // set VRAM bits + GPU_FB_BOTTOM_ADDR_1 = GPU_FB_BOTTOM_ADDR_2 = FB_BOTTOM_VRAM_PA; - GPU_FB_BOTTOM_FMT = (GPU_FB_BOTTOM_FMT & ~7) | GSP_RGB565_OES; + GPU_FB_BOTTOM_FMT = format; GPU_FB_BOTTOM_STRIDE = 240 * 2; return framebufferCacheSize; @@ -205,7 +220,7 @@ void Draw_RestoreFramebuffer(void) void Draw_FlushFramebuffer(void) { - svcFlushProcessDataCache(CUR_PROCESS_HANDLE, FB_BOTTOM_VRAM_ADDR, FB_BOTTOM_SIZE); + svcFlushProcessDataCache(CUR_PROCESS_HANDLE, (u32)FB_BOTTOM_VRAM_ADDR, FB_BOTTOM_SIZE); } u32 Draw_GetCurrentFramebufferAddress(bool top, bool left) @@ -226,6 +241,21 @@ u32 Draw_GetCurrentFramebufferAddress(bool top, bool left) } } +void Draw_GetCurrentScreenInfo(u32 *width, bool *is3d, bool top) +{ + if (top) + { + bool isNormal2d = (GPU_FB_TOP_FMT & BIT(6)) != 0; + *is3d = (GPU_FB_TOP_FMT & BIT(5)) != 0; + *width = !(*is3d) && !isNormal2d ? 800 : 400; + } + else + { + *is3d = false; + *width = 320; + } +} + static inline void Draw_WriteUnaligned(u8 *dst, u32 tmp, u32 size) { memcpy(dst, &tmp, size); @@ -313,6 +343,7 @@ static inline void Draw_ConvertPixelToBGR8(u8 *dst, const u8 *src, GSPGPU_Frameb typedef struct FrameBufferConvertArgs { u8 *buf; + u32 width; u8 startingLine; u8 numLines; bool top; @@ -324,7 +355,7 @@ static void Draw_ConvertFrameBufferLinesKernel(const FrameBufferConvertArgs *arg static const u8 formatSizes[] = { 4, 3, 2, 2, 2 }; GSPGPU_FramebufferFormat fmt = args->top ? (GSPGPU_FramebufferFormat)(GPU_FB_TOP_FMT & 7) : (GSPGPU_FramebufferFormat)(GPU_FB_BOTTOM_FMT & 7); - u32 width = args->top ? 400 : 320; + u32 width = args->width; u32 stride = args->top ? GPU_FB_TOP_STRIDE : GPU_FB_BOTTOM_STRIDE; u32 pa = Draw_GetCurrentFramebufferAddress(args->top, args->left); @@ -340,8 +371,8 @@ static void Draw_ConvertFrameBufferLinesKernel(const FrameBufferConvertArgs *arg } } -void Draw_ConvertFrameBufferLines(u8 *buf, u32 startingLine, u32 numLines, bool top, bool left) +void Draw_ConvertFrameBufferLines(u8 *buf, u32 width, u32 startingLine, u32 numLines, bool top, bool left) { - FrameBufferConvertArgs args = { buf, (u8)startingLine, (u8)numLines, top, left }; + FrameBufferConvertArgs args = { buf, width, (u8)startingLine, (u8)numLines, top, left }; svcCustomBackdoor(Draw_ConvertFrameBufferLinesKernel, &args); } diff --git a/sysmodules/rosalina/source/menu.c b/sysmodules/rosalina/source/menu.c index e117908..28bed67 100644 --- a/sysmodules/rosalina/source/menu.c +++ b/sysmodules/rosalina/source/menu.c @@ -214,15 +214,15 @@ void menuEnter(void) menuRefCount++; svcKernelSetState(0x10000, 1); svcSleepThread(5 * 1000 * 100LL); - if (Draw_AllocateFramebufferCache() == 0) + if (R_FAILED(Draw_AllocateFramebufferCache(FB_BOTTOM_SIZE))) { // Oops menuRefCount = 0; svcKernelSetState(0x10000, 1); svcSleepThread(5 * 1000 * 100LL); } - - Draw_SetupFramebuffer(); + else + Draw_SetupFramebuffer(); } Draw_Unlock(); } diff --git a/sysmodules/rosalina/source/menus.c b/sysmodules/rosalina/source/menus.c index fa54ae4..0986802 100644 --- a/sysmodules/rosalina/source/menus.c +++ b/sysmodules/rosalina/source/menus.c @@ -293,18 +293,20 @@ void RosalinaMenu_PowerOff(void) // Soft shutdown. static s64 timeSpentConvertingScreenshot = 0; static s64 timeSpentWritingScreenshot = 0; -static Result RosalinaMenu_WriteScreenshot(IFile *file, bool top, bool left) +static Result RosalinaMenu_WriteScreenshot(IFile *file, u32 width, bool top, bool left) { u64 total; Result res = 0; - u32 dimX = top ? 400 : 320; - u32 lineSize = 3 * dimX; + u32 lineSize = 3 * width; u32 remaining = lineSize * 240; + + TRY(Draw_AllocateFramebufferCacheForScreenshot(remaining)); + u8 *framebufferCache = (u8 *)Draw_GetFramebufferCache(); u8 *framebufferCacheEnd = framebufferCache + Draw_GetFramebufferCacheSize(); u8 *buf = framebufferCache; - Draw_CreateBitmapHeader(framebufferCache, dimX, 240); + Draw_CreateBitmapHeader(framebufferCache, width, 240); buf += 54; u32 y = 0; @@ -315,7 +317,7 @@ static Result RosalinaMenu_WriteScreenshot(IFile *file, bool top, bool left) u32 available = (u32)(framebufferCacheEnd - buf); u32 size = available < remaining ? available : remaining; u32 nlines = size / lineSize; - Draw_ConvertFrameBufferLines(buf, y, nlines, top, left); + Draw_ConvertFrameBufferLines(buf, width, y, nlines, top, left); s64 t1 = svcGetSystemTick(); timeSpentConvertingScreenshot += t1 - t0; @@ -326,7 +328,10 @@ static Result RosalinaMenu_WriteScreenshot(IFile *file, bool top, bool left) remaining -= lineSize * nlines; buf = framebufferCache; } - end: return res; + end: + + Draw_FreeFramebufferCache(); + return res; } void RosalinaMenu_TakeScreenshot(void) @@ -350,9 +355,16 @@ void RosalinaMenu_TakeScreenshot(void) archiveId = isSdMode ? ARCHIVE_SDMC : ARCHIVE_NAND_RW; Draw_Lock(); Draw_RestoreFramebuffer(); + Draw_FreeFramebufferCache(); svcFlushEntireDataCache(); + bool is3d; + u32 topWidth, bottomWidth; // actually Y-dim + + Draw_GetCurrentScreenInfo(&bottomWidth, &is3d, false); + Draw_GetCurrentScreenInfo(&topWidth, &is3d, true); + res = FSUSER_OpenArchive(&archive, archiveId, fsMakePath(PATH_EMPTY, "")); if(R_SUCCEEDED(res)) { @@ -407,24 +419,28 @@ 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)); - TRY(RosalinaMenu_WriteScreenshot(&file, true, true)); + TRY(RosalinaMenu_WriteScreenshot(&file, topWidth, 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)); - TRY(RosalinaMenu_WriteScreenshot(&file, false, true)); + TRY(RosalinaMenu_WriteScreenshot(&file, bottomWidth, false, true)); TRY(IFile_Close(&file)); - if((GPU_FB_TOP_FMT & 0x20) && (Draw_GetCurrentFramebufferAddress(true, true) != Draw_GetCurrentFramebufferAddress(true, false))) + if(is3d && (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)); - TRY(RosalinaMenu_WriteScreenshot(&file, true, false)); + TRY(RosalinaMenu_WriteScreenshot(&file, topWidth, true, false)); TRY(IFile_Close(&file)); } end: IFile_Close(&file); + + if (R_FAILED(Draw_AllocateFramebufferCache(FB_BOTTOM_SIZE))) + __builtin_trap(); // We're f***ed if this happens + svcFlushEntireDataCache(); Draw_SetupFramebuffer(); Draw_Unlock(); From e69f89a0d454b0e40b1fbeda5681c6510c743061 Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Sun, 5 Jul 2020 20:54:27 +0100 Subject: [PATCH 2/2] Change screen filters presets (adding more) menu & print CCT. Fixes #1442. Most new presets come from 8bitwonder --- .../rosalina/include/menus/screen_filters.h | 18 ++- .../rosalina/source/menus/screen_filters.c | 120 ++++++++---------- 2 files changed, 64 insertions(+), 74 deletions(-) diff --git a/sysmodules/rosalina/include/menus/screen_filters.h b/sysmodules/rosalina/include/menus/screen_filters.h index 3ba6d09..72323b9 100644 --- a/sysmodules/rosalina/include/menus/screen_filters.h +++ b/sysmodules/rosalina/include/menus/screen_filters.h @@ -32,10 +32,14 @@ extern Menu screenFiltersMenu; extern int screenFiltersCurrentTemperature; -void screenFiltersSetDisabled(void); -void screenFiltersReduceBlueLevel1(void); -void screenFiltersReduceBlueLevel2(void); -void screenFiltersReduceBlueLevel3(void); -void screenFiltersReduceBlueLevel4(void); -void screenFiltersReduceBlueLevel5(void); -void screenFiltersSetTemperature(int temperature); +void ScreenFiltersMenu_SetDefault(void); // 6500K (default) + +void ScreenFiltersMenu_SetAquarium(void); // 10000K +void ScreenFiltersMenu_SetOvercastSky(void); // 7500K +void ScreenFiltersMenu_SetDaylight(void); // 5500K +void ScreenFiltersMenu_SetFluorescent(void); // 4200K +void ScreenFiltersMenu_SetHalogen(void); // 3400K +void ScreenFiltersMenu_SetIncandescent(void); // 2700K +void ScreenFiltersMenu_SetWarmIncandescent(void); // 2300K +void ScreenFiltersMenu_SetCandle(void); // 1900K +void ScreenFiltersMenu_SetEmber(void); // 1200K diff --git a/sysmodules/rosalina/source/menus/screen_filters.c b/sysmodules/rosalina/source/menus/screen_filters.c index fc37285..7fe3f9e 100644 --- a/sysmodules/rosalina/source/menus/screen_filters.c +++ b/sysmodules/rosalina/source/menus/screen_filters.c @@ -32,11 +32,19 @@ #include "redshift/redshift.h" #include "redshift/colorramp.h" -#define TEMP_DEFAULT NEUTRAL_TEMP +typedef struct { + u8 r; + u8 g; + u8 b; + u8 z; +} Pixel; -int screenFiltersCurrentTemperature = TEMP_DEFAULT; +static u16 g_c[0x600]; +static Pixel g_px[0x400]; -void writeLut(u32* lut) +int screenFiltersCurrentTemperature = 6500; + +static void ScreenFiltersMenu_WriteLut(const u32* lut) { GPU_FB_TOP_COL_LUT_INDEX = 0; GPU_FB_BOTTOM_COL_LUT_INDEX = 0; @@ -48,17 +56,7 @@ void writeLut(u32* lut) } } -typedef struct { - u8 r; - u8 g; - u8 b; - u8 z; -} Pixel; - -static u16 g_c[0x600]; -static Pixel g_px[0x400]; - -void applyColorSettings(color_setting_t* cs) +static void ScreenFiltersMenu_ApplyColorSettings(color_setting_t* cs) { u8 i = 0; @@ -86,68 +84,56 @@ void applyColorSettings(color_setting_t* cs) g_px[i].b = *(g_c + i + 0x200) >> 8; } while(++i); - writeLut((u32*)g_px); + ScreenFiltersMenu_WriteLut((u32*)g_px); } -Menu screenFiltersMenu = { - "Screen filters menu", - { - { "Disable", METHOD, .method = &screenFiltersSetDisabled }, - { "Reduce blue light (level 1)", METHOD, .method = &screenFiltersReduceBlueLevel1 }, - { "Reduce blue light (level 2)", METHOD, .method = &screenFiltersReduceBlueLevel2 }, - { "Reduce blue light (level 3)", METHOD, .method = &screenFiltersReduceBlueLevel3 }, - { "Reduce blue light (level 4)", METHOD, .method = &screenFiltersReduceBlueLevel4 }, - { "Reduce blue light (level 5)", METHOD, .method = &screenFiltersReduceBlueLevel5 }, - {}, - } -}; - -void screenFiltersSetDisabled(void) -{ - screenFiltersCurrentTemperature = TEMP_DEFAULT; - screenFiltersSetTemperature(screenFiltersCurrentTemperature); -} - -void screenFiltersReduceBlueLevel1(void) -{ - screenFiltersCurrentTemperature = 4300; - screenFiltersSetTemperature(screenFiltersCurrentTemperature); -} - -void screenFiltersReduceBlueLevel2(void) -{ - screenFiltersCurrentTemperature = 3200; - screenFiltersSetTemperature(screenFiltersCurrentTemperature); -} - -void screenFiltersReduceBlueLevel3(void) -{ - screenFiltersCurrentTemperature = 2100; - screenFiltersSetTemperature(screenFiltersCurrentTemperature); -} - -void screenFiltersReduceBlueLevel4(void) -{ - screenFiltersCurrentTemperature = 1550; - screenFiltersSetTemperature(screenFiltersCurrentTemperature); -} - -void screenFiltersReduceBlueLevel5(void) -{ - screenFiltersCurrentTemperature = 1000; - screenFiltersSetTemperature(screenFiltersCurrentTemperature); -} - -void screenFiltersSetTemperature(int temperature) +static void ScreenFiltersMenu_SetCct(int cct) { color_setting_t cs; memset(&cs, 0, sizeof(cs)); - cs.temperature = temperature; + cs.temperature = cct; /*cs.gamma[0] = 1.0F; cs.gamma[1] = 1.0F; cs.gamma[2] = 1.0F; cs.brightness = 1.0F;*/ - applyColorSettings(&cs); + ScreenFiltersMenu_ApplyColorSettings(&cs); } + + +Menu screenFiltersMenu = { + "Screen filters menu", + { + { "[6500K] Default", METHOD, .method = &ScreenFiltersMenu_SetDefault }, + { "[10000K] Aquarium", METHOD, .method = &ScreenFiltersMenu_SetAquarium }, + { "[7500K] Overcast Sky", METHOD, .method = &ScreenFiltersMenu_SetOvercastSky }, + { "[5500K] Daylight", METHOD, .method = &ScreenFiltersMenu_SetDaylight }, + { "[4200K] Fluorescent", METHOD, .method = &ScreenFiltersMenu_SetFluorescent }, + { "[3400K] Halogen", METHOD, .method = &ScreenFiltersMenu_SetHalogen }, + { "[2700K] Incandescent", METHOD, .method = &ScreenFiltersMenu_SetIncandescent }, + { "[2300K] Warm Incandescent", METHOD, .method = &ScreenFiltersMenu_SetWarmIncandescent }, + { "[1900K] Candle", METHOD, .method = &ScreenFiltersMenu_SetCandle }, + { "[2700K] Ember", METHOD, .method = &ScreenFiltersMenu_SetEmber }, + {}, + } +}; + +#define DEF_CCT_SETTER(temp, name)\ +void ScreenFiltersMenu_Set##name(void)\ +{\ + screenFiltersCurrentTemperature = temp;\ + ScreenFiltersMenu_SetCct(temp);\ +} + +DEF_CCT_SETTER(6500, Default) + +DEF_CCT_SETTER(10000, Aquarium) +DEF_CCT_SETTER(7500, OvercastSky) +DEF_CCT_SETTER(5500, Daylight) +DEF_CCT_SETTER(4200, Fluorescent) +DEF_CCT_SETTER(3400, Halogen) +DEF_CCT_SETTER(2700, Incandescent) +DEF_CCT_SETTER(2300, WarmIncandescent) +DEF_CCT_SETTER(1900, Candle) +DEF_CCT_SETTER(1200, Ember)