mirror of
https://github.com/visualboyadvance-m/visualboyadvance-m
synced 2025-10-05 23:52:49 +02:00
Compare commits
81 Commits
v2.2.2
...
ede668b712
Author | SHA1 | Date | |
---|---|---|---|
|
ede668b712 | ||
|
5bd8904746 | ||
|
46326939eb | ||
|
3f005837dd | ||
|
2b3edb266a | ||
|
8e5fc43dd6 | ||
|
362ca53cbe | ||
|
9dc10ff6c4 | ||
|
ab01be3373 | ||
|
6ec0ba0610 | ||
|
9fcc0ad7a8 | ||
|
32622efc1e | ||
|
1dd5ba4567 | ||
|
2070f75934 | ||
|
89146a8597 | ||
|
043956753b | ||
|
e0eb3b3dab | ||
|
e3e14232f7 | ||
|
7565cac230 | ||
|
33c5aeb80e | ||
|
c5510ba28f | ||
|
96c23628ba | ||
|
37fb449fc9 | ||
|
7519c9b818 | ||
|
24b779c09e | ||
|
a17df26e52 | ||
|
b2dd03c6cb | ||
|
967426e2f0 | ||
|
ee2678c13c | ||
|
337e465741 | ||
|
5007977189 | ||
|
99f97138a2 | ||
|
5b867c1483 | ||
|
fe08f4d326 | ||
|
c334e3ffca | ||
|
35f8ba0b8f | ||
|
fca5fae329 | ||
|
56ea6456f5 | ||
|
0510656ca3 | ||
|
b92fcf7e31 | ||
|
22f381a19e | ||
|
e9fc6c8e13 | ||
|
bd20c79013 | ||
|
203be42665 | ||
|
d75072009b | ||
|
0e32b90002 | ||
|
2640716496 | ||
|
b065db66d9 | ||
|
4d837fd739 | ||
|
1ef356c6f0 | ||
|
a8c82bb4a1 | ||
|
1778d605f4 | ||
|
d6d2a83e7e | ||
|
881667a5f8 | ||
|
b332aa693d | ||
|
7f7035a07b | ||
|
3e355509e9 | ||
|
e68681ffda | ||
|
f83aa940d7 | ||
|
a18559678c | ||
|
d927594af2 | ||
|
06507775e8 | ||
|
b08ecd123d | ||
|
d154a6abc8 | ||
|
b134bacc45 | ||
|
9ae1473f36 | ||
|
9cd0c5c04c | ||
|
9e41c5476a | ||
|
e91171459d | ||
|
16f008b448 | ||
|
bad10342bd | ||
|
06b3cb094e | ||
|
82617ea75d | ||
|
0561ef91a4 | ||
|
afc6a1cc3a | ||
|
35df9d7647 | ||
|
031ae2ebf6 | ||
|
6242679e23 | ||
|
537393a0ab | ||
|
616f7abc4e | ||
|
f1414000e6 |
2
.github/workflows/macos-build.yml
vendored
2
.github/workflows/macos-build.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install nix
|
||||
uses: cachix/install-nix-action@v22
|
||||
uses: cachix/install-nix-action@v31
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-unstable
|
||||
|
||||
|
@@ -1,6 +1,17 @@
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
cmake_policy(VERSION 3.19...3.28.3)
|
||||
|
||||
# Use new link library de-duplication behavior.
|
||||
if(POLICY CMP0156)
|
||||
cmake_policy(SET CMP0156 NEW)
|
||||
endif()
|
||||
if(POLICY CMP0179)
|
||||
cmake_policy(SET CMP0179 NEW)
|
||||
endif()
|
||||
#if(POLICY CMP0181)
|
||||
# cmake_policy(SET CMP0181 NEW)
|
||||
#endif()
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
||||
|
||||
if(WIN32)
|
||||
|
@@ -2,6 +2,8 @@ if(TRANSLATIONS_ONLY)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# TODO: Use compiler CPU not CMake.
|
||||
|
||||
if(NOT CMAKE_SYSTEM_PROCESSOR)
|
||||
if(NOT CMAKE_TOOLCHAIN_FILE AND CMAKE_HOST_SYSTEM_PROCESSOR)
|
||||
set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_HOST_SYSTEM_PROCESSOR})
|
||||
@@ -71,14 +73,6 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "[aA][aA][rR][cC][hH]|[aA][rR][mM]")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(DEFINED VCPKG_TARGET_TRIPLET)
|
||||
string(REGEX MATCH "^[^-]+" target_arch ${VCPKG_TARGET_TRIPLET})
|
||||
|
||||
if(NOT WINARCH STREQUAL target_arch)
|
||||
message(FATAL_ERROR "Wrong build environment architecture for VCPKG_TARGET_TRIPLET, you specified ${target_arch} but your compiler is for ${WINARCH}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# We do not support amd64 asm yet
|
||||
if(X86_64 AND (ENABLE_ASM_CORE OR ENABLE_ASM_SCALERS OR ENABLE_MMX))
|
||||
message(FATAL_ERROR "The options ASM_CORE, ASM_SCALERS and MMX are not supported on X86_64 yet.")
|
||||
|
@@ -48,16 +48,20 @@ if((NOT ENABLE_SDL3) AND CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg")
|
||||
endif()
|
||||
|
||||
if(ENABLE_SDL3)
|
||||
if(VBAM_STATIC)
|
||||
set(VBAM_SDL_LIBS SDL3::SDL3-static ${SDL_LIBRARY_TEMP})
|
||||
if(UNIX AND NOT APPLE)
|
||||
set(VBAM_SDL_LIBS "${SDL3_LIBRARIES}")
|
||||
else()
|
||||
set(VBAM_SDL_LIBS SDL3::SDL3 ${SDL_LIBRARY_TEMP})
|
||||
if(VBAM_STATIC)
|
||||
set(VBAM_SDL_LIBS SDL3::SDL3-static ${SDL_LIBRARY_TEMP})
|
||||
else()
|
||||
set(VBAM_SDL_LIBS SDL3::SDL3 ${SDL_LIBRARY_TEMP})
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
if(VBAM_STATIC)
|
||||
set(VBAM_SDL_LIBS SDL2::SDL2-static ${SDL_LIBRARY_TEMP})
|
||||
set(VBAM_SDL_LIBS SDL2::SDL2-static ${SDL_LIBRARY_TEMP})
|
||||
else()
|
||||
set(VBAM_SDL_LIBS SDL2::SDL2 ${SDL_LIBRARY_TEMP})
|
||||
set(VBAM_SDL_LIBS SDL2::SDL2 ${SDL_LIBRARY_TEMP})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@@ -97,6 +97,11 @@ endmacro()
|
||||
|
||||
# Check for cached results. If there are skip the costly part.
|
||||
if (NOT FFMPEG_LIBRARIES)
|
||||
set(x265_lib "x265")
|
||||
|
||||
if(CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg" AND FFMPEG_STATIC)
|
||||
set(x265_lib "x265-static")
|
||||
endif()
|
||||
|
||||
# Check for all possible component.
|
||||
find_component(AVFORMAT libavformat avformat libavformat/avformat.h)
|
||||
@@ -108,7 +113,7 @@ if (NOT FFMPEG_LIBRARIES)
|
||||
find_component(POSTPROC libpostproc postproc libpostproc/postprocess.h)
|
||||
find_component(SWRESAMPLE libswresample swresample libswresample/swresample.h)
|
||||
find_component(X264 x264 x264 x264.h)
|
||||
find_component(X265 x265 x265 x265.h)
|
||||
find_component(X265 x265 "${x265_lib}" x265.h)
|
||||
|
||||
# Check if the required components were found and add their stuff to the FFMPEG_* vars.
|
||||
foreach (_component ${FFmpeg_FIND_COMPONENTS})
|
@@ -221,7 +221,7 @@ release notes.
|
||||
|
||||
Run the following commands to commit the change:
|
||||
|
||||
git commit -m'release ${new_tag}' --signoff -S
|
||||
git commit -a -m'release ${new_tag}' --signoff -S
|
||||
git tag -s -m'${new_tag}' ${new_tag}
|
||||
|
||||
To rollback these changes, run this command:
|
||||
|
@@ -40,15 +40,27 @@ if(VBAM_STATIC)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package(SDL3 QUIET)
|
||||
if(CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg")
|
||||
set(PKG_CONFIG_EXECUTABLE "$ENV{VCPKG_ROOT}/installed/x64-windows/tools/pkgconf/pkgconf.exe")
|
||||
endif()
|
||||
|
||||
find_package(PkgConfig)
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
pkg_check_modules(SDL3 sdl3 QUIET)
|
||||
else()
|
||||
find_package(SDL3 QUIET)
|
||||
endif()
|
||||
|
||||
option(ENABLE_SDL3 "Use SDL3" "${SDL3_FOUND}")
|
||||
|
||||
if(NOT TRANSLATIONS_ONLY)
|
||||
if(ENABLE_SDL3)
|
||||
find_package(SDL3 CONFIG REQUIRED)
|
||||
if(NOT UNIX)
|
||||
find_package(SDL3 REQUIRED)
|
||||
endif()
|
||||
else()
|
||||
find_package(SDL2 CONFIG REQUIRED)
|
||||
find_package(SDL2 REQUIRED)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -64,6 +76,18 @@ option(ENABLE_LZMA "Enable LZMA archive support" ON)
|
||||
if(ENABLE_SDL3)
|
||||
set(CMAKE_C_FLAGS "-DENABLE_SDL3 ${CMAKE_C_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "-DENABLE_SDL3 ${CMAKE_CXX_FLAGS}")
|
||||
|
||||
include(CheckSourceCompiles)
|
||||
check_source_compiles(CXX
|
||||
"#include <SDL3/SDL.h>
|
||||
|
||||
int main() { return SDL_SCALEMODE_PIXELART; }
|
||||
" HAVE_SDL_SCALEMODE_PIXELART)
|
||||
|
||||
if(HAVE_SDL_SCALEMODE_PIXELART)
|
||||
set(CMAKE_C_FLAGS "-DHAVE_SDL3_PIXELART ${CMAKE_C_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "-DHAVE_SDL3_PIXELART ${CMAKE_CXX_FLAGS}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(DISABLE_OPENGL)
|
||||
@@ -93,12 +117,6 @@ if(APPLE AND NOT DISABLE_MACOS_PACKAGE_MANAGERS)
|
||||
include(MacPackageManagers)
|
||||
endif()
|
||||
|
||||
if(CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg" AND CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "^([xX]86_64|[aA][mM][dD]64)$")
|
||||
set(PKG_CONFIG_EXECUTABLE "$ENV{VCPKG_ROOT}/installed/x64-windows/tools/pkgconf/pkgconf.exe")
|
||||
endif()
|
||||
|
||||
find_package(PkgConfig)
|
||||
|
||||
# Link / SFML
|
||||
if(NOT TRANSLATIONS_ONLY)
|
||||
set(ENABLE_LINK_DEFAULT ON)
|
||||
@@ -110,31 +128,25 @@ set(FFMPEG_DEFAULT OFF)
|
||||
set(FFMPEG_COMPONENTS AVFORMAT AVCODEC SWSCALE AVUTIL SWRESAMPLE X264 X265)
|
||||
set(FFMPEG_COMPONENT_VERSIONS AVFORMAT>=58.12.100 AVCODEC>=58.18.100 SWSCALE>=5.1.100 AVUTIL>=56.14.100 SWRESAMPLE>=3.1.100 X264>=0 X265>=0)
|
||||
|
||||
option(FIND_FFMPEG_APPLE "Find using Apple FFMPEG function" OFF)
|
||||
|
||||
if(NOT TRANSLATIONS_ONLY AND (NOT DEFINED ENABLE_FFMPEG OR ENABLE_FFMPEG))
|
||||
set(FFMPEG_DEFAULT ON)
|
||||
|
||||
if (APPLE OR FIND_FFMPEG_APPLE)
|
||||
find_package(AppleFFMPEG COMPONENTS ${FFMPEG_COMPONENTS})
|
||||
else()
|
||||
find_package(FFMPEG COMPONENTS ${FFMPEG_COMPONENTS})
|
||||
endif()
|
||||
find_package(FFmpeg COMPONENTS ${FFMPEG_COMPONENTS})
|
||||
|
||||
# check versions, but only if pkgconfig is available
|
||||
if(FFMPEG_FOUND AND PKG_CONFIG_FOUND AND NOT CMAKE_TOOLCHAIN_FILE MATCHES vcpkg)
|
||||
if(FFmpeg_FOUND AND PKG_CONFIG_FOUND AND NOT CMAKE_TOOLCHAIN_FILE MATCHES vcpkg)
|
||||
foreach(component ${FFMPEG_COMPONENT_VERSIONS})
|
||||
string(REPLACE ">=" ";" parts ${component})
|
||||
list(GET parts 0 name)
|
||||
list(GET parts 1 version)
|
||||
|
||||
if((NOT DEFINED ${name}_VERSION) OR ${name}_VERSION VERSION_LESS ${version})
|
||||
set(FFMPEG_FOUND OFF)
|
||||
set(FFmpeg_FOUND OFF)
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if(NOT FFMPEG_FOUND)
|
||||
if(NOT FFmpeg_FOUND)
|
||||
set(FFMPEG_DEFAULT OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
@@ -37,8 +37,48 @@ function(check_clean_exit var)
|
||||
set(${var} ${exit_status} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(try_wx_util var util conf_suffix major_version minor_version)
|
||||
unset(suffix)
|
||||
if(conf_suffix)
|
||||
set(suffix "-${conf_suffix}")
|
||||
endif()
|
||||
if(major_version)
|
||||
set(suffix "${suffix}-${major_version}")
|
||||
|
||||
if(NOT minor_version EQUAL -1)
|
||||
set(suffix "${suffix}.${minor_version}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# find_program caches the result
|
||||
set(exe NOTFOUND CACHE INTERNAL "" FORCE)
|
||||
find_program(exe NAMES "${util}${suffix}")
|
||||
|
||||
# try infix variant, as on FreeBSD
|
||||
if(NOT EXISTS "${exe}")
|
||||
string(REGEX REPLACE "^-" "" suffix "${suffix}")
|
||||
|
||||
string(REGEX REPLACE "-" "${suffix}-" try "${util}")
|
||||
|
||||
set(exe NOTFOUND CACHE INTERNAL "" FORCE)
|
||||
find_program(exe NAMES "${try}")
|
||||
endif()
|
||||
|
||||
if(EXISTS "${exe}")
|
||||
# check that the utility can be executed cleanly
|
||||
# in case we find e.g. the wrong architecture binary
|
||||
# when cross-compiling
|
||||
check_clean_exit(exit_status "${exe}" --help)
|
||||
|
||||
if(exit_status EQUAL 0)
|
||||
set("${var}" "${exe}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(find_wx_util var util)
|
||||
if(WIN32 OR EXISTS /etc/gentoo-release)
|
||||
if((WIN32 AND (NOT CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg")) OR EXISTS /etc/gentoo-release)
|
||||
# On win32, including cross builds we prefer the plain utility
|
||||
# name first from PATH, with the exception of -static for static
|
||||
# builds.
|
||||
@@ -57,48 +97,34 @@ function(find_wx_util var util)
|
||||
set(major_versions ";")
|
||||
endif()
|
||||
|
||||
list(APPEND conf_suffixes gtk4u gtk4 gtk3u gtk3 gtk2u gtk2 "")
|
||||
list(APPEND major_versions 4 3 2 "")
|
||||
list(APPEND conf_suffixes "" gtk3u gtk3 gtk2u gtk2)
|
||||
list(APPEND major_versions "" 3)
|
||||
|
||||
get_target_property(wx_base_lib_prop wx::base LOCATION)
|
||||
string(STRIP "${wx_base_lib_prop}" wx_base_lib)
|
||||
|
||||
if(wx_base_lib MATCHES "wx_baseu?-([0-9]+)\\.([0-9]+)\\.")
|
||||
set(lib_major "${CMAKE_MATCH_1}")
|
||||
set(lib_minor "${CMAKE_MATCH_2}")
|
||||
endif()
|
||||
|
||||
foreach(conf_suffix IN LISTS conf_suffixes)
|
||||
if(lib_major AND lib_minor)
|
||||
try_wx_util(exe "${util}" "${conf_suffix}" "${lib_major}" "${lib_minor}")
|
||||
|
||||
if(exe)
|
||||
set("${var}" "${exe}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
foreach(major_version IN LISTS major_versions)
|
||||
foreach(minor_version RANGE 100 -1 -1)
|
||||
unset(suffix)
|
||||
if(conf_suffix)
|
||||
set(suffix "-${conf_suffix}")
|
||||
endif()
|
||||
if(major_version)
|
||||
set(suffix "${suffix}-${major_version}")
|
||||
foreach(minor_version RANGE 30 -1 -1)
|
||||
try_wx_util(exe "${util}" "${conf_suffix}" "${major_version}" "${minor_version}")
|
||||
|
||||
if(NOT minor_version EQUAL -1)
|
||||
set(suffix "${suffix}.${minor_version}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# find_program caches the result
|
||||
set(exe NOTFOUND CACHE INTERNAL "" FORCE)
|
||||
find_program(exe NAMES "${util}${suffix}")
|
||||
|
||||
# try infix variant, as on FreeBSD
|
||||
if(NOT EXISTS ${exe})
|
||||
string(REGEX REPLACE "^-" "" suffix "${suffix}")
|
||||
|
||||
string(REGEX REPLACE "-" "${suffix}-" try ${util})
|
||||
|
||||
set(exe NOTFOUND CACHE INTERNAL "" FORCE)
|
||||
find_program(exe NAMES ${try})
|
||||
endif()
|
||||
|
||||
if(EXISTS ${exe})
|
||||
# check that the utility can be executed cleanly
|
||||
# in case we find e.g. the wrong architecture binary
|
||||
# when cross-compiling
|
||||
check_clean_exit(exit_status ${exe} --help)
|
||||
|
||||
if(exit_status EQUAL 0)
|
||||
set(${var} ${exe} PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(exe)
|
||||
set("${var}" "${exe}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# don't iterate over minor versions for empty major version
|
||||
|
@@ -2,7 +2,7 @@ with import <nixpkgs> {};
|
||||
stdenv.mkDerivation {
|
||||
name = "visualboyadvance-m";
|
||||
buildInputs = if stdenv.isDarwin then
|
||||
[ ninja cmake nasm faudio gettext libintl libtiff pkg-config zip zlib openal ffmpeg wxGTK32 sdl3 pcre pcre2 darwin.apple_sdk.frameworks.System darwin.apple_sdk.frameworks.IOKit darwin.apple_sdk.frameworks.Carbon darwin.apple_sdk.frameworks.Cocoa darwin.apple_sdk.frameworks.QuartzCore darwin.apple_sdk.frameworks.AudioToolbox darwin.apple_sdk.frameworks.OpenGL darwin.apple_sdk.frameworks.OpenAL llvmPackages_latest.clang llvmPackages_latest.bintools ]
|
||||
[ ninja cmake nasm faudio gettext libintl libtiff pkg-config zip zlib openal ffmpeg wxGTK32 sdl3 pcre pcre2 llvmPackages_latest.clang llvmPackages_latest.bintools ]
|
||||
else
|
||||
[ ninja cmake gcc clang llvm llvmPackages.libcxx nasm faudio gettext libintl libtiff pkg-config zip zlib openal ffmpeg wxGTK32 libGL libGLU glfw sdl3 gtk3-x11 pcre pcre2 util-linuxMinimal libselinux libsepol libthai libdatrie xorg.libXdmcp xorg.libXtst libxkbcommon libepoxy dbus at-spi2-core ];
|
||||
}
|
||||
|
@@ -342,9 +342,12 @@ debian_installdeps() {
|
||||
;;
|
||||
esac
|
||||
|
||||
pkgs="build-essential g++ nasm cmake ccache gettext zlib1g-dev libgl1-mesa-dev libgettextpo-dev libsdl3-dev libglu1-mesa-dev libglu1-mesa libgles2-mesa-dev $glew_lib $wx_libs libgtk2.0-dev libgtk-3-dev ccache zip ninja-build libopenal-dev"
|
||||
sdl_lib=$(apt-cache search libsdl3-dev | grep libsdl3-dev | awk '{ print $1 }')
|
||||
[ -z "$sdl_lib" ] && sdl_lib=libsdl2-dev
|
||||
|
||||
[ -n "$ENABLE_FFMPEG" ] && pkgs="$pkgs libavcodec-dev libavformat-dev libswscale-dev libavutil-dev $libswresample_dev"
|
||||
pkgs="build-essential g++ nasm cmake ccache gettext zlib1g-dev libgl1-mesa-dev libgettextpo-dev $sdl_lib libglu1-mesa-dev libglu1-mesa libgles2-mesa-dev $glew_lib $wx_libs libgtk2.0-dev libgtk-3-dev ccache zip ninja-build libopenal-dev"
|
||||
|
||||
[ -n "$ENABLE_FFMPEG" ] && pkgs="$pkgs libavcodec-dev libavformat-dev libswscale-dev libavutil-dev $libswresample_dev libx264-dev libx265-dev"
|
||||
|
||||
check sudo apt-get -qy install $pkgs
|
||||
else
|
||||
|
673
po/wxvbam/bg.po
673
po/wxvbam/bg.po
File diff suppressed because it is too large
Load Diff
673
po/wxvbam/br.po
673
po/wxvbam/br.po
File diff suppressed because it is too large
Load Diff
673
po/wxvbam/cs.po
673
po/wxvbam/cs.po
File diff suppressed because it is too large
Load Diff
4134
po/wxvbam/de.po
4134
po/wxvbam/de.po
File diff suppressed because it is too large
Load Diff
673
po/wxvbam/el.po
673
po/wxvbam/el.po
File diff suppressed because it is too large
Load Diff
745
po/wxvbam/es.po
745
po/wxvbam/es.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
673
po/wxvbam/gl.po
673
po/wxvbam/gl.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1578
po/wxvbam/id.po
1578
po/wxvbam/id.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
673
po/wxvbam/ja.po
673
po/wxvbam/ja.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
673
po/wxvbam/nb.po
673
po/wxvbam/nb.po
File diff suppressed because it is too large
Load Diff
673
po/wxvbam/nl.po
673
po/wxvbam/nl.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
925
po/wxvbam/sv.po
925
po/wxvbam/sv.po
File diff suppressed because it is too large
Load Diff
673
po/wxvbam/tr.po
673
po/wxvbam/tr.po
File diff suppressed because it is too large
Load Diff
551
po/wxvbam/uk.po
551
po/wxvbam/uk.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -2,5 +2,6 @@ add_subdirectory(av_recording)
|
||||
add_subdirectory(draw_text)
|
||||
add_subdirectory(filters)
|
||||
add_subdirectory(filters_agb)
|
||||
add_subdirectory(filters_cgb)
|
||||
add_subdirectory(filters_interframe)
|
||||
add_subdirectory(user_config)
|
||||
|
@@ -278,7 +278,7 @@ recording::MediaRet recording::MediaRecorder::setup_video_stream_info(int width,
|
||||
switch (pixsize)
|
||||
{
|
||||
case 1:
|
||||
tbord = 1; rbord = 2;
|
||||
tbord = 1; rbord = 4;
|
||||
break;
|
||||
case 2:
|
||||
// 16-bit: 2 @ right, 1 @ top
|
||||
|
@@ -26,10 +26,6 @@ extern "C"
|
||||
bool cpu_mmx = 1;
|
||||
#endif
|
||||
}
|
||||
static uint32_t colorMask = 0xF7DEF7DE;
|
||||
static uint32_t lowPixelMask = 0x08210821;
|
||||
static uint32_t qcolorMask = 0xE79CE79C;
|
||||
static uint32_t qlowpixelMask = 0x18631863;
|
||||
static uint32_t redblueMask = 0xF81F;
|
||||
static uint32_t greenMask = 0x7E0;
|
||||
|
||||
@@ -41,20 +37,12 @@ int Init_2xSaI(uint32_t BitFormat)
|
||||
{
|
||||
if(systemColorDepth == 16) {
|
||||
if (BitFormat == 565) {
|
||||
colorMask = 0xF7DEF7DE;
|
||||
lowPixelMask = 0x08210821;
|
||||
qcolorMask = 0xE79CE79C;
|
||||
qlowpixelMask = 0x18631863;
|
||||
redblueMask = 0xF81F;
|
||||
greenMask = 0x7E0;
|
||||
qRGB_COLOR_MASK[0] = qRGB_COLOR_MASK[1] = 0xF7DEF7DE;
|
||||
hq2x_init(16);
|
||||
RGB_LOW_BITS_MASK = 0x0821;
|
||||
} else if (BitFormat == 555) {
|
||||
colorMask = 0x7BDE7BDE;
|
||||
lowPixelMask = 0x04210421;
|
||||
qcolorMask = 0x739C739C;
|
||||
qlowpixelMask = 0x0C630C63;
|
||||
redblueMask = 0x7C1F;
|
||||
greenMask = 0x3E0;
|
||||
qRGB_COLOR_MASK[0] = qRGB_COLOR_MASK[1] = 0x7BDE7BDE;
|
||||
@@ -64,10 +52,6 @@ int Init_2xSaI(uint32_t BitFormat)
|
||||
return 0;
|
||||
}
|
||||
} else if(systemColorDepth == 32) {
|
||||
colorMask = 0xfefefe;
|
||||
lowPixelMask = 0x010101;
|
||||
qcolorMask = 0xfcfcfc;
|
||||
qlowpixelMask = 0x030303;
|
||||
qRGB_COLOR_MASK[0] = qRGB_COLOR_MASK[1] = 0xfefefe;
|
||||
hq2x_init(32);
|
||||
RGB_LOW_BITS_MASK = 0x010101;
|
||||
@@ -146,25 +130,24 @@ static inline int GetResult (uint32_t A, uint32_t B, uint32_t C, uint32_t D)
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline uint32_t INTERPOLATE (uint32_t A, uint32_t B)
|
||||
{
|
||||
if (A != B) {
|
||||
return (((A & colorMask) >> 1) + ((B & colorMask) >> 1) +
|
||||
(A & B & lowPixelMask));
|
||||
} else
|
||||
return A;
|
||||
static inline uint32_t INTERPOLATE(uint32_t A, uint32_t B) {
|
||||
if (A == B) {
|
||||
return A;
|
||||
}
|
||||
return (
|
||||
(((((A >> 16) & 0xFF) & 0xFE) >> 1) + ((((B >> 16) & 0xFF) & 0xFE) >> 1) + (((A >> 16) & 0xFF) & ((B >> 16) & 0xFF) & 0x01)) << 16) |
|
||||
((((((A >> 8) & 0xFF) & 0xFE) >> 1) + ((((B >> 8) & 0xFF) & 0xFE) >> 1) + (((A >> 8) & 0xFF) & ((B >> 8) & 0xFF) & 0x01)) << 8) |
|
||||
(((((A & 0xFF) & 0xFE) >> 1) + (((B & 0xFF) & 0xFE) >> 1) + ((A & 0xFF) & (B & 0xFF) & 0x01)));
|
||||
}
|
||||
|
||||
static inline uint32_t Q_INTERPOLATE (uint32_t A, uint32_t B, uint32_t C, uint32_t D)
|
||||
{
|
||||
uint32_t x = ((A & qcolorMask) >> 2) +
|
||||
((B & qcolorMask) >> 2) +
|
||||
((C & qcolorMask) >> 2) + ((D & qcolorMask) >> 2);
|
||||
uint32_t y = (A & qlowpixelMask) +
|
||||
(B & qlowpixelMask) + (C & qlowpixelMask) + (D & qlowpixelMask);
|
||||
|
||||
y = (y >> 2) & qlowpixelMask;
|
||||
return x + y;
|
||||
static inline uint32_t Q_INTERPOLATE(uint32_t A, uint32_t B, uint32_t C, uint32_t D) {
|
||||
return (
|
||||
(((((A >> 16) & 0xFC) >> 2) + (((B >> 16) & 0xFC) >> 2) + (((C >> 16) & 0xFC) >> 2) + (((D >> 16) & 0xFC) >> 2) +
|
||||
(((A >> 16) & 0x03) + ((B >> 16) & 0x03) + ((C >> 16) & 0x03) + ((D >> 16) & 0x03))) << 16) |
|
||||
(((((A >> 8) & 0xFC) >> 2) + (((B >> 8) & 0xFC) >> 2) + (((C >> 8) & 0xFC) >> 2) + (((D >> 8) & 0xFC) >> 2) +
|
||||
(((A >> 8) & 0x03) + ((B >> 8) & 0x03) + ((C >> 8) & 0x03) + ((D >> 8) & 0x03))) << 8) |
|
||||
((((A & 0xFC) >> 2) + ((B & 0xFC) >> 2) + ((C & 0xFC) >> 2) + ((D & 0xFC) >> 2) +
|
||||
((A & 0x03) + (B & 0x03) + (C & 0x03) + (D & 0x03)))));
|
||||
}
|
||||
|
||||
static inline int GetResult1_32 (uint32_t A, uint32_t B, uint32_t C, uint32_t D,
|
||||
@@ -1275,4 +1258,3 @@ void Scale_2xSaI (uint8_t *srcPtr, uint32_t srcPitch, uint8_t * /* deltaPtr */,
|
||||
dstPtr += dstPitch;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,17 @@
|
||||
/*
|
||||
* GBA Color Correction Shader Implementation
|
||||
*
|
||||
* Shader modified by Pokefan531.
|
||||
* Color Mangler
|
||||
* Original Author: hunterk
|
||||
* Original License: Public domain
|
||||
*
|
||||
* This code is adapted from the original shader logic.
|
||||
*/
|
||||
|
||||
#include "components/filters_agb/filters_agb.h"
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
extern int systemColorDepth;
|
||||
extern int systemRedShift;
|
||||
@@ -9,272 +22,332 @@ extern uint8_t systemColorMap8[0x10000];
|
||||
extern uint16_t systemColorMap16[0x10000];
|
||||
extern uint32_t systemColorMap32[0x10000];
|
||||
|
||||
static const unsigned char curve[32] = { 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0e, 0x10, 0x12,
|
||||
0x14, 0x16, 0x18, 0x1c, 0x20, 0x28, 0x30, 0x38,
|
||||
0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x80,
|
||||
0x88, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0 };
|
||||
// --- Global Constants and Variables for GBA Color Correction ---
|
||||
// Define the color profile matrix as a static const float 2D array
|
||||
// This replicates the column-major order of GLSL mat4 for easier translation.
|
||||
// Format: { {col0_row0, col0_row1, col0_row2, col0_row3}, ... }
|
||||
static const float GBA_sRGB[4][4] = {
|
||||
{0.905f, 0.10f, 0.1575f, 0.0f}, // Column 0 (R output contributions from R, G, B, A)
|
||||
{0.195f, 0.65f, 0.1425f, 0.0f}, // Column 1 (G output contributions from R, G, B, A)
|
||||
{-0.10f, 0.25f, 0.70f, 0.0f}, // Column 2 (B output contributions from R, G, B, A)
|
||||
{0.0f, 0.0f, 0.0f, 0.91f} // Column 3 (A/Luminance contribution)
|
||||
};
|
||||
|
||||
// output R G B
|
||||
static const unsigned char influence[3 * 3] = { 16, 4, 4, // red
|
||||
8, 16, 8, // green
|
||||
0, 8, 16 }; // blue
|
||||
static const float GBA_DCI[4][4] = {
|
||||
{0.76f, 0.125f, 0.16f, 0.0f},
|
||||
{0.27f, 0.6375f, 0.18f, 0.0f},
|
||||
{-0.03f, 0.2375f, 0.66f, 0.0f},
|
||||
{0.0f, 0.0f, 0.0f, 0.97f}
|
||||
};
|
||||
|
||||
inline void swap(short& a, short& b)
|
||||
{
|
||||
short temp = a;
|
||||
a = b;
|
||||
b = temp;
|
||||
static const float GBA_Rec2020[4][4] = {
|
||||
{0.61f, 0.155f, 0.16f, 0.0f},
|
||||
{0.345f, 0.615f, 0.1875f, 0.0f},
|
||||
{0.045f, 0.23f, 0.6525f, 0.0f},
|
||||
{0.0f, 0.0f, 0.0f, 1.0f}
|
||||
};
|
||||
|
||||
// Screen darkening factor. Default to 0.0f
|
||||
static float darken_screen = 0.0f;
|
||||
|
||||
// Color mode (0 for sRGB, 1 for DCI, 2 for Rec2020). Default to sRGB (0).
|
||||
static int color_mode = 0;
|
||||
|
||||
// Pointer to the currently selected color profile matrix.
|
||||
static const float (*profile)[4];
|
||||
|
||||
// Global constants from the shader for gamma correction values
|
||||
static const float target_gamma = 2.2f;
|
||||
static const float display_gamma = 2.2f;
|
||||
|
||||
|
||||
// --- Function Implementations ---
|
||||
|
||||
// Forward declaration of a helper function to set the profile based on color_mode
|
||||
static void set_profile_from_mode();
|
||||
|
||||
// This constructor-like function runs once when the program starts.
|
||||
struct GbafilterInitializer {
|
||||
GbafilterInitializer() {
|
||||
set_profile_from_mode();
|
||||
}
|
||||
};
|
||||
static GbafilterInitializer __gbafilter_initializer;
|
||||
|
||||
|
||||
// Helper function to set the 'profile' pointer based on the 'color_mode' variable.
|
||||
static void set_profile_from_mode() {
|
||||
if (color_mode == 0) {
|
||||
profile = GBA_sRGB;
|
||||
}
|
||||
else if (color_mode == 1) {
|
||||
profile = GBA_DCI;
|
||||
}
|
||||
else if (color_mode == 2) {
|
||||
profile = GBA_Rec2020;
|
||||
}
|
||||
else {
|
||||
profile = GBA_sRGB; // Default to sRGB if an invalid mode is set
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Public function to set color mode and darken screen from external calls
|
||||
void gbafilter_set_params(int new_color_mode, float new_darken_screen) {
|
||||
color_mode = new_color_mode;
|
||||
darken_screen = fmaxf(0.0f, fminf(1.0f, new_darken_screen)); // Clamp to 0.0-1.0
|
||||
|
||||
// Call the helper to update 'profile' based on the new 'color_mode'
|
||||
set_profile_from_mode();
|
||||
}
|
||||
|
||||
void gbafilter_update_colors(bool lcd) {
|
||||
switch (systemColorDepth) {
|
||||
case 8: {
|
||||
for (int i = 0; i < 0x10000; i++) {
|
||||
systemColorMap8[i] = (uint8_t)((((i & 0x1f) << 3) & 0xE0) |
|
||||
((((i & 0x3e0) >> 5) << 0) & 0x1C) |
|
||||
((((i & 0x7c00) >> 10) >> 3) & 0x3));
|
||||
}
|
||||
} break;
|
||||
case 16: {
|
||||
for (int i = 0; i < 0x10000; i++) {
|
||||
systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
|
||||
(((i & 0x3e0) >> 5) << systemGreenShift) |
|
||||
(((i & 0x7c00) >> 10) << systemBlueShift);
|
||||
}
|
||||
if (lcd)
|
||||
gbafilter_pal(systemColorMap16, 0x10000);
|
||||
} break;
|
||||
case 24:
|
||||
case 32: {
|
||||
for (int i = 0; i < 0x10000; i++) {
|
||||
systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
|
||||
(((i & 0x3e0) >> 5) << systemGreenShift) |
|
||||
(((i & 0x7c00) >> 10) << systemBlueShift);
|
||||
}
|
||||
if (lcd)
|
||||
gbafilter_pal32(systemColorMap32, 0x10000);
|
||||
} break;
|
||||
case 8: {
|
||||
for (int i = 0; i < 0x10000; i++) {
|
||||
systemColorMap8[i] = (uint8_t)((((i & 0x1f) << 3) & 0xE0) |
|
||||
((((i & 0x3e0) >> 5) << 0) & 0x1C) |
|
||||
((((i & 0x7c00) >> 10) >> 3) & 0x3));
|
||||
}
|
||||
if (lcd)
|
||||
gbafilter_pal8(systemColorMap8, 0x10000);
|
||||
} break;
|
||||
case 16: {
|
||||
for (int i = 0x0; i < 0x10000; i++) {
|
||||
systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
|
||||
(((i & 0x3e0) >> 5) << systemGreenShift) |
|
||||
(((i & 0x7c00) >> 10) << systemBlueShift);
|
||||
}
|
||||
if (lcd)
|
||||
gbafilter_pal(systemColorMap16, 0x10000);
|
||||
} break;
|
||||
case 24:
|
||||
case 32: {
|
||||
for (int i = 0; i < 0x10000; i++) {
|
||||
systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
|
||||
(((i & 0x3e0) >> 5) << systemGreenShift) |
|
||||
(((i & 0x7c00) >> 10) << systemBlueShift);
|
||||
}
|
||||
if (lcd)
|
||||
gbafilter_pal32(systemColorMap32, 0x10000);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void gbafilter_pal8(uint8_t* buf, int count)
|
||||
{
|
||||
// Pre-calculate constants for efficiency within function scope
|
||||
const float target_gamma_exponent = target_gamma + darken_screen;
|
||||
const float display_gamma_reciprocal = 1.0f / display_gamma;
|
||||
const float luminance_factor = profile[3][3]; // profile[3].w from GLSL
|
||||
|
||||
while (count--) {
|
||||
uint8_t pix = *buf;
|
||||
|
||||
uint8_t original_r_val_3bit = (uint8_t)((pix & 0xE0) >> 5);
|
||||
uint8_t original_g_val_3bit = (uint8_t)((pix & 0x1C) >> 2);
|
||||
uint8_t original_b_val_2bit = (uint8_t)(pix & 0x3);
|
||||
|
||||
// Normalize to 0.0-1.0 for calculations
|
||||
float r = (float)original_r_val_3bit / 7.0f;
|
||||
float g = (float)original_g_val_3bit / 7.0f;
|
||||
float b = (float)original_b_val_2bit / 3.0f;
|
||||
|
||||
// 1. Apply initial gamma (including darken_screen as exponent) to convert to linear space.
|
||||
// This step will affect non-"white" values.
|
||||
r = powf(r, target_gamma_exponent);
|
||||
g = powf(g, target_gamma_exponent);
|
||||
b = powf(b, target_gamma_exponent);
|
||||
|
||||
// 2. Apply luminance factor and clamp.
|
||||
r = fmaxf(0.0f, fminf(1.0f, r * luminance_factor));
|
||||
g = fmaxf(0.0f, fminf(1.0f, g * luminance_factor));
|
||||
b = fmaxf(0.0f, fminf(1.0f, b * luminance_factor));
|
||||
|
||||
// 3. Apply color profile matrix (using profile[column][row] access)
|
||||
float transformed_r = profile[0][0] * r + profile[1][0] * g + profile[2][0] * b;
|
||||
float transformed_g = profile[0][1] * r + profile[1][1] * g + profile[2][1] * b;
|
||||
float transformed_b = profile[0][2] * r + profile[1][2] * g + profile[2][2] * b;
|
||||
|
||||
// 4. Apply display gamma to convert back for display.
|
||||
transformed_r = copysignf(powf(fabsf(transformed_r), display_gamma_reciprocal), transformed_r);
|
||||
transformed_g = copysignf(powf(fabsf(transformed_g), display_gamma_reciprocal), transformed_g);
|
||||
transformed_b = copysignf(powf(fabsf(transformed_b), display_gamma_reciprocal), transformed_b);
|
||||
|
||||
// Final clamp: ensure values are within 0.0-1.0 range
|
||||
transformed_r = fmaxf(0.0f, fminf(1.0f, transformed_r));
|
||||
transformed_g = fmaxf(0.0f, fminf(1.0f, transformed_g));
|
||||
transformed_b = fmaxf(0.0f, fminf(1.0f, transformed_b));
|
||||
|
||||
// Convert back to 3-bit or 2-bit (0-7 or 0-3) integer and combine into uint8_t
|
||||
// Apply 5-bit to 5-bit conversion, as this palette is for 16-bit output.
|
||||
uint8_t final_red = (uint8_t)(transformed_r * 7.0f + 0.5f);
|
||||
uint8_t final_green = (uint8_t)(transformed_g * 7.0f + 0.5f);
|
||||
uint8_t final_blue = (uint8_t)(transformed_b * 3.0f + 0.5f);
|
||||
|
||||
// Ensure values are strictly within 0-7 or 0-3 range after rounding
|
||||
if (final_red > 7) final_red = 7;
|
||||
if (final_green > 7) final_green = 7;
|
||||
if (final_blue > 3) final_blue = 3;
|
||||
|
||||
*buf++ = ((final_red & 0x7) << 5) |
|
||||
((final_green & 0x7) << 2) |
|
||||
(final_blue & 0x3);
|
||||
}
|
||||
}
|
||||
|
||||
void gbafilter_pal(uint16_t* buf, int count)
|
||||
{
|
||||
short temp[3 * 3], s;
|
||||
uint16_t pix;
|
||||
uint8_t red, green, blue;
|
||||
// Pre-calculate constants for efficiency within function scope
|
||||
const float target_gamma_exponent = target_gamma + darken_screen;
|
||||
const float display_gamma_reciprocal = 1.0f / display_gamma;
|
||||
const float luminance_factor = profile[3][3]; // profile[3].w from GLSL
|
||||
|
||||
while (count--) {
|
||||
pix = *buf;
|
||||
uint16_t pix = *buf;
|
||||
|
||||
s = curve[(pix >> systemGreenShift) & 0x1f];
|
||||
temp[3] = s * influence[3];
|
||||
temp[4] = s * influence[4];
|
||||
temp[5] = s * influence[5];
|
||||
uint8_t original_r_val_5bit = (uint8_t)((pix >> systemRedShift) & 0x1f);
|
||||
uint8_t original_g_val_5bit = (uint8_t)((pix >> systemGreenShift) & 0x1f);
|
||||
uint8_t original_b_val_5bit = (uint8_t)((pix >> systemBlueShift) & 0x1f);
|
||||
|
||||
s = curve[(pix >> systemRedShift) & 0x1f];
|
||||
temp[0] = s * influence[0];
|
||||
temp[1] = s * influence[1];
|
||||
temp[2] = s * influence[2];
|
||||
// Normalize to 0.0-1.0 for calculations
|
||||
float r = (float)original_r_val_5bit / 31.0f;
|
||||
float g = (float)original_g_val_5bit / 31.0f;
|
||||
float b = (float)original_b_val_5bit / 31.0f;
|
||||
|
||||
s = curve[(pix >> systemBlueShift) & 0x1f];
|
||||
temp[6] = s * influence[6];
|
||||
temp[7] = s * influence[7];
|
||||
temp[8] = s * influence[8];
|
||||
// 1. Apply initial gamma (including darken_screen as exponent) to convert to linear space.
|
||||
// This step will affect non-"white" values.
|
||||
r = powf(r, target_gamma_exponent);
|
||||
g = powf(g, target_gamma_exponent);
|
||||
b = powf(b, target_gamma_exponent);
|
||||
|
||||
if (temp[0] < temp[3])
|
||||
swap(temp[0], temp[3]);
|
||||
if (temp[0] < temp[6])
|
||||
swap(temp[0], temp[6]);
|
||||
if (temp[3] < temp[6])
|
||||
swap(temp[3], temp[6]);
|
||||
temp[3] <<= 1;
|
||||
temp[0] <<= 2;
|
||||
temp[0] += temp[3] + temp[6];
|
||||
// 2. Apply luminance factor and clamp.
|
||||
r = fmaxf(0.0f, fminf(1.0f, r * luminance_factor));
|
||||
g = fmaxf(0.0f, fminf(1.0f, g * luminance_factor));
|
||||
b = fmaxf(0.0f, fminf(1.0f, b * luminance_factor));
|
||||
|
||||
red = ((int(temp[0]) * 160) >> 17) + 4;
|
||||
if (red > 31)
|
||||
red = 31;
|
||||
// 3. Apply color profile matrix (using profile[column][row] access)
|
||||
float transformed_r = profile[0][0] * r + profile[1][0] * g + profile[2][0] * b;
|
||||
float transformed_g = profile[0][1] * r + profile[1][1] * g + profile[2][1] * b;
|
||||
float transformed_b = profile[0][2] * r + profile[1][2] * g + profile[2][2] * b;
|
||||
|
||||
if (temp[2] < temp[5])
|
||||
swap(temp[2], temp[5]);
|
||||
if (temp[2] < temp[8])
|
||||
swap(temp[2], temp[8]);
|
||||
if (temp[5] < temp[8])
|
||||
swap(temp[5], temp[8]);
|
||||
temp[5] <<= 1;
|
||||
temp[2] <<= 2;
|
||||
temp[2] += temp[5] + temp[8];
|
||||
// 4. Apply display gamma to convert back for display.
|
||||
transformed_r = copysignf(powf(fabsf(transformed_r), display_gamma_reciprocal), transformed_r);
|
||||
transformed_g = copysignf(powf(fabsf(transformed_g), display_gamma_reciprocal), transformed_g);
|
||||
transformed_b = copysignf(powf(fabsf(transformed_b), display_gamma_reciprocal), transformed_b);
|
||||
|
||||
blue = ((int(temp[2]) * 160) >> 17) + 4;
|
||||
if (blue > 31)
|
||||
blue = 31;
|
||||
// Final clamp: ensure values are within 0.0-1.0 range
|
||||
transformed_r = fmaxf(0.0f, fminf(1.0f, transformed_r));
|
||||
transformed_g = fmaxf(0.0f, fminf(1.0f, transformed_g));
|
||||
transformed_b = fmaxf(0.0f, fminf(1.0f, transformed_b));
|
||||
|
||||
if (temp[1] < temp[4])
|
||||
swap(temp[1], temp[4]);
|
||||
if (temp[1] < temp[7])
|
||||
swap(temp[1], temp[7]);
|
||||
if (temp[4] < temp[7])
|
||||
swap(temp[4], temp[7]);
|
||||
temp[4] <<= 1;
|
||||
temp[1] <<= 2;
|
||||
temp[1] += temp[4] + temp[7];
|
||||
// Convert back to 5-bit (0-31) integer and combine into uint16_t
|
||||
// Apply 5-bit to 5-bit conversion, as this palette is for 16-bit output.
|
||||
uint8_t final_red = (uint8_t)(transformed_r * 31.0f + 0.5f);
|
||||
uint8_t final_green = (uint8_t)(transformed_g * 31.0f + 0.5f);
|
||||
uint8_t final_blue = (uint8_t)(transformed_b * 31.0f + 0.5f);
|
||||
|
||||
green = ((int(temp[1]) * 160) >> 17) + 4;
|
||||
if (green > 31)
|
||||
green = 31;
|
||||
// Ensure values are strictly within 0-31 range after rounding
|
||||
if (final_red > 31) final_red = 31;
|
||||
if (final_green > 31) final_green = 31;
|
||||
if (final_blue > 31) final_blue = 31;
|
||||
|
||||
pix = red << systemRedShift;
|
||||
pix += green << systemGreenShift;
|
||||
pix += blue << systemBlueShift;
|
||||
|
||||
*buf++ = pix;
|
||||
*buf++ = (final_red << systemRedShift) |
|
||||
(final_green << systemGreenShift) |
|
||||
(final_blue << systemBlueShift);
|
||||
}
|
||||
}
|
||||
|
||||
void gbafilter_pal32(uint32_t* buf, int count)
|
||||
{
|
||||
short temp[3 * 3], s;
|
||||
unsigned pix;
|
||||
uint8_t red, green, blue;
|
||||
// Pre-calculate constants for efficiency within function scope
|
||||
const float target_gamma_exponent = target_gamma + darken_screen;
|
||||
const float display_gamma_reciprocal = 1.0f / display_gamma;
|
||||
const float luminance_factor = profile[3][3]; // profile[3].w from GLSL
|
||||
|
||||
while (count--) {
|
||||
pix = *buf;
|
||||
uint32_t pix = *buf;
|
||||
|
||||
s = curve[(pix >> systemGreenShift) & 0x1f];
|
||||
temp[3] = s * influence[3];
|
||||
temp[4] = s * influence[4];
|
||||
temp[5] = s * influence[5];
|
||||
// Extract original 5-bit R, G, B values from the shifted positions in the 32-bit pixel.
|
||||
// These shifts pull out the 5-bit value from its shifted position (e.g., bits 3-7 for Red).
|
||||
uint8_t original_r_val_5bit = (uint8_t)((pix >> systemRedShift) & 0x1f);
|
||||
uint8_t original_g_val_5bit = (uint8_t)((pix >> systemGreenShift) & 0x1f);
|
||||
uint8_t original_b_val_5bit = (uint8_t)((pix >> systemBlueShift) & 0x1f);
|
||||
|
||||
s = curve[(pix >> systemRedShift) & 0x1f];
|
||||
temp[0] = s * influence[0];
|
||||
temp[1] = s * influence[1];
|
||||
temp[2] = s * influence[2];
|
||||
|
||||
s = curve[(pix >> systemBlueShift) & 0x1f];
|
||||
temp[6] = s * influence[6];
|
||||
temp[7] = s * influence[7];
|
||||
temp[8] = s * influence[8];
|
||||
// Normalize to 0.0-1.0 for calculations
|
||||
float r = (float)original_r_val_5bit / 31.0f;
|
||||
float g = (float)original_g_val_5bit / 31.0f;
|
||||
float b = (float)original_b_val_5bit / 31.0f;
|
||||
|
||||
if (temp[0] < temp[3])
|
||||
swap(temp[0], temp[3]);
|
||||
if (temp[0] < temp[6])
|
||||
swap(temp[0], temp[6]);
|
||||
if (temp[3] < temp[6])
|
||||
swap(temp[3], temp[6]);
|
||||
temp[3] <<= 1;
|
||||
temp[0] <<= 2;
|
||||
temp[0] += temp[3] + temp[6];
|
||||
// 1. Apply initial gamma (including darken_screen as exponent) to convert to linear space.
|
||||
r = powf(r, target_gamma_exponent);
|
||||
g = powf(g, target_gamma_exponent);
|
||||
b = powf(b, target_gamma_exponent);
|
||||
|
||||
//red = ((int(temp[0]) * 160) >> 17) + 4;
|
||||
red = ((int(temp[0]) * 160) >> 14) + 32;
|
||||
// 2. Apply luminance factor and clamp.
|
||||
r = fmaxf(0.0f, fminf(1.0f, r * luminance_factor));
|
||||
g = fmaxf(0.0f, fminf(1.0f, g * luminance_factor));
|
||||
b = fmaxf(0.0f, fminf(1.0f, b * luminance_factor));
|
||||
|
||||
if (temp[2] < temp[5])
|
||||
swap(temp[2], temp[5]);
|
||||
if (temp[2] < temp[8])
|
||||
swap(temp[2], temp[8]);
|
||||
if (temp[5] < temp[8])
|
||||
swap(temp[5], temp[8]);
|
||||
temp[5] <<= 1;
|
||||
temp[2] <<= 2;
|
||||
temp[2] += temp[5] + temp[8];
|
||||
// 3. Apply color profile matrix
|
||||
float transformed_r = profile[0][0] * r + profile[1][0] * g + profile[2][0] * b;
|
||||
float transformed_g = profile[0][1] * r + profile[1][1] * g + profile[2][1] * b;
|
||||
float transformed_b = profile[0][2] * r + profile[1][2] * g + profile[2][2] * b;
|
||||
|
||||
//blue = ((int(temp[2]) * 160) >> 17) + 4;
|
||||
blue = ((int(temp[2]) * 160) >> 14) + 32;
|
||||
// 4. Apply display gamma.
|
||||
transformed_r = copysignf(powf(fabsf(transformed_r), display_gamma_reciprocal), transformed_r);
|
||||
transformed_g = copysignf(powf(fabsf(transformed_g), display_gamma_reciprocal), transformed_g);
|
||||
transformed_b = copysignf(powf(fabsf(transformed_b), display_gamma_reciprocal), transformed_b);
|
||||
|
||||
if (temp[1] < temp[4])
|
||||
swap(temp[1], temp[4]);
|
||||
if (temp[1] < temp[7])
|
||||
swap(temp[1], temp[7]);
|
||||
if (temp[4] < temp[7])
|
||||
swap(temp[4], temp[7]);
|
||||
temp[4] <<= 1;
|
||||
temp[1] <<= 2;
|
||||
temp[1] += temp[4] + temp[7];
|
||||
// Final clamp: ensure values are within 0.0-1.0 range
|
||||
transformed_r = fmaxf(0.0f, fminf(1.0f, transformed_r));
|
||||
transformed_g = fmaxf(0.0f, fminf(1.0f, transformed_g));
|
||||
transformed_b = fmaxf(0.0f, fminf(1.0f, transformed_b));
|
||||
|
||||
//green = ((int(temp[1]) * 160) >> 17) + 4;
|
||||
green = ((int(temp[1]) * 160) >> 14) + 32;
|
||||
|
||||
//pix = red << redshift;
|
||||
//pix += green << greenshift;
|
||||
//pix += blue << blueshift;
|
||||
// Convert the floating-point values to 8-bit integer components (0-255).
|
||||
uint8_t final_red_8bit = (uint8_t)(transformed_r * 255.0f + 0.5f);
|
||||
uint8_t final_green_8bit = (uint8_t)(transformed_g * 255.0f + 0.5f);
|
||||
uint8_t final_blue_8bit = (uint8_t)(transformed_b * 255.0f + 0.5f);
|
||||
|
||||
pix = red << (systemRedShift - 3);
|
||||
pix += green << (systemGreenShift - 3);
|
||||
pix += blue << (systemBlueShift - 3);
|
||||
// Ensure values are strictly within 0-255 range after rounding
|
||||
if (final_red_8bit > 255) final_red_8bit = 255;
|
||||
if (final_green_8bit > 255) final_green_8bit = 255;
|
||||
if (final_blue_8bit > 255) final_blue_8bit = 255;
|
||||
|
||||
*buf++ = pix;
|
||||
}
|
||||
}
|
||||
// --- NEW PACKING LOGIC ---
|
||||
// This is the critical change to correctly map 8-bit color to the 5-bit shifted format,
|
||||
// while allowing FFFFFF.
|
||||
// It uses the top 5 bits of the 8-bit value for the GBA's 5-bit component position,
|
||||
// and the bottom 3 bits to fill the lower, normally zeroed, positions.
|
||||
|
||||
// for palette mode to work with the three spoony filters in 32bpp depth
|
||||
uint32_t final_pix = 0;
|
||||
|
||||
void gbafilter_pad(uint8_t* buf, int count)
|
||||
{
|
||||
union {
|
||||
struct
|
||||
{
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
uint8_t a;
|
||||
} part;
|
||||
unsigned whole;
|
||||
} mask;
|
||||
// Red component
|
||||
// 5 most significant bits (MSBs) for the 'systemRedShift' position
|
||||
final_pix |= ((final_red_8bit >> 3) & 0x1f) << systemRedShift;
|
||||
// 3 least significant bits (LSBs) for the 'base' position (systemRedShift - 3)
|
||||
final_pix |= (final_red_8bit & 0x07) << (systemRedShift - 3);
|
||||
|
||||
mask.whole = 0x1f << systemRedShift;
|
||||
mask.whole += 0x1f << systemGreenShift;
|
||||
mask.whole += 0x1f << systemBlueShift;
|
||||
|
||||
switch (systemColorDepth) {
|
||||
case 24:
|
||||
while (count--) {
|
||||
*buf++ &= mask.part.r;
|
||||
*buf++ &= mask.part.g;
|
||||
*buf++ &= mask.part.b;
|
||||
// Green component
|
||||
// 5 MSBs for the 'systemGreenShift' position
|
||||
final_pix |= ((final_green_8bit >> 3) & 0x1f) << systemGreenShift;
|
||||
// 3 LSBs for the 'base' position (systemGreenShift - 3)
|
||||
final_pix |= (final_green_8bit & 0x07) << (systemGreenShift - 3);
|
||||
|
||||
// Blue component
|
||||
// 5 MSBs for the 'systemBlueShift' position
|
||||
final_pix |= ((final_blue_8bit >> 3) & 0x1f) << systemBlueShift;
|
||||
// 3 LSBs for the 'base' position (systemBlueShift - 3)
|
||||
final_pix |= (final_blue_8bit & 0x07) << (systemBlueShift - 3);
|
||||
|
||||
// Preserve existing alpha if present (assuming it's at bits 24-31 for 32-bit depth)
|
||||
if (systemColorDepth == 32) {
|
||||
final_pix |= (pix & (0xFF << 24));
|
||||
}
|
||||
break;
|
||||
case 32:
|
||||
while (count--) {
|
||||
*((uint32_t*)buf) &= mask.whole;
|
||||
buf += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void UpdateSystemColorMaps(int lcd)
|
||||
{
|
||||
switch(systemColorDepth) {
|
||||
case 8:
|
||||
{
|
||||
for(int i = 0; i < 0x10000; i++) {
|
||||
systemColorMap8[i] = (((i & 0x1f) << systemRedShift) & 0xE0) |
|
||||
((((i & 0x3e0) >> 5) << systemGreenShift) & 0x1C) |
|
||||
((((i & 0x7c00) >> 10) << systemBlueShift) & 0x3);
|
||||
}
|
||||
*buf++ = final_pix;
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
{
|
||||
for(int i = 0; i < 0x10000; i++) {
|
||||
systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
|
||||
(((i & 0x3e0) >> 5) << systemGreenShift) |
|
||||
(((i & 0x7c00) >> 10) << systemBlueShift);
|
||||
}
|
||||
if (lcd == 1) gbafilter_pal(systemColorMap16, 0x10000);
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
{
|
||||
for(int i = 0; i < 0x10000; i++) {
|
||||
systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
|
||||
(((i & 0x3e0) >> 5) << systemGreenShift) |
|
||||
(((i & 0x7c00) >> 10) << systemBlueShift);
|
||||
}
|
||||
if (lcd == 1) gbafilter_pal32(systemColorMap32, 0x10000);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
@@ -4,8 +4,9 @@
|
||||
#include <cstdint>
|
||||
|
||||
void gbafilter_update_colors(bool lcd = false);
|
||||
void gbafilter_pal8(uint8_t* buf, int count);
|
||||
void gbafilter_pal(uint16_t* buf, int count);
|
||||
void gbafilter_pal32(uint32_t* buf, int count);
|
||||
void gbafilter_pad(uint8_t* buf, int count);
|
||||
void gbafilter_set_params(int color_mode, float darken_screen);
|
||||
|
||||
#endif // VBAM_COMPONENTS_FILTERS_AGB_FILTERS_AGB_H_
|
||||
|
6
src/components/filters_cgb/CMakeLists.txt
Normal file
6
src/components/filters_cgb/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
add_library(vbam-components-filters-cgb OBJECT)
|
||||
|
||||
target_sources(vbam-components-filters-cgb
|
||||
PRIVATE filters_cgb.cpp
|
||||
PUBLIC filters_cgb.h
|
||||
)
|
352
src/components/filters_cgb/filters_cgb.cpp
Normal file
352
src/components/filters_cgb/filters_cgb.cpp
Normal file
@@ -0,0 +1,352 @@
|
||||
/*
|
||||
* GBC Color Correction Shader Implementation
|
||||
*
|
||||
* Shader modified by Pokefan531.
|
||||
* Color Mangler
|
||||
* Original Author: hunterk
|
||||
* Original License: Public domain
|
||||
*
|
||||
* This code is adapted from the original shader logic.
|
||||
*/
|
||||
|
||||
#include "components/filters_cgb/filters_cgb.h"
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
extern int systemColorDepth;
|
||||
extern int systemRedShift;
|
||||
extern int systemGreenShift;
|
||||
extern int systemBlueShift;
|
||||
|
||||
extern uint8_t systemColorMap8[0x10000];
|
||||
extern uint16_t systemColorMap16[0x10000];
|
||||
extern uint32_t systemColorMap32[0x10000];
|
||||
|
||||
// --- Global Constants and Variables for GBC Color Correction ---
|
||||
// Define the color profile matrix as a static const float 2D array
|
||||
// This replicates the column-major order of GLSL mat4 for easier translation.
|
||||
// Format: { {col0_row0, col0_row1, col0_row2, col0_row3}, ... }
|
||||
static const float GBC_sRGB[4][4] = {
|
||||
{0.905f, 0.10f, 0.1575f, 0.0f}, // Column 0 (R output contributions from R, G, B, A)
|
||||
{0.195f, 0.65f, 0.1425f, 0.0f}, // Column 1 (G output contributions from R, G, B, A)
|
||||
{-0.10f, 0.25f, 0.70f, 0.0f}, // Column 2 (B output contributions from R, G, B, A)
|
||||
{0.0f, 0.0f, 0.0f, 0.91f} // Column 3 (A/Luminance contribution)
|
||||
};
|
||||
|
||||
static const float GBC_DCI[4][4] = {
|
||||
{0.76f, 0.125f, 0.16f, 0.0f},
|
||||
{0.27f, 0.6375f, 0.18f, 0.0f},
|
||||
{-0.03f, 0.2375f, 0.66f, 0.0f},
|
||||
{0.0f, 0.0f, 0.0f, 0.97f}
|
||||
};
|
||||
|
||||
static const float GBC_Rec2020[4][4] = {
|
||||
{0.61f, 0.155f, 0.16f, 0.0f},
|
||||
{0.345f, 0.615f, 0.1875f, 0.0f},
|
||||
{0.045f, 0.23f, 0.6525f, 0.0f},
|
||||
{0.0f, 0.0f, 0.0f, 1.0f}
|
||||
};
|
||||
|
||||
// Screen lightening factor. Default to 0.0f.
|
||||
static float lighten_screen = 0.0f;
|
||||
|
||||
// Color mode (0 for sRGB, 1 for DCI, 2 for Rec2020). Default to sRGB (0).
|
||||
static int color_mode = 0;
|
||||
|
||||
// Pointer to the currently selected color profile matrix.
|
||||
static const float (*profile)[4];
|
||||
|
||||
// Global constants from the shader for gamma correction values
|
||||
static const float target_gamma = 2.2f;
|
||||
static const float display_gamma = 2.2f;
|
||||
|
||||
|
||||
// --- Function Implementations ---
|
||||
|
||||
// Forward declaration of a helper function to set the profile based on color_mode
|
||||
static void set_profile_from_mode();
|
||||
|
||||
// This constructor-like function runs once when the program starts.
|
||||
struct GbcfilterInitializer {
|
||||
GbcfilterInitializer() {
|
||||
set_profile_from_mode();
|
||||
}
|
||||
};
|
||||
static GbcfilterInitializer __gbcfilter_initializer;
|
||||
|
||||
|
||||
// Helper function to set the 'profile' pointer based on the 'color_mode' variable.
|
||||
static void set_profile_from_mode() {
|
||||
if (color_mode == 0) {
|
||||
profile = GBC_sRGB;
|
||||
}
|
||||
else if (color_mode == 1) {
|
||||
profile = GBC_DCI;
|
||||
}
|
||||
else if (color_mode == 2) {
|
||||
profile = GBC_Rec2020;
|
||||
}
|
||||
else {
|
||||
profile = GBC_sRGB; // Default to sRGB if an invalid mode is set
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Public function to set color mode and darken screen from external calls
|
||||
void gbcfilter_set_params(int new_color_mode, float new_lighten_screen) {
|
||||
color_mode = new_color_mode;
|
||||
lighten_screen = fmaxf(0.0f, fminf(1.0f, new_lighten_screen)); // Clamp to 0.0-1.0
|
||||
|
||||
// Call the helper to update 'profile' based on the new 'color_mode'
|
||||
set_profile_from_mode();
|
||||
}
|
||||
|
||||
void gbcfilter_update_colors(bool lcd) {
|
||||
switch (systemColorDepth) {
|
||||
case 8: {
|
||||
for (int i = 0; i < 0x10000; i++) {
|
||||
systemColorMap8[i] = (uint8_t)((((i & 0x1f) << 3) & 0xE0) |
|
||||
((((i & 0x3e0) >> 5) << 0) & 0x1C) |
|
||||
((((i & 0x7c00) >> 10) >> 3) & 0x3));
|
||||
}
|
||||
if (lcd)
|
||||
gbcfilter_pal8(systemColorMap8, 0x10000);
|
||||
} break;
|
||||
case 16: {
|
||||
for (int i = 0x0; i < 0x10000; i++) {
|
||||
systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
|
||||
(((i & 0x3e0) >> 5) << systemGreenShift) |
|
||||
(((i & 0x7c00) >> 10) << systemBlueShift);
|
||||
}
|
||||
if (lcd)
|
||||
gbcfilter_pal(systemColorMap16, 0x10000);
|
||||
} break;
|
||||
case 24:
|
||||
case 32: {
|
||||
for (int i = 0; i < 0x10000; i++) {
|
||||
systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
|
||||
(((i & 0x3e0) >> 5) << systemGreenShift) |
|
||||
(((i & 0x7c00) >> 10) << systemBlueShift);
|
||||
}
|
||||
if (lcd)
|
||||
gbcfilter_pal32(systemColorMap32, 0x10000);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void gbcfilter_pal8(uint8_t* buf, int count)
|
||||
{
|
||||
// Pre-calculate constants for efficiency within function scope
|
||||
const float target_gamma_exponent = target_gamma + (lighten_screen * -1.0f);
|
||||
const float display_gamma_reciprocal = 1.0f / display_gamma;
|
||||
const float luminance_factor = profile[3][3]; // profile[3].w from GLSL
|
||||
|
||||
while (count--) {
|
||||
uint8_t pix = *buf;
|
||||
|
||||
uint8_t original_r_val_3bit = (uint8_t)((pix & 0xE0) >> 5);
|
||||
uint8_t original_g_val_3bit = (uint8_t)((pix & 0x1C) >> 2);
|
||||
uint8_t original_b_val_2bit = (uint8_t)(pix & 0x3);
|
||||
|
||||
// Normalize to 0.0-1.0 for calculations
|
||||
float r = (float)original_r_val_3bit / 7.0f;
|
||||
float g = (float)original_g_val_3bit / 7.0f;
|
||||
float b = (float)original_b_val_2bit / 3.0f;
|
||||
|
||||
// 1. Apply initial gamma (including lighten_screen as exponent) to convert to linear space.
|
||||
// This step will affect non-"white" values.
|
||||
r = powf(r, target_gamma_exponent);
|
||||
g = powf(g, target_gamma_exponent);
|
||||
b = powf(b, target_gamma_exponent);
|
||||
|
||||
// 2. Apply luminance factor and clamp.
|
||||
r = fmaxf(0.0f, fminf(1.0f, r * luminance_factor));
|
||||
g = fmaxf(0.0f, fminf(1.0f, g * luminance_factor));
|
||||
b = fmaxf(0.0f, fminf(1.0f, b * luminance_factor));
|
||||
|
||||
// 3. Apply color profile matrix (using profile[column][row] access)
|
||||
float transformed_r = profile[0][0] * r + profile[1][0] * g + profile[2][0] * b;
|
||||
float transformed_g = profile[0][1] * r + profile[1][1] * g + profile[2][1] * b;
|
||||
float transformed_b = profile[0][2] * r + profile[1][2] * g + profile[2][2] * b;
|
||||
|
||||
// 4. Apply display gamma to convert back for display.
|
||||
transformed_r = copysignf(powf(fabsf(transformed_r), display_gamma_reciprocal), transformed_r);
|
||||
transformed_g = copysignf(powf(fabsf(transformed_g), display_gamma_reciprocal), transformed_g);
|
||||
transformed_b = copysignf(powf(fabsf(transformed_b), display_gamma_reciprocal), transformed_b);
|
||||
|
||||
// Final clamp: ensure values are within 0.0-1.0 range
|
||||
transformed_r = fmaxf(0.0f, fminf(1.0f, transformed_r));
|
||||
transformed_g = fmaxf(0.0f, fminf(1.0f, transformed_g));
|
||||
transformed_b = fmaxf(0.0f, fminf(1.0f, transformed_b));
|
||||
|
||||
// Convert back to 3-bit or 2-bit (0-7 or 0-3) integer and combine into uint8_t
|
||||
// Apply 3-bit or 2-bit to 8-bit conversion, as this palette is for 8-bit output.
|
||||
uint8_t final_red = (uint8_t)(transformed_r * 7.0f + 0.5f);
|
||||
uint8_t final_green = (uint8_t)(transformed_g * 7.0f + 0.5f);
|
||||
uint8_t final_blue = (uint8_t)(transformed_b * 3.0f + 0.5f);
|
||||
|
||||
// Ensure values are strictly within 0-7 or 0-3 range after rounding
|
||||
if (final_red > 7) final_red = 7;
|
||||
if (final_green > 7) final_green = 7;
|
||||
if (final_blue > 3) final_blue = 3;
|
||||
|
||||
*buf++ = ((final_red & 0x7) << 5) |
|
||||
((final_green & 0x7) << 2) |
|
||||
(final_blue & 0x3);
|
||||
}
|
||||
}
|
||||
void gbcfilter_pal(uint16_t* buf, int count)
|
||||
{
|
||||
// Pre-calculate constants for efficiency within function scope
|
||||
const float target_gamma_exponent = target_gamma + (lighten_screen * -1.0f);
|
||||
const float display_gamma_reciprocal = 1.0f / display_gamma;
|
||||
const float luminance_factor = profile[3][3]; // profile[3].w from GLSL
|
||||
|
||||
while (count--) {
|
||||
uint16_t pix = *buf;
|
||||
|
||||
uint8_t original_r_val_5bit = (uint8_t)((pix >> systemRedShift) & 0x1f);
|
||||
uint8_t original_g_val_5bit = (uint8_t)((pix >> systemGreenShift) & 0x1f);
|
||||
uint8_t original_b_val_5bit = (uint8_t)((pix >> systemBlueShift) & 0x1f);
|
||||
|
||||
// Normalize to 0.0-1.0 for calculations
|
||||
float r = (float)original_r_val_5bit / 31.0f;
|
||||
float g = (float)original_g_val_5bit / 31.0f;
|
||||
float b = (float)original_b_val_5bit / 31.0f;
|
||||
|
||||
// 1. Apply initial gamma (including lighten_screen as exponent) to convert to linear space.
|
||||
// This step will affect non-"white" values.
|
||||
r = powf(r, target_gamma_exponent);
|
||||
g = powf(g, target_gamma_exponent);
|
||||
b = powf(b, target_gamma_exponent);
|
||||
|
||||
// 2. Apply luminance factor and clamp.
|
||||
r = fmaxf(0.0f, fminf(1.0f, r * luminance_factor));
|
||||
g = fmaxf(0.0f, fminf(1.0f, g * luminance_factor));
|
||||
b = fmaxf(0.0f, fminf(1.0f, b * luminance_factor));
|
||||
|
||||
// 3. Apply color profile matrix (using profile[column][row] access)
|
||||
float transformed_r = profile[0][0] * r + profile[1][0] * g + profile[2][0] * b;
|
||||
float transformed_g = profile[0][1] * r + profile[1][1] * g + profile[2][1] * b;
|
||||
float transformed_b = profile[0][2] * r + profile[1][2] * g + profile[2][2] * b;
|
||||
|
||||
// 4. Apply display gamma to convert back for display.
|
||||
transformed_r = copysignf(powf(fabsf(transformed_r), display_gamma_reciprocal), transformed_r);
|
||||
transformed_g = copysignf(powf(fabsf(transformed_g), display_gamma_reciprocal), transformed_g);
|
||||
transformed_b = copysignf(powf(fabsf(transformed_b), display_gamma_reciprocal), transformed_b);
|
||||
|
||||
// Final clamp: ensure values are within 0.0-1.0 range
|
||||
transformed_r = fmaxf(0.0f, fminf(1.0f, transformed_r));
|
||||
transformed_g = fmaxf(0.0f, fminf(1.0f, transformed_g));
|
||||
transformed_b = fmaxf(0.0f, fminf(1.0f, transformed_b));
|
||||
|
||||
// Convert back to 5-bit (0-31) integer and combine into uint16_t
|
||||
// Apply 5-bit to 5-bit conversion, as this palette is for 16-bit output.
|
||||
uint8_t final_red = (uint8_t)(transformed_r * 31.0f + 0.5f);
|
||||
uint8_t final_green = (uint8_t)(transformed_g * 31.0f + 0.5f);
|
||||
uint8_t final_blue = (uint8_t)(transformed_b * 31.0f + 0.5f);
|
||||
|
||||
// Ensure values are strictly within 0-31 range after rounding
|
||||
if (final_red > 31) final_red = 31;
|
||||
if (final_green > 31) final_green = 31;
|
||||
if (final_blue > 31) final_blue = 31;
|
||||
|
||||
*buf++ = (final_red << systemRedShift) |
|
||||
(final_green << systemGreenShift) |
|
||||
(final_blue << systemBlueShift);
|
||||
}
|
||||
}
|
||||
|
||||
void gbcfilter_pal32(uint32_t* buf, int count)
|
||||
{
|
||||
// Pre-calculate constants for efficiency within function scope
|
||||
const float target_gamma_exponent = target_gamma + (lighten_screen * -1.0f);
|
||||
const float display_gamma_reciprocal = 1.0f / display_gamma;
|
||||
const float luminance_factor = profile[3][3]; // profile[3].w from GLSL
|
||||
|
||||
while (count--) {
|
||||
uint32_t pix = *buf;
|
||||
|
||||
// Extract original 5-bit R, G, B values from the shifted positions in the 32-bit pixel.
|
||||
// These shifts pull out the 5-bit value from its shifted position (e.g., bits 3-7 for Red).
|
||||
uint8_t original_r_val_5bit = (uint8_t)((pix >> systemRedShift) & 0x1f);
|
||||
uint8_t original_g_val_5bit = (uint8_t)((pix >> systemGreenShift) & 0x1f);
|
||||
uint8_t original_b_val_5bit = (uint8_t)((pix >> systemBlueShift) & 0x1f);
|
||||
|
||||
|
||||
// Normalize to 0.0-1.0 for calculations
|
||||
float r = (float)original_r_val_5bit / 31.0f;
|
||||
float g = (float)original_g_val_5bit / 31.0f;
|
||||
float b = (float)original_b_val_5bit / 31.0f;
|
||||
|
||||
// 1. Apply initial gamma (including lighten_screen as exponent) to convert to linear space.
|
||||
r = powf(r, target_gamma_exponent);
|
||||
g = powf(g, target_gamma_exponent);
|
||||
b = powf(b, target_gamma_exponent);
|
||||
|
||||
// 2. Apply luminance factor and clamp.
|
||||
r = fmaxf(0.0f, fminf(1.0f, r * luminance_factor));
|
||||
g = fmaxf(0.0f, fminf(1.0f, g * luminance_factor));
|
||||
b = fmaxf(0.0f, fminf(1.0f, b * luminance_factor));
|
||||
|
||||
// 3. Apply color profile matrix
|
||||
float transformed_r = profile[0][0] * r + profile[1][0] * g + profile[2][0] * b;
|
||||
float transformed_g = profile[0][1] * r + profile[1][1] * g + profile[2][1] * b;
|
||||
float transformed_b = profile[0][2] * r + profile[1][2] * g + profile[2][2] * b;
|
||||
|
||||
// 4. Apply display gamma.
|
||||
transformed_r = copysignf(powf(fabsf(transformed_r), display_gamma_reciprocal), transformed_r);
|
||||
transformed_g = copysignf(powf(fabsf(transformed_g), display_gamma_reciprocal), transformed_g);
|
||||
transformed_b = copysignf(powf(fabsf(transformed_b), display_gamma_reciprocal), transformed_b);
|
||||
|
||||
// Final clamp: ensure values are within 0.0-1.0 range
|
||||
transformed_r = fmaxf(0.0f, fminf(1.0f, transformed_r));
|
||||
transformed_g = fmaxf(0.0f, fminf(1.0f, transformed_g));
|
||||
transformed_b = fmaxf(0.0f, fminf(1.0f, transformed_b));
|
||||
|
||||
|
||||
// Convert the floating-point values to 8-bit integer components (0-255).
|
||||
uint8_t final_red_8bit = (uint8_t)(transformed_r * 255.0f + 0.5f);
|
||||
uint8_t final_green_8bit = (uint8_t)(transformed_g * 255.0f + 0.5f);
|
||||
uint8_t final_blue_8bit = (uint8_t)(transformed_b * 255.0f + 0.5f);
|
||||
|
||||
// Ensure values are strictly within 0-255 range after rounding
|
||||
if (final_red_8bit > 255) final_red_8bit = 255;
|
||||
if (final_green_8bit > 255) final_green_8bit = 255;
|
||||
if (final_blue_8bit > 255) final_blue_8bit = 255;
|
||||
|
||||
// --- NEW PACKING LOGIC ---
|
||||
// This is the critical change to correctly map 8-bit color to the 5-bit shifted format,
|
||||
// while allowing FFFFFF.
|
||||
// It uses the top 5 bits of the 8-bit value for the GBC's 5-bit component position,
|
||||
// and the bottom 3 bits to fill the lower, normally zeroed, positions.
|
||||
|
||||
uint32_t final_pix = 0;
|
||||
|
||||
// Red component
|
||||
// 5 most significant bits (MSBs) for the 'systemRedShift' position
|
||||
final_pix |= ((final_red_8bit >> 3) & 0x1f) << systemRedShift;
|
||||
// 3 least significant bits (LSBs) for the 'base' position (systemRedShift - 3)
|
||||
final_pix |= (final_red_8bit & 0x07) << (systemRedShift - 3);
|
||||
|
||||
|
||||
// Green component
|
||||
// 5 MSBs for the 'systemGreenShift' position
|
||||
final_pix |= ((final_green_8bit >> 3) & 0x1f) << systemGreenShift;
|
||||
// 3 LSBs for the 'base' position (systemGreenShift - 3)
|
||||
final_pix |= (final_green_8bit & 0x07) << (systemGreenShift - 3);
|
||||
|
||||
// Blue component
|
||||
// 5 MSBs for the 'systemBlueShift' position
|
||||
final_pix |= ((final_blue_8bit >> 3) & 0x1f) << systemBlueShift;
|
||||
// 3 LSBs for the 'base' position (systemBlueShift - 3)
|
||||
final_pix |= (final_blue_8bit & 0x07) << (systemBlueShift - 3);
|
||||
|
||||
// Preserve existing alpha if present (assuming it's at bits 24-31 for 32-bit depth)
|
||||
if (systemColorDepth == 32) {
|
||||
final_pix |= (pix & (0xFF << 24));
|
||||
}
|
||||
|
||||
*buf++ = final_pix;
|
||||
}
|
||||
}
|
12
src/components/filters_cgb/filters_cgb.h
Normal file
12
src/components/filters_cgb/filters_cgb.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef VBAM_COMPONENTS_FILTERS_CGB_FILTERS_CGB_H_
|
||||
#define VBAM_COMPONENTS_FILTERS_CGB_FILTERS_CGB_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
void gbcfilter_update_colors(bool lcd = false);
|
||||
void gbcfilter_pal8(uint8_t* buf, int count);
|
||||
void gbcfilter_pal(uint16_t* buf, int count);
|
||||
void gbcfilter_pal32(uint32_t* buf, int count);
|
||||
void gbcfilter_set_params(int color_mode, float lighten_screen);
|
||||
|
||||
#endif // VBAM_COMPONENTS_FILTERS_CGB_FILTERS_CGB_H_
|
@@ -19,12 +19,12 @@ FILE* utilOpenFile(const char* filename, const char* mode) {
|
||||
#ifdef _WIN32
|
||||
std::wstring wfilename = core::internal::ToUTF16(filename);
|
||||
if (wfilename.empty()) {
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
std::wstring wmode = core::internal::ToUTF16(mode);
|
||||
if (wmode.empty()) {
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if __STDC_WANT_SECURE_LIB__
|
||||
@@ -53,7 +53,7 @@ bool utilIsGBAImage(const char* file) {
|
||||
if (strlen(file) > 4) {
|
||||
const char* p = strrchr(file, '.');
|
||||
|
||||
if (p != nullptr) {
|
||||
if (p != NULL) {
|
||||
if ((strcasecmp(p, ".agb") == 0) || (strcasecmp(p, ".gba") == 0) ||
|
||||
(strcasecmp(p, ".bin") == 0) || (strcasecmp(p, ".elf") == 0))
|
||||
return true;
|
||||
@@ -71,7 +71,7 @@ bool utilIsGBImage(const char* file) {
|
||||
if (strlen(file) > 4) {
|
||||
const char* p = strrchr(file, '.');
|
||||
|
||||
if (p != nullptr) {
|
||||
if (p != NULL) {
|
||||
if ((strcasecmp(p, ".dmg") == 0) || (strcasecmp(p, ".gb") == 0) ||
|
||||
(strcasecmp(p, ".gbc") == 0) || (strcasecmp(p, ".cgb") == 0) ||
|
||||
(strcasecmp(p, ".sgb") == 0))
|
||||
|
@@ -24,7 +24,7 @@ bool utilIsGzipFile(const char* file) {
|
||||
if (strlen(file) > 3) {
|
||||
const char* p = strrchr(file, '.');
|
||||
|
||||
if (p != nullptr) {
|
||||
if (p != NULL) {
|
||||
if (strcasecmp(p, ".gz") == 0)
|
||||
return true;
|
||||
if (strcasecmp(p, ".z") == 0)
|
||||
@@ -36,13 +36,13 @@ bool utilIsGzipFile(const char* file) {
|
||||
}
|
||||
|
||||
// Opens and scans archive using accept(). Returns fex_t if found.
|
||||
// If error or not found, displays message and returns nullptr.
|
||||
// If error or not found, displays message and returns NULL.
|
||||
fex_t* scanArchive(const char* file, bool (*accept)(const char*), char (&buffer)[2048]) {
|
||||
fex_t* fe;
|
||||
fex_err_t err = fex_open(&fe, file);
|
||||
if (!fe) {
|
||||
systemMessage(MSG_CANNOT_OPEN_FILE, N_("Cannot open file %s: %s"), file, err);
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Scan filenames
|
||||
@@ -67,14 +67,14 @@ fex_t* scanArchive(const char* file, bool (*accept)(const char*), char (&buffer)
|
||||
if (err) {
|
||||
systemMessage(MSG_BAD_ZIP_FILE, N_("Cannot read archive %s: %s"), file, err);
|
||||
fex_close(fe);
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
systemMessage(MSG_NO_IMAGE_ON_ZIP, N_("No image found in file %s"), file);
|
||||
fex_close(fe);
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
return fe;
|
||||
}
|
||||
@@ -101,10 +101,10 @@ IMAGE_TYPE utilFindType(const char* file, char (&buffer)[2048]) {
|
||||
return utilIsGBAImage(file) ? IMAGE_GBA : IMAGE_GB;
|
||||
}
|
||||
|
||||
int(ZEXPORT* utilGzWriteFunc)(gzFile, const voidp, unsigned int) = nullptr;
|
||||
int(ZEXPORT* utilGzReadFunc)(gzFile, voidp, unsigned int) = nullptr;
|
||||
int(ZEXPORT* utilGzCloseFunc)(gzFile) = nullptr;
|
||||
z_off_t(ZEXPORT* utilGzSeekFunc)(gzFile, z_off_t, int) = nullptr;
|
||||
int(ZEXPORT* utilGzWriteFunc)(gzFile, const voidp, unsigned int) = NULL;
|
||||
int(ZEXPORT* utilGzReadFunc)(gzFile, voidp, unsigned int) = NULL;
|
||||
int(ZEXPORT* utilGzCloseFunc)(gzFile) = NULL;
|
||||
z_off_t(ZEXPORT* utilGzSeekFunc)(gzFile, z_off_t, int) = NULL;
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -113,7 +113,7 @@ uint8_t* utilLoad(const char* file, bool (*accept)(const char*), uint8_t* data,
|
||||
char buffer[2048];
|
||||
fex_t* fe = scanArchive(file, accept, buffer);
|
||||
if (!fe)
|
||||
return nullptr;
|
||||
return NULL;
|
||||
|
||||
// Allocate space for image
|
||||
fex_err_t err = fex_stat(fe);
|
||||
@@ -122,17 +122,17 @@ uint8_t* utilLoad(const char* file, bool (*accept)(const char*), uint8_t* data,
|
||||
size = fileSize;
|
||||
|
||||
if (size > MAX_CART_SIZE)
|
||||
return nullptr;
|
||||
return NULL;
|
||||
|
||||
uint8_t* image = data;
|
||||
|
||||
if (image == nullptr) {
|
||||
if (image == NULL) {
|
||||
// allocate buffer memory if none was passed to the function
|
||||
image = (uint8_t*)malloc(utilGetSize(size));
|
||||
if (image == nullptr) {
|
||||
if (image == NULL) {
|
||||
fex_close(fe);
|
||||
systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"), "data");
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
size = fileSize;
|
||||
}
|
||||
@@ -144,9 +144,9 @@ uint8_t* utilLoad(const char* file, bool (*accept)(const char*), uint8_t* data,
|
||||
|
||||
if (err) {
|
||||
systemMessage(MSG_ERROR_READING_IMAGE, N_("Error reading image from %s: %s"), buffer, err);
|
||||
if (data == nullptr)
|
||||
if (data == NULL)
|
||||
free(image);
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size = fileSize;
|
||||
@@ -183,7 +183,7 @@ gzFile utilAutoGzOpen(const char* file, const char* mode) {
|
||||
|
||||
std::wstring wfile = core::internal::ToUTF16(file);
|
||||
if (wfile.empty()) {
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return gzopen_w(wfile.data(), mode);
|
||||
|
@@ -25,12 +25,12 @@ static int utilGetSize(int size) {
|
||||
}
|
||||
|
||||
uint8_t* utilLoad(const char* file, bool (*)(const char*), uint8_t* data, int& size) {
|
||||
FILE* fp = nullptr;
|
||||
FILE* fp = NULL;
|
||||
|
||||
fp = fopen(file, "rb");
|
||||
if (!fp) {
|
||||
log("Failed to open file %s", file);
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
fseek(fp, 0, SEEK_END); // go to end
|
||||
|
||||
@@ -38,18 +38,18 @@ uint8_t* utilLoad(const char* file, bool (*)(const char*), uint8_t* data, int& s
|
||||
rewind(fp);
|
||||
|
||||
uint8_t* image = data;
|
||||
if (image == nullptr) {
|
||||
if (image == NULL) {
|
||||
image = (uint8_t*)malloc(utilGetSize(size));
|
||||
if (image == nullptr) {
|
||||
if (image == NULL) {
|
||||
log("Failed to allocate memory for %s", file);
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (fread(image, 1, size, fp) != (size_t)size) {
|
||||
log("Failed to read from %s", file);
|
||||
fclose(fp);
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
@@ -10,8 +10,6 @@ extern "C" {
|
||||
#include "core/base/system.h"
|
||||
#include "core/base/message.h"
|
||||
|
||||
bool no_border = false;
|
||||
|
||||
bool utilWritePNGFile(const char* fileName, int w, int h, uint8_t* pix) {
|
||||
static constexpr size_t kNumChannels = 3;
|
||||
uint8_t* writeBuffer = new uint8_t[w * h * kNumChannels];
|
||||
@@ -23,7 +21,7 @@ bool utilWritePNGFile(const char* fileName, int w, int h, uint8_t* pix) {
|
||||
|
||||
switch (systemColorDepth) {
|
||||
case 8: {
|
||||
uint8_t* pixU8 = (uint8_t*)pix + (w);
|
||||
uint8_t* pixU8 = (uint8_t*)pix + (w + 4);
|
||||
for (int y = 0; y < sizeY; y++) {
|
||||
for (int x = 0; x < sizeX; x++, pixU8++) {
|
||||
// White color fix
|
||||
@@ -38,9 +36,7 @@ bool utilWritePNGFile(const char* fileName, int w, int h, uint8_t* pix) {
|
||||
}
|
||||
}
|
||||
|
||||
if (no_border == false) {
|
||||
pixU8 += 2;
|
||||
}
|
||||
pixU8 += 4;
|
||||
}
|
||||
} break;
|
||||
case 16: {
|
||||
@@ -155,11 +151,7 @@ bool utilWriteBMPFile(const char* fileName, int w, int h, uint8_t* pix) {
|
||||
switch (systemColorDepth) {
|
||||
case 8: {
|
||||
uint8_t* pixU8 = 0;
|
||||
if (no_border == false) {
|
||||
pixU8 = (uint8_t*)pix + ((w + 2) * (h));
|
||||
} else {
|
||||
pixU8 = (uint8_t*)pix + ((w) * (h));
|
||||
}
|
||||
pixU8 = (uint8_t*)pix + ((w + 4) * (h));
|
||||
|
||||
for (int y = 0; y < sizeY; y++) {
|
||||
for (int x = 0; x < sizeX; x++, pixU8++) {
|
||||
@@ -175,13 +167,11 @@ bool utilWriteBMPFile(const char* fileName, int w, int h, uint8_t* pix) {
|
||||
}
|
||||
}
|
||||
|
||||
if (no_border == false) {
|
||||
pixU8++;
|
||||
pixU8++;
|
||||
pixU8 -= 2 * (w + 2);
|
||||
} else {
|
||||
pixU8 -= 2 * (w);
|
||||
}
|
||||
pixU8++;
|
||||
pixU8++;
|
||||
pixU8++;
|
||||
pixU8++;
|
||||
pixU8 -= 2 * (w + 4);
|
||||
|
||||
fwrite(writeBuffer, 1, 3 * w, fp);
|
||||
b = writeBuffer;
|
||||
|
@@ -10,7 +10,7 @@ namespace internal {
|
||||
#if defined(_WIN32)
|
||||
|
||||
std::wstring ToUTF16(const char* utf8) {
|
||||
int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, nullptr, 0);
|
||||
int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
|
||||
if (len == 0) {
|
||||
return std::wstring();
|
||||
}
|
||||
|
@@ -10,7 +10,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
#include <sys/param.h>
|
||||
#define fopen64 fopen
|
||||
#define fseeko64 fseeko
|
||||
@@ -34,7 +34,7 @@
|
||||
#include "core/base/file_util.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__MUSL__) || defined(__APPLE__) || defined(BSD) || defined(__NetBSD__)
|
||||
#if defined(__MUSL__) || defined(__APPLE__) || defined(BSD)
|
||||
typedef off_t __off64_t; /* off_t is 64 bits on BSD. */
|
||||
#define fseeko64 fseeko
|
||||
#define ftello64 ftello
|
||||
|
@@ -37,21 +37,21 @@
|
||||
#else
|
||||
|
||||
// swaps a 16-bit value
|
||||
static inline uint16_t swap16(uint16_t v)
|
||||
static inline uint16_t vbswap16(uint16_t v)
|
||||
{
|
||||
return (v << 8) | (v >> 8);
|
||||
}
|
||||
|
||||
// swaps a 32-bit value
|
||||
static inline uint32_t swap32(uint32_t v)
|
||||
static inline uint32_t vbswap32(uint32_t v)
|
||||
{
|
||||
return (v << 24) | ((v << 8) & 0xff0000) | ((v >> 8) & 0xff00) | (v >> 24);
|
||||
}
|
||||
|
||||
#define READ16LE(x) swap16(*((uint16_t *)(x)))
|
||||
#define READ32LE(x) swap32(*((uint32_t *)(x)))
|
||||
#define WRITE16LE(x, v) *((uint16_t *)x) = swap16((v))
|
||||
#define WRITE32LE(x, v) *((uint32_t *)x) = swap32((v))
|
||||
#define READ16LE(x) vbswap16(*((uint16_t *)(x)))
|
||||
#define READ32LE(x) vbswap32(*((uint32_t *)(x)))
|
||||
#define WRITE16LE(x, v) *((uint16_t *)x) = vbswap16((v))
|
||||
#define WRITE32LE(x, v) *((uint32_t *)x) = vbswap32((v))
|
||||
#endif
|
||||
#else
|
||||
#define READ16LE(x) *((uint16_t *)x)
|
||||
|
@@ -74,8 +74,8 @@ extern struct CoreOptions {
|
||||
uint32_t speedup_throttle = 100;
|
||||
uint32_t speedup_frame_skip = 9;
|
||||
uint32_t throttle = 100;
|
||||
const char* loadDotCodeFile = nullptr;
|
||||
const char* saveDotCodeFile = nullptr;
|
||||
const char* loadDotCodeFile = NULL;
|
||||
const char* saveDotCodeFile = NULL;
|
||||
} coreOptions;
|
||||
|
||||
// The following functions must be implemented by the emulator.
|
||||
|
@@ -877,7 +877,7 @@ BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; }
|
||||
|
||||
#ifdef USE_HWCAP
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
static unsigned long MY_getauxval(int aux)
|
||||
{
|
||||
unsigned long val;
|
||||
|
@@ -129,7 +129,9 @@ wchar etoupperw(wchar ch)
|
||||
{
|
||||
if (ch=='i')
|
||||
return('I');
|
||||
#if defined(__APPLE__) || defined(_MSC_VER) || defined(__MINGW32__) || defined(__linux__)
|
||||
#if defined(__APPLE__) || defined(_MSC_VER) || defined(__MINGW32__) || \
|
||||
defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
|
||||
defined(__OpenBSD__)
|
||||
return(toupper(ch));
|
||||
#else
|
||||
return(toupperw(ch));
|
||||
@@ -234,7 +236,9 @@ bool LowAscii(const wchar *Str)
|
||||
|
||||
int wcsicompc(const wchar *Str1,const wchar *Str2)
|
||||
{
|
||||
#if defined(_UNIX) || defined(_MSC_VER) || defined(__APPLE__) || defined(__linux__)
|
||||
#if defined(_UNIX) || defined(_MSC_VER) || defined(__APPLE__) || \
|
||||
defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
|
||||
defined(__OpenBSD__)
|
||||
return my_wcscmp(Str1,Str2);
|
||||
#elif defined(__MINGW32__)
|
||||
return _wcsicmp(Str1,Str2);
|
||||
|
@@ -38,10 +38,10 @@ extern uint8_t* g_pix;
|
||||
namespace {
|
||||
|
||||
// Mapper functions.
|
||||
void (*g_mapper)(uint16_t, uint8_t) = nullptr;
|
||||
void (*g_mapperRAM)(uint16_t, uint8_t) = nullptr;
|
||||
uint8_t (*g_mapperReadRAM)(uint16_t) = nullptr;
|
||||
void (*g_mapperUpdateClock)() = nullptr;
|
||||
void (*g_mapper)(uint16_t, uint8_t) = NULL;
|
||||
void (*g_mapperRAM)(uint16_t, uint8_t) = NULL;
|
||||
uint8_t (*g_mapperReadRAM)(uint16_t) = NULL;
|
||||
void (*g_mapperUpdateClock)() = NULL;
|
||||
|
||||
// Set to true on battery load error.
|
||||
bool g_gbBatteryError = false;
|
||||
@@ -59,7 +59,7 @@ struct VBamIoVec {
|
||||
int leeway = 0;
|
||||
// Optional action to take on read failure.
|
||||
// If this is set, `g_gbBatteryError` will not be set.
|
||||
void (*action_on_failure)() = nullptr;
|
||||
void (*action_on_failure)() = NULL;
|
||||
};
|
||||
std::vector<VBamIoVec> g_vbamIoVecs;
|
||||
|
||||
@@ -136,7 +136,7 @@ bool WriteBatteryFile(const char* file_name) {
|
||||
}
|
||||
|
||||
FILE* file = utilOpenFile(file_name, "wb");
|
||||
if (file == nullptr) {
|
||||
if (file == NULL) {
|
||||
systemMessage(MSG_ERROR_CREATING_FILE, N_("Error creating file %s"),
|
||||
file_name);
|
||||
return false;
|
||||
@@ -157,7 +157,7 @@ bool ReadBatteryFile(const char* file_name) {
|
||||
}
|
||||
|
||||
gzFile gzFile = utilAutoGzOpen(file_name, "rb");
|
||||
if (gzFile == nullptr) {
|
||||
if (gzFile == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -404,9 +404,9 @@ bool gbInitializeRom(size_t romSize) {
|
||||
break;
|
||||
case gbCartData::MapperType::kTama5:
|
||||
gbRamFill = 0x00;
|
||||
if (gbTAMA5ram == nullptr) {
|
||||
if (gbTAMA5ram == NULL) {
|
||||
gbTAMA5ram = (uint8_t*)calloc(1, kTama5RamSize);
|
||||
if (gbTAMA5ram == nullptr) {
|
||||
if (gbTAMA5ram == NULL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -432,16 +432,16 @@ bool gbInitializeRom(size_t romSize) {
|
||||
|
||||
// We need to explicitly reset gbRam here as the patch application process
|
||||
// may have changed the RAM size.
|
||||
if (gbRam != nullptr) {
|
||||
if (gbRam != NULL) {
|
||||
free(gbRam);
|
||||
gbRam = nullptr;
|
||||
gbRam = NULL;
|
||||
}
|
||||
|
||||
const size_t ramSize = g_gbCartData.ram_size();
|
||||
if (g_gbCartData.HasRam()) {
|
||||
// Always allocate 4 KiB to prevent access issues down the line.
|
||||
gbRam = (uint8_t*)malloc(std::max(k4KiB, ramSize));
|
||||
if (gbRam == nullptr) {
|
||||
if (gbRam == NULL) {
|
||||
return false;
|
||||
}
|
||||
memset(gbRam, gbRamFill, ramSize);
|
||||
@@ -2711,27 +2711,27 @@ void gbReset()
|
||||
gbInterruptLaunched = 0;
|
||||
|
||||
if (gbCgbMode) {
|
||||
if (gbVram == nullptr) {
|
||||
if (gbVram == NULL) {
|
||||
gbVram = (uint8_t*)calloc(1, kGBVRamSize);
|
||||
if (gbVram == nullptr) {
|
||||
if (gbVram == NULL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (gbWram == nullptr) {
|
||||
if (gbWram == NULL) {
|
||||
gbWram = (uint8_t*)malloc(kGBWRamSize);
|
||||
if (gbWram == nullptr) {
|
||||
if (gbWram == NULL) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
memset(gbPalette, 0, sizeof(gbPalette));
|
||||
} else {
|
||||
if (gbVram != nullptr) {
|
||||
if (gbVram != NULL) {
|
||||
free(gbVram);
|
||||
gbVram = nullptr;
|
||||
gbVram = NULL;
|
||||
}
|
||||
if (gbWram != nullptr) {
|
||||
if (gbWram != NULL) {
|
||||
free(gbWram);
|
||||
gbWram = nullptr;
|
||||
gbWram = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2749,7 +2749,7 @@ void gbReset()
|
||||
// In all cases, most of the 2nd bank is filled with 00s.
|
||||
// The starting data are important for some 'buggy' games, like Buster Brothers or
|
||||
// Karamuchou ha Oosawagi!.
|
||||
if (gbMemory != nullptr) {
|
||||
if (gbMemory != NULL) {
|
||||
memset(gbMemory, 0xff, 65536);
|
||||
for (int temp = 0xC000; temp < 0xE000; temp++)
|
||||
if ((temp & 0x8) ^ ((temp & 0x800) >> 8)) {
|
||||
@@ -2775,15 +2775,16 @@ void gbReset()
|
||||
}
|
||||
|
||||
// clean LineBuffer
|
||||
if (gbLineBuffer != nullptr) {
|
||||
if (gbLineBuffer != NULL) {
|
||||
memset(gbLineBuffer, 0, kGBLineBufferSize);
|
||||
}
|
||||
// clean Pix
|
||||
if (g_pix != nullptr) {
|
||||
memset(g_pix, 0, kGBPixSize);
|
||||
if (g_pix != NULL) {
|
||||
free(g_pix);
|
||||
g_pix = (uint8_t *)malloc(kGBPixSize);
|
||||
}
|
||||
// clean Vram
|
||||
if (gbVram != nullptr) {
|
||||
if (gbVram != NULL) {
|
||||
memset(gbVram, 0, kGBVRamSize);
|
||||
}
|
||||
// clean Wram 2
|
||||
@@ -2793,7 +2794,7 @@ void gbReset()
|
||||
// In all cases, most of the 2nd bank is filled with 00s.
|
||||
// The starting data are important for some 'buggy' games, like Buster Brothers or
|
||||
// Karamuchou ha Oosawagi!
|
||||
if (gbWram != nullptr) {
|
||||
if (gbWram != NULL) {
|
||||
for (int i = 0; i < 8; i++)
|
||||
if (i != 2)
|
||||
memcpy((uint16_t*)(gbWram + i * 0x1000), (uint16_t*)(gbMemory + 0xC000), 0x1000);
|
||||
@@ -3433,27 +3434,27 @@ static bool gbReadSaveState(gzFile gzFile)
|
||||
|
||||
// Correct crash when loading color gameboy save in regular gameboy type.
|
||||
if (gbCgbMode) {
|
||||
if (gbVram == nullptr) {
|
||||
if (gbVram == NULL) {
|
||||
gbVram = (uint8_t*)calloc(1, kGBVRamSize);
|
||||
if (gbVram == nullptr) {
|
||||
if (gbVram == NULL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (gbWram == nullptr) {
|
||||
if (gbWram == NULL) {
|
||||
gbWram = (uint8_t*)malloc(kGBWRamSize);
|
||||
if (gbWram == nullptr) {
|
||||
if (gbWram == NULL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
memset(gbPalette, 0, sizeof(gbPalette));
|
||||
} else {
|
||||
if (gbVram != nullptr) {
|
||||
if (gbVram != NULL) {
|
||||
free(gbVram);
|
||||
gbVram = nullptr;
|
||||
gbVram = NULL;
|
||||
}
|
||||
if (gbWram != nullptr) {
|
||||
if (gbWram != NULL) {
|
||||
free(gbWram);
|
||||
gbWram = nullptr;
|
||||
gbWram = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3765,58 +3766,58 @@ bool gbWriteBMPFile(const char* fileName)
|
||||
|
||||
void gbCleanUp()
|
||||
{
|
||||
if (gbRam != nullptr) {
|
||||
if (gbRam != NULL) {
|
||||
free(gbRam);
|
||||
gbRam = nullptr;
|
||||
gbRam = NULL;
|
||||
}
|
||||
|
||||
if (gbRom != nullptr) {
|
||||
if (gbRom != NULL) {
|
||||
free(gbRom);
|
||||
gbRom = nullptr;
|
||||
gbRom = NULL;
|
||||
}
|
||||
|
||||
if (g_bios != nullptr) {
|
||||
if (g_bios != NULL) {
|
||||
free(g_bios);
|
||||
g_bios = nullptr;
|
||||
g_bios = NULL;
|
||||
}
|
||||
|
||||
if (gbMemory != nullptr) {
|
||||
if (gbMemory != NULL) {
|
||||
free(gbMemory);
|
||||
gbMemory = nullptr;
|
||||
gbMemory = NULL;
|
||||
}
|
||||
|
||||
if (gbLineBuffer != nullptr) {
|
||||
if (gbLineBuffer != NULL) {
|
||||
free(gbLineBuffer);
|
||||
gbLineBuffer = nullptr;
|
||||
gbLineBuffer = NULL;
|
||||
}
|
||||
|
||||
if (g_pix != nullptr) {
|
||||
if (g_pix != NULL) {
|
||||
free(g_pix);
|
||||
g_pix = nullptr;
|
||||
g_pix = NULL;
|
||||
}
|
||||
|
||||
gbSgbShutdown();
|
||||
|
||||
if (gbVram != nullptr) {
|
||||
if (gbVram != NULL) {
|
||||
free(gbVram);
|
||||
gbVram = nullptr;
|
||||
gbVram = NULL;
|
||||
}
|
||||
|
||||
if (gbWram != nullptr) {
|
||||
if (gbWram != NULL) {
|
||||
free(gbWram);
|
||||
gbWram = nullptr;
|
||||
gbWram = NULL;
|
||||
}
|
||||
|
||||
if (gbTAMA5ram != nullptr) {
|
||||
if (gbTAMA5ram != NULL) {
|
||||
free(gbTAMA5ram);
|
||||
gbTAMA5ram = nullptr;
|
||||
gbTAMA5ram = NULL;
|
||||
}
|
||||
|
||||
g_gbCartData = gbCartData();
|
||||
g_mapper = nullptr;
|
||||
g_mapperRAM = nullptr;
|
||||
g_mapperReadRAM = nullptr;
|
||||
g_mapperUpdateClock = nullptr;
|
||||
g_mapper = NULL;
|
||||
g_mapperRAM = NULL;
|
||||
g_mapperReadRAM = NULL;
|
||||
g_mapperUpdateClock = NULL;
|
||||
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
||||
|
||||
#if !defined(__LIBRETRO__)
|
||||
@@ -3827,39 +3828,39 @@ void gbCleanUp()
|
||||
bool gbLoadRom(const char* filename) {
|
||||
int romSize = 0;
|
||||
|
||||
if (gbRom != nullptr) {
|
||||
if (gbRom != NULL) {
|
||||
gbCleanUp();
|
||||
}
|
||||
|
||||
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
||||
|
||||
gbRom = utilLoad(filename, utilIsGBImage, nullptr, romSize);
|
||||
gbRom = utilLoad(filename, utilIsGBImage, NULL, romSize);
|
||||
if (!gbRom)
|
||||
return false;
|
||||
|
||||
g_gbBatteryError = false;
|
||||
|
||||
if (g_bios != nullptr) {
|
||||
if (g_bios != NULL) {
|
||||
free(g_bios);
|
||||
g_bios = nullptr;
|
||||
g_bios = NULL;
|
||||
}
|
||||
g_bios = (uint8_t*)calloc(1, kGBBiosBufferSize);
|
||||
if (g_bios == nullptr) {
|
||||
if (g_bios == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gbMemory = (uint8_t*)malloc(65536);
|
||||
if (gbMemory == nullptr) {
|
||||
if (gbMemory == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
g_pix = (uint8_t*)calloc(1, kGBPixSize);
|
||||
if (g_pix == nullptr) {
|
||||
if (g_pix == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gbLineBuffer = (uint16_t*)malloc(kGBLineBufferSize);
|
||||
if (gbLineBuffer == nullptr) {
|
||||
if (gbLineBuffer == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3905,7 +3906,7 @@ void gbDrawLine()
|
||||
uint8_t* dest = (uint8_t*)g_pix + gbBorderLineSkip * (register_LY + gbBorderRowSkip)
|
||||
+ gbBorderColumnSkip;
|
||||
#else
|
||||
uint8_t* dest = (uint8_t*)g_pix + (gbBorderLineSkip + 2) * (register_LY + gbBorderRowSkip + 1)
|
||||
uint8_t* dest = (uint8_t*)g_pix + (gbBorderLineSkip + 4) * (register_LY + gbBorderRowSkip + 1)
|
||||
+ gbBorderColumnSkip;
|
||||
#endif
|
||||
for (size_t x = 0; x < kGBWidth;) {
|
||||
@@ -3932,7 +3933,7 @@ void gbDrawLine()
|
||||
if (gbBorderOn)
|
||||
dest += gbBorderColumnSkip;
|
||||
#ifndef __LIBRETRO__
|
||||
*dest++ = 0; // for filters that read one pixel more
|
||||
* dest++ = 0; // for filters that read one pixel more
|
||||
#endif
|
||||
} break;
|
||||
case 16: {
|
||||
@@ -3970,48 +3971,67 @@ void gbDrawLine()
|
||||
*dest++ = 0; // for filters that read one pixel more
|
||||
#endif
|
||||
} break;
|
||||
|
||||
case 24: {
|
||||
uint8_t* dest = (uint8_t*)g_pix + 3 * (gbBorderLineSkip * (register_LY + gbBorderRowSkip) + gbBorderColumnSkip);
|
||||
#ifdef __LIBRETRO__
|
||||
uint8_t* dest = (uint8_t*)g_pix + (gbBorderLineSkip * 3) * (register_LY + gbBorderRowSkip)
|
||||
+ (gbBorderColumnSkip * 3);
|
||||
#else
|
||||
uint8_t* dest = (uint8_t*)g_pix + (gbBorderLineSkip * 3) * (register_LY + gbBorderRowSkip + 1)
|
||||
+ (gbBorderColumnSkip * 3);
|
||||
#endif
|
||||
for (size_t x = 0; x < kGBWidth;) {
|
||||
*((uint32_t*)dest) = systemColorMap32[gbLineMix[x++]];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[gbLineMix[x++]];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[gbLineMix[x++]];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[gbLineMix[x++]];
|
||||
dest += 3;
|
||||
uint32_t color = systemColorMap32[gbLineMix[x++]];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
color = systemColorMap32[gbLineMix[x++]];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
color = systemColorMap32[gbLineMix[x++]];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
color = systemColorMap32[gbLineMix[x++]];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
|
||||
*((uint32_t*)dest) = systemColorMap32[gbLineMix[x++]];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[gbLineMix[x++]];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[gbLineMix[x++]];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[gbLineMix[x++]];
|
||||
dest += 3;
|
||||
color = systemColorMap32[gbLineMix[x++]];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
color = systemColorMap32[gbLineMix[x++]];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
color = systemColorMap32[gbLineMix[x++]];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
color = systemColorMap32[gbLineMix[x++]];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
|
||||
*((uint32_t*)dest) = systemColorMap32[gbLineMix[x++]];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[gbLineMix[x++]];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[gbLineMix[x++]];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[gbLineMix[x++]];
|
||||
dest += 3;
|
||||
|
||||
*((uint32_t*)dest) = systemColorMap32[gbLineMix[x++]];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[gbLineMix[x++]];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[gbLineMix[x++]];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[gbLineMix[x++]];
|
||||
dest += 3;
|
||||
color = systemColorMap32[gbLineMix[x++]];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
color = systemColorMap32[gbLineMix[x++]];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
color = systemColorMap32[gbLineMix[x++]];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
color = systemColorMap32[gbLineMix[x++]];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
}
|
||||
} break;
|
||||
|
||||
case 32: {
|
||||
#ifdef __LIBRETRO__
|
||||
uint32_t* dest = (uint32_t*)g_pix + gbBorderLineSkip * (register_LY + gbBorderRowSkip)
|
||||
@@ -4946,14 +4966,14 @@ void gbEmulate(int ticksToStop)
|
||||
}
|
||||
|
||||
bool gbLoadRomData(const char* data, size_t size) {
|
||||
if (gbRom != nullptr) {
|
||||
if (gbRom != NULL) {
|
||||
gbCleanUp();
|
||||
}
|
||||
|
||||
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
||||
|
||||
gbRom = (uint8_t*)calloc(1, size);
|
||||
if (gbRom == nullptr) {
|
||||
if (gbRom == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -4961,28 +4981,28 @@ bool gbLoadRomData(const char* data, size_t size) {
|
||||
|
||||
g_gbBatteryError = false;
|
||||
|
||||
if (g_bios != nullptr) {
|
||||
if (g_bios != NULL) {
|
||||
free(g_bios);
|
||||
g_bios = nullptr;
|
||||
g_bios = NULL;
|
||||
}
|
||||
|
||||
g_bios = (uint8_t*)calloc(1, kGBBiosBufferSize);
|
||||
if (g_bios == nullptr) {
|
||||
if (g_bios == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gbMemory = (uint8_t*)malloc(65536);
|
||||
if (gbMemory == nullptr) {
|
||||
if (gbMemory == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
g_pix = (uint8_t*)calloc(1, kGBPixSize);
|
||||
if (g_pix == nullptr) {
|
||||
if (g_pix == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
gbLineBuffer = (uint16_t*)malloc(kGBLineBufferSize);
|
||||
if (gbLineBuffer == nullptr) {
|
||||
if (gbLineBuffer == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -5033,7 +5053,7 @@ unsigned int gbWriteSaveState(uint8_t* data)
|
||||
if (g_gbCartData.mapper_type() == gbCartData::MapperType::kHuC3)
|
||||
utilWriteMem(data, &gbRTCHuC3, sizeof(gbRTCHuC3));
|
||||
utilWriteMem(data, &gbDataTAMA5, sizeof(gbDataTAMA5));
|
||||
if (gbTAMA5ram != nullptr)
|
||||
if (gbTAMA5ram != NULL)
|
||||
utilWriteMem(data, gbTAMA5ram, kTama5RamSize);
|
||||
utilWriteMem(data, &gbDataMMM01, sizeof(gbDataMMM01));
|
||||
|
||||
@@ -5118,27 +5138,27 @@ bool gbReadSaveState(const uint8_t* data)
|
||||
|
||||
// Correct crash when loading color gameboy save in regular gameboy type.
|
||||
if (gbCgbMode) {
|
||||
if (gbVram == nullptr) {
|
||||
if (gbVram == NULL) {
|
||||
gbVram = (uint8_t*)calloc(1, kGBVRamSize);
|
||||
if (gbVram == nullptr) {
|
||||
if (gbVram == NULL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (gbWram == nullptr) {
|
||||
if (gbWram == NULL) {
|
||||
gbWram = (uint8_t*)malloc(kGBWRamSize);
|
||||
if (gbWram == nullptr) {
|
||||
if (gbWram == NULL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
memset(gbPalette, 0, sizeof(gbPalette));
|
||||
} else {
|
||||
if (gbVram != nullptr) {
|
||||
if (gbVram != NULL) {
|
||||
free(gbVram);
|
||||
gbVram = nullptr;
|
||||
gbVram = NULL;
|
||||
}
|
||||
if (gbWram != nullptr) {
|
||||
if (gbWram != NULL) {
|
||||
free(gbWram);
|
||||
gbWram = nullptr;
|
||||
gbWram = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -55,7 +55,7 @@ void gbRenderLine()
|
||||
bank1 = &gbVram[0x2000];
|
||||
} else {
|
||||
bank0 = &gbMemory[0x8000];
|
||||
bank1 = nullptr;
|
||||
bank1 = NULL;
|
||||
}
|
||||
|
||||
int tile_map = 0x1800;
|
||||
@@ -92,7 +92,7 @@ void gbRenderLine()
|
||||
int tile_map_address = tile_map_line_y + tx;
|
||||
|
||||
uint8_t _attrs = 0;
|
||||
if (bank1 != nullptr)
|
||||
if (bank1 != NULL)
|
||||
_attrs = bank1[tile_map_address];
|
||||
|
||||
uint8_t tile = bank0[tile_map_address];
|
||||
@@ -406,7 +406,7 @@ void gbDrawSpriteTile(int tile, int x, int y, int t, int flags,
|
||||
bank1 = &gbVram[0x2000];
|
||||
} else {
|
||||
bank0 = &gbMemory[0x8000];
|
||||
bank1 = nullptr;
|
||||
bank1 = NULL;
|
||||
}
|
||||
|
||||
int SpritesTicks = gbSpritesTicks[x + 8] * (gbSpeed ? 2 : 4);
|
||||
|
@@ -1,14 +1,15 @@
|
||||
#include "core/gb/gbGlobals.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
uint8_t* gbMemoryMap[16];
|
||||
|
||||
uint8_t* gbMemory = nullptr;
|
||||
uint8_t* gbVram = nullptr;
|
||||
uint8_t* gbRom = nullptr;
|
||||
uint8_t* gbRam = nullptr;
|
||||
uint8_t* gbWram = nullptr;
|
||||
uint16_t* gbLineBuffer = nullptr;
|
||||
uint8_t* gbTAMA5ram = nullptr;
|
||||
uint8_t* gbMemory = NULL;
|
||||
uint8_t* gbVram = NULL;
|
||||
uint8_t* gbRom = NULL;
|
||||
uint8_t* gbRam = NULL;
|
||||
uint8_t* gbWram = NULL;
|
||||
uint16_t* gbLineBuffer = NULL;
|
||||
uint8_t* gbTAMA5ram = NULL;
|
||||
|
||||
uint16_t gbPalette[128];
|
||||
uint8_t gbBgp[4] = { 0, 1, 2, 3 };
|
||||
@@ -29,4 +30,4 @@ bool gbCgbMode = false;
|
||||
bool gbSgbMode = false;
|
||||
bool gbColorOption = false;
|
||||
|
||||
uint8_t (*gbSerialFunction)(uint8_t) = nullptr;
|
||||
uint8_t (*gbSerialFunction)(uint8_t) = NULL;
|
||||
|
@@ -16,7 +16,7 @@ extern long soundSampleRate; // current sound quality
|
||||
gb_effects_config_t gb_effects_config = { false, 0.20f, 0.15f, false };
|
||||
|
||||
static gb_effects_config_t gb_effects_config_current;
|
||||
static Simple_Effects_Buffer* stereo_buffer;
|
||||
static Simple_Effects_Buffer* stereo_buffer = 0;
|
||||
static Gb_Apu* gb_apu;
|
||||
|
||||
static float soundVolume_ = -1;
|
||||
|
@@ -117,7 +117,7 @@ std::map<std::string, uint32_t> dexp_vars;
|
||||
# ifndef YY_NULLPTR
|
||||
# if defined __cplusplus
|
||||
# if 201103L <= __cplusplus
|
||||
# define YY_NULLPTR nullptr
|
||||
# define YY_NULLPTR NULL
|
||||
# else
|
||||
# define YY_NULLPTR 0
|
||||
# endif
|
||||
|
@@ -1675,16 +1675,31 @@ void GBAMatrixWrite16(GBAMatrix_t *matrix, uint32_t address, uint16_t value)
|
||||
}
|
||||
}
|
||||
|
||||
static size_t get_gba_rom_size(const char* szFile)
|
||||
{
|
||||
size_t size = 0;
|
||||
FILE *f = fopen(szFile, "rb");
|
||||
|
||||
if (f == NULL)
|
||||
return 0;
|
||||
|
||||
fseek(f, 0, SEEK_END);
|
||||
size = ftell(f);
|
||||
fclose(f);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
int CPULoadRom(const char* szFile)
|
||||
{
|
||||
romSize = SIZE_ROM * 4;
|
||||
romSize = get_gba_rom_size(szFile);
|
||||
if (g_rom != NULL) {
|
||||
CPUCleanUp();
|
||||
}
|
||||
|
||||
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
||||
|
||||
g_rom = (uint8_t*)malloc(SIZE_ROM * 4);
|
||||
g_rom = (uint8_t*)malloc(romSize);
|
||||
if (g_rom == NULL) {
|
||||
systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
|
||||
"ROM");
|
||||
@@ -1829,14 +1844,14 @@ int CPULoadRom(const char* szFile)
|
||||
|
||||
int CPULoadRomData(const char* data, int size)
|
||||
{
|
||||
romSize = SIZE_ROM * 4;
|
||||
romSize = size % 2 == 0 ? size : size + 1;
|
||||
if (g_rom != NULL) {
|
||||
CPUCleanUp();
|
||||
}
|
||||
|
||||
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
||||
|
||||
g_rom = (uint8_t*)malloc(SIZE_ROM * 4);
|
||||
g_rom = (uint8_t*)malloc(romSize);
|
||||
if (g_rom == NULL) {
|
||||
systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
|
||||
"ROM");
|
||||
@@ -1869,7 +1884,7 @@ int CPULoadRomData(const char* data, int size)
|
||||
memcpy(&ident, &g_rom[0xAC], 1);
|
||||
|
||||
if (ident == 'M') {
|
||||
g_rom2 = (uint8_t *)malloc(SIZE_ROM * 4);
|
||||
g_rom2 = (uint8_t *)malloc(romSize);
|
||||
memcpy(g_rom2, data, size);
|
||||
romSize = 0x01000000;
|
||||
|
||||
@@ -4211,7 +4226,7 @@ void CPULoop(int ticks)
|
||||
#ifdef __LIBRETRO__
|
||||
uint8_t* dest = (uint8_t*)g_pix + 240 * VCOUNT;
|
||||
#else
|
||||
uint8_t* dest = (uint8_t*)g_pix + 242 * (VCOUNT + 1);
|
||||
uint8_t* dest = (uint8_t*)g_pix + 244 * (VCOUNT + 1);
|
||||
#endif
|
||||
for (int x = 0; x < 240;) {
|
||||
*dest++ = systemColorMap8[g_lineMix[x++] & 0xFFFF];
|
||||
@@ -4234,9 +4249,9 @@ void CPULoop(int ticks)
|
||||
*dest++ = systemColorMap8[g_lineMix[x++] & 0xFFFF];
|
||||
*dest++ = systemColorMap8[g_lineMix[x++] & 0xFFFF];
|
||||
}
|
||||
// for filters that read past the screen
|
||||
// for filters that read past the screen
|
||||
#ifndef __LIBRETRO__
|
||||
*dest++ = 0;
|
||||
* dest++ = 0;
|
||||
#endif
|
||||
} break;
|
||||
case 16: {
|
||||
@@ -4272,43 +4287,58 @@ void CPULoop(int ticks)
|
||||
#endif
|
||||
} break;
|
||||
case 24: {
|
||||
uint8_t* dest = (uint8_t*)g_pix + 240 * VCOUNT * 3;
|
||||
uint8_t* dest = (uint8_t*)g_pix + (240 * 3) * (VCOUNT + 1);
|
||||
for (int x = 0; x < 240;) {
|
||||
*((uint32_t*)dest) = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
dest += 3;
|
||||
uint32_t color = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
color = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
color = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
color = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
|
||||
*((uint32_t*)dest) = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
dest += 3;
|
||||
color = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
color = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
color = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
color = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
|
||||
*((uint32_t*)dest) = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
dest += 3;
|
||||
|
||||
*((uint32_t*)dest) = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
dest += 3;
|
||||
*((uint32_t*)dest) = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
dest += 3;
|
||||
color = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
color = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
color = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
color = systemColorMap32[g_lineMix[x++] & 0xFFFF];
|
||||
*dest++ = (uint8_t)(color & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 8) & 0xFF);
|
||||
*dest++ = (uint8_t)((color >> 16) & 0xFF);
|
||||
}
|
||||
} break;
|
||||
case 32: {
|
||||
|
@@ -31,7 +31,7 @@ uint32_t systemGetClock() {
|
||||
void systemSetTitle(const char*) {}
|
||||
|
||||
std::unique_ptr<SoundDriver> systemSoundInit() {
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void systemOnWriteDataToSoundBuffer(const uint16_t* /*finalWave*/, int /*length*/) {}
|
||||
|
@@ -1,7 +1,15 @@
|
||||
DEBUG=0
|
||||
TILED_RENDERING=0
|
||||
STATIC_LINKING=0
|
||||
FRONTEND_SUPPORTS_RGB565=1
|
||||
|
||||
ifeq ($(platform), ps2)
|
||||
FRONTEND_SUPPORT_RGB565=0
|
||||
FRONTEND_SUPPORT_BGR1555=1
|
||||
else
|
||||
FRONTEND_SUPPORT_RGB565=1
|
||||
FRONTEND_SUPPORT_BGR1555=0
|
||||
endif
|
||||
|
||||
NO_LINK=1
|
||||
|
||||
SPACE :=
|
||||
@@ -239,6 +247,16 @@ else ifeq ($(platform), psl1ght)
|
||||
PLATFORM_DEFINES := -D__PS3__ -D__POWERPC__ -D__ppc__
|
||||
STATIC_LINKING=1
|
||||
TILED_RENDERING=1
|
||||
else ifeq ($(platform), ps2)
|
||||
EXT=a
|
||||
TARGET := $(TARGET_NAME)_libretro_$(platform).$(EXT)
|
||||
CC = mips64r5900el-ps2-elf-gcc$(EXE_EXT)
|
||||
CXX = mips64r5900el-ps2-elf-g++$(EXE_EXT)
|
||||
AR = mips64r5900el-ps2-elf-ar$(EXE_EXT)
|
||||
VBA_DEFINES += -DPS2
|
||||
CFLAGS += -DHAVE_STRLWR -DPS2 -G0 -ffast-math -DABGR1555 -DNO_FAST_SQRT
|
||||
STATIC_LINKING = 1
|
||||
TILED_RENDERING=1
|
||||
|
||||
# PSP1
|
||||
else ifeq ($(platform), psp1)
|
||||
|
@@ -11,6 +11,10 @@ ifeq ($(FRONTEND_SUPPORTS_RGB565),1)
|
||||
VBA_DEFINES += -DFRONTEND_SUPPORTS_RGB565
|
||||
endif
|
||||
|
||||
ifeq ($(FRONTEND_SUPPORT_BGR1555),1)
|
||||
VBA_DEFINES += -DFRONTEND_SUPPORT_BGR1555
|
||||
endif
|
||||
|
||||
ifeq ($(NO_LINK),1)
|
||||
VBA_DEFINES += -DNO_LINK
|
||||
endif
|
||||
@@ -70,4 +74,5 @@ SOURCES_CXX += \
|
||||
# Filters
|
||||
SOURCES_CXX += \
|
||||
$(CORE_DIR)/components/filters_agb/filters_agb.cpp \
|
||||
$(CORE_DIR)/components/filters_cgb/filters_cgb.cpp \
|
||||
$(CORE_DIR)/components/filters_interframe/interframe.cpp
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#include "scrc32.h"
|
||||
|
||||
#include "components/filters_agb/filters_agb.h"
|
||||
#include "components/filters_cgb/filters_cgb.h"
|
||||
#include "components/filters_interframe/interframe.h"
|
||||
#include "core/base/check.h"
|
||||
#include "core/base/system.h"
|
||||
@@ -184,9 +185,9 @@ static void* gb_rtcdata_prt(void)
|
||||
case gbCartData::MapperType::kGameShark:
|
||||
case gbCartData::MapperType::kUnknown:
|
||||
VBAM_NOTREACHED();
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static size_t gb_rtcdata_size(void)
|
||||
@@ -611,7 +612,15 @@ void retro_init(void)
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY, &dir) && dir)
|
||||
snprintf(retro_system_directory, sizeof(retro_system_directory), "%s", dir);
|
||||
|
||||
#ifdef FRONTEND_SUPPORTS_RGB565
|
||||
#ifdef FRONTEND_SUPPORT_BGR1555
|
||||
systemColorDepth = 16;
|
||||
systemRedShift = 0;
|
||||
systemGreenShift = 5;
|
||||
systemBlueShift = 10;
|
||||
enum retro_pixel_format rgb1555 = RETRO_PIXEL_FORMAT_0RGB1555;
|
||||
if (environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &rgb1555) && log_cb)
|
||||
log_cb(RETRO_LOG_INFO, "Frontend supports BGR1555 - will use that instead of XRGB1555.\n");
|
||||
#elif defined(FRONTEND_SUPPORTS_RGB565)
|
||||
systemColorDepth = 16;
|
||||
systemRedShift = 11;
|
||||
systemGreenShift = 6;
|
||||
@@ -1012,6 +1021,11 @@ static int option_analogDeadzone;
|
||||
static int option_gyroSensitivity, option_tiltSensitivity;
|
||||
static bool option_swapAnalogSticks;
|
||||
|
||||
static int color_mode = 0;
|
||||
static int prev_color_mode = 0;
|
||||
static float color_change = 0.0f;
|
||||
static float prev_color_change = 0.0f;
|
||||
|
||||
static void update_variables(bool startup)
|
||||
{
|
||||
struct retro_variable var = { NULL, NULL };
|
||||
@@ -1215,14 +1229,47 @@ static void update_variables(bool startup)
|
||||
gbColorOption = (!strcmp(var.value, "enabled"));
|
||||
}
|
||||
|
||||
var.key = "vbam_lcdfilter_type";
|
||||
var.value = NULL;
|
||||
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
prev_color_mode = color_mode;
|
||||
if (!strcmp(var.value, "sRGB"))
|
||||
color_mode = 0;
|
||||
else if (!strcmp(var.value, "DCI"))
|
||||
color_mode = 1;
|
||||
else if (!strcmp(var.value, "Rec2020"))
|
||||
color_mode = 2;
|
||||
}
|
||||
|
||||
var.key = "vbam_color_change";
|
||||
var.value = NULL;
|
||||
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
prev_color_change = color_change;
|
||||
color_change = ((float)atoi(var.value)) / 100;
|
||||
}
|
||||
|
||||
var.key = "vbam_lcdfilter";
|
||||
var.value = NULL;
|
||||
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
|
||||
bool prev_lcdfilter = option_lcdfilter;
|
||||
option_lcdfilter = (!strcmp(var.value, "enabled")) ? true : false;
|
||||
if (prev_lcdfilter != option_lcdfilter)
|
||||
gbafilter_update_colors(option_lcdfilter);
|
||||
if ((prev_color_change != color_change) || (prev_color_mode != color_mode)) {
|
||||
if (type == IMAGE_GBA) {
|
||||
gbafilter_set_params(color_mode, color_change);
|
||||
} else {
|
||||
gbcfilter_set_params(color_mode, color_change);
|
||||
}
|
||||
}
|
||||
if ((prev_lcdfilter != option_lcdfilter) || (prev_color_change != color_change) || (prev_color_mode != color_mode)) {
|
||||
if (type == IMAGE_GBA) {
|
||||
gbafilter_update_colors(option_lcdfilter);
|
||||
} else {
|
||||
gbcfilter_update_colors(option_lcdfilter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var.key = "vbam_interframeblending";
|
||||
@@ -1755,9 +1802,9 @@ bool retro_load_game(const struct retro_game_info *game)
|
||||
return emulating;
|
||||
}
|
||||
|
||||
bool retro_load_game_special(unsigned, const struct retro_game_info *, size_t)
|
||||
bool retro_load_game_special(unsigned, const struct retro_game_info *game, size_t)
|
||||
{
|
||||
return false;
|
||||
return retro_load_game(game);
|
||||
}
|
||||
|
||||
void retro_unload_game(void)
|
||||
@@ -1787,8 +1834,10 @@ bool systemCanChangeSoundQuality(void)
|
||||
void systemDrawScreen(void)
|
||||
{
|
||||
unsigned pitch = systemWidth * (systemColorDepth >> 3);
|
||||
|
||||
if (ifb_filter_func)
|
||||
ifb_filter_func(g_pix, pitch, systemWidth, systemHeight);
|
||||
|
||||
video_cb(g_pix, systemWidth, systemHeight, pitch);
|
||||
}
|
||||
|
||||
|
@@ -203,6 +203,54 @@ struct retro_core_option_v2_definition option_defs_us[] = {
|
||||
},
|
||||
"disabled"
|
||||
},
|
||||
{
|
||||
"vbam_lcdfilter_type",
|
||||
"LCD Color Filter Type",
|
||||
NULL,
|
||||
"Screen filter type for onscreen colors.",
|
||||
NULL,
|
||||
"video",
|
||||
{
|
||||
{ "sRGB", NULL },
|
||||
{ "DCI", NULL },
|
||||
{ "Rec2020", NULL },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"sRGB"
|
||||
},
|
||||
{
|
||||
"vbam_color_change",
|
||||
"LCD Color Lighten/Darken",
|
||||
NULL,
|
||||
"Darken GBA or lighten GBC in %.",
|
||||
NULL,
|
||||
"video",
|
||||
{
|
||||
{ "0", NULL },
|
||||
{ "5", NULL },
|
||||
{ "10", NULL },
|
||||
{ "15", NULL },
|
||||
{ "20", NULL },
|
||||
{ "25", NULL },
|
||||
{ "30", NULL },
|
||||
{ "35", NULL },
|
||||
{ "40", NULL },
|
||||
{ "45", NULL },
|
||||
{ "50", NULL },
|
||||
{ "55", NULL },
|
||||
{ "60", NULL },
|
||||
{ "65", NULL },
|
||||
{ "70", NULL },
|
||||
{ "75", NULL },
|
||||
{ "80", NULL },
|
||||
{ "85", NULL },
|
||||
{ "90", NULL },
|
||||
{ "95", NULL },
|
||||
{ "100", NULL },
|
||||
{ NULL, NULL },
|
||||
},
|
||||
"0"
|
||||
},
|
||||
{
|
||||
"vbam_interframeblending",
|
||||
"Interframe Blending",
|
||||
|
@@ -21,3 +21,4 @@ firmware2_desc = "gbc_bios.bin (Game Boy Color BIOS)"
|
||||
firmware2_path = "gbc_bios.bin"
|
||||
firmware2_opt = "true"
|
||||
notes = "(!) gba_bios.bin (md5): a860e8c0b6d573d191e4ec7db1b1e4f6|(!) gb_bios.bin (md5): 32fbbd84168d3482956eb3c5051637f5|(!) gbc_bios.bin (md5): dbfce9db9deaa2567f6a84fde55f9680"
|
||||
|
||||
|
@@ -55,6 +55,7 @@ target_link_libraries(vbam
|
||||
vbam-components-draw-text
|
||||
vbam-components-filters
|
||||
vbam-components-filters-agb
|
||||
vbam-components-filters-cgb
|
||||
vbam-components-filters-interframe
|
||||
vbam-components-user-config
|
||||
${OPENGL_LIBRARIES}
|
||||
|
@@ -111,6 +111,7 @@
|
||||
|
||||
#include "components/draw_text/draw_text.h"
|
||||
#include "components/filters_agb/filters_agb.h"
|
||||
#include "components/filters_cgb/filters_cgb.h"
|
||||
#include "components/user_config/user_config.h"
|
||||
#include "core/base/file_util.h"
|
||||
#include "core/base/message.h"
|
||||
@@ -1163,7 +1164,7 @@ void sdlInitVideo()
|
||||
switch (systemColorDepth)
|
||||
{
|
||||
case 8:
|
||||
srcPitch = sizeX * (systemColorDepth >> 3) + 2;
|
||||
srcPitch = sizeX * (systemColorDepth >> 3) + 4;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
@@ -1186,7 +1187,7 @@ void sdlInitVideo()
|
||||
} else {
|
||||
#ifdef CONFIG_8BIT
|
||||
systemColorDepth = 8;
|
||||
srcPitch = sizeX * (systemColorDepth >> 3) + 2;
|
||||
srcPitch = sizeX * (systemColorDepth >> 3) + 4;
|
||||
#elif defined(CONFIG_16BIT)
|
||||
systemColorDepth = 16;
|
||||
srcPitch = sizeX * (systemColorDepth >> 3) + 4;
|
||||
@@ -2376,6 +2377,7 @@ int main(int argc, char** argv)
|
||||
fprintf(stdout, "Color depth: %d\n", systemColorDepth);
|
||||
|
||||
gbafilter_update_colors();
|
||||
gbcfilter_update_colors();
|
||||
|
||||
if (delta == NULL) {
|
||||
delta = (uint8_t*)malloc(delta_size);
|
||||
|
@@ -254,12 +254,12 @@ void SoundSDL::deinit() {
|
||||
SDL_Delay(100);
|
||||
|
||||
SDL_DestroySemaphore(data_available);
|
||||
data_available = nullptr;
|
||||
data_available = NULL;
|
||||
SDL_DestroySemaphore(data_read);
|
||||
data_read = nullptr;
|
||||
data_read = NULL;
|
||||
|
||||
SDL_DestroyMutex(mutex);
|
||||
mutex = nullptr;
|
||||
mutex = NULL;
|
||||
|
||||
SDL_CloseAudioDevice(sound_device);
|
||||
|
||||
|
@@ -69,16 +69,29 @@ if(NOT ZIP_PROGRAM)
|
||||
if(NOT DEFINED POWERSHELL)
|
||||
message(FATAL_ERROR "Powershell is required for extraction.")
|
||||
endif()
|
||||
|
||||
# Get zip binaries from wxrc.
|
||||
file(DOWNLOAD "https://www.willus.com/archive/zip64/infozip_binaries_win32.zip" ${CMAKE_CURRENT_BINARY_DIR}/infozip_binaries_win32.zip)
|
||||
|
||||
set(_url "https://www.willus.com/archive/zip64/infozip_binaries_win32.zip")
|
||||
set(_path "${CMAKE_CURRENT_BINARY_DIR}/infozip_binaries_win32.zip")
|
||||
set(_sha "b338a0f35e1f849d3466d4260fd8a51f2afe9cdf136cc07cc4d54b00cee13650")
|
||||
foreach(_i RANGE 1 3)
|
||||
# Get zip binaries from wxrc.
|
||||
file(DOWNLOAD "${_url}" "${_path}" SHOW_PROGRESS STATUS _s)
|
||||
list(GET _s 0 _c)
|
||||
if(_c EQUAL 0)
|
||||
file(SHA256 "${_path}" _h)
|
||||
file(SIZE "${_path}" _z)
|
||||
if(_h STREQUAL _sha AND _z GREATER 0)
|
||||
break()
|
||||
endif()
|
||||
endif()
|
||||
file(REMOVE "${_path}")
|
||||
if(_i EQUAL 3)
|
||||
message(FATAL_ERROR "Download failed or SHA256 mismatch after 3 attempts.")
|
||||
endif()
|
||||
endforeach()
|
||||
# Unzip it.
|
||||
execute_process(
|
||||
COMMAND "${POWERSHELL}" -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('${CMAKE_CURRENT_BINARY_DIR}/infozip_binaries_win32.zip', '${CMAKE_CURRENT_BINARY_DIR}'); }"
|
||||
)
|
||||
|
||||
set(ZIP_PROGRAM ${CMAKE_CURRENT_BINARY_DIR}/zip.exe CACHE STRING "zip compressor executable" FORCE)
|
||||
execute_process(COMMAND "${POWERSHELL}" -NoLogo -NoProfile -ExecutionPolicy Bypass
|
||||
-Command "& { Add-Type -A 'System.IO.Compression.FileSystem'; [IO.Compression.ZipFile]::ExtractToDirectory('${_path}', '${CMAKE_CURRENT_BINARY_DIR}'); }")
|
||||
set(ZIP_PROGRAM "${CMAKE_CURRENT_BINARY_DIR}/zip.exe" CACHE STRING "zip compressor executable" FORCE)
|
||||
endif()
|
||||
if(ZIP_PROGRAM)
|
||||
set(ZIP_PROGRAM "${ZIP_PROGRAM}" CACHE STRING "zip compressor executable" FORCE)
|
||||
@@ -424,6 +437,7 @@ target_link_libraries(
|
||||
vbam-components-draw-text
|
||||
vbam-components-filters
|
||||
vbam-components-filters-agb
|
||||
vbam-components-filters-cgb
|
||||
vbam-components-filters-interframe
|
||||
vbam-components-user-config
|
||||
vbam-wx-config
|
||||
|
@@ -60,6 +60,7 @@ std::vector<AudioDevice> EnumerateAudioDevices(const config::AudioApi& audio_api
|
||||
VBAM_NOTREACHED();
|
||||
return {};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::unique_ptr<SoundDriver> CreateSoundDriver(const config::AudioApi& api) {
|
||||
@@ -95,8 +96,9 @@ std::unique_ptr<SoundDriver> CreateSoundDriver(const config::AudioApi& api) {
|
||||
case config::AudioApi::kLast:
|
||||
default:
|
||||
VBAM_NOTREACHED();
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace audio
|
||||
|
@@ -106,12 +106,12 @@ public:
|
||||
uint16_t current_rate = 0;
|
||||
int current_buffer = 0;
|
||||
int filled_buffers = 0;
|
||||
int soundBufferLen = 0;
|
||||
AudioTimeStamp starttime;
|
||||
AudioTimeStamp timestamp;
|
||||
AudioQueueTimelineRef timeline;
|
||||
|
||||
private:
|
||||
int soundBufferLen = 0;
|
||||
AudioDeviceID GetCoreAudioDevice(wxString name);
|
||||
void setBuffer(uint16_t* finalWave, int length);
|
||||
|
||||
@@ -120,13 +120,29 @@ private:
|
||||
|
||||
static void PlaybackBufferReadyCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer)
|
||||
{
|
||||
int curbuf = 0;
|
||||
CoreAudioAudio *cadevice = (CoreAudioAudio *)inUserData;
|
||||
(void)inAQ;
|
||||
|
||||
for (curbuf = 0; curbuf < OPTION(kSoundBuffers); curbuf++) {
|
||||
if (cadevice->buffers[curbuf] == inBuffer) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (curbuf >= OPTION(kSoundBuffers))
|
||||
return;
|
||||
|
||||
// buffer is unexpectedly here? We're probably dying, but try to requeue this buffer with silence.
|
||||
if (inBuffer) {
|
||||
memset(inBuffer->mAudioData, 0, inBuffer->mAudioDataBytesCapacity);
|
||||
inBuffer->mAudioDataByteSize = 0;
|
||||
if (cadevice->buffers[curbuf] != NULL) {
|
||||
AudioQueueFreeBuffer(inAQ, cadevice->buffers[curbuf]);
|
||||
cadevice->soundBufferLen = (soundGetSampleRate() / 60) * cadevice->description.mBytesPerPacket;
|
||||
AudioQueueAllocateBuffer(inAQ, cadevice->soundBufferLen, &cadevice->buffers[curbuf]);
|
||||
cadevice->buffers[curbuf]->mAudioDataByteSize = 0;
|
||||
} else {
|
||||
cadevice->soundBufferLen = (soundGetSampleRate() / 60) * cadevice->description.mBytesPerPacket;
|
||||
AudioQueueAllocateBuffer(inAQ, cadevice->soundBufferLen, &cadevice->buffers[curbuf]);
|
||||
cadevice->buffers[curbuf]->mAudioDataByteSize = 0;
|
||||
}
|
||||
|
||||
if (cadevice->filled_buffers > 0) {
|
||||
@@ -491,8 +507,8 @@ void CoreAudioAudio::write(uint16_t* finalWave, int length) {
|
||||
current_buffer = 0;
|
||||
}
|
||||
|
||||
while (filled_buffers >= (OPTION(kSoundBuffers) - 1)) {
|
||||
wxMilliSleep(1);
|
||||
while (filled_buffers >= OPTION(kSoundBuffers)) {
|
||||
wxMilliSleep(((soundGetSampleRate() / 60) * 4) / (soundGetSampleRate() >> 7));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,8 +523,8 @@ void CoreAudioAudio::write(uint16_t* finalWave, int length) {
|
||||
current_buffer = 0;
|
||||
}
|
||||
|
||||
while (filled_buffers >= (OPTION(kSoundBuffers) - 1)) {
|
||||
wxMilliSleep(1);
|
||||
while (filled_buffers >= OPTION(kSoundBuffers)) {
|
||||
wxMilliSleep(((soundGetSampleRate() / 60) * 4) / (soundGetSampleRate() >> 7));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -333,7 +333,7 @@ void DirectSound::write(uint16_t* finalWave, int) {
|
||||
static BOOL CALLBACK DSEnumCB(LPGUID guid, LPCTSTR desc, LPCTSTR /*module*/, LPVOID user) {
|
||||
std::vector<AudioDevice>* devices = static_cast<std::vector<AudioDevice>*>(user);
|
||||
|
||||
if (guid == nullptr) {
|
||||
if (guid == NULL) {
|
||||
devices->push_back({desc, {}});
|
||||
return TRUE;
|
||||
}
|
||||
|
@@ -159,9 +159,9 @@ FAudio_Output::FAudio_Output() : buffer_count_(OPTION(kSoundBuffers)) {
|
||||
currentBuffer = 0;
|
||||
sound_buffer_len_ = 0;
|
||||
device_changed = false;
|
||||
faud = nullptr;
|
||||
mVoice = nullptr;
|
||||
sVoice = nullptr;
|
||||
faud = NULL;
|
||||
mVoice = NULL;
|
||||
sVoice = NULL;
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
memset(&vState, 0, sizeof(vState));
|
||||
}
|
||||
@@ -179,17 +179,17 @@ void FAudio_Output::close() {
|
||||
}
|
||||
|
||||
FAudioVoice_DestroyVoice(sVoice);
|
||||
sVoice = nullptr;
|
||||
sVoice = NULL;
|
||||
}
|
||||
|
||||
if (mVoice) {
|
||||
FAudioVoice_DestroyVoice(mVoice);
|
||||
mVoice = nullptr;
|
||||
mVoice = NULL;
|
||||
}
|
||||
|
||||
if (faud) {
|
||||
FAudio_Release(faud);
|
||||
faud = nullptr;
|
||||
faud = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ bool FAudio_Output::init(long sampleRate) {
|
||||
|
||||
// create sound receiver
|
||||
hr = FAudio_CreateMasteringVoice(faud, &mVoice, FAUDIO_DEFAULT_CHANNELS,
|
||||
FAUDIO_DEFAULT_SAMPLERATE, 0, FAGetDev(faud), nullptr);
|
||||
FAUDIO_DEFAULT_SAMPLERATE, 0, FAGetDev(faud), NULL);
|
||||
|
||||
if (hr != 0) {
|
||||
wxLogError(_("FAudio: Creating mastering voice failed!"));
|
||||
@@ -243,7 +243,7 @@ bool FAudio_Output::init(long sampleRate) {
|
||||
}
|
||||
|
||||
// create sound emitter
|
||||
hr = FAudio_CreateSourceVoice(faud, &sVoice, &wfx, 0, 4.0f, ¬ify, nullptr, nullptr);
|
||||
hr = FAudio_CreateSourceVoice(faud, &sVoice, &wfx, 0, 4.0f, ¬ify, NULL, NULL);
|
||||
|
||||
if (hr != 0) {
|
||||
wxLogError(_("FAudio: Creating source voice failed!"));
|
||||
@@ -346,7 +346,7 @@ bool FAudio_Output::init(long sampleRate) {
|
||||
}
|
||||
|
||||
if (matrixAvailable) {
|
||||
hr = FAudioVoice_SetOutputMatrix(sVoice, nullptr, 2, dd.OutputFormat.Format.nChannels,
|
||||
hr = FAudioVoice_SetOutputMatrix(sVoice, NULL, 2, dd.OutputFormat.Format.nChannels,
|
||||
matrix.data(), FAUDIO_DEFAULT_CHANNELS);
|
||||
VBAM_CHECK(hr == 0);
|
||||
}
|
||||
@@ -408,7 +408,7 @@ void FAudio_Output::write(uint16_t* finalWave, int) {
|
||||
buf.pAudioData = &buffers_[currentBuffer * sound_buffer_len_];
|
||||
currentBuffer++;
|
||||
currentBuffer %= (buffer_count_ + 1); // + 1 because we need one temporary buffer
|
||||
[[maybe_unused]] uint32_t hr = FAudioSourceVoice_SubmitSourceBuffer(sVoice, &buf, nullptr);
|
||||
[[maybe_unused]] uint32_t hr = FAudioSourceVoice_SubmitSourceBuffer(sVoice, &buf, NULL);
|
||||
VBAM_CHECK(hr == 0);
|
||||
}
|
||||
|
||||
@@ -463,7 +463,7 @@ void FAudio_Output::setThrottle(unsigned short throttle_) {
|
||||
} // namespace
|
||||
|
||||
std::vector<AudioDevice> GetFAudioDevices() {
|
||||
FAudio* fa = nullptr;
|
||||
FAudio* fa = NULL;
|
||||
uint32_t hr;
|
||||
uint32_t flags = 0;
|
||||
#ifdef _DEBUG
|
||||
|
@@ -94,8 +94,8 @@ private:
|
||||
OpenAL::OpenAL() {
|
||||
initialized = false;
|
||||
buffersLoaded = false;
|
||||
device = nullptr;
|
||||
context = nullptr;
|
||||
device = NULL;
|
||||
context = NULL;
|
||||
buffer = (ALuint*)malloc(OPTION(kSoundBuffers) * sizeof(ALuint));
|
||||
memset(buffer, 0, OPTION(kSoundBuffers) * sizeof(ALuint));
|
||||
tempBuffer = 0;
|
||||
@@ -115,7 +115,7 @@ OpenAL::~OpenAL() {
|
||||
alDeleteBuffers(OPTION(kSoundBuffers), buffer);
|
||||
ASSERT_SUCCESS;
|
||||
free(buffer);
|
||||
alcMakeContextCurrent(nullptr);
|
||||
alcMakeContextCurrent(NULL);
|
||||
// Wine incorrectly returns ALC_INVALID_VALUE
|
||||
// and then fails the rest of these functions as well
|
||||
// so there will be a leak under Wine, but that's a bug in Wine, not
|
||||
@@ -175,13 +175,13 @@ bool OpenAL::init(long sampleRate) {
|
||||
const wxString& audio_device = OPTION(kSoundAudioDevice);
|
||||
if (!audio_device.empty()) {
|
||||
device = alcOpenDevice(audio_device.utf8_str());
|
||||
if (device == nullptr) {
|
||||
if (device == NULL) {
|
||||
// Might be the default device. Try again.
|
||||
OPTION(kSoundAudioDevice) = wxEmptyString;
|
||||
device = alcOpenDevice(nullptr);
|
||||
device = alcOpenDevice(NULL);
|
||||
}
|
||||
} else {
|
||||
device = alcOpenDevice(nullptr);
|
||||
device = alcOpenDevice(NULL);
|
||||
}
|
||||
|
||||
if (!device) {
|
||||
@@ -189,8 +189,8 @@ bool OpenAL::init(long sampleRate) {
|
||||
return false;
|
||||
}
|
||||
|
||||
context = alcCreateContext(device, nullptr);
|
||||
VBAM_CHECK(context != nullptr);
|
||||
context = alcCreateContext(device, NULL);
|
||||
VBAM_CHECK(context != NULL);
|
||||
ALCboolean retVal = alcMakeContextCurrent(context);
|
||||
VBAM_CHECK(ALC_TRUE == retVal);
|
||||
alGenBuffers(OPTION(kSoundBuffers), buffer);
|
||||
@@ -368,12 +368,12 @@ std::vector<AudioDevice> GetOpenALDevices() {
|
||||
|
||||
#ifdef ALC_DEVICE_SPECIFIER
|
||||
|
||||
if (alcIsExtensionPresent(nullptr, "ALC_ENUMERATION_EXT") == AL_FALSE) {
|
||||
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATION_EXT") == AL_FALSE) {
|
||||
// this extension isn't critical to OpenAL operating
|
||||
return devices;
|
||||
}
|
||||
|
||||
const char* devs = alcGetString(nullptr, ALC_DEVICE_SPECIFIER);
|
||||
const char* devs = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
|
||||
|
||||
while (*devs) {
|
||||
const wxString device_name(devs, wxConvLibc);
|
||||
|
@@ -104,7 +104,7 @@ void SDLAudio::deinit() {
|
||||
SDL_UnlockMutex(mutex);
|
||||
|
||||
SDL_DestroyMutex(mutex);
|
||||
mutex = nullptr;
|
||||
mutex = NULL;
|
||||
|
||||
SDL_CloseAudioDevice(sound_device);
|
||||
|
||||
@@ -152,13 +152,13 @@ bool SDLAudio::init(long sampleRate) {
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#ifdef ENABLE_SDL3
|
||||
if (SDL_WasInit(SDL_INIT_AUDIO) == false) {
|
||||
if (SDL_Init(SDL_INIT_AUDIO) == false) {
|
||||
#else
|
||||
if (SDL_WasInit(SDL_INIT_AUDIO) < 0) {
|
||||
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
|
||||
#endif
|
||||
SDL_Init(SDL_INIT_AUDIO);
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SDL3
|
||||
|
@@ -584,7 +584,7 @@ void xaudio2_device_changed(XAudio2_Output* instance) {
|
||||
|
||||
std::vector<AudioDevice> GetXAudio2Devices() {
|
||||
HRESULT hr;
|
||||
IXAudio2* xa = nullptr;
|
||||
IXAudio2* xa = NULL;
|
||||
hr = XAudio2Create(&xa, 0);
|
||||
|
||||
if (hr != S_OK) {
|
||||
|
@@ -36,5 +36,5 @@ SparkleWrapper::~SparkleWrapper()
|
||||
|
||||
void SparkleWrapper::checkForUpdatesUi()
|
||||
{
|
||||
[d->updater checkForUpdates: nullptr];
|
||||
[d->updater checkForUpdates: NULL];
|
||||
}
|
||||
|
@@ -42,7 +42,7 @@ WinSparkleDllWrapper::WinSparkleDllWrapper()
|
||||
|
||||
winsparkle_dll = LoadLibraryW(temp_file_name.wc_str());
|
||||
|
||||
if (winsparkle_dll != nullptr) {
|
||||
if (winsparkle_dll != NULL) {
|
||||
winsparkle_init = reinterpret_cast<func_win_sparkle_init>(GetProcAddress(winsparkle_dll, "win_sparkle_init"));
|
||||
winsparkle_check_update_with_ui = reinterpret_cast<func_win_sparkle_check_update_with_ui>(GetProcAddress(winsparkle_dll, "win_sparkle_check_update_with_ui"));
|
||||
winsparkle_set_appcast_url = reinterpret_cast<func_win_sparkle_set_appcast_url>(GetProcAddress(winsparkle_dll, "win_sparkle_set_appcast_url"));
|
||||
@@ -54,7 +54,7 @@ WinSparkleDllWrapper::WinSparkleDllWrapper()
|
||||
|
||||
WinSparkleDllWrapper::~WinSparkleDllWrapper()
|
||||
{
|
||||
if (winsparkle_dll != nullptr) {
|
||||
if (winsparkle_dll != NULL) {
|
||||
while(::FreeLibrary(winsparkle_dll)) {
|
||||
wxMilliSleep(200);
|
||||
}
|
||||
|
@@ -22,11 +22,11 @@ private:
|
||||
|
||||
HMODULE winsparkle_dll;
|
||||
|
||||
func_win_sparkle_init winsparkle_init = nullptr;
|
||||
func_win_sparkle_check_update_with_ui winsparkle_check_update_with_ui = nullptr;
|
||||
func_win_sparkle_set_appcast_url winsparkle_set_appcast_url = nullptr;
|
||||
func_win_sparkle_set_app_details winsparkle_set_app_details = nullptr;
|
||||
func_win_sparkle_cleanup winsparkle_cleanup = nullptr;
|
||||
func_win_sparkle_init winsparkle_init = NULL;
|
||||
func_win_sparkle_check_update_with_ui winsparkle_check_update_with_ui = NULL;
|
||||
func_win_sparkle_set_appcast_url winsparkle_set_appcast_url = NULL;
|
||||
func_win_sparkle_set_app_details winsparkle_set_app_details = NULL;
|
||||
func_win_sparkle_cleanup winsparkle_cleanup = NULL;
|
||||
|
||||
wxString temp_file_name;
|
||||
|
||||
|
@@ -494,7 +494,7 @@ private:
|
||||
SHORT previousState[0xFF];
|
||||
#elif defined(__WXMAC__)
|
||||
#else // defined(__WXGTK__)
|
||||
Display *x11display = nullptr;
|
||||
Display *x11display = NULL;
|
||||
char previousState[32];
|
||||
char currentState[32];
|
||||
int keySymsPerKeycode;
|
||||
@@ -629,7 +629,7 @@ void BackgroundInput::Cleanup()
|
||||
#else // defined(__WXGTK__)
|
||||
if (x11display) {
|
||||
XCloseDisplay(x11display);
|
||||
x11display = nullptr;
|
||||
x11display = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -648,7 +648,7 @@ wxThread::ExitCode BackgroundInput::Entry()
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
BackgroundInput *input = nullptr;
|
||||
BackgroundInput *input = NULL;
|
||||
|
||||
void enableKeyboardBackgroundInput(wxEvtHandler* handler)
|
||||
{
|
||||
@@ -658,7 +658,7 @@ void enableKeyboardBackgroundInput(wxEvtHandler* handler)
|
||||
{
|
||||
wxLogError(wxT("Failed to create keyboard thread!"));
|
||||
delete input;
|
||||
input = nullptr;
|
||||
input = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -667,5 +667,5 @@ void disableKeyboardBackgroundInput()
|
||||
if (input && input->IsRunning()) {
|
||||
input->Delete();
|
||||
}
|
||||
input = nullptr;
|
||||
input = NULL;
|
||||
}
|
||||
|
@@ -58,7 +58,7 @@ void RefreshFrame(void)
|
||||
if (wxGetApp().frame)
|
||||
wxGetApp().frame->Destroy();
|
||||
|
||||
wxGetApp().frame = wxDynamicCast(xr->LoadFrame(nullptr, "MainFrame"), MainFrame);
|
||||
wxGetApp().frame = wxDynamicCast(xr->LoadFrame(NULL, "MainFrame"), MainFrame);
|
||||
if (!wxGetApp().frame) {
|
||||
wxLogError(_("Could not create main window"));
|
||||
return;
|
||||
@@ -2330,7 +2330,7 @@ EVT_HANDLER(UpdateEmu, "Check for updates...")
|
||||
EVT_HANDLER(FactoryReset, "Factory Reset...")
|
||||
{
|
||||
wxMessageDialog dlg(
|
||||
nullptr, _("YOUR CONFIGURATION WILL BE DELETED!\n\nAre you sure?"),
|
||||
NULL, _("YOUR CONFIGURATION WILL BE DELETED!\n\nAre you sure?"),
|
||||
_("FACTORY RESET"), wxYES_NO | wxNO_DEFAULT | wxCENTRE);
|
||||
|
||||
if (dlg.ShowModal() == wxID_YES) {
|
||||
@@ -2800,26 +2800,6 @@ EVT_HANDLER(Language3, "Czech")
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language4, "German")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_GERMAN;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_GERMAN);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language5, "Greek")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_GREEK;
|
||||
|
@@ -29,7 +29,7 @@ cmditem new_cmditem(const wxString cmd = "",
|
||||
const wxString name = "",
|
||||
int cmd_id = 0,
|
||||
int mask_flags = 0,
|
||||
wxMenuItem* mi = nullptr);
|
||||
wxMenuItem* mi = NULL);
|
||||
|
||||
namespace config {
|
||||
// Returns the command INI entry name for the given XRC ID. Will assert if
|
||||
|
@@ -83,6 +83,15 @@ static const std::array<wxString, kNbRenderMethods> kRenderMethodStrings = {
|
||||
#endif
|
||||
};
|
||||
|
||||
// These MUST follow the same order as the definitions of the enum.
|
||||
// Adding an option without adding to this array will result in a compiler
|
||||
// error since kNbColorCorrectionProfiles is automatically updated.
|
||||
static const std::array<wxString, kNbColorCorrectionProfiles> kColorCorrectionProfileStrings = {
|
||||
"srgb",
|
||||
"dci",
|
||||
"rec2020"
|
||||
};
|
||||
|
||||
// These MUST follow the same order as the definitions of the enum above.
|
||||
// Adding an option without adding to this array will result in a compiler
|
||||
// error since kNbAudioApis is automatically updated.
|
||||
@@ -142,6 +151,7 @@ std::array<Option, kNbOptions>& Option::All() {
|
||||
struct OwnedOptions {
|
||||
/// Display
|
||||
bool bilinear = true;
|
||||
bool sdl_pixel_art = false;
|
||||
Filter filter = Filter::kNone;
|
||||
wxString filter_plugin = wxEmptyString;
|
||||
Interframe interframe = Interframe::kNone;
|
||||
@@ -158,27 +168,32 @@ std::array<Option, kNbOptions>& Option::All() {
|
||||
RenderMethod render_method = RenderMethod::kOpenGL;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ColorCorrectionProfile color_correction_profile = ColorCorrectionProfile::kSRGB;
|
||||
|
||||
double video_scale = 3;
|
||||
bool retain_aspect = true;
|
||||
|
||||
/// GB
|
||||
wxString gb_bios = wxEmptyString;
|
||||
bool colorizer_hack = false;
|
||||
bool gb_lcd_filter = false;
|
||||
bool gb_lcd_filter = true;
|
||||
wxString gbc_bios = wxEmptyString;
|
||||
bool print_auto_page = true;
|
||||
bool print_screen_cap = false;
|
||||
wxString gb_rom_dir = wxEmptyString;
|
||||
wxString gbc_rom_dir = wxEmptyString;
|
||||
uint32_t gb_lighten = 0;
|
||||
|
||||
/// GBA
|
||||
bool gba_lcd_filter = false;
|
||||
bool gba_lcd_filter = true;
|
||||
#ifndef NO_LINK
|
||||
bool link_auto = false;
|
||||
bool link_hacks = true;
|
||||
bool link_proto = false;
|
||||
#endif
|
||||
wxString gba_rom_dir;
|
||||
uint32_t gba_darken = 37;
|
||||
|
||||
/// Core
|
||||
bool agb_print = false;
|
||||
@@ -266,6 +281,7 @@ std::array<Option, kNbOptions>& Option::All() {
|
||||
static std::array<Option, kNbOptions> g_all_opts = {
|
||||
/// Display
|
||||
Option(OptionID::kDispBilinear, &g_owned_opts.bilinear),
|
||||
Option(OptionID::kDispSDLPixelArt, &g_owned_opts.sdl_pixel_art),
|
||||
Option(OptionID::kDispFilter, &g_owned_opts.filter),
|
||||
Option(OptionID::kDispFilterPlugin, &g_owned_opts.filter_plugin),
|
||||
Option(OptionID::kDispIFB, &g_owned_opts.interframe),
|
||||
@@ -276,6 +292,7 @@ std::array<Option, kNbOptions>& Option::All() {
|
||||
Option(OptionID::kDispScale, &g_owned_opts.video_scale, 1, 6),
|
||||
Option(OptionID::kDispStretch, &g_owned_opts.retain_aspect),
|
||||
Option(OptionID::kSDLRenderer, &g_owned_opts.sdlrenderer),
|
||||
Option(OptionID::kDispColorCorrectionProfile, &g_owned_opts.color_correction_profile),
|
||||
|
||||
/// GB
|
||||
Option(OptionID::kGBBiosFile, &g_owned_opts.gb_bios),
|
||||
@@ -290,6 +307,7 @@ std::array<Option, kNbOptions>& Option::All() {
|
||||
Option(OptionID::kGBPrintScreenCap, &g_owned_opts.print_screen_cap),
|
||||
Option(OptionID::kGBROMDir, &g_owned_opts.gb_rom_dir),
|
||||
Option(OptionID::kGBGBCROMDir, &g_owned_opts.gbc_rom_dir),
|
||||
Option(OptionID::kGBLighten, &g_owned_opts.gb_lighten, 0, 100),
|
||||
|
||||
/// GBA
|
||||
Option(OptionID::kGBABiosFile, &gopts.gba_bios),
|
||||
@@ -305,6 +323,7 @@ std::array<Option, kNbOptions>& Option::All() {
|
||||
Option(OptionID::kGBALinkType, &gopts.gba_link_type, 0, 5),
|
||||
#endif
|
||||
Option(OptionID::kGBAROMDir, &g_owned_opts.gba_rom_dir),
|
||||
Option(OptionID::kGBADarken, &g_owned_opts.gba_darken, 0, 100),
|
||||
|
||||
/// General
|
||||
Option(OptionID::kGenAutoLoadLastState, &g_owned_opts.autoload_state),
|
||||
@@ -410,6 +429,7 @@ namespace internal {
|
||||
const std::array<OptionData, kNbOptions + 1> kAllOptionsData = {
|
||||
/// Display
|
||||
OptionData{"Display/Bilinear", "Bilinear", _("Use bilinear filter with 3d renderer")},
|
||||
OptionData{"Display/SDLPixelArt", "SDLPixelArt", _("Use the SDL pixel art filter with an SDL renderer")},
|
||||
OptionData{"Display/Filter", "", _("Full-screen filter to apply")},
|
||||
OptionData{"Display/FilterPlugin", "", _("Filter plugin library")},
|
||||
OptionData{"Display/IFB", "", _("Interframe blending function")},
|
||||
@@ -422,6 +442,7 @@ const std::array<OptionData, kNbOptions + 1> kAllOptionsData = {
|
||||
OptionData{"Display/Scale", "", _("Default scale factor")},
|
||||
OptionData{"Display/Stretch", "RetainAspect", _("Retain aspect ratio when resizing")},
|
||||
OptionData{"Display/SDLRenderer", "", _("SDL renderer")},
|
||||
OptionData{"Display/ColorCorrectionProfile", "", _("Color correction profile")},
|
||||
|
||||
/// GB
|
||||
OptionData{"GB/BiosFile", "", _("BIOS file to use for Game Boy, if enabled")},
|
||||
@@ -445,6 +466,7 @@ const std::array<OptionData, kNbOptions + 1> kAllOptionsData = {
|
||||
"suffix")},
|
||||
OptionData{"GB/ROMDir", "", _("Directory to look for ROM files")},
|
||||
OptionData{"GB/GBCROMDir", "", _("Directory to look for Game Boy Color ROM files")},
|
||||
OptionData{"GB/GBCLighten", "", _("Color lightness factor")},
|
||||
|
||||
/// GBA
|
||||
OptionData{"GBA/BiosFile", "", _("BIOS file to use, if enabled")},
|
||||
@@ -472,6 +494,7 @@ const std::array<OptionData, kNbOptions + 1> kAllOptionsData = {
|
||||
OptionData{"GBA/LinkType", "LinkType", _("Link cable type")},
|
||||
#endif
|
||||
OptionData{"GBA/ROMDir", "", _("Directory to look for ROM files")},
|
||||
OptionData{"GBA/GBADarken", "", _("Color darkness factor")},
|
||||
|
||||
/// General
|
||||
OptionData{"General/AutoLoadLastState", "", _("Automatically load last saved state")},
|
||||
@@ -652,6 +675,12 @@ wxString RenderMethodToString(const RenderMethod& value) {
|
||||
return kRenderMethodStrings[size_value];
|
||||
}
|
||||
|
||||
wxString ColorCorrectionProfileToString(const ColorCorrectionProfile& value) {
|
||||
const size_t size_value = static_cast<size_t>(value);
|
||||
VBAM_CHECK(size_value < kNbColorCorrectionProfiles);
|
||||
return kColorCorrectionProfileStrings[size_value];
|
||||
}
|
||||
|
||||
wxString AudioApiToString(const AudioApi& value) {
|
||||
const size_t size_value = static_cast<size_t>(value);
|
||||
VBAM_CHECK(size_value < kNbAudioApis);
|
||||
@@ -725,6 +754,27 @@ RenderMethod StringToRenderMethod(const wxString& config_name,
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
ColorCorrectionProfile StringToColorCorrectionProfile(const wxString& config_name,
|
||||
const wxString& input) {
|
||||
static const std::map<wxString, ColorCorrectionProfile> kStringToColorCorrectionProfile([] {
|
||||
std::map<wxString, ColorCorrectionProfile> string_to_color_correction_profile;
|
||||
for (size_t i = 0; i < kNbColorCorrectionProfiles; i++) {
|
||||
string_to_color_correction_profile.emplace(kColorCorrectionProfileStrings[i], static_cast<ColorCorrectionProfile>(i));
|
||||
}
|
||||
VBAM_CHECK(string_to_color_correction_profile.size() == kNbColorCorrectionProfiles);
|
||||
return string_to_color_correction_profile;
|
||||
}());
|
||||
|
||||
const auto iter = kStringToColorCorrectionProfile.find(input);
|
||||
if (iter == kStringToColorCorrectionProfile.end()) {
|
||||
wxLogWarning(_("Invalid value %s for option %s; valid values are %s"),
|
||||
input, config_name,
|
||||
AllEnumValuesForType(Option::Type::kColorCorrectionProfile));
|
||||
return ColorCorrectionProfile::kSRGB;
|
||||
}
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
AudioApi StringToAudioApi(const wxString& config_name, const wxString& input) {
|
||||
static const std::map<wxString, AudioApi> kStringToAudioApi([] {
|
||||
std::map<wxString, AudioApi> string_to_audio_api;
|
||||
@@ -778,6 +828,10 @@ wxString AllEnumValuesForType(Option::Type type) {
|
||||
static const wxString kAllRenderValues(AllEnumValuesForArray(kRenderMethodStrings));
|
||||
return kAllRenderValues;
|
||||
}
|
||||
case Option::Type::kColorCorrectionProfile: {
|
||||
static const wxString kAllColorCorrectionValues(AllEnumValuesForArray(kColorCorrectionProfileStrings));
|
||||
return kAllColorCorrectionValues;
|
||||
}
|
||||
case Option::Type::kAudioApi: {
|
||||
static const wxString kAllAudioApiValues(AllEnumValuesForArray(kAudioApiStrings));
|
||||
return kAllAudioApiValues;
|
||||
@@ -811,6 +865,8 @@ size_t MaxForType(Option::Type type) {
|
||||
return kNbInterframes;
|
||||
case Option::Type::kRenderMethod:
|
||||
return kNbRenderMethods;
|
||||
case Option::Type::kColorCorrectionProfile:
|
||||
return kNbColorCorrectionProfiles;
|
||||
case Option::Type::kAudioApi:
|
||||
return kNbAudioApis;
|
||||
case Option::Type::kAudioRate:
|
||||
|
@@ -27,11 +27,13 @@ nonstd::optional<OptionID> StringToOptionId(const wxString& input);
|
||||
wxString FilterToString(const Filter& value);
|
||||
wxString InterframeToString(const Interframe& value);
|
||||
wxString RenderMethodToString(const RenderMethod& value);
|
||||
wxString ColorCorrectionProfileToString(const ColorCorrectionProfile& value);
|
||||
wxString AudioApiToString(const AudioApi& value);
|
||||
wxString AudioRateToString(const AudioRate& value);
|
||||
Filter StringToFilter(const wxString& config_name, const wxString& input);
|
||||
Interframe StringToInterframe(const wxString& config_name, const wxString& input);
|
||||
RenderMethod StringToRenderMethod(const wxString& config_name, const wxString& input);
|
||||
ColorCorrectionProfile StringToColorCorrectionProfile(const wxString& config_name, const wxString& input);
|
||||
AudioApi StringToAudioApi(const wxString& config_name, const wxString& input);
|
||||
AudioRate StringToSoundQuality(const wxString& config_name, const wxString& input);
|
||||
|
||||
|
@@ -8,6 +8,7 @@ namespace config {
|
||||
enum class OptionID {
|
||||
/// Display
|
||||
kDispBilinear = 0,
|
||||
kDispSDLPixelArt,
|
||||
kDispFilter,
|
||||
kDispFilterPlugin,
|
||||
kDispIFB,
|
||||
@@ -18,6 +19,7 @@ enum class OptionID {
|
||||
kDispScale,
|
||||
kDispStretch,
|
||||
kSDLRenderer,
|
||||
kDispColorCorrectionProfile,
|
||||
|
||||
/// GB
|
||||
kGBBiosFile,
|
||||
@@ -32,6 +34,7 @@ enum class OptionID {
|
||||
kGBPrintScreenCap,
|
||||
kGBROMDir,
|
||||
kGBGBCROMDir,
|
||||
kGBLighten,
|
||||
|
||||
/// GBA
|
||||
kGBABiosFile,
|
||||
@@ -47,6 +50,7 @@ enum class OptionID {
|
||||
kGBALinkType,
|
||||
#endif
|
||||
kGBAROMDir,
|
||||
kGBADarken,
|
||||
|
||||
/// General
|
||||
kGenAutoLoadLastState,
|
||||
|
@@ -12,6 +12,7 @@ namespace config {
|
||||
static constexpr std::array<Option::Type, kNbOptions> kOptionsTypes = {
|
||||
/// Display
|
||||
/*kDispBilinear*/ Option::Type::kBool,
|
||||
/*kDispSDLPixelArt*/ Option::Type::kBool,
|
||||
/*kDispFilter*/ Option::Type::kFilter,
|
||||
/*kDispFilterPlugin*/ Option::Type::kString,
|
||||
/*kDispIFB*/ Option::Type::kInterframe,
|
||||
@@ -22,6 +23,7 @@ static constexpr std::array<Option::Type, kNbOptions> kOptionsTypes = {
|
||||
/*kDispScale*/ Option::Type::kDouble,
|
||||
/*kDispStretch*/ Option::Type::kBool,
|
||||
/*kSDLRenderer*/ Option::Type::kString,
|
||||
/*kDispColorCorrectionProfile*/ Option::Type::kColorCorrectionProfile,
|
||||
|
||||
/// GB
|
||||
/*kGBBiosFile*/ Option::Type::kString,
|
||||
@@ -36,6 +38,7 @@ static constexpr std::array<Option::Type, kNbOptions> kOptionsTypes = {
|
||||
/*kGBPrintScreenCap*/ Option::Type::kBool,
|
||||
/*kGBROMDir*/ Option::Type::kString,
|
||||
/*kGBGBCROMDir*/ Option::Type::kString,
|
||||
/*kGBLighten*/ Option::Type::kUnsigned,
|
||||
|
||||
/// GBA
|
||||
/*kGBABiosFile*/ Option::Type::kString,
|
||||
@@ -51,6 +54,7 @@ static constexpr std::array<Option::Type, kNbOptions> kOptionsTypes = {
|
||||
/*kGBALinkType*/ Option::Type::kInt,
|
||||
#endif
|
||||
/*kGBAROMDir*/ Option::Type::kString,
|
||||
/*kGBADarken*/ Option::Type::kUnsigned,
|
||||
|
||||
/// General
|
||||
/*kGenAutoLoadLastState*/ Option::Type::kBool,
|
||||
@@ -346,6 +350,25 @@ private:
|
||||
Option* option_;
|
||||
};
|
||||
|
||||
template <OptionID ID>
|
||||
class OptionProxy<
|
||||
ID,
|
||||
typename std::enable_if<kOptionsTypes[static_cast<size_t>(ID)] ==
|
||||
Option::Type::kColorCorrectionProfile>::type> {
|
||||
public:
|
||||
OptionProxy() : option_(Option::ByID(ID)) {}
|
||||
~OptionProxy() = default;
|
||||
|
||||
ColorCorrectionProfile Get() const { return option_->GetColorCorrectionProfile(); }
|
||||
bool Set(ColorCorrectionProfile value) { return option_->SetColorCorrectionProfile(value); }
|
||||
|
||||
bool operator=(ColorCorrectionProfile value) { return Set(value); }
|
||||
operator ColorCorrectionProfile() const { return Get(); }
|
||||
|
||||
private:
|
||||
Option* option_;
|
||||
};
|
||||
|
||||
template <OptionID ID>
|
||||
class OptionProxy<
|
||||
ID,
|
||||
|
@@ -20,7 +20,7 @@ namespace config {
|
||||
Option* Option::ByName(const wxString& config_name) {
|
||||
nonstd::optional<OptionID> option_id = internal::StringToOptionId(config_name);
|
||||
if (!option_id) {
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
return ByID(option_id.value());
|
||||
}
|
||||
@@ -167,6 +167,19 @@ Option::Option(OptionID id, RenderMethod* option)
|
||||
VBAM_CHECK(is_render_method());
|
||||
}
|
||||
|
||||
Option::Option(OptionID id, ColorCorrectionProfile* option)
|
||||
: id_(id),
|
||||
config_name_(internal::kAllOptionsData[static_cast<size_t>(id)].config_name),
|
||||
command_(internal::kAllOptionsData[static_cast<size_t>(id)].command),
|
||||
ux_helper_(wxGetTranslation(internal::kAllOptionsData[static_cast<size_t>(id)].ux_helper)),
|
||||
type_(kOptionsTypes[static_cast<size_t>(id)]),
|
||||
value_(option),
|
||||
min_(),
|
||||
max_(nonstd::in_place_type<size_t>, internal::MaxForType(type_)) {
|
||||
VBAM_CHECK(id != OptionID::Last);
|
||||
VBAM_CHECK(is_color_correction_profile());
|
||||
}
|
||||
|
||||
Option::Option(OptionID id, AudioApi* option)
|
||||
: id_(id),
|
||||
config_name_(internal::kAllOptionsData[static_cast<size_t>(id)].config_name),
|
||||
@@ -246,6 +259,11 @@ RenderMethod Option::GetRenderMethod() const {
|
||||
return *(nonstd::get<RenderMethod*>(value_));
|
||||
}
|
||||
|
||||
ColorCorrectionProfile Option::GetColorCorrectionProfile() const {
|
||||
VBAM_CHECK(is_color_correction_profile());
|
||||
return *(nonstd::get<ColorCorrectionProfile*>(value_));
|
||||
}
|
||||
|
||||
AudioApi Option::GetAudioApi() const {
|
||||
VBAM_CHECK(is_audio_api());
|
||||
return *(nonstd::get<AudioApi*>(value_));
|
||||
@@ -264,6 +282,8 @@ wxString Option::GetEnumString() const {
|
||||
return internal::InterframeToString(GetInterframe());
|
||||
case Option::Type::kRenderMethod:
|
||||
return internal::RenderMethodToString(GetRenderMethod());
|
||||
case Option::Type::kColorCorrectionProfile:
|
||||
return internal::ColorCorrectionProfileToString(GetColorCorrectionProfile());
|
||||
case Option::Type::kAudioApi:
|
||||
return internal::AudioApiToString(GetAudioApi());
|
||||
case Option::Type::kAudioRate:
|
||||
@@ -402,6 +422,17 @@ bool Option::SetRenderMethod(const RenderMethod& value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Option::SetColorCorrectionProfile(const ColorCorrectionProfile& value) {
|
||||
VBAM_CHECK(is_color_correction_profile());
|
||||
VBAM_CHECK(value < ColorCorrectionProfile::kLast);
|
||||
const ColorCorrectionProfile old_value = GetColorCorrectionProfile();
|
||||
*nonstd::get<ColorCorrectionProfile*>(value_) = value;
|
||||
if (old_value != value) {
|
||||
CallObservers();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Option::SetAudioApi(const AudioApi& value) {
|
||||
VBAM_CHECK(is_audio_api());
|
||||
VBAM_CHECK(value < AudioApi::kLast);
|
||||
@@ -432,6 +463,8 @@ bool Option::SetEnumString(const wxString& value) {
|
||||
return SetInterframe(internal::StringToInterframe(config_name_, value));
|
||||
case Option::Type::kRenderMethod:
|
||||
return SetRenderMethod(internal::StringToRenderMethod(config_name_, value));
|
||||
case Option::Type::kColorCorrectionProfile:
|
||||
return SetColorCorrectionProfile(internal::StringToColorCorrectionProfile(config_name_, value));
|
||||
case Option::Type::kAudioApi:
|
||||
return SetAudioApi(internal::StringToAudioApi(config_name_, value));
|
||||
case Option::Type::kAudioRate:
|
||||
@@ -571,6 +604,7 @@ wxString Option::ToHelperString() const {
|
||||
case Option::Type::kFilter:
|
||||
case Option::Type::kInterframe:
|
||||
case Option::Type::kRenderMethod:
|
||||
case Option::Type::kColorCorrectionProfile:
|
||||
case Option::Type::kAudioApi:
|
||||
case Option::Type::kAudioRate:
|
||||
helper_string.Append(" (");
|
||||
|
@@ -81,6 +81,17 @@ enum class RenderMethod {
|
||||
};
|
||||
static constexpr size_t kNbRenderMethods = static_cast<size_t>(RenderMethod::kLast);
|
||||
|
||||
// Values for kDispColorCorrectionProfile.
|
||||
enum class ColorCorrectionProfile {
|
||||
kSRGB = 0,
|
||||
kDCI,
|
||||
kRec2020,
|
||||
|
||||
// Do not add anything under here.
|
||||
kLast,
|
||||
};
|
||||
static constexpr size_t kNbColorCorrectionProfiles = static_cast<size_t>(ColorCorrectionProfile::kLast);
|
||||
|
||||
// Values for kAudioApi.
|
||||
enum class AudioApi {
|
||||
kOpenAL,
|
||||
@@ -116,7 +127,7 @@ static constexpr size_t kNbSoundRate = static_cast<size_t>(AudioRate::kLast);
|
||||
|
||||
// This is incremented whenever we want to change a default value between
|
||||
// release versions. The option update code is in load_opts.
|
||||
static constexpr uint32_t kIniLatestVersion = 1;
|
||||
static constexpr uint32_t kIniLatestVersion = 2;
|
||||
|
||||
// Represents a single option saved in the INI file. Option does not own the
|
||||
// individual option, but keeps a pointer to where the data is actually saved.
|
||||
@@ -143,6 +154,7 @@ public:
|
||||
kFilter,
|
||||
kInterframe,
|
||||
kRenderMethod,
|
||||
kColorCorrectionProfile,
|
||||
kAudioApi,
|
||||
kAudioRate,
|
||||
kGbPalette,
|
||||
@@ -200,6 +212,7 @@ public:
|
||||
bool is_filter() const { return type() == Type::kFilter; }
|
||||
bool is_interframe() const { return type() == Type::kInterframe; }
|
||||
bool is_render_method() const { return type() == Type::kRenderMethod; }
|
||||
bool is_color_correction_profile() const { return type() == Type::kColorCorrectionProfile; }
|
||||
bool is_audio_api() const { return type() == Type::kAudioApi; }
|
||||
bool is_audio_rate() const { return type() == Type::kAudioRate; }
|
||||
bool is_gb_palette() const { return type() == Type::kGbPalette; }
|
||||
@@ -214,6 +227,7 @@ public:
|
||||
Filter GetFilter() const;
|
||||
Interframe GetInterframe() const;
|
||||
RenderMethod GetRenderMethod() const;
|
||||
ColorCorrectionProfile GetColorCorrectionProfile() const;
|
||||
AudioApi GetAudioApi() const;
|
||||
AudioRate GetAudioRate() const;
|
||||
wxString GetEnumString() const;
|
||||
@@ -231,6 +245,7 @@ public:
|
||||
bool SetFilter(const Filter& value);
|
||||
bool SetInterframe(const Interframe& value);
|
||||
bool SetRenderMethod(const RenderMethod& value);
|
||||
bool SetColorCorrectionProfile(const ColorCorrectionProfile& value);
|
||||
bool SetAudioApi(const AudioApi& value);
|
||||
bool SetAudioRate(const AudioRate& value);
|
||||
bool SetEnumString(const wxString& value);
|
||||
@@ -267,6 +282,7 @@ private:
|
||||
Option(OptionID id, Filter* option);
|
||||
Option(OptionID id, Interframe* option);
|
||||
Option(OptionID id, RenderMethod* option);
|
||||
Option(OptionID id, ColorCorrectionProfile* option);
|
||||
Option(OptionID id, AudioApi* option);
|
||||
Option(OptionID id, AudioRate* option);
|
||||
Option(OptionID id, int* option);
|
||||
@@ -299,6 +315,7 @@ private:
|
||||
Filter*,
|
||||
Interframe*,
|
||||
RenderMethod*,
|
||||
ColorCorrectionProfile*,
|
||||
AudioApi*,
|
||||
AudioRate*,
|
||||
uint16_t*>
|
||||
|
@@ -223,6 +223,41 @@ private:
|
||||
const config::RenderMethod render_method_;
|
||||
};
|
||||
|
||||
// Validator for a wxRadioButton with a ColorCorrectionProfile value.
|
||||
class ColorCorrectionProfileValidator : public widgets::OptionValidator {
|
||||
public:
|
||||
explicit ColorCorrectionProfileValidator(config::ColorCorrectionProfile color_correction_profile)
|
||||
: OptionValidator(config::OptionID::kDispColorCorrectionProfile),
|
||||
color_correction_profile_(color_correction_profile) {
|
||||
VBAM_CHECK(color_correction_profile != config::ColorCorrectionProfile::kLast);
|
||||
}
|
||||
~ColorCorrectionProfileValidator() override = default;
|
||||
|
||||
private:
|
||||
// OptionValidator implementation.
|
||||
wxObject* Clone() const override {
|
||||
return new ColorCorrectionProfileValidator(color_correction_profile_);
|
||||
}
|
||||
|
||||
bool IsWindowValueValid() override { return true; }
|
||||
|
||||
bool WriteToWindow() override {
|
||||
wxDynamicCast(GetWindow(), wxRadioButton)
|
||||
->SetValue(option()->GetColorCorrectionProfile() == color_correction_profile_);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteToOption() override {
|
||||
if (wxDynamicCast(GetWindow(), wxRadioButton)->GetValue()) {
|
||||
return option()->SetColorCorrectionProfile(color_correction_profile_);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const config::ColorCorrectionProfile color_correction_profile_;
|
||||
};
|
||||
|
||||
class PluginSelectorValidator : public widgets::OptionValidator {
|
||||
public:
|
||||
PluginSelectorValidator()
|
||||
@@ -351,6 +386,46 @@ DisplayConfig::DisplayConfig(wxWindow* parent)
|
||||
sdlrenderer_selector_ = GetValidatedChild<wxChoice>("SDLRenderer");
|
||||
sdlrenderer_selector_->SetValidator(SDLDevicesValidator());
|
||||
|
||||
#if !defined(ENABLE_SDL3) || !defined(HAVE_SDL3_PIXELART)
|
||||
GetValidatedChild<wxCheckBox>("SDLPixelArt")->Hide();
|
||||
#else
|
||||
GetValidatedChild<wxCheckBox>("SDLPixelArt")
|
||||
->SetValidator(
|
||||
widgets::OptionBoolValidator(config::OptionID::kDispSDLPixelArt));
|
||||
#endif
|
||||
|
||||
wxWindow* color_profile_srgb = GetValidatedChild("ColorProfileSRGB");
|
||||
color_profile_srgb->SetValidator(
|
||||
ColorCorrectionProfileValidator(config::ColorCorrectionProfile::kSRGB));
|
||||
|
||||
wxWindow* color_profile_dci = GetValidatedChild("ColorProfileDCI");
|
||||
color_profile_dci->SetValidator(
|
||||
ColorCorrectionProfileValidator(config::ColorCorrectionProfile::kDCI));
|
||||
|
||||
wxWindow* color_profile_rec2020 = GetValidatedChild("ColorProfileRec2020");
|
||||
color_profile_rec2020->SetValidator(
|
||||
ColorCorrectionProfileValidator(config::ColorCorrectionProfile::kRec2020));
|
||||
|
||||
switch (OPTION(kDispColorCorrectionProfile)) {
|
||||
case config::ColorCorrectionProfile::kSRGB:
|
||||
wxDynamicCast(color_profile_srgb, wxRadioButton)->SetValue(true);
|
||||
break;
|
||||
case config::ColorCorrectionProfile::kDCI:
|
||||
wxDynamicCast(color_profile_dci, wxRadioButton)->SetValue(true);
|
||||
break;
|
||||
case config::ColorCorrectionProfile::kRec2020:
|
||||
wxDynamicCast(color_profile_rec2020, wxRadioButton)->SetValue(true);
|
||||
break;
|
||||
default:
|
||||
wxLogError(_("Invalid color correction profile"));
|
||||
}
|
||||
|
||||
wxSlider* gba_darken_slider = GetValidatedChild<wxSlider>("GBADarken");
|
||||
gba_darken_slider->SetValidator(widgets::OptionUnsignedValidator(config::OptionID::kGBADarken));
|
||||
|
||||
wxSlider* gbc_lighten_slider = GetValidatedChild<wxSlider>("GBCLighten");
|
||||
gbc_lighten_slider->SetValidator(widgets::OptionUnsignedValidator(config::OptionID::kGBLighten));
|
||||
|
||||
filter_selector_ = GetValidatedChild<wxChoice>("Filter");
|
||||
filter_selector_->SetValidator(FilterValidator());
|
||||
filter_selector_->Bind(wxEVT_CHOICE, &DisplayConfig::UpdatePlugin, this,
|
||||
|
@@ -97,8 +97,8 @@ JoypadConfig::JoypadConfig(wxWindow* parent, const config::BindingsProvider bind
|
||||
// Set up tab order so input is easy to configure. Note that there are
|
||||
// two tabs for each panel, so we must check for the parent before
|
||||
// setting up the tab order.
|
||||
wxWindow* prev = nullptr;
|
||||
wxWindow* prev_parent = nullptr;
|
||||
wxWindow* prev = NULL;
|
||||
wxWindow* prev_parent = NULL;
|
||||
for (const config::GameKey& game_key : config::kAllGameKeys) {
|
||||
const wxString game_key_name = config::GameKeyToString(game_key);
|
||||
widgets::UserInputCtrl* game_key_control =
|
||||
|
@@ -40,7 +40,7 @@ protected:
|
||||
void AdjustViewport();
|
||||
void RefreshGL();
|
||||
#ifndef wxGL_IMPLICIT_CONTEXT
|
||||
wxGLContext* ctx = nullptr;
|
||||
wxGLContext* ctx = NULL;
|
||||
#endif
|
||||
bool SetContext();
|
||||
void DrawingPanelInit();
|
||||
|
@@ -1830,20 +1830,20 @@ bool MainFrame::BindControls()
|
||||
// remove this item from the menu completely
|
||||
wxMenuItem* gdbmi = XRCITEM("GDBMenu");
|
||||
gdbmi->GetMenu()->Remove(gdbmi);
|
||||
gdbmi = nullptr;
|
||||
gdbmi = NULL;
|
||||
#endif // !defined(VBAM_ENABLE_DEBUGGER)
|
||||
#ifdef NO_LINK
|
||||
// remove this item from the menu completely
|
||||
wxMenuItem* linkmi = XRCITEM("LinkMenu");
|
||||
linkmi->GetMenu()->Remove(linkmi);
|
||||
linkmi = nullptr;
|
||||
linkmi = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef __WXMAC__
|
||||
// Remove hide menubar in the UI Config submenu on macOS, because it is meaningless there.
|
||||
wxMenuItem* hide_menu_bar = XRCITEM("HideMenuBar");
|
||||
hide_menu_bar->GetMenu()->Remove(hide_menu_bar);
|
||||
hide_menu_bar = nullptr;
|
||||
hide_menu_bar = NULL;
|
||||
#endif
|
||||
|
||||
// if a recent menu is present, save its location
|
||||
@@ -1925,7 +1925,6 @@ bool MainFrame::BindControls()
|
||||
MenuOptionIntRadioValue("Language1", OPTION(kLocale), wxLANGUAGE_BULGARIAN);
|
||||
MenuOptionIntRadioValue("Language2", OPTION(kLocale), wxLANGUAGE_BRETON);
|
||||
MenuOptionIntRadioValue("Language3", OPTION(kLocale), wxLANGUAGE_CZECH);
|
||||
MenuOptionIntRadioValue("Language4", OPTION(kLocale), wxLANGUAGE_GERMAN);
|
||||
MenuOptionIntRadioValue("Language5", OPTION(kLocale), wxLANGUAGE_GREEK);
|
||||
MenuOptionIntRadioValue("Language6", OPTION(kLocale), wxLANGUAGE_ENGLISH_US);
|
||||
MenuOptionIntRadioValue("Language7", OPTION(kLocale), wxLANGUAGE_SPANISH_LATIN_AMERICA);
|
||||
|
@@ -268,7 +268,7 @@ void MetalDrawingPanel::DrawArea()
|
||||
DrawingPanelInit();
|
||||
|
||||
if (systemColorDepth == 8) {
|
||||
srcPitch = std::ceil(width * scale) + 2;
|
||||
srcPitch = std::ceil(width * scale) + 4;
|
||||
} else if (systemColorDepth == 16) {
|
||||
srcPitch = std::ceil(width * scale * 2) + 4;
|
||||
} else if (systemColorDepth == 24) {
|
||||
@@ -302,7 +302,7 @@ void MetalDrawingPanel::DrawArea()
|
||||
src_pos++;
|
||||
}
|
||||
pos++;
|
||||
src_pos += 2;
|
||||
src_pos += 4;
|
||||
}
|
||||
|
||||
_texture = loadTextureUsingData(dst);
|
||||
|
@@ -54,6 +54,7 @@ void SaveOption(config::Option* option) {
|
||||
case config::Option::Type::kFilter:
|
||||
case config::Option::Type::kInterframe:
|
||||
case config::Option::Type::kRenderMethod:
|
||||
case config::Option::Type::kColorCorrectionProfile:
|
||||
case config::Option::Type::kAudioApi:
|
||||
case config::Option::Type::kAudioRate:
|
||||
cfg->Write(option->config_name(), option->GetEnumString());
|
||||
@@ -290,6 +291,7 @@ void load_opts(bool first_time_launch) {
|
||||
case config::Option::Type::kFilter:
|
||||
case config::Option::Type::kInterframe:
|
||||
case config::Option::Type::kRenderMethod:
|
||||
case config::Option::Type::kColorCorrectionProfile:
|
||||
case config::Option::Type::kAudioApi:
|
||||
case config::Option::Type::kAudioRate: {
|
||||
wxString temp;
|
||||
@@ -380,8 +382,11 @@ void load_opts(bool first_time_launch) {
|
||||
OPTION(kGBALinkTimeout) = 500;
|
||||
}
|
||||
#endif
|
||||
// Previous default was true.
|
||||
OPTION(kGBALCDFilter) = false;
|
||||
}
|
||||
case 1: { // up to 2.2.2 included.
|
||||
// Previous defaults were false.
|
||||
OPTION(kGBALCDFilter) = true;
|
||||
OPTION(kGBLCDFilter) = true;
|
||||
}
|
||||
}
|
||||
ini_version++;
|
||||
@@ -475,6 +480,7 @@ void opt_set(const wxString& name, const wxString& val) {
|
||||
case config::Option::Type::kFilter:
|
||||
case config::Option::Type::kInterframe:
|
||||
case config::Option::Type::kRenderMethod:
|
||||
case config::Option::Type::kColorCorrectionProfile:
|
||||
case config::Option::Type::kAudioApi:
|
||||
case config::Option::Type::kAudioRate:
|
||||
opt->SetEnumString(val);
|
||||
|
@@ -39,7 +39,7 @@ extern struct opts_t {
|
||||
int sound_en = 0x30f; // soundSetEnable()
|
||||
|
||||
/// Recent
|
||||
wxFileHistory* recent = nullptr;
|
||||
wxFileHistory* recent = NULL;
|
||||
|
||||
/// UI Config
|
||||
bool hide_menu_bar = true;
|
||||
|
121
src/wx/panel.cpp
121
src/wx/panel.cpp
@@ -35,6 +35,7 @@
|
||||
#include "components/draw_text/draw_text.h"
|
||||
#include "components/filters/filters.h"
|
||||
#include "components/filters_agb/filters_agb.h"
|
||||
#include "components/filters_cgb/filters_cgb.h"
|
||||
#include "components/filters_interframe/interframe.h"
|
||||
#include "core/base/check.h"
|
||||
#include "core/base/file_util.h"
|
||||
@@ -175,7 +176,7 @@ GameArea::GameArea()
|
||||
gb_declick_observer_(
|
||||
config::OptionID::kSoundGBDeclicking,
|
||||
[&](config::Option* option) { gbSoundSetDeclicking(option->GetBool()); }),
|
||||
lcd_filters_observer_({config::OptionID::kGBLCDFilter, config::OptionID::kGBALCDFilter},
|
||||
lcd_filters_observer_({config::OptionID::kGBLCDFilter, config::OptionID::kGBADarken, config::OptionID::kGBLighten, config::OptionID::kDispColorCorrectionProfile, config::OptionID::kGBALCDFilter},
|
||||
std::bind(&GameArea::UpdateLcdFilter, this)),
|
||||
audio_rate_observer_(config::OptionID::kSoundAudioRate,
|
||||
std::bind(&GameArea::OnAudioRateChanged, this)),
|
||||
@@ -932,7 +933,7 @@ void GameArea::AdjustSize(bool force)
|
||||
void GameArea::ResetPanel() {
|
||||
if (panel) {
|
||||
panel->Destroy();
|
||||
panel = nullptr;
|
||||
panel = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1197,20 +1198,14 @@ void GameArea::OnIdle(wxIdleEvent& event)
|
||||
if (!panel) {
|
||||
switch (OPTION(kDispRenderMethod)) {
|
||||
case config::RenderMethod::kSimple:
|
||||
no_border = false;
|
||||
|
||||
panel = new BasicDrawingPanel(this, basic_width, basic_height);
|
||||
break;
|
||||
case config::RenderMethod::kSDL:
|
||||
no_border = false;
|
||||
|
||||
panel = new SDLDrawingPanel(this, basic_width, basic_height);
|
||||
break;
|
||||
#ifdef __WXMAC__
|
||||
#ifndef NO_METAL
|
||||
case config::RenderMethod::kMetal:
|
||||
no_border = false;
|
||||
|
||||
if (is_macosx_1012_or_newer()) {
|
||||
panel =
|
||||
new MetalDrawingPanel(this, basic_width, basic_height);
|
||||
@@ -1221,27 +1216,17 @@ void GameArea::OnIdle(wxIdleEvent& event)
|
||||
break;
|
||||
#endif
|
||||
case config::RenderMethod::kQuartz2d:
|
||||
no_border = false;
|
||||
|
||||
panel =
|
||||
new Quartz2DDrawingPanel(this, basic_width, basic_height);
|
||||
break;
|
||||
#endif
|
||||
#ifndef NO_OGL
|
||||
case config::RenderMethod::kOpenGL:
|
||||
if (out_8) {
|
||||
no_border = true;
|
||||
} else {
|
||||
no_border = false;
|
||||
}
|
||||
|
||||
panel = new GLDrawingPanel(this, basic_width, basic_height);
|
||||
break;
|
||||
#endif
|
||||
#if defined(__WXMSW__) && !defined(NO_D3D)
|
||||
case config::RenderMethod::kDirect3d:
|
||||
no_border = false;
|
||||
|
||||
panel = new DXDrawingPanel(this, basic_width, basic_height);
|
||||
break;
|
||||
#endif
|
||||
@@ -1480,7 +1465,7 @@ DrawingPanelBase::DrawingPanelBase(int _width, int _height)
|
||||
pixbuf1(0),
|
||||
pixbuf2(0),
|
||||
nthreads(0),
|
||||
rpi_(nullptr) {
|
||||
rpi_(NULL) {
|
||||
memset(delta, 0xff, sizeof(delta));
|
||||
|
||||
if (OPTION(kDispFilter) == config::Filter::kPlugin) {
|
||||
@@ -1640,12 +1625,12 @@ public:
|
||||
const int procy = height_ * threadno_ / nthreads_;
|
||||
height_ = height_ * (threadno_ + 1) / nthreads_ - procy;
|
||||
const int inbpp = systemColorDepth >> 3;
|
||||
const int inrb = out_8 ? 2 : out_16 ? 2
|
||||
const int inrb = out_8 ? 4 : out_16 ? 2
|
||||
: out_24 ? 0 : 1;
|
||||
const int instride = (width_ + inrb) * inbpp;
|
||||
const int instride32 = width_ * 4;
|
||||
const int outbpp = systemColorDepth >> 3;
|
||||
const int outrb = out_8 ? 2 : out_24 ? 0 : 4;
|
||||
const int outrb = out_8 ? 4 : out_24 ? 0 : 4;
|
||||
const int outstride = std::ceil(width_ * outbpp * scale_) + outrb;
|
||||
const int outstride32 = std::ceil(width_ * 4 * scale_);
|
||||
uint8_t *dest = NULL;
|
||||
@@ -1708,7 +1693,7 @@ public:
|
||||
pos++;
|
||||
src_pos++;
|
||||
}
|
||||
src_pos += 2;
|
||||
src_pos += 4;
|
||||
}
|
||||
} else if (out_16) {
|
||||
uint16_t *src16_ = (uint16_t *)src_;
|
||||
@@ -1761,7 +1746,7 @@ public:
|
||||
pos++;
|
||||
dst_pos += 4;
|
||||
}
|
||||
pos += 2;
|
||||
pos += 4;
|
||||
}
|
||||
} else if (out_16) {
|
||||
uint16_t *dest16_ = (uint16_t *)dest;
|
||||
@@ -2003,7 +1988,7 @@ void DrawingPanelBase::DrawArea(uint8_t** data)
|
||||
// if filtering, this is filter output, retained for redraws
|
||||
// if not filtering, we still retain current image for redraws
|
||||
int outbpp = systemColorDepth >> 3;
|
||||
int outrb = out_8 ? 2 : out_24 ? 0 : 4;
|
||||
int outrb = out_8 ? 4 : out_24 ? 0 : 4;
|
||||
int outstride = std::ceil(width * outbpp * scale) + outrb;
|
||||
|
||||
if (!pixbuf2) {
|
||||
@@ -2589,6 +2574,17 @@ SDL_TEXTUREACCESS_STREAMING, (width * scale), (height * scale));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Set bilinear or nearest on the texture.
|
||||
#ifdef ENABLE_SDL3
|
||||
#ifdef HAVE_SDL3_PIXELART
|
||||
SDL_SetTextureScaleMode(texture, OPTION(kDispSDLPixelArt) ? SDL_SCALEMODE_PIXELART : OPTION(kDispBilinear) ? SDL_SCALEMODE_LINEAR : SDL_SCALEMODE_NEAREST);
|
||||
#else
|
||||
SDL_SetTextureScaleMode(texture, OPTION(kDispBilinear) ? SDL_SCALEMODE_LINEAR : SDL_SCALEMODE_NEAREST);
|
||||
#endif
|
||||
#else
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, OPTION(kDispBilinear) ? "1" : "0");
|
||||
#endif
|
||||
|
||||
did_init = true;
|
||||
}
|
||||
@@ -2618,7 +2614,7 @@ void SDLDrawingPanel::DrawArea()
|
||||
DrawingPanelInit();
|
||||
|
||||
if (out_8) {
|
||||
srcPitch = std::ceil(width * scale) + 2;
|
||||
srcPitch = std::ceil(width * scale) + 4;
|
||||
} else if (out_16) {
|
||||
srcPitch = std::ceil(width * scale * 2) + 4;
|
||||
} else if (out_24) {
|
||||
@@ -2673,7 +2669,7 @@ void SDLDrawingPanel::DrawArea(uint8_t** data)
|
||||
// if filtering, this is filter output, retained for redraws
|
||||
// if not filtering, we still retain current image for redraws
|
||||
int outbpp = systemColorDepth >> 3;
|
||||
int outrb = out_8 ? 2 : out_24 ? 0 : 4;
|
||||
int outrb = out_8 ? 4 : out_24 ? 0 : 4;
|
||||
int outstride = std::ceil(width * outbpp * scale) + outrb;
|
||||
|
||||
// FIXME: filters race condition?
|
||||
@@ -2847,7 +2843,7 @@ void BasicDrawingPanel::DrawArea(wxWindowDC& dc)
|
||||
} else if (out_8) {
|
||||
// scaled by filters, top/right borders, transform to 24-bit
|
||||
im = new wxImage(std::ceil(width * scale), std::ceil(height * scale), false);
|
||||
uint8_t* src = (uint8_t*)todraw + (int)std::ceil((width + 2) * scale); // skip top border
|
||||
uint8_t* src = (uint8_t*)todraw + (int)std::ceil((width * scale) + 4); // skip top border
|
||||
uint8_t* dst = im->GetData();
|
||||
|
||||
for (int y = 0; y < std::ceil(height * scale); y++) {
|
||||
@@ -2864,7 +2860,7 @@ void BasicDrawingPanel::DrawArea(wxWindowDC& dc)
|
||||
}
|
||||
}
|
||||
|
||||
src += 2;
|
||||
src += 4;
|
||||
}
|
||||
} else if (out_16) {
|
||||
// scaled by filters, top/right borders, transform to 24-bit
|
||||
@@ -2965,7 +2961,7 @@ bool GLDrawingPanel::SetContext()
|
||||
// Delete the old context
|
||||
if (ctx) {
|
||||
delete ctx;
|
||||
ctx = nullptr;
|
||||
ctx = NULL;
|
||||
}
|
||||
|
||||
// Create a new context
|
||||
@@ -3175,9 +3171,6 @@ void GLDrawingPanel::RefreshGL()
|
||||
|
||||
void GLDrawingPanel::DrawArea(wxWindowDC& dc)
|
||||
{
|
||||
uint8_t* src = NULL;
|
||||
uint8_t* dst = NULL;
|
||||
|
||||
(void)dc; // unused params
|
||||
SetContext();
|
||||
RefreshGL();
|
||||
@@ -3186,7 +3179,7 @@ void GLDrawingPanel::DrawArea(wxWindowDC& dc)
|
||||
DrawingPanelInit();
|
||||
|
||||
if (todraw) {
|
||||
int rowlen = std::ceil(width * scale) + (out_8 ? 0 : out_16 ? 2 : out_24 ? 0 : 1);
|
||||
int rowlen = std::ceil(width * scale) + (out_8 ? 4 : out_16 ? 2 : out_24 ? 0 : 1);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlen);
|
||||
#if wxBYTE_ORDER == wxBIG_ENDIAN
|
||||
|
||||
@@ -3195,24 +3188,8 @@ void GLDrawingPanel::DrawArea(wxWindowDC& dc)
|
||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
|
||||
|
||||
#endif
|
||||
if (out_8) {
|
||||
src = (uint8_t*)todraw + (int)std::ceil((width + 2) * ((systemColorDepth >> 3) * scale)); // skip top border
|
||||
dst = (uint8_t*)todraw;
|
||||
|
||||
for (int y = 0; y < std::ceil(height * scale); y++) {
|
||||
for (int x = 0; x < std::ceil(width * scale); x++) {
|
||||
*dst++ = *src++;
|
||||
}
|
||||
|
||||
src += 2;
|
||||
}
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, int_fmt, (int)std::ceil(width * scale), (int)std::ceil(height * scale),
|
||||
0, tex_fmt, todraw);
|
||||
} else {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, int_fmt, (int)std::ceil(width * scale), (int)std::ceil(height * scale),
|
||||
0, tex_fmt, todraw + (int)std::ceil(rowlen * ((systemColorDepth >> 3) * scale)));
|
||||
}
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, int_fmt, (int)std::ceil(width * scale), (int)std::ceil(height * scale),
|
||||
0, tex_fmt, todraw + (int)std::ceil(rowlen * ((systemColorDepth >> 3) * scale)));
|
||||
|
||||
glCallList(vlist);
|
||||
} else
|
||||
@@ -3415,7 +3392,7 @@ void GameArea::HideMenuBar()
|
||||
if (((systemGetClock() - mouse_active_time) > 3000) && !main_frame->MenusOpened()) {
|
||||
#ifdef __WXMSW__
|
||||
current_hmenu = static_cast<HMENU>(main_frame->GetMenuBar()->GetHMenu());
|
||||
::SetMenu(main_frame->GetHandle(), nullptr);
|
||||
::SetMenu(main_frame->GetHandle(), NULL);
|
||||
#else
|
||||
main_frame->GetMenuBar()->Hide();
|
||||
#endif
|
||||
@@ -3431,9 +3408,9 @@ void GameArea::ShowMenuBar()
|
||||
if (!main_frame || !menu_bar_hidden) return;
|
||||
|
||||
#ifdef __WXMSW__
|
||||
if (current_hmenu != nullptr) {
|
||||
if (current_hmenu != NULL) {
|
||||
::SetMenu(main_frame->GetHandle(), current_hmenu);
|
||||
current_hmenu = nullptr;
|
||||
current_hmenu = NULL;
|
||||
}
|
||||
#else
|
||||
main_frame->GetMenuBar()->Show();
|
||||
@@ -3455,12 +3432,38 @@ void GameArea::OnGBBorderChanged(config::Option* option) {
|
||||
}
|
||||
|
||||
void GameArea::UpdateLcdFilter() {
|
||||
if (loaded == IMAGE_GBA)
|
||||
int DCCP = 0;
|
||||
|
||||
switch (OPTION(kDispColorCorrectionProfile)) {
|
||||
case config::ColorCorrectionProfile::kSRGB:
|
||||
DCCP = 0;
|
||||
break;
|
||||
|
||||
case config::ColorCorrectionProfile::kDCI:
|
||||
DCCP = 1;
|
||||
break;
|
||||
|
||||
case config::ColorCorrectionProfile::kRec2020:
|
||||
DCCP = 2;
|
||||
break;
|
||||
|
||||
case config::ColorCorrectionProfile::kLast:
|
||||
DCCP = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (loaded == IMAGE_GBA) {
|
||||
gbafilter_set_params(DCCP, (((float)OPTION(kGBADarken)) / 100));
|
||||
gbafilter_update_colors(OPTION(kGBALCDFilter));
|
||||
else if (loaded == IMAGE_GB)
|
||||
gbafilter_update_colors(OPTION(kGBLCDFilter));
|
||||
else
|
||||
} else if (loaded == IMAGE_GB) {
|
||||
gbcfilter_set_params(DCCP, (((float)OPTION(kGBLighten)) / 100));
|
||||
gbcfilter_update_colors(OPTION(kGBLCDFilter));
|
||||
} else {
|
||||
gbafilter_set_params(DCCP, (((float)OPTION(kGBADarken)) / 100));
|
||||
gbcfilter_set_params(DCCP, (((float)OPTION(kGBLighten)) / 100));
|
||||
gbafilter_update_colors(false);
|
||||
gbcfilter_update_colors(false);
|
||||
}
|
||||
}
|
||||
|
||||
void GameArea::SuspendScreenSaver() {
|
||||
@@ -3536,7 +3539,7 @@ void MetalDrawingPanel::DrawArea(uint8_t** data)
|
||||
// if filtering, this is filter output, retained for redraws
|
||||
// if not filtering, we still retain current image for redraws
|
||||
int outbpp = systemColorDepth >> 3;
|
||||
int outrb = out_8 ? 2 : out_24 ? 0 : 4;
|
||||
int outrb = out_8 ? 4 : out_24 ? 0 : 4;
|
||||
int outstride = std::ceil(width * outbpp * scale) + outrb;
|
||||
|
||||
// FIXME: filters race condition?
|
||||
|
@@ -545,7 +545,7 @@ void MainFrame::IOViewer()
|
||||
cb->SetValidator(wxBoolIntValidator(&systemVerbose, val, val)); \
|
||||
} while (0)
|
||||
LogDialog::LogDialog() :
|
||||
dialogs::BaseDialog(nullptr, "Logging") {
|
||||
dialogs::BaseDialog(NULL, "Logging") {
|
||||
const wxString dname = wxT("Logging");
|
||||
|
||||
SetEscapeId(wxID_OK);
|
||||
|
@@ -7,7 +7,7 @@ namespace widgets {
|
||||
namespace {
|
||||
|
||||
wxWindow* FindTopLevelWindow(wxWindow* window) {
|
||||
while (window != nullptr && !window->IsTopLevel()) {
|
||||
while (window != NULL && !window->IsTopLevel()) {
|
||||
window = window->GetParent();
|
||||
}
|
||||
VBAM_CHECK(window);
|
||||
@@ -18,7 +18,7 @@ GroupCheckBox* FindGroupCheckBox(wxWindow* window,
|
||||
const wxString& name,
|
||||
GroupCheckBox* current) {
|
||||
if (window == current) {
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (window->IsKindOf(wxCLASSINFO(GroupCheckBox))) {
|
||||
@@ -35,7 +35,7 @@ GroupCheckBox* FindGroupCheckBox(wxWindow* window,
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@@ -133,6 +133,50 @@ bool OptionIntValidator::WriteToOption() {
|
||||
return false;
|
||||
}
|
||||
|
||||
OptionUnsignedValidator::OptionUnsignedValidator(config::OptionID option_id) : OptionValidator(option_id) {
|
||||
VBAM_CHECK(option()->is_unsigned());
|
||||
}
|
||||
|
||||
wxObject* OptionUnsignedValidator::Clone() const {
|
||||
return new OptionUnsignedValidator(option()->id());
|
||||
}
|
||||
|
||||
bool OptionUnsignedValidator::IsWindowValueValid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OptionUnsignedValidator::WriteToWindow() {
|
||||
wxSpinCtrl* spin_ctrl = wxDynamicCast(GetWindow(), wxSpinCtrl);
|
||||
if (spin_ctrl) {
|
||||
spin_ctrl->SetValue(option()->GetUnsigned());
|
||||
return true;
|
||||
}
|
||||
|
||||
wxSlider* slider = wxDynamicCast(GetWindow(), wxSlider);
|
||||
if (slider) {
|
||||
slider->SetValue(option()->GetUnsigned());
|
||||
return true;
|
||||
}
|
||||
|
||||
VBAM_NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OptionUnsignedValidator::WriteToOption() {
|
||||
const wxSpinCtrl* spin_ctrl = wxDynamicCast(GetWindow(), wxSpinCtrl);
|
||||
if (spin_ctrl) {
|
||||
return option()->SetUnsigned(spin_ctrl->GetValue());
|
||||
}
|
||||
|
||||
const wxSlider* slider = wxDynamicCast(GetWindow(), wxSlider);
|
||||
if (slider) {
|
||||
return option()->SetUnsigned(slider->GetValue());
|
||||
}
|
||||
|
||||
VBAM_NOTREACHED();
|
||||
return false;
|
||||
}
|
||||
|
||||
OptionChoiceValidator::OptionChoiceValidator(config::OptionID option_id)
|
||||
: OptionValidator(option_id) {
|
||||
VBAM_CHECK(option()->is_unsigned());
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user