git.y1.nz

SameBoy

Accurate GB/GBC emulator
download: https://git.y1.nz/archives/sameboy.tar.gz
README | Files | Log | Refs | LICENSE

commit 159d9d0348bbc14a71a59180f3c5199eb278dd07
parent b5a611c5db46d6a0649d04d24d8d6339200f9ca1
Author: Lior Halphon <LIJI32@gmail.com>
Date:   Fri, 25 Dec 2020 14:14:17 +0200

Color temperature control

Diffstat:
MCocoa/Document.m13+++++++++++++
MCocoa/GBPreferencesWindow.h2+-
MCocoa/GBPreferencesWindow.m20++++++++++++++++++++
MCocoa/Preferences.xib5+++--
MCore/display.c51+++++++++++++++++++++++++++++++++++++++++++++------
MCore/display.h1+
MCore/gb.h1+
MSDL/gui.c43+++++++++++++++++++++++++++++++++++++++++++
MSDL/gui.h4++++
MSDL/main.c3+++
10 files changed, 134 insertions(+), 9 deletions(-)

diff --git a/Cocoa/Document.m b/Cocoa/Document.m @@ -690,6 +690,11 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency) object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(updateLightTemperature) + name:@"GBLightTemperatureChanged" + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateFrameBlendingMode) name:@"GBFrameBlendingModeChanged" object:nil]; @@ -1835,6 +1840,14 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency) } } +- (void) updateLightTemperature +{ + if (GB_is_inited(&gb)) { + GB_set_light_temperature(&gb, [[NSUserDefaults standardUserDefaults] doubleForKey:@"GBLightTemperature"]); + } +} + + - (void) updateFrameBlendingMode { self.view.frameBlendingMode = (GB_frame_blending_mode_t) [[NSUserDefaults standardUserDefaults] integerForKey:@"GBFrameBlendingMode"]; diff --git a/Cocoa/GBPreferencesWindow.h b/Cocoa/GBPreferencesWindow.h @@ -17,7 +17,7 @@ @property (strong) IBOutlet NSMenuItem *bootROMsFolderItem; @property (strong) IBOutlet NSPopUpButtonCell *bootROMsButton; @property (strong) IBOutlet NSPopUpButton *rumbleModePopupButton; - +@property (weak) IBOutlet NSSlider *temperatureSlider; @property (weak) IBOutlet NSPopUpButton *dmgPopupButton; @property (weak) IBOutlet NSPopUpButton *sgbPopupButton; @property (weak) IBOutlet NSPopUpButton *cgbPopupButton; diff --git a/Cocoa/GBPreferencesWindow.m b/Cocoa/GBPreferencesWindow.m @@ -26,6 +26,7 @@ NSPopUpButton *_dmgPopupButton, *_sgbPopupButton, *_cgbPopupButton; NSPopUpButton *_preferredJoypadButton; NSPopUpButton *_rumbleModePopupButton; + NSSlider *_temperatureSlider; } + (NSArray *)filterList @@ -91,11 +92,23 @@ [_colorCorrectionPopupButton selectItemAtIndex:mode]; } + - (NSPopUpButton *)colorCorrectionPopupButton { return _colorCorrectionPopupButton; } +- (void)setTemperatureSlider:(NSSlider *)temperatureSlider +{ + _temperatureSlider = temperatureSlider; + [temperatureSlider setDoubleValue:[[NSUserDefaults standardUserDefaults] doubleForKey:@"GBLightTemperature"] * 256]; + temperatureSlider.continuous = YES; +} + +- (NSSlider *)temperatureSlider +{ + return _temperatureSlider; +} - (void)setFrameBlendingModePopupButton:(NSPopUpButton *)frameBlendingModePopupButton { _frameBlendingModePopupButton = frameBlendingModePopupButton; @@ -284,6 +297,13 @@ [[NSNotificationCenter defaultCenter] postNotificationName:@"GBColorCorrectionChanged" object:nil]; } +- (IBAction)lightTemperatureChanged:(id)sender +{ + [[NSUserDefaults standardUserDefaults] setObject:@([sender doubleValue] / 256.0) + forKey:@"GBLightTemperature"]; + [[NSNotificationCenter defaultCenter] postNotificationName:@"GBLightTemperatureChanged" object:nil]; +} + - (IBAction)franeBlendingModeChanged:(id)sender { [[NSUserDefaults standardUserDefaults] setObject:@([sender indexOfSelectedItem]) diff --git a/Cocoa/Preferences.xib b/Cocoa/Preferences.xib @@ -79,15 +79,16 @@ <outlet property="rumbleModePopupButton" destination="Ogs-xG-b4b" id="vuw-VN-MTp"/> <outlet property="sgbPopupButton" destination="dza-T7-RkX" id="B0o-Nb-pIH"/> <outlet property="skipButton" destination="d2I-jU-sLb" id="udX-8K-0sK"/> + <outlet property="temperatureSlider" destination="G3D-2f-Zcr" id="Etd-U2-wv0"/> </connections> <point key="canvasLocation" x="183" y="354"/> </window> <customView id="sRK-wO-K6R"> - <rect key="frame" x="0.0" y="0.0" width="292" height="323"/> + <rect key="frame" x="0.0" y="0.0" width="292" height="378"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <subviews> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="T91-rh-rRp"> - <rect key="frame" x="18" y="286" width="256" height="17"/> + <rect key="frame" x="18" y="341" width="256" height="17"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Graphics filter:" id="pXg-WY-8Q5"> <font key="font" metaFont="system"/> diff --git a/Core/display.c b/Core/display.c @@ -2,6 +2,7 @@ #include <stdlib.h> #include <assert.h> #include <string.h> +#include <math.h> #include "gb.h" /* FIFO functions */ @@ -208,6 +209,26 @@ static void display_vblank(GB_gameboy_t *gb) GB_timing_sync(gb); } +static inline void temperature_tint(double temperature, double *r, double *g, double *b) +{ + if (temperature >= 0) { + *r = 1; + *g = pow(1 - temperature, 0.375); + if (temperature >= 0.75) { + *b = 0; + } + else { + *b = sqrt(0.75 - temperature); + } + } + else { + *b = 1; + double squared = pow(temperature, 2); + *g = 0.125 * squared + 0.3 * temperature + 1.0; + *r = 0.21875 * squared + 0.5 * temperature + 1.0; + } +} + static inline uint8_t scale_channel(uint8_t x) { return (x << 3) | (x >> 2); @@ -240,13 +261,12 @@ uint32_t GB_convert_rgb15(GB_gameboy_t *gb, uint16_t color, bool for_border) g = scale_channel(g); b = scale_channel(b); } + else if (GB_is_sgb(gb) || for_border) { + r = scale_channel_with_curve_sgb(r); + g = scale_channel_with_curve_sgb(g); + b = scale_channel_with_curve_sgb(b); + } else { - if (GB_is_sgb(gb) || for_border) { - return gb->rgb_encode_callback(gb, - scale_channel_with_curve_sgb(r), - scale_channel_with_curve_sgb(g), - scale_channel_with_curve_sgb(b)); - } bool agb = gb->model == GB_MODEL_AGB; r = agb? scale_channel_with_curve_agb(r) : scale_channel_with_curve(r); g = agb? scale_channel_with_curve_agb(g) : scale_channel_with_curve(g); @@ -301,6 +321,14 @@ uint32_t GB_convert_rgb15(GB_gameboy_t *gb, uint16_t color, bool for_border) } } + if (gb->light_temperature) { + double light_r, light_g, light_b; + temperature_tint(gb->light_temperature, &light_r, &light_g, &light_b); + r = round(light_r * r); + g = round(light_g * g); + b = round(light_b * b); + } + return gb->rgb_encode_callback(gb, r, g, b); } @@ -324,6 +352,17 @@ void GB_set_color_correction_mode(GB_gameboy_t *gb, GB_color_correction_mode_t m } } +void GB_set_light_temperature(GB_gameboy_t *gb, double temperature) +{ + gb->light_temperature = temperature; + if (GB_is_cgb(gb)) { + for (unsigned i = 0; i < 32; i++) { + GB_palette_changed(gb, false, i * 2); + GB_palette_changed(gb, true, i * 2); + } + } +} + /* STAT interrupt is implemented based on this finding: http://board.byuu.org/phpbb3/viewtopic.php?p=25527#p25531 diff --git a/Core/display.h b/Core/display.h @@ -58,5 +58,6 @@ void GB_draw_tilemap(GB_gameboy_t *gb, uint32_t *dest, GB_palette_type_t palette uint8_t GB_get_oam_info(GB_gameboy_t *gb, GB_oam_info_t *dest, uint8_t *sprite_height); uint32_t GB_convert_rgb15(GB_gameboy_t *gb, uint16_t color, bool for_border); void GB_set_color_correction_mode(GB_gameboy_t *gb, GB_color_correction_mode_t mode); +void GB_set_light_temperature(GB_gameboy_t *gb, double temperature); bool GB_is_odd_frame(GB_gameboy_t *gb); #endif /* display_h */ diff --git a/Core/gb.h b/Core/gb.h @@ -573,6 +573,7 @@ struct GB_gameboy_internal_s { uint32_t sprite_palettes_rgb[0x20]; const GB_palette_t *dmg_palette; GB_color_correction_mode_t color_correction_mode; + double light_temperature; bool keys[4][GB_KEY_MAX]; GB_border_mode_t border_mode; GB_sgb_border_t borrowed_border; diff --git a/SDL/gui.c b/SDL/gui.c @@ -110,6 +110,7 @@ configuration_t configuration = .volume = 100, .rumble_mode = GB_RUMBLE_ALL_GAMES, .default_scale = 2, + .color_temperature = 10, }; @@ -453,6 +454,33 @@ const char *current_color_correction_mode(unsigned index) [configuration.color_correction_mode]; } +const char *current_color_temperature(unsigned index) +{ + return (const char *[]){"12000K", + "11450K", + "10900K", + "10350K", + "9800K", + "9250K", + "8700K", + "8150K", + "7600K", + "7050K", + "6500K (White)", + "5950K", + "5400K", + "4850K", + "4300K", + "3750K", + "3200K", + "2650K", + "2100K", + "1550K", + "1000K"} + [configuration.color_temperature]; +} + + const char *current_palette(unsigned index) { return (const char *[]){"Greyscale", "Lime (Game Boy)", "Olive (Pocket)", "Teal (Light)"} @@ -533,6 +561,20 @@ static void cycle_color_correction_backwards(unsigned index) } } +static void decrease_color_temperature(unsigned index) +{ + if (configuration.color_temperature < 20) { + configuration.color_temperature++; + } +} + +static void increase_color_temperature(unsigned index) +{ + if (configuration.color_temperature > 0) { + configuration.color_temperature--; + } +} + static void cycle_palette(unsigned index) { if (configuration.dmg_palette == 3) { @@ -684,6 +726,7 @@ static const struct menu_item graphics_menu[] = { {"Default Window Scale:", cycle_default_scale, current_default_scale, cycle_default_scale_backwards}, {"Scaling Filter:", cycle_filter, current_filter_name, cycle_filter_backwards}, {"Color Correction:", cycle_color_correction, current_color_correction_mode, cycle_color_correction_backwards}, + {"Ambient Light:", decrease_color_temperature, current_color_temperature, increase_color_temperature}, {"Frame Blending:", cycle_blending_mode, blending_mode_string, cycle_blending_mode_backwards}, {"Mono Palette:", cycle_palette, current_palette, cycle_palette_backwards}, {"Display Border:", cycle_border_mode, current_border_mode, cycle_border_mode_backwards}, diff --git a/SDL/gui.h b/SDL/gui.h @@ -110,6 +110,10 @@ typedef struct { GB_rumble_mode_t rumble_mode; uint8_t default_scale; + + /* v0.14 */ + unsigned padding; + uint8_t color_temperature; } configuration_t; extern configuration_t configuration; diff --git a/SDL/main.c b/SDL/main.c @@ -120,6 +120,7 @@ static void open_menu(void) GB_audio_set_paused(false); } GB_set_color_correction_mode(&gb, configuration.color_correction_mode); + GB_set_light_temperature(&gb, (configuration.color_temperature - 10.0) / 10.0); GB_set_border_mode(&gb, configuration.border_mode); update_palette(); GB_set_highpass_filter_mode(&gb, configuration.highpass_mode); @@ -496,6 +497,7 @@ restart: GB_set_rumble_mode(&gb, configuration.rumble_mode); GB_set_sample_rate(&gb, GB_audio_get_frequency()); GB_set_color_correction_mode(&gb, configuration.color_correction_mode); + GB_set_light_temperature(&gb, (configuration.color_temperature - 10.0) / 10.0); update_palette(); if ((unsigned)configuration.border_mode <= GB_BORDER_ALWAYS) { GB_set_border_mode(&gb, configuration.border_mode); @@ -646,6 +648,7 @@ int main(int argc, char **argv) configuration.dmg_palette %= 3; configuration.border_mode %= GB_BORDER_ALWAYS + 1; configuration.rumble_mode %= GB_RUMBLE_ALL_GAMES + 1; + configuration.color_temperature %= 21; } if (configuration.model >= MODEL_MAX) {

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.