Update to SDL3 APIs, fix bpps, add SDL audio/video, add Metal video, fix Quartz drawing
Implement SDL3 for the SDL port if the CMake definition ENABLE_SDL3 is set. Implement setting the color depth for both wxWidgets and the SDL port. Fix the coloring issues in the SDL port for OpenGL. Implement 8 bit color support. Update and fix the wx port SDL sound driver. Implement SDL video in the wx port. Silence GL deprecations on macOS. Add SDL renderer selection. Fix filter for bit depths other than 32 bit. Fix GDK backend for Linux. Add Metal renderer for macOS. Fix Quartz drawing.
This commit is contained in:
parent
3a1780145c
commit
f975809e3c
|
@ -74,6 +74,16 @@ set(CMAKE_C_STANDARD_REQUIRED True)
|
||||||
|
|
||||||
project(VBA-M C CXX)
|
project(VBA-M C CXX)
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
include(CheckLanguage)
|
||||||
|
include(MetalShaderSupport)
|
||||||
|
|
||||||
|
check_language(Metal)
|
||||||
|
if(CMAKE_Metal_COMPILER)
|
||||||
|
enable_language(Metal)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
include(CTest)
|
include(CTest)
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||||
|
# file LICENCE.txt or https://cmake.org/licensing for details.
|
||||||
|
|
||||||
|
# CMakeDetermine(LANG)Compiler.cmake -> this should find the compiler for LANG and configure CMake(LANG)Compiler.cmake.in
|
||||||
|
|
||||||
|
include(${CMAKE_ROOT}/Modules/CMakeDetermineCompiler.cmake)
|
||||||
|
|
||||||
|
if(NOT CMAKE_Metal_COMPILER_NAMES)
|
||||||
|
set(CMAKE_Metal_COMPILER_NAMES metal)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if("${CMAKE_GENERATOR}" STREQUAL "Xcode")
|
||||||
|
set(CMAKE_Metal_COMPILER_XCODE_TYPE sourcecode.metal)
|
||||||
|
|
||||||
|
execute_process(COMMAND xcrun --find metal
|
||||||
|
OUTPUT_VARIABLE _xcrun_out OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
ERROR_VARIABLE _xcrun_err RESULT_VARIABLE _xcrun_result
|
||||||
|
)
|
||||||
|
|
||||||
|
if(_xcrun_result EQUAL 0 AND EXISTS "${_xcrun_out}")
|
||||||
|
set(CMAKE_Metal_COMPILER "${_xcrun_out}")
|
||||||
|
else()
|
||||||
|
_cmake_find_compiler_path(Metal)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if(CMAKE_Metal_COMPILER)
|
||||||
|
_cmake_find_compiler_path(Metal)
|
||||||
|
else()
|
||||||
|
set(CMAKE_Metal_COMPILER_INIT NOTFOUND)
|
||||||
|
|
||||||
|
if(NOT $ENV{METALC} STREQUAL "")
|
||||||
|
get_filename_component(CMAKE_Metal_COMPILER_INIT $ENV{METALC} PROGRAM PROGRAM_ARGS CMAKE_Metal_FLAGS_ENV_INIT)
|
||||||
|
if(CMAKE_Metal_FLAGS_ENV_INIT)
|
||||||
|
set(CMAKE_Metal_COMPILER_ARG1 "${CMAKE_Metal_FLAGS_ENV_INIT}" CACHE STRING "Arguments to the Metal compiler")
|
||||||
|
endif()
|
||||||
|
if(NOT EXISTS ${CMAKE_Metal_COMPILER_INIT})
|
||||||
|
message(FATAL_ERROR "Could not find compiler set in environment variable METALC\n$ENV{METALC}.\n${CMAKE_Metal_COMPILER_INIT}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_Metal_COMPILER_INIT)
|
||||||
|
set(CMAKE_Metal_COMPILER_LIST metal ${_CMAKE_TOOLCHAIN_PREFIX}metal)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
_cmake_find_compiler(Metal)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
mark_as_advanced(CMAKE_Metal_COMPILER)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# For Metal we need to explicitly query the version.
|
||||||
|
if(CMAKE_Metal_COMPILER AND NOT CMAKE_Metal_COMPILER_VERSION)
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${CMAKE_Metal_COMPILER}" --version
|
||||||
|
OUTPUT_VARIABLE output ERROR_VARIABLE output
|
||||||
|
RESULT_VARIABLE result
|
||||||
|
TIMEOUT 10
|
||||||
|
)
|
||||||
|
message(CONFIGURE_LOG
|
||||||
|
"Running the Metal compiler: \"${CMAKE_Metal_COMPILER}\" --version\n"
|
||||||
|
"${output}\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(output MATCHES [[metal version ([0-9]+\.[0-9]+(\.[0-9]+)?)]])
|
||||||
|
set(CMAKE_Metal_COMPILER_VERSION "${CMAKE_MATCH_1}")
|
||||||
|
if(NOT CMAKE_Metal_COMPILER_ID)
|
||||||
|
set(CMAKE_Metal_COMPILER_ID "Apple")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT _CMAKE_TOOLCHAIN_LOCATION)
|
||||||
|
get_filename_component(_CMAKE_TOOLCHAIN_LOCATION "${CMAKE_Metal_COMPILER}" PATH)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
set(_CMAKE_PROCESSING_LANGUAGE "Metal")
|
||||||
|
include(CMakeFindBinUtils)
|
||||||
|
unset(_CMAKE_PROCESSING_LANGUAGE)
|
||||||
|
|
||||||
|
configure_file(
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/CMakeMetalCompiler.cmake.in
|
||||||
|
${CMAKE_PLATFORM_INFO_DIR}/CMakeMetalCompiler.cmake
|
||||||
|
)
|
||||||
|
|
||||||
|
set(CMAKE_Metal_COMPILER_ENV_VAR "METALC")
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||||
|
# file LICENCE.txt or https://cmake.org/licensing for details.
|
||||||
|
|
||||||
|
# CMake(LANG)Compiler.cmake.in -> used by CMakeDetermine(LANG)Compiler.cmake
|
||||||
|
# This file is used to store compiler information and is copied down into try
|
||||||
|
# compile directories so that try compiles do not need to re-determine and test
|
||||||
|
# the LANG
|
||||||
|
|
||||||
|
set(CMAKE_Metal_COMPILER "@CMAKE_Metal_COMPILER@")
|
||||||
|
set(CMAKE_Metal_COMPILER_ID "@CMAKE_Metal_COMPILER_ID@")
|
||||||
|
set(CMAKE_Metal_COMPILER_VERSION "@CMAKE_Metal_COMPILER_VERSION@")
|
||||||
|
|
||||||
|
set(CMAKE_Metal_COMPILER_LOADED 1)
|
||||||
|
set(CMAKE_Metal_COMPILER_WORKS "@CMAKE_Metal_COMPILER_WORKS@")
|
||||||
|
|
||||||
|
set(CMAKE_Metal_COMPILER_ENV_VAR "METALC")
|
||||||
|
|
||||||
|
set(CMAKE_Metal_COMPILER_ID_RUN "@CMAKE_Metal_COMPILER_ID_RUN@")
|
||||||
|
set(CMAKE_Metal_SOURCE_FILE_EXTENSIONS metal)
|
||||||
|
set(CMAKE_Metal_OUTPUT_EXTENSION ".air")
|
||||||
|
set(CMAKE_STATIC_LIBRARY_PREFIX_Metal "")
|
||||||
|
set(CMAKE_STATIC_LIBRARY_SUFFIX_Metal ".metal-ar")
|
||||||
|
set(CMAKE_SHARED_LIBRARY_PREFIX_Metal "")
|
||||||
|
set(CMAKE_SHARED_LIBRARY_SUFFIX_Metal ".metallib")
|
||||||
|
set(CMAKE_SHARED_MODULE_PREFIX_Metal "")
|
||||||
|
set(CMAKE_SHARED_MODULE_SUFFIX_Metal ".metallib")
|
||||||
|
set(CMAKE_EXECUTABLE_SUFFIX_Metal ".metallib")
|
|
@ -0,0 +1,85 @@
|
||||||
|
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||||
|
# file LICENCE.txt or https://cmake.org/licensing for details.
|
||||||
|
|
||||||
|
# CMake(LANG)Information.cmake -> set up rule variables for LANG :
|
||||||
|
# CMAKE_(LANG)_CREATE_SHARED_LIBRARY
|
||||||
|
# CMAKE_(LANG)_CREATE_SHARED_MODULE
|
||||||
|
# CMAKE_(LANG)_CREATE_STATIC_LIBRARY
|
||||||
|
# CMAKE_(LANG)_COMPILE_OBJECT
|
||||||
|
# CMAKE_(LANG)_LINK_EXECUTABLE
|
||||||
|
|
||||||
|
include(CMakeCommonLanguageInclude)
|
||||||
|
|
||||||
|
set(CMAKE_Metal_FLAGS_INIT "-ffast-math")
|
||||||
|
set(CMAKE_Metal_FLAGS_DEBUG_INIT "-gline-tables-only -frecord-sources")
|
||||||
|
set(CMAKE_Metal_FLAGS_RELWITHDEBINFO_INIT "-gline-tables-only -frecord-sources")
|
||||||
|
|
||||||
|
cmake_initialize_per_config_variable(CMAKE_Metal_FLAGS "Flags used by the Metal compiler")
|
||||||
|
|
||||||
|
set(CMAKE_INCLUDE_FLAG_Metal "-I ")
|
||||||
|
set(CMAKE_Metal_COMPILER_ARG1 "")
|
||||||
|
set(CMAKE_Metal_DEFINE_FLAG -D)
|
||||||
|
set(CMAKE_Metal_FRAMEWORK_SEARCH_FLAG "-F ")
|
||||||
|
set(CMAKE_Metal_LIBRARY_PATH_FLAG "-L ")
|
||||||
|
set(CMAKE_Metal_SYSROOT_FLAG "-isysroot")
|
||||||
|
set(CMAKE_Metal_COMPILE_OPTIONS_TARGET "-target ")
|
||||||
|
set(CMAKE_DEPFILE_FLAGS_Metal "-MMD -MT dependencies -MF <DEP_FILE>")
|
||||||
|
|
||||||
|
if(CMAKE_GENERATOR MATCHES "Makefiles")
|
||||||
|
set(CMAKE_Metal_DEPFILE_FORMAT gcc)
|
||||||
|
set(CMAKE_Metal_DEPENDS_USE_COMPILER TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_Metal_COMPILER_PREDEFINES_COMMAND "${CMAKE_Metal_COMPILER}")
|
||||||
|
if(CMAKE_Metal_COMPILER_TARGET)
|
||||||
|
list(APPEND CMAKE_Metal_COMPILER_PREDEFINES_COMMAND "-target" "${CMAKE_Metal_COMPILER_TARGET}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# now define the following rule variables
|
||||||
|
|
||||||
|
# CMAKE_Metal_CREATE_SHARED_LIBRARY
|
||||||
|
# CMAKE_Metal_CREATE_SHARED_MODULE
|
||||||
|
# CMAKE_Metal_COMPILE_OBJECT
|
||||||
|
# CMAKE_Metal_LINK_EXECUTABLE
|
||||||
|
|
||||||
|
# variables supplied by the generator at use time
|
||||||
|
# <TARGET>
|
||||||
|
# <TARGET_BASE> the target without the suffix
|
||||||
|
# <OBJECTS>
|
||||||
|
# <OBJECT>
|
||||||
|
# <LINK_LIBRARIES>
|
||||||
|
# <FLAGS>
|
||||||
|
# <LINK_FLAGS>
|
||||||
|
|
||||||
|
# Metal compiler information
|
||||||
|
# <CMAKE_Metal_COMPILER>
|
||||||
|
# <CMAKE_SHARED_LIBRARY_CREATE_Metal_FLAGS>
|
||||||
|
# <CMAKE_SHARED_MODULE_CREATE_Metal_FLAGS>
|
||||||
|
# <CMAKE_Metal_LINK_FLAGS>
|
||||||
|
|
||||||
|
if(NOT CMAKE_Metal_COMPILE_OBJECT)
|
||||||
|
set(CMAKE_Metal_COMPILE_OBJECT
|
||||||
|
"<CMAKE_Metal_COMPILER> -c <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> <SOURCE>"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_Metal_CREATE_SHARED_LIBRARY)
|
||||||
|
set(CMAKE_Metal_CREATE_SHARED_LIBRARY
|
||||||
|
"<CMAKE_Metal_COMPILER> <CMAKE_SHARED_LIBRARY_Metal_FLAGS> <LANGUAGE_COMPILE_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_Metal_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_Metal_CREATE_SHARED_MODULE)
|
||||||
|
set(CMAKE_Metal_CREATE_SHARED_MODULE
|
||||||
|
"${CMAKE_Metal_CREATE_SHARED_LIBRARY}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_Metal_LINK_EXECUTABLE)
|
||||||
|
# Metal shaders don't really have "executables", but we need this for the try_compile to work properly, so we'll just have it output a metallib file
|
||||||
|
set(CMAKE_Metal_LINK_EXECUTABLE
|
||||||
|
"<CMAKE_Metal_COMPILER> <FLAGS> <CMAKE_Metal_LINK_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_Metal_INFORMATION_LOADED 1)
|
|
@ -0,0 +1,78 @@
|
||||||
|
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||||
|
# file LICENCE.txt or https://cmake.org/licensing for details.
|
||||||
|
|
||||||
|
# CMakeTest(LANG)Compiler.cmake -> test the compiler and set:
|
||||||
|
# SET(CMAKE_(LANG)_COMPILER_WORKS 1 CACHE INTERNAL "")
|
||||||
|
|
||||||
|
if(CMAKE_Metal_COMPILER_FORCED)
|
||||||
|
# The compiler configuration was forced by the user.
|
||||||
|
# Assume the user has configured all compiler information.
|
||||||
|
set(CMAKE_Metal_COMPILER_WORKS TRUE)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(CMakeTestCompilerCommon)
|
||||||
|
|
||||||
|
if("${CMAKE_GENERATOR}" STREQUAL "Xcode")
|
||||||
|
if(XCODE_VERSION VERSION_GREATER 7.0)
|
||||||
|
set(CMAKE_Metal_COMPILER_WORKS 1)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# This file is used by EnableLanguage in cmGlobalGenerator to
|
||||||
|
# determine that that selected Metal compiler can actually compile
|
||||||
|
# and link the most basic of programs. If not, a fatal error
|
||||||
|
# is set and cmake stops processing commands and will not generate
|
||||||
|
# any makefiles or projects.
|
||||||
|
if(NOT CMAKE_Metal_COMPILER_WORKS)
|
||||||
|
PrintTestCompilerStatus("Metal")
|
||||||
|
__TestCompiler_setTryCompileTargetType()
|
||||||
|
|
||||||
|
string(CONCAT __TestCompiler_testMetalCompilerSource
|
||||||
|
"#ifndef __METAL_VERSION__\n"
|
||||||
|
"# error \"The CMAKE_Metal_COMPILER is not a Metal compiler\"\n"
|
||||||
|
"#endif\n"
|
||||||
|
"#import <metal_stdlib>\n"
|
||||||
|
"using namespace metal;\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Clear result from normal variable.
|
||||||
|
unset(CMAKE_Metal_COMPILER_WORKS)
|
||||||
|
|
||||||
|
# Puts test result in cache variable.
|
||||||
|
try_compile(CMAKE_Metal_COMPILER_WORKS
|
||||||
|
SOURCE_FROM_VAR testMetalCompiler.metal __TestCompiler_testMetalCompilerSource
|
||||||
|
OUTPUT_VARIABLE __CMAKE_Metal_COMPILER_OUTPUT
|
||||||
|
)
|
||||||
|
unset(__TestCompiler_testMetalCompilerSource)
|
||||||
|
|
||||||
|
# Move result from cache to normal variable.
|
||||||
|
set(CMAKE_Metal_COMPILER_WORKS ${CMAKE_Metal_COMPILER_WORKS})
|
||||||
|
unset(CMAKE_Metal_COMPILER_WORKS CACHE)
|
||||||
|
__TestCompiler_restoreTryCompileTargetType()
|
||||||
|
set(METAL_TEST_WAS_RUN 1)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT CMAKE_Metal_COMPILER_WORKS)
|
||||||
|
PrintTestCompilerResult(CHECK_FAIL "broken")
|
||||||
|
string(REPLACE "\n" "\n " _output "${__CMAKE_Metal_COMPILER_OUTPUT}")
|
||||||
|
message(FATAL_ERROR "The Metal compiler\n \"${CMAKE_Metal_COMPILER}\"\n"
|
||||||
|
"is not able to compile a simple test program.\nIt fails "
|
||||||
|
"with the following output:\n ${_output}\n\n"
|
||||||
|
"CMake will not be able to correctly generate this project."
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
if(METAL_TEST_WAS_RUN)
|
||||||
|
PrintTestCompilerResult(CHECK_PASS "works")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Re-configure to save learned information.
|
||||||
|
configure_file(
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/CMakeMetalCompiler.cmake.in
|
||||||
|
${CMAKE_PLATFORM_INFO_DIR}/CMakeMetalCompiler.cmake
|
||||||
|
@ONLY
|
||||||
|
)
|
||||||
|
include(${CMAKE_PLATFORM_INFO_DIR}/CMakeMetalCompiler.cmake)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
unset(__CMAKE_Metal_COMPILER_OUTPUT)
|
|
@ -0,0 +1,169 @@
|
||||||
|
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||||
|
# file LICENCE.txt or https://cmake.org/licensing for details.
|
||||||
|
|
||||||
|
#[=======================================================================[.rst:
|
||||||
|
CheckLanguage
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Check whether a language can be enabled by the :command:`enable_language`
|
||||||
|
or :command:`project` commands:
|
||||||
|
|
||||||
|
.. command:: check_language
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
check_language(<lang>)
|
||||||
|
|
||||||
|
Try enabling language ``<lang>`` in a test project and record results
|
||||||
|
in the cache:
|
||||||
|
|
||||||
|
:variable:`CMAKE_<LANG>_COMPILER`
|
||||||
|
If the language can be enabled, this variable is set to the compiler
|
||||||
|
that was found. If the language cannot be enabled, this variable is
|
||||||
|
set to ``NOTFOUND``.
|
||||||
|
|
||||||
|
If this variable is already set, either explicitly or cached by
|
||||||
|
a previous call, the check is skipped.
|
||||||
|
|
||||||
|
:variable:`CMAKE_<LANG>_HOST_COMPILER`
|
||||||
|
This variable is set when ``<lang>`` is ``CUDA`` or ``HIP``.
|
||||||
|
|
||||||
|
If the check detects an explicit host compiler that is required for
|
||||||
|
compilation, this variable will be set to that compiler.
|
||||||
|
If the check detects that no explicit host compiler is needed,
|
||||||
|
this variable will be cleared.
|
||||||
|
|
||||||
|
If this variable is already set, its value is preserved only if
|
||||||
|
:variable:`CMAKE_<LANG>_COMPILER` is also set.
|
||||||
|
Otherwise, the check runs and overwrites
|
||||||
|
:variable:`CMAKE_<LANG>_HOST_COMPILER` with a new result.
|
||||||
|
Note that :variable:`CMAKE_<LANG>_HOST_COMPILER` documents it should
|
||||||
|
not be set without also setting
|
||||||
|
:variable:`CMAKE_<LANG>_COMPILER` to a NVCC compiler.
|
||||||
|
|
||||||
|
:variable:`CMAKE_<LANG>_PLATFORM <CMAKE_HIP_PLATFORM>`
|
||||||
|
This variable is set to the detected GPU platform when ``<lang>`` is ``HIP``.
|
||||||
|
|
||||||
|
If the variable is already set its value is always preserved. Only compatible values
|
||||||
|
will be considered for :variable:`CMAKE_<LANG>_COMPILER`.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
.. code-block:: cmake
|
||||||
|
|
||||||
|
check_language(Fortran)
|
||||||
|
if(CMAKE_Fortran_COMPILER)
|
||||||
|
enable_language(Fortran)
|
||||||
|
else()
|
||||||
|
message(STATUS "No Fortran support")
|
||||||
|
endif()
|
||||||
|
#]=======================================================================]
|
||||||
|
|
||||||
|
# This file has been modified to take into account the CMAKE_MODULES path when trying to build the test project
|
||||||
|
# Ref https://gitlab.kitware.com/cmake/cmake/-/issues/26020
|
||||||
|
# This was merged in to CMake 3.30.0, so we only need this for older versions
|
||||||
|
|
||||||
|
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.30)
|
||||||
|
include(${CMAKE_ROOT}/Modules/CheckLanguage.cmake)
|
||||||
|
else()
|
||||||
|
include_guard(GLOBAL)
|
||||||
|
|
||||||
|
block(SCOPE_FOR POLICIES)
|
||||||
|
cmake_policy(SET CMP0126 NEW)
|
||||||
|
|
||||||
|
macro(check_language lang)
|
||||||
|
if(NOT DEFINED CMAKE_${lang}_COMPILER)
|
||||||
|
set(_desc "Looking for a ${lang} compiler")
|
||||||
|
message(CHECK_START "${_desc}")
|
||||||
|
file(REMOVE_RECURSE ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang})
|
||||||
|
|
||||||
|
set(extra_compiler_variables)
|
||||||
|
if("${lang}" MATCHES "^(CUDA|HIP)$" AND NOT CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||||
|
set(extra_compiler_variables "set(CMAKE_${lang}_HOST_COMPILER \\\"\${CMAKE_${lang}_HOST_COMPILER}\\\")")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if("${lang}" STREQUAL "HIP")
|
||||||
|
list(APPEND extra_compiler_variables "set(CMAKE_${lang}_PLATFORM \\\"\${CMAKE_${lang}_PLATFORM}\\\")")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(TRANSFORM extra_compiler_variables PREPEND "\"")
|
||||||
|
list(TRANSFORM extra_compiler_variables APPEND "\\n\"")
|
||||||
|
list(JOIN extra_compiler_variables "\n " extra_compiler_variables)
|
||||||
|
|
||||||
|
set(_cl_content
|
||||||
|
"cmake_minimum_required(VERSION ${CMAKE_VERSION})
|
||||||
|
set(CMAKE_MODULE_PATH \"${CMAKE_MODULE_PATH}\")
|
||||||
|
project(Check${lang} ${lang})
|
||||||
|
file(WRITE \"\${CMAKE_CURRENT_BINARY_DIR}/result.cmake\"
|
||||||
|
\"set(CMAKE_${lang}_COMPILER \\\"\${CMAKE_${lang}_COMPILER}\\\")\\n\"
|
||||||
|
${extra_compiler_variables}
|
||||||
|
)"
|
||||||
|
)
|
||||||
|
|
||||||
|
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang}/CMakeLists.txt"
|
||||||
|
"${_cl_content}")
|
||||||
|
if(CMAKE_GENERATOR_INSTANCE)
|
||||||
|
set(_D_CMAKE_GENERATOR_INSTANCE "-DCMAKE_GENERATOR_INSTANCE:INTERNAL=${CMAKE_GENERATOR_INSTANCE}")
|
||||||
|
else()
|
||||||
|
set(_D_CMAKE_GENERATOR_INSTANCE "")
|
||||||
|
endif()
|
||||||
|
if(CMAKE_GENERATOR MATCHES "^(Xcode$|Green Hills MULTI$|Visual Studio)")
|
||||||
|
set(_D_CMAKE_MAKE_PROGRAM "")
|
||||||
|
else()
|
||||||
|
set(_D_CMAKE_MAKE_PROGRAM "-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}")
|
||||||
|
endif()
|
||||||
|
if(CMAKE_TOOLCHAIN_FILE)
|
||||||
|
set(_D_CMAKE_TOOLCHAIN_FILE "-DCMAKE_TOOLCHAIN_FILE:FILEPATH=${CMAKE_TOOLCHAIN_FILE}")
|
||||||
|
else()
|
||||||
|
set(_D_CMAKE_TOOLCHAIN_FILE "")
|
||||||
|
endif()
|
||||||
|
if(CMAKE_${lang}_PLATFORM)
|
||||||
|
set(_D_CMAKE_LANG_PLATFORM "-DCMAKE_${lang}_PLATFORM:STRING=${CMAKE_${lang}_PLATFORM}")
|
||||||
|
else()
|
||||||
|
set(_D_CMAKE_LANG_PLATFORM "")
|
||||||
|
endif()
|
||||||
|
execute_process(
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang}
|
||||||
|
COMMAND ${CMAKE_COMMAND} . -G ${CMAKE_GENERATOR}
|
||||||
|
-A "${CMAKE_GENERATOR_PLATFORM}"
|
||||||
|
-T "${CMAKE_GENERATOR_TOOLSET}"
|
||||||
|
${_D_CMAKE_GENERATOR_INSTANCE}
|
||||||
|
${_D_CMAKE_MAKE_PROGRAM}
|
||||||
|
${_D_CMAKE_TOOLCHAIN_FILE}
|
||||||
|
${_D_CMAKE_LANG_PLATFORM}
|
||||||
|
OUTPUT_VARIABLE _cl_output
|
||||||
|
ERROR_VARIABLE _cl_output
|
||||||
|
RESULT_VARIABLE _cl_result
|
||||||
|
)
|
||||||
|
include(${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/Check${lang}/result.cmake OPTIONAL)
|
||||||
|
if(CMAKE_${lang}_COMPILER AND "${_cl_result}" STREQUAL "0")
|
||||||
|
message(CONFIGURE_LOG
|
||||||
|
"${_desc} passed with the following output:\n"
|
||||||
|
"${_cl_output}\n")
|
||||||
|
set(_CHECK_COMPILER_STATUS CHECK_PASS)
|
||||||
|
else()
|
||||||
|
set(CMAKE_${lang}_COMPILER NOTFOUND)
|
||||||
|
set(_CHECK_COMPILER_STATUS CHECK_FAIL)
|
||||||
|
message(CONFIGURE_LOG
|
||||||
|
"${_desc} failed with the following output:\n"
|
||||||
|
"${_cl_output}\n")
|
||||||
|
endif()
|
||||||
|
message(${_CHECK_COMPILER_STATUS} "${CMAKE_${lang}_COMPILER}")
|
||||||
|
set(CMAKE_${lang}_COMPILER "${CMAKE_${lang}_COMPILER}" CACHE FILEPATH "${lang} compiler")
|
||||||
|
mark_as_advanced(CMAKE_${lang}_COMPILER)
|
||||||
|
|
||||||
|
if(CMAKE_${lang}_HOST_COMPILER)
|
||||||
|
message(STATUS "Looking for a ${lang} host compiler - ${CMAKE_${lang}_HOST_COMPILER}")
|
||||||
|
set(CMAKE_${lang}_HOST_COMPILER "${CMAKE_${lang}_HOST_COMPILER}" CACHE FILEPATH "${lang} host compiler")
|
||||||
|
mark_as_advanced(CMAKE_${lang}_HOST_COMPILER)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_${lang}_PLATFORM)
|
||||||
|
set(CMAKE_${lang}_PLATFORM "${CMAKE_${lang}_PLATFORM}" CACHE STRING "${lang} platform")
|
||||||
|
mark_as_advanced(CMAKE_${lang}_PLATFORM)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
endblock()
|
||||||
|
endif()
|
|
@ -11,11 +11,23 @@ if(CMAKE_SYSTEM_NAME STREQUAL FreeBSD)
|
||||||
set(OpenGL_GL_PREFERENCE LEGACY)
|
set(OpenGL_GL_PREFERENCE LEGACY)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(OpenGL REQUIRED)
|
if(NOT DISABLE_OPENGL)
|
||||||
find_package(SDL2 REQUIRED)
|
find_package(OpenGL)
|
||||||
|
|
||||||
# Add libsamplerate to SDL2 with vcpkg
|
if(NOT OpenGL_FOUND)
|
||||||
unset(SDL2_LIBRARY_TEMP)
|
set(CMAKE_C_FLAGS "-DNO_OPENGL -DNO_OGL ${CMAKE_C_FLAGS}")
|
||||||
|
set(CMAKE_CXX_FLAGS "-DNO_OPENGL -DNO_OGL ${CMAKE_CXX_FLAGS}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(ENABLE_SDL3)
|
||||||
|
find_package(SDL3 REQUIRED)
|
||||||
|
else()
|
||||||
|
find_package(SDL2 REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Add libsamplerate to SDL3 with vcpkg
|
||||||
|
unset(SDL_LIBRARY_TEMP)
|
||||||
if(CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg")
|
if(CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg")
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
unset(arch_suffix)
|
unset(arch_suffix)
|
||||||
|
@ -28,16 +40,24 @@ if(CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg")
|
||||||
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})
|
||||||
|
|
||||||
SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${installed_prefix}/lib/samplerate.lib)
|
SET(SDL_LIBRARY_TEMP ${SDL_LIBRARY_TEMP} ${installed_prefix}/lib/samplerate.lib)
|
||||||
else()
|
else()
|
||||||
SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} -lsamplerate)
|
SET(SDL_LIBRARY_TEMP ${SDL_LIBRARY_TEMP} -lsamplerate)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(VBAM_STATIC)
|
if(ENABLE_SDL3)
|
||||||
set(VBAM_SDL2_LIBS SDL2::SDL2-static ${SDL2_LIBRARY_TEMP})
|
if(VBAM_STATIC)
|
||||||
|
set(VBAM_SDL_LIBS SDL3::SDL3-static ${SDL_LIBRARY_TEMP})
|
||||||
|
else()
|
||||||
|
set(VBAM_SDL_LIBS SDL3::SDL3 ${SDL_LIBRARY_TEMP})
|
||||||
|
endif()
|
||||||
else()
|
else()
|
||||||
set(VBAM_SDL2_LIBS SDL2::SDL2 ${SDL2_LIBRARY_TEMP})
|
if(VBAM_STATIC)
|
||||||
|
set(VBAM_SDL_LIBS SDL2::SDL2-static ${SDL_LIBRARY_TEMP})
|
||||||
|
else()
|
||||||
|
set(VBAM_SDL_LIBS SDL2::SDL2 ${SDL_LIBRARY_TEMP})
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_FFMPEG)
|
if(ENABLE_FFMPEG)
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||||
|
# file LICENCE.txt or https://cmake.org/licensing for details.
|
||||||
|
|
||||||
|
function(add_metal_shader_library TARGET)
|
||||||
|
cmake_parse_arguments(PARSE_ARGV 1 _amsl
|
||||||
|
""
|
||||||
|
"STANDARD"
|
||||||
|
""
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library(${TARGET} MODULE ${_amsl_UNPARSED_ARGUMENTS})
|
||||||
|
|
||||||
|
set_target_properties(${TARGET} PROPERTIES
|
||||||
|
DEBUG_POSTFIX ""
|
||||||
|
XCODE_PRODUCT_TYPE com.apple.product-type.metal-library
|
||||||
|
XCODE_ATTRIBUTE_MTL_FAST_MATH "YES"
|
||||||
|
XCODE_ATTRIBUTE_MTL_ENABLE_DEBUG_INFO[variant=Debug] "INCLUDE_SOURCE"
|
||||||
|
XCODE_ATTRIBUTE_MTL_ENABLE_DEBUG_INFO[variant=RelWithDebInfo] "INCLUDE_SOURCE"
|
||||||
|
XCODE_ATTRIBUTE_MTL_HEADER_SEARCH_PATHS "$(HEADER_SEARCH_PATHS)"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(_amsl_STANDARD AND _amsl_STANDARD MATCHES "metal([0-9]+)\.([0-9]+)")
|
||||||
|
target_compile_options(${TARGET}
|
||||||
|
PRIVATE "-std=${_amsl_STANDARD}"
|
||||||
|
)
|
||||||
|
|
||||||
|
set_target_properties(${TARGET} PROPERTIES
|
||||||
|
XCODE_ATTRIBUTE_MTL_LANGUAGE_REVISION "Metal${CMAKE_MATCH_1}${CMAKE_MATCH_2}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
function(target_embed_metal_shader_libraries TARGET)
|
||||||
|
cmake_parse_arguments(PARSE_ARGV 1 _temsl
|
||||||
|
""
|
||||||
|
""
|
||||||
|
""
|
||||||
|
)
|
||||||
|
|
||||||
|
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.28 AND ${CMAKE_GENERATOR} STREQUAL "Xcode")
|
||||||
|
set_target_properties(${TARGET} PROPERTIES
|
||||||
|
XCODE_EMBED_RESOURCES "${_temsl_UNPARSED_ARGUMENTS}"
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
foreach(SHADERLIB IN LISTS _temsl_UNPARSED_ARGUMENTS)
|
||||||
|
add_dependencies(${TARGET} ${SHADERLIB})
|
||||||
|
add_custom_command(TARGET ${TARGET} POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy "$<TARGET_FILE:${SHADERLIB}>" "$<TARGET_BUNDLE_CONTENT_DIR:${TARGET}>/Resources/$<TARGET_FILE_NAME:${SHADERLIB}>"
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
endfunction()
|
|
@ -9,15 +9,28 @@ else()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(ENABLE_SDL_DEFAULT ${BUILD_DEFAULT})
|
set(ENABLE_SDL_DEFAULT ${BUILD_DEFAULT})
|
||||||
|
|
||||||
if(WIN32 OR APPLE)
|
if(WIN32 OR APPLE)
|
||||||
set(ENABLE_SDL_DEFAULT OFF)
|
set(ENABLE_SDL_DEFAULT OFF)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
option(ENABLE_SDL3 "Use SDL3" OFF)
|
||||||
|
option(DISABLE_OPENGL "Disable OpenGL" OFF)
|
||||||
option(ENABLE_SDL "Build the SDL port" ${ENABLE_SDL_DEFAULT})
|
option(ENABLE_SDL "Build the SDL port" ${ENABLE_SDL_DEFAULT})
|
||||||
option(ENABLE_WX "Build the wxWidgets port" ${BUILD_DEFAULT})
|
option(ENABLE_WX "Build the wxWidgets port" ${BUILD_DEFAULT})
|
||||||
option(ENABLE_DEBUGGER "Enable the debugger" ON)
|
option(ENABLE_DEBUGGER "Enable the debugger" ON)
|
||||||
option(ENABLE_ASAN "Enable -fsanitize=address by default. Requires debug build with GCC/Clang" OFF)
|
option(ENABLE_ASAN "Enable -fsanitize=address by default. Requires debug build with GCC/Clang" OFF)
|
||||||
|
|
||||||
|
if(ENABLE_SDL3)
|
||||||
|
set(CMAKE_C_FLAGS "-DENABLE_SDL3 ${CMAKE_C_FLAGS}")
|
||||||
|
set(CMAKE_CXX_FLAGS "-DENABLE_SDL3 ${CMAKE_CXX_FLAGS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(DISABLE_OPENGL)
|
||||||
|
set(CMAKE_C_FLAGS "-DNO_OPENGL -DNO_OGL ${CMAKE_C_FLAGS}")
|
||||||
|
set(CMAKE_CXX_FLAGS "-DNO_OPENGL -DNO_OGL ${CMAKE_CXX_FLAGS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Static linking
|
# Static linking
|
||||||
set(VBAM_STATIC_DEFAULT OFF)
|
set(VBAM_STATIC_DEFAULT OFF)
|
||||||
if(VCPKG_TARGET_TRIPLET MATCHES -static OR CMAKE_TOOLCHAIN_FILE MATCHES "mxe|-static")
|
if(VCPKG_TARGET_TRIPLET MATCHES -static OR CMAKE_TOOLCHAIN_FILE MATCHES "mxe|-static")
|
||||||
|
@ -30,6 +43,8 @@ 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(SDL3_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)
|
||||||
|
|
|
@ -68,6 +68,8 @@ if(CMAKE_VERSION VERSION_LESS "3.25")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:/std:c++17>)
|
||||||
|
|
||||||
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.
|
||||||
|
|
|
@ -361,6 +361,14 @@ msgstr "Няма намерени използваеми добавки в/ъв
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Добавка"
|
msgstr "Добавка"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Битове на пиксел"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Битове на пиксел:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -361,6 +361,14 @@ msgstr "N'eo ket bet kavet an astenn rpi implijadus e-barzh %s"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Astenn"
|
msgstr "Astenn"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bits por pixel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bits por pixel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -365,6 +365,14 @@ msgstr "V %s nenalezeny žádné použitelné zásuvné moduly rpi"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Zásuvný modul"
|
msgstr "Zásuvný modul"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Počet bitů na pixel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Počet bitů na pixel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -378,6 +378,14 @@ msgstr "Keine anwendbaren RPI-Plugins in %s gefunden"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Plugin"
|
msgstr "Plugin"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bits pro Pixel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bits pro Pixel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -362,6 +362,14 @@ msgstr "Δεν βρέθηκαν χρήσιμες επεκτάσεις rpi στο
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Επέκταση"
|
msgstr "Επέκταση"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bits ανά pixel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bits ανά pixel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -1560,6 +1560,14 @@ msgstr ""
|
||||||
msgid "Using interframe blending: %s"
|
msgid "Using interframe blending: %s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bits per pixel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bits per pixel:"
|
||||||
|
|
||||||
#: dialogs/game-boy-config.cpp:142 xrc/GameBoyAdvanceConfig.xrc:122
|
#: dialogs/game-boy-config.cpp:142 xrc/GameBoyAdvanceConfig.xrc:122
|
||||||
#: xrc/GameBoyConfig.xrc:138 xrc/GameBoyConfig.xrc:159
|
#: xrc/GameBoyConfig.xrc:138 xrc/GameBoyConfig.xrc:159
|
||||||
msgid "(None)"
|
msgid "(None)"
|
||||||
|
|
|
@ -382,6 +382,14 @@ msgstr "No se encontraron complementos rpi usables en %s"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Complemento"
|
msgstr "Complemento"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bits por píxel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bits por píxel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -374,6 +374,14 @@ msgstr "No usable rpi plugins found in %s"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Plugin"
|
msgstr "Plugin"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bits por píxel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bits por píxel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -1553,6 +1553,14 @@ msgstr "No usable rpi plugins found in %s"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Plugin"
|
msgstr "Plugin"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bits per píxel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bits per píxel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:417
|
#: dialogs/display-config.cpp:417
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -1549,6 +1549,14 @@ msgstr "No usable rpi plugins found in %s"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Plugin"
|
msgstr "Plugin"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bits per píxel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bits per píxel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:417
|
#: dialogs/display-config.cpp:417
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -1549,6 +1549,14 @@ msgstr "No usable rpi plugins found in %s"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Plugin"
|
msgstr "Plugin"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bits per píxel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bits per píxel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:417
|
#: dialogs/display-config.cpp:417
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -1563,6 +1563,14 @@ msgstr "Extension rpi utilisable non trouvée dans %s"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Extension"
|
msgstr "Extension"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bits par pixel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bits par pixel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:417
|
#: dialogs/display-config.cpp:417
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -369,6 +369,14 @@ msgstr "Aucun plugin RPI utilisable n'a été trouvé dans %s"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Plugin"
|
msgstr "Plugin"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bits par pixel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bits par pixel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -364,6 +364,14 @@ msgstr "Non se atoparon complementos rpi aproveitábeis en %s"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Complemento"
|
msgstr "Complemento"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bits por píxel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bits por píxel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -362,6 +362,14 @@ msgstr "לא נמצא תוסף rpi הניתן לשימוש ב-%s"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "תוסף"
|
msgstr "תוסף"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "סיביות לפיקסל"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "סיביות לפיקסל:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -1549,6 +1549,14 @@ msgstr "A %s helyen nincs használható RPI bővítmény"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Bővítmény"
|
msgstr "Bővítmény"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bit per pixel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bit per pixel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:417
|
#: dialogs/display-config.cpp:417
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -363,6 +363,14 @@ msgstr "A %s helyen nincs használható RPI bővítmény"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Bővítmény"
|
msgstr "Bővítmény"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bit per pixel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bit per pixel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -366,6 +366,14 @@ msgstr "Tidak menemukan plugin rpi yang dapat digunakan di %s"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Plugin"
|
msgstr "Plugin"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bit per piksel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bit per piksel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -378,6 +378,14 @@ msgstr "Non sono stati trovati plugin rpi utilizzabili in %s"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Plugin"
|
msgstr "Plugin"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bit per pixel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bit per pixel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -370,6 +370,14 @@ msgstr "%s に使用可能なrpiプラグインが見つかりませんでした
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "プラグイン"
|
msgstr "プラグイン"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "ピクセルあたりのビット数"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "ピクセルあたりのビット数:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -362,6 +362,14 @@ msgstr ""
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -1552,6 +1552,14 @@ msgstr "%s에서 사용가능한 rpi 플러그인을 찾을 수 없음"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "플러그인"
|
msgstr "플러그인"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "픽셀당 비트"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "픽셀당 비트:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:417
|
#: dialogs/display-config.cpp:417
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -365,6 +365,14 @@ msgstr "%s에서 사용가능한 rpi 플러그인을 찾을 수 없음"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "플러그인"
|
msgstr "플러그인"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "픽셀당 비트"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "픽셀당 비트:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -361,6 +361,14 @@ msgstr "Tiada pemalam rpi boleh guna ditemui dalam %s"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Pemalam"
|
msgstr "Pemalam"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bit setiap piksel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bit setiap piksel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -364,6 +364,14 @@ msgstr "Ingen brukbare rpi plugins funnet i %s"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Plugin"
|
msgstr "Plugin"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bits per piksel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bits per piksel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -365,6 +365,14 @@ msgstr "Geen bruikbare rpi plugin gevonden in %s"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Plug-in"
|
msgstr "Plug-in"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bits per pixel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bits per pixel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -1552,6 +1552,14 @@ msgstr "Nie znaleziono użytecznych wtyczek rpi w %s"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Wtyczka"
|
msgstr "Wtyczka"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bity na piksel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bity na piksel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:417
|
#: dialogs/display-config.cpp:417
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -361,6 +361,14 @@ msgstr "Nie znaleziono użytecznych wtyczek rpi w %s"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Wtyczka"
|
msgstr "Wtyczka"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bity na piksel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bity na piksel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -390,6 +390,14 @@ msgstr "Nenhum plugin rpi usável foi encontrado em %s"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Plugin"
|
msgstr "Plugin"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bits por pixel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bits por pixel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -362,6 +362,14 @@ msgstr ""
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bits por pixel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bits por pixel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -377,6 +377,14 @@ msgstr "Не найдено подходящих rpi-плагинов в %s"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Плагин"
|
msgstr "Плагин"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Бит на пиксель"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Бит на пиксель:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -369,6 +369,14 @@ msgstr "Inga användbara rpi plugins funna i %s"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Plugin"
|
msgstr "Plugin"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Bitar per pixel"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Bitar per pixel:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -370,6 +370,14 @@ msgstr "%s'da kullanılabilir bir rpi eklentisi bulunamadı"
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Eklenti"
|
msgstr "Eklenti"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Piksel başına bit sayısı"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Piksel başına bit sayısı:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -362,6 +362,14 @@ msgstr "Не знайдено придатних rpi-плаґінів у %s."
|
||||||
msgid "Plugin"
|
msgid "Plugin"
|
||||||
msgstr "Плаґін"
|
msgstr "Плаґін"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "Біт на піксель"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "Біт на піксель:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:407
|
#: dialogs/display-config.cpp:407
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Using pixel filter: %s"
|
msgid "Using pixel filter: %s"
|
||||||
|
|
|
@ -1046,6 +1046,14 @@ msgstr ""
|
||||||
msgid "Invalid value for Default magnification."
|
msgid "Invalid value for Default magnification."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:331 xrc/DisplayConfig.xrc:86
|
#: dialogs/display-config.cpp:331 xrc/DisplayConfig.xrc:86
|
||||||
#: xrc/DisplayConfig.xrc:136 xrc/DisplayConfig.xrc:222
|
#: xrc/DisplayConfig.xrc:136 xrc/DisplayConfig.xrc:222
|
||||||
#: xrc/GameBoyAdvanceConfig.xrc:32 xrc/GameBoyAdvanceConfig.xrc:204
|
#: xrc/GameBoyAdvanceConfig.xrc:32 xrc/GameBoyAdvanceConfig.xrc:204
|
||||||
|
|
|
@ -360,6 +360,14 @@ msgstr "浏览"
|
||||||
msgid "Invalid value for Default magnification."
|
msgid "Invalid value for Default magnification."
|
||||||
msgstr "无效的默认放大倍数值。"
|
msgstr "无效的默认放大倍数值。"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth"
|
||||||
|
msgstr "每像素位数"
|
||||||
|
|
||||||
|
#: xrc/DisplayConfig.xrc
|
||||||
|
msgid "Bit Depth:"
|
||||||
|
msgstr "每像素位数:"
|
||||||
|
|
||||||
#: dialogs/display-config.cpp:331 xrc/DisplayConfig.xrc:86
|
#: dialogs/display-config.cpp:331 xrc/DisplayConfig.xrc:86
|
||||||
#: xrc/DisplayConfig.xrc:136 xrc/DisplayConfig.xrc:222
|
#: xrc/DisplayConfig.xrc:136 xrc/DisplayConfig.xrc:222
|
||||||
#: xrc/GameBoyAdvanceConfig.xrc:32 xrc/GameBoyAdvanceConfig.xrc:204
|
#: xrc/GameBoyAdvanceConfig.xrc:32 xrc/GameBoyAdvanceConfig.xrc:204
|
||||||
|
|
|
@ -226,6 +226,9 @@ recording::MediaRet recording::MediaRecorder::setup_video_stream_info(int width,
|
||||||
{
|
{
|
||||||
switch (depth)
|
switch (depth)
|
||||||
{
|
{
|
||||||
|
case 8:
|
||||||
|
pixfmt = AV_PIX_FMT_RGB8;
|
||||||
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
// FIXME: test & make endian-neutral
|
// FIXME: test & make endian-neutral
|
||||||
pixfmt = AV_PIX_FMT_RGB565LE;
|
pixfmt = AV_PIX_FMT_RGB565LE;
|
||||||
|
@ -250,6 +253,9 @@ recording::MediaRet recording::MediaRecorder::setup_video_stream_info(int width,
|
||||||
linesize = pixsize * width;
|
linesize = pixsize * width;
|
||||||
switch (pixsize)
|
switch (pixsize)
|
||||||
{
|
{
|
||||||
|
case 1:
|
||||||
|
tbord = 1; rbord = 2;
|
||||||
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
// 16-bit: 2 @ right, 1 @ top
|
// 16-bit: 2 @ right, 1 @ top
|
||||||
tbord = 1; rbord = 2;
|
tbord = 1; rbord = 2;
|
||||||
|
|
|
@ -45,11 +45,11 @@ void lq2x(uint8_t* src, uint32_t spitch, uint8_t*, uint8_t* dst, uint32_t dstp,
|
||||||
// in any case, they are worthless, since all renderers do "simple" or
|
// in any case, they are worthless, since all renderers do "simple" or
|
||||||
// better by default
|
// better by default
|
||||||
void Simple2x32(uint8_t* src, uint32_t spitch, uint8_t*, uint8_t* dst, uint32_t dstp, int w, int h);
|
void Simple2x32(uint8_t* src, uint32_t spitch, uint8_t*, uint8_t* dst, uint32_t dstp, int w, int h);
|
||||||
void Simple2x(uint8_t* src, uint32_t spitch, uint8_t*, uint8_t* dst, uint32_t dstp, int w, int h);
|
void Simple2x16(uint8_t* src, uint32_t spitch, uint8_t*, uint8_t* dst, uint32_t dstp, int w, int h);
|
||||||
void Simple3x32(uint8_t* src, uint32_t spitch, uint8_t*, uint8_t* dst, uint32_t dstp, int w, int h);
|
void Simple3x32(uint8_t* src, uint32_t spitch, uint8_t*, uint8_t* dst, uint32_t dstp, int w, int h);
|
||||||
void Simple3x(uint8_t* src, uint32_t spitch, uint8_t*, uint8_t* dst, uint32_t dstp, int w, int h);
|
void Simple3x16(uint8_t* src, uint32_t spitch, uint8_t*, uint8_t* dst, uint32_t dstp, int w, int h);
|
||||||
void Simple4x32(uint8_t* src, uint32_t spitch, uint8_t*, uint8_t* dst, uint32_t dstp, int w, int h);
|
void Simple4x32(uint8_t* src, uint32_t spitch, uint8_t*, uint8_t* dst, uint32_t dstp, int w, int h);
|
||||||
void Simple4x(uint8_t* src, uint32_t spitch, uint8_t*, uint8_t* dst, uint32_t dstp, int w, int h);
|
void Simple4x16(uint8_t* src, uint32_t spitch, uint8_t*, uint8_t* dst, uint32_t dstp, int w, int h);
|
||||||
// note: 16-bit input for asm version only!
|
// note: 16-bit input for asm version only!
|
||||||
void hq3x32(uint8_t* src, uint32_t spitch, uint8_t*, uint8_t* dst, uint32_t dstp, int w, int h);
|
void hq3x32(uint8_t* src, uint32_t spitch, uint8_t*, uint8_t* dst, uint32_t dstp, int w, int h);
|
||||||
// this takes 32-bit input
|
// this takes 32-bit input
|
||||||
|
|
|
@ -5,6 +5,7 @@ extern int systemRedShift;
|
||||||
extern int systemGreenShift;
|
extern int systemGreenShift;
|
||||||
extern int systemBlueShift;
|
extern int systemBlueShift;
|
||||||
|
|
||||||
|
extern uint8_t systemColorMap8[0x10000];
|
||||||
extern uint16_t systemColorMap16[0x10000];
|
extern uint16_t systemColorMap16[0x10000];
|
||||||
extern uint32_t systemColorMap32[0x10000];
|
extern uint32_t systemColorMap32[0x10000];
|
||||||
|
|
||||||
|
@ -27,6 +28,13 @@ inline void swap(short& a, short& b)
|
||||||
|
|
||||||
void gbafilter_update_colors(bool lcd) {
|
void gbafilter_update_colors(bool lcd) {
|
||||||
switch (systemColorDepth) {
|
switch (systemColorDepth) {
|
||||||
|
case 8: {
|
||||||
|
for (int i = 0; i < 0x10000; i++) {
|
||||||
|
systemColorMap8[i] = (uint8_t)((((i & 0x1f) << 3) & 0xE0) |
|
||||||
|
((((i & 0x3e0) >> 5) << 0) & 0x1C) |
|
||||||
|
((((i & 0x7c00) >> 10) >> 3) & 0x3));
|
||||||
|
}
|
||||||
|
} break;
|
||||||
case 16: {
|
case 16: {
|
||||||
for (int i = 0; i < 0x10000; i++) {
|
for (int i = 0; i < 0x10000; i++) {
|
||||||
systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
|
systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
|
||||||
|
@ -237,6 +245,15 @@ void gbafilter_pad(uint8_t* buf, int count)
|
||||||
void UpdateSystemColorMaps(int lcd)
|
void UpdateSystemColorMaps(int lcd)
|
||||||
{
|
{
|
||||||
switch(systemColorDepth) {
|
switch(systemColorDepth) {
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
for(int i = 0; i < 0x10000; i++) {
|
||||||
|
systemColorMap8[i] = (((i & 0x1f) << systemRedShift) & 0xE0) |
|
||||||
|
((((i & 0x3e0) >> 5) << systemGreenShift) & 0x1C) |
|
||||||
|
((((i & 0x7c00) >> 10) << systemBlueShift) & 0x3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
{
|
{
|
||||||
for(int i = 0; i < 0x10000; i++) {
|
for(int i = 0; i < 0x10000; i++) {
|
||||||
|
|
|
@ -159,6 +159,51 @@ static void SmartIB_MMX(uint8_t *srcPtr, uint32_t srcPitch, int width, int start
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void SmartIB8(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height)
|
||||||
|
{
|
||||||
|
(void)width; // unused param
|
||||||
|
if(frm1 == NULL) {
|
||||||
|
InterframeFilterInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t colorMask = ~RGB_LOW_BITS_MASK;
|
||||||
|
|
||||||
|
uint8_t *src0 = (uint8_t *)srcPtr + starty * srcPitch;
|
||||||
|
uint8_t *src1 = (uint8_t *)frm1 + srcPitch * starty;
|
||||||
|
uint8_t *src2 = (uint8_t *)frm2 + srcPitch * starty;
|
||||||
|
uint8_t *src3 = (uint8_t *)frm3 + srcPitch * starty;
|
||||||
|
|
||||||
|
int sPitch = srcPitch;
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
for (int j = 0; j < height; j++)
|
||||||
|
for (int i = 0; i < sPitch; i++) {
|
||||||
|
uint16_t color = src0[pos] == 0xff ? 0x7fff : ((src0[pos] & 0xe0) << 7) | ((src0[pos] & 0x1c) << 5) | ((src0[pos] & 0x3) << 3);
|
||||||
|
uint16_t color2 = src1[pos] == 0xff ? 0x7fff : ((src1[pos] & 0xe0) << 7) | ((src1[pos] & 0x1c) << 5) | ((src1[pos] & 0x3) << 3);
|
||||||
|
uint16_t color_dst = ((color & colorMask) >> 1) + ((color2 & colorMask) >> 1);
|
||||||
|
src0[pos] =
|
||||||
|
(src1[pos] != src2[pos]) &&
|
||||||
|
(src3[pos] != color) &&
|
||||||
|
((color == src2[pos]) || (src1[pos] == src3[pos]))
|
||||||
|
? (uint8_t)(((color_dst >> 7) & 0xe0) | ((color_dst >> 5) & 0x1c) | ((color_dst >> 3) & 0x3)) :
|
||||||
|
(uint8_t)(((color >> 7) & 0xe0) | ((color >> 5) & 0x1c) | ((color >> 3) & 0x3));
|
||||||
|
src3[pos] = (uint8_t)(((color >> 7) & 0xe0) | ((color >> 5) & 0x1c) | ((color >> 3) & 0x3)); /* oldest buffer now holds newest frame */
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Swap buffers around */
|
||||||
|
uint8_t *temp = frm1;
|
||||||
|
frm1 = frm3;
|
||||||
|
frm3 = frm2;
|
||||||
|
frm2 = temp;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmartIB8(uint8_t *srcPtr, uint32_t srcPitch, int width, int height)
|
||||||
|
{
|
||||||
|
SmartIB8(srcPtr, srcPitch, width, 0, height);
|
||||||
|
}
|
||||||
|
|
||||||
void SmartIB(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height)
|
void SmartIB(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height)
|
||||||
{
|
{
|
||||||
(void)width; // unused param
|
(void)width; // unused param
|
||||||
|
@ -207,6 +252,64 @@ void SmartIB(uint8_t *srcPtr, uint32_t srcPitch, int width, int height)
|
||||||
SmartIB(srcPtr, srcPitch, width, 0, height);
|
SmartIB(srcPtr, srcPitch, width, 0, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SmartIB24(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height)
|
||||||
|
{
|
||||||
|
(void)width; // unused param
|
||||||
|
if(frm1 == NULL) {
|
||||||
|
InterframeFilterInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t colorMask = 0xfe;
|
||||||
|
|
||||||
|
uint8_t *src0 = (uint8_t *)srcPtr + starty * srcPitch / 3;
|
||||||
|
uint8_t *src1 = (uint8_t *)frm1 + srcPitch * starty / 3;
|
||||||
|
uint8_t *src2 = (uint8_t *)frm2 + srcPitch * starty / 3;
|
||||||
|
uint8_t *src3 = (uint8_t *)frm3 + srcPitch * starty / 3;
|
||||||
|
|
||||||
|
int sPitch = srcPitch / 3;
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
for (int j = 0; j < height; j++)
|
||||||
|
for (int i = 0; i < sPitch; i++) {
|
||||||
|
uint8_t color = src0[pos];
|
||||||
|
uint8_t color2 = src0[pos+1];
|
||||||
|
uint8_t color3 = src0[pos+2];
|
||||||
|
src0[pos] =
|
||||||
|
(src1[pos] != src2[pos]) &&
|
||||||
|
(src3[pos] != color) &&
|
||||||
|
((color == src2[pos]) || (src1[pos] == src3[pos]))
|
||||||
|
? (((color & colorMask) >> 1) + ((src1[pos] & colorMask) >> 1)) :
|
||||||
|
color;
|
||||||
|
src0[pos+1] =
|
||||||
|
(src1[pos+1] != src2[pos+1]) &&
|
||||||
|
(src3[pos+1] != color2) &&
|
||||||
|
((color2 == src2[pos+1]) || (src1[pos+1] == src3[pos+1]))
|
||||||
|
? (((color2 & colorMask) >> 1) + ((src1[pos+1] & colorMask) >> 1)) :
|
||||||
|
color2;
|
||||||
|
src0[pos+2] =
|
||||||
|
(src1[pos+2] != src2[pos+2]) &&
|
||||||
|
(src3[pos+2] != color3) &&
|
||||||
|
((color3 == src2[pos+2]) || (src1[pos+1] == src3[pos+2]))
|
||||||
|
? (((color3 & colorMask) >> 1) + ((src1[pos+2] & colorMask) >> 1)) :
|
||||||
|
color3;
|
||||||
|
src3[pos] = color; /* oldest buffer now holds newest frame */
|
||||||
|
src3[pos+1] = color2; /* oldest buffer now holds newest frame */
|
||||||
|
src3[pos+2] = color3; /* oldest buffer now holds newest frame */
|
||||||
|
pos += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Swap buffers around */
|
||||||
|
uint8_t *temp = frm1;
|
||||||
|
frm1 = frm3;
|
||||||
|
frm3 = frm2;
|
||||||
|
frm2 = temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SmartIB24(uint8_t *srcPtr, uint32_t srcPitch, int width, int height)
|
||||||
|
{
|
||||||
|
SmartIB24(srcPtr, srcPitch, width, 0, height);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef MMX
|
#ifdef MMX
|
||||||
static void SmartIB32_MMX(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height)
|
static void SmartIB32_MMX(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height)
|
||||||
{
|
{
|
||||||
|
@ -443,6 +546,70 @@ static void MotionBlurIB_MMX(uint8_t *srcPtr, uint32_t srcPitch, int width, int
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void MotionBlurIB24(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height)
|
||||||
|
{
|
||||||
|
(void)width; // unused param
|
||||||
|
if(frm1 == NULL) {
|
||||||
|
InterframeFilterInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t colorMask = 0xfe;
|
||||||
|
|
||||||
|
uint8_t *src0 = (uint8_t *)srcPtr + starty * srcPitch / 3;
|
||||||
|
uint8_t *src1 = (uint8_t *)frm1 + starty * srcPitch / 3;
|
||||||
|
int sPitch = srcPitch / 3;
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
for (int j = 0; j < height; j++)
|
||||||
|
for (int i = 0; i < sPitch; i++) {
|
||||||
|
uint8_t color = src0[pos];
|
||||||
|
uint8_t color2 = src0[pos+1];
|
||||||
|
uint8_t color3 = src0[pos+2];
|
||||||
|
src0[pos] = ((color & colorMask) >> 1) + ((src1[pos] & colorMask) >> 1);
|
||||||
|
src0[pos+1] = ((color2 & colorMask) >> 1) + ((src1[pos+1] & colorMask) >> 1);
|
||||||
|
src0[pos+2] = ((color3 & colorMask) >> 1) + ((src1[pos+2] & colorMask) >> 1);
|
||||||
|
src1[pos] = color;
|
||||||
|
src1[pos+1] = color2;
|
||||||
|
src1[pos+2] = color3;
|
||||||
|
pos += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MotionBlurIB24(uint8_t *srcPtr, uint32_t srcPitch, int width, int height)
|
||||||
|
{
|
||||||
|
MotionBlurIB24(srcPtr, srcPitch, width, 0, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MotionBlurIB8(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height)
|
||||||
|
{
|
||||||
|
(void)width; // unused param
|
||||||
|
if(frm1 == NULL) {
|
||||||
|
InterframeFilterInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t colorMask = ~RGB_LOW_BITS_MASK;
|
||||||
|
|
||||||
|
uint8_t *src0 = (uint8_t *)srcPtr + starty * srcPitch;
|
||||||
|
uint8_t *src1 = (uint8_t *)frm1 + starty * srcPitch;
|
||||||
|
int sPitch = srcPitch;
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
for (int j = 0; j < height; j++)
|
||||||
|
for (int i = 0; i < sPitch; i++) {
|
||||||
|
uint16_t color = src0[pos] == 0xff ? 0x7fff : ((src0[pos] & 0xe0) << 7) | ((src0[pos] & 0x1c) << 5) | ((src0[pos] & 0x3) << 3);
|
||||||
|
uint16_t color2 = src1[pos] == 0xff ? 0x7fff : ((src1[pos] & 0xe0) << 7) | ((src1[pos] & 0x1c) << 5) | ((src1[pos] & 0x3) << 3);
|
||||||
|
uint16_t color_dst = ((color & colorMask) >> 1) + ((color2 & colorMask) >> 1);
|
||||||
|
src0[pos] = (uint8_t)(((color_dst >> 7) & 0xe0) | ((color_dst >> 5) & 0x1c) | ((color_dst >> 3) & 0x3));
|
||||||
|
src1[pos] = (uint8_t)(((color >> 7) & 0xe0) | ((color >> 5) & 0x1c) | ((color >> 3) & 0x3));
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MotionBlurIB8(uint8_t *srcPtr, uint32_t srcPitch, int width, int height)
|
||||||
|
{
|
||||||
|
MotionBlurIB8(srcPtr, srcPitch, width, 0, height);
|
||||||
|
}
|
||||||
|
|
||||||
void MotionBlurIB(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height)
|
void MotionBlurIB(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height)
|
||||||
{
|
{
|
||||||
(void)width; // unused param
|
(void)width; // unused param
|
||||||
|
|
|
@ -14,8 +14,12 @@ void InterframeCleanup();
|
||||||
|
|
||||||
// all 4 are MMX-accelerated if enabled
|
// all 4 are MMX-accelerated if enabled
|
||||||
void SmartIB(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height);
|
void SmartIB(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height);
|
||||||
|
void SmartIB8(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height);
|
||||||
|
void SmartIB24(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height);
|
||||||
void SmartIB32(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height);
|
void SmartIB32(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height);
|
||||||
void MotionBlurIB(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height);
|
void MotionBlurIB(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height);
|
||||||
|
void MotionBlurIB8(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height);
|
||||||
|
void MotionBlurIB24(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height);
|
||||||
void MotionBlurIB32(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height);
|
void MotionBlurIB32(uint8_t *srcPtr, uint32_t srcPitch, int width, int starty, int height);
|
||||||
|
|
||||||
#ifdef MMX
|
#ifdef MMX
|
||||||
|
@ -27,8 +31,12 @@ static void MotionBlurIB32_MMX(uint8_t *srcPtr, uint32_t srcPitch, int width, in
|
||||||
|
|
||||||
//Options for if start is 0
|
//Options for if start is 0
|
||||||
void SmartIB(uint8_t *srcPtr, uint32_t srcPitch, int width, int height);
|
void SmartIB(uint8_t *srcPtr, uint32_t srcPitch, int width, int height);
|
||||||
|
void SmartIB8(uint8_t *srcPtr, uint32_t srcPitch, int width, int height);
|
||||||
|
void SmartIB24(uint8_t *srcPtr, uint32_t srcPitch, int width, int height);
|
||||||
void SmartIB32(uint8_t *srcPtr, uint32_t srcPitch, int width, int height);
|
void SmartIB32(uint8_t *srcPtr, uint32_t srcPitch, int width, int height);
|
||||||
void MotionBlurIB(uint8_t *srcPtr, uint32_t srcPitch, int width, int height);
|
void MotionBlurIB(uint8_t *srcPtr, uint32_t srcPitch, int width, int height);
|
||||||
|
void MotionBlurIB8(uint8_t *srcPtr, uint32_t srcPitch, int width, int height);
|
||||||
|
void MotionBlurIB24(uint8_t *srcPtr, uint32_t srcPitch, int width, int height);
|
||||||
void MotionBlurIB32(uint8_t *srcPtr, uint32_t srcPitch, int width, int height);
|
void MotionBlurIB32(uint8_t *srcPtr, uint32_t srcPitch, int width, int height);
|
||||||
|
|
||||||
#endif //VBAM_COMPONENTS_FILTERS_INTERFRAME_INTERFRAME_H_
|
#endif //VBAM_COMPONENTS_FILTERS_INTERFRAME_INTERFRAME_H_
|
||||||
|
|
|
@ -10,6 +10,8 @@ extern "C" {
|
||||||
#include "core/base/system.h"
|
#include "core/base/system.h"
|
||||||
#include "core/base/message.h"
|
#include "core/base/message.h"
|
||||||
|
|
||||||
|
bool no_border = false;
|
||||||
|
|
||||||
bool utilWritePNGFile(const char* fileName, int w, int h, uint8_t* pix) {
|
bool utilWritePNGFile(const char* fileName, int w, int h, uint8_t* pix) {
|
||||||
static constexpr size_t kNumChannels = 3;
|
static constexpr size_t kNumChannels = 3;
|
||||||
uint8_t* writeBuffer = new uint8_t[w * h * kNumChannels];
|
uint8_t* writeBuffer = new uint8_t[w * h * kNumChannels];
|
||||||
|
@ -20,6 +22,27 @@ bool utilWritePNGFile(const char* fileName, int w, int h, uint8_t* pix) {
|
||||||
int sizeY = h;
|
int sizeY = h;
|
||||||
|
|
||||||
switch (systemColorDepth) {
|
switch (systemColorDepth) {
|
||||||
|
case 8: {
|
||||||
|
uint8_t* pixU8 = (uint8_t*)pix + (w);
|
||||||
|
for (int y = 0; y < sizeY; y++) {
|
||||||
|
for (int x = 0; x < sizeX; x++, pixU8++) {
|
||||||
|
// White color fix
|
||||||
|
if (*pixU8 == 0xff) {
|
||||||
|
*b++ = 0xff;
|
||||||
|
*b++ = 0xff;
|
||||||
|
*b++ = 0xff;
|
||||||
|
} else {
|
||||||
|
*b++ = (((*pixU8 >> 5) & 0x7) << 5);
|
||||||
|
*b++ = (((*pixU8 >> 2) & 0x7) << 5);
|
||||||
|
*b++ = ((*pixU8 & 0x3) << 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (no_border == false) {
|
||||||
|
pixU8 += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
case 16: {
|
case 16: {
|
||||||
uint16_t* p = (uint16_t*)(pix + (w + 2) * 2); // skip first black line
|
uint16_t* p = (uint16_t*)(pix + (w + 2) * 2); // skip first black line
|
||||||
for (int y = 0; y < sizeY; y++) {
|
for (int y = 0; y < sizeY; y++) {
|
||||||
|
@ -125,6 +148,40 @@ bool utilWriteBMPFile(const char* fileName, int w, int h, uint8_t* pix) {
|
||||||
int sizeY = h;
|
int sizeY = h;
|
||||||
|
|
||||||
switch (systemColorDepth) {
|
switch (systemColorDepth) {
|
||||||
|
case 8: {
|
||||||
|
uint8_t* pixU8 = 0;
|
||||||
|
if (no_border == false) {
|
||||||
|
pixU8 = (uint8_t*)pix + ((w + 2) * (h));
|
||||||
|
} else {
|
||||||
|
pixU8 = (uint8_t*)pix + ((w) * (h));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int y = 0; y < sizeY; y++) {
|
||||||
|
for (int x = 0; x < sizeX; x++, pixU8++) {
|
||||||
|
// White color fix
|
||||||
|
if (*pixU8 == 0xff) {
|
||||||
|
*b++ = 0xff;
|
||||||
|
*b++ = 0xff;
|
||||||
|
*b++ = 0xff;
|
||||||
|
} else {
|
||||||
|
*b++ = ((*pixU8 & 0x3) << 6);
|
||||||
|
*b++ = (((*pixU8 >> 2) & 0x7) << 5);
|
||||||
|
*b++ = (((*pixU8 >> 5) & 0x7) << 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (no_border == false) {
|
||||||
|
pixU8++;
|
||||||
|
pixU8++;
|
||||||
|
pixU8 -= 2 * (w + 2);
|
||||||
|
} else {
|
||||||
|
pixU8 -= 2 * (w);
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite(writeBuffer, 1, 3 * w, fp);
|
||||||
|
b = writeBuffer;
|
||||||
|
}
|
||||||
|
} break;
|
||||||
case 16: {
|
case 16: {
|
||||||
uint16_t* p = (uint16_t*)(pix + (w + 2) * (h) * 2); // skip first black line
|
uint16_t* p = (uint16_t*)(pix + (w + 2) * (h) * 2); // skip first black line
|
||||||
for (int y = 0; y < sizeY; y++) {
|
for (int y = 0; y < sizeY; y++) {
|
||||||
|
|
|
@ -10,4 +10,6 @@
|
||||||
bool utilWritePNGFile(const char*, int, int, uint8_t*);
|
bool utilWritePNGFile(const char*, int, int, uint8_t*);
|
||||||
bool utilWriteBMPFile(const char*, int, int, uint8_t*);
|
bool utilWriteBMPFile(const char*, int, int, uint8_t*);
|
||||||
|
|
||||||
|
extern bool no_border;
|
||||||
|
|
||||||
#endif // VBAM_CORE_BASE_IMAGE_UTIL_H_
|
#endif // VBAM_CORE_BASE_IMAGE_UTIL_H_
|
|
@ -20,6 +20,10 @@
|
||||||
|
|
||||||
#include "core/base/internal/memgzio.h"
|
#include "core/base/internal/memgzio.h"
|
||||||
|
|
||||||
|
#if __STDC_WANT_SECURE_LIB__
|
||||||
|
#define vsnprintf vsprintf_s
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef local
|
#ifndef local
|
||||||
#define local static
|
#define local static
|
||||||
#endif
|
#endif
|
||||||
|
@ -213,7 +217,7 @@ local int memPrintf(MEMFILE *f, const char *format, ...)
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
va_start(list, format);
|
va_start(list, format);
|
||||||
len = vsprintf(buffer, format, list);
|
len = vsnprintf(buffer, sizeof(buffer), format, list);
|
||||||
va_end(list);
|
va_end(list);
|
||||||
|
|
||||||
return (int)memWrite(buffer, 1, len, f);
|
return (int)memWrite(buffer, 1, len, f);
|
||||||
|
|
|
@ -110,6 +110,7 @@ extern void systemFrame();
|
||||||
extern void systemGbBorderOn();
|
extern void systemGbBorderOn();
|
||||||
extern void (*dbgOutput)(const char* s, uint32_t addr);
|
extern void (*dbgOutput)(const char* s, uint32_t addr);
|
||||||
extern void (*dbgSignal)(int sig, int number);
|
extern void (*dbgSignal)(int sig, int number);
|
||||||
|
extern uint8_t systemColorMap8[0x10000];
|
||||||
extern uint16_t systemColorMap16[0x10000];
|
extern uint16_t systemColorMap16[0x10000];
|
||||||
extern uint32_t systemColorMap32[0x10000];
|
extern uint32_t systemColorMap32[0x10000];
|
||||||
extern uint16_t systemGbPalette[24];
|
extern uint16_t systemGbPalette[24];
|
||||||
|
|
|
@ -3887,6 +3887,41 @@ int gbGetNextEvent(int _clockTicks)
|
||||||
void gbDrawLine()
|
void gbDrawLine()
|
||||||
{
|
{
|
||||||
switch (systemColorDepth) {
|
switch (systemColorDepth) {
|
||||||
|
case 8: {
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
uint8_t* dest = (uint8_t*)g_pix + gbBorderLineSkip * (register_LY + gbBorderRowSkip)
|
||||||
|
+ gbBorderColumnSkip;
|
||||||
|
#else
|
||||||
|
uint8_t* dest = (uint8_t*)g_pix + (gbBorderLineSkip + 2) * (register_LY + gbBorderRowSkip + 1)
|
||||||
|
+ gbBorderColumnSkip;
|
||||||
|
#endif
|
||||||
|
for (size_t x = 0; x < kGBWidth;) {
|
||||||
|
*dest++ = systemColorMap8[gbLineMix[x++]];
|
||||||
|
*dest++ = systemColorMap8[gbLineMix[x++]];
|
||||||
|
*dest++ = systemColorMap8[gbLineMix[x++]];
|
||||||
|
*dest++ = systemColorMap8[gbLineMix[x++]];
|
||||||
|
|
||||||
|
*dest++ = systemColorMap8[gbLineMix[x++]];
|
||||||
|
*dest++ = systemColorMap8[gbLineMix[x++]];
|
||||||
|
*dest++ = systemColorMap8[gbLineMix[x++]];
|
||||||
|
*dest++ = systemColorMap8[gbLineMix[x++]];
|
||||||
|
|
||||||
|
*dest++ = systemColorMap8[gbLineMix[x++]];
|
||||||
|
*dest++ = systemColorMap8[gbLineMix[x++]];
|
||||||
|
*dest++ = systemColorMap8[gbLineMix[x++]];
|
||||||
|
*dest++ = systemColorMap8[gbLineMix[x++]];
|
||||||
|
|
||||||
|
*dest++ = systemColorMap8[gbLineMix[x++]];
|
||||||
|
*dest++ = systemColorMap8[gbLineMix[x++]];
|
||||||
|
*dest++ = systemColorMap8[gbLineMix[x++]];
|
||||||
|
*dest++ = systemColorMap8[gbLineMix[x++]];
|
||||||
|
}
|
||||||
|
if (gbBorderOn)
|
||||||
|
dest += gbBorderColumnSkip;
|
||||||
|
#ifndef __LIBRETRO__
|
||||||
|
*dest++ = 0; // for filters that read one pixel more
|
||||||
|
#endif
|
||||||
|
} break;
|
||||||
case 16: {
|
case 16: {
|
||||||
#ifdef __LIBRETRO__
|
#ifdef __LIBRETRO__
|
||||||
uint16_t* dest = (uint16_t*)g_pix + gbBorderLineSkip * (register_LY + gbBorderRowSkip)
|
uint16_t* dest = (uint16_t*)g_pix + gbBorderLineSkip * (register_LY + gbBorderRowSkip)
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
|
|
||||||
#include "core/gb/gbGlobals.h"
|
#include "core/gb/gbGlobals.h"
|
||||||
|
|
||||||
|
#if __STDC_WANT_SECURE_LIB__
|
||||||
|
#define snprintf sprintf_s
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t mask;
|
uint8_t mask;
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
|
@ -132,12 +136,12 @@ static char* addStr(char* p, const char* s)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
int gbDis(char* buffer, uint16_t address)
|
int gbDis(char* buffer, int buflen, uint16_t address)
|
||||||
{
|
{
|
||||||
char* p = buffer;
|
char* p = buffer;
|
||||||
uint16_t instr = 1;
|
uint16_t instr = 1;
|
||||||
uint16_t addr = address;
|
uint16_t addr = address;
|
||||||
sprintf(p, "%04x ", address);
|
snprintf(p, buflen, "%04x ", address);
|
||||||
p += 12;
|
p += 12;
|
||||||
|
|
||||||
uint8_t opcode = GB_READ(address);
|
uint8_t opcode = GB_READ(address);
|
||||||
|
@ -183,7 +187,7 @@ int gbDis(char* buffer, uint16_t address)
|
||||||
disp = GB_READ(address);
|
disp = GB_READ(address);
|
||||||
if (disp >= 0)
|
if (disp >= 0)
|
||||||
*p++ = '+';
|
*p++ = '+';
|
||||||
p += sprintf(p, "%d", disp);
|
p += snprintf(p, buflen, "%d", disp);
|
||||||
instr++;
|
instr++;
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
|
|
|
@ -3,6 +3,6 @@
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
int gbDis(char*, uint16_t);
|
int gbDis(char* buffer, int buflen, uint16_t address);
|
||||||
|
|
||||||
#endif // VBAM_CORE_GB_GBDIS_H_
|
#endif // VBAM_CORE_GB_GBDIS_H_
|
||||||
|
|
|
@ -54,6 +54,11 @@ inline void gbSgbDraw16Bit(uint16_t* p, uint16_t v)
|
||||||
*p = systemColorMap16[v];
|
*p = systemColorMap16[v];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void gbSgbDraw8Bit(uint8_t* p, uint16_t v)
|
||||||
|
{
|
||||||
|
*p = systemColorMap8[v];
|
||||||
|
}
|
||||||
|
|
||||||
void gbSgbReset()
|
void gbSgbReset()
|
||||||
{
|
{
|
||||||
gbSgbPacketTimeout = 0;
|
gbSgbPacketTimeout = 0;
|
||||||
|
@ -112,6 +117,18 @@ void gbSgbShutdown()
|
||||||
void gbSgbFillScreen(uint16_t color)
|
void gbSgbFillScreen(uint16_t color)
|
||||||
{
|
{
|
||||||
switch (systemColorDepth) {
|
switch (systemColorDepth) {
|
||||||
|
case 8: {
|
||||||
|
for (int y = 0; y < 144; y++) {
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
int yLine = (y + gbBorderRowSkip) * gbBorderLineSkip + gbBorderColumnSkip;
|
||||||
|
#else
|
||||||
|
int yLine = (y + gbBorderRowSkip + 1) * (gbBorderLineSkip + 2) + gbBorderColumnSkip;
|
||||||
|
#endif
|
||||||
|
uint8_t* dest = (uint8_t*)g_pix + yLine;
|
||||||
|
for (int x = 0; x < 160; x++)
|
||||||
|
gbSgbDraw8Bit(dest++, color);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
case 16: {
|
case 16: {
|
||||||
for (int y = 0; y < 144; y++) {
|
for (int y = 0; y < 144; y++) {
|
||||||
#ifdef __LIBRETRO__
|
#ifdef __LIBRETRO__
|
||||||
|
@ -198,7 +215,7 @@ void gbSgbDrawBorderTile(int x, int y, int tile, int attr)
|
||||||
uint32_t* dest32 = (uint32_t*)g_pix + ((y + 1) * (256 + 1)) + x;
|
uint32_t* dest32 = (uint32_t*)g_pix + ((y + 1) * (256 + 1)) + x;
|
||||||
#endif
|
#endif
|
||||||
uint8_t* dest8 = (uint8_t*)g_pix + ((y * 256) + x) * 3;
|
uint8_t* dest8 = (uint8_t*)g_pix + ((y * 256) + x) * 3;
|
||||||
|
uint8_t* dest8b = (uint8_t*)g_pix + ((y * 256) + x);
|
||||||
uint8_t* tileAddress = &gbSgbBorderChar[tile * 32];
|
uint8_t* tileAddress = &gbSgbBorderChar[tile * 32];
|
||||||
uint8_t* tileAddress2 = &gbSgbBorderChar[tile * 32 + 16];
|
uint8_t* tileAddress2 = &gbSgbBorderChar[tile * 32 + 16];
|
||||||
|
|
||||||
|
@ -258,6 +275,12 @@ void gbSgbDrawBorderTile(int x, int y, int tile, int attr)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (systemColorDepth) {
|
switch (systemColorDepth) {
|
||||||
|
case 8:
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
gbSgbDraw8Bit(dest8b + yyy * 256 + xxx, cc);
|
||||||
|
#else
|
||||||
|
gbSgbDraw8Bit(dest8b + yyy * (256 + 2) + xxx, cc);
|
||||||
|
#endif
|
||||||
case 16:
|
case 16:
|
||||||
#ifdef __LIBRETRO__
|
#ifdef __LIBRETRO__
|
||||||
gbSgbDraw16Bit(dest + yyy * 256 + xxx, cc);
|
gbSgbDraw16Bit(dest + yyy * 256 + xxx, cc);
|
||||||
|
|
|
@ -3958,6 +3958,38 @@ void CPULoop(int ticks)
|
||||||
if (frameCount >= framesToSkip) {
|
if (frameCount >= framesToSkip) {
|
||||||
(*renderLine)();
|
(*renderLine)();
|
||||||
switch (systemColorDepth) {
|
switch (systemColorDepth) {
|
||||||
|
case 8: {
|
||||||
|
#ifdef __LIBRETRO__
|
||||||
|
uint8_t* dest = (uint8_t*)g_pix + 240 * VCOUNT;
|
||||||
|
#else
|
||||||
|
uint8_t* dest = (uint8_t*)g_pix + 242 * (VCOUNT + 1);
|
||||||
|
#endif
|
||||||
|
for (int x = 0; x < 240;) {
|
||||||
|
*dest++ = systemColorMap8[g_lineMix[x++] & 0xFFFF];
|
||||||
|
*dest++ = systemColorMap8[g_lineMix[x++] & 0xFFFF];
|
||||||
|
*dest++ = systemColorMap8[g_lineMix[x++] & 0xFFFF];
|
||||||
|
*dest++ = systemColorMap8[g_lineMix[x++] & 0xFFFF];
|
||||||
|
|
||||||
|
*dest++ = systemColorMap8[g_lineMix[x++] & 0xFFFF];
|
||||||
|
*dest++ = systemColorMap8[g_lineMix[x++] & 0xFFFF];
|
||||||
|
*dest++ = systemColorMap8[g_lineMix[x++] & 0xFFFF];
|
||||||
|
*dest++ = systemColorMap8[g_lineMix[x++] & 0xFFFF];
|
||||||
|
|
||||||
|
*dest++ = systemColorMap8[g_lineMix[x++] & 0xFFFF];
|
||||||
|
*dest++ = systemColorMap8[g_lineMix[x++] & 0xFFFF];
|
||||||
|
*dest++ = systemColorMap8[g_lineMix[x++] & 0xFFFF];
|
||||||
|
*dest++ = systemColorMap8[g_lineMix[x++] & 0xFFFF];
|
||||||
|
|
||||||
|
*dest++ = systemColorMap8[g_lineMix[x++] & 0xFFFF];
|
||||||
|
*dest++ = systemColorMap8[g_lineMix[x++] & 0xFFFF];
|
||||||
|
*dest++ = systemColorMap8[g_lineMix[x++] & 0xFFFF];
|
||||||
|
*dest++ = systemColorMap8[g_lineMix[x++] & 0xFFFF];
|
||||||
|
}
|
||||||
|
// for filters that read past the screen
|
||||||
|
#ifndef __LIBRETRO__
|
||||||
|
*dest++ = 0;
|
||||||
|
#endif
|
||||||
|
} break;
|
||||||
case 16: {
|
case 16: {
|
||||||
#ifdef __LIBRETRO__
|
#ifdef __LIBRETRO__
|
||||||
uint16_t* dest = (uint16_t*)g_pix + 240 * VCOUNT;
|
uint16_t* dest = (uint16_t*)g_pix + 240 * VCOUNT;
|
||||||
|
|
|
@ -9,6 +9,10 @@
|
||||||
#include "core/gba/gbaInline.h"
|
#include "core/gba/gbaInline.h"
|
||||||
#include "core/gba/gbaGlobals.h"
|
#include "core/gba/gbaGlobals.h"
|
||||||
|
|
||||||
|
#if __STDC_WANT_SECURE_LIB__
|
||||||
|
#define snprintf sprintf_s
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gameshark code types: (based on AR v1.0)
|
* Gameshark code types: (based on AR v1.0)
|
||||||
*
|
*
|
||||||
|
@ -2615,15 +2619,15 @@ void cheatsReadGame(gzFile file, int version)
|
||||||
if (!cheatsList[i].codestring[0]) {
|
if (!cheatsList[i].codestring[0]) {
|
||||||
switch (cheatsList[i].size) {
|
switch (cheatsList[i].size) {
|
||||||
case 0:
|
case 0:
|
||||||
sprintf(cheatsList[i].codestring, "%08x:%02x", cheatsList[i].address,
|
snprintf(cheatsList[i].codestring, sizeof(cheatsList[i].codestring), "%08x:%02x", cheatsList[i].address,
|
||||||
cheatsList[i].value);
|
cheatsList[i].value);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
sprintf(cheatsList[i].codestring, "%08x:%04x", cheatsList[i].address,
|
snprintf(cheatsList[i].codestring, sizeof(cheatsList[i].codestring), "%08x:%04x", cheatsList[i].address,
|
||||||
cheatsList[i].value);
|
cheatsList[i].value);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
sprintf(cheatsList[i].codestring, "%08x:%08x", cheatsList[i].address,
|
snprintf(cheatsList[i].codestring, sizeof(cheatsList[i].codestring), "%08x:%08x", cheatsList[i].address,
|
||||||
cheatsList[i].value);
|
cheatsList[i].value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2759,15 +2763,15 @@ bool cheatsLoadCheatList(const char* file)
|
||||||
if (!cheatsList[i].codestring[0]) {
|
if (!cheatsList[i].codestring[0]) {
|
||||||
switch (cheatsList[i].size) {
|
switch (cheatsList[i].size) {
|
||||||
case 0:
|
case 0:
|
||||||
sprintf(cheatsList[i].codestring, "%08x:%02x", cheatsList[i].address,
|
snprintf(cheatsList[i].codestring, sizeof(cheatsList[i].codestring), "%08x:%02x", cheatsList[i].address,
|
||||||
cheatsList[i].value);
|
cheatsList[i].value);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
sprintf(cheatsList[i].codestring, "%08x:%04x", cheatsList[i].address,
|
snprintf(cheatsList[i].codestring, sizeof(cheatsList[i].codestring), "%08x:%04x", cheatsList[i].address,
|
||||||
cheatsList[i].value);
|
cheatsList[i].value);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
sprintf(cheatsList[i].codestring, "%08x:%08x", cheatsList[i].address,
|
snprintf(cheatsList[i].codestring, sizeof(cheatsList[i].codestring), "%08x:%08x", cheatsList[i].address,
|
||||||
cheatsList[i].value);
|
cheatsList[i].value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,8 +38,12 @@
|
||||||
#include "core/gba/internal/gbaSockClient.h"
|
#include "core/gba/internal/gbaSockClient.h"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
#if __STDC_WANT_SECURE_LIB__
|
||||||
|
#define snprintf sprintf_s
|
||||||
|
#else
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef UPDATE_REG
|
#ifdef UPDATE_REG
|
||||||
#undef UPDATE_REG
|
#undef UPDATE_REG
|
||||||
|
@ -58,9 +62,9 @@ const char* MakeInstanceFilename(const char* Input)
|
||||||
free(result);
|
free(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = (char*)malloc(strlen(Input) + 3);
|
result = (char*)malloc(strlen(Input) + 4);
|
||||||
char* p = strrchr((char*)Input, '.');
|
char* p = strrchr((char*)Input, '.');
|
||||||
sprintf(result, "%.*s-%d.%s", (int)(p - Input), Input, vbaid + 1, p + 1);
|
snprintf(result, strlen(Input) + 3, "%.*s-%d.%s", (int)(p - Input), Input, vbaid + 1, p + 1);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -852,7 +856,7 @@ void CableServer::Recv(void)
|
||||||
}
|
}
|
||||||
if (inbuffer[1] == -32) {
|
if (inbuffer[1] == -32) {
|
||||||
char message[30];
|
char message[30];
|
||||||
sprintf(message, _("Player %d disconnected."), i + 2);
|
snprintf(message, sizeof(message), _("Player %d disconnected."), i + 2);
|
||||||
systemScreenMessage(message);
|
systemScreenMessage(message);
|
||||||
outbuffer[0] = 4;
|
outbuffer[0] = 4;
|
||||||
outbuffer[1] = -32;
|
outbuffer[1] = -32;
|
||||||
|
@ -916,7 +920,7 @@ bool CableServer::RecvGB(void)
|
||||||
|
|
||||||
if (inbuffer[1] == -32) {
|
if (inbuffer[1] == -32) {
|
||||||
char message[30];
|
char message[30];
|
||||||
sprintf(message, _("Player %d disconnected."), i + 2);
|
snprintf(message, sizeof(message), _("Player %d disconnected."), i + 2);
|
||||||
systemScreenMessage(message);
|
systemScreenMessage(message);
|
||||||
for (i = 1; i < lanlink.numslaves; i++) {
|
for (i = 1; i < lanlink.numslaves; i++) {
|
||||||
tcpsocket[i].disconnect();
|
tcpsocket[i].disconnect();
|
||||||
|
@ -1570,7 +1574,7 @@ void RFUServer::Recv(void)
|
||||||
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::Status::Disconnected) {
|
||||||
char message[30];
|
char message[30];
|
||||||
sprintf(message, _("Player %d disconnected."), i + 1);
|
snprintf(message, sizeof(message), _("Player %d disconnected."), i + 1);
|
||||||
systemScreenMessage(message);
|
systemScreenMessage(message);
|
||||||
//tcpsocket[i + 1].disconnect();
|
//tcpsocket[i + 1].disconnect();
|
||||||
//CloseLink();
|
//CloseLink();
|
||||||
|
@ -2902,7 +2906,7 @@ static void UpdateCableIPC(int)
|
||||||
if (f < (1 << transfer_direction) - 1)
|
if (f < (1 << transfer_direction) - 1)
|
||||||
linkmem->numgbas = transfer_direction - 1;
|
linkmem->numgbas = transfer_direction - 1;
|
||||||
char message[30];
|
char message[30];
|
||||||
sprintf(message, _("Player %d disconnected."), transfer_direction - 1);
|
snprintf(message, sizeof(message), _("Player %d disconnected."), transfer_direction - 1);
|
||||||
systemScreenMessage(message);
|
systemScreenMessage(message);
|
||||||
}
|
}
|
||||||
transfer_direction = linkmem->trgbas + 1;
|
transfer_direction = linkmem->trgbas + 1;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -79,6 +79,7 @@ void systemGbBorderOn() {}
|
||||||
void (*dbgOutput)(const char* s, uint32_t addr);
|
void (*dbgOutput)(const char* s, uint32_t addr);
|
||||||
void (*dbgSignal)(int sig, int number);
|
void (*dbgSignal)(int sig, int number);
|
||||||
|
|
||||||
|
uint8_t systemColorMap8[0x10000];
|
||||||
uint16_t systemColorMap16[0x10000];
|
uint16_t systemColorMap16[0x10000];
|
||||||
uint32_t systemColorMap32[0x10000];
|
uint32_t systemColorMap32[0x10000];
|
||||||
uint16_t systemGbPalette[24];
|
uint16_t systemGbPalette[24];
|
||||||
|
|
|
@ -66,7 +66,7 @@ endif
|
||||||
ifneq (,$(findstring unix,$(platform)))
|
ifneq (,$(findstring unix,$(platform)))
|
||||||
TARGET := $(TARGET_NAME)_libretro.so
|
TARGET := $(TARGET_NAME)_libretro.so
|
||||||
fpic := -fPIC
|
fpic := -fPIC
|
||||||
SHARED := -shared -Wl,-version-script=$(LIBRETRO_DIR)/link.T -Wl,-no-undefined
|
SHARED := -shared -Wl,--version-script=$(LIBRETRO_DIR)/link.T -Wl,--no-undefined
|
||||||
TILED_RENDERING=1
|
TILED_RENDERING=1
|
||||||
|
|
||||||
# Classic Platforms ####################
|
# Classic Platforms ####################
|
||||||
|
@ -222,7 +222,7 @@ else ifeq ($(platform), theos_ios)
|
||||||
else ifeq ($(platform), qnx)
|
else ifeq ($(platform), qnx)
|
||||||
TARGET := $(TARGET_NAME)_libretro_$(platform).so
|
TARGET := $(TARGET_NAME)_libretro_$(platform).so
|
||||||
fpic := -fPIC
|
fpic := -fPIC
|
||||||
SHARED := -lcpp -lm -shared -Wl,-version-script=$(LIBRETRO_DIR)/link.T -Wl,-no-undefined
|
SHARED := -lcpp -lm -shared -Wl,-no-undefined
|
||||||
CC = qcc -Vgcc_ntoarmv7le
|
CC = qcc -Vgcc_ntoarmv7le
|
||||||
CXX = QCC -Vgcc_ntoarmv7le_cpp
|
CXX = QCC -Vgcc_ntoarmv7le_cpp
|
||||||
AR = QCC -Vgcc_ntoarmv7le
|
AR = QCC -Vgcc_ntoarmv7le
|
||||||
|
@ -344,7 +344,7 @@ else ifeq ($(platform), switch)
|
||||||
|
|
||||||
else ifneq (,$(findstring armv,$(platform)))
|
else ifneq (,$(findstring armv,$(platform)))
|
||||||
TARGET := $(TARGET_NAME)_libretro.so
|
TARGET := $(TARGET_NAME)_libretro.so
|
||||||
SHARED := -shared -Wl,--no-undefined
|
SHARED := -shared -Wl,--version-script=$(LIBRETRO_DIR)/link.T -Wl,--no-undefined
|
||||||
TILED_RENDERING=1
|
TILED_RENDERING=1
|
||||||
fpic := -fPIC
|
fpic := -fPIC
|
||||||
ifneq (,$(findstring cortexa8,$(platform)))
|
ifneq (,$(findstring cortexa8,$(platform)))
|
||||||
|
@ -533,7 +533,7 @@ else
|
||||||
TARGET := $(TARGET_NAME)_libretro.dll
|
TARGET := $(TARGET_NAME)_libretro.dll
|
||||||
CC ?= gcc
|
CC ?= gcc
|
||||||
CXX ?= g++
|
CXX ?= g++
|
||||||
SHARED := -shared -static-libgcc -static-libstdc++ -Wl,-no-undefined -Wl,-version-script=$(LIBRETRO_DIR)/link.T
|
SHARED := -shared -static-libgcc -static-libstdc++ -Wl,-no-undefined
|
||||||
TILED_RENDERING=1
|
TILED_RENDERING=1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,11 @@
|
||||||
#include "core/gba/gbaRtc.h"
|
#include "core/gba/gbaRtc.h"
|
||||||
#include "core/gba/gbaSound.h"
|
#include "core/gba/gbaSound.h"
|
||||||
|
|
||||||
|
#if __STDC_WANT_SECURE_LIB__
|
||||||
|
#define snprintf sprintf_s
|
||||||
|
#define vsnprintf vsprintf_s
|
||||||
|
#endif
|
||||||
|
|
||||||
#define FRAMERATE (16777216.0 / 280896.0) // 59.73
|
#define FRAMERATE (16777216.0 / 280896.0) // 59.73
|
||||||
#define SAMPLERATE 32768.0
|
#define SAMPLERATE 32768.0
|
||||||
|
|
||||||
|
@ -68,6 +73,7 @@ static IMAGE_TYPE type = IMAGE_UNKNOWN;
|
||||||
static bool libretro_supports_bitmasks = false;
|
static bool libretro_supports_bitmasks = false;
|
||||||
|
|
||||||
// global vars
|
// global vars
|
||||||
|
uint8_t systemColorMap8[0x10000];
|
||||||
uint16_t systemColorMap16[0x10000];
|
uint16_t systemColorMap16[0x10000];
|
||||||
uint32_t systemColorMap32[0x10000];
|
uint32_t systemColorMap32[0x10000];
|
||||||
int RGB_LOW_BITS_MASK = 0x821; // used for 16bit inter-frame filters
|
int RGB_LOW_BITS_MASK = 0x821; // used for 16bit inter-frame filters
|
||||||
|
@ -1526,7 +1532,7 @@ void retro_cheat_set(unsigned index, bool enabled, const char* code)
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
codeLine = (char *)calloc(codeLineSize, sizeof(char));
|
codeLine = (char *)calloc(codeLineSize, sizeof(char));
|
||||||
sprintf(name, "cheat_%d", index);
|
snprintf(name, sizeof(name), "cheat_%d", index);
|
||||||
for (cursor = 0;; cursor++) {
|
for (cursor = 0;; cursor++) {
|
||||||
if (ISHEXDEC) {
|
if (ISHEXDEC) {
|
||||||
codeLine[codePos++] = toupper(code[cursor]);
|
codeLine[codePos++] = toupper(code[cursor]);
|
||||||
|
@ -1791,7 +1797,7 @@ void systemMessage(const char* fmt, ...)
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vsprintf(buffer, fmt, ap);
|
vsnprintf(buffer, sizeof(buffer), fmt, ap);
|
||||||
if (log_cb)
|
if (log_cb)
|
||||||
log_cb(RETRO_LOG_INFO, "%s\n", buffer);
|
log_cb(RETRO_LOG_INFO, "%s\n", buffer);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
@ -1802,7 +1808,7 @@ void systemMessage(int, const char* fmt, ...)
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
vsprintf(buffer, fmt, ap);
|
vsnprintf(buffer, sizeof(buffer), fmt, ap);
|
||||||
if (log_cb)
|
if (log_cb)
|
||||||
log_cb(RETRO_LOG_INFO, "%s\n", buffer);
|
log_cb(RETRO_LOG_INFO, "%s\n", buffer);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
global: retro_*;
|
||||||
|
local: *;
|
||||||
|
};
|
||||||
|
|
|
@ -40,9 +40,15 @@ if(ENABLE_LIRC)
|
||||||
set(LIRC_CLIENT_LIBRARY lirc_client)
|
set(LIRC_CLIENT_LIBRARY lirc_client)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_include_directories(vbam
|
if(ENABLE_SDL3)
|
||||||
PRIVATE ${SDL2_INCLUDE_DIRS}
|
target_include_directories(vbam
|
||||||
)
|
PRIVATE ${SDL3_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
target_include_directories(vbam
|
||||||
|
PRIVATE ${SDL2_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
target_link_libraries(vbam
|
target_link_libraries(vbam
|
||||||
vbam-core
|
vbam-core
|
||||||
|
@ -52,12 +58,16 @@ target_link_libraries(vbam
|
||||||
vbam-components-filters-interframe
|
vbam-components-filters-interframe
|
||||||
vbam-components-user-config
|
vbam-components-user-config
|
||||||
${OPENGL_LIBRARIES}
|
${OPENGL_LIBRARIES}
|
||||||
${VBAM_SDL2_LIBS}
|
${VBAM_SDL_LIBS}
|
||||||
nonstd-lib
|
nonstd-lib
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_link_libraries(vbam ${SDL2_LIBRARY} ${SDL2MAIN_LIBRARY})
|
if(ENABLE_SDL3)
|
||||||
|
target_link_libraries(vbam ${SDL3_LIBRARY})
|
||||||
|
else()
|
||||||
|
target_link_libraries(vbam ${SDL2_LIBRARY} ${SDL2MAIN_LIBRARY})
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_LIRC)
|
if(ENABLE_LIRC)
|
||||||
|
@ -66,7 +76,7 @@ if(ENABLE_LIRC)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_link_libraries(vbam wsock32 ws2_32 winmm version imm32 ${SDL2MAIN_LIBRARY})
|
target_link_libraries(vbam wsock32 ws2_32 winmm version imm32)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Installation scripts.
|
# Installation scripts.
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
|
||||||
|
#if __STDC_WANT_SECURE_LIB__
|
||||||
|
#define snprintf sprintf_s
|
||||||
|
#endif
|
||||||
|
|
||||||
#define getcwd _getcwd
|
#define getcwd _getcwd
|
||||||
#define stat _stat
|
#define stat _stat
|
||||||
#define mkdir(X,Y) (_mkdir(X))
|
#define mkdir(X,Y) (_mkdir(X))
|
||||||
|
@ -138,6 +142,8 @@ int rewindTimer = 0;
|
||||||
int showSpeed;
|
int showSpeed;
|
||||||
int showSpeedTransparent;
|
int showSpeedTransparent;
|
||||||
|
|
||||||
|
int userColorDepth = 0;
|
||||||
|
|
||||||
const char* preparedCheatCodes[MAX_CHEATS];
|
const char* preparedCheatCodes[MAX_CHEATS];
|
||||||
|
|
||||||
// allow up to 100 IPS/UPS/PPF patches given on commandline
|
// allow up to 100 IPS/UPS/PPF patches given on commandline
|
||||||
|
@ -168,6 +174,7 @@ struct option argOptions[] = {
|
||||||
{ "capture-format", required_argument, 0, OPT_CAPTURE_FORMAT },
|
{ "capture-format", required_argument, 0, OPT_CAPTURE_FORMAT },
|
||||||
{ "cheat", required_argument, 0, OPT_CHEAT },
|
{ "cheat", required_argument, 0, OPT_CHEAT },
|
||||||
{ "cheats-enabled", no_argument, &coreOptions.cheatsEnabled, 1 },
|
{ "cheats-enabled", no_argument, &coreOptions.cheatsEnabled, 1 },
|
||||||
|
{ "color-depth", required_argument, 0, 'z'},
|
||||||
{ "color-option", no_argument, 0, OPT_GB_COLOR_OPTION },
|
{ "color-option", no_argument, 0, OPT_GB_COLOR_OPTION },
|
||||||
{ "config", required_argument, 0, 'c' },
|
{ "config", required_argument, 0, 'c' },
|
||||||
{ "cpu-disable-sfx", no_argument, &coreOptions.cpuDisableSfx, 1 },
|
{ "cpu-disable-sfx", no_argument, &coreOptions.cpuDisableSfx, 1 },
|
||||||
|
@ -457,7 +464,7 @@ const char* FindConfigFile(const char *name)
|
||||||
mkdir(fullDir, 0755);
|
mkdir(fullDir, 0755);
|
||||||
|
|
||||||
if (fullDir) {
|
if (fullDir) {
|
||||||
sprintf(path, "%s%c%s", fullDir, kFileSep, name);
|
snprintf(path, sizeof(path), "%s%c%s", fullDir, kFileSep, name);
|
||||||
if (FileExists(path))
|
if (FileExists(path))
|
||||||
{
|
{
|
||||||
return path;
|
return path;
|
||||||
|
@ -467,7 +474,7 @@ const char* FindConfigFile(const char *name)
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
char *home = getenv("USERPROFILE");
|
char *home = getenv("USERPROFILE");
|
||||||
if (home != NULL) {
|
if (home != NULL) {
|
||||||
sprintf(path, "%s%c%s", home, kFileSep, name);
|
snprintf(path, "%s%c%s", home, kFileSep, name);
|
||||||
if (FileExists(path))
|
if (FileExists(path))
|
||||||
{
|
{
|
||||||
return path;
|
return path;
|
||||||
|
@ -484,10 +491,10 @@ const char* FindConfigFile(const char *name)
|
||||||
char *tok = strtok(buffer, PATH_SEP);
|
char *tok = strtok(buffer, PATH_SEP);
|
||||||
|
|
||||||
while (tok) {
|
while (tok) {
|
||||||
sprintf(env_path, "%s%c%s", tok, kFileSep, EXE_NAME);
|
snprintf(env_path, 4096, "%s%c%s", tok, kFileSep, EXE_NAME);
|
||||||
if (FileExists(env_path)) {
|
if (FileExists(env_path)) {
|
||||||
static char path2[2048];
|
static char path2[2048];
|
||||||
sprintf(path2, "%s%c%s", tok, kFileSep, name);
|
snprintf(path2, sizeof(path2), "%s%c%s", tok, kFileSep, name);
|
||||||
if (FileExists(path2)) {
|
if (FileExists(path2)) {
|
||||||
return path2;
|
return path2;
|
||||||
}
|
}
|
||||||
|
@ -502,7 +509,7 @@ const char* FindConfigFile(const char *name)
|
||||||
char *p = strrchr(buffer, kFileSep);
|
char *p = strrchr(buffer, kFileSep);
|
||||||
if (p) {
|
if (p) {
|
||||||
*p = 0;
|
*p = 0;
|
||||||
sprintf(path, "%s%c%s", buffer, kFileSep, name);
|
snprintf(path, sizeof(path), "%s%c%s", buffer, kFileSep, name);
|
||||||
if (FileExists(path))
|
if (FileExists(path))
|
||||||
{
|
{
|
||||||
return path;
|
return path;
|
||||||
|
@ -510,13 +517,13 @@ const char* FindConfigFile(const char *name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else // ! _WIN32
|
#else // ! _WIN32
|
||||||
sprintf(path, "%s%c%s", PKGDATADIR, kFileSep, name);
|
snprintf(path, sizeof(path), "%s%c%s", PKGDATADIR, kFileSep, name);
|
||||||
if (FileExists(path))
|
if (FileExists(path))
|
||||||
{
|
{
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(path, "%s%c%s", SYSCONF_INSTALL_DIR, kFileSep, name);
|
snprintf(path, sizeof(path), "%s%c%s", SYSCONF_INSTALL_DIR, kFileSep, name);
|
||||||
if (FileExists(path))
|
if (FileExists(path))
|
||||||
{
|
{
|
||||||
return path;
|
return path;
|
||||||
|
@ -745,6 +752,20 @@ int ReadOpts(int argc, char ** argv)
|
||||||
case 'F':
|
case 'F':
|
||||||
fullScreen = 1;
|
fullScreen = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'z':
|
||||||
|
if (optarg != NULL) {
|
||||||
|
userColorDepth = atoi(optarg);
|
||||||
|
|
||||||
|
if ((userColorDepth != 8) && (userColorDepth != 16) && (userColorDepth != 24) && (userColorDepth != 32)) {
|
||||||
|
fprintf(stderr, "Wrong color depth (%d bit)\n", userColorDepth);
|
||||||
|
userColorDepth = 0;
|
||||||
|
} else {
|
||||||
|
log("Set color depth to %d bit\n", userColorDepth);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
userColorDepth = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
if (optarg) {
|
if (optarg) {
|
||||||
filter = (Filter)atoi(optarg);
|
filter = (Filter)atoi(optarg);
|
||||||
|
|
823
src/sdl/SDL.cpp
823
src/sdl/SDL.cpp
File diff suppressed because it is too large
Load Diff
|
@ -20,7 +20,9 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
#include <SDL_events.h>
|
#include <SDL_events.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "core/gba/gbaGlobals.h"
|
#include "core/gba/gbaGlobals.h"
|
||||||
#include "core/gba/gbaSound.h"
|
#include "core/gba/gbaSound.h"
|
||||||
|
@ -37,9 +39,23 @@ SoundSDL::SoundSDL():
|
||||||
initialized(false)
|
initialized(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
void SoundSDL::soundCallback(void* data, uint8_t* stream, int len) {
|
void SoundSDL::soundCallback(void* data, uint8_t* stream, int len) {
|
||||||
reinterpret_cast<SoundSDL*>(data)->read(reinterpret_cast<uint16_t*>(stream), len);
|
reinterpret_cast<SoundSDL*>(data)->read(reinterpret_cast<uint16_t*>(stream), len);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
void SoundSDL::soundCallback(void* data, SDL_AudioStream *stream, int additional_length, int length) {
|
||||||
|
uint16_t streamdata[8192];
|
||||||
|
(void)additional_length;
|
||||||
|
|
||||||
|
while (length > 0)
|
||||||
|
{
|
||||||
|
reinterpret_cast<SoundSDL*>(data)->read(reinterpret_cast<uint16_t*>(streamdata), length > sizeof(streamdata) ? sizeof(streamdata) : length);
|
||||||
|
SDL_PutAudioStreamData(stream, streamdata, length > sizeof(streamdata) ? sizeof(streamdata) : length);
|
||||||
|
length -= sizeof(streamdata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool SoundSDL::should_wait() {
|
bool SoundSDL::should_wait() {
|
||||||
return emulating && !coreOptions.speedup && current_rate && !gba_joybus_active;
|
return emulating && !coreOptions.speedup && current_rate && !gba_joybus_active;
|
||||||
|
@ -65,7 +81,11 @@ void SoundSDL::read(uint16_t* stream, int length) {
|
||||||
|
|
||||||
if (!buffer_size()) {
|
if (!buffer_size()) {
|
||||||
if (should_wait())
|
if (should_wait())
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
SDL_SemWait(data_available);
|
SDL_SemWait(data_available);
|
||||||
|
#else
|
||||||
|
SDL_WaitSemaphore(data_available);
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +96,11 @@ void SoundSDL::read(uint16_t* stream, int length) {
|
||||||
|
|
||||||
SDL_UnlockMutex(mutex);
|
SDL_UnlockMutex(mutex);
|
||||||
|
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
SDL_SemPost(data_read);
|
SDL_SemPost(data_read);
|
||||||
|
#else
|
||||||
|
SDL_SignalSemaphore(data_read);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundSDL::write(uint16_t * finalWave, int length) {
|
void SoundSDL::write(uint16_t * finalWave, int length) {
|
||||||
|
@ -85,8 +109,16 @@ void SoundSDL::write(uint16_t * finalWave, int length) {
|
||||||
|
|
||||||
SDL_LockMutex(mutex);
|
SDL_LockMutex(mutex);
|
||||||
|
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
if (SDL_GetAudioDeviceStatus(sound_device) != SDL_AUDIO_PLAYING)
|
if (SDL_GetAudioDeviceStatus(sound_device) != SDL_AUDIO_PLAYING)
|
||||||
SDL_PauseAudioDevice(sound_device, 0);
|
SDL_PauseAudioDevice(sound_device, 0);
|
||||||
|
#else
|
||||||
|
if (SDL_AudioDevicePaused(sound_device) == true)
|
||||||
|
{
|
||||||
|
SDL_ResumeAudioStreamDevice(sound_stream);
|
||||||
|
SDL_ResumeAudioDevice(sound_device);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
std::size_t samples = length / 4;
|
std::size_t samples = length / 4;
|
||||||
std::size_t avail;
|
std::size_t avail;
|
||||||
|
@ -99,10 +131,18 @@ void SoundSDL::write(uint16_t * finalWave, int length) {
|
||||||
|
|
||||||
SDL_UnlockMutex(mutex);
|
SDL_UnlockMutex(mutex);
|
||||||
|
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
SDL_SemPost(data_available);
|
SDL_SemPost(data_available);
|
||||||
|
#else
|
||||||
|
SDL_SignalSemaphore(data_available);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (should_wait())
|
if (should_wait())
|
||||||
SDL_SemWait(data_read);
|
#ifndef ENABLE_SDL3
|
||||||
|
SDL_SemWait(data_read);
|
||||||
|
#else
|
||||||
|
SDL_WaitSemaphore(data_read);
|
||||||
|
#endif
|
||||||
else
|
else
|
||||||
// Drop the remainder of the audio data
|
// Drop the remainder of the audio data
|
||||||
return;
|
return;
|
||||||
|
@ -125,15 +165,50 @@ bool SoundSDL::init(long sampleRate) {
|
||||||
// for "no throttle" use regular rate, audio is just dropped
|
// for "no throttle" use regular rate, audio is just dropped
|
||||||
audio.freq = current_rate ? static_cast<int>(sampleRate * (current_rate / 100.0)) : sampleRate;
|
audio.freq = current_rate ? static_cast<int>(sampleRate * (current_rate / 100.0)) : sampleRate;
|
||||||
|
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
audio.format = AUDIO_S16SYS;
|
audio.format = AUDIO_S16SYS;
|
||||||
|
#else
|
||||||
|
audio.format = SDL_AUDIO_S16;
|
||||||
|
#endif
|
||||||
|
|
||||||
audio.channels = 2;
|
audio.channels = 2;
|
||||||
|
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
audio.samples = 2048;
|
audio.samples = 2048;
|
||||||
audio.callback = soundCallback;
|
audio.callback = soundCallback;
|
||||||
audio.userdata = this;
|
audio.userdata = this;
|
||||||
|
|
||||||
if (!SDL_WasInit(SDL_INIT_AUDIO)) SDL_Init(SDL_INIT_AUDIO);
|
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
|
||||||
|
#else
|
||||||
|
if (SDL_InitSubSystem(SDL_INIT_AUDIO) == false)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to init audio subsystem: " << SDL_GetError() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
|
if (SDL_WasInit(SDL_INIT_AUDIO) < 0)
|
||||||
|
#else
|
||||||
|
if (SDL_WasInit(SDL_INIT_AUDIO) == false)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
SDL_Init(SDL_INIT_AUDIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
sound_device = SDL_OpenAudioDevice(NULL, 0, &audio, NULL, 0);
|
sound_device = SDL_OpenAudioDevice(NULL, 0, &audio, NULL, 0);
|
||||||
|
#else
|
||||||
|
sound_stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &audio, soundCallback, this);
|
||||||
|
|
||||||
|
if(sound_stream == NULL)
|
||||||
|
{
|
||||||
|
std::cerr << "Failed to open audio stream: " << SDL_GetError() << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sound_device = SDL_GetAudioStreamDevice(sound_stream);
|
||||||
|
#endif
|
||||||
|
|
||||||
if(sound_device == 0) {
|
if(sound_device == 0) {
|
||||||
std::cerr << "Failed to open audio: " << SDL_GetError() << std::endl;
|
std::cerr << "Failed to open audio: " << SDL_GetError() << std::endl;
|
||||||
|
@ -147,7 +222,10 @@ bool SoundSDL::init(long sampleRate) {
|
||||||
data_read = SDL_CreateSemaphore(1);
|
data_read = SDL_CreateSemaphore(1);
|
||||||
|
|
||||||
// turn off audio events because we are not processing them
|
// turn off audio events because we are not processing them
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 4)
|
#if SDL_VERSION_ATLEAST(3, 2, 0)
|
||||||
|
SDL_SetEventEnabled(SDL_EVENT_AUDIO_DEVICE_ADDED, false);
|
||||||
|
SDL_SetEventEnabled(SDL_EVENT_AUDIO_DEVICE_REMOVED, false);
|
||||||
|
#elif SDL_VERSION_ATLEAST(2, 0, 4)
|
||||||
SDL_EventState(SDL_AUDIODEVICEADDED, SDL_IGNORE);
|
SDL_EventState(SDL_AUDIODEVICEADDED, SDL_IGNORE);
|
||||||
SDL_EventState(SDL_AUDIODEVICEREMOVED, SDL_IGNORE);
|
SDL_EventState(SDL_AUDIODEVICEREMOVED, SDL_IGNORE);
|
||||||
#endif
|
#endif
|
||||||
|
@ -164,8 +242,13 @@ void SoundSDL::deinit() {
|
||||||
SDL_LockMutex(mutex);
|
SDL_LockMutex(mutex);
|
||||||
int is_emulating = emulating;
|
int is_emulating = emulating;
|
||||||
emulating = 0;
|
emulating = 0;
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
SDL_SemPost(data_available);
|
SDL_SemPost(data_available);
|
||||||
SDL_SemPost(data_read);
|
SDL_SemPost(data_read);
|
||||||
|
#else
|
||||||
|
SDL_SignalSemaphore(data_available);
|
||||||
|
SDL_SignalSemaphore(data_read);
|
||||||
|
#endif
|
||||||
SDL_UnlockMutex(mutex);
|
SDL_UnlockMutex(mutex);
|
||||||
|
|
||||||
SDL_Delay(100);
|
SDL_Delay(100);
|
||||||
|
|
|
@ -18,7 +18,11 @@
|
||||||
#ifndef VBAM_SDL_AUDIO_SDL_H_
|
#ifndef VBAM_SDL_AUDIO_SDL_H_
|
||||||
#define VBAM_SDL_AUDIO_SDL_H_
|
#define VBAM_SDL_AUDIO_SDL_H_
|
||||||
|
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
#else
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "core/base/ringbuffer.h"
|
#include "core/base/ringbuffer.h"
|
||||||
#include "core/base/sound_driver.h"
|
#include "core/base/sound_driver.h"
|
||||||
|
@ -29,11 +33,16 @@ public:
|
||||||
~SoundSDL() override;
|
~SoundSDL() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void soundCallback(void* data, uint8_t* stream, int length);
|
#ifdef ENABLE_SDL3
|
||||||
void read(uint16_t* stream, int length);
|
static void soundCallback(void* data, SDL_AudioStream *stream, int additional_length, int length);
|
||||||
|
#else
|
||||||
|
static void soundCallback(void* data, uint8_t* stream, int len);
|
||||||
|
#endif
|
||||||
|
|
||||||
bool should_wait();
|
bool should_wait();
|
||||||
std::size_t buffer_size();
|
std::size_t buffer_size();
|
||||||
void deinit();
|
void deinit();
|
||||||
|
void read(uint16_t* stream, int length);
|
||||||
|
|
||||||
// SoundDriver implementation.
|
// SoundDriver implementation.
|
||||||
bool init(long sampleRate) override;
|
bool init(long sampleRate) override;
|
||||||
|
@ -47,9 +56,17 @@ private:
|
||||||
|
|
||||||
SDL_AudioDeviceID sound_device = 0;
|
SDL_AudioDeviceID sound_device = 0;
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
SDL_AudioStream *sound_stream = NULL;
|
||||||
|
SDL_Mutex* mutex;
|
||||||
|
SDL_Semaphore* data_available;
|
||||||
|
SDL_Semaphore* data_read;
|
||||||
|
#else
|
||||||
SDL_mutex* mutex;
|
SDL_mutex* mutex;
|
||||||
SDL_sem* data_available;
|
SDL_semaphore* data_available;
|
||||||
SDL_sem* data_read;
|
SDL_semaphore* data_read;
|
||||||
|
#endif
|
||||||
|
|
||||||
SDL_AudioSpec audio_spec;
|
SDL_AudioSpec audio_spec;
|
||||||
|
|
||||||
unsigned short current_rate;
|
unsigned short current_rate;
|
||||||
|
|
|
@ -30,6 +30,10 @@
|
||||||
#include "core/gba/gbaSound.h"
|
#include "core/gba/gbaSound.h"
|
||||||
#include "sdl/exprNode.h"
|
#include "sdl/exprNode.h"
|
||||||
|
|
||||||
|
#if __STDC_WANT_SECURE_LIB__
|
||||||
|
#define snprintf sprintf_s
|
||||||
|
#endif
|
||||||
|
|
||||||
extern bool debugger;
|
extern bool debugger;
|
||||||
extern int emulating;
|
extern int emulating;
|
||||||
extern void sdlWriteState(int num);
|
extern void sdlWriteState(int num);
|
||||||
|
@ -377,11 +381,11 @@ static const char* debuggerPrintType(Type* t)
|
||||||
strcpy(buffer, debuggerPrintType(t->pointer));
|
strcpy(buffer, debuggerPrintType(t->pointer));
|
||||||
else
|
else
|
||||||
strcpy(buffer, "void");
|
strcpy(buffer, "void");
|
||||||
sprintf(buffer2, "%s *", buffer);
|
snprintf(buffer2, sizeof(buffer2), "%s *", buffer);
|
||||||
return buffer2;
|
return buffer2;
|
||||||
} else if (t->type == TYPE_reference) {
|
} else if (t->type == TYPE_reference) {
|
||||||
strcpy(buffer, debuggerPrintType(t->pointer));
|
strcpy(buffer, debuggerPrintType(t->pointer));
|
||||||
sprintf(buffer2, "%s &", buffer);
|
snprintf(buffer2, sizeof(buffer2), "%s &", buffer);
|
||||||
return buffer2;
|
return buffer2;
|
||||||
}
|
}
|
||||||
return t->name;
|
return t->name;
|
||||||
|
@ -1364,7 +1368,7 @@ static void debuggerDisassembleArm(FILE* f, uint32_t pc, int count)
|
||||||
if (l > len)
|
if (l > len)
|
||||||
len = l;
|
len = l;
|
||||||
}
|
}
|
||||||
sprintf(format, "%%08x %%-%ds %%s\n", len);
|
snprintf(format, sizeof(format), "%%08x %%-%ds %%s\n", len);
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
uint32_t addr = pc;
|
uint32_t addr = pc;
|
||||||
pc += disArm(pc, buffer, 4096, 2);
|
pc += disArm(pc, buffer, 4096, 2);
|
||||||
|
@ -1383,7 +1387,7 @@ static void debuggerDisassembleThumb(FILE* f, uint32_t pc, int count)
|
||||||
if (l > len)
|
if (l > len)
|
||||||
len = l;
|
len = l;
|
||||||
}
|
}
|
||||||
sprintf(format, "%%08x %%-%ds %%s\n", len);
|
snprintf(format, sizeof(format), "%%08x %%-%ds %%s\n", len);
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
uint32_t addr = pc;
|
uint32_t addr = pc;
|
||||||
|
@ -1781,7 +1785,7 @@ static void debuggerRegisters(int, char**)
|
||||||
((!(reg[16].I & 0x40)) ? '.' : 'F'),
|
((!(reg[16].I & 0x40)) ? '.' : 'F'),
|
||||||
(armState ? '.' : 'T'),
|
(armState ? '.' : 'T'),
|
||||||
armMode);
|
armMode);
|
||||||
sprintf(buffer, "%08x", armState ? reg[15].I - 4 : reg[15].I - 2);
|
snprintf(buffer, sizeof(buffer), "%08x", armState ? reg[15].I - 4 : reg[15].I - 2);
|
||||||
command[1] = buffer;
|
command[1] = buffer;
|
||||||
debuggerDisassemble(3, command);
|
debuggerDisassemble(3, command);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,10 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#if __STDC_WANT_SECURE_LIB__
|
||||||
|
#define snprintf sprintf_s
|
||||||
|
#endif
|
||||||
|
|
||||||
/** Maximum value size for integers and doubles. */
|
/** Maximum value size for integers and doubles. */
|
||||||
#define MAXVALSZ 1024
|
#define MAXVALSZ 1024
|
||||||
|
|
||||||
|
@ -372,12 +376,12 @@ int main(int argc, char *argv[])
|
||||||
/* Set values in dictionary */
|
/* Set values in dictionary */
|
||||||
printf("setting %d values...\n", NVALS);
|
printf("setting %d values...\n", NVALS);
|
||||||
for (i = 0; i < NVALS; i++) {
|
for (i = 0; i < NVALS; i++) {
|
||||||
sprintf(cval, "%04d", i);
|
snprintf(cval, sizeof(cval), "%04d", i);
|
||||||
dictionary_set(d, cval, "salut");
|
dictionary_set(d, cval, "salut");
|
||||||
}
|
}
|
||||||
printf("getting %d values...\n", NVALS);
|
printf("getting %d values...\n", NVALS);
|
||||||
for (i = 0; i < NVALS; i++) {
|
for (i = 0; i < NVALS; i++) {
|
||||||
sprintf(cval, "%04d", i);
|
snprintf(cval, sizeof(cval), "%04d", i);
|
||||||
val = dictionary_get(d, cval, DICT_INVALID_KEY);
|
val = dictionary_get(d, cval, DICT_INVALID_KEY);
|
||||||
if (val == DICT_INVALID_KEY) {
|
if (val == DICT_INVALID_KEY) {
|
||||||
printf("cannot get value for key [%s]\n", cval);
|
printf("cannot get value for key [%s]\n", cval);
|
||||||
|
@ -385,7 +389,7 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
printf("unsetting %d values...\n", NVALS);
|
printf("unsetting %d values...\n", NVALS);
|
||||||
for (i = 0; i < NVALS; i++) {
|
for (i = 0; i < NVALS; i++) {
|
||||||
sprintf(cval, "%04d", i);
|
snprintf(cval, sizeof(cval), "%04d", i);
|
||||||
dictionary_unset(d, cval);
|
dictionary_unset(d, cval);
|
||||||
}
|
}
|
||||||
if (d->n != 0) {
|
if (d->n != 0) {
|
||||||
|
|
|
@ -307,6 +307,9 @@ void sdlStretchx4(uint8_t* src, uint8_t* dest, int width) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void (*sdlStretcher8[4])(uint8_t*, uint8_t*, int) = {
|
||||||
|
sdlStretchx1<uint8_t>, sdlStretchx2<uint8_t>, sdlStretchx3<uint8_t>, sdlStretchx4<uint8_t>};
|
||||||
|
|
||||||
void (*sdlStretcher16[4])(uint8_t*, uint8_t*, int) = {
|
void (*sdlStretcher16[4])(uint8_t*, uint8_t*, int) = {
|
||||||
sdlStretchx1<uint16_t>, sdlStretchx2<uint16_t>, sdlStretchx3<uint16_t>, sdlStretchx4<uint16_t>};
|
sdlStretchx1<uint16_t>, sdlStretchx2<uint16_t>, sdlStretchx3<uint16_t>, sdlStretchx4<uint16_t>};
|
||||||
|
|
||||||
|
@ -391,6 +394,9 @@ bool sdlStretchInit(int colorDepth, int sizeMultiplier, int srcWidth) {
|
||||||
sdlMakeStretcher(srcWidth, sizeMultiplier);
|
sdlMakeStretcher(srcWidth, sizeMultiplier);
|
||||||
#else
|
#else
|
||||||
switch (colorDepth) {
|
switch (colorDepth) {
|
||||||
|
case 8:
|
||||||
|
sdlStretcher = sdlStretcher8[sizeMultiplier];
|
||||||
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
sdlStretcher = sdlStretcher16[sizeMultiplier];
|
sdlStretcher = sdlStretcher16[sizeMultiplier];
|
||||||
break;
|
break;
|
||||||
|
@ -493,33 +499,34 @@ void sdlStretch4x(uint8_t* srcPtr,
|
||||||
struct FilterDesc {
|
struct FilterDesc {
|
||||||
char name[30];
|
char name[30];
|
||||||
int enlargeFactor;
|
int enlargeFactor;
|
||||||
|
FilterFunc func8;
|
||||||
FilterFunc func16;
|
FilterFunc func16;
|
||||||
FilterFunc func24;
|
FilterFunc func24;
|
||||||
FilterFunc func32;
|
FilterFunc func32;
|
||||||
};
|
};
|
||||||
|
|
||||||
const FilterDesc Filters[] = {{"Stretch 1x", 1, sdlStretch1x, sdlStretch1x, sdlStretch1x},
|
const FilterDesc Filters[] = {{"Stretch 1x", 1, sdlStretch1x, sdlStretch1x, sdlStretch1x, sdlStretch1x },
|
||||||
{"Stretch 2x", 2, sdlStretch2x, sdlStretch2x, sdlStretch2x},
|
{"Stretch 2x", 2, sdlStretch2x, sdlStretch2x, sdlStretch2x, sdlStretch2x},
|
||||||
{"2xSaI", 2, _2xSaI, 0, _2xSaI32},
|
{"2xSaI", 2, 0, _2xSaI, 0, _2xSaI32},
|
||||||
{"Super 2xSaI", 2, Super2xSaI, 0, Super2xSaI32},
|
{"Super 2xSaI", 2, 0, Super2xSaI, 0, Super2xSaI32},
|
||||||
{"Super Eagle", 2, SuperEagle, 0, SuperEagle32},
|
{"Super Eagle", 2, 0, SuperEagle, 0, SuperEagle32},
|
||||||
{"Pixelate", 2, Pixelate, 0, Pixelate32},
|
{"Pixelate", 2, 0, Pixelate, 0, Pixelate32},
|
||||||
{"AdvanceMAME Scale2x", 2, AdMame2x, 0, AdMame2x32},
|
{"AdvanceMAME Scale2x", 2, 0, AdMame2x, 0, AdMame2x32},
|
||||||
{"Bilinear", 2, Bilinear, 0, Bilinear32},
|
{"Bilinear", 2, 0, Bilinear, 0, Bilinear32},
|
||||||
{"Bilinear Plus", 2, BilinearPlus, 0, BilinearPlus32},
|
{"Bilinear Plus", 2, 0, BilinearPlus, 0, BilinearPlus32},
|
||||||
{"Scanlines", 2, Scanlines, 0, Scanlines32},
|
{"Scanlines", 2, 0, Scanlines, 0, Scanlines32},
|
||||||
{"TV Mode", 2, ScanlinesTV, 0, ScanlinesTV32},
|
{"TV Mode", 2, 0, ScanlinesTV, 0, ScanlinesTV32},
|
||||||
{"lq2x", 2, lq2x, 0, lq2x32},
|
{"lq2x", 2, 0, lq2x, 0, lq2x32},
|
||||||
{"hq2x", 2, hq2x, 0, hq2x32},
|
{"hq2x", 2, 0, hq2x, 0, hq2x32},
|
||||||
{"xbrz2x", 2, 0, 0, xbrz2x32},
|
{"xbrz2x", 2, 0, 0, 0, xbrz2x32},
|
||||||
{"Stretch 3x", 3, sdlStretch3x, sdlStretch3x, sdlStretch3x},
|
{"Stretch 3x", 3, sdlStretch3x, sdlStretch3x, sdlStretch3x, sdlStretch3x},
|
||||||
{"hq3x", 3, hq3x16, 0, hq3x32_32},
|
{"hq3x", 3, 0, hq3x16, 0, hq3x32_32},
|
||||||
{"xbrz3x", 3, 0, 0, xbrz3x32},
|
{"xbrz3x", 3, 0, 0, 0, xbrz3x32},
|
||||||
{"Stretch 4x", 4, sdlStretch4x, sdlStretch4x, sdlStretch4x},
|
{"Stretch 4x", 4, sdlStretch4x, sdlStretch4x, sdlStretch4x, sdlStretch4x},
|
||||||
{"hq4x", 4, hq4x16, 0, hq4x32_32},
|
{"hq4x", 4, 0, hq4x16, 0, hq4x32_32},
|
||||||
{"xbrz4x", 4, 0, 0, xbrz4x32},
|
{"xbrz4x", 4, 0, 0, 0, xbrz4x32},
|
||||||
{"xbrz5x", 5, 0, 0, xbrz5x32},
|
{"xbrz5x", 5, 0, 0, 0, xbrz5x32},
|
||||||
{"xbrz6x", 6, 0, 0, xbrz6x32}};
|
{"xbrz6x", 6, 0, 0, 0, xbrz6x32}};
|
||||||
|
|
||||||
int getFilterEnlargeFactor(const int f) {
|
int getFilterEnlargeFactor(const int f) {
|
||||||
return Filters[f].enlargeFactor;
|
return Filters[f].enlargeFactor;
|
||||||
|
@ -533,6 +540,9 @@ FilterFunc initFilter(const int f, const int colorDepth, const int srcWidth) {
|
||||||
FilterFunc func;
|
FilterFunc func;
|
||||||
|
|
||||||
switch (colorDepth) {
|
switch (colorDepth) {
|
||||||
|
case 8:
|
||||||
|
func = Filters[f].func8;
|
||||||
|
break;
|
||||||
case 15:
|
case 15:
|
||||||
case 16:
|
case 16:
|
||||||
func = Filters[f].func16;
|
func = Filters[f].func16;
|
||||||
|
@ -585,26 +595,33 @@ FilterFunc initFilter(const int f, const int colorDepth, const int srcWidth) {
|
||||||
|
|
||||||
struct IFBFilterDesc {
|
struct IFBFilterDesc {
|
||||||
char name[30];
|
char name[30];
|
||||||
|
IFBFilterFunc func8;
|
||||||
IFBFilterFunc func16;
|
IFBFilterFunc func16;
|
||||||
|
IFBFilterFunc func24;
|
||||||
IFBFilterFunc func32;
|
IFBFilterFunc func32;
|
||||||
};
|
};
|
||||||
|
|
||||||
const IFBFilterDesc IFBFilters[] = {{"No interframe blending", 0, 0},
|
const IFBFilterDesc IFBFilters[] = {{"No interframe blending", 0, 0, 0},
|
||||||
{"Interframe motion blur", MotionBlurIB, MotionBlurIB32},
|
{"Interframe motion blur", MotionBlurIB8, MotionBlurIB, MotionBlurIB24, MotionBlurIB32},
|
||||||
{"Smart interframe blending", SmartIB, SmartIB32}};
|
{"Smart interframe blending", SmartIB8, SmartIB, SmartIB24, SmartIB32}};
|
||||||
|
|
||||||
IFBFilterFunc initIFBFilter(const int f, const int colorDepth) {
|
IFBFilterFunc initIFBFilter(const int f, const int colorDepth) {
|
||||||
IFBFilterFunc func;
|
IFBFilterFunc func;
|
||||||
|
|
||||||
switch (colorDepth) {
|
switch (colorDepth) {
|
||||||
|
case 8:
|
||||||
|
func = IFBFilters[f].func8;
|
||||||
|
break;
|
||||||
case 15:
|
case 15:
|
||||||
case 16:
|
case 16:
|
||||||
func = IFBFilters[f].func16;
|
func = IFBFilters[f].func16;
|
||||||
break;
|
break;
|
||||||
|
case 24:
|
||||||
|
func = IFBFilters[f].func24;
|
||||||
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
func = IFBFilters[f].func32;
|
func = IFBFilters[f].func32;
|
||||||
break;
|
break;
|
||||||
case 24:
|
|
||||||
default:
|
default:
|
||||||
func = 0;
|
func = 0;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#if __STDC_WANT_SECURE_LIB__
|
||||||
|
#define snprintf sprintf_s
|
||||||
|
#endif
|
||||||
|
|
||||||
/*---------------------------- Defines -------------------------------------*/
|
/*---------------------------- Defines -------------------------------------*/
|
||||||
#define ASCIILINESZ (1024)
|
#define ASCIILINESZ (1024)
|
||||||
#define INI_INVALID_KEY ((char *)-1)
|
#define INI_INVALID_KEY ((char *)-1)
|
||||||
|
@ -269,7 +273,7 @@ void iniparser_dumpsection_ini(dictionary *d, char *s, FILE *f)
|
||||||
seclen = (int)strlen(s);
|
seclen = (int)strlen(s);
|
||||||
// fprintf(f, "\n[%s]\n", s);
|
// fprintf(f, "\n[%s]\n", s);
|
||||||
fprintf(f, "[%s]\n", s);
|
fprintf(f, "[%s]\n", s);
|
||||||
sprintf(keym, "%s:", s);
|
snprintf(keym, sizeof(keym), "%s:", s);
|
||||||
for (j = 0; j < d->size; j++) {
|
for (j = 0; j < d->size; j++) {
|
||||||
if (d->key[j] == NULL)
|
if (d->key[j] == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
@ -303,7 +307,7 @@ int iniparser_getsecnkeys(dictionary *d, char *s)
|
||||||
return nkeys;
|
return nkeys;
|
||||||
|
|
||||||
seclen = (int)strlen(s);
|
seclen = (int)strlen(s);
|
||||||
sprintf(keym, "%s:", s);
|
snprintf(keym, sizeof(keym), "%s:", s);
|
||||||
|
|
||||||
for (j = 0; j < d->size; j++) {
|
for (j = 0; j < d->size; j++) {
|
||||||
if (d->key[j] == NULL)
|
if (d->key[j] == NULL)
|
||||||
|
@ -349,7 +353,7 @@ char **iniparser_getseckeys(dictionary *d, char *s)
|
||||||
keys = (char **)malloc(nkeys * sizeof(char *));
|
keys = (char **)malloc(nkeys * sizeof(char *));
|
||||||
|
|
||||||
seclen = (int)strlen(s);
|
seclen = (int)strlen(s);
|
||||||
sprintf(keym, "%s:", s);
|
snprintf(keym, sizeof(keym), "%s:", s);
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
||||||
|
@ -710,9 +714,9 @@ dictionary *iniparser_load(const char *ininame)
|
||||||
|
|
||||||
case LINE_VALUE:
|
case LINE_VALUE:
|
||||||
if (strlen(section))
|
if (strlen(section))
|
||||||
sprintf(tmp, "%s:%s", section, key);
|
snprintf(tmp, sizeof(tmp), "%s:%s", section, key);
|
||||||
else
|
else
|
||||||
sprintf(tmp, "preferences:%s", key);
|
snprintf(tmp, sizeof(tmp), "preferences:%s", key);
|
||||||
errs = dictionary_set(dict, tmp, val);
|
errs = dictionary_set(dict, tmp, val);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
#include "sdl/ConfigManager.h"
|
#include "sdl/ConfigManager.h"
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
#define SDLBUTTONS_NUM 14
|
#define SDLBUTTONS_NUM 14
|
||||||
|
|
||||||
static void sdlUpdateKey(uint32_t key, bool down);
|
static void sdlUpdateKey(uint32_t key, bool down);
|
||||||
|
@ -63,11 +65,23 @@ static uint32_t joypad[5][SDLBUTTONS_NUM] = {
|
||||||
{
|
{
|
||||||
SDLK_LEFT, SDLK_RIGHT,
|
SDLK_LEFT, SDLK_RIGHT,
|
||||||
SDLK_UP, SDLK_DOWN,
|
SDLK_UP, SDLK_DOWN,
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
SDLK_Z, SDLK_X,
|
||||||
|
#else
|
||||||
SDLK_z, SDLK_x,
|
SDLK_z, SDLK_x,
|
||||||
|
#endif
|
||||||
SDLK_RETURN, SDLK_BACKSPACE,
|
SDLK_RETURN, SDLK_BACKSPACE,
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
SDLK_A, SDLK_S,
|
||||||
|
#else
|
||||||
SDLK_a, SDLK_s,
|
SDLK_a, SDLK_s,
|
||||||
|
#endif
|
||||||
SDLK_SPACE, SDLK_F12,
|
SDLK_SPACE, SDLK_F12,
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
SDLK_Q, SDLK_W,
|
||||||
|
#else
|
||||||
SDLK_q, SDLK_w,
|
SDLK_q, SDLK_w,
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -106,18 +120,37 @@ static uint32_t sdlGetAxisCode(const SDL_Event& event)
|
||||||
uint32_t inputGetEventCode(const SDL_Event& event)
|
uint32_t inputGetEventCode(const SDL_Event& event)
|
||||||
{
|
{
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
case SDL_EVENT_KEY_DOWN:
|
||||||
|
case SDL_EVENT_KEY_UP:
|
||||||
|
return event.key.key;
|
||||||
|
#else
|
||||||
case SDL_KEYDOWN:
|
case SDL_KEYDOWN:
|
||||||
case SDL_KEYUP:
|
case SDL_KEYUP:
|
||||||
return event.key.keysym.sym;
|
return event.key.keysym.sym;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
case SDL_EVENT_JOYSTICK_HAT_MOTION:
|
||||||
|
#else
|
||||||
case SDL_JOYHATMOTION:
|
case SDL_JOYHATMOTION:
|
||||||
|
#endif
|
||||||
return sdlGetHatCode(event);
|
return sdlGetHatCode(event);
|
||||||
break;
|
break;
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
|
||||||
|
case SDL_EVENT_JOYSTICK_BUTTON_UP:
|
||||||
|
#else
|
||||||
case SDL_JOYBUTTONDOWN:
|
case SDL_JOYBUTTONDOWN:
|
||||||
case SDL_JOYBUTTONUP:
|
case SDL_JOYBUTTONUP:
|
||||||
|
#endif
|
||||||
return sdlGetButtonCode(event);
|
return sdlGetButtonCode(event);
|
||||||
break;
|
break;
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
case SDL_EVENT_JOYSTICK_AXIS_MOTION:
|
||||||
|
#else
|
||||||
case SDL_JOYAXISMOTION:
|
case SDL_JOYAXISMOTION:
|
||||||
|
#endif
|
||||||
return sdlGetAxisCode(event);
|
return sdlGetAxisCode(event);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -348,18 +381,30 @@ static bool sdlCheckJoyKey(int key)
|
||||||
// joystick button
|
// joystick button
|
||||||
int button = what - 128;
|
int button = what - 128;
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
if (button >= SDL_GetNumJoystickButtons(sdlDevices[dev]))
|
||||||
|
#else
|
||||||
if (button >= SDL_JoystickNumButtons(sdlDevices[dev]))
|
if (button >= SDL_JoystickNumButtons(sdlDevices[dev]))
|
||||||
|
#endif
|
||||||
return false;
|
return false;
|
||||||
} else if (what < 0x20) {
|
} else if (what < 0x20) {
|
||||||
// joystick axis
|
// joystick axis
|
||||||
what >>= 1;
|
what >>= 1;
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
if (what >= SDL_GetNumJoystickAxes(sdlDevices[dev]))
|
||||||
|
#else
|
||||||
if (what >= SDL_JoystickNumAxes(sdlDevices[dev]))
|
if (what >= SDL_JoystickNumAxes(sdlDevices[dev]))
|
||||||
|
#endif
|
||||||
return false;
|
return false;
|
||||||
} else if (what < 0x30) {
|
} else if (what < 0x30) {
|
||||||
// joystick hat
|
// joystick hat
|
||||||
what = (what & 15);
|
what = (what & 15);
|
||||||
what >>= 2;
|
what >>= 2;
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
if (what >= SDL_GetNumJoystickHats(sdlDevices[dev]))
|
||||||
|
#else
|
||||||
if (what >= SDL_JoystickNumHats(sdlDevices[dev]))
|
if (what >= SDL_JoystickNumHats(sdlDevices[dev]))
|
||||||
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -369,17 +414,23 @@ static bool sdlCheckJoyKey(int key)
|
||||||
|
|
||||||
void inputInitJoysticks()
|
void inputInitJoysticks()
|
||||||
{
|
{
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
SDL_JoystickID *joysticks = SDL_GetJoysticks(&sdlNumDevices);
|
||||||
|
#else
|
||||||
|
sdlNumDevices = SDL_NumJoysticks();
|
||||||
|
#endif
|
||||||
|
bool usesJoy = false;
|
||||||
|
|
||||||
// The main joypad has to be entirely defined
|
// The main joypad has to be entirely defined
|
||||||
for (int i = 0; i < SDLBUTTONS_NUM; i++) {
|
for (int i = 0; i < SDLBUTTONS_NUM; i++) {
|
||||||
if (!joypad[PAD_MAIN][i])
|
if (!joypad[PAD_MAIN][i])
|
||||||
joypad[PAD_MAIN][i] = joypad[PAD_DEFAULT][i];
|
joypad[PAD_MAIN][i] = joypad[PAD_DEFAULT][i];
|
||||||
}
|
}
|
||||||
|
|
||||||
sdlNumDevices = SDL_NumJoysticks();
|
|
||||||
|
|
||||||
if (sdlNumDevices)
|
if (sdlNumDevices)
|
||||||
|
{
|
||||||
sdlDevices = (SDL_Joystick**)calloc(1, sdlNumDevices * sizeof(SDL_Joystick**));
|
sdlDevices = (SDL_Joystick**)calloc(1, sdlNumDevices * sizeof(SDL_Joystick**));
|
||||||
bool usesJoy = false;
|
}
|
||||||
|
|
||||||
for (int j = 0; j < 4; j++) {
|
for (int j = 0; j < 4; j++) {
|
||||||
for (int i = 0; i < SDLBUTTONS_NUM; i++) {
|
for (int i = 0; i < SDLBUTTONS_NUM; i++) {
|
||||||
|
@ -391,12 +442,17 @@ void inputInitJoysticks()
|
||||||
if (sdlDevices) {
|
if (sdlDevices) {
|
||||||
if (dev < sdlNumDevices) {
|
if (dev < sdlNumDevices) {
|
||||||
if (sdlDevices[dev] == NULL) {
|
if (sdlDevices[dev] == NULL) {
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
sdlDevices[dev] = SDL_JoystickOpen(dev);
|
sdlDevices[dev] = SDL_JoystickOpen(dev);
|
||||||
|
#else
|
||||||
|
sdlDevices[dev] = SDL_OpenJoystick(joysticks[dev]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = sdlCheckJoyKey(joypad[j][i]);
|
ok = sdlCheckJoyKey(joypad[j][i]);
|
||||||
} else
|
} else {
|
||||||
ok = false;
|
ok = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ok)
|
if (!ok)
|
||||||
|
@ -416,7 +472,11 @@ void inputInitJoysticks()
|
||||||
if (sdlDevices) {
|
if (sdlDevices) {
|
||||||
if (dev < sdlNumDevices) {
|
if (dev < sdlNumDevices) {
|
||||||
if (sdlDevices[dev] == NULL) {
|
if (sdlDevices[dev] == NULL) {
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
sdlDevices[dev] = SDL_JoystickOpen(dev);
|
sdlDevices[dev] = SDL_JoystickOpen(dev);
|
||||||
|
#else
|
||||||
|
sdlDevices[dev] = SDL_OpenJoystick(joysticks[dev]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = sdlCheckJoyKey(motion[i]);
|
ok = sdlCheckJoyKey(motion[i]);
|
||||||
|
@ -432,34 +492,68 @@ void inputInitJoysticks()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usesJoy)
|
if (usesJoy)
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
SDL_SetJoystickEventsEnabled(true);
|
||||||
|
#else
|
||||||
SDL_JoystickEventState(SDL_ENABLE);
|
SDL_JoystickEventState(SDL_ENABLE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void inputProcessSDLEvent(const SDL_Event& event)
|
void inputProcessSDLEvent(const SDL_Event& event)
|
||||||
{
|
{
|
||||||
// fprintf(stdout, "%x\n", inputGetEventCode(event));
|
// fprintf(stdout, "%x\n", inputGetEventCode(event));
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
case SDL_EVENT_KEY_DOWN:
|
||||||
|
if (!event.key.mod)
|
||||||
|
sdlUpdateKey(event.key.key, true);
|
||||||
|
#else
|
||||||
case SDL_KEYDOWN:
|
case SDL_KEYDOWN:
|
||||||
if (!event.key.keysym.mod)
|
if (!event.key.keysym.mod)
|
||||||
sdlUpdateKey(event.key.keysym.sym, true);
|
sdlUpdateKey(event.key.keysym.sym, true);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
case SDL_EVENT_KEY_UP:
|
||||||
|
if (!event.key.mod)
|
||||||
|
sdlUpdateKey(event.key.key, false);
|
||||||
|
#else
|
||||||
case SDL_KEYUP:
|
case SDL_KEYUP:
|
||||||
if (!event.key.keysym.mod)
|
if (!event.key.keysym.mod)
|
||||||
sdlUpdateKey(event.key.keysym.sym, false);
|
sdlUpdateKey(event.key.keysym.sym, false);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
case SDL_EVENT_JOYSTICK_HAT_MOTION:
|
||||||
|
#else
|
||||||
case SDL_JOYHATMOTION:
|
case SDL_JOYHATMOTION:
|
||||||
|
#endif
|
||||||
sdlUpdateJoyHat(event.jhat.which,
|
sdlUpdateJoyHat(event.jhat.which,
|
||||||
event.jhat.hat,
|
event.jhat.hat,
|
||||||
event.jhat.value);
|
event.jhat.value);
|
||||||
break;
|
break;
|
||||||
case SDL_JOYBUTTONDOWN:
|
#ifdef ENABLE_SDL3
|
||||||
case SDL_JOYBUTTONUP:
|
case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
|
||||||
|
case SDL_EVENT_JOYSTICK_BUTTON_UP:
|
||||||
sdlUpdateJoyButton(event.jbutton.which,
|
sdlUpdateJoyButton(event.jbutton.which,
|
||||||
event.jbutton.button,
|
event.jbutton.button,
|
||||||
event.jbutton.state == SDL_PRESSED);
|
event.jbutton.down == true);
|
||||||
|
#else
|
||||||
|
case SDL_JOYBUTTONDOWN:
|
||||||
|
case SDL_JOYBUTTONUP:
|
||||||
|
sdlUpdateJoyButton(event.jbutton.which,
|
||||||
|
event.jbutton.button,
|
||||||
|
event.jbutton.state == SDL_PRESSED);
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
case SDL_EVENT_JOYSTICK_AXIS_MOTION:
|
||||||
|
#else
|
||||||
case SDL_JOYAXISMOTION:
|
case SDL_JOYAXISMOTION:
|
||||||
|
#endif
|
||||||
sdlUpdateJoyAxis(event.jaxis.which,
|
sdlUpdateJoyAxis(event.jaxis.which,
|
||||||
event.jaxis.axis,
|
event.jaxis.axis,
|
||||||
event.jaxis.value);
|
event.jaxis.value);
|
||||||
|
|
|
@ -20,7 +20,11 @@
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include <SDL_events.h>
|
#ifndef ENABLE_SDL3
|
||||||
|
#include <SDL.h>
|
||||||
|
#else
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
enum EKey {
|
enum EKey {
|
||||||
KEY_LEFT,
|
KEY_LEFT,
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
See the LICENSE.txt file for this sample’s licensing information.
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
Header containing types and enum constants shared between Metal shaders and C/ObjC source
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef AAPLShaderTypes_h
|
||||||
|
#define AAPLShaderTypes_h
|
||||||
|
|
||||||
|
#include <simd/simd.h>
|
||||||
|
|
||||||
|
// Buffer index values shared between shader and C code to ensure Metal shader buffer inputs match
|
||||||
|
// Metal API buffer set calls
|
||||||
|
typedef enum AAPLVertexInputIndex
|
||||||
|
{
|
||||||
|
AAPLVertexInputIndexVertices = 0,
|
||||||
|
AAPLVertexInputIndexViewportSize = 1,
|
||||||
|
} AAPLVertexInputIndex;
|
||||||
|
|
||||||
|
// Texture index values shared between shader and C code to ensure Metal shader buffer inputs match
|
||||||
|
// Metal API texture set calls
|
||||||
|
typedef enum AAPLTextureIndex
|
||||||
|
{
|
||||||
|
AAPLTextureIndexBaseColor = 0,
|
||||||
|
} AAPLTextureIndex;
|
||||||
|
|
||||||
|
// This structure defines the layout of each vertex in the array of vertices set as an input to the
|
||||||
|
// Metal vertex shader. Since this header is shared between the .metal shader and C code,
|
||||||
|
// you can be sure that the layout of the vertex array in the code matches the layout that
|
||||||
|
// the vertex shader expects
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
// Positions in pixel space. A value of 100 indicates 100 pixels from the origin/center.
|
||||||
|
vector_float2 position;
|
||||||
|
|
||||||
|
// 2D texture coordinate
|
||||||
|
vector_float2 textureCoordinate;
|
||||||
|
} AAPLVertex;
|
||||||
|
|
||||||
|
#endif /* AAPLShaderTypes_h */
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
See the LICENSE.txt file for this sample’s licensing information.
|
||||||
|
|
||||||
|
Abstract:
|
||||||
|
Metal shaders used for this sample
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <metal_stdlib>
|
||||||
|
#include <simd/simd.h>
|
||||||
|
|
||||||
|
using namespace metal;
|
||||||
|
|
||||||
|
// Include header shared between this Metal shader code and C code executing Metal API commands
|
||||||
|
#include "AAPLShaderTypes.h"
|
||||||
|
|
||||||
|
struct RasterizerData
|
||||||
|
{
|
||||||
|
// The [[position]] attribute qualifier of this member indicates this value is
|
||||||
|
// the clip space position of the vertex when this structure is returned from
|
||||||
|
// the vertex shader
|
||||||
|
float4 position [[position]];
|
||||||
|
|
||||||
|
// Since this member does not have a special attribute qualifier, the rasterizer
|
||||||
|
// will interpolate its value with values of other vertices making up the triangle
|
||||||
|
// and pass that interpolated value to the fragment shader for each fragment in
|
||||||
|
// that triangle.
|
||||||
|
float2 textureCoordinate;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Vertex Function
|
||||||
|
vertex RasterizerData
|
||||||
|
vertexShader(uint vertexID [[ vertex_id ]],
|
||||||
|
constant AAPLVertex *vertexArray [[ buffer(AAPLVertexInputIndexVertices) ]],
|
||||||
|
constant vector_uint2 *viewportSizePointer [[ buffer(AAPLVertexInputIndexViewportSize) ]])
|
||||||
|
{
|
||||||
|
|
||||||
|
RasterizerData out;
|
||||||
|
|
||||||
|
// Index into the array of positions to get the current vertex.
|
||||||
|
// Positions are specified in pixel dimensions (i.e. a value of 100 is 100 pixels from
|
||||||
|
// the origin)
|
||||||
|
float2 pixelSpacePosition = vertexArray[vertexID].position.xy;
|
||||||
|
|
||||||
|
// Get the viewport size and cast to float.
|
||||||
|
float2 viewportSize = float2(*viewportSizePointer);
|
||||||
|
|
||||||
|
// To convert from positions in pixel space to positions in clip-space,
|
||||||
|
// divide the pixel coordinates by half the size of the viewport.
|
||||||
|
// Z is set to 0.0 and w to 1.0 because this is 2D sample.
|
||||||
|
out.position = vector_float4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
out.position.xy = pixelSpacePosition / viewportSize;
|
||||||
|
|
||||||
|
// Pass the input textureCoordinate straight to the output RasterizerData. This value will be
|
||||||
|
// interpolated with the other textureCoordinate values in the vertices that make up the
|
||||||
|
// triangle.
|
||||||
|
out.textureCoordinate = vertexArray[vertexID].textureCoordinate;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fragment function
|
||||||
|
fragment float4
|
||||||
|
samplingShader(RasterizerData in [[stage_in]],
|
||||||
|
texture2d<half> colorTexture [[ texture(AAPLTextureIndexBaseColor) ]])
|
||||||
|
{
|
||||||
|
constexpr sampler textureSampler (mag_filter::linear,
|
||||||
|
min_filter::linear);
|
||||||
|
|
||||||
|
// Sample the texture to obtain a color
|
||||||
|
const half4 colorSample = colorTexture.sample(textureSampler, in.textureCoordinate);
|
||||||
|
|
||||||
|
// return the color of the texture
|
||||||
|
return float4(colorSample);
|
||||||
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ include(VbamFunctions)
|
||||||
set(VBAM_WX_COMMON
|
set(VBAM_WX_COMMON
|
||||||
audio/audio.cpp
|
audio/audio.cpp
|
||||||
audio/audio.h
|
audio/audio.h
|
||||||
|
audio/internal/sdl.cpp
|
||||||
|
audio/internal/sdl.h
|
||||||
audio/internal/openal.cpp
|
audio/internal/openal.cpp
|
||||||
audio/internal/openal.h
|
audio/internal/openal.h
|
||||||
background-input.cpp
|
background-input.cpp
|
||||||
|
@ -156,6 +158,11 @@ if(CMAKE_TOOLCHAIN_FILE MATCHES "vcpkg")
|
||||||
find_package(nanosvg)
|
find_package(nanosvg)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
find_library(METAL Metal)
|
||||||
|
find_library(METALKIT MetalKit)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(ENABLE_OPENGL TRUE)
|
set(ENABLE_OPENGL TRUE)
|
||||||
find_package(wxWidgets COMPONENTS xrc xml html adv net core base gl ${wx_find_extra})
|
find_package(wxWidgets COMPONENTS xrc xml html adv net core base gl ${wx_find_extra})
|
||||||
|
|
||||||
|
@ -254,6 +261,11 @@ function(configure_wx_target target)
|
||||||
_add_compile_definitions(${wxWidgets_DEFINITIONS_DEBUG})
|
_add_compile_definitions(${wxWidgets_DEFINITIONS_DEBUG})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# No Metal
|
||||||
|
if(NOT CMAKE_Metal_COMPILER)
|
||||||
|
_add_compile_definitions(NO_METAL)
|
||||||
|
endif()
|
||||||
|
|
||||||
# OpenAL.
|
# OpenAL.
|
||||||
if(OPENAL_STATIC)
|
if(OPENAL_STATIC)
|
||||||
_add_compile_definitions(AL_LIBTYPE_STATIC)
|
_add_compile_definitions(AL_LIBTYPE_STATIC)
|
||||||
|
@ -294,8 +306,8 @@ function(configure_wx_target target)
|
||||||
_add_compile_definitions(NO_D3D)
|
_add_compile_definitions(NO_D3D)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# SDL2.
|
# SDL.
|
||||||
_add_link_libraries(${VBAM_SDL2_LIBS})
|
_add_link_libraries(${VBAM_SDL_LIBS})
|
||||||
|
|
||||||
# OpenGL.
|
# OpenGL.
|
||||||
if(ENABLE_OPENGL)
|
if(ENABLE_OPENGL)
|
||||||
|
@ -303,6 +315,15 @@ function(configure_wx_target target)
|
||||||
else()
|
else()
|
||||||
_add_compile_definitions(NO_OGL)
|
_add_compile_definitions(NO_OGL)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Metal
|
||||||
|
if(APPLE)
|
||||||
|
if(CMAKE_Metal_COMPILER)
|
||||||
|
_add_link_libraries($<LINK_LIBRARY:WEAK_FRAMEWORK,${METAL}>)
|
||||||
|
_add_link_libraries($<LINK_LIBRARY:WEAK_FRAMEWORK,${METALKIT}>)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
# Sub-projects.
|
# Sub-projects.
|
||||||
|
@ -320,7 +341,12 @@ add_executable(
|
||||||
)
|
)
|
||||||
|
|
||||||
target_sources(visualboyadvance-m PRIVATE ${VBAM_WX_COMMON} ${VBAM_ICON_PATH})
|
target_sources(visualboyadvance-m PRIVATE ${VBAM_WX_COMMON} ${VBAM_ICON_PATH})
|
||||||
target_include_directories(visualboyadvance-m PRIVATE ${SDL2_INCLUDE_DIRS})
|
|
||||||
|
if(ENABLE_SDL3)
|
||||||
|
target_include_directories(visualboyadvance-m PRIVATE ${SDL3_INCLUDE_DIRS})
|
||||||
|
else()
|
||||||
|
target_include_directories(visualboyadvance-m PRIVATE ${SDL2_INCLUDE_DIRS})
|
||||||
|
endif()
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
visualboyadvance-m
|
visualboyadvance-m
|
||||||
|
@ -1047,3 +1073,27 @@ install(
|
||||||
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_MANDIR}/man6)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
if(CMAKE_Metal_COMPILER)
|
||||||
|
set(VBAM_SHADER default.metallib)
|
||||||
|
|
||||||
|
set(ShaderBase_HEADERS
|
||||||
|
AAPLShaderTypes.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(ShaderBase_SOURCES
|
||||||
|
AAPLShaders.metal
|
||||||
|
)
|
||||||
|
|
||||||
|
add_metal_shader_library(default
|
||||||
|
STANDARD macos-metal1.1
|
||||||
|
${ShaderBase_SOURCES}
|
||||||
|
${ShaderBase_HEADERS}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_embed_metal_shader_libraries(visualboyadvance-m
|
||||||
|
default
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "wx/audio/audio.h"
|
#include "wx/audio/audio.h"
|
||||||
|
|
||||||
#include "core/base/check.h"
|
#include "core/base/check.h"
|
||||||
|
#include "wx/audio/internal/sdl.h"
|
||||||
#include "wx/audio/internal/openal.h"
|
#include "wx/audio/internal/openal.h"
|
||||||
|
|
||||||
#if defined(__WXMSW__)
|
#if defined(__WXMSW__)
|
||||||
|
@ -22,6 +23,9 @@ std::vector<AudioDevice> EnumerateAudioDevices(const config::AudioApi& audio_api
|
||||||
case config::AudioApi::kOpenAL:
|
case config::AudioApi::kOpenAL:
|
||||||
return audio::internal::GetOpenALDevices();
|
return audio::internal::GetOpenALDevices();
|
||||||
|
|
||||||
|
case config::AudioApi::kSDL:
|
||||||
|
return audio::internal::GetSDLDevices();
|
||||||
|
|
||||||
#if defined(__WXMSW__)
|
#if defined(__WXMSW__)
|
||||||
case config::AudioApi::kDirectSound:
|
case config::AudioApi::kDirectSound:
|
||||||
return audio::internal::GetDirectSoundDevices();
|
return audio::internal::GetDirectSoundDevices();
|
||||||
|
@ -49,6 +53,9 @@ std::unique_ptr<SoundDriver> CreateSoundDriver(const config::AudioApi& api) {
|
||||||
case config::AudioApi::kOpenAL:
|
case config::AudioApi::kOpenAL:
|
||||||
return audio::internal::CreateOpenALDriver();
|
return audio::internal::CreateOpenALDriver();
|
||||||
|
|
||||||
|
case config::AudioApi::kSDL:
|
||||||
|
return audio::internal::CreateSDLDriver();
|
||||||
|
|
||||||
#if defined(__WXMSW__)
|
#if defined(__WXMSW__)
|
||||||
case config::AudioApi::kDirectSound:
|
case config::AudioApi::kDirectSound:
|
||||||
return audio::internal::CreateDirectSoundDriver();
|
return audio::internal::CreateDirectSoundDriver();
|
||||||
|
|
|
@ -0,0 +1,381 @@
|
||||||
|
#include "wx/audio/internal/sdl.h"
|
||||||
|
|
||||||
|
// === LOGALL writes very detailed informations to vba-trace.log ===
|
||||||
|
// #define LOGALL
|
||||||
|
|
||||||
|
// on win32 and mac, pointer typedefs only happen with AL_NO_PROTOTYPES
|
||||||
|
// on mac, ALC_NO_PROTOTYPES as well
|
||||||
|
|
||||||
|
// #define AL_NO_PROTOTYPES 1
|
||||||
|
|
||||||
|
// on mac, alc pointer typedefs ony happen for ALC if ALC_NO_PROTOTYPES
|
||||||
|
// unfortunately, there is a bug in the system headers (use of ALCvoid when
|
||||||
|
// void should be used; shame on Apple for introducing this error, and shame
|
||||||
|
// on Creative for making a typedef to void in the first place)
|
||||||
|
// #define ALC_NO_PROTOTYPES 1
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#else
|
||||||
|
#include <SDL.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <wx/arrstr.h>
|
||||||
|
#include <wx/log.h>
|
||||||
|
#include <wx/translation.h>
|
||||||
|
#include <wx/utils.h>
|
||||||
|
|
||||||
|
#include "core/base/sound_driver.h"
|
||||||
|
#include "core/base/check.h"
|
||||||
|
#include "core/gba/gbaGlobals.h"
|
||||||
|
#include "core/gba/gbaSound.h"
|
||||||
|
#include "wx/config/option-proxy.h"
|
||||||
|
|
||||||
|
#ifndef LOGALL
|
||||||
|
// replace logging functions with comments
|
||||||
|
#ifdef winlog
|
||||||
|
#undef winlog
|
||||||
|
#endif
|
||||||
|
// https://stackoverflow.com/a/1306690/262458
|
||||||
|
#define winlog(x, ...) \
|
||||||
|
do { \
|
||||||
|
} while (0)
|
||||||
|
#define debugState() //
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern int emulating;
|
||||||
|
|
||||||
|
namespace audio {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class SDLAudio : public SoundDriver {
|
||||||
|
public:
|
||||||
|
SDLAudio();
|
||||||
|
~SDLAudio() override;
|
||||||
|
|
||||||
|
bool init(long sampleRate) override; // initialize the sound buffer queue
|
||||||
|
void deinit();
|
||||||
|
void setThrottle(unsigned short throttle_) override; // set game speed
|
||||||
|
void pause() override; // pause the secondary sound buffer
|
||||||
|
void reset() override; // stop and reset the secondary sound buffer
|
||||||
|
void resume() override; // play/resume the secondary sound buffer
|
||||||
|
void write(uint16_t* finalWave, int length) override; // write the emulated sound to a sound buffer
|
||||||
|
|
||||||
|
private:
|
||||||
|
SDL_AudioDeviceID sound_device = 0;
|
||||||
|
SDL_AudioSpec audio;
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
SDL_AudioStream *sound_stream = NULL;
|
||||||
|
SDL_Mutex* mutex;
|
||||||
|
#else
|
||||||
|
SDL_mutex* mutex;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
SDL_AudioDeviceID *sdl_devices;
|
||||||
|
int sdl_devices_count = 0;
|
||||||
|
#else
|
||||||
|
unsigned short current_rate;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool initialized = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
SDLAudio::SDLAudio():
|
||||||
|
sound_device(0),
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
|
current_rate(static_cast<unsigned short>(coreOptions.throttle)),
|
||||||
|
#endif
|
||||||
|
initialized(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void SDLAudio::deinit() {
|
||||||
|
if (!initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
initialized = false;
|
||||||
|
|
||||||
|
SDL_LockMutex(mutex);
|
||||||
|
int is_emulating = emulating;
|
||||||
|
emulating = 0;
|
||||||
|
SDL_UnlockMutex(mutex);
|
||||||
|
|
||||||
|
SDL_DestroyMutex(mutex);
|
||||||
|
mutex = nullptr;
|
||||||
|
|
||||||
|
SDL_CloseAudioDevice(sound_device);
|
||||||
|
|
||||||
|
emulating = is_emulating;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDLAudio::~SDLAudio() {
|
||||||
|
deinit();
|
||||||
|
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SDLAudio::init(long sampleRate) {
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
int current_device = SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK;
|
||||||
|
sdl_devices = SDL_GetAudioPlaybackDevices(&sdl_devices_count);
|
||||||
|
const char *devs = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
winlog("SDLAudio::init\n");
|
||||||
|
if (initialized) deinit();
|
||||||
|
|
||||||
|
SDL_memset(&audio, 0, sizeof(audio));
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
// for "no throttle" use regular rate, audio is just dropped
|
||||||
|
audio.freq = sampleRate;
|
||||||
|
|
||||||
|
audio.format = SDL_AUDIO_S16;
|
||||||
|
#else
|
||||||
|
// for "no throttle" use regular rate, audio is just dropped
|
||||||
|
audio.freq = current_rate ? static_cast<int>(sampleRate * ((float)current_rate / 100.0)) : sampleRate;
|
||||||
|
|
||||||
|
audio.format = AUDIO_S16SYS;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
audio.channels = 2;
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
if (SDL_InitSubSystem(SDL_INIT_AUDIO) == false) {
|
||||||
|
#else
|
||||||
|
audio.samples = 2048;
|
||||||
|
audio.callback = NULL;
|
||||||
|
audio.userdata = NULL;
|
||||||
|
|
||||||
|
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
if (SDL_WasInit(SDL_INIT_AUDIO) == false) {
|
||||||
|
#else
|
||||||
|
if (SDL_WasInit(SDL_INIT_AUDIO) < 0) {
|
||||||
|
#endif
|
||||||
|
SDL_Init(SDL_INIT_AUDIO);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
#ifdef ONLY_DEFAULT_AUDIO_DEVICE
|
||||||
|
sound_stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &audio, NULL, NULL);
|
||||||
|
#else
|
||||||
|
for (int i = 0; i < sdl_devices_count; i++) {
|
||||||
|
devs = SDL_GetAudioDeviceName(sdl_devices[i]);
|
||||||
|
const wxString device_name(devs, wxConvLibc);
|
||||||
|
|
||||||
|
if (device_name == OPTION(kSoundAudioDevice))
|
||||||
|
{
|
||||||
|
current_device = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OPTION(kSoundAudioDevice) == _("Default device")) {
|
||||||
|
sound_stream = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &audio, NULL, NULL);
|
||||||
|
} else {
|
||||||
|
sound_stream = SDL_OpenAudioDeviceStream(sdl_devices[current_device], &audio, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sound_stream == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sound_device = SDL_GetAudioStreamDevice(sound_stream);
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#ifdef ONLY_DEFAULT_AUDIO_DEVICE
|
||||||
|
sound_device = SDL_OpenAudioDevice(NULL, 0, &audio, NULL, 0);
|
||||||
|
#else
|
||||||
|
const wxString device_name = OPTION(kSoundAudioDevice);
|
||||||
|
|
||||||
|
if (device_name == _("Default device")) {
|
||||||
|
sound_device = SDL_OpenAudioDevice(NULL, 0, &audio, NULL, 0);
|
||||||
|
} else {
|
||||||
|
sound_device = SDL_OpenAudioDevice(device_name.mb_str(), 0, &audio, NULL, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if(sound_device == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex = SDL_CreateMutex();
|
||||||
|
|
||||||
|
// turn off audio events because we are not processing them
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
SDL_SetEventEnabled(SDL_EVENT_AUDIO_DEVICE_ADDED, false);
|
||||||
|
SDL_SetEventEnabled(SDL_EVENT_AUDIO_DEVICE_REMOVED, false);
|
||||||
|
#elif SDL_VERSION_ATLEAST(2, 0, 4)
|
||||||
|
SDL_EventState(SDL_AUDIODEVICEADDED, SDL_IGNORE);
|
||||||
|
SDL_EventState(SDL_AUDIODEVICEREMOVED, SDL_IGNORE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLAudio::setThrottle(unsigned short throttle_) {
|
||||||
|
if (!initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (throttle_ == 0)
|
||||||
|
throttle_ = 450;
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
SDL_SetAudioStreamFrequencyRatio(sound_stream, (float)throttle_ / 100.0f);
|
||||||
|
#else
|
||||||
|
current_rate = throttle_;
|
||||||
|
|
||||||
|
reset();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLAudio::resume() {
|
||||||
|
if (!initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
winlog("SDLAudio::resume\n");
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
if (SDL_AudioDevicePaused(sound_device) == true) {
|
||||||
|
SDL_ResumeAudioStreamDevice(sound_stream);
|
||||||
|
SDL_ResumeAudioDevice(sound_device);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (SDL_GetAudioDeviceStatus(sound_device) != SDL_AUDIO_PLAYING) {
|
||||||
|
SDL_PauseAudioDevice(sound_device, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLAudio::pause() {
|
||||||
|
if (!initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
winlog("SDLAudio::pause\n");
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
if (SDL_AudioDevicePaused(sound_device) == true) {
|
||||||
|
SDL_PauseAudioStreamDevice(sound_stream);
|
||||||
|
SDL_PauseAudioDevice(sound_device);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (SDL_GetAudioDeviceStatus(sound_device) != SDL_AUDIO_PLAYING) {
|
||||||
|
SDL_PauseAudioDevice(sound_device, 1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLAudio::reset() {
|
||||||
|
if (!initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
winlog("SDLAudio::reset\n");
|
||||||
|
|
||||||
|
init(soundGetSampleRate());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLAudio::write(uint16_t* finalWave, int length) {
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
if (!initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SDL_LockMutex(mutex);
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
if (SDL_AudioDevicePaused(sound_device) == true) {
|
||||||
|
SDL_ResumeAudioStreamDevice(sound_stream);
|
||||||
|
SDL_ResumeAudioDevice(sound_device);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (SDL_GetAudioDeviceStatus(sound_device) != SDL_AUDIO_PLAYING) {
|
||||||
|
SDL_PauseAudioDevice(sound_device, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
res = (int)SDL_PutAudioStreamData(sound_stream, finalWave, length) == true;
|
||||||
|
|
||||||
|
while (res && SDL_GetAudioStreamQueued(sound_stream) > (2048 * audio.channels * sizeof(uint16_t))) {
|
||||||
|
SDL_Delay(1);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
res = SDL_QueueAudio(sound_device, finalWave, length) == 0;
|
||||||
|
|
||||||
|
while (res && SDL_GetQueuedAudioSize(sound_device) > (audio.samples * audio.channels * sizeof(uint16_t))) {
|
||||||
|
SDL_Delay(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
winlog("SDL audio queue result: %d\n", res);
|
||||||
|
|
||||||
|
SDL_UnlockMutex(mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
std::vector<AudioDevice> GetSDLDevices() {
|
||||||
|
std::vector<AudioDevice> devices;
|
||||||
|
|
||||||
|
#ifdef ONLY_DEFAULT_AUDIO_DEVICE
|
||||||
|
devices.push_back({_("Default device"), wxEmptyString});
|
||||||
|
#else
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
const char *devs = NULL;
|
||||||
|
SDL_AudioDeviceID *sdl_devices = NULL;
|
||||||
|
int sdl_devices_count = 0;
|
||||||
|
|
||||||
|
SDL_InitSubSystem(SDL_INIT_AUDIO);
|
||||||
|
|
||||||
|
sdl_devices = SDL_GetAudioPlaybackDevices(&sdl_devices_count);
|
||||||
|
|
||||||
|
devices.push_back({_("Default device"), _("Default device")});
|
||||||
|
|
||||||
|
for (int i = 0; i < sdl_devices_count; i++)
|
||||||
|
{
|
||||||
|
devs = SDL_GetAudioDeviceName(sdl_devices[i]);
|
||||||
|
|
||||||
|
if (devs != NULL)
|
||||||
|
{
|
||||||
|
const wxString device_name(devs, wxConvLibc);
|
||||||
|
devices.push_back({device_name, device_name});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
const char *devs = NULL;
|
||||||
|
int sdl_devices_count = 0;
|
||||||
|
|
||||||
|
SDL_InitSubSystem(SDL_INIT_AUDIO);
|
||||||
|
|
||||||
|
sdl_devices_count = SDL_GetNumAudioDevices(0);
|
||||||
|
|
||||||
|
devices.push_back({_("Default device"), _("Default device")});
|
||||||
|
|
||||||
|
for (int i = 0; i < sdl_devices_count; i++)
|
||||||
|
{
|
||||||
|
devs = SDL_GetAudioDeviceName(i, 0);
|
||||||
|
const wxString device_name(devs, wxConvLibc);
|
||||||
|
devices.push_back({device_name, device_name});
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return devices;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<SoundDriver> CreateSDLDriver() {
|
||||||
|
winlog("newSDL\n");
|
||||||
|
return std::make_unique<SDLAudio>();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace audio
|
|
@ -0,0 +1,18 @@
|
||||||
|
#ifndef WX_AUDIO_INTERNAL_SDL_H_
|
||||||
|
#define WX_AUDIO_INTERNAL_SDL_H_
|
||||||
|
|
||||||
|
#include "wx/audio/audio.h"
|
||||||
|
|
||||||
|
namespace audio {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
// Returns the set of OpenAL devices.
|
||||||
|
std::vector<AudioDevice> GetSDLDevices();
|
||||||
|
|
||||||
|
// Creates an OpenAL sound driver.
|
||||||
|
std::unique_ptr<SoundDriver> CreateSDLDriver();
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
} // namespace audio
|
||||||
|
|
||||||
|
#endif // WX_AUDIO_INTERNAL_SDL_H_
|
|
@ -2134,6 +2134,9 @@ EVT_HANDLER_MASK(DisplayConfigure, "Display options...", CMDEN_NREC_ANY)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint32_t bitdepth = OPTION(kBitDepth);
|
||||||
|
systemColorDepth = (int)((bitdepth + 1) << 3);
|
||||||
|
|
||||||
const int frame_skip = OPTION(kPrefFrameSkip);
|
const int frame_skip = OPTION(kPrefFrameSkip);
|
||||||
if (frame_skip != -1) {
|
if (frame_skip != -1) {
|
||||||
systemFrameSkip = frame_skip;
|
systemFrameSkip = frame_skip;
|
||||||
|
@ -2381,6 +2384,11 @@ EVT_HANDLER(NoStatusMsg, "Disable on-screen status messages")
|
||||||
GetMenuOptionConfig("NoStatusMsg", config::OptionID::kPrefDisableStatus);
|
GetMenuOptionConfig("NoStatusMsg", config::OptionID::kPrefDisableStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EVT_HANDLER(BitDepth, "Bit depth")
|
||||||
|
{
|
||||||
|
GetMenuOptionConfig("BitDepth", config::OptionID::kBitDepth);
|
||||||
|
}
|
||||||
|
|
||||||
EVT_HANDLER(FrameSkipAuto, "Auto Skip frames.")
|
EVT_HANDLER(FrameSkipAuto, "Auto Skip frames.")
|
||||||
{
|
{
|
||||||
GetMenuOptionConfig("FrameSkipAuto", config::OptionID::kPrefAutoFrameSkip);
|
GetMenuOptionConfig("FrameSkipAuto", config::OptionID::kPrefAutoFrameSkip);
|
||||||
|
|
|
@ -72,10 +72,14 @@ static const std::array<wxString, kNbInterframes> kInterframeStrings = {
|
||||||
static const std::array<wxString, kNbRenderMethods> kRenderMethodStrings = {
|
static const std::array<wxString, kNbRenderMethods> kRenderMethodStrings = {
|
||||||
"simple",
|
"simple",
|
||||||
"opengl",
|
"opengl",
|
||||||
|
"sdl_video",
|
||||||
#if defined(__WXMSW__) && !defined(NO_D3D)
|
#if defined(__WXMSW__) && !defined(NO_D3D)
|
||||||
"direct3d",
|
"direct3d",
|
||||||
#elif defined(__WXMAC__)
|
#elif defined(__WXMAC__)
|
||||||
"quartz2d",
|
"quartz2d",
|
||||||
|
#ifndef NO_METAL
|
||||||
|
"metal",
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -84,6 +88,7 @@ static const std::array<wxString, kNbRenderMethods> kRenderMethodStrings = {
|
||||||
// error since kNbAudioApis is automatically updated.
|
// error since kNbAudioApis is automatically updated.
|
||||||
static const std::array<wxString, kNbAudioApis> kAudioApiStrings = {
|
static const std::array<wxString, kNbAudioApis> kAudioApiStrings = {
|
||||||
"openal",
|
"openal",
|
||||||
|
"sdl_audio",
|
||||||
#if defined(__WXMSW__)
|
#if defined(__WXMSW__)
|
||||||
"directsound",
|
"directsound",
|
||||||
#endif
|
#endif
|
||||||
|
@ -137,10 +142,16 @@ std::array<Option, kNbOptions>& Option::All() {
|
||||||
Interframe interframe = Interframe::kNone;
|
Interframe interframe = Interframe::kNone;
|
||||||
bool keep_on_top = false;
|
bool keep_on_top = false;
|
||||||
int32_t max_threads = 0;
|
int32_t max_threads = 0;
|
||||||
|
|
||||||
|
#if defined(__WXMAC__) && !defined(NO_METAL)
|
||||||
|
RenderMethod render_method = RenderMethod::kMetal;
|
||||||
|
#else
|
||||||
#if defined(NO_OGL)
|
#if defined(NO_OGL)
|
||||||
RenderMethod render_method = RenderMethod::kSimple;
|
//RenderMethod render_method = RenderMethod::kSimple;
|
||||||
|
RenderMethod render_method = RenderMethod::kSDL;
|
||||||
#else
|
#else
|
||||||
RenderMethod render_method = RenderMethod::kOpenGL;
|
RenderMethod render_method = RenderMethod::kOpenGL;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
double video_scale = 3;
|
double video_scale = 3;
|
||||||
bool retain_aspect = true;
|
bool retain_aspect = true;
|
||||||
|
@ -228,6 +239,8 @@ std::array<Option, kNbOptions>& Option::All() {
|
||||||
bool dsound_hw_accel = false;
|
bool dsound_hw_accel = false;
|
||||||
bool upmix = false;
|
bool upmix = false;
|
||||||
int32_t volume = 100;
|
int32_t volume = 100;
|
||||||
|
uint32_t bitdepth = 3;
|
||||||
|
wxString sdlrenderer = wxString("default");
|
||||||
};
|
};
|
||||||
static OwnedOptions g_owned_opts;
|
static OwnedOptions g_owned_opts;
|
||||||
|
|
||||||
|
@ -243,11 +256,13 @@ std::array<Option, kNbOptions>& Option::All() {
|
||||||
Option(OptionID::kDispFilter, &g_owned_opts.filter),
|
Option(OptionID::kDispFilter, &g_owned_opts.filter),
|
||||||
Option(OptionID::kDispFilterPlugin, &g_owned_opts.filter_plugin),
|
Option(OptionID::kDispFilterPlugin, &g_owned_opts.filter_plugin),
|
||||||
Option(OptionID::kDispIFB, &g_owned_opts.interframe),
|
Option(OptionID::kDispIFB, &g_owned_opts.interframe),
|
||||||
|
Option(OptionID::kBitDepth, &g_owned_opts.bitdepth, 0, 3),
|
||||||
Option(OptionID::kDispKeepOnTop, &g_owned_opts.keep_on_top),
|
Option(OptionID::kDispKeepOnTop, &g_owned_opts.keep_on_top),
|
||||||
Option(OptionID::kDispMaxThreads, &g_owned_opts.max_threads, 0, 256),
|
Option(OptionID::kDispMaxThreads, &g_owned_opts.max_threads, 0, 256),
|
||||||
Option(OptionID::kDispRenderMethod, &g_owned_opts.render_method),
|
Option(OptionID::kDispRenderMethod, &g_owned_opts.render_method),
|
||||||
Option(OptionID::kDispScale, &g_owned_opts.video_scale, 1, 6),
|
Option(OptionID::kDispScale, &g_owned_opts.video_scale, 1, 6),
|
||||||
Option(OptionID::kDispStretch, &g_owned_opts.retain_aspect),
|
Option(OptionID::kDispStretch, &g_owned_opts.retain_aspect),
|
||||||
|
Option(OptionID::kSDLRenderer, &g_owned_opts.sdlrenderer),
|
||||||
|
|
||||||
/// GB
|
/// GB
|
||||||
Option(OptionID::kGBBiosFile, &g_owned_opts.gb_bios),
|
Option(OptionID::kGBBiosFile, &g_owned_opts.gb_bios),
|
||||||
|
@ -383,6 +398,7 @@ const std::array<OptionData, kNbOptions + 1> kAllOptionsData = {
|
||||||
OptionData{"Display/Filter", "", _("Full-screen filter to apply")},
|
OptionData{"Display/Filter", "", _("Full-screen filter to apply")},
|
||||||
OptionData{"Display/FilterPlugin", "", _("Filter plugin library")},
|
OptionData{"Display/FilterPlugin", "", _("Filter plugin library")},
|
||||||
OptionData{"Display/IFB", "", _("Interframe blending function")},
|
OptionData{"Display/IFB", "", _("Interframe blending function")},
|
||||||
|
OptionData{"Display/BitDepth", "BitDepth", _("Bit depth")},
|
||||||
OptionData{"Display/KeepOnTop", "KeepOnTop", _("Keep window on top")},
|
OptionData{"Display/KeepOnTop", "KeepOnTop", _("Keep window on top")},
|
||||||
OptionData{"Display/MaxThreads", "Multithread",
|
OptionData{"Display/MaxThreads", "Multithread",
|
||||||
_("Maximum number of threads to run filters in")},
|
_("Maximum number of threads to run filters in")},
|
||||||
|
@ -390,6 +406,7 @@ const std::array<OptionData, kNbOptions + 1> kAllOptionsData = {
|
||||||
_("Render method; if unsupported, simple method will be used")},
|
_("Render method; if unsupported, simple method will be used")},
|
||||||
OptionData{"Display/Scale", "", _("Default scale factor")},
|
OptionData{"Display/Scale", "", _("Default scale factor")},
|
||||||
OptionData{"Display/Stretch", "RetainAspect", _("Retain aspect ratio when resizing")},
|
OptionData{"Display/Stretch", "RetainAspect", _("Retain aspect ratio when resizing")},
|
||||||
|
OptionData{"Display/SDLRenderer", "", _("SDL renderer")},
|
||||||
|
|
||||||
/// GB
|
/// GB
|
||||||
OptionData{"GB/BiosFile", "", _("BIOS file to use for Game Boy, if enabled")},
|
OptionData{"GB/BiosFile", "", _("BIOS file to use for Game Boy, if enabled")},
|
||||||
|
|
|
@ -11,11 +11,13 @@ enum class OptionID {
|
||||||
kDispFilter,
|
kDispFilter,
|
||||||
kDispFilterPlugin,
|
kDispFilterPlugin,
|
||||||
kDispIFB,
|
kDispIFB,
|
||||||
|
kBitDepth,
|
||||||
kDispKeepOnTop,
|
kDispKeepOnTop,
|
||||||
kDispMaxThreads,
|
kDispMaxThreads,
|
||||||
kDispRenderMethod,
|
kDispRenderMethod,
|
||||||
kDispScale,
|
kDispScale,
|
||||||
kDispStretch,
|
kDispStretch,
|
||||||
|
kSDLRenderer,
|
||||||
|
|
||||||
/// GB
|
/// GB
|
||||||
kGBBiosFile,
|
kGBBiosFile,
|
||||||
|
|
|
@ -15,11 +15,13 @@ static constexpr std::array<Option::Type, kNbOptions> kOptionsTypes = {
|
||||||
/*kDispFilter*/ Option::Type::kFilter,
|
/*kDispFilter*/ Option::Type::kFilter,
|
||||||
/*kDispFilterPlugin*/ Option::Type::kString,
|
/*kDispFilterPlugin*/ Option::Type::kString,
|
||||||
/*kDispIFB*/ Option::Type::kInterframe,
|
/*kDispIFB*/ Option::Type::kInterframe,
|
||||||
|
/*kBitDepth*/ Option::Type::kUnsigned,
|
||||||
/*kDispKeepOnTop*/ Option::Type::kBool,
|
/*kDispKeepOnTop*/ Option::Type::kBool,
|
||||||
/*kDispMaxThreads*/ Option::Type::kInt,
|
/*kDispMaxThreads*/ Option::Type::kInt,
|
||||||
/*kDispRenderMethod*/ Option::Type::kRenderMethod,
|
/*kDispRenderMethod*/ Option::Type::kRenderMethod,
|
||||||
/*kDispScale*/ Option::Type::kDouble,
|
/*kDispScale*/ Option::Type::kDouble,
|
||||||
/*kDispStretch*/ Option::Type::kBool,
|
/*kDispStretch*/ Option::Type::kBool,
|
||||||
|
/*kSDLRenderer*/ Option::Type::kString,
|
||||||
|
|
||||||
/// GB
|
/// GB
|
||||||
/*kGBBiosFile*/ Option::Type::kString,
|
/*kGBBiosFile*/ Option::Type::kString,
|
||||||
|
|
|
@ -268,6 +268,9 @@ TEST(OptionTest, Enum) {
|
||||||
EXPECT_TRUE(option->SetRenderMethod(config::RenderMethod::kSimple));
|
EXPECT_TRUE(option->SetRenderMethod(config::RenderMethod::kSimple));
|
||||||
EXPECT_EQ(option->GetRenderMethod(), config::RenderMethod::kSimple);
|
EXPECT_EQ(option->GetRenderMethod(), config::RenderMethod::kSimple);
|
||||||
|
|
||||||
|
EXPECT_TRUE(option->SetRenderMethod(config::RenderMethod::kSDL));
|
||||||
|
EXPECT_EQ(option->GetRenderMethod(), config::RenderMethod::kSDL);
|
||||||
|
|
||||||
EXPECT_TRUE(option->SetEnumString("opengl"));
|
EXPECT_TRUE(option->SetEnumString("opengl"));
|
||||||
EXPECT_EQ(option->GetRenderMethod(), config::RenderMethod::kOpenGL);
|
EXPECT_EQ(option->GetRenderMethod(), config::RenderMethod::kOpenGL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,10 +66,14 @@ static constexpr size_t kNbInterframes = static_cast<size_t>(Interframe::kLast);
|
||||||
enum class RenderMethod {
|
enum class RenderMethod {
|
||||||
kSimple = 0,
|
kSimple = 0,
|
||||||
kOpenGL,
|
kOpenGL,
|
||||||
|
kSDL,
|
||||||
#if defined(__WXMSW__) && !defined(NO_D3D)
|
#if defined(__WXMSW__) && !defined(NO_D3D)
|
||||||
kDirect3d,
|
kDirect3d,
|
||||||
#elif defined(__WXMAC__)
|
#elif defined(__WXMAC__)
|
||||||
kQuartz2d,
|
kQuartz2d,
|
||||||
|
#ifndef NO_METAL
|
||||||
|
kMetal,
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Do not add anything under here.
|
// Do not add anything under here.
|
||||||
|
@ -80,6 +84,7 @@ static constexpr size_t kNbRenderMethods = static_cast<size_t>(RenderMethod::kLa
|
||||||
// Values for kAudioApi.
|
// Values for kAudioApi.
|
||||||
enum class AudioApi {
|
enum class AudioApi {
|
||||||
kOpenAL,
|
kOpenAL,
|
||||||
|
kSDL,
|
||||||
#if defined(__WXMSW__)
|
#if defined(__WXMSW__)
|
||||||
kDirectSound,
|
kDirectSound,
|
||||||
#endif // __WXMSW__
|
#endif // __WXMSW__
|
||||||
|
|
|
@ -22,10 +22,58 @@
|
||||||
#include "wx/widgets/render-plugin.h"
|
#include "wx/widgets/render-plugin.h"
|
||||||
#include "wx/wxvbam.h"
|
#include "wx/wxvbam.h"
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#else
|
||||||
|
#include <SDL.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace dialogs {
|
namespace dialogs {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
class SDLDevicesValidator : public widgets::OptionValidator {
|
||||||
|
public:
|
||||||
|
SDLDevicesValidator() : widgets::OptionValidator(config::OptionID::kSDLRenderer) {}
|
||||||
|
~SDLDevicesValidator() override = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// OptionValidator implementation.
|
||||||
|
wxObject* Clone() const override { return new SDLDevicesValidator(); }
|
||||||
|
|
||||||
|
bool IsWindowValueValid() override { return true; }
|
||||||
|
|
||||||
|
bool WriteToWindow() override {
|
||||||
|
wxChoice* choice = wxDynamicCast(GetWindow(), wxChoice);
|
||||||
|
VBAM_CHECK(choice);
|
||||||
|
|
||||||
|
const wxString& device_id = option()->GetString();
|
||||||
|
for (size_t i = 0; i < choice->GetCount(); i++) {
|
||||||
|
const wxString& choide_id =
|
||||||
|
dynamic_cast<wxStringClientData*>(choice->GetClientObject(i))->GetData();
|
||||||
|
if (device_id == choide_id) {
|
||||||
|
choice->SetSelection(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
choice->SetSelection(0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WriteToOption() override {
|
||||||
|
const wxChoice* choice = wxDynamicCast(GetWindow(), wxChoice);
|
||||||
|
VBAM_CHECK(choice);
|
||||||
|
const int selection = choice->GetSelection();
|
||||||
|
if (selection == wxNOT_FOUND) {
|
||||||
|
return option()->SetString(wxEmptyString);
|
||||||
|
}
|
||||||
|
|
||||||
|
return option()->SetString(
|
||||||
|
dynamic_cast<wxStringClientData*>(choice->GetClientObject(selection))->GetData());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Custom validator for the kDispScale option. We rely on the existing
|
// Custom validator for the kDispScale option. We rely on the existing
|
||||||
// wxFloatingPointValidator validator for this.
|
// wxFloatingPointValidator validator for this.
|
||||||
class ScaleValidator : public wxFloatingPointValidator<double>,
|
class ScaleValidator : public wxFloatingPointValidator<double>,
|
||||||
|
@ -234,6 +282,10 @@ DisplayConfig::DisplayConfig(wxWindow* parent)
|
||||||
std::bind(&DisplayConfig::OnInterframeChanged,
|
std::bind(&DisplayConfig::OnInterframeChanged,
|
||||||
this,
|
this,
|
||||||
std::placeholders::_1)) {
|
std::placeholders::_1)) {
|
||||||
|
GetValidatedChild("BitDepth")
|
||||||
|
->SetValidator(
|
||||||
|
widgets::OptionChoiceValidator(config::OptionID::kBitDepth));
|
||||||
|
|
||||||
// Speed
|
// Speed
|
||||||
GetValidatedChild("FrameSkip")
|
GetValidatedChild("FrameSkip")
|
||||||
->SetValidator(
|
->SetValidator(
|
||||||
|
@ -253,14 +305,24 @@ DisplayConfig::DisplayConfig(wxWindow* parent)
|
||||||
->SetValidator(wxGenericValidator(&gopts.max_scale));
|
->SetValidator(wxGenericValidator(&gopts.max_scale));
|
||||||
|
|
||||||
// Basic
|
// Basic
|
||||||
GetValidatedChild("OutputSimple")
|
wxWindow *render_method = GetValidatedChild("OutputSimple");
|
||||||
->SetValidator(RenderValidator(config::RenderMethod::kSimple));
|
render_method->SetValidator(RenderValidator(config::RenderMethod::kSimple));
|
||||||
|
|
||||||
|
render_method = GetValidatedChild("OutputSDL");
|
||||||
|
render_method->SetValidator(RenderValidator(config::RenderMethod::kSDL));
|
||||||
|
|
||||||
#if defined(__WXMAC__)
|
#if defined(__WXMAC__)
|
||||||
GetValidatedChild("OutputQuartz2D")
|
render_method = GetValidatedChild("OutputQuartz2D");
|
||||||
->SetValidator(RenderValidator(config::RenderMethod::kQuartz2d));
|
render_method->SetValidator(RenderValidator(config::RenderMethod::kQuartz2d));
|
||||||
|
#ifndef NO_METAL
|
||||||
|
render_method = GetValidatedChild("OutputMetal");
|
||||||
|
render_method->SetValidator(RenderValidator(config::RenderMethod::kMetal));
|
||||||
|
#else
|
||||||
|
GetValidatedChild("OutputMetal")->Hide();
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
GetValidatedChild("OutputQuartz2D")->Hide();
|
GetValidatedChild("OutputQuartz2D")->Hide();
|
||||||
|
GetValidatedChild("OutputMetal")->Hide();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef NO_OGL
|
#ifdef NO_OGL
|
||||||
|
@ -270,22 +332,25 @@ DisplayConfig::DisplayConfig(wxWindow* parent)
|
||||||
if (IsWayland()) {
|
if (IsWayland()) {
|
||||||
GetValidatedChild("OutputOpenGL")->Hide();
|
GetValidatedChild("OutputOpenGL")->Hide();
|
||||||
} else {
|
} else {
|
||||||
GetValidatedChild("OutputOpenGL")
|
render_method = GetValidatedChild("OutputOpenGL");
|
||||||
->SetValidator(RenderValidator(config::RenderMethod::kOpenGL));
|
render_method->SetValidator(RenderValidator(config::RenderMethod::kOpenGL));
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
GetValidatedChild("OutputOpenGL")
|
render_method = GetValidatedChild("OutputOpenGL");
|
||||||
->SetValidator(RenderValidator(config::RenderMethod::kOpenGL));
|
render_method->SetValidator(RenderValidator(config::RenderMethod::kOpenGL));
|
||||||
#endif // NO_OGL
|
#endif // NO_OGL
|
||||||
|
|
||||||
#if defined(__WXMSW__) && !defined(NO_D3D)
|
#if defined(__WXMSW__) && !defined(NO_D3D)
|
||||||
// Enable the Direct3D option on Windows.
|
// Enable the Direct3D option on Windows.
|
||||||
GetValidatedChild("OutputDirect3D")
|
render_method = GetValidatedChild("OutputDirect3D");
|
||||||
->SetValidator(RenderValidator(config::RenderMethod::kDirect3d));
|
render_method->SetValidator(RenderValidator(config::RenderMethod::kDirect3d));
|
||||||
#else
|
#else
|
||||||
GetValidatedChild("OutputDirect3D")->Hide();
|
GetValidatedChild("OutputDirect3D")->Hide();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
sdlrenderer_selector_ = GetValidatedChild<wxChoice>("SDLRenderer");
|
||||||
|
sdlrenderer_selector_->SetValidator(SDLDevicesValidator());
|
||||||
|
|
||||||
filter_selector_ = GetValidatedChild<wxChoice>("Filter");
|
filter_selector_ = GetValidatedChild<wxChoice>("Filter");
|
||||||
filter_selector_->SetValidator(FilterValidator());
|
filter_selector_->SetValidator(FilterValidator());
|
||||||
filter_selector_->Bind(wxEVT_CHOICE, &DisplayConfig::UpdatePlugin, this,
|
filter_selector_->Bind(wxEVT_CHOICE, &DisplayConfig::UpdatePlugin, this,
|
||||||
|
@ -305,12 +370,16 @@ DisplayConfig::DisplayConfig(wxWindow* parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayConfig::OnDialogShowEvent(wxShowEvent& event) {
|
void DisplayConfig::OnDialogShowEvent(wxShowEvent& event) {
|
||||||
|
wxCommandEvent dummy_event;
|
||||||
|
|
||||||
if (event.IsShown()) {
|
if (event.IsShown()) {
|
||||||
PopulatePluginOptions();
|
PopulatePluginOptions();
|
||||||
} else {
|
} else {
|
||||||
StopPluginHandler();
|
StopPluginHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FillRendererList(dummy_event);
|
||||||
|
|
||||||
// Let the event propagate.
|
// Let the event propagate.
|
||||||
event.Skip();
|
event.Skip();
|
||||||
}
|
}
|
||||||
|
@ -415,6 +484,43 @@ void DisplayConfig::OnInterframeChanged(config::Option* option) {
|
||||||
interframe_selector_->GetString(static_cast<size_t>(interframe))));
|
interframe_selector_->GetString(static_cast<size_t>(interframe))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DisplayConfig::FillRendererList(wxCommandEvent& event) {
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
|
SDL_RendererInfo render_info;
|
||||||
|
#endif
|
||||||
|
int num_drivers = 0;
|
||||||
|
|
||||||
|
SDL_InitSubSystem(SDL_INIT_VIDEO);
|
||||||
|
SDL_Init(SDL_INIT_VIDEO);
|
||||||
|
|
||||||
|
num_drivers = SDL_GetNumRenderDrivers();
|
||||||
|
|
||||||
|
sdlrenderer_selector_->Clear();
|
||||||
|
sdlrenderer_selector_->Append("default", new wxStringClientData("default"));
|
||||||
|
sdlrenderer_selector_->SetSelection(0);
|
||||||
|
|
||||||
|
for (int i = 0; i < num_drivers; i++) {
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
sdlrenderer_selector_->Append(SDL_GetRenderDriver(i), new wxStringClientData(SDL_GetRenderDriver(i)));
|
||||||
|
|
||||||
|
if (OPTION(kSDLRenderer) == wxString(SDL_GetRenderDriver(i))) {
|
||||||
|
sdlrenderer_selector_->SetSelection(i+1);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
SDL_GetRenderDriverInfo(i, &render_info);
|
||||||
|
|
||||||
|
sdlrenderer_selector_->Append(render_info.name, new wxStringClientData(render_info.name));
|
||||||
|
|
||||||
|
if (OPTION(kSDLRenderer) == wxString(render_info.name)) {
|
||||||
|
sdlrenderer_selector_->SetSelection(i+1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let the event propagate.
|
||||||
|
event.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
void DisplayConfig::HidePluginOptions() {
|
void DisplayConfig::HidePluginOptions() {
|
||||||
plugin_label_->Hide();
|
plugin_label_->Hide();
|
||||||
plugin_selector_->Hide();
|
plugin_selector_->Hide();
|
||||||
|
|
|
@ -45,6 +45,9 @@ private:
|
||||||
// Displays the new interframe name on the screen.
|
// Displays the new interframe name on the screen.
|
||||||
void OnInterframeChanged(config::Option* option);
|
void OnInterframeChanged(config::Option* option);
|
||||||
|
|
||||||
|
// Renderer changed
|
||||||
|
void FillRendererList(wxCommandEvent& event);
|
||||||
|
|
||||||
// Hides/Shows the plugin-related filter options.
|
// Hides/Shows the plugin-related filter options.
|
||||||
void HidePluginOptions();
|
void HidePluginOptions();
|
||||||
void ShowPluginOptions();
|
void ShowPluginOptions();
|
||||||
|
@ -53,6 +56,7 @@ private:
|
||||||
wxChoice* plugin_selector_;
|
wxChoice* plugin_selector_;
|
||||||
wxChoice* filter_selector_;
|
wxChoice* filter_selector_;
|
||||||
wxChoice* interframe_selector_;
|
wxChoice* interframe_selector_;
|
||||||
|
wxChoice* sdlrenderer_selector_;
|
||||||
const config::OptionsObserver filter_observer_;
|
const config::OptionsObserver filter_observer_;
|
||||||
const config::OptionsObserver interframe_observer_;
|
const config::OptionsObserver interframe_observer_;
|
||||||
};
|
};
|
||||||
|
|
|
@ -158,6 +158,12 @@ SoundConfig::SoundConfig(wxWindow* parent) : BaseDialog(parent, "SoundConfig") {
|
||||||
std::bind(&SoundConfig::OnAudioApiChanged, this, std::placeholders::_1,
|
std::bind(&SoundConfig::OnAudioApiChanged, this, std::placeholders::_1,
|
||||||
config::AudioApi::kOpenAL));
|
config::AudioApi::kOpenAL));
|
||||||
|
|
||||||
|
audio_api_button = GetValidatedChild("SDL");
|
||||||
|
audio_api_button->SetValidator(AudioApiValidator(config::AudioApi::kSDL));
|
||||||
|
audio_api_button->Bind(wxEVT_RADIOBUTTON,
|
||||||
|
std::bind(&SoundConfig::OnAudioApiChanged, this, std::placeholders::_1,
|
||||||
|
config::AudioApi::kSDL));
|
||||||
|
|
||||||
audio_api_button = GetValidatedChild("DirectSound");
|
audio_api_button = GetValidatedChild("DirectSound");
|
||||||
#if defined(__WXMSW__)
|
#if defined(__WXMSW__)
|
||||||
audio_api_button->SetValidator(AudioApiValidator(config::AudioApi::kDirectSound));
|
audio_api_button->SetValidator(AudioApiValidator(config::AudioApi::kDirectSound));
|
||||||
|
|
|
@ -49,6 +49,26 @@ protected:
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
class SDLDrawingPanel : public DrawingPanel {
|
||||||
|
public:
|
||||||
|
SDLDrawingPanel(wxWindow* parent, int _width, int _height);
|
||||||
|
virtual ~SDLDrawingPanel();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void DrawArea();
|
||||||
|
void DrawArea(uint8_t** data);
|
||||||
|
void DrawArea(wxWindowDC&) override;
|
||||||
|
void PaintEv(wxPaintEvent& ev) override;
|
||||||
|
void EraseBackground(wxEraseEvent& ev) override;
|
||||||
|
void OnSize(wxSizeEvent& ev) override;
|
||||||
|
void DrawingPanelInit() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SDL_Window *sdlwindow;
|
||||||
|
SDL_Texture *texture;
|
||||||
|
SDL_Renderer *renderer;
|
||||||
|
};
|
||||||
|
|
||||||
#if defined(__WXMSW__) && !defined(NO_D3D)
|
#if defined(__WXMSW__) && !defined(NO_D3D)
|
||||||
class DXDrawingPanel : public DrawingPanel {
|
class DXDrawingPanel : public DrawingPanel {
|
||||||
public:
|
public:
|
||||||
|
@ -60,6 +80,81 @@ protected:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__WXMAC__)
|
#if defined(__WXMAC__)
|
||||||
|
#ifndef NO_METAL
|
||||||
|
#ifdef __OBJC__
|
||||||
|
#import <Metal/Metal.h>
|
||||||
|
#import <MetalKit/MetalKit.h>
|
||||||
|
#import <CoreGraphics/CoreGraphics.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <simd/simd.h>
|
||||||
|
|
||||||
|
typedef enum AAPLVertexInputIndex
|
||||||
|
{
|
||||||
|
AAPLVertexInputIndexVertices = 0,
|
||||||
|
AAPLVertexInputIndexViewportSize = 1,
|
||||||
|
} AAPLVertexInputIndex;
|
||||||
|
|
||||||
|
// Texture index values shared between shader and C code to ensure Metal shader buffer inputs match
|
||||||
|
// Metal API texture set calls
|
||||||
|
typedef enum AAPLTextureIndex
|
||||||
|
{
|
||||||
|
AAPLTextureIndexBaseColor = 0,
|
||||||
|
} AAPLTextureIndex;
|
||||||
|
|
||||||
|
// This structure defines the layout of each vertex in the array of vertices set as an input to the
|
||||||
|
// Metal vertex shader. Since this header is shared between the .metal shader and C code,
|
||||||
|
// you can be sure that the layout of the vertex array in the code matches the layout that
|
||||||
|
// the vertex shader expects
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
// Positions in pixel space. A value of 100 indicates 100 pixels from the origin/center.
|
||||||
|
vector_float2 position;
|
||||||
|
|
||||||
|
// 2D texture coordinate
|
||||||
|
vector_float2 textureCoordinate;
|
||||||
|
} AAPLVertex;
|
||||||
|
|
||||||
|
bool is_macosx_1012_or_newer();
|
||||||
|
|
||||||
|
class MetalDrawingPanel : public DrawingPanel {
|
||||||
|
public:
|
||||||
|
MetalDrawingPanel(wxWindow* parent, int _width, int _height);
|
||||||
|
virtual ~MetalDrawingPanel();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void DrawArea();
|
||||||
|
void DrawArea(uint8_t** data);
|
||||||
|
void DrawArea(wxWindowDC&) override;
|
||||||
|
void PaintEv(wxPaintEvent& ev) override;
|
||||||
|
void EraseBackground(wxEraseEvent& ev) override;
|
||||||
|
void OnSize(wxSizeEvent& ev) override;
|
||||||
|
void DrawingPanelInit() override;
|
||||||
|
|
||||||
|
#ifdef __OBJC__
|
||||||
|
private:
|
||||||
|
void CreateMetalView();
|
||||||
|
id<MTLTexture> loadTextureUsingData(void *data);
|
||||||
|
|
||||||
|
NSView *view;
|
||||||
|
MTKView *metalView;
|
||||||
|
NSRect metalFrame;
|
||||||
|
MTLRenderPassDescriptor *renderPassDescriptor;
|
||||||
|
id<MTLRenderCommandEncoder> renderEncoder;
|
||||||
|
id<MTLCommandBuffer> commandBuffer;
|
||||||
|
id<MTLDevice> _device;
|
||||||
|
id<MTLCommandQueue> _commandQueue;
|
||||||
|
id<MTLRenderPipelineState> _pipelineState;
|
||||||
|
id<MTLTexture> _texture;
|
||||||
|
id<MTLBuffer> _vertices;
|
||||||
|
NSUInteger _numVertices;
|
||||||
|
vector_uint2 _viewportSize;
|
||||||
|
vector_uint2 _contentSize;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
class Quartz2DDrawingPanel : public BasicDrawingPanel {
|
class Quartz2DDrawingPanel : public BasicDrawingPanel {
|
||||||
public:
|
public:
|
||||||
Quartz2DDrawingPanel(wxWindow* parent, int _width, int _height);
|
Quartz2DDrawingPanel(wxWindow* parent, int _width, int _height);
|
||||||
|
|
|
@ -11,12 +11,37 @@
|
||||||
#include "wx/viewsupt.h"
|
#include "wx/viewsupt.h"
|
||||||
#include "wx/wxvbam.h"
|
#include "wx/wxvbam.h"
|
||||||
|
|
||||||
|
#if __STDC_WANT_SECURE_LIB__
|
||||||
|
#define snprintf sprintf_s
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
void utilReadScreenPixels(uint8_t* dest, int w, int h) {
|
void utilReadScreenPixels(uint8_t* dest, int w, int h) {
|
||||||
uint8_t* b = dest;
|
uint8_t* b = dest;
|
||||||
int sizeX = w;
|
int sizeX = w;
|
||||||
int sizeY = h;
|
int sizeY = h;
|
||||||
switch (systemColorDepth) {
|
switch (systemColorDepth) {
|
||||||
|
case 8: {
|
||||||
|
uint8_t* p = (uint8_t*)(g_pix + (w + 2)); // skip first black line
|
||||||
|
for (int y = 0; y < sizeY; y++) {
|
||||||
|
for (int x = 0; x < sizeX; x++) {
|
||||||
|
uint8_t v = *p++;
|
||||||
|
|
||||||
|
// White color fix
|
||||||
|
if (v == 0xff) {
|
||||||
|
*b++ = 0xff;
|
||||||
|
*b++ = 0xff;
|
||||||
|
*b++ = 0xff;
|
||||||
|
} else {
|
||||||
|
*b++ = (((v >> 5) & 0x7) << 5);
|
||||||
|
*b++ = (((v >> 2) & 0x7) << 5);
|
||||||
|
*b++ = ((v & 0x3) << 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p++; // skip black pixel for filters
|
||||||
|
p++; // skip black pixel for filters
|
||||||
|
}
|
||||||
|
} break;
|
||||||
case 16: {
|
case 16: {
|
||||||
uint16_t* p = (uint16_t*)(g_pix + (w + 2) * 2); // skip first black line
|
uint16_t* p = (uint16_t*)(g_pix + (w + 2) * 2); // skip first black line
|
||||||
for (int y = 0; y < sizeY; y++) {
|
for (int y = 0; y < sizeY; y++) {
|
||||||
|
@ -928,8 +953,9 @@ public:
|
||||||
|
|
||||||
for (int y = 0; y < sizeY; y++) {
|
for (int y = 0; y < sizeY; y++) {
|
||||||
for (int x = 0; x < sizeX; x++) {
|
for (int x = 0; x < sizeX; x++) {
|
||||||
uint32_t color = g_vram[0x10000 + (((c + (y >> 3) * inc) * 32 + (y & 7) * 8 + (x >> 3) * 64 + (x & 7)) & 0x7FFF)];
|
uint32_t color = g_vram[0x10000 + (((c + (((y >> 3) * inc) << 5) + ((y & 7) << 4) + ((x >> 3) << 6) + (x & 7))) & 0x7FFF)];
|
||||||
color = pal[color];
|
color = pal[color];
|
||||||
|
|
||||||
*bmp++ = (color & 0x1f) << 3;
|
*bmp++ = (color & 0x1f) << 3;
|
||||||
*bmp++ = ((color >> 5) & 0x1f) << 3;
|
*bmp++ = ((color >> 5) & 0x1f) << 3;
|
||||||
*bmp++ = ((color >> 10) & 0x1f) << 3;
|
*bmp++ = ((color >> 10) & 0x1f) << 3;
|
||||||
|
@ -950,7 +976,7 @@ public:
|
||||||
|
|
||||||
for (int y = 0; y < sizeY; y++) {
|
for (int y = 0; y < sizeY; y++) {
|
||||||
for (int x = 0; x < sizeX; x++) {
|
for (int x = 0; x < sizeX; x++) {
|
||||||
uint32_t color = g_vram[0x10000 + (((c + (y >> 3) * inc) * 32 + (y & 7) * 4 + (x >> 3) * 32 + ((x & 7) >> 1)) & 0x7FFF)];
|
uint32_t color = g_vram[0x10000 + ((((((c + (((y >> 3) * inc) << 5)) + ((y & 7) << 2)) + ((x >> 3) << 5)) + ((x & 7) >> 1))) & 0x7FFF)];
|
||||||
|
|
||||||
if (x & 1)
|
if (x & 1)
|
||||||
color >>= 4;
|
color >>= 4;
|
||||||
|
@ -958,6 +984,7 @@ public:
|
||||||
color &= 0x0F;
|
color &= 0x0F;
|
||||||
|
|
||||||
color = pal[palette + color];
|
color = pal[palette + color];
|
||||||
|
|
||||||
*bmp++ = (color & 0x1f) << 3;
|
*bmp++ = (color & 0x1f) << 3;
|
||||||
*bmp++ = ((color >> 5) & 0x1f) << 3;
|
*bmp++ = ((color >> 5) & 0x1f) << 3;
|
||||||
*bmp++ = ((color >> 10) & 0x1f) << 3;
|
*bmp++ = ((color >> 10) & 0x1f) << 3;
|
||||||
|
@ -1246,7 +1273,7 @@ void savepal(wxWindow* parent, const uint8_t* data, int ncols, const wxString ty
|
||||||
|
|
||||||
for (int i = 0; i < ncols; i++, data += 3) {
|
for (int i = 0; i < ncols; i++, data += 3) {
|
||||||
char buf[14];
|
char buf[14];
|
||||||
int l = sprintf(buf, "%d %d %d\r\n", data[0], data[1], data[2]);
|
int l = snprintf(buf, sizeof(buf), "%d %d %d\r\n", data[0], data[1], data[2]);
|
||||||
f.Write(buf, l);
|
f.Write(buf, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,410 @@
|
||||||
#include <wx/rawbmp.h>
|
#include <wx/rawbmp.h>
|
||||||
|
|
||||||
#include "wx/drawing.h"
|
#include "wx/drawing.h"
|
||||||
|
#include "wx/config/option-id.h"
|
||||||
|
#include "wx/config/option-proxy.h"
|
||||||
|
#include "wx/config/option.h"
|
||||||
#include "wx/wxvbam.h"
|
#include "wx/wxvbam.h"
|
||||||
|
|
||||||
|
#ifndef NO_METAL
|
||||||
|
bool is_macosx_1012_or_newer()
|
||||||
|
{
|
||||||
|
// Mac OS X 10.12 version check
|
||||||
|
if (NSAppKitVersionNumber >= 1504) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MetalDrawingPanel::~MetalDrawingPanel()
|
||||||
|
{
|
||||||
|
if (did_init)
|
||||||
|
{
|
||||||
|
renderPassDescriptor = nil;
|
||||||
|
commandBuffer = nil;
|
||||||
|
renderEncoder = nil;
|
||||||
|
|
||||||
|
if (metalView != nil)
|
||||||
|
[metalView removeFromSuperview];
|
||||||
|
|
||||||
|
if (_device != nil)
|
||||||
|
[_device release];
|
||||||
|
|
||||||
|
if (_commandQueue != nil)
|
||||||
|
[_commandQueue release];
|
||||||
|
|
||||||
|
if (_pipelineState != nil)
|
||||||
|
[_pipelineState release];
|
||||||
|
|
||||||
|
if (_texture != nil)
|
||||||
|
[_texture release];
|
||||||
|
|
||||||
|
if (_vertices != nil)
|
||||||
|
[_vertices release];
|
||||||
|
|
||||||
|
did_init = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetalDrawingPanel::EraseBackground(wxEraseEvent& ev)
|
||||||
|
{
|
||||||
|
(void)ev; // unused params
|
||||||
|
// do nothing, do not allow propagation
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetalDrawingPanel::CreateMetalView()
|
||||||
|
{
|
||||||
|
view = (NSView *)wxGetApp().frame->GetPanel()->GetHandle();
|
||||||
|
view.layerContentsPlacement = NSViewLayerContentsPlacementCenter;
|
||||||
|
view.layer.backgroundColor = [NSColor colorWithCalibratedRed:0.0f
|
||||||
|
green:0.0f
|
||||||
|
blue:0.0f
|
||||||
|
alpha:0.0f].CGColor;
|
||||||
|
|
||||||
|
metalView = [[MTKView alloc] init];
|
||||||
|
|
||||||
|
metalView.layer.backgroundColor = [NSColor colorWithCalibratedRed:0.0f
|
||||||
|
green:0.0f
|
||||||
|
blue:0.0f
|
||||||
|
alpha:0.0f].CGColor;
|
||||||
|
metalView.device = MTLCreateSystemDefaultDevice();
|
||||||
|
metalView.colorPixelFormat = MTLPixelFormatRGBA8Unorm;
|
||||||
|
|
||||||
|
metalView.layerContentsRedrawPolicy = NSViewLayerContentsRedrawDuringViewResize;
|
||||||
|
metalView.layerContentsPlacement = NSViewLayerContentsPlacementCenter;
|
||||||
|
metalView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||||
|
metalView.layer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable;
|
||||||
|
metalView.layer.needsDisplayOnBoundsChange = YES;
|
||||||
|
((CAMetalLayer *)metalView.layer).device = metalView.device;
|
||||||
|
|
||||||
|
_device = metalView.device;
|
||||||
|
|
||||||
|
const AAPLVertex quadVertices[] =
|
||||||
|
{
|
||||||
|
// Pixel positions, Texture coordinates
|
||||||
|
{ { (float)(width * scale), (float)-(height * scale) }, { 1.f, 1.f } },
|
||||||
|
{ { (float)-(width * scale), (float)-(height * scale) }, { 0.f, 1.f } },
|
||||||
|
{ { (float)-(width * scale), (float)(height * scale) }, { 0.f, 0.f } },
|
||||||
|
|
||||||
|
{ { (float)(width * scale), (float)-(height * scale) }, { 1.f, 1.f } },
|
||||||
|
{ { (float)-(width * scale), (float)(height * scale) }, { 0.f, 0.f } },
|
||||||
|
{ { (float)(width * scale), (float)(height * scale) }, { 1.f, 0.f } },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create a vertex buffer, and initialize it with the quadVertices array
|
||||||
|
_vertices = [_device newBufferWithBytes:quadVertices
|
||||||
|
length:sizeof(quadVertices)
|
||||||
|
options:MTLResourceStorageModeShared];
|
||||||
|
|
||||||
|
// Calculate the number of vertices by dividing the byte length by the size of each vertex
|
||||||
|
_numVertices = sizeof(quadVertices) / sizeof(AAPLVertex);
|
||||||
|
|
||||||
|
/// Create the render pipeline.
|
||||||
|
|
||||||
|
// Load the shaders from the default library
|
||||||
|
id<MTLLibrary> defaultLibrary = [_device newDefaultLibrary];
|
||||||
|
id<MTLFunction> vertexFunction = [defaultLibrary newFunctionWithName:@"vertexShader"];
|
||||||
|
id<MTLFunction> fragmentFunction = [defaultLibrary newFunctionWithName:@"samplingShader"];
|
||||||
|
|
||||||
|
// Set up a descriptor for creating a pipeline state object
|
||||||
|
MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
|
||||||
|
pipelineStateDescriptor.label = @"Texturing Pipeline";
|
||||||
|
pipelineStateDescriptor.vertexFunction = vertexFunction;
|
||||||
|
pipelineStateDescriptor.fragmentFunction = fragmentFunction;
|
||||||
|
pipelineStateDescriptor.colorAttachments[0].pixelFormat = metalView.colorPixelFormat;
|
||||||
|
|
||||||
|
NSError *error = NULL;
|
||||||
|
_pipelineState = [_device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor
|
||||||
|
error:&error];
|
||||||
|
|
||||||
|
_commandQueue = [_device newCommandQueue];
|
||||||
|
|
||||||
|
if (OPTION(kDispStretch) == false) {
|
||||||
|
metalView.frame = view.frame;
|
||||||
|
metalFrame = view.frame;
|
||||||
|
} else {
|
||||||
|
float scaleX = view.frame.size.width / (width * scale);
|
||||||
|
float scaleY = view.frame.size.height / (height * scale);
|
||||||
|
float scaleF = 0;
|
||||||
|
if (scaleX < scaleY) {
|
||||||
|
scaleF = scaleX;
|
||||||
|
} else {
|
||||||
|
scaleF = scaleY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scaleF == 0) {
|
||||||
|
scaleF = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
metalFrame.size.width = (width * scale) * scaleF;
|
||||||
|
metalFrame.size.height = (height * scale) * scaleF;
|
||||||
|
metalFrame.origin.x = (view.frame.size.width - metalFrame.size.width) / 2;
|
||||||
|
metalFrame.origin.y = (view.frame.size.height - metalFrame.size.height) / 2;
|
||||||
|
metalView.frame = metalFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
metalView.wantsLayer = YES;
|
||||||
|
metalView.layer.contentsScale = 1.0;
|
||||||
|
metalView.autoResizeDrawable = NO;
|
||||||
|
metalView.drawableSize = metalFrame.size;
|
||||||
|
((CAMetalLayer *)metalView.layer).drawableSize = metalFrame.size;
|
||||||
|
|
||||||
|
_contentSize.x = metalFrame.size.width;
|
||||||
|
_contentSize.y = metalFrame.size.height;
|
||||||
|
_viewportSize.x = width * scale;
|
||||||
|
_viewportSize.y = height * scale;
|
||||||
|
|
||||||
|
[view addSubview:metalView];
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetalDrawingPanel::DrawingPanelInit()
|
||||||
|
{
|
||||||
|
CreateMetalView();
|
||||||
|
|
||||||
|
did_init = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
id<MTLTexture> MetalDrawingPanel::loadTextureUsingData(void *data)
|
||||||
|
{
|
||||||
|
MTLTextureDescriptor *textureDescriptor = [[MTLTextureDescriptor alloc] init];
|
||||||
|
|
||||||
|
// Indicate that each pixel has a blue, green, red, and alpha channel, where each channel is
|
||||||
|
// an 8-bit unsigned normalized value (i.e. 0 maps to 0.0 and 255 maps to 1.0)
|
||||||
|
textureDescriptor.pixelFormat = metalView.colorPixelFormat;
|
||||||
|
textureDescriptor.usage = MTLTextureUsageRenderTarget;
|
||||||
|
|
||||||
|
// Set the pixel dimensions of the texture
|
||||||
|
textureDescriptor.width = width * scale;
|
||||||
|
textureDescriptor.height = height * scale;
|
||||||
|
|
||||||
|
// Create the texture from the device by using the descriptor
|
||||||
|
id<MTLTexture> texture = [_device newTextureWithDescriptor:textureDescriptor];
|
||||||
|
|
||||||
|
// Calculate the number of bytes per row in the image.
|
||||||
|
NSUInteger bytesPerRow = 0;
|
||||||
|
bytesPerRow = std::ceil((width * scale * 4) + 4);
|
||||||
|
|
||||||
|
MTLRegion region = {
|
||||||
|
{ 0, 0, 0 }, // MTLOrigin
|
||||||
|
{(NSUInteger)(width * scale), (NSUInteger)(height * scale), 1} // MTLSize
|
||||||
|
};
|
||||||
|
|
||||||
|
// Copy the bytes from the data object into the texture
|
||||||
|
[texture replaceRegion:region
|
||||||
|
mipmapLevel:0
|
||||||
|
withBytes:data
|
||||||
|
bytesPerRow:bytesPerRow];
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetalDrawingPanel::OnSize(wxSizeEvent& ev)
|
||||||
|
{
|
||||||
|
if (OPTION(kDispStretch) == false) {
|
||||||
|
metalView.frame = view.frame;
|
||||||
|
metalFrame = view.frame;
|
||||||
|
} else {
|
||||||
|
float scaleX = view.frame.size.width / (width * scale);
|
||||||
|
float scaleY = view.frame.size.height / (height * scale);
|
||||||
|
float scaleF = 0;
|
||||||
|
if (scaleX < scaleY) {
|
||||||
|
scaleF = scaleX;
|
||||||
|
} else {
|
||||||
|
scaleF = scaleY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scaleF == 0) {
|
||||||
|
scaleF = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
metalFrame.size.width = (width * scale) * scaleF;
|
||||||
|
metalFrame.size.height = (height * scale) * scaleF;
|
||||||
|
metalFrame.origin.x = (view.frame.size.width - metalFrame.size.width) / 2;
|
||||||
|
metalFrame.origin.y = (view.frame.size.height - metalFrame.size.height) / 2;
|
||||||
|
metalView.frame = metalFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
metalView.drawableSize = metalFrame.size;
|
||||||
|
((CAMetalLayer *)metalView.layer).drawableSize = metalFrame.size;
|
||||||
|
|
||||||
|
_contentSize.x = metalFrame.size.width;
|
||||||
|
_contentSize.y = metalFrame.size.height;
|
||||||
|
_viewportSize.x = width * scale;
|
||||||
|
_viewportSize.y = height * scale;
|
||||||
|
|
||||||
|
if (todraw) {
|
||||||
|
DrawArea();
|
||||||
|
}
|
||||||
|
|
||||||
|
ev.Skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetalDrawingPanel::DrawArea(wxWindowDC& dc)
|
||||||
|
{
|
||||||
|
(void)dc;
|
||||||
|
DrawArea();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetalDrawingPanel::DrawArea()
|
||||||
|
{
|
||||||
|
uint32_t srcPitch = 0;
|
||||||
|
|
||||||
|
if (!did_init)
|
||||||
|
DrawingPanelInit();
|
||||||
|
|
||||||
|
if (systemColorDepth == 8) {
|
||||||
|
srcPitch = std::ceil(width * scale) + 2;
|
||||||
|
} else if (systemColorDepth == 16) {
|
||||||
|
srcPitch = std::ceil(width * scale * 2) + 4;
|
||||||
|
} else if (systemColorDepth == 24) {
|
||||||
|
srcPitch = std::ceil(width * scale * 3);
|
||||||
|
} else {
|
||||||
|
srcPitch = std::ceil(width * scale * 4) + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (systemColorDepth == 8) {
|
||||||
|
int pos = 0;
|
||||||
|
int src_pos = 0;
|
||||||
|
uint8_t *src = todraw + srcPitch;
|
||||||
|
uint32_t *dst = (uint32_t *)calloc(4, std::ceil((width * scale) * (height * scale) + 1));
|
||||||
|
|
||||||
|
for (int y = 0; y < (height * scale); y++) {
|
||||||
|
for (int x = 0; x < (width * scale); x++) {
|
||||||
|
#if wxBYTE_ORDER == wxLITTLE_ENDIAN
|
||||||
|
if (src[src_pos] == 0xff) {
|
||||||
|
dst[pos] = 0x00ffffff;
|
||||||
|
} else {
|
||||||
|
dst[pos] = (src[src_pos] & 0xe0) + ((src[src_pos] & 0x1c) << 11) + ((src[src_pos] & 0x3) << 22);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (src[src_pos] == 0xff) {
|
||||||
|
dst[pos] = 0xffffff00;
|
||||||
|
} else {
|
||||||
|
dst[pos] = ((src[src_pos] & 0xe0) << 24) + ((src[src_pos] & 0x1c) << 19) + ((src[src_pos] & 0x3) << 14);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
pos++;
|
||||||
|
src_pos++;
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
src_pos += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
_texture = loadTextureUsingData(dst);
|
||||||
|
|
||||||
|
if (dst != NULL) {
|
||||||
|
free(dst);
|
||||||
|
}
|
||||||
|
} else if (systemColorDepth == 16) {
|
||||||
|
int pos = 0;
|
||||||
|
int src_pos = 0;
|
||||||
|
uint8_t *src = todraw + srcPitch;
|
||||||
|
uint32_t *dst = (uint32_t *)calloc(4, std::ceil((width * scale) * (height * scale) + 1));
|
||||||
|
uint16_t *src16 = (uint16_t *)src;
|
||||||
|
|
||||||
|
for (int y = 0; y < (height * scale); y++) {
|
||||||
|
for (int x = 0; x < (width * scale); x++) {
|
||||||
|
#if wxBYTE_ORDER == wxLITTLE_ENDIAN
|
||||||
|
if (src16[src_pos] == 0x7fff) {
|
||||||
|
dst[pos] = 0x00ffffff;
|
||||||
|
} else {
|
||||||
|
dst[pos] = ((src16[src_pos] & 0x7c00) >> 7) + ((src16[src_pos] & 0x03e0) << 6) + ((src16[src_pos] & 0x1f) << 19);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (src16[src_pos] == 0x7fff) {
|
||||||
|
dst[pos] = 0xffffff00;
|
||||||
|
} else {
|
||||||
|
dst[pos] = ((src16[src_pos] & 0x7c00) << 17) + ((src16[src_pos] & 0x03e0) << 14) + ((src16[src_pos] & 0x1f) << 11);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
pos++;
|
||||||
|
src_pos++;
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
src_pos += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
_texture = loadTextureUsingData(dst);
|
||||||
|
|
||||||
|
if (dst != NULL) {
|
||||||
|
free(dst);
|
||||||
|
}
|
||||||
|
} else if (systemColorDepth == 24) {
|
||||||
|
int pos = 0;
|
||||||
|
int src_pos = 0;
|
||||||
|
uint8_t *src = todraw + srcPitch;
|
||||||
|
uint8_t *dst = (uint8_t *)calloc(4, std::ceil((width * scale) * (height * scale) + 1));
|
||||||
|
|
||||||
|
for (int y = 0; y < (height * scale); y++) {
|
||||||
|
for (int x = 0; x < (width * scale); x++) {
|
||||||
|
dst[pos] = src[src_pos];
|
||||||
|
dst[pos+1] = src[src_pos+1];
|
||||||
|
dst[pos+2] = src[src_pos+2];
|
||||||
|
dst[pos+3] = 0;
|
||||||
|
|
||||||
|
pos += 4;
|
||||||
|
src_pos += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
_texture = loadTextureUsingData(dst);
|
||||||
|
|
||||||
|
if (dst != NULL) {
|
||||||
|
free(dst);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_texture = loadTextureUsingData(todraw + srcPitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new command buffer for each render pass to the current drawable
|
||||||
|
commandBuffer = [_commandQueue commandBuffer];
|
||||||
|
commandBuffer.label = @"MyCommand";
|
||||||
|
|
||||||
|
// Obtain a renderPassDescriptor
|
||||||
|
renderPassDescriptor = [metalView currentRenderPassDescriptor];
|
||||||
|
|
||||||
|
if(renderPassDescriptor != nil)
|
||||||
|
{
|
||||||
|
renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
|
||||||
|
renderEncoder.label = @"MyRenderEncoder";
|
||||||
|
|
||||||
|
[renderEncoder setViewport:(MTLViewport){0.0, 0.0, (double)(_contentSize.x), (double)(_contentSize.y), 0.0, 1.0 }];
|
||||||
|
|
||||||
|
[renderEncoder setRenderPipelineState:_pipelineState];
|
||||||
|
|
||||||
|
[renderEncoder setVertexBuffer:_vertices
|
||||||
|
offset:0
|
||||||
|
atIndex:AAPLVertexInputIndexVertices];
|
||||||
|
|
||||||
|
[renderEncoder setVertexBytes:&_viewportSize
|
||||||
|
length:sizeof(_viewportSize)
|
||||||
|
atIndex:AAPLVertexInputIndexViewportSize];
|
||||||
|
|
||||||
|
// Set the texture object. The AAPLTextureIndexBaseColor enum value corresponds
|
||||||
|
/// to the 'colorMap' argument in the 'samplingShader' function because its
|
||||||
|
// texture attribute qualifier also uses AAPLTextureIndexBaseColor for its index.
|
||||||
|
[renderEncoder setFragmentTexture:_texture
|
||||||
|
atIndex:AAPLTextureIndexBaseColor];
|
||||||
|
|
||||||
|
// Draw the triangles.
|
||||||
|
[renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle
|
||||||
|
vertexStart:0
|
||||||
|
vertexCount:_numVertices];
|
||||||
|
|
||||||
|
[renderEncoder endEncoding];
|
||||||
|
|
||||||
|
// Schedule a present once the framebuffer is complete using the next drawable
|
||||||
|
[commandBuffer presentDrawable:metalView.currentDrawable];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finalize rendering here & push the command buffer to the GPU
|
||||||
|
[commandBuffer commit];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Quartz2DDrawingPanel::Quartz2DDrawingPanel(wxWindow* parent, int _width, int _height)
|
Quartz2DDrawingPanel::Quartz2DDrawingPanel(wxWindow* parent, int _width, int _height)
|
||||||
: BasicDrawingPanel(parent, _width, _height)
|
: BasicDrawingPanel(parent, _width, _height)
|
||||||
{
|
{
|
||||||
|
@ -14,8 +416,7 @@ Quartz2DDrawingPanel::Quartz2DDrawingPanel(wxWindow* parent, int _width, int _he
|
||||||
|
|
||||||
void Quartz2DDrawingPanel::DrawImage(wxWindowDC& dc, wxImage* im)
|
void Quartz2DDrawingPanel::DrawImage(wxWindowDC& dc, wxImage* im)
|
||||||
{
|
{
|
||||||
NSView* view = (NSView*)(GetWindow()->GetHandle());
|
NSView *view = (NSView *)GetWindow()->GetHandle();
|
||||||
|
|
||||||
size_t w = std::ceil(width * scale);
|
size_t w = std::ceil(width * scale);
|
||||||
size_t h = std::ceil(height * scale);
|
size_t h = std::ceil(height * scale);
|
||||||
size_t size = w * h * 3;
|
size_t size = w * h * 3;
|
||||||
|
@ -23,18 +424,19 @@ void Quartz2DDrawingPanel::DrawImage(wxWindowDC& dc, wxImage* im)
|
||||||
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, im->GetData(), size, NULL);
|
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, im->GetData(), size, NULL);
|
||||||
|
|
||||||
CGColorSpaceRef color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
|
CGColorSpaceRef color_space = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
|
||||||
|
CGImageRef image = nil;
|
||||||
|
|
||||||
CGImageRef image = CGImageCreate(
|
image = CGImageCreate(w, h, 8, 24, w * 3, color_space, kCGBitmapByteOrderDefault,
|
||||||
w, h, 8, 24, w * 3, color_space,
|
provider, NULL, true, kCGRenderingIntentDefault);
|
||||||
kCGBitmapByteOrderDefault,
|
|
||||||
provider, NULL, true, kCGRenderingIntentDefault
|
|
||||||
);
|
|
||||||
|
|
||||||
// draw the image
|
// draw the image
|
||||||
|
#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101000
|
||||||
|
CGContextRef context = [[NSGraphicsContext currentContext] CGContext];
|
||||||
|
#else
|
||||||
[view lockFocus];
|
[view lockFocus];
|
||||||
|
|
||||||
CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
|
CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
|
||||||
|
#endif
|
||||||
|
|
||||||
CGContextSaveGState(context);
|
CGContextSaveGState(context);
|
||||||
|
|
||||||
|
@ -59,7 +461,11 @@ void Quartz2DDrawingPanel::DrawImage(wxWindowDC& dc, wxImage* im)
|
||||||
dc.DrawRectangle(w-2, h-2, w, h);
|
dc.DrawRectangle(w-2, h-2, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[view setNeedsDisplay:YES];
|
||||||
|
|
||||||
|
#if MAC_OS_X_VERSION_MIN_REQUIRED < 101000
|
||||||
[view unlockFocus];
|
[view unlockFocus];
|
||||||
|
#endif
|
||||||
|
|
||||||
// and release everything
|
// and release everything
|
||||||
|
|
||||||
|
|
1027
src/wx/panel.cpp
1027
src/wx/panel.cpp
File diff suppressed because it is too large
Load Diff
|
@ -4,7 +4,12 @@
|
||||||
#include <wx/generic/prntdlgg.h>
|
#include <wx/generic/prntdlgg.h>
|
||||||
#include <wx/print.h>
|
#include <wx/print.h>
|
||||||
#include <wx/printdlg.h>
|
#include <wx/printdlg.h>
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#else
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "core/base/image_util.h"
|
#include "core/base/image_util.h"
|
||||||
#include "core/gb/gbGlobals.h"
|
#include "core/gb/gbGlobals.h"
|
||||||
|
@ -24,6 +29,7 @@ int systemRedShift;
|
||||||
int systemGreenShift;
|
int systemGreenShift;
|
||||||
int systemBlueShift;
|
int systemBlueShift;
|
||||||
int systemColorDepth;
|
int systemColorDepth;
|
||||||
|
uint8_t systemColorMap8[0x10000];
|
||||||
uint16_t systemColorMap16[0x10000];
|
uint16_t systemColorMap16[0x10000];
|
||||||
uint32_t systemColorMap32[0x10000];
|
uint32_t systemColorMap32[0x10000];
|
||||||
#define gs555(x) (x | (x << 5) | (x << 10))
|
#define gs555(x) (x | (x << 5) | (x << 10))
|
||||||
|
|
|
@ -331,7 +331,7 @@ public:
|
||||||
|
|
||||||
for (int i = 0; i < dis->nlines; i++) {
|
for (int i = 0; i < dis->nlines; i++) {
|
||||||
dis->addrs.push_back(addr);
|
dis->addrs.push_back(addr);
|
||||||
addr += gbDis(buf, addr);
|
addr += gbDis(buf, sizeof(buf), addr);
|
||||||
dis->strings.push_back(wxString(buf, wxConvLibc));
|
dis->strings.push_back(wxString(buf, wxConvLibc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,11 @@
|
||||||
#include <wx/timer.h>
|
#include <wx/timer.h>
|
||||||
#include <wx/toplevel.h>
|
#include <wx/toplevel.h>
|
||||||
|
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#else
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "core/base/check.h"
|
#include "core/base/check.h"
|
||||||
#include "wx/config/option-id.h"
|
#include "wx/config/option-id.h"
|
||||||
|
@ -107,7 +111,11 @@ private:
|
||||||
SDL_JoystickID joystick_id_;
|
SDL_JoystickID joystick_id_;
|
||||||
|
|
||||||
// The SDL GameController instance.
|
// The SDL GameController instance.
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
SDL_GameController* game_controller_ = nullptr;
|
SDL_GameController* game_controller_ = nullptr;
|
||||||
|
#else
|
||||||
|
SDL_Gamepad* game_controller_ = nullptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
// The SDL Joystick instance.
|
// The SDL Joystick instance.
|
||||||
SDL_Joystick* sdl_joystick_ = nullptr;
|
SDL_Joystick* sdl_joystick_ = nullptr;
|
||||||
|
@ -126,6 +134,7 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
JoyState::JoyState(bool enable_game_controller, int sdl_index) : wx_joystick_(sdl_index) {
|
JoyState::JoyState(bool enable_game_controller, int sdl_index) : wx_joystick_(sdl_index) {
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
if (enable_game_controller && SDL_IsGameController(sdl_index)) {
|
if (enable_game_controller && SDL_IsGameController(sdl_index)) {
|
||||||
game_controller_ = SDL_GameControllerOpen(sdl_index);
|
game_controller_ = SDL_GameControllerOpen(sdl_index);
|
||||||
if (game_controller_)
|
if (game_controller_)
|
||||||
|
@ -133,11 +142,30 @@ JoyState::JoyState(bool enable_game_controller, int sdl_index) : wx_joystick_(sd
|
||||||
} else {
|
} else {
|
||||||
sdl_joystick_ = SDL_JoystickOpen(sdl_index);
|
sdl_joystick_ = SDL_JoystickOpen(sdl_index);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
int nrgamepads = 0;
|
||||||
|
int nrjoysticks = 0;
|
||||||
|
SDL_JoystickID *gamepads = SDL_GetGamepads(&nrgamepads);
|
||||||
|
SDL_JoystickID *joysticks = SDL_GetJoysticks(&nrjoysticks);
|
||||||
|
if (enable_game_controller && SDL_IsGamepad(gamepads[sdl_index])) {
|
||||||
|
game_controller_ = SDL_OpenGamepad(gamepads[sdl_index]);
|
||||||
|
if (game_controller_)
|
||||||
|
{
|
||||||
|
sdl_joystick_ = SDL_GetGamepadJoystick(game_controller_);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sdl_joystick_ = SDL_OpenJoystick(joysticks[sdl_index]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!sdl_joystick_)
|
if (!sdl_joystick_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
joystick_id_ = SDL_JoystickInstanceID(sdl_joystick_);
|
joystick_id_ = SDL_JoystickInstanceID(sdl_joystick_);
|
||||||
|
#else
|
||||||
|
joystick_id_ = SDL_GetJoystickID(sdl_joystick_);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
JoyState::~JoyState() {
|
JoyState::~JoyState() {
|
||||||
|
@ -145,11 +173,19 @@ JoyState::~JoyState() {
|
||||||
if (!sdl_joystick_)
|
if (!sdl_joystick_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
if (game_controller_) {
|
if (game_controller_) {
|
||||||
SDL_GameControllerClose(game_controller_);
|
SDL_GameControllerClose(game_controller_);
|
||||||
} else {
|
} else {
|
||||||
SDL_JoystickClose(sdl_joystick_);
|
SDL_JoystickClose(sdl_joystick_);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (game_controller_) {
|
||||||
|
SDL_CloseGamepad(game_controller_);
|
||||||
|
} else {
|
||||||
|
SDL_CloseJoystick(sdl_joystick_);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
JoyState::JoyState(JoyState&& other) : wx_joystick_(other.wx_joystick_) {
|
JoyState::JoyState(JoyState&& other) : wx_joystick_(other.wx_joystick_) {
|
||||||
|
@ -280,7 +316,20 @@ std::vector<UserInputEvent::Data> JoyState::ProcessHatEvent(const uint8_t index,
|
||||||
void JoyState::SetRumble(bool activate_rumble) {
|
void JoyState::SetRumble(bool activate_rumble) {
|
||||||
rumbling_ = activate_rumble;
|
rumbling_ = activate_rumble;
|
||||||
|
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 9)
|
#ifdef ENABLE_SDL3
|
||||||
|
if (game_controller_ == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (rumbling_) {
|
||||||
|
SDL_RumbleGamepad(game_controller_, 0xFFFF, 0xFFFF, 300);
|
||||||
|
if (!IsRunning()) {
|
||||||
|
Start(150);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SDL_RumbleGamepad(game_controller_, 0, 0, 0);
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
#elif SDL_VERSION_ATLEAST(2, 0, 9)
|
||||||
if (!game_controller_)
|
if (!game_controller_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -309,16 +358,30 @@ SdlPoller::SdlPoller(EventHandlerProvider* const handler_provider)
|
||||||
VBAM_CHECK(handler_provider);
|
VBAM_CHECK(handler_provider);
|
||||||
|
|
||||||
wxTimer::Start(50);
|
wxTimer::Start(50);
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS);
|
SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS);
|
||||||
SDL_GameControllerEventState(SDL_ENABLE);
|
SDL_GameControllerEventState(SDL_ENABLE);
|
||||||
SDL_JoystickEventState(SDL_ENABLE);
|
SDL_JoystickEventState(SDL_ENABLE);
|
||||||
|
#else
|
||||||
|
SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD | SDL_INIT_EVENTS);
|
||||||
|
SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD | SDL_INIT_EVENTS);
|
||||||
|
SDL_SetGamepadEventsEnabled(true);
|
||||||
|
SDL_SetJoystickEventsEnabled(true);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SdlPoller::~SdlPoller() {
|
SdlPoller::~SdlPoller() {
|
||||||
wxTimer::Stop();
|
wxTimer::Stop();
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
SDL_QuitSubSystem(SDL_INIT_EVENTS);
|
SDL_QuitSubSystem(SDL_INIT_EVENTS);
|
||||||
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||||
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
|
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
|
||||||
|
#else
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_EVENTS);
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||||
|
SDL_QuitSubSystem(SDL_INIT_GAMEPAD);
|
||||||
|
#endif
|
||||||
|
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,6 +411,7 @@ void SdlPoller::Notify() {
|
||||||
std::vector<UserInputEvent::Data> event_data;
|
std::vector<UserInputEvent::Data> event_data;
|
||||||
JoyState* joy_state = nullptr;
|
JoyState* joy_state = nullptr;
|
||||||
switch (sdl_event.type) {
|
switch (sdl_event.type) {
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
case SDL_CONTROLLERBUTTONDOWN:
|
case SDL_CONTROLLERBUTTONDOWN:
|
||||||
case SDL_CONTROLLERBUTTONUP:
|
case SDL_CONTROLLERBUTTONUP:
|
||||||
joy_state = FindJoyState(sdl_event.cbutton.which);
|
joy_state = FindJoyState(sdl_event.cbutton.which);
|
||||||
|
@ -355,41 +419,86 @@ void SdlPoller::Notify() {
|
||||||
event_data = joy_state->ProcessButtonEvent(sdl_event.cbutton.button,
|
event_data = joy_state->ProcessButtonEvent(sdl_event.cbutton.button,
|
||||||
sdl_event.cbutton.state);
|
sdl_event.cbutton.state);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
|
||||||
|
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
||||||
|
joy_state = FindJoyState(sdl_event.gbutton.which);
|
||||||
|
if (joy_state) {
|
||||||
|
event_data = joy_state->ProcessButtonEvent(sdl_event.gbutton.button,
|
||||||
|
sdl_event.gbutton.down);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
case SDL_CONTROLLERAXISMOTION:
|
case SDL_CONTROLLERAXISMOTION:
|
||||||
joy_state = FindJoyState(sdl_event.caxis.which);
|
joy_state = FindJoyState(sdl_event.caxis.which);
|
||||||
if (joy_state) {
|
if (joy_state) {
|
||||||
event_data = joy_state->ProcessAxisEvent(
|
event_data = joy_state->ProcessAxisEvent(
|
||||||
sdl_event.caxis.axis, AxisValueToStatus(sdl_event.caxis.value));
|
sdl_event.caxis.axis, AxisValueToStatus(sdl_event.caxis.value));
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
||||||
|
joy_state = FindJoyState(sdl_event.gaxis.which);
|
||||||
|
if (joy_state) {
|
||||||
|
event_data = joy_state->ProcessAxisEvent(
|
||||||
|
sdl_event.gaxis.axis, AxisValueToStatus(sdl_event.gaxis.value));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
case SDL_CONTROLLERDEVICEADDED:
|
case SDL_CONTROLLERDEVICEADDED:
|
||||||
case SDL_CONTROLLERDEVICEREMOVED:
|
case SDL_CONTROLLERDEVICEREMOVED:
|
||||||
|
#else
|
||||||
|
case SDL_EVENT_GAMEPAD_ADDED:
|
||||||
|
case SDL_EVENT_GAMEPAD_REMOVED:
|
||||||
|
#endif
|
||||||
// Do nothing. This will be handled with JOYDEVICEADDED and
|
// Do nothing. This will be handled with JOYDEVICEADDED and
|
||||||
// JOYDEVICEREMOVED events.
|
// JOYDEVICEREMOVED events.
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Joystick events for non-GameControllers.
|
// Joystick events for non-GameControllers.
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
case SDL_JOYBUTTONDOWN:
|
case SDL_JOYBUTTONDOWN:
|
||||||
case SDL_JOYBUTTONUP:
|
case SDL_JOYBUTTONUP:
|
||||||
|
#else
|
||||||
|
case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
|
||||||
|
case SDL_EVENT_JOYSTICK_BUTTON_UP:
|
||||||
|
#endif
|
||||||
joy_state = FindJoyState(sdl_event.jbutton.which);
|
joy_state = FindJoyState(sdl_event.jbutton.which);
|
||||||
if (joy_state && !joy_state->is_game_controller()) {
|
if (joy_state && !joy_state->is_game_controller()) {
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
|
event_data = joy_state->ProcessButtonEvent(sdl_event.cbutton.button,
|
||||||
|
sdl_event.cbutton.state);
|
||||||
|
#else
|
||||||
event_data = joy_state->ProcessButtonEvent(sdl_event.jbutton.button,
|
event_data = joy_state->ProcessButtonEvent(sdl_event.jbutton.button,
|
||||||
sdl_event.jbutton.state);
|
sdl_event.jbutton.down);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
case SDL_JOYAXISMOTION:
|
case SDL_JOYAXISMOTION:
|
||||||
|
#else
|
||||||
|
case SDL_EVENT_JOYSTICK_AXIS_MOTION:
|
||||||
|
#endif
|
||||||
joy_state = FindJoyState(sdl_event.jaxis.which);
|
joy_state = FindJoyState(sdl_event.jaxis.which);
|
||||||
if (joy_state && !joy_state->is_game_controller()) {
|
if (joy_state && !joy_state->is_game_controller()) {
|
||||||
event_data = joy_state->ProcessAxisEvent(
|
event_data = joy_state->ProcessAxisEvent(
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
|
sdl_event.caxis.axis, AxisValueToStatus(sdl_event.caxis.value));
|
||||||
|
#else
|
||||||
sdl_event.jaxis.axis, AxisValueToStatus(sdl_event.jaxis.value));
|
sdl_event.jaxis.axis, AxisValueToStatus(sdl_event.jaxis.value));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
case SDL_JOYHATMOTION:
|
case SDL_JOYHATMOTION:
|
||||||
|
#else
|
||||||
|
case SDL_EVENT_JOYSTICK_HAT_MOTION:
|
||||||
|
#endif
|
||||||
joy_state = FindJoyState(sdl_event.jhat.which);
|
joy_state = FindJoyState(sdl_event.jhat.which);
|
||||||
if (joy_state && !joy_state->is_game_controller()) {
|
if (joy_state && !joy_state->is_game_controller()) {
|
||||||
event_data =
|
event_data =
|
||||||
|
@ -397,12 +506,20 @@ void SdlPoller::Notify() {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
case SDL_JOYDEVICEADDED:
|
case SDL_JOYDEVICEADDED:
|
||||||
|
#else
|
||||||
|
case SDL_EVENT_JOYSTICK_ADDED:
|
||||||
|
#endif
|
||||||
// Always remap all controllers.
|
// Always remap all controllers.
|
||||||
RemapControllers();
|
RemapControllers();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
case SDL_JOYDEVICEREMOVED:
|
case SDL_JOYDEVICEREMOVED:
|
||||||
|
#else
|
||||||
|
case SDL_EVENT_JOYSTICK_REMOVED:
|
||||||
|
#endif
|
||||||
joystick_states_.erase(sdl_event.jdevice.which);
|
joystick_states_.erase(sdl_event.jdevice.which);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -426,11 +543,21 @@ JoyState* SdlPoller::FindJoyState(const SDL_JoystickID& joy_id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SdlPoller::RemapControllers() {
|
void SdlPoller::RemapControllers() {
|
||||||
|
#ifdef ENABLE_SDL3
|
||||||
|
int total_joysticks = 0;
|
||||||
|
|
||||||
|
SDL_GetJoysticks(&total_joysticks);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Clear the current joystick states.
|
// Clear the current joystick states.
|
||||||
joystick_states_.clear();
|
joystick_states_.clear();
|
||||||
|
|
||||||
// Reconnect all controllers.
|
// Reconnect all controllers.
|
||||||
|
#ifndef ENABLE_SDL3
|
||||||
for (int i = 0; i < SDL_NumJoysticks(); ++i) {
|
for (int i = 0; i < SDL_NumJoysticks(); ++i) {
|
||||||
|
#else
|
||||||
|
for (int i = 0; i < total_joysticks; ++i) {
|
||||||
|
#endif
|
||||||
JoyState joy_state(enable_game_controller_, i);
|
JoyState joy_state(enable_game_controller_, i);
|
||||||
if (joy_state.IsValid()) {
|
if (joy_state.IsValid()) {
|
||||||
joystick_states_.insert({joy_state.joystick_id(), std::move(joy_state)});
|
joystick_states_.insert({joy_state.joystick_id(), std::move(joy_state)});
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue