#include "cps.h"

extern "C" {
 #include "driver.h"
 #include "ym2151.h"
}

// PSound (CPS1 sound) Mixing

int bPsmOkay=0; // 1 if the module is okay
static short *WaveBuf=NULL;

int PsmInit()
{
  int nRet;
  int nMemLen;
  bPsmOkay=0; // not ok yet
  if (nBurnSoundRate<=0) return 1;

  nRet=YM2151Init(1,3579540,nBurnSoundRate); // Init FM sound chip
  if (nRet!=0) return 1;

  // Allocate a buffer for the intermediate sound (between YM2151 and pBurnSoundOut)
  nMemLen=nBurnSoundLen*2*sizeof(short);
  WaveBuf=(short *)malloc(nMemLen);
  if (WaveBuf==NULL) { PsmExit(); return 1; }
  memset(WaveBuf,0,nMemLen); // init to silence

  // Init ADPCM
  OKIM6295ROM = CpsAd;
  if (Forgottn) {
	nRet = OKIM6295Init(0, 6061, 21.5);
  } else {
	nRet = OKIM6295Init(0, 7576, 21.5);
  }

  if (nRet!=0) { PsmExit(); return 1; }

  bPsmOkay=1; // ok
  return 0;
}

int PsmExit()
{
  bPsmOkay=0; // not ok
  OKIM6295Exit(0);

  if (WaveBuf!=NULL) free(WaveBuf);  WaveBuf=NULL;
  YM2151Shutdown();  // Exit FM sound chip
  return 0;
}

// Render a section of sound
// e.g. 0x200 to 0x400 for second half of frame
int PsmSect(int nStart,int nEnd)
{
  short *Buf[2];
  int p1,p2,i;
  if (bPsmOkay==0) return 1;  if (pBurnSoundOut==NULL) return 1;
  if (nEnd<=nStart) return 0;

  // Copy this portion of YM2151 sound into our WaveBuf buffer
  p1=nStart*nBurnSoundLen; p1>>=10;
  p2=nEnd  *nBurnSoundLen; p2>>=10;
  Buf[0]=WaveBuf+p1;
  Buf[1]=WaveBuf+nBurnSoundLen+p1;

  // Render Fm
  YM2151UpdateOne(0, Buf, p2 - p1);

  // Interleve into our buffer
  for (i=p1;i<p2;i++)
  {
    int l,r;
    l=WaveBuf[i];
    r=WaveBuf[nBurnSoundLen+i];
    l>>=1; r>>=1;

    pBurnSoundOut[(i<<1)+0]=(short)l;
    pBurnSoundOut[(i<<1)+1]=(short)r;
  }

  // Render ADPCM
  OKIM6295Render(0, pBurnSoundOut + (p1 << 1), p2 - p1);

  return 0;
}
