ui changes

This commit is contained in:
zanostro 2025-12-05 19:00:11 +01:00
parent 1fb7d52842
commit d3ab78e76c
6 changed files with 131 additions and 17 deletions

View file

@ -42,8 +42,13 @@ void MachineController::runLoop() {
try {
if (m_machine) {
m_machine->execute();
m_machine->tick();
m_machine->tick();
emit tick();
if (m_machine->isStopped()) {
m_running.store(false);
break;
}
}
} catch (const std::exception &e) {
emit error(QString::fromStdString(e.what()));

View file

@ -17,6 +17,8 @@
#include <QVBoxLayout>
#include <QLabel>
#include <QFont>
#include <QFileDialog>
#include <QMessageBox>
class Loader;
@ -69,8 +71,8 @@ MainWindow::MainWindow(QWidget *parent) :
ui->regF_bin_field->setValidator(floatBinValidator);
connect(m_controller.get(), &MachineController::tick, this, &MainWindow::updateRegisterDisplays);
connect(m_controller.get(), &MachineController::tick, this, &MainWindow::updateMemoryDisplay);
connect(m_controller.get(), &MachineController::tick, this, &MainWindow::updateRegisterDisplays, Qt::QueuedConnection);
connect(m_controller.get(), &MachineController::tick, this, &MainWindow::updateMemoryDisplay, Qt::QueuedConnection);
connectRegisterFields();
@ -95,15 +97,16 @@ MainWindow::MainWindow(QWidget *parent) :
connect(ui->DisasmDec65536Btn, &QPushButton::clicked, this, &MainWindow::onDisassemblyDec256);
connect(ui->DisasmGoToStart, &QPushButton::clicked, this, &MainWindow::onDisassemblyGoToStart);
connect(ui->DisasmGoToEnd, &QPushButton::clicked, this, &MainWindow::onDisassemblyGoToEnd);
connect(m_controller.get(), &MachineController::tick, this, &MainWindow::updateDisassemblyDisplay);
connect(m_controller.get(), &MachineController::tick, this, &MainWindow::updateDisassemblyDisplay, Qt::QueuedConnection);
// Connect menu actions
connect(ui->actionLoad_Object_File, &QAction::triggered, this, &MainWindow::loadObjectFile);
setupMemoryDisplay();
setupDisassemblyDisplay();
loadInstructionSet();
//loadDemoProgram();
Loader loader(m_machine, std::string(PATH_RESOURCES) + "print.obj");
loader.load();
// Don't load any program by default - user will load via File menu
updateRegisterDisplays();
updateMemoryDisplay();
@ -760,7 +763,7 @@ MainWindow::DisassembledInstruction MainWindow::disassembleAt(int address)
QString addrMode = "";
if (p) {
ea += m_machine->getPC();
ea += (address + 3);
addrMode = " (PC)";
} else if (b) {
ea += m_machine->getB();
@ -918,3 +921,38 @@ void MainWindow::updateMemoryDisplay()
ui->MemoryScrollArea->setWidget(container);
}
void MainWindow::loadObjectFile()
{
QString fileName = QFileDialog::getOpenFileName(this,
tr("Load Object File"),
QString(),
tr("Object Files (*.obj);;All Files (*)"));
if (fileName.isEmpty()) {
return;
}
try {
// Stop execution if running
m_controller->stop();
// Reset machine state
m_machine->reset();
// Load the object file
Loader loader(m_machine, fileName.toStdString());
loader.load();
// Update displays
updateRegisterDisplays();
updateMemoryDisplay();
updateDisassemblyDisplay();
QMessageBox::information(this, tr("Success"),
tr("Object file loaded successfully"));
} catch (const std::exception &e) {
QMessageBox::critical(this, tr("Error"),
tr("Failed to load object file: %1").arg(e.what()));
}
}

View file

@ -50,6 +50,7 @@ private slots:
void onDisassemblyDec256();
void onDisassemblyGoToStart();
void onDisassemblyGoToEnd();
void loadObjectFile();
private:
Ui::MainWindow *ui;

View file

@ -866,6 +866,18 @@
</widget>
</widget>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
@ -875,8 +887,43 @@
<height>20</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="actionLoad_Object_File"/>
</widget>
<widget class="QMenu" name="menuMachine">
<property name="title">
<string>Machine</string>
</property>
<addaction name="actionFrequency"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>Help</string>
</property>
<addaction name="actionAbout"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuMachine"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<action name="actionLoad_Object_File">
<property name="text">
<string>Load Object File</string>
</property>
</action>
<action name="actionFrequency">
<property name="text">
<string>Frequency</string>
</property>
</action>
<action name="actionAbout">
<property name="text">
<string>About</string>
</property>
</action>
</widget>
<resources/>
<connections/>

View file

@ -26,7 +26,7 @@ using std::cout;
class Machine {
public:
Machine();
Machine(int speedkHz) : Machine() { this->speedkHz = speedkHz; _instructionsTable = instructions; }
Machine(int speedHz) : Machine() { this->speedHz = speedHz; _instructionsTable = instructions; }
~Machine();
int getA() const { return A; }
@ -84,11 +84,13 @@ public:
// Execution and speed control
int getSpeed() const;
void setSpeed(int kHz);
void setSpeed(int Hz);
void start();
void stop();
void tick();
void halt();
bool isStopped() const { return _stopped; }
void reset();
// error handling methods
void notImplemented(string mnemonic);
@ -128,7 +130,7 @@ private:
// Execution control
std::atomic<bool> running{false};
std::atomic<int> speedkHz{1}; // Default 1 kHz
std::atomic<int> speedHz{10}; // Default 10 Hz
bool execF1(int opcode);
bool execF2(int opcode, int operand);

View file

@ -45,12 +45,12 @@ Machine::~Machine()
int Machine::getSpeed() const
{
return speedkHz.load();
return speedHz.load();
}
void Machine::setSpeed(int kHz)
void Machine::setSpeed(int Hz)
{
speedkHz.store(kHz);
speedHz.store(Hz);
}
// TODO: implement errors
@ -138,10 +138,10 @@ void Machine::setVT(const int *values)
void Machine::tick()
{
const int speed = speedkHz.load();
const int speed = speedHz.load();
if (speed <= 0) throw std::runtime_error("Invalid speed setting in Machine::tick");
const auto delay = std::chrono::microseconds(1000 / speed);
const auto delay = std::chrono::milliseconds(1000 / speed);
std::this_thread::sleep_for(delay);
}
@ -150,6 +150,27 @@ void Machine::halt()
_stopped = true;
}
void Machine::reset()
{
// Reset all registers
A = B = X = L = S = T = PC = SW = 0;
F = 0.0;
// Clear memory
for (int i = 0; i < MEMORY_SIZE; i++) {
memory[i] = 0;
}
// Reset execution state
_stopped = false;
running.store(false);
// Reset vector registers
for (int i = 0; i < VECTOR_REG_SIZE; i++) {
VA[i] = VS[i] = VT[i] = 0;
}
}
int Machine::getReg(int regNum) const
{
switch (regNum) {