-
Notifications
You must be signed in to change notification settings - Fork 2
/
cpuwidget.cpp
116 lines (96 loc) · 4.58 KB
/
cpuwidget.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include "cpuwidget.h"
#include "commonformatters.h"
#include "ui_cpuwidget.h"
#include "uitools.h"
#include <QFontDatabase>
#include <QMetaEnum>
#include <QResizeEvent>
static QString flagStr(bool flagStatus, const char* flagCode) {
return flagStatus ? flagCode : QString("<span style='color:gray'>%1</span>").arg(flagCode);
}
CpuWidget::CpuWidget(QWidget* parent, const Memory& memory) : QDockWidget(parent), ui(new Ui::CpuWidget), memory(memory) {
ui->setupUi(this);
disassemblerView = new DisassemblerView(this, memory);
QVBoxLayout* layout = static_cast<QVBoxLayout*>(ui->dockWidgetContents->layout());
layout->insertWidget(layout->indexOf(ui->auxFrame), disassemblerView);
connect(ui->reset, &QAbstractButton::clicked, this, &CpuWidget::resetRequested);
connect(ui->nmi, &QAbstractButton::clicked, this, &CpuWidget::nmiRequested);
connect(ui->irq, &QAbstractButton::clicked, this, &CpuWidget::irqRequested);
connect(ui->regPC, QOverload<int>::of(&QSpinBox::valueChanged), this, &CpuWidget::programCounterChanged);
connect(ui->regSP, QOverload<int>::of(&QSpinBox::valueChanged), this, &CpuWidget::stackPointerChanged);
connect(ui->regA, QOverload<int>::of(&QSpinBox::valueChanged), this, &CpuWidget::registerAChanged);
connect(ui->regX, QOverload<int>::of(&QSpinBox::valueChanged), this, &CpuWidget::registerXChanged);
connect(ui->regY, QOverload<int>::of(&QSpinBox::valueChanged), this, &CpuWidget::registerYChanged);
connect(ui->clearStatistics, &QAbstractButton::clicked, this, &CpuWidget::clearStatisticsRequested);
connect(ui->skipInstruction, &QAbstractButton::clicked, this, &CpuWidget::skipInstruction);
connect(ui->continuousExecution, &QAbstractButton::clicked, [&] { emitExecutionRequest(true); });
connect(ui->stepExecution, &QAbstractButton::clicked, this, [&] { emitExecutionRequest(false); });
connect(ui->stopExecution, &QAbstractButton::clicked, this, &CpuWidget::stopExecutionRequested);
setMonospaceFont(disassemblerView);
setMonospaceFont(ui->flags);
ui->ioPortConfig->setValue(0b11010001);
}
CpuWidget::~CpuWidget() {
delete ui;
}
void CpuWidget::updateOnChange(AddressRange range) {
disassemblerView->updateMemoryView(range);
updateSpecialCpuAddresses();
}
void CpuWidget::updateState(EmulatorState es) {
const auto& regs = es.regs;
setWindowTitle(tr("%1 @ %2").arg(formatCpuState(es.state), formatRunLevel(es.runLevel)));
ui->regA->setValue(regs.a);
ui->regX->setValue(regs.x);
ui->regY->setValue(regs.y);
ui->regSP->setValue(regs.sp.address());
ui->regPC->setValue(regs.pc);
updateSpecialCpuAddresses();
QString str;
str.append(flagStr(regs.p.negative, "N"));
str.append(flagStr(regs.p.overflow, "V"));
str.append(flagStr(false, "."));
str.append(flagStr(false, "B"));
str.append(flagStr(regs.p.decimal, "D"));
str.append(flagStr(regs.p.interrupt, "I"));
str.append(flagStr(regs.p.zero, "Z"));
str.append(flagStr(regs.p.carry, "C"));
ui->flags->setText(str);
ui->lastExecStats->setText(formatExecutionStatistics(es.lastExecutionStatistics));
ui->avgExecStats->setText(formatExecutionStatistics(es.avgExecutionStatistics));
ui->regPC->setValue(regs.pc);
disassemblerView->changeStart(regs.pc);
updateUI(es.state);
}
void CpuWidget::changeProgramCounter(uint16_t addr) {
ui->regPC->setValue(addr);
}
void CpuWidget::updateSpecialCpuAddresses() {
ui->resetVector->setValue(memory.word(CpuAddress::ResetVector));
ui->nmiVector->setValue(memory.word(CpuAddress::NmiVector));
ui->irqVector->setValue(memory.word(CpuAddress::IrqVector));
ui->ioPortData->setValue(memory[CpuAddress::IoPortData]);
ui->ioPortConfig->setValue(memory[CpuAddress::IoPortConfig]);
}
void CpuWidget::updateUI(CpuState state) {
const auto processing = state == CpuState::Running || state == CpuState::Stopping;
ui->cpuFrame->setDisabled(processing);
ui->skipInstruction->setDisabled(processing);
ui->continuousExecution->setDisabled(processing);
ui->stopExecution->setDisabled(!processing);
ui->stepExecution->setDisabled(processing || state == CpuState::Halted);
ui->nmiVector->setDisabled(processing);
ui->resetVector->setDisabled(processing);
ui->irqVector->setDisabled(processing);
ui->ioPortData->setDisabled(processing);
ui->ioPortConfig->setDisabled(processing);
ui->clockFrequency->setDisabled(processing);
}
void CpuWidget::skipInstruction() {
disassemblerView->nextInstruction();
emit programCounterChanged(disassemblerView->first());
}
void CpuWidget::emitExecutionRequest(bool continuous) {
updateUI(CpuState::Running);
emit executionRequested(continuous, static_cast<Frequency>(ui->clockFrequency->value() * 1e6));
}