Compare commits

...

67 Commits

Author SHA1 Message Date
Rafael Kitover
99cc0a1d39 translations: transifex pull
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-10-05 19:00:20 +00:00
Rafael Kitover
3eee048326 Fix list cheats dialog for dark mode
Change unselected item color from white to none in the List Cheats
dialog to fix it for dark mode.

Done with Claude.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-10-04 22:53:04 +00:00
Rafael Kitover
9551313e19 Add tooltips with numerical value to all sliders
Add a tooltip with the numerical value to all slider widgets in the GUI
on the slider.

Done with Claude.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-10-04 22:38:48 +00:00
Rafael Kitover
cf3a48e15c translations: transifex pull
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-10-04 14:00:20 +00:00
Rafael Kitover
4819adefd1 translations: transifex pull
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-10-04 13:00:20 +00:00
Rafael Kitover
cb5689b216 build: fix Intel macOS build
Fix the Intel build for the macOS builder.

Disable tests for the fmt dist because they do not compile for Intel.

Use the XCode `libclang_rt.osx.a` when not using the Nix clang on ARM64.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-10-04 03:36:08 -07:00
Rafael Kitover
6e20fdc2e3 build: check CMake variable ENABLE_SHARED
Check for the commonly used CMake variable `ENABLE_SHARED` and set
`VBAM_STATIC` accordingly if it is set.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-10-04 09:45:52 +00:00
Rafael Kitover
479a7d9097 build: add libfmt for macOS builder
Add libfmt to the dists for the macOS builder, needed by wxWidgets.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-10-03 23:45:43 -07:00
Rafael Kitover
3a031a01a4 build: link libclang_rt.osx on macOS
Find and link `libclang_rt.osx.a` when using the Nix clang in the macOS
builder.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-10-03 23:45:43 -07:00
Rafael Kitover
c34be3c738 build: link System framework on macOS
Add `-framework System` to SDL libs and wxWidgets targets.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-10-03 23:40:00 -07:00
Rafael Kitover
5a21d94269 translations: transifex pull
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-10-04 04:00:22 +00:00
Rafael Kitover
f653261f97 translations: rebuild source .pot
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-10-04 04:00:07 +00:00
Rafael Kitover
4208f5af6e Fix issues and default dev in Mac CoreAudio driver
Fix some issues identified by Claude in the Mac CoreAudio sound driver,
including a race condition and some memory leaks.

Also fix selecting the default device.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-10-04 02:59:40 +00:00
Rafael Kitover
fc34bbbd12 Add missing error translation in Metal driver
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-10-03 04:43:47 +00:00
Rafael Kitover
b499c2d58c Fix mem leak and wrong API use in Metal driver
Fix massive texture memory leak and some other things wrong with the
Metal driver as suggested by Claude.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-10-02 20:04:42 +00:00
Rafael Kitover
e8aa4467f1 build: disable default bundling of dylibs on macOS
Add CMake option `BUNDLE_DYLIBS` defaulting to `OFF` to bundle dynamic
libraries into the `.app` bundle. This was the default behavior for
`Release` previously.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-10-02 18:30:02 +00:00
Rafael Kitover
40c798ef99 "Claude Code Review workflow" 2025-10-02 14:13:51 +00:00
Rafael Kitover
63894ad3f7 "Claude PR Assistant workflow" 2025-10-02 14:13:51 +00:00
Rafael Kitover
68e7d98b85 Fix pause when inactive for new wxWidgets
Handle the Iconize event to pause when "pause when inactive" is enabled,
to work around a change in recent versions of wxWidgets that ignore this
unfocus event.

Fix #1494.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-10-01 17:05:39 +00:00
Rafael Kitover
ed1b7ff47c translations: transifex pull
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-09-30 16:00:34 +00:00
Rafael Kitover
ff7d1234ea translations: rebuild source .pot
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-09-30 16:00:18 +00:00
Squall-Leonhart
e889e895f2 don't run Color Correct on SGB Hardware, Run GBA Color correct on GBC game run on GBA Hardware 2025-09-29 20:27:05 +00:00
Rafael Kitover
eb7c50017d Revert "SDL PixelArt test fix"
This reverts commit e0e639a02e.
2025-09-28 08:54:42 +00:00
Rafael Kitover
df66c6ff4a Revert "Check file size for GBA ROM and reduce memory footprint"
This reverts commit 56ea6456f5.
2025-09-28 08:54:26 +00:00
Squall Leonhart
e0e639a02e SDL PixelArt test fix 2025-09-28 15:29:17 +10:00
Brad Smith
ede668b712 Fixes for BSD build
- patch fixes for BSD handling
- OpenBSD/aarch64 has elf_aux_info()
- unrar build fix for FreeBSD/NetBSD/OpenBSD
- OpenBSD does not have librt

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-09-25 15:05:32 +00:00
Rafael Kitover
5bd8904746 build: fix check for SDL3 pixel art filter
Fix the CMake compile check for SDL_SCALEMODE_PIXELART to use
CheckSourceCompiles instead of CheckSymbolExists which does not work for
this purpose.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-09-21 19:33:29 +00:00
Rafael Kitover
46326939eb translations: transifex pull
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-09-19 05:00:21 +00:00
Brad Smith
3f005837dd Rename swap16/swap32 functions which conflict with OpenBSD macros 2025-09-19 01:28:30 +00:00
Rafael Kitover
2b3edb266a translations: transifex pull
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-09-18 14:00:23 +00:00
Rafael Kitover
8e5fc43dd6 translations: transifex pull
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-09-18 13:00:23 +00:00
Rafael Kitover
362ca53cbe translations: transifex pull
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-09-18 02:00:23 +00:00
Rafael Kitover
9dc10ff6c4 translations: rebuild source .pot
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-09-18 02:00:07 +00:00
Rafael Kitover
ab01be3373 Add option to enable SDL pixel art texture filter
Add a checkbox in display config to enable SDL_SCALEMODE_PIXELART when
it is available.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-09-18 01:22:47 +00:00
Rafael Kitover
6ec0ba0610 Apply bilinear option for SDL texture
Set the texture option for bilinear or nearest on the SDL texture
depending on the value of the bilinear checkbox.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-09-18 01:22:47 +00:00
Rafael Kitover
9fcc0ad7a8 build: fix finding static vcpkg x265 for FFmpeg
Fix finding static vcpkg x265 when it is named `x265-static.lib` as it
is right now.

Fix finding vcpkg host pkgconf on ARM64 Windows, which uses x64 host
binaries.

Remove build environment architecture check, which fails building x64 on
ARM64. That whole file needs to be rewritten to use the compiler target
architecture.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-09-13 20:59:08 -07:00
Rafael Kitover
32622efc1e translations: transifex pull
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-09-11 11:00:20 +00:00
Rafael Kitover
1dd5ba4567 translations: transifex pull
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-09-04 08:00:21 +00:00
Rafael Kitover
2070f75934 translations: transifex pull
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-09-03 18:00:30 +00:00
Rafael Kitover
89146a8597 translations: transifex pull
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-09-03 17:00:21 +00:00
Rafael Kitover
043956753b translations: transifex pull
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-08-30 15:00:20 +00:00
Rafael Kitover
e0eb3b3dab translations: transifex pull
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-08-30 08:00:21 +00:00
Rafael Kitover
e3e14232f7 Set gba_darken opt default to 37
Set the GBA darken value default to 37 instead of 50, seems to look
pretty good.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-08-28 04:23:51 +00:00
Squall Leonhart
7565cac230 Update 2xSaI.cpp
The previous interpolation operator could cause the channels to bleed into the next when the LCD Color filter was enabled, on some starts, some settings.
2025-08-25 17:41:04 +10:00
Rafael Kitover
33c5aeb80e Default LCD Filter to enabled for GBA/GB
Set the defaults for GB and GBA LCD Filter to enabled and rewrite the
values in previous versions of the config to enabled as well.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-08-24 02:49:59 +00:00
Rafael Kitover
c5510ba28f ci: update install-nix-action to v31
Update the GitHub CI action install-nix-action to v31 and remove
references to apple_sdk from default.nix, they have been deprecated.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-08-23 22:04:19 +00:00
Rafael Kitover
96c23628ba Set default for gba_darken to 50
Set the default for the color correction option gba_darken to 50, which
is the nicest looking value.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-08-23 16:39:22 +00:00
Rafael Kitover
37fb449fc9 Remove gbafilter_pad/gbcfilter_pad, dead code
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-08-23 16:35:06 +00:00
Rafael Kitover
7519c9b818 translations: transifex pull
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-08-23 01:00:20 +00:00
Rafael Kitover
24b779c09e translations: transifex pull
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-08-23 00:00:20 +00:00
Rafael Kitover
a17df26e52 build: fix Debian installdeps for current Ubuntu
Fix installdeps for Debian variants by checking for `libsdl3-dev` and
falling back to `libsdl2-dev` if not available.

Also add `libx264-dev` and `libx265-dev` to the list of FFmpeg packages
as we now require them.

Fix #1486

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-08-21 22:53:33 +00:00
Rafael Kitover
b2dd03c6cb build: guard cmake_policy() w if(POLICY)
Check if CMake policies being set exist to prevent errors on older CMake
versions.

Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-08-21 20:49:32 +00:00
Andy Vandijck
967426e2f0 Fix color change with previous check 2025-08-21 09:17:54 +02:00
Rafael Kitover
ee2678c13c translations: transifex pull
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-08-20 20:00:20 +00:00
Rafael Kitover
337e465741 translations: transifex pull
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-08-20 19:00:19 +00:00
Andy Vandijck
5007977189 Add capital begin letter 2025-08-20 16:36:27 +02:00
Andy Vandijck
99f97138a2 Add LCD filter parameters and add GBC filter 2025-08-20 16:31:05 +02:00
Andy Vandijck
5b867c1483 Fix color name 2025-08-19 15:27:37 +02:00
Andy Vandijck
fe08f4d326 Remove quoted code 2025-08-19 15:26:12 +02:00
Andy Vandijck
c334e3ffca Fix PS2 colors for libretro 2025-08-19 15:20:49 +02:00
Andy Vandijck
35f8ba0b8f Add libretro PlayStation2 support 2025-08-18 16:12:29 +02:00
Andy Vandijck
fca5fae329 Check file size for GBA ROM and reduce memory footprint 2025-08-17 16:02:26 +02:00
Andy Vandijck
56ea6456f5 Check file size for GBA ROM and reduce memory footprint 2025-08-17 16:01:20 +02:00
Rafael Kitover
0510656ca3 translations: transifex pull
Signed-off-by: Rafael Kitover <rkitover@gmail.com>
2025-08-13 00:00:20 +00:00
Squall-Leonhart
b92fcf7e31 prevent the zip program from being incompletely downloaded
\
2025-08-11 14:41:19 +00:00
Andy Vandijck
22f381a19e Update macOS SDL3 to 3.2.20 2025-08-08 10:01:06 +02:00
Andy Vandijck
e9fc6c8e13 Update macOS SDL3 to 3.2.20 2025-08-08 10:00:04 +02:00
68 changed files with 7236 additions and 6562 deletions

View File

@@ -0,0 +1,57 @@
name: Claude Code Review
on:
pull_request:
types: [opened, synchronize]
# Optional: Only run on specific file changes
# paths:
# - "src/**/*.ts"
# - "src/**/*.tsx"
# - "src/**/*.js"
# - "src/**/*.jsx"
jobs:
claude-review:
# Optional: Filter by PR author
# if: |
# github.event.pull_request.user.login == 'external-contributor' ||
# github.event.pull_request.user.login == 'new-developer' ||
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Run Claude Code Review
id: claude-review
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
prompt: |
REPO: ${{ github.repository }}
PR NUMBER: ${{ github.event.pull_request.number }}
Please review this pull request and provide feedback on:
- Code quality and best practices
- Potential bugs or issues
- Performance considerations
- Security concerns
- Test coverage
Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback.
Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR.
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://docs.claude.com/en/docs/claude-code/sdk#command-line for available options
claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"'

50
.github/workflows/claude.yml vendored Normal file
View File

@@ -0,0 +1,50 @@
name: Claude Code
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]
jobs:
claude:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
actions: read # Required for Claude to read CI results on PRs
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# This is an optional setting that allows Claude to read CI results on PRs
additional_permissions: |
actions: read
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
# prompt: 'Update the pull request description to include a summary of changes.'
# Optional: Add claude_args to customize behavior and configuration
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://docs.claude.com/en/docs/claude-code/sdk#command-line for available options
# claude_args: '--model claude-opus-4-1-20250805 --allowed-tools Bash(gh pr:*)'

View File

@@ -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

View File

@@ -2,9 +2,15 @@ cmake_minimum_required(VERSION 3.19)
cmake_policy(VERSION 3.19...3.28.3)
# Use new link library de-duplication behavior.
cmake_policy(SET CMP0156 NEW)
cmake_policy(SET CMP0179 NEW)
# cmake_policy(SET CMP0181 NEW)
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)

View File

@@ -2,6 +2,8 @@ if(TRANSLATIONS_ONLY)
return()
endif()
# TODO: Use compiler CPU not CMake.
if(NOT CMAKE_SYSTEM_PROCESSOR)
if(NOT CMAKE_TOOLCHAIN_FILE AND CMAKE_HOST_SYSTEM_PROCESSOR)
set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_HOST_SYSTEM_PROCESSOR})
@@ -71,14 +73,6 @@ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "[aA][aA][rR][cC][hH]|[aA][rR][mM]")
endif()
endif()
if(DEFINED VCPKG_TARGET_TRIPLET)
string(REGEX MATCH "^[^-]+" target_arch ${VCPKG_TARGET_TRIPLET})
if(NOT WINARCH STREQUAL target_arch)
message(FATAL_ERROR "Wrong build environment architecture for VCPKG_TARGET_TRIPLET, you specified ${target_arch} but your compiler is for ${WINARCH}")
endif()
endif()
# We do not support amd64 asm yet
if(X86_64 AND (ENABLE_ASM_CORE OR ENABLE_ASM_SCALERS OR ENABLE_MMX))
message(FATAL_ERROR "The options ASM_CORE, ASM_SCALERS and MMX are not supported on X86_64 yet.")

View File

@@ -65,6 +65,10 @@ else()
endif()
endif()
if(APPLE)
list(APPEND VBAM_SDL_LIBS "-framework System")
endif()
if(ENABLE_FFMPEG)
if(NOT FFMPEG_LIBRARIES)
message(FATAL_ERROR "ENABLE_FFMPEG was specified, but required versions of ffmpeg libraries cannot be found!")

View File

@@ -97,6 +97,11 @@ endmacro()
# Check for cached results. If there are skip the costly part.
if (NOT FFMPEG_LIBRARIES)
set(x265_lib "x265")
if(CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg" AND FFMPEG_STATIC)
set(x265_lib "x265-static")
endif()
# Check for all possible component.
find_component(AVFORMAT libavformat avformat libavformat/avformat.h)
@@ -108,7 +113,7 @@ if (NOT FFMPEG_LIBRARIES)
find_component(POSTPROC libpostproc postproc libpostproc/postprocess.h)
find_component(SWRESAMPLE libswresample swresample libswresample/swresample.h)
find_component(X264 x264 x264 x264.h)
find_component(X265 x265 x265 x265.h)
find_component(X265 x265 "${x265_lib}" x265.h)
# Check if the required components were found and add their stuff to the FFMPEG_* vars.
foreach (_component ${FFmpeg_FIND_COMPONENTS})

View File

@@ -22,8 +22,18 @@ elseif(MINGW OR MSYS)
# Default to static builds on MinGW and all MSYS2 envs.
set(VBAM_STATIC_DEFAULT ON)
endif()
option(VBAM_STATIC "Try to link all libraries statically" ${VBAM_STATIC_DEFAULT})
# This is a commonly used CMake option.
if(DEFINED ENABLE_SHARED)
if(NOT ENABLE_SHARED)
set(VBAM_STATIC ON)
else()
set(VBAM_STATIC OFF)
endif()
endif()
if(VBAM_STATIC)
set(SDL2_STATIC ON)
set(SDL3_STATIC ON)
@@ -40,7 +50,7 @@ if(VBAM_STATIC)
endif()
endif()
if(CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg" AND CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "^([xX]86_64|[aA][mM][dD]64)$")
if(CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg")
set(PKG_CONFIG_EXECUTABLE "$ENV{VCPKG_ROOT}/installed/x64-windows/tools/pkgconf/pkgconf.exe")
endif()
@@ -76,6 +86,18 @@ option(ENABLE_LZMA "Enable LZMA archive support" ON)
if(ENABLE_SDL3)
set(CMAKE_C_FLAGS "-DENABLE_SDL3 ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-DENABLE_SDL3 ${CMAKE_CXX_FLAGS}")
include(CheckSourceCompiles)
check_source_compiles(CXX
"#include <SDL3/SDL.h>
int main() { return SDL_SCALEMODE_PIXELART; }
" HAVE_SDL_SCALEMODE_PIXELART)
if(HAVE_SDL_SCALEMODE_PIXELART)
set(CMAKE_C_FLAGS "-DHAVE_SDL3_PIXELART ${CMAKE_C_FLAGS}")
set(CMAKE_CXX_FLAGS "-DHAVE_SDL3_PIXELART ${CMAKE_CXX_FLAGS}")
endif()
endif()
if(DISABLE_OPENGL)

View File

@@ -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 ];
}

View File

@@ -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

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

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

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

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

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

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

File diff suppressed because it is too large Load Diff

View File

@@ -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;
}
}

View File

@@ -351,37 +351,3 @@ void gbafilter_pal32(uint32_t* buf, int count)
*buf++ = final_pix;
}
}
// gbafilter_pad remains unchanged as it's for masking.
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;
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;
}
break;
case 32:
while (count--) {
*((uint32_t*)buf) &= mask.whole;
buf += 4;
}
}
}

View File

@@ -7,7 +7,6 @@ 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_

View File

@@ -350,37 +350,3 @@ void gbcfilter_pal32(uint32_t* buf, int count)
*buf++ = final_pix;
}
}
// gbcfilter_pad remains unchanged as it's for masking.
void gbcfilter_pad(uint8_t* buf, int count)
{
union {
struct
{
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
} part;
unsigned whole;
} mask;
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;
}
break;
case 32:
while (count--) {
*((uint32_t*)buf) &= mask.whole;
buf += 4;
}
}
}

View File

@@ -7,7 +7,6 @@ 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_pad(uint8_t* buf, int count);
void gbcfilter_set_params(int color_mode, float lighten_screen);
#endif // VBAM_COMPONENTS_FILTERS_CGB_FILTERS_CGB_H_

View File

@@ -10,7 +10,7 @@
#endif
#if defined(__FreeBSD__) || defined(__NetBSD__)
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#include <sys/param.h>
#define fopen64 fopen
#define fseeko64 fseeko
@@ -34,7 +34,7 @@
#include "core/base/file_util.h"
#ifdef __GNUC__
#if defined(__MUSL__) || defined(__APPLE__) || defined(BSD) || defined(__NetBSD__)
#if defined(__MUSL__) || defined(__APPLE__) || defined(BSD)
typedef off_t __off64_t; /* off_t is 64 bits on BSD. */
#define fseeko64 fseeko
#define ftello64 ftello

View File

@@ -37,21 +37,21 @@
#else
// swaps a 16-bit value
static inline uint16_t swap16(uint16_t v)
static inline uint16_t vbswap16(uint16_t v)
{
return (v << 8) | (v >> 8);
}
// swaps a 32-bit value
static inline uint32_t swap32(uint32_t v)
static inline uint32_t vbswap32(uint32_t v)
{
return (v << 24) | ((v << 8) & 0xff0000) | ((v >> 8) & 0xff00) | (v >> 24);
}
#define READ16LE(x) swap16(*((uint16_t *)(x)))
#define READ32LE(x) swap32(*((uint32_t *)(x)))
#define WRITE16LE(x, v) *((uint16_t *)x) = swap16((v))
#define WRITE32LE(x, v) *((uint32_t *)x) = swap32((v))
#define READ16LE(x) vbswap16(*((uint16_t *)(x)))
#define READ32LE(x) vbswap32(*((uint32_t *)(x)))
#define WRITE16LE(x, v) *((uint16_t *)x) = vbswap16((v))
#define WRITE32LE(x, v) *((uint32_t *)x) = vbswap32((v))
#endif
#else
#define READ16LE(x) *((uint16_t *)x)

View File

@@ -877,7 +877,7 @@ BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; }
#ifdef USE_HWCAP
#if defined(__FreeBSD__)
#if defined(__FreeBSD__) || defined(__OpenBSD__)
static unsigned long MY_getauxval(int aux)
{
unsigned long val;

View File

@@ -129,7 +129,9 @@ wchar etoupperw(wchar ch)
{
if (ch=='i')
return('I');
#if defined(__APPLE__) || defined(_MSC_VER) || defined(__MINGW32__) || defined(__linux__)
#if defined(__APPLE__) || defined(_MSC_VER) || defined(__MINGW32__) || \
defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
defined(__OpenBSD__)
return(toupper(ch));
#else
return(toupperw(ch));
@@ -234,7 +236,9 @@ bool LowAscii(const wchar *Str)
int wcsicompc(const wchar *Str1,const wchar *Str2)
{
#if defined(_UNIX) || defined(_MSC_VER) || defined(__APPLE__) || defined(__linux__)
#if defined(_UNIX) || defined(_MSC_VER) || defined(__APPLE__) || \
defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
defined(__OpenBSD__)
return my_wcscmp(Str1,Str2);
#elif defined(__MINGW32__)
return _wcsicmp(Str1,Str2);

View File

@@ -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)

View File

@@ -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

View File

@@ -612,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;
@@ -1013,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 };
@@ -1216,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";
@@ -1788,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);
}

View File

@@ -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",

View File

@@ -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)
@@ -164,6 +177,7 @@ if(CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg")
endif()
if(APPLE)
find_library(MAC_SYSTEM System)
find_library(COREAUDIO CoreAudio)
find_library(COREFOUNDATION CoreFoundation)
find_library(AUDIOTOOLBOX AudioToolbox)
@@ -346,6 +360,7 @@ function(configure_wx_target target)
# Metal
if(APPLE)
_add_link_libraries(${MAC_SYSTEM})
_add_link_libraries(${COREFOUNDATION})
_add_link_libraries(${COREAUDIO})
_add_link_libraries(${AUDIOTOOLBOX})
@@ -1018,7 +1033,9 @@ if(APPLE)
# bundle dylibs and relink them for releasing .app
# also install translations into the .app
# but only in Release mode
if(CMAKE_BUILD_TYPE MATCHES "^(Release|MinSizeRel)$")
option(BUNDLE_DYLIBS "Bundle dylibs into .app" OFF)
if(GUNDLE_DYLIBS AND CMAKE_BUILD_TYPE MATCHES "^(Release|MinSizeRel)$")
add_custom_command(
TARGET visualboyadvance-m POST_BUILD
COMMAND bash ${CMAKE_SOURCE_DIR}/tools/macOS/third_party_libs_tool ./visualboyadvance-m.app

View File

@@ -20,6 +20,7 @@
#include <AudioToolbox/AudioToolbox.h>
#include <stdlib.h>
#include <memory.h>
#include <mutex>
#include <wx/arrstr.h>
#include <wx/log.h>
@@ -109,7 +110,8 @@ public:
int soundBufferLen = 0;
AudioTimeStamp starttime;
AudioTimeStamp timestamp;
AudioQueueTimelineRef timeline;
AudioQueueTimelineRef timeline = NULL;
std::mutex buffer_mutex;
private:
AudioDeviceID GetCoreAudioDevice(wxString name);
@@ -145,6 +147,7 @@ static void PlaybackBufferReadyCallback(void *inUserData, AudioQueueRef inAQ, Au
cadevice->buffers[curbuf]->mAudioDataByteSize = 0;
}
std::lock_guard<std::mutex> lock(cadevice->buffer_mutex);
if (cadevice->filled_buffers > 0) {
cadevice->filled_buffers--;
}
@@ -180,84 +183,72 @@ AudioDeviceID CoreAudioAudio::GetCoreAudioDevice(wxString name)
AudioBufferList *buflist = NULL;
OSStatus result = 0;
CFStringRef cfstr = NULL;
if (name == _("Default device")) {
if (AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &default_playback_device_address, 0, NULL, &size) != kAudioHardwareNoError) {
return 0;
} else if ((devs = (AudioDeviceID *)malloc(size)) == NULL) {
return 0;
} else if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &default_playback_device_address, 0, NULL, &size, devs) != kAudioHardwareNoError) {
free(devs);
return 0;
}
dev = devs[0];
free(devs);
return dev;
} else {
if (AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &devlist_address, 0, NULL, &size) != kAudioHardwareNoError) {
return 0;
} else if ((devs = (AudioDeviceID *)malloc(size)) == NULL) {
return 0;
} else if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &devlist_address, 0, NULL, &size, devs) != kAudioHardwareNoError) {
free(devs);
return 0;
}
const UInt32 total_devices = (UInt32) (size / sizeof(AudioDeviceID));
for (UInt32 i = 0; i < total_devices; i++)
{
if (AudioObjectGetPropertyDataSize(devs[i], &addr, 0, NULL, &size) != noErr) {
continue;
} else if ((buflist = (AudioBufferList *)malloc(size)) == NULL) {
continue;
}
result = AudioObjectGetPropertyData(devs[i], &addr, 0, NULL, &size, buflist);
if (result != noErr) {
free(buflist);
continue;
}
if (buflist->mNumberBuffers == 0) {
free(buflist);
continue;
}
size = sizeof(CFStringRef);
if (AudioObjectGetPropertyData(devs[i], &nameaddr, 0, NULL, &size, &cfstr) != kAudioHardwareNoError) {
free(buflist);
continue;
}
CFIndex len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfstr), kCFStringEncodingUTF8);
const char *name = (const char *)malloc(len + 1);
CFStringGetCString(cfstr, (char *)name, len + 1, kCFStringEncodingUTF8);
if (name != NULL)
{
const wxString device_name(name, wxConvLibc);
if (device_name == name) {
dev = devs[i];
free(devs);
free(buflist);
free((void *)name);
return dev;
}
}
free(buflist);
free((void *)name);
}
if (AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &devlist_address, 0, NULL, &size) != kAudioHardwareNoError) {
return 0;
} else if ((devs = (AudioDeviceID *)malloc(size)) == NULL) {
return 0;
} else if (AudioObjectGetPropertyData(kAudioObjectSystemObject, &devlist_address, 0, NULL, &size, devs) != kAudioHardwareNoError) {
free(devs);
return 0;
}
const UInt32 total_devices = (UInt32) (size / sizeof(AudioDeviceID));
for (UInt32 i = 0; i < total_devices; i++)
{
if (AudioObjectGetPropertyDataSize(devs[i], &addr, 0, NULL, &size) != noErr) {
continue;
} else if ((buflist = (AudioBufferList *)malloc(size)) == NULL) {
continue;
}
result = AudioObjectGetPropertyData(devs[i], &addr, 0, NULL, &size, buflist);
if (result != noErr) {
free(buflist);
continue;
}
if (buflist->mNumberBuffers == 0) {
free(buflist);
continue;
}
size = sizeof(CFStringRef);
if (AudioObjectGetPropertyData(devs[i], &nameaddr, 0, NULL, &size, &cfstr) != kAudioHardwareNoError) {
free(buflist);
continue;
}
CFIndex len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfstr), kCFStringEncodingUTF8);
const char *device_name_cstr = (const char *)malloc(len + 1);
CFStringGetCString(cfstr, (char *)device_name_cstr, len + 1, kCFStringEncodingUTF8);
if (device_name_cstr != NULL)
{
const wxString device_name(device_name_cstr, wxConvLibc);
if (device_name == name) {
dev = devs[i];
free(devs);
free(buflist);
free((void *)device_name_cstr);
CFRelease(cfstr);
return dev;
}
}
free(buflist);
free((void *)device_name_cstr);
CFRelease(cfstr);
}
free(devs);
return 0;
}
@@ -269,16 +260,37 @@ initialized(false)
void CoreAudioAudio::deinit() {
if (!initialized)
return;
AudioObjectRemovePropertyListener(device, &alive_address, DeviceAliveNotification, this);
for (int i = 0; i < OPTION(kSoundBuffers); i++) {
AudioQueueFreeBuffer(audioQueue, buffers[i]);
if (device != 0) {
AudioObjectRemovePropertyListener(device, &alive_address, DeviceAliveNotification, this);
}
if (buffers != NULL) {
for (int i = 0; i < OPTION(kSoundBuffers); i++) {
if (buffers[i] != NULL) {
AudioQueueFreeBuffer(audioQueue, buffers[i]);
}
}
free(buffers);
buffers = NULL;
}
AudioQueueStop(audioQueue, TRUE);
if (timeline != NULL) {
AudioQueueDisposeTimeline(audioQueue, timeline);
timeline = NULL;
}
if (audioQueue != NULL) {
AudioQueueDispose(audioQueue, TRUE);
audioQueue = NULL;
}
device = 0;
current_buffer = 0;
filled_buffers = 0;
initialized = false;
}
@@ -293,24 +305,20 @@ static bool AssignDeviceToAudioQueue(CoreAudioAudio *cadevice)
kAudioDevicePropertyScopeOutput,
kAudioObjectPropertyElementMain
};
OSStatus result;
CFStringRef devuid;
UInt32 devuidsize = sizeof(devuid);
result = AudioObjectGetPropertyData(cadevice->device, &prop, 0, NULL, &devuidsize, &devuid);
if (result != noErr) {
return false;
}
result = AudioQueueSetProperty(cadevice->audioQueue, kAudioQueueProperty_CurrentDevice, &devuid, devuidsize);
if (result != noErr) {
return false;
}
CFRelease(devuid); // Release devuid; we're done with it and AudioQueueSetProperty should have retained if it wants to keep it.
return (bool)(result == noErr);
}
@@ -362,12 +370,19 @@ bool CoreAudioAudio::init(long sampleRate) {
AudioChannelLayout layout;
memset(&layout, 0, sizeof(layout));
device = GetCoreAudioDevice(OPTION(kSoundAudioDevice));
if (device == 0) {
fprintf(stderr, "Couldn't get Core Audio device\n");
return false;
const wxString device_name = OPTION(kSoundAudioDevice);
const bool use_default_device = (device_name.IsEmpty() || device_name == _("Default device"));
if (!use_default_device) {
device = GetCoreAudioDevice(device_name);
if (device == 0) {
wxLogError(_("Could not get CoreAudio device"));
return false;
}
} else {
device = 0;
}
description.mFormatID = kAudioFormatLinearPCM;
@@ -382,16 +397,20 @@ bool CoreAudioAudio::init(long sampleRate) {
soundBufferLen = (sampleRate / 60) * description.mBytesPerPacket;
PrepareDevice(this);
if (!use_default_device) {
PrepareDevice(this);
AudioObjectAddPropertyListener(device, &alive_address, DeviceAliveNotification, this);
}
AudioObjectAddPropertyListener(device, &alive_address, DeviceAliveNotification, this);
result = AudioQueueNewOutput(&description, PlaybackBufferReadyCallback, this, NULL, NULL, 0, &audioQueue);
if (result != noErr) {
return false;
}
AssignDeviceToAudioQueue(this);
if (!use_default_device) {
AssignDeviceToAudioQueue(this);
}
layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
result = AudioQueueSetProperty(audioQueue, kAudioQueueProperty_ChannelLayout, &layout, sizeof(layout));
@@ -466,10 +485,17 @@ void CoreAudioAudio::setBuffer(uint16_t* finalWave, int length) {
this_buf = buffers[current_buffer];
if (this_buf == NULL) {
fprintf(stderr, "Current buffer is NULL\n");
return;
}
// Bounds checking: ensure we don't write past buffer capacity
if (this_buf->mAudioDataByteSize + length > this_buf->mAudioDataBytesCapacity) {
length = this_buf->mAudioDataBytesCapacity - this_buf->mAudioDataByteSize;
if (length <= 0) {
return;
}
}
memcpy((uint8_t *)this_buf->mAudioData + this_buf->mAudioDataByteSize, finalWave, length);
this_buf->mAudioDataByteSize += (UInt32)length;
@@ -495,10 +521,11 @@ void CoreAudioAudio::write(uint16_t* finalWave, int length) {
{
setBuffer(finalWave, (avail * (description.mBitsPerChannel / 8)));
finalWave += (avail * (description.mBitsPerChannel / 8));
finalWave += avail;
samples -= avail;
if (buffers[current_buffer]->mAudioDataByteSize >= buffers[current_buffer]->mAudioDataBytesCapacity) {
std::lock_guard<std::mutex> lock(buffer_mutex);
current_buffer++;
filled_buffers++;
}
@@ -507,7 +534,13 @@ void CoreAudioAudio::write(uint16_t* finalWave, int length) {
current_buffer = 0;
}
while (filled_buffers >= OPTION(kSoundBuffers)) {
while (true) {
{
std::lock_guard<std::mutex> lock(buffer_mutex);
if (filled_buffers < OPTION(kSoundBuffers)) {
break;
}
}
wxMilliSleep(((soundGetSampleRate() / 60) * 4) / (soundGetSampleRate() >> 7));
}
}
@@ -515,6 +548,7 @@ void CoreAudioAudio::write(uint16_t* finalWave, int length) {
setBuffer(finalWave, samples * (description.mBitsPerChannel / 8));
if (buffers[current_buffer]->mAudioDataByteSize >= buffers[current_buffer]->mAudioDataBytesCapacity) {
std::lock_guard<std::mutex> lock(buffer_mutex);
current_buffer++;
filled_buffers++;
}
@@ -523,7 +557,13 @@ void CoreAudioAudio::write(uint16_t* finalWave, int length) {
current_buffer = 0;
}
while (filled_buffers >= OPTION(kSoundBuffers)) {
while (true) {
{
std::lock_guard<std::mutex> lock(buffer_mutex);
if (filled_buffers < OPTION(kSoundBuffers)) {
break;
}
}
wxMilliSleep(((soundGetSampleRate() / 60) * 4) / (soundGetSampleRate() >> 7));
}
}
@@ -592,6 +632,7 @@ std::vector<AudioDevice> GetCoreAudioDevices() {
free(buflist);
free((void *)name);
CFRelease(cfstr);
}
return devices;

View File

@@ -6,10 +6,10 @@
namespace audio {
namespace internal {
// Returns the set of OpenAL devices.
// Returns the set of CoreAudio devices.
std::vector<AudioDevice> GetCoreAudioDevices();
// Creates an OpenAL sound driver.
// Creates a CoreAudio sound driver.
std::unique_ptr<SoundDriver> CreateCoreAudioDriver();
} // namespace internal

View File

@@ -151,6 +151,7 @@ std::array<Option, kNbOptions>& Option::All() {
struct OwnedOptions {
/// Display
bool bilinear = true;
bool sdl_pixel_art = false;
Filter filter = Filter::kNone;
wxString filter_plugin = wxEmptyString;
Interframe interframe = Interframe::kNone;
@@ -176,7 +177,7 @@ std::array<Option, kNbOptions>& Option::All() {
/// 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;
@@ -185,14 +186,14 @@ std::array<Option, kNbOptions>& Option::All() {
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 = 0;
uint32_t gba_darken = 37;
/// Core
bool agb_print = false;
@@ -280,6 +281,7 @@ std::array<Option, kNbOptions>& Option::All() {
static std::array<Option, kNbOptions> g_all_opts = {
/// Display
Option(OptionID::kDispBilinear, &g_owned_opts.bilinear),
Option(OptionID::kDispSDLPixelArt, &g_owned_opts.sdl_pixel_art),
Option(OptionID::kDispFilter, &g_owned_opts.filter),
Option(OptionID::kDispFilterPlugin, &g_owned_opts.filter_plugin),
Option(OptionID::kDispIFB, &g_owned_opts.interframe),
@@ -427,6 +429,7 @@ namespace internal {
const std::array<OptionData, kNbOptions + 1> kAllOptionsData = {
/// Display
OptionData{"Display/Bilinear", "Bilinear", _("Use bilinear filter with 3d renderer")},
OptionData{"Display/SDLPixelArt", "SDLPixelArt", _("Use the SDL pixel art filter with an SDL renderer")},
OptionData{"Display/Filter", "", _("Full-screen filter to apply")},
OptionData{"Display/FilterPlugin", "", _("Filter plugin library")},
OptionData{"Display/IFB", "", _("Interframe blending function")},

View File

@@ -8,6 +8,7 @@ namespace config {
enum class OptionID {
/// Display
kDispBilinear = 0,
kDispSDLPixelArt,
kDispFilter,
kDispFilterPlugin,
kDispIFB,

View File

@@ -12,6 +12,7 @@ namespace config {
static constexpr std::array<Option::Type, kNbOptions> kOptionsTypes = {
/// Display
/*kDispBilinear*/ Option::Type::kBool,
/*kDispSDLPixelArt*/ Option::Type::kBool,
/*kDispFilter*/ Option::Type::kFilter,
/*kDispFilterPlugin*/ Option::Type::kString,
/*kDispIFB*/ Option::Type::kInterframe,

View File

@@ -127,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.

View File

@@ -8,6 +8,7 @@
#include <wx/log.h>
#include <wx/object.h>
#include <wx/radiobut.h>
#include <wx/slider.h>
#include <wx/textctrl.h>
#include <wx/valnum.h>
@@ -301,6 +302,14 @@ private:
} // namespace
// Helper function to update slider tooltip with its current value
static void UpdateSliderTooltip(wxSlider* slider, wxCommandEvent& event) {
if (slider) {
slider->SetToolTip(wxString::Format("%d", slider->GetValue()));
}
event.Skip();
}
// static
DisplayConfig* DisplayConfig::NewInstance(wxWindow* parent) {
VBAM_CHECK(parent);
@@ -386,6 +395,14 @@ DisplayConfig::DisplayConfig(wxWindow* parent)
sdlrenderer_selector_ = GetValidatedChild<wxChoice>("SDLRenderer");
sdlrenderer_selector_->SetValidator(SDLDevicesValidator());
#if !defined(ENABLE_SDL3) || !defined(HAVE_SDL3_PIXELART)
GetValidatedChild<wxCheckBox>("SDLPixelArt")->Hide();
#else
GetValidatedChild<wxCheckBox>("SDLPixelArt")
->SetValidator(
widgets::OptionBoolValidator(config::OptionID::kDispSDLPixelArt));
#endif
wxWindow* color_profile_srgb = GetValidatedChild("ColorProfileSRGB");
color_profile_srgb->SetValidator(
ColorCorrectionProfileValidator(config::ColorCorrectionProfile::kSRGB));
@@ -414,9 +431,13 @@ DisplayConfig::DisplayConfig(wxWindow* parent)
wxSlider* gba_darken_slider = GetValidatedChild<wxSlider>("GBADarken");
gba_darken_slider->SetValidator(widgets::OptionUnsignedValidator(config::OptionID::kGBADarken));
gba_darken_slider->SetToolTip(wxString::Format("%d", gba_darken_slider->GetValue()));
gba_darken_slider->Bind(wxEVT_SLIDER, std::bind(UpdateSliderTooltip, gba_darken_slider, std::placeholders::_1));
wxSlider* gbc_lighten_slider = GetValidatedChild<wxSlider>("GBCLighten");
gbc_lighten_slider->SetValidator(widgets::OptionUnsignedValidator(config::OptionID::kGBLighten));
gbc_lighten_slider->SetToolTip(wxString::Format("%d", gbc_lighten_slider->GetValue()));
gbc_lighten_slider->Bind(wxEVT_SLIDER, std::bind(UpdateSliderTooltip, gbc_lighten_slider, std::placeholders::_1));
filter_selector_ = GetValidatedChild<wxChoice>("Filter");
filter_selector_->SetValidator(FilterValidator());

View File

@@ -135,6 +135,14 @@ private:
} // namespace
// Helper function to update slider tooltip with its current value
static void UpdateSliderTooltip(wxSlider* slider, wxCommandEvent& event) {
if (slider) {
slider->SetToolTip(wxString::Format("%d", slider->GetValue()));
}
event.Skip();
}
// static
SoundConfig* SoundConfig::NewInstance(wxWindow* parent) {
VBAM_CHECK(parent);
@@ -145,6 +153,8 @@ SoundConfig::SoundConfig(wxWindow* parent) : BaseDialog(parent, "SoundConfig") {
// Volume slider configuration.
wxSlider* volume_slider = GetValidatedChild<wxSlider>("Volume");
volume_slider->SetValidator(widgets::OptionIntValidator(config::OptionID::kSoundVolume));
volume_slider->SetToolTip(wxString::Format("%d", volume_slider->GetValue()));
volume_slider->Bind(wxEVT_SLIDER, std::bind(UpdateSliderTooltip, volume_slider, std::placeholders::_1));
GetValidatedChild("Volume100")
->Bind(wxEVT_BUTTON, std::bind(&wxSlider::SetValue, volume_slider, 100));
@@ -229,17 +239,26 @@ SoundConfig::SoundConfig(wxWindow* parent) : BaseDialog(parent, "SoundConfig") {
buffers_info_label_ = GetValidatedChild<wxControl>("BuffersInfo");
buffers_slider_ = GetValidatedChild<wxSlider>("Buffers");
buffers_slider_->SetValidator(widgets::OptionIntValidator(config::OptionID::kSoundBuffers));
buffers_slider_->SetToolTip(wxString::Format("%d", buffers_slider_->GetValue()));
buffers_slider_->Bind(wxEVT_SLIDER, std::bind(UpdateSliderTooltip, buffers_slider_, std::placeholders::_1));
buffers_slider_->Bind(wxEVT_SLIDER, &SoundConfig::OnBuffersChanged, this);
// Game Boy configuration.
GetValidatedChild("GBEcho")->SetValidator(
widgets::OptionIntValidator(config::OptionID::kSoundGBEcho));
GetValidatedChild("GBStereo")
->SetValidator(widgets::OptionIntValidator(config::OptionID::kSoundGBStereo));
wxSlider* gb_echo_slider = GetValidatedChild<wxSlider>("GBEcho");
gb_echo_slider->SetValidator(widgets::OptionIntValidator(config::OptionID::kSoundGBEcho));
gb_echo_slider->SetToolTip(wxString::Format("%d", gb_echo_slider->GetValue()));
gb_echo_slider->Bind(wxEVT_SLIDER, std::bind(UpdateSliderTooltip, gb_echo_slider, std::placeholders::_1));
wxSlider* gb_stereo_slider = GetValidatedChild<wxSlider>("GBStereo");
gb_stereo_slider->SetValidator(widgets::OptionIntValidator(config::OptionID::kSoundGBStereo));
gb_stereo_slider->SetToolTip(wxString::Format("%d", gb_stereo_slider->GetValue()));
gb_stereo_slider->Bind(wxEVT_SLIDER, std::bind(UpdateSliderTooltip, gb_stereo_slider, std::placeholders::_1));
// Game Boy Advance configuration.
GetValidatedChild("GBASoundFiltering")
->SetValidator(widgets::OptionIntValidator(config::OptionID::kSoundGBAFiltering));
wxSlider* gba_filtering_slider = GetValidatedChild<wxSlider>("GBASoundFiltering");
gba_filtering_slider->SetValidator(widgets::OptionIntValidator(config::OptionID::kSoundGBAFiltering));
gba_filtering_slider->SetToolTip(wxString::Format("%d", gba_filtering_slider->GetValue()));
gba_filtering_slider->Bind(wxEVT_SLIDER, std::bind(UpdateSliderTooltip, gba_filtering_slider, std::placeholders::_1));
// Audio Device configuration.
audio_device_selector_ = GetValidatedChild<wxChoice>("Device");

View File

@@ -4,6 +4,7 @@
#include <wx/colordlg.h>
#include <wx/ffile.h>
#include <wx/slider.h>
#include "core/gb/gbGlobals.h"
#include "core/gba/gbaGlobals.h"
@@ -16,6 +17,15 @@
#endif
namespace {
// Helper function to update slider tooltip with its current value
static void UpdateSliderTooltip(wxSlider* slider, wxCommandEvent& event) {
if (slider) {
slider->SetToolTip(wxString::Format("%d", slider->GetValue()));
}
event.Skip();
}
void utilReadScreenPixels(uint8_t* dest, int w, int h) {
uint8_t* b = dest;
int sizeX = w;
@@ -1549,6 +1559,11 @@ public:
getradio(, "CharBase3", charbase_, 0xc000);
getradio(, "CharBase4", charbase_, 0x10000);
getslider(, "Palette", palette_);
wxSlider* palette_slider = XRCCTRL(*this, "Palette", wxSlider);
if (palette_slider) {
palette_slider->SetToolTip(wxString::Format("%d", palette_slider->GetValue()));
palette_slider->Bind(wxEVT_SLIDER, std::bind(UpdateSliderTooltip, palette_slider, std::placeholders::_1));
}
getlab(tileno_, "Tile", "1WWW");
getlab(addr_, "Address", "06WWWWWW");
selx_ = sely_ = -1;
@@ -1741,6 +1756,11 @@ public:
getradio(, "CharBase0", charbase, 0);
getradio(, "CharBase1", charbase, 0x800);
getslider(, "Palette", palette);
wxSlider* palette_slider = XRCCTRL(*this, "Palette", wxSlider);
if (palette_slider) {
palette_slider->SetToolTip(wxString::Format("%d", palette_slider->GetValue()));
palette_slider->Bind(wxEVT_SLIDER, std::bind(UpdateSliderTooltip, palette_slider, std::placeholders::_1));
}
getlab(tileno, "Tile", "2WW");
getlab(addr, "Address", "WWWW");
selx = sely = -1;

View File

@@ -3,6 +3,7 @@
#import <Cocoa/Cocoa.h>
#include <wx/rawbmp.h>
#include <wx/log.h>
#include "wx/drawing.h"
#include "wx/config/option-id.h"
@@ -92,7 +93,7 @@ void MetalDrawingPanel::CreateMetalView()
metalView.layer.needsDisplayOnBoundsChange = YES;
((CAMetalLayer *)metalView.layer).device = metalView.device;
_device = metalView.device;
_device = [metalView.device retain];
const AAPLVertex quadVertices[] =
{
@@ -131,7 +132,11 @@ void MetalDrawingPanel::CreateMetalView()
NSError *error = NULL;
_pipelineState = [_device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor
error:&error];
if (!_pipelineState) {
wxLogError(_("Failed to create Metal pipeline state: %s"), [[error localizedDescription] UTF8String]);
return;
}
_commandQueue = [_device newCommandQueue];
if (OPTION(kDispStretch) == false) {
@@ -186,7 +191,7 @@ id<MTLTexture> MetalDrawingPanel::loadTextureUsingData(void *data)
// Indicate that each pixel has a blue, green, red, and alpha channel, where each channel is
// an 8-bit unsigned normalized value (i.e. 0 maps to 0.0 and 255 maps to 1.0)
textureDescriptor.pixelFormat = metalView.colorPixelFormat;
textureDescriptor.usage = MTLTextureUsageRenderTarget;
textureDescriptor.usage = MTLTextureUsageShaderRead;
// Set the pixel dimensions of the texture
textureDescriptor.width = width * scale;
@@ -196,8 +201,7 @@ id<MTLTexture> MetalDrawingPanel::loadTextureUsingData(void *data)
id<MTLTexture> texture = [_device newTextureWithDescriptor:textureDescriptor];
// Calculate the number of bytes per row in the image.
NSUInteger bytesPerRow = 0;
bytesPerRow = std::ceil((width * scale * 4) + 4);
NSUInteger bytesPerRow = std::ceil(width * scale * 4) + 4;
MTLRegion region = {
{ 0, 0, 0 }, // MTLOrigin
@@ -305,6 +309,10 @@ void MetalDrawingPanel::DrawArea()
src_pos += 4;
}
if (_texture != nil) {
[_texture release];
_texture = nil;
}
_texture = loadTextureUsingData(dst);
if (dst != NULL) {
@@ -339,6 +347,10 @@ void MetalDrawingPanel::DrawArea()
src_pos += 2;
}
if (_texture != nil) {
[_texture release];
_texture = nil;
}
_texture = loadTextureUsingData(dst);
if (dst != NULL) {
@@ -364,12 +376,20 @@ void MetalDrawingPanel::DrawArea()
pos += 4;
}
if (_texture != nil) {
[_texture release];
_texture = nil;
}
_texture = loadTextureUsingData(dst);
if (dst != NULL) {
free(dst);
}
} else {
if (_texture != nil) {
[_texture release];
_texture = nil;
}
_texture = loadTextureUsingData(todraw + srcPitch);
}
@@ -382,6 +402,9 @@ void MetalDrawingPanel::DrawArea()
if(renderPassDescriptor != nil)
{
// Cache the drawable to avoid potential race condition
id<CAMetalDrawable> currentDrawable = metalView.currentDrawable;
renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
renderEncoder.label = @"MyRenderEncoder";
@@ -410,8 +433,10 @@ void MetalDrawingPanel::DrawArea()
[renderEncoder endEncoding];
// Schedule a present once the framebuffer is complete using the next drawable
[commandBuffer presentDrawable:metalView.currentDrawable];
// Schedule a present once the framebuffer is complete using the cached drawable
if (currentDrawable) {
[commandBuffer presentDrawable:currentDrawable];
}
}
// Finalize rendering here & push the command buffer to the GPU

View File

@@ -382,8 +382,11 @@ void load_opts(bool first_time_launch) {
OPTION(kGBALinkTimeout) = 500;
}
#endif
// Previous default was true.
OPTION(kGBALCDFilter) = false;
}
case 1: { // up to 2.2.2 included.
// Previous defaults were false.
OPTION(kGBALCDFilter) = true;
OPTION(kGBLCDFilter) = true;
}
}
ini_version++;

View File

@@ -2574,6 +2574,17 @@ SDL_TEXTUREACCESS_STREAMING, (width * scale), (height * scale));
}
#endif
}
// Set bilinear or nearest on the texture.
#ifdef ENABLE_SDL3
#ifdef HAVE_SDL3_PIXELART
SDL_SetTextureScaleMode(texture, OPTION(kDispSDLPixelArt) ? SDL_SCALEMODE_PIXELART : OPTION(kDispBilinear) ? SDL_SCALEMODE_LINEAR : SDL_SCALEMODE_NEAREST);
#else
SDL_SetTextureScaleMode(texture, OPTION(kDispBilinear) ? SDL_SCALEMODE_LINEAR : SDL_SCALEMODE_NEAREST);
#endif
#else
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, OPTION(kDispBilinear) ? "1" : "0");
#endif
did_init = true;
}
@@ -3445,8 +3456,18 @@ void GameArea::UpdateLcdFilter() {
gbafilter_set_params(DCCP, (((float)OPTION(kGBADarken)) / 100));
gbafilter_update_colors(OPTION(kGBALCDFilter));
} else if (loaded == IMAGE_GB) {
gbcfilter_set_params(DCCP, (((float)OPTION(kGBLighten)) / 100));
gbcfilter_update_colors(OPTION(kGBLCDFilter));
if (gbHardware & 4) { // Emulated Hardware is SGB
// Prevent CGB LCD filter from applying
gbcfilter_update_colors(false);
} else if (gbHardware & 8) { // Emulated Hardware is GBA
// Apply GBA LCD filter instead of the GBC LCD Filter
gbafilter_set_params(DCCP, (((float)OPTION(kGBADarken)) / 100));
gbafilter_update_colors(OPTION(kGBLCDFilter));
} else {
// Apply GBC LCD filter for GB/GBC modes
gbcfilter_set_params(DCCP, (((float)OPTION(kGBLighten)) / 100));
gbcfilter_update_colors(OPTION(kGBLCDFilter));
}
} else {
gbafilter_set_params(DCCP, (((float)OPTION(kGBADarken)) / 100));
gbcfilter_set_params(DCCP, (((float)OPTION(kGBLighten)) / 100));

View File

@@ -143,7 +143,7 @@ int wxCheckedListCtrl::GetItemImageFromAdditionalState(int addstate)
wxColour wxCheckedListCtrl::GetBgColourFromAdditionalState(int additionalstate)
{
if ((additionalstate & wxLIST_STATE_ENABLED) && this->IsEnabled())
return *wxWHITE;
return wxNullColour;
#ifdef __WXMSW__
return wxColour(212, 208, 200);

View File

@@ -985,6 +985,7 @@ EVT_MOVE(MainFrame::OnMove)
EVT_MOVE_START(MainFrame::OnMoveStart)
EVT_MOVE_END(MainFrame::OnMoveEnd)
EVT_SIZE(MainFrame::OnSize)
EVT_ICONIZE(MainFrame::OnIconize)
#if defined(__WXMSW__)
@@ -1088,6 +1089,17 @@ void MainFrame::OnSize(wxSizeEvent& event)
OPTION(kGeomFullScreen) = IsFullScreen();
}
void MainFrame::OnIconize(wxIconizeEvent& event)
{
if (!init_complete_) {
return;
}
if (OPTION(kPrefPauseWhenInactive)) {
panel->Pause();
}
}
wxString MainFrame::GetGamePath(wxString path)
{
wxString game_path = path;

View File

@@ -360,6 +360,8 @@ private:
void OnMoveStart(wxMoveEvent& event);
void OnMoveEnd(wxMoveEvent& event);
void OnSize(wxSizeEvent& event);
void OnIconize(wxIconizeEvent& event);
// Load a named wxDialog from the XRC file
wxDialog* LoadXRCDialog(const char* name);

View File

@@ -170,6 +170,13 @@
<flag>wxALL|wxEXPAND</flag>
<border>5</border>
</object>
<object class="sizeritem">
<object class="wxCheckBox" name="SDLPixelArt">
<label>SDL Pixel Art Filter</label>
</object>
<flag>wxALL|wxEXPAND</flag>
<border>5</border>
</object>
<cols>2</cols>
<growablecols>1</growablecols>
</object>

View File

@@ -88,7 +88,7 @@ endif()
if(UNIX OR APPLE)
target_link_libraries(sfml-system PRIVATE pthread)
endif()
if(UNIX AND NOT APPLE)
if(UNIX AND NOT APPLE AND NOT CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
target_link_libraries(sfml-system PRIVATE rt)
elseif(WIN32)
target_link_libraries(sfml-system PRIVATE winmm)

View File

@@ -184,14 +184,15 @@ DISTS=$DISTS'
libgpg-error https://gnupg.org/ftp/gcrypt/libgpg-error/libgpg-error-1.54.tar.bz2 lib/libgpg-error.a
libgcrypt https://gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.11.0.tar.bz2 lib/libgcrypt.a
libsecret https://gitlab.gnome.org/GNOME/libsecret/-/archive/0.21.7/libsecret-0.21.7.tar.bz2 lib/libsecret-1.a
sdl3 https://github.com/libsdl-org/SDL/releases/download/release-3.2.16/SDL3-3.2.16.tar.gz lib/libSDL3.a
faudio https://github.com/FNA-XNA/FAudio/archive/refs/tags/25.04.tar.gz lib/libFAudio.a
sdl3 https://github.com/libsdl-org/SDL/releases/download/release-3.2.20/SDL3-3.2.20.tar.gz lib/libSDL3.a
faudio https://github.com/FNA-XNA/FAudio/archive/refs/tags/25.08.tar.gz lib/libFAudio.a
flac https://ftp.osuosl.org/pub/xiph/releases/flac/flac-1.5.0.tar.xz lib/libFLAC.a
harfbuzz https://github.com/harfbuzz/harfbuzz/releases/download/11.1.0/harfbuzz-11.1.0.tar.xz lib/libharfbuzz.a
shared-mime-info https://gitlab.freedesktop.org/xdg/shared-mime-info/-/archive/2.4/shared-mime-info-2.4.tar.bz2 bin/update-mime-database
libmspack https://github.com/kyz/libmspack/archive/refs/tags/v1.11.tar.gz lib/libmspack.a
giflib https://downloads.sourceforge.net/project/giflib/giflib-5.2.2.tar.gz?ts=gAAAAABof7w9w5Ou1me5kQswguOibl2AQUX8WQHClQT0jKeq1qXFf5ZaT6x9TsfhIDqnNPe5j7rjS1curgDQ2h4lLue7wNlV6g%3D%3D&r=https%3A%2F%2Fsourceforge.net%2Fprojects%2Fgiflib%2Ffiles%2Fgiflib-5.2.2.tar.gz%2Fdownload lib/libgif.a
libwebp https://github.com/webmproject/libwebp/archive/refs/tags/v1.6.0.tar.gz lib/libwebp.a
fmt https://github.com/fmtlib/fmt/releases/download/12.0.0/fmt-12.0.0.zip lib/libfmt.a
wxwidgets https://github.com/wxWidgets/wxWidgets/releases/download/v3.3.1/wxWidgets-3.3.1.tar.bz2 lib/libwx_baseu-3.*.a
libx264 https://code.videolan.org/videolan/x264/-/archive/master/x264-master.tar.bz2 lib/libx264.a
libx265 https://bitbucket.org/multicoreware/x265_git/downloads/x265_4.1.tar.gz lib/libx265.a
@@ -402,6 +403,7 @@ DIST_ARGS="$DIST_ARGS
libx264 --enable-static --enable-pic
libwebp -DCMAKE_EXE_LINKER_FLAGS=\"-lutil\"
libx265 -DHIGH_BIT_DEPTH=ON -DENABLE_ASSEMBLY=OFF -DENABLE_CLI=OFF
fmt -DFMT_TEST=OFF
wxwidgets -DwxUSE_LIBJPEG=sys -DwxUSE_LIBPNG=sys -DwxUSE_LIBTIFF=sys -DwxUSE_LIBWEBP=sys -DwxUSE_REGEX=sys
"

View File

@@ -116,6 +116,18 @@ best_llvm_path=$(
# Fallback to XCode version.
[ -z "$best_llvm_path" ] && best_llvm_path=/usr
if [ -n "$APPLE_SILICON" ] && [ -z "$intel_target" ]; then
case "$best_llvm_path" in
/nix/store/*) # Nix
rt_lib=$(find /nix/store -maxdepth 1 -type d -name '*-compiler-rt-libc-*[0-9]' | while read -r d; do echo $d $(echo $d | sed -E 's/.*-([0-9.]+)$/\1/'); done | sort -V -k 2 | tail -n 1 | awk '{ print $1 }')/lib/libclang_rt.osx.a
;;
esac
fi
if [ -z "$rt_lib" ]; then
rt_lib=$(xcode-select -p)/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/"$(/usr/bin/clang --version | head -1 | awk '{ print $4 }')"/lib/darwin/libclang_rt.osx.a
fi
clang_path=${best_llvm_path%%:*}
xcode_path=$(xcode-select -p)
@@ -132,7 +144,7 @@ export CPPFLAGS="-DICONV_CONST="
export CFLAGS="-F$xcode_path/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks -framework Carbon -framework Foundation -framework CoreServices -framework SystemConfiguration -Wno-unused-command-line-argument -Wno-error=incompatible-function-pointer-types -fpermissive -Wno-error=unguarded-availability"
export CXXFLAGS="-F$xcode_path/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks -framework Carbon -framework Foundation -framework CoreServices -framework SystemConfiguration -Wno-unused-command-line-argument -Wno-error=unguarded-availability"
export OBJCXXFLAGS="-F$xcode_path/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks -framework Carbon -framework Foundation -framework CoreServices -framework SystemConfiguration -Wno-unused-command-line-argument -Wno-error=unguarded-availability"
export LDFLAGS="-L\"\$BUILD_ROOT/root/lib\" -L$xcode_path/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib -F$xcode_path/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks -framework Carbon -framework Foundation -framework CoreServices -framework SystemConfiguration -Wno-unused-command-line-argument -Wl,-no_compact_unwind"
export LDFLAGS="-L\"\$BUILD_ROOT/root/lib\" -L$xcode_path/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib -F$xcode_path/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks -framework Carbon -framework Foundation -framework CoreServices -framework SystemConfiguration -Wno-unused-command-line-argument -Wl,-no_compact_unwind $rt_lib"
export UUID_CFLAGS="-I\"\$BUILD_ROOT/root/stow/libuuid/include\""
export UUID_LIBS="-L\"\$BUILD_ROOT/root/stow/libuuid/lib\" -luuid"