Rename GPLv3 document as LICENSE, to fit better the GitHub requirements. Text / Licen...
[clinton/Virtual-Jaguar-Rx.git] / src / gui / mainwin.cpp
CommitLineData
cf76e892
JPM
1//
2// mainwin.cpp - Qt-based GUI for Virtual Jaguar: Main Application Window
3// by James Hammons
4// (C) 2009 Underground Software
5//
6// JLH = James Hammons <jlhamm@acm.org>
7// JPM = Jean-Paul Mari <djipi.mari@gmail.com>
8//
9// Who When What
10// --- ---------- ------------------------------------------------------------
11// JLH 12/23/2009 Created this file
12// JLH 12/20/2010 Added settings, menus & toolbars
13// JLH 07/05/2011 Added CD BIOS functionality to GUI
14// JPM 06/06/2016 Visual Studio support
15// JPM 06/19/2016 Soft debugger integration
16// JPM 01/11/2017 Added stack browser
17// JPM 01/02/2017 Added GPU disassembly
18// JPM 02/02/2017 Added DSP disassembly
19// JPM 07/12/2017 Added all Watch browser window
20// JPM 08/01/2017 Added heap allocator browser window
21// JPM 08/07/2017 Added memories window browser
22// JPM 08/10/2017 Added a restart feature
23// JPM 08/31/2017 Added breakpoints winndow
24// JPM 09/01/2017 Save position & visibility windows status in the settings
25// JPM 09/02/2017 Save size windows in the settings
26// JPM 09/05/2017 Added Exception Vector Table window
27// JPM 09/06/2017 Added the 'Rx' word to the emulator window name
28
29//
30
31// FIXED:
32//
33// - Add dbl click/enter to select in cart list, ESC to dimiss [DONE]
34// - Autoscan/autoload all available BIOS from 'software' folder [DONE]
35// - Add 1 key jumping in cartridge list (press 'R', jumps to carts starting
36// with 'R', etc) [DONE]
37// - Controller configuration [DONE]
38//
39// STILL TO BE DONE:
40//
41// - Fix bug in switching between PAL & NTSC in fullscreen mode.
42// - Remove SDL dependencies (sound, mainly) from Jaguar core lib
43// - Fix inconsistency with trailing slashes in paths (eeproms needs one,
44// software doesn't)
45//
46// SFDX CODE: S1E9T8H5M23YS
47
48// Uncomment this for debugging...
49//#define DEBUG
be44e757
JPM
50//#define DEBUGFOO // Various tool debugging... but not used
51//#define DEBUGTP // Toolpalette debugging... but not used
cf76e892
JPM
52
53#include "mainwin.h"
54
55#include "SDL.h"
56#include "app.h"
57#include "about.h"
58#include "configdialog.h"
59#include "controllertab.h"
60#include "filepicker.h"
61#include "gamepad.h"
62#include "generaltab.h"
63#include "glwidget.h"
64#include "help.h"
65#include "profile.h"
66#include "settings.h"
67#include "version.h"
68#include "emustatus.h"
69#include "debug/cpubrowser.h"
70#include "debug/m68kdasmbrowser.h"
71#include "debug/memorybrowser.h"
72#include "debug/stackbrowser.h"
73#include "debug/opbrowser.h"
74#include "debug/riscdasmbrowser.h"
75
76#include "debugger/allwatchbrowser.h"
77#include "debugger/heapallocatorbrowser.h"
78
79#include "dac.h"
80#include "jaguar.h"
81#include "log.h"
82#include "file.h"
83#include "jagbios.h"
84#include "jagbios2.h"
85#include "jagcdbios.h"
86#include "jagstub2bios.h"
87#include "joystick.h"
88#include "m68000/m68kinterface.h"
89
90#include "debugger/VideoWin.h"
91#include "debugger/DasmWin.h"
92#include "debugger/m68KDasmWin.h"
93#include "debugger/GPUDasmWin.h"
94#include "debugger/DSPDasmWin.h"
95#include "debugger/memory1browser.h"
96#include "debugger/brkWin.h"
97#include "debugger/exceptionvectortablebrowser.h"
98
99// According to SebRmv, this header isn't seen on Arch Linux either... :-/
100//#ifdef __GCCWIN32__
101// Apparently on win32, usleep() is not pulled in by the usual suspects.
102#ifndef _MSC_VER
103#include <unistd.h>
104#else
105#include "_MSC_VER/unistd.h"
106#endif // !_MSC_VER
107//#endif
108
109// The way BSNES controls things is by setting a timer with a zero
110// timeout, sleeping if not emulating anything. Seems there has to be a
111// better way.
112
113// It has a novel approach to plugging-in/using different video/audio/input
114// methods, can we do something similar or should we just use the built-in
115// QOpenGL?
116
117// We're going to try to use the built-in OpenGL support and see how it goes.
118// We'll make the VJ core modular so that it doesn't matter what GUI is in
119// use, we can drop it in anywhere and use it as-is.
120
121MainWin::MainWin(bool autoRun): running(true), powerButtonOn(false),
122 showUntunedTankCircuit(true), cartridgeLoaded(false), CDActive(false),
123 pauseForFileSelector(false), loadAndGo(autoRun), scannedSoftwareFolder(false), plzDontKillMyComputer(false)
124{
125 ReadSettings();
126
127 debugbar = NULL;
128
129 for(int i=0; i<8; i++)
130 keyHeld[i] = false;
131
132 // FPS management
133 for(int i=0; i<RING_BUFFER_SIZE; i++)
134 ringBuffer[i] = 0;
135
136 ringBufferPointer = RING_BUFFER_SIZE - 1;
137
138 // main window
139 //if (vjs.softTypeDebugger)
140 //{
141 // mainWindowCentrale = new QMdiArea;
142 // setCentralWidget(mainWindowCentrale);
143 //}
144
145 // video output
146 videoWidget = new GLWidget(this);
147 videoWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
148
149 // set central output window
150 if (!vjs.softTypeDebugger)
151 {
152 setCentralWidget(videoWidget);
153 }
154 else
155 {
156 mainWindowCentrale = new QMdiArea(this);
157 setCentralWidget(mainWindowCentrale);
158 }
159
160 setWindowIcon(QIcon(":/res/vj-icon.png"));
161
5fe21518 162 QString title = QString(tr("Virtual Jaguar " VJ_RELEASE_VERSION " Rx"));
cf76e892
JPM
163
164 if (vjs.hardwareTypeAlpine)
165 title += QString(tr(" - Alpine Mode"));
166
167 if (vjs.softTypeDebugger)
168 title += QString(tr(" - Debugger Mode"));
169
170 setWindowTitle(title);
171
172 aboutWin = new AboutWindow(this);
173 helpWin = new HelpWindow(this);
174 filePickWin = new FilePickerWindow(this);
175 memBrowseWin = new MemoryBrowserWindow(this);
176 stackBrowseWin = new StackBrowserWindow(this);
177 emuStatusWin = new EmuStatusWindow(this);
178 cpuBrowseWin = new CPUBrowserWindow(this);
179 opBrowseWin = new OPBrowserWindow(this);
180 m68kDasmBrowseWin = new M68KDasmBrowserWindow(this);
181 riscDasmBrowseWin = new RISCDasmBrowserWindow(this);
182 if (vjs.softTypeDebugger)
183 {
184 VideoOutputWin = new VideoOutputWindow(this);
185 //VideoOutputWin->setCentralWidget()
186 //DasmWin = new DasmWindow();
187 DasmWin = new DasmWindow(this);
188 allWatchBrowseWin = new AllWatchBrowserWindow(this);
189 heapallocatorBrowseWin = new HeapAllocatorBrowserWindow(this);
190 brkWin = new BrkWindow(this);
191 exceptionvectortableBrowseWin = new ExceptionVectorTableBrowserWindow(this);
192
193 mem1BrowseWin = (Memory1BrowserWindow **)calloc(vjs.nbrmemory1browserwindow, sizeof(Memory1BrowserWindow));
194#ifdef _MSC_VER
195#pragma message("Warning: !!! Need to do the memory desalocation for mem1BrowseWin !!!")
196#else
197 #warning "!!! Need to do the memory desalocation for mem1BrowseWin !!!"
198#endif // _MSC_VER
199 for (size_t i = 0; i < vjs.nbrmemory1browserwindow; i++)
200 {
201 mem1BrowseWin[i] = new Memory1BrowserWindow(this);
202 }
203
204 dasmtabWidget = new QTabWidget(this);
205 dasmtabWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
206 dasmtabWidget->addTab(m68kDasmWin = new m68KDasmWindow(this), tr("M68000"));
207 dasmtabWidget->addTab(GPUDasmWin = new GPUDasmWindow(this), tr("GPU"));
208 dasmtabWidget->addTab(DSPDasmWin = new DSPDasmWindow(this), tr("DSP"));
209 ////dasmtabWidget->addTab(m68kDasmBrowseWin, tr("M68000"));
210 setCentralWidget(dasmtabWidget);
211
212#if 0
213 QDockWidget *shapesDockWidget = new QDockWidget(tr("Shapes"));
214 shapesDockWidget->setObjectName("shapesDockWidget");
215 shapesDockWidget->setWidget(m68kDasmWin);
216 //shapesDockWidget->setWidget(treeWidget);
217 shapesDockWidget->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
218 addDockWidget(Qt::LeftDockWidgetArea, shapesDockWidget);
219#endif
220 }
221
222// videoWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
223 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
224
225 setUnifiedTitleAndToolBarOnMac(true);
226
227 // Create actions
228
229 quitAppAct = new QAction(tr("E&xit"), this);
230// quitAppAct->setShortcuts(QKeySequence::Quit);
231// quitAppAct->setShortcut(QKeySequence(tr("Alt+x")));
232 quitAppAct->setShortcut(QKeySequence(tr("Ctrl+q")));
233 quitAppAct->setShortcutContext(Qt::ApplicationShortcut);
234 quitAppAct->setStatusTip(tr("Quit Virtual Jaguar"));
235 connect(quitAppAct, SIGNAL(triggered()), this, SLOT(close()));
236
237 powerGreen.addFile(":/res/power-off.png", QSize(), QIcon::Normal, QIcon::Off);
238 powerGreen.addFile(":/res/power-on-green.png", QSize(), QIcon::Normal, QIcon::On);
239 powerRed.addFile(":/res/power-off.png", QSize(), QIcon::Normal, QIcon::Off);
240 powerRed.addFile(":/res/power-on-red.png", QSize(), QIcon::Normal, QIcon::On);
241
242 powerAct = new QAction(powerGreen, tr("&Power"), this);
243 powerAct->setStatusTip(tr("Powers Jaguar on/off"));
244 powerAct->setCheckable(true);
245 powerAct->setChecked(false);
246 connect(powerAct, SIGNAL(triggered()), this, SLOT(TogglePowerState()));
247
248 QIcon pauseIcon;
249 pauseIcon.addFile(":/res/pause-off", QSize(), QIcon::Normal, QIcon::Off);
250 pauseIcon.addFile(":/res/pause-on", QSize(), QIcon::Normal, QIcon::On);
251 pauseAct = new QAction(pauseIcon, tr("Pause"), this);
252 pauseAct->setStatusTip(tr("Toggles the running state"));
253 pauseAct->setCheckable(true);
254 pauseAct->setDisabled(true);
255 pauseAct->setShortcut(QKeySequence(tr("Esc")));
256 pauseAct->setShortcutContext(Qt::ApplicationShortcut);
257 connect(pauseAct, SIGNAL(triggered()), this, SLOT(ToggleRunState()));
258
259 zoomActs = new QActionGroup(this);
260
261 x1Act = new QAction(QIcon(":/res/zoom100.png"), tr("Zoom 100%"), zoomActs);
262 x1Act->setStatusTip(tr("Set window zoom to 100%"));
263 x1Act->setCheckable(true);
264 connect(x1Act, SIGNAL(triggered()), this, SLOT(SetZoom100()));
265
266 x2Act = new QAction(QIcon(":/res/zoom200.png"), tr("Zoom 200%"), zoomActs);
267 x2Act->setStatusTip(tr("Set window zoom to 200%"));
268 x2Act->setCheckable(true);
269 connect(x2Act, SIGNAL(triggered()), this, SLOT(SetZoom200()));
270
271 x3Act = new QAction(QIcon(":/res/zoom300.png"), tr("Zoom 300%"), zoomActs);
272 x3Act->setStatusTip(tr("Set window zoom to 300%"));
273 x3Act->setCheckable(true);
274 connect(x3Act, SIGNAL(triggered()), this, SLOT(SetZoom300()));
275
276 tvTypeActs = new QActionGroup(this);
277
278 ntscAct = new QAction(QIcon(":/res/ntsc.png"), tr("NTSC"), tvTypeActs);
279 ntscAct->setStatusTip(tr("Sets Jaguar to NTSC mode"));
280 ntscAct->setCheckable(true);
281 connect(ntscAct, SIGNAL(triggered()), this, SLOT(SetNTSC()));
282
283 palAct = new QAction(QIcon(":/res/pal.png"), tr("PAL"), tvTypeActs);
284 palAct->setStatusTip(tr("Sets Jaguar to PAL mode"));
285 palAct->setCheckable(true);
286 connect(palAct, SIGNAL(triggered()), this, SLOT(SetPAL()));
287
288 blur.addFile(":/res/blur-off.png", QSize(), QIcon::Normal, QIcon::Off);
289 blur.addFile(":/res/blur-on.png", QSize(), QIcon::Normal, QIcon::On);
290
291 blurAct = new QAction(blur, tr("Blur"), this);
292 blurAct->setStatusTip(tr("Sets OpenGL rendering to GL_NEAREST"));
293 blurAct->setCheckable(true);
294 connect(blurAct, SIGNAL(triggered()), this, SLOT(ToggleBlur()));
295
296 aboutAct = new QAction(QIcon(":/res/vj-icon.png"), tr("&About..."), this);
297 aboutAct->setStatusTip(tr("Blatant self-promotion"));
298 connect(aboutAct, SIGNAL(triggered()), this, SLOT(ShowAboutWin()));
299
300 helpAct = new QAction(QIcon(":/res/vj-icon.png"), tr("&Contents..."), this);
301 helpAct->setStatusTip(tr("Help is available, if you should need it"));
302 connect(helpAct, SIGNAL(triggered()), this, SLOT(ShowHelpWin()));
303
304 if (!vjs.softTypeDebugger)
305 {
306 filePickAct = new QAction(QIcon(":/res/software.png"), tr("&Insert Cartridge..."), this);
307 filePickAct->setStatusTip(tr("Insert a cartridge into Virtual Jaguar"));
308 }
309 else
310 {
311 filePickAct = new QAction(QIcon(":/res/software.png"), tr("&Insert executable file..."), this);
312 filePickAct->setStatusTip(tr("Insert an executable into Virtual Jaguar"));
313 }
314 filePickAct->setShortcut(QKeySequence(tr("Ctrl+i")));
315 filePickAct->setShortcutContext(Qt::ApplicationShortcut);
316 connect(filePickAct, SIGNAL(triggered()), this, SLOT(InsertCart()));
317
318 configAct = new QAction(QIcon(":/res/wrench.png"), tr("&Configure"), this);
319 configAct->setStatusTip(tr("Configure options for Virtual Jaguar"));
320 configAct->setShortcut(QKeySequence(tr("Ctrl+c")));
321 configAct->setShortcutContext(Qt::ApplicationShortcut);
322 connect(configAct, SIGNAL(triggered()), this, SLOT(Configure()));
323
324 emustatusAct = new QAction(QIcon(""), tr("&Status"), this);
325 emustatusAct->setStatusTip(tr("Emulator status"));
326 emustatusAct->setShortcut(QKeySequence(tr("Ctrl+s")));
327 emustatusAct->setShortcutContext(Qt::ApplicationShortcut);
328 connect(emustatusAct, SIGNAL(triggered()), this, SLOT(ShowEmuStatusWin()));
329
330 useCDAct = new QAction(QIcon(":/res/compact-disc.png"), tr("&Use CD Unit"), this);
331 useCDAct->setStatusTip(tr("Use Jaguar Virtual CD unit"));
332// useCDAct->setShortcut(QKeySequence(tr("Ctrl+c")));
333 useCDAct->setCheckable(true);
334 connect(useCDAct, SIGNAL(triggered()), this, SLOT(ToggleCDUsage()));
335
336 frameAdvanceAct = new QAction(QIcon(":/res/frame-advance.png"), tr("&Frame Advance"), this);
337 frameAdvanceAct->setShortcut(QKeySequence(tr("F7")));
338 frameAdvanceAct->setShortcutContext(Qt::ApplicationShortcut);
339 frameAdvanceAct->setDisabled(true);
340 connect(frameAdvanceAct, SIGNAL(triggered()), this, SLOT(FrameAdvance()));
341
342 if (vjs.softTypeDebugger)
343 {
344 restartAct = new QAction(QIcon(":/res/Restart.png"), tr("&Restart"), this);
345 restartAct->setShortcut(QKeySequence(tr("Ctrl+Shift+F5")));
346 restartAct->setShortcutContext(Qt::ApplicationShortcut);
347 restartAct->setCheckable(false);
348 restartAct->setDisabled(true);
349 connect(restartAct, SIGNAL(triggered()), this, SLOT(Restart()));
350
351 traceStepOverAct = new QAction(QIcon(":/res/StepOver.png"), tr("&Step Over"), this);
352 traceStepOverAct->setShortcut(QKeySequence(tr("F10")));
353 traceStepOverAct->setShortcutContext(Qt::ApplicationShortcut);
354 traceStepOverAct->setCheckable(false);
355 traceStepOverAct->setDisabled(true);
356 connect(traceStepOverAct, SIGNAL(triggered()), this, SLOT(TraceStepOver()));
357
358 traceStepIntoAct = new QAction(QIcon(":/res/StepInto.png"), tr("&Step Into"), this);
359 traceStepIntoAct->setShortcut(QKeySequence(tr("F11")));
360 traceStepIntoAct->setShortcutContext(Qt::ApplicationShortcut);
361 traceStepIntoAct->setCheckable(false);
362 traceStepIntoAct->setDisabled(true);
363 connect(traceStepIntoAct, SIGNAL(triggered()), this, SLOT(TraceStepInto()));
364
365 newBreakpointFunctionAct = new QAction(QIcon(""), tr("&Function Breakpoint"), this);
366 newBreakpointFunctionAct->setShortcut(QKeySequence(tr("Ctrl+B")));
367 connect(newBreakpointFunctionAct, SIGNAL(triggered()), this, SLOT(NewBreakpointFunction()));
368 }
369
370 fullScreenAct = new QAction(QIcon(":/res/fullscreen.png"), tr("F&ull Screen"), this);
371 fullScreenAct->setShortcut(QKeySequence(tr("F9")));
372 fullScreenAct->setShortcutContext(Qt::ApplicationShortcut);
373 fullScreenAct->setCheckable(true);
374 connect(fullScreenAct, SIGNAL(triggered()), this, SLOT(ToggleFullScreen()));
375
376 // Debugger Actions
377 if (vjs.softTypeDebugger)
378 {
379 exceptionVectorTableBrowseAct = new QAction(QIcon(""), tr("Exception Vector Table"), this);
380 exceptionVectorTableBrowseAct->setStatusTip(tr("Shows all Exception Vector Table browser window"));
381 connect(exceptionVectorTableBrowseAct, SIGNAL(triggered()), this, SLOT(ShowExceptionVectorTableBrowserWin()));
382
383 allWatchBrowseAct = new QAction(QIcon(":/res/Watch.png"), tr("All Watch"), this);
384 allWatchBrowseAct->setStatusTip(tr("Shows all Watch browser window"));
385 connect(allWatchBrowseAct, SIGNAL(triggered()), this, SLOT(ShowAllWatchBrowserWin()));
386
387 heapallocatorBrowseAct = new QAction(QIcon(""), tr("Heap allocator"), this);
388 heapallocatorBrowseAct->setStatusTip(tr("Shows the heap allocator browser window"));
389 connect(heapallocatorBrowseAct, SIGNAL(triggered()), this, SLOT(ShowHeapAllocatorBrowserWin()));
390
391 mem1BrowseAct = (QAction **)calloc(vjs.nbrmemory1browserwindow, sizeof(QAction));
392 QSignalMapper *signalMapper = new QSignalMapper(this);
393#ifdef _MSC_VER
394#pragma message("Warning: !!! Need to do the memory desalocation for mem1BrowseAct !!!")
395#else
396#warning "!!! Need to do the memory desalocation for mem1BrowseAct !!!"
397#endif // _MSC_VER
398 for (int i = 0; i < vjs.nbrmemory1browserwindow; i++)
399 {
400 char MB[100];
401 sprintf(MB, "Memory %i", (unsigned int)(i+1));
402 mem1BrowseAct[i] = new QAction(QIcon(":/res/tool-memory.png"), tr(MB), this);
403 mem1BrowseAct[i]->setStatusTip(tr("Shows a Jaguar memory browser window"));
404 //mem1BrowseAct[i]->
405 //connect(mem1BrowseAct[0], SIGNAL(triggered()), this, SLOT(ShowMemory1BrowserWin(size_t(0))));
406 connect(mem1BrowseAct[i], SIGNAL(triggered()), signalMapper, SLOT(map()));
407 signalMapper->setMapping(mem1BrowseAct[i], (int)i);
408 connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(ShowMemory1BrowserWin(int)));
409 }
410 }
411
412 // Debugger Browser Actions
413 memBrowseAct = new QAction(QIcon(":/res/tool-memory.png"), tr("Memory Browser"), this);
414 memBrowseAct->setStatusTip(tr("Shows the Jaguar memory browser window"));
415// memBrowseAct->setCheckable(true);
416 connect(memBrowseAct, SIGNAL(triggered()), this, SLOT(ShowMemoryBrowserWin()));
417
418 stackBrowseAct = new QAction(QIcon(":/res/tool-stack.png"), tr("Stack Browser"), this);
419 stackBrowseAct->setStatusTip(tr("Shows the Jaguar stack browser window"));
420 // memBrowseAct->setCheckable(true);
421 connect(stackBrowseAct, SIGNAL(triggered()), this, SLOT(ShowStackBrowserWin()));
422
423 cpuBrowseAct = new QAction(QIcon(":/res/tool-cpu.png"), tr("CPU Browser"), this);
424 cpuBrowseAct->setStatusTip(tr("Shows the Jaguar CPU browser window"));
425// memBrowseAct->setCheckable(true);
426 connect(cpuBrowseAct, SIGNAL(triggered()), this, SLOT(ShowCPUBrowserWin()));
427
428 opBrowseAct = new QAction(QIcon(":/res/tool-op.png"), tr("OP Browser"), this);
429 opBrowseAct->setStatusTip(tr("Shows the Jaguar OP browser window"));
430// memBrowseAct->setCheckable(true);
431 connect(opBrowseAct, SIGNAL(triggered()), this, SLOT(ShowOPBrowserWin()));
432
433 m68kDasmBrowseAct = new QAction(QIcon(":/res/tool-68k-dis.png"), tr("68K Listing Browser"), this);
434 m68kDasmBrowseAct->setStatusTip(tr("Shows the 68K disassembly browser window"));
435// memBrowseAct->setCheckable(true);
436 connect(m68kDasmBrowseAct, SIGNAL(triggered()), this, SLOT(ShowM68KDasmBrowserWin()));
437
438 riscDasmBrowseAct = new QAction(QIcon(":/res/tool-risc-dis.png"), tr("RISC Listing Browser"), this);
439 riscDasmBrowseAct->setStatusTip(tr("Shows the RISC disassembly browser window"));
440// memBrowseAct->setCheckable(true);
441 connect(riscDasmBrowseAct, SIGNAL(triggered()), this, SLOT(ShowRISCDasmBrowserWin()));
442
443 if (vjs.softTypeDebugger)
444 {
445 VideoOutputAct = new QAction(tr("Output Video"), this);
446 VideoOutputAct->setStatusTip(tr("Shows the output video window"));
447 connect(VideoOutputAct, SIGNAL(triggered()), this, SLOT(ShowVideoOutputWin()));
448
449 DasmAct = new QAction(tr("Disassembly"), this);
450 DasmAct->setStatusTip(tr("Shows the disassembly window"));
451 connect(DasmAct, SIGNAL(triggered()), this, SLOT(ShowDasmWin()));
452 }
453
454 // Misc. connections...
455 connect(filePickWin, SIGNAL(RequestLoad(QString)), this, SLOT(LoadSoftware(QString)));
456 connect(filePickWin, SIGNAL(FilePickerHiding()), this, SLOT(Unpause()));
457
458 // Create menus
459
460 fileMenu = menuBar()->addMenu(tr("&Jaguar"));
461 fileMenu->addAction(powerAct);
462 if (!vjs.softTypeDebugger)
463 {
464 fileMenu->addAction(pauseAct);
465 // fileMenu->addAction(frameAdvanceAct);
466 }
467 fileMenu->addAction(filePickAct);
468 fileMenu->addAction(useCDAct);
469 fileMenu->addAction(configAct);
470 fileMenu->addAction(emustatusAct);
471 fileMenu->addSeparator();
472 fileMenu->addAction(quitAppAct);
473
474 if (vjs.hardwareTypeAlpine || vjs.softTypeDebugger)
475 {
476 debugMenu = menuBar()->addMenu(tr("&Debug"));
477 if (vjs.softTypeDebugger)
478 {
479 debugWindowsMenu = debugMenu->addMenu(tr("&Windows"));
480 debugWindowExceptionMenu = debugWindowsMenu->addMenu(tr("&Exception"));
481 debugWindowExceptionMenu->addAction(exceptionVectorTableBrowseAct);
482 debugWindowsMenu->addSeparator();
483#if 0
484 debugWindowOutputMenu = debugWindowsMenu->addMenu(tr("&Output"));
485 debugWindowOutputMenu->addAction(VideoOutputAct);
486 debugWindowsMenu->addSeparator();
487#endif
488 debugWindowsWatchMenu = debugWindowsMenu->addMenu(tr("&Watch"));
489 debugWindowsWatchMenu->addAction(allWatchBrowseAct);
490 debugWindowsMenu->addSeparator();
491 debugWindowsMemoryMenu = debugWindowsMenu->addMenu(tr("&Memory"));
492 debugWindowsMemoryMenu->addAction(heapallocatorBrowseAct);
493 debugWindowsMemoryMenu->addSeparator();
494 for (int i = 0; i < vjs.nbrmemory1browserwindow; i++)
495 {
496 debugWindowsMemoryMenu->addAction(mem1BrowseAct[i]);
497 }
498 debugWindowsMenu->addSeparator();
499 debugWindowsBrowsesMenu = debugWindowsMenu->addMenu(tr("&Browsers"));
500 debugWindowsBrowsesMenu->addAction(memBrowseAct);
501 debugWindowsBrowsesMenu->addAction(stackBrowseAct);
502 debugWindowsBrowsesMenu->addAction(cpuBrowseAct);
503 debugWindowsBrowsesMenu->addAction(opBrowseAct);
504 debugWindowsBrowsesMenu->addAction(m68kDasmBrowseAct);
505 debugWindowsBrowsesMenu->addAction(riscDasmBrowseAct);
506 debugMenu->addSeparator();
507 debugMenu->addAction(pauseAct);
508 debugMenu->addAction(frameAdvanceAct);
509 debugMenu->addAction(restartAct);
510 debugMenu->addSeparator();
511 debugMenu->addAction(traceStepIntoAct);
512 debugMenu->addAction(traceStepOverAct);
513#if 0
514 debugMenu->addSeparator();
515 debugNewBreakpointMenu = debugMenu->addMenu(tr("&New Breakpoint"));
516 debugNewBreakpointMenu->addAction(newBreakpointFunctionAct);
517#endif
518 //debugMenu->addSeparator();
519 //debugMenu->addAction(DasmAct);
520 }
521 else
522 {
523 debugMenu->addAction(memBrowseAct);
524 debugMenu->addAction(stackBrowseAct);
525 debugMenu->addAction(cpuBrowseAct);
526 debugMenu->addAction(opBrowseAct);
527 debugMenu->addAction(m68kDasmBrowseAct);
528 debugMenu->addAction(riscDasmBrowseAct);
529 }
530 }
531
532 helpMenu = menuBar()->addMenu(tr("&Help"));
533 helpMenu->addAction(helpAct);
534 helpMenu->addAction(aboutAct);
535
536 // Create toolbars
537
538 toolbar = addToolBar(tr("Stuff"));
539 toolbar->addAction(powerAct);
540 if (!vjs.softTypeDebugger)
541 {
542 toolbar->addAction(pauseAct);
543 toolbar->addAction(frameAdvanceAct);
544 }
545 toolbar->addAction(filePickAct);
546 toolbar->addAction(useCDAct);
547 toolbar->addSeparator();
548 if (!vjs.softTypeDebugger)
549 {
550 toolbar->addAction(x1Act);
551 toolbar->addAction(x2Act);
552 toolbar->addAction(x3Act);
553 toolbar->addSeparator();
554 toolbar->addAction(ntscAct);
555 toolbar->addAction(palAct);
556 toolbar->addSeparator();
557 toolbar->addAction(blurAct);
558 toolbar->addAction(fullScreenAct);
559 }
560 else
561 {
562 debuggerbar = addToolBar(tr("&Debugger"));
563 debuggerbar->addAction(pauseAct);
564 debuggerbar->addAction(frameAdvanceAct);
565 debuggerbar->addAction(restartAct);
566 debuggerbar->addSeparator();
567 debuggerbar->addAction(traceStepIntoAct);
568 debuggerbar->addAction(traceStepOverAct);
569 }
570
571 if (vjs.hardwareTypeAlpine)
572 {
573 debugbar = addToolBar(tr("&Debug"));
574 debugbar->addAction(memBrowseAct);
575 debugbar->addAction(stackBrowseAct);
576 debugbar->addAction(cpuBrowseAct);
577 debugbar->addAction(opBrowseAct);
578 debugbar->addAction(m68kDasmBrowseAct);
579 debugbar->addAction(riscDasmBrowseAct);
580 }
581
582 // Add actions to the main window, as hiding widgets with them
583 // disables them :-P
584 addAction(fullScreenAct);
585 addAction(quitAppAct);
586 addAction(configAct);
587 addAction(emustatusAct);
588 addAction(pauseAct);
589 addAction(filePickAct);
590 addAction(frameAdvanceAct);
591
592 // Create status bar
593 statusBar()->showMessage(tr("Ready"));
594 ReadUISettings();
595 // Do this in case original size isn't correct (mostly for the first-run
596 // case)
597 ResizeMainWindow();
598
599 // Create our test pattern bitmaps
600 QImage tempImg(":/res/test-pattern.jpg");
601 QImage tempImgScaled = tempImg.scaled(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT_PAL, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
602
603 for(uint32_t y=0; y<VIRTUAL_SCREEN_HEIGHT_PAL; y++)
604 {
605 const QRgb * scanline = (QRgb *)tempImgScaled.constScanLine(y);
606
607 for(uint32_t x=0; x<VIRTUAL_SCREEN_WIDTH; x++)
608 {
609 uint32_t pixel = (qRed(scanline[x]) << 24) | (qGreen(scanline[x]) << 16) | (qBlue(scanline[x]) << 8) | 0xFF;
610 testPattern[(y * VIRTUAL_SCREEN_WIDTH) + x] = pixel;
611 }
612 }
613
614 QImage tempImg2(":/res/test-pattern-pal");
615 QImage tempImgScaled2 = tempImg2.scaled(VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT_PAL, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
616
617 for(uint32_t y=0; y<VIRTUAL_SCREEN_HEIGHT_PAL; y++)
618 {
619 const QRgb * scanline = (QRgb *)tempImgScaled2.constScanLine(y);
620
621 for(uint32_t x=0; x<VIRTUAL_SCREEN_WIDTH; x++)
622 {
623 uint32_t pixel = (qRed(scanline[x]) << 24) | (qGreen(scanline[x]) << 16) | (qBlue(scanline[x]) << 8) | 0xFF;
624 testPattern2[(y * VIRTUAL_SCREEN_WIDTH) + x] = pixel;
625 }
626 }
627
628 // Set up timer based loop for animation...
629 timer = new QTimer(this);
630 connect(timer, SIGNAL(timeout()), this, SLOT(Timer()));
631
632 // This isn't very accurate for NTSC: This is early by 40 msec per frame.
633 // This is because it's discarding the 0.6666... on the end of the fraction.
634 // Alas, 6 doesn't divide cleanly into 10. :-P
635//Should we defer this until SyncUI? Probably.
636//No, it doesn't work, because it uses setInterval() instead of start()...
637// timer->start(vjs.hardwareTypeNTSC ? 16 : 20);
638
639 // We set this initially, to make VJ behave somewhat as it would if no
640 // cart were inserted and the BIOS was set as active...
641 jaguarCartInserted = true;
5fe21518 642 WriteLog("Virtual Jaguar %s Rx (Last full build was on %s %s)\n", VJ_RELEASE_VERSION, __DATE__, __TIME__);
cf76e892
JPM
643 WriteLog("VJ: Initializing jaguar subsystem...\n");
644 JaguarInit();
645// memcpy(jagMemSpace + 0xE00000, jaguarBootROM, 0x20000); // Use the stock BIOS
646 memcpy(jagMemSpace + 0xE00000, (vjs.biosType == BT_K_SERIES ? jaguarBootROM : jaguarBootROM2), 0x20000); // Use the stock BIOS
647
648 // Prevent the file scanner from running if filename passed
649 // in on the command line...
650 if (autoRun)
651 return;
652
653 // Load up the default ROM if in Alpine mode:
654 if (vjs.hardwareTypeAlpine)
655 {
656 bool romLoaded = JaguarLoadFile(vjs.alpineROMPath);
657
658 // If regular load failed, try just a straight file load
659 // (Dev only! I don't want people to start getting lazy with their releases again! :-P)
660 if (!romLoaded)
661 romLoaded = AlpineLoadFile(vjs.alpineROMPath);
662
663 if (romLoaded)
664 WriteLog("Alpine Mode: Successfully loaded file \"%s\".\n", vjs.alpineROMPath);
665 else
666 WriteLog("Alpine Mode: Unable to load file \"%s\"!\n", vjs.alpineROMPath);
667
668 // Attempt to load/run the ABS file...
669 LoadSoftware(vjs.absROMPath);
670 memcpy(jagMemSpace + 0xE00000, jaguarDevBootROM2, 0x20000); // Use the stub BIOS
671 // Prevent the scanner from running...
672 return;
673 }
674
675 // Load up the default ROM if in Debugger mode:
676 if (vjs.softTypeDebugger)
677 {
678 bool romLoaded = JaguarLoadFile(vjs.debuggerROMPath);
679
680 // If regular load failed, try just a straight file load
681 // (Dev only! I don't want people to start getting lazy with their releases again! :-P)
682 if (!romLoaded)
683 romLoaded = DebuggerLoadFile(vjs.debuggerROMPath);
684
685 if (romLoaded)
686 WriteLog("Debugger Mode: Successfully loaded file \"%s\".\n", vjs.debuggerROMPath);
687 else
688 WriteLog("Debugger Mode: Unable to load file \"%s\"!\n", vjs.debuggerROMPath);
689
690 // Attempt to load/run the ABS file...
691 LoadSoftware(vjs.absROMPath);
692 memcpy(jagMemSpace + 0xE00000, jaguarDevBootROM2, 0x20000); // Use the stub BIOS
693 // Prevent the scanner from running...
694 return;
695 }
696
697 // Run the scanner if nothing passed in and *not* Alpine mode...
698 // NB: Really need to look into caching the info scanned in here...
699 filePickWin->ScanSoftwareFolder(allowUnknownSoftware);
700 scannedSoftwareFolder = true;
701}
702
703
704void MainWin::LoadFile(QString file)
705{
706 LoadSoftware(file);
707}
708
709
710void MainWin::SyncUI(void)
711{
712 // Set toolbar buttons/menus based on settings read in (sync the UI)...
713 // (Really, this is to sync command line options passed in)
714 blurAct->setChecked(vjs.glFilter);
715 x1Act->setChecked(zoomLevel == 1);
716 x2Act->setChecked(zoomLevel == 2);
717 x3Act->setChecked(zoomLevel == 3);
718// running = powerAct->isChecked();
719 ntscAct->setChecked(vjs.hardwareTypeNTSC);
720 palAct->setChecked(!vjs.hardwareTypeNTSC);
721 powerAct->setIcon(vjs.hardwareTypeNTSC ? powerRed : powerGreen);
722
723 fullScreenAct->setChecked(vjs.fullscreen);
724 fullScreen = vjs.fullscreen;
725 SetFullScreen(fullScreen);
726
727 // Reset the timer to be what was set in the command line (if any):
728// timer->setInterval(vjs.hardwareTypeNTSC ? 16 : 20);
729 timer->start(vjs.hardwareTypeNTSC ? 16 : 20);
730}
731
732
733void MainWin::closeEvent(QCloseEvent * event)
734{
735 JaguarDone();
736// This should only be done by the config dialog
737// WriteSettings();
738 WriteUISettings();
739 event->accept(); // ignore() if can't close for some reason
740}
741
742
743void MainWin::keyPressEvent(QKeyEvent * e)
744{
745#ifndef VJ_REMOVE_DEV_CODE
746 // From jaguar.cpp
747 //extern bool startM68KTracing; // moved to jaguar.h
748 // From joystick.cpp
749 extern int blit_start_log;
750 // From blitter.cpp
751 extern bool startConciseBlitLogging;
752#endif
753
754 // We ignore the Alt key for now, since it causes problems with the GUI
755 if (e->key() == Qt::Key_Alt)
756 {
757 e->accept();
758 return;
759 }
760// Bar this shite from release versions kthxbai
761#ifndef VJ_REMOVE_DEV_CODE
762 else if (e->key() == Qt::Key_F11)
763 {
764 startM68KTracing = true;
765 e->accept();
766 return;
767 }
768 else if (e->key() == Qt::Key_F12)
769 {
770 blit_start_log = true;
771 e->accept();
772 return;
773 }
774 else if (e->key() == Qt::Key_F10)
775 {
776 startConciseBlitLogging = true;
777 e->accept();
778 return;
779 }
780#endif
781 else if (e->key() == Qt::Key_F8)
782 {
783 // ggn: For extra NYAN pleasure...
784 // ggn: There you go James :P
785 // Shamus: Thanks for the patch! :-D
786 WriteLog(" o + + +\n");
787 WriteLog("+ o o + o\n");
788 WriteLog("-_-_-_-_-_-_-_,------, o \n");
789 WriteLog("_-_-_-_-_-_-_-| /\\_/\\ \n");
790 WriteLog("-_-_-_-_-_-_-~|__( ^ .^) + + \n");
791 WriteLog("_-_-_-_-_-_-_-\"\" \"\" \n");
792 WriteLog("+ o o + o\n");
793 WriteLog(" + +\n");
794 e->accept();
795 return;
796 }
797
798/*
799This is done now by a QAction...
800 if (e->key() == Qt::Key_F9)
801 {
802 ToggleFullScreen();
803 return;
804 }
805*/
806 HandleKeys(e, true);
807}
808
809
810void MainWin::keyReleaseEvent(QKeyEvent * e)
811{
812 // We ignore the Alt key for now, since it causes problems with the GUI
813 if (e->key() == Qt::Key_Alt)
814 {
815 e->accept();
816 return;
817 }
818
819 HandleKeys(e, false);
820}
821
822
823void MainWin::HandleKeys(QKeyEvent * e, bool state)
824{
825 enum { P1LEFT = 0, P1RIGHT, P1UP, P1DOWN, P2LEFT, P2RIGHT, P2UP, P2DOWN };
826 // We kill bad key combos here, before they can get to the emulator...
827 // This also kills the illegal instruction problem that cropped up in
828 // Rayman!
829
830 // First, settle key states...
831 if (e->key() == (int)vjs.p1KeyBindings[BUTTON_L])
832 keyHeld[P1LEFT] = state;
833 else if (e->key() == (int)vjs.p1KeyBindings[BUTTON_R])
834 keyHeld[P1RIGHT] = state;
835 else if (e->key() == (int)vjs.p1KeyBindings[BUTTON_U])
836 keyHeld[P1UP] = state;
837 else if (e->key() == (int)vjs.p1KeyBindings[BUTTON_D])
838 keyHeld[P1DOWN] = state;
839 else if (e->key() == (int)vjs.p2KeyBindings[BUTTON_L])
840 keyHeld[P2LEFT] = state;
841 else if (e->key() == (int)vjs.p2KeyBindings[BUTTON_R])
842 keyHeld[P2RIGHT] = state;
843 else if (e->key() == (int)vjs.p2KeyBindings[BUTTON_U])
844 keyHeld[P2UP] = state;
845 else if (e->key() == (int)vjs.p2KeyBindings[BUTTON_D])
846 keyHeld[P2DOWN] = state;
847
848 // Next, check for conflicts and kill 'em if there are any...
849 if (keyHeld[P1LEFT] && keyHeld[P1RIGHT])
850 keyHeld[P1LEFT] = keyHeld[P1RIGHT] = false;
851
852 if (keyHeld[P1UP] && keyHeld[P1DOWN])
853 keyHeld[P1UP] = keyHeld[P1DOWN] = false;
854
855 if (keyHeld[P2LEFT] && keyHeld[P2RIGHT])
856 keyHeld[P2LEFT] = keyHeld[P2RIGHT] = false;
857
858 if (keyHeld[P2UP] && keyHeld[P2DOWN])
859 keyHeld[P2UP] = keyHeld[P2DOWN] = false;
860
861 // No bad combos exist now, let's stuff the emulator key buffers...!
862 for(int i=BUTTON_FIRST; i<=BUTTON_LAST; i++)
863 {
864 if (e->key() == (int)vjs.p1KeyBindings[i])
865 joypad0Buttons[i] = (state ? 0x01 : 0x00);
866
867 if (e->key() == (int)vjs.p2KeyBindings[i])
868 joypad1Buttons[i] = (state ? 0x01 : 0x00);
869 }
870}
871
872
873//
874// N.B.: The profile system AutoConnect functionality sets the gamepad IDs here.
875//
876void MainWin::HandleGamepads(void)
877{
878 Gamepad::Update();
879
880 for(int i=BUTTON_FIRST; i<=BUTTON_LAST; i++)
881 {
882 if (vjs.p1KeyBindings[i] & (JOY_BUTTON | JOY_HAT | JOY_AXIS))
883 joypad0Buttons[i] = (Gamepad::GetState(gamepadIDSlot1, vjs.p1KeyBindings[i]) ? 0x01 : 0x00);
884
885 if (vjs.p2KeyBindings[i] & (JOY_BUTTON | JOY_HAT | JOY_AXIS))
886 joypad1Buttons[i] = (Gamepad::GetState(gamepadIDSlot2, vjs.p2KeyBindings[i]) ? 0x01 : 0x00);
887 }
888}
889
890
891void MainWin::Open(void)
892{
893}
894
895
896void MainWin::Configure(void)
897{
898 // Call the configuration dialog and update settings
899 ConfigDialog dlg(this);
900 //ick.
901 dlg.generalTab->useUnknownSoftware->setChecked(allowUnknownSoftware);
902 dlg.controllerTab1->profileNum = lastEditedProfile;
903 dlg.controllerTab1->SetupLastUsedProfile();
904// maybe instead of this, we tell the controller tab to work on a copy that gets
905// written if the user hits 'OK'.
906 SaveProfiles(); // Just in case user cancels
907
908 if (dlg.exec() == false)
909 {
910 RestoreProfiles();
911 return;
912 }
913
914 QString before = vjs.ROMPath;
915 QString alpineBefore = vjs.alpineROMPath;
916 QString absBefore = vjs.absROMPath;
917// bool audioBefore = vjs.audioEnabled;
918 bool audioBefore = vjs.DSPEnabled;
919 dlg.UpdateVJSettings();
920 QString after = vjs.ROMPath;
921 QString alpineAfter = vjs.alpineROMPath;
922 QString absAfter = vjs.absROMPath;
923// bool audioAfter = vjs.audioEnabled;
924 bool audioAfter = vjs.DSPEnabled;
925
926 bool allowOld = allowUnknownSoftware;
927 //ick.
928 allowUnknownSoftware = dlg.generalTab->useUnknownSoftware->isChecked();
929 lastEditedProfile = dlg.controllerTab1->profileNum;
930 AutoConnectProfiles();
931
932 // We rescan the "software" folder if the user either changed the path or
933 // checked/unchecked the "Allow unknown files" option in the config dialog.
934 if ((before != after) || (allowOld != allowUnknownSoftware))
935 filePickWin->ScanSoftwareFolder(allowUnknownSoftware);
936
937 // If the "Alpine" ROM is changed, then let's load it...
938 if (alpineBefore != alpineAfter)
939 {
940 if (!JaguarLoadFile(vjs.alpineROMPath) && !AlpineLoadFile(vjs.alpineROMPath))
941 {
942 // Oh crap, we couldn't get the file! Alert the media!
943 QMessageBox msg;
944 msg.setText(QString(tr("Could not load file \"%1\"!")).arg(vjs.alpineROMPath));
945 msg.setIcon(QMessageBox::Warning);
946 msg.exec();
947 }
948 }
949
950 // If the "ABS" ROM is changed, then let's load it...
951 if (absBefore != absAfter)
952 {
953 if (!JaguarLoadFile(vjs.absROMPath))
954 {
955 // Oh crap, we couldn't get the file! Alert the media!
956 QMessageBox msg;
957 msg.setText(QString(tr("Could not load file \"%1\"!")).arg(vjs.absROMPath));
958 msg.setIcon(QMessageBox::Warning);
959 msg.exec();
960 }
961 }
962
963 // If the "Enable DSP" checkbox changed, then we have to re-init the DAC,
964 // since it's running in the host audio IRQ...
965 if (audioBefore != audioAfter)
966 {
967 DACDone();
968 DACInit();
969 }
970
971 // Just in case we crash before a clean exit...
972 WriteSettings();
973
974 RefreshDebuggerWindows();
975}
976
977
978//
979// Here's the main emulator loop
980//
981void MainWin::Timer(void)
982{
983#if 0
984static uint32_t ntscTickCount;
985 if (vjs.hardwareTypeNTSC)
986 {
987 ntscTickCount++;
988 ntscTickCount %= 3;
989 timer->start(16 + (ntscTickCount == 0 ? 1 : 0));
990 }
991#endif
992
993 if (!running)
994 return;
995
996 if (showUntunedTankCircuit)
997 {
998 // Some machines can't handle this, so we give them the option to disable it. :-)
999 if (!plzDontKillMyComputer)
1000 {
1001// if (!vjs.softTypeDebugger)
1002 {
1003 // Random hash & trash
1004 // We try to simulate an untuned tank circuit here... :-)
1005 for (uint32_t x = 0; x < videoWidget->rasterWidth; x++)
1006 {
1007 for (uint32_t y = 0; y < videoWidget->rasterHeight; y++)
1008 {
1009 videoWidget->buffer[(y * videoWidget->textureWidth) + x]
1010 = (rand() & 0xFF) << 8 | (rand() & 0xFF) << 16 | (rand() & 0xFF) << 24;
1011 }
1012 }
1013 }
1014 }
1015 }
1016 else
1017 {
1018 // Otherwise, run the Jaguar simulation
1019 HandleGamepads();
1020 JaguarExecuteNew();
1021 if (!vjs.softTypeDebugger)
1022 videoWidget->HandleMouseHiding();
1023
1024static uint32_t refresh = 0;
1025 // Do autorefresh on debug windows
1026 // Have to be careful, too much causes the emulator to slow way down!
1027 if (vjs.hardwareTypeAlpine || vjs.softTypeDebugger)
1028 {
1029 if (refresh == vjs.refresh)
1030 {
1031 RefreshAlpineWindows();
1032 //memBrowseWin->RefreshContents();
1033 //cpuBrowseWin->RefreshContents();
1034 refresh = 0;
1035 }
1036 else
1037 refresh++;
1038 }
1039 }
1040
1041 //if (!vjs.softTypeDebugger)
1042 videoWidget->updateGL();
1043
1044 // FPS handling
1045 // Approach: We use a ring buffer to store times (in ms) over a given
1046 // amount of frames, then sum them to figure out the FPS.
1047 uint32_t timestamp = SDL_GetTicks();
1048 // This assumes the ring buffer size is a power of 2
1049// ringBufferPointer = (ringBufferPointer + 1) & (RING_BUFFER_SIZE - 1);
1050 // Doing it this way is better. Ring buffer size can be arbitrary then.
1051 ringBufferPointer = (ringBufferPointer + 1) % RING_BUFFER_SIZE;
1052 ringBuffer[ringBufferPointer] = timestamp - oldTimestamp;
1053 uint32_t elapsedTime = 0;
1054
1055 for(uint32_t i=0; i<RING_BUFFER_SIZE; i++)
1056 elapsedTime += ringBuffer[i];
1057
1058 // elapsedTime must be non-zero
1059 if (elapsedTime == 0)
1060 elapsedTime = 1;
1061
1062 // This is in frames per 10 seconds, so we can have 1 decimal
1063 uint32_t framesPerSecond = (uint32_t)(((float)RING_BUFFER_SIZE / (float)elapsedTime) * 10000.0);
1064 uint32_t fpsIntegerPart = framesPerSecond / 10;
1065 uint32_t fpsDecimalPart = framesPerSecond % 10;
1066 // If this is updated too frequently to be useful, we can throttle it down
1067 // so that it only updates every 10th frame or so
1068 statusBar()->showMessage(QString("%1.%2 FPS").arg(fpsIntegerPart).arg(fpsDecimalPart));
1069 oldTimestamp = timestamp;
1070
1071 if (M68KDebugHaltStatus())
1072 ToggleRunState();
1073}
1074
1075
1076void MainWin::TogglePowerState(void)
1077{
1078 powerButtonOn = !powerButtonOn;
1079 running = true;
1080
1081 // With the power off, we simulate white noise on the screen. :-)
1082 if (!powerButtonOn)
1083 {
1084 // Restore the mouse pointer, if hidden:
1085 if (!vjs.softTypeDebugger)
1086 videoWidget->CheckAndRestoreMouseCursor();
1087 useCDAct->setDisabled(false);
1088 palAct->setDisabled(false);
1089 ntscAct->setDisabled(false);
1090 pauseAct->setChecked(false);
1091 pauseAct->setDisabled(true);
1092 showUntunedTankCircuit = true;
1093 DACPauseAudioThread();
1094 // This is just in case the ROM we were playing was in a narrow or wide
1095 // field mode, so the untuned tank sim doesn't look wrong. :-)
1096 TOMReset();
1097
1098 if (plzDontKillMyComputer)
1099 {
1100 //if (!vjs.softTypeDebugger)
1101 {
1102 // We have to do it line by line, because the texture pitch is not
1103 // the same as the picture buffer's pitch.
1104 for (uint32_t y = 0; y < videoWidget->rasterHeight; y++)
1105 {
1106 if (vjs.hardwareTypeNTSC)
1107 memcpy(videoWidget->buffer + (y * videoWidget->textureWidth), testPattern + (y * VIRTUAL_SCREEN_WIDTH), VIRTUAL_SCREEN_WIDTH * sizeof(uint32_t));
1108 else
1109 memcpy(videoWidget->buffer + (y * videoWidget->textureWidth), testPattern2 + (y * VIRTUAL_SCREEN_WIDTH), VIRTUAL_SCREEN_WIDTH * sizeof(uint32_t));
1110 }
1111 }
1112 }
1113 }
1114 else
1115 {
1116 useCDAct->setDisabled(true);
1117 palAct->setDisabled(true);
1118 ntscAct->setDisabled(true);
1119 pauseAct->setChecked(false);
1120 pauseAct->setDisabled(false);
1121 showUntunedTankCircuit = false;
1122
1123 // Otherwise, we prepare for running regular software...
1124 if (CDActive)
1125 {
1126// Should check for cartridgeLoaded here as well...!
1127// We can clear it when toggling CDActive on, so that when we power cycle it
1128// does the expected thing. Otherwise, if we use the file picker to insert a
1129// cart, we expect to run the cart! Maybe have a RemoveCart function that only
1130// works if the CD unit is active?
1131 setWindowTitle(QString("Virtual Jaguar " VJ_RELEASE_VERSION
5fe21518 1132 " Rx - Now playing: Jaguar CD"));
cf76e892
JPM
1133 }
1134
1135 WriteLog("GUI: Resetting Jaguar...\n");
1136 JaguarReset();
1137 DACPauseAudioThread(false);
1138 }
1139}
1140
1141
1142void MainWin::ToggleRunState(void)
1143{
1144 startM68KTracing = running;
1145 running = !running;
1146
1147 if (!running)
1148 {
1149 frameAdvanceAct->setDisabled(false);
1150 pauseAct->setChecked(true);
1151 pauseAct->setDisabled(false);
1152 if (vjs.softTypeDebugger)
1153 {
1154 traceStepIntoAct->setDisabled(false);
1155 traceStepOverAct->setDisabled(false);
1156 restartAct->setDisabled(false);
1157 m68kDasmWin->Use68KPCAddress();
1158 GPUDasmWin->UseGPUPCAddress();
1159 DSPDasmWin->UseDSPPCAddress();
1160 }
1161
1162 //if (!vjs.softTypeDebugger)
1163 {
1164 // Restore the mouse pointer, if hidden:
1165 videoWidget->CheckAndRestoreMouseCursor();
1166 // frameAdvanceAct->setDisabled(false);
1167
1168 for (uint32_t i = 0; i < (uint32_t)(videoWidget->textureWidth * 256); i++)
1169 {
1170 uint32_t pixel = videoWidget->buffer[i];
1171 uint8_t r = (pixel >> 24) & 0xFF, g = (pixel >> 16) & 0xFF, b = (pixel >> 8) & 0xFF;
1172 pixel = ((r + g + b) / 3) & 0x00FF;
1173 videoWidget->buffer[i] = 0x000000FF | (pixel << 16) | (pixel << 8);
1174 }
1175
1176 videoWidget->updateGL();
1177
1178 cpuBrowseWin->HoldBPM();
1179 cpuBrowseWin->HandleBPMContinue();
1180 RefreshDebuggerWindows();
1181 }
1182 }
1183 else
1184 {
1185 frameAdvanceAct->setDisabled(true);
1186 pauseAct->setChecked(false);
1187 pauseAct->setDisabled(false);
1188 if (vjs.softTypeDebugger)
1189 {
1190 traceStepIntoAct->setDisabled(true);
1191 traceStepOverAct->setDisabled(true);
1192 restartAct->setDisabled(true);
1193 }
1194
1195 cpuBrowseWin->UnholdBPM();
1196 }
1197
1198 // Pause/unpause any running/non-running threads...
1199 DACPauseAudioThread(!running);
1200}
1201
1202
1203void MainWin::SetZoom100(void)
1204{
1205 zoomLevel = 1;
1206 ResizeMainWindow();
1207}
1208
1209
1210void MainWin::SetZoom200(void)
1211{
1212 zoomLevel = 2;
1213 ResizeMainWindow();
1214}
1215
1216
1217void MainWin::SetZoom300(void)
1218{
1219 zoomLevel = 3;
1220 ResizeMainWindow();
1221}
1222
1223
1224void MainWin::SetNTSC(void)
1225{
1226 powerAct->setIcon(powerRed);
1227 timer->setInterval(16);
1228 vjs.hardwareTypeNTSC = true;
1229 ResizeMainWindow();
1230 WriteSettings();
1231}
1232
1233
1234void MainWin::SetPAL(void)
1235{
1236 powerAct->setIcon(powerGreen);
1237 timer->setInterval(20);
1238 vjs.hardwareTypeNTSC = false;
1239 ResizeMainWindow();
1240 WriteSettings();
1241}
1242
1243
1244void MainWin::ToggleBlur(void)
1245{
1246 vjs.glFilter = !vjs.glFilter;
1247 WriteSettings();
1248}
1249
1250
1251void MainWin::ShowAboutWin(void)
1252{
1253 aboutWin->show();
1254}
1255
1256
1257void MainWin::ShowHelpWin(void)
1258{
1259 helpWin->show();
1260}
1261
1262
1263void MainWin::InsertCart(void)
1264{
1265 // Check to see if we did autorun, 'cause we didn't load anything in that
1266 // case
1267 if (!scannedSoftwareFolder)
1268 {
1269 filePickWin->ScanSoftwareFolder(allowUnknownSoftware);
1270 scannedSoftwareFolder = true;
1271 }
1272
1273 // If the emulator is running, we pause it here and unpause it later
1274 // if we dismiss the file selector without choosing anything
1275 if (running && powerButtonOn)
1276 {
1277 ToggleRunState();
1278 pauseForFileSelector = true;
1279 }
1280
1281 filePickWin->show();
1282}
1283
1284
1285void MainWin::Unpause(void)
1286{
1287 // Here we unpause the emulator if it was paused when we went into the file selector
1288 if (pauseForFileSelector)
1289 {
1290 pauseForFileSelector = false;
1291
1292 // Some nutter might have unpaused while in the file selector, so check for that
1293 if (!running)
1294 ToggleRunState();
1295 }
1296}
1297
1298
1299void MainWin::LoadSoftware(QString file)
1300{
1301 running = false; // Prevent bad things(TM) from happening...
1302 pauseForFileSelector = false; // Reset the file selector pause flag
1303
1304 uint8_t * biosPointer = jaguarBootROM;
1305
1306 if (vjs.hardwareTypeAlpine)
1307 biosPointer = jaguarDevBootROM2;
1308
1309 if (vjs.softTypeDebugger)
1310 biosPointer = jaguarDevBootROM2;
1311
1312 memcpy(jagMemSpace + 0xE00000, biosPointer, 0x20000);
1313
1314 powerAct->setDisabled(false);
1315 powerAct->setChecked(true);
1316 powerButtonOn = false;
1317 TogglePowerState();
1318
1319 // We have to load our software *after* the Jaguar RESET
1320 cartridgeLoaded = JaguarLoadFile(file.toUtf8().data());
1321 SET32(jaguarMainRAM, 0, vjs.DRAM_size); // Set top of stack...
1322
1323 // This is icky because we've already done it
1324// it gets worse :-P
1325 if (!vjs.useJaguarBIOS)
1326 SET32(jaguarMainRAM, 4, jaguarRunAddress);
1327
1328 m68k_pulse_reset();
1329
1330// set the M68K in halt mode in case of a debug mode is used, so control is at user side
1331 if (vjs.softTypeDebugger)
1332 {
1333 m68kDasmWin->SetAddress(jaguarRunAddress);
1334 //pauseAct->setDisabled(false);
1335 //pauseAct->setChecked(true);
1336 ToggleRunState();
1337 //RefreshWindows();
1338 }
1339 else
1340 {
1341 if (vjs.hardwareTypeAlpine && !jaguarRunAddress)
1342 {
1343 ToggleRunState();
1344 }
1345 }
1346
1347 if ((!vjs.hardwareTypeAlpine || !vjs.softTypeDebugger) && !loadAndGo && jaguarRunAddress)
1348 {
5fe21518 1349 QString newTitle = QString("Virtual Jaguar " VJ_RELEASE_VERSION " Rx - Now playing: %1")
cf76e892
JPM
1350 .arg(filePickWin->GetSelectedPrettyName());
1351 setWindowTitle(newTitle);
1352 }
1353}
1354
1355
1356void MainWin::ToggleCDUsage(void)
1357{
1358 CDActive = !CDActive;
1359
1360 // Set up the Jaguar CD for execution, otherwise, clear memory
1361 if (CDActive)
1362 memcpy(jagMemSpace + 0x800000, jaguarCDBootROM, 0x40000);
1363 else
1364 memset(jagMemSpace + 0x800000, 0xFF, 0x40000);
1365}
1366
1367
1368//
1369void MainWin::NewBreakpointFunction(void)
1370{
1371 brkWin->show();
1372 brkWin->RefreshContents();
1373}
1374
1375
1376// Step Into trace
1377void MainWin::TraceStepInto(void)
1378{
1379 JaguarStepInto();
1380 videoWidget->updateGL();
1381 RefreshDebuggerWindows();
1382#ifdef _MSC_VER
1383#pragma message("Warning: !!! Need to verify the Step Into function !!!")
1384#else
1385 #warning "!!! Need to verify the Step Into function !!!"
1386#endif // _MSC_VER
1387}
1388
1389
1390// Restart
1391void MainWin::Restart(void)
1392{
1393 m68k_set_reg(M68K_REG_PC, jaguarRunAddress);
1394 //m68kDasmWin->SetAddress(jaguarRunAddress);
1395 RefreshDebuggerWindows();
1396#ifdef _MSC_VER
1397#pragma message("Warning: !!! Need to verify the Restart function !!!")
1398#else
1399 #warning "!!! Need to verify the Restart function !!!"
1400#endif // _MSC_VER
1401}
1402
1403
1404// Step Over trace
1405void MainWin::TraceStepOver(void)
1406{
1407 JaguarStepOver(0);
1408 videoWidget->updateGL();
1409 RefreshDebuggerWindows();
1410#ifdef _MSC_VER
1411#pragma message("Warning: !!! Need to verify the Step Over function !!!")
1412#else
1413 #warning "!!! Need to verify the Step Over function !!!"
1414#endif // _MSC_VER
1415}
1416
1417
1418// Advance / Execute for one frame
1419void MainWin::FrameAdvance(void)
1420{
1421//printf("Frame Advance...\n");
1422 ToggleRunState();
1423 // Execute 1 frame, then exit (only useful in Pause mode)
1424 JaguarExecuteNew();
1425 //if (!vjs.softTypeDebugger)
1426 videoWidget->updateGL();
1427 ToggleRunState();
1428 // Need to execute 1 frames' worth of DSP thread as well :-/
1429
1430 //m68kDasmWin->Use68KPCAddress();
1431 //RefreshWindows();
1432#ifdef _MSC_VER
1433#pragma message("Warning: !!! Need to execute the DSP thread for 1 frame too !!!")
1434#else
1435#warning "!!! Need to execute the DSP thread for 1 frame too !!!"
1436#endif // _MSC_VER
1437}
1438
1439
1440void MainWin::SetFullScreen(bool state/*= true*/)
1441{
1442 if (!vjs.softTypeDebugger)
1443 {
1444 if (state)
1445 {
1446 mainWinPosition = pos();
1447 menuBar()->hide();
1448 statusBar()->hide();
1449 toolbar->hide();
1450
1451 if (debugbar)
1452 debugbar->hide();
1453
1454 // This is needed because the fullscreen may happen on a different
1455 // screen than screen 0:
1456 int screenNum = QApplication::desktop()->screenNumber(videoWidget);
1457 QRect r = QApplication::desktop()->screenGeometry(screenNum);
1458 double targetWidth = (double)VIRTUAL_SCREEN_WIDTH,
1459 targetHeight = (double)(vjs.hardwareTypeNTSC ? VIRTUAL_SCREEN_HEIGHT_NTSC : VIRTUAL_SCREEN_HEIGHT_PAL);
1460 double aspectRatio = targetWidth / targetHeight;
1461 // NOTE: Really should check here to see which dimension constrains the
1462 // other. Right now, we assume that height is the constraint.
1463 int newWidth = (int)(aspectRatio * (double)r.height());
1464 videoWidget->offset = (r.width() - newWidth) / 2;
1465 videoWidget->fullscreen = true;
1466 videoWidget->outputWidth = newWidth;
1467 videoWidget->setFixedSize(r.width(), r.height());
1468 showFullScreen();
1469 }
1470 else
1471 {
1472 // Seems Qt is fussy about this: showNormal() has to go first, or it
1473 // will keep the window stuck in a psuedo-fullscreen mode with no way
1474 // to get out of it (except closing the app).
1475 showNormal();
1476
1477 // Reset the video widget to windowed mode
1478 videoWidget->offset = 0;
1479 videoWidget->fullscreen = false;
1480 menuBar()->show();
1481 statusBar()->show();
1482 toolbar->show();
1483
1484 if (debugbar)
1485 debugbar->show();
1486
1487 ResizeMainWindow();
1488 move(mainWinPosition);
1489 }
1490 }
1491}
1492
1493
1494void MainWin::ToggleFullScreen(void)
1495{
1496 fullScreen = !fullScreen;
1497 SetFullScreen(fullScreen);
1498}
1499
1500
1501void MainWin::ShowExceptionVectorTableBrowserWin(void)
1502{
1503 exceptionvectortableBrowseWin->show();
1504 exceptionvectortableBrowseWin->RefreshContents();
1505}
1506
1507
1508void MainWin::ShowAllWatchBrowserWin(void)
1509{
1510 allWatchBrowseWin->show();
1511 allWatchBrowseWin->RefreshContents();
1512}
1513
1514
1515void MainWin::ShowHeapAllocatorBrowserWin(void)
1516{
1517 heapallocatorBrowseWin->show();
1518 heapallocatorBrowseWin->RefreshContents();
1519}
1520
1521
1522void MainWin::ShowMemoryBrowserWin(void)
1523{
1524 memBrowseWin->show();
1525 memBrowseWin->RefreshContents();
1526}
1527
1528
1529void MainWin::ShowMemory1BrowserWin(int NumWin)
1530{
1531// for (int i = 0; i < vjs.nbrmemory1browserwindow; i++)
1532 {
1533 mem1BrowseWin[NumWin]->show();
1534 mem1BrowseWin[NumWin]->RefreshContents(NumWin);
1535 }
1536}
1537
1538
1539void MainWin::ShowEmuStatusWin(void)
1540{
1541 emuStatusWin->show();
1542 emuStatusWin->RefreshContents();
1543}
1544
1545
1546void MainWin::ShowStackBrowserWin(void)
1547{
1548 stackBrowseWin->show();
1549 stackBrowseWin->RefreshContents();
1550}
1551
1552
1553void MainWin::ShowCPUBrowserWin(void)
1554{
1555 cpuBrowseWin->show();
1556 cpuBrowseWin->RefreshContents();
1557}
1558
1559
1560void MainWin::ShowOPBrowserWin(void)
1561{
1562 opBrowseWin->show();
1563 opBrowseWin->RefreshContents();
1564}
1565
1566
1567void MainWin::ShowM68KDasmBrowserWin(void)
1568{
1569 m68kDasmBrowseWin->show();
1570 m68kDasmBrowseWin->RefreshContents();
1571}
1572
1573
1574void MainWin::ShowRISCDasmBrowserWin(void)
1575{
1576 riscDasmBrowseWin->show();
1577 riscDasmBrowseWin->RefreshContents();
1578}
1579
1580
1581void MainWin::ShowDasmWin(void)
1582{
1583 DasmWin->show();
1584// DasmWin->RefreshContents();
1585}
1586
1587
1588void MainWin::ShowVideoOutputWin(void)
1589{
1590 //VideoOutputWindowCentrale = mainWindowCentrale->addSubWindow(videoWidget);
1591 //VideoOutputWindowCentrale->setWindowTitle(QString(tr("Video output")));
1592 //VideoOutputWindowCentrale->show();
1593 //memBrowseWin->show();
1594 VideoOutputWin->show();
1595 //VideoOutputWin->RefreshContents(videoWidget);
1596}
1597
1598
1599void MainWin::ResizeMainWindow(void)
1600{
1601 if (!vjs.softTypeDebugger)
1602 {
1603 videoWidget->setFixedSize(zoomLevel * VIRTUAL_SCREEN_WIDTH,
1604 zoomLevel * (vjs.hardwareTypeNTSC ? VIRTUAL_SCREEN_HEIGHT_NTSC : VIRTUAL_SCREEN_HEIGHT_PAL));
1605
1606 // Show the test pattern if user requested plzDontKillMyComputer mode
1607 if (!powerButtonOn && plzDontKillMyComputer)
1608 {
1609 for (uint32_t y = 0; y < videoWidget->rasterHeight; y++)
1610 {
1611 if (vjs.hardwareTypeNTSC)
1612 memcpy(videoWidget->buffer + (y * videoWidget->textureWidth), testPattern + (y * VIRTUAL_SCREEN_WIDTH), VIRTUAL_SCREEN_WIDTH * sizeof(uint32_t));
1613 else
1614 memcpy(videoWidget->buffer + (y * videoWidget->textureWidth), testPattern2 + (y * VIRTUAL_SCREEN_WIDTH), VIRTUAL_SCREEN_WIDTH * sizeof(uint32_t));
1615 }
1616 }
1617
1618 adjustSize();
1619 }
1620}
1621
1622
be44e757 1623// Read settings
cf76e892
JPM
1624void MainWin::ReadSettings(void)
1625{
1626 QSettings settings("Underground Software", "Virtual Jaguar");
1627
1628 zoomLevel = settings.value("zoom", 2).toInt();
1629 allowUnknownSoftware = settings.value("showUnknownSoftware", false).toBool();
1630 lastEditedProfile = settings.value("lastEditedProfile", 0).toInt();
1631
1632 vjs.useJoystick = settings.value("useJoystick", false).toBool();
1633 vjs.joyport = settings.value("joyport", 0).toInt();
1634 vjs.hardwareTypeNTSC = settings.value("hardwareTypeNTSC", true).toBool();
1635 vjs.frameSkip = settings.value("frameSkip", 0).toInt();
1636 vjs.useJaguarBIOS = settings.value("useJaguarBIOS", false).toBool();
1637 vjs.GPUEnabled = settings.value("GPUEnabled", true).toBool();
1638 vjs.DSPEnabled = settings.value("DSPEnabled", true).toBool();
1639 vjs.audioEnabled = settings.value("audioEnabled", true).toBool();
1640 vjs.usePipelinedDSP = settings.value("usePipelinedDSP", false).toBool();
1641 vjs.fullscreen = settings.value("fullscreen", false).toBool();
1642 vjs.useOpenGL = settings.value("useOpenGL", true).toBool();
1643 vjs.glFilter = settings.value("glFilterType", 1).toInt();
1644 vjs.renderType = settings.value("renderType", 0).toInt();
cf76e892
JPM
1645 vjs.biosType = settings.value("biosType", BT_M_SERIES).toInt();
1646 vjs.useFastBlitter = settings.value("useFastBlitter", false).toBool();
1647 strcpy(vjs.EEPROMPath, settings.value("EEPROMs", QStandardPaths::writableLocation(QStandardPaths::DataLocation).append("/eeproms/")).toString().toUtf8().data());
1648 strcpy(vjs.ROMPath, settings.value("ROMs", QStandardPaths::writableLocation(QStandardPaths::DataLocation).append("/software/")).toString().toUtf8().data());
be44e757
JPM
1649
1650 // Read settings from the Debugger mode
1651 settings.beginGroup("debugger");
cf76e892 1652 strcpy(vjs.debuggerROMPath, settings.value("DefaultROM", "").toString().toUtf8().data());
cf76e892 1653 vjs.nbrdisasmlines = settings.value("NbrDisasmLines", 32).toUInt();
cf76e892
JPM
1654 vjs.disasmopcodes = settings.value("DisasmOpcodes", true).toBool();
1655 vjs.displayHWlabels = settings.value("DisplayHWLabels", true).toBool();
1656 vjs.displayFullSourceFilename = settings.value("displayFullSourceFilename", true).toBool();
1657 vjs.nbrmemory1browserwindow = settings.value("NbrMemory1BrowserWindow", MaxMemory1BrowserWindow).toUInt();
be44e757 1658 settings.endGroup();
cf76e892 1659
be44e757
JPM
1660 // Read settings from the Alpine mode
1661 settings.beginGroup("alpine");
1662 strcpy(vjs.alpineROMPath, settings.value("DefaultROM", "").toString().toUtf8().data());
1663 strcpy(vjs.absROMPath, settings.value("DefaultABS", "").toString().toUtf8().data());
1664 vjs.refresh = settings.value("refresh", 60).toUInt();
1665 vjs.allowWritesToROM = settings.value("writeROM", false).toBool();
1666 settings.endGroup();
1667
1668 // Write important settings to the log file
cf76e892
JPM
1669 WriteLog("MainWin: Paths\n");
1670 WriteLog(" EEPROMPath = \"%s\"\n", vjs.EEPROMPath);
1671 WriteLog(" ROMPath = \"%s\"\n", vjs.ROMPath);
1672 WriteLog(" AlpineROMPath = \"%s\"\n", vjs.alpineROMPath);
1673 WriteLog("DebuggerROMPath = \"%s\"\n", vjs.debuggerROMPath);
1674 WriteLog(" absROMPath = \"%s\"\n", vjs.absROMPath);
1675 WriteLog(" Pipelined DSP = %s\n", (vjs.usePipelinedDSP ? "ON" : "off"));
1676
1677#if 0
1678 // Keybindings in order of U, D, L, R, C, B, A, Op, Pa, 0-9, #, *
1679 vjs.p1KeyBindings[BUTTON_U] = settings.value("p1k_up", Qt::Key_S).toInt();
1680 vjs.p1KeyBindings[BUTTON_D] = settings.value("p1k_down", Qt::Key_X).toInt();
1681 vjs.p1KeyBindings[BUTTON_L] = settings.value("p1k_left", Qt::Key_A).toInt();
1682 vjs.p1KeyBindings[BUTTON_R] = settings.value("p1k_right", Qt::Key_D).toInt();
1683 vjs.p1KeyBindings[BUTTON_C] = settings.value("p1k_c", Qt::Key_J).toInt();
1684 vjs.p1KeyBindings[BUTTON_B] = settings.value("p1k_b", Qt::Key_K).toInt();
1685 vjs.p1KeyBindings[BUTTON_A] = settings.value("p1k_a", Qt::Key_L).toInt();
1686 vjs.p1KeyBindings[BUTTON_OPTION] = settings.value("p1k_option", Qt::Key_O).toInt();
1687 vjs.p1KeyBindings[BUTTON_PAUSE] = settings.value("p1k_pause", Qt::Key_P).toInt();
1688 vjs.p1KeyBindings[BUTTON_0] = settings.value("p1k_0", Qt::Key_0).toInt();
1689 vjs.p1KeyBindings[BUTTON_1] = settings.value("p1k_1", Qt::Key_1).toInt();
1690 vjs.p1KeyBindings[BUTTON_2] = settings.value("p1k_2", Qt::Key_2).toInt();
1691 vjs.p1KeyBindings[BUTTON_3] = settings.value("p1k_3", Qt::Key_3).toInt();
1692 vjs.p1KeyBindings[BUTTON_4] = settings.value("p1k_4", Qt::Key_4).toInt();
1693 vjs.p1KeyBindings[BUTTON_5] = settings.value("p1k_5", Qt::Key_5).toInt();
1694 vjs.p1KeyBindings[BUTTON_6] = settings.value("p1k_6", Qt::Key_6).toInt();
1695 vjs.p1KeyBindings[BUTTON_7] = settings.value("p1k_7", Qt::Key_7).toInt();
1696 vjs.p1KeyBindings[BUTTON_8] = settings.value("p1k_8", Qt::Key_8).toInt();
1697 vjs.p1KeyBindings[BUTTON_9] = settings.value("p1k_9", Qt::Key_9).toInt();
1698 vjs.p1KeyBindings[BUTTON_d] = settings.value("p1k_pound", Qt::Key_Minus).toInt();
1699 vjs.p1KeyBindings[BUTTON_s] = settings.value("p1k_star", Qt::Key_Equal).toInt();
1700
1701 vjs.p2KeyBindings[BUTTON_U] = settings.value("p2k_up", Qt::Key_Up).toInt();
1702 vjs.p2KeyBindings[BUTTON_D] = settings.value("p2k_down", Qt::Key_Down).toInt();
1703 vjs.p2KeyBindings[BUTTON_L] = settings.value("p2k_left", Qt::Key_Left).toInt();
1704 vjs.p2KeyBindings[BUTTON_R] = settings.value("p2k_right", Qt::Key_Right).toInt();
1705 vjs.p2KeyBindings[BUTTON_C] = settings.value("p2k_c", Qt::Key_Z).toInt();
1706 vjs.p2KeyBindings[BUTTON_B] = settings.value("p2k_b", Qt::Key_X).toInt();
1707 vjs.p2KeyBindings[BUTTON_A] = settings.value("p2k_a", Qt::Key_C).toInt();
1708 vjs.p2KeyBindings[BUTTON_OPTION] = settings.value("p2k_option", Qt::Key_Apostrophe).toInt();
1709 vjs.p2KeyBindings[BUTTON_PAUSE] = settings.value("p2k_pause", Qt::Key_Return).toInt();
1710 vjs.p2KeyBindings[BUTTON_0] = settings.value("p2k_0", Qt::Key_0).toInt();
1711 vjs.p2KeyBindings[BUTTON_1] = settings.value("p2k_1", Qt::Key_1).toInt();
1712 vjs.p2KeyBindings[BUTTON_2] = settings.value("p2k_2", Qt::Key_2).toInt();
1713 vjs.p2KeyBindings[BUTTON_3] = settings.value("p2k_3", Qt::Key_3).toInt();
1714 vjs.p2KeyBindings[BUTTON_4] = settings.value("p2k_4", Qt::Key_4).toInt();
1715 vjs.p2KeyBindings[BUTTON_5] = settings.value("p2k_5", Qt::Key_5).toInt();
1716 vjs.p2KeyBindings[BUTTON_6] = settings.value("p2k_6", Qt::Key_6).toInt();
1717 vjs.p2KeyBindings[BUTTON_7] = settings.value("p2k_7", Qt::Key_7).toInt();
1718 vjs.p2KeyBindings[BUTTON_8] = settings.value("p2k_8", Qt::Key_8).toInt();
1719 vjs.p2KeyBindings[BUTTON_9] = settings.value("p2k_9", Qt::Key_9).toInt();
1720 vjs.p2KeyBindings[BUTTON_d] = settings.value("p2k_pound", Qt::Key_Slash).toInt();
1721 vjs.p2KeyBindings[BUTTON_s] = settings.value("p2k_star", Qt::Key_Asterisk).toInt();
1722#endif
1723
1724 ReadProfiles(&settings);
1725}
1726
1727
1728// Read UI settings
1729// Default values will be used in case of no settings can be found
1730#ifdef _MSC_VER
1731#pragma message("Warning: !!! Need to check the window geometry to see if the positions are legal !!!")
1732#else
1733#warning "!!! Need to check the window geometry to see if the positions are legal !!!"
1734#endif // _MSC_VER
1735// i.e., someone could drag it to another screen, close it, then disconnect that screen
1736void MainWin::ReadUISettings(void)
1737{
1738 QPoint pos;
1739 char mem1Name[100];
1740 size_t i;
1741 QSize size;
1742
be44e757 1743 // Point on the emulator settings
cf76e892 1744 QSettings settings("Underground Software", "Virtual Jaguar");
be44e757 1745 settings.beginGroup("ui");
cf76e892
JPM
1746
1747 // Emulator main window UI information
1748 mainWinPosition = settings.value("pos", QPoint(200, 200)).toPoint();
1749 size = settings.value("size", QSize(400, 400)).toSize();
1750 resize(size);
1751 move(mainWinPosition);
1752 pos = settings.value("cartLoadPos", QPoint(200, 200)).toPoint();
1753 filePickWin->move(pos);
1754
1755 // Alpine debug UI information
1756 if (vjs.hardwareTypeAlpine || vjs.softTypeDebugger)
1757 {
1758 // CPU registers UI information
1759 pos = settings.value("cpuBrowseWinPos", QPoint(200, 200)).toPoint();
1760 cpuBrowseWin->move(pos);
1761 settings.value("cpuBrowseWinIsVisible", false).toBool() ? ShowCPUBrowserWin() : void();
1762
1763 // Memory browser UI information
1764 pos = settings.value("memBrowseWinPos", QPoint(200, 200)).toPoint();
1765 memBrowseWin->move(pos);
1766 settings.value("memBrowseWinIsVisible", false).toBool() ? ShowMemoryBrowserWin() : void();
1767
1768 // Stack browser UI information
1769 pos = settings.value("stackBrowseWinPos", QPoint(200, 200)).toPoint();
1770 stackBrowseWin->move(pos);
1771 settings.value("stackBrowseWinIsVisible", false).toBool() ? ShowStackBrowserWin() : void();
1772 size = settings.value("stackBrowseWinSize", QSize(400, 400)).toSize();
1773 stackBrowseWin->resize(size);
1774
1775 // Emulator status UI information
1776 pos = settings.value("emuStatusWinPos", QPoint(200, 200)).toPoint();
1777 emuStatusWin->move(pos);
1778 settings.value("emuStatusWinIsVisible", false).toBool() ? ShowEmuStatusWin() : void();
1779
1780 // OP (Object Processor) UI information
1781 pos = settings.value("opBrowseWinPos", QPoint(200, 200)).toPoint();
1782 opBrowseWin->move(pos);
1783 settings.value("opBrowseWinIsVisible", false).toBool() ? ShowOPBrowserWin() : void();
1784 size = settings.value("opBrowseWinSize", QSize(400, 400)).toSize();
1785 opBrowseWin->resize(size);
1786
1787 // RISC disassembly UI information
1788 pos = settings.value("riscDasmBrowseWinPos", QPoint(200, 200)).toPoint();
1789 riscDasmBrowseWin->move(pos);
1790 settings.value("riscDasmBrowseWinIsVisible", false).toBool() ? ShowRISCDasmBrowserWin() : void();
1791
1792 // M68k disassembly UI information
1793 pos = settings.value("m68kDasmBrowseWinPos", QPoint(200, 200)).toPoint();
1794 m68kDasmBrowseWin->move(pos);
1795 //settings.value("m68kDasmBrowseWinIsVisible", false).toBool() ? ShowM68KDasmBrowserWin() : void();
1796#ifdef _MSC_VER
1797#pragma message("Warning: !!! Need to check the M68k disassembly window position crashing !!!")
1798#else
1799 #warning "!!! Need to check the M68k disassembly window position crashing !!!"
1800#endif // _MSC_VER
1801 }
1802
1803 // Debugger UI information
1804 if (vjs.softTypeDebugger)
1805 {
1806#if 0
1807 pos = settings.value("m68kDasmWinPos", QPoint(200, 200)).toPoint();
1808 m68kDasmWin->move(pos);
1809 //settings.value("m68kDasmWinIsVisible", false).toBool() ? m68kDasmWin->show() : m68kDasmWin->hide();
1810 pos = settings.value("GPUDasmWinPos", QPoint(200, 200)).toPoint();
1811 GPUDasmWin->move(pos);
1812 pos = settings.value("DSPDasmWinPos", QPoint(200, 200)).toPoint();
1813 DSPDasmWin->move(pos);
1814#endif
1815 // All watch browser UI information
1816 pos = settings.value("allWatchBrowseWinPos", QPoint(200, 200)).toPoint();
1817 allWatchBrowseWin->move(pos);
1818 settings.value("allWatchBrowseWinIsVisible", false).toBool() ? ShowAllWatchBrowserWin() : void();
1819 size = settings.value("allWatchBrowseWinSize", QSize(400, 400)).toSize();
1820 allWatchBrowseWin->resize(size);
1821
1822 // Heap memory allocation browser UI information
1823 pos = settings.value("heapallocatorBrowseWinPos", QPoint(200, 200)).toPoint();
1824 heapallocatorBrowseWin->move(pos);
1825 settings.value("heapallocatorBrowseWinIsVisible", false).toBool() ? ShowHeapAllocatorBrowserWin() : void();
1826 size = settings.value("heapallocatorBrowseWinSize", QSize(400, 400)).toSize();
1827 heapallocatorBrowseWin->resize(size);
1828
1829 // Exception Vector Table UI Information
1830 pos = settings.value("exceptionVectorTableBrowseWinPos", QPoint(200, 200)).toPoint();
1831 exceptionvectortableBrowseWin->move(pos);
1832 settings.value("exceptionVectorTableBrowseWinIsVisible", false).toBool() ? ShowExceptionVectorTableBrowserWin() : void();
1833 size = settings.value("exceptionVectorTableBrowseWinSize", QSize(400, 400)).toSize();
1834 exceptionvectortableBrowseWin->resize(size);
1835
1836 // Memories browser UI information
1837 for (i = 0; i < vjs.nbrmemory1browserwindow; i++)
1838 {
1839 sprintf(mem1Name, "mem1BrowseWinPos[%i]", (unsigned int)i);
1840 pos = settings.value(mem1Name, QPoint(200, 200)).toPoint();
1841 mem1BrowseWin[i]->move(pos);
1842 sprintf(mem1Name, "mem1BrowseWinIsVisible[%i]", (unsigned int)i);
1843 settings.value(mem1Name, false).toBool() ? ShowMemory1BrowserWin((int)i) : void();
1844 sprintf(mem1Name, "mem1BrowseWinSize[%i]", (unsigned int)i);
1845 size = settings.value(mem1Name, QSize(400, 400)).toSize();
1846 mem1BrowseWin[i]->resize(size);
1847 }
1848 }
be44e757
JPM
1849
1850 settings.endGroup();
cf76e892
JPM
1851}
1852
1853
1854// Save the settings
1855void MainWin::WriteSettings(void)
1856{
be44e757 1857 // Point on the emulator settings
cf76e892 1858 QSettings settings("Underground Software", "Virtual Jaguar");
be44e757
JPM
1859 //settings.setValue("pos", pos());
1860 //settings.setValue("size", size());
1861 //settings.setValue("cartLoadPos", filePickWin->pos());
cf76e892
JPM
1862
1863 settings.setValue("zoom", zoomLevel);
1864 settings.setValue("showUnknownSoftware", allowUnknownSoftware);
1865 settings.setValue("lastEditedProfile", lastEditedProfile);
1866
1867 settings.setValue("useJoystick", vjs.useJoystick);
1868 settings.setValue("joyport", vjs.joyport);
1869 settings.setValue("hardwareTypeNTSC", vjs.hardwareTypeNTSC);
1870 settings.setValue("frameSkip", vjs.frameSkip);
1871 settings.setValue("useJaguarBIOS", vjs.useJaguarBIOS);
1872 settings.setValue("GPUEnabled", vjs.GPUEnabled);
1873 settings.setValue("DSPEnabled", vjs.DSPEnabled);
1874 settings.setValue("audioEnabled", vjs.audioEnabled);
1875 settings.setValue("usePipelinedDSP", vjs.usePipelinedDSP);
1876 settings.setValue("fullscreen", vjs.fullscreen);
1877 settings.setValue("useOpenGL", vjs.useOpenGL);
1878 settings.setValue("glFilterType", vjs.glFilter);
1879 settings.setValue("renderType", vjs.renderType);
cf76e892
JPM
1880 settings.setValue("biosType", vjs.biosType);
1881 settings.setValue("useFastBlitter", vjs.useFastBlitter);
1882 settings.setValue("JagBootROM", vjs.jagBootPath);
1883 settings.setValue("CDBootROM", vjs.CDBootPath);
1884 settings.setValue("EEPROMs", vjs.EEPROMPath);
1885 settings.setValue("ROMs", vjs.ROMPath);
be44e757
JPM
1886
1887 // Read settings from the Alpine mode
1888 settings.beginGroup("alpine");
1889 settings.setValue("refresh", vjs.refresh);
cf76e892
JPM
1890 settings.setValue("DefaultROM", vjs.alpineROMPath);
1891 settings.setValue("DefaultABS", vjs.absROMPath);
be44e757
JPM
1892 settings.setValue("writeROM", vjs.allowWritesToROM);
1893 settings.endGroup();
1894
1895 // Read settings from the Debugger mode
1896 settings.beginGroup("debugger");
cf76e892
JPM
1897 settings.setValue("DisplayHWLabels", vjs.displayHWlabels);
1898 settings.setValue("NbrDisasmLines", vjs.nbrdisasmlines);
cf76e892
JPM
1899 settings.setValue("DisasmOpcodes", vjs.disasmopcodes);
1900 settings.setValue("displayFullSourceFilename", vjs.displayFullSourceFilename);
1901 settings.setValue("NbrMemory1BrowserWindow", (unsigned int)vjs.nbrmemory1browserwindow);
be44e757
JPM
1902 settings.setValue("DefaultROM", vjs.debuggerROMPath);
1903
1904 settings.endGroup();
cf76e892
JPM
1905
1906#if 0
1907 settings.setValue("p1k_up", vjs.p1KeyBindings[BUTTON_U]);
1908 settings.setValue("p1k_down", vjs.p1KeyBindings[BUTTON_D]);
1909 settings.setValue("p1k_left", vjs.p1KeyBindings[BUTTON_L]);
1910 settings.setValue("p1k_right", vjs.p1KeyBindings[BUTTON_R]);
1911 settings.setValue("p1k_c", vjs.p1KeyBindings[BUTTON_C]);
1912 settings.setValue("p1k_b", vjs.p1KeyBindings[BUTTON_B]);
1913 settings.setValue("p1k_a", vjs.p1KeyBindings[BUTTON_A]);
1914 settings.setValue("p1k_option", vjs.p1KeyBindings[BUTTON_OPTION]);
1915 settings.setValue("p1k_pause", vjs.p1KeyBindings[BUTTON_PAUSE]);
1916 settings.setValue("p1k_0", vjs.p1KeyBindings[BUTTON_0]);
1917 settings.setValue("p1k_1", vjs.p1KeyBindings[BUTTON_1]);
1918 settings.setValue("p1k_2", vjs.p1KeyBindings[BUTTON_2]);
1919 settings.setValue("p1k_3", vjs.p1KeyBindings[BUTTON_3]);
1920 settings.setValue("p1k_4", vjs.p1KeyBindings[BUTTON_4]);
1921 settings.setValue("p1k_5", vjs.p1KeyBindings[BUTTON_5]);
1922 settings.setValue("p1k_6", vjs.p1KeyBindings[BUTTON_6]);
1923 settings.setValue("p1k_7", vjs.p1KeyBindings[BUTTON_7]);
1924 settings.setValue("p1k_8", vjs.p1KeyBindings[BUTTON_8]);
1925 settings.setValue("p1k_9", vjs.p1KeyBindings[BUTTON_9]);
1926 settings.setValue("p1k_pound", vjs.p1KeyBindings[BUTTON_d]);
1927 settings.setValue("p1k_star", vjs.p1KeyBindings[BUTTON_s]);
1928
1929 settings.setValue("p2k_up", vjs.p2KeyBindings[BUTTON_U]);
1930 settings.setValue("p2k_down", vjs.p2KeyBindings[BUTTON_D]);
1931 settings.setValue("p2k_left", vjs.p2KeyBindings[BUTTON_L]);
1932 settings.setValue("p2k_right", vjs.p2KeyBindings[BUTTON_R]);
1933 settings.setValue("p2k_c", vjs.p2KeyBindings[BUTTON_C]);
1934 settings.setValue("p2k_b", vjs.p2KeyBindings[BUTTON_B]);
1935 settings.setValue("p2k_a", vjs.p2KeyBindings[BUTTON_A]);
1936 settings.setValue("p2k_option", vjs.p2KeyBindings[BUTTON_OPTION]);
1937 settings.setValue("p2k_pause", vjs.p2KeyBindings[BUTTON_PAUSE]);
1938 settings.setValue("p2k_0", vjs.p2KeyBindings[BUTTON_0]);
1939 settings.setValue("p2k_1", vjs.p2KeyBindings[BUTTON_1]);
1940 settings.setValue("p2k_2", vjs.p2KeyBindings[BUTTON_2]);
1941 settings.setValue("p2k_3", vjs.p2KeyBindings[BUTTON_3]);
1942 settings.setValue("p2k_4", vjs.p2KeyBindings[BUTTON_4]);
1943 settings.setValue("p2k_5", vjs.p2KeyBindings[BUTTON_5]);
1944 settings.setValue("p2k_6", vjs.p2KeyBindings[BUTTON_6]);
1945 settings.setValue("p2k_7", vjs.p2KeyBindings[BUTTON_7]);
1946 settings.setValue("p2k_8", vjs.p2KeyBindings[BUTTON_8]);
1947 settings.setValue("p2k_9", vjs.p2KeyBindings[BUTTON_9]);
1948 settings.setValue("p2k_pound", vjs.p2KeyBindings[BUTTON_d]);
1949 settings.setValue("p2k_star", vjs.p2KeyBindings[BUTTON_s]);
1950#endif
1951
1952 WriteProfiles(&settings);
1953}
1954
1955
1956// Save the UI settings
1957void MainWin::WriteUISettings(void)
1958{
1959 char mem1Name[100];
1960 size_t i;
1961
be44e757 1962 // Point on the emulator settings
cf76e892 1963 QSettings settings("Underground Software", "Virtual Jaguar");
be44e757 1964 settings.beginGroup("ui");
cf76e892
JPM
1965
1966 // Emulator UI information
1967 settings.setValue("pos", pos());
1968 settings.setValue("size", size());
1969 settings.setValue("cartLoadPos", filePickWin->pos());
1970 settings.setValue("zoom", zoomLevel);
1971
1972 // Alpine debug UI information
1973 if (vjs.hardwareTypeAlpine || vjs.softTypeDebugger)
1974 {
1975 settings.setValue("cpuBrowseWinPos", cpuBrowseWin->pos());
1976 settings.setValue("cpuBrowseWinIsVisible", cpuBrowseWin->isVisible());
1977 settings.setValue("memBrowseWinPos", memBrowseWin->pos());
1978 settings.setValue("memBrowseWinIsVisible", memBrowseWin->isVisible());
1979 settings.setValue("stackBrowseWinPos", stackBrowseWin->pos());
1980 settings.setValue("stackBrowseWinIsVisible", stackBrowseWin->isVisible());
1981 settings.setValue("stackBrowseWinSize", stackBrowseWin->size());
1982 settings.setValue("emuStatusWinPos", emuStatusWin->pos());
1983 settings.setValue("emuStatusWinIsVisible", emuStatusWin->isVisible());
1984 settings.setValue("opBrowseWinPos", opBrowseWin->pos());
1985 settings.setValue("opBrowseWinIsVisible", opBrowseWin->isVisible());
1986 settings.setValue("opBrowseWinSize", opBrowseWin->size());
1987 settings.setValue("riscDasmBrowseWinPos", riscDasmBrowseWin->pos());
1988 settings.setValue("riscDasmBrowseWinIsVisible", riscDasmBrowseWin->isVisible());
1989 settings.setValue("m68kDasmBrowseWinPos", m68kDasmBrowseWin->pos());
1990 settings.setValue("m68kDasmBrowseWinIsVisible", m68kDasmBrowseWin->isVisible());
1991 }
1992
1993 // Debugger UI information
1994 if (vjs.softTypeDebugger)
1995 {
1996#if 0
1997 settings.setValue("m68kDasmWinPos", m68kDasmWin->pos());
1998 //settings.setValue("m68kDasmWinIsVisible", m68kDasmWin->isVisible());
1999 settings.setValue("GPUDasmWinPos", GPUDasmWin->pos());
2000 settings.setValue("DSPDasmWinPos", DSPDasmWin->pos());
2001#endif
2002 settings.setValue("allWatchBrowseWinPos", allWatchBrowseWin->pos());
2003 settings.setValue("allWatchBrowseWinIsVisible", allWatchBrowseWin->isVisible());
2004 settings.setValue("allWatchBrowseWinSize", allWatchBrowseWin->size());
2005 settings.setValue("heapallocatorBrowseWinPos", heapallocatorBrowseWin->pos());
2006 settings.setValue("heapallocatorBrowseWinIsVisible", heapallocatorBrowseWin->isVisible());
2007 settings.setValue("heapallocatorBrowseWinSize", heapallocatorBrowseWin->size());
2008 settings.setValue("exceptionVectorTableBrowseWinPos", exceptionvectortableBrowseWin->pos());
2009 settings.setValue("exceptionVectorTableBrowseWinIsVisible", exceptionvectortableBrowseWin->isVisible());
2010 settings.setValue("exceptionVectorTableBrowseWinSize", exceptionvectortableBrowseWin->size());
2011 for (i = 0; i < vjs.nbrmemory1browserwindow; i++)
2012 {
2013 sprintf(mem1Name, "mem1BrowseWinPos[%i]", (unsigned int)i);
2014 settings.setValue(mem1Name, mem1BrowseWin[i]->pos());
2015 sprintf(mem1Name, "mem1BrowseWinIsVisible[%i]", (unsigned int)i);
2016 settings.setValue(mem1Name, mem1BrowseWin[i]->isVisible());
2017 sprintf(mem1Name, "mem1BrowseWinSize[%i]", (unsigned int)i);
2018 settings.setValue(mem1Name, mem1BrowseWin[i]->size());
2019 }
2020 }
be44e757
JPM
2021
2022 settings.endGroup();
cf76e892
JPM
2023}
2024
2025
2026// Refresh alpine debug windows
2027void MainWin::RefreshAlpineWindows(void)
2028{
2029 cpuBrowseWin->RefreshContents();
2030 memBrowseWin->RefreshContents();
2031 stackBrowseWin->RefreshContents();
2032 emuStatusWin->RefreshContents();
2033 opBrowseWin->RefreshContents();
2034 riscDasmBrowseWin->RefreshContents();
2035 m68kDasmBrowseWin->RefreshContents();
2036}
2037
2038
2039// Refresh soft debugger & alpine debug windows
2040void MainWin::RefreshDebuggerWindows(void)
2041{
2042 size_t i;
2043
2044 if (vjs.softTypeDebugger)
2045 {
2046 m68kDasmWin->RefreshContents();
2047 GPUDasmWin->RefreshContents();
2048 DSPDasmWin->RefreshContents();
2049 allWatchBrowseWin->RefreshContents();
2050 heapallocatorBrowseWin->RefreshContents();
2051 for (i = 0; i < vjs.nbrmemory1browserwindow; i++)
2052 {
2053 mem1BrowseWin[i]->RefreshContents(i);
2054 }
2055
2056 RefreshAlpineWindows();
2057 }
2058}