2017-04-04 13:32:50 +00:00
|
|
|
/*
|
2020-02-14 19:18:08 +00:00
|
|
|
Copyright 2016-2020 Arisotura
|
2017-04-04 13:32:50 +00:00
|
|
|
|
|
|
|
This file is part of melonDS.
|
|
|
|
|
|
|
|
melonDS is free software: you can redistribute it and/or modify it under
|
|
|
|
the terms of the GNU General Public License as published by the Free
|
|
|
|
Software Foundation, either version 3 of the License, or (at your option)
|
|
|
|
any later version.
|
|
|
|
|
|
|
|
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
|
|
with melonDS. If not, see http://www.gnu.org/licenses/.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef SPU_H
|
|
|
|
#define SPU_H
|
|
|
|
|
2018-10-18 00:45:38 +00:00
|
|
|
#include "Savestate.h"
|
|
|
|
|
2017-04-04 13:32:50 +00:00
|
|
|
namespace SPU
|
|
|
|
{
|
|
|
|
|
|
|
|
bool Init();
|
|
|
|
void DeInit();
|
|
|
|
void Reset();
|
2017-09-21 01:59:12 +00:00
|
|
|
void Stop();
|
2017-04-04 13:32:50 +00:00
|
|
|
|
2018-10-18 00:45:38 +00:00
|
|
|
void DoSavestate(Savestate* file);
|
|
|
|
|
2017-04-07 15:37:49 +00:00
|
|
|
void SetBias(u16 bias);
|
|
|
|
|
2020-10-31 12:43:33 +00:00
|
|
|
void Mix(u32 dummy);
|
2017-04-06 17:44:34 +00:00
|
|
|
|
2019-09-04 14:29:40 +00:00
|
|
|
void TrimOutput();
|
2019-09-01 13:41:46 +00:00
|
|
|
void DrainOutput();
|
|
|
|
void InitOutput();
|
2019-08-18 09:31:03 +00:00
|
|
|
int GetOutputSize();
|
2019-08-29 13:55:18 +00:00
|
|
|
void Sync(bool wait);
|
2017-12-11 17:41:05 +00:00
|
|
|
int ReadOutput(s16* data, int samples);
|
2020-11-11 16:54:27 +00:00
|
|
|
void TransferOutput();
|
2017-04-06 17:44:34 +00:00
|
|
|
|
|
|
|
u8 Read8(u32 addr);
|
|
|
|
u16 Read16(u32 addr);
|
|
|
|
u32 Read32(u32 addr);
|
|
|
|
void Write8(u32 addr, u8 val);
|
|
|
|
void Write16(u32 addr, u16 val);
|
|
|
|
void Write32(u32 addr, u32 val);
|
|
|
|
|
|
|
|
class Channel
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Channel(u32 num);
|
|
|
|
~Channel();
|
|
|
|
void Reset();
|
2018-10-18 00:45:38 +00:00
|
|
|
void DoSavestate(Savestate* file);
|
2017-04-06 17:44:34 +00:00
|
|
|
|
2017-04-06 20:38:46 +00:00
|
|
|
u32 Num;
|
|
|
|
|
2017-04-06 17:44:34 +00:00
|
|
|
u32 Cnt;
|
|
|
|
u32 SrcAddr;
|
|
|
|
u16 TimerReload;
|
|
|
|
u32 LoopPos;
|
|
|
|
u32 Length;
|
|
|
|
|
2017-04-06 23:06:10 +00:00
|
|
|
u8 Volume;
|
|
|
|
u8 VolumeShift;
|
|
|
|
u8 Pan;
|
|
|
|
|
2020-07-23 10:59:19 +00:00
|
|
|
bool KeyOn;
|
2017-04-06 20:38:46 +00:00
|
|
|
u32 Timer;
|
2017-04-06 23:06:10 +00:00
|
|
|
s32 Pos;
|
2017-04-06 20:38:46 +00:00
|
|
|
s16 CurSample;
|
2017-04-06 23:06:10 +00:00
|
|
|
u16 NoiseVal;
|
|
|
|
|
|
|
|
s32 ADPCMVal;
|
|
|
|
s32 ADPCMIndex;
|
|
|
|
s32 ADPCMValLoop;
|
|
|
|
s32 ADPCMIndexLoop;
|
|
|
|
u8 ADPCMCurByte;
|
2017-04-06 20:38:46 +00:00
|
|
|
|
2017-11-11 17:46:42 +00:00
|
|
|
u32 FIFO[8];
|
|
|
|
u32 FIFOReadPos;
|
|
|
|
u32 FIFOWritePos;
|
|
|
|
u32 FIFOReadOffset;
|
|
|
|
u32 FIFOLevel;
|
|
|
|
|
|
|
|
void FIFO_BufferData();
|
|
|
|
template<typename T> T FIFO_ReadData();
|
|
|
|
|
2017-04-06 17:44:34 +00:00
|
|
|
void SetCnt(u32 val)
|
|
|
|
{
|
2017-04-06 23:06:10 +00:00
|
|
|
u32 oldcnt = Cnt;
|
|
|
|
Cnt = val & 0xFF7F837F;
|
|
|
|
|
|
|
|
Volume = Cnt & 0x7F;
|
|
|
|
if (Volume == 127) Volume++;
|
|
|
|
|
|
|
|
const u8 volshift[4] = {4, 3, 2, 0};
|
|
|
|
VolumeShift = volshift[(Cnt >> 8) & 0x3];
|
|
|
|
|
|
|
|
Pan = (Cnt >> 16) & 0x7F;
|
|
|
|
if (Pan == 127) Pan++;
|
|
|
|
|
|
|
|
if ((val & (1<<31)) && !(oldcnt & (1<<31)))
|
2017-04-06 20:38:46 +00:00
|
|
|
{
|
2020-07-23 10:59:19 +00:00
|
|
|
KeyOn = true;
|
2017-04-06 20:38:46 +00:00
|
|
|
}
|
2017-04-06 17:44:34 +00:00
|
|
|
}
|
|
|
|
|
2017-04-06 23:06:10 +00:00
|
|
|
void SetSrcAddr(u32 val) { SrcAddr = val & 0x07FFFFFC; }
|
|
|
|
void SetTimerReload(u32 val) { TimerReload = val & 0xFFFF; }
|
2017-04-06 17:44:34 +00:00
|
|
|
void SetLoopPos(u32 val) { LoopPos = (val & 0xFFFF) << 2; }
|
|
|
|
void SetLength(u32 val) { Length = (val & 0x001FFFFF) << 2; }
|
2017-04-06 20:38:46 +00:00
|
|
|
|
|
|
|
void Start();
|
|
|
|
|
2017-04-06 23:06:10 +00:00
|
|
|
void NextSample_PCM8();
|
|
|
|
void NextSample_PCM16();
|
|
|
|
void NextSample_ADPCM();
|
2017-04-06 20:38:46 +00:00
|
|
|
void NextSample_PSG();
|
2017-04-06 23:06:10 +00:00
|
|
|
void NextSample_Noise();
|
2017-04-06 20:38:46 +00:00
|
|
|
|
2020-10-31 12:43:33 +00:00
|
|
|
template<u32 type> s32 Run();
|
2017-04-08 20:59:27 +00:00
|
|
|
|
2020-10-31 12:43:33 +00:00
|
|
|
s32 DoRun()
|
2017-04-08 20:59:27 +00:00
|
|
|
{
|
|
|
|
switch ((Cnt >> 29) & 0x3)
|
|
|
|
{
|
2020-10-31 12:43:33 +00:00
|
|
|
case 0: return Run<0>(); break;
|
|
|
|
case 1: return Run<1>(); break;
|
|
|
|
case 2: return Run<2>(); break;
|
2017-04-08 20:59:27 +00:00
|
|
|
case 3:
|
2020-10-31 12:43:33 +00:00
|
|
|
if (Num >= 14) return Run<4>();
|
|
|
|
else if (Num >= 8) return Run<3>();
|
|
|
|
default:
|
|
|
|
return 0;
|
2017-04-08 20:59:27 +00:00
|
|
|
}
|
|
|
|
}
|
2017-06-23 23:21:09 +00:00
|
|
|
|
2020-10-31 12:43:33 +00:00
|
|
|
void PanOutput(s32 in, s32& left, s32& right);
|
2020-06-01 18:36:30 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
u32 (*BusRead32)(u32 addr);
|
2017-04-08 20:59:27 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class CaptureUnit
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CaptureUnit(u32 num);
|
|
|
|
~CaptureUnit();
|
|
|
|
void Reset();
|
2018-10-18 00:45:38 +00:00
|
|
|
void DoSavestate(Savestate* file);
|
2017-04-08 20:59:27 +00:00
|
|
|
|
|
|
|
u32 Num;
|
|
|
|
|
|
|
|
u8 Cnt;
|
|
|
|
u32 DstAddr;
|
|
|
|
u16 TimerReload;
|
|
|
|
u32 Length;
|
|
|
|
|
|
|
|
u32 Timer;
|
|
|
|
s32 Pos;
|
|
|
|
|
2017-11-11 17:46:42 +00:00
|
|
|
u32 FIFO[4];
|
|
|
|
u32 FIFOReadPos;
|
|
|
|
u32 FIFOWritePos;
|
|
|
|
u32 FIFOWriteOffset;
|
|
|
|
u32 FIFOLevel;
|
|
|
|
|
|
|
|
void FIFO_FlushData();
|
|
|
|
template<typename T> void FIFO_WriteData(T val);
|
|
|
|
|
2017-04-08 20:59:27 +00:00
|
|
|
void SetCnt(u8 val)
|
|
|
|
{
|
|
|
|
if ((val & 0x80) && !(Cnt & 0x80))
|
|
|
|
Start();
|
|
|
|
|
|
|
|
val &= 0x8F;
|
|
|
|
if (!(val & 0x80)) val &= ~0x01;
|
|
|
|
Cnt = val;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetDstAddr(u32 val) { DstAddr = val & 0x07FFFFFC; }
|
|
|
|
void SetTimerReload(u32 val) { TimerReload = val & 0xFFFF; }
|
|
|
|
void SetLength(u32 val) { Length = val << 2; if (Length == 0) Length = 4; }
|
|
|
|
|
2017-11-11 17:46:42 +00:00
|
|
|
void Start()
|
|
|
|
{
|
|
|
|
Timer = TimerReload;
|
|
|
|
Pos = 0;
|
|
|
|
FIFOReadPos = 0;
|
|
|
|
FIFOWritePos = 0;
|
|
|
|
FIFOWriteOffset = 0;
|
|
|
|
FIFOLevel = 0;
|
|
|
|
}
|
2017-04-08 20:59:27 +00:00
|
|
|
|
|
|
|
void Run(s32 sample);
|
2020-06-01 18:36:30 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
void (*BusWrite32)(u32 addr, u32 val);
|
2017-04-06 17:44:34 +00:00
|
|
|
};
|
|
|
|
|
2017-04-04 13:32:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif // SPU_H
|