@@ -12,6 +12,7 @@

#include "Core/ConfigManager.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"

#include "VideoCommon/OpcodeDecoding.h"
#include "VideoCommon/XFStructs.h"
@@ -229,8 +230,10 @@ void FifoRecorder::StartRecording(s32 numFrames, CallbackFunc finishedCb)
// - Global variables suck
// - Multithreading with the above two sucks
//
m_Ram.resize(Memory::GetRamSize());
m_ExRam.resize(Memory::GetExRamSize());
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
m_Ram.resize(memory.GetRamSize());
m_ExRam.resize(memory.GetExRamSize());

std::fill(m_Ram.begin(), m_Ram.end(), 0);
std::fill(m_ExRam.begin(), m_ExRam.end(), 0);
@@ -310,17 +313,20 @@ void FifoRecorder::WriteGPCommand(const u8* data, u32 size)

void FifoRecorder::UseMemory(u32 address, u32 size, MemoryUpdate::Type type, bool dynamicUpdate)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

u8* curData;
u8* newData;
if (address & 0x10000000)
{
curData = &m_ExRam[address & Memory::GetExRamMask()];
newData = &Memory::m_pEXRAM[address & Memory::GetExRamMask()];
curData = &m_ExRam[address & memory.GetExRamMask()];
newData = &memory.GetEXRAM()[address & memory.GetExRamMask()];
}
else
{
curData = &m_Ram[address & Memory::GetRamMask()];
newData = &Memory::m_pRAM[address & Memory::GetRamMask()];
curData = &m_Ram[address & memory.GetRamMask()];
newData = &memory.GetRAM()[address & memory.GetRamMask()];
}

if (!dynamicUpdate && memcmp(curData, newData, size) != 0)
@@ -19,6 +19,7 @@
#include "Core/IOS/ES/ES.h"
#include "Core/PowerPC/PPCSymbolDB.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"

namespace HLE
{
@@ -90,7 +91,9 @@ void PatchFixedFunctions()
if (!Config::Get(Config::MAIN_ENABLE_CHEATS))
{
Patch(0x80001800, "HBReload");
Memory::CopyToEmu(0x00001804, "STUBHAXX", 8);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyToEmu(0x00001804, "STUBHAXX", 8);
}

// Not part of the binary itself, but either we or Gecko OS might insert
@@ -10,6 +10,7 @@
#include "Core/HW/DSP.h"
#include "Core/HW/Memmap.h"
#include "Core/PowerPC/MMU.h"
#include "Core/System.h"

namespace AddressSpace
{
@@ -92,6 +93,9 @@ struct EffectiveAddressSpaceAccessors : Accessors

bool Matches(u32 haystack_start, const u8* needle_start, std::size_t needle_size) const
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

u32 page_base = haystack_start & 0xfffff000;
u32 offset = haystack_start & 0x0000fff;
do
@@ -114,7 +118,7 @@ struct EffectiveAddressSpaceAccessors : Accessors
return false;
}

u8* page_ptr = Memory::GetPointer(*page_physical_address);
u8* page_ptr = memory.GetPointer(*page_physical_address);
if (page_ptr == nullptr)
{
return false;
@@ -417,9 +421,12 @@ Accessors* GetAccessors(Type address_space)

void Init()
{
s_mem1_address_space_accessors = {&Memory::m_pRAM, Memory::GetRamSizeReal()};
s_mem2_address_space_accessors = {&Memory::m_pEXRAM, Memory::GetExRamSizeReal()};
s_fake_address_space_accessors = {&Memory::m_pFakeVMEM, Memory::GetFakeVMemSize()};
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

s_mem1_address_space_accessors = {&memory.GetRAM(), memory.GetRamSizeReal()};
s_mem2_address_space_accessors = {&memory.GetEXRAM(), memory.GetExRamSizeReal()};
s_fake_address_space_accessors = {&memory.GetFakeVMEM(), memory.GetFakeVMemSize()};
s_physical_address_space_accessors_gcn = {{0x00000000, &s_mem1_address_space_accessors}};
s_physical_address_space_accessors_wii = {{0x00000000, &s_mem1_address_space_accessors},
{0x10000000, &s_mem2_address_space_accessors}};
@@ -205,16 +205,18 @@ void Init(bool hle)

void Reinit(bool hle)
{
auto& state = Core::System::GetInstance().GetDSPState().GetData();
auto& system = Core::System::GetInstance();
auto& state = system.GetDSPState().GetData();
state.dsp_emulator = CreateDSPEmulator(hle);
state.is_lle = state.dsp_emulator->IsLLE();

if (SConfig::GetInstance().bWii)
{
auto& memory = system.GetMemory();
state.aram.wii_mode = true;
state.aram.size = Memory::GetExRamSizeReal();
state.aram.mask = Memory::GetExRamMask();
state.aram.ptr = Memory::m_pEXRAM;
state.aram.size = memory.GetExRamSizeReal();
state.aram.mask = memory.GetExRamMask();
state.aram.ptr = memory.GetEXRAM();
}
else
{
@@ -527,7 +529,8 @@ void UpdateAudioDMA()
// Read audio at g_audioDMA.current_source_address in RAM and push onto an
// external audio fifo in the emulator, to be mixed with the disc
// streaming output.
void* address = Memory::GetPointer(state.audio_dma.current_source_address);
auto& memory = system.GetMemory();
void* address = memory.GetPointer(state.audio_dma.current_source_address);
AudioCommon::SendAIBuffer(system, reinterpret_cast<short*>(address), 8);

if (state.audio_dma.remaining_blocks_count != 0)
@@ -554,6 +557,7 @@ static void Do_ARAM_DMA()
{
auto& system = Core::System::GetInstance();
auto& core_timing = system.GetCoreTiming();
auto& memory = system.GetMemory();
auto& state = system.GetDSPState().GetData();

state.dsp_control.DMAState = 1;
@@ -581,18 +585,18 @@ static void Do_ARAM_DMA()
// See below in the write section for more information
if ((state.aram_info.Hex & 0xf) == 3)
{
Memory::Write_U64_Swap(*(u64*)&state.aram.ptr[state.aram_dma.ARAddr & state.aram.mask],
state.aram_dma.MMAddr);
memory.Write_U64_Swap(*(u64*)&state.aram.ptr[state.aram_dma.ARAddr & state.aram.mask],
state.aram_dma.MMAddr);
}
else if ((state.aram_info.Hex & 0xf) == 4)
{
Memory::Write_U64_Swap(*(u64*)&state.aram.ptr[state.aram_dma.ARAddr & state.aram.mask],
state.aram_dma.MMAddr);
memory.Write_U64_Swap(*(u64*)&state.aram.ptr[state.aram_dma.ARAddr & state.aram.mask],
state.aram_dma.MMAddr);
}
else
{
Memory::Write_U64_Swap(*(u64*)&state.aram.ptr[state.aram_dma.ARAddr & state.aram.mask],
state.aram_dma.MMAddr);
memory.Write_U64_Swap(*(u64*)&state.aram.ptr[state.aram_dma.ARAddr & state.aram.mask],
state.aram_dma.MMAddr);
}

state.aram_dma.MMAddr += 8;
@@ -604,7 +608,7 @@ static void Do_ARAM_DMA()
{
while (state.aram_dma.Cnt.count)
{
Memory::Write_U64(HSP::Read(state.aram_dma.ARAddr), state.aram_dma.MMAddr);
memory.Write_U64(HSP::Read(state.aram_dma.ARAddr), state.aram_dma.MMAddr);
state.aram_dma.MMAddr += 8;
state.aram_dma.ARAddr += 8;
state.aram_dma.Cnt.count -= 8;
@@ -628,22 +632,22 @@ static void Do_ARAM_DMA()
if ((state.aram_info.Hex & 0xf) == 3)
{
*(u64*)&state.aram.ptr[state.aram_dma.ARAddr & state.aram.mask] =
Common::swap64(Memory::Read_U64(state.aram_dma.MMAddr));
Common::swap64(memory.Read_U64(state.aram_dma.MMAddr));
}
else if ((state.aram_info.Hex & 0xf) == 4)
{
if (state.aram_dma.ARAddr < 0x400000)
{
*(u64*)&state.aram.ptr[(state.aram_dma.ARAddr + 0x400000) & state.aram.mask] =
Common::swap64(Memory::Read_U64(state.aram_dma.MMAddr));
Common::swap64(memory.Read_U64(state.aram_dma.MMAddr));
}
*(u64*)&state.aram.ptr[state.aram_dma.ARAddr & state.aram.mask] =
Common::swap64(Memory::Read_U64(state.aram_dma.MMAddr));
Common::swap64(memory.Read_U64(state.aram_dma.MMAddr));
}
else
{
*(u64*)&state.aram.ptr[state.aram_dma.ARAddr & state.aram.mask] =
Common::swap64(Memory::Read_U64(state.aram_dma.MMAddr));
Common::swap64(memory.Read_U64(state.aram_dma.MMAddr));
}

state.aram_dma.MMAddr += 8;
@@ -655,7 +659,7 @@ static void Do_ARAM_DMA()
{
while (state.aram_dma.Cnt.count)
{
HSP::Write(state.aram_dma.ARAddr, Memory::Read_U64(state.aram_dma.MMAddr));
HSP::Write(state.aram_dma.ARAddr, memory.Read_U64(state.aram_dma.MMAddr));

state.aram_dma.MMAddr += 8;
state.aram_dma.ARAddr += 8;
@@ -670,14 +674,20 @@ static void Do_ARAM_DMA()
// (LM) It just means that DSP reads via '0xffdd' on Wii can end up in EXRAM or main RAM
u8 ReadARAM(u32 address)
{
auto& state = Core::System::GetInstance().GetDSPState().GetData();
auto& system = Core::System::GetInstance();
auto& state = system.GetDSPState().GetData();

if (state.aram.wii_mode)
{
if (address & 0x10000000)
{
return state.aram.ptr[address & state.aram.mask];
}
else
return Memory::Read_U8(address & Memory::GetRamMask());
{
auto& memory = system.GetMemory();
return memory.Read_U8(address & memory.GetRamMask());
}
}
else
{
@@ -19,6 +19,7 @@
#include "Common/Swap.h"
#include "Core/HW/DSPHLE/UCodes/UCodes.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"

namespace DSP::HLE
{
@@ -142,8 +143,10 @@ class AXUCode /* not final: subclassed by AXWiiUCode */ : public UCodeInterface
template <int Millis, size_t BufCount>
void InitMixingBuffers(u32 init_addr, const std::array<BufferDesc, BufCount>& buffers)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
std::array<u16, 3 * BufCount> init_array;
Memory::CopyFromEmuSwapped(init_array.data(), init_addr, sizeof(init_array));
memory.CopyFromEmuSwapped(init_array.data(), init_addr, sizeof(init_array));
for (size_t i = 0; i < BufCount; ++i)
{
const BufferDesc& buf = buffers[i];
@@ -22,6 +22,7 @@
#include "Core/HW/DSPHLE/UCodes/AX.h"
#include "Core/HW/DSPHLE/UCodes/AXStructs.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"

namespace DSP::HLE
{
@@ -101,10 +102,13 @@ bool HasLpf(u32 crc)
// Read a PB from MRAM/ARAM
void ReadPB(u32 addr, PB_TYPE& pb, u32 crc)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

if (HasLpf(crc))
{
u16* dst = (u16*)&pb;
Memory::CopyFromEmuSwapped<u16>(dst, addr, sizeof(pb));
memory.CopyFromEmuSwapped<u16>(dst, addr, sizeof(pb));
}
else
{
@@ -116,19 +120,22 @@ void ReadPB(u32 addr, PB_TYPE& pb, u32 crc)
constexpr size_t lpf_off = offsetof(AXPB, lpf);
constexpr size_t lc_off = offsetof(AXPB, loop_counter);

Memory::CopyFromEmuSwapped<u16>((u16*)dst, addr, lpf_off);
memory.CopyFromEmuSwapped<u16>((u16*)dst, addr, lpf_off);
memset(dst + lpf_off, 0, lc_off - lpf_off);
Memory::CopyFromEmuSwapped<u16>((u16*)(dst + lc_off), addr + lpf_off, sizeof(pb) - lc_off);
memory.CopyFromEmuSwapped<u16>((u16*)(dst + lc_off), addr + lpf_off, sizeof(pb) - lc_off);
}
}

// Write a PB back to MRAM/ARAM
void WritePB(u32 addr, const PB_TYPE& pb, u32 crc)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

if (HasLpf(crc))
{
const u16* src = (const u16*)&pb;
Memory::CopyToEmuSwapped<u16>(addr, src, sizeof(pb));
memory.CopyToEmuSwapped<u16>(addr, src, sizeof(pb));
}
else
{
@@ -140,8 +147,8 @@ void WritePB(u32 addr, const PB_TYPE& pb, u32 crc)
constexpr size_t lpf_off = offsetof(AXPB, lpf);
constexpr size_t lc_off = offsetof(AXPB, loop_counter);

Memory::CopyToEmuSwapped<u16>(addr, (const u16*)src, lpf_off);
Memory::CopyToEmuSwapped<u16>(addr + lpf_off, (const u16*)(src + lc_off), sizeof(pb) - lc_off);
memory.CopyToEmuSwapped<u16>(addr, (const u16*)src, lpf_off);
memory.CopyToEmuSwapped<u16>(addr + lpf_off, (const u16*)(src + lc_off), sizeof(pb) - lc_off);
}
}

@@ -30,6 +30,7 @@
#include "Core/HW/DSPHLE/UCodes/ROM.h"
#include "Core/HW/DSPHLE/UCodes/Zelda.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"

namespace DSP::HLE
{
@@ -40,28 +41,37 @@ constexpr bool ExramRead(u32 address)

u8 HLEMemory_Read_U8(u32 address)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

if (ExramRead(address))
return Memory::m_pEXRAM[address & Memory::GetExRamMask()];
return memory.GetEXRAM()[address & memory.GetExRamMask()];

return Memory::m_pRAM[address & Memory::GetRamMask()];
return memory.GetRAM()[address & memory.GetRamMask()];
}

void HLEMemory_Write_U8(u32 address, u8 value)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

if (ExramRead(address))
Memory::m_pEXRAM[address & Memory::GetExRamMask()] = value;
memory.GetEXRAM()[address & memory.GetExRamMask()] = value;
else
Memory::m_pRAM[address & Memory::GetRamMask()] = value;
memory.GetRAM()[address & memory.GetRamMask()] = value;
}

u16 HLEMemory_Read_U16LE(u32 address)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

u16 value;

if (ExramRead(address))
std::memcpy(&value, &Memory::m_pEXRAM[address & Memory::GetExRamMask()], sizeof(u16));
std::memcpy(&value, &memory.GetEXRAM()[address & memory.GetExRamMask()], sizeof(u16));
else
std::memcpy(&value, &Memory::m_pRAM[address & Memory::GetRamMask()], sizeof(u16));
std::memcpy(&value, &memory.GetRAM()[address & memory.GetRamMask()], sizeof(u16));

return value;
}
@@ -73,10 +83,13 @@ u16 HLEMemory_Read_U16(u32 address)

void HLEMemory_Write_U16LE(u32 address, u16 value)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

if (ExramRead(address))
std::memcpy(&Memory::m_pEXRAM[address & Memory::GetExRamMask()], &value, sizeof(u16));
std::memcpy(&memory.GetEXRAM()[address & memory.GetExRamMask()], &value, sizeof(u16));
else
std::memcpy(&Memory::m_pRAM[address & Memory::GetRamMask()], &value, sizeof(u16));
std::memcpy(&memory.GetRAM()[address & memory.GetRamMask()], &value, sizeof(u16));
}

void HLEMemory_Write_U16(u32 address, u16 value)
@@ -86,12 +99,15 @@ void HLEMemory_Write_U16(u32 address, u16 value)

u32 HLEMemory_Read_U32LE(u32 address)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

u32 value;

if (ExramRead(address))
std::memcpy(&value, &Memory::m_pEXRAM[address & Memory::GetExRamMask()], sizeof(u32));
std::memcpy(&value, &memory.GetEXRAM()[address & memory.GetExRamMask()], sizeof(u32));
else
std::memcpy(&value, &Memory::m_pRAM[address & Memory::GetRamMask()], sizeof(u32));
std::memcpy(&value, &memory.GetRAM()[address & memory.GetRamMask()], sizeof(u32));

return value;
}
@@ -103,10 +119,13 @@ u32 HLEMemory_Read_U32(u32 address)

void HLEMemory_Write_U32LE(u32 address, u32 value)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

if (ExramRead(address))
std::memcpy(&Memory::m_pEXRAM[address & Memory::GetExRamMask()], &value, sizeof(u32));
std::memcpy(&memory.GetEXRAM()[address & memory.GetExRamMask()], &value, sizeof(u32));
else
std::memcpy(&Memory::m_pRAM[address & Memory::GetRamMask()], &value, sizeof(u32));
std::memcpy(&memory.GetRAM()[address & memory.GetRamMask()], &value, sizeof(u32));
}

void HLEMemory_Write_U32(u32 address, u32 value)
@@ -116,10 +135,13 @@ void HLEMemory_Write_U32(u32 address, u32 value)

void* HLEMemory_Get_Pointer(u32 address)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

if (ExramRead(address))
return &Memory::m_pEXRAM[address & Memory::GetExRamMask()];
return &memory.GetEXRAM()[address & memory.GetExRamMask()];

return &Memory::m_pRAM[address & Memory::GetRamMask()];
return &memory.GetRAM()[address & memory.GetRamMask()];
}

UCodeInterface::UCodeInterface(DSPHLE* dsphle, u32 crc)
@@ -188,7 +210,9 @@ void UCodeInterface::PrepareBootUCode(u32 mail)

if (Config::Get(Config::MAIN_DUMP_UCODE))
{
DSP::DumpDSPCode(Memory::GetPointer(m_next_ucode.iram_mram_addr), m_next_ucode.iram_size,
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
DSP::DumpDSPCode(memory.GetPointer(m_next_ucode.iram_mram_addr), m_next_ucode.iram_size,
ector_crc);
}

@@ -18,6 +18,7 @@
#include "Core/HW/DSPLLE/DSPSymbols.h"
#include "Core/HW/Memmap.h"
#include "Core/Host.h"
#include "Core/System.h"
#include "VideoCommon/OnScreenDisplay.h"

// The user of the DSPCore library must supply a few functions so that the
@@ -39,12 +40,16 @@ void WriteHostMemory(u8 value, u32 addr)

void DMAToDSP(u16* dst, u32 addr, u32 size)
{
Memory::CopyFromEmuSwapped(dst, addr, size);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyFromEmuSwapped(dst, addr, size);
}

void DMAFromDSP(const u16* src, u32 addr, u32 size)
{
Memory::CopyToEmuSwapped(addr, src, size);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyToEmuSwapped(addr, src, size);
}

void OSD_AddMessage(std::string str, u32 ms)
@@ -70,7 +75,9 @@ void InterruptRequest()

void CodeLoaded(DSPCore& dsp, u32 addr, size_t size)
{
CodeLoaded(dsp, Memory::GetPointer(addr), size);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
CodeLoaded(dsp, memory.GetPointer(addr), size);
}

void CodeLoaded(DSPCore& dsp, const u8* ptr, size_t size)
@@ -896,15 +896,17 @@ void ExecuteCommand(ReplyType reply_type)
{
// Used by both GC and Wii
case DICommand::Inquiry:
{
// (shuffle2) Taken from my Wii
Memory::Write_U32(0x00000002, state.DIMAR); // Revision level, device code
Memory::Write_U32(0x20060526, state.DIMAR + 4); // Release date
Memory::Write_U32(0x41000000, state.DIMAR + 8); // Version
auto& memory = system.GetMemory();
memory.Write_U32(0x00000002, state.DIMAR); // Revision level, device code
memory.Write_U32(0x20060526, state.DIMAR + 4); // Release date
memory.Write_U32(0x41000000, state.DIMAR + 8); // Version

INFO_LOG_FMT(DVDINTERFACE, "DVDLowInquiry (Buffer {:#010x}, {:#x})", state.DIMAR,
state.DILENGTH);
break;

}
// GC-only patched drive firmware command, used by libogc
case DICommand::Unknown55:
INFO_LOG_FMT(DVDINTERFACE, "SetExtension");
@@ -1024,17 +1026,20 @@ void ExecuteCommand(ReplyType reply_type)
break;
// Wii-exclusive
case DICommand::ReadBCA:
{
WARN_LOG_FMT(DVDINTERFACE, "DVDLowReadDiskBca - supplying dummy data to appease NSMBW");
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DVD_LOW_READ_DISK_BCA);
// NSMBW checks that the first 0x33 bytes of the BCA are 0, then it expects a 1.
// Most (all?) other games have 0x34 0's at the start of the BCA, but don't actually
// read it. NSMBW doesn't care about the other 12 bytes (which contain manufacturing data?)

auto& memory = system.GetMemory();
// TODO: Read the .bca file that cleanrip generates, if it exists
// Memory::CopyToEmu(output_address, bca_data, 0x40);
Memory::Memset(state.DIMAR, 0, 0x40);
Memory::Write_U8(1, state.DIMAR + 0x33);
// memory.CopyToEmu(output_address, bca_data, 0x40);
memory.Memset(state.DIMAR, 0, 0x40);
memory.Write_U8(1, state.DIMAR + 0x33);
break;
}
// Wii-exclusive
case DICommand::RequestDiscStatus:
ERROR_LOG_FMT(DVDINTERFACE, "DVDLowRequestDiscStatus");
@@ -391,7 +391,10 @@ static void FinishRead(Core::System& system, u64 id, s64 cycles_late)
else
{
if (request.copy_to_ram)
Memory::CopyToEmu(request.output_address, buffer.data(), request.length);
{
auto& memory = system.GetMemory();
memory.CopyToEmu(request.output_address, buffer.data(), request.length);
}

interrupt = DVDInterface::DIInterruptType::TCINT;
}
@@ -15,6 +15,7 @@
#include "Core/HW/EXI/EXI_DeviceMemoryCard.h"
#include "Core/HW/EXI/EXI_DeviceMic.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"

namespace ExpansionInterface
{
@@ -47,20 +48,24 @@ void IEXIDevice::ImmReadWrite(u32& data, u32 size)

void IEXIDevice::DMAWrite(u32 address, u32 size)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
while (size--)
{
u8 byte = Memory::Read_U8(address++);
u8 byte = memory.Read_U8(address++);
TransferByte(byte);
}
}

void IEXIDevice::DMARead(u32 address, u32 size)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
while (size--)
{
u8 byte = 0;
TransferByte(byte);
Memory::Write_U8(byte, address++);
memory.Write_U8(byte, address++);
}
}

@@ -19,6 +19,7 @@
#include "Core/HW/EXI/EXI.h"
#include "Core/HW/Memmap.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"

namespace ExpansionInterface
{
@@ -233,7 +234,9 @@ void CEXIETHERNET::DMAWrite(u32 addr, u32 size)
if (transfer.region == transfer.MX && transfer.direction == transfer.WRITE &&
transfer.address == BBA_WRTXFIFOD)
{
DirectFIFOWrite(Memory::GetPointer(addr), size);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
DirectFIFOWrite(memory.GetPointer(addr), size);
}
else
{
@@ -246,7 +249,9 @@ void CEXIETHERNET::DMAWrite(u32 addr, u32 size)
void CEXIETHERNET::DMARead(u32 addr, u32 size)
{
DEBUG_LOG_FMT(SP1, "DMA read: {:08x} {:x}", addr, size);
Memory::CopyToEmu(addr, &mBbaMem[transfer.address], size);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyToEmu(addr, &mBbaMem[transfer.address], size);
transfer.address += size;
}

@@ -523,15 +523,17 @@ void CEXIMemoryCard::DoState(PointerWrap& p)
// read all at once instead of single byte at a time as done by IEXIDevice::DMARead
void CEXIMemoryCard::DMARead(u32 addr, u32 size)
{
m_memory_card->Read(m_address, size, Memory::GetPointer(addr));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
m_memory_card->Read(m_address, size, memory.GetPointer(addr));

if ((m_address + size) % Memcard::BLOCK_SIZE == 0)
{
INFO_LOG_FMT(EXPANSIONINTERFACE, "reading from block: {:x}", m_address / Memcard::BLOCK_SIZE);
}

// Schedule transfer complete later based on read speed
Core::System::GetInstance().GetCoreTiming().ScheduleEvent(
system.GetCoreTiming().ScheduleEvent(
size * (SystemTimers::GetTicksPerSecond() / MC_TRANSFER_RATE_READ),
s_et_transfer_complete[m_card_slot], static_cast<u64>(m_card_slot));
}
@@ -540,15 +542,17 @@ void CEXIMemoryCard::DMARead(u32 addr, u32 size)
// write all at once instead of single byte at a time as done by IEXIDevice::DMAWrite
void CEXIMemoryCard::DMAWrite(u32 addr, u32 size)
{
m_memory_card->Write(m_address, size, Memory::GetPointer(addr));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
m_memory_card->Write(m_address, size, memory.GetPointer(addr));

if (((m_address + size) % Memcard::BLOCK_SIZE) == 0)
{
INFO_LOG_FMT(EXPANSIONINTERFACE, "writing to block: {:x}", m_address / Memcard::BLOCK_SIZE);
}

// Schedule transfer complete later based on write speed
Core::System::GetInstance().GetCoreTiming().ScheduleEvent(
system.GetCoreTiming().ScheduleEvent(
size * (SystemTimers::GetTicksPerSecond() / MC_TRANSFER_RATE_WRITE),
s_et_transfer_complete[m_card_slot], static_cast<u64>(m_card_slot));
}
@@ -83,9 +83,12 @@ void ResetGatherPipe()

void UpdateGatherPipe()
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

size_t pipe_count = GetGatherPipeCount();
size_t processed;
u8* cur_mem = Memory::GetPointer(ProcessorInterface::Fifo_CPUWritePointer);
u8* cur_mem = memory.GetPointer(ProcessorInterface::Fifo_CPUWritePointer);
for (processed = 0; pipe_count >= GATHER_PIPE_SIZE; processed += GATHER_PIPE_SIZE)
{
// copy the GatherPipe
@@ -96,15 +99,14 @@ void UpdateGatherPipe()
if (ProcessorInterface::Fifo_CPUWritePointer == ProcessorInterface::Fifo_CPUEnd)
{
ProcessorInterface::Fifo_CPUWritePointer = ProcessorInterface::Fifo_CPUBase;
cur_mem = Memory::GetPointer(ProcessorInterface::Fifo_CPUWritePointer);
cur_mem = memory.GetPointer(ProcessorInterface::Fifo_CPUWritePointer);
}
else
{
cur_mem += GATHER_PIPE_SIZE;
ProcessorInterface::Fifo_CPUWritePointer += GATHER_PIPE_SIZE;
}

auto& system = Core::System::GetInstance();
system.GetCommandProcessor().GatherPipeBursted(system);
}

@@ -33,7 +33,8 @@ namespace HW
{
void Init(const Sram* override_sram)
{
Core::System::GetInstance().GetCoreTiming().Init();
auto& system = Core::System::GetInstance();
system.GetCoreTiming().Init();
SystemTimers::PreInit();

State::Init();
@@ -45,7 +46,7 @@ void Init(const Sram* override_sram)
ProcessorInterface::Init();
ExpansionInterface::Init(override_sram); // Needs to be initialized before Memory
HSP::Init();
Memory::Init(); // Needs to be initialized before AddressSpace
system.GetMemory().Init(); // Needs to be initialized before AddressSpace
AddressSpace::Init();
MemoryInterface::Init();
DSP::Init(Config::Get(Config::MAIN_DSP_HLE));
@@ -63,6 +64,8 @@ void Init(const Sram* override_sram)

void Shutdown()
{
auto& system = Core::System::GetInstance();

// IOS should always be shut down regardless of bWii because it can be running in GC mode (MIOS).
IOS::HLE::Shutdown(); // Depends on Memory
IOS::Shutdown();
@@ -73,19 +76,20 @@ void Shutdown()
DSP::Shutdown();
MemoryInterface::Shutdown();
AddressSpace::Shutdown();
Memory::Shutdown();
system.GetMemory().Shutdown();
HSP::Shutdown();
ExpansionInterface::Shutdown();
SerialInterface::Shutdown();
AudioInterface::Shutdown();

State::Shutdown();
Core::System::GetInstance().GetCoreTiming().Shutdown();
system.GetCoreTiming().Shutdown();
}

void DoState(PointerWrap& p)
{
Memory::DoState(p);
auto& system = Core::System::GetInstance();
system.GetMemory().DoState(p);
p.DoMarker("Memory");
MemoryInterface::DoState(p);
p.DoMarker("MemoryInterface");

Large diffs are not rendered by default.

@@ -3,11 +3,14 @@

#pragma once

#include <array>
#include <memory>
#include <string>
#include <vector>

#include "Common/CommonTypes.h"
#include "Common/MathUtil.h"
#include "Common/MemArena.h"
#include "Common/Swap.h"
#include "Core/PowerPC/MMU.h"

@@ -20,98 +23,221 @@ class Mapping;

namespace Memory
{
// Base is a pointer to the base of the memory map. Yes, some MMU tricks
// are used to set up a full GC or Wii memory map in process memory.
// In 64-bit, this might point to "high memory" (above the 32-bit limit),
// so be sure to load it into a 64-bit register.
extern u8* physical_base;
extern u8* logical_base;

// This page table is used for a "soft MMU" implementation when
// setting up the full memory map in process memory isn't possible.
extern u8* physical_page_mappings_base;
extern u8* logical_page_mappings_base;

// The actual memory used for backing the memory map.
extern u8* m_pRAM;
extern u8* m_pEXRAM;
extern u8* m_pL1Cache;
extern u8* m_pFakeVMEM;

u32 GetRamSizeReal();
u32 GetRamSize();
u32 GetRamMask();
u32 GetFakeVMemSize();
u32 GetFakeVMemMask();
u32 GetL1CacheSize();
u32 GetL1CacheMask();
u32 GetExRamSizeReal();
u32 GetExRamSize();
u32 GetExRamMask();

constexpr u32 MEM1_BASE_ADDR = 0x80000000U;
constexpr u32 MEM2_BASE_ADDR = 0x90000000U;
constexpr u32 MEM1_SIZE_RETAIL = 0x01800000U;
constexpr u32 MEM1_SIZE_GDEV = 0x04000000U;
constexpr u32 MEM2_SIZE_RETAIL = 0x04000000U;
constexpr u32 MEM2_SIZE_NDEV = 0x08000000U;

// MMIO mapping object.
extern std::unique_ptr<MMIO::Mapping> mmio_mapping;

// Init and Shutdown
bool IsInitialized();
void Init();
void Shutdown();
bool InitFastmemArena();
void ShutdownFastmemArena();
void DoState(PointerWrap& p);

void UpdateLogicalMemory(const PowerPC::BatTable& dbat_table);

void Clear();

// Routines to access physically addressed memory, designed for use by
// emulated hardware outside the CPU. Use "Device_" prefix.
std::string GetString(u32 em_address, size_t size = 0);
u8* GetPointer(u32 address);
u8* GetPointerForRange(u32 address, size_t size);
void CopyFromEmu(void* data, u32 address, size_t size);
void CopyToEmu(u32 address, const void* data, size_t size);
void Memset(u32 address, u8 value, size_t size);
u8 Read_U8(u32 address);
u16 Read_U16(u32 address);
u32 Read_U32(u32 address);
u64 Read_U64(u32 address);
void Write_U8(u8 var, u32 address);
void Write_U16(u16 var, u32 address);
void Write_U32(u32 var, u32 address);
void Write_U64(u64 var, u32 address);
void Write_U32_Swap(u32 var, u32 address);
void Write_U64_Swap(u64 var, u32 address);

// Templated functions for byteswapped copies.
template <typename T>
void CopyFromEmuSwapped(T* data, u32 address, size_t size)
struct PhysicalMemoryRegion
{
const T* src = reinterpret_cast<T*>(GetPointerForRange(address, size));

if (src == nullptr)
return;

for (size_t i = 0; i < size / sizeof(T); i++)
data[i] = Common::FromBigEndian(src[i]);
}

template <typename T>
void CopyToEmuSwapped(u32 address, const T* data, size_t size)
u8** out_pointer;
u32 physical_address;
u32 size;
enum : u32
{
ALWAYS = 0,
FAKE_VMEM = 1,
WII_ONLY = 2,
} flags;
u32 shm_position;
bool active;
};

struct LogicalMemoryView
{
T* dest = reinterpret_cast<T*>(GetPointerForRange(address, size));

if (dest == nullptr)
return;
void* mapped_pointer;
u32 mapped_size;
};

for (size_t i = 0; i < size / sizeof(T); i++)
dest[i] = Common::FromBigEndian(data[i]);
}
class MemoryManager
{
public:
MemoryManager();
MemoryManager(const MemoryManager& other) = delete;
MemoryManager(MemoryManager&& other) = delete;
MemoryManager& operator=(const MemoryManager& other) = delete;
MemoryManager& operator=(MemoryManager&& other) = delete;
~MemoryManager();

u32 GetRamSizeReal() const { return m_ram_size_real; }
u32 GetRamSize() const { return m_ram_size; }
u32 GetRamMask() const { return m_ram_mask; }
u32 GetFakeVMemSize() const { return m_fakevmem_size; }
u32 GetFakeVMemMask() const { return m_fakevmem_mask; }
u32 GetL1CacheSize() const { return m_l1_cache_size; }
u32 GetL1CacheMask() const { return m_l1_cache_mask; }
u32 GetExRamSizeReal() const { return m_exram_size_real; }
u32 GetExRamSize() const { return m_exram_size; }
u32 GetExRamMask() const { return m_exram_mask; }

u8* GetPhysicalBase() const { return m_physical_base; }
u8* GetLogicalBase() const { return m_logical_base; }
u8* GetPhysicalPageMappingsBase() const { return m_physical_page_mappings_base; }
u8* GetLogicalPageMappingsBase() const { return m_logical_page_mappings_base; }

// FIXME: these should not return their address, but AddressSpace wants that
u8*& GetRAM() { return m_ram; }
u8*& GetEXRAM() { return m_exram; }
u8* GetL1Cache() { return m_l1_cache; }
u8*& GetFakeVMEM() { return m_fake_vmem; }

MMIO::Mapping* GetMMIOMapping() const { return m_mmio_mapping.get(); }

// Init and Shutdown
bool IsInitialized() const { return m_is_initialized; }
void Init();
void Shutdown();
bool InitFastmemArena();
void ShutdownFastmemArena();
void DoState(PointerWrap& p);

void UpdateLogicalMemory(const PowerPC::BatTable& dbat_table);

void Clear();

// Routines to access physically addressed memory, designed for use by
// emulated hardware outside the CPU. Use "Device_" prefix.
std::string GetString(u32 em_address, size_t size = 0);
u8* GetPointer(u32 address) const;
u8* GetPointerForRange(u32 address, size_t size) const;
void CopyFromEmu(void* data, u32 address, size_t size) const;
void CopyToEmu(u32 address, const void* data, size_t size);
void Memset(u32 address, u8 value, size_t size);
u8 Read_U8(u32 address) const;
u16 Read_U16(u32 address) const;
u32 Read_U32(u32 address) const;
u64 Read_U64(u32 address) const;
void Write_U8(u8 var, u32 address);
void Write_U16(u16 var, u32 address);
void Write_U32(u32 var, u32 address);
void Write_U64(u64 var, u32 address);
void Write_U32_Swap(u32 var, u32 address);
void Write_U64_Swap(u64 var, u32 address);

// Templated functions for byteswapped copies.
template <typename T>
void CopyFromEmuSwapped(T* data, u32 address, size_t size) const
{
const T* src = reinterpret_cast<T*>(GetPointerForRange(address, size));

if (src == nullptr)
return;

for (size_t i = 0; i < size / sizeof(T); i++)
data[i] = Common::FromBigEndian(src[i]);
}

template <typename T>
void CopyToEmuSwapped(u32 address, const T* data, size_t size)
{
T* dest = reinterpret_cast<T*>(GetPointerForRange(address, size));

if (dest == nullptr)
return;

for (size_t i = 0; i < size / sizeof(T); i++)
dest[i] = Common::FromBigEndian(data[i]);
}

private:
// Base is a pointer to the base of the memory map. Yes, some MMU tricks
// are used to set up a full GC or Wii memory map in process memory.
// In 64-bit, this might point to "high memory" (above the 32-bit limit),
// so be sure to load it into a 64-bit register.
u8* m_physical_base = nullptr;
u8* m_logical_base = nullptr;

// This page table is used for a "soft MMU" implementation when
// setting up the full memory map in process memory isn't possible.
u8* m_physical_page_mappings_base = nullptr;
u8* m_logical_page_mappings_base = nullptr;

// The actual memory used for backing the memory map.
u8* m_ram;
u8* m_exram;
u8* m_l1_cache;
u8* m_fake_vmem;

// m_ram_size is the amount allocated by the emulator, whereas m_ram_size_real
// is what will be reported in lowmem, and thus used by emulated software.
// Note: Writing to lowmem is done by IPL. If using retail IPL, it will
// always be set to 24MB.
u32 m_ram_size_real;
u32 m_ram_size;
u32 m_ram_mask;
u32 m_fakevmem_size;
u32 m_fakevmem_mask;
u32 m_l1_cache_size;
u32 m_l1_cache_mask;
// m_exram_size is the amount allocated by the emulator, whereas m_exram_size_real
// is what gets used by emulated software. If using retail IOS, it will
// always be set to 64MB.
u32 m_exram_size_real;
u32 m_exram_size;
u32 m_exram_mask;

bool m_is_fastmem_arena_initialized = false;

// STATE_TO_SAVE
// Save the Init(), Shutdown() state
bool m_is_initialized = false;
// END STATE_TO_SAVE

// MMIO mapping object.
std::unique_ptr<MMIO::Mapping> m_mmio_mapping;

// The MemArena class
Common::MemArena m_arena;

// Dolphin allocates memory to represent four regions:
// - 32MB RAM (actually 24MB on hardware), available on GameCube and Wii
// - 64MB "EXRAM", RAM only available on Wii
// - 32MB FakeVMem, allocated in GameCube mode when MMU support is turned off.
// This is used to approximate the behavior of a common library which pages
// memory to and from the DSP's dedicated RAM. The DSP's RAM (ARAM) isn't
// directly addressable on GameCube.
// - 256KB Locked L1, to represent cache lines allocated out of the L1 data
// cache in Locked L1 mode. Dolphin does not emulate this hardware feature
// accurately; it just pretends there is extra memory at 0xE0000000.
//
// The 4GB starting at m_physical_base represents access from the CPU
// with address translation turned off. (This is only used by the CPU;
// other devices, like the GPU, use other rules, approximated by
// Memory::GetPointer.) This memory is laid out as follows:
// [0x00000000, 0x02000000) - 32MB RAM
// [0x02000000, 0x08000000) - Mirrors of 32MB RAM (not handled here)
// [0x08000000, 0x0C000000) - EFB "mapping" (not handled here)
// [0x0C000000, 0x0E000000) - MMIO etc. (not handled here)
// [0x10000000, 0x14000000) - 64MB RAM (Wii-only; slightly slower)
// [0x7E000000, 0x80000000) - FakeVMEM
// [0xE0000000, 0xE0040000) - 256KB locked L1
//
// The 4GB starting at m_logical_base represents access from the CPU
// with address translation turned on. This mapping is computed based
// on the BAT registers.
//
// Each of these 4GB regions is followed by 4GB of empty space so overflows
// in address computation in the JIT don't access the wrong memory.
//
// The neighboring mirrors of RAM ([0x02000000, 0x08000000), etc.) exist because
// the bus masks off the bits in question for RAM accesses; using them is a
// terrible idea because the CPU cache won't handle them correctly, but a
// few buggy games (notably Rogue Squadron 2) use them by accident. They
// aren't backed by memory mappings because they are used very rarely.
//
// Dolphin doesn't emulate the difference between cached and uncached access.
//
// TODO: The actual size of RAM is 24MB; the other 8MB shouldn't be backed by actual memory.
// TODO: Do we want to handle the mirrors of the GC RAM?
std::array<PhysicalMemoryRegion, 4> m_physical_regions;

std::vector<LogicalMemoryView> m_logical_mapped_entries;

std::array<void*, PowerPC::BAT_PAGE_COUNT> m_physical_page_mappings;
std::array<void*, PowerPC::BAT_PAGE_COUNT> m_logical_page_mappings;

void InitMMIO(bool is_wii);
};
} // namespace Memory
@@ -21,14 +21,25 @@
#include "Core/HW/WII_IPC.h"
#include "Core/IOS/ES/ES.h"
#include "Core/IOS/ES/Formats.h"
#include "Core/System.h"
#include "DiscIO/Volume.h"

template <u32 addr>
class RegisterWrapper
{
public:
operator u32() const { return Memory::mmio_mapping->Read<u32>(addr); }
void operator=(u32 rhs) { Memory::mmio_mapping->Write(addr, rhs); }
operator u32() const
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
return memory.GetMMIOMapping()->Read<u32>(addr);
}
void operator=(u32 rhs)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.GetMMIOMapping()->Write(addr, rhs);
}
};
static RegisterWrapper<0x0D806000> DISR;
static RegisterWrapper<0x0D806004> DICVR;
@@ -76,7 +87,9 @@ std::optional<IPCReply> DIDevice::IOCtl(const IOCtlRequest& request)
// asynchronously. The rest are also treated as async to match this. Only one command can be
// executed at a time, so commands are queued until DVDInterface is ready to handle them.

const u8 command = Memory::Read_U8(request.buffer_in);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u8 command = memory.Read_U8(request.buffer_in);
if (request.request != command)
{
WARN_LOG_FMT(IOS_DI,
@@ -128,7 +141,9 @@ std::optional<DIDevice::DIResult> DIDevice::WriteIfFits(const IOCtlRequest& requ
}
else
{
Memory::Write_U32(value, request.buffer_out);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(value, request.buffer_out);
return DIResult::Success;
}
}
@@ -152,6 +167,9 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
return DIResult::SecurityError;
}

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

// DVDInterface's ExecuteCommand handles most of the work for most of these.
// The IOCtl callback is used to generate a reply afterwards.
switch (static_cast<DIIoctl>(request.request))
@@ -169,16 +187,16 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
return StartDMATransfer(0x20, request);
// TODO: Include an additional read that happens on Wii discs, or at least
// emulate its side effect of disabling DTK configuration
// if (Memory::Read_U32(request.buffer_out + 24) == 0x5d1c9ea3) { // Wii Magic
// if (memory.Read_U32(request.buffer_out + 24) == 0x5d1c9ea3) { // Wii Magic
// if (!m_has_read_encryption_info) {
// // Read 0x44 (=> 0x60) bytes starting from offset 8 or byte 0x20;
// // byte 0x60 is disable hashing and byte 0x61 is disable encryption
// }
// }
case DIIoctl::DVDLowRead:
{
const u32 length = Memory::Read_U32(request.buffer_in + 4);
const u32 position = Memory::Read_U32(request.buffer_in + 8);
const u32 length = memory.Read_U32(request.buffer_in + 4);
const u32 position = memory.Read_U32(request.buffer_in + 8);
INFO_LOG_FMT(IOS_DI, "DVDLowRead: offset {:#010x} (byte {:#011x}), length {:#x}", position,
static_cast<u64>(position) << 2, length);
if (m_current_partition == DiscIO::PARTITION_NONE)
@@ -220,7 +238,7 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
return DIResult::BadArgument;
case DIIoctl::DVDLowReadDvdPhysical:
{
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);
DICMDBUF0 = 0xAD000000 | (position << 8);
DICMDBUF1 = 0;
@@ -229,7 +247,7 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
}
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);
DICMDBUF0 = 0xAD010000 | (position << 8);
DICMDBUF1 = 0;
@@ -238,7 +256,7 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
}
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);
DICMDBUF0 = 0xAD020000 | (position << 8);
DICMDBUF1 = 0;
@@ -280,7 +298,7 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
return DIResult::Success;
case DIIoctl::DVDLowReset:
{
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.
const u32 old_gpio = HW_GPIO_OUT;
@@ -318,8 +336,8 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
return DIResult::Success;
case DIIoctl::DVDLowUnencryptedRead:
{
const u32 length = Memory::Read_U32(request.buffer_in + 4);
const u32 position = Memory::Read_U32(request.buffer_in + 8);
const u32 length = memory.Read_U32(request.buffer_in + 4);
const u32 position = memory.Read_U32(request.buffer_in + 8);
const u32 end = position + (length >> 2); // a 32-bit offset
INFO_LOG_FMT(IOS_DI, "DVDLowUnencryptedRead: offset {:#010x} (byte {:#011x}), length {:#x}",
position, static_cast<u64>(position) << 2, length);
@@ -395,8 +413,8 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
}
case DIIoctl::DVDLowReportKey:
{
const u8 param1 = Memory::Read_U8(request.buffer_in + 7);
const u32 param2 = Memory::Read_U32(request.buffer_in + 8);
const u8 param1 = memory.Read_U8(request.buffer_in + 7);
const u32 param2 = memory.Read_U32(request.buffer_in + 8);
INFO_LOG_FMT(IOS_DI, "DVDLowReportKey: param1 {:#04x}, param2 {:#08x}", param1, param2);
DICMDBUF0 = 0xA4000000 | (param1 << 16);
DICMDBUF1 = param2 & 0xFFFFFF;
@@ -405,7 +423,7 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
}
case DIIoctl::DVDLowSeek:
{
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,
position); // TODO: do partition translation!
DICMDBUF0 = 0xAB000000;
@@ -414,10 +432,10 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
}
case DIIoctl::DVDLowReadDvd:
{
const u8 flag1 = Memory::Read_U8(request.buffer_in + 7);
const u8 flag2 = Memory::Read_U8(request.buffer_in + 11);
const u32 length = Memory::Read_U32(request.buffer_in + 12);
const u32 position = Memory::Read_U32(request.buffer_in + 16);
const u8 flag1 = memory.Read_U8(request.buffer_in + 7);
const u8 flag2 = memory.Read_U8(request.buffer_in + 11);
const u32 length = memory.Read_U32(request.buffer_in + 12);
const u32 position = memory.Read_U32(request.buffer_in + 16);
INFO_LOG_FMT(IOS_DI, "DVDLowReadDvd({}, {}): position {:#08x}, length {:#08x}", flag1, flag2,
position, length);
DICMDBUF0 = 0xD0000000 | ((flag1 & 1) << 7) | ((flag2 & 1) << 6);
@@ -427,9 +445,9 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
}
case DIIoctl::DVDLowReadDvdConfig:
{
const u8 flag1 = Memory::Read_U8(request.buffer_in + 7);
const u8 param2 = Memory::Read_U8(request.buffer_in + 11);
const u32 position = Memory::Read_U32(request.buffer_in + 12);
const u8 flag1 = memory.Read_U8(request.buffer_in + 7);
const u8 param2 = memory.Read_U8(request.buffer_in + 11);
const u32 position = memory.Read_U32(request.buffer_in + 12);
INFO_LOG_FMT(IOS_DI, "DVDLowReadDvdConfig({}, {}): position {:#08x}", flag1, param2, position);
DICMDBUF0 = 0xD1000000 | ((flag1 & 1) << 16) | param2;
DICMDBUF1 = position & 0xFFFFFF;
@@ -442,8 +460,8 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
return StartImmediateTransfer(request);
case DIIoctl::DVDLowOffset:
{
const u8 flag = Memory::Read_U8(request.buffer_in + 7);
const u32 offset = Memory::Read_U32(request.buffer_in + 8);
const u8 flag = memory.Read_U8(request.buffer_in + 7);
const u32 offset = memory.Read_U32(request.buffer_in + 8);
INFO_LOG_FMT(IOS_DI, "DVDLowOffset({}): offset {:#010x}", flag, offset);
DICMDBUF0 = 0xD9000000 | ((flag & 1) << 16);
DICMDBUF1 = offset;
@@ -463,15 +481,15 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
return StartImmediateTransfer(request);
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);
DICMDBUF0 = 0xDD000000 | ((speed & 3) << 16);
return StartImmediateTransfer(request, false);
}
case DIIoctl::DVDLowSerMeasControl:
{
const u8 flag1 = Memory::Read_U8(request.buffer_in + 7);
const u8 flag2 = Memory::Read_U8(request.buffer_in + 11);
const u8 flag1 = memory.Read_U8(request.buffer_in + 7);
const u8 flag2 = memory.Read_U8(request.buffer_in + 11);
INFO_LOG_FMT(IOS_DI, "DVDLowSerMeasControl({}, {})", flag1, flag2);
DICMDBUF0 = 0xDF000000 | ((flag1 & 1) << 17) | ((flag2 & 1) << 16);
return StartDMATransfer(0x20, request);
@@ -482,9 +500,9 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
return StartImmediateTransfer(request);
case DIIoctl::DVDLowAudioStream:
{
const u8 mode = Memory::Read_U8(request.buffer_in + 7);
const u32 length = Memory::Read_U32(request.buffer_in + 8);
const u32 position = Memory::Read_U32(request.buffer_in + 12);
const u8 mode = memory.Read_U8(request.buffer_in + 7);
const u32 length = memory.Read_U32(request.buffer_in + 8);
const u32 position = memory.Read_U32(request.buffer_in + 12);
INFO_LOG_FMT(IOS_DI, "DVDLowAudioStream({}): offset {:#010x} (byte {:#011x}), length {:#x}",
mode, position, static_cast<u64>(position) << 2, length);
DICMDBUF0 = 0xE1000000 | ((mode & 3) << 16);
@@ -494,7 +512,7 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
}
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);
DICMDBUF0 = 0xE2000000 | ((mode & 3) << 16);
DICMDBUF1 = 0;
@@ -504,17 +522,17 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
}
case DIIoctl::DVDLowStopMotor:
{
const u8 eject = Memory::Read_U8(request.buffer_in + 7);
const u8 kill = Memory::Read_U8(request.buffer_in + 11);
const u8 eject = memory.Read_U8(request.buffer_in + 7);
const u8 kill = memory.Read_U8(request.buffer_in + 11);
INFO_LOG_FMT(IOS_DI, "DVDLowStopMotor({}, {})", eject, kill);
DICMDBUF0 = 0xE3000000 | ((eject & 1) << 17) | ((kill & 1) << 20);
DICMDBUF1 = 0;
return StartImmediateTransfer(request);
}
case DIIoctl::DVDLowAudioBufferConfig:
{
const u8 enable = Memory::Read_U8(request.buffer_in + 7);
const u8 buffer_size = Memory::Read_U8(request.buffer_in + 11);
const u8 enable = memory.Read_U8(request.buffer_in + 7);
const u8 buffer_size = memory.Read_U8(request.buffer_in + 11);
INFO_LOG_FMT(IOS_DI, "DVDLowAudioBufferConfig: {}, buffer size {}",
enable ? "enabled" : "disabled", buffer_size);
DICMDBUF0 = 0xE4000000 | ((enable & 1) << 16) | (buffer_size & 0xf);
@@ -643,9 +661,12 @@ void DIDevice::FinishDICommand(DIResult result)
return;
}

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

IOCtlRequest request{m_executing_command->m_request_address};
if (m_executing_command->m_copy_diimmbuf)
Memory::Write_U32(DIIMMBUF, request.buffer_out);
memory.Write_U32(DIIMMBUF, request.buffer_out);

m_ios.EnqueueIPCReply(request, static_cast<s32>(result));

@@ -672,7 +693,11 @@ std::optional<IPCReply> DIDevice::IOCtlV(const IOCtlVRequest& request)
request.in_vectors[0].size);
return IPCReply{static_cast<s32>(DIResult::BadArgument)};
}
const u8 command = Memory::Read_U8(request.in_vectors[0].address);

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const u8 command = memory.Read_U8(request.in_vectors[0].address);
if (request.request != command)
{
WARN_LOG_FMT(
@@ -708,18 +733,18 @@ std::optional<IPCReply> DIDevice::IOCtlV(const IOCtlVRequest& request)
}

const u64 partition_offset =
static_cast<u64>(Memory::Read_U32(request.in_vectors[0].address + 4)) << 2;
static_cast<u64>(memory.Read_U32(request.in_vectors[0].address + 4)) << 2;
ChangePartition(DiscIO::Partition(partition_offset));

INFO_LOG_FMT(IOS_DI, "DVDLowOpenPartition: partition_offset {:#011x}", partition_offset);

// Read TMD to the buffer
const ES::TMDReader tmd = DVDThread::GetTMD(m_current_partition);
const std::vector<u8>& raw_tmd = tmd.GetBytes();
Memory::CopyToEmu(request.io_vectors[0].address, raw_tmd.data(), raw_tmd.size());
memory.CopyToEmu(request.io_vectors[0].address, raw_tmd.data(), raw_tmd.size());

ReturnCode es_result = m_ios.GetES()->DIVerify(tmd, DVDThread::GetTicket(m_current_partition));
Memory::Write_U32(es_result, request.io_vectors[1].address);
memory.Write_U32(es_result, request.io_vectors[1].address);

return_value = DIResult::Success;
break;
@@ -12,19 +12,24 @@
#include "Core/HW/Memmap.h"
#include "Core/HW/SystemTimers.h"
#include "Core/IOS/IOS.h"
#include "Core/System.h"

namespace IOS::HLE
{
Request::Request(const u32 address_) : address(address_)
{
command = static_cast<IPCCommandType>(Memory::Read_U32(address));
fd = Memory::Read_U32(address + 8);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
command = static_cast<IPCCommandType>(memory.Read_U32(address));
fd = memory.Read_U32(address + 8);
}

OpenRequest::OpenRequest(const u32 address_) : Request(address_)
{
path = Memory::GetString(Memory::Read_U32(address + 0xc));
flags = static_cast<OpenMode>(Memory::Read_U32(address + 0x10));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
path = memory.GetString(memory.Read_U32(address + 0xc));
flags = static_cast<OpenMode>(memory.Read_U32(address + 0x10));
const Kernel* ios = GetIOS();
if (ios)
{
@@ -35,38 +40,46 @@ OpenRequest::OpenRequest(const u32 address_) : Request(address_)

ReadWriteRequest::ReadWriteRequest(const u32 address_) : Request(address_)
{
buffer = Memory::Read_U32(address + 0xc);
size = Memory::Read_U32(address + 0x10);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
buffer = memory.Read_U32(address + 0xc);
size = memory.Read_U32(address + 0x10);
}

SeekRequest::SeekRequest(const u32 address_) : Request(address_)
{
offset = Memory::Read_U32(address + 0xc);
mode = static_cast<SeekMode>(Memory::Read_U32(address + 0x10));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
offset = memory.Read_U32(address + 0xc);
mode = static_cast<SeekMode>(memory.Read_U32(address + 0x10));
}

IOCtlRequest::IOCtlRequest(const u32 address_) : Request(address_)
{
request = Memory::Read_U32(address + 0x0c);
buffer_in = Memory::Read_U32(address + 0x10);
buffer_in_size = Memory::Read_U32(address + 0x14);
buffer_out = Memory::Read_U32(address + 0x18);
buffer_out_size = Memory::Read_U32(address + 0x1c);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
request = memory.Read_U32(address + 0x0c);
buffer_in = memory.Read_U32(address + 0x10);
buffer_in_size = memory.Read_U32(address + 0x14);
buffer_out = memory.Read_U32(address + 0x18);
buffer_out_size = memory.Read_U32(address + 0x1c);
}

IOCtlVRequest::IOCtlVRequest(const u32 address_) : Request(address_)
{
request = Memory::Read_U32(address + 0x0c);
const u32 in_number = Memory::Read_U32(address + 0x10);
const u32 out_number = Memory::Read_U32(address + 0x14);
const u32 vectors_base = Memory::Read_U32(address + 0x18); // address to vectors
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
request = memory.Read_U32(address + 0x0c);
const u32 in_number = memory.Read_U32(address + 0x10);
const u32 out_number = memory.Read_U32(address + 0x14);
const u32 vectors_base = memory.Read_U32(address + 0x18); // address to vectors

u32 offset = 0;
for (size_t i = 0; i < (in_number + out_number); ++i)
{
IOVector vector;
vector.address = Memory::Read_U32(vectors_base + offset);
vector.size = Memory::Read_U32(vectors_base + offset + 4);
vector.address = memory.Read_U32(vectors_base + offset);
vector.size = memory.Read_U32(vectors_base + offset + 4);
offset += 8;
if (i < in_number)
in_vectors.emplace_back(vector);
@@ -104,11 +117,14 @@ void IOCtlRequest::Log(std::string_view device_name, Common::Log::LogType type,
void IOCtlRequest::Dump(const std::string& description, Common::Log::LogType type,
Common::Log::LogLevel level) const
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

Log("===== " + description, type, level);
GENERIC_LOG_FMT(type, level, "In buffer\n{}",
HexDump(Memory::GetPointer(buffer_in), buffer_in_size));
HexDump(memory.GetPointer(buffer_in), buffer_in_size));
GENERIC_LOG_FMT(type, level, "Out buffer\n{}",
HexDump(Memory::GetPointer(buffer_out), buffer_out_size));
HexDump(memory.GetPointer(buffer_out), buffer_out_size));
}

void IOCtlRequest::DumpUnknown(const std::string& description, Common::Log::LogType type,
@@ -120,14 +136,17 @@ void IOCtlRequest::DumpUnknown(const std::string& description, Common::Log::LogT
void IOCtlVRequest::Dump(std::string_view description, Common::Log::LogType type,
Common::Log::LogLevel level) const
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

GENERIC_LOG_FMT(type, level, "===== {} (fd {}) - IOCtlV {:#x} ({} in, {} io)", description, fd,
request, in_vectors.size(), io_vectors.size());

size_t i = 0;
for (const auto& vector : in_vectors)
{
GENERIC_LOG_FMT(type, level, "in[{}] (size={:#x}):\n{}", i++, vector.size,
HexDump(Memory::GetPointer(vector.address), vector.size));
HexDump(memory.GetPointer(vector.address), vector.size));
}

i = 0;
@@ -19,6 +19,7 @@
#include "Core/Core.h"
#include "Core/HW/Memmap.h"
#include "Core/Host.h"
#include "Core/System.h"

namespace IOS::HLE
{
@@ -48,8 +49,10 @@ IPCReply GetVersion(const IOCtlVRequest& request)

const auto length = std::min(size_t(request.io_vectors[0].size), Common::GetScmDescStr().size());

Memory::Memset(request.io_vectors[0].address, 0, request.io_vectors[0].size);
Memory::CopyToEmu(request.io_vectors[0].address, Common::GetScmDescStr().data(), length);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Memset(request.io_vectors[0].address, 0, request.io_vectors[0].size);
memory.CopyToEmu(request.io_vectors[0].address, Common::GetScmDescStr().data(), length);

return IPCReply(IPC_SUCCESS);
}
@@ -71,7 +74,9 @@ IPCReply GetCPUSpeed(const IOCtlVRequest& request)

const u32 core_clock = u32(float(SystemTimers::GetTicksPerSecond()) * oc);

Memory::Write_U32(core_clock, request.io_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(core_clock, request.io_vectors[0].address);

return IPCReply(IPC_SUCCESS);
}
@@ -90,7 +95,10 @@ IPCReply GetSpeedLimit(const IOCtlVRequest& request)
}

const u32 speed_percent = Config::Get(Config::MAIN_EMULATION_SPEED) * 100;
Memory::Write_U32(speed_percent, request.io_vectors[0].address);

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(speed_percent, request.io_vectors[0].address);

return IPCReply(IPC_SUCCESS);
}
@@ -108,7 +116,9 @@ IPCReply SetSpeedLimit(const IOCtlVRequest& request)
return IPCReply(IPC_EINVAL);
}

const float speed = float(Memory::Read_U32(request.in_vectors[0].address)) / 100.0f;
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const float speed = float(memory.Read_U32(request.in_vectors[0].address)) / 100.0f;
Config::SetCurrent(Config::MAIN_EMULATION_SPEED, speed);

return IPCReply(IPC_SUCCESS);
@@ -140,8 +150,10 @@ IPCReply GetRealProductCode(const IOCtlVRequest& request)
if (length == 0)
return IPCReply(IPC_ENOENT);

Memory::Memset(request.io_vectors[0].address, 0, request.io_vectors[0].size);
Memory::CopyToEmu(request.io_vectors[0].address, code.c_str(), length);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Memset(request.io_vectors[0].address, 0, request.io_vectors[0].size);
memory.CopyToEmu(request.io_vectors[0].address, code.c_str(), length);
return IPCReply(IPC_SUCCESS);
}

@@ -153,8 +165,10 @@ IPCReply SetDiscordClient(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(1, 0))
return IPCReply(IPC_EINVAL);

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
std::string new_client_id =
Memory::GetString(request.in_vectors[0].address, request.in_vectors[0].size);
memory.GetString(request.in_vectors[0].address, request.in_vectors[0].size);

Host_UpdateDiscordClientID(new_client_id);

@@ -169,22 +183,24 @@ IPCReply SetDiscordPresence(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(10, 0))
return IPCReply(IPC_EINVAL);

std::string details =
Memory::GetString(request.in_vectors[0].address, request.in_vectors[0].size);
std::string state = Memory::GetString(request.in_vectors[1].address, request.in_vectors[1].size);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

std::string details = memory.GetString(request.in_vectors[0].address, request.in_vectors[0].size);
std::string state = memory.GetString(request.in_vectors[1].address, request.in_vectors[1].size);
std::string large_image_key =
Memory::GetString(request.in_vectors[2].address, request.in_vectors[2].size);
memory.GetString(request.in_vectors[2].address, request.in_vectors[2].size);
std::string large_image_text =
Memory::GetString(request.in_vectors[3].address, request.in_vectors[3].size);
memory.GetString(request.in_vectors[3].address, request.in_vectors[3].size);
std::string small_image_key =
Memory::GetString(request.in_vectors[4].address, request.in_vectors[4].size);
memory.GetString(request.in_vectors[4].address, request.in_vectors[4].size);
std::string small_image_text =
Memory::GetString(request.in_vectors[5].address, request.in_vectors[5].size);
memory.GetString(request.in_vectors[5].address, request.in_vectors[5].size);

int64_t start_timestamp = Memory::Read_U64(request.in_vectors[6].address);
int64_t end_timestamp = Memory::Read_U64(request.in_vectors[7].address);
int party_size = Memory::Read_U32(request.in_vectors[8].address);
int party_max = Memory::Read_U32(request.in_vectors[9].address);
int64_t start_timestamp = memory.Read_U64(request.in_vectors[6].address);
int64_t end_timestamp = memory.Read_U64(request.in_vectors[7].address);
int party_size = memory.Read_U32(request.in_vectors[8].address);
int party_max = memory.Read_U32(request.in_vectors[9].address);

bool ret = Host_UpdateDiscordPresenceRaw(details, state, large_image_key, large_image_text,
small_image_key, small_image_text, start_timestamp,
@@ -225,7 +241,11 @@ IPCReply DolphinDevice::GetElapsedTime(const IOCtlVRequest& request) const
// Return elapsed time instead of current timestamp to make buggy emulated code less likely to
// have issues.
const u32 milliseconds = static_cast<u32>(m_timer.ElapsedMs());
Memory::Write_U32(milliseconds, request.io_vectors[0].address);

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(milliseconds, request.io_vectors[0].address);

return IPCReply(IPC_SUCCESS);
}

@@ -241,11 +261,14 @@ IPCReply DolphinDevice::GetSystemTime(const IOCtlVRequest& request) const
return IPCReply(IPC_EINVAL);
}

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

// Write Unix timestamp in milliseconds to memory address
const u64 milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::system_clock::now().time_since_epoch())
.count();
Memory::Write_U64(milliseconds, request.io_vectors[0].address);
memory.Write_U64(milliseconds, request.io_vectors[0].address);
return IPCReply(IPC_SUCCESS);
}

@@ -202,9 +202,12 @@ IPCReply ESDevice::GetTitleDirectory(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(1, 1))
return IPCReply(ES_EINVAL);

const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const u64 title_id = memory.Read_U64(request.in_vectors[0].address);

char* path = reinterpret_cast<char*>(Memory::GetPointer(request.io_vectors[0].address));
char* path = reinterpret_cast<char*>(memory.GetPointer(request.io_vectors[0].address));
sprintf(path, "/title/%08x/%08x/data", static_cast<u32>(title_id >> 32),
static_cast<u32>(title_id));

@@ -230,7 +233,10 @@ IPCReply ESDevice::GetTitleId(const IOCtlVRequest& request)
if (ret != IPC_SUCCESS)
return IPCReply(ret);

Memory::Write_U64(title_id, request.io_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

memory.Write_U64(title_id, request.io_vectors[0].address);
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETTITLEID: {:08x}/{:08x}", static_cast<u32>(title_id >> 32),
static_cast<u32>(title_id));
return IPCReply(IPC_SUCCESS);
@@ -278,7 +284,10 @@ IPCReply ESDevice::SetUID(u32 uid, const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 8)
return IPCReply(ES_EINVAL);

const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const u64 title_id = memory.Read_U64(request.in_vectors[0].address);

const s32 ret = CheckIsAllowedToSetUID(m_ios, uid, m_title_context.tmd);
if (ret < 0)
@@ -707,7 +716,9 @@ IPCReply ESDevice::GetConsumption(const IOCtlVRequest& request)
return IPCReply(ES_EINVAL);

// This is at least what crediar's ES module does
Memory::Write_U32(0, request.io_vectors[1].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(0, request.io_vectors[1].address);
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETCONSUMPTION");
return IPCReply(IPC_SUCCESS);
}
@@ -717,12 +728,15 @@ std::optional<IPCReply> ESDevice::Launch(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(2, 0))
return IPCReply(ES_EINVAL);

const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
const u32 view = Memory::Read_U32(request.in_vectors[1].address);
const u64 ticketid = Memory::Read_U64(request.in_vectors[1].address + 4);
const u32 devicetype = Memory::Read_U32(request.in_vectors[1].address + 12);
const u64 titleid = Memory::Read_U64(request.in_vectors[1].address + 16);
const u16 access = Memory::Read_U16(request.in_vectors[1].address + 24);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
const u32 view = memory.Read_U32(request.in_vectors[1].address);
const u64 ticketid = memory.Read_U64(request.in_vectors[1].address + 4);
const u32 devicetype = memory.Read_U32(request.in_vectors[1].address + 12);
const u64 titleid = memory.Read_U64(request.in_vectors[1].address + 16);
const u16 access = memory.Read_U16(request.in_vectors[1].address + 24);

INFO_LOG_FMT(IOS_ES, "IOCTL_ES_LAUNCH {:016x} {:08x} {:016x} {:08x} {:016x} {:04x}", title_id,
view, ticketid, devicetype, titleid, access);
@@ -936,17 +950,20 @@ IPCReply ESDevice::SetUpStreamKey(const Context& context, const IOCtlVRequest& r
return IPCReply(ES_EINVAL);
}

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

std::vector<u8> tmd_bytes(request.in_vectors[1].size);
Memory::CopyFromEmu(tmd_bytes.data(), request.in_vectors[1].address, tmd_bytes.size());
memory.CopyFromEmu(tmd_bytes.data(), request.in_vectors[1].address, tmd_bytes.size());
const ES::TMDReader tmd{std::move(tmd_bytes)};

if (!tmd.IsValid())
return IPCReply(ES_EINVAL);

u32 handle;
const ReturnCode ret =
SetUpStreamKey(context.uid, Memory::GetPointer(request.in_vectors[0].address), tmd, &handle);
Memory::Write_U32(handle, request.io_vectors[0].address);
SetUpStreamKey(context.uid, memory.GetPointer(request.in_vectors[0].address), tmd, &handle);
memory.Write_U32(handle, request.io_vectors[0].address);
return IPCReply(ret);
}

@@ -955,7 +972,9 @@ IPCReply ESDevice::DeleteStreamKey(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u32))
return IPCReply(ES_EINVAL);

const u32 handle = Memory::Read_U32(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 handle = memory.Read_U32(request.in_vectors[0].address);
return IPCReply(m_ios.GetIOSC().DeleteObject(handle, PID_ES));
}

@@ -15,6 +15,7 @@
#include "Core/IOS/ES/Formats.h"
#include "Core/IOS/IOSC.h"
#include "Core/IOS/Uids.h"
#include "Core/System.h"

namespace IOS::HLE
{
@@ -34,7 +35,10 @@ IPCReply ESDevice::GetDeviceId(const IOCtlVRequest& request)
const ReturnCode ret = GetDeviceId(&device_id);
if (ret != IPC_SUCCESS)
return IPCReply(ret);
Memory::Write_U32(device_id, request.io_vectors[0].address);

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(device_id, request.io_vectors[0].address);
return IPCReply(IPC_SUCCESS);
}

@@ -43,11 +47,13 @@ IPCReply ESDevice::Encrypt(u32 uid, const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(3, 2))
return IPCReply(ES_EINVAL);

u32 keyIndex = Memory::Read_U32(request.in_vectors[0].address);
u8* source = Memory::GetPointer(request.in_vectors[2].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u32 keyIndex = memory.Read_U32(request.in_vectors[0].address);
u8* source = memory.GetPointer(request.in_vectors[2].address);
u32 size = request.in_vectors[2].size;
u8* iv = Memory::GetPointer(request.io_vectors[0].address);
u8* destination = Memory::GetPointer(request.io_vectors[1].address);
u8* iv = memory.GetPointer(request.io_vectors[0].address);
u8* destination = memory.GetPointer(request.io_vectors[1].address);

// TODO: Check whether the active title is allowed to encrypt.

@@ -60,11 +66,13 @@ IPCReply ESDevice::Decrypt(u32 uid, const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(3, 2))
return IPCReply(ES_EINVAL);

u32 keyIndex = Memory::Read_U32(request.in_vectors[0].address);
u8* source = Memory::GetPointer(request.in_vectors[2].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u32 keyIndex = memory.Read_U32(request.in_vectors[0].address);
u8* source = memory.GetPointer(request.in_vectors[2].address);
u32 size = request.in_vectors[2].size;
u8* iv = Memory::GetPointer(request.io_vectors[0].address);
u8* destination = Memory::GetPointer(request.io_vectors[1].address);
u8* iv = memory.GetPointer(request.io_vectors[0].address);
u8* destination = memory.GetPointer(request.io_vectors[1].address);

// TODO: Check whether the active title is allowed to decrypt.

@@ -92,8 +100,10 @@ IPCReply ESDevice::GetDeviceCertificate(const IOCtlVRequest& request)

INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETDEVICECERT");

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const IOS::CertECC cert = m_ios.GetIOSC().GetDeviceCertificate();
Memory::CopyToEmu(request.io_vectors[0].address, &cert, sizeof(cert));
memory.CopyToEmu(request.io_vectors[0].address, &cert, sizeof(cert));
return IPCReply(IPC_SUCCESS);
}

@@ -103,10 +113,12 @@ IPCReply ESDevice::Sign(const IOCtlVRequest& request)
return IPCReply(ES_EINVAL);

INFO_LOG_FMT(IOS_ES, "IOCTL_ES_SIGN");
u8* ap_cert_out = Memory::GetPointer(request.io_vectors[1].address);
u8* data = Memory::GetPointer(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u8* ap_cert_out = memory.GetPointer(request.io_vectors[1].address);
u8* data = memory.GetPointer(request.in_vectors[0].address);
u32 data_size = request.in_vectors[0].size;
u8* sig_out = Memory::GetPointer(request.io_vectors[0].address);
u8* sig_out = memory.GetPointer(request.io_vectors[0].address);

if (!m_title_context.active)
return IPCReply(ES_EINVAL);
@@ -193,14 +205,17 @@ IPCReply ESDevice::VerifySign(const IOCtlVRequest& request)
if (request.in_vectors[1].size != sizeof(Common::ec::Signature))
return IPCReply(ES_EINVAL);

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

std::vector<u8> hash(request.in_vectors[0].size);
Memory::CopyFromEmu(hash.data(), request.in_vectors[0].address, hash.size());
memory.CopyFromEmu(hash.data(), request.in_vectors[0].address, hash.size());

std::vector<u8> ecc_signature(request.in_vectors[1].size);
Memory::CopyFromEmu(ecc_signature.data(), request.in_vectors[1].address, ecc_signature.size());
memory.CopyFromEmu(ecc_signature.data(), request.in_vectors[1].address, ecc_signature.size());

std::vector<u8> certs(request.in_vectors[2].size);
Memory::CopyFromEmu(certs.data(), request.in_vectors[2].address, certs.size());
memory.CopyFromEmu(certs.data(), request.in_vectors[2].address, certs.size());

return IPCReply(VerifySign(hash, ecc_signature, certs));
}
@@ -10,6 +10,7 @@
#include "Core/IOS/ES/Formats.h"
#include "Core/IOS/FS/FileSystemProxy.h"
#include "Core/IOS/Uids.h"
#include "Core/System.h"

namespace IOS::HLE
{
@@ -56,8 +57,10 @@ IPCReply ESDevice::OpenContent(u32 uid, const IOCtlVRequest& request)
return ES_EINVAL;
}

const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
const u32 content_index = Memory::Read_U32(request.in_vectors[2].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
const u32 content_index = memory.Read_U32(request.in_vectors[2].address);
// TODO: check the ticket view, check permissions.

const auto tmd = FindInstalledTMD(title_id, ticks);
@@ -74,7 +77,9 @@ IPCReply ESDevice::OpenActiveTitleContent(u32 caller_uid, const IOCtlVRequest& r
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u32))
return ES_EINVAL;

const u32 content_index = Memory::Read_U32(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 content_index = memory.Read_U32(request.in_vectors[0].address);

if (!m_title_context.active)
return ES_EINVAL;
@@ -109,13 +114,15 @@ IPCReply ESDevice::ReadContent(u32 uid, const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
return ES_EINVAL;

const u32 cfd = Memory::Read_U32(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 cfd = memory.Read_U32(request.in_vectors[0].address);
const u32 size = request.io_vectors[0].size;
const u32 addr = request.io_vectors[0].address;

INFO_LOG_FMT(IOS_ES, "ReadContent(uid={:#x}, cfd={}, size={}, addr={:08x})", uid, cfd, size,
addr);
return ReadContent(cfd, Memory::GetPointer(addr), size, uid, ticks);
return ReadContent(cfd, memory.GetPointer(addr), size, uid, ticks);
});
}

@@ -142,7 +149,9 @@ IPCReply ESDevice::CloseContent(u32 uid, const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u32))
return ES_EINVAL;

const u32 cfd = Memory::Read_U32(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 cfd = memory.Read_U32(request.in_vectors[0].address);
return CloseContent(cfd, uid, ticks);
});
}
@@ -167,9 +176,11 @@ IPCReply ESDevice::SeekContent(u32 uid, const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(3, 0))
return ES_EINVAL;

const u32 cfd = Memory::Read_U32(request.in_vectors[0].address);
const u32 offset = Memory::Read_U32(request.in_vectors[1].address);
const auto mode = static_cast<SeekMode>(Memory::Read_U32(request.in_vectors[2].address));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 cfd = memory.Read_U32(request.in_vectors[0].address);
const u32 offset = memory.Read_U32(request.in_vectors[1].address);
const auto mode = static_cast<SeekMode>(memory.Read_U32(request.in_vectors[2].address));

return SeekContent(cfd, offset, mode, uid, ticks);
});
@@ -10,6 +10,7 @@
#include "Common/Logging/Log.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/ES/Formats.h"
#include "Core/System.h"

namespace IOS::HLE
{
@@ -21,7 +22,9 @@ IPCReply ESDevice::GetStoredContentsCount(const ES::TMDReader& tmd, const IOCtlV
return IPCReply(ES_EINVAL);

const u16 num_contents = static_cast<u16>(GetStoredContentsFromTMD(tmd).size());
Memory::Write_U32(num_contents, request.io_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(num_contents, request.io_vectors[0].address);

INFO_LOG_FMT(IOS_ES, "GetStoredContentsCount ({:#x}): {} content(s) for {:016x}",
request.request, num_contents, tmd.GetTitleId());
@@ -35,16 +38,18 @@ IPCReply ESDevice::GetStoredContents(const ES::TMDReader& tmd, const IOCtlVReque
if (!tmd.IsValid())
return IPCReply(ES_EINVAL);

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
if (request.in_vectors[1].size != sizeof(u32) ||
request.io_vectors[0].size != Memory::Read_U32(request.in_vectors[1].address) * sizeof(u32))
request.io_vectors[0].size != memory.Read_U32(request.in_vectors[1].address) * sizeof(u32))
{
return IPCReply(ES_EINVAL);
}

const auto contents = GetStoredContentsFromTMD(tmd);
const u32 max_content_count = Memory::Read_U32(request.in_vectors[1].address);
const u32 max_content_count = memory.Read_U32(request.in_vectors[1].address);
for (u32 i = 0; i < std::min(static_cast<u32>(contents.size()), max_content_count); ++i)
Memory::Write_U32(contents[i].id, request.io_vectors[0].address + i * sizeof(u32));
memory.Write_U32(contents[i].id, request.io_vectors[0].address + i * sizeof(u32));

return IPCReply(IPC_SUCCESS);
}
@@ -54,7 +59,9 @@ IPCReply ESDevice::GetStoredContentsCount(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u64))
return IPCReply(ES_EINVAL);

const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
const ES::TMDReader tmd = FindInstalledTMD(title_id);
if (!tmd.IsValid())
return IPCReply(FS_ENOENT);
@@ -66,7 +73,9 @@ IPCReply ESDevice::GetStoredContents(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(2, 1) || request.in_vectors[0].size != sizeof(u64))
return IPCReply(ES_EINVAL);

const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
const ES::TMDReader tmd = FindInstalledTMD(title_id);
if (!tmd.IsValid())
return IPCReply(FS_ENOENT);
@@ -79,7 +88,9 @@ IPCReply ESDevice::GetTMDStoredContentsCount(const IOCtlVRequest& request)
return IPCReply(ES_EINVAL);

std::vector<u8> tmd_bytes(request.in_vectors[0].size);
Memory::CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
return GetStoredContentsCount(ES::TMDReader{std::move(tmd_bytes)}, request);
}

@@ -89,7 +100,9 @@ IPCReply ESDevice::GetTMDStoredContents(const IOCtlVRequest& request)
return IPCReply(ES_EINVAL);

std::vector<u8> tmd_bytes(request.in_vectors[0].size);
Memory::CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());

const ES::TMDReader tmd{std::move(tmd_bytes)};
if (!tmd.IsValid())
@@ -112,7 +125,9 @@ IPCReply ESDevice::GetTitleCount(const std::vector<u64>& titles, const IOCtlVReq
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != 4)
return IPCReply(ES_EINVAL);

Memory::Write_U32(static_cast<u32>(titles.size()), request.io_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(static_cast<u32>(titles.size()), request.io_vectors[0].address);

return IPCReply(IPC_SUCCESS);
}
@@ -122,10 +137,12 @@ IPCReply ESDevice::GetTitles(const std::vector<u64>& titles, const IOCtlVRequest
if (!request.HasNumberOfValidVectors(1, 1))
return IPCReply(ES_EINVAL);

const size_t max_count = Memory::Read_U32(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const size_t max_count = memory.Read_U32(request.in_vectors[0].address);
for (size_t i = 0; i < std::min(max_count, titles.size()); i++)
{
Memory::Write_U64(titles[i], request.io_vectors[0].address + static_cast<u32>(i) * sizeof(u64));
memory.Write_U64(titles[i], request.io_vectors[0].address + static_cast<u32>(i) * sizeof(u64));
INFO_LOG_FMT(IOS_ES, " title {:016x}", titles[i]);
}
return IPCReply(IPC_SUCCESS);
@@ -148,13 +165,15 @@ IPCReply ESDevice::GetStoredTMDSize(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(1, 1))
return IPCReply(ES_EINVAL);

const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
const ES::TMDReader tmd = FindInstalledTMD(title_id);
if (!tmd.IsValid())
return IPCReply(FS_ENOENT);

const u32 tmd_size = static_cast<u32>(tmd.GetBytes().size());
Memory::Write_U32(tmd_size, request.io_vectors[0].address);
memory.Write_U32(tmd_size, request.io_vectors[0].address);

INFO_LOG_FMT(IOS_ES, "GetStoredTMDSize: {} bytes for {:016x}", tmd_size, title_id);

@@ -166,19 +185,21 @@ IPCReply ESDevice::GetStoredTMD(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(2, 1))
return IPCReply(ES_EINVAL);

const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
const ES::TMDReader tmd = FindInstalledTMD(title_id);
if (!tmd.IsValid())
return IPCReply(FS_ENOENT);

// TODO: actually use this param in when writing to the outbuffer :/
const u32 MaxCount = Memory::Read_U32(request.in_vectors[1].address);
const u32 MaxCount = memory.Read_U32(request.in_vectors[1].address);

const std::vector<u8>& raw_tmd = tmd.GetBytes();
if (raw_tmd.size() != request.io_vectors[0].size)
return IPCReply(ES_EINVAL);

Memory::CopyToEmu(request.io_vectors[0].address, raw_tmd.data(), raw_tmd.size());
memory.CopyToEmu(request.io_vectors[0].address, raw_tmd.data(), raw_tmd.size());

INFO_LOG_FMT(IOS_ES, "GetStoredTMD: title {:016x} (buffer size: {})", title_id, MaxCount);
return IPCReply(IPC_SUCCESS);
@@ -204,7 +225,9 @@ IPCReply ESDevice::GetBoot2Version(const IOCtlVRequest& request)
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETBOOT2VERSION");

// as of 26/02/2012, this was latest bootmii version
Memory::Write_U32(4, request.io_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(4, request.io_vectors[0].address);
return IPCReply(IPC_SUCCESS);
}

@@ -214,7 +237,9 @@ IPCReply ESDevice::GetSharedContentsCount(const IOCtlVRequest& request) const
return IPCReply(ES_EINVAL);

const u32 count = GetSharedContentsCount();
Memory::Write_U32(count, request.io_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(count, request.io_vectors[0].address);

INFO_LOG_FMT(IOS_ES, "GetSharedContentsCount: {} contents", count);
return IPCReply(IPC_SUCCESS);
@@ -225,13 +250,15 @@ IPCReply ESDevice::GetSharedContents(const IOCtlVRequest& request) const
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
return IPCReply(ES_EINVAL);

const u32 max_count = Memory::Read_U32(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 max_count = memory.Read_U32(request.in_vectors[0].address);
if (request.io_vectors[0].size != 20 * max_count)
return IPCReply(ES_EINVAL);

const std::vector<std::array<u8, 20>> hashes = GetSharedContents();
const u32 count = std::min(static_cast<u32>(hashes.size()), max_count);
Memory::CopyToEmu(request.io_vectors[0].address, hashes.data(), 20 * count);
memory.CopyToEmu(request.io_vectors[0].address, hashes.data(), 20 * count);

INFO_LOG_FMT(IOS_ES, "GetSharedContents: {} contents ({} requested)", count, max_count);
return IPCReply(IPC_SUCCESS);
@@ -19,6 +19,7 @@
#include "Core/IOS/ES/Formats.h"
#include "Core/IOS/FS/FileSystem.h"
#include "Core/IOS/Uids.h"
#include "Core/System.h"

namespace IOS::HLE
{
@@ -97,10 +98,13 @@ IPCReply ESDevice::ImportTicket(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(3, 0))
return IPCReply(ES_EINVAL);

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

std::vector<u8> bytes(request.in_vectors[0].size);
Memory::CopyFromEmu(bytes.data(), request.in_vectors[0].address, request.in_vectors[0].size);
memory.CopyFromEmu(bytes.data(), request.in_vectors[0].address, request.in_vectors[0].size);
std::vector<u8> cert_chain(request.in_vectors[1].size);
Memory::CopyFromEmu(cert_chain.data(), request.in_vectors[1].address, request.in_vectors[1].size);
memory.CopyFromEmu(cert_chain.data(), request.in_vectors[1].address, request.in_vectors[1].size);
return IPCReply(ImportTicket(bytes, cert_chain));
}

@@ -187,8 +191,11 @@ IPCReply ESDevice::ImportTmd(Context& context, const IOCtlVRequest& request)
if (!ES::IsValidTMDSize(request.in_vectors[0].size))
return IPCReply(ES_EINVAL);

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

std::vector<u8> tmd(request.in_vectors[0].size);
Memory::CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
memory.CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
return IPCReply(ImportTmd(context, tmd, m_title_context.tmd.GetTitleId(),
m_title_context.tmd.GetTitleFlags()));
}
@@ -273,10 +280,13 @@ IPCReply ESDevice::ImportTitleInit(Context& context, const IOCtlVRequest& reques
if (!ES::IsValidTMDSize(request.in_vectors[0].size))
return IPCReply(ES_EINVAL);

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

std::vector<u8> tmd(request.in_vectors[0].size);
Memory::CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
memory.CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
std::vector<u8> certs(request.in_vectors[1].size);
Memory::CopyFromEmu(certs.data(), request.in_vectors[1].address, request.in_vectors[1].size);
memory.CopyFromEmu(certs.data(), request.in_vectors[1].address, request.in_vectors[1].size);
return IPCReply(ImportTitleInit(context, tmd, certs));
}

@@ -328,8 +338,11 @@ IPCReply ESDevice::ImportContentBegin(Context& context, const IOCtlVRequest& req
if (!request.HasNumberOfValidVectors(2, 0))
return IPCReply(ES_EINVAL);

u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
u32 content_id = Memory::Read_U32(request.in_vectors[1].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

u64 title_id = memory.Read_U64(request.in_vectors[0].address);
u32 content_id = memory.Read_U32(request.in_vectors[1].address);
return IPCReply(ImportContentBegin(context, title_id, content_id));
}

@@ -347,8 +360,11 @@ IPCReply ESDevice::ImportContentData(Context& context, const IOCtlVRequest& requ
if (!request.HasNumberOfValidVectors(2, 0))
return IPCReply(ES_EINVAL);

u32 content_fd = Memory::Read_U32(request.in_vectors[0].address);
u8* data_start = Memory::GetPointer(request.in_vectors[1].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

u32 content_fd = memory.Read_U32(request.in_vectors[0].address);
u8* data_start = memory.GetPointer(request.in_vectors[1].address);
return IPCReply(ImportContentData(context, content_fd, data_start, request.in_vectors[1].size));
}

@@ -430,7 +446,10 @@ IPCReply ESDevice::ImportContentEnd(Context& context, const IOCtlVRequest& reque
if (!request.HasNumberOfValidVectors(1, 0))
return IPCReply(ES_EINVAL);

u32 content_fd = Memory::Read_U32(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

u32 content_fd = memory.Read_U32(request.in_vectors[0].address);
return IPCReply(ImportContentEnd(context, content_fd));
}

@@ -542,7 +561,10 @@ IPCReply ESDevice::DeleteTitle(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 8)
return IPCReply(ES_EINVAL);

const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
return IPCReply(DeleteTitle(title_id));
}

@@ -595,7 +617,10 @@ IPCReply ESDevice::DeleteTicket(const IOCtlVRequest& request)
{
return IPCReply(ES_EINVAL);
}
return IPCReply(DeleteTicket(Memory::GetPointer(request.in_vectors[0].address)));

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
return IPCReply(DeleteTicket(memory.GetPointer(request.in_vectors[0].address)));
}

ReturnCode ESDevice::DeleteTitleContent(u64 title_id) const
@@ -621,7 +646,10 @@ IPCReply ESDevice::DeleteTitleContent(const IOCtlVRequest& request)
{
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u64))
return IPCReply(ES_EINVAL);
return IPCReply(DeleteTitleContent(Memory::Read_U64(request.in_vectors[0].address)));

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
return IPCReply(DeleteTitleContent(memory.Read_U64(request.in_vectors[0].address)));
}

ReturnCode ESDevice::DeleteContent(u64 title_id, u32 content_id) const
@@ -649,8 +677,11 @@ IPCReply ESDevice::DeleteContent(const IOCtlVRequest& request)
{
return IPCReply(ES_EINVAL);
}
return IPCReply(DeleteContent(Memory::Read_U64(request.in_vectors[0].address),
Memory::Read_U32(request.in_vectors[1].address)));

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
return IPCReply(DeleteContent(memory.Read_U64(request.in_vectors[0].address),
memory.Read_U32(request.in_vectors[1].address)));
}

ReturnCode ESDevice::ExportTitleInit(Context& context, u64 title_id, u8* tmd_bytes, u32 tmd_size,
@@ -687,8 +718,11 @@ IPCReply ESDevice::ExportTitleInit(Context& context, const IOCtlVRequest& reques
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != 8)
return IPCReply(ES_EINVAL);

const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
u8* tmd_bytes = Memory::GetPointer(request.io_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
u8* tmd_bytes = memory.GetPointer(request.io_vectors[0].address);
const u32 tmd_size = request.io_vectors[0].size;

return IPCReply(ExportTitleInit(context, title_id, tmd_bytes, tmd_size,
@@ -733,8 +767,11 @@ IPCReply ESDevice::ExportContentBegin(Context& context, const IOCtlVRequest& req
request.in_vectors[1].size != 4)
return IPCReply(ES_EINVAL);

const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
const u32 content_id = Memory::Read_U32(request.in_vectors[1].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
const u32 content_id = memory.Read_U32(request.in_vectors[1].address);

return IPCReply(ExportContentBegin(context, title_id, content_id));
}
@@ -781,8 +818,11 @@ IPCReply ESDevice::ExportContentData(Context& context, const IOCtlVRequest& requ
return IPCReply(ES_EINVAL);
}

const u32 content_fd = Memory::Read_U32(request.in_vectors[0].address);
u8* data = Memory::GetPointer(request.io_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const u32 content_fd = memory.Read_U32(request.in_vectors[0].address);
u8* data = memory.GetPointer(request.io_vectors[0].address);
const u32 bytes_to_read = request.io_vectors[0].size;

return IPCReply(ExportContentData(context, content_fd, data, bytes_to_read));
@@ -800,7 +840,10 @@ IPCReply ESDevice::ExportContentEnd(Context& context, const IOCtlVRequest& reque
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 4)
return IPCReply(ES_EINVAL);

const u32 content_fd = Memory::Read_U32(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

const u32 content_fd = memory.Read_U32(request.in_vectors[0].address);
return IPCReply(ExportContentEnd(context, content_fd));
}

@@ -857,7 +900,11 @@ IPCReply ESDevice::DeleteSharedContent(const IOCtlVRequest& request)
std::array<u8, 20> sha1;
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sha1.size())
return IPCReply(ES_EINVAL);
Memory::CopyFromEmu(sha1.data(), request.in_vectors[0].address, request.in_vectors[0].size);

auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();

memory.CopyFromEmu(sha1.data(), request.in_vectors[0].address, request.in_vectors[0].size);
return IPCReply(DeleteSharedContent(sha1));
}
} // namespace IOS::HLE