00001
00013 #if defined(__ER6__)
00014 #include "audiodrv_er6.h"
00015 #else
00016 #include "audiodrv_epoc.h"
00017 #endif
00018
00019 #include <e32test.h>
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include "player.h"
00023 #include "myendian.h"
00024
00025 #include "6510_.h"
00026
00027 GLDEF_D RTest gTest(_L("esidplay"));
00028
00029 const TInt EXIT_ERROR_STATUS = (-1);
00030
00031
00032
00033
00034 LOCAL_D emuEngine* myEmuEngine;
00035 LOCAL_D TInt16* buffer;
00036 LOCAL_D audioDriver* myAudio;
00037 LOCAL_D sidTune* myTune;
00038 LOCAL_D int bufSize;
00039 LOCAL_D uword selectedSong = 0;
00040
00041 ELOG( LOCAL_D int count = 0;)
00042
00043 const uword fragments = 16;
00044 const uword fragSizeBase = 12;
00045
00046
00047
00048
00049 GLREF_C bool sidEmuInitializeSong(emuEngine & thisEmuEngine,
00050 sidTune & thisTune,
00051 uword songNumber);
00052
00053
00054 TInt SidPlayerThread(TAny* )
00059 {
00060 gTest.Printf(_L("."));
00061 ELOG2(_L8("count=%d \n"), count++);
00062
00063 if(!myAudio->iIsReady)
00064 return ETrue;
00065
00066 if(!myAudio->iPrefilled)
00067 {
00068 myEmuEngine->FillBuffer(*myTune, buffer, bufSize);
00069 gTest.Printf(_L("/"));
00070 myAudio->iPrefilled = ETrue;
00071 }
00072
00073 if(myAudio->iPrefilled && myAudio->iBlocksInQueue == 0)
00074 {
00075 myAudio->Play((ubyte*)buffer, bufSize);
00076 gTest.Printf(_L("-"));
00077 myAudio->iBlocksInQueue = 1;
00078 myAudio->iPrefilled = EFalse;
00079 }
00080
00081 return ETrue;
00082 }
00083
00084
00085
00086
00087
00088
00089 void SidPlayExceptionHandler(TExcType aExc)
00090 {
00091 gTest.Printf(_L("### SOMETHING went wrong (exception = %d)\n"), aExc);
00092
00093 ELOG2(_L8("dump: myEmuEngine: 0x%08x \n") , myEmuEngine );
00094 ELOG2(_L8(" buffer : 0x%08x \n") , buffer );
00095 ELOG2(_L8(" myAudio : 0x%08x \n") , myAudio );
00096 ELOG2(_L8(" myTune : 0x%08x \n") , myTune );
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 FOREVER
00109 {
00110 TInt ret = getchar();
00111 if(ret == 'q' || ret == 'Q')
00112 User::Panic(_L("bye"), 0);
00113 }
00114 }
00115
00116
00117
00118 enum
00119 {
00120 ERR_NOT_ENOUGH_MEMORY,
00121 ERR_SYNTAX,
00122 ERR_ENDIANESS
00123 };
00124
00125 void printtext( int messageNum );
00126
00127 static bool verboseOutput = false;
00128
00129
00135 class CConsoleReader : public CActive
00136 {
00137 public:
00138 CConsoleReader(CConsoleBase& aConsole);
00139 ~CConsoleReader();
00140 protected:
00141 void Activate();
00142
00143 virtual void DoCancel();
00144 virtual void RunL();
00145 private:
00146 TBuf8<2> buffTx;
00147 CConsoleBase& iConsole;
00148 };
00149
00150 CConsoleReader::CConsoleReader(CConsoleBase& aConsole)
00156 :CActive(EPriorityHigh)
00157 ,buffTx(2)
00158 ,iConsole(aConsole)
00159 {
00160 CTOR(CConsoleReader);
00161
00162 iStatus = 0;
00163
00164 CActiveScheduler::Add(this);
00165 Activate();
00166 }
00167
00168 CConsoleReader::~CConsoleReader()
00172 {
00173 DTOR(CConsoleReader);
00174 if(IsAdded())
00175 Deque();
00176
00177 DoCancel();
00178 }
00179
00180 void CConsoleReader::Activate()
00184 {
00185 ELOG1(_L8("CConsoleReader::Activate\n") );
00186 iConsole.Read(iStatus);
00187 CActive::SetActive();
00188 }
00189
00190 void CConsoleReader::DoCancel()
00194 {
00195 iConsole.ReadCancel();
00196 }
00197
00198 void CConsoleReader::RunL()
00203 {
00204 ELOG2(_L8("CConsoleReader::RunL iStatus=%d\n"), iStatus.Int() );
00205
00206 const TInt key = iConsole.KeyCode();
00207 switch(key)
00208 {
00209 case 'q':
00210 case 'Q':
00211 case 0x03:
00212 CActiveScheduler::Stop();
00213 return;
00214
00215 case EKeyUpArrow:
00216 {
00217 const TInt vol = myAudio->VolumeDelta(+1);
00218 gTest.Printf(_L("\nVolume++ (%d)"), vol);
00219 break;
00220 }
00221
00222 case EKeyDownArrow:
00223 {
00224 const TInt vol = myAudio->VolumeDelta(-1);
00225 gTest.Printf(_L("\nVolume-- (%d)"), vol);
00226 break;
00227 }
00228
00229 case EKeyLeftArrow:
00230 selectedSong-=2;
00231
00232 case EKeyRightArrow:
00233 ++selectedSong;
00234 if ( !sidEmuInitializeSong(*myEmuEngine, *myTune, selectedSong) )
00235 {
00236 gTest.Printf(_L("SIDPLAY: SID Emulator Engine components not ready"));
00237 }
00238 gTest.Printf(_L("\nsong: %d"), selectedSong);
00239 break;
00240
00241
00242 #ifdef __PROFILING__
00243 case 'p':
00244 case 'P':
00245 {
00246 TFixedArray<TProfile, EProfiles> result;
00247 RDebug::ProfileResult(result.Begin(), 0, EProfiles);
00248 gTest.Printf(_L("===dumping profiles===\n" ));
00249 ELOG1(_L8("===dumping profiles===\n") );
00250 for (TInt i=0; i<EProfiles; i++)
00251 {
00252 gTest.Printf(_L("Profile %d: Calls: %d, Clock ticks: %d Avg: %d\n"),
00253 i, result[i].iCount, result[i].iTime,
00254 result[i].iCount ? (result[i].iTime / result[i].iCount) : -1 );
00255 TBuf8<256> buf;
00256 buf.AppendFormat(_L8("Profile %d: Calls: %d, Clock ticks: %d Avg: %d\n"),
00257 i, result[i].iCount, result[i].iTime,
00258 result[i].iCount ? (result[i].iTime / result[i].iCount) : -1 );
00259 ELOG1(buf);
00260 }
00261 }
00262
00263 #endif // __PROFILING__
00264
00265
00266 default:
00267 gTest.Printf(_L("%c [0x%04x]"), key, key);
00268 break;
00269 }
00270 Activate();
00271 }
00272
00273
00274 LOCAL_C void InitMainL(void)
00278 {
00279 TInt ret;
00280
00281 ELOG1(_L8("----------new log----------\n") );
00282
00283
00284
00285 #if 0
00286
00287 _ELOG(_L8("installing exception handler...") );
00288 ret = RThread().SetExceptionHandler(SidPlayExceptionHandler, 0xffffffff);
00289 if(ret == KErrNone)
00290 _ELOG(_L8("OK\n"));
00291 else
00292 _ELOG(_L8("failed!\n"));
00293 #endif
00294
00295 gTest.Printf(_L("\nSIDPLAY Music player and C64 SID chip emulator Base Version %s \n"), emu_version );
00296 gTest.Printf(_L("Copyright (c) 1994-1997 Michael Schwendt All rights reserved.\n"));
00297 gTest.Printf(_L("Ported to Epoc32 by Alfred E. Heggestad <edmund@roland.org>\n"));
00298 gTest.Printf(_L("This is version %s\n"), epoc_version);
00299 gTest.Printf(_L("\n"));
00300 gTest.Printf(_L("Use arrow keys for volume and song number\n"));
00301
00302
00303
00304
00305
00306 ELOG1(_L8("initialising EE (Emulator Engine)...\n"));
00307 myEmuEngine = new (ELeave) emuEngine();
00308 ELOG1(_L8("emuEngine created\n"));
00309
00310
00311
00312
00313 if ( !myEmuEngine->verifyEndianess() )
00314 {
00315 printtext(ERR_ENDIANESS);
00316 }
00317
00318 ELOG1(_L8("...Done\n"));
00319
00320
00321 struct emuConfig myEmuConfig;
00322 myEmuEngine->getConfig(myEmuConfig);
00323
00324
00325
00326
00327 #if defined(__ER6__)
00328 if (RProcess().CommandLineLength() == 0)
00329 printtext(ERR_SYNTAX);
00330 TBuf<256> cmdLineBuf;
00331 RProcess().CommandLine(cmdLineBuf);
00332 #else
00333 TCommand cmdLineBuf = RProcess().CommandLine();
00334 if (cmdLineBuf.Length() == 0)
00335 printtext(ERR_SYNTAX);
00336 #endif
00337
00338
00339 #ifdef __ER6__
00340 myEmuConfig.frequency = SAMPLE_FREQ;
00341 myEmuConfig.channels = SIDEMU_MONO;
00342 myEmuConfig.bitsPerSample = SIDEMU_16BIT;
00343 #else
00344 myEmuConfig.frequency = KAlawSamplesPerSecond;
00345 myEmuConfig.channels = SIDEMU_MONO;
00346 myEmuConfig.bitsPerSample = SIDEMU_8BIT;
00347 #endif
00348
00349 ELOG1(_L8("parsing command line arguments..."));
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437 ELOG1(_L8("Validating SID emulator settings..."));
00438
00439 if ((myEmuConfig.autoPanning!=SIDEMU_NONE) && (myEmuConfig.channels==SIDEMU_MONO))
00440 {
00441 myEmuConfig.channels = SIDEMU_STEREO;
00442 }
00443 if ((myEmuConfig.autoPanning!=SIDEMU_NONE) && (myEmuConfig.volumeControl==SIDEMU_NONE))
00444 {
00445 myEmuConfig.volumeControl = SIDEMU_FULLPANNING;
00446 }
00447
00448 ELOG1(_L8("Done\n"));
00449
00450
00451
00452
00453
00454 ELOG1(_L8("creating Sidtune object..."));
00455 {
00456 TBuf8<256> buf8;
00457 buf8.Copy(cmdLineBuf);
00458 myTune = new sidTune((const char*)buf8.PtrZ());
00459 }
00460 struct sidTuneInfo mySidInfo;
00461 myTune->getInfo( mySidInfo );
00462 if ( !myTune )
00463 {
00464 gTest.Printf(_L("SIDPLAY: %s\n"), mySidInfo.statusString);
00465 exit(EXIT_ERROR_STATUS);
00466 }
00467 else
00468 {
00469 if (verboseOutput)
00470 {
00471
00472
00473
00474 }
00475 gTest.Printf(_L("--------------------------------------------------\n"));
00476 if ( mySidInfo.numberOfInfoStrings == 3 )
00477 {
00478
00479
00480
00481
00482 }
00483 else
00484 {
00485 for ( int infoi = 0; infoi < mySidInfo.numberOfInfoStrings; infoi++ )
00486 gTest.Printf(_L("Description : %s\n"), mySidInfo.infoString[infoi] );
00487 }
00488 gTest.Printf(_L("--------------------------------------------------\n"));
00489 if (verboseOutput)
00490 {
00491 gTest.Printf(_L("Load address : $%04x\n"), mySidInfo.loadAddr );
00492 gTest.Printf(_L("Init address : $%04x\n"), mySidInfo.initAddr );
00493 gTest.Printf(_L("Play address : $%04x\n"), mySidInfo.playAddr );
00494 }
00495 }
00496
00497 ELOG1(_L8("Done\n"));
00498
00499
00500
00501
00502
00503 #if defined (__WINS__)
00504 #define PDD_NAME _L("ESDRV")
00505 #define LDD_NAME _L("ESOUND")
00506
00507 gTest.Printf(_L("loading device drivers...(WINS only)"));
00508
00509 ret = User::LoadPhysicalDevice(PDD_NAME);
00510 if (ret!=KErrNone && ret!=KErrAlreadyExists)
00511 User::LeaveIfError(ret);
00512
00513 ret = User::LoadLogicalDevice(LDD_NAME);
00514 if (ret!=KErrNone && ret!=KErrAlreadyExists)
00515 User::LeaveIfError(ret);
00516
00517 gTest.Printf(_L("Loaded!\n"));
00518 #endif
00519
00520
00521 ELOG1(_L8("check if audio device exist..."));
00522
00523
00524
00525 myAudio = new (ELeave) audioDriver();
00526 myAudio->ConstructL();
00527
00528 if ( !myAudio->IsThere() )
00529 {
00530 gTest.Printf(_L("SIDPLAY: No audio device available !\n"));
00531 exit(EXIT_ERROR_STATUS);
00532 }
00533 ELOG1(_L8("Done\n"));
00534
00535
00536
00537 ELOG1(_L8("opening sound device... "));
00538 if ( !myAudio->Open(myEmuConfig.frequency, myEmuConfig.bitsPerSample,
00539 myEmuConfig.channels, fragments, fragSizeBase))
00540 {
00541 gTest.Printf(_L("%s \n"), myAudio->GetErrorString() );
00542 exit(EXIT_ERROR_STATUS);
00543 }
00544 ELOG1(_L8("Done\n"));
00545
00546
00547 if (verboseOutput)
00548 {
00549 gTest.Printf(_L("Block size : %d \n"), (udword)myAudio->GetBlockSize() );
00550 gTest.Printf(_L("Fragments : %d \n"), myAudio->GetFragments() );
00551 }
00552
00553
00554
00555
00556
00557 ELOG1(_L8("Configuring the Emulator Engine..."));
00558
00559
00560 myEmuConfig.frequency = (uword)myAudio->GetFrequency();
00561 myEmuConfig.bitsPerSample = myAudio->GetSamplePrecision();
00562 myEmuConfig.sampleFormat = myAudio->GetSampleEncoding();
00563 ret = myEmuEngine->setConfig( myEmuConfig );
00564 if(!ret)
00565 {
00566 gTest.Printf(_L("Could not SetConfig on emu engine\n") );
00567 exit(EXIT_ERROR_STATUS);
00568 }
00569
00570
00571 if (verboseOutput)
00572 {
00573 gTest.Printf(_L("Frequency : %d Hz\n"), myEmuConfig.frequency );
00574 gTest.Printf(_L("SID Filter : %s \n"), (myEmuConfig.emulateFilter ? "Yes" : "No") );
00575 if (myEmuConfig.memoryMode == MPU_PLAYSID_ENVIRONMENT)
00576 {
00577 gTest.Printf(_L("Memory mode : PlaySID (this is supposed to fix PlaySID-specific rips)\n"));
00578 }
00579 else if (myEmuConfig.memoryMode == MPU_TRANSPARENT_ROM)
00580 {
00581 gTest.Printf(_L("Memory mode : Transparent ROM (SIDPLAY default)\n"));
00582 }
00583 else if (myEmuConfig.memoryMode == MPU_BANK_SWITCHING)
00584 {
00585 gTest.Printf(_L("Memory mode : Bank Switching\n"));
00586 }
00587 }
00588 ELOG1(_L8("Done\n"));
00589
00590
00591
00592
00593
00594 ELOG1(_L8("preparing to play a Sidtune..."));
00595 if ( !sidEmuInitializeSong(*myEmuEngine, *myTune, selectedSong) )
00596 {
00597 gTest.Printf(_L("SIDPLAY: SID Emulator Engine components not ready"));
00598 exit(EXIT_ERROR_STATUS);
00599 }
00600 ELOG1(_L8("Done\n"));
00601
00602
00603 ELOG1(_L8("Reading current setting of the Sidtune..."));
00604 myTune->getInfo( mySidInfo );
00605 if ( !myTune )
00606 {
00607 gTest.Printf(_L("SIDPLAY: %s \n"), mySidInfo.statusString );
00608 exit(EXIT_ERROR_STATUS);
00609 }
00610 ELOG1(_L8("Done\n"));
00611
00612 gTest.Printf(_L("Setting song : %d out of %d (default = %d)"),
00613 mySidInfo.currentSong, mySidInfo.songs, mySidInfo.startSong );
00614 selectedSong = mySidInfo.startSong;
00615 if (verboseOutput)
00616 {
00617 gTest.Printf(_L("Song speed : %s \n"), mySidInfo.speedString );
00618 }
00619
00620
00621
00622
00623
00624 ELOG1(_L8("keep up a continuous output sample stream..."));
00625 bufSize = myAudio->GetBlockSize();
00626
00627 if(bufSize <= 0 )
00628 {
00629 gTest.Printf(_L("Error: buffer size is not positive! (%d) \n"), bufSize);
00630 exit(EXIT_ERROR_STATUS);
00631 }
00632
00633 if ((buffer = new TInt16[bufSize]) == 0)
00634 {
00635 printtext(ERR_NOT_ENOUGH_MEMORY);
00636 exit(EXIT_ERROR_STATUS);
00637 }
00638
00639 ELOG1(_L8("Done\n"));
00640
00641 ELOG3(_L8("BUF: size = %d at 0x%08x\n"), bufSize, buffer );
00642
00643
00644 gTest.Printf(_L("Playing, press Ctrl-C to stop ...\n"));
00645 ELOG1(_L8("now playing...\n"));
00646
00647
00648
00649
00650
00651
00652
00653
00654 CConsoleReader* cons = new (ELeave) CConsoleReader(*gTest.Console());
00655
00656 ELOG1(_L8("Creating new CIdle object. \n"));
00657 CIdle* idle = CIdle::NewL(CActive::EPriorityLow);
00658 idle->Start(TCallBack(SidPlayerThread));
00659 ELOG1(_L8("Callback installed. \n"));
00660
00661 gTest.Printf(_L("SID emulation started\n"));
00662 CActiveScheduler::Start();
00663 gTest.Printf(_L("SID emulation stopped\n"));
00664
00665 #ifndef __ER6__
00666 delete idle;
00667 #endif
00668 delete cons;
00669
00670 ELOG1(_L8("stopped! \n"));
00671
00672
00673
00674
00675 delete myEmuEngine;
00676 delete myAudio;
00677 delete myTune;
00678 delete buffer;
00679
00680 exit(0);
00681 }
00682
00683
00684 void printtext(int number)
00685 {
00686 switch (number)
00687 {
00688 case ERR_ENDIANESS:
00689 {
00690 gTest.Printf(_L("SIDPLAY: ERROR: Hardware endianess improperly configured.\n"));
00691 exit(EXIT_ERROR_STATUS);
00692 break;
00693 }
00694 case ERR_NOT_ENOUGH_MEMORY:
00695 gTest.Printf(_L("SIDPLAY: ERROR: Not enough memory\n"));
00696 exit(EXIT_ERROR_STATUS);
00697 case ERR_SYNTAX:
00698 gTest.Printf(_L(" syntax: sidplay [-<command>] <datafile>|-\n"));
00699 gTest.Printf(_L(" commands: -h display this screen\n"));
00700 gTest.Printf(_L(" -v verbose output\n"));
00701 gTest.Printf(_L(" -f<num> set frequency in Hz (default: 22050)\n"));
00702 gTest.Printf(_L(" -o<num> set song number (default: preset)\n"));
00703 gTest.Printf(_L(" -a improve PlaySID compatibility (read the docs !)\n"));
00704 gTest.Printf(_L(" -a2 bank switching mode (overrides -a)\n"));
00705 #if defined(linux) || defined(__FreeBSD__) || defined(__amigaos__) || defined(hpux)
00706 gTest.Printf(_L(" -s enable stereo replay\n"));
00707 gTest.Printf(_L(" -ss enable stereo surround\n"));
00708 gTest.Printf(_L(" -pc enable centered auto-panning (stereo only)\n"));
00709 #endif
00710 gTest.Printf(_L(" -nf no SID filter emulation\n"));
00711 gTest.Printf(_L(" -n set NTSC clock speed (default: PAL)\n"));
00712 gTest.Printf(_L(" -c force song speed = clock speed (PAL/NTSC)\n"));
00713 gTest.Printf(_L(" -bn<num> set number of audio buffer fragments to use\n"));
00714 gTest.Printf(_L(" -bs<num> set size 2^<num> of audio buffer fragments\n"));
00715 (void)gTest.Getch();
00716 exit(EXIT_ERROR_STATUS);
00717 default:
00718 gTest.Printf(_L("SIDPLAY: ERROR: Internal system error\n"));
00719 exit(EXIT_ERROR_STATUS);
00720 }
00721
00722 }
00723
00724
00725 LOCAL_C void RunTestsL()
00729 {
00730 InitMainL();
00731 }
00732
00733
00734 GLDEF_C TInt E32Main()
00738 {
00739
00740
00741 TInt processHandleCountBefore;
00742 TInt threadHandleCountBefore;
00743 RThread().HandleCount(processHandleCountBefore, threadHandleCountBefore);
00744
00745 CTrapCleanup* cleanup = CTrapCleanup::New();
00746
00747 __UHEAP_MARK;
00748
00749 CActiveScheduler* theActiveScheduler = new CActiveScheduler();
00750 CActiveScheduler::Install(theActiveScheduler);
00751
00752 gTest.Printf(_L("."));
00753
00754 TRAPD(err, RunTestsL());
00755 if (err!=KErrNone)
00756 {
00757 gTest.Printf(_L("ERROR: Leave %d - press a key\n"), err);
00758 (void)gTest.Getch();
00759 }
00760
00761 gTest.End();
00762 gTest.Close();
00763
00764 __UHEAP_MARKEND;
00765
00766 __ASSERT_ALWAYS(RThread().RequestCount()==0, User::Panic(_L("outstanding requests!"), RThread().RequestCount()) );
00767
00768
00769 TInt processHandleCountAfter;
00770 TInt threadHandleCountAfter;
00771 RThread().HandleCount(processHandleCountAfter, threadHandleCountAfter);
00772
00773 __ASSERT_ALWAYS(threadHandleCountBefore==threadHandleCountAfter,
00774 User::Panic(_L("outstanding handles!"), threadHandleCountAfter) );
00775
00776 delete cleanup;
00777 return KErrNone;
00778 }
00779
00780
00781
00782
00783
00784
00785 GLDEF_C TInt E32Dll(TDllReason)
00789 {
00790 return KErrNone;
00791 }
00792
00793
00794