all repos — mgba @ a5890bfea5dfdb956d3464d0b6c4076e963dffab

mGBA Game Boy Advance Emulator

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#include <QThread>
 12
 13#include <mgba/internal/debugger/cli-debugger.h>
 14
 15using namespace QGBA;
 16
 17DebuggerConsoleController::DebuggerConsoleController(QObject* parent)
 18	: DebuggerController(&m_cliDebugger.d, parent)
 19{
 20	m_backend.d.printf = printf;
 21	m_backend.d.init = init;
 22	m_backend.d.deinit = deinit;
 23	m_backend.d.readline = readLine;
 24	m_backend.d.lineAppend = lineAppend;
 25	m_backend.d.historyLast = historyLast;
 26	m_backend.d.historyAppend = historyAppend;
 27	m_backend.self = this;
 28
 29	CLIDebuggerCreate(&m_cliDebugger);
 30	CLIDebuggerAttachBackend(&m_cliDebugger, &m_backend.d);
 31}
 32
 33void DebuggerConsoleController::enterLine(const QString& line) {
 34	CoreController::Interrupter interrupter(m_gameController);
 35	QMutexLocker lock(&m_mutex);
 36	m_lines.append(line);
 37	if (m_cliDebugger.d.state == DEBUGGER_RUNNING) {
 38		mDebuggerEnter(&m_cliDebugger.d, DEBUGGER_ENTER_MANUAL, nullptr);
 39	}
 40	m_cond.wakeOne();
 41}
 42
 43void DebuggerConsoleController::detach() {
 44	{
 45		CoreController::Interrupter interrupter(m_gameController);
 46		QMutexLocker lock(&m_mutex);
 47		if (m_cliDebugger.d.state != DEBUGGER_SHUTDOWN) {
 48			m_lines.append(QString());
 49			m_cond.wakeOne();
 50		}
 51	}
 52	DebuggerController::detach();
 53}
 54
 55void DebuggerConsoleController::attachInternal() {
 56	CoreController::Interrupter interrupter(m_gameController);
 57	QMutexLocker lock(&m_mutex);
 58	m_history.clear();
 59	mCore* core = m_gameController->thread()->core;
 60	CLIDebuggerAttachBackend(&m_cliDebugger, &m_backend.d);
 61	CLIDebuggerAttachSystem(&m_cliDebugger, core->cliDebuggerSystem(core));
 62}
 63
 64void DebuggerConsoleController::printf(struct CLIDebuggerBackend* be, const char* fmt, ...) {
 65	Backend* consoleBe = reinterpret_cast<Backend*>(be);
 66	DebuggerConsoleController* self = consoleBe->self;
 67	va_list args;
 68	va_start(args, fmt);
 69	self->log(QString().vsprintf(fmt, args));
 70	va_end(args);
 71}
 72
 73void DebuggerConsoleController::init(struct CLIDebuggerBackend* be) {
 74	Backend* consoleBe = reinterpret_cast<Backend*>(be);
 75	DebuggerConsoleController* self = consoleBe->self;
 76	UNUSED(self);
 77}
 78
 79void DebuggerConsoleController::deinit(struct CLIDebuggerBackend* be) {
 80	Backend* consoleBe = reinterpret_cast<Backend*>(be);
 81	DebuggerConsoleController* self = consoleBe->self;
 82	if (QThread::currentThread() == self->thread() && be->p->d.state != DEBUGGER_SHUTDOWN) {
 83		self->m_lines.append(QString());
 84		self->m_cond.wakeOne();
 85	}
 86}
 87
 88const char* DebuggerConsoleController::readLine(struct CLIDebuggerBackend* be, size_t* len) {
 89	Backend* consoleBe = reinterpret_cast<Backend*>(be);
 90	DebuggerConsoleController* self = consoleBe->self;
 91	CoreController::Interrupter interrupter(self->m_gameController);
 92	QMutexLocker lock(&self->m_mutex);
 93	while (self->m_lines.isEmpty()) {
 94		self->m_cond.wait(&self->m_mutex);
 95	}
 96	QString last = self->m_lines.takeFirst();
 97	if (last.isNull()) {
 98		return nullptr;
 99	}
100	self->m_last = last.toUtf8();
101	*len = self->m_last.size();
102	return self->m_last.constData();
103
104}
105
106void DebuggerConsoleController::lineAppend(struct CLIDebuggerBackend* be, const char* line) {
107	Backend* consoleBe = reinterpret_cast<Backend*>(be);
108	DebuggerConsoleController* self = consoleBe->self;
109	self->lineAppend(QString::fromUtf8(line));
110}
111
112const char* DebuggerConsoleController::historyLast(struct CLIDebuggerBackend* be, size_t* len) {
113	Backend* consoleBe = reinterpret_cast<Backend*>(be);
114	DebuggerConsoleController* self = consoleBe->self;
115	CoreController::Interrupter interrupter(self->m_gameController);
116	QMutexLocker lock(&self->m_mutex);
117	if (self->m_history.isEmpty()) {
118		return "i";
119	}
120	self->m_last = self->m_history.last().toUtf8();
121	*len = self->m_last.size();
122	return self->m_last.constData();
123}
124
125void DebuggerConsoleController::historyAppend(struct CLIDebuggerBackend* be, const char* line) {
126	Backend* consoleBe = reinterpret_cast<Backend*>(be);
127	DebuggerConsoleController* self = consoleBe->self;
128	CoreController::Interrupter interrupter(self->m_gameController);
129	QMutexLocker lock(&self->m_mutex);
130	self->m_history.append(QString::fromUtf8(line));
131}