From ac418b9de18765cdd8c0e94d7df46d5ca0820f0f Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Mon, 30 Sep 2019 00:09:25 +0300 Subject: [PATCH 01/30] Pass channel_1_freq_change_timing --- Core/apu.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Core/apu.c b/Core/apu.c index ee58138..a6247ec 100644 --- a/Core/apu.c +++ b/Core/apu.c @@ -681,6 +681,21 @@ void GB_apu_write(GB_gameboy_t *gb, uint8_t reg, uint8_t value) case GB_IO_NR14: case GB_IO_NR24: { unsigned index = reg == GB_IO_NR24? GB_SQUARE_2: GB_SQUARE_1; + + /* TODO: When the sample length changes right before being updated, the countdown should change to the + old length, but the current sample should not change. Because our write timing isn't accurate to + the T-cycle, we hack around it by stepping the sample index backwards. */ + if ((value & 0x80) == 0 && gb->apu.is_active[index]) { + /* On an AGB, as well as on CGB C and earlier (TODO: Tested: 0, B and C), it behaves slightly different on + double speed. */ + if (gb->model == GB_MODEL_CGB_E /* || gb->model == GB_MODEL_CGB_D */ || gb->apu.square_channels[index].sample_countdown & 1) { + if (gb->apu.square_channels[index].sample_countdown >> 1 == (gb->apu.square_channels[index].sample_length ^ 0x7FF)) { + gb->apu.square_channels[index].current_sample_index--; + gb->apu.square_channels[index].current_sample_index &= 7; + } + } + } + gb->apu.square_channels[index].sample_length &= 0xFF; gb->apu.square_channels[index].sample_length |= (value & 7) << 8; if (index == GB_SQUARE_1) { From ca370eee7e05224edfcc385b3c755b671645e732 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Tue, 1 Oct 2019 18:50:59 +0300 Subject: [PATCH 02/30] A bit more accurate AGB audio rendering --- Core/apu.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/Core/apu.c b/Core/apu.c index a6247ec..55898b2 100644 --- a/Core/apu.c +++ b/Core/apu.c @@ -48,6 +48,23 @@ bool GB_apu_is_DAC_enabled(GB_gameboy_t *gb, unsigned index) return false; } +static uint8_t agb_bias_for_channel(GB_gameboy_t *gb, unsigned index) +{ + if (!gb->apu.is_active[index]) return 0; + + switch (index) { + case GB_SQUARE_1: + return gb->apu.square_channels[GB_SQUARE_1].current_volume; + case GB_SQUARE_2: + return gb->apu.square_channels[GB_SQUARE_2].current_volume; + case GB_WAVE: + return 0; + case GB_NOISE: + return gb->apu.noise_channel.current_volume; + } + return 0; +} + static void update_sample(GB_gameboy_t *gb, unsigned index, int8_t value, unsigned cycles_offset) { if (gb->model >= GB_MODEL_AGB) { @@ -66,15 +83,17 @@ static void update_sample(GB_gameboy_t *gb, unsigned index, int8_t value, unsign } GB_sample_t output; + uint8_t bias = agb_bias_for_channel(gb, index); + if (gb->io_registers[GB_IO_NR51] & (1 << index)) { - output.right = (0xf - value * 2) * right_volume; + output.right = (0xf - value * 2 + bias) * right_volume; } else { output.right = 0xf * right_volume; } if (gb->io_registers[GB_IO_NR51] & (0x10 << index)) { - output.left = (0xf - value * 2) * left_volume; + output.left = (0xf - value * 2 + bias) * left_volume; } else { output.left = 0xf * left_volume; From c50ea6a63fb76f4111e305048788071dd0541730 Mon Sep 17 00:00:00 2001 From: f21red <54341442+f21red@users.noreply.github.com> Date: Sat, 5 Oct 2019 20:24:32 -0500 Subject: [PATCH 03/30] libretro: sgb color correction --- libretro/libretro.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libretro/libretro.c b/libretro/libretro.c index e075b2c..8c00ac5 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -486,7 +486,7 @@ static void check_variables() { var.key = "sameboy_color_correction_mode"; var.value = NULL; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && GB_is_cgb(&gameboy[0])) + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (strcmp(var.value, "off") == 0) GB_set_color_correction_mode(&gameboy[0], GB_COLOR_CORRECTION_DISABLED); @@ -540,7 +540,7 @@ static void check_variables() { var.key = "sameboy_color_correction_mode_1"; var.value = NULL; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && GB_is_cgb(&gameboy[0])) + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (strcmp(var.value, "off") == 0) GB_set_color_correction_mode(&gameboy[0], GB_COLOR_CORRECTION_DISABLED); @@ -554,7 +554,7 @@ static void check_variables() var.key = "sameboy_color_correction_mode_2"; var.value = NULL; - if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value && GB_is_cgb(&gameboy[1])) + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) { if (strcmp(var.value, "off") == 0) GB_set_color_correction_mode(&gameboy[1], GB_COLOR_CORRECTION_DISABLED); From 0a7a0ca5fe28e34e479411d00c0ce3bc79c69334 Mon Sep 17 00:00:00 2001 From: f21red <54341442+f21red@users.noreply.github.com> Date: Sat, 5 Oct 2019 20:51:59 -0500 Subject: [PATCH 04/30] libretro: sgb border option --- libretro/libretro.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/libretro/libretro.c b/libretro/libretro.c index 8c00ac5..54c7906 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -92,6 +92,7 @@ static unsigned emulated_devices = 1; static bool initialized = false; static unsigned screen_layout = 0; static unsigned audio_out = 0; +static unsigned sgb_border = 1; static bool geometry_updated = false; static bool link_cable_emulation = false; @@ -204,6 +205,7 @@ static const struct retro_variable vars_single[] = { { "sameboy_color_correction_mode", "Color correction; off|correct curves|emulate hardware|preserve brightness" }, { "sameboy_high_pass_filter_mode", "High-pass filter; off|accurate|remove dc offset" }, { "sameboy_model", "Emulated model; Auto|Game Boy|Game Boy Color|Game Boy Advance|Super Game Boy|Super Game Boy 2" }, + { "sameboy_border", "Super Game Boy border; enabled|disabled" }, { NULL } }; @@ -535,6 +537,16 @@ static void check_variables() init_for_current_model(0); } } + + var.key = "sameboy_border"; + var.value = NULL; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) + { + if (strcmp(var.value, "enabled") == 0) + sgb_border = 1; + else if (strcmp(var.value, "disabled") == 0) + sgb_border = 0; + } } else { @@ -880,8 +892,15 @@ void retro_run(void) } else { - if (model[0] == MODEL_SGB || model[0] == MODEL_SGB2) - video_cb(frame_buf, SGB_VIDEO_WIDTH, SGB_VIDEO_HEIGHT, SGB_VIDEO_WIDTH * sizeof(uint32_t)); + if (model[0] == MODEL_SGB || model[0] == MODEL_SGB2) { + if (sgb_border == 1) + video_cb(frame_buf, SGB_VIDEO_WIDTH, SGB_VIDEO_HEIGHT, SGB_VIDEO_WIDTH * sizeof(uint32_t)); + else { + int crop = SGB_VIDEO_WIDTH * ((SGB_VIDEO_HEIGHT - VIDEO_HEIGHT) / 2) + ((SGB_VIDEO_WIDTH - VIDEO_WIDTH) / 2); + + video_cb(frame_buf + crop, VIDEO_WIDTH, VIDEO_HEIGHT, SGB_VIDEO_WIDTH * sizeof(uint32_t)); + } + } else video_cb(frame_buf, VIDEO_WIDTH, VIDEO_HEIGHT, VIDEO_WIDTH * sizeof(uint32_t)); } From dee29c118cbded7703c2f7edcbc7230ffb70b844 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Tue, 8 Oct 2019 15:10:24 +0300 Subject: [PATCH 05/30] Added GB_set_sample_rate_by_clocks API, split SGB_NO_SFC into PAL and NTSC; now they report the correct clock rate. --- Core/apu.c | 15 +++++++++++++++ Core/apu.h | 3 +++ Core/gb.c | 20 ++++++++++++-------- Core/gb.h | 4 +++- Core/memory.c | 6 ++++-- 5 files changed, 37 insertions(+), 11 deletions(-) diff --git a/Core/apu.c b/Core/apu.c index 55898b2..3be92d6 100644 --- a/Core/apu.c +++ b/Core/apu.c @@ -1004,9 +1004,23 @@ void GB_set_sample_rate(GB_gameboy_t *gb, unsigned sample_rate) if (sample_rate) { gb->apu_output.highpass_rate = pow(0.999958, GB_get_clock_rate(gb) / (double)sample_rate); } + gb->apu_output.rate_set_in_clocks = false; GB_apu_update_cycles_per_sample(gb); } +void GB_set_sample_rate_by_clocks(GB_gameboy_t *gb, unsigned cycles_per_sample) +{ + + if (cycles_per_sample == 0) { + GB_set_sample_rate(gb, 0); + return; + } + gb->apu_output.cycles_per_sample = cycles_per_sample; + gb->apu_output.sample_rate = GB_get_clock_rate(gb) / cycles_per_sample * 2; + gb->apu_output.highpass_rate = pow(0.999958, cycles_per_sample); + gb->apu_output.rate_set_in_clocks = true; +} + void GB_apu_set_sample_callback(GB_gameboy_t *gb, GB_sample_callback_t callback) { gb->apu_output.sample_callback = callback; @@ -1019,6 +1033,7 @@ void GB_set_highpass_filter_mode(GB_gameboy_t *gb, GB_highpass_mode_t mode) void GB_apu_update_cycles_per_sample(GB_gameboy_t *gb) { + if (gb->apu_output.rate_set_in_clocks) return; if (gb->apu_output.sample_rate) { gb->apu_output.cycles_per_sample = 2 * GB_get_clock_rate(gb) / (double)gb->apu_output.sample_rate; /* 2 * because we use 8MHz units */ } diff --git a/Core/apu.h b/Core/apu.h index 7f8acfc..ee6055b 100644 --- a/Core/apu.h +++ b/Core/apu.h @@ -143,9 +143,12 @@ typedef struct { GB_double_sample_t highpass_diff; GB_sample_callback_t sample_callback; + + bool rate_set_in_clocks; } GB_apu_output_t; void GB_set_sample_rate(GB_gameboy_t *gb, unsigned sample_rate); +void GB_set_sample_rate_by_clocks(GB_gameboy_t *gb, unsigned cycles_per_sample); /* Cycles are in 8MHz units */ void GB_set_highpass_filter_mode(GB_gameboy_t *gb, GB_highpass_mode_t mode); void GB_apu_set_sample_callback(GB_gameboy_t *gb, GB_sample_callback_t callback); #ifdef GB_INTERNAL diff --git a/Core/gb.c b/Core/gb.c index 6604e4f..93ac9d7 100644 --- a/Core/gb.c +++ b/Core/gb.c @@ -712,7 +712,8 @@ static void reset_ram(GB_gameboy_t *gb) case GB_MODEL_DMG_B: case GB_MODEL_SGB_NTSC: /* Unverified*/ case GB_MODEL_SGB_PAL: /* Unverified */ - case GB_MODEL_SGB_NO_SFC: + case GB_MODEL_SGB_NTSC_NO_SFC: /* Unverified */ + case GB_MODEL_SGB_PAL_NO_SFC: /* Unverified */ for (unsigned i = 0; i < gb->ram_size; i++) { gb->ram[i] = GB_random(); if (i & 0x100) { @@ -758,7 +759,8 @@ static void reset_ram(GB_gameboy_t *gb) case GB_MODEL_DMG_B: case GB_MODEL_SGB_NTSC: /* Unverified*/ case GB_MODEL_SGB_PAL: /* Unverified */ - case GB_MODEL_SGB_NO_SFC: + case GB_MODEL_SGB_NTSC_NO_SFC: /* Unverified */ + case GB_MODEL_SGB_PAL_NO_SFC: /* Unverified */ case GB_MODEL_SGB2: case GB_MODEL_SGB2_NO_SFC: for (unsigned i = 0; i < sizeof(gb->hram); i++) { @@ -783,7 +785,8 @@ static void reset_ram(GB_gameboy_t *gb) case GB_MODEL_DMG_B: case GB_MODEL_SGB_NTSC: /* Unverified */ case GB_MODEL_SGB_PAL: /* Unverified */ - case GB_MODEL_SGB_NO_SFC: /* Unverified */ + case GB_MODEL_SGB_NTSC_NO_SFC: /* Unverified */ + case GB_MODEL_SGB_PAL_NO_SFC: /* Unverified */ case GB_MODEL_SGB2: case GB_MODEL_SGB2_NO_SFC: for (unsigned i = 0; i < 8; i++) { @@ -811,7 +814,8 @@ static void reset_ram(GB_gameboy_t *gb) case GB_MODEL_DMG_B: case GB_MODEL_SGB_NTSC: /* Unverified*/ case GB_MODEL_SGB_PAL: /* Unverified */ - case GB_MODEL_SGB_NO_SFC: /* Unverified */ + case GB_MODEL_SGB_NTSC_NO_SFC: /* Unverified */ + case GB_MODEL_SGB_PAL_NO_SFC: /* Unverified */ case GB_MODEL_SGB2: case GB_MODEL_SGB2_NO_SFC: { uint8_t temp; @@ -1017,12 +1021,12 @@ void GB_set_clock_multiplier(GB_gameboy_t *gb, double multiplier) uint32_t GB_get_clock_rate(GB_gameboy_t *gb) { - if (gb->model == GB_MODEL_SGB_NTSC) { - return SGB_NTSC_FREQUENCY * gb->clock_multiplier; - } - if (gb->model == GB_MODEL_SGB_PAL) { + if (gb->model & GB_MODEL_PAL_BIT) { return SGB_PAL_FREQUENCY * gb->clock_multiplier; } + if ((gb->model & ~GB_MODEL_NO_SFC_BIT) == GB_MODEL_SGB) { + return SGB_NTSC_FREQUENCY * gb->clock_multiplier; + } return CPU_FREQUENCY * gb->clock_multiplier; } diff --git a/Core/gb.h b/Core/gb.h index 59a11c2..dbd9e16 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -70,7 +70,9 @@ typedef enum { GB_MODEL_SGB = 0x004, GB_MODEL_SGB_NTSC = GB_MODEL_SGB, GB_MODEL_SGB_PAL = GB_MODEL_SGB | GB_MODEL_PAL_BIT, - GB_MODEL_SGB_NO_SFC = GB_MODEL_SGB | GB_MODEL_NO_SFC_BIT, + GB_MODEL_SGB_NTSC_NO_SFC = GB_MODEL_SGB | GB_MODEL_NO_SFC_BIT, + GB_MODEL_SGB_NO_SFC = GB_MODEL_SGB_NTSC_NO_SFC, + GB_MODEL_SGB_PAL_NO_SFC = GB_MODEL_SGB | GB_MODEL_NO_SFC_BIT | GB_MODEL_PAL_BIT, // GB_MODEL_MGB = 0x100, GB_MODEL_SGB2 = 0x101, GB_MODEL_SGB2_NO_SFC = GB_MODEL_SGB2 | GB_MODEL_NO_SFC_BIT, diff --git a/Core/memory.c b/Core/memory.c index 4c4a702..c481ad2 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -273,7 +273,8 @@ static uint8_t read_high_memory(GB_gameboy_t *gb, uint16_t addr) case GB_MODEL_DMG_B: case GB_MODEL_SGB_NTSC: case GB_MODEL_SGB_PAL: - case GB_MODEL_SGB_NO_SFC: + case GB_MODEL_SGB_NTSC_NO_SFC: + case GB_MODEL_SGB_PAL_NO_SFC: case GB_MODEL_SGB2: case GB_MODEL_SGB2_NO_SFC: ; @@ -591,7 +592,8 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) case GB_MODEL_DMG_B: case GB_MODEL_SGB_NTSC: case GB_MODEL_SGB_PAL: - case GB_MODEL_SGB_NO_SFC: + case GB_MODEL_SGB_NTSC_NO_SFC: + case GB_MODEL_SGB_PAL_NO_SFC: case GB_MODEL_SGB2: case GB_MODEL_SGB2_NO_SFC: case GB_MODEL_CGB_E: From 7d6cdf381974819d2c9b94a0d9344058bed90910 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Thu, 17 Oct 2019 21:21:10 +0300 Subject: [PATCH 06/30] =?UTF-8?q?Fix=20SGB=20support=20in=20SDL=E2=80=99s?= =?UTF-8?q?=20software=20rendering.=20Fixes=20#208?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SDL/gui.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDL/gui.c b/SDL/gui.c index 0723384..6cffeaf 100644 --- a/SDL/gui.c +++ b/SDL/gui.c @@ -33,7 +33,7 @@ void render_texture(void *pixels, void *previous) { if (renderer) { if (pixels) { - SDL_UpdateTexture(texture, NULL, pixels, 160 * sizeof (uint32_t)); + SDL_UpdateTexture(texture, NULL, pixels, GB_get_screen_width(&gb) * sizeof (uint32_t)); } SDL_RenderClear(renderer); SDL_RenderCopy(renderer, texture, NULL, NULL); From 70542137f2143e626aa2253f97d360b7e8bd46c5 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Tue, 29 Oct 2019 20:31:20 +0200 Subject: [PATCH 07/30] Fix #214 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 79b5e14..dfab248 100644 --- a/Makefile +++ b/Makefile @@ -95,7 +95,7 @@ ifeq ($(PLATFORM),Darwin) SYSROOT := $(shell xcodebuild -sdk macosx -version Path 2> /dev/null) CFLAGS += -F/Library/Frameworks OCFLAGS += -x objective-c -fobjc-arc -Wno-deprecated-declarations -isysroot $(SYSROOT) -mmacosx-version-min=10.9 -LDFLAGS += -framework AppKit -framework PreferencePanes -framework Carbon -framework QuartzCore -weak_framework Metal -weak_framework MetalKit +LDFLAGS += -framework AppKit -framework PreferencePanes -framework Carbon -framework QuartzCore -weak_framework Metal -weak_framework MetalKit -mmacosx-version-min=10.9 SDL_LDFLAGS := -F/Library/Frameworks -framework SDL2 -framework OpenGL endif CFLAGS += -Wno-deprecated-declarations From 719a92d8a468770a85777134130ad0de6e4cd5bf Mon Sep 17 00:00:00 2001 From: Matthew Coppola Date: Sat, 2 Nov 2019 23:31:23 -0400 Subject: [PATCH 08/30] SDL2: Fix fullscreen viewport bug --- SDL/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDL/main.c b/SDL/main.c index ba2a5fb..2993d36 100755 --- a/SDL/main.c +++ b/SDL/main.c @@ -123,7 +123,7 @@ static void handle_events(GB_gameboy_t *gb) } case SDL_WINDOWEVENT: { - if (event.window.event == SDL_WINDOWEVENT_RESIZED) { + if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) { update_viewport(); } break; From 139ae8cc08b2d882f1e1d21a7a0aafdc3f0e3824 Mon Sep 17 00:00:00 2001 From: Matthew Coppola Date: Sat, 2 Nov 2019 23:50:29 -0400 Subject: [PATCH 09/30] SDL2: Write battery to disk when ROMs are hot-swapped --- SDL/main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/SDL/main.c b/SDL/main.c index ba2a5fb..cc3fd20 100755 --- a/SDL/main.c +++ b/SDL/main.c @@ -406,14 +406,12 @@ static bool handle_pending_command(void) return false; } - case GB_SDL_RESET_COMMAND: - GB_save_battery(&gb, battery_save_path_ptr); - return true; - case GB_SDL_NO_COMMAND: return false; + case GB_SDL_RESET_COMMAND: case GB_SDL_NEW_FILE_COMMAND: + GB_save_battery(&gb, battery_save_path_ptr); return true; case GB_SDL_QUIT_COMMAND: From 2f4a10913b2df3de5279aec58a3bf758b58f3194 Mon Sep 17 00:00:00 2001 From: Matthew Coppola Date: Sat, 2 Nov 2019 23:43:25 -0400 Subject: [PATCH 10/30] SDL2: Hide mouse cursor when menu is not active --- SDL/gui.c | 1 + SDL/main.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/SDL/gui.c b/SDL/gui.c index 6cffeaf..b34bb1a 100644 --- a/SDL/gui.c +++ b/SDL/gui.c @@ -792,6 +792,7 @@ void connect_joypad(void) void run_gui(bool is_running) { + SDL_ShowCursor(SDL_ENABLE); connect_joypad(); /* Draw the background screen */ diff --git a/SDL/main.c b/SDL/main.c index ba2a5fb..d96ee1b 100755 --- a/SDL/main.c +++ b/SDL/main.c @@ -98,6 +98,7 @@ static void open_menu(void) SDL_PauseAudioDevice(device_id, 1); } run_gui(true); + SDL_ShowCursor(SDL_DISABLE); if (audio_playing) { SDL_ClearQueuedAudio(device_id); SDL_PauseAudioDevice(device_id, 0); @@ -425,6 +426,7 @@ static bool handle_pending_command(void) static void run(void) { + SDL_ShowCursor(SDL_DISABLE); GB_model_t model; pending_command = GB_SDL_NO_COMMAND; restart: From 143e1f88a8dc3fee4a40dbebd843cbb8cfbd5e84 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Sun, 3 Nov 2019 22:02:33 +0200 Subject: [PATCH 11/30] =?UTF-8?q?There=E2=80=99s=20not=20reason=20it=20mus?= =?UTF-8?q?t=20be=20an=20integer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Core/apu.c | 2 +- Core/apu.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/apu.c b/Core/apu.c index 3be92d6..9afa5c9 100644 --- a/Core/apu.c +++ b/Core/apu.c @@ -1008,7 +1008,7 @@ void GB_set_sample_rate(GB_gameboy_t *gb, unsigned sample_rate) GB_apu_update_cycles_per_sample(gb); } -void GB_set_sample_rate_by_clocks(GB_gameboy_t *gb, unsigned cycles_per_sample) +void GB_set_sample_rate_by_clocks(GB_gameboy_t *gb, double cycles_per_sample) { if (cycles_per_sample == 0) { diff --git a/Core/apu.h b/Core/apu.h index ee6055b..885e0ce 100644 --- a/Core/apu.h +++ b/Core/apu.h @@ -148,7 +148,7 @@ typedef struct { } GB_apu_output_t; void GB_set_sample_rate(GB_gameboy_t *gb, unsigned sample_rate); -void GB_set_sample_rate_by_clocks(GB_gameboy_t *gb, unsigned cycles_per_sample); /* Cycles are in 8MHz units */ +void GB_set_sample_rate_by_clocks(GB_gameboy_t *gb, double cycles_per_sample); /* Cycles are in 8MHz units */ void GB_set_highpass_filter_mode(GB_gameboy_t *gb, GB_highpass_mode_t mode); void GB_apu_set_sample_callback(GB_gameboy_t *gb, GB_sample_callback_t callback); #ifdef GB_INTERNAL From c8023618009cca1f7f0707e8a6d1188aad574ee5 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Fri, 8 Nov 2019 16:14:16 +0200 Subject: [PATCH 12/30] Whoops, this function was missing --- Core/memory.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Core/memory.c b/Core/memory.c index c481ad2..7e74a80 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -422,6 +422,11 @@ static GB_read_function_t * const read_map[] = read_ram, read_high_memory, /* EXXX FXXX */ }; +void GB_set_read_memory_callback(GB_gameboy_t *gb, GB_read_memory_callback_t callback) +{ + gb->read_memory_callback = callback; +} + uint8_t GB_read_memory(GB_gameboy_t *gb, uint16_t addr) { if (gb->n_watchpoints) { From 31609319deaab51cea6113d976681b83f628bfb2 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Sat, 9 Nov 2019 14:45:38 +0200 Subject: [PATCH 13/30] Fix the set_joyp API --- Core/memory.c | 6 +++++- Core/sgb.c | 6 +----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Core/memory.c b/Core/memory.c index 7e74a80..003bb77 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -753,7 +753,11 @@ static void write_high_memory(GB_gameboy_t *gb, uint16_t addr, uint8_t value) return; case GB_IO_JOYP: - if ((gb->io_registers[GB_IO_JOYP] & 0x30) != (value & 0x30)) { + if (gb->joyp_write_callback) { + gb->joyp_write_callback(gb, value); + GB_update_joyp(gb); + } + else if ((gb->io_registers[GB_IO_JOYP] & 0x30) != (value & 0x30)) { GB_sgb_write(gb, value); gb->io_registers[GB_IO_JOYP] = value & 0xF0; GB_update_joyp(gb); diff --git a/Core/sgb.c b/Core/sgb.c index 8539238..7ebeae0 100644 --- a/Core/sgb.c +++ b/Core/sgb.c @@ -385,11 +385,7 @@ static void command_ready(GB_gameboy_t *gb) } void GB_sgb_write(GB_gameboy_t *gb, uint8_t value) -{ - if (gb->joyp_write_callback) { - gb->joyp_write_callback(gb, value); - } - +{ if (!GB_is_sgb(gb)) return; if (!GB_is_hle_sgb(gb)) { /* Notify via callback */ From bd9ac204c2cb95427c49d655b35921fb2d2da67b Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Wed, 20 Nov 2019 22:40:03 +0200 Subject: [PATCH 14/30] Allow SameBoy to compile on 4-byte-bools platforms --- Core/gb.c | 11 +++++++++-- Core/gb.h | 4 ---- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Core/gb.c b/Core/gb.c index 93ac9d7..f29d400 100644 --- a/Core/gb.c +++ b/Core/gb.c @@ -18,6 +18,13 @@ #define GB_rewind_push(...) #endif + +static inline uint32_t state_magic(void) +{ + if (sizeof(bool) == 1) return 'SAME'; + return 'S4ME'; +} + void GB_attributed_logv(GB_gameboy_t *gb, GB_log_attributes attributes, const char *fmt, va_list args) { char *string = NULL; @@ -660,7 +667,7 @@ void GB_disconnect_serial(GB_gameboy_t *gb) bool GB_is_inited(GB_gameboy_t *gb) { - return gb->magic == 'SAME'; + return gb->magic == state_magic(); } bool GB_is_cgb(GB_gameboy_t *gb) @@ -929,7 +936,7 @@ void GB_reset(GB_gameboy_t *gb) gb->nontrivial_jump_state = NULL; } - gb->magic = (uintptr_t)'SAME'; + gb->magic = state_magic(); } void GB_switch_model_and_reset(GB_gameboy_t *gb, GB_model_t model) diff --git a/Core/gb.h b/Core/gb.h index dbd9e16..a561111 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -278,10 +278,6 @@ typedef struct { This struct is not packed, but dumped sections exclusively use types that have the same alignment in both 32 and 64 bit platforms. */ -/* We make sure bool is 1 for cross-platform save state compatibility. */ -/* Todo: We might want to typedef our own bool if this prevents SameBoy from working on specific platforms. */ -_Static_assert(sizeof(bool) == 1, "sizeof(bool) != 1"); - #ifdef GB_INTERNAL struct GB_gameboy_s { #else From 436dc0b67a0e392ff0e0e1c05f16e9292f4245eb Mon Sep 17 00:00:00 2001 From: retro-wertz Date: Sat, 13 Jul 2019 22:11:29 +0800 Subject: [PATCH 15/30] Fix GBC memory map and add IO port range for cheevos --- libretro/libretro.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/libretro/libretro.c b/libretro/libretro.c index 54c7906..59dfdc4 100644 --- a/libretro/libretro.c +++ b/libretro/libretro.c @@ -425,21 +425,20 @@ static void init_for_current_model(unsigned id) descs[7].len = 0x4000; descs[7].flags = RETRO_MEMDESC_CONST; - descs[8].ptr = GB_get_direct_access(&gameboy[i], GB_DIRECT_ACCESS_OAM, &size, &bank); - descs[8].start = 0xFE00; - descs[8].select = 0xFFFFFF00; - descs[8].len = 0x00A0; + descs[8].ptr = GB_get_direct_access(&gameboy[i], GB_DIRECT_ACCESS_OAM, &size, &bank); + descs[8].start = 0xFE00; + descs[8].len = 0x00A0; + descs[8].select= 0xFFFFFF00; - descs[9].ptr = descs[2].ptr + 0x2000; /* GBC RAM bank 2 */ - descs[9].start = 0x10000; - descs[9].select = 0xFFFF0000; - descs[9].len = GB_is_cgb(&gameboy[i]) ? 0x6000 : 0; /* 0x1000 per bank (2-7), unmapped on GB */ + descs[9].ptr = descs[2].ptr + 0x2000; /* GBC RAM bank 2 */ + descs[9].start = 0x10000; + descs[9].len = GB_is_cgb(&gameboy[i]) ? 0x6000 : 0; /* 0x1000 per bank (2-7), unmapped on GB */ + descs[9].select= 0xFFFF0000; - descs[10].ptr = descs[8].ptr; - descs[10].offset = 0x100; - descs[10].start = 0xFF00; - descs[10].select = 0xFFFFFF00; - descs[10].len = 0x0080; + descs[10].ptr = GB_get_direct_access(&gameboy[i], GB_DIRECT_ACCESS_IO, &size, &bank); + descs[10].start = 0xFF00; + descs[10].len = 0x0080; + descs[10].select= 0xFFFFFF00; struct retro_memory_map mmaps; mmaps.descriptors = descs; From 7c9508ae961d9ddf6cdf8a8ff638261ddb4b5bb3 Mon Sep 17 00:00:00 2001 From: "Anthony J. Bentley" Date: Tue, 25 Jun 2019 21:01:54 -0600 Subject: [PATCH 16/30] Include the canonical SDL2 path, which drops the SDL2/ prefix. Use pkg-config or sdl2-config to determine SDL and GL compilation flags. --- Makefile | 29 +++++++++++++++++++++++++++-- SDL/gui.c | 2 +- SDL/gui.h | 2 +- SDL/main.c | 2 +- SDL/opengl_compat.c | 2 +- SDL/opengl_compat.h | 4 ++-- SDL/utils.c | 2 +- 7 files changed, 34 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index dfab248..bc2b371 100644 --- a/Makefile +++ b/Makefile @@ -55,6 +55,11 @@ CC := clang endif endif +# Find libraries with pkg-config if available. +ifneq (, $(shell which pkg-config)) +PKG_CONFIG := pkg-config +endif + ifeq ($(PLATFORM),windows32) # To force use of the Unix version instead of the Windows version MKDIR := $(shell which mkdir) @@ -82,7 +87,19 @@ endif CFLAGS += -Werror -Wall -Wno-unused-result -Wno-strict-aliasing -Wno-unknown-warning -Wno-unknown-warning-option -Wno-multichar -Wno-int-in-bool-context -std=gnu11 -D_GNU_SOURCE -DVERSION="$(VERSION)" -I. -D_USE_MATH_DEFINES -SDL_LDFLAGS := -lSDL2 -lGL +ifeq (,$(PKG_CONFIG)) +SDL_CFLAGS := $(shell sdl2-config --cflags) +SDL_LDFLAGS := $(shell sdl2-config --libs) +else +SDL_CFLAGS := $(shell $(PKG_CONFIG) --cflags sdl2) +SDL_LDFLAGS := $(shell $(PKG_CONFIG) --libs sdl2) +endif +ifeq (,$(PKG_CONFIG)) +GL_LDFLAGS := -lGL +else +GL_CFLAGS := $(shell $(PKG_CONFIG) --cflags gl) +GL_LDFLAGS := $(shell $(PKG_CONFIG) --libs gl || echo -lGL) +endif ifeq ($(PLATFORM),windows32) CFLAGS += -IWindows -Drandom=rand LDFLAGS += -lmsvcrt -lcomdlg32 -lSDL2main -Wl,/MANIFESTFILE:NUL @@ -169,6 +186,10 @@ ifneq ($(filter $(MAKECMDGOALS),cocoa),) endif endif +$(OBJ)/SDL/%.dep: SDL/% + -@$(MKDIR) -p $(dir $@) + $(CC) $(CFLAGS) $(SDL_CFLAGS) $(GL_CFLAGS) -MT $(OBJ)/$^.o -M $^ -c -o $@ + $(OBJ)/%.dep: % -@$(MKDIR) -p $(dir $@) $(CC) $(CFLAGS) -MT $(OBJ)/$^.o -M $^ -c -o $@ @@ -179,6 +200,10 @@ $(OBJ)/Core/%.c.o: Core/%.c -@$(MKDIR) -p $(dir $@) $(CC) $(CFLAGS) -DGB_INTERNAL -c $< -o $@ +$(OBJ)/SDL/%.c.o: SDL/%.c + -@$(MKDIR) -p $(dir $@) + $(CC) $(CFLAGS) $(SDL_CFLAGS) $(GL_CFLAGS) -c $< -o $@ + $(OBJ)/%.c.o: %.c -@$(MKDIR) -p $(dir $@) $(CC) $(CFLAGS) -c $< -o $@ @@ -256,7 +281,7 @@ $(BIN)/SameBoy.qlgenerator/Contents/Resources/cgb_boot_fast.bin: $(BIN)/BootROMs # Unix versions build only one binary $(BIN)/SDL/sameboy: $(CORE_OBJECTS) $(SDL_OBJECTS) -@$(MKDIR) -p $(dir $@) - $(CC) $^ -o $@ $(LDFLAGS) $(SDL_LDFLAGS) + $(CC) $^ -o $@ $(LDFLAGS) $(SDL_LDFLAGS) $(GL_LDFLAGS) ifeq ($(CONF), release) strip $@ endif diff --git a/SDL/gui.c b/SDL/gui.c index b34bb1a..3bfd99e 100644 --- a/SDL/gui.c +++ b/SDL/gui.c @@ -1,5 +1,5 @@ -#include #include +#include #include #include #include diff --git a/SDL/gui.h b/SDL/gui.h index 6974849..b22c74f 100644 --- a/SDL/gui.h +++ b/SDL/gui.h @@ -1,7 +1,7 @@ #ifndef gui_h #define gui_h -#include +#include #include #include #include "shader.h" diff --git a/SDL/main.c b/SDL/main.c index 933237e..a095064 100755 --- a/SDL/main.c +++ b/SDL/main.c @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include "utils.h" #include "gui.h" diff --git a/SDL/opengl_compat.c b/SDL/opengl_compat.c index aed2a76..af7ce6d 100644 --- a/SDL/opengl_compat.c +++ b/SDL/opengl_compat.c @@ -1,5 +1,5 @@ #define GL_GLEXT_PROTOTYPES -#include +#include #ifndef __APPLE__ #define GL_COMPAT_NAME(func) gl_compat_##func diff --git a/SDL/opengl_compat.h b/SDL/opengl_compat.h index 9fd1ca9..15b2a17 100644 --- a/SDL/opengl_compat.h +++ b/SDL/opengl_compat.h @@ -2,8 +2,8 @@ #define opengl_compat_h #define GL_GLEXT_PROTOTYPES -#include -#include +#include +#include #ifndef __APPLE__ #define GL_COMPAT_NAME(func) gl_compat_##func diff --git a/SDL/utils.c b/SDL/utils.c index eee6ce6..8cdd00b 100644 --- a/SDL/utils.c +++ b/SDL/utils.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include "utils.h" From 8a99d41c3199f5e1dcb2f53e51ec424aece5716e Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Thu, 26 Dec 2019 02:00:58 +0200 Subject: [PATCH 17/30] Fix broken SDL builds on macOS and Windows --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index bc2b371..1c23610 100644 --- a/Makefile +++ b/Makefile @@ -103,7 +103,8 @@ endif ifeq ($(PLATFORM),windows32) CFLAGS += -IWindows -Drandom=rand LDFLAGS += -lmsvcrt -lcomdlg32 -lSDL2main -Wl,/MANIFESTFILE:NUL -SDL_LDFLAGS := -lSDL2 -lopengl32 +SDL_LDFLAGS := -lSDL2 +GL_LDFLAGS := -lopengl32 else LDFLAGS += -lc -lm -ldl endif @@ -113,7 +114,8 @@ SYSROOT := $(shell xcodebuild -sdk macosx -version Path 2> /dev/null) CFLAGS += -F/Library/Frameworks OCFLAGS += -x objective-c -fobjc-arc -Wno-deprecated-declarations -isysroot $(SYSROOT) -mmacosx-version-min=10.9 LDFLAGS += -framework AppKit -framework PreferencePanes -framework Carbon -framework QuartzCore -weak_framework Metal -weak_framework MetalKit -mmacosx-version-min=10.9 -SDL_LDFLAGS := -F/Library/Frameworks -framework SDL2 -framework OpenGL +SDL_LDFLAGS := -F/Library/Frameworks -framework SDL2 +GL_LDFLAGS := -framework OpenGL endif CFLAGS += -Wno-deprecated-declarations ifeq ($(PLATFORM),windows32) From 4c243235309dd52fd5bb4469065fedcf417fb7b9 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Sun, 29 Dec 2019 17:34:43 +0100 Subject: [PATCH 18/30] Fix Game Boy Camera support in macOS Mojave and newer --- Cocoa/Document.m | 17 +++++++++++++++++ Cocoa/Info.plist | 4 ++++ 2 files changed, 21 insertions(+) diff --git a/Cocoa/Document.m b/Cocoa/Document.m index a520d62..85dd728 100644 --- a/Cocoa/Document.m +++ b/Cocoa/Document.m @@ -1171,6 +1171,23 @@ static void audioCallback(GB_gameboy_t *gb, GB_sample_t *sample) dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ @try { if (!cameraSession) { + if (@available(macOS 10.14, *)) { + switch ([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]) { + case AVAuthorizationStatusAuthorized: + break; + case AVAuthorizationStatusNotDetermined: { + [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) { + [self cameraRequestUpdate]; + }]; + return; + } + case AVAuthorizationStatusDenied: + case AVAuthorizationStatusRestricted: + GB_camera_updated(&gb); + return; + } + } + NSError *error; AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo]; AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice: device error: &error]; diff --git a/Cocoa/Info.plist b/Cocoa/Info.plist index dd801cb..d86b9fd 100644 --- a/Cocoa/Info.plist +++ b/Cocoa/Info.plist @@ -2,6 +2,8 @@ + CFBundleDisplayName + SameBoy CFBundleDevelopmentRegion en CFBundleDocumentTypes @@ -116,6 +118,8 @@ + NSCameraUsageDescription + SameBoy needs to access your camera to emulate the Game Boy Camera NSSupportsAutomaticGraphicsSwitching From e434b625ea14ee8f9937e0cc6e1ea39ec5d040b8 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Mon, 30 Dec 2019 16:19:06 +0100 Subject: [PATCH 19/30] Allow the fullscreen key combo to work while in the menu --- SDL/gui.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/SDL/gui.c b/SDL/gui.c index 3bfd99e..1664e74 100644 --- a/SDL/gui.c +++ b/SDL/gui.c @@ -1012,6 +1012,15 @@ void run_gui(bool is_running) } case SDL_KEYDOWN: + if (event.key.keysym.scancode == SDL_SCANCODE_F && event.key.keysym.mod & MODIFIER) { + if ((SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN_DESKTOP) == false) { + SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); + } + else { + SDL_SetWindowFullscreen(window, 0); + } + } + break; if (event.key.keysym.scancode == SDL_SCANCODE_O) { if (event.key.keysym.mod & MODIFIER) { char *filename = do_open_rom_dialog(); From 7929573dc170670a6cf1e43b6d11483d8c640920 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Wed, 1 Jan 2020 00:17:54 +0200 Subject: [PATCH 20/30] Refinements to the last commit --- SDL/gui.c | 2 +- SDL/main.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/SDL/gui.c b/SDL/gui.c index 1664e74..db72c4d 100644 --- a/SDL/gui.c +++ b/SDL/gui.c @@ -1019,8 +1019,8 @@ void run_gui(bool is_running) else { SDL_SetWindowFullscreen(window, 0); } + update_viewport(); } - break; if (event.key.keysym.scancode == SDL_SCANCODE_O) { if (event.key.keysym.mod & MODIFIER) { char *filename = do_open_rom_dialog(); diff --git a/SDL/main.c b/SDL/main.c index a095064..51e7c1a 100755 --- a/SDL/main.c +++ b/SDL/main.c @@ -274,6 +274,7 @@ static void handle_events(GB_gameboy_t *gb) else { SDL_SetWindowFullscreen(window, 0); } + update_viewport(); } break; From 3882b1b4b9ab34361211cbf7840e2f11d888a16f Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Wed, 1 Jan 2020 00:27:41 +0200 Subject: [PATCH 21/30] Fix Windows build, hopefully fix High DPI support on Windows 10 (fixes #202) --- Makefile | 6 +++--- SDL/main.c | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) mode change 100755 => 100644 SDL/main.c diff --git a/Makefile b/Makefile index 1c23610..4417528 100644 --- a/Makefile +++ b/Makefile @@ -102,7 +102,7 @@ GL_LDFLAGS := $(shell $(PKG_CONFIG) --libs gl || echo -lGL) endif ifeq ($(PLATFORM),windows32) CFLAGS += -IWindows -Drandom=rand -LDFLAGS += -lmsvcrt -lcomdlg32 -lSDL2main -Wl,/MANIFESTFILE:NUL +LDFLAGS += -lmsvcrt -lcomdlg32 -luser32 -lSDL2main -Wl,/MANIFESTFILE:NUL SDL_LDFLAGS := -lSDL2 GL_LDFLAGS := -lopengl32 else @@ -291,11 +291,11 @@ endif # Windows version builds two, one with a conole and one without it $(BIN)/SDL/sameboy.exe: $(CORE_OBJECTS) $(SDL_OBJECTS) $(OBJ)/Windows/resources.o -@$(MKDIR) -p $(dir $@) - $(CC) $^ -o $@ $(LDFLAGS) $(SDL_LDFLAGS) -Wl,/subsystem:windows + $(CC) $^ -o $@ $(LDFLAGS) $(SDL_LDFLAGS) $(GL_LDFLAGS) -Wl,/subsystem:windows $(BIN)/SDL/sameboy_debugger.exe: $(CORE_OBJECTS) $(SDL_OBJECTS) $(OBJ)/Windows/resources.o -@$(MKDIR) -p $(dir $@) - $(CC) $^ -o $@ $(LDFLAGS) $(SDL_LDFLAGS) -Wl,/subsystem:console + $(CC) $^ -o $@ $(LDFLAGS) $(SDL_LDFLAGS) $(GL_LDFLAGS) -Wl,/subsystem:console ifneq ($(USE_WINDRES),) $(OBJ)/%.o: %.rc diff --git a/SDL/main.c b/SDL/main.c old mode 100755 new mode 100644 index 51e7c1a..96f4994 --- a/SDL/main.c +++ b/SDL/main.c @@ -10,6 +10,7 @@ #ifndef _WIN32 +#include #define AUDIO_FREQUENCY 96000 #else /* Windows (well, at least my VM) can't handle 96KHz sound well :( */ @@ -551,6 +552,9 @@ static bool get_arg_flag(const char *flag, int *argc, char **argv) int main(int argc, char **argv) { +#ifdef _WIN32 + SetProcessDPIAware(); +#endif #define str(x) #x #define xstr(x) str(x) fprintf(stderr, "SameBoy v" xstr(VERSION) "\n"); From e9f6667cf52fb55a935ef0620845e7b7ad795126 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Wed, 1 Jan 2020 22:57:24 +0200 Subject: [PATCH 22/30] Minor build cleanup --- Makefile | 29 +++++++++++++++++------------ QuickLook/exports.sym | 2 +- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index 4417528..bd31875 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,7 @@ endif # Use clang if it's available. ifeq ($(origin CC),default) ifneq (, $(shell which clang)) -CC := clang +CC := clang endif endif @@ -76,9 +76,11 @@ endif # Set compilation and linkage flags based on target, platform and configuration OPEN_DIALOG = OpenDialog/gtk.c +NULL := /dev/null ifeq ($(PLATFORM),windows32) OPEN_DIALOG = OpenDialog/windows.c +NULL := NUL endif ifeq ($(PLATFORM),Darwin) @@ -110,9 +112,9 @@ LDFLAGS += -lc -lm -ldl endif ifeq ($(PLATFORM),Darwin) -SYSROOT := $(shell xcodebuild -sdk macosx -version Path 2> /dev/null) -CFLAGS += -F/Library/Frameworks -OCFLAGS += -x objective-c -fobjc-arc -Wno-deprecated-declarations -isysroot $(SYSROOT) -mmacosx-version-min=10.9 +SYSROOT := $(shell xcodebuild -sdk macosx -version Path 2> $(NULL)) +CFLAGS += -F/Library/Frameworks -mmacosx-version-min=10.9 +OCFLAGS += -x objective-c -fobjc-arc -Wno-deprecated-declarations -isysroot $(SYSROOT) LDFLAGS += -framework AppKit -framework PreferencePanes -framework Carbon -framework QuartzCore -weak_framework Metal -weak_framework MetalKit -mmacosx-version-min=10.9 SDL_LDFLAGS := -F/Library/Frameworks -framework SDL2 GL_LDFLAGS := -framework OpenGL @@ -127,10 +129,16 @@ ifeq ($(CONF),debug) CFLAGS += -g else ifeq ($(CONF), release) CFLAGS += -O3 -DNDEBUG +STRIP := strip +ifeq ($(PLATFORM),Darwin) +LDFLAGS += -Wl,-exported_symbols_list,$(NULL) +STRIP := -@true +endif ifneq ($(PLATFORM),windows32) LDFLAGS += -flto CFLAGS += -flto endif + else $(error Invalid value for CONF: $(CONF). Use "debug", "release" or "native_release") endif @@ -247,7 +255,7 @@ $(BIN)/SameBoy.app/Contents/MacOS/SameBoy: $(CORE_OBJECTS) $(COCOA_OBJECTS) -@$(MKDIR) -p $(dir $@) $(CC) $^ -o $@ $(LDFLAGS) -framework OpenGL -framework AudioUnit -framework AVFoundation -framework CoreVideo -framework CoreMedia -framework IOKit ifeq ($(CONF), release) - strip $@ + $(STRIP) $@ endif $(BIN)/SameBoy.app/Contents/Resources/Base.lproj/%.nib: Cocoa/%.xib @@ -267,10 +275,7 @@ $(BIN)/SameBoy.qlgenerator: $(BIN)/SameBoy.qlgenerator/Contents/MacOS/SameBoyQL # once in the QL Generator. It should probably become a dylib instead. $(BIN)/SameBoy.qlgenerator/Contents/MacOS/SameBoyQL: $(CORE_OBJECTS) $(QUICKLOOK_OBJECTS) -@$(MKDIR) -p $(dir $@) - $(CC) $^ -o $@ $(LDFLAGS) -bundle -framework Cocoa -framework Quicklook -ifeq ($(CONF), release) - strip -u -r -s QuickLook/exports.sym $@ -endif + $(CC) $^ -o $@ $(LDFLAGS) -Wl,-exported_symbols_list,QuickLook/exports.sym -bundle -framework Cocoa -framework Quicklook # cgb_boot_fast.bin is not a standard boot ROM, we don't expect it to exist in the user-provided # boot ROM directory. @@ -285,7 +290,7 @@ $(BIN)/SDL/sameboy: $(CORE_OBJECTS) $(SDL_OBJECTS) -@$(MKDIR) -p $(dir $@) $(CC) $^ -o $@ $(LDFLAGS) $(SDL_LDFLAGS) $(GL_LDFLAGS) ifeq ($(CONF), release) - strip $@ + $(STRIP) $@ endif # Windows version builds two, one with a conole and one without it @@ -321,7 +326,7 @@ $(BIN)/tester/sameboy_tester: $(CORE_OBJECTS) $(TESTER_OBJECTS) -@$(MKDIR) -p $(dir $@) $(CC) $^ -o $@ $(LDFLAGS) ifeq ($(CONF), release) - strip $@ + $(STRIP) $@ endif $(BIN)/tester/sameboy_tester.exe: $(CORE_OBJECTS) $(SDL_OBJECTS) @@ -372,7 +377,7 @@ $(BIN)/BootROMs/%.bin: BootROMs/%.asm $(OBJ)/BootROMs/SameBoyLogo.pb8 -@$(MKDIR) -p $(dir $@) rgbasm -i $(OBJ)/BootROMs/ -i BootROMs/ -o $@.tmp $< rgblink -o $@.tmp2 $@.tmp - dd if=$@.tmp2 of=$@ count=1 bs=$(if $(findstring dmg,$@)$(findstring sgb,$@),256,2304) + dd if=$@.tmp2 of=$@ count=1 bs=$(if $(findstring dmg,$@)$(findstring sgb,$@),256,2304) 2> $(NULL) @rm $@.tmp $@.tmp2 # Libretro Core (uses its own build system) diff --git a/QuickLook/exports.sym b/QuickLook/exports.sym index 778b203..f979687 100644 --- a/QuickLook/exports.sym +++ b/QuickLook/exports.sym @@ -1,3 +1,3 @@ _DeallocQuickLookGeneratorPluginType _QuickLookGeneratorQueryInterface -_QuickLookGeneratorPluginFactory \ No newline at end of file +_QuickLookGeneratorPluginFactory From 23c7fb28858677f6cef474fae754898c246de8b0 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Wed, 1 Jan 2020 23:40:56 +0200 Subject: [PATCH 23/30] Update version, update copyright year --- Cocoa/Info.plist | 2 +- Cocoa/License.html | 2 +- LICENSE | 2 +- Makefile | 2 +- QuickLook/Info.plist | 2 +- Windows/resources.rc | Bin 1210 -> 1210 bytes 6 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cocoa/Info.plist b/Cocoa/Info.plist index d86b9fd..1c7bdb5 100644 --- a/Cocoa/Info.plist +++ b/Cocoa/Info.plist @@ -72,7 +72,7 @@ LSMinimumSystemVersion 10.9 NSHumanReadableCopyright - Copyright © 2015-2019 Lior Halphon + Copyright © 2015-2020 Lior Halphon NSMainNibFile MainMenu NSPrincipalClass diff --git a/Cocoa/License.html b/Cocoa/License.html index 49851fd..b21cf8d 100644 --- a/Cocoa/License.html +++ b/Cocoa/License.html @@ -30,7 +30,7 @@

SameBoy

MIT License

-

Copyright © 2015-2019 Lior Halphon

+

Copyright © 2015-2020 Lior Halphon

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/LICENSE b/LICENSE index 94966be..17619e9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2015-2019 Lior Halphon +Copyright (c) 2015-2020 Lior Halphon Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile index bd31875..7c22375 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,7 @@ ifeq ($(MAKECMDGOALS),) MAKECMDGOALS := $(DEFAULT) endif -VERSION := 0.12.2 +VERSION := 0.12.3 export VERSION CONF ?= debug diff --git a/QuickLook/Info.plist b/QuickLook/Info.plist index 9540214..2cff196 100644 --- a/QuickLook/Info.plist +++ b/QuickLook/Info.plist @@ -47,7 +47,7 @@ CFPlugInUnloadFunction NSHumanReadableCopyright - Copyright © 2015-2019 Lior Halphon + Copyright © 2015-2020 Lior Halphon QLNeedsToBeRunInMainThread QLPreviewHeight diff --git a/Windows/resources.rc b/Windows/resources.rc index ffa8b3b93a3b02e11c7283a4c4764b7e27b9321f..73c12139e68ff25a1cf03c451e05e25df9d3c05f 100644 GIT binary patch delta 16 XcmdnRxr=i{6ce)%gTdxlrdTEbD~beZ delta 16 XcmdnRxr=i{6ce){gT>}prdTEbE3yP| From 5a1812f237cc3c5501187728f5758949e6a930e5 Mon Sep 17 00:00:00 2001 From: Pixelnarium Date: Thu, 2 Jan 2020 10:50:55 +0100 Subject: [PATCH 24/30] fix SDL build --- SDL/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SDL/main.c b/SDL/main.c index 96f4994..1646d5c 100644 --- a/SDL/main.c +++ b/SDL/main.c @@ -10,9 +10,9 @@ #ifndef _WIN32 -#include #define AUDIO_FREQUENCY 96000 #else +#include /* Windows (well, at least my VM) can't handle 96KHz sound well :( */ /* felsqualle says: For SDL 2.0.6+ using the WASAPI driver, the highest freq. From 95af00a7524fda0ba932f89f3aaf232fc20f56e7 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Fri, 3 Jan 2020 21:11:45 +0200 Subject: [PATCH 25/30] speling is veri difikult --- Core/debugger.c | 2 +- Core/gb.h | 2 +- Core/sm83_cpu.c | 34 +++++++++++++++++----------------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Core/debugger.c b/Core/debugger.c index df480f3..8b6d6cf 100644 --- a/Core/debugger.c +++ b/Core/debugger.c @@ -819,7 +819,7 @@ static bool registers(GB_gameboy_t *gb, char *arguments, char *modifiers, const GB_log(gb, "AF = $%04x (%c%c%c%c)\n", gb->registers[GB_REGISTER_AF], /* AF can't really be an address */ (gb->f & GB_CARRY_FLAG)? 'C' : '-', (gb->f & GB_HALF_CARRY_FLAG)? 'H' : '-', - (gb->f & GB_SUBSTRACT_FLAG)? 'N' : '-', + (gb->f & GB_SUBTRACT_FLAG)? 'N' : '-', (gb->f & GB_ZERO_FLAG)? 'Z' : '-'); GB_log(gb, "BC = %s\n", value_to_string(gb, gb->registers[GB_REGISTER_BC], false)); GB_log(gb, "DE = %s\n", value_to_string(gb, gb->registers[GB_REGISTER_DE], false)); diff --git a/Core/gb.h b/Core/gb.h index a561111..c27b6c6 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -98,7 +98,7 @@ enum { enum { GB_CARRY_FLAG = 16, GB_HALF_CARRY_FLAG = 32, - GB_SUBSTRACT_FLAG = 64, + GB_SUBTRACT_FLAG = 64, GB_ZERO_FLAG = 128, }; diff --git a/Core/sm83_cpu.c b/Core/sm83_cpu.c index 77248b5..0009a69 100644 --- a/Core/sm83_cpu.c +++ b/Core/sm83_cpu.c @@ -318,7 +318,7 @@ static void inc_hr(GB_gameboy_t *gb, uint8_t opcode) uint8_t register_id; register_id = ((opcode >> 4) + 1) & 0x03; gb->registers[register_id] += 0x100; - gb->registers[GB_REGISTER_AF] &= ~(GB_SUBSTRACT_FLAG | GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); + gb->registers[GB_REGISTER_AF] &= ~(GB_SUBTRACT_FLAG | GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); if ((gb->registers[register_id] & 0x0F00) == 0) { gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; @@ -334,7 +334,7 @@ static void dec_hr(GB_gameboy_t *gb, uint8_t opcode) register_id = ((opcode >> 4) + 1) & 0x03; gb->registers[register_id] -= 0x100; gb->registers[GB_REGISTER_AF] &= ~(GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); - gb->registers[GB_REGISTER_AF] |= GB_SUBSTRACT_FLAG; + gb->registers[GB_REGISTER_AF] |= GB_SUBTRACT_FLAG; if ((gb->registers[register_id] & 0x0F00) == 0xF00) { gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; @@ -396,7 +396,7 @@ static void add_hl_rr(GB_gameboy_t *gb, uint8_t opcode) register_id = (opcode >> 4) + 1; rr = gb->registers[register_id]; gb->registers[GB_REGISTER_HL] = hl + rr; - gb->registers[GB_REGISTER_AF] &= ~(GB_SUBSTRACT_FLAG | GB_CARRY_FLAG | GB_HALF_CARRY_FLAG); + gb->registers[GB_REGISTER_AF] &= ~(GB_SUBTRACT_FLAG | GB_CARRY_FLAG | GB_HALF_CARRY_FLAG); /* The meaning of the Half Carry flag is really hard to track -_- */ if (((hl & 0xFFF) + (rr & 0xFFF)) & 0x1000) { @@ -432,7 +432,7 @@ static void inc_lr(GB_gameboy_t *gb, uint8_t opcode) value = (gb->registers[register_id] & 0xFF) + 1; gb->registers[register_id] = (gb->registers[register_id] & 0xFF00) | value; - gb->registers[GB_REGISTER_AF] &= ~(GB_SUBSTRACT_FLAG | GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); + gb->registers[GB_REGISTER_AF] &= ~(GB_SUBTRACT_FLAG | GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); if ((gb->registers[register_id] & 0x0F) == 0) { gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; @@ -452,7 +452,7 @@ static void dec_lr(GB_gameboy_t *gb, uint8_t opcode) gb->registers[register_id] = (gb->registers[register_id] & 0xFF00) | value; gb->registers[GB_REGISTER_AF] &= ~(GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); - gb->registers[GB_REGISTER_AF] |= GB_SUBSTRACT_FLAG; + gb->registers[GB_REGISTER_AF] |= GB_SUBTRACT_FLAG; if ((gb->registers[register_id] & 0x0F) == 0xF) { gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; @@ -533,7 +533,7 @@ static void daa(GB_gameboy_t *gb, uint8_t opcode) gb->registers[GB_REGISTER_AF] &= ~(0xFF00 | GB_ZERO_FLAG); - if (gb->registers[GB_REGISTER_AF] & GB_SUBSTRACT_FLAG) { + if (gb->registers[GB_REGISTER_AF] & GB_SUBTRACT_FLAG) { if (gb->registers[GB_REGISTER_AF] & GB_HALF_CARRY_FLAG) { result = (result - 0x06) & 0xFF; } @@ -567,19 +567,19 @@ static void daa(GB_gameboy_t *gb, uint8_t opcode) static void cpl(GB_gameboy_t *gb, uint8_t opcode) { gb->registers[GB_REGISTER_AF] ^= 0xFF00; - gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG | GB_SUBSTRACT_FLAG; + gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG | GB_SUBTRACT_FLAG; } static void scf(GB_gameboy_t *gb, uint8_t opcode) { gb->registers[GB_REGISTER_AF] |= GB_CARRY_FLAG; - gb->registers[GB_REGISTER_AF] &= ~(GB_HALF_CARRY_FLAG | GB_SUBSTRACT_FLAG); + gb->registers[GB_REGISTER_AF] &= ~(GB_HALF_CARRY_FLAG | GB_SUBTRACT_FLAG); } static void ccf(GB_gameboy_t *gb, uint8_t opcode) { gb->registers[GB_REGISTER_AF] ^= GB_CARRY_FLAG; - gb->registers[GB_REGISTER_AF] &= ~(GB_HALF_CARRY_FLAG | GB_SUBSTRACT_FLAG); + gb->registers[GB_REGISTER_AF] &= ~(GB_HALF_CARRY_FLAG | GB_SUBTRACT_FLAG); } static void ld_dhli_a(GB_gameboy_t *gb, uint8_t opcode) @@ -610,7 +610,7 @@ static void inc_dhl(GB_gameboy_t *gb, uint8_t opcode) value = cycle_read(gb, gb->registers[GB_REGISTER_HL]) + 1; cycle_write(gb, gb->registers[GB_REGISTER_HL], value); - gb->registers[GB_REGISTER_AF] &= ~(GB_SUBSTRACT_FLAG | GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); + gb->registers[GB_REGISTER_AF] &= ~(GB_SUBTRACT_FLAG | GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); if ((value & 0x0F) == 0) { gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; } @@ -627,7 +627,7 @@ static void dec_dhl(GB_gameboy_t *gb, uint8_t opcode) cycle_write(gb, gb->registers[GB_REGISTER_HL], value); gb->registers[GB_REGISTER_AF] &= ~( GB_ZERO_FLAG | GB_HALF_CARRY_FLAG); - gb->registers[GB_REGISTER_AF] |= GB_SUBSTRACT_FLAG; + gb->registers[GB_REGISTER_AF] |= GB_SUBTRACT_FLAG; if ((value & 0x0F) == 0x0F) { gb->registers[GB_REGISTER_AF] |= GB_HALF_CARRY_FLAG; } @@ -763,7 +763,7 @@ static void sub_a_r(GB_gameboy_t *gb, uint8_t opcode) uint8_t value, a; value = get_src_value(gb, opcode); a = gb->registers[GB_REGISTER_AF] >> 8; - gb->registers[GB_REGISTER_AF] = ((a - value) << 8) | GB_SUBSTRACT_FLAG; + gb->registers[GB_REGISTER_AF] = ((a - value) << 8) | GB_SUBTRACT_FLAG; if (a == value) { gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; } @@ -781,7 +781,7 @@ static void sbc_a_r(GB_gameboy_t *gb, uint8_t opcode) value = get_src_value(gb, opcode); a = gb->registers[GB_REGISTER_AF] >> 8; carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; - gb->registers[GB_REGISTER_AF] = ((a - value - carry) << 8) | GB_SUBSTRACT_FLAG; + gb->registers[GB_REGISTER_AF] = ((a - value - carry) << 8) | GB_SUBTRACT_FLAG; if ((uint8_t) (a - value - carry) == 0) { gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; @@ -833,7 +833,7 @@ static void cp_a_r(GB_gameboy_t *gb, uint8_t opcode) value = get_src_value(gb, opcode); a = gb->registers[GB_REGISTER_AF] >> 8; gb->registers[GB_REGISTER_AF] &= 0xFF00; - gb->registers[GB_REGISTER_AF] |= GB_SUBSTRACT_FLAG; + gb->registers[GB_REGISTER_AF] |= GB_SUBTRACT_FLAG; if (a == value) { gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; } @@ -962,7 +962,7 @@ static void sub_a_d8(GB_gameboy_t *gb, uint8_t opcode) uint8_t value, a; value = cycle_read_inc_oam_bug(gb, gb->pc++); a = gb->registers[GB_REGISTER_AF] >> 8; - gb->registers[GB_REGISTER_AF] = ((a - value) << 8) | GB_SUBSTRACT_FLAG; + gb->registers[GB_REGISTER_AF] = ((a - value) << 8) | GB_SUBTRACT_FLAG; if (a == value) { gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; } @@ -980,7 +980,7 @@ static void sbc_a_d8(GB_gameboy_t *gb, uint8_t opcode) value = cycle_read_inc_oam_bug(gb, gb->pc++); a = gb->registers[GB_REGISTER_AF] >> 8; carry = (gb->registers[GB_REGISTER_AF] & GB_CARRY_FLAG) != 0; - gb->registers[GB_REGISTER_AF] = ((a - value - carry) << 8) | GB_SUBSTRACT_FLAG; + gb->registers[GB_REGISTER_AF] = ((a - value - carry) << 8) | GB_SUBTRACT_FLAG; if ((uint8_t) (a - value - carry) == 0) { gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; @@ -1032,7 +1032,7 @@ static void cp_a_d8(GB_gameboy_t *gb, uint8_t opcode) value = cycle_read_inc_oam_bug(gb, gb->pc++); a = gb->registers[GB_REGISTER_AF] >> 8; gb->registers[GB_REGISTER_AF] &= 0xFF00; - gb->registers[GB_REGISTER_AF] |= GB_SUBSTRACT_FLAG; + gb->registers[GB_REGISTER_AF] |= GB_SUBTRACT_FLAG; if (a == value) { gb->registers[GB_REGISTER_AF] |= GB_ZERO_FLAG; } From 163a5ea20c061fe66452017ef8f1b613af3f352f Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Wed, 29 Jan 2020 14:19:11 +0200 Subject: [PATCH 26/30] Add DMG color palettes (Cocoa) --- Cocoa/Document.m | 28 ++++++++++++++++++++ Cocoa/GBPreferencesWindow.h | 1 + Cocoa/GBPreferencesWindow.m | 21 +++++++++++++++ Cocoa/Preferences.xib | 43 ++++++++++++++++++++++++++----- Core/display.c | 14 +++++++--- Core/gb.c | 51 ++++++++++++++++++++++--------------- Core/gb.h | 15 ++++++++++- 7 files changed, 143 insertions(+), 30 deletions(-) diff --git a/Cocoa/Document.m b/Cocoa/Document.m index 85dd728..0c40776 100644 --- a/Cocoa/Document.m +++ b/Cocoa/Document.m @@ -184,6 +184,27 @@ static void audioCallback(GB_gameboy_t *gb, GB_sample_t *sample) } } +- (void) updatePalette +{ + switch ([[NSUserDefaults standardUserDefaults] integerForKey:@"GBColorPalette"]) { + case 1: + GB_set_palette(&gb, &GB_PALETTE_DMG); + break; + + case 2: + GB_set_palette(&gb, &GB_PALETTE_MGB); + break; + + case 3: + GB_set_palette(&gb, &GB_PALETTE_GBL); + break; + + default: + GB_set_palette(&gb, &GB_PALETTE_GREY); + break; + } +} + - (void) initCommon { GB_init(&gb, [self internalModel]); @@ -193,6 +214,7 @@ static void audioCallback(GB_gameboy_t *gb, GB_sample_t *sample) GB_set_input_callback(&gb, (GB_input_callback_t) consoleInput); GB_set_async_input_callback(&gb, (GB_input_callback_t) asyncConsoleInput); GB_set_color_correction_mode(&gb, (GB_color_correction_mode_t) [[NSUserDefaults standardUserDefaults] integerForKey:@"GBColorCorrection"]); + [self updatePalette]; GB_set_rgb_encode_callback(&gb, rgbEncode); GB_set_camera_get_pixel_callback(&gb, cameraGetPixel); GB_set_camera_update_request_callback(&gb, cameraRequestUpdate); @@ -452,6 +474,12 @@ static void audioCallback(GB_gameboy_t *gb, GB_sample_t *sample) name:@"GBColorCorrectionChanged" object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(updatePalette) + name:@"GBColorPaletteChanged" + object:nil]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateRewindLength) name:@"GBRewindLengthChanged" diff --git a/Cocoa/GBPreferencesWindow.h b/Cocoa/GBPreferencesWindow.h index 90eee54..b34aafa 100644 --- a/Cocoa/GBPreferencesWindow.h +++ b/Cocoa/GBPreferencesWindow.h @@ -7,6 +7,7 @@ @property (strong) IBOutlet NSButton *aspectRatioCheckbox; @property (strong) IBOutlet NSPopUpButton *highpassFilterPopupButton; @property (strong) IBOutlet NSPopUpButton *colorCorrectionPopupButton; +@property (nonatomic, strong) IBOutlet NSPopUpButton *colorPalettePopupButton; @property (strong) IBOutlet NSPopUpButton *rewindPopupButton; @property (strong) IBOutlet NSButton *configureJoypadButton; @property (strong) IBOutlet NSButton *skipButton; diff --git a/Cocoa/GBPreferencesWindow.m b/Cocoa/GBPreferencesWindow.m index ecf0311..8d3e73d 100644 --- a/Cocoa/GBPreferencesWindow.m +++ b/Cocoa/GBPreferencesWindow.m @@ -14,6 +14,7 @@ NSPopUpButton *_graphicsFilterPopupButton; NSPopUpButton *_highpassFilterPopupButton; NSPopUpButton *_colorCorrectionPopupButton; + NSPopUpButton *_colorPalettePopupButton; NSPopUpButton *_rewindPopupButton; NSButton *_aspectRatioCheckbox; NSEventModifierFlags previousModifiers; @@ -84,6 +85,18 @@ return _colorCorrectionPopupButton; } +- (void)setColorPalettePopupButton:(NSPopUpButton *)colorPalettePopupButton +{ + _colorPalettePopupButton = colorPalettePopupButton; + NSInteger mode = [[NSUserDefaults standardUserDefaults] integerForKey:@"GBColorPalette"]; + [_colorPalettePopupButton selectItemAtIndex:mode]; +} + +- (NSPopUpButton *)colorPalettePopupButton +{ + return _colorPalettePopupButton; +} + - (void)setRewindPopupButton:(NSPopUpButton *)rewindPopupButton { _rewindPopupButton = rewindPopupButton; @@ -199,6 +212,14 @@ } +- (IBAction)colorPaletteChanged:(id)sender +{ + [[NSUserDefaults standardUserDefaults] setObject:@([sender indexOfSelectedItem]) + forKey:@"GBColorPalette"]; + [[NSNotificationCenter defaultCenter] postNotificationName:@"GBColorPaletteChanged" object:nil]; + +} + - (IBAction)rewindLengthChanged:(id)sender { [[NSUserDefaults standardUserDefaults] setObject:@([sender selectedTag]) diff --git a/Cocoa/Preferences.xib b/Cocoa/Preferences.xib index 8278ee1..2c05a64 100644 --- a/Cocoa/Preferences.xib +++ b/Cocoa/Preferences.xib @@ -63,6 +63,7 @@ + @@ -78,11 +79,11 @@ - + - + @@ -91,7 +92,7 @@ - + @@ -127,7 +128,7 @@ - + @@ -136,7 +137,7 @@ - + @@ -156,6 +157,36 @@ + + + + + + + + + + + + + + + +

+ + + + + + + + + + + + + + - + diff --git a/Core/display.c b/Core/display.c index 5c1935c..f0e2ff2 100644 --- a/Core/display.c +++ b/Core/display.c @@ -142,9 +142,17 @@ static void display_vblank(GB_gameboy_t *gb) } } else { - uint32_t color = (gb->io_registers[GB_IO_LCDC] & 0x80) && gb->stopped && GB_is_cgb(gb) ? - gb->rgb_encode_callback(gb, 0, 0, 0) : - gb->rgb_encode_callback(gb, 0xFF, 0xFF, 0xFF); + uint32_t color = 0; + if (GB_is_cgb(gb)) { + color = (gb->io_registers[GB_IO_LCDC] & 0x80) && gb->stopped ? + gb->rgb_encode_callback(gb, 0, 0, 0) : + gb->rgb_encode_callback(gb, 0xFF, 0xFF, 0xFF); + } + else { + color = (gb->io_registers[GB_IO_LCDC] & 0x80) && gb->stopped ? + gb->background_palettes_rgb[3] : + gb->background_palettes_rgb[4]; + } for (unsigned i = 0; i < WIDTH * LINES; i++) { gb ->screen[i] = color; } diff --git a/Core/gb.c b/Core/gb.c index f29d400..d019fc4 100644 --- a/Core/gb.c +++ b/Core/gb.c @@ -573,21 +573,41 @@ void GB_set_async_input_callback(GB_gameboy_t *gb, GB_input_callback_t callback) #endif } +const GB_palette_t GB_PALETTE_GREY = {{{0x00, 0x00, 0x00}, {0x55, 0x55, 0x55}, {0xaa, 0xaa, 0xaa}, {0xff ,0xff, 0xff}, {0xff ,0xff, 0xff}}}; +const GB_palette_t GB_PALETTE_DMG = {{{0x08, 0x18, 0x10}, {0x39, 0x61, 0x39}, {0x84, 0xa5, 0x63}, {0xc6, 0xde, 0x8c}, {0xd2 ,0xe6 ,0xa6}}}; +const GB_palette_t GB_PALETTE_MGB = {{{0x07, 0x10, 0x0e}, {0x3a, 0x4c, 0x3a}, {0x81, 0x8d, 0x66}, {0xc2, 0xce, 0x93}, {0xcf, 0xda, 0xac}}}; +const GB_palette_t GB_PALETTE_GBL = {{{0x0a, 0x1c, 0x15}, {0x35, 0x78, 0x62}, {0x56, 0xb4, 0x95}, {0x7f, 0xe2, 0xc3}, {0x91, 0xea, 0xd0}}}; + +static void update_dmg_palette(GB_gameboy_t *gb) +{ + const GB_palette_t *palette = gb->dmg_palette ?: &GB_PALETTE_GREY; + if (gb->rgb_encode_callback && !GB_is_cgb(gb)) { + gb->sprite_palettes_rgb[4] = gb->sprite_palettes_rgb[0] = gb->background_palettes_rgb[0] = + gb->rgb_encode_callback(gb, palette->colors[3].r, palette->colors[3].g, palette->colors[3].b); + gb->sprite_palettes_rgb[5] = gb->sprite_palettes_rgb[1] = gb->background_palettes_rgb[1] = + gb->rgb_encode_callback(gb, palette->colors[2].r, palette->colors[2].g, palette->colors[2].b); + gb->sprite_palettes_rgb[6] = gb->sprite_palettes_rgb[2] = gb->background_palettes_rgb[2] = + gb->rgb_encode_callback(gb, palette->colors[1].r, palette->colors[1].g, palette->colors[1].b); + gb->sprite_palettes_rgb[7] = gb->sprite_palettes_rgb[3] = gb->background_palettes_rgb[3] = + gb->rgb_encode_callback(gb, palette->colors[0].r, palette->colors[0].g, palette->colors[0].b); + + // LCD off color + gb->background_palettes_rgb[4] = + gb->rgb_encode_callback(gb, palette->colors[4].r, palette->colors[4].g, palette->colors[4].b); + } +} + +void GB_set_palette(GB_gameboy_t *gb, const GB_palette_t *palette) +{ + gb->dmg_palette = palette; + update_dmg_palette(gb); +} void GB_set_rgb_encode_callback(GB_gameboy_t *gb, GB_rgb_encode_callback_t callback) { - if (!gb->rgb_encode_callback && !GB_is_cgb(gb)) { - gb->sprite_palettes_rgb[4] = gb->sprite_palettes_rgb[0] = gb->background_palettes_rgb[0] = - callback(gb, 0xFF, 0xFF, 0xFF); - gb->sprite_palettes_rgb[5] = gb->sprite_palettes_rgb[1] = gb->background_palettes_rgb[1] = - callback(gb, 0xAA, 0xAA, 0xAA); - gb->sprite_palettes_rgb[6] = gb->sprite_palettes_rgb[2] = gb->background_palettes_rgb[2] = - callback(gb, 0x55, 0x55, 0x55); - gb->sprite_palettes_rgb[7] = gb->sprite_palettes_rgb[3] = gb->background_palettes_rgb[3] = - callback(gb, 0, 0, 0); - } gb->rgb_encode_callback = callback; + update_dmg_palette(gb); for (unsigned i = 0; i < 32; i++) { GB_palette_changed(gb, true, i * 2); @@ -882,16 +902,7 @@ void GB_reset(GB_gameboy_t *gb) gb->vram_size = 0x2000; memset(gb->vram, 0, gb->vram_size); - if (gb->rgb_encode_callback) { - gb->sprite_palettes_rgb[4] = gb->sprite_palettes_rgb[0] = gb->background_palettes_rgb[0] = - gb->rgb_encode_callback(gb, 0xFF, 0xFF, 0xFF); - gb->sprite_palettes_rgb[5] = gb->sprite_palettes_rgb[1] = gb->background_palettes_rgb[1] = - gb->rgb_encode_callback(gb, 0xAA, 0xAA, 0xAA); - gb->sprite_palettes_rgb[6] = gb->sprite_palettes_rgb[2] = gb->background_palettes_rgb[2] = - gb->rgb_encode_callback(gb, 0x55, 0x55, 0x55); - gb->sprite_palettes_rgb[7] = gb->sprite_palettes_rgb[3] = gb->background_palettes_rgb[3] = - gb->rgb_encode_callback(gb, 0, 0, 0); - } + update_dmg_palette(gb); } reset_ram(gb); diff --git a/Core/gb.h b/Core/gb.h index c27b6c6..7831cb7 100644 --- a/Core/gb.h +++ b/Core/gb.h @@ -50,6 +50,17 @@ #error Unable to detect endianess #endif +typedef struct { + struct { + uint8_t r,g,b; + } colors[5]; +} GB_palette_t; + +extern const GB_palette_t GB_PALETTE_GREY; +extern const GB_palette_t GB_PALETTE_DMG; +extern const GB_palette_t GB_PALETTE_MGB; +extern const GB_palette_t GB_PALETTE_GBL; + typedef union { struct { uint8_t seconds; @@ -61,7 +72,6 @@ typedef union { uint8_t data[5]; } GB_rtc_time_t; - typedef enum { // GB_MODEL_DMG_0 = 0x000, // GB_MODEL_DMG_A = 0x001, @@ -513,6 +523,7 @@ struct GB_gameboy_internal_s { uint32_t *screen; uint32_t background_palettes_rgb[0x20]; uint32_t sprite_palettes_rgb[0x20]; + const GB_palette_t *dmg_palette; GB_color_correction_mode_t color_correction_mode; bool keys[4][GB_KEY_MAX]; @@ -696,6 +707,8 @@ void GB_set_infrared_callback(GB_gameboy_t *gb, GB_infrared_callback_t callback) void GB_set_rumble_callback(GB_gameboy_t *gb, GB_rumble_callback_t callback); void GB_set_update_input_hint_callback(GB_gameboy_t *gb, GB_update_input_hint_callback_t callback); +void GB_set_palette(GB_gameboy_t *gb, const GB_palette_t *palette); + /* These APIs are used when using internal clock */ void GB_set_serial_transfer_bit_start_callback(GB_gameboy_t *gb, GB_serial_transfer_bit_start_callback_t callback); void GB_set_serial_transfer_bit_end_callback(GB_gameboy_t *gb, GB_serial_transfer_bit_end_callback_t callback); From 046b09052cd54562de710c1577df05e18713800a Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Wed, 29 Jan 2020 15:36:19 +0200 Subject: [PATCH 27/30] Add DMG color palettes (SDL), add scrolling to SDL menus --- SDL/gui.c | 81 +++++++++++++++++++++++++++++++++++++++++------------- SDL/gui.h | 3 ++ SDL/main.c | 22 +++++++++++++++ 3 files changed, 87 insertions(+), 19 deletions(-) diff --git a/SDL/gui.c b/SDL/gui.c index db72c4d..d476175 100644 --- a/SDL/gui.c +++ b/SDL/gui.c @@ -175,8 +175,10 @@ static void draw_char(uint32_t *buffer, unsigned width, unsigned height, unsigne } } +static unsigned scroll = 0; static void draw_unbordered_text(uint32_t *buffer, unsigned width, unsigned height, unsigned x, unsigned y, const char *string, uint32_t color) { + y -= scroll; unsigned orig_x = x; while (*string) { if (*string == '\n') { @@ -297,6 +299,7 @@ static void return_to_root_menu(unsigned index) { current_menu = root_menu; current_selection = 0; + scroll = 0; } static void cycle_model(unsigned index) @@ -407,6 +410,7 @@ static void enter_emulation_menu(unsigned index) { current_menu = emulation_menu; current_selection = 0; + scroll = 0; } const char *current_scaling_mode(unsigned index) @@ -421,6 +425,12 @@ const char *current_color_correction_mode(unsigned index) [configuration.color_correction_mode]; } +const char *current_palette(unsigned index) +{ + return (const char *[]){"Greyscale", "Lime (Game Boy)", "Olive (Pocket)", "Teal (Light)"} + [configuration.dmg_palette]; +} + void cycle_scaling(unsigned index) { configuration.scaling_mode++; @@ -463,6 +473,26 @@ static void cycle_color_correction_backwards(unsigned index) } } +static void cycle_palette(unsigned index) +{ + if (configuration.dmg_palette == 3) { + configuration.dmg_palette = 0; + } + else { + configuration.dmg_palette++; + } +} + +static void cycle_palette_backwards(unsigned index) +{ + if (configuration.dmg_palette == 0) { + configuration.dmg_palette = 3; + } + else { + configuration.dmg_palette--; + } +} + struct shader_name { const char *file_name; const char *display_name; @@ -556,6 +586,7 @@ static const struct menu_item graphics_menu[] = { {"Scaling Mode:", cycle_scaling, current_scaling_mode, cycle_scaling_backwards}, {"Scaling Filter:", cycle_filter, current_filter_name, cycle_filter_backwards}, {"Color Correction:", cycle_color_correction, current_color_correction_mode, cycle_color_correction_backwards}, + {"Mono Palette:", cycle_palette, current_palette, cycle_palette_backwards}, {"Blend Frames:", toggle_blend_frames, blend_frames_string, toggle_blend_frames}, {"Back", return_to_root_menu}, {NULL,} @@ -565,6 +596,7 @@ static void enter_graphics_menu(unsigned index) { current_menu = graphics_menu; current_selection = 0; + scroll = 0; } const char *highpass_filter_string(unsigned index) @@ -601,6 +633,7 @@ static void enter_audio_menu(unsigned index) { current_menu = audio_menu; current_selection = 0; + scroll = 0; } static void modify_key(unsigned index) @@ -608,7 +641,6 @@ static void modify_key(unsigned index) gui_state = WAITING_FOR_KEY; } -static void enter_controls_menu_2(unsigned index); static const char *key_name(unsigned index); static const struct menu_item controls_menu[] = { @@ -620,12 +652,6 @@ static const struct menu_item controls_menu[] = { {"B:", modify_key, key_name,}, {"Select:", modify_key, key_name,}, {"Start:", modify_key, key_name,}, - {"Next Page", enter_controls_menu_2}, - {"Back", return_to_root_menu}, - {NULL,} -}; - -static const struct menu_item controls_menu_2[] = { {"Turbo:", modify_key, key_name,}, {"Rewind:", modify_key, key_name,}, {"Slow-Motion:", modify_key, key_name,}, @@ -635,11 +661,11 @@ static const struct menu_item controls_menu_2[] = { static const char *key_name(unsigned index) { - if (current_menu == controls_menu_2) { - if (index == 0) { + if (index >= 8) { + if (index == 8) { return SDL_GetScancodeName(configuration.keys[8]); } - return SDL_GetScancodeName(configuration.keys_2[index - 1]); + return SDL_GetScancodeName(configuration.keys_2[index - 9]); } return SDL_GetScancodeName(configuration.keys[index]); } @@ -648,12 +674,7 @@ static void enter_controls_menu(unsigned index) { current_menu = controls_menu; current_selection = 0; -} - -static void enter_controls_menu_2(unsigned index) -{ - current_menu = controls_menu_2; - current_selection = 0; + scroll = 0; } static unsigned joypad_index = 0; @@ -744,6 +765,7 @@ static void enter_joypad_menu(unsigned index) { current_menu = joypad_menu; current_selection = 0; + scroll = 0; } joypad_button_t get_joypad_button(uint8_t physical_button) @@ -826,6 +848,7 @@ void run_gui(bool is_running) bool should_render = true; current_menu = root_menu = is_running? paused_menu : nonpaused_menu; current_selection = 0; + scroll = 0; do { /* Convert Joypad and mouse events (We only generate down events) */ if (gui_state != WAITING_FOR_KEY && gui_state != WAITING_FOR_JBUTTON) { @@ -850,6 +873,7 @@ void run_gui(bool is_running) y = y * 8 / 7; y -= 144 / 16; } + y += scroll; if (x < 0 || x >= 160 || y < 24) { continue; @@ -1058,6 +1082,7 @@ void run_gui(bool is_running) gui_state = SHOWING_DROP_MESSAGE; } current_selection = 0; + scroll = 0; current_menu = root_menu; should_render = true; } @@ -1106,12 +1131,12 @@ void run_gui(bool is_running) should_render = true; } else if (gui_state == WAITING_FOR_KEY) { - if (current_menu == controls_menu_2) { - if (current_selection == 0) { + if (current_selection >= 8) { + if (current_selection == 8) { configuration.keys[8] = event.key.keysym.scancode; } else { - configuration.keys_2[current_selection - 1] = event.key.keysym.scancode; + configuration.keys_2[current_selection - 9] = event.key.keysym.scancode; } } else { @@ -1125,6 +1150,7 @@ void run_gui(bool is_running) if (should_render) { should_render = false; + rerender: if (width == 160 && height == 144) { memcpy(pixels, converted_background->pixels, sizeof(pixels)); } @@ -1144,6 +1170,16 @@ void run_gui(bool is_running) draw_text_centered(pixels, width, height, 8 + y_offset, "SameBoy", gui_palette_native[3], gui_palette_native[0], false); unsigned i = 0, y = 24; for (const struct menu_item *item = current_menu; item->string; item++, i++) { + if (i == current_selection) { + if (y < scroll) { + scroll = y - 4; + goto rerender; + } + } + if (i == current_selection && i == 0 && scroll != 0) { + scroll = 0; + goto rerender; + } if (item->value_getter && !item->backwards_handler) { char line[25]; snprintf(line, sizeof(line), "%s%*s", item->string, 24 - (int)strlen(item->string), item->value_getter(i)); @@ -1162,6 +1198,13 @@ void run_gui(bool is_running) y += 12; } } + if (i == current_selection) { + if (y > scroll + 144) { + scroll = y - 144; + goto rerender; + } + } + } break; case SHOWING_HELP: diff --git a/SDL/gui.h b/SDL/gui.h index b22c74f..ccfdfb9 100644 --- a/SDL/gui.h +++ b/SDL/gui.h @@ -100,6 +100,9 @@ typedef struct { SGB_2, SGB_MAX } sgb_revision; + + /* v0.13 */ + uint8_t dmg_palette; } configuration_t; extern configuration_t configuration; diff --git a/SDL/main.c b/SDL/main.c index 1646d5c..e83bfd8 100644 --- a/SDL/main.c +++ b/SDL/main.c @@ -92,6 +92,26 @@ static const char *end_capturing_logs(bool show_popup, bool should_exit) return captured_log; } +static void update_palette(void) +{ + switch (configuration.dmg_palette) { + case 1: + GB_set_palette(&gb, &GB_PALETTE_DMG); + break; + + case 2: + GB_set_palette(&gb, &GB_PALETTE_MGB); + break; + + case 3: + GB_set_palette(&gb, &GB_PALETTE_GBL); + break; + + default: + GB_set_palette(&gb, &GB_PALETTE_GREY); + } +} + static void open_menu(void) { bool audio_playing = SDL_GetAudioDeviceStatus(device_id) == SDL_AUDIO_PLAYING; @@ -105,6 +125,7 @@ static void open_menu(void) SDL_PauseAudioDevice(device_id, 0); } GB_set_color_correction_mode(&gb, configuration.color_correction_mode); + update_palette(); GB_set_highpass_filter_mode(&gb, configuration.highpass_mode); } @@ -454,6 +475,7 @@ restart: GB_set_rgb_encode_callback(&gb, rgb_encode); GB_set_sample_rate(&gb, have_aspec.freq); GB_set_color_correction_mode(&gb, configuration.color_correction_mode); + update_palette(); GB_set_highpass_filter_mode(&gb, configuration.highpass_mode); GB_set_rewind_length(&gb, configuration.rewind_length); GB_set_update_input_hint_callback(&gb, handle_events); From 99d2c0258c4da19b6b7a135bd9d0472388c79c33 Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Wed, 29 Jan 2020 15:51:53 +0200 Subject: [PATCH 28/30] Add monochrome LCD shader --- Cocoa/GBPreferencesWindow.m | 1 + Cocoa/Preferences.xib | 15 ++++++++------- SDL/gui.c | 1 + Shaders/MonoLCD.fsh | 38 +++++++++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 Shaders/MonoLCD.fsh diff --git a/Cocoa/GBPreferencesWindow.m b/Cocoa/GBPreferencesWindow.m index 8d3e73d..5c5d375 100644 --- a/Cocoa/GBPreferencesWindow.m +++ b/Cocoa/GBPreferencesWindow.m @@ -32,6 +32,7 @@ @"NearestNeighbor", @"Bilinear", @"SmoothBilinear", + @"MonoLCD", @"LCD", @"CRT", @"Scale2x", diff --git a/Cocoa/Preferences.xib b/Cocoa/Preferences.xib index 2c05a64..1062dae 100644 --- a/Cocoa/Preferences.xib +++ b/Cocoa/Preferences.xib @@ -1,8 +1,8 @@ - + - + @@ -17,7 +17,7 @@ - + @@ -104,7 +104,8 @@ - + + @@ -428,7 +429,7 @@ - + @@ -472,11 +473,11 @@ -