pcsx2/plugins/spu2-x/src/ReadInput.cpp

178 lines
5.1 KiB
C++

/* SPU2-X, A plugin for Emulating the Sound Processing Unit of the Playstation 2
* Developed and maintained by the Pcsx2 Development Team.
*
* Original portions from SPU2ghz are (c) 2008 by David Quintana [gigaherz]
*
* SPU2-X is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SPU2-X 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with SPU2-X. If not, see <http://www.gnu.org/licenses/>.
*/
#include "Global.h"
#include "Dma.h"
#include "PS2E-spu2.h" // required for ENABLE_NEW_IOPDMA_SPU2 define
// Core 0 Input is "SPDIF mode" - Source audio is AC3 compressed.
// Core 1 Input is "CDDA mode" - Source audio data is 32 bits.
// PS2 note: Very! few PS2 games use this mode. Some PSX games used it, however no
// *known* PS2 game does since it was likely only available if the game was recorded to CD
// media (ie, not available in DVD mode, which almost all PS2 games use). Plus PS2 games
// generally prefer to use ADPCM streaming audio since they need as much storage space as
// possible for FMVs and high-def textures.
//
StereoOut32 V_Core::ReadInput_HiFi()
{
InputPosRead &= ~1;
//
//#ifdef PCM24_S1_INTERLEAVE
// StereoOut32 retval(
// *((s32*)(ADMATempBuffer+(InputPosRead<<1))),
// *((s32*)(ADMATempBuffer+(InputPosRead<<1)+2))
// );
//#else
// StereoOut32 retval(
// (s32&)(ADMATempBuffer[InputPosRead]),
// (s32&)(ADMATempBuffer[InputPosRead+0x200])
// );
//#endif
StereoOut32 retval(
(s32&)(*GetMemPtr(0x2000 + (Index<<10) + InputPosRead)),
(s32&)(*GetMemPtr(0x2200 + (Index<<10) + InputPosRead))
);
if( Index == 1 )
{
// CDDA Mode:
// give 30 bit data (SndOut downsamples the rest of the way)
// HACKFIX: 28 bits seems better according to rama. I should take some time and do some
// bitcounting on this one. --air
retval.Left >>= 4;
retval.Right >>= 4;
}
InputPosRead += 2;
// Why does CDDA mode check for InputPos == 0x100? In the old code, SPDIF mode did not but CDDA did.
// One of these seems wrong, they should be the same. Since standard ADMA checks too I'm assuming that as default. -- air
if( (InputPosRead==0x100) || (InputPosRead>=0x200) )
{
#ifdef ENABLE_NEW_IOPDMA_SPU2
// WARNING: Assumes this to be in the same thread as the dmas
AutoDmaFree += 0x200;
#else
AdmaInProgress = 0;
if(InputDataLeft >= 0x200)
{
#ifdef PCM24_S1_INTERLEAVE
AutoDMAReadBuffer(1);
#else
AutoDMAReadBuffer(0);
#endif
AdmaInProgress = 1;
TSA = (Index<<10) + InputPosRead;
if (InputDataLeft < 0x200)
{
FileLog("[%10d] %s AutoDMA%c block end.\n", (Index==1) ? "CDDA" : "SPDIF", Cycles, GetDmaIndexChar());
if( IsDevBuild )
{
if(InputDataLeft > 0)
{
if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n");
}
}
InputDataLeft = 0;
// Hack, kinda. We call the interrupt early here, since PCSX2 doesn't like them delayed.
//DMAICounter = 1;
if(Index == 0) { if(dma4callback) dma4callback(); }
else { if(dma7callback) dma7callback(); }
}
}
#endif
InputPosRead &= 0x1ff;
}
return retval;
}
StereoOut32 V_Core::ReadInput()
{
StereoOut32 retval;
if( (Index!=1) || ((PlayMode&2)==0) )
{
for (int i=0; i<2; i++)
if (Cores[i].IRQEnable && 0x2000 + (Index << 10) + InputPosRead == (Cores[i].IRQA & 0xfffffdff))
SetIrqCall(i);
//retval = StereoOut32(
// (s32)ADMATempBuffer[InputPosRead],
// (s32)ADMATempBuffer[InputPosRead+0x200]
//);
retval = StereoOut32(
(s32)(*GetMemPtr(0x2000 + (Index<<10) + InputPosRead)),
(s32)(*GetMemPtr(0x2200 + (Index<<10) + InputPosRead))
);
}
#ifdef PCSX2_DEVBUILD
DebugCores[Index].admaWaveformL[InputPosRead%0x100]=retval.Left;
DebugCores[Index].admaWaveformR[InputPosRead%0x100]=retval.Right;
#endif
InputPosRead++;
if (AutoDMACtrl & (Index + 1) && (InputPosRead == 0x100 || InputPosRead == 0x200))
{
#ifdef ENABLE_NEW_IOPDMA_SPU2
// WARNING: Assumes this to be in the same thread as the dmas
AutoDmaFree += 0x200;
#else
AdmaInProgress = 0;
if(InputDataLeft >= 0x200)
{
//u8 k=InputDataLeft>=InputDataProgress;
AutoDMAReadBuffer(0);
AdmaInProgress = 1;
TSA = (Index<<10) + InputPosRead;
if (InputDataLeft < 0x200)
{
AutoDMACtrl |= ~3;
if( IsDevBuild )
{
FileLog("[%10d] AutoDMA%c block end.\n",Cycles, GetDmaIndexChar());
if(InputDataLeft>0)
{
if(MsgAutoDMA()) ConLog("WARNING: adma buffer didn't finish with a whole block!!\n");
}
}
InputDataLeft = 0;
// Hack, kinda. We call the interrupt early here, since PCSX2 doesn't like them delayed.
//DMAICounter = 1;
if(Index == 0) { if(dma4callback) dma4callback(); }
else { if(dma7callback) dma7callback(); }
}
}
#endif
}
InputPosRead &= 0x1ff;
return retval;
}