Handle number of M68K cycles used when tracing in debugger mode
[clinton/Virtual-Jaguar-Rx.git] / src / gui / app.cpp
1 //
2 // app.cpp - Qt-based GUI for Virtual Jaguar
3 //
4 // by James Hammons
5 // (C) 2010 Underground Software
6 //
7 // JLH = James Hammons <jlhamm@acm.org>
8 // JPM = Jean-Paul Mari <djipi.mari@gmail.com>
9 //
10 // Who When What
11 // --- ---------- -----------------------------------------------------------
12 // JLH 12/23/2009 Created this file
13 // JLH 01/21/2011 Added SDL initialization
14 // JLH 06/26/2011 Added fix to keep SDL from hijacking main() on win32
15 // JLH 05/24/2012 Added option switches
16 // JLH 03/05/2013 Fixed console redirection on win32 platform :-P
17 // JPM Sept./2016 Visual Studio support, and Soft debugger support (--debugger)
18 // JPM 09/ /2017 Added option (--dram-max) to support 8MB ram (which doesn't exist)
19 // JPM Sept./2017 Added the 'Rx' word to the emulator name, updated the credits line, added option (--es-all, --es-ui, --es-alpine & --es-debugger) to support the erase settings
20 // JPM Oct./2018 Added the Rx version's contact in the help text, added timer initialisation in the SDL_Init
21 // JPM Apr./2019 Fixed a command line option duplication
22 //
23
24 #include "app.h"
25
26 #include <SDL.h>
27 #include <QtWidgets/QApplication>
28 #include "gamepad.h"
29 #include "log.h"
30 #include "mainwin.h"
31 #include "profile.h"
32 #include "settings.h"
33 #include "version.h"
34 #include "debugger/DBGManager.h"
35
36 // Apparently on win32, SDL is hijacking main from Qt. So let's do this:
37 #if defined (__GCCWIN32__) || defined (_MSC_VER)
38 #undef main
39 #include <windows.h> // Ick, but needed for console redirection on win32 :-O
40 #endif
41
42 // Function prototypes...
43 static bool ParseCommandLine(int argc, char * argv[]);
44 static void ParseOptions(int argc, char * argv[]);
45
46
47 //hm. :-/
48 // This is stuff we pass into the mainWindow...
49 // Also, these are defaults. :-)
50 bool noUntunedTankPlease = false;
51 bool loadAndGo = false;
52 bool useLogfile = false;
53 QString filename;
54
55 // Here's the main application loop--short and simple...
56 int main(int argc, char * argv[])
57 {
58 // Win32 console redirection, because MS and their band of super geniuses
59 // decided that nobody would ever launch an app from the command line. :-P
60 // [Unfortunately, this doesn't seem to work on Vista/7. :-(]
61 #if defined (__GCCWIN32__) || defined (_MSC_VER)
62 BOOL(WINAPI * AttachConsole)(DWORD dwProcessId);
63
64 AttachConsole = (BOOL (WINAPI *)(DWORD))GetProcAddress(LoadLibraryA("kernel32.dll"), "AttachConsole");
65
66 if (AttachConsole != NULL && AttachConsole(((DWORD)-1)))
67 {
68 if (_fileno(stdout) == -1)
69 freopen("CONOUT$", "wb", stdout);
70 if (_fileno(stderr) == -1)
71 freopen("CONOUT$", "wb", stderr);
72 if (_fileno(stdin) == -1)
73 freopen("CONIN$", "rb", stdin);
74
75 // Fix C++
76 std::ios::sync_with_stdio();
77 }
78 #endif
79
80 // Normally, this would be read in from the settings module... :-P
81 vjs.hardwareTypeAlpine = false;
82 vjs.softTypeDebugger = false;
83 vjs.DRAM_size = 0x200000;
84 // This is stuff we pass into the mainWindow...
85 // noUntunedTankPlease = false;
86
87 // Check for options that must be in place be constructing the App object
88 if (!ParseCommandLine(argc, argv))
89 {
90 return 0;
91 }
92
93 Q_INIT_RESOURCE(virtualjaguar); // This must the same name as the exe filename
94 //or is it the .qrc filename???
95 // This is so we can pass this stuff using signal/slot mechanism...
96 //this is left here to remind me not to try doing this again :-P
97 //ick int id = qRegisterMetaType<uint32>();
98
99 int retVal = -1; // Default is failure
100
101 if (useLogfile)
102 {
103 bool success = (bool)LogInit("./virtualjaguar.log"); // Init logfile
104
105 if (!success)
106 printf("Failed to open virtualjaguar.log for writing!\n");
107 }
108
109 // Set up SDL library
110 if (SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0)
111 {
112 WriteLog("VJ: Could not initialize the SDL library: %s\n", SDL_GetError());
113 }
114 else
115 {
116 WriteLog("VJ: SDL (joystick, audio) successfully initialized.\n");
117 DBGManager_Init();
118 App app(argc, argv); // Declare an instance of the application
119 Gamepad::AllocateJoysticks();
120 AutoConnectProfiles();
121 retVal = app.exec(); // And run it!
122 DBGManager_Close();
123 Gamepad::DeallocateJoysticks();
124
125 // Free SDL components last...!
126 SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_AUDIO);
127 SDL_Quit();
128 }
129
130 #if defined (__GCCWIN32__) || defined (_MSC_VER)
131 #if 0
132 fclose(ctt);
133 #endif
134 #endif
135 // Close logfile
136 LogDone();
137 return retVal;
138 }
139
140
141 //
142 // Main app constructor--we stick globally accessible stuff here... (?)
143 //
144 App::App(int & argc, char * argv[]): QApplication(argc, argv)
145 {
146 bool loadAndGo = !filename.isEmpty();
147
148 mainWindow = new MainWin(loadAndGo);
149 mainWindow->plzDontKillMyComputer = noUntunedTankPlease;
150 // Override defaults with command line (if any)
151 ParseOptions(argc, argv);
152 mainWindow->SyncUI();
153
154 if (loadAndGo)
155 {
156 mainWindow->LoadFile(filename);
157
158 if (!mainWindow->cartridgeLoaded)
159 printf("Could not load file \"%s\"!\n", filename.toUtf8().data());
160 }
161
162 mainWindow->show();
163 }
164
165
166 //
167 // Here we parse out stuff that needs to be looked at *before* we construct the
168 // App object.
169 //
170 bool ParseCommandLine(int argc, char * argv[])
171 {
172 for(int i=1; i<argc; i++)
173 {
174 if ((strcmp(argv[i], "--help") == 0) || (strcmp(argv[i], "-h") == 0) || (strcmp(argv[i], "-?") == 0))
175 {
176 printf(
177 "Virtual Jaguar " VJ_RELEASE_VERSION " (" VJ_RELEASE_SUBVERSION ") Rx - " __DATE__ "\n"
178 "Based upon Virtual Jaguar core v1.0.0 by David Raingeard.\n"
179 "Based upon the work by James Hammons (Linux/WIN32), Niels Wagenaar (Linux/WIN32),\n"
180 "Carwin Jones (BeOS), and Adam Green (MacOS)\n"
181 "Contact: http://sdlemu.ngemu.com/ | sdlemu@ngemu.com\n"
182 "Contact: https://github.com/djipi/Virtual-Jaguar-Rx | djipi.mari@gmail.com\n"
183 "\n"
184 "Usage:\n"
185 " virtualjaguar [<filename>] [switches]\n"
186 "\n"
187 " Option Description\n"
188 " ---------------- -----------------------------------\n"
189 " <filename> Name of file to autoload\n"
190 " --alpine -a Put Virtual Jaguar into Alpine mode\n"
191 " --debugger -D Put Virtual Jaguar into Debugger mode\n"
192 " --pal -p PAL mode\n"
193 " --ntsc -n NTSC mode\n"
194 " --dram-max Set DRAM size to 8MB\n"
195 " --bios -b Boot using Jaguar BIOS\n"
196 " --no-bios Do not use Jaguar BIOS\n"
197 " --gpu -g Enable GPU\n"
198 " --no-gpu Disable GPU\n"
199 " --dsp -d Enable DSP\n"
200 " --no-dsp Disable DSP\n"
201 " --fullscreen -f Start in full screen mode\n"
202 " --blur -B Enable GL bilinear filter\n"
203 " --no-blur Disable GL bilinear filtering\n"
204 " --log -l Create and use log file\n"
205 " --no-log Do not use log file (default)\n"
206 " --help -h Show this message\n"
207 " -? Show this message\n"
208 " --es-all Erase all settings\n"
209 " --es-ui Erase UI settings only\n"
210 " --es-alpine Erase alpine mode settings only\n"
211 " --es-debugger Erase debugger mode settings only\n"
212 " --please-dont-kill-my-computer\n"
213 " -z Run Virtual Jaguar without \"snow\"\n"
214 "\n"
215 "Invoking Virtual Jaguar with no filename will cause it to boot up\n"
216 "with the VJ GUI. Using Alpine mode will enable log file.\n"
217 "\n");
218 return false;
219 }
220
221 // Easter egg
222 if (strcmp(argv[i], "--yarrr") == 0)
223 {
224 printf("\n");
225 printf("Shiver me timbers!\n");
226 printf("\n");
227 return false;
228 }
229
230 // Erase settings
231 if (strstr(argv[i], "--es-"))
232 {
233 printf("\n");
234 if (EraseSettings(&argv[i][5]))
235 {
236 printf("Settings have been erased");
237 }
238 else
239 {
240 printf("No requested settings have been found");
241 }
242 printf("\n\n");
243 return false;
244 }
245
246 // Alpine/Debug mode
247 if ((strcmp(argv[i], "--alpine") == 0) || (strcmp(argv[i], "-a") == 0))
248 {
249 printf("Alpine Mode enabled.\n");
250 vjs.hardwareTypeAlpine = true;
251 // We also enable logging as well :-)
252 useLogfile = true;
253 }
254
255 // Debugger mode
256 if ((strcmp(argv[i], "--debugger") == 0) || (strcmp(argv[i], "-D") == 0))
257 {
258 printf("Debugger mode enabled.\n");
259 vjs.softTypeDebugger = true;
260 }
261
262 // No snow display
263 if ((strcmp(argv[i], "--please-dont-kill-my-computer") == 0) || (strcmp(argv[i], "-z") == 0))
264 {
265 noUntunedTankPlease = true;
266 }
267
268 // Log file
269 if ((strcmp(argv[i], "--log") == 0) || (strcmp(argv[i], "-l") == 0))
270 {
271 printf("Log file enabled.\n");
272 useLogfile = true;
273 }
274
275 // No log file
276 if (strcmp(argv[i], "--no-log") == 0)
277 {
278 printf("Log file disabled.\n");
279 useLogfile = false;
280 }
281
282 // DRAM size max
283 if (strcmp(argv[i], "--dram-max") == 0)
284 {
285 printf("DRAM size set at 8 MBytes.\n");
286 vjs.DRAM_size = 0x800000;
287 }
288
289 // Check for filename
290 if (argv[i][0] != '-')
291 {
292 loadAndGo = true;
293 filename = argv[i];
294 }
295 }
296
297 return true;
298 }
299
300
301 //
302 // This is to override settings loaded from the config file.
303 // Note that settings set here will become the new defaults!
304 // (Not any more: Settings are only saved if the config dialog was OKed, or the toolbar buttons were pressed.)
305 //
306 void ParseOptions(int argc, char * argv[])
307 {
308 for(int i=1; i<argc; i++)
309 {
310 // PAL mode
311 if ((strcmp(argv[i], "--pal") == 0) || (strcmp(argv[i], "-p") == 0))
312 {
313 vjs.hardwareTypeNTSC = false;
314 }
315
316 // NTSC mode
317 if ((strcmp(argv[i], "--ntsc") == 0) || (strcmp(argv[i], "-n") == 0))
318 {
319 vjs.hardwareTypeNTSC = true;
320 }
321
322 // Boot with Bios
323 if ((strcmp(argv[i], "--bios") == 0) || (strcmp(argv[i], "-b") == 0))
324 {
325 vjs.useJaguarBIOS = true;
326 }
327
328 // No boot with Bios
329 if (strcmp(argv[i], "--no-bios") == 0)
330 {
331 vjs.useJaguarBIOS = false;
332 }
333
334 // GPU enable
335 if ((strcmp(argv[i], "--gpu") == 0) || (strcmp(argv[i], "-g") == 0))
336 {
337 vjs.GPUEnabled = true;
338 }
339
340 // GPU disable
341 if (strcmp(argv[i], "--no-gpu") == 0)
342 {
343 vjs.GPUEnabled = false;
344 }
345
346 // DSP enable
347 if ((strcmp(argv[i], "--dsp") == 0) || (strcmp(argv[i], "-d") == 0))
348 {
349 vjs.DSPEnabled = true;
350 vjs.audioEnabled = true;
351 }
352
353 // DSP disable
354 if (strcmp(argv[i], "--no-dsp") == 0)
355 {
356 vjs.DSPEnabled = false;
357 vjs.audioEnabled = false;
358 }
359
360 // Fullscreen mode
361 if ((strcmp(argv[i], "--fullscreen") == 0) || (strcmp(argv[i], "-f") == 0))
362 {
363 vjs.fullscreen = true;
364 }
365
366 // Enable GL bilinear filter
367 if ((strcmp(argv[i], "--blur") == 0) || (strcmp(argv[i], "-B") == 0))
368 {
369 vjs.glFilter = 1;
370 }
371
372 // Disable GL bilinear filter
373 if (strcmp(argv[i], "--no-blur") == 0)
374 {
375 vjs.glFilter = 0;
376 }
377 }
378 }
379
380 #if 0
381 bool useJoystick;
382 int32 joyport; // Joystick port
383 bool hardwareTypeNTSC; // Set to false for PAL
384 bool useJaguarBIOS;
385 bool GPUEnabled;
386 bool DSPEnabled;
387 bool usePipelinedDSP;
388 bool fullscreen;
389 bool useOpenGL;
390 uint32 glFilter;
391 bool hardwareTypeAlpine;
392 bool softTypeDebugger;
393 bool audioEnabled;
394 uint32 frameSkip;
395 uint32 renderType;
396 bool allowWritesToROM;
397
398 // Keybindings in order of U, D, L, R, C, B, A, Op, Pa, 0-9, #, *
399
400 uint32 p1KeyBindings[21];
401 uint32 p2KeyBindings[21];
402
403 // Paths
404
405 char ROMPath[MAX_PATH];
406 char jagBootPath[MAX_PATH];
407 char CDBootPath[MAX_PATH];
408 char EEPROMPath[MAX_PATH];
409 char alpineROMPath[MAX_PATH];
410 char absROMPath[MAX_PATH];
411 #endif
412