Subversion Repositories pentevo

Rev

Rev 716 | Blame | Last modification | View Log | Download | RSS feed

  1. #include "std.h"
  2.  
  3. #include "emul.h"
  4. #include "vars.h"
  5. #include "vs1001.h"
  6. #include "bass.h"
  7. #include "snd_bass.h"
  8.  
  9. bool SkipZeroes = true;
  10.  
  11. void TRingBuffer::Reset()
  12. {
  13.     CritSect.Lock();
  14.     WrPos = RdPos = 0;
  15.     Dreq = true;
  16.     Count = 0;
  17.     Cancelled = false;
  18.     NotEmpty.Reset();
  19.     CritSect.Unlock();
  20. }
  21.  
  22. void TRingBuffer::Put(u8 Val)
  23. {
  24.     CritSect.Lock();
  25.     Buf[WrPos++] = Val;
  26.     WrPos &= (Size - 1);
  27.     Count++;
  28.     assert(Count < Size);
  29.     Dreq = (Size - Count) > 32;
  30.     NotEmpty.Set();
  31.     CritSect.Unlock();
  32. }
  33.  
  34. u32 TRingBuffer::Get(void *Data, u32 ReqLen)
  35. {
  36.     u32 RetLen;
  37.     u8 *Ptr = (u8 *)Data;
  38.  
  39. retry:
  40.     NotEmpty.Wait();
  41.  
  42.     CritSect.Lock();
  43.     if(Count == 0)
  44.     {
  45.         CritSect.Unlock();
  46.         if(Cancelled)
  47.             return 0;
  48.         goto retry;
  49.     }
  50.  
  51.     assert(Count != 0);
  52.  
  53.     if(Cancelled)
  54.     {
  55.         CritSect.Unlock();
  56.         return 0;
  57.     }
  58.  
  59.     RetLen = min(Count, ReqLen);
  60.     if(RetLen)
  61.     {
  62.         u32 RdLen = min(RetLen, Size - RdPos);
  63.         memcpy(Ptr, &Buf[RdPos], RdLen);
  64.         RdPos += RdLen;
  65.         RdPos &= (Size - 1);
  66.         Ptr += RdLen;
  67.         if(RetLen > RdLen)
  68.         {
  69.             assert(RdPos == 0);
  70.             RdLen = RetLen - RdLen;
  71.             memcpy(Ptr, Buf, RdLen);
  72.             RdPos += RdLen;
  73.             RdPos &= (Size - 1);
  74.         }
  75.         Count -= RetLen;
  76.  
  77.         Dreq = (Size - Count) > 32;
  78.  
  79.         if(Count == 0)
  80.             NotEmpty.Reset();
  81.     }
  82.     CritSect.Unlock();
  83.  
  84.     return RetLen;
  85. }
  86.  
  87. BASS_FILEPROCS TVs1001::Procs = { TVs1001::StreamClose, TVs1001::StreamLen, TVs1001::StreamRead, TVs1001::StreamSeek };
  88.  
  89. TVs1001::TVs1001() : EventStreamClose(FALSE)
  90. {
  91.     Mp3Stream = 0;
  92.     ThreadHandle = 0;
  93.  
  94.     Regs[VOL] = 0; // max volume on all channels
  95.  
  96.     Reset();
  97.  
  98.     SetVol(Regs[VOL]);
  99. }
  100.  
  101. void TVs1001::Reset()
  102. {
  103. //    printf(__FUNCTION__"\n");
  104.  
  105.     memset(Regs, 0, sizeof(Regs));
  106.  
  107.     CurState = ST_IDLE;
  108.     Idx = 0;
  109.     Msb = Lsb = 0xFF;
  110.     nCs = true;
  111.     RingBuffer.Reset();
  112.  
  113.     if(conf.gs_type != 1)
  114.         return;
  115.  
  116.     static bool BassInit = false;
  117.     if(!BassInit)
  118.     {
  119.         BASS::Init(-1, conf.sound.fq, BASS_DEVICE_LATENCY, wnd, NULL);
  120.         ThreadHandle = (HANDLE)_beginthreadex(0, 0, Thread, this, 0, 0);
  121.         BassInit = true;
  122.     }
  123. }
  124.  
  125. void TVs1001::SetNcs(bool nCs)
  126. {
  127.     TVs1001::nCs = nCs;
  128.     if(nCs)
  129.         CurState = ST_IDLE;
  130. }
  131.  
  132. u8 TVs1001::Rd()
  133. {
  134.     if(nCs) // codec not selected
  135.         return 0xFF;
  136.  
  137.     u16 Val = Rd(Idx);
  138.     u8 RetVal = 0xFF;
  139.     TState NextState = CurState;
  140.     switch(CurState)
  141.     {
  142.     case ST_RD_MSB: RetVal = (Val >> 8U) & 0xFF; NextState = ST_RD_LSB; break;
  143.     case ST_RD_LSB: RetVal = Val & 0xFF;  NextState = ST_IDLE; break;
  144.     }
  145. //    printf("Vs1001: RD %s->%s, val = 0x%X\n", State2Str(CurState), State2Str(NextState), RetVal);
  146.     CurState = NextState;
  147.  
  148.     return RetVal;
  149. }
  150.  
  151. u16 TVs1001::Rd(int Idx)
  152. {
  153.     switch(Idx)
  154.     {
  155.     case MODE:
  156.     case CLOCKF:
  157.     case STATUS:
  158.     case AUDATA:
  159.     case HDAT0:
  160.     case HDAT1:
  161.     case AIADDR:
  162.     case VOL:
  163.     case AICTRL0:
  164.     case AICTRL1:
  165.         return Regs[Idx];
  166.     case DECODE_TIME:
  167.         return GetDecodeTime();
  168.     }
  169.     return 0xFFFF;
  170. }
  171.  
  172. void TVs1001::Wr(int Idx, u16 Val)
  173. {
  174.     switch(Idx)
  175.     {
  176.     case CLOCKF:
  177.     case WRAM_W:
  178.     case WRAMADDR_W:
  179.     case AIADDR:
  180.     case AICTRL0:
  181.     case AICTRL1:
  182.         Regs[Idx] = Val;
  183.     break;
  184.  
  185.     case VOL:
  186.         Regs[Idx] = Val;
  187.         SetVol(Val);
  188.     break;
  189.  
  190.     case MODE:
  191.         Regs[Idx] = Val;
  192.         if(Val & SM_RESET)
  193.             SoftReset();
  194.     break;
  195.  
  196.     case STATUS:
  197.         Regs[Idx] = Val & 0xF; // vs1001
  198.     break;
  199.     }
  200. }
  201.  
  202. void TVs1001::WrCmd(u8 Val)
  203. {
  204.     TState NextState = ST_IDLE;
  205.  
  206.     if(nCs) // codec not selected
  207.         return;
  208.  
  209.     switch(CurState)
  210.     {
  211.     case ST_IDLE:
  212.         switch(Val)
  213.         {
  214.         case CMD_RD: NextState = ST_RD_IDX; break;
  215.         case CMD_WR: NextState = ST_WR_IDX; break;
  216.         default:
  217. //            printf("Vs1001: invalid cmd = 0x%X\n", Val);
  218.            ;
  219.         }
  220.     break;
  221.     case ST_RD_IDX: Idx = Val; NextState = ST_RD_MSB; break;
  222.     case ST_WR_IDX: Idx = Val; NextState = ST_WR_MSB; break;
  223.     case ST_WR_MSB: Msb = Val; NextState = ST_WR_LSB; break;
  224.     case ST_WR_LSB:
  225.         Lsb = Val;
  226.         Wr(Idx, (Msb << 8U) | Lsb);
  227.     break;
  228.  
  229.     case ST_RD_MSB:
  230.     case ST_RD_LSB:
  231.         NextState = CurState;
  232.     break;
  233.  
  234.     default:
  235. //        printf("Vs1001: WR invalid state = %s\n", State2Str(CurState));
  236.         ;
  237.     }
  238. //    printf("Vs1001: WR %s->%s, val = 0x%X\n", State2Str(CurState), State2Str(NextState), Val);
  239.     CurState = NextState;
  240. }
  241.  
  242. void TVs1001::Wr(u8 Val)
  243. {
  244. //    printf(__FUNCTION__" val = 0x%X\n", Val);
  245.     if(!Mp3Stream && SkipZeroes)
  246.     {
  247.         if(Val == 0) // skip zeroes before format detection
  248.             return;
  249.         SkipZeroes = false;
  250.     }
  251.  
  252.     RingBuffer.Put(Val);
  253. }
  254.  
  255. void TVs1001::SetVol(u16 Vol)
  256. {
  257. //   __debugbreak();
  258.    if(!Mp3Stream)
  259.        return;
  260.  
  261.    float VolDbR = (Vol & 0xFF) / 2.0f;
  262.    float VolDbL = ((Vol >> 8U) & 0xFF) / 2.0f;
  263.    float VolR = powf(10.0f, -VolDbR / 10.0f);
  264.    float VolL = powf(10.0f, -VolDbL / 10.0f);
  265.    float Pan = VolR - VolL;
  266.    float VolM = (VolR + VolL) / 2.0f;
  267.  
  268. //   printf("%s, Vol = %u\n", __FUNCTION__, Vol);
  269.    if (!BASS::ChannelSetAttribute(Mp3Stream, BASS_ATTRIB_VOL, VolM))
  270.        printf("BASS_ChannelSetAttribute() [vol]\n");
  271.    if (!BASS::ChannelSetAttribute(Mp3Stream, BASS_ATTRIB_PAN, Pan))
  272.        printf("BASS_ChannelSetAttribute() [pan]\n");
  273. }
  274.  
  275. u16 TVs1001::GetDecodeTime()
  276. {
  277.     if(!Mp3Stream)
  278.         return 0;
  279.  
  280.     QWORD Pos = BASS::ChannelGetPosition(Mp3Stream, BASS_POS_BYTE);
  281.     double Time = BASS::ChannelBytes2Seconds(Mp3Stream, Pos);
  282.     return (u16)Time;
  283. }
  284.  
  285. // called from main loop when processing ngs z80 code
  286. void TVs1001::SoftReset()
  287. {
  288. //    printf("%s\n", __FUNCTION__);
  289.  
  290.     ShutDown();
  291.  
  292.     if(Mp3Stream)
  293.     {
  294.         if(!BASS::ChannelStop(Mp3Stream))
  295.         {
  296.             printf("BASS_ChannelStop()\n");
  297.             assert(false);
  298.         }
  299.  
  300.         if(!BASS::StreamFree(Mp3Stream))
  301.         {
  302.             printf("BASS_ChannelStop()\n");
  303.             assert(false);
  304.         }
  305.  
  306.         EventStreamClose.Wait();
  307.         EventStreamClose.Reset();
  308.         Mp3Stream = 0;
  309.     }
  310.  
  311.     RingBuffer.Reset();
  312.     SkipZeroes = true;
  313.     ThreadHandle = (HANDLE)_beginthreadex(0, 0, Thread, this, 0, 0);
  314. }
  315.  
  316. void TVs1001::ShutDown()
  317. {
  318.     RingBuffer.Cancel();
  319.  
  320.     if(ThreadHandle)
  321.     {
  322.         WaitForSingleObject(ThreadHandle, INFINITE);
  323.         CloseHandle(ThreadHandle);
  324.         ThreadHandle = 0;
  325.     }
  326. }
  327.  
  328. // called from main loop priodicaly
  329. void TVs1001::Play()
  330. {
  331.    if(!Mp3Stream)
  332.        return;
  333.  
  334.    BASS::ChannelPlay(Mp3Stream, FALSE);
  335. }
  336.  
  337. // stream file format detection tread
  338. void TVs1001::Thread()
  339. {
  340. //    printf(__FUNCTION__"\n");
  341.     Mp3Stream = BASS::StreamCreateFileUser(STREAMFILE_BUFFER, BASS_SAMPLE_FLOAT | BASS_STREAM_BLOCK, &Procs, this);
  342.     if(!Mp3Stream)
  343.     {
  344. //        printf(__FUNCTION__" Err = %d\n", BASS_ErrorGetCode());
  345.     }
  346. //    printf(__FUNCTION__"->Exit\n");
  347. }
  348.  
  349. // bass asynchronous callback
  350. void TVs1001::StreamClose()
  351. {
  352.     EventStreamClose.Set();
  353. }
  354.  
  355. // bass asynchronous callback
  356. QWORD TVs1001::StreamLen()
  357. {
  358.     return 0;
  359. }
  360.  
  361. // bass asynchronous callback
  362. DWORD TVs1001::StreamRead(void *Buffer, DWORD Length)
  363. {
  364.     DWORD Len = RingBuffer.Get(Buffer, Length);
  365. //    printf(__FUNCTION__"->%d/%d\n", Length, Len);
  366.  
  367. /*
  368.     static FILE *f = fopen("dump.mp3", "wb");
  369.     if(Len != 0)
  370.         fwrite(Buffer, Len, 1, f);
  371. */
  372.     return Len;
  373. }
  374.  
  375. // bass asynchronous callback
  376. BOOL TVs1001::StreamSeek(QWORD offset)
  377. {
  378.     return FALSE;
  379. }
  380.  
  381. #define STATE2STR(x) case x:  return #x
  382.  
  383. const char *TVs1001::State2Str(TState State)
  384. {
  385.     switch(State)
  386.     {
  387.     STATE2STR(ST_IDLE);
  388.     STATE2STR(ST_RD);
  389.     STATE2STR(ST_WR);
  390.     STATE2STR(ST_RD_IDX);
  391.     STATE2STR(ST_WR_IDX);
  392.     STATE2STR(ST_RD_MSB);
  393.     STATE2STR(ST_RD_LSB);
  394.     STATE2STR(ST_WR_MSB);
  395.     STATE2STR(ST_WR_LSB);
  396.     }
  397.     return "???";
  398. }
  399.  
  400. TVs1001 Vs1001;
  401.