diff options
Diffstat (limited to 'src/SPU.cpp')
| -rw-r--r-- | src/SPU.cpp | 112 | 
1 files changed, 83 insertions, 29 deletions
diff --git a/src/SPU.cpp b/src/SPU.cpp index 7f70e65..9862077 100644 --- a/src/SPU.cpp +++ b/src/SPU.cpp @@ -1,5 +1,5 @@  /* -    Copyright 2016-2017 StapleButter +    Copyright 2016-2019 StapleButter      This file is part of melonDS. @@ -24,8 +24,6 @@  // SPU TODO  // * loop mode 3, what does it do? -// * the FIFO, whatever it is. GBAtek mentions it but gives no details. -// * consider mixing every sample instead of every 16?  namespace SPU @@ -121,6 +119,21 @@ void Stop()      memset(OutputBuffer, 0, 2*OutputBufferSize*2);  } +void DoSavestate(Savestate* file) +{ +    file->Section("SPU."); + +    file->Var16(&Cnt); +    file->Var8(&MasterVolume); +    file->Var16(&Bias); + +    for (int i = 0; i < 16; i++) +        Channels[i]->DoSavestate(file); + +    Capture[0]->DoSavestate(file); +    Capture[1]->DoSavestate(file); +} +  void SetBias(u16 bias)  { @@ -154,6 +167,36 @@ void Channel::Reset()      FIFOLevel = 0;  } +void Channel::DoSavestate(Savestate* file) +{ +    file->Var32(&Cnt); +    file->Var32(&SrcAddr); +    file->Var16(&TimerReload); +    file->Var32(&LoopPos); +    file->Var32(&Length); + +    file->Var8(&Volume); +    file->Var8(&VolumeShift); +    file->Var8(&Pan); + +    file->Var32(&Timer); +    file->Var32((u32*)&Pos); +    file->Var16((u16*)&CurSample); +    file->Var16(&NoiseVal); + +    file->Var32((u32*)&ADPCMVal); +    file->Var32((u32*)&ADPCMIndex); +    file->Var32((u32*)&ADPCMValLoop); +    file->Var32((u32*)&ADPCMIndexLoop); +    file->Var8(&ADPCMCurByte); + +    file->Var32(&FIFOReadPos); +    file->Var32(&FIFOWritePos); +    file->Var32(&FIFOReadOffset); +    file->Var32(&FIFOLevel); +    file->VarArray(FIFO, 8*4); +} +  void Channel::FIFO_BufferData()  {      u32 totallen = LoopPos + Length; @@ -161,8 +204,8 @@ void Channel::FIFO_BufferData()      if (FIFOReadOffset >= totallen)      {          u32 repeatmode = (Cnt >> 27) & 0x3; -        if (repeatmode == 2) return; // one-shot sound, we're done -        if (repeatmode == 1) FIFOReadOffset = LoopPos; +        if      (repeatmode & 1) FIFOReadOffset = LoopPos; +        else if (repeatmode & 2) return; // one-shot sound, we're done      }      u32 burstlen = 16; @@ -212,7 +255,7 @@ void Channel::Start()      FIFOReadOffset = 0;      FIFOLevel = 0; -    // when starting a channel, two 4-word chunks are buffered +    // when starting a channel, buffer data      if (((Cnt >> 29) & 0x3) != 3)      {          FIFO_BufferData(); @@ -226,18 +269,17 @@ void Channel::NextSample_PCM8()      if (Pos < 0) return;      if (Pos >= (LoopPos + Length))      { -        // TODO: what happens when mode 3 is used?          u32 repeat = (Cnt >> 27) & 0x3; -        if (repeat == 2) +        if (repeat & 1) +        { +            Pos = LoopPos; +        } +        else if (repeat & 2)          {              CurSample = 0;              Cnt &= ~(1<<31);              return;          } -        else if (repeat == 1) -        { -            Pos = LoopPos; -        }      }      s8 val = FIFO_ReadData<s8>(); @@ -250,18 +292,17 @@ void Channel::NextSample_PCM16()      if (Pos < 0) return;      if ((Pos<<1) >= (LoopPos + Length))      { -        // TODO: what happens when mode 3 is used?          u32 repeat = (Cnt >> 27) & 0x3; -        if (repeat == 2) +        if (repeat & 1) +        { +            Pos = LoopPos>>1; +        } +        else if (repeat & 2)          {              CurSample = 0;              Cnt &= ~(1<<31);              return;          } -        else if (repeat == 1) -        { -            Pos = LoopPos>>1; -        }      }      s16 val = FIFO_ReadData<s16>(); @@ -290,21 +331,20 @@ void Channel::NextSample_ADPCM()      if ((Pos>>1) >= (LoopPos + Length))      { -        // TODO: what happens when mode 3 is used?          u32 repeat = (Cnt >> 27) & 0x3; -        if (repeat == 2) -        { -            CurSample = 0; -            Cnt &= ~(1<<31); -            return; -        } -        else if (repeat == 1) +        if (repeat & 1)          {              Pos = LoopPos<<1;              ADPCMVal = ADPCMValLoop;              ADPCMIndex = ADPCMIndexLoop;              ADPCMCurByte = FIFO_ReadData<u8>();          } +        else if (repeat & 2) +        { +            CurSample = 0; +            Cnt &= ~(1<<31); +            return; +        }      }      else      { @@ -367,9 +407,6 @@ void Channel::NextSample_Noise()  template<u32 type>  void Channel::Run(s32* buf, u32 samples)  { -    for (u32 s = 0; s < samples; s++) -        buf[s] = 0; -      if (!(Cnt & (1<<31))) return;      for (u32 s = 0; s < samples; s++) @@ -439,6 +476,23 @@ void CaptureUnit::Reset()      FIFOLevel = 0;  } +void CaptureUnit::DoSavestate(Savestate* file) +{ +    file->Var8(&Cnt); +    file->Var32(&DstAddr); +    file->Var16(&TimerReload); +    file->Var32(&Length); + +    file->Var32(&Timer); +    file->Var32((u32*)&Pos); + +    file->Var32(&FIFOReadPos); +    file->Var32(&FIFOWritePos); +    file->Var32(&FIFOWriteOffset); +    file->Var32(&FIFOLevel); +    file->VarArray(FIFO, 4*4); +} +  void CaptureUnit::FIFO_FlushData()  {      for (u32 i = 0; i < 4; i++)  |