Compare commits

...

14 commits

Author SHA1 Message Date
Herman Semenov b8e5081235
Merge d60935a274 into dbcac0e48c 2024-05-15 09:43:38 +07:00
Henrik Rydgård dbcac0e48c
Merge pull request #19142 from hrydgard/fix-shortcut-launch
Android: Fix issue where shortcuts wouldn't override the currently running game.
2024-05-14 17:30:18 +02:00
Henrik Rydgård dadc37cb9b EmuScreen: If a requested-to-boot game is already running, ignore the request. 2024-05-14 00:04:40 +02:00
Henrik Rydgård ecdc7940f4 Android: Fix issue where shortcuts wouldn't override the currently running game. 2024-05-14 00:02:59 +02:00
Henrik Rydgård 8fdb6e16b1
Merge pull request #19139 from hrydgard/android-upgrade-sdk
Android: Upgrade SDK and target versions, implement shortcut icons
2024-05-13 16:29:14 +02:00
Henrik Rydgård ec5eff6aa2 Android: implement loading icons for shortcuts - but only works if PPSSPP is running in the background. 2024-05-13 15:34:02 +02:00
Henrik Rydgård bc378fd0d6 Android: Compile using the newest SDK, update targetVersion to 34 2024-05-13 14:59:13 +02:00
Henrik Rydgård 9ab775fde1
Merge pull request #19138 from hrydgard/shortcut-icons-windows
Windows: When using "Create shortcut", use the game's icon instead of PPSSPP's
2024-05-13 13:42:25 +02:00
Henrik Rydgård bb7972c437 Correct the wPlanes field in the ico format 2024-05-13 01:48:15 +02:00
Henrik Rydgård 4d0f3183f2 Windows: When using "Create shortcut", use the game's icon instead of PPSSPP's.
Since on Windows, shortcuts can't embed icons, we first save the game's
icon .png as an .ico in the SAVESTATE folder (there might be a better
place, but it also doesn't seem worth it to create a new folder for
this).

Part of #10885 (Android functionality still missing, for example).
2024-05-13 01:37:53 +02:00
Henrik Rydgård 0f15bf4808
Merge pull request #19136 from hrydgard/gpi-gpo-support
Add basic checkbox UI for GPI switches, add display of GPO LEDs
2024-05-12 20:17:01 +02:00
Henrik Rydgård 1dd363ae3e Add the new UI strings for GPI/GPO switches/leds 2024-05-12 18:10:53 +02:00
Henrik Rydgård a059750f5a Add basic checkbox UI for GPI switched, add display of GPO LEDs
Try it with Parappa.
2024-05-12 18:01:25 +02:00
Herman Semenov d60935a274 [Core/HLE/Dialog] Fixed memleak after first return error and increase lifetime in current scope 2024-04-05 20:15:16 +03:00
67 changed files with 457 additions and 64 deletions

View file

@ -852,6 +852,11 @@ void CheckBox::GetContentDimensions(const UIContext &dc, float &w, float &h) con
w = bounds_.w;
}
BitCheckBox::BitCheckBox(uint32_t *bitfield, uint32_t bit, std::string_view text, std::string_view smallText, LayoutParams *layoutParams)
: CheckBox(nullptr, text, smallText, layoutParams), bitfield_(bitfield), bit_(bit) {
_dbg_assert_msg_(bit != 0, "bit is a mask, not a bit index");
}
void BitCheckBox::Toggle() {
if (bitfield_) {
*bitfield_ = *bitfield_ ^ bit_;

View file

@ -916,10 +916,8 @@ class CollapsibleHeader : public CheckBox {
class BitCheckBox : public CheckBox {
public:
BitCheckBox(uint32_t *bitfield, uint32_t bit, std::string_view text, std::string_view smallText = "", LayoutParams *layoutParams = nullptr)
: CheckBox(nullptr, text, smallText, layoutParams), bitfield_(bitfield), bit_(bit) {
}
// bit is a bitmask (should only have a single bit set), not a bit index.
BitCheckBox(uint32_t *bitfield, uint32_t bit, std::string_view text, std::string_view smallText = "", LayoutParams *layoutParams = nullptr);
BitCheckBox(int *bitfield, int bit, std::string_view text, std::string_view smallText = "", LayoutParams *layoutParams = nullptr) : BitCheckBox((uint32_t *)bitfield, (uint32_t)bit, text, smallText, layoutParams) {}
void Toggle() override;

View file

@ -306,6 +306,8 @@ static const ConfigSetting generalSettings[] = {
ConfigSetting("IgnoreCompatSettings", &g_Config.sIgnoreCompatSettings, "", CfgFlag::PER_GAME | CfgFlag::REPORT),
ConfigSetting("RunBehindPauseMenu", &g_Config.bRunBehindPauseMenu, false, CfgFlag::DEFAULT),
ConfigSetting("ShowGPOLEDs", &g_Config.bShowGPOLEDs, false, CfgFlag::PER_GAME),
};
static bool DefaultSasThread() {

View file

@ -265,6 +265,9 @@ struct Config {
bool bRenderDuplicateFrames;
bool bRenderMultiThreading;
// HW debug
bool bShowGPOLEDs;
// Sound
bool bEnableSound;
int iAudioBackend;

View file

@ -512,15 +512,15 @@ int SavedataParam::Save(SceUtilitySavedataParam* param, const std::string &saveD
// For each file, 13 bytes for filename, 16 bytes for file hash (0 in PPSSPP), 3 byte for padding
u32 tmpDataSize = 0;
SaveSFOFileListEntry *tmpDataOrig = (SaveSFOFileListEntry *)sfoFile->GetValueData("SAVEDATA_FILE_LIST", &tmpDataSize);
SaveSFOFileListEntry *updatedList = new SaveSFOFileListEntry[FILE_LIST_COUNT_MAX];
auto updatedList = std::make_unique<SaveSFOFileListEntry[]>(FILE_LIST_COUNT_MAX);
if (tmpDataSize != 0)
memcpy(updatedList, tmpDataOrig, std::min(tmpDataSize, FILE_LIST_TOTAL_SIZE));
memcpy(updatedList.get(), tmpDataOrig, std::min(tmpDataSize, FILE_LIST_TOTAL_SIZE));
if (tmpDataSize < FILE_LIST_TOTAL_SIZE)
memset(updatedList + tmpDataSize, 0, FILE_LIST_TOTAL_SIZE - tmpDataSize);
memset(updatedList.get() + tmpDataSize, 0, FILE_LIST_TOTAL_SIZE - tmpDataSize);
// Leave a hash there and unchanged if it was already there.
if (secureMode && param->dataBuf.IsValid()) {
const std::string saveFilename = GetFileName(param);
for (auto entry = updatedList; entry < updatedList + FILE_LIST_COUNT_MAX; ++entry) {
for (auto entry = updatedList.get(); entry < updatedList.get() + FILE_LIST_COUNT_MAX; ++entry) {
if (entry->filename[0] != '\0') {
if (strncmp(entry->filename, saveFilename.c_str(), sizeof(entry->filename)) != 0)
continue;
@ -532,8 +532,7 @@ int SavedataParam::Save(SceUtilitySavedataParam* param, const std::string &saveD
}
}
sfoFile->SetValue("SAVEDATA_FILE_LIST", (u8 *)updatedList, FILE_LIST_TOTAL_SIZE, (int)FILE_LIST_TOTAL_SIZE);
delete[] updatedList;
sfoFile->SetValue("SAVEDATA_FILE_LIST", (u8 *)updatedList.get(), FILE_LIST_TOTAL_SIZE, (int)FILE_LIST_TOTAL_SIZE);
// Init param with 0. This will be used to detect crypted save or not on loading
u8 zeroes[128]{};

View file

@ -1084,13 +1084,12 @@ static u32 sceFontOpenUserMemory(u32 libHandle, u32 memoryFontPtr, u32 memoryFon
while (!Memory::IsValidAddress(memoryFontPtr + memoryFontLength - 1)) {
--memoryFontLength;
}
Font *f = new Font(fontData, memoryFontLength);
LoadedFont *font = fontLib->OpenFont(f, FONT_OPEN_USERBUFFER, *errorCode);
auto f = std::make_unique<Font>(fontData, memoryFontLength);
LoadedFont *font = fontLib->OpenFont(f.get(), FONT_OPEN_USERBUFFER, *errorCode);
if (font) {
*errorCode = 0;
return hleLogSuccessX(SCEFONT, font->Handle());
}
delete f;
return 0;
}
@ -1123,15 +1122,14 @@ static u32 sceFontOpenUserFile(u32 libHandle, const char *fileName, u32 mode, u3
return hleLogError(SCEFONT, 0, "file does not exist");
}
Font *f = new Font(buffer);
auto f = std::make_unique<Font>(buffer);
FontOpenMode openMode = mode == 0 ? FONT_OPEN_USERFILE_HANDLERS : FONT_OPEN_USERFILE_FULL;
LoadedFont *font = fontLib->OpenFont(f, openMode, *errorCode);
LoadedFont *font = fontLib->OpenFont(f.get(), openMode, *errorCode);
if (font) {
*errorCode = 0;
return hleLogSuccessInfoX(SCEFONT, font->Handle());
}
delete f;
// Message was already logged.
return 0;
}

View file

@ -100,6 +100,8 @@ static bool kernelRunning = false;
KernelObjectPool kernelObjects;
KernelStats kernelStats;
u32 registeredExitCbId;
u32 g_GPOBits; // Really just 8 bits on the real hardware.
u32 g_GPIBits; // Really just 8 bits on the real hardware.
void __KernelInit()
{
@ -161,6 +163,7 @@ void __KernelInit()
__PPGeInit();
kernelRunning = true;
g_GPOBits = 0;
INFO_LOG(SCEKERNEL, "Kernel initialized.");
}
@ -355,18 +358,19 @@ int sceKernelRegisterDefaultExceptionHandler()
return 0;
}
void sceKernelSetGPO(u32 ledAddr)
void sceKernelSetGPO(u32 ledBits)
{
// Sets debug LEDs.
// Not really interesting, and a few games really spam it
// DEBUG_LOG(SCEKERNEL, "sceKernelSetGPO(%02x)", ledAddr);
// Sets debug LEDs. Some games do interesting stuff with this, like a metronome in Parappa.
// Shows up as a vertical strip of LEDs at the side of the screen, if enabled.
g_GPOBits = ledBits;
}
u32 sceKernelGetGPI()
{
// Always returns 0 on production systems.
DEBUG_LOG(SCEKERNEL, "0=sceKernelGetGPI()");
return 0;
// On developer systems, there are 8 switches that control the lower 8 bits of the return value.
DEBUG_LOG(SCEKERNEL, "%d=sceKernelGetGPI()", g_GPIBits);
return g_GPIBits;
}
// #define LOG_CACHE

View file

@ -569,6 +569,9 @@ struct KernelStats {
extern KernelStats kernelStats;
extern u32 registeredExitCbId;
extern u32 g_GPOBits;
extern u32 g_GPIBits;
void Register_ThreadManForUser();
void Register_ThreadManForKernel();
void Register_LoadExecForUser();

View file

@ -407,7 +407,7 @@ static void ExecuteWebServer() {
AndroidJNIThreadContext context; // Destructor detaches.
auto http = new http::Server(new NewThreadExecutor());
auto http = std::make_unique<http::Server>(new NewThreadExecutor());
http->RegisterHandler("/", &HandleListing);
// This lists all the (current) recent ISOs.
http->SetFallbackHandler(&HandleFallback);
@ -437,7 +437,6 @@ static void ExecuteWebServer() {
http->Stop();
StopAllDebuggers();
delete http;
UpdateStatus(ServerStatus::FINISHED);
}

View file

@ -142,9 +142,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.61"
version = "2.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c993ed8ccba56ae856363b1845da7266a7cb78e1d146c8a32d54b45a8b831fc9"
checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704"
dependencies = [
"proc-macro2",
"quote",

View file

@ -56,6 +56,7 @@
#include "Core/System.h"
#include "Core/Reporting.h"
#include "Core/CoreParameter.h"
#include "Core/HLE/sceKernel.h" // GPI/GPO
#include "Core/MIPS/MIPSTables.h"
#include "Core/MIPS/JitCommon/JitBlockCache.h"
#include "Core/MIPS/JitCommon/JitCommon.h"
@ -141,6 +142,11 @@ void DevMenuScreen::CreatePopupContents(UI::ViewGroup *parent) {
items->Add(new Choice(dev->T("Reset limited logging")))->OnClick.Handle(this, &DevMenuScreen::OnResetLimitedLogging);
items->Add(new Choice(dev->T("GPI/GPO switches/LEDs")))->OnClick.Add([=](UI::EventParams &e) {
screenManager()->push(new GPIGPOScreen(dev->T("GPI/GPO switches/LEDs")));
return UI::EVENT_DONE;
});
items->Add(new Choice(dev->T("Create frame dump")))->OnClick.Add([](UI::EventParams &e) {
GPURecord::RecordNextFrame([](const Path &dumpPath) {
NOTICE_LOG(SYSTEM, "Frame dump created at '%s'", dumpPath.c_str());
@ -213,6 +219,16 @@ void DevMenuScreen::dialogFinished(const Screen *dialog, DialogResult result) {
// TriggerFinish(DR_OK);
}
void GPIGPOScreen::CreatePopupContents(UI::ViewGroup *parent) {
using namespace UI;
auto dev = GetI18NCategory(I18NCat::DEVELOPER);
parent->Add(new CheckBox(&g_Config.bShowGPOLEDs, dev->T("Show GPO LEDs")));
for (int i = 0; i < 8; i++) {
std::string name = ApplySafeSubstitutions(dev->T("GPI switch %1"), i);
parent->Add(new BitCheckBox(&g_GPIBits, 1 << i, name));
}
}
void LogScreen::UpdateLog() {
using namespace UI;
RingbufferLogListener *ring = LogManager::GetInstance()->GetRingbufferListener();

View file

@ -145,6 +145,15 @@ class AddressPromptScreen : public PopupScreen {
unsigned int addr_;
};
class GPIGPOScreen : public PopupScreen {
public:
GPIGPOScreen(std::string_view title) : PopupScreen(title, "OK") {}
const char *tag() const override { return "GPIGPO"; }
protected:
void CreatePopupContents(UI::ViewGroup *parent) override;
};
class JitCompareScreen : public UIDialogScreenWithBackground {
public:
void CreateViews() override;

View file

@ -537,6 +537,11 @@ void EmuScreen::sendMessage(UIMessage message, const char *value) {
return;
}
} else if (message == UIMessage::REQUEST_GAME_BOOT) {
// TODO: Ignore or not if it's the same game that's already running?
if (gamePath_ == Path(value)) {
WARN_LOG(LOADER, "Game already running, ignoring");
return;
}
const char *ext = strrchr(value, '.');
if (ext != nullptr && !strcmp(ext, ".ppst")) {
SaveState::Load(Path(value), -1, &AfterStateBoot);
@ -1521,6 +1526,8 @@ bool EmuScreen::hasVisibleUI() {
return true;
if (g_Config.bEnableCardboardVR || g_Config.bEnableNetworkChat)
return true;
if (g_Config.bShowGPOLEDs)
return true;
// Debug UI.
if ((DebugOverlay)g_Config.iDebugOverlay != DebugOverlay::OFF || g_Config.bShowDeveloperMenu)
return true;
@ -1571,6 +1578,26 @@ void EmuScreen::renderUI() {
}
#endif
if (g_Config.bShowGPOLEDs) {
// Draw a vertical strip of LEDs at the right side of the screen.
const float ledSize = 24.0f;
const float spacing = 4.0f;
const float height = 8 * ledSize + 7 * spacing;
const float x = ctx->GetBounds().w - spacing - ledSize;
const float y = (ctx->GetBounds().h - height) * 0.5f;
ctx->FillRect(UI::Drawable(0xFF000000), Bounds(x - spacing, y - spacing, ledSize + spacing * 2, height + spacing * 2));
for (int i = 0; i < 8; i++) {
int bit = (g_GPOBits >> i) & 1;
uint32_t color = 0xFF30FF30;
if (!bit) {
color = darkenColor(darkenColor(color));
}
Bounds ledBounds(x, y + (spacing + ledSize) * i, ledSize, ledSize);
ctx->FillRect(UI::Drawable(color), ledBounds);
}
ctx->Flush();
}
if (coreState == CORE_RUNTIME_ERROR || coreState == CORE_STEPPING) {
const MIPSExceptionInfo &info = Core_GetExceptionInfo();
if (info.type != MIPSExceptionType::NONE) {

View file

@ -456,7 +456,7 @@ class GameInfoWorkItem : public Task {
// Mark everything requested as done, so
std::unique_lock<std::mutex> lock(info_->lock);
info_->MarkReadyNoLock(flags_);
ERROR_LOG(LOADER, "Failed getting game info.");
ERROR_LOG(LOADER, "Failed getting game info for %s", info_->GetFilePath().ToVisualString().c_str());
return;
}

View file

@ -109,6 +109,10 @@ class GameInfo {
std::string GetTitle();
void SetTitle(const std::string &newTitle);
const Path &GetFilePath() const {
return filePath_;
}
bool Ready(GameInfoFlags flags) {
std::unique_lock<std::mutex> guard(lock);
// Avoid the operator, we want to check all the bits.

View file

@ -1843,6 +1843,11 @@ void DeveloperToolsScreen::CreateViews() {
list->Add(new CheckBox(&g_Config.bShowOnScreenMessages, dev->T("Show on-screen messages")));
list->Add(new Choice(dev->T("GPI/GPO switches/LEDs")))->OnClick.Add([=](UI::EventParams &e) {
screenManager()->push(new GPIGPOScreen(dev->T("GPI/GPO switches/LEDs")));
return UI::EVENT_DONE;
});
#if PPSSPP_PLATFORM(ANDROID)
static const char *framerateModes[] = { "Default", "Request 60Hz", "Force 60Hz" };
PopupMultiChoice *framerateMode = list->Add(new PopupMultiChoice(&g_Config.iDisplayFramerateMode, gr->T("Framerate mode"), framerateModes, 0, ARRAY_SIZE(framerateModes), I18NCat::GRAPHICS, screenManager()));

View file

@ -6,6 +6,8 @@
#include <thread>
#include "Common/Data/Encoding/Utf8.h"
#include "Common/File/FileUtil.h"
#include "Common/Data/Format/PNGLoad.h"
#include "ShellUtil.h"
#include <shlobj.h>
@ -188,7 +190,7 @@ namespace W32Util {
// http://msdn.microsoft.com/en-us/library/aa969393.aspx
HRESULT CreateLink(LPCWSTR lpszPathObj, LPCWSTR lpszArguments, LPCWSTR lpszPathLink, LPCWSTR lpszDesc) {
static HRESULT CreateLink(LPCWSTR lpszPathObj, LPCWSTR lpszArguments, LPCWSTR lpszPathLink, LPCWSTR lpszDesc, LPCWSTR lpszIcon, int iconIndex) {
HRESULT hres;
IShellLink *psl = nullptr;
hres = CoInitializeEx(NULL, COINIT_MULTITHREADED);
@ -205,7 +207,9 @@ HRESULT CreateLink(LPCWSTR lpszPathObj, LPCWSTR lpszArguments, LPCWSTR lpszPathL
psl->SetPath(lpszPathObj);
psl->SetArguments(lpszArguments);
psl->SetDescription(lpszDesc);
// psl->SetIconLocation(..)
if (lpszIcon) {
psl->SetIconLocation(lpszIcon, iconIndex);
}
// Query IShellLink for the IPersistFile interface, used for saving the
// shortcut in persistent storage.
@ -223,7 +227,7 @@ HRESULT CreateLink(LPCWSTR lpszPathObj, LPCWSTR lpszArguments, LPCWSTR lpszPathL
return hres;
}
bool CreateDesktopShortcut(std::string_view argumentPath, std::string_view gameTitleStr) {
bool CreateDesktopShortcut(std::string_view argumentPath, std::string_view gameTitleStr, const Path &icoFile) {
// Get the desktop folder
wchar_t *pathbuf = new wchar_t[4096];
SHGetFolderPath(0, CSIDL_DESKTOPDIRECTORY, NULL, SHGFP_TYPE_CURRENT, pathbuf);
@ -264,7 +268,12 @@ bool CreateDesktopShortcut(std::string_view argumentPath, std::string_view gameT
sanitizedArgument = "\"" + sanitizedArgument + "\"";
CreateLink(moduleFilename.c_str(), ConvertUTF8ToWString(sanitizedArgument).c_str(), pathbuf, ConvertUTF8ToWString(gameTitle).c_str());
std::wstring icon;
if (!icoFile.empty()) {
icon = icoFile.ToWString();
}
CreateLink(moduleFilename.c_str(), ConvertUTF8ToWString(sanitizedArgument).c_str(), pathbuf, ConvertUTF8ToWString(gameTitle).c_str(), icon.empty() ? nullptr : icon.c_str(), 0);
// TODO: Also extract the game icon and convert to .ico, put it somewhere under Memstick, and set it.
@ -272,4 +281,56 @@ bool CreateDesktopShortcut(std::string_view argumentPath, std::string_view gameT
return false;
}
// Function to create an icon file from PNG image data (these icons require Windows Vista).
// The Old New Thing comes to the rescue again! ChatGPT failed miserably.
// https://devblogs.microsoft.com/oldnewthing/20101018-00/?p=12513
// https://devblogs.microsoft.com/oldnewthing/20101022-00/?p=12473
bool CreateICOFromPNGData(const uint8_t *imageData, size_t imageDataSize, const Path &icoPath) {
if (imageDataSize <= sizeof(PNGHeaderPeek)) {
return false;
}
// Parse the PNG
PNGHeaderPeek pngHeader;
memcpy(&pngHeader, imageData, sizeof(PNGHeaderPeek));
if (pngHeader.Width() > 256 || pngHeader.Height() > 256) {
// Reject the png as an icon.
return false;
}
struct IconHeader {
uint16_t reservedZero;
uint16_t type; // should be 1
uint16_t imageCount;
};
IconHeader hdr{ 0, 1, 1 };
struct IconDirectoryEntry {
BYTE bWidth;
BYTE bHeight;
BYTE bColorCount;
BYTE bReserved;
WORD wPlanes;
WORD wBitCount;
DWORD dwBytesInRes;
DWORD dwImageOffset;
};
IconDirectoryEntry entry{};
entry.bWidth = pngHeader.Width();
entry.bHeight = pngHeader.Height();
entry.bColorCount = 0;
entry.dwBytesInRes = (DWORD)imageDataSize;
entry.wPlanes = 1;
entry.wBitCount = 32;
entry.dwImageOffset = sizeof(hdr) + sizeof(entry);
FILE *file = File::OpenCFile(icoPath, "wb");
if (!file) {
return false;
}
fwrite(&hdr, sizeof(hdr), 1, file);
fwrite(&entry, sizeof(entry), 1, file);
fwrite(imageData, 1, imageDataSize, file);
fclose(file);
return true;
}
} // namespace

View file

@ -5,18 +5,22 @@
#include <vector>
#include <thread>
class Path;
namespace W32Util
{
// Can't make initialPath a string_view, need the null so might as well require it.
std::string BrowseForFolder(HWND parent, std::string_view title, std::string_view initialPath);
std::string BrowseForFolder(HWND parent, const wchar_t *title, std::string_view initialPath);
bool BrowseForFileName (bool _bLoad, HWND _hParent, const wchar_t*_pTitle,
const wchar_t *_pInitialFolder,const wchar_t *_pFilter,const wchar_t*_pExtension,
std::string& _strFileName);
std::vector<std::string> BrowseForFileNameMultiSelect(bool _bLoad, HWND _hParent, const wchar_t*_pTitle,
const wchar_t*_pInitialFolder,const wchar_t*_pFilter,const wchar_t*_pExtension);
// Can't make initialPath a string_view, need the null so might as well require it.
std::string BrowseForFolder(HWND parent, std::string_view title, std::string_view initialPath);
std::string BrowseForFolder(HWND parent, const wchar_t *title, std::string_view initialPath);
bool BrowseForFileName(bool _bLoad, HWND _hParent, const wchar_t*_pTitle,
const wchar_t *_pInitialFolder, const wchar_t *_pFilter, const wchar_t*_pExtension,
std::string& _strFileName);
std::vector<std::string> BrowseForFileNameMultiSelect(bool _bLoad, HWND _hParent, const wchar_t*_pTitle,
const wchar_t*_pInitialFolder, const wchar_t*_pFilter, const wchar_t*_pExtension);
std::string UserDocumentsPath();
std::string UserDocumentsPath();
bool CreateDesktopShortcut(std::string_view argumentPath, std::string_view gameTitle);
} // namespace
bool CreateDesktopShortcut(std::string_view argumentPath, std::string_view gameTitle, const Path &icoFile);
bool CreateICOFromPNGData(const uint8_t *imageData, size_t imageDataSize, const Path &icoPath);
} // namespace

View file

@ -635,7 +635,27 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string
return true;
}
case SystemRequestType::CREATE_GAME_SHORTCUT:
return W32Util::CreateDesktopShortcut(param1, param2);
{
// Get the game info to get our hands on the icon png
Path gamePath(param1);
std::shared_ptr<GameInfo> info = g_gameInfoCache->GetInfo(nullptr, gamePath, GameInfoFlags::ICON);
Path icoPath;
if (info->icon.dataLoaded) {
// Write the icon png out as a .ICO file so the shortcut can point to it
// Savestate seems like a good enough place to put ico files.
Path iconFolder = GetSysDirectory(PSPDirectories::DIRECTORY_SAVESTATE);
icoPath = iconFolder / (info->id + ".ico");
if (!File::Exists(icoPath)) {
if (!W32Util::CreateICOFromPNGData((const uint8_t *)info->icon.data.data(), info->icon.data.size(), icoPath)) {
ERROR_LOG(SYSTEM, "ICO creation failed");
icoPath.clear();
}
}
}
return W32Util::CreateDesktopShortcut(param1, param2, icoPath);
}
case SystemRequestType::RUN_CALLBACK_IN_WNDPROC:
{
auto func = reinterpret_cast<void (*)(void *window, void *userdata)>(param3);

View file

@ -11,6 +11,7 @@ androidGitVersion {
}
dependencies {
// 1.2.0 is the newest version we can use that won't complain about minSdk version.
def appcompat_version = "1.2.0"
implementation "androidx.appcompat:appcompat:$appcompat_version"
@ -21,7 +22,7 @@ dependencies {
}
android {
flavorDimensions "variant"
flavorDimensions += "variant"
namespace 'org.ppsspp.ppsspp'
signingConfigs {
debug {
@ -45,10 +46,20 @@ android {
}
}
compileSdk 33
compileSdk 34
ndkVersion "21.4.7075529"
defaultConfig {
/*
configurations.all {
resolutionStrategy {
// Newer versions are not compatible with our minsdk. Should find a way to exclude it entirely
// since we have no use for this transitive dependency.
force 'androidx.emoji2:emoji2-views-helper:1.0.0'
}
}
*/
applicationId 'org.ppsspp.ppsspp'
if (androidGitVersion.name() != "unknown" && androidGitVersion.code() >= 14000000) {
// Start using automatic Android version numbers from version 1.4.
@ -63,7 +74,7 @@ android {
new File("versioncode.txt").write(androidGitVersion.code().toString())
minSdk 9
targetSdk 33
targetSdk 34
if (project.hasProperty("ANDROID_VERSION_CODE") && project.hasProperty("ANDROID_VERSION_NAME")) {
versionCode ANDROID_VERSION_CODE
versionName ANDROID_VERSION_NAME

View file

@ -547,6 +547,8 @@ bool System_GetPropertyBool(SystemProperty prop) {
return deviceType != DEVICE_TYPE_VR;
case SYSPROP_HAS_ACCELEROMETER:
return deviceType == DEVICE_TYPE_MOBILE;
case SYSPROP_CAN_CREATE_SHORTCUT:
return false; // We can't create shortcuts directly from game code, but we can from the Android UI.
#ifndef HTTPS_NOT_AVAILABLE
case SYSPROP_SUPPORTS_HTTPS:
return !g_Config.bDisableHTTPS;
@ -789,6 +791,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init
std::vector<std::string> temp;
args.push_back(app_name.c_str());
if (!shortcut_param.empty()) {
EARLY_LOG("NativeInit shortcut param %s", shortcut_param.c_str());
parse_args(temp, shortcut_param);
for (const auto &arg : temp) {
args.push_back(arg.c_str());
@ -797,7 +800,7 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init
NativeInit((int)args.size(), &args[0], user_data_path.c_str(), externalStorageDir.c_str(), cacheDir.c_str());
// In debug mode, don't allow creating software Vulkan devices (reject by VulkaMaybeAvailable).
// In debug mode, don't allow creating software Vulkan devices (reject by VulkanMaybeAvailable).
// Needed for #16931.
#ifdef NDEBUG
if (!VulkanMayBeAvailable()) {
@ -1319,9 +1322,9 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_accelerometer(JNIEnv *,
NativeAccelerometer(x, y, z);
}
extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendMessageFromJava(JNIEnv *env, jclass, jstring message, jstring param) {
std::string msg = GetJavaString(env, message);
std::string prm = GetJavaString(env, param);
extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendMessageFromJava(JNIEnv *env, jclass, jstring jmessage, jstring jparam) {
std::string msg = GetJavaString(env, jmessage);
std::string prm = GetJavaString(env, jparam);
// A bit ugly, see InputDeviceState.java.
static InputDeviceID nextInputDeviceID = DEVICE_ID_ANY;
@ -1364,6 +1367,13 @@ extern "C" void JNICALL Java_org_ppsspp_ppsspp_NativeApp_sendMessageFromJava(JNI
System_PostUIMessage(UIMessage::POWER_SAVING, prm);
} else if (msg == "exception") {
g_OSD.Show(OSDType::MESSAGE_ERROR, std::string("Java Exception"), prm, 10.0f);
} else if (msg == "shortcutParam") {
if (prm.empty()) {
WARN_LOG(SYSTEM, "shortcutParam empty");
return;
}
INFO_LOG(SYSTEM, "shortcutParam received: %s", prm.c_str());
System_PostUIMessage(UIMessage::REQUEST_GAME_BOOT, StripQuotes(prm));
} else {
ERROR_LOG(SYSTEM, "Got unexpected message from Java, ignoring: %s / %s", msg.c_str(), prm.c_str());
}
@ -1662,7 +1672,7 @@ static void VulkanEmuThread(ANativeWindow *wnd) {
// NOTE: This is defunct and not working, due to how the Android storage functions currently require
// a PpssppActivity specifically and we don't have one here.
extern "C" jstring Java_org_ppsspp_ppsspp_ShortcutActivity_queryGameName(JNIEnv *env, jclass, jstring jpath) {
extern "C" jstring Java_org_ppsspp_ppsspp_ShortcutActivity_queryGameName(JNIEnv * env, jclass, jstring jpath) {
bool teardownThreadManager = false;
if (!g_threadManager.IsInitialized()) {
INFO_LOG(SYSTEM, "No thread manager - initializing one");
@ -1710,3 +1720,58 @@ extern "C" jstring Java_org_ppsspp_ppsspp_ShortcutActivity_queryGameName(JNIEnv
return env->NewStringUTF(result.c_str());
}
extern "C"
JNIEXPORT jbyteArray JNICALL
Java_org_ppsspp_ppsspp_ShortcutActivity_queryGameIcon(JNIEnv * env, jclass clazz, jstring jpath) {
bool teardownThreadManager = false;
if (!g_threadManager.IsInitialized()) {
INFO_LOG(SYSTEM, "No thread manager - initializing one");
// Need a thread manager.
teardownThreadManager = true;
g_threadManager.Init(1, 1);
}
// TODO: implement requestIcon()
Path path = Path(GetJavaString(env, jpath));
INFO_LOG(SYSTEM, "queryGameIcon(%s)", path.c_str());
jbyteArray result = nullptr;
GameInfoCache *cache = new GameInfoCache();
std::shared_ptr<GameInfo> info = cache->GetInfo(nullptr, path, GameInfoFlags::ICON);
// Wait until it's done: this is synchronous, unfortunately.
if (info) {
INFO_LOG(SYSTEM, "GetInfo successful, waiting");
int attempts = 1000;
while (!info->Ready(GameInfoFlags::ICON)) {
sleep_ms(1);
attempts--;
if (!attempts) {
break;
}
}
INFO_LOG(SYSTEM, "Done waiting");
if (info->Ready(GameInfoFlags::ICON)) {
if (!info->icon.data.empty()) {
INFO_LOG(SYSTEM, "requestIcon: Got icon");
result = env->NewByteArray(info->icon.data.size());
env->SetByteArrayRegion(result, 0, info->icon.data.size(), (const jbyte *)info->icon.data.data());
}
} else {
INFO_LOG(SYSTEM, "requestIcon: Filetype unknown");
}
} else {
INFO_LOG(SYSTEM, "No info from cache");
}
delete cache;
if (teardownThreadManager) {
g_threadManager.Teardown();
}
return result;
}

View file

@ -443,6 +443,7 @@ public void Initialize() {
String languageRegion = Locale.getDefault().getLanguage() + "_" + Locale.getDefault().getCountry();
String shortcut = overrideShortcutParam == null ? shortcutParam : overrideShortcutParam;
overrideShortcutParam = null;
shortcutParam = null;
NativeApp.audioConfig(optimalFramesPerBuffer, optimalSampleRate);
NativeApp.init(model, deviceType, languageRegion, apkFilePath, dataDir, extStorageDir, externalFilesDir, nativeLibDir, additionalStorageDirs, cacheDir, shortcut, Build.VERSION.SDK_INT, Build.BOARD);
@ -594,6 +595,7 @@ public void onCreate(Bundle savedInstanceState) {
// whether to start at 1x or 2x.
sizeManager.updateDisplayMeasurements();
boolean wasInitialized = initialized;
if (!initialized) {
Initialize();
initialized = true;
@ -661,6 +663,13 @@ public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "setcontentview after");
startRenderLoopThread();
}
if (shortcutParam != null && shortcutParam.length() > 0) {
Log.i(TAG, "Got shortcutParam in onCreate on secondary run: " + shortcutParam);
// Make sure we only send it once.
NativeApp.sendMessageFromJava("shortcutParam", shortcutParam);
shortcutParam = null;
}
}
@Override

View file

@ -99,7 +99,9 @@ public void run() {
if (data != null) {
String path = data.toString();
Log.i(TAG, "Found Shortcut Parameter in data: " + path);
super.setShortcutParam("\"" + path.replace("\\", "\\\\").replace("\"", "\\\"") + "\"");
String escaped = "\"" + path.replace("\\", "\\\\").replace("\"", "\\\"") + "\"";
Log.i(TAG, "Escaped: " + escaped);
super.setShortcutParam(escaped);
// Toast.makeText(getApplicationContext(), path, Toast.LENGTH_SHORT).show();
} else {
String param = getIntent().getStringExtra(SHORTCUT_EXTRA_KEY);

View file

@ -4,6 +4,8 @@
import android.app.AlertDialog;
import android.content.Intent;
import android.content.Intent.ShortcutIconResource;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
@ -75,6 +77,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
}
public static native String queryGameName(String path);
public static native byte[] queryGameIcon(String path);
// Create shortcut as response for ACTION_CREATE_SHORTCUT intent.
private void respondToShortcutRequest(Uri uri) {
@ -99,13 +102,13 @@ private void respondToShortcutRequest(Uri uri) {
if (path.startsWith("content://")) {
String [] segments = path.split("/");
try {
pathStr = java.net.URLDecoder.decode(segments[segments.length - 1], StandardCharsets.UTF_8.name());
pathStr = java.net.URLDecoder.decode(segments[segments.length - 1], "UTF-8");
} catch (Exception e) {
Log.i(TAG, "Exception getting name: " + e);
}
} else if (path.startsWith("file:///")) {
try {
pathStr = java.net.URLDecoder.decode(path.substring(7), StandardCharsets.UTF_8.name());
pathStr = java.net.URLDecoder.decode(path.substring(7), "UTF-8");
} catch (Exception e) {
Log.i(TAG, "Exception getting name: " + e);
}
@ -116,16 +119,19 @@ private void respondToShortcutRequest(Uri uri) {
String[] pathSegments = pathStr.split("/");
name = pathSegments[pathSegments.length - 1];
/*
// No longer working for various reasons.
PpssppActivity.CheckABIAndLoadLibrary();
String name = queryGameName(path);
if (name.equals("")) {
String gameName = queryGameName(path);
byte [] iconData = null;
if (gameName.equals("")) {
Log.i(TAG, "Failed to retrieve game name - ignoring.");
showBadGameMessage();
return;
}*/
// This probably happened because PPSSPP isn't running so the GameInfoCache isn't working.
// Let's just continue with our fallback name until we can fix that.
// showBadGameMessage();
// return;
} else {
name = gameName;
iconData = queryGameIcon(path);
}
Log.i(TAG, "Game name: " + name + " : Creating shortcut to " + uri.toString());
@ -134,9 +140,23 @@ private void respondToShortcutRequest(Uri uri) {
Intent responseIntent = new Intent();
responseIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
responseIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, name);
ShortcutIconResource iconResource = ShortcutIconResource.fromContext(this, R.drawable.ic_launcher);
responseIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource);
boolean setIcon = false;
if (iconData != null) {
// Try to create a PNG from the iconData.
Bitmap bmp = BitmapFactory.decodeByteArray(iconData, 0, iconData.length);
if (bmp != null) {
// Scale it to a square.
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bmp, 144, 144, true);
responseIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, scaledBitmap);
}
setIcon = true;
}
if (!setIcon) {
// Fall back to the PPSSPP icon.
ShortcutIconResource iconResource = ShortcutIconResource.fromContext(this, R.drawable.ic_launcher);
responseIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE, iconResource);
}
setResult(RESULT_OK, responseIntent);
// Must call finish for result to be returned immediately

View file

@ -315,6 +315,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Frame profiler
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU log profiler = GPU log profiler
@ -341,6 +343,7 @@ Run CPU Tests = ‎شغل فحوص المعالج
Save new textures = ‎حفظ الرسم الجديد
Shader Viewer = ‎مستعرض الرسوميات
Show Developer Menu = ‎أظهر قائمة المطور
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = إظهار الرسائل على الشاشة
Stats = ‎الحالات
System Information = ‎معلومات النظام

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Frame profiler
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = Run CPU tests
Save new textures = Save new textures
Shader Viewer = Shader viewer
Show Developer Menu = Show developer menu
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Stats
System Information = System information

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Frame profiler
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = Run CPU tests
Save new textures = Save new textures
Shader Viewer = Shader viewer
Show Developer Menu = Покажи developer меню
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Stats
System Information = Системна информация

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Amidar el rendiment
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = Proves de CPU
Save new textures = Desa les noves textures
Shader Viewer = Visualitzador de shader
Show Developer Menu = Mostra el menú de desenvolupament
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Estadístiques
System Information = Informació del sistema

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Profilovač snímku
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = Spustit zkoušky CPU
Save new textures = Save new textures
Shader Viewer = Prohlížeč shaderů
Show Developer Menu = Zobrazit nabídku pro vývojáře
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Statistiky
System Information = Informace o systému

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Frame profiler
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = Kør CPU test
Save new textures = Gem nye textures
Shader Viewer = Shader viewer
Show Developer Menu = Vis udviklermenu
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Stats
System Information = System information

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Frame Profiler
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU Treibertest
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = CPU Test starten
Save new textures = Speichere neue Texturen
Shader Viewer = Shader-Anzeige
Show Developer Menu = Zeige Entwicklermenü
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Statistiken
System Information = Systeminformationen

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Frame profiler
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = Pajalanni tes CPU
Save new textures = Save new textures
Shader Viewer = Shader viewer
Show Developer Menu = Show developer menu
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Stats
System Information = Pempakitan to sistem dipake

View file

@ -333,6 +333,8 @@ FPU = FPU
Framedump tests = Framedump tests
Frame Profiler = Frame profiler
Frame timing = Frame timing
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU Profile = GPU profile
@ -359,6 +361,7 @@ Run CPU Tests = Run CPU tests
Save new textures = Save new textures
Shader Viewer = Shader viewer
Show Developer Menu = Show developer menu
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Stats
System Information = System information

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame Profiler = Medir rendimiento
Frame timing = Frame timing
Framedump tests = Tests de volcado de cuadros
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = Test de controlador GPU
GPU log profiler = log de perfiles GPU
@ -333,6 +335,7 @@ Run CPU Tests = Pruebas de CPU
Save new textures = Guardar texturas nuevas
Shader Viewer = Visor de shader
Show Developer Menu = Mostrar menú de desarrollo
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Mostrar mensajes en pantalla
Stats = Estadísticas
System Information = Información del sistema

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Pruebas de volcado de frames
Frame Profiler = Perfilado de frame
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = Probar controlador GPU
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = Ejecutando pruebas de CPU
Save new textures = Guardar nuevas texturas
Shader Viewer = Visor de shader
Show Developer Menu = Mostrar menú de desarrollador
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Mostrar mensajes en pantalla
Stats = Estadísticas
System Information = Información del sistema

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Frame profiler
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = تست کردن جی پی یو سخت افزار
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = CPU اجرای تست
Save new textures = ذخیره بافت جدید
Shader Viewer = Shader viewer
Show Developer Menu = نمایش منو توسعه دهنده
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = نمایش پیام اسکرین
Stats = Stats
System Information = ‎اطلاعات سیستم

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Frame profiler
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = Suorita suoritin testi
Save new textures = Save new textures
Shader Viewer = Shader viewer
Show Developer Menu = Show developer menu
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Stats
System Information = System information

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Profileur d'image
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = Test du pilote du GPU
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = Exécuter des tests CPU
Save new textures = Sauvegarder les nouvelles textures
Shader Viewer = Visionneur de shader
Show Developer Menu = Montrer le menu développeur "MenuDev"
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Afficher les messages à l'écran
Stats = Statistiques
System Information = Informations système

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Frame profiler
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = Probas de CPU
Save new textures = Save new textures
Shader Viewer = Shader viewer
Show Developer Menu = Mostrar menú de desenrolo
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Stats
System Information = Información do sistema

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Profiler πλαισίου
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = Εκκίνηση τέστ CPU
Save new textures = Αποθήκευση νέων υφών
Shader Viewer = Προβολέας Shader
Show Developer Menu = Εμφάνιση μενού προγραμματιστών
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Στατιστικά
System Information = Πληροφορίες Συστήματος

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Frame profiler
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = הרץ בדיקות מעבד
Save new textures = Save new textures
Shader Viewer = Shader viewer
Show Developer Menu = Show developer menu
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Stats
System Information = מידע על המערכת

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Frame profiler
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = דבעמ תוקידב ץרה
Save new textures = Save new textures
Shader Viewer = Shader viewer
Show Developer Menu = Show developer menu
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Stats
System Information = תכרעמה לע עדימ

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Frame profiler
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = Testiranje GPU drivera
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = Pokreni CPU testove
Save new textures = Spremi nove teksture
Shader Viewer = Pregled sjenčanja
Show Developer Menu = Prikaži developer izbornik
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Stats
System Information = System informacija

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Képkocka profilozó
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver teszt
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = CPU tesztek futtatása
Save new textures = Új textúrák mentése
Shader Viewer = Shader megjelenítő
Show Developer Menu = Fejlesztői menü megjelenítése
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Statisztikák
System Information = Rendszer információ

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Tes pembuangan laju bingkai
Frame Profiler = Profil laju bingkai
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = Tes driver GPU
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = Jalankan pengujian CPU
Save new textures = Simpan tekstur baru
Shader Viewer = Penampil shader
Show Developer Menu = Tampilkan menu pengembang
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Tampilkan obrolan di layar
Stats = Statistik
System Information = Informasi sistem

View file

@ -307,6 +307,8 @@ Fragment = Frammento
Frame timing = Frame timing
Framedump tests = Test del framedump
Frame Profiler = Profilatore di Frame
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = Visualizzatore dell'Allocatore GPU
GPU Driver Test = Test dei driver GPU
GPU log profiler = Profilatore dei registri GPU
@ -333,6 +335,7 @@ Run CPU Tests = Fai Test CPU
Save new textures = Salva nuove texture
Shader Viewer = Visualizzatore shader
Show Developer Menu = Mostra Menu Sviluppatore
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Mostra i messaggi on-screen
Stats = Statistiche
System Information = Informazioni Sistema

View file

@ -307,6 +307,8 @@ Fragment = フラグメント
Frame timing = フレームタイミング
Framedump tests = フレームダンプのテスト
Frame Profiler = フレームプロファイラ
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPUドライバをテスト
GPU Profile = GPUプロファイル
@ -333,6 +335,7 @@ Run CPU Tests = CPUテストを実行する
Save new textures = 新しいテクスチャを保存する
Shader Viewer = シェーダビューワ
Show Developer Menu = 開発者向けメニューを表示する
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = オンスクリーンメッセージを表示する
Stats = 状況
System Information = システム情報

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Pigura Profiler
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = Mbukak Tes CPU
Save new textures = Save new textures
Shader Viewer = Tampilan shader
Show Developer Menu = Tampilno menu pengembang
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Stats
System Information = Informasi Sistem

View file

@ -309,6 +309,8 @@ FPU = FPU
Framedump tests = 프레임 덤프 테스트
Frame Profiler = 프레임 프로파일러
Frame timing = 프레임 타이밍
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU 할당기 뷰어
GPU Driver Test = GPU 드라이버 테스트
GPU Profile = GPU 프로파일
@ -335,6 +337,7 @@ Run CPU Tests = CPU 테스트 실행
Save new textures = 새로운 텍스처 저장
Shader Viewer = 셰이더 뷰어
Show Developer Menu = 개발자 메뉴 표시
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = 화면 메시지 표시
Stats = 상태
System Information = 시스템 정보

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = ລາຍລະອຽດຂອງເຟຣມ
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = ເອີ້ນໃຊ້ການທົດສອບ CPU
Save new textures = ບັນທຶກພື້ນຜິວໃໝ່
Shader Viewer = ມຸມມອງການປັບໄລ່ເສດສີ
Show Developer Menu = ສະແດງເມນູສຳລັບນັກພັດທະນາ
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = ສະຖິຕິ
System Information = ຂໍ້ມູນຂອງລະບົບ

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Frame profiler
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = Atidaryti pagrindinio procesoriaus testus
Save new textures = Save new textures
Shader Viewer = Shader viewer
Show Developer Menu = Rodyti kūrėjų meniu
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Stats
System Information = Sistemos informacija

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Frame profiler
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = Ujian driver GPU
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = Jalankan percubaan CPU
Save new textures = Save new textures
Shader Viewer = Shader viewer
Show Developer Menu = Papar menu pembangun
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Stats
System Information = Maklumat sistem

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Frameanalyse
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = CPU-controles uitvoeren
Save new textures = Nieuwe textures opslaan
Shader Viewer = Shader weergeven
Show Developer Menu = Ontwikkelaarsmenu weergeven
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Statistieken
System Information = Systeeminformatie

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Frame profiler
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = Kjør CPU-test
Save new textures = Save new textures
Shader Viewer = Shader viewer
Show Developer Menu = Show developer menu
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Stats
System Information = Systeminformasjon

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Test zrzutu klatki
Frame Profiler = Profiler klatki
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = Test sterownika GPU
GPU log profiler = Profilowanie logów GPU
@ -333,6 +335,7 @@ Run CPU Tests = Uruchom testy CPU
Save new textures = Zapisz nową teksturę
Shader Viewer = Podgląd Shaderów
Show Developer Menu = Pokaż przycisk menu dewelopera
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Pokaż komunikaty na ekranie
Stats = Statystyki
System Information = Informacje o systemie

View file

@ -333,6 +333,8 @@ FPU = FPU
Framedump tests = Testes dos dumps dos frames
Frame Profiler = Analista dos frames
Frame timing = Tempo do frame
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = Visualizador do Distribuidor da GPU
GPU Driver Test = Teste do driver da GPU
GPU Profile = Perfil da GPU
@ -359,6 +361,7 @@ Run CPU Tests = Executar testes da CPU
Save new textures = Salvar novas texturas
Shader Viewer = Visualizador dos shaders
Show Developer Menu = Mostrar menu do desenvolvedor
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Mostrar mensagens na tela
Stats = Estatísticas
System Information = Informação do sistema

View file

@ -331,6 +331,8 @@ Fragment = Fragmento
Frame timing = Tempo do frame
Framedump tests = Testes dos dumps dos frames
Frame Profiler = Analista dos frames
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = Visualizador do Distribuidor da GPU
GPU Driver Test = Teste do driver da GPU
GPU Profile = Perfil da GPU
@ -357,6 +359,7 @@ Run CPU Tests = Executar testes na CPU
Save new textures = Guardar novas texturas
Shader Viewer = Visualizador dos Shaders
Show Developer Menu = Mostrar Menu de Desenvolvedor
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Mostrar mensagens no ecrã
Stats = Estatísticas
System Information = Informação do sistema

View file

@ -308,6 +308,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Frame profiler
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU log profiler = GPU log profiler
@ -334,6 +336,7 @@ Run CPU Tests = Run CPU tests
Save new textures = Save new textures
Shader Viewer = Shader viewer
Show Developer Menu = Show developer menu
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Stats
System Information = System information

View file

@ -307,6 +307,8 @@ Fragment = Фрагмент
Frame timing = Время кадра
Framedump tests = Тест дампов кадров
Frame Profiler = Профайлер кадров
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = Просмотрщик аллокатора ГП
GPU Driver Test = Проверка драйвера ГП
GPU log profiler = Профилировщик логов ГП
@ -333,6 +335,7 @@ Run CPU Tests = Запустить тесты ЦП
Save new textures = Сохранять новые текстуры
Shader Viewer = Просмотрщик шейдеров
Show Developer Menu = Показывать меню разработчика
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Показывать сообщения на экране
Stats = Статистика
System Information = Информация о системе

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump-tester
Frame Profiler = Frame-profiler
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU drivrutins-test
GPU log profiler = GPU logg-profiler
@ -333,6 +335,7 @@ Run CPU Tests = Kör CPU-tester
Save new textures = Spara nya texturer
Shader Viewer = Shader-visare
Show Developer Menu = Visa Developer-menyn
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Stats
System Information = Systeminformation

View file

@ -308,6 +308,8 @@ Fragment = Fragment
Frame timing = Timing ng frame
Framedump tests = Framedump tests
Frame Profiler = Frame profiler
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU log profiler = GPU log profiler
@ -334,6 +336,7 @@ Run CPU Tests = Magsagawa ng CPU Tests
Save new textures = I-save ang mga bagong texture
Shader Viewer = Shader viewer
Show Developer Menu = Ipakita ang Developer Menu
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Ipakita ang mensahe sa screen
Stats = Istatistik
System Information = Impormasyon tungkol sa sistema

View file

@ -308,6 +308,8 @@ Framebuffer List = รายการของเฟรมบัฟเฟอร
Framedump tests = ทดสอบไฟล์เฟรมดั๊มพ์
Frame Profiler = รายละเอียดของเฟรม
Frame timing = ช่วงเวลาของเฟรม
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = ตัวแสดงการจัดสรร GPU
GPU Driver Test = ทดสอบไดรเวอร์ GPU
GPU log profiler = ตัวแสดงค่าโปรไฟล์ GPU
@ -334,6 +336,7 @@ Run CPU Tests = เรียกใช้การทดสอบซีพีย
Save new textures = บันทึกพื้นผิวลงในแหล่งที่เก็บข้อมูล
Shader Viewer = มุมมองการปรับเฉดแสงสี
Show Developer Menu = แสดงเมนูสำหรับนักพัฒนา
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = แสดงข้อความการแจ้งเตือนต่างๆ
Stats = สถิติ
System Information = ข้อมูลโดยรวมของระบบ

View file

@ -309,6 +309,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump testleri
Frame Profiler = Frame profiler
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU sürücü testi
GPU log profiler = GPU log profiler
@ -335,6 +337,7 @@ Run CPU Tests = İşlemci testlerini başlat
Save new textures = Yeni dokuları kaydet
Shader Viewer = Shader Görüntüleyici
Show Developer Menu = Geliştirici Menüsünü Göster
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Ekran üzerinde mesajları göster
Stats = İstatistikler
System Information = Sistem bilgisi

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Профілі кадрів
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = Перевірка драйверу GPU
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = Запустити тести CPU
Save new textures = Зберегти нові текстури
Shader Viewer = Переглядач шейдеру
Show Developer Menu = Показати меню розробника
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Статистика
System Information = Інформація про систему

View file

@ -307,6 +307,8 @@ Fragment = Fragment
Frame timing = Frame timing
Framedump tests = Framedump tests
Frame Profiler = Khung hồ sơ
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU Allocator Viewer
GPU Driver Test = GPU driver test
GPU log profiler = GPU log profiler
@ -333,6 +335,7 @@ Run CPU Tests = Chạy thử CPU
Save new textures = Lưu file textures mới
Shader Viewer = Xem trước đỗ bóng
Show Developer Menu = Hiện menu NPH
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = Show on-screen messages
Stats = Thống kê
System Information = Thông tin hệ thống

View file

@ -307,6 +307,8 @@ Fragment = 片段着色器
Frame timing = 帧时间统计信息
Framedump tests = 帧转储测试
Frame Profiler = 帧分析器
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU分配器查看
GPU Driver Test = GPU驱动程序测试
GPU log profiler = GPU日志分析器
@ -333,6 +335,7 @@ Run CPU Tests = 运行CPU测试
Save new textures = 保存新纹理
Shader Viewer = 着色器查看器
Show Developer Menu = 显示开发者菜单
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = 屏幕上方显示消息
Stats = 统计数据
System Information = 系统信息

View file

@ -307,6 +307,8 @@ Fragment = 片段
Frame timing = 影格計時
Framedump tests = 影格傾印測試
Frame Profiler = 影格分析工具
GPI switch %1 = GPI switch %1
GPI/GPO switches/LEDs = GPI/GPO switches/LEDs
GPU Allocator Viewer = GPU 配置器檢視器
GPU Driver Test = GPU 驅動程式測試
GPU Profile = GPU 設定檔
@ -333,6 +335,7 @@ Run CPU Tests = 執行 CPU 測試
Save new textures = 儲存新紋理
Shader Viewer = 著色器檢視器
Show Developer Menu = 顯示開發人員選單
Show GPO LEDs = Show GPO LEDs
Show on-screen messages = 顯示螢幕訊息
Stats = 統計資料
System Information = 系統資訊