Compare commits

..

5 Commits

Author SHA1 Message Date
Lorenzo Dellacà
53ab41e6d0 fixed ARM "undefined instruction" kernel panic when closing games 2020-07-07 00:16:45 +02:00
Lorenzo Dellacà
1176fa8f28 Merge branch 'master' into 3gx-master
* master:
  Change screen filters presets (adding more) menu & print CCT. Fixes #1442.
  rosalina: implement 800px top-screen screenshot, etc. Fixes #1443

# Conflicts:
#	sysmodules/rosalina/source/draw.c
2020-07-06 20:20:27 +02:00
TuxSH
e69f89a0d4 Change screen filters presets (adding more) menu & print CCT. Fixes #1442.
Most new presets come from 8bitwonder
2020-07-05 20:54:27 +01:00
TuxSH
9411a8c186 rosalina: implement 800px top-screen screenshot, etc. Fixes #1443 2020-07-05 18:44:41 +01:00
Lorenzo Dellacà
aa577d0e39 Update README.md 2020-07-04 14:43:01 +02:00
8 changed files with 149 additions and 106 deletions

View File

@@ -5,6 +5,7 @@
This edition of **Luma3DS** allows the loading of **.3GX plugins** in Luma3DS, which are otherwise officially unsupported. This edition of **Luma3DS** allows the loading of **.3GX plugins** in Luma3DS, which are otherwise officially unsupported.
#
### How to install this Edition ### How to install this Edition
1. download the latest `boot.firm` from [the releases page](https://github.com/mind-overflow/Luma3DS-3GX/releases/latest) 1. download the latest `boot.firm` from [the releases page](https://github.com/mind-overflow/Luma3DS-3GX/releases/latest)
2. put the downloaded `boot.firm` file in the `root` directory of your SD card (`sd:/boot.firm`), overwriting the official Luma3DS `boot.firm`. 2. put the downloaded `boot.firm` file in the `root` directory of your SD card (`sd:/boot.firm`), overwriting the official Luma3DS `boot.firm`.
@@ -15,6 +16,7 @@ This edition of **Luma3DS** allows the loading of **.3GX plugins** in Luma3DS, w
You successfully installed the 3GX Plugin Loader! Now, proceed to the next step to learn how to install and enable 3GX plugins. You successfully installed the 3GX Plugin Loader! Now, proceed to the next step to learn how to install and enable 3GX plugins.
#
### How to install 3GX plugins ### How to install 3GX plugins
Plugins have to be installed in the `sd:/luma/plugins` folder. Plugins have to be installed in the `sd:/luma/plugins` folder.
Usually, you need to put your specific plugin in the `<TITLEID>` subdirectory, eg: `sd:/luma/plugins/<TITLEID>/<filename>.3gx`. Usually, you need to put your specific plugin in the `<TITLEID>` subdirectory, eg: `sd:/luma/plugins/<TITLEID>/<filename>.3gx`.
@@ -28,6 +30,7 @@ So:
Now you know how to install 3GX plugins! Proceed to the next step to learn how how to enable 3GX plugins. Now you know how to install 3GX plugins! Proceed to the next step to learn how how to enable 3GX plugins.
#
### How to enable 3GX plugins ### How to enable 3GX plugins
1. when booted, press `L + D-Pad Down + Select` to open the Rosalina menu. 1. when booted, press `L + D-Pad Down + Select` to open the Rosalina menu.
2. Press `D-Pad Down` again until `Plugin Loader`, is selected, then press `A` and set it to `[Enabled]`. 2. Press `D-Pad Down` again until `Plugin Loader`, is selected, then press `A` and set it to `[Enabled]`.
@@ -35,6 +38,7 @@ Now you know how to install 3GX plugins! Proceed to the next step to learn how h
Done! You learned to install the 3GX Plugin loader, install 3GX Plugins and enable them. Now, simply launch the game you want to play and press `SELECT` to open up the 3GX menu! Done! You learned to install the 3GX Plugin loader, install 3GX Plugins and enable them. Now, simply launch the game you want to play and press `SELECT` to open up the 3GX menu!
#
### Luma3DS introduction ### Luma3DS introduction
**Luma3DS** is a program to patch the system software of (New) Nintendo (2)3DS handheld consoles "on the fly", adding features such as per-game language settings, debugging capabilities for developers, and removing restrictions enforced by Nintendo such as the region lock. **Luma3DS** is a program to patch the system software of (New) Nintendo (2)3DS handheld consoles "on the fly", adding features such as per-game language settings, debugging capabilities for developers, and removing restrictions enforced by Nintendo such as the region lock.

View File

@@ -118,7 +118,6 @@ void *svcHook(u8 *pageEnd)
KEvent* event = (KEvent *)KProcessHandleTable__ToKAutoObject(handleTableOfProcess(currentProcess), KEvent* event = (KEvent *)KProcessHandleTable__ToKAutoObject(handleTableOfProcess(currentProcess),
KPROCESS_GET_RVALUE(currentProcess, resumeProcessExitEvent)); KPROCESS_GET_RVALUE(currentProcess, resumeProcessExitEvent));
WaitSynchronization1(NULL, currentCoreContext->objectContext.currentThread, (KSynchronizationObject *)event, 10000000000ULL);
((KAutoObject *)event)->vtable->DecrementReferenceCount((KAutoObject *)event); ((KAutoObject *)event)->vtable->DecrementReferenceCount((KAutoObject *)event);
} }
return officialSVCs[0x3]; return officialSVCs[0x3];

View File

@@ -91,7 +91,8 @@ u32 Draw_DrawFormattedString(u32 posX, u32 posY, u32 color, const char *fmt, ...
void Draw_FillFramebuffer(u32 value); void Draw_FillFramebuffer(u32 value);
void Draw_ClearFramebuffer(void); void Draw_ClearFramebuffer(void);
u32 Draw_AllocateFramebufferCache(void); Result Draw_AllocateFramebufferCache(u32 size);
Result Draw_AllocateFramebufferCacheForScreenshot(u32 size);
void Draw_FreeFramebufferCache(void); void Draw_FreeFramebufferCache(void);
void *Draw_GetFramebufferCache(void); void *Draw_GetFramebufferCache(void);
u32 Draw_GetFramebufferCacheSize(void); u32 Draw_GetFramebufferCacheSize(void);
@@ -99,6 +100,8 @@ u32 Draw_SetupFramebuffer(void);
void Draw_RestoreFramebuffer(void); void Draw_RestoreFramebuffer(void);
void Draw_FlushFramebuffer(void); void Draw_FlushFramebuffer(void);
u32 Draw_GetCurrentFramebufferAddress(bool top, bool left); 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_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);

View File

@@ -32,10 +32,14 @@ extern Menu screenFiltersMenu;
extern int screenFiltersCurrentTemperature; extern int screenFiltersCurrentTemperature;
void screenFiltersSetDisabled(void); void ScreenFiltersMenu_SetDefault(void); // 6500K (default)
void screenFiltersReduceBlueLevel1(void);
void screenFiltersReduceBlueLevel2(void); void ScreenFiltersMenu_SetAquarium(void); // 10000K
void screenFiltersReduceBlueLevel3(void); void ScreenFiltersMenu_SetOvercastSky(void); // 7500K
void screenFiltersReduceBlueLevel4(void); void ScreenFiltersMenu_SetDaylight(void); // 5500K
void screenFiltersReduceBlueLevel5(void); void ScreenFiltersMenu_SetFluorescent(void); // 4200K
void screenFiltersSetTemperature(int temperature); 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

View File

@@ -129,18 +129,19 @@ void Draw_ClearFramebuffer(void)
Draw_FillFramebuffer(0); 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?) // Can't use fbs in FCRAM when Home Menu is active (AXI config related maybe?)
u32 addr = 0x0D000000; u32 addr = 0x0D000000;
u32 tmp; u32 tmp;
u32 minSize = (FB_BOTTOM_SIZE + 0xFFF) & ~0xFFF;
u32 maxSize = (FB_SCREENSHOT_SIZE + 0xFFF) & ~0xFFF; size = (size + 0xFFF) >> 12 << 12; // round-up
u32 remaining = (u32)osGetMemRegionFree(MEMREGION_SYSTEM);
u32 size = remaining < maxSize ? remaining : maxSize; if (framebufferCache != NULL)
__builtin_trap();
if (size < minSize || R_FAILED(svcControlMemoryEx(&tmp, addr, 0, size, MEMOP_ALLOC, MEMREGION_SYSTEM | MEMPERM_READ | MEMPERM_WRITE, true)))
Result res = svcControlMemoryEx(&tmp, addr, 0, size, MEMOP_ALLOC, MEMREGION_SYSTEM | MEMPERM_READWRITE, true);
if (R_FAILED(res))
{ {
framebufferCache = NULL; framebufferCache = NULL;
framebufferCacheSize = 0; framebufferCacheSize = 0;
@@ -151,13 +152,21 @@ u32 Draw_AllocateFramebufferCache(void)
framebufferCacheSize = size; 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) void Draw_FreeFramebufferCache(void)
{ {
u32 tmp; 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; framebufferCacheSize = 0;
framebufferCache = NULL; framebufferCache = NULL;
} }
@@ -180,13 +189,19 @@ u32 Draw_SetupFramebuffer(void)
memcpy(framebufferCache, FB_BOTTOM_VRAM_ADDR, FB_BOTTOM_SIZE); memcpy(framebufferCache, FB_BOTTOM_VRAM_ADDR, FB_BOTTOM_SIZE);
Draw_ClearFramebuffer(); Draw_ClearFramebuffer();
Draw_FlushFramebuffer(); Draw_FlushFramebuffer();
u32 format = GPU_FB_BOTTOM_FMT;
gpuSavedFramebufferAddr1 = GPU_FB_BOTTOM_ADDR_1; gpuSavedFramebufferAddr1 = GPU_FB_BOTTOM_ADDR_1;
gpuSavedFramebufferAddr2 = GPU_FB_BOTTOM_ADDR_2; gpuSavedFramebufferAddr2 = GPU_FB_BOTTOM_ADDR_2;
gpuSavedFramebufferFormat = GPU_FB_BOTTOM_FMT; gpuSavedFramebufferFormat = format;
gpuSavedFramebufferStride = GPU_FB_BOTTOM_STRIDE; 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_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; GPU_FB_BOTTOM_STRIDE = 240 * 2;
return framebufferCacheSize; return framebufferCacheSize;
@@ -205,7 +220,7 @@ void Draw_RestoreFramebuffer(void)
void Draw_FlushFramebuffer(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) 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) static inline void Draw_WriteUnaligned(u8 *dst, u32 tmp, u32 size)
{ {
memcpy(dst, &tmp, size); memcpy(dst, &tmp, size);
@@ -313,6 +343,7 @@ static inline void Draw_ConvertPixelToBGR8(u8 *dst, const u8 *src, GSPGPU_Frameb
typedef struct FrameBufferConvertArgs { typedef struct FrameBufferConvertArgs {
u8 *buf; u8 *buf;
u32 width;
u8 startingLine; u8 startingLine;
u8 numLines; u8 numLines;
bool top; bool top;
@@ -324,7 +355,7 @@ static void Draw_ConvertFrameBufferLinesKernel(const FrameBufferConvertArgs *arg
static const u8 formatSizes[] = { 4, 3, 2, 2, 2 }; static const u8 formatSizes[] = { 4, 3, 2, 2, 2 };
GSPGPU_FramebufferFormats fmt = args->top ? (GSPGPU_FramebufferFormats)(GPU_FB_TOP_FMT & 7) : (GSPGPU_FramebufferFormats)(GPU_FB_BOTTOM_FMT & 7); GSPGPU_FramebufferFormats fmt = args->top ? (GSPGPU_FramebufferFormats)(GPU_FB_TOP_FMT & 7) : (GSPGPU_FramebufferFormats)(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 stride = args->top ? GPU_FB_TOP_STRIDE : GPU_FB_BOTTOM_STRIDE;
u32 pa = Draw_GetCurrentFramebufferAddress(args->top, args->left); 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); svcCustomBackdoor(Draw_ConvertFrameBufferLinesKernel, &args);
} }

View File

@@ -228,15 +228,15 @@ void menuEnter(void)
menuRefCount++; menuRefCount++;
svcKernelSetState(0x10000, 1); svcKernelSetState(0x10000, 1);
svcSleepThread(5 * 1000 * 100LL); svcSleepThread(5 * 1000 * 100LL);
if (Draw_AllocateFramebufferCache() == 0) if (R_FAILED(Draw_AllocateFramebufferCache(FB_BOTTOM_SIZE)))
{ {
// Oops // Oops
menuRefCount = 0; menuRefCount = 0;
svcKernelSetState(0x10000, 1); svcKernelSetState(0x10000, 1);
svcSleepThread(5 * 1000 * 100LL); svcSleepThread(5 * 1000 * 100LL);
} }
else
Draw_SetupFramebuffer(); Draw_SetupFramebuffer();
} }
Draw_Unlock(); Draw_Unlock();
} }

View File

@@ -296,18 +296,20 @@ void RosalinaMenu_PowerOff(void) // Soft shutdown.
static s64 timeSpentConvertingScreenshot = 0; static s64 timeSpentConvertingScreenshot = 0;
static s64 timeSpentWritingScreenshot = 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; u64 total;
Result res = 0; Result res = 0;
u32 dimX = top ? 400 : 320; u32 lineSize = 3 * width;
u32 lineSize = 3 * dimX;
u32 remaining = lineSize * 240; u32 remaining = lineSize * 240;
TRY(Draw_AllocateFramebufferCacheForScreenshot(remaining));
u8 *framebufferCache = (u8 *)Draw_GetFramebufferCache(); u8 *framebufferCache = (u8 *)Draw_GetFramebufferCache();
u8 *framebufferCacheEnd = framebufferCache + Draw_GetFramebufferCacheSize(); u8 *framebufferCacheEnd = framebufferCache + Draw_GetFramebufferCacheSize();
u8 *buf = framebufferCache; u8 *buf = framebufferCache;
Draw_CreateBitmapHeader(framebufferCache, dimX, 240); Draw_CreateBitmapHeader(framebufferCache, width, 240);
buf += 54; buf += 54;
u32 y = 0; u32 y = 0;
@@ -318,7 +320,7 @@ static Result RosalinaMenu_WriteScreenshot(IFile *file, bool top, bool left)
u32 available = (u32)(framebufferCacheEnd - buf); u32 available = (u32)(framebufferCacheEnd - buf);
u32 size = available < remaining ? available : remaining; u32 size = available < remaining ? available : remaining;
u32 nlines = size / lineSize; u32 nlines = size / lineSize;
Draw_ConvertFrameBufferLines(buf, y, nlines, top, left); Draw_ConvertFrameBufferLines(buf, width, y, nlines, top, left);
s64 t1 = svcGetSystemTick(); s64 t1 = svcGetSystemTick();
timeSpentConvertingScreenshot += t1 - t0; timeSpentConvertingScreenshot += t1 - t0;
@@ -329,7 +331,10 @@ static Result RosalinaMenu_WriteScreenshot(IFile *file, bool top, bool left)
remaining -= lineSize * nlines; remaining -= lineSize * nlines;
buf = framebufferCache; buf = framebufferCache;
} }
end: return res; end:
Draw_FreeFramebufferCache();
return res;
} }
void RosalinaMenu_TakeScreenshot(void) void RosalinaMenu_TakeScreenshot(void)
@@ -353,9 +358,16 @@ void RosalinaMenu_TakeScreenshot(void)
archiveId = isSdMode ? ARCHIVE_SDMC : ARCHIVE_NAND_RW; archiveId = isSdMode ? ARCHIVE_SDMC : ARCHIVE_NAND_RW;
Draw_Lock(); Draw_Lock();
Draw_RestoreFramebuffer(); Draw_RestoreFramebuffer();
Draw_FreeFramebufferCache();
svcFlushEntireDataCache(); 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, "")); res = FSUSER_OpenArchive(&archive, archiveId, fsMakePath(PATH_EMPTY, ""));
if(R_SUCCEEDED(res)) if(R_SUCCEEDED(res))
{ {
@@ -410,24 +422,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); 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(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)); TRY(IFile_Close(&file));
sprintf(filename, "/luma/screenshots/%04lu-%02lu-%02lu_%02lu-%02lu-%02lu.%03llu_bot.bmp", year, month, days, hours, minutes, seconds, milliseconds); 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(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)); 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); 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(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)); TRY(IFile_Close(&file));
} }
end: end:
IFile_Close(&file); IFile_Close(&file);
if (R_FAILED(Draw_AllocateFramebufferCache(FB_BOTTOM_SIZE)))
__builtin_trap(); // We're f***ed if this happens
svcFlushEntireDataCache(); svcFlushEntireDataCache();
Draw_SetupFramebuffer(); Draw_SetupFramebuffer();
Draw_Unlock(); Draw_Unlock();

View File

@@ -32,11 +32,19 @@
#include "redshift/redshift.h" #include "redshift/redshift.h"
#include "redshift/colorramp.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_TOP_COL_LUT_INDEX = 0;
GPU_FB_BOTTOM_COL_LUT_INDEX = 0; GPU_FB_BOTTOM_COL_LUT_INDEX = 0;
@@ -48,17 +56,7 @@ void writeLut(u32* lut)
} }
} }
typedef struct { static void ScreenFiltersMenu_ApplyColorSettings(color_setting_t* cs)
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)
{ {
u8 i = 0; u8 i = 0;
@@ -86,68 +84,56 @@ void applyColorSettings(color_setting_t* cs)
g_px[i].b = *(g_c + i + 0x200) >> 8; g_px[i].b = *(g_c + i + 0x200) >> 8;
} while(++i); } while(++i);
writeLut((u32*)g_px); ScreenFiltersMenu_WriteLut((u32*)g_px);
} }
Menu screenFiltersMenu = { static void ScreenFiltersMenu_SetCct(int cct)
"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)
{ {
color_setting_t cs; color_setting_t cs;
memset(&cs, 0, sizeof(cs)); memset(&cs, 0, sizeof(cs));
cs.temperature = temperature; cs.temperature = cct;
/*cs.gamma[0] = 1.0F; /*cs.gamma[0] = 1.0F;
cs.gamma[1] = 1.0F; cs.gamma[1] = 1.0F;
cs.gamma[2] = 1.0F; cs.gamma[2] = 1.0F;
cs.brightness = 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)