Core/HW/MMIO: Pass System through Read() and Write().

This commit is contained in:
Admiral H. Curtiss 2024-01-12 06:42:51 +01:00
parent 6725c25600
commit 42d61cfc4c
No known key found for this signature in database
GPG Key ID: F051B4C4044F33FB
5 changed files with 120 additions and 90 deletions

View File

@ -15,6 +15,7 @@
#include "Core/HW/EXI/EXI_Device.h" #include "Core/HW/EXI/EXI_Device.h"
#include "Core/HW/MMIO.h" #include "Core/HW/MMIO.h"
#include "Core/Movie.h" #include "Core/Movie.h"
#include "Core/System.h"
namespace ExpansionInterface namespace ExpansionInterface
{ {

View File

@ -15,7 +15,11 @@
#include "Core/ConfigManager.h" #include "Core/ConfigManager.h"
#include "Core/HW/GPFifo.h" #include "Core/HW/GPFifo.h"
#include "Core/HW/MMIOHandlers.h" #include "Core/HW/MMIOHandlers.h"
#include "Core/System.h"
namespace Core
{
class System;
}
namespace MMIO namespace MMIO
{ {
@ -131,15 +135,15 @@ public:
// called in interpreter mode, from Dolphin's own code, or from JIT'd code // called in interpreter mode, from Dolphin's own code, or from JIT'd code
// where the access address could not be predicted. // where the access address could not be predicted.
template <typename Unit> template <typename Unit>
Unit Read(u32 addr) Unit Read(Core::System& system, u32 addr)
{ {
return GetHandlerForRead<Unit>(addr).Read(Core::System::GetInstance(), addr); return GetHandlerForRead<Unit>(addr).Read(system, addr);
} }
template <typename Unit> template <typename Unit>
void Write(u32 addr, Unit val) void Write(Core::System& system, u32 addr, Unit val)
{ {
GetHandlerForWrite<Unit>(addr).Write(Core::System::GetInstance(), addr, val); GetHandlerForWrite<Unit>(addr).Write(system, addr, val);
} }
// Handlers access interface. // Handlers access interface.
@ -214,14 +218,14 @@ private:
// Dummy 64 bits variants of these functions. While 64 bits MMIO access is // Dummy 64 bits variants of these functions. While 64 bits MMIO access is
// not supported, we need these in order to make the code compile. // not supported, we need these in order to make the code compile.
template <> template <>
inline u64 Mapping::Read<u64>(u32 addr) inline u64 Mapping::Read<u64>(Core::System& system, u32 addr)
{ {
DEBUG_ASSERT(false); DEBUG_ASSERT(false);
return 0; return 0;
} }
template <> template <>
inline void Mapping::Write(u32 addr, u64 val) inline void Mapping::Write(Core::System& system, u32 addr, u64 val)
{ {
DEBUG_ASSERT(false); DEBUG_ASSERT(false);
} }

View File

@ -162,14 +162,14 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
{ {
case DIIoctl::DVDLowInquiry: case DIIoctl::DVDLowInquiry:
INFO_LOG_FMT(IOS_DI, "DVDLowInquiry"); INFO_LOG_FMT(IOS_DI, "DVDLowInquiry");
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0x12000000); mmio->Write<u32>(system, ADDRESS_DICMDBUF0, 0x12000000);
mmio->Write<u32>(ADDRESS_DICMDBUF1, 0); mmio->Write<u32>(system, ADDRESS_DICMDBUF1, 0);
return StartDMATransfer(0x20, request); return StartDMATransfer(0x20, request);
case DIIoctl::DVDLowReadDiskID: case DIIoctl::DVDLowReadDiskID:
INFO_LOG_FMT(IOS_DI, "DVDLowReadDiskID"); INFO_LOG_FMT(IOS_DI, "DVDLowReadDiskID");
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xA8000040); mmio->Write<u32>(system, ADDRESS_DICMDBUF0, 0xA8000040);
mmio->Write<u32>(ADDRESS_DICMDBUF1, 0); mmio->Write<u32>(system, ADDRESS_DICMDBUF1, 0);
mmio->Write<u32>(ADDRESS_DICMDBUF2, 0x20); mmio->Write<u32>(system, ADDRESS_DICMDBUF2, 0x20);
return StartDMATransfer(0x20, request); return StartDMATransfer(0x20, request);
// TODO: Include an additional read that happens on Wii discs, or at least // TODO: Include an additional read that happens on Wii discs, or at least
// emulate its side effect of disabling DTK configuration // emulate its side effect of disabling DTK configuration
@ -211,7 +211,7 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
return DIResult::CoverClosed; return DIResult::CoverClosed;
case DIIoctl::DVDLowGetCoverRegister: case DIIoctl::DVDLowGetCoverRegister:
{ {
const u32 dicvr = mmio->Read<u32>(ADDRESS_DICVR); const u32 dicvr = mmio->Read<u32>(system, ADDRESS_DICVR);
DEBUG_LOG_FMT(IOS_DI, "DVDLowGetCoverRegister {:#010x}", dicvr); DEBUG_LOG_FMT(IOS_DI, "DVDLowGetCoverRegister {:#010x}", dicvr);
return WriteIfFits(request, dicvr); return WriteIfFits(request, dicvr);
} }
@ -226,27 +226,27 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
{ {
const u8 position = memory.Read_U8(request.buffer_in + 7); const u8 position = memory.Read_U8(request.buffer_in + 7);
INFO_LOG_FMT(IOS_DI, "DVDLowReadDvdPhysical: position {:#04x}", position); INFO_LOG_FMT(IOS_DI, "DVDLowReadDvdPhysical: position {:#04x}", position);
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xAD000000 | (position << 8)); mmio->Write<u32>(system, ADDRESS_DICMDBUF0, 0xAD000000 | (position << 8));
mmio->Write<u32>(ADDRESS_DICMDBUF1, 0); mmio->Write<u32>(system, ADDRESS_DICMDBUF1, 0);
mmio->Write<u32>(ADDRESS_DICMDBUF2, 0); mmio->Write<u32>(system, ADDRESS_DICMDBUF2, 0);
return StartDMATransfer(0x800, request); return StartDMATransfer(0x800, request);
} }
case DIIoctl::DVDLowReadDvdCopyright: case DIIoctl::DVDLowReadDvdCopyright:
{ {
const u8 position = memory.Read_U8(request.buffer_in + 7); const u8 position = memory.Read_U8(request.buffer_in + 7);
INFO_LOG_FMT(IOS_DI, "DVDLowReadDvdCopyright: position {:#04x}", position); INFO_LOG_FMT(IOS_DI, "DVDLowReadDvdCopyright: position {:#04x}", position);
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xAD010000 | (position << 8)); mmio->Write<u32>(system, ADDRESS_DICMDBUF0, 0xAD010000 | (position << 8));
mmio->Write<u32>(ADDRESS_DICMDBUF1, 0); mmio->Write<u32>(system, ADDRESS_DICMDBUF1, 0);
mmio->Write<u32>(ADDRESS_DICMDBUF2, 0); mmio->Write<u32>(system, ADDRESS_DICMDBUF2, 0);
return StartImmediateTransfer(request); return StartImmediateTransfer(request);
} }
case DIIoctl::DVDLowReadDvdDiscKey: case DIIoctl::DVDLowReadDvdDiscKey:
{ {
const u8 position = memory.Read_U8(request.buffer_in + 7); const u8 position = memory.Read_U8(request.buffer_in + 7);
INFO_LOG_FMT(IOS_DI, "DVDLowReadDvdDiscKey: position {:#04x}", position); INFO_LOG_FMT(IOS_DI, "DVDLowReadDvdDiscKey: position {:#04x}", position);
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xAD020000 | (position << 8)); mmio->Write<u32>(system, ADDRESS_DICMDBUF0, 0xAD020000 | (position << 8));
mmio->Write<u32>(ADDRESS_DICMDBUF1, 0); mmio->Write<u32>(system, ADDRESS_DICMDBUF1, 0);
mmio->Write<u32>(ADDRESS_DICMDBUF2, 0); mmio->Write<u32>(system, ADDRESS_DICMDBUF2, 0);
return StartDMATransfer(0x800, request); return StartDMATransfer(0x800, request);
} }
case DIIoctl::DVDLowGetLength: case DIIoctl::DVDLowGetLength:
@ -254,7 +254,7 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
return WriteIfFits(request, m_last_length); return WriteIfFits(request, m_last_length);
case DIIoctl::DVDLowGetImmBuf: case DIIoctl::DVDLowGetImmBuf:
{ {
const u32 diimmbuf = mmio->Read<u32>(ADDRESS_DIIMMBUF); const u32 diimmbuf = mmio->Read<u32>(system, ADDRESS_DIIMMBUF);
INFO_LOG_FMT(IOS_DI, "DVDLowGetImmBuf {:#010x}", diimmbuf); INFO_LOG_FMT(IOS_DI, "DVDLowGetImmBuf {:#010x}", diimmbuf);
return WriteIfFits(request, diimmbuf); return WriteIfFits(request, diimmbuf);
} }
@ -289,27 +289,30 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
const bool spinup = memory.Read_U32(request.buffer_in + 4); const bool spinup = memory.Read_U32(request.buffer_in + 4);
// The GPIO *disables* spinning up the drive. Normally handled via syscall 0x4e. // The GPIO *disables* spinning up the drive. Normally handled via syscall 0x4e.
const u32 old_gpio = mmio->Read<u32>(ADDRESS_HW_GPIO_OUT); const u32 old_gpio = mmio->Read<u32>(system, ADDRESS_HW_GPIO_OUT);
if (spinup) if (spinup)
mmio->Write<u32>(ADDRESS_HW_GPIO_OUT, old_gpio & ~static_cast<u32>(GPIO::DI_SPIN)); mmio->Write<u32>(system, ADDRESS_HW_GPIO_OUT, old_gpio & ~static_cast<u32>(GPIO::DI_SPIN));
else else
mmio->Write<u32>(ADDRESS_HW_GPIO_OUT, old_gpio | static_cast<u32>(GPIO::DI_SPIN)); mmio->Write<u32>(system, ADDRESS_HW_GPIO_OUT, old_gpio | static_cast<u32>(GPIO::DI_SPIN));
// Syscall 0x46 check_di_reset // Syscall 0x46 check_di_reset
const bool was_resetting = (mmio->Read<u32>(ADDRESS_HW_RESETS) & (1 << 10)) == 0; const bool was_resetting = (mmio->Read<u32>(system, ADDRESS_HW_RESETS) & (1 << 10)) == 0;
if (was_resetting) if (was_resetting)
{ {
// This route will not generally be taken in Dolphin but is included for completeness // This route will not generally be taken in Dolphin but is included for completeness
// Syscall 0x45 deassert_di_reset // Syscall 0x45 deassert_di_reset
mmio->Write<u32>(ADDRESS_HW_RESETS, mmio->Read<u32>(ADDRESS_HW_RESETS) | (1 << 10)); mmio->Write<u32>(system, ADDRESS_HW_RESETS,
mmio->Read<u32>(system, ADDRESS_HW_RESETS) | (1 << 10));
} }
else else
{ {
// Syscall 0x44 assert_di_reset // Syscall 0x44 assert_di_reset
mmio->Write<u32>(ADDRESS_HW_RESETS, mmio->Read<u32>(ADDRESS_HW_RESETS) & ~(1 << 10)); mmio->Write<u32>(system, ADDRESS_HW_RESETS,
mmio->Read<u32>(system, ADDRESS_HW_RESETS) & ~(1 << 10));
// Normally IOS sleeps for 12 microseconds here, but we can't easily emulate that // Normally IOS sleeps for 12 microseconds here, but we can't easily emulate that
// Syscall 0x45 deassert_di_reset // Syscall 0x45 deassert_di_reset
mmio->Write<u32>(ADDRESS_HW_RESETS, mmio->Read<u32>(ADDRESS_HW_RESETS) | (1 << 10)); mmio->Write<u32>(system, ADDRESS_HW_RESETS,
mmio->Read<u32>(system, ADDRESS_HW_RESETS) | (1 << 10));
} }
ResetDIRegisters(); ResetDIRegisters();
return DIResult::Success; return DIResult::Success;
@ -342,14 +345,14 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
if (range.start <= position && position <= range.end && range.start <= end && if (range.start <= position && position <= range.end && range.start <= end &&
end <= range.end) end <= range.end)
{ {
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xA8000000); mmio->Write<u32>(system, ADDRESS_DICMDBUF0, 0xA8000000);
mmio->Write<u32>(ADDRESS_DICMDBUF1, position); mmio->Write<u32>(system, ADDRESS_DICMDBUF1, position);
mmio->Write<u32>(ADDRESS_DICMDBUF2, length); mmio->Write<u32>(system, ADDRESS_DICMDBUF2, length);
if (range.is_error_001_range && Config::Get(Config::SESSION_SHOULD_FAKE_ERROR_001)) if (range.is_error_001_range && Config::Get(Config::SESSION_SHOULD_FAKE_ERROR_001))
{ {
mmio->Write<u32>(ADDRESS_DIMAR, request.buffer_out); mmio->Write<u32>(system, ADDRESS_DIMAR, request.buffer_out);
m_last_length = length; m_last_length = length;
mmio->Write<u32>(ADDRESS_DILENGTH, length); mmio->Write<u32>(system, ADDRESS_DILENGTH, length);
system.GetDVDInterface().ForceOutOfBoundsRead(DVD::ReplyType::IOS); system.GetDVDInterface().ForceOutOfBoundsRead(DVD::ReplyType::IOS);
return {}; return {};
} }
@ -389,13 +392,13 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
return DIResult::SecurityError; return DIResult::SecurityError;
case DIIoctl::DVDLowGetStatusRegister: case DIIoctl::DVDLowGetStatusRegister:
{ {
const u32 disr = mmio->Read<u32>(ADDRESS_DISR); const u32 disr = mmio->Read<u32>(system, ADDRESS_DISR);
INFO_LOG_FMT(IOS_DI, "DVDLowGetStatusRegister: {:#010x}", disr); INFO_LOG_FMT(IOS_DI, "DVDLowGetStatusRegister: {:#010x}", disr);
return WriteIfFits(request, disr); return WriteIfFits(request, disr);
} }
case DIIoctl::DVDLowGetControlRegister: case DIIoctl::DVDLowGetControlRegister:
{ {
const u32 dicr = mmio->Read<u32>(ADDRESS_DICR); const u32 dicr = mmio->Read<u32>(system, ADDRESS_DICR);
INFO_LOG_FMT(IOS_DI, "DVDLowGetControlRegister: {:#010x}", dicr); INFO_LOG_FMT(IOS_DI, "DVDLowGetControlRegister: {:#010x}", dicr);
return WriteIfFits(request, dicr); return WriteIfFits(request, dicr);
} }
@ -404,9 +407,9 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
const u8 param1 = memory.Read_U8(request.buffer_in + 7); const u8 param1 = memory.Read_U8(request.buffer_in + 7);
const u32 param2 = memory.Read_U32(request.buffer_in + 8); const u32 param2 = memory.Read_U32(request.buffer_in + 8);
INFO_LOG_FMT(IOS_DI, "DVDLowReportKey: param1 {:#04x}, param2 {:#08x}", param1, param2); INFO_LOG_FMT(IOS_DI, "DVDLowReportKey: param1 {:#04x}, param2 {:#08x}", param1, param2);
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xA4000000 | (param1 << 16)); mmio->Write<u32>(system, ADDRESS_DICMDBUF0, 0xA4000000 | (param1 << 16));
mmio->Write<u32>(ADDRESS_DICMDBUF1, param2 & 0xFFFFFF); mmio->Write<u32>(system, ADDRESS_DICMDBUF1, param2 & 0xFFFFFF);
mmio->Write<u32>(ADDRESS_DICMDBUF2, 0); mmio->Write<u32>(system, ADDRESS_DICMDBUF2, 0);
return StartDMATransfer(0x20, request); return StartDMATransfer(0x20, request);
} }
case DIIoctl::DVDLowSeek: case DIIoctl::DVDLowSeek:
@ -414,8 +417,8 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
const u32 position = memory.Read_U32(request.buffer_in + 4); // 32-bit offset const u32 position = memory.Read_U32(request.buffer_in + 4); // 32-bit offset
INFO_LOG_FMT(IOS_DI, "DVDLowSeek: position {:#010x}, translated to {:#010x}", position, INFO_LOG_FMT(IOS_DI, "DVDLowSeek: position {:#010x}, translated to {:#010x}", position,
position); // TODO: do partition translation! position); // TODO: do partition translation!
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xAB000000); mmio->Write<u32>(system, ADDRESS_DICMDBUF0, 0xAB000000);
mmio->Write<u32>(ADDRESS_DICMDBUF1, position); mmio->Write<u32>(system, ADDRESS_DICMDBUF1, position);
return StartImmediateTransfer(request, false); return StartImmediateTransfer(request, false);
} }
case DIIoctl::DVDLowReadDvd: case DIIoctl::DVDLowReadDvd:
@ -426,9 +429,10 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
const u32 position = memory.Read_U32(request.buffer_in + 16); const u32 position = memory.Read_U32(request.buffer_in + 16);
INFO_LOG_FMT(IOS_DI, "DVDLowReadDvd({}, {}): position {:#08x}, length {:#08x}", flag1, flag2, INFO_LOG_FMT(IOS_DI, "DVDLowReadDvd({}, {}): position {:#08x}, length {:#08x}", flag1, flag2,
position, length); position, length);
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xD0000000 | ((flag1 & 1) << 7) | ((flag2 & 1) << 6)); mmio->Write<u32>(system, ADDRESS_DICMDBUF0,
mmio->Write<u32>(ADDRESS_DICMDBUF1, position & 0xFFFFFF); 0xD0000000 | ((flag1 & 1) << 7) | ((flag2 & 1) << 6));
mmio->Write<u32>(ADDRESS_DICMDBUF2, length & 0xFFFFFF); mmio->Write<u32>(system, ADDRESS_DICMDBUF1, position & 0xFFFFFF);
mmio->Write<u32>(system, ADDRESS_DICMDBUF2, length & 0xFFFFFF);
return StartDMATransfer(0x800 * length, request); return StartDMATransfer(0x800 * length, request);
} }
case DIIoctl::DVDLowReadDvdConfig: case DIIoctl::DVDLowReadDvdConfig:
@ -437,41 +441,41 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
const u8 param2 = memory.Read_U8(request.buffer_in + 11); const u8 param2 = memory.Read_U8(request.buffer_in + 11);
const u32 position = memory.Read_U32(request.buffer_in + 12); const u32 position = memory.Read_U32(request.buffer_in + 12);
INFO_LOG_FMT(IOS_DI, "DVDLowReadDvdConfig({}, {}): position {:#08x}", flag1, param2, position); INFO_LOG_FMT(IOS_DI, "DVDLowReadDvdConfig({}, {}): position {:#08x}", flag1, param2, position);
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xD1000000 | ((flag1 & 1) << 16) | param2); mmio->Write<u32>(system, ADDRESS_DICMDBUF0, 0xD1000000 | ((flag1 & 1) << 16) | param2);
mmio->Write<u32>(ADDRESS_DICMDBUF1, position & 0xFFFFFF); mmio->Write<u32>(system, ADDRESS_DICMDBUF1, position & 0xFFFFFF);
mmio->Write<u32>(ADDRESS_DICMDBUF2, 0); mmio->Write<u32>(system, ADDRESS_DICMDBUF2, 0);
return StartImmediateTransfer(request); return StartImmediateTransfer(request);
} }
case DIIoctl::DVDLowStopLaser: case DIIoctl::DVDLowStopLaser:
INFO_LOG_FMT(IOS_DI, "DVDLowStopLaser"); INFO_LOG_FMT(IOS_DI, "DVDLowStopLaser");
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xD2000000); mmio->Write<u32>(system, ADDRESS_DICMDBUF0, 0xD2000000);
return StartImmediateTransfer(request); return StartImmediateTransfer(request);
case DIIoctl::DVDLowOffset: case DIIoctl::DVDLowOffset:
{ {
const u8 flag = memory.Read_U8(request.buffer_in + 7); const u8 flag = memory.Read_U8(request.buffer_in + 7);
const u32 offset = memory.Read_U32(request.buffer_in + 8); const u32 offset = memory.Read_U32(request.buffer_in + 8);
INFO_LOG_FMT(IOS_DI, "DVDLowOffset({}): offset {:#010x}", flag, offset); INFO_LOG_FMT(IOS_DI, "DVDLowOffset({}): offset {:#010x}", flag, offset);
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xD9000000 | ((flag & 1) << 16)); mmio->Write<u32>(system, ADDRESS_DICMDBUF0, 0xD9000000 | ((flag & 1) << 16));
mmio->Write<u32>(ADDRESS_DICMDBUF1, offset); mmio->Write<u32>(system, ADDRESS_DICMDBUF1, offset);
return StartImmediateTransfer(request); return StartImmediateTransfer(request);
} }
case DIIoctl::DVDLowReadDiskBca: case DIIoctl::DVDLowReadDiskBca:
INFO_LOG_FMT(IOS_DI, "DVDLowReadDiskBca"); INFO_LOG_FMT(IOS_DI, "DVDLowReadDiskBca");
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xDA000000); mmio->Write<u32>(system, ADDRESS_DICMDBUF0, 0xDA000000);
return StartDMATransfer(0x40, request); return StartDMATransfer(0x40, request);
case DIIoctl::DVDLowRequestDiscStatus: case DIIoctl::DVDLowRequestDiscStatus:
INFO_LOG_FMT(IOS_DI, "DVDLowRequestDiscStatus"); INFO_LOG_FMT(IOS_DI, "DVDLowRequestDiscStatus");
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xDB000000); mmio->Write<u32>(system, ADDRESS_DICMDBUF0, 0xDB000000);
return StartImmediateTransfer(request); return StartImmediateTransfer(request);
case DIIoctl::DVDLowRequestRetryNumber: case DIIoctl::DVDLowRequestRetryNumber:
INFO_LOG_FMT(IOS_DI, "DVDLowRequestRetryNumber"); INFO_LOG_FMT(IOS_DI, "DVDLowRequestRetryNumber");
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xDC000000); mmio->Write<u32>(system, ADDRESS_DICMDBUF0, 0xDC000000);
return StartImmediateTransfer(request); return StartImmediateTransfer(request);
case DIIoctl::DVDLowSetMaximumRotation: case DIIoctl::DVDLowSetMaximumRotation:
{ {
const u8 speed = memory.Read_U8(request.buffer_in + 7); const u8 speed = memory.Read_U8(request.buffer_in + 7);
INFO_LOG_FMT(IOS_DI, "DVDLowSetMaximumRotation: speed {}", speed); INFO_LOG_FMT(IOS_DI, "DVDLowSetMaximumRotation: speed {}", speed);
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xDD000000 | ((speed & 3) << 16)); mmio->Write<u32>(system, ADDRESS_DICMDBUF0, 0xDD000000 | ((speed & 3) << 16));
return StartImmediateTransfer(request, false); return StartImmediateTransfer(request, false);
} }
case DIIoctl::DVDLowSerMeasControl: case DIIoctl::DVDLowSerMeasControl:
@ -479,12 +483,13 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
const u8 flag1 = memory.Read_U8(request.buffer_in + 7); const u8 flag1 = memory.Read_U8(request.buffer_in + 7);
const u8 flag2 = memory.Read_U8(request.buffer_in + 11); const u8 flag2 = memory.Read_U8(request.buffer_in + 11);
INFO_LOG_FMT(IOS_DI, "DVDLowSerMeasControl({}, {})", flag1, flag2); INFO_LOG_FMT(IOS_DI, "DVDLowSerMeasControl({}, {})", flag1, flag2);
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xDF000000 | ((flag1 & 1) << 17) | ((flag2 & 1) << 16)); mmio->Write<u32>(system, ADDRESS_DICMDBUF0,
0xDF000000 | ((flag1 & 1) << 17) | ((flag2 & 1) << 16));
return StartDMATransfer(0x20, request); return StartDMATransfer(0x20, request);
} }
case DIIoctl::DVDLowRequestError: case DIIoctl::DVDLowRequestError:
INFO_LOG_FMT(IOS_DI, "DVDLowRequestError"); INFO_LOG_FMT(IOS_DI, "DVDLowRequestError");
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xE0000000); mmio->Write<u32>(system, ADDRESS_DICMDBUF0, 0xE0000000);
return StartImmediateTransfer(request); return StartImmediateTransfer(request);
case DIIoctl::DVDLowAudioStream: case DIIoctl::DVDLowAudioStream:
{ {
@ -493,17 +498,17 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
const u32 position = memory.Read_U32(request.buffer_in + 12); const u32 position = memory.Read_U32(request.buffer_in + 12);
INFO_LOG_FMT(IOS_DI, "DVDLowAudioStream({}): offset {:#010x} (byte {:#011x}), length {:#x}", INFO_LOG_FMT(IOS_DI, "DVDLowAudioStream({}): offset {:#010x} (byte {:#011x}), length {:#x}",
mode, position, static_cast<u64>(position) << 2, length); mode, position, static_cast<u64>(position) << 2, length);
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xE1000000 | ((mode & 3) << 16)); mmio->Write<u32>(system, ADDRESS_DICMDBUF0, 0xE1000000 | ((mode & 3) << 16));
mmio->Write<u32>(ADDRESS_DICMDBUF1, position); mmio->Write<u32>(system, ADDRESS_DICMDBUF1, position);
mmio->Write<u32>(ADDRESS_DICMDBUF2, length); mmio->Write<u32>(system, ADDRESS_DICMDBUF2, length);
return StartImmediateTransfer(request, false); return StartImmediateTransfer(request, false);
} }
case DIIoctl::DVDLowRequestAudioStatus: case DIIoctl::DVDLowRequestAudioStatus:
{ {
const u8 mode = memory.Read_U8(request.buffer_in + 7); const u8 mode = memory.Read_U8(request.buffer_in + 7);
INFO_LOG_FMT(IOS_DI, "DVDLowRequestAudioStatus({})", mode); INFO_LOG_FMT(IOS_DI, "DVDLowRequestAudioStatus({})", mode);
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xE2000000 | ((mode & 3) << 16)); mmio->Write<u32>(system, ADDRESS_DICMDBUF0, 0xE2000000 | ((mode & 3) << 16));
mmio->Write<u32>(ADDRESS_DICMDBUF1, 0); mmio->Write<u32>(system, ADDRESS_DICMDBUF1, 0);
// Note that this command does not copy the value written to DIIMMBUF, which makes it rather // Note that this command does not copy the value written to DIIMMBUF, which makes it rather
// useless (to actually use it, DVDLowGetImmBuf would need to be used afterwards) // useless (to actually use it, DVDLowGetImmBuf would need to be used afterwards)
return StartImmediateTransfer(request, false); return StartImmediateTransfer(request, false);
@ -513,8 +518,9 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
const u8 eject = memory.Read_U8(request.buffer_in + 7); const u8 eject = memory.Read_U8(request.buffer_in + 7);
const u8 kill = memory.Read_U8(request.buffer_in + 11); const u8 kill = memory.Read_U8(request.buffer_in + 11);
INFO_LOG_FMT(IOS_DI, "DVDLowStopMotor({}, {})", eject, kill); INFO_LOG_FMT(IOS_DI, "DVDLowStopMotor({}, {})", eject, kill);
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xE3000000 | ((eject & 1) << 17) | ((kill & 1) << 20)); mmio->Write<u32>(system, ADDRESS_DICMDBUF0,
mmio->Write<u32>(ADDRESS_DICMDBUF1, 0); 0xE3000000 | ((eject & 1) << 17) | ((kill & 1) << 20));
mmio->Write<u32>(system, ADDRESS_DICMDBUF1, 0);
return StartImmediateTransfer(request); return StartImmediateTransfer(request);
} }
case DIIoctl::DVDLowAudioBufferConfig: case DIIoctl::DVDLowAudioBufferConfig:
@ -523,8 +529,9 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
const u8 buffer_size = memory.Read_U8(request.buffer_in + 11); const u8 buffer_size = memory.Read_U8(request.buffer_in + 11);
INFO_LOG_FMT(IOS_DI, "DVDLowAudioBufferConfig: {}, buffer size {}", INFO_LOG_FMT(IOS_DI, "DVDLowAudioBufferConfig: {}, buffer size {}",
enable ? "enabled" : "disabled", buffer_size); enable ? "enabled" : "disabled", buffer_size);
mmio->Write<u32>(ADDRESS_DICMDBUF0, 0xE4000000 | ((enable & 1) << 16) | (buffer_size & 0xf)); mmio->Write<u32>(system, ADDRESS_DICMDBUF0,
mmio->Write<u32>(ADDRESS_DICMDBUF1, 0); 0xE4000000 | ((enable & 1) << 16) | (buffer_size & 0xf));
mmio->Write<u32>(system, ADDRESS_DICMDBUF1, 0);
// On the other hand, this command *does* copy DIIMMBUF, but the actual code in the drive never // On the other hand, this command *does* copy DIIMMBUF, but the actual code in the drive never
// writes anything to it, so it just copies over a stale value (e.g. from DVDLowRequestError). // writes anything to it, so it just copies over a stale value (e.g. from DVDLowRequestError).
return StartImmediateTransfer(request); return StartImmediateTransfer(request);
@ -565,9 +572,9 @@ std::optional<DIDevice::DIResult> DIDevice::StartDMATransfer(u32 command_length,
auto& system = GetSystem(); auto& system = GetSystem();
auto* mmio = system.GetMemory().GetMMIOMapping(); auto* mmio = system.GetMemory().GetMMIOMapping();
mmio->Write<u32>(ADDRESS_DIMAR, request.buffer_out); mmio->Write<u32>(system, ADDRESS_DIMAR, request.buffer_out);
m_last_length = command_length; m_last_length = command_length;
mmio->Write<u32>(ADDRESS_DILENGTH, command_length); mmio->Write<u32>(system, ADDRESS_DILENGTH, command_length);
system.GetDVDInterface().ExecuteCommand(DVD::ReplyType::IOS); system.GetDVDInterface().ExecuteCommand(DVD::ReplyType::IOS);
// Reply will be posted when done by FinishIOCtl. // Reply will be posted when done by FinishIOCtl.
@ -658,7 +665,7 @@ void DIDevice::FinishDICommand(DIResult result)
IOCtlRequest request{system, m_executing_command->m_request_address}; IOCtlRequest request{system, m_executing_command->m_request_address};
if (m_executing_command->m_copy_diimmbuf) if (m_executing_command->m_copy_diimmbuf)
memory.Write_U32(mmio->Read<u32>(ADDRESS_DIIMMBUF), request.buffer_out); memory.Write_U32(mmio->Read<u32>(system, ADDRESS_DIIMMBUF), request.buffer_out);
GetEmulationKernel().EnqueueIPCReply(request, static_cast<s32>(result)); GetEmulationKernel().EnqueueIPCReply(request, static_cast<s32>(result));

View File

@ -189,9 +189,14 @@ T MMU::ReadFromHardware(u32 em_address)
if (flag == XCheckTLBFlag::Read && (em_address & 0xF8000000) == 0x08000000) if (flag == XCheckTLBFlag::Read && (em_address & 0xF8000000) == 0x08000000)
{ {
if (em_address < 0x0c000000) if (em_address < 0x0c000000)
{
return EFB_Read(em_address); return EFB_Read(em_address);
}
else else
return static_cast<T>(m_memory.GetMMIOMapping()->Read<std::make_unsigned_t<T>>(em_address)); {
return static_cast<T>(
m_memory.GetMMIOMapping()->Read<std::make_unsigned_t<T>>(m_system, em_address));
}
} }
// Locked L1 technically doesn't have a fixed address, but games all use 0xE0000000. // Locked L1 technically doesn't have a fixed address, but games all use 0xE0000000.
@ -346,20 +351,20 @@ void MMU::WriteToHardware(u32 em_address, const u32 data, const u32 size)
switch (size) switch (size)
{ {
case 1: case 1:
m_memory.GetMMIOMapping()->Write<u8>(em_address, static_cast<u8>(data)); m_memory.GetMMIOMapping()->Write<u8>(m_system, em_address, static_cast<u8>(data));
return; return;
case 2: case 2:
m_memory.GetMMIOMapping()->Write<u16>(em_address, static_cast<u16>(data)); m_memory.GetMMIOMapping()->Write<u16>(m_system, em_address, static_cast<u16>(data));
return; return;
case 4: case 4:
m_memory.GetMMIOMapping()->Write<u32>(em_address, data); m_memory.GetMMIOMapping()->Write<u32>(m_system, em_address, data);
return; return;
default: default:
// Some kind of misaligned write. TODO: Does this match how the actual hardware handles it? // Some kind of misaligned write. TODO: Does this match how the actual hardware handles it?
for (size_t i = size * 8; i > 0; em_address++) for (size_t i = size * 8; i > 0; em_address++)
{ {
i -= 8; i -= 8;
m_memory.GetMMIOMapping()->Write<u8>(em_address, static_cast<u8>(data >> i)); m_memory.GetMMIOMapping()->Write<u8>(m_system, em_address, static_cast<u8>(data >> i));
} }
return; return;
} }
@ -1035,7 +1040,7 @@ void MMU::DMA_LCToMemory(const u32 mem_address, const u32 cache_address, const u
for (u32 i = 0; i < 32 * num_blocks; i += 4) for (u32 i = 0; i < 32 * num_blocks; i += 4)
{ {
const u32 data = Common::swap32(m_memory.GetL1Cache() + ((cache_address + i) & 0x3FFFF)); const u32 data = Common::swap32(m_memory.GetL1Cache() + ((cache_address + i) & 0x3FFFF));
m_memory.GetMMIOMapping()->Write(mem_address + i, data); m_memory.GetMMIOMapping()->Write(m_system, mem_address + i, data);
} }
return; return;
} }
@ -1071,7 +1076,8 @@ void MMU::DMA_MemoryToLC(const u32 cache_address, const u32 mem_address, const u
{ {
for (u32 i = 0; i < 32 * num_blocks; i += 4) for (u32 i = 0; i < 32 * num_blocks; i += 4)
{ {
const u32 data = Common::swap32(m_memory.GetMMIOMapping()->Read<u32>(mem_address + i)); const u32 data =
Common::swap32(m_memory.GetMMIOMapping()->Read<u32>(m_system, mem_address + i));
std::memcpy(m_memory.GetL1Cache() + ((cache_address + i) & 0x3FFFF), &data, sizeof(u32)); std::memcpy(m_memory.GetL1Cache() + ((cache_address + i) & 0x3FFFF), &data, sizeof(u32));
} }
return; return;

View File

@ -2,6 +2,8 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <memory>
#include <string> #include <string>
#include <unordered_set> #include <unordered_set>
@ -10,6 +12,7 @@
#include "Common/FileUtil.h" #include "Common/FileUtil.h"
#include "Core/HW/GPFifo.h" #include "Core/HW/GPFifo.h"
#include "Core/HW/MMIO.h" #include "Core/HW/MMIO.h"
#include "Core/System.h"
#include "UICommon/UICommon.h" #include "UICommon/UICommon.h"
// Tests that the UniqueID function returns a "unique enough" identifier // Tests that the UniqueID function returns a "unique enough" identifier
@ -66,9 +69,18 @@ TEST(IsMMIOAddress, SpecialAddresses)
class MappingTest : public testing::Test class MappingTest : public testing::Test
{ {
protected: protected:
virtual void SetUp() override { m_mapping = new MMIO::Mapping(); } virtual void SetUp() override
virtual void TearDown() override { delete m_mapping; } {
MMIO::Mapping* m_mapping = nullptr; m_system = &Core::System::GetInstance();
m_mapping = std::make_unique<MMIO::Mapping>();
}
virtual void TearDown() override
{
m_system = nullptr;
m_mapping.reset();
}
Core::System* m_system = nullptr;
std::unique_ptr<MMIO::Mapping> m_mapping;
}; };
TEST_F(MappingTest, ReadConstant) TEST_F(MappingTest, ReadConstant)
@ -77,9 +89,9 @@ TEST_F(MappingTest, ReadConstant)
m_mapping->Register(0x0C001234, MMIO::Constant<u16>(0x1234), MMIO::Nop<u16>()); m_mapping->Register(0x0C001234, MMIO::Constant<u16>(0x1234), MMIO::Nop<u16>());
m_mapping->Register(0x0C001234, MMIO::Constant<u32>(0xdeadbeef), MMIO::Nop<u32>()); m_mapping->Register(0x0C001234, MMIO::Constant<u32>(0xdeadbeef), MMIO::Nop<u32>());
u8 val8 = m_mapping->Read<u8>(0x0C001234); u8 val8 = m_mapping->Read<u8>(*m_system, 0x0C001234);
u16 val16 = m_mapping->Read<u16>(0x0C001234); u16 val16 = m_mapping->Read<u16>(*m_system, 0x0C001234);
u32 val32 = m_mapping->Read<u32>(0x0C001234); u32 val32 = m_mapping->Read<u32>(*m_system, 0x0C001234);
EXPECT_EQ(0x42, val8); EXPECT_EQ(0x42, val8);
EXPECT_EQ(0x1234, val16); EXPECT_EQ(0x1234, val16);
@ -101,19 +113,19 @@ TEST_F(MappingTest, ReadWriteDirect)
for (u32 i = 0; i < 100; ++i) for (u32 i = 0; i < 100; ++i)
{ {
u8 val8 = m_mapping->Read<u8>(0x0C001234); u8 val8 = m_mapping->Read<u8>(*m_system, 0x0C001234);
EXPECT_EQ(i, val8); EXPECT_EQ(i, val8);
u16 val16 = m_mapping->Read<u16>(0x0C001234); u16 val16 = m_mapping->Read<u16>(*m_system, 0x0C001234);
EXPECT_EQ(i, val16); EXPECT_EQ(i, val16);
u32 val32 = m_mapping->Read<u32>(0x0C001234); u32 val32 = m_mapping->Read<u32>(*m_system, 0x0C001234);
EXPECT_EQ(i, val32); EXPECT_EQ(i, val32);
val8 += 1; val8 += 1;
m_mapping->Write(0x0C001234, val8); m_mapping->Write(*m_system, 0x0C001234, val8);
val16 += 1; val16 += 1;
m_mapping->Write(0x0C001234, val16); m_mapping->Write(*m_system, 0x0C001234, val16);
val32 += 1; val32 += 1;
m_mapping->Write(0x0C001234, val32); m_mapping->Write(*m_system, 0x0C001234, val32);
} }
} }
@ -132,9 +144,9 @@ TEST_F(MappingTest, ReadWriteComplex)
write_called = true; write_called = true;
})); }));
u8 val = m_mapping->Read<u8>(0x0C001234); u8 val = m_mapping->Read<u8>(*m_system, 0x0C001234);
EXPECT_EQ(0x12, val); EXPECT_EQ(0x12, val);
m_mapping->Write(0x0C001234, (u8)0x34); m_mapping->Write(*m_system, 0x0C001234, (u8)0x34);
EXPECT_TRUE(read_called); EXPECT_TRUE(read_called);
EXPECT_TRUE(write_called); EXPECT_TRUE(write_called);