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