Merge branch 'master' into TemporaryHackishBranch

# Conflicts:
#	UI/GameSettingsScreen.cpp
This commit is contained in:
LunaMoo committed 2019-07-14 22:37:36 +02:00
commit 0929c0bfdf
68 files changed
+1000 -685

No files matched your search

+25 -45
View File
@@ -2,7 +2,7 @@
export USE_CCACHE=1
export NDK_CCACHE=ccache
NDK_VER=android-ndk-r16b
NDK_VER=android-ndk-r18b
download_extract() {
aria2c -x 16 $1 -o $2
@@ -18,53 +18,19 @@ download_extract_zip() {
unzip $2 2>&1 | pv > /dev/null
}
brew_install() {
brew install $1
brew outdated $1 || brew upgrade $1
}
travis_before_install() {
git submodule update --init --recursive
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
sudo apt-get update -qq
sudo apt-get install software-properties-common aria2 pv build-essential libgl1-mesa-dev libglu1-mesa-dev -qq
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
brew update
brew_install ccache
fi
}
setup_ccache_script() {
if [ ! -e "$1" ]; then
mkdir "$1"
fi
echo "#!/bin/bash" > "$1/$3"
echo "ccache $2/$3 \$*" >> "$1/$3"
chmod +x "$1/$3"
}
travis_install() {
# Ubuntu Linux + GCC 4.8
if [ "$PPSSPP_BUILD_TYPE" = "Linux" ]; then
# For libsdl2-dev.
sudo add-apt-repository ppa:zoogie/sdl2-snapshots -y
if [ "$CXX" = "g++" ]; then
sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
fi
if [ "$QT" = "TRUE" ]; then
sudo add-apt-repository --yes ppa:ubuntu-sdk-team/ppa
fi
sudo apt-get update
sudo apt-get install libsdl2-dev -qq
if [ "$CXX" = "g++" ]; then
sudo apt-get install g++-4.8 -qq
sudo apt-get install -qq g++-4.8
fi
if [ "$QT" = "TRUE" ]; then
sudo apt-get install -qq qt5-qmake qtmultimedia5-dev qtsystems5-dev qtbase5-dev qtdeclarative5-dev qttools5-dev-tools libqt5webkit5-dev libsqlite3-dev qt5-default
sudo apt-get install -qq qt5-qmake qtmultimedia5-dev qtsystems5-dev qtbase5-dev qtdeclarative5-dev qttools5-dev-tools libqt5webkit5-dev libqt5opengl5-dev libsqlite3-dev qt5-default
fi
download_extract "https://cmake.org/files/v3.6/cmake-3.6.2-Linux-x86_64.tar.gz" cmake-3.6.2-Linux-x86_64.tar.gz
@@ -72,16 +38,12 @@ travis_install() {
# Android NDK + GCC 4.8
if [ "$PPSSPP_BUILD_TYPE" = "Android" ]; then
free -m
sudo apt-get install ant -qq
download_extract_zip http://dl.google.com/android/repository/${NDK_VER}-linux-x86_64.zip ${NDK_VER}-linux-x86_64.zip
fi
if [ "$PPSSPP_BUILD_TYPE" = "macOS" ]; then
brew_install sdl2
brew upgrade python
elif [ "$PPSSPP_BUILD_TYPE" = "iOS" ]; then
brew upgrade python
if [ "$PPSSPP_BUILD_TYPE" = "Windows" ]; then
curl -L https://github.com/frerich/clcache/releases/download/v4.2.0/clcache.4.2.0.nupkg --output clcache.4.2.0.nupkg
choco install clcache --source=.
fi
# Ensure we're using ccache
@@ -135,10 +97,28 @@ travis_script() {
if [ "$PPSSPP_BUILD_TYPE" = "macOS" ]; then
./b.sh --headless
fi
if [ "$PPSSPP_BUILD_TYPE" = "Windows" ]; then
export "MSBUILD_PATH=/c/Program Files (x86)/Microsoft Visual Studio/2017/BuildTools/MSBuild/15.0/Bin"
export "PATH=$MSBUILD_PATH:$PATH"
export CLCACHE_OBJECT_CACHE_TIMEOUT_MS=120000
# Set DebugInformationFormat to nothing, the default is ProgramDatabase which breaks clcache.
# Turns out it's not possible to pass this on the msbuild command line.
for f in `find . -name *.vcxproj`; do
sed -i 's/>ProgramDatabase<\/DebugInformationFormat>/><\/DebugInformationFormat>/g' $f
done
msbuild.exe Windows\\PPSSPP.sln -m -p:CLToolExe=clcache.exe -p:Configuration=Release -p:Platform=x64 -p:TrackFileAccess=false
fi
}
travis_after_success() {
ccache -s
if [ "$PPSSPP_BUILD_TYPE" != "Windows" ]; then
ccache -s
else
clcache -s
clcache -z
fi
if [ "$PPSSPP_BUILD_TYPE" = "Linux" ]; then
./test.py
+26 -12
View File
@@ -4,27 +4,38 @@ sudo: required
language: cpp
dist: trusty
dist: xenial
addons:
apt:
update: true
packages:
- ant
- aria2
- build-essential
- cmake
- libgl1-mesa-dev
- libglu1-mesa-dev
- cmake
- aria2
- ant
- lib32stdc++6
- lib32z1
- lib32z1-dev
- lib32bz2-1.0
- libsdl2-dev
- pv
- software-properties-common
sources:
- sourceline: 'ppa:zoogie/sdl2-snapshots'
- sourceline: 'ppa:ubuntu-toolchain-r/test'
- sourceline: 'ppa:ubuntu-sdk-team/ppa'
homebrew:
update: true
packages:
- ccache
- python
- sdl2
cache:
apt: true
ccache: true
directories:
- $HOME/Library/Caches/Homebrew
- $HOME/clcache
# By encrypting the channel name, we disable notifications from forks by default.
# It's not actually a big secret.
@@ -75,19 +86,22 @@ matrix:
env: PPSSPP_BUILD_TYPE=Linux
LIBRETRO=TRUE
- os: osx
osx_image: xcode8
osx_image: xcode8.3
compiler: "clang"
env: PPSSPP_BUILD_TYPE=macOS
- os: osx
osx_image: xcode8
osx_image: xcode8.3
compiler: "clang"
env: PPSSPP_BUILD_TYPE=iOS
- os: windows
compiler: "msvc2017"
env: PPSSPP_BUILD_TYPE=Windows
before_install:
- bash .travis.sh travis_before_install
- travis_retry bash .travis.sh travis_before_install
install:
- bash .travis.sh travis_install
- travis_retry bash .travis.sh travis_install
script:
- bash .travis.sh travis_script
-2
View File
@@ -1874,8 +1874,6 @@ set(WindowsFiles
Windows/InputBox.h
Windows/InputDevice.cpp
Windows/InputDevice.h
Windows/KeyboardDevice.cpp
Windows/KeyboardDevice.h
Windows/W32Util/DialogManager.cpp
Windows/W32Util/DialogManager.h
Windows/W32Util/Misc.cpp
+4
View File
@@ -258,6 +258,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -292,6 +293,7 @@
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StringPooling>true</StringPooling>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -326,6 +328,7 @@
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StringPooling>true</StringPooling>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -360,6 +363,7 @@
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StringPooling>true</StringPooling>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
-4
View File
@@ -705,10 +705,6 @@ struct ConfigTranslator {
typedef ConfigTranslator<GPUBackend, GPUBackendToString, GPUBackendFromString> GPUBackendTranslator;
static ConfigSetting graphicsSettings[] = {
ConfigSetting("EnableCardboard", &g_Config.bEnableCardboard, false, true, true),
ConfigSetting("CardboardScreenSize", &g_Config.iCardboardScreenSize, 50, true, true),
ConfigSetting("CardboardXShift", &g_Config.iCardboardXShift, 0, true, true),
ConfigSetting("CardboardYShift", &g_Config.iCardboardXShift, 0, true, true),
ConfigSetting("ShowFPSCounter", &g_Config.iShowFPSCounter, 0, true, true),
ReportedConfigSetting("GraphicsBackend", &g_Config.iGPUBackend, &DefaultGPUBackend, &GPUBackendTranslator::To, &GPUBackendTranslator::From, true, false),
ConfigSetting("FailedGraphicsBackends", &g_Config.sFailedGPUBackends, ""),
-5
View File
@@ -159,11 +159,6 @@ public:
bool bAutoFrameSkip;
bool bFrameSkipUnthrottle;
bool bEnableCardboard; // Cardboard Master Switch
int iCardboardScreenSize; // Screen Size (in %)
int iCardboardXShift; // X-Shift of Screen (in %)
int iCardboardYShift; // Y-Shift of Screen (in %)
int iWindowX;
int iWindowY;
int iWindowWidth; // Windows and other windowed environments
+4
View File
@@ -238,6 +238,7 @@
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -271,6 +272,7 @@
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StringPooling>true</StringPooling>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -300,6 +302,7 @@
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StringPooling>true</StringPooling>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -329,6 +332,7 @@
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StringPooling>true</StringPooling>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
+22 -13
View File
@@ -98,7 +98,7 @@ static bool FixFilenameCase(const std::string &path, std::string &filename)
return retValue;
}
bool FixPathCase(std::string& basePath, std::string &path, FixPathCaseBehavior behavior)
bool FixPathCase(const std::string &basePath, std::string &path, FixPathCaseBehavior behavior)
{
size_t len = path.size();
@@ -158,25 +158,25 @@ DirectoryFileSystem::~DirectoryFileSystem() {
CloseAll();
}
std::string DirectoryFileHandle::GetLocalPath(std::string& basePath, std::string localpath)
std::string DirectoryFileHandle::GetLocalPath(const std::string &basePath, std::string localpath)
{
if (localpath.empty())
return basePath;
if (localpath[0] == '/')
localpath.erase(0,1);
//Convert slashes
localpath.erase(0, 1);
std::string result = basePath + localpath;
#ifdef _WIN32
for (size_t i = 0; i < localpath.size(); i++) {
if (localpath[i] == '/')
localpath[i] = '\\';
for (char &c : result) {
if (c == '/')
c = '\\';
}
#endif
return basePath + localpath;
return result;
}
bool DirectoryFileHandle::Open(std::string &basePath, std::string &fileName, FileAccess access, u32 &error)
{
bool DirectoryFileHandle::Open(const std::string &basePath, std::string &fileName, FileAccess access, u32 &error) {
error = 0;
#if HOST_IS_CASE_SENSITIVE
@@ -190,7 +190,7 @@ bool DirectoryFileHandle::Open(std::string &basePath, std::string &fileName, Fil
// else we try fopen first (in case we're lucky) before simulating case insensitivity
#endif
std::string fullName = GetLocalPath(basePath,fileName);
std::string fullName = GetLocalPath(basePath, fileName);
VERBOSE_LOG(FILESYS,"Actually opening %s", fullName.c_str());
// On the PSP, truncating doesn't lose data. If you seek later, you'll recover it.
@@ -322,6 +322,11 @@ bool DirectoryFileHandle::Open(std::string &basePath, std::string &fileName, Fil
}
#endif
// Try to detect reads/writes to PSP/GAME to avoid them in replays.
if (fullName.find("/PSP/GAME/") != fullName.npos || fullName.find("\\PSP\\GAME\\") != fullName.npos) {
inGameDir_ = true;
}
return success;
}
@@ -333,7 +338,7 @@ size_t DirectoryFileHandle::Read(u8* pointer, s64 size)
// On a PSP. it actually is truncated, but the data wasn't erased.
off_t off = (off_t)Seek(0, FILEMOVE_CURRENT);
if (needsTrunc_ <= off) {
return replay_ ? ReplayApplyDiskRead(pointer, 0, (uint32_t)size, CoreTiming::GetGlobalTimeUs()) : 0;
return replay_ ? ReplayApplyDiskRead(pointer, 0, (uint32_t)size, inGameDir_, CoreTiming::GetGlobalTimeUs()) : 0;
}
if (needsTrunc_ < off + size) {
size = needsTrunc_ - off;
@@ -344,7 +349,7 @@ size_t DirectoryFileHandle::Read(u8* pointer, s64 size)
#else
bytesRead = read(hFile, pointer, size);
#endif
return replay_ ? ReplayApplyDiskRead(pointer, (uint32_t)bytesRead, (uint32_t)size, CoreTiming::GetGlobalTimeUs()) : bytesRead;
return replay_ ? ReplayApplyDiskRead(pointer, (uint32_t)bytesRead, (uint32_t)size, inGameDir_, CoreTiming::GetGlobalTimeUs()) : bytesRead;
}
size_t DirectoryFileHandle::Write(const u8* pointer, s64 size)
@@ -371,6 +376,10 @@ size_t DirectoryFileHandle::Write(const u8* pointer, s64 size)
}
}
if (replay_) {
bytesWritten = ReplayApplyDiskWrite(pointer, (uint64_t)bytesWritten, (uint64_t)size, &diskFull, inGameDir_, CoreTiming::GetGlobalTimeUs());
}
if (diskFull) {
ERROR_LOG(FILESYS, "Disk full");
I18NCategory *err = GetI18NCategory("Error");
+4 -3
View File
@@ -54,7 +54,7 @@ enum FixPathCaseBehavior {
FPC_PARTIAL_ALLOWED, // don't care how many exist (mkdir recursive)
};
bool FixPathCase(std::string& basePath, std::string &path, FixPathCaseBehavior behavior);
bool FixPathCase(const std::string &basePath, std::string &path, FixPathCaseBehavior behavior);
#endif
struct DirectoryFileHandle {
@@ -70,12 +70,13 @@ struct DirectoryFileHandle {
#endif
s64 needsTrunc_ = -1;
bool replay_ = true;
bool inGameDir_ = false;
DirectoryFileHandle(Flags flags) : replay_(flags != SKIP_REPLAY) {
}
std::string GetLocalPath(std::string& basePath, std::string localpath);
bool Open(std::string& basePath, std::string& fileName, FileAccess access, u32 &err);
std::string GetLocalPath(const std::string &basePath, std::string localpath);
bool Open(const std::string &basePath, std::string &fileName, FileAccess access, u32 &err);
size_t Read(u8* pointer, s64 size);
size_t Write(const u8* pointer, s64 size);
size_t Seek(s32 position, FileMove type);
+59 -4
View File
@@ -62,6 +62,7 @@ enum latency {
int eventAudioUpdate = -1;
int eventHostAudioUpdate = -1;
int mixFrequency = 44100;
int srcFrequency = 0;
const int hwSampleRate = 44100;
@@ -107,6 +108,7 @@ static void __AudioCPUMHzChange() {
void __AudioInit() {
memset(&g_AudioDebugStats, 0, sizeof(g_AudioDebugStats));
mixFrequency = 44100;
srcFrequency = 0;
switch (g_Config.iAudioLatency) {
case LOW_LATENCY:
@@ -149,7 +151,7 @@ void __AudioInit() {
}
void __AudioDoState(PointerWrap &p) {
auto s = p.Section("sceAudio", 1);
auto s = p.Section("sceAudio", 1, 2);
if (!s)
return;
@@ -159,6 +161,13 @@ void __AudioDoState(PointerWrap &p) {
CoreTiming::RestoreRegisterEvent(eventHostAudioUpdate, "AudioUpdateHost", &hleHostAudioUpdate);
p.Do(mixFrequency);
if (s >= 2) {
p.Do(srcFrequency);
} else {
// Assume that it was actually the SRC channel frequency.
srcFrequency = mixFrequency;
mixFrequency = 44100;
}
// TODO: This never happens because maxVer=1.
if (s >= 2) {
@@ -176,6 +185,7 @@ void __AudioDoState(PointerWrap &p) {
if (chanCount != ARRAY_SIZE(chans))
{
ERROR_LOG(SCEAUDIO, "Savestate failure: different number of audio channels.");
p.SetError(p.ERROR_FAILURE);
return;
}
for (int i = 0; i < chanCount; ++i)
@@ -329,6 +339,10 @@ void __AudioSetOutputFrequency(int freq) {
mixFrequency = freq;
}
void __AudioSetSRCFrequency(int freq) {
srcFrequency = freq;
}
// Mix samples from the various audio channels into a single sample queue.
// This single sample queue is where __AudioMix should read from. If the sample queue is full, we should
// just sleep the main emulator thread a little.
@@ -337,6 +351,7 @@ void __AudioUpdate(bool resetRecording) {
// to the CPU. Much better to throttle the frame rate on frame display and just throw away audio
// if the buffer somehow gets full.
bool firstChannel = true;
std::vector<int16_t> srcBuffer;
for (u32 i = 0; i < PSP_AUDIO_CHANNEL_MAX + 1; i++) {
if (!chans[i].reserved)
@@ -348,14 +363,54 @@ void __AudioUpdate(bool resetRecording) {
continue;
}
if (hwBlockSize * 2 > (int)chans[i].sampleQueue.size()) {
ERROR_LOG(SCEAUDIO, "Channel %i buffer underrun at %i of %i", i, (int)chans[i].sampleQueue.size() / 2, hwBlockSize);
bool needsResample = i == PSP_AUDIO_CHANNEL_SRC && srcFrequency != 0 && srcFrequency != mixFrequency;
size_t sz = needsResample ? (hwBlockSize * 2 * srcFrequency) / mixFrequency : hwBlockSize * 2;
if (sz > chans[i].sampleQueue.size()) {
ERROR_LOG(SCEAUDIO, "Channel %i buffer underrun at %i of %i", i, (int)chans[i].sampleQueue.size() / 2, (int)sz / 2);
}
const s16 *buf1 = 0, *buf2 = 0;
size_t sz1, sz2;
chans[i].sampleQueue.popPointers(hwBlockSize * 2, &buf1, &sz1, &buf2, &sz2);
chans[i].sampleQueue.popPointers(sz, &buf1, &sz1, &buf2, &sz2);
if (needsResample) {
auto read = [&](size_t i) {
if (i < sz1)
return buf1[i];
if (i < sz1 + sz2)
return buf2[i - sz1];
if (buf2)
return buf2[sz2 - 1];
return buf1[sz1 - 1];
};
srcBuffer.resize(hwBlockSize * 2);
// TODO: This is terrible, since it's doing it by small chunk and discarding frac.
const uint32_t ratio = (uint32_t)(65536.0 * srcFrequency / (double)mixFrequency);
uint32_t frac = 0;
size_t readIndex = 0;
for (size_t outIndex = 0; readIndex < sz && outIndex < srcBuffer.size(); outIndex += 2) {
size_t readIndex2 = readIndex + 2;
int16_t l1 = read(readIndex);
int16_t r1 = read(readIndex + 1);
int16_t l2 = read(readIndex2);
int16_t r2 = read(readIndex2 + 1);
int sampleL = ((l1 << 16) + (l2 - l1) * (uint16_t)frac) >> 16;
int sampleR = ((r1 << 16) + (r2 - r1) * (uint16_t)frac) >> 16;
srcBuffer[outIndex] = sampleL;
srcBuffer[outIndex + 1] = sampleR;
frac += ratio;
readIndex += 2 * (uint16_t)(frac >> 16);
frac &= 0xffff;
}
buf1 = srcBuffer.data();
sz1 = srcBuffer.size();
buf2 = nullptr;
sz2 = 0;
}
if (firstChannel) {
for (size_t s = 0; s < sz1; s++)
+1
View File
@@ -36,6 +36,7 @@ void __AudioDoState(PointerWrap &p);
void __AudioUpdate(bool resetRecording = false);
void __AudioShutdown();
void __AudioSetOutputFrequency(int freq);
void __AudioSetSRCFrequency(int freq);
// May return SCE_ERROR_AUDIO_CHANNEL_BUSY if buffer too large
u32 __AudioEnqueue(AudioChannel &chan, int chanNum, bool blocking);
+30 -19
View File
@@ -248,10 +248,10 @@ static u32 sceAudioChRelease(u32 chan) {
ERROR_LOG(SCEAUDIO, "sceAudioChRelease(%i) - channel not reserved", chan);
return SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED;
}
DEBUG_LOG(SCEAUDIO, "sceAudioChRelease(%i)", chan);
// TODO: Does this error if busy?
chans[chan].reset();
chans[chan].reserved = false;
return 1;
return hleLogSuccessI(SCEAUDIO, 0);
}
static u32 sceAudioSetChannelDataLen(u32 chan, u32 len) {
@@ -329,6 +329,7 @@ static u32 sceAudioOutput2Reserve(u32 sampleCount) {
chan.sampleCount = sampleCount;
chan.format = PSP_AUDIO_FORMAT_STEREO;
chan.reserved = true;
__AudioSetSRCFrequency(0);
return hleLogSuccessI(SCEAUDIO, 0);
}
@@ -339,11 +340,15 @@ static u32 sceAudioOutput2OutputBlocking(u32 vol, u32 dataPtr) {
}
auto &chan = chans[PSP_AUDIO_CHANNEL_OUTPUT2];
if (!chan.reserved) {
return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED, "channel not reserved");
}
chan.leftVolume = vol;
chan.rightVolume = vol;
chan.sampleAddress = dataPtr;
hleEatCycles(10000);
hleEatCycles(10000);
int result = __AudioEnqueue(chan, PSP_AUDIO_CHANNEL_OUTPUT2, true);
if (result < 0)
return hleLogError(SCEAUDIO, result);
@@ -351,22 +356,25 @@ static u32 sceAudioOutput2OutputBlocking(u32 vol, u32 dataPtr) {
}
static u32 sceAudioOutput2ChangeLength(u32 sampleCount) {
if (!chans[PSP_AUDIO_CHANNEL_OUTPUT2].reserved) {
ERROR_LOG(SCEAUDIO, "sceAudioOutput2ChangeLength(%08x) - channel not reserved ", sampleCount);
return SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED;
auto &chan = chans[PSP_AUDIO_CHANNEL_OUTPUT2];
if (!chan.reserved) {
return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED, "channel not reserved");
}
DEBUG_LOG(SCEAUDIO, "sceAudioOutput2ChangeLength(%08x)", sampleCount);
chans[PSP_AUDIO_CHANNEL_OUTPUT2].sampleCount = sampleCount;
return 0;
chan.sampleCount = sampleCount;
return hleLogSuccessI(SCEAUDIO, 0);
}
static u32 sceAudioOutput2GetRestSample() {
if (!chans[PSP_AUDIO_CHANNEL_OUTPUT2].reserved) {
ERROR_LOG(SCEAUDIO, "sceAudioOutput2GetRestSample() - channel not reserved ");
return SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED;
auto &chan = chans[PSP_AUDIO_CHANNEL_OUTPUT2];
if (!chan.reserved) {
return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED, "channel not reserved");
}
DEBUG_LOG(SCEAUDIO, "sceAudioOutput2GetRestSample()");
return (u32) chans[PSP_AUDIO_CHANNEL_OUTPUT2].sampleQueue.size() / 2;
u32 size = (u32)chan.sampleQueue.size() / 2;
if (size > chan.sampleCount) {
// If ChangeLength reduces the size, it still gets output but this return is clamped.
size = chan.sampleCount;
}
return hleLogSuccessI(SCEAUDIO, size);
}
static u32 sceAudioOutput2Release() {
@@ -382,6 +390,7 @@ static u32 sceAudioOutput2Release() {
}
static u32 sceAudioSetFrequency(u32 freq) {
// TODO: Not available from user code.
if (freq == 44100 || freq == 48000) {
INFO_LOG(SCEAUDIO, "sceAudioSetFrequency(%08x)", freq);
__AudioSetOutputFrequency(freq);
@@ -424,10 +433,8 @@ static u32 sceAudioSRCChReserve(u32 sampleCount, u32 freq, u32 format) {
chan.reserved = true;
chan.sampleCount = sampleCount;
chan.format = format == 2 ? PSP_AUDIO_FORMAT_STEREO : PSP_AUDIO_FORMAT_MONO;
// TODO: Zero probably means don't change? Or it means default?
if (freq != 0) {
__AudioSetOutputFrequency(freq);
}
// Zero means default to 44.1kHz.
__AudioSetSRCFrequency(freq);
return hleLogSuccessI(SCEAUDIO, 0);
}
@@ -449,6 +456,10 @@ static u32 sceAudioSRCOutputBlocking(u32 vol, u32 buf) {
}
auto &chan = chans[PSP_AUDIO_CHANNEL_SRC];
if (!chan.reserved) {
return hleLogError(SCEAUDIO, SCE_ERROR_AUDIO_CHANNEL_NOT_RESERVED, "channel not reserved");
}
chan.leftVolume = vol;
chan.rightVolume = vol;
chan.sampleAddress = buf;
@@ -511,7 +522,7 @@ const HLEFunction sceAudio[] =
{0X95FD0C2D, &WrapU_UU<sceAudioChangeChannelConfig>, "sceAudioChangeChannelConfig", 'x', "ii" },
{0XB7E1D8E7, &WrapU_UUU<sceAudioChangeChannelVolume>, "sceAudioChangeChannelVolume", 'x', "ixx" },
// Not sure about the point of these, maybe like traditional but with ability to do sample rate conversion?
// Like Output2, but with ability to do sample rate conversion.
{0X38553111, &WrapU_UUU<sceAudioSRCChReserve>, "sceAudioSRCChReserve", 'x', "iii" },
{0X5C37C0AE, &WrapU_V<sceAudioSRCChRelease>, "sceAudioSRCChRelease", 'x', "" },
{0XE0727056, &WrapU_UU<sceAudioSRCOutputBlocking>, "sceAudioSRCOutputBlocking", 'x', "xx" },
+1
View File
@@ -1626,6 +1626,7 @@ bool __KernelLoadExec(const char *filename, u32 paramPtr, std::string *error_str
if (param_argp) delete[] param_argp;
if (param_key) delete[] param_key;
}
__KernelShutdown();
return false;
}
+4
View File
@@ -188,3 +188,7 @@ std::string KernelTimeNowFormatted() {
std::string timestamp = StringFromFormat("%04d-%02d-%02d_%02d-%02d-%02d", years, months, days, hours, minutes, seconds);
return timestamp;
}
void KernelTimeSetBase(int64_t seconds) {
start_time = (time_t)seconds;
}
+1
View File
@@ -28,6 +28,7 @@ int sceKernelSysClock2USecWide(u32 lowClock, u32 highClock, u32 lowPtr, u32 high
u64 sceKernelUSec2SysClockWide(u32 usec);
u32 sceKernelLibcClock();
std::string KernelTimeNowFormatted();
void KernelTimeSetBase(int64_t seconds);
void __KernelTimeInit();
void __KernelTimeDoState(PointerWrap &p);
+19 -2
View File
@@ -138,6 +138,10 @@ static time_t rtc_timegm(struct tm *tm)
#endif
static void RtcUpdateBaseTicks() {
rtcBaseTicks = 1000000ULL * rtcBaseTime.tv_sec + rtcBaseTime.tv_usec + rtcMagicOffset;
}
void __RtcInit()
{
// This is the base time, the only case we use gettimeofday() for.
@@ -147,7 +151,7 @@ void __RtcInit()
rtcBaseTime.tv_sec = tv.tv_sec;
rtcBaseTime.tv_usec = 0;
// Precalculate the current time in microseconds (rtcMagicOffset is offset to 1970.)
rtcBaseTicks = 1000000ULL * rtcBaseTime.tv_sec + rtcBaseTime.tv_usec + rtcMagicOffset;
RtcUpdateBaseTicks();
}
void __RtcDoState(PointerWrap &p)
@@ -158,7 +162,7 @@ void __RtcDoState(PointerWrap &p)
p.Do(rtcBaseTime);
// Update the precalc, pointless to savestate this as it's just based on the other value.
rtcBaseTicks = 1000000ULL * rtcBaseTime.tv_sec + rtcBaseTime.tv_usec + rtcMagicOffset;
RtcUpdateBaseTicks();
}
void __RtcTimeOfDay(PSPTimeval *tv)
@@ -171,6 +175,19 @@ void __RtcTimeOfDay(PSPTimeval *tv)
tv->tv_usec = adjustedUs % 1000000UL;
}
int32_t RtcBaseTime(int32_t *micro) {
if (micro) {
*micro = rtcBaseTime.tv_usec;
}
return rtcBaseTime.tv_sec;
}
void RtcSetBaseTime(int32_t seconds, int32_t micro) {
rtcBaseTime.tv_sec = seconds;
rtcBaseTime.tv_usec = micro;
RtcUpdateBaseTicks();
}
static void __RtcTmToPspTime(ScePspDateTime &t, const tm *val)
{
t.year = val->tm_year + 1900;
+2
View File
@@ -27,6 +27,8 @@ struct PSPTimeval {
};
void __RtcTimeOfDay(PSPTimeval *tv);
int32_t RtcBaseTime(int32_t *micro = nullptr);
void RtcSetBaseTime(int32_t seconds, int32_t micro = 0);
void Register_sceRtc();
void __RtcInit();
+1 -1
View File
@@ -56,7 +56,7 @@ static u32 sceVaudioChReserve(int sampleCount, int freq, int format) {
chans[PSP_AUDIO_CHANNEL_VAUDIO].leftVolume = 0;
chans[PSP_AUDIO_CHANNEL_VAUDIO].rightVolume = 0;
vaudioReserved = true;
__AudioSetOutputFrequency(freq);
__AudioSetSRCFrequency(freq);
return 0;
}
+2
View File
@@ -293,4 +293,6 @@ void StereoResampler::DoState(PointerWrap &p) {
auto s = p.Section("resampler", 1);
if (!s)
return;
if (p.mode == p.MODE_READ)
Clear();
}
+1 -2
View File
@@ -54,9 +54,8 @@ enum class IdentifiedFileType {
UNKNOWN,
};
class FileLoader {
// NB: It is a REQUIREMENT that implementations of this class are entirely thread safe!
class FileLoader {
public:
enum class Flags {
NONE,
+1 -1
View File
@@ -2202,7 +2202,7 @@ namespace MIPSInt
ReadVector(s.f, sz, vs);
ApplySwizzleS(s.f, sz);
ReadVector(t.f, sz, vs);
ReadVector(t.f, sz, vt);
ApplySwizzleT(t.f, sz);
// Swizzle does apply to the value read as an integer.
u8 exp = (u8)(127 + t.i[0]);
+111 -35
View File
@@ -24,6 +24,8 @@
#include "Core/Replay.h"
#include "Core/FileSystems/FileSystem.h"
#include "Core/HLE/sceCtrl.h"
#include "Core/HLE/sceKernelTime.h"
#include "Core/HLE/sceRtc.h"
enum class ReplayState {
IDLE,
@@ -31,19 +33,42 @@ enum class ReplayState {
SAVE,
};
// Overall structure of file format:
//
// - ReplayFileHeader with basic data about replay (mostly timestamp for sync.)
// - An indeterminate sequence of events:
// - ReplayItemHeader (primary event details)
// - Side data of bytes listed in header, if SIDEDATA flag set on action.
//
// The header doesn't say how long the replay is, because new events are
// appended to the file as they occur. It is usually near, and always less than:
//
// (fileSize - sizeof(ReplayFileHeader)) / sizeof(ReplayItemHeader)
// File data formats below.
#pragma pack(push, 1)
static const char *REPLAY_MAGIC = "PPREPLAY";
static const int REPLAY_VERSION_MIN = 1;
static const int REPLAY_VERSION_CURRENT = 1;
struct ReplayFileHeader {
char magic[8];
u32_le version = REPLAY_VERSION_CURRENT;
u32_le reserved[3]{};
u64_le rtcBaseSeconds;
};
struct ReplayItemHeader {
ReplayAction action;
uint64_t timestamp;
u64_le timestamp;
union {
uint32_t buttons;
u32_le buttons;
uint8_t analog[2][2];
uint32_t result;
uint64_t result64;
u32_le result;
u64_le result64;
// NOTE: Certain action types have data, always sized by this/result.
uint32_t size;
u32_le size;
};
ReplayItemHeader(ReplayAction a, uint64_t t) {
@@ -68,14 +93,14 @@ static const int REPLAY_MAX_FILENAME = 256;
struct ReplayFileInfo {
char filename[REPLAY_MAX_FILENAME]{};
int64_t size = 0;
uint16_t access = 0;
s64_le size = 0;
u16_le access = 0;
uint8_t exists = 0;
uint8_t isDirectory = 0;
int64_t atime = 0;
int64_t ctime = 0;
int64_t mtime = 0;
s64_le atime = 0;
s64_le ctime = 0;
s64_le mtime = 0;
};
#pragma pack(pop)
@@ -93,6 +118,7 @@ static std::vector<ReplayItem> replayItems;
static size_t replayExecPos = 0;
static bool replaySaveWroteHeader = false;
static ReplayState replayState = ReplayState::IDLE;
static bool replaySawGameDirWrite = false;
static size_t replayCtrlPos = 0;
static uint32_t lastButtons = 0;
@@ -101,8 +127,6 @@ static uint8_t lastAnalog[2][2]{};
static size_t replayDiskPos = 0;
static bool diskFailed = false;
// TODO: File format either needs rtc and rand seed, or must be paired with a save state.
void ReplayExecuteBlob(const std::vector<u8> &data) {
ReplayAbort();
@@ -145,28 +169,52 @@ bool ReplayExecuteFile(const std::string &filename) {
return false;
}
// TODO: Header handling.
// Include initial rand state or timestamp?
// TODO: Maybe stream instead.
size_t sz = File::GetFileSize(fp);
if (sz == 0) {
ERROR_LOG(SYSTEM, "Empty replay data");
fclose(fp);
return false;
}
std::vector<u8> data;
data.resize(sz);
auto loadData = [&]() {
// TODO: Maybe stream instead.
size_t sz = File::GetFileSize(fp);
if (sz <= sizeof(ReplayFileHeader)) {
ERROR_LOG(SYSTEM, "Empty replay data");
return false;
}
if (fread(&data[0], sz, 1, fp) != 1) {
ERROR_LOG(SYSTEM, "Could not read replay data");
ReplayFileHeader fh;
if (fread(&fh, sizeof(fh), 1, fp) != 1) {
ERROR_LOG(SYSTEM, "Could not read replay file header");
return false;
}
sz -= sizeof(fh);
if (memcmp(fh.magic, REPLAY_MAGIC, sizeof(fh.magic)) != 0) {
ERROR_LOG(SYSTEM, "Replay header corrupt");
return false;
}
if (fh.version < REPLAY_VERSION_MIN) {
ERROR_LOG(SYSTEM, "Replay version %d unsupported", fh.version);
return false;
} else if (fh.version > REPLAY_VERSION_CURRENT) {
WARN_LOG(SYSTEM, "Replay version %d scary and futuristic, trying anyway", fh.version);
}
data.resize(sz);
if (fread(&data[0], sz, 1, fp) != 1) {
ERROR_LOG(SYSTEM, "Could not read replay data");
return false;
}
return true;
};
if (loadData()) {
fclose(fp);
return false;
ReplayExecuteBlob(data);
return true;
}
ReplayExecuteBlob(data);
return true;
fclose(fp);
return false;
}
bool ReplayHasMoreEvents() {
@@ -219,13 +267,18 @@ bool ReplayFlushFile(const std::string &filename) {
return false;
}
// TODO: Header handling.
// Include initial rand state or timestamp?
replaySaveWroteHeader = true;
bool success = true;
if (!replaySaveWroteHeader) {
ReplayFileHeader fh;
memcpy(fh.magic, REPLAY_MAGIC, sizeof(fh.magic));
fh.rtcBaseSeconds = RtcBaseTime();
success = fwrite(&fh, sizeof(fh), 1, fp) == 1;
replaySaveWroteHeader = true;
}
size_t c = replayItems.size();
bool success = true;
if (c != 0) {
if (success && c != 0) {
// TODO: Maybe stream instead.
std::vector<u8> data;
ReplayFlushBlob(&data);
@@ -247,6 +300,7 @@ void ReplayAbort() {
replayExecPos = 0;
replaySaveWroteHeader = false;
replayState = ReplayState::IDLE;
replaySawGameDirWrite = false;
replayCtrlPos = 0;
lastButtons = 0;
@@ -387,7 +441,12 @@ uint64_t ReplayApplyDisk64(ReplayAction action, uint64_t result, uint64_t t) {
}
}
uint32_t ReplayApplyDiskRead(void *data, uint32_t readSize, uint32_t dataSize, uint64_t t) {
uint32_t ReplayApplyDiskRead(void *data, uint32_t readSize, uint32_t dataSize, bool inGameDir, uint64_t t) {
// Ignore PSP/GAME reads if we haven't seen a write there.
if (inGameDir && !replaySawGameDirWrite) {
return readSize;
}
switch (replayState) {
case ReplayState::EXECUTE:
{
@@ -414,6 +473,23 @@ uint32_t ReplayApplyDiskRead(void *data, uint32_t readSize, uint32_t dataSize, u
}
}
uint64_t ReplayApplyDiskWrite(const void *data, uint64_t writeSize, uint64_t dataSize, bool *diskFull, bool inGameDir, uint64_t t) {
switch (replayState) {
case ReplayState::EXECUTE:
case ReplayState::SAVE:
// Never let the disk return full during replay.
if (diskFull)
*diskFull = false;
if (inGameDir)
replaySawGameDirWrite = true;
return writeSize;
case ReplayState::IDLE:
default:
return writeSize;
}
}
static int64_t ConvertFromTm(const struct tm *t) {
// Remember, mktime modifies.
struct tm copy = *t;
+3 -2
View File
@@ -46,7 +46,7 @@ enum class ReplayAction : uint8_t {
struct PSPFileInfo;
// Replay from data in memory.
// Replay from data in memory. Does not manipulate base time / RNG state.
void ReplayExecuteBlob(const std::vector<u8> &data);
// Replay from data in a file. Returns false if invalid.
bool ReplayExecuteFile(const std::string &filename);
@@ -68,6 +68,7 @@ void ReplayAbort();
void ReplayApplyCtrl(uint32_t &buttons, uint8_t analog[2][2], uint64_t t);
uint32_t ReplayApplyDisk(ReplayAction action, uint32_t result, uint64_t t);
uint64_t ReplayApplyDisk64(ReplayAction action, uint64_t result, uint64_t t);
uint32_t ReplayApplyDiskRead(void *data, uint32_t readSize, uint32_t dataSize, uint64_t t);
uint32_t ReplayApplyDiskRead(void *data, uint32_t readSize, uint32_t dataSize, bool inGameDir, uint64_t t);
uint64_t ReplayApplyDiskWrite(const void *data, uint64_t writeSize, uint64_t dataSize, bool *diskFull, bool inGameDir, uint64_t t);
PSPFileInfo ReplayApplyDiskFileInfo(const PSPFileInfo &data, uint64_t t);
std::vector<PSPFileInfo> ReplayApplyDiskListing(const std::vector<PSPFileInfo> &data, uint64_t t);
+240 -100
View File
@@ -16,6 +16,8 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <algorithm>
#include <cctype>
#include <string>
#include <set>
#include <cstring>
#include <thread>
@@ -30,6 +32,7 @@
#include "Common/Log.h"
#include "Common/FileUtil.h"
#include "Common/StringUtils.h"
#include "Core/Config.h"
#include "Core/System.h"
#include "Core/Util/GameManager.h"
@@ -58,7 +61,7 @@ bool GameManager::IsGameInstalled(std::string name) {
return File::Exists(pspGame + name);
}
bool GameManager::DownloadAndInstall(std::string storeZipUrl) {
bool GameManager::DownloadAndInstall(std::string storeFileUrl) {
if (curDownload_.get() != 0) {
ERROR_LOG(HLE, "Can only process one download at a time");
return false;
@@ -69,7 +72,7 @@ bool GameManager::DownloadAndInstall(std::string storeZipUrl) {
}
std::string filename = GetTempFilename();
curDownload_ = g_DownloadManager.StartDownload(storeZipUrl, filename);
curDownload_ = g_DownloadManager.StartDownload(storeFileUrl, filename);
return true;
}
@@ -88,114 +91,241 @@ bool GameManager::Uninstall(std::string name) {
return false;
}
std::string gameDir = GetSysDirectory(DIRECTORY_GAME) + name;
INFO_LOG(HLE, "Deleting %s", gameDir.c_str());
INFO_LOG(HLE, "Deleting '%s'", gameDir.c_str());
if (!File::Exists(gameDir)) {
ERROR_LOG(HLE, "Game %s not installed, cannot uninstall", name.c_str());
ERROR_LOG(HLE, "Game '%s' not installed, cannot uninstall", name.c_str());
return false;
}
bool success = File::DeleteDirRecursively(gameDir);
if (success) {
INFO_LOG(HLE, "Successfully deleted game %s", name.c_str());
INFO_LOG(HLE, "Successfully deleted game '%s'", name.c_str());
g_Config.CleanRecent();
return true;
} else {
ERROR_LOG(HLE, "Failed to delete game %s", name.c_str());
ERROR_LOG(HLE, "Failed to delete game '%s'", name.c_str());
return false;
}
}
void GameManager::Update() {
if (curDownload_.get() && curDownload_->Done()) {
INFO_LOG(HLE, "Download completed! Status = %i", curDownload_->ResultCode());
std::string zipName = curDownload_->outfile();
INFO_LOG(HLE, "Download completed! Status = %d", curDownload_->ResultCode());
std::string fileName = curDownload_->outfile();
if (curDownload_->ResultCode() == 200) {
if (!File::Exists(zipName)) {
ERROR_LOG(HLE, "Downloaded file %s does not exist :(", zipName.c_str());
if (!File::Exists(fileName)) {
ERROR_LOG(HLE, "Downloaded file '%s' does not exist :(", fileName.c_str());
curDownload_.reset();
return;
}
// Game downloaded to temporary file - install it!
InstallGameOnThread(zipName, true);
InstallGameOnThread(curDownload_->url(), fileName, true);
} else {
ERROR_LOG(HLE, "Expected HTTP status code 200, got status code %i. Install cancelled, deleting partial file.", curDownload_->ResultCode());
File::Delete(zipName.c_str());
ERROR_LOG(HLE, "Expected HTTP status code 200, got status code %d. Install cancelled, deleting partial file '%s'",
curDownload_->ResultCode(), fileName.c_str());
File::Delete(fileName.c_str());
}
curDownload_.reset();
}
}
bool GameManager::InstallGame(std::string zipfile, bool deleteAfter) {
void countSlashes(std::string fileName, int *slashLocation, int *slashCount) {
*slashCount = 0;
int lastSlashLocation = -1;
*slashLocation = -1;
for (size_t i = 0; i < fileName.size(); i++) {
if (fileName[i] == '/') {
(*slashCount)++;
*slashLocation = lastSlashLocation;
lastSlashLocation = (int)i;
}
}
}
ZipFileContents DetectZipFileContents(std::string fileName, ZipFileInfo *info) {
int error = 0;
#ifdef _WIN32
struct zip *z = zip_open(ConvertUTF8ToWString(fileName).c_str(), 0, &error);
#else
struct zip *z = zip_open(fileName.c_str(), 0, &error);
#endif
if (!z) {
return ZipFileContents::UNKNOWN;
}
ZipFileContents retVal = DetectZipFileContents(z, info);
zip_close(z);
return retVal;
}
inline char asciitolower(char in) {
if (in <= 'Z' && in >= 'A')
return in - ('Z' - 'z');
return in;
}
ZipFileContents DetectZipFileContents(struct zip *z, ZipFileInfo *info) {
int numFiles = zip_get_num_files(z);
// Verify that this is a PSP zip file with the correct layout. We also try
// to detect simple zipped ISO files, those we'll just "install" to the current
// directory of the Games tab (where else?).
bool isPSPMemstickGame = false;
bool isZippedISO = false;
int stripChars = 0;
int isoFileIndex = -1;
for (int i = 0; i < numFiles; i++) {
const char *fn = zip_get_name(z, i, 0);
std::string zippedName = fn;
std::transform(zippedName.begin(), zippedName.end(), zippedName.begin(),
[](unsigned char c) { return asciitolower(c); }); // Not using std::tolower to avoid Turkish I->ı conversion.
if (zippedName.find("eboot.pbp") != std::string::npos) {
int slashCount = 0;
int slashLocation = -1;
countSlashes(zippedName, &slashLocation, &slashCount);
if (slashCount >= 1 && (!isPSPMemstickGame || slashLocation < stripChars + 1)) {
stripChars = slashLocation + 1;
isPSPMemstickGame = true;
} else {
INFO_LOG(HLE, "Wrong number of slashes (%i) in '%s'", slashCount, fn);
}
} else if (endsWith(zippedName, ".iso") || endsWith(zippedName, ".cso")) {
int slashCount = 0;
int slashLocation = -1;
countSlashes(zippedName, &slashLocation, &slashCount);
if (slashCount <= 1) {
// We only do this if the ISO file is in the root or one level down.
isZippedISO = true;
isoFileIndex = i;
}
}
}
info->stripChars = stripChars;
info->numFiles = numFiles;
info->isoFileIndex = isoFileIndex;
// If a ZIP is detected as both, let's let the memstick game interpretation prevail.
if (isPSPMemstickGame) {
return ZipFileContents::PSP_GAME_DIR;
} else if (isZippedISO) {
return ZipFileContents::ISO_FILE;
} else {
return ZipFileContents::UNKNOWN;
}
}
bool GameManager::InstallGame(const std::string &url, const std::string &fileName, bool deleteAfter) {
if (installInProgress_) {
ERROR_LOG(HLE, "Cannot have two installs in progress at the same time");
return false;
}
if (!File::Exists(zipfile)) {
ERROR_LOG(HLE, "ZIP file %s doesn't exist", zipfile.c_str());
if (!File::Exists(fileName)) {
ERROR_LOG(HLE, "Game file '%s' doesn't exist", fileName.c_str());
return false;
}
// Examine the URL to guess out what we're installing.
if (endsWithNoCase(url, ".cso") || endsWithNoCase(url, ".iso")) {
// It's a raw ISO or CSO file. We just copy it to the destination.
std::string shortFilename = GetFilenameFromPath(url);
return InstallRawISO(fileName, shortFilename, deleteAfter);
}
I18NCategory *sy = GetI18NCategory("System");
installInProgress_ = true;
std::string pspGame = GetSysDirectory(DIRECTORY_GAME);
INFO_LOG(HLE, "Installing %s into %s", zipfile.c_str(), pspGame.c_str());
int error;
INFO_LOG(HLE, "Installing '%s' into '%s'", fileName.c_str(), pspGame.c_str());
int error = 0;
#ifdef _WIN32
struct zip *z = zip_open(ConvertUTF8ToWString(zipfile).c_str(), 0, &error);
struct zip *z = zip_open(ConvertUTF8ToWString(fileName).c_str(), 0, &error);
#else
struct zip *z = zip_open(zipfile.c_str(), 0, &error);
struct zip *z = zip_open(fileName.c_str(), 0, &error);
#endif
if (!z) {
ERROR_LOG(HLE, "Failed to open ZIP file %s, error code=%i", zipfile.c_str(), error);
ERROR_LOG(HLE, "Failed to open ZIP file '%s', error code=%i", fileName.c_str(), error);
return false;
}
int numFiles = zip_get_num_files(z);
// First, find all the directories, and precreate them before we fill in with files.
// Also, verify that this is a PSP zip file with the correct layout.
bool isPSP = false;
int stripChars = 0;
for (int i = 0; i < numFiles; i++) {
const char *fn = zip_get_name(z, i, 0);
std::string zippedName = fn;
if (zippedName.find("EBOOT.PBP") != std::string::npos) {
int slashCount = 0;
int lastSlashLocation = -1;
int slashLocation = -1;
for (size_t i = 0; i < zippedName.size(); i++) {
if (zippedName[i] == '/') {
slashCount++;
slashLocation = lastSlashLocation;
lastSlashLocation = (int)i;
}
}
if (slashCount >= 1 && (!isPSP || slashLocation < stripChars + 1)) {
stripChars = slashLocation + 1;
isPSP = true;
} else {
INFO_LOG(HLE, "Wrong number of slashes (%i) in %s", slashCount, zippedName.c_str());
}
}
}
if (!isPSP) {
ZipFileInfo info;
ZipFileContents contents = DetectZipFileContents(z, &info);
switch (contents) {
case ZipFileContents::PSP_GAME_DIR:
// InstallMemstickGame contains code to close z.
return InstallMemstickGame(z, fileName, pspGame, info.numFiles, info.stripChars, deleteAfter);
case ZipFileContents::ISO_FILE:
return InstallZippedISO(z, info.isoFileIndex, fileName, deleteAfter);
default:
ERROR_LOG(HLE, "File not a PSP game, no EBOOT.PBP found.");
installProgress_ = 0.0f;
installInProgress_ = false;
installError_ = sy->T("Not a PSP game");
InstallDone();
if (deleteAfter)
File::Delete(zipfile);
File::Delete(fileName);
return false;
}
}
size_t allBytes = 0, bytesCopied = 0;
bool GameManager::ExtractFile(struct zip *z, int file_index, std::string outFilename, size_t *bytesCopied, size_t allBytes) {
struct zip_stat zstat;
zip_stat_index(z, file_index, 0, &zstat);
size_t size = zstat.size;
// Create all the directories in one pass
// Don't spam the log.
if (file_index < 10) {
INFO_LOG(HLE, "Writing %d bytes to '%s'", (int)size, outFilename.c_str());
}
zip_file *zf = zip_fopen_index(z, file_index, 0);
FILE *f = File::OpenCFile(outFilename, "wb");
if (f) {
size_t pos = 0;
const size_t blockSize = 1024 * 128;
u8 *buffer = new u8[blockSize];
while (pos < size) {
size_t readSize = std::min(blockSize, size - pos);
ssize_t retval = zip_fread(zf, buffer, readSize);
if (retval < readSize) {
ERROR_LOG(HLE, "Failed to read %d bytes from zip (%d) - archive corrupt?", (int)readSize, (int)retval);
delete[] buffer;
fclose(f);
zip_fclose(zf);
File::Delete(outFilename.c_str());
return false;
}
size_t written = fwrite(buffer, 1, readSize, f);
if (written != readSize) {
ERROR_LOG(HLE, "Wrote %d bytes out of %d - Disk full?", (int)written, (int)readSize);
delete[] buffer;
fclose(f);
zip_fclose(zf);
File::Delete(outFilename.c_str());
return false;
}
pos += readSize;
*bytesCopied += readSize;
installProgress_ = (float)*bytesCopied / (float)allBytes;
}
zip_fclose(zf);
fclose(f);
delete[] buffer;
return true;
} else {
ERROR_LOG(HLE, "Failed to open file for writing");
return false;
}
}
bool GameManager::InstallMemstickGame(struct zip *z, std::string zipfile, std::string pspGame, int numFiles, int stripChars, bool deleteAfter) {
size_t allBytes = 0;
size_t bytesCopied = 0;
I18NCategory *sy = GetI18NCategory("System");
// Create all the directories first in one pass
std::set<std::string> createdDirs;
for (int i = 0; i < numFiles; i++) {
const char *fn = zip_get_name(z, i, 0);
@@ -224,53 +354,16 @@ bool GameManager::InstallGame(std::string zipfile, bool deleteAfter) {
// Note that we do NOT write files that are not in a directory, to avoid random
// README files etc.
if (strchr(fn, '/') != 0) {
struct zip_stat zstat;
zip_stat_index(z, i, 0, &zstat);
size_t size = zstat.size;
fn += stripChars;
std::string outFilename = pspGame + fn;
bool isDir = *outFilename.rbegin() == '/';
if (isDir)
continue;
if (i < 10) {
INFO_LOG(HLE, "Writing %i bytes to %s", (int)size, outFilename.c_str());
}
zip_file *zf = zip_fopen_index(z, i, 0);
FILE *f = File::OpenCFile(outFilename, "wb");
if (f) {
size_t pos = 0;
const size_t blockSize = 1024 * 128;
u8 *buffer = new u8[blockSize];
while (pos < size) {
size_t bs = std::min(blockSize, size - pos);
zip_fread(zf, buffer, bs);
size_t written = fwrite(buffer, 1, bs, f);
if (written != bs) {
ERROR_LOG(HLE, "Wrote %i bytes out of %i - Disk full?", (int)written, (int)bs);
delete [] buffer;
buffer = 0;
fclose(f);
zip_fclose(zf);
File::Delete(outFilename.c_str());
// Yes it's a goto. Sue me. I think it's appropriate here.
goto bail;
}
pos += bs;
bytesCopied += bs;
installProgress_ = (float)bytesCopied / (float)allBytes;
// printf("Progress: %f\n", installProgress_);
}
zip_fclose(zf);
fclose(f);
createdFiles.push_back(outFilename);
delete [] buffer;
if (!ExtractFile(z, i, outFilename, &bytesCopied, allBytes)) {
goto bail;
} else {
ERROR_LOG(HLE, "Failed to open file for writing");
createdFiles.push_back(outFilename);
}
}
}
@@ -293,9 +386,7 @@ bail:
installProgress_ = 0.0f;
installInProgress_ = false;
installError_ = sy->T("Storage full");
if (deleteAfter) {
File::Delete(zipfile.c_str());
}
// We don't delete the original in this case. Try to delete the files we created so far.
for (size_t i = 0; i < createdFiles.size(); i++) {
File::Delete(createdFiles[i].c_str());
}
@@ -306,15 +397,64 @@ bail:
return false;
}
bool GameManager::InstallGameOnThread(std::string zipFile, bool deleteAfter) {
bool GameManager::InstallZippedISO(struct zip *z, int isoFileIndex, std::string zipfile, bool deleteAfter) {
// Let's place the output file in the currently selected Games directory.
std::string fn = zip_get_name(z, isoFileIndex, 0);
size_t nameOffset = fn.rfind('/');
if (nameOffset == std::string::npos) {
nameOffset = 0;
} else {
nameOffset++;
}
size_t allBytes = 1;
struct zip_stat zstat;
if (zip_stat_index(z, isoFileIndex, 0, &zstat) >= 0) {
allBytes += zstat.size;
}
std::string outputISOFilename = g_Config.currentDirectory + "/" + fn.substr(nameOffset);
size_t bytesCopied = 0;
if (ExtractFile(z, isoFileIndex, outputISOFilename, &bytesCopied, allBytes)) {
ILOG("Successfully extracted ISO file to '%s'", outputISOFilename.c_str());
}
zip_close(z);
if (deleteAfter) {
File::Delete(zipfile.c_str());
}
z = 0;
installProgress_ = 1.0f;
installInProgress_ = false;
installError_ = "";
InstallDone();
return true;
}
bool GameManager::InstallGameOnThread(std::string url, std::string fileName, bool deleteAfter) {
if (installInProgress_) {
return false;
}
installThread_.reset(new std::thread(std::bind(&GameManager::InstallGame, this, zipFile, deleteAfter)));
installThread_.reset(new std::thread(std::bind(&GameManager::InstallGame, this, url, fileName, deleteAfter)));
installThread_->detach();
return true;
}
bool GameManager::InstallRawISO(const std::string &file, const std::string &originalName, bool deleteAfter) {
std::string destPath = g_Config.currentDirectory + "/" + originalName;
// TODO: To save disk space, we should probably attempt a move first.
if (File::Copy(file, destPath)) {
if (deleteAfter) {
File::Delete(file.c_str());
}
}
installProgress_ = 1.0f;
installInProgress_ = false;
installError_ = "";
InstallDone();
return true;
}
void GameManager::InstallDone() {
if (installThread_.get() != 0) {
installThread_.reset();
+23 -2
View File
@@ -31,6 +31,8 @@ enum class GameManagerState {
INSTALLING,
};
struct zip;
class GameManager {
public:
GameManager();
@@ -64,11 +66,15 @@ public:
}
// Only returns false if there's already an installation in progress.
bool InstallGameOnThread(std::string zipFile, bool deleteAfter);
bool InstallGameOnThread(std::string url, std::string tempFileName, bool deleteAfter);
private:
bool InstallGame(std::string zipfile, bool deleteAfter = false);
bool InstallGame(const std::string &url, const std::string &tempFileName, bool deleteAfter);
bool InstallMemstickGame(struct zip *z, std::string zipFile, std::string pspGame, int numFiles, int stripChars, bool deleteAfter);
bool InstallZippedISO(struct zip *z, int isoFileIndex, std::string zipfile, bool deleteAfter);
bool InstallRawISO(const std::string &zipFile, const std::string &originalName, bool deleteAfter);
void InstallDone();
bool ExtractFile(struct zip *z, int file_index, std::string outFilename, size_t *bytesCopied, size_t allBytes);
std::string GetTempFilename() const;
std::shared_ptr<http::Download> curDownload_;
@@ -79,3 +85,18 @@ private:
};
extern GameManager g_GameManager;
enum class ZipFileContents {
UNKNOWN,
PSP_GAME_DIR,
ISO_FILE,
};
struct ZipFileInfo {
int numFiles;
int stripChars; // for PSP game
int isoFileIndex; // for ISO
};
ZipFileContents DetectZipFileContents(struct zip *z, ZipFileInfo *info);
ZipFileContents DetectZipFileContents(std::string fileName, ZipFileInfo *info);
+17 -78
View File
@@ -784,9 +784,6 @@ void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, GEBu
float v0 = 0.0f, v1 = 1.0f;
MakePixelTexture(srcPixels, srcPixelFormat, srcStride, 512, 272, u1, v1);
struct CardboardSettings cardboardSettings;
GetCardboardSettings(&cardboardSettings);
// This might draw directly at the backbuffer (if so, applyPostShader is set) so if there's a post shader, we need to apply it here.
// Should try to unify this path with the regular path somehow, but this simple solution works for most of the post shaders
// (it always runs at output resolution so FXAA may look odd).
@@ -812,18 +809,9 @@ void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, GEBu
DrawTextureFlags flags = g_Config.iBufFilter == SCALE_LINEAR ? DRAWTEX_LINEAR : DRAWTEX_NEAREST;
flags = flags | DRAWTEX_TO_BACKBUFFER;
if (cardboardSettings.enabled) {
// Left Eye Image
SetViewport2D(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, ROTATION_LOCKED_HORIZONTAL, flags | DRAWTEX_KEEP_TEX);
// Right Eye Image
SetViewport2D(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, ROTATION_LOCKED_HORIZONTAL, flags);
} else {
// Fullscreen Image
SetViewport2D(0, 0, pixelWidth_, pixelHeight_);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, uvRotation, flags);
}
// Fullscreen Image
SetViewport2D(0, 0, pixelWidth_, pixelHeight_);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, uvRotation, flags);
gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE);
}
@@ -868,9 +856,6 @@ void FramebufferManagerCommon::CopyDisplayToOutput() {
u32 offsetX = 0;
u32 offsetY = 0;
CardboardSettings cardboardSettings;
GetCardboardSettings(&cardboardSettings);
VirtualFramebuffer *vfb = GetVFBAt(displayFramebufPtr_);
if (!vfb) {
// Let's search for a framebuf within this range. Note that we also look for
@@ -986,19 +971,9 @@ void FramebufferManagerCommon::CopyDisplayToOutput() {
// flip V.
if (needBackBufferYSwap_)
std::swap(v0, v1);
if (cardboardSettings.enabled) {
// Left Eye Image
SetViewport2D(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, ROTATION_LOCKED_HORIZONTAL, flags | DRAWTEX_KEEP_TEX);
// Right Eye Image
SetViewport2D(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, ROTATION_LOCKED_HORIZONTAL, flags);
} else {
// Fullscreen Image
SetViewport2D(0, 0, pixelWidth_, pixelHeight_);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, uvRotation, flags);
}
// Fullscreen Image
SetViewport2D(0, 0, pixelWidth_, pixelHeight_);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, uvRotation, flags);
} else if (usePostShader_ && extraFBOs_.size() == 1 && !postShaderAtOutputResolution_) {
// An additional pass, post-processing shader to the extra FBO.
shaderManager_->DirtyLastShader(); // dirty lastShader_
@@ -1033,19 +1008,9 @@ void FramebufferManagerCommon::CopyDisplayToOutput() {
Bind2DShader();
flags = (!postShaderIsUpscalingFilter_ && g_Config.iBufFilter == SCALE_LINEAR) ? DRAWTEX_LINEAR : DRAWTEX_NEAREST;
flags = flags | DRAWTEX_TO_BACKBUFFER;
if (g_Config.bEnableCardboard) {
// Left Eye Image
SetViewport2D(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, ROTATION_LOCKED_HORIZONTAL, flags | DRAWTEX_KEEP_TEX);
// Right Eye Image
SetViewport2D(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, ROTATION_LOCKED_HORIZONTAL, flags);
} else {
// Fullscreen Image
SetViewport2D(0, 0, pixelWidth_, pixelHeight_);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, uvRotation, flags);
}
// Fullscreen Image
SetViewport2D(0, 0, pixelWidth_, pixelHeight_);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, uvRotation, flags);
} else {
shaderManager_->DirtyLastShader(); // dirty lastShader_ BEFORE drawing
draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR });
@@ -1061,19 +1026,9 @@ void FramebufferManagerCommon::CopyDisplayToOutput() {
PostShaderUniforms uniforms{};
CalculatePostShaderUniforms(vfb->bufferWidth, vfb->bufferHeight, vfb->renderWidth, vfb->renderHeight, &uniforms);
BindPostShader(uniforms);
if (g_Config.bEnableCardboard) {
// Left Eye Image
SetViewport2D(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, ROTATION_LOCKED_HORIZONTAL, flags | DRAWTEX_KEEP_TEX);
// Right Eye Image
SetViewport2D(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, ROTATION_LOCKED_HORIZONTAL, flags);
} else {
// Fullscreen Image
SetViewport2D(0, 0, pixelWidth_, pixelHeight_);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, uvRotation, flags);
}
// Fullscreen Image
SetViewport2D(0, 0, pixelWidth_, pixelHeight_);
DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, uvRotation, flags);
}
}
else if (useBufferedRendering_) {
@@ -1843,27 +1798,6 @@ void FramebufferManagerCommon::CalculatePostShaderUniforms(int bufferWidth, int
uniforms->video = textureCache_->VideoIsPlaying();
}
void FramebufferManagerCommon::GetCardboardSettings(CardboardSettings *cardboardSettings) {
// Calculate Cardboard Settings
float cardboardScreenScale = g_Config.iCardboardScreenSize / 100.0f;
float cardboardScreenWidth = pixelWidth_ / 2.0f * cardboardScreenScale;
float cardboardScreenHeight = pixelHeight_ / 2.0f * cardboardScreenScale;
float cardboardMaxXShift = (pixelWidth_ / 2.0f - cardboardScreenWidth) / 2.0f;
float cardboardUserXShift = g_Config.iCardboardXShift / 100.0f * cardboardMaxXShift;
float cardboardLeftEyeX = cardboardMaxXShift + cardboardUserXShift;
float cardboardRightEyeX = pixelWidth_ / 2.0f + cardboardMaxXShift - cardboardUserXShift;
float cardboardMaxYShift = pixelHeight_ / 2.0f - cardboardScreenHeight / 2.0f;
float cardboardUserYShift = g_Config.iCardboardYShift / 100.0f * cardboardMaxYShift;
float cardboardScreenY = cardboardMaxYShift + cardboardUserYShift;
cardboardSettings->enabled = g_Config.bEnableCardboard;
cardboardSettings->leftEyeXPosition = cardboardLeftEyeX;
cardboardSettings->rightEyeXPosition = cardboardRightEyeX;
cardboardSettings->screenYPosition = cardboardScreenY;
cardboardSettings->screenWidth = cardboardScreenWidth;
cardboardSettings->screenHeight = cardboardScreenHeight;
}
Draw::Framebuffer *FramebufferManagerCommon::GetTempFBO(TempFBO reason, u16 w, u16 h, Draw::FBColorDepth depth) {
u64 key = ((u64)reason << 48) | ((u64)depth << 32) | ((u32)w << 16) | h;
auto it = tempFBOs_.find(key);
@@ -2150,6 +2084,11 @@ void FramebufferManagerCommon::DownloadFramebufferForClut(u32 fb_address, u32 lo
int w = std::min(pixels % vfb->fb_stride, (int)vfb->width);
int h = std::min((pixels + vfb->fb_stride - 1) / vfb->fb_stride, (int)vfb->height);
if (w == 0 && h > 0) {
// Exactly aligned (means pixels == vfb->fb_stride, so modulus gave zero.)
w = std::min(vfb->fb_stride, (int)vfb->width);
}
// We might still have a pending draw to the fb in question, flush if so.
FlushBeforeCopy();
-12
View File
@@ -46,15 +46,6 @@ namespace Draw {
class Framebuffer;
}
struct CardboardSettings {
bool enabled;
float leftEyeXPosition;
float rightEyeXPosition;
float screenYPosition;
float screenWidth;
float screenHeight;
};
class VulkanFBO;
struct PostShaderUniforms {
@@ -325,9 +316,6 @@ protected:
virtual void Bind2DShader() = 0;
virtual void BindPostShader(const PostShaderUniforms &uniforms) = 0;
// Cardboard Settings Calculator
void GetCardboardSettings(CardboardSettings *cardboardSettings);
bool UpdateSize();
void SetNumExtraFBOs(int num);
+4
View File
@@ -268,6 +268,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -296,6 +297,7 @@
<PreprocessorDefinitions>USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_64=1;_M_X64=1;_LIB;NDEBUG;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StringPooling>true</StringPooling>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -324,6 +326,7 @@
<PreprocessorDefinitions>USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_64=1;_LIB;NDEBUG;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StringPooling>true</StringPooling>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -352,6 +355,7 @@
<PreprocessorDefinitions>USING_WIN_UI;_CRT_SECURE_NO_WARNINGS;WIN32;_ARCH_32=1;_LIB;NDEBUG;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StringPooling>true</StringPooling>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
+14 -4
View File
@@ -720,6 +720,8 @@ u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer<Ps
if (currentList->state != PSP_GE_DL_STATE_PAUSED)
return SCE_KERNEL_ERROR_INVALID_VALUE;
currentList->state = PSP_GE_DL_STATE_QUEUED;
// Make sure we clear the signal so we don't try to pause it again.
currentList->signal = PSP_GE_SIGNAL_NONE;
}
dl.state = PSP_GE_DL_STATE_PAUSED;
@@ -789,8 +791,7 @@ u32 GPUCommon::Continue() {
if (currentList->state == PSP_GE_DL_STATE_PAUSED)
{
if (!isbreak)
{
if (!isbreak) {
// TODO: Supposedly this returns SCE_KERNEL_ERROR_BUSY in some case, previously it had
// currentList->signal == PSP_GE_SIGNAL_HANDLER_PAUSE, but it doesn't reproduce.
@@ -802,9 +803,10 @@ u32 GPUCommon::Continue() {
// We have a list now, so it's not complete.
drawCompleteTicks = (u64)-1;
}
else
} else {
currentList->state = PSP_GE_DL_STATE_QUEUED;
currentList->signal = PSP_GE_SIGNAL_NONE;
}
}
else if (currentList->state == PSP_GE_DL_STATE_RUNNING)
{
@@ -2453,6 +2455,14 @@ void GPUCommon::InterruptEnd(int listid) {
}
dl.waitTicks = 0;
__GeTriggerWait(GPU_SYNC_LIST, listid);
// Make sure the list isn't still queued since it's now completed.
if (!dlQueue.empty()) {
if (listid == dlQueue.front())
PopDLQueue();
else
dlQueue.remove(listid);
}
}
ProcessDLQueue();
+91 -33
View File
@@ -17,15 +17,12 @@ class GLRenderManager;
#if defined(USING_EGL)
// TODO: Move these into the class.
static EGLDisplay g_eglDisplay = NULL;
static EGLContext g_eglContext = NULL;
static EGLSurface g_eglSurface = NULL;
#ifdef USING_FBDEV
static EGLNativeDisplayType g_Display = NULL;
#else
static Display* g_Display = NULL;
#endif
static NativeWindowType g_Window = (NativeWindowType)NULL;
static EGLDisplay g_eglDisplay = EGL_NO_DISPLAY;
static EGLContext g_eglContext = nullptr;
static EGLSurface g_eglSurface = nullptr;
static EGLNativeDisplayType g_Display = nullptr;
static bool g_XDisplayOpen = false;
static EGLNativeWindowType g_Window = (EGLNativeWindowType)nullptr;
int CheckEGLErrors(const char *file, int line) {
EGLenum error;
@@ -59,18 +56,82 @@ int CheckEGLErrors(const char *file, int line) {
return 1; \
}
int8_t EGL_Open() {
#ifdef USING_FBDEV
g_Display = ((EGLNativeDisplayType)0);
#else
if ((g_Display = XOpenDisplay(NULL)) == NULL)
EGL_ERROR("Unable to get display!", false);
#endif
if ((g_eglDisplay = eglGetDisplay((NativeDisplayType)g_Display)) == EGL_NO_DISPLAY)
static bool EGL_OpenInit() {
if ((g_eglDisplay = eglGetDisplay(g_Display)) == EGL_NO_DISPLAY) {
EGL_ERROR("Unable to create EGL display.", true);
if (eglInitialize(g_eglDisplay, NULL, NULL) != EGL_TRUE)
return false;
}
if (eglInitialize(g_eglDisplay, NULL, NULL) != EGL_TRUE) {
EGL_ERROR("Unable to initialize EGL display.", true);
return 0;
eglTerminate(g_eglDisplay);
g_eglDisplay = EGL_NO_DISPLAY;
return false;
}
return true;
}
static int8_t EGL_Open(SDL_Window *window) {
#if defined(USING_FBDEV)
g_Display = (EGLNativeDisplayType)nullptr;
g_Window = (EGLNativeWindowType)nullptr;
#elif defined(__APPLE__)
g_Display = (EGLNativeDisplayType)XOpenDisplay(nullptr);
g_XDisplayOpen = g_Display != nullptr;
if (!g_XDisplayOpen)
EGL_ERROR("Unable to get display!", false);
g_Window = (EGLNativeWindowType)nullptr;
#else
// Get the SDL window native handle
SDL_SysWMinfo sysInfo{};
SDL_VERSION(&sysInfo.version);
if (!SDL_GetWindowWMInfo(window, &sysInfo)) {
printf("ERROR: Unable to retrieve native window handle\n");
g_Display = (EGLNativeDisplayType)XOpenDisplay(nullptr);
g_XDisplayOpen = g_Display != nullptr;
if (!g_XDisplayOpen)
EGL_ERROR("Unable to get display!", false);
g_Window = (EGLNativeWindowType)nullptr;
} else {
switch (sysInfo.subsystem) {
case SDL_SYSWM_X11:
g_Display = (EGLNativeDisplayType)sysInfo.info.x11.display;
g_Window = (EGLNativeWindowType)sysInfo.info.x11.window;
break;
#if defined(SDL_VIDEO_DRIVER_DIRECTFB)
case SDL_SYSWM_DIRECTFB:
g_Display = (EGLNativeDisplayType)EGL_DEFAULT_DISPLAY;
g_Window = (EGLNativeWindowType)sysInfo.info.dfb.surface;
break;
#endif
#if SDL_VERSION_ATLEAST(2, 0, 2) && defined(SDL_VIDEO_DRIVER_WAYLAND)
case SDL_SYSWM_WAYLAND:
g_Display = (EGLNativeDisplayType)sysInfo.info.wl.display;
g_Window = (EGLNativeWindowType)sysInfo.info.wl.shell_surface;
break;
#endif
#if SDL_VERSION_ATLEAST(2, 0, 5) && defined(SDL_VIDEO_DRIVER_VIVANTE)
case SDL_SYSWM_VIVANTE:
g_Display = (EGLNativeDisplayType)sysInfo.info.vivante.display;
g_Window = (EGLNativeWindowType)sysInfo.info.vivante.window;
break;
#endif
}
if (!EGL_OpenInit()) {
// Let's try again with X11.
g_Display = (EGLNativeDisplayType)XOpenDisplay(nullptr);
g_XDisplayOpen = g_Display != nullptr;
if (!g_XDisplayOpen)
EGL_ERROR("Unable to get display!", false);
g_Window = (EGLNativeWindowType)nullptr;
}
}
#endif
if (g_eglDisplay == EGL_NO_DISPLAY)
EGL_OpenInit();
return g_eglDisplay == EGL_NO_DISPLAY ? 1 : 0;
}
#ifndef EGL_OPENGL_ES3_BIT_KHR
@@ -193,15 +254,6 @@ int8_t EGL_Init(SDL_Window *window) {
return 1;
}
#if !defined(USING_FBDEV) && !defined(__APPLE__)
// Get the SDL window handle
SDL_SysWMinfo sysInfo; //Will hold our Window information
SDL_VERSION(&sysInfo.version); //Set SDL version
SDL_GetWindowWMInfo(window, &sysInfo);
g_Window = (NativeWindowType)sysInfo.info.x11.window;
#else
g_Window = (NativeWindowType)NULL;
#endif
g_eglSurface = eglCreateWindowSurface(g_eglDisplay, eglConfig, g_Window, nullptr);
if (g_eglSurface == EGL_NO_SURFACE) {
EGL_ERROR("Unable to create EGL surface!", true);
@@ -217,7 +269,7 @@ int8_t EGL_Init(SDL_Window *window) {
}
void EGL_Close() {
if (g_eglDisplay != NULL) {
if (g_eglDisplay != EGL_NO_DISPLAY) {
eglMakeCurrent(g_eglDisplay, NULL, NULL, EGL_NO_CONTEXT);
if (g_eglContext != NULL) {
eglDestroyContext(g_eglDisplay, g_eglContext);
@@ -226,13 +278,15 @@ void EGL_Close() {
eglDestroySurface(g_eglDisplay, g_eglSurface);
}
eglTerminate(g_eglDisplay);
g_eglDisplay = NULL;
g_eglDisplay = EGL_NO_DISPLAY;
}
if (g_Display != NULL) {
if (g_Display != nullptr) {
#if !defined(USING_FBDEV)
XCloseDisplay(g_Display);
if (g_XDisplayOpen)
XCloseDisplay((Display *)g_Display);
#endif
g_Display = NULL;
g_XDisplayOpen = false;
g_Display = nullptr;
}
g_eglSurface = NULL;
g_eglContext = NULL;
@@ -320,6 +374,10 @@ int SDLGLGraphicsContext::Init(SDL_Window *&window, int x, int y, int mode, std:
SDL_ShowWindow(window);
#ifdef USING_EGL
if (EGL_Open(window) != 0) {
printf("EGL_Open() failed\n");
return 1;
}
if (EGL_Init(window) != 0) {
printf("EGL_Init() failed\n");
return 1;
-7
View File
@@ -7,11 +7,6 @@
#include "gfx/gl_common.h"
#include "Common/GraphicsContext.h"
// TODO: Move this to a better place.
#if defined(USING_EGL)
int8_t EGL_Open();
#endif
class SDLGLGraphicsContext : public DummyGraphicsContext {
public:
SDLGLGraphicsContext() {
@@ -54,5 +49,3 @@ private:
SDL_GLContext glContext = nullptr;
GLRenderManager *renderManager_ = nullptr;
};
-6
View File
@@ -426,12 +426,6 @@ int main(int argc, char *argv[]) {
}
}
// TODO: How do we get this into the GraphicsContext?
#ifdef USING_EGL
if (EGL_Open())
return 1;
#endif
// Get the video info before doing anything else, so we don't get skewed resolution results.
// TODO: support multiple displays correctly
SDL_DisplayMode displayMode;
-12
View File
@@ -466,18 +466,6 @@ void GameSettingsScreen::CreateViews() {
static const char *bufFilters[] = { "Linear", "Nearest", };
graphicsSettings->Add(new PopupMultiChoice(&g_Config.iBufFilter, gr->T("Screen Scaling Filter"), bufFilters, 1, ARRAY_SIZE(bufFilters), gr->GetName(), screenManager()));
#ifdef __ANDROID__
graphicsSettings->Add(new ItemHeader(gr->T("Cardboard Settings", "Cardboard Settings")));
CheckBox *cardboardMode = graphicsSettings->Add(new CheckBox(&g_Config.bEnableCardboard, gr->T("Enable Cardboard", "Enable Cardboard")));
cardboardMode->SetDisabledPtr(&g_Config.bSoftwareRendering);
PopupSliderChoice * cardboardScreenSize = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iCardboardScreenSize, 30, 100, gr->T("Cardboard Screen Size", "Screen Size (in % of the viewport)"), 1, screenManager(), gr->T("% of viewport")));
cardboardScreenSize->SetDisabledPtr(&g_Config.bSoftwareRendering);
PopupSliderChoice *cardboardXShift = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iCardboardXShift, -100, 100, gr->T("Cardboard Screen X Shift", "X Shift (in % of the void)"), 1, screenManager(), gr->T("% of the void")));
cardboardXShift->SetDisabledPtr(&g_Config.bSoftwareRendering);
PopupSliderChoice *cardboardYShift = graphicsSettings->Add(new PopupSliderChoice(&g_Config.iCardboardYShift, -100, 100, gr->T("Cardboard Screen Y Shift", "Y Shift (in % of the void)"), 1, screenManager(), gr->T("% of the void")));
cardboardYShift->SetDisabledPtr(&g_Config.bSoftwareRendering);
#endif
graphicsSettings->Add(new ItemHeader(gr->T("Hack Settings")));
static const char *bloomHackOptions[] = { "Off", "Safe", "Balanced", "Aggressive" };
+31 -18
View File
@@ -42,24 +42,34 @@ void InstallZipScreen::CreateViews() {
root_ = new LinearLayout(ORIENT_HORIZONTAL);
ViewGroup *leftColumn = new AnchorLayout(new LinearLayoutParams(1.0f));
root_->Add(leftColumn);
std::string shortFilename = GetFilenameFromPath(zipPath_);
leftColumn->Add(new TextView(iz->T("Install game from ZIP file?"), ALIGN_LEFT, false, new AnchorLayoutParams(10, 10, NONE, NONE)));
leftColumn->Add(new TextView(shortFilename, ALIGN_LEFT, false, new AnchorLayoutParams(10, 60, NONE, NONE)));
doneView_ = leftColumn->Add(new TextView("", new AnchorLayoutParams(10, 120, NONE, NONE)));
progressBar_ = leftColumn->Add(new ProgressBar(new AnchorLayoutParams(10, 200, 200, NONE)));
ViewGroup *rightColumnItems = new LinearLayout(ORIENT_VERTICAL, new LinearLayoutParams(300, FILL_PARENT, actionMenuMargins));
root_->Add(leftColumn);
root_->Add(rightColumnItems);
installChoice_ = rightColumnItems->Add(new Choice(iz->T("Install")));
installChoice_->OnClick.Handle(this, &InstallZipScreen::OnInstall);
backChoice_ = rightColumnItems->Add(new Choice(di->T("Back")));
backChoice_->OnClick.Handle<UIScreen>(this, &UIScreen::OnOK); // OK so that EmuScreen will handle it right
std::string shortFilename = GetFilenameFromPath(zipPath_);
// TODO: Do in the background?
ZipFileInfo zipInfo;
ZipFileContents contents = DetectZipFileContents(zipPath_, &zipInfo);
rightColumnItems->Add(new CheckBox(&deleteZipFile_, iz->T("Delete ZIP file")));
if (contents == ZipFileContents::ISO_FILE || contents == ZipFileContents::PSP_GAME_DIR) {
std::string question = iz->T("Install game from ZIP file?");
leftColumn->Add(new TextView(question, ALIGN_LEFT, false, new AnchorLayoutParams(10, 10, NONE, NONE)));
leftColumn->Add(new TextView(shortFilename, ALIGN_LEFT, false, new AnchorLayoutParams(10, 60, NONE, NONE)));
doneView_ = leftColumn->Add(new TextView("", new AnchorLayoutParams(10, 120, NONE, NONE)));
progressBar_ = leftColumn->Add(new ProgressBar(new AnchorLayoutParams(10, 200, 200, NONE)));
installChoice_ = rightColumnItems->Add(new Choice(iz->T("Install")));
installChoice_->OnClick.Handle(this, &InstallZipScreen::OnInstall);
backChoice_ = rightColumnItems->Add(new Choice(di->T("Back")));
backChoice_->OnClick.Handle<UIScreen>(this, &UIScreen::OnOK); // OK so that EmuScreen will handle it right
rightColumnItems->Add(new CheckBox(&deleteZipFile_, iz->T("Delete ZIP file")));
} else {
leftColumn->Add(new TextView(iz->T("Zip file does not contain PSP software"), ALIGN_LEFT, false, new AnchorLayoutParams(10, 10, NONE, NONE)));
backChoice_ = rightColumnItems->Add(new Choice(di->T("Back")));
backChoice_->OnClick.Handle<UIScreen>(this, &UIScreen::OnOK); // OK so that EmuScreen will handle it right
}
}
bool InstallZipScreen::key(const KeyInput &key) {
@@ -71,7 +81,7 @@ bool InstallZipScreen::key(const KeyInput &key) {
}
UI::EventReturn InstallZipScreen::OnInstall(UI::EventParams &params) {
if (g_GameManager.InstallGameOnThread(zipPath_, deleteZipFile_)) {
if (g_GameManager.InstallGameOnThread(zipPath_, zipPath_, deleteZipFile_)) {
installStarted_ = true;
installChoice_->SetEnabled(false);
}
@@ -87,13 +97,16 @@ void InstallZipScreen::update() {
progressBar_->SetProgress(g_GameManager.GetCurrentInstallProgressPercentage());
backChoice_->SetEnabled(false);
} else {
progressBar_->SetVisibility(V_GONE);
if (progressBar_)
progressBar_->SetVisibility(V_GONE);
backChoice_->SetEnabled(true);
std::string err = g_GameManager.GetInstallError();
if (!err.empty()) {
doneView_->SetText(iz->T(err.c_str()));
if (doneView_)
doneView_->SetText(iz->T(err.c_str()));
} else if (installStarted_) {
doneView_->SetText(iz->T("Installed!"));
if (doneView_)
doneView_->SetText(iz->T("Installed!"));
MainScreen::showHomebrewTab = true;
}
}
+7 -7
View File
@@ -26,7 +26,7 @@
class InstallZipScreen : public UIDialogScreenWithBackground {
public:
InstallZipScreen(std::string zipPath) : installChoice_(0), doneView_(0), zipPath_(zipPath), installStarted_(false), deleteZipFile_(false) {}
InstallZipScreen(std::string zipPath) : zipPath_(zipPath) {}
virtual void update() override;
virtual bool key(const KeyInput &key) override;
@@ -36,12 +36,12 @@ protected:
private:
UI::EventReturn OnInstall(UI::EventParams &params);
UI::Choice *installChoice_;
UI::Choice *backChoice_;
UI::ProgressBar *progressBar_;
UI::TextView *doneView_;
UI::Choice *installChoice_ = nullptr;
UI::Choice *backChoice_ = nullptr;
UI::ProgressBar *progressBar_ = nullptr;
UI::TextView *doneView_ = nullptr;
std::string zipPath_;
bool installStarted_;
bool deleteZipFile_;
bool installStarted_ = false;
bool deleteZipFile_ = false;
};
+8 -5
View File
@@ -284,13 +284,16 @@ void ProductView::Update() {
}
UI::EventReturn ProductView::OnInstall(UI::EventParams &e) {
std::string zipUrl;
std::string fileUrl;
if (entry_.downloadURL.empty()) {
// Construct the URL, easy to predict from our server
zipUrl = storeBaseUrl + "files/" + entry_.file + ".zip";
std::string shortName = entry_.file;
if (shortName.find('.') == std::string::npos)
shortName += ".zip";
fileUrl = storeBaseUrl + "files/" + shortName;
} else {
// Use the provided URL, for external hosting.
zipUrl = entry_.downloadURL;
fileUrl = entry_.downloadURL;
}
if (installButton_) {
installButton_->SetEnabled(false);
@@ -298,8 +301,8 @@ UI::EventReturn ProductView::OnInstall(UI::EventParams &e) {
if (cancelButton_) {
cancelButton_->SetVisibility(UI::V_VISIBLE);
}
INFO_LOG(SYSTEM, "Triggering install of %s", zipUrl.c_str());
g_GameManager.DownloadAndInstall(zipUrl);
INFO_LOG(SYSTEM, "Triggering install of '%s'", fileUrl.c_str());
g_GameManager.DownloadAndInstall(fileUrl);
return UI::EVENT_DONE;
}
+4
View File
@@ -317,6 +317,7 @@
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<AdditionalOptions>$(EXTERNAL_COMPILE_OPTIONS)</AdditionalOptions>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -347,6 +348,7 @@
<AdditionalOptions>$(EXTERNAL_COMPILE_OPTIONS)</AdditionalOptions>
<OmitFramePointers>false</OmitFramePointers>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -377,6 +379,7 @@
<AdditionalOptions>$(EXTERNAL_COMPILE_OPTIONS)</AdditionalOptions>
<OmitFramePointers>false</OmitFramePointers>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -407,6 +410,7 @@
<AdditionalOptions>$(EXTERNAL_COMPILE_OPTIONS)</AdditionalOptions>
<OmitFramePointers>false</OmitFramePointers>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
+3 -7
View File
@@ -38,7 +38,7 @@
UWPHost::UWPHost() {
// add first XInput device to respond
input.push_back(std::shared_ptr<InputDevice>(new XinputDevice()));
input.push_back(std::make_unique<XinputDevice>());
}
UWPHost::~UWPHost() {
@@ -86,14 +86,10 @@ void UWPHost::SetDebugMode(bool mode) {
}
void UWPHost::PollControllers() {
bool doPad = true;
for (auto iter = this->input.begin(); iter != this->input.end(); iter++)
for (const auto& device : this->input)
{
auto device = *iter;
if (!doPad && device->IsPad())
continue;
if (device->UpdateState() == InputDevice::UPDATESTATE_SKIP_PAD)
doPad = false;
break;
}
/*
+1 -1
View File
@@ -45,5 +45,5 @@ private:
void SetConsolePosition();
void UpdateConsolePosition();
std::list<std::shared_ptr<InputDevice>> input;
std::list<std::unique_ptr<InputDevice>> input;
};
+2 -3
View File
@@ -24,7 +24,7 @@
#include "InputDevice.h"
#include "dinput.h"
class DinputDevice :
class DinputDevice final :
public InputDevice
{
public:
@@ -32,8 +32,7 @@ public:
//getDevices(), enumerates all devices if not done yet
DinputDevice(int devnum);
~DinputDevice();
virtual int UpdateState();
virtual bool IsPad() { return true; }
virtual int UpdateState() override;
static size_t getNumPads();
static void CheckDevices() {
needsCheck_ = true;
-1
View File
@@ -193,7 +193,6 @@ CGEDebugger::CGEDebugger(HINSTANCE _hInstance, HWND _hParent)
}
CGEDebugger::~CGEDebugger() {
DestroyWindow(displayList->GetHWND());
CleanupPrimPreview();
delete flags;
delete lighting;
+12 -30
View File
@@ -15,28 +15,21 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <list>
#include <thread>
#include <memory>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include "input/input_state.h"
#include "thread/threadutil.h"
#include "Core/Config.h"
#include "Core/Host.h"
#include "Windows/InputDevice.h"
#include "Windows/WindowsHost.h"
static volatile bool inputThreadStatus = false;
static volatile bool inputThreadEnabled = false;
static std::thread *inputThread = NULL;
static std::mutex inputMutex;
static std::condition_variable inputEndCond;
static bool focused = true;
static std::atomic_flag threadRunningFlag;
static std::thread inputThread;
static std::atomic_bool focused = true;
inline static void ExecuteInputPoll() {
if (host && (focused || !g_Config.bGamepadOnlyFocused)) {
if (host && (focused.load(std::memory_order_relaxed) || !g_Config.bGamepadOnlyFocused)) {
host->PollControllers();
}
}
@@ -47,40 +40,29 @@ static void RunInputThread() {
// NOTE: The keyboard and mouse buttons are handled via raw input, not here.
// This is mainly for controllers which need to be polled, instead of generating events.
while (inputThreadEnabled) {
while (threadRunningFlag.test_and_set(std::memory_order_relaxed)) {
ExecuteInputPoll();
// Try to update 250 times per second.
Sleep(4);
}
std::lock_guard<std::mutex> guard(inputMutex);
inputThreadStatus = false;
inputEndCond.notify_one();
}
void InputDevice::BeginPolling() {
std::lock_guard<std::mutex> guard(inputMutex);
inputThreadEnabled = true;
inputThread = new std::thread(&RunInputThread);
inputThread->detach();
threadRunningFlag.test_and_set(std::memory_order_relaxed);
inputThread = std::thread(&RunInputThread);
}
void InputDevice::StopPolling() {
inputThreadEnabled = false;
threadRunningFlag.clear(std::memory_order_relaxed);
std::unique_lock<std::mutex> guard(inputMutex);
if (inputThreadStatus) {
inputEndCond.wait(guard);
}
delete inputThread;
inputThread = NULL;
inputThread.join();
}
void InputDevice::GainFocus() {
focused = true;
focused.store(true, std::memory_order_relaxed);
}
void InputDevice::LoseFocus() {
focused = false;
focused.store(false, std::memory_order_relaxed);
}
-1
View File
@@ -26,7 +26,6 @@ class InputDevice {
public:
enum { UPDATESTATE_SKIP_PAD = 0x1234};
virtual int UpdateState() = 0;
virtual bool IsPad() = 0;
static void BeginPolling();
static void StopPolling();
-126
View File
@@ -1,126 +0,0 @@
#include "base/NativeApp.h"
#include "input/input_state.h"
#include "input/keycodes.h"
#include "util/const_map.h"
#include "KeyMap.h"
#include "KeyboardDevice.h"
#include "../Common/CommonTypes.h"
#include "../Common/CommonWindows.h"
// TODO: More keys need to be added, but this is more than
// a fair start.
std::map<int, int> windowsTransTable = InitConstMap<int, int>
('A', NKCODE_A)
('B', NKCODE_B)
('C', NKCODE_C)
('D', NKCODE_D)
('E', NKCODE_E)
('F', NKCODE_F)
('G', NKCODE_G)
('H', NKCODE_H)
('I', NKCODE_I)
('J', NKCODE_J)
('K', NKCODE_K)
('L', NKCODE_L)
('M', NKCODE_M)
('N', NKCODE_N)
('O', NKCODE_O)
('P', NKCODE_P)
('Q', NKCODE_Q)
('R', NKCODE_R)
('S', NKCODE_S)
('T', NKCODE_T)
('U', NKCODE_U)
('V', NKCODE_V)
('W', NKCODE_W)
('X', NKCODE_X)
('Y', NKCODE_Y)
('Z', NKCODE_Z)
('0', NKCODE_0)
('1', NKCODE_1)
('2', NKCODE_2)
('3', NKCODE_3)
('4', NKCODE_4)
('5', NKCODE_5)
('6', NKCODE_6)
('7', NKCODE_7)
('8', NKCODE_8)
('9', NKCODE_9)
(VK_OEM_PERIOD, NKCODE_PERIOD)
(VK_OEM_COMMA, NKCODE_COMMA)
(VK_NUMPAD0, NKCODE_NUMPAD_0)
(VK_NUMPAD1, NKCODE_NUMPAD_1)
(VK_NUMPAD2, NKCODE_NUMPAD_2)
(VK_NUMPAD3, NKCODE_NUMPAD_3)
(VK_NUMPAD4, NKCODE_NUMPAD_4)
(VK_NUMPAD5, NKCODE_NUMPAD_5)
(VK_NUMPAD6, NKCODE_NUMPAD_6)
(VK_NUMPAD7, NKCODE_NUMPAD_7)
(VK_NUMPAD8, NKCODE_NUMPAD_8)
(VK_NUMPAD9, NKCODE_NUMPAD_9)
(VK_DECIMAL, NKCODE_NUMPAD_DOT)
(VK_DIVIDE, NKCODE_NUMPAD_DIVIDE)
(VK_MULTIPLY, NKCODE_NUMPAD_MULTIPLY)
(VK_SUBTRACT, NKCODE_NUMPAD_SUBTRACT)
(VK_ADD, NKCODE_NUMPAD_ADD)
(VK_SEPARATOR, NKCODE_NUMPAD_COMMA)
(VK_OEM_MINUS, NKCODE_MINUS)
(VK_OEM_PLUS, NKCODE_PLUS)
(VK_LCONTROL, NKCODE_CTRL_LEFT)
(VK_RCONTROL, NKCODE_CTRL_RIGHT)
(VK_LSHIFT, NKCODE_SHIFT_LEFT)
(VK_RSHIFT, NKCODE_SHIFT_RIGHT)
(VK_LMENU, NKCODE_ALT_LEFT)
(VK_RMENU, NKCODE_ALT_RIGHT)
(VK_BACK, NKCODE_DEL) // yes! http://stackoverflow.com/questions/4886858/android-edittext-deletebackspace-key-event
(VK_SPACE, NKCODE_SPACE)
(VK_ESCAPE, NKCODE_ESCAPE)
(VK_UP, NKCODE_DPAD_UP)
(VK_INSERT, NKCODE_INSERT)
(VK_HOME, NKCODE_MOVE_HOME)
(VK_PRIOR, NKCODE_PAGE_UP)
(VK_NEXT, NKCODE_PAGE_DOWN)
(VK_DELETE, NKCODE_FORWARD_DEL)
(VK_END, NKCODE_MOVE_END)
(VK_TAB, NKCODE_TAB)
(VK_DOWN, NKCODE_DPAD_DOWN)
(VK_LEFT, NKCODE_DPAD_LEFT)
(VK_RIGHT, NKCODE_DPAD_RIGHT)
(VK_CAPITAL, NKCODE_CAPS_LOCK)
(VK_CLEAR, NKCODE_CLEAR)
(VK_SNAPSHOT, NKCODE_SYSRQ)
(VK_SCROLL, NKCODE_SCROLL_LOCK)
(VK_OEM_1, NKCODE_SEMICOLON)
(VK_OEM_2, NKCODE_SLASH)
(VK_OEM_3, NKCODE_GRAVE)
(VK_OEM_4, NKCODE_LEFT_BRACKET)
(VK_OEM_5, NKCODE_BACKSLASH)
(VK_OEM_6, NKCODE_RIGHT_BRACKET)
(VK_OEM_7, NKCODE_APOSTROPHE)
(VK_RETURN, NKCODE_ENTER)
(VK_APPS, NKCODE_MENU) // Context menu key, let's call this "menu".
(VK_PAUSE, NKCODE_BREAK)
(VK_F1, NKCODE_F1)
(VK_F2, NKCODE_F2)
(VK_F3, NKCODE_F3)
(VK_F4, NKCODE_F4)
(VK_F5, NKCODE_F5)
(VK_F6, NKCODE_F6)
(VK_F7, NKCODE_F7)
(VK_F8, NKCODE_F8)
(VK_F9, NKCODE_F9)
(VK_F10, NKCODE_F10)
(VK_F11, NKCODE_F11)
(VK_F12, NKCODE_F12)
(VK_OEM_102, NKCODE_EXT_PIPE)
(VK_LBUTTON, NKCODE_EXT_MOUSEBUTTON_1)
(VK_RBUTTON, NKCODE_EXT_MOUSEBUTTON_2)
(VK_MBUTTON, NKCODE_EXT_MOUSEBUTTON_3)
(VK_XBUTTON1, NKCODE_EXT_MOUSEBUTTON_4)
(VK_XBUTTON2, NKCODE_EXT_MOUSEBUTTON_5);
int KeyboardDevice::UpdateState() {
// Nothing to do, all done in WM_INPUT
return 0;
}
-14
View File
@@ -1,14 +0,0 @@
#pragma once
#include <map>
#include "InputDevice.h"
extern std::map<int, int> windowsTransTable;
class KeyboardDevice : public InputDevice {
public:
virtual int UpdateState();
virtual bool IsPad() { return false; }
private:
};
+1 -3
View File
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM">
@@ -740,7 +740,6 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|ARM'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="InputDevice.cpp" />
<ClCompile Include="KeyboardDevice.cpp" />
<ClCompile Include="MainWindowMenu.cpp" />
<ClCompile Include="RawInput.cpp" />
<ClCompile Include="TouchInputHandler.cpp" />
@@ -926,7 +925,6 @@
</ClInclude>
<ClInclude Include="GPU\WindowsGraphicsContext.h" />
<ClInclude Include="InputDevice.h" />
<ClInclude Include="KeyboardDevice.h" />
<ClInclude Include="MainWindowMenu.h" />
<ClInclude Include="RawInput.h" />
<ClInclude Include="TouchInputHandler.h" />
-6
View File
@@ -82,9 +82,6 @@
<ClCompile Include="XinputDevice.cpp">
<Filter>Windows\Input</Filter>
</ClCompile>
<ClCompile Include="KeyboardDevice.cpp">
<Filter>Windows\Input</Filter>
</ClCompile>
<ClCompile Include="InputDevice.cpp">
<Filter>Windows\Input</Filter>
</ClCompile>
@@ -246,9 +243,6 @@
<ClInclude Include="XinputDevice.h">
<Filter>Windows\Input</Filter>
</ClInclude>
<ClInclude Include="KeyboardDevice.h">
<Filter>Windows\Input</Filter>
</ClInclude>
<ClInclude Include="stdafx.h" />
<ClInclude Include="..\android\jni\ArmEmitterTest.h">
<Filter>Other Platforms</Filter>
+113 -1
View File
@@ -24,7 +24,6 @@
#include "input/input_state.h"
#include "Common/Log.h"
#include "Windows/RawInput.h"
#include "Windows/KeyboardDevice.h"
#include "Windows/MainWindow.h"
#include "Windows/WindowsHost.h"
#include "Common/CommonFuncs.h"
@@ -65,6 +64,119 @@ namespace WindowsRawInput {
static float mouseX = 0.0f;
static float mouseY = 0.0f;
// TODO: More keys need to be added, but this is more than
// a fair start.
static std::map<int, int> windowsTransTable = {
{ 'A', NKCODE_A },
{ 'B', NKCODE_B },
{ 'C', NKCODE_C },
{ 'D', NKCODE_D },
{ 'E', NKCODE_E },
{ 'F', NKCODE_F },
{ 'G', NKCODE_G },
{ 'H', NKCODE_H },
{ 'I', NKCODE_I },
{ 'J', NKCODE_J },
{ 'K', NKCODE_K },
{ 'L', NKCODE_L },
{ 'M', NKCODE_M },
{ 'N', NKCODE_N },
{ 'O', NKCODE_O },
{ 'P', NKCODE_P },
{ 'Q', NKCODE_Q },
{ 'R', NKCODE_R },
{ 'S', NKCODE_S },
{ 'T', NKCODE_T },
{ 'U', NKCODE_U },
{ 'V', NKCODE_V },
{ 'W', NKCODE_W },
{ 'X', NKCODE_X },
{ 'Y', NKCODE_Y },
{ 'Z', NKCODE_Z },
{ '0', NKCODE_0 },
{ '1', NKCODE_1 },
{ '2', NKCODE_2 },
{ '3', NKCODE_3 },
{ '4', NKCODE_4 },
{ '5', NKCODE_5 },
{ '6', NKCODE_6 },
{ '7', NKCODE_7 },
{ '8', NKCODE_8 },
{ '9', NKCODE_9 },
{ VK_OEM_PERIOD, NKCODE_PERIOD },
{ VK_OEM_COMMA, NKCODE_COMMA },
{ VK_NUMPAD0, NKCODE_NUMPAD_0 },
{ VK_NUMPAD1, NKCODE_NUMPAD_1 },
{ VK_NUMPAD2, NKCODE_NUMPAD_2 },
{ VK_NUMPAD3, NKCODE_NUMPAD_3 },
{ VK_NUMPAD4, NKCODE_NUMPAD_4 },
{ VK_NUMPAD5, NKCODE_NUMPAD_5 },
{ VK_NUMPAD6, NKCODE_NUMPAD_6 },
{ VK_NUMPAD7, NKCODE_NUMPAD_7 },
{ VK_NUMPAD8, NKCODE_NUMPAD_8 },
{ VK_NUMPAD9, NKCODE_NUMPAD_9 },
{ VK_DECIMAL, NKCODE_NUMPAD_DOT },
{ VK_DIVIDE, NKCODE_NUMPAD_DIVIDE },
{ VK_MULTIPLY, NKCODE_NUMPAD_MULTIPLY },
{ VK_SUBTRACT, NKCODE_NUMPAD_SUBTRACT },
{ VK_ADD, NKCODE_NUMPAD_ADD },
{ VK_SEPARATOR, NKCODE_NUMPAD_COMMA },
{ VK_OEM_MINUS, NKCODE_MINUS },
{ VK_OEM_PLUS, NKCODE_PLUS },
{ VK_LCONTROL, NKCODE_CTRL_LEFT },
{ VK_RCONTROL, NKCODE_CTRL_RIGHT },
{ VK_LSHIFT, NKCODE_SHIFT_LEFT },
{ VK_RSHIFT, NKCODE_SHIFT_RIGHT },
{ VK_LMENU, NKCODE_ALT_LEFT },
{ VK_RMENU, NKCODE_ALT_RIGHT },
{ VK_BACK, NKCODE_DEL }, // yes! http://stackoverflow.com/questions/4886858/android-edittext-deletebackspace-key-event
{ VK_SPACE, NKCODE_SPACE },
{ VK_ESCAPE, NKCODE_ESCAPE },
{ VK_UP, NKCODE_DPAD_UP },
{ VK_INSERT, NKCODE_INSERT },
{ VK_HOME, NKCODE_MOVE_HOME },
{ VK_PRIOR, NKCODE_PAGE_UP },
{ VK_NEXT, NKCODE_PAGE_DOWN },
{ VK_DELETE, NKCODE_FORWARD_DEL },
{ VK_END, NKCODE_MOVE_END },
{ VK_TAB, NKCODE_TAB },
{ VK_DOWN, NKCODE_DPAD_DOWN },
{ VK_LEFT, NKCODE_DPAD_LEFT },
{ VK_RIGHT, NKCODE_DPAD_RIGHT },
{ VK_CAPITAL, NKCODE_CAPS_LOCK },
{ VK_CLEAR, NKCODE_CLEAR },
{ VK_SNAPSHOT, NKCODE_SYSRQ },
{ VK_SCROLL, NKCODE_SCROLL_LOCK },
{ VK_OEM_1, NKCODE_SEMICOLON },
{ VK_OEM_2, NKCODE_SLASH },
{ VK_OEM_3, NKCODE_GRAVE },
{ VK_OEM_4, NKCODE_LEFT_BRACKET },
{ VK_OEM_5, NKCODE_BACKSLASH },
{ VK_OEM_6, NKCODE_RIGHT_BRACKET },
{ VK_OEM_7, NKCODE_APOSTROPHE },
{ VK_RETURN, NKCODE_ENTER },
{ VK_APPS, NKCODE_MENU }, // Context menu key, let's call this "menu".
{ VK_PAUSE, NKCODE_BREAK },
{ VK_F1, NKCODE_F1 },
{ VK_F2, NKCODE_F2 },
{ VK_F3, NKCODE_F3 },
{ VK_F4, NKCODE_F4 },
{ VK_F5, NKCODE_F5 },
{ VK_F6, NKCODE_F6 },
{ VK_F7, NKCODE_F7 },
{ VK_F8, NKCODE_F8 },
{ VK_F9, NKCODE_F9 },
{ VK_F10, NKCODE_F10 },
{ VK_F11, NKCODE_F11 },
{ VK_F12, NKCODE_F12 },
{ VK_OEM_102, NKCODE_EXT_PIPE },
{ VK_LBUTTON, NKCODE_EXT_MOUSEBUTTON_1 },
{ VK_RBUTTON, NKCODE_EXT_MOUSEBUTTON_2 },
{ VK_MBUTTON, NKCODE_EXT_MOUSEBUTTON_3 },
{ VK_XBUTTON1, NKCODE_EXT_MOUSEBUTTON_4 },
{ VK_XBUTTON2, NKCODE_EXT_MOUSEBUTTON_5 },
};
void Init() {
RAWINPUTDEVICE dev[3];
memset(dev, 0, sizeof(dev));
+4 -11
View File
@@ -66,7 +66,6 @@
#include "Windows/DinputDevice.h"
#endif
#include "Windows/XinputDevice.h"
#include "Windows/KeyboardDevice.h"
#include "Windows/main.h"
#include "UI/OnScreenDisplay.h"
@@ -89,17 +88,14 @@ WindowsHost::WindowsHost(HINSTANCE hInstance, HWND mainWindow, HWND displayWindo
g_mouseDeltaY = 0;
//add first XInput device to respond
input.push_back(std::shared_ptr<InputDevice>(new XinputDevice()));
input.push_back(std::make_unique<XinputDevice>());
#ifndef _M_ARM
//find all connected DInput devices of class GamePad
numDinputDevices_ = DinputDevice::getNumPads();
for (size_t i = 0; i < numDinputDevices_; i++) {
input.push_back(std::shared_ptr<InputDevice>(new DinputDevice(static_cast<int>(i))));
input.push_back(std::make_unique<DinputDevice>(static_cast<int>(i)));
}
#endif
keyboard = std::shared_ptr<KeyboardDevice>(new KeyboardDevice());
input.push_back(keyboard);
SetConsolePosition();
}
@@ -221,7 +217,7 @@ void WindowsHost::PollControllers() {
if (newCount > numDinputDevices_) {
INFO_LOG(SYSTEM, "New controller device detected");
for (size_t i = numDinputDevices_; i < newCount; i++) {
input.push_back(std::shared_ptr<InputDevice>(new DinputDevice(static_cast<int>(i))));
input.push_back(std::make_unique<DinputDevice>(static_cast<int>(i)));
}
numDinputDevices_ = newCount;
}
@@ -229,12 +225,9 @@ void WindowsHost::PollControllers() {
checkCounter = 0;
}
bool doPad = true;
for (const auto &device : input) {
if (!doPad && device->IsPad())
continue;
if (device->UpdateState() == InputDevice::UPDATESTATE_SKIP_PAD)
doPad = false;
break;
}
// Disabled by default, needs a workaround to map to psp keys.
+1 -4
View File
@@ -17,7 +17,6 @@
#include "../Core/Host.h"
#include "InputDevice.h"
#include "KeyboardDevice.h"
#include "Common/CommonWindows.h"
#include <list>
#include <memory>
@@ -63,8 +62,6 @@ public:
void NotifyUserMessage(const std::string &message, float duration = 1.0f, u32 color = 0x00FFFFFF, const char *id = nullptr) override;
void SendUIMessage(const std::string &message, const std::string &value) override;
std::shared_ptr<KeyboardDevice> keyboard;
GraphicsContext *GetGraphicsContext() { return gfx_; }
private:
@@ -77,5 +74,5 @@ private:
GraphicsContext *gfx_ = nullptr;
size_t numDinputDevices_ = 0;
std::list<std::shared_ptr<InputDevice>> input;
std::list<std::unique_ptr<InputDevice>> input;
};
+15 -11
View File
@@ -17,12 +17,8 @@
#if !PPSSPP_PLATFORM(UWP)
typedef DWORD (WINAPI *XInputGetState_t) (DWORD dwUserIndex, XINPUT_STATE* pState);
typedef DWORD (WINAPI *XInputSetState_t) (DWORD dwUserIndex, XINPUT_VIBRATION* pVibration);
typedef DWORD (WINAPI *XInputGetCapabilities_t) (DWORD dwUserIndex, DWORD dwFlags, XINPUT_CAPABILITIES* pCapabilities);
static XInputGetState_t PPSSPP_XInputGetState = NULL;
static XInputSetState_t PPSSPP_XInputSetState = NULL;
static XInputGetCapabilities_t PPSSPP_XInputGetCapabilities = NULL;
static DWORD PPSSPP_XInputVersion = 0;
static HMODULE s_pXInputDLL = 0;
static int s_XInputDLLRefCount = 0;
@@ -42,6 +38,10 @@ static int LoadXInputDLL() {
if (!s_pXInputDLL) {
version = (1 << 16) | 3;
s_pXInputDLL = LoadLibrary( L"XInput1_3.dll" ); // 1.3 Ships with Vista and Win7, can be installed as a restributable component.
if (!s_pXInputDLL) {
version = (1 << 16) | 0;
s_pXInputDLL = LoadLibrary( L"XInput9_1_0.dll" ); // 1.0 ships with any Windows since WinXP
}
}
if (!s_pXInputDLL) {
return -1;
@@ -50,11 +50,17 @@ static int LoadXInputDLL() {
PPSSPP_XInputVersion = version;
s_XInputDLLRefCount = 1;
/* 100 is the ordinal for _XInputGetStateEx, which returns the same struct as XinputGetState, but with extra data in wButtons for the guide button, we think... */
PPSSPP_XInputGetState = (XInputGetState_t)GetProcAddress( (HMODULE)s_pXInputDLL, (LPCSTR)100 );
PPSSPP_XInputSetState = (XInputSetState_t)GetProcAddress( (HMODULE)s_pXInputDLL, "XInputSetState" );
PPSSPP_XInputGetCapabilities = (XInputGetCapabilities_t)GetProcAddress( (HMODULE)s_pXInputDLL, "XInputGetCapabilities" );
if ( !PPSSPP_XInputGetState || !PPSSPP_XInputSetState || !PPSSPP_XInputGetCapabilities ) {
/* 100 is the ordinal for _XInputGetStateEx, which returns the same struct as XinputGetState, but with extra data in wButtons for the guide button, we think...
Let's try the name first, though - then fall back to ordinal, then to a non-Ex version (xinput9_1_0.dll doesn't have Ex) */
PPSSPP_XInputGetState = (XInputGetState_t)GetProcAddress( (HMODULE)s_pXInputDLL, "XInputGetStateEx" );
if ( !PPSSPP_XInputGetState ) {
PPSSPP_XInputGetState = (XInputGetState_t)GetProcAddress( (HMODULE)s_pXInputDLL, (LPCSTR)100 );
if ( !PPSSPP_XInputGetState ) {
PPSSPP_XInputGetState = (XInputGetState_t)GetProcAddress( (HMODULE)s_pXInputDLL, "XInputGetState" );
}
}
if ( !PPSSPP_XInputGetState ) {
UnloadXInputDLL();
return -1;
}
@@ -75,8 +81,6 @@ static void UnloadXInputDLL() {
static int LoadXInputDLL() { return 0; }
static void UnloadXInputDLL() {}
#define PPSSPP_XInputGetState XInputGetState
#define PPSSPP_XInputSetState XInputSetState
#define PPSSPP_XInputGetCapabilities XInputGetCapabilities
#endif
#ifndef XUSER_MAX_COUNT
+2 -3
View File
@@ -4,12 +4,11 @@
#include "Xinput.h"
class XinputDevice : public InputDevice {
class XinputDevice final : public InputDevice {
public:
XinputDevice();
~XinputDevice();
virtual int UpdateState();
virtual bool IsPad() { return true; }
virtual int UpdateState() override;
private:
void UpdatePad(int pad, const XINPUT_STATE &state);
+1 -3
View File
@@ -572,7 +572,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
#ifndef _DEBUG
// See #11719 - too many Vulkan drivers crash on basic init.
if (g_Config.IsBackendEnabled(GPUBackend::VULKAN)) {
if (g_Config.IsBackendEnabled(GPUBackend::VULKAN, false)) {
VulkanSetAvailable(DetectVulkanInExternalProcess());
}
#endif
@@ -674,8 +674,6 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
VFSShutdown();
InputDevice::StopPolling();
MainWindow::DestroyDebugWindows();
DialogManager::DestroyAll();
timeEndPeriod(1);
+1
View File
@@ -12,3 +12,4 @@ ui_atlas.zim.png
#assets/ui_atlas_luna.zim
#jni/ui_atlas.cpp
#jni/ui_atlas.h
.cxx
+23 -9
View File
@@ -1,4 +1,10 @@
if(NOT EXISTS "/opt/vc/include/bcm_host.h")
file(READ "/sys/firmware/devicetree/base/compatible" PPSSPP_PI_MODEL)
if(PPSSPP_PI_MODEL MATCHES "raspberrypi,4")
set(PPSSPP_PI_MODEL4 ON)
endif()
if(NOT PPSSPP_PI_MODEL4 AND NOT EXISTS "/opt/vc/include/bcm_host.h")
message(FATAL_ERROR "RaspberryPI platform not recognized")
endif()
@@ -8,21 +14,29 @@ include_directories(SYSTEM
/opt/vc/include/interface/vmcx_host/linux
)
add_definitions(
-DPPSSPP_PLATFORM_RPI=1
-U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
)
if(NOT PPSSPP_PI_MODEL4)
add_definitions(
-DPPSSPP_PLATFORM_RPI=1
-U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
)
endif()
set(ARCH_FLAGS "-mcpu=cortex-a7 -mfpu=neon -mfloat-abi=hard")
if(PPSSPP_PI_MODEL4)
set(ARCH_FLAGS "-march=armv7-a -mcpu=cortex-a72 -mtune=cortex-a72 -mfpu=neon-vfpv4 -mfloat-abi=hard")
else()
set(ARCH_FLAGS "-mcpu=cortex-a7 -mfpu=neon -mfloat-abi=hard")
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ARCH_FLAGS}" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARCH_FLAGS}" CACHE STRING "" FORCE)
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${ARCH_FLAGS}" CACHE STRING "" FORCE)
set(CMAKE_EXE_LINKER_FLAGS "-L/opt/vc/lib" CACHE STRING "" FORCE)
set(OPENGL_LIBRARIES brcmGLESv2 bcm_host)
set(EGL_LIBRARIES brcmEGL)
if(NOT PPSSPP_PI_MODEL4)
set(OPENGL_LIBRARIES brcmGLESv2 bcm_host)
set(EGL_LIBRARIES brcmEGL)
set(USING_FBDEV ON)
endif()
set(USING_GLES2 ON)
set(USING_FBDEV ON)
set(ARMV7 ON)
set(USE_WAYLAND_WSI OFF)
+4
View File
@@ -239,6 +239,7 @@
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -259,6 +260,7 @@
<BufferSecurityCheck>false</BufferSecurityCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<OmitFramePointers>false</OmitFramePointers>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -279,6 +281,7 @@
<BufferSecurityCheck>false</BufferSecurityCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<OmitFramePointers>false</OmitFramePointers>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -299,6 +302,7 @@
<BufferSecurityCheck>false</BufferSecurityCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<OmitFramePointers>false</OmitFramePointers>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -187,6 +187,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<OmitFramePointers>false</OmitFramePointers>
<BufferSecurityCheck>false</BufferSecurityCheck>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -208,6 +209,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<OmitFramePointers>false</OmitFramePointers>
<BufferSecurityCheck>false</BufferSecurityCheck>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -229,6 +231,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<OmitFramePointers>false</OmitFramePointers>
<BufferSecurityCheck>false</BufferSecurityCheck>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -313,6 +316,7 @@
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BufferSecurityCheck>false</BufferSecurityCheck>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
+4
View File
@@ -221,6 +221,7 @@
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<BufferSecurityCheck>false</BufferSecurityCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -243,6 +244,7 @@
<BufferSecurityCheck>false</BufferSecurityCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<OmitFramePointers>false</OmitFramePointers>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -265,6 +267,7 @@
<BufferSecurityCheck>false</BufferSecurityCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<OmitFramePointers>false</OmitFramePointers>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -287,6 +290,7 @@
<BufferSecurityCheck>false</BufferSecurityCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<OmitFramePointers>false</OmitFramePointers>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
+4
View File
@@ -404,6 +404,7 @@
<AdditionalIncludeDirectories>armips</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<BufferSecurityCheck>false</BufferSecurityCheck>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -426,6 +427,7 @@
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<OmitFramePointers>false</OmitFramePointers>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -448,6 +450,7 @@
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<OmitFramePointers>false</OmitFramePointers>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -470,6 +473,7 @@
<StringPooling>true</StringPooling>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<OmitFramePointers>false</OmitFramePointers>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
+16 -11
View File
@@ -211,20 +211,19 @@ bool FileInfo::operator <(const FileInfo &other) const {
size_t getFilesInDir(const char *directory, std::vector<FileInfo> *files, const char *filter, int flags) {
size_t foundEntries = 0;
std::set<std::string> filters;
std::string tmp;
if (filter) {
std::string tmp;
while (*filter) {
if (*filter == ':') {
filters.insert(tmp);
tmp = "";
filters.insert(std::move(tmp));
} else {
tmp.push_back(*filter);
}
filter++;
}
if (!tmp.empty())
filters.insert(std::move(tmp));
}
if (tmp.size())
filters.insert(tmp);
#ifdef _WIN32
// Find the first file in the directory.
WIN32_FIND_DATA ffd;
@@ -252,14 +251,20 @@ size_t getFilesInDir(const char *directory, std::vector<FileInfo> *files, const
const std::string virtualName(result->d_name);
#endif
// check for "." and ".."
if (((virtualName[0] == '.') && (virtualName[1] == '\0')) ||
((virtualName[0] == '.') && (virtualName[1] == '.') &&
(virtualName[2] == '\0')))
if (virtualName == "." || virtualName == "..")
continue;
// Remove dotfiles (optional with flag.)
if (!(flags & GETFILES_GETHIDDEN) && virtualName[0] == '.')
continue;
if (!(flags & GETFILES_GETHIDDEN))
{
#ifdef _WIN32
if ((ffd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0)
continue;
#else
if (virtualName[0] == '.')
continue;
#endif
}
FileInfo info;
info.name = virtualName;
@@ -283,7 +288,7 @@ size_t getFilesInDir(const char *directory, std::vector<FileInfo> *files, const
}
if (files)
files->push_back(info);
files->push_back(std::move(info));
foundEntries++;
#ifdef _WIN32
} while (FindNextFile(hFind, &ffd) != 0);
+4
View File
@@ -257,6 +257,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
@@ -284,6 +285,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BufferSecurityCheck>false</BufferSecurityCheck>
<StringPooling>true</StringPooling>
<OmitFramePointers>false</OmitFramePointers>
@@ -313,6 +315,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BufferSecurityCheck>false</BufferSecurityCheck>
<StringPooling>true</StringPooling>
<OmitFramePointers>false</OmitFramePointers>
@@ -342,6 +345,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<BufferSecurityCheck>false</BufferSecurityCheck>
<StringPooling>true</StringPooling>
<OmitFramePointers>false</OmitFramePointers>
+4
View File
@@ -268,6 +268,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -294,6 +295,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<StringPooling>true</StringPooling>
</ClCompile>
<Link>
@@ -321,6 +323,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<StringPooling>true</StringPooling>
</ClCompile>
<Link>
@@ -348,6 +351,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<StringPooling>true</StringPooling>
</ClCompile>
<Link>
+1
View File
@@ -379,6 +379,7 @@ int main(int argc, const char* argv[])
g_Config.bHighQualityDepth = true;
g_Config.bMemStickInserted = true;
g_Config.bFragmentTestCache = true;
g_Config.iAudioLatency = 1;
#ifdef _WIN32
InitSysDirectories();
+4
View File
@@ -309,6 +309,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -345,6 +346,7 @@
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StringPooling>true</StringPooling>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -381,6 +383,7 @@
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StringPooling>true</StringPooling>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -414,6 +417,7 @@
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<StringPooling>true</StringPooling>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
+6 -4
View File
@@ -61,10 +61,12 @@ bool System_GetPropertyBool(SystemProperty prop) {
void System_SendMessage(const char *command, const char *parameter) {
if (!strcmp(command, "finish")) {
dispatch_async(dispatch_get_main_queue(), ^{
[sharedViewController shutdown];
exit(0);
});
exit(0);
// The below seems right, but causes hangs. See #12140.
// dispatch_async(dispatch_get_main_queue(), ^{
// [sharedViewController shutdown];
// exit(0);
// });
}
}
+5 -1
View File
@@ -324,10 +324,14 @@ void retro_init(void) {
g_Config.bFrameSkipUnthrottle = false;
g_Config.bMemStickInserted = PSP_MEMORYSTICK_STATE_INSERTED;
g_Config.iGlobalVolume = VOLUME_MAX - 1;
g_Config.iAltSpeedVolume = -1;
g_Config.bEnableSound = true;
g_Config.bAudioResampler = false;
g_Config.iCwCheatRefreshRate = 60;
g_Config.iFirmwareVersion = PSP_DEFAULT_FIRMWARE;
g_Config.iPSPModel = PSP_MODEL_SLIM;
LogManager::Init();
host = new LibretroHost;
+4
View File
@@ -270,6 +270,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -298,6 +299,7 @@
<StringPooling>true</StringPooling>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<OmitFramePointers>false</OmitFramePointers>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -326,6 +328,7 @@
<StringPooling>true</StringPooling>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<OmitFramePointers>false</OmitFramePointers>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -354,6 +357,7 @@
<StringPooling>true</StringPooling>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<OmitFramePointers>false</OmitFramePointers>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>