src/platform/qt/DebuggerConsoleController.cpp (view raw)
1/* Copyright (c) 2013-2016 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "DebuggerConsoleController.h"
7
8#include "CoreController.h"
9
10#include <QMutexLocker>
11
12#include <mgba/internal/debugger/cli-debugger.h>
13
14using namespace QGBA;
15
16DebuggerConsoleController::DebuggerConsoleController(QObject* parent)
17 : DebuggerController(&m_cliDebugger.d, parent)
18{
19 m_backend.d.printf = printf;
20 m_backend.d.init = init;
21 m_backend.d.deinit = deinit;
22 m_backend.d.readline = readLine;
23 m_backend.d.lineAppend = lineAppend;
24 m_backend.d.historyLast = historyLast;
25 m_backend.d.historyAppend = historyAppend;
26 m_backend.self = this;
27
28 CLIDebuggerCreate(&m_cliDebugger);
29 CLIDebuggerAttachBackend(&m_cliDebugger, &m_backend.d);
30}
31
32void DebuggerConsoleController::enterLine(const QString& line) {
33 QMutexLocker lock(&m_mutex);
34 m_lines.append(line);
35 if (m_cliDebugger.d.state == DEBUGGER_RUNNING) {
36 mDebuggerEnter(&m_cliDebugger.d, DEBUGGER_ENTER_MANUAL, nullptr);
37 }
38 m_cond.wakeOne();
39}
40
41void DebuggerConsoleController::detach() {
42 if (m_cliDebugger.d.state != DEBUGGER_SHUTDOWN) {
43 m_lines.append(QString());
44 m_cond.wakeOne();
45 }
46 DebuggerController::detach();
47}
48
49void DebuggerConsoleController::attachInternal() {
50 m_history.clear();
51 mCore* core = m_gameController->thread()->core;
52 CLIDebuggerAttachBackend(&m_cliDebugger, &m_backend.d);
53 CLIDebuggerAttachSystem(&m_cliDebugger, core->cliDebuggerSystem(core));
54}
55
56void DebuggerConsoleController::printf(struct CLIDebuggerBackend* be, const char* fmt, ...) {
57 Backend* consoleBe = reinterpret_cast<Backend*>(be);
58 DebuggerConsoleController* self = consoleBe->self;
59 va_list args;
60 va_start(args, fmt);
61 self->log(QString().vsprintf(fmt, args));
62 va_end(args);
63}
64
65void DebuggerConsoleController::init(struct CLIDebuggerBackend* be) {
66 Backend* consoleBe = reinterpret_cast<Backend*>(be);
67 DebuggerConsoleController* self = consoleBe->self;
68}
69
70void DebuggerConsoleController::deinit(struct CLIDebuggerBackend* be) {
71 Backend* consoleBe = reinterpret_cast<Backend*>(be);
72 DebuggerConsoleController* self = consoleBe->self;
73 if (be->p->d.state != DEBUGGER_SHUTDOWN) {
74 self->m_lines.append(QString());
75 self->m_cond.wakeOne();
76 }
77}
78
79const char* DebuggerConsoleController::readLine(struct CLIDebuggerBackend* be, size_t* len) {
80 Backend* consoleBe = reinterpret_cast<Backend*>(be);
81 DebuggerConsoleController* self = consoleBe->self;
82 CoreController::Interrupter interrupter(self->m_gameController);
83 QMutexLocker lock(&self->m_mutex);
84 while (self->m_lines.isEmpty()) {
85 self->m_cond.wait(&self->m_mutex);
86 }
87 QString last = self->m_lines.takeFirst();
88 if (last.isNull()) {
89 return nullptr;
90 }
91 self->m_last = last.toUtf8();
92 *len = self->m_last.size();
93 return self->m_last.constData();
94
95}
96
97void DebuggerConsoleController::lineAppend(struct CLIDebuggerBackend* be, const char* line) {
98 Backend* consoleBe = reinterpret_cast<Backend*>(be);
99 DebuggerConsoleController* self = consoleBe->self;
100 self->lineAppend(QString::fromUtf8(line));
101}
102
103const char* DebuggerConsoleController::historyLast(struct CLIDebuggerBackend* be, size_t* len) {
104 Backend* consoleBe = reinterpret_cast<Backend*>(be);
105 DebuggerConsoleController* self = consoleBe->self;
106 CoreController::Interrupter interrupter(self->m_gameController);
107 QMutexLocker lock(&self->m_mutex);
108 if (self->m_history.isEmpty()) {
109 return "i";
110 }
111 self->m_last = self->m_history.last().toUtf8();
112 return self->m_last.constData();
113}
114
115void DebuggerConsoleController::historyAppend(struct CLIDebuggerBackend* be, const char* line) {
116 Backend* consoleBe = reinterpret_cast<Backend*>(be);
117 DebuggerConsoleController* self = consoleBe->self;
118 CoreController::Interrupter interrupter(self->m_gameController);
119 QMutexLocker lock(&self->m_mutex);
120 self->m_history.append(QString::fromUtf8(line));
121}