mirror of https://github.com/mgba-emu/mgba.git
Qt: Memory range dumping (closes #1298)
This commit is contained in:
parent
c076878495
commit
81fd7e3c1a
1
CHANGES
1
CHANGES
|
@ -21,6 +21,7 @@ Features:
|
||||||
- Qt: Add export button for tile view (closes mgba.io/i/1507)
|
- Qt: Add export button for tile view (closes mgba.io/i/1507)
|
||||||
- Qt: Add recent game list clearing (closes mgba.io/i/1380)
|
- Qt: Add recent game list clearing (closes mgba.io/i/1380)
|
||||||
- GB: Yanking gamepak now supported
|
- GB: Yanking gamepak now supported
|
||||||
|
- Qt: Memory range dumping (closes mgba.io/i/1298)
|
||||||
Emulation fixes:
|
Emulation fixes:
|
||||||
- GBA: All IRQs have 7 cycle delay (fixes mgba.io/i/539, mgba.io/i/1208)
|
- GBA: All IRQs have 7 cycle delay (fixes mgba.io/i/539, mgba.io/i/1208)
|
||||||
- GBA: Reset now reloads multiboot ROMs
|
- GBA: Reset now reloads multiboot ROMs
|
||||||
|
|
|
@ -40,7 +40,7 @@ static const struct mCoreChannelInfo _GBAudioChannels[] = {
|
||||||
|
|
||||||
static const struct mCoreMemoryBlock _GBMemoryBlocks[] = {
|
static const struct mCoreMemoryBlock _GBMemoryBlocks[] = {
|
||||||
{ -1, "mem", "All", "All", 0, 0x10000, 0x10000, mCORE_MEMORY_VIRTUAL },
|
{ -1, "mem", "All", "All", 0, 0x10000, 0x10000, mCORE_MEMORY_VIRTUAL },
|
||||||
{ GB_REGION_CART_BANK0, "cart0", "ROM Bank", "Game Pak (32kiB)", GB_BASE_CART_BANK0, GB_SIZE_CART_BANK0 * 2, 0x800000, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED, 511 },
|
{ GB_REGION_CART_BANK0, "cart0", "ROM Bank", "Game Pak (32kiB)", GB_BASE_CART_BANK0, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 * 2, 0x800000, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED, 511, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 },
|
||||||
{ GB_REGION_VRAM, "vram", "VRAM", "Video RAM (8kiB)", GB_BASE_VRAM, GB_BASE_VRAM + GB_SIZE_VRAM, GB_SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
{ GB_REGION_VRAM, "vram", "VRAM", "Video RAM (8kiB)", GB_BASE_VRAM, GB_BASE_VRAM + GB_SIZE_VRAM, GB_SIZE_VRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||||
{ GB_REGION_EXTERNAL_RAM, "sram", "SRAM", "External RAM (8kiB)", GB_BASE_EXTERNAL_RAM, GB_BASE_EXTERNAL_RAM + GB_SIZE_EXTERNAL_RAM, GB_SIZE_EXTERNAL_RAM * 4, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 3 },
|
{ GB_REGION_EXTERNAL_RAM, "sram", "SRAM", "External RAM (8kiB)", GB_BASE_EXTERNAL_RAM, GB_BASE_EXTERNAL_RAM + GB_SIZE_EXTERNAL_RAM, GB_SIZE_EXTERNAL_RAM * 4, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 3 },
|
||||||
{ GB_REGION_WORKING_RAM_BANK0, "wram", "WRAM", "Working RAM (8kiB)", GB_BASE_WORKING_RAM_BANK0, GB_BASE_WORKING_RAM_BANK0 + GB_SIZE_WORKING_RAM_BANK0 * 2 , GB_SIZE_WORKING_RAM_BANK0 * 2, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
{ GB_REGION_WORKING_RAM_BANK0, "wram", "WRAM", "Working RAM (8kiB)", GB_BASE_WORKING_RAM_BANK0, GB_BASE_WORKING_RAM_BANK0 + GB_SIZE_WORKING_RAM_BANK0 * 2 , GB_SIZE_WORKING_RAM_BANK0 * 2, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||||
|
@ -51,10 +51,10 @@ static const struct mCoreMemoryBlock _GBMemoryBlocks[] = {
|
||||||
|
|
||||||
static const struct mCoreMemoryBlock _GBCMemoryBlocks[] = {
|
static const struct mCoreMemoryBlock _GBCMemoryBlocks[] = {
|
||||||
{ -1, "mem", "All", "All", 0, 0x10000, 0x10000, mCORE_MEMORY_VIRTUAL },
|
{ -1, "mem", "All", "All", 0, 0x10000, 0x10000, mCORE_MEMORY_VIRTUAL },
|
||||||
{ GB_REGION_CART_BANK0, "cart0", "ROM Bank", "Game Pak (32kiB)", GB_BASE_CART_BANK0, GB_SIZE_CART_BANK0 * 2, 0x800000, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED, 511 },
|
{ GB_REGION_CART_BANK0, "cart0", "ROM Bank", "Game Pak (32kiB)", GB_BASE_CART_BANK0, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 * 2, 0x800000, mCORE_MEMORY_READ | mCORE_MEMORY_MAPPED, 511, GB_BASE_CART_BANK0 + GB_SIZE_CART_BANK0 },
|
||||||
{ GB_REGION_VRAM, "vram", "VRAM", "Video RAM (8kiB)", GB_BASE_VRAM, GB_BASE_VRAM + GB_SIZE_VRAM, GB_SIZE_VRAM * 2, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 1 },
|
{ GB_REGION_VRAM, "vram", "VRAM", "Video RAM (8kiB)", GB_BASE_VRAM, GB_BASE_VRAM + GB_SIZE_VRAM, GB_SIZE_VRAM * 2, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 1 },
|
||||||
{ GB_REGION_EXTERNAL_RAM, "sram", "SRAM", "External RAM (8kiB)", GB_BASE_EXTERNAL_RAM, GB_BASE_EXTERNAL_RAM + GB_SIZE_EXTERNAL_RAM, GB_SIZE_EXTERNAL_RAM * 4, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 3 },
|
{ GB_REGION_EXTERNAL_RAM, "sram", "SRAM", "External RAM (8kiB)", GB_BASE_EXTERNAL_RAM, GB_BASE_EXTERNAL_RAM + GB_SIZE_EXTERNAL_RAM, GB_SIZE_EXTERNAL_RAM * 4, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 3 },
|
||||||
{ GB_REGION_WORKING_RAM_BANK0, "wram", "WRAM", "Working RAM (8kiB)", GB_BASE_WORKING_RAM_BANK0, GB_BASE_WORKING_RAM_BANK0 + GB_SIZE_WORKING_RAM_BANK0 * 2, GB_SIZE_WORKING_RAM_BANK0 * 8, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 7 },
|
{ GB_REGION_WORKING_RAM_BANK0, "wram", "WRAM", "Working RAM (8kiB)", GB_BASE_WORKING_RAM_BANK0, GB_BASE_WORKING_RAM_BANK0 + GB_SIZE_WORKING_RAM_BANK0 * 2, GB_SIZE_WORKING_RAM_BANK0 * 8, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED, 7, GB_BASE_WORKING_RAM_BANK0 + GB_SIZE_WORKING_RAM_BANK0 },
|
||||||
{ GB_BASE_OAM, "oam", "OAM", "OBJ Attribute Memory", GB_BASE_OAM, GB_BASE_OAM + GB_SIZE_OAM, GB_SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
{ GB_BASE_OAM, "oam", "OAM", "OBJ Attribute Memory", GB_BASE_OAM, GB_BASE_OAM + GB_SIZE_OAM, GB_SIZE_OAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||||
{ GB_BASE_IO, "io", "MMIO", "Memory-Mapped I/O", GB_BASE_IO, GB_BASE_IO + GB_SIZE_IO, GB_SIZE_IO, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
{ GB_BASE_IO, "io", "MMIO", "Memory-Mapped I/O", GB_BASE_IO, GB_BASE_IO + GB_SIZE_IO, GB_SIZE_IO, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||||
{ GB_BASE_HRAM, "hram", "HRAM", "High RAM", GB_BASE_HRAM, GB_BASE_HRAM + GB_SIZE_HRAM, GB_SIZE_HRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
{ GB_BASE_HRAM, "hram", "HRAM", "High RAM", GB_BASE_HRAM, GB_BASE_HRAM + GB_SIZE_HRAM, GB_SIZE_HRAM, mCORE_MEMORY_RW | mCORE_MEMORY_MAPPED },
|
||||||
|
|
|
@ -85,6 +85,7 @@ set(SOURCE_FILES
|
||||||
LogConfigModel.cpp
|
LogConfigModel.cpp
|
||||||
LogView.cpp
|
LogView.cpp
|
||||||
MapView.cpp
|
MapView.cpp
|
||||||
|
MemoryDump.cpp
|
||||||
MemoryModel.cpp
|
MemoryModel.cpp
|
||||||
MemorySearch.cpp
|
MemorySearch.cpp
|
||||||
MemoryView.cpp
|
MemoryView.cpp
|
||||||
|
@ -126,6 +127,7 @@ set(UI_FILES
|
||||||
LoadSaveState.ui
|
LoadSaveState.ui
|
||||||
LogView.ui
|
LogView.ui
|
||||||
MapView.ui
|
MapView.ui
|
||||||
|
MemoryDump.ui
|
||||||
MemorySearch.ui
|
MemorySearch.ui
|
||||||
MemoryView.ui
|
MemoryView.ui
|
||||||
ObjView.ui
|
ObjView.ui
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
/* Copyright (c) 2013-2019 Jeffrey Pfau
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
#include "MemoryDump.h"
|
||||||
|
|
||||||
|
#include "CoreController.h"
|
||||||
|
#include "GBAApp.h"
|
||||||
|
#include "LogController.h"
|
||||||
|
|
||||||
|
using namespace QGBA;
|
||||||
|
|
||||||
|
MemoryDump::MemoryDump(std::shared_ptr<CoreController> controller, QWidget* parent)
|
||||||
|
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint)
|
||||||
|
, m_controller(controller)
|
||||||
|
{
|
||||||
|
m_ui.setupUi(this);
|
||||||
|
|
||||||
|
connect(this, &QDialog::accepted, this, &MemoryDump::save);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryDump::save() {
|
||||||
|
QString filename = GBAApp::app()->getSaveFileName(this, tr("Save memory region"));
|
||||||
|
if (filename.isNull()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QFile outfile(filename);
|
||||||
|
if (!outfile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||||
|
LOG(QT, WARN) << tr("Failed to open output file: %1").arg(filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QByteArray out(serialize());
|
||||||
|
outfile.write(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryDump::setAddress(uint32_t start) {
|
||||||
|
m_ui.address->setValue(start);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryDump::setSegment(int seg) {
|
||||||
|
m_ui.segment->setValue(seg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MemoryDump::setByteCount(uint32_t count) {
|
||||||
|
m_ui.bytes->setValue(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray MemoryDump::serialize() {
|
||||||
|
CoreController::Interrupter interrupter(m_controller);
|
||||||
|
mCore* core = m_controller->thread()->core;
|
||||||
|
const mCoreMemoryBlock* blocks;
|
||||||
|
size_t nBlocks = core->listMemoryBlocks(core, &blocks);
|
||||||
|
|
||||||
|
int size = m_ui.bytes->value();
|
||||||
|
uint32_t start = m_ui.address->value();
|
||||||
|
int segment = m_ui.segment->value();
|
||||||
|
bool spanSegments = m_ui.spanSegments->isChecked();
|
||||||
|
|
||||||
|
QByteArray mem;
|
||||||
|
while (size) {
|
||||||
|
const mCoreMemoryBlock* bestMatch = NULL;
|
||||||
|
const char* block = NULL;
|
||||||
|
size_t blockSize = 0;
|
||||||
|
for (size_t i = 0; i < nBlocks; ++i) {
|
||||||
|
if (blocks[i].end <= start) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (blocks[i].start > start) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
block = static_cast<const char*>(core->getMemoryBlock(core, blocks[i].id, &blockSize));
|
||||||
|
if (block) {
|
||||||
|
bestMatch = &blocks[i];
|
||||||
|
break;
|
||||||
|
} else if (!bestMatch) {
|
||||||
|
bestMatch = &blocks[i];
|
||||||
|
blockSize = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!spanSegments) {
|
||||||
|
blockSize = bestMatch->end - bestMatch->start;
|
||||||
|
} else if (!blockSize) {
|
||||||
|
blockSize = bestMatch->size;
|
||||||
|
}
|
||||||
|
size_t segmentSize = bestMatch->end - bestMatch->start;
|
||||||
|
if (bestMatch->segmentStart) {
|
||||||
|
segmentSize = bestMatch->segmentStart - bestMatch->start;
|
||||||
|
}
|
||||||
|
if (segment > 0) {
|
||||||
|
start += segment * segmentSize;
|
||||||
|
}
|
||||||
|
int maxFromRegion = blockSize - (start - bestMatch->start);
|
||||||
|
if (maxFromRegion <= 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int fromRegion = std::min(size, maxFromRegion);
|
||||||
|
if (block && (segment >= 0 || segmentSize == blockSize)) {
|
||||||
|
block = &block[start - bestMatch->start];
|
||||||
|
mem.append(QByteArray::fromRawData(block, fromRegion));
|
||||||
|
size -= fromRegion;
|
||||||
|
start += fromRegion;
|
||||||
|
if (spanSegments) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < 16; ++i) {
|
||||||
|
char datum = core->rawRead8(core, start, segment);
|
||||||
|
mem.append(datum);
|
||||||
|
++start;
|
||||||
|
--size;
|
||||||
|
if (!size) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mem;
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/* Copyright (c) 2013-2019 Jeffrey Pfau
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ui_MemoryDump.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace QGBA {
|
||||||
|
|
||||||
|
class CoreController;
|
||||||
|
|
||||||
|
class MemoryDump : public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MemoryDump(std::shared_ptr<CoreController> controller, QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setSegment(int);
|
||||||
|
void setAddress(uint32_t address);
|
||||||
|
void setByteCount(uint32_t);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void save();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QByteArray serialize();
|
||||||
|
|
||||||
|
Ui::MemoryDump m_ui;
|
||||||
|
|
||||||
|
std::shared_ptr<CoreController> m_controller;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,159 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MemoryDump</class>
|
||||||
|
<widget class="QDialog" name="MemoryDump">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>448</width>
|
||||||
|
<height>208</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Save Memory Range</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Start Address:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="segment">
|
||||||
|
<property name="minimum">
|
||||||
|
<number>-1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>511</number>
|
||||||
|
</property>
|
||||||
|
<property name="displayIntegerBase">
|
||||||
|
<number>16</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="text">
|
||||||
|
<string>:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="address">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="accelerated">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="prefix">
|
||||||
|
<string>0x</string>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>268435455</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>16</number>
|
||||||
|
</property>
|
||||||
|
<property name="displayIntegerBase">
|
||||||
|
<number>16</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Byte Count:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QSpinBox" name="bytes">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="prefix">
|
||||||
|
<string>0x</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>268435456</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>256</number>
|
||||||
|
</property>
|
||||||
|
<property name="displayIntegerBase">
|
||||||
|
<number>16</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="spanSegments">
|
||||||
|
<property name="text">
|
||||||
|
<string>Dump across banks</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0" colspan="2">
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>MemoryDump</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>MemoryDump</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
|
@ -7,6 +7,7 @@
|
||||||
#include "MemoryView.h"
|
#include "MemoryView.h"
|
||||||
|
|
||||||
#include "CoreController.h"
|
#include "CoreController.h"
|
||||||
|
#include "MemoryDump.h"
|
||||||
|
|
||||||
#include <mgba/core/core.h>
|
#include <mgba/core/core.h>
|
||||||
|
|
||||||
|
@ -44,6 +45,7 @@ MemoryView::MemoryView(std::shared_ptr<CoreController> controller, QWidget* pare
|
||||||
connect(m_ui.setAddress, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
|
connect(m_ui.setAddress, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged),
|
||||||
this, static_cast<void (MemoryView::*)(uint32_t)>(&MemoryView::jumpToAddress));
|
this, static_cast<void (MemoryView::*)(uint32_t)>(&MemoryView::jumpToAddress));
|
||||||
connect(m_ui.hexfield, &MemoryModel::selectionChanged, this, &MemoryView::updateSelection);
|
connect(m_ui.hexfield, &MemoryModel::selectionChanged, this, &MemoryView::updateSelection);
|
||||||
|
connect(m_ui.saveRange, &QAbstractButton::clicked, this, &MemoryView::saveRange);
|
||||||
|
|
||||||
connect(controller.get(), &CoreController::stopping, this, &QWidget::close);
|
connect(controller.get(), &CoreController::stopping, this, &QWidget::close);
|
||||||
|
|
||||||
|
@ -69,6 +71,7 @@ void MemoryView::setIndex(int index) {
|
||||||
m_region = qMakePair(info.start, info.end);
|
m_region = qMakePair(info.start, info.end);
|
||||||
m_ui.segments->setValue(-1);
|
m_ui.segments->setValue(-1);
|
||||||
m_ui.segments->setVisible(info.maxSegment > 0);
|
m_ui.segments->setVisible(info.maxSegment > 0);
|
||||||
|
m_ui.segmentColon->setVisible(info.maxSegment > 0);
|
||||||
m_ui.segments->setMaximum(info.maxSegment);
|
m_ui.segments->setMaximum(info.maxSegment);
|
||||||
m_ui.hexfield->setRegion(info.start, info.end - info.start, info.shortName);
|
m_ui.hexfield->setRegion(info.start, info.end - info.start, info.shortName);
|
||||||
}
|
}
|
||||||
|
@ -142,3 +145,12 @@ void MemoryView::updateStatus() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MemoryView::saveRange() {
|
||||||
|
MemoryDump* memdump = new MemoryDump(m_controller);
|
||||||
|
memdump->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
memdump->setAddress(m_selection.first);
|
||||||
|
memdump->setSegment(m_ui.segments->value());
|
||||||
|
memdump->setByteCount(m_selection.second - m_selection.first);
|
||||||
|
memdump->show();
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ private slots:
|
||||||
void setSegment(int);
|
void setSegment(int);
|
||||||
void updateSelection(uint32_t start, uint32_t end);
|
void updateSelection(uint32_t start, uint32_t end);
|
||||||
void updateStatus();
|
void updateStatus();
|
||||||
|
void saveRange();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::MemoryView m_ui;
|
Ui::MemoryView m_ui;
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>822</width>
|
<width>874</width>
|
||||||
<height>886</height>
|
<height>900</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -52,6 +52,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="segmentColon">
|
||||||
|
<property name="text">
|
||||||
|
<string>:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSpinBox" name="setAddress">
|
<widget class="QSpinBox" name="setAddress">
|
||||||
<property name="accelerated">
|
<property name="accelerated">
|
||||||
|
@ -271,6 +278,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="saveRange">
|
||||||
|
<property name="text">
|
||||||
|
<string>Save Range</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="load">
|
<widget class="QPushButton" name="load">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
|
Loading…
Reference in New Issue