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