mirror of
https://github.com/visualboyadvance-m/visualboyadvance-m
synced 2025-10-05 23:52:49 +02:00
Compare commits
67 Commits
bd20c79013
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
99cc0a1d39 | ||
|
3eee048326 | ||
|
9551313e19 | ||
|
cf3a48e15c | ||
|
4819adefd1 | ||
|
cb5689b216 | ||
|
6e20fdc2e3 | ||
|
479a7d9097 | ||
|
3a031a01a4 | ||
|
c34be3c738 | ||
|
5a21d94269 | ||
|
f653261f97 | ||
|
4208f5af6e | ||
|
fc34bbbd12 | ||
|
b499c2d58c | ||
|
e8aa4467f1 | ||
|
40c798ef99 | ||
|
63894ad3f7 | ||
|
68e7d98b85 | ||
|
ed1b7ff47c | ||
|
ff7d1234ea | ||
|
e889e895f2 | ||
|
eb7c50017d | ||
|
df66c6ff4a | ||
|
e0e639a02e | ||
|
ede668b712 | ||
|
5bd8904746 | ||
|
46326939eb | ||
|
3f005837dd | ||
|
2b3edb266a | ||
|
8e5fc43dd6 | ||
|
362ca53cbe | ||
|
9dc10ff6c4 | ||
|
ab01be3373 | ||
|
6ec0ba0610 | ||
|
9fcc0ad7a8 | ||
|
32622efc1e | ||
|
1dd5ba4567 | ||
|
2070f75934 | ||
|
89146a8597 | ||
|
043956753b | ||
|
e0eb3b3dab | ||
|
e3e14232f7 | ||
|
7565cac230 | ||
|
33c5aeb80e | ||
|
c5510ba28f | ||
|
96c23628ba | ||
|
37fb449fc9 | ||
|
7519c9b818 | ||
|
24b779c09e | ||
|
a17df26e52 | ||
|
b2dd03c6cb | ||
|
967426e2f0 | ||
|
ee2678c13c | ||
|
337e465741 | ||
|
5007977189 | ||
|
99f97138a2 | ||
|
5b867c1483 | ||
|
fe08f4d326 | ||
|
c334e3ffca | ||
|
35f8ba0b8f | ||
|
fca5fae329 | ||
|
56ea6456f5 | ||
|
0510656ca3 | ||
|
b92fcf7e31 | ||
|
22f381a19e | ||
|
e9fc6c8e13 |
57
.github/workflows/claude-code-review.yml
vendored
Normal file
57
.github/workflows/claude-code-review.yml
vendored
Normal 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
50
.github/workflows/claude.yml
vendored
Normal 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:*)'
|
||||
|
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
|
||||
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -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.")
|
||||
|
@@ -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!")
|
||||
|
@@ -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})
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
468
po/wxvbam/bg.po
468
po/wxvbam/bg.po
File diff suppressed because it is too large
Load Diff
468
po/wxvbam/br.po
468
po/wxvbam/br.po
File diff suppressed because it is too large
Load Diff
468
po/wxvbam/cs.po
468
po/wxvbam/cs.po
File diff suppressed because it is too large
Load Diff
468
po/wxvbam/el.po
468
po/wxvbam/el.po
File diff suppressed because it is too large
Load Diff
550
po/wxvbam/es.po
550
po/wxvbam/es.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
468
po/wxvbam/gl.po
468
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
1385
po/wxvbam/id.po
1385
po/wxvbam/id.po
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
468
po/wxvbam/ja.po
468
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
468
po/wxvbam/nb.po
468
po/wxvbam/nb.po
File diff suppressed because it is too large
Load Diff
468
po/wxvbam/nl.po
468
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
834
po/wxvbam/sv.po
834
po/wxvbam/sv.po
File diff suppressed because it is too large
Load Diff
468
po/wxvbam/tr.po
468
po/wxvbam/tr.po
File diff suppressed because it is too large
Load Diff
436
po/wxvbam/uk.po
436
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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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_
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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_
|
||||
|
@@ -10,7 +10,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__)
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
#include <sys/param.h>
|
||||
#define fopen64 fopen
|
||||
#define fseeko64 fseeko
|
||||
@@ -34,7 +34,7 @@
|
||||
#include "core/base/file_util.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined(__MUSL__) || defined(__APPLE__) || defined(BSD) || defined(__NetBSD__)
|
||||
#if defined(__MUSL__) || defined(__APPLE__) || defined(BSD)
|
||||
typedef off_t __off64_t; /* off_t is 64 bits on BSD. */
|
||||
#define fseeko64 fseeko
|
||||
#define ftello64 ftello
|
||||
|
@@ -37,21 +37,21 @@
|
||||
#else
|
||||
|
||||
// swaps a 16-bit value
|
||||
static inline uint16_t swap16(uint16_t v)
|
||||
static inline uint16_t vbswap16(uint16_t v)
|
||||
{
|
||||
return (v << 8) | (v >> 8);
|
||||
}
|
||||
|
||||
// swaps a 32-bit value
|
||||
static inline uint32_t swap32(uint32_t v)
|
||||
static inline uint32_t vbswap32(uint32_t v)
|
||||
{
|
||||
return (v << 24) | ((v << 8) & 0xff0000) | ((v >> 8) & 0xff00) | (v >> 24);
|
||||
}
|
||||
|
||||
#define READ16LE(x) swap16(*((uint16_t *)(x)))
|
||||
#define READ32LE(x) swap32(*((uint32_t *)(x)))
|
||||
#define WRITE16LE(x, v) *((uint16_t *)x) = swap16((v))
|
||||
#define WRITE32LE(x, v) *((uint32_t *)x) = swap32((v))
|
||||
#define READ16LE(x) vbswap16(*((uint16_t *)(x)))
|
||||
#define READ32LE(x) vbswap32(*((uint32_t *)(x)))
|
||||
#define WRITE16LE(x, v) *((uint16_t *)x) = vbswap16((v))
|
||||
#define WRITE32LE(x, v) *((uint32_t *)x) = vbswap32((v))
|
||||
#endif
|
||||
#else
|
||||
#define READ16LE(x) *((uint16_t *)x)
|
||||
|
@@ -877,7 +877,7 @@ BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; }
|
||||
|
||||
#ifdef USE_HWCAP
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
static unsigned long MY_getauxval(int aux)
|
||||
{
|
||||
unsigned long val;
|
||||
|
@@ -129,7 +129,9 @@ wchar etoupperw(wchar ch)
|
||||
{
|
||||
if (ch=='i')
|
||||
return('I');
|
||||
#if defined(__APPLE__) || defined(_MSC_VER) || defined(__MINGW32__) || defined(__linux__)
|
||||
#if defined(__APPLE__) || defined(_MSC_VER) || defined(__MINGW32__) || \
|
||||
defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
|
||||
defined(__OpenBSD__)
|
||||
return(toupper(ch));
|
||||
#else
|
||||
return(toupperw(ch));
|
||||
@@ -234,7 +236,9 @@ bool LowAscii(const wchar *Str)
|
||||
|
||||
int wcsicompc(const wchar *Str1,const wchar *Str2)
|
||||
{
|
||||
#if defined(_UNIX) || defined(_MSC_VER) || defined(__APPLE__) || defined(__linux__)
|
||||
#if defined(_UNIX) || defined(_MSC_VER) || defined(__APPLE__) || \
|
||||
defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
|
||||
defined(__OpenBSD__)
|
||||
return my_wcscmp(Str1,Str2);
|
||||
#elif defined(__MINGW32__)
|
||||
return _wcsicmp(Str1,Str2);
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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",
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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")},
|
||||
|
@@ -8,6 +8,7 @@ namespace config {
|
||||
enum class OptionID {
|
||||
/// Display
|
||||
kDispBilinear = 0,
|
||||
kDispSDLPixelArt,
|
||||
kDispFilter,
|
||||
kDispFilterPlugin,
|
||||
kDispIFB,
|
||||
|
@@ -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,
|
||||
|
@@ -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.
|
||||
|
@@ -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());
|
||||
|
@@ -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");
|
||||
|
@@ -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;
|
||||
|
@@ -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
|
||||
|
@@ -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++;
|
||||
|
@@ -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));
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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>
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
"
|
||||
|
||||
|
@@ -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"
|
||||
|
Reference in New Issue
Block a user