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