mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-13 17:49:29 +01:00
Merge pull request #19975 from hrydgard/custom_icon
Allow custom game icons if texture replacement is enabled
This commit is contained in:
5 files changed
+84
-10
No files matched your search
@@ -314,3 +314,48 @@ void ZipFileReader::CloseFile(VFSOpenFile *vfsOpenFile) {
|
||||
lock_.unlock();
|
||||
delete file;
|
||||
}
|
||||
|
||||
bool ReadSingleFileFromZip(Path zipFile, const char *path, std::string *data, std::mutex *mutex) {
|
||||
zip *zip = nullptr;
|
||||
int error = 0;
|
||||
if (zipFile.Type() == PathType::CONTENT_URI) {
|
||||
int fd = File::OpenFD(zipFile, File::OPEN_READ);
|
||||
if (!fd) {
|
||||
return false;
|
||||
}
|
||||
zip = zip_fdopen(fd, 0, &error);
|
||||
} else {
|
||||
zip = zip_open(zipFile.c_str(), 0, &error);
|
||||
}
|
||||
|
||||
if (!zip) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct zip_stat zstat;
|
||||
if (zip_stat(zip, path, ZIP_FL_NOCASE | ZIP_FL_UNCHANGED, &zstat) != 0) {
|
||||
return false;
|
||||
}
|
||||
zip_file *file = zip_fopen_index(zip, zstat.index, ZIP_FL_UNCHANGED);
|
||||
if (!file) {
|
||||
return false;
|
||||
}
|
||||
if (mutex) {
|
||||
mutex->lock();
|
||||
}
|
||||
data->resize(zstat.size);
|
||||
if (zip_fread(file, data->data(), zstat.size) != zstat.size) {
|
||||
if (mutex) {
|
||||
mutex->unlock();
|
||||
}
|
||||
zip_fclose(file);
|
||||
zip_close(zip);
|
||||
return false;
|
||||
}
|
||||
if (mutex) {
|
||||
mutex->unlock();
|
||||
}
|
||||
zip_fclose(file);
|
||||
zip_close(zip);
|
||||
return true;
|
||||
}
|
||||
@@ -54,3 +54,7 @@ private:
|
||||
std::string inZipPath_;
|
||||
Path zipPath_;
|
||||
};
|
||||
|
||||
// When you just want a single file from a ZIP, and don't care about accurate error reporting, use this.
|
||||
// The buffer should be free'd with free. Mutex will be locked while updating data, if non-null.
|
||||
bool ReadSingleFileFromZip(Path zipFile, const char *path, std::string *data, std::mutex *mutex);
|
||||
@@ -103,7 +103,7 @@ u32 sceNetStrchr(void *str, int ch) {
|
||||
|
||||
u32 sceNetStrlen(const char* str) {
|
||||
// Redirect that to libc
|
||||
u32 res = std::strlen(str);
|
||||
u32 res = (u32)std::strlen(str);
|
||||
|
||||
return hleLogDebug(Log::sceNet, res);
|
||||
}
|
||||
|
||||
+31
-7
@@ -1,3 +1,4 @@
|
||||
|
||||
// Copyright (c) 2013- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
@@ -25,6 +26,7 @@
|
||||
#include "Common/GPU/thin3d.h"
|
||||
#include "Common/Thread/ThreadManager.h"
|
||||
#include "Common/File/VFS/VFS.h"
|
||||
#include "Common/File/VFS/ZipFileReader.h"
|
||||
#include "Common/File/FileUtil.h"
|
||||
#include "Common/File/Path.h"
|
||||
#include "Common/Render/ManagedTexture.h"
|
||||
@@ -453,6 +455,22 @@ static bool ReadVFSToString(const char *filename, std::string *contents, std::mu
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool LoadReplacementImage(GameInfo *info, GameInfoTex *tex, const char *filename) {
|
||||
if (g_Config.bReplaceTextures) {
|
||||
const Path customIconFilename = GetSysDirectory(DIRECTORY_TEXTURES) / info->id / filename;
|
||||
const Path zipFilename = GetSysDirectory(DIRECTORY_TEXTURES) / info->id / "textures.zip";
|
||||
if (File::Exists(customIconFilename)) {
|
||||
tex->dataLoaded = ReadLocalFileToString(customIconFilename, &tex->data, &info->lock);
|
||||
} else if (File::Exists(zipFilename)) {
|
||||
// Read file from zip if available.
|
||||
tex->dataLoaded = ReadSingleFileFromZip(zipFilename, filename, &tex->data, &info->lock);
|
||||
}
|
||||
return tex->dataLoaded;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class GameInfoWorkItem : public Task {
|
||||
public:
|
||||
GameInfoWorkItem(const Path &gamePath, std::shared_ptr<GameInfo> &info, GameInfoFlags flags)
|
||||
@@ -542,20 +560,23 @@ public:
|
||||
|
||||
// Then, ICON0.PNG.
|
||||
if (flags_ & GameInfoFlags::ICON) {
|
||||
if (pbp.GetSubFileSize(PBP_ICON0_PNG) > 0) {
|
||||
if (LoadReplacementImage(info_.get(), &info_->icon, "icon.png")) {
|
||||
// Nothing more to do
|
||||
} else if (pbp.GetSubFileSize(PBP_ICON0_PNG) > 0) {
|
||||
std::lock_guard<std::mutex> lock(info_->lock);
|
||||
pbp.GetSubFileAsString(PBP_ICON0_PNG, &info_->icon.data);
|
||||
} else {
|
||||
Path screenshot_jpg = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.jpg");
|
||||
Path screenshot_png = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.png");
|
||||
// Try using png/jpg screenshots first
|
||||
if (File::Exists(screenshot_png))
|
||||
if (File::Exists(screenshot_png)) {
|
||||
ReadLocalFileToString(screenshot_png, &info_->icon.data, &info_->lock);
|
||||
else if (File::Exists(screenshot_jpg))
|
||||
} else if (File::Exists(screenshot_jpg)) {
|
||||
ReadLocalFileToString(screenshot_jpg, &info_->icon.data, &info_->lock);
|
||||
else
|
||||
} else {
|
||||
// Read standard icon
|
||||
ReadVFSToString("unknown.png", &info_->icon.data, &info_->lock);
|
||||
}
|
||||
}
|
||||
info_->icon.dataLoaded = true;
|
||||
}
|
||||
@@ -755,8 +776,13 @@ handleELF:
|
||||
}
|
||||
|
||||
// Fall back to unknown icon if ISO is broken/is a homebrew ISO, override is allowed though
|
||||
// First, do try to get an icon from the replacement texture pack, if available.
|
||||
if (flags_ & GameInfoFlags::ICON) {
|
||||
if (!ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->icon.data, &info_->lock)) {
|
||||
if (LoadReplacementImage(info_.get(), &info_->icon, "icon.png")) {
|
||||
// Nothing more to do
|
||||
} else if (ReadFileToString(&umd, "/PSP_GAME/ICON0.PNG", &info_->icon.data, &info_->lock)) {
|
||||
info_->icon.dataLoaded = true;
|
||||
} else {
|
||||
Path screenshot_jpg = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.jpg");
|
||||
Path screenshot_png = GetSysDirectory(DIRECTORY_SCREENSHOT) / (info_->id + "_00000.png");
|
||||
// Try using png/jpg screenshots first
|
||||
@@ -768,8 +794,6 @@ handleELF:
|
||||
DEBUG_LOG(Log::Loader, "Loading unknown.png because no icon was found");
|
||||
info_->icon.dataLoaded = ReadVFSToString("unknown.png", &info_->icon.data, &info_->lock);
|
||||
}
|
||||
} else {
|
||||
info_->icon.dataLoaded = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -280,6 +280,7 @@ void GameSettingsScreen::CreateTabs() {
|
||||
void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings) {
|
||||
auto gr = GetI18NCategory(I18NCat::GRAPHICS);
|
||||
auto vr = GetI18NCategory(I18NCat::VR);
|
||||
auto dev = GetI18NCategory(I18NCat::DEVELOPER);
|
||||
|
||||
using namespace UI;
|
||||
|
||||
@@ -415,6 +416,8 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings)
|
||||
});
|
||||
}
|
||||
|
||||
graphicsSettings->Add(new CheckBox(&g_Config.bReplaceTextures, dev->T("Replace textures")));
|
||||
|
||||
graphicsSettings->Add(new ItemHeader(gr->T("Frame Rate Control")));
|
||||
static const char *frameSkip[] = {"Off", "1", "2", "3", "4", "5", "6", "7", "8"};
|
||||
graphicsSettings->Add(new PopupMultiChoice(&g_Config.iFrameSkip, gr->T("Frame Skipping"), frameSkip, 0, ARRAY_SIZE(frameSkip), I18NCat::GRAPHICS, screenManager()));
|
||||
@@ -527,8 +530,6 @@ void GameSettingsScreen::CreateGraphicsSettings(UI::ViewGroup *graphicsSettings)
|
||||
return DoesBackendSupportHWTess() && !g_Config.bSoftwareRendering && g_Config.bHardwareTransform;
|
||||
});
|
||||
|
||||
// In case we're going to add few other antialiasing option like MSAA in the future.
|
||||
// graphicsSettings->Add(new CheckBox(&g_Config.bFXAA, gr->T("FXAA")));
|
||||
graphicsSettings->Add(new ItemHeader(gr->T("Texture Scaling")));
|
||||
#ifndef MOBILE_DEVICE
|
||||
static const char *texScaleLevels[] = {"Off", "2x", "3x", "4x", "5x"};
|
||||
|
||||
Reference in new issue
Block a user