1 #ifndef EMUTHREAD_H
2 #define EMUTHREAD_H
3 
4 #include "../../core/debug/debug.h"
5 #include "../../core/emu.h"
6 #include "../../core/link.h"
7 
8 #include <QtCore/QMutex>
9 #include <QtCore/QQueue>
10 #include <QtCore/QSemaphore>
11 #include <QtCore/QThread>
12 #include <QtCore/QTimer>
13 
14 #include <chrono>
15 #include <condition_variable>
16 
17 #define CONSOLE_BUFFER_SIZE 512
18 
19 class EmuThread : public QThread {
20     Q_OBJECT
21 
22 public:
23     explicit EmuThread(QObject *parent = Q_NULLPTR);
24     void stop();
25     void reset();
26     void resume();
27     void receive();
28     void unblock();
29     void debug(bool);
30     void doStuff();
31     void throttleWait();
32     void setSpeed(int value);
33     void setThrottle(bool state);
34     void writeConsole(int console, const char *format, va_list args);
35     void debugOpen(int reason, uint32_t addr);
36     void save(emu_data_t type, const QString &path);
37     void setRam(const QString &path);
38     void load(emu_data_t type, const QString &path);
39     void test(const QString &config, bool run);
40 
41     enum {
42         ConsoleNorm,
43         ConsoleErr,
44         ConsoleMax
45     };
46     enum {
47         RequestNone,
48         RequestPause,
49         RequestReset,
50         RequestSave,
51         RequestLoad,
52         RequestSend,
53         RequestReceive,
54         RequestAutoTester,
55         RequestDebugger
56     };
57 
58     int type = ConsoleNorm;
59     int writePos = 0;
60     int readPos = 0;
61     char buffer[CONSOLE_BUFFER_SIZE];
62     QSemaphore write;
63     QSemaphore read;
64 
65 signals:
66     // console
67     void consoleStr();
68     void consoleClear();
69 
70     // debug
71     void debugDisable();
72     void debugCommand(int reason, uint32_t addr);
73 
74     // speed
75     void sendSpeed(int value);
76 
77     // state
78     void tested(int status);
79     void saved(bool success);
80     void loaded(emu_state_t state, emu_data_t type);
81     void blocked(int req);
82     void sentFile(const QString &file, int ok);
83 
84 public slots:
85     void send(const QStringList &names, int location);
86     void enqueueKeys(quint16 key1, quint16 key2 = 0, bool repeat = false);
87 
88 protected:
89     virtual void run() Q_DECL_OVERRIDE;
90 
91 private:
92 
sendFiles()93     void sendFiles() {
94         for (const QString &f : m_vars) {
95             emit sentFile(f, emu_send_variable(f.toUtf8(), m_sendLoc));
96         }
97         emit sentFile(QString(), LINK_GOOD);
98     }
99 
req(int req)100     void req(int req) {
101         m_reqQueue.enqueue(req);
102     }
103 
block(int status)104     void block(int status) {
105         std::unique_lock<std::mutex> lock(m_mutex);
106         emit blocked(status);
107         m_cv.wait(lock);
108     }
109 
110     QQueue<int> m_reqQueue;
111     emu_data_t m_saveType;
112     emu_data_t m_loadType;
113 
114     int m_speed, m_actualSpeed;
115     bool m_throttle;
116     std::chrono::steady_clock::time_point m_lastTime;
117     std::mutex m_mutexSpeed;
118     std::condition_variable m_cvSpeed;
119 
120     bool m_debug; // protected by m_mutexDebug
121 
122     QString m_autotesterPath;
123     bool m_autotesterRun;
124 
125     QString m_savePath;
126     QString m_loadPath;
127     QStringList m_vars;
128     int m_sendLoc;
129 
130     std::mutex m_mutex;
131     std::condition_variable m_cv;
132     std::mutex m_mutexDebug;
133     std::condition_variable m_cvDebug; // protected by m_mutexDebug
134 
135     QQueue<quint16> m_keyQueue;
136     QMutex m_keyQueueMutex;
137 };
138 
139 #endif
140