From 27545462e4b14f77929d9469382299fe2a7510e1 Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Tue, 1 Nov 2016 17:45:37 -0700 Subject: [PATCH] Qt: Memory viewer now supports load/paste --- CHANGES | 1 + src/platform/qt/MemoryModel.cpp | 93 +++++++++++++++++++++++++++++---- src/platform/qt/MemoryModel.h | 5 +- 3 files changed, 89 insertions(+), 10 deletions(-) diff --git a/CHANGES b/CHANGES index 8286b8219..f8d11203f 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,7 @@ Features: - GB: Tile viewer - Sprite viewer - Debugging console + - Improved memory viewer Bugfixes: - LR35902: Fix core never exiting with certain event patterns - GB Timer: Improve DIV reset behavior diff --git a/src/platform/qt/MemoryModel.cpp b/src/platform/qt/MemoryModel.cpp index 5371c27bf..d38c08e9c 100644 --- a/src/platform/qt/MemoryModel.cpp +++ b/src/platform/qt/MemoryModel.cpp @@ -56,6 +56,16 @@ MemoryModel::MemoryModel(QWidget* parent) connect(save, SIGNAL(triggered()), this, SLOT(save())); addAction(save); + QAction* paste = new QAction(tr("Paste"), this); + paste->setShortcut(QKeySequence::Paste); + connect(paste, SIGNAL(triggered()), this, SLOT(paste())); + addAction(paste); + + QAction* load = new QAction(tr("Load"), this); + load->setShortcut(QKeySequence::Open); + connect(load, SIGNAL(triggered()), this, SLOT(load())); + addAction(load); + static QString arg("%0"); for (int i = 0; i < 256; ++i) { QStaticText str(arg.arg(i, 2, 16, QChar('0')).toUpper()); @@ -144,9 +154,7 @@ void MemoryModel::copy() { if (!clipboard) { return; } - QByteArray bytestring; - QDataStream stream(&bytestring, QIODevice::WriteOnly); - serialize(&stream); + QByteArray bytestring(serialize()); QString string; string.reserve(bytestring.size() * 2); static QString arg("%0"); @@ -157,6 +165,20 @@ void MemoryModel::copy() { clipboard->setText(string); } +void MemoryModel::paste() { + QClipboard* clipboard = QApplication::clipboard(); + if (!clipboard) { + return; + } + QString string = clipboard->text(); + if (string.isEmpty()) { + return; + } + QByteArray bytestring(QByteArray::fromHex(string.toLocal8Bit())); + deserialize(bytestring); + viewport()->update(); +} + void MemoryModel::save() { QString filename = GBAApp::app()->getSaveFileName(this, tr("Save selected memory")); if (filename.isNull()) { @@ -167,25 +189,78 @@ void MemoryModel::save() { LOG(QT, WARN) << tr("Failed to open output file: %1").arg(filename); return; } - QDataStream stream(&outfile); - serialize(&stream); + QByteArray out(serialize()); + outfile.write(out); } -void MemoryModel::serialize(QDataStream* stream) { +void MemoryModel::load() { + QString filename = GBAApp::app()->getOpenFileName(this, tr("Load memory")); + if (filename.isNull()) { + return; + } + QFile infile(filename); + if (!infile.open(QIODevice::ReadOnly)) { + LOG(QT, WARN) << tr("Failed to open input file: %1").arg(filename); + return; + } + QByteArray bytestring(infile.readAll()); + deserialize(bytestring); + viewport()->update(); +} + +QByteArray MemoryModel::serialize() { + QByteArray bytes; + bytes.reserve(m_selection.second - m_selection.first); switch (m_align) { case 1: for (uint32_t i = m_selection.first; i < m_selection.second; i += m_align) { - *stream << m_core->rawRead8(m_core, i, m_currentBank); + char datum = m_core->rawRead8(m_core, i, m_currentBank); + bytes.append(datum); } break; case 2: for (uint32_t i = m_selection.first; i < m_selection.second; i += m_align) { - *stream << m_core->rawRead16(m_core, i, m_currentBank); + quint16 datum = m_core->rawRead16(m_core, i, m_currentBank); + char leDatum[2]; + STORE_16LE(datum, 0, (uint16_t*) leDatum); + bytes.append(leDatum, 2); } break; case 4: for (uint32_t i = m_selection.first; i < m_selection.second; i += m_align) { - *stream << m_core->rawRead32(m_core, i, m_currentBank); + quint32 datum = m_core->rawRead32(m_core, i, m_currentBank); + char leDatum[4]; + STORE_32LE(datum, 0, (uint16_t*) leDatum); + bytes.append(leDatum, 4); + } + break; + } + return bytes; +} + +void MemoryModel::deserialize(const QByteArray& bytes) { + uint32_t addr = m_selection.first; + switch (m_align) { + case 1: + for (int i = 0; i < bytes.size(); i += m_align, addr += m_align) { + uint8_t datum = bytes[i]; + m_core->rawWrite8(m_core, addr, m_currentBank, datum); + } + break; + case 2: + for (int i = 0; i < bytes.size(); i += m_align, addr += m_align) { + char leDatum[2]{ bytes[i], bytes[i + 1] }; + uint16_t datum; + LOAD_16LE(datum, 0, leDatum); + m_core->rawWrite16(m_core, addr, m_currentBank, datum); + } + break; + case 4: + for (int i = 0; i < bytes.size(); i += m_align, addr += m_align) { + char leDatum[4]{ bytes[i], bytes[i + 1], bytes[i + 2], bytes[i + 3] }; + uint32_t datum; + LOAD_32LE(datum, 0, leDatum); + m_core->rawWrite32(m_core, addr, m_currentBank, datum); } break; } diff --git a/src/platform/qt/MemoryModel.h b/src/platform/qt/MemoryModel.h index 2ade84c77..f1f46f406 100644 --- a/src/platform/qt/MemoryModel.h +++ b/src/platform/qt/MemoryModel.h @@ -37,7 +37,9 @@ public slots: void jumpToAddress(uint32_t); void copy(); + void paste(); void save(); + void load(); signals: void selectionChanged(uint32_t start, uint32_t end); @@ -59,7 +61,8 @@ private: void adjustCursor(int adjust, bool shift); - void serialize(QDataStream* stream); + QByteArray serialize(); + void deserialize(const QByteArray&); mCore* m_core; QFont m_font;