LCOV - code coverage report
Current view: top level - source/ps - Util.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 7 89 7.9 %
Date: 2023-01-19 00:18:29 Functions: 3 10 30.0 %

          Line data    Source code
       1             : /* Copyright (C) 2022 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       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.
       8             :  *
       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.
      13             :  *
      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/>.
      16             :  */
      17             : 
      18             : #include "precompiled.h"
      19             : 
      20             : #include "ps/Util.h"
      21             : 
      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"
      38             : 
      39             : #if CONFIG2_AUDIO
      40             : #include "soundmanager/SoundManager.h"
      41             : #endif
      42             : 
      43             : #include <iomanip>
      44             : #include <sstream>
      45             : 
      46           0 : void WriteSystemInfo()
      47             : {
      48           0 :     TIMER(L"write_sys_info");
      49             :     struct utsname un;
      50           0 :     uname(&un);
      51             : 
      52           0 :     OsPath pathname = psLogDir()/"system_info.txt";
      53           0 :     FILE* f = sys_OpenFile(pathname, "w");
      54           0 :     if(!f)
      55           0 :         return;
      56             : 
      57             :     // current timestamp (redundant WRT OS timestamp, but that is not
      58             :     // visible when people are posting this file's contents online)
      59             :     {
      60           0 :     wchar_t timestampBuf[100] = {'\0'};
      61             :     time_t seconds;
      62           0 :     time(&seconds);
      63           0 :     struct tm* t = gmtime(&seconds);
      64           0 :     const size_t charsWritten = wcsftime(timestampBuf, ARRAY_SIZE(timestampBuf), L"(generated %Y-%m-%d %H:%M:%S UTC)", t);
      65           0 :     ENSURE(charsWritten != 0);
      66           0 :     fprintf(f, "%ls\n\n", timestampBuf);
      67             :     }
      68             : 
      69             :     // OS
      70           0 :     fprintf(f, "OS             : %s %s (%s)\n", un.sysname, un.release, un.version);
      71             : 
      72             :     // CPU
      73           0 :     fprintf(f, "CPU            : %s, %s", un.machine, cpu_IdentifierString());
      74           0 :     double cpuClock = os_cpu_ClockFrequency();  // query OS (may fail)
      75             : #if ARCH_X86_X64
      76           0 :     if(cpuClock <= 0.0)
      77           0 :         cpuClock = x86_x64::ClockFrequency();   // measure (takes a few ms)
      78             : #endif
      79           0 :     if(cpuClock > 0.0)
      80             :     {
      81           0 :         if(cpuClock < 1e9)
      82           0 :             fprintf(f, ", %.2f MHz\n", cpuClock*1e-6);
      83             :         else
      84           0 :             fprintf(f, ", %.2f GHz\n", cpuClock*1e-9);
      85             :     }
      86             :     else
      87           0 :         fprintf(f, "\n");
      88             : 
      89             :     // memory
      90           0 :     fprintf(f, "Memory         : %u MiB; %u MiB free\n", (unsigned)os_cpu_MemorySize(), (unsigned)os_cpu_MemoryAvailable());
      91             : 
      92             :     // graphics
      93           0 :     fprintf(f, "Video Card     : %s\n", g_VideoMode.GetBackendDevice()->GetName().c_str());
      94           0 :     fprintf(f, "Video Driver   : %s\n", g_VideoMode.GetBackendDevice()->GetDriverInformation().c_str());
      95           0 :     fprintf(f, "Video Mode     : %dx%d:%d\n", g_VideoMode.GetXRes(), g_VideoMode.GetYRes(), g_VideoMode.GetBPP());
      96             : 
      97             : #if CONFIG2_AUDIO
      98           0 :     if (g_SoundManager)
      99             :     {
     100           0 :         fprintf(f, "Sound Card     : %s\n", g_SoundManager->GetSoundCardNames().c_str());
     101           0 :         fprintf(f, "Sound Drivers  : %s\n", g_SoundManager->GetOpenALVersion().c_str());
     102             :     }
     103           0 :     else if(g_DisableAudio)
     104           0 :         fprintf(f, "Sound          : Game was ran without audio\n");
     105             :     else
     106           0 :         fprintf(f, "Sound          : No audio device was found\n");
     107             : #else
     108             :     fprintf(f, "Sound          : Game was compiled without audio\n");
     109             : #endif
     110             : 
     111             :     // OpenGL extensions (write them last, since it's a lot of text)
     112           0 :     fprintf(f, "\nBackend Extensions:\n");
     113           0 :     if (g_VideoMode.GetBackendDevice()->GetExtensions().empty())
     114           0 :         fprintf(f, "{unknown}\n");
     115             :     else
     116           0 :         for (const std::string& extension : g_VideoMode.GetBackendDevice()->GetExtensions())
     117           0 :             fprintf(f, "%s\n", extension.c_str());
     118             : 
     119             :     // System Management BIOS (even more text than OpenGL extensions)
     120           0 :     std::string smbios = SMBIOS::StringizeStructures(SMBIOS::GetStructures());
     121           0 :     fprintf(f, "\nSMBIOS: \n%s\n", smbios.c_str());
     122             : 
     123           0 :     fclose(f);
     124           0 :     f = 0;
     125             : 
     126           0 :     debug_printf("FILES| Hardware details written to '%s'\n", pathname.string8().c_str());
     127             : }
     128             : 
     129             : 
     130             : // not thread-safe!
     131           0 : static const wchar_t* HardcodedErrorString(int err)
     132             : {
     133             :     static wchar_t description[200];
     134           0 :     StatusDescription((Status)err, description, ARRAY_SIZE(description));
     135           0 :     return description;
     136             : }
     137             : 
     138             : // not thread-safe!
     139           0 : const wchar_t* ErrorString(int err)
     140             : {
     141             :     // language file not available (yet)
     142           0 :     return HardcodedErrorString(err);
     143             : 
     144             :     // TODO: load from language file
     145             : }
     146             : 
     147           0 : CStr GetStatusAsString(Status status)
     148             : {
     149           0 :     return utf8_from_wstring(ErrorString(status));
     150             : }
     151             : 
     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           0 : Status tex_write(Tex* t, const VfsPath& filename)
     156             : {
     157             :     DynArray da;
     158           0 :     RETURN_STATUS_IF_ERR(t->encode(filename.Extension(), &da));
     159             : 
     160             :     // write to disk
     161           0 :     Status ret = INFO::OK;
     162             :     {
     163           0 :         std::shared_ptr<u8> file = DummySharedPtr(da.base);
     164           0 :         const ssize_t bytes_written = g_VFS->CreateFile(filename, file, da.pos);
     165           0 :         if(bytes_written > 0)
     166           0 :             ENSURE(bytes_written == (ssize_t)da.pos);
     167             :         else
     168           0 :             ret = (Status)bytes_written;
     169             :     }
     170             : 
     171           0 :     ignore_result(da_free(&da));
     172           0 :     return ret;
     173             : }
     174             : 
     175             : /**
     176             :  * Return an unused directory, based on date and index (for example 2016-02-09_0001)
     177             :  */
     178           0 : OsPath createDateIndexSubdirectory(const OsPath& parentDir)
     179             : {
     180           0 :     const std::time_t timestamp = std::time(nullptr);
     181           0 :     const struct std::tm* now = std::localtime(&timestamp);
     182             : 
     183             :     // Two processes executing this simultaneously might attempt to create the same directory.
     184           0 :     int tries = 0;
     185           0 :     const int maxTries = 10;
     186             : 
     187           0 :     int i = 0;
     188           0 :     OsPath path;
     189             :     char directory[256];
     190             : 
     191           0 :     do
     192             :     {
     193           0 :         sprintf(directory, "%04d-%02d-%02d_%04d", now->tm_year+1900, now->tm_mon+1, now->tm_mday, ++i);
     194           0 :         path = parentDir / CStr(directory);
     195             : 
     196           0 :         if (DirectoryExists(path) || FileExists(path))
     197           0 :             continue;
     198             : 
     199           0 :         if (CreateDirectories(path, 0700, ++tries > maxTries) == INFO::OK)
     200           0 :             break;
     201             : 
     202           0 :     } while(tries <= maxTries);
     203             : 
     204           0 :     return path;
     205             : }
     206             : 
     207           0 : std::string Hexify(const std::string& s)
     208             : {
     209           0 :     std::stringstream str;
     210           0 :     str << std::hex;
     211           0 :     for (const char& c : s)
     212           0 :         str << std::setfill('0') << std::setw(2) << static_cast<int>(static_cast<unsigned char>(c));
     213           0 :     return str.str();
     214             : }
     215             : 
     216         495 : std::string Hexify(const u8* s, size_t length)
     217             : {
     218         990 :     std::stringstream str;
     219         495 :     str << std::hex;
     220        5591 :     for (size_t i = 0; i < length; ++i)
     221        5096 :         str << std::setfill('0') << std::setw(2) << static_cast<int>(s[i]);
     222         990 :     return str.str();
     223           3 : }

Generated by: LCOV version 1.13