make Osaris and 5mx emulator classes inherit from a shared base

This commit is contained in:
Ash Wolf
2019-12-25 00:29:03 +00:00
parent bf71b18d27
commit 8f30d6fcef
20 changed files with 326 additions and 1564 deletions

View File

@ -1,10 +1,58 @@
#include "mainwindow.h"
#include <QApplication>
#include <QFileDialog>
#include <QMessageBox>
#include "../WindCore/clps7111.h"
#include "../WindCore/windermere.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
auto args = a.arguments();
QString romFile;
if (args.length() > 1)
romFile = args.first();
else
romFile = QFileDialog::getOpenFileName(nullptr, "Select a ROM");
if (romFile.isNull()) return 0;
// what do we have?
QFile f(romFile);
f.open(QFile::ReadOnly);
auto buffer = f.readAll();
f.close();
if (buffer.size() < 0x400000) {
QMessageBox::critical(nullptr, "WindEmu", "Invalid ROM file!");
return 0;
}
EmuBase *emu = nullptr;
uint8_t *romData = (uint8_t *)buffer.data();
// parse this ROM to learn what hardware it's for
int variantFile = *((uint32_t *)&romData[0x80 + 0x4C]) & 0xFFFFFFF;
if (variantFile < (buffer.size() - 8)) {
int variantImg = *((uint32_t *)&romData[variantFile + 4]) & 0xFFFFFFF;
if (variantImg < (buffer.size() - 0x70)) {
int variant = *((uint32_t *)&romData[variantImg + 0x60]);
if (variant == 0x7060001) {
// 5mx ROM
emu = new Windermere::Emulator;
} else if (variant == 0x5040001) {
// Osaris ROM
emu = new CLPS7111::Emulator;
} else {
QMessageBox::critical(nullptr, "WindEmu", "Unrecognised ROM file!");
return 0;
}
}
}
emu->loadROM(romData, buffer.size());
MainWindow w(emu);
w.show();
return a.exec();

View File

@ -1,19 +1,17 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "../WindCore/clps7111_defs.h"
#include <QTimer>
#include <QKeyEvent>
#include "../WindCore/decoder.h"
MainWindow::MainWindow(QWidget *parent) :
MainWindow::MainWindow(EmuBase *emu, QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
ui(new Ui::MainWindow),
emu(emu)
{
ui->setupUi(this);
ui->logView->setMaximumBlockCount(1000);
emu = new CLPS7111;
emu->loadROM("/Users/ash/src/psion/Osaris.bin");
emu->setLogger([&](const char *str) {
ui->logView->appendPlainText(str);
});
@ -102,68 +100,13 @@ void MainWindow::updateScreen()
ui->codeLabel->setText(codeLines.join('\n'));
// now, the actual screen
const uint8_t *lcdBuf = emu->getLCDBuffer();
if (lcdBuf) {
#if 0
QImage img(640, 240, QImage::Format_Grayscale8);
uint8_t *lines[1024];
QImage img(emu->getLCDWidth(), emu->getLCDHeight(), QImage::Format_Grayscale8);
for (int y = 0; y < img.height(); y++)
lines[y] = img.scanLine(y);
emu->readLCDIntoBuffer(lines);
// fetch palette
int bpp = 1 << (lcdBuf[1] >> 4);
int ppb = 8 / bpp;
uint16_t palette[16];
for (int i = 0; i < 16; i++)
palette[i] = lcdBuf[i*2] | ((lcdBuf[i*2+1] << 8) & 0xF00);
// build our image out
int lineWidth = (img.width() * bpp) / 8;
for (int y = 0; y < img.height(); y++) {
uint8_t *scanline = img.scanLine(y);
int lineOffs = 0x20 + (lineWidth * y);
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 palIdx = (byte >> shift) & mask;
int palValue = palette[palIdx];
palValue |= (palValue << 4);
scanline[x] = palValue ^ 0xFF;
}
}
#else
QImage img(320, 200, QImage::Format_Grayscale8);
uint32_t lcdControl = emu->getLCDControl();
uint64_t lcdPalette = emu->getLCDPalette();
int bpp = 1;
if (lcdControl & 0x40000000) bpp = 2;
if (lcdControl & 0x80000000) bpp = 4;
int ppb = 8 / bpp;
// build our image out
int lineWidth = (img.width() * bpp) / 8;
for (int y = 0; y < img.height(); y++) {
uint8_t *scanline = img.scanLine(y);
int lineOffs = lineWidth * y;
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 palIdx = (byte >> shift) & mask;
int palValue;
if (bpp == 1)
palValue = palIdx * 255;
else
palValue = (lcdPalette >> (palIdx * 4)) & 0xF;
palValue |= (palValue << 4);
scanline[x] = palValue ^ 0xFF;
}
}
#endif
ui->screen->setPixmap(QPixmap::fromImage(std::move(img)));
}
ui->screen->setPixmap(QPixmap::fromImage(std::move(img)));
}
@ -296,8 +239,10 @@ void MainWindow::on_stepInsnButton_clicked()
void MainWindow::execTimer()
{
emu->executeUntil(emu->currentCycles() + (CLOCK_SPEED / 64));
updateScreen();
if (emu) {
emu->executeUntil(emu->currentCycles() + (emu->getClockSpeed() / 64));
updateScreen();
}
}
void MainWindow::on_addBreakButton_clicked()
@ -332,7 +277,7 @@ void MainWindow::updateMemory()
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);
bool ok = physBaseOpt.has_value();
if (ok && (virtBase != physBase))
ui->physicalAddressLabel->setText(QStringLiteral("Physical: %1").arg(physBase, 8, 16, QLatin1Char('0')));

View File

@ -2,7 +2,7 @@
#define MAINWINDOW_H
#include <QMainWindow>
#include "../WindCore/clps7111.h"
#include "../WindCore/emubase.h"
namespace Ui {
class MainWindow;
@ -13,7 +13,7 @@ class MainWindow : public QMainWindow
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
explicit MainWindow(EmuBase *emu, QWidget *parent = nullptr);
~MainWindow() override;
private slots:
@ -44,7 +44,7 @@ private slots:
private:
Ui::MainWindow *ui;
CLPS7111 *emu;
EmuBase *emu;
QTimer *timer;
void updateScreen();
void updateBreakpointsList();