rosalina: add color gamma control, and more
This commits adds an "Advanced configuration" option to screen filters, where CCT, color gamma, contrast and "brightness" can be fine-tuned, instead of just using a preset. Persistence in config.ini TBD in a later commit.
This commit is contained in:
parent
6592b516a4
commit
7397c85434
@ -75,6 +75,7 @@ extern bool preTerminationRequested;
|
||||
extern Handle preTerminationEvent;
|
||||
|
||||
u32 waitInputWithTimeout(s32 msec);
|
||||
u32 waitInputWithTimeoutEx(u32 *outHeldKeys, s32 msec);
|
||||
u32 waitInput(void);
|
||||
|
||||
u32 waitComboWithTimeout(s32 msec);
|
||||
|
@ -49,3 +49,5 @@ void ScreenFiltersMenu_SetIncandescent(void); // 2700K
|
||||
void ScreenFiltersMenu_SetWarmIncandescent(void); // 2300K
|
||||
void ScreenFiltersMenu_SetCandle(void); // 1900K
|
||||
void ScreenFiltersMenu_SetEmber(void); // 1200K
|
||||
|
||||
void ScreenFiltersMenu_AdvancedConfiguration(void);
|
||||
|
@ -41,6 +41,8 @@
|
||||
|
||||
#define REG32(addr) (*(vu32 *)(PA_PTR(addr)))
|
||||
|
||||
#define CLAMP(v, m, M) ((v) <= (m) ? (m) : (v) >= (M) ? (M) : (v))
|
||||
|
||||
static inline u32 makeArmBranch(const void *src, const void *dst, bool link) // the macros for those are ugly and buggy
|
||||
{
|
||||
u32 instrBase = link ? 0xEB000000 : 0xEA000000;
|
||||
@ -68,3 +70,4 @@ void formatMemoryPermission(char *outbuf, MemPerm perm);
|
||||
void formatUserMemoryState(char *outbuf, MemState state);
|
||||
u32 formatMemoryMapOfProcess(char *outbuf, u32 bufLen, Handle handle);
|
||||
int dateTimeToString(char *out, u64 msSince1900, bool filenameFormat);
|
||||
int floatToString(char *out, float f, u32 precision, bool pad);
|
||||
|
@ -81,6 +81,33 @@ u32 waitInputWithTimeout(s32 msec)
|
||||
return keys;
|
||||
}
|
||||
|
||||
u32 waitInputWithTimeoutEx(u32 *outHeldKeys, s32 msec)
|
||||
{
|
||||
s32 n = 0;
|
||||
u32 keys;
|
||||
|
||||
do
|
||||
{
|
||||
svcSleepThread(1 * 1000 * 1000LL);
|
||||
Draw_Lock();
|
||||
if (!isHidInitialized || menuShouldExit)
|
||||
{
|
||||
keys = 0;
|
||||
Draw_Unlock();
|
||||
break;
|
||||
}
|
||||
n++;
|
||||
|
||||
hidScanInput();
|
||||
keys = convertHidKeys(hidKeysDown()) | (convertHidKeys(hidKeysDownRepeat()) & DIRECTIONAL_KEYS);
|
||||
*outHeldKeys = convertHidKeys(hidKeysHeld());
|
||||
Draw_Unlock();
|
||||
} while (keys == 0 && !menuShouldExit && isHidInitialized && (msec < 0 || n < msec));
|
||||
|
||||
|
||||
return keys;
|
||||
}
|
||||
|
||||
u32 waitInput(void)
|
||||
{
|
||||
return waitInputWithTimeout(-1);
|
||||
|
@ -59,7 +59,8 @@ static inline bool ScreenFiltersMenu_IsDefaultSettings(void)
|
||||
static inline u8 ScreenFiltersMenu_GetColorLevel(int inLevel, float wp, float a, float b, float g)
|
||||
{
|
||||
float level = inLevel / 255.0f;
|
||||
level = powf(a * wp * level + b, g);
|
||||
level = a * wp * level + b;
|
||||
level = powf(CLAMP(level, 0.0f, 1.0f), g);
|
||||
s32 levelInt = (s32)(255.0f * level + 0.5f); // round to nearest integer
|
||||
return levelInt <= 0 ? 0 : levelInt >= 255 ? 255 : (u8)levelInt; // clamp
|
||||
}
|
||||
@ -105,6 +106,7 @@ Menu screenFiltersMenu = {
|
||||
{ "[2300K] Warm Incandescent", METHOD, .method = &ScreenFiltersMenu_SetWarmIncandescent },
|
||||
{ "[1900K] Candle", METHOD, .method = &ScreenFiltersMenu_SetCandle },
|
||||
{ "[1200K] Ember", METHOD, .method = &ScreenFiltersMenu_SetEmber },
|
||||
{ "Advanced configuration", METHOD, .method = &ScreenFiltersMenu_AdvancedConfiguration },
|
||||
{},
|
||||
}
|
||||
};
|
||||
@ -137,3 +139,83 @@ DEF_CCT_SETTER(2700, Incandescent)
|
||||
DEF_CCT_SETTER(2300, WarmIncandescent)
|
||||
DEF_CCT_SETTER(1900, Candle)
|
||||
DEF_CCT_SETTER(1200, Ember)
|
||||
|
||||
static void ScreenFiltersMenu_AdvancedConfigurationChangeValue(int pos, int mult)
|
||||
{
|
||||
switch (pos)
|
||||
{
|
||||
case 0:
|
||||
screenFiltersCurrentTemperature += 100 * mult;
|
||||
break;
|
||||
case 1:
|
||||
screenFiltersCurrentGamma += 0.01f * mult;
|
||||
break;
|
||||
case 2:
|
||||
screenFiltersCurrentContrast += 0.01f * mult;
|
||||
break;
|
||||
case 3:
|
||||
screenFiltersCurrentBrightness += 0.01f * mult;
|
||||
break;
|
||||
}
|
||||
|
||||
// Clamp
|
||||
screenFiltersCurrentTemperature = CLAMP(screenFiltersCurrentTemperature, 1000, 25100);
|
||||
screenFiltersCurrentGamma = CLAMP(screenFiltersCurrentGamma, 0.0f, 1411.0f); // ln(255) / ln(254/255): (254/255)^1411 <= 1/255
|
||||
screenFiltersCurrentContrast = CLAMP(screenFiltersCurrentContrast, 0.0f, 255.0f);
|
||||
screenFiltersCurrentBrightness = CLAMP(screenFiltersCurrentBrightness, -1.0f, 1.0f);
|
||||
|
||||
// Update the LUT
|
||||
ScreenFiltersMenu_ApplyColorSettings();
|
||||
}
|
||||
|
||||
void ScreenFiltersMenu_AdvancedConfiguration(void)
|
||||
{
|
||||
u32 posY;
|
||||
u32 input = 0;
|
||||
u32 held = 0;
|
||||
|
||||
char buf[64];
|
||||
int pos = 0;
|
||||
int mult = 1;
|
||||
|
||||
do
|
||||
{
|
||||
Draw_Lock();
|
||||
Draw_DrawString(10, 10, COLOR_TITLE, "Screen filters menu");
|
||||
|
||||
posY = 30;
|
||||
posY = Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Use left/right to increase/decrease the sel. value.\n");
|
||||
posY = Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Hold R to change the value faster.\n") + SPACING_Y;
|
||||
|
||||
Draw_DrawCharacter(10, posY, COLOR_TITLE, pos == 0 ? '>' : ' ');
|
||||
posY = Draw_DrawFormattedString(30, posY, COLOR_WHITE, "Temperature: %12dK \n", screenFiltersCurrentTemperature);
|
||||
|
||||
floatToString(buf, screenFiltersCurrentGamma, 2, true);
|
||||
Draw_DrawCharacter(10, posY, COLOR_TITLE, pos == 1 ? '>' : ' ');
|
||||
posY = Draw_DrawFormattedString(30, posY, COLOR_WHITE, "Gamma: %13s \n", buf);
|
||||
|
||||
floatToString(buf, screenFiltersCurrentContrast, 2, true);
|
||||
Draw_DrawCharacter(10, posY, COLOR_TITLE, pos == 2 ? '>' : ' ');
|
||||
posY = Draw_DrawFormattedString(30, posY, COLOR_WHITE, "Contrast: %13s \n", buf);
|
||||
|
||||
floatToString(buf, screenFiltersCurrentBrightness, 2, true);
|
||||
Draw_DrawCharacter(10, posY, COLOR_TITLE, pos == 3 ? '>' : ' ');
|
||||
posY = Draw_DrawFormattedString(30, posY, COLOR_WHITE, "Brightness: %13s \n", buf);
|
||||
|
||||
input = waitInputWithTimeoutEx(&held, -1);
|
||||
mult = (held & KEY_R) ? 10 : 1;
|
||||
|
||||
if (input & KEY_LEFT)
|
||||
ScreenFiltersMenu_AdvancedConfigurationChangeValue(pos, -mult);
|
||||
if (input & KEY_RIGHT)
|
||||
ScreenFiltersMenu_AdvancedConfigurationChangeValue(pos, mult);
|
||||
if (input & KEY_UP)
|
||||
pos = (4 + pos - 1) % 4;
|
||||
if (input & KEY_DOWN)
|
||||
pos = (pos + 1) % 4;
|
||||
|
||||
Draw_FlushFramebuffer();
|
||||
Draw_Unlock();
|
||||
}
|
||||
while(!(input & (KEY_A | KEY_B)) && !menuShouldExit);
|
||||
}
|
||||
|
@ -28,6 +28,8 @@
|
||||
#include "csvc.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <3ds.h>
|
||||
|
||||
void formatMemoryPermission(char *outbuf, MemPerm perm)
|
||||
{
|
||||
@ -161,3 +163,30 @@ int dateTimeToString(char *out, u64 msSince1900, bool filenameFormat)
|
||||
else
|
||||
return sprintf(out, "%04lu-%02lu-%02lu %02lu:%02lu:%02lu", year, month, days, hours, minutes, seconds);
|
||||
}
|
||||
|
||||
int floatToString(char *out, float f, u32 precision, bool pad)
|
||||
{
|
||||
// Floating point stuff is cringe
|
||||
if (isnanf(f))
|
||||
return sprintf(out, "NaN");
|
||||
else if (isinff(f) && f >= -0.0f)
|
||||
return sprintf(out, "inf");
|
||||
else if (isinff(f))
|
||||
return sprintf(out, "-inf");
|
||||
|
||||
static const u64 pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
|
||||
precision = precision >= 10 ? 10 : precision;
|
||||
|
||||
u64 mult = pow10[precision];
|
||||
double f2 = fabs((double)f) * mult + 0.5;
|
||||
const char *sign = f2 >= 0.0f ? "" : "-";
|
||||
u64 f3 = (u64)f2;
|
||||
|
||||
u64 intPart = f3 / mult;
|
||||
u64 fracPart = f3 % mult;
|
||||
|
||||
if (pad)
|
||||
return sprintf(out, "%s%llu.%0*llu", sign, intPart, (int)precision, fracPart);
|
||||
else
|
||||
return sprintf(out, "%s%llu.%llu", sign, intPart, fracPart);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user