Merge branch 'spice2x' into spice22x
This commit is contained in:
@@ -2,3 +2,4 @@ bin/**
|
|||||||
dist/**
|
dist/**
|
||||||
docker/**
|
docker/**
|
||||||
cmake-build*
|
cmake-build*
|
||||||
|
.ccache/**
|
||||||
@@ -16,3 +16,5 @@ bin/*
|
|||||||
dist/*
|
dist/*
|
||||||
|
|
||||||
external/cv2pdb/*
|
external/cv2pdb/*
|
||||||
|
|
||||||
|
.ccache/*
|
||||||
Generated
+17
@@ -0,0 +1,17 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Clion[Init]" type="ShConfigurationType" activateToolWindowBeforeRun="false">
|
||||||
|
<option name="SCRIPT_TEXT" value="" />
|
||||||
|
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
|
||||||
|
<option name="SCRIPT_PATH" value="$PROJECT_DIR$/cmake.sh" />
|
||||||
|
<option name="SCRIPT_OPTIONS" value="clion init" />
|
||||||
|
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
|
||||||
|
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||||
|
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
|
||||||
|
<option name="INTERPRETER_PATH" value="/usr/bin/bash" />
|
||||||
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
|
<option name="EXECUTE_IN_TERMINAL" value="false" />
|
||||||
|
<option name="EXECUTE_SCRIPT_FILE" value="true" />
|
||||||
|
<envs />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Deploy[Extra_x64]" type="ShConfigurationType">
|
||||||
|
<option name="SCRIPT_TEXT" value="" />
|
||||||
|
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
|
||||||
|
<option name="SCRIPT_PATH" value="$PROJECT_DIR$/cmake.sh" />
|
||||||
|
<option name="SCRIPT_OPTIONS" value="deploy all" />
|
||||||
|
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
|
||||||
|
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||||
|
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
|
||||||
|
<option name="INTERPRETER_PATH" value="/usr/bin/bash" />
|
||||||
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
|
<option name="EXECUTE_IN_TERMINAL" value="true" />
|
||||||
|
<option name="EXECUTE_SCRIPT_FILE" value="true" />
|
||||||
|
<envs>
|
||||||
|
<env name="_G_clean" value="false" />
|
||||||
|
<env name="_G_debug" value="false" />
|
||||||
|
</envs>
|
||||||
|
<method v="2">
|
||||||
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="spicetools_stubs_nvEncodeAPI64" run_configuration_type="CMakeRunConfiguration" run_configuration_target="CMakeBuildProfile:Release_x64[WIN_32]" />
|
||||||
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="spicetools_stubs_nvcuda" run_configuration_type="CMakeRunConfiguration" run_configuration_target="CMakeBuildProfile:Release_x64[WIN_32]" />
|
||||||
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="spicetools_stubs_nvcuvid" run_configuration_type="CMakeRunConfiguration" run_configuration_target="CMakeBuildProfile:Release_x64[WIN_32]" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Deploy[Extra_x86]" type="ShConfigurationType">
|
||||||
|
<option name="SCRIPT_TEXT" value="" />
|
||||||
|
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
|
||||||
|
<option name="SCRIPT_PATH" value="$PROJECT_DIR$/cmake.sh" />
|
||||||
|
<option name="SCRIPT_OPTIONS" value="deploy all" />
|
||||||
|
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
|
||||||
|
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||||
|
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
|
||||||
|
<option name="INTERPRETER_PATH" value="/usr/bin/bash" />
|
||||||
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
|
<option name="EXECUTE_IN_TERMINAL" value="true" />
|
||||||
|
<option name="EXECUTE_SCRIPT_FILE" value="true" />
|
||||||
|
<envs>
|
||||||
|
<env name="_G_clean" value="false" />
|
||||||
|
<env name="_G_debug" value="false" />
|
||||||
|
</envs>
|
||||||
|
<method v="2">
|
||||||
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="spicetools_spice_laa" run_configuration_type="CMakeRunConfiguration" run_configuration_target="CMakeBuildProfile:Release_x86[WIN_32]" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
+6
-1
@@ -15,6 +15,11 @@
|
|||||||
<env name="_G_clean" value="false" />
|
<env name="_G_clean" value="false" />
|
||||||
<env name="_G_debug" value="false" />
|
<env name="_G_debug" value="false" />
|
||||||
</envs>
|
</envs>
|
||||||
<method v="2" />
|
<method v="2">
|
||||||
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="Deploy[Release_x64]" run_configuration_type="ShConfigurationType" />
|
||||||
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="Deploy[Release_x86]" run_configuration_type="ShConfigurationType" />
|
||||||
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="Deploy[Extra_x64]" run_configuration_type="ShConfigurationType" />
|
||||||
|
<option name="RunConfigurationTask" enabled="true" run_configuration_name="Deploy[Extra_x86]" run_configuration_type="ShConfigurationType" />
|
||||||
|
</method>
|
||||||
</configuration>
|
</configuration>
|
||||||
</component>
|
</component>
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="spicetools_cfg" type="CMakeRunConfiguration" factoryName="Application" folderName="32" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="spicetools" TARGET_NAME="spicetools_cfg" CONFIG_NAME="Release_x64[WIN_32]" RUN_PATH="/bin/true">
|
<configuration default="false" name="spicetools_cfg" type="CMakeRunConfiguration" factoryName="Application" folderName="32" activateToolWindowBeforeRun="false" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="spicetools" TARGET_NAME="spicetools_cfg" CONFIG_NAME="Release_x64[WIN_32]" RUN_PATH="/bin/true">
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="CMake.Explicit.Target" predefinedTargetName="spicetools_stubs_kbt" />
|
<option name="CMake.Explicit.Target" predefinedTargetName="spicetools_stubs_kbt" />
|
||||||
<option name="CMake.Explicit.Target" predefinedTargetName="spicetools_stubs_kld" />
|
<option name="CMake.Explicit.Target" predefinedTargetName="spicetools_stubs_kld" />
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="spicetools_spice" type="CMakeRunConfiguration" factoryName="Application" folderName="32" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="spicetools" TARGET_NAME="spicetools_spice" CONFIG_NAME="Release_x64[WIN_32]" RUN_PATH="/bin/true">
|
<configuration default="false" name="spicetools_spice" type="CMakeRunConfiguration" factoryName="Application" folderName="32" activateToolWindowBeforeRun="false" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="spicetools" TARGET_NAME="spicetools_spice" CONFIG_NAME="Release_x64[WIN_32]" RUN_PATH="/bin/true">
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="CMake.Explicit.Target" predefinedTargetName="spicetools_stubs_kbt" />
|
<option name="CMake.Explicit.Target" predefinedTargetName="spicetools_stubs_kbt" />
|
||||||
<option name="CMake.Explicit.Target" predefinedTargetName="spicetools_stubs_kld" />
|
<option name="CMake.Explicit.Target" predefinedTargetName="spicetools_stubs_kld" />
|
||||||
|
|||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
<component name="ProjectRunConfigurationManager">
|
||||||
<configuration default="false" name="spicetools_spice64" type="CMakeRunConfiguration" factoryName="Application" folderName="64" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="spicetools" TARGET_NAME="spicetools_spice64" CONFIG_NAME="Release_x64[WIN_32]" RUN_PATH="/bin/true">
|
<configuration default="false" name="spicetools_spice64" type="CMakeRunConfiguration" factoryName="Application" folderName="64" activateToolWindowBeforeRun="false" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="spicetools" TARGET_NAME="spicetools_spice64" CONFIG_NAME="Release_x64[WIN_32]" RUN_PATH="/bin/true">
|
||||||
<method v="2">
|
<method v="2">
|
||||||
<option name="CMake.Explicit.Target" predefinedTargetName="spicetools_stubs_kbt64" />
|
<option name="CMake.Explicit.Target" predefinedTargetName="spicetools_stubs_kbt64" />
|
||||||
<option name="CMake.Explicit.Target" predefinedTargetName="spicetools_stubs_kld64" />
|
<option name="CMake.Explicit.Target" predefinedTargetName="spicetools_stubs_kld64" />
|
||||||
|
|||||||
+158
-67
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.9)
|
cmake_minimum_required(VERSION 3.12)
|
||||||
cmake_policy(SET CMP0069 NEW)
|
cmake_policy(SET CMP0069 NEW)
|
||||||
project(spicetools)
|
project(spicetools)
|
||||||
include(CheckIPOSupported)
|
include(CheckIPOSupported)
|
||||||
@@ -14,7 +14,6 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
|
|||||||
add_compile_definitions(RAPIDJSON_HAS_STDSTRING)
|
add_compile_definitions(RAPIDJSON_HAS_STDSTRING)
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
|
|
||||||
# disable intermediate manifest
|
# disable intermediate manifest
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /manifest:no")
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /manifest:no")
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /manifest:no")
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /manifest:no")
|
||||||
@@ -34,6 +33,9 @@ if(MSVC)
|
|||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DYNAMICBASE:NO")
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DYNAMICBASE:NO")
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DYNAMICBASE:NO")
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DYNAMICBASE:NO")
|
||||||
|
|
||||||
|
set(USE_STATIC_MSVCRT ON CACHE BOOL "If enabled, will force the use of static crt instead of dynamic")
|
||||||
|
|
||||||
|
if(USE_STATIC_MSVCRT)
|
||||||
# use statically linked runtime
|
# use statically linked runtime
|
||||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||||
set(CompilerFlags
|
set(CompilerFlags
|
||||||
@@ -44,17 +46,40 @@ if(MSVC)
|
|||||||
CMAKE_C_FLAGS_DEBUG
|
CMAKE_C_FLAGS_DEBUG
|
||||||
CMAKE_C_FLAGS_RELEASE
|
CMAKE_C_FLAGS_RELEASE
|
||||||
)
|
)
|
||||||
|
|
||||||
foreach(CompilerFlag ${CompilerFlags})
|
foreach(CompilerFlag ${CompilerFlags})
|
||||||
string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
|
string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# enable PDB generation with Release builds
|
|
||||||
if(CMAKE_BUILD_TYPE MATCHES "Release")
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Zi")
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zi")
|
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG /OPT:REF /OPT:ICF")
|
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUG /OPT:REF /OPT:ICF")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# disable C4996 "The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name" warning
|
||||||
|
add_compile_options("/wd4996")
|
||||||
|
|
||||||
|
# cleanup windows.h includes
|
||||||
|
add_compile_options("/DNOMINMAX")
|
||||||
|
|
||||||
|
# cleanup weird types
|
||||||
|
add_compile_options("/DWINBOOL=BOOL")
|
||||||
|
|
||||||
|
# add support for the deprecated std::result_of in c++20
|
||||||
|
add_compile_options("/D_HAS_DEPRECATED_RESULT_OF")
|
||||||
|
|
||||||
|
# enable build paralellization
|
||||||
|
add_compile_options("/MP")
|
||||||
|
|
||||||
|
# enable edit and continue in Debug
|
||||||
|
add_compile_options("$<$<CONFIG:DEBUG>:/ZI>")
|
||||||
|
add_link_options("$<$<CONFIG:DEBUG>:/SAFESEH:NO>")
|
||||||
|
|
||||||
|
# enable fast pdb generation in debug
|
||||||
|
add_link_options("$<$<CONFIG:DEBUG>:/DEBUG:FASTLINK>")
|
||||||
|
|
||||||
|
# enable pdb generation for release builds
|
||||||
|
add_compile_options("$<$<CONFIG:RELEASE,MINSIZEREL>:/Zi>")
|
||||||
|
add_link_options("$<$<CONFIG:RELEASE,MINSIZEREL>:/DEBUG:FULL>")
|
||||||
|
|
||||||
|
# enable COMDAT folding for even smaller release builds
|
||||||
|
add_link_options("$<$<CONFIG:RELEASE,MINSIZEREL>:/OPT:ICF>")
|
||||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
# disable warnings about using non _s variants like strncpy
|
# disable warnings about using non _s variants like strncpy
|
||||||
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
||||||
@@ -94,8 +119,13 @@ else()
|
|||||||
# hide ident strings
|
# hide ident strings
|
||||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fno-ident -ffunction-sections -fdata-sections")
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fno-ident -ffunction-sections -fdata-sections")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-ident -ffunction-sections -fdata-sections")
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-ident -ffunction-sections -fdata-sections")
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
|
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections")
|
# a change in the linker caused the executable to be loaded above 4GB base virtual address
|
||||||
|
# https://github.com/msys2/MINGW-packages/pull/6880
|
||||||
|
# some games crash if some DLLS load above 4GB VA, so manually set base address to standard 32-bit VA,
|
||||||
|
# and might as well double make sure ASLR is disabled here
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections,--disable-dynamicbase,--image-base=0x400000")
|
||||||
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections,--disable-dynamicbase,--image-base=0x400000")
|
||||||
|
|
||||||
# set visibility to hidden
|
# set visibility to hidden
|
||||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fvisibility=hidden")
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fvisibility=hidden")
|
||||||
@@ -106,8 +136,8 @@ else()
|
|||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s")
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -s")
|
||||||
|
|
||||||
# performance
|
# performance
|
||||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast -pipe")
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O2 -pipe")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -pipe")
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2 -pipe")
|
||||||
|
|
||||||
# ensure frame pointers are enabled
|
# ensure frame pointers are enabled
|
||||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fno-omit-frame-pointer")
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fno-omit-frame-pointer")
|
||||||
@@ -128,8 +158,10 @@ else()
|
|||||||
# hide ident strings
|
# hide ident strings
|
||||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-fno-ident -ffunction-sections -fdata-sections")
|
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-fno-ident -ffunction-sections -fdata-sections")
|
||||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-fno-ident -ffunction-sections -fdata-sections")
|
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-fno-ident -ffunction-sections -fdata-sections")
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
|
|
||||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections")
|
# linker fix to load below 4GB
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections,--disable-dynamicbase,--image-base=0x400000")
|
||||||
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections,--disable-dynamicbase,--image-base=0x400000")
|
||||||
|
|
||||||
# set visibility to hidden
|
# set visibility to hidden
|
||||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fvisibility=hidden")
|
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fvisibility=hidden")
|
||||||
@@ -151,6 +183,10 @@ else()
|
|||||||
set(CMAKE_C_FLAGS_DEBUG "-gdwarf")
|
set(CMAKE_C_FLAGS_DEBUG "-gdwarf")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "-gdwarf")
|
set(CMAKE_CXX_FLAGS_DEBUG "-gdwarf")
|
||||||
|
|
||||||
|
# linker fix to load below 4GB
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--disable-dynamicbase,--image-base=0x400000")
|
||||||
|
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--disable-dynamicbase,--image-base=0x400000")
|
||||||
|
|
||||||
# enable debug symbols on level 3 and keep frame pointers
|
# enable debug symbols on level 3 and keep frame pointers
|
||||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g3 -fno-omit-frame-pointer")
|
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g3 -fno-omit-frame-pointer")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g3 -fno-omit-frame-pointer")
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g3 -fno-omit-frame-pointer")
|
||||||
@@ -169,14 +205,13 @@ endif()
|
|||||||
add_compile_definitions(
|
add_compile_definitions(
|
||||||
WIN32_LEAN_AND_MEAN
|
WIN32_LEAN_AND_MEAN
|
||||||
_WIN32_IE=0x0400
|
_WIN32_IE=0x0400
|
||||||
OPENVR_BUILD_STATIC
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# acioemu log
|
# acioemu log
|
||||||
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DACIOEMU_LOG")
|
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DACIOEMU_LOG")
|
||||||
|
|
||||||
# add project directory to include path so we can comfortably import
|
# add project directory to include path so we can comfortably import
|
||||||
include_directories(${spicetools_SOURCE_DIR})
|
include_directories(${spicetools_SOURCE_DIR} ${spicetools_SOURCE_DIR}/external/imgui)
|
||||||
|
|
||||||
# add external libraries
|
# add external libraries
|
||||||
add_subdirectory(external/fmt EXCLUDE_FROM_ALL)
|
add_subdirectory(external/fmt EXCLUDE_FROM_ALL)
|
||||||
@@ -184,18 +219,16 @@ add_subdirectory(external/discord-rpc EXCLUDE_FROM_ALL)
|
|||||||
add_subdirectory(external/hash-library EXCLUDE_FROM_ALL)
|
add_subdirectory(external/hash-library EXCLUDE_FROM_ALL)
|
||||||
add_subdirectory(external/imgui EXCLUDE_FROM_ALL)
|
add_subdirectory(external/imgui EXCLUDE_FROM_ALL)
|
||||||
add_subdirectory(external/minhook EXCLUDE_FROM_ALL)
|
add_subdirectory(external/minhook EXCLUDE_FROM_ALL)
|
||||||
add_subdirectory(external/openvr EXCLUDE_FROM_ALL)
|
add_subdirectory(external/cpu_features EXCLUDE_FROM_ALL)
|
||||||
add_subdirectory(external/lua EXCLUDE_FROM_ALL)
|
|
||||||
|
|
||||||
# set link time optimizations (disabled for Debug builds for speed, disabled
|
# set link time optimizations (disabled for Debug builds for speed, disabled
|
||||||
# for RelWithDebInfo builds due to "lto1: error: two or more sections for"
|
# for RelWithDebInfo builds due to "lto1: error: two or more sections for"
|
||||||
# errors)
|
# errors)
|
||||||
check_ipo_supported()
|
check_ipo_supported()
|
||||||
if(CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo" OR CMAKE_BUILD_TYPE MATCHES "Debug")
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_DEBUG OFF)
|
||||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION FALSE)
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO OFF)
|
||||||
else()
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL ON)
|
||||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
|
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)
|
||||||
endif()
|
|
||||||
|
|
||||||
# resources
|
# resources
|
||||||
###########
|
###########
|
||||||
@@ -266,6 +299,8 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
|||||||
api/serial.cpp
|
api/serial.cpp
|
||||||
api/modules/drs.cpp
|
api/modules/drs.cpp
|
||||||
api/modules/lcd.cpp
|
api/modules/lcd.cpp
|
||||||
|
api/modules/ddr.cpp
|
||||||
|
api/modules/resize.cpp
|
||||||
|
|
||||||
# avs
|
# avs
|
||||||
avs/core.cpp
|
avs/core.cpp
|
||||||
@@ -297,17 +332,6 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
|||||||
# external asio
|
# external asio
|
||||||
external/asio/asiolist.cpp
|
external/asio/asiolist.cpp
|
||||||
|
|
||||||
# external layeredfs
|
|
||||||
external/layeredfs/config.cpp
|
|
||||||
external/layeredfs/hook.cpp
|
|
||||||
external/layeredfs/modpath_handler.cpp
|
|
||||||
external/layeredfs/texture_packer.cpp
|
|
||||||
external/layeredfs/utils.cpp
|
|
||||||
external/layeredfs/3rd_party/GuillotineBinPack.cpp
|
|
||||||
external/layeredfs/3rd_party/lodepng.cpp
|
|
||||||
external/layeredfs/3rd_party/Rect.cpp
|
|
||||||
external/layeredfs/3rd_party/stb_dxt.cpp
|
|
||||||
|
|
||||||
# external cardio
|
# external cardio
|
||||||
external/cardio/cardio_hid.cpp
|
external/cardio/cardio_hid.cpp
|
||||||
external/cardio/cardio_window.cpp
|
external/cardio/cardio_window.cpp
|
||||||
@@ -335,10 +359,15 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
|||||||
games/hpm/io.cpp
|
games/hpm/io.cpp
|
||||||
games/iidx/iidx.cpp
|
games/iidx/iidx.cpp
|
||||||
games/iidx/io.cpp
|
games/iidx/io.cpp
|
||||||
|
games/iidx/poke.cpp
|
||||||
games/iidx/bi2a.cpp
|
games/iidx/bi2a.cpp
|
||||||
games/iidx/bi2x.cpp
|
games/iidx/bi2x.cpp
|
||||||
games/iidx/bi2x_hook.cpp
|
games/iidx/bi2x_hook.cpp
|
||||||
games/iidx/ezusb.cpp
|
games/iidx/ezusb.cpp
|
||||||
|
games/iidx/legacy_camera.cpp
|
||||||
|
games/iidx/local_camera.cpp
|
||||||
|
games/iidx/camera.cpp
|
||||||
|
games/iidx/mf_wrappers.cpp
|
||||||
games/sdvx/bi2x_hook.cpp
|
games/sdvx/bi2x_hook.cpp
|
||||||
games/sdvx/sdvx.cpp
|
games/sdvx/sdvx.cpp
|
||||||
games/sdvx/io.cpp
|
games/sdvx/io.cpp
|
||||||
@@ -347,6 +376,7 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
|||||||
games/jb/io.cpp
|
games/jb/io.cpp
|
||||||
games/nost/nost.cpp
|
games/nost/nost.cpp
|
||||||
games/nost/io.cpp
|
games/nost/io.cpp
|
||||||
|
games/nost/poke.cpp
|
||||||
games/gitadora/gitadora.cpp
|
games/gitadora/gitadora.cpp
|
||||||
games/gitadora/io.cpp
|
games/gitadora/io.cpp
|
||||||
games/mga/mga.cpp
|
games/mga/mga.cpp
|
||||||
@@ -362,6 +392,7 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
|||||||
games/rf3d/rf3d.cpp
|
games/rf3d/rf3d.cpp
|
||||||
games/rf3d/io.cpp
|
games/rf3d/io.cpp
|
||||||
games/museca/io.cpp
|
games/museca/io.cpp
|
||||||
|
games/museca/museca.cpp
|
||||||
games/dea/dea.cpp
|
games/dea/dea.cpp
|
||||||
games/dea/io.cpp
|
games/dea/io.cpp
|
||||||
games/qma/qma.cpp
|
games/qma/qma.cpp
|
||||||
@@ -372,6 +403,8 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
|||||||
games/ddr/p3io/p3io.cpp
|
games/ddr/p3io/p3io.cpp
|
||||||
games/ddr/p3io/sate.cpp
|
games/ddr/p3io/sate.cpp
|
||||||
games/ddr/p3io/usbmem.cpp
|
games/ddr/p3io/usbmem.cpp
|
||||||
|
games/ddr/p4io/p4io.cpp
|
||||||
|
games/ddr/p4io/p4io.h
|
||||||
games/mfc/mfc.cpp
|
games/mfc/mfc.cpp
|
||||||
games/mfc/io.cpp
|
games/mfc/io.cpp
|
||||||
games/ftt/ftt.cpp
|
games/ftt/ftt.cpp
|
||||||
@@ -400,12 +433,23 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
|||||||
games/onpara/touchpanel.cpp
|
games/onpara/touchpanel.cpp
|
||||||
games/bc/bc.cpp
|
games/bc/bc.cpp
|
||||||
games/bc/io.cpp
|
games/bc/io.cpp
|
||||||
|
games/ccj/ccj.cpp
|
||||||
|
games/ccj/io.cpp
|
||||||
|
games/ccj/bi2x_hook.cpp
|
||||||
|
games/ccj/trackball.cpp
|
||||||
|
games/qks/qks.cpp
|
||||||
|
games/qks/io.cpp
|
||||||
|
games/qks/bi2x_hook.cpp
|
||||||
|
games/mfg/mfg.cpp
|
||||||
|
games/mfg/io.cpp
|
||||||
|
games/mfg/bi2a_hook.cpp
|
||||||
|
|
||||||
# hooks
|
# hooks
|
||||||
hooks/audio/audio.cpp
|
hooks/audio/audio.cpp
|
||||||
hooks/audio/buffer.cpp
|
hooks/audio/buffer.cpp
|
||||||
hooks/audio/util.cpp
|
hooks/audio/util.cpp
|
||||||
hooks/audio/backends/dsound/dsound_backend.cpp
|
hooks/audio/backends/dsound/dsound_backend.cpp
|
||||||
|
hooks/audio/backends/mmdevice/audio_endpoint_volume.cpp
|
||||||
hooks/audio/backends/mmdevice/device.cpp
|
hooks/audio/backends/mmdevice/device.cpp
|
||||||
hooks/audio/backends/mmdevice/device_enumerator.cpp
|
hooks/audio/backends/mmdevice/device_enumerator.cpp
|
||||||
hooks/audio/backends/wasapi/audio_client.cpp
|
hooks/audio/backends/wasapi/audio_client.cpp
|
||||||
@@ -414,6 +458,7 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
|||||||
hooks/audio/backends/wasapi/dummy_audio_clock.cpp
|
hooks/audio/backends/wasapi/dummy_audio_clock.cpp
|
||||||
hooks/audio/backends/wasapi/dummy_audio_render_client.cpp
|
hooks/audio/backends/wasapi/dummy_audio_render_client.cpp
|
||||||
hooks/audio/backends/wasapi/dummy_audio_session_control.cpp
|
hooks/audio/backends/wasapi/dummy_audio_session_control.cpp
|
||||||
|
hooks/audio/backends/wasapi/low_latency_client.cpp
|
||||||
hooks/audio/backends/wasapi/util.cpp
|
hooks/audio/backends/wasapi/util.cpp
|
||||||
hooks/audio/implementations/asio.cpp
|
hooks/audio/implementations/asio.cpp
|
||||||
hooks/audio/implementations/wave_out.cpp
|
hooks/audio/implementations/wave_out.cpp
|
||||||
@@ -425,6 +470,8 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
|||||||
hooks/devicehook.cpp
|
hooks/devicehook.cpp
|
||||||
hooks/graphics/graphics.cpp
|
hooks/graphics/graphics.cpp
|
||||||
hooks/graphics/graphics_windowed.cpp
|
hooks/graphics/graphics_windowed.cpp
|
||||||
|
hooks/graphics/nvapi_hook.cpp
|
||||||
|
hooks/graphics/nvenc_hook.cpp
|
||||||
hooks/graphics/backends/d3d9/d3d9_backend.cpp
|
hooks/graphics/backends/d3d9/d3d9_backend.cpp
|
||||||
hooks/graphics/backends/d3d9/d3d9_device.cpp
|
hooks/graphics/backends/d3d9/d3d9_device.cpp
|
||||||
hooks/graphics/backends/d3d9/d3d9_fake_swapchain.cpp
|
hooks/graphics/backends/d3d9/d3d9_fake_swapchain.cpp
|
||||||
@@ -441,6 +488,7 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
|||||||
hooks/setupapihook.cpp
|
hooks/setupapihook.cpp
|
||||||
hooks/sleephook.cpp
|
hooks/sleephook.cpp
|
||||||
hooks/unisintrhook.cpp
|
hooks/unisintrhook.cpp
|
||||||
|
hooks/winuser.cpp
|
||||||
|
|
||||||
# launcher
|
# launcher
|
||||||
launcher/launcher.cpp
|
launcher/launcher.cpp
|
||||||
@@ -459,18 +507,21 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
|||||||
misc/extdev.cpp
|
misc/extdev.cpp
|
||||||
misc/sciunit.cpp
|
misc/sciunit.cpp
|
||||||
misc/sde.cpp
|
misc/sde.cpp
|
||||||
misc/vrutil.cpp
|
|
||||||
misc/wintouchemu.cpp
|
misc/wintouchemu.cpp
|
||||||
|
|
||||||
|
# nvapi
|
||||||
|
nvapi/nvapi.cpp
|
||||||
|
|
||||||
# overlay
|
# overlay
|
||||||
overlay/overlay.cpp
|
overlay/overlay.cpp
|
||||||
overlay/window.cpp
|
overlay/window.cpp
|
||||||
overlay/imgui/extensions.cpp
|
overlay/imgui/extensions.cpp
|
||||||
overlay/imgui/impl_dx9.cpp
|
|
||||||
overlay/imgui/impl_spice.cpp
|
overlay/imgui/impl_spice.cpp
|
||||||
overlay/imgui/impl_sw.cpp
|
overlay/imgui/impl_sw.cpp
|
||||||
overlay/windows/acio_status_buffers.cpp
|
overlay/windows/acio_status_buffers.cpp
|
||||||
|
overlay/windows/camera_control.cpp
|
||||||
overlay/windows/card_manager.cpp
|
overlay/windows/card_manager.cpp
|
||||||
|
overlay/windows/drs_dancefloor.cpp
|
||||||
overlay/windows/screen_resize.cpp
|
overlay/windows/screen_resize.cpp
|
||||||
overlay/windows/sdvx_sub.cpp
|
overlay/windows/sdvx_sub.cpp
|
||||||
overlay/windows/config.cpp
|
overlay/windows/config.cpp
|
||||||
@@ -485,11 +536,9 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
|||||||
overlay/windows/iopanel_gfdm.cpp
|
overlay/windows/iopanel_gfdm.cpp
|
||||||
overlay/windows/iopanel_iidx.cpp
|
overlay/windows/iopanel_iidx.cpp
|
||||||
overlay/windows/keypad.cpp
|
overlay/windows/keypad.cpp
|
||||||
overlay/windows/kfcontrol.cpp
|
|
||||||
overlay/windows/log.cpp
|
overlay/windows/log.cpp
|
||||||
overlay/windows/midi.cpp
|
overlay/windows/midi.cpp
|
||||||
overlay/windows/patch_manager.cpp
|
overlay/windows/patch_manager.cpp
|
||||||
overlay/windows/vr.cpp
|
|
||||||
overlay/windows/wnd_manager.cpp
|
overlay/windows/wnd_manager.cpp
|
||||||
|
|
||||||
# rawinput
|
# rawinput
|
||||||
@@ -498,6 +547,12 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
|||||||
rawinput/piuio.cpp
|
rawinput/piuio.cpp
|
||||||
rawinput/touch.cpp
|
rawinput/touch.cpp
|
||||||
rawinput/hotplug.cpp
|
rawinput/hotplug.cpp
|
||||||
|
rawinput/smx.cpp
|
||||||
|
rawinput/smx.h
|
||||||
|
rawinput/smxstage.cpp
|
||||||
|
rawinput/smxstage.h
|
||||||
|
rawinput/smxdedicab.cpp
|
||||||
|
rawinput/smxdedicab.h
|
||||||
|
|
||||||
# reader
|
# reader
|
||||||
reader/reader.cpp
|
reader/reader.cpp
|
||||||
@@ -505,30 +560,12 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
|||||||
reader/structuredmessage.cpp
|
reader/structuredmessage.cpp
|
||||||
reader/crypt.cpp
|
reader/crypt.cpp
|
||||||
|
|
||||||
# script
|
|
||||||
script/api/analogs.cpp
|
|
||||||
script/api/buttons.cpp
|
|
||||||
script/api/capture.cpp
|
|
||||||
script/api/card.cpp
|
|
||||||
script/api/coin.cpp
|
|
||||||
script/api/control.cpp
|
|
||||||
script/api/drs.cpp
|
|
||||||
script/api/iidx.cpp
|
|
||||||
script/api/info.cpp
|
|
||||||
script/api/keypads.cpp
|
|
||||||
script/api/lcd.cpp
|
|
||||||
script/api/lights.cpp
|
|
||||||
script/api/memory.cpp
|
|
||||||
script/api/touch.cpp
|
|
||||||
script/instance.cpp
|
|
||||||
script/lib.cpp
|
|
||||||
script/manager.cpp
|
|
||||||
|
|
||||||
# stubs
|
# stubs
|
||||||
stubs/stubs.cpp
|
stubs/stubs.cpp
|
||||||
|
|
||||||
# touch
|
# touch
|
||||||
touch/touch.cpp
|
touch/touch.cpp
|
||||||
|
touch/touch_indicators.cpp
|
||||||
touch/win7.cpp
|
touch/win7.cpp
|
||||||
touch/win8.cpp
|
touch/win8.cpp
|
||||||
|
|
||||||
@@ -541,6 +578,7 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
|||||||
util/libutils.cpp
|
util/libutils.cpp
|
||||||
util/fileutils.cpp
|
util/fileutils.cpp
|
||||||
util/resutils.cpp
|
util/resutils.cpp
|
||||||
|
util/unity_player.cpp
|
||||||
util/utils.cpp
|
util/utils.cpp
|
||||||
util/memutils.cpp
|
util/memutils.cpp
|
||||||
util/rc4.cpp
|
util/rc4.cpp
|
||||||
@@ -548,17 +586,22 @@ set(SOURCE_FILES ${SOURCE_FILES}
|
|||||||
util/time.cpp
|
util/time.cpp
|
||||||
util/cpuutils.cpp
|
util/cpuutils.cpp
|
||||||
util/netutils.cpp
|
util/netutils.cpp
|
||||||
|
util/sysutils.cpp
|
||||||
util/lz77.cpp
|
util/lz77.cpp
|
||||||
|
util/tapeled.cpp
|
||||||
|
util/execexe.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} PREFIX "Source Files" FILES ${SOURCE_FILES})
|
||||||
|
|
||||||
# spice.exe
|
# spice.exe
|
||||||
###########
|
###########
|
||||||
|
|
||||||
set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc)
|
set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc)
|
||||||
add_executable(spicetools_spice ${SOURCE_FILES} ${RESOURCE_FILES})
|
add_executable(spicetools_spice ${SOURCE_FILES} ${RESOURCE_FILES})
|
||||||
target_link_libraries(spicetools_spice
|
target_link_libraries(spicetools_spice
|
||||||
PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard
|
PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard winhttp
|
||||||
PRIVATE fmt-header-only discord-rpc imgui hash-library minhook openvr_api lua_static imm32 dwmapi)
|
PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features)
|
||||||
set_target_properties(spicetools_spice PROPERTIES PREFIX "")
|
set_target_properties(spicetools_spice PROPERTIES PREFIX "")
|
||||||
set_target_properties(spicetools_spice PROPERTIES OUTPUT_NAME "spice")
|
set_target_properties(spicetools_spice PROPERTIES OUTPUT_NAME "spice")
|
||||||
|
|
||||||
@@ -566,14 +609,33 @@ IF(NOT MSVC)
|
|||||||
set_target_properties(spicetools_spice PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
|
set_target_properties(spicetools_spice PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# spice_laa.exe
|
||||||
|
###########
|
||||||
|
|
||||||
|
set(RESOURCE_FILES build/manifest.manifest build/manifest.rc build/icon.rc cfg/Win32D.rc)
|
||||||
|
add_executable(spicetools_spice_laa ${SOURCE_FILES} ${RESOURCE_FILES})
|
||||||
|
target_link_libraries(spicetools_spice_laa
|
||||||
|
PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard winhttp
|
||||||
|
PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features)
|
||||||
|
set_target_properties(spicetools_spice_laa PROPERTIES PREFIX "")
|
||||||
|
set_target_properties(spicetools_spice_laa PROPERTIES OUTPUT_NAME "spice_laa")
|
||||||
|
target_compile_definitions(spicetools_spice_laa PRIVATE SPICE32_LARGE_ADDRESS_AWARE=1)
|
||||||
|
|
||||||
|
IF(NOT MSVC)
|
||||||
|
set_target_properties(spicetools_spice_laa PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32 -Wl,--large-address-aware")
|
||||||
|
endif()
|
||||||
|
|
||||||
# spice64.exe
|
# spice64.exe
|
||||||
#############
|
#############
|
||||||
|
|
||||||
set(RESOURCE_FILES build/manifest.manifest build/manifest64.rc build/icon.rc cfg/Win32D.rc)
|
set(RESOURCE_FILES build/manifest.manifest build/manifest64.rc build/icon.rc cfg/Win32D.rc)
|
||||||
add_executable(spicetools_spice64 ${SOURCE_FILES} ${RESOURCE_FILES})
|
add_executable(spicetools_spice64 ${SOURCE_FILES} ${RESOURCE_FILES})
|
||||||
|
|
||||||
|
# do NOT link against: mf, mfplat, mfreadwrite; otherwise unity games will break
|
||||||
target_link_libraries(spicetools_spice64
|
target_link_libraries(spicetools_spice64
|
||||||
PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard
|
PUBLIC d3d9 ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard winhttp mfuuid strmiids dxva2
|
||||||
PRIVATE fmt-header-only discord-rpc imgui hash-library minhook openvr_api64 lua_static imm32 dwmapi ntdll)
|
PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features)
|
||||||
|
|
||||||
set_target_properties(spicetools_spice64 PROPERTIES PREFIX "")
|
set_target_properties(spicetools_spice64 PROPERTIES PREFIX "")
|
||||||
set_target_properties(spicetools_spice64 PROPERTIES OUTPUT_NAME "spice64")
|
set_target_properties(spicetools_spice64 PROPERTIES OUTPUT_NAME "spice64")
|
||||||
target_compile_definitions(spicetools_spice64 PRIVATE SPICE64=1)
|
target_compile_definitions(spicetools_spice64 PRIVATE SPICE64=1)
|
||||||
@@ -582,7 +644,6 @@ IF(NOT MSVC)
|
|||||||
set_target_properties(spicetools_spice64 PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-m64")
|
set_target_properties(spicetools_spice64 PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-m64")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
# spicecfg.exe
|
# spicecfg.exe
|
||||||
##############
|
##############
|
||||||
|
|
||||||
@@ -590,8 +651,8 @@ set(SOURCE_FILES ${SOURCE_FILES} launcher/options.h launcher/options.cpp)
|
|||||||
set(RESOURCE_FILES cfg/manifest.manifest cfg/manifest.rc cfg/icon.rc cfg/Win32D.rc)
|
set(RESOURCE_FILES cfg/manifest.manifest cfg/manifest.rc cfg/icon.rc cfg/Win32D.rc)
|
||||||
add_executable(spicetools_cfg WIN32 ${SOURCE_FILES} ${RESOURCE_FILES})
|
add_executable(spicetools_cfg WIN32 ${SOURCE_FILES} ${RESOURCE_FILES})
|
||||||
target_link_libraries(spicetools_cfg
|
target_link_libraries(spicetools_cfg
|
||||||
PUBLIC ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard
|
PUBLIC ws2_32 version comctl32 shlwapi iphlpapi hid secur32 setupapi psapi winmm winscard winhttp strmiids
|
||||||
PRIVATE fmt-header-only discord-rpc imgui hash-library minhook openvr_api lua_static imm32 dwmapi)
|
PRIVATE fmt-header-only discord-rpc imgui hash-library minhook imm32 dwmapi CpuFeatures::cpu_features)
|
||||||
set_target_properties(spicetools_cfg PROPERTIES PREFIX "")
|
set_target_properties(spicetools_cfg PROPERTIES PREFIX "")
|
||||||
set_target_properties(spicetools_cfg PROPERTIES OUTPUT_NAME "spicecfg")
|
set_target_properties(spicetools_cfg PROPERTIES OUTPUT_NAME "spicecfg")
|
||||||
target_compile_definitions(spicetools_cfg PRIVATE SPICETOOLS_SPICECFG_STANDALONE=1)
|
target_compile_definitions(spicetools_cfg PRIVATE SPICETOOLS_SPICECFG_STANDALONE=1)
|
||||||
@@ -649,6 +710,36 @@ if(NOT MSVC)
|
|||||||
set_target_properties(spicetools_stubs_kld64 PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-m64")
|
set_target_properties(spicetools_stubs_kld64 PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-m64")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# nvcuda.dll
|
||||||
|
set(SOURCE_FILES stubs/nvcuda.cpp)
|
||||||
|
add_library(spicetools_stubs_nvcuda SHARED ${SOURCE_FILES} stubs/nvcuda.def)
|
||||||
|
set_target_properties(spicetools_stubs_nvcuda PROPERTIES PREFIX "")
|
||||||
|
set_target_properties(spicetools_stubs_nvcuda PROPERTIES OUTPUT_NAME "nvcuda")
|
||||||
|
|
||||||
|
if(NOT MSVC)
|
||||||
|
set_target_properties(spicetools_stubs_nvcuda PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-m64")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# nvcuvid.dll
|
||||||
|
set(SOURCE_FILES stubs/nvcuvid.cpp)
|
||||||
|
add_library(spicetools_stubs_nvcuvid SHARED ${SOURCE_FILES} stubs/nvcuvid.def)
|
||||||
|
set_target_properties(spicetools_stubs_nvcuvid PROPERTIES PREFIX "")
|
||||||
|
set_target_properties(spicetools_stubs_nvcuvid PROPERTIES OUTPUT_NAME "nvcuvid")
|
||||||
|
|
||||||
|
if(NOT MSVC)
|
||||||
|
set_target_properties(spicetools_stubs_nvcuvid PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-m64")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# nvEncodeAPI64.dll
|
||||||
|
set(SOURCE_FILES stubs/nvEncodeAPI64.cpp)
|
||||||
|
add_library(spicetools_stubs_nvEncodeAPI64 SHARED ${SOURCE_FILES} stubs/nvEncodeAPI64.def)
|
||||||
|
set_target_properties(spicetools_stubs_nvEncodeAPI64 PROPERTIES PREFIX "")
|
||||||
|
set_target_properties(spicetools_stubs_nvEncodeAPI64 PROPERTIES OUTPUT_NAME "nvEncodeAPI64")
|
||||||
|
|
||||||
|
if(NOT MSVC)
|
||||||
|
set_target_properties(spicetools_stubs_nvEncodeAPI64 PROPERTIES COMPILE_FLAGS "-m64" LINK_FLAGS "-m64")
|
||||||
|
endif()
|
||||||
|
|
||||||
# output directories
|
# output directories
|
||||||
####################
|
####################
|
||||||
|
|
||||||
@@ -658,14 +749,14 @@ set_target_properties(spicetools_cfg
|
|||||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools")
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools")
|
||||||
|
|
||||||
# output 32bit
|
# output 32bit
|
||||||
set_target_properties(spicetools_spice spicetools_stubs_kbt spicetools_stubs_kld
|
set_target_properties(spicetools_spice spicetools_spice_laa spicetools_stubs_kbt spicetools_stubs_kld
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/archive32"
|
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/archive32"
|
||||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools/32"
|
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools/32"
|
||||||
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools/32")
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools/32")
|
||||||
|
|
||||||
# output 64bit
|
# output 64bit
|
||||||
set_target_properties(spicetools_spice64 spicetools_stubs_kbt64 spicetools_stubs_kld64
|
set_target_properties(spicetools_spice64 spicetools_stubs_kbt64 spicetools_stubs_kld64 spicetools_stubs_nvcuda spicetools_stubs_nvcuvid spicetools_stubs_nvEncodeAPI64
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/archive64"
|
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/archive64"
|
||||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools/64"
|
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/spicetools/64"
|
||||||
|
|||||||
+5
-4
@@ -1,6 +1,7 @@
|
|||||||
FROM spicetools/deps
|
FROM spicetools/deps
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
RUN chown user:user /src
|
|
||||||
USER user
|
COPY --from=gitroot . /src/.git
|
||||||
COPY --chown=user:user . /src
|
COPY . /src/src/spice2x
|
||||||
CMD ./build_all.sh
|
WORKDIR /src/src/spice2x
|
||||||
|
ENTRYPOINT ["./build_all.sh"]
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ If you need more examples, you can check the example code.
|
|||||||
"id": 1,
|
"id": 1,
|
||||||
"module": "card",
|
"module": "card",
|
||||||
"function": "insert",
|
"function": "insert",
|
||||||
"params": [0, "E004000000000000"]
|
"params": [0, "E004010000000000"]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
#### Response
|
#### Response
|
||||||
@@ -181,6 +181,12 @@ All of those three modules have equally named methods for you to call.
|
|||||||
- removes the override value from the objects specified by name
|
- removes the override value from the objects specified by name
|
||||||
- if no names were passed, all overrides will be removed
|
- if no names were passed, all overrides will be removed
|
||||||
|
|
||||||
|
##### Additional API for lights
|
||||||
|
- read(name: string, ...)
|
||||||
|
- same as read(), but you can specify light names
|
||||||
|
- write_reset(name: str, ...)
|
||||||
|
- same as write_reset(), but it accepts a flat list of strings
|
||||||
|
|
||||||
#### Touch
|
#### Touch
|
||||||
- read()
|
- read()
|
||||||
- returns an array of state objects containing id, x and y
|
- returns an array of state objects containing id, x and y
|
||||||
@@ -246,6 +252,18 @@ which also means that your hex edits are applicable directly.
|
|||||||
- info()
|
- info()
|
||||||
- returns information about the serial LCD controller some games use
|
- returns information about the serial LCD controller some games use
|
||||||
|
|
||||||
|
#### Resize
|
||||||
|
- image_resize_enable(enable: bool)
|
||||||
|
- enables or disables image resize state
|
||||||
|
- image_resize_set_scene(scene: int)
|
||||||
|
- sets the active scene for image resize state; set to 0 to disable resize
|
||||||
|
|
||||||
|
## Native wrapper libraries
|
||||||
|
Spicetools provides wrapper libraries in: Arduino, C++, Dart, and Python.
|
||||||
|
Python is the only one that is fully spec compliant.
|
||||||
|
Other libraries may be missing features and contain bugs; please feel free to
|
||||||
|
contribute code to fill the gaps if you work on a project using these libraries.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
Unless otherwise noted, all files are licensed under the GPLv3.
|
Unless otherwise noted, all files are licensed under the GPLv3.
|
||||||
See the LICENSE file for the full license text.
|
See the LICENSE file for the full license text.
|
||||||
|
|||||||
@@ -70,6 +70,9 @@ void acio::attach() {
|
|||||||
libraryhook_hook_library("libacioex.dll", acio::DLL_INSTANCE);
|
libraryhook_hook_library("libacioex.dll", acio::DLL_INSTANCE);
|
||||||
libraryhook_hook_library("libacio_ex.dll", acio::DLL_INSTANCE);
|
libraryhook_hook_library("libacio_ex.dll", acio::DLL_INSTANCE);
|
||||||
libraryhook_hook_library("libacio_old.dll", acio::DLL_INSTANCE);
|
libraryhook_hook_library("libacio_old.dll", acio::DLL_INSTANCE);
|
||||||
|
// libacioEx.dll for Road Fighters 3D
|
||||||
|
// needed as comparisons in LoadLibrary hooks are case-sensitive
|
||||||
|
libraryhook_hook_library("libacioEx.dll", acio::DLL_INSTANCE);
|
||||||
libraryhook_enable(avs::game::DLL_INSTANCE);
|
libraryhook_enable(avs::game::DLL_INSTANCE);
|
||||||
|
|
||||||
// get hook mode
|
// get hook mode
|
||||||
|
|||||||
+288
-2
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "avs/game.h"
|
#include "avs/game.h"
|
||||||
#include "games/ddr/io.h"
|
#include "games/ddr/io.h"
|
||||||
|
#include "games/ddr/ddr.h"
|
||||||
#include "games/sdvx/sdvx.h"
|
#include "games/sdvx/sdvx.h"
|
||||||
#include "games/sdvx/io.h"
|
#include "games/sdvx/io.h"
|
||||||
#include "games/drs/io.h"
|
#include "games/drs/io.h"
|
||||||
@@ -9,6 +10,7 @@
|
|||||||
#include "misc/eamuse.h"
|
#include "misc/eamuse.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
#include "util/utils.h"
|
#include "util/utils.h"
|
||||||
|
#include "util/tapeled.h"
|
||||||
|
|
||||||
using namespace GameAPI;
|
using namespace GameAPI;
|
||||||
|
|
||||||
@@ -399,6 +401,148 @@ static long __cdecl ac_io_bi2a_control_led_bright(size_t index, uint8_t brightne
|
|||||||
if (light.light2 >= 0) {
|
if (light.light2 >= 0) {
|
||||||
Lights::writeLight(RI_MGR, lights[light.light2], brightness / light.max);
|
Lights::writeLight(RI_MGR, lights[light.light2], brightness / light.max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DANCERUSH
|
||||||
|
} else if (avs::game::is_model("REC")) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Control R G B
|
||||||
|
* ==============================
|
||||||
|
* CARD UNIT 13 14 15
|
||||||
|
* TITLE PANEL 28 29 30
|
||||||
|
* MONITOR SIDE LEFT (tape LED - see ac_io_bi2a_control_tapeled_bright)
|
||||||
|
* MONITOR SIDE RIGHT (tape LED - see ac_io_bi2a_control_tapeled_bright)
|
||||||
|
*
|
||||||
|
* Values go up to 127.
|
||||||
|
*
|
||||||
|
* Control Index
|
||||||
|
* ==================
|
||||||
|
* 1P LEFT 11
|
||||||
|
* 1P RIGHT 12
|
||||||
|
* 1P UP 9
|
||||||
|
* 1P DOWN 10
|
||||||
|
* 1P START 8
|
||||||
|
* 2P LEFT 19
|
||||||
|
* 2P RIGHT 20
|
||||||
|
* 2P UP 17
|
||||||
|
* 2P DOWN 18
|
||||||
|
* 2P START 16
|
||||||
|
*
|
||||||
|
* Values go up to 127.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static const struct {
|
||||||
|
int light;
|
||||||
|
float max;
|
||||||
|
} mapping[] = {
|
||||||
|
{ -1, 0 }, // 0
|
||||||
|
{ -1, 0 }, // 1
|
||||||
|
{ -1, 0 }, // 2
|
||||||
|
{ -1, 0 }, // 3
|
||||||
|
{ -1, 0 }, // 4
|
||||||
|
{ -1, 0 }, // 5
|
||||||
|
{ -1, 0 }, // 6
|
||||||
|
{ -1, 0 }, // 7
|
||||||
|
{ games::drs::Lights::P1_START, 127 }, // 8
|
||||||
|
{ games::drs::Lights::P1_MENU_UP, 127 }, // 9
|
||||||
|
{ games::drs::Lights::P1_MENU_DOWN, 127 }, // 10
|
||||||
|
{ games::drs::Lights::P1_MENU_LEFT, 127 }, // 11
|
||||||
|
{ games::drs::Lights::P1_MENU_RIGHT, 127 }, // 12
|
||||||
|
{ games::drs::Lights::CARD_READER_R, 127 }, // 13
|
||||||
|
{ games::drs::Lights::CARD_READER_G, 127 }, // 14
|
||||||
|
{ games::drs::Lights::CARD_READER_B, 127 }, // 15
|
||||||
|
{ games::drs::Lights::P2_START, 127 }, // 16
|
||||||
|
{ games::drs::Lights::P2_MENU_UP, 127 }, // 17
|
||||||
|
{ games::drs::Lights::P2_MENU_DOWN, 127 }, // 18
|
||||||
|
{ games::drs::Lights::P2_MENU_LEFT, 127 }, // 19
|
||||||
|
{ games::drs::Lights::P2_MENU_RIGHT, 127 }, // 20
|
||||||
|
{ -1, 0 }, // 21
|
||||||
|
{ -1, 0 }, // 22
|
||||||
|
{ -1, 0 }, // 23
|
||||||
|
{ -1, 0 }, // 24
|
||||||
|
{ -1, 0 }, // 25
|
||||||
|
{ -1, 0 }, // 26
|
||||||
|
{ -1, 0 }, // 27
|
||||||
|
{ games::drs::Lights::TITLE_PANEL_R, 127 }, // 28
|
||||||
|
{ games::drs::Lights::TITLE_PANEL_G, 127 }, // 29
|
||||||
|
{ games::drs::Lights::TITLE_PANEL_B, 127 }, // 30
|
||||||
|
};
|
||||||
|
|
||||||
|
// ignore index out of range
|
||||||
|
if (index > std::size(mapping)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get lights
|
||||||
|
auto &lights = games::drs::get_lights();
|
||||||
|
|
||||||
|
// get light from mapping
|
||||||
|
auto light = mapping[index];
|
||||||
|
|
||||||
|
// write lights
|
||||||
|
if (light.light >= 0) {
|
||||||
|
Lights::writeLight(RI_MGR, lights[light.light], brightness / light.max);
|
||||||
|
} else {
|
||||||
|
log_warning("drs", "light unset {} {}", index, (int) brightness);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DanceDanceRevolution
|
||||||
|
} else if (avs::game::is_model("MDX")) {
|
||||||
|
|
||||||
|
static const struct {
|
||||||
|
int light;
|
||||||
|
float max;
|
||||||
|
} mapping[] = {
|
||||||
|
{ -1, 0 }, // 0
|
||||||
|
{ -1, 0 }, // 1
|
||||||
|
{ -1, 0 }, // 2
|
||||||
|
{ -1, 0 }, // 3
|
||||||
|
{ -1, 0 }, // 4
|
||||||
|
{ -1, 0 }, // 5
|
||||||
|
{ -1, 0 }, // 6
|
||||||
|
{ -1, 0 }, // 7
|
||||||
|
{ games::ddr::Lights::GOLD_P1_MENU_START, 127 }, // 8
|
||||||
|
{ games::ddr::Lights::GOLD_P1_MENU_UP, 127 }, // 9
|
||||||
|
{ games::ddr::Lights::GOLD_P1_MENU_DOWN, 127 }, // 10
|
||||||
|
{ games::ddr::Lights::GOLD_P1_MENU_LEFT, 127 }, // 11
|
||||||
|
{ games::ddr::Lights::GOLD_P1_MENU_RIGHT, 127 }, // 12
|
||||||
|
{ games::ddr::Lights::GOLD_P1_CARD_UNIT_R, 127 }, // 13
|
||||||
|
{ games::ddr::Lights::GOLD_P1_CARD_UNIT_G, 127 }, // 14
|
||||||
|
{ games::ddr::Lights::GOLD_P1_CARD_UNIT_B, 127 }, // 15
|
||||||
|
{ games::ddr::Lights::GOLD_P2_MENU_START, 127 }, // 16
|
||||||
|
{ games::ddr::Lights::GOLD_P2_MENU_UP, 127 }, // 17
|
||||||
|
{ games::ddr::Lights::GOLD_P2_MENU_DOWN, 127 }, // 18
|
||||||
|
{ games::ddr::Lights::GOLD_P2_MENU_LEFT, 127 }, // 19
|
||||||
|
{ games::ddr::Lights::GOLD_P2_MENU_RIGHT, 127 }, // 20
|
||||||
|
{ games::ddr::Lights::GOLD_P2_CARD_UNIT_R, 0 }, // 21
|
||||||
|
{ games::ddr::Lights::GOLD_P2_CARD_UNIT_G, 0 }, // 22
|
||||||
|
{ games::ddr::Lights::GOLD_P2_CARD_UNIT_B, 0 }, // 23
|
||||||
|
{ -1, 0 }, // 24
|
||||||
|
{ -1, 0 }, // 25
|
||||||
|
{ -1, 0 }, // 26
|
||||||
|
{ -1, 0 }, // 27
|
||||||
|
{ games::ddr::Lights::GOLD_TITLE_PANEL_LEFT, 0 }, // 28
|
||||||
|
{ games::ddr::Lights::GOLD_TITLE_PANEL_CENTER, 0 }, // 29
|
||||||
|
{ games::ddr::Lights::GOLD_TITLE_PANEL_RIGHT, 0 }, // 30
|
||||||
|
{ games::ddr::Lights::GOLD_P1_WOOFER_CORNER, 0 }, // 31
|
||||||
|
{ games::ddr::Lights::GOLD_P2_WOOFER_CORNER, 0 } // 32
|
||||||
|
};
|
||||||
|
|
||||||
|
// ignore index out of range
|
||||||
|
if (index > std::size(mapping)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get lights
|
||||||
|
auto &lights = games::ddr::get_lights();
|
||||||
|
|
||||||
|
// get light from mapping
|
||||||
|
auto light = mapping[index];
|
||||||
|
|
||||||
|
// write lights
|
||||||
|
if (light.light >= 0) {
|
||||||
|
Lights::writeLight(RI_MGR, lights[light.light], brightness / light.max);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// return success
|
// return success
|
||||||
@@ -443,7 +587,7 @@ static bool __cdecl ac_io_bi2a_tapeled_init_is_finished() {
|
|||||||
static bool __cdecl ac_io_bi2a_control_tapeled_rec_set(uint8_t* data, size_t x_sz, size_t y_sz) {
|
static bool __cdecl ac_io_bi2a_control_tapeled_rec_set(uint8_t* data, size_t x_sz, size_t y_sz) {
|
||||||
|
|
||||||
// check dimensions
|
// check dimensions
|
||||||
if (x_sz != 38 || y_sz != 49) {
|
if (x_sz != DRS_TAPELED_COLS || y_sz != DRS_TAPELED_ROWS) {
|
||||||
log_fatal("drs", "DRS tapeled wrong dimensions");
|
log_fatal("drs", "DRS tapeled wrong dimensions");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,9 +602,151 @@ static bool __cdecl ac_io_bi2a_control_tapeled_rec_set(uint8_t* data, size_t x_s
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: this controls the upright RGB bars on the sides
|
// TODO: DRS tape lights
|
||||||
static bool __cdecl ac_io_bi2a_control_tapeled_bright(size_t off1, size_t off2,
|
static bool __cdecl ac_io_bi2a_control_tapeled_bright(size_t off1, size_t off2,
|
||||||
uint8_t r, uint8_t g, uint8_t b, uint8_t bank) {
|
uint8_t r, uint8_t g, uint8_t b, uint8_t bank) {
|
||||||
|
|
||||||
|
if (!tapeledutils::is_enabled()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (avs::game::is_model("MDX")) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* r, g, b values range from [0-255]
|
||||||
|
* bank always seems to be [0]
|
||||||
|
*
|
||||||
|
* [off1.off2] [LEDs] [tape name]
|
||||||
|
* 0.0 25 P1 Foot Up (0.0 to 0.24, inclusive)
|
||||||
|
* 0.25 25 P1 Foot Right
|
||||||
|
* 1.0 25 P1 Foot Left
|
||||||
|
* 1.25 25 P1 Foot Down
|
||||||
|
*
|
||||||
|
* 2.0 25 P2 Foot Up
|
||||||
|
* 2.25 25 P2 Foot Right
|
||||||
|
* 3.0 25 P2 Foot Left
|
||||||
|
* 3.25 25 P2 Foot Down
|
||||||
|
*
|
||||||
|
* 5.0 50 Top Panel
|
||||||
|
* 6.0 50 Monitor side left
|
||||||
|
* 7.0 50 Monitor side right
|
||||||
|
*/
|
||||||
|
|
||||||
|
// In order to set the data that can be output via Spice API, we first
|
||||||
|
// need to figure out which device in our buffers this data belongs to
|
||||||
|
int device = -1;
|
||||||
|
if (off1 == 0) {
|
||||||
|
if (off2 < 25) device = 0; // P1 Foot Up
|
||||||
|
else device = 1; // P1 Foot Right
|
||||||
|
} else if (off1 == 1) {
|
||||||
|
if (off2 < 25) device = 2; // P1 Foot Left
|
||||||
|
else device = 3; // P1 Foot Down
|
||||||
|
} else if (off1 == 2) {
|
||||||
|
if (off2 < 25) device = 4; // P2 Foot Up
|
||||||
|
else device = 5; // P2 Foot Right
|
||||||
|
} else if (off1 == 3) {
|
||||||
|
if (off2 < 25) device = 6; // P2 Foot Left
|
||||||
|
else device = 7; // P2 Foot Down
|
||||||
|
} else if (off1 >= 5 && off1 <= 7) {
|
||||||
|
device = off1 + 3; // Top Panel / Monitor Side Left / Monitor Side Right
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device != -1) {
|
||||||
|
// We subtract 25 from off2 to get the device's LED index, if it's for one of the
|
||||||
|
// arrow panels that is on the latter half of the logical strip
|
||||||
|
size_t subtractor = 0;
|
||||||
|
if (off1 <= 3 && off2 >= 25) {
|
||||||
|
subtractor = 25;
|
||||||
|
}
|
||||||
|
size_t led_index = off2 - subtractor;
|
||||||
|
|
||||||
|
games::ddr::DDR_TAPELEDS[device][led_index][0] = r;
|
||||||
|
games::ddr::DDR_TAPELEDS[device][led_index][1] = g;
|
||||||
|
games::ddr::DDR_TAPELEDS[device][led_index][2] = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct TapeLedMapping {
|
||||||
|
bool split; // true == 50 LEDs for one light, false == 25 for two lights
|
||||||
|
uint8_t index_r0, index_g0, index_b0;
|
||||||
|
uint8_t index_r1, index_g1, index_b1;
|
||||||
|
size_t index_for_avg0 = UINT8_MAX;
|
||||||
|
size_t index_for_avg1 = UINT8_MAX;
|
||||||
|
|
||||||
|
TapeLedMapping(
|
||||||
|
uint8_t index_r0, uint8_t index_g0, uint8_t index_b0,
|
||||||
|
uint8_t index_r1, uint8_t index_g1, uint8_t index_b1)
|
||||||
|
: index_r0(index_r0), index_g0(index_g0), index_b0(index_b0),
|
||||||
|
index_r1(index_r1), index_g1(index_g1), index_b1(index_b1) {
|
||||||
|
|
||||||
|
split = (index_r1 != UINT8_MAX);
|
||||||
|
if (split) {
|
||||||
|
index_for_avg0 = tapeledutils::get_led_index_using_avg_algo(25);
|
||||||
|
index_for_avg1 = index_for_avg0 + 25;
|
||||||
|
} else {
|
||||||
|
index_for_avg0 = tapeledutils::get_led_index_using_avg_algo(50);
|
||||||
|
index_for_avg1 = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} mapping[] = {
|
||||||
|
{
|
||||||
|
games::ddr::Lights::GOLD_P1_FOOT_UP_AVG_R, games::ddr::Lights::GOLD_P1_FOOT_UP_AVG_G, games::ddr::Lights::GOLD_P1_FOOT_UP_AVG_B,
|
||||||
|
games::ddr::Lights::GOLD_P1_FOOT_RIGHT_AVG_R, games::ddr::Lights::GOLD_P1_FOOT_RIGHT_AVG_G, games::ddr::Lights::GOLD_P1_FOOT_RIGHT_AVG_B
|
||||||
|
},
|
||||||
|
{
|
||||||
|
games::ddr::Lights::GOLD_P1_FOOT_LEFT_AVG_R, games::ddr::Lights::GOLD_P1_FOOT_LEFT_AVG_G, games::ddr::Lights::GOLD_P1_FOOT_LEFT_AVG_B,
|
||||||
|
games::ddr::Lights::GOLD_P1_FOOT_DOWN_AVG_R, games::ddr::Lights::GOLD_P1_FOOT_DOWN_AVG_G, games::ddr::Lights::GOLD_P1_FOOT_DOWN_AVG_B
|
||||||
|
},
|
||||||
|
{
|
||||||
|
games::ddr::Lights::GOLD_P2_FOOT_UP_AVG_R, games::ddr::Lights::GOLD_P2_FOOT_UP_AVG_G, games::ddr::Lights::GOLD_P2_FOOT_UP_AVG_B,
|
||||||
|
games::ddr::Lights::GOLD_P2_FOOT_RIGHT_AVG_R, games::ddr::Lights::GOLD_P2_FOOT_RIGHT_AVG_G, games::ddr::Lights::GOLD_P2_FOOT_RIGHT_AVG_B
|
||||||
|
},
|
||||||
|
{
|
||||||
|
games::ddr::Lights::GOLD_P2_FOOT_LEFT_AVG_R, games::ddr::Lights::GOLD_P2_FOOT_LEFT_AVG_G, games::ddr::Lights::GOLD_P2_FOOT_LEFT_AVG_B,
|
||||||
|
games::ddr::Lights::GOLD_P2_FOOT_DOWN_AVG_R, games::ddr::Lights::GOLD_P2_FOOT_DOWN_AVG_G, games::ddr::Lights::GOLD_P2_FOOT_DOWN_AVG_B
|
||||||
|
},
|
||||||
|
{
|
||||||
|
games::ddr::Lights::GOLD_TOP_PANEL_AVG_R, games::ddr::Lights::GOLD_TOP_PANEL_AVG_G, games::ddr::Lights::GOLD_TOP_PANEL_AVG_B,
|
||||||
|
UINT8_MAX, UINT8_MAX, UINT8_MAX
|
||||||
|
},
|
||||||
|
{
|
||||||
|
UINT8_MAX, UINT8_MAX, UINT8_MAX,
|
||||||
|
UINT8_MAX, UINT8_MAX, UINT8_MAX
|
||||||
|
},
|
||||||
|
{
|
||||||
|
games::ddr::Lights::GOLD_MONITOR_SIDE_LEFT_AVG_R, games::ddr::Lights::GOLD_MONITOR_SIDE_LEFT_AVG_G, games::ddr::Lights::GOLD_MONITOR_SIDE_LEFT_AVG_B,
|
||||||
|
UINT8_MAX, UINT8_MAX, UINT8_MAX
|
||||||
|
},
|
||||||
|
{
|
||||||
|
games::ddr::Lights::GOLD_MONITOR_SIDE_RIGHT_AVG_R, games::ddr::Lights::GOLD_MONITOR_SIDE_RIGHT_AVG_G, games::ddr::Lights::GOLD_MONITOR_SIDE_RIGHT_AVG_B,
|
||||||
|
UINT8_MAX, UINT8_MAX, UINT8_MAX
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (off1 < std::size(mapping)) {
|
||||||
|
auto &map = mapping[off1];
|
||||||
|
|
||||||
|
size_t off2_match = -1;
|
||||||
|
if (!map.split || off2 < 25) {
|
||||||
|
off2_match = map.index_for_avg0;
|
||||||
|
} else {
|
||||||
|
off2_match = map.index_for_avg1;
|
||||||
|
}
|
||||||
|
if (off2_match == off2 && map.index_r0 != UINT8_MAX) {
|
||||||
|
auto &lights = games::ddr::get_lights();
|
||||||
|
if (!map.split || off2 < 25) {
|
||||||
|
Lights::writeLight(RI_MGR, lights[map.index_r0], r / 255.f);
|
||||||
|
Lights::writeLight(RI_MGR, lights[map.index_g0], g / 255.f);
|
||||||
|
Lights::writeLight(RI_MGR, lights[map.index_b0], b / 255.f);
|
||||||
|
} else {
|
||||||
|
Lights::writeLight(RI_MGR, lights[map.index_r1], r / 255.f);
|
||||||
|
Lights::writeLight(RI_MGR, lights[map.index_g1], g / 255.f);
|
||||||
|
Lights::writeLight(RI_MGR, lights[map.index_b1], b / 255.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,11 @@ static int __cdecl ac_io_bmpu_control_1p_start_led_off() {
|
|||||||
if (avs::game::is_model("KDM")) {
|
if (avs::game::is_model("KDM")) {
|
||||||
auto &lights = games::dea::get_lights();
|
auto &lights = games::dea::get_lights();
|
||||||
Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P1Start), 0.f);
|
Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P1Start), 0.f);
|
||||||
|
|
||||||
|
// MUSECA
|
||||||
|
} else if (avs::game::is_model("PIX")) {
|
||||||
|
auto &lights = games::museca::get_lights();
|
||||||
|
Lights::writeLight(RI_MGR, lights.at(games::museca::Lights::Start), 0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -44,6 +49,11 @@ static int __cdecl ac_io_bmpu_control_1p_start_led_on() {
|
|||||||
if (avs::game::is_model("KDM")) {
|
if (avs::game::is_model("KDM")) {
|
||||||
auto &lights = games::dea::get_lights();
|
auto &lights = games::dea::get_lights();
|
||||||
Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P1Start), 1.f);
|
Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P1Start), 1.f);
|
||||||
|
|
||||||
|
// MUSECA
|
||||||
|
} else if (avs::game::is_model("PIX")) {
|
||||||
|
auto &lights = games::museca::get_lights();
|
||||||
|
Lights::writeLight(RI_MGR, lights.at(games::museca::Lights::Start), 1.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -55,6 +65,11 @@ static int __cdecl ac_io_bmpu_control_2p_start_led_off() {
|
|||||||
if (avs::game::is_model("KDM")) {
|
if (avs::game::is_model("KDM")) {
|
||||||
auto &lights = games::dea::get_lights();
|
auto &lights = games::dea::get_lights();
|
||||||
Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P2Start), 0.f);
|
Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P2Start), 0.f);
|
||||||
|
|
||||||
|
// MUSECA
|
||||||
|
} else if (avs::game::is_model("PIX")) {
|
||||||
|
auto &lights = games::museca::get_lights();
|
||||||
|
Lights::writeLight(RI_MGR, lights.at(games::museca::Lights::Keypad), 0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@@ -66,6 +81,11 @@ static int __cdecl ac_io_bmpu_control_2p_start_led_on() {
|
|||||||
if (avs::game::is_model("KDM")) {
|
if (avs::game::is_model("KDM")) {
|
||||||
auto &lights = games::dea::get_lights();
|
auto &lights = games::dea::get_lights();
|
||||||
Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P2Start), 1.f);
|
Lights::writeLight(RI_MGR, lights.at(games::dea::Lights::P2Start), 1.f);
|
||||||
|
|
||||||
|
// MUSECA
|
||||||
|
} else if (avs::game::is_model("PIX")) {
|
||||||
|
auto &lights = games::museca::get_lights();
|
||||||
|
Lights::writeLight(RI_MGR, lights.at(games::museca::Lights::Keypad), 1.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
+38
-3
@@ -25,6 +25,13 @@ struct ICCA_STATUS {
|
|||||||
uint32_t key_edge;
|
uint32_t key_edge;
|
||||||
uint32_t key_level;
|
uint32_t key_level;
|
||||||
};
|
};
|
||||||
|
struct ICCA_STATUS_LA9 {
|
||||||
|
uint8_t status_code;
|
||||||
|
uint8_t card_in;
|
||||||
|
uint8_t uid[8];
|
||||||
|
uint8_t error;
|
||||||
|
uint8_t uid2[8];
|
||||||
|
};
|
||||||
static_assert(sizeof(struct ICCA_STATUS) == 24, "ICCA_STATUS must be 24 bytes");
|
static_assert(sizeof(struct ICCA_STATUS) == 24, "ICCA_STATUS must be 24 bytes");
|
||||||
|
|
||||||
enum ICCA_WORKFLOW {
|
enum ICCA_WORKFLOW {
|
||||||
@@ -52,6 +59,7 @@ struct ICCA_UNIT {
|
|||||||
char key_serial = 0;
|
char key_serial = 0;
|
||||||
bool uid_skip = false;
|
bool uid_skip = false;
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
|
int felica_retries = 0;
|
||||||
};
|
};
|
||||||
static ICCA_UNIT ICCA_UNITS[2] {};
|
static ICCA_UNIT ICCA_UNITS[2] {};
|
||||||
static bool IS_LAST_CARD_FELICA = false;
|
static bool IS_LAST_CARD_FELICA = false;
|
||||||
@@ -88,14 +96,25 @@ static inline void update_card(int unit_id) {
|
|||||||
// eamio keypress
|
// eamio keypress
|
||||||
int index = unit_id > 0 && icca_get_active_count() > 1 ? 1 : 0;
|
int index = unit_id > 0 && icca_get_active_count() > 1 ? 1 : 0;
|
||||||
bool kb_insert_press = (eamuse_get_keypad_state(index) & (1 << EAM_IO_INSERT)) > 0;
|
bool kb_insert_press = (eamuse_get_keypad_state(index) & (1 << EAM_IO_INSERT)) > 0;
|
||||||
|
static bool kb_insert_press_old[2] = {false, false};
|
||||||
|
|
||||||
// get unit
|
// get unit
|
||||||
ICCA_UNIT *unit = &ICCA_UNITS[unit_id];
|
ICCA_UNIT *unit = &ICCA_UNITS[unit_id];
|
||||||
|
|
||||||
|
const bool card_presented = eamuse_card_insert_consume(icca_get_active_count(), unit_id);
|
||||||
|
const bool key_pressed = (kb_insert_press && !kb_insert_press_old[unit_id]);
|
||||||
|
|
||||||
|
// beatstream and nostalgia have logic that requires ac_io_icca_get_uid_felica to return the
|
||||||
|
// exact same card number multiple times in a row in order for the card number to be read...
|
||||||
|
// for whatever reason setting this to 3-4 doesn't work the very first time the game boots up
|
||||||
|
// so we use 10 just to be safe
|
||||||
|
const bool need_felica_retries = avs::game::is_model({"NBT", "PAN"});
|
||||||
|
if (need_felica_retries && (card_presented || key_pressed)) {
|
||||||
|
unit->felica_retries = 10;
|
||||||
|
}
|
||||||
|
|
||||||
// check for card insert
|
// check for card insert
|
||||||
static bool kb_insert_press_old[2] = {false, false};
|
if (card_presented || key_pressed || (0 < unit->felica_retries)) {
|
||||||
if (eamuse_card_insert_consume(icca_get_active_count(), unit_id) ||
|
|
||||||
(kb_insert_press && !kb_insert_press_old[unit_id])) {
|
|
||||||
if (!unit->card_cmd_pressed) {
|
if (!unit->card_cmd_pressed) {
|
||||||
unit->card_cmd_pressed = true;
|
unit->card_cmd_pressed = true;
|
||||||
if (unit->state == GET_USERID || unit->state == CLOSE_EJECT || unit->state == STEP) {
|
if (unit->state == GET_USERID || unit->state == CLOSE_EJECT || unit->state == STEP) {
|
||||||
@@ -288,7 +307,18 @@ static char __cdecl ac_io_icca_get_status(void *a1, void *a2) {
|
|||||||
|
|
||||||
// funny workaround
|
// funny workaround
|
||||||
if (acio::ICCA_COMPAT_ACTIVE) {
|
if (acio::ICCA_COMPAT_ACTIVE) {
|
||||||
|
if (avs::game::is_model("LA9")) {
|
||||||
|
auto p = (ICCA_STATUS*) status;
|
||||||
|
|
||||||
|
ICCA_STATUS_LA9 p_la9;
|
||||||
|
p_la9.status_code = unit->state;
|
||||||
|
p_la9.card_in = unit->card_in;
|
||||||
|
memcpy(p_la9.uid, p->uid, sizeof(p_la9.uid));
|
||||||
|
p_la9.error = p->error;
|
||||||
|
memcpy(p_la9.uid2, p->uid, sizeof(p_la9.uid));
|
||||||
|
|
||||||
|
memcpy(status, &p_la9, sizeof(ICCA_STATUS_LA9));
|
||||||
|
} else {
|
||||||
// the struct is different (28 bytes instead of 24) but nobody ain't got time for that
|
// the struct is different (28 bytes instead of 24) but nobody ain't got time for that
|
||||||
auto p = (ICCA_STATUS*) status;
|
auto p = (ICCA_STATUS*) status;
|
||||||
p->error = p->key_level << 16;
|
p->error = p->key_level << 16;
|
||||||
@@ -300,6 +330,7 @@ static char __cdecl ac_io_icca_get_status(void *a1, void *a2) {
|
|||||||
p->uid[sizeof(p->uid) - 2] = 0;
|
p->uid[sizeof(p->uid) - 2] = 0;
|
||||||
p->uid[sizeof(p->uid) - 1] = 0;
|
p->uid[sizeof(p->uid) - 1] = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -330,6 +361,10 @@ static char __cdecl ac_io_icca_get_uid_felica(int unit_id, char *card) {
|
|||||||
card[8] = (char) (felica ? 1 : 0);
|
card[8] = (char) (felica ? 1 : 0);
|
||||||
IS_LAST_CARD_FELICA = felica;
|
IS_LAST_CARD_FELICA = felica;
|
||||||
|
|
||||||
|
if (0 < unit->felica_retries) {
|
||||||
|
unit->felica_retries--;
|
||||||
|
}
|
||||||
|
|
||||||
// check for error
|
// check for error
|
||||||
return unit->state != ERR_GETUID;
|
return unit->state != ERR_GETUID;
|
||||||
}
|
}
|
||||||
|
|||||||
+68
-16
@@ -16,13 +16,26 @@ static uint8_t COUNTER = 0;
|
|||||||
// buffers
|
// buffers
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
static struct {
|
static struct {
|
||||||
uint8_t STATUS_BUFFER_17[7][STATUS_BUFFER_SIZE] {};
|
uint8_t STATUS_BUFFER_P1[7][STATUS_BUFFER_SIZE] {};
|
||||||
uint8_t STATUS_BUFFER_18[7][STATUS_BUFFER_SIZE] {};
|
uint8_t STATUS_BUFFER_P2[7][STATUS_BUFFER_SIZE] {};
|
||||||
} BUFFERS {};
|
} BUFFERS {};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
static bool STATUS_BUFFER_FREEZE = false;
|
static bool STATUS_BUFFER_FREEZE = false;
|
||||||
|
|
||||||
|
typedef uint64_t (__cdecl *ARK_GET_TICK_TIME64_T)();
|
||||||
|
|
||||||
|
static uint64_t arkGetTickTime64() {
|
||||||
|
static ARK_GET_TICK_TIME64_T getTickTime64 =
|
||||||
|
(ARK_GET_TICK_TIME64_T)GetProcAddress(avs::game::DLL_INSTANCE, "arkGetTickTime64");
|
||||||
|
if (getTickTime64 == nullptr) {
|
||||||
|
// this works on 32-bit versions of avs, but not on 64.
|
||||||
|
// it's better than nothing though.
|
||||||
|
return timeGetTime();
|
||||||
|
}
|
||||||
|
return getTickTime64();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Implementations
|
* Implementations
|
||||||
*/
|
*/
|
||||||
@@ -33,13 +46,13 @@ static bool __cdecl ac_io_mdxf_get_control_status_buffer(int node, void *buffer,
|
|||||||
if (avs::game::is_model("MDX")) {
|
if (avs::game::is_model("MDX")) {
|
||||||
|
|
||||||
// get buffer index
|
// get buffer index
|
||||||
auto i = (COUNTER + a3) % std::size(BUFFERS.STATUS_BUFFER_17);
|
auto i = (COUNTER + a3) % std::size(BUFFERS.STATUS_BUFFER_P1);
|
||||||
|
|
||||||
// copy buffer
|
// copy buffer
|
||||||
if (node == 17) {
|
if (node == 17 || node == 25) {
|
||||||
memcpy(buffer, BUFFERS.STATUS_BUFFER_17[i], STATUS_BUFFER_SIZE);
|
memcpy(buffer, BUFFERS.STATUS_BUFFER_P1[i], STATUS_BUFFER_SIZE);
|
||||||
} else if (node == 18) {
|
} else if (node == 18 || node == 26) {
|
||||||
memcpy(buffer, BUFFERS.STATUS_BUFFER_18[i], STATUS_BUFFER_SIZE);
|
memcpy(buffer, BUFFERS.STATUS_BUFFER_P2[i], STATUS_BUFFER_SIZE);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// fill with zeros on unknown node
|
// fill with zeros on unknown node
|
||||||
@@ -52,8 +65,41 @@ static bool __cdecl ac_io_mdxf_get_control_status_buffer(int node, void *buffer,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool __cdecl ac_io_mdxf_set_output_level(unsigned int a1, unsigned int a2, uint8_t a3) {
|
static bool __cdecl ac_io_mdxf_set_output_level(unsigned int a1, unsigned int a2, uint8_t value) {
|
||||||
// TODO(felix): DDR BIO2 lights
|
if (avs::game::is_model("MDX")) {
|
||||||
|
static const struct {
|
||||||
|
int a2[4];
|
||||||
|
} mapping[] = {
|
||||||
|
{
|
||||||
|
// a1 == 17
|
||||||
|
{
|
||||||
|
games::ddr::Lights::GOLD_P1_STAGE_UP_RIGHT,
|
||||||
|
games::ddr::Lights::GOLD_P1_STAGE_DOWN_LEFT,
|
||||||
|
games::ddr::Lights::GOLD_P1_STAGE_UP_LEFT,
|
||||||
|
games::ddr::Lights::GOLD_P1_STAGE_DOWN_RIGHT
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// a1 == 18
|
||||||
|
{
|
||||||
|
games::ddr::Lights::GOLD_P2_STAGE_UP_RIGHT,
|
||||||
|
games::ddr::Lights::GOLD_P2_STAGE_DOWN_LEFT,
|
||||||
|
games::ddr::Lights::GOLD_P2_STAGE_UP_LEFT,
|
||||||
|
games::ddr::Lights::GOLD_P2_STAGE_DOWN_RIGHT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if ((a1 == 17 || a1 == 18) && (a2 < 4)) {
|
||||||
|
// get light from mapping
|
||||||
|
const auto light = mapping[a1 - 17].a2[a2];
|
||||||
|
|
||||||
|
// get lights
|
||||||
|
auto &lights = games::ddr::get_lights();
|
||||||
|
|
||||||
|
// write lights
|
||||||
|
GameAPI::Lights::writeLight(RI_MGR, lights[light], value / 128.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -61,7 +107,7 @@ static bool __cdecl ac_io_mdxf_set_output_level(unsigned int a1, unsigned int a2
|
|||||||
static bool __cdecl ac_io_mdxf_update_control_status_buffer(int node) {
|
static bool __cdecl ac_io_mdxf_update_control_status_buffer(int node) {
|
||||||
|
|
||||||
// increase counter
|
// increase counter
|
||||||
COUNTER = (COUNTER + 1) % std::size(BUFFERS.STATUS_BUFFER_17);
|
COUNTER = (COUNTER + 1) % std::size(BUFFERS.STATUS_BUFFER_P1);
|
||||||
|
|
||||||
// check freeze
|
// check freeze
|
||||||
if (STATUS_BUFFER_FREEZE) {
|
if (STATUS_BUFFER_FREEZE) {
|
||||||
@@ -72,10 +118,12 @@ static bool __cdecl ac_io_mdxf_update_control_status_buffer(int node) {
|
|||||||
uint8_t *buffer = nullptr;
|
uint8_t *buffer = nullptr;
|
||||||
switch (node) {
|
switch (node) {
|
||||||
case 17:
|
case 17:
|
||||||
buffer = BUFFERS.STATUS_BUFFER_17[COUNTER];
|
case 25:
|
||||||
|
buffer = BUFFERS.STATUS_BUFFER_P1[COUNTER];
|
||||||
break;
|
break;
|
||||||
case 18:
|
case 18:
|
||||||
buffer = BUFFERS.STATUS_BUFFER_18[COUNTER];
|
case 26:
|
||||||
|
buffer = BUFFERS.STATUS_BUFFER_P2[COUNTER];
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
||||||
@@ -92,13 +140,13 @@ static bool __cdecl ac_io_mdxf_update_control_status_buffer(int node) {
|
|||||||
// FOOT UP = bit 36-39 = byte 4, bit 4-7
|
// FOOT UP = bit 36-39 = byte 4, bit 4-7
|
||||||
// FOOT RIGHT = bit 40-43 = byte 5, bit 0-3
|
// FOOT RIGHT = bit 40-43 = byte 5, bit 0-3
|
||||||
// FOOT LEFT = bit 44-47 = byte 5, bit 4-7
|
// FOOT LEFT = bit 44-47 = byte 5, bit 4-7
|
||||||
static const size_t buttons_17[] = {
|
static const size_t buttons_p1[] = {
|
||||||
games::ddr::Buttons::P1_PANEL_UP,
|
games::ddr::Buttons::P1_PANEL_UP,
|
||||||
games::ddr::Buttons::P1_PANEL_DOWN,
|
games::ddr::Buttons::P1_PANEL_DOWN,
|
||||||
games::ddr::Buttons::P1_PANEL_LEFT,
|
games::ddr::Buttons::P1_PANEL_LEFT,
|
||||||
games::ddr::Buttons::P1_PANEL_RIGHT,
|
games::ddr::Buttons::P1_PANEL_RIGHT,
|
||||||
};
|
};
|
||||||
static const size_t buttons_18[] = {
|
static const size_t buttons_p2[] = {
|
||||||
games::ddr::Buttons::P2_PANEL_UP,
|
games::ddr::Buttons::P2_PANEL_UP,
|
||||||
games::ddr::Buttons::P2_PANEL_DOWN,
|
games::ddr::Buttons::P2_PANEL_DOWN,
|
||||||
games::ddr::Buttons::P2_PANEL_LEFT,
|
games::ddr::Buttons::P2_PANEL_LEFT,
|
||||||
@@ -109,13 +157,17 @@ static bool __cdecl ac_io_mdxf_update_control_status_buffer(int node) {
|
|||||||
const size_t *button_map = nullptr;
|
const size_t *button_map = nullptr;
|
||||||
switch (node) {
|
switch (node) {
|
||||||
case 17:
|
case 17:
|
||||||
button_map = &buttons_17[0];
|
case 25:
|
||||||
|
button_map = &buttons_p1[0];
|
||||||
break;
|
break;
|
||||||
case 18:
|
case 18:
|
||||||
button_map = &buttons_18[0];
|
case 26:
|
||||||
|
button_map = &buttons_p2[0];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*(uint64_t*)&buffer[0x18] = arkGetTickTime64();
|
||||||
|
|
||||||
// get buttons
|
// get buttons
|
||||||
auto &buttons = games::ddr::get_buttons();
|
auto &buttons = games::ddr::get_buttons();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
|
|||||||
+110
-9
@@ -6,6 +6,11 @@
|
|||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
#include "avs/game.h"
|
#include "avs/game.h"
|
||||||
|
|
||||||
|
// std::min
|
||||||
|
#ifdef min
|
||||||
|
#undef min
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace GameAPI;
|
using namespace GameAPI;
|
||||||
|
|
||||||
// static stuff
|
// static stuff
|
||||||
@@ -79,6 +84,32 @@ static bool __cdecl ac_io_panb_start_auto_input() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint8_t panb_get_button_velocity(Button button, Button button_soft, Button button_medium, Button button_hard) {
|
||||||
|
const auto velocity = Buttons::getVelocity(RI_MGR, button);
|
||||||
|
const auto velocity_soft = Buttons::getVelocity(RI_MGR, button_soft);
|
||||||
|
const auto velocity_medium = Buttons::getVelocity(RI_MGR, button_medium);
|
||||||
|
const auto velocity_hard = Buttons::getVelocity(RI_MGR, button_hard);
|
||||||
|
|
||||||
|
// note that the digital values have been obtained via trial-and-error in recital mode
|
||||||
|
// based on Op3:
|
||||||
|
// * soft presses glow blue, should trigger Elegant in blue sections
|
||||||
|
// * hard presses glow red/orange, should trigger Elegant in yellow sections
|
||||||
|
// * default (medium) presses glow green, triggers Elegant in both blue and yellow sections
|
||||||
|
|
||||||
|
// digital-only values
|
||||||
|
if (velocity_hard > 0.f) {
|
||||||
|
// do NOT use 15 here!! 14 properly registers as a hard press, but 15 does not
|
||||||
|
return 14;
|
||||||
|
} else if (velocity_medium > 0.f) {
|
||||||
|
return 11;
|
||||||
|
} else if (velocity_soft > 0.f) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// digital or midi (velocity-sensitive) values
|
||||||
|
return std::min((uint8_t)(velocity * 15.999f), (uint8_t)14);
|
||||||
|
}
|
||||||
|
|
||||||
static bool __cdecl ac_io_panb_update_control_status_buffer() {
|
static bool __cdecl ac_io_panb_update_control_status_buffer() {
|
||||||
|
|
||||||
// check freeze
|
// check freeze
|
||||||
@@ -107,6 +138,7 @@ static bool __cdecl ac_io_panb_update_control_status_buffer() {
|
|||||||
auto &analogs = games::nost::get_analogs();
|
auto &analogs = games::nost::get_analogs();
|
||||||
|
|
||||||
// mappings
|
// mappings
|
||||||
|
// "normal" buttons - these are velocity sensitive (digital or MIDI)
|
||||||
static const size_t button_mapping[] = {
|
static const size_t button_mapping[] = {
|
||||||
games::nost::Buttons::Key1, games::nost::Buttons::Key2,
|
games::nost::Buttons::Key1, games::nost::Buttons::Key2,
|
||||||
games::nost::Buttons::Key3, games::nost::Buttons::Key4,
|
games::nost::Buttons::Key3, games::nost::Buttons::Key4,
|
||||||
@@ -123,6 +155,60 @@ static bool __cdecl ac_io_panb_update_control_status_buffer() {
|
|||||||
games::nost::Buttons::Key25, games::nost::Buttons::Key26,
|
games::nost::Buttons::Key25, games::nost::Buttons::Key26,
|
||||||
games::nost::Buttons::Key27, games::nost::Buttons::Key28,
|
games::nost::Buttons::Key27, games::nost::Buttons::Key28,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// soft (digital) button - always registers as soft press
|
||||||
|
static const size_t soft_button_mapping[] = {
|
||||||
|
games::nost::Buttons::Key1Soft, games::nost::Buttons::Key2Soft,
|
||||||
|
games::nost::Buttons::Key3Soft, games::nost::Buttons::Key4Soft,
|
||||||
|
games::nost::Buttons::Key5Soft, games::nost::Buttons::Key6Soft,
|
||||||
|
games::nost::Buttons::Key7Soft, games::nost::Buttons::Key8Soft,
|
||||||
|
games::nost::Buttons::Key9Soft, games::nost::Buttons::Key10Soft,
|
||||||
|
games::nost::Buttons::Key11Soft, games::nost::Buttons::Key12Soft,
|
||||||
|
games::nost::Buttons::Key13Soft, games::nost::Buttons::Key14Soft,
|
||||||
|
games::nost::Buttons::Key15Soft, games::nost::Buttons::Key16Soft,
|
||||||
|
games::nost::Buttons::Key17Soft, games::nost::Buttons::Key18Soft,
|
||||||
|
games::nost::Buttons::Key19Soft, games::nost::Buttons::Key20Soft,
|
||||||
|
games::nost::Buttons::Key21Soft, games::nost::Buttons::Key22Soft,
|
||||||
|
games::nost::Buttons::Key23Soft, games::nost::Buttons::Key24Soft,
|
||||||
|
games::nost::Buttons::Key25Soft, games::nost::Buttons::Key26Soft,
|
||||||
|
games::nost::Buttons::Key27Soft, games::nost::Buttons::Key28Soft,
|
||||||
|
};
|
||||||
|
|
||||||
|
// medium (digital) button - always registers as medium press
|
||||||
|
static const size_t medium_button_mapping[] = {
|
||||||
|
games::nost::Buttons::Key1Medium, games::nost::Buttons::Key2Medium,
|
||||||
|
games::nost::Buttons::Key3Medium, games::nost::Buttons::Key4Medium,
|
||||||
|
games::nost::Buttons::Key5Medium, games::nost::Buttons::Key6Medium,
|
||||||
|
games::nost::Buttons::Key7Medium, games::nost::Buttons::Key8Medium,
|
||||||
|
games::nost::Buttons::Key9Medium, games::nost::Buttons::Key10Medium,
|
||||||
|
games::nost::Buttons::Key11Medium, games::nost::Buttons::Key12Medium,
|
||||||
|
games::nost::Buttons::Key13Medium, games::nost::Buttons::Key14Medium,
|
||||||
|
games::nost::Buttons::Key15Medium, games::nost::Buttons::Key16Medium,
|
||||||
|
games::nost::Buttons::Key17Medium, games::nost::Buttons::Key18Medium,
|
||||||
|
games::nost::Buttons::Key19Medium, games::nost::Buttons::Key20Medium,
|
||||||
|
games::nost::Buttons::Key21Medium, games::nost::Buttons::Key22Medium,
|
||||||
|
games::nost::Buttons::Key23Medium, games::nost::Buttons::Key24Medium,
|
||||||
|
games::nost::Buttons::Key25Medium, games::nost::Buttons::Key26Medium,
|
||||||
|
games::nost::Buttons::Key27Medium, games::nost::Buttons::Key28Medium,
|
||||||
|
};
|
||||||
|
|
||||||
|
// hard (digital) button - always registers as hard press
|
||||||
|
static const size_t hard_button_mapping[] = {
|
||||||
|
games::nost::Buttons::Key1Hard, games::nost::Buttons::Key2Hard,
|
||||||
|
games::nost::Buttons::Key3Hard, games::nost::Buttons::Key4Hard,
|
||||||
|
games::nost::Buttons::Key5Hard, games::nost::Buttons::Key6Hard,
|
||||||
|
games::nost::Buttons::Key7Hard, games::nost::Buttons::Key8Hard,
|
||||||
|
games::nost::Buttons::Key9Hard, games::nost::Buttons::Key10Hard,
|
||||||
|
games::nost::Buttons::Key11Hard, games::nost::Buttons::Key12Hard,
|
||||||
|
games::nost::Buttons::Key13Hard, games::nost::Buttons::Key14Hard,
|
||||||
|
games::nost::Buttons::Key15Hard, games::nost::Buttons::Key16Hard,
|
||||||
|
games::nost::Buttons::Key17Hard, games::nost::Buttons::Key18Hard,
|
||||||
|
games::nost::Buttons::Key19Hard, games::nost::Buttons::Key20Hard,
|
||||||
|
games::nost::Buttons::Key21Hard, games::nost::Buttons::Key22Hard,
|
||||||
|
games::nost::Buttons::Key23Hard, games::nost::Buttons::Key24Hard,
|
||||||
|
games::nost::Buttons::Key25Hard, games::nost::Buttons::Key26Hard,
|
||||||
|
games::nost::Buttons::Key27Hard, games::nost::Buttons::Key28Hard,
|
||||||
|
};
|
||||||
static const size_t analog_mapping[] = {
|
static const size_t analog_mapping[] = {
|
||||||
games::nost::Analogs::Key1, games::nost::Analogs::Key2,
|
games::nost::Analogs::Key1, games::nost::Analogs::Key2,
|
||||||
games::nost::Analogs::Key3, games::nost::Analogs::Key4,
|
games::nost::Analogs::Key3, games::nost::Analogs::Key4,
|
||||||
@@ -148,23 +234,38 @@ static bool __cdecl ac_io_panb_update_control_status_buffer() {
|
|||||||
uint8_t state1 = 0;
|
uint8_t state1 = 0;
|
||||||
|
|
||||||
// check analogs
|
// check analogs
|
||||||
|
//
|
||||||
|
// while 15 is technically allowed by the I/O board & is recognized correctly in test
|
||||||
|
// menu, when you play recital mode, 15 fails to register Elegant in yellow sections.
|
||||||
|
// therefore, cap the value at 14. tested with Nostroller.
|
||||||
auto &analog0 = analogs.at(analog_mapping[key_pair * 2 + 0]);
|
auto &analog0 = analogs.at(analog_mapping[key_pair * 2 + 0]);
|
||||||
auto &analog1 = analogs.at(analog_mapping[key_pair * 2 + 1]);
|
auto &analog1 = analogs.at(analog_mapping[key_pair * 2 + 1]);
|
||||||
if (analog0.isSet()) {
|
if (analog0.isSet()) {
|
||||||
state0 = (uint8_t) (Analogs::getState(RI_MGR, analog0) * 15.999f);
|
state0 = std::min((uint8_t)(Analogs::getState(RI_MGR, analog0) * 15.999f), (uint8_t)14);
|
||||||
}
|
}
|
||||||
if (analog1.isSet()) {
|
if (analog1.isSet()) {
|
||||||
state1 = (uint8_t) (Analogs::getState(RI_MGR, analog1) * 15.999f);
|
state1 = std::min((uint8_t)(Analogs::getState(RI_MGR, analog1) * 15.999f), (uint8_t)14);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check buttons
|
// check digital buttons
|
||||||
auto velocity0 = Buttons::getVelocity(RI_MGR, buttons.at(button_mapping[key_pair * 2 + 0]));
|
const auto button0 = panb_get_button_velocity(
|
||||||
auto velocity1 = Buttons::getVelocity(RI_MGR, buttons.at(button_mapping[key_pair * 2 + 1]));
|
buttons.at(button_mapping[key_pair * 2 + 0]),
|
||||||
if (velocity0 > 0.f) {
|
buttons.at(soft_button_mapping[key_pair * 2 + 0]),
|
||||||
state0 = (uint8_t) (velocity0 * 15.999f);
|
buttons.at(medium_button_mapping[key_pair * 2 + 0]),
|
||||||
|
buttons.at(hard_button_mapping[key_pair * 2 + 0])
|
||||||
|
);
|
||||||
|
if (button0 > 0) {
|
||||||
|
state0 = button0;
|
||||||
}
|
}
|
||||||
if (velocity1 > 0.f) {
|
|
||||||
state1 = (uint8_t) (velocity1 * 15.999f);
|
const auto button1 = panb_get_button_velocity(
|
||||||
|
buttons.at(button_mapping[key_pair * 2 + 1]),
|
||||||
|
buttons.at(soft_button_mapping[key_pair * 2 + 1]),
|
||||||
|
buttons.at(medium_button_mapping[key_pair * 2 + 1]),
|
||||||
|
buttons.at(hard_button_mapping[key_pair * 2 + 1])
|
||||||
|
);
|
||||||
|
if (button1 > 0) {
|
||||||
|
state1 = button1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// build value
|
// build value
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace acio2emu::firmware {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 785: { // write output
|
case 785: { // write output
|
||||||
auto count = write_output(std::span{cur.base(), static_cast<size_t>(in.payload.end() - cur)});
|
auto count = write_output(std::span{&*cur, static_cast<size_t>(in.payload.end() - cur)});
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,6 +108,10 @@ std::optional<uint8_t> ACIOEmu::read() {
|
|||||||
return this->response_buffer->get();
|
return this->response_buffer->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t ACIOEmu::bytes_available() {
|
||||||
|
return this->response_buffer->size();
|
||||||
|
}
|
||||||
|
|
||||||
void ACIOEmu::msg_parse() {
|
void ACIOEmu::msg_parse() {
|
||||||
|
|
||||||
#ifdef ACIOEMU_LOG
|
#ifdef ACIOEMU_LOG
|
||||||
|
|||||||
@@ -28,5 +28,6 @@ namespace acioemu {
|
|||||||
|
|
||||||
void write(uint8_t byte);
|
void write(uint8_t byte);
|
||||||
std::optional<uint8_t> read();
|
std::optional<uint8_t> read();
|
||||||
|
size_t bytes_available();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-2
@@ -4,8 +4,9 @@
|
|||||||
#include "rawinput/rawinput.h"
|
#include "rawinput/rawinput.h"
|
||||||
#include "util/utils.h"
|
#include "util/utils.h"
|
||||||
|
|
||||||
acioemu::ACIOHandle::ACIOHandle(LPCWSTR lpCOMPort) {
|
acioemu::ACIOHandle::ACIOHandle(LPCWSTR lpCOMPort, uint8_t iccaNodeCount) {
|
||||||
this->com_port = lpCOMPort;
|
this->com_port = lpCOMPort;
|
||||||
|
this->icca_node_count = iccaNodeCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool acioemu::ACIOHandle::open(LPCWSTR lpFileName) {
|
bool acioemu::ACIOHandle::open(LPCWSTR lpFileName) {
|
||||||
@@ -16,7 +17,7 @@ bool acioemu::ACIOHandle::open(LPCWSTR lpFileName) {
|
|||||||
log_info("acioemu", "Opened {} (ACIO)", ws2s(com_port));
|
log_info("acioemu", "Opened {} (ACIO)", ws2s(com_port));
|
||||||
|
|
||||||
// ACIO device
|
// ACIO device
|
||||||
acio_emu.add_device(new acioemu::ICCADevice(false, true, 2));
|
acio_emu.add_device(new acioemu::ICCADevice(false, true, icca_node_count));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -62,6 +63,10 @@ int acioemu::ACIOHandle::device_io(
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t acioemu::ACIOHandle::bytes_available() {
|
||||||
|
return acio_emu.bytes_available();
|
||||||
|
}
|
||||||
|
|
||||||
bool acioemu::ACIOHandle::close() {
|
bool acioemu::ACIOHandle::close() {
|
||||||
log_info("acioemu", "Closed {} (ACIO)", ws2s(com_port));
|
log_info("acioemu", "Closed {} (ACIO)", ws2s(com_port));
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -9,10 +9,12 @@ namespace acioemu {
|
|||||||
private:
|
private:
|
||||||
LPCWSTR com_port;
|
LPCWSTR com_port;
|
||||||
|
|
||||||
|
uint8_t icca_node_count;
|
||||||
|
|
||||||
acioemu::ACIOEmu acio_emu;
|
acioemu::ACIOEmu acio_emu;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ACIOHandle(LPCWSTR lpCOMPort);
|
ACIOHandle(LPCWSTR lpCOMPort, uint8_t iccaNodeCount = 2);
|
||||||
|
|
||||||
bool open(LPCWSTR lpFileName) override;
|
bool open(LPCWSTR lpFileName) override;
|
||||||
|
|
||||||
@@ -23,6 +25,8 @@ namespace acioemu {
|
|||||||
int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||||
DWORD nOutBufferSize) override;
|
DWORD nOutBufferSize) override;
|
||||||
|
|
||||||
|
size_t bytes_available() override;
|
||||||
|
|
||||||
bool close() override;
|
bool close() override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+57
-13
@@ -8,6 +8,10 @@
|
|||||||
|
|
||||||
using namespace acioemu;
|
using namespace acioemu;
|
||||||
|
|
||||||
|
namespace acioemu {
|
||||||
|
bool ICCA_DEVICE_HACK = false;
|
||||||
|
}
|
||||||
|
|
||||||
ICCADevice::ICCADevice(bool flip_order, bool keypad_thread, uint8_t node_count) {
|
ICCADevice::ICCADevice(bool flip_order, bool keypad_thread, uint8_t node_count) {
|
||||||
|
|
||||||
// init defaults
|
// init defaults
|
||||||
@@ -98,11 +102,13 @@ bool ICCADevice::parse_msg(MessageData *msg_in,
|
|||||||
// send version data
|
// send version data
|
||||||
auto msg = this->create_msg(msg_in, MSG_VERSION_SIZE);
|
auto msg = this->create_msg(msg_in, MSG_VERSION_SIZE);
|
||||||
if (
|
if (
|
||||||
avs::game::is_model({"LDJ", "TBS"}) ||
|
avs::game::is_model({"LDJ", "TBS", "UJK"}) ||
|
||||||
// SDVX Valkyrie cabinet mode
|
// SDVX Valkyrie cabinet mode
|
||||||
(avs::game::is_model("KFC") && (avs::game::SPEC[0] == 'G' || avs::game::SPEC[0] == 'H'))
|
(avs::game::is_model("KFC") && (avs::game::SPEC[0] == 'G' || avs::game::SPEC[0] == 'H'))
|
||||||
) {
|
) {
|
||||||
this->set_version(msg, 0x3, 0, 1, 7, 0, "ICCA");
|
this->set_version(msg, 0x3, 0, 1, 7, 0, "ICCA");
|
||||||
|
} else if (avs::game::is_model({"VFG"})) {
|
||||||
|
this->set_version(msg, 0x3, 0, 1, 7, 0, "ICCB");
|
||||||
} else {
|
} else {
|
||||||
this->set_version(msg, 0x3, 0, 1, 6, 0, "ICCA");
|
this->set_version(msg, 0x3, 0, 1, 6, 0, "ICCA");
|
||||||
}
|
}
|
||||||
@@ -327,6 +333,9 @@ bool ICCADevice::parse_msg(MessageData *msg_in,
|
|||||||
}
|
}
|
||||||
case ACIO_CMD_STARTUP:
|
case ACIO_CMD_STARTUP:
|
||||||
case ACIO_CMD_CLEAR:
|
case ACIO_CMD_CLEAR:
|
||||||
|
case 0x30: // GetBoardProductNumber
|
||||||
|
case 0x31: // GetMicomInfo
|
||||||
|
case 0x3A: // ???
|
||||||
case 0x0116: // ???
|
case 0x0116: // ???
|
||||||
case 0x0120: // ???
|
case 0x0120: // ???
|
||||||
case 0xFF: // BROADCAST
|
case 0xFF: // BROADCAST
|
||||||
@@ -385,19 +394,48 @@ void ICCADevice::update_card(int unit) {
|
|||||||
static int KEYPAD_EAMUSE_MAPPING[] = {
|
static int KEYPAD_EAMUSE_MAPPING[] = {
|
||||||
0, 1, 5, 9, 2, 6, 10, 3, 7, 11, 8, 4
|
0, 1, 5, 9, 2, 6, 10, 3, 7, 11, 8, 4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// map for KEYPAD_KEY_CODES:
|
||||||
|
// 7 8 9 | 800 8000 8
|
||||||
|
// 4 5 6 | 400 4000 4
|
||||||
|
// 1 2 3 | 200 2000 2
|
||||||
|
// 0 00 . | 100 1000 1
|
||||||
static int KEYPAD_KEY_CODES[]{
|
static int KEYPAD_KEY_CODES[]{
|
||||||
0x100,
|
0x100, // 0
|
||||||
0x200,
|
0x200, // 1
|
||||||
0x2000,
|
0x2000, // 2
|
||||||
2,
|
2, // 3
|
||||||
0x400,
|
0x400, // 4
|
||||||
0x4000,
|
0x4000, // 5
|
||||||
4,
|
4, // 6
|
||||||
0x800,
|
0x800, // 7
|
||||||
0x8000,
|
0x8000, // 8
|
||||||
8,
|
8, // 9
|
||||||
1,
|
1, // .
|
||||||
0x1000
|
0x1000 // 00
|
||||||
|
};
|
||||||
|
|
||||||
|
// map for KEYPAD_KEY_CODES_ALT:
|
||||||
|
// 7 8 9 | 8 80 800
|
||||||
|
// 4 5 6 | 4 40 400
|
||||||
|
// 1 2 3 | 2 20 200
|
||||||
|
// 0 00 . | 1 10 100
|
||||||
|
//
|
||||||
|
// note that the only game that needs this (SDVX VM) does not accept decimal,
|
||||||
|
// so that key is untested
|
||||||
|
static int KEYPAD_KEY_CODES_ALT[]{
|
||||||
|
1, // 0
|
||||||
|
2, // 1
|
||||||
|
0x20, // 2
|
||||||
|
0x200, // 3
|
||||||
|
4, // 4
|
||||||
|
0x40, // 5
|
||||||
|
0x400, // 6
|
||||||
|
8, // 7
|
||||||
|
0x80, // 8
|
||||||
|
0x800, // 9
|
||||||
|
0x100, // .
|
||||||
|
0x10 // 00
|
||||||
};
|
};
|
||||||
static uint8_t KEYPAD_KEY_CODE_NUMS[]{
|
static uint8_t KEYPAD_KEY_CODE_NUMS[]{
|
||||||
0, 1, 5, 9, 2, 6, 10, 3, 7, 11, 8, 4
|
0, 1, 5, 9, 2, 6, 10, 3, 7, 11, 8, 4
|
||||||
@@ -421,7 +459,13 @@ void ICCADevice::update_keypad(int unit, bool update_edge) {
|
|||||||
|
|
||||||
// check if pressed
|
// check if pressed
|
||||||
if (eamu_state & (1 << KEYPAD_EAMUSE_MAPPING[i])) {
|
if (eamu_state & (1 << KEYPAD_EAMUSE_MAPPING[i])) {
|
||||||
|
|
||||||
|
if (ICCA_DEVICE_HACK) {
|
||||||
|
this->keypad[unit] |= KEYPAD_KEY_CODES_ALT[i];
|
||||||
|
} else {
|
||||||
this->keypad[unit] |= KEYPAD_KEY_CODES[i];
|
this->keypad[unit] |= KEYPAD_KEY_CODES[i];
|
||||||
|
}
|
||||||
|
|
||||||
if (!this->keypad_last[unit][i] && update_edge) {
|
if (!this->keypad_last[unit][i] && update_edge) {
|
||||||
this->keydown[unit] = (this->keypad_capture[unit] << 4) | KEYPAD_KEY_CODE_NUMS[n];
|
this->keydown[unit] = (this->keypad_capture[unit] << 4) | KEYPAD_KEY_CODE_NUMS[n];
|
||||||
this->keypad_last[unit][i] = true;
|
this->keypad_last[unit][i] = true;
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
#include "reader/crypt.h"
|
#include "reader/crypt.h"
|
||||||
|
|
||||||
namespace acioemu {
|
namespace acioemu {
|
||||||
|
extern bool ICCA_DEVICE_HACK;
|
||||||
|
|
||||||
class ICCADevice : public ACIODeviceEmu {
|
class ICCADevice : public ACIODeviceEmu {
|
||||||
private:
|
private:
|
||||||
bool type_new;
|
bool type_new;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "modules/capture.h"
|
#include "modules/capture.h"
|
||||||
#include "modules/coin.h"
|
#include "modules/coin.h"
|
||||||
#include "modules/control.h"
|
#include "modules/control.h"
|
||||||
|
#include "modules/ddr.h"
|
||||||
#include "modules/drs.h"
|
#include "modules/drs.h"
|
||||||
#include "modules/iidx.h"
|
#include "modules/iidx.h"
|
||||||
#include "modules/info.h"
|
#include "modules/info.h"
|
||||||
@@ -26,6 +27,7 @@
|
|||||||
#include "modules/lights.h"
|
#include "modules/lights.h"
|
||||||
#include "modules/memory.h"
|
#include "modules/memory.h"
|
||||||
#include "modules/touch.h"
|
#include "modules/touch.h"
|
||||||
|
#include "modules/resize.h"
|
||||||
#include "request.h"
|
#include "request.h"
|
||||||
#include "response.h"
|
#include "response.h"
|
||||||
|
|
||||||
@@ -393,6 +395,7 @@ void Controller::init_state(api::ClientState *state) {
|
|||||||
state->modules.push_back(new modules::Capture());
|
state->modules.push_back(new modules::Capture());
|
||||||
state->modules.push_back(new modules::Coin());
|
state->modules.push_back(new modules::Coin());
|
||||||
state->modules.push_back(new modules::Control());
|
state->modules.push_back(new modules::Control());
|
||||||
|
state->modules.push_back(new modules::DDR());
|
||||||
state->modules.push_back(new modules::DRS());
|
state->modules.push_back(new modules::DRS());
|
||||||
state->modules.push_back(new modules::IIDX());
|
state->modules.push_back(new modules::IIDX());
|
||||||
state->modules.push_back(new modules::Info());
|
state->modules.push_back(new modules::Info());
|
||||||
@@ -401,6 +404,7 @@ void Controller::init_state(api::ClientState *state) {
|
|||||||
state->modules.push_back(new modules::Lights());
|
state->modules.push_back(new modules::Lights());
|
||||||
state->modules.push_back(new modules::Memory());
|
state->modules.push_back(new modules::Memory());
|
||||||
state->modules.push_back(new modules::Touch());
|
state->modules.push_back(new modules::Touch());
|
||||||
|
state->modules.push_back(new modules::Resize());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::free_state(api::ClientState *state) {
|
void Controller::free_state(api::ClientState *state) {
|
||||||
|
|||||||
+1
-29
@@ -27,34 +27,6 @@ namespace api::modules {
|
|||||||
{ SIGTERM, "SIGTERM" },
|
{ SIGTERM, "SIGTERM" },
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline bool acquire_shutdown_privs() {
|
|
||||||
|
|
||||||
// check if already acquired
|
|
||||||
static bool acquired = false;
|
|
||||||
if (acquired)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// get process token
|
|
||||||
HANDLE hToken;
|
|
||||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// get the LUID for the shutdown privilege
|
|
||||||
TOKEN_PRIVILEGES tkp;
|
|
||||||
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
|
|
||||||
tkp.PrivilegeCount = 1;
|
|
||||||
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
||||||
|
|
||||||
// get the shutdown privilege for this process
|
|
||||||
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0);
|
|
||||||
|
|
||||||
// check for error
|
|
||||||
bool success = GetLastError() == ERROR_SUCCESS;
|
|
||||||
if (success)
|
|
||||||
acquired = true;
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
Control::Control() : Module("control", true) {
|
Control::Control() : Module("control", true) {
|
||||||
functions["raise"] = std::bind(&Control::raise, this, _1, _2);
|
functions["raise"] = std::bind(&Control::raise, this, _1, _2);
|
||||||
functions["exit"] = std::bind(&Control::exit, this, _1, _2);
|
functions["exit"] = std::bind(&Control::exit, this, _1, _2);
|
||||||
@@ -150,7 +122,7 @@ namespace api::modules {
|
|||||||
return error(res, "Unable to acquire shutdown privileges");
|
return error(res, "Unable to acquire shutdown privileges");
|
||||||
|
|
||||||
// exit windows
|
// exit windows
|
||||||
if (!ExitWindowsEx(EWX_POWEROFF | EWX_FORCE,
|
if (!ExitWindowsEx(EWX_SHUTDOWN | EWX_HYBRID_SHUTDOWN | EWX_FORCE,
|
||||||
SHTDN_REASON_MAJOR_APPLICATION |
|
SHTDN_REASON_MAJOR_APPLICATION |
|
||||||
SHTDN_REASON_MINOR_MAINTENANCE))
|
SHTDN_REASON_MINOR_MAINTENANCE))
|
||||||
return error(res, "Unable to shutdown system");
|
return error(res, "Unable to shutdown system");
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
#include "ddr.h"
|
||||||
|
#include <functional>
|
||||||
|
#include "external/rapidjson/document.h"
|
||||||
|
#include "games/ddr/ddr.h"
|
||||||
|
|
||||||
|
using namespace std::placeholders;
|
||||||
|
using namespace rapidjson;
|
||||||
|
|
||||||
|
namespace api::modules {
|
||||||
|
|
||||||
|
DDR::DDR() : Module("ddr") {
|
||||||
|
functions["tapeled_get"] = std::bind(&DDR::tapeled_get, this, _1, _2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows fetching of the RGB LED strips that are gold cabinets, via SpiceAPI
|
||||||
|
*/
|
||||||
|
void DDR::tapeled_get(Request &req, Response &res) {
|
||||||
|
static const char* device_names[11] = {
|
||||||
|
"p1_foot_up",
|
||||||
|
"p1_foot_right",
|
||||||
|
"p1_foot_left",
|
||||||
|
"p1_foot_down",
|
||||||
|
"p2_foot_up",
|
||||||
|
"p2_foot_right",
|
||||||
|
"p2_foot_left",
|
||||||
|
"p2_foot_down",
|
||||||
|
"top_panel",
|
||||||
|
"monitor_left",
|
||||||
|
"monitor_right"
|
||||||
|
};
|
||||||
|
|
||||||
|
Value response_object(kObjectType);
|
||||||
|
|
||||||
|
// Iterate through each device and dump its lights data into the response
|
||||||
|
for (size_t device = 0; device < 11; device++) {
|
||||||
|
size_t num_leds = 25;
|
||||||
|
if (device > 7)
|
||||||
|
num_leds = 50;
|
||||||
|
|
||||||
|
Value light_state(kArrayType);
|
||||||
|
light_state.Reserve(num_leds * 3, res.doc()->GetAllocator());
|
||||||
|
for (size_t led = 0; led < num_leds; led++) {
|
||||||
|
light_state.PushBack(games::ddr::DDR_TAPELEDS[device][led][0], res.doc()->GetAllocator());
|
||||||
|
light_state.PushBack(games::ddr::DDR_TAPELEDS[device][led][1], res.doc()->GetAllocator());
|
||||||
|
light_state.PushBack(games::ddr::DDR_TAPELEDS[device][led][2], res.doc()->GetAllocator());
|
||||||
|
}
|
||||||
|
|
||||||
|
response_object.AddMember(StringRef(device_names[device]), light_state, res.doc()->GetAllocator());
|
||||||
|
}
|
||||||
|
|
||||||
|
res.add_data(response_object);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "api/module.h"
|
||||||
|
#include "api/request.h"
|
||||||
|
|
||||||
|
namespace api::modules {
|
||||||
|
|
||||||
|
class DDR : public Module {
|
||||||
|
public:
|
||||||
|
DDR();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// function definitions
|
||||||
|
void tapeled_get(Request &req, Response &res);
|
||||||
|
};
|
||||||
|
}
|
||||||
+58
-18
@@ -1,5 +1,7 @@
|
|||||||
#include "lights.h"
|
#include "lights.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <cfg/configurator.h>
|
||||||
|
|
||||||
#include "external/rapidjson/document.h"
|
#include "external/rapidjson/document.h"
|
||||||
#include "misc/eamuse.h"
|
#include "misc/eamuse.h"
|
||||||
#include "cfg/light.h"
|
#include "cfg/light.h"
|
||||||
@@ -17,11 +19,16 @@ namespace api::modules {
|
|||||||
functions["read"] = std::bind(&Lights::read, this, _1, _2);
|
functions["read"] = std::bind(&Lights::read, this, _1, _2);
|
||||||
functions["write"] = std::bind(&Lights::write, this, _1, _2);
|
functions["write"] = std::bind(&Lights::write, this, _1, _2);
|
||||||
functions["write_reset"] = std::bind(&Lights::write_reset, this, _1, _2);
|
functions["write_reset"] = std::bind(&Lights::write_reset, this, _1, _2);
|
||||||
lights = games::get_lights(eamuse_get_game());
|
|
||||||
|
this->lights = games::get_lights(eamuse_get_game());
|
||||||
|
for (auto &light : *this->lights) {
|
||||||
|
this->lights_by_names.emplace(light.getName(), light);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* read()
|
* read()
|
||||||
|
* read(name: str, ...)
|
||||||
*/
|
*/
|
||||||
void Lights::read(api::Request &req, Response &res) {
|
void Lights::read(api::Request &req, Response &res) {
|
||||||
|
|
||||||
@@ -30,8 +37,31 @@ namespace api::modules {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// all lights for this game
|
||||||
|
if (req.params.Size() == 0) {
|
||||||
// add state for each light
|
// add state for each light
|
||||||
for (auto &light : *this->lights) {
|
for (auto &light : *this->lights) {
|
||||||
|
get_light(light, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// specified light names
|
||||||
|
for (Value ¶m : req.params.GetArray()) {
|
||||||
|
// check params
|
||||||
|
if (!param.IsString()) {
|
||||||
|
error_type(res, "name", "string");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto name = param.GetString();
|
||||||
|
if (this->lights_by_names.contains(name)) {
|
||||||
|
get_light(this->lights_by_names.at(name).get(), res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Lights::get_light(Light &light, Response &res) {
|
||||||
Value state(kArrayType);
|
Value state(kArrayType);
|
||||||
Value light_name(light.getName().c_str(), res.doc()->GetAllocator());
|
Value light_name(light.getName().c_str(), res.doc()->GetAllocator());
|
||||||
Value light_state(GameAPI::Lights::readLight(RI_MGR, light));
|
Value light_state(GameAPI::Lights::readLight(RI_MGR, light));
|
||||||
@@ -41,7 +71,6 @@ namespace api::modules {
|
|||||||
state.PushBack(light_enabled, res.doc()->GetAllocator());
|
state.PushBack(light_enabled, res.doc()->GetAllocator());
|
||||||
res.add_data(state);
|
res.add_data(state);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* write([name: str, state: float], ...)
|
* write([name: str, state: float], ...)
|
||||||
@@ -88,6 +117,7 @@ namespace api::modules {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* write_reset()
|
* write_reset()
|
||||||
|
* write_reset(name: str, ...)
|
||||||
* write_reset([name: str], ...)
|
* write_reset([name: str], ...)
|
||||||
*/
|
*/
|
||||||
void Lights::write_reset(Request &req, Response &res) {
|
void Lights::write_reset(Request &req, Response &res) {
|
||||||
@@ -104,20 +134,23 @@ namespace api::modules {
|
|||||||
if (params.Size() == 0) {
|
if (params.Size() == 0) {
|
||||||
if (lights != nullptr) {
|
if (lights != nullptr) {
|
||||||
for (auto &light : *this->lights) {
|
for (auto &light : *this->lights) {
|
||||||
|
if (light.override_enabled) {
|
||||||
|
if (cfg::CONFIGURATOR_STANDALONE) {
|
||||||
|
GameAPI::Lights::writeLight(RI_MGR, light, light.last_state);
|
||||||
|
}
|
||||||
light.override_enabled = false;
|
light.override_enabled = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop parameters
|
// loop parameters
|
||||||
for (Value ¶m : req.params.GetArray()) {
|
for (Value ¶m : req.params.GetArray()) {
|
||||||
|
const char* light_name = nullptr;
|
||||||
|
|
||||||
// check params
|
// check params
|
||||||
if (!param.IsArray()) {
|
if (param.IsArray()) {
|
||||||
error(res, "parameters must be arrays");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (param.Size() < 1) {
|
if (param.Size() < 1) {
|
||||||
error_params_insufficient(res);
|
error_params_insufficient(res);
|
||||||
continue;
|
continue;
|
||||||
@@ -126,12 +159,16 @@ namespace api::modules {
|
|||||||
error_type(res, "name", "string");
|
error_type(res, "name", "string");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get params
|
// get params
|
||||||
auto light_name = param[0].GetString();
|
light_name = param[0].GetString();
|
||||||
|
} else if (param.IsString()) {
|
||||||
|
light_name = param.GetString();
|
||||||
|
} else {
|
||||||
|
error(res, "parameters must be arrays or strings");
|
||||||
|
}
|
||||||
|
|
||||||
// write analog state
|
// write analog state
|
||||||
if (!this->write_light_reset(light_name)) {
|
if (light_name && !this->write_light_reset(light_name)) {
|
||||||
error_unknown(res, "analog", light_name);
|
error_unknown(res, "analog", light_name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -146,17 +183,21 @@ namespace api::modules {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// find light
|
// find light
|
||||||
for (auto &light : *this->lights) {
|
if (this->lights_by_names.contains(name)) {
|
||||||
if (light.getName() == name) {
|
auto &light = this->lights_by_names.at(name).get();
|
||||||
light.override_state = CLAMP(state, 0.f, 1.f);
|
light.override_state = CLAMP(state, 0.f, 1.f);
|
||||||
light.override_enabled = true;
|
light.override_enabled = true;
|
||||||
return true;
|
|
||||||
}
|
if (cfg::CONFIGURATOR_STANDALONE) {
|
||||||
|
GameAPI::Lights::writeLight(RI_MGR, light, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
// unknown light
|
// unknown light
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Lights::write_light_reset(std::string name) {
|
bool Lights::write_light_reset(std::string name) {
|
||||||
|
|
||||||
@@ -166,14 +207,13 @@ namespace api::modules {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// find light
|
// find light
|
||||||
for (auto &light : *this->lights) {
|
if (this->lights_by_names.contains(name)) {
|
||||||
if (light.getName() == name) {
|
auto &light = this->lights_by_names.at(name).get();
|
||||||
light.override_enabled = false;
|
light.override_enabled = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
// unknown light
|
// unknown light
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <external/robin_hood.h>
|
||||||
|
|
||||||
#include "api/module.h"
|
#include "api/module.h"
|
||||||
#include "api/request.h"
|
#include "api/request.h"
|
||||||
#include "cfg/api.h"
|
#include "cfg/api.h"
|
||||||
@@ -15,6 +17,7 @@ namespace api::modules {
|
|||||||
|
|
||||||
// state
|
// state
|
||||||
std::vector<Light> *lights;
|
std::vector<Light> *lights;
|
||||||
|
robin_hood::unordered_map<std::string, std::reference_wrapper<Light>> lights_by_names;
|
||||||
|
|
||||||
// function definitions
|
// function definitions
|
||||||
void read(Request &req, Response &res);
|
void read(Request &req, Response &res);
|
||||||
@@ -22,6 +25,7 @@ namespace api::modules {
|
|||||||
void write_reset(Request &req, Response &res);
|
void write_reset(Request &req, Response &res);
|
||||||
|
|
||||||
// helper
|
// helper
|
||||||
|
void get_light(Light &light, Response &res);
|
||||||
bool write_light(std::string name, float state);
|
bool write_light(std::string name, float state);
|
||||||
bool write_light_reset(std::string name);
|
bool write_light_reset(std::string name);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
#include "resize.h"
|
||||||
|
#include "external/rapidjson/document.h"
|
||||||
|
#include "cfg/screen_resize.h"
|
||||||
|
|
||||||
|
using namespace std::placeholders;
|
||||||
|
using namespace rapidjson;
|
||||||
|
|
||||||
|
namespace api::modules {
|
||||||
|
|
||||||
|
static thread_local std::vector<uint8_t> CAPTURE_BUFFER;
|
||||||
|
|
||||||
|
Resize::Resize() : Module("resize") {
|
||||||
|
functions["image_resize_enable"] = std::bind(&Resize::image_resize_enable, this, _1, _2);
|
||||||
|
functions["image_resize_set_scene"] = std::bind(&Resize::image_resize_set_scene, this, _1, _2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* image_resize_enable(enable: bool)
|
||||||
|
*/
|
||||||
|
void Resize::image_resize_enable(Request &req, Response &res) {
|
||||||
|
if (req.params.Size() < 1) {
|
||||||
|
return error_params_insufficient(res);
|
||||||
|
}
|
||||||
|
if (!req.params[0].IsBool()) {
|
||||||
|
return error_type(res, "enable", "bool");
|
||||||
|
}
|
||||||
|
|
||||||
|
cfg::SCREENRESIZE->enable_screen_resize = req.params[0].GetBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* image_resize_set_scene(scene: int)
|
||||||
|
*/
|
||||||
|
void Resize::image_resize_set_scene(Request &req, Response &res) {
|
||||||
|
if (req.params.Size() < 1) {
|
||||||
|
return error_params_insufficient(res);
|
||||||
|
}
|
||||||
|
if (!req.params[0].IsInt()) {
|
||||||
|
return error_type(res, "scene", "int");
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto scene = req.params[0].GetInt();
|
||||||
|
if (scene < 0 || (int)std::size(cfg::SCREENRESIZE->scene_settings) < scene) {
|
||||||
|
return error(res, "invalid scene number");
|
||||||
|
}
|
||||||
|
if (scene == 0) {
|
||||||
|
cfg::SCREENRESIZE->enable_screen_resize = false;
|
||||||
|
} else {
|
||||||
|
cfg::SCREENRESIZE->enable_screen_resize = true;
|
||||||
|
cfg::SCREENRESIZE->screen_resize_current_scene = scene - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "api/module.h"
|
||||||
|
#include "api/request.h"
|
||||||
|
|
||||||
|
namespace api::modules {
|
||||||
|
|
||||||
|
class Resize : public Module {
|
||||||
|
public:
|
||||||
|
Resize();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// function definitions
|
||||||
|
void image_resize_enable(Request &req, Response &res);
|
||||||
|
void image_resize_set_scene(Request &req, Response &res);
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "external/rapidjson/document.h"
|
#include "external/rapidjson/document.h"
|
||||||
#include "avs/game.h"
|
#include "avs/game.h"
|
||||||
|
#include "hooks/graphics/graphics.h"
|
||||||
#include "misc/eamuse.h"
|
#include "misc/eamuse.h"
|
||||||
#include "launcher/launcher.h"
|
#include "launcher/launcher.h"
|
||||||
#include "touch/touch.h"
|
#include "touch/touch.h"
|
||||||
@@ -18,7 +19,12 @@ namespace api::modules {
|
|||||||
|
|
||||||
Touch::Touch() : Module("touch") {
|
Touch::Touch() : Module("touch") {
|
||||||
is_sdvx = avs::game::is_model("KFC");
|
is_sdvx = avs::game::is_model("KFC");
|
||||||
|
|
||||||
is_tdj_fhd = (avs::game::is_model("LDJ") && games::iidx::is_tdj_fhd());
|
is_tdj_fhd = (avs::game::is_model("LDJ") && games::iidx::is_tdj_fhd());
|
||||||
|
// special case: when windowed subscreen is in use, use the original coords
|
||||||
|
if (GRAPHICS_IIDX_WSUB) {
|
||||||
|
is_tdj_fhd = false;
|
||||||
|
}
|
||||||
|
|
||||||
functions["read"] = std::bind(&Touch::read, this, _1, _2);
|
functions["read"] = std::bind(&Touch::read, this, _1, _2);
|
||||||
functions["write"] = std::bind(&Touch::write, this, _1, _2);
|
functions["write"] = std::bind(&Touch::write, this, _1, _2);
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
# Lua Scripting
|
|
||||||
Supported version: Lua 5.4.3
|
|
||||||
No proper documentation yet. Check the example scripts if you need this!
|
|
||||||
For undocumented functions you can find the definitions in the source code (script/api/*.cpp).
|
|
||||||
They are very similar to what the network API provides.
|
|
||||||
|
|
||||||
# Automatic Execution
|
|
||||||
Create a "scripts" folder next to spice and put your scripts in there (subfolders allowed).
|
|
||||||
The prefix specifies when the script will be called:
|
|
||||||
|
|
||||||
- `boot_*`: executed on game boot
|
|
||||||
- `shutdown_*`: executed on game end
|
|
||||||
- `config_*`: executed when you start spicecfg (mostly for debugging/tests)
|
|
||||||
|
|
||||||
Example: "scripts/boot_patch.py" would be called on game boot.
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
-- example script for light effects on IIDX TT stab movement
|
|
||||||
-- create a folder called "script" next to spice and put me in there
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- settings
|
|
||||||
tt_duration = 0.25
|
|
||||||
zero_duration = 0.3141592
|
|
||||||
loop_delta = 1 / 240
|
|
||||||
curve_pow = 1 / 4
|
|
||||||
col_r = 1.0
|
|
||||||
col_g = 0.0
|
|
||||||
col_b = 0.0
|
|
||||||
light_p1_r = "Side Panel Left Avg R"
|
|
||||||
light_p1_g = "Side Panel Left Avg G"
|
|
||||||
light_p1_b = "Side Panel Left Avg B"
|
|
||||||
light_p2_r = "Side Panel Right Avg R"
|
|
||||||
light_p2_g = "Side Panel Right Avg G"
|
|
||||||
light_p2_b = "Side Panel Right Avg B"
|
|
||||||
|
|
||||||
-- wait for game
|
|
||||||
while not analogs.read()["Turntable P1"] do yield() end
|
|
||||||
|
|
||||||
-- initial state
|
|
||||||
tt1_last = tonumber(analogs.read()["Turntable P1"].state)
|
|
||||||
tt2_last = tonumber(analogs.read()["Turntable P2"].state)
|
|
||||||
tt1_diff_last = 0
|
|
||||||
tt2_diff_last = 0
|
|
||||||
tt1_trigger = 0
|
|
||||||
tt2_trigger = 0
|
|
||||||
tt1_zero_elapsed = 0
|
|
||||||
tt2_zero_elapsed = 0
|
|
||||||
|
|
||||||
-- main loop
|
|
||||||
while true do
|
|
||||||
|
|
||||||
-- read state
|
|
||||||
tt1 = tonumber(analogs.read()["Turntable P1"].state)
|
|
||||||
tt2 = tonumber(analogs.read()["Turntable P2"].state)
|
|
||||||
time_cur = time()
|
|
||||||
|
|
||||||
-- calculate difference
|
|
||||||
tt1_diff = tt1 - tt1_last
|
|
||||||
tt2_diff = tt2 - tt2_last
|
|
||||||
|
|
||||||
-- fix wrap around
|
|
||||||
if math.abs(tt1_diff) > 0.5 then tt1_diff = 0 end
|
|
||||||
if math.abs(tt2_diff) > 0.5 then tt2_diff = 0 end
|
|
||||||
|
|
||||||
-- trigger on movement start and direction changes
|
|
||||||
if (tt1_diff_last == 0 and tt1_diff ~= 0)
|
|
||||||
or (tt1_diff_last > 0 and tt1_diff < 0)
|
|
||||||
or (tt1_diff_last < 0 and tt1_diff > 0) then
|
|
||||||
tt1_trigger = time_cur
|
|
||||||
end
|
|
||||||
if (tt2_diff_last == 0 and tt2_diff ~= 0)
|
|
||||||
or (tt2_diff_last > 0 and tt2_diff < 0)
|
|
||||||
or (tt2_diff_last < 0 and tt2_diff > 0) then
|
|
||||||
tt2_trigger = time_cur
|
|
||||||
end
|
|
||||||
|
|
||||||
-- light effects when last trigger is still active
|
|
||||||
if time_cur - tt1_trigger < tt_duration then
|
|
||||||
brightness = 1 - ((time_cur - tt1_trigger) / tt_duration) ^ curve_pow
|
|
||||||
lights.write({[light_p1_r]={state=brightness*col_r}})
|
|
||||||
lights.write({[light_p1_g]={state=brightness*col_g}})
|
|
||||||
lights.write({[light_p1_b]={state=brightness*col_b}})
|
|
||||||
else
|
|
||||||
lights.write_reset(light_p1_r)
|
|
||||||
lights.write_reset(light_p1_g)
|
|
||||||
lights.write_reset(light_p1_b)
|
|
||||||
end
|
|
||||||
if time_cur - tt2_trigger < tt_duration then
|
|
||||||
brightness = 1 - ((time_cur - tt2_trigger) / tt_duration) ^ curve_pow
|
|
||||||
lights.write({[light_p2_r]={state=brightness*col_r}})
|
|
||||||
lights.write({[light_p2_g]={state=brightness*col_g}})
|
|
||||||
lights.write({[light_p2_b]={state=brightness*col_b}})
|
|
||||||
else
|
|
||||||
lights.write_reset(light_p2_r)
|
|
||||||
lights.write_reset(light_p2_g)
|
|
||||||
lights.write_reset(light_p2_b)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- flush HID light output
|
|
||||||
lights.update()
|
|
||||||
|
|
||||||
-- turntable movement detection
|
|
||||||
-- doesn't set the diff back to zero unless enough time has passed
|
|
||||||
if tt1_diff == 0 then
|
|
||||||
tt1_zero_elapsed = tt1_zero_elapsed + loop_delta
|
|
||||||
if tt1_zero_elapsed >= zero_duration then
|
|
||||||
tt1_diff_last = tt1_diff
|
|
||||||
end
|
|
||||||
else
|
|
||||||
tt1_zero_elapsed = 0
|
|
||||||
tt1_diff_last = tt1_diff
|
|
||||||
end
|
|
||||||
if tt2_diff == 0 then
|
|
||||||
tt2_zero_elapsed = tt2_zero_elapsed + loop_delta
|
|
||||||
if tt2_zero_elapsed >= zero_duration then
|
|
||||||
tt2_diff_last = tt2_diff
|
|
||||||
end
|
|
||||||
else
|
|
||||||
tt2_zero_elapsed = 0
|
|
||||||
tt2_diff_last = tt2_diff
|
|
||||||
end
|
|
||||||
|
|
||||||
-- remember state
|
|
||||||
tt1_last = tt1
|
|
||||||
tt2_last = tt2
|
|
||||||
|
|
||||||
-- loop end
|
|
||||||
sleep(loop_delta)
|
|
||||||
end
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
-- script examples
|
|
||||||
-- no proper documentation yet
|
|
||||||
-- create a folder called "script" next to spice and put me in there
|
|
||||||
-- then open the config and if needed select IIDX for the demo
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- sleep for 0.2 seconds
|
|
||||||
sleep(0.2)
|
|
||||||
|
|
||||||
-- log functions
|
|
||||||
log_misc("example misc")
|
|
||||||
log_info("example info")
|
|
||||||
log_warning("example warning")
|
|
||||||
--log_fatal("this would terminate")
|
|
||||||
|
|
||||||
-- print time
|
|
||||||
log_info(time())
|
|
||||||
|
|
||||||
-- show message box
|
|
||||||
msgbox("You are running the example script! Select IIDX if not already done.")
|
|
||||||
|
|
||||||
-- wait until analog is available
|
|
||||||
while not analogs.read()["Turntable P1"] do yield() end
|
|
||||||
|
|
||||||
-- write button state
|
|
||||||
buttons.write({["P1 Start"]={state=1}})
|
|
||||||
|
|
||||||
-- write analog state
|
|
||||||
analogs.write({["Turntable P1"]={state=0.33}})
|
|
||||||
|
|
||||||
-- write light state
|
|
||||||
lights.write({["P2 Start"]={state=0.8}})
|
|
||||||
|
|
||||||
-- import other libraries in "script" folder
|
|
||||||
--local example = require('script.example')
|
|
||||||
|
|
||||||
-- demo
|
|
||||||
while true do
|
|
||||||
|
|
||||||
-- analog animation
|
|
||||||
analogs.write({["Turntable P2"]={state=math.abs(math.sin(time()))}})
|
|
||||||
|
|
||||||
-- button blink
|
|
||||||
if math.cos(time() * 10) > 0 then
|
|
||||||
buttons.write({["P1 1"]={state=1}})
|
|
||||||
else
|
|
||||||
buttons.write({["P1 1"]={state=0}})
|
|
||||||
end
|
|
||||||
|
|
||||||
-- flush HID light output
|
|
||||||
lights.update()
|
|
||||||
|
|
||||||
-- check for keyboard press
|
|
||||||
if GetAsyncKeyState(0x20) > 0 then
|
|
||||||
msgbox("You pressed space!")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -12,3 +12,4 @@ from .keypads import *
|
|||||||
from .lights import *
|
from .lights import *
|
||||||
from .memory import *
|
from .memory import *
|
||||||
from .touch import *
|
from .touch import *
|
||||||
|
from .resize import *
|
||||||
@@ -2,8 +2,14 @@ from .connection import Connection
|
|||||||
from .request import Request
|
from .request import Request
|
||||||
|
|
||||||
|
|
||||||
def lights_read(con: Connection):
|
def lights_read(con: Connection, light_names=None):
|
||||||
res = con.request(Request("lights", "read"))
|
req = Request("lights", "read")
|
||||||
|
|
||||||
|
if light_names:
|
||||||
|
for light_name in light_names:
|
||||||
|
req.add_param(light_name)
|
||||||
|
|
||||||
|
res = con.request(req)
|
||||||
return res.get_data()
|
return res.get_data()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
from .connection import Connection
|
||||||
|
from .request import Request
|
||||||
|
|
||||||
|
def image_resize_enable(con: Connection, enable: bool):
|
||||||
|
req = Request("resize", "image_resize_enable")
|
||||||
|
req.add_param(enable)
|
||||||
|
con.request(req)
|
||||||
|
|
||||||
|
def image_resize_set_scene(con: Connection, scene: int):
|
||||||
|
req = Request("resize", "image_resize_set_scene")
|
||||||
|
req.add_param(scene)
|
||||||
|
con.request(req)
|
||||||
@@ -179,7 +179,7 @@ class ControlTab(ttk.Frame):
|
|||||||
self.card_lbl = ttk.Label(self.card, text="Card")
|
self.card_lbl = ttk.Label(self.card, text="Card")
|
||||||
self.card_lbl.grid(row=0, columnspan=2)
|
self.card_lbl.grid(row=0, columnspan=2)
|
||||||
self.card_entry = ttk.Entry(self.card)
|
self.card_entry = ttk.Entry(self.card)
|
||||||
self.card_entry.insert(tk.END, "E004000000000000")
|
self.card_entry.insert(tk.END, "E004010000000000")
|
||||||
self.card_entry.grid(row=1, columnspan=2, sticky=NSEW, padx=2, pady=2)
|
self.card_entry.grid(row=1, columnspan=2, sticky=NSEW, padx=2, pady=2)
|
||||||
self.card_insert_p1 = ttk.Button(self.card, text="Insert P1", command=self.action_insert_p1)
|
self.card_insert_p1 = ttk.Button(self.card, text="Insert P1", command=self.action_insert_p1)
|
||||||
self.card_insert_p1.grid(row=2, column=0, sticky=NSEW, padx=2, pady=2)
|
self.card_insert_p1.grid(row=2, column=0, sticky=NSEW, padx=2, pady=2)
|
||||||
@@ -397,6 +397,65 @@ class LightsTab(ttk.Frame):
|
|||||||
# set text
|
# set text
|
||||||
self.txt_lights.set_text(txt)
|
self.txt_lights.set_text(txt)
|
||||||
|
|
||||||
|
class ResizeTab(ttk.Frame):
|
||||||
|
"""Resize tab."""
|
||||||
|
|
||||||
|
def __init__(self, app, parent, **kwargs):
|
||||||
|
|
||||||
|
# init frame
|
||||||
|
ttk.Frame.__init__(self, parent, **kwargs)
|
||||||
|
self.app = app
|
||||||
|
self.parent = parent
|
||||||
|
|
||||||
|
# scale grid
|
||||||
|
self.columnconfigure(0, weight=1)
|
||||||
|
|
||||||
|
# image resize
|
||||||
|
self.resize = ttk.Frame(self, padding=(8, 8, 8, 8))
|
||||||
|
self.resize.grid(row=0, column=0, sticky=tk.E+tk.W)
|
||||||
|
self.resize.columnconfigure(0, weight=1)
|
||||||
|
self.resize.columnconfigure(1, weight=1)
|
||||||
|
self.resize_lbl = ttk.Label(self.resize, text="Image Resize")
|
||||||
|
self.resize_lbl.grid(row=0, columnspan=2)
|
||||||
|
|
||||||
|
self.resize_off = ttk.Button(self.resize, text="Disable", command=self.action_resize_false)
|
||||||
|
self.resize_off.grid(row=2, column=0, sticky=NSEW, padx=2, pady=2)
|
||||||
|
|
||||||
|
self.resize_on = ttk.Button(self.resize, text="Enable", command=self.action_resize_on)
|
||||||
|
self.resize_on.grid(row=2, column=1, sticky=NSEW, padx=2, pady=2)
|
||||||
|
|
||||||
|
self.resize_scene_1 = ttk.Button(self.resize, text="Scene 1", command=self.action_resize_scene_1)
|
||||||
|
self.resize_scene_1.grid(row=3, column=0, sticky=NSEW, padx=2, pady=2)
|
||||||
|
self.resize_scene_2 = ttk.Button(self.resize, text="Scene 2", command=self.action_resize_scene_2)
|
||||||
|
self.resize_scene_2.grid(row=3, column=1, sticky=NSEW, padx=2, pady=2)
|
||||||
|
self.resize_scene_3 = ttk.Button(self.resize, text="Scene 3", command=self.action_resize_scene_3)
|
||||||
|
self.resize_scene_3.grid(row=4, column=0, sticky=NSEW, padx=2, pady=2)
|
||||||
|
self.resize_scene_4 = ttk.Button(self.resize, text="Scene 4", command=self.action_resize_scene_4)
|
||||||
|
self.resize_scene_4.grid(row=4, column=1, sticky=NSEW, padx=2, pady=2)
|
||||||
|
|
||||||
|
@api_action
|
||||||
|
def action_resize_on(self):
|
||||||
|
spiceapi.image_resize_enable(self.app.connection, True)
|
||||||
|
|
||||||
|
@api_action
|
||||||
|
def action_resize_false(self):
|
||||||
|
spiceapi.image_resize_enable(self.app.connection, False)
|
||||||
|
|
||||||
|
@api_action
|
||||||
|
def action_resize_scene_1(self):
|
||||||
|
spiceapi.image_resize_set_scene(self.app.connection, 1)
|
||||||
|
|
||||||
|
@api_action
|
||||||
|
def action_resize_scene_2(self):
|
||||||
|
spiceapi.image_resize_set_scene(self.app.connection, 2)
|
||||||
|
|
||||||
|
@api_action
|
||||||
|
def action_resize_scene_3(self):
|
||||||
|
spiceapi.image_resize_set_scene(self.app.connection, 3)
|
||||||
|
|
||||||
|
@api_action
|
||||||
|
def action_resize_scene_4(self):
|
||||||
|
spiceapi.image_resize_set_scene(self.app.connection, 4)
|
||||||
|
|
||||||
class MainApp(ttk.Frame):
|
class MainApp(ttk.Frame):
|
||||||
"""The main application frame."""
|
"""The main application frame."""
|
||||||
@@ -419,6 +478,8 @@ class MainApp(ttk.Frame):
|
|||||||
self.tabs.add(self.tab_analogs, text="Analogs")
|
self.tabs.add(self.tab_analogs, text="Analogs")
|
||||||
self.tab_lights = LightsTab(self, self.tabs)
|
self.tab_lights = LightsTab(self, self.tabs)
|
||||||
self.tabs.add(self.tab_lights, text="Lights")
|
self.tabs.add(self.tab_lights, text="Lights")
|
||||||
|
self.tab_resize = ResizeTab(self, self.tabs)
|
||||||
|
self.tabs.add(self.tab_resize, text="Resize")
|
||||||
self.tab_manual = ManualTab(self, self.tabs)
|
self.tab_manual = ManualTab(self, self.tabs)
|
||||||
self.tabs.add(self.tab_manual, text="Manual")
|
self.tabs.add(self.tab_manual, text="Manual")
|
||||||
self.tabs.pack(expand=True, fill=tk.BOTH)
|
self.tabs.pack(expand=True, fill=tk.BOTH)
|
||||||
|
|||||||
+1
-1
@@ -471,7 +471,7 @@ namespace avs::automap {
|
|||||||
ENABLED = true;
|
ENABLED = true;
|
||||||
|
|
||||||
// check if optional imports are supported for this avs version
|
// check if optional imports are supported for this avs version
|
||||||
if (!avs::core::property_node_read) {
|
if (!avs::core::property_node_read || !avs::core::property_get_error) {
|
||||||
log_fatal("automap", "missing optional avs imports which are required for this module to work");
|
log_fatal("automap", "missing optional avs imports which are required for this module to work");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+28
-4
@@ -334,8 +334,12 @@ namespace avs {
|
|||||||
.avs_fs_close = "XC0bbe97000119",
|
.avs_fs_close = "XC0bbe97000119",
|
||||||
.avs_fs_dump_mountpoint = "XC0bbe970000c5",
|
.avs_fs_dump_mountpoint = "XC0bbe970000c5",
|
||||||
.avs_fs_mount = "XC0bbe97000099",
|
.avs_fs_mount = "XC0bbe97000099",
|
||||||
|
.avs_fs_fstat = "XC0bbe970000ce",
|
||||||
.avs_fs_lstat = "XC0bbe9700005f",
|
.avs_fs_lstat = "XC0bbe9700005f",
|
||||||
|
.avs_fs_read = "XC0bbe97000134",
|
||||||
.avs_fs_opendir = "XC0bbe970000db",
|
.avs_fs_opendir = "XC0bbe970000db",
|
||||||
|
.property_file_write = "property_file_write", // not found
|
||||||
|
.property_get_error = "property_get_error", // not found
|
||||||
.avs_net_add_protocol = "XC0bbe97000124",
|
.avs_net_add_protocol = "XC0bbe97000124",
|
||||||
.avs_net_del_protocol = "XC0bbe97000026",
|
.avs_net_del_protocol = "XC0bbe97000026",
|
||||||
.avs_net_addrinfobyaddr = "XC0bbe970000a4",
|
.avs_net_addrinfobyaddr = "XC0bbe970000a4",
|
||||||
@@ -1360,10 +1364,12 @@ namespace avs {
|
|||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
||||||
// error checking
|
// error checking
|
||||||
|
if (avs::core::property_get_error) {
|
||||||
auto err = avs::core::property_get_error(property);
|
auto err = avs::core::property_get_error(property);
|
||||||
if (err > 0) {
|
if (err > 0) {
|
||||||
log_fatal("avs-core", "failed to read config file ({}): {}", filename, error_str(err));
|
log_fatal("avs-core", "failed to read config file ({}): {}", filename, error_str(err));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// return value
|
// return value
|
||||||
return property;
|
return property;
|
||||||
@@ -1467,7 +1473,7 @@ namespace avs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool load_dll() {
|
void load_dll() {
|
||||||
log_info("avs-core", "loading DLL");
|
log_info("avs-core", "loading DLL");
|
||||||
|
|
||||||
// detect DLL name
|
// detect DLL name
|
||||||
@@ -1479,12 +1485,30 @@ namespace avs {
|
|||||||
#else
|
#else
|
||||||
DLL_NAME = "libavs-win32.dll";
|
DLL_NAME = "libavs-win32.dll";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!fileutils::file_exists(MODULE_PATH / DLL_NAME)) {
|
||||||
|
std::string info_str { fmt::format(
|
||||||
|
"\n\n"
|
||||||
|
"Failed to find critical avs DLL on disk (avs2-core.dll OR {})\n"
|
||||||
|
"Looked in the following directory: {}\n"
|
||||||
|
"\n"
|
||||||
|
"One of these is required to boot the game. Spice found neither of them. You do not need both, just one, next to your game DLL.\n"
|
||||||
|
"\n"
|
||||||
|
"HOW TO FIX:\n"
|
||||||
|
" * Avoid manually specifying DLL path (-exec) and module directory (-modules); let spice2x auto-detect unless you have a good reason not to\n"
|
||||||
|
" * Ensure you do NOT have multiple copies of the game DLLs (e.g., in contents and in contents\\modules)\n"
|
||||||
|
" * It's also possible that you have incomplete game data\n"
|
||||||
|
" * Do NOT copy over random DLLs from another game installation; DLL must match game version\n"
|
||||||
|
"\n"
|
||||||
|
, DLL_NAME, MODULE_PATH.string()) };
|
||||||
|
log_fatal("avs-ea3", "{}", info_str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// load library
|
// load library
|
||||||
DLL_INSTANCE = libutils::load_library(MODULE_PATH / DLL_NAME, false);
|
DLL_INSTANCE = libutils::load_library(MODULE_PATH / DLL_NAME);
|
||||||
if (!DLL_INSTANCE) {
|
if (!DLL_INSTANCE) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check by version string if obtained
|
// check by version string if obtained
|
||||||
@@ -1709,7 +1733,7 @@ namespace avs {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// success
|
// success
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void create_dir(
|
static void create_dir(
|
||||||
|
|||||||
+2
-1
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
@@ -448,7 +449,7 @@ namespace avs {
|
|||||||
// functions
|
// functions
|
||||||
void set_default_heap_size(const std::string &dll_name);
|
void set_default_heap_size(const std::string &dll_name);
|
||||||
void create_log();
|
void create_log();
|
||||||
bool load_dll();
|
void load_dll();
|
||||||
void boot();
|
void boot();
|
||||||
void copy_defaults();
|
void copy_defaults();
|
||||||
void shutdown();
|
void shutdown();
|
||||||
|
|||||||
+18
@@ -133,6 +133,24 @@ namespace avs {
|
|||||||
#else
|
#else
|
||||||
DLL_NAME = "libavs-win32-ea3.dll";
|
DLL_NAME = "libavs-win32-ea3.dll";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (!fileutils::file_exists(MODULE_PATH / DLL_NAME)) {
|
||||||
|
std::string info_str { fmt::format(
|
||||||
|
"\n\n"
|
||||||
|
"Failed to find critical ea3 DLL on disk (avs2-ea3.dll OR {})\n"
|
||||||
|
"Looked in the following directory: {}\n"
|
||||||
|
"\n"
|
||||||
|
"One of these is required to boot the game. Spice found neither of them. You do not need both, just one, next to your game DLL.\n"
|
||||||
|
"\n"
|
||||||
|
"HOW TO FIX:\n"
|
||||||
|
" * Avoid manually specifying DLL path (-exec) and module directory (-modules); let spice2x auto-detect unless you have a good reason not to\n"
|
||||||
|
" * Ensure you do NOT have multiple copies of the game DLLs (e.g., in contents and in contents\\modules)\n"
|
||||||
|
" * It's also possible that you have incomplete game data\n"
|
||||||
|
" * Do NOT copy over random DLLs from another game installation; DLL must match game version\n"
|
||||||
|
"\n"
|
||||||
|
, DLL_NAME, MODULE_PATH.string()) };
|
||||||
|
log_fatal("avs-ea3", "{}", info_str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// load library
|
// load library
|
||||||
|
|||||||
+29
-2
@@ -72,8 +72,35 @@ namespace avs {
|
|||||||
log_info("avs-game", "loading DLL '{}'", DLL_NAME);
|
log_info("avs-game", "loading DLL '{}'", DLL_NAME);
|
||||||
|
|
||||||
// load game instance
|
// load game instance
|
||||||
if (fileutils::verify_header_pe(MODULE_PATH / DLL_NAME)) {
|
const auto dll_path = MODULE_PATH / DLL_NAME;
|
||||||
DLL_INSTANCE = libutils::load_library(MODULE_PATH / DLL_NAME);
|
const auto dll_path_s = dll_path.string();
|
||||||
|
log_info("avs-game", "DLL path: {}", dll_path_s.c_str());
|
||||||
|
|
||||||
|
// MAX_PATH is 260
|
||||||
|
if (130 <= dll_path_s.length()) {
|
||||||
|
log_warning(
|
||||||
|
"avs-game",
|
||||||
|
"PATH TOO LONG WARNING\n\n\n"
|
||||||
|
"-------------------------------------------------------------------\n"
|
||||||
|
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
|
||||||
|
"WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING\n"
|
||||||
|
" PATH TOO LONG \n"
|
||||||
|
"WARNING - WARNING - WARNING - WARNING - WARNING - WARNING - WARNING\n"
|
||||||
|
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
|
||||||
|
"The path '{}'\n"
|
||||||
|
" has a length of {}\n"
|
||||||
|
"Most of these games may behave unexpectedly when the path is too\n"
|
||||||
|
"long, often resulting in random crashes. Move the game contents to\n"
|
||||||
|
"a directory with shorter path.\n"
|
||||||
|
"-------------------------------------------------------------------\n\n",
|
||||||
|
dll_path_s, dll_path_s.length());
|
||||||
|
}
|
||||||
|
if (!fileutils::file_exists(dll_path)) {
|
||||||
|
log_warning("avs-game", "game DLL could not be found on disk: {}", dll_path.string().c_str());
|
||||||
|
log_warning("avs-game", "double check -exec and -modules parameters; unless you know what you're doing, leave them blank");
|
||||||
|
}
|
||||||
|
if (fileutils::verify_header_pe(dll_path)) {
|
||||||
|
DLL_INSTANCE = libutils::load_library(dll_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// load entry points
|
// load entry points
|
||||||
|
|||||||
Regular → Executable
+66
-41
@@ -19,6 +19,25 @@ function trap_error_exit {
|
|||||||
trap trap_error_dbg DEBUG
|
trap trap_error_dbg DEBUG
|
||||||
trap trap_error_exit EXIT
|
trap trap_error_exit EXIT
|
||||||
|
|
||||||
|
IGNORE_CACHE=0
|
||||||
|
|
||||||
|
# Parse options
|
||||||
|
while getopts "ih" opt; do
|
||||||
|
case $opt in
|
||||||
|
i) IGNORE_CACHE=1 ;;
|
||||||
|
h)
|
||||||
|
echo "Usage: $0 [-i]"
|
||||||
|
echo " -i: Ignore build cache"
|
||||||
|
echo " -h: Show this help"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
\?)
|
||||||
|
echo "Invalid option: -$OPTARG" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
# settings
|
# settings
|
||||||
GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2> /dev/null || echo "none")
|
GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2> /dev/null || echo "none")
|
||||||
GIT_HEAD=$(git rev-parse HEAD || echo "none")
|
GIT_HEAD=$(git rev-parse HEAD || echo "none")
|
||||||
@@ -41,8 +60,8 @@ DIST_ENABLE=1
|
|||||||
DIST_FOLDER="./dist"
|
DIST_FOLDER="./dist"
|
||||||
DIST_NAME="spice2x-$(date +%y)-$(date +%m)-$(date +%d).zip"
|
DIST_NAME="spice2x-$(date +%y)-$(date +%m)-$(date +%d).zip"
|
||||||
DIST_COMMENT=${DIST_NAME}$'\n'"$GIT_BRANCH - $GIT_HEAD"$'\nThank you for playing.'
|
DIST_COMMENT=${DIST_NAME}$'\n'"$GIT_BRANCH - $GIT_HEAD"$'\nThank you for playing.'
|
||||||
TARGETS_32="spicetools_stubs_kbt spicetools_stubs_kld spicetools_cfg spicetools_spice"
|
TARGETS_32="spicetools_stubs_kbt spicetools_stubs_kld spicetools_cfg spicetools_spice spicetools_spice_laa"
|
||||||
TARGETS_64="spicetools_stubs_kbt64 spicetools_stubs_kld64 spicetools_spice64"
|
TARGETS_64="spicetools_stubs_kbt64 spicetools_stubs_kld64 spicetools_stubs_nvEncodeAPI64 spicetools_stubs_nvcuvid spicetools_stubs_nvcuda spicetools_spice64"
|
||||||
|
|
||||||
# determine build type
|
# determine build type
|
||||||
BUILD_TYPE="Release"
|
BUILD_TYPE="Release"
|
||||||
@@ -57,7 +76,7 @@ then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# determine number of cores
|
# determine number of cores
|
||||||
CORES=$(awk '/^processor\t/ {cores[$NF]++} END {print length(cores)}' /proc/cpuinfo)
|
CORES=$(nproc)
|
||||||
|
|
||||||
# print information
|
# print information
|
||||||
echo ""
|
echo ""
|
||||||
@@ -74,34 +93,45 @@ echo "Build Type: $BUILD_TYPE"
|
|||||||
echo "Cores: $CORES"
|
echo "Cores: $CORES"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# 32 bit
|
if ((IGNORE_CACHE > 0))
|
||||||
echo "Building 32bit targets..."
|
|
||||||
echo "========================="
|
|
||||||
if ((CLEAN_BUILD > 0))
|
|
||||||
then
|
then
|
||||||
|
echo "Ignoring build cache..."
|
||||||
|
else
|
||||||
|
export CCACHE_DIR="$(pwd)/.ccache"
|
||||||
|
export CMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||||
|
export CMAKE_C_COMPILER_LAUNCHER=ccache
|
||||||
|
fi
|
||||||
|
|
||||||
|
time (
|
||||||
|
# 32 bit
|
||||||
|
echo "Building 32bit targets..."
|
||||||
|
echo "========================="
|
||||||
|
if ((CLEAN_BUILD > 0))
|
||||||
|
then
|
||||||
rm -rf ${BUILDDIR_32}
|
rm -rf ${BUILDDIR_32}
|
||||||
fi
|
fi
|
||||||
mkdir -p ${BUILDDIR_32}
|
mkdir -p ${BUILDDIR_32}
|
||||||
pushd ${BUILDDIR_32} > /dev/null
|
pushd ${BUILDDIR_32} > /dev/null
|
||||||
cmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_32} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} $OLDPWD && make -j ${CORES} ${TARGETS_32}
|
cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_32} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} $OLDPWD && ninja ${TARGETS_32}
|
||||||
popd > /dev/null
|
popd > /dev/null
|
||||||
|
|
||||||
# 64 bit
|
# 64 bit
|
||||||
echo ""
|
echo ""
|
||||||
echo "Building 64bit targets..."
|
echo "Building 64bit targets..."
|
||||||
echo "========================="
|
echo "========================="
|
||||||
if ((CLEAN_BUILD > 0))
|
if ((CLEAN_BUILD > 0))
|
||||||
then
|
then
|
||||||
rm -rf ${BUILDDIR_64}
|
rm -rf ${BUILDDIR_64}
|
||||||
fi
|
fi
|
||||||
mkdir -p ${BUILDDIR_64}
|
mkdir -p ${BUILDDIR_64}
|
||||||
pushd ${BUILDDIR_64} > /dev/null
|
pushd ${BUILDDIR_64} > /dev/null
|
||||||
cmake -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_64} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} $OLDPWD && make -j ${CORES} ${TARGETS_64}
|
cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_64} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} $OLDPWD && ninja ${TARGETS_64}
|
||||||
popd > /dev/null
|
popd > /dev/null
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "Compilation process done :)"
|
echo "Compilation process done :)"
|
||||||
echo "==========================="
|
echo "==========================="
|
||||||
|
)
|
||||||
|
|
||||||
# generate PDBs
|
# generate PDBs
|
||||||
if false # ((DEBUG > 0))
|
if false # ((DEBUG > 0))
|
||||||
@@ -152,7 +182,8 @@ echo "Copy files to output directory..."
|
|||||||
rm -rf ${OUTDIR}
|
rm -rf ${OUTDIR}
|
||||||
mkdir -p ${OUTDIR}
|
mkdir -p ${OUTDIR}
|
||||||
#mkdir -p ${OUTDIR}/stubs/32
|
#mkdir -p ${OUTDIR}/stubs/32
|
||||||
#mkdir -p ${OUTDIR}/stubs/64
|
mkdir -p ${OUTDIR}/stubs/64
|
||||||
|
mkdir -p ${OUTDIR}/extras/largeaddressaware
|
||||||
if false # ((DEBUG > 0))
|
if false # ((DEBUG > 0))
|
||||||
then
|
then
|
||||||
# debug files
|
# debug files
|
||||||
@@ -166,28 +197,22 @@ then
|
|||||||
cp ${BUILDDIR_64}/spicetools/64/spice64-pdb.pdb ${OUTDIR} 2>/dev/null
|
cp ${BUILDDIR_64}/spicetools/64/spice64-pdb.pdb ${OUTDIR} 2>/dev/null
|
||||||
#cp ${BUILDDIR_64}/spicetools/64/kbt.dll ${OUTDIR}/stubs/64 2>/dev/null
|
#cp ${BUILDDIR_64}/spicetools/64/kbt.dll ${OUTDIR}/stubs/64 2>/dev/null
|
||||||
#cp ${BUILDDIR_64}/spicetools/64/kld.dll ${OUTDIR}/stubs/64 2>/dev/null
|
#cp ${BUILDDIR_64}/spicetools/64/kld.dll ${OUTDIR}/stubs/64 2>/dev/null
|
||||||
|
#cp ${BUILDDIR_64}/spicetools/64/nvEncodeAPI64.dll ${OUTDIR}/stubs/64 2>/dev/null
|
||||||
|
#cp ${BUILDDIR_64}/spicetools/64/nvcuda.dll ${OUTDIR}/stubs/64 2>/dev/null
|
||||||
|
#cp ${BUILDDIR_64}/spicetools/64/nvcuvid.dll ${OUTDIR}/stubs/64 2>/dev/null
|
||||||
else
|
else
|
||||||
# release files
|
# release files
|
||||||
cp ${BUILDDIR_32}/spicetools/spicecfg.exe ${OUTDIR} 2>/dev/null
|
cp ${BUILDDIR_32}/spicetools/spicecfg.exe ${OUTDIR} 2>/dev/null
|
||||||
cp ${BUILDDIR_32}/spicetools/32/spice.exe ${OUTDIR} 2>/dev/null
|
cp ${BUILDDIR_32}/spicetools/32/spice.exe ${OUTDIR} 2>/dev/null
|
||||||
|
cp ${BUILDDIR_32}/spicetools/32/spice_laa.exe ${OUTDIR}/extras/largeaddressaware/spice.exe 2>/dev/null
|
||||||
#cp ${BUILDDIR_32}/spicetools/32/kbt.dll ${OUTDIR}/stubs/32 2>/dev/null
|
#cp ${BUILDDIR_32}/spicetools/32/kbt.dll ${OUTDIR}/stubs/32 2>/dev/null
|
||||||
#cp ${BUILDDIR_32}/spicetools/32/kld.dll ${OUTDIR}/stubs/32 2>/dev/null
|
#cp ${BUILDDIR_32}/spicetools/32/kld.dll ${OUTDIR}/stubs/32 2>/dev/null
|
||||||
cp ${BUILDDIR_64}/spicetools/64/spice64.exe ${OUTDIR} 2>/dev/null
|
cp ${BUILDDIR_64}/spicetools/64/spice64.exe ${OUTDIR} 2>/dev/null
|
||||||
#cp ${BUILDDIR_64}/spicetools/64/kbt.dll ${OUTDIR}/stubs/64 2>/dev/null
|
#cp ${BUILDDIR_64}/spicetools/64/kbt.dll ${OUTDIR}/stubs/64 2>/dev/null
|
||||||
#cp ${BUILDDIR_64}/spicetools/64/kld.dll ${OUTDIR}/stubs/64 2>/dev/null
|
#cp ${BUILDDIR_64}/spicetools/64/kld.dll ${OUTDIR}/stubs/64 2>/dev/null
|
||||||
fi
|
cp ${BUILDDIR_64}/spicetools/64/nvEncodeAPI64.dll ${OUTDIR}/stubs/64 2>/dev/null
|
||||||
|
cp ${BUILDDIR_64}/spicetools/64/nvcuda.dll ${OUTDIR}/stubs/64 2>/dev/null
|
||||||
# compress using UPX
|
cp ${BUILDDIR_64}/spicetools/64/nvcuvid.dll ${OUTDIR}/stubs/64 2>/dev/null
|
||||||
if ((UPX_ENABLE > 0 && DEBUG == 0))
|
|
||||||
then
|
|
||||||
echo "Processing files with UPX..."
|
|
||||||
upx ${UPX_FLAGS} ${OUTDIR}/spicecfg.exe > /dev/null
|
|
||||||
upx ${UPX_FLAGS} ${OUTDIR}/spice.exe > /dev/null
|
|
||||||
#upx ${UPX_FLAGS} ${OUTDIR}/stubs/32/kbt.dll > /dev/null
|
|
||||||
#upx ${UPX_FLAGS} ${OUTDIR}/stubs/32/kld.dll > /dev/null
|
|
||||||
upx ${UPX_FLAGS} ${OUTDIR}/spice64.exe > /dev/null
|
|
||||||
#upx ${UPX_FLAGS} ${OUTDIR}/stubs/64/kbt.dll > /dev/null
|
|
||||||
#upx ${UPX_FLAGS} ${OUTDIR}/stubs/64/kld.dll > /dev/null
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# pack source files to output directory
|
# pack source files to output directory
|
||||||
@@ -196,7 +221,7 @@ mkdir -p ${OUTDIR}/src
|
|||||||
if ((INCLUDE_SRC > 0))
|
if ((INCLUDE_SRC > 0))
|
||||||
then
|
then
|
||||||
echo "Generating source file archive..."
|
echo "Generating source file archive..."
|
||||||
git archive --format tar.gz --prefix=spice2x/ HEAD > ${OUTDIR}/src/spice2x-${GIT_BRANCH}.tar.gz 2>/dev/null || \
|
git archive --format tar.gz --prefix=spice2x/ HEAD ./ > ${OUTDIR}/src/spice2x-${GIT_BRANCH}.tar.gz 2>/dev/null || \
|
||||||
echo "WARNING: Couldn't get git to create the archive. Is this a git repository?"
|
echo "WARNING: Couldn't get git to create the archive. Is this a git repository?"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
docker build --pull external/docker -t spicetools/deps
|
docker build --pull external/docker -t spicetools/deps
|
||||||
docker build . -t spicetools/spice --no-cache
|
docker build --build-context gitroot=%cd%/../../.git . -t spicetools/spice
|
||||||
docker run --rm -it -v %cd%/dist:/src/dist -v %cd%/bin:/src/bin spicetools/spice
|
docker run --rm -it -v %cd%/dist:/src/src/spice2x/dist -v %cd%/bin:/src/src/spice2x/bin -v %cd%/.ccache:/src/src/spice2x/.ccache spicetools/spice %*
|
||||||
@REM to generate PDBs, set DEBUG to 1 in build_all.sh, place cv2pdb in external\cv2pdb, and run below
|
@REM to generate PDBs, set DEBUG to 1 in build_all.sh, place cv2pdb in external\cv2pdb, and run below
|
||||||
@REM external\cv2pdb\cv2pdb.exe bin\spice2x\spicecfg.exe bin\spice2x\spicecfg-pdb.exe bin\spice2x\spicecfg-pdb.pdb
|
@REM external\cv2pdb\cv2pdb.exe bin\spice2x\spicecfg.exe bin\spice2x\spicecfg-pdb.exe bin\spice2x\spicecfg-pdb.pdb
|
||||||
@REM external\cv2pdb\cv2pdb.exe bin\spice2x\spice.exe bin\spice2x\spice-pdb.exe bin\spice2x\spice-pdb.pdb
|
@REM external\cv2pdb\cv2pdb.exe bin\spice2x\spice.exe bin\spice2x\spice-pdb.exe bin\spice2x\spice-pdb.pdb
|
||||||
|
|||||||
Regular → Executable
+2
-4
@@ -1,6 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
export DOCKER_BUILDKIT=0
|
|
||||||
|
|
||||||
docker build --pull $PWD/external/docker -t spicetools/deps --platform linux/x86_64
|
docker build --pull $PWD/external/docker -t spicetools/deps --platform linux/x86_64
|
||||||
docker build . -t spicetools/spice:latest --no-cache
|
docker build --build-context gitroot=$PWD/../../.git . -t spicetools/spice:latest
|
||||||
docker run --rm -it -v $PWD/dist:/src/dist -v $PWD/bin:/src/bin spicetools/spice
|
docker run --rm -v $PWD/dist:/src/src/spice2x/dist -v $PWD/bin:/src/src/spice2x/bin -v $PWD/.ccache:/src/src/spice2x/.ccache spicetools/spice "$@"
|
||||||
|
|||||||
@@ -1,85 +0,0 @@
|
|||||||
from typing import Dict, List
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
|
|
||||||
def get_vs_installation_path() -> str:
|
|
||||||
program_files_x86 = os.environ["ProgramFiles(x86)"]
|
|
||||||
process = subprocess.run(
|
|
||||||
[f"{program_files_x86}\\Microsoft Visual Studio\\Installer\\vswhere.exe", "-prerelease", "-latest", "-property",
|
|
||||||
"installationPath"],
|
|
||||||
capture_output=True, check=True, encoding="utf-8")
|
|
||||||
|
|
||||||
return process.stdout.strip()
|
|
||||||
|
|
||||||
|
|
||||||
def source_bat(bat_file: str, arch: str) -> Dict[str, str]:
|
|
||||||
interesting = {"INCLUDE", "LIB", "LIBPATH", "PATH"}
|
|
||||||
result = {}
|
|
||||||
|
|
||||||
process = subprocess.Popen(f"\"{bat_file}\" {arch} & set", stdout=subprocess.PIPE, shell=True, encoding="utf-8")
|
|
||||||
(out, err) = process.communicate()
|
|
||||||
|
|
||||||
if err is not None:
|
|
||||||
raise Exception(err)
|
|
||||||
|
|
||||||
for line in out.split("\n"):
|
|
||||||
if '=' not in line:
|
|
||||||
continue
|
|
||||||
|
|
||||||
key, value = line.strip().split('=', 1)
|
|
||||||
key = key.upper()
|
|
||||||
|
|
||||||
if key in interesting:
|
|
||||||
result[key] = value
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def run_build(build_dir: str, build_type: str, build_targets: List[str], build_env: Dict[str, str]):
|
|
||||||
os.makedirs(build_dir, exist_ok=True)
|
|
||||||
|
|
||||||
subprocess.check_call(["cmake.exe", f"-DCMAKE_BUILD_TYPE={build_type}", "-GNinja", ".."], cwd=build_dir,
|
|
||||||
env=build_env, shell=True)
|
|
||||||
subprocess.check_call(["ninja.exe"] + build_targets, cwd=build_dir, env=build_env, shell=True)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
parser = argparse.ArgumentParser(description='Build SpiceTools with MSVC')
|
|
||||||
parser.add_argument('--build-type', type=str, default='Release', help='CMake build type')
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
build_dir = args.build_type.lower()
|
|
||||||
parent_env = {key: os.environ[key] for key in os.environ}
|
|
||||||
|
|
||||||
vs_installation_path = get_vs_installation_path()
|
|
||||||
bat_file = f"{vs_installation_path}\\VC\\Auxiliary\\Build\\vcvarsall.bat"
|
|
||||||
print(bat_file)
|
|
||||||
|
|
||||||
# parent_env["CC"] = "clang"
|
|
||||||
# parent_env["CXX"] = "clang++"
|
|
||||||
|
|
||||||
print("Building spice64")
|
|
||||||
|
|
||||||
env_64 = source_bat(bat_file, "x64")
|
|
||||||
env_64_merged = parent_env.copy()
|
|
||||||
env_64_merged.update(env_64)
|
|
||||||
|
|
||||||
run_build(f"cmake-build-{build_dir}-64", args.build_type,
|
|
||||||
["spicetools_stubs_kbt64", "spicetools_stubs_kld64", "spicetools_spice64"], env_64_merged)
|
|
||||||
|
|
||||||
print("Building spice")
|
|
||||||
|
|
||||||
env_32 = source_bat(bat_file, "x86")
|
|
||||||
env_32_merged = parent_env.copy()
|
|
||||||
env_32_merged.update(env_32)
|
|
||||||
|
|
||||||
run_build(f"cmake-build-{build_dir}-32", args.build_type,
|
|
||||||
["spicetools_stubs_kbt", "spicetools_stubs_kld", "spicetools_cfg", "spicetools_spice"], env_32_merged)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
del /s /q .ccache
|
||||||
|
call build_docker.bat
|
||||||
+121
-7
@@ -55,20 +55,39 @@ std::string Analog::getDisplayString(rawinput::RawInputManager *manager) {
|
|||||||
}
|
}
|
||||||
case rawinput::MIDI: {
|
case rawinput::MIDI: {
|
||||||
auto midi = device->midiInfo;
|
auto midi = device->midiInfo;
|
||||||
|
// update strings in button.cpp as well
|
||||||
if (index < midi->controls_precision.size()) {
|
if (index < midi->controls_precision.size()) {
|
||||||
return "MIDI PREC " + indexString + " (" + device->desc + ")";
|
const int channel = (index / 32) + 1;
|
||||||
|
const int cc_index = (index % 32);
|
||||||
|
return fmt::format("MIDI Prec Ctrl Ch.{} CC#{} ({})", channel, cc_index, device->desc);
|
||||||
} else if (index < midi->controls_precision.size() + midi->controls_single.size()) {
|
} else if (index < midi->controls_precision.size() + midi->controls_single.size()) {
|
||||||
return "MIDI CTRL " + indexString + " (" + device->desc + ")";
|
const int index_rel = index - midi->controls_precision.size();
|
||||||
|
const int channel = (index_rel / 44) + 1;
|
||||||
|
int cc_index = (index_rel % 44);
|
||||||
|
if (cc_index < 26) {
|
||||||
|
cc_index += 0x46; // single byte range
|
||||||
|
} else {
|
||||||
|
cc_index = cc_index - 26 + 0x66; // undefined single byte range
|
||||||
|
}
|
||||||
|
return fmt::format("MIDI Ctrl Ch.{} CC#{} ({})", channel, cc_index, device->desc);
|
||||||
} else if (index < midi->controls_precision.size() + midi->controls_single.size()
|
} else if (index < midi->controls_precision.size() + midi->controls_single.size()
|
||||||
+ midi->controls_onoff.size())
|
+ midi->controls_onoff.size())
|
||||||
{
|
{
|
||||||
return "MIDI ONOFF " + indexString + " (" + device->desc + ")";
|
const int index_rel = index - midi->controls_precision.size() - midi->controls_single.size();
|
||||||
} else if (index == midi->controls_precision.size() + midi->controls_single.size()
|
const int channel = (index_rel / 6) + 1;
|
||||||
+ midi->controls_onoff.size())
|
const int cc_index = (index_rel % 6) + 0x40;
|
||||||
|
return fmt::format("MIDI OnOff Ch.{} CC#{} ({})", channel, cc_index, device->desc);
|
||||||
|
} else if (index <
|
||||||
|
midi->controls_precision.size() + midi->controls_single.size() + midi->controls_onoff.size() + midi->pitch_bend.size())
|
||||||
{
|
{
|
||||||
return "MIDI Pitch Bend (" + device->desc + ")";
|
const int index_rel =
|
||||||
|
index -
|
||||||
|
midi->controls_precision.size() -
|
||||||
|
midi->controls_single.size() -
|
||||||
|
midi->controls_onoff.size();
|
||||||
|
return fmt::format("MIDI Pitch Ch.{} ({})", index_rel + 1, device->desc);
|
||||||
} else {
|
} else {
|
||||||
return "MIDI Unknown " + indexString + " (" + device->desc + ")";
|
return "MIDI Unknown Index " + indexString + " (" + device->desc + ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case rawinput::DESTROYED:
|
case rawinput::DESTROYED:
|
||||||
@@ -158,3 +177,98 @@ float Analog::normalizeAngle(float rads) {
|
|||||||
}
|
}
|
||||||
return angle;
|
return angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Analog::applyMultiplier(float value) {
|
||||||
|
if (1 < this->multiplier) {
|
||||||
|
// multiplier - just multiply the value and take the decimal part
|
||||||
|
return normalizeAnalogValue(value * this->multiplier);
|
||||||
|
} else if (this->multiplier < -1) {
|
||||||
|
const unsigned short number_of_divisions = -this->multiplier;
|
||||||
|
// divisor - need to take care of over/underflow
|
||||||
|
if (0.75f < this->divisor_previous_value && value < 0.25f) {
|
||||||
|
this->divisor_region = (this->divisor_region + 1) % number_of_divisions;
|
||||||
|
} else if (this->divisor_previous_value < 0.25f && 0.75f < value) {
|
||||||
|
if (1 <= this->divisor_region) {
|
||||||
|
this->divisor_region -= 1;
|
||||||
|
} else {
|
||||||
|
this->divisor_region = number_of_divisions - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->divisor_previous_value = value;
|
||||||
|
return ((float)this->divisor_region + value) / (float)number_of_divisions;
|
||||||
|
} else {
|
||||||
|
// multiplier in [-1, 1] range is just treated as 1
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float Analog::normalizeAnalogValue(float value) {
|
||||||
|
// effectively the same as fmodf(value, 1.f)
|
||||||
|
// for small values, this is MUCH faster than fmodf.
|
||||||
|
float new_value = value;
|
||||||
|
while (new_value > 1.f) {
|
||||||
|
new_value -= 1.f;
|
||||||
|
}
|
||||||
|
while (new_value < 0.f) {
|
||||||
|
new_value += 1.f;
|
||||||
|
}
|
||||||
|
return new_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Analog::applyDeadzone(float raw_value) {
|
||||||
|
float value = raw_value;
|
||||||
|
const auto deadzone = this->getDeadzone();
|
||||||
|
if (deadzone > 0) {
|
||||||
|
|
||||||
|
// calculate values
|
||||||
|
const auto delta = value - 0.5f;
|
||||||
|
const auto dtlen = 1.f - deadzone;
|
||||||
|
|
||||||
|
// check mirror
|
||||||
|
if (this->getDeadzoneMirror()) {
|
||||||
|
|
||||||
|
// deadzone on the edges
|
||||||
|
if (dtlen != 0.f) {
|
||||||
|
value = std::max(0.f, std::min(1.f, 0.5f + (delta / dtlen)));
|
||||||
|
} else {
|
||||||
|
value = 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// deadzone around the middle
|
||||||
|
const auto limit = deadzone * 0.5f;
|
||||||
|
if (dtlen != 0.f) {
|
||||||
|
if (delta > limit) {
|
||||||
|
value = std::min(1.f, 0.5f + std::max(0.f, (delta - limit) / dtlen));
|
||||||
|
} else if (delta < -limit) {
|
||||||
|
value = std::max(0.f, 0.5f + std::min(0.f, (delta + limit) / dtlen));
|
||||||
|
} else {
|
||||||
|
value = 0.5f;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value = 0.5f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (deadzone < 0) {
|
||||||
|
|
||||||
|
// invert for mirror
|
||||||
|
if (this->getDeadzoneMirror()) {
|
||||||
|
value = 1.f - value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// deadzone from minimum value
|
||||||
|
if (deadzone > -1 && value > -deadzone) {
|
||||||
|
value = std::min(1.f, (value + deadzone) / (1.f + deadzone));
|
||||||
|
} else {
|
||||||
|
value = 0.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// revert value for mirror
|
||||||
|
if (this->getDeadzoneMirror()) {
|
||||||
|
value = 1.f - value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
+58
-1
@@ -3,6 +3,7 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
#define ANALOG_HISTORY_CNT 10
|
#define ANALOG_HISTORY_CNT 10
|
||||||
#define M_TAU (2 * M_PI)
|
#define M_TAU (2 * M_PI)
|
||||||
@@ -22,7 +23,7 @@ class Analog {
|
|||||||
private:
|
private:
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string device_identifier = "";
|
std::string device_identifier = "";
|
||||||
unsigned short index = 0xFF;
|
unsigned short index = USHRT_MAX;
|
||||||
float sensitivity = 1.f;
|
float sensitivity = 1.f;
|
||||||
float deadzone = 0.f;
|
float deadzone = 0.f;
|
||||||
bool deadzone_mirror = false;
|
bool deadzone_mirror = false;
|
||||||
@@ -41,8 +42,22 @@ private:
|
|||||||
float previous_raw_rads = 0.f;
|
float previous_raw_rads = 0.f;
|
||||||
float adjusted_rads = 0.f;
|
float adjusted_rads = 0.f;
|
||||||
|
|
||||||
|
// multiplier/divisor
|
||||||
|
int multiplier = 1;
|
||||||
|
float divisor_previous_value = 0.5f;
|
||||||
|
unsigned short divisor_region = 0;
|
||||||
|
|
||||||
|
// relative input mode
|
||||||
|
float absolute_value_for_rel_mode = 0.5f;
|
||||||
|
bool relative_mode = false;
|
||||||
|
|
||||||
|
// circular buffer (delayed input)
|
||||||
|
int delay_buffer_depth = 0;
|
||||||
|
std::queue<float> delay_buffer;
|
||||||
|
|
||||||
float calculateAngularDifference(float old_rads, float new_rads);
|
float calculateAngularDifference(float old_rads, float new_rads);
|
||||||
float normalizeAngle(float rads);
|
float normalizeAngle(float rads);
|
||||||
|
float normalizeAnalogValue(float value);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -57,6 +72,8 @@ public:
|
|||||||
std::string getDisplayString(rawinput::RawInputManager* manager);
|
std::string getDisplayString(rawinput::RawInputManager* manager);
|
||||||
float getSmoothedValue(float raw_rads);
|
float getSmoothedValue(float raw_rads);
|
||||||
float applyAngularSensitivity(float raw_rads);
|
float applyAngularSensitivity(float raw_rads);
|
||||||
|
float applyMultiplier(float raw_value);
|
||||||
|
float applyDeadzone(float raw_value);
|
||||||
|
|
||||||
inline bool isSet() {
|
inline bool isSet() {
|
||||||
if (this->override_enabled) {
|
if (this->override_enabled) {
|
||||||
@@ -72,6 +89,9 @@ public:
|
|||||||
setDeadzone(0.f);
|
setDeadzone(0.f);
|
||||||
invert = false;
|
invert = false;
|
||||||
smoothing = false;
|
smoothing = false;
|
||||||
|
setMultiplier(1);
|
||||||
|
setRelativeMode(false);
|
||||||
|
setDelayBufferDepth(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const std::string &getName() const {
|
inline const std::string &getName() const {
|
||||||
@@ -144,6 +164,16 @@ public:
|
|||||||
this->smoothing = smoothing;
|
this->smoothing = smoothing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int getMultiplier() const {
|
||||||
|
return this->multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setMultiplier(int multiplier) {
|
||||||
|
this->multiplier = multiplier;
|
||||||
|
this->divisor_region = 0;
|
||||||
|
this->divisor_previous_value = 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
inline float getLastState() const {
|
inline float getLastState() const {
|
||||||
return this->last_state;
|
return this->last_state;
|
||||||
}
|
}
|
||||||
@@ -151,4 +181,31 @@ public:
|
|||||||
inline void setLastState(float last_state) {
|
inline void setLastState(float last_state) {
|
||||||
this->last_state = last_state;
|
this->last_state = last_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool isRelativeMode() const {
|
||||||
|
return this->relative_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setRelativeMode(bool relative_mode) {
|
||||||
|
this->relative_mode = relative_mode;
|
||||||
|
this->absolute_value_for_rel_mode = 0.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline float getAbsoluteValue(float relative_delta) {
|
||||||
|
this->absolute_value_for_rel_mode =
|
||||||
|
normalizeAnalogValue(this->absolute_value_for_rel_mode + relative_delta);
|
||||||
|
return this->absolute_value_for_rel_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int getDelayBufferDepth() const {
|
||||||
|
return this->delay_buffer_depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setDelayBufferDepth(int depth) {
|
||||||
|
this->delay_buffer_depth = depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::queue<float> &getDelayBuffer() {
|
||||||
|
return this->delay_buffer;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+256
-90
@@ -17,6 +17,8 @@ std::vector<Button> GameAPI::Buttons::getButtons(Game *game) {
|
|||||||
return Config::getInstance().getButtons(game);
|
return Config::getInstance().getButtons(game);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Buttons::State getMidiV2ButtonState(float last_on_time, float last_off_time);
|
||||||
|
|
||||||
std::vector<Button> GameAPI::Buttons::sortButtons(
|
std::vector<Button> GameAPI::Buttons::sortButtons(
|
||||||
const std::vector<Button> &buttons,
|
const std::vector<Button> &buttons,
|
||||||
const std::vector<std::string> &button_names,
|
const std::vector<std::string> &button_names,
|
||||||
@@ -161,14 +163,17 @@ GameAPI::Buttons::State GameAPI::Buttons::getState(rawinput::RawInputManager *ma
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BAT_NEGATIVE:
|
case BAT_NEGATIVE:
|
||||||
case BAT_POSITIVE: {
|
case BAT_POSITIVE:
|
||||||
|
case BAT_ANY: {
|
||||||
auto value_states = &hid->value_states;
|
auto value_states = &hid->value_states;
|
||||||
if (vKey < value_states->size()) {
|
if (vKey < value_states->size()) {
|
||||||
auto value = value_states->at(vKey);
|
auto value = value_states->at(vKey);
|
||||||
if (current_button->getAnalogType() == BAT_POSITIVE) {
|
if (current_button->getAnalogType() == BAT_POSITIVE) {
|
||||||
state = value > 0.6f ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
state = value > 0.6f ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
||||||
} else {
|
} else if (current_button->getAnalogType() == BAT_NEGATIVE) {
|
||||||
state = value < 0.4f ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
state = value < 0.4f ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
||||||
|
} else {
|
||||||
|
state = value > 0.01f ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
state = BUTTON_NOT_PRESSED;
|
state = BUTTON_NOT_PRESSED;
|
||||||
@@ -216,8 +221,21 @@ GameAPI::Buttons::State GameAPI::Buttons::getState(rawinput::RawInputManager *ma
|
|||||||
auto midi = device->midiInfo;
|
auto midi = device->midiInfo;
|
||||||
switch (bat) {
|
switch (bat) {
|
||||||
case BAT_NONE: {
|
case BAT_NONE: {
|
||||||
if (vKey < 16 * 128) {
|
if (rawinput::get_midi_algorithm() == rawinput::MidiNoteAlgorithm::LEGACY) {
|
||||||
|
// spicetools legacy midi logic: use event log
|
||||||
|
//
|
||||||
|
// drums send NOTE_ON and NOTE_OFF in rapid succession, before game engine has a chance
|
||||||
|
// to poll for it - to address this, keep a counter (states_events array) and the last
|
||||||
|
// state (states array), incrementing the states_events on rising edges (NOTE_ON)
|
||||||
|
// and popping events off the queue every time it's checked.
|
||||||
|
//
|
||||||
|
// if the same drum pad is mapped to multiple buttons, multiple issues arise:
|
||||||
|
// 1. we run through this logic for each button, which consumes an event every time;
|
||||||
|
// therefore, the first button may see the ON event, but subsequent mappings may
|
||||||
|
// completely miss it as it already has been drained
|
||||||
|
// 2. it is impossible to implement velocity threshold with this logic since the
|
||||||
|
// velocity is a per-note value that goes away as soon as NOTE_OFF is detected
|
||||||
|
if (vKey < midi->states_events.size()) {
|
||||||
// check for event
|
// check for event
|
||||||
auto midi_event = midi->states_events[vKey];
|
auto midi_event = midi->states_events[vKey];
|
||||||
if (midi_event) {
|
if (midi_event) {
|
||||||
@@ -226,40 +244,112 @@ GameAPI::Buttons::State GameAPI::Buttons::getState(rawinput::RawInputManager *ma
|
|||||||
state = (midi_event % 2) ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
state = (midi_event % 2) ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
||||||
|
|
||||||
// update event
|
// update event
|
||||||
if (!midi->states[vKey] || midi_event > 1)
|
if (!midi->states[vKey] || midi_event > 1) {
|
||||||
midi->states_events[vKey]--;
|
midi->states_events[vKey]--;
|
||||||
|
}
|
||||||
} else
|
} else {
|
||||||
state = BUTTON_NOT_PRESSED;
|
state = BUTTON_NOT_PRESSED;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// spice2x midi logic (new!)
|
||||||
|
//
|
||||||
|
// for every MIDI NOTE ON message, latch the "on" for a certain time, even if NOTE
|
||||||
|
// OFF message is seen immediately afterwards.
|
||||||
|
//
|
||||||
|
// each ON event is held long enough for the game's input poll to see it (e.g., gitadora
|
||||||
|
// polls every 16ms or so, rawinput holds it for 20ms by default)
|
||||||
|
//
|
||||||
|
// this is much simpler and does not have the issues mentioned above for the legacy
|
||||||
|
// logic, however the downside is that there is a risk of coalescing rapid inputs into
|
||||||
|
// one.
|
||||||
|
//
|
||||||
|
// that being said:
|
||||||
|
// * default value of 20ms should be reasonable; humans can't realistically hit the
|
||||||
|
// same note faster than this; in fact it's likely to be a misfire
|
||||||
|
// * we can tweak it per-game if needed to suit the game's polling period (in the
|
||||||
|
// future)
|
||||||
|
// * as a last resort the user can always override it via the option (MidiNoteSustain)
|
||||||
|
if (vKey < midi->v2_last_on_time.size()) {
|
||||||
|
|
||||||
|
// take the velocity threshold from first button binding we encounter here
|
||||||
|
// this hardware key may be mapped to multiple bindings, but the UI should keep them
|
||||||
|
// the same value, as only one threshold value can be set per MIDI key
|
||||||
|
// (otherwise it makes the sustain logic too complicated)
|
||||||
|
const auto sw_threshold = current_button->getVelocityThreshold();
|
||||||
|
if (0 < sw_threshold && !midi->v2_velocity_threshold_set_on_device[vKey]) {
|
||||||
|
midi->v2_velocity_threshold_set_on_device[vKey] = true;
|
||||||
|
midi->v2_velocity_threshold[vKey] = sw_threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
state = getMidiV2ButtonState(
|
||||||
|
midi->v2_last_on_time[vKey],
|
||||||
|
midi->v2_last_off_time[vKey]);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
state = BUTTON_NOT_PRESSED;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BAT_MIDI_CTRL_PRECISION: {
|
case BAT_MIDI_CTRL_PRECISION: {
|
||||||
if (vKey < 16 * 32)
|
if (vKey < midi->controls_precision.size()) {
|
||||||
|
if (rawinput::get_midi_algorithm() == rawinput::MidiNoteAlgorithm::LEGACY) {
|
||||||
state = midi->controls_precision[vKey] > 0 ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
state = midi->controls_precision[vKey] > 0 ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
||||||
else
|
} else {
|
||||||
|
// not using getVelocityHelper here to avoid locking and other checks
|
||||||
|
const auto v = device->midiInfo->controls_precision[vKey];
|
||||||
|
// velocity threshold ranges from [0, 127], so do some math for double precision
|
||||||
|
const auto threshold = (current_button->getVelocityThreshold() << 7u) | 0x7f;
|
||||||
|
state = (threshold < v) ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
state = BUTTON_NOT_PRESSED;
|
state = BUTTON_NOT_PRESSED;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BAT_MIDI_CTRL_SINGLE: {
|
case BAT_MIDI_CTRL_SINGLE: {
|
||||||
if (vKey < 16 * 44)
|
if (vKey < midi->controls_single.size()) {
|
||||||
|
if (rawinput::get_midi_algorithm() == rawinput::MidiNoteAlgorithm::LEGACY) {
|
||||||
state = midi->controls_single[vKey] > 0 ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
state = midi->controls_single[vKey] > 0 ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
||||||
else
|
} else {
|
||||||
|
// not using getVelocityHelper here to avoid locking and other checks
|
||||||
|
const auto v = device->midiInfo->controls_single[vKey];
|
||||||
|
state = (current_button->getVelocityThreshold() < v) ?
|
||||||
|
BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
state = BUTTON_NOT_PRESSED;
|
state = BUTTON_NOT_PRESSED;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BAT_MIDI_CTRL_ONOFF: {
|
case BAT_MIDI_CTRL_ONOFF: {
|
||||||
if (vKey < 16 * 6)
|
if (vKey < midi->controls_onoff.size()) {
|
||||||
|
if (rawinput::get_midi_algorithm() == rawinput::MidiNoteAlgorithm::LEGACY) {
|
||||||
state = midi->controls_onoff[vKey] ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
state = midi->controls_onoff[vKey] ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
||||||
else
|
} else {
|
||||||
|
state = getMidiV2ButtonState(
|
||||||
|
midi->v2_controls_onoff_last_on_time[vKey],
|
||||||
|
midi->v2_controls_onoff_last_off_time[vKey]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
state = BUTTON_NOT_PRESSED;
|
state = BUTTON_NOT_PRESSED;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BAT_MIDI_PITCH_DOWN:
|
case BAT_MIDI_PITCH_DOWN:
|
||||||
state = midi->pitch_bend < 0x2000 ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
if (vKey < midi->pitch_bend.size()) {
|
||||||
|
state = midi->pitch_bend[vKey] < 0 ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
||||||
|
} else {
|
||||||
|
state = BUTTON_NOT_PRESSED;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case BAT_MIDI_PITCH_UP:
|
case BAT_MIDI_PITCH_UP:
|
||||||
state = midi->pitch_bend > 0x2000 ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
if (vKey < midi->pitch_bend.size()) {
|
||||||
|
state = midi->pitch_bend[vKey] > 0 ? BUTTON_PRESSED : BUTTON_NOT_PRESSED;
|
||||||
|
} else {
|
||||||
|
state = BUTTON_NOT_PRESSED;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
state = BUTTON_NOT_PRESSED;
|
state = BUTTON_NOT_PRESSED;
|
||||||
@@ -372,24 +462,64 @@ static float getVelocityHelper(rawinput::RawInputManager *manager, Button &butto
|
|||||||
device->mutex->lock();
|
device->mutex->lock();
|
||||||
|
|
||||||
// determine velocity based on device type
|
// determine velocity based on device type
|
||||||
switch (device->type) {
|
if (device->type == rawinput::MIDI) {
|
||||||
case rawinput::MIDI: {
|
switch (button.getAnalogType()) {
|
||||||
|
case ButtonAnalogType::BAT_MIDI_CTRL_PRECISION:
|
||||||
|
if (vKey < device->midiInfo->controls_precision.size()) {
|
||||||
|
velocity = device->midiInfo->controls_precision[vKey] / 16383.f;
|
||||||
|
} else {
|
||||||
|
velocity = 0.f;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
// read control
|
case ButtonAnalogType::BAT_MIDI_CTRL_SINGLE:
|
||||||
if (vKey < 16 * 128) {
|
if (vKey < device->midiInfo->controls_single.size()) {
|
||||||
|
velocity = device->midiInfo->controls_single[vKey] / 127.f;
|
||||||
|
} else {
|
||||||
|
velocity = 0.f;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ButtonAnalogType::BAT_MIDI_CTRL_ONOFF:
|
||||||
|
if (vKey < device->midiInfo->controls_onoff.size()) {
|
||||||
|
velocity = device->midiInfo->controls_onoff[vKey] ? 1.f : 0.f;
|
||||||
|
} else {
|
||||||
|
velocity = 0.f;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ButtonAnalogType::BAT_MIDI_PITCH_DOWN:
|
||||||
|
if (vKey < device->midiInfo->pitch_bend.size()) {
|
||||||
|
velocity = device->midiInfo->pitch_bend[vKey] < 0 ? 1.f : 0.f;
|
||||||
|
} else {
|
||||||
|
velocity = 0.f;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ButtonAnalogType::BAT_MIDI_PITCH_UP:
|
||||||
|
if (vKey < device->midiInfo->pitch_bend.size()) {
|
||||||
|
// pitch range is [-8192, 8191]
|
||||||
|
velocity = (device->midiInfo->pitch_bend[vKey]) > 0 ? 1.f : 0.f;
|
||||||
|
} else {
|
||||||
|
velocity = 0.f;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ButtonAnalogType::BAT_NONE:
|
||||||
|
default:
|
||||||
|
// velocity sensitive
|
||||||
|
if (vKey < device->midiInfo->velocity.size()) {
|
||||||
velocity = (float) device->midiInfo->velocity[vKey] / 127.f;
|
velocity = (float) device->midiInfo->velocity[vKey] / 127.f;
|
||||||
} else {
|
} else {
|
||||||
velocity = 0.f;
|
velocity = 0.f;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// invert
|
// invert
|
||||||
if (button.getInvert()) {
|
if (button.getInvert()) {
|
||||||
velocity = 1.f - velocity;
|
velocity = 1.f - velocity;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// unlock device
|
// unlock device
|
||||||
@@ -490,6 +620,36 @@ float GameAPI::Analogs::getState(rawinput::Device *device, Analog &analog) {
|
|||||||
value = device->hidInfo->value_states[index];
|
value = device->hidInfo->value_states[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// deadzone
|
||||||
|
if (analog.isDeadzoneSet()) {
|
||||||
|
value = analog.applyDeadzone(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (analog.isRelativeMode()) {
|
||||||
|
float relative_delta = value - 0.5f;
|
||||||
|
// built-in scaling to make values reasonable
|
||||||
|
relative_delta /= 80.f;
|
||||||
|
|
||||||
|
// integer multiplier/divisor
|
||||||
|
const auto mult = analog.getMultiplier();
|
||||||
|
if (mult < -1) {
|
||||||
|
relative_delta /= -mult;
|
||||||
|
} else if (1 < mult) {
|
||||||
|
relative_delta *= mult;
|
||||||
|
}
|
||||||
|
|
||||||
|
// sensitivity (ranges from 0.0 to 4.0)
|
||||||
|
if (analog.isSensitivitySet()) {
|
||||||
|
relative_delta *= analog.getSensitivity();
|
||||||
|
}
|
||||||
|
|
||||||
|
// translate relative movement to absolute value
|
||||||
|
value = analog.getAbsoluteValue(relative_delta);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// integer multiplier
|
||||||
|
value = analog.applyMultiplier(value);
|
||||||
|
|
||||||
// smoothing/sensitivity
|
// smoothing/sensitivity
|
||||||
if (analog.getSmoothing() || analog.isSensitivitySet()) {
|
if (analog.getSmoothing() || analog.isSensitivitySet()) {
|
||||||
float rads = value * (float) M_TAU;
|
float rads = value * (float) M_TAU;
|
||||||
@@ -514,6 +674,29 @@ float GameAPI::Analogs::getState(rawinput::Device *device, Analog &analog) {
|
|||||||
// apply to value
|
// apply to value
|
||||||
value = rads * (float) M_1_TAU;
|
value = rads * (float) M_1_TAU;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// delay
|
||||||
|
if (0 < analog.getDelayBufferDepth()) {
|
||||||
|
auto& queue = analog.getDelayBuffer();
|
||||||
|
|
||||||
|
// ensure the queue isn't too long; drop old values
|
||||||
|
while (analog.getDelayBufferDepth() <= (int)queue.size()) {
|
||||||
|
queue.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// always push new value
|
||||||
|
queue.push(value);
|
||||||
|
|
||||||
|
// get a new value to return
|
||||||
|
if ((int)queue.size() < analog.getDelayBufferDepth()) {
|
||||||
|
// not enough in the queue, stall for now, shouldn't happen often
|
||||||
|
value = analog.getLastState();
|
||||||
|
} else {
|
||||||
|
value = queue.front();
|
||||||
|
queue.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -524,6 +707,7 @@ float GameAPI::Analogs::getState(rawinput::Device *device, Analog &analog) {
|
|||||||
auto prec_count = (int) midi->controls_precision.size();
|
auto prec_count = (int) midi->controls_precision.size();
|
||||||
auto single_count = (int) midi->controls_single.size();
|
auto single_count = (int) midi->controls_single.size();
|
||||||
auto onoff_count = (int) midi->controls_onoff.size();
|
auto onoff_count = (int) midi->controls_onoff.size();
|
||||||
|
auto pitch_count = (int) midi->pitch_bend.size();
|
||||||
|
|
||||||
// decide on value
|
// decide on value
|
||||||
if (index < prec_count)
|
if (index < prec_count)
|
||||||
@@ -532,81 +716,19 @@ float GameAPI::Analogs::getState(rawinput::Device *device, Analog &analog) {
|
|||||||
value = midi->controls_single[index - prec_count] / 127.f;
|
value = midi->controls_single[index - prec_count] / 127.f;
|
||||||
else if (index < prec_count + single_count + onoff_count)
|
else if (index < prec_count + single_count + onoff_count)
|
||||||
value = midi->controls_onoff[index - prec_count - single_count] ? 1.f : 0.f;
|
value = midi->controls_onoff[index - prec_count - single_count] ? 1.f : 0.f;
|
||||||
else if (index == prec_count + single_count + onoff_count)
|
else if (index < prec_count + single_count + onoff_count + pitch_count)
|
||||||
value = midi->pitch_bend / 16383.f;
|
value = (midi->pitch_bend[index - prec_count - single_count - onoff_count] + 0x2000) / 16383.f;
|
||||||
|
|
||||||
// invert value
|
// invert value
|
||||||
if (inverted) {
|
if (inverted) {
|
||||||
value = 1.f - value;
|
value = 1.f - value;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// deadzone logic
|
// deadzone
|
||||||
switch (device->type) {
|
|
||||||
case rawinput::HID:
|
|
||||||
case rawinput::MIDI: {
|
|
||||||
|
|
||||||
// check if set
|
|
||||||
if (analog.isDeadzoneSet()) {
|
if (analog.isDeadzoneSet()) {
|
||||||
|
value = analog.applyDeadzone(value);
|
||||||
// check sign
|
|
||||||
auto deadzone = analog.getDeadzone();
|
|
||||||
if (deadzone > 0) {
|
|
||||||
|
|
||||||
// calculate values
|
|
||||||
auto delta = value - 0.5f;
|
|
||||||
auto dtlen = 1.f - deadzone;
|
|
||||||
|
|
||||||
// check mirror
|
|
||||||
if (analog.getDeadzoneMirror()) {
|
|
||||||
|
|
||||||
// deadzone on the edges
|
|
||||||
if (dtlen != 0.f) {
|
|
||||||
value = std::max(0.f, std::min(1.f, 0.5f + (delta / dtlen)));
|
|
||||||
} else {
|
|
||||||
value = 0.5f;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// deadzone around the middle
|
|
||||||
auto limit = deadzone * 0.5f;
|
|
||||||
if (dtlen != 0.f) {
|
|
||||||
if (delta > limit) {
|
|
||||||
value = std::min(1.f, 0.5f + std::max(0.f, (delta - limit) / dtlen));
|
|
||||||
} else if (delta < -limit) {
|
|
||||||
value = std::max(0.f, 0.5f + std::min(0.f, (delta + limit) / dtlen));
|
|
||||||
} else {
|
|
||||||
value = 0.5f;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
value = 0.5f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (deadzone < 0) {
|
|
||||||
|
|
||||||
// invert for mirror
|
|
||||||
if (analog.getDeadzoneMirror()) {
|
|
||||||
value = 1.f - value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// deadzone from minimum value
|
|
||||||
if (deadzone > -1 && value > -deadzone) {
|
|
||||||
value = std::min(1.f, (value + deadzone) / (1.f + deadzone));
|
|
||||||
} else {
|
|
||||||
value = 0.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
// revert value for mirror
|
|
||||||
if (analog.getDeadzoneMirror()) {
|
|
||||||
value = 1.f - value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -761,6 +883,7 @@ void GameAPI::Lights::writeLight(rawinput::Device *device, int index, float valu
|
|||||||
if (index < rawinput::SextetDevice::LIGHT_COUNT) {
|
if (index < rawinput::SextetDevice::LIGHT_COUNT) {
|
||||||
device->sextetInfo->light_state[index] = value > 0;
|
device->sextetInfo->light_state[index] = value > 0;
|
||||||
device->sextetInfo->push_light_state();
|
device->sextetInfo->push_light_state();
|
||||||
|
device->output_pending = true;
|
||||||
} else {
|
} else {
|
||||||
log_warning("api", "invalid sextet light index: {}", index);
|
log_warning("api", "invalid sextet light index: {}", index);
|
||||||
}
|
}
|
||||||
@@ -769,11 +892,30 @@ void GameAPI::Lights::writeLight(rawinput::Device *device, int index, float valu
|
|||||||
case rawinput::PIUIO_DEVICE: {
|
case rawinput::PIUIO_DEVICE: {
|
||||||
if (index < rawinput::PIUIO::PIUIO_MAX_NUM_OF_LIGHTS) {
|
if (index < rawinput::PIUIO::PIUIO_MAX_NUM_OF_LIGHTS) {
|
||||||
device->piuioDev->SetLight(index, value > 0);
|
device->piuioDev->SetLight(index, value > 0);
|
||||||
|
device->output_pending = true;
|
||||||
} else {
|
} else {
|
||||||
log_warning("api", "invalid piuio light index: {}", index);
|
log_warning("api", "invalid piuio light index: {}", index);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case rawinput::SMX_STAGE: {
|
||||||
|
if (index < rawinput::SmxStageDevice::TOTAL_LIGHT_COUNT) {
|
||||||
|
device->smxstageInfo->SetLightByIndex(index, static_cast<uint8_t>(value*255.f));
|
||||||
|
device->output_pending = true;
|
||||||
|
} else {
|
||||||
|
log_warning("api", "invalid smx stage light index: {}", index);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case rawinput::SMX_DEDICAB: {
|
||||||
|
if (index < rawinput::SmxDedicabDevice::LIGHTS_COUNT) {
|
||||||
|
device->smxdedicabInfo->SetLightByIndex(index, static_cast<uint8_t>(value * 255.f));
|
||||||
|
device->output_pending = true;
|
||||||
|
} else {
|
||||||
|
log_warning("api", "invalid SMX dedicab light index: {}", index);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -922,3 +1064,27 @@ void GameAPI::Options::sortOptions(std::vector<Option> &options, const std::vect
|
|||||||
|
|
||||||
options = std::move(sorted);
|
options = std::move(sorted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Buttons::State getMidiV2ButtonState(float on, float off) {
|
||||||
|
if (on == 0.0) {
|
||||||
|
return Buttons::State::BUTTON_NOT_PRESSED;
|
||||||
|
} else if (off < on) {
|
||||||
|
// if OFF was not observed strictly after ON, we can confidently say that the note
|
||||||
|
// remains ON; in case of a tie (rarely in v2, all the time in v2_drum), prefer to keep note
|
||||||
|
// off since that's better than a note stuck on
|
||||||
|
return Buttons::State::BUTTON_PRESSED;
|
||||||
|
} else {
|
||||||
|
// otherwise, this is an ON-OFF sequence
|
||||||
|
// check for time the most recent ON message
|
||||||
|
//
|
||||||
|
// if recent, consider the button to be on - even if there were OFF messages following it
|
||||||
|
// this is needed to detect things like MIDI drums which send a quick ON-OFF sequence
|
||||||
|
// between the game's polling period
|
||||||
|
const auto now = get_performance_milliseconds();
|
||||||
|
if ((now - on) < (double)rawinput::MIDI_NOTE_SUSTAIN) {
|
||||||
|
return Buttons::State::BUTTON_PRESSED;
|
||||||
|
} else {
|
||||||
|
return Buttons::State::BUTTON_NOT_PRESSED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+151
-13
@@ -22,6 +22,7 @@ const char *ButtonAnalogTypeStr[] = {
|
|||||||
"MIDI Control On/Off",
|
"MIDI Control On/Off",
|
||||||
"MIDI Pitch Down",
|
"MIDI Pitch Down",
|
||||||
"MIDI Pitch Up",
|
"MIDI Pitch Up",
|
||||||
|
"Any Direction",
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string Button::getVKeyString() {
|
std::string Button::getVKeyString() {
|
||||||
@@ -267,6 +268,15 @@ std::string Button::getVKeyString() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Button::getMidiNoteString() {
|
||||||
|
static const std::string note_names[] = {"C","C#","D","D#","E","F","F#","G","G#","A","A#","B"};
|
||||||
|
|
||||||
|
int channel;
|
||||||
|
int index;
|
||||||
|
this->getMidiVKey(channel, index);
|
||||||
|
return fmt::format("{}{}", note_names[index % 12], ((index / 12) - 1));
|
||||||
|
}
|
||||||
|
|
||||||
std::string Button::getDisplayString(rawinput::RawInputManager* manager) {
|
std::string Button::getDisplayString(rawinput::RawInputManager* manager) {
|
||||||
|
|
||||||
// get VKey string
|
// get VKey string
|
||||||
@@ -317,8 +327,16 @@ std::string Button::getDisplayString(rawinput::RawInputManager* manager) {
|
|||||||
else
|
else
|
||||||
return "Invalid button (" + device->desc + ")";
|
return "Invalid button (" + device->desc + ")";
|
||||||
case BAT_NEGATIVE:
|
case BAT_NEGATIVE:
|
||||||
case BAT_POSITIVE: {
|
case BAT_POSITIVE:
|
||||||
const char *sign = this->analog_type == BAT_NEGATIVE ? "-" : "+";
|
case BAT_ANY: {
|
||||||
|
const char *sign;
|
||||||
|
if (this->analog_type == BAT_NEGATIVE) {
|
||||||
|
sign = "-";
|
||||||
|
} else if (this->analog_type == BAT_POSITIVE) {
|
||||||
|
sign = "+";
|
||||||
|
} else {
|
||||||
|
sign = "*";
|
||||||
|
}
|
||||||
if (vKey < hid->value_caps_names.size()) {
|
if (vKey < hid->value_caps_names.size()) {
|
||||||
return hid->value_caps_names[vKey] + sign + " (" + device->desc + ")";
|
return hid->value_caps_names[vKey] + sign + " (" + device->desc + ")";
|
||||||
} else {
|
} else {
|
||||||
@@ -347,23 +365,34 @@ std::string Button::getDisplayString(rawinput::RawInputManager* manager) {
|
|||||||
return "Unknown analog type (" + device->desc + ")";
|
return "Unknown analog type (" + device->desc + ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case rawinput::MIDI:
|
case rawinput::MIDI: {
|
||||||
|
int channel = 0;
|
||||||
|
int ctrl = 0;
|
||||||
|
this->getMidiVKey(channel, ctrl);
|
||||||
switch (this->analog_type) {
|
switch (this->analog_type) {
|
||||||
case BAT_NONE:
|
// update strings in analog.cpp as well
|
||||||
return "MIDI " + vKeyString + " (" + device->desc + ")";
|
case BAT_NONE: {
|
||||||
case BAT_MIDI_CTRL_PRECISION:
|
const auto note = this->getMidiNoteString();
|
||||||
return "MIDI PREC " + vKeyString + " (" + device->desc + ")";
|
return fmt::format("MIDI Note Ch.{} #{} {} ({})", channel, ctrl, note, device->desc);
|
||||||
case BAT_MIDI_CTRL_SINGLE:
|
}
|
||||||
return "MIDI CTRL " + vKeyString + " (" + device->desc + ")";
|
case BAT_MIDI_CTRL_PRECISION: {
|
||||||
case BAT_MIDI_CTRL_ONOFF:
|
return fmt::format("MIDI Prec Ctrl Ch.{} CC#{} ({})", channel, ctrl, device->desc);
|
||||||
return "MIDI ONOFF " + vKeyString + " (" + device->desc + ")";
|
}
|
||||||
|
case BAT_MIDI_CTRL_SINGLE: {
|
||||||
|
return fmt::format("MIDI Ctrl Ch.{} CC#{} ({})", channel, ctrl, device->desc);
|
||||||
|
}
|
||||||
|
case BAT_MIDI_CTRL_ONOFF: {
|
||||||
|
return fmt::format("MIDI OnOff Ch.{} CC#{} ({})", channel, ctrl, device->desc);
|
||||||
|
}
|
||||||
case BAT_MIDI_PITCH_DOWN:
|
case BAT_MIDI_PITCH_DOWN:
|
||||||
return "MIDI Pitch Down (" + device->desc + ")";
|
return fmt::format("MIDI Pitch Down Ch.{} ({})", channel, device->desc);
|
||||||
case BAT_MIDI_PITCH_UP:
|
case BAT_MIDI_PITCH_UP:
|
||||||
return "MIDI Pitch Up (" + device->desc + ")";
|
return fmt::format("MIDI Pitch Up Ch.{} ({})", channel, device->desc);
|
||||||
default:
|
default:
|
||||||
return "MIDI Unknown " + vKeyString + " (" + device->desc + ")";
|
return "MIDI Unknown " + vKeyString + " (" + device->desc + ")";
|
||||||
}
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
case rawinput::PIUIO_DEVICE:
|
case rawinput::PIUIO_DEVICE:
|
||||||
return "PIUIO " + vKeyString;
|
return "PIUIO " + vKeyString;
|
||||||
case rawinput::DESTROYED:
|
case rawinput::DESTROYED:
|
||||||
@@ -374,6 +403,115 @@ std::string Button::getDisplayString(rawinput::RawInputManager* manager) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Button::getMidiVKey(int& channel, int& index) {
|
||||||
|
switch (this->analog_type) {
|
||||||
|
// update strings in analog.cpp as well
|
||||||
|
case BAT_NONE:
|
||||||
|
channel = (vKey / 0x80) + 1;
|
||||||
|
index = vKey & 0x7f;
|
||||||
|
break;
|
||||||
|
case BAT_MIDI_CTRL_PRECISION:
|
||||||
|
channel = (vKey / 32) + 1;
|
||||||
|
index = (vKey % 32);
|
||||||
|
break;
|
||||||
|
case BAT_MIDI_CTRL_SINGLE:
|
||||||
|
channel = (vKey / 44) + 1;
|
||||||
|
index = (vKey % 44);
|
||||||
|
if (index <= 25) {
|
||||||
|
index += 0x46; // single byte range
|
||||||
|
} else {
|
||||||
|
index = index - 26 + 0x66; // undefined single byte range
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BAT_MIDI_CTRL_ONOFF:
|
||||||
|
channel = (vKey / 6) + 1;
|
||||||
|
index = (vKey % 6) + 0x40;
|
||||||
|
break;
|
||||||
|
case BAT_MIDI_PITCH_DOWN:
|
||||||
|
case BAT_MIDI_PITCH_UP:
|
||||||
|
channel = vKey + 1;
|
||||||
|
index = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
channel = 0;
|
||||||
|
index = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Button::setMidiVKey(rawinput::RawInputManager* manager, bool is_note, int channel, int index) {
|
||||||
|
int vKey = 0;
|
||||||
|
if (is_note) {
|
||||||
|
vKey = (channel - 1) * 0x80 + index;
|
||||||
|
this->setVKey(vKey);
|
||||||
|
this->setAnalogType(BAT_NONE);
|
||||||
|
|
||||||
|
// ensure that velocity threshold is read back from what rawinput has for other bindings
|
||||||
|
if (manager && !this->device_identifier.empty()) {
|
||||||
|
auto device = manager->devices_get(this->device_identifier);
|
||||||
|
if (device &&
|
||||||
|
device->midiInfo &&
|
||||||
|
(size_t)vKey < device->midiInfo->v2_velocity_threshold.size()) {
|
||||||
|
this->setVelocityThreshold(device->midiInfo->v2_velocity_threshold[vKey]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channel < 1 || 16 < channel) {
|
||||||
|
this->setVKey(0);
|
||||||
|
this->setAnalogType(BAT_NONE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (index < 0 || 127 < index) {
|
||||||
|
this->setVKey(0);
|
||||||
|
this->setAnalogType(BAT_NONE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// continuous controller MSB
|
||||||
|
if (0x00 <= index && index <= 0x1F) {
|
||||||
|
vKey = (channel - 1) * 32 + index;
|
||||||
|
this->setVKey(vKey);
|
||||||
|
this->setAnalogType(BAT_MIDI_CTRL_PRECISION);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// continuous controller LSB
|
||||||
|
if (0x20 <= index && index <= 0x3F) {
|
||||||
|
vKey = (channel - 1) * 32 + index - 0x20;
|
||||||
|
this->setVKey(vKey);
|
||||||
|
this->setAnalogType(BAT_MIDI_CTRL_PRECISION);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// on/off controls
|
||||||
|
if (0x40 <= index && index <= 0x45) {
|
||||||
|
vKey = (channel - 1) * 6 + (index - 0x40);
|
||||||
|
this->setVKey(vKey);
|
||||||
|
this->setAnalogType(BAT_MIDI_CTRL_ONOFF);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// single byte controllers
|
||||||
|
if (0x46 <= index && index <= 0x5F) {
|
||||||
|
vKey = (channel - 1) * 44;
|
||||||
|
vKey += index - 0x46; // single byte range
|
||||||
|
this->setVKey(vKey);
|
||||||
|
this->setAnalogType(BAT_MIDI_CTRL_SINGLE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// undefined single byte controllers
|
||||||
|
if (0x66 <= index && index <= 0x77) {
|
||||||
|
vKey = (channel - 1) * 44;
|
||||||
|
vKey += index - 0x66 + (0x5F - 0x46 + 1) ; // undefined single byte range
|
||||||
|
this->setVKey(vKey);
|
||||||
|
this->setAnalogType(BAT_MIDI_CTRL_SINGLE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define HAT_SWITCH_INCREMENT (1.f / 7)
|
#define HAT_SWITCH_INCREMENT (1.f / 7)
|
||||||
|
|
||||||
void Button::getHatSwitchValues(float analog_state, ButtonAnalogType* buffer) {
|
void Button::getHatSwitchValues(float analog_state, ButtonAnalogType* buffer) {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ enum ButtonAnalogType {
|
|||||||
BAT_MIDI_CTRL_ONOFF = 14,
|
BAT_MIDI_CTRL_ONOFF = 14,
|
||||||
BAT_MIDI_PITCH_DOWN = 15,
|
BAT_MIDI_PITCH_DOWN = 15,
|
||||||
BAT_MIDI_PITCH_UP = 16,
|
BAT_MIDI_PITCH_UP = 16,
|
||||||
|
BAT_ANY = 17,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const char *ButtonAnalogTypeStr[];
|
extern const char *ButtonAnalogTypeStr[];
|
||||||
@@ -45,8 +46,10 @@ private:
|
|||||||
|
|
||||||
GameAPI::Buttons::State last_state = GameAPI::Buttons::BUTTON_NOT_PRESSED;
|
GameAPI::Buttons::State last_state = GameAPI::Buttons::BUTTON_NOT_PRESSED;
|
||||||
float last_velocity = 0.f;
|
float last_velocity = 0.f;
|
||||||
|
unsigned short velocity_threshold = 0;
|
||||||
|
|
||||||
std::string getVKeyString();
|
std::string getVKeyString();
|
||||||
|
std::string getMidiNoteString();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -159,6 +162,17 @@ public:
|
|||||||
this->last_velocity = last_velocity;
|
this->last_velocity = last_velocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline unsigned short getVelocityThreshold() const {
|
||||||
|
return this->velocity_threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setVelocityThreshold(unsigned short velocity_threshold) {
|
||||||
|
this->velocity_threshold = velocity_threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
void getMidiVKey(int& channel, int& index);
|
||||||
|
void setMidiVKey(rawinput::RawInputManager* manager, bool is_note, int channel, int index);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Map hat switch float value from [0-1] to directions.
|
* Map hat switch float value from [0-1] to directions.
|
||||||
* Buffer must be sized 3 or bigger.
|
* Buffer must be sized 3 or bigger.
|
||||||
|
|||||||
+106
-13
@@ -19,10 +19,16 @@ Config::Config() {
|
|||||||
this->status = false;
|
this->status = false;
|
||||||
if (CONFIG_PATH_OVERRIDE.length() > 0) {
|
if (CONFIG_PATH_OVERRIDE.length() > 0) {
|
||||||
this->configLocation = CONFIG_PATH_OVERRIDE;
|
this->configLocation = CONFIG_PATH_OVERRIDE;
|
||||||
|
log_info("cfg", "using custom config file: {}", this->configLocation.string());
|
||||||
} else {
|
} else {
|
||||||
this->configLocation = std::string(getenv("APPDATA")) + "\\spicetools.xml";
|
this->configLocation = std::filesystem::path(_wgetenv(L"APPDATA")) / L"spicetools.xml";
|
||||||
|
// avoids logging the expanded appdata path as it contains user name
|
||||||
|
log_info("cfg", "using global config file: %appdata%\\spicetools.xml");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->configLocationTemp = this->configLocation;
|
||||||
|
this->configLocationTemp.replace_extension(L"tmp");
|
||||||
|
|
||||||
tinyxml2::XMLError configLoadError, *previousConfigLoadError = nullptr;
|
tinyxml2::XMLError configLoadError, *previousConfigLoadError = nullptr;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@@ -42,7 +48,7 @@ Config::Config() {
|
|||||||
this->firstFillConfigFile();
|
this->firstFillConfigFile();
|
||||||
break;
|
break;
|
||||||
case tinyxml2::XMLError::XML_ERROR_FILE_COULD_NOT_BE_OPENED:
|
case tinyxml2::XMLError::XML_ERROR_FILE_COULD_NOT_BE_OPENED:
|
||||||
log_fatal("cfg", "could not open config file: {}", this->configLocation);
|
log_fatal("cfg", "could not open config file: {}", this->configLocation.string());
|
||||||
break;
|
break;
|
||||||
case tinyxml2::XMLError::XML_ERROR_FILE_NOT_FOUND:
|
case tinyxml2::XMLError::XML_ERROR_FILE_NOT_FOUND:
|
||||||
this->createConfigFile();
|
this->createConfigFile();
|
||||||
@@ -57,7 +63,7 @@ Config::Config() {
|
|||||||
case tinyxml2::XMLError::XML_ERROR_PARSING_UNKNOWN:
|
case tinyxml2::XMLError::XML_ERROR_PARSING_UNKNOWN:
|
||||||
case tinyxml2::XMLError::XML_ERROR_MISMATCHED_ELEMENT:
|
case tinyxml2::XMLError::XML_ERROR_MISMATCHED_ELEMENT:
|
||||||
case tinyxml2::XMLError::XML_ERROR_PARSING:
|
case tinyxml2::XMLError::XML_ERROR_PARSING:
|
||||||
log_warning("cfg", "Couldn't read config file: {}", this->configLocation);
|
log_warning("cfg", "Couldn't read config file: {}", this->configLocation.string());
|
||||||
this->createConfigFile();
|
this->createConfigFile();
|
||||||
this->firstFillConfigFile();
|
this->firstFillConfigFile();
|
||||||
break;
|
break;
|
||||||
@@ -147,12 +153,14 @@ bool Config::addGame(Game &game) {
|
|||||||
auto analogType = (int) BAT_NONE;
|
auto analogType = (int) BAT_NONE;
|
||||||
double debounce_up = 0.0;
|
double debounce_up = 0.0;
|
||||||
double debounce_down = 0.0;
|
double debounce_down = 0.0;
|
||||||
|
int velocity_threshold = 0;
|
||||||
bool invert = false;
|
bool invert = false;
|
||||||
tinyxml2::XMLError attrError = gameButtonNode->QueryIntAttribute("vkey", &vKey);
|
tinyxml2::XMLError attrError = gameButtonNode->QueryIntAttribute("vkey", &vKey);
|
||||||
const char *devid = gameButtonNode->Attribute("devid");
|
const char *devid = gameButtonNode->Attribute("devid");
|
||||||
gameButtonNode->QueryIntAttribute("analogtype", &analogType);
|
gameButtonNode->QueryIntAttribute("analogtype", &analogType);
|
||||||
gameButtonNode->QueryDoubleAttribute("debounce_up", &debounce_up);
|
gameButtonNode->QueryDoubleAttribute("debounce_up", &debounce_up);
|
||||||
gameButtonNode->QueryDoubleAttribute("debounce_down", &debounce_down);
|
gameButtonNode->QueryDoubleAttribute("debounce_down", &debounce_down);
|
||||||
|
gameButtonNode->QueryIntAttribute("velocity_threshold", &velocity_threshold);
|
||||||
gameButtonNode->QueryBoolAttribute("invert", &invert);
|
gameButtonNode->QueryBoolAttribute("invert", &invert);
|
||||||
if (attrError != tinyxml2::XMLError::XML_SUCCESS) {
|
if (attrError != tinyxml2::XMLError::XML_SUCCESS) {
|
||||||
gameButtonsNode->DeleteChild(gameButtonNode);
|
gameButtonsNode->DeleteChild(gameButtonNode);
|
||||||
@@ -163,6 +171,7 @@ bool Config::addGame(Game &game) {
|
|||||||
gameButtonNode->SetAttribute("devid", button->getDeviceIdentifier().c_str());
|
gameButtonNode->SetAttribute("devid", button->getDeviceIdentifier().c_str());
|
||||||
gameButtonNode->SetAttribute("debounce_up", debounce_up);
|
gameButtonNode->SetAttribute("debounce_up", debounce_up);
|
||||||
gameButtonNode->SetAttribute("debounce_down", debounce_down);
|
gameButtonNode->SetAttribute("debounce_down", debounce_down);
|
||||||
|
gameButtonNode->SetAttribute("velocity_threshold", velocity_threshold);
|
||||||
gameButtonNode->SetAttribute("invert", invert);
|
gameButtonNode->SetAttribute("invert", invert);
|
||||||
gameButtonsNode->InsertEndChild(gameButtonNode);
|
gameButtonsNode->InsertEndChild(gameButtonNode);
|
||||||
} else {
|
} else {
|
||||||
@@ -170,6 +179,7 @@ bool Config::addGame(Game &game) {
|
|||||||
button->setAnalogType((ButtonAnalogType) analogType);
|
button->setAnalogType((ButtonAnalogType) analogType);
|
||||||
button->setDebounceUp(debounce_up);
|
button->setDebounceUp(debounce_up);
|
||||||
button->setDebounceDown(debounce_down);
|
button->setDebounceDown(debounce_down);
|
||||||
|
button->setVelocityThreshold(velocity_threshold);
|
||||||
button->setInvert(invert);
|
button->setInvert(invert);
|
||||||
if (devid) {
|
if (devid) {
|
||||||
button->setDeviceIdentifier(devid);
|
button->setDeviceIdentifier(devid);
|
||||||
@@ -188,6 +198,7 @@ bool Config::addGame(Game &game) {
|
|||||||
gameButtonNode->SetAttribute("analogtype", (int) it.getAnalogType());
|
gameButtonNode->SetAttribute("analogtype", (int) it.getAnalogType());
|
||||||
gameButtonNode->SetAttribute("debounce_up", it.getDebounceUp());
|
gameButtonNode->SetAttribute("debounce_up", it.getDebounceUp());
|
||||||
gameButtonNode->SetAttribute("debounce_down", it.getDebounceDown());
|
gameButtonNode->SetAttribute("debounce_down", it.getDebounceDown());
|
||||||
|
gameButtonNode->SetAttribute("velocity_threshold", it.getVelocityThreshold());
|
||||||
gameButtonNode->SetAttribute("invert", it.getInvert());
|
gameButtonNode->SetAttribute("invert", it.getInvert());
|
||||||
gameButtonNode->SetAttribute("devid", it.getDeviceIdentifier().c_str());
|
gameButtonNode->SetAttribute("devid", it.getDeviceIdentifier().c_str());
|
||||||
gameButtonsNode->InsertEndChild(gameButtonNode);
|
gameButtonsNode->InsertEndChild(gameButtonNode);
|
||||||
@@ -226,12 +237,18 @@ bool Config::addGame(Game &game) {
|
|||||||
bool deadzone_mirror = false;
|
bool deadzone_mirror = false;
|
||||||
bool invert = false;
|
bool invert = false;
|
||||||
bool smoothing = false;
|
bool smoothing = false;
|
||||||
|
int multiplier = 1;
|
||||||
|
bool relative_mode = false;
|
||||||
|
int delay_buffer_depth = 0;
|
||||||
tinyxml2::XMLError err1 = gameAnalogNode->QueryIntAttribute("index", &index);
|
tinyxml2::XMLError err1 = gameAnalogNode->QueryIntAttribute("index", &index);
|
||||||
gameAnalogNode->QueryFloatAttribute("sensivity", &sensitivity);
|
gameAnalogNode->QueryFloatAttribute("sensivity", &sensitivity);
|
||||||
gameAnalogNode->QueryFloatAttribute("deadzone", &deadzone);
|
gameAnalogNode->QueryFloatAttribute("deadzone", &deadzone);
|
||||||
gameAnalogNode->QueryBoolAttribute("deadzone_mirror", &deadzone_mirror);
|
gameAnalogNode->QueryBoolAttribute("deadzone_mirror", &deadzone_mirror);
|
||||||
gameAnalogNode->QueryBoolAttribute("invert", &invert);
|
gameAnalogNode->QueryBoolAttribute("invert", &invert);
|
||||||
gameAnalogNode->QueryBoolAttribute("smoothing", &smoothing);
|
gameAnalogNode->QueryBoolAttribute("smoothing", &smoothing);
|
||||||
|
gameAnalogNode->QueryIntAttribute("multiplier", &multiplier);
|
||||||
|
gameAnalogNode->QueryBoolAttribute("relative", &relative_mode);
|
||||||
|
gameAnalogNode->QueryIntAttribute("delay", &delay_buffer_depth);
|
||||||
const char *devid = gameAnalogNode->Attribute("devid");
|
const char *devid = gameAnalogNode->Attribute("devid");
|
||||||
|
|
||||||
if (err1 != tinyxml2::XMLError::XML_SUCCESS || !devid) {
|
if (err1 != tinyxml2::XMLError::XML_SUCCESS || !devid) {
|
||||||
@@ -245,6 +262,9 @@ bool Config::addGame(Game &game) {
|
|||||||
gameAnalogNode->SetAttribute("deadzone_mirror", it.getDeadzoneMirror());
|
gameAnalogNode->SetAttribute("deadzone_mirror", it.getDeadzoneMirror());
|
||||||
gameAnalogNode->SetAttribute("invert", it.getInvert());
|
gameAnalogNode->SetAttribute("invert", it.getInvert());
|
||||||
gameAnalogNode->SetAttribute("smoothing", it.getSmoothing());
|
gameAnalogNode->SetAttribute("smoothing", it.getSmoothing());
|
||||||
|
gameAnalogNode->SetAttribute("multiplier", it.getMultiplier());
|
||||||
|
gameAnalogNode->SetAttribute("relative", it.isRelativeMode());
|
||||||
|
gameAnalogNode->SetAttribute("delay", it.getDelayBufferDepth());
|
||||||
gameAnalogsNode->InsertEndChild(gameAnalogNode);
|
gameAnalogsNode->InsertEndChild(gameAnalogNode);
|
||||||
} else {
|
} else {
|
||||||
it.setIndex(static_cast<unsigned short int>(index));
|
it.setIndex(static_cast<unsigned short int>(index));
|
||||||
@@ -254,6 +274,9 @@ bool Config::addGame(Game &game) {
|
|||||||
it.setDeadzoneMirror(deadzone_mirror);
|
it.setDeadzoneMirror(deadzone_mirror);
|
||||||
it.setInvert(invert);
|
it.setInvert(invert);
|
||||||
it.setSmoothing(smoothing);
|
it.setSmoothing(smoothing);
|
||||||
|
it.setMultiplier(multiplier);
|
||||||
|
it.setRelativeMode(relative_mode);
|
||||||
|
it.setDelayBufferDepth(delay_buffer_depth);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
gameAnalogNode = this->configFile.NewElement("analog");
|
gameAnalogNode = this->configFile.NewElement("analog");
|
||||||
@@ -264,6 +287,9 @@ bool Config::addGame(Game &game) {
|
|||||||
gameAnalogNode->SetAttribute("deadzone_mirror", it.getDeadzoneMirror());
|
gameAnalogNode->SetAttribute("deadzone_mirror", it.getDeadzoneMirror());
|
||||||
gameAnalogNode->SetAttribute("invert", it.getInvert());
|
gameAnalogNode->SetAttribute("invert", it.getInvert());
|
||||||
gameAnalogNode->SetAttribute("smoothing", it.getSmoothing());
|
gameAnalogNode->SetAttribute("smoothing", it.getSmoothing());
|
||||||
|
gameAnalogNode->SetAttribute("multiplier", it.getMultiplier());
|
||||||
|
gameAnalogNode->SetAttribute("relative", it.isRelativeMode());
|
||||||
|
gameAnalogNode->SetAttribute("delay", it.getDelayBufferDepth());
|
||||||
gameAnalogNode->SetAttribute("devid", it.getDeviceIdentifier().c_str());
|
gameAnalogNode->SetAttribute("devid", it.getDeviceIdentifier().c_str());
|
||||||
gameAnalogsNode->InsertEndChild(gameAnalogNode);
|
gameAnalogsNode->InsertEndChild(gameAnalogNode);
|
||||||
}
|
}
|
||||||
@@ -397,6 +423,7 @@ bool Config::addGame(Game &game) {
|
|||||||
gameButtonNode->SetAttribute("analogtype", it.getAnalogType());
|
gameButtonNode->SetAttribute("analogtype", it.getAnalogType());
|
||||||
gameButtonNode->SetAttribute("debounce_up", it.getDebounceUp());
|
gameButtonNode->SetAttribute("debounce_up", it.getDebounceUp());
|
||||||
gameButtonNode->SetAttribute("debounce_down", it.getDebounceDown());
|
gameButtonNode->SetAttribute("debounce_down", it.getDebounceDown());
|
||||||
|
gameButtonNode->SetAttribute("velocity_threshold", it.getVelocityThreshold());
|
||||||
gameButtonNode->SetAttribute("invert", it.getInvert());
|
gameButtonNode->SetAttribute("invert", it.getInvert());
|
||||||
gameButtonNode->SetAttribute("devid", it.getDeviceIdentifier().c_str());
|
gameButtonNode->SetAttribute("devid", it.getDeviceIdentifier().c_str());
|
||||||
gameButtonsNode->InsertEndChild(gameButtonNode);
|
gameButtonsNode->InsertEndChild(gameButtonNode);
|
||||||
@@ -414,6 +441,9 @@ bool Config::addGame(Game &game) {
|
|||||||
gameAnalogNode->SetAttribute("deadzone_mirror", it.getDeadzoneMirror());
|
gameAnalogNode->SetAttribute("deadzone_mirror", it.getDeadzoneMirror());
|
||||||
gameAnalogNode->SetAttribute("invert", it.getInvert());
|
gameAnalogNode->SetAttribute("invert", it.getInvert());
|
||||||
gameAnalogNode->SetAttribute("smoothing", it.getSmoothing());
|
gameAnalogNode->SetAttribute("smoothing", it.getSmoothing());
|
||||||
|
gameAnalogNode->SetAttribute("multiplier", it.getMultiplier());
|
||||||
|
gameAnalogNode->SetAttribute("relative", it.isRelativeMode());
|
||||||
|
gameAnalogNode->SetAttribute("delay", it.getDelayBufferDepth());
|
||||||
gameAnalogsNode->InsertEndChild(gameAnalogNode);
|
gameAnalogsNode->InsertEndChild(gameAnalogNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,7 +472,7 @@ bool Config::addGame(Game &game) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// save config
|
// save config
|
||||||
this->configFile.SaveFile(this->configLocation.c_str(), false);
|
this->saveConfigFile();
|
||||||
|
|
||||||
// return success
|
// return success
|
||||||
return true;
|
return true;
|
||||||
@@ -494,6 +524,7 @@ bool Config::updateBinding(const Game &game, const Button &button, int alternati
|
|||||||
gameButtonNode->SetAttribute("analogtype", (int) button.getAnalogType());
|
gameButtonNode->SetAttribute("analogtype", (int) button.getAnalogType());
|
||||||
gameButtonNode->SetAttribute("debounce_up", button.getDebounceUp());
|
gameButtonNode->SetAttribute("debounce_up", button.getDebounceUp());
|
||||||
gameButtonNode->SetAttribute("debounce_down", button.getDebounceDown());
|
gameButtonNode->SetAttribute("debounce_down", button.getDebounceDown());
|
||||||
|
gameButtonNode->SetAttribute("velocity_threshold", button.getVelocityThreshold());
|
||||||
gameButtonNode->SetAttribute("invert", button.getInvert());
|
gameButtonNode->SetAttribute("invert", button.getInvert());
|
||||||
gameButtonNode->SetAttribute("devid", button.getDeviceIdentifier().c_str());
|
gameButtonNode->SetAttribute("devid", button.getDeviceIdentifier().c_str());
|
||||||
break;
|
break;
|
||||||
@@ -509,19 +540,47 @@ bool Config::updateBinding(const Game &game, const Button &button, int alternati
|
|||||||
gameButtonNode->SetAttribute("analogtype", 0);
|
gameButtonNode->SetAttribute("analogtype", 0);
|
||||||
gameButtonNode->SetAttribute("debounce_up", 0.0);
|
gameButtonNode->SetAttribute("debounce_up", 0.0);
|
||||||
gameButtonNode->SetAttribute("debounce_down", 0.0);
|
gameButtonNode->SetAttribute("debounce_down", 0.0);
|
||||||
|
gameButtonNode->SetAttribute("velocity_threshold", 0);
|
||||||
gameButtonNode->SetAttribute("invert", false);
|
gameButtonNode->SetAttribute("invert", false);
|
||||||
gameButtonNode->SetAttribute("devid", "");
|
gameButtonNode->SetAttribute("devid", "");
|
||||||
gameButtonsNode->InsertEndChild(gameButtonNode);
|
gameButtonsNode->InsertEndChild(gameButtonNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for MIDI notes, need to keep velocity threshold consistent for all bindings
|
||||||
|
// ;MIDI; is a unique prefix that we use at rawinput layer to identify MIDI devices
|
||||||
|
const bool fixup_other_buttons =
|
||||||
|
(button.getAnalogType() == (int)BAT_NONE &&
|
||||||
|
!button.getDeviceIdentifier().empty() &&
|
||||||
|
button.getDeviceIdentifier().find(";MIDI;", 0) == 0);
|
||||||
|
if (fixup_other_buttons) {
|
||||||
|
gameButtonNode = gameButtonsNode->FirstChildElement("button");
|
||||||
|
while (gameButtonNode != nullptr) {
|
||||||
|
const char *devid = gameButtonNode->Attribute("devid");
|
||||||
|
if (button.getDeviceIdentifier() == devid) {
|
||||||
|
int other_vKey = 0;
|
||||||
|
int other_vel = 0;
|
||||||
|
int other_type = 0;
|
||||||
|
gameButtonNode->QueryIntAttribute("velocity_threshold", &other_vel);
|
||||||
|
gameButtonNode->QueryIntAttribute("vkey", &other_vKey);
|
||||||
|
gameButtonNode->QueryIntAttribute("analogtype", &other_type);
|
||||||
|
if (other_vKey == button.getVKey() &&
|
||||||
|
other_type == button.getAnalogType() &&
|
||||||
|
other_vel != button.getVelocityThreshold()) {
|
||||||
|
gameButtonNode->SetAttribute("velocity_threshold", button.getVelocityThreshold());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gameButtonNode = gameButtonNode->NextSiblingElement("button");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check if button was not found
|
// check if button was not found
|
||||||
if (button_count == 0) {
|
if (button_count == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// save config
|
// save config
|
||||||
this->configFile.SaveFile(this->configLocation.c_str(), false);
|
this->saveConfigFile();
|
||||||
|
|
||||||
// return success
|
// return success
|
||||||
return true;
|
return true;
|
||||||
@@ -579,6 +638,9 @@ bool Config::updateBinding(const Game &game, const Analog &analog) {
|
|||||||
gameAnalogNode->SetAttribute("deadzone_mirror", analog.getDeadzoneMirror());
|
gameAnalogNode->SetAttribute("deadzone_mirror", analog.getDeadzoneMirror());
|
||||||
gameAnalogNode->SetAttribute("invert", analog.getInvert());
|
gameAnalogNode->SetAttribute("invert", analog.getInvert());
|
||||||
gameAnalogNode->SetAttribute("smoothing", analog.getSmoothing());
|
gameAnalogNode->SetAttribute("smoothing", analog.getSmoothing());
|
||||||
|
gameAnalogNode->SetAttribute("multiplier", analog.getMultiplier());
|
||||||
|
gameAnalogNode->SetAttribute("relative", analog.isRelativeMode());
|
||||||
|
gameAnalogNode->SetAttribute("delay", analog.getDelayBufferDepth());
|
||||||
gameAnalogNode->SetAttribute("devid", analog.getDeviceIdentifier().c_str());
|
gameAnalogNode->SetAttribute("devid", analog.getDeviceIdentifier().c_str());
|
||||||
} else {
|
} else {
|
||||||
gameAnalogNode = this->configFile.NewElement("analog");
|
gameAnalogNode = this->configFile.NewElement("analog");
|
||||||
@@ -588,11 +650,14 @@ bool Config::updateBinding(const Game &game, const Analog &analog) {
|
|||||||
gameAnalogNode->SetAttribute("deadzone_mirror", analog.getDeadzoneMirror());
|
gameAnalogNode->SetAttribute("deadzone_mirror", analog.getDeadzoneMirror());
|
||||||
gameAnalogNode->SetAttribute("invert", analog.getInvert());
|
gameAnalogNode->SetAttribute("invert", analog.getInvert());
|
||||||
gameAnalogNode->SetAttribute("smoothing", analog.getSmoothing());
|
gameAnalogNode->SetAttribute("smoothing", analog.getSmoothing());
|
||||||
|
gameAnalogNode->SetAttribute("multiplier", analog.getMultiplier());
|
||||||
|
gameAnalogNode->SetAttribute("relative", analog.isRelativeMode());
|
||||||
|
gameAnalogNode->SetAttribute("delay", analog.getDelayBufferDepth());
|
||||||
gameAnalogNode->SetAttribute("devid", analog.getDeviceIdentifier().c_str());
|
gameAnalogNode->SetAttribute("devid", analog.getDeviceIdentifier().c_str());
|
||||||
gameAnalogsNode->InsertEndChild(gameAnalogNode);
|
gameAnalogsNode->InsertEndChild(gameAnalogNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->configFile.SaveFile(this->configLocation.c_str(), false);
|
this->saveConfigFile();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -633,7 +698,7 @@ bool Config::updateBinding(const Game &game, ConfigKeypadBindings &keypads) {
|
|||||||
gameKeypadNode->SetAttribute("cardpath1", reinterpret_cast<const char *>(keypads.card_paths[0].u8string().c_str()));
|
gameKeypadNode->SetAttribute("cardpath1", reinterpret_cast<const char *>(keypads.card_paths[0].u8string().c_str()));
|
||||||
gameKeypadNode->SetAttribute("cardpath2", reinterpret_cast<const char *>(keypads.card_paths[1].u8string().c_str()));
|
gameKeypadNode->SetAttribute("cardpath2", reinterpret_cast<const char *>(keypads.card_paths[1].u8string().c_str()));
|
||||||
|
|
||||||
this->configFile.SaveFile(this->configLocation.c_str(), false);
|
this->saveConfigFile();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -701,7 +766,7 @@ bool Config::updateBinding(const Game &game, const Light &light, int alternative
|
|||||||
}
|
}
|
||||||
|
|
||||||
// save config
|
// save config
|
||||||
this->configFile.SaveFile(this->configLocation.c_str(), false);
|
this->saveConfigFile();
|
||||||
|
|
||||||
// return success
|
// return success
|
||||||
return true;
|
return true;
|
||||||
@@ -760,7 +825,7 @@ bool Config::updateBinding(const Game &game, const Option &option) {
|
|||||||
gameOptionsNode->InsertEndChild(gameOptionNode);
|
gameOptionsNode->InsertEndChild(gameOptionNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->configFile.SaveFile(this->configLocation.c_str(), false);
|
this->saveConfigFile();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -806,11 +871,13 @@ std::vector<Button> Config::getButtons(const std::string &gameName) {
|
|||||||
auto analogType = (int) BAT_NONE;
|
auto analogType = (int) BAT_NONE;
|
||||||
double debounce_up = 0.0;
|
double debounce_up = 0.0;
|
||||||
double debounce_down = 0.0;
|
double debounce_down = 0.0;
|
||||||
|
int velocity_threshold = 0;
|
||||||
bool invert = false;
|
bool invert = false;
|
||||||
gameButtonNode->QueryIntAttribute("vkey", &vKey);
|
gameButtonNode->QueryIntAttribute("vkey", &vKey);
|
||||||
gameButtonNode->QueryIntAttribute("analogtype", &analogType);
|
gameButtonNode->QueryIntAttribute("analogtype", &analogType);
|
||||||
gameButtonNode->QueryDoubleAttribute("debounce_up", &debounce_up);
|
gameButtonNode->QueryDoubleAttribute("debounce_up", &debounce_up);
|
||||||
gameButtonNode->QueryDoubleAttribute("debounce_down", &debounce_down);
|
gameButtonNode->QueryDoubleAttribute("debounce_down", &debounce_down);
|
||||||
|
gameButtonNode->QueryIntAttribute("velocity_threshold", &velocity_threshold);
|
||||||
gameButtonNode->QueryBoolAttribute("invert", &invert);
|
gameButtonNode->QueryBoolAttribute("invert", &invert);
|
||||||
const char *devid = gameButtonNode->Attribute("devid");
|
const char *devid = gameButtonNode->Attribute("devid");
|
||||||
|
|
||||||
@@ -824,6 +891,7 @@ std::vector<Button> Config::getButtons(const std::string &gameName) {
|
|||||||
alt.setAnalogType((ButtonAnalogType) analogType);
|
alt.setAnalogType((ButtonAnalogType) analogType);
|
||||||
alt.setDebounceUp(debounce_up);
|
alt.setDebounceUp(debounce_up);
|
||||||
alt.setDebounceDown(debounce_down);
|
alt.setDebounceDown(debounce_down);
|
||||||
|
alt.setVelocityThreshold(velocity_threshold);
|
||||||
alt.setInvert(invert);
|
alt.setInvert(invert);
|
||||||
if (devid) {
|
if (devid) {
|
||||||
alt.setDeviceIdentifier(std::string(devid));
|
alt.setDeviceIdentifier(std::string(devid));
|
||||||
@@ -835,13 +903,13 @@ std::vector<Button> Config::getButtons(const std::string &gameName) {
|
|||||||
|
|
||||||
// if no alternative was found
|
// if no alternative was found
|
||||||
if (!alternative_found) {
|
if (!alternative_found) {
|
||||||
|
|
||||||
// create button and add to list
|
// create button and add to list
|
||||||
auto &button = buttons.emplace_back(buttonNodeName);
|
auto &button = buttons.emplace_back(buttonNodeName);
|
||||||
button.setVKey((unsigned short) vKey);
|
button.setVKey((unsigned short) vKey);
|
||||||
button.setAnalogType((ButtonAnalogType) analogType);
|
button.setAnalogType((ButtonAnalogType) analogType);
|
||||||
button.setDebounceUp(debounce_up);
|
button.setDebounceUp(debounce_up);
|
||||||
button.setDebounceDown(debounce_down);
|
button.setDebounceDown(debounce_down);
|
||||||
|
button.setVelocityThreshold(velocity_threshold);
|
||||||
button.setInvert(invert);
|
button.setInvert(invert);
|
||||||
if (devid) {
|
if (devid) {
|
||||||
button.setDeviceIdentifier(devid);
|
button.setDeviceIdentifier(devid);
|
||||||
@@ -985,12 +1053,18 @@ std::vector<Analog> Config::getAnalogs(const std::string &gameName) {
|
|||||||
bool deadzone_mirror = false;
|
bool deadzone_mirror = false;
|
||||||
bool invert = false;
|
bool invert = false;
|
||||||
bool smoothing = false;
|
bool smoothing = false;
|
||||||
|
int multiplier = 1;
|
||||||
|
bool relative_mode = false;
|
||||||
|
int delay_buffer_depth = 0;
|
||||||
gameAnalogNode->QueryIntAttribute("index", &index);
|
gameAnalogNode->QueryIntAttribute("index", &index);
|
||||||
gameAnalogNode->QueryFloatAttribute("sensivity", &sensitivity);
|
gameAnalogNode->QueryFloatAttribute("sensivity", &sensitivity);
|
||||||
gameAnalogNode->QueryFloatAttribute("deadzone", &deadzone);
|
gameAnalogNode->QueryFloatAttribute("deadzone", &deadzone);
|
||||||
gameAnalogNode->QueryBoolAttribute("deadzone_mirror", &deadzone_mirror);
|
gameAnalogNode->QueryBoolAttribute("deadzone_mirror", &deadzone_mirror);
|
||||||
gameAnalogNode->QueryBoolAttribute("invert", &invert);
|
gameAnalogNode->QueryBoolAttribute("invert", &invert);
|
||||||
gameAnalogNode->QueryBoolAttribute("smoothing", &smoothing);
|
gameAnalogNode->QueryBoolAttribute("smoothing", &smoothing);
|
||||||
|
gameAnalogNode->QueryIntAttribute("multiplier", &multiplier);
|
||||||
|
gameAnalogNode->QueryBoolAttribute("relative", &relative_mode);
|
||||||
|
gameAnalogNode->QueryIntAttribute("delay", &delay_buffer_depth);
|
||||||
const char *devid = gameAnalogNode->Attribute("devid");
|
const char *devid = gameAnalogNode->Attribute("devid");
|
||||||
|
|
||||||
// create analog and add to list
|
// create analog and add to list
|
||||||
@@ -1001,6 +1075,9 @@ std::vector<Analog> Config::getAnalogs(const std::string &gameName) {
|
|||||||
analog.setDeadzoneMirror(deadzone_mirror);
|
analog.setDeadzoneMirror(deadzone_mirror);
|
||||||
analog.setInvert(invert);
|
analog.setInvert(invert);
|
||||||
analog.setSmoothing(smoothing);
|
analog.setSmoothing(smoothing);
|
||||||
|
analog.setMultiplier(multiplier);
|
||||||
|
analog.setRelativeMode(relative_mode);
|
||||||
|
analog.setDelayBufferDepth(delay_buffer_depth);
|
||||||
if (devid) {
|
if (devid) {
|
||||||
analog.setDeviceIdentifier(devid);
|
analog.setDeviceIdentifier(devid);
|
||||||
}
|
}
|
||||||
@@ -1136,7 +1213,7 @@ std::vector<Option> Config::getOptions(Game *game) {
|
|||||||
|
|
||||||
bool Config::createConfigFile() {
|
bool Config::createConfigFile() {
|
||||||
std::ofstream ofsConfig;
|
std::ofstream ofsConfig;
|
||||||
ofsConfig.open(this->configLocation);
|
ofsConfig.open(this->configLocationTemp);
|
||||||
if (!ofsConfig.is_open() || ofsConfig.fail() || ofsConfig.bad()) {
|
if (!ofsConfig.is_open() || ofsConfig.fail() || ofsConfig.bad()) {
|
||||||
this->status = false;
|
this->status = false;
|
||||||
return false;
|
return false;
|
||||||
@@ -1146,7 +1223,7 @@ bool Config::createConfigFile() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Config::firstFillConfigFile() {
|
bool Config::firstFillConfigFile() {
|
||||||
this->configFile.LoadFile(this->configLocation.c_str());
|
this->configFile.LoadFile(this->configLocationTemp.c_str());
|
||||||
this->configFile.Clear();
|
this->configFile.Clear();
|
||||||
|
|
||||||
tinyxml2::XMLNode *declarationNode = this->configFile.NewDeclaration();
|
tinyxml2::XMLNode *declarationNode = this->configFile.NewDeclaration();
|
||||||
@@ -1155,6 +1232,22 @@ bool Config::firstFillConfigFile() {
|
|||||||
tinyxml2::XMLNode *rootNode = this->configFile.NewElement("games");
|
tinyxml2::XMLNode *rootNode = this->configFile.NewElement("games");
|
||||||
this->configFile.InsertEndChild(rootNode);
|
this->configFile.InsertEndChild(rootNode);
|
||||||
|
|
||||||
this->configFile.SaveFile(this->configLocation.c_str(), false);
|
this->saveConfigFile();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Config::saveConfigFile() {
|
||||||
|
// create a .tmp file and write to it...
|
||||||
|
const auto xml_result = this->configFile.SaveFile(this->configLocationTemp.c_str(), false);
|
||||||
|
if (xml_result != tinyxml2::XMLError::XML_SUCCESS) {
|
||||||
|
log_info("cfg", "failed to write file: {}", this->configLocationTemp.string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// copy the .tmp file to the main file...
|
||||||
|
if (CopyFileW(this->configLocationTemp.c_str(), this->configLocation.c_str(), false) == 0) {
|
||||||
|
log_warning("cfg", "CopyFileA failed: 0x{:08x}", GetLastError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// delete the .tmp file (not critical if this fails)
|
||||||
|
DeleteFileW(this->configLocationTemp.c_str());
|
||||||
|
}
|
||||||
+3
-1
@@ -54,7 +54,9 @@ private:
|
|||||||
|
|
||||||
tinyxml2::XMLDocument configFile;
|
tinyxml2::XMLDocument configFile;
|
||||||
bool status;
|
bool status;
|
||||||
std::string configLocation;
|
std::filesystem::path configLocation;
|
||||||
|
std::filesystem::path configLocationTemp;
|
||||||
|
|
||||||
bool firstFillConfigFile();
|
bool firstFillConfigFile();
|
||||||
|
void saveConfigFile();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "configurator.h"
|
#include "configurator.h"
|
||||||
|
|
||||||
#include "overlay/overlay.h"
|
#include "overlay/overlay.h"
|
||||||
#include "script/manager.h"
|
|
||||||
|
|
||||||
namespace cfg {
|
namespace cfg {
|
||||||
|
|
||||||
@@ -26,14 +25,7 @@ namespace cfg {
|
|||||||
overlay::OVERLAY->hotkeys_enable = false;
|
overlay::OVERLAY->hotkeys_enable = false;
|
||||||
ImGui::GetIO().MouseDrawCursor = false;
|
ImGui::GetIO().MouseDrawCursor = false;
|
||||||
|
|
||||||
// scripts
|
|
||||||
script::manager_scan();
|
|
||||||
script::manager_config();
|
|
||||||
|
|
||||||
// run window
|
// run window
|
||||||
this->wnd.run();
|
this->wnd.run();
|
||||||
|
|
||||||
// clean up
|
|
||||||
script::manager_shutdown();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -5,8 +5,7 @@
|
|||||||
namespace cfg {
|
namespace cfg {
|
||||||
|
|
||||||
enum class ConfigType {
|
enum class ConfigType {
|
||||||
Config,
|
Config
|
||||||
KFControl,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// globals
|
// globals
|
||||||
|
|||||||
@@ -29,13 +29,9 @@ cfg::ConfiguratorWindow::ConfiguratorWindow() {
|
|||||||
|
|
||||||
// determine window title
|
// determine window title
|
||||||
if (cfg::CONFIGURATOR_TYPE == cfg::ConfigType::Config) {
|
if (cfg::CONFIGURATOR_TYPE == cfg::ConfigType::Config) {
|
||||||
WINDOW_TITLE = "spice2x config - a fork of SpiceTools (" + to_string(VERSION_STRING_CFG) + ")";
|
WINDOW_TITLE = "spice2x config (" + to_string(VERSION_STRING_CFG) + ")";
|
||||||
WINDOW_SIZE_X = 800;
|
WINDOW_SIZE_X = 800;
|
||||||
WINDOW_SIZE_Y = 600;
|
WINDOW_SIZE_Y = 600;
|
||||||
} else if (cfg::CONFIGURATOR_TYPE == cfg::ConfigType::KFControl) {
|
|
||||||
WINDOW_TITLE = "KFControl (" + to_string(VERSION_STRING_CFG) + ")";
|
|
||||||
WINDOW_SIZE_X = 400;
|
|
||||||
WINDOW_SIZE_Y = 316;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// open window
|
// open window
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
#include "rawinput/piuio.h"
|
#include "rawinput/piuio.h"
|
||||||
#include "rawinput/rawinput.h"
|
#include "rawinput/rawinput.h"
|
||||||
#include "rawinput/sextet.h"
|
#include "rawinput/sextet.h"
|
||||||
|
#include "rawinput/smxdedicab.h"
|
||||||
|
#include "rawinput/smxstage.h"
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
|
|
||||||
std::string Light::getDisplayString(rawinput::RawInputManager* manager) {
|
std::string Light::getDisplayString(rawinput::RawInputManager* manager) {
|
||||||
@@ -65,6 +67,24 @@ std::string Light::getDisplayString(rawinput::RawInputManager* manager) {
|
|||||||
|
|
||||||
return "Invalid PIUIO Light (" + index_string + ")";
|
return "Invalid PIUIO Light (" + index_string + ")";
|
||||||
}
|
}
|
||||||
|
case rawinput::SMX_STAGE: {
|
||||||
|
|
||||||
|
// get light name of SMX Stage device
|
||||||
|
if (index < rawinput::SmxStageDevice::TOTAL_LIGHT_COUNT) {
|
||||||
|
return rawinput::SmxStageDevice::GetLightNameByIndex(index) + " (" + index_string + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Invalid SMX Stage Light (" + index_string + ")";
|
||||||
|
}
|
||||||
|
case rawinput::SMX_DEDICAB: {
|
||||||
|
|
||||||
|
// get light name of SMX Dedicab device
|
||||||
|
if (index < rawinput::SmxDedicabDevice::LIGHTS_COUNT) {
|
||||||
|
return rawinput::SmxDedicabDevice::GetLightNameByIndex(index) + " (" + index_string + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Invalid SMX Dedicab Light (" + index_string + ")";
|
||||||
|
}
|
||||||
case rawinput::DESTROYED:
|
case rawinput::DESTROYED:
|
||||||
return "Unplugged device (" + index_string + ")";
|
return "Unplugged device (" + index_string + ")";
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "option.h"
|
#include "option.h"
|
||||||
|
|
||||||
#include "util/logging.h"
|
#include "util/logging.h"
|
||||||
|
#include "util/utils.h"
|
||||||
|
|
||||||
void Option::value_add(std::string new_value) {
|
void Option::value_add(std::string new_value) {
|
||||||
|
|
||||||
@@ -97,3 +98,15 @@ uint64_t Option::value_hex64() const {
|
|||||||
}
|
}
|
||||||
return affinity;
|
return affinity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Option::search_match(const std::string &query_in_lower_case) {
|
||||||
|
if (this->search_string.empty()) {
|
||||||
|
const auto ¶m =
|
||||||
|
this->definition.display_name.empty() ?
|
||||||
|
this->definition.name : this->definition.display_name;
|
||||||
|
|
||||||
|
const auto s = this->definition.title + " -" + param;
|
||||||
|
this->search_string = strtolower(s);
|
||||||
|
}
|
||||||
|
return this->search_string.find(query_in_lower_case) != std::string::npos;
|
||||||
|
}
|
||||||
|
|||||||
+13
-1
@@ -3,6 +3,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
enum class OptionType {
|
enum class OptionType {
|
||||||
Bool,
|
Bool,
|
||||||
@@ -14,7 +15,14 @@ enum class OptionType {
|
|||||||
|
|
||||||
struct OptionDefinition {
|
struct OptionDefinition {
|
||||||
std::string title;
|
std::string title;
|
||||||
|
// unique identifier used for flag matching but also stored in config files
|
||||||
|
// (should not be changed once published for compat)
|
||||||
std::string name;
|
std::string name;
|
||||||
|
// what's displayed in the UI/logs as the flag name
|
||||||
|
std::string display_name = "";
|
||||||
|
// slash-delimited list of strings that also work as flag
|
||||||
|
std::string aliases = "";
|
||||||
|
// what's displayed in the UI/logs as the tooltip
|
||||||
std::string desc;
|
std::string desc;
|
||||||
OptionType type;
|
OptionType type;
|
||||||
bool hidden = false;
|
bool hidden = false;
|
||||||
@@ -23,11 +31,13 @@ struct OptionDefinition {
|
|||||||
std::string category = "Development";
|
std::string category = "Development";
|
||||||
bool sensitive = false;
|
bool sensitive = false;
|
||||||
std::vector<std::pair<std::string, std::string>> elements = {};
|
std::vector<std::pair<std::string, std::string>> elements = {};
|
||||||
|
bool disabled = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Option {
|
class Option {
|
||||||
private:
|
private:
|
||||||
OptionDefinition definition;
|
OptionDefinition definition;
|
||||||
|
std::string search_string;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::string value;
|
std::string value;
|
||||||
@@ -35,7 +45,8 @@ public:
|
|||||||
bool disabled = false;
|
bool disabled = false;
|
||||||
|
|
||||||
explicit Option(OptionDefinition definition, std::string value = "") :
|
explicit Option(OptionDefinition definition, std::string value = "") :
|
||||||
definition(std::move(definition)), value(std::move(value)) {};
|
definition(std::move(definition)), value(std::move(value)) {
|
||||||
|
};
|
||||||
|
|
||||||
inline const OptionDefinition &get_definition() const {
|
inline const OptionDefinition &get_definition() const {
|
||||||
return this->definition;
|
return this->definition;
|
||||||
@@ -57,4 +68,5 @@ public:
|
|||||||
std::vector<std::string> values_text() const;
|
std::vector<std::string> values_text() const;
|
||||||
uint32_t value_uint32() const;
|
uint32_t value_uint32() const;
|
||||||
uint64_t value_hex64() const;
|
uint64_t value_hex64() const;
|
||||||
|
bool search_match(const std::string &query_in_lower_case);
|
||||||
};
|
};
|
||||||
|
|||||||
+38
-23
@@ -12,10 +12,21 @@ namespace cfg {
|
|||||||
|
|
||||||
// globals
|
// globals
|
||||||
std::unique_ptr<cfg::ScreenResize> SCREENRESIZE;
|
std::unique_ptr<cfg::ScreenResize> SCREENRESIZE;
|
||||||
|
std::optional<std::string> SCREEN_RESIZE_CFG_PATH_OVERRIDE;
|
||||||
|
|
||||||
ScreenResize::ScreenResize() {
|
ScreenResize::ScreenResize() {
|
||||||
this->config_path = std::string(getenv("APPDATA")) + "\\spicetools_screen_resize.json";
|
bool file_exists = false;
|
||||||
|
if (SCREEN_RESIZE_CFG_PATH_OVERRIDE.has_value()) {
|
||||||
|
this->config_path = SCREEN_RESIZE_CFG_PATH_OVERRIDE.value();
|
||||||
if (fileutils::file_exists(this->config_path)) {
|
if (fileutils::file_exists(this->config_path)) {
|
||||||
|
log_info("ScreenResize", "loading config from: {}", this->config_path.string());
|
||||||
|
file_exists = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this->config_path =
|
||||||
|
fileutils::get_config_file_path("ScreenResize", "spicetools_screen_resize.json", &file_exists);
|
||||||
|
}
|
||||||
|
if (file_exists) {
|
||||||
this->config_load();
|
this->config_load();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -24,10 +35,9 @@ namespace cfg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ScreenResize::config_load() {
|
void ScreenResize::config_load() {
|
||||||
log_info("ScreenResize", "loading config");
|
|
||||||
|
|
||||||
std::string config = fileutils::text_read(this->config_path);
|
std::string config = fileutils::text_read(this->config_path);
|
||||||
if (config.empty()) {
|
if (config.empty()) {
|
||||||
|
log_info("ScreenResize", "config is empty");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,14 +76,18 @@ namespace cfg {
|
|||||||
eamuse_get_game(),
|
eamuse_get_game(),
|
||||||
use_game_setting,
|
use_game_setting,
|
||||||
root);
|
root);
|
||||||
load_int_value(doc, root + "offset_x", this->offset_x);
|
|
||||||
load_int_value(doc, root + "offset_y", this->offset_y);
|
|
||||||
load_float_value(doc, root + "scale_x", this->scale_x);
|
|
||||||
load_float_value(doc, root + "scale_y", this->scale_y);
|
|
||||||
load_bool_value(doc, root + "enable_screen_resize", this->enable_screen_resize);
|
load_bool_value(doc, root + "enable_screen_resize", this->enable_screen_resize);
|
||||||
load_bool_value(doc, root + "enable_linear_filter", this->enable_linear_filter);
|
load_bool_value(doc, root + "enable_linear_filter", this->enable_linear_filter);
|
||||||
load_bool_value(doc, root + "keep_aspect_ratio", this->keep_aspect_ratio);
|
for (size_t i = 0; i < std::size(this->scene_settings); i++) {
|
||||||
load_bool_value(doc, root + "centered", this->centered);
|
auto& scene = this->scene_settings[i];
|
||||||
|
const std::string prefix = fmt::format("scenes/{}/", i);
|
||||||
|
load_int_value(doc, root + prefix + "offset_x", scene.offset_x);
|
||||||
|
load_int_value(doc, root + prefix + "offset_y", scene.offset_y);
|
||||||
|
load_float_value(doc, root + prefix + "scale_x", scene.scale_x);
|
||||||
|
load_float_value(doc, root + prefix + "scale_y", scene.scale_y);
|
||||||
|
load_bool_value(doc, root + prefix + "keep_aspect_ratio", scene.keep_aspect_ratio);
|
||||||
|
}
|
||||||
|
|
||||||
// windowed settings are always under game settings
|
// windowed settings are always under game settings
|
||||||
root = "/sp2x_games/" + eamuse_get_game() + "/";
|
root = "/sp2x_games/" + eamuse_get_game() + "/";
|
||||||
@@ -95,7 +109,7 @@ namespace cfg {
|
|||||||
bool ScreenResize::load_bool_value(rapidjson::Document& doc, std::string path, bool& value) {
|
bool ScreenResize::load_bool_value(rapidjson::Document& doc, std::string path, bool& value) {
|
||||||
const auto v = rapidjson::Pointer(path).Get(doc);
|
const auto v = rapidjson::Pointer(path).Get(doc);
|
||||||
if (!v) {
|
if (!v) {
|
||||||
log_warning("ScreenResize", "{} not found", path);
|
log_misc("ScreenResize", "{} not found", path);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!v->IsBool()) {
|
if (!v->IsBool()) {
|
||||||
@@ -109,7 +123,7 @@ namespace cfg {
|
|||||||
bool ScreenResize::load_int_value(rapidjson::Document& doc, std::string path, int& value) {
|
bool ScreenResize::load_int_value(rapidjson::Document& doc, std::string path, int& value) {
|
||||||
const auto v = rapidjson::Pointer(path).Get(doc);
|
const auto v = rapidjson::Pointer(path).Get(doc);
|
||||||
if (!v) {
|
if (!v) {
|
||||||
log_warning("ScreenResize", "{} not found", path);
|
log_misc("ScreenResize", "{} not found", path);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!v->IsInt()) {
|
if (!v->IsInt()) {
|
||||||
@@ -123,7 +137,7 @@ namespace cfg {
|
|||||||
bool ScreenResize::load_uint32_value(rapidjson::Document& doc, std::string path, uint32_t& value) {
|
bool ScreenResize::load_uint32_value(rapidjson::Document& doc, std::string path, uint32_t& value) {
|
||||||
const auto v = rapidjson::Pointer(path).Get(doc);
|
const auto v = rapidjson::Pointer(path).Get(doc);
|
||||||
if (!v) {
|
if (!v) {
|
||||||
log_warning("ScreenResize", "{} not found", path);
|
log_misc("ScreenResize", "{} not found", path);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!v->IsUint()) {
|
if (!v->IsUint()) {
|
||||||
@@ -137,7 +151,7 @@ namespace cfg {
|
|||||||
bool ScreenResize::load_float_value(rapidjson::Document& doc, std::string path, float& value) {
|
bool ScreenResize::load_float_value(rapidjson::Document& doc, std::string path, float& value) {
|
||||||
const auto v = rapidjson::Pointer(path).Get(doc);
|
const auto v = rapidjson::Pointer(path).Get(doc);
|
||||||
if (!v) {
|
if (!v) {
|
||||||
log_warning("ScreenResize", "{} not found", path);
|
log_misc("ScreenResize", "{} not found", path);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (v->IsInt()) {
|
if (v->IsInt()) {
|
||||||
@@ -156,8 +170,6 @@ namespace cfg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ScreenResize::config_save() {
|
void ScreenResize::config_save() {
|
||||||
log_info("ScreenResize", "saving config");
|
|
||||||
|
|
||||||
rapidjson::Document doc;
|
rapidjson::Document doc;
|
||||||
std::string config = fileutils::text_read(this->config_path);
|
std::string config = fileutils::text_read(this->config_path);
|
||||||
if (!config.empty()) {
|
if (!config.empty()) {
|
||||||
@@ -179,14 +191,17 @@ namespace cfg {
|
|||||||
root);
|
root);
|
||||||
|
|
||||||
// full screen image settings
|
// full screen image settings
|
||||||
rapidjson::Pointer(root + "offset_x").Set(doc, this->offset_x);
|
|
||||||
rapidjson::Pointer(root + "offset_y").Set(doc, this->offset_y);
|
|
||||||
rapidjson::Pointer(root + "scale_x").Set(doc, this->scale_x);
|
|
||||||
rapidjson::Pointer(root + "scale_y").Set(doc, this->scale_y);
|
|
||||||
rapidjson::Pointer(root + "enable_screen_resize").Set(doc, this->enable_screen_resize);
|
rapidjson::Pointer(root + "enable_screen_resize").Set(doc, this->enable_screen_resize);
|
||||||
rapidjson::Pointer(root + "enable_linear_filter").Set(doc, this->enable_linear_filter);
|
rapidjson::Pointer(root + "enable_linear_filter").Set(doc, this->enable_linear_filter);
|
||||||
rapidjson::Pointer(root + "keep_aspect_ratio").Set(doc, this->keep_aspect_ratio);
|
for (size_t i = 0; i < std::size(this->scene_settings); i++) {
|
||||||
rapidjson::Pointer(root + "centered").Set(doc, this->centered);
|
auto& scene = this->scene_settings[i];
|
||||||
|
const std::string prefix = fmt::format("scenes/{}/", i);
|
||||||
|
rapidjson::Pointer(root + prefix + "offset_x").Set(doc, scene.offset_x);
|
||||||
|
rapidjson::Pointer(root + prefix + "offset_y").Set(doc, scene.offset_y);
|
||||||
|
rapidjson::Pointer(root + prefix + "scale_x").Set(doc, scene.scale_x);
|
||||||
|
rapidjson::Pointer(root + prefix + "scale_y").Set(doc, scene.scale_y);
|
||||||
|
rapidjson::Pointer(root + prefix + "keep_aspect_ratio").Set(doc, scene.keep_aspect_ratio);
|
||||||
|
}
|
||||||
|
|
||||||
// windowed mode settings
|
// windowed mode settings
|
||||||
rapidjson::Pointer(root + "w_always_on_top").Set(doc, this->window_always_on_top);
|
rapidjson::Pointer(root + "w_always_on_top").Set(doc, this->window_always_on_top);
|
||||||
@@ -204,10 +219,10 @@ namespace cfg {
|
|||||||
doc.Accept(writer);
|
doc.Accept(writer);
|
||||||
|
|
||||||
// save to file
|
// save to file
|
||||||
if (fileutils::text_write(this->config_path, buffer.GetString())) {
|
if (fileutils::write_config_file("ScreenResize", this->config_path, buffer.GetString())) {
|
||||||
// this->config_dirty = false;
|
// this->config_dirty = false;
|
||||||
} else {
|
} else {
|
||||||
log_warning("ScreenResize", "unable to save config file to {}", this->config_path);
|
log_warning("ScreenResize", "unable to save config file");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-7
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
|
#include <filesystem>
|
||||||
#include "external/rapidjson/document.h"
|
#include "external/rapidjson/document.h"
|
||||||
|
|
||||||
namespace cfg {
|
namespace cfg {
|
||||||
@@ -12,9 +14,19 @@ namespace cfg {
|
|||||||
ResizableFrame = 2
|
ResizableFrame = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct fullscreen_setting {
|
||||||
|
int offset_x = 0;
|
||||||
|
int offset_y = 0;
|
||||||
|
float scale_x = 1.0;
|
||||||
|
float scale_y = 1.0;
|
||||||
|
bool keep_aspect_ratio = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern std::optional<std::string> SCREEN_RESIZE_CFG_PATH_OVERRIDE;
|
||||||
|
|
||||||
class ScreenResize {
|
class ScreenResize {
|
||||||
private:
|
private:
|
||||||
std::string config_path;
|
std::filesystem::path config_path;
|
||||||
// bool config_dirty = false;
|
// bool config_dirty = false;
|
||||||
|
|
||||||
bool load_bool_value(rapidjson::Document& doc, std::string path, bool& value);
|
bool load_bool_value(rapidjson::Document& doc, std::string path, bool& value);
|
||||||
@@ -27,14 +39,10 @@ namespace cfg {
|
|||||||
~ScreenResize();
|
~ScreenResize();
|
||||||
|
|
||||||
// full screen (directx) image settings
|
// full screen (directx) image settings
|
||||||
int offset_x = 0;
|
|
||||||
int offset_y = 0;
|
|
||||||
float scale_x = 1.0;
|
|
||||||
float scale_y = 1.0;
|
|
||||||
bool enable_screen_resize = false;
|
bool enable_screen_resize = false;
|
||||||
|
int8_t screen_resize_current_scene = 0;
|
||||||
bool enable_linear_filter = true;
|
bool enable_linear_filter = true;
|
||||||
bool keep_aspect_ratio = true;
|
fullscreen_setting scene_settings[4];
|
||||||
bool centered = true;
|
|
||||||
|
|
||||||
// windowed mode sizing
|
// windowed mode sizing
|
||||||
// Windows terminology:
|
// Windows terminology:
|
||||||
|
|||||||
+393
-3
@@ -1,3 +1,393 @@
|
|||||||
|
04/25/2025 [spice2x]
|
||||||
|
LargeAddressAware variant of spice.exe for Metal Gear
|
||||||
|
Save new JSON config files to %appdata%/spice2x
|
||||||
|
Various bug fixes
|
||||||
|
|
||||||
|
04/08/2025 [spice2x]
|
||||||
|
Ensure rawinput touch is default for all games (-wintouch to override)
|
||||||
|
Various overlay UI fixes and improvements, update ImGui library
|
||||||
|
Add missing lights in Museca
|
||||||
|
|
||||||
|
03/29/2025 [spice2x]
|
||||||
|
Add SDVX landscape mode, -forceresswap option
|
||||||
|
Fix bugs in image scaler
|
||||||
|
Configurator UI tweaks
|
||||||
|
|
||||||
|
03/25/2025 [spice2x]
|
||||||
|
Add Mahjong Fight Girl support
|
||||||
|
Add option for custom full screen resolution (-forceres)
|
||||||
|
|
||||||
|
03/24/2025 [spice2x]
|
||||||
|
Auto PIN entry
|
||||||
|
Multiple scenes for image resize
|
||||||
|
API: add resize function, lights.read can now filter lights by name
|
||||||
|
Fix DLL hooks not receiving command-line arguments
|
||||||
|
|
||||||
|
03/16/2025 [spice2x]
|
||||||
|
Fix clipboard copy function truncating last character of string
|
||||||
|
|
||||||
|
03/03/2025 [spice2x]
|
||||||
|
IIDX: add workaround for REVERB EX filter missing in Windows 11 update
|
||||||
|
|
||||||
|
02/25/2025 [spice2x]
|
||||||
|
Add -vsyncbuffer option for forcing double/triple buffering
|
||||||
|
|
||||||
|
02/22/2025 [spice2x]
|
||||||
|
Add -windowscale option for resizing DX9 backbuffer dimensions
|
||||||
|
|
||||||
|
01/26/2025 [spice2x]
|
||||||
|
Expanded main menu in overlay (default bind: esc key)
|
||||||
|
Nostalgia: touch and swipe gestures (-nostpoke)
|
||||||
|
Jubeat: detect root directory boot failure
|
||||||
|
Add "Any Direction" analog type for button binding
|
||||||
|
|
||||||
|
01/16/2025 [spice2x]
|
||||||
|
More MIDI improvements:
|
||||||
|
use v2_drum algorithm instead of v2 by default for drummania & FTT
|
||||||
|
threshold setting for CC when mapped as a button (hi-hat pedals)
|
||||||
|
sustain duration applied to CC OnOff controls (sustain pedals)
|
||||||
|
Nostalgia, Beatstream: fix EA card insertion issue
|
||||||
|
CCJ, QKS: translate some windowed mode settings to Unity engine
|
||||||
|
Fix DEBUG build
|
||||||
|
|
||||||
|
01/08/2025 [spice2x]
|
||||||
|
Better MIDI support; significant improvements for drums
|
||||||
|
Fix various UI bugs in Buttons / Analog tabs
|
||||||
|
Nostalgia: fix velocity handling for MIDI input
|
||||||
|
Show camera names in camera control overlay
|
||||||
|
Game exit dialog (default: Escape key)
|
||||||
|
Button layout help text in Buttons tab
|
||||||
|
|
||||||
|
12/31/2024 [spice2x]
|
||||||
|
Fix videos not playing in Unity-based games
|
||||||
|
Dump audio device info in wrapped WASAPI handler
|
||||||
|
Update DLL load failure message
|
||||||
|
|
||||||
|
12/30/2024 [spice2x]
|
||||||
|
Busou Shinki: Show Cursor option now properly shows cursor in game
|
||||||
|
IIDX: add IIDX NVENC Quality option (-iidxreccqp)
|
||||||
|
IIDX: always enable NVENC hook, not just when -iidx is set
|
||||||
|
IIDX: add help text to keypad overlay in TDJ mode
|
||||||
|
Busou Shinki, QKS, CCJ: Only show cursor by default if no touchscreen detected
|
||||||
|
Ignore invalid HID devices with bad device path
|
||||||
|
|
||||||
|
12/13/2024 [spice2x]
|
||||||
|
Improve error messages for DLL load failures
|
||||||
|
Load cardio module in spicecfg
|
||||||
|
|
||||||
|
12/06/2024 [spice2x]
|
||||||
|
Clean up seldom used features (VR, Lua scripting, layeredfs, KFControl)
|
||||||
|
New card scanner section in Cards tab
|
||||||
|
Add -scardfix option for converting NFC cards into E00401 format
|
||||||
|
Add system information logging, controlled by -sysdump option
|
||||||
|
|
||||||
|
11/20/2024 [spice2x]
|
||||||
|
DRS: add subscreen overlay window (dance floor tape LED display)
|
||||||
|
IIDX: TDJ cam selection options for users with 3+ cameras
|
||||||
|
(-iidxtdjcamhooktop /-iidxtdjcamhookfront)
|
||||||
|
IIDX/SDVX: move some options to Advanced tab
|
||||||
|
Update -nvprofile to set V-Sync settings as Application Controlled
|
||||||
|
|
||||||
|
10/29/2024 [spice2x]
|
||||||
|
(IIDX31+) apply signature patch to force WASAPI by default; use -iidxsounddevice to override
|
||||||
|
Fix SDVX EG song search when using Japanese touch keyboard (when OS is not ja-JP)
|
||||||
|
Nostalgia I/O improvements
|
||||||
|
Expose DDR Gold cabinet tape LEDs via Spice API
|
||||||
|
|
||||||
|
10/14/2024 [spice2x]
|
||||||
|
Apply patches earlier, on DLL load notification
|
||||||
|
SMX dedicab lights improvements
|
||||||
|
|
||||||
|
10/12/2024 [spice2x]
|
||||||
|
SMX dedicab lights support (requires forked SMX.dll - see Issue #228)
|
||||||
|
Option to show FPS overlay on top left (-fpsflip)
|
||||||
|
Allow TDJ camhook to load without -iidx (for cabs)
|
||||||
|
|
||||||
|
09/21/2024 [spice2x]
|
||||||
|
Add Inject Early DLL Hooks option (-z)
|
||||||
|
|
||||||
|
09/14/2024 [spice2x]
|
||||||
|
Add Patch Manager Config Path (-patchcfgpath) option
|
||||||
|
Vertical/horizontal flip for TDJ cam hook
|
||||||
|
Fix mouse button behavior when left/right buttons are swapped
|
||||||
|
|
||||||
|
08/24/2024 [spice2x]
|
||||||
|
Fix Patch Manager failing to import patches when modules path is Unicode
|
||||||
|
|
||||||
|
08/22/2024 [spice2x]
|
||||||
|
UI update for Card Manager in overlay
|
||||||
|
|
||||||
|
08/12/2024 [spice2x]
|
||||||
|
IIDX TDJ camera - bug fixes
|
||||||
|
Prevent users from accidentally enabling -cfg and -kfcontrol in spicecfg
|
||||||
|
|
||||||
|
08/07/2024 [spice2x]
|
||||||
|
IIDX TDJ camera improvements - draw modes (stretch/crop), bug fixes
|
||||||
|
|
||||||
|
08/06/2024 [spice2x]
|
||||||
|
IIDX TDJ camera improvements
|
||||||
|
Automatic cropping for 16:9 resolutions
|
||||||
|
Toggle to keep or override camera parameters
|
||||||
|
Fix Unicode path handling for config files
|
||||||
|
|
||||||
|
08/03/2024 [spice2x]
|
||||||
|
IIDX TDJ camera improvements
|
||||||
|
Camera control overlay (check Overlay tab)
|
||||||
|
Hardware acceleration for camera rendering
|
||||||
|
IIDX TDJ play record improvements
|
||||||
|
NVENC hooks have been added to fix crash on song start; -nod3d9devhook
|
||||||
|
is no longer required
|
||||||
|
|
||||||
|
07/29/2024 [spice2x]
|
||||||
|
Fix IIDX TDJ not launching in fullscreen with two monitors
|
||||||
|
|
||||||
|
07/28/2024 [spice2x]
|
||||||
|
Add more DLL support for -iidxtdjcamhook
|
||||||
|
Add -iidxtdjcamhookratio and -iidxtdjcamhookoffset
|
||||||
|
|
||||||
|
07/25/2024 [spice2x]
|
||||||
|
Add -iidxtdjcamhook option for webcam support in TDJ
|
||||||
|
|
||||||
|
07/17/2024 [spice2x]
|
||||||
|
Disable touch feedback indicators
|
||||||
|
Bug fixes
|
||||||
|
|
||||||
|
07/15/2024 [spice2x]
|
||||||
|
Fix touch and touch emulation in wintouch-based games (Nostalgia, BeatStream...)
|
||||||
|
Fix misaligned SpiceCompanion touches on windowed TDJ subscreen
|
||||||
|
Improvements to TDJ poke feature
|
||||||
|
|
||||||
|
07/13/2024 [spice2x]
|
||||||
|
Fix windowed TDJ subscreen not accepting mouse clicks after card in
|
||||||
|
Allow windowed TDJ/UFC subscreen to minimize, but not close
|
||||||
|
|
||||||
|
07/10/2024 [spice2x]
|
||||||
|
Better gfdm XG2 and XG3 support
|
||||||
|
IIDX TDJ windowed mode rendering improvements
|
||||||
|
IIDX TDJ subscreen poke feature
|
||||||
|
CardIO NumLock toggle option
|
||||||
|
Patch manager UI tweaks
|
||||||
|
|
||||||
|
07/06/2024 [spice2x]
|
||||||
|
Reliability improvements for config file saving
|
||||||
|
Experimental and incomplete support for gfdm XG3
|
||||||
|
Option to specify path for screen resize config
|
||||||
|
Reflec Beat: fix being unable to type into overlay
|
||||||
|
|
||||||
|
07/03/2024 [spice2x]
|
||||||
|
Fix SMX stage compatibility
|
||||||
|
Patch manager: log header in patches JSON, better error handling
|
||||||
|
|
||||||
|
06/26/2024 [spice2x]
|
||||||
|
Fix MDX-003 not retrieving patches from online source
|
||||||
|
|
||||||
|
06/22/2024 [spice2x]
|
||||||
|
Reliability & performance improvements for auto-card-insert
|
||||||
|
Update -sdvxnosub to prevent creation of subscreen in windowed mode
|
||||||
|
Bug fixes
|
||||||
|
|
||||||
|
06/20/2024 [spice2x]
|
||||||
|
Improve experience for windowed SDVX UFC (always launch subscreen window)
|
||||||
|
Add Delay option in analog binds
|
||||||
|
Fix pop'n soft-lock with auto card insert
|
||||||
|
Fix -graphics-single-adapter not working in Beatstream/Nostalgia
|
||||||
|
|
||||||
|
06/14/2024 [spice2x]
|
||||||
|
Improve experience for touch-enabled games in windowed mode (SpiceTouch)
|
||||||
|
|
||||||
|
06/08/2024 [spice2x]
|
||||||
|
Patch manager bug fixes
|
||||||
|
|
||||||
|
06/03/2024 [spice2x]
|
||||||
|
Fix patch status not being saved properly
|
||||||
|
Search tab for finding options
|
||||||
|
|
||||||
|
06/02/2024 [spice2x]
|
||||||
|
Fix BBC and Museca hang on boot when COM ports are present
|
||||||
|
Deprecate -iidxtdjw (use -iidxtdj and -w together instead)
|
||||||
|
|
||||||
|
05/31/2024 [spice2x]
|
||||||
|
Redesign patches tab
|
||||||
|
Bug fixes for patches.json parsing
|
||||||
|
|
||||||
|
05/29/2024 [spice2x]
|
||||||
|
Add support for "number" patch type
|
||||||
|
History for remote patch URLs
|
||||||
|
|
||||||
|
05/28/2024 [spice2x]
|
||||||
|
Update -iidxtdjw to hide useless second window
|
||||||
|
|
||||||
|
05/27/2024 [spice2x]
|
||||||
|
Fix -apiserial crashing when -apiserialbaud is not provided
|
||||||
|
Suppress "failed to acquire subscreen" error when not relevant
|
||||||
|
|
||||||
|
05/22/2024 [spice2x]
|
||||||
|
Add caution string to patches.json format
|
||||||
|
Paste from clipboard button for URL patches import
|
||||||
|
|
||||||
|
05/12/2024 [spice2x]
|
||||||
|
Disable URL patch importing in-game
|
||||||
|
UI tweaks for importing patches
|
||||||
|
|
||||||
|
05/05/2024 [spice2x]
|
||||||
|
UI tweaks for importing patches
|
||||||
|
Add aliases for arguments with -sp2x prefix
|
||||||
|
|
||||||
|
05/04/2024 [spice2x]
|
||||||
|
New patch JSON format, importing patches from URL
|
||||||
|
Add Process Efficiency Class option for hetero CPUs
|
||||||
|
|
||||||
|
04/29/2024 [spice2x]
|
||||||
|
Move -vr to be DANCERUSH only option
|
||||||
|
Fix being unable to type into overlay when -nolegacy is on
|
||||||
|
|
||||||
|
04/08/2024 [spice2x]
|
||||||
|
Fix Discord rich presence app IDs
|
||||||
|
|
||||||
|
03/31/2024 [spice2x]
|
||||||
|
Fix IC CARD UNIT ERROR in UFC when COM ports are present
|
||||||
|
|
||||||
|
03/24/2024 [spice2x]
|
||||||
|
Fix Ongaku Paradise crash on boot due to VFS redirection
|
||||||
|
Address all compiler warnings
|
||||||
|
|
||||||
|
03/17/2024 [spice2x]
|
||||||
|
SMX pad lights output
|
||||||
|
Fix DDR pad input for P4IO / BIO2
|
||||||
|
Option aliases for IIDX/SDVX subscreen disable
|
||||||
|
|
||||||
|
03/16/2024 [spice2x]
|
||||||
|
I/O for DDR white cabinet type (P4IO)
|
||||||
|
Remove background animation from configurator
|
||||||
|
Compiler updates
|
||||||
|
|
||||||
|
03/06/2024 [spice2x]
|
||||||
|
Lights output for DDR gold cabinet type
|
||||||
|
|
||||||
|
02/13/2024 [spice2x]
|
||||||
|
Fix lights not updating over API in configurator
|
||||||
|
CCJ mouse trackball improvements
|
||||||
|
Make IIDX/SDVX native touch the default when -sp2x-nod3d9devhook is on
|
||||||
|
Remove log spam in IIDX
|
||||||
|
|
||||||
|
02/02/2024 [spice2x]
|
||||||
|
Add missing NVCUDA stubs for cuStreamCreate and cuStreamDestroy_v2
|
||||||
|
|
||||||
|
02/01/2024 [spice2x]
|
||||||
|
QuizKnock STADIUM support
|
||||||
|
Busou Shinki analog joystick support
|
||||||
|
|
||||||
|
01/30/2024 [spice2x]
|
||||||
|
Add woofer lights to popn HD mode
|
||||||
|
Prevent crash when both -graphics-force-single-adapter and
|
||||||
|
-sp2x-nod3d9devhook are enabled
|
||||||
|
|
||||||
|
01/27/2024 [spice2x]
|
||||||
|
Add Disable D3D9 Device Hook option (-sp2x-nod3d9devhook)
|
||||||
|
|
||||||
|
01/20/2024 [spice2x]
|
||||||
|
Force Exit overlay hotkey
|
||||||
|
Improve Low Latency Audio to work with more games
|
||||||
|
Charge Machine I/O fixes
|
||||||
|
UI tweaks (API tab, Development tab)
|
||||||
|
|
||||||
|
01/07/2024 [spice2x]
|
||||||
|
Chase Chase Jokers improvements (trackball and vsync fix)
|
||||||
|
|
||||||
|
01/06/2024 [spice2x]
|
||||||
|
Chase Chase Jokers improvements (cmd line args, trackball sensitivity)
|
||||||
|
|
||||||
|
01/05/2024 [spice2x]
|
||||||
|
Chase Chase Jokers support
|
||||||
|
|
||||||
|
01/01/2024 [spice2x]
|
||||||
|
UI tweaks - menu bar in configurator window
|
||||||
|
IIDX: scan for SOUND_OUTPUT_DEVICE in binary and log message
|
||||||
|
Switch from -Ofast to -O2
|
||||||
|
Remove ImGui demo and debug files from release (reduced binary size)
|
||||||
|
|
||||||
|
12/30/2023 [spice2x]
|
||||||
|
Add NVAPI Block option (-sp2x-nonvapi)
|
||||||
|
SDVX: Auto Card Insert disables itself after a timeout to prevent soft lock
|
||||||
|
|
||||||
|
12/27/2023 [spice2x]
|
||||||
|
Prevent SDVX from dumping PATH variable to log
|
||||||
|
Stubs for NVIDIA DLLs (nvcuda.dll, nvcuvid.dll, nvEncodeAPI64.dll)
|
||||||
|
UI tweaks
|
||||||
|
|
||||||
|
12/25/2023 [spice2x]
|
||||||
|
Fix Lock Cursor option not updating capture area in windowed mode
|
||||||
|
Update TDJ rom file hooks
|
||||||
|
|
||||||
|
12/23/2023 [spice2x]
|
||||||
|
Remove the need for hex edits to fix note scroll speed in SDVX VM on NVIDIA
|
||||||
|
Improvements to -graphics-force-refresh
|
||||||
|
|
||||||
|
12/22/2023 [spice2x]
|
||||||
|
HID analog relative axis mode
|
||||||
|
Automatic process affinity fix for Gitadora
|
||||||
|
Fix -cfgpath option not working
|
||||||
|
Buttons tab UI fix for Bind Many
|
||||||
|
|
||||||
|
12/18/2023 [spice2x]
|
||||||
|
Fix Road Fighters 3D I/O error on boot
|
||||||
|
|
||||||
|
12/17/2023 [spice2x]
|
||||||
|
Integer multiplier / divisor for HID analog
|
||||||
|
(alternative to existing sensitivity option)
|
||||||
|
|
||||||
|
12/15/2023 [spice2x]
|
||||||
|
Add hooks to prevent display scaling changes when SDVX launches
|
||||||
|
|
||||||
|
12/12/2023 [spice2x]
|
||||||
|
Add support for keypad in SDVX UFC/VM mode
|
||||||
|
New DX9on12 flag with more options (-sp2x-dx9on12, replaces -9on12)
|
||||||
|
|
||||||
|
12/11/2023 [spice2x]
|
||||||
|
Fix crash at launch on AMD/Intel GPUs when nvapi DLL is present
|
||||||
|
|
||||||
|
12/09/2023 [spice2x]
|
||||||
|
Lights output for Gitadora
|
||||||
|
Lights output for DRS
|
||||||
|
Tape LED averaging algorithm option (-sp2x-tapeledalgo)
|
||||||
|
Fix occasional crash on shutdown
|
||||||
|
|
||||||
|
11/23/2023 [spice2x]
|
||||||
|
Low latency shared audio option (-sp2x-lowlatencysharedaudio)
|
||||||
|
Automatic dev/raw/* folder creation for popn19-21
|
||||||
|
Move overlay bindings to Overlay tab
|
||||||
|
|
||||||
|
11/17/2023 [spice2x]
|
||||||
|
Use E00401 prefix for card number generation
|
||||||
|
Volume API hooks to prevent audio volume change (enabled by default)
|
||||||
|
Small UI tweaks
|
||||||
|
|
||||||
|
11/15/2023 [spice2x]
|
||||||
|
Automatic card insert option (-sp2x-autocard)
|
||||||
|
Dump CPU features to log on startup
|
||||||
|
|
||||||
|
11/12/2023 [spice2x]
|
||||||
|
Fix crash in some games caused by linker changes in 2022
|
||||||
|
(Gitadora Exchain and older, Bone Eater, etc)
|
||||||
|
Add IIDX native touch option (-sp2x-iidxnativetouch)
|
||||||
|
Fix V-Sync issues with auto-screen-orientation
|
||||||
|
|
||||||
|
11/04/2023 [spice2x]
|
||||||
|
Option for NVIDIA GPU optimization (-sp2x-nvprofile)
|
||||||
|
SmartCard fixes (for -scardflip and -scardtoggle)
|
||||||
|
Small reorganization of options in configurator
|
||||||
|
|
||||||
|
10/30/2023 [spice2x]
|
||||||
|
Add touch input support for DRS
|
||||||
|
Add TDJ Windowed mode for IIDX (-sp2x-iidxtdjw)
|
||||||
|
Fix -iidxasio not working in some versions of IIDX
|
||||||
|
|
||||||
|
10/22/2023 [spice2x]
|
||||||
|
Add E-spec I/O emulation for IIDX 30+
|
||||||
|
Fix IIDX TDJ launching at 60Hz for some users
|
||||||
|
Add workaround for buggy ASIO drivers that lock up on close
|
||||||
|
Hide Insert Card overlay by default, add option to show it again
|
||||||
|
|
||||||
09/29/2023 [spice2x]
|
09/29/2023 [spice2x]
|
||||||
Fix subscreen not updating in certain versions of EG.
|
Fix subscreen not updating in certain versions of EG.
|
||||||
Detect long paths and log a warning message.
|
Detect long paths and log a warning message.
|
||||||
@@ -15,19 +405,19 @@
|
|||||||
Update font for IIDX segment display
|
Update font for IIDX segment display
|
||||||
New option: auto show FPS window
|
New option: auto show FPS window
|
||||||
|
|
||||||
04/16/2023 [spice2x] (beta)
|
04/16/2023 [spice2x]
|
||||||
New feature: window resize. Added new options to change window size and
|
New feature: window resize. Added new options to change window size and
|
||||||
position on launch. Screen Resize window (F11) also updated with new
|
position on launch. Screen Resize window (F11) also updated with new
|
||||||
controls
|
controls
|
||||||
Screen Resize settings are now per-game
|
Screen Resize settings are now per-game
|
||||||
Misc bug fixes
|
Misc bug fixes
|
||||||
|
|
||||||
04/09/2023 [spice2x] (beta)
|
04/09/2023 [spice2x]
|
||||||
Add IIDX LED ticker (segment display) as subscreen overlay for LDJ
|
Add IIDX LED ticker (segment display) as subscreen overlay for LDJ
|
||||||
Add I/O panel window for all games, special support for IIDX, DDR, GFDM
|
Add I/O panel window for all games, special support for IIDX, DDR, GFDM
|
||||||
Add options to automatically show certain windows on game launch
|
Add options to automatically show certain windows on game launch
|
||||||
|
|
||||||
04/03/2023 [spice2x] (beta)
|
04/03/2023 [spice2x]
|
||||||
Move/resize for IIDX/SDVX subscreen overlay window
|
Move/resize for IIDX/SDVX subscreen overlay window
|
||||||
New options to control subscreen overlay window
|
New options to control subscreen overlay window
|
||||||
Turn common config mistakes into fatal error messages
|
Turn common config mistakes into fatal error messages
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
# Hidden build all temporary environment for sourcing
|
# Hidden build all temporary environment for sourcing
|
||||||
<<__BUILDALLINIT__
|
<<__BUILDALLINIT__
|
||||||
# Auto-config for build_al.sh
|
# Auto-config for build_all.sh
|
||||||
GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2> /dev/null || echo "none")
|
GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2> /dev/null || echo "none")
|
||||||
GIT_HEAD=$(git rev-parse --short HEAD || echo "none")
|
GIT_HEAD=$(git rev-parse --short HEAD || echo "none")
|
||||||
BUILD_TYPE=$({ $_G_debug && echo Debug; } || echo Release)
|
BUILD_TYPE=$({ $_G_debug && echo Debug; } || echo Release)
|
||||||
@@ -16,6 +16,7 @@ DIST_NAME="${GIT_BRANCH}-${GIT_HEAD}.zip"
|
|||||||
DIST_COMMENT="$(date +%Y)/$(date +%m)/$(date +%d):$(git rev-parse HEAD)"
|
DIST_COMMENT="$(date +%Y)/$(date +%m)/$(date +%d):$(git rev-parse HEAD)"
|
||||||
: ${DIST_ENABLE:=$({ $_G_debug && echo 0; } || echo 1)}
|
: ${DIST_ENABLE:=$({ $_G_debug && echo 0; } || echo 1)}
|
||||||
UPX_ENABLE="$DIST_ENABLE"
|
UPX_ENABLE="$DIST_ENABLE"
|
||||||
|
IGNORE_CACHE=0
|
||||||
INCLUDE_SRC=0
|
INCLUDE_SRC=0
|
||||||
UPX_FLAGS="-q --best --lzma --compress-exports=0"
|
UPX_FLAGS="-q --best --lzma --compress-exports=0"
|
||||||
CLEAN_BUILD=$({ $_G_clean && echo 1; } || echo 0)
|
CLEAN_BUILD=$({ $_G_clean && echo 1; } || echo 0)
|
||||||
@@ -29,12 +30,14 @@ BUILDDIR_64="$_G_buildir/x64/${BUILD_TYPE}"
|
|||||||
__BUILDALLINIT__
|
__BUILDALLINIT__
|
||||||
|
|
||||||
run_build_all() {
|
run_build_all() {
|
||||||
|
DIST_ENABLE=0
|
||||||
|
|
||||||
# Init build_all.sh
|
# Init build_all.sh
|
||||||
source <(sed -n '/__BUILDALLINIT__/{:a;n;/__BUILDALLINIT__/q;p;$!ba}' "$0")
|
source <(sed -n '/__BUILDALLINIT__/{:a;n;/__BUILDALLINIT__/q;p;$!ba}' "$0")
|
||||||
source <(head -n +20 ./build_all.sh)
|
source <(head -n +20 ./build_all.sh)
|
||||||
|
|
||||||
# Run build_all.sh
|
# Run build_all.sh
|
||||||
source <(tail -n +59 ./build_all.sh | head -n -3 | sed 's~.*pushd ${OUTDIR}/.. > /dev/null*~\tpushd ${OUTDIR} > /dev/null~')
|
source <(tail -n +78 ./build_all.sh | head -n -3 | sed -e 's~.*pushd ${OUTDIR}/.. > /dev/null*~\tpushd ${OUTDIR} > /dev/null~' -e 's~mkdir -p ${OUTDIR}/src~~')
|
||||||
}
|
}
|
||||||
|
|
||||||
run_deploy_all() {
|
run_deploy_all() {
|
||||||
@@ -46,7 +49,7 @@ run_deploy_all() {
|
|||||||
|
|
||||||
# Run deploy in build_all.sh
|
# Run deploy in build_all.sh
|
||||||
set +e
|
set +e
|
||||||
source <(tail -n +150 ./build_all.sh | head -n -3 | sed 's~.*pushd ${OUTDIR}/.. > /dev/null*~\tpushd ${OUTDIR} > /dev/null~')
|
source <(tail -n +180 ./build_all.sh | head -n -3 | sed -e 's~.*pushd ${OUTDIR}/.. > /dev/null*~\tpushd ${OUTDIR} > /dev/null~' -e 's~mkdir -p ${OUTDIR}/src~~')
|
||||||
}
|
}
|
||||||
|
|
||||||
run_distribute_all() {
|
run_distribute_all() {
|
||||||
@@ -55,7 +58,7 @@ run_distribute_all() {
|
|||||||
source <(head -n +20 ./build_all.sh)
|
source <(head -n +20 ./build_all.sh)
|
||||||
|
|
||||||
# Run deploy in build_all.sh
|
# Run deploy in build_all.sh
|
||||||
source <(tail -n +150 ./build_all.sh | head -n -3 | sed 's~.*pushd ${OUTDIR}/.. > /dev/null*~\tpushd ${OUTDIR} > /dev/null~')
|
source <(tail -n +180 ./build_all.sh | head -n -3 | sed -e 's~.*pushd ${OUTDIR}/.. > /dev/null*~\tpushd ${OUTDIR} > /dev/null~' -e 's~mkdir -p ${OUTDIR}/src~~')
|
||||||
}
|
}
|
||||||
|
|
||||||
run_clion_init() {
|
run_clion_init() {
|
||||||
@@ -67,7 +70,7 @@ run_clion_init() {
|
|||||||
|
|
||||||
# Sanity checks
|
# Sanity checks
|
||||||
[ -d "external/cmake-various/toolchain" ] || { echo "Toolchain not found" ; exit 1; }
|
[ -d "external/cmake-various/toolchain" ] || { echo "Toolchain not found" ; exit 1; }
|
||||||
[ "$(md5sum ./build_all.sh | cut -c -32)" = "9a89bba3fa2435983e5bce423d0f4a61" ] || { echo "Version mismatch for build_all.sh " ; exit 1; }
|
[ "$(md5sum ./build_all.sh | cut -c -32)" = "a0665866b9aa2a11606cb4765eed97d9" ] || { echo "Version mismatch for build_all.sh " ; exit 1; }
|
||||||
|
|
||||||
# Run requested task
|
# Run requested task
|
||||||
if [[ $(type -t "run_${1}_${2}") == function ]]; then
|
if [[ $(type -t "run_${1}_${2}") == function ]]; then
|
||||||
|
|||||||
@@ -388,6 +388,9 @@ static void easrv_worker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void easrv_start(unsigned short port, bool maintenance, int backlog, int thread_count) {
|
void easrv_start(unsigned short port, bool maintenance, int backlog, int thread_count) {
|
||||||
|
if (avs::game::is_model("UJK")) {
|
||||||
|
log_fatal("easrv", "easrv is currently non-functional for Chase Chase Jokers; turn off -ea");
|
||||||
|
}
|
||||||
|
|
||||||
// WSA startup
|
// WSA startup
|
||||||
WSADATA wsa_data;
|
WSADATA wsa_data;
|
||||||
|
|||||||
Vendored
-8614
File diff suppressed because it is too large
Load Diff
Vendored
+11
-1
@@ -7,6 +7,7 @@
|
|||||||
#include "cardio_window.h"
|
#include "cardio_window.h"
|
||||||
|
|
||||||
bool CARDIO_RUNNER_FLIP = false;
|
bool CARDIO_RUNNER_FLIP = false;
|
||||||
|
bool CARDIO_RUNNER_TOGGLE = false;
|
||||||
static bool CARDIO_RUNNER_INITIALIZED = false;
|
static bool CARDIO_RUNNER_INITIALIZED = false;
|
||||||
static std::thread* CARDIO_RUNNER_THREAD = nullptr;
|
static std::thread* CARDIO_RUNNER_THREAD = nullptr;
|
||||||
static HWND CARDIO_RUNNER_HWND = NULL;
|
static HWND CARDIO_RUNNER_HWND = NULL;
|
||||||
@@ -71,8 +72,17 @@ void cardio_runner_start(bool scan_hid) {
|
|||||||
// if card not empty
|
// if card not empty
|
||||||
if (*((uint64_t*) &device->usage_value[0]) > 0) {
|
if (*((uint64_t*) &device->usage_value[0]) > 0) {
|
||||||
|
|
||||||
|
bool flip_order = CARDIO_RUNNER_FLIP;
|
||||||
|
if (CARDIO_RUNNER_FLIP) {
|
||||||
|
log_info("cardio", "Flip order of readers since flip option is set");
|
||||||
|
}
|
||||||
|
if (CARDIO_RUNNER_TOGGLE && (GetKeyState(VK_NUMLOCK) & 1) > 0) {
|
||||||
|
log_info("cardio", "Flip order of readers since Num Lock is on");
|
||||||
|
flip_order = !flip_order;
|
||||||
|
}
|
||||||
|
|
||||||
// insert card
|
// insert card
|
||||||
if (CARDIO_RUNNER_FLIP)
|
if (flip_order)
|
||||||
eamuse_card_insert((int) (device_no + 1) & 1, &device->usage_value[0]);
|
eamuse_card_insert((int) (device_no + 1) & 1, &device->usage_value[0]);
|
||||||
else
|
else
|
||||||
eamuse_card_insert((int) device_no & 1, &device->usage_value[0]);
|
eamuse_card_insert((int) device_no & 1, &device->usage_value[0]);
|
||||||
|
|||||||
Vendored
+1
@@ -2,6 +2,7 @@
|
|||||||
#define SPICETOOLS_CARDIO_RUNNER_H
|
#define SPICETOOLS_CARDIO_RUNNER_H
|
||||||
|
|
||||||
extern bool CARDIO_RUNNER_FLIP;
|
extern bool CARDIO_RUNNER_FLIP;
|
||||||
|
extern bool CARDIO_RUNNER_TOGGLE;
|
||||||
|
|
||||||
void cardio_runner_start(bool scan_hid);
|
void cardio_runner_start(bool scan_hid);
|
||||||
void cardio_runner_stop();
|
void cardio_runner_stop();
|
||||||
|
|||||||
Vendored
+4
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
BasedOnStyle: Google
|
||||||
|
...
|
||||||
Vendored
+36
@@ -0,0 +1,36 @@
|
|||||||
|
# Project Files unneeded by docker
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
.github
|
||||||
|
.dockerignore
|
||||||
|
.clang-format
|
||||||
|
appveyor.yml
|
||||||
|
.travis.yml
|
||||||
|
AUTHORS
|
||||||
|
CONTRIBUTING.md
|
||||||
|
CONTRIBUTORS
|
||||||
|
LICENSE
|
||||||
|
README.md
|
||||||
|
|
||||||
|
bazel/ci/Makefile
|
||||||
|
bazel/ci/docker
|
||||||
|
bazel/ci/doc
|
||||||
|
|
||||||
|
cmake/ci/Makefile
|
||||||
|
cmake/ci/docker
|
||||||
|
cmake/ci/doc
|
||||||
|
cmake/ci/cache
|
||||||
|
|
||||||
|
build/
|
||||||
|
cmake_build/
|
||||||
|
build_cross/
|
||||||
|
cmake-build-*/
|
||||||
|
out/
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.idea/
|
||||||
|
.vagrant/
|
||||||
|
.vscode/
|
||||||
|
.vs/
|
||||||
|
*.user
|
||||||
|
*.swp
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# Build folders
|
||||||
|
build/
|
||||||
|
cmake_build/
|
||||||
|
build_cross/
|
||||||
|
cmake-build-*/
|
||||||
|
out/
|
||||||
|
|
||||||
|
# IDEs / CI temp files
|
||||||
|
.idea/
|
||||||
|
.vagrant/
|
||||||
|
.vscode/
|
||||||
|
.vs/
|
||||||
|
*.swp
|
||||||
|
|
||||||
|
# Bazel artifacts
|
||||||
|
**/bazel-*
|
||||||
|
|
||||||
|
# Per-user bazelrc files
|
||||||
|
user.bazelrc
|
||||||
Vendored
+21
@@ -0,0 +1,21 @@
|
|||||||
|
---
|
||||||
|
dataSource: "prs"
|
||||||
|
ignoreLabels:
|
||||||
|
- "Apple M1"
|
||||||
|
- "duplicate"
|
||||||
|
- "help wanted"
|
||||||
|
- "invalid"
|
||||||
|
- "question"
|
||||||
|
- "wontfix"
|
||||||
|
onlyMilestones: false
|
||||||
|
groupBy:
|
||||||
|
"API Change":
|
||||||
|
- "API Change"
|
||||||
|
"New features / Enhancements":
|
||||||
|
- "enhancement"
|
||||||
|
- "internal"
|
||||||
|
"Bug Fixes":
|
||||||
|
- "bug"
|
||||||
|
"Misc":
|
||||||
|
- "misc"
|
||||||
|
changelogFilename: "CHANGELOG.md"
|
||||||
Vendored
+378
@@ -0,0 +1,378 @@
|
|||||||
|
# cpu_features, a cross platform C99 library to get cpu features at runtime.
|
||||||
|
|
||||||
|
load("@bazel_skylib//lib:selects.bzl", "selects")
|
||||||
|
load("//:bazel/platforms.bzl", "PLATFORM_CPU_ARM", "PLATFORM_CPU_ARM64", "PLATFORM_CPU_MIPS", "PLATFORM_CPU_PPC", "PLATFORM_CPU_RISCV32", "PLATFORM_CPU_RISCV64", "PLATFORM_CPU_X86_64")
|
||||||
|
load("//:bazel/platforms.bzl", "PLATFORM_OS_MACOS")
|
||||||
|
|
||||||
|
package(
|
||||||
|
default_visibility = ["//visibility:public"],
|
||||||
|
licenses = ["notice"],
|
||||||
|
)
|
||||||
|
|
||||||
|
exports_files(["LICENSE"])
|
||||||
|
|
||||||
|
INCLUDES = ["include"]
|
||||||
|
|
||||||
|
C99_FLAGS = [
|
||||||
|
"-std=c99",
|
||||||
|
"-Wall",
|
||||||
|
"-Wextra",
|
||||||
|
"-Wmissing-declarations",
|
||||||
|
"-Wmissing-prototypes",
|
||||||
|
"-Wno-implicit-fallthrough",
|
||||||
|
"-Wno-unused-function",
|
||||||
|
"-Wold-style-definition",
|
||||||
|
"-Wshadow",
|
||||||
|
"-Wsign-compare",
|
||||||
|
"-Wstrict-prototypes",
|
||||||
|
]
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "cpu_features_macros",
|
||||||
|
copts = C99_FLAGS,
|
||||||
|
includes = INCLUDES,
|
||||||
|
textual_hdrs = ["include/cpu_features_macros.h"],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "cpu_features_cache_info",
|
||||||
|
copts = C99_FLAGS,
|
||||||
|
includes = INCLUDES,
|
||||||
|
textual_hdrs = ["include/cpu_features_cache_info.h"],
|
||||||
|
deps = [":cpu_features_macros"],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "bit_utils",
|
||||||
|
copts = C99_FLAGS,
|
||||||
|
includes = INCLUDES,
|
||||||
|
textual_hdrs = ["include/internal/bit_utils.h"],
|
||||||
|
deps = [":cpu_features_macros"],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_test(
|
||||||
|
name = "bit_utils_test",
|
||||||
|
srcs = ["test/bit_utils_test.cc"],
|
||||||
|
includes = INCLUDES,
|
||||||
|
deps = [
|
||||||
|
":bit_utils",
|
||||||
|
"@com_google_googletest//:gtest_main",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "memory_utils",
|
||||||
|
copts = C99_FLAGS,
|
||||||
|
includes = INCLUDES,
|
||||||
|
textual_hdrs = [
|
||||||
|
"src/copy.inl",
|
||||||
|
"src/equals.inl",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "string_view",
|
||||||
|
srcs = [
|
||||||
|
"src/string_view.c",
|
||||||
|
],
|
||||||
|
copts = C99_FLAGS,
|
||||||
|
includes = INCLUDES,
|
||||||
|
textual_hdrs = ["include/internal/string_view.h"],
|
||||||
|
deps = [
|
||||||
|
":cpu_features_macros",
|
||||||
|
":memory_utils",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_test(
|
||||||
|
name = "string_view_test",
|
||||||
|
srcs = ["test/string_view_test.cc"],
|
||||||
|
includes = INCLUDES,
|
||||||
|
deps = [
|
||||||
|
":string_view",
|
||||||
|
"@com_google_googletest//:gtest_main",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "filesystem",
|
||||||
|
srcs = ["src/filesystem.c"],
|
||||||
|
copts = C99_FLAGS,
|
||||||
|
includes = INCLUDES,
|
||||||
|
textual_hdrs = ["include/internal/filesystem.h"],
|
||||||
|
deps = [":cpu_features_macros"],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "filesystem_for_testing",
|
||||||
|
testonly = 1,
|
||||||
|
srcs = [
|
||||||
|
"src/filesystem.c",
|
||||||
|
"test/filesystem_for_testing.cc",
|
||||||
|
],
|
||||||
|
hdrs = [
|
||||||
|
"include/internal/filesystem.h",
|
||||||
|
"test/filesystem_for_testing.h",
|
||||||
|
],
|
||||||
|
defines = ["CPU_FEATURES_MOCK_FILESYSTEM"],
|
||||||
|
includes = INCLUDES,
|
||||||
|
deps = [
|
||||||
|
":cpu_features_macros",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "stack_line_reader",
|
||||||
|
srcs = ["src/stack_line_reader.c"],
|
||||||
|
copts = C99_FLAGS,
|
||||||
|
defines = ["STACK_LINE_READER_BUFFER_SIZE=1024"],
|
||||||
|
includes = INCLUDES,
|
||||||
|
textual_hdrs = ["include/internal/stack_line_reader.h"],
|
||||||
|
deps = [
|
||||||
|
":cpu_features_macros",
|
||||||
|
":filesystem",
|
||||||
|
":string_view",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_test(
|
||||||
|
name = "stack_line_reader_test",
|
||||||
|
srcs = [
|
||||||
|
"include/internal/stack_line_reader.h",
|
||||||
|
"src/stack_line_reader.c",
|
||||||
|
"test/stack_line_reader_test.cc",
|
||||||
|
],
|
||||||
|
defines = ["STACK_LINE_READER_BUFFER_SIZE=16"],
|
||||||
|
includes = INCLUDES,
|
||||||
|
deps = [
|
||||||
|
":cpu_features_macros",
|
||||||
|
":filesystem_for_testing",
|
||||||
|
":string_view",
|
||||||
|
"@com_google_googletest//:gtest_main",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "stack_line_reader_to_use_with_filesystem_for_testing",
|
||||||
|
testonly = 1,
|
||||||
|
srcs = ["src/stack_line_reader.c"],
|
||||||
|
hdrs = ["include/internal/stack_line_reader.h"],
|
||||||
|
copts = C99_FLAGS,
|
||||||
|
defines = ["STACK_LINE_READER_BUFFER_SIZE=1024"],
|
||||||
|
includes = INCLUDES,
|
||||||
|
deps = [
|
||||||
|
":cpu_features_macros",
|
||||||
|
":filesystem_for_testing",
|
||||||
|
":string_view",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "hwcaps",
|
||||||
|
srcs = ["src/hwcaps.c"],
|
||||||
|
copts = C99_FLAGS,
|
||||||
|
defines = selects.with_or({
|
||||||
|
PLATFORM_OS_MACOS: ["HAVE_DLFCN_H"],
|
||||||
|
"//conditions:default": ["HAVE_STRONG_GETAUXVAL"],
|
||||||
|
}),
|
||||||
|
includes = INCLUDES,
|
||||||
|
textual_hdrs = ["include/internal/hwcaps.h"],
|
||||||
|
deps = [
|
||||||
|
":cpu_features_macros",
|
||||||
|
":filesystem",
|
||||||
|
":string_view",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "hwcaps_for_testing",
|
||||||
|
testonly = 1,
|
||||||
|
srcs = [
|
||||||
|
"src/hwcaps.c",
|
||||||
|
"test/hwcaps_for_testing.cc",
|
||||||
|
],
|
||||||
|
hdrs = [
|
||||||
|
"include/internal/hwcaps.h",
|
||||||
|
"test/hwcaps_for_testing.h",
|
||||||
|
],
|
||||||
|
defines = [
|
||||||
|
"CPU_FEATURES_MOCK_GET_ELF_HWCAP_FROM_GETAUXVAL",
|
||||||
|
"CPU_FEATURES_TEST",
|
||||||
|
],
|
||||||
|
includes = INCLUDES,
|
||||||
|
deps = [
|
||||||
|
":cpu_features_macros",
|
||||||
|
":filesystem_for_testing",
|
||||||
|
":string_view",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "cpuinfo",
|
||||||
|
srcs = selects.with_or({
|
||||||
|
PLATFORM_CPU_X86_64: [
|
||||||
|
"src/impl_x86_freebsd.c",
|
||||||
|
"src/impl_x86_linux_or_android.c",
|
||||||
|
"src/impl_x86_macos.c",
|
||||||
|
"src/impl_x86_windows.c",
|
||||||
|
],
|
||||||
|
PLATFORM_CPU_ARM: ["src/impl_arm_linux_or_android.c"],
|
||||||
|
PLATFORM_CPU_ARM64: [
|
||||||
|
"src/impl_aarch64_linux_or_android.c",
|
||||||
|
"src/impl_aarch64_macos_or_iphone.c",
|
||||||
|
"src/impl_aarch64_windows.c",
|
||||||
|
],
|
||||||
|
PLATFORM_CPU_MIPS: ["src/impl_mips_linux_or_android.c"],
|
||||||
|
PLATFORM_CPU_PPC: ["src/impl_ppc_linux.c"],
|
||||||
|
PLATFORM_CPU_RISCV32: ["src/impl_riscv_linux.c"],
|
||||||
|
PLATFORM_CPU_RISCV64: ["src/impl_riscv_linux.c"],
|
||||||
|
}),
|
||||||
|
hdrs = selects.with_or({
|
||||||
|
PLATFORM_CPU_X86_64: [
|
||||||
|
"include/cpuinfo_x86.h",
|
||||||
|
"include/internal/cpuid_x86.h",
|
||||||
|
"include/internal/windows_utils.h",
|
||||||
|
],
|
||||||
|
PLATFORM_CPU_ARM: ["include/cpuinfo_arm.h"],
|
||||||
|
PLATFORM_CPU_ARM64: ["include/cpuinfo_aarch64.h"],
|
||||||
|
PLATFORM_CPU_MIPS: ["include/cpuinfo_mips.h"],
|
||||||
|
PLATFORM_CPU_PPC: ["include/cpuinfo_ppc.h"],
|
||||||
|
PLATFORM_CPU_RISCV32: ["include/cpuinfo_riscv.h"],
|
||||||
|
PLATFORM_CPU_RISCV64: ["include/cpuinfo_riscv.h"],
|
||||||
|
}),
|
||||||
|
copts = C99_FLAGS,
|
||||||
|
defines = selects.with_or({
|
||||||
|
PLATFORM_OS_MACOS: ["HAVE_SYSCTLBYNAME"],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
|
includes = INCLUDES,
|
||||||
|
textual_hdrs = selects.with_or({
|
||||||
|
PLATFORM_CPU_X86_64: ["src/impl_x86__base_implementation.inl"],
|
||||||
|
PLATFORM_CPU_ARM64: ["src/impl_aarch64__base_implementation.inl"],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}) + [
|
||||||
|
"src/define_introspection.inl",
|
||||||
|
"src/define_introspection_and_hwcaps.inl",
|
||||||
|
],
|
||||||
|
deps = [
|
||||||
|
":bit_utils",
|
||||||
|
":cpu_features_cache_info",
|
||||||
|
":cpu_features_macros",
|
||||||
|
":filesystem",
|
||||||
|
":hwcaps",
|
||||||
|
":memory_utils",
|
||||||
|
":stack_line_reader",
|
||||||
|
":string_view",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "cpuinfo_for_testing",
|
||||||
|
testonly = 1,
|
||||||
|
srcs = selects.with_or({
|
||||||
|
PLATFORM_CPU_X86_64: [
|
||||||
|
"src/impl_x86_freebsd.c",
|
||||||
|
"src/impl_x86_linux_or_android.c",
|
||||||
|
"src/impl_x86_macos.c",
|
||||||
|
"src/impl_x86_windows.c",
|
||||||
|
],
|
||||||
|
PLATFORM_CPU_ARM: ["src/impl_arm_linux_or_android.c"],
|
||||||
|
PLATFORM_CPU_ARM64: [
|
||||||
|
"src/impl_aarch64_linux_or_android.c",
|
||||||
|
"src/impl_aarch64_macos_or_iphone.c",
|
||||||
|
"src/impl_aarch64_windows.c",
|
||||||
|
],
|
||||||
|
PLATFORM_CPU_MIPS: ["src/impl_mips_linux_or_android.c"],
|
||||||
|
PLATFORM_CPU_PPC: ["src/impl_ppc_linux.c"],
|
||||||
|
PLATFORM_CPU_RISCV32: ["src/impl_riscv_linux.c"],
|
||||||
|
PLATFORM_CPU_RISCV64: ["src/impl_riscv_linux.c"],
|
||||||
|
}),
|
||||||
|
hdrs = selects.with_or({
|
||||||
|
PLATFORM_CPU_X86_64: [
|
||||||
|
"include/cpuinfo_x86.h",
|
||||||
|
"include/internal/cpuid_x86.h",
|
||||||
|
"include/internal/windows_utils.h",
|
||||||
|
],
|
||||||
|
PLATFORM_CPU_ARM: ["include/cpuinfo_arm.h"],
|
||||||
|
PLATFORM_CPU_ARM64: ["include/cpuinfo_aarch64.h"],
|
||||||
|
PLATFORM_CPU_MIPS: ["include/cpuinfo_mips.h"],
|
||||||
|
PLATFORM_CPU_PPC: ["include/cpuinfo_ppc.h"],
|
||||||
|
PLATFORM_CPU_RISCV32: ["include/cpuinfo_riscv.h"],
|
||||||
|
PLATFORM_CPU_RISCV64: ["include/cpuinfo_riscv.h"],
|
||||||
|
}),
|
||||||
|
copts = C99_FLAGS,
|
||||||
|
defines = selects.with_or({
|
||||||
|
PLATFORM_CPU_X86_64: ["CPU_FEATURES_MOCK_CPUID_X86"],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}) + selects.with_or({
|
||||||
|
PLATFORM_OS_MACOS: ["HAVE_SYSCTLBYNAME"],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}),
|
||||||
|
includes = INCLUDES,
|
||||||
|
textual_hdrs = selects.with_or({
|
||||||
|
PLATFORM_CPU_X86_64: ["src/impl_x86__base_implementation.inl"],
|
||||||
|
PLATFORM_CPU_ARM64: ["src/impl_aarch64__base_implementation.inl"],
|
||||||
|
"//conditions:default": [],
|
||||||
|
}) + [
|
||||||
|
"src/define_introspection.inl",
|
||||||
|
"src/define_introspection_and_hwcaps.inl",
|
||||||
|
],
|
||||||
|
deps = [
|
||||||
|
":bit_utils",
|
||||||
|
":cpu_features_cache_info",
|
||||||
|
":cpu_features_macros",
|
||||||
|
":filesystem_for_testing",
|
||||||
|
":hwcaps_for_testing",
|
||||||
|
":memory_utils",
|
||||||
|
":stack_line_reader_to_use_with_filesystem_for_testing",
|
||||||
|
":string_view",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_test(
|
||||||
|
name = "cpuinfo_test",
|
||||||
|
srcs = selects.with_or({
|
||||||
|
PLATFORM_CPU_ARM64: ["test/cpuinfo_aarch64_test.cc"],
|
||||||
|
PLATFORM_CPU_ARM: ["test/cpuinfo_arm_test.cc"],
|
||||||
|
PLATFORM_CPU_MIPS: ["test/cpuinfo_mips_test.cc"],
|
||||||
|
PLATFORM_CPU_PPC: ["test/cpuinfo_ppc_test.cc"],
|
||||||
|
PLATFORM_CPU_RISCV32: ["test/cpuinfo_riscv_test.cc"],
|
||||||
|
PLATFORM_CPU_RISCV64: ["test/cpuinfo_riscv_test.cc"],
|
||||||
|
PLATFORM_CPU_X86_64: ["test/cpuinfo_x86_test.cc"],
|
||||||
|
}),
|
||||||
|
includes = INCLUDES,
|
||||||
|
deps = [
|
||||||
|
":cpuinfo_for_testing",
|
||||||
|
":filesystem_for_testing",
|
||||||
|
":hwcaps_for_testing",
|
||||||
|
":string_view",
|
||||||
|
"@com_google_googletest//:gtest_main",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_binary(
|
||||||
|
name = "list_cpu_features",
|
||||||
|
srcs = ["src/utils/list_cpu_features.c"],
|
||||||
|
copts = C99_FLAGS,
|
||||||
|
includes = INCLUDES,
|
||||||
|
deps = [
|
||||||
|
":bit_utils",
|
||||||
|
":cpu_features_macros",
|
||||||
|
":cpuinfo",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "ndk_compat",
|
||||||
|
srcs = ["ndk_compat/cpu-features.c"],
|
||||||
|
copts = C99_FLAGS,
|
||||||
|
includes = INCLUDES + ["ndk_compat"],
|
||||||
|
textual_hdrs = ["ndk_compat/cpu-features.h"],
|
||||||
|
deps = [
|
||||||
|
":cpu_features_macros",
|
||||||
|
":cpuinfo",
|
||||||
|
":filesystem",
|
||||||
|
":stack_line_reader",
|
||||||
|
":string_view",
|
||||||
|
],
|
||||||
|
)
|
||||||
Vendored
+302
@@ -0,0 +1,302 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
|
# option() honors normal variables.
|
||||||
|
# see: https://cmake.org/cmake/help/git-stage/policy/CMP0077.html
|
||||||
|
if(POLICY CMP0077)
|
||||||
|
cmake_policy(SET CMP0077 NEW)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
project(CpuFeatures VERSION 0.9.0 LANGUAGES C)
|
||||||
|
|
||||||
|
set(CMAKE_C_STANDARD 99)
|
||||||
|
|
||||||
|
# when cpu_features is included as subproject (i.e. using add_subdirectory(cpu_features))
|
||||||
|
# in the source tree of a project that uses it, test rules are disabled.
|
||||||
|
if(NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
||||||
|
option(BUILD_TESTING "Enable test rule" OFF)
|
||||||
|
else()
|
||||||
|
option(BUILD_TESTING "Enable test rule" ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Default Build Type to be Release
|
||||||
|
if(NOT CMAKE_BUILD_TYPE)
|
||||||
|
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
|
||||||
|
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
|
||||||
|
FORCE)
|
||||||
|
endif(NOT CMAKE_BUILD_TYPE)
|
||||||
|
|
||||||
|
# An option to enable/disable the executable target list_cpu_features.
|
||||||
|
# Disable it by default if the project is included as a subproject.
|
||||||
|
if(NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
||||||
|
option(BUILD_EXECUTABLE "Build list_cpu_features executable." OFF)
|
||||||
|
else()
|
||||||
|
option(BUILD_EXECUTABLE "Build list_cpu_features executable." ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# An option which allows to switch off install steps. Useful for embedding.
|
||||||
|
# Disable it by default if the project is included as a subproject.
|
||||||
|
if(NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
|
||||||
|
option(ENABLE_INSTALL "Enable install targets" OFF)
|
||||||
|
else()
|
||||||
|
option(ENABLE_INSTALL "Enable install targets" ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to make
|
||||||
|
# it prominent in the GUI.
|
||||||
|
# cpu_features uses bit-fields which are - to some extends - implementation-defined (see https://en.cppreference.com/w/c/language/bit_field).
|
||||||
|
# As a consequence it is discouraged to use cpu_features as a shared library because different compilers may interpret the code in different ways.
|
||||||
|
# Prefer static linking from source whenever possible.
|
||||||
|
option(BUILD_SHARED_LIBS "Build library as shared." OFF)
|
||||||
|
|
||||||
|
# Force PIC on unix when building shared libs
|
||||||
|
# see: https://en.wikipedia.org/wiki/Position-independent_code
|
||||||
|
if(BUILD_SHARED_LIBS AND UNIX)
|
||||||
|
option(CMAKE_POSITION_INDEPENDENT_CODE "Build with Position Independant Code." ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(CheckIncludeFile)
|
||||||
|
include(CheckSymbolExists)
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
macro(setup_include_and_definitions TARGET_NAME)
|
||||||
|
target_include_directories(${TARGET_NAME}
|
||||||
|
PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
|
||||||
|
PRIVATE $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include/internal>
|
||||||
|
)
|
||||||
|
target_compile_definitions(${TARGET_NAME}
|
||||||
|
PUBLIC STACK_LINE_READER_BUFFER_SIZE=1024
|
||||||
|
)
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
set(PROCESSOR_IS_MIPS FALSE)
|
||||||
|
set(PROCESSOR_IS_ARM FALSE)
|
||||||
|
set(PROCESSOR_IS_AARCH64 FALSE)
|
||||||
|
set(PROCESSOR_IS_X86 FALSE)
|
||||||
|
set(PROCESSOR_IS_POWER FALSE)
|
||||||
|
set(PROCESSOR_IS_S390X FALSE)
|
||||||
|
set(PROCESSOR_IS_RISCV FALSE)
|
||||||
|
set(PROCESSOR_IS_LOONGARCH FALSE)
|
||||||
|
|
||||||
|
if(CMAKE_SYSTEM_PROCESSOR MATCHES "^mips")
|
||||||
|
set(PROCESSOR_IS_MIPS TRUE)
|
||||||
|
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(^aarch64)|(^arm64)|(^ARM64)")
|
||||||
|
set(PROCESSOR_IS_AARCH64 TRUE)
|
||||||
|
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
|
||||||
|
set(PROCESSOR_IS_ARM TRUE)
|
||||||
|
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(x86_64)|(AMD64|amd64)|(^i.86$)")
|
||||||
|
set(PROCESSOR_IS_X86 TRUE)
|
||||||
|
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)")
|
||||||
|
set(PROCESSOR_IS_POWER TRUE)
|
||||||
|
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(s390x)")
|
||||||
|
set(PROCESSOR_IS_S390X TRUE)
|
||||||
|
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^riscv")
|
||||||
|
set(PROCESSOR_IS_RISCV TRUE)
|
||||||
|
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^loongarch")
|
||||||
|
set(PROCESSOR_IS_LOONGARCH TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
macro(add_cpu_features_headers_and_sources HDRS_LIST_NAME SRCS_LIST_NAME)
|
||||||
|
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpu_features_macros.h)
|
||||||
|
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpu_features_cache_info.h)
|
||||||
|
file(GLOB IMPL_SOURCES CONFIGURE_DEPENDS "${PROJECT_SOURCE_DIR}/src/impl_*.c")
|
||||||
|
list(APPEND ${SRCS_LIST_NAME} ${IMPL_SOURCES})
|
||||||
|
if(PROCESSOR_IS_MIPS)
|
||||||
|
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_mips.h)
|
||||||
|
elseif(PROCESSOR_IS_ARM)
|
||||||
|
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_arm.h)
|
||||||
|
elseif(PROCESSOR_IS_AARCH64)
|
||||||
|
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_aarch64.h)
|
||||||
|
list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/windows_utils.h)
|
||||||
|
elseif(PROCESSOR_IS_X86)
|
||||||
|
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_x86.h)
|
||||||
|
list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/cpuid_x86.h)
|
||||||
|
list(APPEND ${SRCS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/internal/windows_utils.h)
|
||||||
|
elseif(PROCESSOR_IS_POWER)
|
||||||
|
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_ppc.h)
|
||||||
|
elseif(PROCESSOR_IS_S390X)
|
||||||
|
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_s390x.h)
|
||||||
|
elseif(PROCESSOR_IS_RISCV)
|
||||||
|
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_riscv.h)
|
||||||
|
elseif(PROCESSOR_IS_LOONGARCH)
|
||||||
|
list(APPEND ${HDRS_LIST_NAME} ${PROJECT_SOURCE_DIR}/include/cpuinfo_loongarch.h)
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "Unsupported architectures ${CMAKE_SYSTEM_PROCESSOR}")
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
#
|
||||||
|
# library : utils
|
||||||
|
#
|
||||||
|
|
||||||
|
add_library(utils OBJECT
|
||||||
|
${PROJECT_SOURCE_DIR}/include/internal/bit_utils.h
|
||||||
|
${PROJECT_SOURCE_DIR}/include/internal/filesystem.h
|
||||||
|
${PROJECT_SOURCE_DIR}/include/internal/stack_line_reader.h
|
||||||
|
${PROJECT_SOURCE_DIR}/include/internal/string_view.h
|
||||||
|
${PROJECT_SOURCE_DIR}/src/filesystem.c
|
||||||
|
${PROJECT_SOURCE_DIR}/src/stack_line_reader.c
|
||||||
|
${PROJECT_SOURCE_DIR}/src/string_view.c
|
||||||
|
)
|
||||||
|
setup_include_and_definitions(utils)
|
||||||
|
|
||||||
|
#
|
||||||
|
# library : unix_based_hardware_detection
|
||||||
|
#
|
||||||
|
|
||||||
|
if(UNIX)
|
||||||
|
add_library(unix_based_hardware_detection OBJECT
|
||||||
|
${PROJECT_SOURCE_DIR}/include/internal/hwcaps.h
|
||||||
|
${PROJECT_SOURCE_DIR}/src/hwcaps.c
|
||||||
|
)
|
||||||
|
setup_include_and_definitions(unix_based_hardware_detection)
|
||||||
|
check_include_file(dlfcn.h HAVE_DLFCN_H)
|
||||||
|
if(HAVE_DLFCN_H)
|
||||||
|
target_compile_definitions(unix_based_hardware_detection PRIVATE HAVE_DLFCN_H)
|
||||||
|
endif()
|
||||||
|
check_symbol_exists(getauxval "sys/auxv.h" HAVE_STRONG_GETAUXVAL)
|
||||||
|
if(HAVE_STRONG_GETAUXVAL)
|
||||||
|
target_compile_definitions(unix_based_hardware_detection PRIVATE HAVE_STRONG_GETAUXVAL)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#
|
||||||
|
# library : cpu_features
|
||||||
|
#
|
||||||
|
set (CPU_FEATURES_HDRS)
|
||||||
|
set (CPU_FEATURES_SRCS)
|
||||||
|
add_cpu_features_headers_and_sources(CPU_FEATURES_HDRS CPU_FEATURES_SRCS)
|
||||||
|
list(APPEND CPU_FEATURES_SRCS $<TARGET_OBJECTS:utils>)
|
||||||
|
if(NOT PROCESSOR_IS_X86 AND UNIX)
|
||||||
|
list(APPEND CPU_FEATURES_SRCS $<TARGET_OBJECTS:unix_based_hardware_detection>)
|
||||||
|
endif()
|
||||||
|
add_library(cpu_features ${CPU_FEATURES_HDRS} ${CPU_FEATURES_SRCS})
|
||||||
|
set_target_properties(cpu_features PROPERTIES PUBLIC_HEADER "${CPU_FEATURES_HDRS}")
|
||||||
|
setup_include_and_definitions(cpu_features)
|
||||||
|
target_link_libraries(cpu_features PUBLIC ${CMAKE_DL_LIBS})
|
||||||
|
target_include_directories(cpu_features
|
||||||
|
PUBLIC $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cpu_features>
|
||||||
|
)
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
target_compile_definitions(cpu_features PRIVATE HAVE_SYSCTLBYNAME)
|
||||||
|
endif()
|
||||||
|
add_library(CpuFeatures::cpu_features ALIAS cpu_features)
|
||||||
|
|
||||||
|
#
|
||||||
|
# program : list_cpu_features
|
||||||
|
#
|
||||||
|
|
||||||
|
if(BUILD_EXECUTABLE)
|
||||||
|
add_executable(list_cpu_features ${PROJECT_SOURCE_DIR}/src/utils/list_cpu_features.c)
|
||||||
|
target_link_libraries(list_cpu_features PRIVATE cpu_features)
|
||||||
|
add_executable(CpuFeatures::list_cpu_features ALIAS list_cpu_features)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#
|
||||||
|
# ndk_compat
|
||||||
|
#
|
||||||
|
|
||||||
|
if(ANDROID)
|
||||||
|
add_subdirectory(ndk_compat)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#
|
||||||
|
# tests
|
||||||
|
#
|
||||||
|
|
||||||
|
include(CTest)
|
||||||
|
if(BUILD_TESTING)
|
||||||
|
# Automatically incorporate googletest into the CMake Project if target not
|
||||||
|
# found.
|
||||||
|
enable_language(CXX)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 14)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF) # prefer use of -std14 instead of -gnustd14
|
||||||
|
|
||||||
|
if(NOT TARGET gtest OR NOT TARGET gmock_main)
|
||||||
|
# Download and unpack googletest at configure time.
|
||||||
|
configure_file(
|
||||||
|
cmake/googletest.CMakeLists.txt.in
|
||||||
|
googletest-download/CMakeLists.txt
|
||||||
|
)
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
|
||||||
|
RESULT_VARIABLE result
|
||||||
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download)
|
||||||
|
|
||||||
|
if(result)
|
||||||
|
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${CMAKE_COMMAND} --build .
|
||||||
|
RESULT_VARIABLE result
|
||||||
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download)
|
||||||
|
|
||||||
|
if(result)
|
||||||
|
message(FATAL_ERROR "Build step for googletest failed: ${result}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Prevent overriding the parent project's compiler/linker settings on
|
||||||
|
# Windows.
|
||||||
|
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
|
# Add googletest directly to our build. This defines the gtest and
|
||||||
|
# gtest_main targets.
|
||||||
|
add_subdirectory(${CMAKE_BINARY_DIR}/googletest-src
|
||||||
|
${CMAKE_BINARY_DIR}/googletest-build
|
||||||
|
EXCLUDE_FROM_ALL)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_subdirectory(test)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
#
|
||||||
|
# Install cpu_features and list_cpu_features
|
||||||
|
#
|
||||||
|
if(ENABLE_INSTALL)
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
install(TARGETS cpu_features
|
||||||
|
EXPORT CpuFeaturesTargets
|
||||||
|
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cpu_features
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
)
|
||||||
|
if(BUILD_EXECUTABLE)
|
||||||
|
install(TARGETS list_cpu_features
|
||||||
|
EXPORT CpuFeaturesTargets
|
||||||
|
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/cpu_features
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
install(EXPORT CpuFeaturesTargets
|
||||||
|
NAMESPACE CpuFeatures::
|
||||||
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures
|
||||||
|
COMPONENT Devel
|
||||||
|
)
|
||||||
|
include(CMakePackageConfigHelpers)
|
||||||
|
configure_package_config_file(cmake/CpuFeaturesConfig.cmake.in
|
||||||
|
"${PROJECT_BINARY_DIR}/CpuFeaturesConfig.cmake"
|
||||||
|
INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures"
|
||||||
|
NO_SET_AND_CHECK_MACRO
|
||||||
|
NO_CHECK_REQUIRED_COMPONENTS_MACRO
|
||||||
|
)
|
||||||
|
write_basic_package_version_file(
|
||||||
|
"${PROJECT_BINARY_DIR}/CpuFeaturesConfigVersion.cmake"
|
||||||
|
COMPATIBILITY SameMajorVersion
|
||||||
|
)
|
||||||
|
install(
|
||||||
|
FILES
|
||||||
|
"${PROJECT_BINARY_DIR}/CpuFeaturesConfig.cmake"
|
||||||
|
"${PROJECT_BINARY_DIR}/CpuFeaturesConfigVersion.cmake"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/CpuFeatures"
|
||||||
|
COMPONENT Devel
|
||||||
|
)
|
||||||
|
endif()
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
# How to Contribute
|
||||||
|
|
||||||
|
We'd love to accept your patches and contributions to this project. There are
|
||||||
|
just a few small guidelines you need to follow.
|
||||||
|
|
||||||
|
## Contributor License Agreement
|
||||||
|
|
||||||
|
Contributions to this project must be accompanied by a Contributor License
|
||||||
|
Agreement. You (or your employer) retain the copyright to your contribution;
|
||||||
|
this simply gives us permission to use and redistribute your contributions as
|
||||||
|
part of the project. Head over to <https://cla.developers.google.com/> to see
|
||||||
|
your current agreements on file or to sign a new one.
|
||||||
|
|
||||||
|
You generally only need to submit a CLA once, so if you've already submitted one
|
||||||
|
(even if it was for a different project), you probably don't need to do it
|
||||||
|
again.
|
||||||
|
|
||||||
|
## Code reviews
|
||||||
|
|
||||||
|
All submissions, including submissions by project members, require review. We
|
||||||
|
use GitHub pull requests for this purpose. Consult
|
||||||
|
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
|
||||||
|
information on using pull requests.
|
||||||
Vendored
+230
@@ -0,0 +1,230 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
For files in the `ndk_compat` folder:
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Copyright (C) 2010 The Android Open Source Project
|
||||||
|
All rights reserved.
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions
|
||||||
|
are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in
|
||||||
|
the documentation and/or other materials provided with the
|
||||||
|
distribution.
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||||
|
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGE.
|
||||||
Vendored
+282
@@ -0,0 +1,282 @@
|
|||||||
|
# cpu_features
|
||||||
|
|
||||||
|
A cross-platform C library to retrieve CPU features (such as available
|
||||||
|
instructions) at runtime.
|
||||||
|
|
||||||
|
# GitHub-CI Status
|
||||||
|
|
||||||
|
[comment]: <> (The following lines are generated by "scripts/generate_badges.d" that you can run online https://run.dlang.io/)
|
||||||
|
|
||||||
|
| | Linux | FreeBSD | MacOS | Windows |
|
||||||
|
| :-- | --: | --: | --: | --: |
|
||||||
|
| amd64 | [![CMake][i1a0]][l1a0]<br/>[![Bazel][i1a1]][l1a1] | [![CMake][i2a0]][l2a0]<br/>![Bazel][d1] | [![CMake][i3a0]][l3a0]<br/>[![Bazel][i3a1]][l3a1] | [![CMake][i4a0]][l4a0]<br/>![Bazel][d1] |
|
||||||
|
| AArch64 | [![CMake][i1b0]][l1b0]<br/>[![Bazel][i1b1]][l1b1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] |
|
||||||
|
| ARM | [![CMake][i1c0]][l1c0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] |
|
||||||
|
| MIPS | [![CMake][i1d0]][l1d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] |
|
||||||
|
| POWER | [![CMake][i1e0]][l1e0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] |
|
||||||
|
| RISCV | [![CMake][i1f0]][l1f0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] |
|
||||||
|
| LOONGARCH | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] |
|
||||||
|
| s390x | [![CMake][i1h0]][l1h0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] | ![CMake][d0]<br/>![Bazel][d1] |
|
||||||
|
|
||||||
|
[d0]: https://img.shields.io/badge/n%2Fa-lightgrey?&logo=cmake
|
||||||
|
[d1]: https://img.shields.io/badge/n%2Fa-lightgrey?&logo=data:image/svg%2bxml;base64,PHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNiAuMTZsNS43ODYgNS43ODZMNiAxMS43MzIuMjE0IDUuOTQ2IDYgLjE2MXpNMCA2LjIxNFYxMmw1Ljc4NiA1Ljc4NlYxMkwwIDYuMjE0ek0xOCAuMTZsNS43ODYgNS43ODZMMTggMTEuNzMybC01Ljc4Ni01Ljc4NkwxOCAuMTYxek0yNCA2LjIxNFYxMmwtNS43ODYgNS43ODZWMTJMMjQgNi4yMTR6TTEyIDYuMTZsNS43ODYgNS43ODZMMTIgMTcuNzMybC01Ljc4Ni01Ljc4NkwxMiA2LjE2MXpNMTEuODQgMTguMDU0djUuNzg1bC01Ljc4Ni01Ljc4NXYtNS43ODZsNS43ODUgNS43ODZ6TTEyLjE2IDE4LjA1NGw1Ljc4Ni01Ljc4NnY1Ljc4NmwtNS43ODUgNS43ODV2LTUuNzg1eiIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgZmlsbD0id2hpdGUiLz48L3N2Zz4=
|
||||||
|
[i1a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_linux_cmake.yml?branch=main&event=push&label=&logo=cmake
|
||||||
|
[i1a1]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_linux_bazel.yml?branch=main&event=push&label=&logo=data:image/svg%2bxml;base64,PHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNiAuMTZsNS43ODYgNS43ODZMNiAxMS43MzIuMjE0IDUuOTQ2IDYgLjE2MXpNMCA2LjIxNFYxMmw1Ljc4NiA1Ljc4NlYxMkwwIDYuMjE0ek0xOCAuMTZsNS43ODYgNS43ODZMMTggMTEuNzMybC01Ljc4Ni01Ljc4NkwxOCAuMTYxek0yNCA2LjIxNFYxMmwtNS43ODYgNS43ODZWMTJMMjQgNi4yMTR6TTEyIDYuMTZsNS43ODYgNS43ODZMMTIgMTcuNzMybC01Ljc4Ni01Ljc4NkwxMiA2LjE2MXpNMTEuODQgMTguMDU0djUuNzg1bC01Ljc4Ni01Ljc4NXYtNS43ODZsNS43ODUgNS43ODZ6TTEyLjE2IDE4LjA1NGw1Ljc4Ni01Ljc4NnY1Ljc4NmwtNS43ODUgNS43ODV2LTUuNzg1eiIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgZmlsbD0id2hpdGUiLz48L3N2Zz4=
|
||||||
|
[i1b0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/aarch64_linux_cmake.yml?branch=main&event=push&label=&logo=cmake
|
||||||
|
[i1b1]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/aarch64_linux_bazel.yml?branch=main&event=push&label=&logo=data:image/svg%2bxml;base64,PHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNiAuMTZsNS43ODYgNS43ODZMNiAxMS43MzIuMjE0IDUuOTQ2IDYgLjE2MXpNMCA2LjIxNFYxMmw1Ljc4NiA1Ljc4NlYxMkwwIDYuMjE0ek0xOCAuMTZsNS43ODYgNS43ODZMMTggMTEuNzMybC01Ljc4Ni01Ljc4NkwxOCAuMTYxek0yNCA2LjIxNFYxMmwtNS43ODYgNS43ODZWMTJMMjQgNi4yMTR6TTEyIDYuMTZsNS43ODYgNS43ODZMMTIgMTcuNzMybC01Ljc4Ni01Ljc4NkwxMiA2LjE2MXpNMTEuODQgMTguMDU0djUuNzg1bC01Ljc4Ni01Ljc4NXYtNS43ODZsNS43ODUgNS43ODZ6TTEyLjE2IDE4LjA1NGw1Ljc4Ni01Ljc4NnY1Ljc4NmwtNS43ODUgNS43ODV2LTUuNzg1eiIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgZmlsbD0id2hpdGUiLz48L3N2Zz4=
|
||||||
|
[i1c0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/arm_linux_cmake.yml?branch=main&event=push&label=&logo=cmake
|
||||||
|
[i1d0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/mips_linux_cmake.yml?branch=main&event=push&label=&logo=cmake
|
||||||
|
[i1e0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/power_linux_cmake.yml?branch=main&event=push&label=&logo=cmake
|
||||||
|
[i1f0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/riscv_linux_cmake.yml?branch=main&event=push&label=&logo=cmake
|
||||||
|
[i1h0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/s390x_linux_cmake.yml?branch=main&event=push&label=&logo=cmake
|
||||||
|
[i2a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_freebsd_cmake.yml?branch=main&event=push&label=&logo=cmake
|
||||||
|
[i3a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_macos_cmake.yml?branch=main&event=push&label=&logo=cmake
|
||||||
|
[i3a1]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_macos_bazel.yml?branch=main&event=push&label=&logo=data:image/svg%2bxml;base64,PHN2ZyByb2xlPSJpbWciIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNNiAuMTZsNS43ODYgNS43ODZMNiAxMS43MzIuMjE0IDUuOTQ2IDYgLjE2MXpNMCA2LjIxNFYxMmw1Ljc4NiA1Ljc4NlYxMkwwIDYuMjE0ek0xOCAuMTZsNS43ODYgNS43ODZMMTggMTEuNzMybC01Ljc4Ni01Ljc4NkwxOCAuMTYxek0yNCA2LjIxNFYxMmwtNS43ODYgNS43ODZWMTJMMjQgNi4yMTR6TTEyIDYuMTZsNS43ODYgNS43ODZMMTIgMTcuNzMybC01Ljc4Ni01Ljc4NkwxMiA2LjE2MXpNMTEuODQgMTguMDU0djUuNzg1bC01Ljc4Ni01Ljc4NXYtNS43ODZsNS43ODUgNS43ODZ6TTEyLjE2IDE4LjA1NGw1Ljc4Ni01Ljc4NnY1Ljc4NmwtNS43ODUgNS43ODV2LTUuNzg1eiIgc3Ryb2tlPSJ0cmFuc3BhcmVudCIgZmlsbD0id2hpdGUiLz48L3N2Zz4=
|
||||||
|
[i4a0]: https://img.shields.io/github/actions/workflow/status/google/cpu_features/amd64_windows_cmake.yml?branch=main&event=push&label=&logo=cmake
|
||||||
|
[l1a0]: https://github.com/google/cpu_features/actions/workflows/amd64_linux_cmake.yml
|
||||||
|
[l1a1]: https://github.com/google/cpu_features/actions/workflows/amd64_linux_bazel.yml
|
||||||
|
[l1b0]: https://github.com/google/cpu_features/actions/workflows/aarch64_linux_cmake.yml
|
||||||
|
[l1b1]: https://github.com/google/cpu_features/actions/workflows/aarch64_linux_bazel.yml
|
||||||
|
[l1c0]: https://github.com/google/cpu_features/actions/workflows/arm_linux_cmake.yml
|
||||||
|
[l1d0]: https://github.com/google/cpu_features/actions/workflows/mips_linux_cmake.yml
|
||||||
|
[l1e0]: https://github.com/google/cpu_features/actions/workflows/power_linux_cmake.yml
|
||||||
|
[l1f0]: https://github.com/google/cpu_features/actions/workflows/riscv_linux_cmake.yml
|
||||||
|
[l1h0]: https://github.com/google/cpu_features/actions/workflows/s390x_linux_cmake.yml
|
||||||
|
[l2a0]: https://github.com/google/cpu_features/actions/workflows/amd64_freebsd_cmake.yml
|
||||||
|
[l3a0]: https://github.com/google/cpu_features/actions/workflows/amd64_macos_cmake.yml
|
||||||
|
[l3a1]: https://github.com/google/cpu_features/actions/workflows/amd64_macos_bazel.yml
|
||||||
|
[l4a0]: https://github.com/google/cpu_features/actions/workflows/amd64_windows_cmake.yml
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [Design Rationale](#rationale)
|
||||||
|
- [Code samples](#codesample)
|
||||||
|
- [Running sample code](#usagesample)
|
||||||
|
- [What's supported](#support)
|
||||||
|
- [Android NDK's drop in replacement](#ndk)
|
||||||
|
- [License](#license)
|
||||||
|
- [Build with cmake](#cmake)
|
||||||
|
- [Community Bindings](#bindings)
|
||||||
|
|
||||||
|
<a name="rationale"></a>
|
||||||
|
## Design Rationale
|
||||||
|
|
||||||
|
- **Simple to use.** See the snippets below for examples.
|
||||||
|
- **Extensible.** Easy to add missing features or architectures.
|
||||||
|
- **Compatible with old compilers** and available on many architectures so it
|
||||||
|
can be used widely. To ensure that cpu_features works on as many platforms
|
||||||
|
as possible, we implemented it in a highly portable version of C: C99.
|
||||||
|
- **Sandbox-compatible.** The library uses a variety of strategies to cope
|
||||||
|
with sandboxed environments or when `cpuid` is unavailable. This is useful
|
||||||
|
when running integration tests in hermetic environments.
|
||||||
|
- **Thread safe, no memory allocation, and raises no exceptions.**
|
||||||
|
cpu_features is suitable for implementing fundamental libc functions like
|
||||||
|
`malloc`, `memcpy`, and `memcmp`.
|
||||||
|
- **Unit tested.**
|
||||||
|
|
||||||
|
<a name="codesample"></a>
|
||||||
|
## Code samples
|
||||||
|
|
||||||
|
**Note:** For C++ code, the library functions are defined in the `cpu_features` namespace.
|
||||||
|
|
||||||
|
### Checking features at runtime
|
||||||
|
|
||||||
|
Here's a simple example that executes a codepath if the CPU supports both the
|
||||||
|
AES and the SSE4.2 instruction sets:
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include "cpuinfo_x86.h"
|
||||||
|
|
||||||
|
// For C++, add `using namespace cpu_features;`
|
||||||
|
static const X86Features features = GetX86Info().features;
|
||||||
|
|
||||||
|
void Compute(void) {
|
||||||
|
if (features.aes && features.sse4_2) {
|
||||||
|
// Run optimized code.
|
||||||
|
} else {
|
||||||
|
// Run standard code.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Caching for faster evaluation of complex checks
|
||||||
|
|
||||||
|
If you wish, you can read all the features at once into a global variable, and
|
||||||
|
then query for the specific features you care about. Below, we store all the ARM
|
||||||
|
features and then check whether AES and NEON are supported.
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "cpuinfo_arm.h"
|
||||||
|
|
||||||
|
// For C++, add `using namespace cpu_features;`
|
||||||
|
static const ArmFeatures features = GetArmInfo().features;
|
||||||
|
static const bool has_aes_and_neon = features.aes && features.neon;
|
||||||
|
|
||||||
|
// use has_aes_and_neon.
|
||||||
|
```
|
||||||
|
|
||||||
|
This is a good approach to take if you're checking for combinations of features
|
||||||
|
when using a compiler that is slow to extract individual bits from bit-packed
|
||||||
|
structures.
|
||||||
|
|
||||||
|
### Checking compile time flags
|
||||||
|
|
||||||
|
The following code determines whether the compiler was told to use the AVX
|
||||||
|
instruction set (e.g., `g++ -mavx`) and sets `has_avx` accordingly.
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "cpuinfo_x86.h"
|
||||||
|
|
||||||
|
// For C++, add `using namespace cpu_features;`
|
||||||
|
static const X86Features features = GetX86Info().features;
|
||||||
|
static const bool has_avx = CPU_FEATURES_COMPILED_X86_AVX || features.avx;
|
||||||
|
|
||||||
|
// use has_avx.
|
||||||
|
```
|
||||||
|
|
||||||
|
`CPU_FEATURES_COMPILED_X86_AVX` is set to 1 if the compiler was instructed to
|
||||||
|
use AVX and 0 otherwise, combining compile time and runtime knowledge.
|
||||||
|
|
||||||
|
### Rejecting poor hardware implementations based on microarchitecture
|
||||||
|
|
||||||
|
On x86, the first incarnation of a feature in a microarchitecture might not be
|
||||||
|
the most efficient (e.g. AVX on Sandy Bridge). We provide a function to retrieve
|
||||||
|
the underlying microarchitecture so you can decide whether to use it.
|
||||||
|
|
||||||
|
Below, `has_fast_avx` is set to 1 if the CPU supports the AVX instruction
|
||||||
|
set—but only if it's not Sandy Bridge.
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "cpuinfo_x86.h"
|
||||||
|
|
||||||
|
// For C++, add `using namespace cpu_features;`
|
||||||
|
static const X86Info info = GetX86Info();
|
||||||
|
static const X86Microarchitecture uarch = GetX86Microarchitecture(&info);
|
||||||
|
static const bool has_fast_avx = info.features.avx && uarch != INTEL_SNB;
|
||||||
|
|
||||||
|
// use has_fast_avx.
|
||||||
|
```
|
||||||
|
|
||||||
|
This feature is currently available only for x86 microarchitectures.
|
||||||
|
|
||||||
|
<a name="usagesample"></a>
|
||||||
|
### Running sample code
|
||||||
|
|
||||||
|
Building `cpu_features` (check [quickstart](#quickstart) below) brings a small executable to test the library.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
% ./build/list_cpu_features
|
||||||
|
arch : x86
|
||||||
|
brand : Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz
|
||||||
|
family : 6 (0x06)
|
||||||
|
model : 45 (0x2D)
|
||||||
|
stepping : 7 (0x07)
|
||||||
|
uarch : INTEL_SNB
|
||||||
|
flags : aes,avx,cx16,smx,sse4_1,sse4_2,ssse3
|
||||||
|
```
|
||||||
|
|
||||||
|
```shell
|
||||||
|
% ./build/list_cpu_features --json
|
||||||
|
{"arch":"x86","brand":" Intel(R) Xeon(R) CPU E5-1650 0 @ 3.20GHz","family":6,"model":45,"stepping":7,"uarch":"INTEL_SNB","flags":["aes","avx","cx16","smx","sse4_1","sse4_2","ssse3"]}
|
||||||
|
```
|
||||||
|
|
||||||
|
<a name="support"></a>
|
||||||
|
## What's supported
|
||||||
|
|
||||||
|
| | x86³ | AArch64 | ARM | MIPS⁴ | POWER | RISCV | Loongarch | s390x |
|
||||||
|
|---------|:----:|:-------:|:-------:|:-------:|:-------:|:-------:|:---------:|:-------:|
|
||||||
|
| Linux | yes² | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ | yes¹ |
|
||||||
|
| FreeBSD | yes² | not yet | not yet | not yet | not yet | N/A | not yet | not yet |
|
||||||
|
| MacOs | yes² | yes⁵ | N/A | N/A | N/A | N/A | N/A | N/A |
|
||||||
|
| Windows | yes² | not yet | not yet | N/A | N/A | N/A | N/A | N/A |
|
||||||
|
| Android | yes² | yes¹ | yes¹ | yes¹ | N/A | N/A | N/A | N/A |
|
||||||
|
| iOS | N/A | not yet | not yet | N/A | N/A | N/A | N/A | N/A |
|
||||||
|
|
||||||
|
1. **Features revealed from Linux.** We gather data from several sources
|
||||||
|
depending on availability:
|
||||||
|
+ from glibc's
|
||||||
|
[getauxval](https://www.gnu.org/software/libc/manual/html_node/Auxiliary-Vector.html)
|
||||||
|
+ by parsing `/proc/self/auxv`
|
||||||
|
+ by parsing `/proc/cpuinfo`
|
||||||
|
2. **Features revealed from CPU.** features are retrieved by using the `cpuid`
|
||||||
|
instruction.
|
||||||
|
3. **Microarchitecture detection.** On x86 some features are not always
|
||||||
|
implemented efficiently in hardware (e.g. AVX on Sandybridge). Exposing the
|
||||||
|
microarchitecture allows the client to reject particular microarchitectures.
|
||||||
|
4. All flavors of Mips are supported, little and big endian as well as 32/64
|
||||||
|
bits.
|
||||||
|
5. **Features revealed from sysctl.** features are retrieved by the `sysctl`
|
||||||
|
instruction.
|
||||||
|
|
||||||
|
<a name="ndk"></a>
|
||||||
|
## Android NDK's drop in replacement
|
||||||
|
|
||||||
|
[cpu_features](https://github.com/google/cpu_features) is now officially
|
||||||
|
supporting Android and offers a drop in replacement of for the NDK's [cpu-features.h](https://android.googlesource.com/platform/ndk/+/main/sources/android/cpufeatures/cpu-features.h)
|
||||||
|
, see [ndk_compat](ndk_compat) folder for details.
|
||||||
|
|
||||||
|
<a name="license"></a>
|
||||||
|
## License
|
||||||
|
|
||||||
|
The cpu_features library is licensed under the terms of the Apache license.
|
||||||
|
See [LICENSE](LICENSE) for more information.
|
||||||
|
|
||||||
|
<a name="cmake"></a>
|
||||||
|
## Build with CMake
|
||||||
|
|
||||||
|
Please check the [CMake build instructions](cmake/README.md).
|
||||||
|
|
||||||
|
<a name="quickstart"></a>
|
||||||
|
### Quickstart
|
||||||
|
|
||||||
|
- Run `list_cpu_features`
|
||||||
|
```sh
|
||||||
|
cmake -S. -Bbuild -DBUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=Release
|
||||||
|
cmake --build build --config Release -j
|
||||||
|
./build/list_cpu_features --json
|
||||||
|
```
|
||||||
|
|
||||||
|
_Note_: Use `--target ALL_BUILD` on the second line for `Visual Studio` and `XCode`.
|
||||||
|
|
||||||
|
- run tests
|
||||||
|
```sh
|
||||||
|
cmake -S. -Bbuild -DBUILD_TESTING=ON -DCMAKE_BUILD_TYPE=Debug
|
||||||
|
cmake --build build --config Debug -j
|
||||||
|
cmake --build build --config Debug --target test
|
||||||
|
```
|
||||||
|
|
||||||
|
_Note_: Use `--target RUN_TESTS` on the last line for `Visual Studio` and `--target RUN_TEST` for `XCode`.
|
||||||
|
|
||||||
|
|
||||||
|
- install `cpu_features`
|
||||||
|
```sh
|
||||||
|
cmake --build build --config Release --target install -v
|
||||||
|
```
|
||||||
|
|
||||||
|
_Note_: Use `--target INSTALL` for `Visual Studio`.
|
||||||
|
|
||||||
|
_Note_: When using `Makefile` or `XCode` generator, you can use
|
||||||
|
[`DESTDIR`](https://www.gnu.org/software/make/manual/html_node/DESTDIR.html)
|
||||||
|
to install on a local repository.<br>
|
||||||
|
e.g.
|
||||||
|
```sh
|
||||||
|
cmake --build build --config Release --target install -v -- DESTDIR=install
|
||||||
|
```
|
||||||
|
|
||||||
|
<a name="bindings"></a>
|
||||||
|
## Community bindings
|
||||||
|
|
||||||
|
Links provided here are not affiliated with Google but are kindly provided by the OSS Community.
|
||||||
|
|
||||||
|
- .Net
|
||||||
|
- https://github.com/toor1245/cpu_features.NET
|
||||||
|
- Python
|
||||||
|
- https://github.com/Narasimha1997/py_cpu
|
||||||
|
- Java
|
||||||
|
- https://github.com/aecsocket/cpu-features-java
|
||||||
|
|
||||||
|
|
||||||
|
_Send PR to showcase your wrapper here_
|
||||||
Vendored
+19
@@ -0,0 +1,19 @@
|
|||||||
|
workspace(name = "com_google_cpufeatures")
|
||||||
|
|
||||||
|
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
|
||||||
|
|
||||||
|
git_repository(
|
||||||
|
name = "com_google_googletest",
|
||||||
|
tag = "release-1.11.0",
|
||||||
|
remote = "https://github.com/google/googletest.git",
|
||||||
|
)
|
||||||
|
|
||||||
|
git_repository(
|
||||||
|
name = "bazel_skylib",
|
||||||
|
tag = "1.2.0",
|
||||||
|
remote = "https://github.com/bazelbuild/bazel-skylib.git",
|
||||||
|
)
|
||||||
|
|
||||||
|
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
|
||||||
|
|
||||||
|
bazel_skylib_workspace()
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# CpuFeatures CMake configuration file
|
||||||
|
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/CpuFeaturesTargets.cmake")
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# CpuFeaturesNdkCompat CMake configuration file
|
||||||
|
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/CpuFeaturesNdkCompatTargets.cmake")
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
# CMake build instructions
|
||||||
|
|
||||||
|
## Recommended usage : Incorporating cpu_features into a CMake project
|
||||||
|
|
||||||
|
For API / ABI compatibility reasons, it is recommended to build and use
|
||||||
|
cpu_features in a subdirectory of your project or as an embedded dependency.
|
||||||
|
|
||||||
|
This is similar to the recommended usage of the googletest framework
|
||||||
|
( https://github.com/google/googletest/blob/main/googletest/README.md )
|
||||||
|
|
||||||
|
Build and use step-by-step
|
||||||
|
|
||||||
|
|
||||||
|
1- Download cpu_features and copy it in a sub-directory in your project.
|
||||||
|
or add cpu_features as a git-submodule in your project
|
||||||
|
|
||||||
|
2- You can then use the cmake command `add_subdirectory()` to include
|
||||||
|
cpu_features directly and use the `cpu_features` target in your project.
|
||||||
|
|
||||||
|
3- Add the `CpuFeatures::cpu_features` target to the `target_link_libraries()` section of
|
||||||
|
your executable or of your library.
|
||||||
|
|
||||||
|
## Disabling tests
|
||||||
|
|
||||||
|
CMake default options for cpu_features is `Release` built type with tests
|
||||||
|
enabled. To disable testing set cmake `BUILD_TESTING` variable to `OFF`.
|
||||||
|
e.g.
|
||||||
|
```sh
|
||||||
|
cmake -S. -Bbuild -DBUILD_TESTING=OFF
|
||||||
|
```
|
||||||
+252
@@ -0,0 +1,252 @@
|
|||||||
|
PROJECT := cpu_features
|
||||||
|
BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
|
||||||
|
SHA1 := $(shell git rev-parse --verify HEAD)
|
||||||
|
|
||||||
|
# General commands
|
||||||
|
.PHONY: help
|
||||||
|
BOLD=\e[1m
|
||||||
|
RESET=\e[0m
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo -e "${BOLD}SYNOPSIS${RESET}"
|
||||||
|
@echo -e "\tmake <target> [NOCACHE=1]"
|
||||||
|
@echo
|
||||||
|
@echo -e "${BOLD}DESCRIPTION${RESET}"
|
||||||
|
@echo -e "\ttest build inside docker container to have a reproductible build."
|
||||||
|
@echo
|
||||||
|
@echo -e "${BOLD}MAKE TARGETS${RESET}"
|
||||||
|
@echo -e "\t${BOLD}help${RESET}: display this help and exit."
|
||||||
|
@echo
|
||||||
|
@echo -e "\t${BOLD}amd64_<stage>${RESET}: build <stage> docker image using an Ubuntu:latest x86_64 base image."
|
||||||
|
@echo -e "\t${BOLD}save_amd64_<stage>${RESET}: Save the <stage> docker image."
|
||||||
|
@echo -e "\t${BOLD}sh_amd64_<stage>${RESET}: run a container using the <stage> docker image (debug purpose)."
|
||||||
|
@echo -e "\t${BOLD}clean_amd64_<stage>${RESET}: Remove cache and docker image."
|
||||||
|
@echo
|
||||||
|
@echo -e "\tWith ${BOLD}<stage>${RESET}:"
|
||||||
|
@echo -e "\t\t${BOLD}env${RESET}"
|
||||||
|
@echo -e "\t\t${BOLD}devel${RESET}"
|
||||||
|
@echo -e "\t\t${BOLD}build${RESET}"
|
||||||
|
@echo -e "\t\t${BOLD}test${RESET}"
|
||||||
|
@echo -e "\t\t${BOLD}install_env${RESET}"
|
||||||
|
@echo -e "\t\t${BOLD}install_devel${RESET}"
|
||||||
|
@echo -e "\t\t${BOLD}install_build${RESET}"
|
||||||
|
@echo -e "\t\t${BOLD}install_test${RESET}"
|
||||||
|
@echo -e "\te.g. 'make amd64_build'"
|
||||||
|
@echo
|
||||||
|
@echo -e "\t${BOLD}<target>_<toolchain_stage>${RESET}: build <stage> docker image for a specific toolchain target."
|
||||||
|
@echo -e "\t${BOLD}save_<target>_<toolchain_stage>${RESET}: Save the <stage> docker image for a specific platform."
|
||||||
|
@echo -e "\t${BOLD}sh_<target>_<toolchain_stage>${RESET}: run a container using the <stage> docker image specified (debug purpose)."
|
||||||
|
@echo -e "\t${BOLD}clean_<target>_<toolchain_stage>${RESET}: Remove cache and docker image."
|
||||||
|
@echo
|
||||||
|
@echo -e "\tWith ${BOLD}<target>${RESET}:"
|
||||||
|
@echo -e "\t\t${BOLD}arm-linux-gnueabihf${RESET} (linaro toolchain)"
|
||||||
|
@echo -e "\t\t${BOLD}armv8l-linux-gnueabihf${RESET} (linaro toolchain)"
|
||||||
|
@echo -e "\t\t${BOLD}arm-linux-gnueabi${RESET} (linaro toolchain)"
|
||||||
|
@echo -e "\t\t${BOLD}armeb-linux-gnueabihf${RESET} (linaro toolchain)"
|
||||||
|
@echo -e "\t\t${BOLD}armeb-linux-gnueabi${RESET} (linaro toolchain)"
|
||||||
|
@echo -e "\t\t${BOLD}aarch64-linux-gnu${RESET} (linaro toolchain)"
|
||||||
|
@echo -e "\t\t${BOLD}aarch64${RESET} (bootlin toolchain)"
|
||||||
|
@echo -e "\t\t${BOLD}aarch64_be-linux-gnu${RESET} (linaro toolchain)"
|
||||||
|
@echo -e "\t\t${BOLD}aarch64be${RESET} (bootlin toolchain)"
|
||||||
|
@echo -e "\t\t${BOLD}mips32${RESET} (codespace toolchain)"
|
||||||
|
@echo -e "\t\t${BOLD}mips64${RESET} (codespace toolchain)"
|
||||||
|
@echo -e "\t\t${BOLD}mips32el${RESET} (codespace toolchain)"
|
||||||
|
@echo -e "\t\t${BOLD}mips64el${RESET} (codespace toolchain)"
|
||||||
|
@echo -e "\t\t${BOLD}ppc${RESET} (bootlin toolchain)"
|
||||||
|
@echo -e "\t\t${BOLD}ppc64${RESET} (bootlin toolchain)"
|
||||||
|
@echo -e "\t\t${BOLD}ppc64le${RESET} (bootlin toolchain)"
|
||||||
|
@echo -e "\t\t${BOLD}riscv32${RESET} (bootlin toolchain)"
|
||||||
|
@echo -e "\t\t${BOLD}riscv64${RESET} (bootlin toolchain)"
|
||||||
|
@echo -e "\t\t${BOLD}s390x${RESET} (bootlin toolchain)"
|
||||||
|
@echo
|
||||||
|
@echo -e "\tWith ${BOLD}<toolchain_stage>${RESET}:"
|
||||||
|
@echo -e "\t\t${BOLD}env${RESET}"
|
||||||
|
@echo -e "\t\t${BOLD}devel${RESET}"
|
||||||
|
@echo -e "\t\t${BOLD}build${RESET}"
|
||||||
|
@echo -e "\t\t${BOLD}test${RESET}"
|
||||||
|
@echo -e "\te.g. 'make aarch64_test'"
|
||||||
|
@echo
|
||||||
|
@echo -e "\t${BOLD}<VM>${RESET}: build the vagrant <VM> virtual machine."
|
||||||
|
@echo -e "\t${BOLD}clean_<VM>${RESET}: Remove virtual machine for the specified vm."
|
||||||
|
@echo
|
||||||
|
@echo -e "\t${BOLD}<VM>${RESET}:"
|
||||||
|
@echo -e "\t\t${BOLD}freebsd${RESET} (FreeBSD)"
|
||||||
|
@echo
|
||||||
|
@echo -e "\t${BOLD}clean${RESET}: Remove cache and ALL docker images."
|
||||||
|
@echo
|
||||||
|
@echo -e "\t${BOLD}NOCACHE=1${RESET}: use 'docker build --no-cache' when building container (default use cache)."
|
||||||
|
@echo
|
||||||
|
@echo -e "branch: $(BRANCH)"
|
||||||
|
@echo -e "sha1: $(SHA1)"
|
||||||
|
|
||||||
|
# Need to add cmd_platform to PHONY otherwise target are ignored since they do not
|
||||||
|
# contain recipe (using FORCE do not work here)
|
||||||
|
.PHONY: all
|
||||||
|
all: build
|
||||||
|
|
||||||
|
# Delete all implicit rules to speed up makefile
|
||||||
|
MAKEFLAGS += --no-builtin-rules
|
||||||
|
.SUFFIXES:
|
||||||
|
# Remove some rules from gmake that .SUFFIXES does not remove.
|
||||||
|
SUFFIXES =
|
||||||
|
# Keep all intermediate files
|
||||||
|
# ToDo: try to remove it later
|
||||||
|
.SECONDARY:
|
||||||
|
|
||||||
|
# Docker image name prefix.
|
||||||
|
IMAGE := ${PROJECT}
|
||||||
|
|
||||||
|
ifdef NOCACHE
|
||||||
|
DOCKER_BUILD_CMD := docker build --no-cache
|
||||||
|
else
|
||||||
|
DOCKER_BUILD_CMD := docker build
|
||||||
|
endif
|
||||||
|
|
||||||
|
DOCKER_RUN_CMD := docker run --rm --init --net=host
|
||||||
|
|
||||||
|
# $* stem
|
||||||
|
# $< first prerequist
|
||||||
|
# $@ target name
|
||||||
|
|
||||||
|
############
|
||||||
|
## NATIVE ##
|
||||||
|
############
|
||||||
|
STAGES = env devel build test install_env install_devel install_build install_test
|
||||||
|
|
||||||
|
targets_amd64 = $(addprefix amd64_, $(STAGES))
|
||||||
|
.PHONY: $(targets_amd64)
|
||||||
|
$(targets_amd64): amd64_%: docker/amd64/Dockerfile
|
||||||
|
#@docker image rm -f ${IMAGE}:amd64_$* 2>/dev/null
|
||||||
|
${DOCKER_BUILD_CMD} \
|
||||||
|
--tag ${IMAGE}:amd64_$* \
|
||||||
|
--target=$* \
|
||||||
|
-f $< \
|
||||||
|
../..
|
||||||
|
|
||||||
|
#$(info Create targets: save_amd64 $(addprefix save_amd64_, $(STAGES)) (debug).)
|
||||||
|
save_targets_amd64 = $(addprefix save_amd64_, $(STAGES))
|
||||||
|
.PHONY: $(save_targets_amd64)
|
||||||
|
$(save_targets_amd64): save_amd64_%: cache/amd64/docker_%.tar
|
||||||
|
cache/amd64/docker_%.tar: amd64_%
|
||||||
|
@rm -f $@
|
||||||
|
mkdir -p cache/amd64
|
||||||
|
docker save ${IMAGE}:amd64_$* -o $@
|
||||||
|
|
||||||
|
#$(info Create targets: $(addprefix sh_amd64_, $(STAGES)) (debug).)
|
||||||
|
sh_targets_amd64 = $(addprefix sh_amd64_, $(STAGES))
|
||||||
|
.PHONY: $(sh_targets_amd64)
|
||||||
|
$(sh_targets_amd64): sh_amd64_%: amd64_%
|
||||||
|
${DOCKER_RUN_CMD} -it --name ${IMAGE}_amd64_$* ${IMAGE}:amd64_$*
|
||||||
|
|
||||||
|
#$(info Create targets: $(addprefix clean_amd64_, $(STAGES)).)
|
||||||
|
clean_targets_amd64 = $(addprefix clean_amd64_, $(STAGES))
|
||||||
|
.PHONY: clean_amd64 $(clean_targets_amd64)
|
||||||
|
clean_amd64: $(clean_targets_amd64)
|
||||||
|
$(clean_targets_amd64): clean_amd64_%:
|
||||||
|
docker image rm -f ${IMAGE}:amd64_$* 2>/dev/null
|
||||||
|
rm -f cache/amd64/docker_$*.tar
|
||||||
|
|
||||||
|
|
||||||
|
###############
|
||||||
|
## TOOLCHAIN ##
|
||||||
|
###############
|
||||||
|
TOOLCHAIN_TARGETS = \
|
||||||
|
aarch64 aarch64be \
|
||||||
|
arm-linux-gnueabihf armv8l-linux-gnueabihf arm-linux-gnueabi armeb-linux-gnueabihf armeb-linux-gnueabi \
|
||||||
|
aarch64-linux-gnu aarch64_be-linux-gnu \
|
||||||
|
mips32 mips32el mips64 mips64el \
|
||||||
|
ppc ppc64 ppc64le \
|
||||||
|
riscv32 riscv64 \
|
||||||
|
s390x
|
||||||
|
TOOLCHAIN_STAGES = env devel build test
|
||||||
|
define toolchain-stage-target =
|
||||||
|
#$$(info STAGE: $1)
|
||||||
|
#$$(info Create targets: toolchain_$1 $(addsuffix _$1, $(TOOLCHAIN_TARGETS)).)
|
||||||
|
targets_toolchain_$1 = $(addsuffix _$1, $(TOOLCHAIN_TARGETS))
|
||||||
|
.PHONY: toolchain_$1 $$(targets_toolchain_$1)
|
||||||
|
toolchain_$1: $$(targets_toolchain_$1)
|
||||||
|
$$(targets_toolchain_$1): %_$1: docker/toolchain/Dockerfile
|
||||||
|
#@docker image rm -f ${IMAGE}:$$*_$1 2>/dev/null
|
||||||
|
${DOCKER_BUILD_CMD} \
|
||||||
|
--tag ${IMAGE}:$$*_$1 \
|
||||||
|
--build-arg TARGET=$$* \
|
||||||
|
--target=$1 \
|
||||||
|
-f $$< \
|
||||||
|
../..
|
||||||
|
|
||||||
|
#$$(info Create targets: save_toolchain_$1 $(addprefix save_, $(addsuffix _$1, $(TOOLCHAIN_TARGETS))) (debug).)
|
||||||
|
save_targets_toolchain_$1 = $(addprefix save_, $(addsuffix _$1, $(TOOLCHAIN_TARGETS)))
|
||||||
|
.PHONY: save_toolchain_$1 $$(save_targets_toolchain_$1)
|
||||||
|
save_toolchain_$1: $$(save_targets_toolchain_$1)
|
||||||
|
$$(save_targets_toolchain_$1): save_%_$1: cache/%/docker_$1.tar
|
||||||
|
cache/%/docker_$1.tar: %_$1
|
||||||
|
@rm -f $$@
|
||||||
|
mkdir -p cache/$$*
|
||||||
|
docker save ${IMAGE}:$$*_$1 -o $$@
|
||||||
|
|
||||||
|
#$$(info Create targets: $(addprefix sh_, $(addsuffix _$1, $(TOOLCHAIN_TARGETS))) (debug).)
|
||||||
|
sh_targets_toolchain_$1 = $(addprefix sh_, $(addsuffix _$1, $(TOOLCHAIN_TARGETS)))
|
||||||
|
.PHONY: $$(sh_targets_toolchain_$1)
|
||||||
|
$$(sh_targets_toolchain_$1): sh_%_$1: %_$1
|
||||||
|
${DOCKER_RUN_CMD} -it --name ${IMAGE}_$$*_$1 ${IMAGE}:$$*_$1
|
||||||
|
|
||||||
|
#$$(info Create targets: clean_toolchain_$1 $(addprefix clean_, $(addsuffix _$1, $(TOOLCHAIN_TARGETS))).)
|
||||||
|
clean_targets_toolchain_$1 = $(addprefix clean_, $(addsuffix _$1, $(TOOLCHAIN_TARGETS)))
|
||||||
|
.PHONY: clean_toolchain_$1 $$(clean_targets_toolchain_$1)
|
||||||
|
clean_toolchain_$1: $$(clean_targets_toolchain_$1)
|
||||||
|
$$(clean_targets_toolchain_$1): clean_%_$1:
|
||||||
|
docker image rm -f ${IMAGE}:$$*_$1 2>/dev/null
|
||||||
|
rm -f cache/$$*/docker_$1.tar
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(foreach stage,$(TOOLCHAIN_STAGES),$(eval $(call toolchain-stage-target,$(stage))))
|
||||||
|
|
||||||
|
## MERGE ##
|
||||||
|
.PHONY: clean_toolchain
|
||||||
|
clean_toolchain: $(addprefix clean_toolchain_, $(TOOLCHAIN_STAGES))
|
||||||
|
-rmdir $(addprefix cache/, $(TOOLCHAIN_TARGETS))
|
||||||
|
|
||||||
|
.PHONY: env devel build test
|
||||||
|
env: amd64_env toolchain_env
|
||||||
|
devel: amd64_devel toolchain_devel
|
||||||
|
build: amd64_build toolchain_build
|
||||||
|
test: amd64_test toolchain_test
|
||||||
|
|
||||||
|
.PHONY: install_env install_devel install_build install_test
|
||||||
|
install_env: amd64_install_env
|
||||||
|
install_devel: amd64_install_devel
|
||||||
|
install_build: amd64_install_build
|
||||||
|
install_test: amd64_install_test
|
||||||
|
|
||||||
|
#############
|
||||||
|
## VAGRANT ##
|
||||||
|
#############
|
||||||
|
VMS = freebsd
|
||||||
|
|
||||||
|
vms_targets = $(addsuffix _build, $(VMS))
|
||||||
|
.PHONY: $(vms_targets)
|
||||||
|
$(vms_targets): %_build: vagrant/%/Vagrantfile
|
||||||
|
@cd vagrant/$* && vagrant destroy -f
|
||||||
|
cd vagrant/$* && vagrant up
|
||||||
|
|
||||||
|
clean_vms_targets = $(addprefix clean_, $(VMS))
|
||||||
|
.PHONY: clean_vms $(clean_vms_targets)
|
||||||
|
clean_vms: $(clean_vms_targets)
|
||||||
|
$(clean_vms_targets): clean_%:
|
||||||
|
cd vagrant/$* && vagrant destroy -f
|
||||||
|
-rm -rf vagrant/$*/.vagrant
|
||||||
|
|
||||||
|
###########
|
||||||
|
## CLEAN ##
|
||||||
|
###########
|
||||||
|
.PHONY: clean
|
||||||
|
clean: clean_amd64 clean_toolchain clean_vms
|
||||||
|
docker container prune -f
|
||||||
|
docker image prune -f
|
||||||
|
-rmdir cache
|
||||||
|
|
||||||
|
.PHONY: distclean
|
||||||
|
distclean: clean
|
||||||
|
-docker container rm -f $$(docker container ls -aq)
|
||||||
|
-docker image rm -f $$(docker image ls -aq)
|
||||||
|
-vagrant box remove -f generic/freebsd12
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
## Makefile/Docker testing
|
||||||
|
To test the build on various distro, we are using docker containers and a Makefile for orchestration.
|
||||||
|
|
||||||
|
pros:
|
||||||
|
* You are independent of third party CI runner config
|
||||||
|
(e.g. [github action virtual-environnments](https://github.com/actions/virtual-environments)).
|
||||||
|
* You can run it locally on your linux system.
|
||||||
|
* Most CI provide runners with docker and Makefile installed.
|
||||||
|
|
||||||
|
cons:
|
||||||
|
* Only GNU/Linux distro supported.
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
To get the help simply type:
|
||||||
|
```sh
|
||||||
|
make
|
||||||
|
```
|
||||||
|
|
||||||
|
note: you can also use from top directory
|
||||||
|
```sh
|
||||||
|
make --directory=cmake/ci
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example
|
||||||
|
For example to test mips32 inside an container:
|
||||||
|
```sh
|
||||||
|
make mips32_test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker layers
|
||||||
|
Dockerfile is splitted in several stages.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
## Makefile/Vagrant testing
|
||||||
|
To test build for FreeBSD we are using Vagrant and VirtualBox box.
|
||||||
|
|
||||||
|
This is similar to the docker stuff but use `vagrant` as `docker` cli and
|
||||||
|
VirtuaBox to replace the docker engine daemon.
|
||||||
+64
@@ -0,0 +1,64 @@
|
|||||||
|
@startdot
|
||||||
|
digraph DockerDeps {
|
||||||
|
//rankdir=BT;
|
||||||
|
rankdir=TD;
|
||||||
|
node [shape=cylinder, style="rounded,filled", color=black, fillcolor=royalblue];
|
||||||
|
DISTRO_IMG [label="ubuntu:latest"];
|
||||||
|
PKG [label="packages\ne.g. cmake, g++", shape=box3d];
|
||||||
|
SRC [label="git repo", shape=folder];
|
||||||
|
SPL [label="sample", shape=folder];
|
||||||
|
|
||||||
|
subgraph clusterDockerfile {
|
||||||
|
ENV_IMG [label="cpu_features:amd64_env\nenv"];
|
||||||
|
DEVEL_IMG [label="cpu_features:amd64_devel\ndevel"];
|
||||||
|
BUILD_IMG [label="cpu_features:amd64_build\nbuild"];
|
||||||
|
TEST_IMG [label="cpu_features:amd64_test\ntest"];
|
||||||
|
INSTALL_ENV_IMG [label="cpu_features:amd64_install_env\ninstall_env"];
|
||||||
|
INSTALL_DEVEL_IMG [label="cpu_features:amd64_install_devel\ninstall_devel"];
|
||||||
|
INSTALL_BUILD_IMG [label="cpu_features:amd64_install_build\ninstall_build"];
|
||||||
|
INSTALL_TEST_IMG [label="cpu_features:amd64_install_test\ninstall_test"];
|
||||||
|
|
||||||
|
ENV_IMG -> DEVEL_IMG;
|
||||||
|
DEVEL_IMG -> BUILD_IMG;
|
||||||
|
BUILD_IMG -> TEST_IMG;
|
||||||
|
|
||||||
|
ENV_IMG -> INSTALL_ENV_IMG;
|
||||||
|
BUILD_IMG -> INSTALL_ENV_IMG [label="copy install", style="dashed"];
|
||||||
|
INSTALL_ENV_IMG -> INSTALL_DEVEL_IMG;
|
||||||
|
SPL -> INSTALL_DEVEL_IMG [label="copy", style="dashed"];
|
||||||
|
INSTALL_DEVEL_IMG -> INSTALL_BUILD_IMG;
|
||||||
|
INSTALL_BUILD_IMG -> INSTALL_TEST_IMG;
|
||||||
|
|
||||||
|
color=royalblue;
|
||||||
|
label = "docker/amd64/Dockerfile";
|
||||||
|
}
|
||||||
|
DISTRO_IMG -> ENV_IMG;
|
||||||
|
PKG -> ENV_IMG [label="install", style="dashed"];
|
||||||
|
SRC -> DEVEL_IMG [label="copy", style="dashed"];
|
||||||
|
|
||||||
|
subgraph clusterCache {
|
||||||
|
node [shape=note, style="rounded,filled", color=black, fillcolor=royalblue];
|
||||||
|
ENV_TAR [label="docker_amd64_env.tar"];
|
||||||
|
DEVEL_TAR [label="docker_amd64_devel.tar"];
|
||||||
|
BUILD_TAR [label="docker_amd64_build.tar"];
|
||||||
|
TEST_TAR [label="docker_amd64_test.tar"];
|
||||||
|
INSTALL_ENV_TAR [label="docker_amd64_install_env.tar"];
|
||||||
|
INSTALL_DEVEL_TAR [label="docker_amd64_install_devel.tar"];
|
||||||
|
INSTALL_BUILD_TAR [label="docker_amd64_install_build.tar"];
|
||||||
|
INSTALL_TEST_TAR [label="docker_amd64_install_test.tar"];
|
||||||
|
|
||||||
|
edge [color=red];
|
||||||
|
ENV_IMG -> ENV_TAR [label="make save_amd64_env"];
|
||||||
|
DEVEL_IMG -> DEVEL_TAR [label="make save_amd64_devel"];
|
||||||
|
BUILD_IMG -> BUILD_TAR [label="make save_amd64_build"];
|
||||||
|
TEST_IMG -> TEST_TAR [label="make save_amd64_test"];
|
||||||
|
INSTALL_ENV_IMG -> INSTALL_ENV_TAR [label="make save_amd64_install_env"];
|
||||||
|
INSTALL_DEVEL_IMG -> INSTALL_DEVEL_TAR [label="make save_amd64_install_devel"];
|
||||||
|
INSTALL_BUILD_IMG -> INSTALL_BUILD_TAR [label="make save_amd64_install_build"];
|
||||||
|
INSTALL_TEST_IMG -> INSTALL_TEST_TAR [label="make save_amd64_install_test"];
|
||||||
|
|
||||||
|
color=royalblue;
|
||||||
|
label = "cache/amd64/";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@enddot
|
||||||
+312
@@ -0,0 +1,312 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||||
|
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<!-- Generated by graphviz version 2.49.2 (0)
|
||||||
|
-->
|
||||||
|
<!-- Title: DockerDeps Pages: 1 -->
|
||||||
|
<svg width="1904pt" height="900pt"
|
||||||
|
viewBox="0.00 0.00 1904.00 899.75" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 895.75)">
|
||||||
|
<title>DockerDeps</title>
|
||||||
|
<polygon fill="white" stroke="transparent" points="-4,4 -4,-895.75 1900,-895.75 1900,4 -4,4"/>
|
||||||
|
<g id="clust1" class="cluster">
|
||||||
|
<title>clusterDockerfile</title>
|
||||||
|
<polygon fill="none" stroke="royalblue" points="691,-116 691,-812.75 1253,-812.75 1253,-116 691,-116"/>
|
||||||
|
<text text-anchor="middle" x="972" y="-797.55" font-family="Times,serif" font-size="14.00">docker/amd64/Dockerfile</text>
|
||||||
|
</g>
|
||||||
|
<g id="clust2" class="cluster">
|
||||||
|
<title>clusterCache</title>
|
||||||
|
<polygon fill="none" stroke="royalblue" points="8,-8 8,-83 1826,-83 1826,-8 8,-8"/>
|
||||||
|
<text text-anchor="middle" x="917" y="-67.8" font-family="Times,serif" font-size="14.00">cache/amd64/</text>
|
||||||
|
</g>
|
||||||
|
<!-- DISTRO_IMG -->
|
||||||
|
<g id="node1" class="node">
|
||||||
|
<title>DISTRO_IMG</title>
|
||||||
|
<path fill="royalblue" stroke="black" d="M893.5,-887.48C893.5,-889.28 868.18,-890.75 837,-890.75 805.82,-890.75 780.5,-889.28 780.5,-887.48 780.5,-887.48 780.5,-858.02 780.5,-858.02 780.5,-856.22 805.82,-854.75 837,-854.75 868.18,-854.75 893.5,-856.22 893.5,-858.02 893.5,-858.02 893.5,-887.48 893.5,-887.48"/>
|
||||||
|
<path fill="none" stroke="black" d="M893.5,-887.48C893.5,-885.67 868.18,-884.2 837,-884.2 805.82,-884.2 780.5,-885.67 780.5,-887.48"/>
|
||||||
|
<text text-anchor="middle" x="837" y="-869.05" font-family="Times,serif" font-size="14.00">ubuntu:latest</text>
|
||||||
|
</g>
|
||||||
|
<!-- ENV_IMG -->
|
||||||
|
<g id="node5" class="node">
|
||||||
|
<title>ENV_IMG</title>
|
||||||
|
<path fill="royalblue" stroke="black" d="M1005,-777.1C1005,-779.74 961.52,-781.88 908,-781.88 854.48,-781.88 811,-779.74 811,-777.1 811,-777.1 811,-734.15 811,-734.15 811,-731.51 854.48,-729.37 908,-729.37 961.52,-729.37 1005,-731.51 1005,-734.15 1005,-734.15 1005,-777.1 1005,-777.1"/>
|
||||||
|
<path fill="none" stroke="black" d="M1005,-777.1C1005,-774.47 961.52,-772.33 908,-772.33 854.48,-772.33 811,-774.47 811,-777.1"/>
|
||||||
|
<text text-anchor="middle" x="908" y="-759.42" font-family="Times,serif" font-size="14.00">cpu_features:amd64_env</text>
|
||||||
|
<text text-anchor="middle" x="908" y="-744.42" font-family="Times,serif" font-size="14.00">env</text>
|
||||||
|
</g>
|
||||||
|
<!-- DISTRO_IMG->ENV_IMG -->
|
||||||
|
<g id="edge10" class="edge">
|
||||||
|
<title>DISTRO_IMG->ENV_IMG</title>
|
||||||
|
<path fill="none" stroke="black" d="M847.78,-854.26C858.17,-837.42 874.16,-811.49 887.05,-790.59"/>
|
||||||
|
<polygon fill="black" stroke="black" points="890.09,-792.33 892.37,-781.98 884.14,-788.65 890.09,-792.33"/>
|
||||||
|
</g>
|
||||||
|
<!-- PKG -->
|
||||||
|
<g id="node2" class="node">
|
||||||
|
<title>PKG</title>
|
||||||
|
<polygon fill="royalblue" stroke="black" points="1046.5,-891.75 915.5,-891.75 911.5,-887.75 911.5,-853.75 1042.5,-853.75 1046.5,-857.75 1046.5,-891.75"/>
|
||||||
|
<polyline fill="none" stroke="black" points="1042.5,-887.75 911.5,-887.75 "/>
|
||||||
|
<polyline fill="none" stroke="black" points="1042.5,-887.75 1042.5,-853.75 "/>
|
||||||
|
<polyline fill="none" stroke="black" points="1042.5,-887.75 1046.5,-891.75 "/>
|
||||||
|
<text text-anchor="middle" x="979" y="-876.55" font-family="Times,serif" font-size="14.00">packages</text>
|
||||||
|
<text text-anchor="middle" x="979" y="-861.55" font-family="Times,serif" font-size="14.00">e.g. cmake, g++</text>
|
||||||
|
</g>
|
||||||
|
<!-- PKG->ENV_IMG -->
|
||||||
|
<g id="edge11" class="edge">
|
||||||
|
<title>PKG->ENV_IMG</title>
|
||||||
|
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M967.75,-853.51C957.4,-836.72 941.77,-811.38 929.09,-790.83"/>
|
||||||
|
<polygon fill="black" stroke="black" points="931.91,-788.73 923.69,-782.06 925.96,-792.41 931.91,-788.73"/>
|
||||||
|
<text text-anchor="middle" x="978.5" y="-824.55" font-family="Times,serif" font-size="14.00">install</text>
|
||||||
|
</g>
|
||||||
|
<!-- SRC -->
|
||||||
|
<g id="node3" class="node">
|
||||||
|
<title>SRC</title>
|
||||||
|
<polygon fill="royalblue" stroke="black" points="1334.5,-773.62 1331.5,-777.62 1310.5,-777.62 1307.5,-773.62 1261.5,-773.62 1261.5,-737.62 1334.5,-737.62 1334.5,-773.62"/>
|
||||||
|
<text text-anchor="middle" x="1298" y="-751.92" font-family="Times,serif" font-size="14.00">git repo</text>
|
||||||
|
</g>
|
||||||
|
<!-- DEVEL_IMG -->
|
||||||
|
<g id="node6" class="node">
|
||||||
|
<title>DEVEL_IMG</title>
|
||||||
|
<path fill="royalblue" stroke="black" d="M1189,-673.85C1189,-676.49 1142.83,-678.63 1086,-678.63 1029.17,-678.63 983,-676.49 983,-673.85 983,-673.85 983,-630.9 983,-630.9 983,-628.26 1029.17,-626.12 1086,-626.12 1142.83,-626.12 1189,-628.26 1189,-630.9 1189,-630.9 1189,-673.85 1189,-673.85"/>
|
||||||
|
<path fill="none" stroke="black" d="M1189,-673.85C1189,-671.22 1142.83,-669.08 1086,-669.08 1029.17,-669.08 983,-671.22 983,-673.85"/>
|
||||||
|
<text text-anchor="middle" x="1086" y="-656.17" font-family="Times,serif" font-size="14.00">cpu_features:amd64_devel</text>
|
||||||
|
<text text-anchor="middle" x="1086" y="-641.17" font-family="Times,serif" font-size="14.00">devel</text>
|
||||||
|
</g>
|
||||||
|
<!-- SRC->DEVEL_IMG -->
|
||||||
|
<g id="edge12" class="edge">
|
||||||
|
<title>SRC->DEVEL_IMG</title>
|
||||||
|
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M1271.39,-737.62C1266.66,-734.8 1261.73,-731.99 1257,-729.5 1224.81,-712.57 1188.08,-695.89 1156.94,-682.48"/>
|
||||||
|
<polygon fill="black" stroke="black" points="1158.03,-679.14 1147.46,-678.43 1155.28,-685.58 1158.03,-679.14"/>
|
||||||
|
<text text-anchor="middle" x="1237" y="-700.3" font-family="Times,serif" font-size="14.00">copy</text>
|
||||||
|
</g>
|
||||||
|
<!-- SPL -->
|
||||||
|
<g id="node4" class="node">
|
||||||
|
<title>SPL</title>
|
||||||
|
<polygon fill="royalblue" stroke="black" points="767,-477.88 764,-481.88 743,-481.88 740,-477.88 699,-477.88 699,-441.88 767,-441.88 767,-477.88"/>
|
||||||
|
<text text-anchor="middle" x="733" y="-456.18" font-family="Times,serif" font-size="14.00">sample</text>
|
||||||
|
</g>
|
||||||
|
<!-- INSTALL_DEVEL_IMG -->
|
||||||
|
<g id="node10" class="node">
|
||||||
|
<title>INSTALL_DEVEL_IMG</title>
|
||||||
|
<path fill="royalblue" stroke="black" d="M956.5,-378.1C956.5,-380.74 898.9,-382.88 828,-382.88 757.1,-382.88 699.5,-380.74 699.5,-378.1 699.5,-378.1 699.5,-335.15 699.5,-335.15 699.5,-332.51 757.1,-330.37 828,-330.37 898.9,-330.37 956.5,-332.51 956.5,-335.15 956.5,-335.15 956.5,-378.1 956.5,-378.1"/>
|
||||||
|
<path fill="none" stroke="black" d="M956.5,-378.1C956.5,-375.47 898.9,-373.33 828,-373.33 757.1,-373.33 699.5,-375.47 699.5,-378.1"/>
|
||||||
|
<text text-anchor="middle" x="828" y="-360.43" font-family="Times,serif" font-size="14.00">cpu_features:amd64_install_devel</text>
|
||||||
|
<text text-anchor="middle" x="828" y="-345.43" font-family="Times,serif" font-size="14.00">install_devel</text>
|
||||||
|
</g>
|
||||||
|
<!-- SPL->INSTALL_DEVEL_IMG -->
|
||||||
|
<g id="edge7" class="edge">
|
||||||
|
<title>SPL->INSTALL_DEVEL_IMG</title>
|
||||||
|
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M749.12,-441.7C762.24,-427.71 781.16,-407.54 797.18,-390.47"/>
|
||||||
|
<polygon fill="black" stroke="black" points="800.02,-392.56 804.31,-382.87 794.91,-387.77 800.02,-392.56"/>
|
||||||
|
<text text-anchor="middle" x="803" y="-404.55" font-family="Times,serif" font-size="14.00">copy</text>
|
||||||
|
</g>
|
||||||
|
<!-- ENV_IMG->DEVEL_IMG -->
|
||||||
|
<g id="edge1" class="edge">
|
||||||
|
<title>ENV_IMG->DEVEL_IMG</title>
|
||||||
|
<path fill="none" stroke="black" d="M952.46,-729.34C976.87,-715.45 1007.3,-698.14 1032.95,-683.55"/>
|
||||||
|
<polygon fill="black" stroke="black" points="1034.84,-686.5 1041.8,-678.52 1031.38,-680.42 1034.84,-686.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- INSTALL_ENV_IMG -->
|
||||||
|
<g id="node9" class="node">
|
||||||
|
<title>INSTALL_ENV_IMG</title>
|
||||||
|
<path fill="royalblue" stroke="black" d="M1030.5,-481.35C1030.5,-483.99 975.59,-486.13 908,-486.13 840.41,-486.13 785.5,-483.99 785.5,-481.35 785.5,-481.35 785.5,-438.4 785.5,-438.4 785.5,-435.76 840.41,-433.62 908,-433.62 975.59,-433.62 1030.5,-435.76 1030.5,-438.4 1030.5,-438.4 1030.5,-481.35 1030.5,-481.35"/>
|
||||||
|
<path fill="none" stroke="black" d="M1030.5,-481.35C1030.5,-478.72 975.59,-476.58 908,-476.58 840.41,-476.58 785.5,-478.72 785.5,-481.35"/>
|
||||||
|
<text text-anchor="middle" x="908" y="-463.68" font-family="Times,serif" font-size="14.00">cpu_features:amd64_install_env</text>
|
||||||
|
<text text-anchor="middle" x="908" y="-448.68" font-family="Times,serif" font-size="14.00">install_env</text>
|
||||||
|
</g>
|
||||||
|
<!-- ENV_IMG->INSTALL_ENV_IMG -->
|
||||||
|
<g id="edge4" class="edge">
|
||||||
|
<title>ENV_IMG->INSTALL_ENV_IMG</title>
|
||||||
|
<path fill="none" stroke="black" d="M908,-729.33C908,-676.94 908,-556.49 908,-496.37"/>
|
||||||
|
<polygon fill="black" stroke="black" points="911.5,-496.22 908,-486.22 904.5,-496.22 911.5,-496.22"/>
|
||||||
|
</g>
|
||||||
|
<!-- ENV_TAR -->
|
||||||
|
<g id="node13" class="node">
|
||||||
|
<title>ENV_TAR</title>
|
||||||
|
<polygon fill="royalblue" stroke="black" points="186,-52 16,-52 16,-16 192,-16 192,-46 186,-52"/>
|
||||||
|
<polyline fill="none" stroke="black" points="186,-52 186,-46 "/>
|
||||||
|
<polyline fill="none" stroke="black" points="192,-46 186,-46 "/>
|
||||||
|
<text text-anchor="middle" x="104" y="-30.3" font-family="Times,serif" font-size="14.00">docker_amd64_env.tar</text>
|
||||||
|
</g>
|
||||||
|
<!-- ENV_IMG->ENV_TAR -->
|
||||||
|
<g id="edge13" class="edge">
|
||||||
|
<title>ENV_IMG->ENV_TAR</title>
|
||||||
|
<path fill="none" stroke="red" d="M810.87,-751.31C609.47,-743.14 165,-717.82 165,-653.38 165,-653.38 165,-653.38 165,-149.12 165,-115.26 143.85,-81.71 126.46,-59.84"/>
|
||||||
|
<polygon fill="red" stroke="red" points="129.09,-57.54 120.03,-52.05 123.7,-61.99 129.09,-57.54"/>
|
||||||
|
<text text-anchor="middle" x="246.5" y="-404.55" font-family="Times,serif" font-size="14.00">make save_amd64_env</text>
|
||||||
|
</g>
|
||||||
|
<!-- BUILD_IMG -->
|
||||||
|
<g id="node7" class="node">
|
||||||
|
<title>BUILD_IMG</title>
|
||||||
|
<path fill="royalblue" stroke="black" d="M1245,-584.6C1245,-587.24 1199.28,-589.38 1143,-589.38 1086.72,-589.38 1041,-587.24 1041,-584.6 1041,-584.6 1041,-541.65 1041,-541.65 1041,-539.01 1086.72,-536.87 1143,-536.87 1199.28,-536.87 1245,-539.01 1245,-541.65 1245,-541.65 1245,-584.6 1245,-584.6"/>
|
||||||
|
<path fill="none" stroke="black" d="M1245,-584.6C1245,-581.97 1199.28,-579.83 1143,-579.83 1086.72,-579.83 1041,-581.97 1041,-584.6"/>
|
||||||
|
<text text-anchor="middle" x="1143" y="-566.92" font-family="Times,serif" font-size="14.00">cpu_features:amd64_build</text>
|
||||||
|
<text text-anchor="middle" x="1143" y="-551.92" font-family="Times,serif" font-size="14.00">build</text>
|
||||||
|
</g>
|
||||||
|
<!-- DEVEL_IMG->BUILD_IMG -->
|
||||||
|
<g id="edge2" class="edge">
|
||||||
|
<title>DEVEL_IMG->BUILD_IMG</title>
|
||||||
|
<path fill="none" stroke="black" d="M1102.49,-626.14C1108.28,-617.28 1114.88,-607.17 1121.04,-597.73"/>
|
||||||
|
<polygon fill="black" stroke="black" points="1124.01,-599.59 1126.55,-589.3 1118.15,-595.76 1124.01,-599.59"/>
|
||||||
|
</g>
|
||||||
|
<!-- DEVEL_TAR -->
|
||||||
|
<g id="node14" class="node">
|
||||||
|
<title>DEVEL_TAR</title>
|
||||||
|
<polygon fill="royalblue" stroke="black" points="395.5,-52 210.5,-52 210.5,-16 401.5,-16 401.5,-46 395.5,-52"/>
|
||||||
|
<polyline fill="none" stroke="black" points="395.5,-52 395.5,-46 "/>
|
||||||
|
<polyline fill="none" stroke="black" points="401.5,-46 395.5,-46 "/>
|
||||||
|
<text text-anchor="middle" x="306" y="-30.3" font-family="Times,serif" font-size="14.00">docker_amd64_devel.tar</text>
|
||||||
|
</g>
|
||||||
|
<!-- DEVEL_IMG->DEVEL_TAR -->
|
||||||
|
<g id="edge14" class="edge">
|
||||||
|
<title>DEVEL_IMG->DEVEL_TAR</title>
|
||||||
|
<path fill="none" stroke="red" d="M982.94,-648.59C792.56,-642.05 405,-621.67 405,-564.12 405,-564.12 405,-564.12 405,-149.12 405,-110.26 371.83,-78.15 343.9,-58"/>
|
||||||
|
<polygon fill="red" stroke="red" points="345.65,-54.96 335.44,-52.14 341.66,-60.71 345.65,-54.96"/>
|
||||||
|
<text text-anchor="middle" x="493" y="-352.93" font-family="Times,serif" font-size="14.00">make save_amd64_devel</text>
|
||||||
|
</g>
|
||||||
|
<!-- TEST_IMG -->
|
||||||
|
<g id="node8" class="node">
|
||||||
|
<title>TEST_IMG</title>
|
||||||
|
<path fill="royalblue" stroke="black" d="M1245,-481.35C1245,-483.99 1201.07,-486.13 1147,-486.13 1092.93,-486.13 1049,-483.99 1049,-481.35 1049,-481.35 1049,-438.4 1049,-438.4 1049,-435.76 1092.93,-433.62 1147,-433.62 1201.07,-433.62 1245,-435.76 1245,-438.4 1245,-438.4 1245,-481.35 1245,-481.35"/>
|
||||||
|
<path fill="none" stroke="black" d="M1245,-481.35C1245,-478.72 1201.07,-476.58 1147,-476.58 1092.93,-476.58 1049,-478.72 1049,-481.35"/>
|
||||||
|
<text text-anchor="middle" x="1147" y="-463.68" font-family="Times,serif" font-size="14.00">cpu_features:amd64_test</text>
|
||||||
|
<text text-anchor="middle" x="1147" y="-448.68" font-family="Times,serif" font-size="14.00">test</text>
|
||||||
|
</g>
|
||||||
|
<!-- BUILD_IMG->TEST_IMG -->
|
||||||
|
<g id="edge3" class="edge">
|
||||||
|
<title>BUILD_IMG->TEST_IMG</title>
|
||||||
|
<path fill="none" stroke="black" d="M1144,-536.84C1144.48,-524.63 1145.07,-509.79 1145.59,-496.47"/>
|
||||||
|
<polygon fill="black" stroke="black" points="1149.1,-496.32 1146,-486.19 1142.11,-496.05 1149.1,-496.32"/>
|
||||||
|
</g>
|
||||||
|
<!-- BUILD_IMG->INSTALL_ENV_IMG -->
|
||||||
|
<g id="edge5" class="edge">
|
||||||
|
<title>BUILD_IMG->INSTALL_ENV_IMG</title>
|
||||||
|
<path fill="none" stroke="black" stroke-dasharray="5,2" d="M1084.61,-536.97C1051.68,-522.78 1010.38,-504.99 976,-490.17"/>
|
||||||
|
<polygon fill="black" stroke="black" points="977.07,-486.82 966.5,-486.08 974.3,-493.25 977.07,-486.82"/>
|
||||||
|
<text text-anchor="middle" x="1080" y="-507.8" font-family="Times,serif" font-size="14.00">copy install</text>
|
||||||
|
</g>
|
||||||
|
<!-- BUILD_TAR -->
|
||||||
|
<g id="node15" class="node">
|
||||||
|
<title>BUILD_TAR</title>
|
||||||
|
<polygon fill="royalblue" stroke="black" points="1812,-52 1630,-52 1630,-16 1818,-16 1818,-46 1812,-52"/>
|
||||||
|
<polyline fill="none" stroke="black" points="1812,-52 1812,-46 "/>
|
||||||
|
<polyline fill="none" stroke="black" points="1818,-46 1812,-46 "/>
|
||||||
|
<text text-anchor="middle" x="1724" y="-30.3" font-family="Times,serif" font-size="14.00">docker_amd64_build.tar</text>
|
||||||
|
</g>
|
||||||
|
<!-- BUILD_IMG->BUILD_TAR -->
|
||||||
|
<g id="edge15" class="edge">
|
||||||
|
<title>BUILD_IMG->BUILD_TAR</title>
|
||||||
|
<path fill="none" stroke="red" d="M1245.18,-554.53C1411.4,-540.79 1722,-508.71 1722,-460.88 1722,-460.88 1722,-460.88 1722,-149.12 1722,-119.36 1722.69,-85.23 1723.26,-62.11"/>
|
||||||
|
<polygon fill="red" stroke="red" points="1726.76,-62.1 1723.52,-52.01 1719.76,-61.92 1726.76,-62.1"/>
|
||||||
|
<text text-anchor="middle" x="1809" y="-301.3" font-family="Times,serif" font-size="14.00">make save_amd64_build</text>
|
||||||
|
</g>
|
||||||
|
<!-- TEST_TAR -->
|
||||||
|
<g id="node16" class="node">
|
||||||
|
<title>TEST_TAR</title>
|
||||||
|
<polygon fill="royalblue" stroke="black" points="1606,-52 1432,-52 1432,-16 1612,-16 1612,-46 1606,-52"/>
|
||||||
|
<polyline fill="none" stroke="black" points="1606,-52 1606,-46 "/>
|
||||||
|
<polyline fill="none" stroke="black" points="1612,-46 1606,-46 "/>
|
||||||
|
<text text-anchor="middle" x="1522" y="-30.3" font-family="Times,serif" font-size="14.00">docker_amd64_test.tar</text>
|
||||||
|
</g>
|
||||||
|
<!-- TEST_IMG->TEST_TAR -->
|
||||||
|
<g id="edge16" class="edge">
|
||||||
|
<title>TEST_IMG->TEST_TAR</title>
|
||||||
|
<path fill="none" stroke="red" d="M1245.07,-451.87C1356.77,-441.13 1524,-415.4 1524,-357.62 1524,-357.62 1524,-357.62 1524,-149.12 1524,-119.36 1523.31,-85.23 1522.74,-62.11"/>
|
||||||
|
<polygon fill="red" stroke="red" points="1526.24,-61.92 1522.48,-52.01 1519.24,-62.1 1526.24,-61.92"/>
|
||||||
|
<text text-anchor="middle" x="1607" y="-249.68" font-family="Times,serif" font-size="14.00">make save_amd64_test</text>
|
||||||
|
</g>
|
||||||
|
<!-- INSTALL_ENV_IMG->INSTALL_DEVEL_IMG -->
|
||||||
|
<g id="edge6" class="edge">
|
||||||
|
<title>INSTALL_ENV_IMG->INSTALL_DEVEL_IMG</title>
|
||||||
|
<path fill="none" stroke="black" d="M888.02,-433.59C877.81,-420.66 865.25,-404.76 854.26,-390.86"/>
|
||||||
|
<polygon fill="black" stroke="black" points="856.95,-388.62 848,-382.94 851.46,-392.96 856.95,-388.62"/>
|
||||||
|
</g>
|
||||||
|
<!-- INSTALL_ENV_TAR -->
|
||||||
|
<g id="node17" class="node">
|
||||||
|
<title>INSTALL_ENV_TAR</title>
|
||||||
|
<polygon fill="royalblue" stroke="black" points="1407.5,-52 1186.5,-52 1186.5,-16 1413.5,-16 1413.5,-46 1407.5,-52"/>
|
||||||
|
<polyline fill="none" stroke="black" points="1407.5,-52 1407.5,-46 "/>
|
||||||
|
<polyline fill="none" stroke="black" points="1413.5,-46 1407.5,-46 "/>
|
||||||
|
<text text-anchor="middle" x="1300" y="-30.3" font-family="Times,serif" font-size="14.00">docker_amd64_install_env.tar</text>
|
||||||
|
</g>
|
||||||
|
<!-- INSTALL_ENV_IMG->INSTALL_ENV_TAR -->
|
||||||
|
<g id="edge17" class="edge">
|
||||||
|
<title>INSTALL_ENV_IMG->INSTALL_ENV_TAR</title>
|
||||||
|
<path fill="none" stroke="red" d="M1012.88,-434.97C1121.03,-409.58 1274,-371.26 1274,-357.62 1274,-357.62 1274,-357.62 1274,-149.12 1274,-118.64 1282.93,-84.69 1290.32,-61.81"/>
|
||||||
|
<polygon fill="red" stroke="red" points="1293.71,-62.72 1293.57,-52.12 1287.07,-60.49 1293.71,-62.72"/>
|
||||||
|
<text text-anchor="middle" x="1381" y="-249.68" font-family="Times,serif" font-size="14.00">make save_amd64_install_env</text>
|
||||||
|
</g>
|
||||||
|
<!-- INSTALL_BUILD_IMG -->
|
||||||
|
<g id="node11" class="node">
|
||||||
|
<title>INSTALL_BUILD_IMG</title>
|
||||||
|
<path fill="royalblue" stroke="black" d="M955.5,-274.85C955.5,-277.49 898.35,-279.63 828,-279.63 757.65,-279.63 700.5,-277.49 700.5,-274.85 700.5,-274.85 700.5,-231.9 700.5,-231.9 700.5,-229.26 757.65,-227.12 828,-227.12 898.35,-227.12 955.5,-229.26 955.5,-231.9 955.5,-231.9 955.5,-274.85 955.5,-274.85"/>
|
||||||
|
<path fill="none" stroke="black" d="M955.5,-274.85C955.5,-272.22 898.35,-270.08 828,-270.08 757.65,-270.08 700.5,-272.22 700.5,-274.85"/>
|
||||||
|
<text text-anchor="middle" x="828" y="-257.18" font-family="Times,serif" font-size="14.00">cpu_features:amd64_install_build</text>
|
||||||
|
<text text-anchor="middle" x="828" y="-242.18" font-family="Times,serif" font-size="14.00">install_build</text>
|
||||||
|
</g>
|
||||||
|
<!-- INSTALL_DEVEL_IMG->INSTALL_BUILD_IMG -->
|
||||||
|
<g id="edge8" class="edge">
|
||||||
|
<title>INSTALL_DEVEL_IMG->INSTALL_BUILD_IMG</title>
|
||||||
|
<path fill="none" stroke="black" d="M828,-330.34C828,-318.13 828,-303.29 828,-289.97"/>
|
||||||
|
<polygon fill="black" stroke="black" points="831.5,-289.69 828,-279.69 824.5,-289.69 831.5,-289.69"/>
|
||||||
|
</g>
|
||||||
|
<!-- INSTALL_DEVEL_TAR -->
|
||||||
|
<g id="node18" class="node">
|
||||||
|
<title>INSTALL_DEVEL_TAR</title>
|
||||||
|
<polygon fill="royalblue" stroke="black" points="656,-52 420,-52 420,-16 662,-16 662,-46 656,-52"/>
|
||||||
|
<polyline fill="none" stroke="black" points="656,-52 656,-46 "/>
|
||||||
|
<polyline fill="none" stroke="black" points="662,-46 656,-46 "/>
|
||||||
|
<text text-anchor="middle" x="541" y="-30.3" font-family="Times,serif" font-size="14.00">docker_amd64_install_devel.tar</text>
|
||||||
|
</g>
|
||||||
|
<!-- INSTALL_DEVEL_IMG->INSTALL_DEVEL_TAR -->
|
||||||
|
<g id="edge18" class="edge">
|
||||||
|
<title>INSTALL_DEVEL_IMG->INSTALL_DEVEL_TAR</title>
|
||||||
|
<path fill="none" stroke="red" d="M761.39,-330.48C708.37,-307.05 636.42,-266.99 595,-209.25 562.63,-164.12 549.27,-99.06 544.06,-62.54"/>
|
||||||
|
<polygon fill="red" stroke="red" points="547.47,-61.64 542.7,-52.18 540.53,-62.55 547.47,-61.64"/>
|
||||||
|
<text text-anchor="middle" x="708.5" y="-198.05" font-family="Times,serif" font-size="14.00">make save_amd64_install_devel</text>
|
||||||
|
</g>
|
||||||
|
<!-- INSTALL_TEST_IMG -->
|
||||||
|
<g id="node12" class="node">
|
||||||
|
<title>INSTALL_TEST_IMG</title>
|
||||||
|
<path fill="royalblue" stroke="black" d="M948.5,-171.6C948.5,-174.24 893.15,-176.38 825,-176.38 756.85,-176.38 701.5,-174.24 701.5,-171.6 701.5,-171.6 701.5,-128.65 701.5,-128.65 701.5,-126.01 756.85,-123.87 825,-123.87 893.15,-123.87 948.5,-126.01 948.5,-128.65 948.5,-128.65 948.5,-171.6 948.5,-171.6"/>
|
||||||
|
<path fill="none" stroke="black" d="M948.5,-171.6C948.5,-168.97 893.15,-166.83 825,-166.83 756.85,-166.83 701.5,-168.97 701.5,-171.6"/>
|
||||||
|
<text text-anchor="middle" x="825" y="-153.93" font-family="Times,serif" font-size="14.00">cpu_features:amd64_install_test</text>
|
||||||
|
<text text-anchor="middle" x="825" y="-138.93" font-family="Times,serif" font-size="14.00">install_test</text>
|
||||||
|
</g>
|
||||||
|
<!-- INSTALL_BUILD_IMG->INSTALL_TEST_IMG -->
|
||||||
|
<g id="edge9" class="edge">
|
||||||
|
<title>INSTALL_BUILD_IMG->INSTALL_TEST_IMG</title>
|
||||||
|
<path fill="none" stroke="black" d="M827.25,-227.09C826.89,-214.88 826.45,-200.04 826.05,-186.72"/>
|
||||||
|
<polygon fill="black" stroke="black" points="829.54,-186.33 825.75,-176.44 822.55,-186.54 829.54,-186.33"/>
|
||||||
|
</g>
|
||||||
|
<!-- INSTALL_BUILD_TAR -->
|
||||||
|
<g id="node19" class="node">
|
||||||
|
<title>INSTALL_BUILD_TAR</title>
|
||||||
|
<polygon fill="royalblue" stroke="black" points="1162.5,-52 929.5,-52 929.5,-16 1168.5,-16 1168.5,-46 1162.5,-52"/>
|
||||||
|
<polyline fill="none" stroke="black" points="1162.5,-52 1162.5,-46 "/>
|
||||||
|
<polyline fill="none" stroke="black" points="1168.5,-46 1162.5,-46 "/>
|
||||||
|
<text text-anchor="middle" x="1049" y="-30.3" font-family="Times,serif" font-size="14.00">docker_amd64_install_build.tar</text>
|
||||||
|
</g>
|
||||||
|
<!-- INSTALL_BUILD_IMG->INSTALL_BUILD_TAR -->
|
||||||
|
<g id="edge19" class="edge">
|
||||||
|
<title>INSTALL_BUILD_IMG->INSTALL_BUILD_TAR</title>
|
||||||
|
<path fill="none" stroke="red" d="M882.76,-227.11C907.43,-214.09 935.91,-196.66 958,-176.25 994.16,-142.85 1022.19,-92.11 1037.09,-61.41"/>
|
||||||
|
<polygon fill="red" stroke="red" points="1040.34,-62.72 1041.46,-52.19 1034.02,-59.72 1040.34,-62.72"/>
|
||||||
|
<text text-anchor="middle" x="1117.5" y="-146.43" font-family="Times,serif" font-size="14.00">make save_amd64_install_build</text>
|
||||||
|
</g>
|
||||||
|
<!-- INSTALL_TEST_TAR -->
|
||||||
|
<g id="node20" class="node">
|
||||||
|
<title>INSTALL_TEST_TAR</title>
|
||||||
|
<polygon fill="royalblue" stroke="black" points="905.5,-52 680.5,-52 680.5,-16 911.5,-16 911.5,-46 905.5,-52"/>
|
||||||
|
<polyline fill="none" stroke="black" points="905.5,-52 905.5,-46 "/>
|
||||||
|
<polyline fill="none" stroke="black" points="911.5,-46 905.5,-46 "/>
|
||||||
|
<text text-anchor="middle" x="796" y="-30.3" font-family="Times,serif" font-size="14.00">docker_amd64_install_test.tar</text>
|
||||||
|
</g>
|
||||||
|
<!-- INSTALL_TEST_IMG->INSTALL_TEST_TAR -->
|
||||||
|
<g id="edge20" class="edge">
|
||||||
|
<title>INSTALL_TEST_IMG->INSTALL_TEST_TAR</title>
|
||||||
|
<path fill="none" stroke="red" d="M799.99,-123.98C795.9,-118.47 792.26,-112.36 790,-106 785.07,-92.11 786.03,-75.77 788.46,-62.27"/>
|
||||||
|
<polygon fill="red" stroke="red" points="791.96,-62.66 790.65,-52.15 785.12,-61.19 791.96,-62.66"/>
|
||||||
|
<text text-anchor="middle" x="898.5" y="-94.8" font-family="Times,serif" font-size="14.00">make save_amd64_install_test</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 21 KiB |
@@ -0,0 +1,7 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
rm -f ./*.svg ./*.png
|
||||||
|
for i in *.dot; do
|
||||||
|
plantuml -Tsvg "$i";
|
||||||
|
done
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
# Create a virtual environment with all tools installed
|
||||||
|
# ref: https://hub.docker.com/_/ubuntu
|
||||||
|
FROM ubuntu:latest AS env
|
||||||
|
LABEL maintainer="corentinl@google.com"
|
||||||
|
# Install system build dependencies
|
||||||
|
ENV PATH=/usr/local/bin:$PATH
|
||||||
|
RUN apt-get update -qq \
|
||||||
|
&& DEBIAN_FRONTEND=noninteractive apt-get install -yq git wget libssl-dev build-essential \
|
||||||
|
ninja-build python3 pkgconf libglib2.0-dev \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||||
|
ENTRYPOINT ["/usr/bin/bash", "-c"]
|
||||||
|
CMD ["/usr/bin/bash"]
|
||||||
|
|
||||||
|
# Install CMake 3.21.3
|
||||||
|
RUN wget "https://cmake.org/files/v3.21/cmake-3.21.3-linux-x86_64.sh" \
|
||||||
|
&& chmod a+x cmake-3.21.3-linux-x86_64.sh \
|
||||||
|
&& ./cmake-3.21.3-linux-x86_64.sh --prefix=/usr/local/ --skip-license \
|
||||||
|
&& rm cmake-3.21.3-linux-x86_64.sh
|
||||||
|
|
||||||
|
FROM env AS devel
|
||||||
|
WORKDIR /home/project
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
FROM devel AS build
|
||||||
|
RUN cmake -version
|
||||||
|
RUN cmake -S. -Bbuild
|
||||||
|
RUN cmake --build build --target all -v
|
||||||
|
RUN cmake --build build --target install -v
|
||||||
|
|
||||||
|
FROM build AS test
|
||||||
|
ENV CTEST_OUTPUT_ON_FAILURE=1
|
||||||
|
RUN cmake --build build --target test -v
|
||||||
|
|
||||||
|
# Test install rules
|
||||||
|
FROM env AS install_env
|
||||||
|
COPY --from=build /usr/local /usr/local/
|
||||||
|
|
||||||
|
FROM install_env AS install_devel
|
||||||
|
WORKDIR /home/sample
|
||||||
|
COPY cmake/ci/sample .
|
||||||
|
|
||||||
|
FROM install_devel AS install_build
|
||||||
|
RUN cmake -S. -Bbuild
|
||||||
|
RUN cmake --build build --target all -v
|
||||||
|
|
||||||
|
FROM install_build AS install_test
|
||||||
|
RUN cmake --build build --target test
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
# Create a virtual environment with all tools installed
|
||||||
|
# ref: https://hub.docker.com/_/ubuntu
|
||||||
|
FROM ubuntu:latest AS env
|
||||||
|
LABEL maintainer="corentinl@google.com"
|
||||||
|
# Install system build dependencies
|
||||||
|
ENV PATH=/usr/local/bin:$PATH
|
||||||
|
RUN apt-get update -qq \
|
||||||
|
&& DEBIAN_FRONTEND=noninteractive apt-get install -yq git wget libssl-dev build-essential \
|
||||||
|
ninja-build python3 pkgconf libglib2.0-dev \
|
||||||
|
&& apt-get clean \
|
||||||
|
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||||
|
ENTRYPOINT ["/usr/bin/bash", "-c"]
|
||||||
|
CMD ["/usr/bin/bash"]
|
||||||
|
|
||||||
|
# Install CMake 3.21.3
|
||||||
|
RUN wget "https://cmake.org/files/v3.21/cmake-3.21.3-linux-x86_64.sh" \
|
||||||
|
&& chmod a+x cmake-3.21.3-linux-x86_64.sh \
|
||||||
|
&& ./cmake-3.21.3-linux-x86_64.sh --prefix=/usr/local/ --skip-license \
|
||||||
|
&& rm cmake-3.21.3-linux-x86_64.sh
|
||||||
|
|
||||||
|
FROM env AS devel
|
||||||
|
WORKDIR /home/project
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
ARG TARGET
|
||||||
|
ENV TARGET ${TARGET:-unknown}
|
||||||
|
|
||||||
|
FROM devel AS build
|
||||||
|
RUN cmake -version
|
||||||
|
RUN ./scripts/run_integration.sh build
|
||||||
|
|
||||||
|
FROM build AS test
|
||||||
|
RUN ./scripts/run_integration.sh qemu
|
||||||
|
RUN ./scripts/run_integration.sh test
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.15)
|
||||||
|
project(Sample VERSION 1.0.0 LANGUAGES CXX)
|
||||||
|
|
||||||
|
include(CTest)
|
||||||
|
find_package(CpuFeatures REQUIRED)
|
||||||
|
|
||||||
|
add_executable(sample main.cpp)
|
||||||
|
target_compile_features(sample PUBLIC cxx_std_11)
|
||||||
|
set_target_properties(sample PROPERTIES
|
||||||
|
CXX_STANDARD 11
|
||||||
|
CXX_STANDARD_REQUIRED ON
|
||||||
|
VERSION ${PROJECT_VERSION})
|
||||||
|
target_link_libraries(sample PRIVATE CpuFeatures::cpu_features)
|
||||||
|
|
||||||
|
if(BUILD_TESTING)
|
||||||
|
add_test(NAME sample_test COMMAND sample)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
install(TARGETS sample
|
||||||
|
EXPORT SampleTargets
|
||||||
|
DESTINATION ${CMAKE_INSTALL_BIN_DIR})
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "cpuinfo_x86.h"
|
||||||
|
|
||||||
|
using namespace cpu_features;
|
||||||
|
|
||||||
|
int main(int /*argc*/, char** /*argv*/) {
|
||||||
|
static const X86Features features = GetX86Info().features;
|
||||||
|
std::cout << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
# -*- mode: ruby -*-
|
||||||
|
# vi: set ft=ruby :
|
||||||
|
|
||||||
|
# All Vagrant configuration is done below. The "2" in Vagrant.configure
|
||||||
|
# configures the configuration version (we support older styles for
|
||||||
|
# backwards compatibility). Please don't change it unless you know what
|
||||||
|
# you're doing.
|
||||||
|
Vagrant.configure("2") do |config|
|
||||||
|
# The most common configuration options are documented and commented below.
|
||||||
|
# For a complete reference, please see the online documentation at
|
||||||
|
# https://docs.vagrantup.com.
|
||||||
|
|
||||||
|
# Every Vagrant development environment requires a box. You can search for
|
||||||
|
# boxes at https://vagrantcloud.com/search.
|
||||||
|
config.vm.guest = :freebsd
|
||||||
|
config.vm.box = "generic/freebsd12"
|
||||||
|
|
||||||
|
config.ssh.shell = "sh"
|
||||||
|
|
||||||
|
# Disable automatic box update checking. If you disable this, then
|
||||||
|
# boxes will only be checked for updates when the user runs
|
||||||
|
# `vagrant box outdated`. This is not recommended.
|
||||||
|
# config.vm.box_check_update = false
|
||||||
|
|
||||||
|
# Create a forwarded port mapping which allows access to a specific port
|
||||||
|
# within the machine from a port on the host machine. In the example below,
|
||||||
|
# accessing "localhost:8080" will access port 80 on the guest machine.
|
||||||
|
# NOTE: This will enable public access to the opened port
|
||||||
|
# config.vm.network "forwarded_port", guest: 80, host: 8080
|
||||||
|
|
||||||
|
# Create a forwarded port mapping which allows access to a specific port
|
||||||
|
# within the machine from a port on the host machine and only allow access
|
||||||
|
# via 127.0.0.1 to disable public access
|
||||||
|
# config.vm.network "forwarded_port", guest: 80, host: 8080, host_ip: "127.0.0.1"
|
||||||
|
|
||||||
|
# Create a private network, which allows host-only access to the machine
|
||||||
|
# using a specific IP.
|
||||||
|
# config.vm.network "private_network", ip: "192.168.33.10"
|
||||||
|
|
||||||
|
# Create a public network, which generally matched to bridged network.
|
||||||
|
# Bridged networks make the machine appear as another physical device on
|
||||||
|
# your network.
|
||||||
|
# config.vm.network "public_network"
|
||||||
|
|
||||||
|
# Share an additional folder to the guest VM. The first argument is
|
||||||
|
# the path on the host to the actual folder. The second argument is
|
||||||
|
# the path on the guest to mount the folder. And the optional third
|
||||||
|
# argument is a set of non-required options.
|
||||||
|
#config.vm.synced_folder "../../..", "/home/vagrant/project"
|
||||||
|
config.vm.synced_folder ".", "/vagrant", id: "vagrant-root", disabled: true
|
||||||
|
|
||||||
|
config.vm.provision "file", source: "../../../../CMakeLists.txt", destination: "$HOME/project/"
|
||||||
|
config.vm.provision "file", source: "../../../../cmake", destination: "$HOME/project/"
|
||||||
|
config.vm.provision "file", source: "../../../../include", destination: "$HOME/project/"
|
||||||
|
config.vm.provision "file", source: "../../../../src", destination: "$HOME/project/"
|
||||||
|
config.vm.provision "file", source: "../../../../test", destination: "$HOME/project/"
|
||||||
|
|
||||||
|
# Provider-specific configuration so you can fine-tune various
|
||||||
|
# backing providers for Vagrant. These expose provider-specific options.
|
||||||
|
# Example for VirtualBox:
|
||||||
|
#
|
||||||
|
# config.vm.provider "virtualbox" do |vb|
|
||||||
|
# # Display the VirtualBox GUI when booting the machine
|
||||||
|
# vb.gui = true
|
||||||
|
#
|
||||||
|
# # Customize the amount of memory on the VM:
|
||||||
|
# vb.memory = "1024"
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# View the documentation for the provider you are using for more
|
||||||
|
# information on available options.
|
||||||
|
|
||||||
|
# Enable provisioning with a shell script. Additional provisioners such as
|
||||||
|
# Ansible, Chef, Docker, Puppet and Salt are also available. Please see the
|
||||||
|
# documentation for more information about their specific syntax and use.
|
||||||
|
# note: clang installed by default
|
||||||
|
config.vm.provision "env", type: "shell", inline:<<-SHELL
|
||||||
|
set -x
|
||||||
|
pkg update -f
|
||||||
|
pkg install -y git cmake
|
||||||
|
SHELL
|
||||||
|
config.vm.provision "devel", type: "shell", inline:<<-SHELL
|
||||||
|
set -x
|
||||||
|
cd project
|
||||||
|
ls
|
||||||
|
SHELL
|
||||||
|
config.vm.provision "configure", type: "shell", inline:<<-SHELL
|
||||||
|
set -x
|
||||||
|
cd project
|
||||||
|
cmake -S. -Bbuild -DBUILD_TESTING=ON
|
||||||
|
SHELL
|
||||||
|
config.vm.provision "build", type: "shell", inline:<<-SHELL
|
||||||
|
set -x
|
||||||
|
cd project
|
||||||
|
cmake --build build -v
|
||||||
|
SHELL
|
||||||
|
config.vm.provision "test", type: "shell", inline:<<-SHELL
|
||||||
|
set -x
|
||||||
|
cd project
|
||||||
|
cmake --build build --target test -v
|
||||||
|
SHELL
|
||||||
|
config.vm.provision "test", type: "shell", inline:<<-SHELL
|
||||||
|
set -x
|
||||||
|
cd project
|
||||||
|
cmake --build build --target install -v
|
||||||
|
SHELL
|
||||||
|
end
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
cmake_minimum_required(VERSION 2.8.2)
|
||||||
|
|
||||||
|
project(googletest-download NONE)
|
||||||
|
|
||||||
|
include(ExternalProject)
|
||||||
|
ExternalProject_Add(googletest
|
||||||
|
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||||
|
GIT_TAG main
|
||||||
|
SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src"
|
||||||
|
BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build"
|
||||||
|
CONFIGURE_COMMAND ""
|
||||||
|
BUILD_COMMAND ""
|
||||||
|
INSTALL_COMMAND ""
|
||||||
|
TEST_COMMAND ""
|
||||||
|
)
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
// Copyright 2017 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_COMMON_H_
|
||||||
|
#define CPU_FEATURES_INCLUDE_CPUINFO_COMMON_H_
|
||||||
|
|
||||||
|
#include "cpu_features_macros.h"
|
||||||
|
|
||||||
|
CPU_FEATURES_START_CPP_NAMESPACE
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CPU_FEATURE_CACHE_NULL = 0,
|
||||||
|
CPU_FEATURE_CACHE_DATA = 1,
|
||||||
|
CPU_FEATURE_CACHE_INSTRUCTION = 2,
|
||||||
|
CPU_FEATURE_CACHE_UNIFIED = 3,
|
||||||
|
CPU_FEATURE_CACHE_TLB = 4,
|
||||||
|
CPU_FEATURE_CACHE_DTLB = 5,
|
||||||
|
CPU_FEATURE_CACHE_STLB = 6,
|
||||||
|
CPU_FEATURE_CACHE_PREFETCH = 7
|
||||||
|
} CacheType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int level;
|
||||||
|
CacheType cache_type;
|
||||||
|
int cache_size; // Cache size in bytes
|
||||||
|
int ways; // Associativity, 0 undefined, 0xFF fully associative
|
||||||
|
int line_size; // Cache line size in bytes
|
||||||
|
int tlb_entries; // number of entries for TLB
|
||||||
|
int partitioning; // number of lines per sector
|
||||||
|
} CacheLevelInfo;
|
||||||
|
|
||||||
|
// Increase this value if more cache levels are needed.
|
||||||
|
#ifndef CPU_FEATURES_MAX_CACHE_LEVEL
|
||||||
|
#define CPU_FEATURES_MAX_CACHE_LEVEL 10
|
||||||
|
#endif
|
||||||
|
typedef struct {
|
||||||
|
int size;
|
||||||
|
CacheLevelInfo levels[CPU_FEATURES_MAX_CACHE_LEVEL];
|
||||||
|
} CacheInfo;
|
||||||
|
|
||||||
|
CPU_FEATURES_END_CPP_NAMESPACE
|
||||||
|
|
||||||
|
#endif // CPU_FEATURES_INCLUDE_CPUINFO_COMMON_H_
|
||||||
+388
@@ -0,0 +1,388 @@
|
|||||||
|
// Copyright 2017 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#ifndef CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_
|
||||||
|
#define CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Architectures
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if defined(__pnacl__) || defined(__CLR_VER)
|
||||||
|
#define CPU_FEATURES_ARCH_VM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(_M_IX86) || defined(__i386__)) && !defined(CPU_FEATURES_ARCH_VM)
|
||||||
|
#define CPU_FEATURES_ARCH_X86_32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(_M_X64) || defined(__x86_64__)) && !defined(CPU_FEATURES_ARCH_VM)
|
||||||
|
#define CPU_FEATURES_ARCH_X86_64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CPU_FEATURES_ARCH_X86_32) || defined(CPU_FEATURES_ARCH_X86_64)
|
||||||
|
#define CPU_FEATURES_ARCH_X86
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(__arm__) || defined(_M_ARM))
|
||||||
|
#define CPU_FEATURES_ARCH_ARM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(__aarch64__) || defined(_M_ARM64))
|
||||||
|
#define CPU_FEATURES_ARCH_AARCH64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(CPU_FEATURES_ARCH_AARCH64) || defined(CPU_FEATURES_ARCH_ARM))
|
||||||
|
#define CPU_FEATURES_ARCH_ANY_ARM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__mips64)
|
||||||
|
#define CPU_FEATURES_ARCH_MIPS64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__mips__) && !defined(__mips64) // mips64 also declares __mips__
|
||||||
|
#define CPU_FEATURES_ARCH_MIPS32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CPU_FEATURES_ARCH_MIPS32) || defined(CPU_FEATURES_ARCH_MIPS64)
|
||||||
|
#define CPU_FEATURES_ARCH_MIPS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__powerpc__)
|
||||||
|
#define CPU_FEATURES_ARCH_PPC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__s390x__)
|
||||||
|
#define CPU_FEATURES_ARCH_S390X
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__riscv)
|
||||||
|
#define CPU_FEATURES_ARCH_RISCV
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 32
|
||||||
|
#define CPU_FEATURES_ARCH_RISCV32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 64
|
||||||
|
#define CPU_FEATURES_ARCH_RISCV64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 128
|
||||||
|
#define CPU_FEATURES_ARCH_RISCV128
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__loongarch64)
|
||||||
|
#define CPU_FEATURES_ARCH_LOONGARCH
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Os
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if (defined(__freebsd__) || defined(__FreeBSD__))
|
||||||
|
#define CPU_FEATURES_OS_FREEBSD
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__ANDROID__)
|
||||||
|
#define CPU_FEATURES_OS_ANDROID
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__linux__) && !defined(CPU_FEATURES_OS_FREEBSD) && \
|
||||||
|
!defined(CPU_FEATURES_OS_ANDROID)
|
||||||
|
#define CPU_FEATURES_OS_LINUX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(_WIN64) || defined(_WIN32))
|
||||||
|
#define CPU_FEATURES_OS_WINDOWS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(__apple__) || defined(__APPLE__) || defined(__MACH__))
|
||||||
|
// From https://stackoverflow.com/a/49560690
|
||||||
|
#include "TargetConditionals.h"
|
||||||
|
#if defined(TARGET_OS_OSX)
|
||||||
|
#define CPU_FEATURES_OS_MACOS
|
||||||
|
#endif
|
||||||
|
#if defined(TARGET_OS_IPHONE)
|
||||||
|
// This is set for any non-Mac Apple products (IOS, TV, WATCH)
|
||||||
|
#define CPU_FEATURES_OS_IPHONE
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Compilers
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#define CPU_FEATURES_COMPILER_CLANG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && !defined(__clang__)
|
||||||
|
#define CPU_FEATURES_COMPILER_GCC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define CPU_FEATURES_COMPILER_MSC
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Cpp
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
#define CPU_FEATURES_START_CPP_NAMESPACE \
|
||||||
|
namespace cpu_features { \
|
||||||
|
extern "C" {
|
||||||
|
#define CPU_FEATURES_END_CPP_NAMESPACE \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_START_CPP_NAMESPACE
|
||||||
|
#define CPU_FEATURES_END_CPP_NAMESPACE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Compiler flags
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Use the following to check if a feature is known to be available at
|
||||||
|
// compile time. See README.md for an example.
|
||||||
|
#if defined(CPU_FEATURES_ARCH_X86)
|
||||||
|
|
||||||
|
#if defined(__AES__)
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_AES 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_AES 0
|
||||||
|
#endif // defined(__AES__)
|
||||||
|
|
||||||
|
#if defined(__F16C__)
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_F16C 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_F16C 0
|
||||||
|
#endif // defined(__F16C__)
|
||||||
|
|
||||||
|
#if defined(__BMI__)
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_BMI 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_BMI 0
|
||||||
|
#endif // defined(__BMI__)
|
||||||
|
|
||||||
|
#if defined(__BMI2__)
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_BMI2 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_BMI2 0
|
||||||
|
#endif // defined(__BMI2__)
|
||||||
|
|
||||||
|
#if (defined(__SSE__) || (_M_IX86_FP >= 1))
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSE 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(__SSE2__) || (_M_IX86_FP >= 2))
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSE2 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSE2 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__SSE3__)
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSE3 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSE3 0
|
||||||
|
#endif // defined(__SSE3__)
|
||||||
|
|
||||||
|
#if defined(__SSSE3__)
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSSE3 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSSE3 0
|
||||||
|
#endif // defined(__SSSE3__)
|
||||||
|
|
||||||
|
#if defined(__SSE4_1__)
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSE4_1 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSE4_1 0
|
||||||
|
#endif // defined(__SSE4_1__)
|
||||||
|
|
||||||
|
#if defined(__SSE4_2__)
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSE4_2 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_SSE4_2 0
|
||||||
|
#endif // defined(__SSE4_2__)
|
||||||
|
|
||||||
|
#if defined(__AVX__)
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_AVX 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_AVX 0
|
||||||
|
#endif // defined(__AVX__)
|
||||||
|
|
||||||
|
#if defined(__AVX2__)
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_AVX2 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_X86_AVX2 0
|
||||||
|
#endif // defined(__AVX2__)
|
||||||
|
|
||||||
|
#endif // defined(CPU_FEATURES_ARCH_X86)
|
||||||
|
|
||||||
|
#if defined(CPU_FEATURES_ARCH_ANY_ARM)
|
||||||
|
#if defined(__ARM_NEON__)
|
||||||
|
#define CPU_FEATURES_COMPILED_ANY_ARM_NEON 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_ANY_ARM_NEON 0
|
||||||
|
#endif // defined(__ARM_NEON__)
|
||||||
|
#endif // defined(CPU_FEATURES_ARCH_ANY_ARM)
|
||||||
|
|
||||||
|
#if defined(CPU_FEATURES_ARCH_MIPS)
|
||||||
|
#if defined(__mips_msa)
|
||||||
|
#define CPU_FEATURES_COMPILED_MIPS_MSA 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_MIPS_MSA 0
|
||||||
|
#endif // defined(__mips_msa)
|
||||||
|
#if defined(__mips3d)
|
||||||
|
#define CPU_FEATURES_COMPILED_MIPS_MIPS3D 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_MIPS_MIPS3D 0
|
||||||
|
#endif
|
||||||
|
#endif // defined(CPU_FEATURES_ARCH_MIPS)
|
||||||
|
|
||||||
|
#if defined(CPU_FEATURES_ARCH_RISCV)
|
||||||
|
#if defined(__riscv_e)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_E 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_E 0
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_i)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_I 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_I 0
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_m)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_M 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_M 0
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_a)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_A 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_A 0
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_f)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_F 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_F 0
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_d)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_D 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_D 0
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_q)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_Q 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_Q 0
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_c)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_C 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_C 0
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_v)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_V 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_V 0
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_zba)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZBA 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZBA 0
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_zbb)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZBB 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZBB 0
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_zbc)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZBC 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZBC 0
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_zbs)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZBS 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZBS 0
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_zfh)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZFH 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZFH 0
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_zfhmin)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZFHMIN 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZFHMIN 0
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_zknd)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZKND 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZKND 0
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_zkne)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZKNE 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZKNE 0
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_zknh)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZKNH 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZKNH 0
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_zksed)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZKSED 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZKSED 0
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_zksh)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZKSH 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZKSH 0
|
||||||
|
#endif
|
||||||
|
#if defined(__riscv_zkr)
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZKR 1
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_COMPILED_RISCV_ZKR 0
|
||||||
|
#endif
|
||||||
|
#endif // defined(CPU_FEATURES_ARCH_RISCV)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Utils
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Communicates to the compiler that the block is unreachable
|
||||||
|
#if defined(CPU_FEATURES_COMPILER_CLANG) || defined(CPU_FEATURES_COMPILER_GCC)
|
||||||
|
#define CPU_FEATURES_UNREACHABLE() __builtin_unreachable()
|
||||||
|
#elif defined(CPU_FEATURES_COMPILER_MSC)
|
||||||
|
#define CPU_FEATURES_UNREACHABLE() __assume(0)
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_UNREACHABLE()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Communicates to the compiler that the function is now deprecated
|
||||||
|
#if defined(CPU_FEATURES_COMPILER_CLANG) || defined(CPU_FEATURES_COMPILER_GCC)
|
||||||
|
#define CPU_FEATURES_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||||
|
#elif defined(CPU_FEATURES_COMPILER_MSC)
|
||||||
|
#define CPU_FEATURES_DEPRECATED(message) __declspec(deprecated(message))
|
||||||
|
#else
|
||||||
|
#define CPU_FEATURES_DEPRECATED(message)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // CPU_FEATURES_INCLUDE_CPU_FEATURES_MACROS_H_
|
||||||
+301
@@ -0,0 +1,301 @@
|
|||||||
|
// Copyright 2017 Google LLC
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// A note on Windows AArch64 implementation
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// Getting cpu info via EL1 system registers is not possible, so we delegate it
|
||||||
|
// to the Windows API (i.e., IsProcessorFeaturePresent and GetNativeSystemInfo).
|
||||||
|
// The `implementer`, `variant` and `part` fields of the `Aarch64Info` struct
|
||||||
|
// are not used, so they are set to 0. To get `revision` we use
|
||||||
|
// `wProcessorRevision` from `SYSTEM_INFO`.
|
||||||
|
//
|
||||||
|
// Cryptographic Extension:
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// According to documentation Arm Architecture Reference Manual for
|
||||||
|
// A-profile architecture. A2.3 The Armv8 Cryptographic Extension. The Armv8.0
|
||||||
|
// Cryptographic Extension provides instructions for the acceleration of
|
||||||
|
// encryption and decryption, and includes the following features: FEAT_AES,
|
||||||
|
// FEAT_PMULL, FEAT_SHA1, FEAT_SHA256.
|
||||||
|
// see: https://developer.arm.com/documentation/ddi0487/latest
|
||||||
|
//
|
||||||
|
// We use `PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE` to detect all Armv8.0 crypto
|
||||||
|
// features. This value reports all features or nothing, so even if you only
|
||||||
|
// have support FEAT_AES and FEAT_PMULL, it will still return false.
|
||||||
|
//
|
||||||
|
// From Armv8.2, an implementation of the Armv8.0 Cryptographic Extension can
|
||||||
|
// include either or both of:
|
||||||
|
//
|
||||||
|
// • The AES functionality, including support for multiplication of 64-bit
|
||||||
|
// polynomials. The ID_AA64ISAR0_EL1.AES field indicates whether this
|
||||||
|
// functionality is supported.
|
||||||
|
// • The SHA1 and SHA2-256 functionality. The ID_AA64ISAR0_EL1.{SHA2, SHA1}
|
||||||
|
// fields indicate whether this functionality is supported.
|
||||||
|
//
|
||||||
|
// ID_AA64ISAR0_EL1.AES, bits [7:4]:
|
||||||
|
// Indicates support for AES instructions in AArch64 state. Defined values are:
|
||||||
|
// - 0b0000 No AES instructions implemented.
|
||||||
|
// - 0b0001 AESE, AESD, AESMC, and AESIMC instructions implemented.
|
||||||
|
// - 0b0010 As for 0b0001, plus PMULL/PMULL2 instructions operating on 64-bit
|
||||||
|
// data quantities.
|
||||||
|
//
|
||||||
|
// FEAT_AES implements the functionality identified by the value 0b0001.
|
||||||
|
// FEAT_PMULL implements the functionality identified by the value 0b0010.
|
||||||
|
// From Armv8, the permitted values are 0b0000 and 0b0010.
|
||||||
|
//
|
||||||
|
// ID_AA64ISAR0_EL1.SHA1, bits [11:8]:
|
||||||
|
// Indicates support for SHA1 instructions in AArch64 state. Defined values are:
|
||||||
|
// - 0b0000 No SHA1 instructions implemented.
|
||||||
|
// - 0b0001 SHA1C, SHA1P, SHA1M, SHA1H, SHA1SU0, and SHA1SU1 instructions
|
||||||
|
// implemented.
|
||||||
|
//
|
||||||
|
// FEAT_SHA1 implements the functionality identified by the value 0b0001.
|
||||||
|
// From Armv8, the permitted values are 0b0000 and 0b0001.
|
||||||
|
// If the value of ID_AA64ISAR0_EL1.SHA2 is 0b0000, this field must have the
|
||||||
|
// value 0b0000.
|
||||||
|
//
|
||||||
|
// ID_AA64ISAR0_EL1.SHA2, bits [15:12]:
|
||||||
|
// Indicates support for SHA2 instructions in AArch64 state. Defined values are:
|
||||||
|
// - 0b0000 No SHA2 instructions implemented.
|
||||||
|
// - 0b0001 Implements instructions: SHA256H, SHA256H2, SHA256SU0, and
|
||||||
|
// SHA256SU1.
|
||||||
|
// - 0b0010 Implements instructions:
|
||||||
|
// • SHA256H, SHA256H2, SHA256SU0, and SHA256SU1.
|
||||||
|
// • SHA512H, SHA512H2, SHA512SU0, and SHA512SU1.
|
||||||
|
//
|
||||||
|
// FEAT_SHA256 implements the functionality identified by the value 0b0001.
|
||||||
|
// FEAT_SHA512 implements the functionality identified by the value 0b0010.
|
||||||
|
//
|
||||||
|
// In Armv8, the permitted values are 0b0000 and 0b0001.
|
||||||
|
// From Armv8.2, the permitted values are 0b0000, 0b0001, and 0b0010.
|
||||||
|
//
|
||||||
|
// If the value of ID_AA64ISAR0_EL1.SHA1 is 0b0000, this field must have the
|
||||||
|
// value 0b0000.
|
||||||
|
//
|
||||||
|
// If the value of this field is 0b0010, ID_AA64ISAR0_EL1.SHA3
|
||||||
|
// must have the value 0b0001.
|
||||||
|
//
|
||||||
|
// Other cryptographic features that we cannot detect such as sha512, sha3, sm3,
|
||||||
|
// sm4, sveaes, svepmull, svesha3, svesm4 we set to 0.
|
||||||
|
//
|
||||||
|
// FP/SIMD:
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// FP/SIMD must be implemented on all Armv8.0 implementations, but
|
||||||
|
// implementations targeting specialized markets may support the following
|
||||||
|
// combinations:
|
||||||
|
//
|
||||||
|
// • No NEON or floating-point.
|
||||||
|
// • Full floating-point and SIMD support with exception trapping.
|
||||||
|
// • Full floating-point and SIMD support without exception trapping.
|
||||||
|
//
|
||||||
|
// ref:
|
||||||
|
// https://developer.arm.com/documentation/den0024/a/AArch64-Floating-point-and-NEON
|
||||||
|
//
|
||||||
|
// So, we use `PF_ARM_VFP_32_REGISTERS_AVAILABLE`,
|
||||||
|
// `PF_ARM_NEON_INSTRUCTIONS_AVAILABLE` to detect `asimd` and `fp`
|
||||||
|
|
||||||
|
#ifndef CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_
|
||||||
|
#define CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_
|
||||||
|
|
||||||
|
#include "cpu_features_cache_info.h"
|
||||||
|
#include "cpu_features_macros.h"
|
||||||
|
|
||||||
|
CPU_FEATURES_START_CPP_NAMESPACE
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int fp : 1; // Floating-point.
|
||||||
|
int asimd : 1; // Advanced SIMD.
|
||||||
|
int evtstrm : 1; // Generic timer generated events.
|
||||||
|
int aes : 1; // Hardware-accelerated Advanced Encryption Standard.
|
||||||
|
int pmull : 1; // Polynomial multiply long.
|
||||||
|
int sha1 : 1; // Hardware-accelerated SHA1.
|
||||||
|
int sha2 : 1; // Hardware-accelerated SHA2-256.
|
||||||
|
int crc32 : 1; // Hardware-accelerated CRC-32.
|
||||||
|
int atomics : 1; // Armv8.1 atomic instructions.
|
||||||
|
int fphp : 1; // Half-precision floating point support.
|
||||||
|
int asimdhp : 1; // Advanced SIMD half-precision support.
|
||||||
|
int cpuid : 1; // Access to certain ID registers.
|
||||||
|
int asimdrdm : 1; // Rounding Double Multiply Accumulate/Subtract.
|
||||||
|
int jscvt : 1; // Support for JavaScript conversion.
|
||||||
|
int fcma : 1; // Floating point complex numbers.
|
||||||
|
int lrcpc : 1; // Support for weaker release consistency.
|
||||||
|
int dcpop : 1; // Data persistence writeback.
|
||||||
|
int sha3 : 1; // Hardware-accelerated SHA3.
|
||||||
|
int sm3 : 1; // Hardware-accelerated SM3.
|
||||||
|
int sm4 : 1; // Hardware-accelerated SM4.
|
||||||
|
int asimddp : 1; // Dot product instruction.
|
||||||
|
int sha512 : 1; // Hardware-accelerated SHA512.
|
||||||
|
int sve : 1; // Scalable Vector Extension.
|
||||||
|
int asimdfhm : 1; // Additional half-precision instructions.
|
||||||
|
int dit : 1; // Data independent timing.
|
||||||
|
int uscat : 1; // Unaligned atomics support.
|
||||||
|
int ilrcpc : 1; // Additional support for weaker release consistency.
|
||||||
|
int flagm : 1; // Flag manipulation instructions.
|
||||||
|
int ssbs : 1; // Speculative Store Bypass Safe PSTATE bit.
|
||||||
|
int sb : 1; // Speculation barrier.
|
||||||
|
int paca : 1; // Address authentication.
|
||||||
|
int pacg : 1; // Generic authentication.
|
||||||
|
int dcpodp : 1; // Data cache clean to point of persistence.
|
||||||
|
int sve2 : 1; // Scalable Vector Extension (version 2).
|
||||||
|
int sveaes : 1; // SVE AES instructions.
|
||||||
|
int svepmull : 1; // SVE polynomial multiply long instructions.
|
||||||
|
int svebitperm : 1; // SVE bit permute instructions.
|
||||||
|
int svesha3 : 1; // SVE SHA3 instructions.
|
||||||
|
int svesm4 : 1; // SVE SM4 instructions.
|
||||||
|
int flagm2 : 1; // Additional flag manipulation instructions.
|
||||||
|
int frint : 1; // Floating point to integer rounding.
|
||||||
|
int svei8mm : 1; // SVE Int8 matrix multiplication instructions.
|
||||||
|
int svef32mm : 1; // SVE FP32 matrix multiplication instruction.
|
||||||
|
int svef64mm : 1; // SVE FP64 matrix multiplication instructions.
|
||||||
|
int svebf16 : 1; // SVE BFloat16 instructions.
|
||||||
|
int i8mm : 1; // Int8 matrix multiplication instructions.
|
||||||
|
int bf16 : 1; // BFloat16 instructions.
|
||||||
|
int dgh : 1; // Data Gathering Hint instruction.
|
||||||
|
int rng : 1; // True random number generator support.
|
||||||
|
int bti : 1; // Branch target identification.
|
||||||
|
int mte : 1; // Memory tagging extension.
|
||||||
|
int ecv : 1; // Enhanced counter virtualization.
|
||||||
|
int afp : 1; // Alternate floating-point behaviour.
|
||||||
|
int rpres : 1; // 12-bit reciprocal (square root) estimate precision.
|
||||||
|
int mte3 : 1; // MTE asymmetric fault handling.
|
||||||
|
int sme : 1; // Scalable Matrix Extension.
|
||||||
|
int smei16i64 : 1; // 16-bit to 64-bit integer widening outer product.
|
||||||
|
int smef64f64 : 1; // FP64 to FP64 outer product.
|
||||||
|
int smei8i32 : 1; // 8-bit to 32-bit integer widening outer product.
|
||||||
|
int smef16f32 : 1; // FP16 to FP32 outer product.
|
||||||
|
int smeb16f32 : 1; // BFloat16 to FP32 outper product.
|
||||||
|
int smef32f32 : 1; // FP32 to FP32 outer product.
|
||||||
|
int smefa64 : 1; // Full A64 support for SME in streaming mode.
|
||||||
|
int wfxt : 1; // WFE and WFI with timeout.
|
||||||
|
int ebf16 : 1; // Extended BFloat16 instructions.
|
||||||
|
int sveebf16 : 1; // SVE BFloat16 instructions.
|
||||||
|
int cssc : 1; // Common short sequence compression instructions.
|
||||||
|
int rprfm : 1; // Range Prefetch Memory hint instruction.
|
||||||
|
int sve2p1 : 1; // Scalable Vector Extension (version 2.1).
|
||||||
|
int sme2 : 1; // Scalable Matrix Extension (version 2).
|
||||||
|
int sme2p1 : 1; // Scalable Matrix Extension (version 2.1).
|
||||||
|
int smei16i32 : 1; // 16-bit to 64-bit integer widening outer product.
|
||||||
|
int smebi32i32 : 1; // 1-bit binary to 32-bit integer outer product.
|
||||||
|
int smeb16b16 : 1; // SME2.1 BFloat16 instructions.
|
||||||
|
int smef16f16 : 1; // FP16 to FP16 outer product.
|
||||||
|
|
||||||
|
// Make sure to update Aarch64FeaturesEnum below if you add a field here.
|
||||||
|
} Aarch64Features;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Aarch64Features features;
|
||||||
|
int implementer; // We set 0 for Windows.
|
||||||
|
int variant; // We set 0 for Windows.
|
||||||
|
int part; // We set 0 for Windows.
|
||||||
|
int revision; // We use GetNativeSystemInfo to get processor revision for
|
||||||
|
// Windows.
|
||||||
|
} Aarch64Info;
|
||||||
|
|
||||||
|
Aarch64Info GetAarch64Info(void);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Introspection functions
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
AARCH64_FP,
|
||||||
|
AARCH64_ASIMD,
|
||||||
|
AARCH64_EVTSTRM,
|
||||||
|
AARCH64_AES,
|
||||||
|
AARCH64_PMULL,
|
||||||
|
AARCH64_SHA1,
|
||||||
|
AARCH64_SHA2,
|
||||||
|
AARCH64_CRC32,
|
||||||
|
AARCH64_ATOMICS,
|
||||||
|
AARCH64_FPHP,
|
||||||
|
AARCH64_ASIMDHP,
|
||||||
|
AARCH64_CPUID,
|
||||||
|
AARCH64_ASIMDRDM,
|
||||||
|
AARCH64_JSCVT,
|
||||||
|
AARCH64_FCMA,
|
||||||
|
AARCH64_LRCPC,
|
||||||
|
AARCH64_DCPOP,
|
||||||
|
AARCH64_SHA3,
|
||||||
|
AARCH64_SM3,
|
||||||
|
AARCH64_SM4,
|
||||||
|
AARCH64_ASIMDDP,
|
||||||
|
AARCH64_SHA512,
|
||||||
|
AARCH64_SVE,
|
||||||
|
AARCH64_ASIMDFHM,
|
||||||
|
AARCH64_DIT,
|
||||||
|
AARCH64_USCAT,
|
||||||
|
AARCH64_ILRCPC,
|
||||||
|
AARCH64_FLAGM,
|
||||||
|
AARCH64_SSBS,
|
||||||
|
AARCH64_SB,
|
||||||
|
AARCH64_PACA,
|
||||||
|
AARCH64_PACG,
|
||||||
|
AARCH64_DCPODP,
|
||||||
|
AARCH64_SVE2,
|
||||||
|
AARCH64_SVEAES,
|
||||||
|
AARCH64_SVEPMULL,
|
||||||
|
AARCH64_SVEBITPERM,
|
||||||
|
AARCH64_SVESHA3,
|
||||||
|
AARCH64_SVESM4,
|
||||||
|
AARCH64_FLAGM2,
|
||||||
|
AARCH64_FRINT,
|
||||||
|
AARCH64_SVEI8MM,
|
||||||
|
AARCH64_SVEF32MM,
|
||||||
|
AARCH64_SVEF64MM,
|
||||||
|
AARCH64_SVEBF16,
|
||||||
|
AARCH64_I8MM,
|
||||||
|
AARCH64_BF16,
|
||||||
|
AARCH64_DGH,
|
||||||
|
AARCH64_RNG,
|
||||||
|
AARCH64_BTI,
|
||||||
|
AARCH64_MTE,
|
||||||
|
AARCH64_ECV,
|
||||||
|
AARCH64_AFP,
|
||||||
|
AARCH64_RPRES,
|
||||||
|
AARCH64_MTE3,
|
||||||
|
AARCH64_SME,
|
||||||
|
AARCH64_SME_I16I64,
|
||||||
|
AARCH64_SME_F64F64,
|
||||||
|
AARCH64_SME_I8I32,
|
||||||
|
AARCH64_SME_F16F32,
|
||||||
|
AARCH64_SME_B16F32,
|
||||||
|
AARCH64_SME_F32F32,
|
||||||
|
AARCH64_SME_FA64,
|
||||||
|
AARCH64_WFXT,
|
||||||
|
AARCH64_EBF16,
|
||||||
|
AARCH64_SVE_EBF16,
|
||||||
|
AARCH64_CSSC,
|
||||||
|
AARCH64_RPRFM,
|
||||||
|
AARCH64_SVE2P1,
|
||||||
|
AARCH64_SME2,
|
||||||
|
AARCH64_SME2P1,
|
||||||
|
AARCH64_SME_I16I32,
|
||||||
|
AARCH64_SME_BI32I32,
|
||||||
|
AARCH64_SME_B16B16,
|
||||||
|
AARCH64_SME_F16F16,
|
||||||
|
AARCH64_LAST_,
|
||||||
|
} Aarch64FeaturesEnum;
|
||||||
|
|
||||||
|
int GetAarch64FeaturesEnumValue(const Aarch64Features* features,
|
||||||
|
Aarch64FeaturesEnum value);
|
||||||
|
|
||||||
|
const char* GetAarch64FeaturesEnumName(Aarch64FeaturesEnum);
|
||||||
|
|
||||||
|
CPU_FEATURES_END_CPP_NAMESPACE
|
||||||
|
|
||||||
|
#if !defined(CPU_FEATURES_ARCH_AARCH64)
|
||||||
|
#error "Including cpuinfo_aarch64.h from a non-aarch64 target."
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // CPU_FEATURES_INCLUDE_CPUINFO_AARCH64_H_
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user