mirror of
https://github.com/visualboyadvance-m/visualboyadvance-m
synced 2025-10-05 23:52:49 +02:00
Compare commits
141 Commits
v2.2.1
...
043956753b
Author | SHA1 | Date | |
---|---|---|---|
|
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 | ||
|
e2a235768e | ||
|
1d54ee2135 | ||
|
013a9b87ac | ||
|
a06d3ed1b4 | ||
|
b1bad9d53d | ||
|
d2eed85c28 | ||
|
d5a37e06aa | ||
|
cea049161d | ||
|
3eadc6e78f | ||
|
4f3ed0dc8b | ||
|
d38e1d0f89 | ||
|
f870bf252d | ||
|
536ea705ab | ||
|
802162ad97 | ||
|
25895e8636 | ||
|
27e7aa6864 | ||
|
dd7461103b | ||
|
c892c269fa | ||
|
dcf87c0a71 | ||
|
6d1e7e8069 | ||
|
b8868fce37 | ||
|
d92c4e465f | ||
|
bceb138961 | ||
|
83aa80440e | ||
|
4bd54ba128 | ||
|
27acf80b80 | ||
|
ae09ab7189 | ||
|
ce8de563e3 | ||
|
47a8e7e8ed | ||
|
adbaeacf20 | ||
|
8d8ecd8dfa | ||
|
cfbfc9ecb0 | ||
|
4445a20d9c | ||
|
b83a7c8aa2 | ||
|
66aabab61f | ||
|
a5e6b57fd8 | ||
|
b9061ddafd | ||
|
3c291ef3ac | ||
|
e44c83e1d0 | ||
|
8ce4848dd6 | ||
|
34cba3bb2c | ||
|
9b78b26010 | ||
|
94f9df4baa | ||
|
c726989d67 | ||
|
3344e7cf71 | ||
|
3d69bde8cb | ||
|
09984eed2f | ||
|
69809ff556 | ||
|
80dec6a38d | ||
|
ea7b9e5049 | ||
|
18701fc0a4 | ||
|
6b596c7ad7 | ||
|
3c01643112 | ||
|
0895c7a52e | ||
|
1e52787078 | ||
|
fc0e63d554 | ||
|
9b573f4465 | ||
|
51ae605850 | ||
|
ac4b39b6d8 | ||
|
97ca69d050 | ||
|
b1bcaed3a2 | ||
|
2a1b41040d | ||
|
930d0e282c | ||
|
df23826721 | ||
|
de46284747 | ||
|
715f685447 | ||
|
eabf319c9a | ||
|
c98263603d | ||
|
9d46f8e6d1 | ||
|
dab91fc8ca | ||
|
d672d425be | ||
|
53d60b726d | ||
|
b6ce89bff8 | ||
|
8c3d0f0984 | ||
|
3d4c03d0e6 |
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
|
||||
|
||||
|
@@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [2.2.2] - 2025-07-30
|
||||
|
||||
========================
|
||||
* 27acf80b - Make language configurable (requires restart) [andyvand]
|
||||
* ae09ab71 - Embed translations for Windows [andyvand]
|
||||
* 47a8e7e8 - Update wxWidgets for Mac builder to 3.3.1 [andyvand]
|
||||
* 8ce4848d - Fix Wii U VC opcodes [andyvand]
|
||||
* dab91fc8 - Fix bigger than 32MB ROM files [andyvand]
|
||||
|
||||
## [2.2.1] - 2025-07-19
|
||||
=======================
|
||||
* 23a3d0b2 - build: fix include paths for bundled SFML [rkitover]
|
||||
|
@@ -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)
|
||||
@@ -83,7 +94,16 @@ if(APPLE)
|
||||
include(CheckLanguage)
|
||||
include(MetalShaderSupport)
|
||||
|
||||
check_language(Metal)
|
||||
execute_process(
|
||||
COMMAND xcrun -f metal
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
OUTPUT_VARIABLE CMAKE_Metal_COMPILER
|
||||
)
|
||||
|
||||
if(NOT CMAKE_Metal_COMPILER)
|
||||
check_language(Metal)
|
||||
endif()
|
||||
|
||||
if(CMAKE_Metal_COMPILER)
|
||||
enable_language(Metal)
|
||||
endif()
|
||||
|
@@ -31,6 +31,15 @@ elseif(VCPKG_TARGET_TRIPLET MATCHES "^[aA][rR][mM]-")
|
||||
set(CMAKE_SYSTEM_PROCESSOR ARM)
|
||||
endif()
|
||||
|
||||
if(APPLE AND
|
||||
(CMAKE_OSX_ARCHITECTURES MATCHES "[xX]86_64") OR
|
||||
(ENV{CFLAGS} MATCHES "[xX]86_64") OR
|
||||
(ENV{CXXFLAGS} MATCHES "[xX]86_64") OR
|
||||
(ENV{LDFLAGS} MATCHES "[xX]86_64"))
|
||||
|
||||
set(CMAKE_SYSTEM_PROCESSOR "x86_64")
|
||||
endif()
|
||||
|
||||
# Turn asm on by default on 32bit x86 and set WINARCH for windows stuff.
|
||||
if(CMAKE_SYSTEM_PROCESSOR MATCHES "[xX]86|i[3-9]86|[aA][mM][dD]64")
|
||||
if(CMAKE_C_SIZEOF_DATA_PTR EQUAL 4) # 32 bit
|
||||
@@ -46,14 +55,6 @@ if(CMAKE_SYSTEM_PROCESSOR MATCHES "[xX]86|i[3-9]86|[aA][mM][dD]64")
|
||||
set(WINARCH x64)
|
||||
set(ARCH_NAME x86_64)
|
||||
endif()
|
||||
|
||||
if(DEFINED VCPKG_TARGET_TRIPLET)
|
||||
string(REGEX MATCH "^x[86][64]" 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()
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "[aA][aA][rR][cC][hH]|[aA][rR][mM]")
|
||||
if(CMAKE_C_SIZEOF_DATA_PTR EQUAL 4) # 32 bit
|
||||
set(ARM32 ON)
|
||||
@@ -70,6 +71,14 @@ 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()
|
||||
|
||||
@@ -70,7 +74,7 @@ if(ENABLE_FFMPEG)
|
||||
list(APPEND FFMPEG_LDFLAGS "SHELL:-framework CoreText" "SHELL:-framework ApplicationServices")
|
||||
|
||||
if(UPSTREAM_RELEASE)
|
||||
list(APPEND FFMPEG_LDFLAGS -lbz2 -ltiff "SHELL:-framework DiskArbitration" -lfreetype -lfontconfig -llzma -lxml2 -lharfbuzz)
|
||||
list(APPEND FFMPEG_LDFLAGS -lbz2 -ltiff "SHELL:-framework DiskArbitration" -lfreetype -lfontconfig -llzma -lxml2 -lharfbuzz -lcrypto -lssl)
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
set(WIN32_MEDIA_FOUNDATION_LIBS dxva2 evr mf mfplat mfplay mfreadwrite mfuuid amstrmid)
|
||||
|
@@ -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" 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)
|
||||
|
||||
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()
|
||||
|
||||
@@ -93,12 +105,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 +116,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
|
||||
|
773
po/wxvbam/bg.po
773
po/wxvbam/bg.po
File diff suppressed because it is too large
Load Diff
773
po/wxvbam/br.po
773
po/wxvbam/br.po
File diff suppressed because it is too large
Load Diff
773
po/wxvbam/cs.po
773
po/wxvbam/cs.po
File diff suppressed because it is too large
Load Diff
3974
po/wxvbam/de.po
3974
po/wxvbam/de.po
File diff suppressed because it is too large
Load Diff
773
po/wxvbam/el.po
773
po/wxvbam/el.po
File diff suppressed because it is too large
Load Diff
1136
po/wxvbam/es.po
1136
po/wxvbam/es.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
1083
po/wxvbam/fr_FR.po
1083
po/wxvbam/fr_FR.po
File diff suppressed because it is too large
Load Diff
773
po/wxvbam/gl.po
773
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
773
po/wxvbam/id.po
773
po/wxvbam/id.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
773
po/wxvbam/ja.po
773
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
773
po/wxvbam/nb.po
773
po/wxvbam/nb.po
File diff suppressed because it is too large
Load Diff
773
po/wxvbam/nl.po
773
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
1119
po/wxvbam/sv.po
1119
po/wxvbam/sv.po
File diff suppressed because it is too large
Load Diff
773
po/wxvbam/tr.po
773
po/wxvbam/tr.po
File diff suppressed because it is too large
Load Diff
743
po/wxvbam/uk.po
743
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
BIN
resource.xrs
Normal file
BIN
resource.xrs
Normal file
Binary file not shown.
@@ -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();
|
||||
}
|
||||
|
@@ -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.
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/* Compiler.h : Compiler specific defines and pragmas
|
||||
2024-01-22 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef ZIP7_INC_COMPILER_H
|
||||
#define ZIP7_INC_COMPILER_H
|
||||
@@ -183,6 +183,16 @@ typedef void (*Z7_void_Function)(void);
|
||||
#define Z7_ATTRIB_NO_VECTORIZE
|
||||
#endif
|
||||
|
||||
#if defined(Z7_MSC_VER_ORIGINAL) && (Z7_MSC_VER_ORIGINAL >= 1920)
|
||||
#define Z7_PRAGMA_OPTIMIZE_FOR_CODE_SIZE _Pragma("optimize ( \"s\", on )")
|
||||
#define Z7_PRAGMA_OPTIMIZE_DEFAULT _Pragma("optimize ( \"\", on )")
|
||||
#else
|
||||
#define Z7_PRAGMA_OPTIMIZE_FOR_CODE_SIZE
|
||||
#define Z7_PRAGMA_OPTIMIZE_DEFAULT
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#if defined(MY_CPU_X86_OR_AMD64) && ( \
|
||||
defined(__clang__) && (__clang_major__ >= 4) \
|
||||
|| defined(__GNUC__) && (__GNUC__ >= 5))
|
||||
|
@@ -47,6 +47,12 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
|
||||
#define MY_CPU_SIZEOF_POINTER 4
|
||||
#endif
|
||||
|
||||
#if defined(__SSE2__) \
|
||||
|| defined(MY_CPU_AMD64) \
|
||||
|| defined(_M_IX86_FP) && (_M_IX86_FP >= 2)
|
||||
#define MY_CPU_SSE2
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_M_ARM64) \
|
||||
|| defined(_M_ARM64EC) \
|
||||
@@ -571,10 +577,12 @@ problem-4 : performace:
|
||||
#define Z7_CONV_BE_TO_NATIVE_CONST32(v) (v)
|
||||
#define Z7_CONV_LE_TO_NATIVE_CONST32(v) Z7_BSWAP32_CONST(v)
|
||||
#define Z7_CONV_NATIVE_TO_BE_32(v) (v)
|
||||
// #define Z7_GET_NATIVE16_FROM_2_BYTES(b0, b1) ((b1) | ((b0) << 8))
|
||||
#elif defined(MY_CPU_LE)
|
||||
#define Z7_CONV_BE_TO_NATIVE_CONST32(v) Z7_BSWAP32_CONST(v)
|
||||
#define Z7_CONV_LE_TO_NATIVE_CONST32(v) (v)
|
||||
#define Z7_CONV_NATIVE_TO_BE_32(v) Z7_BSWAP32(v)
|
||||
// #define Z7_GET_NATIVE16_FROM_2_BYTES(b0, b1) ((b0) | ((b1) << 8))
|
||||
#else
|
||||
#error Stop_Compiling_Unknown_Endian_CONV
|
||||
#endif
|
||||
|
@@ -59,6 +59,14 @@ BZ2_Inflater::~BZ2_Inflater()
|
||||
end();
|
||||
}
|
||||
|
||||
blargg_err_t BZ2_Inflater::skip_buf( int count )
|
||||
{
|
||||
byte* out = buf.end() - count;
|
||||
zbuf.avail_in = count;
|
||||
zbuf.next_in = (char *)out;
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t BZ2_Inflater::fill_buf( int count )
|
||||
{
|
||||
byte* out = buf.end() - count;
|
||||
@@ -164,6 +172,20 @@ blargg_err_t BZ2_Inflater::read_all( void* out, int count )
|
||||
}
|
||||
*/
|
||||
|
||||
blargg_err_t BZ2_Inflater::get_size( int* count_io )
|
||||
{
|
||||
char *buffer = (char *)malloc(*count_io);
|
||||
|
||||
if (buffer == NULL) {
|
||||
return blargg_err_memory;
|
||||
}
|
||||
|
||||
read(buffer, count_io);
|
||||
free(buffer);
|
||||
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t BZ2_Inflater::read( void* out, int* count_io )
|
||||
{
|
||||
int remain = *count_io;
|
||||
|
@@ -20,6 +20,7 @@ class BZ2_Inflater
|
||||
// filled to 4K, or specify buf_size and initial_read for custom buffer size
|
||||
// and how much to read initially.
|
||||
blargg_err_t begin(callback_t, void *user_data, int buf_size = 0, int initial_read = 0);
|
||||
blargg_err_t get_size(int *count_io);
|
||||
|
||||
// Data read into buffer by begin()
|
||||
const unsigned char *data() const
|
||||
@@ -85,6 +86,7 @@ class BZ2_Inflater
|
||||
void *user_data;
|
||||
|
||||
blargg_err_t fill_buf(int count);
|
||||
blargg_err_t skip_buf(int count);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -19,6 +19,8 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#include "blargg_source.h"
|
||||
|
||||
#include <bzlib.h>
|
||||
|
||||
BZ2_Reader::BZ2_Reader()
|
||||
{
|
||||
close();
|
||||
@@ -34,8 +36,16 @@ static blargg_err_t BZ2_reader_read( void* file, void* out, int* count )
|
||||
|
||||
blargg_err_t BZ2_Reader::calc_size()
|
||||
{
|
||||
size_ = 33554432;
|
||||
size_ = 0x8000000; // Max cart size
|
||||
crc32_ = 0;
|
||||
|
||||
set_remain(size_);
|
||||
inflater.get_size(&size_);
|
||||
|
||||
fprintf(stderr, "Calculated BZ2 size: %d\n", size_);
|
||||
|
||||
in->seek(0);
|
||||
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
@@ -48,6 +58,9 @@ blargg_err_t BZ2_Reader::open( File_Reader* new_in )
|
||||
RETURN_ERR( inflater.begin( BZ2_reader_read, new_in ) );
|
||||
RETURN_ERR( inflater.set_mode( inflater.mode_auto ) );
|
||||
RETURN_ERR( calc_size() );
|
||||
inflater.end();
|
||||
RETURN_ERR( inflater.begin( BZ2_reader_read, new_in ) );
|
||||
RETURN_ERR( inflater.set_mode( inflater.mode_auto ) );
|
||||
set_remain( size_ );
|
||||
|
||||
return blargg_ok;
|
||||
@@ -65,7 +78,7 @@ blargg_err_t BZ2_Reader::read_v( void* out, int count )
|
||||
int actual = count;
|
||||
RETURN_ERR( inflater.read( out, &actual ) );
|
||||
|
||||
if ( actual < count ) {
|
||||
if ( actual < size_ ) {
|
||||
size_ = actual;
|
||||
inflater.resize_buffer(actual);
|
||||
set_remain(0);
|
||||
|
@@ -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
|
||||
|
@@ -165,6 +165,8 @@ uint8_t memoryWait32[16] = { 0, 0, 5, 0, 0, 1, 1, 0, 7, 7, 9, 9, 13, 13, 4, 0 };
|
||||
uint8_t memoryWaitSeq[16] = { 0, 0, 2, 0, 0, 0, 0, 0, 2, 2, 4, 4, 8, 8, 4, 0 };
|
||||
uint8_t memoryWaitSeq32[16] = { 0, 0, 5, 0, 0, 1, 1, 0, 5, 5, 9, 9, 17, 17, 4, 0 };
|
||||
|
||||
GBAMatrix_t stateMatrix;
|
||||
|
||||
// The videoMemoryWait constants are used to add some waitstates
|
||||
// if the opcode access video memory data outside of vblank/hblank
|
||||
// It seems to happen on only one ticks for each pixel.
|
||||
@@ -474,6 +476,40 @@ variable_desc saveGameStruct[] = {
|
||||
};
|
||||
|
||||
static int romSize = SIZE_ROM;
|
||||
static int pristineRomSize = 0;
|
||||
|
||||
#define MAPPING_MASK (GBA_MATRIX_MAPPINGS_MAX - 1)
|
||||
|
||||
static void _remapMatrix(GBAMatrix_t *matrix)
|
||||
{
|
||||
if (matrix == NULL) {
|
||||
log("Matrix is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
if (matrix->vaddr & 0xFFFFE1FF) {
|
||||
log("Invalid Matrix mapping: %08X", matrix->vaddr);
|
||||
return;
|
||||
}
|
||||
if (matrix->size & 0xFFFFE1FF) {
|
||||
log("Invalid Matrix size: %08X", matrix->size);
|
||||
return;
|
||||
}
|
||||
if ((matrix->vaddr + matrix->size - 1) & 0xFFFFE000) {
|
||||
log("Invalid Matrix mapping end: %08X", matrix->vaddr + matrix->size);
|
||||
return;
|
||||
}
|
||||
int start = matrix->vaddr >> 9;
|
||||
int size = (matrix->size >> 9) & MAPPING_MASK;
|
||||
int i;
|
||||
for (i = 0; i < size; ++i) {
|
||||
matrix->mappings[(start + i) & MAPPING_MASK] = matrix->paddr + (i << 9);
|
||||
}
|
||||
|
||||
if ((g_rom2 != NULL) && (g_rom != NULL)) {
|
||||
memcpy(&g_rom[matrix->vaddr], &g_rom2[matrix->paddr], matrix->size);
|
||||
}
|
||||
}
|
||||
|
||||
void gbaUpdateRomSize(int size)
|
||||
{
|
||||
@@ -485,7 +521,7 @@ void gbaUpdateRomSize(int size)
|
||||
g_rom = tmp;
|
||||
|
||||
uint16_t* temp = (uint16_t*)(g_rom + ((romSize + 1) & ~1));
|
||||
for (int i = (romSize + 1) & ~1; i < SIZE_ROM; i += 2) {
|
||||
for (int i = (romSize + 1) & ~1; i < romSize; i += 2) {
|
||||
WRITE16LE(temp, (i >> 1) & 0xFFFF);
|
||||
temp++;
|
||||
}
|
||||
@@ -638,6 +674,15 @@ unsigned int CPUWriteState(uint8_t* data)
|
||||
soundSaveGame(data);
|
||||
rtcSaveGame(data);
|
||||
|
||||
if (pristineRomSize > SIZE_ROM) {
|
||||
uint8_t ident = 0;
|
||||
memcpy(&ident, &g_rom[0xAC], 1);
|
||||
|
||||
if (ident == 'M') {
|
||||
utilWriteMem(data, &GBAMatrix, sizeof(GBAMatrix));
|
||||
}
|
||||
}
|
||||
|
||||
return (ptrdiff_t)data - (ptrdiff_t)orig;
|
||||
}
|
||||
|
||||
@@ -683,6 +728,15 @@ bool CPUReadState(const uint8_t* data)
|
||||
soundReadGame(data);
|
||||
rtcReadGame(data);
|
||||
|
||||
if (pristineRomSize > SIZE_ROM) {
|
||||
uint8_t ident = 0;
|
||||
memcpy(&ident, &g_rom[0xAC], 1);
|
||||
|
||||
if (ident == 'M') {
|
||||
utilReadMem(&stateMatrix, data, sizeof(stateMatrix));
|
||||
}
|
||||
}
|
||||
|
||||
//// Copypasta stuff ...
|
||||
// set pointers!
|
||||
coreOptions.layerEnable = coreOptions.layerSettings & DISPCNT;
|
||||
@@ -710,6 +764,27 @@ bool CPUReadState(const uint8_t* data)
|
||||
|
||||
CPUUpdateRegister(0x204, CPUReadHalfWordQuick(0x4000204));
|
||||
|
||||
if (pristineRomSize > SIZE_ROM) {
|
||||
uint8_t ident = 0;
|
||||
memcpy(&ident, &g_rom[0xAC], 1);
|
||||
|
||||
if (ident == 'M') {
|
||||
GBAMatrix.size = 0x200;
|
||||
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
GBAMatrix.mappings[i] = stateMatrix.mappings[i];
|
||||
GBAMatrix.paddr = GBAMatrix.mappings[i];
|
||||
GBAMatrix.vaddr = i << 9;
|
||||
_remapMatrix(&GBAMatrix);
|
||||
}
|
||||
|
||||
GBAMatrix.cmd = stateMatrix.cmd;
|
||||
GBAMatrix.paddr = stateMatrix.paddr;
|
||||
GBAMatrix.vaddr = stateMatrix.vaddr;
|
||||
GBAMatrix.size = stateMatrix.size;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -749,6 +824,15 @@ static bool CPUWriteState(gzFile gzFile)
|
||||
// version 1.5
|
||||
rtcSaveGame(gzFile);
|
||||
|
||||
if (pristineRomSize > SIZE_ROM) {
|
||||
uint8_t ident = 0;
|
||||
memcpy(&ident, &g_rom[0xAC], 1);
|
||||
|
||||
if (ident == 'M') {
|
||||
utilGzWrite(gzFile, &GBAMatrix, sizeof(GBAMatrix));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -880,6 +964,15 @@ static bool CPUReadState(gzFile gzFile)
|
||||
rtcReadGame(gzFile);
|
||||
}
|
||||
|
||||
if (pristineRomSize > SIZE_ROM) {
|
||||
uint8_t ident = 0;
|
||||
memcpy(&ident, &g_rom[0xAC], 1);
|
||||
|
||||
if (ident == 'M') {
|
||||
utilGzRead(gzFile, &stateMatrix, sizeof(stateMatrix));
|
||||
}
|
||||
}
|
||||
|
||||
if (version <= SAVE_GAME_VERSION_7) {
|
||||
uint32_t temp;
|
||||
#define SWAP(a, b, c) \
|
||||
@@ -930,6 +1023,27 @@ static bool CPUReadState(gzFile gzFile)
|
||||
|
||||
CPUUpdateRegister(0x204, CPUReadHalfWordQuick(0x4000204));
|
||||
|
||||
if (pristineRomSize > SIZE_ROM) {
|
||||
uint8_t ident = 0;
|
||||
memcpy(&ident, &g_rom[0xAC], 1);
|
||||
|
||||
if (ident == 'M') {
|
||||
GBAMatrix.size = 0x200;
|
||||
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
GBAMatrix.mappings[i] = stateMatrix.mappings[i];
|
||||
GBAMatrix.paddr = GBAMatrix.mappings[i];
|
||||
GBAMatrix.vaddr = i << 9;
|
||||
_remapMatrix(&GBAMatrix);
|
||||
}
|
||||
|
||||
GBAMatrix.cmd = stateMatrix.cmd;
|
||||
GBAMatrix.paddr = stateMatrix.paddr;
|
||||
GBAMatrix.vaddr = stateMatrix.vaddr;
|
||||
GBAMatrix.size = stateMatrix.size;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1389,6 +1503,11 @@ void CPUCleanUp()
|
||||
g_rom = NULL;
|
||||
}
|
||||
|
||||
if (g_rom2 != NULL) {
|
||||
free(g_rom2);
|
||||
g_rom2 = NULL;
|
||||
}
|
||||
|
||||
if (g_vram != NULL) {
|
||||
free(g_vram);
|
||||
g_vram = NULL;
|
||||
@@ -1479,16 +1598,108 @@ void SetMapMasks()
|
||||
#endif
|
||||
}
|
||||
|
||||
void GBAMatrixReset(GBAMatrix_t *matrix) {
|
||||
if (matrix == NULL) {
|
||||
log("Matrix is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(matrix->mappings, 0, sizeof(matrix->mappings));
|
||||
matrix->size = 0x1000;
|
||||
|
||||
matrix->paddr = 0;
|
||||
matrix->vaddr = 0;
|
||||
_remapMatrix(matrix);
|
||||
matrix->paddr = 0x200;
|
||||
matrix->vaddr = 0x1000;
|
||||
_remapMatrix(matrix);
|
||||
}
|
||||
|
||||
void GBAMatrixWrite(GBAMatrix_t *matrix, uint32_t address, uint32_t value)
|
||||
{
|
||||
if (matrix == NULL) {
|
||||
log("Matrix is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (address) {
|
||||
case 0x0:
|
||||
matrix->cmd = value;
|
||||
switch (value) {
|
||||
case 0x01:
|
||||
case 0x11:
|
||||
_remapMatrix(matrix);
|
||||
break;
|
||||
default:
|
||||
log("Unknown Matrix command: %08X", value);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
case 0x4:
|
||||
matrix->paddr = value & 0x03FFFFFF;
|
||||
return;
|
||||
case 0x8:
|
||||
matrix->vaddr = value & 0x007FFFFF;
|
||||
return;
|
||||
case 0xC:
|
||||
if (value == 0) {
|
||||
log("Rejecting Matrix write for size 0");
|
||||
return;
|
||||
}
|
||||
matrix->size = value << 9;
|
||||
return;
|
||||
}
|
||||
log("Unknown Matrix write: %08X:%04X", address, value);
|
||||
}
|
||||
|
||||
void GBAMatrixWrite16(GBAMatrix_t *matrix, uint32_t address, uint16_t value)
|
||||
{
|
||||
if (matrix == NULL) {
|
||||
log("Matrix is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (address) {
|
||||
case 0x0:
|
||||
GBAMatrixWrite(matrix, address, value | (matrix->cmd & 0xFFFF0000));
|
||||
break;
|
||||
case 0x4:
|
||||
GBAMatrixWrite(matrix, address, value | (matrix->paddr & 0xFFFF0000));
|
||||
break;
|
||||
case 0x8:
|
||||
GBAMatrixWrite(matrix, address, value | (matrix->vaddr & 0xFFFF0000));
|
||||
break;
|
||||
case 0xC:
|
||||
GBAMatrixWrite(matrix, address, value | (matrix->size & 0xFFFF0000));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
romSize = get_gba_rom_size(szFile);
|
||||
if (g_rom != NULL) {
|
||||
CPUCleanUp();
|
||||
}
|
||||
|
||||
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
||||
|
||||
g_rom = (uint8_t*)malloc(SIZE_ROM);
|
||||
g_rom = (uint8_t*)malloc(romSize);
|
||||
if (g_rom == NULL) {
|
||||
systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
|
||||
"ROM");
|
||||
@@ -1539,13 +1750,39 @@ int CPULoadRom(const char* szFile)
|
||||
}
|
||||
}
|
||||
|
||||
memset(&GBAMatrix, 0, sizeof(GBAMatrix));
|
||||
pristineRomSize = romSize;
|
||||
|
||||
uint16_t* temp = (uint16_t*)(g_rom + ((romSize + 1) & ~1));
|
||||
int i;
|
||||
for (i = (romSize + 1) & ~1; i < SIZE_ROM; i += 2) {
|
||||
for (i = (romSize + 1) & ~1; i < romSize; i += 2) {
|
||||
WRITE16LE(temp, (i >> 1) & 0xFFFF);
|
||||
temp++;
|
||||
}
|
||||
|
||||
char ident = 0;
|
||||
|
||||
if (romSize > SIZE_ROM) {
|
||||
memcpy(&ident, &g_rom[0xAC], 1);
|
||||
|
||||
if (ident == 'M') {
|
||||
g_rom2 = (uint8_t*)malloc(SIZE_ROM * 4);
|
||||
if (!utilLoad(szFile,
|
||||
utilIsGBAImage,
|
||||
g_rom2,
|
||||
romSize)) {
|
||||
free(g_rom2);
|
||||
g_rom2 = NULL;
|
||||
}
|
||||
|
||||
romSize = 0x01000000;
|
||||
|
||||
log("GBA Matrix detected");
|
||||
} else {
|
||||
romSize = SIZE_ROM;
|
||||
}
|
||||
}
|
||||
|
||||
g_bios = (uint8_t*)calloc(1, SIZE_BIOS);
|
||||
if (g_bios == NULL) {
|
||||
systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
|
||||
@@ -1607,14 +1844,14 @@ int CPULoadRom(const char* szFile)
|
||||
|
||||
int CPULoadRomData(const char* data, int size)
|
||||
{
|
||||
romSize = SIZE_ROM;
|
||||
romSize = size % 2 == 0 ? size : size + 1;
|
||||
if (g_rom != NULL) {
|
||||
CPUCleanUp();
|
||||
}
|
||||
|
||||
systemSaveUpdateCounter = SYSTEM_SAVE_NOT_UPDATED;
|
||||
|
||||
g_rom = (uint8_t*)malloc(SIZE_ROM);
|
||||
g_rom = (uint8_t*)malloc(romSize);
|
||||
if (g_rom == NULL) {
|
||||
systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
|
||||
"ROM");
|
||||
@@ -1632,13 +1869,31 @@ int CPULoadRomData(const char* data, int size)
|
||||
romSize = size % 2 == 0 ? size : size + 1;
|
||||
memcpy(whereToLoad, data, size);
|
||||
|
||||
memset(&GBAMatrix, 0, sizeof(GBAMatrix));
|
||||
pristineRomSize = romSize;
|
||||
|
||||
uint16_t* temp = (uint16_t*)(g_rom + ((romSize + 1) & ~1));
|
||||
int i;
|
||||
for (i = (romSize + 1) & ~1; i < SIZE_ROM; i += 2) {
|
||||
for (i = (romSize + 1) & ~1; i < romSize; i += 2) {
|
||||
WRITE16LE(temp, (i >> 1) & 0xFFFF);
|
||||
temp++;
|
||||
}
|
||||
|
||||
if (romSize > SIZE_ROM) {
|
||||
char ident = 0;
|
||||
memcpy(&ident, &g_rom[0xAC], 1);
|
||||
|
||||
if (ident == 'M') {
|
||||
g_rom2 = (uint8_t *)malloc(romSize);
|
||||
memcpy(g_rom2, data, size);
|
||||
romSize = 0x01000000;
|
||||
|
||||
log("GBA Matrix detected");
|
||||
} else {
|
||||
romSize = SIZE_ROM;
|
||||
}
|
||||
}
|
||||
|
||||
g_bios = (uint8_t*)calloc(1, SIZE_BIOS);
|
||||
if (g_bios == NULL) {
|
||||
systemMessage(MSG_OUT_OF_MEMORY, N_("Failed to allocate memory for %s"),
|
||||
@@ -3686,6 +3941,15 @@ void CPUReset()
|
||||
lastTime = systemGetClock();
|
||||
|
||||
SWITicks = 0;
|
||||
|
||||
if (pristineRomSize > SIZE_ROM) {
|
||||
char ident = 0;
|
||||
memcpy(&ident, &g_rom[0xAC], 1);
|
||||
|
||||
if (ident == 'M') {
|
||||
GBAMatrixReset(&GBAMatrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CPUInterrupt()
|
||||
@@ -3962,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];
|
||||
@@ -3985,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: {
|
||||
@@ -4023,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: {
|
||||
|
@@ -2593,6 +2593,19 @@ static INSN_REGPARM void armE01(uint32_t opcode)
|
||||
#define armE01 armUnknownInsn
|
||||
#endif
|
||||
|
||||
static INSN_REGPARM void armE80(uint32_t opcode)
|
||||
{
|
||||
if ((opcode & 0xFFFC0000) == (0xEE800000)) {
|
||||
#ifdef GBA_LOGGING
|
||||
if (systemVerbose & VERBOSE_UNDEFINED)
|
||||
log("Undefined Wii U ARM instruction %08x at %08Xx\n", opcode, armNextPC - 4);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
armUnknownInsn(opcode);
|
||||
}
|
||||
|
||||
// SWI <comment>
|
||||
static INSN_REGPARM void armF00(uint32_t opcode)
|
||||
{
|
||||
@@ -2791,7 +2804,11 @@ static insnfunc_t armInsnTable[4096] = {
|
||||
REP16(arm_UI), // E20
|
||||
REP16(arm_UI), // E30
|
||||
REP16(arm_UI), REP16(arm_UI), REP16(arm_UI), REP16(arm_UI), // E40
|
||||
REP16(arm_UI), REP16(arm_UI), REP16(arm_UI), REP16(arm_UI), // E80
|
||||
|
||||
armE80, arm_UI, arm_UI, arm_UI, arm_UI, arm_UI, arm_UI, arm_UI, // E80
|
||||
arm_UI, arm_UI, arm_UI, arm_UI, arm_UI, arm_UI, arm_UI, arm_UI, // E88
|
||||
|
||||
REP16(arm_UI), REP16(arm_UI), REP16(arm_UI), // E90
|
||||
REP16(arm_UI), REP16(arm_UI), REP16(arm_UI), REP16(arm_UI), // EC0
|
||||
|
||||
REP256(armF00), // F00
|
||||
|
@@ -26,8 +26,11 @@ bool gba_joybus_active = false;
|
||||
// 0x0000 to 0x7FFF: set custom 15 bit color
|
||||
int customBackdropColor = -1;
|
||||
|
||||
GBAMatrix_t GBAMatrix;
|
||||
|
||||
uint8_t* g_bios = 0;
|
||||
uint8_t* g_rom = 0;
|
||||
uint8_t* g_rom2 = 0;
|
||||
uint8_t* g_internalRAM = 0;
|
||||
uint8_t* g_workRAM = 0;
|
||||
uint8_t* g_paletteRAM = 0;
|
||||
|
@@ -15,6 +15,23 @@
|
||||
#define VERBOSE_AGBPRINT 512
|
||||
#define VERBOSE_SOUNDOUTPUT 1024
|
||||
|
||||
#define GBA_MATRIX_MAPPINGS_MAX 16
|
||||
|
||||
typedef struct GBAMatrix {
|
||||
uint32_t cmd;
|
||||
uint32_t paddr;
|
||||
uint32_t vaddr;
|
||||
uint32_t size;
|
||||
|
||||
uint32_t mappings[GBA_MATRIX_MAPPINGS_MAX];
|
||||
} GBAMatrix_t;
|
||||
|
||||
extern GBAMatrix_t GBAMatrix;
|
||||
|
||||
extern void GBAMatrixReset(GBAMatrix_t *matrix);
|
||||
extern void GBAMatrixWrite(GBAMatrix_t *matrix, uint32_t address, uint32_t value);
|
||||
extern void GBAMatrixWrite16(GBAMatrix_t *matrix, uint32_t address, uint16_t value);
|
||||
|
||||
extern reg_pair reg[45];
|
||||
extern bool ioReadable[0x400];
|
||||
extern bool N_FLAG;
|
||||
@@ -32,6 +49,7 @@ extern int customBackdropColor;
|
||||
|
||||
extern uint8_t* g_bios;
|
||||
extern uint8_t* g_rom;
|
||||
extern uint8_t* g_rom2;
|
||||
extern uint8_t* g_internalRAM;
|
||||
extern uint8_t* g_workRAM;
|
||||
extern uint8_t* g_paletteRAM;
|
||||
|
@@ -535,6 +535,17 @@ static inline void CPUWriteMemory(uint32_t address, uint32_t value)
|
||||
#endif
|
||||
WRITE32LE(((uint32_t*)&g_oam[address & 0x3fc]), value);
|
||||
break;
|
||||
case 0x08:
|
||||
case 0x09:
|
||||
case 0x0A:
|
||||
case 0x0B:
|
||||
case 0x0C:
|
||||
if (GBAMatrix.size && (address & 0x01FFFF00) == 0x00800100)
|
||||
{
|
||||
GBAMatrixWrite(&GBAMatrix, address & 0x3C, value);
|
||||
break;
|
||||
}
|
||||
goto unwritable;
|
||||
case 0x0D:
|
||||
if (cpuEEPROMEnabled) {
|
||||
eepromWrite(address, DowncastU8(value));
|
||||
@@ -639,12 +650,26 @@ static inline void CPUWriteHalfWord(uint32_t address, uint16_t value)
|
||||
break;
|
||||
case 8:
|
||||
case 9:
|
||||
if (GBAMatrix.size && (address & 0x01FFFF00) == 0x00800100)
|
||||
{
|
||||
GBAMatrixWrite16(&GBAMatrix, address & 0x3C, value);
|
||||
break;
|
||||
}
|
||||
if (address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8) {
|
||||
if (!rtcWrite(address, value))
|
||||
goto unwritable;
|
||||
} else if (!agbPrintWrite(address, value))
|
||||
goto unwritable;
|
||||
break;
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
if (GBAMatrix.size && (address & 0x01FFFF00) == 0x00800100)
|
||||
{
|
||||
GBAMatrixWrite16(&GBAMatrix, address & 0x3C, value);
|
||||
break;
|
||||
}
|
||||
goto unwritable;
|
||||
case 13:
|
||||
if (cpuEEPROMEnabled) {
|
||||
eepromWrite(address, (uint8_t)value);
|
||||
|
@@ -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";
|
||||
@@ -1632,12 +1679,26 @@ bool retro_load_game(const struct retro_game_info *game)
|
||||
desc[1].start=0x02000000; desc[1].select=0xFF000000; desc[1].len=0x40000; desc[1].ptr=g_workRAM;//slow WRAM
|
||||
/* TODO: if SRAM is flash, use start=0 addrspace="S" instead */
|
||||
desc[2].start=0x0E000000; desc[2].select=0; desc[2].len=g_flashSize; desc[2].ptr=flashSaveMemory;//SRAM
|
||||
desc[3].start=0x08000000; desc[3].select=0; desc[3].len=romSize; desc[3].ptr=g_rom;//ROM
|
||||
desc[3].flags=RETRO_MEMDESC_CONST;
|
||||
desc[4].start=0x0A000000; desc[4].select=0; desc[4].len=romSize; desc[4].ptr=g_rom;//ROM mirror 1
|
||||
desc[4].flags=RETRO_MEMDESC_CONST;
|
||||
desc[5].start=0x0C000000; desc[5].select=0; desc[5].len=romSize; desc[5].ptr=g_rom;//ROM mirror 2
|
||||
desc[5].flags=RETRO_MEMDESC_CONST;
|
||||
|
||||
char ident = 0;
|
||||
memcpy(&ident, &g_rom[0xAC], 1);
|
||||
|
||||
if (ident == 'M') {
|
||||
desc[3].start=0x08000000; desc[3].select=0; desc[3].len=SIZE_ROM; desc[3].ptr=g_rom;//ROM
|
||||
desc[3].flags=RETRO_MEMDESC_CONST;
|
||||
desc[4].start=0x0A000000; desc[4].select=0; desc[4].len=SIZE_ROM; desc[4].ptr=g_rom;//ROM mirror 1
|
||||
desc[4].flags=RETRO_MEMDESC_CONST;
|
||||
desc[5].start=0x0C000000; desc[5].select=0; desc[5].len=SIZE_ROM; desc[5].ptr=g_rom;//ROM mirror 2
|
||||
desc[5].flags=RETRO_MEMDESC_CONST;
|
||||
} else {
|
||||
desc[3].start=0x08000000; desc[3].select=0; desc[3].len=romSize; desc[3].ptr=g_rom;//ROM
|
||||
desc[3].flags=RETRO_MEMDESC_CONST;
|
||||
desc[4].start=0x0A000000; desc[4].select=0; desc[4].len=romSize; desc[4].ptr=g_rom;//ROM mirror 1
|
||||
desc[4].flags=RETRO_MEMDESC_CONST;
|
||||
desc[5].start=0x0C000000; desc[5].select=0; desc[5].len=romSize; desc[5].ptr=g_rom;//ROM mirror 2
|
||||
desc[5].flags=RETRO_MEMDESC_CONST;
|
||||
}
|
||||
|
||||
desc[6].start=0x00000000; desc[6].select=0; desc[6].len=0x4000; desc[6].ptr=g_bios;//BIOS
|
||||
desc[6].flags=RETRO_MEMDESC_CONST;
|
||||
desc[7].start=0x06000000; desc[7].select=0xFF000000; desc[7].len=0x18000; desc[7].ptr=g_vram;//VRAM
|
||||
@@ -1732,7 +1793,7 @@ bool retro_load_game(const struct retro_game_info *game)
|
||||
|
||||
update_input_descriptors(); // Initialize input descriptors and info
|
||||
update_variables(false);
|
||||
uint8_t* state_buf = (uint8_t*)malloc(2000000);
|
||||
uint8_t* state_buf = (uint8_t*)malloc(2000080);
|
||||
serialize_size = core->emuWriteState(state_buf);
|
||||
free(state_buf);
|
||||
|
||||
@@ -1741,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)
|
||||
@@ -1773,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)
|
||||
@@ -394,6 +407,9 @@ if(APPLE)
|
||||
default
|
||||
)
|
||||
endif()
|
||||
|
||||
# Needed for CoreAudio.
|
||||
target_compile_options(visualboyadvance-m PRIVATE -Wno-error=elaborated-enum-base)
|
||||
endif()
|
||||
|
||||
target_sources(visualboyadvance-m PRIVATE ${VBAM_WX_COMMON} ${VBAM_ICON_PATH})
|
||||
@@ -421,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
|
||||
@@ -479,6 +496,7 @@ if(WIN32)
|
||||
PRIVATE
|
||||
audio/internal/dsound.cpp
|
||||
wxvbam.rc
|
||||
wxvbam_translations.rc
|
||||
)
|
||||
target_link_libraries(visualboyadvance-m
|
||||
dxguid dsound wsock32 ws2_32 imm32 version winmm)
|
||||
|
@@ -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);
|
||||
|
||||
@@ -113,8 +113,6 @@ void SDLAudio::deinit() {
|
||||
|
||||
SDLAudio::~SDLAudio() {
|
||||
deinit();
|
||||
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
}
|
||||
|
||||
bool SDLAudio::init(long sampleRate) {
|
||||
@@ -154,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;
|
||||
}
|
||||
|
@@ -27,10 +27,78 @@
|
||||
#include "wx/config/option-proxy.h"
|
||||
#include "wx/config/option.h"
|
||||
#include "wx/dialogs/game-maker.h"
|
||||
#include "wx/wxvbam.h"
|
||||
#include "wx/widgets/group-check-box.h"
|
||||
#include "wx/widgets/user-input-ctrl.h"
|
||||
#include "wx/widgets/utils.h"
|
||||
|
||||
#define GetXRCDialog(n) \
|
||||
wxStaticCast(wxGetApp().frame->FindWindowByName(n), wxDialog)
|
||||
|
||||
void RefreshFrame(void)
|
||||
{
|
||||
wxXmlResource* xr = wxXmlResource::Get();
|
||||
const wxRect client_rect(
|
||||
OPTION(kGeomWindowX).Get(),
|
||||
OPTION(kGeomWindowY).Get(),
|
||||
OPTION(kGeomWindowWidth).Get(),
|
||||
OPTION(kGeomWindowHeight).Get());
|
||||
const bool is_fullscreen = OPTION(kGeomFullScreen);
|
||||
const bool is_maximized = OPTION(kGeomIsMaximized);
|
||||
|
||||
// note: if linking statically, next 2 pull in lot of unused code
|
||||
// maybe in future if not wxSHARED, load only builtin-needed handlers
|
||||
xr->InitAllHandlers();
|
||||
xr->AddHandler(new widgets::GroupCheckBoxXmlHandler());
|
||||
xr->AddHandler(new widgets::UserInputCtrlXmlHandler());
|
||||
wxInitAllImageHandlers();
|
||||
|
||||
wxGetApp().SetExitOnFrameDelete(false);
|
||||
|
||||
if (wxGetApp().frame)
|
||||
wxGetApp().frame->Destroy();
|
||||
|
||||
wxGetApp().frame = wxDynamicCast(xr->LoadFrame(NULL, "MainFrame"), MainFrame);
|
||||
if (!wxGetApp().frame) {
|
||||
wxLogError(_("Could not create main window"));
|
||||
return;
|
||||
}
|
||||
|
||||
wxConfigBase* cfg = wxConfigBase::Get();
|
||||
gopts.recent = new wxFileHistory(10);
|
||||
cfg->SetPath("/Recent");
|
||||
gopts.recent->Load(*cfg);
|
||||
cfg->SetPath("/");
|
||||
cfg->Flush();
|
||||
|
||||
// Create() cannot be overridden easily
|
||||
if (!wxGetApp().frame->BindControls()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure we are not drawing out of bounds.
|
||||
if (widgets::GetDisplayRect().Intersects(client_rect)) {
|
||||
wxGetApp().frame->SetSize(client_rect);
|
||||
}
|
||||
|
||||
if (is_maximized) {
|
||||
wxGetApp().frame->Maximize();
|
||||
}
|
||||
|
||||
if (is_fullscreen && wxGetApp().pending_load != wxEmptyString)
|
||||
wxGetApp().frame->ShowFullScreen(is_fullscreen);
|
||||
|
||||
wxGetApp().frame->Show(true);
|
||||
|
||||
// Windows can render the taskbar icon late if this is done in MainFrame
|
||||
// It may also not update at all until the Window has been minimized/restored
|
||||
// This seems timing related, possibly based on HWND
|
||||
// So do this here since it reliably draws the Taskbar icon on Window creation.
|
||||
wxGetApp().frame->BindAppIcon();
|
||||
|
||||
wxGetApp().SetExitOnFrameDelete(true);
|
||||
}
|
||||
|
||||
void MainFrame::GetMenuOptionBool(const wxString& menuName, bool* field)
|
||||
{
|
||||
VBAM_CHECK(field);
|
||||
@@ -2262,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) {
|
||||
@@ -2643,13 +2711,753 @@ EVT_HANDLER(LinkConfigure, "Link options...")
|
||||
#endif
|
||||
}
|
||||
|
||||
EVT_HANDLER(ExternalTranslations, "Use external translations")
|
||||
{
|
||||
GetMenuOptionConfig("ExternalTranslations", config::OptionID::kExternalTranslations);
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language0, "Default Language")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_DEFAULT;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_DEFAULT);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language1, "Bulgarian")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_BULGARIAN;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_BULGARIAN);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language2, "Breton")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_BRETON;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_BRETON);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language3, "Czech")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_CZECH;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_CZECH);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language5, "Greek")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_GREEK;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_GREEK);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language6, "English (US)")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_ENGLISH_US;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_ENGLISH_US);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language7, "Spanish (Latin American)")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_SPANISH_LATIN_AMERICA;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_SPANISH_LATIN_AMERICA);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language8, "Spanish (Colombia)")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_SPANISH_COLOMBIA;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_SPANISH_COLOMBIA);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language9, "Spanish (Peru)")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_SPANISH_PERU;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_SPANISH_PERU);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language10, "Spanish (US)")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_SPANISH_US;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_SPANISH_US);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language11, "Spanish")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_SPANISH;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_SPANISH);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language12, "French (France)")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_FRENCH_FRANCE;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_FRENCH_FRANCE);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language13, "French")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_FRENCH;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_FRENCH);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language14, "Galician")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_GALICIAN;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_GALICIAN);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language15, "Hebrew (Israel)")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_HEBREW_ISRAEL;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_HEBREW_ISRAEL);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language16, "Hungarian (Hungary)")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_HUNGARIAN_HUNGARY;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_HUNGARIAN_HUNGARY);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language17, "Hungarian")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_HUNGARIAN;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_HUNGARIAN);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language18, "Indonesian")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_INDONESIAN;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_INDONESIAN);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language19, "Italian")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_ITALIAN_ITALY;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_ITALIAN_ITALY);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language20, "Japanese")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_JAPANESE;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_JAPANESE);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language21, "Korean (Korea)")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_KOREAN_KOREA;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_KOREAN_KOREA);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language22, "Korean")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_KOREAN;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_KOREAN);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language23, "Malay (Malaysia)")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_MALAY_MALAYSIA;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_MALAY_MALAYSIA);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language24, "Norwegian")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_NORWEGIAN;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_NORWEGIAN);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language25, "Dutch")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_DUTCH;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_DUTCH);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language26, "Polish (Poland)")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_POLISH_POLAND;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_POLISH_POLAND);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language27, "Polish")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_POLISH;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_POLISH);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language28, "Portuguese (Brazil)")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_PORTUGUESE_BRAZILIAN;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_PORTUGUESE_BRAZILIAN);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language29, "Portuguese (Portugal)")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_PORTUGUESE_PORTUGAL;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_PORTUGUESE_PORTUGAL);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language30, "Russian (Russia)")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_RUSSIAN_RUSSIA;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_RUSSIAN_RUSSIA);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language31, "Swedish")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_SWEDISH;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_SWEDISH);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language32, "Turkish")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_TURKISH;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_TURKISH);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language33, "Ukrainian")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_UKRAINIAN;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_UKRAINIAN);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language34, "Urdu (Pakistan)")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_URDU_PAKISTAN;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_URDU_PAKISTAN);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
EVT_HANDLER(Language35, "Chinese (China)")
|
||||
{
|
||||
OPTION(kLocale) = wxLANGUAGE_CHINESE_CHINA;
|
||||
|
||||
if (wxvbam_locale != NULL)
|
||||
wxDELETE(wxvbam_locale);
|
||||
|
||||
wxvbam_locale = new wxLocale;
|
||||
wxvbam_locale->Init(OPTION(kLocale), wxLOCALE_LOAD_DEFAULT);
|
||||
|
||||
#ifdef _WIN32
|
||||
if (OPTION(kExternalTranslations) == false)
|
||||
wxTranslations::Get()->SetLoader(new wxResourceTranslationsLoader);
|
||||
#endif
|
||||
|
||||
wxvbam_locale->AddCatalog("wxvbam", wxLANGUAGE_CHINESE_CHINA);
|
||||
|
||||
update_opts();
|
||||
RefreshFrame();
|
||||
}
|
||||
|
||||
// Dummy for disabling system key bindings
|
||||
EVT_HANDLER_MASK(NOOP, "Do nothing", CMDEN_NEVER)
|
||||
{
|
||||
}
|
||||
|
||||
// The following have been moved to dialogs
|
||||
// I will not implement as command unless there is great demand
|
||||
// I will not implement as command unless there is great demand cvbn,;
|
||||
// CheatsList
|
||||
//EVT_HANDLER(CheatsLoad, "Load Cheats...")
|
||||
//EVT_HANDLER(CheatsSave, "Save Cheats...")
|
||||
|
@@ -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.
|
||||
@@ -158,27 +167,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;
|
||||
@@ -252,6 +266,8 @@ std::array<Option, kNbOptions>& Option::All() {
|
||||
int32_t volume = 100;
|
||||
uint32_t bitdepth = 3;
|
||||
wxString sdlrenderer = wxString("default");
|
||||
int locale = wxLANGUAGE_DEFAULT;
|
||||
bool exttrans = false;
|
||||
};
|
||||
static OwnedOptions g_owned_opts;
|
||||
|
||||
@@ -274,6 +290,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),
|
||||
@@ -288,6 +305,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),
|
||||
@@ -303,6 +321,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),
|
||||
@@ -393,6 +412,8 @@ std::array<Option, kNbOptions>& Option::All() {
|
||||
Option(OptionID::kSoundDSoundHWAccel, &g_owned_opts.dsound_hw_accel),
|
||||
Option(OptionID::kSoundUpmix, &g_owned_opts.upmix),
|
||||
Option(OptionID::kSoundVolume, &g_owned_opts.volume, 0, 200),
|
||||
Option(OptionID::kLocale, &g_owned_opts.locale, 0, 911),
|
||||
Option(OptionID::kExternalTranslations, &g_owned_opts.exttrans)
|
||||
};
|
||||
// clang-format on
|
||||
return g_all_opts;
|
||||
@@ -418,6 +439,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")},
|
||||
@@ -441,6 +463,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")},
|
||||
@@ -468,6 +491,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")},
|
||||
@@ -602,6 +626,8 @@ const std::array<OptionData, kNbOptions + 1> kAllOptionsData = {
|
||||
OptionData{"Sound/DSoundHWAccel", "DSoundHWAccel", _("Use DirectSound hardware acceleration")},
|
||||
OptionData{"Sound/Upmix", "Upmix", _("Upmix stereo to surround")},
|
||||
OptionData{"Sound/Volume", "", _("Sound volume (%)")},
|
||||
OptionData{"Language/Locale", _("Language")},
|
||||
OptionData{"Language/ExternalTranslations", _("External translations")},
|
||||
|
||||
// Last. This should never be used, it actually maps to OptionID::kLast.
|
||||
// This is to prevent a memory access violation error in case something
|
||||
@@ -646,6 +672,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);
|
||||
@@ -719,6 +751,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;
|
||||
@@ -772,6 +825,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;
|
||||
@@ -805,6 +862,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);
|
||||
|
||||
|
@@ -18,6 +18,7 @@ enum class OptionID {
|
||||
kDispScale,
|
||||
kDispStretch,
|
||||
kSDLRenderer,
|
||||
kDispColorCorrectionProfile,
|
||||
|
||||
/// GB
|
||||
kGBBiosFile,
|
||||
@@ -32,6 +33,7 @@ enum class OptionID {
|
||||
kGBPrintScreenCap,
|
||||
kGBROMDir,
|
||||
kGBGBCROMDir,
|
||||
kGBLighten,
|
||||
|
||||
/// GBA
|
||||
kGBABiosFile,
|
||||
@@ -47,6 +49,7 @@ enum class OptionID {
|
||||
kGBALinkType,
|
||||
#endif
|
||||
kGBAROMDir,
|
||||
kGBADarken,
|
||||
|
||||
/// General
|
||||
kGenAutoLoadLastState,
|
||||
@@ -137,6 +140,8 @@ enum class OptionID {
|
||||
kSoundDSoundHWAccel,
|
||||
kSoundUpmix,
|
||||
kSoundVolume,
|
||||
kLocale,
|
||||
kExternalTranslations,
|
||||
|
||||
// Do not add anything under here.
|
||||
Last,
|
||||
|
@@ -22,6 +22,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 +37,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 +53,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,
|
||||
@@ -141,6 +144,8 @@ static constexpr std::array<Option::Type, kNbOptions> kOptionsTypes = {
|
||||
/*kSoundDSoundHWAccel*/ Option::Type::kBool,
|
||||
/*kSoundUpmix*/ Option::Type::kBool,
|
||||
/*kSoundVolume*/ Option::Type::kInt,
|
||||
/*kLocale*/ Option::Type::kInt,
|
||||
/*kExternalTranslations*/ Option::Type::kBool,
|
||||
};
|
||||
|
||||
// Less verbose accessor for a specific OptionID with compile-time type checks.
|
||||
@@ -344,6 +349,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,38 @@ DisplayConfig::DisplayConfig(wxWindow* parent)
|
||||
sdlrenderer_selector_ = GetValidatedChild<wxChoice>("SDLRenderer");
|
||||
sdlrenderer_selector_->SetValidator(SDLDevicesValidator());
|
||||
|
||||
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,26 +1830,25 @@ 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
|
||||
wxMenuItem* recentmi = XRCITEM("RecentMenu");
|
||||
|
||||
wxMenuItem *recentmi = XRCITEM("RecentMenu");
|
||||
|
||||
if (recentmi && recentmi->IsSubMenu()) {
|
||||
recent = recentmi->GetSubMenu();
|
||||
gopts.recent->UseMenu(recent);
|
||||
@@ -1922,6 +1921,42 @@ bool MainFrame::BindControls()
|
||||
MenuOptionIntRadioValue("LinkType2Wireless", gopts.gba_link_type, 2);
|
||||
MenuOptionIntRadioValue("LinkType3GameCube", gopts.gba_link_type, 3);
|
||||
MenuOptionIntRadioValue("LinkType4Gameboy", gopts.gba_link_type, 4);
|
||||
MenuOptionIntRadioValue("Language0", OPTION(kLocale), wxLANGUAGE_DEFAULT);
|
||||
MenuOptionIntRadioValue("Language1", OPTION(kLocale), wxLANGUAGE_BULGARIAN);
|
||||
MenuOptionIntRadioValue("Language2", OPTION(kLocale), wxLANGUAGE_BRETON);
|
||||
MenuOptionIntRadioValue("Language3", OPTION(kLocale), wxLANGUAGE_CZECH);
|
||||
MenuOptionIntRadioValue("Language5", OPTION(kLocale), wxLANGUAGE_GREEK);
|
||||
MenuOptionIntRadioValue("Language6", OPTION(kLocale), wxLANGUAGE_ENGLISH_US);
|
||||
MenuOptionIntRadioValue("Language7", OPTION(kLocale), wxLANGUAGE_SPANISH_LATIN_AMERICA);
|
||||
MenuOptionIntRadioValue("Language8", OPTION(kLocale), wxLANGUAGE_SPANISH_COLOMBIA);
|
||||
MenuOptionIntRadioValue("Language9", OPTION(kLocale), wxLANGUAGE_SPANISH_PERU);
|
||||
MenuOptionIntRadioValue("Language10", OPTION(kLocale), wxLANGUAGE_SPANISH_US);
|
||||
MenuOptionIntRadioValue("Language11", OPTION(kLocale), wxLANGUAGE_SPANISH);
|
||||
MenuOptionIntRadioValue("Language12", OPTION(kLocale), wxLANGUAGE_FRENCH_FRANCE);
|
||||
MenuOptionIntRadioValue("Language13", OPTION(kLocale), wxLANGUAGE_FRENCH);
|
||||
MenuOptionIntRadioValue("Language14", OPTION(kLocale), wxLANGUAGE_GALICIAN);
|
||||
MenuOptionIntRadioValue("Language15", OPTION(kLocale), wxLANGUAGE_HEBREW_ISRAEL);
|
||||
MenuOptionIntRadioValue("Language16", OPTION(kLocale), wxLANGUAGE_HUNGARIAN_HUNGARY);
|
||||
MenuOptionIntRadioValue("Language17", OPTION(kLocale), wxLANGUAGE_HUNGARIAN);
|
||||
MenuOptionIntRadioValue("Language18", OPTION(kLocale), wxLANGUAGE_INDONESIAN);
|
||||
MenuOptionIntRadioValue("Language19", OPTION(kLocale), wxLANGUAGE_ITALIAN_ITALY);
|
||||
MenuOptionIntRadioValue("Language20", OPTION(kLocale), wxLANGUAGE_JAPANESE);
|
||||
MenuOptionIntRadioValue("Language21", OPTION(kLocale), wxLANGUAGE_KOREAN_KOREA);
|
||||
MenuOptionIntRadioValue("Language22", OPTION(kLocale), wxLANGUAGE_KOREAN);
|
||||
MenuOptionIntRadioValue("Language23", OPTION(kLocale), wxLANGUAGE_MALAY_MALAYSIA);
|
||||
MenuOptionIntRadioValue("Language24", OPTION(kLocale), wxLANGUAGE_NORWEGIAN);
|
||||
MenuOptionIntRadioValue("Language25", OPTION(kLocale), wxLANGUAGE_DUTCH);
|
||||
MenuOptionIntRadioValue("Language26", OPTION(kLocale), wxLANGUAGE_POLISH_POLAND);
|
||||
MenuOptionIntRadioValue("Language27", OPTION(kLocale), wxLANGUAGE_POLISH);
|
||||
MenuOptionIntRadioValue("Language28", OPTION(kLocale), wxLANGUAGE_PORTUGUESE_BRAZILIAN);
|
||||
MenuOptionIntRadioValue("Language29", OPTION(kLocale), wxLANGUAGE_PORTUGUESE_PORTUGAL);
|
||||
MenuOptionIntRadioValue("Language30", OPTION(kLocale), wxLANGUAGE_RUSSIAN_RUSSIA);
|
||||
MenuOptionIntRadioValue("Language31", OPTION(kLocale), wxLANGUAGE_SWEDISH);
|
||||
MenuOptionIntRadioValue("Language32", OPTION(kLocale), wxLANGUAGE_TURKISH);
|
||||
MenuOptionIntRadioValue("Language33", OPTION(kLocale), wxLANGUAGE_UKRAINIAN);
|
||||
MenuOptionIntRadioValue("Language34", OPTION(kLocale), wxLANGUAGE_URDU_PAKISTAN);
|
||||
MenuOptionIntRadioValue("Language35", OPTION(kLocale), wxLANGUAGE_CHINESE_CHINA);
|
||||
MenuOptionBool("ExternalTranslations", OPTION(kExternalTranslations));
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < checkable_mi.size(); i++) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user