Merge pull request #11320 from AdmiralCurtiss/globals-memory

HW/Memmap: Refactor Memory to class, move to Core::System.
This commit is contained in:
Mai 2022-12-07 00:52:31 +00:00 committed by GitHub
commit 94faad0d37
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
83 changed files with 2222 additions and 1361 deletions

View file

@ -55,6 +55,7 @@ namespace fs = std::filesystem;
#include "Core/PowerPC/PPCAnalyst.h"
#include "Core/PowerPC/PPCSymbolDB.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
#include "DiscIO/Enums.h"
#include "DiscIO/GameModDescriptor.h"
@ -348,7 +349,10 @@ bool CBoot::DVDRead(const DiscIO::VolumeDisc& disc, u64 dvd_offset, u32 output_a
std::vector<u8> buffer(length);
if (!disc.Read(dvd_offset, length, buffer.data(), partition))
return false;
Memory::CopyToEmu(output_address, buffer.data(), length);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyToEmu(output_address, buffer.data(), length);
return true;
}
@ -357,7 +361,11 @@ bool CBoot::DVDReadDiscID(const DiscIO::VolumeDisc& disc, u32 output_address)
std::array<u8, 0x20> buffer;
if (!disc.Read(0, buffer.size(), buffer.data(), DiscIO::PARTITION_NONE))
return false;
Memory::CopyToEmu(output_address, buffer.data(), buffer.size());
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyToEmu(output_address, buffer.data(), buffer.size());
// Transition out of the DiscIdNotRead state (which the drive should be in at this point,
// on the assumption that this is only used for the first read)
DVDInterface::SetDriveState(DVDInterface::DriveState::ReadyNoReadsMade);
@ -455,8 +463,10 @@ bool CBoot::Load_BS2(const std::string& boot_rom_filename)
// copying the initial boot code to 0x81200000 is a hack.
// For now, HLE the first few instructions and start at 0x81200150
// to work around this.
Memory::CopyToEmu(0x01200000, data.data() + 0x100, 0x700);
Memory::CopyToEmu(0x01300000, data.data() + 0x820, 0x1AFE00);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyToEmu(0x01200000, data.data() + 0x100, 0x700);
memory.CopyToEmu(0x01300000, data.data() + 0x820, 0x1AFE00);
PowerPC::ppcState.gpr[3] = 0xfff0001f;
PowerPC::ppcState.gpr[4] = 0x00002030;
@ -491,9 +501,11 @@ static void CopyDefaultExceptionHandlers()
0x00000900, 0x00000C00, 0x00000D00, 0x00000F00,
0x00001300, 0x00001400, 0x00001700};
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
constexpr u32 RFI_INSTRUCTION = 0x4C000064;
for (const u32 address : EXCEPTION_HANDLER_ADDRESSES)
Memory::Write_U32(RFI_INSTRUCTION, address);
memory.Write_U32(RFI_INSTRUCTION, address);
}
// Third boot step after BootManager and Core. See Call schedule in BootManager.cpp

View file

@ -32,6 +32,7 @@
#include "Core/IOS/Uids.h"
#include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
#include "DiscIO/Enums.h"
#include "DiscIO/RiivolutionPatcher.h"
@ -212,11 +213,14 @@ bool CBoot::RunApploader(bool is_wii, const DiscIO::VolumeDisc& volume,
void CBoot::SetupGCMemory()
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// Booted from bootrom. 0xE5207C22 = booted from jtag
PowerPC::HostWrite_U32(0x0D15EA5E, 0x80000020);
// Physical Memory Size (24MB on retail)
PowerPC::HostWrite_U32(Memory::GetRamSizeReal(), 0x80000028);
PowerPC::HostWrite_U32(memory.GetRamSizeReal(), 0x80000028);
// Console type - DevKit (retail ID == 0x00000003) see YAGCD 4.2.1.1.2
// TODO: determine why some games fail when using a retail ID.
@ -271,10 +275,12 @@ bool CBoot::EmulatedBS2_GC(const DiscIO::VolumeDisc& volume,
DVDReadDiscID(volume, 0x00000000);
bool streaming = Memory::Read_U8(0x80000008);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
bool streaming = memory.Read_U8(0x80000008);
if (streaming)
{
u8 streaming_size = Memory::Read_U8(0x80000009);
u8 streaming_size = memory.Read_U8(0x80000009);
// If the streaming buffer size is 0, then BS2 uses a default size of 10 instead.
// No known game uses a size other than the default.
if (streaming_size == 0)
@ -412,8 +418,11 @@ bool CBoot::SetupWiiMemory(IOS::HLE::IOSC::ConsoleType console_type)
return false;
}
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// Write the 256 byte setting.txt to memory.
Memory::CopyToEmu(0x3800, gen.GetBytes().data(), gen.GetBytes().size());
memory.CopyToEmu(0x3800, gen.GetBytes().data(), gen.GetBytes().size());
INFO_LOG_FMT(BOOT, "Setup Wii Memory...");
@ -427,28 +436,28 @@ bool CBoot::SetupWiiMemory(IOS::HLE::IOSC::ConsoleType console_type)
0x80000060 Copyright code
*/
Memory::Write_U32(0x0D15EA5E, 0x00000020); // Another magic word
Memory::Write_U32(0x00000001, 0x00000024); // Unknown
Memory::Write_U32(Memory::GetRamSizeReal(), 0x00000028); // MEM1 size 24MB
memory.Write_U32(0x0D15EA5E, 0x00000020); // Another magic word
memory.Write_U32(0x00000001, 0x00000024); // Unknown
memory.Write_U32(memory.GetRamSizeReal(), 0x00000028); // MEM1 size 24MB
const Core::ConsoleType board_model = console_type == IOS::HLE::IOSC::ConsoleType::RVT ?
Core::ConsoleType::NDEV2_1 :
Core::ConsoleType::RVL_Retail3;
Memory::Write_U32(static_cast<u32>(board_model), 0x0000002c); // Board Model
Memory::Write_U32(0x00000000, 0x00000030); // Init
Memory::Write_U32(0x817FEC60, 0x00000034); // Init
memory.Write_U32(static_cast<u32>(board_model), 0x0000002c); // Board Model
memory.Write_U32(0x00000000, 0x00000030); // Init
memory.Write_U32(0x817FEC60, 0x00000034); // Init
// 38, 3C should get start, size of FST through apploader
Memory::Write_U32(0x8008f7b8, 0x000000e4); // Thread Init
Memory::Write_U32(Memory::GetRamSizeReal(), 0x000000f0); // "Simulated memory size" (debug mode?)
Memory::Write_U32(0x8179b500, 0x000000f4); // __start
Memory::Write_U32(0x0e7be2c0, 0x000000f8); // Bus speed
Memory::Write_U32(0x2B73A840, 0x000000fc); // CPU speed
Memory::Write_U16(0x0000, 0x000030e6); // Console type
Memory::Write_U32(0x00000000, 0x000030c0); // EXI
Memory::Write_U32(0x00000000, 0x000030c4); // EXI
Memory::Write_U32(0x00000000, 0x000030dc); // Time
Memory::Write_U32(0xffffffff, 0x000030d8); // Unknown, set by any official NAND title
Memory::Write_U16(0x8201, 0x000030e6); // Dev console / debug capable
Memory::Write_U32(0x00000000, 0x000030f0); // Apploader
memory.Write_U32(0x8008f7b8, 0x000000e4); // Thread Init
memory.Write_U32(memory.GetRamSizeReal(), 0x000000f0); // "Simulated memory size" (debug mode?)
memory.Write_U32(0x8179b500, 0x000000f4); // __start
memory.Write_U32(0x0e7be2c0, 0x000000f8); // Bus speed
memory.Write_U32(0x2B73A840, 0x000000fc); // CPU speed
memory.Write_U16(0x0000, 0x000030e6); // Console type
memory.Write_U32(0x00000000, 0x000030c0); // EXI
memory.Write_U32(0x00000000, 0x000030c4); // EXI
memory.Write_U32(0x00000000, 0x000030dc); // Time
memory.Write_U32(0xffffffff, 0x000030d8); // Unknown, set by any official NAND title
memory.Write_U16(0x8201, 0x000030e6); // Dev console / debug capable
memory.Write_U32(0x00000000, 0x000030f0); // Apploader
// During the boot process, 0x315c is first set to 0xdeadbeef by IOS
// in the boot_ppc syscall. The value is then partly overwritten by SDK titles.
@ -457,19 +466,19 @@ bool CBoot::SetupWiiMemory(IOS::HLE::IOSC::ConsoleType console_type)
//
// 0x0113 appears to mean v1.13, which is the latest version.
// It is fine to always use the latest value as apploaders work with all versions.
Memory::Write_U16(0x0113, 0x0000315e);
memory.Write_U16(0x0113, 0x0000315e);
Memory::Write_U8(0x80, 0x0000315c); // OSInit
Memory::Write_U16(0x0000, 0x000030e0); // PADInit
Memory::Write_U32(0x80000000, 0x00003184); // GameID Address
memory.Write_U8(0x80, 0x0000315c); // OSInit
memory.Write_U16(0x0000, 0x000030e0); // PADInit
memory.Write_U32(0x80000000, 0x00003184); // GameID Address
// Fake the VI Init of the IPL
Memory::Write_U32(DiscIO::IsNTSC(SConfig::GetInstance().m_region) ? 0 : 1, 0x000000CC);
memory.Write_U32(DiscIO::IsNTSC(SConfig::GetInstance().m_region) ? 0 : 1, 0x000000CC);
// Clear exception handler. Why? Don't we begin with only zeros?
for (int i = 0x3000; i <= 0x3038; i += 4)
{
Memory::Write_U32(0x00000000, i);
memory.Write_U32(0x00000000, i);
}
return true;
@ -513,6 +522,9 @@ bool CBoot::EmulatedBS2_Wii(const DiscIO::VolumeDisc& volume,
state->discstate = 0x01;
});
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// The system menu clears the RTC flags.
// However, the system menu also updates the disc cache when this happens; see
// https://wiibrew.org/wiki/MX23L4005#DI and
@ -526,8 +538,8 @@ bool CBoot::EmulatedBS2_Wii(const DiscIO::VolumeDisc& volume,
// When launching the disc game, it copies the partition type and offset to 0x3194
// and 0x3198 respectively.
const DiscIO::Partition data_partition = volume.GetGamePartition();
Memory::Write_U32(0, 0x3194);
Memory::Write_U32(static_cast<u32>(data_partition.offset >> 2), 0x3198);
memory.Write_U32(0, 0x3194);
memory.Write_U32(static_cast<u32>(data_partition.offset >> 2), 0x3198);
const s32 ios_override = Config::Get(Config::MAIN_OVERRIDE_BOOT_IOS);
const u64 ios = ios_override >= 0 ? Titles::IOS(static_cast<u32>(ios_override)) : tmd.GetIOSId();
@ -554,9 +566,9 @@ bool CBoot::EmulatedBS2_Wii(const DiscIO::VolumeDisc& volume,
SetupHID(/*is_wii*/ true);
SetupBAT(/*is_wii*/ true);
Memory::Write_U32(0x4c000064, 0x00000300); // Write default DSI Handler: rfi
Memory::Write_U32(0x4c000064, 0x00000800); // Write default FPU Handler: rfi
Memory::Write_U32(0x4c000064, 0x00000C00); // Write default Syscall Handler: rfi
memory.Write_U32(0x4c000064, 0x00000300); // Write default DSI Handler: rfi
memory.Write_U32(0x4c000064, 0x00000800); // Write default FPU Handler: rfi
memory.Write_U32(0x4c000064, 0x00000C00); // Write default Syscall Handler: rfi
PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer

View file

@ -12,6 +12,7 @@
#include "Common/Swap.h"
#include "Core/Boot/AncastTypes.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"
DolReader::DolReader(std::vector<u8> buffer) : BootExecutableReader(std::move(buffer))
{
@ -117,25 +118,32 @@ bool DolReader::LoadIntoMemory(bool only_in_mem1) const
if (m_is_ancast)
return LoadAncastIntoMemory();
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// load all text (code) sections
for (size_t i = 0; i < m_text_sections.size(); ++i)
{
if (!m_text_sections[i].empty() &&
!(only_in_mem1 &&
m_dolheader.textAddress[i] + m_text_sections[i].size() >= Memory::GetRamSizeReal()))
m_dolheader.textAddress[i] + m_text_sections[i].size() >= memory.GetRamSizeReal()))
{
Memory::CopyToEmu(m_dolheader.textAddress[i], m_text_sections[i].data(),
m_text_sections[i].size());
memory.CopyToEmu(m_dolheader.textAddress[i], m_text_sections[i].data(),
m_text_sections[i].size());
}
}
// load all data sections
for (size_t i = 0; i < m_data_sections.size(); ++i)
{
if (!m_data_sections[i].empty() &&
!(only_in_mem1 &&
m_dolheader.dataAddress[i] + m_data_sections[i].size() >= Memory::GetRamSizeReal()))
m_dolheader.dataAddress[i] + m_data_sections[i].size() >= memory.GetRamSizeReal()))
{
Memory::CopyToEmu(m_dolheader.dataAddress[i], m_data_sections[i].data(),
m_data_sections[i].size());
memory.CopyToEmu(m_dolheader.dataAddress[i], m_data_sections[i].data(),
m_data_sections[i].size());
}
}
return true;
}
@ -219,11 +227,14 @@ bool DolReader::LoadAncastIntoMemory() const
body_size))
return false;
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// Copy the Ancast header to the emu
Memory::CopyToEmu(section_address, header, sizeof(EspressoAncastHeader));
memory.CopyToEmu(section_address, header, sizeof(EspressoAncastHeader));
// Copy the decrypted body to the emu
Memory::CopyToEmu(section_address + sizeof(EspressoAncastHeader), decrypted.data(), body_size);
memory.CopyToEmu(section_address + sizeof(EspressoAncastHeader), decrypted.data(), body_size);
return true;
}

View file

@ -14,6 +14,7 @@
#include "Core/HW/Memmap.h"
#include "Core/PowerPC/PPCSymbolDB.h"
#include "Core/System.h"
static void bswap(u32& w)
{
@ -135,6 +136,9 @@ bool ElfReader::LoadIntoMemory(bool only_in_mem1) const
INFO_LOG_FMT(BOOT, "{} segments:", header->e_phnum);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// Copy segments into ram.
for (int i = 0; i < header->e_phnum; i++)
{
@ -150,12 +154,12 @@ bool ElfReader::LoadIntoMemory(bool only_in_mem1) const
u32 srcSize = p->p_filesz;
u32 dstSize = p->p_memsz;
if (only_in_mem1 && p->p_vaddr >= Memory::GetRamSizeReal())
if (only_in_mem1 && p->p_vaddr >= memory.GetRamSizeReal())
continue;
Memory::CopyToEmu(writeAddr, src, srcSize);
memory.CopyToEmu(writeAddr, src, srcSize);
if (srcSize < dstSize)
Memory::Memset(writeAddr + srcSize, 0, dstSize - srcSize); // zero out bss
memory.Memset(writeAddr + srcSize, 0, dstSize - srcSize); // zero out bss
INFO_LOG_FMT(BOOT, "Loadable Segment Copied to {:08x}, size {:08x}", writeAddr, p->p_memsz);
}

View file

@ -13,6 +13,7 @@
#include "Common/MsgHandler.h"
#include "Core/Config/MainSettings.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"
constexpr u32 FILE_ID = 0x0d01f1f0;
constexpr u32 VERSION_NUMBER = 5;
@ -161,8 +162,10 @@ bool FifoDataFile::Save(const std::string& filename)
header.flags = m_Flags;
header.mem1_size = Memory::GetRamSizeReal();
header.mem2_size = Memory::GetExRamSizeReal();
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
header.mem1_size = memory.GetRamSizeReal();
header.mem2_size = memory.GetExRamSizeReal();
file.Seek(0, File::SeekOrigin::Begin);
file.WriteBytes(&header, sizeof(FileHeader));
@ -267,14 +270,15 @@ std::unique_ptr<FifoDataFile> FifoDataFile::Load(const std::string& filename, bo
// It should be noted, however, that Dolphin *will still crash* from the nullptr being returned
// in a non-flagsOnly context, so if this code becomes necessary, it should be moved above the
// prior conditional.
if (header.mem1_size != Memory::GetRamSizeReal() ||
header.mem2_size != Memory::GetExRamSizeReal())
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
if (header.mem1_size != memory.GetRamSizeReal() || header.mem2_size != memory.GetExRamSizeReal())
{
CriticalAlertFmtT("Emulated memory size mismatch!\n"
"Current: MEM1 {0:08X} ({1} MiB), MEM2 {2:08X} ({3} MiB)\n"
"DFF: MEM1 {4:08X} ({5} MiB), MEM2 {6:08X} ({7} MiB)",
Memory::GetRamSizeReal(), Memory::GetRamSizeReal() / 0x100000,
Memory::GetExRamSizeReal(), Memory::GetExRamSizeReal() / 0x100000,
memory.GetRamSizeReal(), memory.GetRamSizeReal() / 0x100000,
memory.GetExRamSizeReal(), memory.GetExRamSizeReal() / 0x100000,
header.mem1_size, header.mem1_size / 0x100000, header.mem2_size,
header.mem2_size / 0x100000);
return nullptr;

View file

@ -494,12 +494,14 @@ void FifoPlayer::WriteAllMemoryUpdates()
void FifoPlayer::WriteMemory(const MemoryUpdate& memUpdate)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u8* mem = nullptr;
if (memUpdate.address & 0x10000000)
mem = &Memory::m_pEXRAM[memUpdate.address & Memory::GetExRamMask()];
mem = &memory.GetEXRAM()[memUpdate.address & memory.GetExRamMask()];
else
mem = &Memory::m_pRAM[memUpdate.address & Memory::GetRamMask()];
mem = &memory.GetRAM()[memUpdate.address & memory.GetRamMask()];
std::copy(memUpdate.data.begin(), memUpdate.data.end(), mem);
}

View file

@ -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)

View file

@ -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

View file

@ -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}};

View file

@ -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
{

View file

@ -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 @@ protected:
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];

View file

@ -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);
}
}

View file

@ -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)
{
if (ExramRead(address))
return Memory::m_pEXRAM[address & Memory::GetExRamMask()];
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
return Memory::m_pRAM[address & Memory::GetRamMask()];
if (ExramRead(address))
return memory.GetEXRAM()[address & memory.GetExRamMask()];
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)
{
if (ExramRead(address))
return &Memory::m_pEXRAM[address & Memory::GetExRamMask()];
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
return &Memory::m_pRAM[address & Memory::GetRamMask()];
if (ExramRead(address))
return &memory.GetEXRAM()[address & memory.GetExRamMask()];
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);
}

View file

@ -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)

View file

@ -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");

View file

@ -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;
}

View file

@ -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++);
}
}

View file

@ -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;
}

View file

@ -523,7 +523,9 @@ 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)
{
@ -531,7 +533,7 @@ void CEXIMemoryCard::DMARead(u32 addr, u32 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,7 +542,9 @@ 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)
{
@ -548,7 +552,7 @@ void CEXIMemoryCard::DMAWrite(u32 addr, u32 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));
}

View file

@ -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,7 +99,7 @@ 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
{
@ -104,7 +107,6 @@ void UpdateGatherPipe()
ProcessorInterface::Fifo_CPUWritePointer += GATHER_PIPE_SIZE;
}
auto& system = Core::System::GetInstance();
system.GetCommandProcessor().GatherPipeBursted(system);
}

View file

@ -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");

View file

@ -41,190 +41,35 @@
namespace Memory
{
// =================================
// Init() declarations
// ----------------
// Store the MemArena here
u8* physical_base = nullptr;
u8* logical_base = nullptr;
u8* physical_page_mappings_base = nullptr;
u8* logical_page_mappings_base = nullptr;
static bool is_fastmem_arena_initialized = false;
MemoryManager::MemoryManager() = default;
MemoryManager::~MemoryManager() = default;
// The MemArena class
static Common::MemArena g_arena;
// ==============
// STATE_TO_SAVE
static bool m_IsInitialized = false; // Save the Init(), Shutdown() state
// END STATE_TO_SAVE
u8* m_pRAM;
u8* m_pL1Cache;
u8* m_pEXRAM;
u8* m_pFakeVMEM;
// s_ram_size is the amount allocated by the emulator, whereas s_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.
static u32 s_ram_size_real;
static u32 s_ram_size;
static u32 s_ram_mask;
static u32 s_fakevmem_size;
static u32 s_fakevmem_mask;
static u32 s_L1_cache_size;
static u32 s_L1_cache_mask;
// s_exram_size is the amount allocated by the emulator, whereas s_exram_size_real
// is what gets used by emulated software. If using retail IOS, it will
// always be set to 64MB.
static u32 s_exram_size_real;
static u32 s_exram_size;
static u32 s_exram_mask;
u32 GetRamSizeReal()
void MemoryManager::InitMMIO(bool is_wii)
{
return s_ram_size_real;
}
u32 GetRamSize()
{
return s_ram_size;
}
u32 GetRamMask()
{
return s_ram_mask;
}
u32 GetFakeVMemSize()
{
return s_fakevmem_size;
}
u32 GetFakeVMemMask()
{
return s_fakevmem_mask;
}
u32 GetL1CacheSize()
{
return s_L1_cache_size;
}
u32 GetL1CacheMask()
{
return s_L1_cache_mask;
}
u32 GetExRamSizeReal()
{
return s_exram_size_real;
}
u32 GetExRamSize()
{
return s_exram_size;
}
u32 GetExRamMask()
{
return s_exram_mask;
}
// MMIO mapping object.
std::unique_ptr<MMIO::Mapping> mmio_mapping;
static void InitMMIO(bool is_wii)
{
mmio_mapping = std::make_unique<MMIO::Mapping>();
m_mmio_mapping = std::make_unique<MMIO::Mapping>();
auto& system = Core::System::GetInstance();
system.GetCommandProcessor().RegisterMMIO(system, mmio_mapping.get(), 0x0C000000);
PixelEngine::RegisterMMIO(mmio_mapping.get(), 0x0C001000);
VideoInterface::RegisterMMIO(mmio_mapping.get(), 0x0C002000);
ProcessorInterface::RegisterMMIO(mmio_mapping.get(), 0x0C003000);
MemoryInterface::RegisterMMIO(mmio_mapping.get(), 0x0C004000);
DSP::RegisterMMIO(mmio_mapping.get(), 0x0C005000);
DVDInterface::RegisterMMIO(mmio_mapping.get(), 0x0C006000, false);
SerialInterface::RegisterMMIO(mmio_mapping.get(), 0x0C006400);
ExpansionInterface::RegisterMMIO(mmio_mapping.get(), 0x0C006800);
AudioInterface::RegisterMMIO(mmio_mapping.get(), 0x0C006C00);
system.GetCommandProcessor().RegisterMMIO(system, m_mmio_mapping.get(), 0x0C000000);
PixelEngine::RegisterMMIO(m_mmio_mapping.get(), 0x0C001000);
VideoInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0C002000);
ProcessorInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0C003000);
MemoryInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0C004000);
DSP::RegisterMMIO(m_mmio_mapping.get(), 0x0C005000);
DVDInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0C006000, false);
SerialInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0C006400);
ExpansionInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0C006800);
AudioInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0C006C00);
if (is_wii)
{
IOS::RegisterMMIO(mmio_mapping.get(), 0x0D000000);
DVDInterface::RegisterMMIO(mmio_mapping.get(), 0x0D006000, true);
SerialInterface::RegisterMMIO(mmio_mapping.get(), 0x0D006400);
ExpansionInterface::RegisterMMIO(mmio_mapping.get(), 0x0D006800);
AudioInterface::RegisterMMIO(mmio_mapping.get(), 0x0D006C00);
IOS::RegisterMMIO(m_mmio_mapping.get(), 0x0D000000);
DVDInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0D006000, true);
SerialInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0D006400);
ExpansionInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0D006800);
AudioInterface::RegisterMMIO(m_mmio_mapping.get(), 0x0D006C00);
}
}
bool IsInitialized()
{
return m_IsInitialized;
}
struct PhysicalMemoryRegion
{
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
{
void* mapped_pointer;
u32 mapped_size;
};
// 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 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 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?
static std::array<PhysicalMemoryRegion, 4> s_physical_regions;
static std::vector<LogicalMemoryView> logical_mapped_entries;
static std::array<void*, PowerPC::BAT_PAGE_COUNT> s_physical_page_mappings;
static std::array<void*, PowerPC::BAT_PAGE_COUNT> s_logical_page_mappings;
void Init()
void MemoryManager::Init()
{
const auto get_mem1_size = [] {
if (Config::Get(Config::MAIN_RAM_OVERRIDE_ENABLE))
@ -236,25 +81,25 @@ void Init()
return Config::Get(Config::MAIN_MEM2_SIZE);
return Memory::MEM2_SIZE_RETAIL;
};
s_ram_size_real = get_mem1_size();
s_ram_size = MathUtil::NextPowerOf2(GetRamSizeReal());
s_ram_mask = GetRamSize() - 1;
s_fakevmem_size = 0x02000000;
s_fakevmem_mask = GetFakeVMemSize() - 1;
s_L1_cache_size = 0x00040000;
s_L1_cache_mask = GetL1CacheSize() - 1;
s_exram_size_real = get_mem2_size();
s_exram_size = MathUtil::NextPowerOf2(GetExRamSizeReal());
s_exram_mask = GetExRamSize() - 1;
m_ram_size_real = get_mem1_size();
m_ram_size = MathUtil::NextPowerOf2(GetRamSizeReal());
m_ram_mask = GetRamSize() - 1;
m_fakevmem_size = 0x02000000;
m_fakevmem_mask = GetFakeVMemSize() - 1;
m_l1_cache_size = 0x00040000;
m_l1_cache_mask = GetL1CacheSize() - 1;
m_exram_size_real = get_mem2_size();
m_exram_size = MathUtil::NextPowerOf2(GetExRamSizeReal());
m_exram_mask = GetExRamSize() - 1;
s_physical_regions[0] = PhysicalMemoryRegion{
&m_pRAM, 0x00000000, GetRamSize(), PhysicalMemoryRegion::ALWAYS, 0, false};
s_physical_regions[1] = PhysicalMemoryRegion{
&m_pL1Cache, 0xE0000000, GetL1CacheSize(), PhysicalMemoryRegion::ALWAYS, 0, false};
s_physical_regions[2] = PhysicalMemoryRegion{
&m_pFakeVMEM, 0x7E000000, GetFakeVMemSize(), PhysicalMemoryRegion::FAKE_VMEM, 0, false};
s_physical_regions[3] = PhysicalMemoryRegion{
&m_pEXRAM, 0x10000000, GetExRamSize(), PhysicalMemoryRegion::WII_ONLY, 0, false};
m_physical_regions[0] = PhysicalMemoryRegion{
&m_ram, 0x00000000, GetRamSize(), PhysicalMemoryRegion::ALWAYS, 0, false};
m_physical_regions[1] = PhysicalMemoryRegion{
&m_l1_cache, 0xE0000000, GetL1CacheSize(), PhysicalMemoryRegion::ALWAYS, 0, false};
m_physical_regions[2] = PhysicalMemoryRegion{
&m_fake_vmem, 0x7E000000, GetFakeVMemSize(), PhysicalMemoryRegion::FAKE_VMEM, 0, false};
m_physical_regions[3] = PhysicalMemoryRegion{
&m_exram, 0x10000000, GetExRamSize(), PhysicalMemoryRegion::WII_ONLY, 0, false};
const bool wii = SConfig::GetInstance().bWii;
const bool mmu = Core::System::GetInstance().IsMMUMode();
@ -268,7 +113,7 @@ void Init()
#endif
u32 mem_size = 0;
for (PhysicalMemoryRegion& region : s_physical_regions)
for (PhysicalMemoryRegion& region : m_physical_regions)
{
if (!wii && (region.flags & PhysicalMemoryRegion::WII_ONLY))
continue;
@ -279,17 +124,17 @@ void Init()
region.active = true;
mem_size += region.size;
}
g_arena.GrabSHMSegment(mem_size);
m_arena.GrabSHMSegment(mem_size);
s_physical_page_mappings.fill(nullptr);
m_physical_page_mappings.fill(nullptr);
// Create an anonymous view of the physical memory
for (const PhysicalMemoryRegion& region : s_physical_regions)
for (const PhysicalMemoryRegion& region : m_physical_regions)
{
if (!region.active)
continue;
*region.out_pointer = (u8*)g_arena.CreateView(region.shm_position, region.size);
*region.out_pointer = (u8*)m_arena.CreateView(region.shm_position, region.size);
if (!*region.out_pointer)
{
@ -302,43 +147,43 @@ void Init()
for (u32 i = 0; i < region.size; i += PowerPC::BAT_PAGE_SIZE)
{
const size_t index = (i + region.physical_address) >> PowerPC::BAT_INDEX_SHIFT;
s_physical_page_mappings[index] = *region.out_pointer + i;
m_physical_page_mappings[index] = *region.out_pointer + i;
}
}
physical_page_mappings_base = reinterpret_cast<u8*>(s_physical_page_mappings.data());
logical_page_mappings_base = reinterpret_cast<u8*>(s_logical_page_mappings.data());
m_physical_page_mappings_base = reinterpret_cast<u8*>(m_physical_page_mappings.data());
m_logical_page_mappings_base = reinterpret_cast<u8*>(m_logical_page_mappings.data());
InitMMIO(wii);
Clear();
INFO_LOG_FMT(MEMMAP, "Memory system initialized. RAM at {}", fmt::ptr(m_pRAM));
m_IsInitialized = true;
INFO_LOG_FMT(MEMMAP, "Memory system initialized. RAM at {}", fmt::ptr(m_ram));
m_is_initialized = true;
}
bool InitFastmemArena()
bool MemoryManager::InitFastmemArena()
{
#if _ARCH_32
const size_t memory_size = 0x31000000;
#else
const size_t memory_size = 0x400000000;
#endif
physical_base = g_arena.ReserveMemoryRegion(memory_size);
m_physical_base = m_arena.ReserveMemoryRegion(memory_size);
if (!physical_base)
if (!m_physical_base)
{
PanicAlertFmt("Memory::InitFastmemArena(): Failed finding a memory base.");
return false;
}
for (const PhysicalMemoryRegion& region : s_physical_regions)
for (const PhysicalMemoryRegion& region : m_physical_regions)
{
if (!region.active)
continue;
u8* base = physical_base + region.physical_address;
u8* view = (u8*)g_arena.MapInMemoryRegion(region.shm_position, region.size, base);
u8* base = m_physical_base + region.physical_address;
u8* view = (u8*)m_arena.MapInMemoryRegion(region.shm_position, region.size, base);
if (base != view)
{
@ -350,22 +195,22 @@ bool InitFastmemArena()
}
#ifndef _ARCH_32
logical_base = physical_base + 0x200000000;
m_logical_base = m_physical_base + 0x200000000;
#endif
is_fastmem_arena_initialized = true;
m_is_fastmem_arena_initialized = true;
return true;
}
void UpdateLogicalMemory(const PowerPC::BatTable& dbat_table)
void MemoryManager::UpdateLogicalMemory(const PowerPC::BatTable& dbat_table)
{
for (auto& entry : logical_mapped_entries)
for (auto& entry : m_logical_mapped_entries)
{
g_arena.UnmapFromMemoryRegion(entry.mapped_pointer, entry.mapped_size);
m_arena.UnmapFromMemoryRegion(entry.mapped_pointer, entry.mapped_size);
}
logical_mapped_entries.clear();
m_logical_mapped_entries.clear();
s_logical_page_mappings.fill(nullptr);
m_logical_page_mappings.fill(nullptr);
for (u32 i = 0; i < dbat_table.size(); ++i)
{
@ -375,7 +220,7 @@ void UpdateLogicalMemory(const PowerPC::BatTable& dbat_table)
// TODO: Merge adjacent mappings to make this faster.
u32 logical_size = PowerPC::BAT_PAGE_SIZE;
u32 translated_address = dbat_table[i] & PowerPC::BAT_RESULT_MASK;
for (const auto& physical_region : s_physical_regions)
for (const auto& physical_region : m_physical_regions)
{
if (!physical_region.active)
continue;
@ -388,13 +233,13 @@ void UpdateLogicalMemory(const PowerPC::BatTable& dbat_table)
{
// Found an overlapping region; map it.
if (is_fastmem_arena_initialized)
if (m_is_fastmem_arena_initialized)
{
u32 position = physical_region.shm_position + intersection_start - mapping_address;
u8* base = logical_base + logical_address + intersection_start - translated_address;
u8* base = m_logical_base + logical_address + intersection_start - translated_address;
u32 mapped_size = intersection_end - intersection_start;
void* mapped_pointer = g_arena.MapInMemoryRegion(position, mapped_size, base);
void* mapped_pointer = m_arena.MapInMemoryRegion(position, mapped_size, base);
if (!mapped_pointer)
{
PanicAlertFmt(
@ -403,10 +248,10 @@ void UpdateLogicalMemory(const PowerPC::BatTable& dbat_table)
intersection_start, mapped_size, logical_address);
exit(0);
}
logical_mapped_entries.push_back({mapped_pointer, mapped_size});
m_logical_mapped_entries.push_back({mapped_pointer, mapped_size});
}
s_logical_page_mappings[i] =
m_logical_page_mappings[i] =
*physical_region.out_pointer + intersection_start - mapping_address;
}
}
@ -414,13 +259,13 @@ void UpdateLogicalMemory(const PowerPC::BatTable& dbat_table)
}
}
void DoState(PointerWrap& p)
void MemoryManager::DoState(PointerWrap& p)
{
const u32 current_ram_size = GetRamSize();
const u32 current_l1_cache_size = GetL1CacheSize();
const bool current_have_fake_vmem = !!m_pFakeVMEM;
const bool current_have_fake_vmem = !!m_fake_vmem;
const u32 current_fake_vmem_size = current_have_fake_vmem ? GetFakeVMemSize() : 0;
const bool current_have_exram = !!m_pEXRAM;
const bool current_have_exram = !!m_exram;
const u32 current_exram_size = current_have_exram ? GetExRamSize() : 0;
u32 state_ram_size = current_ram_size;
@ -452,76 +297,76 @@ void DoState(PointerWrap& p)
return;
}
p.DoArray(m_pRAM, current_ram_size);
p.DoArray(m_pL1Cache, current_l1_cache_size);
p.DoArray(m_ram, current_ram_size);
p.DoArray(m_l1_cache, current_l1_cache_size);
p.DoMarker("Memory RAM");
if (current_have_fake_vmem)
p.DoArray(m_pFakeVMEM, current_fake_vmem_size);
p.DoArray(m_fake_vmem, current_fake_vmem_size);
p.DoMarker("Memory FakeVMEM");
if (current_have_exram)
p.DoArray(m_pEXRAM, current_exram_size);
p.DoArray(m_exram, current_exram_size);
p.DoMarker("Memory EXRAM");
}
void Shutdown()
void MemoryManager::Shutdown()
{
ShutdownFastmemArena();
m_IsInitialized = false;
for (const PhysicalMemoryRegion& region : s_physical_regions)
m_is_initialized = false;
for (const PhysicalMemoryRegion& region : m_physical_regions)
{
if (!region.active)
continue;
g_arena.ReleaseView(*region.out_pointer, region.size);
m_arena.ReleaseView(*region.out_pointer, region.size);
*region.out_pointer = nullptr;
}
g_arena.ReleaseSHMSegment();
mmio_mapping.reset();
m_arena.ReleaseSHMSegment();
m_mmio_mapping.reset();
INFO_LOG_FMT(MEMMAP, "Memory system shut down.");
}
void ShutdownFastmemArena()
void MemoryManager::ShutdownFastmemArena()
{
if (!is_fastmem_arena_initialized)
if (!m_is_fastmem_arena_initialized)
return;
for (const PhysicalMemoryRegion& region : s_physical_regions)
for (const PhysicalMemoryRegion& region : m_physical_regions)
{
if (!region.active)
continue;
u8* base = physical_base + region.physical_address;
g_arena.UnmapFromMemoryRegion(base, region.size);
u8* base = m_physical_base + region.physical_address;
m_arena.UnmapFromMemoryRegion(base, region.size);
}
for (auto& entry : logical_mapped_entries)
for (auto& entry : m_logical_mapped_entries)
{
g_arena.UnmapFromMemoryRegion(entry.mapped_pointer, entry.mapped_size);
m_arena.UnmapFromMemoryRegion(entry.mapped_pointer, entry.mapped_size);
}
logical_mapped_entries.clear();
m_logical_mapped_entries.clear();
g_arena.ReleaseMemoryRegion();
m_arena.ReleaseMemoryRegion();
physical_base = nullptr;
logical_base = nullptr;
m_physical_base = nullptr;
m_logical_base = nullptr;
is_fastmem_arena_initialized = false;
m_is_fastmem_arena_initialized = false;
}
void Clear()
void MemoryManager::Clear()
{
if (m_pRAM)
memset(m_pRAM, 0, GetRamSize());
if (m_pL1Cache)
memset(m_pL1Cache, 0, GetL1CacheSize());
if (m_pFakeVMEM)
memset(m_pFakeVMEM, 0, GetFakeVMemSize());
if (m_pEXRAM)
memset(m_pEXRAM, 0, GetExRamSize());
if (m_ram)
memset(m_ram, 0, GetRamSize());
if (m_l1_cache)
memset(m_l1_cache, 0, GetL1CacheSize());
if (m_fake_vmem)
memset(m_fake_vmem, 0, GetFakeVMemSize());
if (m_exram)
memset(m_exram, 0, GetExRamSize());
}
u8* GetPointerForRange(u32 address, size_t size)
u8* MemoryManager::GetPointerForRange(u32 address, size_t size) const
{
// Make sure we don't have a range spanning 2 separate banks
if (size >= GetExRamSizeReal())
@ -541,7 +386,7 @@ u8* GetPointerForRange(u32 address, size_t size)
return pointer;
}
void CopyFromEmu(void* data, u32 address, size_t size)
void MemoryManager::CopyFromEmu(void* data, u32 address, size_t size) const
{
if (size == 0)
return;
@ -555,7 +400,7 @@ void CopyFromEmu(void* data, u32 address, size_t size)
memcpy(data, pointer, size);
}
void CopyToEmu(u32 address, const void* data, size_t size)
void MemoryManager::CopyToEmu(u32 address, const void* data, size_t size)
{
if (size == 0)
return;
@ -569,7 +414,7 @@ void CopyToEmu(u32 address, const void* data, size_t size)
memcpy(pointer, data, size);
}
void Memset(u32 address, u8 value, size_t size)
void MemoryManager::Memset(u32 address, u8 value, size_t size)
{
if (size == 0)
return;
@ -583,7 +428,7 @@ void Memset(u32 address, u8 value, size_t size)
memset(pointer, value, size);
}
std::string GetString(u32 em_address, size_t size)
std::string MemoryManager::GetString(u32 em_address, size_t size)
{
const char* ptr = reinterpret_cast<const char*>(GetPointer(em_address));
if (ptr == nullptr)
@ -600,81 +445,81 @@ std::string GetString(u32 em_address, size_t size)
}
}
u8* GetPointer(u32 address)
u8* MemoryManager::GetPointer(u32 address) const
{
// TODO: Should we be masking off more bits here? Can all devices access
// EXRAM?
address &= 0x3FFFFFFF;
if (address < GetRamSizeReal())
return m_pRAM + address;
return m_ram + address;
if (m_pEXRAM)
if (m_exram)
{
if ((address >> 28) == 0x1 && (address & 0x0fffffff) < GetExRamSizeReal())
return m_pEXRAM + (address & GetExRamMask());
return m_exram + (address & GetExRamMask());
}
PanicAlertFmt("Unknown Pointer {:#010x} PC {:#010x} LR {:#010x}", address, PC, LR);
return nullptr;
}
u8 Read_U8(u32 address)
u8 MemoryManager::Read_U8(u32 address) const
{
u8 value = 0;
CopyFromEmu(&value, address, sizeof(value));
return value;
}
u16 Read_U16(u32 address)
u16 MemoryManager::Read_U16(u32 address) const
{
u16 value = 0;
CopyFromEmu(&value, address, sizeof(value));
return Common::swap16(value);
}
u32 Read_U32(u32 address)
u32 MemoryManager::Read_U32(u32 address) const
{
u32 value = 0;
CopyFromEmu(&value, address, sizeof(value));
return Common::swap32(value);
}
u64 Read_U64(u32 address)
u64 MemoryManager::Read_U64(u32 address) const
{
u64 value = 0;
CopyFromEmu(&value, address, sizeof(value));
return Common::swap64(value);
}
void Write_U8(u8 value, u32 address)
void MemoryManager::Write_U8(u8 value, u32 address)
{
CopyToEmu(address, &value, sizeof(value));
}
void Write_U16(u16 value, u32 address)
void MemoryManager::Write_U16(u16 value, u32 address)
{
u16 swapped_value = Common::swap16(value);
CopyToEmu(address, &swapped_value, sizeof(swapped_value));
}
void Write_U32(u32 value, u32 address)
void MemoryManager::Write_U32(u32 value, u32 address)
{
u32 swapped_value = Common::swap32(value);
CopyToEmu(address, &swapped_value, sizeof(swapped_value));
}
void Write_U64(u64 value, u32 address)
void MemoryManager::Write_U64(u64 value, u32 address)
{
u64 swapped_value = Common::swap64(value);
CopyToEmu(address, &swapped_value, sizeof(swapped_value));
}
void Write_U32_Swap(u32 value, u32 address)
void MemoryManager::Write_U32_Swap(u32 value, u32 address)
{
CopyToEmu(address, &value, sizeof(value));
}
void Write_U64_Swap(u64 value, u32 address)
void MemoryManager::Write_U64_Swap(u64 value, u32 address)
{
CopyToEmu(address, &value, sizeof(value));
}

View file

@ -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,35 +23,6 @@ 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;
@ -56,62 +30,214 @@ 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));
u8** out_pointer;
u32 physical_address;
u32 size;
enum : u32
{
ALWAYS = 0,
FAKE_VMEM = 1,
WII_ONLY = 2,
} flags;
u32 shm_position;
bool active;
};
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)
struct LogicalMemoryView
{
T* dest = reinterpret_cast<T*>(GetPointerForRange(address, size));
void* mapped_pointer;
u32 mapped_size;
};
if (dest == nullptr)
return;
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();
for (size_t i = 0; i < size / sizeof(T); i++)
dest[i] = Common::FromBigEndian(data[i]);
}
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

View file

@ -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,7 +187,7 @@ 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
@ -177,8 +195,8 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
// }
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,8 +522,8 @@ 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;
@ -513,8 +531,8 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
}
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,7 +733,7 @@ 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);
@ -716,10 +741,10 @@ std::optional<IPCReply> DIDevice::IOCtlV(const IOCtlVRequest& request)
// 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;

View file

@ -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,6 +136,9 @@ 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());
@ -127,7 +146,7 @@ void IOCtlVRequest::Dump(std::string_view description, Common::Log::LogType type
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;

View file

@ -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);
std::string large_image_key =
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);
std::string small_image_key =
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);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
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);
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);
std::string large_image_text =
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);
std::string small_image_text =
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);
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);
}

View file

@ -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();
char* path = reinterpret_cast<char*>(Memory::GetPointer(request.io_vectors[0].address));
const u64 title_id = memory.Read_U64(request.in_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,8 +950,11 @@ 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())
@ -945,8 +962,8 @@ IPCReply ESDevice::SetUpStreamKey(const Context& context, const IOCtlVRequest& r
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));
}

View file

@ -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));
}

View file

@ -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);
});

View file

@ -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);

View file

@ -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

View file

@ -16,6 +16,7 @@
#include "Core/HW/Memmap.h"
#include "Core/IOS/ES/Formats.h"
#include "Core/IOS/VersionInfo.h"
#include "Core/System.h"
namespace IOS::HLE
{
@ -40,7 +41,10 @@ IPCReply ESDevice::GetTicketViewCount(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(1, 1))
return IPCReply(ES_EINVAL);
const u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u64 TitleID = memory.Read_U64(request.in_vectors[0].address);
const ES::TicketReader ticket = FindSignedTicket(TitleID);
u32 view_count = ticket.IsValid() ? static_cast<u32>(ticket.GetNumberOfTickets()) : 0;
@ -59,7 +63,7 @@ IPCReply ESDevice::GetTicketViewCount(const IOCtlVRequest& request)
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETVIEWCNT for titleID: {:016x} (View Count = {})", TitleID,
view_count);
Memory::Write_U32(view_count, request.io_vectors[0].address);
memory.Write_U32(view_count, request.io_vectors[0].address);
return IPCReply(IPC_SUCCESS);
}
@ -68,8 +72,11 @@ IPCReply ESDevice::GetTicketViews(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(2, 1))
return IPCReply(ES_EINVAL);
const u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
const u32 maxViews = Memory::Read_U32(request.in_vectors[1].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u64 TitleID = memory.Read_U64(request.in_vectors[0].address);
const u32 maxViews = memory.Read_U32(request.in_vectors[1].address);
const ES::TicketReader ticket = FindSignedTicket(TitleID);
@ -83,13 +90,13 @@ IPCReply ESDevice::GetTicketViews(const IOCtlVRequest& request)
for (u32 view = 0; view < number_of_views; ++view)
{
const std::vector<u8> ticket_view = ticket.GetRawTicketView(view);
Memory::CopyToEmu(request.io_vectors[0].address + view * sizeof(ES::TicketView),
ticket_view.data(), ticket_view.size());
memory.CopyToEmu(request.io_vectors[0].address + view * sizeof(ES::TicketView),
ticket_view.data(), ticket_view.size());
}
}
else if (ShouldReturnFakeViewsForIOSes(TitleID, m_title_context))
{
Memory::Memset(request.io_vectors[0].address, 0, sizeof(ES::TicketView));
memory.Memset(request.io_vectors[0].address, 0, sizeof(ES::TicketView));
WARN_LOG_FMT(IOS_ES, "GetViews: Faking IOS title {:016x} being present", TitleID);
}
@ -152,8 +159,11 @@ IPCReply ESDevice::GetV0TicketFromView(const IOCtlVRequest& request)
{
return IPCReply(ES_EINVAL);
}
return IPCReply(GetTicketFromView(Memory::GetPointer(request.in_vectors[0].address),
Memory::GetPointer(request.io_vectors[0].address), nullptr, 0));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
return IPCReply(GetTicketFromView(memory.GetPointer(request.in_vectors[0].address),
memory.GetPointer(request.io_vectors[0].address), nullptr, 0));
}
IPCReply ESDevice::GetTicketSizeFromView(const IOCtlVRequest& request)
@ -165,9 +175,12 @@ IPCReply ESDevice::GetTicketSizeFromView(const IOCtlVRequest& request)
{
return IPCReply(ES_EINVAL);
}
const ReturnCode ret = GetTicketFromView(Memory::GetPointer(request.in_vectors[0].address),
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const ReturnCode ret = GetTicketFromView(memory.GetPointer(request.in_vectors[0].address),
nullptr, &ticket_size, std::nullopt);
Memory::Write_U32(ticket_size, request.io_vectors[0].address);
memory.Write_U32(ticket_size, request.io_vectors[0].address);
return IPCReply(ret);
}
@ -180,12 +193,15 @@ IPCReply ESDevice::GetTicketFromView(const IOCtlVRequest& request)
return IPCReply(ES_EINVAL);
}
u32 ticket_size = Memory::Read_U32(request.in_vectors[1].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u32 ticket_size = memory.Read_U32(request.in_vectors[1].address);
if (ticket_size != request.io_vectors[0].size)
return IPCReply(ES_EINVAL);
return IPCReply(GetTicketFromView(Memory::GetPointer(request.in_vectors[0].address),
Memory::GetPointer(request.io_vectors[0].address), &ticket_size,
return IPCReply(GetTicketFromView(memory.GetPointer(request.in_vectors[0].address),
memory.GetPointer(request.io_vectors[0].address), &ticket_size,
std::nullopt));
}
@ -194,14 +210,17 @@ IPCReply ESDevice::GetTMDViewSize(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(1, 1))
return IPCReply(ES_EINVAL);
const u64 TitleID = Memory::Read_U64(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u64 TitleID = memory.Read_U64(request.in_vectors[0].address);
const ES::TMDReader tmd = FindInstalledTMD(TitleID);
if (!tmd.IsValid())
return IPCReply(FS_ENOENT);
const u32 view_size = static_cast<u32>(tmd.GetRawView().size());
Memory::Write_U32(view_size, request.io_vectors[0].address);
memory.Write_U32(view_size, request.io_vectors[0].address);
INFO_LOG_FMT(IOS_ES, "GetTMDViewSize: {} bytes for title {:016x}", view_size, TitleID);
return IPCReply(IPC_SUCCESS);
@ -209,15 +228,18 @@ IPCReply ESDevice::GetTMDViewSize(const IOCtlVRequest& request)
IPCReply ESDevice::GetTMDViews(const IOCtlVRequest& request)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
if (!request.HasNumberOfValidVectors(2, 1) ||
request.in_vectors[0].size != sizeof(ES::TMDHeader::title_id) ||
request.in_vectors[1].size != sizeof(u32) ||
Memory::Read_U32(request.in_vectors[1].address) != request.io_vectors[0].size)
memory.Read_U32(request.in_vectors[1].address) != request.io_vectors[0].size)
{
return IPCReply(ES_EINVAL);
}
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
const ES::TMDReader tmd = FindInstalledTMD(title_id);
if (!tmd.IsValid())
@ -227,7 +249,7 @@ IPCReply ESDevice::GetTMDViews(const IOCtlVRequest& request)
if (request.io_vectors[0].size < raw_view.size())
return IPCReply(ES_EINVAL);
Memory::CopyToEmu(request.io_vectors[0].address, raw_view.data(), raw_view.size());
memory.CopyToEmu(request.io_vectors[0].address, raw_view.data(), raw_view.size());
INFO_LOG_FMT(IOS_ES, "GetTMDView: {} bytes for title {:016x}", raw_view.size(), title_id);
return IPCReply(IPC_SUCCESS);
@ -245,13 +267,16 @@ IPCReply ESDevice::DIGetTMDViewSize(const IOCtlVRequest& request)
if (request.io_vectors[0].size != sizeof(u32))
return IPCReply(ES_EINVAL);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const bool has_tmd = request.in_vectors[0].size != 0;
size_t tmd_view_size = 0;
if (has_tmd)
{
std::vector<u8> tmd_bytes(request.in_vectors[0].size);
Memory::CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
memory.CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
const ES::TMDReader tmd{std::move(tmd_bytes)};
// Yes, this returns -1017, not ES_INVALID_TMD.
@ -270,7 +295,7 @@ IPCReply ESDevice::DIGetTMDViewSize(const IOCtlVRequest& request)
tmd_view_size = m_title_context.tmd.GetRawView().size();
}
Memory::Write_U32(static_cast<u32>(tmd_view_size), request.io_vectors[0].address);
memory.Write_U32(static_cast<u32>(tmd_view_size), request.io_vectors[0].address);
return IPCReply(IPC_SUCCESS);
}
@ -283,9 +308,12 @@ IPCReply ESDevice::DIGetTMDView(const IOCtlVRequest& request)
if (request.in_vectors[0].size >= 4 * 1024 * 1024)
return IPCReply(ES_EINVAL);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// Check whether the TMD view size is consistent.
if (request.in_vectors[1].size != sizeof(u32) ||
Memory::Read_U32(request.in_vectors[1].address) != request.io_vectors[0].size)
memory.Read_U32(request.in_vectors[1].address) != request.io_vectors[0].size)
{
return IPCReply(ES_EINVAL);
}
@ -296,7 +324,7 @@ IPCReply ESDevice::DIGetTMDView(const IOCtlVRequest& request)
if (has_tmd)
{
std::vector<u8> tmd_bytes(request.in_vectors[0].size);
Memory::CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
memory.CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
const ES::TMDReader tmd{std::move(tmd_bytes)};
if (!tmd.IsValid())
@ -316,7 +344,7 @@ IPCReply ESDevice::DIGetTMDView(const IOCtlVRequest& request)
if (tmd_view.size() > request.io_vectors[0].size)
return IPCReply(ES_EINVAL);
Memory::CopyToEmu(request.io_vectors[0].address, tmd_view.data(), tmd_view.size());
memory.CopyToEmu(request.io_vectors[0].address, tmd_view.data(), tmd_view.size());
return IPCReply(IPC_SUCCESS);
}
@ -334,6 +362,9 @@ IPCReply ESDevice::DIGetTicketView(const IOCtlVRequest& request)
if (!has_ticket_vector && request.in_vectors[0].size != 0)
return IPCReply(ES_EINVAL);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
std::vector<u8> view;
// If no ticket was passed in, IOS returns the ticket view for the current title.
@ -348,13 +379,13 @@ IPCReply ESDevice::DIGetTicketView(const IOCtlVRequest& request)
else
{
std::vector<u8> ticket_bytes(request.in_vectors[0].size);
Memory::CopyFromEmu(ticket_bytes.data(), request.in_vectors[0].address, ticket_bytes.size());
memory.CopyFromEmu(ticket_bytes.data(), request.in_vectors[0].address, ticket_bytes.size());
const ES::TicketReader ticket{std::move(ticket_bytes)};
view = ticket.GetRawTicketView(0);
}
Memory::CopyToEmu(request.io_vectors[0].address, view.data(), view.size());
memory.CopyToEmu(request.io_vectors[0].address, view.data(), view.size());
return IPCReply(IPC_SUCCESS);
}
@ -366,8 +397,10 @@ IPCReply ESDevice::DIGetTMDSize(const IOCtlVRequest& request)
if (!m_title_context.active)
return IPCReply(ES_EINVAL);
Memory::Write_U32(static_cast<u32>(m_title_context.tmd.GetBytes().size()),
request.io_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(static_cast<u32>(m_title_context.tmd.GetBytes().size()),
request.io_vectors[0].address);
return IPCReply(IPC_SUCCESS);
}
@ -376,7 +409,10 @@ IPCReply ESDevice::DIGetTMD(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
return IPCReply(ES_EINVAL);
const u32 tmd_size = Memory::Read_U32(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 tmd_size = memory.Read_U32(request.in_vectors[0].address);
if (tmd_size != request.io_vectors[0].size)
return IPCReply(ES_EINVAL);
@ -388,7 +424,7 @@ IPCReply ESDevice::DIGetTMD(const IOCtlVRequest& request)
if (static_cast<u32>(tmd_bytes.size()) > tmd_size)
return IPCReply(ES_EINVAL);
Memory::CopyToEmu(request.io_vectors[0].address, tmd_bytes.data(), tmd_bytes.size());
memory.CopyToEmu(request.io_vectors[0].address, tmd_bytes.data(), tmd_bytes.size());
return IPCReply(IPC_SUCCESS);
}
} // namespace IOS::HLE

View file

@ -16,6 +16,7 @@
#include "Core/HW/SystemTimers.h"
#include "Core/IOS/FS/FileSystem.h"
#include "Core/IOS/Uids.h"
#include "Core/System.h"
namespace IOS::HLE
{
@ -312,7 +313,9 @@ bool FSDevice::HasCacheForFile(u64 fd, u32 offset) const
std::optional<IPCReply> FSDevice::Read(const ReadWriteRequest& request)
{
return MakeIPCReply([&](Ticks t) {
return Read(request.fd, Memory::GetPointer(request.buffer), request.size, request.buffer, t);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
return Read(request.fd, memory.GetPointer(request.buffer), request.size, request.buffer, t);
});
}
@ -340,7 +343,9 @@ s32 FSDevice::Read(u64 fd, u8* data, u32 size, std::optional<u32> ipc_buffer_add
std::optional<IPCReply> FSDevice::Write(const ReadWriteRequest& request)
{
return MakeIPCReply([&](Ticks t) {
return Write(request.fd, Memory::GetPointer(request.buffer), request.size, request.buffer, t);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
return Write(request.fd, memory.GetPointer(request.buffer), request.size, request.buffer, t);
});
}
@ -422,8 +427,11 @@ static Result<T> GetParams(const IOCtlRequest& request)
if (request.buffer_in_size < sizeof(T))
return ResultCode::Invalid;
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
T params;
Memory::CopyFromEmu(&params, request.buffer_in, sizeof(params));
memory.CopyFromEmu(&params, request.buffer_in, sizeof(params));
return params;
}
@ -498,6 +506,9 @@ IPCReply FSDevice::GetStats(const Handle& handle, const IOCtlRequest& request)
if (!stats)
return IPCReply(ConvertResult(stats.Error()));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
ISFSNandStats out;
out.cluster_size = stats->cluster_size;
out.free_clusters = stats->free_clusters;
@ -506,7 +517,7 @@ IPCReply FSDevice::GetStats(const Handle& handle, const IOCtlRequest& request)
out.reserved_clusters = stats->reserved_clusters;
out.free_inodes = stats->free_inodes;
out.used_inodes = stats->used_inodes;
Memory::CopyToEmu(request.buffer_out, &out, sizeof(out));
memory.CopyToEmu(request.buffer_out, &out, sizeof(out));
return IPCReply(IPC_SUCCESS);
}
@ -530,28 +541,31 @@ IPCReply FSDevice::ReadDirectory(const Handle& handle, const IOCtlVRequest& requ
return GetFSReply(ConvertResult(ResultCode::Invalid));
}
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u32 file_list_address, file_count_address, max_count;
if (request.in_vectors.size() == 2)
{
if (request.in_vectors[1].size != 4 || request.io_vectors[1].size != 4)
return GetFSReply(ConvertResult(ResultCode::Invalid));
max_count = Memory::Read_U32(request.in_vectors[1].address);
max_count = memory.Read_U32(request.in_vectors[1].address);
file_count_address = request.io_vectors[1].address;
file_list_address = request.io_vectors[0].address;
if (request.io_vectors[0].size != 13 * max_count)
return GetFSReply(ConvertResult(ResultCode::Invalid));
Memory::Write_U32(max_count, file_count_address);
memory.Write_U32(max_count, file_count_address);
}
else
{
if (request.io_vectors[0].size != 4)
return GetFSReply(ConvertResult(ResultCode::Invalid));
max_count = Memory::Read_U32(request.io_vectors[0].address);
max_count = memory.Read_U32(request.io_vectors[0].address);
file_count_address = request.io_vectors[0].address;
file_list_address = 0;
}
const std::string directory = Memory::GetString(request.in_vectors[0].address, 64);
const std::string directory = memory.GetString(request.in_vectors[0].address, 64);
const Result<std::vector<std::string>> list =
m_ios.GetFS()->ReadDirectory(handle.uid, handle.gid, directory);
LogResult(list, "ReadDirectory({})", directory);
@ -560,19 +574,19 @@ IPCReply FSDevice::ReadDirectory(const Handle& handle, const IOCtlVRequest& requ
if (!file_list_address)
{
Memory::Write_U32(static_cast<u32>(list->size()), file_count_address);
memory.Write_U32(static_cast<u32>(list->size()), file_count_address);
return GetFSReply(IPC_SUCCESS);
}
for (size_t i = 0; i < list->size() && i < max_count; ++i)
{
Memory::Memset(file_list_address, 0, 13);
Memory::CopyToEmu(file_list_address, (*list)[i].data(), (*list)[i].size());
Memory::Write_U8(0, file_list_address + 12);
memory.Memset(file_list_address, 0, 13);
memory.CopyToEmu(file_list_address, (*list)[i].data(), (*list)[i].size());
memory.Write_U8(0, file_list_address + 12);
file_list_address += static_cast<u32>((*list)[i].size()) + 1;
}
// Write the actual number of entries in the buffer.
Memory::Write_U32(std::min(max_count, static_cast<u32>(list->size())), file_count_address);
memory.Write_U32(std::min(max_count, static_cast<u32>(list->size())), file_count_address);
return GetFSReply(IPC_SUCCESS);
}
@ -593,7 +607,10 @@ IPCReply FSDevice::GetAttribute(const Handle& handle, const IOCtlRequest& reques
if (request.buffer_in_size < 64 || request.buffer_out_size < sizeof(ISFSParams))
return GetFSReply(ConvertResult(ResultCode::Invalid));
const std::string path = Memory::GetString(request.buffer_in, 64);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const std::string path = memory.GetString(request.buffer_in, 64);
const auto ticks = EstimateFileLookupTicks(path, FileLookupMode::Split);
const Result<Metadata> metadata = m_ios.GetFS()->GetMetadata(handle.uid, handle.gid, path);
LogResult(metadata, "GetMetadata({})", path);
@ -608,7 +625,7 @@ IPCReply FSDevice::GetAttribute(const Handle& handle, const IOCtlRequest& reques
out.gid = metadata->gid;
out.attribute = metadata->attribute;
out.modes = metadata->modes;
Memory::CopyToEmu(request.buffer_out, &out, sizeof(out));
memory.CopyToEmu(request.buffer_out, &out, sizeof(out));
return GetFSReply(IPC_SUCCESS, ticks);
}
@ -627,7 +644,10 @@ IPCReply FSDevice::DeleteFile(const Handle& handle, const IOCtlRequest& request)
if (request.buffer_in_size < 64)
return GetFSReply(ConvertResult(ResultCode::Invalid));
const std::string path = Memory::GetString(request.buffer_in, 64);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const std::string path = memory.GetString(request.buffer_in, 64);
return MakeIPCReply(
[&](Ticks ticks) { return ConvertResult(DeleteFile(handle.uid, handle.gid, path, ticks)); });
}
@ -648,8 +668,11 @@ IPCReply FSDevice::RenameFile(const Handle& handle, const IOCtlRequest& request)
if (request.buffer_in_size < 64 * 2)
return GetFSReply(ConvertResult(ResultCode::Invalid));
const std::string old_path = Memory::GetString(request.buffer_in, 64);
const std::string new_path = Memory::GetString(request.buffer_in + 64, 64);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const std::string old_path = memory.GetString(request.buffer_in, 64);
const std::string new_path = memory.GetString(request.buffer_in + 64, 64);
return MakeIPCReply([&](Ticks ticks) {
return ConvertResult(RenameFile(handle.uid, handle.gid, old_path, new_path, ticks));
});
@ -699,10 +722,13 @@ IPCReply FSDevice::GetFileStats(const Handle& handle, const IOCtlRequest& reques
if (!status)
return ConvertResult(status.Error());
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
ISFSFileStats out;
out.size = status->size;
out.seek_position = status->offset;
Memory::CopyToEmu(request.buffer_out, &out, sizeof(out));
memory.CopyToEmu(request.buffer_out, &out, sizeof(out));
return IPC_SUCCESS;
});
}
@ -727,14 +753,17 @@ IPCReply FSDevice::GetUsage(const Handle& handle, const IOCtlVRequest& request)
return GetFSReply(ConvertResult(ResultCode::Invalid));
}
const std::string directory = Memory::GetString(request.in_vectors[0].address, 64);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const std::string directory = memory.GetString(request.in_vectors[0].address, 64);
const Result<DirectoryStats> stats = m_ios.GetFS()->GetDirectoryStats(directory);
LogResult(stats, "GetDirectoryStats({})", directory);
if (!stats)
return GetFSReply(ConvertResult(stats.Error()));
Memory::Write_U32(stats->used_clusters, request.io_vectors[0].address);
Memory::Write_U32(stats->used_inodes, request.io_vectors[1].address);
memory.Write_U32(stats->used_clusters, request.io_vectors[0].address);
memory.Write_U32(stats->used_inodes, request.io_vectors[1].address);
return GetFSReply(IPC_SUCCESS);
}

View file

@ -104,6 +104,9 @@ constexpr u32 PLACEHOLDER = 0xDEADBEEF;
static bool SetupMemory(u64 ios_title_id, MemorySetupType setup_type)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
auto target_imv = std::find_if(
GetMemoryValues().begin(), GetMemoryValues().end(),
[&](const MemoryValues& imv) { return imv.ios_number == (ios_title_id & 0xffff); });
@ -116,7 +119,7 @@ static bool SetupMemory(u64 ios_title_id, MemorySetupType setup_type)
if (setup_type == MemorySetupType::IOSReload)
{
Memory::Write_U32(target_imv->ios_version, ADDR_IOS_VERSION);
memory.Write_U32(target_imv->ios_version, ADDR_IOS_VERSION);
// These values are written by the IOS kernel as part of its boot process (for IOS28 and newer).
//
@ -127,15 +130,15 @@ static bool SetupMemory(u64 ios_title_id, MemorySetupType setup_type)
// the new IOS either updates the range (>= IOS28) or inherits it (< IOS28).
//
// We can skip this convoluted process and just write the correct range directly.
Memory::Write_U32(target_imv->mem2_physical_size, ADDR_MEM2_SIZE);
Memory::Write_U32(target_imv->mem2_simulated_size, ADDR_MEM2_SIM_SIZE);
Memory::Write_U32(target_imv->mem2_end, ADDR_MEM2_END);
Memory::Write_U32(target_imv->mem2_arena_begin, ADDR_MEM2_ARENA_BEGIN);
Memory::Write_U32(target_imv->mem2_arena_end, ADDR_MEM2_ARENA_END);
Memory::Write_U32(target_imv->ipc_buffer_begin, ADDR_IPC_BUFFER_BEGIN);
Memory::Write_U32(target_imv->ipc_buffer_end, ADDR_IPC_BUFFER_END);
Memory::Write_U32(target_imv->ios_reserved_begin, ADDR_IOS_RESERVED_BEGIN);
Memory::Write_U32(target_imv->ios_reserved_end, ADDR_IOS_RESERVED_END);
memory.Write_U32(target_imv->mem2_physical_size, ADDR_MEM2_SIZE);
memory.Write_U32(target_imv->mem2_simulated_size, ADDR_MEM2_SIM_SIZE);
memory.Write_U32(target_imv->mem2_end, ADDR_MEM2_END);
memory.Write_U32(target_imv->mem2_arena_begin, ADDR_MEM2_ARENA_BEGIN);
memory.Write_U32(target_imv->mem2_arena_end, ADDR_MEM2_ARENA_END);
memory.Write_U32(target_imv->ipc_buffer_begin, ADDR_IPC_BUFFER_BEGIN);
memory.Write_U32(target_imv->ipc_buffer_end, ADDR_IPC_BUFFER_END);
memory.Write_U32(target_imv->ios_reserved_begin, ADDR_IOS_RESERVED_BEGIN);
memory.Write_U32(target_imv->ios_reserved_end, ADDR_IOS_RESERVED_END);
RAMOverrideForIOSMemoryValues(setup_type);
@ -146,40 +149,40 @@ static bool SetupMemory(u64 ios_title_id, MemorySetupType setup_type)
// and system information (see below).
constexpr u32 LOW_MEM1_REGION_START = 0;
constexpr u32 LOW_MEM1_REGION_SIZE = 0x3fff;
Memory::Memset(LOW_MEM1_REGION_START, 0, LOW_MEM1_REGION_SIZE);
memory.Memset(LOW_MEM1_REGION_START, 0, LOW_MEM1_REGION_SIZE);
Memory::Write_U32(target_imv->mem1_physical_size, ADDR_MEM1_SIZE);
Memory::Write_U32(target_imv->mem1_simulated_size, ADDR_MEM1_SIM_SIZE);
Memory::Write_U32(target_imv->mem1_end, ADDR_MEM1_END);
Memory::Write_U32(target_imv->mem1_arena_begin, ADDR_MEM1_ARENA_BEGIN);
Memory::Write_U32(target_imv->mem1_arena_end, ADDR_MEM1_ARENA_END);
Memory::Write_U32(PLACEHOLDER, ADDR_PH1);
Memory::Write_U32(target_imv->mem2_physical_size, ADDR_MEM2_SIZE);
Memory::Write_U32(target_imv->mem2_simulated_size, ADDR_MEM2_SIM_SIZE);
Memory::Write_U32(target_imv->mem2_end, ADDR_MEM2_END);
Memory::Write_U32(target_imv->mem2_arena_begin, ADDR_MEM2_ARENA_BEGIN);
Memory::Write_U32(target_imv->mem2_arena_end, ADDR_MEM2_ARENA_END);
Memory::Write_U32(PLACEHOLDER, ADDR_PH2);
Memory::Write_U32(target_imv->ipc_buffer_begin, ADDR_IPC_BUFFER_BEGIN);
Memory::Write_U32(target_imv->ipc_buffer_end, ADDR_IPC_BUFFER_END);
Memory::Write_U32(target_imv->hollywood_revision, ADDR_HOLLYWOOD_REVISION);
Memory::Write_U32(PLACEHOLDER, ADDR_PH3);
Memory::Write_U32(target_imv->ios_version, ADDR_IOS_VERSION);
Memory::Write_U32(target_imv->ios_date, ADDR_IOS_DATE);
Memory::Write_U32(target_imv->ios_reserved_begin, ADDR_IOS_RESERVED_BEGIN);
Memory::Write_U32(target_imv->ios_reserved_end, ADDR_IOS_RESERVED_END);
Memory::Write_U32(PLACEHOLDER, ADDR_PH4);
Memory::Write_U32(PLACEHOLDER, ADDR_PH5);
Memory::Write_U32(target_imv->ram_vendor, ADDR_RAM_VENDOR);
Memory::Write_U8(0xDE, ADDR_BOOT_FLAG);
Memory::Write_U8(0xAD, ADDR_APPLOADER_FLAG);
Memory::Write_U16(0xBEEF, ADDR_DEVKIT_BOOT_PROGRAM_VERSION);
Memory::Write_U32(target_imv->sysmenu_sync, ADDR_SYSMENU_SYNC);
memory.Write_U32(target_imv->mem1_physical_size, ADDR_MEM1_SIZE);
memory.Write_U32(target_imv->mem1_simulated_size, ADDR_MEM1_SIM_SIZE);
memory.Write_U32(target_imv->mem1_end, ADDR_MEM1_END);
memory.Write_U32(target_imv->mem1_arena_begin, ADDR_MEM1_ARENA_BEGIN);
memory.Write_U32(target_imv->mem1_arena_end, ADDR_MEM1_ARENA_END);
memory.Write_U32(PLACEHOLDER, ADDR_PH1);
memory.Write_U32(target_imv->mem2_physical_size, ADDR_MEM2_SIZE);
memory.Write_U32(target_imv->mem2_simulated_size, ADDR_MEM2_SIM_SIZE);
memory.Write_U32(target_imv->mem2_end, ADDR_MEM2_END);
memory.Write_U32(target_imv->mem2_arena_begin, ADDR_MEM2_ARENA_BEGIN);
memory.Write_U32(target_imv->mem2_arena_end, ADDR_MEM2_ARENA_END);
memory.Write_U32(PLACEHOLDER, ADDR_PH2);
memory.Write_U32(target_imv->ipc_buffer_begin, ADDR_IPC_BUFFER_BEGIN);
memory.Write_U32(target_imv->ipc_buffer_end, ADDR_IPC_BUFFER_END);
memory.Write_U32(target_imv->hollywood_revision, ADDR_HOLLYWOOD_REVISION);
memory.Write_U32(PLACEHOLDER, ADDR_PH3);
memory.Write_U32(target_imv->ios_version, ADDR_IOS_VERSION);
memory.Write_U32(target_imv->ios_date, ADDR_IOS_DATE);
memory.Write_U32(target_imv->ios_reserved_begin, ADDR_IOS_RESERVED_BEGIN);
memory.Write_U32(target_imv->ios_reserved_end, ADDR_IOS_RESERVED_END);
memory.Write_U32(PLACEHOLDER, ADDR_PH4);
memory.Write_U32(PLACEHOLDER, ADDR_PH5);
memory.Write_U32(target_imv->ram_vendor, ADDR_RAM_VENDOR);
memory.Write_U8(0xDE, ADDR_BOOT_FLAG);
memory.Write_U8(0xAD, ADDR_APPLOADER_FLAG);
memory.Write_U16(0xBEEF, ADDR_DEVKIT_BOOT_PROGRAM_VERSION);
memory.Write_U32(target_imv->sysmenu_sync, ADDR_SYSMENU_SYNC);
Memory::Write_U32(target_imv->mem1_physical_size, ADDR_LEGACY_MEM_SIZE);
Memory::Write_U32(target_imv->mem1_arena_begin, ADDR_LEGACY_ARENA_LOW);
Memory::Write_U32(target_imv->mem1_arena_end, ADDR_LEGACY_ARENA_HIGH);
Memory::Write_U32(target_imv->mem1_simulated_size, ADDR_LEGACY_MEM_SIM_SIZE);
memory.Write_U32(target_imv->mem1_physical_size, ADDR_LEGACY_MEM_SIZE);
memory.Write_U32(target_imv->mem1_arena_begin, ADDR_LEGACY_ARENA_LOW);
memory.Write_U32(target_imv->mem1_arena_end, ADDR_LEGACY_ARENA_HIGH);
memory.Write_U32(target_imv->mem1_simulated_size, ADDR_LEGACY_MEM_SIM_SIZE);
RAMOverrideForIOSMemoryValues(setup_type);
@ -193,14 +196,18 @@ static bool SetupMemory(u64 ios_title_id, MemorySetupType setup_type)
static void ResetAndPausePPC()
{
// This should be cleared when the PPC is released so that the write is not observable.
Memory::Write_U32(0x48000000, 0x00000000); // b 0x0
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(0x48000000, 0x00000000); // b 0x0
PowerPC::Reset();
PC = 0;
}
static void ReleasePPC()
{
Memory::Write_U32(0, 0);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(0, 0);
// HLE the bootstub that jumps to 0x3400.
// NAND titles start with address translation off at 0x3400 (via the PPC bootstub)
// The state of other CPU registers (like the BAT registers) doesn't matter much
@ -210,7 +217,9 @@ static void ReleasePPC()
static void ReleasePPCAncast()
{
Memory::Write_U32(0, 0);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(0, 0);
// On a real console the Espresso verifies and decrypts the Ancast image,
// then jumps to the decrypted ancast body.
// The Ancast loader already did this, so just jump to the decrypted body.
@ -223,19 +232,22 @@ void RAMOverrideForIOSMemoryValues(MemorySetupType setup_type)
if (!Config::Get(Config::MAIN_RAM_OVERRIDE_ENABLE))
return;
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// Some unstated constants that can be inferred.
const u32 ipc_buffer_size =
Memory::Read_U32(ADDR_IPC_BUFFER_END) - Memory::Read_U32(ADDR_IPC_BUFFER_BEGIN);
memory.Read_U32(ADDR_IPC_BUFFER_END) - memory.Read_U32(ADDR_IPC_BUFFER_BEGIN);
const u32 ios_reserved_size =
Memory::Read_U32(ADDR_IOS_RESERVED_END) - Memory::Read_U32(ADDR_IOS_RESERVED_BEGIN);
memory.Read_U32(ADDR_IOS_RESERVED_END) - memory.Read_U32(ADDR_IOS_RESERVED_BEGIN);
const u32 mem1_physical_size = Memory::GetRamSizeReal();
const u32 mem1_simulated_size = Memory::GetRamSizeReal();
const u32 mem1_physical_size = memory.GetRamSizeReal();
const u32 mem1_simulated_size = memory.GetRamSizeReal();
const u32 mem1_end = Memory::MEM1_BASE_ADDR + mem1_simulated_size;
const u32 mem1_arena_begin = 0;
const u32 mem1_arena_end = mem1_end;
const u32 mem2_physical_size = Memory::GetExRamSizeReal();
const u32 mem2_simulated_size = Memory::GetExRamSizeReal();
const u32 mem2_physical_size = memory.GetExRamSizeReal();
const u32 mem2_simulated_size = memory.GetExRamSizeReal();
const u32 mem2_end = Memory::MEM2_BASE_ADDR + mem2_simulated_size - ios_reserved_size;
const u32 mem2_arena_begin = Memory::MEM2_BASE_ADDR + 0x800U;
const u32 mem2_arena_end = mem2_end - ipc_buffer_size;
@ -247,31 +259,33 @@ void RAMOverrideForIOSMemoryValues(MemorySetupType setup_type)
if (setup_type == MemorySetupType::Full)
{
// Overwriting these after the game's apploader sets them would be bad
Memory::Write_U32(mem1_physical_size, ADDR_MEM1_SIZE);
Memory::Write_U32(mem1_simulated_size, ADDR_MEM1_SIM_SIZE);
Memory::Write_U32(mem1_end, ADDR_MEM1_END);
Memory::Write_U32(mem1_arena_begin, ADDR_MEM1_ARENA_BEGIN);
Memory::Write_U32(mem1_arena_end, ADDR_MEM1_ARENA_END);
memory.Write_U32(mem1_physical_size, ADDR_MEM1_SIZE);
memory.Write_U32(mem1_simulated_size, ADDR_MEM1_SIM_SIZE);
memory.Write_U32(mem1_end, ADDR_MEM1_END);
memory.Write_U32(mem1_arena_begin, ADDR_MEM1_ARENA_BEGIN);
memory.Write_U32(mem1_arena_end, ADDR_MEM1_ARENA_END);
Memory::Write_U32(mem1_physical_size, ADDR_LEGACY_MEM_SIZE);
Memory::Write_U32(mem1_arena_begin, ADDR_LEGACY_ARENA_LOW);
Memory::Write_U32(mem1_arena_end, ADDR_LEGACY_ARENA_HIGH);
Memory::Write_U32(mem1_simulated_size, ADDR_LEGACY_MEM_SIM_SIZE);
memory.Write_U32(mem1_physical_size, ADDR_LEGACY_MEM_SIZE);
memory.Write_U32(mem1_arena_begin, ADDR_LEGACY_ARENA_LOW);
memory.Write_U32(mem1_arena_end, ADDR_LEGACY_ARENA_HIGH);
memory.Write_U32(mem1_simulated_size, ADDR_LEGACY_MEM_SIM_SIZE);
}
Memory::Write_U32(mem2_physical_size, ADDR_MEM2_SIZE);
Memory::Write_U32(mem2_simulated_size, ADDR_MEM2_SIM_SIZE);
Memory::Write_U32(mem2_end, ADDR_MEM2_END);
Memory::Write_U32(mem2_arena_begin, ADDR_MEM2_ARENA_BEGIN);
Memory::Write_U32(mem2_arena_end, ADDR_MEM2_ARENA_END);
Memory::Write_U32(ipc_buffer_begin, ADDR_IPC_BUFFER_BEGIN);
Memory::Write_U32(ipc_buffer_end, ADDR_IPC_BUFFER_END);
Memory::Write_U32(ios_reserved_begin, ADDR_IOS_RESERVED_BEGIN);
Memory::Write_U32(ios_reserved_end, ADDR_IOS_RESERVED_END);
memory.Write_U32(mem2_physical_size, ADDR_MEM2_SIZE);
memory.Write_U32(mem2_simulated_size, ADDR_MEM2_SIM_SIZE);
memory.Write_U32(mem2_end, ADDR_MEM2_END);
memory.Write_U32(mem2_arena_begin, ADDR_MEM2_ARENA_BEGIN);
memory.Write_U32(mem2_arena_end, ADDR_MEM2_ARENA_END);
memory.Write_U32(ipc_buffer_begin, ADDR_IPC_BUFFER_BEGIN);
memory.Write_U32(ipc_buffer_end, ADDR_IPC_BUFFER_END);
memory.Write_U32(ios_reserved_begin, ADDR_IOS_RESERVED_BEGIN);
memory.Write_U32(ios_reserved_end, ADDR_IOS_RESERVED_END);
}
void WriteReturnValue(s32 value, u32 address)
{
Memory::Write_U32(static_cast<u32>(value), address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(static_cast<u32>(value), address);
}
Kernel::Kernel(IOSC::ConsoleType console_type) : m_iosc(console_type)
@ -751,13 +765,14 @@ void Kernel::EnqueueIPCRequest(u32 address)
void Kernel::EnqueueIPCReply(const Request& request, const s32 return_value, s64 cycles_in_future,
CoreTiming::FromThread from)
{
Memory::Write_U32(static_cast<u32>(return_value), request.address + 4);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(static_cast<u32>(return_value), request.address + 4);
// IOS writes back the command that was responded to in the FD field.
Memory::Write_U32(request.command, request.address + 8);
memory.Write_U32(request.command, request.address + 8);
// IOS also overwrites the command type with the reply type.
Memory::Write_U32(IPC_REPLY, request.address);
Core::System::GetInstance().GetCoreTiming().ScheduleEvent(cycles_in_future, s_event_enqueue,
request.address, from);
memory.Write_U32(IPC_REPLY, request.address);
system.GetCoreTiming().ScheduleEvent(cycles_in_future, s_event_enqueue, request.address, from);
}
void Kernel::HandleIPCEvent(u64 userdata)

View file

@ -24,6 +24,7 @@
#include "Core/Host.h"
#include "Core/PowerPC/PPCSymbolDB.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
namespace IOS::HLE::MIOS
{
@ -32,7 +33,9 @@ static void ReinitHardware()
SConfig::GetInstance().bWii = false;
// IOS clears mem2 and overwrites it with pseudo-random data (for security).
std::memset(Memory::m_pEXRAM, 0, Memory::GetExRamSizeReal());
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
std::memset(memory.GetEXRAM(), 0, memory.GetExRamSizeReal());
// MIOS appears to only reset the DI and the PPC.
// HACK However, resetting DI will reset the DTK config, which is set by the system menu
// (and not by MIOS), causing games that use DTK to break. Perhaps MIOS doesn't actually
@ -52,8 +55,10 @@ constexpr u32 ADDRESS_INIT_SEMAPHORE = 0x30f8;
bool Load()
{
Memory::Write_U32(0x00000000, ADDRESS_INIT_SEMAPHORE);
Memory::Write_U32(0x09142001, 0x3180);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(0x00000000, ADDRESS_INIT_SEMAPHORE);
memory.Write_U32(0x09142001, 0x3180);
ReinitHardware();
NOTICE_LOG_FMT(IOS, "Reinitialised hardware.");
@ -79,11 +84,11 @@ bool Load()
// IOS writes 0 to 0x30f8 before bootstrapping the PPC. Once started, the IPL eventually writes
// 0xdeadbeef there, then waits for it to be cleared by IOS before continuing.
while (Memory::Read_U32(ADDRESS_INIT_SEMAPHORE) != 0xdeadbeef)
while (memory.Read_U32(ADDRESS_INIT_SEMAPHORE) != 0xdeadbeef)
PowerPC::SingleStep();
PowerPC::SetMode(core_mode);
Memory::Write_U32(0x00000000, ADDRESS_INIT_SEMAPHORE);
memory.Write_U32(0x00000000, ADDRESS_INIT_SEMAPHORE);
NOTICE_LOG_FMT(IOS, "IPL ready.");
SConfig::GetInstance().m_is_mios = true;
DVDInterface::UpdateRunningGameMetadata();

View file

@ -31,6 +31,7 @@
#include "Core/IOS/Network/ICMP.h"
#include "Core/IOS/Network/MACUtils.h"
#include "Core/IOS/Network/Socket.h"
#include "Core/System.h"
#ifdef _WIN32
#include <iphlpapi.h>
@ -381,9 +382,12 @@ IPCReply NetIPTopDevice::HandleInitInterfaceRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleSocketRequest(const IOCtlRequest& request)
{
const u32 af = Memory::Read_U32(request.buffer_in);
const u32 type = Memory::Read_U32(request.buffer_in + 4);
const u32 prot = Memory::Read_U32(request.buffer_in + 8);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 af = memory.Read_U32(request.buffer_in);
const u32 type = memory.Read_U32(request.buffer_in + 4);
const u32 prot = memory.Read_U32(request.buffer_in + 8);
WiiSockMan& sm = WiiSockMan::GetInstance();
const s32 return_value = sm.NewSocket(af, type, prot);
@ -398,7 +402,10 @@ IPCReply NetIPTopDevice::HandleSocketRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleICMPSocketRequest(const IOCtlRequest& request)
{
const u32 pf = Memory::Read_U32(request.buffer_in);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 pf = memory.Read_U32(request.buffer_in);
WiiSockMan& sm = WiiSockMan::GetInstance();
const s32 return_value = sm.NewSocket(pf, SOCK_RAW, IPPROTO_ICMP);
@ -408,7 +415,10 @@ IPCReply NetIPTopDevice::HandleICMPSocketRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleCloseRequest(const IOCtlRequest& request)
{
const u32 fd = Memory::Read_U32(request.buffer_in);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 fd = memory.Read_U32(request.buffer_in);
WiiSockMan& sm = WiiSockMan::GetInstance();
const s32 return_value = sm.DeleteSocket(fd);
const char* const close_fn =
@ -421,7 +431,10 @@ IPCReply NetIPTopDevice::HandleCloseRequest(const IOCtlRequest& request)
std::optional<IPCReply> NetIPTopDevice::HandleDoSockRequest(const IOCtlRequest& request)
{
const u32 fd = Memory::Read_U32(request.buffer_in);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 fd = memory.Read_U32(request.buffer_in);
WiiSockMan& sm = WiiSockMan::GetInstance();
sm.DoSock(fd, request, static_cast<NET_IOCTL>(request.request));
return std::nullopt;
@ -436,8 +449,11 @@ IPCReply NetIPTopDevice::HandleShutdownRequest(const IOCtlRequest& request)
return IPCReply(-SO_EINVAL);
}
const u32 fd = Memory::Read_U32(request.buffer_in);
const u32 how = Memory::Read_U32(request.buffer_in + 4);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 fd = memory.Read_U32(request.buffer_in);
const u32 how = memory.Read_U32(request.buffer_in + 4);
WiiSockMan& sm = WiiSockMan::GetInstance();
const s32 return_value = sm.ShutdownSocket(fd, how);
@ -447,8 +463,11 @@ IPCReply NetIPTopDevice::HandleShutdownRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleListenRequest(const IOCtlRequest& request)
{
u32 fd = Memory::Read_U32(request.buffer_in);
u32 BACKLOG = Memory::Read_U32(request.buffer_in + 0x04);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u32 fd = memory.Read_U32(request.buffer_in);
u32 BACKLOG = memory.Read_U32(request.buffer_in + 0x04);
u32 ret = listen(WiiSockMan::GetInstance().GetHostSocket(fd), BACKLOG);
request.Log(GetDeviceName(), Common::Log::LogType::IOS_WC24);
@ -457,9 +476,12 @@ IPCReply NetIPTopDevice::HandleListenRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleGetSockOptRequest(const IOCtlRequest& request)
{
u32 fd = Memory::Read_U32(request.buffer_out);
u32 level = Memory::Read_U32(request.buffer_out + 4);
u32 optname = Memory::Read_U32(request.buffer_out + 8);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u32 fd = memory.Read_U32(request.buffer_out);
u32 level = memory.Read_U32(request.buffer_out + 4);
u32 optname = memory.Read_U32(request.buffer_out + 8);
request.Log(GetDeviceName(), Common::Log::LogType::IOS_WC24);
@ -474,15 +496,15 @@ IPCReply NetIPTopDevice::HandleGetSockOptRequest(const IOCtlRequest& request)
(char*)&optval, (socklen_t*)&optlen);
const s32 return_value = WiiSockMan::GetNetErrorCode(ret, "SO_GETSOCKOPT", false);
Memory::Write_U32(optlen, request.buffer_out + 0xC);
Memory::CopyToEmu(request.buffer_out + 0x10, optval, optlen);
memory.Write_U32(optlen, request.buffer_out + 0xC);
memory.CopyToEmu(request.buffer_out + 0x10, optval, optlen);
if (optname == SO_ERROR)
{
s32 last_error = WiiSockMan::GetInstance().GetLastNetError();
Memory::Write_U32(sizeof(s32), request.buffer_out + 0xC);
Memory::Write_U32(last_error, request.buffer_out + 0x10);
memory.Write_U32(sizeof(s32), request.buffer_out + 0xC);
memory.Write_U32(last_error, request.buffer_out + 0x10);
}
return IPCReply(return_value);
@ -490,13 +512,16 @@ IPCReply NetIPTopDevice::HandleGetSockOptRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleSetSockOptRequest(const IOCtlRequest& request)
{
const u32 fd = Memory::Read_U32(request.buffer_in);
const u32 level = Memory::Read_U32(request.buffer_in + 4);
const u32 optname = Memory::Read_U32(request.buffer_in + 8);
u32 optlen = Memory::Read_U32(request.buffer_in + 0xc);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 fd = memory.Read_U32(request.buffer_in);
const u32 level = memory.Read_U32(request.buffer_in + 4);
const u32 optname = memory.Read_U32(request.buffer_in + 8);
u32 optlen = memory.Read_U32(request.buffer_in + 0xc);
u8 optval[20];
optlen = std::min(optlen, (u32)sizeof(optval));
Memory::CopyFromEmu(optval, request.buffer_in + 0x10, optlen);
memory.CopyFromEmu(optval, request.buffer_in + 0x10, optlen);
INFO_LOG_FMT(IOS_NET,
"IOCTL_SO_SETSOCKOPT({:08x}, {:08x}, {:08x}, {:08x}) "
@ -525,7 +550,10 @@ IPCReply NetIPTopDevice::HandleSetSockOptRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleGetSockNameRequest(const IOCtlRequest& request)
{
u32 fd = Memory::Read_U32(request.buffer_in);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u32 fd = memory.Read_U32(request.buffer_in);
request.Log(GetDeviceName(), Common::Log::LogType::IOS_WC24);
@ -537,13 +565,13 @@ IPCReply NetIPTopDevice::HandleGetSockNameRequest(const IOCtlRequest& request)
WARN_LOG_FMT(IOS_NET, "IOCTL_SO_GETSOCKNAME output buffer is too small. Truncating");
if (request.buffer_out_size > 0)
Memory::Write_U8(request.buffer_out_size, request.buffer_out);
memory.Write_U8(request.buffer_out_size, request.buffer_out);
if (request.buffer_out_size > 1)
Memory::Write_U8(sa.sa_family & 0xFF, request.buffer_out + 1);
memory.Write_U8(sa.sa_family & 0xFF, request.buffer_out + 1);
if (request.buffer_out_size > 2)
{
Memory::CopyToEmu(request.buffer_out + 2, &sa.sa_data,
std::min<size_t>(sizeof(sa.sa_data), request.buffer_out_size - 2));
memory.CopyToEmu(request.buffer_out + 2, &sa.sa_data,
std::min<size_t>(sizeof(sa.sa_data), request.buffer_out_size - 2));
}
return IPCReply(ret);
@ -551,7 +579,10 @@ IPCReply NetIPTopDevice::HandleGetSockNameRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleGetPeerNameRequest(const IOCtlRequest& request)
{
u32 fd = Memory::Read_U32(request.buffer_in);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u32 fd = memory.Read_U32(request.buffer_in);
sockaddr sa;
socklen_t sa_len = sizeof(sa);
@ -561,13 +592,13 @@ IPCReply NetIPTopDevice::HandleGetPeerNameRequest(const IOCtlRequest& request)
WARN_LOG_FMT(IOS_NET, "IOCTL_SO_GETPEERNAME output buffer is too small. Truncating");
if (request.buffer_out_size > 0)
Memory::Write_U8(request.buffer_out_size, request.buffer_out);
memory.Write_U8(request.buffer_out_size, request.buffer_out);
if (request.buffer_out_size > 1)
Memory::Write_U8(AF_INET, request.buffer_out + 1);
memory.Write_U8(AF_INET, request.buffer_out + 1);
if (request.buffer_out_size > 2)
{
Memory::CopyToEmu(request.buffer_out + 2, &sa.sa_data,
std::min<size_t>(sizeof(sa.sa_data), request.buffer_out_size - 2));
memory.CopyToEmu(request.buffer_out + 2, &sa.sa_data,
std::min<size_t>(sizeof(sa.sa_data), request.buffer_out_size - 2));
}
INFO_LOG_FMT(IOS_NET, "IOCTL_SO_GETPEERNAME({:x})", fd);
@ -585,7 +616,10 @@ IPCReply NetIPTopDevice::HandleGetHostIDRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleInetAToNRequest(const IOCtlRequest& request)
{
const std::string hostname = Memory::GetString(request.buffer_in);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const std::string hostname = memory.GetString(request.buffer_in);
struct hostent* remoteHost = gethostbyname(hostname.c_str());
if (remoteHost == nullptr || remoteHost->h_addr_list == nullptr ||
@ -601,7 +635,7 @@ IPCReply NetIPTopDevice::HandleInetAToNRequest(const IOCtlRequest& request)
}
const auto ip = Common::swap32(reinterpret_cast<u8*>(remoteHost->h_addr_list[0]));
Memory::Write_U32(ip, request.buffer_out);
memory.Write_U32(ip, request.buffer_out);
INFO_LOG_FMT(IOS_NET,
"IOCTL_SO_INETATON = 0 "
@ -614,24 +648,30 @@ IPCReply NetIPTopDevice::HandleInetAToNRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleInetPToNRequest(const IOCtlRequest& request)
{
const std::string address = Memory::GetString(request.buffer_in);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const std::string address = memory.GetString(request.buffer_in);
INFO_LOG_FMT(IOS_NET, "IOCTL_SO_INETPTON (Translating: {})", address);
return IPCReply(inet_pton(address.c_str(), Memory::GetPointer(request.buffer_out + 4)));
return IPCReply(inet_pton(address.c_str(), memory.GetPointer(request.buffer_out + 4)));
}
IPCReply NetIPTopDevice::HandleInetNToPRequest(const IOCtlRequest& request)
{
// u32 af = Memory::Read_U32(BufferIn);
// u32 validAddress = Memory::Read_U32(request.buffer_in + 4);
// u32 src = Memory::Read_U32(request.buffer_in + 8);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// u32 af = memory.Read_U32(BufferIn);
// u32 validAddress = memory.Read_U32(request.buffer_in + 4);
// u32 src = memory.Read_U32(request.buffer_in + 8);
char ip_s[16];
sprintf(ip_s, "%i.%i.%i.%i", Memory::Read_U8(request.buffer_in + 8),
Memory::Read_U8(request.buffer_in + 8 + 1), Memory::Read_U8(request.buffer_in + 8 + 2),
Memory::Read_U8(request.buffer_in + 8 + 3));
sprintf(ip_s, "%i.%i.%i.%i", memory.Read_U8(request.buffer_in + 8),
memory.Read_U8(request.buffer_in + 8 + 1), memory.Read_U8(request.buffer_in + 8 + 2),
memory.Read_U8(request.buffer_in + 8 + 3));
INFO_LOG_FMT(IOS_NET, "IOCTL_SO_INETNTOP {}", ip_s);
Memory::CopyToEmu(request.buffer_out, reinterpret_cast<u8*>(ip_s), std::strlen(ip_s));
memory.CopyToEmu(request.buffer_out, reinterpret_cast<u8*>(ip_s), std::strlen(ip_s));
return IPCReply(0);
}
@ -642,8 +682,11 @@ std::optional<IPCReply> NetIPTopDevice::HandlePollRequest(const IOCtlRequest& re
if (!request.buffer_in || !request.buffer_out)
return IPCReply(-SO_EINVAL);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// Negative timeout indicates wait forever
const s64 timeout = static_cast<s64>(Memory::Read_U64(request.buffer_in));
const s64 timeout = static_cast<s64>(memory.Read_U64(request.buffer_in));
const u32 nfds = request.buffer_out_size / 0xc;
if (nfds == 0 || nfds > WII_SOCKET_FD_MAX)
@ -656,9 +699,9 @@ std::optional<IPCReply> NetIPTopDevice::HandlePollRequest(const IOCtlRequest& re
for (u32 i = 0; i < nfds; ++i)
{
const s32 wii_fd = Memory::Read_U32(request.buffer_out + 0xc * i);
ufds[i].fd = sm.GetHostSocket(wii_fd); // fd
const int events = Memory::Read_U32(request.buffer_out + 0xc * i + 4); // events
const s32 wii_fd = memory.Read_U32(request.buffer_out + 0xc * i);
ufds[i].fd = sm.GetHostSocket(wii_fd); // fd
const int events = memory.Read_U32(request.buffer_out + 0xc * i + 4); // events
ufds[i].revents = 0;
// Translate Wii to native events
@ -686,7 +729,10 @@ IPCReply NetIPTopDevice::HandleGetHostByNameRequest(const IOCtlRequest& request)
return IPCReply(-1);
}
const std::string hostname = Memory::GetString(request.buffer_in);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const std::string hostname = memory.GetString(request.buffer_in);
hostent* remoteHost = gethostbyname(hostname.c_str());
INFO_LOG_FMT(IOS_NET,
@ -721,9 +767,8 @@ IPCReply NetIPTopDevice::HandleGetHostByNameRequest(const IOCtlRequest& request)
ERROR_LOG_FMT(IOS_NET, "Hostname too long in IOCTL_SO_GETHOSTBYNAME");
return IPCReply(-1);
}
Memory::CopyToEmu(request.buffer_out + GETHOSTBYNAME_STRUCT_SIZE, remoteHost->h_name,
name_length);
Memory::Write_U32(request.buffer_out + GETHOSTBYNAME_STRUCT_SIZE, request.buffer_out);
memory.CopyToEmu(request.buffer_out + GETHOSTBYNAME_STRUCT_SIZE, remoteHost->h_name, name_length);
memory.Write_U32(request.buffer_out + GETHOSTBYNAME_STRUCT_SIZE, request.buffer_out);
// IP address list; located at offset 0x110.
u32 num_ip_addr = 0;
@ -736,30 +781,30 @@ IPCReply NetIPTopDevice::HandleGetHostByNameRequest(const IOCtlRequest& request)
for (u32 i = 0; i < num_ip_addr; ++i)
{
u32 addr = request.buffer_out + GETHOSTBYNAME_IP_LIST_OFFSET + i * 4;
Memory::Write_U32_Swap(*(u32*)(remoteHost->h_addr_list[i]), addr);
memory.Write_U32_Swap(*(u32*)(remoteHost->h_addr_list[i]), addr);
}
// List of pointers to IP addresses; located at offset 0x340.
// This must be exact: PPC code to convert the struct hardcodes
// this offset.
static const u32 GETHOSTBYNAME_IP_PTR_LIST_OFFSET = 0x340;
Memory::Write_U32(request.buffer_out + GETHOSTBYNAME_IP_PTR_LIST_OFFSET, request.buffer_out + 12);
memory.Write_U32(request.buffer_out + GETHOSTBYNAME_IP_PTR_LIST_OFFSET, request.buffer_out + 12);
for (u32 i = 0; i < num_ip_addr; ++i)
{
u32 addr = request.buffer_out + GETHOSTBYNAME_IP_PTR_LIST_OFFSET + i * 4;
Memory::Write_U32(request.buffer_out + GETHOSTBYNAME_IP_LIST_OFFSET + i * 4, addr);
memory.Write_U32(request.buffer_out + GETHOSTBYNAME_IP_LIST_OFFSET + i * 4, addr);
}
Memory::Write_U32(0, request.buffer_out + GETHOSTBYNAME_IP_PTR_LIST_OFFSET + num_ip_addr * 4);
memory.Write_U32(0, request.buffer_out + GETHOSTBYNAME_IP_PTR_LIST_OFFSET + num_ip_addr * 4);
// Aliases - empty. (Hardware doesn't return anything.)
Memory::Write_U32(request.buffer_out + GETHOSTBYNAME_IP_PTR_LIST_OFFSET + num_ip_addr * 4,
request.buffer_out + 4);
memory.Write_U32(request.buffer_out + GETHOSTBYNAME_IP_PTR_LIST_OFFSET + num_ip_addr * 4,
request.buffer_out + 4);
// Returned struct must be ipv4.
ASSERT_MSG(IOS_NET, remoteHost->h_addrtype == AF_INET && remoteHost->h_length == sizeof(u32),
"returned host info is not IPv4");
Memory::Write_U16(AF_INET, request.buffer_out + 8);
Memory::Write_U16(sizeof(u32), request.buffer_out + 10);
memory.Write_U16(AF_INET, request.buffer_out + 8);
memory.Write_U16(sizeof(u32), request.buffer_out + 10);
return IPCReply(0);
}
@ -772,10 +817,13 @@ IPCReply NetIPTopDevice::HandleICMPCancelRequest(const IOCtlRequest& request)
IPCReply NetIPTopDevice::HandleGetInterfaceOptRequest(const IOCtlVRequest& request)
{
const u32 param = Memory::Read_U32(request.in_vectors[0].address);
const u32 param2 = Memory::Read_U32(request.in_vectors[0].address + 4);
const u32 param3 = Memory::Read_U32(request.io_vectors[0].address);
const u32 param4 = Memory::Read_U32(request.io_vectors[1].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 param = memory.Read_U32(request.in_vectors[0].address);
const u32 param2 = memory.Read_U32(request.in_vectors[0].address + 4);
const u32 param3 = memory.Read_U32(request.io_vectors[0].address);
const u32 param4 = memory.Read_U32(request.io_vectors[1].address);
u32 param5 = 0;
if (param != 0xfffe)
@ -786,7 +834,7 @@ IPCReply NetIPTopDevice::HandleGetInterfaceOptRequest(const IOCtlVRequest& reque
if (request.io_vectors[0].size >= 8)
{
param5 = Memory::Read_U32(request.io_vectors[0].address + 4);
param5 = memory.Read_U32(request.io_vectors[0].address + 4);
}
INFO_LOG_FMT(IOS_NET,
@ -893,63 +941,63 @@ IPCReply NetIPTopDevice::HandleGetInterfaceOptRequest(const IOCtlVRequest& reque
INFO_LOG_FMT(IOS_NET, "Primary DNS: {:X}", address);
INFO_LOG_FMT(IOS_NET, "Secondary DNS: {:X}", default_backup_dns_resolver);
Memory::Write_U32(address, request.io_vectors[0].address);
Memory::Write_U32(default_backup_dns_resolver, request.io_vectors[0].address + 4);
memory.Write_U32(address, request.io_vectors[0].address);
memory.Write_U32(default_backup_dns_resolver, request.io_vectors[0].address + 4);
break;
}
case 0x1003: // error
Memory::Write_U32(0, request.io_vectors[0].address);
memory.Write_U32(0, request.io_vectors[0].address);
break;
case 0x1004: // mac address
{
const Common::MACAddress address = IOS::Net::GetMACAddress();
Memory::CopyToEmu(request.io_vectors[0].address, address.data(), address.size());
memory.CopyToEmu(request.io_vectors[0].address, address.data(), address.size());
break;
}
case 0x1005: // link state
Memory::Write_U32(1, request.io_vectors[0].address);
memory.Write_U32(1, request.io_vectors[0].address);
break;
case 0x3001: // hardcoded value
Memory::Write_U32(0x10, request.io_vectors[0].address);
memory.Write_U32(0x10, request.io_vectors[0].address);
break;
case 0x4002: // ip addr numberHandle
Memory::Write_U32(1, request.io_vectors[0].address);
memory.Write_U32(1, request.io_vectors[0].address);
break;
case 0x4003: // ip addr table
{
// XXX: this isn't exactly right; the buffer can be larger than 12 bytes, in which case
// SO can write 12 more bytes.
Memory::Write_U32(0xC, request.io_vectors[1].address);
memory.Write_U32(0xC, request.io_vectors[1].address);
const DefaultInterface interface = GetSystemDefaultInterfaceOrFallback();
Memory::Write_U32(Common::swap32(interface.inet), request.io_vectors[0].address);
Memory::Write_U32(Common::swap32(interface.netmask), request.io_vectors[0].address + 4);
Memory::Write_U32(Common::swap32(interface.broadcast), request.io_vectors[0].address + 8);
memory.Write_U32(Common::swap32(interface.inet), request.io_vectors[0].address);
memory.Write_U32(Common::swap32(interface.netmask), request.io_vectors[0].address + 4);
memory.Write_U32(Common::swap32(interface.broadcast), request.io_vectors[0].address + 8);
break;
}
case 0x4005: // hardcoded value
Memory::Write_U32(0x20, request.io_vectors[0].address);
memory.Write_U32(0x20, request.io_vectors[0].address);
break;
case 0x6003: // hardcoded value
Memory::Write_U32(0x80, request.io_vectors[0].address);
memory.Write_U32(0x80, request.io_vectors[0].address);
break;
case 0x600a: // hardcoded value
Memory::Write_U32(0x80, request.io_vectors[0].address);
memory.Write_U32(0x80, request.io_vectors[0].address);
break;
case 0x600c: // hardcoded value
Memory::Write_U32(0x80, request.io_vectors[0].address);
memory.Write_U32(0x80, request.io_vectors[0].address);
break;
case 0xb002: // hardcoded value
Memory::Write_U32(2, request.io_vectors[0].address);
memory.Write_U32(2, request.io_vectors[0].address);
break;
default:
@ -962,7 +1010,10 @@ IPCReply NetIPTopDevice::HandleGetInterfaceOptRequest(const IOCtlVRequest& reque
std::optional<IPCReply> NetIPTopDevice::HandleSendToRequest(const IOCtlVRequest& request)
{
u32 fd = Memory::Read_U32(request.in_vectors[1].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u32 fd = memory.Read_U32(request.in_vectors[1].address);
WiiSockMan& sm = WiiSockMan::GetInstance();
sm.DoSock(fd, request, IOCTLV_SO_SENDTO);
return std::nullopt;
@ -970,7 +1021,10 @@ std::optional<IPCReply> NetIPTopDevice::HandleSendToRequest(const IOCtlVRequest&
std::optional<IPCReply> NetIPTopDevice::HandleRecvFromRequest(const IOCtlVRequest& request)
{
u32 fd = Memory::Read_U32(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u32 fd = memory.Read_U32(request.in_vectors[0].address);
WiiSockMan& sm = WiiSockMan::GetInstance();
sm.DoSock(fd, request, IOCTLV_SO_RECVFROM);
return std::nullopt;
@ -978,16 +1032,19 @@ std::optional<IPCReply> NetIPTopDevice::HandleRecvFromRequest(const IOCtlVReques
IPCReply NetIPTopDevice::HandleGetAddressInfoRequest(const IOCtlVRequest& request)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
addrinfo hints;
const bool hints_valid = request.in_vectors.size() > 2 && request.in_vectors[2].size;
if (hints_valid)
{
hints.ai_flags = Memory::Read_U32(request.in_vectors[2].address);
hints.ai_family = Memory::Read_U32(request.in_vectors[2].address + 0x4);
hints.ai_socktype = Memory::Read_U32(request.in_vectors[2].address + 0x8);
hints.ai_protocol = Memory::Read_U32(request.in_vectors[2].address + 0xC);
hints.ai_addrlen = Memory::Read_U32(request.in_vectors[2].address + 0x10);
hints.ai_flags = memory.Read_U32(request.in_vectors[2].address);
hints.ai_family = memory.Read_U32(request.in_vectors[2].address + 0x4);
hints.ai_socktype = memory.Read_U32(request.in_vectors[2].address + 0x8);
hints.ai_protocol = memory.Read_U32(request.in_vectors[2].address + 0xC);
hints.ai_addrlen = memory.Read_U32(request.in_vectors[2].address + 0x10);
hints.ai_canonname = nullptr;
hints.ai_addr = nullptr;
hints.ai_next = nullptr;
@ -999,7 +1056,7 @@ IPCReply NetIPTopDevice::HandleGetAddressInfoRequest(const IOCtlVRequest& reques
const char* pNodeName = nullptr;
if (!request.in_vectors.empty() && request.in_vectors[0].size > 0)
{
nodeNameStr = Memory::GetString(request.in_vectors[0].address, request.in_vectors[0].size);
nodeNameStr = memory.GetString(request.in_vectors[0].address, request.in_vectors[0].size);
pNodeName = nodeNameStr.c_str();
}
@ -1007,7 +1064,7 @@ IPCReply NetIPTopDevice::HandleGetAddressInfoRequest(const IOCtlVRequest& reques
const char* pServiceName = nullptr;
if (request.in_vectors.size() > 1 && request.in_vectors[1].size > 0)
{
serviceNameStr = Memory::GetString(request.in_vectors[1].address, request.in_vectors[1].size);
serviceNameStr = memory.GetString(request.in_vectors[1].address, request.in_vectors[1].size);
pServiceName = serviceNameStr.c_str();
}
@ -1020,35 +1077,35 @@ IPCReply NetIPTopDevice::HandleGetAddressInfoRequest(const IOCtlVRequest& reques
constexpr size_t WII_ADDR_INFO_SIZE = 0x20;
for (addrinfo* result_iter = result; result_iter != nullptr; result_iter = result_iter->ai_next)
{
Memory::Write_U32(result_iter->ai_flags, addr);
Memory::Write_U32(result_iter->ai_family, addr + 0x04);
Memory::Write_U32(result_iter->ai_socktype, addr + 0x08);
Memory::Write_U32(result_iter->ai_protocol, addr + 0x0C);
Memory::Write_U32((u32)result_iter->ai_addrlen, addr + 0x10);
memory.Write_U32(result_iter->ai_flags, addr);
memory.Write_U32(result_iter->ai_family, addr + 0x04);
memory.Write_U32(result_iter->ai_socktype, addr + 0x08);
memory.Write_U32(result_iter->ai_protocol, addr + 0x0C);
memory.Write_U32((u32)result_iter->ai_addrlen, addr + 0x10);
// what to do? where to put? the buffer of 0x834 doesn't allow space for this
Memory::Write_U32(/*result->ai_cannonname*/ 0, addr + 0x14);
memory.Write_U32(/*result->ai_cannonname*/ 0, addr + 0x14);
if (result_iter->ai_addr)
{
Memory::Write_U32(sockoffset, addr + 0x18);
Memory::Write_U8(result_iter->ai_addrlen & 0xFF, sockoffset);
Memory::Write_U8(result_iter->ai_addr->sa_family & 0xFF, sockoffset + 0x01);
Memory::CopyToEmu(sockoffset + 0x2, result_iter->ai_addr->sa_data,
sizeof(result_iter->ai_addr->sa_data));
memory.Write_U32(sockoffset, addr + 0x18);
memory.Write_U8(result_iter->ai_addrlen & 0xFF, sockoffset);
memory.Write_U8(result_iter->ai_addr->sa_family & 0xFF, sockoffset + 0x01);
memory.CopyToEmu(sockoffset + 0x2, result_iter->ai_addr->sa_data,
sizeof(result_iter->ai_addr->sa_data));
sockoffset += 0x1C;
}
else
{
Memory::Write_U32(0, addr + 0x18);
memory.Write_U32(0, addr + 0x18);
}
if (result_iter->ai_next)
{
Memory::Write_U32(addr + WII_ADDR_INFO_SIZE, addr + 0x1C);
memory.Write_U32(addr + WII_ADDR_INFO_SIZE, addr + 0x1C);
}
else
{
Memory::Write_U32(0, addr + 0x1C);
memory.Write_U32(0, addr + 0x1C);
}
addr += WII_ADDR_INFO_SIZE;
@ -1075,19 +1132,22 @@ IPCReply NetIPTopDevice::HandleICMPPingRequest(const IOCtlVRequest& request)
u32 ip;
} ip_info;
const u32 fd = Memory::Read_U32(request.in_vectors[0].address);
const u32 num_ip = Memory::Read_U32(request.in_vectors[0].address + 4);
const u64 timeout = Memory::Read_U64(request.in_vectors[0].address + 8);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 fd = memory.Read_U32(request.in_vectors[0].address);
const u32 num_ip = memory.Read_U32(request.in_vectors[0].address + 4);
const u64 timeout = memory.Read_U64(request.in_vectors[0].address + 8);
if (num_ip != 1)
{
INFO_LOG_FMT(IOS_NET, "IOCTLV_SO_ICMPPING {} IPs", num_ip);
}
ip_info.length = Memory::Read_U8(request.in_vectors[0].address + 16);
ip_info.addr_family = Memory::Read_U8(request.in_vectors[0].address + 17);
ip_info.icmp_id = Memory::Read_U16(request.in_vectors[0].address + 18);
ip_info.ip = Memory::Read_U32(request.in_vectors[0].address + 20);
ip_info.length = memory.Read_U8(request.in_vectors[0].address + 16);
ip_info.addr_family = memory.Read_U8(request.in_vectors[0].address + 17);
ip_info.icmp_id = memory.Read_U16(request.in_vectors[0].address + 18);
ip_info.ip = memory.Read_U32(request.in_vectors[0].address + 20);
if (ip_info.length != 8 || ip_info.addr_family != AF_INET)
{
@ -1110,7 +1170,7 @@ IPCReply NetIPTopDevice::HandleICMPPingRequest(const IOCtlVRequest& request)
if (request.in_vectors.size() > 1 && request.in_vectors[1].size == sizeof(data))
{
Memory::CopyFromEmu(data, request.in_vectors[1].address, request.in_vectors[1].size);
memory.CopyFromEmu(data, request.in_vectors[1].address, request.in_vectors[1].size);
}
else
{

View file

@ -23,6 +23,7 @@
#include "Core/IOS/Network/KD/VFF/VFFUtil.h"
#include "Core/IOS/Network/Socket.h"
#include "Core/IOS/Uids.h"
#include "Core/System.h"
namespace IOS::HLE
{
@ -232,12 +233,14 @@ NWC24::ErrorCode NetKDRequestDevice::KDDownload(const u16 entry_index,
IPCReply NetKDRequestDevice::HandleNWC24DownloadNowEx(const IOCtlRequest& request)
{
const u32 flags = Memory::Read_U32(request.buffer_in);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 flags = memory.Read_U32(request.buffer_in);
// Nintendo converts the entry ID between a u32 and u16
// several times, presumably for alignment purposes.
// We'll skip past buffer_in+4 and keep the entry index as a u16.
const u16 entry_index = Memory::Read_U16(request.buffer_in + 6);
const u32 subtask_bitmask = Memory::Read_U32(request.buffer_in + 8);
const u16 entry_index = memory.Read_U16(request.buffer_in + 6);
const u32 subtask_bitmask = memory.Read_U32(request.buffer_in + 8);
INFO_LOG_FMT(IOS_WC24,
"NET_KD_REQ: IOCTL_NWC24_DOWNLOAD_NOW_EX - NI - flags: {}, index: {}, bitmask: {}",
@ -315,6 +318,8 @@ std::optional<IPCReply> NetKDRequestDevice::IOCtl(const IOCtlRequest& request)
IOCTL_NWC24_REQUEST_SHUTDOWN = 0x28,
};
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
s32 return_value = 0;
switch (request.request)
{
@ -335,7 +340,7 @@ std::optional<IPCReply> NetKDRequestDevice::IOCtl(const IOCtlRequest& request)
case IOCTL_NWC24_STARTUP_SOCKET: // NWC24iStartupSocket
WriteReturnValue(0, request.buffer_out);
Memory::Write_U32(0, request.buffer_out + 4);
memory.Write_U32(0, request.buffer_out + 4);
return_value = 0;
INFO_LOG_FMT(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_STARTUP_SOCKET - NI");
break;
@ -356,7 +361,7 @@ std::optional<IPCReply> NetKDRequestDevice::IOCtl(const IOCtlRequest& request)
case IOCTL_NWC24_REQUEST_REGISTER_USER_ID:
INFO_LOG_FMT(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_REQUEST_REGISTER_USER_ID");
WriteReturnValue(0, request.buffer_out);
Memory::Write_U32(0, request.buffer_out + 4);
memory.Write_U32(0, request.buffer_out + 4);
break;
case IOCTL_NWC24_REQUEST_GENERATED_USER_ID: // (Input: none, Output: 32 bytes)
@ -409,8 +414,8 @@ std::optional<IPCReply> NetKDRequestDevice::IOCtl(const IOCtlRequest& request)
{
WriteReturnValue(NWC24::WC24_ERR_ID_REGISTERED, request.buffer_out);
}
Memory::Write_U64(config.Id(), request.buffer_out + 4);
Memory::Write_U32(u32(config.CreationStage()), request.buffer_out + 0xC);
memory.Write_U64(config.Id(), request.buffer_out + 4);
memory.Write_U32(u32(config.CreationStage()), request.buffer_out + 0xC);
break;
case IOCTL_NWC24_GET_SCHEDULER_STAT:
@ -435,7 +440,7 @@ std::optional<IPCReply> NetKDRequestDevice::IOCtl(const IOCtlRequest& request)
}
INFO_LOG_FMT(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_REQUEST_SHUTDOWN");
[[maybe_unused]] const u32 event = Memory::Read_U32(request.buffer_in);
[[maybe_unused]] const u32 event = memory.Read_U32(request.buffer_in);
// TODO: Advertise shutdown event
// TODO: Shutdown USB keyboard LEDs if event == 3
// TODO: IOCTLV_NCD_SETCONFIG

View file

@ -8,6 +8,7 @@
#include "Common/CommonTypes.h"
#include "Core/HW/EXI/EXI_DeviceIPL.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"
namespace IOS::HLE
{
@ -34,36 +35,39 @@ std::optional<IPCReply> NetKDTimeDevice::IOCtl(const IOCtlRequest& request)
// TODO Writes stuff to /shared2/nwc24/misc.bin
u32 update_misc = 0;
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
switch (request.request)
{
case IOCTL_NW24_GET_UNIVERSAL_TIME:
{
const u64 adjusted_utc = GetAdjustedUTC();
Memory::Write_U64(adjusted_utc, request.buffer_out + 4);
memory.Write_U64(adjusted_utc, request.buffer_out + 4);
INFO_LOG_FMT(IOS_WC24, "IOCTL_NW24_GET_UNIVERSAL_TIME = {}, time = {}", result, adjusted_utc);
}
break;
case IOCTL_NW24_SET_UNIVERSAL_TIME:
{
const u64 adjusted_utc = Memory::Read_U64(request.buffer_in);
const u64 adjusted_utc = memory.Read_U64(request.buffer_in);
SetAdjustedUTC(adjusted_utc);
update_misc = Memory::Read_U32(request.buffer_in + 8);
update_misc = memory.Read_U32(request.buffer_in + 8);
INFO_LOG_FMT(IOS_WC24, "IOCTL_NW24_SET_UNIVERSAL_TIME ({}, {}) = {}", adjusted_utc, update_misc,
result);
}
break;
case IOCTL_NW24_SET_RTC_COUNTER:
rtc = Memory::Read_U32(request.buffer_in);
update_misc = Memory::Read_U32(request.buffer_in + 4);
rtc = memory.Read_U32(request.buffer_in);
update_misc = memory.Read_U32(request.buffer_in + 4);
INFO_LOG_FMT(IOS_WC24, "IOCTL_NW24_SET_RTC_COUNTER ({}, {}) = {}", rtc, update_misc, result);
break;
case IOCTL_NW24_GET_TIME_DIFF:
{
const u64 time_diff = GetAdjustedUTC() - rtc;
Memory::Write_U64(time_diff, request.buffer_out + 4);
memory.Write_U64(time_diff, request.buffer_out + 4);
INFO_LOG_FMT(IOS_WC24, "IOCTL_NW24_GET_TIME_DIFF = {}, time_diff = {}", result, time_diff);
}
break;
@ -79,7 +83,7 @@ std::optional<IPCReply> NetKDTimeDevice::IOCtl(const IOCtlRequest& request)
}
// write return values
Memory::Write_U32(common_result, request.buffer_out);
memory.Write_U32(common_result, request.buffer_out);
return IPCReply(result);
}

View file

@ -11,6 +11,7 @@
#include "Core/HW/Memmap.h"
#include "Core/IOS/Network/MACUtils.h"
#include "Core/System.h"
namespace IOS::HLE
{
@ -32,6 +33,9 @@ std::optional<IPCReply> NetNCDManageDevice::IOCtlV(const IOCtlVRequest& request)
u32 common_result = 0;
u32 common_vector = 0;
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
switch (request.request)
{
case IOCTLV_NCD_LOCKWIRELESSDRIVER:
@ -52,7 +56,7 @@ std::optional<IPCReply> NetNCDManageDevice::IOCtlV(const IOCtlVRequest& request)
// We will just write the value of the file descriptor.
// The value will be positive so this will work fine.
m_ipc_fd = request.fd;
Memory::Write_U32(request.fd, request.io_vectors[0].address + 4);
memory.Write_U32(request.fd, request.io_vectors[0].address + 4);
}
break;
@ -67,7 +71,7 @@ std::optional<IPCReply> NetNCDManageDevice::IOCtlV(const IOCtlVRequest& request)
if (request.io_vectors[0].size < sizeof(u32))
return IPCReply(IPC_EINVAL);
const u32 request_handle = Memory::Read_U32(request.in_vectors[0].address);
const u32 request_handle = memory.Read_U32(request.in_vectors[0].address);
if (m_ipc_fd == request_handle)
{
m_ipc_fd = 0;
@ -107,7 +111,7 @@ std::optional<IPCReply> NetNCDManageDevice::IOCtlV(const IOCtlVRequest& request)
case IOCTLV_NCD_GETLINKSTATUS:
INFO_LOG_FMT(IOS_NET, "NET_NCD_MANAGE: IOCTLV_NCD_GETLINKSTATUS");
// Always connected
Memory::Write_U32(Net::ConnectionSettings::LINK_WIRED, request.io_vectors.at(0).address + 4);
memory.Write_U32(Net::ConnectionSettings::LINK_WIRED, request.io_vectors.at(0).address + 4);
break;
case IOCTLV_NCD_GETWIRELESSMACADDRESS:
@ -115,7 +119,7 @@ std::optional<IPCReply> NetNCDManageDevice::IOCtlV(const IOCtlVRequest& request)
INFO_LOG_FMT(IOS_NET, "NET_NCD_MANAGE: IOCTLV_NCD_GETWIRELESSMACADDRESS");
const Common::MACAddress address = IOS::Net::GetMACAddress();
Memory::CopyToEmu(request.io_vectors.at(1).address, address.data(), address.size());
memory.CopyToEmu(request.io_vectors.at(1).address, address.data(), address.size());
break;
}
@ -124,10 +128,10 @@ std::optional<IPCReply> NetNCDManageDevice::IOCtlV(const IOCtlVRequest& request)
break;
}
Memory::Write_U32(common_result, request.io_vectors.at(common_vector).address);
memory.Write_U32(common_result, request.io_vectors.at(common_vector).address);
if (common_vector == 1)
{
Memory::Write_U32(common_result, request.io_vectors.at(common_vector).address + 4);
memory.Write_U32(common_result, request.io_vectors.at(common_vector).address + 4);
}
return IPCReply(return_value);
}

View file

@ -12,6 +12,7 @@
#include "Core/IOS/FS/FileSystem.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/Uids.h"
#include "Core/System.h"
namespace IOS::HLE::Net
{
@ -53,11 +54,15 @@ void WiiNetConfig::ResetConfig(FS::FileSystem* fs)
void WiiNetConfig::WriteToMem(const u32 address) const
{
Memory::CopyToEmu(address, &m_data, sizeof(m_data));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyToEmu(address, &m_data, sizeof(m_data));
}
void WiiNetConfig::ReadFromMem(const u32 address)
{
Memory::CopyFromEmu(&m_data, address, sizeof(m_data));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyFromEmu(&m_data, address, sizeof(m_data));
}
} // namespace IOS::HLE::Net

View file

@ -20,6 +20,7 @@
#include "Core/HW/Memmap.h"
#include "Core/IOS/Network/Socket.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
namespace IOS::HLE
{
@ -225,12 +226,15 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
if (Core::WantsDeterminism())
return IPCReply(IPC_EACCES);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
switch (request.request)
{
case IOCTLV_NET_SSL_NEW:
{
int verifyOption = Memory::Read_U32(BufferOut);
std::string hostname = Memory::GetString(BufferOut2, BufferOutSize2);
int verifyOption = memory.Read_U32(BufferOut);
std::string hostname = memory.GetString(BufferOut2, BufferOutSize2);
int freeSSL = GetSSLFreeID();
if (freeSSL)
@ -290,7 +294,7 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
}
case IOCTLV_NET_SSL_SHUTDOWN:
{
int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WII_SSL* ssl = &_SSL[sslID];
@ -335,17 +339,17 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WII_SSL* ssl = &_SSL[sslID];
int ret =
mbedtls_x509_crt_parse_der(&ssl->cacert, Memory::GetPointer(BufferOut2), BufferOutSize2);
mbedtls_x509_crt_parse_der(&ssl->cacert, memory.GetPointer(BufferOut2), BufferOutSize2);
if (Config::Get(Config::MAIN_NETWORK_SSL_DUMP_ROOT_CA))
{
std::string filename = File::GetUserPath(D_DUMPSSL_IDX) + ssl->hostname + "_rootca.der";
File::IOFile(filename, "wb").WriteBytes(Memory::GetPointer(BufferOut2), BufferOutSize2);
File::IOFile(filename, "wb").WriteBytes(memory.GetPointer(BufferOut2), BufferOutSize2);
}
if (ret)
@ -376,7 +380,7 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WII_SSL* ssl = &_SSL[sslID];
@ -423,7 +427,7 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WII_SSL* ssl = &_SSL[sslID];
@ -442,7 +446,7 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
}
case IOCTLV_NET_SSL_SETBUILTINROOTCA:
{
int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WII_SSL* ssl = &_SSL[sslID];
@ -480,12 +484,12 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
}
case IOCTLV_NET_SSL_CONNECT:
{
int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WII_SSL* ssl = &_SSL[sslID];
mbedtls_ssl_setup(&ssl->ctx, &ssl->config);
ssl->sockfd = Memory::Read_U32(BufferOut2);
ssl->sockfd = memory.Read_U32(BufferOut2);
WiiSockMan& sm = WiiSockMan::GetInstance();
ssl->hostfd = sm.GetHostSocket(ssl->sockfd);
INFO_LOG_FMT(IOS_SSL, "IOCTLV_NET_SSL_CONNECT socket = {}", ssl->sockfd);
@ -507,7 +511,7 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
}
case IOCTLV_NET_SSL_DOHANDSHAKE:
{
int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WiiSockMan& sm = WiiSockMan::GetInstance();
@ -522,7 +526,7 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
}
case IOCTLV_NET_SSL_WRITE:
{
const int sslID = Memory::Read_U32(BufferOut) - 1;
const int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WiiSockMan& sm = WiiSockMan::GetInstance();
@ -540,13 +544,13 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
"BufferOut2: ({:08x}, {}), BufferOut3: ({:08x}, {})",
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
INFO_LOG_FMT(IOS_SSL, "{}", Memory::GetString(BufferOut2));
INFO_LOG_FMT(IOS_SSL, "{}", memory.GetString(BufferOut2));
break;
}
case IOCTLV_NET_SSL_READ:
{
int ret = 0;
int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WiiSockMan& sm = WiiSockMan::GetInstance();
@ -569,7 +573,7 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
}
case IOCTLV_NET_SSL_SETROOTCADEFAULT:
{
int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WriteReturnValue(SSL_OK, BufferIn);
@ -597,7 +601,7 @@ std::optional<IPCReply> NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferIn3, BufferInSize3,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2, BufferOut3, BufferOutSize3);
int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
WriteReturnValue(SSL_OK, BufferIn);

View file

@ -26,6 +26,7 @@
#include "Core/IOS/Device.h"
#include "Core/IOS/IOS.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
#ifdef _WIN32
#define ERRORCODE(name) WSA##name
@ -244,6 +245,9 @@ s32 WiiSocket::FCntl(u32 cmd, u32 arg)
void WiiSocket::Update(bool read, bool write, bool except)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
auto it = pending_sockops.begin();
while (it != pending_sockops.end())
{
@ -257,15 +261,15 @@ void WiiSocket::Update(bool read, bool write, bool except)
{
case IOCTL_SO_FCNTL:
{
u32 cmd = Memory::Read_U32(ioctl.buffer_in + 4);
u32 arg = Memory::Read_U32(ioctl.buffer_in + 8);
u32 cmd = memory.Read_U32(ioctl.buffer_in + 4);
u32 arg = memory.Read_U32(ioctl.buffer_in + 8);
ReturnValue = FCntl(cmd, arg);
break;
}
case IOCTL_SO_BIND:
{
sockaddr_in local_name;
const u8* addr = Memory::GetPointer(ioctl.buffer_in + 8);
const u8* addr = memory.GetPointer(ioctl.buffer_in + 8);
WiiSockMan::ToNativeAddrIn(addr, &local_name);
int ret = bind(fd, (sockaddr*)&local_name, sizeof(local_name));
@ -278,7 +282,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
case IOCTL_SO_CONNECT:
{
sockaddr_in local_name;
const u8* addr = Memory::GetPointer(ioctl.buffer_in + 8);
const u8* addr = memory.GetPointer(ioctl.buffer_in + 8);
WiiSockMan::ToNativeAddrIn(addr, &local_name);
int ret = connect(fd, (sockaddr*)&local_name, sizeof(local_name));
@ -295,7 +299,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
if (ioctl.buffer_out_size > 0)
{
sockaddr_in local_name;
u8* addr = Memory::GetPointer(ioctl.buffer_out);
u8* addr = memory.GetPointer(ioctl.buffer_out);
WiiSockMan::ToNativeAddrIn(addr, &local_name);
socklen_t addrlen = sizeof(sockaddr_in);
@ -375,7 +379,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
if (it->is_ssl)
{
int sslID = Memory::Read_U32(BufferOut) - 1;
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
switch (it->ssl_type)
@ -479,11 +483,11 @@ void WiiSocket::Update(bool read, bool write, bool except)
{
WII_SSL* ssl = &NetSSLDevice::_SSL[sslID];
const int ret =
mbedtls_ssl_write(&ssl->ctx, Memory::GetPointer(BufferOut2), BufferOutSize2);
mbedtls_ssl_write(&ssl->ctx, memory.GetPointer(BufferOut2), BufferOutSize2);
if (ret >= 0)
{
PowerPC::debug_interface.NetworkLogger()->LogSSLWrite(Memory::GetPointer(BufferOut2),
PowerPC::debug_interface.NetworkLogger()->LogSSLWrite(memory.GetPointer(BufferOut2),
ret, ssl->hostfd);
// Return bytes written or SSL_ERR_ZERO if none
WriteReturnValue((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn);
@ -513,11 +517,11 @@ void WiiSocket::Update(bool read, bool write, bool except)
{
WII_SSL* ssl = &NetSSLDevice::_SSL[sslID];
const int ret =
mbedtls_ssl_read(&ssl->ctx, Memory::GetPointer(BufferIn2), BufferInSize2);
mbedtls_ssl_read(&ssl->ctx, memory.GetPointer(BufferIn2), BufferInSize2);
if (ret >= 0)
{
PowerPC::debug_interface.NetworkLogger()->LogSSLRead(Memory::GetPointer(BufferIn2),
PowerPC::debug_interface.NetworkLogger()->LogSSLRead(memory.GetPointer(BufferIn2),
ret, ssl->hostfd);
// Return bytes read or SSL_ERR_ZERO if none
WriteReturnValue((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn);
@ -568,11 +572,11 @@ void WiiSocket::Update(bool read, bool write, bool except)
break;
}
u32 flags = Memory::Read_U32(BufferIn2 + 0x04);
u32 has_destaddr = Memory::Read_U32(BufferIn2 + 0x08);
u32 flags = memory.Read_U32(BufferIn2 + 0x04);
u32 has_destaddr = memory.Read_U32(BufferIn2 + 0x08);
// Not a string, Windows requires a const char* for sendto
const char* data = (const char*)Memory::GetPointer(BufferIn);
const char* data = (const char*)memory.GetPointer(BufferIn);
// Act as non blocking when SO_MSG_NONBLOCK is specified
forceNonBlock = ((flags & SO_MSG_NONBLOCK) == SO_MSG_NONBLOCK);
@ -582,7 +586,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
sockaddr_in local_name = {0};
if (has_destaddr)
{
const u8* addr = Memory::GetPointer(BufferIn2 + 0x0C);
const u8* addr = memory.GetPointer(BufferIn2 + 0x0C);
WiiSockMan::ToNativeAddrIn(addr, &local_name);
}
@ -615,9 +619,9 @@ void WiiSocket::Update(bool read, bool write, bool except)
break;
}
u32 flags = Memory::Read_U32(BufferIn + 0x04);
u32 flags = memory.Read_U32(BufferIn + 0x04);
// Not a string, Windows requires a char* for recvfrom
char* data = (char*)Memory::GetPointer(BufferOut);
char* data = (char*)memory.GetPointer(BufferOut);
int data_len = BufferOutSize;
sockaddr_in local_name;
@ -625,7 +629,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
if (BufferOutSize2 != 0)
{
const u8* addr = Memory::GetPointer(BufferOut2);
const u8* addr = memory.GetPointer(BufferOut2);
WiiSockMan::ToNativeAddrIn(addr, &local_name);
}
@ -662,7 +666,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
if (BufferOutSize2 != 0)
{
u8* addr = Memory::GetPointer(BufferOut2);
u8* addr = memory.GetPointer(BufferOut2);
WiiSockMan::ToWiiAddrIn(local_name, addr, addrlen);
}
break;
@ -1008,10 +1012,13 @@ void WiiSockMan::UpdatePollCommands()
pcmd.timeout = std::max<s64>(0, pcmd.timeout - elapsed);
}
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
pending_polls.erase(
std::remove_if(
pending_polls.begin(), pending_polls.end(),
[this](PollCommand& pcmd) {
[&memory, this](PollCommand& pcmd) {
const auto request = Request(pcmd.request_addr);
auto& pfds = pcmd.wii_fds;
int ret = 0;
@ -1030,7 +1037,7 @@ void WiiSockMan::UpdatePollCommands()
std::iota(original_order.begin(), original_order.end(), 0);
// Select indices with valid fds
auto mid = std::partition(original_order.begin(), original_order.end(), [&](auto i) {
return GetHostSocket(Memory::Read_U32(pcmd.buffer_out + 0xc * i)) >= 0;
return GetHostSocket(memory.Read_U32(pcmd.buffer_out + 0xc * i)) >= 0;
});
const auto n_valid = std::distance(original_order.begin(), mid);
@ -1057,9 +1064,9 @@ void WiiSockMan::UpdatePollCommands()
const int revents = ConvertEvents(pfds[i].revents, ConvertDirection::NativeToWii);
// No need to change fd or events as they are input only.
// Memory::Write_U32(ufds[i].fd, request.buffer_out + 0xc*i); //fd
// Memory::Write_U32(events, request.buffer_out + 0xc*i + 4); //events
Memory::Write_U32(revents, pcmd.buffer_out + 0xc * i + 8); // revents
// memory.Write_U32(ufds[i].fd, request.buffer_out + 0xc*i); //fd
// memory.Write_U32(events, request.buffer_out + 0xc*i + 4); //events
memory.Write_U32(revents, pcmd.buffer_out + 0xc * i + 8); // revents
DEBUG_LOG_FMT(IOS_NET,
"IOCTL_SO_POLL socket {} wevents {:08X} events {:08X} revents {:08X}",
i, revents, pfds[i].events, pfds[i].revents);

View file

@ -14,6 +14,7 @@
#include "Core/DolphinAnalytics.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/Network/MACUtils.h"
#include "Core/System.h"
namespace IOS::HLE
{
@ -233,7 +234,9 @@ IPCReply NetWDCommandDevice::SetLinkState(const IOCtlVRequest& request)
if (!vector || vector->address == 0)
return IPCReply(u32(ResultCode::IllegalParameter));
const u32 state = Memory::Read_U32(vector->address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 state = memory.Read_U32(vector->address);
INFO_LOG_FMT(IOS_NET, "WD_SetLinkState called (state={}, mode={})", state, m_mode);
if (state == 0)
@ -279,8 +282,11 @@ IPCReply NetWDCommandDevice::Disassociate(const IOCtlVRequest& request)
if (!vector || vector->address == 0)
return IPCReply(u32(ResultCode::IllegalParameter));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
Common::MACAddress mac;
Memory::CopyFromEmu(mac.data(), vector->address, mac.size());
memory.CopyFromEmu(mac.data(), vector->address, mac.size());
INFO_LOG_FMT(IOS_NET, "WD_Disassociate: MAC {}", Common::MacAddressToString(mac));
@ -309,7 +315,9 @@ IPCReply NetWDCommandDevice::GetInfo(const IOCtlVRequest& request) const
if (!vector || vector->address == 0)
return IPCReply(u32(ResultCode::IllegalParameter));
Memory::CopyToEmu(vector->address, &m_info, sizeof(m_info));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyToEmu(vector->address, &m_info, sizeof(m_info));
return IPCReply(IPC_SUCCESS);
}
@ -332,9 +340,11 @@ std::optional<IPCReply> NetWDCommandDevice::IOCtlV(const IOCtlVRequest& request)
{
// Gives parameters detailing type of scan and what to match
// XXX - unused
// ScanInfo *scan = (ScanInfo *)Memory::GetPointer(request.in_vectors.at(0).m_Address);
// ScanInfo *scan = (ScanInfo *)memory.GetPointer(request.in_vectors.at(0).m_Address);
u16* results = (u16*)Memory::GetPointer(request.io_vectors.at(0).address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u16* results = (u16*)memory.GetPointer(request.io_vectors.at(0).address);
// first u16 indicates number of BSSInfo following
results[0] = Common::swap16(1);

View file

@ -21,6 +21,7 @@
#include "Core/HW/Memmap.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/VersionInfo.h"
#include "Core/System.h"
namespace IOS::HLE
{
@ -128,7 +129,9 @@ std::optional<IPCReply> SDIOSlot0Device::Close(u32 fd)
std::optional<IPCReply> SDIOSlot0Device::IOCtl(const IOCtlRequest& request)
{
Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Memset(request.buffer_out, 0, request.buffer_out_size);
switch (request.request)
{
@ -187,15 +190,18 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
u32 pad0;
} req;
req.command = Memory::Read_U32(buffer_in + 0);
req.type = Memory::Read_U32(buffer_in + 4);
req.resp = Memory::Read_U32(buffer_in + 8);
req.arg = Memory::Read_U32(buffer_in + 12);
req.blocks = Memory::Read_U32(buffer_in + 16);
req.bsize = Memory::Read_U32(buffer_in + 20);
req.addr = Memory::Read_U32(buffer_in + 24);
req.isDMA = Memory::Read_U32(buffer_in + 28);
req.pad0 = Memory::Read_U32(buffer_in + 32);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
req.command = memory.Read_U32(buffer_in + 0);
req.type = memory.Read_U32(buffer_in + 4);
req.resp = memory.Read_U32(buffer_in + 8);
req.arg = memory.Read_U32(buffer_in + 12);
req.blocks = memory.Read_U32(buffer_in + 16);
req.bsize = memory.Read_U32(buffer_in + 20);
req.addr = memory.Read_U32(buffer_in + 24);
req.isDMA = memory.Read_U32(buffer_in + 28);
req.pad0 = memory.Read_U32(buffer_in + 32);
// Note: req.addr is the virtual address of _rwBuffer
@ -206,19 +212,19 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
case GO_IDLE_STATE:
INFO_LOG_FMT(IOS_SD, "GO_IDLE_STATE");
// Response is R1 (idle state)
Memory::Write_U32(0x00, buffer_out);
memory.Write_U32(0x00, buffer_out);
break;
case SEND_RELATIVE_ADDR:
// Technically RCA should be generated when asked and at power on...w/e :p
Memory::Write_U32(0x9f62, buffer_out);
memory.Write_U32(0x9f62, buffer_out);
break;
case SELECT_CARD:
// This covers both select and deselect
// Differentiate by checking if rca is set in req.arg
// If it is, it's a select and return 0x700
Memory::Write_U32((req.arg >> 16) ? 0x700 : 0x900, buffer_out);
memory.Write_U32((req.arg >> 16) ? 0x700 : 0x900, buffer_out);
break;
case SEND_IF_COND:
@ -227,45 +233,45 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
// voltage and the check pattern that were set in the command argument.
// This command is used to differentiate between protocol v1 and v2.
InitSDHC();
Memory::Write_U32(req.arg, buffer_out);
memory.Write_U32(req.arg, buffer_out);
break;
case SEND_CSD:
{
const std::array<u32, 4> csd = m_protocol == SDProtocol::V1 ? GetCSDv1() : GetCSDv2();
Memory::CopyToEmuSwapped(buffer_out, csd.data(), csd.size() * sizeof(u32));
memory.CopyToEmuSwapped(buffer_out, csd.data(), csd.size() * sizeof(u32));
}
break;
case ALL_SEND_CID:
case SEND_CID:
INFO_LOG_FMT(IOS_SD, "(ALL_)SEND_CID");
Memory::Write_U32(0x80114d1c, buffer_out);
Memory::Write_U32(0x80080000, buffer_out + 4);
Memory::Write_U32(0x8007b520, buffer_out + 8);
Memory::Write_U32(0x80080000, buffer_out + 12);
memory.Write_U32(0x80114d1c, buffer_out);
memory.Write_U32(0x80080000, buffer_out + 4);
memory.Write_U32(0x8007b520, buffer_out + 8);
memory.Write_U32(0x80080000, buffer_out + 12);
break;
case SET_BLOCKLEN:
m_block_length = req.arg;
Memory::Write_U32(0x900, buffer_out);
memory.Write_U32(0x900, buffer_out);
break;
case APP_CMD_NEXT:
// Next cmd is going to be ACMD_*
Memory::Write_U32(0x920, buffer_out);
memory.Write_U32(0x920, buffer_out);
break;
case ACMD_SETBUSWIDTH:
// 0 = 1bit, 2 = 4bit
m_bus_width = (req.arg & 3);
Memory::Write_U32(0x920, buffer_out);
memory.Write_U32(0x920, buffer_out);
break;
case ACMD_SENDOPCOND:
// Sends host capacity support information (HCS) and asks the accessed card to send
// its operating condition register (OCR) content
Memory::Write_U32(GetOCRegister(), buffer_out);
memory.Write_U32(GetOCRegister(), buffer_out);
break;
case READ_MULTIPLE_BLOCK:
@ -283,7 +289,7 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
if (!m_card.Seek(address, File::SeekOrigin::Begin))
ERROR_LOG_FMT(IOS_SD, "Seek failed");
if (m_card.ReadBytes(Memory::GetPointer(req.addr), size))
if (m_card.ReadBytes(memory.GetPointer(req.addr), size))
{
DEBUG_LOG_FMT(IOS_SD, "Outbuffer size {} got {}", rw_buffer_size, size);
}
@ -295,7 +301,7 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
}
}
}
Memory::Write_U32(0x900, buffer_out);
memory.Write_U32(0x900, buffer_out);
break;
case WRITE_MULTIPLE_BLOCK:
@ -313,7 +319,7 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
if (!m_card.Seek(address, File::SeekOrigin::Begin))
ERROR_LOG_FMT(IOS_SD, "Seek failed");
if (!m_card.WriteBytes(Memory::GetPointer(req.addr), size))
if (!m_card.WriteBytes(memory.GetPointer(req.addr), size))
{
ERROR_LOG_FMT(IOS_SD, "Write Failed - error: {}, eof: {}", std::ferror(m_card.GetHandle()),
std::feof(m_card.GetHandle()));
@ -321,7 +327,7 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
}
}
}
Memory::Write_U32(0x900, buffer_out);
memory.Write_U32(0x900, buffer_out);
break;
case EVENT_REGISTER: // async
@ -354,8 +360,11 @@ s32 SDIOSlot0Device::ExecuteCommand(const Request& request, u32 buffer_in, u32 b
IPCReply SDIOSlot0Device::WriteHCRegister(const IOCtlRequest& request)
{
const u32 reg = Memory::Read_U32(request.buffer_in);
const u32 val = Memory::Read_U32(request.buffer_in + 16);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 reg = memory.Read_U32(request.buffer_in);
const u32 val = memory.Read_U32(request.buffer_in + 16);
INFO_LOG_FMT(IOS_SD, "IOCTL_WRITEHCR {:#010x} - {:#010x}", reg, val);
@ -386,7 +395,10 @@ IPCReply SDIOSlot0Device::WriteHCRegister(const IOCtlRequest& request)
IPCReply SDIOSlot0Device::ReadHCRegister(const IOCtlRequest& request)
{
const u32 reg = Memory::Read_U32(request.buffer_in);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 reg = memory.Read_U32(request.buffer_in);
if (reg >= m_registers.size())
{
@ -398,7 +410,7 @@ IPCReply SDIOSlot0Device::ReadHCRegister(const IOCtlRequest& request)
INFO_LOG_FMT(IOS_SD, "IOCTL_READHCR {:#010x} - {:#010x}", reg, val);
// Just reading the register
Memory::Write_U32(val, request.buffer_out);
memory.Write_U32(val, request.buffer_out);
return IPCReply(IPC_SUCCESS);
}
@ -406,8 +418,11 @@ IPCReply SDIOSlot0Device::ResetCard(const IOCtlRequest& request)
{
INFO_LOG_FMT(IOS_SD, "IOCTL_RESETCARD");
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// Returns 16bit RCA and 16bit 0s (meaning success)
Memory::Write_U32(m_status, request.buffer_out);
memory.Write_U32(m_status, request.buffer_out);
return IPCReply(IPC_SUCCESS);
}
@ -416,9 +431,12 @@ IPCReply SDIOSlot0Device::SetClk(const IOCtlRequest& request)
{
INFO_LOG_FMT(IOS_SD, "IOCTL_SETCLK");
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// libogc only sets it to 1 and makes sure the return isn't negative...
// one half of the sdclk divisor: a power of two or zero.
const u32 clock = Memory::Read_U32(request.buffer_in);
const u32 clock = memory.Read_U32(request.buffer_in);
if (clock != 1)
INFO_LOG_FMT(IOS_SD, "Setting to {}, interesting", clock);
@ -427,7 +445,10 @@ IPCReply SDIOSlot0Device::SetClk(const IOCtlRequest& request)
std::optional<IPCReply> SDIOSlot0Device::SendCommand(const IOCtlRequest& request)
{
INFO_LOG_FMT(IOS_SD, "IOCTL_SENDCMD {:x} IPC:{:08x}", Memory::Read_U32(request.buffer_in),
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
INFO_LOG_FMT(IOS_SD, "IOCTL_SENDCMD {:x} IPC:{:08x}", memory.Read_U32(request.buffer_in),
request.address);
const s32 return_value = ExecuteCommand(request, request.buffer_in, request.buffer_in_size, 0, 0,
@ -476,23 +497,31 @@ IPCReply SDIOSlot0Device::GetStatus(const IOCtlRequest& request)
(status & CARD_INSERTED) ? "inserted" : "not present",
(status & CARD_INITIALIZED) ? " and initialized" : "");
Memory::Write_U32(status, request.buffer_out);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(status, request.buffer_out);
return IPCReply(IPC_SUCCESS);
}
IPCReply SDIOSlot0Device::GetOCRegister(const IOCtlRequest& request)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 ocr = GetOCRegister();
INFO_LOG_FMT(IOS_SD, "IOCTL_GETOCR. Replying with ocr {:x}", ocr);
Memory::Write_U32(ocr, request.buffer_out);
memory.Write_U32(ocr, request.buffer_out);
return IPCReply(IPC_SUCCESS);
}
IPCReply SDIOSlot0Device::SendCommand(const IOCtlVRequest& request)
{
DEBUG_LOG_FMT(IOS_SD, "IOCTLV_SENDCMD {:#010x}", Memory::Read_U32(request.in_vectors[0].address));
Memory::Memset(request.io_vectors[0].address, 0, request.io_vectors[0].size);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
DEBUG_LOG_FMT(IOS_SD, "IOCTLV_SENDCMD {:#010x}", memory.Read_U32(request.in_vectors[0].address));
memory.Memset(request.io_vectors[0].address, 0, request.io_vectors[0].size);
const s32 return_value =
ExecuteCommand(request, request.in_vectors[0].address, request.in_vectors[0].size,

View file

@ -10,6 +10,7 @@
#include "Common/Logging/Log.h"
#include "Core/Core.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"
namespace IOS::HLE
{
@ -17,6 +18,9 @@ static std::unique_ptr<IOCtlRequest> s_event_hook_request;
std::optional<IPCReply> STMImmediateDevice::IOCtl(const IOCtlRequest& request)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
s32 return_value = IPC_SUCCESS;
switch (request.request)
{
@ -32,7 +36,7 @@ std::optional<IPCReply> STMImmediateDevice::IOCtl(const IOCtlRequest& request)
return_value = IPC_ENOENT;
break;
}
Memory::Write_U32(0, s_event_hook_request->buffer_out);
memory.Write_U32(0, s_event_hook_request->buffer_out);
m_ios.EnqueueIPCReply(*s_event_hook_request, IPC_SUCCESS);
s_event_hook_request.reset();
break;
@ -45,7 +49,7 @@ std::optional<IPCReply> STMImmediateDevice::IOCtl(const IOCtlRequest& request)
case IOCTL_STM_VIDIMMING: // (Input: 20 bytes, Output: 20 bytes)
INFO_LOG_FMT(IOS_STM, "{} - IOCtl:", GetDeviceName());
INFO_LOG_FMT(IOS_STM, " IOCTL_STM_VIDIMMING");
// Memory::Write_U32(1, buffer_out);
// memory.Write_U32(1, buffer_out);
// return_value = 1;
break;
@ -101,7 +105,9 @@ void STMEventHookDevice::TriggerEvent(const u32 event) const
if (!m_is_active || !s_event_hook_request)
return;
Memory::Write_U32(event, s_event_hook_request->buffer_out);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(event, s_event_hook_request->buffer_out);
m_ios.EnqueueIPCReply(*s_event_hook_request, IPC_SUCCESS);
s_event_hook_request.reset();
}

View file

@ -164,15 +164,18 @@ std::optional<IPCReply> BluetoothEmuDevice::IOCtlV(const IOCtlVRequest& request)
{
case ACL_DATA_OUT: // ACL data is received from the stack
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// This is the ACL datapath from CPU to Wii Remote
const auto* acl_header =
reinterpret_cast<hci_acldata_hdr_t*>(Memory::GetPointer(ctrl.data_address));
reinterpret_cast<hci_acldata_hdr_t*>(memory.GetPointer(ctrl.data_address));
DEBUG_ASSERT(HCI_BC_FLAG(acl_header->con_handle) == HCI_POINT2POINT);
DEBUG_ASSERT(HCI_PB_FLAG(acl_header->con_handle) == HCI_PACKET_START);
SendToDevice(HCI_CON_HANDLE(acl_header->con_handle),
Memory::GetPointer(ctrl.data_address + sizeof(hci_acldata_hdr_t)),
memory.GetPointer(ctrl.data_address + sizeof(hci_acldata_hdr_t)),
acl_header->length);
break;
}
@ -244,8 +247,11 @@ void BluetoothEmuDevice::SendACLPacket(const bdaddr_t& source, const u8* data, u
DEBUG_LOG_FMT(IOS_WIIMOTE, "ACL endpoint valid, sending packet to {:08x}",
m_acl_endpoint->ios_request.address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
hci_acldata_hdr_t* header =
reinterpret_cast<hci_acldata_hdr_t*>(Memory::GetPointer(m_acl_endpoint->data_address));
reinterpret_cast<hci_acldata_hdr_t*>(memory.GetPointer(m_acl_endpoint->data_address));
header->con_handle = HCI_MK_CON_HANDLE(connection_handle, HCI_PACKET_START, HCI_POINT2POINT);
header->length = size;
@ -421,7 +427,10 @@ void BluetoothEmuDevice::ACLPool::WriteToEndpoint(const USB::V0BulkMessage& endp
DEBUG_LOG_FMT(IOS_WIIMOTE, "ACL packet being written from queue to {:08x}",
endpoint.ios_request.address);
hci_acldata_hdr_t* header = (hci_acldata_hdr_t*)Memory::GetPointer(endpoint.data_address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
hci_acldata_hdr_t* header = (hci_acldata_hdr_t*)memory.GetPointer(endpoint.data_address);
header->con_handle = HCI_MK_CON_HANDLE(conn_handle, HCI_PACKET_START, HCI_POINT2POINT);
header->length = size;
@ -957,10 +966,13 @@ bool BluetoothEmuDevice::SendEventConPacketTypeChange(u16 connection_handle, u16
// This is called from the USB::IOCTLV_USBV0_CTRLMSG Ioctlv
void BluetoothEmuDevice::ExecuteHCICommandMessage(const USB::V0CtrlMessage& ctrl_message)
{
const u8* input = Memory::GetPointer(ctrl_message.data_address + 3);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u8* input = memory.GetPointer(ctrl_message.data_address + 3);
SCommandMessage msg;
std::memcpy(&msg, Memory::GetPointer(ctrl_message.data_address), sizeof(msg));
std::memcpy(&msg, memory.GetPointer(ctrl_message.data_address), sizeof(msg));
const u16 ocf = HCI_OCF(msg.Opcode);
const u16 ogf = HCI_OGF(msg.Opcode);

View file

@ -28,6 +28,7 @@
#include "Core/Core.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/Device.h"
#include "Core/System.h"
#include "VideoCommon/OnScreenDisplay.h"
namespace IOS::HLE
@ -213,9 +214,12 @@ std::optional<IPCReply> BluetoothRealDevice::IOCtlV(const IOCtlVRequest& request
// HCI commands to the Bluetooth adapter
case USB::IOCTLV_USBV0_CTRLMSG:
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
std::lock_guard lk(m_transfers_mutex);
auto cmd = std::make_unique<USB::V0CtrlMessage>(m_ios, request);
const u16 opcode = Common::swap16(Memory::Read_U16(cmd->data_address));
const u16 opcode = Common::swap16(memory.Read_U16(cmd->data_address));
if (opcode == HCI_CMD_READ_BUFFER_SIZE)
{
m_fake_read_buffer_size_reply.Set();
@ -231,7 +235,7 @@ std::optional<IPCReply> BluetoothRealDevice::IOCtlV(const IOCtlVRequest& request
{
// Delete link key(s) from our own link key storage when the game tells the adapter to
hci_delete_stored_link_key_cp delete_cmd;
Memory::CopyFromEmu(&delete_cmd, cmd->data_address, sizeof(delete_cmd));
memory.CopyFromEmu(&delete_cmd, cmd->data_address, sizeof(delete_cmd));
if (delete_cmd.delete_all)
m_link_keys.clear();
else
@ -240,7 +244,7 @@ std::optional<IPCReply> BluetoothRealDevice::IOCtlV(const IOCtlVRequest& request
auto buffer = std::make_unique<u8[]>(cmd->length + LIBUSB_CONTROL_SETUP_SIZE);
libusb_fill_control_setup(buffer.get(), cmd->request_type, cmd->request, cmd->value, cmd->index,
cmd->length);
Memory::CopyFromEmu(buffer.get() + LIBUSB_CONTROL_SETUP_SIZE, cmd->data_address, cmd->length);
memory.CopyFromEmu(buffer.get() + LIBUSB_CONTROL_SETUP_SIZE, cmd->data_address, cmd->length);
libusb_transfer* transfer = libusb_alloc_transfer(0);
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
libusb_fill_control_transfer(transfer, m_handle, buffer.get(), nullptr, this, 0);
@ -490,13 +494,16 @@ bool BluetoothRealDevice::SendHCIStoreLinkKeyCommand()
void BluetoothRealDevice::FakeVendorCommandReply(USB::V0IntrMessage& ctrl)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
SHCIEventCommand hci_event;
Memory::CopyFromEmu(&hci_event, ctrl.data_address, sizeof(hci_event));
memory.CopyFromEmu(&hci_event, ctrl.data_address, sizeof(hci_event));
hci_event.EventType = HCI_EVENT_COMMAND_COMPL;
hci_event.PayloadLength = sizeof(SHCIEventCommand) - 2;
hci_event.PacketIndicator = 0x01;
hci_event.Opcode = m_fake_vendor_command_reply_opcode;
Memory::CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));
memory.CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));
m_ios.EnqueueIPCReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event)));
}
@ -507,13 +514,16 @@ void BluetoothRealDevice::FakeVendorCommandReply(USB::V0IntrMessage& ctrl)
// (including Wiimote disconnects and "event mismatch" warning messages).
void BluetoothRealDevice::FakeReadBufferSizeReply(USB::V0IntrMessage& ctrl)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
SHCIEventCommand hci_event;
Memory::CopyFromEmu(&hci_event, ctrl.data_address, sizeof(hci_event));
memory.CopyFromEmu(&hci_event, ctrl.data_address, sizeof(hci_event));
hci_event.EventType = HCI_EVENT_COMMAND_COMPL;
hci_event.PayloadLength = sizeof(SHCIEventCommand) - 2 + sizeof(hci_read_buffer_size_rp);
hci_event.PacketIndicator = 0x01;
hci_event.Opcode = HCI_CMD_READ_BUFFER_SIZE;
Memory::CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));
memory.CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));
hci_read_buffer_size_rp reply;
reply.status = 0x00;
@ -521,19 +531,22 @@ void BluetoothRealDevice::FakeReadBufferSizeReply(USB::V0IntrMessage& ctrl)
reply.num_acl_pkts = ACL_PKT_NUM;
reply.max_sco_size = SCO_PKT_SIZE;
reply.num_sco_pkts = SCO_PKT_NUM;
Memory::CopyToEmu(ctrl.data_address + sizeof(hci_event), &reply, sizeof(reply));
memory.CopyToEmu(ctrl.data_address + sizeof(hci_event), &reply, sizeof(reply));
m_ios.EnqueueIPCReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event) + sizeof(reply)));
}
void BluetoothRealDevice::FakeSyncButtonEvent(USB::V0IntrMessage& ctrl, const u8* payload,
const u8 size)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
hci_event_hdr_t hci_event;
Memory::CopyFromEmu(&hci_event, ctrl.data_address, sizeof(hci_event));
memory.CopyFromEmu(&hci_event, ctrl.data_address, sizeof(hci_event));
hci_event.event = HCI_EVENT_VENDOR;
hci_event.length = size;
Memory::CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));
Memory::CopyToEmu(ctrl.data_address + sizeof(hci_event), payload, size);
memory.CopyToEmu(ctrl.data_address, &hci_event, sizeof(hci_event));
memory.CopyToEmu(ctrl.data_address + sizeof(hci_event), payload, size);
m_ios.EnqueueIPCReply(ctrl.ios_request, static_cast<s32>(sizeof(hci_event) + size));
}

View file

@ -11,6 +11,7 @@
#include "Common/CommonTypes.h"
#include "Common/Swap.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"
namespace IOS::HLE::USB
{
@ -18,14 +19,18 @@ std::unique_ptr<u8[]> TransferCommand::MakeBuffer(const size_t size) const
{
ASSERT_MSG(IOS_USB, data_address != 0, "Invalid data_address");
auto buffer = std::make_unique<u8[]>(size);
Memory::CopyFromEmu(buffer.get(), data_address, size);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyFromEmu(buffer.get(), data_address, size);
return buffer;
}
void TransferCommand::FillBuffer(const u8* src, const size_t size) const
{
ASSERT_MSG(IOS_USB, size == 0 || data_address != 0, "Invalid data_address");
Memory::CopyToEmu(data_address, src, size);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyToEmu(data_address, src, size);
}
void TransferCommand::OnTransferComplete(s32 return_value) const
@ -35,7 +40,9 @@ void TransferCommand::OnTransferComplete(s32 return_value) const
void IsoMessage::SetPacketReturnValue(const size_t packet_num, const u16 return_value) const
{
Memory::Write_U16(return_value, static_cast<u32>(packet_sizes_addr + packet_num * sizeof(u16)));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U16(return_value, static_cast<u32>(packet_sizes_addr + packet_num * sizeof(u16)));
}
Device::~Device() = default;

View file

@ -21,6 +21,7 @@
#include "Core/HW/Memmap.h"
#include "Core/IOS/Device.h"
#include "Core/IOS/IOS.h"
#include "Core/System.h"
namespace IOS::HLE::USB
{
@ -247,7 +248,11 @@ int LibusbDevice::SubmitTransfer(std::unique_ptr<CtrlMessage> cmd)
auto buffer = std::make_unique<u8[]>(size);
libusb_fill_control_setup(buffer.get(), cmd->request_type, cmd->request, cmd->value, cmd->index,
cmd->length);
Memory::CopyFromEmu(buffer.get() + LIBUSB_CONTROL_SETUP_SIZE, cmd->data_address, cmd->length);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyFromEmu(buffer.get() + LIBUSB_CONTROL_SETUP_SIZE, cmd->data_address, cmd->length);
libusb_transfer* transfer = libusb_alloc_transfer(0);
transfer->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
libusb_fill_control_transfer(transfer, m_handle, buffer.release(), CtrlTransferCallback, this, 0);

View file

@ -18,6 +18,7 @@
#include "Core/IOS/USB/Common.h"
#include "Core/IOS/USB/USBV0.h"
#include "Core/IOS/VersionInfo.h"
#include "Core/System.h"
namespace IOS::HLE
{
@ -92,9 +93,12 @@ IPCReply OH0::CancelInsertionHook(const IOCtlRequest& request)
if (!request.buffer_in || request.buffer_in_size != 4)
return IPCReply(IPC_EINVAL);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// IOS assigns random IDs, but ours are simply the VID + PID (see RegisterInsertionHookWithID)
TriggerHook(m_insertion_hooks,
{Memory::Read_U16(request.buffer_in), Memory::Read_U16(request.buffer_in + 2)},
{memory.Read_U16(request.buffer_in), memory.Read_U16(request.buffer_in + 2)},
USB_ECANCELED);
return IPCReply(IPC_SUCCESS);
}
@ -104,11 +108,14 @@ IPCReply OH0::GetDeviceList(const IOCtlVRequest& request) const
if (!request.HasNumberOfValidVectors(2, 2))
return IPCReply(IPC_EINVAL);
const u8 max_entries_count = Memory::Read_U8(request.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u8 max_entries_count = memory.Read_U8(request.in_vectors[0].address);
if (request.io_vectors[1].size != max_entries_count * sizeof(DeviceEntry))
return IPCReply(IPC_EINVAL);
const u8 interface_class = Memory::Read_U8(request.in_vectors[1].address);
const u8 interface_class = memory.Read_U8(request.in_vectors[1].address);
u8 entries_count = 0;
std::lock_guard lk(m_devices_mutex);
for (const auto& device : m_devices)
@ -122,9 +129,9 @@ IPCReply OH0::GetDeviceList(const IOCtlVRequest& request) const
entry.unknown = 0;
entry.vid = Common::swap16(device.second->GetVid());
entry.pid = Common::swap16(device.second->GetPid());
Memory::CopyToEmu(request.io_vectors[1].address + 8 * entries_count++, &entry, 8);
memory.CopyToEmu(request.io_vectors[1].address + 8 * entries_count++, &entry, 8);
}
Memory::Write_U8(entries_count, request.io_vectors[0].address);
memory.Write_U8(entries_count, request.io_vectors[0].address);
return IPCReply(IPC_SUCCESS);
}
@ -133,8 +140,11 @@ IPCReply OH0::GetRhDesca(const IOCtlRequest& request) const
if (!request.buffer_out || request.buffer_out_size != 4)
return IPCReply(IPC_EINVAL);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// Based on a hardware test, this ioctl seems to return a constant value
Memory::Write_U32(0x02000302, request.buffer_out);
memory.Write_U32(0x02000302, request.buffer_out);
request.Dump(GetDeviceName(), Common::Log::LogType::IOS_USB, Common::Log::LogLevel::LWARNING);
return IPCReply(IPC_SUCCESS);
}
@ -174,8 +184,11 @@ std::optional<IPCReply> OH0::RegisterInsertionHook(const IOCtlVRequest& request)
if (!request.HasNumberOfValidVectors(2, 0))
return IPCReply(IPC_EINVAL);
const u16 vid = Memory::Read_U16(request.in_vectors[0].address);
const u16 pid = Memory::Read_U16(request.in_vectors[1].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u16 vid = memory.Read_U16(request.in_vectors[0].address);
const u16 pid = memory.Read_U16(request.in_vectors[1].address);
if (HasDeviceWithVidPid(vid, pid))
return IPCReply(IPC_SUCCESS);
@ -190,16 +203,19 @@ std::optional<IPCReply> OH0::RegisterInsertionHookWithID(const IOCtlVRequest& re
if (!request.HasNumberOfValidVectors(3, 1))
return IPCReply(IPC_EINVAL);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
std::lock_guard lock{m_hooks_mutex};
const u16 vid = Memory::Read_U16(request.in_vectors[0].address);
const u16 pid = Memory::Read_U16(request.in_vectors[1].address);
const bool trigger_only_for_new_device = Memory::Read_U8(request.in_vectors[2].address) == 1;
const u16 vid = memory.Read_U16(request.in_vectors[0].address);
const u16 pid = memory.Read_U16(request.in_vectors[1].address);
const bool trigger_only_for_new_device = memory.Read_U8(request.in_vectors[2].address) == 1;
if (!trigger_only_for_new_device && HasDeviceWithVidPid(vid, pid))
return IPCReply(IPC_SUCCESS);
// TODO: figure out whether IOS allows more than one hook.
m_insertion_hooks.insert({{vid, pid}, request.address});
// The output vector is overwritten with an ID to use with ioctl 31 for cancelling the hook.
Memory::Write_U32(vid << 16 | pid, request.io_vectors[0].address);
memory.Write_U32(vid << 16 | pid, request.io_vectors[0].address);
return std::nullopt;
}
@ -316,25 +332,28 @@ std::optional<IPCReply> OH0::DeviceIOCtlV(const u64 device_id, const IOCtlVReque
s32 OH0::SubmitTransfer(USB::Device& device, const IOCtlVRequest& ioctlv)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
switch (ioctlv.request)
{
case USB::IOCTLV_USBV0_CTRLMSG:
if (!ioctlv.HasNumberOfValidVectors(6, 1) ||
Common::swap16(Memory::Read_U16(ioctlv.in_vectors[4].address)) != ioctlv.io_vectors[0].size)
Common::swap16(memory.Read_U16(ioctlv.in_vectors[4].address)) != ioctlv.io_vectors[0].size)
return IPC_EINVAL;
return device.SubmitTransfer(std::make_unique<USB::V0CtrlMessage>(m_ios, ioctlv));
case USB::IOCTLV_USBV0_BLKMSG:
case USB::IOCTLV_USBV0_LBLKMSG:
if (!ioctlv.HasNumberOfValidVectors(2, 1) ||
Memory::Read_U16(ioctlv.in_vectors[1].address) != ioctlv.io_vectors[0].size)
memory.Read_U16(ioctlv.in_vectors[1].address) != ioctlv.io_vectors[0].size)
return IPC_EINVAL;
return device.SubmitTransfer(std::make_unique<USB::V0BulkMessage>(
m_ios, ioctlv, ioctlv.request == USB::IOCTLV_USBV0_LBLKMSG));
case USB::IOCTLV_USBV0_INTRMSG:
if (!ioctlv.HasNumberOfValidVectors(2, 1) ||
Memory::Read_U16(ioctlv.in_vectors[1].address) != ioctlv.io_vectors[0].size)
memory.Read_U16(ioctlv.in_vectors[1].address) != ioctlv.io_vectors[0].size)
return IPC_EINVAL;
return device.SubmitTransfer(std::make_unique<USB::V0IntrMessage>(m_ios, ioctlv));

View file

@ -9,44 +9,53 @@
#include "Common/Swap.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/Device.h"
#include "Core/System.h"
namespace IOS::HLE::USB
{
V0CtrlMessage::V0CtrlMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: CtrlMessage(ios, ioctlv, ioctlv.io_vectors[0].address)
{
request_type = Memory::Read_U8(ioctlv.in_vectors[0].address);
request = Memory::Read_U8(ioctlv.in_vectors[1].address);
value = Common::swap16(Memory::Read_U16(ioctlv.in_vectors[2].address));
index = Common::swap16(Memory::Read_U16(ioctlv.in_vectors[3].address));
length = Common::swap16(Memory::Read_U16(ioctlv.in_vectors[4].address));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
request_type = memory.Read_U8(ioctlv.in_vectors[0].address);
request = memory.Read_U8(ioctlv.in_vectors[1].address);
value = Common::swap16(memory.Read_U16(ioctlv.in_vectors[2].address));
index = Common::swap16(memory.Read_U16(ioctlv.in_vectors[3].address));
length = Common::swap16(memory.Read_U16(ioctlv.in_vectors[4].address));
}
V0BulkMessage::V0BulkMessage(Kernel& ios, const IOCtlVRequest& ioctlv, bool long_length)
: BulkMessage(ios, ioctlv, ioctlv.io_vectors[0].address)
{
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
endpoint = memory.Read_U8(ioctlv.in_vectors[0].address);
if (long_length)
length = Memory::Read_U32(ioctlv.in_vectors[1].address);
length = memory.Read_U32(ioctlv.in_vectors[1].address);
else
length = Memory::Read_U16(ioctlv.in_vectors[1].address);
length = memory.Read_U16(ioctlv.in_vectors[1].address);
}
V0IntrMessage::V0IntrMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: IntrMessage(ios, ioctlv, ioctlv.io_vectors[0].address)
{
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address);
length = Memory::Read_U16(ioctlv.in_vectors[1].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
endpoint = memory.Read_U8(ioctlv.in_vectors[0].address);
length = memory.Read_U16(ioctlv.in_vectors[1].address);
}
V0IsoMessage::V0IsoMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: IsoMessage(ios, ioctlv, ioctlv.io_vectors[1].address)
{
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address);
length = Memory::Read_U16(ioctlv.in_vectors[1].address);
num_packets = Memory::Read_U8(ioctlv.in_vectors[2].address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
endpoint = memory.Read_U8(ioctlv.in_vectors[0].address);
length = memory.Read_U16(ioctlv.in_vectors[1].address);
num_packets = memory.Read_U8(ioctlv.in_vectors[2].address);
packet_sizes_addr = ioctlv.io_vectors[0].address;
for (size_t i = 0; i < num_packets; ++i)
packet_sizes.push_back(Memory::Read_U16(static_cast<u32>(packet_sizes_addr + i * sizeof(u16))));
packet_sizes.push_back(memory.Read_U16(static_cast<u32>(packet_sizes_addr + i * sizeof(u16))));
}
} // namespace IOS::HLE::USB

View file

@ -12,6 +12,7 @@
#include "Common/Swap.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/Device.h"
#include "Core/System.h"
namespace IOS::HLE::USB
{
@ -47,8 +48,11 @@ struct HIDRequest
V4CtrlMessage::V4CtrlMessage(Kernel& ios, const IOCtlRequest& ioctl) : CtrlMessage(ios, ioctl, 0)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
HIDRequest hid_request;
Memory::CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request));
memory.CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request));
request_type = hid_request.control.bmRequestType;
request = hid_request.control.bmRequest;
value = Common::swap16(hid_request.control.wValue);
@ -63,8 +67,11 @@ V4CtrlMessage::V4CtrlMessage(Kernel& ios, const IOCtlRequest& ioctl) : CtrlMessa
V4GetUSStringMessage::V4GetUSStringMessage(Kernel& ios, const IOCtlRequest& ioctl)
: CtrlMessage(ios, ioctl, 0)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
HIDRequest hid_request;
Memory::CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request));
memory.CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request));
request_type = 0x80;
request = REQUEST_GET_DESCRIPTOR;
value = (0x03 << 8) | hid_request.string.bIndex;
@ -75,16 +82,22 @@ V4GetUSStringMessage::V4GetUSStringMessage(Kernel& ios, const IOCtlRequest& ioct
void V4GetUSStringMessage::OnTransferComplete(s32 return_value) const
{
std::string message = Memory::GetString(data_address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
std::string message = memory.GetString(data_address);
std::replace_if(message.begin(), message.end(), std::not_fn(IsPrintableCharacter), '?');
Memory::CopyToEmu(data_address, message.c_str(), message.size());
memory.CopyToEmu(data_address, message.c_str(), message.size());
TransferCommand::OnTransferComplete(return_value);
}
V4IntrMessage::V4IntrMessage(Kernel& ios, const IOCtlRequest& ioctl) : IntrMessage(ios, ioctl, 0)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
HIDRequest hid_request;
Memory::CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request));
memory.CopyFromEmu(&hid_request, ioctl.buffer_in, sizeof(hid_request));
length = Common::swap32(hid_request.interrupt.length);
endpoint = static_cast<u8>(Common::swap32(hid_request.interrupt.endpoint));
data_address = Common::swap32(hid_request.data_addr);

View file

@ -13,6 +13,7 @@
#include "Common/Swap.h"
#include "Core/CoreTiming.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"
namespace IOS::HLE
{
@ -21,37 +22,45 @@ namespace USB
V5CtrlMessage::V5CtrlMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: CtrlMessage(ios, ioctlv, ioctlv.GetVector(1)->address)
{
request_type = Memory::Read_U8(ioctlv.in_vectors[0].address + 8);
request = Memory::Read_U8(ioctlv.in_vectors[0].address + 9);
value = Memory::Read_U16(ioctlv.in_vectors[0].address + 10);
index = Memory::Read_U16(ioctlv.in_vectors[0].address + 12);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
request_type = memory.Read_U8(ioctlv.in_vectors[0].address + 8);
request = memory.Read_U8(ioctlv.in_vectors[0].address + 9);
value = memory.Read_U16(ioctlv.in_vectors[0].address + 10);
index = memory.Read_U16(ioctlv.in_vectors[0].address + 12);
length = static_cast<u16>(ioctlv.GetVector(1)->size);
}
V5BulkMessage::V5BulkMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: BulkMessage(ios, ioctlv, ioctlv.GetVector(1)->address)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
length = ioctlv.GetVector(1)->size;
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address + 18);
endpoint = memory.Read_U8(ioctlv.in_vectors[0].address + 18);
}
V5IntrMessage::V5IntrMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: IntrMessage(ios, ioctlv, ioctlv.GetVector(1)->address)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
length = ioctlv.GetVector(1)->size;
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address + 14);
endpoint = memory.Read_U8(ioctlv.in_vectors[0].address + 14);
}
V5IsoMessage::V5IsoMessage(Kernel& ios, const IOCtlVRequest& ioctlv)
: IsoMessage(ios, ioctlv, ioctlv.GetVector(2)->address)
{
num_packets = Memory::Read_U8(ioctlv.in_vectors[0].address + 16);
endpoint = Memory::Read_U8(ioctlv.in_vectors[0].address + 17);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
num_packets = memory.Read_U8(ioctlv.in_vectors[0].address + 16);
endpoint = memory.Read_U8(ioctlv.in_vectors[0].address + 17);
packet_sizes_addr = ioctlv.GetVector(1)->address;
u32 total_packet_size = 0;
for (size_t i = 0; i < num_packets; ++i)
{
const u32 packet_size = Memory::Read_U16(static_cast<u32>(packet_sizes_addr + i * sizeof(u16)));
const u32 packet_size = memory.Read_U16(static_cast<u32>(packet_sizes_addr + i * sizeof(u16)));
packet_sizes.push_back(packet_size);
total_packet_size += packet_size;
}
@ -99,8 +108,10 @@ void USBV5ResourceManager::DoState(PointerWrap& p)
USBV5ResourceManager::USBV5Device* USBV5ResourceManager::GetUSBV5Device(u32 in_buffer)
{
const u8 index = Memory::Read_U8(in_buffer + offsetof(DeviceID, index));
const u16 number = Memory::Read_U16(in_buffer + offsetof(DeviceID, number));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u8 index = memory.Read_U8(in_buffer + offsetof(DeviceID, index));
const u16 number = memory.Read_U16(in_buffer + offsetof(DeviceID, number));
if (index >= m_usbv5_devices.size())
return nullptr;
@ -135,7 +146,9 @@ IPCReply USBV5ResourceManager::SetAlternateSetting(USBV5Device& device, const IO
if (!host_device->AttachAndChangeInterface(device.interface_number))
return IPCReply(-1);
const u8 alt_setting = Memory::Read_U8(request.buffer_in + 2 * sizeof(s32));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u8 alt_setting = memory.Read_U8(request.buffer_in + 2 * sizeof(s32));
const bool success = host_device->SetAltSetting(alt_setting) == 0;
return IPCReply(success ? IPC_SUCCESS : IPC_EINVAL);
@ -160,8 +173,11 @@ IPCReply USBV5ResourceManager::Shutdown(const IOCtlRequest& request)
IPCReply USBV5ResourceManager::SuspendResume(USBV5Device& device, const IOCtlRequest& request)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const auto host_device = GetDeviceById(device.host_id);
const s32 resumed = Memory::Read_U32(request.buffer_in + 8);
const s32 resumed = memory.Read_U32(request.buffer_in + 8);
// Note: this is unimplemented because there's no easy way to do this in a
// platform-independant way (libusb does not support power management).
@ -232,6 +248,9 @@ void USBV5ResourceManager::TriggerDeviceChangeReply()
return;
}
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
std::lock_guard lock{m_usbv5_devices_mutex};
u8 num_devices = 0;
for (auto it = m_usbv5_devices.crbegin(); it != m_usbv5_devices.crend(); ++it)
@ -264,8 +283,8 @@ void USBV5ResourceManager::TriggerDeviceChangeReply()
entry.interface_number = usbv5_device.interface_number;
entry.num_altsettings = device->GetNumberOfAltSettings(entry.interface_number);
Memory::CopyToEmu(m_devicechange_hook_request->buffer_out + sizeof(entry) * num_devices, &entry,
sizeof(entry));
memory.CopyToEmu(m_devicechange_hook_request->buffer_out + sizeof(entry) * num_devices, &entry,
sizeof(entry));
++num_devices;
}

View file

@ -18,6 +18,7 @@
#include "Core/IOS/Device.h"
#include "Core/IOS/USB/Common.h"
#include "Core/IOS/USB/USBV4.h"
#include "Core/System.h"
namespace IOS::HLE
{
@ -32,6 +33,9 @@ USB_HIDv4::~USB_HIDv4()
std::optional<IPCReply> USB_HIDv4::IOCtl(const IOCtlRequest& request)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
request.Log(GetDeviceName(), Common::Log::LogType::IOS_USB);
switch (request.request)
{
@ -53,7 +57,7 @@ std::optional<IPCReply> USB_HIDv4::IOCtl(const IOCtlRequest& request)
{
if (request.buffer_in == 0 || request.buffer_in_size != 32)
return IPCReply(IPC_EINVAL);
const auto device = GetDeviceByIOSID(Memory::Read_U32(request.buffer_in + 16));
const auto device = GetDeviceByIOSID(memory.Read_U32(request.buffer_in + 16));
if (!device->Attach())
return IPCReply(IPC_EINVAL);
return HandleTransfer(device, request.request,
@ -70,10 +74,13 @@ IPCReply USB_HIDv4::CancelInterrupt(const IOCtlRequest& request)
if (request.buffer_in == 0 || request.buffer_in_size != 8)
return IPCReply(IPC_EINVAL);
auto device = GetDeviceByIOSID(Memory::Read_U32(request.buffer_in));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
auto device = GetDeviceByIOSID(memory.Read_U32(request.buffer_in));
if (!device)
return IPCReply(IPC_ENOENT);
device->CancelTransfer(Memory::Read_U8(request.buffer_in + 4));
device->CancelTransfer(memory.Read_U8(request.buffer_in + 4));
return IPCReply(IPC_SUCCESS);
}
@ -98,7 +105,9 @@ IPCReply USB_HIDv4::Shutdown(const IOCtlRequest& request)
std::lock_guard lk{m_devicechange_hook_address_mutex};
if (m_devicechange_hook_request != 0)
{
Memory::Write_U32(0xffffffff, m_devicechange_hook_request->buffer_out);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.Write_U32(0xffffffff, m_devicechange_hook_request->buffer_out);
m_ios.EnqueueIPCReply(*m_devicechange_hook_request, -1);
m_devicechange_hook_request.reset();
}
@ -182,6 +191,9 @@ void USB_HIDv4::TriggerDeviceChangeReply()
if (!m_devicechange_hook_request)
return;
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
{
std::lock_guard lk(m_devices_mutex);
const u32 dest = m_devicechange_hook_request->buffer_out;
@ -194,11 +206,11 @@ void USB_HIDv4::TriggerDeviceChangeReply()
WARN_LOG_FMT(IOS_USB, "Too many devices connected, skipping");
break;
}
Memory::CopyToEmu(dest + offset, device_section.data(), device_section.size());
memory.CopyToEmu(dest + offset, device_section.data(), device_section.size());
offset += Common::AlignUp(static_cast<u32>(device_section.size()), 4);
}
// IOS writes 0xffffffff to the buffer when there are no more devices
Memory::Write_U32(0xffffffff, dest + offset);
memory.Write_U32(0xffffffff, dest + offset);
}
m_ios.EnqueueIPCReply(*m_devicechange_hook_request, IPC_SUCCESS, 0, CoreTiming::FromThread::ANY);

View file

@ -12,6 +12,7 @@
#include "Common/Logging/Log.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/USB/Common.h"
#include "Core/System.h"
namespace IOS::HLE
{
@ -24,11 +25,14 @@ USB_HIDv5::~USB_HIDv5()
std::optional<IPCReply> USB_HIDv5::IOCtl(const IOCtlRequest& request)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
request.Log(GetDeviceName(), Common::Log::LogType::IOS_USB);
switch (request.request)
{
case USB::IOCTL_USBV5_GETVERSION:
Memory::Write_U32(USBV5_VERSION, request.buffer_out);
memory.Write_U32(USBV5_VERSION, request.buffer_out);
return IPCReply(IPC_SUCCESS);
case USB::IOCTL_USBV5_GETDEVICECHANGE:
return GetDeviceChange(request);
@ -93,11 +97,14 @@ s32 USB_HIDv5::SubmitTransfer(USBV5Device& device, USB::Device& host_device,
{
auto message = std::make_unique<USB::V5IntrMessage>(m_ios, ioctlv);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// Unlike VEN, the endpoint is determined by the value at 8-12.
// If it's non-zero, HID submits the request to the interrupt OUT endpoint.
// Otherwise, the request is submitted to the IN endpoint.
AdditionalDeviceData* data = &m_additional_device_data[&device - m_usbv5_devices.data()];
if (Memory::Read_U32(ioctlv.in_vectors[0].address + 8) != 0)
if (memory.Read_U32(ioctlv.in_vectors[0].address + 8) != 0)
message->endpoint = data->interrupt_out_endpoint;
else
message->endpoint = data->interrupt_in_endpoint;
@ -111,7 +118,10 @@ s32 USB_HIDv5::SubmitTransfer(USBV5Device& device, USB::Device& host_device,
IPCReply USB_HIDv5::CancelEndpoint(USBV5Device& device, const IOCtlRequest& request)
{
const u8 value = Memory::Read_U8(request.buffer_in + 8);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u8 value = memory.Read_U8(request.buffer_in + 8);
u8 endpoint = 0;
switch (value)
{
@ -138,21 +148,24 @@ IPCReply USB_HIDv5::GetDeviceInfo(USBV5Device& device, const IOCtlRequest& reque
if (request.buffer_out == 0 || request.buffer_out_size != 0x60)
return IPCReply(IPC_EINVAL);
const std::shared_ptr<USB::Device> host_device = GetDeviceById(device.host_id);
const u8 alt_setting = Memory::Read_U8(request.buffer_in + 8);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
Memory::Write_U32(Memory::Read_U32(request.buffer_in), request.buffer_out);
Memory::Write_U32(1, request.buffer_out + 4);
const std::shared_ptr<USB::Device> host_device = GetDeviceById(device.host_id);
const u8 alt_setting = memory.Read_U8(request.buffer_in + 8);
memory.Memset(request.buffer_out, 0, request.buffer_out_size);
memory.Write_U32(memory.Read_U32(request.buffer_in), request.buffer_out);
memory.Write_U32(1, request.buffer_out + 4);
USB::DeviceDescriptor device_descriptor = host_device->GetDeviceDescriptor();
device_descriptor.Swap();
Memory::CopyToEmu(request.buffer_out + 36, &device_descriptor, sizeof(device_descriptor));
memory.CopyToEmu(request.buffer_out + 36, &device_descriptor, sizeof(device_descriptor));
// Just like VEN, HIDv5 only cares about the first configuration.
USB::ConfigDescriptor config_descriptor = host_device->GetConfigurations()[0];
config_descriptor.Swap();
Memory::CopyToEmu(request.buffer_out + 56, &config_descriptor, sizeof(config_descriptor));
memory.CopyToEmu(request.buffer_out + 56, &config_descriptor, sizeof(config_descriptor));
std::vector<USB::InterfaceDescriptor> interfaces = host_device->GetInterfaces(0);
auto it = std::find_if(interfaces.begin(), interfaces.end(),
@ -163,7 +176,7 @@ IPCReply USB_HIDv5::GetDeviceInfo(USBV5Device& device, const IOCtlRequest& reque
if (it == interfaces.end())
return IPCReply(IPC_EINVAL);
it->Swap();
Memory::CopyToEmu(request.buffer_out + 68, &*it, sizeof(*it));
memory.CopyToEmu(request.buffer_out + 68, &*it, sizeof(*it));
auto endpoints = host_device->GetEndpoints(0, it->bInterfaceNumber, it->bAlternateSetting);
for (auto& endpoint : endpoints)
@ -182,7 +195,7 @@ IPCReply USB_HIDv5::GetDeviceInfo(USBV5Device& device, const IOCtlRequest& reque
const u32 offset = is_in_endpoint ? 80 : 88;
endpoint.Swap();
Memory::CopyToEmu(request.buffer_out + offset, &endpoint, sizeof(endpoint));
memory.CopyToEmu(request.buffer_out + offset, &endpoint, sizeof(endpoint));
}
}

View file

@ -13,6 +13,7 @@
#include "Core/Config/MainSettings.h"
#include "Core/Core.h" // Local core functions
#include "Core/HW/Memmap.h"
#include "Core/System.h"
#include "InputCommon/ControlReference/ControlReference.h" // For background input check
#ifdef _WIN32
@ -213,7 +214,9 @@ std::optional<IPCReply> USB_KBD::IOCtl(const IOCtlRequest& request)
if (Config::Get(Config::MAIN_WII_KEYBOARD) && !Core::WantsDeterminism() &&
ControlReference::GetInputGate() && !m_message_queue.empty())
{
Memory::CopyToEmu(request.buffer_out, &m_message_queue.front(), sizeof(MessageData));
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyToEmu(request.buffer_out, &m_message_queue.front(), sizeof(MessageData));
m_message_queue.pop();
}
return IPCReply(IPC_SUCCESS);

View file

@ -12,6 +12,7 @@
#include "Common/Logging/Log.h"
#include "Core/HW/Memmap.h"
#include "Core/IOS/USB/Common.h"
#include "Core/System.h"
namespace IOS::HLE
{
@ -24,11 +25,14 @@ USB_VEN::~USB_VEN()
std::optional<IPCReply> USB_VEN::IOCtl(const IOCtlRequest& request)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
request.Log(GetDeviceName(), Common::Log::LogType::IOS_USB);
switch (request.request)
{
case USB::IOCTL_USBV5_GETVERSION:
Memory::Write_U32(USBV5_VERSION, request.buffer_out);
memory.Write_U32(USBV5_VERSION, request.buffer_out);
return IPCReply(IPC_SUCCESS);
case USB::IOCTL_USBV5_GETDEVICECHANGE:
return GetDeviceChange(request);
@ -110,7 +114,10 @@ s32 USB_VEN::SubmitTransfer(USB::Device& device, const IOCtlVRequest& ioctlv)
IPCReply USB_VEN::CancelEndpoint(USBV5Device& device, const IOCtlRequest& request)
{
const u8 endpoint = Memory::Read_U8(request.buffer_in + 8);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u8 endpoint = memory.Read_U8(request.buffer_in + 8);
// IPC_EINVAL (-4) is returned when no transfer was cancelled.
if (GetDeviceById(device.host_id)->CancelTransfer(endpoint) < 0)
return IPCReply(IPC_EINVAL);
@ -122,21 +129,24 @@ IPCReply USB_VEN::GetDeviceInfo(USBV5Device& device, const IOCtlRequest& request
if (request.buffer_out == 0 || request.buffer_out_size != 0xc0)
return IPCReply(IPC_EINVAL);
const std::shared_ptr<USB::Device> host_device = GetDeviceById(device.host_id);
const u8 alt_setting = Memory::Read_U8(request.buffer_in + 8);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
Memory::Write_U32(Memory::Read_U32(request.buffer_in), request.buffer_out);
Memory::Write_U32(1, request.buffer_out + 4);
const std::shared_ptr<USB::Device> host_device = GetDeviceById(device.host_id);
const u8 alt_setting = memory.Read_U8(request.buffer_in + 8);
memory.Memset(request.buffer_out, 0, request.buffer_out_size);
memory.Write_U32(memory.Read_U32(request.buffer_in), request.buffer_out);
memory.Write_U32(1, request.buffer_out + 4);
USB::DeviceDescriptor device_descriptor = host_device->GetDeviceDescriptor();
device_descriptor.Swap();
Memory::CopyToEmu(request.buffer_out + 20, &device_descriptor, sizeof(device_descriptor));
memory.CopyToEmu(request.buffer_out + 20, &device_descriptor, sizeof(device_descriptor));
// VEN only cares about the first configuration.
USB::ConfigDescriptor config_descriptor = host_device->GetConfigurations()[0];
config_descriptor.Swap();
Memory::CopyToEmu(request.buffer_out + 40, &config_descriptor, sizeof(config_descriptor));
memory.CopyToEmu(request.buffer_out + 40, &config_descriptor, sizeof(config_descriptor));
std::vector<USB::InterfaceDescriptor> interfaces = host_device->GetInterfaces(0);
auto it = std::find_if(interfaces.begin(), interfaces.end(),
@ -147,14 +157,14 @@ IPCReply USB_VEN::GetDeviceInfo(USBV5Device& device, const IOCtlRequest& request
if (it == interfaces.end())
return IPCReply(IPC_EINVAL);
it->Swap();
Memory::CopyToEmu(request.buffer_out + 52, &*it, sizeof(*it));
memory.CopyToEmu(request.buffer_out + 52, &*it, sizeof(*it));
auto endpoints = host_device->GetEndpoints(0, it->bInterfaceNumber, it->bAlternateSetting);
for (size_t i = 0; i < endpoints.size(); ++i)
{
endpoints[i].Swap();
Memory::CopyToEmu(request.buffer_out + 64 + 8 * static_cast<u8>(i), &endpoints[i],
sizeof(endpoints[i]));
memory.CopyToEmu(request.buffer_out + 64 + 8 * static_cast<u8>(i), &endpoints[i],
sizeof(endpoints[i]));
}
return IPCReply(IPC_SUCCESS);

View file

@ -20,6 +20,7 @@
#include "Core/IOS/ES/Formats.h"
#include "Core/IOS/IOS.h"
#include "Core/IOS/WFS/WFSSRV.h"
#include "Core/System.h"
namespace
{
@ -127,15 +128,18 @@ std::optional<IPCReply> WFSIDevice::IOCtl(const IOCtlRequest& request)
{
s32 return_error_code = IPC_SUCCESS;
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
switch (request.request)
{
case IOCTL_WFSI_IMPORT_TITLE_INIT:
{
const u32 tmd_addr = Memory::Read_U32(request.buffer_in);
const u32 tmd_size = Memory::Read_U32(request.buffer_in + 4);
const u32 tmd_addr = memory.Read_U32(request.buffer_in);
const u32 tmd_size = memory.Read_U32(request.buffer_in + 4);
m_patch_type = static_cast<PatchType>(Memory::Read_U32(request.buffer_in + 32));
m_continue_install = Memory::Read_U32(request.buffer_in + 36);
m_patch_type = static_cast<PatchType>(memory.Read_U32(request.buffer_in + 32));
m_continue_install = memory.Read_U32(request.buffer_in + 36);
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFSI_IMPORT_TITLE_INIT: patch type {}, continue install: {}",
static_cast<u32>(m_patch_type), m_continue_install ? "true" : "false");
@ -157,7 +161,7 @@ std::optional<IPCReply> WFSIDevice::IOCtl(const IOCtlRequest& request)
}
std::vector<u8> tmd_bytes;
tmd_bytes.resize(tmd_size);
Memory::CopyFromEmu(tmd_bytes.data(), tmd_addr, tmd_size);
memory.CopyFromEmu(tmd_bytes.data(), tmd_addr, tmd_size);
m_tmd.SetBytes(std::move(tmd_bytes));
const ES::TicketReader ticket = m_ios.GetES()->FindSignedTicket(m_tmd.GetTitleId());
@ -190,7 +194,7 @@ std::optional<IPCReply> WFSIDevice::IOCtl(const IOCtlRequest& request)
"IOCTL_WFSI_PREPARE_CONTENT";
// Initializes the IV from the index of the content in the TMD contents.
const u32 content_id = Memory::Read_U32(request.buffer_in + 8);
const u32 content_id = memory.Read_U32(request.buffer_in + 8);
ES::Content content_info;
if (!m_tmd.FindContentById(content_id, &content_info))
{
@ -216,14 +220,14 @@ std::optional<IPCReply> WFSIDevice::IOCtl(const IOCtlRequest& request)
"IOCTL_WFSI_IMPORT_PROFILE" :
"IOCTL_WFSI_IMPORT_CONTENT";
const u32 content_id = Memory::Read_U32(request.buffer_in + 0xC);
const u32 input_ptr = Memory::Read_U32(request.buffer_in + 0x10);
const u32 input_size = Memory::Read_U32(request.buffer_in + 0x14);
const u32 content_id = memory.Read_U32(request.buffer_in + 0xC);
const u32 input_ptr = memory.Read_U32(request.buffer_in + 0x10);
const u32 input_size = memory.Read_U32(request.buffer_in + 0x14);
INFO_LOG_FMT(IOS_WFS, "{}: {:08x} bytes of data at {:08x} from content id {}", ioctl_name,
input_size, input_ptr, content_id);
std::vector<u8> decrypted(input_size);
m_aes_ctx->Crypt(m_aes_iv, m_aes_iv, Memory::GetPointer(input_ptr), decrypted.data(),
m_aes_ctx->Crypt(m_aes_iv, m_aes_iv, memory.GetPointer(input_ptr), decrypted.data(),
input_size);
m_arc_unpacker.AddBytes(decrypted);
@ -331,8 +335,8 @@ std::optional<IPCReply> WFSIDevice::IOCtl(const IOCtlRequest& request)
case IOCTL_WFSI_CHANGE_TITLE:
{
const u64 title_id = Memory::Read_U64(request.buffer_in);
const u16 group_id = Memory::Read_U16(request.buffer_in + 0x1C);
const u64 title_id = memory.Read_U64(request.buffer_in);
const u16 group_id = memory.Read_U16(request.buffer_in + 0x1C);
// TODO: Handle permissions
SetCurrentTitleIdAndGroupId(title_id, group_id);
@ -357,14 +361,14 @@ std::optional<IPCReply> WFSIDevice::IOCtl(const IOCtlRequest& request)
case IOCTL_WFSI_GET_VERSION:
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFSI_GET_VERSION");
Memory::Write_U32(0x20, request.buffer_out);
memory.Write_U32(0x20, request.buffer_out);
break;
case IOCTL_WFSI_IMPORT_TITLE_CANCEL:
{
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFSI_IMPORT_TITLE_CANCEL");
const bool continue_install = Memory::Read_U32(request.buffer_in) != 0;
const bool continue_install = memory.Read_U32(request.buffer_in) != 0;
if (m_patch_type == PatchType::NOT_A_PATCH)
return_error_code = CancelTitleImport(continue_install);
else if (m_patch_type == PatchType::PATCH_TYPE_1 || m_patch_type == PatchType::PATCH_TYPE_2)
@ -394,7 +398,7 @@ std::optional<IPCReply> WFSIDevice::IOCtl(const IOCtlRequest& request)
case IOCTL_WFSI_SET_DEVICE_NAME:
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFSI_SET_DEVICE_NAME");
m_device_name = Memory::GetString(request.buffer_in);
m_device_name = memory.GetString(request.buffer_in);
break;
case IOCTL_WFSI_APPLY_TITLE_PROFILE:
@ -438,30 +442,30 @@ std::optional<IPCReply> WFSIDevice::IOCtl(const IOCtlRequest& request)
case IOCTL_WFSI_GET_TMD:
{
const u64 subtitle_id = Memory::Read_U64(request.buffer_in);
const u32 address = Memory::Read_U32(request.buffer_in + 24);
const u64 subtitle_id = memory.Read_U64(request.buffer_in);
const u32 address = memory.Read_U32(request.buffer_in + 24);
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFSI_GET_TMD: subtitle ID {:016x}", subtitle_id);
u32 tmd_size;
return_error_code =
GetTmd(m_current_group_id, m_current_title_id, subtitle_id, address, &tmd_size);
Memory::Write_U32(tmd_size, request.buffer_out);
memory.Write_U32(tmd_size, request.buffer_out);
break;
}
case IOCTL_WFSI_GET_TMD_ABSOLUTE:
{
const u64 subtitle_id = Memory::Read_U64(request.buffer_in);
const u32 address = Memory::Read_U32(request.buffer_in + 24);
const u16 group_id = Memory::Read_U16(request.buffer_in + 36);
const u32 title_id = Memory::Read_U32(request.buffer_in + 32);
const u64 subtitle_id = memory.Read_U64(request.buffer_in);
const u32 address = memory.Read_U32(request.buffer_in + 24);
const u16 group_id = memory.Read_U16(request.buffer_in + 36);
const u32 title_id = memory.Read_U32(request.buffer_in + 32);
INFO_LOG_FMT(IOS_WFS,
"IOCTL_WFSI_GET_TMD_ABSOLUTE: tid {:08x}, gid {:04x}, subtitle ID {:016x}",
title_id, group_id, subtitle_id);
u32 tmd_size;
return_error_code = GetTmd(group_id, title_id, subtitle_id, address, &tmd_size);
Memory::Write_U32(tmd_size, request.buffer_out);
memory.Write_U32(tmd_size, request.buffer_out);
break;
}
@ -480,9 +484,9 @@ std::optional<IPCReply> WFSIDevice::IOCtl(const IOCtlRequest& request)
std::string path = fmt::format("/vol/{}/title/{}/{}/content", m_device_name,
m_current_group_id_str, m_current_title_id_str);
const u32 dol_addr = Memory::Read_U32(request.buffer_in + 0x18);
const u32 max_dol_size = Memory::Read_U32(request.buffer_in + 0x14);
const u16 dol_extension_id = Memory::Read_U16(request.buffer_in + 0x1e);
const u32 dol_addr = memory.Read_U32(request.buffer_in + 0x18);
const u32 max_dol_size = memory.Read_U32(request.buffer_in + 0x14);
const u16 dol_extension_id = memory.Read_U16(request.buffer_in + 0x1e);
if (dol_extension_id == 0)
{
@ -508,13 +512,13 @@ std::optional<IPCReply> WFSIDevice::IOCtl(const IOCtlRequest& request)
if (dol_addr == 0)
{
// Write the expected size to the size parameter, in the input.
Memory::Write_U32(real_dol_size, request.buffer_in + 0x14);
memory.Write_U32(real_dol_size, request.buffer_in + 0x14);
}
else
{
fp.ReadBytes(Memory::GetPointer(dol_addr), max_dol_size);
fp.ReadBytes(memory.GetPointer(dol_addr), max_dol_size);
}
Memory::Write_U32(real_dol_size, request.buffer_out);
memory.Write_U32(real_dol_size, request.buffer_out);
break;
}
@ -541,7 +545,7 @@ std::optional<IPCReply> WFSIDevice::IOCtl(const IOCtlRequest& request)
// succeeding.
request.DumpUnknown(GetDeviceName(), Common::Log::LogType::IOS_WFS,
Common::Log::LogLevel::LWARNING);
Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
memory.Memset(request.buffer_out, 0, request.buffer_out_size);
break;
}
@ -560,7 +564,9 @@ u32 WFSIDevice::GetTmd(u16 group_id, u32 title_id, u64 subtitle_id, u32 address,
}
if (address)
{
fp.ReadBytes(Memory::GetPointer(address), fp.GetSize());
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
fp.ReadBytes(memory.GetPointer(address), fp.GetSize());
}
*size = fp.GetSize();
return IPC_SUCCESS;

View file

@ -13,6 +13,7 @@
#include "Common/Logging/Log.h"
#include "Common/NandPaths.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"
namespace IOS::HLE
{
@ -33,6 +34,9 @@ std::optional<IPCReply> WFSSRVDevice::IOCtl(const IOCtlRequest& request)
{
int return_error_code = IPC_SUCCESS;
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
switch (request.request)
{
case IOCTL_WFS_INIT:
@ -43,8 +47,8 @@ std::optional<IPCReply> WFSSRVDevice::IOCtl(const IOCtlRequest& request)
case IOCTL_WFS_UNKNOWN_8:
// TODO(wfs): Figure out what this actually does.
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFS_UNKNOWN_8");
Memory::Write_U8(7, request.buffer_out);
Memory::CopyToEmu(request.buffer_out + 1, "msc01\x00\x00\x00", 8);
memory.Write_U8(7, request.buffer_out);
memory.CopyToEmu(request.buffer_out + 1, "msc01\x00\x00\x00", 8);
break;
case IOCTL_WFS_SHUTDOWN:
@ -54,33 +58,33 @@ std::optional<IPCReply> WFSSRVDevice::IOCtl(const IOCtlRequest& request)
for (auto address : m_hanging)
{
IOCtlRequest hanging_request{address};
Memory::Write_U32(0x80000000, hanging_request.buffer_out);
Memory::Write_U32(0, hanging_request.buffer_out + 4);
Memory::Write_U32(0, hanging_request.buffer_out + 8);
memory.Write_U32(0x80000000, hanging_request.buffer_out);
memory.Write_U32(0, hanging_request.buffer_out + 4);
memory.Write_U32(0, hanging_request.buffer_out + 8);
m_ios.EnqueueIPCReply(hanging_request, 0);
}
break;
case IOCTL_WFS_DEVICE_INFO:
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFS_DEVICE_INFO");
Memory::Write_U64(16ull << 30, request.buffer_out); // 16GB storage.
Memory::Write_U8(4, request.buffer_out + 8);
memory.Write_U64(16ull << 30, request.buffer_out); // 16GB storage.
memory.Write_U8(4, request.buffer_out + 8);
break;
case IOCTL_WFS_GET_DEVICE_NAME:
{
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFS_GET_DEVICE_NAME");
Memory::Write_U8(static_cast<u8>(m_device_name.size()), request.buffer_out);
Memory::CopyToEmu(request.buffer_out + 1, m_device_name.data(), m_device_name.size());
memory.Write_U8(static_cast<u8>(m_device_name.size()), request.buffer_out);
memory.CopyToEmu(request.buffer_out + 1, m_device_name.data(), m_device_name.size());
break;
}
case IOCTL_WFS_ATTACH_DETACH_2:
// TODO(wfs): Implement.
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFS_ATTACH_DETACH_2({})", request.request);
Memory::Write_U32(1, request.buffer_out);
Memory::Write_U32(0, request.buffer_out + 4); // device id?
Memory::Write_U32(0, request.buffer_out + 8);
memory.Write_U32(1, request.buffer_out);
memory.Write_U32(0, request.buffer_out + 4); // device id?
memory.Write_U32(0, request.buffer_out + 8);
break;
case IOCTL_WFS_ATTACH_DETACH:
@ -98,7 +102,7 @@ std::optional<IPCReply> WFSSRVDevice::IOCtl(const IOCtlRequest& request)
case IOCTL_WFS_MKDIR:
{
const std::string path = NormalizePath(
Memory::GetString(request.buffer_in + 34, Memory::Read_U16(request.buffer_in + 32)));
memory.GetString(request.buffer_in + 34, memory.Read_U16(request.buffer_in + 32)));
const std::string native_path = WFS::NativePath(path);
if (File::Exists(native_path))
@ -122,8 +126,8 @@ std::optional<IPCReply> WFSSRVDevice::IOCtl(const IOCtlRequest& request)
// (listing /vol/*) which is required to get the installer to work.
case IOCTL_WFS_GLOB_START:
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFS_GLOB_START({})", request.request);
Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
Memory::CopyToEmu(request.buffer_out + 0x14, m_device_name.data(), m_device_name.size());
memory.Memset(request.buffer_out, 0, request.buffer_out_size);
memory.CopyToEmu(request.buffer_out + 0x14, m_device_name.data(), m_device_name.size());
break;
case IOCTL_WFS_GLOB_NEXT:
@ -133,34 +137,33 @@ std::optional<IPCReply> WFSSRVDevice::IOCtl(const IOCtlRequest& request)
case IOCTL_WFS_GLOB_END:
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFS_GLOB_END({})", request.request);
Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
memory.Memset(request.buffer_out, 0, request.buffer_out_size);
break;
case IOCTL_WFS_SET_HOMEDIR:
m_home_directory =
Memory::GetString(request.buffer_in + 2, Memory::Read_U16(request.buffer_in));
m_home_directory = memory.GetString(request.buffer_in + 2, memory.Read_U16(request.buffer_in));
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFS_SET_HOMEDIR: {}", m_home_directory);
break;
case IOCTL_WFS_CHDIR:
m_current_directory =
Memory::GetString(request.buffer_in + 2, Memory::Read_U16(request.buffer_in));
memory.GetString(request.buffer_in + 2, memory.Read_U16(request.buffer_in));
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFS_CHDIR: {}", m_current_directory);
break;
case IOCTL_WFS_GET_HOMEDIR:
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFS_GET_HOMEDIR: {}", m_home_directory);
Memory::Write_U16(static_cast<u16>(m_home_directory.size()), request.buffer_out);
Memory::CopyToEmu(request.buffer_out + 2, m_home_directory.data(), m_home_directory.size());
memory.Write_U16(static_cast<u16>(m_home_directory.size()), request.buffer_out);
memory.CopyToEmu(request.buffer_out + 2, m_home_directory.data(), m_home_directory.size());
break;
case IOCTL_WFS_GET_ATTRIBUTES:
{
const std::string path = NormalizePath(
Memory::GetString(request.buffer_in + 2, Memory::Read_U16(request.buffer_in)));
const std::string path =
NormalizePath(memory.GetString(request.buffer_in + 2, memory.Read_U16(request.buffer_in)));
const std::string native_path = WFS::NativePath(path);
Memory::Memset(0, request.buffer_out, request.buffer_out_size);
memory.Memset(0, request.buffer_out, request.buffer_out_size);
if (!File::Exists(native_path))
{
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFS_GET_ATTRIBUTES({}): no such file or directory", path);
@ -169,13 +172,13 @@ std::optional<IPCReply> WFSSRVDevice::IOCtl(const IOCtlRequest& request)
else if (File::IsDirectory(native_path))
{
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFS_GET_ATTRIBUTES({}): directory", path);
Memory::Write_U32(0x80000000, request.buffer_out + 4);
memory.Write_U32(0x80000000, request.buffer_out + 4);
}
else
{
const auto size = static_cast<u32>(File::GetSize(native_path));
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFS_GET_ATTRIBUTES({}): file with size {}", path, size);
Memory::Write_U32(size, request.buffer_out);
memory.Write_U32(size, request.buffer_out);
}
break;
}
@ -184,9 +187,9 @@ std::optional<IPCReply> WFSSRVDevice::IOCtl(const IOCtlRequest& request)
case IOCTL_WFS_RENAME_2:
{
const std::string source_path =
Memory::GetString(request.buffer_in + 2, Memory::Read_U16(request.buffer_in));
memory.GetString(request.buffer_in + 2, memory.Read_U16(request.buffer_in));
const std::string dest_path =
Memory::GetString(request.buffer_in + 512 + 2, Memory::Read_U16(request.buffer_in + 512));
memory.GetString(request.buffer_in + 512 + 2, memory.Read_U16(request.buffer_in + 512));
return_error_code = Rename(source_path, dest_path);
break;
}
@ -196,9 +199,9 @@ std::optional<IPCReply> WFSSRVDevice::IOCtl(const IOCtlRequest& request)
{
const char* ioctl_name =
request.request == IOCTL_WFS_OPEN ? "IOCTL_WFS_OPEN" : "IOCTL_WFS_CREATE_OPEN";
const u32 mode = request.request == IOCTL_WFS_OPEN ? Memory::Read_U32(request.buffer_in) : 2;
const u16 path_len = Memory::Read_U16(request.buffer_in + 0x20);
std::string path = Memory::GetString(request.buffer_in + 0x22, path_len);
const u32 mode = request.request == IOCTL_WFS_OPEN ? memory.Read_U32(request.buffer_in) : 2;
const u16 path_len = memory.Read_U16(request.buffer_in + 0x20);
std::string path = memory.GetString(request.buffer_in + 0x22, path_len);
path = NormalizePath(path);
@ -220,18 +223,18 @@ std::optional<IPCReply> WFSSRVDevice::IOCtl(const IOCtlRequest& request)
INFO_LOG_FMT(IOS_WFS, "{}({}, {}) -> {}", ioctl_name, path, mode, fd);
if (request.request == IOCTL_WFS_OPEN)
{
Memory::Write_U16(fd, request.buffer_out + 0x14);
memory.Write_U16(fd, request.buffer_out + 0x14);
}
else
{
Memory::Write_U16(fd, request.buffer_out);
memory.Write_U16(fd, request.buffer_out);
}
break;
}
case IOCTL_WFS_GET_SIZE:
{
const u16 fd = Memory::Read_U16(request.buffer_in);
const u16 fd = memory.Read_U16(request.buffer_in);
FileDescriptor* fd_obj = FindFileDescriptor(fd);
if (fd_obj == nullptr)
{
@ -247,13 +250,13 @@ std::optional<IPCReply> WFSSRVDevice::IOCtl(const IOCtlRequest& request)
{
ERROR_LOG_FMT(IOS_WFS, "IOCTL_WFS_GET_SIZE: file {} too large ({})", fd, size);
}
Memory::Write_U32(truncated_size, request.buffer_out);
memory.Write_U32(truncated_size, request.buffer_out);
break;
}
case IOCTL_WFS_CLOSE:
{
const u16 fd = Memory::Read_U16(request.buffer_in + 0x4);
const u16 fd = memory.Read_U16(request.buffer_in + 0x4);
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFS_CLOSE({})", fd);
ReleaseFileDescriptor(fd);
break;
@ -263,7 +266,7 @@ std::optional<IPCReply> WFSSRVDevice::IOCtl(const IOCtlRequest& request)
{
// TODO(wfs): Figure out the exact semantics difference from the other
// close.
const u16 fd = Memory::Read_U16(request.buffer_in + 0x4);
const u16 fd = memory.Read_U16(request.buffer_in + 0x4);
INFO_LOG_FMT(IOS_WFS, "IOCTL_WFS_CLOSE_2({})", fd);
ReleaseFileDescriptor(fd);
break;
@ -272,10 +275,10 @@ std::optional<IPCReply> WFSSRVDevice::IOCtl(const IOCtlRequest& request)
case IOCTL_WFS_READ:
case IOCTL_WFS_READ_ABSOLUTE:
{
const u32 addr = Memory::Read_U32(request.buffer_in);
const u32 position = Memory::Read_U32(request.buffer_in + 4); // Only for absolute.
const u16 fd = Memory::Read_U16(request.buffer_in + 0xC);
const u32 size = Memory::Read_U32(request.buffer_in + 8);
const u32 addr = memory.Read_U32(request.buffer_in);
const u32 position = memory.Read_U32(request.buffer_in + 4); // Only for absolute.
const u16 fd = memory.Read_U16(request.buffer_in + 0xC);
const u32 size = memory.Read_U32(request.buffer_in + 8);
const bool absolute = request.request == IOCTL_WFS_READ_ABSOLUTE;
@ -293,7 +296,7 @@ std::optional<IPCReply> WFSSRVDevice::IOCtl(const IOCtlRequest& request)
fd_obj->file.Seek(position, File::SeekOrigin::Begin);
}
size_t read_bytes;
fd_obj->file.ReadArray(Memory::GetPointer(addr), size, &read_bytes);
fd_obj->file.ReadArray(memory.GetPointer(addr), size, &read_bytes);
// TODO(wfs): Handle read errors.
if (absolute)
{
@ -313,10 +316,10 @@ std::optional<IPCReply> WFSSRVDevice::IOCtl(const IOCtlRequest& request)
case IOCTL_WFS_WRITE:
case IOCTL_WFS_WRITE_ABSOLUTE:
{
const u32 addr = Memory::Read_U32(request.buffer_in);
const u32 position = Memory::Read_U32(request.buffer_in + 4); // Only for absolute.
const u16 fd = Memory::Read_U16(request.buffer_in + 0xC);
const u32 size = Memory::Read_U32(request.buffer_in + 8);
const u32 addr = memory.Read_U32(request.buffer_in);
const u32 position = memory.Read_U32(request.buffer_in + 4); // Only for absolute.
const u16 fd = memory.Read_U16(request.buffer_in + 0xC);
const u32 size = memory.Read_U32(request.buffer_in + 8);
const bool absolute = request.request == IOCTL_WFS_WRITE_ABSOLUTE;
@ -333,7 +336,7 @@ std::optional<IPCReply> WFSSRVDevice::IOCtl(const IOCtlRequest& request)
{
fd_obj->file.Seek(position, File::SeekOrigin::Begin);
}
fd_obj->file.WriteArray(Memory::GetPointer(addr), size);
fd_obj->file.WriteArray(memory.GetPointer(addr), size);
// TODO(wfs): Handle write errors.
if (absolute)
{
@ -354,7 +357,7 @@ std::optional<IPCReply> WFSSRVDevice::IOCtl(const IOCtlRequest& request)
// properly stubbed it's easier to simulate the methods succeeding.
request.DumpUnknown(GetDeviceName(), Common::Log::LogType::IOS_WFS,
Common::Log::LogLevel::LWARNING);
Memory::Memset(request.buffer_out, 0, request.buffer_out_size);
memory.Memset(request.buffer_out, 0, request.buffer_out_size);
break;
}

View file

@ -809,7 +809,10 @@ static void ReadMemory()
if (!PowerPC::HostIsRAMAddress(addr))
return SendReply("E00");
u8* data = Memory::GetPointer(addr);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u8* data = memory.GetPointer(addr);
Mem2hex(reply, data, len);
reply[len * 2] = '\0';
SendReply((char*)reply);
@ -833,7 +836,10 @@ static void WriteMemory()
if (!PowerPC::HostIsRAMAddress(addr))
return SendReply("E00");
u8* dst = Memory::GetPointer(addr);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u8* dst = memory.GetPointer(addr);
Hex2mem(dst, s_cmd_bfr + i + 1, len);
SendReply("OK");
}

View file

@ -224,12 +224,15 @@ bool Jit64::HandleFault(uintptr_t access_address, SContext* ctx)
// Only instructions that access I/O will get these, and there won't be that
// many of them in a typical program/game.
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// TODO: do we properly handle off-the-end?
const auto base_ptr = reinterpret_cast<uintptr_t>(Memory::physical_base);
const auto base_ptr = reinterpret_cast<uintptr_t>(memory.GetPhysicalBase());
if (access_address >= base_ptr && access_address < base_ptr + 0x100010000)
return BackPatch(static_cast<u32>(access_address - base_ptr), ctx);
const auto logical_base_ptr = reinterpret_cast<uintptr_t>(Memory::logical_base);
const auto logical_base_ptr = reinterpret_cast<uintptr_t>(memory.GetLogicalBase());
if (access_address >= logical_base_ptr && access_address < logical_base_ptr + 0x100010000)
return BackPatch(static_cast<u32>(access_address - logical_base_ptr), ctx);
@ -330,7 +333,10 @@ void Jit64::Init()
{
EnableBlockLink();
jo.fastmem_arena = m_fastmem_enabled && Memory::InitFastmemArena();
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
jo.fastmem_arena = m_fastmem_enabled && memory.InitFastmemArena();
jo.optimizeGatherPipe = true;
jo.accurateSinglePrecision = true;
UpdateMemoryAndExceptionOptions();
@ -404,7 +410,9 @@ void Jit64::Shutdown()
FreeStack();
FreeCodeSpace();
Memory::ShutdownFastmemArena();
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.ShutdownFastmemArena();
blocks.Shutdown();
m_far_code.Shutdown();

View file

@ -16,6 +16,7 @@
#include "Core/PowerPC/Jit64/Jit.h"
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
using namespace Gen;
@ -102,6 +103,9 @@ void Jit64AsmRoutineManager::Generate()
dispatcher_no_check = GetCodePtr();
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// The following is a translation of JitBaseBlockCache::Dispatch into assembly.
const bool assembly_dispatcher = true;
if (assembly_dispatcher)
@ -141,10 +145,10 @@ void Jit64AsmRoutineManager::Generate()
// Switch to the correct memory base, in case MSR.DR has changed.
TEST(32, PPCSTATE(msr), Imm32(1 << (31 - 27)));
FixupBranch physmem = J_CC(CC_Z);
MOV(64, R(RMEM), ImmPtr(Memory::logical_base));
MOV(64, R(RMEM), ImmPtr(memory.GetLogicalBase()));
JMPptr(MDisp(RSCRATCH, static_cast<s32>(offsetof(JitBlockData, normalEntry))));
SetJumpTarget(physmem);
MOV(64, R(RMEM), ImmPtr(Memory::physical_base));
MOV(64, R(RMEM), ImmPtr(memory.GetPhysicalBase()));
JMPptr(MDisp(RSCRATCH, static_cast<s32>(offsetof(JitBlockData, normalEntry))));
SetJumpTarget(not_found);
@ -165,10 +169,10 @@ void Jit64AsmRoutineManager::Generate()
// Switch to the correct memory base, in case MSR.DR has changed.
TEST(32, PPCSTATE(msr), Imm32(1 << (31 - 27)));
FixupBranch physmem = J_CC(CC_Z);
MOV(64, R(RMEM), ImmPtr(Memory::logical_base));
MOV(64, R(RMEM), ImmPtr(memory.GetLogicalBase()));
JMPptr(R(ABI_RETURN));
SetJumpTarget(physmem);
MOV(64, R(RMEM), ImmPtr(Memory::physical_base));
MOV(64, R(RMEM), ImmPtr(memory.GetPhysicalBase()));
JMPptr(R(ABI_RETURN));
SetJumpTarget(no_block_available);

View file

@ -442,7 +442,9 @@ void EmuCodeBlock::SafeLoadToRegImmediate(X64Reg reg_value, u32 address, int acc
u32 mmioAddress = PowerPC::IsOptimizableMMIOAccess(address, accessSize);
if (accessSize != 64 && mmioAddress)
{
MMIOLoadToReg(Memory::mmio_mapping.get(), reg_value, registersInUse, mmioAddress, accessSize,
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
MMIOLoadToReg(memory.GetMMIOMapping(), reg_value, registersInUse, mmioAddress, accessSize,
signExtend);
return;
}

View file

@ -53,7 +53,10 @@ void JitArm64::Init()
AllocCodeSpace(CODE_SIZE + child_code_size);
AddChildCodeSpace(&m_far_code, child_code_size);
jo.fastmem_arena = m_fastmem_enabled && Memory::InitFastmemArena();
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
jo.fastmem_arena = m_fastmem_enabled && memory.InitFastmemArena();
jo.enableBlocklink = true;
jo.optimizeGatherPipe = true;
UpdateMemoryAndExceptionOptions();
@ -154,7 +157,9 @@ void JitArm64::ResetFreeMemoryRanges()
void JitArm64::Shutdown()
{
Memory::ShutdownFastmemArena();
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.ShutdownFastmemArena();
FreeCodeSpace();
blocks.Shutdown();
FreeStack();

View file

@ -22,6 +22,7 @@
#include "Core/PowerPC/JitArmCommon/BackPatch.h"
#include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
using namespace Arm64Gen;
@ -302,14 +303,17 @@ void JitArm64::EmitBackpatchRoutine(u32 flags, MemAccessMode mode, ARM64Reg RS,
bool JitArm64::HandleFastmemFault(uintptr_t access_address, SContext* ctx)
{
if (!(access_address >= (uintptr_t)Memory::physical_base &&
access_address < (uintptr_t)Memory::physical_base + 0x100010000) &&
!(access_address >= (uintptr_t)Memory::logical_base &&
access_address < (uintptr_t)Memory::logical_base + 0x100010000))
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
if (!(access_address >= (uintptr_t)memory.GetPhysicalBase() &&
access_address < (uintptr_t)memory.GetPhysicalBase() + 0x100010000) &&
!(access_address >= (uintptr_t)memory.GetLogicalBase() &&
access_address < (uintptr_t)memory.GetLogicalBase() + 0x100010000))
{
ERROR_LOG_FMT(DYNA_REC,
"Exception handler - access below memory space. PC: {:#018x} {:#018x} < {:#018x}",
ctx->CTX_PC, access_address, (uintptr_t)Memory::physical_base);
ctx->CTX_PC, access_address, (uintptr_t)memory.GetPhysicalBase());
return false;
}

View file

@ -20,6 +20,7 @@
#include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PPCTables.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
using namespace Arm64Gen;
@ -144,8 +145,10 @@ void JitArm64::SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 o
regs_in_use[DecodeReg(ARM64Reg::W0)] = 0;
regs_in_use[DecodeReg(ARM64Reg::W30)] = 0;
regs_in_use[DecodeReg(dest_reg)] = 0;
MMIOLoadToReg(Memory::mmio_mapping.get(), this, &m_float_emit, regs_in_use, fprs_in_use,
dest_reg, mmio_address, flags);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
MMIOLoadToReg(memory.GetMMIOMapping(), this, &m_float_emit, regs_in_use, fprs_in_use, dest_reg,
mmio_address, flags);
addr_reg_set = false;
}
else
@ -316,8 +319,10 @@ void JitArm64::SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s
regs_in_use[DecodeReg(ARM64Reg::W1)] = 0;
regs_in_use[DecodeReg(ARM64Reg::W30)] = 0;
regs_in_use[DecodeReg(RS)] = 0;
MMIOWriteRegToAddr(Memory::mmio_mapping.get(), this, &m_float_emit, regs_in_use, fprs_in_use,
RS, mmio_address, flags);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
MMIOWriteRegToAddr(memory.GetMMIOMapping(), this, &m_float_emit, regs_in_use, fprs_in_use, RS,
mmio_address, flags);
addr_reg_set = false;
}
else

View file

@ -20,6 +20,7 @@
#include "Core/PowerPC/JitCommon/JitCache.h"
#include "Core/PowerPC/MMU.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
using namespace Arm64Gen;
@ -88,15 +89,20 @@ void JitArm64::GenerateAsm()
bool assembly_dispatcher = true;
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
if (assembly_dispatcher)
{
// set the mem_base based on MSR flags
LDR(IndexType::Unsigned, ARM64Reg::W28, PPC_REG, PPCSTATE_OFF(msr));
FixupBranch physmem = TBNZ(ARM64Reg::W28, 31 - 27);
MOVP2R(MEM_REG, jo.fastmem_arena ? Memory::physical_base : Memory::physical_page_mappings_base);
MOVP2R(MEM_REG,
jo.fastmem_arena ? memory.GetPhysicalBase() : memory.GetPhysicalPageMappingsBase());
FixupBranch membaseend = B();
SetJumpTarget(physmem);
MOVP2R(MEM_REG, jo.fastmem_arena ? Memory::logical_base : Memory::logical_page_mappings_base);
MOVP2R(MEM_REG,
jo.fastmem_arena ? memory.GetLogicalBase() : memory.GetLogicalPageMappingsBase());
SetJumpTarget(membaseend);
// iCache[(address >> 2) & iCache_Mask];
@ -141,10 +147,11 @@ void JitArm64::GenerateAsm()
// set the mem_base based on MSR flags and jump to next block.
LDR(IndexType::Unsigned, ARM64Reg::W28, PPC_REG, PPCSTATE_OFF(msr));
FixupBranch physmem = TBNZ(ARM64Reg::W28, 31 - 27);
MOVP2R(MEM_REG, jo.fastmem_arena ? Memory::physical_base : Memory::physical_page_mappings_base);
MOVP2R(MEM_REG,
jo.fastmem_arena ? memory.GetPhysicalBase() : memory.GetPhysicalPageMappingsBase());
BR(ARM64Reg::X0);
SetJumpTarget(physmem);
MOVP2R(MEM_REG, jo.fastmem_arena ? Memory::logical_base : Memory::logical_page_mappings_base);
MOVP2R(MEM_REG, jo.fastmem_arena ? memory.GetLogicalBase() : memory.GetLogicalPageMappingsBase());
BR(ARM64Reg::X0);
// Call JIT

View file

@ -171,7 +171,7 @@ BatTable dbat_table;
static void GenerateDSIException(u32 effective_address, bool write);
template <XCheckTLBFlag flag, typename T, bool never_translate = false>
static T ReadFromHardware(u32 em_address)
static T ReadFromHardware(Memory::MemoryManager& memory, u32 em_address)
{
const u32 em_address_start_page = em_address & ~HW_PAGE_MASK;
const u32 em_address_end_page = (em_address + sizeof(T) - 1) & ~HW_PAGE_MASK;
@ -183,7 +183,7 @@ static T ReadFromHardware(u32 em_address)
// Note that "word" means 32-bit, so paired singles or doubles might still be 32-bit aligned!
u64 var = 0;
for (u32 i = 0; i < sizeof(T); ++i)
var = (var << 8) | ReadFromHardware<flag, u8, never_translate>(em_address + i);
var = (var << 8) | ReadFromHardware<flag, u8, never_translate>(memory, em_address + i);
return static_cast<T>(var);
}
@ -204,42 +204,42 @@ static T ReadFromHardware(u32 em_address)
if (em_address < 0x0c000000)
return EFB_Read(em_address);
else
return static_cast<T>(Memory::mmio_mapping->Read<std::make_unsigned_t<T>>(em_address));
return static_cast<T>(memory.GetMMIOMapping()->Read<std::make_unsigned_t<T>>(em_address));
}
// Locked L1 technically doesn't have a fixed address, but games all use 0xE0000000.
if (Memory::m_pL1Cache && (em_address >> 28) == 0xE &&
(em_address < (0xE0000000 + Memory::GetL1CacheSize())))
if (memory.GetL1Cache() && (em_address >> 28) == 0xE &&
(em_address < (0xE0000000 + memory.GetL1CacheSize())))
{
T value;
std::memcpy(&value, &Memory::m_pL1Cache[em_address & 0x0FFFFFFF], sizeof(T));
std::memcpy(&value, &memory.GetL1Cache()[em_address & 0x0FFFFFFF], sizeof(T));
return bswap(value);
}
if (Memory::m_pRAM && (em_address & 0xF8000000) == 0x00000000)
if (memory.GetRAM() && (em_address & 0xF8000000) == 0x00000000)
{
// Handle RAM; the masking intentionally discards bits (essentially creating
// mirrors of memory).
T value;
std::memcpy(&value, &Memory::m_pRAM[em_address & Memory::GetRamMask()], sizeof(T));
std::memcpy(&value, &memory.GetRAM()[em_address & memory.GetRamMask()], sizeof(T));
return bswap(value);
}
if (Memory::m_pEXRAM && (em_address >> 28) == 0x1 &&
(em_address & 0x0FFFFFFF) < Memory::GetExRamSizeReal())
if (memory.GetEXRAM() && (em_address >> 28) == 0x1 &&
(em_address & 0x0FFFFFFF) < memory.GetExRamSizeReal())
{
T value;
std::memcpy(&value, &Memory::m_pEXRAM[em_address & 0x0FFFFFFF], sizeof(T));
std::memcpy(&value, &memory.GetEXRAM()[em_address & 0x0FFFFFFF], sizeof(T));
return bswap(value);
}
// In Fake-VMEM mode, we need to map the memory somewhere into
// physical memory for BAT translation to work; we currently use
// [0x7E000000, 0x80000000).
if (Memory::m_pFakeVMEM && ((em_address & 0xFE000000) == 0x7E000000))
if (memory.GetFakeVMEM() && ((em_address & 0xFE000000) == 0x7E000000))
{
T value;
std::memcpy(&value, &Memory::m_pFakeVMEM[em_address & Memory::GetFakeVMemMask()], sizeof(T));
std::memcpy(&value, &memory.GetFakeVMEM()[em_address & memory.GetFakeVMemMask()], sizeof(T));
return bswap(value);
}
@ -253,7 +253,8 @@ static T ReadFromHardware(u32 em_address)
}
template <XCheckTLBFlag flag, bool never_translate = false>
static void WriteToHardware(u32 em_address, const u32 data, const u32 size)
static void WriteToHardware(Memory::MemoryManager& memory, u32 em_address, const u32 data,
const u32 size)
{
DEBUG_ASSERT(size <= 4);
@ -267,8 +268,8 @@ static void WriteToHardware(u32 em_address, const u32 data, const u32 size)
const u32 first_half_size = em_address_end_page - em_address;
const u32 second_half_size = size - first_half_size;
WriteToHardware<flag, never_translate>(
em_address, Common::RotateRight(data, second_half_size * 8), first_half_size);
WriteToHardware<flag, never_translate>(em_address_end_page, data, second_half_size);
memory, em_address, Common::RotateRight(data, second_half_size * 8), first_half_size);
WriteToHardware<flag, never_translate>(memory, em_address_end_page, data, second_half_size);
return;
}
@ -333,20 +334,20 @@ static void WriteToHardware(u32 em_address, const u32 data, const u32 size)
switch (size)
{
case 1:
Memory::mmio_mapping->Write<u8>(em_address, static_cast<u8>(data));
memory.GetMMIOMapping()->Write<u8>(em_address, static_cast<u8>(data));
return;
case 2:
Memory::mmio_mapping->Write<u16>(em_address, static_cast<u16>(data));
memory.GetMMIOMapping()->Write<u16>(em_address, static_cast<u16>(data));
return;
case 4:
Memory::mmio_mapping->Write<u32>(em_address, data);
memory.GetMMIOMapping()->Write<u32>(em_address, data);
return;
default:
// 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++)
{
i -= 8;
Memory::mmio_mapping->Write<u8>(em_address, static_cast<u8>(data >> i));
memory.GetMMIOMapping()->Write<u8>(em_address, static_cast<u8>(data >> i));
}
return;
}
@ -355,10 +356,10 @@ static void WriteToHardware(u32 em_address, const u32 data, const u32 size)
const u32 swapped_data = Common::swap32(Common::RotateRight(data, size * 8));
// Locked L1 technically doesn't have a fixed address, but games all use 0xE0000000.
if (Memory::m_pL1Cache && (em_address >> 28 == 0xE) &&
(em_address < (0xE0000000 + Memory::GetL1CacheSize())))
if (memory.GetL1Cache() && (em_address >> 28 == 0xE) &&
(em_address < (0xE0000000 + memory.GetL1CacheSize())))
{
std::memcpy(&Memory::m_pL1Cache[em_address & 0x0FFFFFFF], &swapped_data, size);
std::memcpy(&memory.GetL1Cache()[em_address & 0x0FFFFFFF], &swapped_data, size);
return;
}
@ -379,34 +380,34 @@ static void WriteToHardware(u32 em_address, const u32 data, const u32 size)
for (u32 addr = em_address & ~0x7; addr < em_address + size; addr += 8)
{
WriteToHardware<flag, true>(addr, rotated_data, 4);
WriteToHardware<flag, true>(addr + 4, rotated_data, 4);
WriteToHardware<flag, true>(memory, addr, rotated_data, 4);
WriteToHardware<flag, true>(memory, addr + 4, rotated_data, 4);
}
return;
}
if (Memory::m_pRAM && (em_address & 0xF8000000) == 0x00000000)
if (memory.GetRAM() && (em_address & 0xF8000000) == 0x00000000)
{
// Handle RAM; the masking intentionally discards bits (essentially creating
// mirrors of memory).
std::memcpy(&Memory::m_pRAM[em_address & Memory::GetRamMask()], &swapped_data, size);
std::memcpy(&memory.GetRAM()[em_address & memory.GetRamMask()], &swapped_data, size);
return;
}
if (Memory::m_pEXRAM && (em_address >> 28) == 0x1 &&
(em_address & 0x0FFFFFFF) < Memory::GetExRamSizeReal())
if (memory.GetEXRAM() && (em_address >> 28) == 0x1 &&
(em_address & 0x0FFFFFFF) < memory.GetExRamSizeReal())
{
std::memcpy(&Memory::m_pEXRAM[em_address & 0x0FFFFFFF], &swapped_data, size);
std::memcpy(&memory.GetEXRAM()[em_address & 0x0FFFFFFF], &swapped_data, size);
return;
}
// In Fake-VMEM mode, we need to map the memory somewhere into
// physical memory for BAT translation to work; we currently use
// [0x7E000000, 0x80000000).
if (Memory::m_pFakeVMEM && ((em_address & 0xFE000000) == 0x7E000000))
if (memory.GetFakeVMEM() && ((em_address & 0xFE000000) == 0x7E000000))
{
std::memcpy(&Memory::m_pFakeVMEM[em_address & Memory::GetFakeVMemMask()], &swapped_data, size);
std::memcpy(&memory.GetFakeVMEM()[em_address & memory.GetFakeVMemMask()], &swapped_data, size);
return;
}
@ -454,11 +455,14 @@ TryReadInstResult TryReadInstruction(u32 address)
}
}
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u32 hex;
// TODO: Refactor this. This icache implementation is totally wrong if used with the fake vmem.
if (Memory::m_pFakeVMEM && ((address & 0xFE000000) == 0x7E000000))
if (memory.GetFakeVMEM() && ((address & 0xFE000000) == 0x7E000000))
{
hex = Common::swap32(&Memory::m_pFakeVMEM[address & Memory::GetFakeVMemMask()]);
hex = Common::swap32(&memory.GetFakeVMEM()[address & memory.GetFakeVMemMask()]);
}
else
{
@ -469,7 +473,9 @@ TryReadInstResult TryReadInstruction(u32 address)
u32 HostRead_Instruction(const u32 address)
{
return ReadFromHardware<XCheckTLBFlag::OpcodeNoException, u32>(address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
return ReadFromHardware<XCheckTLBFlag::OpcodeNoException, u32>(memory, address);
}
std::optional<ReadResult<u32>> HostTryReadInstruction(const u32 address,
@ -478,23 +484,27 @@ std::optional<ReadResult<u32>> HostTryReadInstruction(const u32 address,
if (!HostIsInstructionRAMAddress(address, space))
return std::nullopt;
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
switch (space)
{
case RequestedAddressSpace::Effective:
{
const u32 value = ReadFromHardware<XCheckTLBFlag::OpcodeNoException, u32>(address);
const u32 value = ReadFromHardware<XCheckTLBFlag::OpcodeNoException, u32>(memory, address);
return ReadResult<u32>(!!MSR.DR, value);
}
case RequestedAddressSpace::Physical:
{
const u32 value = ReadFromHardware<XCheckTLBFlag::OpcodeNoException, u32, true>(address);
const u32 value =
ReadFromHardware<XCheckTLBFlag::OpcodeNoException, u32, true>(memory, address);
return ReadResult<u32>(false, value);
}
case RequestedAddressSpace::Virtual:
{
if (!MSR.DR)
return std::nullopt;
const u32 value = ReadFromHardware<XCheckTLBFlag::OpcodeNoException, u32>(address);
const u32 value = ReadFromHardware<XCheckTLBFlag::OpcodeNoException, u32>(memory, address);
return ReadResult<u32>(true, value);
}
}
@ -541,28 +551,36 @@ static void Memcheck(u32 address, u64 var, bool write, size_t size)
u8 Read_U8(const u32 address)
{
u8 var = ReadFromHardware<XCheckTLBFlag::Read, u8>(address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u8 var = ReadFromHardware<XCheckTLBFlag::Read, u8>(memory, address);
Memcheck(address, var, false, 1);
return var;
}
u16 Read_U16(const u32 address)
{
u16 var = ReadFromHardware<XCheckTLBFlag::Read, u16>(address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u16 var = ReadFromHardware<XCheckTLBFlag::Read, u16>(memory, address);
Memcheck(address, var, false, 2);
return var;
}
u32 Read_U32(const u32 address)
{
u32 var = ReadFromHardware<XCheckTLBFlag::Read, u32>(address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u32 var = ReadFromHardware<XCheckTLBFlag::Read, u32>(memory, address);
Memcheck(address, var, false, 4);
return var;
}
u64 Read_U64(const u32 address)
{
u64 var = ReadFromHardware<XCheckTLBFlag::Read, u64>(address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u64 var = ReadFromHardware<XCheckTLBFlag::Read, u64>(memory, address);
Memcheck(address, var, false, 8);
return var;
}
@ -587,23 +605,26 @@ static std::optional<ReadResult<T>> HostTryReadUX(const u32 address, RequestedAd
if (!HostIsRAMAddress(address, space))
return std::nullopt;
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
switch (space)
{
case RequestedAddressSpace::Effective:
{
T value = ReadFromHardware<XCheckTLBFlag::NoException, T>(address);
T value = ReadFromHardware<XCheckTLBFlag::NoException, T>(memory, address);
return ReadResult<T>(!!MSR.DR, std::move(value));
}
case RequestedAddressSpace::Physical:
{
T value = ReadFromHardware<XCheckTLBFlag::NoException, T, true>(address);
T value = ReadFromHardware<XCheckTLBFlag::NoException, T, true>(memory, address);
return ReadResult<T>(false, std::move(value));
}
case RequestedAddressSpace::Virtual:
{
if (!MSR.DR)
return std::nullopt;
T value = ReadFromHardware<XCheckTLBFlag::NoException, T>(address);
T value = ReadFromHardware<XCheckTLBFlag::NoException, T>(memory, address);
return ReadResult<T>(true, std::move(value));
}
}
@ -661,13 +682,17 @@ u32 Read_U16_ZX(const u32 address)
void Write_U8(const u32 var, const u32 address)
{
Memcheck(address, var, true, 1);
WriteToHardware<XCheckTLBFlag::Write>(address, var, 1);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
WriteToHardware<XCheckTLBFlag::Write>(memory, address, var, 1);
}
void Write_U16(const u32 var, const u32 address)
{
Memcheck(address, var, true, 2);
WriteToHardware<XCheckTLBFlag::Write>(address, var, 2);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
WriteToHardware<XCheckTLBFlag::Write>(memory, address, var, 2);
}
void Write_U16_Swap(const u32 var, const u32 address)
{
@ -677,7 +702,9 @@ void Write_U16_Swap(const u32 var, const u32 address)
void Write_U32(const u32 var, const u32 address)
{
Memcheck(address, var, true, 4);
WriteToHardware<XCheckTLBFlag::Write>(address, var, 4);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
WriteToHardware<XCheckTLBFlag::Write>(memory, address, var, 4);
}
void Write_U32_Swap(const u32 var, const u32 address)
{
@ -687,8 +714,10 @@ void Write_U32_Swap(const u32 var, const u32 address)
void Write_U64(const u64 var, const u32 address)
{
Memcheck(address, var, true, 8);
WriteToHardware<XCheckTLBFlag::Write>(address, static_cast<u32>(var >> 32), 4);
WriteToHardware<XCheckTLBFlag::Write>(address + sizeof(u32), static_cast<u32>(var), 4);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
WriteToHardware<XCheckTLBFlag::Write>(memory, address, static_cast<u32>(var >> 32), 4);
WriteToHardware<XCheckTLBFlag::Write>(memory, address + sizeof(u32), static_cast<u32>(var), 4);
}
void Write_U64_Swap(const u64 var, const u32 address)
{
@ -704,22 +733,30 @@ void Write_F64(const double var, const u32 address)
u8 HostRead_U8(const u32 address)
{
return ReadFromHardware<XCheckTLBFlag::NoException, u8>(address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
return ReadFromHardware<XCheckTLBFlag::NoException, u8>(memory, address);
}
u16 HostRead_U16(const u32 address)
{
return ReadFromHardware<XCheckTLBFlag::NoException, u16>(address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
return ReadFromHardware<XCheckTLBFlag::NoException, u16>(memory, address);
}
u32 HostRead_U32(const u32 address)
{
return ReadFromHardware<XCheckTLBFlag::NoException, u32>(address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
return ReadFromHardware<XCheckTLBFlag::NoException, u32>(memory, address);
}
u64 HostRead_U64(const u32 address)
{
return ReadFromHardware<XCheckTLBFlag::NoException, u64>(address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
return ReadFromHardware<XCheckTLBFlag::NoException, u64>(memory, address);
}
float HostRead_F32(const u32 address)
@ -738,23 +775,32 @@ double HostRead_F64(const u32 address)
void HostWrite_U8(const u32 var, const u32 address)
{
WriteToHardware<XCheckTLBFlag::NoException>(address, var, 1);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
WriteToHardware<XCheckTLBFlag::NoException>(memory, address, var, 1);
}
void HostWrite_U16(const u32 var, const u32 address)
{
WriteToHardware<XCheckTLBFlag::NoException>(address, var, 2);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
WriteToHardware<XCheckTLBFlag::NoException>(memory, address, var, 2);
}
void HostWrite_U32(const u32 var, const u32 address)
{
WriteToHardware<XCheckTLBFlag::NoException>(address, var, 4);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
WriteToHardware<XCheckTLBFlag::NoException>(memory, address, var, 4);
}
void HostWrite_U64(const u64 var, const u32 address)
{
WriteToHardware<XCheckTLBFlag::NoException>(address, static_cast<u32>(var >> 32), 4);
WriteToHardware<XCheckTLBFlag::NoException>(address + sizeof(u32), static_cast<u32>(var), 4);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
WriteToHardware<XCheckTLBFlag::NoException>(memory, address, static_cast<u32>(var >> 32), 4);
WriteToHardware<XCheckTLBFlag::NoException>(memory, address + sizeof(u32), static_cast<u32>(var),
4);
}
void HostWrite_F32(const float var, const u32 address)
@ -777,18 +823,21 @@ static std::optional<WriteResult> HostTryWriteUX(const u32 var, const u32 addres
if (!HostIsRAMAddress(address, space))
return std::nullopt;
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
switch (space)
{
case RequestedAddressSpace::Effective:
WriteToHardware<XCheckTLBFlag::NoException>(address, var, size);
WriteToHardware<XCheckTLBFlag::NoException>(memory, address, var, size);
return WriteResult(!!MSR.DR);
case RequestedAddressSpace::Physical:
WriteToHardware<XCheckTLBFlag::NoException, true>(address, var, size);
WriteToHardware<XCheckTLBFlag::NoException, true>(memory, address, var, size);
return WriteResult(false);
case RequestedAddressSpace::Virtual:
if (!MSR.DR)
return std::nullopt;
WriteToHardware<XCheckTLBFlag::NoException>(address, var, size);
WriteToHardware<XCheckTLBFlag::NoException>(memory, address, var, size);
return WriteResult(true);
}
@ -893,7 +942,7 @@ bool IsOptimizableRAMAddress(const u32 address)
}
template <XCheckTLBFlag flag>
static bool IsRAMAddress(u32 address, bool translate)
static bool IsRAMAddress(Memory::MemoryManager& memory, u32 address, bool translate)
{
if (translate)
{
@ -904,21 +953,21 @@ static bool IsRAMAddress(u32 address, bool translate)
}
u32 segment = address >> 28;
if (Memory::m_pRAM && segment == 0x0 && (address & 0x0FFFFFFF) < Memory::GetRamSizeReal())
if (memory.GetRAM() && segment == 0x0 && (address & 0x0FFFFFFF) < memory.GetRamSizeReal())
{
return true;
}
else if (Memory::m_pEXRAM && segment == 0x1 &&
(address & 0x0FFFFFFF) < Memory::GetExRamSizeReal())
else if (memory.GetEXRAM() && segment == 0x1 &&
(address & 0x0FFFFFFF) < memory.GetExRamSizeReal())
{
return true;
}
else if (Memory::m_pFakeVMEM && ((address & 0xFE000000) == 0x7E000000))
else if (memory.GetFakeVMEM() && ((address & 0xFE000000) == 0x7E000000))
{
return true;
}
else if (Memory::m_pL1Cache && segment == 0xE &&
(address < (0xE0000000 + Memory::GetL1CacheSize())))
else if (memory.GetL1Cache() && segment == 0xE &&
(address < (0xE0000000 + memory.GetL1CacheSize())))
{
return true;
}
@ -927,16 +976,19 @@ static bool IsRAMAddress(u32 address, bool translate)
bool HostIsRAMAddress(u32 address, RequestedAddressSpace space)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
switch (space)
{
case RequestedAddressSpace::Effective:
return IsRAMAddress<XCheckTLBFlag::NoException>(address, MSR.DR);
return IsRAMAddress<XCheckTLBFlag::NoException>(memory, address, MSR.DR);
case RequestedAddressSpace::Physical:
return IsRAMAddress<XCheckTLBFlag::NoException>(address, false);
return IsRAMAddress<XCheckTLBFlag::NoException>(memory, address, false);
case RequestedAddressSpace::Virtual:
if (!MSR.DR)
return false;
return IsRAMAddress<XCheckTLBFlag::NoException>(address, true);
return IsRAMAddress<XCheckTLBFlag::NoException>(memory, address, true);
}
ASSERT(0);
@ -949,16 +1001,19 @@ bool HostIsInstructionRAMAddress(u32 address, RequestedAddressSpace space)
if (address & 3)
return false;
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
switch (space)
{
case RequestedAddressSpace::Effective:
return IsRAMAddress<XCheckTLBFlag::OpcodeNoException>(address, MSR.IR);
return IsRAMAddress<XCheckTLBFlag::OpcodeNoException>(memory, address, MSR.IR);
case RequestedAddressSpace::Physical:
return IsRAMAddress<XCheckTLBFlag::OpcodeNoException>(address, false);
return IsRAMAddress<XCheckTLBFlag::OpcodeNoException>(memory, address, false);
case RequestedAddressSpace::Virtual:
if (!MSR.IR)
return false;
return IsRAMAddress<XCheckTLBFlag::OpcodeNoException>(address, true);
return IsRAMAddress<XCheckTLBFlag::OpcodeNoException>(memory, address, true);
}
ASSERT(0);
@ -967,6 +1022,9 @@ bool HostIsInstructionRAMAddress(u32 address, RequestedAddressSpace space)
void DMA_LCToMemory(const u32 mem_address, const u32 cache_address, const u32 num_blocks)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// TODO: It's not completely clear this is the right spot for this code;
// what would happen if, for example, the DVD drive tried to write to the EFB?
// TODO: This is terribly slow.
@ -976,7 +1034,7 @@ void DMA_LCToMemory(const u32 mem_address, const u32 cache_address, const u32 nu
{
for (u32 i = 0; i < 32 * num_blocks; i += 4)
{
const u32 data = Common::swap32(Memory::m_pL1Cache + ((cache_address + i) & 0x3FFFF));
const u32 data = Common::swap32(memory.GetL1Cache() + ((cache_address + i) & 0x3FFFF));
EFB_Write(data, mem_address + i);
}
return;
@ -988,14 +1046,14 @@ void DMA_LCToMemory(const u32 mem_address, const u32 cache_address, const u32 nu
{
for (u32 i = 0; i < 32 * num_blocks; i += 4)
{
const u32 data = Common::swap32(Memory::m_pL1Cache + ((cache_address + i) & 0x3FFFF));
Memory::mmio_mapping->Write(mem_address + i, data);
const u32 data = Common::swap32(memory.GetL1Cache() + ((cache_address + i) & 0x3FFFF));
memory.GetMMIOMapping()->Write(mem_address + i, data);
}
return;
}
const u8* src = Memory::m_pL1Cache + (cache_address & 0x3FFFF);
u8* dst = Memory::GetPointer(mem_address);
const u8* src = memory.GetL1Cache() + (cache_address & 0x3FFFF);
u8* dst = memory.GetPointer(mem_address);
if (dst == nullptr)
return;
@ -1004,8 +1062,11 @@ void DMA_LCToMemory(const u32 mem_address, const u32 cache_address, const u32 nu
void DMA_MemoryToLC(const u32 cache_address, const u32 mem_address, const u32 num_blocks)
{
const u8* src = Memory::GetPointer(mem_address);
u8* dst = Memory::m_pL1Cache + (cache_address & 0x3FFFF);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u8* src = memory.GetPointer(mem_address);
u8* dst = memory.GetL1Cache() + (cache_address & 0x3FFFF);
// No known game uses this; here for completeness.
// TODO: Refactor.
@ -1014,7 +1075,7 @@ void DMA_MemoryToLC(const u32 cache_address, const u32 mem_address, const u32 nu
for (u32 i = 0; i < 32 * num_blocks; i += 4)
{
const u32 data = Common::swap32(EFB_Read(mem_address + i));
std::memcpy(Memory::m_pL1Cache + ((cache_address + i) & 0x3FFFF), &data, sizeof(u32));
std::memcpy(memory.GetL1Cache() + ((cache_address + i) & 0x3FFFF), &data, sizeof(u32));
}
return;
}
@ -1025,8 +1086,8 @@ void DMA_MemoryToLC(const u32 cache_address, const u32 mem_address, const u32 nu
{
for (u32 i = 0; i < 32 * num_blocks; i += 4)
{
const u32 data = Common::swap32(Memory::mmio_mapping->Read<u32>(mem_address + i));
std::memcpy(Memory::m_pL1Cache + ((cache_address + i) & 0x3FFFF), &data, sizeof(u32));
const u32 data = Common::swap32(memory.GetMMIOMapping()->Read<u32>(mem_address + i));
std::memcpy(memory.GetL1Cache() + ((cache_address + i) & 0x3FFFF), &data, sizeof(u32));
}
return;
}
@ -1059,10 +1120,13 @@ void ClearCacheLine(u32 address)
address = translated_address.address;
}
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// TODO: This isn't precisely correct for non-RAM regions, but the difference
// is unlikely to matter.
for (u32 i = 0; i < 32; i += 4)
WriteToHardware<XCheckTLBFlag::Write, true>(address + i, 0, 4);
WriteToHardware<XCheckTLBFlag::Write, true>(memory, address + i, 0, 4);
}
u32 IsOptimizableMMIOAccess(u32 address, u32 access_size)
@ -1346,6 +1410,9 @@ static TranslateAddressResult TranslatePageAddress(const EffectiveAddress addres
pte1.API = api;
pte1.V = 1;
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
for (int hash_func = 0; hash_func < 2; hash_func++)
{
// hash function no 2 "not" .360
@ -1360,11 +1427,11 @@ static TranslateAddressResult TranslatePageAddress(const EffectiveAddress addres
for (int i = 0; i < 8; i++, pteg_addr += 8)
{
const u32 pteg = Memory::Read_U32(pteg_addr);
const u32 pteg = memory.Read_U32(pteg_addr);
if (pte1.Hex == pteg)
{
UPTE_Hi pte2(Memory::Read_U32(pteg_addr + 4));
UPTE_Hi pte2(memory.Read_U32(pteg_addr + 4));
// set the access bits
switch (flag)
@ -1386,7 +1453,7 @@ static TranslateAddressResult TranslatePageAddress(const EffectiveAddress addres
if (!IsNoExceptionFlag(flag))
{
Memory::Write_U32(pte2.Hex, pteg_addr + 4);
memory.Write_U32(pte2.Hex, pteg_addr + 4);
}
// We already updated the TLB entry if this was caused by a C bit.
@ -1405,6 +1472,9 @@ static TranslateAddressResult TranslatePageAddress(const EffectiveAddress addres
static void UpdateBATs(BatTable& bat_table, u32 base_spr)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// TODO: Separate BATs for MSR.PR==0 and MSR.PR==1
// TODO: Handle PP settings.
// TODO: Check how hardware reacts to overlapping BATs (including
@ -1464,21 +1534,21 @@ static void UpdateBATs(BatTable& bat_table, u32 base_spr)
// that fastmem doesn't emulate properly (though no normal games are known to rely on them).
if (!wi)
{
if (Memory::m_pFakeVMEM && (physical_address & 0xFE000000) == 0x7E000000)
if (memory.GetFakeVMEM() && (physical_address & 0xFE000000) == 0x7E000000)
{
valid_bit |= BAT_PHYSICAL_BIT;
}
else if (physical_address < Memory::GetRamSizeReal())
else if (physical_address < memory.GetRamSizeReal())
{
valid_bit |= BAT_PHYSICAL_BIT;
}
else if (Memory::m_pEXRAM && physical_address >> 28 == 0x1 &&
(physical_address & 0x0FFFFFFF) < Memory::GetExRamSizeReal())
else if (memory.GetEXRAM() && physical_address >> 28 == 0x1 &&
(physical_address & 0x0FFFFFFF) < memory.GetExRamSizeReal())
{
valid_bit |= BAT_PHYSICAL_BIT;
}
else if (physical_address >> 28 == 0xE &&
physical_address < 0xE0000000 + Memory::GetL1CacheSize())
physical_address < 0xE0000000 + memory.GetL1CacheSize())
{
valid_bit |= BAT_PHYSICAL_BIT;
}
@ -1497,12 +1567,15 @@ static void UpdateBATs(BatTable& bat_table, u32 base_spr)
static void UpdateFakeMMUBat(BatTable& bat_table, u32 start_addr)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
for (u32 i = 0; i < (0x10000000 >> BAT_INDEX_SHIFT); ++i)
{
// Map from 0x4XXXXXXX or 0x7XXXXXXX to the range
// [0x7E000000,0x80000000).
u32 e_address = i + (start_addr >> BAT_INDEX_SHIFT);
u32 p_address = 0x7E000000 | (i << BAT_INDEX_SHIFT & Memory::GetFakeVMemMask());
u32 p_address = 0x7E000000 | (i << BAT_INDEX_SHIFT & memory.GetFakeVMemMask());
u32 flags = BAT_MAPPED_BIT | BAT_PHYSICAL_BIT;
if (PowerPC::memchecks.OverlapsMemcheck(e_address << BAT_INDEX_SHIFT, BAT_PAGE_SIZE))
@ -1514,12 +1587,15 @@ static void UpdateFakeMMUBat(BatTable& bat_table, u32 start_addr)
void DBATUpdated()
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
dbat_table = {};
UpdateBATs(dbat_table, SPR_DBAT0U);
bool extended_bats = SConfig::GetInstance().bWii && HID4.SBE;
if (extended_bats)
UpdateBATs(dbat_table, SPR_DBAT4U);
if (Memory::m_pFakeVMEM)
if (memory.GetFakeVMEM())
{
// In Fake-MMU mode, insert some extra entries into the BAT tables.
UpdateFakeMMUBat(dbat_table, 0x40000000);
@ -1527,7 +1603,7 @@ void DBATUpdated()
}
#ifndef _ARCH_32
Memory::UpdateLogicalMemory(dbat_table);
memory.UpdateLogicalMemory(dbat_table);
#endif
// IsOptimizable*Address and dcbz depends on the BAT mapping, so we need a flush here.
@ -1536,12 +1612,15 @@ void DBATUpdated()
void IBATUpdated()
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
ibat_table = {};
UpdateBATs(ibat_table, SPR_IBAT0U);
bool extended_bats = SConfig::GetInstance().bWii && HID4.SBE;
if (extended_bats)
UpdateBATs(ibat_table, SPR_IBAT4U);
if (Memory::m_pFakeVMEM)
if (memory.GetFakeVMEM())
{
// In Fake-MMU mode, insert some extra entries into the BAT tables.
UpdateFakeMMUBat(ibat_table, 0x40000000);

View file

@ -12,6 +12,7 @@
#include "Core/HW/Memmap.h"
#include "Core/PowerPC/JitInterface.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/System.h"
namespace PowerPC
{
@ -139,8 +140,11 @@ void InstructionCache::Invalidate(u32 addr)
u32 InstructionCache::ReadInstruction(u32 addr)
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
if (!HID0.ICE || m_disable_icache) // instruction cache is disabled
return Memory::Read_U32(addr);
return memory.Read_U32(addr);
u32 set = (addr >> 5) & 0x7f;
u32 tag = addr >> 12;
@ -161,14 +165,14 @@ u32 InstructionCache::ReadInstruction(u32 addr)
if (t == 0xff) // load to the cache
{
if (HID0.ILOCK) // instruction cache is locked
return Memory::Read_U32(addr);
return memory.Read_U32(addr);
// select a way
if (valid[set] != 0xff)
t = s_way_from_valid[valid[set]];
else
t = s_way_from_plru[plru[set]];
// load
Memory::CopyFromEmu(reinterpret_cast<u8*>(data[set][t].data()), (addr & ~0x1f), 32);
memory.CopyFromEmu(reinterpret_cast<u8*>(data[set][t].data()), (addr & ~0x1f), 32);
if (valid[set] & (1 << t))
{
if (tags[set][t] & (ICACHE_VMEM_BIT >> 12))
@ -191,7 +195,7 @@ u32 InstructionCache::ReadInstruction(u32 addr)
// update plru
plru[set] = (plru[set] & ~s_plru_mask[t]) | s_plru_value[t];
const u32 res = Common::swap32(data[set][t][(addr >> 2) & 7]);
const u32 inmem = Memory::Read_U32(addr);
const u32 inmem = memory.Read_U32(addr);
if (res != inmem)
{
INFO_LOG_FMT(POWERPC,

View file

@ -194,17 +194,19 @@ static void DoState(PointerWrap& p)
}
// Check to make sure the emulated memory sizes are the same as the savestate
u32 state_mem1_size = Memory::GetRamSizeReal();
u32 state_mem2_size = Memory::GetExRamSizeReal();
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u32 state_mem1_size = memory.GetRamSizeReal();
u32 state_mem2_size = memory.GetExRamSizeReal();
p.Do(state_mem1_size);
p.Do(state_mem2_size);
if (state_mem1_size != Memory::GetRamSizeReal() || state_mem2_size != Memory::GetExRamSizeReal())
if (state_mem1_size != memory.GetRamSizeReal() || state_mem2_size != memory.GetExRamSizeReal())
{
OSD::AddMessage(fmt::format("Memory size mismatch!\n"
"Current | MEM1 {:08X} ({:3}MB) MEM2 {:08X} ({:3}MB)\n"
"State | MEM1 {:08X} ({:3}MB) MEM2 {:08X} ({:3}MB)",
Memory::GetRamSizeReal(), Memory::GetRamSizeReal() / 0x100000U,
Memory::GetExRamSizeReal(), Memory::GetExRamSizeReal() / 0x100000U,
memory.GetRamSizeReal(), memory.GetRamSizeReal() / 0x100000U,
memory.GetExRamSizeReal(), memory.GetExRamSizeReal() / 0x100000U,
state_mem1_size, state_mem1_size / 0x100000U, state_mem2_size,
state_mem2_size / 0x100000U));
p.SetMeasureMode();
@ -225,7 +227,7 @@ static void DoState(PointerWrap& p)
p.DoMarker("PowerPC");
// CoreTiming needs to be restored before restoring Hardware because
// the controller code might need to schedule an event if the controller has changed.
Core::System::GetInstance().GetCoreTiming().DoState(p);
system.GetCoreTiming().DoState(p);
p.DoMarker("CoreTiming");
HW::DoState(p);
p.DoMarker("HW");

View file

@ -13,6 +13,7 @@
#include "Core/HW/DVD/DVDInterface.h"
#include "Core/HW/DVD/DVDThread.h"
#include "Core/HW/EXI/EXI.h"
#include "Core/HW/Memmap.h"
#include "Core/HW/MemoryInterface.h"
#include "Core/HW/SI/SI.h"
#include "Core/HW/Sram.h"
@ -34,6 +35,7 @@ struct System::Impl
DVDInterface::DVDInterfaceState m_dvd_interface_state;
DVDThread::DVDThreadState m_dvd_thread_state;
ExpansionInterface::ExpansionInterfaceState m_expansion_interface_state;
Memory::MemoryManager m_memory;
MemoryInterface::MemoryInterfaceState m_memory_interface_state;
SerialInterface::SerialInterfaceState m_serial_interface_state;
Sram m_sram;
@ -118,6 +120,11 @@ ExpansionInterface::ExpansionInterfaceState& System::GetExpansionInterfaceState(
return m_impl->m_expansion_interface_state;
}
Memory::MemoryManager& System::GetMemory() const
{
return m_impl->m_memory;
}
MemoryInterface::MemoryInterfaceState& System::GetMemoryInterfaceState() const
{
return m_impl->m_memory_interface_state;

View file

@ -36,6 +36,10 @@ namespace ExpansionInterface
{
class ExpansionInterfaceState;
};
namespace Memory
{
class MemoryManager;
};
namespace MemoryInterface
{
class MemoryInterfaceState;
@ -90,6 +94,7 @@ public:
DVDInterface::DVDInterfaceState& GetDVDInterfaceState() const;
DVDThread::DVDThreadState& GetDVDThreadState() const;
ExpansionInterface::ExpansionInterfaceState& GetExpansionInterfaceState() const;
Memory::MemoryManager& GetMemory() const;
MemoryInterface::MemoryInterfaceState& GetMemoryInterfaceState() const;
SerialInterface::SerialInterfaceState& GetSerialInterfaceState() const;
Sram& GetSRAM() const;

View file

@ -18,6 +18,7 @@
#include "Core/HW/Memmap.h"
#include "Core/IOS/FS/FileSystem.h"
#include "Core/PowerPC/MMU.h"
#include "Core/System.h"
#include "DiscIO/DirectoryBlob.h"
#include "DiscIO/RiivolutionParser.h"
@ -582,6 +583,9 @@ static void ApplyOcarinaMemoryPatch(const Patch& patch, const Memory& memory_pat
void ApplyGeneralMemoryPatches(const std::vector<Patch>& patches)
{
auto& system = Core::System::GetInstance();
auto& system_memory = system.GetMemory();
for (const auto& patch : patches)
{
for (const auto& memory : patch.m_memory_patches)
@ -590,7 +594,7 @@ void ApplyGeneralMemoryPatches(const std::vector<Patch>& patches)
continue;
if (memory.m_search)
ApplySearchMemoryPatch(patch, memory, 0x80000000, ::Memory::GetRamSize());
ApplySearchMemoryPatch(patch, memory, 0x80000000, system_memory.GetRamSize());
else
ApplyMemoryPatch(patch, memory);
}

View file

@ -23,6 +23,7 @@
#include "Core/Core.h"
#include "Core/HW/Memmap.h"
#include "Core/PowerPC/MMU.h"
#include "Core/System.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
@ -164,9 +165,11 @@ void CheatSearchFactoryWidget::OnNewSearchClicked()
return;
}
memory_ranges.emplace_back(0x80000000, Memory::GetRamSizeReal());
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory_ranges.emplace_back(0x80000000, memory.GetRamSizeReal());
if (SConfig::GetInstance().bWii)
memory_ranges.emplace_back(0x90000000, Memory::GetExRamSizeReal());
memory_ranges.emplace_back(0x90000000, memory.GetExRamSizeReal());
address_space = PowerPC::RequestedAddressSpace::Virtual;
}
else

View file

@ -43,6 +43,7 @@
#include "Core/PowerPC/PowerPC.h"
#include "Core/PowerPC/SignatureDB/SignatureDB.h"
#include "Core/State.h"
#include "Core/System.h"
#include "Core/TitleDatabase.h"
#include "Core/WiiUtils.h"
@ -1194,15 +1195,21 @@ void MenuBar::ClearSymbols()
void MenuBar::GenerateSymbolsFromAddress()
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
PPCAnalyst::FindFunctions(Memory::MEM1_BASE_ADDR,
Memory::MEM1_BASE_ADDR + Memory::GetRamSizeReal(), &g_symbolDB);
Memory::MEM1_BASE_ADDR + memory.GetRamSizeReal(), &g_symbolDB);
emit NotifySymbolsUpdated();
}
void MenuBar::GenerateSymbolsFromSignatureDB()
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
PPCAnalyst::FindFunctions(Memory::MEM1_BASE_ADDR,
Memory::MEM1_BASE_ADDR + Memory::GetRamSizeReal(), &g_symbolDB);
Memory::MEM1_BASE_ADDR + memory.GetRamSizeReal(), &g_symbolDB);
SignatureDB db(SignatureDB::HandlerType::DSY);
if (db.Load(File::GetSysDirectory() + TOTALDB))
{
@ -1409,6 +1416,9 @@ RSOVector MenuBar::DetectRSOModules(ParallelProgressDialog& progress)
void MenuBar::LoadSymbolMap()
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
std::string existing_map_file, writable_map_file;
bool map_exists = CBoot::FindMapFile(&existing_map_file, &writable_map_file);
@ -1416,7 +1426,7 @@ void MenuBar::LoadSymbolMap()
{
g_symbolDB.Clear();
PPCAnalyst::FindFunctions(Memory::MEM1_BASE_ADDR + 0x1300000,
Memory::MEM1_BASE_ADDR + Memory::GetRamSizeReal(), &g_symbolDB);
Memory::MEM1_BASE_ADDR + memory.GetRamSizeReal(), &g_symbolDB);
SignatureDB db(SignatureDB::HandlerType::DSY);
if (db.Load(File::GetSysDirectory() + TOTALDB))
db.Apply(&g_symbolDB);
@ -1657,8 +1667,11 @@ void MenuBar::SearchInstruction()
if (!good)
return;
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
bool found = false;
for (u32 addr = Memory::MEM1_BASE_ADDR; addr < Memory::MEM1_BASE_ADDR + Memory::GetRamSizeReal();
for (u32 addr = Memory::MEM1_BASE_ADDR; addr < Memory::MEM1_BASE_ADDR + memory.GetRamSizeReal();
addr += 4)
{
const auto ins_name =

View file

@ -9,6 +9,7 @@
#include "Common/CommonTypes.h"
#include "Common/MsgHandler.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"
#include "VideoCommon/BPMemory.h"
#include "VideoCommon/TextureDecoder.h"
@ -132,8 +133,11 @@ void SampleMip(s32 s, s32 t, s32 mip, bool linear, u8 texmap, u8* sample)
}
else
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u32 imageBase = texUnit.texImage3.image_base << 5;
imageSrc = Memory::GetPointer(imageBase);
imageSrc = memory.GetPointer(imageBase);
}
int image_width_minus_1 = ti0.width;

View file

@ -357,7 +357,9 @@ static void BPWritten(const BPCmd& bp, int cycles_into_future)
if (!SConfig::GetInstance().bWii)
addr = addr & 0x01FFFFFF;
Memory::CopyFromEmu(texMem + tlutTMemAddr, addr, tlutXferCount);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyFromEmu(texMem + tlutTMemAddr, addr, tlutXferCount);
if (OpcodeDecoder::g_record_fifo_data)
FifoRecorder::GetInstance().UseMemory(addr, tlutXferCount, MemoryUpdate::TMEM);
@ -549,11 +551,15 @@ static void BPWritten(const BPCmd& bp, int cycles_into_future)
if (tmem_addr_even + bytes_read > TMEM_SIZE)
bytes_read = TMEM_SIZE - tmem_addr_even;
Memory::CopyFromEmu(texMem + tmem_addr_even, src_addr, bytes_read);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyFromEmu(texMem + tmem_addr_even, src_addr, bytes_read);
}
else // RGBA8 tiles (and CI14, but that might just be stupid libogc!)
{
u8* src_ptr = Memory::GetPointer(src_addr);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u8* src_ptr = memory.GetPointer(src_addr);
// AR and GB tiles are stored in separate TMEM banks => can't use a single memcpy for
// everything

View file

@ -270,7 +270,9 @@ static void ReadDataFromFifo(u32 readPtr)
s_video_buffer_read_ptr = s_video_buffer;
}
// Copy new video instructions to s_video_buffer for future use in rendering the new picture
Memory::CopyFromEmu(s_video_buffer_write_ptr, readPtr, GPFifo::GATHER_PIPE_SIZE);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyFromEmu(s_video_buffer_write_ptr, readPtr, GPFifo::GATHER_PIPE_SIZE);
s_video_buffer_write_ptr += GPFifo::GATHER_PIPE_SIZE;
}
@ -303,7 +305,9 @@ static void ReadDataFromFifoOnCPU(u32 readPtr)
return;
}
}
Memory::CopyFromEmu(s_video_buffer_write_ptr, readPtr, GPFifo::GATHER_PIPE_SIZE);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
memory.CopyFromEmu(s_video_buffer_write_ptr, readPtr, GPFifo::GATHER_PIPE_SIZE);
s_video_buffer_pp_read_ptr = OpcodeDecoder::RunFifo<true>(
DataReader(s_video_buffer_pp_read_ptr, write_ptr + GPFifo::GATHER_PIPE_SIZE), nullptr);
// This would have to be locked if the GPU thread didn't spin.

View file

@ -153,7 +153,9 @@ public:
if constexpr (is_preprocess)
{
const u8* const start_address = Memory::GetPointer(address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u8* const start_address = memory.GetPointer(address);
Fifo::PushFifoAuxBuffer(start_address, size);
@ -167,11 +169,17 @@ public:
const u8* start_address;
if (Fifo::UseDeterministicGPUThread())
{
start_address = static_cast<u8*>(Fifo::PopFifoAuxBuffer(size));
}
else
start_address = Memory::GetPointer(address);
{
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
start_address = memory.GetPointer(address);
}
// Avoid the crash if Memory::GetPointer failed ..
// Avoid the crash if memory.GetPointer failed ..
if (start_address != nullptr)
{
// temporarily swap dl and non-dl (small "hack" for the stats)

View file

@ -31,6 +31,7 @@
#include "Core/FifoPlayer/FifoPlayer.h"
#include "Core/FifoPlayer/FifoRecorder.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"
#include "VideoCommon/AbstractFramebuffer.h"
#include "VideoCommon/AbstractStagingTexture.h"
@ -1732,7 +1733,9 @@ TextureCacheBase::TCacheEntry*
TextureCacheBase::GetXFBTexture(u32 address, u32 width, u32 height, u32 stride,
MathUtil::Rectangle<int>* display_rect)
{
const u8* src_data = Memory::GetPointer(address);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u8* src_data = memory.GetPointer(address);
if (!src_data)
{
ERROR_LOG_FMT(VIDEO, "Trying to load XFB texture from invalid address {:#010x}", address);
@ -2107,7 +2110,9 @@ void TextureCacheBase::CopyRenderTargetToTexture(
!(is_xfb_copy ? g_ActiveConfig.bSkipXFBCopyToRam : g_ActiveConfig.bSkipEFBCopyToRam) ||
!copy_to_vram;
u8* dst = Memory::GetPointer(dstAddr);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u8* dst = memory.GetPointer(dstAddr);
if (dst == nullptr)
{
ERROR_LOG_FMT(VIDEO, "Trying to copy from EFB to invalid address {:#010x}", dstAddr);
@ -2422,7 +2427,9 @@ void TextureCacheBase::WriteEFBCopyToRAM(u8* dst_ptr, u32 width, u32 height, u32
void TextureCacheBase::FlushEFBCopy(TCacheEntry* entry)
{
// Copy from texture -> guest memory.
u8* const dst = Memory::GetPointer(entry->addr);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u8* const dst = memory.GetPointer(entry->addr);
WriteEFBCopyToRAM(dst, entry->pending_efb_copy_width, entry->pending_efb_copy_height,
entry->memory_stride, std::move(entry->pending_efb_copy));
@ -3024,7 +3031,9 @@ u64 TextureCacheBase::TCacheEntry::CalculateHash() const
const u32 hash_sample_size = HashSampleSize();
// FIXME: textures from tmem won't get the correct hash.
u8* ptr = Memory::GetPointer(addr);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
u8* ptr = memory.GetPointer(addr);
if (memory_stride == bytes_per_row)
{
return Common::GetHash64(ptr, size_in_bytes, hash_sample_size);

View file

@ -8,6 +8,7 @@
#include "Common/Align.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"
#include "VideoCommon/BPMemory.h"
#include "VideoCommon/TextureDecoder.h"
@ -44,7 +45,9 @@ TextureInfo TextureInfo::FromStage(u32 stage)
&texMem[tmem_address_even], mip_count);
}
return TextureInfo(stage, Memory::GetPointer(address), tlut_ptr, address, texture_format,
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
return TextureInfo(stage, memory.GetPointer(address), tlut_ptr, address, texture_format,
tlut_format, width, height, false, nullptr, nullptr, mip_count);
}

View file

@ -18,6 +18,7 @@
#include "Core/DolphinAnalytics.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"
#include "VideoCommon/BPMemory.h"
#include "VideoCommon/CPMemory.h"
@ -81,6 +82,9 @@ void UpdateVertexArrayPointers()
if (!g_bases_dirty) [[likely]]
return;
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
// Some games such as Burnout 2 can put invalid addresses into
// the array base registers. (see issue 8591)
// But the vertex arrays with invalid addresses aren't actually enabled.
@ -89,24 +93,24 @@ void UpdateVertexArrayPointers()
// We also only update the array base if the vertex description states we are going to use it.
if (IsIndexed(g_main_cp_state.vtx_desc.low.Position))
cached_arraybases[CPArray::Position] =
Memory::GetPointer(g_main_cp_state.array_bases[CPArray::Position]);
memory.GetPointer(g_main_cp_state.array_bases[CPArray::Position]);
if (IsIndexed(g_main_cp_state.vtx_desc.low.Normal))
cached_arraybases[CPArray::Normal] =
Memory::GetPointer(g_main_cp_state.array_bases[CPArray::Normal]);
memory.GetPointer(g_main_cp_state.array_bases[CPArray::Normal]);
for (u8 i = 0; i < g_main_cp_state.vtx_desc.low.Color.Size(); i++)
{
if (IsIndexed(g_main_cp_state.vtx_desc.low.Color[i]))
cached_arraybases[CPArray::Color0 + i] =
Memory::GetPointer(g_main_cp_state.array_bases[CPArray::Color0 + i]);
memory.GetPointer(g_main_cp_state.array_bases[CPArray::Color0 + i]);
}
for (u8 i = 0; i < g_main_cp_state.vtx_desc.high.TexCoord.Size(); i++)
{
if (IsIndexed(g_main_cp_state.vtx_desc.high.TexCoord[i]))
cached_arraybases[CPArray::TexCoord0 + i] =
Memory::GetPointer(g_main_cp_state.array_bases[CPArray::TexCoord0 + i]);
memory.GetPointer(g_main_cp_state.array_bases[CPArray::TexCoord0 + i]);
}
g_bases_dirty = false;

View file

@ -10,6 +10,7 @@
#include "Core/DolphinAnalytics.h"
#include "Core/HW/Memmap.h"
#include "Core/System.h"
#include "VideoCommon/CPMemory.h"
#include "VideoCommon/Fifo.h"
@ -262,8 +263,10 @@ void LoadIndexedXF(CPArray array, u32 index, u16 address, u8 size)
}
else
{
newData = (u32*)Memory::GetPointer(g_main_cp_state.array_bases[array] +
g_main_cp_state.array_strides[array] * index);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
newData = (u32*)memory.GetPointer(g_main_cp_state.array_bases[array] +
g_main_cp_state.array_strides[array] * index);
}
bool changed = false;
for (u32 i = 0; i < size; ++i)
@ -284,8 +287,10 @@ void LoadIndexedXF(CPArray array, u32 index, u16 address, u8 size)
void PreprocessIndexedXF(CPArray array, u32 index, u16 address, u8 size)
{
const u8* new_data = Memory::GetPointer(g_preprocess_cp_state.array_bases[array] +
g_preprocess_cp_state.array_strides[array] * index);
auto& system = Core::System::GetInstance();
auto& memory = system.GetMemory();
const u8* new_data = memory.GetPointer(g_preprocess_cp_state.array_bases[array] +
g_preprocess_cp_state.array_strides[array] * index);
const size_t buf_size = size * sizeof(u32);
Fifo::PushFifoAuxBuffer(new_data, buf_size);