1 /*****************************************************************************
2 ** $Source: /cvsroot/bluemsx/blueMSX/Src/Emulator/CommandLine.c,v $
3 **
4 ** $Revision: 1.35 $
5 **
6 ** $Date: 2008/08/31 06:13:13 $
7 **
8 ** More info: http://www.bluemsx.com
9 **
10 ** Copyright (C) 2003-2006 Daniel Vik
11 **
12 ** This program is free software; you can redistribute it and/or modify
13 ** it under the terms of the GNU General Public License as published by
14 ** the Free Software Foundation; either version 2 of the License, or
15 ** (at your option) any later version.
16 **
17 ** This program is distributed in the hope that it will be useful,
18 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ** GNU General Public License for more details.
21 **
22 ** You should have received a copy of the GNU General Public License
23 ** along with this program; if not, write to the Free Software
24 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 **
26 ******************************************************************************
27 */
28 #include "CommandLine.h"
29 #include "TokenExtract.h"
30 #include "IsFileExtension.h"
31 #include "MediaDb.h"
32 #include "ziphelper.h"
33 #include "Machine.h"
34 #include "Casette.h"
35 #include "Disk.h"
36 #include "FileHistory.h"
37 #include "LaunchFile.h"
38 #include "Emulator.h"
39 #include "StrcmpNoCase.h"
40 #include "AppConfig.h"
41 #include <stdlib.h>
42 #include <string.h>
43
romNameToType(char * name)44 static RomType romNameToType(char* name) {
45 RomType romType = ROM_UNKNOWN;
46
47 if (name == NULL) {
48 return ROM_UNKNOWN;
49 }
50
51 romType = mediaDbStringToType(name);
52
53 if (romType == ROM_UNKNOWN) {
54 romType = atoi(name);
55 if (romType < ROM_STANDARD || romType > ROM_MAXROMID) {
56 romType = ROM_UNKNOWN;
57 }
58 }
59
60 return romType;
61 }
62
isRomFileType(char * filename,char * inZip)63 static int isRomFileType(char* filename, char* inZip) {
64 inZip[0] = 0;
65
66 if (isFileExtension(filename, ".zip")) {
67 int count;
68 char* fileList;
69
70 fileList = zipGetFileList(filename, ".rom", &count);
71 if (fileList) {
72 strcpy(inZip, fileList);
73 free(fileList);
74 return 1;
75 }
76
77 fileList = zipGetFileList(filename, ".ri", &count);
78 if (fileList) {
79 strcpy(inZip, fileList);
80 free(fileList);
81 return 1;
82 }
83
84 fileList = zipGetFileList(filename, ".mx1", &count);
85 if (fileList) {
86 strcpy(inZip, fileList);
87 free(fileList);
88 return 1;
89 }
90
91 fileList = zipGetFileList(filename, ".mx2", &count);
92 if (fileList) {
93 strcpy(inZip, fileList);
94 free(fileList);
95 return 1;
96 }
97
98 fileList = zipGetFileList(filename, ".sms", &count);
99 if (fileList) {
100 strcpy(inZip, fileList);
101 free(fileList);
102 return 1;
103 }
104
105 fileList = zipGetFileList(filename, ".col", &count);
106 if (fileList) {
107 strcpy(inZip, fileList);
108 free(fileList);
109 return 1;
110 }
111
112 fileList = zipGetFileList(filename, ".sg", &count);
113 if (fileList) {
114 strcpy(inZip, fileList);
115 free(fileList);
116 return 1;
117 }
118
119 fileList = zipGetFileList(filename, ".sc", &count);
120 if (fileList) {
121 strcpy(inZip, fileList);
122 free(fileList);
123 return 1;
124 }
125
126 return 0;
127 }
128
129 return isFileExtension(filename, ".rom") ||
130 isFileExtension(filename, ".ri") ||
131 isFileExtension(filename, ".mx1") ||
132 isFileExtension(filename, ".mx2") ||
133 isFileExtension(filename, ".sms") ||
134 isFileExtension(filename, ".col") ||
135 isFileExtension(filename, ".sg") ||
136 isFileExtension(filename, ".sc");
137 }
138
isDskFileType(char * filename,char * inZip)139 static int isDskFileType(char* filename, char* inZip) {
140 inZip[0] = 0;
141
142 if (isFileExtension(filename, ".zip")) {
143 int count;
144 char* fileList;
145
146 fileList = zipGetFileList(filename, ".dsk", &count);
147 if (fileList) {
148 strcpy(inZip, fileList);
149 free(fileList);
150 return 1;
151 }
152
153 fileList = zipGetFileList(filename, ".di1", &count);
154 if (fileList) {
155 strcpy(inZip, fileList);
156 free(fileList);
157 return 1;
158 }
159
160 fileList = zipGetFileList(filename, ".di2", &count);
161 if (fileList) {
162 strcpy(inZip, fileList);
163 free(fileList);
164 return 1;
165 }
166
167 fileList = zipGetFileList(filename, ".360", &count);
168 if (fileList) {
169 strcpy(inZip, fileList);
170 free(fileList);
171 return 1;
172 }
173
174 fileList = zipGetFileList(filename, ".720", &count);
175 if (fileList) {
176 strcpy(inZip, fileList);
177 free(fileList);
178 return 1;
179 }
180
181 fileList = zipGetFileList(filename, ".sf7", &count);
182 if (fileList) {
183 strcpy(inZip, fileList);
184 free(fileList);
185 return 1;
186 }
187
188 return 0;
189 }
190
191 return isFileExtension(filename, ".dsk") ||
192 isFileExtension(filename, ".di1") ||
193 isFileExtension(filename, ".di2") ||
194 isFileExtension(filename, ".360") ||
195 isFileExtension(filename, ".720") ||
196 isFileExtension(filename, ".Sf7");
197 }
198
isCasFileType(char * filename,char * inZip)199 static int isCasFileType(char* filename, char* inZip) {
200 inZip[0] = 0;
201
202 if (isFileExtension(filename, ".zip")) {
203 int count;
204 char* fileList;
205
206 fileList = zipGetFileList(filename, ".cas", &count);
207 if (fileList) {
208 strcpy(inZip, fileList);
209 free(fileList);
210 return 1;
211 }
212 return 0;
213 }
214
215 return isFileExtension(filename, ".cas");
216 }
217
checkArg(const char * arg,const char * value)218 static int checkArg(const char* arg, const char* value) {
219 if (arg[0] != '/' && arg[0] != '-') {
220 return 0;
221 }
222
223 return strcmpnocase(arg + 1, value) == 0;
224 }
225
226
emuCheckResetArgument(char * cmdLine)227 int emuCheckResetArgument(char* cmdLine) {
228 int i;
229 char* argument;
230
231 for (i = 0; (argument = extractToken(cmdLine, i)) != NULL; i++) {
232 if (checkArg(argument, "reset")) {
233 return 1;
234 }
235 if (checkArg(argument, "resetregs")) {
236 return 2;
237 }
238 }
239
240 return 0;
241 }
242
emuCheckThemeArgument(char * cmdLine)243 char* emuCheckThemeArgument(char* cmdLine){
244 static char themeName[PROP_MAXPATH];
245 int i;
246 char* argument;
247
248 themeName[0] = 0;
249
250 for (i = 0; (argument = extractToken(cmdLine, i)) != NULL; i++) {
251 if (checkArg(argument, "theme")) {
252 argument = extractToken(cmdLine, i + 1);
253 if (argument != NULL) {
254 strcat(themeName, argument);
255 }
256 return themeName;
257 }
258 }
259
260 return NULL;
261 }
262
emuCheckFullscreenArgument(Properties * properties,char * cmdLine)263 void emuCheckFullscreenArgument(Properties* properties, char* cmdLine){
264 int i;
265 char* argument;
266
267 if (NULL == extractToken(cmdLine, 0)) {
268 return;
269 }
270
271 // properties->video.windowSize = P_VIDEO_SIZEX2;
272
273 for (i = 0; (argument = extractToken(cmdLine, i)) != NULL; i++) {
274 if (checkArg(argument, "fullscreen")) {
275 properties->video.windowSize = P_VIDEO_SIZEFULLSCREEN;
276 }
277 }
278 }
279
emuStartWithArguments(Properties * properties,char * commandLine,char * gamedir)280 static int emuStartWithArguments(Properties* properties, char* commandLine, char *gamedir) {
281 int i;
282 char cmdLine[512] = "";
283 char* argument;
284 char rom1[512] = "";
285 char rom2[512] = "";
286 char rom1zip[256] = "";
287 char rom2zip[256] = "";
288 RomType romType1 = ROM_UNKNOWN;
289 RomType romType2 = ROM_UNKNOWN;
290 char machineName[64] = "";
291 char diskA[512] = "";
292 char diskB[512] = "";
293 char diskAzip[256] = "";
294 char diskBzip[256] = "";
295 char ide1p[256] = "";
296 char ide1s[256] = "";
297 char cas[512] = "";
298 char caszip[256] = "";
299 int fullscreen = 0;
300 #ifdef WII
301 int startEmu = 1; // always start
302 #else
303 int startEmu = 0;
304 #endif
305
306 if (commandLine[0] != '/' && commandLine[1] == ':') {
307 char* ptr;
308 strcat(cmdLine, "\"");
309 strcat(cmdLine, commandLine);
310 ptr = cmdLine + strlen(commandLine);
311 while (ptr > cmdLine && *ptr == ' ') {
312 *ptr-- = '\0';
313 }
314 strcat(cmdLine, "\"");
315 }
316 else {
317 strcat(cmdLine, commandLine);
318 }
319
320 // If one argument, assume it is a rom or disk to run
321 if (!extractToken(cmdLine, 1)) {
322 argument = extractToken(cmdLine, 0);
323
324 if (argument && *argument != '/') {
325 if (*argument == '\"') argument++;
326
327 if (*argument) {
328 int i;
329
330 for (i = 0; i < PROP_MAX_CARTS; i++) {
331 properties->media.carts[i].fileName[0] = 0;
332 properties->media.carts[i].fileNameInZip[0] = 0;
333 properties->media.carts[i].type = ROM_UNKNOWN;
334 updateExtendedRomName(i, properties->media.carts[i].fileName, properties->media.carts[i].fileNameInZip);
335 }
336
337 for (i = 0; i < PROP_MAX_DISKS; i++) {
338 properties->media.disks[i].fileName[0] = 0;
339 properties->media.disks[i].fileNameInZip[0] = 0;
340 updateExtendedDiskName(i, properties->media.disks[i].fileName, properties->media.disks[i].fileNameInZip);
341 }
342
343 return tryLaunchUnknownFile(properties, argument, 1);
344 }
345 return 0;
346 }
347 }
348
349 // If more than one argument, check arguments,
350 // set configuration and then run
351
352 for (i = 0; (argument = extractToken(cmdLine, i)) != NULL; i++) {
353 if (checkArg(argument, "rom1")) {
354 argument = extractTokenEx(cmdLine, ++i, gamedir);
355 if (argument == NULL || !isRomFileType(argument, rom1zip)) return 0; // Invaid argument
356 strcpy(rom1, argument);
357 startEmu = 1;
358 }
359 if (checkArg(argument, "rom1zip")) {
360 argument = extractToken(cmdLine, ++i);
361 if (argument == NULL) return 0;
362 strcpy(rom1zip, argument);
363 }
364 if (checkArg(argument, "romtype1")) {
365 argument = extractToken(cmdLine, ++i);
366 if (argument == NULL) return 0; // Invaid argument
367 romType1 = romNameToType(argument);
368 startEmu = 1;
369 }
370 if (checkArg(argument, "rom2")) {
371 argument = extractTokenEx(cmdLine, ++i, gamedir);
372 if (argument == NULL || !isRomFileType(argument, rom2zip)) return 0; // Invaid argument
373 strcpy(rom2, argument);
374 startEmu = 1;
375 }
376 if (checkArg(argument, "rom2zip")) {
377 argument = extractToken(cmdLine, ++i);
378 if (argument == NULL) return 0;
379 strcpy(rom2zip, argument);
380 }
381 if (checkArg(argument, "romtype2")) {
382 argument = extractToken(cmdLine, ++i);
383 if (argument == NULL) return 0; // Invaid argument
384 romType2 = romNameToType(argument);
385 startEmu = 1;
386 }
387 if (checkArg(argument, "diskA")) {
388 argument = extractTokenEx(cmdLine, ++i, gamedir);
389 if (argument == NULL || !isDskFileType(argument, diskAzip)) return 0; // Invaid argument
390 strcpy(diskA, argument);
391 startEmu = 1;
392 }
393 if (checkArg(argument, "diskAzip")) {
394 argument = extractToken(cmdLine, ++i);
395 if (argument == NULL) return 0;
396 strcpy(diskAzip, argument);
397 }
398 if (checkArg(argument, "diskB")) {
399 argument = extractTokenEx(cmdLine, ++i, gamedir);
400 if (argument == NULL || !isDskFileType(argument, diskBzip)) return 0; // Invaid argument
401 strcpy(diskB, argument);
402 startEmu = 1;
403 }
404 if (checkArg(argument, "diskBzip")) {
405 argument = extractToken(cmdLine, ++i);
406 if (argument == NULL) return 0;
407 strcpy(diskBzip, argument);
408 }
409 if (checkArg(argument, "cas")) {
410 argument = extractTokenEx(cmdLine, ++i, gamedir);
411 if (argument == NULL || !isCasFileType(argument, caszip)) return 0; // Invaid argument
412 strcpy(cas, argument);
413 startEmu = 1;
414 }
415 if (checkArg(argument, "ide1primary")) {
416 argument = extractToken(cmdLine, ++i);
417 if (argument == NULL) return 0; // Invaid argument
418 strcpy(ide1p, argument);
419 startEmu = 1;
420 }
421 if (checkArg(argument, "ide1secondary")) {
422 argument = extractToken(cmdLine, ++i);
423 if (argument == NULL) return 0; // Invaid argument
424 strcpy(ide1s, argument);
425 startEmu = 1;
426 }
427 if (checkArg(argument, "caszip")) {
428 argument = extractToken(cmdLine, ++i);
429 if (argument == NULL) return 0;
430 strcpy(caszip, argument);
431 }
432 if (checkArg(argument, "machine")) {
433 argument = extractToken(cmdLine, ++i);
434 if (argument == NULL) return 0; // Invaid argument
435 strcpy(machineName, argument);
436 if (!machineIsValid(machineName, 1)) return 0;
437 startEmu = 1;
438 }
439 if (checkArg(argument, "fullscreen")) {
440 fullscreen = 1;
441 }
442 }
443
444 if (!startEmu) {
445 return 1;
446 }
447
448 for (i = 0; i < PROP_MAX_CARTS; i++) {
449 properties->media.carts[i].fileName[0] = 0;
450 properties->media.carts[i].fileNameInZip[0] = 0;
451 properties->media.carts[i].type = ROM_UNKNOWN;
452 updateExtendedRomName(i, properties->media.carts[i].fileName, properties->media.carts[i].fileNameInZip);
453 }
454
455 for (i = 0; i < PROP_MAX_DISKS; i++) {
456 properties->media.disks[i].fileName[0] = 0;
457 properties->media.disks[i].fileNameInZip[0] = 0;
458 updateExtendedDiskName(i, properties->media.disks[i].fileName, properties->media.disks[i].fileNameInZip);
459 }
460
461 for (i = 0; i < PROP_MAX_TAPES; i++) {
462 properties->media.tapes[i].fileName[0] = 0;
463 properties->media.tapes[i].fileNameInZip[0] = 0;
464 updateExtendedCasName(i, properties->media.tapes[i].fileName, properties->media.tapes[i].fileNameInZip);
465 }
466
467 if (!strlen(rom1)) {
468 switch (romType1) {
469 case ROM_SCC: strcat(rom1, CARTNAME_SCC); romType1 = ROM_SCC; break;
470 case ROM_SCCPLUS: strcat(rom1, CARTNAME_SCCPLUS); romType1 = ROM_SCCPLUS; break;
471 case ROM_SNATCHER: strcat(rom1, CARTNAME_SNATCHER); break;
472 case ROM_SDSNATCHER: strcat(rom1, CARTNAME_SDSNATCHER); break;
473 case ROM_SCCMIRRORED: strcat(rom1, CARTNAME_SCCMIRRORED); break;
474 case ROM_SCCEXTENDED: strcat(rom1, CARTNAME_SCCEXPANDED); break;
475 case ROM_FMPAC: strcat(rom1, CARTNAME_FMPAC); break;
476 case ROM_PAC: strcat(rom1, CARTNAME_PAC); break;
477 case ROM_GAMEREADER: strcat(rom1, CARTNAME_GAMEREADER); break;
478 case ROM_SUNRISEIDE: strcat(rom1, CARTNAME_SUNRISEIDE); break;
479 case ROM_NOWIND: strcat(rom1, CARTNAME_NOWINDDOS1); break;
480 case ROM_BEERIDE: strcat(rom1, CARTNAME_BEERIDE); break;
481 case ROM_GIDE: strcat(rom1, CARTNAME_GIDE); break;
482 case ROM_GOUDASCSI: strcat(rom1, CARTNAME_GOUDASCSI); break;
483 case ROM_NMS1210: strcat(rom1, CARTNAME_NMS1210); break;
484 case ROM_SONYHBI55: strcat(rom1, CARTNAME_SONYHBI55); break;
485 }
486 }
487
488 if (!strlen(rom2)) {
489 switch (romType2) {
490 case ROM_SCC: strcat(rom2, CARTNAME_SCC); romType2 = ROM_SCC; break;
491 case ROM_SCCPLUS: strcat(rom2, CARTNAME_SCCPLUS); romType2 = ROM_SCCPLUS; break;
492 case ROM_SNATCHER: strcat(rom2, CARTNAME_SNATCHER); break;
493 case ROM_SDSNATCHER: strcat(rom2, CARTNAME_SDSNATCHER); break;
494 case ROM_SCCMIRRORED: strcat(rom2, CARTNAME_SCCMIRRORED); break;
495 case ROM_SCCEXTENDED: strcat(rom2, CARTNAME_SCCEXPANDED); break;
496 case ROM_FMPAC: strcat(rom2, CARTNAME_FMPAC); break;
497 case ROM_PAC: strcat(rom2, CARTNAME_PAC); break;
498 case ROM_GAMEREADER: strcat(rom2, CARTNAME_GAMEREADER); break;
499 case ROM_SUNRISEIDE: strcat(rom2, CARTNAME_SUNRISEIDE); break;
500 case ROM_NOWIND: strcat(rom2, CARTNAME_NOWINDDOS1); break;
501 case ROM_BEERIDE: strcat(rom2, CARTNAME_BEERIDE); break;
502 case ROM_GIDE: strcat(rom2, CARTNAME_GIDE); break;
503 case ROM_GOUDASCSI: strcat(rom2, CARTNAME_GOUDASCSI); break;
504 case ROM_NMS1210: strcat(rom2, CARTNAME_NMS1210); break;
505 case ROM_SONYHBI55: strcat(rom2, CARTNAME_SONYHBI55); break;
506 }
507 }
508
509 if (properties->cassette.rewindAfterInsert) tapeRewindNextInsert();
510
511 if (strlen(rom1) && !insertCartridge(properties, 0, rom1, *rom1zip ? rom1zip : NULL, romType1, -1)) return 0;
512 if (strlen(rom2) && !insertCartridge(properties, 1, rom2, *rom2zip ? rom2zip : NULL, romType2, -1)) return 0;
513 if (strlen(diskA) && !insertDiskette(properties, 0, diskA, *diskAzip ? diskAzip : NULL, -1)) return 0;
514 if (strlen(diskB) && !insertDiskette(properties, 1, diskB, *diskBzip ? diskBzip : NULL, -1)) return 0;
515 if (strlen(ide1p) && !insertDiskette(properties, diskGetHdDriveId(0, 0), ide1p, NULL, -1)) return 0;
516 if (strlen(ide1s) && !insertDiskette(properties, diskGetHdDriveId(0, 1), ide1s, NULL, -1)) return 0;
517 if (strlen(cas) && !insertCassette(properties, 0, cas, *caszip ? caszip : NULL, -1)) return 0;
518
519 if (strlen(machineName)) strcpy(properties->emulation.machineName, machineName);
520 #ifdef WII
521 else strcpy(properties->emulation.machineName, "MSX2 - No Moonsound"); /* If not specified, use MSX2 without moonsound as default */
522 #endif
523
524 emulatorStop();
525 emulatorStart(NULL);
526
527 return 1;
528 }
529
emuTryStartWithArguments(Properties * properties,char * cmdLine,char * gamedir)530 int emuTryStartWithArguments(Properties* properties, char* cmdLine, char *gamedir) {
531 if (cmdLine == NULL || *cmdLine == 0) {
532 if (appConfigGetInt("autostart", 0) != 0) {
533 emulatorStop();
534 emulatorStart(properties->filehistory.quicksave);
535 }
536 return 0;
537 }
538
539 if (*cmdLine) {
540 int success;
541 if (0 == strncmp(cmdLine, "/onearg ", 8)) {
542 char args[2048];
543 char* ptr;
544 sprintf(args, "\"%s", cmdLine + 8);
545 ptr = args + strlen(args);
546 while(*--ptr == ' ') {
547 *ptr = 0;
548 }
549 strcat(args, "\"");
550 success = emuStartWithArguments(properties, args, gamedir);
551 }
552 else {
553 success = emuStartWithArguments(properties, cmdLine, gamedir);
554 }
555 if (!success) {
556 return -1;
557 }
558 }
559
560 return 1;
561 }
562