Merge pull request #9392 from smurf3tte/audio_wmask

DSP: Fix write masks on AUDIO_*/AR_* MMIO registers
This commit is contained in:
Pierre Bourdon 2021-01-05 15:08:06 +01:00 committed by GitHub
commit bd89523e63
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 43 additions and 14 deletions

View File

@ -231,30 +231,51 @@ void Shutdown()
void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
{
static constexpr u16 WMASK_NONE = 0x0000;
static constexpr u16 WMASK_AR_INFO = 0x007f;
static constexpr u16 WMASK_AR_REFRESH = 0x07ff;
static constexpr u16 WMASK_AR_HI_RESTRICT = 0x03ff;
static constexpr u16 WMASK_AR_CNT_DIR_BIT = 0x8000;
static constexpr u16 WMASK_AUDIO_HI_RESTRICT_GCN = 0x03ff;
static constexpr u16 WMASK_AUDIO_HI_RESTRICT_WII = 0x1fff;
static constexpr u16 WMASK_LO_ALIGN_32BIT = 0xffe0;
// Declare all the boilerplate direct MMIOs.
struct
{
u32 addr;
u16* ptr;
bool align_writes_on_32_bytes;
u16 wmask;
} directly_mapped_vars[] = {
{AR_INFO, &s_ARAM_Info.Hex},
{AR_MODE, &s_AR_MODE},
{AR_REFRESH, &s_AR_REFRESH},
{AR_DMA_MMADDR_H, MMIO::Utils::HighPart(&s_arDMA.MMAddr)},
{AR_DMA_MMADDR_L, MMIO::Utils::LowPart(&s_arDMA.MMAddr), true},
{AR_DMA_ARADDR_H, MMIO::Utils::HighPart(&s_arDMA.ARAddr)},
{AR_DMA_ARADDR_L, MMIO::Utils::LowPart(&s_arDMA.ARAddr), true},
{AR_DMA_CNT_H, MMIO::Utils::HighPart(&s_arDMA.Cnt.Hex)},
// This register is read-only
{AR_MODE, &s_AR_MODE, WMASK_NONE},
// For these registers, only some bits can be set
{AR_INFO, &s_ARAM_Info.Hex, WMASK_AR_INFO},
{AR_REFRESH, &s_AR_REFRESH, WMASK_AR_REFRESH},
// For AR_DMA_*_H registers, only bits 0x03ff can be set
// For AR_DMA_*_L registers, only bits 0xffe0 can be set
{AR_DMA_MMADDR_H, MMIO::Utils::HighPart(&s_arDMA.MMAddr), WMASK_AR_HI_RESTRICT},
{AR_DMA_MMADDR_L, MMIO::Utils::LowPart(&s_arDMA.MMAddr), WMASK_LO_ALIGN_32BIT},
{AR_DMA_ARADDR_H, MMIO::Utils::HighPart(&s_arDMA.ARAddr), WMASK_AR_HI_RESTRICT},
{AR_DMA_ARADDR_L, MMIO::Utils::LowPart(&s_arDMA.ARAddr), WMASK_LO_ALIGN_32BIT},
// For this register, the topmost (dir) bit can also be set
{AR_DMA_CNT_H, MMIO::Utils::HighPart(&s_arDMA.Cnt.Hex),
WMASK_AR_HI_RESTRICT | WMASK_AR_CNT_DIR_BIT},
// AR_DMA_CNT_L triggers DMA
{AUDIO_DMA_START_HI, MMIO::Utils::HighPart(&s_audioDMA.SourceAddress)},
{AUDIO_DMA_START_LO, MMIO::Utils::LowPart(&s_audioDMA.SourceAddress)},
// For AUDIO_DMA_START_HI, only bits 0x03ff can be set on GCN and 0x1fff on Wii
// For AUDIO_DMA_START_LO, only bits 0xffe0 can be set
// AUDIO_DMA_START_HI requires a complex write handler
{AUDIO_DMA_START_LO, MMIO::Utils::LowPart(&s_audioDMA.SourceAddress), WMASK_LO_ALIGN_32BIT},
};
for (auto& mapped_var : directly_mapped_vars)
{
u16 write_mask = mapped_var.align_writes_on_32_bytes ? 0xFFE0 : 0xFFFF;
mmio->Register(base | mapped_var.addr, MMIO::DirectRead<u16>(mapped_var.ptr),
MMIO::DirectWrite<u16>(mapped_var.ptr, write_mask));
mapped_var.wmask != WMASK_NONE ?
MMIO::DirectWrite<u16>(mapped_var.ptr, mapped_var.wmask) :
MMIO::InvalidWrite<u16>());
}
// DSP mail MMIOs call DSP emulator functions to get results or write data.
@ -340,10 +361,18 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
// ARAM MMIO controlling the DMA start.
mmio->Register(base | AR_DMA_CNT_L, MMIO::DirectRead<u16>(MMIO::Utils::LowPart(&s_arDMA.Cnt.Hex)),
MMIO::ComplexWrite<u16>([](u32, u16 val) {
s_arDMA.Cnt.Hex = (s_arDMA.Cnt.Hex & 0xFFFF0000) | (val & ~31);
s_arDMA.Cnt.Hex = (s_arDMA.Cnt.Hex & 0xFFFF0000) | (val & WMASK_LO_ALIGN_32BIT);
Do_ARAM_DMA();
}));
mmio->Register(base | AUDIO_DMA_START_HI,
MMIO::DirectRead<u16>(MMIO::Utils::HighPart(&s_audioDMA.SourceAddress)),
MMIO::ComplexWrite<u16>([](u32, u16 val) {
*MMIO::Utils::HighPart(&s_audioDMA.SourceAddress) =
val & (SConfig::GetInstance().bWii ? WMASK_AUDIO_HI_RESTRICT_WII :
WMASK_AUDIO_HI_RESTRICT_GCN);
}));
// Audio DMA MMIO controlling the DMA start.
mmio->Register(
base | AUDIO_DMA_CONTROL_LEN, MMIO::DirectRead<u16>(&s_audioDMA.AudioDMAControl.Hex),