Compare commits

..

1 Commits

Author SHA1 Message Date
Fabrice de Gans
34e50d2cf6 [Build] Add devkitpro-based libretro targets to CI 2024-05-10 12:19:32 -07:00
244 changed files with 19158 additions and 34944 deletions

View File

@@ -11,7 +11,7 @@ body:
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
Please try the nightly build from: https://nightly.visualboyadvance-m.org and factory resetting the emulator from the Help menu. Please try the nightly build from: https://nightly.vba-m.com and factory resetting the emulator from the Help menu.
On Linux build master from source or use the edge snap. On Linux build master from source or use the edge snap.
And last but not least, search for existing reports via the filters bar on the issues page. And last but not least, search for existing reports via the filters bar on the issues page.
- type: markdown - type: markdown

View File

@@ -1,7 +1,7 @@
blank_issues_enabled: false blank_issues_enabled: false
contact_links: contact_links:
- name: VBA-M Forum - name: VBA-M Forum
url: https://board.visualboyadvance-m.org/ url: https://board.vba-m.com/
about: For general questions and support please join our forum or our about: For general questions and support please join our forum or our
- name: VBA-M IRC Channel - name: VBA-M IRC Channel
url: https://web.libera.chat/#vba-m url: https://web.libera.chat/#vba-m

View File

@@ -14,7 +14,7 @@ body:
- type: markdown - type: markdown
attributes: attributes:
value: | value: |
Please try a nightly build from: https://nightly.visualboyadvance-m.org to see if your idea has already been implemented. Please try a nightly build from: https://nightly.vba-m.com to see if your idea has already been implemented.
On Linux build master from source or use the edge snap. On Linux build master from source or use the edge snap.
And last but not least, search for existing requests via the filters bar on the issues page. And last but not least, search for existing requests via the filters bar on the issues page.
- type: textarea - type: textarea

View File

@@ -1,4 +1,4 @@
name: Libretro Devkitpro name: Libretro Latest devkitppc builds
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:

View File

@@ -1,4 +1,4 @@
name: macOS Latest name: macOS Latest Build
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
@@ -60,4 +60,4 @@ jobs:
- if: matrix.build_options == 'default' - if: matrix.build_options == 'default'
name: Run tests name: Run tests
run: >- run: >-
nix-shell --command 'cd build && ctest -j --output-on-failure' nix-shell --command 'cd build && ctest -j'

View File

@@ -1,4 +1,4 @@
name: MSYS2 name: MSYS2 Build
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:

View File

@@ -1,4 +1,4 @@
name: Ubuntu Latest name: Ubuntu Latest Build
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
@@ -45,9 +45,6 @@ jobs:
run: >- run: >-
bash installdeps; if [ "${{ matrix.build_compiler }}" = clang ]; then sudo apt -y install clang; fi bash installdeps; if [ "${{ matrix.build_compiler }}" = clang ]; then sudo apt -y install clang; fi
- name: Install xvfb
run: sudo apt -y install xvfb
# CMake build # CMake build
- if: matrix.build_options != 'libretro' - if: matrix.build_options != 'libretro'
name: Configure CMake name: Configure CMake
@@ -68,4 +65,4 @@ jobs:
# Run tests # Run tests
- if: matrix.build_options == 'default' - if: matrix.build_options == 'default'
name: Run tests name: Run tests
run: cd build && xvfb-run ctest -j --output-on-failure run: cd build && ctest -j

View File

@@ -1,4 +1,4 @@
name: Visual Studio name: Visual Studio Build
on: [push, pull_request] on: [push, pull_request]
jobs: jobs:
@@ -37,6 +37,54 @@ jobs:
msvc_arch: amd64_arm64 msvc_arch: amd64_arm64
runs-on: windows-latest runs-on: windows-latest
steps: steps:
# TODO: Remove these 2 steps after May 13, 2024.
# See https://github.com/actions/runner-images/issues/9701 for details.
- name: Delete components
run: |
Set-Location "C:\Program Files (x86)\Microsoft Visual Studio\Installer\"
$InstallPath = "C:\Program Files\Microsoft Visual Studio\2022\Enterprise"
$componentsToRemove= @(
"Microsoft.VisualStudio.Component.VC.14.38.17.8.ARM"
"Microsoft.VisualStudio.Component.VC.14.38.17.8.ARM.Spectre"
"Microsoft.VisualStudio.Component.VC.14.38.17.8.ARM64"
"Microsoft.VisualStudio.Component.VC.14.38.17.8.ARM64.Spectre"
"Microsoft.VisualStudio.Component.VC.14.38.17.8.x86.x64"
"Microsoft.VisualStudio.Component.VC.14.38.17.8.x86.x64.Spectre"
"Microsoft.VisualStudio.Component.VC.14.38.17.8.ATL"
"Microsoft.VisualStudio.Component.VC.14.38.17.8.ATL.Spectre"
"Microsoft.VisualStudio.Component.VC.14.38.17.8.ATL.ARM"
"Microsoft.VisualStudio.Component.VC.14.38.17.8.ATL.ARM.Spectre"
"Microsoft.VisualStudio.Component.VC.14.38.17.8.ATL.ARM64"
"Microsoft.VisualStudio.Component.VC.14.38.17.8.ATL.ARM64.Spectre"
"Microsoft.VisualStudio.Component.VC.14.38.17.8.MFC"
"Microsoft.VisualStudio.Component.VC.14.38.17.8.MFC.Spectre"
"Microsoft.VisualStudio.Component.VC.14.38.17.8.MFC.ARM"
"Microsoft.VisualStudio.Component.VC.14.38.17.8.MFC.ARM.Spectre"
"Microsoft.VisualStudio.Component.VC.14.38.17.8.MFC.ARM64"
"Microsoft.VisualStudio.Component.VC.14.38.17.8.MFC.ARM64.Spectre"
)
[string]$workloadArgs = $componentsToRemove | ForEach-Object {" --remove " + $_}
$Arguments = ('/c', "vs_installer.exe", 'modify', '--installPath', "`"$InstallPath`"",$workloadArgs, '--quiet', '--norestart', '--nocache')
# should be run twice
$process = Start-Process -FilePath cmd.exe -ArgumentList $Arguments -Wait -PassThru -WindowStyle Hidden
$process = Start-Process -FilePath cmd.exe -ArgumentList $Arguments -Wait -PassThru -WindowStyle Hidden
- name: Install components
run: |
Set-Location "C:\Program Files (x86)\Microsoft Visual Studio\Installer\"
$InstallPath = "C:\Program Files\Microsoft Visual Studio\2022\Enterprise"
$componentsToAdd= @(
"Microsoft.VisualStudio.Component.VC.14.39.17.9.ARM64"
"Microsoft.VisualStudio.Component.VC.14.39.17.9.ARM64.Spectre"
"Microsoft.VisualStudio.Component.VC.14.39.17.9.x86.x64"
"Microsoft.VisualStudio.Component.VC.14.39.17.9.x86.x64.Spectre"
)
[string]$workloadArgs = $componentsToAdd | ForEach-Object {" --add " + $_}
$Arguments = ('/c', "vs_installer.exe", 'modify', '--installPath', "`"$InstallPath`"",$workloadArgs, '--quiet', '--norestart', '--nocache')
# should be run twice
$process = Start-Process -FilePath cmd.exe -ArgumentList $Arguments -Wait -PassThru -WindowStyle Hidden
$process = Start-Process -FilePath cmd.exe -ArgumentList $Arguments -Wait -PassThru -WindowStyle Hidden
- name: Checkout the code - name: Checkout the code
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
@@ -57,4 +105,4 @@ jobs:
# Run tests # Run tests
- if: matrix.build_options == 'default' && matrix.msvc_arch != 'amd64_arm64' - if: matrix.build_options == 'default' && matrix.msvc_arch != 'amd64_arm64'
name: Run tests name: Run tests
run: cd build && ctest -j --output-on-failure run: cd build && ctest -j

10
.gitmodules vendored
View File

@@ -1,6 +1,4 @@
[submodule "win32-deps"] [submodule "dependencies"]
path = win32-deps path = dependencies
url = https://github.com/visualboyadvance-m/win32-deps.git url = https://github.com/visualboyadvance-m/dependencies.git
[submodule "third_party/googletest"] branch = master
path = third_party/googletest
url = https://github.com/google/googletest.git

View File

@@ -4,68 +4,6 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [2.1.11] - 2024-09-15
==========================
* 3eea90af - build: set BUILD_TESTING=OFF when not git checkout [rkitover]
* b3952d74 - build: fix ENABLE_LIRC=ON [rkitover]
* f264e7f8 - Fix Help -> Translations URL [rkitover]
* 61f427de - Write shortcuts in the proper section (#1335) [Steelskin]
* d619ee2b - build: fix installing GoogleTest [rkitover]
* 26207038 - Update WinSparkle to 0.8.1 and add ARM64 [rkitover]
## [2.1.10] - 2024-09-08
==========================
* 7f06428d - Disable dialog position save/restore on wxGTK (#1331) [Steelskin]
* e4ef4aa6 - Propagate key events (#1323) [Steelskin]
* e2cf6ecb - Add option to mute sound during speedup [rkitover]
* d516683a - build: fix for wx using GTK2 [rkitover]
* 834c7de8 - build: update macOS builder dists [rkitover]
* fc82e062 - build: do not build SDL bin on Windows or macOS [rkitover]
* d543784a - [UserInput] Filter key events globally [steelskin]
* 902c6c8e - [UserInput] Only process shortcut commands once [steelskin]
* b7765092 - [bindings] Set default shortcut for recent file 3 [steelskin]
* cc65ef28 - doc: add system requirements to README.md [danialhorton]
* 32627f6b - [Dialogs] Save and restore dialog positions [steelskin]
* 41952d06 - build: update macOS linker tool to 1.5 [rkitover]
* 0c39a5ba - build: override FindGettext to not update po files [rkitover]
* 1b77d659 - build: update macOS build to ffmpeg 7.0 [rkitover]
* 8d08223d - build: fix compatibility with older ffmpeg [rkitover]
* af6028a9 - build: fix build for nix on macOS [rkitover]
* b52edf52 - build: fix building on macOS with Homebrew [rkitover]
* 6766b9ca - build: fix ffmpeg 7.x compat [rkitover]
* 795f25bb - build: fix nix deps for OpenGL [rkitover]
* 647be137 - gba: set cpsr=spsr when switching to FIQ mode [40356555+Aikku93]
* 8abe3e79 - build: remove -lgcc from static link flags [rkitover]
* f4835674 - [Audio] Rework audio devices enumeration [steelskin]
* 775a571f - build: fix detecting Visual Studio default vcpkg [rkitover]
* 64abd3e8 - [Audio] Remove manual memory allocations [steelskin]
* 047ad277 - [Dialogs] Prevent viewers from causing a crash [steelskin]
* 045c98d8 - build: only use -Werror=lto-type-mismatch on gcc [rkitover]
* 3518dc6a - build: fix LTO on Linux [rkitover]
* cc9a03ce - Add toggle: SDL GameController mode for joysticks [rkitover]
* 8576733c - [Build] Remove lingering references to OpenAl [steelskin]
* 05561922 - build: fix MSYS2 check [rkitover]
* d9432ebb - build: fix build on MINGW{64,32}/UCRT64 on MSYS2 [rkitover]
* f57cad67 - build: fix static linking on MSYS2 CLANG64 [rkitover]
* 23e15734 - build: set wxWidgets_DIR with vcpkg [rkitover]
* 98b51910 - [Build] Remove ENABLE_NLS, fix TRANSLATIONS_ONLY [steelskin]
* a565cea8 - [Build] Remove the OpenGL check [steelskin]
* f96e42fe - build: cmake refactor and improvements [Steelskin]
* 07e49025 - Fix most remaining release warnings (#1243) [Steelskin]
* 18b97b43 - Fix various build warnings (#1242) [Steelskin]
* 13a16eb7 - Fix various warnings in filters and headers (#1241) [Steelskin]
* f46da1c5 - build: remove our version of FindSDL2.cmake [rkitover]
* 404e9a1a - build: add clang to ./installdeps for MSYS2 [rkitover]
* 613bd403 - Make menu more reasonably organized (#1230) [wwrustc]
* 215e3c5a - build: use find_program() to find powershell [rkitover]
* e5aa685f - build: don't use wx utils as UNIX cmds on Windows [rkitover]
* 9e4c8e17 - build: fix gentoo dependency namespaces [68k]
* 5f853b99 - Update metainfo.xml to new standards [jhonny.oliveira]
* e7d135db - Update links to new domain visualboyadvance-m.org [rkitover]
* 60fc096f - build: add libglu-devel for solus in installdeps [rkitover]
## [2.1.9] - 2024-02-03 ## [2.1.9] - 2024-02-03
======================= =======================
* 84b0a3e3 - Remove SDL sound driver [rkitover] * 84b0a3e3 - Remove SDL sound driver [rkitover]

View File

@@ -5,13 +5,6 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
if(WIN32) if(WIN32)
include(RemoveStrawberryPerlFromPATH) include(RemoveStrawberryPerlFromPATH)
find_program(POWERSHELL
NAMES powershell.exe pwsh.exe
HINTS "/Windows/System32/WindowsPowerShell/v1.0"
REQUIRED)
else()
find_program(POWERSHELL pwsh)
endif() endif()
if(UPDATE_APPCAST) if(UPDATE_APPCAST)
@@ -25,10 +18,20 @@ endif()
set(VCPKG_DEPS pkgconf zlib pthreads "sdl2[samplerate]" gettext wxwidgets) set(VCPKG_DEPS pkgconf zlib pthreads "sdl2[samplerate]" gettext wxwidgets)
set(VCPKG_DEPS_OPTIONAL set(VCPKG_DEPS_OPTIONAL
sfml ENABLE_LINK
ffmpeg ENABLE_FFMPEG ffmpeg ENABLE_FFMPEG
faudio ENABLE_FAUDIO faudio ENABLE_FAUDIO
) )
if(WIN32)
find_program(POWERSHELL
NAMES powershell.exe pwsh.exe
HINTS "/Windows/System32/WindowsPowerShell/v1.0"
REQUIRED)
else()
find_program(POWERSHELL pwsh)
endif()
include(Set-Toolchain-vcpkg) include(Set-Toolchain-vcpkg)
# Use ccache if available and not already enabled on the command line. # Use ccache if available and not already enabled on the command line.
@@ -51,7 +54,7 @@ if(GIT_FOUND AND WIN32)
# Win32 deps submodule # Win32 deps submodule
set(SUBMODULE_MANUAL_UPDATE FALSE) set(SUBMODULE_MANUAL_UPDATE FALSE)
if(EXISTS "${CMAKE_SOURCE_DIR}/.git" AND NOT EXISTS "${CMAKE_SOURCE_DIR}/win32-deps/mingw-xaudio/include") if(EXISTS "${CMAKE_SOURCE_DIR}/.git" AND NOT EXISTS "${CMAKE_SOURCE_DIR}/dependencies/mingw-xaudio/include")
set(SUBMODULE_MANUAL_UPDATE TRUE) set(SUBMODULE_MANUAL_UPDATE TRUE)
execute_process( execute_process(
COMMAND "${GIT_EXECUTABLE}" submodule update --init --remote --recursive COMMAND "${GIT_EXECUTABLE}" submodule update --init --remote --recursive
@@ -60,7 +63,7 @@ if(GIT_FOUND AND WIN32)
) )
endif() endif()
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/win32-deps/mingw-xaudio/include") if(NOT EXISTS "${CMAKE_SOURCE_DIR}/dependencies/mingw-xaudio/include")
if(NOT (SUBMODULE_MANUAL_UPDATE AND SUBMODULE_UPDATE_STATUS EQUAL 0)) if(NOT (SUBMODULE_MANUAL_UPDATE AND SUBMODULE_UPDATE_STATUS EQUAL 0))
message(FATAL_ERROR "Please pull in git submodules, e.g.\nrun: git submodule update --init --remote --recursive") message(FATAL_ERROR "Please pull in git submodules, e.g.\nrun: git submodule update --init --remote --recursive")
endif() endif()
@@ -82,29 +85,16 @@ include(Options)
include(Toolchain) include(Toolchain)
include(Dependencies) include(Dependencies)
# Disable tests when not in a git checkout.
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/.git")
set(BUILD_TESTING OFF)
endif()
# Configure gtest # Configure gtest
if(BUILD_TESTING) if(BUILD_TESTING)
FetchContent_Declare(googletest
URL https://github.com/google/googletest/archive/2d16ed055d09c3689d44b272adc097393de948a0.zip
)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
set(INSTALL_GTEST OFF CACHE BOOL "" FORCE) FetchContent_MakeAvailable(googletest)
if(NOT EXISTS third_party/googletest/CMakeLists.txt) include(GoogleTest)
execute_process(
COMMAND git submodule update --init --recursive -- third_party/googletest
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
endif()
if(EXISTS third_party/googletest/CMakeLists.txt)
add_subdirectory(./third_party/googletest)
include(GoogleTest)
else()
set(BUILD_TESTING OFF)
endif()
endif() endif()
if(NOT CMAKE_PREFIX_PATH AND (NOT ("$ENV{CMAKE_PREFIX_PATH}" STREQUAL ""))) if(NOT CMAKE_PREFIX_PATH AND (NOT ("$ENV{CMAKE_PREFIX_PATH}" STREQUAL "")))
@@ -117,6 +107,11 @@ elseif(NOT CMAKE_BUILD_TYPE MATCHES "^(Release|Debug|RelWithDebInfo|MinSizeRel)$
message(FATAL_ERROR "Invalid CMAKE_BUILD_TYPE: '${CMAKE_BUILD_TYPE}', must be one of: 'Release', 'Debug', 'RelWithDebInfo' or 'MinSizeRel'") message(FATAL_ERROR "Invalid CMAKE_BUILD_TYPE: '${CMAKE_BUILD_TYPE}', must be one of: 'Release', 'Debug', 'RelWithDebInfo' or 'MinSizeRel'")
endif() endif()
# Link debug libs for RelWithDebInfo
if(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
set(CMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBINFO "Debug")
endif()
set(MSYS OFF) set(MSYS OFF)
if(NOT "$ENV{MSYSTEM_PREFIX}" STREQUAL "") if(NOT "$ENV{MSYSTEM_PREFIX}" STREQUAL "")
set(MSYS ON) set(MSYS ON)
@@ -182,18 +177,8 @@ endif()
set(LOCALEDIR ${CMAKE_INSTALL_PREFIX}/share/locale) set(LOCALEDIR ${CMAKE_INSTALL_PREFIX}/share/locale)
if(NOT TRANSLATIONS_ONLY) if(NOT TRANSLATIONS_ONLY)
include_directories(third_party/include/nonstd) add_subdirectory(third_party/include/nonstd)
include_directories(third_party/include/ghc)
add_subdirectory(third_party/include/stb) add_subdirectory(third_party/include/stb)
if(ENABLE_LINK)
include_directories(third_party/sfml/include)
add_subdirectory(third_party/sfml/src/SFML/System EXCLUDE_FROM_ALL)
add_subdirectory(third_party/sfml/src/SFML/Network EXCLUDE_FROM_ALL)
set(SFML_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/third_party/sfml/include)
set(SFML_LIBRARIES sfml-system sfml-network)
endif()
add_subdirectory(src/core) add_subdirectory(src/core)
add_subdirectory(src/components) add_subdirectory(src/components)
add_subdirectory(src/sdl) add_subdirectory(src/sdl)
@@ -207,5 +192,5 @@ set(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_PACKAGE_VERSION_MAJOR "2") set(CPACK_PACKAGE_VERSION_MAJOR "2")
set(CPACK_PACKAGE_VERSION_MINOR "0") set(CPACK_PACKAGE_VERSION_MINOR "0")
set(CPACK_PACKAGE_VERSION_PATCH "0-Git-${COMMITHASH}") set(CPACK_PACKAGE_VERSION_PATCH "0-Git-${COMMITHASH}")
list(APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/win32-deps") list(APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/dependencies")
include(CPack) include(CPack)

View File

@@ -9,15 +9,17 @@
- [Commit Message](#commit-message) - [Commit Message](#commit-message)
- [Collaboration on a Branch](#collaboration-on-a-branch) - [Collaboration on a Branch](#collaboration-on-a-branch)
- [Commits from Maintainers](#commits-from-maintainers) - [Commits from Maintainers](#commits-from-maintainers)
- [Miscellaneous](#miscellaneous) - [Strings, Character Sets and Translations](#strings-character-sets-and-translations)
- [Debug Messages](#debug-messages) - [Pulling Updated Translations](#pulling-updated-translations)
- [Translations Message Catalog](#translations-message-catalog)
- [Interaction with non-wxWidgets Code](#interaction-with-non-wxwidgets-code)
- [Windows Native Development Environment Setup](#windows-native-development-environment-setup)
- [Release Process](#release-process) - [Release Process](#release-process)
- [Certificates](#certificates) - [Environment](#environment)
- [Release Commit and Tag](#release-commit-and-tag) - [Release Commit and Tag](#release-commit-and-tag)
- [64-bit Windows Binary](#64-bit-windows-binary) - [64-bit Windows Binary](#64-bit-windows-binary)
- [32-bit Windows Binary](#32-bit-windows-binary) - [32-bit Windows Binary](#32-bit-windows-binary)
- [ARM64 Windows Binary](#arm64-windows-binary) - [64-bit Mac Binary](#64-bit-mac-binary)
- [macOS Binary](#macos-binary)
- [Final steps](#final-steps) - [Final steps](#final-steps)
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
@@ -51,12 +53,11 @@ Follow the following steps to process newly submitted issues:
- An issue is resolved by closing it in github. A commit that fixes the issue - An issue is resolved by closing it in github. A commit that fixes the issue
should have the following line near the end of the body of the commit message: should have the following line near the end of the body of the commit message:
``` ```
Fix #999. - Fix #999.
``` ```
This will automatically close the issue and assign the closing commit in the This will automatically close the issue and assign the closing commit in the
github metadata when it is merged to master. The issue can be reopened if github metadata when it is merged to master. The issue can be reopened if
needed. needed.
- A commit that is work towards resolving an issue, should have the issue number - A commit that is work towards resolving an issue, should have the issue number
preceded by a pound sign either at the end of a commit message title, if it is preceded by a pound sign either at the end of a commit message title, if it is
of primary relevance to the issue, or the body otherwise. of primary relevance to the issue, or the body otherwise.
@@ -69,7 +70,7 @@ Follow these guidelines always:
https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
, the description of your work should be in the **commit message NOT the pull the description of your work should be in the **commit message NOT the pull
request description**. request description**.
The title line must be no more than 50 characters and the description must be The title line must be no more than 50 characters and the description must be
@@ -94,21 +95,16 @@ other projects, fewer is better.
The commit title line should be prefixed with an area, unless it involves the The commit title line should be prefixed with an area, unless it involves the
wxWidgets GUI app, in which case it should **NOT** have a prefix. wxWidgets GUI app, in which case it should **NOT** have a prefix.
If the commit is a user-facing functionality change or enhancement, the title
line of the commit must be a non-technical description of this change. For
example "Mute on speedup" because this will go into the changelog.
The text after the area prefix should not be capitalized. The text after the area prefix should not be capitalized.
Please use one of these area prefixes for non-main-GUI-app commits: Please use one of these area prefixes otherwise:
- doc: documentation, README.md etc. - doc: documentation, README.md etc.
- build: cmake, installdeps, preprocessor compatibility defines, compatibility - build: cmake, installdeps, preprocessor compatibility defines, etc.
headers, etc. - gb-core: the GameBoy emulator core
- gb: the GameBoy emulator core - gba-core: the GameBoy Advance emulator core
- gba: the GameBoy Advance emulator core
- libretro: the libretro core glue and build - libretro: the libretro core glue and build
- sdl: anything for the SDL port - sdl-app: anything for the SDL app
- translations: anything related to translations - translations: anything related to translations
. Add other areas here if needed. . Add other areas here if needed.
@@ -142,79 +138,137 @@ things in mind:
better to edit the history than to add more commits. Never add commits fixing better to edit the history than to add more commits. Never add commits fixing
previous commits, only improving or adding to them. previous commits, only improving or adding to them.
- To update when someone else updated the branch with a `push -f` - To update when someone else (very rudely you might say) did a `push -f`, `pull
--rebase` will **USUALLY** work. Verify the log, and if necessary do this
instead:
```bash ```bash
git status # should be clean, with your work having been already pushed git status # should be clean, with your work having been already pushed
git fetch --all --prune git fetch --all --prune
git reset --hard origin/<branch-name> git reset --hard origin/<branch-name>
``` ```
.
- While actively working on a branch, keep it rebased on top of master. While actively working on a branch, keep it rebased on top of master.
#### Commits from Maintainers #### Commits from Maintainers
Maintainers and project members have the power to commit directly to master. Maintainers have the power to commit directly to master. This power must be
This power must be used responsibly. used responsibly, something I fail to do myself often, and will try to improve
upon.
Make your best attempt to follow these general guidelines to keep our Make your most earnest attempt to follow these general guidelines to keep our
history clean: history clean:
- Things that are a minor fix or improvement that does not require discussion - Things that are a straight fix or improvement that does not require discussion
can be committed directly, keeping the following guidelines in mind. can be committed directly, keeping the following guidelines in mind.
- Bigger new features, code refactors and changes in architecture should go - Bigger new features, code refactors and changes in architecture should go
through the PR process. through the PR process.
- Push code changes to a branch first, so they can run through the CI. When you - Push code changes to a branch first, so they can run through the CI.
open the commit in GitHub there is a little icon in the upper left corner that Differences in what different compilers allow is a problem that comes up
shows the CI status for this commit. Differences in what different compilers **VERY** frequently. As well as incompatibilities between different
allow is a problem that comes up **VERY** frequently. As well as configurations for both the C++ code and any supporting code.
incompatibilities between different configurations for both the C++ code and
any supporting code.
### Miscellaneous
#### Debug Messages ### Strings, Character Sets and Translations
We have an override for `wxLogDebug()` to make it work even in non-debug builds #### Pulling Updated Translations
of wx and on windows, even in mintty.
It works like `printf()`, e.g.: Once in a while it is necessary to pull new and updated translations from
transifex.
```cpp For this you need the transifex client, available for Windows as well from
int foo = 42; chocolatey as `transifex-client`.
wxLogDebug(wxT("the value of foo = %d"), foo);
To pull translations run:
```bash
tx pull -af
``` ```
From the core etc. the usual: then check `git status` and if any message catalogs were updated, commit the
result as:
```bash
git commit -a --signoff -S -m'Transifex pull.'
git push
```
#### Translations Message Catalog
Strings that need to be translated by our wonderful translators on transifex
(thank you guys very much) need to be enclosed in `_("...")`, for example:
```cpp ```cpp
fprintf(stderr, "...", ...); wxLogError(_("error: something very wrong"));
``` ```
, will work fine.
You need a debug build for this to work or to even have a console on Windows. The next time you run cmake after adding a string to be translated, the `.pot`
Pass `-DCMAKE_BUILD_TYPE=Debug` to cmake. message catalog source will be regenerated, and you will see a loud message
telling you to push to transifex.
Strings in the XRC XML GUI definition files are automatically added to the
message catalog as well.
If you are working on a branch or a PR, don't push to transifex until it has
been merged to master.
Once it is, push it with:
```bash
tx push -s
```
#### Interaction with non-wxWidgets Code
Use our `UTF8(...)` function to force any `wxString` to UTF-8 for use by other
libraries, screen output or OS APIs. For example:
```cpp
fprintf(STDERR, "Error: %s\n", UTF8(err_msg));
```
There is one exception to this, when using `wxString::Printf()` and such, you
can't pass another `wxString` to the `%s` format directly, use something like
this:
```cpp
wxString err;
err.Printf("Cannot read file: %s", fname.wc_str());
```
this uses the `wchar_t` UTF-16 representation on Windows and does nothing
elsewhere.
For calling Windows APIs with strings, use the wide char `W` variants and the
`wc_str()` method as well.
### Windows Native Development Environment Setup
This guide has been moved to:
https://github.com/rkitover/windows-dev-guide
### Release Process ### Release Process
#### GnuPG Key #### Environment
You will need to create a GnuPG key for signing your commits and release tags, The variable `VBAM_NO_PAUSE`, if set, will cause cmake to not pause before gpg
and upload it to a keyserver. signing operations, you want to set this if you've disabled your gpg passphrase
to not require interaction during release builds.
Make sure to install GnuPG on all environments where you will be making commits gpg set up with your key is helpful for the release process on all environments
and tags. where a binary is built, but you can also make the detached signature files
yourself at the end of the process.
#### Certificates For codesigning windows binaries, put your certificate into
`~/.codesign/windows_comodo.pkcs12`.
Make sure you have set up a Windows code signing certificate with the right On Mac the 'Developer ID Application' certificate stored in your login keychain
password and a Mac 'Developer ID Application' certificate. is used, `keychain unlock` will prompt you for your login keychain password, to
avoid that set the `LOGIN_KEYCHAIN_PASSWORD` environment variable to your
Put the Windows certificate into `~/.codesign/windows_comodo.pkcs12` as a PKCS12 password.
file that is password protected, and put the password for it into
`~/.codesign/windows_comodo.pkcs12.password`.
#### Release Commit and Tag #### Release Commit and Tag
@@ -226,10 +280,8 @@ tag:
mkdir build && cd build mkdir build && cd build
cmake .. -DTAG_RELEASE=TRUE cmake .. -DTAG_RELEASE=TRUE
``` ```
, follow the instructions to edit the `CHANGELOG.md` and then push the release:
To reiterate, **make sure you edit the `CHANGELOG.md`** to remove any then push the release:
non-user-facing changes before you make the release commit.
```bash ```bash
git push git push
@@ -244,126 +296,84 @@ cmake .. -DTAG_RELEASE=UNDO
#### 64-bit Windows Binary #### 64-bit Windows Binary
For this you will preferably need the PowerShell environment setup described For this you will preferably need the powershell environment setup described
[here](https://github.com/rkitover/windows-dev-guide), or by starting the `x64 earlier, however you can use a regular Visual Studio 64 bit native developer
Native Tools Command Prompt` from your Start Menu. command prompt as well.
```powershell ```powershell
mkdir build-msvc64 mkdir build
cd build-msvc64 cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DUPSTREAM_RELEASE=TRUE -G Ninja cmake .. -DVCPKG_TARGET_TRIPLET=x64-windows-static -DCMAKE_BUILD_TYPE=Release -DUPSTREAM_RELEASE=TRUE -G Ninja
ninja ninja
``` ```
Collect the following files for the release: Collect the following files for the release:
- `visualboyadvance-m-Win-x86_64.zip` - `visualboyadvance-m-Win-64bit.zip`
- `visualboyadvance-m-Win-64bit.zip.asc`
- `translations.zip` - `translations.zip`
- `translations.zip.asc`
Repeat the process for the debug build, with `-DCMAKE_BUILD_TYPE=Debug` and
collect this file:
- `visualboyadvance-m-Win-x86_64-debug.zip`
.
#### 32-bit Windows Binary #### 32-bit Windows Binary
The 32-bit build is a legacy build for Windows XP compatibility. You will need For this the optimal environment is a linux distribution with the mingw
the MinGW toolchain to build it. The easiest method is to use the MINGW32 MSYS2 toolchain, I use fedora.
environment.
Make sure the Visual Studio `signtool.exe` is in your path, you can start MSYS2 You can set up a shell on a fedora distribution with docker as described here:
with an inherited `PATH` from a Visual Studio enabled environment or add it to
your shell configuration.
First install dependencies with: https://gist.github.com/rkitover/6379764c619c10e829e4b2fa0ae243fd
If using fedora, the cross script will install all necessary dependencies, if
not install the base toolchain (mingw gcc, binutils, winpthreads) using the
preferred method for your distribution, you can also use mxe for this.
https://mxe.cc/
```bash ```bash
./installdeps sh tools/win/linux-cross-builder -32
``` ```
. Then build the 32-bit binary as follows:
You can also use msys2 on Windows, this is not recommended:
```bash ```bash
mkdir build-mingw32 sh tools/win/msys2-builder -32
cd build-mingw32
cmake .. -DCMAKE_BUILD_TYPE=Release -DUPSTREAM_RELEASE=TRUE -G Ninja
ninja
``` ```
. Collect this file for the release:
- `visualboyadvance-m-Win-x86_32.zip` To set up msys2, see this guide:
. Then repeat the process for the debug build with `-DCMAKE_BUILD_TYPE=Debug`, https://gist.github.com/rkitover/d008324309044fc0cc742bdb16064454
and collect this file:
- `visualboyadvance-m-Win-x86_32-debug.zip` Collect the following files from `~/vbam-build-mingw32/project` if using linux,
. or `~/vbam-build-msys2-x86_64/project` if using msys2:
#### ARM64 Windows Binary - `visualboyadvance-m-Win-32bit.zip`
- `visualboyadvance-m-Win-32bit.zip.asc`
You will need the MSVC ARM64 cross toolchain to build this binary, if you used #### 64-bit Mac Binary
the install script from [here](https://github.com/rkitover/windows-dev-guide)
you will have it installed, otherwise run Visual Studio Installer and install
the component.
To enter the ARM64 cross environment, edit the PowerShell profile described
[here](https://github.com/rkitover/windows-dev-guide) or use the `vcvarsall.bat`
script with the `amd64_arm64` argument as described
[here](https://learn.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=msvc-170).
From there the process is the same as for the 64-bit build, collect the
following files for the release:
- `visualboyadvance-m-Win-arm64.zip`
- 'visualboyadvance-m-Win-arm64-debug.zip'
.
#### macOS Binary
Install the latest Xcode for your OS. Install the latest Xcode for your OS.
You will need bash from Homebrew/nix/MacPorts/whatever to run the build script. You will need bash and (optionally) gpg from homebrew (which you will also need
to install):
```bash
brew install bash gnupg
```
You will need a codesigning certificate from Apple, which you will be able to You will need a codesigning certificate from Apple, which you will be able to
generate once you join their developer program from XCode. This is the generate once you join their developer program. This is the certificate of the
certificate of the type 'Developer ID Application' stored in your login type 'Developer ID Application' stored in your login keychain. `keychain
keychain. unlock` will prompt you for your login keychain password, to avoid that set the
`LOGIN_KEYCHAIN_PASSWORD` environment variable to your password.
If you are not using a GUI session, you will need to use a method to unlock your
login keychain before building so that your codesigning certificate can be used.
Adding the certificate and key to the System keychain is also a method that some
people use.
To unlock your keychain on login, you can add something like this to your
`~/.zshrc`:
```bash ```bash
security unlock-keychain -p "$(cat ~/.login-keychain-password)" login.keychain /usr/local/bin/bash tools/osx/builder -64
``` ```
, with your login password in that file.
For notarization to work, you will need to create an app-specific password on
https://appleid.apple.com , get your Team ID from your Apple Developer account,
and store them with this command:
```bash
xcrun notarytool store-credentials AC_PASSWORD \
--apple-id you@domain.com \
--team-id <DeveloperTeamID> \
--password <secret_app_specific_2FA_password>
```
. Once all of this is set up, run:
```bash
tools/osx/builder
```
, this will take a while because it builds all of the dependencies.
Collect the following files from `~/vbam-build-mac-64bit/project`: Collect the following files from `~/vbam-build-mac-64bit/project`:
- `visualboyadvance-m-Mac-x86_64.zip` - `visualboyadvance-m-Mac-64bit.zip`
- `visualboyadvance-m-Mac-x86_64-debug.zip` - `visualboyadvance-m-Mac-64bit.zip.asc`
.
#### Final steps #### Final steps
@@ -371,26 +381,27 @@ Go to the github releases tab, and make a release for the tag you pushed
earlier. earlier.
Put any notes to users and distro maintainers into the description as well as Put any notes to users and distro maintainers into the description as well as
the generated entries from `CHANGELOG.md` you edited earlier. the entries from `CHANGELOG.md` generated earlier from git by the release
commit script.
Upload all files collected during the earlier builds, the complete list is: Upload all files collected during the earlier builds, the complete list is:
- `translations.zip` - `translations.zip`
- `visualboyadvance-m-Win-x86_64.zip` - `translations.zip.asc`
- `visualboyadvance-m-Win-x86_64-debug.zip` - `visualboyadvance-m-Mac-64bit.zip`
- `visualboyadvance-m-Win-x86_32.zip` - `visualboyadvance-m-Mac-64bit.zip.asc`
- `visualboyadvance-m-Win-x86_32-debug.zip` - `visualboyadvance-m-Win-32bit.zip`
- `visualboyadvance-m-Win-arm64.zip` - `visualboyadvance-m-Win-32bit.zip.asc`
- 'visualboyadvance-m-Win-arm64-debug.zip' - `visualboyadvance-m-Win-64bit.zip`
- `visualboyadvance-m-Mac-x86_64.zip` - `visualboyadvance-m-Win-64bit.zip.asc`
- `visualboyadvance-m-Mac-x86_64-debug.zip`
Update the winsparkle `appcast.xml` by running this cmake command: Update the winsparkle appcast.xml by running this cmake command:
```bash ```bash
cmake .. -DUPDATE_APPCAST=TRUE cmake .. -DUPDATE_APPCAST=TRUE
``` ```
, follow the instructions to push the change to the web data repo.
follow the instructions to push the change to the web data repo.
Announce the release on reddit r/emulation and the forum. Announce the release on reddit r/emulation and the forum.

172
README.md
View File

@@ -19,6 +19,8 @@
<!-- END doctoc generated TOC please keep comment here to allow auto update --> <!-- END doctoc generated TOC please keep comment here to allow auto update -->
[![Join the chat at https://gitter.im/visualboyadvance-m/Lobby](https://badges.gitter.im/visualboyadvance-m/Lobby.svg)](https://gitter.im/visualboyadvance-m/Lobby)
Our bridged Discord server is [Here](https://discord.gg/EpfxEuGMKH). Our bridged Discord server is [Here](https://discord.gg/EpfxEuGMKH).
We are also on *`#vba-m`* on [Libera IRC](https://libera.chat/) which has a [Web We are also on *`#vba-m`* on [Libera IRC](https://libera.chat/) which has a [Web
@@ -57,39 +59,35 @@ Factory Reset`.
## System Requirements ## System Requirements
Windows XP, Vista, 7, 8.1 or 10/11, Linux distros or macOS. Windows 7, 8.1 or 10/11, Linux distro's or macOS.
2Ghz x86 (or x86-64) Intel Core 2 or AMD Athlon processor with SSE, Snapdragon 835
or newer CPU compatible with Arm for Windows.
2Ghz x86(or x86-64) Intel Core 2 or AMD Athlon processor with SSE, Snapdragon 835
or newer cpu compatible with Arm for Windows.
- Just a guideline, lower clock speeds and Celeron processors may be able to run at full - Just a guideline, lower clock speeds and Celeron processors may be able to run at full
speed on lower settings, and Linux based ARM Operating systems have wider CPU support. speed on lower settings, and Linux based ARM Operating systems have wider cpu support.
DirectX June 2010 Redist DirectX June 2010 Redist [Full](https://www.microsoft.com/en-au/download/details.aspx?id=8109) / [Websetup](https://www.microsoft.com/en-au/download/details.aspx?id=35) for Xaudio (Remember to uncheck Bing on the websetup)
[Full](https://www.microsoft.com/en-au/download/details.aspx?id=8109) /
[Websetup](https://www.microsoft.com/en-au/download/details.aspx?id=35) for
Xaudio (Remember to uncheck Bing on the websetup.)
## Building ## Building
The basic formula to build vba-m is: The basic formula to build vba-m is:
```bash ```shell
cd ~ && mkdir src && cd src cd ~ && mkdir src && cd src
git clone https://github.com/visualboyadvance-m/visualboyadvance-m.git git clone https://github.com/visualboyadvance-m/visualboyadvance-m.git
cd visualboyadvance-m cd visualboyadvance-m
./installdeps
./installdeps # On Linux or macOS # ./installdeps will give you build instructions, which will be similar to:
mkdir build mkdir build && cd build
cd build cmake .. -G Ninja
cmake .. -DCMAKE_BUILD_TYPE=Release -G Ninja
ninja ninja
``` ```
`./installdeps` is supported on MSYS2, Linux (Debian/Ubuntu, Fedora, Arch, `./installdeps` is supported on MSys2, Linux (Debian/Ubuntu, Fedora, Arch,
Solus, OpenSUSE, Gentoo and RHEL/CentOS) and Mac OS X (homebrew, MacPorts or Solus, OpenSUSE, Gentoo and RHEL/CentOS) and Mac OS X (homebrew, macports or
Fink.) fink.)
## Building a Libretro core ## Building a Libretro core
@@ -100,7 +98,7 @@ cd src/libretro
make -j`nproc` make -j`nproc`
``` ```
Copy `vbam_libretro.so` to your RetroArch cores directory. Copy vbam_libretro.so to your RetroArch cores directory.
## Visual Studio Support ## Visual Studio Support
@@ -120,16 +118,14 @@ environment loaded.
Using your own user-wide installation of vcpkg is supported, just make sure the Using your own user-wide installation of vcpkg is supported, just make sure the
environment variable `VCPKG_ROOT` is set. environment variable `VCPKG_ROOT` is set.
To build in the Visual Studio `x64 Native Tools Command Prompt`, use something To build in the visual studio command prompt, use something like this:
like this:
``` ```
mkdir build mkdir build
cd build cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -G Ninja cmake .. -DVCPKG_TARGET_TRIPLET=x64-windows-static -DCMAKE_BUILD_TYPE=Debug -G Ninja
ninja ninja
``` ```
.
## Visual Studio Code Support ## Visual Studio Code Support
@@ -166,7 +162,8 @@ And the following development libraries:
- [ffmpeg](https://ffmpeg.org/) (optional, at least version `4.0.4`, for game recording) - [ffmpeg](https://ffmpeg.org/) (optional, at least version `4.0.4`, for game recording)
- [gettext](https://www.gnu.org/software/gettext/) and gettext-tools - [gettext](https://www.gnu.org/software/gettext/) and gettext-tools
- [SDL2](https://www.libsdl.org/) (required) - [SDL2](https://www.libsdl.org/) (required)
- [openal-soft](https://kcat.strangesoft.net/openal.html) (required, a sound interface) - [SFML](https://www.sfml-dev.org/) (optional, for link)
- [OpenAL](https://www.openal.org/) or [openal-soft](https://kcat.strangesoft.net/openal.html) (required, a sound interface)
- [wxWidgets](https://wxwidgets.org/) (required for GUI, 2.8 and non-stl builds are no longer supported) - [wxWidgets](https://wxwidgets.org/) (required for GUI, 2.8 and non-stl builds are no longer supported)
On Linux and similar, you also need the version of GTK your wxWidgets is linked On Linux and similar, you also need the version of GTK your wxWidgets is linked
@@ -186,46 +183,61 @@ This is supported on Fedora, Arch, Solus and MSYS2.
may be `win32` which is an alias for `mingw-w64-i686` to target 32 bit Windows, may be `win32` which is an alias for `mingw-w64-i686` to target 32 bit Windows,
or `mingw-w64-x86_64` for 64 bit Windows targets. or `mingw-w64-x86_64` for 64 bit Windows targets.
The target is implicit on MSYS2 depending on which MINGW shell you started (the The target is implicit on MSys2 depending on which MINGW shell you started (the
value of `$MSYSTEM`.) value of `$MSYSTEM`.)
On Debian/Ubuntu this uses the MXE apt repository and works quite well. On Debian/Ubuntu this uses the MXE apt repository and works quite well.
On Fedora it can build using the Fedora MinGW packages, albeit with wx 2.8, no
OpenGL support, and no Link support for lack of SFML.
On Arch it currently doesn't work at all because the AUR stuff is completely
broken, I will at some point redo the arch stuff to use MXE as well.
## CMake Options ## CMake Options
The CMake code tries to guess reasonable defaults for options, but you can The CMake code tries to guess reasonable defaults for options, but you can
override them, for example: override them, for example:
```shell ```shell
cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_LINK=NO -G Ninja cmake .. -DENABLE_LINK=NO -G Ninja
``` ```
. Here is the complete list:
Of particular interest is making **Release** or **Debug** builds, the default
mode is **Release**, to make a **Debug** build use something like:
```shell
cmake .. -DCMAKE_BUILD_TYPE=Debug -G Ninja
```
Here is the complete list:
| **CMake Option** | **What it Does** | **Defaults** | | **CMake Option** | **What it Does** | **Defaults** |
|-----------------------|----------------------------------------------------------------------|-----------------------| |-----------------------|----------------------------------------------------------------------|-----------------------|
| `ENABLE_SDL` | Build the SDL port | OFF | | ENABLE_SDL | Build the SDL port | OFF |
| `ENABLE_WX` | Build the wxWidgets port | ON | | ENABLE_WX | Build the wxWidgets port | ON |
| `ENABLE_DEBUGGER` | Enable the debugger | ON | | ENABLE_DEBUGGER | Enable the debugger | ON |
| `ENABLE_ASM_CORE` | Enable x86 ASM CPU cores (**BUGGY AND DANGEROUS**) | OFF | | ENABLE_ASM_CORE | Enable x86 ASM CPU cores (**BUGGY AND DANGEROUS**) | OFF |
| `ENABLE_ASM` | Enable the following two ASM options | ON for 32 bit builds | | ENABLE_ASM | Enable the following two ASM options | ON for 32 bit builds |
| `ENABLE_ASM_SCALERS` | Enable x86 ASM graphic filters | ON for 32 bit builds | | ENABLE_ASM_SCALERS | Enable x86 ASM graphic filters | ON for 32 bit builds |
| `ENABLE_MMX` | Enable MMX | ON for 32 bit builds | | ENABLE_MMX | Enable MMX | ON for 32 bit builds |
| `ENABLE_LINK` | Enable GBA linking functionality | AUTO | | ENABLE_LINK | Enable GBA linking functionality (requires SFML) | AUTO |
| `ENABLE_LIRC` | Enable LIRC support | OFF | | ENABLE_LIRC | Enable LIRC support | OFF |
| `ENABLE_FFMPEG` | Enable ffmpeg A/V recording | AUTO | | ENABLE_FFMPEG | Enable ffmpeg A/V recording | AUTO |
| `ENABLE_ONLINEUPDATES` | Enable online update checks | ON | | ENABLE_ONLINEUPDATES | Enable online update checks | ON |
| `ENABLE_LTO` | Compile with Link Time Optimization (gcc and clang only) | ON for release build | | ENABLE_LTO | Compile with Link Time Optimization (gcc and clang only) | ON for release build |
| `ENABLE_GBA_LOGGING` | Enable extended GBA logging | ON | | ENABLE_GBA_LOGGING | Enable extended GBA logging | ON |
| `ENABLE_XAUDIO2` | Enable xaudio2 sound output for wxWidgets (Windows only) | ON | | ENABLE_DIRECT3D | Direct3D rendering for wxWidgets (Windows, **NOT IMPLEMENTED!!!**) | ON |
| `ENABLE_FAUDIO` | Enable faudio sound output for wxWidgets, | ON, not 32 bit Win | | ENABLE_XAUDIO2 | Enable xaudio2 sound output for wxWidgets (Windows only) | ON |
| `ENABLE_ASAN` | Enable libasan sanitizers (by default address, only in debug mode) | OFF | | ENABLE_ASAN | Enable libasan sanitizers (by default address, only in debug mode) | OFF |
| `UPSTREAM_RELEASE` | Do some release tasks, like codesigning, making zip and gpg sigs. | OFF | | UPSTREAM_RELEASE | Do some release tasks, like codesigning, making zip and gpg sigs. | OFF |
| `BUILD_TESTING` | Build the tests and enable ctest support. | ON | | BUILD_TESTING | Build the tests and enable ctest support. | ON |
| `VBAM_STATIC` | Try link all libs statically (the following are set to ON if ON) | OFF | | VBAM_STATIC | Try link all libs statically (the following are set to ON if ON) | OFF |
| `SDL2_STATIC` | Try to link static SDL2 libraries | OFF | | SDL2_STATIC | Try to link static SDL2 libraries | OFF |
| `FFMPEG_STATIC` | Try to link static ffmpeg libraries | OFF | | SFML_STATIC_LIBRARIES | Try to link static SFML libraries | OFF |
| `OPENAL_STATIC` | Try to link static OpenAL libraries | OFF | | FFMPEG_STATIC | Try to link static ffmpeg libraries | OFF |
| `TRANSLATIONS_ONLY` | Build only the translations.zip and nothing else | OFF | | OPENAL_STATIC | Try to link static OpenAL libraries | OFF |
| TRANSLATIONS_ONLY | Build only the translations.zip and nothing else | OFF |
Note for distro packagers, we use the CMake module Note for distro packagers, we use the CMake module
[GNUInstallDirs](https://cmake.org/cmake/help/v2.8.12/cmake.html#module:GNUInstallDirs) [GNUInstallDirs](https://cmake.org/cmake/help/v2.8.12/cmake.html#module:GNUInstallDirs)
@@ -235,6 +247,52 @@ On Unix to use a different version of wxWidgets, set
`wxWidgets_CONFIG_EXECUTABLE` to the path to the `wx-config` script you want to `wxWidgets_CONFIG_EXECUTABLE` to the path to the `wx-config` script you want to
use. use.
## MSys2 Notes
To run the resulting binary, you can simply type:
```shell
./visualboyadvance-m
```
in the shell where you built it.
If you built with `-DCMAKE_BUILD_TYPE=Debug`, you will get a console app and
will see debug messages, even in mintty.
If you want to start the binary from e.g. a shortcut or Explorer, you will need
to put `c:\msys64\mingw32\bin` for 32 bit builds and `c:\msys64\mingw64\bin`
for 64 bit builds in your PATH (to edit system PATH, go to Control Panel ->
System -> Advanced system settings -> Environment Variables.)
If you want to package the binary, you will need to include the MinGW DLLs it
depends on, they can install to the same directory as the binary.
Our own builds are static.
## Debug Messages
We have an override for `wxLogDebug()` to make it work even in non-debug builds
of wx and on windows, even in mintty.
It works like `printf()`, e.g.:
```cpp
int foo = 42;
wxLogDebug(wxT("the value of foo = %d"), foo);
```
From the core etc. the usual:
```cpp
fprintf(stderr, "...", ...);
```
will work fine.
You need a debug build for this to work or to even have a console on Windows.
Pass `-DCMAKE_BUILD_TYPE=Debug` to cmake.
## Reporting Crash Bugs ## Reporting Crash Bugs
If the emulator crashes and you wish to report the bug, a backtrace made with If the emulator crashes and you wish to report the bug, a backtrace made with
@@ -253,25 +311,27 @@ do something such as:
```shell ```shell
ulimit -c unlimited ulimit -c unlimited
``` ```
, in your shell to enable core files.
in your shell to enable coredump files.
[This [This
post](https://ask.fedoraproject.org/en/question/98776/where-is-core-dump-located/?answer=98779#post-id-98779) post](https://ask.fedoraproject.org/en/question/98776/where-is-core-dump-located/?answer=98779#post-id-98779)
explains how to retrieve core dump on some distributions, when they are managed explains how to retrieve core dump on Fedora Linux (and possibly other
by systemd. distributions.)
Once you have the core file, open it with `gdb`, for example: Once you have the core dump file, open it with `gdb`, for example:
```shell ```shell
gdb -c core ./visualboyadvance-m gdb -c core ./visualboyadvance-m
``` ```
. In the `gdb` shell, to start the process and print the backtrace, type:
In the `gdb` shell, to print the backtrace, type:
``` ```
run
bt bt
``` ```
. This may be a bit of a hassle, but it helps us out immensely.
This may be a bit of a hassle, but it helps us out immensely.
## Contributing ## Contributing

View File

@@ -56,12 +56,10 @@ if(CMAKE_SYSTEM_PROCESSOR MATCHES "[xX]86|i[3-9]86|[aA][mM][dD]64")
endif() endif()
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "[aA][aA][rR][cC][hH]|[aA][rR][mM]") elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "[aA][aA][rR][cC][hH]|[aA][rR][mM]")
if(CMAKE_C_SIZEOF_DATA_PTR EQUAL 4) # 32 bit if(CMAKE_C_SIZEOF_DATA_PTR EQUAL 4) # 32 bit
set(ARM32 ON) set(ARCH_NAME arm32)
set(ARCH_NAME ARM32)
set(WINARCH arm) set(WINARCH arm)
elseif(CMAKE_C_SIZEOF_DATA_PTR EQUAL 8) elseif(CMAKE_C_SIZEOF_DATA_PTR EQUAL 8)
set(ARM64 ON) set(ARCH_NAME arm64)
set(ARCH_NAME ARM64)
set(WINARCH arm64) set(WINARCH arm64)
endif() endif()

View File

@@ -23,7 +23,7 @@ if(CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg")
if(VCPKG_TARGET_TRIPLET MATCHES -static) if(VCPKG_TARGET_TRIPLET MATCHES -static)
set(arch_suffix -static) set(arch_suffix -static)
endif() endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug") if(CMAKE_BUILD_TYPE MATCHES "^(Debug|RelWithDebInfo)$")
set(path_prefix debug) set(path_prefix debug)
endif() endif()
set(installed_prefix ${_VCPKG_INSTALLED_DIR}/${WINARCH}-windows${arch_suffix}/${path_prefix}) set(installed_prefix ${_VCPKG_INSTALLED_DIR}/${WINARCH}-windows${arch_suffix}/${path_prefix})
@@ -119,3 +119,4 @@ if(ENABLE_LINK OR ENABLE_WX)
message(FATAL_ERROR "NLS requires libintl/gettext") message(FATAL_ERROR "NLS requires libintl/gettext")
endif() endif()
endif() endif()

110
cmake/FindOpenAL.cmake Normal file
View File

@@ -0,0 +1,110 @@
#.rst:
# FindOpenAL
# ----------
#
#
#
# Locate OpenAL This module defines OPENAL_LIBRARY OPENAL_FOUND, if
# false, do not try to link to OpenAL OPENAL_INCLUDE_DIR, where to find
# the headers
#
# $OPENALDIR is an environment variable that would correspond to the
# ./configure --prefix=$OPENALDIR used in building OpenAL.
#
# Created by Eric Wing. This was influenced by the FindSDL.cmake
# module.
#=============================================================================
# Copyright 2005-2009 Kitware, Inc.
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
# This makes the presumption that you are include al.h like
# #include "al.h"
# and not
# #include <AL/al.h>
# The reason for this is that the latter is not entirely portable.
# Windows/Creative Labs does not by default put their headers in AL/ and
# OS X uses the convention <OpenAL/al.h>.
#
# For Windows, Creative Labs seems to have added a registry key for their
# OpenAL 1.1 installer. I have added that key to the list of search paths,
# however, the key looks like it could be a little fragile depending on
# if they decide to change the 1.00.0000 number for bug fix releases.
# Also, they seem to have laid down groundwork for multiple library platforms
# which puts the library in an extra subdirectory. Currently there is only
# Win32 and I have hardcoded that here. This may need to be adjusted as
# platforms are introduced.
# The OpenAL 1.0 installer doesn't seem to have a useful key I can use.
# I do not know if the Nvidia OpenAL SDK has a registry key.
#
# For OS X, remember that OpenAL was added by Apple in 10.4 (Tiger).
# To support the framework, I originally wrote special framework detection
# code in this module which I have now removed with CMake's introduction
# of native support for frameworks.
# In addition, OpenAL is open source, and it is possible to compile on Panther.
# Furthermore, due to bugs in the initial OpenAL release, and the
# transition to OpenAL 1.1, it is common to need to override the built-in
# framework.
# Per my request, CMake should search for frameworks first in
# the following order:
# ~/Library/Frameworks/OpenAL.framework/Headers
# /Library/Frameworks/OpenAL.framework/Headers
# /System/Library/Frameworks/OpenAL.framework/Headers
#
# On OS X, this will prefer the Framework version (if found) over others.
# People will have to manually change the cache values of
# OPENAL_LIBRARY to override this selection or set the CMake environment
# CMAKE_INCLUDE_PATH to modify the search paths.
find_path(OPENAL_INCLUDE_DIR al.h
HINTS
ENV OPENALDIR
PATH_SUFFIXES AL OpenAL
PATHS
~/Library/Frameworks
/Library/Frameworks
/sw # Fink
/opt/local # DarwinPorts
/opt/csw # Blastwave
/opt
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Creative\ Labs\\OpenAL\ 1.1\ Software\ Development\ Kit\\1.00.0000;InstallDir]
)
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(_OpenAL_ARCH_DIR libs/Win64)
else()
set(_OpenAL_ARCH_DIR libs/Win32)
endif()
find_library(OPENAL_LIBRARY
NAMES OpenAL al openal OpenAL32
HINTS
ENV OPENALDIR
PATH_SUFFIXES lib64 lib libs64 libs ${_OpenAL_ARCH_DIR}
PATHS
~/Library/Frameworks
/Library/Frameworks
/sw
/opt/local
/opt/csw
/opt
[HKEY_LOCAL_MACHINE\\SOFTWARE\\Creative\ Labs\\OpenAL\ 1.1\ Software\ Development\ Kit\\1.00.0000;InstallDir]
)
unset(_OpenAL_ARCH_DIR)
# handle the QUIETLY and REQUIRED arguments and set OPENAL_FOUND to TRUE if
# all listed variables are TRUE
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenAL DEFAULT_MSG OPENAL_LIBRARY OPENAL_INCLUDE_DIR)
mark_as_advanced(OPENAL_LIBRARY OPENAL_INCLUDE_DIR)

365
cmake/FindSFML.cmake Normal file
View File

@@ -0,0 +1,365 @@
# This script locates the SFML library
# ------------------------------------
#
# Usage
# -----
#
# When you try to locate the SFML libraries, you must specify which modules you want to use (system, window, graphics, network, audio, main).
# If none is given, the SFML_LIBRARIES variable will be empty and you'll end up linking to nothing.
# example:
# find_package(SFML COMPONENTS graphics window system) # find the graphics, window and system modules
#
# You can enforce a specific version, either MAJOR.MINOR or only MAJOR.
# If nothing is specified, the version won't be checked (i.e. any version will be accepted).
# example:
# find_package(SFML COMPONENTS ...) # no specific version required
# find_package(SFML 2 COMPONENTS ...) # any 2.x version
# find_package(SFML 2.4 COMPONENTS ...) # version 2.4 or greater
#
# By default, the dynamic libraries of SFML will be found. To find the static ones instead,
# you must set the SFML_STATIC_LIBRARIES variable to TRUE before calling find_package(SFML ...).
# Since you have to link yourself all the SFML dependencies when you link it statically, the following
# additional variables are defined: SFML_XXX_DEPENDENCIES and SFML_DEPENDENCIES (see their detailed
# description below).
# In case of static linking, the SFML_STATIC macro will also be defined by this script.
# example:
# set(SFML_STATIC_LIBRARIES TRUE)
# find_package(SFML 2 COMPONENTS network system)
#
# On Mac OS X if SFML_STATIC_LIBRARIES is not set to TRUE then by default CMake will search for frameworks unless
# CMAKE_FIND_FRAMEWORK is set to "NEVER" for example. Please refer to CMake documentation for more details.
# Moreover, keep in mind that SFML frameworks are only available as release libraries unlike dylibs which
# are available for both release and debug modes.
#
# If SFML is not installed in a standard path, you can use the SFML_ROOT CMake (or environment) variable
# to tell CMake where SFML is.
#
# Output
# ------
#
# This script defines the following variables:
# - For each specified module XXX (system, window, graphics, network, audio, main):
# - SFML_XXX_LIBRARY_DEBUG: the name of the debug library of the xxx module (set to SFML_XXX_LIBRARY_RELEASE is no debug version is found)
# - SFML_XXX_LIBRARY_RELEASE: the name of the release library of the xxx module (set to SFML_XXX_LIBRARY_DEBUG is no release version is found)
# - SFML_XXX_LIBRARY: the name of the library to link to for the xxx module (includes both debug and optimized names if necessary)
# - SFML_XXX_FOUND: true if either the debug or release library of the xxx module is found
# - SFML_XXX_DEPENDENCIES: the list of libraries the module depends on, in case of static linking
# - SFML_LIBRARIES: the list of all libraries corresponding to the required modules
# - SFML_FOUND: true if all the required modules are found
# - SFML_INCLUDE_DIR: the path where SFML headers are located (the directory containing the SFML/Config.hpp file)
# - SFML_DEPENDENCIES: the list of libraries SFML depends on, in case of static linking
#
# example:
# find_package(SFML 2 COMPONENTS system window graphics audio REQUIRED)
# include_directories(${SFML_INCLUDE_DIR})
# add_executable(myapp ...)
# target_link_libraries(myapp ${SFML_LIBRARIES})
# define the SFML_STATIC macro if static build was chosen
if(SFML_STATIC_LIBRARIES)
add_compile_definitions(SFML_STATIC)
endif()
# define the list of search paths for headers and libraries
set(FIND_SFML_PATHS
${SFML_ROOT}
$ENV{SFML_ROOT}
~/Library/Frameworks
/Library/Frameworks
/usr/local
/usr
/sw
/opt/local
/opt/csw
/opt)
# find the SFML include directory
find_path(SFML_INCLUDE_DIR SFML/Config.hpp
PATH_SUFFIXES include
PATHS ${FIND_SFML_PATHS})
# check the version number
set(SFML_VERSION_OK TRUE)
if(SFML_FIND_VERSION AND SFML_INCLUDE_DIR)
# extract the major and minor version numbers from SFML/Config.hpp
# we have to handle framework a little bit differently:
if("${SFML_INCLUDE_DIR}" MATCHES "SFML.framework")
set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/Headers/Config.hpp")
else()
set(SFML_CONFIG_HPP_INPUT "${SFML_INCLUDE_DIR}/SFML/Config.hpp")
endif()
FILE(READ "${SFML_CONFIG_HPP_INPUT}" SFML_CONFIG_HPP_CONTENTS)
STRING(REGEX REPLACE ".*#define *SFML_VERSION_MAJOR *([0-9]+).*" "\\1" SFML_VERSION_MAJOR "${SFML_CONFIG_HPP_CONTENTS}")
STRING(REGEX REPLACE ".*#define *SFML_VERSION_MINOR *([0-9]+).*" "\\1" SFML_VERSION_MINOR "${SFML_CONFIG_HPP_CONTENTS}")
STRING(REGEX REPLACE ".*#define *SFML_VERSION_PATCH *([0-9]+).*" "\\1" SFML_VERSION_PATCH "${SFML_CONFIG_HPP_CONTENTS}")
if (NOT "${SFML_VERSION_PATCH}" MATCHES "^[0-9]+$")
set(SFML_VERSION_PATCH 0)
endif()
math(EXPR SFML_REQUESTED_VERSION "${SFML_FIND_VERSION_MAJOR} * 10000 + ${SFML_FIND_VERSION_MINOR} * 100 + ${SFML_FIND_VERSION_PATCH}")
# if we could extract them, compare with the requested version number
if (SFML_VERSION_MAJOR)
# transform version numbers to an integer
math(EXPR SFML_VERSION "${SFML_VERSION_MAJOR} * 10000 + ${SFML_VERSION_MINOR} * 100 + ${SFML_VERSION_PATCH}")
# compare them
if(SFML_VERSION LESS SFML_REQUESTED_VERSION)
set(SFML_VERSION_OK FALSE)
endif()
else()
# SFML version is < 2.0
if (SFML_REQUESTED_VERSION GREATER 10900)
set(SFML_VERSION_OK FALSE)
set(SFML_VERSION_MAJOR 1)
set(SFML_VERSION_MINOR x)
set(SFML_VERSION_PATCH x)
endif()
endif()
endif()
# find the requested modules
set(SFML_FOUND TRUE) # will be set to false if one of the required modules is not found
foreach(FIND_SFML_COMPONENT ${SFML_FIND_COMPONENTS})
string(TOLOWER ${FIND_SFML_COMPONENT} FIND_SFML_COMPONENT_LOWER)
string(TOUPPER ${FIND_SFML_COMPONENT} FIND_SFML_COMPONENT_UPPER)
set(FIND_SFML_COMPONENT_NAME sfml-${FIND_SFML_COMPONENT_LOWER})
# no suffix for sfml-main, it is always a static library
if(FIND_SFML_COMPONENT_LOWER STREQUAL "main")
# release library
find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE
NAMES ${FIND_SFML_COMPONENT_NAME}
PATH_SUFFIXES lib64 lib
PATHS ${FIND_SFML_PATHS})
# debug library
find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG
NAMES ${FIND_SFML_COMPONENT_NAME}-d
PATH_SUFFIXES lib64 lib
PATHS ${FIND_SFML_PATHS})
else()
# static release library
find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE
NAMES ${FIND_SFML_COMPONENT_NAME}-s
PATH_SUFFIXES lib64 lib
PATHS ${FIND_SFML_PATHS})
# static debug library
find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG
NAMES ${FIND_SFML_COMPONENT_NAME}-s-d
PATH_SUFFIXES lib64 lib
PATHS ${FIND_SFML_PATHS})
# dynamic release library
find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE
NAMES ${FIND_SFML_COMPONENT_NAME}
PATH_SUFFIXES lib64 lib
PATHS ${FIND_SFML_PATHS})
# dynamic debug library
find_library(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG
NAMES ${FIND_SFML_COMPONENT_NAME}-d
PATH_SUFFIXES lib64 lib
PATHS ${FIND_SFML_PATHS})
# choose the entries that fit the requested link type
if(SFML_STATIC_LIBRARIES)
if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE)
set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE})
endif()
if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG)
set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG})
endif()
else()
if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE)
set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE})
endif()
if(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG)
set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG})
endif()
endif()
endif()
if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG OR SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE)
# library found
set(SFML_${FIND_SFML_COMPONENT_UPPER}_FOUND TRUE)
# if both are found, set SFML_XXX_LIBRARY to contain both
if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG AND SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE)
set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY debug ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG}
optimized ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE})
endif()
# if only one debug/release variant is found, set the other to be equal to the found one
if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG AND NOT SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE)
# debug and not release
set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG})
set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG})
endif()
if (SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE AND NOT SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG)
# release and not debug
set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE})
set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY ${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE})
endif()
else()
# library not found
set(SFML_FOUND FALSE)
set(SFML_${FIND_SFML_COMPONENT_UPPER}_FOUND FALSE)
set(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY "")
set(FIND_SFML_MISSING "${FIND_SFML_MISSING} SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY")
endif()
# mark as advanced
MARK_AS_ADVANCED(SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY
SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_RELEASE
SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DEBUG
SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_RELEASE
SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_STATIC_DEBUG
SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_RELEASE
SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY_DYNAMIC_DEBUG)
# add to the global list of libraries
set(SFML_LIBRARIES ${SFML_LIBRARIES} "${SFML_${FIND_SFML_COMPONENT_UPPER}_LIBRARY}")
endforeach()
# in case of static linking, we must also define the list of all the dependencies of SFML libraries
if(SFML_STATIC_LIBRARIES)
# detect the OS
if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
set(FIND_SFML_OS_WINDOWS 1)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
set(FIND_SFML_OS_LINUX 1)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
set(FIND_SFML_OS_FREEBSD 1)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(FIND_SFML_OS_MACOSX 1)
endif()
# start with an empty list
set(SFML_DEPENDENCIES)
set(FIND_SFML_DEPENDENCIES_NOTFOUND)
# macro that searches for a 3rd-party library
macro(find_sfml_dependency output friendlyname)
# No lookup in environment variables (PATH on Windows), as they may contain wrong library versions
find_library(${output} NAMES ${ARGN} PATHS ${FIND_SFML_PATHS} PATH_SUFFIXES lib NO_SYSTEM_ENVIRONMENT_PATH)
if(${${output}} STREQUAL "${output}-NOTFOUND")
unset(output)
set(FIND_SFML_DEPENDENCIES_NOTFOUND "${FIND_SFML_DEPENDENCIES_NOTFOUND} ${friendlyname}")
endif()
endmacro()
# sfml-system
list(FIND SFML_FIND_COMPONENTS "system" FIND_SFML_SYSTEM_COMPONENT)
if(NOT ${FIND_SFML_SYSTEM_COMPONENT} EQUAL -1)
# update the list -- these are only system libraries, no need to find them
if(FIND_SFML_OS_LINUX OR FIND_SFML_OS_FREEBSD OR FIND_SFML_OS_MACOSX)
set(SFML_SYSTEM_DEPENDENCIES "pthread")
endif()
if(FIND_SFML_OS_LINUX)
set(SFML_SYSTEM_DEPENDENCIES ${SFML_SYSTEM_DEPENDENCIES} "rt")
endif()
if(FIND_SFML_OS_WINDOWS)
set(SFML_SYSTEM_DEPENDENCIES "winmm")
endif()
set(SFML_DEPENDENCIES ${SFML_SYSTEM_DEPENDENCIES} ${SFML_DEPENDENCIES})
endif()
# sfml-network
list(FIND SFML_FIND_COMPONENTS "network" FIND_SFML_NETWORK_COMPONENT)
if(NOT ${FIND_SFML_NETWORK_COMPONENT} EQUAL -1)
# update the list -- these are only system libraries, no need to find them
if(FIND_SFML_OS_WINDOWS)
set(SFML_NETWORK_DEPENDENCIES "ws2_32")
endif()
set(SFML_DEPENDENCIES ${SFML_NETWORK_DEPENDENCIES} ${SFML_DEPENDENCIES})
endif()
# sfml-window
list(FIND SFML_FIND_COMPONENTS "window" FIND_SFML_WINDOW_COMPONENT)
if(NOT ${FIND_SFML_WINDOW_COMPONENT} EQUAL -1)
# find libraries
if(FIND_SFML_OS_LINUX OR FIND_SFML_OS_FREEBSD)
find_sfml_dependency(X11_LIBRARY "X11" X11)
find_sfml_dependency(XRANDR_LIBRARY "Xrandr" Xrandr)
endif()
if(FIND_SFML_OS_LINUX)
find_sfml_dependency(UDEV_LIBRARIES "UDev" udev libudev)
endif()
# update the list
if(FIND_SFML_OS_WINDOWS)
set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "opengl32" "winmm" "gdi32")
elseif(FIND_SFML_OS_LINUX)
set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "GL" ${X11_LIBRARY} ${XRANDR_LIBRARY} ${UDEV_LIBRARIES})
elseif(FIND_SFML_OS_FREEBSD)
set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "GL" ${X11_LIBRARY} ${XRANDR_LIBRARY} "usbhid")
elseif(FIND_SFML_OS_MACOSX)
set(SFML_WINDOW_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} "-framework OpenGL -framework Foundation -framework AppKit -framework IOKit -framework Carbon")
endif()
set(SFML_DEPENDENCIES ${SFML_WINDOW_DEPENDENCIES} ${SFML_DEPENDENCIES})
endif()
# sfml-graphics
list(FIND SFML_FIND_COMPONENTS "graphics" FIND_SFML_GRAPHICS_COMPONENT)
if(NOT ${FIND_SFML_GRAPHICS_COMPONENT} EQUAL -1)
# find libraries
find_sfml_dependency(FREETYPE_LIBRARY "FreeType" freetype)
find_sfml_dependency(JPEG_LIBRARY "libjpeg" jpeg)
# update the list
set(SFML_GRAPHICS_DEPENDENCIES ${FREETYPE_LIBRARY} ${JPEG_LIBRARY})
set(SFML_DEPENDENCIES ${SFML_GRAPHICS_DEPENDENCIES} ${SFML_DEPENDENCIES})
endif()
# sfml-audio
list(FIND SFML_FIND_COMPONENTS "audio" FIND_SFML_AUDIO_COMPONENT)
if(NOT ${FIND_SFML_AUDIO_COMPONENT} EQUAL -1)
# find libraries
find_sfml_dependency(OPENAL_LIBRARY "OpenAL" openal openal32)
find_sfml_dependency(OGG_LIBRARY "Ogg" ogg)
find_sfml_dependency(VORBIS_LIBRARY "Vorbis" vorbis)
find_sfml_dependency(VORBISFILE_LIBRARY "VorbisFile" vorbisfile)
find_sfml_dependency(VORBISENC_LIBRARY "VorbisEnc" vorbisenc)
find_sfml_dependency(FLAC_LIBRARY "FLAC" FLAC)
# update the list
set(SFML_AUDIO_DEPENDENCIES ${OPENAL_LIBRARY} ${FLAC_LIBRARY} ${VORBISENC_LIBRARY} ${VORBISFILE_LIBRARY} ${VORBIS_LIBRARY} ${OGG_LIBRARY})
set(SFML_DEPENDENCIES ${SFML_DEPENDENCIES} ${SFML_AUDIO_DEPENDENCIES})
endif()
endif()
# handle errors
if(NOT SFML_VERSION_OK)
# SFML version not ok
set(FIND_SFML_ERROR "SFML found but version too low (requested: ${SFML_FIND_VERSION}, found: ${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR}.${SFML_VERSION_PATCH})")
set(SFML_FOUND FALSE)
elseif(SFML_STATIC_LIBRARIES AND FIND_SFML_DEPENDENCIES_NOTFOUND)
set(FIND_SFML_ERROR "SFML found but some of its dependencies are missing (${FIND_SFML_DEPENDENCIES_NOTFOUND})")
set(SFML_FOUND FALSE)
elseif(NOT SFML_FOUND)
# include directory or library not found
set(FIND_SFML_ERROR "Could NOT find SFML (missing: ${FIND_SFML_MISSING})")
endif()
if (NOT SFML_FOUND)
if(SFML_FIND_REQUIRED)
# fatal error
message(FATAL_ERROR ${FIND_SFML_ERROR})
elseif(NOT SFML_FIND_QUIETLY)
# error but continue
message("${FIND_SFML_ERROR}")
endif()
endif()
# handle success
if(SFML_FOUND AND NOT SFML_FIND_QUIETLY)
message(STATUS "Found SFML ${SFML_VERSION_MAJOR}.${SFML_VERSION_MINOR}.${SFML_VERSION_PATCH} in ${SFML_INCLUDE_DIR}")
endif()

View File

@@ -10,6 +10,10 @@ if(NOT EXISTS "${CMAKE_SOURCE_DIR}/.git")
message(FATAL_ERROR "releases can only be done from a git clone") message(FATAL_ERROR "releases can only be done from a git clone")
endif() endif()
if(NOT GIT_FOUND)
message(FATAL_ERROR "git is required to make a release")
endif()
find_program(GPG_EXECUTABLE gpg) find_program(GPG_EXECUTABLE gpg)
if(NOT GPG_EXECUTABLE) if(NOT GPG_EXECUTABLE)
@@ -31,7 +35,7 @@ function(make_release_commit_and_tag)
# First make sure we are on master. # First make sure we are on master.
execute_process( execute_process(
COMMAND git rev-parse --short --abbrev-ref=strict HEAD COMMAND ${GIT_EXECUTABLE} rev-parse --short --abbrev-ref=strict HEAD
OUTPUT_VARIABLE git_branch OUTPUT_VARIABLE git_branch
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_STRIP_TRAILING_WHITESPACE
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
@@ -42,7 +46,7 @@ function(make_release_commit_and_tag)
endif() endif()
execute_process( execute_process(
COMMAND git status --porcelain=2 COMMAND ${GIT_EXECUTABLE} status --porcelain=2
OUTPUT_VARIABLE git_status OUTPUT_VARIABLE git_status
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_STRIP_TRAILING_WHITESPACE
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
@@ -55,7 +59,7 @@ function(make_release_commit_and_tag)
endif() endif()
execute_process( execute_process(
COMMAND git tag --sort=-v:refname COMMAND ${GIT_EXECUTABLE} tag --sort=-v:refname
OUTPUT_VARIABLE git_tags OUTPUT_VARIABLE git_tags
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_STRIP_TRAILING_WHITESPACE
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
@@ -76,7 +80,7 @@ function(make_release_commit_and_tag)
endif() endif()
execute_process( execute_process(
COMMAND git log ${git_last_tag}.. "--pretty=format:* %h - %s [%aL]" COMMAND ${GIT_EXECUTABLE} log ${git_last_tag}.. "--pretty=format:* %h - %s [%aL]"
OUTPUT_VARIABLE release_log OUTPUT_VARIABLE release_log
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_STRIP_TRAILING_WHITESPACE
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
@@ -86,17 +90,17 @@ function(make_release_commit_and_tag)
if(TAG_RELEASE STREQUAL UNDO) if(TAG_RELEASE STREQUAL UNDO)
execute_process( execute_process(
COMMAND git tag -d ${git_last_tag} COMMAND ${GIT_EXECUTABLE} tag -d ${git_last_tag}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
) )
execute_process( execute_process(
COMMAND git reset HEAD~1 COMMAND ${GIT_EXECUTABLE} reset HEAD~1
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
) )
execute_process( execute_process(
COMMAND git checkout HEAD CHANGELOG.md COMMAND ${GIT_EXECUTABLE} checkout HEAD CHANGELOG.md
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
) )
@@ -208,37 +212,45 @@ Ignore the following cmake error.
) )
execute_process( execute_process(
COMMAND git add CHANGELOG.md COMMAND ${GIT_EXECUTABLE} add CHANGELOG.md
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
) )
message(FATAL_ERROR " # Make the release commit.
Release prepared. execute_process(
COMMAND ${GIT_EXECUTABLE} commit -m "release ${new_tag}" --signoff -S
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
Edit CHANGELOG.md to remove any non-user-facing commits, and optionally add any # Make release tag.
release notes.
Run the following commands to commit the change: execute_process(
COMMAND ${GIT_EXECUTABLE} tag -s -m${new_tag} ${new_tag}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
git commit -m'release ${new_tag}' --signoff -S message(FATAL_ERROR [=[
git tag -s -m'${new_tag}' ${new_tag}
Release commit and tag generated.
**** IF YOU ARE SURE YOU WANT TO RELEASE ****
Run the following commands to push the release commit and tag:
git push
git push --tags
**** TO UNDO THE RELEASE ****
To rollback these changes, run this command: To rollback these changes, run this command:
cmake .. -DTAG_RELEASE=UNDO cmake .. -DTAG_RELEASE=UNDO
==== IF YOU ARE SURE YOU WANT TO RELEASE, THIS **CANNOT** BE REVERSED ==== Ignore the "configuration incomplete" message following, this mode does not
Run the following to push the release commit and tag:
git push
git push --tags
Ignore the 'configuration incomplete' message following, this mode does not
build anything. build anything.
") ]=])
endfunction() endfunction()
make_release_commit_and_tag() make_release_commit_and_tag()

View File

@@ -30,6 +30,7 @@ option(VBAM_STATIC "Try to link all libraries statically" ${VBAM_STATIC_DEFAULT}
if(VBAM_STATIC) if(VBAM_STATIC)
set(SDL2_STATIC ON) set(SDL2_STATIC ON)
set(SFML_STATIC_LIBRARIES ON)
set(FFMPEG_STATIC ON) set(FFMPEG_STATIC ON)
set(OPENAL_STATIC ON) set(OPENAL_STATIC ON)
set_property(GLOBAL PROPERTY LINK_SEARCH_START_STATIC ON) set_property(GLOBAL PROPERTY LINK_SEARCH_START_STATIC ON)
@@ -67,8 +68,21 @@ endif()
find_package(PkgConfig) find_package(PkgConfig)
# Link / SFML # Link / SFML
if(NOT TRANSLATIONS_ONLY) if(TRANSLATIONS_ONLY)
set(ENABLE_LINK_DEFAULT ON) set(ENABLE_LINK_DEFAULT OFF)
else()
find_package(SFML 2.4 COMPONENTS network system)
if(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
if(SFML_STATIC_LIBRARIES AND SFML_NETWORK_LIBRARY_STATIC_DEBUG AND SFML_SYSTEM_LIBRARY_STATIC_DEBUG)
set(SFML_LIBRARIES ${SFML_NETWORK_LIBRARY_STATIC_DEBUG} ${SFML_SYSTEM_LIBRARY_STATIC_DEBUG})
elseif(SFML_NETWORK_LIBRARY_DYNAMIC_DEBUG AND SFML_SYSTEM_LIBRARY_DYNAMIC_DEBUG)
set(SFML_LIBRARIES ${SFML_NETWORK_LIBRARY_DYNAMIC_DEBUG} ${SFML_SYSTEM_LIBRARY_DYNAMIC_DEBUG})
endif()
endif()
set(ENABLE_LINK_DEFAULT OFF)
if(SFML_FOUND)
set(ENABLE_LINK_DEFAULT ON)
endif()
endif() endif()
option(ENABLE_LINK "Enable GBA linking functionality" ${ENABLE_LINK_DEFAULT}) option(ENABLE_LINK "Enable GBA linking functionality" ${ENABLE_LINK_DEFAULT})
@@ -77,7 +91,7 @@ set(FFMPEG_DEFAULT OFF)
set(FFMPEG_COMPONENTS AVCODEC AVFORMAT SWSCALE AVUTIL SWRESAMPLE) set(FFMPEG_COMPONENTS AVCODEC AVFORMAT SWSCALE AVUTIL SWRESAMPLE)
set(FFMPEG_COMPONENT_VERSIONS AVCODEC>=58.18.100 AVFORMAT>=58.12.100 SWSCALE>=5.1.100 AVUTIL>=56.14.100 SWRESAMPLE>=3.1.100) set(FFMPEG_COMPONENT_VERSIONS AVCODEC>=58.18.100 AVFORMAT>=58.12.100 SWSCALE>=5.1.100 AVUTIL>=56.14.100 SWRESAMPLE>=3.1.100)
if(NOT TRANSLATIONS_ONLY AND (NOT DEFINED ENABLE_FFMPEG OR ENABLE_FFMPEG) AND (NOT (X86 AND MINGW))) if(NOT TRANSLATIONS_ONLY AND NOT DEFINED ENABLE_FFMPEG OR ENABLE_FFMPEG)
set(FFMPEG_DEFAULT ON) set(FFMPEG_DEFAULT ON)
find_package(FFmpeg COMPONENTS ${FFMPEG_COMPONENTS}) find_package(FFmpeg COMPONENTS ${FFMPEG_COMPONENTS})

View File

@@ -10,28 +10,19 @@ if(NOT DEFINED VCPKG_TARGET_TRIPLET)
# Check if we are in an MSVC environment. # Check if we are in an MSVC environment.
find_program(cl_exe_path NAME cl.exe HINTS ENV PATH) find_program(cl_exe_path NAME cl.exe HINTS ENV PATH)
if(ENV{CXX} MATCHES "cl.exe$" OR cl_exe_path) if($ENV{CXX} MATCHES "cl.exe$" OR cl_exe_path)
# Infer the architecture from the LIB folders. # Infer the architecture from the LIB folders.
foreach(lib $ENV{LIB}) foreach(LIB $ENV{LIB})
if(lib MATCHES "x64$") if(${LIB} MATCHES "x64$")
set(VBAM_VCPKG_PLATFORM "x64-windows-static") set(VBAM_VCPKG_PLATFORM "x64-windows-static")
break() break()
endif() endif()
if(lib MATCHES "x86$") if(${LIB} MATCHES "x86$")
set(VBAM_VCPKG_PLATFORM "x86-windows-static") set(VBAM_VCPKG_PLATFORM "x86-windows-static")
break() break()
endif() endif()
if(lib MATCHES "ARM64$") if(${LIB} MATCHES "ARM64$")
set(VBAM_VCPKG_PLATFORM "arm64-windows-static") set(VBAM_VCPKG_PLATFORM "arm64-windows-static")
foreach(path $ENV{PATH})
if(path MATCHES "[Hh]ost[Xx]64")
set(VCPKG_HOST_TRIPLET "x64-windows-static" CACHE STRING "Vcpkg host triplet" FORCE)
set(VCPKG_USE_HOST_TOOLS ON CACHE BOOL "Use vcpkg host tools" FORCE)
break()
endif()
endforeach()
break() break()
endif() endif()
endforeach() endforeach()
@@ -60,28 +51,6 @@ if(NOT DEFINED VCPKG_TARGET_TRIPLET)
message(STATUS "Inferred VCPKG_TARGET_TRIPLET=${VCPKG_TARGET_TRIPLET}") message(STATUS "Inferred VCPKG_TARGET_TRIPLET=${VCPKG_TARGET_TRIPLET}")
endif() endif()
function(vcpkg_seconds)
if(CMAKE_HOST_SYSTEM MATCHES Windows OR ((NOT DEFINED CMAKE_HOST_SYSTEM) AND WIN32))
execute_process(
COMMAND cmd /c echo %TIME:~0,8%
OUTPUT_VARIABLE time
)
else()
execute_process(
COMMAND date +%H:%M:%S
OUTPUT_VARIABLE time
)
endif()
string(SUBSTRING "${time}" 0 2 hours)
string(SUBSTRING "${time}" 3 2 minutes)
string(SUBSTRING "${time}" 6 2 secs)
math(EXPR seconds "(${hours} * 60 * 60) + (${minutes} * 60) + ${secs}")
set(seconds ${seconds} PARENT_SCOPE)
endfunction()
function(vcpkg_check_git_status git_status) function(vcpkg_check_git_status git_status)
# The VS vcpkg component cannot be written to without elevation. # The VS vcpkg component cannot be written to without elevation.
if(NOT git_status EQUAL 0 AND NOT VCPKG_ROOT MATCHES "Visual Studio") if(NOT git_status EQUAL 0 AND NOT VCPKG_ROOT MATCHES "Visual Studio")
@@ -502,7 +471,7 @@ function(vcpkg_set_toolchain)
# Install core deps. # Install core deps.
execute_process( execute_process(
COMMAND ${vcpkg_exe} --triplet ${VCPKG_TARGET_TRIPLET} install ${pkg} COMMAND ${vcpkg_exe} install ${VCPKG_DEPS_QUALIFIED}
WORKING_DIRECTORY ${VCPKG_ROOT} WORKING_DIRECTORY ${VCPKG_ROOT}
) )
@@ -544,7 +513,7 @@ function(vcpkg_set_toolchain)
set(dep_qualified "${dep}:${VCPKG_TARGET_TRIPLET}") set(dep_qualified "${dep}:${VCPKG_TARGET_TRIPLET}")
execute_process( execute_process(
COMMAND --triplet ${VCPKG_TARGET_TRIPLET} ${vcpkg_exe} install ${dep} COMMAND ${vcpkg_exe} install ${dep_qualified}
WORKING_DIRECTORY ${VCPKG_ROOT} WORKING_DIRECTORY ${VCPKG_ROOT}
) )
@@ -576,4 +545,14 @@ endfunction()
vcpkg_set_toolchain() vcpkg_set_toolchain()
# Make vcpkg use debug libs for RelWithDebInfo
set(orig_build_type ${CMAKE_BUILD_TYPE})
if(CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo)
set(CMAKE_BUILD_TYPE Debug)
endif()
include(${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake) include(${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake)
set(CMAKE_BUILD_TYPE ${orig_build_type})
unset(orig_build_type)

View File

@@ -5,16 +5,10 @@ endif()
if(UPSTREAM_RELEASE) if(UPSTREAM_RELEASE)
if(X86_64) if(X86_64)
# Require and optimize for Core2 level support, tune for generic. # Require and optimize for Core2 level support, tune for generic.
if(APPLE) add_compile_options(-march=core2 -mtune=generic)
add_compile_options(-march=core2 -mtune=skylake)
else()
add_compile_options(-march=core2 -mtune=generic)
endif()
elseif(X86_32) elseif(X86_32)
# Optimize for pentiumi3 and tune for generic for Windows XP builds. # Optimize for pentium-mmx and tune for generic for older builds.
set(WINXP TRUE) add_compile_options(-march=pentium-mmx -mtune=generic)
add_compile_options(-march=pentium3 -mtune=generic)
add_compile_definitions(-DWINXP)
endif() endif()
endif() endif()
@@ -52,9 +46,9 @@ if(NOT ENABLE_ASM) # inline asm is not allowed with -fPIC
endif() endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug") if(CMAKE_BUILD_TYPE STREQUAL "Debug")
add_compile_options(-ggdb3 -fno-omit-frame-pointer -Wall -Wextra) add_compile_options(-ggdb3 -Og -fno-omit-frame-pointer -Wall -Wextra)
else() else()
add_compile_options(-O3 -ffast-math -fomit-frame-pointer) add_compile_options(-Ofast -fomit-frame-pointer)
endif() endif()
# for some reason this is necessary # for some reason this is necessary

View File

@@ -3,8 +3,8 @@ if (NOT MINGW)
endif() endif()
# this has to run after the toolchain is initialized. # this has to run after the toolchain is initialized.
include_directories("${CMAKE_SOURCE_DIR}/win32-deps/mingw-include") include_directories("${CMAKE_SOURCE_DIR}/dependencies/mingw-include")
include_directories("${CMAKE_SOURCE_DIR}/win32-deps/mingw-xaudio/include") include_directories("${CMAKE_SOURCE_DIR}/dependencies/mingw-xaudio/include")
# Add Winsock as the last library linked because of broken link precedence. # Add Winsock as the last library linked because of broken link precedence.
set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} -lws2_32") set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} -lws2_32")

View File

@@ -10,7 +10,7 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
endif() endif()
endif() endif()
include_directories("${CMAKE_SOURCE_DIR}/win32-deps/msvc") include_directories("${CMAKE_SOURCE_DIR}/dependencies/msvc")
add_compile_definitions( add_compile_definitions(
_FORCENAMELESSUNION _FORCENAMELESSUNION
@@ -68,8 +68,6 @@ if(CMAKE_VERSION VERSION_LESS "3.25")
endif() endif()
endif() endif()
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:/std:c++14>)
set(CMAKE_RC_FLAGS "-c65001 /DWIN32" CACHE STRING "" FORCE) set(CMAKE_RC_FLAGS "-c65001 /DWIN32" CACHE STRING "" FORCE)
# We need to explicitly set all of these to override the CMake defaults. # We need to explicitly set all of these to override the CMake defaults.

View File

@@ -16,7 +16,7 @@ Ignore the following cmake error.
# Get last tag. # Get last tag.
execute_process( execute_process(
COMMAND git tag --sort=-v:refname COMMAND ${GIT_EXECUTABLE} tag --sort=-v:refname
OUTPUT_VARIABLE git_tags OUTPUT_VARIABLE git_tags
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_STRIP_TRAILING_WHITESPACE
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
@@ -43,7 +43,7 @@ Ignore the following cmake error.
# Clone repo. # Clone repo.
execute_process( execute_process(
COMMAND git clone git@github.com:visualboyadvance-m/visualboyadvance-m.github.io web-data COMMAND ${GIT_EXECUTABLE} clone git@github.com:visualboyadvance-m/visualboyadvance-m.github.io web-data
WORKING_DIRECTORY ${CMAKE_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
) )
@@ -103,21 +103,21 @@ Ignore the following cmake error.
) )
execute_process( execute_process(
COMMAND git add appcast.xml COMMAND ${GIT_EXECUTABLE} add appcast.xml
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/web-data WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/web-data
) )
# Commit the change. # Commit the change.
execute_process( execute_process(
COMMAND git commit -m "release ${new_tag}" --signoff -S COMMAND ${GIT_EXECUTABLE} commit -m "release ${new_tag}" --signoff -S
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/web-data WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/web-data
) )
# Make release tag. # Make release tag.
execute_process( execute_process(
COMMAND git tag -s -m${new_tag} ${new_tag} COMMAND ${GIT_EXECUTABLE} tag -s -m${new_tag} ${new_tag}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/web-data WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/web-data
) )

View File

@@ -2,7 +2,7 @@ with import <nixpkgs> {};
stdenv.mkDerivation { stdenv.mkDerivation {
name = "visualboyadvance-m"; name = "visualboyadvance-m";
buildInputs = if stdenv.isDarwin then buildInputs = if stdenv.isDarwin then
[ ninja cmake nasm faudio gettext libintl libtiff pkg-config zip zlib openal ffmpeg wxGTK32 SDL2 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 gcc nasm faudio gettext libintl pkg-config zip sfml zlib openal ffmpeg wxGTK32 SDL2 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 ]
else else
[ ninja cmake gcc clang llvm llvmPackages.libcxx nasm faudio gettext libintl libtiff pkg-config zip zlib openal ffmpeg wxGTK32 libGL libGLU glfw SDL2 gtk3-x11 pcre pcre2 util-linuxMinimal libselinux libsepol libthai libdatrie xorg.libXdmcp xorg.libXtst libxkbcommon libepoxy dbus at-spi2-core ]; [ ninja cmake gcc nasm faudio gettext libintl pkg-config zip sfml zlib openal ffmpeg wxGTK32 libGL libGLU glfw SDL2 gtk3-x11 pcre pcre2 util-linuxMinimal libselinux libsepol libthai libdatrie xorg.libXdmcp xorg.libXtst libxkbcommon epoxy dbus at-spi2-core ];
} }

1
dependencies Submodule

Submodule dependencies added at e8ce758a98

View File

@@ -191,7 +191,7 @@ freebsd_installdeps() {
check sudo pkg update check sudo pkg update
pkgs="llvm-devel cmake ccache nasm ffmpeg gettext-tools gettext pkgconf sdl2 wx31-gtk3 iconv zip ninja" pkgs="llvm-devel cmake ccache nasm ffmpeg gettext-tools gettext pkgconf sdl2 sfml wx31-gtk3 iconv zip ninja"
[ -n "$ENABLE_FFMPEG" ] && pkgs="$pkgs ffmpeg" [ -n "$ENABLE_FFMPEG" ] && pkgs="$pkgs ffmpeg"
@@ -318,6 +318,12 @@ debian_installdeps() {
if [ -z "$target" ]; then if [ -z "$target" ]; then
sudo apt-get -qq -y update sudo apt-get -qq -y update
sfml_libs=
for lib in graphics window network; do
sfml_libs="$sfml_libs $(apt-cache search "libsfml-$lib" | sed 's/ - .*//' | sort -r | head -1)"
done
glew_lib=$(apt-cache search libglew | grep '^libglew[0-9]' | sed 's/ - .*//' | sort -r | head -1) glew_lib=$(apt-cache search libglew | grep '^libglew[0-9]' | sed 's/ - .*//' | sort -r | head -1)
sdl_lib=$(apt-cache search '^libsdl2-2.0' | sed 's/ - .*//' | sort -r | head -1) sdl_lib=$(apt-cache search '^libsdl2-2.0' | sed 's/ - .*//' | sort -r | head -1)
@@ -344,7 +350,7 @@ debian_installdeps() {
;; ;;
esac esac
pkgs="build-essential g++ nasm cmake ccache gettext zlib1g-dev libgl1-mesa-dev libgettextpo-dev libsdl2-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" pkgs="build-essential g++ nasm cmake ccache gettext zlib1g-dev libgl1-mesa-dev libgettextpo-dev libsdl2-dev $sdl_lib libglu1-mesa-dev libglu1-mesa libgles2-mesa-dev libsfml-dev $sfml_libs $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" [ -n "$ENABLE_FFMPEG" ] && pkgs="$pkgs libavcodec-dev libavformat-dev libswscale-dev libavutil-dev $libswresample_dev"
@@ -395,7 +401,7 @@ debian_installdeps() {
fi fi
fi fi
deps="gcc zlib ffmpeg gettext sdl2 openal wxwidgets openal" deps="gcc zlib ffmpeg gettext sdl2 sfml openal wxwidgets openal"
[ -n "$ENABLE_FFMPEG" ] && deps="$deps ffmpeg" [ -n "$ENABLE_FFMPEG" ] && deps="$deps ffmpeg"
set -- set --
@@ -492,7 +498,7 @@ fedora_installdeps() {
# this is sometimes necessary for rawhide # this is sometimes necessary for rawhide
set -- --exclude='glibc32*' set -- --exclude='glibc32*'
fi fi
for pkg in zlib-devel mesa-libGL-devel ffmpeg-devel gettext-devel SDL2-devel openal-soft-devel wxGTK-devel gtk3-devel; do for pkg in zlib-devel mesa-libGL-devel ffmpeg-devel gettext-devel SDL2-devel SFML-devel openal-soft-devel wxGTK-devel gtk3-devel; do
case $pkg in case $pkg in
*ffmpeg*) *ffmpeg*)
[ -z "$ENABLE_FFMPEG" ] && continue [ -z "$ENABLE_FFMPEG" ] && continue
@@ -591,6 +597,8 @@ fedora_installdeps() {
# get the necessary win32 headers # get the necessary win32 headers
git submodule update --init --remote --recursive git submodule update --init --remote --recursive
warning='SFML is required for LINK support, Fedora does not currently have a MinGW SFML package, if you want LINK support you will need to install it manually'
fi fi
[ -z "$rpms_installed" ] && check sudo dnf -y --nogpgcheck --best --allowerasing install "$@" [ -z "$rpms_installed" ] && check sudo dnf -y --nogpgcheck --best --allowerasing install "$@"
@@ -676,6 +684,8 @@ rhel_installdeps() {
set -- --exclude='glibc32*' set -- --exclude='glibc32*'
fi fi
warning='RHEL does not currently have SFML packages, LINK support will be disabled'
for pkg in zlib-devel mesa-libGL-devel ffmpeg-devel gettext-devel SDL2-devel openal-soft-devel wxGTK3-devel gtk3-devel; do for pkg in zlib-devel mesa-libGL-devel ffmpeg-devel gettext-devel SDL2-devel openal-soft-devel wxGTK3-devel gtk3-devel; do
case $pkg in case $pkg in
*ffmpeg*) *ffmpeg*)
@@ -767,6 +777,8 @@ rhel_installdeps() {
# get the necessary win32 headers # get the necessary win32 headers
git submodule update --init --remote --recursive git submodule update --init --remote --recursive
warning='SFML is required for LINK support, RHEL/EPEL does not currently have a MinGW SFML package, if you want LINK support you will need to install it manually'
fi fi
[ -z "$rpms_installed" ] && check sudo yum -y install "$@" [ -z "$rpms_installed" ] && check sudo yum -y install "$@"
@@ -785,12 +797,14 @@ suse_installdeps() {
check_cross check_cross
installing installing
tools="make cmake ccache nasm gettext-tools pkg-config ccache zip ninja" tools="make cmake ccache nasm gettext-tools pkg-config ccache zip sfml2-devel ninja"
libs="gcc gcc-c++ libSDL2-devel wxGTK3-3_2-devel openal-soft-devel ffmpeg-7-libavcodec-devel ffmpeg-7-libavdevice-devel ffmpeg-7-libavfilter-devel ffmpeg-7-libavformat-devel ffmpeg-7-libavutil-devel ffmpeg-7-libpostproc-devel ffmpeg-7-libswresample-devel ffmpeg-7-libswscale-devel" libs="gcc gcc-c++ libSDL2-devel wxWidgets-3_0-devel openal-soft-devel" # ffmpeg-devel
# ffmpeg requires packman repos
if [ "$target" = m32 ]; then if [ "$target" = m32 ]; then
error '32 bit cross builds are no longer supported on OpenSUSE' libs=$(echo "$libs" | sed -E 's/([^ ]) ([^ ])/\1-32bit \2/g; s/$/-32bit/;')
fi fi
check sudo zypper in -y $tools $libs check sudo zypper in -y $tools $libs
@@ -854,7 +868,7 @@ archlinux_installdeps() {
$pacman -Q gtk3-classic >/dev/null 2>&1 && gtk=gtk3-classic $pacman -Q gtk3-classic >/dev/null 2>&1 && gtk=gtk3-classic
libs="zlib mesa gettext sdl2 wxgtk3 $gtk openal" libs="zlib mesa gettext sdl2 wxgtk3 $gtk sfml openal"
[ -n "$ENABLE_FFMPEG" ] && libs="$libs ffmpeg" [ -n "$ENABLE_FFMPEG" ] && libs="$libs ffmpeg"
@@ -870,7 +884,7 @@ archlinux_installdeps() {
else else
# try to build 32 bit binaries # try to build 32 bit binaries
# lib32-ffmpeg is in AUR # lib32-sfml and lib32-ffmpeg are in AUR
archlinux_require_yaourt archlinux_require_yaourt
# enable multilib repos if not enabled # enable multilib repos if not enabled
@@ -964,6 +978,8 @@ EOF
# get the necessary win32 headers # get the necessary win32 headers
git submodule update --init --remote --recursive git submodule update --init --remote --recursive
warning 'SFML is required for LINK support, the SFML package in AUR is currently broken, if you want LINK support you will need to install it manually'
fi fi
build_instructions build_instructions
@@ -1026,12 +1042,13 @@ solus_installdeps() {
done done
else else
# no 32bit versions of these # no 32bit versions of these
set -- "$@" ffmpeg-devel set -- "$@" SFML-devel ffmpeg-devel
fi fi
check sudo eopkg -y install "$@" check sudo eopkg -y install "$@"
if [ -n "$amd64" -a "$target" = m32 ]; then if [ -n "$amd64" -a "$target" = m32 ]; then
warning 'SFML is required for LINK support, there is no 32 bit SFML package in Solus currently, if you want LINK support you will need to install it manually'
warning 'ffmpeg is required for game recording, there is no 32 bit ffmpeg package in Solus currently, you may wish to install it manually' warning 'ffmpeg is required for game recording, there is no 32 bit ffmpeg package in Solus currently, you may wish to install it manually'
fi fi
@@ -1053,6 +1070,7 @@ gentoo_installdeps() {
dev-util/ccache \ dev-util/ccache \
sys-devel/binutils \ sys-devel/binutils \
media-libs/libsdl2 \ media-libs/libsdl2 \
media-libs/libsfml \
media-libs/openal \ media-libs/openal \
x11-libs/wxGTK:$wx_slot \ x11-libs/wxGTK:$wx_slot \
sys-libs/zlib \ sys-libs/zlib \
@@ -1070,7 +1088,7 @@ gentoo_installdeps() {
alpine_installdeps() { alpine_installdeps() {
installing installing
check sudo apk add cmake ninja g++ ccache nasm gettext-dev zlib-dev mesa-dev sdl2-dev glu-dev wxwidgets-dev gtk+3.0-dev zip check sudo apk add cmake ninja g++ ccache nasm gettext-dev zlib-dev mesa-dev sdl2-dev glu-dev sfml-dev wxwidgets-dev gtk+3.0-dev zip
build_instructions build_instructions
} }
@@ -1100,12 +1118,9 @@ windows_installdeps() {
*i686*) *i686*)
pkgs="$pkgs nasm" pkgs="$pkgs nasm"
;; ;;
*)
pkgs="$pkgs FAudio"
;;
esac esac
pkgs="$pkgs SDL2 wxWidgets3.2 zlib binutils cmake crt-git headers-git make pkgconf tools-git windows-default-manifest libmangle-git ninja gdb ccache openal" pkgs="$pkgs SDL2 sfml FAudio wxWidgets3.2 zlib binutils cmake crt-git headers-git make pkgconf tools-git windows-default-manifest libmangle-git ninja gdb ccache openal"
case "$target" in case "$target" in
*x86_64) *x86_64)
@@ -1177,10 +1192,15 @@ brew_installdeps() {
check brew -v update check brew -v update
brews="nasm cmake ccache gettext libtiff pkg-config sdl2 wxwidgets faudio ccache ninja zlib" brews="nasm cmake ccache gettext pkg-config sdl2 wxwidgets faudio ccache ninja zlib"
[ -n "$ENABLE_FFMPEG" ] && brews="$brews ffmpeg" [ -n "$ENABLE_FFMPEG" ] && brews="$brews ffmpeg"
# sfml brew currently broken in the travis mac environment
# if [ -z "$TRAVIS" ]; then
brews="$brews sfml"
# fi
# This is necessary for the GitHub Actions CI: # This is necessary for the GitHub Actions CI:
brew -v install python brew -v install python
brew link --overwrite python brew link --overwrite python
@@ -1203,7 +1223,7 @@ macports_installdeps() {
check sudo port -v selfupdate check sudo port -v selfupdate
ports="cmake ccache nasm gettext pkgconfig libsdl2 wxWidgets-3.0 libiconv ninja" ports="cmake ccache nasm gettext pkgconfig libsdl2 sfml wxWidgets-3.0 libiconv ninja"
[ -n "$ENABLE_FFMPEG" ] && ports="$ports ffmpeg" [ -n "$ENABLE_FFMPEG" ] && ports="$ports ffmpeg"
@@ -1219,7 +1239,7 @@ fink_installdeps() {
check sudo fink -vy selfupdate check sudo fink -vy selfupdate
pkgs="cmake ccache nasm libgettext8-dev gettext-tools pkgconfig sdl2 wxwidgets300-osxcocoa libiconv-dev ccache ninja" pkgs="cmake ccache nasm libgettext8-dev gettext-tools pkgconfig sdl2 wxwidgets300-osxcocoa libiconv-dev sfml24-dev ccache ninja"
[ -n "$ENABLE_FFMPEG" ] && pkgs="$pkgs ffmpeg" [ -n "$ENABLE_FFMPEG" ] && pkgs="$pkgs ffmpeg"

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

3888
po/wxvbam/zh-Hans.po Normal file

File diff suppressed because it is too large Load Diff

3706
po/wxvbam/zh.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -19,6 +19,8 @@ parts:
cmake-generator: Ninja cmake-generator: Ninja
stage-packages: stage-packages:
- libsdl2-2.0-0 - libsdl2-2.0-0
- libsfml-network2.5
- libsfml-system2.5
- libnotify4 - libnotify4
- libsm6 - libsm6
- libopenal1 - libopenal1
@@ -44,6 +46,7 @@ parts:
- zip - zip
- libnotify-dev - libnotify-dev
- libsdl2-dev - libsdl2-dev
- libsfml-dev
- libgtk-3-dev - libgtk-3-dev
- libopenal-dev - libopenal-dev
- libwxgtk3.0-gtk3-dev - libwxgtk3.0-gtk3-dev

View File

@@ -1,13 +1,5 @@
add_library(vbam-components-filters OBJECT) add_library(vbam-components-filters OBJECT)
unset(extra_src)
if(WINXP)
list(APPEND extra_src
${CMAKE_SOURCE_DIR}/third_party/quake3-sqrt/quake3-sqrt.h
)
target_include_directories(vbam-components-filters PRIVATE ${CMAKE_SOURCE_DIR}/third_party/quake3-sqrt)
endif()
target_sources(vbam-components-filters target_sources(vbam-components-filters
PRIVATE PRIVATE
internal/2xSaI.cpp internal/2xSaI.cpp
@@ -25,7 +17,6 @@ target_sources(vbam-components-filters
internal/xBRZ/xbrz_config.h internal/xBRZ/xbrz_config.h
internal/xBRZ/xbrz_tools.h internal/xBRZ/xbrz_tools.h
internal/xbrzfilter.cpp internal/xbrzfilter.cpp
${extra_src}
PUBLIC PUBLIC
filters.h filters.h

View File

@@ -21,10 +21,6 @@
#include <cmath> //std::sqrt #include <cmath> //std::sqrt
#include "xbrz_tools.h" #include "xbrz_tools.h"
#ifdef WINXP
#include "quake3-sqrt.h"
#endif
// some gcc versions lie about having this C++17 feature // some gcc versions lie about having this C++17 feature
#define static_assert(x) static_assert(x, "assertion failed") #define static_assert(x) static_assert(x, "assertion failed")
@@ -70,9 +66,7 @@ uint32_t gradientARGB(uint32_t pixFront, uint32_t pixBack) //find intermediate c
inline double fastSqrt(double n) inline double fastSqrt(double n)
{ {
#ifdef WINXP #if (defined(__GNUC__) || defined(__clang__)) && (defined(__x86_64__) || defined(__i386__))
return quake3_sqrt((float)n);
#elif (defined(__GNUC__) || defined(__clang__)) && (defined(__x86_64__) || defined(__i386__))
__asm__ ("fsqrt" : "+t" (n)); __asm__ ("fsqrt" : "+t" (n));
return n; return n;
#elif defined(_MSC_VER) && defined(_M_IX86) #elif defined(_MSC_VER) && defined(_M_IX86)

View File

@@ -35,7 +35,6 @@ target_sources(vbam-core-base
version.cpp version.cpp
PUBLIC PUBLIC
check.h
array.h array.h
file_util.h file_util.h
image_util.h image_util.h
@@ -60,5 +59,3 @@ target_link_libraries(vbam-core-base
PRIVATE vbam-fex stb-image PRIVATE vbam-fex stb-image
PUBLIC ${ZLIB_LIBRARY} PUBLIC ${ZLIB_LIBRARY}
) )
add_subdirectory(test)

View File

@@ -1,58 +0,0 @@
#ifndef VBAM_CORE_BASE_CHECK_H_
#define VBAM_CORE_BASE_CHECK_H_
// This header defines a number of macros for checking conditions and crashing
// the program if they are not met.
// * VBAM_CHECK(condition) - crashes the program if the condition is not met.
// * VBAM_NOTREACHED() - crashes the program if this line of code is reached.
// In release builds, this macro also tells the compiler that this code path
// is unreachable, which can help the compiler generate better code.
// * VBAM_STRINGIFY(x) - converts the argument to a string literal.
// While a number of other macros are defined in this file, they are not
// intended for general use and should be avoided.
#if defined(__GNUC__) || defined(__clang__)
// GCC/Clang.
#define VBAM_IMMEDIATE_CRASH_DETAIL() __builtin_trap()
#define VBAM_INTRINSIC_UNREACHABLE_DETAIL() __builtin_unreachable()
#elif defined(_MSC_VER) // defined(__GNUC__) || defined(__clang__)
// MSVC.
#define VBAM_IMMEDIATE_CRASH_DETAIL() __debugbreak()
#define VBAM_INTRINSIC_UNREACHABLE_DETAIL() __assume(0)
#else // defined(__GNUC__) || defined(__clang__)
#error "Unsupported compiler"
#endif // defined(__GNUC__) || defined(__clang__)
#define VBAM_STRINGIFY_DETAIL(x) #x
#define VBAM_STRINGIFY(x) VBAM_STRINGIFY_DETAIL(x)
#define VBAM_REQUIRE_SEMICOLON_DETAIL() \
static_assert(true, "Require a semicolon after macros invocation.")
#define VBAM_CHECK(condition) \
if (!(condition)) { \
fputs("CHECK failed at " __FILE__ ":" VBAM_STRINGIFY(__LINE__) ": " #condition "\n", \
stderr); \
VBAM_IMMEDIATE_CRASH_DETAIL(); \
} \
VBAM_REQUIRE_SEMICOLON_DETAIL()
#if defined(DEBUG)
#define VBAM_NOTREACHED() \
fputs("NOTREACHED code reached at " __FILE__ ":" VBAM_STRINGIFY(__LINE__) "\n", stderr); \
VBAM_IMMEDIATE_CRASH_DETAIL()
#else // defined(DEBUG)
#define VBAM_NOTREACHED() VBAM_INTRINSIC_UNREACHABLE_DETAIL()
#endif // defined(DEBUG)
#endif // VBAM_CORE_BASE_CHECK_H_

View File

@@ -59,7 +59,6 @@ extern struct CoreOptions {
bool speedHack = false; bool speedHack = false;
bool speedup = false; bool speedup = false;
bool speedup_throttle_frame_skip = false; bool speedup_throttle_frame_skip = false;
bool speedup_mute = true;
int cheatsEnabled = 1; int cheatsEnabled = 1;
int cpuDisableSfx = 0; int cpuDisableSfx = 0;
int cpuSaveType = 0; int cpuSaveType = 0;
@@ -70,7 +69,7 @@ extern struct CoreOptions {
int skipSaveGameBattery = 1; int skipSaveGameBattery = 1;
int skipSaveGameCheats = 0; int skipSaveGameCheats = 0;
int useBios = 0; int useBios = 0;
int gbPrinterEnabled = 0; int winGbPrinterEnabled = 1;
uint32_t speedup_throttle = 100; uint32_t speedup_throttle = 100;
uint32_t speedup_frame_skip = 9; uint32_t speedup_frame_skip = 9;
uint32_t throttle = 100; uint32_t throttle = 100;
@@ -126,4 +125,4 @@ extern int systemSpeed;
#define SYSTEM_SAVE_UPDATED 30 #define SYSTEM_SAVE_UPDATED 30
#define SYSTEM_SAVE_NOT_UPDATED 0 #define SYSTEM_SAVE_NOT_UPDATED 0
#endif // VBAM_CORE_BASE_SYSTEM_H_ #endif // VBAM_CORE_BASE_SYSTEM_H_

View File

@@ -1,12 +0,0 @@
# This defines the `vbam-core-base-test` library.
if(NOT BUILD_TESTING)
return()
endif()
add_library(vbam-core-base-test
INTERFACE
notreached.h)
target_link_libraries(vbam-core-base-test
INTERFACE GTest::gtest)

View File

@@ -1,22 +0,0 @@
#ifndef VBAM_CORE_BASE_TEST_NOTREACHED_H_
#define VBAM_CORE_BASE_TEST_NOTREACHED_H_
#include <gtest/gtest.h>
#if defined(DEBUG)
#define VBAM_EXPECT_NOTREACHED(statement) EXPECT_DEATH(statement, "NOTREACHED")
#else // defined(DEBUG)
// There is no way to test this in release builds as the compiler might optimize
// this code path away. Eat the statement to avoid unused variable warnings.
#define VBAM_EXPECT_NOTREACHED(statement) \
if constexpr (false) { \
statement; \
} \
static_assert(true, "")
#endif // defined(DEBUG)
#endif // VBAM_CORE_BASE_TEST_NOTREACHED_H_

View File

@@ -1,13 +1,13 @@
#include "core/gb/gb.h" #include "core/gb/gb.h"
#include <array> #include <array>
#include <cassert>
#include <cmath> #include <cmath>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <vector> #include <vector>
#include "core/base/check.h"
#include "core/base/file_util.h" #include "core/base/file_util.h"
#include "core/base/message.h" #include "core/base/message.h"
#include "core/base/sizes.h" #include "core/base/sizes.h"
@@ -291,7 +291,8 @@ bool gbInitializeRom(size_t romSize) {
switch (g_gbCartData.validity()) { switch (g_gbCartData.validity()) {
case gbCartData::Validity::kValid: case gbCartData::Validity::kValid:
case gbCartData::Validity::kUninitialized: case gbCartData::Validity::kUninitialized:
VBAM_NOTREACHED(); // Unreachable.
assert(false);
break; break;
case gbCartData::Validity::kSizeTooSmall: case gbCartData::Validity::kSizeTooSmall:
systemMessage(MSG_UNSUPPORTED_ROM_SIZE, systemMessage(MSG_UNSUPPORTED_ROM_SIZE,
@@ -1416,7 +1417,7 @@ void gbWriteMemory(uint16_t address, uint8_t value)
EmuReseted = false; EmuReseted = false;
gbMemory[0xff02] = value; gbMemory[0xff02] = value;
if (gbSerialOn && (GetLinkMode() == LINK_GAMEBOY_IPC || GetLinkMode() == LINK_GAMEBOY_SOCKET if (gbSerialOn && (GetLinkMode() == LINK_GAMEBOY_IPC || GetLinkMode() == LINK_GAMEBOY_SOCKET
|| GetLinkMode() == LINK_DISCONNECTED || coreOptions.gbPrinterEnabled)) { || GetLinkMode() == LINK_DISCONNECTED || coreOptions.winGbPrinterEnabled)) {
gbSerialTicks = GBSERIAL_CLOCK_TICKS; gbSerialTicks = GBSERIAL_CLOCK_TICKS;
@@ -2969,13 +2970,8 @@ void gbReset()
inBios = true; inBios = true;
} else if (gbHardware & 0xa) { } else if (gbHardware & 0xa) {
// Set compatibility mode if it is a DMG ROM. // Set compatibility mode if it is a DMG ROM.
if (g_gbCartData.SupportsCGB()) { const uint8_t gbcFlag = g_gbCartData.SupportsCGB() ? 0x80 : 0x00;
// OPRI with bit 0 set to 0 = CGB mode. gbMemory[0xff6c] = 0xfe | gbcFlag;
gbMemory[0xff6c] = 0xfe;
} else {
// OPRI with bit 0 set to 1 = DMG mode.
gbMemory[0xff6c] = 0xff;
}
} }
gbLine99Ticks = 1; gbLine99Ticks = 1;

View File

@@ -2,8 +2,8 @@
#include <algorithm> #include <algorithm>
#include <array> #include <array>
#include <cassert>
#include "core/base/check.h"
#include "core/base/sizes.h" #include "core/base/sizes.h"
namespace { namespace {
@@ -62,7 +62,7 @@ char byte_to_char(uint8_t byte) {
} else if (byte < 16) { } else if (byte < 16) {
return 'A' + (byte - 10); return 'A' + (byte - 10);
} else { } else {
VBAM_NOTREACHED(); assert(false);
return '\0'; return '\0';
} }
} }
@@ -98,7 +98,7 @@ bool is_valid_manufacturer_code(const std::string& manufacturer_code) {
constexpr size_t kHeaderGlobalChecksumAdress = 0x14e; constexpr size_t kHeaderGlobalChecksumAdress = 0x14e;
uint16_t get_rom_checksum(const uint8_t* romData, size_t romDataSize) { uint16_t get_rom_checksum(const uint8_t* romData, size_t romDataSize) {
VBAM_CHECK(romData); assert(romData);
uint16_t checksum = 0; uint16_t checksum = 0;
for (size_t i = 0; i < romDataSize; i++) { for (size_t i = 0; i < romDataSize; i++) {
@@ -160,7 +160,7 @@ constexpr size_t kHeaderChecksumEndAdress = 0x14c;
} // namespace } // namespace
gbCartData::gbCartData(const uint8_t* romData, size_t romDataSize) { gbCartData::gbCartData(const uint8_t* romData, size_t romDataSize) {
VBAM_CHECK(romData); assert(romData);
if (romDataSize < sizeof(gbRomHeader)) { if (romDataSize < sizeof(gbRomHeader)) {
validity_ = Validity::kSizeTooSmall; validity_ = Validity::kSizeTooSmall;

View File

@@ -481,7 +481,7 @@ void gbaUpdateRomSize(int size)
if (size > romSize) { if (size > romSize) {
romSize = size; romSize = size;
uint8_t* tmp = (uint8_t*)realloc(g_rom, romSize); uint8_t* tmp = (uint8_t*)realloc(g_rom, SIZE_ROM);
g_rom = tmp; g_rom = tmp;
uint16_t* temp = (uint16_t*)(g_rom + ((romSize + 1) & ~1)); uint16_t* temp = (uint16_t*)(g_rom + ((romSize + 1) & ~1));
@@ -3845,8 +3845,6 @@ void CPULoop(int ticks)
bool turbo_button_pressed = (joy >> 10) & 1; bool turbo_button_pressed = (joy >> 10) & 1;
#ifndef __LIBRETRO__ #ifndef __LIBRETRO__
static uint32_t last_throttle; static uint32_t last_throttle;
static bool current_volume_saved = false;
static float current_volume;
if (turbo_button_pressed) { if (turbo_button_pressed) {
if (coreOptions.speedup_frame_skip) if (coreOptions.speedup_frame_skip)
@@ -3861,23 +3859,10 @@ void CPULoop(int ticks)
if (coreOptions.speedup_throttle_frame_skip) if (coreOptions.speedup_throttle_frame_skip)
framesToSkip += static_cast<int>(std::ceil(double(coreOptions.speedup_throttle) / 100.0) - 1); framesToSkip += static_cast<int>(std::ceil(double(coreOptions.speedup_throttle) / 100.0) - 1);
} }
if (coreOptions.speedup_mute && !current_volume_saved) {
current_volume = soundGetVolume();
current_volume_saved = true;
soundSetVolume(0);
}
} }
else { else if (speedup_throttle_set) {
if (current_volume_saved) { soundSetThrottle(DowncastU16(last_throttle));
soundSetVolume(current_volume); speedup_throttle_set = false;
current_volume_saved = false;
}
if (speedup_throttle_set) {
soundSetThrottle(DowncastU16(last_throttle));
speedup_throttle_set = false;
}
} }
#else #else
if (turbo_button_pressed) if (turbo_button_pressed)

View File

@@ -1822,16 +1822,6 @@ static INSN_REGPARM void thumbE0(uint32_t opcode)
busPrefetchCount = 0; busPrefetchCount = 0;
} }
static INSN_REGPARM void thumbE8(uint32_t opcode)
{
#ifdef GBA_LOGGING
// TODO: This is (erroneously) used by some Wii U VC ROMs. We should have a configuration
// toggle to enable the correct hardware behavior, which would be to call CPUUndefinedException.
if (systemVerbose & VERBOSE_UNDEFINED)
log("Undefined Wii U THUMB instruction %04x at %08x (ignored)\n", opcode, armNextPC - 2);
#endif
}
// BLL #offset (forward) // BLL #offset (forward)
static INSN_REGPARM void thumbF0(uint32_t opcode) static INSN_REGPARM void thumbF0(uint32_t opcode)
{ {
@@ -1989,7 +1979,7 @@ static insnfunc_t thumbInsnTable[1024] = {
thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0,
thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0,
thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0, thumbE0,
thumbE8, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, // E8 thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, // E8
thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI,
thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI,
thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI, thumbUI,

View File

@@ -26,7 +26,7 @@
#include <cstring> #include <cstring>
#include <string> #include <string>
#include "SFML/Network.hpp" #include <SFML/Network.hpp>
#include <libintl.h> #include <libintl.h>
#define _(x) gettext(x) #define _(x) gettext(x)
@@ -41,22 +41,17 @@
#define snprintf _snprintf #define snprintf _snprintf
#endif #endif
#ifdef UPDATE_REG
#undef UPDATE_REG
#endif
#define UPDATE_REG(address, value) WRITE16LE(((uint16_t*)&g_ioMem[address]), value) #define UPDATE_REG(address, value) WRITE16LE(((uint16_t*)&g_ioMem[address]), value)
static int vbaid = 0; static int vbaid = 0;
const char* MakeInstanceFilename(const char* Input) const char* MakeInstanceFilename(const char* Input)
{ {
if (vbaid == 0) { if (vbaid == 0)
return Input; return Input;
}
static char* result = NULL; static char* result = NULL;
if (result != NULL) { if (result != NULL)
free(result); free(result);
}
result = (char*)malloc(strlen(Input) + 3); result = (char*)malloc(strlen(Input) + 3);
char* p = strrchr((char*)Input, '.'); char* p = strrchr((char*)Input, '.');
@@ -275,7 +270,7 @@ class RFUServer {
public: public:
sf::TcpSocket tcpsocket[5]; sf::TcpSocket tcpsocket[5];
sf::IpAddress udpaddr[5] = { sf::IpAddress{0}, sf::IpAddress{0}, sf::IpAddress{0}, sf::IpAddress{0}, sf::IpAddress{0} }; sf::IpAddress udpaddr[5];
RFUServer(void); RFUServer(void);
sf::Packet& Serialize(sf::Packet& packet, int slave); sf::Packet& Serialize(sf::Packet& packet, int slave);
void DeSerialize(sf::Packet& packet, int slave); void DeSerialize(sf::Packet& packet, int slave);
@@ -288,7 +283,7 @@ class RFUClient {
int numbytes; int numbytes;
public: public:
sf::IpAddress serveraddr{0}; sf::IpAddress serveraddr;
unsigned short serverport; unsigned short serverport;
bool transferring; bool transferring;
RFUClient(void); RFUClient(void);
@@ -397,7 +392,7 @@ enum {
typedef struct { typedef struct {
sf::TcpSocket tcpsocket; sf::TcpSocket tcpsocket;
sf::TcpListener tcplistener; sf::TcpListener tcplistener;
uint16_t numslaves; int numslaves;
int connectedSlaves; int connectedSlaves;
int type; int type;
bool server; bool server;
@@ -417,7 +412,7 @@ class CableServer {
public: public:
sf::TcpSocket tcpsocket[4]; sf::TcpSocket tcpsocket[4];
sf::IpAddress udpaddr[4] = { sf::IpAddress{0}, sf::IpAddress{0}, sf::IpAddress{0}, sf::IpAddress{0} }; sf::IpAddress udpaddr[4];
CableServer(void); CableServer(void);
void Send(void); void Send(void);
void Recv(void); void Recv(void);
@@ -435,7 +430,7 @@ class CableClient {
int numbytes; int numbytes;
public: public:
sf::IpAddress serveraddr{0}; sf::IpAddress serveraddr;
unsigned short serverport; unsigned short serverport;
bool transferring; bool transferring;
CableClient(void); CableClient(void);
@@ -525,48 +520,33 @@ LinkMode GetLinkMode()
return LINK_DISCONNECTED; return LINK_DISCONNECTED;
} }
bool GetLinkServerHost(char* const host, size_t size) void GetLinkServerHost(char* const host, size_t size)
{ {
if (host == NULL || size == 0) { if (host == NULL || size == 0)
return false; return;
}
host[0] = '\0'; host[0] = '\0';
if (linkDriver && linkDriver->mode == LINK_GAMECUBE_DOLPHIN) { if (linkDriver && linkDriver->mode == LINK_GAMECUBE_DOLPHIN)
strncpy(host, joybusHostAddr.toString().c_str(), size); strncpy(host, joybusHostAddr.toString().c_str(), size);
} else if (lanlink.server) { else if (lanlink.server) {
if (IP_LINK_BIND_ADDRESS == "*") { if (IP_LINK_BIND_ADDRESS == "*")
auto local_addr = sf::IpAddress::getLocalAddress(); strncpy(host, sf::IpAddress::getLocalAddress().toString().c_str(), size);
if (local_addr) { else
strncpy(host, local_addr.value().toString().c_str(), size);
} else {
return false;
}
} else {
strncpy(host, IP_LINK_BIND_ADDRESS.c_str(), size); strncpy(host, IP_LINK_BIND_ADDRESS.c_str(), size);
}
} }
else { else
strncpy(host, lc.serveraddr.toString().c_str(), size); strncpy(host, lc.serveraddr.toString().c_str(), size);
}
return true;
} }
bool SetLinkServerHost(const char* host) bool SetLinkServerHost(const char* host)
{ {
sf::IpAddress addr{0}; sf::IpAddress addr = sf::IpAddress(host);
auto resolved = sf::IpAddress::resolve(host);
if (!resolved) {
return false;
}
addr = resolved.value();
lc.serveraddr = addr; lc.serveraddr = addr;
joybusHostAddr = addr; joybusHostAddr = addr;
return true; return addr != sf::IpAddress::None;
} }
int GetLinkPlayerId() int GetLinkPlayerId()
@@ -1064,13 +1044,11 @@ static ConnectionState InitSocket()
{ {
linkid = 0; linkid = 0;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++)
cable_data[i] = 0xffff; cable_data[i] = 0xffff;
}
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++)
cable_gb_data[i] = 0xff; cable_gb_data[i] = 0xff;
}
if (lanlink.server) { if (lanlink.server) {
lanlink.connectedSlaves = 0; lanlink.connectedSlaves = 0;
@@ -1079,33 +1057,26 @@ static ConnectionState InitSocket()
// too bad Listen() doesn't take an address as well // too bad Listen() doesn't take an address as well
// then again, old code used INADDR_ANY anyway // then again, old code used INADDR_ANY anyway
sf::IpAddress bind_ip{0}; sf::IpAddress bind_ip = IP_LINK_BIND_ADDRESS == "*" ? sf::IpAddress::Any : IP_LINK_BIND_ADDRESS;
if (IP_LINK_BIND_ADDRESS != "*") { if (lanlink.tcplistener.listen(IP_LINK_PORT, bind_ip) == sf::Socket::Error)
auto resolved = sf::IpAddress::resolve(IP_LINK_BIND_ADDRESS);
if (resolved) {
bind_ip = resolved.value();
} else {
return LINK_ERROR;
}
}
if (lanlink.tcplistener.listen(IP_LINK_PORT, bind_ip) == sf::Socket::Status::Error) {
// Note: old code closed socket & retried once on bind failure // Note: old code closed socket & retried once on bind failure
return LINK_ERROR; // FIXME: error code? return LINK_ERROR; // FIXME: error code?
} else { else
return LINK_NEEDS_UPDATE; return LINK_NEEDS_UPDATE;
}
} else { } else {
lc.serverport = IP_LINK_PORT; lc.serverport = IP_LINK_PORT;
lanlink.tcpsocket.setBlocking(false); if (lc.serveraddr == sf::IpAddress::None) {
sf::Socket::Status status = lanlink.tcpsocket.connect(lc.serveraddr, lc.serverport);
if (status == sf::Socket::Status::Error || status == sf::Socket::Status::Disconnected) {
return LINK_ERROR; return LINK_ERROR;
} else { } else {
return LINK_NEEDS_UPDATE; lanlink.tcpsocket.setBlocking(false);
sf::Socket::Status status = lanlink.tcpsocket.connect(lc.serveraddr, lc.serverport);
if (status == sf::Socket::Error || status == sf::Socket::Disconnected)
return LINK_ERROR;
else
return LINK_NEEDS_UPDATE;
} }
} }
} }
@@ -1119,11 +1090,11 @@ static ConnectionState ConnectUpdateSocket(char* const message, size_t size)
fdset.add(lanlink.tcplistener); fdset.add(lanlink.tcplistener);
if (fdset.wait(sf::milliseconds(150))) { if (fdset.wait(sf::milliseconds(150))) {
uint16_t nextSlave = lanlink.connectedSlaves + 1; int nextSlave = lanlink.connectedSlaves + 1;
sf::Socket::Status st = lanlink.tcplistener.accept(ls.tcpsocket[nextSlave]); sf::Socket::Status st = lanlink.tcplistener.accept(ls.tcpsocket[nextSlave]);
if (st == sf::Socket::Status::Error) { if (st == sf::Socket::Error) {
for (int j = 1; j < nextSlave; j++) for (int j = 1; j < nextSlave; j++)
ls.tcpsocket[j].disconnect(); ls.tcpsocket[j].disconnect();
@@ -1131,7 +1102,8 @@ static ConnectionState ConnectUpdateSocket(char* const message, size_t size)
newState = LINK_ERROR; newState = LINK_ERROR;
} else { } else {
sf::Packet packet; sf::Packet packet;
packet << nextSlave << lanlink.numslaves; packet << static_cast<sf::Uint16>(nextSlave)
<< static_cast<sf::Uint16>(lanlink.numslaves);
ls.tcpsocket[nextSlave].send(packet); ls.tcpsocket[nextSlave].send(packet);
@@ -1157,13 +1129,13 @@ static ConnectionState ConnectUpdateSocket(char* const message, size_t size)
sf::Packet packet; sf::Packet packet;
sf::Socket::Status status = lanlink.tcpsocket.receive(packet); sf::Socket::Status status = lanlink.tcpsocket.receive(packet);
if (status == sf::Socket::Status::Error || status == sf::Socket::Status::Disconnected) { if (status == sf::Socket::Error || status == sf::Socket::Disconnected) {
snprintf(message, size, N_("Network error.")); snprintf(message, size, N_("Network error."));
newState = LINK_ERROR; newState = LINK_ERROR;
} else if (status == sf::Socket::Status::Done) { } else if (status == sf::Socket::Done) {
if (linkid == 0) { if (linkid == 0) {
uint16_t receivedId, receivedSlaves; sf::Uint16 receivedId, receivedSlaves;
packet >> receivedId >> receivedSlaves; packet >> receivedId >> receivedSlaves;
if (packet) { if (packet) {
@@ -1568,7 +1540,7 @@ void RFUServer::Recv(void)
sf::Packet packet; sf::Packet packet;
tcpsocket[i + 1].setBlocking(false); tcpsocket[i + 1].setBlocking(false);
sf::Socket::Status status = tcpsocket[i + 1].receive(packet); sf::Socket::Status status = tcpsocket[i + 1].receive(packet);
if (status == sf::Socket::Status::Disconnected) { if (status == sf::Socket::Disconnected) {
char message[30]; char message[30];
sprintf(message, _("Player %d disconnected."), i + 1); sprintf(message, _("Player %d disconnected."), i + 1);
systemScreenMessage(message); systemScreenMessage(message);
@@ -1678,7 +1650,7 @@ void RFUClient::Recv(void)
} }
sf::Packet packet; sf::Packet packet;
sf::Socket::Status status = lanlink.tcpsocket.receive(packet); sf::Socket::Status status = lanlink.tcpsocket.receive(packet);
if (status == sf::Socket::Status::Disconnected) { if (status == sf::Socket::Disconnected) {
systemScreenMessage(_("Server disconnected.")); systemScreenMessage(_("Server disconnected."));
CloseLink(); CloseLink();
return; return;
@@ -1699,7 +1671,7 @@ static ConnectionState ConnectUpdateRFUSocket(char* const message, size_t size)
sf::Socket::Status st = lanlink.tcplistener.accept(rfu_server.tcpsocket[nextSlave]); sf::Socket::Status st = lanlink.tcplistener.accept(rfu_server.tcpsocket[nextSlave]);
if (st == sf::Socket::Status::Error) { if (st == sf::Socket::Error) {
for (int j = 1; j < nextSlave; j++) for (int j = 1; j < nextSlave; j++)
rfu_server.tcpsocket[j].disconnect(); rfu_server.tcpsocket[j].disconnect();
@@ -1707,7 +1679,8 @@ static ConnectionState ConnectUpdateRFUSocket(char* const message, size_t size)
newState = LINK_ERROR; newState = LINK_ERROR;
} else { } else {
sf::Packet packet; sf::Packet packet;
packet << nextSlave << lanlink.numslaves; packet << static_cast<sf::Uint16>(nextSlave)
<< static_cast<sf::Uint16>(lanlink.numslaves);
rfu_server.tcpsocket[nextSlave].send(packet); rfu_server.tcpsocket[nextSlave].send(packet);
@@ -1734,13 +1707,13 @@ static ConnectionState ConnectUpdateRFUSocket(char* const message, size_t size)
lanlink.tcpsocket.setBlocking(false); lanlink.tcpsocket.setBlocking(false);
sf::Socket::Status status = lanlink.tcpsocket.receive(packet); sf::Socket::Status status = lanlink.tcpsocket.receive(packet);
if (status == sf::Socket::Status::Error || status == sf::Socket::Status::Disconnected) { if (status == sf::Socket::Error || status == sf::Socket::Disconnected) {
snprintf(message, size, N_("Network error.")); snprintf(message, size, N_("Network error."));
newState = LINK_ERROR; newState = LINK_ERROR;
} else if (status == sf::Socket::Status::Done) { } else if (status == sf::Socket::Done) {
if (linkid == 0) { if (linkid == 0) {
uint16_t receivedId, receivedSlaves; sf::Uint16 receivedId, receivedSlaves;
packet >> receivedId >> receivedSlaves; packet >> receivedId >> receivedSlaves;
if (packet) { if (packet) {

View File

@@ -86,9 +86,8 @@ extern bool SetLinkServerHost(const char* host);
* If in lan client mode, returns the IP adress of the host to connect to * If in lan client mode, returns the IP adress of the host to connect to
* If in gamecube mode, returns the IP adress of the dolphin host * If in gamecube mode, returns the IP adress of the dolphin host
* *
* @return false on error
*/ */
extern bool GetLinkServerHost(char* const host, size_t size); extern void GetLinkServerHost(char* const host, size_t size);
/** /**
* Set the value in milliseconds of the timeout after which a connection is * Set the value in milliseconds of the timeout after which a connection is

View File

@@ -8,7 +8,10 @@
GBASockClient::GBASockClient(sf::IpAddress _server_addr) GBASockClient::GBASockClient(sf::IpAddress _server_addr)
{ {
server_addr = _server_addr; if (_server_addr == sf::IpAddress::None)
server_addr = sf::IpAddress::getPublicAddress();
else
server_addr = _server_addr;
client.connect(server_addr, 0xd6ba); client.connect(server_addr, 0xd6ba);
client.setBlocking(false); client.setBlocking(false);
@@ -41,9 +44,8 @@ void GBASockClient::Send(std::vector<char> data)
// Returns cmd for convenience // Returns cmd for convenience
char GBASockClient::ReceiveCmd(char* data_in, bool block) char GBASockClient::ReceiveCmd(char* data_in, bool block)
{ {
if (IsDisconnected()) { if (IsDisconnected())
return data_in[0]; return data_in[0];
}
std::size_t num_received = 0; std::size_t num_received = 0;
if (block || clock_sync == 0) { if (block || clock_sync == 0) {
@@ -51,9 +53,8 @@ char GBASockClient::ReceiveCmd(char* data_in, bool block)
Selector.add(client); Selector.add(client);
Selector.wait(sf::seconds(6)); Selector.wait(sf::seconds(6));
} }
if (client.receive(data_in, 5, num_received) == sf::Socket::Status::Disconnected) { if (client.receive(data_in, 5, num_received) == sf::Socket::Disconnected)
Disconnect(); Disconnect();
}
return data_in[0]; return data_in[0];
} }
@@ -66,15 +67,13 @@ void GBASockClient::ReceiveClock(bool block)
char sync_ticks[4] = { 0, 0, 0, 0 }; char sync_ticks[4] = { 0, 0, 0, 0 };
std::size_t num_received = 0; std::size_t num_received = 0;
if (clock_client.receive(sync_ticks, 4, num_received) == sf::Socket::Status::Disconnected) { if (clock_client.receive(sync_ticks, 4, num_received) == sf::Socket::Disconnected)
Disconnect(); Disconnect();
}
if (num_received == 4) { if (num_received == 4) {
clock_sync_ticks = 0; clock_sync_ticks = 0;
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++)
clock_sync_ticks |= (uint8_t)(sync_ticks[i]) << ((3 - i) * 8); clock_sync_ticks |= (uint8_t)(sync_ticks[i]) << ((3 - i) * 8);
}
clock_sync += clock_sync_ticks; clock_sync += clock_sync_ticks;
} }
} }

View File

@@ -7,7 +7,7 @@
#include <cstdint> #include <cstdint>
#include "SFML/Network.hpp" #include <SFML/Network.hpp>
class GBASockClient { class GBASockClient {
public: public:
@@ -24,7 +24,7 @@ public:
bool IsDisconnected(); bool IsDisconnected();
private: private:
sf::IpAddress server_addr{0}; sf::IpAddress server_addr;
sf::TcpSocket client; sf::TcpSocket client;
sf::TcpSocket clock_client; sf::TcpSocket clock_client;

View File

@@ -1,4 +0,0 @@
# Game Boy Overrrides
[ALLEY WAY]
gbPrinter = 0

View File

@@ -79,7 +79,7 @@ else ifeq ($(platform), classic_armv7_a7)
TARGET := $(TARGET_NAME)_libretro.so TARGET := $(TARGET_NAME)_libretro.so
fpic := -fPIC fpic := -fPIC
SHARED := -shared -Wl,--no-undefined -fPIC SHARED := -shared -Wl,--no-undefined -fPIC
CFLAGS += -O3 -ffast-math \ CFLAGS += -Ofast \
-flto=4 -fwhole-program -fuse-linker-plugin \ -flto=4 -fwhole-program -fuse-linker-plugin \
-fdata-sections -ffunction-sections -Wl,--gc-sections \ -fdata-sections -ffunction-sections -Wl,--gc-sections \
-fno-stack-protector -fno-ident -fomit-frame-pointer \ -fno-stack-protector -fno-ident -fomit-frame-pointer \
@@ -112,7 +112,7 @@ else ifeq ($(platform), classic_armv8_a35)
fpic := -fPIC fpic := -fPIC
SHARED := -shared SHARED := -shared
TILED_RENDERING=1 TILED_RENDERING=1
CFLAGS += -O3 -ffast-math \ CFLAGS += -Ofast \
-flto=4 -fwhole-program -fuse-linker-plugin \ -flto=4 -fwhole-program -fuse-linker-plugin \
-fdata-sections -ffunction-sections -Wl,--gc-sections \ -fdata-sections -ffunction-sections -Wl,--gc-sections \
-fno-stack-protector -fno-ident -fomit-frame-pointer \ -fno-stack-protector -fno-ident -fomit-frame-pointer \
@@ -311,24 +311,12 @@ else ifeq ($(platform), wiiu)
CXX = $(DEVKITPPC)/bin/powerpc-eabi-g++$(EXE_EXT) CXX = $(DEVKITPPC)/bin/powerpc-eabi-g++$(EXE_EXT)
AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT)
ENDIANNESS_DEFINES += -DMSB_FIRST -DWORDS_BIGENDIAN=1 ENDIANNESS_DEFINES += -DMSB_FIRST -DWORDS_BIGENDIAN=1
PLATFORM_DEFINES += -DGEKKO -DWIIU -DHW_WUP -mcpu=750 -meabi -mhard-float -D__ppc__ PLATFORM_DEFINES += -DGEKKO -DWIIU -DHW_RVL -mwup -mcpu=750 -meabi -mhard-float -D__ppc__
PLATFORM_DEFINES += -U__INT32_TYPE__ -U __UINT32_TYPE__ -D__INT32_TYPE__=int PLATFORM_DEFINES += -U__INT32_TYPE__ -U __UINT32_TYPE__ -D__INT32_TYPE__=int
STATIC_LINKING=1 STATIC_LINKING=1
TILED_RENDERING=1 TILED_RENDERING=1
# Nintendo Switch (libnx) # Nintendo Switch
else ifeq ($(platform), libnx)
include $(DEVKITPRO)/libnx/switch_rules
TARGET := $(TARGET_NAME)_libretro_$(platform).a
DEFINES := -DSWITCH=1 -U__linux__ -U__linux -DRARCH_INTERNAL -DHAVE_THREADS=1
CFLAGS := $(DEFINES) -g -O3 \
-fPIE -I$(LIBNX)/include/ -ffunction-sections -fdata-sections -ftls-model=local-exec -Wl,--allow-multiple-definition -specs=$(LIBNX)/switch.specs
CFLAGS += $(INCDIRS)
CFLAGS += $(INCLUDE) -D__SWITCH__ -DHAVE_LIBNX
CXXFLAGS := $(ASFLAGS) $(CFLAGS) -fno-rtti -fno-exceptions
STATIC_LINKING=1
# Nintendo Switch (devkitpro)
else ifeq ($(platform), switch) else ifeq ($(platform), switch)
TARGET := $(TARGET_NAME)_libretro_$(platform).a TARGET := $(TARGET_NAME)_libretro_$(platform).a
CC = $(DEVKITPRO)/devkitA64/bin/aarch64-none-elf-gcc$(EXE_EXT) CC = $(DEVKITPRO)/devkitA64/bin/aarch64-none-elf-gcc$(EXE_EXT)

View File

@@ -1,3 +1,4 @@
#include <cassert>
#include <cstdarg> #include <cstdarg>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
@@ -11,7 +12,6 @@
#include "components/filters_agb/filters_agb.h" #include "components/filters_agb/filters_agb.h"
#include "components/filters_interframe/interframe.h" #include "components/filters_interframe/interframe.h"
#include "core/base/check.h"
#include "core/base/system.h" #include "core/base/system.h"
#include "core/base/file_util.h" #include "core/base/file_util.h"
#include "core/base/sizes.h" #include "core/base/sizes.h"
@@ -177,7 +177,8 @@ static void* gb_rtcdata_prt(void)
case gbCartData::MapperType::kGameGenie: case gbCartData::MapperType::kGameGenie:
case gbCartData::MapperType::kGameShark: case gbCartData::MapperType::kGameShark:
case gbCartData::MapperType::kUnknown: case gbCartData::MapperType::kUnknown:
VBAM_NOTREACHED(); // Unreachable.
assert(false);
return nullptr; return nullptr;
} }
return nullptr; return nullptr;
@@ -204,7 +205,8 @@ static size_t gb_rtcdata_size(void)
case gbCartData::MapperType::kGameGenie: case gbCartData::MapperType::kGameGenie:
case gbCartData::MapperType::kGameShark: case gbCartData::MapperType::kGameShark:
case gbCartData::MapperType::kUnknown: case gbCartData::MapperType::kUnknown:
VBAM_NOTREACHED(); // Unreachable.
assert(false);
break; break;
} }
return 0; return 0;
@@ -270,7 +272,8 @@ static void gbInitRTC(void)
case gbCartData::MapperType::kGameGenie: case gbCartData::MapperType::kGameGenie:
case gbCartData::MapperType::kGameShark: case gbCartData::MapperType::kGameShark:
case gbCartData::MapperType::kUnknown: case gbCartData::MapperType::kUnknown:
VBAM_NOTREACHED(); // Unreachable.
assert(false);
break; break;
} }
} }
@@ -590,7 +593,7 @@ void retro_init(void)
coreOptions.parseDebug = true; coreOptions.parseDebug = true;
coreOptions.cheatsEnabled = 0; coreOptions.cheatsEnabled = 0;
coreOptions.skipSaveGameBattery = 0; coreOptions.skipSaveGameBattery = 0;
coreOptions.gbPrinterEnabled = 0; coreOptions.winGbPrinterEnabled = 0;
struct retro_log_callback log; struct retro_log_callback log;
struct retro_rumble_interface rumble; struct retro_rumble_interface rumble;
@@ -1453,7 +1456,8 @@ void retro_run(void)
case gbCartData::MapperType::kGameGenie: case gbCartData::MapperType::kGameGenie:
case gbCartData::MapperType::kGameShark: case gbCartData::MapperType::kGameShark:
case gbCartData::MapperType::kUnknown: case gbCartData::MapperType::kUnknown:
VBAM_NOTREACHED(); // Unreachable.
assert(false);
break; break;
} }
/* Initialize RTC using local time if needed */ /* Initialize RTC using local time if needed */

View File

@@ -31,8 +31,8 @@ if(MSVC)
# We should probably use an external library for this. # We should probably use an external library for this.
target_sources(vbam target_sources(vbam
PRIVATE PRIVATE
${CMAKE_SOURCE_DIR}/win32-deps/msvc/getopt.c ${CMAKE_SOURCE_DIR}/dependencies/msvc/getopt.c
${CMAKE_SOURCE_DIR}/win32-deps/msvc/getopt.h ${CMAKE_SOURCE_DIR}/dependencies/msvc/getopt.h
) )
endif() endif()
@@ -61,7 +61,7 @@ endif()
if(ENABLE_LIRC) if(ENABLE_LIRC)
target_link_libraries(vbam lirc_client) target_link_libraries(vbam lirc_client)
target_compile_definitions(vbam PUBLIC VBAM_ENABLE_LIRC) target_compile_definitions(vbam VBAM_ENABLE_LIRC)
endif() endif()
if(WIN32) if(WIN32)
@@ -71,15 +71,15 @@ endif()
# Installation scripts. # Installation scripts.
install( install(
PROGRAMS ${PROJECT_BINARY_DIR}/vbam${CMAKE_EXECUTABLE_SUFFIX} PROGRAMS ${PROJECT_BINARY_DIR}/vbam${CMAKE_EXECUTABLE_SUFFIX}
DESTINATION ${CMAKE_INSTALL_BINDIR} DESTINATION ${CMAKE_INSTALL_FULL_BINDIR}
) )
install( install(
FILES ${CMAKE_CURRENT_LIST_DIR}/vbam.cfg-example FILES ${CMAKE_CURRENT_LIST_DIR}/vbam.cfg-example
DESTINATION ${CMAKE_INSTALL_SYSCONFDIR} DESTINATION ${CMAKE_INSTALL_FULL_SYSCONFDIR}
RENAME vbam.cfg RENAME vbam.cfg
) )
if(UNIX) if(UNIX)
# man pages. # man pages.
install(FILES ${CMAKE_SOURCE_DIR}/src/debian/vbam.6 DESTINATION ${CMAKE_INSTALL_MANDIR}/man6) install(FILES ${CMAKE_SOURCE_DIR}/src/debian/vbam.6 DESTINATION ${CMAKE_INSTALL_FULL_MANDIR}/man6)
endif() endif()

View File

@@ -98,8 +98,7 @@ enum named_opts
OPT_SOUND_FILTERING, OPT_SOUND_FILTERING,
OPT_SPEEDUP_THROTTLE, OPT_SPEEDUP_THROTTLE,
OPT_SPEEDUP_FRAME_SKIP, OPT_SPEEDUP_FRAME_SKIP,
OPT_NO_SPEEDUP_THROTTLE_FRAME_SKIP, OPT_NO_SPEEDUP_THROTTLE_FRAME_SKIP
OPT_NO_SPEEDUP_MUTE
}; };
#define SOUND_MAX_VOLUME 2.0 #define SOUND_MAX_VOLUME 2.0
@@ -189,7 +188,7 @@ struct option argOptions[] = {
{ "gb-emulator-type", required_argument, 0, OPT_GB_EMULATOR_TYPE }, { "gb-emulator-type", required_argument, 0, OPT_GB_EMULATOR_TYPE },
{ "gb-frame-skip", required_argument, 0, OPT_GB_FRAME_SKIP }, { "gb-frame-skip", required_argument, 0, OPT_GB_FRAME_SKIP },
{ "gb-palette-option", required_argument, 0, OPT_GB_PALETTE_OPTION }, { "gb-palette-option", required_argument, 0, OPT_GB_PALETTE_OPTION },
{ "gb-printer", no_argument, &coreOptions.gbPrinterEnabled, 1 }, { "gb-printer", no_argument, &coreOptions.winGbPrinterEnabled, 1 },
{ "gdb", required_argument, 0, 'G' }, { "gdb", required_argument, 0, 'G' },
{ "help", no_argument, &optPrintUsage, 1 }, { "help", no_argument, &optPrintUsage, 1 },
{ "ifb-filter", required_argument, 0, 'I' }, { "ifb-filter", required_argument, 0, 'I' },
@@ -233,10 +232,9 @@ struct option argOptions[] = {
{ "speedup-throttle", required_argument, 0, OPT_SPEEDUP_THROTTLE }, { "speedup-throttle", required_argument, 0, OPT_SPEEDUP_THROTTLE },
{ "speedup-frame-skip", required_argument, 0, OPT_SPEEDUP_FRAME_SKIP }, { "speedup-frame-skip", required_argument, 0, OPT_SPEEDUP_FRAME_SKIP },
{ "no-speedup-throttle-frame-skip", no_argument, 0, OPT_NO_SPEEDUP_THROTTLE_FRAME_SKIP }, { "no-speedup-throttle-frame-skip", no_argument, 0, OPT_NO_SPEEDUP_THROTTLE_FRAME_SKIP },
{ "no-speedup-mute", no_argument, 0, OPT_NO_SPEEDUP_MUTE },
{ "use-bios", no_argument, &coreOptions.useBios, 1 }, { "use-bios", no_argument, &coreOptions.useBios, 1 },
{ "verbose", required_argument, 0, 'v' }, { "verbose", required_argument, 0, 'v' },
{ "win-gb-printer-enabled", no_argument, &coreOptions.gbPrinterEnabled, 1 }, { "win-gb-printer-enabled", no_argument, &coreOptions.winGbPrinterEnabled, 1 },
{ NULL, no_argument, NULL, 0 } { NULL, no_argument, NULL, 0 }
@@ -349,9 +347,8 @@ void LoadConfig()
coreOptions.speedup_throttle = ReadPref("speedupThrottle", 100); coreOptions.speedup_throttle = ReadPref("speedupThrottle", 100);
coreOptions.speedup_frame_skip = ReadPref("speedupFrameSkip", 9); coreOptions.speedup_frame_skip = ReadPref("speedupFrameSkip", 9);
coreOptions.speedup_throttle_frame_skip = ReadPref("speedupThrottleFrameSkip", 0); coreOptions.speedup_throttle_frame_skip = ReadPref("speedupThrottleFrameSkip", 0);
coreOptions.speedup_mute = ReadPref("speedupMute", 1);
coreOptions.useBios = ReadPrefHex("useBiosGBA"); coreOptions.useBios = ReadPrefHex("useBiosGBA");
coreOptions.gbPrinterEnabled = ReadPref("gbPrinter", 0); coreOptions.winGbPrinterEnabled = ReadPref("gbPrinter", 0);
int soundQuality = (ReadPrefHex("soundQuality", 1)); int soundQuality = (ReadPrefHex("soundQuality", 1));
switch (soundQuality) { switch (soundQuality) {
@@ -993,9 +990,6 @@ int ReadOpts(int argc, char ** argv)
case OPT_NO_SPEEDUP_THROTTLE_FRAME_SKIP: case OPT_NO_SPEEDUP_THROTTLE_FRAME_SKIP:
coreOptions.speedup_throttle_frame_skip = false; coreOptions.speedup_throttle_frame_skip = false;
break; break;
case OPT_NO_SPEEDUP_MUTE:
coreOptions.speedup_mute = false;
break;
} }
} }
return op; return op;

View File

@@ -364,10 +364,6 @@ mirroringEnabled=1
saveType=1 saveType=1
mirroringEnabled=1 mirroringEnabled=1
# Higurashi no Nakukoroni (Japan)
[HGRS]
saveType=2
# Koro Koro Puzzle - Happy Panechu! (Japan) # Koro Koro Puzzle - Happy Panechu! (Japan)
[KHPJ] [KHPJ]
saveType=4 saveType=4

View File

@@ -31,8 +31,6 @@ set(VBAM_WX_COMMON
dialogs/joypad-config.h dialogs/joypad-config.h
dialogs/sound-config.cpp dialogs/sound-config.cpp
dialogs/sound-config.h dialogs/sound-config.h
dialogs/speedup-config.cpp
dialogs/speedup-config.h
drawing.h drawing.h
extra-translations.cpp extra-translations.cpp
gfxviewers.cpp gfxviewers.cpp
@@ -48,6 +46,33 @@ set(VBAM_WX_COMMON
viewsupt.h viewsupt.h
wayland.cpp wayland.cpp
wayland.h wayland.h
# from external source with minor modifications
widgets/checkedlistctrl.cpp
widgets/checkedlistctrl.h
widgets/client-data.h
widgets/dpi-support.h
widgets/event-handler-provider.h
widgets/group-check-box.cpp
widgets/group-check-box.h
widgets/keep-on-top-styler.cpp
widgets/keep-on-top-styler.h
widgets/option-validator.cpp
widgets/option-validator.h
widgets/render-plugin.cpp
widgets/render-plugin.h
widgets/user-input-ctrl.cpp
widgets/user-input-ctrl.h
widgets/user-input-event.cpp
widgets/user-input-event.h
widgets/sdl-poller.cpp
widgets/sdl-poller.h
widgets/shortcut-menu-bar.cpp
widgets/shortcut-menu-bar.h
widgets/utils.cpp
widgets/utils.h
widgets/webupdatedef.h
widgets/wxmisc.h
widgets/wxmisc.cpp
wxhead.h wxhead.h
wxlogdebug.h wxlogdebug.h
wxvbam.cpp wxvbam.cpp
@@ -59,7 +84,6 @@ set(VBAM_WX_COMMON
${VBAM_GENERATED_DIR}/wx/builtin-over.h ${VBAM_GENERATED_DIR}/wx/builtin-over.h
${VBAM_GENERATED_DIR}/wx/cmdhandlers.h ${VBAM_GENERATED_DIR}/wx/cmdhandlers.h
${VBAM_GENERATED_DIR}/wx/cmd-evtable.h ${VBAM_GENERATED_DIR}/wx/cmd-evtable.h
${VBAM_GENERATED_DIR}/wx/gb-builtin-over.h
) )
if(NOT ZIP_PROGRAM) if(NOT ZIP_PROGRAM)
@@ -142,7 +166,7 @@ endif()
# wxWidgets configuration. # wxWidgets configuration.
set(wxWidgets_USE_UNICODE ON) set(wxWidgets_USE_UNICODE ON)
if(CMAKE_BUILD_TYPE STREQUAL "Debug") if(CMAKE_BUILD_TYPE MATCHES "^(Debug|RelWithDebInfo)$")
set(wxWidgets_USE_DEBUG ON) # noop if wx is compiled with --disable-debug, like in Mac Homebrew atm set(wxWidgets_USE_DEBUG ON) # noop if wx is compiled with --disable-debug, like in Mac Homebrew atm
endif() endif()
if(VBAM_STATIC) if(VBAM_STATIC)
@@ -153,7 +177,6 @@ unset(wx_find_extra)
if(CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg") if(CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg")
set(wx_find_extra NO_DEFAULT_PATH) set(wx_find_extra NO_DEFAULT_PATH)
set(wxWidgets_DIR "${VCPKG_ROOT}/installed/${VCPKG_TARGET_TRIPLET}/share/wxwidgets") set(wxWidgets_DIR "${VCPKG_ROOT}/installed/${VCPKG_TARGET_TRIPLET}/share/wxwidgets")
find_package(nanosvg)
endif() endif()
set(ENABLE_OPENGL TRUE) set(ENABLE_OPENGL TRUE)
@@ -164,13 +187,6 @@ if(NOT wxWidgets_FOUND)
set(ENABLE_OPENGL FALSE) set(ENABLE_OPENGL FALSE)
endif() endif()
# Fixup wxWidgets paths for vcpkg debug builds.
if(CMAKE_BUILD_TYPE STREQUAL "Debug" AND CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg")
set(wxWidgets_ROOT_DIR "${wxWidgets_ROOT_DIR}/debug" CACHE INTERNAL "wxWidgets root directory" FORCE)
string(REGEX REPLACE "/lib$" "/debug/lib" wxWidgets_LIB_DIR "${wxWidgets_LIB_DIR}")
set(wxWidgets_LIB_DIR "${wxWidgets_LIB_DIR}" CACHE INTERNAL "wxWidgets library directory" FORCE)
endif()
# Find OpenAL (required). # Find OpenAL (required).
find_package(OpenAL REQUIRED) find_package(OpenAL REQUIRED)
@@ -237,9 +253,6 @@ function(configure_wx_target target)
endif() endif()
endfunction() endfunction()
# Core emulator.
_add_link_libraries(vbam-core)
# Nonstd. # Nonstd.
_add_link_libraries(nonstd-lib) _add_link_libraries(nonstd-lib)
_add_include_directories(${NONSTD_INCLUDE_DIR}) _add_include_directories(${NONSTD_INCLUDE_DIR})
@@ -249,17 +262,13 @@ function(configure_wx_target target)
_add_include_directories(${wxWidgets_INCLUDE_DIRS}) _add_include_directories(${wxWidgets_INCLUDE_DIRS})
_add_compile_options(${wxWidgets_CXX_FLAGS}) _add_compile_options(${wxWidgets_CXX_FLAGS})
_add_compile_definitions(${wxWidgets_DEFINITIONS}) _add_compile_definitions(${wxWidgets_DEFINITIONS})
if(CMAKE_BUILD_TYPE STREQUAL "Debug") if(CMAKE_BUILD_TYPE MATCHES "^(Debug|RelWithDebInfo)$")
_add_compile_definitions(${wxWidgets_DEFINITIONS_DEBUG}) _add_compile_definitions(${wxWidgets_DEFINITIONS_DEBUG})
endif() endif()
# OpenAL. # OpenAL.
if(OPENAL_STATIC) if(OPENAL_STATIC)
_add_compile_definitions(AL_LIBTYPE_STATIC) _add_compile_definitions(AL_LIBTYPE_STATIC)
if(WIN32)
list(APPEND OPENAL_LIBRARY avrt)
endif()
endif() endif()
_add_include_directories(${OPENAL_INCLUDE_DIR}) _add_include_directories(${OPENAL_INCLUDE_DIR})
_add_link_libraries(${OPENAL_LIBRARY}) _add_link_libraries(${OPENAL_LIBRARY})
@@ -275,15 +284,9 @@ function(configure_wx_target target)
if(MSVC) if(MSVC)
_add_link_libraries(FAudio::FAudio) _add_link_libraries(FAudio::FAudio)
else() else()
_add_link_libraries(FAudio)
if(WIN32) if(WIN32)
if(MINGW AND VBAM_STATIC)
_add_link_libraries(FAudio.a)
else()
_add_link_libraries(FAudio)
endif()
_add_link_libraries(dxguid uuid winmm ole32 advapi32 user32 mfplat mfreadwrite mfuuid propsys) _add_link_libraries(dxguid uuid winmm ole32 advapi32 user32 mfplat mfreadwrite mfuuid propsys)
else()
_add_link_libraries(FAudio)
endif() endif()
endif() endif()
endif() endif()
@@ -308,7 +311,6 @@ endfunction()
# Sub-projects. # Sub-projects.
add_subdirectory(test) add_subdirectory(test)
add_subdirectory(config) add_subdirectory(config)
add_subdirectory(widgets)
set(VBAM_ICON visualboyadvance-m.icns) set(VBAM_ICON visualboyadvance-m.icns)
set(VBAM_ICON_PATH ${CMAKE_CURRENT_SOURCE_DIR}/icons/${VBAM_ICON}) set(VBAM_ICON_PATH ${CMAKE_CURRENT_SOURCE_DIR}/icons/${VBAM_ICON})
@@ -324,13 +326,13 @@ target_include_directories(visualboyadvance-m PRIVATE ${SDL2_INCLUDE_DIRS})
target_link_libraries( target_link_libraries(
visualboyadvance-m visualboyadvance-m
vbam-core
vbam-components-draw-text vbam-components-draw-text
vbam-components-filters vbam-components-filters
vbam-components-filters-agb vbam-components-filters-agb
vbam-components-filters-interframe vbam-components-filters-interframe
vbam-components-user-config vbam-components-user-config
vbam-wx-config vbam-wx-config
vbam-wx-widgets
) )
# adjust link command when making a static binary for gcc # adjust link command when making a static binary for gcc
@@ -399,15 +401,21 @@ if(WIN32)
# Disable the auto-generated manifest from CMake. # Disable the auto-generated manifest from CMake.
target_link_options(visualboyadvance-m PRIVATE "/MANIFEST:NO") target_link_options(visualboyadvance-m PRIVATE "/MANIFEST:NO")
endif() endif()
# wxWidgets fails to bring in its dependency.
find_library(PCRE_LIB pcre2-16 REQUIRED)
target_link_libraries(visualboyadvance-m ${PCRE_LIB})
endif() endif()
if(APPLE) if(APPLE)
target_sources(visualboyadvance-m PRIVATE target_sources(visualboyadvance-m PRIVATE
macsupport.mm macsupport.mm
widgets/dpi-support-mac.mm
)
else()
target_sources(visualboyadvance-m PRIVATE
widgets/dpi-support.cpp
) )
target_link_libraries(visualboyadvance-m
tiff zstd deflate)
endif() endif()
# link libgcc/libstdc++ statically on mingw # link libgcc/libstdc++ statically on mingw
@@ -528,7 +536,7 @@ host_compile(${CMAKE_CURRENT_SOURCE_DIR}/bin2c.c ${BIN2C})
# Override wxrc when cross-compiling. # Override wxrc when cross-compiling.
if(CMAKE_HOST_WIN32 AND CMAKE_CROSSCOMPILING) if(CMAKE_HOST_WIN32 AND CMAKE_CROSSCOMPILING)
set(WXRC ${CMAKE_SOURCE_DIR}/win32-deps/wxrc/wxrc.exe) set(WXRC ${CMAKE_SOURCE_DIR}/dependencies/wxrc/wxrc.exe)
endif() endif()
# Configure wxrc. # Configure wxrc.
@@ -651,12 +659,6 @@ add_custom_command(
DEPENDS ${CMAKE_SOURCE_DIR}/src/vba-over.ini ${BIN2C} DEPENDS ${CMAKE_SOURCE_DIR}/src/vba-over.ini ${BIN2C}
) )
add_custom_command(
OUTPUT ${VBAM_GENERATED_DIR}/wx/gb-builtin-over.h
COMMAND ${BIN2C} ${CMAKE_SOURCE_DIR}/src/gb-over.ini ${VBAM_GENERATED_DIR}/wx/gb-builtin-over.h gb_builtin_over
DEPENDS ${CMAKE_SOURCE_DIR}/src/gb-over.ini ${BIN2C}
)
set(VBAM_LOCALIZABLE_FILES ${VBAM_WX_COMMON} ${VBAM_LOCALIZABLE_WX_CONFIG_FILES}) set(VBAM_LOCALIZABLE_FILES ${VBAM_WX_COMMON} ${VBAM_LOCALIZABLE_WX_CONFIG_FILES})
list(APPEND VBAM_LOCALIZABLE_FILES list(APPEND VBAM_LOCALIZABLE_FILES
audio/internal/dsound.cpp audio/internal/dsound.cpp
@@ -679,9 +681,9 @@ if(APPLE)
set(CMAKE_INSTALL_RPATH "@loader_path/../Frameworks") set(CMAKE_INSTALL_RPATH "@loader_path/../Frameworks")
endif() endif()
if(WIN32 AND (X86_64 OR ARM64 OR X86_32) AND ENABLE_ONLINEUPDATES) if(WIN32 AND (X86_64 OR X86_32) AND ENABLE_ONLINEUPDATES)
if(NOT DEFINED WINSPARKLE_BIN_RELEASE_DIR) if(NOT DEFINED WINSPARKLE_BIN_RELEASE_DIR)
set(WINSPARKLE_BIN_RELEASE_DIR ${CMAKE_SOURCE_DIR}/win32-deps/WinSparkle-0.8.1) set(WINSPARKLE_BIN_RELEASE_DIR ${CMAKE_SOURCE_DIR}/dependencies/WinSparkle-0.6.0)
endif() endif()
target_include_directories( target_include_directories(
@@ -690,11 +692,9 @@ if(WIN32 AND (X86_64 OR ARM64 OR X86_32) AND ENABLE_ONLINEUPDATES)
) )
if(X86_64) if(X86_64)
set(WINSPARKLE_DLL ${WINSPARKLE_BIN_RELEASE_DIR}/x64/Release/WinSparkle.dll) set(WINSPARKLE_DLL ${CMAKE_SOURCE_DIR}/dependencies/WinSparkle-0.6.0/x64/Release/WinSparkle.dll)
elseif(ARM64) else()
set(WINSPARKLE_DLL ${WINSPARKLE_BIN_RELEASE_DIR}/ARM64/Release/WinSparkle.dll) set(WINSPARKLE_DLL ${CMAKE_SOURCE_DIR}/dependencies/WinSparkle-0.6.0/Release/WinSparkle.dll)
elseif(X86_32)
set(WINSPARKLE_DLL ${WINSPARKLE_BIN_RELEASE_DIR}/Release/WinSparkle.dll)
endif() endif()
configure_file(autoupdater/wxmsw/winsparkle-path.h.in ${CMAKE_BINARY_DIR}/winsparkle-path.h) configure_file(autoupdater/wxmsw/winsparkle-path.h.in ${CMAKE_BINARY_DIR}/winsparkle-path.h)
@@ -803,7 +803,7 @@ endif()
if(UPSTREAM_RELEASE AND WIN32) if(UPSTREAM_RELEASE AND WIN32)
set(home "$ENV{HOME}") set(home "$ENV{HOME}")
if(NOT home OR ((MSVC OR NOT CMAKE_CROSSCOMPILING) AND NOT DEFINED ENV{MSYSTEM_PREFIX})) if((MSVC OR NOT CMAKE_CROSSCOMPILING) AND NOT DEFINED ENV{MSYSTEM_PREFIX})
set(home "$ENV{USERPROFILE}") set(home "$ENV{USERPROFILE}")
endif() endif()
@@ -811,9 +811,8 @@ if(UPSTREAM_RELEASE AND WIN32)
string(REGEX REPLACE "\\\\" "/" home "${home}") string(REGEX REPLACE "\\\\" "/" home "${home}")
set(cert "${home}/.codesign/windows_comodo.pkcs12") set(cert "${home}/.codesign/windows_comodo.pkcs12")
file(STRINGS "${home}/.codesign/windows_comodo.pkcs12.password" cert_password)
if(EXISTS "${cert}" AND cert_password) if(EXISTS "${cert}")
find_program(OSSLSIGNCODE_PROGRAM osslsigncode) find_program(OSSLSIGNCODE_PROGRAM osslsigncode)
find_program(SIGNTOOL_PROGRAM signtool) find_program(SIGNTOOL_PROGRAM signtool)
@@ -822,7 +821,7 @@ if(UPSTREAM_RELEASE AND WIN32)
TARGET visualboyadvance-m TARGET visualboyadvance-m
POST_BUILD POST_BUILD
COMMAND ${CMAKE_COMMAND} -E rename visualboyadvance-m.exe visualboyadvance-m-unsigned.exe COMMAND ${CMAKE_COMMAND} -E rename visualboyadvance-m.exe visualboyadvance-m-unsigned.exe
COMMAND ${OSSLSIGNCODE_PROGRAM} sign -pkcs12 ${cert} -pass "${cert_password}" -t http://timestamp.digicert.com -n visualboyadvance-m -i https://github.com/visualboyadvance-m/visualboyadvance-m -in visualboyadvance-m-unsigned.exe -out visualboyadvance-m.exe COMMAND ${OSSLSIGNCODE_PROGRAM} sign -pkcs12 ${cert} -pass "vbam3!13" -t http://timestamp.digicert.com -n visualboyadvance-m -i https://github.com/visualboyadvance-m/visualboyadvance-m -in visualboyadvance-m-unsigned.exe -out visualboyadvance-m.exe
WORKING_DIRECTORY ${CMAKE_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
) )
elseif(SIGNTOOL_PROGRAM) elseif(SIGNTOOL_PROGRAM)
@@ -830,7 +829,7 @@ if(UPSTREAM_RELEASE AND WIN32)
TARGET visualboyadvance-m TARGET visualboyadvance-m
POST_BUILD POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy visualboyadvance-m.exe visualboyadvance-m-unsigned.exe COMMAND ${CMAKE_COMMAND} -E copy visualboyadvance-m.exe visualboyadvance-m-unsigned.exe
COMMAND ${SIGNTOOL_PROGRAM} sign /f ${cert} /fd certHash /td certHash /p "${cert_password}" /tr http://timestamp.digicert.com /du https://github.com/visualboyadvance-m/visualboyadvance-m /a visualboyadvance-m.exe COMMAND ${SIGNTOOL_PROGRAM} sign /f ${cert} /fd certHash /td certHash /p "vbam3!13" /tr http://timestamp.digicert.com /du https://github.com/visualboyadvance-m/visualboyadvance-m /a visualboyadvance-m.exe
WORKING_DIRECTORY ${CMAKE_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
) )
endif() endif()
@@ -904,7 +903,7 @@ if(APPLE)
if(CMAKE_BUILD_TYPE MATCHES "^(Release|MinSizeRel)$") if(CMAKE_BUILD_TYPE MATCHES "^(Release|MinSizeRel)$")
add_custom_command( add_custom_command(
TARGET visualboyadvance-m POST_BUILD TARGET visualboyadvance-m POST_BUILD
COMMAND bash ${CMAKE_SOURCE_DIR}/tools/macOS/third_party_libs_tool ./visualboyadvance-m.app COMMAND ${CMAKE_SOURCE_DIR}/tools/macOS/third_party_libs_tool ./visualboyadvance-m.app
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
) )
endif() endif()
@@ -1035,13 +1034,13 @@ install(
# Installation scripts. # Installation scripts.
install( install(
PROGRAMS ${PROJECT_BINARY_DIR}/visualboyadvance-m${CMAKE_EXECUTABLE_SUFFIX} PROGRAMS ${PROJECT_BINARY_DIR}/visualboyadvance-m${CMAKE_EXECUTABLE_SUFFIX}
DESTINATION ${CMAKE_INSTALL_BINDIR} DESTINATION ${CMAKE_INSTALL_FULL_BINDIR}
) )
install( install(
FILES ${CMAKE_SOURCE_DIR}/src/vba-over.ini FILES ${CMAKE_SOURCE_DIR}/src/vba-over.ini
DESTINATION ${CMAKE_INSTALL_DATADIR}/vbam DESTINATION ${CMAKE_INSTALL_FULL_DATADIR}/vbam
) )
if (UNIX) if (UNIX)
install(FILES ${CMAKE_SOURCE_DIR}/src/debian/visualboyadvance-m.6 DESTINATION ${CMAKE_INSTALL_MANDIR}/man6) install(FILES ${CMAKE_SOURCE_DIR}/src/debian/visualboyadvance-m.6 DESTINATION ${CMAKE_INSTALL_FULL_MANDIR}/man6)
endif() endif()

View File

@@ -1,12 +1,12 @@
#include "wx/audio/audio.h" #include "wx/audio/audio.h"
#include "core/base/check.h"
#include "wx/audio/internal/openal.h" #include "wx/audio/internal/openal.h"
#if defined(__WXMSW__) #if defined(__WXMSW__)
#include "wx/audio/internal/dsound.h" #include "wx/audio/internal/dsound.h"
#endif #endif
#if defined(VBAM_ENABLE_FAUDIO) #if defined(VBAM_ENABLE_FAUDIO)
#include "wx/audio/internal/faudio.h" #include "wx/audio/internal/faudio.h"
#endif #endif
@@ -39,7 +39,8 @@ std::vector<AudioDevice> EnumerateAudioDevices(const config::AudioApi& audio_api
case config::AudioApi::kLast: case config::AudioApi::kLast:
default: default:
VBAM_NOTREACHED(); // This should never happen.
assert(false);
return {}; return {};
} }
} }
@@ -66,7 +67,8 @@ std::unique_ptr<SoundDriver> CreateSoundDriver(const config::AudioApi& api) {
case config::AudioApi::kLast: case config::AudioApi::kLast:
default: default:
VBAM_NOTREACHED(); // This should never happen.
assert(false);
return nullptr; return nullptr;
} }
} }

View File

@@ -5,6 +5,8 @@
#include "wx/audio/internal/faudio.h" #include "wx/audio/internal/faudio.h"
#include <cassert>
#include <condition_variable> #include <condition_variable>
#include <mutex> #include <mutex>
#include <vector> #include <vector>
@@ -16,11 +18,9 @@
#include <wx/log.h> #include <wx/log.h>
#include <wx/translation.h> #include <wx/translation.h>
#include "core/base/check.h"
#include "core/base/system.h" #include "core/base/system.h"
#include "core/gba/gbaGlobals.h" #include "core/gba/gbaGlobals.h"
#include "wx/config/option-proxy.h" #include "wx/config/option-proxy.h"
#include "wx/config/strutils.h"
namespace audio { namespace audio {
namespace internal { namespace internal {
@@ -28,7 +28,7 @@ namespace internal {
namespace { namespace {
int FAGetDev(FAudio* fa) { int FAGetDev(FAudio* fa) {
const wxString audio_device = OPTION(kSoundAudioDevice).Get(); const wxString& audio_device = OPTION(kSoundAudioDevice);
if (audio_device.empty()) { if (audio_device.empty()) {
// Just use the default device. // Just use the default device.
return 0; return 0;
@@ -48,7 +48,7 @@ int FAGetDev(FAudio* fa) {
if (hr != 0) { if (hr != 0) {
continue; continue;
} }
const wxString device_id = config::utf16_to_utf8(dd.DeviceID); const wxString device_id(reinterpret_cast<wchar_t*>(dd.DeviceID));
if (audio_device == device_id) { if (audio_device == device_id) {
return i; return i;
} }
@@ -59,17 +59,6 @@ int FAGetDev(FAudio* fa) {
class FAudio_BufferNotify : public FAudioVoiceCallback { class FAudio_BufferNotify : public FAudioVoiceCallback {
public: public:
FAudio_BufferNotify() {
OnBufferEnd = &FAudio_BufferNotify::StaticOnBufferEnd;
OnVoiceProcessingPassStart = &FAudio_BufferNotify::StaticOnVoiceProcessingPassStart;
OnVoiceProcessingPassEnd = &FAudio_BufferNotify::StaticOnVoiceProcessingPassEnd;
OnStreamEnd = &FAudio_BufferNotify::StaticOnStreamEnd;
OnBufferStart = &FAudio_BufferNotify::StaticOnBufferStart;
OnLoopEnd = &FAudio_BufferNotify::StaticOnLoopEnd;
OnVoiceError = &FAudio_BufferNotify::StaticOnVoiceError;
}
~FAudio_BufferNotify() = default;
// Waits for the buffer end event to be signaled for 10 seconds. // Waits for the buffer end event to be signaled for 10 seconds.
// Returns true if the buffer end event was signaled, false if the wait timed out. // Returns true if the buffer end event was signaled, false if the wait timed out.
bool WaitForSignal() { bool WaitForSignal() {
@@ -82,6 +71,17 @@ public:
return was_signaled; return was_signaled;
} }
FAudio_BufferNotify() {
OnBufferEnd = &FAudio_BufferNotify::StaticOnBufferEnd;
OnVoiceProcessingPassStart = &FAudio_BufferNotify::StaticOnVoiceProcessingPassStart;
OnVoiceProcessingPassEnd = &FAudio_BufferNotify::StaticOnVoiceProcessingPassEnd;
OnStreamEnd = &FAudio_BufferNotify::StaticOnStreamEnd;
OnBufferStart = &FAudio_BufferNotify::StaticOnBufferStart;
OnLoopEnd = &FAudio_BufferNotify::StaticOnLoopEnd;
OnVoiceError = &FAudio_BufferNotify::StaticOnVoiceError;
}
~FAudio_BufferNotify() = default;
private: private:
// Signals that the buffer end event has occurred. // Signals that the buffer end event has occurred.
void SignalBufferEnd() { void SignalBufferEnd() {
@@ -120,6 +120,8 @@ public:
FAudio_Output(); FAudio_Output();
~FAudio_Output(); ~FAudio_Output();
void device_change();
private: private:
void close(); void close();
@@ -157,7 +159,6 @@ FAudio_Output::FAudio_Output() : buffer_count_(OPTION(kSoundBuffers)) {
playing = false; playing = false;
freq_ = 0; freq_ = 0;
currentBuffer = 0; currentBuffer = 0;
sound_buffer_len_ = 0;
device_changed = false; device_changed = false;
faud = nullptr; faud = nullptr;
mVoice = nullptr; mVoice = nullptr;
@@ -175,7 +176,7 @@ void FAudio_Output::close() {
if (sVoice) { if (sVoice) {
if (playing) { if (playing) {
VBAM_CHECK(FAudioSourceVoice_Stop(sVoice, 0, FAUDIO_COMMIT_NOW) == 0); assert(FAudioSourceVoice_Stop(sVoice, 0, FAUDIO_COMMIT_NOW) == 0);
} }
FAudioVoice_DestroyVoice(sVoice); FAudioVoice_DestroyVoice(sVoice);
@@ -193,6 +194,10 @@ void FAudio_Output::close() {
} }
} }
void FAudio_Output::device_change() {
device_changed = true;
}
bool FAudio_Output::init(long sampleRate) { bool FAudio_Output::init(long sampleRate) {
if (failed || initialized) if (failed || initialized)
return false; return false;
@@ -254,7 +259,7 @@ bool FAudio_Output::init(long sampleRate) {
if (OPTION(kSoundUpmix)) { if (OPTION(kSoundUpmix)) {
// set up stereo upmixing // set up stereo upmixing
FAudioDeviceDetails dd{}; FAudioDeviceDetails dd{};
VBAM_CHECK(FAudio_GetDeviceDetails(faud, 0, &dd) == 0); assert(FAudio_GetDeviceDetails(faud, 0, &dd) == 0);
std::vector<float> matrix(sizeof(float) * 2 * dd.OutputFormat.Format.nChannels); std::vector<float> matrix(sizeof(float) * 2 * dd.OutputFormat.Format.nChannels);
bool matrixAvailable = true; bool matrixAvailable = true;
@@ -348,12 +353,12 @@ bool FAudio_Output::init(long sampleRate) {
if (matrixAvailable) { if (matrixAvailable) {
hr = FAudioVoice_SetOutputMatrix(sVoice, nullptr, 2, dd.OutputFormat.Format.nChannels, hr = FAudioVoice_SetOutputMatrix(sVoice, nullptr, 2, dd.OutputFormat.Format.nChannels,
matrix.data(), FAUDIO_DEFAULT_CHANNELS); matrix.data(), FAUDIO_DEFAULT_CHANNELS);
VBAM_CHECK(hr == 0); assert(hr == 0);
} }
} }
hr = FAudioSourceVoice_Start(sVoice, 0, FAUDIO_COMMIT_NOW); hr = FAudioSourceVoice_Start(sVoice, 0, FAUDIO_COMMIT_NOW);
VBAM_CHECK(hr == 0); assert(hr == 0);
playing = true; playing = true;
currentBuffer = 0; currentBuffer = 0;
device_changed = false; device_changed = false;
@@ -375,7 +380,7 @@ void FAudio_Output::write(uint16_t* finalWave, int) {
} }
FAudioSourceVoice_GetState(sVoice, &vState, flags); FAudioSourceVoice_GetState(sVoice, &vState, flags);
VBAM_CHECK(vState.BuffersQueued <= buffer_count_); assert(vState.BuffersQueued <= buffer_count_);
if (vState.BuffersQueued < buffer_count_) { if (vState.BuffersQueued < buffer_count_) {
if (vState.BuffersQueued == 0) { if (vState.BuffersQueued == 0) {
@@ -392,7 +397,7 @@ void FAudio_Output::write(uint16_t* finalWave, int) {
// the maximum number of buffers is currently queued // the maximum number of buffers is currently queued
if (!coreOptions.speedup && coreOptions.throttle && !gba_joybus_active) { if (!coreOptions.speedup && coreOptions.throttle && !gba_joybus_active) {
// wait for one buffer to finish playing // wait for one buffer to finish playing
if (!notify.WaitForSignal()) { if (notify.WaitForSignal()) {
device_changed = true; device_changed = true;
} }
} else { } else {
@@ -409,7 +414,7 @@ void FAudio_Output::write(uint16_t* finalWave, int) {
currentBuffer++; currentBuffer++;
currentBuffer %= (buffer_count_ + 1); // + 1 because we need one temporary buffer currentBuffer %= (buffer_count_ + 1); // + 1 because we need one temporary buffer
[[maybe_unused]] uint32_t hr = FAudioSourceVoice_SubmitSourceBuffer(sVoice, &buf, nullptr); [[maybe_unused]] uint32_t hr = FAudioSourceVoice_SubmitSourceBuffer(sVoice, &buf, nullptr);
VBAM_CHECK(hr == 0); assert(hr == 0);
} }
void FAudio_Output::pause() { void FAudio_Output::pause() {
@@ -418,7 +423,7 @@ void FAudio_Output::pause() {
if (playing) { if (playing) {
[[maybe_unused]] uint32_t hr = FAudioSourceVoice_Stop(sVoice, 0, FAUDIO_COMMIT_NOW); [[maybe_unused]] uint32_t hr = FAudioSourceVoice_Stop(sVoice, 0, FAUDIO_COMMIT_NOW);
VBAM_CHECK(hr == 0); assert(hr == 0);
playing = false; playing = false;
} }
} }
@@ -429,7 +434,7 @@ void FAudio_Output::resume() {
if (!playing) { if (!playing) {
[[maybe_unused]] int32_t hr = FAudioSourceVoice_Start(sVoice, 0, FAUDIO_COMMIT_NOW); [[maybe_unused]] int32_t hr = FAudioSourceVoice_Start(sVoice, 0, FAUDIO_COMMIT_NOW);
VBAM_CHECK(hr == 0); assert(hr == 0);
playing = true; playing = true;
} }
} }
@@ -440,7 +445,7 @@ void FAudio_Output::reset() {
if (playing) { if (playing) {
[[maybe_unused]] uint32_t hr = FAudioSourceVoice_Stop(sVoice, 0, FAUDIO_COMMIT_NOW); [[maybe_unused]] uint32_t hr = FAudioSourceVoice_Stop(sVoice, 0, FAUDIO_COMMIT_NOW);
VBAM_CHECK(hr == 0); assert(hr == 0);
} }
FAudioSourceVoice_FlushSourceBuffers(sVoice); FAudioSourceVoice_FlushSourceBuffers(sVoice);
@@ -457,7 +462,7 @@ void FAudio_Output::setThrottle(unsigned short throttle_) {
[[maybe_unused]] uint32_t hr = [[maybe_unused]] uint32_t hr =
FAudioSourceVoice_SetFrequencyRatio(sVoice, (float)throttle_ / 100.0f, FAUDIO_COMMIT_NOW); FAudioSourceVoice_SetFrequencyRatio(sVoice, (float)throttle_ / 100.0f, FAUDIO_COMMIT_NOW);
VBAM_CHECK(hr == 0); assert(hr == 0);
} }
} // namespace } // namespace
@@ -484,11 +489,8 @@ std::vector<AudioDevice> GetFAudioDevices() {
} }
std::vector<AudioDevice> devices; std::vector<AudioDevice> devices;
#if defined(__WXMSW__)
// Add a separate default device on Windows.
devices.reserve(dev_count + 1); devices.reserve(dev_count + 1);
devices.push_back({_("Default device"), wxEmptyString}); devices.push_back({_("Default device"), wxEmptyString});
#endif
for (uint32_t i = 0; i < dev_count; i++) { for (uint32_t i = 0; i < dev_count; i++) {
FAudioDeviceDetails dd; FAudioDeviceDetails dd;
@@ -497,9 +499,9 @@ std::vector<AudioDevice> GetFAudioDevices() {
continue; continue;
} }
// Convert to UTF-8. const wxString display_name(reinterpret_cast<wchar_t*>(dd.DisplayName));
const wxString display_name = config::utf16_to_utf8(dd.DisplayName); const wxString device_id(reinterpret_cast<wchar_t*>(dd.DeviceID));
const wxString device_id = config::utf16_to_utf8(dd.DeviceID);
devices.push_back({display_name, device_id}); devices.push_back({display_name, device_id});
} }
@@ -512,4 +514,4 @@ std::unique_ptr<SoundDriver> CreateFAudioDriver() {
} }
} // namespace internal } // namespace internal
} // namespace audio } // namespace audio

View File

@@ -30,12 +30,13 @@ typedef ALCboolean(ALC_APIENTRY* LPALCISEXTENSIONPRESENT)(ALCdevice* device,
typedef const ALCchar*(ALC_APIENTRY* LPALCGETSTRING)(ALCdevice* device, ALCenum param); typedef const ALCchar*(ALC_APIENTRY* LPALCGETSTRING)(ALCdevice* device, ALCenum param);
#endif #endif
#include <cassert>
#include <wx/arrstr.h> #include <wx/arrstr.h>
#include <wx/log.h> #include <wx/log.h>
#include <wx/translation.h> #include <wx/translation.h>
#include <wx/utils.h> #include <wx/utils.h>
#include "core/base/check.h"
#include "core/gba/gbaGlobals.h" #include "core/gba/gbaGlobals.h"
#include "core/gba/gbaSound.h" #include "core/gba/gbaSound.h"
#include "wx/config/option-proxy.h" #include "wx/config/option-proxy.h"
@@ -46,7 +47,7 @@ namespace internal {
namespace { namespace {
// Debug // Debug
#define ASSERT_SUCCESS VBAM_CHECK(AL_NO_ERROR == alGetError()) #define ASSERT_SUCCESS assert(AL_NO_ERROR == alGetError())
#ifndef LOGALL #ifndef LOGALL
// replace logging functions with comments // replace logging functions with comments
@@ -170,7 +171,7 @@ void OpenAL::debugState() {
bool OpenAL::init(long sampleRate) { bool OpenAL::init(long sampleRate) {
winlog("OpenAL::init\n"); winlog("OpenAL::init\n");
VBAM_CHECK(initialized == false); assert(initialized == false);
const wxString& audio_device = OPTION(kSoundAudioDevice); const wxString& audio_device = OPTION(kSoundAudioDevice);
if (!audio_device.empty()) { if (!audio_device.empty()) {
@@ -190,9 +191,9 @@ bool OpenAL::init(long sampleRate) {
} }
context = alcCreateContext(device, nullptr); context = alcCreateContext(device, nullptr);
VBAM_CHECK(context != nullptr); assert(context != nullptr);
ALCboolean retVal = alcMakeContextCurrent(context); ALCboolean retVal = alcMakeContextCurrent(context);
VBAM_CHECK(ALC_TRUE == retVal); assert(ALC_TRUE == retVal);
alGenBuffers(OPTION(kSoundBuffers), buffer); alGenBuffers(OPTION(kSoundBuffers), buffer);
ASSERT_SUCCESS; ASSERT_SUCCESS;
alGenSources(1, &source); alGenSources(1, &source);
@@ -337,7 +338,7 @@ void OpenAL::write(uint16_t* finalWave, int length) {
return; return;
} }
VBAM_CHECK(nBuffersProcessed > 0); assert(nBuffersProcessed > 0);
// unqueue buffer // unqueue buffer
tempBuffer = 0; tempBuffer = 0;

View File

@@ -11,7 +11,6 @@
#include <wx/msgdlg.h> #include <wx/msgdlg.h>
#include "components/filters_interframe/interframe.h" #include "components/filters_interframe/interframe.h"
#include "core/base/check.h"
#include "core/base/version.h" #include "core/base/version.h"
#include "core/gb/gb.h" #include "core/gb/gb.h"
#include "core/gb/gbCheats.h" #include "core/gb/gbCheats.h"
@@ -33,7 +32,7 @@
void MainFrame::GetMenuOptionBool(const wxString& menuName, bool* field) void MainFrame::GetMenuOptionBool(const wxString& menuName, bool* field)
{ {
VBAM_CHECK(field); assert(field);
*field = !*field; *field = !*field;
int id = wxXmlResource::GetXRCID(menuName); int id = wxXmlResource::GetXRCID(menuName);
@@ -49,7 +48,7 @@ void MainFrame::GetMenuOptionBool(const wxString& menuName, bool* field)
void MainFrame::GetMenuOptionConfig(const wxString& menu_name, void MainFrame::GetMenuOptionConfig(const wxString& menu_name,
const config::OptionID& option_id) { const config::OptionID& option_id) {
config::Option* option = config::Option::ByID(option_id); config::Option* option = config::Option::ByID(option_id);
VBAM_CHECK(option); assert(option);
int id = wxXmlResource::GetXRCID(menu_name); int id = wxXmlResource::GetXRCID(menu_name);
for (size_t i = 0; i < checkable_mi.size(); i++) { for (size_t i = 0; i < checkable_mi.size(); i++) {
@@ -65,7 +64,7 @@ void MainFrame::GetMenuOptionConfig(const wxString& menu_name,
option->SetInt(is_checked); option->SetInt(is_checked);
break; break;
default: default:
VBAM_CHECK(false); assert(false);
return; return;
} }
break; break;
@@ -74,7 +73,7 @@ void MainFrame::GetMenuOptionConfig(const wxString& menu_name,
void MainFrame::GetMenuOptionInt(const wxString& menuName, int* field, int mask) void MainFrame::GetMenuOptionInt(const wxString& menuName, int* field, int mask)
{ {
VBAM_CHECK(field); assert(field);
int value = mask; int value = mask;
bool is_checked = ((*field) & (mask)) != (value); bool is_checked = ((*field) & (mask)) != (value);
int id = wxXmlResource::GetXRCID(menuName); int id = wxXmlResource::GetXRCID(menuName);
@@ -126,7 +125,7 @@ static void toggleBitVar(bool *menuValue, int *globalVar, int mask)
EVT_HANDLER(wxID_OPEN, "Open ROM...") EVT_HANDLER(wxID_OPEN, "Open ROM...")
{ {
static int open_ft = 0; static int open_ft = 0;
const wxString gba_rom_dir = OPTION(kGBAROMDir); const wxString& gba_rom_dir = OPTION(kGBAROMDir);
// FIXME: ignore if non-existent or not a dir // FIXME: ignore if non-existent or not a dir
wxString pats = _( wxString pats = _(
@@ -158,7 +157,7 @@ EVT_HANDLER(wxID_OPEN, "Open ROM...")
EVT_HANDLER(OpenGB, "Open GB...") EVT_HANDLER(OpenGB, "Open GB...")
{ {
static int open_ft = 0; static int open_ft = 0;
const wxString gb_rom_dir = OPTION(kGBROMDir); const wxString& gb_rom_dir = OPTION(kGBROMDir);
// FIXME: ignore if non-existent or not a dir // FIXME: ignore if non-existent or not a dir
wxString pats = _( wxString pats = _(
@@ -185,7 +184,7 @@ EVT_HANDLER(OpenGB, "Open GB...")
EVT_HANDLER(OpenGBC, "Open GBC...") EVT_HANDLER(OpenGBC, "Open GBC...")
{ {
static int open_ft = 0; static int open_ft = 0;
const wxString gbc_rom_dir = OPTION(kGBGBCROMDir); const wxString& gbc_rom_dir = OPTION(kGBGBCROMDir);
// FIXME: ignore if non-existent or not a dir // FIXME: ignore if non-existent or not a dir
wxString pats = _( wxString pats = _(
@@ -1990,7 +1989,7 @@ EVT_HANDLER(GameBoyAdvanceConfigure, "Game Boy Advance options...")
XRCCTRL(*dlg, "GameCode", wxControl) XRCCTRL(*dlg, "GameCode", wxControl)
->SetLabel(s); ->SetLabel(s);
cmt = wxString((const char*)&g_rom[0xa0], wxConvLibc, 12); cmt = wxString((const char*)&g_rom[0xa0], wxConvLibc, 12);
wxFileConfig* cfg = wxGetApp().overrides_.get(); wxFileConfig* cfg = wxGetApp().overrides;
if (cfg->HasGroup(s)) { if (cfg->HasGroup(s)) {
cfg->SetPath(s); cfg->SetPath(s);
@@ -2024,7 +2023,7 @@ EVT_HANDLER(GameBoyAdvanceConfigure, "Game Boy Advance options...")
if (panel->game_type() == IMAGE_GBA) { if (panel->game_type() == IMAGE_GBA) {
agbPrintEnable(OPTION(kPrefAgbPrint)); agbPrintEnable(OPTION(kPrefAgbPrint));
wxString s = wxString((const char*)&g_rom[0xac], wxConvLibc, 4); wxString s = wxString((const char*)&g_rom[0xac], wxConvLibc, 4);
wxFileConfig* cfg = wxGetApp().overrides_.get(); wxFileConfig* cfg = wxGetApp().overrides;
bool chg; bool chg;
if (cfg->HasGroup(s)) { if (cfg->HasGroup(s)) {
@@ -2219,7 +2218,7 @@ EVT_HANDLER(FAQ, "VBA-M support forum")
EVT_HANDLER(Translate, "Translations") EVT_HANDLER(Translate, "Translations")
{ {
wxLaunchDefaultBrowser(wxT("https://explore.transifex.com/bgk/vba-m/")); wxLaunchDefaultBrowser(wxT("http://www.transifex.com/projects/p/vba-m"));
} }
// was About // was About
@@ -2297,7 +2296,7 @@ EVT_HANDLER(RetainAspect, "Retain aspect ratio when resizing")
EVT_HANDLER(Printer, "Enable printer emulation") EVT_HANDLER(Printer, "Enable printer emulation")
{ {
GetMenuOptionInt("Printer", &coreOptions.gbPrinterEnabled, 1); GetMenuOptionInt("Printer", &coreOptions.winGbPrinterEnabled, 1);
#if (defined __WIN32__ || defined _WIN32) #if (defined __WIN32__ || defined _WIN32)
#ifndef NO_LINK #ifndef NO_LINK
gbSerialFunction = gbStartLink; gbSerialFunction = gbStartLink;
@@ -2305,7 +2304,7 @@ EVT_HANDLER(Printer, "Enable printer emulation")
gbSerialFunction = NULL; gbSerialFunction = NULL;
#endif #endif
#endif #endif
if (coreOptions.gbPrinterEnabled) if (coreOptions.winGbPrinterEnabled)
gbSerialFunction = gbPrinterSend; gbSerialFunction = gbPrinterSend;
update_opts(); update_opts();

View File

@@ -1,5 +1,5 @@
# This defines the vbam-wx-config target and the # This defines the vbam-wx-config target and the
# `VBAM_LOCALIZABLE_WX_CONFIG_FILES` variable, containing the list of # `VBAM_LOCALIZABLE_WX_CONFIG_FILES` variable, containing the list of
# localizable files in the vbam-wx-config target. # localizable files in the vbam-wx-config target.
# I don't like duplicating/triplicating code, so I only declare # I don't like duplicating/triplicating code, so I only declare
@@ -61,9 +61,15 @@ target_sources(vbam-wx-config
user-input.h user-input.h
) )
target_link_libraries(vbam-wx-config
PUBLIC
nonstd-lib
vbam-core
)
configure_wx_target(vbam-wx-config) configure_wx_target(vbam-wx-config)
if(BUILD_TESTING) if (BUILD_TESTING)
add_executable(vbam-wx-config-tests add_executable(vbam-wx-config-tests
bindings-test.cpp bindings-test.cpp
command-test.cpp command-test.cpp
@@ -73,12 +79,10 @@ if(BUILD_TESTING)
user-input-test.cpp user-input-test.cpp
) )
target_link_libraries(vbam-wx-config-tests target_link_libraries(vbam-wx-config-tests
# Test deps. vbam-core
vbam-core-fake vbam-core-fake
vbam-wx-fake-opts
# Target deps.
vbam-wx-config vbam-wx-config
vbam-wx-fake-opts
GTest::gtest_main GTest::gtest_main
) )

View File

@@ -176,7 +176,7 @@ void Bindings::AssignInputsToCommand(const std::unordered_set<UserInput>& inputs
} }
void Bindings::UnassignInput(const UserInput& input) { void Bindings::UnassignInput(const UserInput& input) {
VBAM_CHECK(input); assert(input);
auto iter = input_to_control_.find(input); auto iter = input_to_control_.find(input);
if (iter == input_to_control_.end()) { if (iter == input_to_control_.end()) {
@@ -194,7 +194,7 @@ void Bindings::UnassignInput(const UserInput& input) {
// Otherwise, just remove it from the 2 maps. // Otherwise, just remove it from the 2 maps.
auto command_iter = control_to_inputs_.find(iter->second); auto command_iter = control_to_inputs_.find(iter->second);
VBAM_CHECK(command_iter != control_to_inputs_.end()); assert(command_iter != control_to_inputs_.end());
command_iter->second.erase(input); command_iter->second.erase(input);
if (command_iter->second.empty()) { if (command_iter->second.empty()) {
@@ -238,7 +238,7 @@ void Bindings::UnassignDefaultBinding(const UserInput& input) {
} }
auto command_iter = control_to_inputs_.find(input_iter->second); auto command_iter = control_to_inputs_.find(input_iter->second);
VBAM_CHECK(command_iter != control_to_inputs_.end()); assert(command_iter != control_to_inputs_.end());
command_iter->second.erase(input); command_iter->second.erase(input);
if (command_iter->second.empty()) { if (command_iter->second.empty()) {

View File

@@ -4,8 +4,6 @@
#include <wx/wxcrt.h> #include <wx/wxcrt.h>
#include "core/base/check.h"
// Initializer for struct cmditem // Initializer for struct cmditem
cmditem new_cmditem(const wxString cmd, cmditem new_cmditem(const wxString cmd,
const wxString name, const wxString name,
@@ -24,7 +22,7 @@ namespace config {
} }
// Command not found. This should never happen. // Command not found. This should never happen.
VBAM_NOTREACHED(); assert(false);
return wxEmptyString; return wxEmptyString;
} }
@@ -36,7 +34,7 @@ namespace config {
} }
// Command not found. This should never happen. // Command not found. This should never happen.
VBAM_NOTREACHED(); assert(false);
return wxEmptyString; return wxEmptyString;
} }

View File

@@ -2,6 +2,7 @@
#define VBAM_WX_CONFIG_COMMAND_H_ #define VBAM_WX_CONFIG_COMMAND_H_
#include <array> #include <array>
#include <cassert>
#include <functional> #include <functional>
#include <optional.hpp> #include <optional.hpp>
@@ -9,8 +10,6 @@
#include <wx/string.h> #include <wx/string.h>
#include "core/base/check.h"
namespace config { namespace config {
// clang-format off // clang-format off
@@ -57,7 +56,7 @@ static constexpr size_t kNbJoypads = 4;
// Represents an emulated joypad. The internal index is zero-based. // Represents an emulated joypad. The internal index is zero-based.
class GameJoy { class GameJoy {
public: public:
constexpr explicit GameJoy(size_t index) : index_(index) { VBAM_CHECK(index < kNbJoypads); } constexpr explicit GameJoy(size_t index) : index_(index) { assert(index < kNbJoypads); }
// The underlying zero-based index for this emulated joypad. // The underlying zero-based index for this emulated joypad.
constexpr size_t index() const { return index_; } constexpr size_t index() const { return index_; }
@@ -180,12 +179,12 @@ public:
bool is_shortcut() const { return tag() == Tag::kShortcut; } bool is_shortcut() const { return tag() == Tag::kShortcut; }
const GameCommand& game() const { const GameCommand& game() const {
VBAM_CHECK(is_game()); assert(is_game());
return nonstd::get<GameCommand>(control_); return nonstd::get<GameCommand>(control_);
} }
const ShortcutCommand& shortcut() const { const ShortcutCommand& shortcut() const {
VBAM_CHECK(is_shortcut()); assert(is_shortcut());
return nonstd::get<ShortcutCommand>(control_); return nonstd::get<ShortcutCommand>(control_);
} }
@@ -202,7 +201,8 @@ public:
return shortcut() < other.shortcut(); return shortcut() < other.shortcut();
} }
VBAM_NOTREACHED(); // Unreachable.
assert(false);
return false; return false;
} else { } else {
return tag_ < other.tag_; return tag_ < other.tag_;
@@ -260,7 +260,8 @@ struct std::hash<config::Command> {
return std::hash<config::ShortcutCommand>{}(control.shortcut()); return std::hash<config::ShortcutCommand>{}(control.shortcut());
} }
VBAM_NOTREACHED(); // Unreachable.
assert(false);
return 0; return 0;
} }
}; };

View File

@@ -31,6 +31,7 @@ LIST(SORT EVLINES)
STRING(REGEX REPLACE ",\n\$" "\n" EVLINES "${EVLINES}") STRING(REGEX REPLACE ",\n\$" "\n" EVLINES "${EVLINES}")
FILE(APPEND "${CMDTAB}" ${EVLINES}) FILE(APPEND "${CMDTAB}" ${EVLINES})
FILE(APPEND "${CMDTAB}" "};\n") FILE(APPEND "${CMDTAB}" "};\n")
FILE(APPEND "${CMDTAB}" "const int ncmds = sizeof(cmdtab) / sizeof(cmdtab[0]);\n")
# cmdhandlers.h contains prototypes for all handlers # cmdhandlers.h contains prototypes for all handlers
FILE(WRITE "${EVPROTO}" "// Generated from cmdevents.cpp; do not edit\n") FILE(WRITE "${EVPROTO}" "// Generated from cmdevents.cpp; do not edit\n")

View File

@@ -135,8 +135,7 @@ TEST_F(GamepadTest, NonDefaultInput) {
const config::KeyboardInput f1(WXK_F1); const config::KeyboardInput f1(WXK_F1);
// Assign F1 to "Up". // Assign F1 to "Up".
bindings()->AssignInputToCommand(f1, bindings()->AssignInputToCommand(f1, config::GameCommand(config::GameJoy(0), config::GameKey::Up));
config::GameCommand(config::GameJoy(0), config::GameKey::Up));
// Press F1, the up key should be pressed. // Press F1, the up key should be pressed.
EXPECT_TRUE(gamepad()->OnInputPressed(f1)); EXPECT_TRUE(gamepad()->OnInputPressed(f1));

View File

@@ -1,7 +1,5 @@
#include "wx/config/emulated-gamepad.h" #include "wx/config/emulated-gamepad.h"
#include "core/base/check.h"
namespace config { namespace config {
namespace { namespace {
@@ -64,7 +62,7 @@ EmulatedGamepad::EmulatedGamepad(const BindingsProvider bindings_provider)
: joypads_({0, 0, 0, 0}), bindings_provider_(bindings_provider) {} : joypads_({0, 0, 0, 0}), bindings_provider_(bindings_provider) {}
bool EmulatedGamepad::OnInputPressed(const config::UserInput& user_input) { bool EmulatedGamepad::OnInputPressed(const config::UserInput& user_input) {
VBAM_CHECK(user_input); assert(user_input);
const auto command = bindings_provider_()->CommandForInput(user_input); const auto command = bindings_provider_()->CommandForInput(user_input);
if (!command || !command->is_game()) { if (!command || !command->is_game()) {
@@ -87,7 +85,7 @@ bool EmulatedGamepad::OnInputPressed(const config::UserInput& user_input) {
} }
bool EmulatedGamepad::OnInputReleased(const config::UserInput& user_input) { bool EmulatedGamepad::OnInputReleased(const config::UserInput& user_input) {
VBAM_CHECK(user_input); assert(user_input);
const auto command = bindings_provider_()->CommandForInput(user_input); const auto command = bindings_provider_()->CommandForInput(user_input);
if (!command || !command->is_game()) { if (!command || !command->is_game()) {

View File

@@ -11,7 +11,6 @@
#include <wx/log.h> #include <wx/log.h>
#include <wx/translation.h> #include <wx/translation.h>
#include "core/base/check.h"
#include "core/base/system.h" #include "core/base/system.h"
#include "core/gb/gbGlobals.h" #include "core/gb/gbGlobals.h"
#include "core/gba/gbaSound.h" #include "core/gba/gbaSound.h"
@@ -312,7 +311,7 @@ std::array<Option, kNbOptions>& Option::All() {
Option(OptionID::kPrefFlashSize, &g_owned_opts.flash_size, 0, 1), Option(OptionID::kPrefFlashSize, &g_owned_opts.flash_size, 0, 1),
Option(OptionID::kPrefFrameSkip, &g_owned_opts.frame_skip, -1, 9), Option(OptionID::kPrefFrameSkip, &g_owned_opts.frame_skip, -1, 9),
Option(OptionID::kPrefGBPaletteOption, &gbPaletteOption, 0, 2), Option(OptionID::kPrefGBPaletteOption, &gbPaletteOption, 0, 2),
Option(OptionID::kPrefGBPrinter, &coreOptions.gbPrinterEnabled, 0, 1), Option(OptionID::kPrefGBPrinter, &coreOptions.winGbPrinterEnabled, 0, 1),
Option(OptionID::kPrefGDBBreakOnLoad, &g_owned_opts.gdb_break_on_load), Option(OptionID::kPrefGDBBreakOnLoad, &g_owned_opts.gdb_break_on_load),
Option(OptionID::kPrefGDBPort, &gopts.gdb_port, 0, 65535), Option(OptionID::kPrefGDBPort, &gopts.gdb_port, 0, 65535),
#ifndef NO_LINK #ifndef NO_LINK
@@ -328,10 +327,9 @@ std::array<Option, kNbOptions>& Option::All() {
Option(OptionID::kPrefSkipSaveGameCheats, &coreOptions.skipSaveGameCheats, 0, 1), Option(OptionID::kPrefSkipSaveGameCheats, &coreOptions.skipSaveGameCheats, 0, 1),
Option(OptionID::kPrefSkipSaveGameBattery, &coreOptions.skipSaveGameBattery, 0, 1), Option(OptionID::kPrefSkipSaveGameBattery, &coreOptions.skipSaveGameBattery, 0, 1),
Option(OptionID::kPrefThrottle, &coreOptions.throttle, 0, 450), Option(OptionID::kPrefThrottle, &coreOptions.throttle, 0, 450),
Option(OptionID::kPrefSpeedupThrottle, &coreOptions.speedup_throttle, 0, 450), Option(OptionID::kPrefSpeedupThrottle, &coreOptions.speedup_throttle, 0, 3000),
Option(OptionID::kPrefSpeedupFrameSkip, &coreOptions.speedup_frame_skip, 0, 40), Option(OptionID::kPrefSpeedupFrameSkip, &coreOptions.speedup_frame_skip, 0, 300),
Option(OptionID::kPrefSpeedupThrottleFrameSkip, &coreOptions.speedup_throttle_frame_skip), Option(OptionID::kPrefSpeedupThrottleFrameSkip, &coreOptions.speedup_throttle_frame_skip),
Option(OptionID::kPrefSpeedupMute, &coreOptions.speedup_mute),
Option(OptionID::kPrefUseBiosGB, &g_owned_opts.use_bios_file_gb), Option(OptionID::kPrefUseBiosGB, &g_owned_opts.use_bios_file_gb),
Option(OptionID::kPrefUseBiosGBA, &g_owned_opts.use_bios_file_gba), Option(OptionID::kPrefUseBiosGBA, &g_owned_opts.use_bios_file_gba),
Option(OptionID::kPrefUseBiosGBC, &g_owned_opts.use_bios_file_gbc), Option(OptionID::kPrefUseBiosGBC, &g_owned_opts.use_bios_file_gbc),
@@ -532,8 +530,6 @@ const std::array<OptionData, kNbOptions + 1> kAllOptionsData = {
"throttle)")}, "throttle)")},
OptionData{"preferences/speedupThrottleFrameSkip", "", OptionData{"preferences/speedupThrottleFrameSkip", "",
_("Use frame skip for speedup throttle")}, _("Use frame skip for speedup throttle")},
OptionData{"preferences/speedupMute", "",
_("Mute sound during speedup")},
OptionData{"preferences/useBiosGB", "BootRomGB", _("Use the specified BIOS file for Game Boy")}, OptionData{"preferences/useBiosGB", "BootRomGB", _("Use the specified BIOS file for Game Boy")},
OptionData{"preferences/useBiosGBA", "BootRomEn", _("Use the specified BIOS file")}, OptionData{"preferences/useBiosGBA", "BootRomEn", _("Use the specified BIOS file")},
OptionData{"preferences/useBiosGBC", "BootRomGBC", OptionData{"preferences/useBiosGBC", "BootRomGBC",
@@ -584,14 +580,14 @@ const std::array<OptionData, kNbOptions + 1> kAllOptionsData = {
}; };
nonstd::optional<OptionID> StringToOptionId(const wxString& input) { nonstd::optional<OptionID> StringToOptionId(const wxString& input) {
static const std::map<wxString, OptionID> kStringToOptionId([] { static std::map<wxString, OptionID> kStringToOptionId;
std::map<wxString, OptionID> string_to_option_id; if (kStringToOptionId.empty()) {
for (size_t i = 0; i < kNbOptions; i++) { for (size_t i = 0; i < kNbOptions; i++) {
string_to_option_id.emplace(kAllOptionsData[i].config_name, static_cast<OptionID>(i)); kStringToOptionId.emplace(kAllOptionsData[i].config_name,
static_cast<OptionID>(i));
} }
VBAM_CHECK(string_to_option_id.size() == kNbOptions); assert(kStringToOptionId.size() == kNbOptions);
return string_to_option_id; }
}());
const auto iter = kStringToOptionId.find(input); const auto iter = kStringToOptionId.find(input);
if (iter == kStringToOptionId.end()) { if (iter == kStringToOptionId.end()) {
@@ -602,43 +598,42 @@ nonstd::optional<OptionID> StringToOptionId(const wxString& input) {
wxString FilterToString(const Filter& value) { wxString FilterToString(const Filter& value) {
const size_t size_value = static_cast<size_t>(value); const size_t size_value = static_cast<size_t>(value);
VBAM_CHECK(size_value < kNbFilters); assert(size_value < kNbFilters);
return kFilterStrings[size_value]; return kFilterStrings[size_value];
} }
wxString InterframeToString(const Interframe& value) { wxString InterframeToString(const Interframe& value) {
const size_t size_value = static_cast<size_t>(value); const size_t size_value = static_cast<size_t>(value);
VBAM_CHECK(size_value < kNbInterframes); assert(size_value < kNbInterframes);
return kInterframeStrings[size_value]; return kInterframeStrings[size_value];
} }
wxString RenderMethodToString(const RenderMethod& value) { wxString RenderMethodToString(const RenderMethod& value) {
const size_t size_value = static_cast<size_t>(value); const size_t size_value = static_cast<size_t>(value);
VBAM_CHECK(size_value < kNbRenderMethods); assert(size_value < kNbRenderMethods);
return kRenderMethodStrings[size_value]; return kRenderMethodStrings[size_value];
} }
wxString AudioApiToString(const AudioApi& value) { wxString AudioApiToString(const AudioApi& value) {
const size_t size_value = static_cast<size_t>(value); const size_t size_value = static_cast<size_t>(value);
VBAM_CHECK(size_value < kNbAudioApis); assert(size_value < kNbAudioApis);
return kAudioApiStrings[size_value]; return kAudioApiStrings[size_value];
} }
wxString AudioRateToString(const AudioRate& value) { wxString AudioRateToString(const AudioRate& value) {
const size_t size_value = static_cast<size_t>(value); const size_t size_value = static_cast<size_t>(value);
VBAM_CHECK(size_value < kNbSoundRate); assert(size_value < kNbSoundRate);
return kAudioRateStrings[size_value]; return kAudioRateStrings[size_value];
} }
Filter StringToFilter(const wxString& config_name, const wxString& input) { Filter StringToFilter(const wxString& config_name, const wxString& input) {
static const std::map<wxString, Filter> kStringToFilter([] { static std::map<wxString, Filter> kStringToFilter;
std::map<wxString, Filter> string_to_filter; if (kStringToFilter.empty()) {
for (size_t i = 0; i < kNbFilters; i++) { for (size_t i = 0; i < kNbFilters; i++) {
string_to_filter.emplace(kFilterStrings[i], static_cast<Filter>(i)); kStringToFilter.emplace(kFilterStrings[i], static_cast<Filter>(i));
} }
VBAM_CHECK(string_to_filter.size() == kNbFilters); assert(kStringToFilter.size() == kNbFilters);
return string_to_filter; }
}());
const auto iter = kStringToFilter.find(input); const auto iter = kStringToFilter.find(input);
if (iter == kStringToFilter.end()) { if (iter == kStringToFilter.end()) {
@@ -651,14 +646,14 @@ Filter StringToFilter(const wxString& config_name, const wxString& input) {
} }
Interframe StringToInterframe(const wxString& config_name, const wxString& input) { Interframe StringToInterframe(const wxString& config_name, const wxString& input) {
static const std::map<wxString, Interframe> kStringToInterframe([] { static std::map<wxString, Interframe> kStringToInterframe;
std::map<wxString, Interframe> string_to_interframe; if (kStringToInterframe.empty()) {
for (size_t i = 0; i < kNbInterframes; i++) { for (size_t i = 0; i < kNbInterframes; i++) {
string_to_interframe.emplace(kInterframeStrings[i], static_cast<Interframe>(i)); kStringToInterframe.emplace(kInterframeStrings[i],
static_cast<Interframe>(i));
} }
VBAM_CHECK(string_to_interframe.size() == kNbInterframes); assert(kStringToInterframe.size() == kNbInterframes);
return string_to_interframe; }
}());
const auto iter = kStringToInterframe.find(input); const auto iter = kStringToInterframe.find(input);
if (iter == kStringToInterframe.end()) { if (iter == kStringToInterframe.end()) {
@@ -672,14 +667,14 @@ Interframe StringToInterframe(const wxString& config_name, const wxString& input
RenderMethod StringToRenderMethod(const wxString& config_name, RenderMethod StringToRenderMethod(const wxString& config_name,
const wxString& input) { const wxString& input) {
static const std::map<wxString, RenderMethod> kStringToRenderMethod([] { static std::map<wxString, RenderMethod> kStringToRenderMethod;
std::map<wxString, RenderMethod> string_to_render_method; if (kStringToRenderMethod.empty()) {
for (size_t i = 0; i < kNbRenderMethods; i++) { for (size_t i = 0; i < kNbRenderMethods; i++) {
string_to_render_method.emplace(kRenderMethodStrings[i], static_cast<RenderMethod>(i)); kStringToRenderMethod.emplace(kRenderMethodStrings[i],
static_cast<RenderMethod>(i));
} }
VBAM_CHECK(string_to_render_method.size() == kNbRenderMethods); assert(kStringToRenderMethod.size() == kNbRenderMethods);
return string_to_render_method; }
}());
const auto iter = kStringToRenderMethod.find(input); const auto iter = kStringToRenderMethod.find(input);
if (iter == kStringToRenderMethod.end()) { if (iter == kStringToRenderMethod.end()) {
@@ -692,14 +687,14 @@ RenderMethod StringToRenderMethod(const wxString& config_name,
} }
AudioApi StringToAudioApi(const wxString& config_name, const wxString& input) { AudioApi StringToAudioApi(const wxString& config_name, const wxString& input) {
static const std::map<wxString, AudioApi> kStringToAudioApi([] { static std::map<wxString, AudioApi> kStringToAudioApi;
std::map<wxString, AudioApi> string_to_audio_api; if (kStringToAudioApi.empty()) {
for (size_t i = 0; i < kNbAudioApis; i++) { for (size_t i = 0; i < kNbAudioApis; i++) {
string_to_audio_api.emplace(kAudioApiStrings[i], static_cast<AudioApi>(i)); kStringToAudioApi.emplace(kAudioApiStrings[i],
static_cast<AudioApi>(i));
} }
VBAM_CHECK(string_to_audio_api.size() == kNbAudioApis); assert(kStringToAudioApi.size() == kNbAudioApis);
return string_to_audio_api; }
}());
const auto iter = kStringToAudioApi.find(input); const auto iter = kStringToAudioApi.find(input);
if (iter == kStringToAudioApi.end()) { if (iter == kStringToAudioApi.end()) {
@@ -712,14 +707,13 @@ AudioApi StringToAudioApi(const wxString& config_name, const wxString& input) {
} }
AudioRate StringToSoundQuality(const wxString& config_name, const wxString& input) { AudioRate StringToSoundQuality(const wxString& config_name, const wxString& input) {
static const std::map<wxString, AudioRate> kStringToSoundQuality([] { static std::map<wxString, AudioRate> kStringToSoundQuality;
std::map<wxString, AudioRate> string_to_sound_quality; if (kStringToSoundQuality.empty()) {
for (size_t i = 0; i < kNbSoundRate; i++) { for (size_t i = 0; i < kNbSoundRate; i++) {
string_to_sound_quality.emplace(kAudioRateStrings[i], static_cast<AudioRate>(i)); kStringToSoundQuality.emplace(kAudioRateStrings[i], static_cast<AudioRate>(i));
} }
VBAM_CHECK(string_to_sound_quality.size() == kNbSoundRate); assert(kStringToSoundQuality.size() == kNbSoundRate);
return string_to_sound_quality; }
}());
const auto iter = kStringToSoundQuality.find(input); const auto iter = kStringToSoundQuality.find(input);
if (iter == kStringToSoundQuality.end()) { if (iter == kStringToSoundQuality.end()) {
@@ -733,23 +727,28 @@ AudioRate StringToSoundQuality(const wxString& config_name, const wxString& inpu
wxString AllEnumValuesForType(Option::Type type) { wxString AllEnumValuesForType(Option::Type type) {
switch (type) { switch (type) {
case Option::Type::kFilter: { case Option::Type::kFilter: {
static const wxString kAllFilterValues(AllEnumValuesForArray(kFilterStrings)); static const wxString kAllFilterValues =
AllEnumValuesForArray(kFilterStrings);
return kAllFilterValues; return kAllFilterValues;
} }
case Option::Type::kInterframe: { case Option::Type::kInterframe: {
static const wxString kAllInterframeValues(AllEnumValuesForArray(kInterframeStrings)); static const wxString kAllInterframeValues =
AllEnumValuesForArray(kInterframeStrings);
return kAllInterframeValues; return kAllInterframeValues;
} }
case Option::Type::kRenderMethod: { case Option::Type::kRenderMethod: {
static const wxString kAllRenderValues(AllEnumValuesForArray(kRenderMethodStrings)); static const wxString kAllRenderValues =
AllEnumValuesForArray(kRenderMethodStrings);
return kAllRenderValues; return kAllRenderValues;
} }
case Option::Type::kAudioApi: { case Option::Type::kAudioApi: {
static const wxString kAllAudioApiValues(AllEnumValuesForArray(kAudioApiStrings)); static const wxString kAllAudioApiValues =
AllEnumValuesForArray(kAudioApiStrings);
return kAllAudioApiValues; return kAllAudioApiValues;
} }
case Option::Type::kAudioRate: { case Option::Type::kAudioRate: {
static const wxString kAllSoundQualityValues(AllEnumValuesForArray(kAudioRateStrings)); static const wxString kAllSoundQualityValues =
AllEnumValuesForArray(kAudioRateStrings);
return kAllSoundQualityValues; return kAllSoundQualityValues;
} }
@@ -762,10 +761,10 @@ wxString AllEnumValuesForType(Option::Type type) {
case Option::Type::kUnsigned: case Option::Type::kUnsigned:
case Option::Type::kString: case Option::Type::kString:
case Option::Type::kGbPalette: case Option::Type::kGbPalette:
VBAM_NOTREACHED(); assert(false);
return wxEmptyString; return wxEmptyString;
} }
VBAM_NOTREACHED(); assert(false);
return wxEmptyString; return wxEmptyString;
} }
@@ -791,10 +790,10 @@ size_t MaxForType(Option::Type type) {
case Option::Type::kUnsigned: case Option::Type::kUnsigned:
case Option::Type::kString: case Option::Type::kString:
case Option::Type::kGbPalette: case Option::Type::kGbPalette:
VBAM_NOTREACHED(); assert(false);
return 0; return 0;
} }
VBAM_NOTREACHED(); assert(false);
return 0; return 0;
} }

View File

@@ -99,7 +99,6 @@ enum class OptionID {
kPrefSpeedupThrottle, kPrefSpeedupThrottle,
kPrefSpeedupFrameSkip, kPrefSpeedupFrameSkip,
kPrefSpeedupThrottleFrameSkip, kPrefSpeedupThrottleFrameSkip,
kPrefSpeedupMute,
kPrefUseBiosGB, kPrefUseBiosGB,
kPrefUseBiosGBA, kPrefUseBiosGBA,
kPrefUseBiosGBC, kPrefUseBiosGBC,

View File

@@ -1,10 +1,7 @@
#include "wx/config/option-observer.h" #include "wx/config/option-observer.h"
#include "core/base/check.h"
#include "wx/config/option.h" #include "wx/config/option.h"
#include "core/base/check.h"
namespace config { namespace config {
// An Option::Observer that calls a callback when an option has changed. // An Option::Observer that calls a callback when an option has changed.
@@ -13,7 +10,7 @@ public:
CallbackOptionObserver(const OptionID& option_id, CallbackOptionObserver(const OptionID& option_id,
std::function<void(Option*)> callback) std::function<void(Option*)> callback)
: Option::Observer(option_id), callback_(std::move(callback)) { : Option::Observer(option_id), callback_(std::move(callback)) {
VBAM_CHECK(callback_); assert(callback_);
} }
~CallbackOptionObserver() override = default; ~CallbackOptionObserver() override = default;

View File

@@ -103,7 +103,6 @@ static constexpr std::array<Option::Type, kNbOptions> kOptionsTypes = {
/*kPrefSpeedupThrottle*/ Option::Type::kUnsigned, /*kPrefSpeedupThrottle*/ Option::Type::kUnsigned,
/*kPrefSpeedupFrameSkip*/ Option::Type::kUnsigned, /*kPrefSpeedupFrameSkip*/ Option::Type::kUnsigned,
/*kPrefSpeedupThrottleFrameSkip*/ Option::Type::kBool, /*kPrefSpeedupThrottleFrameSkip*/ Option::Type::kBool,
/*kPrefSpeedupMute*/ Option::Type::kBool,
/*kPrefUseBiosGB*/ Option::Type::kBool, /*kPrefUseBiosGB*/ Option::Type::kBool,
/*kPrefUseBiosGBA*/ Option::Type::kBool, /*kPrefUseBiosGBA*/ Option::Type::kBool,
/*kPrefUseBiosGBC*/ Option::Type::kBool, /*kPrefUseBiosGBC*/ Option::Type::kBool,
@@ -175,43 +174,11 @@ private:
Option* option_; Option* option_;
}; };
template <typename T>
class OptionProxyNumeric {
public:
virtual T Get() const = 0;
virtual bool Set(T value) = 0;
virtual T Min() const = 0;
virtual T Max() const = 0;
bool operator++() { return *this += 1; }
bool operator--() { return *this -= 1; }
bool operator++(int) { return *this += 1; }
bool operator--(int) { return *this -= 1; }
bool operator+=(T value) {
const T new_value = Get() + value;
if (new_value > Max()) {
return Set(Max());
} else {
return Set(new_value);
}
}
bool operator-=(T value) {
const T new_value = Get() - value;
if (new_value < Min()) {
return Set(Min());
} else {
return Set(new_value);
}
}
operator T() const { return Get(); }
};
template <OptionID ID> template <OptionID ID>
class OptionProxy< class OptionProxy<
ID, ID,
typename std::enable_if<kOptionsTypes[static_cast<size_t>(ID)] == typename std::enable_if<kOptionsTypes[static_cast<size_t>(ID)] ==
Option::Type::kDouble>::type> : public OptionProxyNumeric<double> { Option::Type::kDouble>::type> {
public: public:
OptionProxy() : option_(Option::ByID(ID)) {} OptionProxy() : option_(Option::ByID(ID)) {}
~OptionProxy() = default; ~OptionProxy() = default;
@@ -220,7 +187,9 @@ public:
bool Set(double value) { return option_->SetDouble(value); } bool Set(double value) { return option_->SetDouble(value); }
double Min() const { return option_->GetDoubleMin(); } double Min() const { return option_->GetDoubleMin(); }
double Max() const { return option_->GetDoubleMax(); } double Max() const { return option_->GetDoubleMax(); }
bool operator=(double value) { return Set(value); } bool operator=(double value) { return Set(value); }
operator double() const { return Get(); }
private: private:
Option* option_; Option* option_;
@@ -230,7 +199,7 @@ template <OptionID ID>
class OptionProxy< class OptionProxy<
ID, ID,
typename std::enable_if<kOptionsTypes[static_cast<size_t>(ID)] == typename std::enable_if<kOptionsTypes[static_cast<size_t>(ID)] ==
Option::Type::kInt>::type> : public OptionProxyNumeric<int32_t> { Option::Type::kInt>::type> {
public: public:
OptionProxy() : option_(Option::ByID(ID)) {} OptionProxy() : option_(Option::ByID(ID)) {}
~OptionProxy() = default; ~OptionProxy() = default;
@@ -239,7 +208,25 @@ public:
bool Set(int32_t value) { return option_->SetInt(value); } bool Set(int32_t value) { return option_->SetInt(value); }
int32_t Min() const { return option_->GetIntMin(); } int32_t Min() const { return option_->GetIntMin(); }
int32_t Max() const { return option_->GetIntMax(); } int32_t Max() const { return option_->GetIntMax(); }
bool operator=(int32_t value) { return Set(value); } bool operator=(int32_t value) { return Set(value); }
bool operator+=(int32_t value) {
const int new_value = Get() + value;
if (new_value > Max()) {
return Set(Max());
} else {
return Set(new_value);
}
}
bool operator-=(int32_t value) {
const int new_value = Get() - value;
if (new_value < Min()) {
return Set(Min());
} else {
return Set(new_value);
}
}
operator int32_t() const { return Get(); }
private: private:
Option* option_; Option* option_;
@@ -249,7 +236,7 @@ template <OptionID ID>
class OptionProxy< class OptionProxy<
ID, ID,
typename std::enable_if<kOptionsTypes[static_cast<size_t>(ID)] == typename std::enable_if<kOptionsTypes[static_cast<size_t>(ID)] ==
Option::Type::kUnsigned>::type> : public OptionProxyNumeric<uint32_t> { Option::Type::kUnsigned>::type> {
public: public:
OptionProxy() : option_(Option::ByID(ID)) {} OptionProxy() : option_(Option::ByID(ID)) {}
~OptionProxy() = default; ~OptionProxy() = default;
@@ -258,7 +245,9 @@ public:
bool Set(uint32_t value) { return option_->SetUnsigned(value); } bool Set(uint32_t value) { return option_->SetUnsigned(value); }
uint32_t Min() const { return option_->GetUnsignedMin(); } uint32_t Min() const { return option_->GetUnsignedMin(); }
uint32_t Max() const { return option_->GetUnsignedMax(); } uint32_t Max() const { return option_->GetUnsignedMax(); }
bool operator=(uint32_t value) { return Set(value); }
bool operator=(int32_t value) { return Set(value); }
operator int32_t() const { return Get(); }
private: private:
Option* option_; Option* option_;

View File

@@ -21,16 +21,18 @@ TEST(OptionTest, Bool) {
EXPECT_TRUE(option->SetBool(false)); EXPECT_TRUE(option->SetBool(false));
EXPECT_FALSE(option->GetBool()); EXPECT_FALSE(option->GetBool());
EXPECT_DEATH(option->SetDouble(2.0), "is_double\\(\\)"); #if !defined(NDEBUG)
EXPECT_DEATH(option->SetInt(2), "is_int\\(\\)"); EXPECT_DEATH(option->SetDouble(2.0), ".*");
EXPECT_DEATH(option->SetUnsigned(2), "is_unsigned\\(\\)"); EXPECT_DEATH(option->SetInt(2), ".*");
EXPECT_DEATH(option->SetString("foo"), "is_string\\(\\)"); EXPECT_DEATH(option->SetUnsigned(2), ".*");
EXPECT_DEATH(option->SetFilter(config::Filter::kNone), "is_filter\\(\\)"); EXPECT_DEATH(option->SetString("foo"), ".*");
EXPECT_DEATH(option->SetInterframe(config::Interframe::kNone), "is_interframe\\(\\)"); EXPECT_DEATH(option->SetFilter(config::Filter::kNone), ".*");
EXPECT_DEATH(option->SetRenderMethod(config::RenderMethod::kSimple), "is_render_method\\(\\)"); EXPECT_DEATH(option->SetInterframe(config::Interframe::kNone), ".*");
EXPECT_DEATH(option->SetAudioApi(config::AudioApi::kOpenAL), "is_audio_api\\(\\)"); EXPECT_DEATH(option->SetRenderMethod(config::RenderMethod::kSimple), ".*");
EXPECT_DEATH(option->SetAudioRate(config::AudioRate::k11kHz), "is_audio_rate\\(\\)"); EXPECT_DEATH(option->SetAudioApi(config::AudioApi::kOpenAL), ".*");
EXPECT_DEATH(option->SetGbPalette({0, 1, 2, 3, 4, 5, 6, 7}), "is_gb_palette\\(\\)"); EXPECT_DEATH(option->SetAudioRate(config::AudioRate::k11kHz), ".*");
EXPECT_DEATH(option->SetGbPalette({0, 1, 2, 3, 4, 5, 6, 7}), ".*");
#endif // !defined(NDEBUG)
} }
TEST(OptionTest, Double) { TEST(OptionTest, Double) {
@@ -54,205 +56,18 @@ TEST(OptionTest, Double) {
EXPECT_FALSE(option->SetDouble(7.0)); EXPECT_FALSE(option->SetDouble(7.0));
EXPECT_DOUBLE_EQ(option->GetDouble(), 2.5); EXPECT_DOUBLE_EQ(option->GetDouble(), 2.5);
EXPECT_DEATH(option->SetBool(true), "is_bool\\(\\)"); #if !defined(NDEBUG)
EXPECT_DEATH(option->SetInt(2), "is_int\\(\\)"); EXPECT_DEATH(option->SetBool(true), ".*");
EXPECT_DEATH(option->SetUnsigned(2), "is_unsigned\\(\\)"); EXPECT_DEATH(option->SetInt(2), ".*");
EXPECT_DEATH(option->SetString("foo"), "is_string\\(\\)"); EXPECT_DEATH(option->SetUnsigned(2), ".*");
EXPECT_DEATH(option->SetFilter(config::Filter::kNone), "is_filter\\(\\)"); EXPECT_DEATH(option->SetString("foo"), ".*");
EXPECT_DEATH(option->SetInterframe(config::Interframe::kNone), "is_interframe\\(\\)"); EXPECT_DEATH(option->SetFilter(config::Filter::kNone), ".*");
EXPECT_DEATH(option->SetRenderMethod(config::RenderMethod::kSimple), "is_render_method\\(\\)"); EXPECT_DEATH(option->SetInterframe(config::Interframe::kNone), ".*");
EXPECT_DEATH(option->SetAudioApi(config::AudioApi::kOpenAL), "is_audio_api\\(\\)"); EXPECT_DEATH(option->SetRenderMethod(config::RenderMethod::kSimple), ".*");
EXPECT_DEATH(option->SetAudioRate(config::AudioRate::k11kHz), "is_audio_rate\\(\\)"); EXPECT_DEATH(option->SetAudioApi(config::AudioApi::kOpenAL), ".*");
EXPECT_DEATH(option->SetGbPalette({0, 1, 2, 3, 4, 5, 6, 7}), "is_gb_palette\\(\\)"); EXPECT_DEATH(option->SetAudioRate(config::AudioRate::k11kHz), ".*");
} EXPECT_DEATH(option->SetGbPalette({0, 1, 2, 3, 4, 5, 6, 7}), ".*");
#endif // !defined(NDEBUG)
TEST(OptionTest, Int) {
config::Option* option = config::Option::ByID(config::OptionID::kSoundBuffers);
ASSERT_TRUE(option);
EXPECT_TRUE(option->command().empty());
EXPECT_EQ(option->config_name(), "Sound/Buffers");
EXPECT_EQ(option->id(), config::OptionID::kSoundBuffers);
EXPECT_EQ(option->type(), config::Option::Type::kInt);
EXPECT_TRUE(option->is_int());
EXPECT_TRUE(option->SetInt(8));
EXPECT_EQ(option->GetInt(), 8);
// Need to disable logging to test for errors.
const wxLogNull disable_logging;
// Test out of bounds values.
EXPECT_FALSE(option->SetInt(-1));
EXPECT_FALSE(option->SetInt(42));
EXPECT_EQ(option->GetInt(), 8);
EXPECT_DEATH(option->SetBool(true), "is_bool\\(\\)");
EXPECT_DEATH(option->SetDouble(2.0), "is_double\\(\\)");
EXPECT_DEATH(option->SetUnsigned(2), "is_unsigned\\(\\)");
EXPECT_DEATH(option->SetString("foo"), "is_string\\(\\)");
EXPECT_DEATH(option->SetFilter(config::Filter::kNone), "is_filter\\(\\)");
EXPECT_DEATH(option->SetInterframe(config::Interframe::kNone), "is_interframe\\(\\)");
EXPECT_DEATH(option->SetRenderMethod(config::RenderMethod::kSimple), "is_render_method\\(\\)");
EXPECT_DEATH(option->SetAudioApi(config::AudioApi::kOpenAL), "is_audio_api\\(\\)");
EXPECT_DEATH(option->SetAudioRate(config::AudioRate::k11kHz), "is_audio_rate\\(\\)");
EXPECT_DEATH(option->SetGbPalette({0, 1, 2, 3, 4, 5, 6, 7}), "is_gb_palette\\(\\)");
}
TEST(OptionTest, Unsigned) {
config::Option* option = config::Option::ByID(config::OptionID::kGeomWindowHeight);
ASSERT_TRUE(option);
EXPECT_EQ(option->config_name(), "geometry/windowHeight");
EXPECT_EQ(option->id(), config::OptionID::kGeomWindowHeight);
EXPECT_EQ(option->type(), config::Option::Type::kUnsigned);
EXPECT_TRUE(option->is_unsigned());
EXPECT_TRUE(option->SetUnsigned(100));
EXPECT_EQ(option->GetUnsigned(), 100);
// Need to disable logging to test for errors.
const wxLogNull disable_logging;
// Test out of bounds values.
EXPECT_FALSE(option->SetUnsigned(100000));
EXPECT_EQ(option->GetUnsigned(), 100);
EXPECT_DEATH(option->SetBool(true), "is_bool\\(\\)");
EXPECT_DEATH(option->SetDouble(2.0), "is_double\\(\\)");
EXPECT_DEATH(option->SetInt(2), "is_int\\(\\)");
EXPECT_DEATH(option->SetString("foo"), "is_string\\(\\)");
EXPECT_DEATH(option->SetFilter(config::Filter::kNone), "is_filter\\(\\)");
EXPECT_DEATH(option->SetInterframe(config::Interframe::kNone), "is_interframe\\(\\)");
EXPECT_DEATH(option->SetRenderMethod(config::RenderMethod::kSimple), "is_render_method\\(\\)");
EXPECT_DEATH(option->SetAudioApi(config::AudioApi::kOpenAL), "is_audio_api\\(\\)");
EXPECT_DEATH(option->SetAudioRate(config::AudioRate::k11kHz), "is_audio_rate\\(\\)");
EXPECT_DEATH(option->SetGbPalette({0, 1, 2, 3, 4, 5, 6, 7}), "is_gb_palette\\(\\)");
}
TEST(OptionTest, String) {
config::Option* option = config::Option::ByID(config::OptionID::kGenStateDir);
ASSERT_TRUE(option);
EXPECT_TRUE(option->command().empty());
EXPECT_EQ(option->config_name(), "General/StateDir");
EXPECT_EQ(option->id(), config::OptionID::kGenStateDir);
EXPECT_EQ(option->type(), config::Option::Type::kString);
EXPECT_TRUE(option->is_string());
EXPECT_TRUE(option->SetString("/path/to/sthg"));
EXPECT_EQ(option->GetString(), "/path/to/sthg");
EXPECT_DEATH(option->SetBool(true), "is_bool\\(\\)");
EXPECT_DEATH(option->SetDouble(2.0), "is_double\\(\\)");
EXPECT_DEATH(option->SetInt(2), "is_int\\(\\)");
EXPECT_DEATH(option->SetUnsigned(2), "is_unsigned\\(\\)");
EXPECT_DEATH(option->SetFilter(config::Filter::kNone), "is_filter\\(\\)");
EXPECT_DEATH(option->SetInterframe(config::Interframe::kNone), "is_interframe\\(\\)");
EXPECT_DEATH(option->SetRenderMethod(config::RenderMethod::kSimple), "is_render_method\\(\\)");
EXPECT_DEATH(option->SetAudioApi(config::AudioApi::kOpenAL), "is_audio_api\\(\\)");
EXPECT_DEATH(option->SetAudioRate(config::AudioRate::k11kHz), "is_audio_rate\\(\\)");
EXPECT_DEATH(option->SetGbPalette({0, 1, 2, 3, 4, 5, 6, 7}), "is_gb_palette\\(\\)");
}
TEST(OptionTest, Filter) {
config::Option* option = config::Option::ByID(config::OptionID::kDispFilter);
ASSERT_TRUE(option);
EXPECT_TRUE(option->command().empty());
EXPECT_EQ(option->config_name(), "Display/Filter");
EXPECT_EQ(option->id(), config::OptionID::kDispFilter);
EXPECT_EQ(option->type(), config::Option::Type::kFilter);
EXPECT_TRUE(option->is_filter());
EXPECT_TRUE(option->SetFilter(config::Filter::kNone));
EXPECT_EQ(option->GetFilter(), config::Filter::kNone);
EXPECT_DEATH(option->SetBool(true), "is_bool\\(\\)");
EXPECT_DEATH(option->SetDouble(2.0), "is_double\\(\\)");
EXPECT_DEATH(option->SetInt(2), "is_int\\(\\)");
EXPECT_DEATH(option->SetUnsigned(2), "is_unsigned\\(\\)");
EXPECT_DEATH(option->SetString("foo"), "is_string\\(\\)");
EXPECT_DEATH(option->SetInterframe(config::Interframe::kNone), "is_interframe\\(\\)");
EXPECT_DEATH(option->SetRenderMethod(config::RenderMethod::kSimple), "is_render_method\\(\\)");
EXPECT_DEATH(option->SetAudioApi(config::AudioApi::kOpenAL), "is_audio_api\\(\\)");
EXPECT_DEATH(option->SetAudioRate(config::AudioRate::k11kHz), "is_audio_rate\\(\\)");
EXPECT_DEATH(option->SetGbPalette({0, 1, 2, 3, 4, 5, 6, 7}), "is_gb_palette\\(\\)");
}
TEST(OptionTest, Interframe) {
config::Option* option = config::Option::ByID(config::OptionID::kDispIFB);
ASSERT_TRUE(option);
EXPECT_TRUE(option->command().empty());
EXPECT_EQ(option->config_name(), "Display/IFB");
EXPECT_EQ(option->id(), config::OptionID::kDispIFB);
EXPECT_EQ(option->type(), config::Option::Type::kInterframe);
EXPECT_TRUE(option->is_interframe());
EXPECT_TRUE(option->SetInterframe(config::Interframe::kNone));
EXPECT_EQ(option->GetInterframe(), config::Interframe::kNone);
EXPECT_DEATH(option->SetBool(true), "is_bool\\(\\)");
EXPECT_DEATH(option->SetDouble(2.0), "is_double\\(\\)");
EXPECT_DEATH(option->SetInt(2), "is_int\\(\\)");
EXPECT_DEATH(option->SetUnsigned(2), "is_unsigned\\(\\)");
EXPECT_DEATH(option->SetString("foo"), "is_string\\(\\)");
EXPECT_DEATH(option->SetFilter(config::Filter::kNone), "is_filter\\(\\)");
EXPECT_DEATH(option->SetRenderMethod(config::RenderMethod::kSimple), "is_render_method\\(\\)");
EXPECT_DEATH(option->SetAudioApi(config::AudioApi::kOpenAL), "is_audio_api\\(\\)");
EXPECT_DEATH(option->SetAudioRate(config::AudioRate::k11kHz), "is_audio_rate\\(\\)");
EXPECT_DEATH(option->SetGbPalette({0, 1, 2, 3, 4, 5, 6, 7}), "is_gb_palette\\(\\)");
}
TEST(OptionTest, AudioApi) {
config::Option* option = config::Option::ByID(config::OptionID::kSoundAudioAPI);
ASSERT_TRUE(option);
EXPECT_TRUE(option->command().empty());
EXPECT_EQ(option->config_name(), "Sound/AudioAPI");
EXPECT_EQ(option->id(), config::OptionID::kSoundAudioAPI);
EXPECT_EQ(option->type(), config::Option::Type::kAudioApi);
EXPECT_TRUE(option->is_audio_api());
EXPECT_TRUE(option->SetAudioApi(config::AudioApi::kOpenAL));
EXPECT_EQ(option->GetAudioApi(), config::AudioApi::kOpenAL);
EXPECT_DEATH(option->SetBool(true), "is_bool\\(\\)");
EXPECT_DEATH(option->SetDouble(2.0), "is_double\\(\\)");
EXPECT_DEATH(option->SetInt(2), "is_int\\(\\)");
EXPECT_DEATH(option->SetUnsigned(2), "is_unsigned\\(\\)");
EXPECT_DEATH(option->SetString("foo"), "is_string\\(\\)");
EXPECT_DEATH(option->SetFilter(config::Filter::kNone), "is_filter\\(\\)");
EXPECT_DEATH(option->SetInterframe(config::Interframe::kNone), "is_interframe\\(\\)");
EXPECT_DEATH(option->SetRenderMethod(config::RenderMethod::kSimple), "is_render_method\\(\\)");
EXPECT_DEATH(option->SetAudioRate(config::AudioRate::k11kHz), "is_audio_rate\\(\\)");
EXPECT_DEATH(option->SetGbPalette({0, 1, 2, 3, 4, 5, 6, 7}), "is_gb_palette\\(\\)");
}
TEST(OptionTest, AudioRate) {
config::Option* option = config::Option::ByID(config::OptionID::kSoundAudioRate);
ASSERT_TRUE(option);
EXPECT_TRUE(option->command().empty());
EXPECT_EQ(option->config_name(), "Sound/Quality");
EXPECT_EQ(option->id(), config::OptionID::kSoundAudioRate);
EXPECT_EQ(option->type(), config::Option::Type::kAudioRate);
EXPECT_TRUE(option->is_audio_rate());
EXPECT_TRUE(option->SetAudioRate(config::AudioRate::k11kHz));
EXPECT_EQ(option->GetAudioRate(), config::AudioRate::k11kHz);
EXPECT_DEATH(option->SetBool(true), "is_bool\\(\\)");
EXPECT_DEATH(option->SetDouble(2.0), "is_double\\(\\)");
EXPECT_DEATH(option->SetInt(2), "is_int\\(\\)");
EXPECT_DEATH(option->SetUnsigned(2), "is_unsigned\\(\\)");
EXPECT_DEATH(option->SetString("foo"), "is_string\\(\\)");
EXPECT_DEATH(option->SetFilter(config::Filter::kNone), "is_filter\\(\\)");
EXPECT_DEATH(option->SetInterframe(config::Interframe::kNone), "is_interframe\\(\\)");
EXPECT_DEATH(option->SetRenderMethod(config::RenderMethod::kSimple), "is_render_method\\(\\)");
EXPECT_DEATH(option->SetAudioApi(config::AudioApi::kOpenAL), "is_audio_api\\(\\)");
EXPECT_DEATH(option->SetGbPalette({0, 1, 2, 3, 4, 5, 6, 7}), "is_gb_palette\\(\\)");
} }
TEST(OptionTest, Enum) { TEST(OptionTest, Enum) {
@@ -295,16 +110,6 @@ TEST(Optiontest, GbPalette) {
EXPECT_FALSE(option->SetGbPaletteString("")); EXPECT_FALSE(option->SetGbPaletteString(""));
EXPECT_FALSE(option->SetGbPaletteString("0000,0001,0002,0003,0004,0005,0006,000Q")); EXPECT_FALSE(option->SetGbPaletteString("0000,0001,0002,0003,0004,0005,0006,000Q"));
EXPECT_DEATH(option->SetBool(true), "is_bool\\(\\)");
EXPECT_DEATH(option->SetDouble(2.0), "is_double\\(\\)");
EXPECT_DEATH(option->SetInt(2), "is_int\\(\\)");
EXPECT_DEATH(option->SetUnsigned(2), "is_unsigned\\(\\)");
EXPECT_DEATH(option->SetString("foo"), "is_string\\(\\)");
EXPECT_DEATH(option->SetFilter(config::Filter::kNone), "is_filter\\(\\)");
EXPECT_DEATH(option->SetInterframe(config::Interframe::kNone), "is_interframe\\(\\)");
EXPECT_DEATH(option->SetRenderMethod(config::RenderMethod::kSimple), "is_render_method\\(\\)");
EXPECT_DEATH(option->SetAudioApi(config::AudioApi::kOpenAL), "is_audio_api\\(\\)");
EXPECT_DEATH(option->SetAudioRate(config::AudioRate::k11kHz), "is_audio_rate\\(\\)");
} }
TEST(OptionObserverTest, Basic) { TEST(OptionObserverTest, Basic) {
@@ -353,109 +158,3 @@ TEST(OptionProxyTest, MatchingTypes) {
EXPECT_EQ(option->type(), proxy_type); EXPECT_EQ(option->type(), proxy_type);
} }
} }
TEST(OptionProxyTest, NumericOperators) {
wxLogNull disable_logging;
int32_t int_opt = OPTION(kDispMaxThreads);
int_opt++;
OPTION(kDispMaxThreads)++;
EXPECT_EQ(int_opt, OPTION(kDispMaxThreads));
int_opt--;
OPTION(kDispMaxThreads)--;
EXPECT_EQ(int_opt, OPTION(kDispMaxThreads));
++int_opt;
OPTION(kDispMaxThreads)++;
EXPECT_EQ(int_opt, OPTION(kDispMaxThreads));
--int_opt;
OPTION(kDispMaxThreads)--;
EXPECT_EQ(int_opt, OPTION(kDispMaxThreads));
int_opt += 2;
OPTION(kDispMaxThreads) += 2;
EXPECT_EQ(int_opt, OPTION(kDispMaxThreads));
int_opt -= 2;
OPTION(kDispMaxThreads) -= 2;
EXPECT_EQ(int_opt, OPTION(kDispMaxThreads));
OPTION(kDispMaxThreads) = OPTION(kDispMaxThreads).Max();
OPTION(kDispMaxThreads)++;
EXPECT_EQ(OPTION(kDispMaxThreads), OPTION(kDispMaxThreads).Max());
OPTION(kDispMaxThreads) = OPTION(kDispMaxThreads).Min();
OPTION(kDispMaxThreads)--;
EXPECT_EQ(OPTION(kDispMaxThreads), OPTION(kDispMaxThreads).Min());
uint32_t unsigned_opt = OPTION(kJoyDefault);
unsigned_opt++;
OPTION(kJoyDefault)++;
EXPECT_EQ(unsigned_opt, OPTION(kJoyDefault));
unsigned_opt--;
OPTION(kJoyDefault)--;
EXPECT_EQ(unsigned_opt, OPTION(kJoyDefault));
++unsigned_opt;
OPTION(kJoyDefault)++;
EXPECT_EQ(unsigned_opt, OPTION(kJoyDefault));
--unsigned_opt;
OPTION(kJoyDefault)--;
EXPECT_EQ(unsigned_opt, OPTION(kJoyDefault));
unsigned_opt += 2;
OPTION(kJoyDefault) += 2;
EXPECT_EQ(unsigned_opt, OPTION(kJoyDefault));
unsigned_opt -= 2;
OPTION(kJoyDefault) -= 2;
EXPECT_EQ(unsigned_opt, OPTION(kJoyDefault));
OPTION(kJoyDefault) = OPTION(kJoyDefault).Max();
OPTION(kJoyDefault)++;
EXPECT_EQ(OPTION(kJoyDefault), OPTION(kJoyDefault).Max());
OPTION(kJoyDefault) = OPTION(kJoyDefault).Min();
OPTION(kJoyDefault)--;
EXPECT_EQ(OPTION(kJoyDefault), OPTION(kJoyDefault).Min());
double double_opt = OPTION(kDispScale);
double_opt++;
OPTION(kDispScale)++;
EXPECT_EQ(double_opt, OPTION(kDispScale));
double_opt--;
OPTION(kDispScale)--;
EXPECT_EQ(double_opt, OPTION(kDispScale));
++double_opt;
OPTION(kDispScale)++;
EXPECT_EQ(double_opt, OPTION(kDispScale));
--double_opt;
OPTION(kDispScale)--;
EXPECT_EQ(double_opt, OPTION(kDispScale));
double_opt += 2;
OPTION(kDispScale) += 2;
EXPECT_EQ(double_opt, OPTION(kDispScale));
double_opt -= 2;
OPTION(kDispScale) -= 2;
EXPECT_EQ(double_opt, OPTION(kDispScale));
OPTION(kDispScale) = OPTION(kDispScale).Max();
OPTION(kDispScale)++;
EXPECT_EQ(OPTION(kDispScale), OPTION(kDispScale).Max());
OPTION(kDispScale) = OPTION(kDispScale).Min();
OPTION(kDispScale)--;
EXPECT_EQ(OPTION(kDispScale), OPTION(kDispScale).Min());
}

View File

@@ -11,7 +11,6 @@
#include "wx/config/internal/option-internal.h" #include "wx/config/internal/option-internal.h"
#undef VBAM_OPTION_INTERNAL_INCLUDE #undef VBAM_OPTION_INTERNAL_INCLUDE
#include "core/base/check.h"
#include "wx/config/option-proxy.h" #include "wx/config/option-proxy.h"
namespace config { namespace config {
@@ -27,14 +26,14 @@ Option* Option::ByName(const wxString& config_name) {
// static // static
Option* Option::ByID(OptionID id) { Option* Option::ByID(OptionID id) {
VBAM_CHECK(id != OptionID::Last); assert(id != OptionID::Last);
return &All()[static_cast<size_t>(id)]; return &All()[static_cast<size_t>(id)];
} }
Option::~Option() = default; Option::~Option() = default;
Option::Observer::Observer(OptionID option_id) : option_(Option::ByID(option_id)) { Option::Observer::Observer(OptionID option_id) : option_(Option::ByID(option_id)) {
VBAM_CHECK(option_); assert(option_);
option_->AddObserver(this); option_->AddObserver(this);
} }
Option::Observer::~Observer() { Option::Observer::~Observer() {
@@ -50,8 +49,8 @@ Option::Option(OptionID id)
value_(), value_(),
min_(), min_(),
max_() { max_() {
VBAM_CHECK(id != OptionID::Last); assert(id != OptionID::Last);
VBAM_CHECK(is_none()); assert(is_none());
} }
Option::Option(OptionID id, bool* option) Option::Option(OptionID id, bool* option)
@@ -63,8 +62,8 @@ Option::Option(OptionID id, bool* option)
value_(option), value_(option),
min_(), min_(),
max_() { max_() {
VBAM_CHECK(id != OptionID::Last); assert(id != OptionID::Last);
VBAM_CHECK(is_bool()); assert(is_bool());
} }
Option::Option(OptionID id, double* option, double min, double max) Option::Option(OptionID id, double* option, double min, double max)
@@ -76,8 +75,8 @@ Option::Option(OptionID id, double* option, double min, double max)
value_(option), value_(option),
min_(min), min_(min),
max_(max) { max_(max) {
VBAM_CHECK(id != OptionID::Last); assert(id != OptionID::Last);
VBAM_CHECK(is_double()); assert(is_double());
// Validate the initial value. // Validate the initial value.
SetDouble(*option); SetDouble(*option);
@@ -92,8 +91,8 @@ Option::Option(OptionID id, int32_t* option, int32_t min, int32_t max)
value_(option), value_(option),
min_(min), min_(min),
max_(max) { max_(max) {
VBAM_CHECK(id != OptionID::Last); assert(id != OptionID::Last);
VBAM_CHECK(is_int()); assert(is_int());
// Validate the initial value. // Validate the initial value.
SetInt(*option); SetInt(*option);
@@ -108,8 +107,8 @@ Option::Option(OptionID id, uint32_t* option, uint32_t min, uint32_t max)
value_(option), value_(option),
min_(min), min_(min),
max_(max) { max_(max) {
VBAM_CHECK(id != OptionID::Last); assert(id != OptionID::Last);
VBAM_CHECK(is_unsigned()); assert(is_unsigned());
// Validate the initial value. // Validate the initial value.
SetUnsigned(*option); SetUnsigned(*option);
@@ -124,8 +123,8 @@ Option::Option(OptionID id, wxString* option)
value_(option), value_(option),
min_(), min_(),
max_() { max_() {
VBAM_CHECK(id != OptionID::Last); assert(id != OptionID::Last);
VBAM_CHECK(is_string()); assert(is_string());
} }
Option::Option(OptionID id, Filter* option) Option::Option(OptionID id, Filter* option)
@@ -137,8 +136,8 @@ Option::Option(OptionID id, Filter* option)
value_(option), value_(option),
min_(), min_(),
max_(nonstd::in_place_type<size_t>, internal::MaxForType(type_)) { max_(nonstd::in_place_type<size_t>, internal::MaxForType(type_)) {
VBAM_CHECK(id != OptionID::Last); assert(id != OptionID::Last);
VBAM_CHECK(is_filter()); assert(is_filter());
} }
Option::Option(OptionID id, Interframe* option) Option::Option(OptionID id, Interframe* option)
@@ -150,8 +149,8 @@ Option::Option(OptionID id, Interframe* option)
value_(option), value_(option),
min_(), min_(),
max_(nonstd::in_place_type<size_t>, internal::MaxForType(type_)) { max_(nonstd::in_place_type<size_t>, internal::MaxForType(type_)) {
VBAM_CHECK(id != OptionID::Last); assert(id != OptionID::Last);
VBAM_CHECK(is_interframe()); assert(is_interframe());
} }
Option::Option(OptionID id, RenderMethod* option) Option::Option(OptionID id, RenderMethod* option)
@@ -163,8 +162,8 @@ Option::Option(OptionID id, RenderMethod* option)
value_(option), value_(option),
min_(), min_(),
max_(nonstd::in_place_type<size_t>, internal::MaxForType(type_)) { max_(nonstd::in_place_type<size_t>, internal::MaxForType(type_)) {
VBAM_CHECK(id != OptionID::Last); assert(id != OptionID::Last);
VBAM_CHECK(is_render_method()); assert(is_render_method());
} }
Option::Option(OptionID id, AudioApi* option) Option::Option(OptionID id, AudioApi* option)
@@ -176,8 +175,8 @@ Option::Option(OptionID id, AudioApi* option)
value_(option), value_(option),
min_(), min_(),
max_(nonstd::in_place_type<size_t>, internal::MaxForType(type_)) { max_(nonstd::in_place_type<size_t>, internal::MaxForType(type_)) {
VBAM_CHECK(id != OptionID::Last); assert(id != OptionID::Last);
VBAM_CHECK(is_audio_api()); assert(is_audio_api());
} }
Option::Option(OptionID id, AudioRate* option) Option::Option(OptionID id, AudioRate* option)
@@ -189,8 +188,8 @@ Option::Option(OptionID id, AudioRate* option)
value_(option), value_(option),
min_(), min_(),
max_(nonstd::in_place_type<size_t>, internal::MaxForType(type_)) { max_(nonstd::in_place_type<size_t>, internal::MaxForType(type_)) {
VBAM_CHECK(id != OptionID::Last); assert(id != OptionID::Last);
VBAM_CHECK(is_audio_rate()); assert(is_audio_rate());
} }
Option::Option(OptionID id, uint16_t* option) Option::Option(OptionID id, uint16_t* option)
@@ -202,57 +201,57 @@ Option::Option(OptionID id, uint16_t* option)
value_(option), value_(option),
min_(), min_(),
max_() { max_() {
VBAM_CHECK(id != OptionID::Last); assert(id != OptionID::Last);
VBAM_CHECK(is_gb_palette()); assert(is_gb_palette());
} }
bool Option::GetBool() const { bool Option::GetBool() const {
VBAM_CHECK(is_bool()); assert(is_bool());
return *(nonstd::get<bool*>(value_)); return *(nonstd::get<bool*>(value_));
} }
double Option::GetDouble() const { double Option::GetDouble() const {
VBAM_CHECK(is_double()); assert(is_double());
return *(nonstd::get<double*>(value_)); return *(nonstd::get<double*>(value_));
} }
int32_t Option::GetInt() const { int32_t Option::GetInt() const {
VBAM_CHECK(is_int()); assert(is_int());
return *(nonstd::get<int32_t*>(value_)); return *(nonstd::get<int32_t*>(value_));
} }
uint32_t Option::GetUnsigned() const { uint32_t Option::GetUnsigned() const {
VBAM_CHECK(is_unsigned()); assert(is_unsigned());
return *(nonstd::get<uint32_t*>(value_)); return *(nonstd::get<uint32_t*>(value_));
} }
const wxString& Option::GetString() const { const wxString& Option::GetString() const {
VBAM_CHECK(is_string()); assert(is_string());
return *(nonstd::get<wxString*>(value_)); return *(nonstd::get<wxString*>(value_));
} }
Filter Option::GetFilter() const { Filter Option::GetFilter() const {
VBAM_CHECK(is_filter()); assert(is_filter());
return *(nonstd::get<Filter*>(value_)); return *(nonstd::get<Filter*>(value_));
} }
Interframe Option::GetInterframe() const { Interframe Option::GetInterframe() const {
VBAM_CHECK(is_interframe()); assert(is_interframe());
return *(nonstd::get<Interframe*>(value_)); return *(nonstd::get<Interframe*>(value_));
} }
RenderMethod Option::GetRenderMethod() const { RenderMethod Option::GetRenderMethod() const {
VBAM_CHECK(is_render_method()); assert(is_render_method());
return *(nonstd::get<RenderMethod*>(value_)); return *(nonstd::get<RenderMethod*>(value_));
} }
AudioApi Option::GetAudioApi() const { AudioApi Option::GetAudioApi() const {
VBAM_CHECK(is_audio_api()); assert(is_audio_api());
return *(nonstd::get<AudioApi*>(value_)); return *(nonstd::get<AudioApi*>(value_));
} }
AudioRate Option::GetAudioRate() const { AudioRate Option::GetAudioRate() const {
VBAM_CHECK(is_audio_rate()); assert(is_audio_rate());
return *(nonstd::get<AudioRate*>(value_)); return *(nonstd::get<AudioRate*>(value_));
} }
@@ -278,15 +277,15 @@ wxString Option::GetEnumString() const {
case Option::Type::kUnsigned: case Option::Type::kUnsigned:
case Option::Type::kString: case Option::Type::kString:
case Option::Type::kGbPalette: case Option::Type::kGbPalette:
VBAM_CHECK(false); assert(false);
return wxEmptyString; return wxEmptyString;
} }
VBAM_NOTREACHED(); assert(false);
return wxEmptyString; return wxEmptyString;
} }
std::array<uint16_t, 8> Option::GetGbPalette() const { std::array<uint16_t, 8> Option::GetGbPalette() const {
VBAM_CHECK(is_gb_palette()); assert(is_gb_palette());
const uint16_t* raw_palette = (nonstd::get<uint16_t*>(value_)); const uint16_t* raw_palette = (nonstd::get<uint16_t*>(value_));
std::array<uint16_t, 8> palette; std::array<uint16_t, 8> palette;
@@ -295,7 +294,7 @@ std::array<uint16_t, 8> Option::GetGbPalette() const {
} }
wxString Option::GetGbPaletteString() const { wxString Option::GetGbPaletteString() const {
VBAM_CHECK(is_gb_palette()); assert(is_gb_palette());
wxString palette_string; wxString palette_string;
uint16_t const* value = nonstd::get<uint16_t*>(value_); uint16_t const* value = nonstd::get<uint16_t*>(value_);
@@ -305,7 +304,7 @@ wxString Option::GetGbPaletteString() const {
} }
bool Option::SetBool(bool value) { bool Option::SetBool(bool value) {
VBAM_CHECK(is_bool()); assert(is_bool());
bool old_value = GetBool(); bool old_value = GetBool();
*nonstd::get<bool*>(value_) = value; *nonstd::get<bool*>(value_) = value;
if (old_value != value) { if (old_value != value) {
@@ -315,7 +314,7 @@ bool Option::SetBool(bool value) {
} }
bool Option::SetDouble(double value) { bool Option::SetDouble(double value) {
VBAM_CHECK(is_double()); assert(is_double());
double old_value = GetDouble(); double old_value = GetDouble();
if (value < nonstd::get<double>(min_) || value > nonstd::get<double>(max_)) { if (value < nonstd::get<double>(min_) || value > nonstd::get<double>(max_)) {
wxLogWarning(_("Invalid value %f for option %s; valid values are %f - %f"), value, wxLogWarning(_("Invalid value %f for option %s; valid values are %f - %f"), value,
@@ -330,7 +329,7 @@ bool Option::SetDouble(double value) {
} }
bool Option::SetInt(int32_t value) { bool Option::SetInt(int32_t value) {
VBAM_CHECK(is_int()); assert(is_int());
int old_value = GetInt(); int old_value = GetInt();
if (value < nonstd::get<int32_t>(min_) || value > nonstd::get<int32_t>(max_)) { if (value < nonstd::get<int32_t>(min_) || value > nonstd::get<int32_t>(max_)) {
wxLogWarning(_("Invalid value %d for option %s; valid values are %d - %d"), value, wxLogWarning(_("Invalid value %d for option %s; valid values are %d - %d"), value,
@@ -345,7 +344,7 @@ bool Option::SetInt(int32_t value) {
} }
bool Option::SetUnsigned(uint32_t value) { bool Option::SetUnsigned(uint32_t value) {
VBAM_CHECK(is_unsigned()); assert(is_unsigned());
uint32_t old_value = GetUnsigned(); uint32_t old_value = GetUnsigned();
if (value < nonstd::get<uint32_t>(min_) || value > nonstd::get<uint32_t>(max_)) { if (value < nonstd::get<uint32_t>(min_) || value > nonstd::get<uint32_t>(max_)) {
wxLogWarning(_("Invalid value %d for option %s; valid values are %d - %d"), value, wxLogWarning(_("Invalid value %d for option %s; valid values are %d - %d"), value,
@@ -360,7 +359,7 @@ bool Option::SetUnsigned(uint32_t value) {
} }
bool Option::SetString(const wxString& value) { bool Option::SetString(const wxString& value) {
VBAM_CHECK(is_string()); assert(is_string());
const wxString old_value = GetString(); const wxString old_value = GetString();
*nonstd::get<wxString*>(value_) = value; *nonstd::get<wxString*>(value_) = value;
if (old_value != value) { if (old_value != value) {
@@ -370,8 +369,8 @@ bool Option::SetString(const wxString& value) {
} }
bool Option::SetFilter(const Filter& value) { bool Option::SetFilter(const Filter& value) {
VBAM_CHECK(is_filter()); assert(is_filter());
VBAM_CHECK(value < Filter::kLast); assert(value < Filter::kLast);
const Filter old_value = GetFilter(); const Filter old_value = GetFilter();
*nonstd::get<Filter*>(value_) = value; *nonstd::get<Filter*>(value_) = value;
if (old_value != value) { if (old_value != value) {
@@ -381,8 +380,8 @@ bool Option::SetFilter(const Filter& value) {
} }
bool Option::SetInterframe(const Interframe& value) { bool Option::SetInterframe(const Interframe& value) {
VBAM_CHECK(is_interframe()); assert(is_interframe());
VBAM_CHECK(value < Interframe::kLast); assert(value < Interframe::kLast);
const Interframe old_value = GetInterframe(); const Interframe old_value = GetInterframe();
*nonstd::get<Interframe*>(value_) = value; *nonstd::get<Interframe*>(value_) = value;
if (old_value != value) { if (old_value != value) {
@@ -392,8 +391,8 @@ bool Option::SetInterframe(const Interframe& value) {
} }
bool Option::SetRenderMethod(const RenderMethod& value) { bool Option::SetRenderMethod(const RenderMethod& value) {
VBAM_CHECK(is_render_method()); assert(is_render_method());
VBAM_CHECK(value < RenderMethod::kLast); assert(value < RenderMethod::kLast);
const RenderMethod old_value = GetRenderMethod(); const RenderMethod old_value = GetRenderMethod();
*nonstd::get<RenderMethod*>(value_) = value; *nonstd::get<RenderMethod*>(value_) = value;
if (old_value != value) { if (old_value != value) {
@@ -403,8 +402,8 @@ bool Option::SetRenderMethod(const RenderMethod& value) {
} }
bool Option::SetAudioApi(const AudioApi& value) { bool Option::SetAudioApi(const AudioApi& value) {
VBAM_CHECK(is_audio_api()); assert(is_audio_api());
VBAM_CHECK(value < AudioApi::kLast); assert(value < AudioApi::kLast);
const AudioApi old_value = GetAudioApi(); const AudioApi old_value = GetAudioApi();
*nonstd::get<AudioApi*>(value_) = value; *nonstd::get<AudioApi*>(value_) = value;
if (old_value != value) { if (old_value != value) {
@@ -414,8 +413,8 @@ bool Option::SetAudioApi(const AudioApi& value) {
} }
bool Option::SetAudioRate(const AudioRate& value) { bool Option::SetAudioRate(const AudioRate& value) {
VBAM_CHECK(is_audio_rate()); assert(is_audio_rate());
VBAM_CHECK(value < AudioRate::kLast); assert(value < AudioRate::kLast);
const AudioRate old_value = GetAudioRate(); const AudioRate old_value = GetAudioRate();
*nonstd::get<AudioRate*>(value_) = value; *nonstd::get<AudioRate*>(value_) = value;
if (old_value != value) { if (old_value != value) {
@@ -446,15 +445,15 @@ bool Option::SetEnumString(const wxString& value) {
case Option::Type::kUnsigned: case Option::Type::kUnsigned:
case Option::Type::kString: case Option::Type::kString:
case Option::Type::kGbPalette: case Option::Type::kGbPalette:
VBAM_CHECK(false); assert(false);
return false; return false;
} }
VBAM_NOTREACHED(); assert(false);
return false; return false;
} }
bool Option::SetGbPalette(const std::array<uint16_t, 8>& value) { bool Option::SetGbPalette(const std::array<uint16_t, 8>& value) {
VBAM_CHECK(is_gb_palette()); assert(is_gb_palette());
uint16_t* dest = nonstd::get<uint16_t*>(value_); uint16_t* dest = nonstd::get<uint16_t*>(value_);
@@ -472,7 +471,7 @@ bool Option::SetGbPalette(const std::array<uint16_t, 8>& value) {
} }
bool Option::SetGbPaletteString(const wxString& value) { bool Option::SetGbPaletteString(const wxString& value) {
VBAM_CHECK(is_gb_palette()); assert(is_gb_palette());
// 8 values of 4 chars and 7 commas. // 8 values of 4 chars and 7 commas.
static constexpr size_t kPaletteStringSize = 8 * 4 + 7; static constexpr size_t kPaletteStringSize = 8 * 4 + 7;
@@ -498,50 +497,50 @@ bool Option::SetGbPaletteString(const wxString& value) {
} }
double Option::GetDoubleMin() const { double Option::GetDoubleMin() const {
VBAM_CHECK(is_double()); assert(is_double());
return nonstd::get<double>(min_); return nonstd::get<double>(min_);
} }
double Option::GetDoubleMax() const { double Option::GetDoubleMax() const {
VBAM_CHECK(is_double()); assert(is_double());
return nonstd::get<double>(max_); return nonstd::get<double>(max_);
} }
int32_t Option::GetIntMin() const { int32_t Option::GetIntMin() const {
VBAM_CHECK(is_int()); assert(is_int());
return nonstd::get<int32_t>(min_); return nonstd::get<int32_t>(min_);
} }
int32_t Option::GetIntMax() const { int32_t Option::GetIntMax() const {
VBAM_CHECK(is_int()); assert(is_int());
return nonstd::get<int32_t>(max_); return nonstd::get<int32_t>(max_);
} }
uint32_t Option::GetUnsignedMin() const { uint32_t Option::GetUnsignedMin() const {
VBAM_CHECK(is_unsigned()); assert(is_unsigned());
return nonstd::get<uint32_t>(min_); return nonstd::get<uint32_t>(min_);
} }
uint32_t Option::GetUnsignedMax() const { uint32_t Option::GetUnsignedMax() const {
VBAM_CHECK(is_unsigned()); assert(is_unsigned());
return nonstd::get<uint32_t>(max_); return nonstd::get<uint32_t>(max_);
} }
size_t Option::GetEnumMax() const { size_t Option::GetEnumMax() const {
VBAM_CHECK(is_filter() || is_interframe() || is_render_method() || is_audio_api() || assert(is_filter() || is_interframe() || is_render_method() || is_audio_api() ||
is_audio_rate()); is_audio_rate());
return nonstd::get<size_t>(max_); return nonstd::get<size_t>(max_);
} }
void Option::NextFilter() { void Option::NextFilter() {
VBAM_CHECK(is_filter()); assert(is_filter());
const int old_value = static_cast<int>(GetFilter()); const int old_value = static_cast<int>(GetFilter());
const int new_value = (old_value + 1) % kNbFilters; const int new_value = (old_value + 1) % kNbFilters;
SetFilter(static_cast<Filter>(new_value)); SetFilter(static_cast<Filter>(new_value));
} }
void Option::NextInterframe() { void Option::NextInterframe() {
VBAM_CHECK(is_interframe()); assert(is_interframe());
const int old_value = static_cast<int>(GetInterframe()); const int old_value = static_cast<int>(GetInterframe());
const int new_value = (old_value + 1) % kNbInterframes; const int new_value = (old_value + 1) % kNbInterframes;
SetInterframe(static_cast<Interframe>(new_value)); SetInterframe(static_cast<Interframe>(new_value));
@@ -589,19 +588,19 @@ wxString Option::ToHelperString() const {
} }
void Option::AddObserver(Observer* observer) { void Option::AddObserver(Observer* observer) {
VBAM_CHECK(observer); assert(observer);
[[maybe_unused]] const auto pair = observers_.emplace(observer); [[maybe_unused]] const auto pair = observers_.emplace(observer);
VBAM_CHECK(pair.second); assert(pair.second);
} }
void Option::RemoveObserver(Observer* observer) { void Option::RemoveObserver(Observer* observer) {
VBAM_CHECK(observer); assert(observer);
[[maybe_unused]] const size_t removed = observers_.erase(observer); [[maybe_unused]] const size_t removed = observers_.erase(observer);
VBAM_CHECK(removed == 1u); assert(removed == 1u);
} }
void Option::CallObservers() { void Option::CallObservers() {
VBAM_CHECK(!calling_observers_); assert(!calling_observers_);
calling_observers_ = true; calling_observers_ = true;
for (const auto observer : observers_) { for (const auto observer : observers_) {
observer->OnValueChanged(); observer->OnValueChanged();

View File

@@ -94,91 +94,3 @@ TEST(StrSplitWithSepTest, MultipleSepTokens) {
EXPECT_EQ(vec[4], "baz"); EXPECT_EQ(vec[4], "baz");
EXPECT_EQ(vec[5], "|-|"); EXPECT_EQ(vec[5], "|-|");
} }
TEST(UTF16ToUTF8Test, Basic) {
const std::vector<uint16_t> utf16 = {'f', 'o', 'o', 0};
auto vec = config::utf16_to_utf8_vector(utf16.data());
ASSERT_EQ(vec.size(), 3);
EXPECT_EQ(vec[0], 'f');
EXPECT_EQ(vec[1], 'o');
EXPECT_EQ(vec[2], 'o');
}
TEST(UTF16ToUTF8Test, MultiByte) {
// U+20AC EURO SIGN.
const std::vector<uint16_t> utf16 = {0x20AC, 0};
auto vec = config::utf16_to_utf8_vector(utf16.data());
ASSERT_EQ(vec.size(), 3);
EXPECT_EQ(vec[0], 0xE2);
EXPECT_EQ(vec[1], 0x82);
EXPECT_EQ(vec[2], 0xAC);
}
TEST(UTF16ToUTF8Test, DualMultiByte) {
// This is a variant of the above to test the buffer reset is done properly.
const std::vector<uint16_t> utf16 = {0x20AC, 0x20AC, 0};
auto vec = config::utf16_to_utf8_vector(utf16.data());
ASSERT_EQ(vec.size(), 6);
EXPECT_EQ(vec[0], 0xE2);
EXPECT_EQ(vec[1], 0x82);
EXPECT_EQ(vec[2], 0xAC);
EXPECT_EQ(vec[3], 0xE2);
EXPECT_EQ(vec[4], 0x82);
EXPECT_EQ(vec[5], 0xAC);
}
TEST(UTF16ToUTF8Test, SurrogatePair) {
// U+1F914 THINKING FACE.
const std::vector<uint16_t> utf16 = {0xD83E, 0xDD14, 0};
auto vec = config::utf16_to_utf8_vector(utf16.data());
ASSERT_EQ(vec.size(), 4);
EXPECT_EQ(vec[0], 0xF0);
EXPECT_EQ(vec[1], 0x9F);
EXPECT_EQ(vec[2], 0xA4);
EXPECT_EQ(vec[3], 0x94);
}
TEST(UTF16ToUTF8Test, InvalidSurrogatePair) {
// U+D800 HIGH SURROGATE.
const std::vector<uint16_t> utf16 = {0xD800, 0};
EXPECT_DEATH(config::utf16_to_utf8_vector(utf16.data()), ".*");
}
TEST(UTF16ToUTF8Test, InvalidSurrogatePair2) {
// U+D800 HIGH SURROGATE followed by U+0020 SPACE.
const std::vector<uint16_t> utf16 = {0xD800, 0x0020, 0};
EXPECT_DEATH(config::utf16_to_utf8_vector(utf16.data()), ".*");
}
TEST(UTF16ToUTF8Test, InvalidSurrogatePair3) {
// U+D800 HIGH SURROGATE followed by U+D800 HIGH SURROGATE.
const std::vector<uint16_t> utf16 = {0xD800, 0xD800, 0};
EXPECT_DEATH(config::utf16_to_utf8_vector(utf16.data()), ".*");
}
TEST(UTF16ToUTF8Test, FullString) {
// "foo€🤔"
const std::vector<uint16_t> utf16 = {'f', 'o', 'o', 0x20AC, 0xD83E, 0xDD14, 0};
auto vec = config::utf16_to_utf8_vector(utf16.data());
ASSERT_EQ(vec.size(), 10);
EXPECT_EQ(vec[0], 'f');
EXPECT_EQ(vec[1], 'o');
EXPECT_EQ(vec[2], 'o');
EXPECT_EQ(vec[3], 0xE2);
EXPECT_EQ(vec[4], 0x82);
EXPECT_EQ(vec[5], 0xAC);
EXPECT_EQ(vec[6], 0xF0);
EXPECT_EQ(vec[7], 0x9F);
EXPECT_EQ(vec[8], 0xA4);
EXPECT_EQ(vec[9], 0x94);
}

View File

@@ -1,11 +1,7 @@
#include "wx/config/strutils.h" #include "wx/config/strutils.h"
#include <cstdint>
#include <wx/tokenzr.h> #include <wx/tokenzr.h>
#include "core/base/check.h"
namespace config { namespace config {
// From: https://stackoverflow.com/a/7408245/262458 // From: https://stackoverflow.com/a/7408245/262458
@@ -41,50 +37,4 @@ wxArrayString str_split_with_sep(const wxString& text, const wxString& sep)
return str_split(text, sep, true); return str_split(text, sep, true);
} }
std::vector<uint8_t> utf16_to_utf8_vector(const uint16_t* utf16) {
std::vector<uint8_t> out;
for (size_t i = 0; utf16[i]; i++) {
const uint16_t c = utf16[i];
if (c < 0x80) {
out.push_back(c);
} else if (c < 0x800) {
out.push_back(0xC0 | (c >> 6));
out.push_back(0x80 | (c & 0x3F));
} else if (c < 0xD800 || c >= 0xE000) {
// Regular 3-byte UTF-8 character.
out.push_back(0xE0 | (c >> 12));
out.push_back(0x80 | ((c >> 6) & 0x3F));
out.push_back(0x80 | (c & 0x3F));
} else {
// Surrogate pair, construct the original code point.
const uint32_t high = c;
// The next code unit must be a low surrogate.
i++;
const uint32_t low = utf16[i];
VBAM_CHECK(low);
VBAM_CHECK(low >= 0xDC00 && low < 0xE000);
const uint32_t codepoint = 0x10000 + ((high & 0x3FF) << 10) + (low & 0x3FF);
// Convert to UTF-8.
out.push_back(0xF0 | (codepoint >> 18));
out.push_back(0x80 | ((codepoint >> 12) & 0x3F));
out.push_back(0x80 | ((codepoint >> 6) & 0x3F));
out.push_back(0x80 | (codepoint & 0x3F));
}
}
return out;
}
wxString utf16_to_utf8(const uint16_t* utf16) {
std::vector<uint8_t> output_vector = utf16_to_utf8_vector(utf16);
return wxString::FromUTF8(reinterpret_cast<const char*>(output_vector.data()),
output_vector.size());
}
wxString utf16_to_utf8(const int16_t* utf16) {
return utf16_to_utf8(reinterpret_cast<const uint16_t*>(utf16));
}
} // namespace config } // namespace config

View File

@@ -1,9 +1,6 @@
#ifndef VBAM_WX_CONFIG_STRUTILS_H_ #ifndef VBAM_WX_CONFIG_STRUTILS_H_
#define VBAM_WX_CONFIG_STRUTILS_H_ #define VBAM_WX_CONFIG_STRUTILS_H_
#include <cstdint>
#include <vector>
#include <wx/string.h> #include <wx/string.h>
#include <wx/arrstr.h> #include <wx/arrstr.h>
@@ -17,14 +14,6 @@ wxArrayString str_split(const wxString& text, const wxString& sep, bool empty_to
// 'A', ',' and 'B' will be in the output. // 'A', ',' and 'B' will be in the output.
wxArrayString str_split_with_sep(const wxString& text, const wxString& sep); wxArrayString str_split_with_sep(const wxString& text, const wxString& sep);
// Converts a null-terminated array of UTF-16 code units to a vector of UTF-8 code units.
// This will assert if the input is not a valid UTF-16 string.
std::vector<uint8_t> utf16_to_utf8_vector(const uint16_t* utf16);
// Convenience functions to convert a null-terminated array of UTF-16 code units to a wxString.
wxString utf16_to_utf8(const uint16_t* utf16);
wxString utf16_to_utf8(const int16_t* utf16);
} // namespace config } // namespace config
#endif // VBAM_WX_CONFIG_STRUTILS_H_ #endif // VBAM_WX_CONFIG_STRUTILS_H_

Some files were not shown because too many files have changed in this diff Show More