diff --git a/sysmodules/rosalina/Makefile b/sysmodules/rosalina/Makefile index 99f666b..a966fee 100644 --- a/sysmodules/rosalina/Makefile +++ b/sysmodules/rosalina/Makefile @@ -46,7 +46,7 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 ASFLAGS := -g $(ARCH) LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map),-wrap,exit,--section-start,.text=0x14000000 -LIBS := -lctru +LIBS := -lctru -lm #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing diff --git a/sysmodules/rosalina/include/menus/screen_filters.h b/sysmodules/rosalina/include/menus/screen_filters.h index 8d35ee3..3fdaee1 100644 --- a/sysmodules/rosalina/include/menus/screen_filters.h +++ b/sysmodules/rosalina/include/menus/screen_filters.h @@ -31,6 +31,9 @@ extern Menu screenFiltersMenu; extern int screenFiltersCurrentTemperature; +extern float screenFiltersCurrentGamma; +extern float screenFiltersCurrentContrast; +extern float screenFiltersCurrentBrightness; void ScreenFiltersMenu_SetCct(int cct); void ScreenFiltersMenu_RestoreCct(void); diff --git a/sysmodules/rosalina/include/redshift/colorramp.h b/sysmodules/rosalina/include/redshift/colorramp.h index 985e774..92080c4 100644 --- a/sysmodules/rosalina/include/redshift/colorramp.h +++ b/sysmodules/rosalina/include/redshift/colorramp.h @@ -22,11 +22,8 @@ #include -#include "redshift.h" +//#include "redshift.h" -void colorramp_fill(uint16_t *gamma_r, uint16_t *gamma_g, uint16_t *gamma_b, - int size, const color_setting_t *setting); -void colorramp_fill_float(float *gamma_r, float *gamma_g, float *gamma_b, - int size, const color_setting_t *setting); +void colorramp_get_white_point(float *out_white_point, int temperature); // not in original code -#endif /* ! REDSHIFT_COLORRAMP_H */ \ No newline at end of file +#endif /* ! REDSHIFT_COLORRAMP_H */ diff --git a/sysmodules/rosalina/include/redshift/redshift.h b/sysmodules/rosalina/include/redshift/redshift.h deleted file mode 100644 index 6aca3e6..0000000 --- a/sysmodules/rosalina/include/redshift/redshift.h +++ /dev/null @@ -1,153 +0,0 @@ -/* redshift.h -- Main program header - This file is part of Redshift. - - Redshift is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Redshift is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Redshift. If not, see . - - Copyright (c) 2013-2017 Jon Lund Steffensen -*/ - -#ifndef REDSHIFT_REDSHIFT_H -#define REDSHIFT_REDSHIFT_H - -#include -#include - -/* The color temperature when no adjustment is applied. */ -#define NEUTRAL_TEMP 6500 - - -/* Location */ -typedef struct { - float lat; - float lon; -} location_t; - -/* Periods of day. */ -typedef enum { - PERIOD_NONE = 0, - PERIOD_DAYTIME, - PERIOD_NIGHT, - PERIOD_TRANSITION -} period_t; - -/* Color setting */ -typedef struct { - int temperature; - float gamma[3]; - float brightness; -} color_setting_t; - -/* Program modes. */ -typedef enum { - PROGRAM_MODE_CONTINUAL, - PROGRAM_MODE_ONE_SHOT, - PROGRAM_MODE_PRINT, - PROGRAM_MODE_RESET, - PROGRAM_MODE_MANUAL -} program_mode_t; - -/* Time range. - Fields are offsets from midnight in seconds. */ -typedef struct { - int start; - int end; -} time_range_t; - -/* Transition scheme. - The solar elevations at which the transition begins/ends, - and the association color settings. */ -typedef struct { - double high; - double low; - int use_time; /* When enabled, ignore elevation and use time ranges. */ - time_range_t dawn; - time_range_t dusk; - color_setting_t day; - color_setting_t night; -} transition_scheme_t; - - -/* Gamma adjustment method */ -typedef struct gamma_state gamma_state_t; - -typedef int gamma_method_init_func(gamma_state_t **state); -typedef int gamma_method_start_func(gamma_state_t *state); -typedef void gamma_method_free_func(gamma_state_t *state); -typedef void gamma_method_print_help_func(FILE *f); -typedef int gamma_method_set_option_func(gamma_state_t *state, const char *key, - const char *value); -typedef void gamma_method_restore_func(gamma_state_t *state); -typedef int gamma_method_set_temperature_func( - gamma_state_t *state, const color_setting_t *setting, int preserve); - -typedef struct { - char *name; - - /* If true, this method will be tried if none is explicitly chosen. */ - int autostart; - - /* Initialize state. Options can be set between init and start. */ - gamma_method_init_func *init; - /* Allocate storage and make connections that depend on options. */ - gamma_method_start_func *start; - /* Free all allocated storage and close connections. */ - gamma_method_free_func *free; - - /* Print help on options for this adjustment method. */ - gamma_method_print_help_func *print_help; - /* Set an option key, value-pair */ - gamma_method_set_option_func *set_option; - - /* Restore the adjustment to the state before start was called. */ - gamma_method_restore_func *restore; - /* Set a specific color temperature. */ - gamma_method_set_temperature_func *set_temperature; -} gamma_method_t; - - -/* Location provider */ -typedef struct location_state location_state_t; - -typedef int location_provider_init_func(location_state_t **state); -typedef int location_provider_start_func(location_state_t *state); -typedef void location_provider_free_func(location_state_t *state); -typedef void location_provider_print_help_func(FILE *f); -typedef int location_provider_set_option_func( - location_state_t *state, const char *key, const char *value); -typedef int location_provider_get_fd_func(location_state_t *state); -typedef int location_provider_handle_func( - location_state_t *state, location_t *location, int *available); - -typedef struct { - char *name; - - /* Initialize state. Options can be set between init and start. */ - location_provider_init_func *init; - /* Allocate storage and make connections that depend on options. */ - location_provider_start_func *start; - /* Free all allocated storage and close connections. */ - location_provider_free_func *free; - - /* Print help on options for this location provider. */ - location_provider_print_help_func *print_help; - /* Set an option key, value-pair. */ - location_provider_set_option_func *set_option; - - /* Listen and handle location updates. */ - location_provider_get_fd_func *get_fd; - location_provider_handle_func *handle; -} location_provider_t; - - -#endif /* ! REDSHIFT_REDSHIFT_H */ \ No newline at end of file diff --git a/sysmodules/rosalina/source/menus/screen_filters.c b/sysmodules/rosalina/source/menus/screen_filters.c index 045fae3..84c00ca 100644 --- a/sysmodules/rosalina/source/menus/screen_filters.c +++ b/sysmodules/rosalina/source/menus/screen_filters.c @@ -25,11 +25,11 @@ */ #include <3ds.h> +#include #include "memory.h" #include "menu.h" #include "menus/screen_filters.h" #include "draw.h" -#include "redshift/redshift.h" #include "redshift/colorramp.h" typedef union { @@ -42,67 +42,54 @@ typedef union { u32 raw; } Pixel; -static u16 g_c[0x600]; -static Pixel g_px[0x400]; - int screenFiltersCurrentTemperature = 6500; +float screenFiltersCurrentGamma = 1.0f; +float screenFiltersCurrentContrast = 1.0f; +float screenFiltersCurrentBrightness = 0.0f; -static void ScreenFiltersMenu_WriteLut(const Pixel* lut) +static inline bool ScreenFiltersMenu_IsDefaultSettings(void) +{ + bool ret = screenFiltersCurrentTemperature == 6500; + ret = ret && screenFiltersCurrentGamma == 1.0f; + ret = ret && screenFiltersCurrentContrast == 1.0f; + ret = ret && screenFiltersCurrentBrightness == 0.0f; + return ret; +} + +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); + s32 levelInt = (s32)(255.0f * level + 0.5f); // round to nearest integer + return levelInt <= 0 ? 0 : levelInt >= 255 ? 255 : (u8)levelInt; // clamp +} + +static void ScreenFiltersMenu_ApplyColorSettings(void) { GPU_FB_TOP_COL_LUT_INDEX = 0; GPU_FB_BOTTOM_COL_LUT_INDEX = 0; + float wp[3]; + colorramp_get_white_point(wp, screenFiltersCurrentTemperature); + float a = screenFiltersCurrentContrast; + float g = screenFiltersCurrentGamma; + float b = screenFiltersCurrentBrightness; + for (int i = 0; i <= 255; i++) { - GPU_FB_TOP_COL_LUT_ELEM = lut->raw; - GPU_FB_BOTTOM_COL_LUT_ELEM = lut->raw; - lut++; + Pixel px; + px.r = ScreenFiltersMenu_GetColorLevel(i, wp[0], a, b, g); + px.g = ScreenFiltersMenu_GetColorLevel(i, wp[1], a, b, g); + px.b = ScreenFiltersMenu_GetColorLevel(i, wp[2], a, b, g); + px.z = 0; + GPU_FB_TOP_COL_LUT_ELEM = px.raw; + GPU_FB_BOTTOM_COL_LUT_ELEM = px.raw; } } -static void ScreenFiltersMenu_ApplyColorSettings(color_setting_t* cs) -{ - u8 i = 0; - - memset(g_c, 0, sizeof(g_c)); - memset(g_px, 0, sizeof(g_px)); - - do { - g_px[i].r = i; - g_px[i].g = i; - g_px[i].b = i; - g_px[i].z = 0; - } while(++i); - - do { - *(g_c + i + 0x000) = g_px[i].r | (g_px[i].r << 8); - *(g_c + i + 0x100) = g_px[i].g | (g_px[i].g << 8); - *(g_c + i + 0x200) = g_px[i].b | (g_px[i].b << 8); - } while(++i); - - colorramp_fill(g_c + 0x000, g_c + 0x100, g_c + 0x200, 0x100, cs); - - do { - g_px[i].r = *(g_c + i + 0x000) >> 8; - g_px[i].g = *(g_c + i + 0x100) >> 8; - g_px[i].b = *(g_c + i + 0x200) >> 8; - } while(++i); - - ScreenFiltersMenu_WriteLut(g_px); -} - void ScreenFiltersMenu_SetCct(int cct) { - color_setting_t cs; - memset(&cs, 0, sizeof(cs)); - - cs.temperature = cct; - /*cs.gamma[0] = 1.0F; - cs.gamma[1] = 1.0F; - cs.gamma[2] = 1.0F; - cs.brightness = 1.0F;*/ - - ScreenFiltersMenu_ApplyColorSettings(&cs); screenFiltersCurrentTemperature = cct; + ScreenFiltersMenu_ApplyColorSettings(); } Menu screenFiltersMenu = { @@ -131,15 +118,12 @@ void ScreenFiltersMenu_Set##name(void)\ void ScreenFiltersMenu_RestoreCct(void) { // Not initialized/default: return - if (screenFiltersCurrentTemperature == 6500) + if (ScreenFiltersMenu_IsDefaultSettings()) return; // Wait for GSP to restore the CCT table - while (GPU_FB_TOP_COL_LUT_ELEM != g_px[0].raw) - svcSleepThread(10 * 1000 * 1000LL); - - svcSleepThread(10 * 1000 * 1000LL); - ScreenFiltersMenu_WriteLut(g_px); + svcSleepThread(20 * 1000 * 1000LL); + ScreenFiltersMenu_ApplyColorSettings(); } DEF_CCT_SETTER(6500, Default) diff --git a/sysmodules/rosalina/source/redshift/colorramp.c b/sysmodules/rosalina/source/redshift/colorramp.c index e24b9d7..dfb427e 100644 --- a/sysmodules/rosalina/source/redshift/colorramp.c +++ b/sysmodules/rosalina/source/redshift/colorramp.c @@ -21,7 +21,7 @@ #include //#include -#include "redshift/redshift.h" +//#include "redshift/redshift.h" /* Whitepoint values for temperatures at 100K intervals. These will be interpolated for the actual temperature. @@ -281,49 +281,13 @@ interpolate_color(float a, const float *c1, const float *c2, float *c) c[2] = (1.0-a)*c1[2] + a*c2[2]; } -/* Helper macro used in the fill functions */ -#define F(Y, C) ((Y) * white_point[C]) -/*#define F(Y, C) pow((Y) * setting->brightness * \ - white_point[C], 1.0/setting->gamma[C])*/ - -void -colorramp_fill(uint16_t *gamma_r, uint16_t *gamma_g, uint16_t *gamma_b, - int size, const color_setting_t *setting) +// Not in original code +void colorramp_get_white_point(float *out_white_point, int temperature) { /* Approximate white point */ - float white_point[3]; - float alpha = (setting->temperature % 100) / 100.0; - int temp_index = ((setting->temperature - 1000) / 100)*3; + float alpha = (temperature % 100) / 100.0; + int temp_index = ((temperature - 1000) / 100)*3; interpolate_color(alpha, &blackbody_color[temp_index], - &blackbody_color[temp_index+3], white_point); - - for (int i = 0; i < size; i++) { - gamma_r[i] = F((double)gamma_r[i]/(UINT16_MAX+1), 0) * - (UINT16_MAX+1); - gamma_g[i] = F((double)gamma_g[i]/(UINT16_MAX+1), 1) * - (UINT16_MAX+1); - gamma_b[i] = F((double)gamma_b[i]/(UINT16_MAX+1), 2) * - (UINT16_MAX+1); - } + &blackbody_color[temp_index+3], out_white_point); } - -void -colorramp_fill_float(float *gamma_r, float *gamma_g, float *gamma_b, - int size, const color_setting_t *setting) -{ - /* Approximate white point */ - float white_point[3]; - float alpha = (setting->temperature % 100) / 100.0; - int temp_index = ((setting->temperature - 1000) / 100)*3; - interpolate_color(alpha, &blackbody_color[temp_index], - &blackbody_color[temp_index+3], white_point); - - for (int i = 0; i < size; i++) { - gamma_r[i] = F((double)gamma_r[i], 0); - gamma_g[i] = F((double)gamma_g[i], 1); - gamma_b[i] = F((double)gamma_b[i], 2); - } -} - -#undef F