/* * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. * * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and * Jerremy Koot (jkoot@snes9x.com) * * Super FX C emulator code * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and * Gary Henderson. * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. * * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com). * * DOS port code contains the works of other authors. See headers in * individual files. * * Snes9x homepage: http://www.snes9x.com * * Permission to use, copy, modify and distribute Snes9x in both binary and * source form, for non-commercial purposes, is hereby granted without fee, * providing that this license information and copyright notice appear with * all copies and any derived work. * * This software is provided 'as-is', without any express or implied * warranty. In no event shall the authors be held liable for any damages * arising from the use of this software. * * Snes9x is freeware for PERSONAL USE only. Commercial users should * seek permission of the copyright holders first. Commercial use includes * charging money for Snes9x or software derived from Snes9x. * * The copyright holders request that bug fixes and improvements to the code * should be forwarded to them so everyone can benefit from the modifications * in future versions. * * Super NES and Super Nintendo Entertainment System are trademarks of * Nintendo Co., Limited and its subsidiary companies. */ #include #include #include "snes9x.h" #include "memmap.h" #include "display.h" #include "cheats.h" #ifdef DEBUGGER extern FILE *trace; #endif void S9xUsage () { S9xMessage (S9X_INFO, S9X_USAGE, "snes9x: S9xUsage: snes9x \n\n"); S9xMessage (S9X_INFO, S9X_USAGE, "Where can be:\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -cycles or -h Percentage of CPU cycles to execute every scan line (default 90)\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -frameskip or -f Screen update frame skip rate (default 2)\n"); S9xExtraUsage (); S9xMessage (S9X_INFO, S9X_USAGE, "\ -forcehirom or -F or -FH Force Hi-ROM memory map, useful for hacked ROM imagess.\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -forcelorom or -FL Force Lo-ROM memory map, useful for hacked ROM images.\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -old or -o Enable old-style SNES joypad emulation\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -noold or -no Disbale old-style SNES joypad emulation\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -soundskip or -ss Sound CPU skip-waiting method, 0 - 3 (default 0)\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -sound or -S Enable digital sound output (default: enabled)\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -nosound or -NS Disable digital sound output\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -sound or -S Enable digital sound output (default: off)\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -soundquality or -r Sound sample playback rate/quality, 0-7 (default 4)\n"); #ifdef __sgi /* BS: changed the sample rate values to match the IRIX options */ S9xMessage (S9X_INFO, S9X_USAGE, "\ 0 - off, 1 - 8192, 2 - 11025, 3 - 16000,\n\ 4 - 22050 (default), 5 - 32000, 6 - 44100,\n\ 7 - 48000\n"); #else S9xMessage (S9X_INFO, S9X_USAGE, "\ 0 - off, 1 - 8192, 2 - 11025, 3 - 16500,\n\ 4 - 22050 (default), 5 - 29300, 6 - 36600,\n\ 7 - 44000\n"); #endif S9xMessage (S9X_INFO, S9X_USAGE, "\ -stereo Enable stereo sound (default: mono sound)\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -mono Enable mono sound (default: mono sound)\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -buffersize or -B Sound playback buffer size (default auto for playback rate)\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -nospeedhacks or -N Disable some internal speed ups that break a few ROMs\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -speedhacks or -SH Enable some internal speed ups that break a few ROMs\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -loadsnapshot or -l \n\ Load saved game position snapshot file & required ROM\n\ image.\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -swapjoypads or -s Swap joypad 1 and 2 around\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -pal or -p Fool ROM into thinking that this is a PAL SNES system\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -ntsc or -n Fool ROM into thinking that this is a NTCS SNES system\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -interleaved or -i ROM image is in interleaved format.\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -interleaved2 or -i2 ROM image is in interleaved 2 format\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -nohdma or -H Disable H-DMA emulation (default: enabled)\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -hdma or -NH Enable H-DMA emulation (default: enabled)\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -layering or -L Swap some background priority levels - helps some games\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -graphicwindows Enable graphic window effects (default: enabled)\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -nographicwindows or -nw Disable graphic window effects (default: enabled)\n"); #ifdef DEBUGGER S9xMessage (S9X_INFO, S9X_USAGE, "\ -noirq or -I Disable processor IRQ (for debugging)\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -debug or -d Enter debug mode once ROM has loaded\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -trace or -t Trace CPU instructions to file (WARNING: file gets very large!)\n"); #endif #ifdef JOYSTICK_SUPPORT #ifdef __linux S9xMessage (S9X_INFO, S9X_USAGE, "\ -joydevX /dev/jsY Use joystick device /dev/jsY for emulation of gamepad X\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -joymapX 0 1 2 3 4 5 6 7 Joystick buttons which should be assigned to gamepad X - A B X Y TL TR Start and Select\n"); #else S9xMessage (S9X_INFO, S9X_USAGE, "\ -four or -4 Single standard PC joystick has four buttons\n"); S9xMessage (S9X_INFO, S9X_USAGE, "\ -six or -6 Single standard PC joystick has six buttons\n"); #endif S9xMessage (S9X_INFO, S9X_USAGE, "\ -nojoy or -j Disable joystick support\n"); #endif S9xMessage (S9X_INFO, S9X_USAGE, "\ \nROM image needs to be in Super MagiCom (*.smc), Super FamiCom (*.sfc),\n\ *.fig, or split (*.1, *.2, or sf32527a, sf32527b, etc) format and can be\n\ compressed with gzip or compress.\n"); exit (1); } #ifdef STORM extern int dofps; extern int hicolor; extern int secondjoy; extern int minimal; int prelude=0; extern int unit; #endif char *S9xParseArgs (char **argv, int argc) { char *rom_filename = NULL; for (int i = 1; i < argc; i++) { if (*argv[i] == '-') { if (strcasecmp (argv [i], "-so") == 0 || strcasecmp (argv [i], "-sound") == 0) { Settings.NextAPUEnabled = TRUE; } else if (strcasecmp (argv [i], "-ns") == 0 || strcasecmp (argv [i], "-nosound") == 0) { Settings.NextAPUEnabled = FALSE; } else if (strcasecmp (argv [i], "-soundskip") == 0 || strcasecmp (argv [i], "-sk") == 0) { if (i + 1 < argc) Settings.SoundSkipMethod = atoi (argv [++i]); else S9xUsage (); } else if (strcasecmp (argv [i], "-ra") == 0 || strcasecmp (argv [i], "-ratio") == 0) { if (i + 1 < argc) { } else S9xUsage (); } else if (strcasecmp (argv [i], "-h") == 0 || strcasecmp (argv [i], "-cycles") == 0) { if (i + 1 < argc) { int p = atoi (argv [++i]); if (p > 0 && p < 200) Settings.CyclesPercentage = p; } else S9xUsage (); } else if (strcasecmp (argv [i], "-nh") == 0 || strcasecmp (argv [i], "-nohdma") == 0) { Settings.DisableHDMA = TRUE; } else if (strcasecmp (argv [i], "-ha") == 0 || strcasecmp (argv [i], "-hdma") == 0) { Settings.DisableHDMA = FALSE; } else if (strcasecmp (argv [i], "-n") == 0 || strcasecmp (argv [i], "-nospeedhacks") == 0) { Settings.ShutdownMaster = FALSE; } else if (strcasecmp (argv [i], "-sh") == 0 || strcasecmp (argv [i], "-speedhacks") == 0) { Settings.ShutdownMaster = TRUE; } else if (strcasecmp (argv [i], "-p") == 0 || strcasecmp (argv [i], "-pal") == 0) { Settings.ForcePAL = TRUE; } else if (strcasecmp (argv [i], "-n") == 0 || strcasecmp (argv [i], "-ntsc") == 0) { Settings.ForceNTSC = TRUE; } else if (strcasecmp (argv [i], "-f") == 0 || strcasecmp (argv [i], "-frameskip") == 0) { if (i + 1 < argc) Settings.SkipFrames = atoi (argv [++i]) + 1; else S9xUsage (); } else if (strcasecmp (argv [i], "-fh") == 0 || strcasecmp (argv [i], "-hr") == 0 || strcasecmp (argv [i], "-hirom") == 0) Settings.ForceHiROM = TRUE; else if (strcasecmp (argv [i], "-fl") == 0 || strcasecmp (argv [i], "-lr") == 0 || strcasecmp (argv [i], "-lorom") == 0) Settings.ForceLoROM = TRUE; else if (strcasecmp (argv [i], "-hd") == 0 || strcasecmp (argv [i], "-header") == 0 || strcasecmp (argv [i], "-he") == 0) { Settings.ForceHeader = TRUE; } else if (strcasecmp (argv [i], "-nhd") == 0 || strcasecmp (argv [i], "-noheader") == 0) { Settings.ForceNoHeader = TRUE; } else if (strcasecmp (argv [i], "-bs") == 0) { Settings.BS = TRUE; } #ifdef DEBUGGER else if (strcasecmp (argv [i], "-d") == 0 || strcasecmp (argv [i], "-debug") == 0) { CPU.Flags |= DEBUG_MODE_FLAG; } else if (strcasecmp (argv [i], "-t") == 0 || strcasecmp (argv [i], "-trace") == 0) { trace = fopen ("trace.log", "wb"); CPU.Flags |= TRACE_FLAG; } #endif else if (strcasecmp (argv [i], "-L") == 0 || strcasecmp (argv [i], "-layering") == 0) Settings.BGLayering = TRUE; else if (strcasecmp (argv [i], "-nl") == 0 || strcasecmp (argv [i], "-nolayering") == 0) Settings.BGLayering = FALSE; else if (strcasecmp (argv [i], "-O") == 0 || strcasecmp (argv [i], "-tileredraw") == 0) { } else if (strcasecmp (argv [i], "-no") == 0 || strcasecmp (argv [i], "-lineredraw") == 0) { } else if (strcasecmp (argv [i], "-tr") == 0 || strcasecmp (argv [i], "-transparency") == 0) { Settings.ForceTransparency = TRUE; Settings.ForceNoTransparency = FALSE; } else if (strcasecmp (argv [i], "-nt") == 0 || strcasecmp (argv [i], "-notransparency") == 0) { Settings.ForceNoTransparency = TRUE; Settings.ForceTransparency = FALSE; } else if (strcasecmp (argv [i], "-hi") == 0 || strcasecmp (argv [i], "-hires") == 0) { Settings.SupportHiRes = TRUE; } else if (strcasecmp (argv [i], "-16") == 0 || strcasecmp (argv [i], "-sixteen") == 0) { Settings.SixteenBit = TRUE; } else if (strcasecmp (argv [i], "-displayframerate") == 0 || strcasecmp (argv [i], "-dfr") == 0) { Settings.DisplayFrameRate = TRUE; } else if (strcasecmp (argv [i], "-s") == 0 || strcasecmp (argv [i], "-swapjoypads") == 0 || strcasecmp (argv [i], "-sw") == 0) Settings.SwapJoypads = TRUE; else if (strcasecmp (argv [i], "-i") == 0 || strcasecmp (argv [i], "-interleaved") == 0) Settings.ForceInterleaved = TRUE; else if (strcasecmp (argv [i], "-i2") == 0 || strcasecmp (argv [i], "-interleaved2") == 0) Settings.ForceInterleaved2 = TRUE; else if (strcasecmp (argv [i], "-ni") == 0 || strcasecmp (argv [i], "-nointerleave") == 0) Settings.ForceNotInterleaved = TRUE; else if (strcasecmp (argv [i], "-noirq") == 0) Settings.DisableIRQ = TRUE; else if (strcasecmp (argv [i], "-nw") == 0 || strcasecmp (argv [i], "-nowindows") == 0) { Settings.DisableGraphicWindows = TRUE; } else if (strcasecmp (argv [i], "-windows") == 0) { Settings.DisableGraphicWindows = FALSE; } else if (strcasecmp (argv [i], "-im7") == 0) { Settings.Mode7Interpolate = TRUE; } else if (strcasecmp (argv [i], "-gg") == 0 || strcasecmp (argv [i], "-gamegenie") == 0) { if (i + 1 < argc) { uint32 address; uint8 byte; const char *error; if ((error = S9xGameGenieToRaw (argv [++i], address, byte)) == NULL) S9xAddCheat (TRUE, FALSE, address, byte); else S9xMessage (S9X_ERROR, S9X_GAME_GENIE_CODE_ERROR, error); } else S9xUsage (); } else if (strcasecmp (argv [i], "-ar") == 0 || strcasecmp (argv [i], "-actionreplay") == 0) { if (i + 1 < argc) { uint32 address; uint8 byte; const char *error; if ((error = S9xProActionReplayToRaw (argv [++i], address, byte)) == NULL) S9xAddCheat (TRUE, FALSE, address, byte); else S9xMessage (S9X_ERROR, S9X_ACTION_REPLY_CODE_ERROR, error); } else S9xUsage (); } else if (strcasecmp (argv [i], "-gf") == 0 || strcasecmp (argv [i], "-goldfinger") == 0) { if (i + 1 < argc) { uint32 address; uint8 bytes [3]; bool8 sram; uint8 num_bytes; const char *error; if ((error = S9xGoldFingerToRaw (argv [++i], address, sram, num_bytes, bytes)) == NULL) { for (int c = 0; c < num_bytes; c++) S9xAddCheat (TRUE, FALSE, address + c, bytes [c]); } else S9xMessage (S9X_ERROR, S9X_GOLD_FINGER_CODE_ERROR, error); } else S9xUsage (); } else if (strcasecmp (argv[i], "-ft") == 0 || strcasecmp (argv [i], "-frametime") == 0) { if (i + 1 < argc) { double ft; if (sscanf (argv [++i], "%lf", &ft) == 1) { #ifdef __WIN32__ Settings.FrameTimePAL = (int32) (ft * 1000); Settings.FrameTimeNTSC = (int32) (ft * 1000); #else Settings.FrameTimePAL = (int32) ft; Settings.FrameTimeNTSC = (int32) ft; #endif } } else S9xUsage (); } else if (strcasecmp (argv [i], "-e") == 0 || strcasecmp (argv [i], "-echo") == 0) Settings.DisableSoundEcho = FALSE; else if (strcasecmp (argv [i], "-ne") == 0 || strcasecmp (argv [i], "-noecho") == 0) Settings.DisableSoundEcho = TRUE; else if (strcasecmp (argv [i], "-r") == 0 || strcasecmp (argv [i], "-soundquality") == 0 || strcasecmp (argv [i], "-sq") == 0) { if (i + 1 < argc) Settings.SoundPlaybackRate = atoi (argv [++i]) & 7; else S9xUsage (); } else if (strcasecmp (argv [i], "-stereo") == 0 || strcasecmp (argv [i], "-st") == 0) { Settings.Stereo = TRUE; Settings.APUEnabled = TRUE; Settings.NextAPUEnabled = TRUE; } else if (strcasecmp (argv [i], "-mono") == 0) { Settings.Stereo = FALSE; Settings.NextAPUEnabled = TRUE; } else if (strcasecmp (argv [i], "-envx") == 0 || strcasecmp (argv [i], "-ex") == 0) { Settings.SoundEnvelopeHeightReading = TRUE; } else if (strcasecmp (argv [i], "-nosamplecaching") == 0 || strcasecmp (argv [i], "-nsc") == 0 || strcasecmp (argv [i], "-nc") == 0) { Settings.DisableSampleCaching = TRUE; } else if (strcasecmp (argv [i], "-nomastervolume") == 0 || strcasecmp (argv [i], "-nmv") == 0) { Settings.DisableMasterVolume = TRUE; } else if (strcasecmp (argv [i], "-soundsync") == 0 || strcasecmp (argv [i], "-sy") == 0) { Settings.SoundSync = TRUE; Settings.SoundEnvelopeHeightReading = TRUE; Settings.InterpolatedSound = TRUE; } else if (strcasecmp (argv [i], "-soundsync2") == 0 || strcasecmp (argv [i], "-sy2") == 0) { Settings.SoundSync = 2; Settings.SoundEnvelopeHeightReading = TRUE; Settings.InterpolatedSound = TRUE; } else if (strcasecmp (argv [i], "-interpolatedsound") == 0 || strcasecmp (argv [i], "-is") == 0) { Settings.InterpolatedSound = TRUE; } #ifdef USE_THREADS else if (strcasecmp (argv [i], "-threadsound") == 0 || strcasecmp (argv [i], "-ts") == 0) { Settings.ThreadSound = TRUE; } #endif else if (strcasecmp (argv [i], "-alt") == 0 || strcasecmp (argv [i], "-altsampledecode") == 0) { Settings.AltSampleDecode = 1; } else if (strcasecmp (argv [i], "-fix") == 0) { Settings.FixFrequency = 1; } else if (strcasecmp (argv [i], "-nosuperfx") == 0 || strcasecmp (argv [i], "-nosfx") == 0) Settings.ForceNoSuperFX = TRUE; else if (strcasecmp (argv [i], "-superfx") == 0 || strcasecmp (argv [i], "-sfx") == 0) Settings.ForceSuperFX = TRUE; else if (strcasecmp (argv [i], "-dsp1") == 0) Settings.ForceDSP1 = TRUE; else if (strcasecmp (argv [i], "-nodsp1") == 0) Settings.ForceNoDSP1 = TRUE; else if (strcasecmp (argv [i], "-nomultiplayer5") == 0 || strcasecmp (argv [i], "-nmp") == 0) Settings.MultiPlayer5 = FALSE; else if (strcasecmp (argv [i], "-multiplayer5") == 0 || strcasecmp (argv [i], "-mp") == 0) { Settings.MultiPlayer5 = TRUE; Settings.ControllerOption = SNES_MULTIPLAYER5; } else if (strcasecmp (argv [i], "-mouse") == 0 || strcasecmp (argv [i], "-mo") == 0) { Settings.ControllerOption = SNES_MOUSE_SWAPPED; Settings.Mouse = TRUE; } else if (strcasecmp (argv [i], "-nomouse") == 0 || strcasecmp (argv [i], "-nm") == 0) { Settings.Mouse = FALSE; } else if (strcasecmp (argv [i], "-superscope") == 0 || strcasecmp (argv [i], "-ss") == 0) { Settings.SuperScope = TRUE; Settings.ControllerOption = SNES_SUPERSCOPE; } else if (strcasecmp (argv [i], "-nosuperscope") == 0 || strcasecmp (argv [i], "-nss") == 0) { Settings.SuperScope = FALSE; } #ifdef NETPLAY_SUPPORT else if (strcasecmp (argv [i], "-port") == 0 || strcasecmp (argv [i], "-po") == 0) { if (i + 1 < argc) { Settings.NetPlay = TRUE; Settings.Port = -atoi (argv [++i]); } else S9xUsage (); } else if (strcasecmp (argv [i], "-server") == 0 || strcasecmp (argv [i], "-srv") == 0) { if (i + 1 < argc) { Settings.NetPlay = TRUE; strncpy (Settings.ServerName, argv [++i], 127); Settings.ServerName [127] = 0; } else S9xUsage (); } else if (strcasecmp (argv [i], "-net") == 0) { Settings.NetPlay = TRUE; } #endif #ifdef STORM else if (strcasecmp(argv[i],"-nosecondjoy")==0){secondjoy=0;} else if (strcasecmp(argv[i],"-showfps")==0){dofps=1;} else if (strcasecmp(argv[i],"-hicolor")==0){hicolor=1;} else if (strcasecmp(argv[i],"-minimal")==0){minimal=1;printf("Keyboard with exception of ESC switched off!\n");} else if (strcasecmp(argv[i],"-ahiunit")==0) { if (i+1