Merge pull request #19369 from hrydgard/minor-cleanups

Minor cleanups, add new more precise "sleep" function for Windows
This commit is contained in:
Henrik Rydgård
2024-07-26 18:22:54 +02:00
committed by GitHub
30 changed files with 155 additions and 92 deletions
+17 -5
View File
@@ -5,10 +5,8 @@
<ClInclude Include="Common.h" />
<ClInclude Include="CommonFuncs.h" />
<ClInclude Include="CommonTypes.h" />
<ClInclude Include="ConsoleListener.h" />
<ClInclude Include="CPUDetect.h" />
<ClInclude Include="Log.h" />
<ClInclude Include="Log\LogManager.h" />
<ClInclude Include="MemArena.h" />
<ClInclude Include="MemoryUtil.h" />
<ClInclude Include="StringUtils.h" />
@@ -560,15 +558,20 @@
<ClInclude Include="Render\Text\draw_text_cocoa.h">
<Filter>Render\Text</Filter>
</ClInclude>
<ClInclude Include="Log\StdioListener.h" />
<ClInclude Include="Log\ConsoleListener.h">
<Filter>Log</Filter>
</ClInclude>
<ClInclude Include="Log\LogManager.h">
<Filter>Log</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="ABI.cpp" />
<ClCompile Include="Log\ConsoleListener.cpp" />
<ClCompile Include="Log\StdioListener.cpp" />
<ClCompile Include="CPUDetect.cpp" />
<ClCompile Include="FakeCPUDetect.cpp" />
<ClCompile Include="MipsCPUDetect.cpp" />
<ClCompile Include="Log\LogManager.cpp" />
<ClCompile Include="MemoryUtil.cpp" />
<ClCompile Include="StringUtils.cpp" />
<ClCompile Include="Thunk.cpp" />
@@ -1045,6 +1048,12 @@
<ClCompile Include="..\ext\at3_standalone\compat.cpp">
<Filter>ext\at3_standalone</Filter>
</ClCompile>
<ClCompile Include="Log\ConsoleListener.cpp">
<Filter>Log</Filter>
</ClCompile>
<ClCompile Include="Log\LogManager.cpp">
<Filter>Log</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="Crypto">
@@ -1161,6 +1170,9 @@
<Filter Include="ext\at3_standalone">
<UniqueIdentifier>{586da66e-922a-4479-9dac-9d608a1b9183}</UniqueIdentifier>
</Filter>
<Filter Include="Log">
<UniqueIdentifier>{cb2c7c09-1177-4a1e-962c-5cc7bcb56789}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<Text Include="..\ext\libpng17\CMakeLists.txt">
@@ -1208,4 +1220,4 @@
<Filter>Render\Text</Filter>
</None>
</ItemGroup>
</Project>
</Project>
+1 -1
View File
@@ -62,4 +62,4 @@ void ReportMessage(const char *message, ...);
// The same, but with a preformatted version (message is still the key.)
void ReportMessageFormatted(const char *message, const char *formatted);
}
} // namespace Reporting
+84 -19
View File
@@ -41,20 +41,29 @@ static LARGE_INTEGER frequency;
static double frequencyMult;
static LARGE_INTEGER startTime;
static inline void InitTime() {
if (frequency.QuadPart == 0) {
QueryPerformanceFrequency(&frequency);
QueryPerformanceCounter(&startTime);
frequencyMult = 1.0 / static_cast<double>(frequency.QuadPart);
}
HANDLE Timer;
int SchedulerPeriodMs = 10;
INT64 QpcPerSecond;
void TimeInit() {
QueryPerformanceFrequency(&frequency);
QueryPerformanceCounter(&startTime);
QpcPerSecond = frequency.QuadPart;
frequencyMult = 1.0 / static_cast<double>(frequency.QuadPart);
Timer = CreateWaitableTimerExW(NULL, NULL, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS);
#if !PPSSPP_PLATFORM(UWP)
TIMECAPS caps;
timeGetDevCaps(&caps, sizeof caps);
timeBeginPeriod(caps.wPeriodMin);
SchedulerPeriodMs = (int)caps.wPeriodMin;
#endif
}
double time_now_d() {
InitTime();
LARGE_INTEGER time;
QueryPerformanceCounter(&time);
double elapsed = static_cast<double>(time.QuadPart - startTime.QuadPart);
return elapsed * frequencyMult;
return static_cast<double>(time.QuadPart - startTime.QuadPart) * frequencyMult;
}
// Fake, but usable in a pinch. Don't, though.
@@ -91,24 +100,28 @@ void yield() {
YieldProcessor();
}
TimeSpan::TimeSpan() {
Instant::Instant() {
_dbg_assert_(frequencyMult != 0.0);
QueryPerformanceCounter(reinterpret_cast<LARGE_INTEGER *>(&nativeStart_));
}
double TimeSpan::ElapsedSeconds() const {
double Instant::ElapsedSeconds() const {
LARGE_INTEGER time;
QueryPerformanceCounter(&time);
double elapsed = static_cast<double>(time.QuadPart - nativeStart_);
return elapsed * frequencyMult;
}
int64_t TimeSpan::ElapsedNanos() const {
int64_t Instant::ElapsedNanos() const {
return (int64_t)(ElapsedSeconds() * 1000000000.0);
}
#elif PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(LINUX) || PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS)
void TimeInit() {
// Nothing to do.
}
// The only intended use is to match the timings in VK_GOOGLE_display_timing
uint64_t time_now_raw() {
struct timespec tp;
@@ -149,14 +162,14 @@ void yield() {
#endif
}
TimeSpan::TimeSpan() {
Instant::Instant() {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
nativeStart_ = ts.tv_sec;
nsecs_ = ts.tv_nsec;
}
int64_t TimeSpan::ElapsedNanos() const {
int64_t Instant::ElapsedNanos() const {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
int64_t secs = ts.tv_sec - nativeStart_;
@@ -168,12 +181,16 @@ int64_t TimeSpan::ElapsedNanos() const {
return secs * 1000000000ULL + nsecs;
}
double TimeSpan::ElapsedSeconds() const {
double Instant::ElapsedSeconds() const {
return (double)ElapsedNanos() * (1.0 / nanos);
}
#else
void TimeInit() {
// Nothing to do.
}
static time_t start;
double time_now_d() {
@@ -208,14 +225,14 @@ double time_now_unix_utc() {
return time_now_raw();
}
TimeSpan::TimeSpan() {
Instant::Instant() {
struct timeval tv;
gettimeofday(&tv, nullptr);
nativeStart_ = tv.tv_sec;
nsecs_ = tv.tv_usec;
}
int64_t TimeSpan::ElapsedNanos() const {
int64_t Instant::ElapsedNanos() const {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
@@ -228,8 +245,8 @@ int64_t TimeSpan::ElapsedNanos() const {
return secs * 1000000000 + usecs * 1000;
}
double TimeSpan::ElapsedSeconds() const {
return (double)ElapsedNanos() * (1.0 / 1000000000);
double Instant::ElapsedSeconds() const {
return (double)ElapsedNanos() * (1.0 / 1000000000.0);
}
#endif
@@ -246,6 +263,54 @@ void sleep_ms(int ms) {
#endif
}
// Precise Windows sleep function from: https://github.com/blat-blatnik/Snippets/blob/main/precise_sleep.c
// Described in: https://blog.bearcats.nl/perfect-sleep-function/
void sleep_precise(double seconds) {
#ifdef _WIN32
LARGE_INTEGER qpc;
QueryPerformanceCounter(&qpc);
INT64 targetQpc = (INT64)(qpc.QuadPart + seconds * QpcPerSecond);
if (Timer) { // Try using a high resolution timer first.
const double TOLERANCE = 0.001'02;
INT64 maxTicks = (INT64)SchedulerPeriodMs * 9'500;
for (;;) // Break sleep up into parts that are lower than scheduler period.
{
double remainingSeconds = (targetQpc - qpc.QuadPart) / (double)QpcPerSecond;
INT64 sleepTicks = (INT64)((remainingSeconds - TOLERANCE) * 10'000'000);
if (sleepTicks <= 0)
break;
LARGE_INTEGER due;
due.QuadPart = -(sleepTicks > maxTicks ? maxTicks : sleepTicks);
SetWaitableTimerEx(Timer, &due, 0, NULL, NULL, NULL, 0);
WaitForSingleObject(Timer, INFINITE);
QueryPerformanceCounter(&qpc);
}
} else { // Fallback to Sleep.
const double TOLERANCE = 0.000'02;
double sleepMs = (seconds - TOLERANCE) * 1000 - SchedulerPeriodMs; // Sleep for 1 scheduler period less than requested.
int sleepSlices = (int)(sleepMs / SchedulerPeriodMs);
if (sleepSlices > 0)
Sleep((DWORD)sleepSlices * SchedulerPeriodMs);
QueryPerformanceCounter(&qpc);
}
while (qpc.QuadPart < targetQpc) // Spin for any remaining time.
{
YieldProcessor();
QueryPerformanceCounter(&qpc);
}
#else
#if defined(HAVE_LIBNX)
svcSleepThread((int64_t)(seconds * 1000000000.0));
#elif defined(__EMSCRIPTEN__)
emscripten_sleep(seconds * 1000.0);
#else
usleep(seconds * 1000000.0);
#endif
#endif
}
// Return the current time formatted as Minutes:Seconds:Milliseconds
// in the form 00:00:000.
void GetCurrentTimeFormatted(char formattedTime[13]) {
+8 -14
View File
@@ -1,6 +1,8 @@
#pragma once
#include <cstdint>
void TimeInit();
// Seconds.
double time_now_d();
@@ -18,32 +20,24 @@ double time_now_unix_utc();
// Sleep. Does not necessarily have millisecond granularity, especially on Windows.
void sleep_ms(int ms);
// Precise sleep. Can consume a little bit of CPU on Windows at least.
void sleep_precise(double seconds);
// Yield. Signals that this thread is busy-waiting but wants to allow other hyperthreads to run.
void yield();
void GetCurrentTimeFormatted(char formattedTime[13]);
// Rust-style Instant for clear and easy timing.
// Most accurate timer possible - no extra double conversions. Only for spans.
class Instant {
public:
static Instant Now() {
return Instant(time_now_d());
return Instant();
}
double ElapsedSeconds() const {
return time_now_d() - instantTime_;
}
private:
explicit Instant(double initTime) : instantTime_(initTime) {}
double instantTime_;
};
// Most accurate timer possible - no extra double conversions. Only for spans.
class TimeSpan {
public:
TimeSpan();
double ElapsedSeconds() const;
int64_t ElapsedNanos() const;
private:
Instant();
uint64_t nativeStart_;
#ifndef _WIN32
int64_t nsecs_;
+10
View File
@@ -62,7 +62,17 @@
#include "Common/Serialize/SerializeFuncs.h"
#include "Common/TimeUtil.h"
#include "Core/HLE/sceKernelThread.h"
#include "Core/HLE/sceKernel.h"
#include "Core/HLE/sceKernelMutex.h"
#include "Core/HLE/sceUtility.h"
#include "Core/MemMap.h"
#include "Core/HLE/HLE.h"
#include "Core/HLE/HLEHelperThread.h"
#include "Core/Config.h"
#include "Core/CoreTiming.h"
#include "Core/Core.h"
#include "Core/HLE/sceKernelInterrupt.h"
#include "Core/HLE/sceKernelThread.h"
+1 -5
View File
@@ -39,17 +39,13 @@
#endif
#include <atomic>
#include <climits>
#include <mutex>
#include <thread>
#include <climits>
#include "Common/Net/Resolve.h"
#include "Common/Serialize/Serializer.h"
#include "Core/CoreTiming.h"
#include "Core/MemMap.h"
#include "Core/HLE/HLE.h"
#include "Core/HLE/HLEHelperThread.h"
#include "Core/HLE/sceKernelThread.h"
#include "Core/HLE/sceKernel.h"
#include "Core/HLE/sceKernelMutex.h"
-1
View File
@@ -29,7 +29,6 @@
#include "Core/HLE/HLE.h"
#include "Core/HLE/FunctionWrappers.h"
#include "Core/HW/MediaEngine.h"
#include "Core/Config.h"
#include "Core/MemMapHelpers.h"
#include "Core/Reporting.h"
#include "GPU/GPUInterface.h"
+3 -1
View File
@@ -15,12 +15,14 @@
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include <string> // for some reason required for the 'new'.
#include "Common/Data/Random/Rng.h"
#include "Common/CommonTypes.h"
#include "Core/HLE/HLE.h"
#include "Core/HLE/FunctionWrappers.h"
#include "Core/HLE/sceMt19937.h"
#include "Core/MemMap.h"
#include "Core/Reporting.h"
#ifdef USE_CRT_DBG
#undef new
+2 -3
View File
@@ -22,7 +22,6 @@
#include <fcntl.h>
#endif
#include "Common/Net/Resolve.h"
#include "Common/Data/Text/Parsers.h"
#include "Common/Serialize/Serializer.h"
@@ -34,18 +33,18 @@
#include "Core/MIPS/MIPS.h"
#include "Core/Config.h"
#include "Core/MemMapHelpers.h"
#include "Core/Reporting.h"
#include "Core/Util/PortManager.h"
#include "sceKernel.h"
#include "sceKernelThread.h"
#include "sceKernelMutex.h"
#include "sceUtility.h"
#include "Core/HLE/proAdhoc.h"
#include "Core/HLE/sceNetAdhoc.h"
#include "Core/HLE/sceNet.h"
#include "Core/HLE/sceNp.h"
#include "Core/Reporting.h"
#include "Core/CoreTiming.h"
#include "Core/Instance.h"
#if PPSSPP_PLATFORM(SWITCH) && !defined(INADDR_NONE)
+1
View File
@@ -46,6 +46,7 @@
#include "Core/MIPS/MIPSCodeUtils.h"
#include "Core/Util/PortManager.h"
#include "Core/Config.h"
#include "Core/CoreTiming.h"
#include "Core/Core.h"
#include "Core/Reporting.h"
#include "Core/MemMapHelpers.h"
-12
View File
@@ -35,12 +35,6 @@
#include "Core/ELF/PBPReader.h"
#include "Core/ELF/ParamSFO.h"
static std::map<std::string, std::unique_ptr<FileLoaderFactory>> factories;
void RegisterFileLoaderFactory(const std::string &prefix, std::unique_ptr<FileLoaderFactory> factory) {
factories[prefix] = std::move(factory);
}
FileLoader *ConstructFileLoader(const Path &filename) {
if (filename.Type() == PathType::HTTP) {
FileLoader *baseLoader = new RetryingFileLoader(new HTTPFileLoader(filename));
@@ -50,12 +44,6 @@ FileLoader *ConstructFileLoader(const Path &filename) {
}
return new CachingFileLoader(baseLoader);
}
for (auto &iter : factories) {
if (startsWith(filename.ToString(), iter.first)) {
return iter.second->ConstructFileLoader(filename);
}
}
return new LocalFileLoader(filename);
}
-7
View File
@@ -147,13 +147,6 @@ Path ResolvePBPFile(const Path &filename);
IdentifiedFileType Identify_File(FileLoader *fileLoader, std::string *errorString);
class FileLoaderFactory {
public:
virtual ~FileLoaderFactory() {}
virtual FileLoader *ConstructFileLoader(const Path &filename) = 0;
};
void RegisterFileLoaderFactory(const std::string &prefix, std::unique_ptr<FileLoaderFactory> factory);
// Can modify the string filename, as it calls IdentifyFile above.
bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string);
+1 -1
View File
@@ -200,7 +200,7 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst) {
mips->r[inst->dest] = mips->r[inst->src1] ^ inst->constant;
break;
case IROp::Neg:
mips->r[inst->dest] = -(s32)mips->r[inst->src1];
mips->r[inst->dest] = (u32)(-(s32)mips->r[inst->src1]);
break;
case IROp::Not:
mips->r[inst->dest] = ~mips->r[inst->src1];
+2 -2
View File
@@ -285,9 +285,9 @@ void IRJit::RunLoopUntil(u64 globalticks) {
instPtr++;
#ifdef IR_PROFILING
IRBlock *block = blocks_.GetBlock(blocks_.GetBlockNumFromOffset(offset));
TimeSpan span;
Instant start = Instant::Now();
mips->pc = IRInterpret(mips, instPtr);
int64_t elapsedNanos = span.ElapsedNanos();
int64_t elapsedNanos = start.ElapsedNanos();
block->profileStats_.executions += 1;
block->profileStats_.totalNanos += elapsedNanos;
#else
-2
View File
@@ -45,7 +45,6 @@ MIPSDebugInterface *currentDebugMIPS = &debugr4k;
u8 voffset[128];
u8 fromvoffset[128];
#ifndef M_LOG2E
#define M_E 2.71828182845904523536f
#define M_LOG2E 1.44269504088896340736f
@@ -89,7 +88,6 @@ const float cst_constants[32] = {
sqrtf(3.0f)/2.0f,
};
MIPSState::MIPSState() {
MIPSComp::jit = nullptr;
+1 -3
View File
@@ -219,7 +219,7 @@ public:
};
u32 nextPC;
int downcount; // This really doesn't belong here, it belongs in CoreTiming. But you gotta do what you gotta do, this needs to be reachable in the ARM JIT.
int downcount; // This really doesn't belong here, it belongs in CoreTiming. But you gotta do what you gotta do, this needs to be reachable in the JITs without additional pointers.
bool inDelaySlot;
int llBit; // ll/sc
@@ -261,7 +261,6 @@ public:
int RunLoopUntil(u64 globalTicks);
// To clear jit caches, etc.
void InvalidateICache(u32 address, int length = 4);
void ClearJitCache();
void ProcessPendingClears();
@@ -271,7 +270,6 @@ public:
volatile bool hasPendingClears = false;
};
class MIPSDebugInterface;
//The one we are compiling or running currently
-1
View File
@@ -521,7 +521,6 @@ struct PSPPointer
}
};
constexpr u32 PSP_GetScratchpadMemoryBase() { return 0x00010000;}
constexpr u32 PSP_GetScratchpadMemoryEnd() { return 0x00014000;}
+6 -6
View File
@@ -56,7 +56,7 @@
#include "Core/HLE/sceKernelModule.h"
#include "Core/HLE/sceKernelMemory.h"
static std::thread loadingThread;
static std::thread g_loadingThread;
static void UseLargeMem(int memsize) {
if (memsize != 1) {
@@ -313,7 +313,7 @@ bool Load_PSP_ISO(FileLoader *fileLoader, std::string *error_string) {
// Note: this thread reads the game binary, loads caches, and links HLE while UI spins.
// To do something deterministically when the game starts, disabling this thread won't be enough.
// Instead: Use Core_ListenLifecycle() or watch coreState.
loadingThread = std::thread([bootpath] {
g_loadingThread = std::thread([bootpath] {
SetCurrentThreadName("ExecLoader");
PSP_LoadingLock guard;
if (coreState != CORE_POWERUP)
@@ -474,7 +474,7 @@ bool Load_PSP_ELF_PBP(FileLoader *fileLoader, std::string *error_string) {
PSPLoaders_Shutdown();
// Note: See Load_PSP_ISO for notes about this thread.
loadingThread = std::thread([finalName] {
g_loadingThread = std::thread([finalName] {
SetCurrentThreadName("ExecLoader");
PSP_LoadingLock guard;
if (coreState != CORE_POWERUP)
@@ -500,7 +500,7 @@ bool Load_PSP_GE_Dump(FileLoader *fileLoader, std::string *error_string) {
PSPLoaders_Shutdown();
// Note: See Load_PSP_ISO for notes about this thread.
loadingThread = std::thread([] {
g_loadingThread = std::thread([] {
SetCurrentThreadName("ExecLoader");
PSP_LoadingLock guard;
if (coreState != CORE_POWERUP)
@@ -521,6 +521,6 @@ bool Load_PSP_GE_Dump(FileLoader *fileLoader, std::string *error_string) {
}
void PSPLoaders_Shutdown() {
if (loadingThread.joinable())
loadingThread.join();
if (g_loadingThread.joinable())
g_loadingThread.join();
}
-2
View File
@@ -1,9 +1,7 @@
#pragma once
#include "Common/GPU/ShaderWriter.h"
#include "GPU/ge_constants.h"
#include "GPU/GPUCommon.h"
#include "GPU/Common/Draw2D.h"
Draw2DPipelineInfo GenerateReinterpretFragmentShader(ShaderWriter &writer, GEBufferFormat from, GEBufferFormat to);
-1
View File
@@ -22,7 +22,6 @@
#include "Common/Common.h"
#include "Common/Swap.h"
#include "Core/MemMap.h"
#include "Core/ConfigValues.h"
#include "GPU/ge_constants.h"
#include "GPU/GPUState.h"
-2
View File
@@ -22,12 +22,10 @@
#include <string>
#include "Common/CommonTypes.h"
#include "Common/GPU/Shader.h"
#include "Common/GPU/thin3d.h"
#include "GPU/ge_constants.h"
#include "GPU/Common/Draw2D.h"
#include "GPU/Common/ShaderCommon.h"
#include "GPU/Common/DepalettizeShaderCommon.h"
class ClutTexture {
+4
View File
@@ -45,6 +45,8 @@
#include "Common/Thread/ThreadUtil.h"
#include "Common/Data/Encoding/Utf8.h"
#include "Common/StringUtils.h"
#include "Common/TimeUtil.h"
#include "Core/Config.h"
#include "Core/ConfigValues.h"
#include "Core/HW/Camera.h"
@@ -799,6 +801,8 @@ Q_DECL_EXPORT
#endif
int main(int argc, char *argv[])
{
TimeInit();
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "--version")) {
printf("%s\n", PPSSPP_GIT_VERSION);
+2
View File
@@ -1108,6 +1108,8 @@ int main(int argc, char *argv[]) {
}
}
TimeInit();
#ifdef HAVE_LIBNX
socketInitializeDefault();
nxlinkStdio();
+1
View File
@@ -67,6 +67,7 @@ using namespace std::placeholders;
#if !PPSSPP_PLATFORM(UWP)
#include "GPU/Vulkan/DebugVisVulkan.h"
#endif
#include "Core/MIPS/MIPS.h"
#include "Core/HLE/sceCtrl.h"
#include "Core/HLE/sceSas.h"
#include "Core/Debugger/SymbolMap.h"
+2
View File
@@ -65,6 +65,8 @@ PPSSPP_UWPMain::PPSSPP_UWPMain(App ^app, const std::shared_ptr<DX::DeviceResourc
app_(app),
m_deviceResources(deviceResources)
{
TimeInit();
// Register to be notified if the Device is lost or recreated
m_deviceResources->RegisterDeviceNotify(this);
+2 -3
View File
@@ -887,6 +887,8 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
SetCurrentThreadName("Main");
TimeInit();
WinMainInit();
#ifndef _DEBUG
@@ -1016,9 +1018,6 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
LogManager::GetInstance()->SetAllLogLevels(LogLevel::LDEBUG);
}
// This still seems to improve performance noticeably.
timeBeginPeriod(1);
ContextMenuInit(_hInstance);
MainWindow::Init(_hInstance);
MainWindow::Show(_hInstance);
+2
View File
@@ -294,6 +294,8 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *pjvm, void *reserved) {
"(Ljava/lang/String;)Ljava/lang/Class;");
RegisterAttachDetach(&Android_AttachThreadToJNI, &Android_DetachThreadFromJNI);
TimeInit();
return JNI_VERSION_1_6;
}
+1 -1
View File
@@ -318,9 +318,9 @@ std::vector<std::string> ReadFromListFile(const std::string &listFilename) {
int main(int argc, const char* argv[])
{
PROFILE_INIT();
TimeInit();
#if PPSSPP_PLATFORM(WINDOWS)
SetCleanExitOnAssert();
timeBeginPeriod(1);
#else
// Ignore sigpipe.
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
+2
View File
@@ -1195,6 +1195,8 @@ static const struct retro_controller_info ports[] =
void retro_init(void)
{
TimeInit();
struct retro_log_callback log;
if (environ_cb(RETRO_ENVIRONMENT_GET_LOG_INTERFACE, &log))
{
+2
View File
@@ -60,6 +60,7 @@
#include "Common/System/System.h"
#include "Common/Thread/ThreadUtil.h"
#include "Common/Data/Format/IniFile.h"
#include "Common/TimeUtil.h"
#include "Common/ArmEmitter.h"
#include "Common/BitScan.h"
@@ -1096,6 +1097,7 @@ TestItem availableTests[] = {
int main(int argc, const char *argv[]) {
SetCurrentThreadName("UnitTest");
TimeInit();
printf("CPU name: %s\n", cpu_info.cpu_string);
printf("ABI: %s\n", GetCompilerABI());