From ea05fa0c3e8256f387c810311ebbaaffe5c3b528 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Tue, 27 Jun 2023 16:41:59 +1000 Subject: [PATCH 1/5] CI: Update the 'nightly' tag along with the release. --- .github/workflows/build.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6083d50cb..08fb83c43 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -114,6 +114,10 @@ jobs: { github_rest DELETE "/repos/${GITHUB_REPOSITORY}/releases/${1}" } + github_delete_tag() + { + github_rest DELETE "/repos/${GITHUB_REPOSITORY}/git/refs/tags/${1}" + } github_create_release() { local payload="{ @@ -156,7 +160,12 @@ jobs: { release_id=$(github_get_release_id_for_tag nightly); status=$?; } || true # Delete existing nightly release if it exists. case ${status} in - 0) github_delete_release_by_id "${release_id}" ;; + 0) + github_delete_release_by_id "${release_id}" + # Deleting the 'nightly' release doesn't delete + # the 'nightly' tag, so let's do it manually. + github_delete_tag nightly + ;; 22) >&2 echo "No current nightly release; skipping tag deletion." ;; *) >&2 echo "API call failed unexpectedly." && exit 1 ;; esac From 18afbc37707c56d0c5cade7c3081e239ec283b24 Mon Sep 17 00:00:00 2001 From: Rupert Carmichael <5050061-carmiker@users.noreply.gitlab.com> Date: Fri, 4 Aug 2023 21:01:06 -0400 Subject: [PATCH 2/5] libretro: Support blargg's NTSC filter --- bsnes/target-libretro/libretro.cpp | 37 ++++++++++++-- bsnes/target-libretro/program.cpp | 80 ++++++++++++++++++++++++++++-- 2 files changed, 109 insertions(+), 8 deletions(-) diff --git a/bsnes/target-libretro/libretro.cpp b/bsnes/target-libretro/libretro.cpp index 31537e78a..a9eadd7c8 100644 --- a/bsnes/target-libretro/libretro.cpp +++ b/bsnes/target-libretro/libretro.cpp @@ -287,7 +287,32 @@ static void flush_variables() else run_ahead_frames = atoi(variable.value); } - + + variable = { "bsnes_video_filter", nullptr }; + if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &variable) && variable.value) + { + if (strcmp(variable.value, "None") == 0) { + program->filterRender = &Filter::None::render; + program->filterSize = &Filter::None::size; + } + else if (strcmp(variable.value, "NTSC (RF)") == 0) { + program->filterRender = &Filter::NTSC_RF::render; + program->filterSize = &Filter::NTSC_RF::size; + } + else if (strcmp(variable.value, "NTSC (Composite)") == 0) { + program->filterRender = &Filter::NTSC_Composite::render; + program->filterSize = &Filter::NTSC_Composite::size; + } + else if (strcmp(variable.value, "NTSC (S-Video)") == 0) { + program->filterRender = &Filter::NTSC_SVideo::render; + program->filterSize = &Filter::NTSC_SVideo::size; + } + else if (strcmp(variable.value, "NTSC (RGB)") == 0) { + program->filterRender = &Filter::NTSC_RGB::render; + program->filterSize = &Filter::NTSC_RGB::size; + } + } + // Refresh Geometry struct retro_system_av_info avinfo; retro_get_system_av_info(&avinfo); @@ -483,6 +508,7 @@ static void set_environment_info(retro_environment_t cb) { "bsnes_coprocessor_prefer_hle", "Coprocessor Prefer HLE; ON|OFF" }, { "bsnes_sgb_bios", "Preferred Super GameBoy BIOS (restart); SGB1.sfc|SGB2.sfc" }, { "bsnes_run_ahead_frames", "Amount of frames for run-ahead; OFF|1|2|3|4" }, + { "bsnes_video_filter", "Video Filter; None|NTSC (RF)|NTSC (Composite)|NTSC (S-Video)|NTSC (RGB)" }, { nullptr }, }; cb(RETRO_ENVIRONMENT_SET_VARIABLES, const_cast(vars)); @@ -653,13 +679,14 @@ RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code) RETRO_API bool retro_load_game(const retro_game_info *game) { - // bsnes uses 0RGB1555 internally but it is deprecated - // let software conversion happen in frontend - /*retro_pixel_format fmt = RETRO_PIXEL_FORMAT_0RGB1555; + retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888; if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) - return false;*/ + return false; emulator->configure("Audio/Frequency", SAMPLERATE); + program->filterRender = &Filter::None::render; + program->filterSize = &Filter::None::size; + program->updateVideoPalette(); flush_variables(); diff --git a/bsnes/target-libretro/program.cpp b/bsnes/target-libretro/program.cpp index 9f1019089..9a5b12b98 100644 --- a/bsnes/target-libretro/program.cpp +++ b/bsnes/target-libretro/program.cpp @@ -46,6 +46,7 @@ struct Program : Emulator::Platform auto openRomBSMemory(string name, vfs::file::mode mode) -> shared_pointer; auto hackPatchMemory(vector& data) -> void; + auto updateVideoPalette() -> void; string base_name; @@ -79,6 +80,13 @@ struct Program : Emulator::Platform struct BSMemory : Game { vector program; } bsMemory; + + uint32_t palette[32768]; + uint32_t paletteDimmed[32768]; + uint32_t videoOut[2304*2160]; + + Filter::Render filterRender; + Filter::Size filterSize; }; static Program *program = nullptr; @@ -157,6 +165,59 @@ auto Program::open(uint id, string name, vfs::file::mode mode, bool required) -> return result; } +auto Program::updateVideoPalette() -> void { + double luminance = 100.0 / 100.0; + double saturation = 100.0 / 100.0; + double gamma = 150.0 / 100.0; + + uint depth = 24; + + for(uint color : range(32768)) { + uint16 r = (color >> 10) & 31; + uint16 g = (color >> 5) & 31; + uint16 b = (color >> 0) & 31; + + r = r << 3 | r >> 2; r = r << 8 | r << 0; + g = g << 3 | g >> 2; g = g << 8 | g << 0; + b = b << 3 | b >> 2; b = b << 8 | b << 0; + + if(saturation != 1.0) { + uint16 grayscale = uclamp<16>((r + g + b) / 3); + double inverse = max(0.0, 1.0 - saturation); + r = uclamp<16>(r * saturation + grayscale * inverse); + g = uclamp<16>(g * saturation + grayscale * inverse); + b = uclamp<16>(b * saturation + grayscale * inverse); + } + + if(gamma != 1.0) { + double reciprocal = 1.0 / 32767.0; + r = r > 32767 ? r : uint16(32767 * pow(r * reciprocal, gamma)); + g = g > 32767 ? g : uint16(32767 * pow(g * reciprocal, gamma)); + b = b > 32767 ? b : uint16(32767 * pow(b * reciprocal, gamma)); + } + + if(luminance != 1.0) { + r = uclamp<16>(r * luminance); + g = uclamp<16>(g * luminance); + b = uclamp<16>(b * luminance); + } + + switch(depth) { + case 24: palette[color] = r >> 8 << 16 | g >> 8 << 8 | b >> 8 << 0; break; + case 30: palette[color] = r >> 6 << 20 | g >> 6 << 10 | b >> 6 << 0; break; + } + + r >>= 1; + g >>= 1; + b >>= 1; + + switch(depth) { + case 24: paletteDimmed[color] = r >> 8 << 16 | g >> 8 << 8 | b >> 8 << 0; break; + case 30: paletteDimmed[color] = r >> 6 << 20 | g >> 6 << 10 | b >> 6 << 0; break; + } + } +} + auto Program::load() -> void { emulator->unload(); emulator->load(); @@ -227,12 +288,12 @@ auto Program::load(uint id, string name, string type, vector options) -> { if (loadGameBoy(gameBoy.location)) { - return { id, NULL }; + return { id, "" }; } } else if (id == 3) { if (loadBSMemory(bsMemory.location)) { - return { id, NULL }; + return { id, "" }; } } return { id, options(0) }; @@ -245,7 +306,20 @@ auto Program::videoFrame(const uint16* data, uint pitch, uint width, uint height data += 8 * (pitch >> 1) * multiplier; height -= 16 * multiplier; } - video_cb(data, width, height, pitch); + + uint filterWidth = width, filterHeight = height; + + filterSize(filterWidth, filterHeight); + + // Scale the NTSC filter properly for HD Mode 7 + if ((scale > 1) && (filterWidth == 602)) + { + filterWidth = 301 * scale; + } + + filterRender(palette, videoOut, filterWidth << 2, (const uint16_t*)data, pitch, width, height); + + video_cb(videoOut, filterWidth, filterHeight, filterWidth << 2); } // Double the fun! From e3fcc35922a58ecc3181201752570fa50d6e2663 Mon Sep 17 00:00:00 2001 From: Rupert Carmichael <5050061-carmiker@users.noreply.gitlab.com> Date: Sun, 6 Aug 2023 20:53:56 -0400 Subject: [PATCH 3/5] libretro: Correctly apply filters for subsystems --- bsnes/target-libretro/libretro.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bsnes/target-libretro/libretro.cpp b/bsnes/target-libretro/libretro.cpp index a9eadd7c8..fc7f32118 100644 --- a/bsnes/target-libretro/libretro.cpp +++ b/bsnes/target-libretro/libretro.cpp @@ -718,7 +718,14 @@ RETRO_API bool retro_load_game(const retro_game_info *game) RETRO_API bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info) { + retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888; + if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt)) + return false; + emulator->configure("Audio/Frequency", SAMPLERATE); + program->filterRender = &Filter::None::render; + program->filterSize = &Filter::None::size; + program->updateVideoPalette(); flush_variables(); From 55925d91495d5df7021e778ee408d2909f3ed6d5 Mon Sep 17 00:00:00 2001 From: deadmeu Date: Sat, 16 Sep 2023 18:23:55 +1000 Subject: [PATCH 4/5] Update desktop entry comment field --- bsnes/target-bsnes/resource/bsnes.desktop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bsnes/target-bsnes/resource/bsnes.desktop b/bsnes/target-bsnes/resource/bsnes.desktop index 4e6a4a6b6..b48e1d369 100644 --- a/bsnes/target-bsnes/resource/bsnes.desktop +++ b/bsnes/target-bsnes/resource/bsnes.desktop @@ -1,6 +1,6 @@ [Desktop Entry] Name=bsnes -Comment=Emulator +Comment=SNES Emulator Exec=bsnes Icon=bsnes Terminal=false From dab534b6584e4debef2c9572e6b6588a604d79a9 Mon Sep 17 00:00:00 2001 From: Adrian Siekierka Date: Sun, 29 Oct 2023 20:16:41 +0100 Subject: [PATCH 5/5] wdc65816: fix PLB wrapping in emulation mode (#1277) >Regarding PLB, it looks like it reads from $200 and snes9x, mesen, bsnes, and the official CPU manual all got it wrong. Reproduced and verified on real hardware via https://github.com/gilyon/snes-tests --- bsnes/processor/wdc65816/instructions-other.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bsnes/processor/wdc65816/instructions-other.cpp b/bsnes/processor/wdc65816/instructions-other.cpp index c7290eaa6..01fb5cc4c 100755 --- a/bsnes/processor/wdc65816/instructions-other.cpp +++ b/bsnes/processor/wdc65816/instructions-other.cpp @@ -205,9 +205,10 @@ E S.h = 0x01; auto WDC65816::instructionPullB() -> void { idle(); idle(); -L B = pull(); +L B = pullN(); ZF = B == 0; NF = B & 0x80; +E S.h = 0x01; } auto WDC65816::instructionPullP() -> void {