From f8baa0eb85eca16abaac371466824ff5cca8afce Mon Sep 17 00:00:00 2001 From: meepingsnesroms Date: Thu, 27 Dec 2018 14:56:01 -0800 Subject: [PATCH] See description below Fix FIFO incaauracys. Remove extra left shift on SPI1 data after the final bit is in. Remove old image when last state is deleted. Set active state to the newest one on save state and update image accordingly. Set spi1RxOverflowed to false on boot. Move variables to top of function in mainwindow constructor. --- qtBuildSystem/Mu/emuwrapper.cpp | 2 +- qtBuildSystem/Mu/emuwrapper.h | 2 +- qtBuildSystem/Mu/mainwindow.cpp | 48 ++++++++++++++++-------------- qtBuildSystem/Mu/statemanager.cpp | 34 ++++++++++++++++----- qtBuildSystem/Mu/statemanager.h | 4 +-- src/hardwareRegisters.c | 2 ++ src/hardwareRegistersAccessors.c.h | 30 ++++++++++--------- src/sdCard.c | 2 ++ 8 files changed, 75 insertions(+), 49 deletions(-) diff --git a/qtBuildSystem/Mu/emuwrapper.cpp b/qtBuildSystem/Mu/emuwrapper.cpp index d815040..d274e2b 100644 --- a/qtBuildSystem/Mu/emuwrapper.cpp +++ b/qtBuildSystem/Mu/emuwrapper.cpp @@ -316,7 +316,7 @@ uint32_t EmuWrapper::loadState(const QString& path){ return error; } -uint32_t EmuWrapper::installApplication(QString path){ +uint32_t EmuWrapper::installApplication(const QString& path){ bool wasPaused = isPaused(); uint32_t error = EMU_ERROR_INVALID_PARAMETER; QFile appFile(path); diff --git a/qtBuildSystem/Mu/emuwrapper.h b/qtBuildSystem/Mu/emuwrapper.h index 432c2ee..c68f92d 100644 --- a/qtBuildSystem/Mu/emuwrapper.h +++ b/qtBuildSystem/Mu/emuwrapper.h @@ -43,7 +43,7 @@ public: bool isRunning() const{return emuRunning;} bool isPaused() const{return emuPaused;} - uint32_t installApplication(QString path); + uint32_t installApplication(const QString& path); std::vector& getDebugStrings(); std::vector& getDuplicateCallCount(); diff --git a/qtBuildSystem/Mu/mainwindow.cpp b/qtBuildSystem/Mu/mainwindow.cpp index d23ae94..27e08c0 100644 --- a/qtBuildSystem/Mu/mainwindow.cpp +++ b/qtBuildSystem/Mu/mainwindow.cpp @@ -53,9 +53,10 @@ void printLastRun(){ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow){ - ui->setupUi(this); - QAudioFormat format; + QString resourceDirPath; + + //audio output format.setSampleRate(AUDIO_SAMPLE_RATE); format.setChannelCount(2); format.setSampleSize(16); @@ -67,6 +68,7 @@ MainWindow::MainWindow(QWidget* parent) : #endif format.setSampleType(QAudioFormat::SignedInt); + //submodules settings = new QSettings(QDir::homePath() + "/MuCfg.txt", QSettings::IniFormat);//settings is public, create it first stateManager = new StateManager(this); emuDebugger = new DebugViewer(this); @@ -74,6 +76,27 @@ MainWindow::MainWindow(QWidget* parent) : audioDevice = new QAudioOutput(format, this); audioOut = audioDevice->start(); + //resource directory + resourceDirPath = settings->value("resourceDirectory", "").toString(); + + //get default path if path not set + if(resourceDirPath == ""){ +#if defined(Q_OS_ANDROID) + resourceDirPath = "/sdcard/Mu"; +#elif defined(Q_OS_IOS) + resourceDirPath = "/var/mobile/Media/Mu"; +#else + resourceDirPath = QDir::homePath() + "/Mu"; +#endif + settings->setValue("resourceDirectory", resourceDirPath); + } + + //create directory tree, in case someone deleted it since the emu was last run or it was never created + createHomeDirectoryTree(resourceDirPath); + + //GUI + ui->setupUi(this); + //this makes the display window and button icons resize properly ui->centralWidget->installEventFilter(this); ui->centralWidget->setObjectName("centralWidget"); @@ -97,29 +120,9 @@ MainWindow::MainWindow(QWidget* parent) : ui->screenshot->installEventFilter(this); ui->stateManager->installEventFilter(this); - - QString resourceDirPath = settings->value("resourceDirectory", "").toString(); - - //use default path if path not set - if(resourceDirPath == ""){ -#if defined(Q_OS_ANDROID) - resourceDirPath = "/sdcard/Mu"; -#elif defined(Q_OS_IOS) - resourceDirPath = "/var/mobile/Media/Mu"; -#else - resourceDirPath = QDir::homePath() + "/Mu"; -#endif - settings->setValue("resourceDirectory", resourceDirPath); - } - - //create directory tree, in case someone deleted it since the emu was last run - createHomeDirectoryTree(resourceDirPath); - - #if !defined(EMU_DEBUG) || defined(Q_OS_ANDROID) || defined(Q_OS_IOS) ui->debugger->hide(); #endif - connect(refreshDisplay, SIGNAL(timeout()), this, SLOT(updateDisplay())); refreshDisplay->start(1000 / EMU_FPS);//update display every X milliseconds } @@ -372,7 +375,6 @@ void MainWindow::on_stateManager_clicked(){ if(!wasPaused) emu.pause(); - stateManager->updateStateList(); stateManager->exec(); if(!wasPaused) diff --git a/qtBuildSystem/Mu/statemanager.cpp b/qtBuildSystem/Mu/statemanager.cpp index 2bfab5f..d03879c 100644 --- a/qtBuildSystem/Mu/statemanager.cpp +++ b/qtBuildSystem/Mu/statemanager.cpp @@ -20,12 +20,21 @@ StateManager::StateManager(QWidget* parent) : //this allows resizing the screenshot of the savestate ui->statePreview->installEventFilter(this); ui->statePreview->setObjectName("statePreview"); + + updateStateList(); } StateManager::~StateManager(){ delete ui; } +bool StateManager::eventFilter(QObject* object, QEvent* event){ + if(object->objectName() == "statePreview" && event->type() == QEvent::Resize) + updateStatePreview(); + + return QDialog::eventFilter(object, event); +} + void StateManager::updateStateList(){ MainWindow* parent = (MainWindow*)parentWidget(); QString saveDirPath = parent->settings->value("resourceDirectory", "").toString() + "/saveStates"; @@ -47,21 +56,27 @@ void StateManager::updateStateList(){ } } -bool StateManager::eventFilter(QObject* object, QEvent* event){ - if(object->objectName() == "statePreview" && event->type() == QEvent::Resize) - updateStatePreview(); - - return QDialog::eventFilter(object, event); -} - void StateManager::updateStatePreview(){ if(ui->states->currentItem()){ MainWindow* parent = (MainWindow*)parentWidget(); QString statePath = parent->settings->value("resourceDirectory", "").toString() + "/saveStates/" + ui->states->currentItem()->text(); ui->statePreview->setPixmap(QPixmap(statePath + ".png").scaled(ui->statePreview->width() * 0.98, ui->statePreview->height() * 0.98, Qt::KeepAspectRatio, Qt::SmoothTransformation)); - ui->statePreview->update(); } + else{ + //remove outdated image + ui->statePreview->clear(); + } + + ui->statePreview->update(); +} + +int StateManager::getStateIndexRowByName(const QString& name){ + for(int index = 0; index < ui->states->count(); index++) + if(ui->states->item(index)->text() == name) + return index; + + return -1;//nothing by that name exists } void StateManager::on_saveState_clicked(){ @@ -72,6 +87,8 @@ void StateManager::on_saveState_clicked(){ parent->emu.saveState(statePath + ".state"); parent->emu.getFramebuffer().save(statePath + ".png"); updateStateList(); + + ui->states->setCurrentRow(getStateIndexRowByName(ui->newStateName->text()));//this also updates the preview image } } @@ -92,6 +109,7 @@ void StateManager::on_deleteState_clicked(){ QFile(statePath + ".state").remove(); QFile(statePath + ".png").remove(); updateStateList(); + ui->states->setCurrentRow(0);//pick first valid entry since the old one is no longer valid } } diff --git a/qtBuildSystem/Mu/statemanager.h b/qtBuildSystem/Mu/statemanager.h index b3758e4..95834b1 100644 --- a/qtBuildSystem/Mu/statemanager.h +++ b/qtBuildSystem/Mu/statemanager.h @@ -16,12 +16,12 @@ public: explicit StateManager(QWidget* parent = nullptr); ~StateManager(); - void updateStateList(); - private slots: bool eventFilter(QObject* object, QEvent* event); + void updateStateList(); void updateStatePreview(); + int getStateIndexRowByName(const QString& name); void on_saveState_clicked(); void on_loadState_clicked(); diff --git a/src/hardwareRegisters.c b/src/hardwareRegisters.c index 6fc6806..4caf73d 100644 --- a/src/hardwareRegisters.c +++ b/src/hardwareRegisters.c @@ -434,6 +434,7 @@ uint16_t getHwRegister16(uint32_t address){ uint16_t fifoVal = spi1RxFifoRead(); //check if SPI1 interrupts changed setSpiIntCs(registerArrayRead16(SPIINTCS)); + debugLog("SPIRXD read, FIFO value:0x%04X, SPIINTCS:0x%04X\n", fifoVal, registerArrayRead16(SPIINTCS)); return fifoVal; } @@ -1020,6 +1021,7 @@ void resetHwRegisters(void){ memset(spi1TxFifo, 0x00, sizeof(spi1TxFifo)); spi1RxReadPosition = 0; spi1RxWritePosition = 0; + spi1RxOverflowed = false; spi1TxReadPosition = 0; spi1TxWritePosition = 0; pwm1ClocksToNextSample = 0; diff --git a/src/hardwareRegistersAccessors.c.h b/src/hardwareRegistersAccessors.c.h index fdb3495..1fa759f 100644 --- a/src/hardwareRegistersAccessors.c.h +++ b/src/hardwareRegistersAccessors.c.h @@ -40,21 +40,22 @@ static uint8_t spi1RxFifoEntrys(void){ } static uint16_t spi1RxFifoRead(void){ - uint16_t value = spi1RxFifo[spi1RxReadPosition]; if(spi1RxFifoEntrys() > 0) spi1RxReadPosition = (spi1RxReadPosition + 1) % 9; spi1RxOverflowed = false; - return value; + + return spi1RxFifo[spi1RxReadPosition]; } static void spi1RxFifoWrite(uint16_t value){ if(spi1RxFifoEntrys() < 8){ spi1RxWritePosition = (spi1RxWritePosition + 1) % 9; - spi1RxFifo[spi1RxWritePosition] = value; } else{ spi1RxOverflowed = true; + debugLog("SPI1 RX FIFO overflowed\n"); } + spi1RxFifo[spi1RxWritePosition] = value; } static void spi1RxFifoFlush(void){ @@ -69,10 +70,9 @@ static uint8_t spi1TxFifoEntrys(void){ } static uint16_t spi1TxFifoRead(void){ - uint16_t value = spi1TxFifo[spi1TxReadPosition]; //dont need a safety check here, the emulator will always check that data is present before trying to access it spi1TxReadPosition = (spi1TxReadPosition + 1) % 9; - return value; + return spi1TxFifo[spi1TxReadPosition]; } static void spi1TxFifoWrite(uint16_t value){ @@ -95,7 +95,6 @@ static uint8_t pwm1FifoEntrys(void){ } int32_t pwm1FifoRunSample(int32_t now, int32_t clockOffset){ - uint8_t sample = pwm1Fifo[pwm1ReadPosition]; uint16_t period = registerArrayRead8(PWMP1) + 2; uint16_t pwmc1 = registerArrayRead16(PWMC1); uint8_t prescaler = (pwmc1 >> 8 & 0x7F) + 1; @@ -103,9 +102,14 @@ int32_t pwm1FifoRunSample(int32_t now, int32_t clockOffset){ uint8_t repeat = 1 << (pwmc1 >> 2 & 0x03); int32_t audioNow = now + clockOffset; int32_t audioSampleDuration = (pwmc1 & 0x8000)/*CLKSRC*/ ? audioGetFramePercentIncrementFromClk32s(period * prescaler * clockDivider) : audioGetFramePercentIncrementFromSysclks(period * prescaler * clockDivider); - float dutyCycle = fMin((float)sample / period, 1.00); + float dutyCycle; uint8_t index; + //try to get next sample, if none are available play old sample + if(pwm1FifoEntrys() > 0) + pwm1ReadPosition = (pwm1ReadPosition + 1) % 6; + dutyCycle = fMin((float)pwm1Fifo[pwm1ReadPosition] / period, 1.00); + for(index = 0; index < repeat; index++){ #if !defined(EMU_NO_SAFETY) if(audioNow + audioSampleDuration >= AUDIO_CLOCK_RATE) @@ -117,10 +121,6 @@ int32_t pwm1FifoRunSample(int32_t now, int32_t clockOffset){ audioNow += audioSampleDuration; } - //remove used entry - if(pwm1FifoEntrys() > 0) - pwm1ReadPosition = (pwm1ReadPosition + 1) % 6; - //check for interrupt if(pwm1FifoEntrys() < 2){ //trigger interrupt if enabled @@ -336,7 +336,7 @@ static void setSpiIntCs(uint16_t value){ newSpiIntCs |= (rxEntrys >= 4) << 4;//RH newSpiIntCs |= (rxEntrys > 0) << 3;//RR newSpiIntCs |= (txEntrys == 8) << 2;//TF - newSpiIntCs |= (txEntrys >= 4) << 1;//TH + newSpiIntCs |= (txEntrys >= 4) << 1;//TH, the datasheet contradicts itself on whether its more than or equal to 4 empty or full slots newSpiIntCs |= txEntrys == 0;//TE //if interrupt state changed update interrupts too, top 8 bits are just the enable bits for the bottom 8 @@ -358,7 +358,7 @@ static void setSpiCont1(uint16_t value){ //debugLog("SPICONT1 write, old value:0x%04X, value:0x%04X\n", oldSpiCont1, value); //SPI1 disabled - if(oldSpiCont1 & 0x0200 && !(value & 0x2000)){ + if(oldSpiCont1 & 0x0200 && !(value & 0x0200)){ spi1RxFifoFlush(); spi1TxFifoFlush(); } @@ -380,8 +380,8 @@ static void setSpiCont1(uint16_t value){ //The most significant bit is output when the CPU loads the transmitted data, 13.2.3 SPI 1 Phase and Polarity Configurations MC68VZ328UM.pdf for(bits = 0; bits < bitCount; bits++){ - newRxFifoEntry |= sdCardExchangeBit(!!(currentTxFifoEntry & startBit)); newRxFifoEntry <<= 1; + newRxFifoEntry |= sdCardExchangeBit(!!(currentTxFifoEntry & startBit)); currentTxFifoEntry <<= 1; } @@ -398,6 +398,8 @@ static void setSpiCont1(uint16_t value){ //update SPIINTCS interrupt bits setSpiIntCs(registerArrayRead16(SPIINTCS)); + debugLog("Transfer complete, SPIINTCS:0x%04X\n", registerArrayRead16(SPIINTCS)); + registerArrayWrite16(SPICONT1, value); } diff --git a/src/sdCard.c b/src/sdCard.c index c5ed9c2..f0495c2 100644 --- a/src/sdCard.c +++ b/src/sdCard.c @@ -67,6 +67,7 @@ static void sdCardDoResponseR1(uint8_t r1){ palmSdCard.response = SD_CARD_RESPONSE_SHIFT_OUT; palmSdCard.responseState = (uint64_t)r1 << 56; palmSdCard.responseState |= (uint64_t)1 << 55;//add shift termination bit + //palmSdCard.responseState >>= 8; } static void sdCardDoResponseR3(uint8_t r1){ @@ -74,6 +75,7 @@ static void sdCardDoResponseR3(uint8_t r1){ palmSdCard.responseState = (uint64_t)r1 << 56; palmSdCard.responseState |= (uint64_t)sdCardOcr << 24; palmSdCard.responseState |= (uint64_t)1 << 23;//add shift termination bit + //palmSdCard.responseState >>= 8; } void sdCardReset(void){