mirror of
https://github.com/Treeki/WindEmu.git
synced 2025-08-28 22:00:23 +00:00
broken draft of a fully custom ARM emulator core
This commit is contained in:
@@ -20,7 +20,8 @@ DEFINES += QT_DEPRECATED_WARNINGS
|
||||
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
CONFIG += c++11
|
||||
CONFIG += c++17
|
||||
QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.14
|
||||
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
|
@@ -12,13 +12,13 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
ui->setupUi(this);
|
||||
|
||||
emu = new Emu;
|
||||
emu->loadROM("/Users/ash/src/psion/Sys$rom.bin");
|
||||
emu->loadROM("/Users/ash/src/psion/Sys$rom.bin");
|
||||
|
||||
timer = new QTimer(this);
|
||||
timer->setInterval(1000/64);
|
||||
connect(timer, SIGNAL(timeout()), SLOT(execTimer()));
|
||||
|
||||
updateScreen();
|
||||
updateScreen();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
@@ -30,10 +30,10 @@ void MainWindow::updateScreen()
|
||||
{
|
||||
ui->cycleCounter->setText(QString("Cycles: %1").arg(emu->currentCycles()));
|
||||
|
||||
updateMemory();
|
||||
updateMemory();
|
||||
|
||||
ui->regsLabel->setText(
|
||||
QString("R0: %1 / R1: %2 / R2: %3 / R3: %4 / R4: %5 / R5: %6 / R6: %7 / R7: %8\nR8: %9 / R9: %10 / R10:%11 / R11:%12 / R12:%13 / SP: %14 / LR: %15 / PC: %16")
|
||||
QString("R0: %1 / R1: %2 / R2: %3 / R3: %4 / R4: %5 / R5: %6 / R6: %7 / R7: %8\nR8: %9 / R9: %10 / R10:%11 / R11:%12 / R12:%13 / SP: %14 / LR: %15 / PC: %16")
|
||||
.arg(emu->getGPR(0), 8, 16)
|
||||
.arg(emu->getGPR(1), 8, 16)
|
||||
.arg(emu->getGPR(2), 8, 16)
|
||||
@@ -56,24 +56,27 @@ void MainWindow::updateScreen()
|
||||
const int context = 8 * 4;
|
||||
uint32_t pc = emu->getGPR(15) - 4;
|
||||
uint32_t minCode = pc - context;
|
||||
if (minCode >= (UINT32_MAX - context))
|
||||
if (minCode >= (UINT32_MAX - context))
|
||||
minCode = 0;
|
||||
uint32_t maxCode = pc + context;
|
||||
if (maxCode < context)
|
||||
if (maxCode < context)
|
||||
maxCode = UINT32_MAX;
|
||||
|
||||
QStringList codeLines;
|
||||
for (uint32_t addr = minCode; addr >= minCode && addr <= maxCode; addr += 4) {
|
||||
const char *prefix = (addr == pc) ? "==>" : " ";
|
||||
QStringList codeLines;
|
||||
for (uint32_t addr = minCode; addr >= minCode && addr <= maxCode; addr += 4) {
|
||||
const char *prefix = (addr == pc) ? "==>" : " ";
|
||||
struct ARMInstructionInfo info;
|
||||
char buffer[512];
|
||||
|
||||
uint32_t opcode = emu->readVirt32(addr);
|
||||
ARMDecodeARM(opcode, &info);
|
||||
ARMDisassemble(&info, addr, buffer, sizeof(buffer));
|
||||
codeLines.append(QString("%1 %2 | %3 | %4").arg(prefix).arg(addr, 8, 16).arg(opcode, 8, 16).arg(buffer));
|
||||
auto result = emu->readVirtual(addr, ARM710a::V32);
|
||||
if (result.first.has_value()) {
|
||||
uint32_t opcode = result.first.value();
|
||||
ARMDecodeARM(opcode, &info);
|
||||
ARMDisassemble(&info, addr, buffer, sizeof(buffer));
|
||||
codeLines.append(QString("%1 %2 | %3 | %4").arg(prefix).arg(addr, 8, 16).arg(opcode, 8, 16).arg(buffer));
|
||||
}
|
||||
}
|
||||
ui->codeLabel->setText(codeLines.join('\n'));
|
||||
ui->codeLabel->setText(codeLines.join('\n'));
|
||||
|
||||
// now, the actual screen
|
||||
const uint8_t *lcdBuf = emu->getLCDBuffer();
|
||||
@@ -95,12 +98,12 @@ void MainWindow::updateScreen()
|
||||
for (int x = 0; x < img.width(); x++) {
|
||||
uint8_t byte = lcdBuf[lineOffs + (x / ppb)];
|
||||
int shift = (x & (ppb - 1)) * bpp;
|
||||
int mask = (1 << bpp) - 1;
|
||||
int mask = (1 << bpp) - 1;
|
||||
int palIdx = (byte >> shift) & mask;
|
||||
int palValue = palette[palIdx];
|
||||
|
||||
palValue |= (palValue << 4);
|
||||
scanline[x] = palValue ^ 0xFF;
|
||||
palValue |= (palValue << 4);
|
||||
scanline[x] = palValue ^ 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +201,7 @@ void MainWindow::keyPressEvent(QKeyEvent *event)
|
||||
void MainWindow::keyReleaseEvent(QKeyEvent *event)
|
||||
{
|
||||
int k = resolveKey(event->key());
|
||||
if (k >= 0)
|
||||
if (k >= 0)
|
||||
emu->keyboardKeys[k] = false;
|
||||
}
|
||||
|
||||
@@ -243,71 +246,72 @@ void MainWindow::execTimer()
|
||||
|
||||
void MainWindow::on_addBreakButton_clicked()
|
||||
{
|
||||
uint32_t addr = ui->breakpointAddress->text().toUInt(nullptr, 16);
|
||||
emu->breakpoints().insert(addr);
|
||||
updateBreakpointsList();
|
||||
uint32_t addr = ui->breakpointAddress->text().toUInt(nullptr, 16);
|
||||
emu->breakpoints().insert(addr);
|
||||
updateBreakpointsList();
|
||||
}
|
||||
|
||||
void MainWindow::on_removeBreakButton_clicked()
|
||||
{
|
||||
uint32_t addr = ui->breakpointAddress->text().toUInt(nullptr, 16);
|
||||
emu->breakpoints().erase(addr);
|
||||
updateBreakpointsList();
|
||||
uint32_t addr = ui->breakpointAddress->text().toUInt(nullptr, 16);
|
||||
emu->breakpoints().erase(addr);
|
||||
updateBreakpointsList();
|
||||
}
|
||||
|
||||
void MainWindow::updateBreakpointsList()
|
||||
{
|
||||
ui->breakpointsList->clear();
|
||||
for (uint32_t addr : emu->breakpoints()) {
|
||||
ui->breakpointsList->addItem(QString::number(addr, 16));
|
||||
}
|
||||
ui->breakpointsList->clear();
|
||||
for (uint32_t addr : emu->breakpoints()) {
|
||||
ui->breakpointsList->addItem(QString::number(addr, 16));
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_memoryViewAddress_textEdited(const QString &)
|
||||
{
|
||||
updateMemory();
|
||||
updateMemory();
|
||||
}
|
||||
|
||||
void MainWindow::updateMemory()
|
||||
{
|
||||
uint32_t virtBase = ui->memoryViewAddress->text().toUInt(nullptr, 16) & ~0xFF;
|
||||
uint32_t physBase = emu->virtToPhys(virtBase);
|
||||
bool ok = (physBase != 0xFFFFFFFF) && emu->isPhysAddressValid(physBase);
|
||||
if (ok && (virtBase != physBase))
|
||||
ui->physicalAddressLabel->setText(QStringLiteral("Physical: %1").arg(physBase, 8, 16, QLatin1Char('0')));
|
||||
uint32_t virtBase = ui->memoryViewAddress->text().toUInt(nullptr, 16) & ~0xFF;
|
||||
auto physBaseOpt = emu->virtToPhys(virtBase);
|
||||
auto physBase = physBaseOpt.value_or(0xFFFFFFFF);
|
||||
bool ok = physBaseOpt.has_value() && emu->isPhysAddressValid(physBase);
|
||||
if (ok && (virtBase != physBase))
|
||||
ui->physicalAddressLabel->setText(QStringLiteral("Physical: %1").arg(physBase, 8, 16, QLatin1Char('0')));
|
||||
|
||||
uint8_t block[0x100];
|
||||
if (ok) {
|
||||
for (int i = 0; i < 0x100; i++) {
|
||||
block[i] = emu->readPhys8(physBase + i);
|
||||
}
|
||||
}
|
||||
uint8_t block[0x100];
|
||||
if (ok) {
|
||||
for (int i = 0; i < 0x100; i++) {
|
||||
block[i] = emu->readPhysical(physBase + i, ARM710a::V8).value();
|
||||
}
|
||||
}
|
||||
|
||||
QStringList output;
|
||||
for (int row = 0; row < 16; row++) {
|
||||
QString outLine;
|
||||
outLine.reserve(8 + 2 + (2 * 16) + 3 + 16);
|
||||
outLine.append(QStringLiteral("%1 |").arg(virtBase + (row * 16), 8, 16));
|
||||
for (int col = 0; col < 16; col++) {
|
||||
if (ok)
|
||||
outLine.append(QStringLiteral(" %1").arg(block[row*16+col], 2, 16, QLatin1Char('0')));
|
||||
else
|
||||
outLine.append(QStringLiteral(" ??"));
|
||||
}
|
||||
outLine.append(QStringLiteral(" | "));
|
||||
for (int col = 0; col < 16; col++) {
|
||||
uint8_t byte = block[row*16+col];
|
||||
if (!ok)
|
||||
outLine.append('?');
|
||||
else if (byte >= 0x20 && byte <= 0x7E)
|
||||
outLine.append(byte);
|
||||
else
|
||||
outLine.append('.');
|
||||
}
|
||||
output.append(outLine);
|
||||
}
|
||||
QStringList output;
|
||||
for (int row = 0; row < 16; row++) {
|
||||
QString outLine;
|
||||
outLine.reserve(8 + 2 + (2 * 16) + 3 + 16);
|
||||
outLine.append(QStringLiteral("%1 |").arg(virtBase + (row * 16), 8, 16));
|
||||
for (int col = 0; col < 16; col++) {
|
||||
if (ok)
|
||||
outLine.append(QStringLiteral(" %1").arg(block[row*16+col], 2, 16, QLatin1Char('0')));
|
||||
else
|
||||
outLine.append(QStringLiteral(" ??"));
|
||||
}
|
||||
outLine.append(QStringLiteral(" | "));
|
||||
for (int col = 0; col < 16; col++) {
|
||||
uint8_t byte = block[row*16+col];
|
||||
if (!ok)
|
||||
outLine.append('?');
|
||||
else if (byte >= 0x20 && byte <= 0x7E)
|
||||
outLine.append(byte);
|
||||
else
|
||||
outLine.append('.');
|
||||
}
|
||||
output.append(outLine);
|
||||
}
|
||||
|
||||
ui->memoryViewLabel->setText(output.join('\n'));
|
||||
ui->memoryViewLabel->setText(output.join('\n'));
|
||||
}
|
||||
|
||||
void MainWindow::on_memoryAdd1_clicked() { adjustMemoryAddress(1); }
|
||||
@@ -320,24 +324,24 @@ void MainWindow::on_memorySub10_clicked() { adjustMemoryAddress(-0x10); }
|
||||
void MainWindow::on_memorySub100_clicked() { adjustMemoryAddress(-0x100); }
|
||||
|
||||
void MainWindow::adjustMemoryAddress(int offset) {
|
||||
uint32_t address = ui->memoryViewAddress->text().toUInt(nullptr, 16);
|
||||
address += offset;
|
||||
ui->memoryViewAddress->setText(QString("%1").arg(address, 8, 16, QLatin1Char('0')));
|
||||
updateMemory();
|
||||
uint32_t address = ui->memoryViewAddress->text().toUInt(nullptr, 16);
|
||||
address += offset;
|
||||
ui->memoryViewAddress->setText(QString("%1").arg(address, 8, 16, QLatin1Char('0')));
|
||||
updateMemory();
|
||||
}
|
||||
|
||||
void MainWindow::on_writeByteButton_clicked()
|
||||
{
|
||||
uint32_t address = ui->memoryViewAddress->text().toUInt(nullptr, 16);
|
||||
uint8_t value = (uint8_t)ui->memoryWriteValue->text().toUInt(nullptr, 16);
|
||||
emu->writeVirt8(address, value);
|
||||
updateMemory();
|
||||
uint32_t address = ui->memoryViewAddress->text().toUInt(nullptr, 16);
|
||||
uint8_t value = (uint8_t)ui->memoryWriteValue->text().toUInt(nullptr, 16);
|
||||
emu->writeVirtual(value, address, ARM710a::V8);
|
||||
updateMemory();
|
||||
}
|
||||
|
||||
void MainWindow::on_writeDwordButton_clicked()
|
||||
{
|
||||
uint32_t address = ui->memoryViewAddress->text().toUInt(nullptr, 16);
|
||||
uint32_t value = ui->memoryWriteValue->text().toUInt(nullptr, 16);
|
||||
emu->writeVirt32(address, value);
|
||||
updateMemory();
|
||||
uint32_t address = ui->memoryViewAddress->text().toUInt(nullptr, 16);
|
||||
uint32_t value = ui->memoryWriteValue->text().toUInt(nullptr, 16);
|
||||
emu->writeVirtual(value, address, ARM710a::V32);
|
||||
updateMemory();
|
||||
}
|
||||
|
Reference in New Issue
Block a user