Add config persistence for new screen filters stuff

This commit is contained in:
TuxSH 2023-01-21 18:28:53 +00:00
parent e2e38d9b9f
commit 8dd40158ca
15 changed files with 223 additions and 27 deletions

Binary file not shown.

View File

@ -24,6 +24,8 @@
* reasonable ways as different from the original version. * reasonable ways as different from the original version.
*/ */
#define _GNU_SOURCE // for strchrnul
#include <assert.h> #include <assert.h>
#include <strings.h> #include <strings.h>
#include "config.h" #include "config.h"
@ -42,6 +44,9 @@
#define MAKE_LUMA_VERSION_MCU(major, minor, build) (u16)(((major) & 0xFF) << 8 | ((minor) & 0x1F) << 5 | ((build) & 7)) #define MAKE_LUMA_VERSION_MCU(major, minor, build) (u16)(((major) & 0xFF) << 8 | ((minor) & 0x1F) << 5 | ((build) & 7))
#define FLOAT_CONV_MULT 100000000ll
#define FLOAT_CONV_PRECISION 8u
CfgData configData; CfgData configData;
ConfigurationStatus needConfig; ConfigurationStatus needConfig;
static CfgData oldConfig; static CfgData oldConfig;
@ -95,10 +100,9 @@ static int parseBoolOption(bool *out, const char *val)
} }
} }
static int parseDecIntOption(s64 *out, const char *val, s64 minval, s64 maxval) static int parseDecIntOptionImpl(s64 *out, const char *val, size_t numDigits, s64 minval, s64 maxval)
{ {
*out = 0; *out = 0;
size_t numDigits = strlen(val);
s64 res = 0; s64 res = 0;
size_t i = 0; size_t i = 0;
@ -130,6 +134,61 @@ static int parseDecIntOption(s64 *out, const char *val, s64 minval, s64 maxval)
} }
} }
static int parseDecIntOption(s64 *out, const char *val, s64 minval, s64 maxval)
{
return parseDecIntOptionImpl(out, val, strlen(val), minval, maxval);
}
static int parseDecFloatOption(s64 *out, const char *val, s64 minval, s64 maxval)
{
char *point = strchrnul(val, '.');
if (point == val) {
return -1;
}
// Parse integer part, then fractional part
s64 intPart = 0;
s64 fracPart = 0;
int rc = parseDecIntOptionImpl(&intPart, val, point - val, INT64_MIN, INT64_MAX);
if (rc != 0) {
return -1;
}
s64 sign = intPart < 0 ? -1 : 1;
s64 intPartAbs = sign == -1 ? -intPart : intPart;
s64 res = 0;
bool of = __builtin_mul_overflow(intPartAbs, FLOAT_CONV_MULT, &res);
if (of) {
return -1;
}
s64 mul = FLOAT_CONV_MULT / 10;
// Check if there's a fractional part
if (point[0] != '\0' && point[1] != '\0') {
for (char *pos = point + 1; *pos != '\0' && mul > 0; pos++) {
if (*pos < '0' || *pos > '9') {
return -1;
}
res += (*pos - '0') * mul;
mul /= 10;
}
}
res = sign * (res + fracPart);
if (res <= maxval && res >= minval && !of) {
*out = res;
return 0;
} else {
return -1;
}
}
static int parseHexIntOption(u64 *out, const char *val, u64 minval, u64 maxval) static int parseHexIntOption(u64 *out, const char *val, u64 minval, u64 maxval)
{ {
*out = 0; *out = 0;
@ -222,6 +281,34 @@ static void menuComboToString(char *out, u32 combo)
out[-1] = 0; out[-1] = 0;
} }
static int encodedFloatToString(char *out, s64 val)
{
s64 sign = val >= 0 ? 1 : -1;
s64 intPart = (sign * val) / FLOAT_CONV_MULT;
s64 fracPart = (sign * val) % FLOAT_CONV_MULT;
while (fracPart % 10 != 0) {
// Remove trailing zeroes
fracPart /= 10;
}
int n = sprintf(out, "%lld", sign * intPart);
if (fracPart != 0) {
n += sprintf(out + n, ".%0*lld", (int)FLOAT_CONV_PRECISION, fracPart);
// Remove trailing zeroes
int n2 = n - 1;
while (out[n2] == '0') {
out[n2--] = '\0';
}
n = n2;
}
return n;
}
static bool hasIniParseError = false; static bool hasIniParseError = false;
static int iniParseErrorLine = 0; static int iniParseErrorLine = 0;
@ -339,15 +426,35 @@ static int configIniHandler(void* user, const char* section, const char* name, c
CHECK_PARSE_OPTION(parseKeyComboOption(&opt, value)); CHECK_PARSE_OPTION(parseKeyComboOption(&opt, value));
cfg->rosalinaMenuCombo = opt; cfg->rosalinaMenuCombo = opt;
return 1; return 1;
} else if (strcmp(name, "ntp_tz_offset_min") == 0) {
s64 opt;
CHECK_PARSE_OPTION(parseDecIntOption(&opt, value, -779, 899));
cfg->ntpTzOffetMinutes = (s16)opt;
return 1;
} else if (strcmp(name, "screen_filters_cct") == 0) { } else if (strcmp(name, "screen_filters_cct") == 0) {
s64 opt; s64 opt;
CHECK_PARSE_OPTION(parseDecIntOption(&opt, value, 1000, 25100)); CHECK_PARSE_OPTION(parseDecIntOption(&opt, value, 1000, 25100));
cfg->screenFiltersCct = (u32)opt; cfg->screenFiltersCct = (u32)opt;
return 1; return 1;
} else if (strcmp(name, "ntp_tz_offset_min") == 0) { } else if (strcmp(name, "screen_filters_gamma") == 0) {
s64 opt; s64 opt;
CHECK_PARSE_OPTION(parseDecIntOption(&opt, value, -779, 899)); CHECK_PARSE_OPTION(parseDecFloatOption(&opt, value, 0, 1411 * FLOAT_CONV_MULT));
cfg->ntpTzOffetMinutes = (s16)opt; cfg->screenFiltersGammaEnc = opt;
return 1;
} else if (strcmp(name, "screen_filters_contrast") == 0) {
s64 opt;
CHECK_PARSE_OPTION(parseDecFloatOption(&opt, value, 0, 255 * FLOAT_CONV_MULT));
cfg->screenFiltersContrastEnc = opt;
return 1;
} else if (strcmp(name, "screen_filters_brightness") == 0) {
s64 opt;
CHECK_PARSE_OPTION(parseDecFloatOption(&opt, value, -1 * FLOAT_CONV_MULT, 1 * FLOAT_CONV_MULT));
cfg->screenFiltersBrightnessEnc = opt;
return 1;
} else if (strcmp(name, "screen_filters_invert") == 0) {
bool opt;
CHECK_PARSE_OPTION(parseBoolOption(&opt, value));
cfg->screenFiltersInvert = opt;
return 1; return 1;
} }
else { else {
@ -423,6 +530,13 @@ static size_t saveLumaIniConfigToStr(char *out)
static const int pinOptionToDigits[] = { 0, 4, 6, 8 }; static const int pinOptionToDigits[] = { 0, 4, 6, 8 };
int pinNumDigits = pinOptionToDigits[MULTICONFIG(PIN)]; int pinNumDigits = pinOptionToDigits[MULTICONFIG(PIN)];
char screenFiltersGammaStr[32];
char screenFiltersContrastStr[32];
char screenFiltersBrightnessStr[32];
encodedFloatToString(screenFiltersGammaStr, cfg->screenFiltersGammaEnc);
encodedFloatToString(screenFiltersContrastStr, cfg->screenFiltersContrastEnc);
encodedFloatToString(screenFiltersBrightnessStr, cfg->screenFiltersBrightnessEnc);
int n = sprintf( int n = sprintf(
out, (const char *)config_template_ini, out, (const char *)config_template_ini,
lumaVerStr, lumaRevSuffixStr, lumaVerStr, lumaRevSuffixStr,
@ -437,7 +551,11 @@ static size_t saveLumaIniConfigToStr(char *out)
pinNumDigits, n3dsCpuStr, (int)MULTICONFIG(AUTOBOOTMODE), pinNumDigits, n3dsCpuStr, (int)MULTICONFIG(AUTOBOOTMODE),
cfg->hbldr3dsxTitleId, rosalinaMenuComboStr, cfg->hbldr3dsxTitleId, rosalinaMenuComboStr,
(int)cfg->screenFiltersCct, (int)cfg->ntpTzOffetMinutes, (int)cfg->ntpTzOffetMinutes,
(int)cfg->screenFiltersCct, screenFiltersGammaStr,
screenFiltersContrastStr, screenFiltersBrightnessStr,
(int)cfg->screenFiltersInvert,
cfg->autobootTwlTitleId, (int)cfg->autobootCtrAppmemtype, cfg->autobootTwlTitleId, (int)cfg->autobootCtrAppmemtype,
@ -547,6 +665,8 @@ bool readConfig(void)
configData.hbldr3dsxTitleId = HBLDR_DEFAULT_3DSX_TID; configData.hbldr3dsxTitleId = HBLDR_DEFAULT_3DSX_TID;
configData.rosalinaMenuCombo = 1u << 9 | 1u << 7 | 1u << 2; // L+Start+Select configData.rosalinaMenuCombo = 1u << 9 | 1u << 7 | 1u << 2; // L+Start+Select
configData.screenFiltersCct = 6500; // default temp, no-op configData.screenFiltersCct = 6500; // default temp, no-op
configData.screenFiltersGammaEnc = 1 * FLOAT_CONV_MULT; // 1.0f
configData.screenFiltersContrastEnc = 1 * FLOAT_CONV_MULT; // 1.0f
configData.autobootTwlTitleId = AUTOBOOT_DEFAULT_TWL_TID; configData.autobootTwlTitleId = AUTOBOOT_DEFAULT_TWL_TID;
ret = false; ret = false;
} }

View File

@ -36,7 +36,7 @@
#define CONFIG_FILE "config.bin" #define CONFIG_FILE "config.bin"
#define CONFIG_VERSIONMAJOR 3 #define CONFIG_VERSIONMAJOR 3
#define CONFIG_VERSIONMINOR 1 #define CONFIG_VERSIONMINOR 2
#define BOOTCFG_NAND BOOTCONFIG(0, 7) #define BOOTCFG_NAND BOOTCONFIG(0, 7)
#define BOOTCFG_FIRM BOOTCONFIG(3, 7) #define BOOTCFG_FIRM BOOTCONFIG(3, 7)

View File

@ -132,8 +132,12 @@ u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32
u32 splashDurationMsec; u32 splashDurationMsec;
u64 hbldr3dsxTitleId; u64 hbldr3dsxTitleId;
u32 rosalinaMenuCombo; u32 rosalinaMenuCombo;
u16 screenFiltersCct;
s16 ntpTzOffetMinutes; s16 ntpTzOffetMinutes;
u16 screenFiltersCct;
s64 screenFiltersGammaEnc;
s64 screenFiltersContrastEnc;
s64 screenFiltersBrightnessEnc;
bool screenFiltersInvert;
u64 autobootTwlTitleId; u64 autobootTwlTitleId;
u8 autobootCtrAppmemtype; u8 autobootCtrAppmemtype;
} info; } info;
@ -209,8 +213,12 @@ u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32
info->splashDurationMsec = configData.splashDurationMsec; info->splashDurationMsec = configData.splashDurationMsec;
info->hbldr3dsxTitleId = configData.hbldr3dsxTitleId; info->hbldr3dsxTitleId = configData.hbldr3dsxTitleId;
info->rosalinaMenuCombo = configData.rosalinaMenuCombo; info->rosalinaMenuCombo = configData.rosalinaMenuCombo;
info->screenFiltersCct = configData.screenFiltersCct;
info->ntpTzOffetMinutes = configData.ntpTzOffetMinutes; info->ntpTzOffetMinutes = configData.ntpTzOffetMinutes;
info->screenFiltersCct = configData.screenFiltersCct;
info->screenFiltersGammaEnc = configData.screenFiltersGammaEnc;
info->screenFiltersContrastEnc = configData.screenFiltersContrastEnc;
info->screenFiltersBrightnessEnc = configData.screenFiltersBrightnessEnc;
info->screenFiltersInvert = configData.screenFiltersInvert;
info->autobootTwlTitleId = configData.autobootTwlTitleId; info->autobootTwlTitleId = configData.autobootTwlTitleId;
info->autobootCtrAppmemtype = configData.autobootCtrAppmemtype; info->autobootCtrAppmemtype = configData.autobootCtrAppmemtype;
info->versionMajor = VERSION_MAJOR; info->versionMajor = VERSION_MAJOR;

View File

@ -69,8 +69,12 @@ typedef struct {
u64 hbldr3dsxTitleId; u64 hbldr3dsxTitleId;
u32 rosalinaMenuCombo; u32 rosalinaMenuCombo;
u16 screenFiltersCct;
s16 ntpTzOffetMinutes; s16 ntpTzOffetMinutes;
u16 screenFiltersCct;
s64 screenFiltersGammaEnc;
s64 screenFiltersContrastEnc;
s64 screenFiltersBrightnessEnc;
bool screenFiltersInvert;
u64 autobootTwlTitleId; u64 autobootTwlTitleId;
u8 autobootCtrAppmemtype; u8 autobootCtrAppmemtype;

View File

@ -130,8 +130,12 @@ typedef struct CfwInfo
u32 splashDurationMsec; u32 splashDurationMsec;
u64 hbldr3dsxTitleId; u64 hbldr3dsxTitleId;
u32 rosalinaMenuCombo; u32 rosalinaMenuCombo;
u16 screenFiltersCct;
s16 ntpTzOffetMinutes; s16 ntpTzOffetMinutes;
u16 screenFiltersCct;
s64 screenFiltersGammaEnc;
s64 screenFiltersContrastEnc;
s64 screenFiltersBrightnessEnc;
bool screenFiltersInvert;
u64 autobootTwlTitleId; u64 autobootTwlTitleId;
u8 autobootCtrAppmemtype; u8 autobootCtrAppmemtype;
} CfwInfo; } CfwInfo;

View File

@ -80,6 +80,18 @@ Result GetSystemInfoHook(s64 *out, s32 type, s32 param)
case 0x103: case 0x103:
*out = (s64)cfwInfo.ntpTzOffetMinutes; *out = (s64)cfwInfo.ntpTzOffetMinutes;
break; break;
case 0x104:
*out = cfwInfo.screenFiltersGammaEnc;
break;
case 0x105:
*out = cfwInfo.screenFiltersContrastEnc;
break;
case 0x106:
*out = cfwInfo.screenFiltersBrightnessEnc;
break;
case 0x107:
*out = (s64)cfwInfo.screenFiltersInvert;
break;
case 0x200: // isRelease case 0x200: // isRelease
*out = cfwInfo.flags & 1; *out = cfwInfo.flags & 1;

View File

@ -33,13 +33,14 @@
#define HID_PAD (REG32(0x10146000) ^ 0xFFF) #define HID_PAD (REG32(0x10146000) ^ 0xFFF)
#define DEFAULT_MENU_COMBO (KEY_L | KEY_DDOWN | KEY_SELECT) #define DEFAULT_MENU_COMBO (KEY_L | KEY_DDOWN | KEY_SELECT)
#define DIRECTIONAL_KEYS (KEY_DOWN | KEY_UP | KEY_LEFT | KEY_RIGHT) #define DIRECTIONAL_KEYS (KEY_DOWN | KEY_UP | KEY_LEFT | KEY_RIGHT)
#define CORE_APPLICATION 0 #define CORE_APPLICATION 0
#define CORE_SYSTEM 1 #define CORE_SYSTEM 1
#define FLOAT_CONV_MULT 1e8 // for screen filters
typedef enum MenuItemAction { typedef enum MenuItemAction {
MENU_END = 0, MENU_END = 0,
METHOD = 1, METHOD = 1,

View File

@ -34,9 +34,9 @@ extern int screenFiltersCurrentTemperature;
extern float screenFiltersCurrentGamma; extern float screenFiltersCurrentGamma;
extern float screenFiltersCurrentContrast; extern float screenFiltersCurrentContrast;
extern float screenFiltersCurrentBrightness; extern float screenFiltersCurrentBrightness;
extern bool screenFiltersCurrentInvert;
void ScreenFiltersMenu_SetCct(int cct); void ScreenFiltersMenu_RestoreSettings(void);
void ScreenFiltersMenu_RestoreCct(void);
void ScreenFiltersMenu_SetDefault(void); // 6500K (default) void ScreenFiltersMenu_SetDefault(void); // 6500K (default)

View File

@ -163,7 +163,7 @@ static void handleShellNotification(u32 notificationId)
if (notificationId == 0x213) { if (notificationId == 0x213) {
// Shell opened // Shell opened
// Note that this notification is fired on system init // Note that this notification is fired on system init
ScreenFiltersMenu_RestoreCct(); ScreenFiltersMenu_RestoreSettings();
menuShouldExit = false; menuShouldExit = false;
} else { } else {
// Shell closed // Shell closed

View File

@ -258,15 +258,32 @@ void menuThreadMain(void)
while (!isServiceUsable("ac:u") || !isServiceUsable("hid:USER")) while (!isServiceUsable("ac:u") || !isServiceUsable("hid:USER"))
svcSleepThread(500 * 1000 * 1000LL); svcSleepThread(500 * 1000 * 1000LL);
s64 out; s64 out = 0;
svcGetSystemInfo(&out, 0x10000, 0x102); svcGetSystemInfo(&out, 0x10000, 0x102);
screenFiltersCurrentTemperature = (int)(u32)out; screenFiltersCurrentTemperature = (int)(u32)out;
if (screenFiltersCurrentTemperature < 1000 || screenFiltersCurrentTemperature > 25100) if (screenFiltersCurrentTemperature < 1000 || screenFiltersCurrentTemperature > 25100)
screenFiltersCurrentTemperature = 6500; screenFiltersCurrentTemperature = 6500;
// Careful about race conditions here svcGetSystemInfo(&out, 0x10000, 0x104);
if (screenFiltersCurrentTemperature != 6500) screenFiltersCurrentGamma = (float)(out / FLOAT_CONV_MULT);
ScreenFiltersMenu_SetCct(screenFiltersCurrentTemperature); if (screenFiltersCurrentGamma < 0.0f || screenFiltersCurrentGamma > 1411.0f)
screenFiltersCurrentGamma = 1.0f;
svcGetSystemInfo(&out, 0x10000, 0x105);
screenFiltersCurrentContrast = (float)(out / FLOAT_CONV_MULT);
if (screenFiltersCurrentContrast < 0.0f || screenFiltersCurrentContrast > 255.0f)
screenFiltersCurrentContrast = 1.0f;
svcGetSystemInfo(&out, 0x10000, 0x106);
screenFiltersCurrentBrightness = (float)(out / FLOAT_CONV_MULT);
if (screenFiltersCurrentBrightness < -1.0f || screenFiltersCurrentBrightness > 1.0f)
screenFiltersCurrentBrightness = 0.0f;
svcGetSystemInfo(&out, 0x10000, 0x107);
screenFiltersCurrentInvert = (bool)out;
ScreenFiltersMenu_RestoreSettings();
hidInit(); // assume this doesn't fail hidInit(); // assume this doesn't fail
isHidInitialized = true; isHidInitialized = true;

View File

@ -98,8 +98,12 @@ typedef struct CfgData {
u64 hbldr3dsxTitleId; u64 hbldr3dsxTitleId;
u32 rosalinaMenuCombo; u32 rosalinaMenuCombo;
u16 screenFiltersCct;
s16 ntpTzOffetMinutes; s16 ntpTzOffetMinutes;
u16 screenFiltersCct;
float screenFiltersGamma;
float screenFiltersContrast;
float screenFiltersBrightness;
bool screenFiltersInvert;
u64 autobootTwlTitleId; u64 autobootTwlTitleId;
u8 autobootCtrAppmemtype; u8 autobootCtrAppmemtype;
@ -297,6 +301,13 @@ static size_t saveLumaIniConfigToStr(char *out, const CfgData *cfg)
static const int pinOptionToDigits[] = { 0, 4, 6, 8 }; static const int pinOptionToDigits[] = { 0, 4, 6, 8 };
int pinNumDigits = pinOptionToDigits[MULTICONFIG(PIN)]; int pinNumDigits = pinOptionToDigits[MULTICONFIG(PIN)];
char screenFiltersGammaStr[32];
char screenFiltersContrastStr[32];
char screenFiltersBrightnessStr[32];
floatToString(screenFiltersGammaStr, cfg->screenFiltersGamma, 6, false);
floatToString(screenFiltersContrastStr, cfg->screenFiltersContrast, 6, false);
floatToString(screenFiltersBrightnessStr, cfg->screenFiltersBrightness, 6, false);
int n = sprintf( int n = sprintf(
out, (const char *)config_template_ini, out, (const char *)config_template_ini,
lumaVerStr, lumaRevSuffixStr, lumaVerStr, lumaRevSuffixStr,
@ -311,7 +322,11 @@ static size_t saveLumaIniConfigToStr(char *out, const CfgData *cfg)
pinNumDigits, n3dsCpuStr, (int)MULTICONFIG(AUTOBOOTMODE), pinNumDigits, n3dsCpuStr, (int)MULTICONFIG(AUTOBOOTMODE),
cfg->hbldr3dsxTitleId, rosalinaMenuComboStr, cfg->hbldr3dsxTitleId, rosalinaMenuComboStr,
(int)cfg->screenFiltersCct, (int)cfg->ntpTzOffetMinutes, (int)cfg->ntpTzOffetMinutes,
(int)cfg->screenFiltersCct, screenFiltersGammaStr,
screenFiltersContrastStr, screenFiltersBrightnessStr,
(int)cfg->screenFiltersInvert,
cfg->autobootTwlTitleId, (int)cfg->autobootCtrAppmemtype, cfg->autobootTwlTitleId, (int)cfg->autobootCtrAppmemtype,
@ -370,8 +385,12 @@ void MiscellaneousMenu_SaveSettings(void)
configData.splashDurationMsec = splashDurationMsec; configData.splashDurationMsec = splashDurationMsec;
configData.hbldr3dsxTitleId = Luma_SharedConfig->hbldr_3dsx_tid; configData.hbldr3dsxTitleId = Luma_SharedConfig->hbldr_3dsx_tid;
configData.rosalinaMenuCombo = menuCombo; configData.rosalinaMenuCombo = menuCombo;
configData.screenFiltersCct = (u16)screenFiltersCurrentTemperature;
configData.ntpTzOffetMinutes = (s16)lastNtpTzOffset; configData.ntpTzOffetMinutes = (s16)lastNtpTzOffset;
configData.screenFiltersCct = (u16)screenFiltersCurrentTemperature;
configData.screenFiltersGamma = screenFiltersCurrentGamma;
configData.screenFiltersContrast = screenFiltersCurrentContrast;
configData.screenFiltersBrightness = screenFiltersCurrentBrightness;
configData.screenFiltersInvert = screenFiltersCurrentInvert;
configData.autobootTwlTitleId = autobootTwlTitleId; configData.autobootTwlTitleId = autobootTwlTitleId;
configData.autobootCtrAppmemtype = autobootCtrAppmemtype; configData.autobootCtrAppmemtype = autobootCtrAppmemtype;

View File

@ -81,7 +81,7 @@ static u8 ScreenFilterMenu_CalculatePolynomialColorLutComponent(const float coef
level = powf(CLAMP(level, 0.0f, 1.0f), gamma); level = powf(CLAMP(level, 0.0f, 1.0f), gamma);
s32 levelInt = (s32)(255.0f * level + 0.5f); // round up s32 levelInt = (s32)(255.0f * level + 0.5f); // round up
return (u8)CLAMP(levelInt, 0, 255); return (u8)CLAMP(levelInt, 0, 255); // clamp again just to be sure
} }
static void ScreenFilterMenu_WritePolynomialColorLut(const float coeffs[][3], bool invert, float gamma, u32 dim) static void ScreenFilterMenu_WritePolynomialColorLut(const float coeffs[][3], bool invert, float gamma, u32 dim)
@ -121,7 +121,7 @@ static void ScreenFiltersMenu_ApplyColorSettings(void)
ScreenFilterMenu_WritePolynomialColorLut(poly, inv, g, 1); ScreenFilterMenu_WritePolynomialColorLut(poly, inv, g, 1);
} }
void ScreenFiltersMenu_SetCct(int cct) static void ScreenFiltersMenu_SetCct(int cct)
{ {
screenFiltersCurrentTemperature = cct; screenFiltersCurrentTemperature = cct;
ScreenFiltersMenu_ApplyColorSettings(); ScreenFiltersMenu_ApplyColorSettings();
@ -151,7 +151,7 @@ void ScreenFiltersMenu_Set##name(void)\
ScreenFiltersMenu_SetCct(temp);\ ScreenFiltersMenu_SetCct(temp);\
} }
void ScreenFiltersMenu_RestoreCct(void) void ScreenFiltersMenu_RestoreSettings(void)
{ {
// Not initialized/default: return // Not initialized/default: return
if (ScreenFiltersMenu_IsDefaultSettings()) if (ScreenFiltersMenu_IsDefaultSettings())

View File

@ -175,7 +175,7 @@ int floatToString(char *out, float f, u32 precision, bool pad)
return sprintf(out, "-inf"); return sprintf(out, "-inf");
static const u64 pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; static const u64 pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
precision = precision >= 10 ? 10 : precision; precision = precision >= 6 ? 6 : precision; // result inaccurate after 1e-6
u64 mult = pow10[precision]; u64 mult = pow10[precision];
double f2 = fabs((double)f) * mult + 0.5; double f2 = fabs((double)f) * mult + 0.5;
@ -188,5 +188,16 @@ int floatToString(char *out, float f, u32 precision, bool pad)
if (pad) if (pad)
return sprintf(out, "%s%llu.%0*llu", sign, intPart, (int)precision, fracPart); return sprintf(out, "%s%llu.%0*llu", sign, intPart, (int)precision, fracPart);
else else
return sprintf(out, "%s%llu.%llu", sign, intPart, fracPart); {
int n = sprintf(out, "%s%llu", sign, intPart);
if (fracPart == 0)
return n;
n += sprintf(out + n, ".%0*llu", (int)precision, fracPart);
int n2 = n - 1;
while (out[n2] == '0')
out[n2--] = '\0';
return n2;
}
} }