1 /** ADAMEm: Coleco ADAM emulator ********************************************/
2 /**                                                                        **/
3 /**                                ADAMEm.c                                **/
4 /**                                                                        **/
5 /** This file contains the main() function starting the emulator           **/
6 /**                                                                        **/
7 /** Copyright (C) Marcel de Kogel 1996,1997,1998,1999                      **/
8 /**     You are not allowed to distribute this software commercially       **/
9 /**     Please, notify me, if you make any changes to this file            **/
10 /****************************************************************************/
11 
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #include "Coleco.h"
17 #ifdef MSDOS
18 #include "MSDOS.h"
19 #include <sys/stat.h>
20 #include <conio.h>
21 #endif
22 #ifdef LINUX_SVGA
23 #include "SVGALib.h"
24 #endif
25 #ifdef UNIX_X
26 #include "X.h"
27 #endif
28 #include "Help.h"
29 
30 /* Program title for -help output */
31 extern char Title[];
32 
33 #define MAX_CONFIG_FILE_SIZE    1024
34 #define MAX_FILE_NAME           256
35 
36 char *Options[]=
37 {
38   "verbose","help","cpuspeed","ifreq",
39   "cheat","video","sound","joystick","swapbuttons",
40   "expansion","calibrate","overscan","volume","soundtrack",
41   "trap","os7","sensitivity","reverb","chorus","uperiod",
42   "soundquality","speakerchannels","keys","printer","keypad",
43   "eos","wp","diska","diskb","diskc","diskd",
44   "tapea","tapeb","tapec","taped","sync","adam","cv","stereo",
45   "printertype","chipset","sprite","shm","savecpu","palette",
46   "ram","snap","autosnap","diskspeed","tapespeed","lpt","tdos",
47   NULL
48 };
49 
50 char *AbvOptions[]=
51 {
52   "vb","he","cs","if",
53   "cheat","vi","so","js","sb",
54   "ex","ca","os","vo","st",
55   "trap","os7","se","re","ch","up",
56   "sq","sc","ke","pr","kp",
57   "eos","wp","da","db","dc","dd",
58   "ta","tb","tc","td","sy","adam","cv","stereo",
59   "pt","chipset","sprite","shm","savecpu","pal",
60   "ram","sn","asn","ds","ts","lpt","tdos",
61   NULL
62 };
63 
64 #define PROGRAM_ADAMEM  0
65 #define PROGRAM_CVEM    1
66 static int Program;
67 static int CPUSpeed;
68 static int _argc;
69 static char *_argv[256];
70 static char MainConfigFile[MAX_CONFIG_FILE_SIZE];
71 static char SubConfigFile[MAX_CONFIG_FILE_SIZE];
72 static char szTempFileName[MAX_FILE_NAME];
73 static char _CartName[MAX_FILE_NAME];
74 static char CartNameNoExt[MAX_FILE_NAME];
75 static char _SnapshotName[MAX_FILE_NAME];
76 static char _OS7File[MAX_FILE_NAME];
77 static char _EOSFile[MAX_FILE_NAME];
78 static char _WPFile[MAX_FILE_NAME];
79 static char ProgramPath[MAX_FILE_NAME];
80 static char ProgramName[MAX_FILE_NAME];
81 static int  CartNameSupplied=0;
82 
83 #ifndef MSDOS
84 /* Get full path name, convert all backslashes to UNIX style slashes */
_fixpath(char * old,char * new)85 static void _fixpath (char *old,char *new)
86 {
87  strcpy (new,old);
88 }
89 #endif
90 
91 #ifdef MSDOS
ParseSpeakerChannels(char * p)92 static void ParseSpeakerChannels (char *p)
93 {
94  int i,a;
95  memset (spk_channels,0,sizeof(spk_channels));
96  for (i=0;i<4&&p;++i)
97  {
98   a=atoi(p);
99   if (a<0 || a>4)
100    a=0;
101   spk_channels[i]=a;
102   p=strchr(p,',');
103   if (p)
104   {
105    *p='\0';
106    ++p;
107   }
108  }
109 }
110 #endif
111 
ParseOptions(int argc,char * argv[])112 static int ParseOptions (int argc,char *argv[])
113 {
114  int N,I,J,tmp;
115  int misparm;
116  for(N=1,I=0;N<argc;N++)
117  {
118   misparm=0;
119   if(*argv[N]!='-')
120    switch(I++)
121    {
122     case 0:  /* CartName=argv[N]; */
123              break;
124     default: printf("Excessive filename '%s'\n",argv[N]);
125              return 0;
126    }
127   else
128   {
129    for(J=0;Options[J];J++)
130     if(!strcmp(argv[N]+1,Options[J])) break;
131    if (!Options[J])
132     for(J=0;AbvOptions[J];J++)
133      if(!strcmp(argv[N]+1,AbvOptions[J])) break;
134    switch(J)
135    {
136     case 0:  N++;
137              if(N<argc)
138               Verbose=atoi(argv[N]);
139              else
140               misparm=1;
141              break;
142     case 1:  printf ("%s\n"
143                      "Copyright (C) 1996  Marcel de Kogel\n"
144                      "Usage: %s [-option1 [-option2...]] [filename]\n"
145                      "[filename] = name of the file to load as a cartridge [CART.ROM]\n"
146                      "[-option]  =\n",Title,ProgramName);
147              tmp=5;
148              for(J=0;HelpText[J];J++)
149              {
150               if (HelpText[J][0]=='A')
151               {
152                if (Program==PROGRAM_ADAMEM)
153                {
154                 puts (HelpText[J]+1);
155                 ++tmp;
156                }
157               }
158               else if (HelpText[J][0]=='C')
159               {
160                if (Program==PROGRAM_CVEM)
161                {
162                 puts (HelpText[J]+1);
163                 ++tmp;
164                }
165               }
166               else
167               {
168                puts(HelpText[J]);
169                ++tmp;
170               }
171 #if defined(MSDOS) || defined(LINUX_SVGA)
172               if (tmp==24)
173               {
174                printf ("-- More --");
175                fflush (stdout);
176 #ifdef MSDOS
177                getch();
178 #else
179                fgetc (stdin);
180 #endif
181                fflush (stdin);
182                printf ("\n\n");
183                tmp=1;
184               }
185 #endif
186              }
187              return 0;
188     case 2:  N++;
189              if(N<argc)
190               CPUSpeed=atoi(argv[N]);
191              else
192               misparm=1;
193              break;
194     case 3:  N++;
195              if(N<argc)
196               IFreq=atoi(argv[N]);
197              else
198               misparm=1;
199              break;
200     case 13: N++;
201              if(N<argc)
202              {
203 #ifdef MSDOS
204               strcpy (szTempFileName,argv[N]);
205               strupr (szTempFileName);
206               if (!strcmp(szTempFileName,"NULL"))
207                SoundName=NULL;
208               else
209 #endif
210                SoundName=argv[N];
211              }
212              else
213               misparm=1;
214              break;
215     case 15: N++;
216              if(N<argc)
217               OS7File=argv[N];
218              else
219               misparm=1;
220              break;
221     case 19: N++;
222              if(N<argc)
223               UPeriod=atoi(argv[N]);
224              else
225               misparm=1;
226              break;
227     case 25: N++;
228              if(N<argc)
229               EOSFile=argv[N];
230              else
231               misparm=1;
232              break;
233     case 26: N++;
234              if(N<argc)
235               WPFile=argv[N];
236              else
237               misparm=1;
238              break;
239     case 27: case 28: case 29: case 30:
240              N++;
241              if(N<argc)
242               DiskName[J-27]=argv[N];
243              else
244               return 0;
245              break;
246     case 31: case 32: case 33: case 34:
247              N++;
248              if(N<argc)
249               TapeName[J-31]=argv[N];
250              else
251               return 0;
252              break;
253     case 23: N++;
254              if(N<argc)
255               PrnName=argv[N];
256              else
257               misparm=1;
258              break;
259     case 36: EmuMode=1;
260              break;
261     case 37: EmuMode=0;
262              break;
263 #ifdef SOUND
264     case 6:  N++;
265              if(N<argc)
266               soundmode=atoi(argv[N]);
267              else
268               misparm=1;
269              break;
270     case 12: N++;
271              if(N<argc)
272               mastervolume=atoi(argv[N]);
273              else
274               misparm=1;
275              break;
276     case 20: N++;
277              if(N<argc)
278               soundquality=atoi(argv[N]);
279              else
280               misparm=1;
281              break;
282     case 38: N++;
283              if(N<argc)
284               panning=atoi(argv[N]);
285              else
286               misparm=1;
287              break;
288     case 17: N++;
289              if(N<argc)
290               reverb=atoi(argv[N]);
291              else
292               misparm=1;
293              break;
294     case 18: N++;
295              if(N<argc)
296               chorus=atoi(argv[N]);
297              else
298               misparm=1;
299              break;
300 #ifdef MSDOS
301     case 21: N++;
302              if(N<argc)
303               ParseSpeakerChannels(argv[N]);
304              else
305               misparm=1;
306              break;
307 #endif
308 #endif /* SOUND */
309     case 4:  N++;
310              if(N<argc)
311              {
312               if (CheatCount<MAX_CHEATS)
313                Cheats[CheatCount++]=strtoul(argv[N],NULL,16);
314               else
315                printf ("WARNING: Maximum number of cheats (%d) reached\n",
316                        MAX_CHEATS);
317              }
318              else
319               misparm=1;
320              break;
321     case 5:  N++;
322              if(N<argc)
323               videomode=atoi(argv[N]);
324              else
325               misparm=1;
326              break;
327 #if defined(MSDOS) || defined(LINUX_SVGA)
328     case 11: N++;
329              if(N<argc)
330               useoverscan=atoi(argv[N]);
331              else
332               misparm=1;
333              break;
334 #endif
335     case 7:  N++;
336              if(N<argc)
337               joystick=atoi(argv[N]);
338              else
339               misparm=1;
340              break;
341     case 8:  N++;
342              if(N<argc)
343               swapbuttons=atoi(argv[N]);
344              else
345               misparm=1;
346              break;
347     case 9:  N++;
348              if(N<argc)
349               expansionmode=atoi(argv[N]);
350              else
351               misparm=1;
352              break;
353     case 10: N++;
354              if(N<argc)
355               calibrate=atoi(argv[N]);
356              else
357               misparm=1;
358              break;
359     case 16: N++;
360              if(N<argc)
361               mouse_sens=atoi(argv[N]);
362              else
363               misparm=1;
364              break;
365     case 22: N++;
366              if(N<argc)
367               szKeys=argv[N];
368              else
369               misparm=1;
370              break;
371     case 24: N++;
372              if(N<argc)
373               keypadmode=atoi(argv[N]);
374              else
375               misparm=1;
376              break;
377     case 35: N++;
378              if(N<argc)
379               syncemu=atoi(argv[N]);
380              else
381               misparm=1;
382              break;
383     case 39: N++;
384              if(N<argc)
385               PrnType=atoi(argv[N]);
386              else
387               misparm=1;
388              break;
389     case 44: N++;
390              if(N<argc)
391               PalNum=atoi(argv[N]);
392              else
393               misparm=1;
394              break;
395     case 45: N++;
396              if(N<argc)
397               RAMPages=atoi(argv[N]);
398              else
399               misparm=1;
400              break;
401     case 46: N++;
402              if(N<argc)
403               SnapshotName=argv[N];
404              else
405               misparm=1;
406              break;
407     case 47: N++;
408              if(N<argc)
409               SaveSnapshot=atoi(argv[N]);
410              else
411               misparm=1;
412              break;
413     case 48: N++;
414              if(N<argc)
415               DiskSpeed=atoi(argv[N]);
416              else
417               misparm=1;
418              break;
419     case 49: N++;
420              if(N<argc)
421               TapeSpeed=atoi(argv[N]);
422              else
423               misparm=1;
424              break;
425     case 50: N++;
426              if(N<argc)
427               LPTName=argv[N];
428              else
429               misparm=1;
430              break;
431 #ifdef TEXT80
432     case 51: N++;
433              if(N<argc)
434               AutoText80=atoi(argv[N]);
435              else
436               misparm=1;
437              break;
438 #endif
439 #ifdef LINUX_SVGA
440     case 40: N++;
441              if(N<argc)
442               chipset=atoi(argv[N]);
443              else
444               misparm=1;
445              break;
446 #endif
447     case 41: N++;
448              if (N<argc)
449               Support5thSprite=atoi(argv[N]);
450              else
451               misparm=1;
452              break;
453 #ifdef UNIX_X
454  #ifdef MITSHM
455     case 42: N++;
456              if(N<argc)
457               UseSHM=atoi(argv[N]);
458              else
459               misparm=1;
460              break;
461  #endif
462     case 43: N++;
463              if(N<argc)
464               SaveCPU=atoi(argv[N]);
465              else
466               misparm=1;
467              break;
468 #endif
469 #ifdef DEBUG
470     case 14: N++;
471              if (!strcmp(argv[N],"now")) Z80_Trace=1;
472              else Z80_Trap=strtoul(argv[N],NULL,16);
473              break;
474 #endif
475     default: printf("Wrong option '%s'\n",argv[N]);
476              return 0;
477    }
478    if (misparm)
479    {
480     printf("%s: Missing parameter\n",argv[N-1]);
481     return 0;
482    }
483   }
484  }
485  return 1;
486 }
487 
GetCartName(int argc,char * argv[])488 static int GetCartName (int argc,char *argv[])
489 {
490  int N,I,J,tmp;
491  for(N=1,I=0;N<argc;N++)
492  {
493   if(*argv[N]!='-')
494    switch(I++)
495    {
496     case 0:  CartName=argv[N];
497              CartNameSupplied=1;
498              break;
499     default: return 0;
500    }
501   else
502   {
503    for(J=0;Options[J];J++)
504     if(!strcmp(argv[N]+1,Options[J])) break;
505    if (!Options[J])
506     for(J=0;AbvOptions[J];J++)
507      if(!strcmp(argv[N]+1,AbvOptions[J])) break;
508    switch(J)
509    {
510     case 1:  return 0;
511     case 2:  N++;
512              tmp=0;
513              if(N<argc)
514               tmp=atoi(argv[N]);
515              if (!tmp)
516               return 0;
517              break;
518     case 36: case 37:
519              break;
520     case 27: case 28: case 29: case 30:
521              N++;
522              if(N<argc)
523               DiskName[J-27]=argv[N];
524              else
525               return 0;
526              break;
527     case 31: case 32: case 33: case 34:
528              N++;
529              if(N<argc)
530               TapeName[J-31]=argv[N];
531              else
532               return 0;
533              break;
534 #if defined(MSDOS) || defined(LINUX_SVGA)
535     case 4: case 11:
536 #endif
537 #ifdef LINUX_SVGA
538     case 40:
539 #endif
540 #ifdef UNIX_X
541  #ifdef MITSHM
542     case 42:
543  #endif
544     case 43:
545 #endif
546 #ifdef SOUND
547     case 6: case 12: case 20:
548     case 38: case 17: case 18:
549 #ifdef MSDOS
550     case 21:
551 #endif
552 #endif
553     case 5: case 7: case 8: case 9: case 10:
554     case 16: case 22: case 24: case 35:
555     case 0: case 3: case 13: case 15: case 19:
556     case 23: case 25: case 26: case 39: case 41: case 44:
557     case 45: case 46: case 47: case 48: case 49: case 50:
558 #ifdef TEXT80
559     case 51:
560 #endif
561 #ifdef DEBUG
562     case 14:
563 #endif
564              N++;
565              if (N>=argc)
566               return 0;
567              break;
568     default: return 0;
569    }
570   }
571  }
572  return 1;
573 }
574 
LoadConfigFile(char * szFileName,unsigned char * ptr)575 static void LoadConfigFile (char *szFileName,unsigned char *ptr)
576 {
577  FILE *infile;
578  infile=fopen (szFileName,"rb");
579  if (infile==NULL)
580   return;
581  fread (ptr,1,MAX_CONFIG_FILE_SIZE,infile);
582  fclose (infile);
583  while (*ptr)
584  {
585   while (*ptr && *ptr<=' ')
586    ++ptr;
587   if (*ptr)
588   {
589    _argv[_argc++]=ptr;
590    while (*ptr && *ptr>' ')
591     ++ptr;
592    if (*ptr)
593     *ptr++='\0';
594   }
595  }
596 }
597 
FixFileNames(void)598 static void FixFileNames (void)
599 {
600  char *p=NULL,*q=NULL,*x=NULL;
601  int i;
602  CartNameNoExt[0]='\0';
603  if (!CartNameSupplied)
604  {
605   for (i=0;i<2;++i)
606    if (DiskName[i]) { _fixpath (DiskName[i],CartNameNoExt); break; }
607   if (CartNameNoExt[0]=='\0')
608    for (i=0;i<2;++i)
609     if (TapeName[i]) { _fixpath (TapeName[i],CartNameNoExt); break; }
610  }
611  if (CartNameNoExt[0]=='\0')
612   _fixpath (CartName,CartNameNoExt);
613  p=CartNameNoExt;
614  q=strchr(CartNameNoExt,'/');
615  while (q)                      /* get last '/' */
616  {
617   p=++q;
618   q=strchr(q,'/');
619  };
620  q=NULL;
621  while ((p=strchr(p,'.'))!=NULL) /* get last '.' */
622  {
623   q=p;
624   ++p;
625  }
626  if (q)                         /* remove extension */
627   *q='\0';
628 
629  p=CartName;
630  q=strchr(CartName,'/'); if (!q) strchr(CartName,'\\');
631  while (q)                      /* get last '/' */
632  {
633   p=++q;
634   x=strchr(q,'/'); if (!x) x=strchr(q,'\\');
635   q=x;
636  };
637  q=NULL;
638  while ((p=strchr(p,'.'))!=NULL) /* get last '.' */
639  {
640   q=p;
641   ++p;
642  }
643  strcpy (_CartName,CartName);
644  if (!q)
645   strcat (_CartName,".rom");
646  CartName=_CartName;
647 }
648 
FixROMPath(char ** file,char * storage)649 static void FixROMPath (char **file,char *storage)
650 {
651  char *p=NULL,*q=NULL;
652  if (!strchr(*file,'/') && !strchr(*file,'\\'))
653  {      /* If no path is given, assume emulator path */
654   strcpy (storage,ProgramPath);
655   strcat (storage,*file);
656  }
657  else
658  {
659   _fixpath (*file,storage);
660  }
661  p=storage;
662  q=strchr(storage,'/');
663  while (q)                      /* get last '/' */
664  {
665   p=++q;
666   q=strchr(q,'/');
667  };
668  q=NULL;
669  while ((p=strchr(p,'.'))!=NULL) /* get last '.' */
670  {
671   q=p;
672   ++p;
673  }
674  if (!q)                       /* Default extension='.rom' */
675   strcat (storage,".rom");
676  *file=storage;
677 }
678 
GetPath(char * szFullPath,char * szPath,char * szFile)679 static void GetPath (char *szFullPath,char *szPath,char *szFile)
680 {
681  char *p,*q;
682  strcpy (szPath,szFullPath);
683  p=szPath;
684  q=strchr(p,'/');
685  while (q)                      /* get last '/' */
686  {
687   p=++q;
688   q=strchr(q,'/');
689  };
690  if (szFile)
691  {
692   strcpy (szFile,p);
693   *p='\0';                      /* remove filename */
694   p=szFile;
695   q=NULL;
696   while ((p=strchr(p,'.'))!=NULL) /* get last '.' */
697   {
698    q=p;
699    ++p;
700   }
701   if (q) *q='\0';               /* remove extension */
702  }
703  else
704   *p='\0';                      /* remove filename */
705 }
706 
main(int argc,char * argv[])707 int main (int argc,char *argv[])
708 {
709  Verbose=1;
710  CPUSpeed=100;
711  IFreq=50;
712  UPeriod=3;
713  CheatCount=0;
714 #ifdef MSDOS
715  PrnName=LPTName="PRN";
716 #endif
717  memset (MainConfigFile,0,sizeof(MainConfigFile));
718  memset (SubConfigFile,0,sizeof(SubConfigFile));
719  GetPath (argv[0],ProgramPath,ProgramName);
720  if (!strcmp(ProgramName,"cvem") || !strcmp(ProgramName,"cvemx"))
721  {
722   EmuMode=0;
723   Program=PROGRAM_CVEM;
724  }
725  else
726  {
727   EmuMode=1;
728   Program=PROGRAM_ADAMEM;
729  }
730  _argc=1;
731  _argv[0]=argv[0];
732 /* Load Config Files */
733  strcpy (szTempFileName,ProgramPath);
734  strcat (szTempFileName,ProgramName);
735  strcat (szTempFileName,".cfg");
736  strcpy (szJoystickFileName,ProgramPath);
737  strcat (szJoystickFileName,"adamem.joy");
738 #ifdef SOUND
739  strcpy (szSoundFileName,ProgramPath);
740  strcat (szSoundFileName,"/usr/local/share/adamem/adamem.snd");
741 #endif
742  LoadConfigFile (szTempFileName,MainConfigFile);
743  if (!ParseOptions(_argc,_argv))
744   return 1;
745  GetCartName (argc,argv);
746  FixFileNames ();
747 #if defined(MSDOS) || defined(LINUX_SVGA)
748  strcpy (szBitmapFile,CartNameNoExt);
749  strcat (szBitmapFile,".b00");
750 #endif
751 #if defined(MSDOS) || defined(LINUX_SVGA) || defined(UNIX_X)
752  strcpy (szSnapshotFile,CartNameNoExt);
753  strcat (szSnapshotFile,".s00");
754 #endif
755  strcpy (szTempFileName,CartNameNoExt);
756  strcat (szTempFileName,".cfg");
757  _argc=1;
758  LoadConfigFile (szTempFileName,SubConfigFile);
759  if (!ParseOptions(_argc,_argv))
760   return 1;
761  if (!ParseOptions(argc,argv))
762   return 1;
763  if (SaveSnapshot && !SnapshotName)
764  {
765   strcpy (_SnapshotName,CartNameNoExt);
766   strcat (_SnapshotName,".snp");
767   SnapshotName=_SnapshotName;
768  }
769  FixROMPath (&OS7File,_OS7File);
770  FixROMPath (&EOSFile,_EOSFile);
771  FixROMPath (&WPFile,_WPFile);
772  if (!UPeriod) UPeriod=3;
773  if (UPeriod>10) UPeriod=10;
774  if (IFreq<10) IFreq=10;
775  if (IFreq>200) IFreq=200;
776  if (CPUSpeed>1000) CPUSpeed=1000;
777  if (CPUSpeed<10) CPUSpeed=10;
778  Z80_IPeriod=(3579545*CPUSpeed)/(100*1000);
779  if (PalNum<0) PalNum=0;
780  if (PalNum>=NR_PALETTES) PalNum=NR_PALETTES-1;
781 #ifndef MSDOS
782  if (!InitMachine()) return 0;
783 #endif
784  StartColeco();
785  TrashColeco();
786 #ifndef MSDOS
787  TrashMachine ();
788 #endif
789  return 0;
790 }
791 
792