UI: Massive revamp, new features and improvements
|
@ -89,12 +89,12 @@ if(WIN32 AND USE_SDL2)
|
||||||
set(SDL2_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/sdl2/lib64/SDL2.lib")
|
set(SDL2_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/sdl2/lib64/SDL2.lib")
|
||||||
set(SDL2MAIN_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/sdl2/lib64/SDL2main.lib")
|
set(SDL2MAIN_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/sdl2/lib64/SDL2main.lib")
|
||||||
set(SDL2_DLL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/sdl2/bin64/SDL2.dll")
|
set(SDL2_DLL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/sdl2/bin64/SDL2.dll")
|
||||||
set(Qt5_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/qt/5.15.0/msvc2017_64/lib/cmake/Qt5")
|
set(Qt6_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/qt/6.1.0/msvc2019_64/lib/cmake/Qt6")
|
||||||
else()
|
else()
|
||||||
set(SDL2_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/sdl2/lib32/SDL2.lib")
|
set(SDL2_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/sdl2/lib32/SDL2.lib")
|
||||||
set(SDL2MAIN_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/sdl2/lib32/SDL2main.lib")
|
set(SDL2MAIN_LIBRARIES "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/sdl2/lib32/SDL2main.lib")
|
||||||
set(SDL2_DLL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/sdl2/bin32/SDL2.dll")
|
set(SDL2_DLL_PATH "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/sdl2/bin32/SDL2.dll")
|
||||||
set(Qt5_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/qt/5.15.0/msvc2017_32/lib/cmake/Qt5")
|
set(Qt6_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dep/msvc/qt/6.1.0/msvc2019_32/lib/cmake/Qt6")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ if(NOT ANDROID)
|
||||||
find_package(SDL2 REQUIRED)
|
find_package(SDL2 REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
if(BUILD_QT_FRONTEND)
|
if(BUILD_QT_FRONTEND)
|
||||||
find_package(Qt5 COMPONENTS Core Gui Widgets Network LinguistTools REQUIRED)
|
find_package(Qt6 COMPONENTS Core Gui Widgets Network LinguistTools REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -36683,7 +36683,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -94490,7 +94490,7 @@
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"PlayStationMouse",
|
"PlayStationMouse",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"KonamiJustifier"
|
"KonamiJustifier"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
|
@ -94528,7 +94528,7 @@
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"PlayStationMouse",
|
"PlayStationMouse",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"KonamiJustifier"
|
"KonamiJustifier"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
|
@ -94566,7 +94566,7 @@
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"PlayStationMouse",
|
"PlayStationMouse",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"KonamiJustifier"
|
"KonamiJustifier"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
|
@ -94604,7 +94604,7 @@
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"PlayStationMouse",
|
"PlayStationMouse",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"KonamiJustifier"
|
"KonamiJustifier"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
|
@ -94642,7 +94642,7 @@
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"PlayStationMouse",
|
"PlayStationMouse",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"KonamiJustifier"
|
"KonamiJustifier"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
|
@ -118156,7 +118156,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"KonamiJustifier",
|
"KonamiJustifier",
|
||||||
"PlayStationMouse"
|
"PlayStationMouse"
|
||||||
],
|
],
|
||||||
|
@ -131024,7 +131024,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -159741,7 +159741,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"KonamiJustifier",
|
"KonamiJustifier",
|
||||||
"PlayStationMouse"
|
"PlayStationMouse"
|
||||||
],
|
],
|
||||||
|
@ -161094,7 +161094,7 @@
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"PlayStationMouse",
|
"PlayStationMouse",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -168086,7 +168086,7 @@
|
||||||
"linkCable": false,
|
"linkCable": false,
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -168130,7 +168130,7 @@
|
||||||
"linkCable": false,
|
"linkCable": false,
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -168166,7 +168166,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -168202,7 +168202,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -168264,7 +168264,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -168300,7 +168300,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -169280,7 +169280,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -169316,7 +169316,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -169792,7 +169792,7 @@
|
||||||
"linkCable": false,
|
"linkCable": false,
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -200165,7 +200165,7 @@
|
||||||
"linkCable": false,
|
"linkCable": false,
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"KonamiJustifier"
|
"KonamiJustifier"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
|
@ -200201,7 +200201,7 @@
|
||||||
"linkCable": false,
|
"linkCable": false,
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"KonamiJustifier"
|
"KonamiJustifier"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
|
@ -201057,7 +201057,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -243440,7 +243440,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"KonamiJustifier"
|
"KonamiJustifier"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
|
@ -243477,7 +243477,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"KonamiJustifier"
|
"KonamiJustifier"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
|
@ -250279,7 +250279,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"KonamiJustifier"
|
"KonamiJustifier"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
|
@ -250316,7 +250316,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"KonamiJustifier"
|
"KonamiJustifier"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
|
@ -257141,7 +257141,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -257262,7 +257262,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -290498,7 +290498,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -313576,7 +313576,7 @@
|
||||||
"linkCable": false,
|
"linkCable": false,
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -313620,7 +313620,7 @@
|
||||||
"linkCable": false,
|
"linkCable": false,
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -313660,7 +313660,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -313696,7 +313696,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -313736,7 +313736,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -313772,7 +313772,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -313808,7 +313808,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -323119,7 +323119,7 @@
|
||||||
"linkCable": false,
|
"linkCable": false,
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -336352,7 +336352,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"PlayStationMouse"
|
"PlayStationMouse"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
|
@ -336389,7 +336389,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"PlayStationMouse"
|
"PlayStationMouse"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -336437,7 +336437,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"PlayStationMouse"
|
"PlayStationMouse"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
|
@ -336837,7 +336837,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -336874,7 +336874,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -336910,7 +336910,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -338230,7 +338230,7 @@
|
||||||
"linkCable": false,
|
"linkCable": false,
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -338333,7 +338333,7 @@
|
||||||
"linkCable": false,
|
"linkCable": false,
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -338436,7 +338436,7 @@
|
||||||
"linkCable": false,
|
"linkCable": false,
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -338539,7 +338539,7 @@
|
||||||
"linkCable": false,
|
"linkCable": false,
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -370386,7 +370386,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -372433,7 +372433,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -430122,7 +430122,7 @@
|
||||||
"linkCable": false,
|
"linkCable": false,
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"PlayStationMouse"
|
"PlayStationMouse"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
|
@ -430287,7 +430287,7 @@
|
||||||
"linkCable": false,
|
"linkCable": false,
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"PlayStationMouse"
|
"PlayStationMouse"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
|
@ -430451,7 +430451,7 @@
|
||||||
"linkCable": false,
|
"linkCable": false,
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"PlayStationMouse"
|
"PlayStationMouse"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
|
@ -430615,7 +430615,7 @@
|
||||||
"linkCable": false,
|
"linkCable": false,
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"PlayStationMouse"
|
"PlayStationMouse"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
|
@ -430780,7 +430780,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -430810,7 +430810,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -431114,7 +431114,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -431234,7 +431234,7 @@
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon"
|
"GunCon"
|
||||||
],
|
],
|
||||||
"track_data": [
|
"track_data": [
|
||||||
{
|
{
|
||||||
|
@ -431353,7 +431353,7 @@
|
||||||
"linkCable": false,
|
"linkCable": false,
|
||||||
"controllers": [
|
"controllers": [
|
||||||
"DigitalController",
|
"DigitalController",
|
||||||
"NamcoGuncon",
|
"GunCon",
|
||||||
"PlayStationMouse"
|
"PlayStationMouse"
|
||||||
]
|
]
|
||||||
},
|
},
|
202
data/resources/fonts/LICENSE.txt
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
|
||||||
|
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.
|
BIN
data/resources/fonts/RobotoMono-Medium.ttf
Normal file
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 117 KiB |
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
Before Width: | Height: | Size: 202 KiB After Width: | Height: | Size: 202 KiB |
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 72 KiB |
BIN
data/resources/fullscreenui/placeholder.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 6 KiB After Width: | Height: | Size: 6 KiB |
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
BIN
data/resources/images/cover-placeholder.png
Normal file
After Width: | Height: | Size: 209 KiB |
|
@ -1 +1 @@
|
||||||
Subproject commit fb9018121818293b72e9f5064b2cb202e713c501
|
Subproject commit f44f99baad9c52e6e98831f95dde283b3c3d7993
|
|
@ -2,36 +2,38 @@
|
||||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
<PropertyGroup Label="UserMacros">
|
<PropertyGroup Label="UserMacros">
|
||||||
<BinaryOutputDir>$(SolutionDir)bin\$(Platform)\</BinaryOutputDir>
|
<BinaryOutputDir>$(SolutionDir)bin\$(Platform)\</BinaryOutputDir>
|
||||||
<QTDIRDefault Condition="'$(Platform)'=='x64'">$(SolutionDir)dep\msvc\qt\6.1.0\msvc2019_64\</QTDIRDefault>
|
<DSQTDIRDefault Condition="'$(Platform)'=='x64'">$(SolutionDir)dep\msvc\qt\6.1.0\msvc2019_64\</DSQTDIRDefault>
|
||||||
<QTDIRDefault Condition="'$(Platform)'=='ARM64'">$(SolutionDir)dep\msvc\qt\6.1.0\msvc2019_arm64\</QTDIRDefault>
|
<DSQTDIRDefault Condition="'$(Platform)'=='ARM64'">$(SolutionDir)dep\msvc\qt\6.3.1\msvc2022_arm64\</DSQTDIRDefault>
|
||||||
<QTDIR Condition="Exists('$(QTDIRDefault)') And ('$(QTDIR)'=='' Or !Exists('$(QTDIR)'))">$(QTDIRDefault)</QTDIR>
|
<DSQTDIR Condition="Exists('$(DSQTDIRDefault)') And ('$(DSQTDIR)'=='' Or !Exists('$(DSQTDIR)'))">$(DSQTDIRDefault)</DSQTDIR>
|
||||||
<QTDIR Condition="Exists('$(QTDIR)') And !HasTrailingSlash('$(QTDIR)')">$(QTDIR)\</QTDIR>
|
<DSQTDIR Condition="Exists('$(DSQTDIR)') And !HasTrailingSlash('$(DSQTDIR)')">$(DSQTDIR)\</DSQTDIR>
|
||||||
<QTDIRHost>$(SolutionDir)dep\msvc\qt\6.1.0\msvc2019_64\</QTDIRHost>
|
<DSQTDIRHost Condition="'$(Platform)'!='ARM64'">$(SolutionDir)dep\msvc\qt\6.1.0\msvc2019_64\</DSQTDIRHost>
|
||||||
<QtDirValid>false</QtDirValid>
|
<DSQTDIRHost Condition="'$(Platform)'=='ARM64'">$(SolutionDir)dep\msvc\qt\6.3.1\msvc2022_64\</DSQTDIRHost>
|
||||||
<QtDirValid Condition="Exists('$(QTDIR)')">true</QtDirValid>
|
<DSQTDIRValid>false</DSQTDIRValid>
|
||||||
<QtIncludeDir>$(QTDIR)include\</QtIncludeDir>
|
<DSQTDIRValid Condition="Exists('$(DSQTDIR)')">true</DSQTDIRValid>
|
||||||
<QtLibDir>$(QTDIR)lib\</QtLibDir>
|
<QtIncludeDir>$(DSQTDIR)include\</QtIncludeDir>
|
||||||
<QtBinDir>$(QTDIR)bin\</QtBinDir>
|
<QtLibDir>$(DSQTDIR)lib\</QtLibDir>
|
||||||
<QtHostBinDir>$(QTDIRHost)bin\</QtHostBinDir>
|
<QtBinDir>$(DSQTDIR)bin\</QtBinDir>
|
||||||
<QtPluginsDir>$(QTDIR)plugins\</QtPluginsDir>
|
<QtHostBinDir>$(DSQTDIRHost)bin\</QtHostBinDir>
|
||||||
<QtTranslationsDir>$(QTDIR)translations\</QtTranslationsDir>
|
<QtPluginsDir>$(DSQTDIR)plugins\</QtPluginsDir>
|
||||||
<QtToolOutDir>$(SolutionDir)build\$(ProjectName)-$(Platform)-$(Configuration)\</QtToolOutDir>
|
<QtTranslationsDir>$(DSQTDIR)translations\</QtTranslationsDir>
|
||||||
|
<QtToolOutDir>$(IntDir)</QtToolOutDir>
|
||||||
<QtMocOutPrefix>$(QtToolOutDir)moc_</QtMocOutPrefix>
|
<QtMocOutPrefix>$(QtToolOutDir)moc_</QtMocOutPrefix>
|
||||||
<QtTsOutDir>$(BinaryOutputDir)translations\</QtTsOutDir>
|
<QtTsOutDir>$(BinaryOutputDir)translations\</QtTsOutDir>
|
||||||
<QtDebugSuffix>d</QtDebugSuffix>
|
<QtDebugSuffix>d</QtDebugSuffix>
|
||||||
<QtLibSuffix Condition="'$(Configuration)'=='Debug' Or '$(Configuration)'=='DebugFast'">$(QtDebugSuffix)</QtLibSuffix>
|
<QtLibSuffix Condition="$(Configuration.Contains(Debug))">$(QtDebugSuffix)</QtLibSuffix>
|
||||||
<QtPluginFolder>QtPlugins</QtPluginFolder>
|
<QtPluginFolder>QtPlugins</QtPluginFolder>
|
||||||
|
<QtEntryPointLib>$(QtLibDir)Qt6EntryPoint$(QtLibSuffix).lib</QtEntryPointLib>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup>
|
<ItemDefinitionGroup>
|
||||||
<ClCompile>
|
<ClCompile>
|
||||||
<PreprocessorDefinitions Condition="'$(Configuration)'=='Release' Or '$(Configuration)'=='ReleaseLTCG'">QT_NO_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions Condition="!$(Configuration.Contains(Debug))">QT_NO_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<AdditionalIncludeDirectories>$(QtToolOutDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(QtToolOutDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<AdditionalIncludeDirectories>$(QtIncludeDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(QtIncludeDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<AdditionalLibraryDirectories>$(QtLibDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
<AdditionalLibraryDirectories>$(QtLibDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||||
<AdditionalDependencies>Qt6Core$(QtLibSuffix).lib;Qt6Gui$(QtLibSuffix).lib;Qt6Widgets$(QtLibSuffix).lib;Qt6Network$(QtLibSuffix).lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>Qt6Core$(QtLibSuffix).lib;Qt6Gui$(QtLibSuffix).lib;Qt6Widgets$(QtLibSuffix).lib;Qt6Network$(QtLibSuffix).lib;Qt6Concurrent$(QtLibSuffix).lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
|
|
||||||
|
@ -45,7 +47,7 @@
|
||||||
Condition="'@(QtResource)'!=''"
|
Condition="'@(QtResource)'!=''"
|
||||||
Outputs="@(ResFiles->'$(QtToolOutDir)qrc_%(Filename).cpp')">
|
Outputs="@(ResFiles->'$(QtToolOutDir)qrc_%(Filename).cpp')">
|
||||||
<Message Text="rcc %(ResFiles.Filename)" Importance="High" />
|
<Message Text="rcc %(ResFiles.Filename)" Importance="High" />
|
||||||
<Error Condition="!$(QtDirValid)" Text="QTDIR not set or non-existent (pull the submodule?)" />
|
<Error Condition="!$(DSQTDIRValid)" Text="Qt directory non-existent (pull the submodule?)" />
|
||||||
<MakeDir Directories="$(QtToolOutDir)" />
|
<MakeDir Directories="$(QtToolOutDir)" />
|
||||||
<Exec Command=""$(QtHostBinDir)rcc.exe" "%(ResFiles.FullPath)" -o "$(QtToolOutDir)qrc_%(ResFiles.Filename).cpp"" />
|
<Exec Command=""$(QtHostBinDir)rcc.exe" "%(ResFiles.FullPath)" -o "$(QtToolOutDir)qrc_%(ResFiles.Filename).cpp"" />
|
||||||
</Target>
|
</Target>
|
||||||
|
@ -64,7 +66,7 @@
|
||||||
Condition="'@(QtUi)'!=''"
|
Condition="'@(QtUi)'!=''"
|
||||||
Outputs="@(UiFiles->'$(QtToolOutDir)ui_%(Filename).h')">
|
Outputs="@(UiFiles->'$(QtToolOutDir)ui_%(Filename).h')">
|
||||||
<Message Text="uic %(UiFiles.Filename)" Importance="High" />
|
<Message Text="uic %(UiFiles.Filename)" Importance="High" />
|
||||||
<Error Condition="!$(QtDirValid)" Text="QTDIR not set or non-existent (pull the submodule?)" />
|
<Error Condition="!$(DSQTDIRValid)" Text="Qt directory non-existent (pull the submodule?)" />
|
||||||
<MakeDir Directories="$(QtToolOutDir)" />
|
<MakeDir Directories="$(QtToolOutDir)" />
|
||||||
<Exec Command=""$(QtHostBinDir)uic.exe" "%(UiFiles.FullPath)" -o "$(QtToolOutDir)ui_%(UiFiles.Filename).h"" />
|
<Exec Command=""$(QtHostBinDir)uic.exe" "%(UiFiles.FullPath)" -o "$(QtToolOutDir)ui_%(UiFiles.Filename).h"" />
|
||||||
</Target>
|
</Target>
|
||||||
|
@ -77,26 +79,18 @@
|
||||||
<!--TODO find a way to autocreate from ClCompile settings-->
|
<!--TODO find a way to autocreate from ClCompile settings-->
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<MocDefines></MocDefines>
|
<MocDefines></MocDefines>
|
||||||
<MocDefines Condition="'$(Configuration)'=='Release' Or '$(Configuration)'=='ReleaseLTCG'">-DQT_NO_DEBUG -DNDEBUG $(MocDefines)</MocDefines>
|
<MocDefines Condition="!$(Configuration.Contains(Debug))">-DQT_NO_DEBUG -DNDEBUG $(MocDefines)</MocDefines>
|
||||||
<!-- !!!HOLY UGLY BATMAN!!!
|
<MocIncludes>-I"$(QtIncludeDir)." -I"$(SolutionDir)pcsx2" "-I$(SolutionDir)." -I.</MocIncludes>
|
||||||
Be very careful here when adding include directories. Each path must have the whole arg surrounded by doublequotes - HOWEVER,
|
|
||||||
the ending doublequote cannot be directly preceeded by a directory seperator. In other words, you must use:
|
|
||||||
"-I$(SomeDir) "
|
|
||||||
instead of
|
|
||||||
"-I$(SomeDir)"
|
|
||||||
in order to prevent the trailing slash from escaping the doublequote after value replacement.
|
|
||||||
-->
|
|
||||||
<MocIncludes>"-I$(QtIncludeDir)" "-I$(SolutionDir)src" -I.</MocIncludes>
|
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Target Name="QtMoc"
|
<Target Name="QtMoc"
|
||||||
BeforeTargets="ClCompile"
|
BeforeTargets="ClCompile"
|
||||||
Condition="'@(QtMoc)'!=''"
|
Condition="'@(QtMoc)'!=''"
|
||||||
Inputs="%(QtMoc.Identity);%(QtMoc.AdditionalDependencies);$(MSBuildProjectFile)"
|
Inputs="%(QtMoc.Identity);%(QtMoc.AdditionalDependencies);$(MSBuildProjectFile)"
|
||||||
Outputs="$(QtToolOutDir)moc_%(QtMoc.Filename).cpp">
|
Outputs="$(QtToolOutDir)%(QtMoc.RelativeDir)moc_%(QtMoc.Filename).cpp">
|
||||||
<Message Text="moc %(QtMoc.Filename) $(QtToolOutDir)moc_%(QtMoc.Filename).cpp" Importance="High" />
|
<Message Text="moc %(QtMoc.Filename) $(QtToolOutDir)%(QtMoc.RelativeDir)moc_%(QtMoc.Filename).cpp" Importance="High" />
|
||||||
<Error Condition="!$(QtDirValid)" Text="QTDIR not set or non-existent (pull the submodule?)" />
|
<Error Condition="!$(DSQTDIRValid)" Text="Qt directory non-existent (pull the submodule?)" />
|
||||||
<MakeDir Directories="$(QtToolOutDir)" />
|
<MakeDir Directories="$(QtToolOutDir)" />
|
||||||
<Exec Command=""$(QtHostBinDir)moc.exe" "%(QtMoc.FullPath)" -o "$(QtToolOutDir)moc_%(QtMoc.Filename).cpp" -f%(QtMoc.Filename)%(QtMoc.Extension) $(MocDefines) $(MocIncludes)" />
|
<Exec Command=""$(QtHostBinDir)moc.exe" "%(QtMoc.FullPath)" -o "$(QtToolOutDir)%(QtMoc.RelativeDir)moc_%(QtMoc.Filename).cpp" -f%(QtMoc.Filename)%(QtMoc.Extension) $(MocDefines) $(MocIncludes)" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -125,21 +119,24 @@
|
||||||
|
|
||||||
<!--Copy the needed dlls-->
|
<!--Copy the needed dlls-->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<QtLibNames Include="Qt6Core$(QtLibSuffix);Qt6Gui$(QtLibSuffix);Qt6Widgets$(QtLibSuffix);Qt6Network$(QtLibSuffix);Qt6Svg$(QtLibSuffix)" />
|
<QtLibNames Include="Qt6Core$(QtLibSuffix);Qt6Gui$(QtLibSuffix);Qt6Widgets$(QtLibSuffix);Qt6Network$(QtLibSuffix);Qt6Svg$(QtLibSuffix);Qt6Concurrent$(QtLibSuffix)" />
|
||||||
<QtDlls Include="@(QtLibNames -> '$(QtBinDir)%(Identity).dll')" />
|
<QtDlls Include="@(QtLibNames -> '$(QtBinDir)%(Identity).dll')" />
|
||||||
<!--Filter plugins to copy based on the observation that all debug versions end in "d"-->
|
<!--Filter plugins to copy based on the observation that all debug versions end in "d"-->
|
||||||
<QtAllPlugins Include="$(QtPluginsDir)**\*$(QtLibSuffix).dll" />
|
<QtAllPlugins Include="$(QtPluginsDir)**\*$(QtLibSuffix).dll" />
|
||||||
<QtPlugins Condition="'$(Configuration)'=='Debug' Or '$(Configuration)'=='DebugFast'" Include="@(QtAllPlugins)" />
|
<QtPlugins Condition="$(Configuration.Contains(Debug))" Include="@(QtAllPlugins)" />
|
||||||
<QtPlugins Condition="'$(Configuration)'=='Release' Or '$(Configuration)'=='ReleaseLTCG'" Exclude="$(QtPluginsDir)**\*$(QtDebugSuffix).dll" Include="@(QtAllPlugins)" />
|
<QtPlugins Condition="!$(Configuration.Contains(Debug))" Exclude="$(QtPluginsDir)**\*$(QtDebugSuffix).dll" Include="@(QtAllPlugins)" />
|
||||||
<QtPluginsDest Include="@(QtPlugins -> '$(BinaryOutputDir)$(QtPluginFolder)\%(RecursiveDir)%(Filename)%(Extension)')" />
|
<QtPluginsDest Include="@(QtPlugins -> '$(BinaryOutputDir)$(QtPluginFolder)\%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||||
|
<!--Our normal *d filter fails for the TLS DLLs, because backend ends in d. -->
|
||||||
|
<!--<QtTLSDlls Include="$(QtPluginsDir)tls\qcertonlybackend$(QtLibSuffix).dll;$(QtPluginsDir)tls\qschannelbackend$(QtLibSuffix).dll" />-->
|
||||||
|
<QtTLSDllsDest Include="@(QtTLSDlls -> '$(BinaryOutputDir)$(QtPluginFolder)\tls\%(Filename)%(Extension)')" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<QtConfFile>$(BinaryOutputDir)qt.conf</QtConfFile>
|
<QtConfFile>$(BinaryOutputDir)qt.conf</QtConfFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Target Name="QtCopyBinaries"
|
<Target Name="QtCopyBinaries"
|
||||||
AfterTargets="Build"
|
AfterTargets="Build"
|
||||||
Inputs="@(QtDlls);@(QtPlugins)"
|
Inputs="@(QtDlls);@(QtPlugins);@(QtTLSDlls)"
|
||||||
Outputs="@(QtDlls -> '$(BinaryOutputDir)%(RecursiveDir)%(Filename)%(Extension)');@(QtPlugins -> '$(BinaryOutputDir)$(QtPluginFolder)\%(RecursiveDir)%(Filename)%(Extension)')">
|
Outputs="@(QtDlls -> '$(BinaryOutputDir)%(RecursiveDir)%(Filename)%(Extension)');@(QtPluginsDest);@(QtTLSDllsDest)">
|
||||||
<Message Text="Copying Qt .dlls" Importance="High" />
|
<Message Text="Copying Qt .dlls" Importance="High" />
|
||||||
<Copy
|
<Copy
|
||||||
SourceFiles="@(QtDlls)"
|
SourceFiles="@(QtDlls)"
|
||||||
|
@ -151,6 +148,11 @@
|
||||||
DestinationFiles="@(QtPluginsDest)"
|
DestinationFiles="@(QtPluginsDest)"
|
||||||
SkipUnchangedFiles="true"
|
SkipUnchangedFiles="true"
|
||||||
/>
|
/>
|
||||||
|
<Copy
|
||||||
|
SourceFiles="@(QtTLSDlls)"
|
||||||
|
DestinationFiles="@(QtTLSDllsDest)"
|
||||||
|
SkipUnchangedFiles="true"
|
||||||
|
/>
|
||||||
</Target>
|
</Target>
|
||||||
<Target Name="QtCreateConf"
|
<Target Name="QtCreateConf"
|
||||||
BeforeTargets="QtCopyBinaries"
|
BeforeTargets="QtCopyBinaries"
|
||||||
|
@ -192,7 +194,7 @@
|
||||||
Condition="'@(QtTs)'!=''"
|
Condition="'@(QtTs)'!=''"
|
||||||
Outputs="@(TsFiles->'$(QtTsOutDir)%(Filename).qm')">
|
Outputs="@(TsFiles->'$(QtTsOutDir)%(Filename).qm')">
|
||||||
<Message Text="lrelease %(TsFiles.Filename)" Importance="High" />
|
<Message Text="lrelease %(TsFiles.Filename)" Importance="High" />
|
||||||
<Error Condition="!$(QtDirValid)" Text="QTDIR not set or non-existent (pull the submodule?)" />
|
<Error Condition="!$(DSQTDIRValid)" Text="Qt directory non-existent (pull the submodule?)" />
|
||||||
<MakeDir Directories="$(QtTsOutDir)" />
|
<MakeDir Directories="$(QtTsOutDir)" />
|
||||||
<Exec Command=""$(QtHostBinDir)lrelease.exe" "%(TsFiles.FullPath)" -qm "$(QtTsOutDir)%(TsFiles.Filename).qm"" />
|
<Exec Command=""$(QtHostBinDir)lrelease.exe" "%(TsFiles.FullPath)" -qm "$(QtTsOutDir)%(TsFiles.Filename).qm"" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
|
@ -16,6 +16,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "src\common\common
|
||||||
{ED601289-AC1A-46B8-A8ED-17DB9EB73423} = {ED601289-AC1A-46B8-A8ED-17DB9EB73423}
|
{ED601289-AC1A-46B8-A8ED-17DB9EB73423} = {ED601289-AC1A-46B8-A8ED-17DB9EB73423}
|
||||||
{8BDA439C-6358-45FB-9994-2FF083BABE06} = {8BDA439C-6358-45FB-9994-2FF083BABE06}
|
{8BDA439C-6358-45FB-9994-2FF083BABE06} = {8BDA439C-6358-45FB-9994-2FF083BABE06}
|
||||||
{7FF9FDB9-D504-47DB-A16A-B08071999620} = {7FF9FDB9-D504-47DB-A16A-B08071999620}
|
{7FF9FDB9-D504-47DB-A16A-B08071999620} = {7FF9FDB9-D504-47DB-A16A-B08071999620}
|
||||||
|
{8BE398E6-B882-4248-9065-FECC8728E038} = {8BE398E6-B882-4248-9065-FECC8728E038}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core", "src\core\core.vcxproj", "{868B98C8-65A1-494B-8346-250A73A48C0A}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core", "src\core\core.vcxproj", "{868B98C8-65A1-494B-8346-250A73A48C0A}"
|
||||||
|
@ -811,30 +812,22 @@ Global
|
||||||
{39F0ADFF-3A84-470D-9CF0-CA49E164F2F3}.ReleaseUWP|x64.ActiveCfg = ReleaseUWP|x64
|
{39F0ADFF-3A84-470D-9CF0-CA49E164F2F3}.ReleaseUWP|x64.ActiveCfg = ReleaseUWP|x64
|
||||||
{39F0ADFF-3A84-470D-9CF0-CA49E164F2F3}.ReleaseUWP|x86.ActiveCfg = ReleaseUWP|Win32
|
{39F0ADFF-3A84-470D-9CF0-CA49E164F2F3}.ReleaseUWP|x86.ActiveCfg = ReleaseUWP|Win32
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.Debug|ARM64.Build.0 = Debug|ARM64
|
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.Debug|x64.ActiveCfg = Debug|x64
|
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.Debug|x64.Build.0 = Debug|x64
|
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.Debug|x86.ActiveCfg = Debug|Win32
|
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.Debug|x86.Build.0 = Debug|Win32
|
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.Debug|x86.Build.0 = Debug|Win32
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.DebugFast|ARM64.ActiveCfg = DebugFast|ARM64
|
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.DebugFast|ARM64.ActiveCfg = DebugFast|ARM64
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.DebugFast|ARM64.Build.0 = DebugFast|ARM64
|
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.DebugFast|x64.ActiveCfg = DebugFast|x64
|
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.DebugFast|x64.ActiveCfg = DebugFast|x64
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.DebugFast|x64.Build.0 = DebugFast|x64
|
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.DebugFast|x86.ActiveCfg = DebugFast|Win32
|
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.DebugFast|x86.ActiveCfg = DebugFast|Win32
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.DebugFast|x86.Build.0 = DebugFast|Win32
|
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.DebugFast|x86.Build.0 = DebugFast|Win32
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.DebugUWP|ARM64.ActiveCfg = DebugUWP|ARM64
|
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.DebugUWP|ARM64.ActiveCfg = DebugUWP|ARM64
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.DebugUWP|x64.ActiveCfg = DebugUWP|x64
|
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.DebugUWP|x64.ActiveCfg = DebugUWP|x64
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.DebugUWP|x86.ActiveCfg = DebugUWP|Win32
|
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.DebugUWP|x86.ActiveCfg = DebugUWP|Win32
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.Release|ARM64.ActiveCfg = Release|ARM64
|
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.Release|ARM64.Build.0 = Release|ARM64
|
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.Release|x64.ActiveCfg = Release|x64
|
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.Release|x64.ActiveCfg = Release|x64
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.Release|x64.Build.0 = Release|x64
|
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.Release|x86.ActiveCfg = Release|Win32
|
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.Release|x86.ActiveCfg = Release|Win32
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.Release|x86.Build.0 = Release|Win32
|
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.Release|x86.Build.0 = Release|Win32
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.ReleaseLTCG|ARM64.ActiveCfg = ReleaseLTCG|ARM64
|
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.ReleaseLTCG|ARM64.ActiveCfg = ReleaseLTCG|ARM64
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.ReleaseLTCG|ARM64.Build.0 = ReleaseLTCG|ARM64
|
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.ReleaseLTCG|x64.ActiveCfg = ReleaseLTCG|x64
|
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.ReleaseLTCG|x64.ActiveCfg = ReleaseLTCG|x64
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.ReleaseLTCG|x64.Build.0 = ReleaseLTCG|x64
|
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.ReleaseLTCG|x86.ActiveCfg = ReleaseLTCG|Win32
|
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.ReleaseLTCG|x86.ActiveCfg = ReleaseLTCG|Win32
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.ReleaseLTCG|x86.Build.0 = ReleaseLTCG|Win32
|
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.ReleaseLTCG|x86.Build.0 = ReleaseLTCG|Win32
|
||||||
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.ReleaseUWP|ARM64.ActiveCfg = ReleaseUWP|ARM64
|
{0A172B2E-DC67-49FC-A4C1-975F93C586C4}.ReleaseUWP|ARM64.ActiveCfg = ReleaseUWP|ARM64
|
||||||
|
|
|
@ -896,6 +896,105 @@ void GrowableMemoryByteStream::Grow(u32 MinimumGrowth)
|
||||||
ResizeMemory(NewSize);
|
ResizeMemory(NewSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ByteStream::ReadU8(u8* dest)
|
||||||
|
{
|
||||||
|
return Read2(dest, sizeof(u8));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteStream::ReadU16(u16* dest)
|
||||||
|
{
|
||||||
|
return Read2(dest, sizeof(u16));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteStream::ReadU32(u32* dest)
|
||||||
|
{
|
||||||
|
return Read2(dest, sizeof(u32));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteStream::ReadU64(u64* dest)
|
||||||
|
{
|
||||||
|
return Read2(dest, sizeof(u64));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteStream::ReadS8(s8* dest)
|
||||||
|
{
|
||||||
|
return Read2(dest, sizeof(s8));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteStream::ReadS16(s16* dest)
|
||||||
|
{
|
||||||
|
return Read2(dest, sizeof(s16));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteStream::ReadS32(s32* dest)
|
||||||
|
{
|
||||||
|
return Read2(dest, sizeof(s32));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteStream::ReadS64(s64* dest)
|
||||||
|
{
|
||||||
|
return Read2(dest, sizeof(s64));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteStream::ReadSizePrefixedString(std::string* dest)
|
||||||
|
{
|
||||||
|
u32 size;
|
||||||
|
if (!Read2(&size, sizeof(size)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
dest->resize(size);
|
||||||
|
if (!Read2(dest->data(), size))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteStream::WriteU8(u8 dest)
|
||||||
|
{
|
||||||
|
return Write2(&dest, sizeof(u8));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteStream::WriteU16(u16 dest)
|
||||||
|
{
|
||||||
|
return Write2(&dest, sizeof(u16));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteStream::WriteU32(u32 dest)
|
||||||
|
{
|
||||||
|
return Write2(&dest, sizeof(u32));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteStream::WriteU64(u64 dest)
|
||||||
|
{
|
||||||
|
return Write2(&dest, sizeof(u64));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteStream::WriteS8(s8 dest)
|
||||||
|
{
|
||||||
|
return Write2(&dest, sizeof(s8));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteStream::WriteS16(s16 dest)
|
||||||
|
{
|
||||||
|
return Write2(&dest, sizeof(s16));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteStream::WriteS32(s32 dest)
|
||||||
|
{
|
||||||
|
return Write2(&dest, sizeof(s32));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteStream::WriteS64(s64 dest)
|
||||||
|
{
|
||||||
|
return Write2(&dest, sizeof(s64));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ByteStream::WriteSizePrefixedString(const std::string_view& str)
|
||||||
|
{
|
||||||
|
const u32 size = static_cast<u32>(str.size());
|
||||||
|
return (Write2(&size, sizeof(size)) && (size == 0 || Write2(str.data(), size)));
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<ByteStream> ByteStream::OpenFile(const char* fileName, u32 openMode)
|
std::unique_ptr<ByteStream> ByteStream::OpenFile(const char* fileName, u32 openMode)
|
||||||
{
|
{
|
||||||
if ((openMode & (BYTESTREAM_OPEN_CREATE | BYTESTREAM_OPEN_WRITE)) == BYTESTREAM_OPEN_WRITE)
|
if ((openMode & (BYTESTREAM_OPEN_CREATE | BYTESTREAM_OPEN_WRITE)) == BYTESTREAM_OPEN_WRITE)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
// base byte stream creation functions
|
// base byte stream creation functions
|
||||||
|
@ -76,6 +77,26 @@ public:
|
||||||
inline void SetErrorState() { m_errorState = true; }
|
inline void SetErrorState() { m_errorState = true; }
|
||||||
inline void ClearErrorState() { m_errorState = false; }
|
inline void ClearErrorState() { m_errorState = false; }
|
||||||
|
|
||||||
|
bool ReadU8(u8* dest);
|
||||||
|
bool ReadU16(u16* dest);
|
||||||
|
bool ReadU32(u32* dest);
|
||||||
|
bool ReadU64(u64* dest);
|
||||||
|
bool ReadS8(s8* dest);
|
||||||
|
bool ReadS16(s16* dest);
|
||||||
|
bool ReadS32(s32* dest);
|
||||||
|
bool ReadS64(s64* dest);
|
||||||
|
bool ReadSizePrefixedString(std::string* dest);
|
||||||
|
|
||||||
|
bool WriteU8(u8 dest);
|
||||||
|
bool WriteU16(u16 dest);
|
||||||
|
bool WriteU32(u32 dest);
|
||||||
|
bool WriteU64(u64 dest);
|
||||||
|
bool WriteS8(s8 dest);
|
||||||
|
bool WriteS16(s16 dest);
|
||||||
|
bool WriteS32(s32 dest);
|
||||||
|
bool WriteS64(s64 dest);
|
||||||
|
bool WriteSizePrefixedString(const std::string_view& str);
|
||||||
|
|
||||||
// base byte stream creation functions
|
// base byte stream creation functions
|
||||||
// opens a local file-based stream. fills in error if passed, and returns false if the file cannot be opened.
|
// opens a local file-based stream. fills in error if passed, and returns false if the file cannot be opened.
|
||||||
static std::unique_ptr<ByteStream> OpenFile(const char* FileName, u32 OpenMode);
|
static std::unique_ptr<ByteStream> OpenFile(const char* FileName, u32 OpenMode);
|
||||||
|
|
|
@ -167,7 +167,7 @@ std::string ShaderCache::GetCacheBaseFileName(const std::string_view& base_path,
|
||||||
bool debug)
|
bool debug)
|
||||||
{
|
{
|
||||||
std::string base_filename(base_path);
|
std::string base_filename(base_path);
|
||||||
base_filename += "d3d_shaders_";
|
base_filename += FS_OSPATH_SEPARATOR_STR "d3d_shaders_";
|
||||||
|
|
||||||
switch (feature_level)
|
switch (feature_level)
|
||||||
{
|
{
|
||||||
|
|
|
@ -226,7 +226,7 @@ std::string ShaderCache::GetCacheBaseFileName(const std::string_view& base_path,
|
||||||
D3D_FEATURE_LEVEL feature_level, bool debug)
|
D3D_FEATURE_LEVEL feature_level, bool debug)
|
||||||
{
|
{
|
||||||
std::string base_filename(base_path);
|
std::string base_filename(base_path);
|
||||||
base_filename += "d3d12_";
|
base_filename += FS_OSPATH_SEPARATOR_STR "d3d12_";
|
||||||
base_filename += type;
|
base_filename += type;
|
||||||
base_filename += "_";
|
base_filename += "_";
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "../file_system.h"
|
#include "../file_system.h"
|
||||||
#include "../log.h"
|
#include "../log.h"
|
||||||
#include "../md5_digest.h"
|
#include "../md5_digest.h"
|
||||||
|
#include "../path.h"
|
||||||
#include "../string_util.h"
|
#include "../string_util.h"
|
||||||
Log_SetChannel(GL::ShaderCache);
|
Log_SetChannel(GL::ShaderCache);
|
||||||
|
|
||||||
|
@ -251,12 +252,12 @@ ShaderCache::CacheIndexKey ShaderCache::GetCacheKey(const std::string_view& vert
|
||||||
|
|
||||||
std::string ShaderCache::GetIndexFileName() const
|
std::string ShaderCache::GetIndexFileName() const
|
||||||
{
|
{
|
||||||
return StringUtil::StdStringFromFormat("%sgl_programs.idx", m_base_path.c_str());
|
return Path::Combine(m_base_path, "gl_programs.idx");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ShaderCache::GetBlobFileName() const
|
std::string ShaderCache::GetBlobFileName() const
|
||||||
{
|
{
|
||||||
return StringUtil::StdStringFromFormat("%sgl_programs.bin", m_base_path.c_str());
|
return Path::Combine(m_base_path, "gl_programs.bin");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<Program> ShaderCache::GetProgram(const std::string_view vertex_shader,
|
std::optional<Program> ShaderCache::GetProgram(const std::string_view vertex_shader,
|
||||||
|
|
|
@ -7,7 +7,7 @@ Log_SetChannel(HTTPDownloader);
|
||||||
static constexpr float DEFAULT_TIMEOUT_IN_SECONDS = 30;
|
static constexpr float DEFAULT_TIMEOUT_IN_SECONDS = 30;
|
||||||
static constexpr u32 DEFAULT_MAX_ACTIVE_REQUESTS = 4;
|
static constexpr u32 DEFAULT_MAX_ACTIVE_REQUESTS = 4;
|
||||||
|
|
||||||
namespace FrontendCommon {
|
namespace Common {
|
||||||
|
|
||||||
const char HTTPDownloader::DEFAULT_USER_AGENT[] =
|
const char HTTPDownloader::DEFAULT_USER_AGENT[] =
|
||||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0";
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:85.0) Gecko/20100101 Firefox/85.0";
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace FrontendCommon {
|
namespace Common {
|
||||||
|
|
||||||
class HTTPDownloader
|
class HTTPDownloader
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
Log_SetChannel(HTTPDownloaderCurl);
|
Log_SetChannel(HTTPDownloaderCurl);
|
||||||
|
|
||||||
namespace FrontendCommon {
|
namespace Common {
|
||||||
|
|
||||||
HTTPDownloaderCurl::HTTPDownloaderCurl() : HTTPDownloader() {}
|
HTTPDownloaderCurl::HTTPDownloaderCurl() : HTTPDownloader() {}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
namespace FrontendCommon {
|
namespace Common {
|
||||||
|
|
||||||
class HTTPDownloaderCurl final : public HTTPDownloader
|
class HTTPDownloaderCurl final : public HTTPDownloader
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,7 +13,7 @@ Log_SetChannel(HTTPDownloaderWinHttp);
|
||||||
using namespace winrt::Windows::Foundation;
|
using namespace winrt::Windows::Foundation;
|
||||||
using namespace winrt::Windows::Web::Http;
|
using namespace winrt::Windows::Web::Http;
|
||||||
|
|
||||||
namespace FrontendCommon {
|
namespace Common {
|
||||||
|
|
||||||
HTTPDownloaderUWP::HTTPDownloaderUWP(std::string user_agent) : HTTPDownloader(), m_user_agent(std::move(user_agent)) {}
|
HTTPDownloaderUWP::HTTPDownloaderUWP(std::string user_agent) : HTTPDownloader(), m_user_agent(std::move(user_agent)) {}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include <winrt/windows.Web.Http.h>
|
#include <winrt/windows.Web.Http.h>
|
||||||
|
|
||||||
namespace FrontendCommon {
|
namespace Common {
|
||||||
|
|
||||||
class HTTPDownloaderUWP final : public HTTPDownloader
|
class HTTPDownloaderUWP final : public HTTPDownloader
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,7 +9,7 @@ Log_SetChannel(HTTPDownloaderWinHttp);
|
||||||
|
|
||||||
#pragma comment(lib, "winhttp.lib")
|
#pragma comment(lib, "winhttp.lib")
|
||||||
|
|
||||||
namespace FrontendCommon {
|
namespace Common {
|
||||||
|
|
||||||
HTTPDownloaderWinHttp::HTTPDownloaderWinHttp() : HTTPDownloader() {}
|
HTTPDownloaderWinHttp::HTTPDownloaderWinHttp() : HTTPDownloader() {}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
#include <winhttp.h>
|
#include <winhttp.h>
|
||||||
|
|
||||||
namespace FrontendCommon {
|
namespace Common {
|
||||||
|
|
||||||
class HTTPDownloaderWinHttp final : public HTTPDownloader
|
class HTTPDownloaderWinHttp final : public HTTPDownloader
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include "heterogeneous_containers.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
@ -13,7 +14,7 @@ class LRUCache
|
||||||
CounterType last_access;
|
CounterType last_access;
|
||||||
};
|
};
|
||||||
|
|
||||||
using MapType = std::map<K, Item>;
|
using MapType = std::conditional_t<std::is_same_v<K, std::string>, StringMap<Item>, std::map<K, Item>>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LRUCache(std::size_t max_capacity = 16, bool manual_evict = false)
|
LRUCache(std::size_t max_capacity = 16, bool manual_evict = false)
|
||||||
|
|
|
@ -24,15 +24,18 @@
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
#define gettid() syscall(SYS_gettid)
|
#define gettid() syscall(SYS_gettid)
|
||||||
#endif
|
#endif
|
||||||
#else
|
#elif defined(__APPLE__)
|
||||||
|
#include <mach/mach.h>
|
||||||
|
#include <mach/mach_error.h>
|
||||||
|
#include <mach/mach_time.h>
|
||||||
|
#include <mach/semaphore.h>
|
||||||
|
#include <mach/task.h>
|
||||||
#include <pthread_np.h>
|
#include <pthread_np.h>
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
// This hacky union would probably fail on some cpu platforms if the contents of FILETIME aren't
|
union FileTimeU64Union
|
||||||
// packed (but for any x86 CPU and microsoft compiler, they will be).
|
|
||||||
union FileTimeSucks
|
|
||||||
{
|
{
|
||||||
FILETIME filetime;
|
FILETIME filetime;
|
||||||
u64 u64time;
|
u64 u64time;
|
||||||
|
@ -208,18 +211,16 @@ Threading::ThreadHandle& Threading::ThreadHandle::operator=(const ThreadHandle&
|
||||||
|
|
||||||
u64 Threading::ThreadHandle::GetCPUTime() const
|
u64 Threading::ThreadHandle::GetCPUTime() const
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32) && !defined(_UWP) && !defined(_M_ARM64)
|
||||||
#if 0
|
|
||||||
u64 ret = 0;
|
u64 ret = 0;
|
||||||
if (m_native_handle)
|
if (m_native_handle)
|
||||||
QueryThreadCycleTime((HANDLE)m_native_handle, &ret);
|
QueryThreadCycleTime((HANDLE)m_native_handle, &ret);
|
||||||
return ret;
|
return ret;
|
||||||
#else
|
#elif defined(_WIN32)
|
||||||
FileTimeSucks user = {}, kernel = {};
|
FileTimeU64Union user = {}, kernel = {};
|
||||||
FILETIME dummy;
|
FILETIME dummy;
|
||||||
GetThreadTimes((HANDLE)m_native_handle, &dummy, &dummy, &kernel.filetime, &user.filetime);
|
GetThreadTimes((HANDLE)m_native_handle, &dummy, &dummy, &kernel.filetime, &user.filetime);
|
||||||
return user.u64time + kernel.u64time;
|
return user.u64time + kernel.u64time;
|
||||||
#endif
|
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
return getthreadtime(pthread_mach_thread_np((pthread_t)m_native_handle));
|
return getthreadtime(pthread_mach_thread_np((pthread_t)m_native_handle));
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
|
@ -457,17 +458,15 @@ Threading::ThreadHandle& Threading::Thread::operator=(Thread&& thread)
|
||||||
|
|
||||||
u64 Threading::GetThreadCpuTime()
|
u64 Threading::GetThreadCpuTime()
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32) && !defined(_UWP) && !defined(_M_ARM64)
|
||||||
#if 0
|
|
||||||
u64 ret = 0;
|
u64 ret = 0;
|
||||||
QueryThreadCycleTime(GetCurrentThread(), &ret);
|
QueryThreadCycleTime(GetCurrentThread(), &ret);
|
||||||
return ret;
|
return ret;
|
||||||
#else
|
#elif defined(_WIN32)
|
||||||
FileTimeSucks user = {}, kernel = {};
|
FileTimeU64Union user = {}, kernel = {};
|
||||||
FILETIME dummy;
|
FILETIME dummy;
|
||||||
GetThreadTimes(GetCurrentThread(), &dummy, &dummy, &kernel.filetime, &user.filetime);
|
GetThreadTimes(GetCurrentThread(), &dummy, &dummy, &kernel.filetime, &user.filetime);
|
||||||
return user.u64time + kernel.u64time;
|
return user.u64time + kernel.u64time;
|
||||||
#endif
|
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
return getthreadtime(pthread_mach_thread_np(pthread_self()));
|
return getthreadtime(pthread_mach_thread_np(pthread_self()));
|
||||||
#else
|
#else
|
||||||
|
@ -477,17 +476,33 @@ u64 Threading::GetThreadCpuTime()
|
||||||
|
|
||||||
u64 Threading::GetThreadTicksPerSecond()
|
u64 Threading::GetThreadTicksPerSecond()
|
||||||
{
|
{
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32) && !defined(_UWP) && !defined(_M_ARM64)
|
||||||
#if 0
|
|
||||||
// On x86, despite what the MS documentation says, this basically appears to be rdtsc.
|
// On x86, despite what the MS documentation says, this basically appears to be rdtsc.
|
||||||
// So, the frequency is our base clock speed (and stable regardless of power management).
|
// So, the frequency is our base clock speed (and stable regardless of power management).
|
||||||
static u64 frequency = 0;
|
static u64 frequency = 0;
|
||||||
if (unlikely(frequency == 0))
|
if (UNLIKELY(frequency == 0))
|
||||||
frequency = x86caps.CachedMHz() * u64(1000000);
|
{
|
||||||
|
frequency = 1000000;
|
||||||
|
|
||||||
|
HKEY hKey;
|
||||||
|
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", 0, KEY_READ, &hKey) ==
|
||||||
|
ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
DWORD value;
|
||||||
|
DWORD value_size = sizeof(value);
|
||||||
|
if (RegQueryValueExW(hKey, L"~MHz", 0, nullptr, reinterpret_cast<LPBYTE>(&value), &value_size) == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
// value is in mhz, convert to hz
|
||||||
|
frequency *= value;
|
||||||
|
}
|
||||||
|
|
||||||
|
RegCloseKey(hKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return frequency;
|
return frequency;
|
||||||
#else
|
#elif defined(_WIN32)
|
||||||
return 10000000;
|
return 10000000;
|
||||||
#endif
|
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
return 1000000;
|
return 1000000;
|
||||||
|
|
||||||
|
@ -539,3 +554,60 @@ void Threading::SetNameOfCurrentThread(const char* name)
|
||||||
pthread_set_name_np(pthread_self(), name);
|
pthread_set_name_np(pthread_self(), name);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Threading::KernelSemaphore::KernelSemaphore()
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
m_sema = CreateSemaphore(nullptr, 0, LONG_MAX, nullptr);
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
semaphore_create(mach_task_self(), &m_sema, SYNC_POLICY_FIFO, 0);
|
||||||
|
#else
|
||||||
|
sem_init(&m_sema, false, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Threading::KernelSemaphore::~KernelSemaphore()
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
CloseHandle(m_sema);
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
semaphore_destroy(mach_task_self(), m_sema);
|
||||||
|
#else
|
||||||
|
sem_destroy(&m_sema);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Threading::KernelSemaphore::Post()
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
ReleaseSemaphore(m_sema, 1, nullptr);
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
semaphore_signal(m_sema);
|
||||||
|
#else
|
||||||
|
sem_post(&m_sema);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Threading::KernelSemaphore::Wait()
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
WaitForSingleObject(m_sema, INFINITE);
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
semaphore_wait(m_sema);
|
||||||
|
#else
|
||||||
|
sem_wait(&m_sema);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Threading::KernelSemaphore::TryWait()
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
return WaitForSingleObject(m_sema, 0) == WAIT_OBJECT_0;
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
mach_timespec_t time = {};
|
||||||
|
kern_return_t res = semaphore_timedwait(m_sema, time);
|
||||||
|
return (res != KERN_OPERATION_TIMED_OUT);
|
||||||
|
#else
|
||||||
|
return sem_trywait(&m_sema) == 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -55,6 +55,16 @@ char (&__countof_ArraySizeHelper(T (&array)[N]))[N];
|
||||||
#define printflike(n,m)
|
#define printflike(n,m)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
// TODO: Use C++20 [[likely]] when available.
|
||||||
|
#define LIKELY(x) (!!(x))
|
||||||
|
#define UNLIKELY(x) (!!(x))
|
||||||
|
#else
|
||||||
|
#define LIKELY(x) __builtin_expect(!!(x), 1)
|
||||||
|
#define UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// disable warnings that show up at warning level 4
|
// disable warnings that show up at warning level 4
|
||||||
// TODO: Move to build system instead
|
// TODO: Move to build system instead
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
|
@ -386,7 +386,7 @@ void ShaderCache::ClosePipelineCache()
|
||||||
std::string ShaderCache::GetShaderCacheBaseFileName(const std::string_view& base_path, bool debug)
|
std::string ShaderCache::GetShaderCacheBaseFileName(const std::string_view& base_path, bool debug)
|
||||||
{
|
{
|
||||||
std::string base_filename(base_path);
|
std::string base_filename(base_path);
|
||||||
base_filename += "vulkan_shaders";
|
base_filename += FS_OSPATH_SEPARATOR_STR "vulkan_shaders";
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
base_filename += "_debug";
|
base_filename += "_debug";
|
||||||
|
@ -397,7 +397,7 @@ std::string ShaderCache::GetShaderCacheBaseFileName(const std::string_view& base
|
||||||
std::string ShaderCache::GetPipelineCacheBaseFileName(const std::string_view& base_path, bool debug)
|
std::string ShaderCache::GetPipelineCacheBaseFileName(const std::string_view& base_path, bool debug)
|
||||||
{
|
{
|
||||||
std::string base_filename(base_path);
|
std::string base_filename(base_path);
|
||||||
base_filename += "vulkan_pipelines";
|
base_filename += FS_OSPATH_SEPARATOR_STR "vulkan_pipelines";
|
||||||
|
|
||||||
if (debug)
|
if (debug)
|
||||||
base_filename += "_debug";
|
base_filename += "_debug";
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
add_library(core
|
add_library(core
|
||||||
|
achievements.h
|
||||||
analog_controller.cpp
|
analog_controller.cpp
|
||||||
analog_controller.h
|
analog_controller.h
|
||||||
analog_joystick.cpp
|
analog_joystick.cpp
|
||||||
|
@ -28,6 +29,8 @@ add_library(core
|
||||||
digital_controller.h
|
digital_controller.h
|
||||||
dma.cpp
|
dma.cpp
|
||||||
dma.h
|
dma.h
|
||||||
|
game_database.cpp
|
||||||
|
game_database.h
|
||||||
gdb_protocol.cpp
|
gdb_protocol.cpp
|
||||||
gdb_protocol.h
|
gdb_protocol.h
|
||||||
gpu.cpp
|
gpu.cpp
|
||||||
|
@ -48,21 +51,18 @@ add_library(core
|
||||||
gpu_sw_backend.cpp
|
gpu_sw_backend.cpp
|
||||||
gpu_sw_backend.h
|
gpu_sw_backend.h
|
||||||
gpu_types.h
|
gpu_types.h
|
||||||
|
guncon.cpp
|
||||||
|
guncon.h
|
||||||
gte.cpp
|
gte.cpp
|
||||||
gte.h
|
gte.h
|
||||||
gte_types.h
|
gte_types.h
|
||||||
|
host.cpp
|
||||||
host.h
|
host.h
|
||||||
host_display.cpp
|
host_display.cpp
|
||||||
host_display.h
|
host_display.h
|
||||||
host_interface.cpp
|
|
||||||
host_interface.h
|
|
||||||
host_interface_progress_callback.cpp
|
host_interface_progress_callback.cpp
|
||||||
host_interface_progress_callback.h
|
host_interface_progress_callback.h
|
||||||
host_settings.h
|
host_settings.h
|
||||||
imgui_styles.cpp
|
|
||||||
imgui_styles.h
|
|
||||||
imgui_fullscreen.cpp
|
|
||||||
imgui_fullscreen.h
|
|
||||||
interrupt_controller.cpp
|
interrupt_controller.cpp
|
||||||
interrupt_controller.h
|
interrupt_controller.h
|
||||||
libcrypt_game_codes.cpp
|
libcrypt_game_codes.cpp
|
||||||
|
@ -75,8 +75,6 @@ add_library(core
|
||||||
memory_card_image.h
|
memory_card_image.h
|
||||||
multitap.cpp
|
multitap.cpp
|
||||||
multitap.h
|
multitap.h
|
||||||
namco_guncon.cpp
|
|
||||||
namco_guncon.h
|
|
||||||
negcon.cpp
|
negcon.cpp
|
||||||
negcon.h
|
negcon.h
|
||||||
pad.cpp
|
pad.cpp
|
||||||
|
@ -123,7 +121,7 @@ set(RECOMPILER_SRCS
|
||||||
target_include_directories(core PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
target_include_directories(core PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
||||||
target_include_directories(core PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
target_include_directories(core PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
|
||||||
target_link_libraries(core PUBLIC Threads::Threads common util zlib)
|
target_link_libraries(core PUBLIC Threads::Threads common util zlib)
|
||||||
target_link_libraries(core PRIVATE glad stb xxhash imgui)
|
target_link_libraries(core PRIVATE glad stb xxhash imgui rapidjson tinyxml2)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
target_sources(core PRIVATE
|
target_sources(core PRIVATE
|
||||||
|
@ -161,10 +159,5 @@ else()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(ENABLE_CHEEVOS)
|
if(ENABLE_CHEEVOS)
|
||||||
target_sources(core PRIVATE
|
target_compile_definitions(core PRIVATE -DWITH_CHEEVOS=1)
|
||||||
cheevos.cpp
|
|
||||||
cheevos.h
|
|
||||||
)
|
|
||||||
target_compile_definitions(core PUBLIC -DWITH_CHEEVOS=1)
|
|
||||||
target_link_libraries(core PRIVATE rcheevos rapidjson)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
55
src/core/achievements.h
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
#pragma once
|
||||||
|
#include "common/types.h"
|
||||||
|
|
||||||
|
class StateWrapper;
|
||||||
|
class CDImage;
|
||||||
|
|
||||||
|
namespace Achievements {
|
||||||
|
|
||||||
|
#ifdef WITH_CHEEVOS
|
||||||
|
|
||||||
|
// Implemented in Host.
|
||||||
|
extern bool Reset();
|
||||||
|
extern bool DoState(StateWrapper& sw);
|
||||||
|
extern void GameChanged(const std::string& path, CDImage* image);
|
||||||
|
|
||||||
|
/// Re-enables hardcode mode if it is enabled in the settings.
|
||||||
|
extern void ResetChallengeMode();
|
||||||
|
|
||||||
|
/// Forces hardcore mode off until next reset.
|
||||||
|
extern void DisableChallengeMode();
|
||||||
|
|
||||||
|
/// Prompts the user to disable hardcore mode, if they agree, returns true.
|
||||||
|
extern bool ConfirmChallengeModeDisable(const char* trigger);
|
||||||
|
|
||||||
|
/// Returns true if features such as save states should be disabled.
|
||||||
|
extern bool ChallengeModeActive();
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// Make noops when compiling without cheevos.
|
||||||
|
static inline bool Reset()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static inline bool DoState(StateWrapper& sw)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
static constexpr inline bool ChallengeModeActive()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ResetChallengeMode() {}
|
||||||
|
|
||||||
|
static inline void DisableChallengeMode() {}
|
||||||
|
|
||||||
|
static inline bool ConfirmChallengeModeDisable(const char* trigger)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace Achievements
|
|
@ -1,14 +1,14 @@
|
||||||
#include "analog_controller.h"
|
#include "analog_controller.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "host_interface.h"
|
#include "host.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "util/state_wrapper.h"
|
#include "util/state_wrapper.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
Log_SetChannel(AnalogController);
|
Log_SetChannel(AnalogController);
|
||||||
|
|
||||||
AnalogController::AnalogController(u32 index) : m_index(index)
|
AnalogController::AnalogController(u32 index) : Controller(index)
|
||||||
{
|
{
|
||||||
m_axis_state.fill(0x80);
|
m_axis_state.fill(0x80);
|
||||||
Reset();
|
Reset();
|
||||||
|
@ -29,7 +29,12 @@ void AnalogController::Reset()
|
||||||
m_tx_buffer.fill(0x00);
|
m_tx_buffer.fill(0x00);
|
||||||
m_analog_mode = false;
|
m_analog_mode = false;
|
||||||
m_configuration_mode = false;
|
m_configuration_mode = false;
|
||||||
m_motor_state.fill(0);
|
|
||||||
|
for (u32 i = 0; i < NUM_MOTORS; i++)
|
||||||
|
{
|
||||||
|
if (m_motor_state[i] != 0)
|
||||||
|
SetMotorState(i, 0);
|
||||||
|
}
|
||||||
|
|
||||||
m_dualshock_enabled = false;
|
m_dualshock_enabled = false;
|
||||||
ResetRumbleConfig();
|
ResetRumbleConfig();
|
||||||
|
@ -40,8 +45,8 @@ void AnalogController::Reset()
|
||||||
{
|
{
|
||||||
if (g_settings.controller_disable_analog_mode_forcing)
|
if (g_settings.controller_disable_analog_mode_forcing)
|
||||||
{
|
{
|
||||||
g_host_interface->AddOSDMessage(
|
Host::AddOSDMessage(
|
||||||
g_host_interface->TranslateStdString(
|
Host::TranslateStdString(
|
||||||
"OSDMessage", "Analog mode forcing is disabled by game settings. Controller will start in digital mode."),
|
"OSDMessage", "Analog mode forcing is disabled by game settings. Controller will start in digital mode."),
|
||||||
10.0f);
|
10.0f);
|
||||||
}
|
}
|
||||||
|
@ -88,72 +93,42 @@ bool AnalogController::DoState(StateWrapper& sw, bool apply_input_state)
|
||||||
|
|
||||||
if (old_analog_mode != m_analog_mode)
|
if (old_analog_mode != m_analog_mode)
|
||||||
{
|
{
|
||||||
g_host_interface->AddFormattedOSDMessage(
|
Host::AddFormattedOSDMessage(
|
||||||
5.0f,
|
5.0f,
|
||||||
m_analog_mode ?
|
m_analog_mode ? Host::TranslateString("AnalogController", "Controller %u switched to analog mode.") :
|
||||||
g_host_interface->TranslateString("AnalogController", "Controller %u switched to analog mode.") :
|
Host::TranslateString("AnalogController", "Controller %u switched to digital mode."),
|
||||||
g_host_interface->TranslateString("AnalogController", "Controller %u switched to digital mode."),
|
|
||||||
m_index + 1u);
|
m_index + 1u);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<s32> AnalogController::GetAxisCodeByName(std::string_view axis_name) const
|
float AnalogController::GetBindState(u32 index) const
|
||||||
{
|
{
|
||||||
return StaticGetAxisCodeByName(axis_name);
|
if (index >= static_cast<u32>(Button::Count))
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<s32> AnalogController::GetButtonCodeByName(std::string_view button_name) const
|
|
||||||
{
|
{
|
||||||
return StaticGetButtonCodeByName(button_name);
|
const u32 sub_index = index - static_cast<u32>(Button::Count);
|
||||||
}
|
if (sub_index >= static_cast<u32>(m_half_axis_state.size()))
|
||||||
|
|
||||||
float AnalogController::GetAxisState(s32 axis_code) const
|
|
||||||
{
|
|
||||||
if (axis_code < 0 || axis_code >= static_cast<s32>(Axis::Count))
|
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
|
|
||||||
// 0..255 -> -1..1
|
return static_cast<float>(m_half_axis_state[sub_index]) * (1.0f / 255.0f);
|
||||||
const float value = (((static_cast<float>(m_axis_state[static_cast<s32>(axis_code)]) / 255.0f) * 2.0f) - 1.0f);
|
}
|
||||||
return std::clamp(value / m_axis_scale, -1.0f, 1.0f);
|
else if (index < static_cast<u32>(Button::Analog))
|
||||||
|
{
|
||||||
|
return static_cast<float>(((m_button_state >> index) & 1u) ^ 1u);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnalogController::SetAxisState(s32 axis_code, float value)
|
void AnalogController::SetBindState(u32 index, float value)
|
||||||
{
|
{
|
||||||
if (axis_code < 0 || axis_code >= static_cast<s32>(Axis::Count))
|
if (index == static_cast<s32>(Button::Analog))
|
||||||
return;
|
|
||||||
|
|
||||||
// -1..1 -> 0..255
|
|
||||||
const float scaled_value = std::clamp(value * m_axis_scale, -1.0f, 1.0f);
|
|
||||||
const u8 u8_value = static_cast<u8>(std::clamp(std::round(((scaled_value + 1.0f) / 2.0f) * 255.0f), 0.0f, 255.0f));
|
|
||||||
|
|
||||||
SetAxisState(static_cast<Axis>(axis_code), u8_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnalogController::SetAxisState(Axis axis, u8 value)
|
|
||||||
{
|
|
||||||
if (value != m_axis_state[static_cast<u8>(axis)])
|
|
||||||
System::SetRunaheadReplayFlag();
|
|
||||||
|
|
||||||
m_axis_state[static_cast<u8>(axis)] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AnalogController::GetButtonState(s32 button_code) const
|
|
||||||
{
|
|
||||||
if (button_code < 0 || button_code >= static_cast<s32>(Button::Analog))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const u16 bit = u16(1) << static_cast<u8>(button_code);
|
|
||||||
return ((m_button_state & bit) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnalogController::SetButtonState(Button button, bool pressed)
|
|
||||||
{
|
|
||||||
if (button == Button::Analog)
|
|
||||||
{
|
{
|
||||||
// analog toggle
|
// analog toggle
|
||||||
if (pressed)
|
if (value >= 0.5f)
|
||||||
{
|
{
|
||||||
if (m_command == Command::Idle)
|
if (m_command == Command::Idle)
|
||||||
ProcessAnalogModeToggle();
|
ProcessAnalogModeToggle();
|
||||||
|
@ -163,10 +138,58 @@ void AnalogController::SetButtonState(Button button, bool pressed)
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (index >= static_cast<u32>(Button::Count))
|
||||||
|
{
|
||||||
|
const u32 sub_index = index - static_cast<u32>(Button::Count);
|
||||||
|
if (sub_index >= static_cast<u32>(m_half_axis_state.size()))
|
||||||
|
return;
|
||||||
|
|
||||||
const u16 bit = u16(1) << static_cast<u8>(button);
|
value = ApplyAnalogDeadzoneSensitivity(m_analog_deadzone, m_analog_sensitivity, value);
|
||||||
|
const u8 u8_value = static_cast<u8>(std::clamp(value * 255.0f, 0.0f, 255.0f));
|
||||||
|
if (u8_value == m_half_axis_state[sub_index])
|
||||||
|
return;
|
||||||
|
|
||||||
if (pressed)
|
m_half_axis_state[sub_index] = u8_value;
|
||||||
|
System::SetRunaheadReplayFlag();
|
||||||
|
|
||||||
|
#define MERGE(pos, neg) \
|
||||||
|
((m_half_axis_state[static_cast<u32>(pos)] != 0) ? (127u + ((m_half_axis_state[static_cast<u32>(pos)] + 1u) / 2u)) : \
|
||||||
|
(127u - (m_half_axis_state[static_cast<u32>(neg)] / 2u)))
|
||||||
|
|
||||||
|
switch (static_cast<HalfAxis>(sub_index))
|
||||||
|
{
|
||||||
|
case HalfAxis::LLeft:
|
||||||
|
case HalfAxis::LRight:
|
||||||
|
m_axis_state[static_cast<u8>(Axis::LeftX)] = MERGE(HalfAxis::LRight, HalfAxis::LLeft);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HalfAxis::LDown:
|
||||||
|
case HalfAxis::LUp:
|
||||||
|
m_axis_state[static_cast<u8>(Axis::LeftY)] = MERGE(HalfAxis::LDown, HalfAxis::LUp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HalfAxis::RLeft:
|
||||||
|
case HalfAxis::RRight:
|
||||||
|
m_axis_state[static_cast<u8>(Axis::RightX)] = MERGE(HalfAxis::RRight, HalfAxis::RLeft);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HalfAxis::RDown:
|
||||||
|
case HalfAxis::RUp:
|
||||||
|
m_axis_state[static_cast<u8>(Axis::RightY)] = MERGE(HalfAxis::RDown, HalfAxis::RUp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef MERGE
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u16 bit = u16(1) << static_cast<u8>(index);
|
||||||
|
|
||||||
|
if (value >= 0.5f)
|
||||||
{
|
{
|
||||||
if (m_button_state & bit)
|
if (m_button_state & bit)
|
||||||
System::SetRunaheadReplayFlag();
|
System::SetRunaheadReplayFlag();
|
||||||
|
@ -182,14 +205,6 @@ void AnalogController::SetButtonState(Button button, bool pressed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnalogController::SetButtonState(s32 button_code, bool pressed)
|
|
||||||
{
|
|
||||||
if (button_code < 0 || button_code >= static_cast<s32>(Button::Count))
|
|
||||||
return;
|
|
||||||
|
|
||||||
SetButtonState(static_cast<Button>(button_code), pressed);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 AnalogController::GetButtonStateBits() const
|
u32 AnalogController::GetButtonStateBits() const
|
||||||
{
|
{
|
||||||
// flip bits, native data is active low
|
// flip bits, native data is active low
|
||||||
|
@ -202,26 +217,6 @@ std::optional<u32> AnalogController::GetAnalogInputBytes() const
|
||||||
m_axis_state[static_cast<size_t>(Axis::RightY)] << 8 | m_axis_state[static_cast<size_t>(Axis::RightX)];
|
m_axis_state[static_cast<size_t>(Axis::RightY)] << 8 | m_axis_state[static_cast<size_t>(Axis::RightX)];
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 AnalogController::GetVibrationMotorCount() const
|
|
||||||
{
|
|
||||||
return NUM_MOTORS;
|
|
||||||
}
|
|
||||||
|
|
||||||
float AnalogController::GetVibrationMotorStrength(u32 motor)
|
|
||||||
{
|
|
||||||
DebugAssert(motor < NUM_MOTORS);
|
|
||||||
if (m_motor_state[motor] == 0)
|
|
||||||
return 0.0f;
|
|
||||||
|
|
||||||
// Curve from https://github.com/KrossX/Pokopom/blob/master/Pokopom/Input_XInput.cpp#L210
|
|
||||||
const double x =
|
|
||||||
static_cast<double>(std::min<u32>(static_cast<u32>(m_motor_state[motor]) + static_cast<u32>(m_rumble_bias), 255));
|
|
||||||
const double strength = 0.006474549734772402 * std::pow(x, 3.0) - 1.258165252213538 * std::pow(x, 2.0) +
|
|
||||||
156.82454281087692 * x + 3.637978807091713e-11;
|
|
||||||
|
|
||||||
return static_cast<float>(strength / 65535.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnalogController::ResetTransferState()
|
void AnalogController::ResetTransferState()
|
||||||
{
|
{
|
||||||
if (m_analog_toggle_queued)
|
if (m_analog_toggle_queued)
|
||||||
|
@ -240,10 +235,10 @@ void AnalogController::SetAnalogMode(bool enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Log_InfoPrintf("Controller %u switched to %s mode.", m_index + 1u, enabled ? "analog" : "digital");
|
Log_InfoPrintf("Controller %u switched to %s mode.", m_index + 1u, enabled ? "analog" : "digital");
|
||||||
g_host_interface->AddFormattedOSDMessage(
|
Host::AddFormattedOSDMessage(5.0f,
|
||||||
5.0f,
|
enabled ?
|
||||||
enabled ? g_host_interface->TranslateString("AnalogController", "Controller %u switched to analog mode.") :
|
Host::TranslateString("AnalogController", "Controller %u switched to analog mode.") :
|
||||||
g_host_interface->TranslateString("AnalogController", "Controller %u switched to digital mode."),
|
Host::TranslateString("AnalogController", "Controller %u switched to digital mode."),
|
||||||
m_index + 1u);
|
m_index + 1u);
|
||||||
m_analog_mode = enabled;
|
m_analog_mode = enabled;
|
||||||
}
|
}
|
||||||
|
@ -252,11 +247,10 @@ void AnalogController::ProcessAnalogModeToggle()
|
||||||
{
|
{
|
||||||
if (m_analog_locked)
|
if (m_analog_locked)
|
||||||
{
|
{
|
||||||
g_host_interface->AddFormattedOSDMessage(
|
Host::AddFormattedOSDMessage(
|
||||||
5.0f,
|
5.0f,
|
||||||
m_analog_mode ?
|
m_analog_mode ? Host::TranslateString("AnalogController", "Controller %u is locked to analog mode by the game.") :
|
||||||
g_host_interface->TranslateString("AnalogController", "Controller %u is locked to analog mode by the game.") :
|
Host::TranslateString("AnalogController", "Controller %u is locked to digital mode by the game."),
|
||||||
g_host_interface->TranslateString("AnalogController", "Controller %u is locked to digital mode by the game."),
|
|
||||||
m_index + 1u);
|
m_index + 1u);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -269,10 +263,32 @@ void AnalogController::ProcessAnalogModeToggle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnalogController::SetMotorState(u8 motor, u8 value)
|
void AnalogController::SetMotorState(u32 motor, u8 value)
|
||||||
{
|
{
|
||||||
DebugAssert(motor < NUM_MOTORS);
|
DebugAssert(motor < NUM_MOTORS);
|
||||||
|
if (m_motor_state[motor] != value)
|
||||||
|
{
|
||||||
m_motor_state[motor] = value;
|
m_motor_state[motor] = value;
|
||||||
|
UpdateHostVibration();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnalogController::UpdateHostVibration()
|
||||||
|
{
|
||||||
|
std::array<float, NUM_MOTORS> hvalues;
|
||||||
|
for (u32 motor = 0; motor < NUM_MOTORS; motor++)
|
||||||
|
{
|
||||||
|
// Curve from https://github.com/KrossX/Pokopom/blob/master/Pokopom/Input_XInput.cpp#L210
|
||||||
|
const u8 state = m_motor_state[motor];
|
||||||
|
const double x =
|
||||||
|
static_cast<double>(std::min<u32>(state + static_cast<u32>(m_rumble_bias), 255));
|
||||||
|
const double strength = 0.006474549734772402 * std::pow(x, 3.0) - 1.258165252213538 * std::pow(x, 2.0) +
|
||||||
|
156.82454281087692 * x + 3.637978807091713e-11;
|
||||||
|
|
||||||
|
hvalues[motor] = (state != 0) ? static_cast<float>(strength / 65535.0) : 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
Host::SetPadVibrationIntensity(m_index, hvalues[0], hvalues[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 AnalogController::GetExtraButtonMaskLSB() const
|
u8 AnalogController::GetExtraButtonMaskLSB() const
|
||||||
|
@ -350,7 +366,7 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out)
|
||||||
|
|
||||||
if (data_in == 0x01)
|
if (data_in == 0x01)
|
||||||
{
|
{
|
||||||
Log_DevPrintf("ACK controller access");
|
Log_DebugPrintf("ACK controller access");
|
||||||
m_command = Command::Ready;
|
m_command = Command::Ready;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -689,9 +705,9 @@ bool AnalogController::Transfer(const u8 data_in, u8* data_out)
|
||||||
{
|
{
|
||||||
m_command = Command::Idle;
|
m_command = Command::Idle;
|
||||||
|
|
||||||
Log_DevPrintf("Rx: %02x %02x %02x %02x %02x %02x %02x %02x", m_rx_buffer[0], m_rx_buffer[1], m_rx_buffer[2],
|
Log_DebugPrintf("Rx: %02x %02x %02x %02x %02x %02x %02x %02x", m_rx_buffer[0], m_rx_buffer[1], m_rx_buffer[2],
|
||||||
m_rx_buffer[3], m_rx_buffer[4], m_rx_buffer[5], m_rx_buffer[6], m_rx_buffer[7]);
|
m_rx_buffer[3], m_rx_buffer[4], m_rx_buffer[5], m_rx_buffer[6], m_rx_buffer[7]);
|
||||||
Log_DevPrintf("Tx: %02x %02x %02x %02x %02x %02x %02x %02x", m_tx_buffer[0], m_tx_buffer[1], m_tx_buffer[2],
|
Log_DebugPrintf("Tx: %02x %02x %02x %02x %02x %02x %02x %02x", m_tx_buffer[0], m_tx_buffer[1], m_tx_buffer[2],
|
||||||
m_tx_buffer[3], m_tx_buffer[4], m_tx_buffer[5], m_tx_buffer[6], m_tx_buffer[7]);
|
m_tx_buffer[3], m_tx_buffer[4], m_tx_buffer[5], m_tx_buffer[6], m_tx_buffer[7]);
|
||||||
|
|
||||||
m_rx_buffer.fill(0x00);
|
m_rx_buffer.fill(0x00);
|
||||||
|
@ -706,122 +722,89 @@ std::unique_ptr<AnalogController> AnalogController::Create(u32 index)
|
||||||
return std::make_unique<AnalogController>(index);
|
return std::make_unique<AnalogController>(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<s32> AnalogController::StaticGetAxisCodeByName(std::string_view axis_name)
|
static const Controller::ControllerBindingInfo s_binding_info[] = {
|
||||||
{
|
#define BUTTON(name, display_name, button, genb) \
|
||||||
#define AXIS(name) \
|
|
||||||
if (axis_name == #name) \
|
|
||||||
{ \
|
{ \
|
||||||
return static_cast<s32>(ZeroExtend32(static_cast<u8>(Axis::name))); \
|
name, display_name, static_cast<u32>(button), Controller::ControllerBindingType::Button, genb \
|
||||||
|
}
|
||||||
|
#define AXIS(name, display_name, halfaxis, genb) \
|
||||||
|
{ \
|
||||||
|
name, display_name, static_cast<u32>(AnalogController::Button::Count) + static_cast<u32>(halfaxis), \
|
||||||
|
Controller::ControllerBindingType::HalfAxis, genb \
|
||||||
}
|
}
|
||||||
|
|
||||||
AXIS(LeftX);
|
BUTTON("Up", "D-Pad Up", AnalogController::Button::Up, GenericInputBinding::DPadUp),
|
||||||
AXIS(LeftY);
|
BUTTON("Right", "D-Pad Right", AnalogController::Button::Right, GenericInputBinding::DPadRight),
|
||||||
AXIS(RightX);
|
BUTTON("Down", "D-Pad Down", AnalogController::Button::Down, GenericInputBinding::DPadDown),
|
||||||
AXIS(RightY);
|
BUTTON("Left", "D-Pad Left", AnalogController::Button::Left, GenericInputBinding::DPadLeft),
|
||||||
|
BUTTON("Triangle", "Triangle", AnalogController::Button::Triangle, GenericInputBinding::Triangle),
|
||||||
|
BUTTON("Circle", "Circle", AnalogController::Button::Circle, GenericInputBinding::Circle),
|
||||||
|
BUTTON("Cross", "Cross", AnalogController::Button::Cross, GenericInputBinding::Cross),
|
||||||
|
BUTTON("Square", "Square", AnalogController::Button::Square, GenericInputBinding::Square),
|
||||||
|
BUTTON("Select", "Select", AnalogController::Button::Select, GenericInputBinding::Select),
|
||||||
|
BUTTON("Start", "Start", AnalogController::Button::Start, GenericInputBinding::Start),
|
||||||
|
BUTTON("Analog", "Analog Toggle", AnalogController::Button::Analog, GenericInputBinding::System),
|
||||||
|
BUTTON("L1", "L1", AnalogController::Button::L1, GenericInputBinding::L1),
|
||||||
|
BUTTON("R1", "R1", AnalogController::Button::R1, GenericInputBinding::R1),
|
||||||
|
BUTTON("L2", "L2", AnalogController::Button::L2, GenericInputBinding::L2),
|
||||||
|
BUTTON("R2", "R2", AnalogController::Button::R2, GenericInputBinding::R2),
|
||||||
|
BUTTON("L3", "L3", AnalogController::Button::L3, GenericInputBinding::L3),
|
||||||
|
BUTTON("R3", "R3", AnalogController::Button::R3, GenericInputBinding::R3),
|
||||||
|
|
||||||
return std::nullopt;
|
AXIS("LLeft", "Left Stick Left", AnalogController::HalfAxis::LLeft, GenericInputBinding::LeftStickLeft),
|
||||||
|
AXIS("LRight", "Left Stick Right", AnalogController::HalfAxis::LRight, GenericInputBinding::LeftStickRight),
|
||||||
|
AXIS("LDown", "Left Stick Down", AnalogController::HalfAxis::LDown, GenericInputBinding::LeftStickDown),
|
||||||
|
AXIS("LUp", "Left Stick Up", AnalogController::HalfAxis::LUp, GenericInputBinding::LeftStickUp),
|
||||||
|
AXIS("RLeft", "Right Stick Left", AnalogController::HalfAxis::RLeft, GenericInputBinding::RightStickLeft),
|
||||||
|
AXIS("RRight", "Right Stick Right", AnalogController::HalfAxis::RRight, GenericInputBinding::RightStickRight),
|
||||||
|
AXIS("RDown", "Right Stick Down", AnalogController::HalfAxis::RDown, GenericInputBinding::RightStickDown),
|
||||||
|
AXIS("RUp", "Right Stick Up", AnalogController::HalfAxis::RUp, GenericInputBinding::RightStickUp),
|
||||||
|
|
||||||
#undef AXIS
|
#undef AXIS
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<s32> AnalogController::StaticGetButtonCodeByName(std::string_view button_name)
|
|
||||||
{
|
|
||||||
#define BUTTON(name) \
|
|
||||||
if (button_name == #name) \
|
|
||||||
{ \
|
|
||||||
return static_cast<s32>(ZeroExtend32(static_cast<u8>(Button::name))); \
|
|
||||||
}
|
|
||||||
|
|
||||||
BUTTON(Select);
|
|
||||||
BUTTON(L3);
|
|
||||||
BUTTON(R3);
|
|
||||||
BUTTON(Start);
|
|
||||||
BUTTON(Up);
|
|
||||||
BUTTON(Right);
|
|
||||||
BUTTON(Down);
|
|
||||||
BUTTON(Left);
|
|
||||||
BUTTON(L2);
|
|
||||||
BUTTON(R2);
|
|
||||||
BUTTON(L1);
|
|
||||||
BUTTON(R1);
|
|
||||||
BUTTON(Triangle);
|
|
||||||
BUTTON(Circle);
|
|
||||||
BUTTON(Cross);
|
|
||||||
BUTTON(Square);
|
|
||||||
BUTTON(Analog);
|
|
||||||
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
#undef BUTTON
|
#undef BUTTON
|
||||||
}
|
};
|
||||||
|
|
||||||
Controller::AxisList AnalogController::StaticGetAxisNames()
|
static const SettingInfo s_settings[] = {
|
||||||
{
|
{SettingInfo::Type::Boolean, "ForceAnalogOnReset", TRANSLATABLE("AnalogController", "Force Analog Mode on Reset"),
|
||||||
return {{TRANSLATABLE("AnalogController", "LeftX"), static_cast<s32>(Axis::LeftX), AxisType::Full},
|
|
||||||
{TRANSLATABLE("AnalogController", "LeftY"), static_cast<s32>(Axis::LeftY), AxisType::Full},
|
|
||||||
{TRANSLATABLE("AnalogController", "RightX"), static_cast<s32>(Axis::RightX), AxisType::Full},
|
|
||||||
{TRANSLATABLE("AnalogController", "RightY"), static_cast<s32>(Axis::RightY), AxisType::Full}};
|
|
||||||
}
|
|
||||||
|
|
||||||
Controller::ButtonList AnalogController::StaticGetButtonNames()
|
|
||||||
{
|
|
||||||
return {{TRANSLATABLE("AnalogController", "Up"), static_cast<s32>(Button::Up)},
|
|
||||||
{TRANSLATABLE("AnalogController", "Down"), static_cast<s32>(Button::Down)},
|
|
||||||
{TRANSLATABLE("AnalogController", "Left"), static_cast<s32>(Button::Left)},
|
|
||||||
{TRANSLATABLE("AnalogController", "Right"), static_cast<s32>(Button::Right)},
|
|
||||||
{TRANSLATABLE("AnalogController", "Select"), static_cast<s32>(Button::Select)},
|
|
||||||
{TRANSLATABLE("AnalogController", "Start"), static_cast<s32>(Button::Start)},
|
|
||||||
{TRANSLATABLE("AnalogController", "Triangle"), static_cast<s32>(Button::Triangle)},
|
|
||||||
{TRANSLATABLE("AnalogController", "Cross"), static_cast<s32>(Button::Cross)},
|
|
||||||
{TRANSLATABLE("AnalogController", "Circle"), static_cast<s32>(Button::Circle)},
|
|
||||||
{TRANSLATABLE("AnalogController", "Square"), static_cast<s32>(Button::Square)},
|
|
||||||
{TRANSLATABLE("AnalogController", "L1"), static_cast<s32>(Button::L1)},
|
|
||||||
{TRANSLATABLE("AnalogController", "L2"), static_cast<s32>(Button::L2)},
|
|
||||||
{TRANSLATABLE("AnalogController", "R1"), static_cast<s32>(Button::R1)},
|
|
||||||
{TRANSLATABLE("AnalogController", "R2"), static_cast<s32>(Button::R2)},
|
|
||||||
{TRANSLATABLE("AnalogController", "L3"), static_cast<s32>(Button::L3)},
|
|
||||||
{TRANSLATABLE("AnalogController", "R3"), static_cast<s32>(Button::R3)},
|
|
||||||
{TRANSLATABLE("AnalogController", "Analog"), static_cast<s32>(Button::Analog)}};
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 AnalogController::StaticGetVibrationMotorCount()
|
|
||||||
{
|
|
||||||
return NUM_MOTORS;
|
|
||||||
}
|
|
||||||
|
|
||||||
Controller::SettingList AnalogController::StaticGetSettings()
|
|
||||||
{
|
|
||||||
static constexpr std::array<SettingInfo, 4> settings = {
|
|
||||||
{{SettingInfo::Type::Boolean, "ForceAnalogOnReset", TRANSLATABLE("AnalogController", "Force Analog Mode on Reset"),
|
|
||||||
TRANSLATABLE("AnalogController", "Forces the controller to analog mode when the console is reset/powered on. May "
|
TRANSLATABLE("AnalogController", "Forces the controller to analog mode when the console is reset/powered on. May "
|
||||||
"cause issues with games, so it is recommended to leave this option off."),
|
"cause issues with games, so it is recommended to leave this option off."),
|
||||||
"false"},
|
"true"},
|
||||||
{SettingInfo::Type::Boolean, "AnalogDPadInDigitalMode",
|
{SettingInfo::Type::Boolean, "AnalogDPadInDigitalMode",
|
||||||
TRANSLATABLE("AnalogController", "Use Analog Sticks for D-Pad in Digital Mode"),
|
TRANSLATABLE("AnalogController", "Use Analog Sticks for D-Pad in Digital Mode"),
|
||||||
TRANSLATABLE("AnalogController",
|
TRANSLATABLE("AnalogController",
|
||||||
"Allows you to use the analog sticks to control the d-pad in digital mode, as well as the buttons."),
|
"Allows you to use the analog sticks to control the d-pad in digital mode, as well as the buttons."),
|
||||||
"false"},
|
"true"},
|
||||||
{SettingInfo::Type::Float, "AxisScale", TRANSLATABLE("AnalogController", "Analog Axis Scale"),
|
{SettingInfo::Type::Float, "AnalogDeadzone", TRANSLATABLE("AnalogController", "Analog Deadzone"),
|
||||||
|
TRANSLATABLE("AnalogController",
|
||||||
|
"Sets the analog stick deadzone, i.e. the fraction of the stick movement which will be ignored."),
|
||||||
|
"0.00f", "0.00f", "1.00f", "0.01f"},
|
||||||
|
{SettingInfo::Type::Float, "AnalogSensitivity", TRANSLATABLE("AnalogController", "Analog Sensitivity"),
|
||||||
TRANSLATABLE(
|
TRANSLATABLE(
|
||||||
"AnalogController",
|
"AnalogController",
|
||||||
"Sets the analog stick axis scaling factor. A value between 1.30 and 1.40 is recommended when using recent "
|
"Sets the analog stick axis scaling factor. A value between 1.30 and 1.40 is recommended when using recent "
|
||||||
"controllers, e.g. DualShock 4, Xbox One Controller."),
|
"controllers, e.g. DualShock 4, Xbox One Controller."),
|
||||||
"1.00f", "0.01f", "1.50f", "0.01f"},
|
"1.33f", "0.01f", "2.00f", "0.01f"},
|
||||||
{SettingInfo::Type::Integer, "VibrationBias", TRANSLATABLE("AnalogController", "Vibration Bias"),
|
{SettingInfo::Type::Integer, "VibrationBias", TRANSLATABLE("AnalogController", "Vibration Bias"),
|
||||||
TRANSLATABLE("AnalogController", "Sets the rumble bias value. If rumble in some games is too weak or not "
|
TRANSLATABLE("AnalogController", "Sets the rumble bias value. If rumble in some games is too weak or not "
|
||||||
"functioning, try increasing this value."),
|
"functioning, try increasing this value."),
|
||||||
"8", "0", "255", "1"}}};
|
"8", "0", "255", "1"}};
|
||||||
|
|
||||||
return SettingList(settings.begin(), settings.end());
|
const Controller::ControllerInfo AnalogController::INFO = {ControllerType::AnalogController,
|
||||||
}
|
"AnalogController",
|
||||||
|
TRANSLATABLE("ControllerType", "Analog Controller"),
|
||||||
|
s_binding_info,
|
||||||
|
countof(s_binding_info),
|
||||||
|
s_settings,
|
||||||
|
countof(s_settings),
|
||||||
|
Controller::VibrationCapabilities::LargeSmallMotors};
|
||||||
|
|
||||||
void AnalogController::LoadSettings(const char* section)
|
void AnalogController::LoadSettings(SettingsInterface& si, const char* section)
|
||||||
{
|
{
|
||||||
Controller::LoadSettings(section);
|
Controller::LoadSettings(si, section);
|
||||||
m_force_analog_on_reset = g_host_interface->GetBoolSettingValue(section, "ForceAnalogOnReset", false);
|
m_force_analog_on_reset = si.GetBoolValue(section, "ForceAnalogOnReset", true);
|
||||||
m_analog_dpad_in_digital_mode = g_host_interface->GetBoolSettingValue(section, "AnalogDPadInDigitalMode", false);
|
m_analog_dpad_in_digital_mode = si.GetBoolValue(section, "AnalogDPadInDigitalMode", true);
|
||||||
m_axis_scale =
|
m_analog_deadzone = std::clamp(si.GetFloatValue(section, "AnalogDeadzone", DEFAULT_STICK_DEADZONE), 0.0f, 1.0f);
|
||||||
std::clamp(std::abs(g_host_interface->GetFloatSettingValue(section, "AxisScale", 1.00f)), 0.01f, 1.50f);
|
m_analog_sensitivity =
|
||||||
m_rumble_bias =
|
std::clamp(si.GetFloatValue(section, "AnalogSensitivity", DEFAULT_STICK_SENSITIVITY), 0.01f, 3.0f);
|
||||||
static_cast<u8>(std::min<u32>(g_host_interface->GetIntSettingValue(section, "VibrationBias", 8), 255));
|
m_rumble_bias = static_cast<u8>(std::min<u32>(si.GetIntValue(section, "VibrationBias", 8), 255));
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,43 +39,42 @@ public:
|
||||||
Count
|
Count
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class HalfAxis : u8
|
||||||
|
{
|
||||||
|
LLeft,
|
||||||
|
LRight,
|
||||||
|
LDown,
|
||||||
|
LUp,
|
||||||
|
RLeft,
|
||||||
|
RRight,
|
||||||
|
RDown,
|
||||||
|
RUp,
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
|
||||||
static constexpr u8 NUM_MOTORS = 2;
|
static constexpr u8 NUM_MOTORS = 2;
|
||||||
|
|
||||||
|
static const Controller::ControllerInfo INFO;
|
||||||
|
|
||||||
AnalogController(u32 index);
|
AnalogController(u32 index);
|
||||||
~AnalogController() override;
|
~AnalogController() override;
|
||||||
|
|
||||||
static std::unique_ptr<AnalogController> Create(u32 index);
|
static std::unique_ptr<AnalogController> Create(u32 index);
|
||||||
static std::optional<s32> StaticGetAxisCodeByName(std::string_view axis_name);
|
|
||||||
static std::optional<s32> StaticGetButtonCodeByName(std::string_view button_name);
|
|
||||||
static AxisList StaticGetAxisNames();
|
|
||||||
static ButtonList StaticGetButtonNames();
|
|
||||||
static u32 StaticGetVibrationMotorCount();
|
|
||||||
static SettingList StaticGetSettings();
|
|
||||||
|
|
||||||
ControllerType GetType() const override;
|
ControllerType GetType() const override;
|
||||||
std::optional<s32> GetAxisCodeByName(std::string_view axis_name) const override;
|
|
||||||
std::optional<s32> GetButtonCodeByName(std::string_view button_name) const override;
|
|
||||||
|
|
||||||
void Reset() override;
|
void Reset() override;
|
||||||
bool DoState(StateWrapper& sw, bool ignore_input_state) override;
|
bool DoState(StateWrapper& sw, bool ignore_input_state) override;
|
||||||
|
|
||||||
float GetAxisState(s32 axis_code) const override;
|
float GetBindState(u32 index) const override;
|
||||||
void SetAxisState(s32 axis_code, float value) override;
|
void SetBindState(u32 index, float value) override;
|
||||||
bool GetButtonState(s32 button_code) const override;
|
|
||||||
void SetButtonState(s32 button_code, bool pressed) override;
|
|
||||||
u32 GetButtonStateBits() const override;
|
u32 GetButtonStateBits() const override;
|
||||||
std::optional<u32> GetAnalogInputBytes() const override;
|
std::optional<u32> GetAnalogInputBytes() const override;
|
||||||
|
|
||||||
void ResetTransferState() override;
|
void ResetTransferState() override;
|
||||||
bool Transfer(const u8 data_in, u8* data_out) override;
|
bool Transfer(const u8 data_in, u8* data_out) override;
|
||||||
|
|
||||||
void SetAxisState(Axis axis, u8 value);
|
void LoadSettings(SettingsInterface& si, const char* section) override;
|
||||||
void SetButtonState(Button button, bool pressed);
|
|
||||||
|
|
||||||
u32 GetVibrationMotorCount() const override;
|
|
||||||
float GetVibrationMotorStrength(u32 motor) override;
|
|
||||||
|
|
||||||
void LoadSettings(const char* section) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using MotorState = std::array<u8, NUM_MOTORS>;
|
using MotorState = std::array<u8, NUM_MOTORS>;
|
||||||
|
@ -111,16 +110,16 @@ private:
|
||||||
|
|
||||||
void SetAnalogMode(bool enabled);
|
void SetAnalogMode(bool enabled);
|
||||||
void ProcessAnalogModeToggle();
|
void ProcessAnalogModeToggle();
|
||||||
void SetMotorState(u8 motor, u8 value);
|
void SetMotorState(u32 motor, u8 value);
|
||||||
|
void UpdateHostVibration();
|
||||||
u8 GetExtraButtonMaskLSB() const;
|
u8 GetExtraButtonMaskLSB() const;
|
||||||
void ResetRumbleConfig();
|
void ResetRumbleConfig();
|
||||||
void SetMotorStateForConfigIndex(int index, u8 value);
|
void SetMotorStateForConfigIndex(int index, u8 value);
|
||||||
|
|
||||||
u32 m_index;
|
|
||||||
|
|
||||||
bool m_force_analog_on_reset = false;
|
bool m_force_analog_on_reset = false;
|
||||||
bool m_analog_dpad_in_digital_mode = false;
|
bool m_analog_dpad_in_digital_mode = false;
|
||||||
float m_axis_scale = 1.00f;
|
float m_analog_deadzone = 0.0f;
|
||||||
|
float m_analog_sensitivity = 1.33f;
|
||||||
u8 m_rumble_bias = 8;
|
u8 m_rumble_bias = 8;
|
||||||
|
|
||||||
bool m_analog_mode = false;
|
bool m_analog_mode = false;
|
||||||
|
@ -151,6 +150,9 @@ private:
|
||||||
|
|
||||||
MotorState m_motor_state{};
|
MotorState m_motor_state{};
|
||||||
|
|
||||||
|
// both directions of axis state, merged to m_axis_state
|
||||||
|
std::array<u8, static_cast<u32>(HalfAxis::Count)> m_half_axis_state{};
|
||||||
|
|
||||||
// Member variables that are no longer used, but kept and serialized for compatibility with older save states
|
// Member variables that are no longer used, but kept and serialized for compatibility with older save states
|
||||||
u8 m_command_param = 0;
|
u8 m_command_param = 0;
|
||||||
bool m_legacy_rumble_unlocked = false;
|
bool m_legacy_rumble_unlocked = false;
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
#include "analog_joystick.h"
|
#include "analog_joystick.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "host_interface.h"
|
#include "host.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "util/state_wrapper.h"
|
#include "util/state_wrapper.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
Log_SetChannel(AnalogJoystick);
|
Log_SetChannel(AnalogJoystick);
|
||||||
|
|
||||||
AnalogJoystick::AnalogJoystick(u32 index)
|
AnalogJoystick::AnalogJoystick(u32 index) : Controller(index)
|
||||||
{
|
{
|
||||||
m_index = index;
|
|
||||||
m_axis_state.fill(0x80);
|
m_axis_state.fill(0x80);
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
@ -50,82 +49,101 @@ bool AnalogJoystick::DoState(StateWrapper& sw, bool apply_input_state)
|
||||||
|
|
||||||
if (sw.IsReading() && (old_analog_mode != m_analog_mode))
|
if (sw.IsReading() && (old_analog_mode != m_analog_mode))
|
||||||
{
|
{
|
||||||
g_host_interface->AddFormattedOSDMessage(
|
Host::AddFormattedOSDMessage(5.0f,
|
||||||
5.0f,
|
m_analog_mode ?
|
||||||
m_analog_mode ? g_host_interface->TranslateString("AnalogJoystick", "Controller %u switched to analog mode.") :
|
Host::TranslateString("AnalogJoystick", "Controller %u switched to analog mode.") :
|
||||||
g_host_interface->TranslateString("AnalogJoystick", "Controller %u switched to digital mode."),
|
Host::TranslateString("AnalogJoystick", "Controller %u switched to digital mode."),
|
||||||
m_index + 1u);
|
m_index + 1u);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<s32> AnalogJoystick::GetAxisCodeByName(std::string_view axis_name) const
|
float AnalogJoystick::GetBindState(u32 index) const
|
||||||
{
|
{
|
||||||
return StaticGetAxisCodeByName(axis_name);
|
if (index >= static_cast<u32>(Button::Count))
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<s32> AnalogJoystick::GetButtonCodeByName(std::string_view button_name) const
|
|
||||||
{
|
{
|
||||||
return StaticGetButtonCodeByName(button_name);
|
const u32 sub_index = index - static_cast<u32>(Button::Count);
|
||||||
}
|
if (sub_index >= static_cast<u32>(m_half_axis_state.size()))
|
||||||
|
|
||||||
float AnalogJoystick::GetAxisState(s32 axis_code) const
|
|
||||||
{
|
|
||||||
if (axis_code < 0 || axis_code >= static_cast<s32>(Axis::Count))
|
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
|
|
||||||
// 0..255 -> -1..1
|
return static_cast<float>(m_half_axis_state[sub_index]) * (1.0f / 255.0f);
|
||||||
const float value = (((static_cast<float>(m_axis_state[static_cast<s32>(axis_code)]) / 255.0f) * 2.0f) - 1.0f);
|
}
|
||||||
return std::clamp(value / m_axis_scale, -1.0f, 1.0f);
|
else if (index < static_cast<u32>(Button::Mode))
|
||||||
|
{
|
||||||
|
return static_cast<float>(((m_button_state >> index) & 1u) ^ 1u);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnalogJoystick::SetAxisState(s32 axis_code, float value)
|
void AnalogJoystick::SetBindState(u32 index, float value)
|
||||||
{
|
{
|
||||||
if (axis_code < 0 || axis_code >= static_cast<s32>(Axis::Count))
|
if (index == static_cast<s32>(Button::Mode))
|
||||||
return;
|
|
||||||
|
|
||||||
// -1..1 -> 0..255
|
|
||||||
const float scaled_value = std::clamp(value * m_axis_scale, -1.0f, 1.0f);
|
|
||||||
const u8 u8_value = static_cast<u8>(std::clamp(std::round(((scaled_value + 1.0f) / 2.0f) * 255.0f), 0.0f, 255.0f));
|
|
||||||
|
|
||||||
SetAxisState(static_cast<Axis>(axis_code), u8_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnalogJoystick::SetAxisState(Axis axis, u8 value)
|
|
||||||
{
|
{
|
||||||
if (m_axis_state[static_cast<u8>(axis)] != value)
|
// analog toggle
|
||||||
System::SetRunaheadReplayFlag();
|
if (value >= 0.5f)
|
||||||
|
|
||||||
m_axis_state[static_cast<u8>(axis)] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AnalogJoystick::GetButtonState(s32 button_code) const
|
|
||||||
{
|
|
||||||
if (button_code < 0 || button_code >= static_cast<s32>(Button::Count))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const u16 bit = u16(1) << static_cast<u8>(button_code);
|
|
||||||
return ((m_button_state & bit) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AnalogJoystick::SetButtonState(Button button, bool pressed)
|
|
||||||
{
|
|
||||||
if (button == Button::Mode)
|
|
||||||
{
|
|
||||||
if (pressed)
|
|
||||||
ToggleAnalogMode();
|
ToggleAnalogMode();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (index >= static_cast<u32>(Button::Count))
|
||||||
|
{
|
||||||
|
const u32 sub_index = index - static_cast<u32>(Button::Count);
|
||||||
|
if (sub_index >= static_cast<u32>(m_half_axis_state.size()))
|
||||||
|
return;
|
||||||
|
|
||||||
const u16 bit = u16(1) << static_cast<u8>(button);
|
value = ApplyAnalogDeadzoneSensitivity(m_analog_deadzone, m_analog_sensitivity, value);
|
||||||
|
const u8 u8_value = static_cast<u8>(std::clamp(value * 255.0f, 0.0f, 255.0f));
|
||||||
|
if (u8_value != m_half_axis_state[sub_index])
|
||||||
|
System::SetRunaheadReplayFlag();
|
||||||
|
|
||||||
if (pressed)
|
m_half_axis_state[sub_index] = u8_value;
|
||||||
|
|
||||||
|
#define MERGE(pos, neg) \
|
||||||
|
((m_half_axis_state[static_cast<u32>(pos)] != 0) ? (127u + ((m_half_axis_state[static_cast<u32>(pos)] + 1u) / 2u)) : \
|
||||||
|
(127u - (m_half_axis_state[static_cast<u32>(neg)] / 2u)))
|
||||||
|
|
||||||
|
switch (static_cast<HalfAxis>(sub_index))
|
||||||
|
{
|
||||||
|
case HalfAxis::LLeft:
|
||||||
|
case HalfAxis::LRight:
|
||||||
|
m_axis_state[static_cast<u8>(Axis::LeftX)] = MERGE(HalfAxis::LRight, HalfAxis::LLeft);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HalfAxis::LDown:
|
||||||
|
case HalfAxis::LUp:
|
||||||
|
m_axis_state[static_cast<u8>(Axis::LeftY)] = MERGE(HalfAxis::LDown, HalfAxis::LUp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HalfAxis::RLeft:
|
||||||
|
case HalfAxis::RRight:
|
||||||
|
m_axis_state[static_cast<u8>(Axis::RightX)] = MERGE(HalfAxis::RRight, HalfAxis::RLeft);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HalfAxis::RDown:
|
||||||
|
case HalfAxis::RUp:
|
||||||
|
m_axis_state[static_cast<u8>(Axis::RightY)] = MERGE(HalfAxis::RDown, HalfAxis::RUp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef MERGE
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u16 bit = u16(1) << static_cast<u8>(index);
|
||||||
|
|
||||||
|
if (value >= 0.5f)
|
||||||
{
|
{
|
||||||
if (m_button_state & bit)
|
if (m_button_state & bit)
|
||||||
System::SetRunaheadReplayFlag();
|
System::SetRunaheadReplayFlag();
|
||||||
|
|
||||||
m_button_state &= ~bit;
|
m_button_state &= ~(bit);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -136,14 +154,6 @@ void AnalogJoystick::SetButtonState(Button button, bool pressed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnalogJoystick::SetButtonState(s32 button_code, bool pressed)
|
|
||||||
{
|
|
||||||
if (button_code < 0 || button_code >= static_cast<s32>(Button::Count))
|
|
||||||
return;
|
|
||||||
|
|
||||||
SetButtonState(static_cast<Button>(button_code), pressed);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 AnalogJoystick::GetButtonStateBits() const
|
u32 AnalogJoystick::GetButtonStateBits() const
|
||||||
{
|
{
|
||||||
return m_button_state ^ 0xFFFF;
|
return m_button_state ^ 0xFFFF;
|
||||||
|
@ -173,10 +183,10 @@ void AnalogJoystick::ToggleAnalogMode()
|
||||||
m_analog_mode = !m_analog_mode;
|
m_analog_mode = !m_analog_mode;
|
||||||
|
|
||||||
Log_InfoPrintf("Joystick %u switched to %s mode.", m_index + 1u, m_analog_mode ? "analog" : "digital");
|
Log_InfoPrintf("Joystick %u switched to %s mode.", m_index + 1u, m_analog_mode ? "analog" : "digital");
|
||||||
g_host_interface->AddFormattedOSDMessage(
|
Host::AddFormattedOSDMessage(5.0f,
|
||||||
5.0f,
|
m_analog_mode ?
|
||||||
m_analog_mode ? g_host_interface->TranslateString("AnalogJoystick", "Controller %u switched to analog mode.") :
|
Host::TranslateString("AnalogJoystick", "Controller %u switched to analog mode.") :
|
||||||
g_host_interface->TranslateString("AnalogJoystick", "Controller %u switched to digital mode."),
|
Host::TranslateString("AnalogJoystick", "Controller %u switched to digital mode."),
|
||||||
m_index + 1u);
|
m_index + 1u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,104 +282,73 @@ std::unique_ptr<AnalogJoystick> AnalogJoystick::Create(u32 index)
|
||||||
return std::make_unique<AnalogJoystick>(index);
|
return std::make_unique<AnalogJoystick>(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<s32> AnalogJoystick::StaticGetAxisCodeByName(std::string_view axis_name)
|
static const Controller::ControllerBindingInfo s_binding_info[] = {
|
||||||
{
|
#define BUTTON(name, display_name, button, genb) \
|
||||||
#define AXIS(name) \
|
|
||||||
if (axis_name == #name) \
|
|
||||||
{ \
|
{ \
|
||||||
return static_cast<s32>(ZeroExtend32(static_cast<u8>(Axis::name))); \
|
name, display_name, static_cast<u32>(button), Controller::ControllerBindingType::Button, genb \
|
||||||
|
}
|
||||||
|
#define AXIS(name, display_name, halfaxis, genb) \
|
||||||
|
{ \
|
||||||
|
name, display_name, static_cast<u32>(AnalogJoystick::Button::Count) + static_cast<u32>(halfaxis), \
|
||||||
|
Controller::ControllerBindingType::HalfAxis, genb \
|
||||||
}
|
}
|
||||||
|
|
||||||
AXIS(LeftX);
|
BUTTON("Up", "D-Pad Up", AnalogJoystick::Button::Up, GenericInputBinding::DPadUp),
|
||||||
AXIS(LeftY);
|
BUTTON("Right", "D-Pad Right", AnalogJoystick::Button::Right, GenericInputBinding::DPadRight),
|
||||||
AXIS(RightX);
|
BUTTON("Down", "D-Pad Down", AnalogJoystick::Button::Down, GenericInputBinding::DPadDown),
|
||||||
AXIS(RightY);
|
BUTTON("Left", "D-Pad Left", AnalogJoystick::Button::Left, GenericInputBinding::DPadLeft),
|
||||||
|
BUTTON("Triangle", "Triangle", AnalogJoystick::Button::Triangle, GenericInputBinding::Triangle),
|
||||||
|
BUTTON("Circle", "Circle", AnalogJoystick::Button::Circle, GenericInputBinding::Circle),
|
||||||
|
BUTTON("Cross", "Cross", AnalogJoystick::Button::Cross, GenericInputBinding::Cross),
|
||||||
|
BUTTON("Square", "Square", AnalogJoystick::Button::Square, GenericInputBinding::Square),
|
||||||
|
BUTTON("Select", "Select", AnalogJoystick::Button::Select, GenericInputBinding::Select),
|
||||||
|
BUTTON("Start", "Start", AnalogJoystick::Button::Start, GenericInputBinding::Start),
|
||||||
|
BUTTON("Mode", "Mode Toggle", AnalogJoystick::Button::Mode, GenericInputBinding::System),
|
||||||
|
BUTTON("L1", "L1", AnalogJoystick::Button::L1, GenericInputBinding::L1),
|
||||||
|
BUTTON("R1", "R1", AnalogJoystick::Button::R1, GenericInputBinding::R1),
|
||||||
|
BUTTON("L2", "L2", AnalogJoystick::Button::L2, GenericInputBinding::L2),
|
||||||
|
BUTTON("R2", "R2", AnalogJoystick::Button::R2, GenericInputBinding::R2),
|
||||||
|
BUTTON("L3", "L3", AnalogJoystick::Button::L3, GenericInputBinding::L3),
|
||||||
|
BUTTON("R3", "R3", AnalogJoystick::Button::R3, GenericInputBinding::R3),
|
||||||
|
|
||||||
return std::nullopt;
|
AXIS("LLeft", "Left Stick Left", AnalogJoystick::HalfAxis::LLeft, GenericInputBinding::LeftStickLeft),
|
||||||
|
AXIS("LRight", "Left Stick Right", AnalogJoystick::HalfAxis::LRight, GenericInputBinding::LeftStickRight),
|
||||||
|
AXIS("LDown", "Left Stick Down", AnalogJoystick::HalfAxis::LDown, GenericInputBinding::LeftStickDown),
|
||||||
|
AXIS("LUp", "Left Stick Up", AnalogJoystick::HalfAxis::LUp, GenericInputBinding::LeftStickUp),
|
||||||
|
AXIS("RLeft", "Right Stick Left", AnalogJoystick::HalfAxis::RLeft, GenericInputBinding::RightStickLeft),
|
||||||
|
AXIS("RRight", "Right Stick Right", AnalogJoystick::HalfAxis::RRight, GenericInputBinding::RightStickRight),
|
||||||
|
AXIS("RDown", "Right Stick Down", AnalogJoystick::HalfAxis::RDown, GenericInputBinding::RightStickDown),
|
||||||
|
AXIS("RUp", "Right Stick Up", AnalogJoystick::HalfAxis::RUp, GenericInputBinding::RightStickUp),
|
||||||
|
|
||||||
#undef AXIS
|
#undef AXIS
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<s32> AnalogJoystick::StaticGetButtonCodeByName(std::string_view button_name)
|
|
||||||
{
|
|
||||||
#define BUTTON(name) \
|
|
||||||
if (button_name == #name) \
|
|
||||||
{ \
|
|
||||||
return static_cast<s32>(ZeroExtend32(static_cast<u8>(Button::name))); \
|
|
||||||
}
|
|
||||||
|
|
||||||
BUTTON(Select);
|
|
||||||
BUTTON(L3);
|
|
||||||
BUTTON(R3);
|
|
||||||
BUTTON(Start);
|
|
||||||
BUTTON(Up);
|
|
||||||
BUTTON(Right);
|
|
||||||
BUTTON(Down);
|
|
||||||
BUTTON(Left);
|
|
||||||
BUTTON(L2);
|
|
||||||
BUTTON(R2);
|
|
||||||
BUTTON(L1);
|
|
||||||
BUTTON(R1);
|
|
||||||
BUTTON(Triangle);
|
|
||||||
BUTTON(Circle);
|
|
||||||
BUTTON(Cross);
|
|
||||||
BUTTON(Square);
|
|
||||||
BUTTON(Mode);
|
|
||||||
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
#undef BUTTON
|
#undef BUTTON
|
||||||
}
|
};
|
||||||
|
|
||||||
Controller::AxisList AnalogJoystick::StaticGetAxisNames()
|
static const SettingInfo s_settings[] = {
|
||||||
{
|
{SettingInfo::Type::Float, "AnalogDeadzone", TRANSLATABLE("AnalogController", "Analog Deadzone"),
|
||||||
return {{TRANSLATABLE("AnalogJoystick", "LeftX"), static_cast<s32>(Axis::LeftX), AxisType::Full},
|
TRANSLATABLE("AnalogController",
|
||||||
{TRANSLATABLE("AnalogJoystick", "LeftY"), static_cast<s32>(Axis::LeftY), AxisType::Full},
|
"Sets the analog stick deadzone, i.e. the fraction of the stick movement which will be ignored.s"),
|
||||||
{TRANSLATABLE("AnalogJoystick", "RightX"), static_cast<s32>(Axis::RightX), AxisType::Full},
|
"1.00f", "0.00f", "1.00f", "0.01f"},
|
||||||
{TRANSLATABLE("AnalogJoystick", "RightY"), static_cast<s32>(Axis::RightY), AxisType::Full}};
|
{SettingInfo::Type::Float, "AnalogSensitivity", TRANSLATABLE("AnalogController", "Analog Sensitivity"),
|
||||||
}
|
|
||||||
|
|
||||||
Controller::ButtonList AnalogJoystick::StaticGetButtonNames()
|
|
||||||
{
|
|
||||||
return {{TRANSLATABLE("AnalogJoystick", "Up"), static_cast<s32>(Button::Up)},
|
|
||||||
{TRANSLATABLE("AnalogJoystick", "Down"), static_cast<s32>(Button::Down)},
|
|
||||||
{TRANSLATABLE("AnalogJoystick", "Left"), static_cast<s32>(Button::Left)},
|
|
||||||
{TRANSLATABLE("AnalogJoystick", "Right"), static_cast<s32>(Button::Right)},
|
|
||||||
{TRANSLATABLE("AnalogJoystick", "Select"), static_cast<s32>(Button::Select)},
|
|
||||||
{TRANSLATABLE("AnalogJoystick", "Start"), static_cast<s32>(Button::Start)},
|
|
||||||
{TRANSLATABLE("AnalogJoystick", "Triangle"), static_cast<s32>(Button::Triangle)},
|
|
||||||
{TRANSLATABLE("AnalogJoystick", "Cross"), static_cast<s32>(Button::Cross)},
|
|
||||||
{TRANSLATABLE("AnalogJoystick", "Circle"), static_cast<s32>(Button::Circle)},
|
|
||||||
{TRANSLATABLE("AnalogJoystick", "Square"), static_cast<s32>(Button::Square)},
|
|
||||||
{TRANSLATABLE("AnalogJoystick", "L1"), static_cast<s32>(Button::L1)},
|
|
||||||
{TRANSLATABLE("AnalogJoystick", "L2"), static_cast<s32>(Button::L2)},
|
|
||||||
{TRANSLATABLE("AnalogJoystick", "R1"), static_cast<s32>(Button::R1)},
|
|
||||||
{TRANSLATABLE("AnalogJoystick", "R2"), static_cast<s32>(Button::R2)},
|
|
||||||
{TRANSLATABLE("AnalogJoystick", "L3"), static_cast<s32>(Button::L3)},
|
|
||||||
{TRANSLATABLE("AnalogJoystick", "R3"), static_cast<s32>(Button::R3)},
|
|
||||||
{TRANSLATABLE("AnalogJoystick", "Analog"), static_cast<s32>(Button::Mode)}};
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 AnalogJoystick::StaticGetVibrationMotorCount()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Controller::SettingList AnalogJoystick::StaticGetSettings()
|
|
||||||
{
|
|
||||||
static constexpr std::array<SettingInfo, 1> settings = {
|
|
||||||
{{SettingInfo::Type::Float, "AxisScale", TRANSLATABLE("AnalogJoystick", "Analog Axis Scale"),
|
|
||||||
TRANSLATABLE(
|
TRANSLATABLE(
|
||||||
"AnalogJoystick",
|
"AnalogController",
|
||||||
"Sets the analog stick axis scaling factor. A value between 1.30 and 1.40 is recommended when using recent "
|
"Sets the analog stick axis scaling factor. A value between 1.30 and 1.40 is recommended when using recent "
|
||||||
"controllers, e.g. DualShock 4, Xbox One Controller."),
|
"controllers, e.g. DualShock 4, Xbox One Controller."),
|
||||||
"1.00f", "0.01f", "1.50f", "0.01f"}}};
|
"1.33f", "0.01f", "2.00f", "0.01f"}};
|
||||||
|
|
||||||
return SettingList(settings.begin(), settings.end());
|
const Controller::ControllerInfo AnalogJoystick::INFO = {ControllerType::AnalogJoystick,
|
||||||
}
|
"AnalogJoystick",
|
||||||
|
TRANSLATABLE("ControllerType", "Analog Joystick"),
|
||||||
|
s_binding_info,
|
||||||
|
countof(s_binding_info),
|
||||||
|
s_settings,
|
||||||
|
countof(s_settings),
|
||||||
|
Controller::VibrationCapabilities::NoVibration};
|
||||||
|
|
||||||
void AnalogJoystick::LoadSettings(const char* section)
|
void AnalogJoystick::LoadSettings(SettingsInterface& si, const char* section)
|
||||||
{
|
{
|
||||||
Controller::LoadSettings(section);
|
Controller::LoadSettings(si, section);
|
||||||
m_axis_scale = std::clamp(g_host_interface->GetFloatSettingValue(section, "AxisScale", 1.00f), 0.01f, 1.50f);
|
m_analog_deadzone = std::clamp(si.GetFloatValue(section, "AnalogDeadzone", DEFAULT_STICK_DEADZONE), 0.0f, 1.0f);
|
||||||
|
m_analog_sensitivity =
|
||||||
|
std::clamp(si.GetFloatValue(section, "AnalogSensitivity", DEFAULT_STICK_SENSITIVITY), 0.01f, 3.0f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,38 +39,40 @@ public:
|
||||||
Count
|
Count
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class HalfAxis : u8
|
||||||
|
{
|
||||||
|
LLeft,
|
||||||
|
LRight,
|
||||||
|
LDown,
|
||||||
|
LUp,
|
||||||
|
RLeft,
|
||||||
|
RRight,
|
||||||
|
RDown,
|
||||||
|
RUp,
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
|
||||||
|
static const Controller::ControllerInfo INFO;
|
||||||
|
|
||||||
AnalogJoystick(u32 index);
|
AnalogJoystick(u32 index);
|
||||||
~AnalogJoystick() override;
|
~AnalogJoystick() override;
|
||||||
|
|
||||||
static std::unique_ptr<AnalogJoystick> Create(u32 index);
|
static std::unique_ptr<AnalogJoystick> Create(u32 index);
|
||||||
static std::optional<s32> StaticGetAxisCodeByName(std::string_view axis_name);
|
|
||||||
static std::optional<s32> StaticGetButtonCodeByName(std::string_view button_name);
|
|
||||||
static AxisList StaticGetAxisNames();
|
|
||||||
static ButtonList StaticGetButtonNames();
|
|
||||||
static u32 StaticGetVibrationMotorCount();
|
|
||||||
static SettingList StaticGetSettings();
|
|
||||||
|
|
||||||
ControllerType GetType() const override;
|
ControllerType GetType() const override;
|
||||||
std::optional<s32> GetAxisCodeByName(std::string_view axis_name) const override;
|
|
||||||
std::optional<s32> GetButtonCodeByName(std::string_view button_name) const override;
|
|
||||||
|
|
||||||
void Reset() override;
|
void Reset() override;
|
||||||
bool DoState(StateWrapper& sw, bool apply_input_state) override;
|
bool DoState(StateWrapper& sw, bool apply_input_state) override;
|
||||||
|
|
||||||
float GetAxisState(s32 axis_code) const override;
|
float GetBindState(u32 index) const override;
|
||||||
void SetAxisState(s32 axis_code, float value) override;
|
void SetBindState(u32 index, float value) override;
|
||||||
bool GetButtonState(s32 button_code) const override;
|
|
||||||
void SetButtonState(s32 button_code, bool pressed) override;
|
|
||||||
u32 GetButtonStateBits() const override;
|
u32 GetButtonStateBits() const override;
|
||||||
std::optional<u32> GetAnalogInputBytes() const override;
|
std::optional<u32> GetAnalogInputBytes() const override;
|
||||||
|
|
||||||
void ResetTransferState() override;
|
void ResetTransferState() override;
|
||||||
bool Transfer(const u8 data_in, u8* data_out) override;
|
bool Transfer(const u8 data_in, u8* data_out) override;
|
||||||
|
|
||||||
void LoadSettings(const char* section) override;
|
void LoadSettings(SettingsInterface& si, const char* section) override;
|
||||||
|
|
||||||
void SetAxisState(Axis axis, u8 value);
|
|
||||||
void SetButtonState(Button button, bool pressed);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class TransferState : u8
|
enum class TransferState : u8
|
||||||
|
@ -89,9 +91,8 @@ private:
|
||||||
u16 GetID() const;
|
u16 GetID() const;
|
||||||
void ToggleAnalogMode();
|
void ToggleAnalogMode();
|
||||||
|
|
||||||
u32 m_index;
|
float m_analog_deadzone = 0.0f;
|
||||||
|
float m_analog_sensitivity = 1.33f;
|
||||||
float m_axis_scale = 1.00f;
|
|
||||||
|
|
||||||
// On original hardware, the mode toggle is a switch rather than a button, so we'll enable Analog Mode by default
|
// On original hardware, the mode toggle is a switch rather than a button, so we'll enable Analog Mode by default
|
||||||
bool m_analog_mode = true;
|
bool m_analog_mode = true;
|
||||||
|
@ -101,5 +102,8 @@ private:
|
||||||
|
|
||||||
std::array<u8, static_cast<u8>(Axis::Count)> m_axis_state{};
|
std::array<u8, static_cast<u8>(Axis::Count)> m_axis_state{};
|
||||||
|
|
||||||
|
// both directions of axis state, merged to m_axis_state
|
||||||
|
std::array<u8, static_cast<u32>(HalfAxis::Count)> m_half_axis_state{};
|
||||||
|
|
||||||
TransferState m_transfer_state = TransferState::Idle;
|
TransferState m_transfer_state = TransferState::Idle;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,11 @@
|
||||||
#include "common/file_system.h"
|
#include "common/file_system.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/md5_digest.h"
|
#include "common/md5_digest.h"
|
||||||
|
#include "common/path.h"
|
||||||
#include "cpu_disasm.h"
|
#include "cpu_disasm.h"
|
||||||
|
#include "host.h"
|
||||||
|
#include "host_settings.h"
|
||||||
|
#include "settings.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
Log_SetChannel(BIOS);
|
Log_SetChannel(BIOS);
|
||||||
|
@ -272,3 +276,143 @@ DiscRegion GetPSExeDiscRegion(const PSEXEHeader& header)
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace BIOS
|
} // namespace BIOS
|
||||||
|
|
||||||
|
std::optional<std::vector<u8>> BIOS::GetBIOSImage(ConsoleRegion region)
|
||||||
|
{
|
||||||
|
std::string bios_name;
|
||||||
|
switch (region)
|
||||||
|
{
|
||||||
|
case ConsoleRegion::NTSC_J:
|
||||||
|
bios_name = Host::GetStringSettingValue("BIOS", "PathNTSCJ", "");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ConsoleRegion::PAL:
|
||||||
|
bios_name = Host::GetStringSettingValue("BIOS", "PathPAL", "");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ConsoleRegion::NTSC_U:
|
||||||
|
default:
|
||||||
|
bios_name = Host::GetStringSettingValue("BIOS", "PathNTSCU", "");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bios_name.empty())
|
||||||
|
{
|
||||||
|
// auto-detect
|
||||||
|
return FindBIOSImageInDirectory(region, EmuFolders::Bios.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// try the configured path
|
||||||
|
std::optional<Image> image = LoadImageFromFile(Path::Combine(EmuFolders::Bios, bios_name).c_str());
|
||||||
|
if (!image.has_value())
|
||||||
|
{
|
||||||
|
Host::ReportFormattedErrorAsync(
|
||||||
|
"Error", Host::TranslateString("HostInterface", "Failed to load configured BIOS file '%s'"), bios_name.c_str());
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
Hash found_hash = GetHash(*image);
|
||||||
|
Log_DevPrintf("Hash for BIOS '%s': %s", bios_name.c_str(), found_hash.ToString().c_str());
|
||||||
|
|
||||||
|
if (!IsValidHashForRegion(region, found_hash))
|
||||||
|
Log_WarningPrintf("Hash for BIOS '%s' does not match region. This may cause issues.", bios_name.c_str());
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::vector<u8>> BIOS::FindBIOSImageInDirectory(ConsoleRegion region, const char* directory)
|
||||||
|
{
|
||||||
|
Log_InfoPrintf("Searching for a %s BIOS in '%s'...", Settings::GetConsoleRegionDisplayName(region), directory);
|
||||||
|
|
||||||
|
FileSystem::FindResultsArray results;
|
||||||
|
FileSystem::FindFiles(
|
||||||
|
directory, "*", FILESYSTEM_FIND_FILES | FILESYSTEM_FIND_HIDDEN_FILES | FILESYSTEM_FIND_RELATIVE_PATHS, &results);
|
||||||
|
|
||||||
|
std::string fallback_path;
|
||||||
|
std::optional<Image> fallback_image;
|
||||||
|
const ImageInfo* fallback_info = nullptr;
|
||||||
|
|
||||||
|
for (const FILESYSTEM_FIND_DATA& fd : results)
|
||||||
|
{
|
||||||
|
if (fd.Size != BIOS_SIZE && fd.Size != BIOS_SIZE_PS2 && fd.Size != BIOS_SIZE_PS3)
|
||||||
|
{
|
||||||
|
Log_WarningPrintf("Skipping '%s': incorrect size", fd.FileName.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string full_path(Path::Combine(directory, fd.FileName));
|
||||||
|
std::optional<Image> found_image = LoadImageFromFile(full_path.c_str());
|
||||||
|
if (!found_image)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Hash found_hash = GetHash(*found_image);
|
||||||
|
Log_DevPrintf("Hash for BIOS '%s': %s", fd.FileName.c_str(), found_hash.ToString().c_str());
|
||||||
|
|
||||||
|
const ImageInfo* ii = GetImageInfoForHash(found_hash);
|
||||||
|
|
||||||
|
if (IsValidHashForRegion(region, found_hash))
|
||||||
|
{
|
||||||
|
Log_InfoPrintf("Using BIOS '%s': %s", fd.FileName.c_str(), ii ? ii->description : "");
|
||||||
|
return found_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't let an unknown bios take precedence over a known one
|
||||||
|
if (!fallback_path.empty() && (fallback_info || !ii))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
fallback_path = std::move(full_path);
|
||||||
|
fallback_image = std::move(found_image);
|
||||||
|
fallback_info = ii;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fallback_image.has_value())
|
||||||
|
{
|
||||||
|
Host::ReportFormattedErrorAsync("Error",
|
||||||
|
Host::TranslateString("HostInterface", "No BIOS image found for %s region"),
|
||||||
|
Settings::GetConsoleRegionDisplayName(region));
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fallback_info)
|
||||||
|
{
|
||||||
|
Log_WarningPrintf("Using unknown BIOS '%s'. This may crash.", fallback_path.c_str());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log_WarningPrintf("Falling back to possibly-incompatible image '%s': %s", fallback_path.c_str(),
|
||||||
|
fallback_info->description);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fallback_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, const BIOS::ImageInfo*>> BIOS::FindBIOSImagesInDirectory(const char* directory)
|
||||||
|
{
|
||||||
|
std::vector<std::pair<std::string, const ImageInfo*>> results;
|
||||||
|
|
||||||
|
FileSystem::FindResultsArray files;
|
||||||
|
FileSystem::FindFiles(directory, "*",
|
||||||
|
FILESYSTEM_FIND_FILES | FILESYSTEM_FIND_HIDDEN_FILES | FILESYSTEM_FIND_RELATIVE_PATHS, &files);
|
||||||
|
|
||||||
|
for (FILESYSTEM_FIND_DATA& fd : files)
|
||||||
|
{
|
||||||
|
if (fd.Size != BIOS_SIZE && fd.Size != BIOS_SIZE_PS2 && fd.Size != BIOS_SIZE_PS3)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::string full_path(Path::Combine(directory, fd.FileName));
|
||||||
|
std::optional<Image> found_image = LoadImageFromFile(full_path.c_str());
|
||||||
|
if (!found_image)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Hash found_hash = GetHash(*found_image);
|
||||||
|
const ImageInfo* ii = GetImageInfoForHash(found_hash);
|
||||||
|
results.emplace_back(std::move(fd.FileName), ii);
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BIOS::HasAnyBIOSImages()
|
||||||
|
{
|
||||||
|
return FindBIOSImageInDirectory(ConsoleRegion::Auto, EmuFolders::Bios.c_str()).has_value();
|
||||||
|
}
|
||||||
|
|
|
@ -70,4 +70,17 @@ bool PatchBIOSForEXE(u8* image, u32 image_size, u32 r_pc, u32 r_gp, u32 r_sp, u3
|
||||||
|
|
||||||
bool IsValidPSExeHeader(const PSEXEHeader& header, u32 file_size);
|
bool IsValidPSExeHeader(const PSEXEHeader& header, u32 file_size);
|
||||||
DiscRegion GetPSExeDiscRegion(const PSEXEHeader& header);
|
DiscRegion GetPSExeDiscRegion(const PSEXEHeader& header);
|
||||||
|
|
||||||
|
/// Loads the BIOS image for the specified region.
|
||||||
|
std::optional<std::vector<u8>> GetBIOSImage(ConsoleRegion region);
|
||||||
|
|
||||||
|
/// Searches for a BIOS image for the specified region in the specified directory. If no match is found, the first
|
||||||
|
/// BIOS image within 512KB and 4MB will be used.
|
||||||
|
std::optional<std::vector<u8>> FindBIOSImageInDirectory(ConsoleRegion region, const char* directory);
|
||||||
|
|
||||||
|
/// Returns a list of filenames and descriptions for BIOS images in a directory.
|
||||||
|
std::vector<std::pair<std::string, const BIOS::ImageInfo*>> FindBIOSImagesInDirectory(const char* directory);
|
||||||
|
|
||||||
|
/// Returns true if any BIOS images are found in the configured BIOS directory.
|
||||||
|
bool HasAnyBIOSImages();
|
||||||
} // namespace BIOS
|
} // namespace BIOS
|
|
@ -10,7 +10,7 @@
|
||||||
#include "cpu_disasm.h"
|
#include "cpu_disasm.h"
|
||||||
#include "dma.h"
|
#include "dma.h"
|
||||||
#include "gpu.h"
|
#include "gpu.h"
|
||||||
#include "host_interface.h"
|
#include "host.h"
|
||||||
#include "interrupt_controller.h"
|
#include "interrupt_controller.h"
|
||||||
#include "mdec.h"
|
#include "mdec.h"
|
||||||
#include "pad.h"
|
#include "pad.h"
|
||||||
|
@ -130,7 +130,7 @@ bool Initialize()
|
||||||
{
|
{
|
||||||
if (!AllocateMemory(g_settings.enable_8mb_ram))
|
if (!AllocateMemory(g_settings.enable_8mb_ram))
|
||||||
{
|
{
|
||||||
g_host_interface->ReportError("Failed to allocate memory");
|
Host::ReportErrorAsync("Error", "Failed to allocate memory");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/platform.h"
|
#include "common/platform.h"
|
||||||
#include "dma.h"
|
#include "dma.h"
|
||||||
|
#include "host.h"
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "interrupt_controller.h"
|
#include "interrupt_controller.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
@ -2722,7 +2723,7 @@ void CDROM::DrawDebugWindow()
|
||||||
{
|
{
|
||||||
static const ImVec4 active_color{1.0f, 1.0f, 1.0f, 1.0f};
|
static const ImVec4 active_color{1.0f, 1.0f, 1.0f, 1.0f};
|
||||||
static const ImVec4 inactive_color{0.4f, 0.4f, 0.4f, 1.0f};
|
static const ImVec4 inactive_color{0.4f, 0.4f, 0.4f, 1.0f};
|
||||||
const float framebuffer_scale = ImGui::GetIO().DisplayFramebufferScale.x;
|
const float framebuffer_scale = Host::GetOSDScale();
|
||||||
|
|
||||||
ImGui::SetNextWindowSize(ImVec2(800.0f * framebuffer_scale, 550.0f * framebuffer_scale), ImGuiCond_FirstUseEver);
|
ImGui::SetNextWindowSize(ImVec2(800.0f * framebuffer_scale, 550.0f * framebuffer_scale), ImGuiCond_FirstUseEver);
|
||||||
if (!ImGui::Begin("CDROM State", nullptr))
|
if (!ImGui::Begin("CDROM State", nullptr))
|
||||||
|
|
|
@ -29,6 +29,7 @@ public:
|
||||||
bool HasMedia() const { return m_reader.HasMedia(); }
|
bool HasMedia() const { return m_reader.HasMedia(); }
|
||||||
const std::string& GetMediaFileName() const { return m_reader.GetMediaFileName(); }
|
const std::string& GetMediaFileName() const { return m_reader.GetMediaFileName(); }
|
||||||
const CDImage* GetMedia() const { return m_reader.GetMedia(); }
|
const CDImage* GetMedia() const { return m_reader.GetMedia(); }
|
||||||
|
DiscRegion GetDiscRegion() const { return m_disc_region; }
|
||||||
bool IsMediaPS1Disc() const;
|
bool IsMediaPS1Disc() const;
|
||||||
bool DoesMediaRegionMatchConsole() const;
|
bool DoesMediaRegionMatchConsole() const;
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
#include "cpu_code_cache.h"
|
#include "cpu_code_cache.h"
|
||||||
#include "cpu_core.h"
|
#include "cpu_core.h"
|
||||||
#include "host_interface.h"
|
#include "host.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
@ -686,17 +686,11 @@ bool CheatList::SaveToPCSXRFile(const char* filename)
|
||||||
|
|
||||||
bool CheatList::LoadFromPackage(const std::string& game_code)
|
bool CheatList::LoadFromPackage(const std::string& game_code)
|
||||||
{
|
{
|
||||||
std::unique_ptr<ByteStream> stream =
|
const std::optional<std::string> db_string(Host::ReadResourceFileToString("chtdb.txt"));
|
||||||
g_host_interface->OpenPackageFile("database/chtdb.txt", BYTESTREAM_OPEN_READ | BYTESTREAM_OPEN_STREAMED);
|
if (!db_string.has_value())
|
||||||
if (!stream)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::string db_string = ByteStream::ReadStreamToString(stream.get());
|
std::istringstream iss(db_string.value());
|
||||||
stream.reset();
|
|
||||||
if (db_string.empty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
std::istringstream iss(db_string);
|
|
||||||
std::string line;
|
std::string line;
|
||||||
while (std::getline(iss, line))
|
while (std::getline(iss, line))
|
||||||
{
|
{
|
||||||
|
|
1802
src/core/cheevos.cpp
|
@ -2,12 +2,27 @@
|
||||||
#include "analog_controller.h"
|
#include "analog_controller.h"
|
||||||
#include "analog_joystick.h"
|
#include "analog_joystick.h"
|
||||||
#include "digital_controller.h"
|
#include "digital_controller.h"
|
||||||
#include "namco_guncon.h"
|
#include "fmt/format.h"
|
||||||
|
#include "guncon.h"
|
||||||
#include "negcon.h"
|
#include "negcon.h"
|
||||||
#include "playstation_mouse.h"
|
#include "playstation_mouse.h"
|
||||||
#include "util/state_wrapper.h"
|
#include "util/state_wrapper.h"
|
||||||
|
|
||||||
Controller::Controller() = default;
|
static const Controller::ControllerInfo s_none_info = {ControllerType::None,
|
||||||
|
"None",
|
||||||
|
"Not Connected",
|
||||||
|
nullptr,
|
||||||
|
0,
|
||||||
|
nullptr,
|
||||||
|
0,
|
||||||
|
Controller::VibrationCapabilities::NoVibration};
|
||||||
|
|
||||||
|
static const Controller::ControllerInfo* s_controller_info[] = {
|
||||||
|
&s_none_info, &DigitalController::INFO, &AnalogController::INFO, &AnalogJoystick::INFO, &NeGcon::INFO,
|
||||||
|
&GunCon::INFO, &PlayStationMouse::INFO,
|
||||||
|
};
|
||||||
|
|
||||||
|
Controller::Controller(u32 index) : m_index(index) {}
|
||||||
|
|
||||||
Controller::~Controller() = default;
|
Controller::~Controller() = default;
|
||||||
|
|
||||||
|
@ -26,19 +41,12 @@ bool Controller::Transfer(const u8 data_in, u8* data_out)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Controller::GetAxisState(s32 axis_code) const
|
float Controller::GetBindState(u32 index) const
|
||||||
{
|
{
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::SetAxisState(s32 axis_code, float value) {}
|
void Controller::SetBindState(u32 index, float value) {}
|
||||||
|
|
||||||
bool Controller::GetButtonState(s32 button_code) const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Controller::SetButtonState(s32 button_code, bool pressed) {}
|
|
||||||
|
|
||||||
u32 Controller::GetButtonStateBits() const
|
u32 Controller::GetButtonStateBits() const
|
||||||
{
|
{
|
||||||
|
@ -50,17 +58,7 @@ std::optional<u32> Controller::GetAnalogInputBytes() const
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Controller::GetVibrationMotorCount() const
|
void Controller::LoadSettings(SettingsInterface& si, const char* section) {}
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
float Controller::GetVibrationMotorStrength(u32 motor)
|
|
||||||
{
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Controller::LoadSettings(const char* section) {}
|
|
||||||
|
|
||||||
bool Controller::GetSoftwareCursor(const Common::RGBA8Image** image, float* image_scale, bool* relative_mode)
|
bool Controller::GetSoftwareCursor(const Common::RGBA8Image** image, float* image_scale, bool* relative_mode)
|
||||||
{
|
{
|
||||||
|
@ -72,7 +70,7 @@ std::unique_ptr<Controller> Controller::Create(ControllerType type, u32 index)
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case ControllerType::DigitalController:
|
case ControllerType::DigitalController:
|
||||||
return DigitalController::Create();
|
return DigitalController::Create(index);
|
||||||
|
|
||||||
case ControllerType::AnalogController:
|
case ControllerType::AnalogController:
|
||||||
return AnalogController::Create(index);
|
return AnalogController::Create(index);
|
||||||
|
@ -80,14 +78,14 @@ std::unique_ptr<Controller> Controller::Create(ControllerType type, u32 index)
|
||||||
case ControllerType::AnalogJoystick:
|
case ControllerType::AnalogJoystick:
|
||||||
return AnalogJoystick::Create(index);
|
return AnalogJoystick::Create(index);
|
||||||
|
|
||||||
case ControllerType::NamcoGunCon:
|
case ControllerType::GunCon:
|
||||||
return NamcoGunCon::Create();
|
return GunCon::Create(index);
|
||||||
|
|
||||||
case ControllerType::PlayStationMouse:
|
case ControllerType::PlayStationMouse:
|
||||||
return PlayStationMouse::Create();
|
return PlayStationMouse::Create(index);
|
||||||
|
|
||||||
case ControllerType::NeGcon:
|
case ControllerType::NeGcon:
|
||||||
return NeGcon::Create();
|
return NeGcon::Create(index);
|
||||||
|
|
||||||
case ControllerType::None:
|
case ControllerType::None:
|
||||||
default:
|
default:
|
||||||
|
@ -95,179 +93,134 @@ std::unique_ptr<Controller> Controller::Create(ControllerType type, u32 index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<s32> Controller::GetAxisCodeByName(std::string_view button_name) const
|
const char* Controller::GetDefaultPadType(u32 pad)
|
||||||
{
|
{
|
||||||
|
return (pad == 0) ? "DigitalController" : "None";
|
||||||
|
}
|
||||||
|
|
||||||
|
const Controller::ControllerInfo* Controller::GetControllerInfo(ControllerType type)
|
||||||
|
{
|
||||||
|
for (const ControllerInfo* info : s_controller_info)
|
||||||
|
{
|
||||||
|
if (type == info->type)
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Controller::ControllerInfo* Controller::GetControllerInfo(const std::string_view& name)
|
||||||
|
{
|
||||||
|
for (const ControllerInfo* info : s_controller_info)
|
||||||
|
{
|
||||||
|
if (name == info->name)
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, std::string>> Controller::GetControllerTypeNames()
|
||||||
|
{
|
||||||
|
std::vector<std::pair<std::string, std::string>> ret;
|
||||||
|
for (const ControllerInfo* info : s_controller_info)
|
||||||
|
ret.emplace_back(info->name, info->display_name);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> Controller::GetControllerBinds(const std::string_view& type)
|
||||||
|
{
|
||||||
|
std::vector<std::string> ret;
|
||||||
|
|
||||||
|
const ControllerInfo* info = GetControllerInfo(type);
|
||||||
|
if (info)
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < info->num_bindings; i++)
|
||||||
|
{
|
||||||
|
const ControllerBindingInfo& bi = info->bindings[i];
|
||||||
|
if (bi.type == ControllerBindingType::Unknown || bi.type == ControllerBindingType::Motor)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret.emplace_back(info->bindings[i].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> Controller::GetControllerBinds(ControllerType type)
|
||||||
|
{
|
||||||
|
std::vector<std::string> ret;
|
||||||
|
|
||||||
|
const ControllerInfo* info = GetControllerInfo(type);
|
||||||
|
if (info)
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < info->num_bindings; i++)
|
||||||
|
{
|
||||||
|
const ControllerBindingInfo& bi = info->bindings[i];
|
||||||
|
if (bi.type == ControllerBindingType::Unknown || bi.type == ControllerBindingType::Motor)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret.emplace_back(info->bindings[i].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<u32> Controller::GetBindIndex(ControllerType type, const std::string_view& bind_name)
|
||||||
|
{
|
||||||
|
const ControllerInfo* info = GetControllerInfo(type);
|
||||||
|
if (!info)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
for (u32 i = 0; i < info->num_bindings; i++)
|
||||||
|
{
|
||||||
|
if (bind_name == info->bindings[i].name)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<s32> Controller::GetButtonCodeByName(std::string_view button_name) const
|
Controller::VibrationCapabilities Controller::GetControllerVibrationCapabilities(const std::string_view& type)
|
||||||
{
|
{
|
||||||
return std::nullopt;
|
const ControllerInfo* info = GetControllerInfo(type);
|
||||||
|
return info ? info->vibration_caps : VibrationCapabilities::NoVibration;
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller::AxisList Controller::GetAxisNames(ControllerType type)
|
std::tuple<u32, u32> Controller::ConvertPadToPortAndSlot(u32 index)
|
||||||
{
|
{
|
||||||
switch (type)
|
if (index > 4) // [5,6,7]
|
||||||
{
|
return std::make_tuple(1, index - 4); // 2B,2C,2D
|
||||||
case ControllerType::DigitalController:
|
else if (index > 1) // [2,3,4]
|
||||||
return DigitalController::StaticGetAxisNames();
|
return std::make_tuple(0, index - 1); // 1B,1C,1D
|
||||||
|
else // [0,1]
|
||||||
case ControllerType::AnalogController:
|
return std::make_tuple(index, 0); // 1A,2A
|
||||||
return AnalogController::StaticGetAxisNames();
|
|
||||||
|
|
||||||
case ControllerType::AnalogJoystick:
|
|
||||||
return AnalogJoystick::StaticGetAxisNames();
|
|
||||||
|
|
||||||
case ControllerType::NamcoGunCon:
|
|
||||||
return NamcoGunCon::StaticGetAxisNames();
|
|
||||||
|
|
||||||
case ControllerType::PlayStationMouse:
|
|
||||||
return PlayStationMouse::StaticGetAxisNames();
|
|
||||||
|
|
||||||
case ControllerType::NeGcon:
|
|
||||||
return NeGcon::StaticGetAxisNames();
|
|
||||||
|
|
||||||
case ControllerType::None:
|
|
||||||
default:
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller::ButtonList Controller::GetButtonNames(ControllerType type)
|
u32 Controller::ConvertPortAndSlotToPad(u32 port, u32 slot)
|
||||||
{
|
{
|
||||||
switch (type)
|
if (slot == 0)
|
||||||
{
|
return port;
|
||||||
case ControllerType::DigitalController:
|
else if (port == 0) // slot=[0,1]
|
||||||
return DigitalController::StaticGetButtonNames();
|
return slot + 1; // 2,3,4
|
||||||
|
else
|
||||||
case ControllerType::AnalogController:
|
return slot + 4; // 5,6,7
|
||||||
return AnalogController::StaticGetButtonNames();
|
|
||||||
|
|
||||||
case ControllerType::AnalogJoystick:
|
|
||||||
return AnalogJoystick::StaticGetButtonNames();
|
|
||||||
|
|
||||||
case ControllerType::NamcoGunCon:
|
|
||||||
return NamcoGunCon::StaticGetButtonNames();
|
|
||||||
|
|
||||||
case ControllerType::PlayStationMouse:
|
|
||||||
return PlayStationMouse::StaticGetButtonNames();
|
|
||||||
|
|
||||||
case ControllerType::NeGcon:
|
|
||||||
return NeGcon::StaticGetButtonNames();
|
|
||||||
|
|
||||||
case ControllerType::None:
|
|
||||||
default:
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Controller::GetVibrationMotorCount(ControllerType type)
|
bool Controller::PadIsMultitapSlot(u32 index)
|
||||||
{
|
{
|
||||||
switch (type)
|
return (index >= 2);
|
||||||
{
|
|
||||||
case ControllerType::DigitalController:
|
|
||||||
return DigitalController::StaticGetVibrationMotorCount();
|
|
||||||
|
|
||||||
case ControllerType::AnalogController:
|
|
||||||
return AnalogController::StaticGetVibrationMotorCount();
|
|
||||||
|
|
||||||
case ControllerType::AnalogJoystick:
|
|
||||||
return AnalogJoystick::StaticGetVibrationMotorCount();
|
|
||||||
|
|
||||||
case ControllerType::NamcoGunCon:
|
|
||||||
return NamcoGunCon::StaticGetVibrationMotorCount();
|
|
||||||
|
|
||||||
case ControllerType::PlayStationMouse:
|
|
||||||
return PlayStationMouse::StaticGetVibrationMotorCount();
|
|
||||||
|
|
||||||
case ControllerType::NeGcon:
|
|
||||||
return NeGcon::StaticGetVibrationMotorCount();
|
|
||||||
|
|
||||||
case ControllerType::None:
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<s32> Controller::GetAxisCodeByName(ControllerType type, std::string_view axis_name)
|
bool Controller::PortAndSlotIsMultitap(u32 port, u32 slot)
|
||||||
{
|
{
|
||||||
switch (type)
|
return (slot != 0);
|
||||||
{
|
|
||||||
case ControllerType::DigitalController:
|
|
||||||
return DigitalController::StaticGetAxisCodeByName(axis_name);
|
|
||||||
|
|
||||||
case ControllerType::AnalogController:
|
|
||||||
return AnalogController::StaticGetAxisCodeByName(axis_name);
|
|
||||||
|
|
||||||
case ControllerType::AnalogJoystick:
|
|
||||||
return AnalogJoystick::StaticGetAxisCodeByName(axis_name);
|
|
||||||
|
|
||||||
case ControllerType::NamcoGunCon:
|
|
||||||
return NamcoGunCon::StaticGetAxisCodeByName(axis_name);
|
|
||||||
|
|
||||||
case ControllerType::PlayStationMouse:
|
|
||||||
return PlayStationMouse::StaticGetAxisCodeByName(axis_name);
|
|
||||||
|
|
||||||
case ControllerType::NeGcon:
|
|
||||||
return NeGcon::StaticGetAxisCodeByName(axis_name);
|
|
||||||
|
|
||||||
case ControllerType::None:
|
|
||||||
default:
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<s32> Controller::GetButtonCodeByName(ControllerType type, std::string_view button_name)
|
std::string Controller::GetSettingsSection(u32 pad)
|
||||||
{
|
{
|
||||||
switch (type)
|
return fmt::format("Pad{}", pad + 1u);
|
||||||
{
|
|
||||||
case ControllerType::DigitalController:
|
|
||||||
return DigitalController::StaticGetButtonCodeByName(button_name);
|
|
||||||
|
|
||||||
case ControllerType::AnalogController:
|
|
||||||
return AnalogController::StaticGetButtonCodeByName(button_name);
|
|
||||||
|
|
||||||
case ControllerType::AnalogJoystick:
|
|
||||||
return AnalogJoystick::StaticGetButtonCodeByName(button_name);
|
|
||||||
|
|
||||||
case ControllerType::NamcoGunCon:
|
|
||||||
return NamcoGunCon::StaticGetButtonCodeByName(button_name);
|
|
||||||
|
|
||||||
case ControllerType::PlayStationMouse:
|
|
||||||
return PlayStationMouse::StaticGetButtonCodeByName(button_name);
|
|
||||||
|
|
||||||
case ControllerType::NeGcon:
|
|
||||||
return NeGcon::StaticGetButtonCodeByName(button_name);
|
|
||||||
|
|
||||||
case ControllerType::None:
|
|
||||||
default:
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Controller::SettingList Controller::GetSettings(ControllerType type)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case ControllerType::DigitalController:
|
|
||||||
return DigitalController::StaticGetSettings();
|
|
||||||
|
|
||||||
case ControllerType::AnalogController:
|
|
||||||
return AnalogController::StaticGetSettings();
|
|
||||||
|
|
||||||
case ControllerType::AnalogJoystick:
|
|
||||||
return AnalogJoystick::StaticGetSettings();
|
|
||||||
|
|
||||||
case ControllerType::NamcoGunCon:
|
|
||||||
return NamcoGunCon::StaticGetSettings();
|
|
||||||
|
|
||||||
case ControllerType::NeGcon:
|
|
||||||
return NeGcon::StaticGetSettings();
|
|
||||||
|
|
||||||
case ControllerType::PlayStationMouse:
|
|
||||||
return PlayStationMouse::StaticGetSettings();
|
|
||||||
|
|
||||||
default:
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,36 +6,67 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
class SettingsInterface;
|
||||||
class StateWrapper;
|
class StateWrapper;
|
||||||
class HostInterface;
|
class HostInterface;
|
||||||
|
|
||||||
|
enum class GenericInputBinding : u8;
|
||||||
|
|
||||||
class Controller
|
class Controller
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class AxisType : u8
|
enum class ControllerBindingType : u8
|
||||||
{
|
{
|
||||||
Full,
|
Unknown,
|
||||||
Half
|
Button,
|
||||||
|
Axis,
|
||||||
|
HalfAxis,
|
||||||
|
Motor,
|
||||||
|
Macro
|
||||||
};
|
};
|
||||||
|
|
||||||
using ButtonList = std::vector<std::pair<std::string, s32>>;
|
enum class VibrationCapabilities : u8
|
||||||
using AxisList = std::vector<std::tuple<std::string, s32, AxisType>>;
|
{
|
||||||
using SettingList = std::vector<SettingInfo>;
|
NoVibration,
|
||||||
|
LargeSmallMotors,
|
||||||
|
SingleMotor,
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
|
||||||
Controller();
|
struct ControllerBindingInfo
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
const char* display_name;
|
||||||
|
u32 bind_index;
|
||||||
|
ControllerBindingType type;
|
||||||
|
GenericInputBinding generic_mapping;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ControllerInfo
|
||||||
|
{
|
||||||
|
ControllerType type;
|
||||||
|
const char* name;
|
||||||
|
const char* display_name;
|
||||||
|
const ControllerBindingInfo* bindings;
|
||||||
|
u32 num_bindings;
|
||||||
|
const SettingInfo* settings;
|
||||||
|
u32 num_settings;
|
||||||
|
VibrationCapabilities vibration_caps;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Default stick deadzone/sensitivity.
|
||||||
|
static constexpr float DEFAULT_STICK_DEADZONE = 0.0f;
|
||||||
|
static constexpr float DEFAULT_STICK_SENSITIVITY = 1.33f;
|
||||||
|
|
||||||
|
Controller(u32 index);
|
||||||
virtual ~Controller();
|
virtual ~Controller();
|
||||||
|
|
||||||
/// Returns the type of controller.
|
/// Returns the type of controller.
|
||||||
virtual ControllerType GetType() const = 0;
|
virtual ControllerType GetType() const = 0;
|
||||||
|
|
||||||
/// Gets the integer code for an axis in the specified controller type.
|
|
||||||
virtual std::optional<s32> GetAxisCodeByName(std::string_view axis_name) const;
|
|
||||||
|
|
||||||
/// Gets the integer code for a button in the specified controller type.
|
|
||||||
virtual std::optional<s32> GetButtonCodeByName(std::string_view button_name) const;
|
|
||||||
|
|
||||||
virtual void Reset();
|
virtual void Reset();
|
||||||
virtual bool DoState(StateWrapper& sw, bool apply_input_state);
|
virtual bool DoState(StateWrapper& sw, bool apply_input_state);
|
||||||
|
|
||||||
|
@ -46,16 +77,10 @@ public:
|
||||||
virtual bool Transfer(const u8 data_in, u8* data_out);
|
virtual bool Transfer(const u8 data_in, u8* data_out);
|
||||||
|
|
||||||
/// Changes the specified axis state. Values are normalized from -1..1.
|
/// Changes the specified axis state. Values are normalized from -1..1.
|
||||||
virtual float GetAxisState(s32 axis_code) const;
|
virtual float GetBindState(u32 index) const;
|
||||||
|
|
||||||
/// Changes the specified axis state. Values are normalized from -1..1.
|
/// Changes the specified bind state. Values are normalized from -1..1.
|
||||||
virtual void SetAxisState(s32 axis_code, float value);
|
virtual void SetBindState(u32 index, float value);
|
||||||
|
|
||||||
/// Returns the specified button state.
|
|
||||||
virtual bool GetButtonState(s32 button_code) const;
|
|
||||||
|
|
||||||
/// Changes the specified button state.
|
|
||||||
virtual void SetButtonState(s32 button_code, bool pressed);
|
|
||||||
|
|
||||||
/// Returns a bitmask of the current button states, 1 = on.
|
/// Returns a bitmask of the current button states, 1 = on.
|
||||||
virtual u32 GetButtonStateBits() const;
|
virtual u32 GetButtonStateBits() const;
|
||||||
|
@ -63,14 +88,8 @@ public:
|
||||||
/// Returns analog input bytes packed as a u32. Values are specific to controller type.
|
/// Returns analog input bytes packed as a u32. Values are specific to controller type.
|
||||||
virtual std::optional<u32> GetAnalogInputBytes() const;
|
virtual std::optional<u32> GetAnalogInputBytes() const;
|
||||||
|
|
||||||
/// Returns the number of vibration motors.
|
|
||||||
virtual u32 GetVibrationMotorCount() const;
|
|
||||||
|
|
||||||
/// Queries the state of the specified vibration motor. Values are normalized from 0..1.
|
|
||||||
virtual float GetVibrationMotorStrength(u32 motor);
|
|
||||||
|
|
||||||
/// Loads/refreshes any per-controller settings.
|
/// Loads/refreshes any per-controller settings.
|
||||||
virtual void LoadSettings(const char* section);
|
virtual void LoadSettings(SettingsInterface& si, const char* section);
|
||||||
|
|
||||||
/// Returns the software cursor to use for this controller, if any.
|
/// Returns the software cursor to use for this controller, if any.
|
||||||
virtual bool GetSoftwareCursor(const Common::RGBA8Image** image, float* image_scale, bool* relative_mode);
|
virtual bool GetSoftwareCursor(const Common::RGBA8Image** image, float* image_scale, bool* relative_mode);
|
||||||
|
@ -78,21 +97,45 @@ public:
|
||||||
/// Creates a new controller of the specified type.
|
/// Creates a new controller of the specified type.
|
||||||
static std::unique_ptr<Controller> Create(ControllerType type, u32 index);
|
static std::unique_ptr<Controller> Create(ControllerType type, u32 index);
|
||||||
|
|
||||||
|
/// Returns the default type for the specified port.
|
||||||
|
static const char* GetDefaultPadType(u32 pad);
|
||||||
|
|
||||||
|
/// Returns a list of controller type names. Pair of [name, display name].
|
||||||
|
static std::vector<std::pair<std::string, std::string>> GetControllerTypeNames();
|
||||||
|
|
||||||
|
/// Returns the list of binds for the specified controller type.
|
||||||
|
static std::vector<std::string> GetControllerBinds(const std::string_view& type);
|
||||||
|
static std::vector<std::string> GetControllerBinds(ControllerType type);
|
||||||
|
|
||||||
/// Gets the integer code for an axis in the specified controller type.
|
/// Gets the integer code for an axis in the specified controller type.
|
||||||
static std::optional<s32> GetAxisCodeByName(ControllerType type, std::string_view axis_name);
|
static std::optional<u32> GetBindIndex(ControllerType type, const std::string_view& bind_name);
|
||||||
|
|
||||||
/// Gets the integer code for a button in the specified controller type.
|
/// Returns the vibration configuration for the specified controller type.
|
||||||
static std::optional<s32> GetButtonCodeByName(ControllerType type, std::string_view button_name);
|
static VibrationCapabilities GetControllerVibrationCapabilities(const std::string_view& type);
|
||||||
|
|
||||||
/// Returns a list of axises for the specified controller type.
|
/// Returns general information for the specified controller type.
|
||||||
static AxisList GetAxisNames(ControllerType type);
|
static const ControllerInfo* GetControllerInfo(ControllerType type);
|
||||||
|
static const ControllerInfo* GetControllerInfo(const std::string_view& name);
|
||||||
|
|
||||||
/// Returns a list of buttons for the specified controller type.
|
/// Converts a global pad index to a multitap port and slot.
|
||||||
static ButtonList GetButtonNames(ControllerType type);
|
static std::tuple<u32, u32> ConvertPadToPortAndSlot(u32 index);
|
||||||
|
|
||||||
/// Returns the number of vibration motors.
|
/// Converts a multitap port and slot to a global pad index.
|
||||||
static u32 GetVibrationMotorCount(ControllerType type);
|
static u32 ConvertPortAndSlotToPad(u32 port, u32 slot);
|
||||||
|
|
||||||
/// Returns settings for the controller.
|
/// Returns true if the given pad index is a multitap slot.
|
||||||
static SettingList GetSettings(ControllerType type);
|
static bool PadIsMultitapSlot(u32 index);
|
||||||
|
static bool PortAndSlotIsMultitap(u32 port, u32 slot);
|
||||||
|
|
||||||
|
/// Returns the configuration section for the specified gamepad.
|
||||||
|
static std::string GetSettingsSection(u32 pad);
|
||||||
|
|
||||||
|
/// Applies an analog deadzone/sensitivity.
|
||||||
|
static float ApplyAnalogDeadzoneSensitivity(float deadzone, float sensitivity, float value)
|
||||||
|
{
|
||||||
|
return (value < deadzone) ? 0.0f : ((value - deadzone) / (1.0f - deadzone) * sensitivity);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
u32 m_index;
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<PreprocessorDefinitions Condition="('$(Platform)'=='x64' Or '$(Platform)'=='ARM' Or '$(Platform)'=='ARM64')">WITH_RECOMPILER=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions Condition="('$(Platform)'=='x64' Or '$(Platform)'=='ARM' Or '$(Platform)'=='ARM64')">WITH_RECOMPILER=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<PreprocessorDefinitions Condition="('$(Platform)'=='x64' Or '$(Platform)'=='ARM64') And ('$(BuildingForUWP)'!='true')">WITH_MMAP_FASTMEM=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions Condition="('$(Platform)'=='x64' Or '$(Platform)'=='ARM64') And ('$(BuildingForUWP)'!='true')">WITH_MMAP_FASTMEM=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xxhash\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\rcheevos\include;$(SolutionDir)dep\rapidjson\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)dep\tinyxml2\include;$(SolutionDir)dep\glad\include;$(SolutionDir)dep\stb\include;$(SolutionDir)dep\imgui\include;$(SolutionDir)dep\xxhash\include;$(SolutionDir)dep\zlib\include;$(SolutionDir)dep\rcheevos\include;$(SolutionDir)dep\rapidjson\include;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<AdditionalIncludeDirectories Condition="('$(BuildingForUWP)'!='true' And '$(Platform)'!='ARM64')">$(SolutionDir)dep\rainterface;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories Condition="('$(BuildingForUWP)'!='true' And '$(Platform)'!='ARM64')">$(SolutionDir)dep\rainterface;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
|
||||||
<AdditionalIncludeDirectories Condition="'$(Platform)'=='x64'">$(SolutionDir)dep\xbyak\xbyak;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories Condition="'$(Platform)'=='x64'">$(SolutionDir)dep\xbyak\xbyak;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
<ItemDefinitionGroup>
|
<ItemDefinitionGroup>
|
||||||
<Lib>
|
<Lib>
|
||||||
<AdditionalDependencies>$(RootBuildDir)rcheevos\rcheevos.lib;$(RootBuildDir)imgui\imgui.lib;$(RootBuildDir)stb\stb.lib;$(RootBuildDir)xxhash\xxhash.lib;$(RootBuildDir)zlib\zlib.lib;$(RootBuildDir)util\util.lib;$(RootBuildDir)common\common.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>$(RootBuildDir)tinyxml2\tinyxml2.lib;$(RootBuildDir)rcheevos\rcheevos.lib;$(RootBuildDir)imgui\imgui.lib;$(RootBuildDir)stb\stb.lib;$(RootBuildDir)xxhash\xxhash.lib;$(RootBuildDir)zlib\zlib.lib;$(RootBuildDir)util\util.lib;$(RootBuildDir)common\common.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalDependencies Condition="('$(BuildingForUWP)'!='true' And '$(Platform)'!='ARM64')">$(RootBuildDir)rainterface\rainterface.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies Condition="('$(BuildingForUWP)'!='true' And '$(Platform)'!='ARM64')">$(RootBuildDir)rainterface\rainterface.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
<AdditionalDependencies Condition="'$(Platform)'=='ARM64'">$(RootBuildDir)vixl\vixl.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies Condition="'$(Platform)'=='ARM64'">$(RootBuildDir)vixl\vixl.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Lib>
|
</Lib>
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
<ClCompile Include="cdrom.cpp" />
|
<ClCompile Include="cdrom.cpp" />
|
||||||
<ClCompile Include="cdrom_async_reader.cpp" />
|
<ClCompile Include="cdrom_async_reader.cpp" />
|
||||||
<ClCompile Include="cheats.cpp" />
|
<ClCompile Include="cheats.cpp" />
|
||||||
<ClCompile Include="cheevos.cpp" />
|
|
||||||
<ClCompile Include="cpu_core.cpp" />
|
<ClCompile Include="cpu_core.cpp" />
|
||||||
<ClCompile Include="cpu_disasm.cpp" />
|
<ClCompile Include="cpu_disasm.cpp" />
|
||||||
<ClCompile Include="cpu_code_cache.cpp" />
|
<ClCompile Include="cpu_code_cache.cpp" />
|
||||||
|
@ -33,6 +32,7 @@
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="cpu_types.cpp" />
|
<ClCompile Include="cpu_types.cpp" />
|
||||||
<ClCompile Include="digital_controller.cpp" />
|
<ClCompile Include="digital_controller.cpp" />
|
||||||
|
<ClCompile Include="game_database.cpp" />
|
||||||
<ClCompile Include="gpu_backend.cpp" />
|
<ClCompile Include="gpu_backend.cpp" />
|
||||||
<ClCompile Include="gpu_commands.cpp" />
|
<ClCompile Include="gpu_commands.cpp" />
|
||||||
<ClCompile Include="gpu_hw_d3d11.cpp" />
|
<ClCompile Include="gpu_hw_d3d11.cpp" />
|
||||||
|
@ -47,18 +47,16 @@
|
||||||
<ClCompile Include="gpu.cpp" />
|
<ClCompile Include="gpu.cpp" />
|
||||||
<ClCompile Include="gpu_hw.cpp" />
|
<ClCompile Include="gpu_hw.cpp" />
|
||||||
<ClCompile Include="gpu_hw_opengl.cpp" />
|
<ClCompile Include="gpu_hw_opengl.cpp" />
|
||||||
|
<ClCompile Include="host.cpp" />
|
||||||
<ClCompile Include="host_display.cpp" />
|
<ClCompile Include="host_display.cpp" />
|
||||||
<ClCompile Include="host_interface.cpp" />
|
|
||||||
<ClCompile Include="host_interface_progress_callback.cpp" />
|
<ClCompile Include="host_interface_progress_callback.cpp" />
|
||||||
<ClCompile Include="imgui_fullscreen.cpp" />
|
|
||||||
<ClCompile Include="imgui_styles.cpp" />
|
|
||||||
<ClCompile Include="interrupt_controller.cpp" />
|
<ClCompile Include="interrupt_controller.cpp" />
|
||||||
<ClCompile Include="libcrypt_game_codes.cpp" />
|
<ClCompile Include="libcrypt_game_codes.cpp" />
|
||||||
<ClCompile Include="mdec.cpp" />
|
<ClCompile Include="mdec.cpp" />
|
||||||
<ClCompile Include="memory_card.cpp" />
|
<ClCompile Include="memory_card.cpp" />
|
||||||
<ClCompile Include="memory_card_image.cpp" />
|
<ClCompile Include="memory_card_image.cpp" />
|
||||||
<ClCompile Include="multitap.cpp" />
|
<ClCompile Include="multitap.cpp" />
|
||||||
<ClCompile Include="namco_guncon.cpp" />
|
<ClCompile Include="guncon.cpp" />
|
||||||
<ClCompile Include="negcon.cpp" />
|
<ClCompile Include="negcon.cpp" />
|
||||||
<ClCompile Include="pad.cpp" />
|
<ClCompile Include="pad.cpp" />
|
||||||
<ClCompile Include="controller.cpp" />
|
<ClCompile Include="controller.cpp" />
|
||||||
|
@ -83,7 +81,7 @@
|
||||||
<ClInclude Include="cdrom.h" />
|
<ClInclude Include="cdrom.h" />
|
||||||
<ClInclude Include="cdrom_async_reader.h" />
|
<ClInclude Include="cdrom_async_reader.h" />
|
||||||
<ClInclude Include="cheats.h" />
|
<ClInclude Include="cheats.h" />
|
||||||
<ClInclude Include="cheevos.h" />
|
<ClInclude Include="achievements.h" />
|
||||||
<ClInclude Include="cpu_core.h" />
|
<ClInclude Include="cpu_core.h" />
|
||||||
<ClInclude Include="cpu_core_private.h" />
|
<ClInclude Include="cpu_core_private.h" />
|
||||||
<ClInclude Include="cpu_disasm.h" />
|
<ClInclude Include="cpu_disasm.h" />
|
||||||
|
@ -101,6 +99,7 @@
|
||||||
<ExcludedFromBuild Condition="'$(Platform)'=='Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Platform)'=='Win32'">true</ExcludedFromBuild>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="digital_controller.h" />
|
<ClInclude Include="digital_controller.h" />
|
||||||
|
<ClInclude Include="game_database.h" />
|
||||||
<ClInclude Include="gpu_backend.h" />
|
<ClInclude Include="gpu_backend.h" />
|
||||||
<ClInclude Include="gpu_hw_d3d11.h" />
|
<ClInclude Include="gpu_hw_d3d11.h" />
|
||||||
<ClInclude Include="gpu_hw_d3d12.h" />
|
<ClInclude Include="gpu_hw_d3d12.h" />
|
||||||
|
@ -119,18 +118,15 @@
|
||||||
<ClInclude Include="gte_types.h" />
|
<ClInclude Include="gte_types.h" />
|
||||||
<ClInclude Include="host.h" />
|
<ClInclude Include="host.h" />
|
||||||
<ClInclude Include="host_display.h" />
|
<ClInclude Include="host_display.h" />
|
||||||
<ClInclude Include="host_interface.h" />
|
|
||||||
<ClInclude Include="host_interface_progress_callback.h" />
|
<ClInclude Include="host_interface_progress_callback.h" />
|
||||||
<ClInclude Include="host_settings.h" />
|
<ClInclude Include="host_settings.h" />
|
||||||
<ClInclude Include="imgui_fullscreen.h" />
|
|
||||||
<ClInclude Include="imgui_styles.h" />
|
|
||||||
<ClInclude Include="interrupt_controller.h" />
|
<ClInclude Include="interrupt_controller.h" />
|
||||||
<ClInclude Include="libcrypt_game_codes.h" />
|
<ClInclude Include="libcrypt_game_codes.h" />
|
||||||
<ClInclude Include="mdec.h" />
|
<ClInclude Include="mdec.h" />
|
||||||
<ClInclude Include="memory_card.h" />
|
<ClInclude Include="memory_card.h" />
|
||||||
<ClInclude Include="memory_card_image.h" />
|
<ClInclude Include="memory_card_image.h" />
|
||||||
<ClInclude Include="multitap.h" />
|
<ClInclude Include="multitap.h" />
|
||||||
<ClInclude Include="namco_guncon.h" />
|
<ClInclude Include="guncon.h" />
|
||||||
<ClInclude Include="negcon.h" />
|
<ClInclude Include="negcon.h" />
|
||||||
<ClInclude Include="pad.h" />
|
<ClInclude Include="pad.h" />
|
||||||
<ClInclude Include="controller.h" />
|
<ClInclude Include="controller.h" />
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
<ClCompile Include="gpu.cpp" />
|
<ClCompile Include="gpu.cpp" />
|
||||||
<ClCompile Include="gpu_hw_opengl.cpp" />
|
<ClCompile Include="gpu_hw_opengl.cpp" />
|
||||||
<ClCompile Include="gpu_hw.cpp" />
|
<ClCompile Include="gpu_hw.cpp" />
|
||||||
<ClCompile Include="host_interface.cpp" />
|
|
||||||
<ClCompile Include="interrupt_controller.cpp" />
|
<ClCompile Include="interrupt_controller.cpp" />
|
||||||
<ClCompile Include="cdrom.cpp" />
|
<ClCompile Include="cdrom.cpp" />
|
||||||
<ClCompile Include="gte.cpp" />
|
<ClCompile Include="gte.cpp" />
|
||||||
|
@ -40,7 +39,7 @@
|
||||||
<ClCompile Include="timing_event.cpp" />
|
<ClCompile Include="timing_event.cpp" />
|
||||||
<ClCompile Include="cdrom_async_reader.cpp" />
|
<ClCompile Include="cdrom_async_reader.cpp" />
|
||||||
<ClCompile Include="psf_loader.cpp" />
|
<ClCompile Include="psf_loader.cpp" />
|
||||||
<ClCompile Include="namco_guncon.cpp" />
|
<ClCompile Include="guncon.cpp" />
|
||||||
<ClCompile Include="playstation_mouse.cpp" />
|
<ClCompile Include="playstation_mouse.cpp" />
|
||||||
<ClCompile Include="negcon.cpp" />
|
<ClCompile Include="negcon.cpp" />
|
||||||
<ClCompile Include="gpu_hw_vulkan.cpp" />
|
<ClCompile Include="gpu_hw_vulkan.cpp" />
|
||||||
|
@ -58,9 +57,8 @@
|
||||||
<ClCompile Include="texture_replacements.cpp" />
|
<ClCompile Include="texture_replacements.cpp" />
|
||||||
<ClCompile Include="multitap.cpp" />
|
<ClCompile Include="multitap.cpp" />
|
||||||
<ClCompile Include="gpu_hw_d3d12.cpp" />
|
<ClCompile Include="gpu_hw_d3d12.cpp" />
|
||||||
<ClCompile Include="imgui_fullscreen.cpp" />
|
<ClCompile Include="host.cpp" />
|
||||||
<ClCompile Include="imgui_styles.cpp" />
|
<ClCompile Include="game_database.cpp" />
|
||||||
<ClCompile Include="cheevos.cpp" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="types.h" />
|
<ClInclude Include="types.h" />
|
||||||
|
@ -74,7 +72,6 @@
|
||||||
<ClInclude Include="gpu.h" />
|
<ClInclude Include="gpu.h" />
|
||||||
<ClInclude Include="gpu_hw_opengl.h" />
|
<ClInclude Include="gpu_hw_opengl.h" />
|
||||||
<ClInclude Include="gpu_hw.h" />
|
<ClInclude Include="gpu_hw.h" />
|
||||||
<ClInclude Include="host_interface.h" />
|
|
||||||
<ClInclude Include="interrupt_controller.h" />
|
<ClInclude Include="interrupt_controller.h" />
|
||||||
<ClInclude Include="cdrom.h" />
|
<ClInclude Include="cdrom.h" />
|
||||||
<ClInclude Include="gte.h" />
|
<ClInclude Include="gte.h" />
|
||||||
|
@ -101,7 +98,7 @@
|
||||||
<ClInclude Include="timing_event.h" />
|
<ClInclude Include="timing_event.h" />
|
||||||
<ClInclude Include="cdrom_async_reader.h" />
|
<ClInclude Include="cdrom_async_reader.h" />
|
||||||
<ClInclude Include="psf_loader.h" />
|
<ClInclude Include="psf_loader.h" />
|
||||||
<ClInclude Include="namco_guncon.h" />
|
<ClInclude Include="guncon.h" />
|
||||||
<ClInclude Include="playstation_mouse.h" />
|
<ClInclude Include="playstation_mouse.h" />
|
||||||
<ClInclude Include="negcon.h" />
|
<ClInclude Include="negcon.h" />
|
||||||
<ClInclude Include="gpu_hw_vulkan.h" />
|
<ClInclude Include="gpu_hw_vulkan.h" />
|
||||||
|
@ -123,10 +120,9 @@
|
||||||
<ClInclude Include="multitap.h" />
|
<ClInclude Include="multitap.h" />
|
||||||
<ClInclude Include="gpu_hw_d3d12.h" />
|
<ClInclude Include="gpu_hw_d3d12.h" />
|
||||||
<ClInclude Include="gdb_protocol.h" />
|
<ClInclude Include="gdb_protocol.h" />
|
||||||
<ClInclude Include="imgui_fullscreen.h" />
|
|
||||||
<ClInclude Include="imgui_styles.h" />
|
|
||||||
<ClInclude Include="cheevos.h" />
|
|
||||||
<ClInclude Include="host.h" />
|
<ClInclude Include="host.h" />
|
||||||
<ClInclude Include="host_settings.h" />
|
<ClInclude Include="host_settings.h" />
|
||||||
|
<ClInclude Include="achievements.h" />
|
||||||
|
<ClInclude Include="game_database.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
|
@ -7,7 +7,7 @@
|
||||||
#include "cpu_disasm.h"
|
#include "cpu_disasm.h"
|
||||||
#include "cpu_recompiler_thunks.h"
|
#include "cpu_recompiler_thunks.h"
|
||||||
#include "gte.h"
|
#include "gte.h"
|
||||||
#include "host_interface.h"
|
#include "host.h"
|
||||||
#include "pgxp.h"
|
#include "pgxp.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
@ -1691,8 +1691,8 @@ bool AddBreakpoint(VirtualMemoryAddress address, bool auto_clear, bool enabled)
|
||||||
|
|
||||||
if (!auto_clear)
|
if (!auto_clear)
|
||||||
{
|
{
|
||||||
g_host_interface->ReportFormattedDebuggerMessage(
|
Host::ReportFormattedDebuggerMessage(Host::TranslateString("DebuggerMessage", "Added breakpoint at 0x%08X."),
|
||||||
g_host_interface->TranslateString("DebuggerMessage", "Added breakpoint at 0x%08X."), address);
|
address);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -1718,8 +1718,8 @@ bool RemoveBreakpoint(VirtualMemoryAddress address)
|
||||||
if (it == s_breakpoints.end())
|
if (it == s_breakpoints.end())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
g_host_interface->ReportFormattedDebuggerMessage(
|
Host::ReportFormattedDebuggerMessage(Host::TranslateString("DebuggerMessage", "Removed breakpoint at 0x%08X."),
|
||||||
g_host_interface->TranslateString("DebuggerMessage", "Removed breakpoint at 0x%08X."), address);
|
address);
|
||||||
|
|
||||||
s_breakpoints.erase(it);
|
s_breakpoints.erase(it);
|
||||||
UpdateDebugDispatcherFlag();
|
UpdateDebugDispatcherFlag();
|
||||||
|
@ -1750,8 +1750,8 @@ bool AddStepOverBreakpoint()
|
||||||
|
|
||||||
if (!IsCallInstruction(inst))
|
if (!IsCallInstruction(inst))
|
||||||
{
|
{
|
||||||
g_host_interface->ReportFormattedDebuggerMessage(
|
Host::ReportFormattedDebuggerMessage(Host::TranslateString("DebuggerMessage", "0x%08X is not a call instruction."),
|
||||||
g_host_interface->TranslateString("DebuggerMessage", "0x%08X is not a call instruction."), g_state.regs.pc);
|
g_state.regs.pc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1760,16 +1760,15 @@ bool AddStepOverBreakpoint()
|
||||||
|
|
||||||
if (IsBranchInstruction(inst))
|
if (IsBranchInstruction(inst))
|
||||||
{
|
{
|
||||||
g_host_interface->ReportFormattedDebuggerMessage(
|
Host::ReportFormattedDebuggerMessage(
|
||||||
g_host_interface->TranslateString("DebuggerMessage", "Can't step over double branch at 0x%08X"), g_state.regs.pc);
|
Host::TranslateString("DebuggerMessage", "Can't step over double branch at 0x%08X"), g_state.regs.pc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip the delay slot
|
// skip the delay slot
|
||||||
bp_pc += sizeof(Instruction);
|
bp_pc += sizeof(Instruction);
|
||||||
|
|
||||||
g_host_interface->ReportFormattedDebuggerMessage(
|
Host::ReportFormattedDebuggerMessage(Host::TranslateString("DebuggerMessage", "Stepping over to 0x%08X."), bp_pc);
|
||||||
g_host_interface->TranslateString("DebuggerMessage", "Stepping over to 0x%08X."), bp_pc);
|
|
||||||
|
|
||||||
return AddBreakpoint(bp_pc, true);
|
return AddBreakpoint(bp_pc, true);
|
||||||
}
|
}
|
||||||
|
@ -1785,25 +1784,22 @@ bool AddStepOutBreakpoint(u32 max_instructions_to_search)
|
||||||
Instruction inst;
|
Instruction inst;
|
||||||
if (!SafeReadInstruction(ret_pc, &inst.bits))
|
if (!SafeReadInstruction(ret_pc, &inst.bits))
|
||||||
{
|
{
|
||||||
g_host_interface->ReportFormattedDebuggerMessage(
|
Host::ReportFormattedDebuggerMessage(
|
||||||
g_host_interface->TranslateString("DebuggerMessage",
|
Host::TranslateString("DebuggerMessage", "Instruction read failed at %08X while searching for function end."),
|
||||||
"Instruction read failed at %08X while searching for function end."),
|
|
||||||
ret_pc);
|
ret_pc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsReturnInstruction(inst))
|
if (IsReturnInstruction(inst))
|
||||||
{
|
{
|
||||||
g_host_interface->ReportFormattedDebuggerMessage(
|
Host::ReportFormattedDebuggerMessage(Host::TranslateString("DebuggerMessage", "Stepping out to 0x%08X."), ret_pc);
|
||||||
g_host_interface->TranslateString("DebuggerMessage", "Stepping out to 0x%08X."), ret_pc);
|
|
||||||
|
|
||||||
return AddBreakpoint(ret_pc, true);
|
return AddBreakpoint(ret_pc, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_host_interface->ReportFormattedDebuggerMessage(
|
Host::ReportFormattedDebuggerMessage(
|
||||||
g_host_interface->TranslateString("DebuggerMessage",
|
Host::TranslateString("DebuggerMessage", "No return instruction found after %u instructions for step-out at %08X."),
|
||||||
"No return instruction found after %u instructions for step-out at %08X."),
|
|
||||||
max_instructions_to_search, g_state.regs.pc);
|
max_instructions_to_search, g_state.regs.pc);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -1857,18 +1853,18 @@ ALWAYS_INLINE_RELEASE static bool BreakpointCheck()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_host_interface->PauseSystem(true);
|
System::PauseSystem(true);
|
||||||
|
|
||||||
if (bp.auto_clear)
|
if (bp.auto_clear)
|
||||||
{
|
{
|
||||||
g_host_interface->ReportFormattedDebuggerMessage("Stopped execution at 0x%08X.", pc);
|
Host::ReportFormattedDebuggerMessage("Stopped execution at 0x%08X.", pc);
|
||||||
s_breakpoints.erase(s_breakpoints.begin() + i);
|
s_breakpoints.erase(s_breakpoints.begin() + i);
|
||||||
count--;
|
count--;
|
||||||
UpdateDebugDispatcherFlag();
|
UpdateDebugDispatcherFlag();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_host_interface->ReportFormattedDebuggerMessage("Hit breakpoint %u at 0x%08X.", bp.number, pc);
|
Host::ReportFormattedDebuggerMessage("Hit breakpoint %u at 0x%08X.", bp.number, pc);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1979,7 +1975,7 @@ void SingleStep()
|
||||||
{
|
{
|
||||||
s_single_step = true;
|
s_single_step = true;
|
||||||
ExecuteDebug();
|
ExecuteDebug();
|
||||||
g_host_interface->ReportFormattedDebuggerMessage("Stepped to 0x%08X.", g_state.regs.pc);
|
Host::ReportFormattedDebuggerMessage("Stepped to 0x%08X.", g_state.regs.pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace CodeCache {
|
namespace CodeCache {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#include "digital_controller.h"
|
#include "digital_controller.h"
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "host_interface.h"
|
#include "host.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "util/state_wrapper.h"
|
#include "util/state_wrapper.h"
|
||||||
|
|
||||||
DigitalController::DigitalController() = default;
|
DigitalController::DigitalController(u32 index) : Controller(index) {}
|
||||||
|
|
||||||
DigitalController::~DigitalController() = default;
|
DigitalController::~DigitalController() = default;
|
||||||
|
|
||||||
|
@ -13,16 +13,6 @@ ControllerType DigitalController::GetType() const
|
||||||
return ControllerType::DigitalController;
|
return ControllerType::DigitalController;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<s32> DigitalController::GetAxisCodeByName(std::string_view axis_name) const
|
|
||||||
{
|
|
||||||
return StaticGetAxisCodeByName(axis_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<s32> DigitalController::GetButtonCodeByName(std::string_view button_name) const
|
|
||||||
{
|
|
||||||
return StaticGetButtonCodeByName(button_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DigitalController::Reset()
|
void DigitalController::Reset()
|
||||||
{
|
{
|
||||||
m_transfer_state = TransferState::Idle;
|
m_transfer_state = TransferState::Idle;
|
||||||
|
@ -42,18 +32,25 @@ bool DigitalController::DoState(StateWrapper& sw, bool apply_input_state)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DigitalController::GetButtonState(s32 button_code) const
|
float DigitalController::GetBindState(u32 index) const
|
||||||
{
|
{
|
||||||
if (button_code < 0 || button_code >= static_cast<s32>(Button::Count))
|
if (index < static_cast<u32>(Button::Count))
|
||||||
return false;
|
{
|
||||||
|
return static_cast<float>(((m_button_state >> index) & 1u) ^ 1u);
|
||||||
const u16 bit = u16(1) << static_cast<u8>(button_code);
|
}
|
||||||
return ((m_button_state & bit) == 0);
|
else
|
||||||
|
{
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DigitalController::SetButtonState(Button button, bool pressed)
|
void DigitalController::SetBindState(u32 index, float value)
|
||||||
{
|
{
|
||||||
const u16 bit = u16(1) << static_cast<u8>(button);
|
if (index >= static_cast<u32>(Button::Count))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const bool pressed = (value >= 0.5f);
|
||||||
|
const u16 bit = u16(1) << static_cast<u8>(index);
|
||||||
if (pressed)
|
if (pressed)
|
||||||
{
|
{
|
||||||
if (m_button_state & bit)
|
if (m_button_state & bit)
|
||||||
|
@ -70,14 +67,6 @@ void DigitalController::SetButtonState(Button button, bool pressed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DigitalController::SetButtonState(s32 button_code, bool pressed)
|
|
||||||
{
|
|
||||||
if (button_code < 0 || button_code >= static_cast<s32>(Button::Count))
|
|
||||||
return;
|
|
||||||
|
|
||||||
SetButtonState(static_cast<Button>(button_code), pressed);
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 DigitalController::GetButtonStateBits() const
|
u32 DigitalController::GetButtonStateBits() const
|
||||||
{
|
{
|
||||||
return m_button_state ^ 0xFFFF;
|
return m_button_state ^ 0xFFFF;
|
||||||
|
@ -146,87 +135,53 @@ bool DigitalController::Transfer(const u8 data_in, u8* data_out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<DigitalController> DigitalController::Create()
|
std::unique_ptr<DigitalController> DigitalController::Create(u32 index)
|
||||||
{
|
{
|
||||||
return std::make_unique<DigitalController>();
|
return std::make_unique<DigitalController>(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<s32> DigitalController::StaticGetAxisCodeByName(std::string_view button_name)
|
static const Controller::ControllerBindingInfo s_binding_info[] = {
|
||||||
{
|
#define BUTTON(name, display_name, button, genb) \
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<s32> DigitalController::StaticGetButtonCodeByName(std::string_view button_name)
|
|
||||||
{
|
|
||||||
#define BUTTON(name) \
|
|
||||||
if (button_name == #name) \
|
|
||||||
{ \
|
{ \
|
||||||
return static_cast<s32>(ZeroExtend32(static_cast<u8>(Button::name))); \
|
name, display_name, static_cast<u32>(button), Controller::ControllerBindingType::Button, genb \
|
||||||
}
|
}
|
||||||
|
|
||||||
BUTTON(Select);
|
BUTTON("Up", "D-Pad Up", DigitalController::Button::Up, GenericInputBinding::DPadUp),
|
||||||
BUTTON(L3);
|
BUTTON("Right", "D-Pad Right", DigitalController::Button::Right, GenericInputBinding::DPadRight),
|
||||||
BUTTON(R3);
|
BUTTON("Down", "D-Pad Down", DigitalController::Button::Down, GenericInputBinding::DPadDown),
|
||||||
BUTTON(Start);
|
BUTTON("Left", "D-Pad Left", DigitalController::Button::Left, GenericInputBinding::DPadLeft),
|
||||||
BUTTON(Up);
|
BUTTON("Triangle", "Triangle", DigitalController::Button::Triangle, GenericInputBinding::Triangle),
|
||||||
BUTTON(Right);
|
BUTTON("Circle", "Circle", DigitalController::Button::Circle, GenericInputBinding::Circle),
|
||||||
BUTTON(Down);
|
BUTTON("Cross", "Cross", DigitalController::Button::Cross, GenericInputBinding::Cross),
|
||||||
BUTTON(Left);
|
BUTTON("Square", "Square", DigitalController::Button::Square, GenericInputBinding::Square),
|
||||||
BUTTON(L2);
|
BUTTON("Select", "Select", DigitalController::Button::Select, GenericInputBinding::Select),
|
||||||
BUTTON(R2);
|
BUTTON("Start", "Start", DigitalController::Button::Start, GenericInputBinding::Start),
|
||||||
BUTTON(L1);
|
BUTTON("L1", "L1", DigitalController::Button::L1, GenericInputBinding::L1),
|
||||||
BUTTON(R1);
|
BUTTON("R1", "R1", DigitalController::Button::R1, GenericInputBinding::R1),
|
||||||
BUTTON(Triangle);
|
BUTTON("L2", "L2", DigitalController::Button::L2, GenericInputBinding::L2),
|
||||||
BUTTON(Circle);
|
BUTTON("R2", "R2", DigitalController::Button::R2, GenericInputBinding::R2),
|
||||||
BUTTON(Cross);
|
|
||||||
BUTTON(Square);
|
|
||||||
|
|
||||||
return std::nullopt;
|
|
||||||
|
|
||||||
#undef BUTTON
|
#undef BUTTON
|
||||||
}
|
};
|
||||||
|
|
||||||
Controller::AxisList DigitalController::StaticGetAxisNames()
|
static const SettingInfo s_settings[] = {
|
||||||
{
|
{SettingInfo::Type::Boolean, "ForcePopnControllerMode",
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Controller::ButtonList DigitalController::StaticGetButtonNames()
|
|
||||||
{
|
|
||||||
return {{TRANSLATABLE("DigitalController", "Up"), static_cast<s32>(Button::Up)},
|
|
||||||
{TRANSLATABLE("DigitalController", "Down"), static_cast<s32>(Button::Down)},
|
|
||||||
{TRANSLATABLE("DigitalController", "Left"), static_cast<s32>(Button::Left)},
|
|
||||||
{TRANSLATABLE("DigitalController", "Right"), static_cast<s32>(Button::Right)},
|
|
||||||
{TRANSLATABLE("DigitalController", "Select"), static_cast<s32>(Button::Select)},
|
|
||||||
{TRANSLATABLE("DigitalController", "Start"), static_cast<s32>(Button::Start)},
|
|
||||||
{TRANSLATABLE("DigitalController", "Triangle"), static_cast<s32>(Button::Triangle)},
|
|
||||||
{TRANSLATABLE("DigitalController", "Cross"), static_cast<s32>(Button::Cross)},
|
|
||||||
{TRANSLATABLE("DigitalController", "Circle"), static_cast<s32>(Button::Circle)},
|
|
||||||
{TRANSLATABLE("DigitalController", "Square"), static_cast<s32>(Button::Square)},
|
|
||||||
{TRANSLATABLE("DigitalController", "L1"), static_cast<s32>(Button::L1)},
|
|
||||||
{TRANSLATABLE("DigitalController", "L2"), static_cast<s32>(Button::L2)},
|
|
||||||
{TRANSLATABLE("DigitalController", "R1"), static_cast<s32>(Button::R1)},
|
|
||||||
{TRANSLATABLE("DigitalController", "R2"), static_cast<s32>(Button::R2)}};
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 DigitalController::StaticGetVibrationMotorCount()
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Controller::SettingList DigitalController::StaticGetSettings()
|
|
||||||
{
|
|
||||||
static constexpr std::array<SettingInfo, 1> settings = {
|
|
||||||
{{SettingInfo::Type::Boolean, "ForcePopnControllerMode",
|
|
||||||
TRANSLATABLE("DigitalController", "Force Pop'n Controller Mode"),
|
TRANSLATABLE("DigitalController", "Force Pop'n Controller Mode"),
|
||||||
TRANSLATABLE("DigitalController", "Forces the Digital Controller to act as a Pop'n Controller."), "false"}}};
|
TRANSLATABLE("DigitalController", "Forces the Digital Controller to act as a Pop'n Controller."), "false"}};
|
||||||
return SettingList(settings.begin(), settings.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
void DigitalController::LoadSettings(const char* section)
|
const Controller::ControllerInfo DigitalController::INFO = {ControllerType::DigitalController,
|
||||||
|
"DigitalController",
|
||||||
|
TRANSLATABLE("ControllerType", "Digital Controller"),
|
||||||
|
s_binding_info,
|
||||||
|
countof(s_binding_info),
|
||||||
|
s_settings,
|
||||||
|
countof(s_settings),
|
||||||
|
Controller::VibrationCapabilities::NoVibration};
|
||||||
|
|
||||||
|
void DigitalController::LoadSettings(SettingsInterface& si, const char* section)
|
||||||
{
|
{
|
||||||
Controller::LoadSettings(section);
|
Controller::LoadSettings(si, section);
|
||||||
m_popn_controller_mode = g_host_interface->GetBoolSettingValue(section, "ForcePopnControllerMode", false);
|
m_popn_controller_mode = si.GetBoolValue(section, "ForcePopnControllerMode", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 DigitalController::GetButtonsLSBMask() const
|
u8 DigitalController::GetButtonsLSBMask() const
|
||||||
|
|
|
@ -28,34 +28,26 @@ public:
|
||||||
Count
|
Count
|
||||||
};
|
};
|
||||||
|
|
||||||
DigitalController();
|
static const Controller::ControllerInfo INFO;
|
||||||
|
|
||||||
|
DigitalController(u32 index);
|
||||||
~DigitalController() override;
|
~DigitalController() override;
|
||||||
|
|
||||||
static std::unique_ptr<DigitalController> Create();
|
static std::unique_ptr<DigitalController> Create(u32 index);
|
||||||
static std::optional<s32> StaticGetAxisCodeByName(std::string_view button_name);
|
|
||||||
static std::optional<s32> StaticGetButtonCodeByName(std::string_view button_name);
|
|
||||||
static AxisList StaticGetAxisNames();
|
|
||||||
static ButtonList StaticGetButtonNames();
|
|
||||||
static u32 StaticGetVibrationMotorCount();
|
|
||||||
static SettingList StaticGetSettings();
|
|
||||||
|
|
||||||
ControllerType GetType() const override;
|
ControllerType GetType() const override;
|
||||||
std::optional<s32> GetAxisCodeByName(std::string_view axis_name) const override;
|
|
||||||
std::optional<s32> GetButtonCodeByName(std::string_view button_name) const override;
|
|
||||||
|
|
||||||
void Reset() override;
|
void Reset() override;
|
||||||
bool DoState(StateWrapper& sw, bool apply_input_state) override;
|
bool DoState(StateWrapper& sw, bool apply_input_state) override;
|
||||||
|
|
||||||
bool GetButtonState(s32 button_code) const override;
|
float GetBindState(u32 index) const override;
|
||||||
void SetButtonState(s32 button_code, bool pressed) override;
|
void SetBindState(u32 index, float value) override;
|
||||||
u32 GetButtonStateBits() const override;
|
u32 GetButtonStateBits() const override;
|
||||||
|
|
||||||
void ResetTransferState() override;
|
void ResetTransferState() override;
|
||||||
bool Transfer(const u8 data_in, u8* data_out) override;
|
bool Transfer(const u8 data_in, u8* data_out) override;
|
||||||
|
|
||||||
void SetButtonState(Button button, bool pressed);
|
void LoadSettings(SettingsInterface& si, const char* section) override;
|
||||||
|
|
||||||
void LoadSettings(const char* section) override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class TransferState : u8
|
enum class TransferState : u8
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "cpu_code_cache.h"
|
#include "cpu_code_cache.h"
|
||||||
#include "cpu_core.h"
|
#include "cpu_core.h"
|
||||||
#include "gpu.h"
|
#include "gpu.h"
|
||||||
|
#include "host.h"
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "interrupt_controller.h"
|
#include "interrupt_controller.h"
|
||||||
#include "mdec.h"
|
#include "mdec.h"
|
||||||
|
@ -626,7 +627,7 @@ void DMA::DrawDebugStateWindow()
|
||||||
{"MDECin", "MDECout", "GPU", "CDROM", "SPU", "PIO", "OTC"}};
|
{"MDECin", "MDECout", "GPU", "CDROM", "SPU", "PIO", "OTC"}};
|
||||||
static constexpr std::array<const char*, 4> sync_mode_names = {{"Manual", "Request", "LinkedList", "Reserved"}};
|
static constexpr std::array<const char*, 4> sync_mode_names = {{"Manual", "Request", "LinkedList", "Reserved"}};
|
||||||
|
|
||||||
const float framebuffer_scale = ImGui::GetIO().DisplayFramebufferScale.x;
|
const float framebuffer_scale = Host::GetOSDScale();
|
||||||
|
|
||||||
ImGui::SetNextWindowSize(ImVec2(850.0f * framebuffer_scale, 250.0f * framebuffer_scale), ImGuiCond_FirstUseEver);
|
ImGui::SetNextWindowSize(ImVec2(850.0f * framebuffer_scale, 250.0f * framebuffer_scale), ImGuiCond_FirstUseEver);
|
||||||
if (!ImGui::Begin("DMA State", nullptr))
|
if (!ImGui::Begin("DMA State", nullptr))
|
||||||
|
|
1137
src/core/game_database.cpp
Normal file
122
src/core/game_database.h
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
#pragma once
|
||||||
|
#include "core/types.h"
|
||||||
|
#include "util/cd_image_hasher.h"
|
||||||
|
#include <bitset>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class CDImage;
|
||||||
|
|
||||||
|
struct Settings;
|
||||||
|
|
||||||
|
namespace GameDatabase {
|
||||||
|
enum class CompatibilityRating : u32
|
||||||
|
{
|
||||||
|
Unknown = 0,
|
||||||
|
DoesntBoot = 1,
|
||||||
|
CrashesInIntro = 2,
|
||||||
|
CrashesInGame = 3,
|
||||||
|
GraphicalAudioIssues = 4,
|
||||||
|
NoIssues = 5,
|
||||||
|
Count,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Trait : u32
|
||||||
|
{
|
||||||
|
ForceInterpreter,
|
||||||
|
ForceSoftwareRenderer,
|
||||||
|
ForceSoftwareRendererForReadbacks,
|
||||||
|
ForceInterlacing,
|
||||||
|
DisableTrueColor,
|
||||||
|
DisableUpscaling,
|
||||||
|
DisableScaledDithering,
|
||||||
|
DisableForceNTSCTimings,
|
||||||
|
DisableWidescreen,
|
||||||
|
DisablePGXP,
|
||||||
|
DisablePGXPCulling,
|
||||||
|
DisablePGXPTextureCorrection,
|
||||||
|
DisablePGXPDepthBuffer,
|
||||||
|
ForcePGXPVertexCache,
|
||||||
|
ForcePGXPCPUMode,
|
||||||
|
ForceRecompilerMemoryExceptions,
|
||||||
|
ForceRecompilerICache,
|
||||||
|
ForceRecompilerLUTFastmem,
|
||||||
|
|
||||||
|
Count
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Entry
|
||||||
|
{
|
||||||
|
// TODO: Make string_view.
|
||||||
|
std::string serial;
|
||||||
|
std::string title;
|
||||||
|
std::string genre;
|
||||||
|
std::string developer;
|
||||||
|
std::string publisher;
|
||||||
|
u64 release_date;
|
||||||
|
u8 min_players;
|
||||||
|
u8 max_players;
|
||||||
|
u8 min_blocks;
|
||||||
|
u8 max_blocks;
|
||||||
|
u32 supported_controllers;
|
||||||
|
CompatibilityRating compatibility;
|
||||||
|
|
||||||
|
std::bitset<static_cast<int>(Trait::Count)> traits{};
|
||||||
|
std::optional<s16> display_active_start_offset;
|
||||||
|
std::optional<s16> display_active_end_offset;
|
||||||
|
std::optional<s8> display_line_start_offset;
|
||||||
|
std::optional<s8> display_line_end_offset;
|
||||||
|
std::optional<u32> dma_max_slice_ticks;
|
||||||
|
std::optional<u32> dma_halt_ticks;
|
||||||
|
std::optional<u32> gpu_fifo_size;
|
||||||
|
std::optional<u32> gpu_max_run_ahead;
|
||||||
|
std::optional<float> gpu_pgxp_tolerance;
|
||||||
|
std::optional<float> gpu_pgxp_depth_threshold;
|
||||||
|
|
||||||
|
ALWAYS_INLINE bool HasTrait(Trait trait) const { return traits[static_cast<int>(trait)]; }
|
||||||
|
|
||||||
|
void ApplySettings(Settings& settings, bool display_osd_messages) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
void EnsureLoaded();
|
||||||
|
void Unload();
|
||||||
|
|
||||||
|
const Entry* GetEntryForDisc(CDImage* image);
|
||||||
|
const Entry* GetEntryForSerial(const std::string_view& serial);
|
||||||
|
const Entry* GetEntryForCode(const std::string_view& code);
|
||||||
|
std::string GetSerialForDisc(CDImage* image);
|
||||||
|
std::string GetSerialForPath(const char* path);
|
||||||
|
|
||||||
|
const char* GetTraitName(Trait trait);
|
||||||
|
const char* GetTraitDisplayName(Trait trait);
|
||||||
|
|
||||||
|
const char* GetCompatibilityRatingName(CompatibilityRating rating);
|
||||||
|
const char* GetCompatibilityRatingDisplayName(CompatibilityRating rating);
|
||||||
|
|
||||||
|
/// Map of track hashes for image verification
|
||||||
|
struct TrackData
|
||||||
|
{
|
||||||
|
TrackData(std::vector<std::string> codes, std::string revisionString, uint32_t revision)
|
||||||
|
: codes(std::move(codes)), revisionString(revisionString), revision(revision)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
friend bool operator==(const TrackData& left, const TrackData& right)
|
||||||
|
{
|
||||||
|
// 'revisionString' is deliberately ignored in comparisons as it's redundant with comparing 'revision'! Do not
|
||||||
|
// change!
|
||||||
|
return left.codes == right.codes && left.revision == right.revision;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> codes;
|
||||||
|
std::string revisionString;
|
||||||
|
uint32_t revision;
|
||||||
|
};
|
||||||
|
|
||||||
|
using TrackHashesMap = std::multimap<CDImageHasher::Hash, TrackData>;
|
||||||
|
const TrackHashesMap& GetTrackHashesMap();
|
||||||
|
void EnsureTrackHashesMapLoaded();
|
||||||
|
|
||||||
|
} // namespace GameDatabase
|
|
@ -4,7 +4,7 @@
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "cpu_core.h"
|
#include "cpu_core.h"
|
||||||
#include "frontend-common/common_host_interface.h"
|
#include "frontend-common/common_host.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "dma.h"
|
#include "dma.h"
|
||||||
|
#include "host.h"
|
||||||
#include "host_display.h"
|
#include "host_display.h"
|
||||||
#include "host_interface.h"
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "interrupt_controller.h"
|
#include "interrupt_controller.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
@ -24,9 +24,8 @@ GPU::GPU() = default;
|
||||||
|
|
||||||
GPU::~GPU() = default;
|
GPU::~GPU() = default;
|
||||||
|
|
||||||
bool GPU::Initialize(HostDisplay* host_display)
|
bool GPU::Initialize()
|
||||||
{
|
{
|
||||||
m_host_display = host_display;
|
|
||||||
m_force_progressive_scan = g_settings.gpu_disable_interlacing;
|
m_force_progressive_scan = g_settings.gpu_disable_interlacing;
|
||||||
m_force_ntsc_timings = g_settings.gpu_force_ntsc_timings;
|
m_force_ntsc_timings = g_settings.gpu_force_ntsc_timings;
|
||||||
m_crtc_tick_event = TimingEvents::CreateTimingEvent(
|
m_crtc_tick_event = TimingEvents::CreateTimingEvent(
|
||||||
|
@ -41,6 +40,16 @@ bool GPU::Initialize(HostDisplay* host_display)
|
||||||
m_max_run_ahead = g_settings.gpu_max_run_ahead;
|
m_max_run_ahead = g_settings.gpu_max_run_ahead;
|
||||||
m_console_is_pal = System::IsPALRegion();
|
m_console_is_pal = System::IsPALRegion();
|
||||||
UpdateCRTCConfig();
|
UpdateCRTCConfig();
|
||||||
|
|
||||||
|
g_host_display->SetDisplayLinearFiltering(g_settings.display_linear_filtering);
|
||||||
|
g_host_display->SetDisplayIntegerScaling(g_settings.display_integer_scaling);
|
||||||
|
g_host_display->SetDisplayStretch(g_settings.display_stretch);
|
||||||
|
if (g_settings.display_post_processing &&
|
||||||
|
!g_host_display->SetPostProcessingChain(g_settings.display_post_process_chain))
|
||||||
|
{
|
||||||
|
Host::AddOSDMessage(Host::TranslateStdString("OSDMessage", "Failed to load post processing shader chain."), 20.0f);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +68,10 @@ void GPU::UpdateSettings()
|
||||||
|
|
||||||
// Crop mode calls this, so recalculate the display area
|
// Crop mode calls this, so recalculate the display area
|
||||||
UpdateCRTCDisplayParameters();
|
UpdateCRTCDisplayParameters();
|
||||||
|
|
||||||
|
g_host_display->SetDisplayLinearFiltering(g_settings.display_linear_filtering);
|
||||||
|
g_host_display->SetDisplayIntegerScaling(g_settings.display_integer_scaling);
|
||||||
|
g_host_display->SetDisplayStretch(g_settings.display_stretch);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPU::IsHardwareRenderer()
|
bool GPU::IsHardwareRenderer()
|
||||||
|
@ -962,9 +975,9 @@ void GPU::UpdateCommandTickEvent()
|
||||||
bool GPU::ConvertScreenCoordinatesToBeamTicksAndLines(s32 window_x, s32 window_y, float x_scale, u32* out_tick,
|
bool GPU::ConvertScreenCoordinatesToBeamTicksAndLines(s32 window_x, s32 window_y, float x_scale, u32* out_tick,
|
||||||
u32* out_line) const
|
u32* out_line) const
|
||||||
{
|
{
|
||||||
auto [display_x, display_y] = m_host_display->ConvertWindowCoordinatesToDisplayCoordinates(
|
auto [display_x, display_y] = g_host_display->ConvertWindowCoordinatesToDisplayCoordinates(
|
||||||
window_x, window_y, m_host_display->GetWindowWidth(), m_host_display->GetWindowHeight(),
|
window_x, window_y, g_host_display->GetWindowWidth(), g_host_display->GetWindowHeight(),
|
||||||
m_host_display->GetDisplayTopMargin());
|
g_host_display->GetDisplayTopMargin());
|
||||||
|
|
||||||
if (x_scale != 1.0f)
|
if (x_scale != 1.0f)
|
||||||
{
|
{
|
||||||
|
@ -1551,7 +1564,7 @@ bool GPU::DumpVRAMToFile(const char* filename, u32 width, u32 height, u32 stride
|
||||||
|
|
||||||
void GPU::DrawDebugStateWindow()
|
void GPU::DrawDebugStateWindow()
|
||||||
{
|
{
|
||||||
const float framebuffer_scale = ImGui::GetIO().DisplayFramebufferScale.x;
|
const float framebuffer_scale = Host::GetOSDScale();
|
||||||
|
|
||||||
ImGui::SetNextWindowSize(ImVec2(450.0f * framebuffer_scale, 550.0f * framebuffer_scale), ImGuiCond_FirstUseEver);
|
ImGui::SetNextWindowSize(ImVec2(450.0f * framebuffer_scale, 550.0f * framebuffer_scale), ImGuiCond_FirstUseEver);
|
||||||
if (!ImGui::Begin("GPU", nullptr))
|
if (!ImGui::Begin("GPU", nullptr))
|
||||||
|
|
|
@ -75,7 +75,7 @@ public:
|
||||||
|
|
||||||
virtual GPURenderer GetRendererType() const = 0;
|
virtual GPURenderer GetRendererType() const = 0;
|
||||||
|
|
||||||
virtual bool Initialize(HostDisplay* host_display);
|
virtual bool Initialize();
|
||||||
virtual void Reset(bool clear_vram);
|
virtual void Reset(bool clear_vram);
|
||||||
virtual bool DoState(StateWrapper& sw, HostDisplayTexture** save_to_texture, bool update_display);
|
virtual bool DoState(StateWrapper& sw, HostDisplayTexture** save_to_texture, bool update_display);
|
||||||
|
|
||||||
|
@ -319,8 +319,6 @@ protected:
|
||||||
AddCommandTicks(std::max(width, height));
|
AddCommandTicks(std::max(width, height));
|
||||||
}
|
}
|
||||||
|
|
||||||
HostDisplay* m_host_display = nullptr;
|
|
||||||
|
|
||||||
std::unique_ptr<TimingEvent> m_crtc_tick_event;
|
std::unique_ptr<TimingEvent> m_crtc_tick_event;
|
||||||
std::unique_ptr<TimingEvent> m_command_tick_event;
|
std::unique_ptr<TimingEvent> m_command_tick_event;
|
||||||
|
|
||||||
|
|
|
@ -173,7 +173,7 @@ void GPUBackend::StartGPUThread()
|
||||||
{
|
{
|
||||||
m_gpu_loop_done.store(false);
|
m_gpu_loop_done.store(false);
|
||||||
m_use_gpu_thread = true;
|
m_use_gpu_thread = true;
|
||||||
m_gpu_thread = std::thread(&GPUBackend::RunGPULoop, this);
|
m_gpu_thread.Start([this]() { RunGPULoop(); });
|
||||||
Log_InfoPrint("GPU thread started.");
|
Log_InfoPrint("GPU thread started.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +184,7 @@ void GPUBackend::StopGPUThread()
|
||||||
|
|
||||||
m_gpu_loop_done.store(true);
|
m_gpu_loop_done.store(true);
|
||||||
WakeGPUThread();
|
WakeGPUThread();
|
||||||
m_gpu_thread.join();
|
m_gpu_thread.Join();
|
||||||
m_use_gpu_thread = false;
|
m_use_gpu_thread = false;
|
||||||
Log_InfoPrint("GPU thread stopped.");
|
Log_InfoPrint("GPU thread stopped.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "common/event.h"
|
#include "common/event.h"
|
||||||
#include "common/heap_array.h"
|
#include "common/heap_array.h"
|
||||||
|
#include "common/threading.h"
|
||||||
#include "gpu_types.h"
|
#include "gpu_types.h"
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
|
@ -20,6 +21,7 @@ public:
|
||||||
virtual ~GPUBackend();
|
virtual ~GPUBackend();
|
||||||
|
|
||||||
ALWAYS_INLINE u16* GetVRAM() const { return m_vram_ptr; }
|
ALWAYS_INLINE u16* GetVRAM() const { return m_vram_ptr; }
|
||||||
|
ALWAYS_INLINE const Threading::Thread* GetThread() const { return m_use_gpu_thread ? &m_gpu_thread : nullptr; }
|
||||||
|
|
||||||
virtual bool Initialize(bool force_thread);
|
virtual bool Initialize(bool force_thread);
|
||||||
virtual void UpdateSettings();
|
virtual void UpdateSettings();
|
||||||
|
@ -67,7 +69,7 @@ protected:
|
||||||
Common::Event m_sync_event;
|
Common::Event m_sync_event;
|
||||||
std::atomic_bool m_gpu_thread_sleeping{false};
|
std::atomic_bool m_gpu_thread_sleeping{false};
|
||||||
std::atomic_bool m_gpu_loop_done{false};
|
std::atomic_bool m_gpu_loop_done{false};
|
||||||
std::thread m_gpu_thread;
|
Threading::Thread m_gpu_thread;
|
||||||
bool m_use_gpu_thread = false;
|
bool m_use_gpu_thread = false;
|
||||||
|
|
||||||
std::mutex m_sync_mutex;
|
std::mutex m_sync_mutex;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "cpu_core.h"
|
#include "cpu_core.h"
|
||||||
#include "gpu_sw_backend.h"
|
#include "gpu_sw_backend.h"
|
||||||
|
#include "host.h"
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "pgxp.h"
|
#include "pgxp.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
@ -43,14 +44,14 @@ GPU_HW::~GPU_HW()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPU_HW::Initialize(HostDisplay* host_display)
|
bool GPU_HW::Initialize()
|
||||||
{
|
{
|
||||||
if (!GPU::Initialize(host_display))
|
if (!GPU::Initialize())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_resolution_scale = CalculateResolutionScale();
|
m_resolution_scale = CalculateResolutionScale();
|
||||||
m_multisamples = std::min(g_settings.gpu_multisamples, m_max_multisamples);
|
m_multisamples = std::min(g_settings.gpu_multisamples, m_max_multisamples);
|
||||||
m_render_api = host_display->GetRenderAPI();
|
m_render_api = g_host_display->GetRenderAPI();
|
||||||
m_per_sample_shading = g_settings.gpu_per_sample_shading && m_supports_per_sample_shading;
|
m_per_sample_shading = g_settings.gpu_per_sample_shading && m_supports_per_sample_shading;
|
||||||
m_true_color = g_settings.gpu_true_color;
|
m_true_color = g_settings.gpu_true_color;
|
||||||
m_scaled_dithering = g_settings.gpu_scaled_dithering;
|
m_scaled_dithering = g_settings.gpu_scaled_dithering;
|
||||||
|
@ -61,29 +62,26 @@ bool GPU_HW::Initialize(HostDisplay* host_display)
|
||||||
|
|
||||||
if (m_multisamples != g_settings.gpu_multisamples)
|
if (m_multisamples != g_settings.gpu_multisamples)
|
||||||
{
|
{
|
||||||
g_host_interface->AddFormattedOSDMessage(
|
Host::AddFormattedOSDMessage(20.0f,
|
||||||
20.0f, g_host_interface->TranslateString("OSDMessage", "%ux MSAA is not supported, using %ux instead."),
|
Host::TranslateString("OSDMessage", "%ux MSAA is not supported, using %ux instead."),
|
||||||
g_settings.gpu_multisamples, m_multisamples);
|
g_settings.gpu_multisamples, m_multisamples);
|
||||||
}
|
}
|
||||||
if (!m_per_sample_shading && g_settings.gpu_per_sample_shading)
|
if (!m_per_sample_shading && g_settings.gpu_per_sample_shading)
|
||||||
{
|
{
|
||||||
g_host_interface->AddOSDMessage(
|
Host::AddOSDMessage(Host::TranslateStdString("OSDMessage", "SSAA is not supported, using MSAA instead."), 20.0f);
|
||||||
g_host_interface->TranslateStdString("OSDMessage", "SSAA is not supported, using MSAA instead."), 20.0f);
|
|
||||||
}
|
}
|
||||||
if (!m_supports_dual_source_blend && TextureFilterRequiresDualSourceBlend(m_texture_filtering))
|
if (!m_supports_dual_source_blend && TextureFilterRequiresDualSourceBlend(m_texture_filtering))
|
||||||
{
|
{
|
||||||
g_host_interface->AddFormattedOSDMessage(
|
Host::AddFormattedOSDMessage(
|
||||||
20.0f,
|
20.0f, Host::TranslateString("OSDMessage", "Texture filter '%s' is not supported with the current renderer."),
|
||||||
g_host_interface->TranslateString("OSDMessage",
|
|
||||||
"Texture filter '%s' is not supported with the current renderer."),
|
|
||||||
Settings::GetTextureFilterDisplayName(m_texture_filtering));
|
Settings::GetTextureFilterDisplayName(m_texture_filtering));
|
||||||
m_texture_filtering = GPUTextureFilter::Nearest;
|
m_texture_filtering = GPUTextureFilter::Nearest;
|
||||||
}
|
}
|
||||||
if (!m_supports_adaptive_downsampling && g_settings.gpu_resolution_scale > 1 &&
|
if (!m_supports_adaptive_downsampling && g_settings.gpu_resolution_scale > 1 &&
|
||||||
g_settings.gpu_downsample_mode == GPUDownsampleMode::Adaptive)
|
g_settings.gpu_downsample_mode == GPUDownsampleMode::Adaptive)
|
||||||
{
|
{
|
||||||
g_host_interface->AddOSDMessage(
|
Host::AddOSDMessage(
|
||||||
g_host_interface->TranslateStdString(
|
Host::TranslateStdString(
|
||||||
"OSDMessage", "Adaptive downsampling is not supported with the current renderer, using box filter instead."),
|
"OSDMessage", "Adaptive downsampling is not supported with the current renderer, using box filter instead."),
|
||||||
20.0f);
|
20.0f);
|
||||||
}
|
}
|
||||||
|
@ -149,27 +147,26 @@ void GPU_HW::UpdateHWSettings(bool* framebuffer_changed, bool* shaders_changed)
|
||||||
|
|
||||||
if (m_resolution_scale != resolution_scale)
|
if (m_resolution_scale != resolution_scale)
|
||||||
{
|
{
|
||||||
g_host_interface->AddKeyedFormattedOSDMessage(
|
Host::AddKeyedFormattedOSDMessage(
|
||||||
"ResolutionScale", 10.0f,
|
"ResolutionScale", 10.0f,
|
||||||
g_host_interface->TranslateString("OSDMessage", "Resolution scale set to %ux (display %ux%u, VRAM %ux%u)"),
|
Host::TranslateString("OSDMessage", "Resolution scale set to %ux (display %ux%u, VRAM %ux%u)"), resolution_scale,
|
||||||
resolution_scale, m_crtc_state.display_vram_width * resolution_scale,
|
m_crtc_state.display_vram_width * resolution_scale, resolution_scale * m_crtc_state.display_vram_height,
|
||||||
resolution_scale * m_crtc_state.display_vram_height, VRAM_WIDTH * resolution_scale,
|
VRAM_WIDTH * resolution_scale, VRAM_HEIGHT * resolution_scale);
|
||||||
VRAM_HEIGHT * resolution_scale);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_multisamples != multisamples || m_per_sample_shading != per_sample_shading)
|
if (m_multisamples != multisamples || m_per_sample_shading != per_sample_shading)
|
||||||
{
|
{
|
||||||
if (per_sample_shading)
|
if (per_sample_shading)
|
||||||
{
|
{
|
||||||
g_host_interface->AddKeyedFormattedOSDMessage(
|
Host::AddKeyedFormattedOSDMessage(
|
||||||
"Multisampling", 10.0f,
|
"Multisampling", 10.0f, Host::TranslateString("OSDMessage", "Multisample anti-aliasing set to %ux (SSAA)."),
|
||||||
g_host_interface->TranslateString("OSDMessage", "Multisample anti-aliasing set to %ux (SSAA)."), multisamples);
|
multisamples);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_host_interface->AddKeyedFormattedOSDMessage(
|
Host::AddKeyedFormattedOSDMessage("Multisampling", 10.0f,
|
||||||
"Multisampling", 10.0f,
|
Host::TranslateString("OSDMessage", "Multisample anti-aliasing set to %ux."),
|
||||||
g_host_interface->TranslateString("OSDMessage", "Multisample anti-aliasing set to %ux."), multisamples);
|
multisamples);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +212,7 @@ u32 GPU_HW::CalculateResolutionScale() const
|
||||||
(m_console_is_pal ? (PAL_VERTICAL_ACTIVE_END - PAL_VERTICAL_ACTIVE_START) :
|
(m_console_is_pal ? (PAL_VERTICAL_ACTIVE_END - PAL_VERTICAL_ACTIVE_START) :
|
||||||
(NTSC_VERTICAL_ACTIVE_END - NTSC_VERTICAL_ACTIVE_START));
|
(NTSC_VERTICAL_ACTIVE_END - NTSC_VERTICAL_ACTIVE_START));
|
||||||
const s32 preferred_scale =
|
const s32 preferred_scale =
|
||||||
static_cast<s32>(std::ceil(static_cast<float>(m_host_display->GetWindowHeight()) / height));
|
static_cast<s32>(std::ceil(static_cast<float>(g_host_display->GetWindowHeight()) / height));
|
||||||
Log_InfoPrintf("Height = %d, preferred scale = %d", height, preferred_scale);
|
Log_InfoPrintf("Height = %d, preferred scale = %d", height, preferred_scale);
|
||||||
|
|
||||||
scale = static_cast<u32>(std::clamp<s32>(preferred_scale, 1, m_max_resolution_scale));
|
scale = static_cast<u32>(std::clamp<s32>(preferred_scale, 1, m_max_resolution_scale));
|
||||||
|
@ -229,10 +226,9 @@ u32 GPU_HW::CalculateResolutionScale() const
|
||||||
|
|
||||||
if (g_settings.gpu_resolution_scale != 0)
|
if (g_settings.gpu_resolution_scale != 0)
|
||||||
{
|
{
|
||||||
g_host_interface->AddFormattedOSDMessage(
|
Host::AddFormattedOSDMessage(
|
||||||
10.0f,
|
10.0f,
|
||||||
g_host_interface->TranslateString("OSDMessage",
|
Host::TranslateString("OSDMessage", "Resolution scale %ux not supported for adaptive smoothing, using %ux."),
|
||||||
"Resolution scale %ux not supported for adaptive smoothing, using %ux."),
|
|
||||||
scale, new_scale);
|
scale, new_scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1410,7 +1406,7 @@ void GPU_HW::DrawRendererStats(bool is_idle_frame)
|
||||||
const auto& stats = m_last_renderer_stats;
|
const auto& stats = m_last_renderer_stats;
|
||||||
|
|
||||||
ImGui::Columns(2);
|
ImGui::Columns(2);
|
||||||
ImGui::SetColumnWidth(0, 200.0f * ImGui::GetIO().DisplayFramebufferScale.x);
|
ImGui::SetColumnWidth(0, 200.0f * Host::GetOSDScale());
|
||||||
|
|
||||||
ImGui::TextUnformatted("Resolution Scale:");
|
ImGui::TextUnformatted("Resolution Scale:");
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
|
@ -1487,7 +1483,7 @@ void GPU_HW::ShaderCompileProgressTracker::Increment()
|
||||||
const u64 tv = Common::Timer::GetCurrentValue();
|
const u64 tv = Common::Timer::GetCurrentValue();
|
||||||
if ((tv - m_start_time) >= m_min_time && (tv - m_last_update_time) >= m_update_interval)
|
if ((tv - m_start_time) >= m_min_time && (tv - m_last_update_time) >= m_update_interval)
|
||||||
{
|
{
|
||||||
g_host_interface->DisplayLoadingScreen(m_title.c_str(), 0, static_cast<int>(m_total), static_cast<int>(m_progress));
|
Host::DisplayLoadingScreen(m_title.c_str(), 0, static_cast<int>(m_total), static_cast<int>(m_progress));
|
||||||
m_last_update_time = tv;
|
m_last_update_time = tv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ public:
|
||||||
GPU_HW();
|
GPU_HW();
|
||||||
virtual ~GPU_HW();
|
virtual ~GPU_HW();
|
||||||
|
|
||||||
virtual bool Initialize(HostDisplay* host_display) override;
|
virtual bool Initialize() override;
|
||||||
virtual void Reset(bool clear_vram) override;
|
virtual void Reset(bool clear_vram) override;
|
||||||
virtual bool DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display) override;
|
virtual bool DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display) override;
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include "gpu_hw_shadergen.h"
|
#include "gpu_hw_shadergen.h"
|
||||||
#include "gpu_sw_backend.h"
|
#include "gpu_sw_backend.h"
|
||||||
#include "host_display.h"
|
#include "host_display.h"
|
||||||
#include "host_interface.h"
|
|
||||||
#include "shader_cache_version.h"
|
#include "shader_cache_version.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "util/state_wrapper.h"
|
#include "util/state_wrapper.h"
|
||||||
|
@ -16,8 +15,11 @@ GPU_HW_D3D11::GPU_HW_D3D11() = default;
|
||||||
|
|
||||||
GPU_HW_D3D11::~GPU_HW_D3D11()
|
GPU_HW_D3D11::~GPU_HW_D3D11()
|
||||||
{
|
{
|
||||||
if (m_host_display)
|
if (g_host_display)
|
||||||
m_host_display->ClearDisplayTexture();
|
{
|
||||||
|
g_host_display->ClearDisplayTexture();
|
||||||
|
ResetGraphicsAPIState();
|
||||||
|
}
|
||||||
|
|
||||||
if (m_context)
|
if (m_context)
|
||||||
m_context->ClearState();
|
m_context->ClearState();
|
||||||
|
@ -31,22 +33,22 @@ GPURenderer GPU_HW_D3D11::GetRendererType() const
|
||||||
return GPURenderer::HardwareD3D11;
|
return GPURenderer::HardwareD3D11;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPU_HW_D3D11::Initialize(HostDisplay* host_display)
|
bool GPU_HW_D3D11::Initialize()
|
||||||
{
|
{
|
||||||
if (host_display->GetRenderAPI() != HostDisplay::RenderAPI::D3D11)
|
if (!Host::AcquireHostDisplay(HostDisplay::RenderAPI::D3D11))
|
||||||
{
|
{
|
||||||
Log_ErrorPrintf("Host render API is incompatible");
|
Log_ErrorPrintf("Host render API is incompatible");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_device = static_cast<ID3D11Device*>(host_display->GetRenderDevice());
|
m_device = static_cast<ID3D11Device*>(g_host_display->GetRenderDevice());
|
||||||
m_context = static_cast<ID3D11DeviceContext*>(host_display->GetRenderContext());
|
m_context = static_cast<ID3D11DeviceContext*>(g_host_display->GetRenderContext());
|
||||||
if (!m_device || !m_context)
|
if (!m_device || !m_context)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
SetCapabilities();
|
SetCapabilities();
|
||||||
|
|
||||||
if (!GPU_HW::Initialize(host_display))
|
if (!GPU_HW::Initialize())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!CreateFramebuffer())
|
if (!CreateFramebuffer())
|
||||||
|
@ -122,7 +124,7 @@ bool GPU_HW_D3D11::DoState(StateWrapper& sw, HostDisplayTexture** host_texture,
|
||||||
{
|
{
|
||||||
delete tex;
|
delete tex;
|
||||||
|
|
||||||
tex = m_host_display
|
tex = g_host_display
|
||||||
->CreateTexture(m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1, 1,
|
->CreateTexture(m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1, 1,
|
||||||
m_vram_texture.GetSamples(), HostDisplayPixelFormat::RGBA8, nullptr, 0, false)
|
m_vram_texture.GetSamples(), HostDisplayPixelFormat::RGBA8, nullptr, 0, false)
|
||||||
.release();
|
.release();
|
||||||
|
@ -178,7 +180,7 @@ void GPU_HW_D3D11::UpdateSettings()
|
||||||
RestoreGraphicsAPIState();
|
RestoreGraphicsAPIState();
|
||||||
ReadVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT);
|
ReadVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT);
|
||||||
ResetGraphicsAPIState();
|
ResetGraphicsAPIState();
|
||||||
m_host_display->ClearDisplayTexture();
|
g_host_display->ClearDisplayTexture();
|
||||||
CreateFramebuffer();
|
CreateFramebuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,10 +503,10 @@ void GPU_HW_D3D11::DestroyStateObjects()
|
||||||
bool GPU_HW_D3D11::CompileShaders()
|
bool GPU_HW_D3D11::CompileShaders()
|
||||||
{
|
{
|
||||||
D3D11::ShaderCache shader_cache;
|
D3D11::ShaderCache shader_cache;
|
||||||
shader_cache.Open(g_host_interface->GetShaderCacheBasePath(), m_device->GetFeatureLevel(), SHADER_CACHE_VERSION,
|
shader_cache.Open(EmuFolders::Cache, m_device->GetFeatureLevel(), SHADER_CACHE_VERSION,
|
||||||
g_settings.gpu_use_debug_device);
|
g_settings.gpu_use_debug_device);
|
||||||
|
|
||||||
GPU_HW_ShaderGen shadergen(m_host_display->GetRenderAPI(), m_resolution_scale, m_multisamples, m_per_sample_shading,
|
GPU_HW_ShaderGen shadergen(g_host_display->GetRenderAPI(), m_resolution_scale, m_multisamples, m_per_sample_shading,
|
||||||
m_true_color, m_scaled_dithering, m_texture_filtering, m_using_uv_limits,
|
m_true_color, m_scaled_dithering, m_texture_filtering, m_using_uv_limits,
|
||||||
m_pgxp_depth_buffer, m_supports_dual_source_blend);
|
m_pgxp_depth_buffer, m_supports_dual_source_blend);
|
||||||
|
|
||||||
|
@ -826,7 +828,7 @@ void GPU_HW_D3D11::ClearDisplay()
|
||||||
{
|
{
|
||||||
GPU_HW::ClearDisplay();
|
GPU_HW::ClearDisplay();
|
||||||
|
|
||||||
m_host_display->ClearDisplayTexture();
|
g_host_display->ClearDisplayTexture();
|
||||||
|
|
||||||
static constexpr std::array<float, 4> clear_color = {0.0f, 0.0f, 0.0f, 1.0f};
|
static constexpr std::array<float, 4> clear_color = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||||
m_context->ClearRenderTargetView(m_display_texture.GetD3DRTV(), clear_color.data());
|
m_context->ClearRenderTargetView(m_display_texture.GetD3DRTV(), clear_color.data());
|
||||||
|
@ -841,23 +843,23 @@ void GPU_HW_D3D11::UpdateDisplay()
|
||||||
if (IsUsingMultisampling())
|
if (IsUsingMultisampling())
|
||||||
{
|
{
|
||||||
UpdateVRAMReadTexture();
|
UpdateVRAMReadTexture();
|
||||||
m_host_display->SetDisplayTexture(m_vram_read_texture.GetD3DSRV(), HostDisplayPixelFormat::RGBA8,
|
g_host_display->SetDisplayTexture(m_vram_read_texture.GetD3DSRV(), HostDisplayPixelFormat::RGBA8,
|
||||||
m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight(), 0, 0,
|
m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight(), 0, 0,
|
||||||
m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight());
|
m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayTexture(m_vram_texture.GetD3DSRV(), HostDisplayPixelFormat::RGBA8,
|
g_host_display->SetDisplayTexture(m_vram_texture.GetD3DSRV(), HostDisplayPixelFormat::RGBA8,
|
||||||
m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 0, 0,
|
m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 0, 0,
|
||||||
m_vram_texture.GetWidth(), m_vram_texture.GetHeight());
|
m_vram_texture.GetWidth(), m_vram_texture.GetHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
|
g_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
|
||||||
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
|
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayParameters(m_crtc_state.display_width, m_crtc_state.display_height,
|
g_host_display->SetDisplayParameters(m_crtc_state.display_width, m_crtc_state.display_height,
|
||||||
m_crtc_state.display_origin_left, m_crtc_state.display_origin_top,
|
m_crtc_state.display_origin_left, m_crtc_state.display_origin_top,
|
||||||
m_crtc_state.display_vram_width, m_crtc_state.display_vram_height,
|
m_crtc_state.display_vram_width, m_crtc_state.display_vram_height,
|
||||||
GetDisplayAspectRatio());
|
GetDisplayAspectRatio());
|
||||||
|
@ -875,7 +877,7 @@ void GPU_HW_D3D11::UpdateDisplay()
|
||||||
|
|
||||||
if (IsDisplayDisabled())
|
if (IsDisplayDisabled())
|
||||||
{
|
{
|
||||||
m_host_display->ClearDisplayTexture();
|
g_host_display->ClearDisplayTexture();
|
||||||
}
|
}
|
||||||
else if (!m_GPUSTAT.display_area_color_depth_24 && interlaced == InterlacedRenderMode::None &&
|
else if (!m_GPUSTAT.display_area_color_depth_24 && interlaced == InterlacedRenderMode::None &&
|
||||||
!IsUsingMultisampling() && (scaled_vram_offset_x + scaled_display_width) <= m_vram_texture.GetWidth() &&
|
!IsUsingMultisampling() && (scaled_vram_offset_x + scaled_display_width) <= m_vram_texture.GetWidth() &&
|
||||||
|
@ -889,7 +891,7 @@ void GPU_HW_D3D11::UpdateDisplay()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayTexture(m_vram_texture.GetD3DSRV(), HostDisplayPixelFormat::RGBA8,
|
g_host_display->SetDisplayTexture(m_vram_texture.GetD3DSRV(), HostDisplayPixelFormat::RGBA8,
|
||||||
m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), scaled_vram_offset_x,
|
m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), scaled_vram_offset_x,
|
||||||
scaled_vram_offset_y, scaled_display_width, scaled_display_height);
|
scaled_vram_offset_y, scaled_display_width, scaled_display_height);
|
||||||
}
|
}
|
||||||
|
@ -921,7 +923,7 @@ void GPU_HW_D3D11::UpdateDisplay()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayTexture(m_display_texture.GetD3DSRV(), HostDisplayPixelFormat::RGBA8,
|
g_host_display->SetDisplayTexture(m_display_texture.GetD3DSRV(), HostDisplayPixelFormat::RGBA8,
|
||||||
m_display_texture.GetWidth(), m_display_texture.GetHeight(), 0, 0,
|
m_display_texture.GetWidth(), m_display_texture.GetHeight(), 0, 0,
|
||||||
scaled_display_width, scaled_display_height);
|
scaled_display_width, scaled_display_height);
|
||||||
}
|
}
|
||||||
|
@ -1202,7 +1204,7 @@ void GPU_HW_D3D11::DownsampleFramebufferAdaptive(D3D11::Texture& source, u32 lef
|
||||||
|
|
||||||
RestoreGraphicsAPIState();
|
RestoreGraphicsAPIState();
|
||||||
|
|
||||||
m_host_display->SetDisplayTexture(m_display_texture.GetD3DSRV(), HostDisplayPixelFormat::RGBA8,
|
g_host_display->SetDisplayTexture(m_display_texture.GetD3DSRV(), HostDisplayPixelFormat::RGBA8,
|
||||||
m_display_texture.GetWidth(), m_display_texture.GetHeight(), left, top, width,
|
m_display_texture.GetWidth(), m_display_texture.GetHeight(), left, top, width,
|
||||||
height);
|
height);
|
||||||
}
|
}
|
||||||
|
@ -1227,7 +1229,7 @@ void GPU_HW_D3D11::DownsampleFramebufferBoxFilter(D3D11::Texture& source, u32 le
|
||||||
|
|
||||||
RestoreGraphicsAPIState();
|
RestoreGraphicsAPIState();
|
||||||
|
|
||||||
m_host_display->SetDisplayTexture(m_downsample_texture.GetD3DSRV(), HostDisplayPixelFormat::RGBA8,
|
g_host_display->SetDisplayTexture(m_downsample_texture.GetD3DSRV(), HostDisplayPixelFormat::RGBA8,
|
||||||
m_downsample_texture.GetWidth(), m_downsample_texture.GetHeight(), ds_left, ds_top,
|
m_downsample_texture.GetWidth(), m_downsample_texture.GetHeight(), ds_left, ds_top,
|
||||||
ds_width, ds_height);
|
ds_width, ds_height);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ public:
|
||||||
|
|
||||||
GPURenderer GetRendererType() const override;
|
GPURenderer GetRendererType() const override;
|
||||||
|
|
||||||
bool Initialize(HostDisplay* host_display) override;
|
bool Initialize() override;
|
||||||
void Reset(bool clear_vram) override;
|
void Reset(bool clear_vram) override;
|
||||||
bool DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display) override;
|
bool DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display) override;
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#include "common/timer.h"
|
#include "common/timer.h"
|
||||||
#include "gpu_hw_shadergen.h"
|
#include "gpu_hw_shadergen.h"
|
||||||
#include "host_display.h"
|
#include "host_display.h"
|
||||||
#include "host_interface.h"
|
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
Log_SetChannel(GPU_HW_D3D12);
|
Log_SetChannel(GPU_HW_D3D12);
|
||||||
|
|
||||||
|
@ -19,9 +18,9 @@ GPU_HW_D3D12::GPU_HW_D3D12() = default;
|
||||||
|
|
||||||
GPU_HW_D3D12::~GPU_HW_D3D12()
|
GPU_HW_D3D12::~GPU_HW_D3D12()
|
||||||
{
|
{
|
||||||
if (m_host_display)
|
if (g_host_display)
|
||||||
{
|
{
|
||||||
m_host_display->ClearDisplayTexture();
|
g_host_display->ClearDisplayTexture();
|
||||||
ResetGraphicsAPIState();
|
ResetGraphicsAPIState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,9 +32,9 @@ GPURenderer GPU_HW_D3D12::GetRendererType() const
|
||||||
return GPURenderer::HardwareD3D12;
|
return GPURenderer::HardwareD3D12;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPU_HW_D3D12::Initialize(HostDisplay* host_display)
|
bool GPU_HW_D3D12::Initialize()
|
||||||
{
|
{
|
||||||
if (host_display->GetRenderAPI() != HostDisplay::RenderAPI::D3D12)
|
if (!Host::AcquireHostDisplay(HostDisplay::RenderAPI::D3D12))
|
||||||
{
|
{
|
||||||
Log_ErrorPrintf("Host render API is incompatible");
|
Log_ErrorPrintf("Host render API is incompatible");
|
||||||
return false;
|
return false;
|
||||||
|
@ -43,7 +42,7 @@ bool GPU_HW_D3D12::Initialize(HostDisplay* host_display)
|
||||||
|
|
||||||
SetCapabilities();
|
SetCapabilities();
|
||||||
|
|
||||||
if (!GPU_HW::Initialize(host_display))
|
if (!GPU_HW::Initialize())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!CreateRootSignatures())
|
if (!CreateRootSignatures())
|
||||||
|
@ -144,7 +143,7 @@ void GPU_HW_D3D12::UpdateSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Everything should be finished executing before recreating resources.
|
// Everything should be finished executing before recreating resources.
|
||||||
m_host_display->ClearDisplayTexture();
|
g_host_display->ClearDisplayTexture();
|
||||||
g_d3d12_context->ExecuteCommandList(true);
|
g_d3d12_context->ExecuteCommandList(true);
|
||||||
|
|
||||||
if (framebuffer_changed)
|
if (framebuffer_changed)
|
||||||
|
@ -413,10 +412,9 @@ bool GPU_HW_D3D12::CreateTextureBuffer()
|
||||||
bool GPU_HW_D3D12::CompilePipelines()
|
bool GPU_HW_D3D12::CompilePipelines()
|
||||||
{
|
{
|
||||||
D3D12::ShaderCache shader_cache;
|
D3D12::ShaderCache shader_cache;
|
||||||
shader_cache.Open(g_host_interface->GetShaderCacheBasePath(), g_d3d12_context->GetFeatureLevel(),
|
shader_cache.Open(EmuFolders::Cache, g_d3d12_context->GetFeatureLevel(), g_settings.gpu_use_debug_device);
|
||||||
g_settings.gpu_use_debug_device);
|
|
||||||
|
|
||||||
GPU_HW_ShaderGen shadergen(m_host_display->GetRenderAPI(), m_resolution_scale, m_multisamples, m_per_sample_shading,
|
GPU_HW_ShaderGen shadergen(g_host_display->GetRenderAPI(), m_resolution_scale, m_multisamples, m_per_sample_shading,
|
||||||
m_true_color, m_scaled_dithering, m_texture_filtering, m_using_uv_limits,
|
m_true_color, m_scaled_dithering, m_texture_filtering, m_using_uv_limits,
|
||||||
m_pgxp_depth_buffer, m_supports_dual_source_blend);
|
m_pgxp_depth_buffer, m_supports_dual_source_blend);
|
||||||
|
|
||||||
|
@ -852,7 +850,7 @@ void GPU_HW_D3D12::ClearDisplay()
|
||||||
{
|
{
|
||||||
GPU_HW::ClearDisplay();
|
GPU_HW::ClearDisplay();
|
||||||
|
|
||||||
m_host_display->ClearDisplayTexture();
|
g_host_display->ClearDisplayTexture();
|
||||||
|
|
||||||
static constexpr float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
|
static constexpr float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||||
m_display_texture.TransitionToState(D3D12_RESOURCE_STATE_RENDER_TARGET);
|
m_display_texture.TransitionToState(D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||||
|
@ -869,23 +867,23 @@ void GPU_HW_D3D12::UpdateDisplay()
|
||||||
if (IsUsingMultisampling())
|
if (IsUsingMultisampling())
|
||||||
{
|
{
|
||||||
UpdateVRAMReadTexture();
|
UpdateVRAMReadTexture();
|
||||||
m_host_display->SetDisplayTexture(&m_vram_read_texture, HostDisplayPixelFormat::RGBA8,
|
g_host_display->SetDisplayTexture(&m_vram_read_texture, HostDisplayPixelFormat::RGBA8,
|
||||||
m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight(), 0, 0,
|
m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight(), 0, 0,
|
||||||
m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight());
|
m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_vram_texture.TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
m_vram_texture.TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||||
m_host_display->SetDisplayTexture(&m_vram_texture, HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(),
|
g_host_display->SetDisplayTexture(&m_vram_texture, HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(),
|
||||||
m_vram_texture.GetHeight(), 0, 0, m_vram_texture.GetWidth(),
|
m_vram_texture.GetHeight(), 0, 0, m_vram_texture.GetWidth(),
|
||||||
m_vram_texture.GetHeight());
|
m_vram_texture.GetHeight());
|
||||||
}
|
}
|
||||||
m_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
|
g_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
|
||||||
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
|
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayParameters(m_crtc_state.display_width, m_crtc_state.display_height,
|
g_host_display->SetDisplayParameters(m_crtc_state.display_width, m_crtc_state.display_height,
|
||||||
m_crtc_state.display_origin_left, m_crtc_state.display_origin_top,
|
m_crtc_state.display_origin_left, m_crtc_state.display_origin_top,
|
||||||
m_crtc_state.display_vram_width, m_crtc_state.display_vram_height,
|
m_crtc_state.display_vram_width, m_crtc_state.display_vram_height,
|
||||||
GetDisplayAspectRatio());
|
GetDisplayAspectRatio());
|
||||||
|
@ -903,14 +901,14 @@ void GPU_HW_D3D12::UpdateDisplay()
|
||||||
|
|
||||||
if (IsDisplayDisabled())
|
if (IsDisplayDisabled())
|
||||||
{
|
{
|
||||||
m_host_display->ClearDisplayTexture();
|
g_host_display->ClearDisplayTexture();
|
||||||
}
|
}
|
||||||
else if (!m_GPUSTAT.display_area_color_depth_24 && interlaced == InterlacedRenderMode::None &&
|
else if (!m_GPUSTAT.display_area_color_depth_24 && interlaced == InterlacedRenderMode::None &&
|
||||||
!IsUsingMultisampling() && (scaled_vram_offset_x + scaled_display_width) <= m_vram_texture.GetWidth() &&
|
!IsUsingMultisampling() && (scaled_vram_offset_x + scaled_display_width) <= m_vram_texture.GetWidth() &&
|
||||||
(scaled_vram_offset_y + scaled_display_height) <= m_vram_texture.GetHeight())
|
(scaled_vram_offset_y + scaled_display_height) <= m_vram_texture.GetHeight())
|
||||||
{
|
{
|
||||||
m_vram_texture.TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
m_vram_texture.TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||||
m_host_display->SetDisplayTexture(&m_vram_texture, HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(),
|
g_host_display->SetDisplayTexture(&m_vram_texture, HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(),
|
||||||
m_vram_texture.GetHeight(), scaled_vram_offset_x, scaled_vram_offset_y,
|
m_vram_texture.GetHeight(), scaled_vram_offset_x, scaled_vram_offset_y,
|
||||||
scaled_display_width, scaled_display_height);
|
scaled_display_width, scaled_display_height);
|
||||||
}
|
}
|
||||||
|
@ -938,7 +936,7 @@ void GPU_HW_D3D12::UpdateDisplay()
|
||||||
m_display_texture.TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
m_display_texture.TransitionToState(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
|
||||||
m_vram_texture.TransitionToState(D3D12_RESOURCE_STATE_RENDER_TARGET);
|
m_vram_texture.TransitionToState(D3D12_RESOURCE_STATE_RENDER_TARGET);
|
||||||
|
|
||||||
m_host_display->SetDisplayTexture(&m_display_texture, HostDisplayPixelFormat::RGBA8, m_display_texture.GetWidth(),
|
g_host_display->SetDisplayTexture(&m_display_texture, HostDisplayPixelFormat::RGBA8, m_display_texture.GetWidth(),
|
||||||
m_display_texture.GetHeight(), 0, 0, scaled_display_width,
|
m_display_texture.GetHeight(), 0, 0, scaled_display_width,
|
||||||
scaled_display_height);
|
scaled_display_height);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ public:
|
||||||
|
|
||||||
GPURenderer GetRendererType() const override;
|
GPURenderer GetRendererType() const override;
|
||||||
|
|
||||||
bool Initialize(HostDisplay* host_display) override;
|
bool Initialize() override;
|
||||||
void Reset(bool clear_vram) override;
|
void Reset(bool clear_vram) override;
|
||||||
|
|
||||||
void ResetGraphicsAPIState() override;
|
void ResetGraphicsAPIState() override;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/timer.h"
|
#include "common/timer.h"
|
||||||
#include "gpu_hw_shadergen.h"
|
#include "gpu_hw_shadergen.h"
|
||||||
|
#include "host.h"
|
||||||
#include "host_display.h"
|
#include "host_display.h"
|
||||||
#include "shader_cache_version.h"
|
#include "shader_cache_version.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
@ -24,9 +25,9 @@ GPU_HW_OpenGL::~GPU_HW_OpenGL()
|
||||||
if (m_texture_buffer_r16ui_texture != 0)
|
if (m_texture_buffer_r16ui_texture != 0)
|
||||||
glDeleteTextures(1, &m_texture_buffer_r16ui_texture);
|
glDeleteTextures(1, &m_texture_buffer_r16ui_texture);
|
||||||
|
|
||||||
if (m_host_display)
|
if (g_host_display)
|
||||||
{
|
{
|
||||||
m_host_display->ClearDisplayTexture();
|
g_host_display->ClearDisplayTexture();
|
||||||
ResetGraphicsAPIState();
|
ResetGraphicsAPIState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,31 +41,30 @@ GPURenderer GPU_HW_OpenGL::GetRendererType() const
|
||||||
return GPURenderer::HardwareOpenGL;
|
return GPURenderer::HardwareOpenGL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPU_HW_OpenGL::Initialize(HostDisplay* host_display)
|
bool GPU_HW_OpenGL::Initialize()
|
||||||
{
|
{
|
||||||
if (host_display->GetRenderAPI() != HostDisplay::RenderAPI::OpenGL &&
|
if (!Host::AcquireHostDisplay(HostDisplay::RenderAPI::OpenGL))
|
||||||
host_display->GetRenderAPI() != HostDisplay::RenderAPI::OpenGLES)
|
|
||||||
{
|
{
|
||||||
Log_ErrorPrintf("Host render API type is incompatible");
|
Log_ErrorPrintf("Host render API type is incompatible");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool opengl_is_available =
|
const bool opengl_is_available =
|
||||||
((host_display->GetRenderAPI() == HostDisplay::RenderAPI::OpenGL &&
|
((g_host_display->GetRenderAPI() == HostDisplay::RenderAPI::OpenGL &&
|
||||||
(GLAD_GL_VERSION_3_0 || GLAD_GL_ARB_uniform_buffer_object)) ||
|
(GLAD_GL_VERSION_3_0 || GLAD_GL_ARB_uniform_buffer_object)) ||
|
||||||
(host_display->GetRenderAPI() == HostDisplay::RenderAPI::OpenGLES && GLAD_GL_ES_VERSION_3_0));
|
(g_host_display->GetRenderAPI() == HostDisplay::RenderAPI::OpenGLES && GLAD_GL_ES_VERSION_3_0));
|
||||||
if (!opengl_is_available)
|
if (!opengl_is_available)
|
||||||
{
|
{
|
||||||
g_host_interface->AddOSDMessage(
|
Host::AddOSDMessage(Host::TranslateStdString("OSDMessage",
|
||||||
g_host_interface->TranslateStdString("OSDMessage", "OpenGL renderer unavailable, your driver or hardware is not "
|
"OpenGL renderer unavailable, your driver or hardware is not "
|
||||||
"recent enough. OpenGL 3.1 or OpenGL ES 3.0 is required."),
|
"recent enough. OpenGL 3.1 or OpenGL ES 3.0 is required."),
|
||||||
20.0f);
|
20.0f);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SetCapabilities(host_display);
|
SetCapabilities();
|
||||||
|
|
||||||
if (!GPU_HW::Initialize(host_display))
|
if (!GPU_HW::Initialize())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!CreateFramebuffer())
|
if (!CreateFramebuffer())
|
||||||
|
@ -133,7 +133,7 @@ bool GPU_HW_OpenGL::DoState(StateWrapper& sw, HostDisplayTexture** host_texture,
|
||||||
{
|
{
|
||||||
delete tex;
|
delete tex;
|
||||||
|
|
||||||
tex = m_host_display
|
tex = g_host_display
|
||||||
->CreateTexture(m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1, 1,
|
->CreateTexture(m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1, 1,
|
||||||
m_vram_texture.GetSamples(), HostDisplayPixelFormat::RGBA8, nullptr, 0, false)
|
m_vram_texture.GetSamples(), HostDisplayPixelFormat::RGBA8, nullptr, 0, false)
|
||||||
.release();
|
.release();
|
||||||
|
@ -252,7 +252,7 @@ void GPU_HW_OpenGL::UpdateSettings()
|
||||||
RestoreGraphicsAPIState();
|
RestoreGraphicsAPIState();
|
||||||
ReadVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT);
|
ReadVRAM(0, 0, VRAM_WIDTH, VRAM_HEIGHT);
|
||||||
ResetGraphicsAPIState();
|
ResetGraphicsAPIState();
|
||||||
m_host_display->ClearDisplayTexture();
|
g_host_display->ClearDisplayTexture();
|
||||||
CreateFramebuffer();
|
CreateFramebuffer();
|
||||||
}
|
}
|
||||||
if (shaders_changed)
|
if (shaders_changed)
|
||||||
|
@ -297,7 +297,7 @@ std::tuple<s32, s32> GPU_HW_OpenGL::ConvertToFramebufferCoordinates(s32 x, s32 y
|
||||||
return std::make_tuple(x, static_cast<s32>(static_cast<s32>(VRAM_HEIGHT) - y));
|
return std::make_tuple(x, static_cast<s32>(static_cast<s32>(VRAM_HEIGHT) - y));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPU_HW_OpenGL::SetCapabilities(HostDisplay* host_display)
|
void GPU_HW_OpenGL::SetCapabilities()
|
||||||
{
|
{
|
||||||
GLint max_texture_size = VRAM_WIDTH;
|
GLint max_texture_size = VRAM_WIDTH;
|
||||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
|
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
|
||||||
|
@ -510,10 +510,10 @@ bool GPU_HW_OpenGL::CreateTextureBuffer()
|
||||||
bool GPU_HW_OpenGL::CompilePrograms()
|
bool GPU_HW_OpenGL::CompilePrograms()
|
||||||
{
|
{
|
||||||
GL::ShaderCache shader_cache;
|
GL::ShaderCache shader_cache;
|
||||||
shader_cache.Open(IsGLES(), g_host_interface->GetShaderCacheBasePath(), SHADER_CACHE_VERSION);
|
shader_cache.Open(IsGLES(), EmuFolders::Cache, SHADER_CACHE_VERSION);
|
||||||
|
|
||||||
const bool use_binding_layout = GPU_HW_ShaderGen::UseGLSLBindingLayout();
|
const bool use_binding_layout = GPU_HW_ShaderGen::UseGLSLBindingLayout();
|
||||||
GPU_HW_ShaderGen shadergen(m_host_display->GetRenderAPI(), m_resolution_scale, m_multisamples, m_per_sample_shading,
|
GPU_HW_ShaderGen shadergen(g_host_display->GetRenderAPI(), m_resolution_scale, m_multisamples, m_per_sample_shading,
|
||||||
m_true_color, m_scaled_dithering, m_texture_filtering, m_using_uv_limits,
|
m_true_color, m_scaled_dithering, m_texture_filtering, m_using_uv_limits,
|
||||||
m_pgxp_depth_buffer, m_supports_dual_source_blend);
|
m_pgxp_depth_buffer, m_supports_dual_source_blend);
|
||||||
|
|
||||||
|
@ -844,7 +844,7 @@ void GPU_HW_OpenGL::ClearDisplay()
|
||||||
{
|
{
|
||||||
GPU_HW::ClearDisplay();
|
GPU_HW::ClearDisplay();
|
||||||
|
|
||||||
m_host_display->ClearDisplayTexture();
|
g_host_display->ClearDisplayTexture();
|
||||||
|
|
||||||
m_display_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER);
|
m_display_texture.BindFramebuffer(GL_DRAW_FRAMEBUFFER);
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
@ -864,7 +864,7 @@ void GPU_HW_OpenGL::UpdateDisplay()
|
||||||
{
|
{
|
||||||
UpdateVRAMReadTexture();
|
UpdateVRAMReadTexture();
|
||||||
|
|
||||||
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_read_texture.GetGLId())),
|
g_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_read_texture.GetGLId())),
|
||||||
HostDisplayPixelFormat::RGBA8, m_vram_read_texture.GetWidth(),
|
HostDisplayPixelFormat::RGBA8, m_vram_read_texture.GetWidth(),
|
||||||
static_cast<s32>(m_vram_read_texture.GetHeight()), 0,
|
static_cast<s32>(m_vram_read_texture.GetHeight()), 0,
|
||||||
m_vram_read_texture.GetHeight(), m_vram_read_texture.GetWidth(),
|
m_vram_read_texture.GetHeight(), m_vram_read_texture.GetWidth(),
|
||||||
|
@ -872,17 +872,17 @@ void GPU_HW_OpenGL::UpdateDisplay()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_texture.GetGLId())),
|
g_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_texture.GetGLId())),
|
||||||
HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(),
|
HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(),
|
||||||
static_cast<s32>(m_vram_texture.GetHeight()), 0, m_vram_texture.GetHeight(),
|
static_cast<s32>(m_vram_texture.GetHeight()), 0, m_vram_texture.GetHeight(),
|
||||||
m_vram_texture.GetWidth(), -static_cast<s32>(m_vram_texture.GetHeight()));
|
m_vram_texture.GetWidth(), -static_cast<s32>(m_vram_texture.GetHeight()));
|
||||||
}
|
}
|
||||||
m_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
|
g_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
|
||||||
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
|
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayParameters(m_crtc_state.display_width, m_crtc_state.display_height,
|
g_host_display->SetDisplayParameters(m_crtc_state.display_width, m_crtc_state.display_height,
|
||||||
m_crtc_state.display_origin_left, m_crtc_state.display_origin_top,
|
m_crtc_state.display_origin_left, m_crtc_state.display_origin_top,
|
||||||
m_crtc_state.display_vram_width, m_crtc_state.display_vram_height,
|
m_crtc_state.display_vram_width, m_crtc_state.display_vram_height,
|
||||||
GetDisplayAspectRatio());
|
GetDisplayAspectRatio());
|
||||||
|
@ -900,7 +900,7 @@ void GPU_HW_OpenGL::UpdateDisplay()
|
||||||
|
|
||||||
if (IsDisplayDisabled())
|
if (IsDisplayDisabled())
|
||||||
{
|
{
|
||||||
m_host_display->ClearDisplayTexture();
|
g_host_display->ClearDisplayTexture();
|
||||||
}
|
}
|
||||||
else if (!m_GPUSTAT.display_area_color_depth_24 && interlaced == GPU_HW::InterlacedRenderMode::None &&
|
else if (!m_GPUSTAT.display_area_color_depth_24 && interlaced == GPU_HW::InterlacedRenderMode::None &&
|
||||||
!IsUsingMultisampling() && (scaled_vram_offset_x + scaled_display_width) <= m_vram_texture.GetWidth() &&
|
!IsUsingMultisampling() && (scaled_vram_offset_x + scaled_display_width) <= m_vram_texture.GetWidth() &&
|
||||||
|
@ -913,7 +913,7 @@ void GPU_HW_OpenGL::UpdateDisplay()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_texture.GetGLId())),
|
g_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_vram_texture.GetGLId())),
|
||||||
HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(),
|
HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(),
|
||||||
m_vram_texture.GetHeight(), scaled_vram_offset_x,
|
m_vram_texture.GetHeight(), scaled_vram_offset_x,
|
||||||
m_vram_texture.GetHeight() - scaled_vram_offset_y, scaled_display_width,
|
m_vram_texture.GetHeight() - scaled_vram_offset_y, scaled_display_width,
|
||||||
|
@ -960,7 +960,7 @@ void GPU_HW_OpenGL::UpdateDisplay()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_display_texture.GetGLId())),
|
g_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_display_texture.GetGLId())),
|
||||||
HostDisplayPixelFormat::RGBA8, m_display_texture.GetWidth(),
|
HostDisplayPixelFormat::RGBA8, m_display_texture.GetWidth(),
|
||||||
m_display_texture.GetHeight(), 0, scaled_display_height, scaled_display_width,
|
m_display_texture.GetHeight(), 0, scaled_display_height, scaled_display_width,
|
||||||
-static_cast<s32>(scaled_display_height));
|
-static_cast<s32>(scaled_display_height));
|
||||||
|
@ -1353,7 +1353,7 @@ void GPU_HW_OpenGL::DownsampleFramebufferBoxFilter(GL::Texture& source, u32 left
|
||||||
|
|
||||||
RestoreGraphicsAPIState();
|
RestoreGraphicsAPIState();
|
||||||
|
|
||||||
m_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_downsample_texture.GetGLId())),
|
g_host_display->SetDisplayTexture(reinterpret_cast<void*>(static_cast<uintptr_t>(m_downsample_texture.GetGLId())),
|
||||||
HostDisplayPixelFormat::RGBA8, m_downsample_texture.GetWidth(),
|
HostDisplayPixelFormat::RGBA8, m_downsample_texture.GetWidth(),
|
||||||
m_downsample_texture.GetHeight(), ds_left,
|
m_downsample_texture.GetHeight(), ds_left,
|
||||||
m_downsample_texture.GetHeight() - ds_top, ds_width, -static_cast<s32>(ds_height));
|
m_downsample_texture.GetHeight() - ds_top, ds_width, -static_cast<s32>(ds_height));
|
||||||
|
|
|
@ -18,7 +18,7 @@ public:
|
||||||
|
|
||||||
GPURenderer GetRendererType() const override;
|
GPURenderer GetRendererType() const override;
|
||||||
|
|
||||||
bool Initialize(HostDisplay* host_display) override;
|
bool Initialize() override;
|
||||||
void Reset(bool clear_vram) override;
|
void Reset(bool clear_vram) override;
|
||||||
bool DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display) override;
|
bool DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display) override;
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ private:
|
||||||
|
|
||||||
std::tuple<s32, s32> ConvertToFramebufferCoordinates(s32 x, s32 y);
|
std::tuple<s32, s32> ConvertToFramebufferCoordinates(s32 x, s32 y);
|
||||||
|
|
||||||
void SetCapabilities(HostDisplay* host_display);
|
void SetCapabilities();
|
||||||
bool CreateFramebuffer();
|
bool CreateFramebuffer();
|
||||||
void ClearFramebuffer();
|
void ClearFramebuffer();
|
||||||
void CopyFramebufferForState(GLenum target, GLuint src_texture, u32 src_fbo, u32 src_x, u32 src_y, GLuint dst_texture,
|
void CopyFramebufferForState(GLenum target, GLuint src_texture, u32 src_fbo, u32 src_x, u32 src_y, GLuint dst_texture,
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include "common/vulkan/util.h"
|
#include "common/vulkan/util.h"
|
||||||
#include "gpu_hw_shadergen.h"
|
#include "gpu_hw_shadergen.h"
|
||||||
#include "host_display.h"
|
#include "host_display.h"
|
||||||
#include "host_interface.h"
|
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "util/state_wrapper.h"
|
#include "util/state_wrapper.h"
|
||||||
Log_SetChannel(GPU_HW_Vulkan);
|
Log_SetChannel(GPU_HW_Vulkan);
|
||||||
|
@ -18,9 +17,9 @@ GPU_HW_Vulkan::GPU_HW_Vulkan() = default;
|
||||||
|
|
||||||
GPU_HW_Vulkan::~GPU_HW_Vulkan()
|
GPU_HW_Vulkan::~GPU_HW_Vulkan()
|
||||||
{
|
{
|
||||||
if (m_host_display)
|
if (g_host_display)
|
||||||
{
|
{
|
||||||
m_host_display->ClearDisplayTexture();
|
g_host_display->ClearDisplayTexture();
|
||||||
ResetGraphicsAPIState();
|
ResetGraphicsAPIState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,9 +31,9 @@ GPURenderer GPU_HW_Vulkan::GetRendererType() const
|
||||||
return GPURenderer::HardwareVulkan;
|
return GPURenderer::HardwareVulkan;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPU_HW_Vulkan::Initialize(HostDisplay* host_display)
|
bool GPU_HW_Vulkan::Initialize()
|
||||||
{
|
{
|
||||||
if (host_display->GetRenderAPI() != HostDisplay::RenderAPI::Vulkan)
|
if (!Host::AcquireHostDisplay(HostDisplay::RenderAPI::Vulkan))
|
||||||
{
|
{
|
||||||
Log_ErrorPrintf("Host render API is incompatible");
|
Log_ErrorPrintf("Host render API is incompatible");
|
||||||
return false;
|
return false;
|
||||||
|
@ -43,7 +42,7 @@ bool GPU_HW_Vulkan::Initialize(HostDisplay* host_display)
|
||||||
Assert(g_vulkan_shader_cache);
|
Assert(g_vulkan_shader_cache);
|
||||||
SetCapabilities();
|
SetCapabilities();
|
||||||
|
|
||||||
if (!GPU_HW::Initialize(host_display))
|
if (!GPU_HW::Initialize())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!CreatePipelineLayouts())
|
if (!CreatePipelineLayouts())
|
||||||
|
@ -144,7 +143,7 @@ bool GPU_HW_Vulkan::DoState(StateWrapper& sw, HostDisplayTexture** host_texture,
|
||||||
{
|
{
|
||||||
delete htex;
|
delete htex;
|
||||||
|
|
||||||
htex = m_host_display
|
htex = g_host_display
|
||||||
->CreateTexture(m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1, 1,
|
->CreateTexture(m_vram_texture.GetWidth(), m_vram_texture.GetHeight(), 1, 1,
|
||||||
m_vram_texture.GetSamples(), HostDisplayPixelFormat::RGBA8, nullptr, 0, false)
|
m_vram_texture.GetSamples(), HostDisplayPixelFormat::RGBA8, nullptr, 0, false)
|
||||||
.release();
|
.release();
|
||||||
|
@ -179,7 +178,7 @@ void GPU_HW_Vulkan::ResetGraphicsAPIState()
|
||||||
|
|
||||||
EndRenderPass();
|
EndRenderPass();
|
||||||
|
|
||||||
if (m_host_display->GetDisplayTextureHandle() == &m_vram_texture)
|
if (g_host_display->GetDisplayTextureHandle() == &m_vram_texture)
|
||||||
{
|
{
|
||||||
m_vram_texture.TransitionToLayout(g_vulkan_context->GetCurrentCommandBuffer(),
|
m_vram_texture.TransitionToLayout(g_vulkan_context->GetCurrentCommandBuffer(),
|
||||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||||
|
@ -218,7 +217,7 @@ void GPU_HW_Vulkan::UpdateSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Everything should be finished executing before recreating resources.
|
// Everything should be finished executing before recreating resources.
|
||||||
m_host_display->ClearDisplayTexture();
|
g_host_display->ClearDisplayTexture();
|
||||||
g_vulkan_context->ExecuteCommandBuffer(true);
|
g_vulkan_context->ExecuteCommandBuffer(true);
|
||||||
|
|
||||||
if (framebuffer_changed)
|
if (framebuffer_changed)
|
||||||
|
@ -923,7 +922,7 @@ bool GPU_HW_Vulkan::CompilePipelines()
|
||||||
VkDevice device = g_vulkan_context->GetDevice();
|
VkDevice device = g_vulkan_context->GetDevice();
|
||||||
VkPipelineCache pipeline_cache = g_vulkan_shader_cache->GetPipelineCache();
|
VkPipelineCache pipeline_cache = g_vulkan_shader_cache->GetPipelineCache();
|
||||||
|
|
||||||
GPU_HW_ShaderGen shadergen(m_host_display->GetRenderAPI(), m_resolution_scale, m_multisamples, m_per_sample_shading,
|
GPU_HW_ShaderGen shadergen(g_host_display->GetRenderAPI(), m_resolution_scale, m_multisamples, m_per_sample_shading,
|
||||||
m_true_color, m_scaled_dithering, m_texture_filtering, m_using_uv_limits,
|
m_true_color, m_scaled_dithering, m_texture_filtering, m_using_uv_limits,
|
||||||
m_pgxp_depth_buffer, m_supports_dual_source_blend);
|
m_pgxp_depth_buffer, m_supports_dual_source_blend);
|
||||||
|
|
||||||
|
@ -1405,7 +1404,7 @@ void GPU_HW_Vulkan::ClearDisplay()
|
||||||
GPU_HW::ClearDisplay();
|
GPU_HW::ClearDisplay();
|
||||||
EndRenderPass();
|
EndRenderPass();
|
||||||
|
|
||||||
m_host_display->ClearDisplayTexture();
|
g_host_display->ClearDisplayTexture();
|
||||||
|
|
||||||
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
|
VkCommandBuffer cmdbuf = g_vulkan_context->GetCurrentCommandBuffer();
|
||||||
const Vulkan::Util::DebugScope debugScope(cmdbuf, "GPU_HW_Vulkan::ClearDisplay");
|
const Vulkan::Util::DebugScope debugScope(cmdbuf, "GPU_HW_Vulkan::ClearDisplay");
|
||||||
|
@ -1435,22 +1434,22 @@ void GPU_HW_Vulkan::UpdateDisplay()
|
||||||
UpdateVRAMReadTexture();
|
UpdateVRAMReadTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_host_display->SetDisplayTexture(&m_vram_read_texture, HostDisplayPixelFormat::RGBA8,
|
g_host_display->SetDisplayTexture(&m_vram_read_texture, HostDisplayPixelFormat::RGBA8,
|
||||||
m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight(), 0, 0,
|
m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight(), 0, 0,
|
||||||
m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight());
|
m_vram_read_texture.GetWidth(), m_vram_read_texture.GetHeight());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayTexture(&m_vram_texture, HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(),
|
g_host_display->SetDisplayTexture(&m_vram_texture, HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(),
|
||||||
m_vram_texture.GetHeight(), 0, 0, m_vram_texture.GetWidth(),
|
m_vram_texture.GetHeight(), 0, 0, m_vram_texture.GetWidth(),
|
||||||
m_vram_texture.GetHeight());
|
m_vram_texture.GetHeight());
|
||||||
}
|
}
|
||||||
m_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
|
g_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
|
||||||
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
|
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayParameters(m_crtc_state.display_width, m_crtc_state.display_height,
|
g_host_display->SetDisplayParameters(m_crtc_state.display_width, m_crtc_state.display_height,
|
||||||
m_crtc_state.display_origin_left, m_crtc_state.display_origin_top,
|
m_crtc_state.display_origin_left, m_crtc_state.display_origin_top,
|
||||||
m_crtc_state.display_vram_width, m_crtc_state.display_vram_height,
|
m_crtc_state.display_vram_width, m_crtc_state.display_vram_height,
|
||||||
GetDisplayAspectRatio());
|
GetDisplayAspectRatio());
|
||||||
|
@ -1468,7 +1467,7 @@ void GPU_HW_Vulkan::UpdateDisplay()
|
||||||
|
|
||||||
if (IsDisplayDisabled())
|
if (IsDisplayDisabled())
|
||||||
{
|
{
|
||||||
m_host_display->ClearDisplayTexture();
|
g_host_display->ClearDisplayTexture();
|
||||||
}
|
}
|
||||||
else if (!m_GPUSTAT.display_area_color_depth_24 && interlaced == InterlacedRenderMode::None &&
|
else if (!m_GPUSTAT.display_area_color_depth_24 && interlaced == InterlacedRenderMode::None &&
|
||||||
!IsUsingMultisampling() && (scaled_vram_offset_x + scaled_display_width) <= m_vram_texture.GetWidth() &&
|
!IsUsingMultisampling() && (scaled_vram_offset_x + scaled_display_width) <= m_vram_texture.GetWidth() &&
|
||||||
|
@ -1481,7 +1480,7 @@ void GPU_HW_Vulkan::UpdateDisplay()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayTexture(&m_vram_texture, HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(),
|
g_host_display->SetDisplayTexture(&m_vram_texture, HostDisplayPixelFormat::RGBA8, m_vram_texture.GetWidth(),
|
||||||
m_vram_texture.GetHeight(), scaled_vram_offset_x, scaled_vram_offset_y,
|
m_vram_texture.GetHeight(), scaled_vram_offset_x, scaled_vram_offset_y,
|
||||||
scaled_display_width, scaled_display_height);
|
scaled_display_width, scaled_display_height);
|
||||||
}
|
}
|
||||||
|
@ -1528,7 +1527,7 @@ void GPU_HW_Vulkan::UpdateDisplay()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayTexture(&m_display_texture, HostDisplayPixelFormat::RGBA8,
|
g_host_display->SetDisplayTexture(&m_display_texture, HostDisplayPixelFormat::RGBA8,
|
||||||
m_display_texture.GetWidth(), m_display_texture.GetHeight(), 0, 0,
|
m_display_texture.GetWidth(), m_display_texture.GetHeight(), 0, 0,
|
||||||
scaled_display_width, scaled_display_height);
|
scaled_display_width, scaled_display_height);
|
||||||
RestoreGraphicsAPIState();
|
RestoreGraphicsAPIState();
|
||||||
|
@ -1938,7 +1937,7 @@ void GPU_HW_Vulkan::DownsampleFramebufferBoxFilter(Vulkan::Texture& source, u32
|
||||||
|
|
||||||
RestoreGraphicsAPIState();
|
RestoreGraphicsAPIState();
|
||||||
|
|
||||||
m_host_display->SetDisplayTexture(&m_downsample_texture, HostDisplayPixelFormat::RGBA8,
|
g_host_display->SetDisplayTexture(&m_downsample_texture, HostDisplayPixelFormat::RGBA8,
|
||||||
m_downsample_texture.GetWidth(), m_downsample_texture.GetHeight(), ds_left, ds_top,
|
m_downsample_texture.GetWidth(), m_downsample_texture.GetHeight(), ds_left, ds_top,
|
||||||
ds_width, ds_height);
|
ds_width, ds_height);
|
||||||
}
|
}
|
||||||
|
@ -2037,7 +2036,7 @@ void GPU_HW_Vulkan::DownsampleFramebufferAdaptive(Vulkan::Texture& source, u32 l
|
||||||
}
|
}
|
||||||
RestoreGraphicsAPIState();
|
RestoreGraphicsAPIState();
|
||||||
|
|
||||||
m_host_display->SetDisplayTexture(&m_display_texture, HostDisplayPixelFormat::RGBA8, m_display_texture.GetWidth(),
|
g_host_display->SetDisplayTexture(&m_display_texture, HostDisplayPixelFormat::RGBA8, m_display_texture.GetWidth(),
|
||||||
m_display_texture.GetHeight(), left, top, width, height);
|
m_display_texture.GetHeight(), left, top, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ public:
|
||||||
|
|
||||||
GPURenderer GetRendererType() const override;
|
GPURenderer GetRendererType() const override;
|
||||||
|
|
||||||
bool Initialize(HostDisplay* host_display) override;
|
bool Initialize() override;
|
||||||
void Reset(bool clear_vram) override;
|
void Reset(bool clear_vram) override;
|
||||||
bool DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display) override;
|
bool DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display) override;
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,8 @@ GPU_SW::GPU_SW()
|
||||||
GPU_SW::~GPU_SW()
|
GPU_SW::~GPU_SW()
|
||||||
{
|
{
|
||||||
m_backend.Shutdown();
|
m_backend.Shutdown();
|
||||||
if (m_host_display)
|
if (g_host_display)
|
||||||
m_host_display->ClearDisplayTexture();
|
g_host_display->ClearDisplayTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
GPURenderer GPU_SW::GetRendererType() const
|
GPURenderer GPU_SW::GetRendererType() const
|
||||||
|
@ -45,9 +45,13 @@ GPURenderer GPU_SW::GetRendererType() const
|
||||||
return GPURenderer::Software;
|
return GPURenderer::Software;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GPU_SW::Initialize(HostDisplay* host_display)
|
bool GPU_SW::Initialize()
|
||||||
{
|
{
|
||||||
if (!GPU::Initialize(host_display) || !m_backend.Initialize(false))
|
// we need something to draw in.. but keep the current api if we have one
|
||||||
|
if (!g_host_display && !Host::AcquireHostDisplay(HostDisplay::GetPreferredAPI()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!GPU::Initialize() || !m_backend.Initialize(false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
static constexpr auto formats_for_16bit = make_array(HostDisplayPixelFormat::RGB565, HostDisplayPixelFormat::RGBA5551,
|
static constexpr auto formats_for_16bit = make_array(HostDisplayPixelFormat::RGB565, HostDisplayPixelFormat::RGBA5551,
|
||||||
|
@ -57,7 +61,7 @@ bool GPU_SW::Initialize(HostDisplay* host_display)
|
||||||
HostDisplayPixelFormat::RGBA5551);
|
HostDisplayPixelFormat::RGBA5551);
|
||||||
for (const HostDisplayPixelFormat format : formats_for_16bit)
|
for (const HostDisplayPixelFormat format : formats_for_16bit)
|
||||||
{
|
{
|
||||||
if (m_host_display->SupportsDisplayPixelFormat(format))
|
if (g_host_display->SupportsDisplayPixelFormat(format))
|
||||||
{
|
{
|
||||||
m_16bit_display_format = format;
|
m_16bit_display_format = format;
|
||||||
break;
|
break;
|
||||||
|
@ -65,7 +69,7 @@ bool GPU_SW::Initialize(HostDisplay* host_display)
|
||||||
}
|
}
|
||||||
for (const HostDisplayPixelFormat format : formats_for_24bit)
|
for (const HostDisplayPixelFormat format : formats_for_24bit)
|
||||||
{
|
{
|
||||||
if (m_host_display->SupportsDisplayPixelFormat(format))
|
if (g_host_display->SupportsDisplayPixelFormat(format))
|
||||||
{
|
{
|
||||||
m_24bit_display_format = format;
|
m_24bit_display_format = format;
|
||||||
break;
|
break;
|
||||||
|
@ -233,7 +237,7 @@ void GPU_SW::CopyOut15Bit(u32 src_x, u32 src_y, u32 width, u32 height, u32 field
|
||||||
|
|
||||||
if (!interlaced)
|
if (!interlaced)
|
||||||
{
|
{
|
||||||
if (!m_host_display->BeginSetDisplayPixels(display_format, width, height, reinterpret_cast<void**>(&dst_ptr),
|
if (!g_host_display->BeginSetDisplayPixels(display_format, width, height, reinterpret_cast<void**>(&dst_ptr),
|
||||||
&dst_stride))
|
&dst_stride))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -285,11 +289,11 @@ void GPU_SW::CopyOut15Bit(u32 src_x, u32 src_y, u32 width, u32 height, u32 field
|
||||||
|
|
||||||
if (!interlaced)
|
if (!interlaced)
|
||||||
{
|
{
|
||||||
m_host_display->EndSetDisplayPixels();
|
g_host_display->EndSetDisplayPixels();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayPixels(display_format, width, height, m_display_texture_buffer.data(), output_stride);
|
g_host_display->SetDisplayPixels(display_format, width, height, m_display_texture_buffer.data(), output_stride);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,7 +331,7 @@ void GPU_SW::CopyOut24Bit(u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 heigh
|
||||||
|
|
||||||
if (!interlaced)
|
if (!interlaced)
|
||||||
{
|
{
|
||||||
if (!m_host_display->BeginSetDisplayPixels(display_format, width, height, reinterpret_cast<void**>(&dst_ptr),
|
if (!g_host_display->BeginSetDisplayPixels(display_format, width, height, reinterpret_cast<void**>(&dst_ptr),
|
||||||
&dst_stride))
|
&dst_stride))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -443,11 +447,11 @@ void GPU_SW::CopyOut24Bit(u32 src_x, u32 src_y, u32 skip_x, u32 width, u32 heigh
|
||||||
|
|
||||||
if (!interlaced)
|
if (!interlaced)
|
||||||
{
|
{
|
||||||
m_host_display->EndSetDisplayPixels();
|
g_host_display->EndSetDisplayPixels();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayPixels(display_format, width, height, m_display_texture_buffer.data(), output_stride);
|
g_host_display->SetDisplayPixels(display_format, width, height, m_display_texture_buffer.data(), output_stride);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,14 +490,14 @@ void GPU_SW::UpdateDisplay()
|
||||||
|
|
||||||
if (!g_settings.debugging.show_vram)
|
if (!g_settings.debugging.show_vram)
|
||||||
{
|
{
|
||||||
m_host_display->SetDisplayParameters(m_crtc_state.display_width, m_crtc_state.display_height,
|
g_host_display->SetDisplayParameters(m_crtc_state.display_width, m_crtc_state.display_height,
|
||||||
m_crtc_state.display_origin_left, m_crtc_state.display_origin_top,
|
m_crtc_state.display_origin_left, m_crtc_state.display_origin_top,
|
||||||
m_crtc_state.display_vram_width, m_crtc_state.display_vram_height,
|
m_crtc_state.display_vram_width, m_crtc_state.display_vram_height,
|
||||||
GetDisplayAspectRatio());
|
GetDisplayAspectRatio());
|
||||||
|
|
||||||
if (IsDisplayDisabled())
|
if (IsDisplayDisabled())
|
||||||
{
|
{
|
||||||
m_host_display->ClearDisplayTexture();
|
g_host_display->ClearDisplayTexture();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -534,7 +538,7 @@ void GPU_SW::UpdateDisplay()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CopyOut15Bit(m_16bit_display_format, 0, 0, VRAM_WIDTH, VRAM_HEIGHT, 0, false, false);
|
CopyOut15Bit(m_16bit_display_format, 0, 0, VRAM_WIDTH, VRAM_HEIGHT, 0, false, false);
|
||||||
m_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
|
g_host_display->SetDisplayParameters(VRAM_WIDTH, VRAM_HEIGHT, 0, 0, VRAM_WIDTH, VRAM_HEIGHT,
|
||||||
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
|
static_cast<float>(VRAM_WIDTH) / static_cast<float>(VRAM_HEIGHT));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,11 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
namespace Threading
|
||||||
|
{
|
||||||
|
class Thread;
|
||||||
|
}
|
||||||
|
|
||||||
class HostDisplayTexture;
|
class HostDisplayTexture;
|
||||||
|
|
||||||
class GPU_SW final : public GPU
|
class GPU_SW final : public GPU
|
||||||
|
@ -15,9 +20,11 @@ public:
|
||||||
GPU_SW();
|
GPU_SW();
|
||||||
~GPU_SW() override;
|
~GPU_SW() override;
|
||||||
|
|
||||||
|
ALWAYS_INLINE const GPU_SW_Backend& GetBackend() const { return m_backend; }
|
||||||
|
|
||||||
GPURenderer GetRendererType() const override;
|
GPURenderer GetRendererType() const override;
|
||||||
|
|
||||||
bool Initialize(HostDisplay* host_display) override;
|
bool Initialize() override;
|
||||||
bool DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display) override;
|
bool DoState(StateWrapper& sw, HostDisplayTexture** host_texture, bool update_display) override;
|
||||||
void Reset(bool clear_vram) override;
|
void Reset(bool clear_vram) override;
|
||||||
void UpdateSettings() override;
|
void UpdateSettings() override;
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include "cpu_core.h"
|
#include "cpu_core.h"
|
||||||
#include "cpu_core_private.h"
|
#include "cpu_core_private.h"
|
||||||
#include "host_display.h"
|
#include "host_display.h"
|
||||||
#include "host_interface.h"
|
|
||||||
#include "pgxp.h"
|
#include "pgxp.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "timing_event.h"
|
#include "timing_event.h"
|
||||||
|
@ -188,15 +187,14 @@ void UpdateAspectRatio()
|
||||||
{
|
{
|
||||||
case DisplayAspectRatio::MatchWindow:
|
case DisplayAspectRatio::MatchWindow:
|
||||||
{
|
{
|
||||||
const HostDisplay* display = g_host_interface->GetDisplay();
|
if (!g_host_display)
|
||||||
if (!display)
|
|
||||||
{
|
{
|
||||||
s_aspect_ratio = DisplayAspectRatio::R4_3;
|
s_aspect_ratio = DisplayAspectRatio::R4_3;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
num = display->GetWindowWidth();
|
num = g_host_display->GetWindowWidth();
|
||||||
denom = display->GetWindowHeight();
|
denom = g_host_display->GetWindowHeight();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
273
src/core/guncon.cpp
Normal file
|
@ -0,0 +1,273 @@
|
||||||
|
#include "guncon.h"
|
||||||
|
#include "common/assert.h"
|
||||||
|
#include "common/log.h"
|
||||||
|
#include "gpu.h"
|
||||||
|
#include "host.h"
|
||||||
|
#include "host_display.h"
|
||||||
|
#include "resources.h"
|
||||||
|
#include "system.h"
|
||||||
|
#include "util/state_wrapper.h"
|
||||||
|
#include <array>
|
||||||
|
Log_SetChannel(GunCon);
|
||||||
|
|
||||||
|
static constexpr std::array<u8, static_cast<size_t>(GunCon::Button::Count)> s_button_indices = {{13, 3, 14}};
|
||||||
|
|
||||||
|
GunCon::GunCon(u32 index) : Controller(index) {}
|
||||||
|
|
||||||
|
GunCon::~GunCon() = default;
|
||||||
|
|
||||||
|
ControllerType GunCon::GetType() const
|
||||||
|
{
|
||||||
|
return ControllerType::GunCon;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GunCon::Reset()
|
||||||
|
{
|
||||||
|
m_transfer_state = TransferState::Idle;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GunCon::DoState(StateWrapper& sw, bool apply_input_state)
|
||||||
|
{
|
||||||
|
if (!Controller::DoState(sw, apply_input_state))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
u16 button_state = m_button_state;
|
||||||
|
u16 position_x = m_position_x;
|
||||||
|
u16 position_y = m_position_y;
|
||||||
|
sw.Do(&button_state);
|
||||||
|
sw.Do(&position_x);
|
||||||
|
sw.Do(&position_y);
|
||||||
|
if (apply_input_state)
|
||||||
|
{
|
||||||
|
m_button_state = button_state;
|
||||||
|
m_position_x = position_x;
|
||||||
|
m_position_y = position_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
sw.Do(&m_transfer_state);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GunCon::GetBindState(u32 index) const
|
||||||
|
{
|
||||||
|
if (index >= s_button_indices.size())
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
const u32 bit = s_button_indices[index];
|
||||||
|
return static_cast<float>(((m_button_state >> bit) & 1u) ^ 1u);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GunCon::SetBindState(u32 index, float value)
|
||||||
|
{
|
||||||
|
const bool pressed = (value >= 0.5f);
|
||||||
|
if (index == static_cast<u32>(Button::ShootOffscreen))
|
||||||
|
{
|
||||||
|
if (m_shoot_offscreen != pressed)
|
||||||
|
{
|
||||||
|
m_shoot_offscreen = pressed;
|
||||||
|
SetBindState(static_cast<u32>(Button::Trigger), pressed);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pressed)
|
||||||
|
m_button_state &= ~(u16(1) << s_button_indices[static_cast<u8>(index)]);
|
||||||
|
else
|
||||||
|
m_button_state |= u16(1) << s_button_indices[static_cast<u8>(index)];
|
||||||
|
}
|
||||||
|
|
||||||
|
void GunCon::ResetTransferState()
|
||||||
|
{
|
||||||
|
m_transfer_state = TransferState::Idle;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GunCon::Transfer(const u8 data_in, u8* data_out)
|
||||||
|
{
|
||||||
|
static constexpr u16 ID = 0x5A63;
|
||||||
|
|
||||||
|
switch (m_transfer_state)
|
||||||
|
{
|
||||||
|
case TransferState::Idle:
|
||||||
|
{
|
||||||
|
*data_out = 0xFF;
|
||||||
|
|
||||||
|
if (data_in == 0x01)
|
||||||
|
{
|
||||||
|
m_transfer_state = TransferState::Ready;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TransferState::Ready:
|
||||||
|
{
|
||||||
|
if (data_in == 0x42)
|
||||||
|
{
|
||||||
|
*data_out = Truncate8(ID);
|
||||||
|
m_transfer_state = TransferState::IDMSB;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
*data_out = 0xFF;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TransferState::IDMSB:
|
||||||
|
{
|
||||||
|
*data_out = Truncate8(ID >> 8);
|
||||||
|
m_transfer_state = TransferState::ButtonsLSB;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TransferState::ButtonsLSB:
|
||||||
|
{
|
||||||
|
*data_out = Truncate8(m_button_state);
|
||||||
|
m_transfer_state = TransferState::ButtonsMSB;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TransferState::ButtonsMSB:
|
||||||
|
{
|
||||||
|
*data_out = Truncate8(m_button_state >> 8);
|
||||||
|
m_transfer_state = TransferState::XLSB;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TransferState::XLSB:
|
||||||
|
{
|
||||||
|
UpdatePosition();
|
||||||
|
*data_out = Truncate8(m_position_x);
|
||||||
|
m_transfer_state = TransferState::XMSB;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TransferState::XMSB:
|
||||||
|
{
|
||||||
|
*data_out = Truncate8(m_position_x >> 8);
|
||||||
|
m_transfer_state = TransferState::YLSB;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TransferState::YLSB:
|
||||||
|
{
|
||||||
|
*data_out = Truncate8(m_position_y);
|
||||||
|
m_transfer_state = TransferState::YMSB;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TransferState::YMSB:
|
||||||
|
{
|
||||||
|
*data_out = Truncate8(m_position_y >> 8);
|
||||||
|
m_transfer_state = TransferState::Idle;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
UnreachableCode();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GunCon::UpdatePosition()
|
||||||
|
{
|
||||||
|
// get screen coordinates
|
||||||
|
const s32 mouse_x = g_host_display->GetMousePositionX();
|
||||||
|
const s32 mouse_y = g_host_display->GetMousePositionY();
|
||||||
|
|
||||||
|
// are we within the active display area?
|
||||||
|
u32 tick, line;
|
||||||
|
if (mouse_x < 0 || mouse_y < 0 ||
|
||||||
|
!g_gpu->ConvertScreenCoordinatesToBeamTicksAndLines(mouse_x, mouse_y, m_x_scale, &tick, &line) ||
|
||||||
|
m_shoot_offscreen)
|
||||||
|
{
|
||||||
|
Log_DebugPrintf("Lightgun out of range for window coordinates %d,%d", mouse_x, mouse_y);
|
||||||
|
m_position_x = 0x01;
|
||||||
|
m_position_y = 0x0A;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 8MHz units for X = 44100*768*11/7 = 53222400 / 8000000 = 6.6528
|
||||||
|
const double divider = static_cast<double>(g_gpu->GetCRTCFrequency()) / 8000000.0;
|
||||||
|
m_position_x = static_cast<u16>(static_cast<float>(tick) / static_cast<float>(divider));
|
||||||
|
m_position_y = static_cast<u16>(line);
|
||||||
|
Log_DebugPrintf("Lightgun window coordinates %d,%d -> tick %u line %u 8mhz ticks %u", mouse_x, mouse_y, tick, line,
|
||||||
|
m_position_x);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<GunCon> GunCon::Create(u32 index)
|
||||||
|
{
|
||||||
|
return std::make_unique<GunCon>(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Controller::ControllerBindingInfo s_binding_info[] = {
|
||||||
|
#define BUTTON(name, display_name, button, genb) \
|
||||||
|
{ \
|
||||||
|
name, display_name, static_cast<u32>(button), Controller::ControllerBindingType::Button, genb \
|
||||||
|
}
|
||||||
|
|
||||||
|
BUTTON("Trigger", "Trigger", GunCon::Button::Trigger, GenericInputBinding::R2),
|
||||||
|
BUTTON("ShootOffscreen", "ShootOffscreen", GunCon::Button::ShootOffscreen, GenericInputBinding::L2),
|
||||||
|
BUTTON("A", "A", GunCon::Button::A, GenericInputBinding::Cross),
|
||||||
|
BUTTON("B", "B", GunCon::Button::B, GenericInputBinding::Circle),
|
||||||
|
|
||||||
|
#undef BUTTON
|
||||||
|
};
|
||||||
|
|
||||||
|
static const SettingInfo s_settings[] = {
|
||||||
|
{SettingInfo::Type::Path, "CrosshairImagePath", TRANSLATABLE("NamcoGunCon", "Crosshair Image Path"),
|
||||||
|
TRANSLATABLE("NamcoGunCon", "Path to an image to use as a crosshair/cursor.")},
|
||||||
|
{SettingInfo::Type::Float, "CrosshairScale", TRANSLATABLE("NamcoGunCon", "Crosshair Image Scale"),
|
||||||
|
TRANSLATABLE("NamcoGunCon", "Scale of crosshair image on screen."), "1.0", "0.0001", "100.0", "0.10"},
|
||||||
|
{SettingInfo::Type::Float, "XScale", TRANSLATABLE("NamcoGunCon", "X Scale"),
|
||||||
|
TRANSLATABLE("NamcoGunCon", "Scales X coordinates relative to the center of the screen."), "1.0", "0.01", "2.0",
|
||||||
|
"0.01"}};
|
||||||
|
|
||||||
|
const Controller::ControllerInfo GunCon::INFO = {ControllerType::GunCon,
|
||||||
|
"GunCon",
|
||||||
|
TRANSLATABLE("ControllerType", "GunCon"),
|
||||||
|
s_binding_info,
|
||||||
|
countof(s_binding_info),
|
||||||
|
s_settings,
|
||||||
|
countof(s_settings),
|
||||||
|
Controller::VibrationCapabilities::NoVibration};
|
||||||
|
|
||||||
|
void GunCon::LoadSettings(SettingsInterface& si, const char* section)
|
||||||
|
{
|
||||||
|
Controller::LoadSettings(si, section);
|
||||||
|
|
||||||
|
std::string path = si.GetStringValue(section, "CrosshairImagePath");
|
||||||
|
if (path != m_crosshair_image_path)
|
||||||
|
{
|
||||||
|
m_crosshair_image_path = std::move(path);
|
||||||
|
if (m_crosshair_image_path.empty() || !m_crosshair_image.LoadFromFile(m_crosshair_image_path.c_str()))
|
||||||
|
{
|
||||||
|
m_crosshair_image.Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef __ANDROID__
|
||||||
|
if (!m_crosshair_image.IsValid())
|
||||||
|
{
|
||||||
|
m_crosshair_image.SetPixels(Resources::CROSSHAIR_IMAGE_WIDTH, Resources::CROSSHAIR_IMAGE_HEIGHT,
|
||||||
|
Resources::CROSSHAIR_IMAGE_DATA.data());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
m_crosshair_image_scale = si.GetFloatValue(section, "CrosshairScale", 1.0f);
|
||||||
|
|
||||||
|
m_x_scale = si.GetFloatValue(section, "XScale", 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GunCon::GetSoftwareCursor(const Common::RGBA8Image** image, float* image_scale, bool* relative_mode)
|
||||||
|
{
|
||||||
|
if (!m_crosshair_image.IsValid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
*image = &m_crosshair_image;
|
||||||
|
*image_scale = m_crosshair_image_scale;
|
||||||
|
*relative_mode = false;
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
class NamcoGunCon final : public Controller
|
class GunCon final : public Controller
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum class Button : u8
|
enum class Button : u8
|
||||||
|
@ -16,34 +16,27 @@ public:
|
||||||
Count
|
Count
|
||||||
};
|
};
|
||||||
|
|
||||||
NamcoGunCon();
|
static const Controller::ControllerInfo INFO;
|
||||||
~NamcoGunCon() override;
|
|
||||||
|
|
||||||
static std::unique_ptr<NamcoGunCon> Create();
|
GunCon(u32 index);
|
||||||
static std::optional<s32> StaticGetAxisCodeByName(std::string_view button_name);
|
~GunCon() override;
|
||||||
static std::optional<s32> StaticGetButtonCodeByName(std::string_view button_name);
|
|
||||||
static AxisList StaticGetAxisNames();
|
static std::unique_ptr<GunCon> Create(u32 index);
|
||||||
static ButtonList StaticGetButtonNames();
|
|
||||||
static u32 StaticGetVibrationMotorCount();
|
|
||||||
static SettingList StaticGetSettings();
|
|
||||||
|
|
||||||
ControllerType GetType() const override;
|
ControllerType GetType() const override;
|
||||||
std::optional<s32> GetAxisCodeByName(std::string_view axis_name) const override;
|
|
||||||
std::optional<s32> GetButtonCodeByName(std::string_view button_name) const override;
|
|
||||||
|
|
||||||
void Reset() override;
|
void Reset() override;
|
||||||
bool DoState(StateWrapper& sw, bool apply_input_state) override;
|
bool DoState(StateWrapper& sw, bool apply_input_state) override;
|
||||||
void LoadSettings(const char* section) override;
|
|
||||||
|
void LoadSettings(SettingsInterface& si, const char* section) override;
|
||||||
bool GetSoftwareCursor(const Common::RGBA8Image** image, float* image_scale, bool* relative_mode) override;
|
bool GetSoftwareCursor(const Common::RGBA8Image** image, float* image_scale, bool* relative_mode) override;
|
||||||
|
|
||||||
bool GetButtonState(s32 button_code) const override;
|
float GetBindState(u32 index) const override;
|
||||||
void SetButtonState(s32 button_code, bool pressed) override;
|
void SetBindState(u32 index, float value) override;
|
||||||
|
|
||||||
void ResetTransferState() override;
|
void ResetTransferState() override;
|
||||||
bool Transfer(const u8 data_in, u8* data_out) override;
|
bool Transfer(const u8 data_in, u8* data_out) override;
|
||||||
|
|
||||||
void SetButtonState(Button button, bool pressed);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void UpdatePosition();
|
void UpdatePosition();
|
||||||
|
|
32
src/core/host.cpp
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#include "host.h"
|
||||||
|
#include "common/string_util.h"
|
||||||
|
#include <cstdarg>
|
||||||
|
|
||||||
|
void Host::ReportFormattedErrorAsync(const std::string_view& title, const char* format, ...)
|
||||||
|
{
|
||||||
|
std::va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
std::string message(StringUtil::StdStringFromFormatV(format, ap));
|
||||||
|
va_end(ap);
|
||||||
|
ReportErrorAsync(title, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Host::ConfirmFormattedMessage(const std::string_view& title, const char* format, ...)
|
||||||
|
{
|
||||||
|
std::va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
std::string message = StringUtil::StdStringFromFormatV(format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return ConfirmMessage(title, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Host::ReportFormattedDebuggerMessage(const char* format, ...)
|
||||||
|
{
|
||||||
|
std::va_list ap;
|
||||||
|
va_start(ap, format);
|
||||||
|
std::string message = StringUtil::StdStringFromFormatV(format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
ReportDebuggerMessage(message);
|
||||||
|
}
|
|
@ -1,12 +1,67 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/string.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
|
||||||
|
#include <ctime>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
struct WindowInfo;
|
||||||
|
enum class AudioBackend : u8;
|
||||||
|
class AudioStream;
|
||||||
|
class CDImage;
|
||||||
|
|
||||||
|
/// Marks a core string as being translatable.
|
||||||
|
#define TRANSLATABLE(context, str) str
|
||||||
|
|
||||||
|
/// Generic input bindings. These roughly match a DualShock 4 or XBox One controller.
|
||||||
|
/// They are used for automatic binding to PS2 controller types, and for big picture mode navigation.
|
||||||
|
enum class GenericInputBinding : u8
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
|
||||||
|
DPadUp,
|
||||||
|
DPadRight,
|
||||||
|
DPadLeft,
|
||||||
|
DPadDown,
|
||||||
|
|
||||||
|
LeftStickUp,
|
||||||
|
LeftStickRight,
|
||||||
|
LeftStickDown,
|
||||||
|
LeftStickLeft,
|
||||||
|
L3,
|
||||||
|
|
||||||
|
RightStickUp,
|
||||||
|
RightStickRight,
|
||||||
|
RightStickDown,
|
||||||
|
RightStickLeft,
|
||||||
|
R3,
|
||||||
|
|
||||||
|
Triangle, // Y on XBox pads.
|
||||||
|
Circle, // B on XBox pads.
|
||||||
|
Cross, // A on XBox pads.
|
||||||
|
Square, // X on XBox pads.
|
||||||
|
|
||||||
|
Select, // Share on DS4, View on XBox pads.
|
||||||
|
Start, // Options on DS4, Menu on XBox pads.
|
||||||
|
System, // PS button on DS4, Guide button on XBox pads.
|
||||||
|
|
||||||
|
L1, // LB on Xbox pads.
|
||||||
|
L2, // Left trigger on XBox pads.
|
||||||
|
R1, // RB on XBox pads.
|
||||||
|
R2, // Right trigger on Xbox pads.
|
||||||
|
|
||||||
|
SmallMotor, // High frequency vibration.
|
||||||
|
LargeMotor, // Low frequency vibration.
|
||||||
|
|
||||||
|
Count,
|
||||||
|
};
|
||||||
|
|
||||||
namespace Host {
|
namespace Host {
|
||||||
/// Reads a file from the resources directory of the application.
|
/// Reads a file from the resources directory of the application.
|
||||||
/// This may be outside of the "normal" filesystem on platforms such as Mac.
|
/// This may be outside of the "normal" filesystem on platforms such as Mac.
|
||||||
|
@ -15,6 +70,18 @@ std::optional<std::vector<u8>> ReadResourceFile(const char* filename);
|
||||||
/// Reads a resource file file from the resources directory as a string.
|
/// Reads a resource file file from the resources directory as a string.
|
||||||
std::optional<std::string> ReadResourceFileToString(const char* filename);
|
std::optional<std::string> ReadResourceFileToString(const char* filename);
|
||||||
|
|
||||||
|
/// Returns the modified time of a resource.
|
||||||
|
std::optional<std::time_t> GetResourceFileTimestamp(const char* filename);
|
||||||
|
|
||||||
|
/// Translates a string to the current language.
|
||||||
|
TinyString TranslateString(const char* context, const char* str, const char* disambiguation = nullptr, int n = -1);
|
||||||
|
std::string TranslateStdString(const char* context, const char* str, const char* disambiguation = nullptr, int n = -1);
|
||||||
|
|
||||||
|
std::unique_ptr<AudioStream> CreateAudioStream(AudioBackend backend);
|
||||||
|
|
||||||
|
/// Returns the scale of OSD elements.
|
||||||
|
float GetOSDScale();
|
||||||
|
|
||||||
/// Adds OSD messages, duration is in seconds.
|
/// Adds OSD messages, duration is in seconds.
|
||||||
void AddOSDMessage(std::string message, float duration = 2.0f);
|
void AddOSDMessage(std::string message, float duration = 2.0f);
|
||||||
void AddKeyedOSDMessage(std::string key, std::string message, float duration = 2.0f);
|
void AddKeyedOSDMessage(std::string key, std::string message, float duration = 2.0f);
|
||||||
|
@ -26,4 +93,26 @@ void ClearOSDMessages();
|
||||||
/// Displays an asynchronous error on the UI thread, i.e. doesn't block the caller.
|
/// Displays an asynchronous error on the UI thread, i.e. doesn't block the caller.
|
||||||
void ReportErrorAsync(const std::string_view& title, const std::string_view& message);
|
void ReportErrorAsync(const std::string_view& title, const std::string_view& message);
|
||||||
void ReportFormattedErrorAsync(const std::string_view& title, const char* format, ...);
|
void ReportFormattedErrorAsync(const std::string_view& title, const char* format, ...);
|
||||||
|
|
||||||
|
/// Displays a synchronous confirmation on the UI thread, i.e. blocks the caller.
|
||||||
|
bool ConfirmMessage(const std::string_view& title, const std::string_view& message);
|
||||||
|
bool ConfirmFormattedMessage(const std::string_view& title, const char* format, ...);
|
||||||
|
|
||||||
|
/// Debugger feedback.
|
||||||
|
void ReportDebuggerMessage(const std::string_view& message);
|
||||||
|
void ReportFormattedDebuggerMessage(const char* format, ...);
|
||||||
|
|
||||||
|
/// Displays a loading screen with the logo, rendered with ImGui. Use when executing possibly-time-consuming tasks
|
||||||
|
/// such as compiling shaders when starting up.
|
||||||
|
void DisplayLoadingScreen(const char* message, int progress_min = -1, int progress_max = -1, int progress_value = -1);
|
||||||
|
|
||||||
|
/// Internal method used by pads to dispatch vibration updates to input sources.
|
||||||
|
/// Intensity is normalized from 0 to 1.
|
||||||
|
void SetPadVibrationIntensity(u32 pad_index, float large_or_single_motor_intensity, float small_motor_intensity);
|
||||||
|
|
||||||
|
/// Enables "relative" mouse mode, locking the cursor position and returning relative coordinates.
|
||||||
|
void SetMouseMode(bool relative, bool hide_cursor);
|
||||||
|
|
||||||
|
/// Safely executes a function on the VM thread.
|
||||||
|
void RunOnCPUThread(std::function<void()> function, bool block = false);
|
||||||
} // namespace Host
|
} // namespace Host
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "common/timer.h"
|
#include "common/timer.h"
|
||||||
#include "host_interface.h"
|
|
||||||
#include "stb_image.h"
|
#include "stb_image.h"
|
||||||
#include "stb_image_resize.h"
|
#include "stb_image_resize.h"
|
||||||
#include "stb_image_write.h"
|
#include "stb_image_write.h"
|
||||||
|
@ -16,10 +15,72 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
Log_SetChannel(HostDisplay);
|
Log_SetChannel(HostDisplay);
|
||||||
|
|
||||||
|
std::unique_ptr<HostDisplay> g_host_display;
|
||||||
|
|
||||||
HostDisplayTexture::~HostDisplayTexture() = default;
|
HostDisplayTexture::~HostDisplayTexture() = default;
|
||||||
|
|
||||||
HostDisplay::~HostDisplay() = default;
|
HostDisplay::~HostDisplay() = default;
|
||||||
|
|
||||||
|
HostDisplay::RenderAPI HostDisplay::GetPreferredAPI()
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
return RenderAPI::D3D11;
|
||||||
|
#else
|
||||||
|
return RenderAPI::OpenGL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HostDisplay::ParseFullscreenMode(const std::string_view& mode, u32* width, u32* height, float* refresh_rate)
|
||||||
|
{
|
||||||
|
if (!mode.empty())
|
||||||
|
{
|
||||||
|
std::string_view::size_type sep1 = mode.find('x');
|
||||||
|
if (sep1 != std::string_view::npos)
|
||||||
|
{
|
||||||
|
std::optional<u32> owidth = StringUtil::FromChars<u32>(mode.substr(0, sep1));
|
||||||
|
sep1++;
|
||||||
|
|
||||||
|
while (sep1 < mode.length() && std::isspace(mode[sep1]))
|
||||||
|
sep1++;
|
||||||
|
|
||||||
|
if (owidth.has_value() && sep1 < mode.length())
|
||||||
|
{
|
||||||
|
std::string_view::size_type sep2 = mode.find('@', sep1);
|
||||||
|
if (sep2 != std::string_view::npos)
|
||||||
|
{
|
||||||
|
std::optional<u32> oheight = StringUtil::FromChars<u32>(mode.substr(sep1, sep2 - sep1));
|
||||||
|
sep2++;
|
||||||
|
|
||||||
|
while (sep2 < mode.length() && std::isspace(mode[sep2]))
|
||||||
|
sep2++;
|
||||||
|
|
||||||
|
if (oheight.has_value() && sep2 < mode.length())
|
||||||
|
{
|
||||||
|
std::optional<float> orefresh_rate = StringUtil::FromChars<float>(mode.substr(sep2));
|
||||||
|
if (orefresh_rate.has_value())
|
||||||
|
{
|
||||||
|
*width = owidth.value();
|
||||||
|
*height = oheight.value();
|
||||||
|
*refresh_rate = orefresh_rate.value();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*width = 0;
|
||||||
|
*height = 0;
|
||||||
|
*refresh_rate = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string HostDisplay::GetFullscreenModeString(u32 width, u32 height, float refresh_rate)
|
||||||
|
{
|
||||||
|
return StringUtil::StdStringFromFormat("%u x %u @ %f hz", width, height, refresh_rate);
|
||||||
|
}
|
||||||
|
|
||||||
bool HostDisplay::UsesLowerLeftOrigin() const
|
bool HostDisplay::UsesLowerLeftOrigin() const
|
||||||
{
|
{
|
||||||
const RenderAPI api = GetRenderAPI();
|
const RenderAPI api = GetRenderAPI();
|
||||||
|
|
|
@ -62,6 +62,15 @@ public:
|
||||||
|
|
||||||
virtual ~HostDisplay();
|
virtual ~HostDisplay();
|
||||||
|
|
||||||
|
/// Returns the default/preferred API for the system.
|
||||||
|
static RenderAPI GetPreferredAPI();
|
||||||
|
|
||||||
|
/// Parses a fullscreen mode into its components (width * height @ refresh hz)
|
||||||
|
static bool ParseFullscreenMode(const std::string_view& mode, u32* width, u32* height, float* refresh_rate);
|
||||||
|
|
||||||
|
/// Converts a fullscreen mode to a string.
|
||||||
|
static std::string GetFullscreenModeString(u32 width, u32 height, float refresh_rate);
|
||||||
|
|
||||||
ALWAYS_INLINE const WindowInfo& GetWindowInfo() const { return m_window_info; }
|
ALWAYS_INLINE const WindowInfo& GetWindowInfo() const { return m_window_info; }
|
||||||
ALWAYS_INLINE s32 GetWindowWidth() const { return static_cast<s32>(m_window_info.surface_width); }
|
ALWAYS_INLINE s32 GetWindowWidth() const { return static_cast<s32>(m_window_info.surface_width); }
|
||||||
ALWAYS_INLINE s32 GetWindowHeight() const { return static_cast<s32>(m_window_info.surface_height); }
|
ALWAYS_INLINE s32 GetWindowHeight() const { return static_cast<s32>(m_window_info.surface_height); }
|
||||||
|
@ -290,3 +299,25 @@ protected:
|
||||||
bool m_display_integer_scaling = false;
|
bool m_display_integer_scaling = false;
|
||||||
bool m_display_stretch = false;
|
bool m_display_stretch = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Returns a pointer to the current host display abstraction. Assumes AcquireHostDisplay() has been caled.
|
||||||
|
extern std::unique_ptr<HostDisplay> g_host_display;
|
||||||
|
|
||||||
|
namespace Host {
|
||||||
|
/// Creates the host display. This may create a new window. The API used depends on the current configuration.
|
||||||
|
bool AcquireHostDisplay(HostDisplay::RenderAPI api);
|
||||||
|
|
||||||
|
/// Destroys the host display. This may close the display window.
|
||||||
|
void ReleaseHostDisplay();
|
||||||
|
|
||||||
|
/// Returns false if the window was completely occluded. If frame_skip is set, the frame won't be
|
||||||
|
/// displayed, but the GPU command queue will still be flushed.
|
||||||
|
//bool BeginPresentFrame(bool frame_skip);
|
||||||
|
|
||||||
|
/// Presents the frame to the display, and renders OSD elements.
|
||||||
|
//void EndPresentFrame();
|
||||||
|
|
||||||
|
/// Provided by the host; renders the display.
|
||||||
|
void RenderDisplay();
|
||||||
|
void InvalidateDisplay();
|
||||||
|
} // namespace Host
|
||||||
|
|
|
@ -1,225 +0,0 @@
|
||||||
#pragma once
|
|
||||||
#include "common/string.h"
|
|
||||||
#include "common/timer.h"
|
|
||||||
#include "settings.h"
|
|
||||||
#include "types.h"
|
|
||||||
#include <chrono>
|
|
||||||
#include <deque>
|
|
||||||
#include <functional>
|
|
||||||
#include <memory>
|
|
||||||
#include <mutex>
|
|
||||||
#include <optional>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
enum LOGLEVEL;
|
|
||||||
|
|
||||||
class AudioStream;
|
|
||||||
class ByteStream;
|
|
||||||
class CDImage;
|
|
||||||
class HostDisplay;
|
|
||||||
class GameList;
|
|
||||||
|
|
||||||
struct SystemBootParameters;
|
|
||||||
|
|
||||||
namespace BIOS {
|
|
||||||
struct ImageInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
class HostInterface
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum : u32
|
|
||||||
{
|
|
||||||
AUDIO_SAMPLE_RATE = 44100,
|
|
||||||
AUDIO_CHANNELS = 2,
|
|
||||||
DEFAULT_AUDIO_BUFFER_SIZE = 2048
|
|
||||||
};
|
|
||||||
|
|
||||||
HostInterface();
|
|
||||||
virtual ~HostInterface();
|
|
||||||
|
|
||||||
/// Access to host display.
|
|
||||||
ALWAYS_INLINE HostDisplay* GetDisplay() const { return m_display.get(); }
|
|
||||||
ALWAYS_INLINE bool HasDisplay() const { return static_cast<bool>(m_display.get()); }
|
|
||||||
|
|
||||||
/// Access to host audio stream.
|
|
||||||
ALWAYS_INLINE AudioStream* GetAudioStream() const { return m_audio_stream.get(); }
|
|
||||||
|
|
||||||
/// Initializes the emulator frontend.
|
|
||||||
virtual bool Initialize();
|
|
||||||
|
|
||||||
/// Shuts down the emulator frontend.
|
|
||||||
virtual void Shutdown();
|
|
||||||
|
|
||||||
virtual bool BootSystem(std::shared_ptr<SystemBootParameters> parameters);
|
|
||||||
virtual void PauseSystem(bool paused);
|
|
||||||
virtual void ResetSystem();
|
|
||||||
virtual void DestroySystem();
|
|
||||||
|
|
||||||
/// Loads state from the specified filename.
|
|
||||||
bool LoadState(const char* filename);
|
|
||||||
|
|
||||||
virtual void ReportError(const char* message);
|
|
||||||
virtual void ReportMessage(const char* message);
|
|
||||||
virtual void ReportDebuggerMessage(const char* message);
|
|
||||||
virtual bool ConfirmMessage(const char* message);
|
|
||||||
|
|
||||||
void ReportFormattedError(const char* format, ...) printflike(2, 3);
|
|
||||||
void ReportFormattedMessage(const char* format, ...) printflike(2, 3);
|
|
||||||
void ReportFormattedDebuggerMessage(const char* format, ...) printflike(2, 3);
|
|
||||||
bool ConfirmFormattedMessage(const char* format, ...) printflike(2, 3);
|
|
||||||
|
|
||||||
/// Adds OSD messages, duration is in seconds.
|
|
||||||
virtual void AddOSDMessage(std::string message, float duration = 2.0f) = 0;
|
|
||||||
virtual void AddKeyedOSDMessage(std::string key, std::string message, float duration = 2.0f) = 0;
|
|
||||||
virtual void RemoveKeyedOSDMessage(std::string key) = 0;
|
|
||||||
void AddFormattedOSDMessage(float duration, const char* format, ...) printflike(3, 4);
|
|
||||||
void AddKeyedFormattedOSDMessage(std::string key, float duration, const char* format, ...) printflike(4, 5);
|
|
||||||
|
|
||||||
/// Returns the base user directory path.
|
|
||||||
ALWAYS_INLINE const std::string& GetUserDirectory() const { return m_user_directory; }
|
|
||||||
|
|
||||||
/// Returns a path relative to the user directory.
|
|
||||||
std::string GetUserDirectoryRelativePath(const char* format, ...) const printflike(2, 3);
|
|
||||||
|
|
||||||
/// Returns a path relative to the application directory (for system files).
|
|
||||||
std::string GetProgramDirectoryRelativePath(const char* format, ...) const printflike(2, 3);
|
|
||||||
|
|
||||||
/// Returns a string which can be used as part of a filename, based on the current date/time.
|
|
||||||
static TinyString GetTimestampStringForFileName();
|
|
||||||
|
|
||||||
/// Displays a loading screen with the logo, rendered with ImGui. Use when executing possibly-time-consuming tasks
|
|
||||||
/// such as compiling shaders when starting up.
|
|
||||||
virtual void DisplayLoadingScreen(const char* message, int progress_min = -1, int progress_max = -1,
|
|
||||||
int progress_value = -1) = 0;
|
|
||||||
|
|
||||||
/// Retrieves information about specified game from game list.
|
|
||||||
virtual void GetGameInfo(const char* path, CDImage* image, std::string* code, std::string* title) = 0;
|
|
||||||
|
|
||||||
/// Returns the directory where per-game memory cards will be saved.
|
|
||||||
virtual std::string GetMemoryCardDirectory() const;
|
|
||||||
|
|
||||||
/// Returns the default path to a memory card.
|
|
||||||
virtual std::string GetSharedMemoryCardPath(u32 slot) const;
|
|
||||||
|
|
||||||
/// Returns the default path to a memory card for a specific game.
|
|
||||||
virtual std::string GetGameMemoryCardPath(const char* game_code, u32 slot) const;
|
|
||||||
|
|
||||||
/// Returns the path to the shader cache directory.
|
|
||||||
virtual std::string GetShaderCacheBasePath() const;
|
|
||||||
|
|
||||||
/// Returns a setting value from the configuration.
|
|
||||||
virtual std::string GetStringSettingValue(const char* section, const char* key, const char* default_value = "") = 0;
|
|
||||||
|
|
||||||
/// Returns a boolean setting from the configuration.
|
|
||||||
virtual bool GetBoolSettingValue(const char* section, const char* key, bool default_value = false);
|
|
||||||
|
|
||||||
/// Returns an integer setting from the configuration.
|
|
||||||
virtual int GetIntSettingValue(const char* section, const char* key, int default_value = 0);
|
|
||||||
|
|
||||||
/// Returns a float setting from the configuration.
|
|
||||||
virtual float GetFloatSettingValue(const char* section, const char* key, float default_value = 0.0f);
|
|
||||||
|
|
||||||
/// Returns a string list from the configuration.
|
|
||||||
virtual std::vector<std::string> GetSettingStringList(const char* section, const char* key) = 0;
|
|
||||||
|
|
||||||
/// Returns the settings interface.
|
|
||||||
virtual SettingsInterface* GetSettingsInterface() = 0;
|
|
||||||
virtual std::lock_guard<std::recursive_mutex> GetSettingsLock() = 0;
|
|
||||||
|
|
||||||
/// Translates a string to the current language.
|
|
||||||
virtual TinyString TranslateString(const char* context, const char* str, const char* disambiguation = nullptr,
|
|
||||||
int n = -1) const;
|
|
||||||
virtual std::string TranslateStdString(const char* context, const char* str, const char* disambiguation = nullptr,
|
|
||||||
int n = -1) const;
|
|
||||||
|
|
||||||
/// Returns the path to the directory to search for BIOS images.
|
|
||||||
virtual std::string GetBIOSDirectory();
|
|
||||||
|
|
||||||
/// Loads the BIOS image for the specified region.
|
|
||||||
std::optional<std::vector<u8>> GetBIOSImage(ConsoleRegion region);
|
|
||||||
|
|
||||||
/// Searches for a BIOS image for the specified region in the specified directory. If no match is found, the first
|
|
||||||
/// BIOS image within 512KB and 4MB will be used.
|
|
||||||
std::optional<std::vector<u8>> FindBIOSImageInDirectory(ConsoleRegion region, const char* directory);
|
|
||||||
|
|
||||||
/// Returns a list of filenames and descriptions for BIOS images in a directory.
|
|
||||||
std::vector<std::pair<std::string, const BIOS::ImageInfo*>> FindBIOSImagesInDirectory(const char* directory);
|
|
||||||
|
|
||||||
/// Returns true if any BIOS images are found in the configured BIOS directory.
|
|
||||||
bool HasAnyBIOSImages();
|
|
||||||
|
|
||||||
/// Opens a file in the DuckStation "package".
|
|
||||||
/// This is the APK for Android builds, or the program directory for standalone builds.
|
|
||||||
virtual std::unique_ptr<ByteStream> OpenPackageFile(const char* path, u32 flags) = 0;
|
|
||||||
|
|
||||||
virtual void OnRunningGameChanged(const std::string& path, CDImage* image, const std::string& game_code,
|
|
||||||
const std::string& game_title) = 0;
|
|
||||||
virtual void OnSystemPerformanceCountersUpdated() = 0;
|
|
||||||
|
|
||||||
/// Called when the display is invalidated (e.g. a state is loaded).
|
|
||||||
virtual void OnDisplayInvalidated() = 0;
|
|
||||||
|
|
||||||
/// Called when achievements data is loaded.
|
|
||||||
virtual void OnAchievementsRefreshed() = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool AcquireHostDisplay() = 0;
|
|
||||||
virtual void ReleaseHostDisplay() = 0;
|
|
||||||
virtual std::unique_ptr<AudioStream> CreateAudioStream(AudioBackend backend) = 0;
|
|
||||||
virtual s32 GetAudioOutputVolume() const;
|
|
||||||
|
|
||||||
virtual void OnSystemCreated() = 0;
|
|
||||||
virtual void OnSystemPaused(bool paused) = 0;
|
|
||||||
virtual void OnSystemDestroyed() = 0;
|
|
||||||
virtual void OnControllerTypeChanged(u32 slot) = 0;
|
|
||||||
|
|
||||||
/// Restores all settings to defaults.
|
|
||||||
virtual void SetDefaultSettings(SettingsInterface& si);
|
|
||||||
|
|
||||||
/// Loads settings to m_settings and any frontend-specific parameters.
|
|
||||||
virtual void LoadSettings(SettingsInterface& si);
|
|
||||||
|
|
||||||
/// Saves current settings variables to ini.
|
|
||||||
virtual void SaveSettings(SettingsInterface& si);
|
|
||||||
|
|
||||||
/// Checks and fixes up any incompatible settings.
|
|
||||||
virtual void FixIncompatibleSettings(bool display_osd_messages);
|
|
||||||
|
|
||||||
/// Checks for settings changes, std::move() the old settings away for comparing beforehand.
|
|
||||||
virtual void CheckForSettingsChanges(const Settings& old_settings);
|
|
||||||
|
|
||||||
/// Switches the GPU renderer by saving state, recreating the display window, and restoring state (if needed).
|
|
||||||
virtual void RecreateSystem();
|
|
||||||
|
|
||||||
/// Enables "relative" mouse mode, locking the cursor position and returning relative coordinates.
|
|
||||||
virtual void SetMouseMode(bool relative, bool hide_cursor) = 0;
|
|
||||||
|
|
||||||
/// Call when host display size changes, use with "match display" aspect ratio setting.
|
|
||||||
virtual void OnHostDisplayResized();
|
|
||||||
|
|
||||||
/// Sets the user directory to the program directory, i.e. "portable mode".
|
|
||||||
void SetUserDirectoryToProgramDirectory();
|
|
||||||
|
|
||||||
/// Quick switch between software and hardware rendering.
|
|
||||||
void ToggleSoftwareRendering();
|
|
||||||
|
|
||||||
/// Adjusts the internal (render) resolution of the hardware backends.
|
|
||||||
void ModifyResolutionScale(s32 increment);
|
|
||||||
|
|
||||||
/// Updates software cursor state, based on controllers.
|
|
||||||
void UpdateSoftwareCursor();
|
|
||||||
|
|
||||||
bool SaveState(const char* filename);
|
|
||||||
void CreateAudioStream();
|
|
||||||
|
|
||||||
std::unique_ptr<HostDisplay> m_display;
|
|
||||||
std::unique_ptr<AudioStream> m_audio_stream;
|
|
||||||
std::string m_program_directory;
|
|
||||||
std::string m_user_directory;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define TRANSLATABLE(context, str) str
|
|
||||||
|
|
||||||
extern HostInterface* g_host_interface;
|
|
|
@ -1,10 +1,14 @@
|
||||||
#include "host_interface_progress_callback.h"
|
#include "host_interface_progress_callback.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
|
#include "host.h"
|
||||||
Log_SetChannel(HostInterfaceProgressCallback);
|
Log_SetChannel(HostInterfaceProgressCallback);
|
||||||
|
|
||||||
HostInterfaceProgressCallback::HostInterfaceProgressCallback() : BaseProgressCallback() {}
|
HostInterfaceProgressCallback::HostInterfaceProgressCallback() : BaseProgressCallback() {}
|
||||||
|
|
||||||
void HostInterfaceProgressCallback::PushState() { BaseProgressCallback::PushState(); }
|
void HostInterfaceProgressCallback::PushState()
|
||||||
|
{
|
||||||
|
BaseProgressCallback::PushState();
|
||||||
|
}
|
||||||
|
|
||||||
void HostInterfaceProgressCallback::PopState()
|
void HostInterfaceProgressCallback::PopState()
|
||||||
{
|
{
|
||||||
|
@ -57,32 +61,42 @@ void HostInterfaceProgressCallback::Redraw(bool force)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_last_progress_percent = percent;
|
m_last_progress_percent = percent;
|
||||||
g_host_interface->DisplayLoadingScreen(m_status_text, 0, static_cast<int>(m_progress_range),
|
Host::DisplayLoadingScreen(m_status_text, 0, static_cast<int>(m_progress_range), static_cast<int>(m_progress_value));
|
||||||
static_cast<int>(m_progress_value));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HostInterfaceProgressCallback::DisplayError(const char* message) { Log_ErrorPrint(message); }
|
void HostInterfaceProgressCallback::DisplayError(const char* message)
|
||||||
|
{
|
||||||
|
Log_ErrorPrint(message);
|
||||||
|
}
|
||||||
|
|
||||||
void HostInterfaceProgressCallback::DisplayWarning(const char* message) { Log_WarningPrint(message); }
|
void HostInterfaceProgressCallback::DisplayWarning(const char* message)
|
||||||
|
{
|
||||||
|
Log_WarningPrint(message);
|
||||||
|
}
|
||||||
|
|
||||||
void HostInterfaceProgressCallback::DisplayInformation(const char* message) { Log_InfoPrint(message); }
|
void HostInterfaceProgressCallback::DisplayInformation(const char* message)
|
||||||
|
{
|
||||||
|
Log_InfoPrint(message);
|
||||||
|
}
|
||||||
|
|
||||||
void HostInterfaceProgressCallback::DisplayDebugMessage(const char* message) { Log_DevPrint(message); }
|
void HostInterfaceProgressCallback::DisplayDebugMessage(const char* message)
|
||||||
|
{
|
||||||
|
Log_DevPrint(message);
|
||||||
|
}
|
||||||
|
|
||||||
void HostInterfaceProgressCallback::ModalError(const char* message)
|
void HostInterfaceProgressCallback::ModalError(const char* message)
|
||||||
{
|
{
|
||||||
Log_ErrorPrint(message);
|
Log_ErrorPrint(message);
|
||||||
g_host_interface->ReportError(message);
|
Host::ReportErrorAsync("Error", message);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HostInterfaceProgressCallback::ModalConfirmation(const char* message)
|
bool HostInterfaceProgressCallback::ModalConfirmation(const char* message)
|
||||||
{
|
{
|
||||||
Log_InfoPrint(message);
|
Log_InfoPrint(message);
|
||||||
return g_host_interface->ConfirmMessage(message);
|
return Host::ConfirmMessage("Confirm", message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HostInterfaceProgressCallback::ModalInformation(const char* message)
|
void HostInterfaceProgressCallback::ModalInformation(const char* message)
|
||||||
{
|
{
|
||||||
Log_InfoPrint(message);
|
Log_InfoPrint(message);
|
||||||
g_host_interface->ReportMessage(message);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "common/progress_callback.h"
|
#include "common/progress_callback.h"
|
||||||
#include "host_interface.h"
|
|
||||||
|
|
||||||
class HostInterfaceProgressCallback final : public BaseProgressCallback
|
class HostInterfaceProgressCallback final : public BaseProgressCallback
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,13 +18,16 @@ double GetBaseDoubleSettingValue(const char* section, const char* key, double de
|
||||||
std::vector<std::string> GetBaseStringListSetting(const char* section, const char* key);
|
std::vector<std::string> GetBaseStringListSetting(const char* section, const char* key);
|
||||||
|
|
||||||
// Allows the emucore to write settings back to the frontend. Use with care.
|
// Allows the emucore to write settings back to the frontend. Use with care.
|
||||||
// You should call CommitBaseSettingChanges() after finishing writing, or it may not be written to disk.
|
// You should call CommitBaseSettingChanges() if you directly write to the layer (i.e. not these functions), or it may
|
||||||
|
// not be written to disk.
|
||||||
void SetBaseBoolSettingValue(const char* section, const char* key, bool value);
|
void SetBaseBoolSettingValue(const char* section, const char* key, bool value);
|
||||||
void SetBaseIntSettingValue(const char* section, const char* key, s32 value);
|
void SetBaseIntSettingValue(const char* section, const char* key, s32 value);
|
||||||
void SetBaseUIntSettingValue(const char* section, const char* key, u32 value);
|
void SetBaseUIntSettingValue(const char* section, const char* key, u32 value);
|
||||||
void SetBaseFloatSettingValue(const char* section, const char* key, float value);
|
void SetBaseFloatSettingValue(const char* section, const char* key, float value);
|
||||||
void SetBaseStringSettingValue(const char* section, const char* key, const char* value);
|
void SetBaseStringSettingValue(const char* section, const char* key, const char* value);
|
||||||
void SetBaseStringListSettingValue(const char* section, const char* key, const std::vector<std::string>& values);
|
void SetBaseStringListSettingValue(const char* section, const char* key, const std::vector<std::string>& values);
|
||||||
|
bool AddValueToBaseStringListSetting(const char* section, const char* key, const char* value);
|
||||||
|
bool RemoveValueFromBaseStringListSetting(const char* section, const char* key, const char* value);
|
||||||
void DeleteBaseSettingValue(const char* section, const char* key);
|
void DeleteBaseSettingValue(const char* section, const char* key);
|
||||||
void CommitBaseSettingChanges();
|
void CommitBaseSettingChanges();
|
||||||
|
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
#include "imgui_styles.h"
|
|
||||||
|
|
||||||
void ImGui::StyleColorsDarker(ImGuiStyle* dst)
|
|
||||||
{
|
|
||||||
ImGuiStyle* style = dst ? dst : &ImGui::GetStyle();
|
|
||||||
ImVec4* colors = style->Colors;
|
|
||||||
|
|
||||||
colors[ImGuiCol_Text] = ImVec4(0.95f, 0.96f, 0.98f, 1.00f);
|
|
||||||
colors[ImGuiCol_TextDisabled] = ImVec4(0.36f, 0.42f, 0.47f, 1.00f);
|
|
||||||
colors[ImGuiCol_WindowBg] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
|
|
||||||
colors[ImGuiCol_ChildBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f);
|
|
||||||
colors[ImGuiCol_PopupBg] = ImVec4(0.08f, 0.08f, 0.08f, 0.94f);
|
|
||||||
colors[ImGuiCol_Border] = ImVec4(0.08f, 0.10f, 0.12f, 1.00f);
|
|
||||||
colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
|
||||||
colors[ImGuiCol_FrameBg] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
|
|
||||||
colors[ImGuiCol_FrameBgHovered] = ImVec4(0.12f, 0.20f, 0.28f, 1.00f);
|
|
||||||
colors[ImGuiCol_FrameBgActive] = ImVec4(0.09f, 0.12f, 0.14f, 1.00f);
|
|
||||||
colors[ImGuiCol_TitleBg] = ImVec4(0.09f, 0.12f, 0.14f, 0.65f);
|
|
||||||
colors[ImGuiCol_TitleBgActive] = ImVec4(0.08f, 0.10f, 0.12f, 1.00f);
|
|
||||||
colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.00f, 0.00f, 0.51f);
|
|
||||||
colors[ImGuiCol_MenuBarBg] = ImVec4(0.15f, 0.18f, 0.22f, 1.00f);
|
|
||||||
colors[ImGuiCol_ScrollbarBg] = ImVec4(0.02f, 0.02f, 0.02f, 0.39f);
|
|
||||||
colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
|
|
||||||
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.18f, 0.22f, 0.25f, 1.00f);
|
|
||||||
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.09f, 0.21f, 0.31f, 1.00f);
|
|
||||||
colors[ImGuiCol_CheckMark] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f);
|
|
||||||
colors[ImGuiCol_SliderGrab] = ImVec4(0.28f, 0.56f, 1.00f, 1.00f);
|
|
||||||
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.37f, 0.61f, 1.00f, 1.00f);
|
|
||||||
colors[ImGuiCol_Button] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
|
|
||||||
colors[ImGuiCol_ButtonHovered] = ImVec4(0.33f, 0.38f, 0.46f, 1.00f);
|
|
||||||
colors[ImGuiCol_ButtonActive] = ImVec4(0.27f, 0.32f, 0.38f, 1.00f);
|
|
||||||
colors[ImGuiCol_Header] = ImVec4(0.20f, 0.25f, 0.29f, 0.55f);
|
|
||||||
colors[ImGuiCol_HeaderHovered] = ImVec4(0.33f, 0.38f, 0.46f, 1.00f);
|
|
||||||
colors[ImGuiCol_HeaderActive] = ImVec4(0.27f, 0.32f, 0.38f, 1.00f);
|
|
||||||
colors[ImGuiCol_Separator] = ImVec4(0.20f, 0.25f, 0.29f, 1.00f);
|
|
||||||
colors[ImGuiCol_SeparatorHovered] = ImVec4(0.33f, 0.38f, 0.46f, 1.00f);
|
|
||||||
colors[ImGuiCol_SeparatorActive] = ImVec4(0.27f, 0.32f, 0.38f, 1.00f);
|
|
||||||
colors[ImGuiCol_ResizeGrip] = ImVec4(0.26f, 0.59f, 0.98f, 0.25f);
|
|
||||||
colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.33f, 0.38f, 0.46f, 1.00f);
|
|
||||||
colors[ImGuiCol_ResizeGripActive] = ImVec4(0.27f, 0.32f, 0.38f, 1.00f);
|
|
||||||
colors[ImGuiCol_Tab] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
|
|
||||||
colors[ImGuiCol_TabHovered] = ImVec4(0.33f, 0.38f, 0.46f, 1.00f);
|
|
||||||
colors[ImGuiCol_TabActive] = ImVec4(0.27f, 0.32f, 0.38f, 1.00f);
|
|
||||||
colors[ImGuiCol_TabUnfocused] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
|
|
||||||
colors[ImGuiCol_TabUnfocusedActive] = ImVec4(0.11f, 0.15f, 0.17f, 1.00f);
|
|
||||||
colors[ImGuiCol_PlotLines] = ImVec4(0.61f, 0.61f, 0.61f, 1.00f);
|
|
||||||
colors[ImGuiCol_PlotLinesHovered] = ImVec4(1.00f, 0.43f, 0.35f, 1.00f);
|
|
||||||
colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
|
|
||||||
colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
|
|
||||||
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
|
|
||||||
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
|
|
||||||
colors[ImGuiCol_NavHighlight] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
|
||||||
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
|
|
||||||
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
|
|
||||||
colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.35f);
|
|
||||||
}
|
|