PageRenderTime 670ms CodeModel.GetById 218ms app.highlight 219ms RepoModel.GetById 224ms app.codeStats 0ms

/zloader.c

https://bitbucket.org/nullplan/zsnes64
C | 971 lines | 792 code | 89 blank | 90 comment | 158 complexity | 41ee7785cbe1f9db9456d2481ff4c0cb MD5 | raw file
  1/*
  2Copyright (C) 1997-2007 ZSNES Team ( zsKnight, _Demo_, pagefault, Nach )
  3
  4http://www.zsnes.com
  5http://sourceforge.net/projects/zsnes
  6https://zsnes.bountysource.com
  7
  8This program is free software; you can redistribute it and/or
  9modify it under the terms of the GNU General Public License
 10version 2 as published by the Free Software Foundation.
 11
 12This program is distributed in the hope that it will be useful,
 13but WITHOUT ANY WARRANTY; without even the implied warranty of
 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15GNU General Public License for more details.
 16
 17You should have received a copy of the GNU General Public License
 18along with this program; if not, write to the Free Software
 19Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 20*/
 21
 22#ifdef __UNIXSDL__
 23#include "gblhdr.h"
 24#ifdef __LIBAO__
 25#include <ao/ao.h>
 26#endif
 27#else
 28#define _POSIX_
 29#include <stdio.h>
 30#include <stdlib.h>
 31#include <string.h>
 32#include <ctype.h>
 33#include <limits.h>
 34#include <time.h>
 35#ifdef __WIN32__
 36#include <windows.h>
 37#include <direct.h>
 38#undef _POSIX_
 39#include <io.h>
 40#else
 41#include <unistd.h>
 42#endif
 43#endif
 44#include "asm_call.h"
 45#include "cfg.h"
 46#include "input.h"
 47#include "zpath.h"
 48#include "zloader.h"
 49
 50#ifdef __WIN32__
 51void ImportDirectX();
 52#endif
 53
 54
 55extern unsigned char romtype, MouseDis, ZMVZClose, ZMVRawDump, debugger, debugdisble;
 56extern unsigned char gammalevel, spcon, ForcePal, DSPDisable, V8Mode;
 57extern unsigned char autoloadstate, autoloadmovie, MovieForcedLengthEnabled;
 58extern char *STCart2;
 59extern unsigned int NumInputDevices, MovieForcedLength;
 60void zstart();
 61#ifdef __WIN32__
 62void InitDebugger();
 63#endif
 64
 65#define put_line(x)                          \
 66  if (tty && (lines_out == 22))              \
 67  {                                          \
 68    puts("  -- Press Enter to Continue --"); \
 69    getchar();                               \
 70    lines_out = 0;                           \
 71  }                                          \
 72  puts(x);                                   \
 73  lines_out++;
 74
 75static void display_help()
 76{
 77  size_t lines_out = 0;
 78  bool tty = isatty(fileno(stdout));
 79#ifdef __UNIXSDL__
 80#ifdef __LIBAO__
 81  int driver_count;
 82  ao_info **driver_info;
 83#endif
 84  char line[75];
 85#endif
 86
 87  put_line("Usage : zsnes [-d,-f #, ... ] <filename.sfc>");
 88  put_line("   Eg : zsnes -s -r 2 game.sfc");
 89  put_line("");
 90#ifdef __MSDOS__
 91  put_line("  -0      Force black blackground in 8-bit modes");
 92#endif
 93  put_line("  -1 #/-2 #   Select Player 1/2 Input :");
 94#ifdef __MSDOS__
 95  put_line("                0 = None             1 = Keyboard         2 = 2 button pad");
 96  put_line("                3 = 4 button pad     4 = 6 button pad     5 = 8 button pad");
 97  put_line("                6 = Sidewinder #1    7 = Sidewinder #2    8 = Sidewinder #3");
 98  put_line("                9 = Sidewinder #4   10 = Gamepad Pro #0  11 = Gamepad Pro #1");
 99  put_line("               12 = LPT1 #1         13 = LPT1 #2         14 = LPT1 #3");
100  put_line("               15 = LPT1 #4         16 = LPT1 #5");
101#else
102  put_line("                0 = None       1 = Keyboard/Gamepad");
103#endif
104#ifndef __UNIXSDL__
105  put_line("  -3      Enable triple buffering (replaces vsync)");
106#endif
107#ifdef __WIN32__
108  put_line("  -6 #    Force a user-specified refresh rate for fullscreen modes [50..180]");
109#endif
110#ifdef __UNIXSDL__
111  put_line("  -ad <>  Select Audio Driver :");
112  snprintf(line, sizeof(line), "%22s = Automatically select output", "auto");
113  put_line(line);
114#ifdef __LIBAO__
115  driver_info = ao_driver_info_list(&driver_count);
116  while (driver_count--)
117  {
118    if (driver_info[driver_count]->type == AO_TYPE_LIVE)
119    {
120      snprintf(line, sizeof(line), "%22s = %s", driver_info[driver_count]->short_name, driver_info[driver_count]->name);
121      put_line(line);
122    }
123  }
124#endif
125  snprintf(line, sizeof(line), "%22s = Simple DirectMedia Layer output", "sdl");
126  put_line(line);
127#endif
128#ifdef __MSDOS__
129  put_line("  -8      Force 8-bit sound");
130  put_line("  -c      Enable full/wide screen (when available)");
131  put_line("  -cc     Enable small screen (when available)");
132#endif
133#ifndef NO_DEBUGGER
134  put_line("  -d      Start with debugger enabled");
135#endif
136  put_line("  -dd     Disable sound SPC700/DSP emulation which also disables sound output");
137  put_line("  -ds     Disable sound output");
138  put_line("  -dh     Disable ROM-specific hacks");
139  put_line("  -f #    Enable fixed frame rate [0..9]");
140  put_line("  -g #    Specify gamma correction value [0..15]");
141  put_line("  -h      Force HiROM");
142  put_line("  -j      Disable mouse (Automatically turns off right mouse click)");
143#ifndef __MSDOS__
144  put_line("  -js #   Set joystick sensitivity [0..32767]");
145#endif
146  put_line("  -k #    Set volume level [0..100]");
147#ifdef __WIN32__
148  put_line("  -kp     Enable the KitchenSync for PAL only");
149  put_line("  -ks     Enable the KitchenSync");
150#endif
151  put_line("  -l      Force LoROM");
152  put_line("  -m      Disable GUI (Must specify ROM filename)");
153  put_line("  -mc     Exit ZSNES when closing a movie (use with -zm)");
154  put_line("  -md #   Dump Video (use with -zm)");
155  put_line("             1 = Raw  2 = FFV1 3 = x264");
156  put_line("             4 = XviD 5 = Custom");
157  put_line("  -ml #   Define movie dump length in amount of frames (use with -md)");
158  put_line("  -n #    Enable scanlines (when available)");
159  put_line("             0 = None, 1 = Full, 2 = 25%, 3 = 50%");
160  put_line("  -o      Disable MMX support");
161  put_line("  -p #    Percentage of instructions to execute [50..150]");
162  put_line("  -r #    Set sound sampling rate:");
163  put_line("             0 = 8000Hz  1 = 11025Hz 2 = 22050Hz 3 = 44100Hz");
164  put_line("             4 = 16000Hz 5 = 32000Hz 6 = 48000Hz");
165  put_line("  -s      Enable sound output and enable SPC700/DSP emulation");
166  put_line("  -sa     Show all files in GUI (*.*)");
167#ifdef __MSDOS__
168  put_line("  -sp     Display sound information");
169#endif
170  put_line("  -t      Force NTSC timing");
171  put_line("  -u      Force PAL timing");
172  put_line("  -v #    Select video mode :");
173#ifdef __WIN32__
174#define VIDEO_MODE_COUNT 42
175  put_line("             0 = 256x224      R WIN     1 = 256x224      R FULL");
176  put_line("             2 = 512x448      R WIN     3 = 512x448     DR WIN");
177  put_line("             4 = 640x480      S WIN     5 = 640x480     DS WIN");
178  put_line("             6 = 640x480     DR FULL    7 = 640x480     DS FULL");
179  put_line("             8 = 640x480      S FULL    9 = 768x672      R WIN");
180  put_line("            10 = 768x672     DR WIN    11 = 800x600      S WIN");
181  put_line("            12 = 800x600     DS WIN    13 = 800x600      S FULL");
182  put_line("            14 = 800x600     DR FULL   15 = 800x600     DS FULL");
183  put_line("            16 = 1024x768     S WIN    17 = 1024x768    DS WIN");
184  put_line("            18 = 1024x768     S FULL   19 = 1024x768    DR FULL");
185  put_line("            20 = 1024x768    DS FULL   21 = 1024x896     R WIN");
186  put_line("            22 = 1024x896    DR WIN    23 = 1280x960     S WIN");
187  put_line("            24 = 1280x960    DS WIN    25 = 1280x960     S FULL");
188  put_line("            26 = 1280x960    DR FULL   27 = 1280x960    DS FULL");
189  put_line("            28 = 1280x1024    S WIN    29 = 1280x1024   DS WIN");
190  put_line("            30 = 1280x1024    S FULL   31 = 1280x1024   DR FULL");
191  put_line("            32 = 1280x1024   DS FULL   33 = 1600x1200    S WIN");
192  put_line("            34 = 1600x1200   DS WIN    35 = 1600x1200   DR FULL");
193  put_line("            36 = 1600x1200   DS FULL   37 = 1600x1200    S FULL");
194  put_line("            38 = CUSTOM      D  WIN    39 = CUSTOM      DS FULL");
195  put_line("            40 = CUSTOM         WIN    41 = CUSTOM       S FULL");
196  put_line("            42 = CUSTOM      DR FULL");
197#endif
198#ifdef __UNIXSDL__
199  put_line("             0 = 256x224      R WIN     1 = 256x224      R FULL");
200  put_line("             2 = 512x448     DR WIN     3 = 512x448     DR FULL");
201  put_line("             4 = 640x480     DR FULL");
202#ifndef __OPENGL__
203#define VIDEO_MODE_COUNT 4
204#else
205#define VIDEO_MODE_COUNT 22
206  put_line("             5 = 256x224    O R WIN     6 = 512x448    ODR WIN");
207  put_line("             7 = 640x480    ODS FULL    8 = 640x480    ODS WIN");
208  put_line("             9 = 640x560    ODR WIN    10 = 768x672    ODR WIN");
209  put_line("            11 = 800x600    ODS FULL   12 = 800x600    ODS WIN");
210  put_line("            13 = 896x784    ODR WIN    14 = 1024x768   ODS FULL");
211  put_line("            15 = 1024x768   ODS WIN    16 = 1024x896   ODR WIN");
212  put_line("            17 = 1280x960   ODS FULL   18 = 1280x1024  ODS FULL");
213  put_line("            19 = 1600x1200  ODS FULL   20 = VARIABLE   ODR WIN");
214  put_line("            21 = VARIABLE   ODS WIN    22 = CUSTOM     OD  FULL");
215#endif
216#endif
217#ifdef __MSDOS__
218#define VIDEO_MODE_COUNT 18
219  put_line("             0 = 256x224x8B   MODEQ     1 = 256x240x8B  MODEQ");
220  put_line("             2 = 256x256x8B   MODEQ     3 = 320x224x8B  MODEX");
221  put_line("             4 = 320x240x8B   MODEX     5 = 320x256x8B  MODEX");
222  put_line("             6 = 640x480x16B  VESA1     7 = 320x240x8B  VESA2");
223  put_line("             8 = 320x240x16B  VESA2     9 = 320x480x8B  VESA2");
224  put_line("            10 = 320x480x16B  VESA2    11 = 512x384x8B  VESA2");
225  put_line("            12 = 512x384x16B  VESA2    13 = 640x400x8B  VESA2");
226  put_line("            14 = 640x400x16B  VESA2    15 = 640x480x8B  VESA2");
227  put_line("            16 = 640x480x16B  VESA2    17 = 800x600x8B  VESA2");
228  put_line("            18 = 800x600x16B  VESA2");
229#endif
230  put_line("  -v8     Grayscale mode");
231#ifndef __UNIXSDL__
232  put_line("  -w      Enable vsync (disables triple buffering)");
233#endif
234  put_line("  -y      Enable anti-aliasing (video interpolation)");
235  put_line("  -z      Disable stereo sound");
236  put_line("  -zm #   Auto load specified movie slot on startup [0..9]");
237  put_line("  -zs #   Auto load specified save state slot on startup [0..99]");
238  put_line("");
239  put_line("  File Formats Supported by GUI : SMC,SFC,SWC,FIG,MGD,MGH,UFO,BIN,");
240  put_line("                                  GD3,GD7,USA,EUR,JAP,AUS,ST,BS,");
241  put_line("                                  DX2,048,058,078,1,A,GZ,ZIP,JMA");
242  put_line("");
243#ifndef __UNIXSDL__
244  put_line("  Microsoft-style options (/option) are also accepted");
245#endif
246/*
247#ifndef __MSDOS__
248  put_line("               --Netplay Parameters--");
249  put_line(" Commandline: /ABCDE <nickname> <fname> <IP Addy>");
250  put_line("   nickname = user nickname");
251  put_line("   fname = filename w/ full path (if L) or path name (if C)");
252  put_line("   IP Addy = IP Address (Client Only)");
253  put_line(" A = U (UDP - Recommended if works), T (TCP/IP)");
254  put_line(" B = S (Server), C (Client)");
255  put_line(" C = C (Chat first), L (load game first)");
256  put_line(" D = N (Stay in ZSNES after disconnect), Q (Quit after disconnect)");
257  put_line(" E = # of connections (Keep it 2 for now)");
258#ifdef __WIN32__
259  put_line("   eg: ZSNESW /UCCN2 nickname d:\\snesroms 202.36.124.28");
260#else
261  put_line("   eg: zsnes /UCCN2 nickname /home/zuser/snesroms 202.36.124.28");
262#endif
263#endif
264*/
265
266  exit(1);
267}
268
269#define ConvertJoyMapHelp(a,b) if (b && (a == b)) { b += 0x81; }
270
271void ConvertJoyMap1()
272{
273  unsigned int bl;
274  // Convert if 2,4,6, or sidewinder
275  if (pl1contrl == 2)
276  {
277    pl1Bk = 0x83;
278    pl1Yk = 0x82;
279    pl1upk = 0xCC;
280    pl1downk = 0xCD;
281    pl1leftk = 0xCE;
282    pl1rightk = 0xCF;
283  }
284
285  bl = (pl1contrl == 3 || pl1contrl == 4) ? 4 : 0;
286  if (pl1contrl == 5) { bl = 6; }
287
288  if (bl)
289  {
290    // Convert button data
291    pl1upk = 0xCC;
292    pl1downk = 0xCD;
293    pl1leftk = 0xCE;
294    pl1rightk = 0xCF;
295    ConvertJoyMapHelp(bl, pl1startk);
296    ConvertJoyMapHelp(bl, pl1selk);
297    ConvertJoyMapHelp(bl, pl1Yk);
298    ConvertJoyMapHelp(bl, pl1Xk);
299    ConvertJoyMapHelp(bl, pl1Bk);
300    ConvertJoyMapHelp(bl, pl1Ak);
301    ConvertJoyMapHelp(bl, pl1Lk);
302    ConvertJoyMapHelp(bl, pl1Rk);
303  }
304
305  if (pl1contrl == 6)
306  {
307    pl1upk = 0xD4;
308    pl1downk = 0xD5;
309    pl1leftk = 0xD6;
310    pl1rightk = 0xD7;
311    pl1startk = 0xC8;
312    pl1selk = 0xC9;
313    pl1Ak = 0x89;
314    pl1Bk = 0x88;
315    pl1Xk = 0x8C;
316    pl1Yk = 0x8B;
317    pl1Lk = 0x8E;
318    pl1Rk = 0x8F;
319  }
320  return;
321}
322
323void ConvertJoyMap2()
324{
325  unsigned int bl;
326  //If pl1contrl=2 and pl2contrl=2, then set pl2 buttons to 3 & 4
327  if (pl2contrl == 2)
328  {
329    if (pl1contrl != 2)
330    {
331      pl2Bk = 0x83;
332      pl2Yk = 0x82;
333      pl2upk = 0xCC;
334      pl2downk = 0xCD;
335      pl2leftk = 0xCE;
336      pl2rightk = 0xCF;
337    }
338    else
339    {
340      pl2Bk = 0x85;
341      pl2Yk = 0x84;
342      pl2upk = 0xE8;
343      pl2downk = 0xE9;
344      pl2leftk = 0xEA;
345      pl2rightk = 0xEB;
346    }
347  }
348
349  bl = (pl2contrl == 3 || pl2contrl == 4) ? 4 : 0;
350  if (pl2contrl == 5) { bl = 6; }
351
352  if (bl)
353  {
354    //Convert button data
355    pl2upk = 0xCC;
356    pl2downk = 0xCD;
357    pl2leftk = 0xCE;
358    pl2rightk = 0xCF;
359    ConvertJoyMapHelp(bl, pl2startk);
360    ConvertJoyMapHelp(bl, pl2selk);
361    ConvertJoyMapHelp(bl, pl2Yk);
362    ConvertJoyMapHelp(bl, pl2Xk);
363    ConvertJoyMapHelp(bl, pl2Bk);
364    ConvertJoyMapHelp(bl, pl2Ak);
365    ConvertJoyMapHelp(bl, pl2Lk);
366    ConvertJoyMapHelp(bl, pl2Rk);
367  }
368
369  //If both sidewinder, set pl2 buttons to sw2
370  if (pl2contrl == 6)
371  {
372    if (pl1contrl != 6)
373    {
374      pl2upk = 0xD4;
375      pl2downk = 0xD5;
376      pl2leftk = 0xD6;
377      pl2rightk = 0xD7;
378      pl2startk = 0xC8;
379      pl2selk = 0xC9;
380      pl2Ak = 0x89;
381      pl2Bk = 0x88;
382      pl2Xk = 0x8C;
383      pl2Yk = 0x8B;
384      pl2Lk = 0x8E;
385      pl2Rk = 0x8F;
386    }
387    else
388    {
389      pl2contrl = 7;
390      pl2upk = 0xDC;
391      pl2downk = 0xDD;
392      pl2leftk = 0xDE;
393      pl2rightk = 0xDF;
394      pl2startk = 0xD0;
395      pl2selk = 0xD1;
396      pl2Ak = 0x91;
397      pl2Bk = 0x90;
398      pl2Xk = 0x94;
399      pl2Yk = 0x93;
400      pl2Lk = 0x96;
401      pl2Rk = 0x97;
402    }
403  }
404  return;
405}
406
407struct backup_cmdline_vars saved_cmdline_vars;
408
409#ifdef __MSDOS__
410#define BACKUP_HELP_DOS(func) \
411  func(Palette0); \
412
413#else
414#define BACKUP_HELP_DOS(func)
415#endif
416
417#ifdef __WIN32__
418#define BACKUP_HELP_WIN(func) \
419  func(KitchenSync); \
420  func(KitchenSyncPAL); \
421  func(ForceRefreshRate); \
422  func(SetRefreshRate); \
423  func(joy_sensitivity); \
424
425#else
426#define BACKUP_HELP_WIN(func)
427#endif
428
429#ifdef __UNIXSDL__
430#define BACKUP_HELP_SDL(func) \
431func(joy_sensitivity); \
432
433#else
434#define BACKUP_HELP_SDL(func)
435#endif
436
437
438#define BACKUP_HELP(func) \
439  func(guioff) \
440  func(per2exec) \
441  func(HacksDisable) \
442  func(AllowMMX) \
443  BACKUP_HELP_DOS(func) \
444  BACKUP_HELP_WIN(func) \
445  BACKUP_HELP_SDL(func)
446
447#define BACKUP_VAR(var) saved_cmdline_vars._ ## var = var;
448static void backup_all_vars()
449{
450  BACKUP_HELP(BACKUP_VAR)
451}
452
453#define SWAP_BACKUP_VAR(var) \
454  saved_cmdline_vars._ ## var ^= var; \
455  var ^= saved_cmdline_vars._ ## var; \
456  saved_cmdline_vars._ ## var ^= var;
457void swap_backup_vars()
458{
459  BACKUP_HELP(SWAP_BACKUP_VAR)
460}
461
462static size_t zatoi(const char *str)
463{
464  const char *orig_str = str;
465  if (str)
466  {
467    while (*str)
468    {
469      if (!isdigit(*str++)) { return(~0); }
470    }
471    return((size_t)atoi(orig_str));
472  }
473  return(~0);
474}
475
476static void handle_params(int argc, char *argv[])
477{
478  int i;
479
480  backup_all_vars();
481
482  #ifndef __MSDOS__
483
484  /*
485  if (argc >= 5 && argv[1][0] == '/' && strlen(argv[1]) == 6)
486  {
487    size_t i = 0, j = 0;
488    char *strp;
489
490    if (toupper(argv[1][1]) == 'T') UDPConfig=0;
491
492    //Next should be # of connections
493
494    while (argv[2][i]!=0)
495    {
496      switch (argv[2][i])
497      {
498        case '_':
499        case '-':
500        case '^':
501        case '=':
502        case '+':
503        case '[':
504        case ']':
505        if ( j < 10)
506        {
507          strp[j] = argv[2][i];
508          j++;
509        }
510        break;
511
512        default:
513          if (((toupper(argv[2][i]) >= 'A') && (toupper(argv[2][i]) <= 'Z')) ||
514              ((argv[2][i] >= '0') && (argv[2][i] <= '9')))
515          {
516            if (j < 10)
517            {
518              strp[j] = argv[2][i];
519              j++;
520            }
521          }
522          break;
523      }
524      i++;
525    }
526    strp[j] = 0;
527
528  }
529  */
530  #endif
531
532  for (i = 1; i < argc; i++)
533  {
534    #ifndef __UNIXSDL__
535    if (argv[i][0] == '-' || argv[i][0] == '/')
536    #else
537    if (argv[i][0] == '-')
538    #endif
539    {
540      if (!argv[i][1]) //Nothing but a - or /
541      {
542        display_help();
543      }
544      else if (!argv[i][2]) //- followed by a single letter
545      {
546        switch (tolower(argv[i][1]))
547        {
548          #ifdef __MSDOS__
549          case '0': //Palette color 0 disable
550            Palette0 = 1;
551            break;
552          #endif
553
554          case '1': //Player 1 Input
555            i++;
556
557            if ((pl1contrl = zatoi(argv[i])) >= NumInputDevices)
558            {
559              printf("Player 1 Input must be a value from 0 to %u!\n", NumInputDevices);
560              exit(1);
561            }
562
563            ConvertJoyMap1();
564            break;
565
566          case '2': //Player 2 Input
567            i++;
568
569            if ((pl2contrl = zatoi(argv[i])) > NumInputDevices)
570            {
571              printf("Player 2 Input must be a value from 0 to %u!\n", NumInputDevices);
572              exit(1);
573            }
574
575            ConvertJoyMap2();
576            break;
577
578          #ifndef __UNIXSDL__
579          case '3': //Enable triple buffering for DOS/Windows
580            vsyncon = 0;
581          #ifdef __MSDOS__
582            Triplebufen = 1;
583          #elif __WIN32__
584            TripleBufferWin = 1;
585          #endif
586            break;
587          #endif
588
589          #ifdef __WIN32__
590          case '6': //Force Refresh Rate
591            i++;
592            SetRefreshRate = zatoi(argv[i]);
593            if((SetRefreshRate < 50) || (SetRefreshRate > 180))
594            {
595              ForceRefreshRate = 0;
596              puts("Refresh Rate must be a value 50 to 180!");
597              exit(1);
598            }
599            else
600            {
601              ForceRefreshRate = 1;
602            }
603            break;
604          #endif
605
606          #ifdef __MSDOS__
607          case '8': //Force 8-bit sound
608            Force8b = 1;
609            break;
610
611          case 'c': //Enable full screen (when available)
612            ScreenScale = 1;
613            break;
614          #endif
615
616          #ifndef NO_DEBUGGER
617          case 'd': //Start with debugger enabled
618            debugger = 1;
619            debugdisble = 0;
620          #ifdef __WIN32__
621            InitDebugger();
622          #endif
623            break;
624          #endif
625
626          case 'f': //Enable fixed frame rate
627            i++;
628            if ((frameskip = zatoi(argv[i])+1) > 10)
629            {
630              puts("Frame Skip must be a value of 0 to 9!");
631              exit(1);
632            }
633            break;
634
635          case 'g': //Specify gamma correction value
636            i++;
637            if ((gammalevel = zatoi(argv[i])) > 15)
638            {
639              puts("Gamma Correction Level must be a value of 0 to 15!");
640              exit(1);
641            }
642            break;
643
644          case 'h': //Force HiROM
645            romtype = 2;
646            break;
647
648          case 'j': //Disable mouse
649            MouseDis = 1;
650            break;
651
652          case 'k': //Set volume level
653            i++;
654            if ((MusicRelVol = zatoi(argv[i])) > 100)
655            {
656              puts("Volume must be a value from 0 to 100!");
657              exit(1);
658            }
659            break;
660
661          case 'l': //Force LoROM
662            romtype = 1;
663            break;
664
665          case 'm': //Disable GUI
666            guioff = 1;
667            break;
668
669          case 'n': //Enable scanlines (when available)
670            i++;
671            if ((scanlines = zatoi(argv[i])) > 3)
672            {
673              puts("Scanlines must be a value 0 to 3!");
674              exit(1);
675            }
676            break;
677
678          case 'o': //Disable MMX support
679            AllowMMX = 0;
680            break;
681
682          case 'p': //Percentage of instructions to execute
683            i++;
684            per2exec = zatoi(argv[i]);
685            if (per2exec > 150 || per2exec < 50)
686            {
687              puts("Percentage of instructions to execute must be a value from 50 to 150!");
688              exit(1);
689            }
690            break;
691
692          case 'r': //Set sampling rate
693            i++;
694            if ((SoundQuality = zatoi(argv[i])) > 6)
695            {
696              puts("Sound Sampling Rate must be a value of 0 to 6!");
697              exit(1);
698            }
699            break;
700
701          case 's': //Enable sound output, and SPC700/DSP emulation
702            spcon = 1;
703            soundon = 1;
704            break;
705
706          case 't': //Force NTSC
707            ForcePal = 1;
708            break;
709
710          case 'u': //Force PAL
711            ForcePal = 2;
712            break;
713
714          case 'v': //Select video mode
715            i++;
716            if ((cvidmode = zatoi(argv[i])) > VIDEO_MODE_COUNT)
717            {
718              puts("Invalid Video Mode!");
719              exit(1);
720            }
721            break;
722
723          #ifndef __UNIXSDL__
724          case 'w': //Enable vsync for DOS/Windows
725            vsyncon = 1;
726          #ifdef __MSDOS__
727            Triplebufen = 0;
728          #elif __WIN32__
729            TripleBufferWin = 0;
730          #endif
731            break;
732          #endif
733
734          case 'y': //Enable anti-aliasing
735            antienab = 1;
736            break;
737
738          case 'z': //Disable stereo sound
739            StereoSound = 0;
740            break;
741
742          default:
743            display_help();
744            break;
745        }
746      }
747      else if (!argv[i][3]) //- followed by two letters
748      {
749        if (tolower(argv[i][1]) == 'd' && tolower(argv[i][2]) == 'd') //Disable sound DSP emulation
750        {
751          DSPDisable = 1;
752        }
753
754        #ifdef __UNIXSDL__
755        else if (tolower(argv[i][1]) == 'a' && tolower(argv[i][2]) == 'd') //Disable sound DSP emulation
756        {
757          i++;
758          if (!argv[i])
759          {
760            display_help();
761          }
762
763          #ifdef __LIBAO__
764          if (!strcmp(argv[i], "auto") || !strcmp(argv[i], "sdl") || (ao_driver_id(argv[i]) >= 0))
765          #else
766          if (!strcmp(argv[i], "auto") || !strcmp(argv[i], "sdl"))
767          #endif
768          {
769            strcpy(libAoDriver, argv[i]);
770          }
771          else
772          {
773            puts("Audio driver selection invalid.");
774            exit(1);
775          }
776        }
777        #endif
778
779        else if (tolower(argv[i][1]) == 'd' && tolower(argv[i][2]) == 's') //Disable sound output
780        {
781          soundon = 0;
782        }
783
784        #ifdef __MSDOS__
785        else if (tolower(argv[i][1]) == 'c' && tolower(argv[i][2]) == 'c') //Enable small screen (when available)
786        {
787          smallscreenon = 1;
788        }
789        #endif
790
791        else if (tolower(argv[i][1]) == 'd' && tolower(argv[i][2]) == 'h') //Disable hacks
792        {
793          HacksDisable = 1;
794        }
795
796        #ifndef __MSDOS__
797        else if (tolower(argv[i][1]) == 'j' && tolower(argv[i][2]) == 's') //Set joystick sensitivity
798        {
799          i++;
800          if ((joy_sensitivity = zatoi(argv[i])+1) > 32767)
801          {
802            puts("Joystick sensitivity must be a value of 0 to 32767!");
803            exit(1);
804          }
805        }
806        #endif
807
808        #ifdef __WIN32__
809        else if (tolower(argv[i][1]) == 'k' && tolower(argv[i][2]) == 's') //Enable KitchenSync
810        {
811          KitchenSync = 1;
812        }
813        #endif
814
815        #ifdef __WIN32__
816        else if (tolower(argv[i][1]) == 'k' && tolower(argv[i][2]) == 'p') //Enable KitchenSync for PAL only
817        {
818          KitchenSyncPAL = 1;
819          KitchenSync = 0;
820        }
821        #endif
822
823        else if (tolower(argv[i][1]) == 'm' && tolower(argv[i][2]) == 'c') //Close ZSNES when ZMV closes
824        {
825          ZMVZClose = 1;
826        }
827
828        else if (tolower(argv[i][1]) == 'm' && tolower(argv[i][2]) == 'd') //Dump raw vid with ZMV
829        {
830          i++;
831          if ((ZMVRawDump = zatoi(argv[i])) > 5)
832          {
833            puts("Movie mode must be a number 1 to 5");
834            exit(1);
835          }
836        }
837
838        else if (tolower(argv[i][1]) == 'm' && tolower(argv[i][2]) == 'l') //Force ZMV length
839        {
840          i++;
841          MovieForcedLengthEnabled = true;
842          MovieForcedLength = zatoi(argv[i]);
843        }
844
845        #ifdef __MSDOS__
846        else if (tolower(argv[i][1]) == 's' && tolower(argv[i][2]) == 'p') //Display sound information
847        {
848          DisplayS = 1;
849        }
850        #endif
851
852        else if (tolower(argv[i][1]) == 's' && tolower(argv[i][2]) == 'a') //Show all extensions in GUI
853        {
854          showallext = 1;
855        }
856
857        else if (tolower(argv[i][1]) == 'v' && argv[i][2] == '8') //V8 Mode
858        {
859          V8Mode = 1;
860        }
861
862        else if (tolower(argv[i][1]) == 'z' && tolower(argv[i][2]) == 's') //Autoload save state
863        {
864          i++;
865          if ((autoloadstate = zatoi(argv[i])+1) > 100)
866          {
867            puts("State load position must be a value of 0 to 99!");
868            exit(1);
869          }
870        }
871
872        else if (tolower(argv[i][1]) == 'z' && tolower(argv[i][2]) == 'm') //Autoload movie
873        {
874          i++;
875          if ((autoloadmovie = zatoi(argv[i])+1) > 10)
876          {
877            puts("Movie load position must be a value of 0 to 9!");
878            exit(1);
879          }
880        }
881
882        else
883        {
884          display_help();
885          break;
886        }
887      }
888      else //- followed by more than 2 letters
889      {
890        display_help();
891      }
892    }
893    else //Param with no - or / prefix
894    {
895      if (argv[i] && !init_rom_path(argv[i]))
896      {
897        printf("Could not load: %s\n", argv[i]);
898      }
899
900      if ((STCart2 = argv[i+1])) //Sufami Turbo second cart
901      {
902        char *p;
903
904        natify_slashes(STCart2);
905        p = strrchr(STCart2, DIR_SLASH_C);
906        if (!p) { p = STCart2; }
907        else { p++; }
908        strcpy(ZSaveST2Name, p);
909        setextension(ZSaveST2Name, "srm");
910      }
911      break;
912    }
913  }
914}
915
916static void ZCleanup(void)
917{
918  void deinit_paths();
919  void deallocmem();
920  void DeallocRewindBuffer();
921  void DeallocPauseFrame();
922  void DeallocSystemVars();
923  void free_all_file_lists();
924#ifdef __UNIXSDL__
925  void UnloadSDL();
926#endif
927
928  deinit_paths();
929  deallocmem();
930  DeallocRewindBuffer();
931  DeallocPauseFrame();
932  DeallocSystemVars();
933  free_all_file_lists();
934#ifdef __UNIXSDL__
935  UnloadSDL();
936#endif
937
938}
939
940void zmain(int zargc, char *zargv[])
941{
942  if (init_paths(*zargv))
943  {
944    #ifdef __LIBAO__
945    ao_initialize();
946    atexit(ao_shutdown);
947    #endif
948    handle_params(zargc, zargv);
949
950    atexit(ZCleanup);
951    srand(time(0));
952    zstart();
953  }
954}
955
956#ifdef __WIN32__
957extern HINSTANCE hInst;
958int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
959{
960  hInst=hInstance;
961  ImportDirectX();
962  zmain(__argc, __argv);
963  return(0);
964}
965#else
966int main(int zargc, char *zargv[])
967{
968  zmain(zargc, zargv);
969  return(0);
970}
971#endif