mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge branch 'feature_openxr_quest' into feature_openxr_6dof
This commit is contained in:
commit
9b8a9d3b32
120 changed files with 1553 additions and 996 deletions
1
.github/ISSUE_TEMPLATE/bug.yml
vendored
1
.github/ISSUE_TEMPLATE/bug.yml
vendored
|
@ -79,6 +79,7 @@ body:
|
|||
- Raspberry Pi
|
||||
- Linux / BSD
|
||||
- macOS
|
||||
- UWP / Xbox
|
||||
- Other
|
||||
|
||||
- type: input
|
||||
|
|
1
.github/ISSUE_TEMPLATE/build.yml
vendored
1
.github/ISSUE_TEMPLATE/build.yml
vendored
|
@ -14,6 +14,7 @@ body:
|
|||
- Raspberry Pi
|
||||
- Linux / BSD
|
||||
- macOS
|
||||
- UWP / Xbox
|
||||
- Other
|
||||
|
||||
- type: input
|
||||
|
|
1
.github/ISSUE_TEMPLATE/feature.yml
vendored
1
.github/ISSUE_TEMPLATE/feature.yml
vendored
|
@ -44,6 +44,7 @@ body:
|
|||
- Raspberry Pi
|
||||
- Linux / BSD
|
||||
- macOS
|
||||
- UWP / Xbox
|
||||
- Other
|
||||
|
||||
- type: input
|
||||
|
|
1
.github/ISSUE_TEMPLATE/graphics.yml
vendored
1
.github/ISSUE_TEMPLATE/graphics.yml
vendored
|
@ -93,6 +93,7 @@ body:
|
|||
- Raspberry Pi
|
||||
- Linux / BSD
|
||||
- macOS
|
||||
- UWP / Xbox
|
||||
- Other
|
||||
|
||||
- type: input
|
||||
|
|
1
.github/ISSUE_TEMPLATE/performance.yml
vendored
1
.github/ISSUE_TEMPLATE/performance.yml
vendored
|
@ -72,6 +72,7 @@ body:
|
|||
- Raspberry Pi
|
||||
- Linux / BSD
|
||||
- macOS
|
||||
- UWP / Xbox
|
||||
- Other
|
||||
|
||||
- type: input
|
||||
|
|
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
@ -220,7 +220,7 @@ jobs:
|
|||
if: matrix.extra == 'android'
|
||||
id: setup-ndk
|
||||
with:
|
||||
ndk-version: r21d
|
||||
ndk-version: r21e
|
||||
|
||||
- name: Install Linux dependencies
|
||||
if: runner.os == 'Linux' && matrix.extra != 'android'
|
||||
|
|
2
.github/workflows/manual_generate_apk.yml
vendored
2
.github/workflows/manual_generate_apk.yml
vendored
|
@ -35,7 +35,7 @@ jobs:
|
|||
#- name: Setup NDK
|
||||
# uses: nttld/setup-ndk@v1
|
||||
# with:
|
||||
# ndk-version: r21d
|
||||
# ndk-version: r21e
|
||||
|
||||
- name: Assemble APK
|
||||
run: bash ./gradlew assemble${{ github.event.inputs.buildVariant }} --stacktrace
|
||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -88,6 +88,7 @@ __testoutput.txt
|
|||
__testerror.txt
|
||||
__testfinish.txt
|
||||
__testfailure.bmp
|
||||
__testcompare.png
|
||||
GameLogNotes.txt
|
||||
screenshots
|
||||
android/assets/lang
|
||||
|
|
|
@ -2343,6 +2343,7 @@ if(UNITTEST)
|
|||
unittest/TestShaderGenerators.cpp
|
||||
unittest/TestArmEmitter.cpp
|
||||
unittest/TestArm64Emitter.cpp
|
||||
unittest/TestIRPassSimplify.cpp
|
||||
unittest/TestX64Emitter.cpp
|
||||
unittest/TestVertexJit.cpp
|
||||
unittest/TestSoftwareGPUJit.cpp
|
||||
|
|
|
@ -160,7 +160,9 @@ static bool ParseFileInfo(const std::string &line, File::FileInfo *fileInfo) {
|
|||
fileInfo->exists = true;
|
||||
sscanf(parts[1].c_str(), "%" PRIu64, &fileInfo->size);
|
||||
fileInfo->isWritable = true; // TODO: Should be passed as part of the string.
|
||||
fileInfo->access = fileInfo->isDirectory ? 0666 : 0777; // TODO: For read-only mappings, reflect that here, similarly as with isWritable.
|
||||
// TODO: For read-only mappings, reflect that here, similarly as with isWritable.
|
||||
// Directories are normally executable (0111) which means they're traversable.
|
||||
fileInfo->access = fileInfo->isDirectory ? 0777 : 0666;
|
||||
|
||||
uint64_t lastModifiedMs = 0;
|
||||
sscanf(parts[3].c_str(), "%" PRIu64, &lastModifiedMs);
|
||||
|
|
|
@ -242,6 +242,14 @@ bool GetFilesInDir(const Path &directory, std::vector<FileInfo> *files, const ch
|
|||
info.atime = FiletimeToStatTime(ffd.ftLastAccessTime);
|
||||
info.mtime = FiletimeToStatTime(ffd.ftLastWriteTime);
|
||||
info.ctime = FiletimeToStatTime(ffd.ftCreationTime);
|
||||
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
|
||||
info.access = 0444; // Read
|
||||
} else {
|
||||
info.access = 0666; // Read/Write
|
||||
}
|
||||
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
info.access |= 0111; // Execute
|
||||
}
|
||||
if (!info.isDirectory) {
|
||||
std::string ext = info.fullName.GetFileExtension();
|
||||
if (!ext.empty()) {
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "Common/GPU/Vulkan/VulkanContext.h"
|
||||
|
||||
|
|
|
@ -825,6 +825,11 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit)
|
|||
bugs_.Infest(Bugs::EQUAL_WZ_CORRUPTS_DEPTH);
|
||||
// At least one driver at the upper end of the range is known to be likely to suffer from the bug causing issue #13833 (Midnight Club map broken).
|
||||
bugs_.Infest(Bugs::MALI_STENCIL_DISCARD_BUG);
|
||||
|
||||
// This started in driver 31 or 32.
|
||||
if (VK_API_VERSION_MAJOR(deviceProps.driverVersion) >= 32) {
|
||||
bugs_.Infest(Bugs::MALI_CONSTANT_LOAD_BUG); // See issue #15661
|
||||
}
|
||||
}
|
||||
|
||||
caps_.deviceID = deviceProps.deviceID;
|
||||
|
|
|
@ -630,6 +630,7 @@ const char *Bugs::GetBugName(uint32_t bug) {
|
|||
case EQUAL_WZ_CORRUPTS_DEPTH: return "EQUAL_WZ_CORRUPTS_DEPTH";
|
||||
case MALI_STENCIL_DISCARD_BUG: return "MALI_STENCIL_DISCARD_BUG";
|
||||
case RASPBERRY_SHADER_COMP_HANG: return "RASPBERRY_SHADER_COMP_HANG";
|
||||
case MALI_CONSTANT_LOAD_BUG: return "MALI_CONSTANT_LOAD_BUG";
|
||||
default: return "(N/A)";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -324,6 +324,7 @@ public:
|
|||
EQUAL_WZ_CORRUPTS_DEPTH = 7,
|
||||
MALI_STENCIL_DISCARD_BUG = 8,
|
||||
RASPBERRY_SHADER_COMP_HANG = 9,
|
||||
MALI_CONSTANT_LOAD_BUG = 10,
|
||||
MAX_BUG,
|
||||
};
|
||||
|
||||
|
|
|
@ -234,7 +234,6 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, const
|
|||
file = fileshort + 1;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lk(log_lock_);
|
||||
GetTimeFormatted(message.timestamp);
|
||||
|
||||
if (hleCurrentThreadName) {
|
||||
|
|
|
@ -122,7 +122,6 @@ private:
|
|||
RingbufferLogListener *ringLog_ = nullptr;
|
||||
static LogManager *logManager_; // Singleton. Ugh.
|
||||
|
||||
std::mutex log_lock_;
|
||||
std::mutex listeners_lock_;
|
||||
std::vector<LogListener*> listeners_;
|
||||
|
||||
|
|
|
@ -94,6 +94,8 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) {
|
|||
CheckSetting(iniFile, gameID, "BlueToAlpha", &flags_.BlueToAlpha);
|
||||
CheckSetting(iniFile, gameID, "CenteredLines", &flags_.CenteredLines);
|
||||
CheckSetting(iniFile, gameID, "MaliDepthStencilBugWorkaround", &flags_.MaliDepthStencilBugWorkaround);
|
||||
CheckSetting(iniFile, gameID, "ZZT3SelectHack", &flags_.ZZT3SelectHack);
|
||||
CheckSetting(iniFile, gameID, "AllowLargeFBTextureOffsets", &flags_.AllowLargeFBTextureOffsets);
|
||||
}
|
||||
|
||||
void Compatibility::CheckSetting(IniFile &iniFile, const std::string &gameID, const char *option, bool *flag) {
|
||||
|
|
|
@ -84,6 +84,8 @@ struct CompatFlags {
|
|||
bool BlueToAlpha;
|
||||
bool CenteredLines;
|
||||
bool MaliDepthStencilBugWorkaround;
|
||||
bool ZZT3SelectHack;
|
||||
bool AllowLargeFBTextureOffsets;
|
||||
};
|
||||
|
||||
class IniFile;
|
||||
|
|
105
Core/Config.cpp
105
Core/Config.cpp
|
@ -19,8 +19,10 @@
|
|||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
|
||||
#include "ppsspp_config.h"
|
||||
|
||||
|
@ -57,6 +59,17 @@ Config g_Config;
|
|||
|
||||
bool jitForcedOff;
|
||||
|
||||
// Not in Config.h because it's #included a lot.
|
||||
struct ConfigPrivate {
|
||||
std::mutex recentIsosLock;
|
||||
std::mutex recentIsosThreadLock;
|
||||
std::thread recentIsosThread;
|
||||
bool recentIsosThreadPending = false;
|
||||
|
||||
void ResetRecentIsosThread();
|
||||
void SetRecentIsosThread(std::function<void()> f);
|
||||
};
|
||||
|
||||
#ifdef _DEBUG
|
||||
static const char *logSectionName = "LogDebug";
|
||||
#else
|
||||
|
@ -1214,13 +1227,30 @@ static void IterateSettings(IniFile &iniFile, std::function<void(Section *sectio
|
|||
}
|
||||
}
|
||||
|
||||
void ConfigPrivate::ResetRecentIsosThread() {
|
||||
std::lock_guard<std::mutex> guard(recentIsosThreadLock);
|
||||
if (recentIsosThreadPending && recentIsosThread.joinable())
|
||||
recentIsosThread.join();
|
||||
}
|
||||
|
||||
void ConfigPrivate::SetRecentIsosThread(std::function<void()> f) {
|
||||
std::lock_guard<std::mutex> guard(recentIsosThreadLock);
|
||||
if (recentIsosThreadPending && recentIsosThread.joinable())
|
||||
recentIsosThread.join();
|
||||
recentIsosThread = std::thread(f);
|
||||
recentIsosThreadPending = true;
|
||||
}
|
||||
|
||||
Config::Config() {
|
||||
private_ = new ConfigPrivate();
|
||||
}
|
||||
|
||||
Config::~Config() {
|
||||
if (bUpdatedInstanceCounter) {
|
||||
ShutdownInstanceCounter();
|
||||
}
|
||||
private_->ResetRecentIsosThread();
|
||||
delete private_;
|
||||
}
|
||||
|
||||
std::map<std::string, std::pair<std::string, int>> GetLangValuesMapping() {
|
||||
|
@ -1323,6 +1353,8 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
|
|||
iMaxRecent = 60;
|
||||
|
||||
if (iMaxRecent > 0) {
|
||||
private_->ResetRecentIsosThread();
|
||||
std::lock_guard<std::mutex> guard(private_->recentIsosLock);
|
||||
recentIsos.clear();
|
||||
for (int i = 0; i < iMaxRecent; i++) {
|
||||
char keyName[64];
|
||||
|
@ -1478,9 +1510,11 @@ bool Config::Save(const char *saveReason) {
|
|||
Section *recent = iniFile.GetOrCreateSection("Recent");
|
||||
recent->Set("MaxRecent", iMaxRecent);
|
||||
|
||||
private_->ResetRecentIsosThread();
|
||||
for (int i = 0; i < iMaxRecent; i++) {
|
||||
char keyName[64];
|
||||
snprintf(keyName, sizeof(keyName), "FileName%d", i);
|
||||
std::lock_guard<std::mutex> guard(private_->recentIsosLock);
|
||||
if (i < (int)recentIsos.size()) {
|
||||
recent->Set(keyName, recentIsos[i]);
|
||||
} else {
|
||||
|
@ -1618,6 +1652,8 @@ void Config::AddRecent(const std::string &file) {
|
|||
// We'll add it back below. This makes sure it's at the front, and only once.
|
||||
RemoveRecent(file);
|
||||
|
||||
private_->ResetRecentIsosThread();
|
||||
std::lock_guard<std::mutex> guard(private_->recentIsosLock);
|
||||
const std::string filename = File::ResolvePath(file);
|
||||
recentIsos.insert(recentIsos.begin(), filename);
|
||||
if ((int)recentIsos.size() > iMaxRecent)
|
||||
|
@ -1629,6 +1665,8 @@ void Config::RemoveRecent(const std::string &file) {
|
|||
if (iMaxRecent <= 0)
|
||||
return;
|
||||
|
||||
private_->ResetRecentIsosThread();
|
||||
std::lock_guard<std::mutex> guard(private_->recentIsosLock);
|
||||
const std::string filename = File::ResolvePath(file);
|
||||
for (auto iter = recentIsos.begin(); iter != recentIsos.end();) {
|
||||
const std::string recent = File::ResolvePath(*iter);
|
||||
|
@ -1642,35 +1680,52 @@ void Config::RemoveRecent(const std::string &file) {
|
|||
}
|
||||
|
||||
void Config::CleanRecent() {
|
||||
double startTime = time_now_d();
|
||||
private_->SetRecentIsosThread([this] {
|
||||
double startTime = time_now_d();
|
||||
|
||||
std::vector<std::string> cleanedRecent;
|
||||
for (size_t i = 0; i < recentIsos.size(); i++) {
|
||||
bool exists = false;
|
||||
Path path = Path(recentIsos[i]);
|
||||
switch (path.Type()) {
|
||||
case PathType::CONTENT_URI:
|
||||
case PathType::NATIVE:
|
||||
exists = File::Exists(path);
|
||||
break;
|
||||
default:
|
||||
FileLoader *loader = ConstructFileLoader(path);
|
||||
exists = loader->ExistsFast();
|
||||
delete loader;
|
||||
break;
|
||||
}
|
||||
std::lock_guard<std::mutex> guard(private_->recentIsosLock);
|
||||
std::vector<std::string> cleanedRecent;
|
||||
for (size_t i = 0; i < recentIsos.size(); i++) {
|
||||
bool exists = false;
|
||||
Path path = Path(recentIsos[i]);
|
||||
switch (path.Type()) {
|
||||
case PathType::CONTENT_URI:
|
||||
case PathType::NATIVE:
|
||||
exists = File::Exists(path);
|
||||
break;
|
||||
default:
|
||||
FileLoader *loader = ConstructFileLoader(path);
|
||||
exists = loader->ExistsFast();
|
||||
delete loader;
|
||||
break;
|
||||
}
|
||||
|
||||
if (exists) {
|
||||
// Make sure we don't have any redundant items.
|
||||
auto duplicate = std::find(cleanedRecent.begin(), cleanedRecent.end(), recentIsos[i]);
|
||||
if (duplicate == cleanedRecent.end()) {
|
||||
cleanedRecent.push_back(recentIsos[i]);
|
||||
if (exists) {
|
||||
// Make sure we don't have any redundant items.
|
||||
auto duplicate = std::find(cleanedRecent.begin(), cleanedRecent.end(), recentIsos[i]);
|
||||
if (duplicate == cleanedRecent.end()) {
|
||||
cleanedRecent.push_back(recentIsos[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INFO_LOG(SYSTEM, "CleanRecent took %0.2f", time_now_d() - startTime);
|
||||
recentIsos = cleanedRecent;
|
||||
INFO_LOG(SYSTEM, "CleanRecent took %0.2f", time_now_d() - startTime);
|
||||
recentIsos = cleanedRecent;
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<std::string> Config::RecentIsos() const {
|
||||
std::lock_guard<std::mutex> guard(private_->recentIsosLock);
|
||||
return recentIsos;
|
||||
}
|
||||
bool Config::HasRecentIsos() const {
|
||||
std::lock_guard<std::mutex> guard(private_->recentIsosLock);
|
||||
return !recentIsos.empty();
|
||||
}
|
||||
void Config::ClearRecentIsos() {
|
||||
private_->ResetRecentIsosThread();
|
||||
std::lock_guard<std::mutex> guard(private_->recentIsosLock);
|
||||
recentIsos.clear();
|
||||
}
|
||||
|
||||
void Config::SetSearchPath(const Path &searchPath) {
|
||||
|
@ -1709,7 +1764,7 @@ void Config::RestoreDefaults() {
|
|||
} else {
|
||||
if (File::Exists(iniFilename_))
|
||||
File::Delete(iniFilename_);
|
||||
recentIsos.clear();
|
||||
ClearRecentIsos();
|
||||
currentDirectory = defaultCurrentDirectory;
|
||||
}
|
||||
Load();
|
||||
|
|
|
@ -48,6 +48,7 @@ namespace http {
|
|||
}
|
||||
|
||||
struct UrlEncoder;
|
||||
struct ConfigPrivate;
|
||||
|
||||
struct ConfigTouchPos {
|
||||
float x;
|
||||
|
@ -140,7 +141,6 @@ public:
|
|||
int iInternalScreenRotation; // The internal screen rotation angle. Useful for vertical SHMUPs and similar.
|
||||
|
||||
std::string sReportHost;
|
||||
std::vector<std::string> recentIsos;
|
||||
std::vector<std::string> vPinnedPaths;
|
||||
std::string sLanguageIni;
|
||||
|
||||
|
@ -536,6 +536,10 @@ public:
|
|||
return bFullScreen;
|
||||
}
|
||||
|
||||
std::vector<std::string> RecentIsos() const;
|
||||
bool HasRecentIsos() const;
|
||||
void ClearRecentIsos();
|
||||
|
||||
protected:
|
||||
void LoadStandardControllerIni();
|
||||
|
||||
|
@ -543,9 +547,11 @@ private:
|
|||
bool reload_ = false;
|
||||
std::string gameId_;
|
||||
std::string gameIdTitle_;
|
||||
std::vector<std::string> recentIsos;
|
||||
Path iniFilename_;
|
||||
Path controllerIniFilename_;
|
||||
Path searchPath_;
|
||||
ConfigPrivate *private_ = nullptr;
|
||||
};
|
||||
|
||||
std::map<std::string, std::pair<std::string, int>> GetLangValuesMapping();
|
||||
|
|
|
@ -148,6 +148,17 @@ static const char16_t oskKeys[OSK_KEYBOARD_COUNT][6][14] =
|
|||
|
||||
// This isn't a complete representation of these flags, it just helps ensure we show the right keyboards.
|
||||
int allowedInputFlagsMap[OSK_KEYBOARD_COUNT] = {
|
||||
PSP_UTILITY_OSK_INPUTTYPE_LATIN_LOWERCASE | PSP_UTILITY_OSK_INPUTTYPE_LATIN_UPPERCASE | PSP_UTILITY_OSK_INPUTTYPE_LATIN_SYMBOL | PSP_UTILITY_OSK_INPUTTYPE_LATIN_DIGIT,
|
||||
PSP_UTILITY_OSK_INPUTTYPE_LATIN_LOWERCASE | PSP_UTILITY_OSK_INPUTTYPE_LATIN_UPPERCASE | PSP_UTILITY_OSK_INPUTTYPE_LATIN_SYMBOL,
|
||||
PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_HIRAGANA,
|
||||
PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_KATAKANA | PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_HALF_KATAKANA,
|
||||
PSP_UTILITY_OSK_INPUTTYPE_KOREAN,
|
||||
PSP_UTILITY_OSK_INPUTTYPE_RUSSIAN_LOWERCASE | PSP_UTILITY_OSK_INPUTTYPE_RUSSIAN_UPPERCASE,
|
||||
PSP_UTILITY_OSK_INPUTTYPE_RUSSIAN_LOWERCASE | PSP_UTILITY_OSK_INPUTTYPE_RUSSIAN_UPPERCASE,
|
||||
PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_LOWERCASE | PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_UPPERCASE | PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_SYMBOL | PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_DIGIT,
|
||||
PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_LOWERCASE | PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_UPPERCASE | PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_SYMBOL,
|
||||
};
|
||||
int defaultInputFlagsMap[OSK_KEYBOARD_COUNT] = {
|
||||
PSP_UTILITY_OSK_INPUTTYPE_LATIN_LOWERCASE | PSP_UTILITY_OSK_INPUTTYPE_LATIN_SYMBOL | PSP_UTILITY_OSK_INPUTTYPE_LATIN_DIGIT,
|
||||
PSP_UTILITY_OSK_INPUTTYPE_LATIN_UPPERCASE | PSP_UTILITY_OSK_INPUTTYPE_LATIN_SYMBOL,
|
||||
PSP_UTILITY_OSK_INPUTTYPE_JAPANESE_HIRAGANA,
|
||||
|
@ -249,11 +260,17 @@ static void FindValidKeyboard(s32 inputType, int direction, OskKeyboardLanguage
|
|||
if (inputType == 0) {
|
||||
return;
|
||||
}
|
||||
// We use direction = 0 for default, but we actually move "forward".
|
||||
int *matchMap = allowedInputFlagsMap;
|
||||
if (direction == 0) {
|
||||
direction = 1;
|
||||
matchMap = defaultInputFlagsMap;
|
||||
}
|
||||
|
||||
// TODO: Limit by allowed keyboards properly... this is just an approximation.
|
||||
int tries = OSK_LANGUAGE_COUNT * 2;
|
||||
while (!(inputType & allowedInputFlagsMap[disp]) && tries > 0) {
|
||||
if ((--tries % 1) == 0) {
|
||||
while (!(inputType & matchMap[disp]) && tries > 0) {
|
||||
if ((--tries % 2) == 0) {
|
||||
lang = (OskKeyboardLanguage)((OSK_LANGUAGE_COUNT + lang + direction) % OSK_LANGUAGE_COUNT);
|
||||
disp = OskKeyboardCases[lang][LOWERCASE];
|
||||
} else {
|
||||
|
@ -312,7 +329,7 @@ int PSPOskDialog::Init(u32 oskPtr) {
|
|||
selectedChar = 0;
|
||||
currentKeyboardLanguage = OSK_LANGUAGE_ENGLISH;
|
||||
currentKeyboard = OSK_KEYBOARD_LATIN_LOWERCASE;
|
||||
FindValidKeyboard(oskParams->fields[0].inputtype, 1, currentKeyboardLanguage, currentKeyboard);
|
||||
FindValidKeyboard(oskParams->fields[0].inputtype, 0, currentKeyboardLanguage, currentKeyboard);
|
||||
|
||||
ConvertUCS2ToUTF8(oskDesc, oskParams->fields[0].desc);
|
||||
ConvertUCS2ToUTF8(oskIntext, oskParams->fields[0].intext);
|
||||
|
|
|
@ -493,7 +493,7 @@ int ElfReader::LoadInto(u32 loadAddress, bool fromTop)
|
|||
u32 writeAddr = segmentVAddr[i];
|
||||
|
||||
const u8 *src = GetSegmentPtr(i);
|
||||
u8 *dst = Memory::GetPointer(writeAddr);
|
||||
u8 *dst = Memory::GetPointerWrite(writeAddr);
|
||||
u32 srcSize = p->p_filesz;
|
||||
u32 dstSize = p->p_memsz;
|
||||
|
||||
|
|
|
@ -407,7 +407,7 @@ int ISOFileSystem::Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outd
|
|||
}
|
||||
|
||||
INFO_LOG(SCEIO, "sceIoIoctl: reading ISO9660 volume descriptor read");
|
||||
blockDevice->ReadBlock(16, Memory::GetPointer(outdataPtr));
|
||||
blockDevice->ReadBlock(16, Memory::GetPointerWriteUnchecked(outdataPtr));
|
||||
return 0;
|
||||
|
||||
// Get ISO9660 path table (from open ISO9660 file.)
|
||||
|
@ -424,7 +424,7 @@ int ISOFileSystem::Ioctl(u32 handle, u32 cmd, u32 indataPtr, u32 inlen, u32 outd
|
|||
} else {
|
||||
int block = (u16)desc.firstLETableSector;
|
||||
u32 size = Memory::ValidSize(outdataPtr, (u32)desc.pathTableLength);
|
||||
u8 *out = Memory::GetPointer(outdataPtr);
|
||||
u8 *out = Memory::GetPointerWrite(outdataPtr);
|
||||
|
||||
int blocks = size / blockDevice->GetBlockSize();
|
||||
blockDevice->ReadBlocks(block, blocks, out);
|
||||
|
|
|
@ -106,7 +106,7 @@ template<u32 func()> void WrapU_V() {
|
|||
}
|
||||
|
||||
template<u32 func(int, void *, int)> void WrapU_IVI() {
|
||||
u32 retval = func(PARAM(0), Memory::GetPointer(PARAM(1)), PARAM(2));
|
||||
u32 retval = func(PARAM(0), Memory::GetPointerWrite(PARAM(1)), PARAM(2));
|
||||
RETURN(retval);
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ template<int func(const char *, int, int, u32)> void WrapI_CIIU() {
|
|||
}
|
||||
|
||||
template<int func(int, const char *, u32, void *, void *, u32, int)> void WrapI_ICUVVUI() {
|
||||
u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), Memory::GetPointer(PARAM(3)),Memory::GetPointer(PARAM(4)), PARAM(5), PARAM(6) );
|
||||
u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), Memory::GetPointerWrite(PARAM(3)),Memory::GetPointerWrite(PARAM(4)), PARAM(5), PARAM(6) );
|
||||
RETURN(retval);
|
||||
}
|
||||
|
||||
|
@ -147,13 +147,13 @@ template<int func(int, int, int, int, int, int, u32)> void WrapI_IIIIIIU() {
|
|||
|
||||
// Hm, do so many params get passed in registers?
|
||||
template<int func(int, int, int, int, int, int, int, int, u32)> void WrapI_IIIIIIIIU() {
|
||||
u32 param8 = *(const u32_le *)Memory::GetPointer(currentMIPS->r[29]); //Fixed 9th parameter, thanks to Kingcom
|
||||
u32 param8 = *(const u32_le *)Memory::GetPointerWrite(currentMIPS->r[29]); //Fixed 9th parameter, thanks to Kingcom
|
||||
u32 retval = func(PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4), PARAM(5), PARAM(6), PARAM(7), param8);
|
||||
RETURN(retval);
|
||||
}
|
||||
|
||||
template<u32 func(int, void *)> void WrapU_IV() {
|
||||
u32 retval = func(PARAM(0), Memory::GetPointer(PARAM(1)));
|
||||
u32 retval = func(PARAM(0), Memory::GetPointerWrite(PARAM(1)));
|
||||
RETURN(retval);
|
||||
}
|
||||
|
||||
|
@ -796,16 +796,16 @@ template <int func(int, const char *, int)> void WrapI_ICI() {
|
|||
}
|
||||
|
||||
template<int func(int, void *, void *, void *, void *, u32, int)> void WrapI_IVVVVUI(){
|
||||
u32 retval = func(PARAM(0), Memory::GetPointer(PARAM(1)), Memory::GetPointer(PARAM(2)), Memory::GetPointer(PARAM(3)), Memory::GetPointer(PARAM(4)), PARAM(5), PARAM(6) );
|
||||
u32 retval = func(PARAM(0), Memory::GetPointerWrite(PARAM(1)), Memory::GetPointerWrite(PARAM(2)), Memory::GetPointerWrite(PARAM(3)), Memory::GetPointerWrite(PARAM(4)), PARAM(5), PARAM(6) );
|
||||
RETURN(retval);
|
||||
}
|
||||
|
||||
template<int func(int, const char *, u32, void *, int, int, int)> void WrapI_ICUVIII(){
|
||||
u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), Memory::GetPointer(PARAM(3)), PARAM(4), PARAM(5), PARAM(6));
|
||||
u32 retval = func(PARAM(0), Memory::GetCharPointer(PARAM(1)), PARAM(2), Memory::GetPointerWrite(PARAM(3)), PARAM(4), PARAM(5), PARAM(6));
|
||||
RETURN(retval);
|
||||
}
|
||||
|
||||
template<int func(void *, u32, int)> void WrapI_VUI(){
|
||||
u32 retval = func(Memory::GetPointer(PARAM(0)), PARAM(1), PARAM(2));
|
||||
u32 retval = func(Memory::GetPointerWrite(PARAM(0)), PARAM(1), PARAM(2));
|
||||
RETURN(retval);
|
||||
}
|
||||
|
|
|
@ -138,7 +138,7 @@ static int Replace_memcpy() {
|
|||
}
|
||||
}
|
||||
if (!skip && bytes != 0) {
|
||||
u8 *dst = Memory::GetPointer(destPtr);
|
||||
u8 *dst = Memory::GetPointerWrite(destPtr);
|
||||
const u8 *src = Memory::GetPointer(srcPtr);
|
||||
|
||||
if (!dst || !src) {
|
||||
|
@ -190,7 +190,7 @@ static int Replace_memcpy_jak() {
|
|||
}
|
||||
}
|
||||
if (!skip && bytes != 0) {
|
||||
u8 *dst = Memory::GetPointer(destPtr);
|
||||
u8 *dst = Memory::GetPointerWrite(destPtr);
|
||||
const u8 *src = Memory::GetPointer(srcPtr);
|
||||
|
||||
if (!dst || !src) {
|
||||
|
@ -240,7 +240,7 @@ static int Replace_memcpy16() {
|
|||
}
|
||||
}
|
||||
if (!skip && bytes != 0) {
|
||||
u8 *dst = Memory::GetPointer(destPtr);
|
||||
u8 *dst = Memory::GetPointerWrite(destPtr);
|
||||
const u8 *src = Memory::GetPointer(srcPtr);
|
||||
if (dst && src) {
|
||||
memmove(dst, src, bytes);
|
||||
|
@ -267,7 +267,7 @@ static int Replace_memcpy_swizzled() {
|
|||
gpu->PerformMemoryDownload(srcPtr, pitch * h);
|
||||
}
|
||||
}
|
||||
u8 *dstp = Memory::GetPointer(destPtr);
|
||||
u8 *dstp = Memory::GetPointerWrite(destPtr);
|
||||
const u8 *srcp = Memory::GetPointer(srcPtr);
|
||||
|
||||
if (dstp && srcp) {
|
||||
|
@ -312,7 +312,7 @@ static int Replace_memmove() {
|
|||
}
|
||||
}
|
||||
if (!skip && bytes != 0) {
|
||||
u8 *dst = Memory::GetPointer(destPtr);
|
||||
u8 *dst = Memory::GetPointerWrite(destPtr);
|
||||
const u8 *src = Memory::GetPointer(srcPtr);
|
||||
if (dst && src) {
|
||||
memmove(dst, src, bytes);
|
||||
|
@ -338,7 +338,7 @@ static int Replace_memset() {
|
|||
skip = gpu->PerformMemorySet(destPtr, value, bytes);
|
||||
}
|
||||
if (!skip && bytes != 0) {
|
||||
u8 *dst = Memory::GetPointer(destPtr);
|
||||
u8 *dst = Memory::GetPointerWrite(destPtr);
|
||||
if (dst) {
|
||||
memset(dst, value, bytes);
|
||||
}
|
||||
|
@ -365,7 +365,7 @@ static int Replace_memset_jak() {
|
|||
skip = gpu->PerformMemorySet(destPtr, value, bytes);
|
||||
}
|
||||
if (!skip && bytes != 0) {
|
||||
u8 *dst = Memory::GetPointer(destPtr);
|
||||
u8 *dst = Memory::GetPointerWrite(destPtr);
|
||||
if (dst) {
|
||||
memset(dst, value, bytes);
|
||||
}
|
||||
|
@ -1361,6 +1361,15 @@ static int Hook_gow_vortex_hack() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int Hook_ZZT3_select_hack() {
|
||||
if (PSP_CoreParameter().compat.flags().ZZT3SelectHack) {
|
||||
if (currentMIPS->r[MIPS_REG_V0] == 0) {
|
||||
currentMIPS->r[MIPS_REG_V0] = 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define JITFUNC(f) (&MIPSComp::MIPSFrontendInterface::f)
|
||||
|
||||
// Can either replace with C functions or functions emitted in Asm/ArmAsm.
|
||||
|
@ -1479,6 +1488,7 @@ static const ReplacementTableEntry entries[] = {
|
|||
{ "soltrigger_render_ucschar", &Hook_soltrigger_render_ucschar, 0, REPFLAG_HOOKENTER, 0 },
|
||||
{ "gow_fps_hack", &Hook_gow_fps_hack, 0, REPFLAG_HOOKEXIT , 0 },
|
||||
{ "gow_vortex_hack", &Hook_gow_vortex_hack, 0, REPFLAG_HOOKENTER, 0x60 },
|
||||
{ "ZZT3_select_hack", &Hook_ZZT3_select_hack, 0, REPFLAG_HOOKENTER, 0xC4 },
|
||||
{}
|
||||
};
|
||||
|
||||
|
|
|
@ -1263,7 +1263,7 @@ void notifyMatchingHandler(SceNetAdhocMatchingContext * context, ThreadMessage *
|
|||
MatchingArgs argsNew = { 0 };
|
||||
u32_le dataBufLen = msg->optlen + 8; //max(bufLen, msg->optlen + 8);
|
||||
u32_le dataBufAddr = userMemory.Alloc(dataBufLen); // We will free this memory after returning from mipscall. FIXME: Are these buffers supposed to be taken/pre-allocated from the memory pool during sceNetAdhocMatchingInit?
|
||||
uint8_t * dataPtr = Memory::GetPointer(dataBufAddr);
|
||||
uint8_t * dataPtr = Memory::GetPointerWrite(dataBufAddr);
|
||||
if (dataPtr) {
|
||||
memcpy(dataPtr, &msg->mac, sizeof(msg->mac));
|
||||
if (msg->optlen > 0)
|
||||
|
|
|
@ -33,7 +33,7 @@ static u32 sceAdler32(u32 adler, u32 data, u32 datalen) {
|
|||
}
|
||||
INFO_LOG(SCEMISC, "sceAdler32(adler=%08x, data=%08x, datalen=%08x)", adler, data, datalen);
|
||||
|
||||
u8 *buf = Memory::GetPointerUnchecked(data);
|
||||
u8 *buf = Memory::GetPointerWriteUnchecked(data);
|
||||
u32 ret = adler32(adler, buf, datalen);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -480,7 +480,7 @@ struct Atrac {
|
|||
}
|
||||
|
||||
u8 *BufferStart() {
|
||||
return ignoreDataBuf_ ? Memory::GetPointer(first_.addr) : dataBuf_;
|
||||
return ignoreDataBuf_ ? Memory::GetPointerWrite(first_.addr) : dataBuf_;
|
||||
}
|
||||
|
||||
void SeekToSample(int sample) {
|
||||
|
@ -1345,7 +1345,7 @@ static u32 sceAtracDecodeData(int atracID, u32 outAddr, u32 numSamplesAddr, u32
|
|||
u32 numSamples = 0;
|
||||
u32 finish = 0;
|
||||
int remains = 0;
|
||||
int ret = _AtracDecodeData(atracID, Memory::GetPointer(outAddr), outAddr, &numSamples, &finish, &remains);
|
||||
int ret = _AtracDecodeData(atracID, Memory::GetPointerWrite(outAddr), outAddr, &numSamples, &finish, &remains);
|
||||
if (ret != (int)ATRAC_ERROR_BAD_ATRACID && ret != (int)ATRAC_ERROR_NO_DATA) {
|
||||
if (Memory::IsValidAddress(numSamplesAddr))
|
||||
Memory::Write_U32(numSamples, numSamplesAddr);
|
||||
|
|
|
@ -116,7 +116,7 @@ static int sceAudiocodecDecode(u32 ctxPtr, int codec) {
|
|||
|
||||
if (decoder != NULL) {
|
||||
// Decode audio
|
||||
decoder->Decode(Memory::GetPointer(ctx->inDataPtr), ctx->inDataSize, Memory::GetPointer(ctx->outDataPtr), &outbytes);
|
||||
decoder->Decode(Memory::GetPointer(ctx->inDataPtr), ctx->inDataSize, Memory::GetPointerWrite(ctx->outDataPtr), &outbytes);
|
||||
}
|
||||
DEBUG_LOG(ME, "sceAudiocodecDec(%08x, %i (%s))", ctxPtr, codec, GetCodecName(codec));
|
||||
return 0;
|
||||
|
|
|
@ -218,7 +218,7 @@ static int sceSdGetLastIndex(u32 addressCtx, u32 addressHash, u32 addressKey)
|
|||
{
|
||||
pspChnnlsvContext1 ctx;
|
||||
Memory::ReadStruct(addressCtx, &ctx);
|
||||
int res = sceSdGetLastIndex_(ctx, Memory::GetPointer(addressHash), Memory::GetPointer(addressKey));
|
||||
int res = sceSdGetLastIndex_(ctx, Memory::GetPointerWrite(addressHash), Memory::GetPointerWrite(addressKey));
|
||||
Memory::WriteStruct(addressCtx, &ctx);
|
||||
return res;
|
||||
}
|
||||
|
@ -348,7 +348,7 @@ static int sceSdRemoveValue(u32 addressCtx, u32 addressData, int length)
|
|||
{
|
||||
pspChnnlsvContext1 ctx;
|
||||
Memory::ReadStruct(addressCtx, &ctx);
|
||||
int res = sceSdRemoveValue_(ctx, Memory::GetPointer(addressData), length);
|
||||
int res = sceSdRemoveValue_(ctx, Memory::GetPointerWrite(addressData), length);
|
||||
Memory::WriteStruct(addressCtx, &ctx);
|
||||
|
||||
return res;
|
||||
|
@ -400,8 +400,8 @@ static int sceSdCreateList(u32 ctx2Addr, int mode, int unkwn, u32 dataAddr, u32
|
|||
{
|
||||
pspChnnlsvContext2 ctx2;
|
||||
Memory::ReadStruct(ctx2Addr, &ctx2);
|
||||
u8* data = Memory::GetPointer(dataAddr);
|
||||
u8* cryptkey = Memory::GetPointer(cryptkeyAddr);
|
||||
u8* data = Memory::GetPointerWrite(dataAddr);
|
||||
u8* cryptkey = Memory::GetPointerWrite(cryptkeyAddr);
|
||||
|
||||
int res = sceSdCreateList_(ctx2, mode, unkwn, data, cryptkey);
|
||||
|
||||
|
@ -468,7 +468,7 @@ static int sceSdSetMember(u32 ctxAddr, u32 dataAddr, int alignedLen)
|
|||
{
|
||||
pspChnnlsvContext2 ctx;
|
||||
Memory::ReadStruct(ctxAddr, &ctx);
|
||||
u8* data = Memory::GetPointer(dataAddr);
|
||||
u8* data = Memory::GetPointerWrite(dataAddr);
|
||||
|
||||
int res = sceSdSetMember_(ctx, data, alignedLen);
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ static int CommonDecompress(int windowBits, u32 OutBuffer, int OutBufferLength,
|
|||
}
|
||||
|
||||
z_stream stream{};
|
||||
u8 *outBufferPtr = Memory::GetPointer(OutBuffer);
|
||||
u8 *outBufferPtr = Memory::GetPointerWrite(OutBuffer);
|
||||
stream.next_in = (Bytef*)Memory::GetPointer(InBuffer);
|
||||
// We don't know the available length, just let it use as much as it wants.
|
||||
stream.avail_in = (uInt)Memory::ValidSize(InBuffer, Memory::g_MemorySize);
|
||||
|
|
|
@ -1042,7 +1042,7 @@ static bool __IoRead(int &result, int id, u32 data_addr, int size, int &us) {
|
|||
} else if (Memory::IsValidAddress(data_addr)) {
|
||||
const std::string tag = "IoRead/" + IODetermineFilename(f);
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, data_addr, size, tag.c_str(), tag.size());
|
||||
u8 *data = (u8 *)Memory::GetPointer(data_addr);
|
||||
u8 *data = (u8 *)Memory::GetPointerUnchecked(data_addr);
|
||||
u32 validSize = Memory::ValidSize(data_addr, size);
|
||||
if (f->npdrm) {
|
||||
result = npdrmRead(f, data, validSize);
|
||||
|
@ -2482,7 +2482,7 @@ static int __IoIoctl(u32 id, u32 cmd, u32 indataPtr, u32 inlen, u32 outdataPtr,
|
|||
u8 pgd_magic[4] = {0x00, 0x50, 0x47, 0x44};
|
||||
|
||||
if (Memory::IsValidAddress(indataPtr) && inlen == 16) {
|
||||
memcpy(keybuf, Memory::GetPointer(indataPtr), 16);
|
||||
memcpy(keybuf, Memory::GetPointerUnchecked(indataPtr), 16);
|
||||
key_ptr = keybuf;
|
||||
}else{
|
||||
key_ptr = NULL;
|
||||
|
|
|
@ -133,7 +133,7 @@ static u32 convertARGBtoABGR(u32 argb) {
|
|||
}
|
||||
|
||||
static int __DecodeJpeg(u32 jpegAddr, int jpegSize, u32 imageAddr) {
|
||||
u8 *buf = Memory::GetPointer(jpegAddr);
|
||||
const u8 *buf = Memory::GetPointer(jpegAddr);
|
||||
int width, height, actual_components;
|
||||
unsigned char *jpegBuf = jpgd::decompress_jpeg_image_from_memory(buf, jpegSize, &width, &height, &actual_components, 3);
|
||||
|
||||
|
@ -219,7 +219,7 @@ static int getYCbCrBufferSize(int w, int h) {
|
|||
}
|
||||
|
||||
static int __JpegGetOutputInfo(u32 jpegAddr, int jpegSize, u32 colourInfoAddr) {
|
||||
u8 *buf = Memory::GetPointer(jpegAddr);
|
||||
const u8 *buf = Memory::GetPointer(jpegAddr);
|
||||
int width, height, actual_components;
|
||||
unsigned char *jpegBuf = jpgd::decompress_jpeg_image_from_memory(buf, jpegSize, &width, &height, &actual_components, 3);
|
||||
|
||||
|
@ -325,7 +325,7 @@ static int __JpegConvertRGBToYCbCr (const void *data, u32 bufferOutputAddr, int
|
|||
}
|
||||
|
||||
static int __JpegDecodeMJpegYCbCr(u32 jpegAddr, int jpegSize, u32 yCbCrAddr) {
|
||||
u8 *buf = Memory::GetPointer(jpegAddr);
|
||||
const u8 *buf = Memory::GetPointer(jpegAddr);
|
||||
int width, height, actual_components;
|
||||
unsigned char *jpegBuf = jpgd::decompress_jpeg_image_from_memory(buf, jpegSize, &width, &height, &actual_components, 3);
|
||||
|
||||
|
|
|
@ -634,8 +634,8 @@ static u32 sceKernelMemcpy(u32 dst, u32 src, u32 size)
|
|||
// Technically should crash if these are invalid and size > 0...
|
||||
if (!skip && Memory::IsValidAddress(dst) && Memory::IsValidAddress(src) && Memory::IsValidAddress(dst + size - 1) && Memory::IsValidAddress(src + size - 1))
|
||||
{
|
||||
u8 *dstp = Memory::GetPointerUnchecked(dst);
|
||||
u8 *srcp = Memory::GetPointerUnchecked(src);
|
||||
u8 *dstp = Memory::GetPointerWriteUnchecked(dst);
|
||||
const u8 *srcp = Memory::GetPointerUnchecked(src);
|
||||
|
||||
// If it's non-overlapping, just do it in one go.
|
||||
if (dst + size < src || src + size < dst)
|
||||
|
@ -688,7 +688,7 @@ const HLEFunction Kernel_Library[] =
|
|||
|
||||
static u32 sysclib_memcpy(u32 dst, u32 src, u32 size) {
|
||||
if (Memory::IsValidRange(dst, size) && Memory::IsValidRange(src, size)) {
|
||||
memcpy(Memory::GetPointer(dst), Memory::GetPointer(src), size);
|
||||
memcpy(Memory::GetPointerWriteUnchecked(dst), Memory::GetPointerUnchecked(src), size);
|
||||
}
|
||||
if (MemBlockInfoDetailed(size)) {
|
||||
const std::string tag = "KernelMemcpy/" + GetMemWriteTagAt(src, size);
|
||||
|
@ -701,7 +701,7 @@ static u32 sysclib_memcpy(u32 dst, u32 src, u32 size) {
|
|||
static u32 sysclib_strcat(u32 dst, u32 src) {
|
||||
ERROR_LOG(SCEKERNEL, "Untested sysclib_strcat(dest=%08x, src=%08x)", dst, src);
|
||||
if (Memory::IsValidAddress(dst) && Memory::IsValidAddress(src)) {
|
||||
strcat((char *)Memory::GetPointer(dst), (char *)Memory::GetPointer(src));
|
||||
strcat((char *)Memory::GetPointerWriteUnchecked(dst), (const char *)Memory::GetPointerUnchecked(src));
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
@ -709,7 +709,7 @@ static u32 sysclib_strcat(u32 dst, u32 src) {
|
|||
static int sysclib_strcmp(u32 dst, u32 src) {
|
||||
ERROR_LOG(SCEKERNEL, "Untested sysclib_strcmp(dest=%08x, src=%08x)", dst, src);
|
||||
if (Memory::IsValidAddress(dst) && Memory::IsValidAddress(src)) {
|
||||
return strcmp((char *)Memory::GetPointer(dst), (char *)Memory::GetPointer(src));
|
||||
return strcmp((const char *)Memory::GetPointerUnchecked(dst), (const char *)Memory::GetPointerUnchecked(src));
|
||||
} else {
|
||||
// What to do? Crash, probably.
|
||||
return 0;
|
||||
|
@ -719,7 +719,7 @@ static int sysclib_strcmp(u32 dst, u32 src) {
|
|||
static u32 sysclib_strcpy(u32 dst, u32 src) {
|
||||
ERROR_LOG(SCEKERNEL, "Untested sysclib_strcpy(dest=%08x, src=%08x)", dst, src);
|
||||
if (Memory::IsValidAddress(dst) && Memory::IsValidAddress(src)) {
|
||||
strcpy((char *)Memory::GetPointer(dst), (char *)Memory::GetPointer(src));
|
||||
strcpy((char *)Memory::GetPointerWriteUnchecked(dst), (const char *)Memory::GetPointerUnchecked(src));
|
||||
}
|
||||
return dst;
|
||||
}
|
||||
|
@ -758,7 +758,7 @@ static int sysclib_sprintf(u32 dst, u32 fmt) {
|
|||
static u32 sysclib_memset(u32 destAddr, int data, int size) {
|
||||
ERROR_LOG(SCEKERNEL, "Untested sysclib_memset(dest=%08x, data=%d ,size=%d)", destAddr, data, size);
|
||||
if (Memory::IsValidRange(destAddr, size)) {
|
||||
memset(Memory::GetPointer(destAddr), data, size);
|
||||
memset(Memory::GetPointerWriteUnchecked(destAddr), data, size);
|
||||
}
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, destAddr, size, "KernelMemset");
|
||||
return 0;
|
||||
|
@ -791,7 +791,7 @@ static int sysclib_strncmp(u32 s1, u32 s2, u32 size) {
|
|||
static u32 sysclib_memmove(u32 dst, u32 src, u32 size) {
|
||||
ERROR_LOG(SCEKERNEL, "Untested sysclib_memmove(%08x, %08x, %08x)", dst, src, size);
|
||||
if (Memory::IsValidRange(dst, size) && Memory::IsValidRange(src, size)) {
|
||||
memmove(Memory::GetPointer(dst), Memory::GetPointer(src), size);
|
||||
memmove(Memory::GetPointerWriteUnchecked(dst), Memory::GetPointerUnchecked(src), size);
|
||||
}
|
||||
if (MemBlockInfoDetailed(size)) {
|
||||
const std::string tag = "KernelMemmove/" + GetMemWriteTagAt(src, size);
|
||||
|
@ -810,7 +810,7 @@ static u32 sysclib_strncpy(u32 dest, u32 src, u32 size) {
|
|||
u32 i = 0;
|
||||
u32 srcSize = Memory::ValidSize(src, size);
|
||||
const u8 *srcp = Memory::GetPointer(src);
|
||||
u8 *destp = Memory::GetPointer(dest);
|
||||
u8 *destp = Memory::GetPointerWrite(dest);
|
||||
for (i = 0; i < srcSize; ++i) {
|
||||
u8 c = *srcp++;
|
||||
if (c == 0)
|
||||
|
|
|
@ -432,7 +432,7 @@ void __KernelMemoryInit()
|
|||
MemBlockInfoInit();
|
||||
kernelMemory.Init(PSP_GetKernelMemoryBase(), PSP_GetKernelMemoryEnd() - PSP_GetKernelMemoryBase(), false);
|
||||
userMemory.Init(PSP_GetUserMemoryBase(), PSP_GetUserMemoryEnd() - PSP_GetUserMemoryBase(), false);
|
||||
ParallelMemset(&g_threadManager, Memory::GetPointer(PSP_GetKernelMemoryBase()), 0, PSP_GetUserMemoryEnd() - PSP_GetKernelMemoryBase());
|
||||
ParallelMemset(&g_threadManager, Memory::GetPointerWrite(PSP_GetKernelMemoryBase()), 0, PSP_GetUserMemoryEnd() - PSP_GetKernelMemoryBase());
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, PSP_GetKernelMemoryBase(), PSP_GetUserMemoryEnd() - PSP_GetKernelMemoryBase(), "MemInit");
|
||||
INFO_LOG(SCEKERNEL, "Kernel and user memory pools initialized");
|
||||
|
||||
|
|
|
@ -218,7 +218,7 @@ struct MsgPipe : public KernelObject
|
|||
// Receive as much as possible, even if it's not enough to wake up.
|
||||
u32 bytesToSend = std::min(thread->freeSize, GetUsedSize());
|
||||
|
||||
u8* ptr = Memory::GetPointer(buffer);
|
||||
u8* ptr = Memory::GetPointerWrite(buffer);
|
||||
thread->WriteBuffer(buffer, bytesToSend);
|
||||
// Put the unused data at the start of the buffer.
|
||||
nmp.freeSize += bytesToSend;
|
||||
|
@ -494,7 +494,7 @@ static int __KernelReceiveMsgPipe(MsgPipe *m, u32 receiveBufAddr, u32 receiveSiz
|
|||
{
|
||||
Memory::Memcpy(curReceiveAddr, m->buffer, bytesToReceive, "MsgPipeReceive");
|
||||
m->nmp.freeSize += bytesToReceive;
|
||||
memmove(Memory::GetPointer(m->buffer), Memory::GetPointer(m->buffer) + bytesToReceive, m->GetUsedSize());
|
||||
memmove(Memory::GetPointerWrite(m->buffer), Memory::GetPointer(m->buffer) + bytesToReceive, m->GetUsedSize());
|
||||
curReceiveAddr += bytesToReceive;
|
||||
receiveSize -= bytesToReceive;
|
||||
|
||||
|
|
|
@ -466,8 +466,8 @@ int sceKernelPollSema(SceUID id, int wantedCount)
|
|||
|
||||
static u32 sceUtilsBufferCopyWithRange(u32 outAddr, int outSize, u32 inAddr, int inSize, int cmd)
|
||||
{
|
||||
u8 *outAddress = Memory::IsValidRange(outAddr, outSize) ? Memory::GetPointer(outAddr) : nullptr;
|
||||
const u8 *inAddress = Memory::IsValidRange(inAddr, inSize) ? Memory::GetPointer(inAddr) : nullptr;
|
||||
u8 *outAddress = Memory::IsValidRange(outAddr, outSize) ? Memory::GetPointerWriteUnchecked(outAddr) : nullptr;
|
||||
const u8 *inAddress = Memory::IsValidRange(inAddr, inSize) ? Memory::GetPointerUnchecked(inAddr) : nullptr;
|
||||
int temp = kirk_sceUtilsBufferCopyWithRange(outAddress, outSize, inAddress, inSize, cmd);
|
||||
if (temp != 0) {
|
||||
ERROR_LOG(SCEKERNEL, "hleUtilsBufferCopyWithRange: Failed with %d", temp);
|
||||
|
@ -478,8 +478,8 @@ static u32 sceUtilsBufferCopyWithRange(u32 outAddr, int outSize, u32 inAddr, int
|
|||
// Note sure what difference there is between this and sceUtilsBufferCopyWithRange.
|
||||
static int sceUtilsBufferCopyByPollingWithRange(u32 outAddr, int outSize, u32 inAddr, int inSize, int cmd)
|
||||
{
|
||||
u8 *outAddress = Memory::IsValidRange(outAddr, outSize) ? Memory::GetPointer(outAddr) : nullptr;
|
||||
const u8 *inAddress = Memory::IsValidRange(inAddr, inSize) ? Memory::GetPointer(inAddr) : nullptr;
|
||||
u8 *outAddress = Memory::IsValidRange(outAddr, outSize) ? Memory::GetPointerWriteUnchecked(outAddr) : nullptr;
|
||||
const u8 *inAddress = Memory::IsValidRange(inAddr, inSize) ? Memory::GetPointerUnchecked(inAddr) : nullptr;
|
||||
return kirk_sceUtilsBufferCopyWithRange(outAddress, outSize, inAddress, inSize, cmd);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ u32 sceKernelUtilsMt19937Init(u32 ctx, u32 seed) {
|
|||
DEBUG_LOG(HLE, "sceKernelUtilsMt19937Init(%08x, %08x)", ctx, seed);
|
||||
if (!Memory::IsValidAddress(ctx))
|
||||
return -1;
|
||||
void *ptr = Memory::GetPointer(ctx);
|
||||
void *ptr = Memory::GetPointerWrite(ctx);
|
||||
// This is made to match the memory layout of a PSP MT structure exactly.
|
||||
// Let's just construct it in place with placement new. Elite C++ hackery FTW.
|
||||
new (ptr) MersenneTwister(seed);
|
||||
|
@ -43,7 +43,7 @@ u32 sceKernelUtilsMt19937UInt(u32 ctx) {
|
|||
VERBOSE_LOG(HLE, "sceKernelUtilsMt19937UInt(%08x)", ctx);
|
||||
if (!Memory::IsValidAddress(ctx))
|
||||
return -1;
|
||||
MersenneTwister *mt = (MersenneTwister *)Memory::GetPointer(ctx);
|
||||
MersenneTwister *mt = (MersenneTwister *)Memory::GetPointerUnchecked(ctx);
|
||||
return mt->R32();
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ static int sceMd5Digest(u32 dataAddr, u32 len, u32 digestAddr) {
|
|||
if (!Memory::IsValidAddress(dataAddr) || !Memory::IsValidAddress(digestAddr))
|
||||
return -1;
|
||||
|
||||
md5(Memory::GetPointer(dataAddr), (int)len, Memory::GetPointer(digestAddr));
|
||||
md5(Memory::GetPointerWriteUnchecked(dataAddr), (int)len, Memory::GetPointerWriteUnchecked(digestAddr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ static int sceMd5BlockUpdate(u32 ctxAddr, u32 dataPtr, u32 len) {
|
|||
if (!Memory::IsValidAddress(ctxAddr) || !Memory::IsValidAddress(dataPtr))
|
||||
return -1;
|
||||
|
||||
md5_update(&md5_ctx, Memory::GetPointer(dataPtr), (int)len);
|
||||
md5_update(&md5_ctx, Memory::GetPointerWriteUnchecked(dataPtr), (int)len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ static int sceMd5BlockResult(u32 ctxAddr, u32 digestAddr) {
|
|||
if (!Memory::IsValidAddress(ctxAddr) || !Memory::IsValidAddress(digestAddr))
|
||||
return -1;
|
||||
|
||||
md5_finish(&md5_ctx, Memory::GetPointer(digestAddr));
|
||||
md5_finish(&md5_ctx, Memory::GetPointerWriteUnchecked(digestAddr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -97,7 +97,7 @@ int sceKernelUtilsMd5Digest(u32 dataAddr, int len, u32 digestAddr) {
|
|||
if (!Memory::IsValidAddress(dataAddr) || !Memory::IsValidAddress(digestAddr))
|
||||
return -1;
|
||||
|
||||
md5(Memory::GetPointer(dataAddr), (int)len, Memory::GetPointer(digestAddr));
|
||||
md5(Memory::GetPointerWriteUnchecked(dataAddr), (int)len, Memory::GetPointerWriteUnchecked(digestAddr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ int sceKernelUtilsMd5BlockUpdate(u32 ctxAddr, u32 dataPtr, int len) {
|
|||
if (!Memory::IsValidAddress(ctxAddr) || !Memory::IsValidAddress(dataPtr))
|
||||
return -1;
|
||||
|
||||
md5_update(&md5_ctx, Memory::GetPointer(dataPtr), (int)len);
|
||||
md5_update(&md5_ctx, Memory::GetPointerWriteUnchecked(dataPtr), (int)len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -127,7 +127,7 @@ int sceKernelUtilsMd5BlockResult(u32 ctxAddr, u32 digestAddr) {
|
|||
if (!Memory::IsValidAddress(ctxAddr) || !Memory::IsValidAddress(digestAddr))
|
||||
return -1;
|
||||
|
||||
md5_finish(&md5_ctx, Memory::GetPointer(digestAddr));
|
||||
md5_finish(&md5_ctx, Memory::GetPointerWriteUnchecked(digestAddr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -140,7 +140,7 @@ int sceKernelUtilsSha1Digest(u32 dataAddr, int len, u32 digestAddr) {
|
|||
if (!Memory::IsValidAddress(dataAddr) || !Memory::IsValidAddress(digestAddr))
|
||||
return -1;
|
||||
|
||||
sha1(Memory::GetPointer(dataAddr), (int)len, Memory::GetPointer(digestAddr));
|
||||
sha1(Memory::GetPointerWriteUnchecked(dataAddr), (int)len, Memory::GetPointerWriteUnchecked(digestAddr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -162,7 +162,7 @@ int sceKernelUtilsSha1BlockUpdate(u32 ctxAddr, u32 dataAddr, int len) {
|
|||
if (!Memory::IsValidAddress(ctxAddr) || !Memory::IsValidAddress(dataAddr))
|
||||
return -1;
|
||||
|
||||
sha1_update(&sha1_ctx, Memory::GetPointer(dataAddr), (int)len);
|
||||
sha1_update(&sha1_ctx, Memory::GetPointerWriteUnchecked(dataAddr), (int)len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -171,7 +171,7 @@ int sceKernelUtilsSha1BlockResult(u32 ctxAddr, u32 digestAddr) {
|
|||
if (!Memory::IsValidAddress(ctxAddr) || !Memory::IsValidAddress(digestAddr))
|
||||
return -1;
|
||||
|
||||
sha1_finish(&sha1_ctx, Memory::GetPointer(digestAddr));
|
||||
sha1_finish(&sha1_ctx, Memory::GetPointerWriteUnchecked(digestAddr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -364,7 +364,7 @@ static int CalculateMp3SamplesPerFrame(int versionBits, int layerBits) {
|
|||
static int FindMp3Header(AuCtx *ctx, int &header, int end) {
|
||||
u32 addr = ctx->AuBuf + ctx->AuStreamWorkareaSize();
|
||||
if (Memory::IsValidRange(addr, end)) {
|
||||
u8 *ptr = Memory::GetPointerUnchecked(addr);
|
||||
const u8 *ptr = Memory::GetPointerUnchecked(addr);
|
||||
for (int offset = 0; offset < end; ++offset) {
|
||||
// If we hit valid sync bits, then we've found a header.
|
||||
if (ptr[offset] == 0xFF && (ptr[offset + 1] & 0xC0) == 0xC0) {
|
||||
|
@ -689,11 +689,11 @@ static u32 sceMp3LowLevelDecode(u32 mp3, u32 sourceAddr, u32 sourceBytesConsumed
|
|||
return -1;
|
||||
}
|
||||
|
||||
auto inbuff = Memory::GetPointer(sourceAddr);
|
||||
auto outbuff = Memory::GetPointer(samplesAddr);
|
||||
auto inbuff = Memory::GetPointerWriteUnchecked(sourceAddr);
|
||||
auto outbuff = Memory::GetPointerWriteUnchecked(samplesAddr);
|
||||
|
||||
int outpcmbytes = 0;
|
||||
ctx->decoder->Decode((void*)inbuff, 4096, outbuff, &outpcmbytes);
|
||||
ctx->decoder->Decode(inbuff, 4096, outbuff, &outpcmbytes);
|
||||
NotifyMemInfo(MemBlockFlags::WRITE, samplesAddr, outpcmbytes, "Mp3LowLevelDecode");
|
||||
|
||||
Memory::Write_U32(ctx->decoder->GetSourcePos(), sourceBytesConsumedAddr);
|
||||
|
|
|
@ -628,7 +628,7 @@ static int sceMpegQueryStreamOffset(u32 mpeg, u32 bufferAddr, u32 offsetAddr)
|
|||
DEBUG_LOG(ME, "sceMpegQueryStreamOffset(%08x, %08x, %08x)", mpeg, bufferAddr, offsetAddr);
|
||||
|
||||
// Kinda destructive, no?
|
||||
AnalyzeMpeg(Memory::GetPointer(bufferAddr), Memory::ValidSize(bufferAddr, 32768), ctx);
|
||||
AnalyzeMpeg(Memory::GetPointerWriteUnchecked(bufferAddr), Memory::ValidSize(bufferAddr, 32768), ctx);
|
||||
|
||||
if (ctx->mpegMagic != PSMF_MAGIC) {
|
||||
ERROR_LOG(ME, "sceMpegQueryStreamOffset: Bad PSMF magic");
|
||||
|
@ -660,7 +660,7 @@ static u32 sceMpegQueryStreamSize(u32 bufferAddr, u32 sizeAddr)
|
|||
MpegContext ctx;
|
||||
ctx.mediaengine = 0;
|
||||
|
||||
AnalyzeMpeg(Memory::GetPointer(bufferAddr), Memory::ValidSize(bufferAddr, 32768), &ctx);
|
||||
AnalyzeMpeg(Memory::GetPointerWriteUnchecked(bufferAddr), Memory::ValidSize(bufferAddr, 32768), &ctx);
|
||||
|
||||
if (ctx.mpegMagic != PSMF_MAGIC) {
|
||||
ERROR_LOG(ME, "sceMpegQueryStreamSize: Bad PSMF magic");
|
||||
|
@ -965,7 +965,7 @@ static bool decodePmpVideo(PSPPointer<SceMpegRingBuffer> ringbuffer, u32 pmpctxA
|
|||
for (int i = 0; i < pmp_nBlocks; i++){
|
||||
auto lli = PSPPointer<SceMpegLLI>::Create(pmp_videoSource);
|
||||
// add source block into pmpframes
|
||||
pmpframes->add(Memory::GetPointer(lli->pSrc), lli->iSize);
|
||||
pmpframes->add(Memory::GetPointerWrite(lli->pSrc), lli->iSize);
|
||||
// get next block
|
||||
pmp_videoSource += sizeof(SceMpegLLI);
|
||||
}
|
||||
|
@ -1962,7 +1962,8 @@ static u32 sceMpegAvcCopyYCbCr(u32 mpeg, u32 sourceAddr, u32 YCbCrAddr)
|
|||
return -1;
|
||||
}
|
||||
|
||||
WARN_LOG(ME, "UNIMPL sceMpegAvcCopyYCbCr(%08x, %08x, %08x)", mpeg, sourceAddr, YCbCrAddr);
|
||||
// This is very common.
|
||||
DEBUG_LOG(ME, "UNIMPL sceMpegAvcCopyYCbCr(%08x, %08x, %08x)", mpeg, sourceAddr, YCbCrAddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ static u32 sceMt19937Init(u32 mt19937Addr, u32 seed)
|
|||
{
|
||||
if (!Memory::IsValidAddress(mt19937Addr))
|
||||
return hleLogError(HLE, -1);
|
||||
void *ptr = Memory::GetPointer(mt19937Addr);
|
||||
void *ptr = Memory::GetPointerWriteUnchecked(mt19937Addr);
|
||||
// This is made to match the memory layout of a PSP MT structure exactly.
|
||||
// Let's just construct it in place with placement new. Elite C++ hackery FTW.
|
||||
new (ptr) MersenneTwister(seed);
|
||||
|
|
|
@ -684,7 +684,7 @@ static u32 sceWlanGetEtherAddr(u32 addrAddr) {
|
|||
return hleLogError(SCENET, SCE_KERNEL_ERROR_ILLEGAL_ADDR, "illegal address");
|
||||
}
|
||||
|
||||
u8 *addr = Memory::GetPointer(addrAddr);
|
||||
u8 *addr = Memory::GetPointerWriteUnchecked(addrAddr);
|
||||
if (PPSSPP_ID > 1) {
|
||||
Memory::Memset(addrAddr, PPSSPP_ID, 6);
|
||||
// Making sure the 1st 2-bits on the 1st byte of OUI are zero to prevent issue with some games (ie. Gran Turismo)
|
||||
|
@ -722,8 +722,8 @@ static void sceNetEtherNtostr(u32 macPtr, u32 bufferPtr) {
|
|||
DEBUG_LOG(SCENET, "sceNetEtherNtostr(%08x, %08x) at %08x", macPtr, bufferPtr, currentMIPS->pc);
|
||||
|
||||
if (Memory::IsValidAddress(bufferPtr) && Memory::IsValidAddress(macPtr)) {
|
||||
char *buffer = (char *)Memory::GetPointer(bufferPtr);
|
||||
const u8 *mac = Memory::GetPointer(macPtr);
|
||||
char *buffer = (char *)Memory::GetPointerWriteUnchecked(bufferPtr);
|
||||
const u8 *mac = Memory::GetPointerUnchecked(macPtr);
|
||||
|
||||
// MAC address is always 6 bytes / 48 bits.
|
||||
sprintf(buffer, "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
|
@ -748,8 +748,8 @@ static void sceNetEtherStrton(u32 bufferPtr, u32 macPtr) {
|
|||
DEBUG_LOG(SCENET, "sceNetEtherStrton(%08x, %08x)", bufferPtr, macPtr);
|
||||
|
||||
if (Memory::IsValidAddress(bufferPtr) && Memory::IsValidAddress(macPtr)) {
|
||||
const char *buffer = (char *)Memory::GetPointer(bufferPtr);
|
||||
u8 *mac = Memory::GetPointer(macPtr);
|
||||
const char *buffer = (const char *)Memory::GetPointerUnchecked(bufferPtr);
|
||||
u8 *mac = Memory::GetPointerWrite(macPtr);
|
||||
|
||||
// MAC address is always 6 pairs of hex digits.
|
||||
// TODO: Funny stuff happens if it's too short.
|
||||
|
@ -896,7 +896,7 @@ static int sceNetApctlGetInfo(int code, u32 pInfoAddr) {
|
|||
if (!Memory::IsValidAddress(pInfoAddr))
|
||||
return hleLogError(SCENET, -1, "apctl invalid arg");
|
||||
|
||||
u8* info = Memory::GetPointer(pInfoAddr); // FIXME: Points to a union instead of a struct thus each field have the same address
|
||||
u8* info = Memory::GetPointerWrite(pInfoAddr); // FIXME: Points to a union instead of a struct thus each field have the same address
|
||||
|
||||
switch (code) {
|
||||
case PSP_NET_APCTL_INFO_PROFILE_NAME:
|
||||
|
|
|
@ -5120,7 +5120,7 @@ static int sceNetAdhocMatchingSelectTarget(int matchingId, const char *macAddres
|
|||
if ((optLen == 0) || (optLen > 0 && optDataPtr != 0))
|
||||
{
|
||||
void * opt = NULL;
|
||||
if (Memory::IsValidAddress(optDataPtr)) opt = Memory::GetPointer(optDataPtr);
|
||||
if (Memory::IsValidAddress(optDataPtr)) opt = Memory::GetPointerWriteUnchecked(optDataPtr);
|
||||
// Host Mode
|
||||
if (context->mode == PSP_ADHOC_MATCHING_MODE_PARENT)
|
||||
{
|
||||
|
@ -5247,7 +5247,7 @@ int NetAdhocMatching_CancelTargetWithOpt(int matchingId, const char* macAddress,
|
|||
{
|
||||
SceNetEtherAddr* target = (SceNetEtherAddr*)macAddress;
|
||||
void* opt = NULL;
|
||||
if (Memory::IsValidAddress(optDataPtr)) opt = Memory::GetPointer(optDataPtr);
|
||||
if (Memory::IsValidAddress(optDataPtr)) opt = Memory::GetPointerWriteUnchecked(optDataPtr);
|
||||
|
||||
// Valid Arguments
|
||||
if (target != NULL && ((optLen == 0) || (optLen > 0 && opt != NULL)))
|
||||
|
@ -5351,7 +5351,7 @@ int sceNetAdhocMatchingGetHelloOpt(int matchingId, u32 optLenAddr, u32 optDataAd
|
|||
// Get OptData
|
||||
*optlen = item->hellolen;
|
||||
if ((*optlen > 0) && Memory::IsValidAddress(optDataAddr)) {
|
||||
uint8_t * optdata = Memory::GetPointer(optDataAddr);
|
||||
uint8_t * optdata = Memory::GetPointerWriteUnchecked(optDataAddr);
|
||||
memcpy(optdata, item->hello, *optlen);
|
||||
}
|
||||
//else return ERROR_NET_ADHOC_MATCHING_INVALID_ARG;
|
||||
|
@ -5666,7 +5666,7 @@ int sceNetAdhocMatchingSendData(int matchingId, const char *mac, int dataLen, u3
|
|||
return hleLogError(SCENET, ERROR_NET_ADHOC_MATCHING_INVALID_DATALEN, "invalid datalen");
|
||||
|
||||
void* data = NULL;
|
||||
if (Memory::IsValidAddress(dataAddr)) data = Memory::GetPointer(dataAddr);
|
||||
if (Memory::IsValidAddress(dataAddr)) data = Memory::GetPointerWriteUnchecked(dataAddr);
|
||||
|
||||
// Lock the peer
|
||||
std::lock_guard<std::recursive_mutex> peer_guard(peerlock);
|
||||
|
|
|
@ -267,7 +267,7 @@ static int sceNpAuthGetTicket(u32 requestId, u32 bufferAddr, u32 length)
|
|||
// Dummy Login ticket returned as Login response. Dummy ticket contents were taken from https://www.psdevwiki.com/ps3/X-I-5-Ticket
|
||||
ticket.header.version = TICKET_VER_2_1;
|
||||
ticket.header.size = 0xF0; // size excluding the header
|
||||
u8* buf = Memory::GetPointer(bufferAddr + sizeof(ticket));
|
||||
u8* buf = Memory::GetPointerWrite(bufferAddr + sizeof(ticket));
|
||||
int ofs = 0;
|
||||
ofs += writeTicketParam(buf, PARAM_TYPE_STRING_ASCII, "\x4c\x47\x56\x3b\x81\x39\x4a\x22\xd8\x6b\xc1\x57\x71\x6e\xfd\xb8\xab\x63\xcc\x51", 20); // 20 random letters, token key?
|
||||
ofs += writeTicketU32Param(buf + ofs, PARAM_TYPE_INT, 0x0100); // a flags?
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
static int scePauth_F7AA47F6(u32 srcPtr, int srcLength, u32 destLengthPtr, u32 workArea)
|
||||
{
|
||||
auto src = Memory::GetPointer(srcPtr);
|
||||
auto src = Memory::GetPointerWrite(srcPtr);
|
||||
auto key = Memory::GetPointer(workArea);
|
||||
|
||||
const auto decryptResult = pspDecryptPRX(src, src, srcLength, key);
|
||||
|
@ -46,7 +46,7 @@ static int scePauth_F7AA47F6(u32 srcPtr, int srcLength, u32 destLengthPtr, u32 w
|
|||
|
||||
static int scePauth_98B83B5D(u32 srcPtr, int srcLength, u32 destLengthPtr, u32 workArea)
|
||||
{
|
||||
auto src = Memory::GetPointer(srcPtr);
|
||||
auto src = Memory::GetPointerWrite(srcPtr);
|
||||
auto key = Memory::GetPointer(workArea);
|
||||
|
||||
const auto decryptResult = pspDecryptPRX(src, src, srcLength, key);
|
||||
|
|
|
@ -29,10 +29,10 @@ static int sceSha256Digest(u32 data, int dataLen, u32 digestPtr) {
|
|||
INFO_LOG(HLE, "sceSha256Digest(data=%08x, len=%d, digest=%08x)", data, dataLen, digestPtr);
|
||||
|
||||
// Already checked above...
|
||||
u8 *digest = Memory::GetPointerUnchecked(digestPtr);
|
||||
u8 *digest = Memory::GetPointerWriteUnchecked(digestPtr);
|
||||
sha256_context ctx;
|
||||
sha256_starts(&ctx);
|
||||
sha256_update(&ctx, Memory::GetPointerUnchecked(data), dataLen);
|
||||
sha256_update(&ctx, Memory::GetPointerWriteUnchecked(data), dataLen);
|
||||
sha256_finish(&ctx, digest);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -805,7 +805,7 @@ int MediaEngine::writeVideoImage(u32 bufferPtr, int frameWidth, int videoPixelMo
|
|||
return 0;
|
||||
}
|
||||
|
||||
u8 *buffer = Memory::GetPointer(bufferPtr);
|
||||
u8 *buffer = Memory::GetPointerWrite(bufferPtr);
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
if (!m_pFrame || !m_pFrameRGB)
|
||||
|
@ -895,7 +895,7 @@ int MediaEngine::writeVideoImageWithRange(u32 bufferPtr, int frameWidth, int vid
|
|||
return 0;
|
||||
}
|
||||
|
||||
u8 *buffer = Memory::GetPointer(bufferPtr);
|
||||
u8 *buffer = Memory::GetPointerWrite(bufferPtr);
|
||||
|
||||
#ifdef USE_FFMPEG
|
||||
if (!m_pFrame || !m_pFrameRGB)
|
||||
|
@ -1032,7 +1032,7 @@ int MediaEngine::getAudioSamples(u32 bufferPtr) {
|
|||
ERROR_LOG_REPORT(ME, "Ignoring bad audio decode address %08x during video playback", bufferPtr);
|
||||
}
|
||||
|
||||
u8 *buffer = Memory::GetPointer(bufferPtr);
|
||||
u8 *buffer = Memory::GetPointerWrite(bufferPtr);
|
||||
if (!m_demux) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -64,13 +64,13 @@ void VagDecoder::Start(u32 data, u32 vagSize, bool loopEnabled) {
|
|||
s_2 = 0;
|
||||
}
|
||||
|
||||
void VagDecoder::DecodeBlock(u8 *&read_pointer) {
|
||||
void VagDecoder::DecodeBlock(const u8 *&read_pointer) {
|
||||
if (curBlock_ == numBlocks_ - 1) {
|
||||
end_ = true;
|
||||
return;
|
||||
}
|
||||
|
||||
u8 *readp = read_pointer;
|
||||
const u8 *readp = read_pointer;
|
||||
int predict_nr = *readp++;
|
||||
int shift_factor = predict_nr & 0xf;
|
||||
predict_nr >>= 4;
|
||||
|
@ -124,8 +124,8 @@ void VagDecoder::GetSamples(s16 *outSamples, int numSamples) {
|
|||
WARN_LOG(SASMIX, "Bad VAG samples address?");
|
||||
return;
|
||||
}
|
||||
u8 *readp = Memory::GetPointerUnchecked(read_);
|
||||
u8 *origp = readp;
|
||||
const u8 *readp = Memory::GetPointerUnchecked(read_);
|
||||
const u8 *origp = readp;
|
||||
|
||||
for (int i = 0; i < numSamples; i++) {
|
||||
if (curSample == 28) {
|
||||
|
|
|
@ -102,7 +102,7 @@ public:
|
|||
|
||||
void GetSamples(s16 *outSamples, int numSamples);
|
||||
|
||||
void DecodeBlock(u8 *&readp);
|
||||
void DecodeBlock(const u8 *&readp);
|
||||
bool End() const { return end_; }
|
||||
|
||||
void DoState(PointerWrap &p);
|
||||
|
|
|
@ -177,7 +177,7 @@ bool SimpleAudio::IsOK() const {
|
|||
#endif
|
||||
}
|
||||
|
||||
bool SimpleAudio::Decode(void *inbuf, int inbytes, uint8_t *outbuf, int *outbytes) {
|
||||
bool SimpleAudio::Decode(const uint8_t *inbuf, int inbytes, uint8_t *outbuf, int *outbytes) {
|
||||
#ifdef USE_FFMPEG
|
||||
if (!codecOpen_) {
|
||||
OpenCodec(inbytes);
|
||||
|
@ -185,7 +185,7 @@ bool SimpleAudio::Decode(void *inbuf, int inbytes, uint8_t *outbuf, int *outbyte
|
|||
|
||||
AVPacket packet;
|
||||
av_init_packet(&packet);
|
||||
packet.data = static_cast<uint8_t *>(inbuf);
|
||||
packet.data = (uint8_t *)(inbuf);
|
||||
packet.size = inbytes;
|
||||
|
||||
int got_frame = 0;
|
||||
|
@ -338,7 +338,7 @@ size_t AuCtx::FindNextMp3Sync() {
|
|||
// return output pcm size, <0 error
|
||||
u32 AuCtx::AuDecode(u32 pcmAddr) {
|
||||
u32 outptr = PCMBuf + nextOutputHalf * PCMBufSize / 2;
|
||||
auto outbuf = Memory::GetPointer(outptr);
|
||||
auto outbuf = Memory::GetPointerWrite(outptr);
|
||||
int outpcmbufsize = 0;
|
||||
|
||||
if (pcmAddr)
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
SimpleAudio(int audioType, int sample_rate = 44100, int channels = 2);
|
||||
~SimpleAudio();
|
||||
|
||||
bool Decode(void* inbuf, int inbytes, uint8_t *outbuf, int *outbytes);
|
||||
bool Decode(const uint8_t* inbuf, int inbytes, uint8_t *outbuf, int *outbytes);
|
||||
bool IsOK() const;
|
||||
|
||||
int GetOutSamples();
|
||||
|
|
|
@ -27,6 +27,7 @@ u32 Evaluate(u32 a, u32 b, IROp op) {
|
|||
case IROp::Slt: case IROp::SltConst: return ((s32)a < (s32)b);
|
||||
case IROp::SltU: case IROp::SltUConst: return (a < b);
|
||||
default:
|
||||
_assert_msg_(false, "Unable to evaluate two op %d", (int)op);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +51,7 @@ u32 Evaluate(u32 a, IROp op) {
|
|||
return count;
|
||||
}
|
||||
default:
|
||||
_assert_msg_(false, "Unable to evaluate one op %d", (int)op);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +66,7 @@ IROp ArithToArithConst(IROp op) {
|
|||
case IROp::Slt: return IROp::SltConst;
|
||||
case IROp::SltU: return IROp::SltUConst;
|
||||
default:
|
||||
_assert_msg_(false, "Invalid ArithToArithConst for op %d", (int)op);
|
||||
return (IROp)-1;
|
||||
}
|
||||
}
|
||||
|
@ -75,6 +78,7 @@ IROp ShiftToShiftImm(IROp op) {
|
|||
case IROp::Ror: return IROp::RorImm;
|
||||
case IROp::Sar: return IROp::SarImm;
|
||||
default:
|
||||
_assert_msg_(false, "Invalid ShiftToShiftImm for op %d", (int)op);
|
||||
return (IROp)-1;
|
||||
}
|
||||
}
|
||||
|
@ -412,8 +416,8 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts
|
|||
} else if (gpr.IsImm(inst.src2)) {
|
||||
const u32 imm2 = gpr.GetImm(inst.src2);
|
||||
gpr.MapDirtyIn(inst.dest, inst.src1);
|
||||
if (imm2 == 0 && (inst.op == IROp::Add || inst.op == IROp::Or)) {
|
||||
// Add / Or with zero is just a Mov.
|
||||
if (imm2 == 0 && (inst.op == IROp::Add || inst.op == IROp::Sub || inst.op == IROp::Or || inst.op == IROp::Xor)) {
|
||||
// Add / Sub / Or / Xor with zero is just a Mov. Add / Or are most common.
|
||||
if (inst.dest != inst.src1)
|
||||
out.Write(IROp::Mov, inst.dest, inst.src1);
|
||||
} else {
|
||||
|
@ -422,8 +426,8 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts
|
|||
} else if (symmetric && gpr.IsImm(inst.src1)) {
|
||||
const u32 imm1 = gpr.GetImm(inst.src1);
|
||||
gpr.MapDirtyIn(inst.dest, inst.src2);
|
||||
if (imm1 == 0 && (inst.op == IROp::Add || inst.op == IROp::Or)) {
|
||||
// Add / Or with zero is just a Mov.
|
||||
if (imm1 == 0 && (inst.op == IROp::Add || inst.op == IROp::Or || inst.op == IROp::Xor)) {
|
||||
// Add / Or / Xor with zero is just a Mov.
|
||||
if (inst.dest != inst.src2)
|
||||
out.Write(IROp::Mov, inst.dest, inst.src2);
|
||||
} else {
|
||||
|
@ -463,6 +467,11 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts
|
|||
gpr.SetImm(inst.dest, 0);
|
||||
} else if (gpr.IsImm(inst.src1)) {
|
||||
gpr.SetImm(inst.dest, Evaluate(gpr.GetImm(inst.src1), inst.constant, inst.op));
|
||||
} else if (inst.constant == 0 && (inst.op == IROp::AddConst || inst.op == IROp::SubConst || inst.op == IROp::OrConst || inst.op == IROp::XorConst)) {
|
||||
// Convert an Add/Sub/Or/Xor with a constant zero to a Mov (just like with reg zero.)
|
||||
gpr.MapDirtyIn(inst.dest, inst.src1);
|
||||
if (inst.dest != inst.src1)
|
||||
out.Write(IROp::Mov, inst.dest, inst.src1);
|
||||
} else {
|
||||
gpr.MapDirtyIn(inst.dest, inst.src1);
|
||||
goto doDefault;
|
||||
|
@ -734,6 +743,7 @@ bool PropagateConstants(const IRWriter &in, IRWriter &out, const IROptions &opts
|
|||
}
|
||||
}
|
||||
}
|
||||
gpr.FlushAll();
|
||||
return logBlocks;
|
||||
}
|
||||
|
||||
|
@ -834,7 +844,8 @@ bool PurgeTemps(const IRWriter &in, IRWriter &out, const IROptions &opts) {
|
|||
// This happens with lwl/lwr temps. Replace the original dest.
|
||||
insts[check.index] = IRReplaceDestGPR(insts[check.index], check.reg, inst.dest);
|
||||
lastWrittenTo[inst.dest] = check.index;
|
||||
check.reg = inst.dest;
|
||||
// If it's being read from (by inst), we can't optimize out.
|
||||
check.reg = 0;
|
||||
// Update the read by exit flag to match the new reg.
|
||||
check.readByExit = inst.dest < IRTEMP_0 || inst.dest > IRTEMP_LR_SHIFT;
|
||||
// And swap the args for this mov, since we changed the other dest. We'll optimize this out later.
|
||||
|
|
|
@ -27,8 +27,7 @@ IRRegCache::IRRegCache(IRWriter *ir) : ir_(ir) {
|
|||
|
||||
void IRRegCache::FlushAll() {
|
||||
for (int i = 0; i < TOTAL_MAPPABLE_MIPSREGS; i++) {
|
||||
//if (i < IRTEMP_0)
|
||||
Flush(i);
|
||||
Flush(i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -508,7 +508,8 @@ static const HardHashTableEntry hardcodedHashes[] = {
|
|||
{ 0xffc8f5f8f946152c, 192, "dl_write_light_color", },
|
||||
{ 0x249a3c5981c73480, 1472, "openseason_data_decode", }, // Open Season
|
||||
{ 0x795d940ad0a605f8, 40, "gow_fps_hack", }, // God of War (all)
|
||||
{ 0x4c75043b7b0c643b, 512, "gow_vortex_hack", } // God of War: Ghost of Sparta vortex timer hack, avoids softlock #8299
|
||||
{ 0x4c75043b7b0c643b, 512, "gow_vortex_hack", }, // God of War: Ghost of Sparta vortex timer hack, avoids softlock #8299
|
||||
{ 0x7624dde603717640, 288, "ZZT3_select_hack", }, // Zettai Zetsumei Toshi 3 - bypasses softlock on character select screen #4901
|
||||
};
|
||||
|
||||
namespace MIPSAnalyst {
|
||||
|
@ -1461,7 +1462,7 @@ skip:
|
|||
}
|
||||
break;
|
||||
case 0x08: // addi
|
||||
case 0x09: // adiu
|
||||
case 0x09: // addiu
|
||||
info.hasRelevantAddress = true;
|
||||
info.relevantAddress = cpu->GetRegValue(0,MIPS_GET_RS(op))+((s16)(op & 0xFFFF));
|
||||
break;
|
||||
|
|
|
@ -245,7 +245,7 @@ namespace MIPSInt
|
|||
_dbg_assert_msg_( 0, "Misaligned lv.q at %08x (pc = %08x)", addr, PC);
|
||||
}
|
||||
#ifndef COMMON_BIG_ENDIAN
|
||||
f = reinterpret_cast<float *>(Memory::GetPointer(addr));
|
||||
f = reinterpret_cast<float *>(Memory::GetPointerWrite(addr));
|
||||
if (f)
|
||||
WriteVector(f, V_Quad, vt);
|
||||
#else
|
||||
|
@ -294,7 +294,7 @@ namespace MIPSInt
|
|||
_dbg_assert_msg_( 0, "Misaligned sv.q at %08x (pc = %08x)", addr, PC);
|
||||
}
|
||||
#ifndef COMMON_BIG_ENDIAN
|
||||
f = reinterpret_cast<float *>(Memory::GetPointer(addr));
|
||||
f = reinterpret_cast<float *>(Memory::GetPointerWrite(addr));
|
||||
if (f)
|
||||
ReadVector(f, V_Quad, vt);
|
||||
#else
|
||||
|
|
|
@ -312,7 +312,7 @@ void Reinit() {
|
|||
}
|
||||
|
||||
static void DoMemoryVoid(PointerWrap &p, uint32_t start, uint32_t size) {
|
||||
uint8_t *d = GetPointer(start);
|
||||
uint8_t *d = GetPointerWrite(start);
|
||||
uint8_t *&storage = *p.ptr;
|
||||
|
||||
// We only handle aligned data and sizes.
|
||||
|
@ -479,7 +479,7 @@ void Write_Opcode_JIT(const u32 _Address, const Opcode& _Value)
|
|||
|
||||
void Memset(const u32 _Address, const u8 _iValue, const u32 _iLength, const char *tag) {
|
||||
if (IsValidRange(_Address, _iLength)) {
|
||||
uint8_t *ptr = GetPointerUnchecked(_Address);
|
||||
uint8_t *ptr = GetPointerWriteUnchecked(_Address);
|
||||
memset(ptr, _iValue, _iLength);
|
||||
} else {
|
||||
for (size_t i = 0; i < _iLength; i++)
|
||||
|
|
|
@ -140,7 +140,7 @@ u16 Read_U16(const u32 _Address);
|
|||
u32 Read_U32(const u32 _Address);
|
||||
u64 Read_U64(const u32 _Address);
|
||||
|
||||
inline u8* GetPointerUnchecked(const u32 address) {
|
||||
inline u8* GetPointerWriteUnchecked(const u32 address) {
|
||||
#ifdef MASKED_PSP_MEMORY
|
||||
return (u8 *)(base + (address & MEMVIEW32_MASK));
|
||||
#else
|
||||
|
@ -148,6 +148,14 @@ inline u8* GetPointerUnchecked(const u32 address) {
|
|||
#endif
|
||||
}
|
||||
|
||||
inline const u8* GetPointerUnchecked(const u32 address) {
|
||||
#ifdef MASKED_PSP_MEMORY
|
||||
return (const u8 *)(base + (address & MEMVIEW32_MASK));
|
||||
#else
|
||||
return (const u8 *)(base + address);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline u32 ReadUnchecked_U32(const u32 address) {
|
||||
#ifdef MASKED_PSP_MEMORY
|
||||
return *(u32_le *)(base + (address & MEMVIEW32_MASK));
|
||||
|
@ -236,7 +244,8 @@ inline void Write_Float(float f, u32 address)
|
|||
Write_U32(u, address);
|
||||
}
|
||||
|
||||
u8* GetPointer(const u32 address);
|
||||
u8* GetPointerWrite(const u32 address);
|
||||
const u8* GetPointer(const u32 address);
|
||||
bool IsRAMAddress(const u32 address);
|
||||
inline bool IsVRAMAddress(const u32 address) {
|
||||
return ((address & 0x3F800000) == 0x04000000);
|
||||
|
@ -272,11 +281,11 @@ inline void MemcpyUnchecked(void *to_data, const u32 from_address, const u32 len
|
|||
}
|
||||
|
||||
inline void MemcpyUnchecked(const u32 to_address, const void *from_data, const u32 len) {
|
||||
memcpy(GetPointerUnchecked(to_address), from_data, len);
|
||||
memcpy(GetPointerWriteUnchecked(to_address), from_data, len);
|
||||
}
|
||||
|
||||
inline void MemcpyUnchecked(const u32 to_address, const u32 from_address, const u32 len) {
|
||||
MemcpyUnchecked(GetPointer(to_address), from_address, len);
|
||||
MemcpyUnchecked(GetPointerWrite(to_address), from_address, len);
|
||||
}
|
||||
|
||||
inline bool IsValidAddress(const u32 address) {
|
||||
|
|
|
@ -28,18 +28,28 @@
|
|||
|
||||
namespace Memory {
|
||||
|
||||
u8 *GetPointer(const u32 address) {
|
||||
if ((address & 0x3E000000) == 0x08000000) {
|
||||
// RAM
|
||||
return GetPointerUnchecked(address);
|
||||
} else if ((address & 0x3F800000) == 0x04000000) {
|
||||
// VRAM
|
||||
return GetPointerUnchecked(address);
|
||||
} else if ((address & 0xBFFFC000) == 0x00010000) {
|
||||
// Scratchpad
|
||||
return GetPointerUnchecked(address);
|
||||
} else if ((address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize) {
|
||||
// More RAM (remasters, etc.)
|
||||
u8 *GetPointerWrite(const u32 address) {
|
||||
if ((address & 0x3E000000) == 0x08000000 || // RAM
|
||||
(address & 0x3F800000) == 0x04000000 || // VRAM
|
||||
(address & 0xBFFFC000) == 0x00010000 || // Scratchpad
|
||||
((address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize)) { // More RAM (remasters, etc.)
|
||||
return GetPointerWriteUnchecked(address);
|
||||
} else {
|
||||
static bool reported = false;
|
||||
if (!reported) {
|
||||
Reporting::ReportMessage("Unknown GetPointerWrite %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
|
||||
reported = true;
|
||||
}
|
||||
Core_MemoryException(address, currentMIPS->pc, MemoryExceptionType::WRITE_BLOCK);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
const u8 *GetPointer(const u32 address) {
|
||||
if ((address & 0x3E000000) == 0x08000000 || // RAM
|
||||
(address & 0x3F800000) == 0x04000000 || // VRAM
|
||||
(address & 0xBFFFC000) == 0x00010000 || // Scratchpad
|
||||
((address & 0x3F000000) >= 0x08000000 && (address & 0x3F000000) < 0x08000000 + g_MemorySize)) { // More RAM (remasters, etc.)
|
||||
return GetPointerUnchecked(address);
|
||||
} else {
|
||||
static bool reported = false;
|
||||
|
@ -47,7 +57,7 @@ u8 *GetPointer(const u32 address) {
|
|||
Reporting::ReportMessage("Unknown GetPointer %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]);
|
||||
reported = true;
|
||||
}
|
||||
Core_MemoryException(address, currentMIPS->pc, MemoryExceptionType::WRITE_BLOCK);
|
||||
Core_MemoryException(address, currentMIPS->pc, MemoryExceptionType::READ_BLOCK);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace Memory
|
|||
{
|
||||
|
||||
inline void Memcpy(const u32 to_address, const void *from_data, const u32 len, const char *tag, size_t tagLen) {
|
||||
u8 *to = GetPointer(to_address);
|
||||
u8 *to = GetPointerWrite(to_address);
|
||||
if (to) {
|
||||
memcpy(to, from_data, len);
|
||||
if (!tag) {
|
||||
|
@ -57,7 +57,7 @@ inline void Memcpy(void *to_data, const u32 from_address, const u32 len, const c
|
|||
}
|
||||
|
||||
inline void Memcpy(const u32 to_address, const u32 from_address, const u32 len, const char *tag, size_t tagLen) {
|
||||
u8 *to = GetPointer(to_address);
|
||||
u8 *to = GetPointerWrite(to_address);
|
||||
// If not, GetPointer will log.
|
||||
if (!to)
|
||||
return;
|
||||
|
|
|
@ -375,7 +375,7 @@ bool GameManager::DetectTexturePackDest(struct zip *z, int iniIndex, Path &dest)
|
|||
std::string gameID = games.begin()->first;
|
||||
if (games.size() > 1) {
|
||||
// Check for any supported game on their recent list and use that instead.
|
||||
for (const std::string &path : g_Config.recentIsos) {
|
||||
for (const std::string &path : g_Config.RecentIsos()) {
|
||||
std::string recentID = GetGameID(Path(path));
|
||||
if (games.find(recentID) != games.end()) {
|
||||
gameID = recentID;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "Common/Serialize/SerializeFuncs.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Core/Config.h"
|
||||
#include "Common/BitScan.h"
|
||||
#include "Core/HDRemaster.h"
|
||||
#include "Core/Host.h"
|
||||
#include "GPU/ge_constants.h"
|
||||
|
@ -841,14 +842,9 @@ void PPGeDrawCurrentText(u32 color)
|
|||
}
|
||||
|
||||
// Return a value such that (1 << value) >= x
|
||||
int GetPow2(int x) {
|
||||
#ifdef __GNUC__
|
||||
int ret = 31 - __builtin_clz(x | 1);
|
||||
inline int GetPow2(int x) {
|
||||
int ret = 31 - clz32_nonzero(x | 1);
|
||||
if ((1 << ret) < x)
|
||||
#else
|
||||
int ret = 0;
|
||||
while ((1 << ret) < x)
|
||||
#endif
|
||||
ret++;
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -150,7 +150,7 @@ static std::string RemotePathForRecent(const std::string &filename) {
|
|||
}
|
||||
|
||||
static Path LocalFromRemotePath(const std::string &path) {
|
||||
for (const std::string &filename : g_Config.recentIsos) {
|
||||
for (const std::string &filename : g_Config.RecentIsos()) {
|
||||
std::string basename = RemotePathForRecent(filename);
|
||||
if (basename == path) {
|
||||
return Path(filename);
|
||||
|
@ -216,7 +216,7 @@ static void HandleListing(const http::Request &request) {
|
|||
request.Out()->Printf("/\n");
|
||||
if (serverFlags & (int)WebServerFlags::DISCS) {
|
||||
// List the current discs in their recent order.
|
||||
for (const std::string &filename : g_Config.recentIsos) {
|
||||
for (const std::string &filename : g_Config.RecentIsos()) {
|
||||
std::string basename = RemotePathForRecent(filename);
|
||||
if (!basename.empty()) {
|
||||
request.Out()->Printf("%s\n", basename.c_str());
|
||||
|
@ -248,7 +248,7 @@ static bool ServeDebuggerFile(const http::Request &request) {
|
|||
} else if (ext == ".js") {
|
||||
mimeType = "application/javascript";
|
||||
} else if (ext == ".svg") {
|
||||
mimeType = "image/svg";
|
||||
mimeType = "image/svg+xml";
|
||||
} else if (ext == ".png") {
|
||||
mimeType = "image/png";
|
||||
} else if (ext == ".css") {
|
||||
|
|
|
@ -192,7 +192,7 @@ u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr,
|
|||
//
|
||||
// It does the simplest and safest test possible: If all points of a bbox is outside a single of
|
||||
// our clipping planes, we reject the box. Tighter bounds would be desirable but would take more calculations.
|
||||
bool DrawEngineCommon::TestBoundingBox(void* control_points, int vertexCount, u32 vertType, int *bytesRead) {
|
||||
bool DrawEngineCommon::TestBoundingBox(const void* control_points, int vertexCount, u32 vertType, int *bytesRead) {
|
||||
SimpleVertex *corners = (SimpleVertex *)(decoded + 65536 * 12);
|
||||
float *verts = (float *)(decoded + 65536 * 18);
|
||||
|
||||
|
@ -217,7 +217,7 @@ bool DrawEngineCommon::TestBoundingBox(void* control_points, int vertexCount, u3
|
|||
// Simplify away bones and morph before proceeding
|
||||
u8 *temp_buffer = decoded + 65536 * 24;
|
||||
int vertexSize = 0;
|
||||
NormalizeVertices((u8 *)corners, temp_buffer, (u8 *)control_points, 0, vertexCount, vertType, &vertexSize);
|
||||
NormalizeVertices((u8 *)corners, temp_buffer, (const u8 *)control_points, 0, vertexCount, vertType, &vertexSize);
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
verts[i * 3] = corners[i].pos.x;
|
||||
verts[i * 3 + 1] = corners[i].pos.y;
|
||||
|
@ -663,7 +663,7 @@ uint64_t DrawEngineCommon::ComputeHash() {
|
|||
}
|
||||
|
||||
// vertTypeID is the vertex type but with the UVGen mode smashed into the top bits.
|
||||
void DrawEngineCommon::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead) {
|
||||
void DrawEngineCommon::SubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead) {
|
||||
if (!indexGen.PrimCompatible(prevPrim_, prim) || numDrawCalls >= MAX_DEFERRED_DRAW_CALLS || vertexCountInDrawCalls_ + vertexCount > VERTEX_BUFFER_MAX) {
|
||||
DispatchFlush();
|
||||
}
|
||||
|
|
|
@ -69,18 +69,18 @@ public:
|
|||
// This would seem to be unnecessary now, but is still required for splines/beziers to work in the software backend since SubmitPrim
|
||||
// is different. Should probably refactor that.
|
||||
// Note that vertTypeID should be computed using GetVertTypeID().
|
||||
virtual void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead) {
|
||||
virtual void DispatchSubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead) {
|
||||
SubmitPrim(verts, inds, prim, vertexCount, vertTypeID, cullMode, bytesRead);
|
||||
}
|
||||
|
||||
virtual void DispatchSubmitImm(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead) {
|
||||
virtual void DispatchSubmitImm(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead) {
|
||||
SubmitPrim(verts, inds, prim, vertexCount, vertTypeID, cullMode, bytesRead);
|
||||
DispatchFlush();
|
||||
}
|
||||
|
||||
bool TestBoundingBox(void* control_points, int vertexCount, u32 vertType, int *bytesRead);
|
||||
bool TestBoundingBox(const void* control_points, int vertexCount, u32 vertType, int *bytesRead);
|
||||
|
||||
void SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead);
|
||||
void SubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead);
|
||||
template<class Surface>
|
||||
void SubmitCurve(const void *control_points, const void *indices, Surface &surface, u32 vertType, int *bytesRead, const char *scope);
|
||||
void ClearSplineBezierWeights();
|
||||
|
@ -150,8 +150,8 @@ protected:
|
|||
|
||||
// Defer all vertex decoding to a "Flush" (except when software skinning)
|
||||
struct DeferredDrawCall {
|
||||
void *verts;
|
||||
void *inds;
|
||||
const void *verts;
|
||||
const void *inds;
|
||||
u32 vertexCount;
|
||||
u8 indexType;
|
||||
s8 prim;
|
||||
|
|
|
@ -266,13 +266,16 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
|
|||
int drawing_width, drawing_height;
|
||||
EstimateDrawingSize(params.fb_address, params.fmt, params.viewportWidth, params.viewportHeight, params.regionWidth, params.regionHeight, params.scissorWidth, params.scissorHeight, std::max(params.fb_stride, 4), drawing_width, drawing_height);
|
||||
|
||||
gstate_c.SetCurRTOffsetX(0);
|
||||
gstate_c.SetCurRTOffset(0, 0);
|
||||
bool vfbFormatChanged = false;
|
||||
|
||||
// Find a matching framebuffer
|
||||
VirtualFramebuffer *vfb = nullptr;
|
||||
for (size_t i = 0; i < vfbs_.size(); ++i) {
|
||||
VirtualFramebuffer *v = vfbs_[i];
|
||||
|
||||
const u32 bpp = v->format == GE_FORMAT_8888 ? 4 : 2;
|
||||
|
||||
if (v->fb_address == params.fb_address) {
|
||||
vfb = v;
|
||||
// Update fb stride in case it changed
|
||||
|
@ -302,18 +305,36 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
|
|||
vfb->height = drawing_height;
|
||||
}
|
||||
break;
|
||||
} else if (v->fb_address < params.fb_address && v->fb_address + v->fb_stride * 4 > params.fb_address) {
|
||||
// Possibly a render-to-offset.
|
||||
const u32 bpp = v->format == GE_FORMAT_8888 ? 4 : 2;
|
||||
const int x_offset = (params.fb_address - v->fb_address) / bpp;
|
||||
if (v->format == params.fmt && v->fb_stride == params.fb_stride && x_offset < params.fb_stride && v->height >= drawing_height) {
|
||||
WARN_LOG_REPORT_ONCE(renderoffset, HLE, "Rendering to framebuffer offset: %08x +%dx%d", v->fb_address, x_offset, 0);
|
||||
vfb = v;
|
||||
gstate_c.SetCurRTOffsetX(x_offset);
|
||||
vfb->width = std::max((int)vfb->width, x_offset + drawing_width);
|
||||
// To prevent the newSize code from being confused.
|
||||
drawing_width += x_offset;
|
||||
break;
|
||||
} else if (v->fb_stride == params.fb_stride && v->format == params.fmt) {
|
||||
u32 v_fb_first_line_end_ptr = v->fb_address + v->fb_stride * 4; // This should be * bpp, but leaving like this until after 1.13 to be safe. The God of War games use this for shadows.
|
||||
u32 v_fb_end_ptr = v->fb_address + v->fb_stride * v->height * bpp;
|
||||
|
||||
if (params.fb_address > v->fb_address && params.fb_address < v_fb_first_line_end_ptr) {
|
||||
const int x_offset = (params.fb_address - v->fb_address) / bpp;
|
||||
if (x_offset < params.fb_stride && v->height >= drawing_height) {
|
||||
// Pretty certainly a pure render-to-X-offset.
|
||||
WARN_LOG_REPORT_ONCE(renderoffset, HLE, "Rendering to framebuffer offset: %08x +%dx%d", v->fb_address, x_offset, 0);
|
||||
vfb = v;
|
||||
gstate_c.SetCurRTOffset(x_offset, 0);
|
||||
vfb->width = std::max((int)vfb->width, x_offset + drawing_width);
|
||||
// To prevent the newSize code from being confused.
|
||||
drawing_width += x_offset;
|
||||
break;
|
||||
}
|
||||
} else if (params.fb_address > v->fb_address && params.fb_address < v_fb_end_ptr && PSP_CoreParameter().compat.flags().AllowLargeFBTextureOffsets) {
|
||||
if (params.fb_address % params.fb_stride == v->fb_address % params.fb_stride) {
|
||||
// Framebuffers are overlapping on the Y axis.
|
||||
const int y_offset = (params.fb_address - v->fb_address) / (bpp * params.fb_stride);
|
||||
|
||||
vfb = v;
|
||||
gstate_c.SetCurRTOffset(0, y_offset);
|
||||
// To prevent the newSize code from being confused.
|
||||
drawing_height += y_offset;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// We ignore this match.
|
||||
// TODO: We can allow X/Y overlaps too, but haven't seen any so safer to not.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -386,7 +407,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
|
|||
|
||||
SetColorUpdated(vfb, skipDrawReason);
|
||||
|
||||
INFO_LOG(FRAMEBUF, "Creating FBO for %08x (z: %08x) : %i x %i x %i", vfb->fb_address, vfb->z_address, vfb->width, vfb->height, vfb->format);
|
||||
INFO_LOG(FRAMEBUF, "Creating FBO for %08x (z: %08x) : %d x %d x %s", vfb->fb_address, vfb->z_address, vfb->width, vfb->height, GeBufferFormatToString(vfb->format));
|
||||
|
||||
vfb->last_frame_render = gpuStats.numFlips;
|
||||
frameLastFramebufUsed_ = gpuStats.numFlips;
|
||||
|
@ -494,6 +515,8 @@ void FramebufferManagerCommon::BlitFramebufferDepth(VirtualFramebuffer *src, Vir
|
|||
return;
|
||||
}
|
||||
|
||||
gpuStats.numDepthCopies++;
|
||||
|
||||
int w = std::min(src->renderWidth, dst->renderWidth);
|
||||
int h = std::min(src->renderHeight, dst->renderHeight);
|
||||
|
||||
|
@ -852,7 +875,7 @@ void FramebufferManagerCommon::DrawPixels(VirtualFramebuffer *vfb, int dstX, int
|
|||
draw_->SetScissorRect(0, 0, pixelWidth_, pixelHeight_);
|
||||
}
|
||||
|
||||
Draw::Texture *pixelsTex = MakePixelTexture(srcPixels, srcPixelFormat, srcStride, width, height, u1, v1);
|
||||
Draw::Texture *pixelsTex = MakePixelTexture(srcPixels, srcPixelFormat, srcStride, width, height);
|
||||
if (pixelsTex) {
|
||||
draw_->BindTextures(0, 1, &pixelsTex);
|
||||
Bind2DShader();
|
||||
|
@ -934,7 +957,7 @@ void FramebufferManagerCommon::CopyFramebufferForColorTexture(VirtualFramebuffer
|
|||
}
|
||||
}
|
||||
|
||||
Draw::Texture *FramebufferManagerCommon::MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, float &u1, float &v1) {
|
||||
Draw::Texture *FramebufferManagerCommon::MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) {
|
||||
// TODO: We can just change the texture format and flip some bits around instead of this.
|
||||
// Could share code with the texture cache perhaps.
|
||||
auto generateTexture = [&](uint8_t *data, const uint8_t *initData, uint32_t w, uint32_t h, uint32_t d, uint32_t byteStride, uint32_t sliceByteStride) {
|
||||
|
@ -1009,7 +1032,7 @@ void FramebufferManagerCommon::DrawFramebufferToOutput(const u8 *srcPixels, GEBu
|
|||
|
||||
float u0 = 0.0f, u1 = 480.0f / 512.0f;
|
||||
float v0 = 0.0f, v1 = 1.0f;
|
||||
Draw::Texture *pixelsTex = MakePixelTexture(srcPixels, srcPixelFormat, srcStride, 512, 272, u1, v1);
|
||||
Draw::Texture *pixelsTex = MakePixelTexture(srcPixels, srcPixelFormat, srcStride, 512, 272);
|
||||
if (!pixelsTex)
|
||||
return;
|
||||
|
||||
|
@ -1694,7 +1717,7 @@ void FramebufferManagerCommon::ApplyClearToMemory(int x1, int y1, int x2, int y2
|
|||
return;
|
||||
}
|
||||
|
||||
u8 *addr = Memory::GetPointerUnchecked(gstate.getFrameBufAddress());
|
||||
u8 *addr = Memory::GetPointerWriteUnchecked(gstate.getFrameBufAddress());
|
||||
const int bpp = gstate_c.framebufFormat == GE_FORMAT_8888 ? 4 : 2;
|
||||
|
||||
u32 clearBits = clearColor;
|
||||
|
@ -2033,7 +2056,7 @@ bool FramebufferManagerCommon::GetFramebuffer(u32 fb_address, int fb_stride, GEB
|
|||
if (!Memory::IsValidAddress(fb_address))
|
||||
return false;
|
||||
// If there's no vfb and we're drawing there, must be memory?
|
||||
buffer = GPUDebugBuffer(Memory::GetPointer(fb_address), fb_stride, 512, format);
|
||||
buffer = GPUDebugBuffer(Memory::GetPointerWriteUnchecked(fb_address), fb_stride, 512, format);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2090,7 +2113,7 @@ bool FramebufferManagerCommon::GetDepthbuffer(u32 fb_address, int fb_stride, u32
|
|||
if (!Memory::IsValidAddress(z_address))
|
||||
return false;
|
||||
// If there's no vfb and we're drawing there, must be memory?
|
||||
buffer = GPUDebugBuffer(Memory::GetPointer(z_address), z_stride, 512, GPU_DBG_FORMAT_16BIT);
|
||||
buffer = GPUDebugBuffer(Memory::GetPointerWriteUnchecked(z_address), z_stride, 512, GPU_DBG_FORMAT_16BIT);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2128,7 +2151,7 @@ bool FramebufferManagerCommon::GetStencilbuffer(u32 fb_address, int fb_stride, G
|
|||
return false;
|
||||
// If there's no vfb and we're drawing there, must be memory?
|
||||
// TODO: Actually get the stencil.
|
||||
buffer = GPUDebugBuffer(Memory::GetPointer(fb_address), fb_stride, 512, GPU_DBG_FORMAT_8888);
|
||||
buffer = GPUDebugBuffer(Memory::GetPointerWrite(fb_address), fb_stride, 512, GPU_DBG_FORMAT_8888);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2193,7 +2216,7 @@ void FramebufferManagerCommon::PackFramebufferSync_(VirtualFramebuffer *vfb, int
|
|||
return;
|
||||
}
|
||||
|
||||
u8 *destPtr = Memory::GetPointer(fb_address + dstByteOffset);
|
||||
u8 *destPtr = Memory::GetPointerWriteUnchecked(fb_address + dstByteOffset);
|
||||
|
||||
// We always need to convert from the framebuffer native format.
|
||||
// Right now that's always 8888.
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
|
@ -336,7 +335,7 @@ public:
|
|||
protected:
|
||||
virtual void PackFramebufferSync_(VirtualFramebuffer *vfb, int x, int y, int w, int h);
|
||||
void SetViewport2D(int x, int y, int w, int h);
|
||||
Draw::Texture *MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, float &u1, float &v1);
|
||||
Draw::Texture *MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height);
|
||||
virtual void DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation, int flags) = 0;
|
||||
virtual void Bind2DShader() = 0;
|
||||
|
||||
|
|
|
@ -584,6 +584,7 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
|
|||
}
|
||||
|
||||
renderX = gstate_c.curRTOffsetX;
|
||||
renderY = gstate_c.curRTOffsetY;
|
||||
|
||||
// Scissor
|
||||
int scissorX1 = gstate.getScissorX1();
|
||||
|
@ -591,7 +592,6 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
|
|||
int scissorX2 = gstate.getScissorX2() + 1;
|
||||
int scissorY2 = gstate.getScissorY2() + 1;
|
||||
|
||||
out.scissorEnable = true;
|
||||
if (scissorX2 < scissorX1 || scissorY2 < scissorY1) {
|
||||
out.scissorX = 0;
|
||||
out.scissorY = 0;
|
||||
|
|
|
@ -65,7 +65,6 @@ LogicOpReplaceType ReplaceLogicOpType();
|
|||
|
||||
// Common representation, should be able to set this directly with any modern API.
|
||||
struct ViewportAndScissor {
|
||||
bool scissorEnable;
|
||||
int scissorX;
|
||||
int scissorY;
|
||||
int scissorW;
|
||||
|
|
|
@ -633,8 +633,17 @@ std::vector<AttachCandidate> TextureCacheCommon::GetFramebufferCandidates(const
|
|||
|
||||
if (candidates.size() > 1) {
|
||||
bool depth = channel == FramebufferNotificationChannel::NOTIFY_FB_DEPTH;
|
||||
WARN_LOG_REPORT_ONCE(multifbcandidate, G3D, "GetFramebufferCandidates(%s): Multiple (%d) candidate framebuffers. texaddr: %08x offset: %d (%dx%d stride %d, %s)",
|
||||
depth ? "DEPTH" : "COLOR", (int)candidates.size(), entry.addr, texAddrOffset, dimWidth(entry.dim), dimHeight(entry.dim), entry.bufw, GeTextureFormatToString(entry.format));
|
||||
|
||||
std::string cands;
|
||||
for (auto &candidate : candidates) {
|
||||
cands += candidate.ToString() + " ";
|
||||
}
|
||||
|
||||
WARN_LOG_REPORT_ONCE(multifbcandidate, G3D, "GetFramebufferCandidates(%s): Multiple (%d) candidate framebuffers. First will be chosen. texaddr: %08x offset: %d (%dx%d stride %d, %s):\n%s",
|
||||
depth ? "DEPTH" : "COLOR", (int)candidates.size(),
|
||||
entry.addr, texAddrOffset, dimWidth(entry.dim), dimHeight(entry.dim), entry.bufw, GeTextureFormatToString(entry.format),
|
||||
cands.c_str()
|
||||
);
|
||||
}
|
||||
|
||||
return candidates;
|
||||
|
@ -975,7 +984,7 @@ FramebufferMatchInfo TextureCacheCommon::MatchFramebuffer(
|
|||
|
||||
// Trying to play it safe. Below 0x04110000 is almost always framebuffers.
|
||||
// TODO: Maybe we can reduce this check and find a better way above 0x04110000?
|
||||
if (fbInfo.yOffset > MAX_SUBAREA_Y_OFFSET_SAFE && addr > 0x04110000) {
|
||||
if (fbInfo.yOffset > MAX_SUBAREA_Y_OFFSET_SAFE && addr > 0x04110000 && !PSP_CoreParameter().compat.flags().AllowLargeFBTextureOffsets) {
|
||||
WARN_LOG_REPORT_ONCE(subareaIgnored, G3D, "Ignoring possible texturing from framebuffer at %08x +%dx%d / %dx%d", fb_address, fbInfo.xOffset, fbInfo.yOffset, framebuffer->width, framebuffer->height);
|
||||
return FramebufferMatchInfo{ FramebufferMatch::NO_MATCH };
|
||||
}
|
||||
|
@ -1996,3 +2005,7 @@ void TextureCacheCommon::InvalidateAll(GPUInvalidationType /*unused*/) {
|
|||
void TextureCacheCommon::ClearNextFrame() {
|
||||
clearCacheNextFrame_ = true;
|
||||
}
|
||||
|
||||
std::string AttachCandidate::ToString() {
|
||||
return StringFromFormat("[C:%08x/%d Z:%08x/%d X:%d Y:%d reint: %s]", this->fb->fb_address, this->fb->fb_stride, this->fb->z_address, this->fb->z_stride, this->match.xOffset, this->match.yOffset, this->match.reinterpret ? "true" : "false");
|
||||
}
|
||||
|
|
|
@ -203,7 +203,6 @@ typedef std::map<u64, std::unique_ptr<TexCacheEntry>> TexCache;
|
|||
#undef IGNORE
|
||||
#endif
|
||||
|
||||
// TODO: Try to get rid of IGNORE, it doesn't match what we want to do
|
||||
enum class FramebufferMatch {
|
||||
// Valid, exact match.
|
||||
VALID = 0,
|
||||
|
@ -224,6 +223,8 @@ struct AttachCandidate {
|
|||
TextureDefinition entry;
|
||||
VirtualFramebuffer *fb;
|
||||
FramebufferNotificationChannel channel;
|
||||
|
||||
std::string ToString();
|
||||
};
|
||||
|
||||
class FramebufferManagerCommon;
|
||||
|
|
|
@ -1052,6 +1052,9 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag
|
|||
WRITE(p, " %sv_color0 = color0;\n", compat.vsOutPrefix);
|
||||
} else {
|
||||
WRITE(p, " %sv_color0 = u_matambientalpha;\n", compat.vsOutPrefix);
|
||||
if (bugs.Has(Draw::Bugs::MALI_CONSTANT_LOAD_BUG) && g_Config.bVendorBugChecksEnabled) {
|
||||
WRITE(p, " %sv_color0.r += 0.000001;\n", compat.vsOutPrefix);
|
||||
}
|
||||
}
|
||||
if (lmode)
|
||||
WRITE(p, " %sv_color1 = splat3(0.0);\n", compat.vsOutPrefix);
|
||||
|
|
|
@ -393,17 +393,10 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
|
|||
}
|
||||
|
||||
D3D11_RECT &scissor = dynState_.scissor;
|
||||
if (vpAndScissor.scissorEnable) {
|
||||
scissor.left = vpAndScissor.scissorX;
|
||||
scissor.top = vpAndScissor.scissorY;
|
||||
scissor.right = vpAndScissor.scissorX + std::max(0, vpAndScissor.scissorW);
|
||||
scissor.bottom = vpAndScissor.scissorY + std::max(0, vpAndScissor.scissorH);
|
||||
} else {
|
||||
scissor.left = 0;
|
||||
scissor.top = 0;
|
||||
scissor.right = framebufferManager_->GetRenderWidth();
|
||||
scissor.bottom = framebufferManager_->GetRenderHeight();
|
||||
}
|
||||
scissor.left = vpAndScissor.scissorX;
|
||||
scissor.top = vpAndScissor.scissorY;
|
||||
scissor.right = vpAndScissor.scissorX + std::max(0, vpAndScissor.scissorW);
|
||||
scissor.bottom = vpAndScissor.scissorY + std::max(0, vpAndScissor.scissorH);
|
||||
}
|
||||
|
||||
if (gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS) && !gstate.isModeClear() && gstate.isTextureMapEnabled()) {
|
||||
|
|
|
@ -157,9 +157,7 @@ bool FramebufferManagerD3D11::NotifyStencilUpload(u32 addr, int size, StencilUpl
|
|||
|
||||
u16 w = dstBuffer->renderWidth;
|
||||
u16 h = dstBuffer->renderHeight;
|
||||
float u1 = 1.0f;
|
||||
float v1 = 1.0f;
|
||||
Draw::Texture *tex = MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->bufferWidth, dstBuffer->bufferHeight, u1, v1);
|
||||
Draw::Texture *tex = MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->bufferWidth, dstBuffer->bufferHeight);
|
||||
if (!tex)
|
||||
return false;
|
||||
if (dstBuffer->fbo) {
|
||||
|
@ -175,9 +173,9 @@ bool FramebufferManagerD3D11::NotifyStencilUpload(u32 addr, int size, StencilUpl
|
|||
|
||||
float coord[20] = {
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.0f, u1, 0.0f,
|
||||
-1.0f, -1.0f, 0.0f, 0.0f, v1,
|
||||
1.0f, -1.0f, 0.0f, u1, v1,
|
||||
1.0f, 1.0f, 0.0f, 1.0, 0.0f,
|
||||
-1.0f, -1.0f, 0.0f, 0.0f, 1.0,
|
||||
1.0f, -1.0f, 0.0f, 1.0, 1.0,
|
||||
};
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE map;
|
||||
|
|
|
@ -369,7 +369,7 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = {
|
|||
// TODO: Handle the other formats? We don't currently create them, I think.
|
||||
const int dstByteOffset = (y * vfb->fb_stride + x) * dstBpp;
|
||||
// Pixel size always 4 here because we always request BGRA8888.
|
||||
ConvertFromBGRA8888(Memory::GetPointer(fb_address + dstByteOffset), (u8 *)locked.pBits, vfb->fb_stride, locked.Pitch / 4, w, h, vfb->format);
|
||||
ConvertFromBGRA8888(Memory::GetPointerWrite(fb_address + dstByteOffset), (u8 *)locked.pBits, vfb->fb_stride, locked.Pitch / 4, w, h, vfb->format);
|
||||
offscreen->UnlockRect();
|
||||
} else {
|
||||
ERROR_LOG_REPORT(G3D, "Unable to lock rect from %08x: %d,%d %dx%d of %dx%d", fb_address, (int)rect.left, (int)rect.top, (int)rect.right, (int)rect.bottom, vfb->renderWidth, vfb->renderHeight);
|
||||
|
@ -464,7 +464,7 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = {
|
|||
if (!Memory::IsValidAddress(fb_address))
|
||||
return false;
|
||||
// If there's no vfb and we're drawing there, must be memory?
|
||||
buffer = GPUDebugBuffer(Memory::GetPointer(fb_address), fb_stride, 512, fb_format);
|
||||
buffer = GPUDebugBuffer(Memory::GetPointerWrite(fb_address), fb_stride, 512, fb_format);
|
||||
return true;
|
||||
}
|
||||
LPDIRECT3DSURFACE9 renderTarget = vfb->fbo ? (LPDIRECT3DSURFACE9)draw_->GetFramebufferAPITexture(vfb->fbo, Draw::FB_COLOR_BIT | Draw::FB_SURFACE_BIT, 0) : nullptr;
|
||||
|
@ -541,7 +541,7 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = {
|
|||
|
||||
if (!vfb) {
|
||||
// If there's no vfb and we're drawing there, must be memory?
|
||||
buffer = GPUDebugBuffer(Memory::GetPointer(z_address), z_stride, 512, GPU_DBG_FORMAT_16BIT);
|
||||
buffer = GPUDebugBuffer(Memory::GetPointerWrite(z_address), z_stride, 512, GPU_DBG_FORMAT_16BIT);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -579,7 +579,7 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = {
|
|||
|
||||
if (!vfb) {
|
||||
// If there's no vfb and we're drawing there, must be memory?
|
||||
buffer = GPUDebugBuffer(Memory::GetPointer(vfb->z_address), vfb->z_stride, 512, GPU_DBG_FORMAT_16BIT);
|
||||
buffer = GPUDebugBuffer(Memory::GetPointerWrite(vfb->z_address), vfb->z_stride, 512, GPU_DBG_FORMAT_16BIT);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -239,12 +239,8 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
|
|||
framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(),
|
||||
vpAndScissor);
|
||||
|
||||
if (vpAndScissor.scissorEnable) {
|
||||
dxstate.scissorTest.enable();
|
||||
dxstate.scissorRect.set(vpAndScissor.scissorX, vpAndScissor.scissorY, vpAndScissor.scissorX + vpAndScissor.scissorW, vpAndScissor.scissorY + vpAndScissor.scissorH);
|
||||
} else {
|
||||
dxstate.scissorTest.disable();
|
||||
}
|
||||
dxstate.scissorTest.enable();
|
||||
dxstate.scissorRect.set(vpAndScissor.scissorX, vpAndScissor.scissorY, vpAndScissor.scissorX + vpAndScissor.scissorW, vpAndScissor.scissorY + vpAndScissor.scissorH);
|
||||
|
||||
float depthMin = vpAndScissor.depthRangeMin;
|
||||
float depthMax = vpAndScissor.depthRangeMax;
|
||||
|
|
|
@ -196,9 +196,7 @@ bool FramebufferManagerDX9::NotifyStencilUpload(u32 addr, int size, StencilUploa
|
|||
D3DVIEWPORT9 vp{ 0, 0, w, h, 0.0f, 1.0f };
|
||||
device_->SetViewport(&vp);
|
||||
|
||||
float u1 = 1.0f;
|
||||
float v1 = 1.0f;
|
||||
Draw::Texture *tex = MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->bufferWidth, dstBuffer->bufferHeight, u1, v1);
|
||||
Draw::Texture *tex = MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->bufferWidth, dstBuffer->bufferHeight);
|
||||
if (!tex)
|
||||
return false;
|
||||
|
||||
|
@ -208,9 +206,9 @@ bool FramebufferManagerDX9::NotifyStencilUpload(u32 addr, int size, StencilUploa
|
|||
|
||||
float coord[20] = {
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.0f, u1, 0.0f,
|
||||
-1.0f, -1.0f, 0.0f, 0.0f, v1,
|
||||
1.0f, -1.0f, 0.0f, u1, v1,
|
||||
1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
|
||||
-1.0f, -1.0f, 0.0f, 0.0f, 1.0f,
|
||||
1.0f, -1.0f, 0.0f, 1.0f, 1.0f,
|
||||
};
|
||||
|
||||
device_->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
|
||||
|
|
|
@ -177,10 +177,8 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, StencilUplo
|
|||
}
|
||||
render_->SetViewport({ 0, 0, (float)w, (float)h, 0.0f, 1.0f });
|
||||
|
||||
float u1 = 1.0f;
|
||||
float v1 = 1.0f;
|
||||
textureCache_->ForgetLastTexture();
|
||||
Draw::Texture *tex = MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->width, dstBuffer->height, u1, v1);
|
||||
Draw::Texture *tex = MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->width, dstBuffer->height);
|
||||
if (!tex)
|
||||
return false;
|
||||
|
||||
|
@ -210,7 +208,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, StencilUplo
|
|||
render_->SetStencilOp(i, GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
||||
render_->SetUniformF1(&u_stencilValue, i * (1.0f / 255.0f));
|
||||
}
|
||||
DrawActiveTexture(0, 0, dstBuffer->width, dstBuffer->height, dstBuffer->bufferWidth, dstBuffer->bufferHeight, 0.0f, 0.0f, u1, v1, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST | DRAWTEX_KEEP_STENCIL_ALPHA);
|
||||
DrawActiveTexture(0, 0, dstBuffer->width, dstBuffer->height, dstBuffer->bufferWidth, dstBuffer->bufferHeight, 0.0f, 0.0f, 1.0f, 1.0f, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST | DRAWTEX_KEEP_STENCIL_ALPHA);
|
||||
}
|
||||
|
||||
if (useBlit) {
|
||||
|
|
|
@ -75,6 +75,7 @@ struct GPUStatistics {
|
|||
numReadbacks = 0;
|
||||
numUploads = 0;
|
||||
numClears = 0;
|
||||
numDepthCopies = 0;
|
||||
msProcessingDisplayLists = 0;
|
||||
vertexGPUCycles = 0;
|
||||
otherGPUCycles = 0;
|
||||
|
@ -100,6 +101,7 @@ struct GPUStatistics {
|
|||
int numReadbacks;
|
||||
int numUploads;
|
||||
int numClears;
|
||||
int numDepthCopies;
|
||||
double msProcessingDisplayLists;
|
||||
int vertexGPUCycles;
|
||||
int otherGPUCycles;
|
||||
|
|
|
@ -1677,8 +1677,8 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) {
|
|||
return;
|
||||
}
|
||||
|
||||
void *verts = Memory::GetPointerUnchecked(gstate_c.vertexAddr);
|
||||
void *inds = nullptr;
|
||||
const void *verts = Memory::GetPointerUnchecked(gstate_c.vertexAddr);
|
||||
const void *inds = nullptr;
|
||||
u32 vertexType = gstate.vertType;
|
||||
if ((vertexType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) {
|
||||
u32 indexAddr = gstate_c.indexAddr;
|
||||
|
@ -1886,8 +1886,8 @@ void GPUCommon::Execute_Bezier(u32 op, u32 diff) {
|
|||
return;
|
||||
}
|
||||
|
||||
void *control_points = Memory::GetPointerUnchecked(gstate_c.vertexAddr);
|
||||
void *indices = NULL;
|
||||
const void *control_points = Memory::GetPointerUnchecked(gstate_c.vertexAddr);
|
||||
const void *indices = NULL;
|
||||
if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) {
|
||||
if (!Memory::IsValidAddress(gstate_c.indexAddr)) {
|
||||
ERROR_LOG_REPORT(G3D, "Bad index address %08x!", gstate_c.indexAddr);
|
||||
|
@ -1956,8 +1956,8 @@ void GPUCommon::Execute_Spline(u32 op, u32 diff) {
|
|||
return;
|
||||
}
|
||||
|
||||
void *control_points = Memory::GetPointerUnchecked(gstate_c.vertexAddr);
|
||||
void *indices = NULL;
|
||||
const void *control_points = Memory::GetPointerUnchecked(gstate_c.vertexAddr);
|
||||
const void *indices = NULL;
|
||||
if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) {
|
||||
if (!Memory::IsValidAddress(gstate_c.indexAddr)) {
|
||||
ERROR_LOG_REPORT(G3D, "Bad index address %08x!", gstate_c.indexAddr);
|
||||
|
@ -2018,7 +2018,7 @@ void GPUCommon::Execute_BoundingBox(u32 op, u32 diff) {
|
|||
return;
|
||||
}
|
||||
if (((count & 7) == 0) && count <= 64) { // Sanity check
|
||||
void *control_points = Memory::GetPointer(gstate_c.vertexAddr);
|
||||
const void *control_points = Memory::GetPointer(gstate_c.vertexAddr);
|
||||
if (!control_points) {
|
||||
ERROR_LOG_REPORT_ONCE(boundingbox, G3D, "Invalid verts in bounding box check");
|
||||
currentList->bboxResult = true;
|
||||
|
@ -2795,7 +2795,7 @@ void GPUCommon::DoBlockTransfer(u32 skipDrawReason) {
|
|||
u32 srcLineStartAddr = srcBasePtr + (srcY * srcStride + srcX) * bpp;
|
||||
u32 dstLineStartAddr = dstBasePtr + (dstY * dstStride + dstX) * bpp;
|
||||
const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr);
|
||||
u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr);
|
||||
u8 *dst = Memory::GetPointerWriteUnchecked(dstLineStartAddr);
|
||||
memcpy(dst, src, width * height * bpp);
|
||||
GPURecord::NotifyMemcpy(dstLineStartAddr, srcLineStartAddr, width * height * bpp);
|
||||
} else {
|
||||
|
@ -2804,7 +2804,7 @@ void GPUCommon::DoBlockTransfer(u32 skipDrawReason) {
|
|||
u32 dstLineStartAddr = dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp;
|
||||
|
||||
const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr);
|
||||
u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr);
|
||||
u8 *dst = Memory::GetPointerWriteUnchecked(dstLineStartAddr);
|
||||
memcpy(dst, src, width * bpp);
|
||||
GPURecord::NotifyMemcpy(dstLineStartAddr, srcLineStartAddr, width * bpp);
|
||||
}
|
||||
|
@ -3029,7 +3029,7 @@ size_t GPUCommon::FormatGPUStatsCommon(char *buffer, size_t size) {
|
|||
"Vertices: %d cached: %d uncached: %d\n"
|
||||
"FBOs active: %d (evaluations: %d)\n"
|
||||
"Textures: %d, dec: %d, invalidated: %d, hashed: %d kB\n"
|
||||
"Readbacks: %d, uploads: %d\n"
|
||||
"Readbacks: %d, uploads: %d, depth copies: %d\n"
|
||||
"GPU cycles executed: %d (%f per vertex)\n",
|
||||
gpuStats.msProcessingDisplayLists * 1000.0f,
|
||||
gpuStats.numDrawCalls,
|
||||
|
@ -3049,6 +3049,7 @@ size_t GPUCommon::FormatGPUStatsCommon(char *buffer, size_t size) {
|
|||
gpuStats.numTextureDataBytesHashed / 1024,
|
||||
gpuStats.numReadbacks,
|
||||
gpuStats.numUploads,
|
||||
gpuStats.numDepthCopies,
|
||||
gpuStats.vertexGPUCycles + gpuStats.otherGPUCycles,
|
||||
vertexAverageCycles
|
||||
);
|
||||
|
|
|
@ -606,13 +606,15 @@ struct GPUStateCache {
|
|||
u32 curRTRenderWidth;
|
||||
u32 curRTRenderHeight;
|
||||
|
||||
void SetCurRTOffsetX(int off) {
|
||||
if (off != curRTOffsetX) {
|
||||
curRTOffsetX = off;
|
||||
void SetCurRTOffset(u32 xoff, u32 yoff) {
|
||||
if (xoff != curRTOffsetX || yoff != curRTOffsetY) {
|
||||
curRTOffsetX = xoff;
|
||||
curRTOffsetY = yoff;
|
||||
Dirty(DIRTY_VIEWPORTSCISSOR_STATE);
|
||||
}
|
||||
}
|
||||
u32 curRTOffsetX;
|
||||
u32 curRTOffsetY;
|
||||
|
||||
// Set if we are doing hardware bezier/spline.
|
||||
SubmitType submitType;
|
||||
|
|
|
@ -1412,7 +1412,7 @@ bool GetCurrentTexture(GPUDebugBuffer &buffer, int level)
|
|||
|
||||
Sampler::FetchFunc sampler = Sampler::GetFetchFunc(id);
|
||||
|
||||
u8 *texptr = Memory::GetPointer(texaddr);
|
||||
u8 *texptr = Memory::GetPointerWrite(texaddr);
|
||||
u32 *row = (u32 *)buffer.GetData();
|
||||
for (int y = 0; y < h; ++y) {
|
||||
for (int x = 0; x < w; ++x) {
|
||||
|
|
|
@ -40,7 +40,7 @@ struct RasterizerState {
|
|||
Sampler::NearestFunc nearest;
|
||||
uint32_t texaddr[8]{};
|
||||
int texbufw[8]{};
|
||||
u8 *texptr[8]{};
|
||||
const u8 *texptr[8]{};
|
||||
float textureLodSlope;
|
||||
int screenOffsetX;
|
||||
int screenOffsetY;
|
||||
|
|
|
@ -395,8 +395,8 @@ const SoftwareCommandTableEntry softgpuCommandTable[] = {
|
|||
SoftGPU::SoftGPU(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
|
||||
: GPUCommon(gfxCtx, draw)
|
||||
{
|
||||
fb.data = Memory::GetPointer(0x44000000); // TODO: correct default address?
|
||||
depthbuf.data = Memory::GetPointer(0x44000000); // TODO: correct default address?
|
||||
fb.data = Memory::GetPointerWrite(0x44000000); // TODO: correct default address?
|
||||
depthbuf.data = Memory::GetPointerWrite(0x44000000); // TODO: correct default address?
|
||||
|
||||
memset(softgpuCmdInfo, 0, sizeof(softgpuCmdInfo));
|
||||
|
||||
|
@ -494,7 +494,7 @@ void SoftGPU::ConvertTextureDescFrom16(Draw::TextureDesc &desc, int srcwidth, in
|
|||
// TODO: This should probably be converted in a shader instead..
|
||||
fbTexBuffer_.resize(srcwidth * srcheight);
|
||||
FormatBuffer displayBuffer;
|
||||
displayBuffer.data = overrideData ? overrideData : Memory::GetPointer(displayFramebuf_);
|
||||
displayBuffer.data = overrideData ? overrideData : Memory::GetPointerWrite(displayFramebuf_);
|
||||
for (int y = 0; y < srcheight; ++y) {
|
||||
u32 *buf_line = &fbTexBuffer_[y * srcwidth];
|
||||
const u16 *fb_line = &displayBuffer.as16[y * displayStride_];
|
||||
|
@ -557,7 +557,7 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) {
|
|||
bool hasPostShader = presentation_ && presentation_->HasPostShader();
|
||||
|
||||
if (PSP_CoreParameter().compat.flags().DarkStalkersPresentHack && displayFormat_ == GE_FORMAT_5551 && g_DarkStalkerStretch != DSStretch::Off) {
|
||||
u8 *data = Memory::GetPointer(0x04088000);
|
||||
u8 *data = Memory::GetPointerWrite(0x04088000);
|
||||
bool fillDesc = true;
|
||||
if (draw_->GetDataFormatSupport(Draw::DataFormat::A1B5G5R5_UNORM_PACK16) & Draw::FMT_TEXTURE) {
|
||||
// The perfect one.
|
||||
|
@ -586,13 +586,13 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) {
|
|||
hasImage = false;
|
||||
u1 = 1.0f;
|
||||
} else if (displayFormat_ == GE_FORMAT_8888) {
|
||||
u8 *data = Memory::GetPointer(displayFramebuf_);
|
||||
u8 *data = Memory::GetPointerWrite(displayFramebuf_);
|
||||
desc.width = displayStride_ == 0 ? srcwidth : displayStride_;
|
||||
desc.height = srcheight;
|
||||
desc.initData.push_back(data);
|
||||
desc.format = Draw::DataFormat::R8G8B8A8_UNORM;
|
||||
} else if (displayFormat_ == GE_FORMAT_5551) {
|
||||
u8 *data = Memory::GetPointer(displayFramebuf_);
|
||||
const u8 *data = Memory::GetPointerWrite(displayFramebuf_);
|
||||
bool fillDesc = true;
|
||||
if (draw_->GetDataFormatSupport(Draw::DataFormat::A1B5G5R5_UNORM_PACK16) & Draw::FMT_TEXTURE) {
|
||||
// The perfect one.
|
||||
|
@ -797,7 +797,7 @@ void SoftGPU::Execute_BlockTransferStart(u32 op, u32 diff) {
|
|||
u32 dstLineStartAddr = dstBasePtr + (dstY * dstStride + dstX) * bpp;
|
||||
|
||||
const u8 *srcp = Memory::GetPointer(srcLineStartAddr);
|
||||
u8 *dstp = Memory::GetPointer(dstLineStartAddr);
|
||||
u8 *dstp = Memory::GetPointerWrite(dstLineStartAddr);
|
||||
memcpy(dstp, srcp, width * height * bpp);
|
||||
GPURecord::NotifyMemcpy(dstLineStartAddr, srcLineStartAddr, width * height * bpp);
|
||||
} else {
|
||||
|
@ -806,7 +806,7 @@ void SoftGPU::Execute_BlockTransferStart(u32 op, u32 diff) {
|
|||
u32 dstLineStartAddr = dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp;
|
||||
|
||||
const u8 *srcp = Memory::GetPointer(srcLineStartAddr);
|
||||
u8 *dstp = Memory::GetPointer(dstLineStartAddr);
|
||||
u8 *dstp = Memory::GetPointerWrite(dstLineStartAddr);
|
||||
memcpy(dstp, srcp, width * bpp);
|
||||
GPURecord::NotifyMemcpy(dstLineStartAddr, srcLineStartAddr, width * bpp);
|
||||
}
|
||||
|
@ -837,14 +837,14 @@ void SoftGPU::Execute_Prim(u32 op, u32 diff) {
|
|||
return;
|
||||
}
|
||||
|
||||
void *verts = Memory::GetPointer(gstate_c.vertexAddr);
|
||||
void *indices = NULL;
|
||||
const void *verts = Memory::GetPointer(gstate_c.vertexAddr);
|
||||
const void *indices = NULL;
|
||||
if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) {
|
||||
if (!Memory::IsValidAddress(gstate_c.indexAddr)) {
|
||||
ERROR_LOG_REPORT(G3D, "Software: Bad index address %08x!", gstate_c.indexAddr);
|
||||
return;
|
||||
}
|
||||
indices = Memory::GetPointer(gstate_c.indexAddr);
|
||||
indices = Memory::GetPointerUnchecked(gstate_c.indexAddr);
|
||||
}
|
||||
|
||||
cyclesExecuted += EstimatePerVertexCost() * count;
|
||||
|
@ -875,8 +875,8 @@ void SoftGPU::Execute_Bezier(u32 op, u32 diff) {
|
|||
return;
|
||||
}
|
||||
|
||||
void *control_points = Memory::GetPointerUnchecked(gstate_c.vertexAddr);
|
||||
void *indices = NULL;
|
||||
const void *control_points = Memory::GetPointerUnchecked(gstate_c.vertexAddr);
|
||||
const void *indices = NULL;
|
||||
if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) {
|
||||
if (!Memory::IsValidAddress(gstate_c.indexAddr)) {
|
||||
ERROR_LOG_REPORT(G3D, "Bad index address %08x!", gstate_c.indexAddr);
|
||||
|
@ -927,8 +927,8 @@ void SoftGPU::Execute_Spline(u32 op, u32 diff) {
|
|||
return;
|
||||
}
|
||||
|
||||
void *control_points = Memory::GetPointerUnchecked(gstate_c.vertexAddr);
|
||||
void *indices = NULL;
|
||||
const void *control_points = Memory::GetPointerUnchecked(gstate_c.vertexAddr);
|
||||
const void *indices = NULL;
|
||||
if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) {
|
||||
if (!Memory::IsValidAddress(gstate_c.indexAddr)) {
|
||||
ERROR_LOG_REPORT(G3D, "Bad index address %08x!", gstate_c.indexAddr);
|
||||
|
@ -1002,7 +1002,7 @@ void SoftGPU::Execute_LoadClut(u32 op, u32 diff) {
|
|||
void SoftGPU::Execute_FramebufPtr(u32 op, u32 diff) {
|
||||
// We assume fb.data won't change while we're drawing.
|
||||
drawEngine_->transformUnit.Flush("framebuf");
|
||||
fb.data = Memory::GetPointer(gstate.getFrameBufAddress());
|
||||
fb.data = Memory::GetPointerWrite(gstate.getFrameBufAddress());
|
||||
}
|
||||
|
||||
void SoftGPU::Execute_FramebufFormat(u32 op, u32 diff) {
|
||||
|
@ -1013,7 +1013,7 @@ void SoftGPU::Execute_FramebufFormat(u32 op, u32 diff) {
|
|||
void SoftGPU::Execute_ZbufPtr(u32 op, u32 diff) {
|
||||
// We assume depthbuf.data won't change while we're drawing.
|
||||
drawEngine_->transformUnit.Flush("depthbuf");
|
||||
depthbuf.data = Memory::GetPointer(gstate.getDepthBufAddress());
|
||||
depthbuf.data = Memory::GetPointerWrite(gstate.getDepthBufAddress());
|
||||
}
|
||||
|
||||
void SoftGPU::Execute_VertexType(u32 op, u32 diff) {
|
||||
|
|
|
@ -65,12 +65,12 @@ void SoftwareDrawEngine::DispatchFlush() {
|
|||
transformUnit.Flush("debug");
|
||||
}
|
||||
|
||||
void SoftwareDrawEngine::DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead) {
|
||||
void SoftwareDrawEngine::DispatchSubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead) {
|
||||
_assert_msg_(cullMode == gstate.getCullMode(), "Mixed cull mode not supported.");
|
||||
transformUnit.SubmitPrimitive(verts, inds, prim, vertexCount, vertTypeID, bytesRead, this);
|
||||
}
|
||||
|
||||
void SoftwareDrawEngine::DispatchSubmitImm(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead) {
|
||||
void SoftwareDrawEngine::DispatchSubmitImm(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead) {
|
||||
_assert_msg_(cullMode == gstate.getCullMode(), "Mixed cull mode not supported.");
|
||||
// TODO: For now, just setting all dirty.
|
||||
transformUnit.SetDirty(SoftDirty(-1));
|
||||
|
@ -449,7 +449,7 @@ enum class CullType {
|
|||
OFF,
|
||||
};
|
||||
|
||||
void TransformUnit::SubmitPrimitive(void* vertices, void* indices, GEPrimitiveType prim_type, int vertex_count, u32 vertex_type, int *bytesRead, SoftwareDrawEngine *drawEngine)
|
||||
void TransformUnit::SubmitPrimitive(const void* vertices, const void* indices, GEPrimitiveType prim_type, int vertex_count, u32 vertex_type, int *bytesRead, SoftwareDrawEngine *drawEngine)
|
||||
{
|
||||
VertexDecoder &vdecoder = *drawEngine->FindVertexDecoder(vertex_type);
|
||||
const DecVtxFormat &vtxfmt = vdecoder.GetDecVtxFmt();
|
||||
|
|
|
@ -118,7 +118,7 @@ public:
|
|||
}
|
||||
static ScreenCoords DrawingToScreen(const DrawingCoords &coords, u16 z);
|
||||
|
||||
void SubmitPrimitive(void* vertices, void* indices, GEPrimitiveType prim_type, int vertex_count, u32 vertex_type, int *bytesRead, SoftwareDrawEngine *drawEngine);
|
||||
void SubmitPrimitive(const void* vertices, const void* indices, GEPrimitiveType prim_type, int vertex_count, u32 vertex_type, int *bytesRead, SoftwareDrawEngine *drawEngine);
|
||||
|
||||
bool GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices);
|
||||
|
||||
|
@ -144,8 +144,8 @@ public:
|
|||
~SoftwareDrawEngine();
|
||||
|
||||
void DispatchFlush() override;
|
||||
void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int cullMode, int *bytesRead) override;
|
||||
void DispatchSubmitImm(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead) override;
|
||||
void DispatchSubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, int cullMode, int *bytesRead) override;
|
||||
void DispatchSubmitImm(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead) override;
|
||||
|
||||
VertexDecoder *FindVertexDecoder(u32 vtype);
|
||||
|
||||
|
|
|
@ -347,17 +347,10 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
|
|||
}
|
||||
|
||||
ScissorRect &scissor = dynState.scissor;
|
||||
if (vpAndScissor.scissorEnable) {
|
||||
scissor.x = vpAndScissor.scissorX;
|
||||
scissor.y = vpAndScissor.scissorY;
|
||||
scissor.width = std::max(0, vpAndScissor.scissorW);
|
||||
scissor.height = std::max(0, vpAndScissor.scissorH);
|
||||
} else {
|
||||
scissor.x = 0;
|
||||
scissor.y = 0;
|
||||
scissor.width = framebufferManager_->GetRenderWidth();
|
||||
scissor.height = framebufferManager_->GetRenderHeight();
|
||||
}
|
||||
scissor.x = vpAndScissor.scissorX;
|
||||
scissor.y = vpAndScissor.scissorY;
|
||||
scissor.width = std::max(0, vpAndScissor.scissorW);
|
||||
scissor.height = std::max(0, vpAndScissor.scissorH);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -168,9 +168,7 @@ bool FramebufferManagerVulkan::NotifyStencilUpload(u32 addr, int size, StencilUp
|
|||
|
||||
u16 w = dstBuffer->renderWidth;
|
||||
u16 h = dstBuffer->renderHeight;
|
||||
float u1 = 1.0f;
|
||||
float v1 = 1.0f;
|
||||
Draw::Texture *tex = MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->bufferWidth, dstBuffer->bufferHeight, u1, v1);
|
||||
Draw::Texture *tex = MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->bufferWidth, dstBuffer->bufferHeight);
|
||||
if (!tex)
|
||||
return false;
|
||||
|
||||
|
|
109
README.md
109
README.md
|
@ -25,6 +25,49 @@ If you want to download regularly updated builds for Android, Windows x86 and x6
|
|||
|
||||
For game compatibility, see [community compatibility feedback](https://report.ppsspp.org/games).
|
||||
|
||||
What's new in 1.13
|
||||
==================
|
||||
|
||||
General
|
||||
|
||||
* Fix assorted Android "scoped storage"-related bugs and performance issues ([#15237], [#15487]), etc.
|
||||
* Analog mapping for fast-forward ([#15645])
|
||||
* Major softgpu accuracy fixes and speedups, including a JIT ([#15163], [#15345], [#15389], [#15529], [#15440], [#15410], [#15405], [#15400]) and many, many more
|
||||
* Fixed some NEON code paths ([#15481])
|
||||
* Fix performance of texture uploads with Vulkan ([#15474])
|
||||
* Don't include the large font atlas when we don't need it
|
||||
* Improved upscaling shaders ([#15566])
|
||||
* Vulkan texture upscaling performance improvements ([#15238]), etc.
|
||||
* Vulkan correctness fixes ([#15217], [#15211]), use the VMA allocator ([#15162]), etc.
|
||||
* Fixes to depth culling ([#15106]), many more
|
||||
* Background loading of texture replacement ([#15025])
|
||||
* Threading manager improvements and fixes ([#15470]), etc.
|
||||
* Added search in settings ([#14414])
|
||||
* Added fast button repeats on custom touch buttons ([#15613])
|
||||
* Two new bicubic upscaling shader: Catmull-Rom and Mitchell-Netravali ([#15569])
|
||||
* Allow to change screen rotation per game and to bind a key to change it ([#15494], [#15510])
|
||||
* Re-enabled software rendering option on Android ([#12958])
|
||||
|
||||
Game fixes
|
||||
|
||||
* Add more workarounds for Mali driver bugs ([#15016])
|
||||
* Vortex in God of War: Ghost of Sparta can now be passed ([#15640])
|
||||
* Various proAdhoc fixes ([#15213], [#15215]), and many more
|
||||
* Correct flickering text in Sol Trigger and Last Ranker. ([#15549])
|
||||
* Fix and improve line drawing in Echochrome ([#15583]), after line refactoring ([#15073], [#15075])
|
||||
* Fix HUD graphics in Split/Second ([#15500], [#15501])
|
||||
* Fix bad screen overlay issues in Clone Wars and Force Unleashed ([#15691], [#15696], [#12949], [#9572])
|
||||
* Zettai Zetsumei Toshi 3 no longer hangs on character select screen ([#15687])
|
||||
* Juiced 2: Bloom effect no longer covering the screen ([#7295], [#15717])
|
||||
* Fix keyboard shift issue in a few games ([#15698])
|
||||
|
||||
UI
|
||||
|
||||
* Windows/Xbox UWP directory navigation improvements ([#15652])
|
||||
* Color change and basic theme support ([#15396], [#15394])
|
||||
* Fix input focus bug ([#15560])
|
||||
* New GE debugger features and other UI fixes ([#15393], [#15324], [#15377], [#15424], [#15402], [#15378], [#15338]), etc.
|
||||
|
||||
What's new in 1.12.3
|
||||
====================
|
||||
* Fix background music speed. A couple translation fixes.
|
||||
|
@ -61,9 +104,9 @@ Game fixes:
|
|||
Graphics and Sound:
|
||||
* Add new texture filtering mode "Auto Max Quality" ([#14789])
|
||||
* Fix Princess Maker 5 Portable half screen in Vulkan ([#13741])
|
||||
* Fix Pro Yakyu Spirits 2010 (NPJH50234): Rendering errors with hardware transform off ([#14167])
|
||||
* Fix Pro Yakyu Spirits 2010 (NPJH50234): Rendering errors with hardware transform off ([#14167])
|
||||
* Support texture replacement filtering overrides ([#14230])
|
||||
* Fix Yarudora Portable: Double Cast's FMVs artifacting ([#13759])
|
||||
* Fix Yarudora Portable: Double Cast's FMVs artifacting ([#13759])
|
||||
* Fix Sims 2 Castaway/Pets EA Logo glitched out ([#13146])
|
||||
* Fix bad size & position on Japanese & Numbers & Alphabets ([#14209])
|
||||
* Implement basic depth texturing for OpenGL ([#14042])
|
||||
|
@ -80,9 +123,9 @@ UI:
|
|||
* Track and show memory allocation / usage information in debugger ([#14056])
|
||||
* Allow searching within the savedata manager ([#14237])
|
||||
* Enable postshaders to access previous frame ([#14528])
|
||||
* Add missing japanese keyboard symbol ([#14548])
|
||||
* Add missing Japanese keyboard symbol ([#14548])
|
||||
* Add Reset button on crash screen, allow load state and related ([#14708])
|
||||
* Implement savestate load and save undo ([#14676], [#14679], [#14697])
|
||||
* Implement save state load and save undo ([#14676], [#14679], [#14697])
|
||||
* A lot of minor debugger improvements
|
||||
|
||||
Controls:
|
||||
|
@ -207,7 +250,7 @@ What's new in 1.10.0
|
|||
* Frames in-flight now configurable to reduce input lag at the cost of speed ([#12660])
|
||||
* Add toggle mode to combo button ([#12623])
|
||||
* SDL mouse support, Qt menu upgrades ([#12612], [#12817])
|
||||
* Real support for chinese patched version of Hatsune Miku Project Diva Extend ([#13007])
|
||||
* Real support for Chinese patched version of Hatsune Miku Project Diva Extend ([#13007])
|
||||
* Some minor kernel module support ([#13028], [#12225], [#13026], [#13004], [#13038], [#13023])
|
||||
* Fixed fullscreen toggling with Vulkan in SDL builds ([#11974])
|
||||
|
||||
|
@ -404,3 +447,59 @@ Credit goes to:
|
|||
[#14513]: https://github.com/hrydgard/ppsspp/issues/14513 "[Adhoc] Reducing HLE delays due to Mutiplayer performance regressions"
|
||||
[#14849]: https://github.com/hrydgard/ppsspp/issues/14849 "[Adhoc] Fix Socket error 10014 on Windows when hosting a game of Vulcanus Seek and Destroy"
|
||||
[#14711]: https://github.com/hrydgard/ppsspp/issues/14711 "Sas: Add option to control reverb volume"
|
||||
[#15237]: https://github.com/hrydgard/ppsspp/issues/15237 "Path: Check for PSP case insensitively"
|
||||
[#15487]: https://github.com/hrydgard/ppsspp/issues/15487 "Save textures on background tasks when texture dumping is enabled."
|
||||
[#15645]: https://github.com/hrydgard/ppsspp/issues/15645 "UI: Add analog speed limit mapping"
|
||||
[#15566]: https://github.com/hrydgard/ppsspp/issues/15566 "Screen upscaling shaders improvements"
|
||||
[#15163]: https://github.com/hrydgard/ppsspp/issues/15163 "Implement a jit for drawing pixels in the software renderer"
|
||||
[#15345]: https://github.com/hrydgard/ppsspp/issues/15345 "Fix some minor softgpu blending bugs"
|
||||
[#15389]: https://github.com/hrydgard/ppsspp/issues/15389 "Draw rectangles always using a specialized path in softgpu"
|
||||
[#15529]: https://github.com/hrydgard/ppsspp/issues/15529 "softgpu: Fix viewport flag clean/dirty"
|
||||
[#15440]: https://github.com/hrydgard/ppsspp/issues/15440 "softgpu: Plug bad leak of bin queue data"
|
||||
[#15410]: https://github.com/hrydgard/ppsspp/issues/15410 "softgpu: Remove offset from screenpos, adjust filtering coords"
|
||||
[#15405]: https://github.com/hrydgard/ppsspp/issues/15405 "Fix some samplerjit issues without SSE4 or AVX"
|
||||
[#15400]: https://github.com/hrydgard/ppsspp/issues/15400 "softgpu: Track dirty vs really dirty per buffer"
|
||||
[#15481]: https://github.com/hrydgard/ppsspp/issues/15481 "Fix some NEON code that had bad compile-time checks"
|
||||
[#15474]: https://github.com/hrydgard/ppsspp/issues/15474 "Merge CheckAlpha into texture decoding"
|
||||
[#15238]: https://github.com/hrydgard/ppsspp/issues/15238 "Vulkan: Be more restrictive about hardware texture upscaling on \"slow\" GPUs"
|
||||
[#15217]: https://github.com/hrydgard/ppsspp/issues/15217 "Vulkan is strict about scissor rect, so let's clamp centrally."
|
||||
[#15211]: https://github.com/hrydgard/ppsspp/issues/15211 "Vulkan: Specify Vulkan version, fix mip level generation calculation"
|
||||
[#15162]: https://github.com/hrydgard/ppsspp/issues/15162 "Integrate VMA (Vulkan Memory Allocator)"
|
||||
[#15106]: https://github.com/hrydgard/ppsspp/issues/15106 "GLES: Explicitly enable ARB_cull_distance"
|
||||
[#15075]: https://github.com/hrydgard/ppsspp/issues/15075 "Draw points using triangles"
|
||||
[#15470]: https://github.com/hrydgard/ppsspp/issues/15470 "Threading manager stresstest and fixes"
|
||||
[#14414]: https://github.com/hrydgard/ppsspp/issues/14414 "Add search for settings"
|
||||
[#15613]: https://github.com/hrydgard/ppsspp/issues/15613 "Allow to repeat a \"single\" button"
|
||||
[#15569]: https://github.com/hrydgard/ppsspp/issues/15569 "Upscaling shaders"
|
||||
[#15494]: https://github.com/hrydgard/ppsspp/issues/15494 "Add key bind to hotswap internal screen rotation"
|
||||
[#15510]: https://github.com/hrydgard/ppsspp/issues/15510 "Allow to set InternalScreenRotation per game"
|
||||
[#12958]: https://github.com/hrydgard/ppsspp/issues/12958 "Feature Request: restore software rendering ui setting on android"
|
||||
[#15016]: https://github.com/hrydgard/ppsspp/issues/15016 "[Android][Mali GPU] Vulkan backend workaround issue in some games with graphics glitch."
|
||||
[#15640]: https://github.com/hrydgard/ppsspp/issues/15640 "Disable ForceMax60FPS for GOW games and replace it with fixed 60 fps"
|
||||
[#15213]: https://github.com/hrydgard/ppsspp/issues/15213 "[Adhoc] Updated PdpCreate, PdpSend, PdpRecv, GetPdpStat, GetPtpStat"
|
||||
[#15215]: https://github.com/hrydgard/ppsspp/issues/15215 "[Adhocctl] Fix Tekken 5 Dark Resurrection Multiplayer"
|
||||
[#15549]: https://github.com/hrydgard/ppsspp/issues/15549 "GPU: Hook Sol Trigger func to flush texture"
|
||||
[#15583]: https://github.com/hrydgard/ppsspp/issues/15583 "Fix and further improve line drawing in Echochrome"
|
||||
[#15073]: https://github.com/hrydgard/ppsspp/issues/15073 "Cleanup line/point handling and refactor a bit"
|
||||
[#15500]: https://github.com/hrydgard/ppsspp/issues/15500 "Add BlueToAlpha compat.ini workaround, fixes Split/Second graphics"
|
||||
[#15501]: https://github.com/hrydgard/ppsspp/issues/15501 "Make the existing ReinterpretFramebuffers/ShaderColorBitmask path work for Split/Second"
|
||||
[#15652]: https://github.com/hrydgard/ppsspp/issues/15652 "Replace Win32 file IO with UWP safe variants and add support for getting drives to UWP build"
|
||||
[#15396]: https://github.com/hrydgard/ppsspp/issues/15396 "Add UI Tint/Saturation settings"
|
||||
[#15394]: https://github.com/hrydgard/ppsspp/issues/15394 "Allow custom UI themes"
|
||||
[#15560]: https://github.com/hrydgard/ppsspp/issues/15560 "UI: Abandon focus movement on returning from pause"
|
||||
[#15393]: https://github.com/hrydgard/ppsspp/issues/15393 "GE Debugger: Avoid crash on Step Draw with flush"
|
||||
[#15324]: https://github.com/hrydgard/ppsspp/issues/15324 "UI: Reset ZIP install errors for new ZIPs"
|
||||
[#15377]: https://github.com/hrydgard/ppsspp/issues/15377 "Debugger: Avoid mem write tag lookup on small alloc"
|
||||
[#15424]: https://github.com/hrydgard/ppsspp/issues/15424 "Windows: Create SYSTEM directory early"
|
||||
[#15402]: https://github.com/hrydgard/ppsspp/issues/15402 "GE Debugger: Highlight changed state values"
|
||||
[#15378]: https://github.com/hrydgard/ppsspp/issues/15378 "GE Debugger: Add filter to skip prim calls"
|
||||
[#15338]: https://github.com/hrydgard/ppsspp/issues/15338 "Alow flushing at will via the GE debugger"
|
||||
[#15025]: https://github.com/hrydgard/ppsspp/issues/15025 "Allow delayed loading of texture replacements"
|
||||
[#15691]: https://github.com/hrydgard/ppsspp/issues/15691 "Add a simple compat flag to workaround the Clone Wars issue, #12949"
|
||||
[#15696]: https://github.com/hrydgard/ppsspp/issues/15696 "Use the recent Clone Wars fix for Star Wars: Force Unleashed too"
|
||||
[#12949]: https://github.com/hrydgard/ppsspp/issues/12949 "Star Wars: The Clone Wars - Graphic glitch [Android/Windows]"
|
||||
[#9572]: https://github.com/hrydgard/ppsspp/issues/9572 "Star Wars force unleashed [Screen Overlay problem]"
|
||||
[#15687]: https://github.com/hrydgard/ppsspp/issues/15687 "Add Zettai Zetsumei Toshi 3"
|
||||
[#7295]: https://github.com/hrydgard/ppsspp/issues/7295 "Juiced 2: Hot Import Nights, screen artifacts and missing half of race tracks"
|
||||
[#15717]: https://github.com/hrydgard/ppsspp/issues/15717 "Allows \"merging\" render targets that overlap on the Y axis. Fixes Juiced 2"
|
||||
[#15698]: https://github.com/hrydgard/ppsspp/issues/15698 "Osk: Allow upper/lower for all keyboards"
|
60
Tools/langtool/Cargo.lock
generated
60
Tools/langtool/Cargo.lock
generated
|
@ -1,10 +1,12 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ansi_term"
|
||||
version = "0.11.0"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
|
||||
dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
@ -28,9 +30,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.33.3"
|
||||
version = "2.34.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
|
||||
checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"atty",
|
||||
|
@ -74,9 +76,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.102"
|
||||
version = "0.2.126"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2a5ac8f984bfcf3a823267e5fde638acc3325f6496633a5da6bb6eb2171e103"
|
||||
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
|
@ -104,18 +106,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.29"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d"
|
||||
checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.9"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
@ -128,9 +130,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
|||
|
||||
[[package]]
|
||||
name = "structopt"
|
||||
version = "0.3.23"
|
||||
version = "0.3.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf9d950ef167e25e0bdb073cf1d68e9ad2795ac826f2f3f59647817cf23c0bfa"
|
||||
checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"lazy_static",
|
||||
|
@ -139,9 +141,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "structopt-derive"
|
||||
version = "0.4.16"
|
||||
version = "0.4.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "134d838a2c9943ac3125cf6df165eda53493451b719f3255b2a26b85f772d0ba"
|
||||
checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
|
@ -152,13 +154,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.76"
|
||||
version = "1.0.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6f107db402c2c2055242dbf4d2af0e69197202e9faacbef9571bbe47f5a1b84"
|
||||
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -171,10 +173,16 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.8.0"
|
||||
name = "unicode-ident"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
|
||||
checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
|
@ -182,12 +190,6 @@ version = "0.1.9"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.2"
|
||||
|
@ -196,9 +198,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
|||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.3"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
|
|
|
@ -18,6 +18,7 @@ enum Command {
|
|||
CopyMissingLines {},
|
||||
CommentUnknownLines {},
|
||||
RemoveUnknownLines {},
|
||||
MoveKey { old: String, new: String, key: String },
|
||||
}
|
||||
|
||||
fn copy_missing_lines(reference_ini: &IniFile, target_ini: &mut IniFile) -> io::Result<()> {
|
||||
|
@ -55,6 +56,29 @@ fn deal_with_unknown_lines(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn move_key(
|
||||
target_ini: &mut IniFile,
|
||||
old: &str,
|
||||
new: &str,
|
||||
key: &str,
|
||||
) -> io::Result<()> {
|
||||
// Insert any missing full sections.
|
||||
if let Some(old_section) = target_ini.get_section_mut(old) {
|
||||
if let Some(line) = old_section.remove_line(key) {
|
||||
if let Some(new_section) = target_ini.get_section_mut(new) {
|
||||
new_section.insert_line_if_missing(&line);
|
||||
} else {
|
||||
println!("No new section {}", new);
|
||||
}
|
||||
} else {
|
||||
println!("No key {} in section {}", key, old);
|
||||
}
|
||||
} else {
|
||||
println!("No old section {}", old);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let opt = Opt::from_args();
|
||||
|
||||
|
@ -103,6 +127,9 @@ fn main() {
|
|||
Command::RemoveUnknownLines {} => {
|
||||
deal_with_unknown_lines(&reference_ini, &mut target_ini, true).unwrap();
|
||||
}
|
||||
Command::MoveKey { ref old, ref new,ref key, } => {
|
||||
move_key(&mut target_ini, &old, &new, &key).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
target_ini.write().unwrap();
|
||||
|
|
|
@ -11,6 +11,28 @@ pub struct Section {
|
|||
}
|
||||
|
||||
impl Section {
|
||||
pub fn remove_line(&mut self, key: &str) -> Option<String> {
|
||||
let mut remove_index = None;
|
||||
for (index, line) in self.lines.iter().enumerate() {
|
||||
let prefix = if let Some(pos) = line.find(" =") {
|
||||
&line[0..pos]
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if prefix.eq_ignore_ascii_case(&key) {
|
||||
remove_index = Some(index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(remove_index) = remove_index {
|
||||
Some(self.lines.remove(remove_index))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert_line_if_missing(&mut self, line: &str) -> bool {
|
||||
let prefix = if let Some(pos) = line.find(" =") {
|
||||
&line[0..pos + 2]
|
||||
|
|
|
@ -574,6 +574,10 @@ void SystemInfoScreen::CreateViews() {
|
|||
deviceSpecs->Add(new InfoItem(si->T("Native Resolution"), StringFromFormat("%dx%d",
|
||||
System_GetPropertyInt(SYSPROP_DISPLAY_XRES),
|
||||
System_GetPropertyInt(SYSPROP_DISPLAY_YRES))));
|
||||
deviceSpecs->Add(new InfoItem(si->T("UI Resolution"), StringFromFormat("%dx%d (dpi: %0.2f)",
|
||||
dp_xres,
|
||||
dp_yres,
|
||||
g_dpi)));
|
||||
#endif
|
||||
|
||||
#if !PPSSPP_PLATFORM(WINDOWS)
|
||||
|
|
|
@ -426,8 +426,8 @@ bool GameScreen::isRecentGame(const Path &gamePath) {
|
|||
return false;
|
||||
|
||||
const std::string resolved = File::ResolvePath(gamePath.ToString());
|
||||
for (auto it = g_Config.recentIsos.begin(); it != g_Config.recentIsos.end(); ++it) {
|
||||
const std::string recent = File::ResolvePath(*it);
|
||||
for (auto iso : g_Config.RecentIsos()) {
|
||||
const std::string recent = File::ResolvePath(iso);
|
||||
if (resolved == recent)
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1088,20 +1088,23 @@ void GameSettingsScreen::CreateViews() {
|
|||
systemSettings->Add(new PopupMultiChoice(&g_Config.iButtonPreference, sy->T("Confirmation Button"), buttonPref, 0, 2, sy->GetName(), screenManager()));
|
||||
|
||||
#if !defined(MOBILE_DEVICE) || PPSSPP_PLATFORM(ANDROID)
|
||||
// Search
|
||||
LinearLayout *searchSettings = AddTab("GameSettingsSearch", ms->T("Search"), true);
|
||||
// Hide search if screen is too small.
|
||||
if (dp_xres < dp_yres || dp_yres >= 500) {
|
||||
// Search
|
||||
LinearLayout *searchSettings = AddTab("GameSettingsSearch", ms->T("Search"), true);
|
||||
|
||||
searchSettings->Add(new ItemHeader(se->T("Find settings")));
|
||||
if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD)) {
|
||||
searchSettings->Add(new ChoiceWithValueDisplay(&searchFilter_, se->T("Filter"), (const char *)nullptr))->OnClick.Handle(this, &GameSettingsScreen::OnChangeSearchFilter);
|
||||
} else {
|
||||
searchSettings->Add(new PopupTextInputChoice(&searchFilter_, se->T("Filter"), "", 64, screenManager()))->OnChange.Handle(this, &GameSettingsScreen::OnChangeSearchFilter);
|
||||
searchSettings->Add(new ItemHeader(se->T("Find settings")));
|
||||
if (System_GetPropertyBool(SYSPROP_HAS_KEYBOARD)) {
|
||||
searchSettings->Add(new ChoiceWithValueDisplay(&searchFilter_, se->T("Filter"), (const char *)nullptr))->OnClick.Handle(this, &GameSettingsScreen::OnChangeSearchFilter);
|
||||
} else {
|
||||
searchSettings->Add(new PopupTextInputChoice(&searchFilter_, se->T("Filter"), "", 64, screenManager()))->OnChange.Handle(this, &GameSettingsScreen::OnChangeSearchFilter);
|
||||
}
|
||||
clearSearchChoice_ = searchSettings->Add(new Choice(se->T("Clear filter")));
|
||||
clearSearchChoice_->OnClick.Handle(this, &GameSettingsScreen::OnClearSearchFilter);
|
||||
noSearchResults_ = searchSettings->Add(new TextView(se->T("No settings matched '%1'"), new LinearLayoutParams(Margins(20, 5))));
|
||||
|
||||
ApplySearchFilter();
|
||||
}
|
||||
clearSearchChoice_ = searchSettings->Add(new Choice(se->T("Clear filter")));
|
||||
clearSearchChoice_->OnClick.Handle(this, &GameSettingsScreen::OnClearSearchFilter);
|
||||
noSearchResults_ = searchSettings->Add(new TextView(se->T("No settings matched '%1'"), new LinearLayoutParams(Margins(20, 5))));
|
||||
|
||||
ApplySearchFilter();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -322,7 +322,17 @@ void GameButton::Draw(UIContext &dc) {
|
|||
dc.Draw()->Flush();
|
||||
dc.RebindTexture();
|
||||
dc.SetFontStyle(dc.theme->uiFont);
|
||||
if (!gridStyle_) {
|
||||
if (gridStyle_ && ginfo->fileType == IdentifiedFileType::PPSSPP_GE_DUMP) {
|
||||
// Super simple drawing for ge dumps.
|
||||
dc.PushScissor(bounds_);
|
||||
const std::string currentTitle = ginfo->GetTitle();
|
||||
dc.SetFontScale(0.6f, 0.6f);
|
||||
dc.DrawText(title_.c_str(), bounds_.x + 4.0f, bounds_.centerY(), style.fgColor, ALIGN_VCENTER | ALIGN_LEFT);
|
||||
dc.SetFontScale(1.0f, 1.0f);
|
||||
title_ = currentTitle;
|
||||
dc.Draw()->Flush();
|
||||
dc.PopScissor();
|
||||
} else if (!gridStyle_) {
|
||||
float tw, th;
|
||||
dc.Draw()->Flush();
|
||||
dc.PushScissor(bounds_);
|
||||
|
@ -587,7 +597,7 @@ bool GameBrowser::DisplayTopBar() {
|
|||
bool GameBrowser::HasSpecialFiles(std::vector<Path> &filenames) {
|
||||
if (path_.GetPath().ToString() == "!RECENT") {
|
||||
filenames.clear();
|
||||
for (auto &str : g_Config.recentIsos) {
|
||||
for (auto &str : g_Config.RecentIsos()) {
|
||||
filenames.push_back(Path(str));
|
||||
}
|
||||
return true;
|
||||
|
@ -986,7 +996,7 @@ void MainScreen::CreateViews() {
|
|||
System_GetPermissionStatus(SYSTEM_PERMISSION_STORAGE) == PERMISSION_STATUS_GRANTED;
|
||||
bool storageIsTemporary = IsTempPath(GetSysDirectory(DIRECTORY_SAVEDATA)) && !confirmedTemporary_;
|
||||
if (showRecent && !hasStorageAccess) {
|
||||
showRecent = !g_Config.recentIsos.empty();
|
||||
showRecent = g_Config.HasRecentIsos();
|
||||
}
|
||||
|
||||
if (showRecent) {
|
||||
|
@ -1036,7 +1046,7 @@ void MainScreen::CreateViews() {
|
|||
tabAllGames->OnHighlight.Handle(this, &MainScreen::OnGameHighlight);
|
||||
tabHomebrew->OnHighlight.Handle(this, &MainScreen::OnGameHighlight);
|
||||
|
||||
if (g_Config.recentIsos.size() > 0) {
|
||||
if (g_Config.HasRecentIsos()) {
|
||||
tabHolder_->SetCurrentTab(0, true);
|
||||
} else if (g_Config.iMaxRecent > 0) {
|
||||
tabHolder_->SetCurrentTab(1, true);
|
||||
|
@ -1121,11 +1131,9 @@ void MainScreen::CreateViews() {
|
|||
ver->SetSmall(true);
|
||||
ver->SetClip(false);
|
||||
|
||||
#ifndef OPENXR
|
||||
if (System_GetPropertyBool(SYSPROP_HAS_FILE_BROWSER)) {
|
||||
rightColumnItems->Add(new Choice(mm->T("Load", "Load...")))->OnClick.Handle(this, &MainScreen::OnLoadFile);
|
||||
}
|
||||
#endif
|
||||
rightColumnItems->Add(new Choice(mm->T("Game Settings", "Settings")))->OnClick.Handle(this, &MainScreen::OnGameSettings);
|
||||
rightColumnItems->Add(new Choice(mm->T("Credits")))->OnClick.Handle(this, &MainScreen::OnCredits);
|
||||
rightColumnItems->Add(new Choice(mm->T("www.ppsspp.org")))->OnClick.Handle(this, &MainScreen::OnPPSSPPOrg);
|
||||
|
@ -1494,7 +1502,7 @@ void UmdReplaceScreen::CreateViews() {
|
|||
rightColumnItems->Add(new Choice(di->T("Cancel")))->OnClick.Handle(this, &UmdReplaceScreen::OnCancel);
|
||||
rightColumnItems->Add(new Choice(mm->T("Game Settings")))->OnClick.Handle(this, &UmdReplaceScreen::OnGameSettings);
|
||||
|
||||
if (g_Config.recentIsos.size() > 0) {
|
||||
if (g_Config.HasRecentIsos()) {
|
||||
leftColumn->SetCurrentTab(0, true);
|
||||
} else if (g_Config.iMaxRecent > 0) {
|
||||
leftColumn->SetCurrentTab(1, true);
|
||||
|
@ -1573,7 +1581,7 @@ UI::EventReturn GridSettingsScreen::GridMinusClick(UI::EventParams &e) {
|
|||
}
|
||||
|
||||
UI::EventReturn GridSettingsScreen::OnRecentClearClick(UI::EventParams &e) {
|
||||
g_Config.recentIsos.clear();
|
||||
g_Config.ClearRecentIsos();
|
||||
OnRecentChanged.Trigger(e);
|
||||
return UI::EVENT_DONE;
|
||||
}
|
||||
|
|
|
@ -203,7 +203,7 @@ public:
|
|||
lastIndex_ = nextIndex_;
|
||||
}
|
||||
|
||||
if (!g_Config.recentIsos.empty()) {
|
||||
if (g_Config.HasRecentIsos()) {
|
||||
std::shared_ptr<GameInfo> lastInfo = GetInfo(dc, lastIndex_);
|
||||
std::shared_ptr<GameInfo> nextInfo = GetInfo(dc, nextIndex_);
|
||||
dc.Flush();
|
||||
|
@ -220,12 +220,12 @@ public:
|
|||
|
||||
private:
|
||||
void CheckNext(UIContext &dc, double t) {
|
||||
if (g_Config.recentIsos.empty()) {
|
||||
if (!g_Config.HasRecentIsos()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int index = lastIndex_ + 1; index != lastIndex_; ++index) {
|
||||
if (index < 0 || index >= (int)g_Config.recentIsos.size()) {
|
||||
if (index < 0 || index >= (int)g_Config.RecentIsos().size()) {
|
||||
if (lastIndex_ == -1)
|
||||
break;
|
||||
index = 0;
|
||||
|
@ -250,7 +250,10 @@ private:
|
|||
if (index < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return g_gameInfoCache->GetInfo(dc.GetDrawContext(), Path(g_Config.recentIsos[index]), GAMEINFO_WANTBG);
|
||||
const auto recentIsos = g_Config.RecentIsos();
|
||||
if (index >= recentIsos.size())
|
||||
return nullptr;
|
||||
return g_gameInfoCache->GetInfo(dc.GetDrawContext(), Path(recentIsos[index]), GAMEINFO_WANTBG);
|
||||
}
|
||||
|
||||
void DrawTex(UIContext &dc, std::shared_ptr<GameInfo> &ginfo, float amount) {
|
||||
|
|
|
@ -631,7 +631,7 @@
|
|||
<ClCompile Include="..\..\ext\libpng17\pngwutil.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="..\..\ext\libpng17\CMakeLists.txt" />
|
||||
<None Include="..\..\ext\libpng17\CMakeLists.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\Common\Math\fast\fast_matrix_neon.S" />
|
||||
|
|
Binary file not shown.
14
UWP/Package.appxmanifest
Normal file
14
UWP/Package.appxmanifest
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10">
|
||||
<Identity Name="DUMMY-APPXMANIFEST" Publisher="CN=DUMMY" Version="1.0.0.0" />
|
||||
<Properties>
|
||||
<DisplayName>DUMMY</DisplayName>
|
||||
<PublisherDisplayName>DUMMY</PublisherDisplayName>
|
||||
</Properties>
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
|
||||
</Dependencies>
|
||||
<Resources>
|
||||
<Resource Language="x-generate" />
|
||||
</Resources>
|
||||
</Package>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue