00001
00002
00003
00004
00005 #include <iostream.h>
00006 #include <iomanip.h>
00007 #include <fstream.h>
00008 #include <stdlib.h>
00009 #include <unistd.h>
00010
00011 #include "player.h"
00012 #include "myendian.h"
00013 #include "audiodrv.h"
00014
00015 #if defined(__amigaos__)
00016 #define EXIT_ERROR_STATUS (20)
00017 #else
00018 #define EXIT_ERROR_STATUS (-1)
00019 #endif
00020
00021
00022 enum
00023 {
00024 ERR_NOT_ENOUGH_MEMORY,
00025 ERR_SYNTAX,
00026 ERR_ENDIANESS
00027 };
00028
00029 void error( char*, char* );
00030 void printtext( int messageNum );
00031
00032 static bool verboseOutput = false;
00033
00034 int main(int argc, char *argv[])
00035 {
00036 cout
00037 << endl
00038 << "SIDPLAY Music player and C64 SID chip emulator Version " << emu_version << endl
00039 << "Copyright (c) 1994-1997 Michael Schwendt All rights reserved." << endl
00040 #if defined(sgi)
00041 << "Ported to SGI by <aagero@aage.priv.no>" << endl
00042 #elif defined(hpux)
00043 << "Ported to HP-UX by <esap@cs.tut.fi>" << endl
00044 #elif defined(__amigaos__)
00045 << "Ported to AmigaOS by <phillwooller@geocities.com>" << endl
00046 #endif
00047 << endl;
00048
00049
00050
00051
00052
00053
00054 emuEngine myEmuEngine;
00055
00056 if ( !myEmuEngine )
00057 {
00058
00059 printtext(ERR_NOT_ENOUGH_MEMORY);
00060 }
00061 if ( !myEmuEngine.verifyEndianess() )
00062 {
00063 printtext(ERR_ENDIANESS);
00064 }
00065
00066
00067 struct emuConfig myEmuConfig;
00068 myEmuEngine.getConfig(myEmuConfig);
00069
00070
00071
00072 if ( argc < 2 )
00073 printtext(ERR_SYNTAX);
00074
00075 uword selectedSong = 0;
00076
00077
00078 myEmuConfig.frequency = 22050;
00079 myEmuConfig.channels = SIDEMU_MONO;
00080 myEmuConfig.bitsPerSample = SIDEMU_8BIT;
00081 uword fragments = 16;
00082 uword fragSizeBase = 12;
00083 int forceBufSize = 0;
00084
00085 ubyte infile = 0;
00086
00087
00088 int a = 1;
00089 while ((a < argc) && (argv[a] != NULL))
00090 {
00091 if ( argv[a][0] == '-')
00092 {
00093
00094 if ( strlen(argv[a]) == 1 )
00095 if ( infile == 0 )
00096 {
00097 infile = a;
00098 break;
00099 }
00100 else
00101 printtext(ERR_SYNTAX);
00102 switch ( argv[a][1] )
00103 {
00104 #if defined(linux) || defined(__FreeBSD__) || defined(__amigaos__)
00105 case '1':
00106 if ( argv[a][2] == '6' )
00107 myEmuConfig.bitsPerSample = SIDEMU_16BIT;
00108 break;
00109 #endif
00110 case 'c':
00111 myEmuConfig.forceSongSpeed = true;
00112 break;
00113 case 'a':
00114 if ( argv[a][2] == '2' )
00115 myEmuConfig.memoryMode = MPU_BANK_SWITCHING;
00116 else
00117 myEmuConfig.memoryMode = MPU_PLAYSID_ENVIRONMENT;
00118 break;
00119 case 'b':
00120 if ( argv[a][2] == 'n' )
00121 {
00122 fragments = (unsigned)atoi(argv[a]+3);
00123 if (( fragments < 2 ) || ( fragments > 255 ))
00124 fragments = 2;
00125 }
00126 else if ( argv[a][2] == 's' )
00127 {
00128 fragSizeBase = (unsigned)atoi(argv[a]+3);
00129 if (( fragSizeBase < 7 ) || ( fragSizeBase > 17 ))
00130 fragSizeBase = 14;
00131 }
00132 else
00133 {
00134 forceBufSize = atoi(argv[a]+2);
00135 }
00136 break;
00137 case 'f':
00138 myEmuConfig.frequency = (udword)atol(argv[a]+2);
00139 break;
00140 case 'h':
00141 printtext(ERR_SYNTAX);
00142 break;
00143 case 'n':
00144 if ( argv[a][2] == 'f' )
00145 myEmuConfig.emulateFilter = false;
00146 else
00147 myEmuConfig.clockSpeed = SIDTUNE_CLOCK_NTSC;
00148 break;
00149 case 'o':
00150 selectedSong = atoi(argv[a]+2);
00151 break;
00152 case 'p':
00153 if ( argv[a][2] == 'c' )
00154 {
00155 myEmuConfig.autoPanning = SIDEMU_CENTEREDAUTOPANNING;
00156 }
00157 break;
00158 case 's':
00159 myEmuConfig.channels = SIDEMU_STEREO;
00160 if ( argv[a][2] == 's' )
00161 {
00162 myEmuConfig.volumeControl = SIDEMU_STEREOSURROUND;
00163 }
00164 break;
00165 case 'v':
00166 verboseOutput = true;
00167 break;
00168 default:
00169 printtext(ERR_SYNTAX);
00170 break;
00171 }
00172 }
00173 else
00174 {
00175 if ( infile == 0 )
00176 infile = a;
00177 else
00178 printtext(ERR_SYNTAX);
00179 }
00180 a++;
00181 };
00182
00183 if (infile == 0)
00184 {
00185 printtext(ERR_SYNTAX);
00186 }
00187
00188
00189
00190
00191
00192 if ((myEmuConfig.autoPanning!=SIDEMU_NONE) && (myEmuConfig.channels==SIDEMU_MONO))
00193 {
00194 myEmuConfig.channels = SIDEMU_STEREO;
00195 }
00196 if ((myEmuConfig.autoPanning!=SIDEMU_NONE) && (myEmuConfig.volumeControl==SIDEMU_NONE))
00197 {
00198 myEmuConfig.volumeControl = SIDEMU_FULLPANNING;
00199 }
00200
00201
00202
00203
00204
00205 sidTune myTune( argv[infile] );
00206 struct sidTuneInfo mySidInfo;
00207 myTune.getInfo( mySidInfo );
00208 if ( !myTune )
00209 {
00210 cerr << "SIDPLAY: " << mySidInfo.statusString << endl;
00211 exit(EXIT_ERROR_STATUS);
00212 }
00213 else
00214 {
00215 if (verboseOutput)
00216 {
00217 cout << "File format : " << mySidInfo.formatString << endl;
00218 cout << "Filenames : " << mySidInfo.dataFileName << ", "
00219 << mySidInfo.infoFileName << endl;
00220 cout << "Condition : " << mySidInfo.statusString << endl;
00221 }
00222 cout << "--------------------------------------------------" << endl;
00223 if ( mySidInfo.numberOfInfoStrings == 3 )
00224 {
00225 cout << "Name : " << mySidInfo.nameString << endl;
00226 cout << "Author : " << mySidInfo.authorString << endl;
00227 cout << "Copyright : " << mySidInfo.copyrightString << endl;
00228 }
00229 else
00230 {
00231 for ( int infoi = 0; infoi < mySidInfo.numberOfInfoStrings; infoi++ )
00232 cout << "Description : " << mySidInfo.infoString[infoi] << endl;
00233 }
00234 cout << "--------------------------------------------------" << endl;
00235 if (verboseOutput)
00236 {
00237 cout << "Load address : $" << hex << setw(4) << setfill('0')
00238 << mySidInfo.loadAddr << endl;
00239 cout << "Init address : $" << hex << setw(4) << setfill('0')
00240 << mySidInfo.initAddr << endl;
00241 cout << "Play address : $" << hex << setw(4) << setfill('0')
00242 << mySidInfo.playAddr << dec << endl;
00243 }
00244 }
00245
00246
00247
00248
00249
00250
00251
00252 audioDriver myAudio;
00253 if ( !myAudio.IsThere() )
00254 {
00255 cerr << "SIDPLAY: No audio device available !" << endl;
00256 exit(EXIT_ERROR_STATUS);
00257 }
00258
00259
00260 if ( !myAudio.Open(myEmuConfig.frequency,myEmuConfig.bitsPerSample,
00261 myEmuConfig.channels,fragments,fragSizeBase))
00262 {
00263 cerr << "SIDPLAY: " << myAudio.GetErrorString() << endl;
00264 exit(EXIT_ERROR_STATUS);
00265 }
00266 if (verboseOutput)
00267 {
00268 cout << "Block size : " << (udword)myAudio.GetBlockSize() << endl
00269 << "Fragments : " << myAudio.GetFragments() << endl;
00270 }
00271
00272
00273
00274
00275
00276
00277 myEmuConfig.frequency = myAudio.GetFrequency();
00278 myEmuConfig.bitsPerSample = myAudio.GetSamplePrecision();
00279 myEmuConfig.sampleFormat = myAudio.GetSampleEncoding();
00280 myEmuEngine.setConfig( myEmuConfig );
00281
00282 if (verboseOutput)
00283 {
00284 cout << "Frequency : " << dec << myEmuConfig.frequency << " Hz" << endl;
00285 cout << "SID Filter : " << ((myEmuConfig.emulateFilter == true) ? "Yes" : "No") << endl;
00286 if (myEmuConfig.memoryMode == MPU_PLAYSID_ENVIRONMENT)
00287 {
00288 cout << "Memory mode : PlaySID (this is supposed to fix PlaySID-specific rips)" << endl;
00289 }
00290 else if (myEmuConfig.memoryMode == MPU_TRANSPARENT_ROM)
00291 {
00292 cout << "Memory mode : Transparent ROM (SIDPLAY default)" << endl;
00293 }
00294 else if (myEmuConfig.memoryMode == MPU_BANK_SWITCHING)
00295 {
00296 cout << "Memory mode : Bank Switching" << endl;
00297 }
00298 }
00299
00300
00301
00302
00303
00304 extern bool sidEmuInitializeSong(emuEngine & thisEmuEngine,
00305 sidTune & thisTune,
00306 uword songNumber);
00307
00308 if ( !sidEmuInitializeSong(myEmuEngine,myTune,selectedSong) )
00309 {
00310 cerr << "SIDPLAY: SID Emulator Engine components not ready" << endl;
00311 exit(EXIT_ERROR_STATUS);
00312 }
00313
00314 myTune.getInfo( mySidInfo );
00315 if ( !myTune )
00316 {
00317 cerr << "SIDPLAY: " << mySidInfo.statusString << endl;
00318 exit(EXIT_ERROR_STATUS);
00319 }
00320 cout << "Setting song : " << mySidInfo.currentSong
00321 << " out of " << mySidInfo.songs
00322 << " (default = " << mySidInfo.startSong << ')' << endl;
00323 if (verboseOutput)
00324 {
00325 cout << "Song speed : " << mySidInfo.speedString << endl;
00326 }
00327
00328
00329
00330
00331
00332 int bufSize = myAudio.GetBlockSize();
00333 if (forceBufSize != 0)
00334 {
00335 bufSize = forceBufSize;
00336 if (verboseOutput)
00337 {
00338 cout << "Buffer size : " << bufSize << endl;
00339 }
00340 }
00341 ubyte* buffer;
00342 if ((buffer = new ubyte[bufSize]) == 0)
00343 {
00344 printtext(ERR_NOT_ENOUGH_MEMORY);
00345 exit(EXIT_ERROR_STATUS);
00346 }
00347 cout << "Playing, press ^C to stop ..." << endl;
00348 for (;;)
00349 {
00350 myEmuEngine.FillBuffer(myTune, buffer, bufSize);
00351
00352 myAudio.Play(buffer,bufSize);
00353 }
00354
00355
00356 exit(0);
00357 }
00358
00359
00360 void error(char* s1, char* s2 = "")
00361 {
00362 cerr << "SIDPLAY: ERROR: " << s1 << ' ' << "'" << s2 << "'" << endl;
00363 exit(EXIT_ERROR_STATUS);
00364 }
00365
00366
00367 void printtext(int number)
00368 {
00369 switch (number)
00370 {
00371 case ERR_ENDIANESS:
00372 {
00373 cerr << "SIDPLAY: ERROR: Hardware endianess improperly configured." << endl;
00374 exit(EXIT_ERROR_STATUS);
00375 break;
00376 }
00377 case ERR_NOT_ENOUGH_MEMORY:
00378 cerr << "SIDPLAY: ERROR: Not enough memory" << endl;
00379 exit(EXIT_ERROR_STATUS);
00380 case ERR_SYNTAX:
00381 cout << " syntax: sidplay [-<command>] <datafile>|-" << endl
00382 << " commands: -h display this screen" << endl
00383 << " -v verbose output" << endl
00384 << " -f<num> set frequency in Hz (default: 22050)" << endl
00385 << " -o<num> set song number (default: preset)" << endl
00386 << " -a improve PlaySID compatibility (read the docs !)" << endl
00387 << " -a2 bank switching mode (overrides -a)" << endl
00388 #if defined(linux) || defined(__FreeBSD__) || defined(__amigaos__)
00389 << " -16 enable 16-bit sample mixing" << endl
00390 #endif
00391 #if defined(linux) || defined(__FreeBSD__) || defined(__amigaos__) || defined(hpux)
00392 << " -s enable stereo replay" << endl
00393 << " -ss enable stereo surround" << endl
00394 << " -pc enable centered auto-panning (stereo only)" << endl
00395 #endif
00396 << " -nf no SID filter emulation" << endl
00397 << " -n set NTSC clock speed (default: PAL)" << endl
00398 << " -c force song speed = clock speed (PAL/NTSC)" << endl
00399 << " -bn<num> set number of audio buffer fragments to use" << endl
00400 << " -bs<num> set size 2^<num> of audio buffer fragments" << endl
00401 << " -b<num> set sample buffer size" << endl
00402 << endl;
00403 exit(EXIT_ERROR_STATUS);
00404 default:
00405 cerr << "SIDPLAY: ERROR: Internal system error" << endl;
00406 exit(EXIT_ERROR_STATUS);
00407 }
00408 }