diff --git a/Source/Core/Core/HW/DVD/DVDInterface.cpp b/Source/Core/Core/HW/DVD/DVDInterface.cpp index 857c6edb91..8f00b955d2 100644 --- a/Source/Core/Core/HW/DVD/DVDInterface.cpp +++ b/Source/Core/Core/HW/DVD/DVDInterface.cpp @@ -606,7 +606,7 @@ bool UpdateRunningGameMetadata(std::optional title_id) return DVDThread::UpdateRunningGameMetadata(IOS::HLE::DIDevice::GetCurrentPartition(), title_id); } -void RegisterMMIO(MMIO::Mapping* mmio, u32 base) +void RegisterMMIO(MMIO::Mapping* mmio, u32 base, bool is_wii) { mmio->Register(base | DI_STATUS_REGISTER, MMIO::DirectRead(&s_DISR.Hex), MMIO::ComplexWrite([](u32, u32 val) { @@ -657,8 +657,18 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base) // DMA related registers. Mostly direct accesses (+ masking for writes to // handle things like address alignment) and complex write on the DMA // control register that will trigger the DMA. + + // The DMA address register masks away the top and bottom bits on GameCube, but only the top bits + // on Wii (which can be observed by reading back the register; this difference probably exists due + // to the existence of MEM2). The behavior of GameCube mode on a Wii (via MIOS/booting form the + // system menu) has not been tested yet. Note that RegisterMMIO does not get re-called when + // switching to GameCube mode; we handle this difference by applying the masking when using the + // GameCube's DI MMIO address (0x0C006000) but not applying it when using the Wii's DI MMIO + // address (0x0D006000), although we allow writes to both of these addresses if Dolphin was + // started in Wii mode. (Also, normally in Wii mode the DI MMIOs are only written by the + // IOS /dev/di module, but we *do* emulate /dev/di writing the DI MMIOs.) mmio->Register(base | DI_DMA_ADDRESS_REGISTER, MMIO::DirectRead(&s_DIMAR), - MMIO::DirectWrite(&s_DIMAR, ~0x1F)); + MMIO::DirectWrite(&s_DIMAR, is_wii ? ~0x1F : ~0xFC00001F)); mmio->Register(base | DI_DMA_LENGTH_REGISTER, MMIO::DirectRead(&s_DILENGTH), MMIO::DirectWrite(&s_DILENGTH, ~0x1F)); mmio->Register(base | DI_DMA_CONTROL_REGISTER, MMIO::DirectRead(&s_DICR.Hex), diff --git a/Source/Core/Core/HW/DVD/DVDInterface.h b/Source/Core/Core/HW/DVD/DVDInterface.h index 80dbbc5f1b..930da55b12 100644 --- a/Source/Core/Core/HW/DVD/DVDInterface.h +++ b/Source/Core/Core/HW/DVD/DVDInterface.h @@ -113,7 +113,7 @@ void ResetDrive(bool spinup); void Shutdown(); void DoState(PointerWrap& p); -void RegisterMMIO(MMIO::Mapping* mmio, u32 base); +void RegisterMMIO(MMIO::Mapping* mmio, u32 base, bool is_wii); void SetDisc(std::unique_ptr disc, std::optional> auto_disc_change_paths); diff --git a/Source/Core/Core/HW/Memmap.cpp b/Source/Core/Core/HW/Memmap.cpp index f61e974bf3..e9b78f6383 100644 --- a/Source/Core/Core/HW/Memmap.cpp +++ b/Source/Core/Core/HW/Memmap.cpp @@ -141,14 +141,14 @@ static void InitMMIO(bool is_wii) ProcessorInterface::RegisterMMIO(mmio_mapping.get(), 0x0C003000); MemoryInterface::RegisterMMIO(mmio_mapping.get(), 0x0C004000); DSP::RegisterMMIO(mmio_mapping.get(), 0x0C005000); - DVDInterface::RegisterMMIO(mmio_mapping.get(), 0x0C006000); + DVDInterface::RegisterMMIO(mmio_mapping.get(), 0x0C006000, false); SerialInterface::RegisterMMIO(mmio_mapping.get(), 0x0C006400); ExpansionInterface::RegisterMMIO(mmio_mapping.get(), 0x0C006800); AudioInterface::RegisterMMIO(mmio_mapping.get(), 0x0C006C00); if (is_wii) { IOS::RegisterMMIO(mmio_mapping.get(), 0x0D000000); - DVDInterface::RegisterMMIO(mmio_mapping.get(), 0x0D006000); + DVDInterface::RegisterMMIO(mmio_mapping.get(), 0x0D006000, true); SerialInterface::RegisterMMIO(mmio_mapping.get(), 0x0D006400); ExpansionInterface::RegisterMMIO(mmio_mapping.get(), 0x0D006800); AudioInterface::RegisterMMIO(mmio_mapping.get(), 0x0D006C00);