1 #include "utils.h"
2 #include "ipc.h"
3 #include "debugger/disasm.h"
4 #include "../../core/cpu.h"
5 #include "../../core/os/os.h"
6 #include "tivarslib/TIVarType.h"
7 #include "tivarslib/TypeHandlers/TypeHandlers.h"
8 
9 #include <array>
10 
11 #include <QtCore/QDir>
12 #include <QtCore/QString>
13 #include <QtCore/QTime>
14 #include <QtCore/QCoreApplication>
15 
16 QString execPath;
17 QString configPath;
18 
19 bool guiDebug;
20 bool guiSend;
21 bool guiReceive;
22 bool guiEmuValid = false;
23 bool guiReset = false;
24 
isNotValidHex(const std::string & s)25 bool isNotValidHex(const std::string &s) {
26     return s.find_first_not_of("0123456789ABCDEF") != std::string::npos || s.empty();
27 }
28 
fileExists(const QString & location)29 bool fileExists(const QString &location) {
30     QString path(location);
31     path = QDir::toNativeSeparators(path);
32 
33     if (path.isEmpty()) {
34         return false;
35     }
36 
37     if (FILE *file = fopen_utf8(path.toStdString().c_str(), "r")) {
38         fclose(file);
39         return true;
40     } else {
41         return false;
42     }
43 }
44 
hex2int(const QString & str)45 int hex2int(const QString &str) {
46     return static_cast<int>(strtol(str.toStdString().c_str(), nullptr, 16));
47 }
48 
int2hex(uint32_t a,uint8_t l)49 QString int2hex(uint32_t a, uint8_t l) {
50     return QString::number(a, 16).rightJustified(l, '0', true).toUpper();
51 }
52 
calc_var_content_string(const calc_var_t & var)53 std::string calc_var_content_string(const calc_var_t& var) {
54     tivars::stringFromData_handler_t func;
55     // We need to special case some specific temp-equ variables...
56     if (var.type == CALC_VAR_TYPE_EQU && var.name[0] == '$') {
57         func = &tivars::TH_TempEqu::makeStringFromData;
58     } else {
59         func = tivars::TIVarType::createFromID(static_cast<uint>(var.type)).getHandlers().second;
60     }
61     const options_t opts = (calc_var_is_prog(&var) || var.type == CALC_VAR_TYPE_STRING)
62                             ? options_t({ {"prettify", true} }) : options_t();
63     return func(data_t(var.data, var.data + var.size), opts);
64 }
65 
isRunningInDarkMode()66 bool isRunningInDarkMode() {
67     static bool isDarkMode = false;
68     static bool boolSet = false;
69 
70     if (boolSet) {
71         return isDarkMode;
72     }
73 
74     // TODO: handle other OS' way to know if we're running in dark mode
75 #if defined(Q_OS_MACX) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14
76     {
77         std::array<char, 20> buffer;
78         std::string result;
79         std::unique_ptr<FILE, decltype(&pclose)> pipe(popen("defaults read -g AppleInterfaceStyle", "r"), pclose);
80         while (pipe && fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
81             result += buffer.data();
82         }
83         if (result.back() == '\n') {
84             result.pop_back();
85         }
86         isDarkMode = (result == "Dark");
87     }
88 #endif
89 
90     boolSet = true;
91 
92     return isDarkMode;
93 }
94 
95 
getAddressOfEquate(const std::string & in)96 QString getAddressOfEquate(const std::string &in) {
97     QString value;
98     map_value_t::const_iterator item = disasm.reverse.find(in);
99     if (item != disasm.reverse.end()) {
100         value = int2hex(item->second, 6);
101     } else {
102         uint32_t conv = 0xFFFFFFFFu;
103         if (in == "AF") {
104             conv = cpu.registers.AF;
105         } else if (in == "HL") {
106             conv = cpu.registers.HL;
107         } else if (in == "DE") {
108             conv = cpu.registers.DE;
109         } else if (in == "BC") {
110             conv = cpu.registers.BC;
111         } else if (in == "IX") {
112             conv = cpu.registers.IX;
113         } else if (in == "IY") {
114             conv = cpu.registers.IY;
115         } else if (in == "AF\'") {
116             conv = cpu.registers._AF;
117         } else if (in == "HL\'") {
118             conv = cpu.registers._HL;
119         } else if (in == "DE\'") {
120             conv = cpu.registers._DE;
121         } else if (in == "BC\'") {
122             conv = cpu.registers._BC;
123         } else if (in == "SPL") {
124             conv = cpu.registers.SPL;
125         } else if (in == "SPS") {
126             conv = cpu.registers.SPS;
127         } else if (in == "PC") {
128             conv = cpu.registers.PC;
129         }
130         if (conv != 0xFFFFFFFFu) {
131             value = int2hex(conv, 6);
132         }
133     }
134     return value;
135 }
136 
guiDelay(int ms)137 void guiDelay(int ms) {
138     QTime dt = QTime::currentTime().addMSecs(ms);
139     while (QTime::currentTime() < dt) {
140         qApp->processEvents();
141     }
142 }
143 
sendingROM(QDragEnterEvent * e,bool * value)144 QString sendingROM(QDragEnterEvent *e, bool *value) {
145     QString ret;
146     if (value) { *value = false; }
147     if (e->mimeData()->urls().size() == 1) {
148         ret = e->mimeData()->urls().at(0).toLocalFile();
149         if (ret.endsWith(QStringLiteral("rom"), Qt::CaseInsensitive)) {
150             e->accept();
151             if (value) { *value = true; }
152         }
153     }
154     return ret;
155 }
156 
157 #ifdef Q_OS_WIN
158 #include <windows.h>
159 #include <tchar.h>
160 #include <psapi.h>
checkProc(DWORD processID)161 static bool checkProc(DWORD processID) {
162     QString processName;
163 
164     HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
165 
166     if (hProcess) {
167         HMODULE hMod;
168         DWORD cbNeeded;
169         wchar_t szProcessName[MAX_PATH];
170 
171         if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded)) {
172             if(GetModuleBaseNameW(hProcess, hMod, szProcessName, sizeof(szProcessName)/sizeof(TCHAR)) > 0) {
173                 processName = QString::fromUtf16((unsigned short*)szProcessName);
174             }
175         }
176         CloseHandle(hProcess);
177     }
178 
179     if (!processName.isEmpty()) {
180         return true;
181     }
182 
183     return false;
184 }
185 #else
186 #include <sys/types.h>
187 #include <csignal>
checkProc(pid_t pid)188 static bool checkProc(pid_t pid) {
189     if (!kill(pid, 0)) {
190         return true;
191     }
192     return false;
193 }
194 #endif
195 
isProcRunning(pid_t procID)196 bool isProcRunning(pid_t procID) {
197 #ifdef Q_OS_WIN
198     return checkProc(static_cast<DWORD>(procID));
199 #else
200     return checkProc(procID);
201 #endif
202 }
203 
randomString(const int length)204 QString randomString(const int length) {
205    const QString possibleCharacters(QStringLiteral("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"));
206 
207    QString randomString;
208    for(int i=0; i<length; ++i) {
209        int index = qrand() % possibleCharacters.length();
210        QChar nextChar = possibleCharacters.at(index);
211        randomString.append(nextChar);
212    }
213    return randomString;
214 }
215 
appDir()216 QDir appDir() {
217     QDir appDir = qApp->applicationDirPath();
218 #ifdef Q_OS_MACX
219     appDir.cdUp(); // On macOS, the binary is
220     appDir.cdUp(); // actually 3 levels deep
221     appDir.cdUp(); // in the .app folder
222 #endif
223     return appDir;
224 }
225