#include "mainwin.h"
-//#include <QtGui>
-//#include <QtOpenGL>
+#include "SDL.h"
#include "glwidget.h"
#include "about.h"
#include "settings.h"
#include "filepicker.h"
+#include "configdialog.h"
+#include "version.h"
#include "jaguar.h"
-#include "video.h"
#include "tom.h"
#include "log.h"
#include "file.h"
+#include "joystick.h"
+
+#ifdef __GCCWIN32__
+// Apparently on win32, usleep() is not pulled in by the usual suspects.
+#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...!
//#define USE_BUILT_IN_BIOS
-// Uncomment this for an official Virtual Jaguar release
-//#define VJ_RELEASE_VERSION "2.0.0"
-#warning !!! FIX !!! Figure out how to use this in GUI.CPP as well!
-
#ifdef USE_BUILT_IN_BIOS
#include "jagboot.h"
#include "jagcd.h"
videoWidget = new GLWidget(this);
setCentralWidget(videoWidget);
setWindowIcon(QIcon(":/res/vj-icon.png"));
- setWindowTitle("Virtual Jaguar v2.0.0");
+// setWindowTitle("Virtual Jaguar v2.0.0");
+ setWindowTitle("Virtual Jaguar " VJ_RELEASE_VERSION );
- ReadSettings();
- setUnifiedTitleAndToolBarOnMac(true);
-
-#warning "!!! Save/Restore window location for FilePickerWindow !!!"
aboutWin = new AboutWindow(this);
filePickWin = new FilePickerWindow(this);
videoWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ ReadSettings();
+ setUnifiedTitleAndToolBarOnMac(true);
+
// Create actions
quitAppAct = new QAction(tr("E&xit"), this);
pauseAct->setStatusTip(tr("Toggles the running state"));
pauseAct->setCheckable(true);
pauseAct->setDisabled(true);
+ pauseAct->setShortcut(QKeySequence(tr("Esc")));
connect(pauseAct, SIGNAL(triggered()), this, SLOT(ToggleRunState()));
zoomActs = new QActionGroup(this);
tvTypeActs = new QActionGroup(this);
- ntscAct = new QAction(QIcon(":/res/generic.png"), tr("NTSC"), tvTypeActs);
+ ntscAct = new QAction(QIcon(":/res/ntsc.png"), tr("NTSC"), tvTypeActs);
ntscAct->setStatusTip(tr("Sets Jaguar to NTSC mode"));
ntscAct->setCheckable(true);
connect(ntscAct, SIGNAL(triggered()), this, SLOT(SetNTSC()));
- palAct = new QAction(QIcon(":/res/generic.png"), tr("PAL"), tvTypeActs);
+ palAct = new QAction(QIcon(":/res/pal.png"), tr("PAL"), tvTypeActs);
palAct->setStatusTip(tr("Sets Jaguar to PAL mode"));
palAct->setCheckable(true);
connect(palAct, SIGNAL(triggered()), this, SLOT(SetPAL()));
blurAct->setCheckable(true);
connect(blurAct, SIGNAL(triggered()), this, SLOT(ToggleBlur()));
- aboutAct = new QAction(QIcon(":/res/generic.png"), tr("&About..."), this);
+ aboutAct = new QAction(QIcon(":/res/vj-icon.png"), tr("&About..."), this);
aboutAct->setStatusTip(tr("Blatant self-promotion"));
connect(aboutAct, SIGNAL(triggered()), this, SLOT(ShowAboutWin()));
-#warning "!!! Set up a decent keyboard shortcut for Insert Cartridge !!!"
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")));
connect(filePickAct, SIGNAL(triggered()), this, SLOT(InsertCart()));
+ configAct = new QAction(QIcon(":/res/generic.png"), tr("&Configure"), this);
+ configAct->setStatusTip(tr("Configure options for Virtual Jaguar"));
+ configAct->setShortcut(QKeySequence(tr("Ctrl+c")));
+ connect(configAct, SIGNAL(triggered()), this, SLOT(Configure()));
+
// Misc. connections...
connect(filePickWin, SIGNAL(RequestLoad(QString)), this, SLOT(LoadSoftware(QString)));
fileMenu->addAction(filePickAct);
fileMenu->addAction(powerAct);
fileMenu->addAction(pauseAct);
+ fileMenu->addAction(configAct);
fileMenu->addAction(quitAppAct);
helpMenu = menuBar()->addMenu(tr("&Help"));
connect(timer, SIGNAL(timeout()), this, SLOT(Timer()));
timer->start(20);
- // NOTE: Keyboards/joysticks will *not* work until SDL is brought back in, or
- // the key handling is improved in Qt...
- // Wait a minute... it seems they already are... So why no keyboard love?
-
-#ifdef VJ_RELEASE_VERSION
WriteLog("Virtual Jaguar %s (Last full build was on %s %s)\n", VJ_RELEASE_VERSION, __DATE__, __TIME__);
-#else
- WriteLog("Virtual Jaguar SVN %s (Last full build was on %s %s)\n", __DATE__, __DATE__, __TIME__);
-#endif
- WriteLog("Initializing jaguar subsystem...\n");
+ WriteLog("VJ: Initializing jaguar subsystem...\n");
JaguarInit();
// Get the BIOS ROM
#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("About to attempt to load BIOSes...\n");
-#if 1
+ 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);
-#else
- BIOSLoaded = false;
-#endif
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
-
- SET32(jaguarMainRAM, 0, 0x00200000); // Set top of stack...
-
-//Let's try this...
-// JaguarLoadFile("./software/Rayman (World).j64");
-// JaguarLoadFile("./software/I-War (World).j64");
-// JaguarLoadFile("./software/Alien vs Predator (World).j64");
-//no JaguarLoadFile("./software/battlesphere.bin");
-// JaguarLoadFile("./software/Battle Sphere Gold (World).j64");
-// JaguarLoadFile("./software/Rayman (USA, Europe).zip");
-//This is crappy!!! !!! FIX !!!
-//Is this even needed any more? Hmm. Maybe. Dunno.
-//Seems like it is... But then again, maybe not. Have to test it to see.
-//WriteLog("GUI: Resetting Jaguar...\n");
-// JaguarReset();
}
void MainWin::closeEvent(QCloseEvent * event)
event->accept(); // ignore() if can't close for some reason
}
+void MainWin::keyPressEvent(QKeyEvent * e)
+{
+ HandleKeys(e, true);
+}
+
+void MainWin::keyReleaseEvent(QKeyEvent * e)
+{
+ HandleKeys(e, false);
+}
+
+void MainWin::HandleKeys(QKeyEvent * e, bool state)
+{
+ // 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...
+#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 (e->key() == vjs.p1KeyBindings[BUTTON_L] && joypad_0_buttons[BUTTON_R])
+ joypad_0_buttons[BUTTON_R] = 0;
+ if (e->key() == vjs.p1KeyBindings[BUTTON_R] && joypad_0_buttons[BUTTON_L])
+ joypad_0_buttons[BUTTON_L] = 0;
+ if (e->key() == vjs.p1KeyBindings[BUTTON_U] && joypad_0_buttons[BUTTON_D])
+ joypad_0_buttons[BUTTON_D] = 0;
+ if (e->key() == vjs.p1KeyBindings[BUTTON_D] && joypad_0_buttons[BUTTON_U])
+ joypad_0_buttons[BUTTON_U] = 0;
+#endif
+
+ // No bad combos exist, let's stuff the emulator key buffers...!
+ for(int i=BUTTON_FIRST; i<=BUTTON_LAST; i++)
+ {
+ if (e->key() == vjs.p1KeyBindings[i])
+ joypad_0_buttons[i] = (uint8)state;
+ }
+}
+
void MainWin::Open(void)
{
}
+void MainWin::Configure(void)
+{
+ // Call the configuration dialog and update settings
+ ConfigDialog dlg(this);
+
+ if (dlg.exec() == false)
+ return;
+
+ dlg.UpdateVJSettings();
+}
+
//
// Here's the main emulator loop
//
else
{
showUntunedTankCircuit = (cartridgeLoaded ? false : true);
+ pauseAct->setChecked(false);
pauseAct->setDisabled(!cartridgeLoaded);
+
+//(Err, what's so crappy about this? It seems to do what it's supposed to...)
//This is crappy!!! !!! FIX !!!
//Is this even needed any more? Hmm. Maybe. Dunno.
//Seems like it is... But then again, maybe not. Have to test it to see.
void MainWin::LoadSoftware(QString file)
{
running = false; // Prevent bad things(TM) from happening...
- SET32(jaguarMainRAM, 0, 0x00200000); // Set top of stack...
+ SET32(jaguarMainRAM, 0, 0x00200000); // Set top of stack...
cartridgeLoaded = (JaguarLoadFile(file.toAscii().data()) ? true : false);
-#if 0
- showUntunedTankCircuit = !cartridgeLoaded;
-//This is crappy!!! !!! FIX !!!
-//Is this even needed any more? Hmm. Maybe. Dunno.
-//Seems like it is... But then again, maybe not. Have to test it to see.
- WriteLog("GUI: Resetting Jaguar...\n");
- JaguarReset();
- running = true;
-#else
powerAct->setDisabled(false);
powerAct->setChecked(true);
powerButtonOn = false;
TogglePowerState();
-#endif
- QString newTitle = QString("Virtual Jaguar 2.0.0 - Now playing: %1")
+// QString newTitle = QString("Virtual Jaguar v2.0.0 - Now playing: %1")
+ QString newTitle = QString("Virtual Jaguar " VJ_RELEASE_VERSION
+ " - Now playing: %1")
.arg(filePickWin->GetSelectedPrettyName());
setWindowTitle(newTitle);
}
QSize size = settings.value("size", QSize(400, 400)).toSize();
resize(size);
move(pos);
+ pos = settings.value("cartLoadPos", QPoint(200, 200)).toPoint();
+ filePickWin->move(pos);
zoomLevel = settings.value("zoom", 1).toInt();
WriteLog(" CDBootPath = \"%s\"\n", vjs.CDBootPath);
WriteLog(" EEPROMPath = \"%s\"\n", vjs.EEPROMPath);
WriteLog(" ROMPath = \"%s\"\n", vjs.ROMPath);
+
+ // Keybindings in order of U, D, L, R, C, B, A, Op, Pa, 0-9, #, *
+ vjs.p1KeyBindings[BUTTON_U] = settings.value("p1k_up", Qt::Key_Up).toInt();
+ vjs.p1KeyBindings[BUTTON_D] = settings.value("p1k_down", Qt::Key_Down).toInt();
+ vjs.p1KeyBindings[BUTTON_L] = settings.value("p1k_left", Qt::Key_Left).toInt();
+ vjs.p1KeyBindings[BUTTON_R] = settings.value("p1k_right", Qt::Key_Right).toInt();
+ vjs.p1KeyBindings[BUTTON_C] = settings.value("p1k_c", Qt::Key_Z).toInt();
+ vjs.p1KeyBindings[BUTTON_B] = settings.value("p1k_b", Qt::Key_X).toInt();
+ vjs.p1KeyBindings[BUTTON_A] = settings.value("p1k_a", Qt::Key_C).toInt();
+ vjs.p1KeyBindings[BUTTON_OPTION] = settings.value("p1k_option", Qt::Key_Apostrophe).toInt();
+ vjs.p1KeyBindings[BUTTON_PAUSE] = settings.value("p1k_pause", Qt::Key_Return).toInt();
+ vjs.p1KeyBindings[BUTTON_0] = settings.value("p1k_0", Qt::Key_0).toInt();
+ vjs.p1KeyBindings[BUTTON_1] = settings.value("p1k_1", Qt::Key_1).toInt();
+ vjs.p1KeyBindings[BUTTON_2] = settings.value("p1k_2", Qt::Key_2).toInt();
+ vjs.p1KeyBindings[BUTTON_3] = settings.value("p1k_3", Qt::Key_3).toInt();
+ vjs.p1KeyBindings[BUTTON_4] = settings.value("p1k_4", Qt::Key_4).toInt();
+ vjs.p1KeyBindings[BUTTON_5] = settings.value("p1k_5", Qt::Key_5).toInt();
+ vjs.p1KeyBindings[BUTTON_6] = settings.value("p1k_6", Qt::Key_6).toInt();
+ vjs.p1KeyBindings[BUTTON_7] = settings.value("p1k_7", Qt::Key_7).toInt();
+ vjs.p1KeyBindings[BUTTON_8] = settings.value("p1k_8", Qt::Key_8).toInt();
+ vjs.p1KeyBindings[BUTTON_9] = settings.value("p1k_9", Qt::Key_9).toInt();
+ vjs.p1KeyBindings[BUTTON_d] = settings.value("p1k_pound", Qt::Key_Slash).toInt();
+ vjs.p1KeyBindings[BUTTON_s] = settings.value("p1k_star", Qt::Key_Asterisk).toInt();
+
+ vjs.p2KeyBindings[BUTTON_U] = settings.value("p2k_up", Qt::Key_Up).toInt();
+ vjs.p2KeyBindings[BUTTON_D] = settings.value("p2k_down", Qt::Key_Down).toInt();
+ vjs.p2KeyBindings[BUTTON_L] = settings.value("p2k_left", Qt::Key_Left).toInt();
+ vjs.p2KeyBindings[BUTTON_R] = settings.value("p2k_right", Qt::Key_Right).toInt();
+ vjs.p2KeyBindings[BUTTON_C] = settings.value("p2k_c", Qt::Key_Z).toInt();
+ vjs.p2KeyBindings[BUTTON_B] = settings.value("p2k_b", Qt::Key_X).toInt();
+ vjs.p2KeyBindings[BUTTON_A] = settings.value("p2k_a", Qt::Key_C).toInt();
+ vjs.p2KeyBindings[BUTTON_OPTION] = settings.value("p2k_option", Qt::Key_Apostrophe).toInt();
+ vjs.p2KeyBindings[BUTTON_PAUSE] = settings.value("p2k_pause", Qt::Key_Return).toInt();
+ vjs.p2KeyBindings[BUTTON_0] = settings.value("p2k_0", Qt::Key_0).toInt();
+ vjs.p2KeyBindings[BUTTON_1] = settings.value("p2k_1", Qt::Key_1).toInt();
+ vjs.p2KeyBindings[BUTTON_2] = settings.value("p2k_2", Qt::Key_2).toInt();
+ vjs.p2KeyBindings[BUTTON_3] = settings.value("p2k_3", Qt::Key_3).toInt();
+ vjs.p2KeyBindings[BUTTON_4] = settings.value("p2k_4", Qt::Key_4).toInt();
+ vjs.p2KeyBindings[BUTTON_5] = settings.value("p2k_5", Qt::Key_5).toInt();
+ vjs.p2KeyBindings[BUTTON_6] = settings.value("p2k_6", Qt::Key_6).toInt();
+ vjs.p2KeyBindings[BUTTON_7] = settings.value("p2k_7", Qt::Key_7).toInt();
+ vjs.p2KeyBindings[BUTTON_8] = settings.value("p2k_8", Qt::Key_8).toInt();
+ 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();
}
void MainWin::WriteSettings(void)
QSettings settings("Underground Software", "Virtual Jaguar");
settings.setValue("pos", pos());
settings.setValue("size", size());
+ settings.setValue("cartLoadPos", filePickWin->pos());
settings.setValue("zoom", zoomLevel);
settings.setValue("CDBootROM", vjs.CDBootPath);
settings.setValue("EEPROMs", vjs.EEPROMPath);
settings.setValue("ROMs", vjs.ROMPath);
+
+ settings.setValue("p1k_up", vjs.p1KeyBindings[BUTTON_U]);
+ settings.setValue("p1k_down", vjs.p1KeyBindings[BUTTON_D]);
+ settings.setValue("p1k_left", vjs.p1KeyBindings[BUTTON_L]);
+ settings.setValue("p1k_right", vjs.p1KeyBindings[BUTTON_R]);
+ settings.setValue("p1k_c", vjs.p1KeyBindings[BUTTON_C]);
+ settings.setValue("p1k_b", vjs.p1KeyBindings[BUTTON_B]);
+ settings.setValue("p1k_a", vjs.p1KeyBindings[BUTTON_A]);
+ settings.setValue("p1k_option", vjs.p1KeyBindings[BUTTON_OPTION]);
+ settings.setValue("p1k_pause", vjs.p1KeyBindings[BUTTON_PAUSE]);
+ settings.setValue("p1k_0", vjs.p1KeyBindings[BUTTON_0]);
+ settings.setValue("p1k_1", vjs.p1KeyBindings[BUTTON_1]);
+ settings.setValue("p1k_2", vjs.p1KeyBindings[BUTTON_2]);
+ settings.setValue("p1k_3", vjs.p1KeyBindings[BUTTON_3]);
+ settings.setValue("p1k_4", vjs.p1KeyBindings[BUTTON_4]);
+ settings.setValue("p1k_5", vjs.p1KeyBindings[BUTTON_5]);
+ settings.setValue("p1k_6", vjs.p1KeyBindings[BUTTON_6]);
+ settings.setValue("p1k_7", vjs.p1KeyBindings[BUTTON_7]);
+ settings.setValue("p1k_8", vjs.p1KeyBindings[BUTTON_8]);
+ settings.setValue("p1k_9", vjs.p1KeyBindings[BUTTON_9]);
+ settings.setValue("p1k_pound", vjs.p1KeyBindings[BUTTON_d]);
+ settings.setValue("p1k_star", vjs.p1KeyBindings[BUTTON_s]);
+
+ settings.setValue("p2k_up", vjs.p2KeyBindings[BUTTON_U]);
+ settings.setValue("p2k_down", vjs.p2KeyBindings[BUTTON_D]);
+ settings.setValue("p2k_left", vjs.p2KeyBindings[BUTTON_L]);
+ settings.setValue("p2k_right", vjs.p2KeyBindings[BUTTON_R]);
+ settings.setValue("p2k_c", vjs.p2KeyBindings[BUTTON_C]);
+ settings.setValue("p2k_b", vjs.p2KeyBindings[BUTTON_B]);
+ settings.setValue("p2k_a", vjs.p2KeyBindings[BUTTON_A]);
+ settings.setValue("p2k_option", vjs.p2KeyBindings[BUTTON_OPTION]);
+ settings.setValue("p2k_pause", vjs.p2KeyBindings[BUTTON_PAUSE]);
+ settings.setValue("p2k_0", vjs.p2KeyBindings[BUTTON_0]);
+ settings.setValue("p2k_1", vjs.p2KeyBindings[BUTTON_1]);
+ settings.setValue("p2k_2", vjs.p2KeyBindings[BUTTON_2]);
+ settings.setValue("p2k_3", vjs.p2KeyBindings[BUTTON_3]);
+ settings.setValue("p2k_4", vjs.p2KeyBindings[BUTTON_4]);
+ settings.setValue("p2k_5", vjs.p2KeyBindings[BUTTON_5]);
+ settings.setValue("p2k_6", vjs.p2KeyBindings[BUTTON_6]);
+ settings.setValue("p2k_7", vjs.p2KeyBindings[BUTTON_7]);
+ settings.setValue("p2k_8", vjs.p2KeyBindings[BUTTON_8]);
+ settings.setValue("p2k_9", vjs.p2KeyBindings[BUTTON_9]);
+ settings.setValue("p2k_pound", vjs.p2KeyBindings[BUTTON_d]);
+ settings.setValue("p2k_star", vjs.p2KeyBindings[BUTTON_s]);
}
// Here's how Byuu does it...