From de43ac4cfbed113310531f468b6806f110c90505 Mon Sep 17 00:00:00 2001 From: Maximilian Mader Date: Wed, 23 May 2018 17:05:19 +0200 Subject: [PATCH] Add simple DMG shader --- Cocoa/GBPreferencesWindow.m | 31 +++++++------- SDL/gui.c | 85 +++++++++++++++++++------------------ Shaders/DMG.fsh | 38 +++++++++++++++++ 3 files changed, 97 insertions(+), 57 deletions(-) create mode 100644 Shaders/DMG.fsh diff --git a/Cocoa/GBPreferencesWindow.m b/Cocoa/GBPreferencesWindow.m index 66d8e4c..17b7184 100644 --- a/Cocoa/GBPreferencesWindow.m +++ b/Cocoa/GBPreferencesWindow.m @@ -29,6 +29,7 @@ @"Bilinear", @"SmoothBilinear", @"LCD", + @"DMG", @"Scale2x", @"Scale4x", @"AAScale2x", @@ -155,7 +156,7 @@ else { [self keyUp:event]; } - + previousModifiers = event.modifierFlags; } @@ -237,21 +238,21 @@ else if (![joystick_being_configured isEqualToString:joystick_name]) { return; } - + NSMutableDictionary *all_mappings = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"GBJoypadMappings"] mutableCopy]; - + if (!all_mappings) { all_mappings = [[NSMutableDictionary alloc] init]; } - + NSMutableDictionary *mapping = [[all_mappings objectForKey:joystick_name] mutableCopy]; - + if (!mapping) { mapping = [[NSMutableDictionary alloc] init]; } - + mapping[GBButtonNames[joystick_configuration_state]] = @(button); - + all_mappings[joystick_name] = mapping; [[NSUserDefaults standardUserDefaults] setObject:all_mappings forKey:@"GBJoypadMappings"]; [self advanceConfigurationStateMachine]; @@ -267,31 +268,31 @@ else if (![joystick_being_configured isEqualToString:joystick_name]) { return; } - + if (last_axis == -1) { last_axis = axis; return; } - + if (axis == last_axis) { return; } - + NSMutableDictionary *all_mappings = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"GBJoypadMappings"] mutableCopy]; - + if (!all_mappings) { all_mappings = [[NSMutableDictionary alloc] init]; } - + NSMutableDictionary *mapping = [[all_mappings objectForKey:joystick_name] mutableCopy]; - + if (!mapping) { mapping = [[NSMutableDictionary alloc] init]; } - + mapping[@"XAxis"] = @(MIN(axis, last_axis)); mapping[@"YAxis"] = @(MAX(axis, last_axis)); - + all_mappings[joystick_name] = mapping; [[NSUserDefaults standardUserDefaults] setObject:all_mappings forKey:@"GBJoypadMappings"]; [self advanceConfigurationStateMachine]; diff --git a/SDL/gui.c b/SDL/gui.c index 3e0151b..28efc4b 100644 --- a/SDL/gui.c +++ b/SDL/gui.c @@ -95,12 +95,12 @@ void update_viewport(void) SDL_GL_GetDrawableSize(window, &win_width, &win_height); double x_factor = win_width / 160.0; double y_factor = win_height / 144.0; - + if (configuration.scaling_mode == GB_SDL_SCALING_INTEGER_FACTOR) { x_factor = (int)(x_factor); y_factor = (int)(y_factor); } - + if (configuration.scaling_mode != GB_SDL_SCALING_ENTIRE_WINDOW) { if (x_factor > y_factor) { x_factor = y_factor; @@ -109,13 +109,13 @@ void update_viewport(void) y_factor = x_factor; } } - + unsigned new_width = x_factor * 160; unsigned new_height = y_factor * 144; - + rect = (SDL_Rect){(win_width - new_width) / 2, (win_height - new_height) /2, new_width, new_height}; - + if (renderer) { SDL_RenderSetViewport(renderer, &rect); } @@ -130,9 +130,9 @@ static void draw_char(uint32_t *buffer, unsigned char ch, uint32_t color) if (ch < ' ' || ch > font_max) { ch = '?'; } - + uint8_t *data = &font[(ch - ' ') * GLYPH_WIDTH * GLYPH_HEIGHT]; - + for (unsigned y = GLYPH_HEIGHT; y--;) { for (unsigned x = GLYPH_WIDTH; x--;) { if (*(data++)) { @@ -154,11 +154,11 @@ static void draw_unbordered_text(uint32_t *buffer, unsigned x, unsigned y, const string++; continue; } - + if (x > 160 - GLYPH_WIDTH || y == 0 || y > 144 - GLYPH_HEIGHT) { break; } - + draw_char(&buffer[x + 160 * y], *string, color); x += GLYPH_WIDTH; string++; @@ -192,7 +192,7 @@ static void draw_text_centered(uint32_t *buffer, unsigned y, const char *string, draw_text(buffer, x - GLYPH_WIDTH, y, LEFT_ARROW_STRING, color, border); draw_text(buffer, 160 - x, y, RIGHT_ARROW_STRING, color, border); break; - + case DECORATION_NONE: break; } @@ -259,7 +259,7 @@ static void return_to_root_menu(unsigned index) static void cycle_model(unsigned index) { - + configuration.model++; if (configuration.model == MODEL_MAX) { configuration.model = 0; @@ -357,6 +357,7 @@ struct shader_name { {"Bilinear", "Bilinear"}, {"SmoothBilinear", "Smooth Bilinear"}, {"LCD", "LCD Display"}, + {"DMG", "DMG Display"}, {"Scale2x", "Scale2x"}, {"Scale4x", "Scale4x"}, {"AAScale2x", "Anti-aliased Scale2x"}, @@ -375,13 +376,13 @@ static void cycle_filter(unsigned index) break; } } - + i += 1; if (i >= sizeof(shaders) / sizeof(shaders[0])) { i -= sizeof(shaders) / sizeof(shaders[0]); } - + strcpy(configuration.filter, shaders[i].file_name); free_shader(&shader); if (!init_shader_with_name(&shader, configuration.filter)) { @@ -397,12 +398,12 @@ static void cycle_filter_backwards(unsigned index) break; } } - + i -= 1; if (i >= sizeof(shaders) / sizeof(shaders[0])) { i = sizeof(shaders) / sizeof(shaders[0]) - 1; } - + strcpy(configuration.filter, shaders[i].file_name); free_shader(&shader); if (!init_shader_with_name(&shader, configuration.filter)) { @@ -418,11 +419,11 @@ const char *current_filter_name(unsigned index) break; } } - + if (i == sizeof(shaders) / sizeof(shaders[0])) { i = 0; } - + return shaders[i].display_name; } @@ -525,7 +526,7 @@ const char *current_joypad_name(unsigned index) const char *orig_name = joystick? SDL_JoystickName(joystick) : NULL; if (!orig_name) return "Not Found"; unsigned i = 0; - + // SDL returns a name with repeated and trailing spaces while (*orig_name && i < sizeof(name) - 2) { if (orig_name[0] != ' ' || orig_name[1] != ' ') { @@ -537,7 +538,7 @@ const char *current_joypad_name(unsigned index) i--; } name[i] = 0; - + return name; } @@ -598,12 +599,12 @@ unsigned fix_joypad_axis(unsigned axis) } return -1; } - - + + if (configuration.div_joystick) { axis >>= 1; } - + return axis & 1; } @@ -619,7 +620,7 @@ unsigned fix_joypad_button(unsigned button) if (i == 9) { return SDL_CONTROLLER_BUTTON_START; } - + if (i == SDL_CONTROLLER_BUTTON_BACK) { return 8; } @@ -631,22 +632,22 @@ unsigned fix_joypad_button(unsigned button) } return -1; } - - + + if (configuration.div_joystick) { button >>= 1; } - + if (button < 4) { if (configuration.swap_joysticks_bits_1_and_2) { button = (int[]){0, 2, 1, 3}[button]; } - + if (configuration.flip_joystick_bit_1) { button ^= 1; } } - + return button; } @@ -699,7 +700,7 @@ void run_gui(bool is_running) converted_background = SDL_ConvertSurface(background, pixel_format, 0); SDL_LockSurface(converted_background); SDL_FreeSurface(background); - + for (unsigned i = 4; i--; ) { gui_palette_native[i] = SDL_MapRGB(pixel_format, gui_palette[i].r, gui_palette[i].g, gui_palette[i].b); } @@ -745,8 +746,8 @@ void run_gui(bool is_running) event.key.keysym.scancode = scancode; } } - } - + } + case SDL_JOYAXISMOTION: { static bool axis_active[2] = {false, false}; event.jaxis.axis = fix_joypad_axis(event.jaxis.axis); @@ -800,7 +801,7 @@ void run_gui(bool is_running) pending_command = GB_SDL_QUIT_COMMAND; return; } - + } case SDL_WINDOWEVENT: { if (event.window.event == SDL_WINDOWEVENT_RESIZED) { @@ -821,25 +822,25 @@ void run_gui(bool is_running) auto_detect_inputs[auto_detect_progress++] = event.jbutton.button; if (auto_detect_progress == 3) { gui_state = SHOWING_MENU; - + configuration.div_joystick = ((auto_detect_inputs[0] | auto_detect_inputs[1] | auto_detect_inputs[2]) & 1) == 0 && auto_detect_inputs[0] > 9; - + if (configuration.div_joystick) { auto_detect_inputs[0] >>= 1; auto_detect_inputs[1] >>= 1; auto_detect_inputs[2] >>= 1; } - + configuration.swap_joysticks_bits_1_and_2 = (auto_detect_inputs[1] & 1) == (auto_detect_inputs[2] & 1); - + if (configuration.swap_joysticks_bits_1_and_2) { auto_detect_inputs[1] = (int[]){0, 2, 1, 3}[auto_detect_inputs[1]]; auto_detect_inputs[2] = (int[]){0, 2, 1, 3}[auto_detect_inputs[2]]; } - + configuration.flip_joystick_bit_1 = auto_detect_inputs[2] & 1; } } @@ -861,7 +862,7 @@ void run_gui(bool is_running) should_render = true; } } - + if (gui_state == SHOWING_MENU) { if (event.key.keysym.scancode == SDL_SCANCODE_DOWN && current_menu[current_selection + 1].string) { current_selection++; @@ -912,11 +913,11 @@ void run_gui(bool is_running) } break; } - + if (should_render) { should_render = false; memcpy(pixels, converted_background->pixels, sizeof(pixels)); - + switch (gui_state) { case SHOWING_DROP_MESSAGE: draw_text_centered(pixels, 8, "Press ESC for menu", gui_palette_native[3], gui_palette_native[0], false); @@ -933,7 +934,7 @@ void run_gui(bool is_running) draw_text_centered(pixels, y, line, gui_palette_native[3], gui_palette_native[0], i == current_selection ? DECORATION_SELECTION : DECORATION_NONE); y += 12; - + } else { draw_text_centered(pixels, y, item->string, gui_palette_native[3], gui_palette_native[0], @@ -963,7 +964,7 @@ void run_gui(bool is_running) gui_palette_native[3], gui_palette_native[0], DECORATION_NONE); break; } - + render_texture(pixels, NULL); } } while (SDL_WaitEvent(&event)); diff --git a/Shaders/DMG.fsh b/Shaders/DMG.fsh new file mode 100644 index 0000000..a462436 --- /dev/null +++ b/Shaders/DMG.fsh @@ -0,0 +1,38 @@ +vec4 pixelize(vec4 image, vec2 scaleVec, vec2 texCoord) { + float scale = max(scaleVec.x, scaleVec.y); + float x = fract(texCoord.x * 160.0) * scale; + float y = fract(texCoord.y * 144.0) * scale; + + float border = 1.0; + + if (scale > 5.0) { + border = 2.0; + } + + if (x < border || x > scale - border || y < border || y > scale - border) { + return vec4(.95, .95, .95, 1); + } + + return image; +} + +vec4 scale(sampler2D image) { + vec2 displayScale = uResolution / vec2(160.0, 144.0); + vec2 texCoord = vec2(gl_FragCoord.x, uResolution.y - gl_FragCoord.y) / uResolution; + vec4 sampled = texture(image, texCoord); + + if (displayScale.x < 3.0 || displayScale.y < 3.0) { + return sampled; + } + + float mixValue = 1.0; + + if (displayScale.x >= 5.0 && displayScale.y >= 5.0) { + mixValue = 0.5; + } + else if (displayScale.x >= 3.0 && displayScale.y >= 3.0) { + mixValue = 0.8; + } + + return mix(pixelize(sampled, displayScale, texCoord), sampled, mixValue); +}