Merge pull request #19668 from hrydgard/file-system-perf

File system perf part 1: Remove some unnecessary file access
This commit is contained in:
Henrik Rydgård 2024-11-28 15:22:02 +01:00 committed by GitHub
commit 18b20e3175
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 124 additions and 96 deletions

View file

@ -28,6 +28,8 @@
#include "Common/File/DirListing.h"
#include "Common/File/FileUtil.h"
#include "Common/File/AndroidStorage.h"
#include "Common/TimeUtil.h"
#include "Common/Log.h"
#if !defined(__linux__) && !defined(_WIN32) && !defined(__QNX__)
#define stat64 stat
@ -40,6 +42,9 @@
#define fileno
#endif // HAVE_LIBNX
// NOTE: There's another one in FileUtil.cpp.
constexpr bool SIMULATE_SLOW_IO = false;
namespace File {
#if PPSSPP_PLATFORM(WINDOWS)
@ -52,6 +57,11 @@ static uint64_t FiletimeToStatTime(FILETIME ft) {
#endif
bool GetFileInfo(const Path &path, FileInfo * fileInfo) {
if (SIMULATE_SLOW_IO) {
INFO_LOG(Log::System, "GetFileInfo %s", path.c_str());
sleep_ms(300, "slow-io-sim");
}
switch (path.Type()) {
case PathType::NATIVE:
break; // OK
@ -171,6 +181,11 @@ std::vector<File::FileInfo> ApplyFilter(std::vector<File::FileInfo> files, const
}
bool GetFilesInDir(const Path &directory, std::vector<FileInfo> *files, const char *filter, int flags) {
if (SIMULATE_SLOW_IO) {
INFO_LOG(Log::System, "GetFilesInDir %s", directory.c_str());
sleep_ms(300, "slow-io-sim");
}
if (directory.Type() == PathType::CONTENT_URI) {
bool exists = false;
std::vector<File::FileInfo> fileList = Android_ListContentUri(directory.ToString(), &exists);
@ -233,6 +248,9 @@ bool GetFilesInDir(const Path &directory, std::vector<FileInfo> *files, const ch
return false;
}
do {
if (SIMULATE_SLOW_IO) {
sleep_ms(100, "slow-io-sim");
}
const std::string virtualName = ConvertWStringToUTF8(ffd.cFileName);
// check for "." and ".."
if (!(flags & GETFILES_GET_NAVIGATION_ENTRIES) && (virtualName == "." || virtualName == ".."))
@ -317,8 +335,7 @@ bool GetFilesInDir(const Path &directory, std::vector<FileInfo> *files, const ch
#if PPSSPP_PLATFORM(WINDOWS)
// Returns a vector with the device names
std::vector<std::string> GetWindowsDrives()
{
std::vector<std::string> GetWindowsDrives() {
std::vector<std::string> drives;
#if PPSSPP_PLATFORM(UWP)
@ -336,16 +353,13 @@ std::vector<std::string> GetWindowsDrives()
#else
const DWORD buffsize = GetLogicalDriveStrings(0, NULL);
std::vector<wchar_t> buff(buffsize);
if (GetLogicalDriveStrings(buffsize, buff.data()) == buffsize - 1)
{
if (GetLogicalDriveStrings(buffsize, buff.data()) == buffsize - 1) {
auto drive = buff.data();
while (*drive)
{
while (*drive) {
std::string str(ConvertWStringToUTF8(drive));
str.pop_back(); // we don't want the final backslash
str += "/";
drives.push_back(str);
// advance to next drive
while (*drive++) {}
}

View file

@ -47,6 +47,7 @@
#include "Common/File/AndroidContentURI.h"
#include "Common/File/FileUtil.h"
#include "Common/StringUtils.h"
#include "Common/TimeUtil.h"
#include "Common/SysError.h"
#ifdef _WIN32
@ -89,6 +90,9 @@
#include <sys/stat.h>
// NOTE: There's another one in DirListing.cpp.
constexpr bool SIMULATE_SLOW_IO = false;
#ifndef S_ISDIR
#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
#endif
@ -111,6 +115,10 @@
namespace File {
FILE *OpenCFile(const Path &path, const char *mode) {
if (SIMULATE_SLOW_IO) {
INFO_LOG(Log::System, "OpenCFile %s, %s", path.c_str(), mode);
sleep_ms(300, "slow-io-sim");
}
switch (path.Type()) {
case PathType::NATIVE:
break;
@ -209,6 +217,11 @@ static std::string OpenFlagToString(OpenFlag flags) {
}
int OpenFD(const Path &path, OpenFlag flags) {
if (SIMULATE_SLOW_IO) {
INFO_LOG(Log::System, "OpenFD %s, %d", path.c_str(), flags);
sleep_ms(300, "slow-io-sim");
}
switch (path.Type()) {
case PathType::CONTENT_URI:
break;
@ -302,6 +315,11 @@ static bool ResolvePathVista(const std::wstring &path, wchar_t *buf, DWORD bufSi
#endif
std::string ResolvePath(const std::string &path) {
if (SIMULATE_SLOW_IO) {
INFO_LOG(Log::System, "ResolvePath %s", path.c_str());
sleep_ms(100, "slow-io-sim");
}
if (startsWith(path, "http://") || startsWith(path, "https://")) {
return path;
}
@ -390,6 +408,11 @@ bool ExistsInDir(const Path &path, const std::string &filename) {
}
bool Exists(const Path &path) {
if (SIMULATE_SLOW_IO) {
sleep_ms(200, "slow-io-sim");
INFO_LOG(Log::System, "Exists %s", path.c_str());
}
if (path.Type() == PathType::CONTENT_URI) {
return Android_FileExists(path.c_str());
}
@ -421,14 +444,19 @@ bool Exists(const Path &path) {
}
// Returns true if filename exists and is a directory
bool IsDirectory(const Path &filename) {
switch (filename.Type()) {
bool IsDirectory(const Path &path) {
if (SIMULATE_SLOW_IO) {
sleep_ms(100, "slow-io-sim");
INFO_LOG(Log::System, "IsDirectory %s", path.c_str());
}
switch (path.Type()) {
case PathType::NATIVE:
break; // OK
case PathType::CONTENT_URI:
{
FileInfo info;
if (!Android_GetFileInfo(filename.ToString(), &info)) {
if (!Android_GetFileInfo(path.ToString(), &info)) {
return false;
}
return info.exists && info.isDirectory;
@ -440,21 +468,21 @@ bool IsDirectory(const Path &filename) {
#if defined(_WIN32)
WIN32_FILE_ATTRIBUTE_DATA data{};
#if PPSSPP_PLATFORM(UWP)
if (!GetFileAttributesExFromAppW(filename.ToWString().c_str(), GetFileExInfoStandard, &data) || data.dwFileAttributes == INVALID_FILE_ATTRIBUTES) {
if (!GetFileAttributesExFromAppW(path.ToWString().c_str(), GetFileExInfoStandard, &data) || data.dwFileAttributes == INVALID_FILE_ATTRIBUTES) {
#else
if (!GetFileAttributesEx(filename.ToWString().c_str(), GetFileExInfoStandard, &data) || data.dwFileAttributes == INVALID_FILE_ATTRIBUTES) {
if (!GetFileAttributesEx(path.ToWString().c_str(), GetFileExInfoStandard, &data) || data.dwFileAttributes == INVALID_FILE_ATTRIBUTES) {
#endif
auto err = GetLastError();
if (err != ERROR_FILE_NOT_FOUND) {
WARN_LOG(Log::Common, "GetFileAttributes failed on %s: %08x %s", filename.ToVisualString().c_str(), (uint32_t)err, GetStringErrorMsg(err).c_str());
WARN_LOG(Log::Common, "GetFileAttributes failed on %s: %08x %s", path.ToVisualString().c_str(), (uint32_t)err, GetStringErrorMsg(err).c_str());
}
return false;
}
DWORD result = data.dwFileAttributes;
return (result & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY;
#else
std::string copy = filename.ToString();
struct stat file_info;
std::string copy = path.ToString();
struct stat file_info{};
int result = stat(copy.c_str(), &file_info);
if (result < 0) {
WARN_LOG(Log::Common, "IsDirectory: stat failed on %s: %s", copy.c_str(), GetLastErrorMsg().c_str());
@ -467,6 +495,9 @@ bool IsDirectory(const Path &filename) {
// Deletes a given filename, return true on success
// Doesn't supports deleting a directory
bool Delete(const Path &filename) {
if (SIMULATE_SLOW_IO) {
sleep_ms(200, "slow-io-sim");
}
switch (filename.Type()) {
case PathType::NATIVE:
break; // OK
@ -516,6 +547,10 @@ bool Delete(const Path &filename) {
// Returns true if successful, or path already exists.
bool CreateDir(const Path &path) {
if (SIMULATE_SLOW_IO) {
sleep_ms(100, "slow-io-sim");
INFO_LOG(Log::System, "CreateDir %s", path.c_str());
}
switch (path.Type()) {
case PathType::NATIVE:
break; // OK
@ -557,7 +592,7 @@ bool CreateDir(const Path &path) {
DWORD error = GetLastError();
if (error == ERROR_ALREADY_EXISTS) {
WARN_LOG(Log::Common, "CreateDir: CreateDirectory failed on %s: already exists", path.c_str());
DEBUG_LOG(Log::Common, "CreateDir: CreateDirectory failed on %s: already exists", path.c_str());
return true;
}
ERROR_LOG(Log::Common, "CreateDir: CreateDirectory failed on %s: %08x %s", path.c_str(), (uint32_t)error, GetStringErrorMsg(error).c_str());
@ -569,7 +604,7 @@ bool CreateDir(const Path &path) {
int err = errno;
if (err == EEXIST) {
WARN_LOG(Log::Common, "CreateDir: mkdir failed on %s: already exists", path.c_str());
DEBUG_LOG(Log::Common, "CreateDir: mkdir failed on %s: already exists", path.c_str());
return true;
}
@ -625,6 +660,11 @@ bool CreateFullPath(const Path &path) {
// renames file srcFilename to destFilename, returns true on success
bool Rename(const Path &srcFilename, const Path &destFilename) {
if (SIMULATE_SLOW_IO) {
sleep_ms(100, "slow-io-sim");
INFO_LOG(Log::System, "Rename %s -> %s", srcFilename.c_str(), destFilename.c_str());
}
if (srcFilename.Type() != destFilename.Type()) {
// Impossible. You're gonna need to make a copy, and delete the original. Not the responsibility
// of Rename.
@ -673,6 +713,10 @@ bool Rename(const Path &srcFilename, const Path &destFilename) {
// copies file srcFilename to destFilename, returns true on success
bool Copy(const Path &srcFilename, const Path &destFilename) {
if (SIMULATE_SLOW_IO) {
sleep_ms(100, "slow-io-sim");
INFO_LOG(Log::System, "Copy %s -> %s", srcFilename.c_str(), destFilename.c_str());
}
switch (srcFilename.Type()) {
case PathType::NATIVE:
break; // OK
@ -771,6 +815,10 @@ bool Copy(const Path &srcFilename, const Path &destFilename) {
// Will overwrite the target.
bool Move(const Path &srcFilename, const Path &destFilename) {
if (SIMULATE_SLOW_IO) {
sleep_ms(100, "slow-io-sim");
INFO_LOG(Log::System, "Move %s -> %s", srcFilename.c_str(), destFilename.c_str());
}
bool fast = MoveIfFast(srcFilename, destFilename);
if (fast) {
return true;
@ -809,6 +857,10 @@ bool MoveIfFast(const Path &srcFilename, const Path &destFilename) {
// Returns the size of file (64bit)
// TODO: Add a way to return an error.
uint64_t GetFileSize(const Path &filename) {
if (SIMULATE_SLOW_IO) {
sleep_ms(100, "slow-io-sim");
INFO_LOG(Log::System, "GetFileSize %s", filename.c_str());
}
switch (filename.Type()) {
case PathType::NATIVE:
break; // OK
@ -915,6 +967,10 @@ bool CreateEmptyFile(const Path &filename) {
// Deletes an empty directory, returns true on success
// WARNING: On Android with content URIs, it will delete recursively!
bool DeleteDir(const Path &path) {
if (SIMULATE_SLOW_IO) {
sleep_ms(100, "slow-io-sim");
INFO_LOG(Log::System, "DeleteDir %s", path.c_str());
}
switch (path.Type()) {
case PathType::NATIVE:
break; // OK
@ -1259,7 +1315,7 @@ bool WriteDataToFile(bool text_file, const void* data, size_t size, const Path &
void ChangeMTime(const Path &path, time_t mtime) {
if (path.Type() == PathType::CONTENT_URI) {
// No clue what to do here.
// No clue what to do here. There doesn't seem to be a way.
return;
}

View file

@ -56,6 +56,7 @@ public:
// Filter support is optional but nice to have
virtual bool GetFileInfo(const char *path, File::FileInfo *info) = 0;
virtual std::string toString() const = 0;
};
@ -72,6 +73,12 @@ public:
bool GetFileInfo(const char *filename, File::FileInfo *fileInfo);
bool GetFileListing(const char *path, std::vector<File::FileInfo> *listing, const char *filter = nullptr) override;
// Shortcut for cleaner code
bool Exists(const char *path) {
File::FileInfo info{};
return GetFileInfo(path, &info);
}
private:
struct VFSEntry {
const char *prefix;

View file

@ -52,7 +52,6 @@ private:
bool completed_ = false;
bool failed_ = false;
bool cancelled_ = false;
bool joined_ = false;
// Naett state
naettReq *req_ = nullptr;

View file

@ -53,6 +53,7 @@
#include "Core/ConfigValues.h"
#include "Core/Loaders.h"
#include "Core/KeyMap.h"
#include "Core/System.h"
#include "Core/HLE/sceUtility.h"
#include "Core/Instance.h"
#include "GPU/Common/FramebufferManagerCommon.h"
@ -1679,7 +1680,9 @@ const Path Config::FindConfigFile(const std::string &baseFilename) {
Path parent = filename.NavigateUp();
// We try to create the path and ignore if it fails (already exists).
File::CreateFullPath(parent);
if (parent != GetSysDirectory(DIRECTORY_SYSTEM)) {
File::CreateFullPath(parent);
}
return filename;
}

View file

@ -28,8 +28,6 @@
#include "Core/Core.h"
#include "SasAudio.h"
// #define AUDIO_TO_FILE
static const u8 f[16][2] = {
{ 0, 0 },
{ 60, 0 },
@ -369,9 +367,6 @@ void ADSREnvelope::SetSimpleEnvelope(u32 ADSREnv1, u32 ADSREnv2) {
}
SasInstance::SasInstance() {
#ifdef AUDIO_TO_FILE
audioDump = fopen("D:\\audio.raw", "wb");
#endif
memset(&waveformEffect, 0, sizeof(waveformEffect));
waveformEffect.type = PSP_SAS_EFFECT_TYPE_OFF;
waveformEffect.isDryOn = 1;
@ -660,10 +655,6 @@ void SasInstance::Mix(u32 outAddr, u32 inAddr, int leftVol, int rightVol) {
}
memset(mixBuffer, 0, grainSize * sizeof(int) * 2);
memset(sendBuffer, 0, grainSize * sizeof(int) * 2);
#ifdef AUDIO_TO_FILE
fwrite(Memory::GetPointer(outAddr, grainSize * 2 * 2), 1, grainSize * 2 * 2, audioDump);
#endif
}
void SasInstance::WriteMixedOutput(s16 *outp, const s16 *inp, int leftVol, int rightVol) {

View file

@ -412,6 +412,7 @@ void Arm64JitBackend::CompIR_FCvt(IRInst inst) {
case IRRoundMode::FLOOR_3: rm = RoundingMode::ROUND_M; break;
default:
_assert_msg_(false, "Invalid rounding mode for FCvtScaledWS");
return;
}
// Unfortunately, only Z has a direct scaled instruction.

View file

@ -39,12 +39,7 @@
// Report the time and throughput for each larger scaling operation in the log
//#define SCALING_MEASURE_TIME
//#define DEBUG_SCALER_OUTPUT
#ifdef SCALING_MEASURE_TIME
#include "Common/TimeUtil.h"
#endif
/////////////////////////////////////// Helper Functions (mostly math for parallelization)
@ -549,41 +544,6 @@ void bilinearV(int factor, const u32 *data, u32 *out, int w, int gl, int gu, int
#undef B
#undef A
#ifdef DEBUG_SCALER_OUTPUT
// used for debugging texture scaling (writing textures to files)
static int g_imgCount = 0;
void dbgPPM(int w, int h, u8* pixels, const char* prefix = "dbg") { // 3 component RGB
char fn[32];
snprintf(fn, 32, "%s%04d.ppm", prefix, g_imgCount++);
FILE *fp = fopen(fn, "wb");
fprintf(fp, "P6\n%d %d\n255\n", w, h);
for (int j = 0; j < h; ++j) {
for (int i = 0; i < w; ++i) {
static unsigned char color[3];
color[0] = pixels[(j*w + i) * 4 + 0]; /* red */
color[1] = pixels[(j*w + i) * 4 + 1]; /* green */
color[2] = pixels[(j*w + i) * 4 + 2]; /* blue */
fwrite(color, 1, 3, fp);
}
}
fclose(fp);
}
void dbgPGM(int w, int h, u32* pixels, const char* prefix = "dbg") { // 1 component
char fn[32];
snprintf(fn, 32, "%s%04d.pgm", prefix, g_imgCount++);
FILE *fp = fopen(fn, "wb");
fprintf(fp, "P5\n%d %d\n65536\n", w, h);
for (int j = 0; j < h; ++j) {
for (int i = 0; i < w; ++i) {
fwrite((pixels + (j*w + i)), 1, 2, fp);
}
}
fclose(fp);
}
#endif
}
/////////////////////////////////////// Texture Scaler
@ -723,7 +683,7 @@ void TextureScalerCommon::ScaleHybrid(int factor, u32* source, u32* dest, int wi
// 3) output = A*C + B*(1-C)
const static int KERNEL_SPLAT[3][3] = {
{ 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }
{ 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }
};
bufTmp1.resize(width*height);

View file

@ -246,16 +246,14 @@ void DrawEngineVulkan::DoFlush() {
}
bool useHWTransform = CanUseHardwareTransform(prim) && provokingVertexOk;
uint32_t ibOffset;
uint32_t vbOffset;
// The optimization to avoid indexing isn't really worth it on Vulkan since it means creating more pipelines.
// This could be avoided with the new dynamic state extensions, but not available enough on mobile.
const bool forceIndexed = draw_->GetDeviceCaps().verySlowShaderCompiler;
if (useHWTransform) {
uint32_t vbOffset;
VkBuffer vbuf = VK_NULL_HANDLE;
VkBuffer ibuf = VK_NULL_HANDLE;
if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) {
// If software skinning, we're predecoding into "decoded". So make sure we're done, then push that content.
DecodeVerts(decoded_);
@ -371,9 +369,8 @@ void DrawEngineVulkan::DoFlush() {
baseUBOOffset, lightUBOOffset, boneUBOOffset,
};
if (useElements) {
if (!ibuf) {
ibOffset = (uint32_t)pushIndex_->Push(decIndex_, sizeof(uint16_t) * vertexCount, 4, &ibuf);
}
VkBuffer ibuf;
u32 ibOffset = (uint32_t)pushIndex_->Push(decIndex_, sizeof(uint16_t) * vertexCount, 4, &ibuf);
renderManager->DrawIndexed(descSetIndex, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, vertexCount, 1);
} else {
renderManager->Draw(descSetIndex, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, vertexCount);
@ -537,8 +534,8 @@ void DrawEngineVulkan::DoFlush() {
PROFILE_THIS_SCOPE("renderman_q");
VkBuffer vbuf, ibuf;
vbOffset = (uint32_t)pushVertex_->Push(result.drawBuffer, numDecodedVerts_ * sizeof(TransformedVertex), 4, &vbuf);
ibOffset = (uint32_t)pushIndex_->Push(inds, sizeof(short) * result.drawNumTrans, 4, &ibuf);
u32 vbOffset = (uint32_t)pushVertex_->Push(result.drawBuffer, numDecodedVerts_ * sizeof(TransformedVertex), 4, &vbuf);
u32 ibOffset = (uint32_t)pushIndex_->Push(inds, sizeof(short) * result.drawNumTrans, 4, &ibuf);
renderManager->DrawIndexed(descSetIndex, ARRAY_SIZE(dynamicUBOOffsets), dynamicUBOOffsets, vbuf, vbOffset, ibuf, ibOffset, result.drawNumTrans, 1);
} else if (result.action == SW_CLEAR) {
// Note: we won't get here if the clear is alpha but not color, or color but not alpha.

View file

@ -65,5 +65,4 @@ private:
std::string gameID_;
int fileCheckCounter_ = 0;
uint64_t fileCheckHash_ = 0;
bool enableAllFlag_ = false;
};

View file

@ -1905,7 +1905,7 @@ void DeveloperToolsScreen::CreateViews() {
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()));
framerateMode->SetEnabledFunc([]() { return System_GetPropertyInt(SYSPROP_SYSTEMVERSION) >= 30; });
framerateMode->OnChoice.Add([this](UI::EventParams &e) {
framerateMode->OnChoice.Add([](UI::EventParams &e) {
System_Notify(SystemNotification::FORCE_RECREATE_ACTIVITY);
return UI::EVENT_DONE;
});

View file

@ -533,7 +533,7 @@ void DrawAudioDecodersView(ImConfig &cfg) {
ImGui::TableNextColumn();
ImGui::Text("%d", iter.second->Channels);
ImGui::TableNextColumn();
ImGui::Text("%d", iter.second->startPos);
ImGui::Text("%d", (int)iter.second->startPos);
}
ImGui::EndTable();
}

View file

@ -1509,7 +1509,6 @@ bool MainScreen::DrawBackgroundFor(UIContext &dc, const Path &gamePath, float pr
}
UI::EventReturn MainScreen::OnGameSelected(UI::EventParams &e) {
g_Config.Save("MainScreen::OnGameSelected");
Path path(e.s);
std::shared_ptr<GameInfo> ginfo = g_gameInfoCache->GetInfo(nullptr, path, GameInfoFlags::FILE_TYPE);
if (ginfo->fileType == IdentifiedFileType::PSP_SAVEDATA_DIRECTORY) {
@ -1555,8 +1554,6 @@ UI::EventReturn MainScreen::OnGameHighlight(UI::EventParams &e) {
}
UI::EventReturn MainScreen::OnGameSelectedInstant(UI::EventParams &e) {
// TODO: This is really not necessary here in all cases.
g_Config.Save("MainScreen::OnGameSelectedInstant");
ScreenManager *screen = screenManager();
LaunchFile(screen, Path(e.s));
return UI::EVENT_DONE;

View file

@ -140,14 +140,20 @@ static void LoadThemeInfo(const std::vector<Path> &directories) {
std::string tmpPath;
section.Get("UIAtlas", &tmpPath, "");
if (!tmpPath.empty()) {
tmpPath = (path / tmpPath).ToString();
File::FileInfo tmpInfo;
if (g_VFS.GetFileInfo((tmpPath + ".meta").c_str(), &tmpInfo) && g_VFS.GetFileInfo((tmpPath + ".zim").c_str(), &tmpInfo)) {
info.sUIAtlas = tmpPath;
if (tmpPath == "../ui_atlas") {
// Do nothing.
} else {
// WARNING: Note that the below appears to be entirely broken. ..-navigation doesn't work on zip VFS.
INFO_LOG(Log::System, "Checking %s", tmpPath.c_str());
tmpPath = (path / tmpPath).ToString();
if (g_VFS.Exists((tmpPath + ".meta").c_str()) && g_VFS.Exists((tmpPath + ".zim").c_str())) {
// INFO_LOG(Log::System, "%s exists", tmpPath.c_str());
info.sUIAtlas = tmpPath;
} else {
INFO_LOG(Log::System, "%s.meta/zim doesn't exist, not overriding atlas", tmpPath.c_str());
}
}
}
appendTheme(info);
}
}

View file

@ -37,7 +37,6 @@ private:
Lin::Vec3 down_{};
JoystickHistoryView *tilt_ = nullptr;
GamepadView *gpView_ = nullptr;
};
extern const char *g_tiltTypes[];

View file

@ -838,10 +838,8 @@ static void InitMemstickDirectory() {
// We're screwed anyway if we can't write to Documents, or can't detect it.
if (!File::CreateEmptyFile(testFile))
g_Config.memStickDirectory = myDocsPath;
// Clean up our mess.
if (File::Exists(testFile))
File::Delete(testFile);
File::Delete(testFile);
}
static void WinMainInit() {
@ -954,6 +952,8 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
}
}
// This will be overridden by the actual config. But we do want to log during startup.
g_Config.bEnableLogging = true;
LogManager::Init(&g_Config.bEnableLogging);
// On Win32 it makes more sense to initialize the system directories here
@ -962,7 +962,6 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
InitMemstickDirectory();
CreateSysDirectories();
// Load config up here, because those changes below would be overwritten
// if it's not loaded here first.
g_Config.SetSearchPath(GetSysDirectory(DIRECTORY_SYSTEM));