X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fgui%2Fmainwin.cpp;h=762c38660758ba834b733319303546236d545086;hb=00f18c4ebbfda2eb5a398cc3166c6ef1692c4f30;hp=782eb25834af46fdd89608e843d6b1416f96cbdf;hpb=7228359373eb7602c26f7b098d6b2271ff5727a1;p=virtualjaguar diff --git a/src/gui/mainwin.cpp b/src/gui/mainwin.cpp index 782eb25..762c386 100644 --- a/src/gui/mainwin.cpp +++ b/src/gui/mainwin.cpp @@ -38,11 +38,13 @@ #include "app.h" #include "about.h" #include "configdialog.h" +#include "controllertab.h" #include "filepicker.h" #include "gamepad.h" #include "generaltab.h" #include "glwidget.h" #include "help.h" +#include "profile.h" #include "settings.h" #include "version.h" #include "debug/cpubrowser.h" @@ -82,11 +84,19 @@ MainWin::MainWin(bool autoRun): running(true), powerButtonOn(false), showUntunedTankCircuit(true), cartridgeLoaded(false), CDActive(false), - pauseForFileSelector(false), loadAndGo(autoRun), plzDontKillMyComputer(false) + pauseForFileSelector(false), loadAndGo(autoRun), scannedSoftwareFolder(false), plzDontKillMyComputer(false) { + debugbar = NULL; + for(int i=0; i<8; i++) keyHeld[i] = false; + // FPS management + for(int i=0; isetShortcuts(QKeySequence::Quit); // quitAppAct->setShortcut(QKeySequence(tr("Alt+x"))); quitAppAct->setShortcut(QKeySequence(tr("Ctrl+q"))); + quitAppAct->setShortcutContext(Qt::ApplicationShortcut); quitAppAct->setStatusTip(tr("Quit Virtual Jaguar")); connect(quitAppAct, SIGNAL(triggered()), this, SLOT(close())); @@ -143,6 +154,7 @@ MainWin::MainWin(bool autoRun): running(true), powerButtonOn(false), pauseAct->setCheckable(true); pauseAct->setDisabled(true); pauseAct->setShortcut(QKeySequence(tr("Esc"))); + pauseAct->setShortcutContext(Qt::ApplicationShortcut); connect(pauseAct, SIGNAL(triggered()), this, SLOT(ToggleRunState())); zoomActs = new QActionGroup(this); @@ -190,11 +202,13 @@ MainWin::MainWin(bool autoRun): running(true), powerButtonOn(false), filePickAct = new QAction(QIcon(":/res/software.png"), tr("&Insert Cartridge..."), this); filePickAct->setStatusTip(tr("Insert a cartridge into Virtual Jaguar")); filePickAct->setShortcut(QKeySequence(tr("Ctrl+i"))); + filePickAct->setShortcutContext(Qt::ApplicationShortcut); connect(filePickAct, SIGNAL(triggered()), this, SLOT(InsertCart())); configAct = new QAction(QIcon(":/res/wrench.png"), tr("&Configure"), this); configAct->setStatusTip(tr("Configure options for Virtual Jaguar")); configAct->setShortcut(QKeySequence(tr("Ctrl+c"))); + configAct->setShortcutContext(Qt::ApplicationShortcut); connect(configAct, SIGNAL(triggered()), this, SLOT(Configure())); useCDAct = new QAction(QIcon(":/res/compact-disc.png"), tr("&Use CD Unit"), this); @@ -205,11 +219,13 @@ MainWin::MainWin(bool autoRun): running(true), powerButtonOn(false), frameAdvanceAct = new QAction(QIcon(":/res/frame-advance.png"), tr("&Frame Advance"), this); frameAdvanceAct->setShortcut(QKeySequence(tr("F7"))); + frameAdvanceAct->setShortcutContext(Qt::ApplicationShortcut); frameAdvanceAct->setDisabled(true); connect(frameAdvanceAct, SIGNAL(triggered()), this, SLOT(FrameAdvance())); fullScreenAct = new QAction(QIcon(":/res/fullscreen.png"), tr("F&ull Screen"), this); fullScreenAct->setShortcut(QKeySequence(tr("F9"))); + fullScreenAct->setShortcutContext(Qt::ApplicationShortcut); fullScreenAct->setCheckable(true); connect(fullScreenAct, SIGNAL(triggered()), this, SLOT(ToggleFullScreen())); @@ -295,6 +311,15 @@ MainWin::MainWin(bool autoRun): running(true), powerButtonOn(false), debugbar->addAction(riscDasmBrowseAct); } + // Add actions to the main window, as hiding widgets with them + // disables them :-P + addAction(fullScreenAct); + addAction(quitAppAct); + addAction(configAct); + addAction(pauseAct); + addAction(filePickAct); + addAction(frameAdvanceAct); + // Create status bar statusBar()->showMessage(tr("Ready")); @@ -368,6 +393,7 @@ MainWin::MainWin(bool autoRun): running(true), powerButtonOn(false), // Run the scanner if nothing passed in and *not* Alpine mode... // NB: Really need to look into caching the info scanned in here... filePickWin->ScanSoftwareFolder(allowUnknownSoftware); + scannedSoftwareFolder = true; } @@ -414,6 +440,11 @@ void MainWin::keyPressEvent(QKeyEvent * e) { // From jaguar.cpp extern bool startM68KTracing; + // From joystick.cpp + extern int blit_start_log; + // From blitter.cpp + extern bool startConciseBlitLogging; + // We ignore the Alt key for now, since it causes problems with the GUI if (e->key() == Qt::Key_Alt) @@ -427,8 +458,37 @@ void MainWin::keyPressEvent(QKeyEvent * e) e->accept(); return; } + else if (e->key() == Qt::Key_F12) + { + blit_start_log = true; + e->accept(); + return; + } + else if (e->key() == Qt::Key_F10) + { + startConciseBlitLogging = true; + e->accept(); + return; + } + else if (e->key() == Qt::Key_F8) + { + // ggn: For extra NYAN pleasure... + // ggn: There you go James :P + // Shamus: Thanks for the patch! :-D + WriteLog(" o + + +\n"); + WriteLog("+ o o + o\n"); + WriteLog("-_-_-_-_-_-_-_,------, o \n"); + WriteLog("_-_-_-_-_-_-_-| /\\_/\\ \n"); + WriteLog("-_-_-_-_-_-_-~|__( ^ .^) + + \n"); + WriteLog("_-_-_-_-_-_-_-\"\" \"\" \n"); + WriteLog("+ o o + o\n"); + WriteLog(" + +\n"); + e->accept(); + return; + } /* +This is done now by a QAction... if (e->key() == Qt::Key_F9) { ToggleFullScreen(); @@ -456,40 +516,9 @@ void MainWin::HandleKeys(QKeyEvent * e, bool state) { enum { P1LEFT = 0, P1RIGHT, P1UP, P1DOWN, P2LEFT, P2RIGHT, P2UP, P2DOWN }; // We kill bad key combos here, before they can get to the emulator... - // This also kills the illegal instruction problem that cropped up in Rayman! - // May want to do this by killing the old one instead of ignoring the new one... - // Seems to work better that way... + // This also kills the illegal instruction problem that cropped up in + // Rayman! -// The problem with this approach is that it causes bad results because it doesn't do -// any checking of previous states. Need to come up with something better because this -// causes problems where the keyboard acts as if it were unresponsive. :-P -#if 0 - if ((e->key() == vjs.p1KeyBindings[BUTTON_L] && joypad_0_buttons[BUTTON_R]) - || (e->key() == vjs.p1KeyBindings[BUTTON_R] && joypad_0_buttons[BUTTON_L]) - || (e->key() == vjs.p1KeyBindings[BUTTON_U] && joypad_0_buttons[BUTTON_D]) - || (e->key() == vjs.p1KeyBindings[BUTTON_D] && joypad_0_buttons[BUTTON_U])) - return; -#else -#if 0 - if (e->key() == (int)vjs.p1KeyBindings[BUTTON_L] && joypad_0_buttons[BUTTON_R]) - joypad_0_buttons[BUTTON_R] = 0; - if (e->key() == (int)vjs.p1KeyBindings[BUTTON_R] && joypad_0_buttons[BUTTON_L]) - joypad_0_buttons[BUTTON_L] = 0; - if (e->key() == (int)vjs.p1KeyBindings[BUTTON_U] && joypad_0_buttons[BUTTON_D]) - joypad_0_buttons[BUTTON_D] = 0; - if (e->key() == (int)vjs.p1KeyBindings[BUTTON_D] && joypad_0_buttons[BUTTON_U]) - joypad_0_buttons[BUTTON_U] = 0; - - if (e->key() == (int)vjs.p2KeyBindings[BUTTON_L] && joypad_1_buttons[BUTTON_R]) - joypad_1_buttons[BUTTON_R] = 0; - if (e->key() == (int)vjs.p2KeyBindings[BUTTON_R] && joypad_1_buttons[BUTTON_L]) - joypad_1_buttons[BUTTON_L] = 0; - if (e->key() == (int)vjs.p2KeyBindings[BUTTON_U] && joypad_1_buttons[BUTTON_D]) - joypad_1_buttons[BUTTON_D] = 0; - if (e->key() == (int)vjs.p2KeyBindings[BUTTON_D] && joypad_1_buttons[BUTTON_U]) - joypad_1_buttons[BUTTON_U] = 0; -#else -//hrm, this still has sticky state problems... Ugh! // First, settle key states... if (e->key() == (int)vjs.p1KeyBindings[BUTTON_L]) keyHeld[P1LEFT] = state; @@ -508,27 +537,27 @@ void MainWin::HandleKeys(QKeyEvent * e, bool state) else if (e->key() == (int)vjs.p2KeyBindings[BUTTON_D]) keyHeld[P2DOWN] = state; - // Next, check for conflicts and bail out if there are any... - if ((keyHeld[P1LEFT] && keyHeld[P1RIGHT]) - || (keyHeld[P1UP] && keyHeld[P1DOWN]) - || (keyHeld[P2LEFT] && keyHeld[P2RIGHT]) - || (keyHeld[P2UP] && keyHeld[P2DOWN])) - return; -#endif -#endif + // Next, check for conflicts and kill 'em if there are any... + if (keyHeld[P1LEFT] && keyHeld[P1RIGHT]) + keyHeld[P1LEFT] = keyHeld[P1RIGHT] = false; - // No bad combos exist, let's stuff the emulator key buffers...! + if (keyHeld[P1UP] && keyHeld[P1DOWN]) + keyHeld[P1UP] = keyHeld[P1DOWN] = false; + + if (keyHeld[P2LEFT] && keyHeld[P2RIGHT]) + keyHeld[P2LEFT] = keyHeld[P2RIGHT] = false; + + if (keyHeld[P2UP] && keyHeld[P2DOWN]) + keyHeld[P2UP] = keyHeld[P2DOWN] = false; + + // No bad combos exist now, let's stuff the emulator key buffers...! for(int i=BUTTON_FIRST; i<=BUTTON_LAST; i++) { if (e->key() == (int)vjs.p1KeyBindings[i]) -// joypad_0_buttons[i] = (uint8)state; - joypad_0_buttons[i] = (state ? 0x01 : 0x00); + joypad0Buttons[i] = (state ? 0x01 : 0x00); -// Pad #2 is screwing up pad #1. Prolly a problem in joystick.cpp... -// So let's try to fix it there. :-P [DONE] if (e->key() == (int)vjs.p2KeyBindings[i]) -// joypad_1_buttons[i] = (uint8)state; - joypad_1_buttons[i] = (state ? 0x01 : 0x00); + joypad1Buttons[i] = (state ? 0x01 : 0x00); } } @@ -540,10 +569,13 @@ void MainWin::HandleGamepads(void) for(int i=BUTTON_FIRST; i<=BUTTON_LAST; i++) { if (vjs.p1KeyBindings[i] & (JOY_BUTTON | JOY_HAT | JOY_AXIS)) - joypad_0_buttons[i] = (Gamepad::GetState(0, vjs.p1KeyBindings[i]) ? 0x01 : 0x00); - + joypad0Buttons[i] = (Gamepad::GetState(0, vjs.p1KeyBindings[i]) ? 0x01 : 0x00); +/*{ +if (vjs.p1KeyBindings[i] & JOY_AXIS) + printf("Axis state (HandleGamepads): %i\n", joypad0Buttons[i]); +}*/ if (vjs.p2KeyBindings[i] & (JOY_BUTTON | JOY_HAT | JOY_AXIS)) - joypad_1_buttons[i] = (Gamepad::GetState(1, vjs.p2KeyBindings[i]) ? 0x01 : 0x00); + joypad1Buttons[i] = (Gamepad::GetState(1, vjs.p2KeyBindings[i]) ? 0x01 : 0x00); } } @@ -559,6 +591,8 @@ void MainWin::Configure(void) ConfigDialog dlg(this); //ick. dlg.generalTab->useUnknownSoftware->setChecked(allowUnknownSoftware); + dlg.controllerTab1->profileNum = lastEditedProfile; + dlg.controllerTab1->SetupLastUsedProfile(); if (dlg.exec() == false) return; @@ -578,6 +612,7 @@ void MainWin::Configure(void) bool allowOld = allowUnknownSoftware; //ick. allowUnknownSoftware = dlg.generalTab->useUnknownSoftware->isChecked(); + lastEditedProfile = dlg.controllerTab1->profileNum; // We rescan the "software" folder if the user either changed the path or // checked/unchecked the "Allow unknown files" option in the config dialog. @@ -628,6 +663,16 @@ void MainWin::Configure(void) // void MainWin::Timer(void) { +#if 0 +static uint32_t ntscTickCount; + if (vjs.hardwareTypeNTSC) + { + ntscTickCount++; + ntscTickCount %= 3; + timer->start(16 + (ntscTickCount == 0 ? 1 : 0)); + } +#endif + if (!running) return; @@ -653,11 +698,37 @@ void MainWin::Timer(void) // Otherwise, run the Jaguar simulation HandleGamepads(); JaguarExecuteNew(); -// videoWidget->HideMouseIfTimedOut(); videoWidget->HandleMouseHiding(); } videoWidget->updateGL(); + + // FPS handling + // Approach: We use a ring buffer to store times (in ms) over a given + // amount of frames, then sum them to figure out the FPS. + uint32_t timestamp = SDL_GetTicks(); + // This assumes the ring buffer size is a power of 2 +// ringBufferPointer = (ringBufferPointer + 1) & (RING_BUFFER_SIZE - 1); + // Doing it this way is better. Ring buffer size can be arbitrary then. + ringBufferPointer = (ringBufferPointer + 1) % RING_BUFFER_SIZE; + ringBuffer[ringBufferPointer] = timestamp - oldTimestamp; + uint32_t elapsedTime = 0; + + for(uint32_t i=0; ishowMessage(QString("%1.%2 FPS").arg(fpsIntegerPart).arg(fpsDecimalPart)); + oldTimestamp = timestamp; } @@ -678,14 +749,14 @@ void MainWin::TogglePowerState(void) pauseAct->setDisabled(true); showUntunedTankCircuit = true; DACPauseAudioThread(); - // 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. :-) + // 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(); if (plzDontKillMyComputer) { - // We have to do it line by line, because the texture pitch is not the - // same as the picture buffer's pitch. + // We have to do it line by line, because the texture pitch is not + // the same as the picture buffer's pitch. for(uint32_t y=0; yrasterHeight; y++) { memcpy(videoWidget->buffer + (y * videoWidget->textureWidth), testPattern + (y * VIRTUAL_SCREEN_WIDTH), VIRTUAL_SCREEN_WIDTH * sizeof(uint32_t)); @@ -705,10 +776,10 @@ void MainWin::TogglePowerState(void) 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? +// 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? setWindowTitle(QString("Virtual Jaguar " VJ_RELEASE_VERSION " - Now playing: Jaguar CD")); } @@ -810,6 +881,14 @@ void MainWin::ShowHelpWin(void) void MainWin::InsertCart(void) { + // Check to see if we did autorun, 'cause we didn't load anything in that + // case + if (!scannedSoftwareFolder) + { + filePickWin->ScanSoftwareFolder(allowUnknownSoftware); + scannedSoftwareFolder = true; + } + // If the emulator is running, we pause it here and unpause it later // if we dismiss the file selector without choosing anything if (running && powerButtonOn) @@ -902,14 +981,17 @@ void MainWin::SetFullScreen(bool state/*= true*/) mainWinPosition = pos(); menuBar()->hide(); statusBar()->hide(); - x1Act->setDisabled(true); - x2Act->setDisabled(true); - x3Act->setDisabled(true); + toolbar->hide(); + + if (debugbar) + debugbar->hide(); + showFullScreen(); // This is needed because the fullscreen may happen on a different // screen than screen 0: int screenNum = QApplication::desktop()->screenNumber(videoWidget); - QRect r = QApplication::desktop()->availableGeometry(screenNum); +// QRect r = QApplication::desktop()->availableGeometry(screenNum); + QRect r = QApplication::desktop()->screenGeometry(screenNum); double targetWidth = (double)VIRTUAL_SCREEN_WIDTH, targetHeight = (double)(vjs.hardwareTypeNTSC ? VIRTUAL_SCREEN_HEIGHT_NTSC : VIRTUAL_SCREEN_HEIGHT_PAL); double aspectRatio = targetWidth / targetHeight; @@ -927,21 +1009,17 @@ void MainWin::SetFullScreen(bool state/*= true*/) // Reset the video widget to windowed mode videoWidget->offset = 0; videoWidget->fullscreen = false; - x1Act->setDisabled(false); - x2Act->setDisabled(false); - x3Act->setDisabled(false); menuBar()->show(); statusBar()->show(); + toolbar->show(); + + if (debugbar) + debugbar->show(); + showNormal(); ResizeMainWindow(); move(mainWinPosition); } - - // For some reason, this doesn't work: If the emu is paused, toggling from - // fullscreen to windowed (& vice versa) shows a white screen. - // (It was the ResizeGL() function in GLWidget: it was being called too - // much, causing the buffer to be deleted, remade & cleared.) -// videoWidget->updateGL(); } @@ -1026,6 +1104,7 @@ void MainWin::ReadSettings(void) zoomLevel = settings.value("zoom", 2).toInt(); allowUnknownSoftware = settings.value("showUnknownSoftware", false).toBool(); + lastEditedProfile = settings.value("lastEditedProfile", 0).toInt(); vjs.useJoystick = settings.value("useJoystick", false).toBool(); vjs.joyport = settings.value("joyport", 0).toInt(); @@ -1033,7 +1112,7 @@ void MainWin::ReadSettings(void) vjs.frameSkip = settings.value("frameSkip", 0).toInt(); vjs.useJaguarBIOS = settings.value("useJaguarBIOS", false).toBool(); vjs.GPUEnabled = settings.value("GPUEnabled", true).toBool(); - vjs.DSPEnabled = settings.value("DSPEnabled", false).toBool(); + vjs.DSPEnabled = settings.value("DSPEnabled", true).toBool(); vjs.audioEnabled = settings.value("audioEnabled", true).toBool(); vjs.usePipelinedDSP = settings.value("usePipelinedDSP", false).toBool(); vjs.fullscreen = settings.value("fullscreen", false).toBool(); @@ -1042,6 +1121,7 @@ void MainWin::ReadSettings(void) vjs.renderType = settings.value("renderType", 0).toInt(); vjs.allowWritesToROM = settings.value("writeROM", false).toBool(); vjs.biosType = settings.value("biosType", BT_M_SERIES).toInt(); + vjs.useFastBlitter = settings.value("useFastBlitter", false).toBool(); strcpy(vjs.EEPROMPath, settings.value("EEPROMs", "./eeproms/").toString().toAscii().data()); strcpy(vjs.ROMPath, settings.value("ROMs", "./software/").toString().toAscii().data()); strcpy(vjs.alpineROMPath, settings.value("DefaultROM", "").toString().toAscii().data()); @@ -1098,6 +1178,8 @@ WriteLog("Pipelined DSP = %s\n", (vjs.usePipelinedDSP ? "ON" : "off")); vjs.p2KeyBindings[BUTTON_9] = settings.value("p2k_9", Qt::Key_9).toInt(); vjs.p2KeyBindings[BUTTON_d] = settings.value("p2k_pound", Qt::Key_Slash).toInt(); vjs.p2KeyBindings[BUTTON_s] = settings.value("p2k_star", Qt::Key_Asterisk).toInt(); + + ReadProfiles(&settings); } @@ -1110,6 +1192,7 @@ void MainWin::WriteSettings(void) settings.setValue("zoom", zoomLevel); settings.setValue("showUnknownSoftware", allowUnknownSoftware); + settings.setValue("lastEditedProfile", lastEditedProfile); settings.setValue("useJoystick", vjs.useJoystick); settings.setValue("joyport", vjs.joyport); @@ -1126,6 +1209,7 @@ void MainWin::WriteSettings(void) settings.setValue("renderType", vjs.renderType); settings.setValue("writeROM", vjs.allowWritesToROM); settings.setValue("biosType", vjs.biosType); + settings.setValue("useFastBlitter", vjs.useFastBlitter); settings.setValue("JagBootROM", vjs.jagBootPath); settings.setValue("CDBootROM", vjs.CDBootPath); settings.setValue("EEPROMs", vjs.EEPROMPath); @@ -1176,6 +1260,8 @@ void MainWin::WriteSettings(void) settings.setValue("p2k_9", vjs.p2KeyBindings[BUTTON_9]); settings.setValue("p2k_pound", vjs.p2KeyBindings[BUTTON_d]); settings.setValue("p2k_star", vjs.p2KeyBindings[BUTTON_s]); + + WriteProfiles(&settings); } @@ -1188,3 +1274,4 @@ void MainWin::WriteUISettings(void) settings.setValue("zoom", zoomLevel); } +