Civ backgrounds for minimap
[0ad.git] / source / ps / Util.cpp
blob02bdf0c0fde7f42e319214018f43715e58f60a42
1 /* Copyright (C) 2022 Wildfire Games.
2 * This file is part of 0 A.D.
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
18 #include "precompiled.h"
20 #include "ps/Util.h"
22 #include "graphics/GameView.h"
23 #include "lib/allocators/shared_ptr.h"
24 #include "lib/posix/posix_utsname.h"
25 #include "lib/sysdep/cpu.h"
26 #include "lib/sysdep/os_cpu.h"
27 #include "lib/sysdep/smbios.h"
28 #include "lib/sysdep/sysdep.h" // sys_OpenFile
29 #include "lib/tex/tex.h"
30 #include "lib/timer.h"
31 #include "ps/CLogger.h"
32 #include "ps/Filesystem.h"
33 #include "ps/GameSetup/Config.h"
34 #include "ps/GameSetup/GameSetup.h"
35 #include "ps/Pyrogenesis.h"
36 #include "ps/VideoMode.h"
37 #include "renderer/backend/IDevice.h"
39 #if CONFIG2_AUDIO
40 #include "soundmanager/SoundManager.h"
41 #endif
43 #include <iomanip>
44 #include <sstream>
46 void WriteSystemInfo()
48 TIMER(L"write_sys_info");
49 struct utsname un;
50 uname(&un);
52 OsPath pathname = psLogDir()/"system_info.txt";
53 FILE* f = sys_OpenFile(pathname, "w");
54 if(!f)
55 return;
57 // current timestamp (redundant WRT OS timestamp, but that is not
58 // visible when people are posting this file's contents online)
60 wchar_t timestampBuf[100] = {'\0'};
61 time_t seconds;
62 time(&seconds);
63 struct tm* t = gmtime(&seconds);
64 const size_t charsWritten = wcsftime(timestampBuf, ARRAY_SIZE(timestampBuf), L"(generated %Y-%m-%d %H:%M:%S UTC)", t);
65 ENSURE(charsWritten != 0);
66 fprintf(f, "%ls\n\n", timestampBuf);
69 // OS
70 fprintf(f, "OS : %s %s (%s)\n", un.sysname, un.release, un.version);
72 // CPU
73 fprintf(f, "CPU : %s, %s", un.machine, cpu_IdentifierString());
74 double cpuClock = os_cpu_ClockFrequency(); // query OS (may fail)
75 #if ARCH_X86_X64
76 if(cpuClock <= 0.0)
77 cpuClock = x86_x64::ClockFrequency(); // measure (takes a few ms)
78 #endif
79 if(cpuClock > 0.0)
81 if(cpuClock < 1e9)
82 fprintf(f, ", %.2f MHz\n", cpuClock*1e-6);
83 else
84 fprintf(f, ", %.2f GHz\n", cpuClock*1e-9);
86 else
87 fprintf(f, "\n");
89 // memory
90 fprintf(f, "Memory : %u MiB; %u MiB free\n", (unsigned)os_cpu_MemorySize(), (unsigned)os_cpu_MemoryAvailable());
92 // graphics
93 fprintf(f, "Video Card : %s\n", g_VideoMode.GetBackendDevice()->GetName().c_str());
94 fprintf(f, "Video Driver : %s\n", g_VideoMode.GetBackendDevice()->GetDriverInformation().c_str());
95 fprintf(f, "Video Mode : %dx%d:%d\n", g_VideoMode.GetXRes(), g_VideoMode.GetYRes(), g_VideoMode.GetBPP());
97 #if CONFIG2_AUDIO
98 if (g_SoundManager)
100 fprintf(f, "Sound Card : %s\n", g_SoundManager->GetSoundCardNames().c_str());
101 fprintf(f, "Sound Drivers : %s\n", g_SoundManager->GetOpenALVersion().c_str());
103 else if(g_DisableAudio)
104 fprintf(f, "Sound : Game was ran without audio\n");
105 else
106 fprintf(f, "Sound : No audio device was found\n");
107 #else
108 fprintf(f, "Sound : Game was compiled without audio\n");
109 #endif
111 // OpenGL extensions (write them last, since it's a lot of text)
112 fprintf(f, "\nBackend Extensions:\n");
113 if (g_VideoMode.GetBackendDevice()->GetExtensions().empty())
114 fprintf(f, "{unknown}\n");
115 else
116 for (const std::string& extension : g_VideoMode.GetBackendDevice()->GetExtensions())
117 fprintf(f, "%s\n", extension.c_str());
119 // System Management BIOS (even more text than OpenGL extensions)
120 std::string smbios = SMBIOS::StringizeStructures(SMBIOS::GetStructures());
121 fprintf(f, "\nSMBIOS: \n%s\n", smbios.c_str());
123 fclose(f);
124 f = 0;
126 debug_printf("FILES| Hardware details written to '%s'\n", pathname.string8().c_str());
130 // not thread-safe!
131 static const wchar_t* HardcodedErrorString(int err)
133 static wchar_t description[200];
134 StatusDescription((Status)err, description, ARRAY_SIZE(description));
135 return description;
138 // not thread-safe!
139 const wchar_t* ErrorString(int err)
141 // language file not available (yet)
142 return HardcodedErrorString(err);
144 // TODO: load from language file
147 CStr GetStatusAsString(Status status)
149 return utf8_from_wstring(ErrorString(status));
152 // write the specified texture to disk.
153 // note: <t> cannot be made const because the image may have to be
154 // transformed to write it out in the format determined by <fn>'s extension.
155 Status tex_write(Tex* t, const VfsPath& filename)
157 DynArray da;
158 RETURN_STATUS_IF_ERR(t->encode(filename.Extension(), &da));
160 // write to disk
161 Status ret = INFO::OK;
163 std::shared_ptr<u8> file = DummySharedPtr(da.base);
164 const ssize_t bytes_written = g_VFS->CreateFile(filename, file, da.pos);
165 if(bytes_written > 0)
166 ENSURE(bytes_written == (ssize_t)da.pos);
167 else
168 ret = (Status)bytes_written;
171 ignore_result(da_free(&da));
172 return ret;
176 * Return an unused directory, based on date and index (for example 2016-02-09_0001)
178 OsPath createDateIndexSubdirectory(const OsPath& parentDir)
180 const std::time_t timestamp = std::time(nullptr);
181 const struct std::tm* now = std::localtime(&timestamp);
183 // Two processes executing this simultaneously might attempt to create the same directory.
184 int tries = 0;
185 const int maxTries = 10;
187 int i = 0;
188 OsPath path;
189 char directory[256];
193 sprintf(directory, "%04d-%02d-%02d_%04d", now->tm_year+1900, now->tm_mon+1, now->tm_mday, ++i);
194 path = parentDir / CStr(directory);
196 if (DirectoryExists(path) || FileExists(path))
197 continue;
199 if (CreateDirectories(path, 0700, ++tries > maxTries) == INFO::OK)
200 break;
202 } while(tries <= maxTries);
204 return path;
207 std::string Hexify(const std::string& s)
209 std::stringstream str;
210 str << std::hex;
211 for (const char& c : s)
212 str << std::setfill('0') << std::setw(2) << static_cast<int>(static_cast<unsigned char>(c));
213 return str.str();
216 std::string Hexify(const u8* s, size_t length)
218 std::stringstream str;
219 str << std::hex;
220 for (size_t i = 0; i < length; ++i)
221 str << std::setfill('0') << std::setw(2) << static_cast<int>(s[i]);
222 return str.str();