From a3ee07a6cc20512e3db26d84a23adfa5b8d0f52b Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Tue, 1 Nov 2016 19:27:44 -0700 Subject: [PATCH] Qt: TBL support in Memory Viewer --- src/platform/qt/MemoryModel.cpp | 76 +++++++++++++++++++++++++++++++-- src/platform/qt/MemoryModel.h | 15 +++++++ src/platform/qt/MemoryView.cpp | 10 ++--- src/platform/qt/MemoryView.ui | 7 +++ 4 files changed, 97 insertions(+), 11 deletions(-) diff --git a/src/platform/qt/MemoryModel.cpp b/src/platform/qt/MemoryModel.cpp index d38c08e9c..23dbc6db3 100644 --- a/src/platform/qt/MemoryModel.cpp +++ b/src/platform/qt/MemoryModel.cpp @@ -8,6 +8,7 @@ #include "GBAApp.h" #include "GameController.h" #include "LogController.h" +#include "VFileDevice.h" #include #include @@ -31,6 +32,7 @@ MemoryModel::MemoryModel(QWidget* parent) , m_align(1) , m_selection(0, 0) , m_selectionAnchor(0) + , m_codec(nullptr) { m_font.setFamily("Source Code Pro"); m_font.setStyleHint(QFont::Monospace); @@ -127,6 +129,24 @@ void MemoryModel::setAlignment(int width) { viewport()->update(); } +void MemoryModel::loadTBL(const QString& path) { + VFile* vf = VFileDevice::open(path, O_RDONLY); + if (!vf) { + return; + } + m_codec = std::unique_ptr(new TextCodec); + TextCodecLoadTBL(m_codec.get(), vf, true); + vf->close(vf); +} + +void MemoryModel::loadTBL() { + QString filename = GBAApp::app()->getOpenFileName(this, tr("Load TBL")); + if (filename.isNull()) { + return; + } + loadTBL(filename); +} + void MemoryModel::jumpToAddress(const QString& hex) { bool ok = false; uint32_t i = hex.toInt(&ok, 16); @@ -266,6 +286,39 @@ void MemoryModel::deserialize(const QByteArray& bytes) { } } +QString MemoryModel::decodeText(const QByteArray& bytes) { + QString text; + if (m_codec) { + TextCodecIterator iter; + TextCodecStartDecode(m_codec.get(), &iter); + uint8_t lineBuffer[128]; + for (quint8 byte : bytes) { + size_t size = TextCodecAdvance(&iter, byte, lineBuffer, sizeof(lineBuffer)); + if (size > sizeof(lineBuffer)) { + size = sizeof(lineBuffer); + } + for (size_t i = 0; i < size; ++i) { + text.append(lineBuffer[i]); + } + } + size_t size = TextCodecFinish(&iter, lineBuffer, sizeof(lineBuffer)); + if (size > sizeof(lineBuffer)) { + size = sizeof(lineBuffer); + } + for (size_t i = 0; i < size; ++i) { + text.append(lineBuffer[i]); + } + } else { + for (QChar c : bytes) { + if (!c.isPrint() || c >= 127) { + continue; + } + text.append(c); + } + } + return text; +} + void MemoryModel::resizeEvent(QResizeEvent*) { m_cellSize = QSizeF((viewport()->size().width() - (m_margins.left() + m_margins.right())) / 16.0, m_cellHeight); verticalScrollBar()->setRange(0, (m_size >> 4) + 1 - viewport()->size().height() / m_cellHeight); @@ -284,7 +337,7 @@ void MemoryModel::paintEvent(QPaintEvent* event) { painter.drawStaticText(QPointF((m_margins.left() - m_regionName.size().width() - 1) / 2.0, 0), m_regionName); painter.drawText( QRect(QPoint(viewport()->size().width() - m_margins.right(), 0), QSize(m_margins.right(), m_margins.top())), - Qt::AlignHCenter, tr("ASCII")); + Qt::AlignHCenter, m_codec ? tr("TBL") : tr("ASCII")); for (int x = 0; x < 16; ++x) { painter.drawText(QRectF(QPointF(m_cellSize.width() * x + m_margins.left(), 0), m_cellSize), Qt::AlignHCenter, QString::number(x, 16).toUpper()); @@ -392,10 +445,20 @@ void MemoryModel::paintEvent(QPaintEvent* event) { } painter.setPen(palette.color(QPalette::WindowText)); for (int x = 0; x < 16; ++x) { - uint8_t b =m_core->rawRead8(m_core, (y + m_top) * 16 + x + m_base, m_currentBank); + uint8_t b = m_core->rawRead8(m_core, (y + m_top) * 16 + x + m_base, m_currentBank); + QString text = decodeText(QByteArray(1, b)); + if (text.isEmpty()) { + b = '.'; + } else { + QChar c = text.at(0); + if (!c.isPrint() || c >= 127) { + b = '.'; + } else { + b = c.toLatin1(); + } + } painter.drawStaticText( - QPointF(viewport()->size().width() - (16 - x) * m_margins.right() / 17.0 - m_letterWidth * 0.5, yp), - b < 0x80 ? m_staticAscii[b] : m_staticAscii[0]); + QPointF(viewport()->size().width() - (16 - x) * m_margins.right() / 17.0 - m_letterWidth * 0.5, yp), m_staticAscii[b]); } } painter.drawLine(m_margins.left(), 0, m_margins.left(), viewport()->size().height()); @@ -635,3 +698,8 @@ void MemoryModel::adjustCursor(int adjust, bool shift) { emit selectionChanged(m_selection.first, m_selection.second); viewport()->update(); } + +void MemoryModel::TextCodecFree::operator()(TextCodec* codec) { + TextCodecDeinit(codec); + delete(codec); +} diff --git a/src/platform/qt/MemoryModel.h b/src/platform/qt/MemoryModel.h index 972a1c7b2..7be2861ac 100644 --- a/src/platform/qt/MemoryModel.h +++ b/src/platform/qt/MemoryModel.h @@ -11,6 +11,11 @@ #include #include #include +#include + +extern "C" { +#include "util/text-codec.h" +} struct mCore; @@ -34,11 +39,15 @@ public: QByteArray serialize(); void deserialize(const QByteArray&); + QString decodeText(const QByteArray&); public slots: void jumpToAddress(const QString& hex); void jumpToAddress(uint32_t); + void loadTBL(const QString& path); + void loadTBL(); + void copy(); void paste(); void save(); @@ -64,7 +73,13 @@ private: void adjustCursor(int adjust, bool shift); + class TextCodecFree { + public: + void operator()(TextCodec*); + }; + mCore* m_core; + std::unique_ptr m_codec; QFont m_font; int m_cellHeight; int m_letterWidth; diff --git a/src/platform/qt/MemoryView.cpp b/src/platform/qt/MemoryView.cpp index ca5e5e32b..07ad16254 100644 --- a/src/platform/qt/MemoryView.cpp +++ b/src/platform/qt/MemoryView.cpp @@ -109,6 +109,8 @@ MemoryView::MemoryView(GameController* controller, QWidget* parent) connect(m_ui.save, SIGNAL(clicked()), m_ui.hexfield, SLOT(save())); connect(m_ui.paste, SIGNAL(clicked()), m_ui.hexfield, SLOT(paste())); connect(m_ui.load, SIGNAL(clicked()), m_ui.hexfield, SLOT(load())); + + connect(m_ui.loadTBL, SIGNAL(clicked()), m_ui.hexfield, SLOT(loadTBL())); } void MemoryView::setIndex(int index) { @@ -172,13 +174,7 @@ void MemoryView::updateStatus() { } mCore* core = m_controller->thread()->core; QByteArray selection(m_ui.hexfield->serialize()); - QString text; - for (QChar c : selection) { - if (!c.isPrint() || c >= 127) { - continue; - } - text.append(c); - } + QString text(m_ui.hexfield->decodeText(selection)); m_ui.stringVal->setText(text); if (m_selection.first & (align - 1) || m_selection.second - m_selection.first != align) { diff --git a/src/platform/qt/MemoryView.ui b/src/platform/qt/MemoryView.ui index cb6a67141..acbd04da7 100644 --- a/src/platform/qt/MemoryView.ui +++ b/src/platform/qt/MemoryView.ui @@ -225,6 +225,13 @@ + + + + Load TBL + + +