mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
merge from upstream
This commit is contained in:
commit
bf2cabb82c
170 changed files with 5991 additions and 1904 deletions
|
@ -38,7 +38,11 @@ include:
|
|||
|
||||
# MacOS 64-bit
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/osx-x64.yml'
|
||||
file: '/osx-cmake-x86.yml'
|
||||
|
||||
# MacOS arm64
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/osx-cmake-arm64.yml'
|
||||
|
||||
################################## CELLULAR ################################
|
||||
# Android
|
||||
|
@ -92,7 +96,16 @@ libretro-build-osx-x64:
|
|||
tags:
|
||||
- macosx-packaging
|
||||
extends:
|
||||
- .libretro-osx-x64-make-default
|
||||
- .libretro-osx-cmake-x86_64
|
||||
- .core-defs
|
||||
- .make-defs
|
||||
|
||||
# MacOS 64-bit
|
||||
libretro-build-osx-arm64:
|
||||
tags:
|
||||
- macosx-packaging
|
||||
extends:
|
||||
- .libretro-osx-cmake-arm64
|
||||
- .core-defs
|
||||
- .make-defs
|
||||
|
||||
|
|
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -38,3 +38,6 @@
|
|||
path = assets/debugger
|
||||
url = https://github.com/unknownbrackets/ppsspp-debugger.git
|
||||
branch = bundled
|
||||
[submodule "cpu_features"]
|
||||
path = ext/cpu_features
|
||||
url = https://github.com/google/cpu_features.git
|
||||
|
|
|
@ -256,6 +256,7 @@ include(FindThreads)
|
|||
|
||||
if(APPLE)
|
||||
find_library(COCOA_LIBRARY Cocoa)
|
||||
find_library(IOKIT_LIBRARY IOKit)
|
||||
find_library(QUARTZ_CORE_LIBRARY QuartzCore)
|
||||
endif()
|
||||
|
||||
|
@ -775,12 +776,13 @@ add_library(Common STATIC
|
|||
Common/SysError.cpp
|
||||
Common/TimeUtil.cpp
|
||||
Common/TimeUtil.h
|
||||
Common/Battery/Battery.h
|
||||
)
|
||||
|
||||
include_directories(Common)
|
||||
setup_target_project(Common Common)
|
||||
|
||||
target_link_libraries(Common Ext::Snappy)
|
||||
target_link_libraries(Common Ext::Snappy cpu_features)
|
||||
|
||||
if(USING_GLES2 OR (USING_EGL AND NOT USING_FBDEV))
|
||||
find_package(X11)
|
||||
|
@ -1150,6 +1152,7 @@ elseif(IOS)
|
|||
ios/iCade/iCadeState.h
|
||||
UI/DarwinMemoryStickManager.mm
|
||||
UI/DarwinMemoryStickManager.h
|
||||
Common/Battery/AppleBatteryClient.m
|
||||
)
|
||||
|
||||
set(nativeExtraLibs ${nativeExtraLibs} "-framework Foundation -framework MediaPlayer -framework AudioToolbox -framework CoreGraphics -framework QuartzCore -framework UIKit -framework GLKit -framework OpenAL -framework AVFoundation -framework CoreLocation -framework CoreVideo -framework CoreMedia -framework CoreServices" )
|
||||
|
@ -1170,6 +1173,7 @@ elseif(IOS)
|
|||
set_source_files_properties(ios/CameraHelper.mm PROPERTIES COMPILE_FLAGS -fobjc-arc)
|
||||
set_source_files_properties(ios/LocationHelper.mm PROPERTIES COMPILE_FLAGS -fobjc-arc)
|
||||
set_source_files_properties(UI/DarwinMemoryStickManager.mm PROPERTIES COMPILE_FLAGS -fobjc-arc)
|
||||
set_source_files_properties(Common/Battery/AppleBatteryClient.m PROPERTIES COMPILE_FLAGS -fobjc-arc)
|
||||
set(TargetBin PPSSPP)
|
||||
elseif(USING_QT_UI)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
@ -1227,9 +1231,10 @@ elseif(TARGET SDL2::SDL2)
|
|||
endif()
|
||||
set(nativeExtraLibs ${nativeExtraLibs} SDL2::SDL2)
|
||||
if(APPLE)
|
||||
set(nativeExtra ${nativeExtra} SDL/SDLMain.h SDL/SDLMain.mm SDL/SDLCocoaMetalLayer.h SDL/SDLCocoaMetalLayer.mm UI/DarwinMemoryStickManager.mm)
|
||||
set(nativeExtra ${nativeExtra} SDL/SDLMain.h SDL/SDLMain.mm SDL/SDLCocoaMetalLayer.h SDL/SDLCocoaMetalLayer.mm UI/DarwinMemoryStickManager.mm Common/Battery/AppleBatteryClient.m)
|
||||
set_source_files_properties(UI/DarwinMemoryStickManager.mm PROPERTIES COMPILE_FLAGS -fobjc-arc)
|
||||
set(nativeExtraLibs ${nativeExtraLibs} ${COCOA_LIBRARY} ${QUARTZ_CORE_LIBRARY})
|
||||
set_source_files_properties(Common/Battery/AppleBatteryClient.m PROPERTIES COMPILE_FLAGS -fobjc-arc)
|
||||
set(nativeExtraLibs ${nativeExtraLibs} ${COCOA_LIBRARY} ${QUARTZ_CORE_LIBRARY} ${IOKIT_LIBRARY})
|
||||
elseif(USING_EGL)
|
||||
set(nativeExtraLibs ${nativeExtraLibs} pthread)
|
||||
endif()
|
||||
|
@ -2378,7 +2383,7 @@ if(HEADLESS)
|
|||
)
|
||||
endif()
|
||||
add_executable(PPSSPPHeadless ${HeadlessSource})
|
||||
target_link_libraries(PPSSPPHeadless ${COCOA_LIBRARY} ${QUARTZ_CORE_LIBRARY} ${LinkCommon})
|
||||
target_link_libraries(PPSSPPHeadless ${COCOA_LIBRARY} ${QUARTZ_CORE_LIBRARY} ${IOKIT_LIBRARY} ${LinkCommon})
|
||||
setup_target_project(PPSSPPHeadless headless)
|
||||
endif()
|
||||
|
||||
|
@ -2398,7 +2403,7 @@ if(UNITTEST)
|
|||
Core/MIPS/ARM/ArmRegCache.cpp
|
||||
Core/MIPS/ARM/ArmRegCacheFPU.cpp
|
||||
)
|
||||
target_link_libraries(PPSSPPUnitTest ${COCOA_LIBRARY} ${QUARTZ_CORE_LIBRARY} ${LinkCommon} Common)
|
||||
target_link_libraries(PPSSPPUnitTest ${COCOA_LIBRARY} ${QUARTZ_CORE_LIBRARY} ${IOKIT_LIBRARY} ${LinkCommon} Common)
|
||||
setup_target_project(PPSSPPUnitTest unittest)
|
||||
add_test(arm64_emitter PPSSPPUnitTest Arm64Emitter)
|
||||
add_test(arm_emitter PPSSPPUnitTest ArmEmitter)
|
||||
|
|
|
@ -26,6 +26,20 @@
|
|||
|
||||
#if PPSSPP_ARCH(ARM) || PPSSPP_ARCH(ARM64)
|
||||
|
||||
#if PPSSPP_ARCH(ARM)
|
||||
#include "ext/cpu_features/include/cpuinfo_arm.h"
|
||||
|
||||
#if defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
|
||||
#define USE_CPU_FEATURES 1
|
||||
#endif
|
||||
#elif PPSSPP_ARCH(ARM64) && defined(__aarch64__)
|
||||
#include "ext/cpu_features/include/cpuinfo_aarch64.h"
|
||||
|
||||
#if defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID)
|
||||
#define USE_CPU_FEATURES 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
@ -337,31 +351,81 @@ void CPUInfo::Detect()
|
|||
bNEON = true;
|
||||
bASIMD = true;
|
||||
#endif
|
||||
|
||||
#if PPSSPP_ARCH(ARM) && defined(USE_CPU_FEATURES)
|
||||
cpu_features::ArmInfo info = cpu_features::GetArmInfo();
|
||||
bSwp = info.features.swp;
|
||||
bHalf = info.features.half;
|
||||
bThumb = info.features.thumb;
|
||||
bFastMult = info.features.fastmult;
|
||||
bEDSP = info.features.edsp;
|
||||
bThumbEE = info.features.thumbee;
|
||||
bNEON = info.features.neon;
|
||||
bTLS = info.features.tls;
|
||||
bVFP = info.features.vfp;
|
||||
bVFPv3 = info.features.vfpv3;
|
||||
bVFPv4 = info.features.vfpv4;
|
||||
bIDIVa = info.features.idiva;
|
||||
bIDIVt = info.features.idivt;
|
||||
#endif
|
||||
#if PPSSPP_ARCH(ARM64) && defined(USE_CPU_FEATURES)
|
||||
cpu_features::Aarch64Info info = cpu_features::GetAarch64Info();
|
||||
bFP = info.features.fp;
|
||||
bASIMD = info.features.asimd;
|
||||
bSVE = info.features.sve;
|
||||
bSVE2 = info.features.sve2;
|
||||
bFRINT = info.features.frint;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector<std::string> CPUInfo::Features() {
|
||||
std::vector<std::string> features;
|
||||
|
||||
struct Flag {
|
||||
bool &flag;
|
||||
const char *str;
|
||||
};
|
||||
const Flag list[] = {
|
||||
{ bSwp, "SWP" },
|
||||
{ bHalf, "Half" },
|
||||
{ bThumb, "Thumb" },
|
||||
{ bFastMult, "FastMult" },
|
||||
{ bEDSP, "EDSP" },
|
||||
{ bThumbEE, "ThumbEE" },
|
||||
{ bTLS, "TLS" },
|
||||
{ bVFP, "VFP" },
|
||||
{ bVFPv3, "VFPv3" },
|
||||
{ bVFPv4, "VFPv4" },
|
||||
{ bNEON, "NEON" },
|
||||
{ bIDIVa, "IDIVa" },
|
||||
{ bIDIVt, "IDIVt" },
|
||||
{ bFRINT, "FRINT" },
|
||||
{ bSVE, "SVE" },
|
||||
{ bSVE2, "SVE2" },
|
||||
{ CPU64bit, "64-bit" },
|
||||
};
|
||||
|
||||
for (auto &item : list) {
|
||||
if (item.flag) {
|
||||
features.push_back(item.str);
|
||||
}
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
// Turn the cpu info into a string we can show
|
||||
std::string CPUInfo::Summarize()
|
||||
{
|
||||
std::string CPUInfo::Summarize() {
|
||||
std::string sum;
|
||||
if (num_cores == 1)
|
||||
sum = StringFromFormat("%s, %d core", cpu_string, num_cores);
|
||||
else
|
||||
sum = StringFromFormat("%s, %d cores", cpu_string, num_cores);
|
||||
if (bSwp) sum += ", SWP";
|
||||
if (bHalf) sum += ", Half";
|
||||
if (bThumb) sum += ", Thumb";
|
||||
if (bFastMult) sum += ", FastMult";
|
||||
if (bEDSP) sum += ", EDSP";
|
||||
if (bThumbEE) sum += ", ThumbEE";
|
||||
if (bTLS) sum += ", TLS";
|
||||
if (bVFP) sum += ", VFP";
|
||||
if (bVFPv3) sum += ", VFPv3";
|
||||
if (bVFPv4) sum += ", VFPv4";
|
||||
if (bNEON) sum += ", NEON";
|
||||
if (bIDIVa) sum += ", IDIVa";
|
||||
if (bIDIVt) sum += ", IDIVt";
|
||||
if (CPU64bit) sum += ", 64-bit";
|
||||
|
||||
auto features = Features();
|
||||
for (std::string &feature : features) {
|
||||
sum += ", " + feature;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
|
96
Common/Battery/AppleBatteryClient.m
Normal file
96
Common/Battery/AppleBatteryClient.m
Normal file
|
@ -0,0 +1,96 @@
|
|||
//
|
||||
// AppleBatteryClient.m
|
||||
// PPSSPP
|
||||
//
|
||||
// Created by Serena on 24/01/2023.
|
||||
//
|
||||
|
||||
#include "Battery.h"
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#if PPSSPP_PLATFORM(MAC)
|
||||
#include <IOKit/ps/IOPSKeys.h>
|
||||
#include <IOKit/ps/IOPowerSources.h>
|
||||
#elif PPSSPP_PLATFORM(IOS)
|
||||
#import <UIKit/UIKit.h>
|
||||
#endif
|
||||
|
||||
@interface AppleBatteryClient : NSObject
|
||||
+(instancetype)sharedClient;
|
||||
-(void)setNeedsToUpdateLevel;
|
||||
@property int batteryLevel;
|
||||
@end
|
||||
|
||||
void _powerSourceRunLoopCallback(void * __unused ctx) {
|
||||
// IOKit has told us that battery information has changed, now update the batteryLevel var
|
||||
[[AppleBatteryClient sharedClient] setNeedsToUpdateLevel];
|
||||
}
|
||||
|
||||
// You may ask,
|
||||
// "Why an entire class?
|
||||
// Why not just call the UIDevice/IOKitPowerSource functions every time getCurrentBatteryCapacity() is called?"
|
||||
// Well, calling the UIDevice/IOKitPowerSource functions very frequently (every second, it seems?) is expensive
|
||||
// So, instead, I made a class with a cached batteryLevel property
|
||||
// that only gets set when it needs to.
|
||||
@implementation AppleBatteryClient
|
||||
|
||||
+ (instancetype)sharedClient {
|
||||
static AppleBatteryClient *client;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
client = [AppleBatteryClient new];
|
||||
[client initialSetup];
|
||||
[client setNeedsToUpdateLevel];
|
||||
});
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
-(void)initialSetup {
|
||||
#if TARGET_OS_IOS
|
||||
// on iOS, this needs to be true to get the battery level
|
||||
// and it needs to be set just once, so do it here
|
||||
UIDevice.currentDevice.batteryMonitoringEnabled = YES;
|
||||
// Register for when the battery % changes
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||
selector:@selector(setNeedsToUpdateLevel)
|
||||
name:UIDeviceBatteryLevelDidChangeNotification object:nil];
|
||||
|
||||
#elif TARGET_OS_MAC
|
||||
CFRunLoopSourceRef loop = IOPSNotificationCreateRunLoopSource(_powerSourceRunLoopCallback, nil);
|
||||
CFRunLoopAddSource(CFRunLoopGetMain(), loop, kCFRunLoopDefaultMode);
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)setNeedsToUpdateLevel {
|
||||
#if TARGET_OS_IOS
|
||||
// `-[UIDevice batteryLevel]` returns the % like '0.(actual %)' (ie, 0.28 when the battery is 28%)
|
||||
// so multiply it by 100 to get a visually appropriate version
|
||||
self.batteryLevel = [[UIDevice currentDevice] batteryLevel] * 100;
|
||||
#elif TARGET_OS_MAC
|
||||
CFTypeRef snapshot = IOPSCopyPowerSourcesInfo();
|
||||
NSArray *sourceList = (__bridge NSArray *)IOPSCopyPowerSourcesList(snapshot);
|
||||
if (!sourceList) {
|
||||
if (snapshot) CFRelease(snapshot);
|
||||
return;
|
||||
}
|
||||
|
||||
for (NSDictionary *source in sourceList) {
|
||||
// kIOPSCurrentCapacityKey = battery level
|
||||
NSNumber *currentCapacity = [source objectForKey:@(kIOPSCurrentCapacityKey)];
|
||||
if (currentCapacity) {
|
||||
// we found what we want
|
||||
self.batteryLevel = currentCapacity.intValue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
CFRelease(snapshot);
|
||||
#endif
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
int getCurrentBatteryCapacity() {
|
||||
return [[AppleBatteryClient sharedClient] batteryLevel];
|
||||
}
|
32
Common/Battery/Battery.h
Normal file
32
Common/Battery/Battery.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
//
|
||||
// Battery.h
|
||||
// PPSSPP
|
||||
//
|
||||
// Created by Serena on 24/01/2023.
|
||||
//
|
||||
|
||||
// NOTE: Though this is a general purpose header file,
|
||||
// though the implementation right now is Darwin specific
|
||||
// In case any future platform implementations are made for other platforms,
|
||||
// define the function below in their own file
|
||||
|
||||
#ifndef BATTERY_H
|
||||
#define BATTERY_H
|
||||
#include "ppsspp_config.h"
|
||||
//#include <Foundation/Foundation.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if PPSSPP_PLATFORM(IOS) || PPSSPP_PLATFORM(MAC)
|
||||
#define CAN_DISPLAY_CURRENT_BATTERY_CAPACITY
|
||||
/// Get the current battery %.
|
||||
int getCurrentBatteryCapacity();
|
||||
#endif /* PPSSPP_PLATFORM(IOS) || PPSSPP_PLATFORM(MAC) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BATTERY_H */
|
|
@ -19,6 +19,12 @@
|
|||
#include "ppsspp_config.h"
|
||||
#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64)
|
||||
|
||||
#include "ext/cpu_features/include/cpuinfo_x86.h"
|
||||
|
||||
#if defined(CPU_FEATURES_OS_FREEBSD) || defined(CPU_FEATURES_OS_LINUX) || defined(CPU_FEATURES_OS_ANDROID) || defined(CPU_FEATURES_OS_MACOS) || defined(CPU_FEATURES_OS_WINDOWS)
|
||||
#define USE_CPU_FEATURES 1
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -141,6 +147,10 @@ static std::vector<int> ParseCPUList(const std::string &filename) {
|
|||
|
||||
// Detects the various cpu features
|
||||
void CPUInfo::Detect() {
|
||||
#ifdef USE_CPU_FEATURES
|
||||
cpu_features::X86Info info = cpu_features::GetX86Info();
|
||||
#endif
|
||||
|
||||
memset(this, 0, sizeof(*this));
|
||||
#if PPSSPP_ARCH(X86)
|
||||
Mode64bit = false;
|
||||
|
@ -185,7 +195,50 @@ void CPUInfo::Detect() {
|
|||
vendor = VENDOR_OTHER;
|
||||
|
||||
// Set reasonable default brand string even if brand string not available.
|
||||
strcpy(brand_string, cpu_string);
|
||||
#ifdef USE_CPU_FEATURES
|
||||
if (info.brand_string[0])
|
||||
strcpy(brand_string, info.brand_string);
|
||||
else
|
||||
#endif
|
||||
strcpy(brand_string, cpu_string);
|
||||
|
||||
#ifdef USE_CPU_FEATURES
|
||||
switch (cpu_features::GetX86Microarchitecture(&info)) {
|
||||
case cpu_features::INTEL_ATOM_BNL:
|
||||
case cpu_features::INTEL_ATOM_SMT:
|
||||
case cpu_features::INTEL_ATOM_GMT:
|
||||
case cpu_features::INTEL_ATOM_GMT_PLUS:
|
||||
case cpu_features::INTEL_ATOM_TMT:
|
||||
bAtom = true;
|
||||
break;
|
||||
default:
|
||||
bAtom = false;
|
||||
break;
|
||||
}
|
||||
|
||||
bPOPCNT = info.features.popcnt;
|
||||
bBMI1 = info.features.bmi1;
|
||||
bBMI2 = info.features.bmi2;
|
||||
bBMI2_fast = bBMI2 && (vendor != VENDOR_AMD || info.family >= 0x19);
|
||||
bMOVBE = info.features.movbe;
|
||||
bLZCNT = info.features.lzcnt;
|
||||
bRTM = info.features.rtm;
|
||||
|
||||
bSSE = info.features.sse;
|
||||
bSSE2 = info.features.sse2;
|
||||
bSSE3 = info.features.sse3;
|
||||
bSSSE3 = info.features.ssse3;
|
||||
bSSE4_1 = info.features.sse4_1;
|
||||
bSSE4_2 = info.features.sse4_2;
|
||||
bSSE4A = info.features.sse4a;
|
||||
bAES = info.features.aes;
|
||||
bSHA = info.features.sha;
|
||||
bF16C = info.features.f16c;
|
||||
bAVX = info.features.avx;
|
||||
bAVX2 = info.features.avx2;
|
||||
bFMA3 = info.features.fma3;
|
||||
bFMA4 = info.features.fma4;
|
||||
#endif
|
||||
|
||||
// Detect family and other misc stuff.
|
||||
bool ht = false;
|
||||
|
@ -193,16 +246,19 @@ void CPUInfo::Detect() {
|
|||
logical_cpu_count = 1;
|
||||
if (max_std_fn >= 1) {
|
||||
do_cpuid(cpu_id, 0x00000001);
|
||||
#ifndef USE_CPU_FEATURES
|
||||
int family = ((cpu_id[0] >> 8) & 0xf) + ((cpu_id[0] >> 20) & 0xff);
|
||||
int model = ((cpu_id[0] >> 4) & 0xf) + ((cpu_id[0] >> 12) & 0xf0);
|
||||
// Detect people unfortunate enough to be running PPSSPP on an Atom
|
||||
if (family == 6 && (model == 0x1C || model == 0x26 || model == 0x27 || model == 0x35 || model == 0x36 ||
|
||||
model == 0x37 || model == 0x4A || model == 0x4D || model == 0x5A || model == 0x5D))
|
||||
bAtom = true;
|
||||
#endif
|
||||
|
||||
logical_cpu_count = (cpu_id[1] >> 16) & 0xFF;
|
||||
ht = (cpu_id[3] >> 28) & 1;
|
||||
|
||||
#ifndef USE_CPU_FEATURES
|
||||
if ((cpu_id[3] >> 25) & 1) bSSE = true;
|
||||
if ((cpu_id[3] >> 26) & 1) bSSE2 = true;
|
||||
if ((cpu_id[2]) & 1) bSSE3 = true;
|
||||
|
@ -215,6 +271,7 @@ void CPUInfo::Detect() {
|
|||
bFMA3 = true;
|
||||
}
|
||||
if ((cpu_id[2] >> 25) & 1) bAES = true;
|
||||
#endif
|
||||
|
||||
if ((cpu_id[3] >> 24) & 1)
|
||||
{
|
||||
|
@ -222,6 +279,7 @@ void CPUInfo::Detect() {
|
|||
bFXSR = true;
|
||||
}
|
||||
|
||||
#ifndef USE_CPU_FEATURES
|
||||
// AVX support requires 3 separate checks:
|
||||
// - Is the AVX bit set in CPUID? (>>28)
|
||||
// - Is the XSAVE bit set in CPUID? ( >>26)
|
||||
|
@ -257,8 +315,10 @@ void CPUInfo::Detect() {
|
|||
}
|
||||
|
||||
bBMI2_fast = bBMI2 && (vendor != VENDOR_AMD || family >= 0x19);
|
||||
#endif
|
||||
}
|
||||
if (max_ex_fn >= 0x80000004) {
|
||||
#ifndef USE_CPU_FEATURES
|
||||
// Extract brand string
|
||||
do_cpuid(cpu_id, 0x80000002);
|
||||
memcpy(brand_string, cpu_id, sizeof(cpu_id));
|
||||
|
@ -266,13 +326,16 @@ void CPUInfo::Detect() {
|
|||
memcpy(brand_string + 16, cpu_id, sizeof(cpu_id));
|
||||
do_cpuid(cpu_id, 0x80000004);
|
||||
memcpy(brand_string + 32, cpu_id, sizeof(cpu_id));
|
||||
#endif
|
||||
}
|
||||
if (max_ex_fn >= 0x80000001) {
|
||||
// Check for more features.
|
||||
do_cpuid(cpu_id, 0x80000001);
|
||||
if (cpu_id[2] & 1) bLAHFSAHF64 = true;
|
||||
#ifndef USE_CPU_FEATURES
|
||||
if ((cpu_id[2] >> 6) & 1) bSSE4A = true;
|
||||
if ((cpu_id[2] >> 16) & 1) bFMA4 = true;
|
||||
#endif
|
||||
if ((cpu_id[2] >> 11) & 1) bXOP = true;
|
||||
// CmpLegacy (bit 2) is deprecated.
|
||||
if ((cpu_id[3] >> 29) & 1) bLongMode = true;
|
||||
|
@ -418,34 +481,63 @@ void CPUInfo::Detect() {
|
|||
logical_cpu_count = 1;
|
||||
}
|
||||
|
||||
// Turn the cpu info into a string we can show
|
||||
std::string CPUInfo::Summarize()
|
||||
{
|
||||
std::string sum;
|
||||
if (num_cores == 1)
|
||||
sum = StringFromFormat("%s, %d core", cpu_string, num_cores);
|
||||
else
|
||||
{
|
||||
sum = StringFromFormat("%s, %d cores", cpu_string, num_cores);
|
||||
if (HTT) sum += StringFromFormat(" (%i logical threads per physical core)", logical_cpu_count);
|
||||
std::vector<std::string> CPUInfo::Features() {
|
||||
std::vector<std::string> features;
|
||||
|
||||
struct Flag {
|
||||
bool &flag;
|
||||
const char *str;
|
||||
};
|
||||
const Flag list[] = {
|
||||
{ bSSE, "SSE" },
|
||||
{ bSSE2, "SSE2" },
|
||||
{ bSSE3, "SSE3" },
|
||||
{ bSSSE3, "SSSE3" },
|
||||
{ bSSE4_1, "SSE4.1" },
|
||||
{ bSSE4_2, "SSE4.2" },
|
||||
{ bSSE4A, "SSE4A" },
|
||||
{ HTT, "HTT" },
|
||||
{ bAVX, "AVX" },
|
||||
{ bAVX2, "AVX2" },
|
||||
{ bFMA3, "FMA3" },
|
||||
{ bFMA4, "FMA4" },
|
||||
{ bAES, "AES" },
|
||||
{ bSHA, "SHA" },
|
||||
{ bXOP, "XOP" },
|
||||
{ bRTM, "TSX" },
|
||||
{ bF16C, "F16C" },
|
||||
{ bBMI1, "BMI1" },
|
||||
{ bBMI2, "BMI2" },
|
||||
{ bPOPCNT, "POPCNT" },
|
||||
{ bMOVBE, "MOVBE" },
|
||||
{ bLZCNT, "LZCNT" },
|
||||
{ bLongMode, "64-bit support" },
|
||||
};
|
||||
|
||||
for (auto &item : list) {
|
||||
if (item.flag) {
|
||||
features.push_back(item.str);
|
||||
}
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
// Turn the cpu info into a string we can show
|
||||
std::string CPUInfo::Summarize() {
|
||||
std::string sum;
|
||||
if (num_cores == 1) {
|
||||
sum = StringFromFormat("%s, %d core", cpu_string, num_cores);
|
||||
} else {
|
||||
sum = StringFromFormat("%s, %d cores", cpu_string, num_cores);
|
||||
if (HTT)
|
||||
sum += StringFromFormat(" (%i logical threads per physical core)", logical_cpu_count);
|
||||
}
|
||||
|
||||
auto features = Features();
|
||||
for (std::string &feature : features) {
|
||||
sum += ", " + feature;
|
||||
}
|
||||
if (bSSE) sum += ", SSE";
|
||||
if (bSSE2) sum += ", SSE2";
|
||||
if (bSSE3) sum += ", SSE3";
|
||||
if (bSSSE3) sum += ", SSSE3";
|
||||
if (bSSE4_1) sum += ", SSE4.1";
|
||||
if (bSSE4_2) sum += ", SSE4.2";
|
||||
if (bSSE4A) sum += ", SSE4A";
|
||||
if (HTT) sum += ", HTT";
|
||||
if (bAVX) sum += ", AVX";
|
||||
if (bAVX2) sum += ", AVX2";
|
||||
if (bFMA3) sum += ", FMA3";
|
||||
if (bFMA4) sum += ", FMA4";
|
||||
if (bAES) sum += ", AES";
|
||||
if (bSHA) sum += ", SHA";
|
||||
if (bXOP) sum += ", XOP";
|
||||
if (bRTM) sum += ", TSX";
|
||||
if (bLongMode) sum += ", 64-bit support";
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "ppsspp_config.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
enum CPUVendor {
|
||||
VENDOR_INTEL = 0,
|
||||
|
@ -68,6 +69,7 @@ struct CPUInfo {
|
|||
bool bSSE4A;
|
||||
bool bAES;
|
||||
bool bSHA;
|
||||
bool bF16C;
|
||||
// x86 : SIMD 256 bit
|
||||
bool bAVX;
|
||||
bool bAVX2;
|
||||
|
@ -92,6 +94,9 @@ struct CPUInfo {
|
|||
// ARMv8 specific
|
||||
bool bFP;
|
||||
bool bASIMD;
|
||||
bool bSVE;
|
||||
bool bSVE2;
|
||||
bool bFRINT;
|
||||
|
||||
// MIPS specific
|
||||
bool bXBurst1;
|
||||
|
@ -105,6 +110,7 @@ struct CPUInfo {
|
|||
bool RiscV_C;
|
||||
bool RiscV_V;
|
||||
bool RiscV_B;
|
||||
bool RiscV_Zicsr;
|
||||
|
||||
// Quirks
|
||||
struct {
|
||||
|
@ -120,6 +126,7 @@ struct CPUInfo {
|
|||
explicit CPUInfo();
|
||||
|
||||
// Turn the cpu info into a string we can show
|
||||
std::vector<std::string> Features();
|
||||
std::string Summarize();
|
||||
|
||||
private:
|
||||
|
|
|
@ -1021,6 +1021,9 @@
|
|||
<Text Include="..\ext\libpng17\CMakeLists.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ext\cpu_features.vcxproj">
|
||||
<Project>{c249f016-7f82-45cf-bb6e-0642a988c4d3}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\ext\zlib\zlib.vcxproj">
|
||||
<Project>{f761046e-6c38-4428-a5f1-38391a37bb34}</Project>
|
||||
</ProjectReference>
|
||||
|
|
|
@ -53,11 +53,20 @@ void CPUInfo::Detect()
|
|||
logical_cpu_count = 2;
|
||||
}
|
||||
|
||||
std::vector<std::string> CPUInfo::Features() {
|
||||
std::vector<std::string> features;
|
||||
return features;
|
||||
}
|
||||
|
||||
// Turn the cpu info into a string we can show
|
||||
std::string CPUInfo::Summarize()
|
||||
{
|
||||
std::string CPUInfo::Summarize() {
|
||||
std::string sum;
|
||||
sum = StringFromFormat("%s, %i core", cpu_string, num_cores);
|
||||
|
||||
auto features = Features();
|
||||
for (std::string &feature : features) {
|
||||
sum += ", " + feature;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1166,17 +1166,20 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last
|
|||
glBindBuffer(GL_ARRAY_BUFFER, buf);
|
||||
curArrayBuffer = buf;
|
||||
}
|
||||
int enable = layout->semanticsMask_ & ~attrMask;
|
||||
int disable = (~layout->semanticsMask_) & attrMask;
|
||||
for (int i = 0; i < 7; i++) { // SEM_MAX
|
||||
if (enable & (1 << i)) {
|
||||
glEnableVertexAttribArray(i);
|
||||
}
|
||||
if (disable & (1 << i)) {
|
||||
glDisableVertexAttribArray(i);
|
||||
if (attrMask != layout->semanticsMask_) {
|
||||
int enable = layout->semanticsMask_ & ~attrMask;
|
||||
int disable = (~layout->semanticsMask_) & attrMask;
|
||||
|
||||
for (int i = 0; i < 7; i++) { // SEM_MAX
|
||||
if (enable & (1 << i)) {
|
||||
glEnableVertexAttribArray(i);
|
||||
}
|
||||
if (disable & (1 << i)) {
|
||||
glDisableVertexAttribArray(i);
|
||||
}
|
||||
}
|
||||
attrMask = layout->semanticsMask_;
|
||||
}
|
||||
attrMask = layout->semanticsMask_;
|
||||
for (size_t i = 0; i < layout->entries.size(); i++) {
|
||||
auto &entry = layout->entries[i];
|
||||
glVertexAttribPointer(entry.location, entry.count, entry.type, entry.normalized, entry.stride, (const void *)(c.bindVertexBuffer.offset + entry.offset));
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "Common/GPU/OpenGL/GLCommon.h"
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "Common/VR/PPSSPPVR.h"
|
||||
|
||||
#include "Common/Log.h"
|
||||
#include "Common/TimeUtil.h"
|
||||
#include "Common/MemoryUtil.h"
|
||||
#include "Common/Math/math_util.h"
|
||||
|
||||
|
@ -112,6 +113,8 @@ void GLDeleter::Perform(GLRenderManager *renderManager, bool skipGLCalls) {
|
|||
}
|
||||
|
||||
GLRenderManager::~GLRenderManager() {
|
||||
_dbg_assert_(!run_);
|
||||
|
||||
for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) {
|
||||
_assert_(frameData_[i].deleter.IsEmpty());
|
||||
_assert_(frameData_[i].deleter_prev.IsEmpty());
|
||||
|
@ -123,7 +126,6 @@ GLRenderManager::~GLRenderManager() {
|
|||
|
||||
void GLRenderManager::ThreadStart(Draw::DrawContext *draw) {
|
||||
queueRunner_.CreateDeviceObjects();
|
||||
threadFrame_ = threadInitFrame_;
|
||||
renderThreadId = std::this_thread::get_id();
|
||||
|
||||
if (newInflightFrames_ != -1) {
|
||||
|
@ -169,24 +171,16 @@ void GLRenderManager::ThreadStart(Draw::DrawContext *draw) {
|
|||
void GLRenderManager::ThreadEnd() {
|
||||
INFO_LOG(G3D, "ThreadEnd");
|
||||
|
||||
// Wait for any shutdown to complete in StopThread().
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
queueRunner_.DestroyDeviceObjects();
|
||||
VLOG("PULL: Quitting");
|
||||
VLOG(" PULL: Quitting");
|
||||
|
||||
// Good point to run all the deleters to get rid of leftover objects.
|
||||
// Good time to run all the deleters to get rid of leftover objects.
|
||||
for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) {
|
||||
// Since we're in shutdown, we should skip the GL calls on Android.
|
||||
frameData_[i].deleter.Perform(this, skipGLCalls_);
|
||||
frameData_[i].deleter_prev.Perform(this, skipGLCalls_);
|
||||
for (int j = 0; j < (int)frameData_[i].steps.size(); j++) {
|
||||
delete frameData_[i].steps[j];
|
||||
}
|
||||
frameData_[i].steps.clear();
|
||||
frameData_[i].initSteps.clear();
|
||||
}
|
||||
deleter_.Perform(this, skipGLCalls_);
|
||||
|
||||
for (int i = 0; i < (int)steps_.size(); i++) {
|
||||
delete steps_[i];
|
||||
}
|
||||
|
@ -194,104 +188,68 @@ void GLRenderManager::ThreadEnd() {
|
|||
initSteps_.clear();
|
||||
}
|
||||
|
||||
// Unlike in Vulkan, this isn't a full independent function, instead it gets called every frame.
|
||||
//
|
||||
// This means that we have to block and run the render queue until we've presented one frame,
|
||||
// at which point we can leave.
|
||||
//
|
||||
// NOTE: If run_ is true, we WILL run a task!
|
||||
bool GLRenderManager::ThreadFrame() {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
if (!run_)
|
||||
if (!run_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GLRRenderThreadTask task;
|
||||
|
||||
// In case of syncs or other partial completion, we keep going until we complete a frame.
|
||||
do {
|
||||
if (nextFrame) {
|
||||
threadFrame_++;
|
||||
if (threadFrame_ >= inflightFrames_)
|
||||
threadFrame_ = 0;
|
||||
}
|
||||
FrameData &frameData = frameData_[threadFrame_];
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(frameData.pull_mutex);
|
||||
while (!frameData.readyForRun && run_) {
|
||||
VLOG("PULL: Waiting for frame[%d].readyForRun", threadFrame_);
|
||||
frameData.pull_condVar.wait(lock);
|
||||
}
|
||||
if (!frameData.readyForRun && !run_) {
|
||||
// This means we're out of frames to render and run_ is false, so bail.
|
||||
return false;
|
||||
}
|
||||
VLOG("PULL: Setting frame[%d].readyForRun = false", threadFrame_);
|
||||
frameData.readyForRun = false;
|
||||
frameData.deleter_prev.Perform(this, skipGLCalls_);
|
||||
frameData.deleter_prev.Take(frameData.deleter);
|
||||
// Previously we had a quick exit here that avoided calling Run() if run_ was suddenly false,
|
||||
// but that created a race condition where frames could end up not finished properly on resize etc.
|
||||
while (true) {
|
||||
// Pop a task of the queue and execute it.
|
||||
// NOTE: We need to actually wait for a task, we can't just bail!
|
||||
|
||||
// Only increment next time if we're done.
|
||||
nextFrame = frameData.type == GLRRunType::END;
|
||||
_assert_(frameData.type == GLRRunType::END || frameData.type == GLRRunType::SYNC);
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(pushMutex_);
|
||||
while (renderThreadQueue_.empty()) {
|
||||
pushCondVar_.wait(lock);
|
||||
}
|
||||
task = renderThreadQueue_.front();
|
||||
renderThreadQueue_.pop();
|
||||
}
|
||||
VLOG("PULL: Running frame %d", threadFrame_);
|
||||
if (firstFrame) {
|
||||
INFO_LOG(G3D, "Running first frame (%d)", threadFrame_);
|
||||
firstFrame = false;
|
||||
|
||||
// We got a task! We can now have pushMutex_ unlocked, allowing the host to
|
||||
// push more work when it feels like it, and just start working.
|
||||
if (task.runType == GLRRunType::EXIT) {
|
||||
// Oh, host wanted out. Let's leave, and also let's notify the host.
|
||||
// This is unlike Vulkan too which can just block on the thread existing.
|
||||
std::unique_lock<std::mutex> lock(syncMutex_);
|
||||
syncCondVar_.notify_one();
|
||||
syncDone_ = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Render the scene.
|
||||
Run(threadFrame_);
|
||||
|
||||
VLOG("PULL: Finished frame %d", threadFrame_);
|
||||
} while (!nextFrame);
|
||||
VLOG(" PULL: Frame %d RUN (%0.3f)", task.frame, time_now_d());
|
||||
if (Run(task)) {
|
||||
// Swap requested, so we just bail the loop.
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLRenderManager::StopThread() {
|
||||
// Since we don't control the thread directly, this will only pause the thread.
|
||||
|
||||
// There's not really a lot to do here anymore.
|
||||
INFO_LOG(G3D, "GLRenderManager::StopThread()");
|
||||
if (run_) {
|
||||
run_ = false;
|
||||
for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) {
|
||||
auto &frameData = frameData_[i];
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(frameData.push_mutex);
|
||||
frameData.push_condVar.notify_all();
|
||||
}
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(frameData.pull_mutex);
|
||||
frameData.pull_condVar.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
// Wait until we've definitely stopped the threadframe.
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
|
||||
INFO_LOG(G3D, "GL submission thread paused. Frame=%d", curFrame_);
|
||||
|
||||
// Eat whatever has been queued up for this frame if anything.
|
||||
Wipe();
|
||||
|
||||
// Wait for any fences to finish and be resignaled, so we don't have sync issues.
|
||||
// Also clean out any queued data, which might refer to things that might not be valid
|
||||
// when we restart...
|
||||
for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) {
|
||||
auto &frameData = frameData_[i];
|
||||
std::unique_lock<std::mutex> lock(frameData.push_mutex);
|
||||
if (frameData.readyForRun || frameData.steps.size() != 0) {
|
||||
Crash();
|
||||
}
|
||||
frameData.readyForRun = false;
|
||||
frameData.readyForSubmit = false;
|
||||
for (size_t i = 0; i < frameData.steps.size(); i++) {
|
||||
delete frameData.steps[i];
|
||||
}
|
||||
frameData.steps.clear();
|
||||
frameData.initSteps.clear();
|
||||
|
||||
while (!frameData.readyForFence) {
|
||||
VLOG("PUSH: Waiting for frame[%d].readyForFence = 1 (stop)", i);
|
||||
frameData.push_condVar.wait(lock);
|
||||
}
|
||||
}
|
||||
std::unique_lock<std::mutex> lock(pushMutex_);
|
||||
GLRRenderThreadTask exitTask{};
|
||||
exitTask.runType = GLRRunType::EXIT;
|
||||
renderThreadQueue_.push(exitTask);
|
||||
pushCondVar_.notify_one();
|
||||
} else {
|
||||
INFO_LOG(G3D, "GL submission thread was already paused.");
|
||||
WARN_LOG(G3D, "GL submission thread was already paused.");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -450,60 +408,51 @@ void GLRenderManager::CopyImageToMemorySync(GLRTexture *texture, int mipLevel, i
|
|||
}
|
||||
|
||||
void GLRenderManager::BeginFrame() {
|
||||
VLOG("BeginFrame");
|
||||
|
||||
#ifdef _DEBUG
|
||||
curProgram_ = nullptr;
|
||||
#endif
|
||||
|
||||
int curFrame = GetCurFrame();
|
||||
FrameData &frameData = frameData_[curFrame];
|
||||
|
||||
// Make sure the very last command buffer from the frame before the previous has been fully executed.
|
||||
FrameData &frameData = frameData_[curFrame];
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(frameData.push_mutex);
|
||||
VLOG("PUSH: BeginFrame (curFrame = %d, readyForFence = %d, time=%0.3f)", curFrame, (int)frameData.readyForFence, time_now_d());
|
||||
std::unique_lock<std::mutex> lock(frameData.fenceMutex);
|
||||
while (!frameData.readyForFence) {
|
||||
VLOG("PUSH: Waiting for frame[%d].readyForFence = 1", curFrame);
|
||||
frameData.push_condVar.wait(lock);
|
||||
frameData.fenceCondVar.wait(lock);
|
||||
}
|
||||
frameData.readyForFence = false;
|
||||
frameData.readyForSubmit = true;
|
||||
}
|
||||
|
||||
VLOG("PUSH: Fencing %d", curFrame);
|
||||
|
||||
// glFenceSync(&frameData.fence...)
|
||||
|
||||
// Must be after the fence - this performs deletes.
|
||||
VLOG("PUSH: BeginFrame %d", curFrame);
|
||||
if (!run_) {
|
||||
WARN_LOG(G3D, "BeginFrame while !run_!");
|
||||
}
|
||||
|
||||
// vulkan_->BeginFrame();
|
||||
// In GL, we have to do deletes on the submission thread.
|
||||
|
||||
insideFrame_ = true;
|
||||
}
|
||||
|
||||
void GLRenderManager::Finish() {
|
||||
curRenderStep_ = nullptr;
|
||||
curRenderStep_ = nullptr; // EndCurRenderStep is this simple here.
|
||||
|
||||
int curFrame = GetCurFrame();
|
||||
FrameData &frameData = frameData_[curFrame];
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(frameData.pull_mutex);
|
||||
VLOG("PUSH: Frame[%d].readyForRun = true, notifying pull", curFrame);
|
||||
frameData.steps = std::move(steps_);
|
||||
steps_.clear();
|
||||
frameData.initSteps = std::move(initSteps_);
|
||||
initSteps_.clear();
|
||||
frameData.readyForRun = true;
|
||||
frameData.type = GLRRunType::END;
|
||||
frameData_[curFrame_].deleter.Take(deleter_);
|
||||
}
|
||||
|
||||
// Notify calls do not in fact need to be done with the mutex locked.
|
||||
frameData.pull_condVar.notify_all();
|
||||
frameData_[curFrame].deleter.Take(deleter_);
|
||||
|
||||
VLOG("PUSH: Finish, pushing task. curFrame = %d", curFrame);
|
||||
GLRRenderThreadTask task;
|
||||
task.frame = curFrame;
|
||||
task.runType = GLRRunType::PRESENT;
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(pushMutex_);
|
||||
renderThreadQueue_.push(task);
|
||||
renderThreadQueue_.back().initSteps = std::move(initSteps_);
|
||||
renderThreadQueue_.back().steps = std::move(steps_);
|
||||
initSteps_.clear();
|
||||
steps_.clear();
|
||||
pushCondVar_.notify_one();
|
||||
}
|
||||
|
||||
curFrame_++;
|
||||
if (curFrame_ >= inflightFrames_)
|
||||
|
@ -512,65 +461,19 @@ void GLRenderManager::Finish() {
|
|||
insideFrame_ = false;
|
||||
}
|
||||
|
||||
void GLRenderManager::BeginSubmitFrame(int frame) {
|
||||
FrameData &frameData = frameData_[frame];
|
||||
// Render thread. Returns true if the caller should handle a swap.
|
||||
bool GLRenderManager::Run(GLRRenderThreadTask &task) {
|
||||
FrameData &frameData = frameData_[task.frame];
|
||||
|
||||
if (!frameData.hasBegun) {
|
||||
frameData.hasBegun = true;
|
||||
|
||||
frameData.deleter_prev.Perform(this, skipGLCalls_);
|
||||
frameData.deleter_prev.Take(frameData.deleter);
|
||||
}
|
||||
}
|
||||
|
||||
// Render thread
|
||||
void GLRenderManager::Submit(int frame, bool triggerFence) {
|
||||
FrameData &frameData = frameData_[frame];
|
||||
|
||||
// In GL, submission happens automatically in Run().
|
||||
|
||||
// When !triggerFence, we notify after syncing with Vulkan.
|
||||
|
||||
if (triggerFence) {
|
||||
VLOG("PULL: Frame %d.readyForFence = true", frame);
|
||||
|
||||
std::unique_lock<std::mutex> lock(frameData.push_mutex);
|
||||
_assert_(frameData.readyForSubmit);
|
||||
frameData.readyForFence = true;
|
||||
frameData.readyForSubmit = false;
|
||||
frameData.push_condVar.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
// Render thread
|
||||
void GLRenderManager::EndSubmitFrame(int frame) {
|
||||
FrameData &frameData = frameData_[frame];
|
||||
frameData.hasBegun = false;
|
||||
|
||||
Submit(frame, true);
|
||||
|
||||
if (!frameData.skipSwap) {
|
||||
if (swapIntervalChanged_) {
|
||||
swapIntervalChanged_ = false;
|
||||
if (swapIntervalFunction_) {
|
||||
swapIntervalFunction_(swapInterval_);
|
||||
}
|
||||
}
|
||||
if (swapFunction_) {
|
||||
swapFunction_();
|
||||
}
|
||||
} else {
|
||||
frameData.skipSwap = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Render thread
|
||||
void GLRenderManager::Run(int frame) {
|
||||
BeginSubmitFrame(frame);
|
||||
|
||||
FrameData &frameData = frameData_[frame];
|
||||
|
||||
auto &stepsOnThread = frameData_[frame].steps;
|
||||
auto &initStepsOnThread = frameData_[frame].initSteps;
|
||||
// queueRunner_.LogSteps(stepsOnThread);
|
||||
queueRunner_.RunInitSteps(initStepsOnThread, skipGLCalls_);
|
||||
initStepsOnThread.clear();
|
||||
queueRunner_.RunInitSteps(task.initSteps, skipGLCalls_);
|
||||
|
||||
// Run this after RunInitSteps so any fresh GLRBuffers for the pushbuffers can get created.
|
||||
if (!skipGLCalls_) {
|
||||
|
@ -584,13 +487,12 @@ void GLRenderManager::Run(int frame) {
|
|||
int passes = GetVRPassesCount();
|
||||
for (int i = 0; i < passes; i++) {
|
||||
PreVRFrameRender(i);
|
||||
queueRunner_.RunSteps(stepsOnThread, skipGLCalls_, i < passes - 1, true);
|
||||
queueRunner_.RunSteps(task.steps, skipGLCalls_, i < passes - 1, true);
|
||||
PostVRFrameRender();
|
||||
}
|
||||
} else {
|
||||
queueRunner_.RunSteps(stepsOnThread, skipGLCalls_, false, false);
|
||||
queueRunner_.RunSteps(task.steps, skipGLCalls_, false, false);
|
||||
}
|
||||
stepsOnThread.clear();
|
||||
|
||||
if (!skipGLCalls_) {
|
||||
for (auto iter : frameData.activePushBuffers) {
|
||||
|
@ -598,89 +500,88 @@ void GLRenderManager::Run(int frame) {
|
|||
}
|
||||
}
|
||||
|
||||
switch (frameData.type) {
|
||||
case GLRRunType::END:
|
||||
EndSubmitFrame(frame);
|
||||
bool swapRequest = false;
|
||||
|
||||
switch (task.runType) {
|
||||
case GLRRunType::PRESENT:
|
||||
if (!frameData.skipSwap) {
|
||||
if (swapIntervalChanged_) {
|
||||
swapIntervalChanged_ = false;
|
||||
if (swapIntervalFunction_) {
|
||||
swapIntervalFunction_(swapInterval_);
|
||||
}
|
||||
}
|
||||
// This is the swapchain framebuffer flip.
|
||||
if (swapFunction_) {
|
||||
VLOG(" PULL: SwapFunction()");
|
||||
swapFunction_();
|
||||
if (!retainControl_) {
|
||||
// get out of here.
|
||||
swapRequest = true;
|
||||
}
|
||||
} else {
|
||||
VLOG(" PULL: SwapRequested");
|
||||
swapRequest = true;
|
||||
}
|
||||
} else {
|
||||
frameData.skipSwap = false;
|
||||
}
|
||||
frameData.hasBegun = false;
|
||||
|
||||
VLOG(" PULL: Frame %d.readyForFence = true", task.frame);
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(frameData.fenceMutex);
|
||||
frameData.readyForFence = true;
|
||||
frameData.fenceCondVar.notify_one();
|
||||
// At this point, we're done with this framedata (for now).
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case GLRRunType::SYNC:
|
||||
EndSyncFrame(frame);
|
||||
frameData.hasBegun = false;
|
||||
|
||||
// glFinish is not actually necessary here, and won't be unless we start using
|
||||
// glBufferStorage. Then we need to use fences.
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(syncMutex_);
|
||||
syncDone_ = true;
|
||||
syncCondVar_.notify_one();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
_assert_(false);
|
||||
}
|
||||
|
||||
VLOG("PULL: Finished running frame %d", frame);
|
||||
VLOG(" PULL: ::Run(): Done running tasks");
|
||||
return swapRequest;
|
||||
}
|
||||
|
||||
void GLRenderManager::FlushSync() {
|
||||
int curFrame = curFrame_;
|
||||
FrameData &frameData = frameData_[curFrame];
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(frameData.pull_mutex);
|
||||
VLOG("PUSH: Frame[%d].readyForRun = true (sync)", curFrame);
|
||||
frameData.initSteps = std::move(initSteps_);
|
||||
initSteps_.clear();
|
||||
frameData.steps = std::move(steps_);
|
||||
VLOG("PUSH: Frame[%d].readyForRun = true (sync)", curFrame_);
|
||||
|
||||
GLRRenderThreadTask task;
|
||||
task.frame = curFrame_;
|
||||
task.runType = GLRRunType::SYNC;
|
||||
|
||||
std::unique_lock<std::mutex> lock(pushMutex_);
|
||||
renderThreadQueue_.push(task);
|
||||
renderThreadQueue_.back().initSteps = std::move(initSteps_);
|
||||
renderThreadQueue_.back().steps = std::move(steps_);
|
||||
pushCondVar_.notify_one();
|
||||
steps_.clear();
|
||||
frameData.readyForRun = true;
|
||||
_assert_(frameData.readyForFence == false);
|
||||
frameData.type = GLRRunType::SYNC;
|
||||
frameData.pull_condVar.notify_all();
|
||||
}
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(frameData.push_mutex);
|
||||
std::unique_lock<std::mutex> lock(syncMutex_);
|
||||
// Wait for the flush to be hit, since we're syncing.
|
||||
while (!frameData.readyForFence) {
|
||||
VLOG("PUSH: Waiting for frame[%d].readyForFence = 1 (sync)", curFrame);
|
||||
frameData.push_condVar.wait(lock);
|
||||
}
|
||||
frameData.readyForFence = false;
|
||||
frameData.readyForSubmit = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Render thread
|
||||
void GLRenderManager::EndSyncFrame(int frame) {
|
||||
FrameData &frameData = frameData_[frame];
|
||||
Submit(frame, false);
|
||||
|
||||
// glFinish is not actually necessary here, and won't be until we start using
|
||||
// glBufferStorage. Then we need to use fences.
|
||||
// glFinish();
|
||||
|
||||
// At this point we can resume filling the command buffers for the current frame since
|
||||
// we know the device is idle - and thus all previously enqueued command buffers have been processed.
|
||||
// No need to switch to the next frame number.
|
||||
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(frameData.push_mutex);
|
||||
frameData.readyForFence = true;
|
||||
frameData.readyForSubmit = true;
|
||||
frameData.push_condVar.notify_all();
|
||||
}
|
||||
}
|
||||
|
||||
void GLRenderManager::Wipe() {
|
||||
initSteps_.clear();
|
||||
for (auto step : steps_) {
|
||||
delete step;
|
||||
}
|
||||
steps_.clear();
|
||||
}
|
||||
|
||||
void GLRenderManager::WaitUntilQueueIdle() {
|
||||
// Just wait for all frames to be ready.
|
||||
for (int i = 0; i < MAX_INFLIGHT_FRAMES; i++) {
|
||||
FrameData &frameData = frameData_[i];
|
||||
|
||||
std::unique_lock<std::mutex> lock(frameData.push_mutex);
|
||||
// Ignore unsubmitted frames.
|
||||
while (!frameData.readyForFence && frameData.readyForRun) {
|
||||
VLOG("PUSH: Waiting for frame[%d].readyForFence = 1 (wait idle)", i);
|
||||
frameData.push_condVar.wait(lock);
|
||||
while (!syncDone_) {
|
||||
VLOG("PUSH: Waiting for frame[%d].readyForFence = 1 (sync)", curFrame_);
|
||||
syncCondVar_.wait(lock);
|
||||
}
|
||||
syncDone_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <set>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <queue>
|
||||
#include <condition_variable>
|
||||
|
||||
#include "Common/GPU/OpenGL/GLCommon.h"
|
||||
|
@ -349,11 +350,29 @@ private:
|
|||
GLBufferStrategy strategy_ = GLBufferStrategy::SUBDATA;
|
||||
};
|
||||
|
||||
enum class GLRRunType {
|
||||
END,
|
||||
SYNC,
|
||||
class GLRInputLayout {
|
||||
public:
|
||||
struct Entry {
|
||||
int location;
|
||||
int count;
|
||||
GLenum type;
|
||||
GLboolean normalized;
|
||||
int stride;
|
||||
intptr_t offset;
|
||||
};
|
||||
std::vector<Entry> entries;
|
||||
int semanticsMask_ = 0;
|
||||
};
|
||||
|
||||
enum class GLRRunType {
|
||||
PRESENT,
|
||||
SYNC,
|
||||
EXIT,
|
||||
};
|
||||
|
||||
class GLRenderManager;
|
||||
class GLPushBuffer;
|
||||
|
||||
class GLDeleter {
|
||||
public:
|
||||
void Perform(GLRenderManager *renderManager, bool skipGLCalls);
|
||||
|
@ -373,18 +392,14 @@ public:
|
|||
std::vector<GLPushBuffer *> pushBuffers;
|
||||
};
|
||||
|
||||
class GLRInputLayout {
|
||||
public:
|
||||
struct Entry {
|
||||
int location;
|
||||
int count;
|
||||
GLenum type;
|
||||
GLboolean normalized;
|
||||
int stride;
|
||||
intptr_t offset;
|
||||
};
|
||||
std::vector<Entry> entries;
|
||||
int semanticsMask_ = 0;
|
||||
// These are enqueued from the main thread,
|
||||
// and the render thread pops them off
|
||||
struct GLRRenderThreadTask {
|
||||
std::vector<GLRStep *> steps;
|
||||
std::vector<GLRInitStep> initSteps;
|
||||
|
||||
int frame;
|
||||
GLRRunType runType;
|
||||
};
|
||||
|
||||
// Note: The GLRenderManager is created and destroyed on the render thread, and the latter
|
||||
|
@ -395,9 +410,15 @@ public:
|
|||
GLRenderManager() {}
|
||||
~GLRenderManager();
|
||||
|
||||
|
||||
void SetInvalidationCallback(InvalidationCallback callback) {
|
||||
invalidationCallback_ = callback;
|
||||
}
|
||||
|
||||
void ThreadStart(Draw::DrawContext *draw);
|
||||
void ThreadEnd();
|
||||
bool ThreadFrame(); // Returns true if it did anything. False means the queue was empty.
|
||||
|
||||
void SetErrorCallback(ErrorCallbackFn callback, void *userdata) {
|
||||
queueRunner_.SetErrorCallback(callback, userdata);
|
||||
}
|
||||
|
@ -406,27 +427,17 @@ public:
|
|||
caps_ = caps;
|
||||
}
|
||||
|
||||
void ThreadStart(Draw::DrawContext *draw);
|
||||
void ThreadEnd();
|
||||
bool ThreadFrame(); // Returns false to request exiting the loop.
|
||||
|
||||
// Makes sure that the GPU has caught up enough that we can start writing buffers of this frame again.
|
||||
void BeginFrame();
|
||||
// Can run on a different thread!
|
||||
void Finish();
|
||||
void Run(int frame);
|
||||
|
||||
// Zaps queued up commands. Use if you know there's a risk you've queued up stuff that has already been deleted. Can happen during in-game shutdown.
|
||||
void Wipe();
|
||||
|
||||
// Wait until no frames are pending. Use during shutdown before freeing pointers.
|
||||
void WaitUntilQueueIdle();
|
||||
void Finish();
|
||||
bool Run(GLRRenderThreadTask &task);
|
||||
|
||||
// Creation commands. These were not needed in Vulkan since there we can do that on the main thread.
|
||||
// We pass in width/height here even though it's not strictly needed until we support glTextureStorage
|
||||
// and then we'll also need formats and stuff.
|
||||
GLRTexture *CreateTexture(GLenum target, int width, int height, int depth, int numMips) {
|
||||
GLRInitStep step{ GLRInitStepType::CREATE_TEXTURE };
|
||||
GLRInitStep step { GLRInitStepType::CREATE_TEXTURE };
|
||||
step.create_texture.texture = new GLRTexture(caps_, width, height, depth, numMips);
|
||||
step.create_texture.texture->target = target;
|
||||
initSteps_.push_back(step);
|
||||
|
@ -981,8 +992,9 @@ public:
|
|||
_dbg_assert_(foundCount == 1);
|
||||
}
|
||||
|
||||
void SetSwapFunction(std::function<void()> swapFunction) {
|
||||
void SetSwapFunction(std::function<void()> swapFunction, bool retainControl) {
|
||||
swapFunction_ = swapFunction;
|
||||
retainControl_ = retainControl;
|
||||
}
|
||||
|
||||
void SetSwapIntervalFunction(std::function<void(int)> swapIntervalFunction) {
|
||||
|
@ -1014,13 +1026,8 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
void BeginSubmitFrame(int frame);
|
||||
void EndSubmitFrame(int frame);
|
||||
void Submit(int frame, bool triggerFence);
|
||||
|
||||
// Bad for performance but sometimes necessary for synchronous CPU readbacks (screenshots and whatnot).
|
||||
void FlushSync();
|
||||
void EndSyncFrame(int frame);
|
||||
|
||||
// When using legacy functionality for push buffers (glBufferData), we need to flush them
|
||||
// before actually making the glDraw* calls. It's best if the render manager handles that.
|
||||
|
@ -1030,26 +1037,14 @@ private:
|
|||
|
||||
// Per-frame data, round-robin so we can overlap submission with execution of the previous frame.
|
||||
struct FrameData {
|
||||
std::mutex push_mutex;
|
||||
std::condition_variable push_condVar;
|
||||
|
||||
std::mutex pull_mutex;
|
||||
std::condition_variable pull_condVar;
|
||||
|
||||
bool readyForFence = true;
|
||||
bool readyForRun = false;
|
||||
bool readyForSubmit = false;
|
||||
|
||||
bool skipSwap = false;
|
||||
GLRRunType type = GLRRunType::END;
|
||||
|
||||
// GLuint fence; For future AZDO stuff?
|
||||
std::vector<GLRStep *> steps;
|
||||
std::vector<GLRInitStep> initSteps;
|
||||
std::mutex fenceMutex;
|
||||
std::condition_variable fenceCondVar;
|
||||
bool readyForFence = true;
|
||||
|
||||
// Swapchain.
|
||||
bool hasBegun = false;
|
||||
uint32_t curSwapchainImage = -1;
|
||||
|
||||
GLDeleter deleter;
|
||||
GLDeleter deleter_prev;
|
||||
|
@ -1067,16 +1062,23 @@ private:
|
|||
|
||||
// Execution time state
|
||||
bool run_ = true;
|
||||
|
||||
// Thread is managed elsewhere, and should call ThreadFrame.
|
||||
std::mutex mutex_;
|
||||
int threadInitFrame_ = 0;
|
||||
GLQueueRunner queueRunner_;
|
||||
|
||||
// Thread state
|
||||
int threadFrame_ = -1;
|
||||
// For pushing data on the queue.
|
||||
std::mutex pushMutex_;
|
||||
std::condition_variable pushCondVar_;
|
||||
|
||||
bool nextFrame = false;
|
||||
bool firstFrame = true;
|
||||
std::queue<GLRRenderThreadTask> renderThreadQueue_;
|
||||
|
||||
// For readbacks and other reasons we need to sync with the render thread.
|
||||
std::mutex syncMutex_;
|
||||
std::condition_variable syncCondVar_;
|
||||
|
||||
bool firstFrame_ = true;
|
||||
bool vrRenderStarted_ = false;
|
||||
bool syncDone_ = false;
|
||||
|
||||
GLDeleter deleter_;
|
||||
bool skipGLCalls_ = false;
|
||||
|
@ -1085,6 +1087,7 @@ private:
|
|||
|
||||
std::function<void()> swapFunction_;
|
||||
std::function<void(int)> swapIntervalFunction_;
|
||||
bool retainControl_ = false;
|
||||
GLBufferStrategy bufferStrategy_ = GLBufferStrategy::SUBDATA;
|
||||
|
||||
int inflightFrames_ = MAX_INFLIGHT_FRAMES;
|
||||
|
|
|
@ -212,7 +212,6 @@ GLuint ShaderStageToOpenGL(ShaderStage stage) {
|
|||
class OpenGLShaderModule : public ShaderModule {
|
||||
public:
|
||||
OpenGLShaderModule(GLRenderManager *render, ShaderStage stage, const std::string &tag) : render_(render), stage_(stage), tag_(tag) {
|
||||
DEBUG_LOG(G3D, "Shader module created (%p)", this);
|
||||
glstage_ = ShaderStageToOpenGL(stage);
|
||||
}
|
||||
|
||||
|
|
|
@ -1197,11 +1197,11 @@ void VulkanRenderManager::Finish() {
|
|||
int curFrame = vulkan_->GetCurFrame();
|
||||
FrameData &frameData = frameData_[curFrame];
|
||||
|
||||
VLOG("PUSH: Frame[%d]", curFrame);
|
||||
VKRRenderThreadTask task;
|
||||
task.frame = curFrame;
|
||||
task.runType = VKRRunType::PRESENT;
|
||||
{
|
||||
VLOG("PUSH: Frame[%d]", curFrame);
|
||||
VKRRenderThreadTask task;
|
||||
task.frame = curFrame;
|
||||
task.runType = VKRRunType::PRESENT;
|
||||
std::unique_lock<std::mutex> lock(pushMutex_);
|
||||
renderThreadQueue_.push(task);
|
||||
renderThreadQueue_.back().steps = std::move(steps_);
|
||||
|
@ -1327,7 +1327,7 @@ void VulkanRenderManager::FlushSync() {
|
|||
std::unique_lock<std::mutex> lock(syncMutex_);
|
||||
// Wait for the flush to be hit, since we're syncing.
|
||||
while (!frameData.syncDone) {
|
||||
VLOG("PUSH: Waiting for frame[%d].readyForFence = 1 (sync)", curFrame);
|
||||
VLOG("PUSH: Waiting for frame[%d].syncDone = 1 (sync)", curFrame);
|
||||
syncCondVar_.wait(lock);
|
||||
}
|
||||
frameData.syncDone = false;
|
||||
|
|
|
@ -198,7 +198,6 @@ public:
|
|||
const std::string &GetSource() const { return source_; }
|
||||
~VKShaderModule() {
|
||||
if (module_) {
|
||||
DEBUG_LOG(G3D, "Queueing %s (shmodule %p) for release", tag_.c_str(), module_);
|
||||
VkShaderModule shaderModule = module_->BlockUntilReady();
|
||||
vulkan_->Delete().QueueDeleteShaderModule(shaderModule);
|
||||
vulkan_->Delete().QueueCallback([](VulkanContext *context, void *m) {
|
||||
|
@ -213,7 +212,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
VulkanContext *vulkan_;
|
||||
VulkanContext *vulkan_ = nullptr;
|
||||
Promise<VkShaderModule> *module_ = nullptr;
|
||||
VkShaderStageFlagBits vkstage_;
|
||||
bool ok_ = false;
|
||||
|
@ -268,7 +267,6 @@ public:
|
|||
vkrDesc = new VKRGraphicsPipelineDesc();
|
||||
}
|
||||
~VKPipeline() {
|
||||
DEBUG_LOG(G3D, "Queueing %s (pipeline) for release", tag_.c_str());
|
||||
if (pipeline) {
|
||||
pipeline->QueueForDeletion(vulkan_);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ const char *GetDeviceName(int deviceId) {
|
|||
case DEVICE_ID_XINPUT_3: return "x360_4";
|
||||
case DEVICE_ID_ACCELEROMETER: return "accelerometer";
|
||||
case DEVICE_ID_MOUSE: return "mouse";
|
||||
case DEVICE_ID_XR_HMD: return "xr_hmd";
|
||||
case DEVICE_ID_XR_CONTROLLER_LEFT: return "xr_l";
|
||||
case DEVICE_ID_XR_CONTROLLER_RIGHT: return "xr_r";
|
||||
default:
|
||||
|
|
|
@ -31,6 +31,7 @@ enum {
|
|||
DEVICE_ID_XINPUT_2 = 22,
|
||||
DEVICE_ID_XINPUT_3 = 23,
|
||||
DEVICE_ID_ACCELEROMETER = 30,
|
||||
DEVICE_ID_XR_HMD = 39,
|
||||
DEVICE_ID_XR_CONTROLLER_LEFT = 40,
|
||||
DEVICE_ID_XR_CONTROLLER_RIGHT = 41,
|
||||
DEVICE_ID_TOUCH = 42,
|
||||
|
|
|
@ -263,13 +263,19 @@ typedef enum _keycode_t {
|
|||
NKCODE_EXT_MOUSEWHEEL_UP = 1008,
|
||||
NKCODE_EXT_MOUSEWHEEL_DOWN = 1009,
|
||||
|
||||
// Virtual reality controller motion
|
||||
// Virtual reality motion
|
||||
NKCODE_EXT_MOTION_UP = 1101,
|
||||
NKCODE_EXT_MOTION_DOWN = 1102,
|
||||
NKCODE_EXT_MOTION_LEFT = 1103,
|
||||
NKCODE_EXT_MOTION_RIGHT = 1104,
|
||||
NKCODE_EXT_MOTION_FORWARD = 1105,
|
||||
|
||||
// Virtual reality rotation
|
||||
NKCODE_EXT_ROTATION_UP = 1111,
|
||||
NKCODE_EXT_ROTATION_DOWN = 1112,
|
||||
NKCODE_EXT_ROTATION_LEFT = 1113,
|
||||
NKCODE_EXT_ROTATION_RIGHT = 1114,
|
||||
|
||||
NKCODE_MAX
|
||||
} keycode_t;
|
||||
|
||||
|
|
|
@ -197,6 +197,28 @@ void CPUInfo::Detect()
|
|||
#endif
|
||||
}
|
||||
|
||||
std::vector<std::string> CPUInfo::Features() {
|
||||
std::vector<std::string> features;
|
||||
|
||||
struct Flag {
|
||||
bool &flag;
|
||||
const char *str;
|
||||
};
|
||||
const Flag list[] = {
|
||||
{ bXBurst1, "XBurst1" },
|
||||
{ bXBurst2, "XBurst2" },
|
||||
{ CPU64bit, "64-bit" },
|
||||
};
|
||||
|
||||
for (auto &item : list) {
|
||||
if (item.flag) {
|
||||
features.push_back(item.str);
|
||||
}
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
// Turn the cpu info into a string we can show
|
||||
std::string CPUInfo::Summarize()
|
||||
{
|
||||
|
@ -205,10 +227,11 @@ std::string CPUInfo::Summarize()
|
|||
sum = StringFromFormat("%s, %i core", cpu_string, num_cores);
|
||||
else
|
||||
sum = StringFromFormat("%s, %i cores", cpu_string, num_cores);
|
||||
if (bXBurst1) sum += ", XBurst1";
|
||||
if (bXBurst2) sum += ", XBurst2";
|
||||
if (CPU64bit) sum += ", 64-bit";
|
||||
|
||||
auto features = Features();
|
||||
for (std::string &feature : features) {
|
||||
sum += ", " + feature;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,11 +18,12 @@ public:
|
|||
// Public variables since it doesn't make sense
|
||||
// to bother with accessors for all these.
|
||||
int status = 100;
|
||||
// Intentional misspelling.
|
||||
char *referer = nullptr;
|
||||
|
||||
char *referer = nullptr; // Intentional misspelling.
|
||||
char *user_agent = nullptr;
|
||||
char *resource = nullptr;
|
||||
char *params = nullptr;
|
||||
|
||||
int content_length = -1;
|
||||
std::unordered_map<std::string, std::string> other;
|
||||
enum RequestType {
|
||||
|
|
|
@ -81,7 +81,7 @@ Request::~Request() {
|
|||
}
|
||||
delete in_;
|
||||
if (!out_->Empty()) {
|
||||
ERROR_LOG(IO, "Output not empty - connection abort?");
|
||||
ERROR_LOG(IO, "Output not empty - connection abort? (%s)", this->header_.resource);
|
||||
}
|
||||
delete out_;
|
||||
}
|
||||
|
|
|
@ -37,8 +37,9 @@ bool Buffer::FlushSocket(uintptr_t sock, double timeout, bool *cancelled) {
|
|||
}
|
||||
}
|
||||
int sent = send(sock, &data_[pos], (int)(end - pos), MSG_NOSIGNAL);
|
||||
// TODO: Do we need some retry logic here, instead of just giving up?
|
||||
if (sent < 0) {
|
||||
ERROR_LOG(IO, "FlushSocket failed");
|
||||
ERROR_LOG(IO, "FlushSocket failed to send: %d", errno);
|
||||
return false;
|
||||
}
|
||||
pos += sent;
|
||||
|
|
|
@ -18,6 +18,12 @@
|
|||
#include "ppsspp_config.h"
|
||||
#if PPSSPP_ARCH(RISCV64)
|
||||
|
||||
#include "ext/cpu_features/include/cpuinfo_riscv.h"
|
||||
|
||||
#if defined(CPU_FEATURES_OS_LINUX)
|
||||
#define USE_CPU_FEATURES 1
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
|
@ -174,20 +180,63 @@ void CPUInfo::Detect()
|
|||
RiscV_C = ExtensionSupported(hwcap, 'C');
|
||||
RiscV_V = ExtensionSupported(hwcap, 'V');
|
||||
RiscV_B = ExtensionSupported(hwcap, 'B');
|
||||
// Let's assume for now...
|
||||
RiscV_Zicsr = RiscV_M && RiscV_A && RiscV_F && RiscV_D;
|
||||
|
||||
#ifdef USE_CPU_FEATURES
|
||||
cpu_features::RiscvInfo info = cpu_features::GetRiscvInfo();
|
||||
CPU64bit = info.features.RV64I;
|
||||
RiscV_M = info.features.M;
|
||||
RiscV_A = info.features.A;
|
||||
RiscV_F = info.features.F;
|
||||
RiscV_D = info.features.D;
|
||||
RiscV_C = info.features.C;
|
||||
RiscV_Zicsr = info.features.Zicsr;
|
||||
|
||||
truncate_cpy(brand_string, info.uarch);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector<std::string> CPUInfo::Features() {
|
||||
std::vector<std::string> features;
|
||||
|
||||
struct Flag {
|
||||
bool &flag;
|
||||
const char *str;
|
||||
};
|
||||
const Flag list[] = {
|
||||
{ RiscV_M, "Muldiv" },
|
||||
{ RiscV_A, "Atomic" },
|
||||
{ RiscV_F, "Float" },
|
||||
{ RiscV_D, "Double" },
|
||||
{ RiscV_C, "Compressed" },
|
||||
{ RiscV_V, "Vector" },
|
||||
{ RiscV_B, "Bitmanip" },
|
||||
{ RiscV_Zicsr, "Zicsr" },
|
||||
{ CPU64bit, "64-bit" },
|
||||
};
|
||||
|
||||
for (auto &item : list) {
|
||||
if (item.flag) {
|
||||
features.push_back(item.str);
|
||||
}
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
// Turn the cpu info into a string we can show
|
||||
std::string CPUInfo::Summarize()
|
||||
{
|
||||
std::string CPUInfo::Summarize() {
|
||||
std::string sum;
|
||||
if (num_cores == 1)
|
||||
sum = StringFromFormat("%s, %i core", cpu_string, num_cores);
|
||||
else
|
||||
sum = StringFromFormat("%s, %i cores", cpu_string, num_cores);
|
||||
if (CPU64bit) sum += ", 64-bit";
|
||||
|
||||
//TODO: parse "isa : rv64imafdc" from /proc/cpuinfo
|
||||
|
||||
auto features = Features();
|
||||
for (std::string &feature : features) {
|
||||
sum += ", " + feature;
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
|
|
@ -50,8 +50,7 @@ static inline bool SupportsAtomic() {
|
|||
}
|
||||
|
||||
static inline bool SupportsZicsr() {
|
||||
// TODO
|
||||
return false;
|
||||
return cpu_info.RiscV_Zicsr;
|
||||
}
|
||||
|
||||
static inline bool SupportsVector() {
|
||||
|
@ -63,6 +62,11 @@ static inline bool SupportsBitmanip(char zbx) {
|
|||
return cpu_info.RiscV_B;
|
||||
}
|
||||
|
||||
static inline bool SupportsFloatHalf(bool allowMin = false) {
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
|
||||
enum class Opcode32 {
|
||||
// Note: invalid, just used for FixupBranch.
|
||||
ZERO = 0b0000000,
|
||||
|
@ -227,6 +231,7 @@ enum class Funct3 {
|
|||
enum class Funct2 {
|
||||
S = 0b00,
|
||||
D = 0b01,
|
||||
H = 0b10,
|
||||
Q = 0b11,
|
||||
|
||||
C_SRLI = 0b00,
|
||||
|
@ -875,10 +880,13 @@ static inline u16 EncodeCJ(Opcode16 op, s32 simm12, Funct3 funct3) {
|
|||
return (u16)op | (imm11_4_9_8_10_6_7_3_2_1_5 << 2) | ((u16)funct3 << 13);
|
||||
}
|
||||
|
||||
static inline Funct3 BitsToFunct3(int bits, bool useFloat = false) {
|
||||
static inline Funct3 BitsToFunct3(int bits, bool useFloat = false, bool allowHalfMin = false) {
|
||||
int bitsSupported = useFloat ? FloatBitsSupported() : BitsSupported();
|
||||
_assert_msg_(bitsSupported >= bits, "Cannot use funct3 width %d, only have %d", bits, bitsSupported);
|
||||
switch (bits) {
|
||||
case 16:
|
||||
_assert_msg_(SupportsFloatHalf(allowHalfMin), "Cannot use width 16 without Zfh/Zfhmin");
|
||||
return Funct3::LS_H;
|
||||
case 32:
|
||||
return Funct3::LS_W;
|
||||
case 64:
|
||||
|
@ -889,9 +897,12 @@ static inline Funct3 BitsToFunct3(int bits, bool useFloat = false) {
|
|||
}
|
||||
}
|
||||
|
||||
static inline Funct2 BitsToFunct2(int bits) {
|
||||
static inline Funct2 BitsToFunct2(int bits, bool allowHalfMin = false) {
|
||||
_assert_msg_(FloatBitsSupported() >= bits, "Cannot use funct2 width %d, only have %d", bits, FloatBitsSupported());
|
||||
switch (bits) {
|
||||
case 16:
|
||||
_assert_msg_(SupportsFloatHalf(allowHalfMin), "Cannot use width 16 without Zfh/Zfhmin");
|
||||
return Funct2::H;
|
||||
case 32:
|
||||
return Funct2::S;
|
||||
case 64:
|
||||
|
@ -916,6 +927,9 @@ static inline int FConvToFloatBits(FConv c) {
|
|||
return 32;
|
||||
case FConv::D:
|
||||
return 64;
|
||||
case FConv::H:
|
||||
_assert_msg_(SupportsFloatHalf(true), "Cannot use width 16 without Zfh/Zfhmin");
|
||||
return 16;
|
||||
case FConv::Q:
|
||||
return 128;
|
||||
}
|
||||
|
@ -926,6 +940,7 @@ static inline int FConvToIntegerBits(FConv c) {
|
|||
switch (c) {
|
||||
case FConv::S:
|
||||
case FConv::D:
|
||||
case FConv::H:
|
||||
case FConv::Q:
|
||||
break;
|
||||
|
||||
|
@ -1976,7 +1991,7 @@ void RiscVEmitter::FL(int bits, RiscVReg rd, RiscVReg rs1, s32 simm12) {
|
|||
}
|
||||
}
|
||||
|
||||
Write32(EncodeI(Opcode32::LOAD_FP, rd, BitsToFunct3(bits, true), rs1, simm12));
|
||||
Write32(EncodeI(Opcode32::LOAD_FP, rd, BitsToFunct3(bits, true, true), rs1, simm12));
|
||||
}
|
||||
|
||||
void RiscVEmitter::FS(int bits, RiscVReg rs2, RiscVReg rs1, s32 simm12) {
|
||||
|
@ -2000,7 +2015,7 @@ void RiscVEmitter::FS(int bits, RiscVReg rs2, RiscVReg rs1, s32 simm12) {
|
|||
}
|
||||
}
|
||||
|
||||
Write32(EncodeS(Opcode32::STORE_FP, BitsToFunct3(bits, true), rs1, rs2, simm12));
|
||||
Write32(EncodeS(Opcode32::STORE_FP, BitsToFunct3(bits, true, true), rs1, rs2, simm12));
|
||||
}
|
||||
|
||||
void RiscVEmitter::FMADD(int bits, RiscVReg rd, RiscVReg rs1, RiscVReg rs2, RiscVReg rs3, Round rm) {
|
||||
|
@ -2069,8 +2084,8 @@ void RiscVEmitter::FCVT(FConv to, FConv from, RiscVReg rd, RiscVReg rs1, Round r
|
|||
|
||||
if (integerBits == 0) {
|
||||
// Convert between float widths.
|
||||
Funct2 fromFmt = BitsToFunct2(FConvToFloatBits(from));
|
||||
Funct2 toFmt = BitsToFunct2(FConvToFloatBits(to));
|
||||
Funct2 fromFmt = BitsToFunct2(FConvToFloatBits(from), true);
|
||||
Funct2 toFmt = BitsToFunct2(FConvToFloatBits(to), true);
|
||||
if (FConvToFloatBits(to) > FConvToFloatBits(from)) {
|
||||
_assert_msg_(rm == Round::DYNAMIC || rm == Round::NEAREST_EVEN, "Invalid rounding mode for widening FCVT");
|
||||
rm = Round::NEAREST_EVEN;
|
||||
|
@ -2090,6 +2105,7 @@ void RiscVEmitter::FMV(FMv to, FMv from, RiscVReg rd, RiscVReg rs1) {
|
|||
switch (to == FMv::X ? from : to) {
|
||||
case FMv::D: bits = 64; break;
|
||||
case FMv::W: bits = 32; break;
|
||||
case FMv::H: bits = 16; break;
|
||||
case FMv::X: bits = 0; break;
|
||||
}
|
||||
|
||||
|
@ -2099,7 +2115,7 @@ void RiscVEmitter::FMV(FMv to, FMv from, RiscVReg rd, RiscVReg rs1) {
|
|||
_assert_msg_(from == FMv::X ? IsGPR(rs1) : IsFPR(rs1), "%s rs1 of wrong type", __func__);
|
||||
|
||||
Funct5 funct5 = to == FMv::X ? Funct5::FMV_TOX : Funct5::FMV_FROMX;
|
||||
Write32(EncodeR(Opcode32::OP_FP, rd, Funct3::FMV, rs1, F0, BitsToFunct2(bits), funct5));
|
||||
Write32(EncodeR(Opcode32::OP_FP, rd, Funct3::FMV, rs1, F0, BitsToFunct2(bits, true), funct5));
|
||||
}
|
||||
|
||||
void RiscVEmitter::FEQ(int bits, RiscVReg rd, RiscVReg rs1, RiscVReg rs2) {
|
||||
|
|
|
@ -90,11 +90,13 @@ enum class FConv {
|
|||
|
||||
S = 0x1000,
|
||||
D = 0x1001,
|
||||
H = 0x1002,
|
||||
Q = 0x1003,
|
||||
};
|
||||
|
||||
enum class FMv {
|
||||
X,
|
||||
H,
|
||||
W,
|
||||
D,
|
||||
};
|
||||
|
|
|
@ -217,6 +217,16 @@ void ThreadManager::Init(int numRealCores, int numLogicalCoresPerCpu) {
|
|||
}
|
||||
|
||||
void ThreadManager::EnqueueTask(Task *task) {
|
||||
if (task->Type() == TaskType::DEDICATED_THREAD) {
|
||||
std::thread th([=](Task *task) {
|
||||
SetCurrentThreadName("DedicatedThreadTask");
|
||||
task->Run();
|
||||
task->Release();
|
||||
}, task);
|
||||
th.detach();
|
||||
return;
|
||||
}
|
||||
|
||||
_assert_msg_(IsInitialized(), "ThreadManager not initialized");
|
||||
|
||||
int minThread;
|
||||
|
@ -270,6 +280,8 @@ void ThreadManager::EnqueueTask(Task *task) {
|
|||
}
|
||||
|
||||
void ThreadManager::EnqueueTaskOnThread(int threadNum, Task *task) {
|
||||
_assert_msg_(task->Type() != TaskType::DEDICATED_THREAD, "Dedicated thread tasks can't be put on specific threads");
|
||||
|
||||
_assert_msg_(threadNum >= 0 && threadNum < (int)global_->threads_.size(), "Bad threadnum or not initialized");
|
||||
ThreadContext *thread = global_->threads_[threadNum];
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
enum class TaskType {
|
||||
CPU_COMPUTE,
|
||||
IO_BLOCKING,
|
||||
DEDICATED_THREAD, // These can never get stuck in queue behind others, but are more expensive to launch. Cannot use I/O.
|
||||
};
|
||||
|
||||
// Implement this to make something that you can run on the thread manager.
|
||||
|
|
|
@ -172,7 +172,7 @@ void UIContext::ActivateTopScissor() {
|
|||
int h = std::max(0.0f, ceilf(scale_y * bounds.h));
|
||||
if (x < 0 || y < 0 || x + w > pixel_xres || y + h > pixel_yres) {
|
||||
// This won't actually report outside a game, but we can try.
|
||||
ERROR_LOG(G3D, "UI scissor out of bounds in %sScreen: %d,%d-%d,%d / %d,%d", screenTag_ ? screenTag_ : "N/A", x, y, w, h, pixel_xres, pixel_yres);
|
||||
DEBUG_LOG(G3D, "UI scissor out of bounds in %sScreen: %d,%d-%d,%d / %d,%d", screenTag_ ? screenTag_ : "N/A", x, y, w, h, pixel_xres, pixel_yres);
|
||||
if (x < 0) { w += x; x = 0; }
|
||||
if (y < 0) { h += y; y = 0; }
|
||||
if (x >= pixel_xres) { x = pixel_xres - 1; }
|
||||
|
|
|
@ -343,7 +343,6 @@ void SliderFloatPopupScreen::CreatePopupContents(UI::ViewGroup *parent) {
|
|||
edit_->SetTextColor(dc.theme->itemStyle.fgColor);
|
||||
edit_->SetTextAlign(FLAG_DYNAMIC_ASCII);
|
||||
edit_->OnTextChange.Handle(this, &SliderFloatPopupScreen::OnTextChange);
|
||||
changing_ = false;
|
||||
lin->Add(edit_);
|
||||
if (!units_.empty())
|
||||
lin->Add(new TextView(units_, new LinearLayoutParams(10.0f)))->SetTextColor(dc.theme->itemStyle.fgColor);
|
||||
|
|
|
@ -99,7 +99,7 @@ private:
|
|||
class SliderFloatPopupScreen : public PopupScreen {
|
||||
public:
|
||||
SliderFloatPopupScreen(float *value, float minValue, float maxValue, const std::string &title, float step = 1.0f, const std::string &units = "", bool liveUpdate = false)
|
||||
: PopupScreen(title, "OK", "Cancel"), units_(units), value_(value), originalValue_(*value), minValue_(minValue), maxValue_(maxValue), step_(step), changing_(false), liveUpdate_(liveUpdate) {}
|
||||
: PopupScreen(title, "OK", "Cancel"), units_(units), value_(value), originalValue_(*value), minValue_(minValue), maxValue_(maxValue), step_(step), liveUpdate_(liveUpdate) {}
|
||||
void CreatePopupContents(UI::ViewGroup *parent) override;
|
||||
|
||||
const char *tag() const override { return "SliderFloatPopup"; }
|
||||
|
@ -114,14 +114,14 @@ private:
|
|||
void OnCompleted(DialogResult result) override;
|
||||
UI::SliderFloat *slider_ = nullptr;
|
||||
UI::TextEdit *edit_ = nullptr;
|
||||
std::string units_ = nullptr;
|
||||
float sliderValue_;
|
||||
float originalValue_;
|
||||
std::string units_;
|
||||
float sliderValue_ = 0.0f;
|
||||
float originalValue_ = 0.0f;
|
||||
float *value_;
|
||||
float minValue_;
|
||||
float maxValue_;
|
||||
float step_;
|
||||
bool changing_;
|
||||
bool changing_ = false;
|
||||
bool liveUpdate_;
|
||||
};
|
||||
|
||||
|
@ -361,7 +361,7 @@ private:
|
|||
std::string placeHolder_;
|
||||
std::string defaultText_;
|
||||
int maxLen_;
|
||||
bool restoreFocus_;
|
||||
bool restoreFocus_ = false;
|
||||
};
|
||||
|
||||
class ChoiceWithValueDisplay : public AbstractChoiceWithValueDisplay {
|
||||
|
|
|
@ -202,7 +202,9 @@ void ScreenManager::sendMessage(const char *msg, const char *value) {
|
|||
if (!strcmp(msg, "recreateviews"))
|
||||
RecreateAllViews();
|
||||
if (!strcmp(msg, "lost_focus")) {
|
||||
TouchInput input;
|
||||
TouchInput input{};
|
||||
input.x = -50000.0f;
|
||||
input.y = -50000.0f;
|
||||
input.flags = TOUCH_RELEASE_ALL;
|
||||
input.timestamp = time_now_d();
|
||||
input.id = 0;
|
||||
|
@ -238,7 +240,9 @@ void ScreenManager::push(Screen *screen, int layerFlags) {
|
|||
|
||||
// Release touches and unfocus.
|
||||
UI::SetFocusedView(nullptr);
|
||||
TouchInput input;
|
||||
TouchInput input{};
|
||||
input.x = -50000.0f;
|
||||
input.y = -50000.0f;
|
||||
input.flags = TOUCH_RELEASE_ALL;
|
||||
input.timestamp = time_now_d();
|
||||
input.id = 0;
|
||||
|
|
|
@ -217,14 +217,13 @@ UI::EventReturn UIScreen::OnCancel(UI::EventParams &e) {
|
|||
}
|
||||
|
||||
PopupScreen::PopupScreen(std::string title, std::string button1, std::string button2)
|
||||
: box_(0), defaultButton_(nullptr), title_(title) {
|
||||
: title_(title) {
|
||||
auto di = GetI18NCategory("Dialog");
|
||||
if (!button1.empty())
|
||||
button1_ = di->T(button1.c_str());
|
||||
if (!button2.empty())
|
||||
button2_ = di->T(button2.c_str());
|
||||
|
||||
alpha_ = 0.0f;
|
||||
alpha_ = 0.0f; // inherited
|
||||
}
|
||||
|
||||
void PopupScreen::touch(const TouchInput &touch) {
|
||||
|
|
|
@ -97,8 +97,8 @@ protected:
|
|||
void update() override;
|
||||
|
||||
private:
|
||||
UI::LinearLayout *box_;
|
||||
UI::Button *defaultButton_;
|
||||
UI::LinearLayout *box_ = nullptr;
|
||||
UI::Button *defaultButton_ = nullptr;
|
||||
std::string title_;
|
||||
std::string button1_;
|
||||
std::string button2_;
|
||||
|
@ -110,7 +110,7 @@ private:
|
|||
|
||||
int frames_ = 0;
|
||||
int finishFrame_ = -1;
|
||||
DialogResult finishResult_;
|
||||
DialogResult finishResult_ = DR_CANCEL;
|
||||
bool hasPopupOrigin_ = false;
|
||||
Point popupOrigin_;
|
||||
float offsetY_ = 0.0f;
|
||||
|
|
|
@ -998,7 +998,8 @@ void TextView::GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz
|
|||
bounds.w -= bulletOffset;
|
||||
}
|
||||
dc.MeasureTextRect(small_ ? dc.theme->uiFontSmall : dc.theme->uiFont, 1.0f, 1.0f, text_.c_str(), (int)text_.length(), bounds, &w, &h, textAlign_);
|
||||
|
||||
w += pad_ * 2.0f;
|
||||
h += pad_ * 2.0f;
|
||||
if (bullet_) {
|
||||
w += bulletOffset;
|
||||
}
|
||||
|
@ -1044,9 +1045,9 @@ void TextView::Draw(UIContext &dc) {
|
|||
|
||||
if (shadow_) {
|
||||
uint32_t shadowColor = 0x80000000;
|
||||
dc.DrawTextRect(text_.c_str(), textBounds.Offset(1.0f, 1.0f), shadowColor, textAlign_);
|
||||
dc.DrawTextRect(text_.c_str(), textBounds.Offset(1.0f + pad_, 1.0f + pad_), shadowColor, textAlign_);
|
||||
}
|
||||
dc.DrawTextRect(text_.c_str(), textBounds, textColor, textAlign_);
|
||||
dc.DrawTextRect(text_.c_str(), textBounds.Offset(pad_, pad_), textColor, textAlign_);
|
||||
if (small_) {
|
||||
// If we changed font style, reset it.
|
||||
dc.SetFontStyle(dc.theme->uiFont);
|
||||
|
|
|
@ -870,6 +870,8 @@ public:
|
|||
BitCheckBox(uint32_t *bitfield, uint32_t bit, const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = nullptr)
|
||||
: CheckBox(nullptr, text, smallText, layoutParams), bitfield_(bitfield), bit_(bit) {
|
||||
}
|
||||
|
||||
BitCheckBox(int *bitfield, int bit, const std::string &text, const std::string &smallText = "", LayoutParams *layoutParams = nullptr) : BitCheckBox((uint32_t *)bitfield, (uint32_t)bit, text, smallText, layoutParams) {}
|
||||
|
||||
void Toggle() override;
|
||||
bool Toggled() const override;
|
||||
|
@ -932,6 +934,7 @@ public:
|
|||
void SetFocusable(bool focusable) { focusable_ = focusable; }
|
||||
void SetClip(bool clip) { clip_ = clip; }
|
||||
void SetBullet(bool bullet) { bullet_ = bullet; }
|
||||
void SetPadding(float pad) { pad_ = pad; }
|
||||
|
||||
bool CanBeFocused() const override { return focusable_; }
|
||||
|
||||
|
@ -945,6 +948,7 @@ private:
|
|||
bool focusable_;
|
||||
bool clip_;
|
||||
bool bullet_ = false;
|
||||
float pad_ = 0.0f;
|
||||
};
|
||||
|
||||
class TextEdit : public View {
|
||||
|
|
|
@ -103,6 +103,10 @@ static std::vector<ButtonMapping> controllerMapping[2] = {
|
|||
rightControllerMapping
|
||||
};
|
||||
static bool controllerMotion[2][5] = {};
|
||||
static bool hmdMotion[4] = {};
|
||||
static float hmdMotionLast[2] = {};
|
||||
static float hmdMotionDiff[2] = {};
|
||||
static float hmdMotionDiffLast[2] = {};
|
||||
static int mouseController = 1;
|
||||
static bool mousePressed = false;
|
||||
|
||||
|
@ -309,6 +313,70 @@ void UpdateVRInput(bool haptics, float dp_xscale, float dp_yscale) {
|
|||
}
|
||||
}
|
||||
|
||||
// Head control
|
||||
if (g_Config.iHeadRotation) {
|
||||
float pitch = -VR_GetHMDAngles().x;
|
||||
float yaw = -VR_GetHMDAngles().y;
|
||||
bool disable = pspKeys[CTRL_SCREEN] || appMode == VR_MENU_MODE;
|
||||
bool isVR = !IsFlatVRScene();
|
||||
|
||||
// calculate delta angles of the rotation
|
||||
if (isVR) {
|
||||
float f = g_Config.bHeadRotationSmoothing ? 0.5f : 1.0f;
|
||||
float deltaPitch = pitch - hmdMotionLast[0];
|
||||
float deltaYaw = yaw - hmdMotionLast[1];
|
||||
while (deltaYaw >= 180) deltaYaw -= 360;
|
||||
while (deltaYaw < -180) deltaYaw += 360;
|
||||
hmdMotionLast[0] = pitch;
|
||||
hmdMotionLast[1] = yaw;
|
||||
hmdMotionDiffLast[0] = hmdMotionDiffLast[0] * (1-f) + hmdMotionDiff[0] * f;
|
||||
hmdMotionDiffLast[1] = hmdMotionDiffLast[1] * (1-f) + hmdMotionDiff[1] * f;
|
||||
hmdMotionDiff[0] += deltaPitch;
|
||||
hmdMotionDiff[1] += deltaYaw;
|
||||
pitch = hmdMotionDiff[0];
|
||||
yaw = hmdMotionDiff[1];
|
||||
}
|
||||
|
||||
bool activate;
|
||||
float limit = isVR ? g_Config.fHeadRotationScale : 20;
|
||||
keyInput.deviceId = DEVICE_ID_XR_HMD;
|
||||
|
||||
// vertical rotations
|
||||
if (g_Config.iHeadRotation == 2) {
|
||||
//up
|
||||
activate = !disable && pitch > limit;
|
||||
keyInput.flags = activate ? KEY_DOWN : KEY_UP;
|
||||
keyInput.keyCode = NKCODE_EXT_ROTATION_UP;
|
||||
if (hmdMotion[0] != activate) NativeKey(keyInput);
|
||||
if (isVR && activate) hmdMotionDiff[0] -= limit;
|
||||
hmdMotion[0] = activate;
|
||||
|
||||
//down
|
||||
activate = !disable && pitch < -limit;
|
||||
keyInput.flags = activate ? KEY_DOWN : KEY_UP;
|
||||
keyInput.keyCode = NKCODE_EXT_ROTATION_DOWN;
|
||||
if (hmdMotion[1] != activate) NativeKey(keyInput);
|
||||
if (isVR && activate) hmdMotionDiff[0] += limit;
|
||||
hmdMotion[1] = activate;
|
||||
}
|
||||
|
||||
//left
|
||||
activate = !disable && yaw < -limit;
|
||||
keyInput.flags = activate ? KEY_DOWN : KEY_UP;
|
||||
keyInput.keyCode = NKCODE_EXT_ROTATION_LEFT;
|
||||
if (hmdMotion[2] != activate) NativeKey(keyInput);
|
||||
if (isVR && activate) hmdMotionDiff[1] += limit;
|
||||
hmdMotion[2] = activate;
|
||||
|
||||
//right
|
||||
activate = !disable && yaw > limit;
|
||||
keyInput.flags = activate ? KEY_DOWN : KEY_UP;
|
||||
keyInput.keyCode = NKCODE_EXT_ROTATION_RIGHT;
|
||||
if (hmdMotion[3] != activate) NativeKey(keyInput);
|
||||
if (isVR && activate) hmdMotionDiff[1] -= limit;
|
||||
hmdMotion[3] = activate;
|
||||
}
|
||||
|
||||
// Camera adjust
|
||||
if (pspKeys[VIRTKEY_VR_CAMERA_ADJUST]) {
|
||||
for (auto& device : pspAxis) {
|
||||
|
@ -606,11 +674,20 @@ bool StartVRRender() {
|
|||
invView = XrPosef_Inverse(invView);
|
||||
}
|
||||
|
||||
// create updated quaternion
|
||||
// decompose rotation
|
||||
XrVector3f rotation = XrQuaternionf_ToEulerAngles(invView.orientation);
|
||||
XrQuaternionf pitch = XrQuaternionf_CreateFromVectorAngle({1, 0, 0}, mx * ToRadians(rotation.x));
|
||||
XrQuaternionf yaw = XrQuaternionf_CreateFromVectorAngle({0, 1, 0}, my * ToRadians(rotation.y));
|
||||
XrQuaternionf roll = XrQuaternionf_CreateFromVectorAngle({0, 0, 1}, mz * ToRadians(rotation.z));
|
||||
float mPitch = mx * ToRadians(rotation.x);
|
||||
float mYaw = my * ToRadians(rotation.y);
|
||||
float mRoll = mz * ToRadians(rotation.z);
|
||||
|
||||
// use in-game camera interpolated rotation
|
||||
if (g_Config.iHeadRotation >= 2) mPitch = -mx * ToRadians(hmdMotionDiffLast[0]); // vertical
|
||||
if (g_Config.iHeadRotation >= 1) mYaw = -my * ToRadians(hmdMotionDiffLast[1]); // horizontal
|
||||
|
||||
// create updated quaternion
|
||||
XrQuaternionf pitch = XrQuaternionf_CreateFromVectorAngle({1, 0, 0}, mPitch);
|
||||
XrQuaternionf yaw = XrQuaternionf_CreateFromVectorAngle({0, 1, 0}, mYaw);
|
||||
XrQuaternionf roll = XrQuaternionf_CreateFromVectorAngle({0, 0, 1}, mRoll);
|
||||
invView.orientation = XrQuaternionf_Multiply(roll, XrQuaternionf_Multiply(pitch, yaw));
|
||||
|
||||
float M[16];
|
||||
|
|
|
@ -465,3 +465,7 @@ void* VR_BindFramebuffer(engine_t *engine) {
|
|||
XrView VR_GetView(int eye) {
|
||||
return projections[eye];
|
||||
}
|
||||
|
||||
XrVector3f VR_GetHMDAngles() {
|
||||
return hmdorientation;
|
||||
}
|
||||
|
|
|
@ -48,3 +48,4 @@ void VR_SetConfigFloat( VRConfigFloat config, float value );
|
|||
|
||||
void* VR_BindFramebuffer(engine_t *engine);
|
||||
XrView VR_GetView(int eye);
|
||||
XrVector3f VR_GetHMDAngles();
|
||||
|
|
|
@ -842,7 +842,7 @@ static ConfigSetting graphicsSettings[] = {
|
|||
ConfigSetting("CardboardScreenSize", &g_Config.iCardboardScreenSize, 50, true, true),
|
||||
ConfigSetting("CardboardXShift", &g_Config.iCardboardXShift, 0, true, true),
|
||||
ConfigSetting("CardboardYShift", &g_Config.iCardboardYShift, 0, true, true),
|
||||
ConfigSetting("ShowFPSCounter", &g_Config.iShowFPSCounter, 0, true, true),
|
||||
ConfigSetting("iShowStatusFlags", &g_Config.iShowStatusFlags, 0, true, true),
|
||||
ReportedConfigSetting("GraphicsBackend", &g_Config.iGPUBackend, &DefaultGPUBackend, &GPUBackendTranslator::To, &GPUBackendTranslator::From, true, false),
|
||||
ConfigSetting("FailedGraphicsBackends", &g_Config.sFailedGPUBackends, ""),
|
||||
ConfigSetting("DisabledGraphicsBackends", &g_Config.sDisabledGPUBackends, ""),
|
||||
|
@ -1197,6 +1197,9 @@ static ConfigSetting vrSettings[] = {
|
|||
ConfigSetting("VRFieldOfView", &g_Config.fFieldOfViewPercentage, 100.0f),
|
||||
ConfigSetting("VRHeadUpDisplayScale", &g_Config.fHeadUpDisplayScale, 0.3f),
|
||||
ConfigSetting("VRMotionLength", &g_Config.fMotionLength, 0.5f),
|
||||
ConfigSetting("VRHeadRotationScale", &g_Config.fHeadRotationScale, 5.0f),
|
||||
ConfigSetting("VRHeadRotationSmoothing", &g_Config.bHeadRotationSmoothing, false),
|
||||
ConfigSetting("VRHeadRotation", &g_Config.iHeadRotation, 0),
|
||||
|
||||
ConfigSetting(false),
|
||||
};
|
||||
|
@ -1761,7 +1764,10 @@ void Config::CleanRecent() {
|
|||
}
|
||||
}
|
||||
|
||||
INFO_LOG(SYSTEM, "CleanRecent took %0.2f", time_now_d() - startTime);
|
||||
double recentTime = time_now_d() - startTime;
|
||||
if (recentTime > 0.1) {
|
||||
INFO_LOG(SYSTEM, "CleanRecent took %0.2f", recentTime);
|
||||
}
|
||||
recentIsos = cleanedRecent;
|
||||
});
|
||||
}
|
||||
|
@ -1809,17 +1815,31 @@ const Path Config::FindConfigFile(const std::string &baseFilename) {
|
|||
return filename;
|
||||
}
|
||||
|
||||
void Config::RestoreDefaults() {
|
||||
void Config::RestoreDefaults(RestoreSettingsBits whatToRestore) {
|
||||
if (bGameSpecific) {
|
||||
deleteGameConfig(gameId_);
|
||||
createGameConfig(gameId_);
|
||||
Load();
|
||||
} else {
|
||||
if (File::Exists(iniFilename_))
|
||||
File::Delete(iniFilename_);
|
||||
ClearRecentIsos();
|
||||
currentDirectory = defaultCurrentDirectory;
|
||||
if (whatToRestore & RestoreSettingsBits::SETTINGS) {
|
||||
if (File::Exists(iniFilename_))
|
||||
File::Delete(iniFilename_);
|
||||
}
|
||||
|
||||
if (whatToRestore & RestoreSettingsBits::CONTROLS) {
|
||||
if (File::Exists(controllerIniFilename_))
|
||||
File::Delete(controllerIniFilename_);
|
||||
}
|
||||
|
||||
if (whatToRestore & RestoreSettingsBits::RECENT) {
|
||||
ClearRecentIsos();
|
||||
currentDirectory = defaultCurrentDirectory;
|
||||
}
|
||||
|
||||
if (whatToRestore & (RestoreSettingsBits::SETTINGS | RestoreSettingsBits::CONTROLS)) {
|
||||
Load();
|
||||
}
|
||||
}
|
||||
Load();
|
||||
}
|
||||
|
||||
bool Config::hasGameConfig(const std::string &pGameId) {
|
||||
|
|
|
@ -270,7 +270,7 @@ public:
|
|||
|
||||
// UI
|
||||
bool bShowDebuggerOnLoad;
|
||||
int iShowFPSCounter;
|
||||
int iShowStatusFlags;
|
||||
bool bShowRegionOnGameIcon;
|
||||
bool bShowIDOnGameIcon;
|
||||
float fGameGridScale;
|
||||
|
@ -475,6 +475,9 @@ public:
|
|||
float fFieldOfViewPercentage;
|
||||
float fHeadUpDisplayScale;
|
||||
float fMotionLength;
|
||||
float fHeadRotationScale;
|
||||
bool bHeadRotationSmoothing;
|
||||
int iHeadRotation;
|
||||
|
||||
// Debugger
|
||||
int iDisasmWindowX;
|
||||
|
@ -523,7 +526,7 @@ public:
|
|||
void Load(const char *iniFileName = nullptr, const char *controllerIniFilename = nullptr);
|
||||
bool Save(const char *saveReason);
|
||||
void Reload();
|
||||
void RestoreDefaults();
|
||||
void RestoreDefaults(RestoreSettingsBits whatToRestore);
|
||||
|
||||
//per game config managment, should maybe be in it's own class
|
||||
void changeGameSpecific(const std::string &gameId = "", const std::string &title = "");
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#ifndef _MSC_VER
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#include "Common/Common.h"
|
||||
#include "Common/CommonFuncs.h"
|
||||
|
||||
const int PSP_MODEL_FAT = 0;
|
||||
|
@ -65,6 +66,13 @@ enum class GPUBackend {
|
|||
VULKAN = 3,
|
||||
};
|
||||
|
||||
enum class RestoreSettingsBits : int {
|
||||
SETTINGS = 1,
|
||||
CONTROLS = 2,
|
||||
RECENT = 4,
|
||||
};
|
||||
ENUM_CLASS_BITOPS(RestoreSettingsBits);
|
||||
|
||||
inline std::string GPUBackendToString(GPUBackend backend) {
|
||||
switch (backend) {
|
||||
case GPUBackend::OPENGL:
|
||||
|
@ -129,3 +137,10 @@ enum class AnalogFpsMode {
|
|||
MAPPED_DIRECTION = 1,
|
||||
MAPPED_DIR_TO_OPPOSITE_DIR = 2,
|
||||
};
|
||||
|
||||
// for Config.iShowStatusFlags
|
||||
enum class ShowStatusFlags {
|
||||
FPS_COUNTER = 1 << 1,
|
||||
SPEED_COUNTER = 1 << 2,
|
||||
BATTERY_PERCENT = 1 << 3,
|
||||
};
|
||||
|
|
|
@ -199,7 +199,6 @@ bool UpdateScreenScale(int width, int height) {
|
|||
dp_yres = new_dp_yres;
|
||||
pixel_xres = width;
|
||||
pixel_yres = height;
|
||||
INFO_LOG(G3D, "pixel_res: %dx%d. Calling NativeResized()", pixel_xres, pixel_yres);
|
||||
NativeResized();
|
||||
return true;
|
||||
}
|
||||
|
@ -328,14 +327,14 @@ void Core_ProcessStepping() {
|
|||
|
||||
// Many platforms, like Android, do not call this function but handle things on their own.
|
||||
// Instead they simply call NativeRender and NativeUpdate directly.
|
||||
void Core_Run(GraphicsContext *ctx) {
|
||||
bool Core_Run(GraphicsContext *ctx) {
|
||||
host->UpdateDisassembly();
|
||||
while (true) {
|
||||
if (GetUIState() != UISTATE_INGAME) {
|
||||
Core_StateProcessed();
|
||||
if (GetUIState() == UISTATE_EXIT) {
|
||||
UpdateRunLoop();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
Core_RunLoop(ctx);
|
||||
continue;
|
||||
|
@ -348,7 +347,7 @@ void Core_Run(GraphicsContext *ctx) {
|
|||
Core_RunLoop(ctx);
|
||||
if (coreState == CORE_POWERDOWN) {
|
||||
Core_StateProcessed();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -359,10 +358,10 @@ void Core_Run(GraphicsContext *ctx) {
|
|||
// Exit loop!!
|
||||
Core_StateProcessed();
|
||||
|
||||
return;
|
||||
return true;
|
||||
|
||||
case CORE_NEXTFRAME:
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,8 +27,10 @@ class GraphicsContext;
|
|||
// called from emu thread
|
||||
void UpdateRunLoop();
|
||||
|
||||
void Core_Run(GraphicsContext *ctx);
|
||||
// Returns false when an UI exit state is detected.
|
||||
bool Core_Run(GraphicsContext *ctx);
|
||||
void Core_Stop();
|
||||
|
||||
// For platforms that don't call Core_Run
|
||||
void Core_SetGraphicsContext(GraphicsContext *ctx);
|
||||
|
||||
|
|
|
@ -233,16 +233,14 @@ void Shutdown()
|
|||
ClearPendingEvents();
|
||||
UnregisterAllEvents();
|
||||
|
||||
while(eventPool)
|
||||
{
|
||||
while (eventPool) {
|
||||
Event *ev = eventPool;
|
||||
eventPool = ev->next;
|
||||
delete ev;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lk(externalEventLock);
|
||||
while(eventTsPool)
|
||||
{
|
||||
while (eventTsPool) {
|
||||
Event *ev = eventTsPool;
|
||||
eventTsPool = ev->next;
|
||||
delete ev;
|
||||
|
@ -251,7 +249,12 @@ void Shutdown()
|
|||
|
||||
u64 GetTicks()
|
||||
{
|
||||
return (u64)globalTimer + slicelength - currentMIPS->downcount;
|
||||
if (currentMIPS) {
|
||||
return (u64)globalTimer + slicelength - currentMIPS->downcount;
|
||||
} else {
|
||||
// Reporting can actually end up here during weird task switching sequences on Android
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
u64 GetIdleTicks()
|
||||
|
|
|
@ -1168,6 +1168,7 @@ static int sceFontFindOptimumFont(u32 libHandle, u32 fontStylePtr, u32 errorCode
|
|||
}
|
||||
|
||||
auto requestedStyle = PSPPointer<const PGFFontStyle>::Create(fontStylePtr);
|
||||
DEBUG_LOG(SCEFONT, "requestedStyle fontAttributes %i,fontCountry %i,fontExpire %i,fontFamily %i,fontFileName %s,fontH %f,fontHRes %f,fontLanguage %i,fontName %s,fontRegion %i,fontStyle %i,fontStyleSub %i,fontV %f,fontVRes %f,fontWeight %f", requestedStyle->fontAttributes, requestedStyle->fontCountry, requestedStyle->fontExpire, requestedStyle->fontFamily, requestedStyle->fontFileName, requestedStyle->fontH, requestedStyle->fontHRes, requestedStyle->fontLanguage, requestedStyle->fontName, requestedStyle->fontRegion, requestedStyle->fontStyle, requestedStyle->fontStyleSub, requestedStyle->fontV, requestedStyle->fontVRes, requestedStyle->fontWeight);
|
||||
|
||||
// Find the first nearest match for H/V, OR the last exact match for others.
|
||||
float hRes = requestedStyle->fontHRes > 0.0f ? (float)requestedStyle->fontHRes : fontLib->FontHRes();
|
||||
|
@ -1235,6 +1236,7 @@ static int sceFontFindFont(u32 libHandle, u32 fontStylePtr, u32 errorCodePtr) {
|
|||
DEBUG_LOG(SCEFONT, "sceFontFindFont(%x, %x, %x)", libHandle, fontStylePtr, errorCodePtr);
|
||||
|
||||
auto requestedStyle = PSPPointer<const PGFFontStyle>::Create(fontStylePtr);
|
||||
DEBUG_LOG(SCEFONT, "requestedStyle fontAttributes %i,fontCountry %i,fontExpire %i,fontFamily %i,fontFileName %s,fontH %f,fontHRes %f,fontLanguage %i,fontName %s,fontRegion %i,fontStyle %i,fontStyleSub %i,fontV %f,fontVRes %f,fontWeight %f", requestedStyle->fontAttributes, requestedStyle->fontCountry, requestedStyle->fontExpire, requestedStyle->fontFamily, requestedStyle->fontFileName, requestedStyle->fontH, requestedStyle->fontHRes, requestedStyle->fontLanguage, requestedStyle->fontName, requestedStyle->fontRegion, requestedStyle->fontStyle, requestedStyle->fontStyleSub, requestedStyle->fontV, requestedStyle->fontVRes, requestedStyle->fontWeight);
|
||||
|
||||
// Find the closest exact match for the fields specified.
|
||||
float hRes = requestedStyle->fontHRes > 0.0f ? (float)requestedStyle->fontHRes : fontLib->FontHRes();
|
||||
|
|
|
@ -310,6 +310,10 @@ static const KeyMap_IntStrPair key_names[] = {
|
|||
{NKCODE_EXT_MOTION_LEFT, "MotionLeft"},
|
||||
{NKCODE_EXT_MOTION_RIGHT, "MotionRight"},
|
||||
{NKCODE_EXT_MOTION_FORWARD, "MotionFwd"},
|
||||
{NKCODE_EXT_ROTATION_UP, "RotationUp"},
|
||||
{NKCODE_EXT_ROTATION_DOWN, "RotationDown"},
|
||||
{NKCODE_EXT_ROTATION_LEFT, "RotationLeft"},
|
||||
{NKCODE_EXT_ROTATION_RIGHT, "RotationRight"},
|
||||
|
||||
{NKCODE_START_QUESTION, "¿"},
|
||||
{NKCODE_LEFTBRACE, "{"},
|
||||
|
|
|
@ -2446,7 +2446,7 @@ void FramebufferManagerCommon::NotifyRenderResized(int msaaLevel) {
|
|||
|
||||
#ifdef _WIN32
|
||||
// Seems related - if you're ok with numbers all the time, show some more :)
|
||||
if (g_Config.iShowFPSCounter != 0) {
|
||||
if (g_Config.iShowStatusFlags != 0) {
|
||||
ShowScreenResolution();
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -521,7 +521,7 @@ float ToScaledDepthFromIntegerScale(float z) {
|
|||
const float depthSliceFactor = DepthSliceFactor();
|
||||
if (gstate_c.Use(GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT)) {
|
||||
const double doffset = 0.5 * (depthSliceFactor - 1.0) * (1.0 / depthSliceFactor);
|
||||
// Use one bit for each value, rather than 1.0 / (25535.0 * 256.0).
|
||||
// Use one bit for each value, rather than 1.0 / (65535.0 * 256.0).
|
||||
return (float)((double)z * (1.0 / 16777215.0) + doffset);
|
||||
} else {
|
||||
const float offset = 0.5f * (depthSliceFactor - 1.0f) * (1.0f / depthSliceFactor);
|
||||
|
@ -730,6 +730,12 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
|
|||
if (maxz == 65535) {
|
||||
maxz += fullDepthRange;
|
||||
}
|
||||
} else if (maxz == 65535) {
|
||||
// This means clamp isn't enabled, but we still want to allow values up to 65535.99.
|
||||
// If DepthSliceFactor() is 1.0, though, this would make out.depthRangeMax exceed 1.
|
||||
// Since that would clamp, it would make Z=1234 not match between draws when maxz changes.
|
||||
if (DepthSliceFactor() > 1.0f)
|
||||
maxz = 65535.99f;
|
||||
}
|
||||
// Okay. So, in our shader, -1 will map to minz, and +1 will map to maxz.
|
||||
float halfActualZRange = (maxz - minz) * (1.0f / 2.0f);
|
||||
|
@ -748,6 +754,7 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
|
|||
}
|
||||
|
||||
// OpenGL will clamp these for us anyway, and Direct3D will error if not clamped.
|
||||
// Of course, if this happens we've skewed out.depthScale/out.zOffset and may get z-fighting.
|
||||
out.depthRangeMin = std::max(out.depthRangeMin, 0.0f);
|
||||
out.depthRangeMax = std::min(out.depthRangeMax, 1.0f);
|
||||
}
|
||||
|
|
|
@ -128,11 +128,6 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
|
|||
}
|
||||
|
||||
GPU_GLES::~GPU_GLES() {
|
||||
if (draw_) {
|
||||
GLRenderManager *render = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||
render->Wipe();
|
||||
}
|
||||
|
||||
// If we're here during app shutdown (exiting the Windows app in-game, for example)
|
||||
// everything should already be cleared since DeviceLost has been run.
|
||||
|
||||
|
|
|
@ -98,12 +98,17 @@ static Promise<VkShaderModule> *CompileShaderModuleAsync(VulkanContext *vulkan,
|
|||
|
||||
#if defined(_DEBUG)
|
||||
// Don't parallelize in debug mode, pathological behavior due to mutex locks in allocator which is HEAVILY used by glslang.
|
||||
return Promise<VkShaderModule>::AlreadyDone(compile());
|
||||
bool singleThreaded = true;
|
||||
#else
|
||||
return Promise<VkShaderModule>::Spawn(&g_threadManager, compile, TaskType::CPU_COMPUTE);
|
||||
bool singleThreaded = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (singleThreaded) {
|
||||
return Promise<VkShaderModule>::AlreadyDone(compile());
|
||||
} else {
|
||||
return Promise<VkShaderModule>::Spawn(&g_threadManager, compile, TaskType::CPU_COMPUTE);
|
||||
}
|
||||
}
|
||||
|
||||
VulkanFragmentShader::VulkanFragmentShader(VulkanContext *vulkan, FShaderID id, FragmentShaderFlags flags, const char *code)
|
||||
: vulkan_(vulkan), id_(id), flags_(flags) {
|
||||
|
|
|
@ -90,7 +90,6 @@ public:
|
|||
}
|
||||
|
||||
void StopThread() override {
|
||||
renderManager_->WaitUntilQueueIdle();
|
||||
renderManager_->StopThread();
|
||||
}
|
||||
|
||||
|
|
|
@ -423,7 +423,7 @@ void MainWindow::forumAct()
|
|||
|
||||
void MainWindow::goldAct()
|
||||
{
|
||||
QDesktopServices::openUrl(QUrl("https://central.ppsspp.org/buygold"));
|
||||
QDesktopServices::openUrl(QUrl("https://www.ppsspp.org/buygold"));
|
||||
}
|
||||
|
||||
void MainWindow::gitAct()
|
||||
|
@ -655,8 +655,6 @@ void MainWindow::createMenus()
|
|||
->addEventChecked(&g_Config.bHardwareTransform);
|
||||
gameSettingsMenu->add(new MenuAction(this, SLOT(vertexCacheAct()), QT_TR_NOOP("&Vertex cache")))
|
||||
->addEventChecked(&g_Config.bVertexCache);
|
||||
gameSettingsMenu->add(new MenuAction(this, SLOT(showFPSAct()), QT_TR_NOOP("&Show FPS counter")))
|
||||
->addEventChecked(&g_Config.iShowFPSCounter);
|
||||
gameSettingsMenu->addSeparator();
|
||||
gameSettingsMenu->add(new MenuAction(this, SLOT(audioAct()), QT_TR_NOOP("Enable s&ound")))
|
||||
->addEventChecked(&g_Config.bEnableSound);
|
||||
|
|
|
@ -184,7 +184,6 @@ private slots:
|
|||
g_Config.bShowDebugStats = !g_Config.bShowDebugStats;
|
||||
NativeMessageReceived("clear jit", "");
|
||||
}
|
||||
void showFPSAct() { g_Config.iShowFPSCounter = g_Config.iShowFPSCounter ? 0 : 3; } // 3 = both speed and FPS
|
||||
|
||||
// Help
|
||||
void websiteAct();
|
||||
|
|
|
@ -429,7 +429,7 @@ int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std:
|
|||
#else
|
||||
SDL_GL_SwapWindow(window_);
|
||||
#endif
|
||||
});
|
||||
}, false);
|
||||
|
||||
renderManager_->SetSwapIntervalFunction([&](int interval) {
|
||||
INFO_LOG(G3D, "SDL SwapInterval: %d", interval);
|
||||
|
|
|
@ -42,7 +42,6 @@ public:
|
|||
}
|
||||
|
||||
void StopThread() override {
|
||||
renderManager_->WaitUntilQueueIdle();
|
||||
renderManager_->StopThread();
|
||||
}
|
||||
|
||||
|
|
|
@ -1011,7 +1011,7 @@ int main(int argc, char *argv[]) {
|
|||
case SDL_BUTTON_LEFT:
|
||||
{
|
||||
mouseDown = true;
|
||||
TouchInput input;
|
||||
TouchInput input{};
|
||||
input.x = mx;
|
||||
input.y = my;
|
||||
input.flags = TOUCH_DOWN | TOUCH_MOUSE;
|
||||
|
@ -1065,7 +1065,7 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
case SDL_MOUSEMOTION:
|
||||
if (mouseDown) {
|
||||
TouchInput input;
|
||||
TouchInput input{};
|
||||
input.x = mx;
|
||||
input.y = my;
|
||||
input.flags = TOUCH_MOVE | TOUCH_MOUSE;
|
||||
|
@ -1080,7 +1080,7 @@ int main(int argc, char *argv[]) {
|
|||
case SDL_BUTTON_LEFT:
|
||||
{
|
||||
mouseDown = false;
|
||||
TouchInput input;
|
||||
TouchInput input{};
|
||||
input.x = mx;
|
||||
input.y = my;
|
||||
input.flags = TOUCH_UP | TOUCH_MOUSE;
|
||||
|
|
|
@ -970,6 +970,12 @@ public:
|
|||
if (img_.isValid()) {
|
||||
scales[0] *= scaleX_;
|
||||
scales[1] *= scaleY_;
|
||||
if (timeLastPressed_ >= 0.0) {
|
||||
double sincePress = time_now_d() - timeLastPressed_;
|
||||
if (sincePress < 1.0) {
|
||||
c = colorBlend(c, dc.theme->itemDownStyle.background.color, (float)sincePress);
|
||||
}
|
||||
}
|
||||
dc.Draw()->DrawImageRotatedStretch(img_, bounds_.Offset(offsetX_, offsetY_), scales, angle_, c);
|
||||
}
|
||||
}
|
||||
|
@ -1010,6 +1016,10 @@ public:
|
|||
return button_;
|
||||
}
|
||||
|
||||
void NotifyPressed() {
|
||||
timeLastPressed_ = time_now_d();
|
||||
}
|
||||
|
||||
private:
|
||||
int button_;
|
||||
ImageID img_;
|
||||
|
@ -1021,6 +1031,7 @@ private:
|
|||
float offsetY_ = 0.0f;
|
||||
bool flipHBG_ = false;
|
||||
int *selectedButton_ = nullptr;
|
||||
double timeLastPressed_ = -1.0;
|
||||
};
|
||||
|
||||
class MockPSP : public UI::AnchorLayout {
|
||||
|
@ -1030,8 +1041,11 @@ public:
|
|||
MockPSP(UI::LayoutParams *layoutParams = nullptr);
|
||||
void SelectButton(int btn);
|
||||
void FocusButton(int btn);
|
||||
void NotifyPressed(int btn);
|
||||
float GetPopupOffset();
|
||||
|
||||
bool SubviewFocused(View *view) override;
|
||||
|
||||
UI::Event ButtonClick;
|
||||
|
||||
private:
|
||||
|
@ -1042,6 +1056,7 @@ private:
|
|||
UI::EventReturn OnSelectButton(UI::EventParams &e);
|
||||
|
||||
std::unordered_map<int, MockButton *> buttons_;
|
||||
UI::TextView *labelView_ = nullptr;
|
||||
int selectedButton_ = 0;
|
||||
};
|
||||
|
||||
|
@ -1070,6 +1085,10 @@ MockPSP::MockPSP(UI::LayoutParams *layoutParams) : AnchorLayout(layoutParams) {
|
|||
AddButton(CTRL_CIRCLE, ImageID("I_CIRCLE"), ImageID("I_ROUND_LINE"), 0.0f, LayoutSize(23.0f, 23.0f, 446.0f, 74.0f))->SetScale(0.7f);
|
||||
AddButton(CTRL_CROSS, ImageID("I_CROSS"), ImageID("I_ROUND_LINE"), 0.0f, LayoutSize(23.0f, 23.0f, 419.0f, 102.0f))->SetScale(0.7f);
|
||||
AddButton(CTRL_SQUARE, ImageID("I_SQUARE"), ImageID("I_ROUND_LINE"), 0.0f, LayoutSize(23.0f, 23.0f, 392.0f, 74.0f))->SetScale(0.7f);
|
||||
|
||||
labelView_ = Add(new UI::TextView(""));
|
||||
labelView_->SetShadow(true);
|
||||
labelView_->SetVisibility(UI::V_GONE);
|
||||
}
|
||||
|
||||
void MockPSP::SelectButton(int btn) {
|
||||
|
@ -1077,9 +1096,31 @@ void MockPSP::SelectButton(int btn) {
|
|||
}
|
||||
|
||||
void MockPSP::FocusButton(int btn) {
|
||||
MockButton *view = buttons_[selectedButton_];
|
||||
if (view)
|
||||
MockButton *view = buttons_[btn];
|
||||
if (view) {
|
||||
view->SetFocus();
|
||||
} else {
|
||||
labelView_->SetVisibility(UI::V_GONE);
|
||||
}
|
||||
}
|
||||
|
||||
void MockPSP::NotifyPressed(int btn) {
|
||||
MockButton *view = buttons_[btn];
|
||||
if (view)
|
||||
view->NotifyPressed();
|
||||
}
|
||||
|
||||
bool MockPSP::SubviewFocused(View *view) {
|
||||
for (auto it : buttons_) {
|
||||
if (view == it.second) {
|
||||
labelView_->SetVisibility(UI::V_VISIBLE);
|
||||
labelView_->SetText(KeyMap::GetPspButtonName(it.first));
|
||||
|
||||
const Bounds &pos = view->GetBounds().Offset(-GetBounds().x, -GetBounds().y);
|
||||
labelView_->ReplaceLayoutParams(new UI::AnchorLayoutParams(pos.centerX(), pos.y2() + 5, UI::NONE, UI::NONE));
|
||||
}
|
||||
}
|
||||
return AnchorLayout::SubviewFocused(view);
|
||||
}
|
||||
|
||||
float MockPSP::GetPopupOffset() {
|
||||
|
@ -1162,6 +1203,50 @@ void VisualMappingScreen::CreateViews() {
|
|||
root_->Add(rightColumn);
|
||||
}
|
||||
|
||||
bool VisualMappingScreen::key(const KeyInput &key) {
|
||||
if (key.flags & KEY_DOWN) {
|
||||
std::vector<int> pspKeys;
|
||||
KeyMap::KeyToPspButton(key.deviceId, key.keyCode, &pspKeys);
|
||||
for (int pspKey : pspKeys) {
|
||||
switch (pspKey) {
|
||||
case VIRTKEY_AXIS_X_MIN:
|
||||
case VIRTKEY_AXIS_Y_MIN:
|
||||
case VIRTKEY_AXIS_X_MAX:
|
||||
case VIRTKEY_AXIS_Y_MAX:
|
||||
psp_->NotifyPressed(VIRTKEY_AXIS_Y_MAX);
|
||||
break;
|
||||
default:
|
||||
psp_->NotifyPressed(pspKey);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return UIDialogScreenWithGameBackground::key(key);
|
||||
}
|
||||
|
||||
void VisualMappingScreen::axis(const AxisInput &axis) {
|
||||
std::vector<int> results;
|
||||
if (axis.value >= g_Config.fAnalogDeadzone * 0.7f)
|
||||
KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, 1, &results);
|
||||
if (axis.value <= g_Config.fAnalogDeadzone * -0.7f)
|
||||
KeyMap::AxisToPspButton(axis.deviceId, axis.axisId, -1, &results);
|
||||
|
||||
for (int result : results) {
|
||||
switch (result) {
|
||||
case VIRTKEY_AXIS_X_MIN:
|
||||
case VIRTKEY_AXIS_Y_MIN:
|
||||
case VIRTKEY_AXIS_X_MAX:
|
||||
case VIRTKEY_AXIS_Y_MAX:
|
||||
psp_->NotifyPressed(VIRTKEY_AXIS_Y_MAX);
|
||||
break;
|
||||
default:
|
||||
psp_->NotifyPressed(result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
UIDialogScreenWithGameBackground::axis(axis);
|
||||
}
|
||||
|
||||
void VisualMappingScreen::resized() {
|
||||
UIDialogScreenWithGameBackground::resized();
|
||||
RecreateViews();
|
||||
|
|
|
@ -177,6 +177,9 @@ public:
|
|||
|
||||
const char *tag() const override { return "VisualMapping"; }
|
||||
|
||||
bool key(const KeyInput &key) override;
|
||||
void axis(const AxisInput &axis) override;
|
||||
|
||||
protected:
|
||||
void CreateViews() override;
|
||||
|
||||
|
|
|
@ -704,10 +704,9 @@ void SystemInfoScreen::CreateViews() {
|
|||
tabHolder->AddTab(si->T("CPU Extensions"), cpuExtensionsScroll);
|
||||
|
||||
cpuExtensions->Add(new ItemHeader(si->T("CPU Extensions")));
|
||||
std::vector<std::string> exts;
|
||||
SplitString(cpu_info.Summarize(), ',', exts);
|
||||
for (size_t i = 2; i < exts.size(); i++) {
|
||||
cpuExtensions->Add(new TextView(exts[i], new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
std::vector<std::string> exts = cpu_info.Features();
|
||||
for (std::string &ext : exts) {
|
||||
cpuExtensions->Add(new TextView(ext, new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
|
||||
ViewGroup *driverBugsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
|
||||
|
|
|
@ -25,6 +25,7 @@ using namespace std::placeholders;
|
|||
#include "Common/Render/TextureAtlas.h"
|
||||
#include "Common/GPU/OpenGL/GLFeatures.h"
|
||||
#include "Common/Render/Text/draw_text.h"
|
||||
#include "Common/Battery/Battery.h"
|
||||
|
||||
#include "Common/UI/Root.h"
|
||||
#include "Common/UI/UI.h"
|
||||
|
@ -1308,23 +1309,30 @@ static void DrawFPS(UIContext *ctx, const Bounds &bounds) {
|
|||
FontID ubuntu24("UBUNTU24");
|
||||
float vps, fps, actual_fps;
|
||||
__DisplayGetFPS(&vps, &fps, &actual_fps);
|
||||
char fpsbuf[256];
|
||||
switch (g_Config.iShowFPSCounter) {
|
||||
case 1:
|
||||
snprintf(fpsbuf, sizeof(fpsbuf), "Speed: %0.1f%%", vps / (59.94f / 100.0f)); break;
|
||||
case 2:
|
||||
snprintf(fpsbuf, sizeof(fpsbuf), "FPS: %0.1f", actual_fps); break;
|
||||
case 3:
|
||||
snprintf(fpsbuf, sizeof(fpsbuf), "%0.0f/%0.0f (%0.1f%%)", actual_fps, fps, vps / (59.94f / 100.0f)); break;
|
||||
default:
|
||||
return;
|
||||
|
||||
char fpsbuf[256]{};
|
||||
if (g_Config.iShowStatusFlags == ((int)ShowStatusFlags::FPS_COUNTER | (int)ShowStatusFlags::SPEED_COUNTER)) {
|
||||
snprintf(fpsbuf, sizeof(fpsbuf), "%0.0f/%0.0f (%0.1f%%)", actual_fps, fps, vps / (59.94f / 100.0f));
|
||||
} else {
|
||||
if (g_Config.iShowStatusFlags & (int)ShowStatusFlags::FPS_COUNTER) {
|
||||
snprintf(fpsbuf, sizeof(fpsbuf), "FPS: %0.1f", actual_fps);
|
||||
}
|
||||
if (g_Config.iShowStatusFlags & (int)ShowStatusFlags::SPEED_COUNTER) {
|
||||
snprintf(fpsbuf, sizeof(fpsbuf), "%s Speed: %0.1f%%", fpsbuf, vps / (59.94f / 100.0f));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CAN_DISPLAY_CURRENT_BATTERY_CAPACITY
|
||||
if (g_Config.iShowStatusFlags & (int)ShowStatusFlags::BATTERY_PERCENT) {
|
||||
snprintf(fpsbuf, sizeof(fpsbuf), "%s Battery: %d%%", fpsbuf, getCurrentBatteryCapacity());
|
||||
}
|
||||
#endif
|
||||
|
||||
ctx->Flush();
|
||||
ctx->BindFontTexture();
|
||||
ctx->Draw()->SetFontScale(0.7f, 0.7f);
|
||||
ctx->Draw()->DrawText(ubuntu24, fpsbuf, bounds.x2() - 8, 12, 0xc0000000, ALIGN_TOPRIGHT | FLAG_DYNAMIC_ASCII);
|
||||
ctx->Draw()->DrawText(ubuntu24, fpsbuf, bounds.x2() - 10, 10, 0xFF3fFF3f, ALIGN_TOPRIGHT | FLAG_DYNAMIC_ASCII);
|
||||
ctx->Draw()->DrawText(ubuntu24, fpsbuf, bounds.x2() - 8, 20, 0xc0000000, ALIGN_TOPRIGHT | FLAG_DYNAMIC_ASCII);
|
||||
ctx->Draw()->DrawText(ubuntu24, fpsbuf, bounds.x2() - 10, 19, 0xFF3fFF3f, ALIGN_TOPRIGHT | FLAG_DYNAMIC_ASCII);
|
||||
ctx->Draw()->SetFontScale(1.0f, 1.0f);
|
||||
ctx->Flush();
|
||||
ctx->RebindTexture();
|
||||
|
@ -1504,7 +1512,7 @@ bool EmuScreen::hasVisibleUI() {
|
|||
// Regular but uncommon UI.
|
||||
if (saveStatePreview_->GetVisibility() != UI::V_GONE || loadingSpinner_->GetVisibility() == UI::V_VISIBLE)
|
||||
return true;
|
||||
if (!osm.IsEmpty() || g_Config.bShowTouchControls || g_Config.iShowFPSCounter != 0)
|
||||
if (!osm.IsEmpty() || g_Config.bShowTouchControls || g_Config.iShowStatusFlags != 0)
|
||||
return true;
|
||||
if (g_Config.bEnableCardboardVR || g_Config.bEnableNetworkChat)
|
||||
return true;
|
||||
|
@ -1551,7 +1559,7 @@ void EmuScreen::renderUI() {
|
|||
DrawAudioDebugStats(ctx, ctx->GetLayoutBounds());
|
||||
}
|
||||
|
||||
if (g_Config.iShowFPSCounter && !invalid_) {
|
||||
if (g_Config.iShowStatusFlags && !invalid_) {
|
||||
DrawFPS(ctx, ctx->GetLayoutBounds());
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
#include "Common/System/Display.h" // Only to check screen aspect ratio with pixel_yres/pixel_xres
|
||||
#include "Common/System/System.h"
|
||||
#include "Common/Battery/Battery.h"
|
||||
#include "Common/System/NativeApp.h"
|
||||
#include "Common/Data/Color/RGBAUtil.h"
|
||||
#include "Common/Math/curves.h"
|
||||
|
@ -211,22 +212,8 @@ void GameSettingsScreen::CreateViews() {
|
|||
// Scrolling action menu to the right.
|
||||
using namespace UI;
|
||||
|
||||
auto di = GetI18NCategory("Dialog");
|
||||
auto gr = GetI18NCategory("Graphics");
|
||||
auto co = GetI18NCategory("Controls");
|
||||
auto a = GetI18NCategory("Audio");
|
||||
auto sa = GetI18NCategory("Savedata");
|
||||
auto se = GetI18NCategory("Search");
|
||||
auto sy = GetI18NCategory("System");
|
||||
auto n = GetI18NCategory("Networking");
|
||||
auto ms = GetI18NCategory("MainSettings");
|
||||
auto dev = GetI18NCategory("Developer");
|
||||
auto ri = GetI18NCategory("RemoteISO");
|
||||
auto ps = GetI18NCategory("PostShaders");
|
||||
auto th = GetI18NCategory("Themes");
|
||||
auto vr = GetI18NCategory("VR");
|
||||
|
||||
int deviceType = System_GetPropertyInt(SYSPROP_DEVICE_TYPE);
|
||||
auto di = GetI18NCategory("Dialog");
|
||||
|
||||
root_ = new AnchorLayout(new LayoutParams(FILL_PARENT, FILL_PARENT));
|
||||
|
||||
|
@ -259,10 +246,59 @@ void GameSettingsScreen::CreateViews() {
|
|||
settingInfo_->Show(oldSettingInfo_, nullptr);
|
||||
}
|
||||
|
||||
// TODO: These currently point to global settings, not game specific ones.
|
||||
|
||||
// Graphics
|
||||
LinearLayout *graphicsSettings = AddTab("GameSettingsGraphics", ms->T("Graphics"));
|
||||
CreateGraphicsSettings(graphicsSettings);
|
||||
|
||||
LinearLayout *controlsSettings = AddTab("GameSettingsControls", ms->T("Controls"));
|
||||
CreateControlsSettings(controlsSettings);
|
||||
|
||||
LinearLayout *audioSettings = AddTab("GameSettingsAudio", ms->T("Audio"));
|
||||
CreateAudioSettings(audioSettings);
|
||||
|
||||
LinearLayout *networkingSettings = AddTab("GameSettingsNetworking", ms->T("Networking"));
|
||||
CreateNetworkingSettings(networkingSettings);
|
||||
|
||||
LinearLayout *tools = AddTab("GameSettingsTools", ms->T("Tools"));
|
||||
CreateToolsSettings(tools);
|
||||
|
||||
LinearLayout *systemSettings = AddTab("GameSettingsSystem", ms->T("System"));
|
||||
systemSettings->SetSpacing(0);
|
||||
CreateSystemSettings(systemSettings);
|
||||
|
||||
int deviceType = System_GetPropertyInt(SYSPROP_DEVICE_TYPE);
|
||||
if (deviceType == DEVICE_TYPE_VR) {
|
||||
LinearLayout *vrSettings = AddTab("GameSettingsVR", ms->T("VR"));
|
||||
CreateVRSettings(vrSettings);
|
||||
}
|
||||
|
||||
#if !defined(MOBILE_DEVICE) || PPSSPP_PLATFORM(ANDROID)
|
||||
// Hide search if screen is too small.
|
||||
if (dp_xres < dp_yres || dp_yres >= 500) {
|
||||
auto se = GetI18NCategory("Search");
|
||||
// Search
|
||||
LinearLayout *searchSettings = AddTab("GameSettingsSearch", ms->T("Search"), true);
|
||||
|
||||
searchSettings->Add(new ItemHeader(se->T("Find settings")));
|
||||
if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD)) {
|
||||
searchSettings->Add(new ChoiceWithValueDisplay(&searchFilter_, se->T("Filter"), (const char *)nullptr))->OnClick.Handle(this, &GameSettingsScreen::OnChangeSearchFilter);
|
||||
} else {
|
||||
searchSettings->Add(new PopupTextInputChoice(&searchFilter_, se->T("Filter"), "", 64, screenManager()))->OnChange.Handle(this, &GameSettingsScreen::OnChangeSearchFilter);
|
||||
}
|
||||
clearSearchChoice_ = searchSettings->Add(new Choice(se->T("Clear filter")));
|
||||
clearSearchChoice_->OnClick.Handle(this, &GameSettingsScreen::OnClearSearchFilter);
|
||||
noSearchResults_ = searchSettings->Add(new TextView(se->T("No settings matched '%1'"), new LinearLayoutParams(Margins(20, 5))));
|
||||
|
||||
ApplySearchFilter();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Graphics
|
||||
void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) {
|
||||
auto gr = GetI18NCategory("Graphics");
|
||||
auto vr = GetI18NCategory("VR");
|
||||
|
||||
using namespace UI;
|
||||
|
||||
graphicsSettings->Add(new ItemHeader(gr->T("Rendering Mode")));
|
||||
|
||||
|
@ -307,6 +343,8 @@ void GameSettingsScreen::CreateViews() {
|
|||
return !g_Config.bSoftwareRendering && !g_Config.bSkipBufferEffects;
|
||||
});
|
||||
|
||||
int deviceType = System_GetPropertyInt(SYSPROP_DEVICE_TYPE);
|
||||
|
||||
if (deviceType != DEVICE_TYPE_VR) {
|
||||
CheckBox *softwareGPU = graphicsSettings->Add(new CheckBox(&g_Config.bSoftwareRendering, gr->T("Software Rendering", "Software Rendering (slow)")));
|
||||
softwareGPU->SetEnabled(!PSP_IsInited());
|
||||
|
@ -563,12 +601,20 @@ void GameSettingsScreen::CreateViews() {
|
|||
});
|
||||
|
||||
graphicsSettings->Add(new ItemHeader(gr->T("Overlay Information")));
|
||||
static const char *fpsChoices[] = { "None", "Speed", "FPS", "Both" };
|
||||
graphicsSettings->Add(new PopupMultiChoice(&g_Config.iShowFPSCounter, gr->T("Show FPS Counter"), fpsChoices, 0, ARRAY_SIZE(fpsChoices), gr->GetName(), screenManager()));
|
||||
graphicsSettings->Add(new CheckBox(&g_Config.bShowDebugStats, gr->T("Show Debug Statistics")))->OnClick.Handle(this, &GameSettingsScreen::OnJitAffectingSetting);
|
||||
graphicsSettings->Add(new BitCheckBox(&g_Config.iShowStatusFlags, (int)ShowStatusFlags::FPS_COUNTER, gr->T("Show FPS Counter")));
|
||||
graphicsSettings->Add(new BitCheckBox(&g_Config.iShowStatusFlags, (int)ShowStatusFlags::SPEED_COUNTER, gr->T("Show Speed")));
|
||||
#ifdef CAN_DISPLAY_CURRENT_BATTERY_CAPACITY
|
||||
graphicsSettings->Add(new BitCheckBox(&g_Config.iShowStatusFlags, (int)ShowStatusFlags::BATTERY_PERCENT, gr->T("Show Battery %")));
|
||||
#endif
|
||||
|
||||
// Audio
|
||||
LinearLayout *audioSettings = AddTab("GameSettingsAudio", ms->T("Audio"));
|
||||
graphicsSettings->Add(new CheckBox(&g_Config.bShowDebugStats, gr->T("Show Debug Statistics")))->OnClick.Handle(this, &GameSettingsScreen::OnJitAffectingSetting);
|
||||
}
|
||||
|
||||
void GameSettingsScreen::CreateAudioSettings(UI::ViewGroup *audioSettings) {
|
||||
using namespace UI;
|
||||
|
||||
auto a = GetI18NCategory("Audio");
|
||||
auto ms = GetI18NCategory("MainSettings");
|
||||
|
||||
audioSettings->Add(new ItemHeader(ms->T("Audio")));
|
||||
audioSettings->Add(new CheckBox(&g_Config.bEnableSound, a->T("Enable Sound")));
|
||||
|
@ -626,9 +672,15 @@ void GameSettingsScreen::CreateViews() {
|
|||
PopupMultiChoiceDynamic *MicChoice = audioSettings->Add(new PopupMultiChoiceDynamic(&g_Config.sMicDevice, a->T("Microphone Device"), micList, nullptr, screenManager()));
|
||||
MicChoice->OnChoice.Handle(this, &GameSettingsScreen::OnMicDeviceChange);
|
||||
}
|
||||
}
|
||||
|
||||
// Control
|
||||
LinearLayout *controlsSettings = AddTab("GameSettingsControls", ms->T("Controls"));
|
||||
void GameSettingsScreen::CreateControlsSettings(UI::ViewGroup *controlsSettings) {
|
||||
using namespace UI;
|
||||
|
||||
auto co = GetI18NCategory("Controls");
|
||||
auto ms = GetI18NCategory("MainSettings");
|
||||
|
||||
int deviceType = System_GetPropertyInt(SYSPROP_DEVICE_TYPE);
|
||||
|
||||
controlsSettings->Add(new ItemHeader(ms->T("Controls")));
|
||||
controlsSettings->Add(new Choice(co->T("Control Mapping")))->OnClick.Handle(this, &GameSettingsScreen::OnControlMapping);
|
||||
|
@ -718,7 +770,7 @@ void GameSettingsScreen::CreateViews() {
|
|||
controlsSettings->Add(new ItemHeader(co->T("Mouse", "Mouse settings")));
|
||||
CheckBox *mouseControl = controlsSettings->Add(new CheckBox(&g_Config.bMouseControl, co->T("Use Mouse Control")));
|
||||
mouseControl->OnClick.Add([=](EventParams &e) {
|
||||
if(g_Config.bMouseControl)
|
||||
if (g_Config.bMouseControl)
|
||||
settingInfo_->Show(co->T("MouseControl Tip", "You can now map mouse in control mapping screen by pressing the 'M' icon."), e.v);
|
||||
return UI::EVENT_CONTINUE;
|
||||
});
|
||||
|
@ -727,8 +779,13 @@ void GameSettingsScreen::CreateViews() {
|
|||
controlsSettings->Add(new PopupSliderChoiceFloat(&g_Config.fMouseSmoothing, 0.0f, 0.95f, co->T("Mouse smoothing"), 0.05f, screenManager(), "x"))->SetEnabledPtr(&g_Config.bMouseControl);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
LinearLayout *networkingSettings = AddTab("GameSettingsNetworking", ms->T("Networking"));
|
||||
void GameSettingsScreen::CreateNetworkingSettings(UI::ViewGroup *networkingSettings) {
|
||||
using namespace UI;
|
||||
|
||||
auto n = GetI18NCategory("Networking");
|
||||
auto ms = GetI18NCategory("MainSettings");
|
||||
|
||||
networkingSettings->Add(new ItemHeader(ms->T("Networking")));
|
||||
|
||||
|
@ -813,8 +870,16 @@ void GameSettingsScreen::CreateViews() {
|
|||
networkingSettings->Add(new PopupSliderChoice(&g_Config.iPortOffset, 0, 60000, n->T("Port offset", "Port offset (0 = PSP compatibility)"), 100, screenManager()));
|
||||
networkingSettings->Add(new PopupSliderChoice(&g_Config.iMinTimeout, 0, 15000, n->T("Minimum Timeout", "Minimum Timeout (override in ms, 0 = default)"), 50, screenManager()));
|
||||
networkingSettings->Add(new CheckBox(&g_Config.bForcedFirstConnect, n->T("Forced First Connect", "Forced First Connect (faster Connect)")));
|
||||
}
|
||||
|
||||
LinearLayout *tools = AddTab("GameSettingsTools", ms->T("Tools"));
|
||||
void GameSettingsScreen::CreateToolsSettings(UI::ViewGroup *tools) {
|
||||
using namespace UI;
|
||||
|
||||
auto sa = GetI18NCategory("Savedata");
|
||||
auto sy = GetI18NCategory("System");
|
||||
auto ms = GetI18NCategory("MainSettings");
|
||||
auto dev = GetI18NCategory("Developer");
|
||||
auto ri = GetI18NCategory("RemoteISO");
|
||||
|
||||
tools->Add(new ItemHeader(ms->T("Tools")));
|
||||
// These were moved here so use the wrong translation objects, to avoid having to change all inis... This isn't a sustainable situation :P
|
||||
|
@ -822,9 +887,14 @@ void GameSettingsScreen::CreateViews() {
|
|||
tools->Add(new Choice(dev->T("System Information")))->OnClick.Handle(this, &GameSettingsScreen::OnSysInfo);
|
||||
tools->Add(new Choice(sy->T("Developer Tools")))->OnClick.Handle(this, &GameSettingsScreen::OnDeveloperTools);
|
||||
tools->Add(new Choice(ri->T("Remote disc streaming")))->OnClick.Handle(this, &GameSettingsScreen::OnRemoteISO);
|
||||
}
|
||||
|
||||
// System
|
||||
LinearLayout *systemSettings = AddTab("GameSettingsSystem", ms->T("System"));
|
||||
void GameSettingsScreen::CreateSystemSettings(UI::ViewGroup *systemSettings) {
|
||||
using namespace UI;
|
||||
|
||||
auto sy = GetI18NCategory("System");
|
||||
auto vr = GetI18NCategory("VR");
|
||||
auto th = GetI18NCategory("Themes");
|
||||
|
||||
systemSettings->Add(new ItemHeader(sy->T("UI")));
|
||||
|
||||
|
@ -870,10 +940,11 @@ void GameSettingsScreen::CreateViews() {
|
|||
PopupMultiChoiceDynamic *theme = systemSettings->Add(new PopupMultiChoiceDynamic(&g_Config.sThemeName, sy->T("Theme"), GetThemeInfoNames(), th->GetName(), screenManager()));
|
||||
theme->OnChoice.Add([=](EventParams &e) {
|
||||
UpdateTheme(screenManager()->getUIContext());
|
||||
|
||||
return UI::EVENT_CONTINUE;
|
||||
});
|
||||
|
||||
Draw::DrawContext *draw = screenManager()->getDrawContext();
|
||||
|
||||
if (!draw->GetBugs().Has(Draw::Bugs::RASPBERRY_SHADER_COMP_HANG)) {
|
||||
// We use shaders without tint capability on hardware with this driver bug.
|
||||
PopupSliderChoiceFloat *tint = new PopupSliderChoiceFloat(&g_Config.fUITint, 0.0, 1.0, sy->T("Color Tint"), 0.01f, screenManager());
|
||||
|
@ -991,6 +1062,8 @@ void GameSettingsScreen::CreateViews() {
|
|||
|
||||
#if PPSSPP_PLATFORM(ANDROID)
|
||||
if (System_GetPropertyInt(SYSPROP_DEVICE_TYPE) == DEVICE_TYPE_MOBILE) {
|
||||
auto co = GetI18NCategory("Controls");
|
||||
|
||||
static const char *screenRotation[] = { "Auto", "Landscape", "Portrait", "Landscape Reversed", "Portrait Reversed", "Landscape Auto" };
|
||||
PopupMultiChoice *rot = systemSettings->Add(new PopupMultiChoice(&g_Config.iScreenRotation, co->T("Screen Rotation"), screenRotation, 0, ARRAY_SIZE(screenRotation), co->GetName(), screenManager()));
|
||||
rot->OnChoice.Handle(this, &GameSettingsScreen::OnScreenRotation);
|
||||
|
@ -1000,7 +1073,6 @@ void GameSettingsScreen::CreateViews() {
|
|||
}
|
||||
}
|
||||
#endif
|
||||
systemSettings->Add(new CheckBox(&g_Config.bCheckForNewVersion, sy->T("VersionCheck", "Check for new versions of PPSSPP")));
|
||||
|
||||
systemSettings->Add(new Choice(sy->T("Restore Default Settings")))->OnClick.Handle(this, &GameSettingsScreen::OnRestoreDefaultSettings);
|
||||
systemSettings->Add(new CheckBox(&g_Config.bEnableStateUndo, sy->T("Savestate slot backups")));
|
||||
|
@ -1010,6 +1082,7 @@ void GameSettingsScreen::CreateViews() {
|
|||
systemSettings->Add(new CheckBox(&g_Config.bBypassOSKWithKeyboard, sy->T("Use system native keyboard")));
|
||||
|
||||
systemSettings->Add(new CheckBox(&g_Config.bCacheFullIsoInRam, sy->T("Cache ISO in RAM", "Cache full ISO in RAM")))->SetEnabled(!PSP_IsInited());
|
||||
systemSettings->Add(new CheckBox(&g_Config.bCheckForNewVersion, sy->T("VersionCheck", "Check for new versions of PPSSPP")));
|
||||
|
||||
systemSettings->Add(new ItemHeader(sy->T("Cheats", "Cheats")));
|
||||
CheckBox *enableCheats = systemSettings->Add(new CheckBox(&g_Config.bEnableCheats, sy->T("Enable Cheats")));
|
||||
|
@ -1017,10 +1090,9 @@ void GameSettingsScreen::CreateViews() {
|
|||
enableReportsCheckbox_->SetEnabled(Reporting::IsSupported());
|
||||
return UI::EVENT_CONTINUE;
|
||||
});
|
||||
systemSettings->SetSpacing(0);
|
||||
|
||||
systemSettings->Add(new ItemHeader(sy->T("PSP Settings")));
|
||||
static const char *models[] = {"PSP-1000", "PSP-2000/3000"};
|
||||
static const char *models[] = { "PSP-1000", "PSP-2000/3000" };
|
||||
systemSettings->Add(new PopupMultiChoice(&g_Config.iPSPModel, sy->T("PSP Model"), models, 0, ARRAY_SIZE(models), sy->GetName(), screenManager()))->SetEnabled(!PSP_IsInited());
|
||||
// TODO: Come up with a way to display a keyboard for mobile users,
|
||||
// so until then, this is Windows/Desktop only.
|
||||
|
@ -1043,52 +1115,41 @@ void GameSettingsScreen::CreateViews() {
|
|||
systemSettings->Add(new CheckBox(&g_Config.bSaveLoadResetsAVdumping, sy->T("Reset Recording on Save/Load State")));
|
||||
#endif
|
||||
systemSettings->Add(new CheckBox(&g_Config.bDayLightSavings, sy->T("Day Light Saving")));
|
||||
static const char *dateFormat[] = { "YYYYMMDD", "MMDDYYYY", "DDMMYYYY"};
|
||||
static const char *dateFormat[] = { "YYYYMMDD", "MMDDYYYY", "DDMMYYYY" };
|
||||
systemSettings->Add(new PopupMultiChoice(&g_Config.iDateFormat, sy->T("Date Format"), dateFormat, 0, 3, sy->GetName(), screenManager()));
|
||||
static const char *timeFormat[] = { "24HR", "12HR" };
|
||||
systemSettings->Add(new PopupMultiChoice(&g_Config.iTimeFormat, sy->T("Time Format"), timeFormat, 0, 2, sy->GetName(), screenManager()));
|
||||
static const char *buttonPref[] = { "Use O to confirm", "Use X to confirm" };
|
||||
systemSettings->Add(new PopupMultiChoice(&g_Config.iButtonPreference, sy->T("Confirmation Button"), buttonPref, 0, 2, sy->GetName(), screenManager()));
|
||||
}
|
||||
|
||||
#if !defined(MOBILE_DEVICE) || PPSSPP_PLATFORM(ANDROID)
|
||||
// Hide search if screen is too small.
|
||||
if (dp_xres < dp_yres || dp_yres >= 500) {
|
||||
// Search
|
||||
LinearLayout *searchSettings = AddTab("GameSettingsSearch", ms->T("Search"), true);
|
||||
void GameSettingsScreen::CreateVRSettings(UI::ViewGroup *vrSettings) {
|
||||
using namespace UI;
|
||||
|
||||
searchSettings->Add(new ItemHeader(se->T("Find settings")));
|
||||
if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD)) {
|
||||
searchSettings->Add(new ChoiceWithValueDisplay(&searchFilter_, se->T("Filter"), (const char *)nullptr))->OnClick.Handle(this, &GameSettingsScreen::OnChangeSearchFilter);
|
||||
} else {
|
||||
searchSettings->Add(new PopupTextInputChoice(&searchFilter_, se->T("Filter"), "", 64, screenManager()))->OnChange.Handle(this, &GameSettingsScreen::OnChangeSearchFilter);
|
||||
}
|
||||
clearSearchChoice_ = searchSettings->Add(new Choice(se->T("Clear filter")));
|
||||
clearSearchChoice_->OnClick.Handle(this, &GameSettingsScreen::OnClearSearchFilter);
|
||||
noSearchResults_ = searchSettings->Add(new TextView(se->T("No settings matched '%1'"), new LinearLayoutParams(Margins(20, 5))));
|
||||
auto vr = GetI18NCategory("VR");
|
||||
|
||||
ApplySearchFilter();
|
||||
}
|
||||
#endif
|
||||
vrSettings->Add(new ItemHeader(vr->T("Virtual reality")));
|
||||
vrSettings->Add(new CheckBox(&g_Config.bEnableVR, vr->T("Virtual reality")));
|
||||
CheckBox *vr6DoF = vrSettings->Add(new CheckBox(&g_Config.bEnable6DoF, vr->T("6DoF movement")));
|
||||
vr6DoF->SetEnabledPtr(&g_Config.bEnableVR);
|
||||
vrSettings->Add(new CheckBox(&g_Config.bEnableStereo, vr->T("Stereoscopic vision (Experimental)")));
|
||||
vrSettings->Add(new CheckBox(&g_Config.bForce72Hz, vr->T("Force 72Hz update")));
|
||||
|
||||
if (deviceType == DEVICE_TYPE_VR) {
|
||||
LinearLayout *vrSettings = AddTab("GameSettingsVR", ms->T("VR"));
|
||||
vrSettings->Add(new ItemHeader(vr->T("Virtual reality")));
|
||||
vrSettings->Add(new CheckBox(&g_Config.bEnableVR, vr->T("Virtual reality")));
|
||||
CheckBox *vr6DoF = vrSettings->Add(new CheckBox(&g_Config.bEnable6DoF, vr->T("6DoF movement")));
|
||||
vr6DoF->SetEnabledPtr(&g_Config.bEnableVR);
|
||||
vrSettings->Add(new CheckBox(&g_Config.bEnableStereo, vr->T("Stereoscopic vision (Experimental)")));
|
||||
vrSettings->Add(new CheckBox(&g_Config.bForce72Hz, vr->T("Force 72Hz update")));
|
||||
vrSettings->Add(new ItemHeader(vr->T("VR camera")));
|
||||
vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fCanvasDistance, 1.0f, 15.0f, vr->T("Distance to 2D menus and scenes"), 1.0f, screenManager(), ""));
|
||||
vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fFieldOfViewPercentage, 100.0f, 200.0f, vr->T("Field of view scale"), 10.0f, screenManager(), vr->T("% of native FoV")));
|
||||
vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fHeadUpDisplayScale, 0.0f, 1.5f, vr->T("Heads-up display scale"), 0.1f, screenManager(), ""));
|
||||
|
||||
vrSettings->Add(new ItemHeader(vr->T("VR camera")));
|
||||
vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fCanvasDistance, 1.0f, 15.0f, vr->T("Distance to 2D menus and scenes"), 1.0f, screenManager(), ""));
|
||||
vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fFieldOfViewPercentage, 100.0f, 200.0f, vr->T("Field of view scale"), 10.0f, screenManager(), vr->T("% of native FoV")));
|
||||
vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fHeadUpDisplayScale, 0.0f, 1.5f, vr->T("Heads-up display scale"), 0.1f, screenManager(), ""));
|
||||
|
||||
vrSettings->Add(new ItemHeader(vr->T("VR controllers")));
|
||||
vrSettings->Add(new CheckBox(&g_Config.bEnableMotions, vr->T("Map controller movements to keys")));
|
||||
PopupSliderChoiceFloat *vrMotions = vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fMotionLength, 0.3f, 1.0f, vr->T("Motion needed to generate action"), 0.1f, screenManager(), vr->T("m")));
|
||||
vrMotions->SetEnabledPtr(&g_Config.bEnableMotions);
|
||||
}
|
||||
vrSettings->Add(new ItemHeader(vr->T("Experts only")));
|
||||
static const char *vrHeadRotations[] = { vr->T("Disabled"), vr->T("Horizontal only"), vr->T("Horizontal and vertical") };
|
||||
vrSettings->Add(new PopupMultiChoice(&g_Config.iHeadRotation, vr->T("Map HMD rotations on keys instead of VR camera"), vrHeadRotations, 0, ARRAY_SIZE(vrHeadRotations), vr->GetName(), screenManager()));
|
||||
PopupSliderChoiceFloat *vrHeadRotationScale = vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fHeadRotationScale, 0.1f, 10.0f, vr->T("Game camera rotation step per frame"), 0.1f, screenManager(), "°"));
|
||||
vrHeadRotationScale->SetEnabledFunc([&] { return g_Config.iHeadRotation > 0; });
|
||||
CheckBox *vrHeadRotationSmoothing = vrSettings->Add(new CheckBox(&g_Config.bHeadRotationSmoothing, vr->T("Game camera uses rotation smoothing")));
|
||||
vrHeadRotationSmoothing->SetEnabledFunc([&] { return g_Config.iHeadRotation > 0; });
|
||||
vrSettings->Add(new CheckBox(&g_Config.bEnableMotions, vr->T("Map controller movements to keys")));
|
||||
PopupSliderChoiceFloat *vrMotions = vrSettings->Add(new PopupSliderChoiceFloat(&g_Config.fMotionLength, 0.3f, 1.0f, vr->T("Motion needed to generate action"), 0.1f, screenManager(), vr->T("m")));
|
||||
vrMotions->SetEnabledPtr(&g_Config.bEnableMotions);
|
||||
}
|
||||
|
||||
UI::LinearLayout *GameSettingsScreen::AddTab(const char *tag, const std::string &title, bool isSearch) {
|
||||
|
@ -1834,27 +1895,24 @@ void DeveloperToolsScreen::onFinish(DialogResult result) {
|
|||
}
|
||||
|
||||
void GameSettingsScreen::CallbackRestoreDefaults(bool yes) {
|
||||
if (yes)
|
||||
g_Config.RestoreDefaults();
|
||||
if (yes) {
|
||||
g_Config.RestoreDefaults(RestoreSettingsBits::SETTINGS);
|
||||
}
|
||||
host->UpdateUI();
|
||||
}
|
||||
|
||||
UI::EventReturn GameSettingsScreen::OnRestoreDefaultSettings(UI::EventParams &e) {
|
||||
auto dev = GetI18NCategory("Developer");
|
||||
auto di = GetI18NCategory("Dialog");
|
||||
if (g_Config.bGameSpecific)
|
||||
{
|
||||
auto sy = GetI18NCategory("System");
|
||||
if (g_Config.bGameSpecific) {
|
||||
screenManager()->push(
|
||||
new PromptScreen(gamePath_, dev->T("RestoreGameDefaultSettings", "Are you sure you want to restore the game-specific settings back to the ppsspp defaults?\n"), di->T("OK"), di->T("Cancel"),
|
||||
std::bind(&GameSettingsScreen::CallbackRestoreDefaults, this, std::placeholders::_1)));
|
||||
} else {
|
||||
const char *title = sy->T("Restore Default Settings");
|
||||
screenManager()->push(new RestoreSettingsScreen(title));
|
||||
}
|
||||
else
|
||||
{
|
||||
screenManager()->push(
|
||||
new PromptScreen(gamePath_, dev->T("RestoreDefaultSettings", "Are you sure you want to restore all settings(except control mapping)\nback to their defaults?\nYou can't undo this.\nPlease restart PPSSPP after restoring settings."), di->T("OK"), di->T("Cancel"),
|
||||
std::bind(&GameSettingsScreen::CallbackRestoreDefaults, this, std::placeholders::_1)));
|
||||
}
|
||||
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
|
@ -2196,3 +2254,32 @@ void GestureMappingScreen::CreateViews() {
|
|||
vert->Add(new ItemHeader(co->T("Double tap")));
|
||||
vert->Add(new PopupMultiChoice(&g_Config.iDoubleTapGesture, mc->T("Double tap button"), gestureButton, 0, ARRAY_SIZE(gestureButton), mc->GetName(), screenManager()))->SetEnabledPtr(&g_Config.bGestureControlEnabled);
|
||||
}
|
||||
|
||||
RestoreSettingsScreen::RestoreSettingsScreen(const char *title)
|
||||
: PopupScreen(title, "OK", "Cancel") {}
|
||||
|
||||
void RestoreSettingsScreen::CreatePopupContents(UI::ViewGroup *parent) {
|
||||
using namespace UI;
|
||||
// Carefully re-use various translations.
|
||||
auto ga = GetI18NCategory("Game");
|
||||
auto ms = GetI18NCategory("MainSettings");
|
||||
auto mm = GetI18NCategory("MainMenu");
|
||||
auto dev = GetI18NCategory("Developer");
|
||||
|
||||
const char *text = dev->T(
|
||||
"RestoreDefaultSettings",
|
||||
"Restore these settings back to their defaults?\nYou can't undo this.\nPlease restart PPSSPP after restoring settings.");
|
||||
|
||||
TextView *textView = parent->Add(new TextView(text, FLAG_WRAP_TEXT, false));
|
||||
textView->SetPadding(10.0f);
|
||||
|
||||
parent->Add(new BitCheckBox(&restoreFlags_, (int)RestoreSettingsBits::SETTINGS, ga->T("Game Settings")));
|
||||
parent->Add(new BitCheckBox(&restoreFlags_, (int)RestoreSettingsBits::CONTROLS, ga->T("Controls")));
|
||||
parent->Add(new BitCheckBox(&restoreFlags_, (int)RestoreSettingsBits::RECENT, mm->T("Recent")));
|
||||
}
|
||||
|
||||
void RestoreSettingsScreen::OnCompleted(DialogResult result) {
|
||||
if (result == DialogResult::DR_OK) {
|
||||
g_Config.RestoreDefaults((RestoreSettingsBits)restoreFlags_);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
#include "Common/UI/UIScreen.h"
|
||||
#include "Core/ConfigValues.h"
|
||||
#include "UI/MiscScreens.h"
|
||||
|
||||
// Per-game settings screen - enables you to configure graphic options, control options, etc
|
||||
|
@ -45,31 +47,39 @@ protected:
|
|||
void RecreateViews() override;
|
||||
|
||||
private:
|
||||
void CreateGraphicsSettings(UI::ViewGroup *graphicsSettings);
|
||||
void CreateControlsSettings(UI::ViewGroup *tools);
|
||||
void CreateAudioSettings(UI::ViewGroup *audioSettings);
|
||||
void CreateNetworkingSettings(UI::ViewGroup *networkingSettings);
|
||||
void CreateToolsSettings(UI::ViewGroup *tools);
|
||||
void CreateSystemSettings(UI::ViewGroup *systemSettings);
|
||||
void CreateVRSettings(UI::ViewGroup *vrSettings);
|
||||
|
||||
UI::LinearLayout *AddTab(const char *tag, const std::string &title, bool isSearch = false);
|
||||
void ApplySearchFilter();
|
||||
void TriggerRestart(const char *why);
|
||||
|
||||
std::string gameID_;
|
||||
UI::CheckBox *enableReportsCheckbox_;
|
||||
UI::Choice *layoutEditorChoice_;
|
||||
UI::Choice *displayEditor_;
|
||||
UI::CheckBox *enableReportsCheckbox_ = nullptr;
|
||||
UI::Choice *layoutEditorChoice_ = nullptr;
|
||||
UI::Choice *displayEditor_ = nullptr;
|
||||
UI::Choice *backgroundChoice_ = nullptr;
|
||||
UI::PopupMultiChoice *resolutionChoice_;
|
||||
UI::CheckBox *frameSkipAuto_;
|
||||
SettingInfoMessage *settingInfo_;
|
||||
UI::Choice *clearSearchChoice_;
|
||||
UI::TextView *noSearchResults_;
|
||||
UI::PopupMultiChoice *resolutionChoice_ = nullptr;
|
||||
UI::CheckBox *frameSkipAuto_ = nullptr;
|
||||
SettingInfoMessage *settingInfo_ = nullptr;
|
||||
UI::Choice *clearSearchChoice_ = nullptr;
|
||||
UI::TextView *noSearchResults_ = nullptr;
|
||||
#ifdef _WIN32
|
||||
UI::CheckBox *SavePathInMyDocumentChoice;
|
||||
UI::CheckBox *SavePathInOtherChoice;
|
||||
UI::CheckBox *SavePathInMyDocumentChoice = nullptr;
|
||||
UI::CheckBox *SavePathInOtherChoice = nullptr;
|
||||
// Used to enable/disable the above two options.
|
||||
bool installed_;
|
||||
bool otherinstalled_;
|
||||
bool installed_ = false;
|
||||
bool otherinstalled_ = false;
|
||||
#endif
|
||||
|
||||
std::string memstickDisplay_;
|
||||
|
||||
UI::TabHolder *tabHolder_;
|
||||
UI::TabHolder *tabHolder_ = nullptr;
|
||||
std::vector<UI::LinearLayout *> settingTabContents_;
|
||||
std::vector<UI::TextView *> settingTabFilterNotices_;
|
||||
|
||||
|
@ -125,18 +135,18 @@ private:
|
|||
UI::EventReturn OnClearSearchFilter(UI::EventParams &e);
|
||||
|
||||
// Temporaries to convert setting types, cache enabled, etc.
|
||||
int iAlternateSpeedPercent1_;
|
||||
int iAlternateSpeedPercent2_;
|
||||
int iAlternateSpeedPercentAnalog_;
|
||||
int prevInflightFrames_;
|
||||
int iAlternateSpeedPercent1_ = 0;
|
||||
int iAlternateSpeedPercent2_ = 0;
|
||||
int iAlternateSpeedPercentAnalog_ = 0;
|
||||
int prevInflightFrames_ = -1;
|
||||
bool enableReports_ = false;
|
||||
bool enableReportsSet_ = false;
|
||||
bool analogSpeedMapped_ = false;
|
||||
|
||||
std::string searchFilter_;
|
||||
|
||||
//edit the game-specific settings and restore the global settings after exiting
|
||||
bool editThenRestore_;
|
||||
// edit the game-specific settings and restore the global settings after exiting
|
||||
bool editThenRestore_ = false;
|
||||
|
||||
// Android-only
|
||||
std::string pendingMemstickFolder_;
|
||||
|
@ -205,6 +215,7 @@ protected:
|
|||
private:
|
||||
void ResolverThread();
|
||||
void SendEditKey(int keyCode, int flags = 0);
|
||||
|
||||
UI::EventReturn OnNumberClick(UI::EventParams &e);
|
||||
UI::EventReturn OnPointClick(UI::EventParams &e);
|
||||
UI::EventReturn OnDeleteClick(UI::EventParams &e);
|
||||
|
@ -244,3 +255,14 @@ public:
|
|||
|
||||
const char *tag() const override { return "GestureMapping"; }
|
||||
};
|
||||
|
||||
class RestoreSettingsScreen : public PopupScreen {
|
||||
public:
|
||||
RestoreSettingsScreen(const char *title);
|
||||
void CreatePopupContents(UI::ViewGroup *parent) override;
|
||||
|
||||
const char *tag() const override { return "RestoreSettingsScreen"; }
|
||||
private:
|
||||
void OnCompleted(DialogResult result) override;
|
||||
int restoreFlags_ = (int)(RestoreSettingsBits::SETTINGS); // RestoreSettingsBits enum
|
||||
};
|
||||
|
|
|
@ -319,6 +319,10 @@ namespace CustomKey {
|
|||
#ifndef MOBILE_DEVICE
|
||||
{ ImageID::invalid(), VIRTKEY_RECORD },
|
||||
#endif
|
||||
{ ImageID::invalid(), VIRTKEY_AXIS_X_MIN },
|
||||
{ ImageID::invalid(), VIRTKEY_AXIS_Y_MIN },
|
||||
{ ImageID::invalid(), VIRTKEY_AXIS_X_MAX },
|
||||
{ ImageID::invalid(), VIRTKEY_AXIS_Y_MAX },
|
||||
};
|
||||
static_assert(ARRAY_SIZE(comboKeyList) <= 64, "Too many key for a uint64_t bit mask");
|
||||
};
|
||||
|
@ -357,5 +361,9 @@ namespace GestureKey {
|
|||
#ifndef MOBILE_DEVICE
|
||||
VIRTKEY_RECORD,
|
||||
#endif
|
||||
VIRTKEY_AXIS_X_MIN,
|
||||
VIRTKEY_AXIS_Y_MIN,
|
||||
VIRTKEY_AXIS_X_MAX,
|
||||
VIRTKEY_AXIS_Y_MAX,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1024,10 +1024,10 @@ void MainScreen::CreateViews() {
|
|||
scrollHomebrew->SetTag("MainScreenHomebrew");
|
||||
|
||||
GameBrowser *tabAllGames = new GameBrowser(Path(g_Config.currentDirectory), BrowseFlags::STANDARD, &g_Config.bGridView2, screenManager(),
|
||||
mm->T("How to get games"), "https://www.ppsspp.org/getgames.html",
|
||||
mm->T("How to get games"), "https://www.ppsspp.org/getgames",
|
||||
new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
|
||||
GameBrowser *tabHomebrew = new GameBrowser(GetSysDirectory(DIRECTORY_GAME), BrowseFlags::HOMEBREW_STORE, &g_Config.bGridView3, screenManager(),
|
||||
mm->T("How to get homebrew & demos", "How to get homebrew && demos"), "https://www.ppsspp.org/gethomebrew.html",
|
||||
mm->T("How to get homebrew & demos", "How to get homebrew && demos"), "https://www.ppsspp.org/gethomebrew",
|
||||
new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
|
||||
|
||||
scrollAllGames_->Add(tabAllGames);
|
||||
|
@ -1221,7 +1221,7 @@ UI::EventReturn MainScreen::OnDownloadUpgrade(UI::EventParams &e) {
|
|||
LaunchBrowser("market://details?id=org.ppsspp.ppsspp");
|
||||
}
|
||||
#elif PPSSPP_PLATFORM(WINDOWS)
|
||||
LaunchBrowser("https://www.ppsspp.org/downloads.html");
|
||||
LaunchBrowser("https://www.ppsspp.org/download");
|
||||
#else
|
||||
// Go directly to ppsspp.org and let the user sort it out
|
||||
// (for details and in case downloads doesn't have their platform.)
|
||||
|
@ -1406,7 +1406,7 @@ UI::EventReturn MainScreen::OnSupport(UI::EventParams &e) {
|
|||
#ifdef __ANDROID__
|
||||
LaunchBrowser("market://details?id=org.ppsspp.ppssppgold");
|
||||
#else
|
||||
LaunchBrowser("https://central.ppsspp.org/buygold");
|
||||
LaunchBrowser("https://www.ppsspp.org/buygold");
|
||||
#endif
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
|
|
@ -302,6 +302,8 @@ void MemStickScreen::CreateViews() {
|
|||
}
|
||||
|
||||
UI::EventReturn MemStickScreen::OnHelp(UI::EventParams ¶ms) {
|
||||
// I'm letting the old redirect handle this one, as the target is within /docs on the website,
|
||||
// and that structure may change a bit.
|
||||
LaunchBrowser("https://www.ppsspp.org/guide_storage.html");
|
||||
|
||||
return UI::EVENT_DONE;
|
||||
|
|
|
@ -842,7 +842,7 @@ UI::EventReturn CreditsScreen::OnSupport(UI::EventParams &e) {
|
|||
#ifdef __ANDROID__
|
||||
LaunchBrowser("market://details?id=org.ppsspp.ppssppgold");
|
||||
#else
|
||||
LaunchBrowser("https://central.ppsspp.org/buygold");
|
||||
LaunchBrowser("https://www.ppsspp.org/buygold");
|
||||
#endif
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
@ -862,7 +862,7 @@ UI::EventReturn CreditsScreen::OnPPSSPPOrg(UI::EventParams &e) {
|
|||
}
|
||||
|
||||
UI::EventReturn CreditsScreen::OnPrivacy(UI::EventParams &e) {
|
||||
LaunchBrowser("https://www.ppsspp.org/privacy.html");
|
||||
LaunchBrowser("https://www.ppsspp.org/privacy");
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
||||
|
|
|
@ -1479,7 +1479,7 @@ void NativeInputBoxReceived(std::function<void(bool, const std::string &)> cb, b
|
|||
|
||||
void NativeResized() {
|
||||
// NativeResized can come from any thread so we just set a flag, then process it later.
|
||||
INFO_LOG(G3D, "NativeResized - setting flag");
|
||||
VERBOSE_LOG(G3D, "NativeResized - setting flag");
|
||||
resized = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -662,6 +662,11 @@
|
|||
<None Include="..\..\Common\Math\fast\fast_matrix_neon.S" />
|
||||
<None Include="..\..\Common\Math\lin\matrix_neon.s" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\cpu_features_UWP\cpu_features_UWP.vcxproj">
|
||||
<Project>{c249f016-7f82-45cf-bb6e-0642a988c4d3}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -32,6 +32,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libzstd_UWP", "libzstd_UWP\
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniupnpc_UWP", "miniupnpc_UWP\miniupnpc_UWP.vcxproj", "{D31FD4F0-53EB-477C-9DC7-149796F628E2}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpu_features_UWP", "cpu_features_UWP\cpu_features_UWP.vcxproj", "{C249F016-7F82-45CF-BB6E-0642A988C4D3}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM = Debug|ARM
|
||||
|
@ -372,6 +374,30 @@ Global
|
|||
{D31FD4F0-53EB-477C-9DC7-149796F628E2}.UWP Gold|Win32.Build.0 = UWP Gold|Win32
|
||||
{D31FD4F0-53EB-477C-9DC7-149796F628E2}.UWP Gold|x64.ActiveCfg = UWP Gold|x64
|
||||
{D31FD4F0-53EB-477C-9DC7-149796F628E2}.UWP Gold|x64.Build.0 = UWP Gold|x64
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|x64.Build.0 = Debug|x64
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|ARM.Build.0 = Release|ARM
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|Win32.Build.0 = Release|Win32
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|x64.ActiveCfg = Release|x64
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|x64.Build.0 = Release|x64
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|ARM.ActiveCfg = UWP Gold|ARM
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|ARM.Build.0 = UWP Gold|ARM
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|ARM64.ActiveCfg = UWP Gold|ARM64
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|ARM64.Build.0 = UWP Gold|ARM64
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|Win32.ActiveCfg = UWP Gold|Win32
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|Win32.Build.0 = UWP Gold|Win32
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|x64.ActiveCfg = UWP Gold|x64
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.UWP Gold|x64.Build.0 = UWP Gold|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
442
UWP/cpu_features_UWP/cpu_features_UWP.vcxproj
Normal file
442
UWP/cpu_features_UWP/cpu_features_UWP.vcxproj
Normal file
|
@ -0,0 +1,442 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|ARM">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|ARM64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|ARM64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="UWP Gold|ARM">
|
||||
<Configuration>UWP Gold</Configuration>
|
||||
<Platform>ARM</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="UWP Gold|ARM64">
|
||||
<Configuration>UWP Gold</Configuration>
|
||||
<Platform>ARM64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="UWP Gold|Win32">
|
||||
<Configuration>UWP Gold</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="UWP Gold|x64">
|
||||
<Configuration>UWP Gold</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{C249F016-7F82-45CF-BB6E-0642A988C4D3}</ProjectGuid>
|
||||
<Keyword>StaticLibrary</Keyword>
|
||||
<RootNamespace>cpufeatures</RootNamespace>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
|
||||
<AppContainerApplication>true</AppContainerApplication>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<WindowsTargetPlatformMinVersion>10.0.15063.0</WindowsTargetPlatformMinVersion>
|
||||
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='UWP Gold|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='UWP Gold|ARM'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='UWP Gold|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>false</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='UWP Gold|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='UWP Gold|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='UWP Gold|ARM'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='UWP Gold|ARM64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='UWP Gold|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='UWP Gold|Win32'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='UWP Gold|ARM'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='UWP Gold|ARM64'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='UWP Gold|x64'">
|
||||
<GenerateManifest>false</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>../../ext/cpu_features/include</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>../../ext/cpu_features/include</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='UWP Gold|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>../../ext/cpu_features/include</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|arm'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>../../ext/cpu_features/include</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>../../ext/cpu_features/include</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|arm'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>../../ext/cpu_features/include</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>../../ext/cpu_features/include</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='UWP Gold|arm'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>../../ext/cpu_features/include</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='UWP Gold|ARM64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>../../ext/cpu_features/include</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>../../ext/cpu_features/include</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>../../ext/cpu_features/include</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='UWP Gold|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||
<AdditionalIncludeDirectories>../../ext/cpu_features/include</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>STACK_LINE_READER_BUFFER_SIZE=1024;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<IgnoreAllDefaultLibraries>false</IgnoreAllDefaultLibraries>
|
||||
<GenerateWindowsMetadata>false</GenerateWindowsMetadata>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\cpuinfo_aarch64.h" />
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\cpuinfo_arm.h" />
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\cpuinfo_mips.h" />
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\cpuinfo_ppc.h" />
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\cpuinfo_riscv.h" />
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\cpuinfo_s390x.h" />
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\cpuinfo_x86.h" />
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\cpu_features_cache_info.h" />
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\cpu_features_macros.h" />
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\internal\bit_utils.h" />
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\internal\cpuid_x86.h" />
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\internal\filesystem.h" />
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\internal\stack_line_reader.h" />
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\internal\string_view.h" />
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\internal\windows_utils.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="..\..\ext\cpu_features\CMakeLists.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\ext\cpu_features\src\copy.inl" />
|
||||
<None Include="..\..\ext\cpu_features\src\define_introspection.inl" />
|
||||
<None Include="..\..\ext\cpu_features\src\define_introspection_and_hwcaps.inl" />
|
||||
<None Include="..\..\ext\cpu_features\src\equals.inl" />
|
||||
<None Include="..\..\ext\cpu_features\src\impl_x86__base_implementation.inl" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\filesystem.c" />
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\impl_aarch64_linux_or_android.c" />
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\impl_arm_linux_or_android.c" />
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\impl_mips_linux_or_android.c" />
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\impl_ppc_linux.c" />
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\impl_riscv_linux.c" />
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\impl_s390x_linux.c" />
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\impl_x86_freebsd.c" />
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\impl_x86_linux_or_android.c" />
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\impl_x86_macos.c" />
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\impl_x86_windows.c" />
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\stack_line_reader.c" />
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\string_view.c" />
|
||||
<ClCompile Include="pch.c">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='UWP Gold|Win32'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='UWP Gold|ARM'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='UWP Gold|ARM64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='UWP Gold|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
133
UWP/cpu_features_UWP/cpu_features_UWP.vcxproj.filters
Normal file
133
UWP/cpu_features_UWP/cpu_features_UWP.vcxproj.filters
Normal file
|
@ -0,0 +1,133 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\internal">
|
||||
<UniqueIdentifier>{530543f7-fdda-43c7-8982-427e4d69e74d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="targetver.h" />
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\cpuinfo_arm.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\cpuinfo_mips.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\cpuinfo_ppc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\cpuinfo_riscv.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\cpuinfo_s390x.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\cpuinfo_x86.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\cpu_features_cache_info.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\cpu_features_macros.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\cpuinfo_aarch64.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\internal\filesystem.h">
|
||||
<Filter>Header Files\internal</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\internal\stack_line_reader.h">
|
||||
<Filter>Header Files\internal</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\internal\string_view.h">
|
||||
<Filter>Header Files\internal</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\internal\windows_utils.h">
|
||||
<Filter>Header Files\internal</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\internal\bit_utils.h">
|
||||
<Filter>Header Files\internal</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\ext\cpu_features\include\internal\cpuid_x86.h">
|
||||
<Filter>Header Files\internal</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="..\..\ext\cpu_features\CMakeLists.txt">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Text>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\ext\cpu_features\src\impl_x86__base_implementation.inl">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
<None Include="..\..\ext\cpu_features\src\copy.inl">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
<None Include="..\..\ext\cpu_features\src\define_introspection.inl">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
<None Include="..\..\ext\cpu_features\src\define_introspection_and_hwcaps.inl">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
<None Include="..\..\ext\cpu_features\src\equals.inl">
|
||||
<Filter>Source Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.c" />
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\impl_x86_freebsd.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\impl_x86_linux_or_android.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\impl_x86_macos.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\impl_x86_windows.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\stack_line_reader.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\string_view.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\filesystem.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\impl_aarch64_linux_or_android.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\impl_arm_linux_or_android.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\impl_mips_linux_or_android.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\impl_ppc_linux.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\impl_riscv_linux.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\ext\cpu_features\src\impl_s390x_linux.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
1
UWP/cpu_features_UWP/pch.c
Normal file
1
UWP/cpu_features_UWP/pch.c
Normal file
|
@ -0,0 +1 @@
|
|||
#include "pch.h"
|
4
UWP/cpu_features_UWP/pch.h
Normal file
4
UWP/cpu_features_UWP/pch.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
#include "targetver.h"
|
||||
|
8
UWP/cpu_features_UWP/targetver.h
Normal file
8
UWP/cpu_features_UWP/targetver.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
// Including SDKDDKVer.h defines the highest available Windows platform.
|
||||
|
||||
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
|
||||
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
|
||||
|
||||
#include <SDKDDKVer.h>
|
1
Windows/.gitignore
vendored
1
Windows/.gitignore
vendored
|
@ -1,2 +1,3 @@
|
|||
*.VC.VC.opendb
|
||||
*.VC.db
|
||||
enc_temp_folder
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// NOTE: Apologies for the quality of this code, this is really from pre-opensource Dolphin - that is, 2003.
|
||||
|
||||
#include "Core/Config.h"
|
||||
#include "Core/MemMap.h"
|
||||
#include "Windows/resource.h"
|
||||
|
@ -13,6 +11,7 @@
|
|||
#include "Windows/Debugger/Debugger_Disasm.h"
|
||||
#include "Windows/Debugger/Debugger_VFPUDlg.h"
|
||||
#include "Windows/Debugger/DebuggerShared.h"
|
||||
// #include "Windows/W32Util/DarkMode.h"
|
||||
|
||||
#include "Windows/main.h"
|
||||
#include "Windows/Debugger/CtrlRegisterList.h"
|
||||
|
@ -350,10 +349,8 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam)
|
|||
switch(message)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
// DarkModeInitDialog(m_hDlg);
|
||||
return TRUE;
|
||||
|
||||
case WM_NOTIFY:
|
||||
switch (wParam)
|
||||
|
@ -692,7 +689,7 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
return 0; // DarkModeDlgProc(m_hDlg, message, wParam, lParam);
|
||||
}
|
||||
|
||||
void CDisasm::updateThreadLabel(bool clear)
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
// NOTE: Apologies for the quality of this code, this is really from pre-opensource Dolphin - that is, 2003.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Windows/W32Util/DialogManager.h"
|
||||
|
|
|
@ -82,7 +82,9 @@ static void EmuThreadFunc(GraphicsContext *graphicsContext) {
|
|||
// This way they can load a new game.
|
||||
if (!Core_IsActive())
|
||||
UpdateUIState(UISTATE_MENU);
|
||||
Core_Run(g_graphicsContext);
|
||||
if (!Core_Run(g_graphicsContext)) {
|
||||
emuThreadState = (int)EmuThreadState::QUIT_REQUESTED;
|
||||
}
|
||||
}
|
||||
|
||||
emuThreadState = (int)EmuThreadState::STOPPED;
|
||||
|
@ -99,12 +101,14 @@ static void EmuThreadStart(GraphicsContext *graphicsContext) {
|
|||
}
|
||||
|
||||
static void EmuThreadStop() {
|
||||
emuThreadState = (int)EmuThreadState::QUIT_REQUESTED;
|
||||
if (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED &&
|
||||
emuThreadState != (int)EmuThreadState::STOPPED) {
|
||||
emuThreadState = (int)EmuThreadState::QUIT_REQUESTED;
|
||||
}
|
||||
}
|
||||
|
||||
static void EmuThreadJoin() {
|
||||
emuThread.join();
|
||||
emuThread = std::thread();
|
||||
INFO_LOG(SYSTEM, "EmuThreadJoin - joined");
|
||||
}
|
||||
|
||||
|
|
|
@ -432,7 +432,7 @@ bool WindowsGLContext::InitFromRenderThread(std::string *error_message) {
|
|||
renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||
renderManager_->SetInflightFrames(g_Config.iInflightFrames);
|
||||
SetGPUBackend(GPUBackend::OPENGL);
|
||||
renderManager_->SetSwapFunction([&]() {::SwapBuffers(hDC); });
|
||||
renderManager_->SetSwapFunction([&]() {::SwapBuffers(hDC); }, true);
|
||||
if (wglSwapIntervalEXT) {
|
||||
// glew loads wglSwapIntervalEXT if available
|
||||
renderManager_->SetSwapIntervalFunction([&](int interval) {
|
||||
|
@ -500,6 +500,5 @@ void WindowsGLContext::ThreadEnd() {
|
|||
}
|
||||
|
||||
void WindowsGLContext::StopThread() {
|
||||
renderManager_->WaitUntilQueueIdle();
|
||||
renderManager_->StopThread();
|
||||
}
|
||||
|
|
|
@ -56,6 +56,8 @@
|
|||
#include "Windows/GPU/WindowsGLContext.h"
|
||||
#include "Windows/GEDebugger/GEDebugger.h"
|
||||
#endif
|
||||
#include "Windows/W32Util/DarkMode.h"
|
||||
#include "Windows/W32Util/UAHMenuBar.h"
|
||||
#include "Windows/Debugger/Debugger_Disasm.h"
|
||||
#include "Windows/Debugger/Debugger_MemoryDlg.h"
|
||||
|
||||
|
@ -177,7 +179,7 @@ namespace MainWindow
|
|||
|
||||
WNDCLASSEX wcdisp;
|
||||
memset(&wcdisp, 0, sizeof(wcdisp));
|
||||
// Display Window
|
||||
// Display Window (contained in main window)
|
||||
wcdisp.cbSize = sizeof(WNDCLASSEX);
|
||||
wcdisp.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wcdisp.lpfnWndProc = (WNDPROC)DisplayProc;
|
||||
|
@ -728,13 +730,52 @@ namespace MainWindow
|
|||
return 0;
|
||||
}
|
||||
|
||||
RECT MapRectFromClientToWndCoords(HWND hwnd, const RECT & r)
|
||||
{
|
||||
RECT wnd_coords = r;
|
||||
|
||||
// map to screen
|
||||
MapWindowPoints(hwnd, NULL, reinterpret_cast<POINT *>(&wnd_coords), 2);
|
||||
|
||||
RECT scr_coords;
|
||||
GetWindowRect(hwnd, &scr_coords);
|
||||
|
||||
// map to window coords by substracting the window coord origin in
|
||||
// screen coords.
|
||||
OffsetRect(&wnd_coords, -scr_coords.left, -scr_coords.top);
|
||||
|
||||
return wnd_coords;
|
||||
}
|
||||
|
||||
RECT GetNonclientMenuBorderRect(HWND hwnd)
|
||||
{
|
||||
RECT r;
|
||||
GetClientRect(hwnd, &r);
|
||||
r = MapRectFromClientToWndCoords(hwnd, r);
|
||||
int y = r.top - 1;
|
||||
return {
|
||||
r.left,
|
||||
y,
|
||||
r.right,
|
||||
y + 1
|
||||
};
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
LRESULT darkResult = 0;
|
||||
if (UAHDarkModeWndProc(hWnd, message, wParam, lParam, &darkResult)) {
|
||||
return darkResult;
|
||||
}
|
||||
|
||||
switch (message) {
|
||||
case WM_CREATE:
|
||||
if (!DoesVersionMatchWindows(6, 0, 0, 0, true)) {
|
||||
// Remove the D3D11 choice on versions below XP
|
||||
RemoveMenu(GetMenu(hWnd), ID_OPTIONS_DIRECT3D11, MF_BYCOMMAND);
|
||||
}
|
||||
if (g_darkModeSupported) {
|
||||
SendMessageW(hWnd, WM_THEMECHANGED, 0, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_USER_GET_BASE_POINTER:
|
||||
|
@ -749,6 +790,26 @@ namespace MainWindow
|
|||
}
|
||||
break;
|
||||
|
||||
// Hack to kill the white line underneath the menubar.
|
||||
// From https://stackoverflow.com/questions/57177310/how-to-paint-over-white-line-between-menu-bar-and-client-area-of-window
|
||||
case WM_NCPAINT:
|
||||
case WM_NCACTIVATE:
|
||||
{
|
||||
if (!IsDarkModeEnabled() || IsIconic(hWnd)) {
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
auto result = DefWindowProc(hWnd, message, wParam, lParam);
|
||||
// Paint over the line with pure black. Could also try to figure out the dark theme color.
|
||||
HDC hdc = GetWindowDC(hWnd);
|
||||
RECT r = GetNonclientMenuBorderRect(hWnd);
|
||||
HBRUSH red = CreateSolidBrush(RGB(0, 0, 0));
|
||||
FillRect(hdc, &r, red);
|
||||
DeleteObject(red);
|
||||
ReleaseDC(hWnd, hdc);
|
||||
return result;
|
||||
}
|
||||
|
||||
case WM_GETMINMAXINFO:
|
||||
{
|
||||
MINMAXINFO *minmax = reinterpret_cast<MINMAXINFO *>(lParam);
|
||||
|
@ -804,7 +865,7 @@ namespace MainWindow
|
|||
|
||||
case WM_ERASEBKGND:
|
||||
// This window is always covered by DisplayWindow. No reason to erase.
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
case WM_MOVE:
|
||||
SavePosition();
|
||||
|
@ -1048,6 +1109,23 @@ namespace MainWindow
|
|||
}
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
break;
|
||||
case WM_SETTINGCHANGE:
|
||||
{
|
||||
if (g_darkModeSupported && IsColorSchemeChangeMessage(lParam))
|
||||
SendMessageW(hWnd, WM_THEMECHANGED, 0, 0);
|
||||
}
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
|
||||
case WM_THEMECHANGED:
|
||||
{
|
||||
if (g_darkModeSupported)
|
||||
{
|
||||
_AllowDarkModeForWindow(hWnd, g_darkModeEnabled);
|
||||
RefreshTitleBarThemeColor(hWnd);
|
||||
}
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
default:
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "Windows/W32Util/Misc.h"
|
||||
#include "Windows/InputBox.h"
|
||||
#include "Windows/main.h"
|
||||
#include "Windows/W32Util/DarkMode.h"
|
||||
|
||||
#include "Core/HLE/sceUmd.h"
|
||||
#include "Core/SaveState.h"
|
||||
|
@ -65,7 +66,7 @@ namespace MainWindow {
|
|||
static bool menuShaderInfoLoaded = false;
|
||||
std::vector<ShaderInfo> menuShaderInfo;
|
||||
|
||||
LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
|
||||
LRESULT CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM);
|
||||
|
||||
void SetIngameMenuItemStates(HMENU menu, const GlobalUIState state) {
|
||||
UINT menuEnable = state == UISTATE_INGAME || state == UISTATE_EXCEPTION ? MF_ENABLED : MF_GRAYED;
|
||||
|
@ -278,7 +279,6 @@ namespace MainWindow {
|
|||
TranslateMenuItem(menu, ID_TEXTURESCALING_DEPOSTERIZE);
|
||||
TranslateMenuItem(menu, ID_OPTIONS_HARDWARETRANSFORM);
|
||||
TranslateMenuItem(menu, ID_OPTIONS_VERTEXCACHE);
|
||||
TranslateMenuItem(menu, ID_OPTIONS_SHOWFPS);
|
||||
TranslateMenuItem(menu, ID_EMULATION_SOUND);
|
||||
TranslateMenuItem(menu, ID_EMULATION_CHEATS, g_Config.bSystemControls ? L"\tCtrl+T" : L"");
|
||||
TranslateMenuItem(menu, ID_EMULATION_CHAT, g_Config.bSystemControls ? L"\tCtrl+C" : L"");
|
||||
|
@ -882,11 +882,6 @@ namespace MainWindow {
|
|||
case ID_OPTIONS_VERTEXCACHE:
|
||||
g_Config.bVertexCache = !g_Config.bVertexCache;
|
||||
break;
|
||||
|
||||
case ID_OPTIONS_SHOWFPS:
|
||||
g_Config.iShowFPSCounter = g_Config.iShowFPSCounter ? 0 : 3; // 3 = both speed and FPS
|
||||
break;
|
||||
|
||||
case ID_OPTIONS_TEXTUREFILTERING_AUTO: setTexFiltering(TEX_FILTER_AUTO); break;
|
||||
case ID_OPTIONS_NEARESTFILTERING: setTexFiltering(TEX_FILTER_FORCE_NEAREST); break;
|
||||
case ID_OPTIONS_LINEARFILTERING: setTexFiltering(TEX_FILTER_FORCE_LINEAR); break;
|
||||
|
@ -925,7 +920,7 @@ namespace MainWindow {
|
|||
break;
|
||||
|
||||
case ID_HELP_BUYGOLD:
|
||||
ShellExecute(NULL, L"open", L"https://central.ppsspp.org/buygold", NULL, NULL, SW_SHOWNORMAL);
|
||||
ShellExecute(NULL, L"open", L"https://www.ppsspp.org/buygold", NULL, NULL, SW_SHOWNORMAL);
|
||||
break;
|
||||
|
||||
case ID_HELP_OPENFORUM:
|
||||
|
@ -942,7 +937,7 @@ namespace MainWindow {
|
|||
|
||||
case ID_HELP_ABOUT:
|
||||
DialogManager::EnableAll(FALSE);
|
||||
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
|
||||
DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)AboutDlgProc);
|
||||
DialogManager::EnableAll(TRUE);
|
||||
break;
|
||||
|
||||
|
@ -984,7 +979,6 @@ namespace MainWindow {
|
|||
CHECKITEM(ID_OPTIONS_HARDWARETRANSFORM, g_Config.bHardwareTransform);
|
||||
CHECKITEM(ID_DEBUG_BREAKONLOAD, !g_Config.bAutoRun);
|
||||
CHECKITEM(ID_OPTIONS_VERTEXCACHE, g_Config.bVertexCache);
|
||||
CHECKITEM(ID_OPTIONS_SHOWFPS, g_Config.iShowFPSCounter);
|
||||
CHECKITEM(ID_OPTIONS_FRAMESKIP_AUTO, g_Config.bAutoFrameSkip);
|
||||
CHECKITEM(ID_OPTIONS_FRAMESKIP, g_Config.iFrameSkip != FRAMESKIP_OFF);
|
||||
CHECKITEM(ID_OPTIONS_FRAMESKIPTYPE_COUNT, g_Config.iFrameSkipType == FRAMESKIPTYPE_COUNT);
|
||||
|
@ -1274,24 +1268,31 @@ namespace MainWindow {
|
|||
}
|
||||
|
||||
// Message handler for about box.
|
||||
LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
LRESULT CALLBACK AboutDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
switch (message) {
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
W32Util::CenterWindow(hDlg);
|
||||
HWND versionBox = GetDlgItem(hDlg, IDC_VERSION);
|
||||
std::string windowText = System_GetPropertyBool(SYSPROP_APP_GOLD) ? "PPSSPP Gold " : "PPSSPP ";
|
||||
windowText.append(PPSSPP_GIT_VERSION);
|
||||
SetWindowText(versionBox, ConvertUTF8ToWString(windowText).c_str());
|
||||
}
|
||||
return TRUE;
|
||||
|
||||
case WM_COMMAND:
|
||||
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
|
||||
EndDialog(hDlg, LOWORD(wParam));
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
W32Util::CenterWindow(hDlg);
|
||||
HWND versionBox = GetDlgItem(hDlg, IDC_VERSION);
|
||||
std::string windowText = System_GetPropertyBool(SYSPROP_APP_GOLD) ? "PPSSPP Gold " : "PPSSPP ";
|
||||
windowText.append(PPSSPP_GIT_VERSION);
|
||||
SetWindowText(versionBox, ConvertUTF8ToWString(windowText).c_str());
|
||||
DarkModeInitDialog(hDlg);
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
{
|
||||
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) {
|
||||
EndDialog(hDlg, LOWORD(wParam));
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
default:
|
||||
return DarkModeDlgProc(hDlg, message, wParam, lParam);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -87,6 +87,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{999C12EA
|
|||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libzstd", "..\ext\libzstd.vcxproj", "{8BFD8150-94D5-4BF9-8A50-7BD9929A0850}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cpu_features", "..\ext\cpu_features.vcxproj", "{C249F016-7F82-45CF-BB6E-0642A988C4D3}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM = Debug|ARM
|
||||
|
@ -357,6 +359,22 @@ Global
|
|||
{8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|Win32.Build.0 = Release|Win32
|
||||
{8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|x64.ActiveCfg = Release|x64
|
||||
{8BFD8150-94D5-4BF9-8A50-7BD9929A0850}.Release|x64.Build.0 = Release|x64
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Debug|x64.Build.0 = Debug|x64
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|ARM.Build.0 = Release|ARM
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|Win32.Build.0 = Release|Win32
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|x64.ActiveCfg = Release|x64
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -372,6 +390,7 @@ Global
|
|||
{B7DED405-40A2-48F8-9382-538F10D442F1} = {999C12EA-A74F-4868-84F7-64C258043C49}
|
||||
{D8A71225-178B-424E-96C1-CC3BE2C1B047} = {39FCACF8-10D9-4D8D-97AA-7507436AD932}
|
||||
{8BFD8150-94D5-4BF9-8A50-7BD9929A0850} = {39FCACF8-10D9-4D8D-97AA-7507436AD932}
|
||||
{C249F016-7F82-45CF-BB6E-0642A988C4D3} = {39FCACF8-10D9-4D8D-97AA-7507436AD932}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {2FD47774-A031-48F4-B645-A49A3140A29B}
|
||||
|
|
|
@ -248,7 +248,7 @@
|
|||
<AdditionalOptions>$(EXTERNAL_COMPILE_OPTIONS)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>../ffmpeg/Windows/x86/lib</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
@ -287,7 +287,7 @@
|
|||
<AdditionalOptions>$(EXTERNAL_COMPILE_OPTIONS)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>../ffmpeg/Windows/x86_64/lib</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(OutDir)$(ProjectName).pdb</ProgramDatabaseFile>
|
||||
|
@ -322,7 +322,7 @@
|
|||
<AdditionalOptions>$(EXTERNAL_COMPILE_OPTIONS)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>../ffmpeg/Windows/aarch64/lib</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(OutDir)$(ProjectName).pdb</ProgramDatabaseFile>
|
||||
|
@ -355,7 +355,7 @@
|
|||
<AdditionalOptions>$(EXTERNAL_COMPILE_OPTIONS)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>../ffmpeg/Windows/arm/lib</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ProgramDatabaseFile>$(OutDir)$(ProjectName).pdb</ProgramDatabaseFile>
|
||||
|
@ -392,7 +392,7 @@
|
|||
<AdditionalOptions>$(EXTERNAL_COMPILE_OPTIONS)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>../ffmpeg/Windows/x86/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
|
@ -440,7 +440,7 @@
|
|||
<AdditionalOptions>$(EXTERNAL_COMPILE_OPTIONS)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>../ffmpeg/Windows/x86_64/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
@ -482,7 +482,7 @@
|
|||
<AdditionalOptions>$(EXTERNAL_COMPILE_OPTIONS)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>../ffmpeg/Windows/aarch64/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
@ -522,7 +522,7 @@
|
|||
<AdditionalOptions>$(EXTERNAL_COMPILE_OPTIONS)</AdditionalOptions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>uxtheme.lib;mf.lib;mfplat.lib;mfreadwrite.lib;mfuuid.lib;shlwapi.lib;Winmm.lib;Ws2_32.lib;dsound.lib;comctl32.lib;d3d9.lib;dxguid.lib;avcodec.lib;avformat.lib;avutil.lib;swresample.lib;swscale.lib;oleaut32.lib;comdlg32.lib;shell32.lib;user32.lib;gdi32.lib;advapi32.lib;ole32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>../ffmpeg/Windows/arm/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
|
@ -917,6 +917,7 @@
|
|||
<ClCompile Include="TouchInputHandler.cpp" />
|
||||
<ClCompile Include="GPU\WindowsVulkanContext.cpp" />
|
||||
<ClCompile Include="W32Util\ContextMenu.cpp" />
|
||||
<ClCompile Include="W32Util\DarkMode.cpp" />
|
||||
<ClCompile Include="W32Util\DialogManager.cpp" />
|
||||
<ClCompile Include="W32Util\Misc.cpp">
|
||||
<ObjectFileName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(IntDir)%(Filename)2.obj</ObjectFileName>
|
||||
|
@ -939,6 +940,7 @@
|
|||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="W32Util\UAHMenuBar.cpp" />
|
||||
<ClCompile Include="WASAPIStream.cpp" />
|
||||
<ClCompile Include="WindowsAudio.cpp" />
|
||||
<ClCompile Include="WindowsHost.cpp" />
|
||||
|
@ -1484,7 +1486,9 @@
|
|||
<ClInclude Include="TouchInputHandler.h" />
|
||||
<ClInclude Include="GPU\WindowsVulkanContext.h" />
|
||||
<ClInclude Include="W32Util\ContextMenu.h" />
|
||||
<ClInclude Include="W32Util\DarkMode.h" />
|
||||
<ClInclude Include="W32Util\DialogManager.h" />
|
||||
<ClInclude Include="W32Util\IatHook.h" />
|
||||
<ClInclude Include="W32Util\Misc.h" />
|
||||
<ClInclude Include="W32Util\ShellUtil.h" />
|
||||
<ClInclude Include="W32Util\TabControl.h" />
|
||||
|
@ -1492,6 +1496,7 @@
|
|||
<ClInclude Include="MainWindow.h" />
|
||||
<ClInclude Include="DSoundStream.h" />
|
||||
<ClInclude Include="GPU\WindowsGLContext.h" />
|
||||
<ClInclude Include="W32Util\UAHMenuBar.h" />
|
||||
<ClInclude Include="WASAPIStream.h" />
|
||||
<ClInclude Include="WindowsAudio.h" />
|
||||
<ClInclude Include="WindowsHost.h" />
|
||||
|
|
|
@ -59,6 +59,9 @@
|
|||
<Filter Include="Build\CMake">
|
||||
<UniqueIdentifier>{8f39c005-9738-41c5-a8d8-cfc05bf178e8}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Windows\Darkmode">
|
||||
<UniqueIdentifier>{e6f1a7f6-807b-484e-9595-bdb58ecaa2ae}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Debugger\CtrlDisAsmView.cpp">
|
||||
|
@ -271,6 +274,12 @@
|
|||
<ClCompile Include="..\libretro\LibretroGLCoreContext.cpp">
|
||||
<Filter>Other Platforms\libretro</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="W32Util\DarkMode.cpp">
|
||||
<Filter>Windows\W32Util</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="W32Util\UAHMenuBar.cpp">
|
||||
<Filter>Windows\W32Util</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Debugger\CtrlDisAsmView.h">
|
||||
|
@ -553,6 +562,15 @@
|
|||
<ClInclude Include="..\ios\iCade\iCadeReaderView.h">
|
||||
<Filter>Other Platforms\iOS\iCade</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="W32Util\DarkMode.h">
|
||||
<Filter>Windows\W32Util</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="W32Util\IatHook.h">
|
||||
<Filter>Windows\W32Util</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="W32Util\UAHMenuBar.h">
|
||||
<Filter>Windows\W32Util</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="icon1.ico">
|
||||
|
@ -820,4 +838,4 @@
|
|||
<Filter>Other Platforms\SDL</Filter>
|
||||
</Text>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
229
Windows/W32Util/DarkMode.cpp
Normal file
229
Windows/W32Util/DarkMode.cpp
Normal file
|
@ -0,0 +1,229 @@
|
|||
#include "IatHook.h"
|
||||
#include "DarkMode.h"
|
||||
|
||||
fnSetWindowCompositionAttribute _SetWindowCompositionAttribute = nullptr;
|
||||
fnShouldAppsUseDarkMode _ShouldAppsUseDarkMode = nullptr;
|
||||
fnAllowDarkModeForWindow _AllowDarkModeForWindow = nullptr;
|
||||
fnAllowDarkModeForApp _AllowDarkModeForApp = nullptr;
|
||||
fnFlushMenuThemes _FlushMenuThemes = nullptr;
|
||||
fnRefreshImmersiveColorPolicyState _RefreshImmersiveColorPolicyState = nullptr;
|
||||
fnIsDarkModeAllowedForWindow _IsDarkModeAllowedForWindow = nullptr;
|
||||
fnGetIsImmersiveColorUsingHighContrast _GetIsImmersiveColorUsingHighContrast = nullptr;
|
||||
fnOpenNcThemeData _OpenNcThemeData = nullptr;
|
||||
// 1903 18362
|
||||
fnShouldSystemUseDarkMode _ShouldSystemUseDarkMode = nullptr;
|
||||
fnSetPreferredAppMode _SetPreferredAppMode = nullptr;
|
||||
fnSetWindowTheme _SetWindowTheme = nullptr;
|
||||
|
||||
bool g_darkModeSupported = false;
|
||||
bool g_darkModeEnabled = false;
|
||||
DWORD g_buildNumber = 0;
|
||||
|
||||
bool AllowDarkModeForWindow(HWND hWnd, bool allow)
|
||||
{
|
||||
if (g_darkModeSupported)
|
||||
return _AllowDarkModeForWindow(hWnd, allow);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsHighContrast()
|
||||
{
|
||||
HIGHCONTRASTW highContrast = { sizeof(highContrast) };
|
||||
if (SystemParametersInfoW(SPI_GETHIGHCONTRAST, sizeof(highContrast), &highContrast, FALSE))
|
||||
return highContrast.dwFlags & HCF_HIGHCONTRASTON;
|
||||
return false;
|
||||
}
|
||||
|
||||
void RefreshTitleBarThemeColor(HWND hWnd)
|
||||
{
|
||||
BOOL dark = FALSE;
|
||||
if (_IsDarkModeAllowedForWindow(hWnd) &&
|
||||
_ShouldAppsUseDarkMode() &&
|
||||
!IsHighContrast())
|
||||
{
|
||||
dark = TRUE;
|
||||
}
|
||||
if (g_buildNumber < 18362)
|
||||
SetPropW(hWnd, L"UseImmersiveDarkModeColors", reinterpret_cast<HANDLE>(static_cast<INT_PTR>(dark)));
|
||||
else if (_SetWindowCompositionAttribute)
|
||||
{
|
||||
WINDOWCOMPOSITIONATTRIBDATA data = { WCA_USEDARKMODECOLORS, &dark, sizeof(dark) };
|
||||
_SetWindowCompositionAttribute(hWnd, &data);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsColorSchemeChangeMessage(LPARAM lParam)
|
||||
{
|
||||
bool is = false;
|
||||
if (lParam && CompareStringOrdinal(reinterpret_cast<LPCWCH>(lParam), -1, L"ImmersiveColorSet", -1, TRUE) == CSTR_EQUAL)
|
||||
{
|
||||
_RefreshImmersiveColorPolicyState();
|
||||
is = true;
|
||||
}
|
||||
_GetIsImmersiveColorUsingHighContrast(IHCM_REFRESH);
|
||||
return is;
|
||||
}
|
||||
|
||||
bool IsColorSchemeChangeMessage(UINT message, LPARAM lParam)
|
||||
{
|
||||
if (message == WM_SETTINGCHANGE)
|
||||
return IsColorSchemeChangeMessage(lParam);
|
||||
return false;
|
||||
}
|
||||
|
||||
void AllowDarkModeForApp(bool allow)
|
||||
{
|
||||
if (_AllowDarkModeForApp)
|
||||
_AllowDarkModeForApp(allow);
|
||||
else if (_SetPreferredAppMode)
|
||||
_SetPreferredAppMode(allow ? AllowDark : Default);
|
||||
}
|
||||
|
||||
void FixDarkScrollBar()
|
||||
{
|
||||
// Disable this, doesn't look good.
|
||||
return;
|
||||
|
||||
HMODULE hComctl = LoadLibraryExW(L"comctl32.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
if (hComctl)
|
||||
{
|
||||
auto addr = FindDelayLoadThunkInModule(hComctl, "uxtheme.dll", 49); // OpenNcThemeData
|
||||
if (addr)
|
||||
{
|
||||
DWORD oldProtect;
|
||||
if (VirtualProtect(addr, sizeof(IMAGE_THUNK_DATA), PAGE_READWRITE, &oldProtect))
|
||||
{
|
||||
auto MyOpenThemeData = [](HWND hWnd, LPCWSTR classList) -> HTHEME {
|
||||
if (wcscmp(classList, L"ScrollBar") == 0)
|
||||
{
|
||||
hWnd = nullptr;
|
||||
classList = L"Explorer::ScrollBar";
|
||||
}
|
||||
return _OpenNcThemeData(hWnd, classList);
|
||||
};
|
||||
|
||||
addr->u1.Function = reinterpret_cast<ULONG_PTR>(static_cast<fnOpenNcThemeData>(MyOpenThemeData));
|
||||
VirtualProtect(addr, sizeof(IMAGE_THUNK_DATA), oldProtect, &oldProtect);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DarkModeInitDialog(HWND hDlg) {
|
||||
if (g_darkModeSupported) {
|
||||
_SetWindowTheme(GetDlgItem(hDlg, IDOK), L"Explorer", nullptr);
|
||||
SendMessageW(hDlg, WM_THEMECHANGED, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
LRESULT DarkModeDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
constexpr COLORREF darkBkColor = 0x383838;
|
||||
constexpr COLORREF darkTextColor = 0xFFFFFF;
|
||||
static HBRUSH hbrBkgnd = nullptr;
|
||||
|
||||
switch (message) {
|
||||
case WM_CTLCOLORDLG:
|
||||
case WM_CTLCOLORSTATIC:
|
||||
{
|
||||
if (g_darkModeSupported && g_darkModeEnabled)
|
||||
{
|
||||
HDC hdc = reinterpret_cast<HDC>(wParam);
|
||||
SetTextColor(hdc, darkTextColor);
|
||||
SetBkColor(hdc, darkBkColor);
|
||||
if (!hbrBkgnd)
|
||||
hbrBkgnd = CreateSolidBrush(darkBkColor);
|
||||
return reinterpret_cast<INT_PTR>(hbrBkgnd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_SETTINGCHANGE:
|
||||
{
|
||||
if (g_darkModeSupported && IsColorSchemeChangeMessage(lParam))
|
||||
SendMessageW(hDlg, WM_THEMECHANGED, 0, 0);
|
||||
break;
|
||||
}
|
||||
case WM_THEMECHANGED:
|
||||
{
|
||||
if (g_darkModeSupported)
|
||||
{
|
||||
_AllowDarkModeForWindow(hDlg, g_darkModeEnabled);
|
||||
RefreshTitleBarThemeColor(hDlg);
|
||||
|
||||
HWND hButton = GetDlgItem(hDlg, IDOK);
|
||||
_AllowDarkModeForWindow(hButton, g_darkModeEnabled);
|
||||
SendMessageW(hButton, WM_THEMECHANGED, 0, 0);
|
||||
|
||||
UpdateWindow(hDlg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool IsDarkModeEnabled() {
|
||||
return g_darkModeEnabled;
|
||||
}
|
||||
|
||||
constexpr bool CheckBuildNumber(DWORD buildNumber)
|
||||
{
|
||||
// TODO: This is BS.
|
||||
|
||||
return (buildNumber == 17763 || // 1809
|
||||
buildNumber == 18362 || // 1903
|
||||
buildNumber == 18363 || // 1909
|
||||
buildNumber >= 19041); // Windows 11
|
||||
}
|
||||
|
||||
void InitDarkMode()
|
||||
{
|
||||
auto RtlGetNtVersionNumbers = reinterpret_cast<fnRtlGetNtVersionNumbers>(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlGetNtVersionNumbers"));
|
||||
if (RtlGetNtVersionNumbers)
|
||||
{
|
||||
DWORD major, minor;
|
||||
RtlGetNtVersionNumbers(&major, &minor, &g_buildNumber);
|
||||
g_buildNumber &= ~0xF0000000;
|
||||
if (major == 10 && minor == 0 && CheckBuildNumber(g_buildNumber))
|
||||
{
|
||||
HMODULE hUxtheme = LoadLibraryExW(L"uxtheme.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
if (hUxtheme)
|
||||
{
|
||||
_OpenNcThemeData = reinterpret_cast<fnOpenNcThemeData>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(49)));
|
||||
_RefreshImmersiveColorPolicyState = reinterpret_cast<fnRefreshImmersiveColorPolicyState>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(104)));
|
||||
_GetIsImmersiveColorUsingHighContrast = reinterpret_cast<fnGetIsImmersiveColorUsingHighContrast>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(106)));
|
||||
_ShouldAppsUseDarkMode = reinterpret_cast<fnShouldAppsUseDarkMode>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(132)));
|
||||
_AllowDarkModeForWindow = reinterpret_cast<fnAllowDarkModeForWindow>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(133)));
|
||||
|
||||
auto ord135 = GetProcAddress(hUxtheme, MAKEINTRESOURCEA(135));
|
||||
if (g_buildNumber < 18362)
|
||||
_AllowDarkModeForApp = reinterpret_cast<fnAllowDarkModeForApp>(ord135);
|
||||
else
|
||||
_SetPreferredAppMode = reinterpret_cast<fnSetPreferredAppMode>(ord135);
|
||||
|
||||
//_FlushMenuThemes = reinterpret_cast<fnFlushMenuThemes>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(136)));
|
||||
_IsDarkModeAllowedForWindow = reinterpret_cast<fnIsDarkModeAllowedForWindow>(GetProcAddress(hUxtheme, MAKEINTRESOURCEA(137)));
|
||||
|
||||
_SetWindowCompositionAttribute = reinterpret_cast<fnSetWindowCompositionAttribute>(GetProcAddress(GetModuleHandleW(L"user32.dll"), "SetWindowCompositionAttribute"));
|
||||
_SetWindowTheme = reinterpret_cast<fnSetWindowTheme>(GetProcAddress(hUxtheme, "SetWindowTheme"));
|
||||
|
||||
if (_OpenNcThemeData &&
|
||||
_RefreshImmersiveColorPolicyState &&
|
||||
_ShouldAppsUseDarkMode &&
|
||||
_AllowDarkModeForWindow &&
|
||||
(_AllowDarkModeForApp || _SetPreferredAppMode) &&
|
||||
//_FlushMenuThemes &&
|
||||
_IsDarkModeAllowedForWindow)
|
||||
{
|
||||
g_darkModeSupported = true;
|
||||
|
||||
AllowDarkModeForApp(true);
|
||||
_RefreshImmersiveColorPolicyState();
|
||||
|
||||
g_darkModeEnabled = _ShouldAppsUseDarkMode() && !IsHighContrast();
|
||||
|
||||
FixDarkScrollBar();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
110
Windows/W32Util/DarkMode.h
Normal file
110
Windows/W32Util/DarkMode.h
Normal file
|
@ -0,0 +1,110 @@
|
|||
#pragma once
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <Windows.h>
|
||||
#include <CommCtrl.h>
|
||||
#include <Uxtheme.h>
|
||||
#include <WindowsX.h>
|
||||
#include <Vssym32.h>
|
||||
|
||||
#include "IatHook.h"
|
||||
|
||||
enum IMMERSIVE_HC_CACHE_MODE
|
||||
{
|
||||
IHCM_USE_CACHED_VALUE,
|
||||
IHCM_REFRESH
|
||||
};
|
||||
|
||||
// 1903 18362
|
||||
enum PreferredAppMode
|
||||
{
|
||||
Default,
|
||||
AllowDark,
|
||||
ForceDark,
|
||||
ForceLight,
|
||||
Max
|
||||
};
|
||||
|
||||
enum WINDOWCOMPOSITIONATTRIB
|
||||
{
|
||||
WCA_UNDEFINED = 0,
|
||||
WCA_NCRENDERING_ENABLED = 1,
|
||||
WCA_NCRENDERING_POLICY = 2,
|
||||
WCA_TRANSITIONS_FORCEDISABLED = 3,
|
||||
WCA_ALLOW_NCPAINT = 4,
|
||||
WCA_CAPTION_BUTTON_BOUNDS = 5,
|
||||
WCA_NONCLIENT_RTL_LAYOUT = 6,
|
||||
WCA_FORCE_ICONIC_REPRESENTATION = 7,
|
||||
WCA_EXTENDED_FRAME_BOUNDS = 8,
|
||||
WCA_HAS_ICONIC_BITMAP = 9,
|
||||
WCA_THEME_ATTRIBUTES = 10,
|
||||
WCA_NCRENDERING_EXILED = 11,
|
||||
WCA_NCADORNMENTINFO = 12,
|
||||
WCA_EXCLUDED_FROM_LIVEPREVIEW = 13,
|
||||
WCA_VIDEO_OVERLAY_ACTIVE = 14,
|
||||
WCA_FORCE_ACTIVEWINDOW_APPEARANCE = 15,
|
||||
WCA_DISALLOW_PEEK = 16,
|
||||
WCA_CLOAK = 17,
|
||||
WCA_CLOAKED = 18,
|
||||
WCA_ACCENT_POLICY = 19,
|
||||
WCA_FREEZE_REPRESENTATION = 20,
|
||||
WCA_EVER_UNCLOAKED = 21,
|
||||
WCA_VISUAL_OWNER = 22,
|
||||
WCA_HOLOGRAPHIC = 23,
|
||||
WCA_EXCLUDED_FROM_DDA = 24,
|
||||
WCA_PASSIVEUPDATEMODE = 25,
|
||||
WCA_USEDARKMODECOLORS = 26,
|
||||
WCA_LAST = 27
|
||||
};
|
||||
|
||||
struct WINDOWCOMPOSITIONATTRIBDATA
|
||||
{
|
||||
WINDOWCOMPOSITIONATTRIB Attrib;
|
||||
PVOID pvData;
|
||||
SIZE_T cbData;
|
||||
};
|
||||
|
||||
using fnRtlGetNtVersionNumbers = void (WINAPI *)(LPDWORD major, LPDWORD minor, LPDWORD build);
|
||||
using fnSetWindowCompositionAttribute = BOOL (WINAPI *)(HWND hWnd, WINDOWCOMPOSITIONATTRIBDATA*);
|
||||
// 1809 17763
|
||||
using fnShouldAppsUseDarkMode = bool (WINAPI *)(); // ordinal 132
|
||||
using fnAllowDarkModeForWindow = bool (WINAPI *)(HWND hWnd, bool allow); // ordinal 133
|
||||
using fnAllowDarkModeForApp = bool (WINAPI *)(bool allow); // ordinal 135, in 1809
|
||||
using fnFlushMenuThemes = void (WINAPI *)(); // ordinal 136
|
||||
using fnRefreshImmersiveColorPolicyState = void (WINAPI *)(); // ordinal 104
|
||||
using fnIsDarkModeAllowedForWindow = bool (WINAPI *)(HWND hWnd); // ordinal 137
|
||||
using fnGetIsImmersiveColorUsingHighContrast = bool (WINAPI *)(IMMERSIVE_HC_CACHE_MODE mode); // ordinal 106
|
||||
using fnOpenNcThemeData = HTHEME(WINAPI *)(HWND hWnd, LPCWSTR pszClassList); // ordinal 49
|
||||
// 1903 18362
|
||||
using fnShouldSystemUseDarkMode = bool (WINAPI *)(); // ordinal 138
|
||||
using fnSetPreferredAppMode = PreferredAppMode (WINAPI *)(PreferredAppMode appMode); // ordinal 135, in 1903
|
||||
using fnIsDarkModeAllowedForApp = bool (WINAPI *)(); // ordinal 139
|
||||
using fnSetWindowTheme = void (WINAPI*)(HWND, LPCWSTR, LPCWSTR);
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
extern fnSetWindowCompositionAttribute _SetWindowCompositionAttribute;
|
||||
extern fnShouldAppsUseDarkMode _ShouldAppsUseDarkMode;
|
||||
extern fnAllowDarkModeForWindow _AllowDarkModeForWindow;
|
||||
extern fnAllowDarkModeForApp _AllowDarkModeForApp;
|
||||
extern fnFlushMenuThemes _FlushMenuThemes;
|
||||
extern fnRefreshImmersiveColorPolicyState _RefreshImmersiveColorPolicyState;
|
||||
extern fnIsDarkModeAllowedForWindow _IsDarkModeAllowedForWindow;
|
||||
extern fnGetIsImmersiveColorUsingHighContrast _GetIsImmersiveColorUsingHighContrast;
|
||||
extern fnOpenNcThemeData _OpenNcThemeData;
|
||||
// 1903 18362
|
||||
extern fnShouldSystemUseDarkMode _ShouldSystemUseDarkMode;
|
||||
extern fnSetPreferredAppMode _SetPreferredAppMode;
|
||||
extern fnSetWindowTheme _SetWindowTheme;
|
||||
|
||||
extern bool g_darkModeSupported;
|
||||
extern bool g_darkModeEnabled;
|
||||
|
||||
void InitDarkMode();
|
||||
bool AllowDarkModeForWindow(HWND hWnd, bool allow);
|
||||
void RefreshTitleBarThemeColor(HWND hWnd);
|
||||
bool IsColorSchemeChangeMessage(LPARAM lParam);
|
||||
bool IsDarkModeEnabled();
|
||||
|
||||
void DarkModeInitDialog(HWND hDlg);
|
||||
LRESULT DarkModeDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
91
Windows/W32Util/IatHook.h
Normal file
91
Windows/W32Util/IatHook.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
// This file contains code from
|
||||
// https://github.com/stevemk14ebr/PolyHook_2_0/blob/master/sources/IatHook.cpp
|
||||
// which is licensed under the MIT License.
|
||||
// See PolyHook_2_0-LICENSE for more information.
|
||||
|
||||
#pragma once
|
||||
|
||||
template <typename T, typename T1, typename T2>
|
||||
constexpr T RVA2VA(T1 base, T2 rva)
|
||||
{
|
||||
return reinterpret_cast<T>(reinterpret_cast<ULONG_PTR>(base) + rva);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr T DataDirectoryFromModuleBase(void *moduleBase, size_t entryID)
|
||||
{
|
||||
auto dosHdr = reinterpret_cast<PIMAGE_DOS_HEADER>(moduleBase);
|
||||
auto ntHdr = RVA2VA<PIMAGE_NT_HEADERS>(moduleBase, dosHdr->e_lfanew);
|
||||
auto dataDir = ntHdr->OptionalHeader.DataDirectory;
|
||||
return RVA2VA<T>(moduleBase, dataDir[entryID].VirtualAddress);
|
||||
}
|
||||
|
||||
inline PIMAGE_THUNK_DATA FindAddressByName(void *moduleBase, PIMAGE_THUNK_DATA impName, PIMAGE_THUNK_DATA impAddr, const char *funcName)
|
||||
{
|
||||
for (; impName->u1.Ordinal; ++impName, ++impAddr)
|
||||
{
|
||||
if (IMAGE_SNAP_BY_ORDINAL(impName->u1.Ordinal))
|
||||
continue;
|
||||
|
||||
auto import = RVA2VA<PIMAGE_IMPORT_BY_NAME>(moduleBase, impName->u1.AddressOfData);
|
||||
if (strcmp(import->Name, funcName) != 0)
|
||||
continue;
|
||||
return impAddr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline PIMAGE_THUNK_DATA FindAddressByOrdinal(void *moduleBase, PIMAGE_THUNK_DATA impName, PIMAGE_THUNK_DATA impAddr, uint16_t ordinal)
|
||||
{
|
||||
for (; impName->u1.Ordinal; ++impName, ++impAddr)
|
||||
{
|
||||
if (IMAGE_SNAP_BY_ORDINAL(impName->u1.Ordinal) && IMAGE_ORDINAL(impName->u1.Ordinal) == ordinal)
|
||||
return impAddr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline PIMAGE_THUNK_DATA FindIatThunkInModule(void *moduleBase, const char *dllName, const char *funcName)
|
||||
{
|
||||
auto imports = DataDirectoryFromModuleBase<PIMAGE_IMPORT_DESCRIPTOR>(moduleBase, IMAGE_DIRECTORY_ENTRY_IMPORT);
|
||||
for (; imports->Name; ++imports)
|
||||
{
|
||||
if (_stricmp(RVA2VA<LPCSTR>(moduleBase, imports->Name), dllName) != 0)
|
||||
continue;
|
||||
|
||||
auto origThunk = RVA2VA<PIMAGE_THUNK_DATA>(moduleBase, imports->OriginalFirstThunk);
|
||||
auto thunk = RVA2VA<PIMAGE_THUNK_DATA>(moduleBase, imports->FirstThunk);
|
||||
return FindAddressByName(moduleBase, origThunk, thunk, funcName);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline PIMAGE_THUNK_DATA FindDelayLoadThunkInModule(void *moduleBase, const char *dllName, const char *funcName)
|
||||
{
|
||||
auto imports = DataDirectoryFromModuleBase<PIMAGE_DELAYLOAD_DESCRIPTOR>(moduleBase, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
|
||||
for (; imports->DllNameRVA; ++imports)
|
||||
{
|
||||
if (_stricmp(RVA2VA<LPCSTR>(moduleBase, imports->DllNameRVA), dllName) != 0)
|
||||
continue;
|
||||
|
||||
auto impName = RVA2VA<PIMAGE_THUNK_DATA>(moduleBase, imports->ImportNameTableRVA);
|
||||
auto impAddr = RVA2VA<PIMAGE_THUNK_DATA>(moduleBase, imports->ImportAddressTableRVA);
|
||||
return FindAddressByName(moduleBase, impName, impAddr, funcName);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
inline PIMAGE_THUNK_DATA FindDelayLoadThunkInModule(void *moduleBase, const char *dllName, uint16_t ordinal)
|
||||
{
|
||||
auto imports = DataDirectoryFromModuleBase<PIMAGE_DELAYLOAD_DESCRIPTOR>(moduleBase, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT);
|
||||
for (; imports->DllNameRVA; ++imports)
|
||||
{
|
||||
if (_stricmp(RVA2VA<LPCSTR>(moduleBase, imports->DllNameRVA), dllName) != 0)
|
||||
continue;
|
||||
|
||||
auto impName = RVA2VA<PIMAGE_THUNK_DATA>(moduleBase, imports->ImportNameTableRVA);
|
||||
auto impAddr = RVA2VA<PIMAGE_THUNK_DATA>(moduleBase, imports->ImportAddressTableRVA);
|
||||
return FindAddressByOrdinal(moduleBase, impName, impAddr, ordinal);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
115
Windows/W32Util/UAHMenuBar.cpp
Normal file
115
Windows/W32Util/UAHMenuBar.cpp
Normal file
|
@ -0,0 +1,115 @@
|
|||
#include "Common/CommonWindows.h"
|
||||
|
||||
#include <Uxtheme.h>
|
||||
#include <vsstyle.h>
|
||||
|
||||
#include "Windows/W32Util/UAHMenuBar.h"
|
||||
#include "Windows/W32Util/DarkMode.h"
|
||||
|
||||
static HTHEME g_menuTheme = nullptr;
|
||||
|
||||
// processes messages related to UAH / custom menubar drawing.
|
||||
// return true if handled, false to continue with normal processing in your wndproc
|
||||
bool UAHDarkModeWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT *lr)
|
||||
{
|
||||
if (!IsDarkModeEnabled() && message != WM_THEMECHANGED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (message)
|
||||
{
|
||||
case WM_UAHDRAWMENU:
|
||||
{
|
||||
UAHMENU *pUDM = (UAHMENU *)lParam;
|
||||
RECT rc = { 0 };
|
||||
|
||||
// get the menubar rect
|
||||
{
|
||||
MENUBARINFO mbi = { sizeof(mbi) };
|
||||
GetMenuBarInfo(hWnd, OBJID_MENU, 0, &mbi);
|
||||
|
||||
RECT rcWindow;
|
||||
GetWindowRect(hWnd, &rcWindow);
|
||||
|
||||
// the rcBar is offset by the window rect
|
||||
rc = mbi.rcBar;
|
||||
OffsetRect(&rc, -rcWindow.left, -rcWindow.top);
|
||||
|
||||
rc.top -= 1;
|
||||
}
|
||||
|
||||
if (!g_menuTheme) {
|
||||
g_menuTheme = OpenThemeData(hWnd, L"Menu");
|
||||
}
|
||||
|
||||
DrawThemeBackground(g_menuTheme, pUDM->hdc, MENU_POPUPITEM, MPI_NORMAL, &rc, nullptr);
|
||||
return true;
|
||||
}
|
||||
case WM_UAHDRAWMENUITEM:
|
||||
{
|
||||
UAHDRAWMENUITEM *pUDMI = (UAHDRAWMENUITEM *)lParam;
|
||||
|
||||
// get the menu item string
|
||||
wchar_t menuString[256] = { 0 };
|
||||
MENUITEMINFO mii = { sizeof(mii), MIIM_STRING };
|
||||
{
|
||||
mii.dwTypeData = menuString;
|
||||
mii.cch = (sizeof(menuString) / 2) - 1;
|
||||
|
||||
GetMenuItemInfo(pUDMI->um.hmenu, pUDMI->umi.iPosition, TRUE, &mii);
|
||||
}
|
||||
|
||||
// get the item state for drawing
|
||||
|
||||
DWORD dwFlags = DT_CENTER | DT_SINGLELINE | DT_VCENTER;
|
||||
|
||||
int iTextStateID = 0;
|
||||
int iBackgroundStateID = 0;
|
||||
{
|
||||
if ((pUDMI->dis.itemState & ODS_INACTIVE) | (pUDMI->dis.itemState & ODS_DEFAULT)) {
|
||||
// normal display
|
||||
iTextStateID = MPI_NORMAL;
|
||||
iBackgroundStateID = MPI_NORMAL;
|
||||
}
|
||||
if (pUDMI->dis.itemState & ODS_HOTLIGHT) {
|
||||
// hot tracking
|
||||
iTextStateID = MPI_HOT;
|
||||
iBackgroundStateID = MPI_HOT;
|
||||
}
|
||||
if (pUDMI->dis.itemState & ODS_SELECTED) {
|
||||
// clicked -- MENU_POPUPITEM has no state for this, though MENU_BARITEM does
|
||||
iTextStateID = MPI_HOT;
|
||||
iBackgroundStateID = MPI_HOT;
|
||||
}
|
||||
if ((pUDMI->dis.itemState & ODS_GRAYED) || (pUDMI->dis.itemState & ODS_DISABLED)) {
|
||||
// disabled / grey text
|
||||
iTextStateID = MPI_DISABLED;
|
||||
iBackgroundStateID = MPI_DISABLED;
|
||||
}
|
||||
if (pUDMI->dis.itemState & ODS_NOACCEL) {
|
||||
dwFlags |= DT_HIDEPREFIX;
|
||||
}
|
||||
}
|
||||
|
||||
if (!g_menuTheme) {
|
||||
g_menuTheme = OpenThemeData(hWnd, L"Menu");
|
||||
}
|
||||
|
||||
DrawThemeBackground(g_menuTheme, pUDMI->um.hdc, MENU_POPUPITEM, iBackgroundStateID, &pUDMI->dis.rcItem, nullptr);
|
||||
DrawThemeText(g_menuTheme, pUDMI->um.hdc, MENU_POPUPITEM, iTextStateID, menuString, mii.cch, dwFlags, 0, &pUDMI->dis.rcItem);
|
||||
|
||||
return true;
|
||||
}
|
||||
case WM_THEMECHANGED:
|
||||
{
|
||||
if (g_menuTheme) {
|
||||
CloseThemeData(g_menuTheme);
|
||||
g_menuTheme = nullptr;
|
||||
}
|
||||
// continue processing in main wndproc
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
74
Windows/W32Util/UAHMenuBar.h
Normal file
74
Windows/W32Util/UAHMenuBar.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
#pragma once
|
||||
|
||||
// MIT license, see LICENSE
|
||||
// Copyright(c) 2021 adzm / Adam D. Walling
|
||||
|
||||
// processes messages related to UAH / custom menubar drawing.
|
||||
// return true if handled, false to continue with normal processing in your wndproc
|
||||
bool UAHDarkModeWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LRESULT* lr);
|
||||
|
||||
// window messages related to menu bar drawing
|
||||
#define WM_UAHDESTROYWINDOW 0x0090 // handled by DefWindowProc
|
||||
#define WM_UAHDRAWMENU 0x0091 // lParam is UAHMENU
|
||||
#define WM_UAHDRAWMENUITEM 0x0092 // lParam is UAHDRAWMENUITEM
|
||||
#define WM_UAHINITMENU 0x0093 // handled by DefWindowProc
|
||||
#define WM_UAHMEASUREMENUITEM 0x0094 // lParam is UAHMEASUREMENUITEM
|
||||
#define WM_UAHNCPAINTMENUPOPUP 0x0095 // handled by DefWindowProc
|
||||
|
||||
// describes the sizes of the menu bar or menu item
|
||||
typedef union tagUAHMENUITEMMETRICS
|
||||
{
|
||||
// cx appears to be 14 / 0xE less than rcItem's width!
|
||||
// cy 0x14 seems stable, i wonder if it is 4 less than rcItem's height which is always 24 atm
|
||||
struct {
|
||||
DWORD cx;
|
||||
DWORD cy;
|
||||
} rgsizeBar[2];
|
||||
struct {
|
||||
DWORD cx;
|
||||
DWORD cy;
|
||||
} rgsizePopup[4];
|
||||
} UAHMENUITEMMETRICS;
|
||||
|
||||
// not really used in our case but part of the other structures
|
||||
typedef struct tagUAHMENUPOPUPMETRICS
|
||||
{
|
||||
DWORD rgcx[4];
|
||||
DWORD fUpdateMaxWidths : 2; // from kernel symbols, padded to full dword
|
||||
} UAHMENUPOPUPMETRICS;
|
||||
|
||||
// hmenu is the main window menu; hdc is the context to draw in
|
||||
typedef struct tagUAHMENU
|
||||
{
|
||||
HMENU hmenu;
|
||||
HDC hdc;
|
||||
DWORD dwFlags; // no idea what these mean, in my testing it's either 0x00000a00 or sometimes 0x00000a10
|
||||
} UAHMENU;
|
||||
|
||||
// menu items are always referred to by iPosition here
|
||||
typedef struct tagUAHMENUITEM
|
||||
{
|
||||
int iPosition; // 0-based position of menu item in menubar
|
||||
UAHMENUITEMMETRICS umim;
|
||||
UAHMENUPOPUPMETRICS umpm;
|
||||
} UAHMENUITEM;
|
||||
|
||||
// the DRAWITEMSTRUCT contains the states of the menu items, as well as
|
||||
// the position index of the item in the menu, which is duplicated in
|
||||
// the UAHMENUITEM's iPosition as well
|
||||
typedef struct UAHDRAWMENUITEM
|
||||
{
|
||||
DRAWITEMSTRUCT dis; // itemID looks uninitialized
|
||||
UAHMENU um;
|
||||
UAHMENUITEM umi;
|
||||
} UAHDRAWMENUITEM;
|
||||
|
||||
// the MEASUREITEMSTRUCT is intended to be filled with the size of the item
|
||||
// height appears to be ignored, but width can be modified
|
||||
typedef struct tagUAHMEASUREMENUITEM
|
||||
{
|
||||
MEASUREITEMSTRUCT mis;
|
||||
UAHMENU um;
|
||||
UAHMENUITEM umi;
|
||||
} UAHMEASUREMENUITEM;
|
||||
|
|
@ -42,6 +42,7 @@
|
|||
#include "Common/Thread/ThreadUtil.h"
|
||||
#include "Common/Data/Encoding/Utf8.h"
|
||||
#include "Common/Net/Resolve.h"
|
||||
#include "W32Util/DarkMode.h"
|
||||
|
||||
#include "Core/Config.h"
|
||||
#include "Core/ConfigValues.h"
|
||||
|
@ -290,7 +291,7 @@ static int ScreenRefreshRateHz() {
|
|||
return 60; // default value
|
||||
} else {
|
||||
if (lpDevMode.dmFields & DM_DISPLAYFREQUENCY) {
|
||||
return lpDevMode.dmDisplayFrequency > 15 ? lpDevMode.dmDisplayFrequency : 60;
|
||||
return lpDevMode.dmDisplayFrequency > 60 ? lpDevMode.dmDisplayFrequency : 60;
|
||||
} else {
|
||||
return 60;
|
||||
}
|
||||
|
@ -553,6 +554,8 @@ static void WinMainInit() {
|
|||
// FMA3 support in the 2013 CRT is broken on Vista and Windows 7 RTM (fixed in SP1). Just disable it.
|
||||
_set_FMA3_enable(0);
|
||||
#endif
|
||||
|
||||
InitDarkMode();
|
||||
}
|
||||
|
||||
static void WinMainCleanup() {
|
||||
|
|
|
@ -639,7 +639,6 @@ BEGIN
|
|||
END
|
||||
MENUITEM "Hardware Transform", ID_OPTIONS_HARDWARETRANSFORM
|
||||
MENUITEM "Vertex Cache", ID_OPTIONS_VERTEXCACHE
|
||||
MENUITEM "Show FPS Counter", ID_OPTIONS_SHOWFPS
|
||||
MENUITEM "", 0, MFT_SEPARATOR
|
||||
MENUITEM "Enable Sound", ID_EMULATION_SOUND
|
||||
MENUITEM "", 0, MFT_SEPARATOR
|
||||
|
|
|
@ -158,7 +158,6 @@
|
|||
#define ID_DEBUG_BREAKONLOAD 40039
|
||||
#define ID_DEBUG_DUMPNEXTFRAME 40040
|
||||
#define ID_OPTIONS_VERTEXCACHE 40041
|
||||
#define ID_OPTIONS_SHOWFPS 40042
|
||||
#define ID_OPTIONS_FRAMESKIP 40044
|
||||
#define IDC_MEMCHECK 40045
|
||||
#define ID_FILE_MEMSTICK 40046
|
||||
|
|
|
@ -4,6 +4,10 @@ SRC := ../..
|
|||
include $(CLEAR_VARS)
|
||||
include $(LOCAL_PATH)/Locals.mk
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
$(LOCAL_PATH)/../../ext/cpu_features/include
|
||||
LOCAL_CFLAGS += -DSTACK_LINE_READER_BUFFER_SIZE=1024 -DHAVE_DLFCN_H
|
||||
|
||||
# http://software.intel.com/en-us/articles/getting-started-on-optimizing-ndk-project-for-multiple-cpu-architectures
|
||||
|
||||
ifeq ($(TARGET_ARCH_ABI),x86)
|
||||
|
@ -119,7 +123,21 @@ EXT_FILES := \
|
|||
$(SRC)/ext/udis86/syn-intel.c \
|
||||
$(SRC)/ext/udis86/syn.c \
|
||||
$(SRC)/ext/udis86/udis86.c \
|
||||
$(SRC)/ext/xbrz/xbrz.cpp
|
||||
$(SRC)/ext/xbrz/xbrz.cpp \
|
||||
$(SRC)/ext/cpu_features/src/filesystem.c \
|
||||
$(SRC)/ext/cpu_features/src/hwcaps.c \
|
||||
$(SRC)/ext/cpu_features/src/impl_aarch64_linux_or_android.c \
|
||||
$(SRC)/ext/cpu_features/src/impl_arm_linux_or_android.c \
|
||||
$(SRC)/ext/cpu_features/src/impl_mips_linux_or_android.c \
|
||||
$(SRC)/ext/cpu_features/src/impl_ppc_linux.c \
|
||||
$(SRC)/ext/cpu_features/src/impl_riscv_linux.c \
|
||||
$(SRC)/ext/cpu_features/src/impl_s390x_linux.c \
|
||||
$(SRC)/ext/cpu_features/src/impl_x86_freebsd.c \
|
||||
$(SRC)/ext/cpu_features/src/impl_x86_linux_or_android.c \
|
||||
$(SRC)/ext/cpu_features/src/impl_x86_macos.c \
|
||||
$(SRC)/ext/cpu_features/src/impl_x86_windows.c \
|
||||
$(SRC)/ext/cpu_features/src/stack_line_reader.c \
|
||||
$(SRC)/ext/cpu_features/src/string_view.c
|
||||
|
||||
EXEC_AND_LIB_FILES := \
|
||||
$(ARCH_FILES) \
|
||||
|
|
|
@ -38,7 +38,6 @@ bool AndroidJavaEGLGraphicsContext::InitFromRenderThread(ANativeWindow *wnd, int
|
|||
|
||||
void AndroidJavaEGLGraphicsContext::ShutdownFromRenderThread() {
|
||||
INFO_LOG(G3D, "AndroidJavaEGLGraphicsContext::Shutdown");
|
||||
renderManager_->WaitUntilQueueIdle();
|
||||
renderManager_ = nullptr; // owned by draw_.
|
||||
delete draw_;
|
||||
draw_ = nullptr;
|
||||
|
|
|
@ -40,7 +40,6 @@ public:
|
|||
}
|
||||
|
||||
void StopThread() override {
|
||||
renderManager_->WaitUntilQueueIdle();
|
||||
renderManager_->StopThread();
|
||||
}
|
||||
|
||||
|
|
|
@ -335,7 +335,7 @@ static void EmuThreadFunc() {
|
|||
while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) {
|
||||
UpdateRunLoopAndroid(env);
|
||||
}
|
||||
INFO_LOG(SYSTEM, "QUIT_REQUESTED found, left loop. Setting state to STOPPED.");
|
||||
INFO_LOG(SYSTEM, "QUIT_REQUESTED found, left EmuThreadFunc loop. Setting state to STOPPED.");
|
||||
emuThreadState = (int)EmuThreadState::STOPPED;
|
||||
|
||||
NativeShutdownGraphics();
|
||||
|
@ -868,17 +868,18 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) {
|
|||
EmuThreadStop("shutdown");
|
||||
INFO_LOG(SYSTEM, "BeginAndroidShutdown");
|
||||
graphicsContext->BeginAndroidShutdown();
|
||||
// Skipping GL calls, the old context is gone.
|
||||
while (graphicsContext->ThreadFrame()) {
|
||||
INFO_LOG(SYSTEM, "graphicsContext->ThreadFrame executed to clear buffers");
|
||||
}
|
||||
INFO_LOG(SYSTEM, "Joining emuthread");
|
||||
EmuThreadJoin();
|
||||
INFO_LOG(SYSTEM, "Joined emuthread");
|
||||
|
||||
// Now, it could be that we had some frames queued up. Get through them.
|
||||
// We're on the render thread, so this is synchronous.
|
||||
do {
|
||||
INFO_LOG(SYSTEM, "Executing graphicsContext->ThreadFrame to clear buffers");
|
||||
} while (graphicsContext->ThreadFrame());
|
||||
graphicsContext->ThreadEnd();
|
||||
INFO_LOG(SYSTEM, "ThreadEnd called.");
|
||||
graphicsContext->ShutdownFromRenderThread();
|
||||
INFO_LOG(SYSTEM, "Graphics context now shut down from NativeApp_shutdown");
|
||||
|
||||
INFO_LOG(SYSTEM, "Joining emuthread");
|
||||
EmuThreadJoin();
|
||||
}
|
||||
|
||||
INFO_LOG(SYSTEM, "NativeApp.shutdown() -- begin");
|
||||
|
|
Binary file not shown.
|
@ -262,7 +262,7 @@ Random = عشوائي
|
|||
Replace textures = إستبدال الرسوم
|
||||
Reset = Reset
|
||||
Reset limited logging = Reset limited logging
|
||||
RestoreDefaultSettings = Are you sure you want to restore all settings back to their defaults?\nControl mapping settings are not changed.\n\nYou can't undo this.\nPlease restart PPSSPP for the changes to take effect.
|
||||
RestoreDefaultSettings = Restore these settings back to their defaults?\nYou can't undo this.\nPlease restart PPSSPP after restoring settings.
|
||||
RestoreGameDefaultSettings = Are you sure you want to restore the game-specific settings\nback to the PPSSPP defaults?
|
||||
Resume = Resume
|
||||
Run CPU Tests = شغل فحوص المعالج
|
||||
|
@ -530,6 +530,8 @@ Must Restart = يجب عليك إعادة تشغيل البرنامج لكي
|
|||
Native device resolution = حجم الجهاز الأساسي
|
||||
Nearest = Nearest
|
||||
No buffer = No buffer
|
||||
Show Battery % = Show Battery %
|
||||
Show Speed = Show Speed
|
||||
Skip Buffer Effects = Skip buffer effects
|
||||
None = لا شئ
|
||||
Number of Frames = Number of frames
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue