]> Shamusworld >> Repos - virtualjaguar/blobdiff - src/gui/mainwin.cpp
2.0.2 release.
[virtualjaguar] / src / gui / mainwin.cpp
index 08693d01882415893540ffdaa5b964adcc38eac4..3cf2ec5a6d1ff183b9eaeebc19cc64b12b32f8d6 100644 (file)
@@ -24,6 +24,7 @@
 // - Remove SDL dependencies (sound, mainly) from Jaguar core lib
 // - Fix inconsistency with trailing slashes in paths (eeproms needs one, software doesn't)
 //
+// SFDX CODE: 9XF9TUHFM2359
 
 // Uncomment this for debugging...
 //#define DEBUG
 #include <unistd.h>
 #endif
 
-// Uncomment this to use built-in BIOS/CD-ROM BIOS
-// You'll need a copy of jagboot.h & jagcd.h for this to work...!
-// Creating those is left as an exercise for the reader. ;-)
-//#define USE_BUILT_IN_BIOS
-
-//#ifdef USE_BUILT_IN_BIOS
-//#include "jagboot.h"
-//#include "jagcd.h"
-//#endif
-
 // The way BSNES controls things is by setting a timer with a zero
 // timeout, sleeping if not emulating anything. Seems there has to be a
 // better way.
@@ -86,7 +77,6 @@ MainWin::MainWin(): running(true), powerButtonOn(false), showUntunedTankCircuit(
        videoWidget = new GLWidget(this);
        setCentralWidget(videoWidget);
        setWindowIcon(QIcon(":/res/vj-icon.png"));
-//     setWindowTitle("Virtual Jaguar v2.0.0");
 
        QString title = QString(tr("Virtual Jaguar " VJ_RELEASE_VERSION ));
 
@@ -107,18 +97,30 @@ MainWin::MainWin(): running(true), powerButtonOn(false), showUntunedTankCircuit(
        // Create actions
 
        quitAppAct = new QAction(tr("E&xit"), this);
-       quitAppAct->setShortcuts(QKeySequence::Quit);
+//     quitAppAct->setShortcuts(QKeySequence::Quit);
+//     quitAppAct->setShortcut(QKeySequence(tr("Alt+x")));
+       quitAppAct->setShortcut(QKeySequence(tr("Ctrl+q")));
        quitAppAct->setStatusTip(tr("Quit Virtual Jaguar"));
        connect(quitAppAct, SIGNAL(triggered()), this, SLOT(close()));
 
-       powerAct = new QAction(QIcon(":/res/power.png"), tr("&Power"), this);
+       powerGreen.addFile(":/res/power-off.png", QSize(), QIcon::Normal, QIcon::Off);
+       powerGreen.addFile(":/res/power-on-green.png", QSize(), QIcon::Normal, QIcon::On);
+       powerRed.addFile(":/res/power-off.png", QSize(), QIcon::Normal, QIcon::Off);
+       powerRed.addFile(":/res/power-on-red.png", QSize(), QIcon::Normal, QIcon::On);
+
+//     powerAct = new QAction(QIcon(":/res/power.png"), tr("&Power"), this);
+       powerAct = new QAction(powerGreen, tr("&Power"), this);
        powerAct->setStatusTip(tr("Powers Jaguar on/off"));
        powerAct->setCheckable(true);
        powerAct->setChecked(false);
 //     powerAct->setDisabled(true);
        connect(powerAct, SIGNAL(triggered()), this, SLOT(TogglePowerState()));
 
-       pauseAct = new QAction(QIcon(":/res/pause.png"), tr("Pause"), this);
+       QIcon pauseIcon;
+       pauseIcon.addFile(":/res/pause-off", QSize(), QIcon::Normal, QIcon::Off);
+       pauseIcon.addFile(":/res/pause-on", QSize(), QIcon::Normal, QIcon::On);
+//     pauseAct = new QAction(QIcon(":/res/pause.png"), tr("Pause"), this);
+       pauseAct = new QAction(pauseIcon, tr("Pause"), this);
        pauseAct->setStatusTip(tr("Toggles the running state"));
        pauseAct->setCheckable(true);
        pauseAct->setDisabled(true);
@@ -183,6 +185,10 @@ MainWin::MainWin(): running(true), powerButtonOn(false), showUntunedTankCircuit(
        useCDAct->setCheckable(true);
        connect(useCDAct, SIGNAL(triggered()), this, SLOT(ToggleCDUsage()));
 
+       frameAdvanceAct = new QAction(QIcon(":/res/generic.png"), tr("&Frame Advance"), this);
+       frameAdvanceAct->setShortcut(QKeySequence(tr("F7")));
+       connect(frameAdvanceAct, SIGNAL(triggered()), this, SLOT(FrameAdvance()));
+
        // Misc. connections...
        connect(filePickWin, SIGNAL(RequestLoad(QString)), this, SLOT(LoadSoftware(QString)));
        connect(filePickWin, SIGNAL(FilePickerHiding()), this, SLOT(Unpause()));
@@ -192,6 +198,7 @@ MainWin::MainWin(): running(true), powerButtonOn(false), showUntunedTankCircuit(
        fileMenu = menuBar()->addMenu(tr("&Jaguar"));
        fileMenu->addAction(powerAct);
        fileMenu->addAction(pauseAct);
+       fileMenu->addAction(frameAdvanceAct);
        fileMenu->addAction(filePickAct);
        fileMenu->addAction(useCDAct);
        fileMenu->addAction(configAct);
@@ -229,6 +236,7 @@ MainWin::MainWin(): running(true), powerButtonOn(false), showUntunedTankCircuit(
 //     running = powerAct->isChecked();
        ntscAct->setChecked(vjs.hardwareTypeNTSC);
        palAct->setChecked(!vjs.hardwareTypeNTSC);
+       powerAct->setIcon(vjs.hardwareTypeNTSC ? powerRed : powerGreen);
 
        // Do this in case original size isn't correct (mostly for the first-run case)
        ResizeMainWindow();
@@ -236,31 +244,21 @@ MainWin::MainWin(): running(true), powerButtonOn(false), showUntunedTankCircuit(
        // Set up timer based loop for animation...
        timer = new QTimer(this);
        connect(timer, SIGNAL(timeout()), this, SLOT(Timer()));
-       timer->start(20);
-
+//This is only correct for PAL. !!! FIX !!! [DONE]
+//Use timer->setInterval( int msec ) to fix this on the fly
+//     timer->start(20);
+       // This isn't very accurate for NTSC: This is early by 40 msec per frame.
+       // This is because it's discarding the 0.6666... on the end of the fraction.
+       // Alas, 6 doesn't divide cleanly into 10. :-P
+       timer->start(vjs.hardwareTypeNTSC ? 16 : 20);
+
+       // We set this initially, to make VJ behave somewhat as it would if no
+       // cart were inserted and the BIOS was set as active...
+       jaguarCartInserted = true;
        WriteLog("Virtual Jaguar %s (Last full build was on %s %s)\n", VJ_RELEASE_VERSION, __DATE__, __TIME__);
        WriteLog("VJ: Initializing jaguar subsystem...\n");
        JaguarInit();
 
-       // Get the BIOS ROM
-#ifdef USE_BUILT_IN_BIOS
-//     WriteLog("VJ: Using built in BIOS/CD BIOS...\n");
-//     memcpy(jaguarBootROM, jagBootROM, 0x20000);
-//     memcpy(jaguarCDBootROM, jagCDROM, 0x40000);
-////   BIOSLoaded = CDBIOSLoaded = true;
-//     biosAvailable |= (BIOS_NORMAL | BIOS_CD);
-#else
-// What would be nice here would be a way to check if the BIOS was loaded so that we
-// could disable the pushbutton on the Misc Options menu... !!! FIX !!! [DONE here, but needs to be fixed in GUI as well!]
-//     WriteLog("VJ: About to attempt to load BIOSes...\n");
-//This is short-circuiting the file finding thread... ??? WHY ???
-//Not anymore. Was related to a QImage object creation/corruption bug elsewhere.
-//     BIOSLoaded = (JaguarLoadROM(jaguarBootROM, vjs.jagBootPath) == 0x20000 ? true : false);
-//     WriteLog("VJ: BIOS is %savailable...\n", (BIOSLoaded ? "" : "not "));
-//     CDBIOSLoaded = (JaguarLoadROM(jaguarCDBootROM, vjs.CDBootPath) == 0x40000 ? true : false);
-//     WriteLog("VJ: CD BIOS is %savailable...\n", (CDBIOSLoaded ? "" : "not "));
-#endif
-
        filePickWin->ScanSoftwareFolder(allowUnknownSoftware);
 
        // Load up the default ROM if in Alpine mode:
@@ -280,6 +278,7 @@ MainWin::MainWin(): running(true), powerButtonOn(false), showUntunedTankCircuit(
 
                // Attempt to load/run the ABS file...
                LoadSoftware(vjs.absROMPath);
+               memcpy(jagMemSpace + 0xE00000, jaguarDevBootROM2, 0x20000);     // Use the stub BIOS
        }
        else
                memcpy(jagMemSpace + 0xE00000, jaguarBootROM, 0x20000); // Otherwise, use the stock BIOS
@@ -449,8 +448,8 @@ void MainWin::Timer(void)
                {
                        for(uint32_t y=0; y<videoWidget->rasterHeight; y++)
                        {
-                               videoWidget->buffer[(y * videoWidget->textureWidth) + x] = (rand() & 0xFF) << 8 | (rand() & 0xFF) << 16 | (rand() & 0xFF) << 24;// | (rand() & 0xFF);//0x000000FF;
-       //                      buffer[(y * textureWidth) + x] = x*y;
+                               videoWidget->buffer[(y * videoWidget->textureWidth) + x]
+                                       = (rand() & 0xFF) << 8 | (rand() & 0xFF) << 16 | (rand() & 0xFF) << 24;
                        }
                }
        }
@@ -458,10 +457,6 @@ void MainWin::Timer(void)
        {
                // Otherwise, run the Jaguar simulation
                JaguarExecuteNew();
-////           memcpy(videoWidget->buffer, backbuffer, videoWidget->rasterHeight * videoWidget->rasterWidth);
-//No longer needed--see glwidget.cpp for details!
-//             memcpy(videoWidget->buffer, backbuffer, videoWidget->rasterHeight * videoWidget->textureWidth * sizeof(uint32_t));
-////           memcpy(surface->pixels, backbuffer, TOMGetVideoModeWidth() * TOMGetVideoModeHeight() * 4);
        }
 
        videoWidget->updateGL();
@@ -470,47 +465,44 @@ void MainWin::Timer(void)
 void MainWin::TogglePowerState(void)
 {
        powerButtonOn = !powerButtonOn;
+       running = true;
 
        // With the power off, we simulate white noise on the screen. :-)
        if (!powerButtonOn)
        {
+               useCDAct->setDisabled(false);
+               palAct->setDisabled(false);
+               ntscAct->setDisabled(false);
                pauseAct->setChecked(false);
                pauseAct->setDisabled(true);
                showUntunedTankCircuit = true;
-               running = true;
                // This is just in case the ROM we were playing was in a narrow or wide field mode,
                // so the untuned tank sim doesn't look wrong. :-)
                TOMReset();
        }
        else
        {
-//NOTE: Low hanging fruit: We can simplify this a lot...
+               useCDAct->setDisabled(true);
+               palAct->setDisabled(true);
+               ntscAct->setDisabled(true);
+               pauseAct->setChecked(false);
+               pauseAct->setDisabled(false);
+               showUntunedTankCircuit = false;
+
                // Otherwise, we prepare for running regular software...
-               if (!CDActive)
-               {
-                       showUntunedTankCircuit = false;//(cartridgeLoaded ? false : true);
-                       pauseAct->setChecked(false);
-                       pauseAct->setDisabled(false);//!cartridgeLoaded);
-               }
-               // Or, set up for the Jaguar CD
-               else
+               if (CDActive)
                {
 // Should check for cartridgeLoaded here as well...!
 // We can clear it when toggling CDActive on, so that when we power cycle it does the
 // expected thing. Otherwise, if we use the file picker to insert a cart, we expect
 // to run the cart! Maybe have a RemoveCart function that only works if the CD unit
 // is active?
-                       showUntunedTankCircuit = false;
-                       pauseAct->setChecked(false);
-                       pauseAct->setDisabled(false);
-                       memcpy(jagMemSpace + 0x800000, jaguarCDBootROM, 0x40000);
                        setWindowTitle(QString("Virtual Jaguar " VJ_RELEASE_VERSION
                                " - Now playing: Jaguar CD"));
                }
 
                WriteLog("GUI: Resetting Jaguar...\n");
                JaguarReset();
-               running = true;
        }
 }
 
@@ -522,14 +514,12 @@ void MainWin::ToggleRunState(void)
        {
                for(uint32_t i=0; i<(uint32_t)(videoWidget->textureWidth * 256); i++)
                {
-                       uint32_t pixel = backbuffer[i];
+                       uint32_t pixel = videoWidget->buffer[i];
                        uint8_t r = (pixel >> 24) & 0xFF, g = (pixel >> 16) & 0xFF, b = (pixel >> 8) & 0xFF;
                        pixel = ((r + g + b) / 3) & 0x00FF;
-                       backbuffer[i] = 0x000000FF | (pixel << 16) | (pixel << 8);
+                       videoWidget->buffer[i] = 0x000000FF | (pixel << 16) | (pixel << 8);
                }
 
-               memcpy(videoWidget->buffer, backbuffer, videoWidget->rasterHeight * videoWidget->textureWidth * sizeof(uint32_t));
-
                videoWidget->updateGL();
        }
 }
@@ -554,12 +544,16 @@ void MainWin::SetZoom300(void)
 
 void MainWin::SetNTSC(void)
 {
+       powerAct->setIcon(powerRed);
+       timer->setInterval(16);
        vjs.hardwareTypeNTSC = true;
        ResizeMainWindow();
 }
 
 void MainWin::SetPAL(void)
 {
+       powerAct->setIcon(powerGreen);
+       timer->setInterval(20);
        vjs.hardwareTypeNTSC = false;
        ResizeMainWindow();
 }
@@ -598,7 +592,10 @@ void MainWin::Unpause(void)
        if (pauseForFileSelector)
        {
                pauseForFileSelector = false;
-               ToggleRunState();
+
+               // Some nutter might have unpaused while in the file selector, so check for that
+               if (!running)
+                       ToggleRunState();
        }
 }
 
@@ -642,9 +639,23 @@ void MainWin::ToggleCDUsage(void)
        {
                powerAct->setDisabled(true);
        }
+#else
+       // Set up the Jaguar CD for execution, otherwise, clear memory
+       if (CDActive)
+               memcpy(jagMemSpace + 0x800000, jaguarCDBootROM, 0x40000);
+       else
+               memset(jagMemSpace + 0x800000, 0xFF, 0x40000);
 #endif
 }
 
+void MainWin::FrameAdvance(void)
+{
+//printf("Frame Advance...\n");
+       // Execute 1 frame, then exit (only useful in Pause mode)
+       JaguarExecuteNew();
+       videoWidget->updateGL();
+}
+
 void MainWin::ResizeMainWindow(void)
 {
        videoWidget->setFixedSize(zoomLevel * 320, zoomLevel * (vjs.hardwareTypeNTSC ? 240 : 256));
@@ -820,90 +831,3 @@ void MainWin::WriteSettings(void)
        settings.setValue("p2k_pound", vjs.p2KeyBindings[BUTTON_d]);
        settings.setValue("p2k_star", vjs.p2KeyBindings[BUTTON_s]);
 }
-
-// Here's how Byuu does it...
-// I think I have it working now... :-)
-#if 0
-void Utility::resizeMainWindow()
-{
-  unsigned region = config().video.context->region;
-  unsigned multiplier = config().video.context->multiplier;
-  unsigned width = 256 * multiplier;
-  unsigned height = (region == 0 ? 224 : 239) * multiplier;
-
-  if(config().video.context->correctAspectRatio)
-  {
-    if(region == 0)
-       {
-      width = (double)width * config().video.ntscAspectRatio + 0.5;  //NTSC adjust
-    }
-       else
-       {
-      width = (double)width * config().video.palAspectRatio  + 0.5;  //PAL adjust
-    }
-  }
-
-  if(config().video.isFullscreen == false)
-  {
-    //get effective desktop work area region (ignore Windows taskbar, OS X dock, etc.)
-    QRect deskRect = QApplication::desktop()->availableGeometry(mainWindow);
-
-    //ensure window size will not be larger than viewable desktop area
-    constrainSize(height, width, deskRect.height()); //- frameHeight);
-    constrainSize(width, height, deskRect.width());  //- frameWidth );
-
-    mainWindow->canvas->setFixedSize(width, height);
-    mainWindow->show();
-  }
-  else
-  {
-    for(unsigned i = 0; i < 2; i++)
-       {
-      unsigned iWidth = width, iHeight = height;
-
-      constrainSize(iHeight, iWidth, mainWindow->canvasContainer->size().height());
-      constrainSize(iWidth, iHeight, mainWindow->canvasContainer->size().width());
-
-      //center canvas onscreen; ensure it is not larger than viewable area
-      mainWindow->canvas->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
-      mainWindow->canvas->setFixedSize(iWidth, iHeight);
-      mainWindow->canvas->setMinimumSize(0, 0);
-
-      usleep(2000);
-      QApplication::processEvents();
-    }
-  }
-
-  //workaround for Qt/Xlib bug:
-  //if window resize occurs with cursor over it, Qt shows Qt::Size*DiagCursor;
-  //so force it to show Qt::ArrowCursor, as expected
-  mainWindow->setCursor(Qt::ArrowCursor);
-  mainWindow->canvasContainer->setCursor(Qt::ArrowCursor);
-  mainWindow->canvas->setCursor(Qt::ArrowCursor);
-
-  //workaround for DirectSound(?) bug:
-  //window resizing sometimes breaks audio sync, this call re-initializes it
-  updateAvSync();
-}
-
-void Utility::setScale(unsigned scale)
-{
-  config().video.context->multiplier = scale;
-  resizeMainWindow();
-  mainWindow->shrink();
-  mainWindow->syncUi();
-}
-
-void QbWindow::shrink()
-{
-  if(config().video.isFullscreen == false)
-  {
-    for(unsigned i = 0; i < 2; i++)
-       {
-      resize(0, 0);
-      usleep(2000);
-      QApplication::processEvents();
-    }
-  }
-}
-#endif