Merge pull request #11320 from AdmiralCurtiss/globals-memory
HW/Memmap: Refactor Memory to class, move to Core::System.
This commit is contained in:
commit
94faad0d37
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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(),
|
||||
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(),
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
#include "VideoCommon/OpcodeDecoding.h"
|
||||
#include "VideoCommon/XFStructs.h"
|
||||
|
@ -229,8 +230,10 @@ void FifoRecorder::StartRecording(s32 numFrames, CallbackFunc finishedCb)
|
|||
// - Global variables suck
|
||||
// - Multithreading with the above two sucks
|
||||
//
|
||||
m_Ram.resize(Memory::GetRamSize());
|
||||
m_ExRam.resize(Memory::GetExRamSize());
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
m_Ram.resize(memory.GetRamSize());
|
||||
m_ExRam.resize(memory.GetExRamSize());
|
||||
|
||||
std::fill(m_Ram.begin(), m_Ram.end(), 0);
|
||||
std::fill(m_ExRam.begin(), m_ExRam.end(), 0);
|
||||
|
@ -310,17 +313,20 @@ void FifoRecorder::WriteGPCommand(const u8* data, u32 size)
|
|||
|
||||
void FifoRecorder::UseMemory(u32 address, u32 size, MemoryUpdate::Type type, bool dynamicUpdate)
|
||||
{
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
u8* curData;
|
||||
u8* newData;
|
||||
if (address & 0x10000000)
|
||||
{
|
||||
curData = &m_ExRam[address & Memory::GetExRamMask()];
|
||||
newData = &Memory::m_pEXRAM[address & Memory::GetExRamMask()];
|
||||
curData = &m_ExRam[address & memory.GetExRamMask()];
|
||||
newData = &memory.GetEXRAM()[address & memory.GetExRamMask()];
|
||||
}
|
||||
else
|
||||
{
|
||||
curData = &m_Ram[address & Memory::GetRamMask()];
|
||||
newData = &Memory::m_pRAM[address & Memory::GetRamMask()];
|
||||
curData = &m_Ram[address & memory.GetRamMask()];
|
||||
newData = &memory.GetRAM()[address & memory.GetRamMask()];
|
||||
}
|
||||
|
||||
if (!dynamicUpdate && memcmp(curData, newData, size) != 0)
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "Core/IOS/ES/ES.h"
|
||||
#include "Core/PowerPC/PPCSymbolDB.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
namespace HLE
|
||||
{
|
||||
|
@ -90,7 +91,9 @@ void PatchFixedFunctions()
|
|||
if (!Config::Get(Config::MAIN_ENABLE_CHEATS))
|
||||
{
|
||||
Patch(0x80001800, "HBReload");
|
||||
Memory::CopyToEmu(0x00001804, "STUBHAXX", 8);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
memory.CopyToEmu(0x00001804, "STUBHAXX", 8);
|
||||
}
|
||||
|
||||
// Not part of the binary itself, but either we or Gecko OS might insert
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "Core/HW/DSP.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/PowerPC/MMU.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
namespace AddressSpace
|
||||
{
|
||||
|
@ -92,6 +93,9 @@ struct EffectiveAddressSpaceAccessors : Accessors
|
|||
|
||||
bool Matches(u32 haystack_start, const u8* needle_start, std::size_t needle_size) const
|
||||
{
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
u32 page_base = haystack_start & 0xfffff000;
|
||||
u32 offset = haystack_start & 0x0000fff;
|
||||
do
|
||||
|
@ -114,7 +118,7 @@ struct EffectiveAddressSpaceAccessors : Accessors
|
|||
return false;
|
||||
}
|
||||
|
||||
u8* page_ptr = Memory::GetPointer(*page_physical_address);
|
||||
u8* page_ptr = memory.GetPointer(*page_physical_address);
|
||||
if (page_ptr == nullptr)
|
||||
{
|
||||
return false;
|
||||
|
@ -417,9 +421,12 @@ Accessors* GetAccessors(Type address_space)
|
|||
|
||||
void Init()
|
||||
{
|
||||
s_mem1_address_space_accessors = {&Memory::m_pRAM, Memory::GetRamSizeReal()};
|
||||
s_mem2_address_space_accessors = {&Memory::m_pEXRAM, Memory::GetExRamSizeReal()};
|
||||
s_fake_address_space_accessors = {&Memory::m_pFakeVMEM, Memory::GetFakeVMemSize()};
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
s_mem1_address_space_accessors = {&memory.GetRAM(), memory.GetRamSizeReal()};
|
||||
s_mem2_address_space_accessors = {&memory.GetEXRAM(), memory.GetExRamSizeReal()};
|
||||
s_fake_address_space_accessors = {&memory.GetFakeVMEM(), memory.GetFakeVMemSize()};
|
||||
s_physical_address_space_accessors_gcn = {{0x00000000, &s_mem1_address_space_accessors}};
|
||||
s_physical_address_space_accessors_wii = {{0x00000000, &s_mem1_address_space_accessors},
|
||||
{0x10000000, &s_mem2_address_space_accessors}};
|
||||
|
|
|
@ -205,16 +205,18 @@ void Init(bool hle)
|
|||
|
||||
void Reinit(bool hle)
|
||||
{
|
||||
auto& state = Core::System::GetInstance().GetDSPState().GetData();
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& state = system.GetDSPState().GetData();
|
||||
state.dsp_emulator = CreateDSPEmulator(hle);
|
||||
state.is_lle = state.dsp_emulator->IsLLE();
|
||||
|
||||
if (SConfig::GetInstance().bWii)
|
||||
{
|
||||
auto& memory = system.GetMemory();
|
||||
state.aram.wii_mode = true;
|
||||
state.aram.size = Memory::GetExRamSizeReal();
|
||||
state.aram.mask = Memory::GetExRamMask();
|
||||
state.aram.ptr = Memory::m_pEXRAM;
|
||||
state.aram.size = memory.GetExRamSizeReal();
|
||||
state.aram.mask = memory.GetExRamMask();
|
||||
state.aram.ptr = memory.GetEXRAM();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -527,7 +529,8 @@ void UpdateAudioDMA()
|
|||
// Read audio at g_audioDMA.current_source_address in RAM and push onto an
|
||||
// external audio fifo in the emulator, to be mixed with the disc
|
||||
// streaming output.
|
||||
void* address = Memory::GetPointer(state.audio_dma.current_source_address);
|
||||
auto& memory = system.GetMemory();
|
||||
void* address = memory.GetPointer(state.audio_dma.current_source_address);
|
||||
AudioCommon::SendAIBuffer(system, reinterpret_cast<short*>(address), 8);
|
||||
|
||||
if (state.audio_dma.remaining_blocks_count != 0)
|
||||
|
@ -554,6 +557,7 @@ static void Do_ARAM_DMA()
|
|||
{
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& core_timing = system.GetCoreTiming();
|
||||
auto& memory = system.GetMemory();
|
||||
auto& state = system.GetDSPState().GetData();
|
||||
|
||||
state.dsp_control.DMAState = 1;
|
||||
|
@ -581,17 +585,17 @@ 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],
|
||||
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],
|
||||
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],
|
||||
memory.Write_U64_Swap(*(u64*)&state.aram.ptr[state.aram_dma.ARAddr & state.aram.mask],
|
||||
state.aram_dma.MMAddr);
|
||||
}
|
||||
|
||||
|
@ -604,7 +608,7 @@ static void Do_ARAM_DMA()
|
|||
{
|
||||
while (state.aram_dma.Cnt.count)
|
||||
{
|
||||
Memory::Write_U64(HSP::Read(state.aram_dma.ARAddr), state.aram_dma.MMAddr);
|
||||
memory.Write_U64(HSP::Read(state.aram_dma.ARAddr), state.aram_dma.MMAddr);
|
||||
state.aram_dma.MMAddr += 8;
|
||||
state.aram_dma.ARAddr += 8;
|
||||
state.aram_dma.Cnt.count -= 8;
|
||||
|
@ -628,22 +632,22 @@ static void Do_ARAM_DMA()
|
|||
if ((state.aram_info.Hex & 0xf) == 3)
|
||||
{
|
||||
*(u64*)&state.aram.ptr[state.aram_dma.ARAddr & state.aram.mask] =
|
||||
Common::swap64(Memory::Read_U64(state.aram_dma.MMAddr));
|
||||
Common::swap64(memory.Read_U64(state.aram_dma.MMAddr));
|
||||
}
|
||||
else if ((state.aram_info.Hex & 0xf) == 4)
|
||||
{
|
||||
if (state.aram_dma.ARAddr < 0x400000)
|
||||
{
|
||||
*(u64*)&state.aram.ptr[(state.aram_dma.ARAddr + 0x400000) & state.aram.mask] =
|
||||
Common::swap64(Memory::Read_U64(state.aram_dma.MMAddr));
|
||||
Common::swap64(memory.Read_U64(state.aram_dma.MMAddr));
|
||||
}
|
||||
*(u64*)&state.aram.ptr[state.aram_dma.ARAddr & state.aram.mask] =
|
||||
Common::swap64(Memory::Read_U64(state.aram_dma.MMAddr));
|
||||
Common::swap64(memory.Read_U64(state.aram_dma.MMAddr));
|
||||
}
|
||||
else
|
||||
{
|
||||
*(u64*)&state.aram.ptr[state.aram_dma.ARAddr & state.aram.mask] =
|
||||
Common::swap64(Memory::Read_U64(state.aram_dma.MMAddr));
|
||||
Common::swap64(memory.Read_U64(state.aram_dma.MMAddr));
|
||||
}
|
||||
|
||||
state.aram_dma.MMAddr += 8;
|
||||
|
@ -655,7 +659,7 @@ static void Do_ARAM_DMA()
|
|||
{
|
||||
while (state.aram_dma.Cnt.count)
|
||||
{
|
||||
HSP::Write(state.aram_dma.ARAddr, Memory::Read_U64(state.aram_dma.MMAddr));
|
||||
HSP::Write(state.aram_dma.ARAddr, memory.Read_U64(state.aram_dma.MMAddr));
|
||||
|
||||
state.aram_dma.MMAddr += 8;
|
||||
state.aram_dma.ARAddr += 8;
|
||||
|
@ -670,14 +674,20 @@ static void Do_ARAM_DMA()
|
|||
// (LM) It just means that DSP reads via '0xffdd' on Wii can end up in EXRAM or main RAM
|
||||
u8 ReadARAM(u32 address)
|
||||
{
|
||||
auto& state = Core::System::GetInstance().GetDSPState().GetData();
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& state = system.GetDSPState().GetData();
|
||||
|
||||
if (state.aram.wii_mode)
|
||||
{
|
||||
if (address & 0x10000000)
|
||||
{
|
||||
return state.aram.ptr[address & state.aram.mask];
|
||||
}
|
||||
else
|
||||
return Memory::Read_U8(address & Memory::GetRamMask());
|
||||
{
|
||||
auto& memory = system.GetMemory();
|
||||
return memory.Read_U8(address & memory.GetRamMask());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "Common/Swap.h"
|
||||
#include "Core/HW/DSPHLE/UCodes/UCodes.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
namespace DSP::HLE
|
||||
{
|
||||
|
@ -142,8 +143,10 @@ 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];
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "Core/HW/DSPHLE/UCodes/AX.h"
|
||||
#include "Core/HW/DSPHLE/UCodes/AXStructs.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
namespace DSP::HLE
|
||||
{
|
||||
|
@ -101,10 +102,13 @@ bool HasLpf(u32 crc)
|
|||
// Read a PB from MRAM/ARAM
|
||||
void ReadPB(u32 addr, PB_TYPE& pb, u32 crc)
|
||||
{
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
if (HasLpf(crc))
|
||||
{
|
||||
u16* dst = (u16*)&pb;
|
||||
Memory::CopyFromEmuSwapped<u16>(dst, addr, sizeof(pb));
|
||||
memory.CopyFromEmuSwapped<u16>(dst, addr, sizeof(pb));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -116,19 +120,22 @@ void ReadPB(u32 addr, PB_TYPE& pb, u32 crc)
|
|||
constexpr size_t lpf_off = offsetof(AXPB, lpf);
|
||||
constexpr size_t lc_off = offsetof(AXPB, loop_counter);
|
||||
|
||||
Memory::CopyFromEmuSwapped<u16>((u16*)dst, addr, lpf_off);
|
||||
memory.CopyFromEmuSwapped<u16>((u16*)dst, addr, lpf_off);
|
||||
memset(dst + lpf_off, 0, lc_off - lpf_off);
|
||||
Memory::CopyFromEmuSwapped<u16>((u16*)(dst + lc_off), addr + lpf_off, sizeof(pb) - lc_off);
|
||||
memory.CopyFromEmuSwapped<u16>((u16*)(dst + lc_off), addr + lpf_off, sizeof(pb) - lc_off);
|
||||
}
|
||||
}
|
||||
|
||||
// Write a PB back to MRAM/ARAM
|
||||
void WritePB(u32 addr, const PB_TYPE& pb, u32 crc)
|
||||
{
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
if (HasLpf(crc))
|
||||
{
|
||||
const u16* src = (const u16*)&pb;
|
||||
Memory::CopyToEmuSwapped<u16>(addr, src, sizeof(pb));
|
||||
memory.CopyToEmuSwapped<u16>(addr, src, sizeof(pb));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -140,8 +147,8 @@ void WritePB(u32 addr, const PB_TYPE& pb, u32 crc)
|
|||
constexpr size_t lpf_off = offsetof(AXPB, lpf);
|
||||
constexpr size_t lc_off = offsetof(AXPB, loop_counter);
|
||||
|
||||
Memory::CopyToEmuSwapped<u16>(addr, (const u16*)src, lpf_off);
|
||||
Memory::CopyToEmuSwapped<u16>(addr + lpf_off, (const u16*)(src + lc_off), sizeof(pb) - lc_off);
|
||||
memory.CopyToEmuSwapped<u16>(addr, (const u16*)src, lpf_off);
|
||||
memory.CopyToEmuSwapped<u16>(addr + lpf_off, (const u16*)(src + lc_off), sizeof(pb) - lc_off);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "Core/HW/DSPHLE/UCodes/ROM.h"
|
||||
#include "Core/HW/DSPHLE/UCodes/Zelda.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
namespace DSP::HLE
|
||||
{
|
||||
|
@ -40,28 +41,37 @@ constexpr bool ExramRead(u32 address)
|
|||
|
||||
u8 HLEMemory_Read_U8(u32 address)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "Core/HW/DSPLLE/DSPSymbols.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/System.h"
|
||||
#include "VideoCommon/OnScreenDisplay.h"
|
||||
|
||||
// The user of the DSPCore library must supply a few functions so that the
|
||||
|
@ -39,12 +40,16 @@ void WriteHostMemory(u8 value, u32 addr)
|
|||
|
||||
void DMAToDSP(u16* dst, u32 addr, u32 size)
|
||||
{
|
||||
Memory::CopyFromEmuSwapped(dst, addr, size);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
memory.CopyFromEmuSwapped(dst, addr, size);
|
||||
}
|
||||
|
||||
void DMAFromDSP(const u16* src, u32 addr, u32 size)
|
||||
{
|
||||
Memory::CopyToEmuSwapped(addr, src, size);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
memory.CopyToEmuSwapped(addr, src, size);
|
||||
}
|
||||
|
||||
void OSD_AddMessage(std::string str, u32 ms)
|
||||
|
@ -70,7 +75,9 @@ void InterruptRequest()
|
|||
|
||||
void CodeLoaded(DSPCore& dsp, u32 addr, size_t size)
|
||||
{
|
||||
CodeLoaded(dsp, Memory::GetPointer(addr), size);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
CodeLoaded(dsp, memory.GetPointer(addr), size);
|
||||
}
|
||||
|
||||
void CodeLoaded(DSPCore& dsp, const u8* ptr, size_t size)
|
||||
|
|
|
@ -896,15 +896,17 @@ void ExecuteCommand(ReplyType reply_type)
|
|||
{
|
||||
// Used by both GC and Wii
|
||||
case DICommand::Inquiry:
|
||||
{
|
||||
// (shuffle2) Taken from my Wii
|
||||
Memory::Write_U32(0x00000002, state.DIMAR); // Revision level, device code
|
||||
Memory::Write_U32(0x20060526, state.DIMAR + 4); // Release date
|
||||
Memory::Write_U32(0x41000000, state.DIMAR + 8); // Version
|
||||
auto& memory = system.GetMemory();
|
||||
memory.Write_U32(0x00000002, state.DIMAR); // Revision level, device code
|
||||
memory.Write_U32(0x20060526, state.DIMAR + 4); // Release date
|
||||
memory.Write_U32(0x41000000, state.DIMAR + 8); // Version
|
||||
|
||||
INFO_LOG_FMT(DVDINTERFACE, "DVDLowInquiry (Buffer {:#010x}, {:#x})", state.DIMAR,
|
||||
state.DILENGTH);
|
||||
break;
|
||||
|
||||
}
|
||||
// GC-only patched drive firmware command, used by libogc
|
||||
case DICommand::Unknown55:
|
||||
INFO_LOG_FMT(DVDINTERFACE, "SetExtension");
|
||||
|
@ -1024,17 +1026,20 @@ void ExecuteCommand(ReplyType reply_type)
|
|||
break;
|
||||
// Wii-exclusive
|
||||
case DICommand::ReadBCA:
|
||||
{
|
||||
WARN_LOG_FMT(DVDINTERFACE, "DVDLowReadDiskBca - supplying dummy data to appease NSMBW");
|
||||
DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DVD_LOW_READ_DISK_BCA);
|
||||
// NSMBW checks that the first 0x33 bytes of the BCA are 0, then it expects a 1.
|
||||
// Most (all?) other games have 0x34 0's at the start of the BCA, but don't actually
|
||||
// read it. NSMBW doesn't care about the other 12 bytes (which contain manufacturing data?)
|
||||
|
||||
auto& memory = system.GetMemory();
|
||||
// TODO: Read the .bca file that cleanrip generates, if it exists
|
||||
// Memory::CopyToEmu(output_address, bca_data, 0x40);
|
||||
Memory::Memset(state.DIMAR, 0, 0x40);
|
||||
Memory::Write_U8(1, state.DIMAR + 0x33);
|
||||
// memory.CopyToEmu(output_address, bca_data, 0x40);
|
||||
memory.Memset(state.DIMAR, 0, 0x40);
|
||||
memory.Write_U8(1, state.DIMAR + 0x33);
|
||||
break;
|
||||
}
|
||||
// Wii-exclusive
|
||||
case DICommand::RequestDiscStatus:
|
||||
ERROR_LOG_FMT(DVDINTERFACE, "DVDLowRequestDiscStatus");
|
||||
|
|
|
@ -391,7 +391,10 @@ static void FinishRead(Core::System& system, u64 id, s64 cycles_late)
|
|||
else
|
||||
{
|
||||
if (request.copy_to_ram)
|
||||
Memory::CopyToEmu(request.output_address, buffer.data(), request.length);
|
||||
{
|
||||
auto& memory = system.GetMemory();
|
||||
memory.CopyToEmu(request.output_address, buffer.data(), request.length);
|
||||
}
|
||||
|
||||
interrupt = DVDInterface::DIInterruptType::TCINT;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "Core/HW/EXI/EXI_DeviceMemoryCard.h"
|
||||
#include "Core/HW/EXI/EXI_DeviceMic.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
namespace ExpansionInterface
|
||||
{
|
||||
|
@ -47,20 +48,24 @@ void IEXIDevice::ImmReadWrite(u32& data, u32 size)
|
|||
|
||||
void IEXIDevice::DMAWrite(u32 address, u32 size)
|
||||
{
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
while (size--)
|
||||
{
|
||||
u8 byte = Memory::Read_U8(address++);
|
||||
u8 byte = memory.Read_U8(address++);
|
||||
TransferByte(byte);
|
||||
}
|
||||
}
|
||||
|
||||
void IEXIDevice::DMARead(u32 address, u32 size)
|
||||
{
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
while (size--)
|
||||
{
|
||||
u8 byte = 0;
|
||||
TransferByte(byte);
|
||||
Memory::Write_U8(byte, address++);
|
||||
memory.Write_U8(byte, address++);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "Core/HW/EXI/EXI.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
namespace ExpansionInterface
|
||||
{
|
||||
|
@ -233,7 +234,9 @@ void CEXIETHERNET::DMAWrite(u32 addr, u32 size)
|
|||
if (transfer.region == transfer.MX && transfer.direction == transfer.WRITE &&
|
||||
transfer.address == BBA_WRTXFIFOD)
|
||||
{
|
||||
DirectFIFOWrite(Memory::GetPointer(addr), size);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
DirectFIFOWrite(memory.GetPointer(addr), size);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -246,7 +249,9 @@ void CEXIETHERNET::DMAWrite(u32 addr, u32 size)
|
|||
void CEXIETHERNET::DMARead(u32 addr, u32 size)
|
||||
{
|
||||
DEBUG_LOG_FMT(SP1, "DMA read: {:08x} {:x}", addr, size);
|
||||
Memory::CopyToEmu(addr, &mBbaMem[transfer.address], size);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
memory.CopyToEmu(addr, &mBbaMem[transfer.address], size);
|
||||
transfer.address += size;
|
||||
}
|
||||
|
||||
|
|
|
@ -523,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));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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,11 +30,63 @@ 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;
|
||||
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;
|
||||
};
|
||||
|
||||
class MemoryManager
|
||||
{
|
||||
public:
|
||||
MemoryManager();
|
||||
MemoryManager(const MemoryManager& other) = delete;
|
||||
MemoryManager(MemoryManager&& other) = delete;
|
||||
MemoryManager& operator=(const MemoryManager& other) = delete;
|
||||
MemoryManager& operator=(MemoryManager&& other) = delete;
|
||||
~MemoryManager();
|
||||
|
||||
u32 GetRamSizeReal() const { return m_ram_size_real; }
|
||||
u32 GetRamSize() const { return m_ram_size; }
|
||||
u32 GetRamMask() const { return m_ram_mask; }
|
||||
u32 GetFakeVMemSize() const { return m_fakevmem_size; }
|
||||
u32 GetFakeVMemMask() const { return m_fakevmem_mask; }
|
||||
u32 GetL1CacheSize() const { return m_l1_cache_size; }
|
||||
u32 GetL1CacheMask() const { return m_l1_cache_mask; }
|
||||
u32 GetExRamSizeReal() const { return m_exram_size_real; }
|
||||
u32 GetExRamSize() const { return m_exram_size; }
|
||||
u32 GetExRamMask() const { return m_exram_mask; }
|
||||
|
||||
u8* GetPhysicalBase() const { return m_physical_base; }
|
||||
u8* GetLogicalBase() const { return m_logical_base; }
|
||||
u8* GetPhysicalPageMappingsBase() const { return m_physical_page_mappings_base; }
|
||||
u8* GetLogicalPageMappingsBase() const { return m_logical_page_mappings_base; }
|
||||
|
||||
// FIXME: these should not return their address, but AddressSpace wants that
|
||||
u8*& GetRAM() { return m_ram; }
|
||||
u8*& GetEXRAM() { return m_exram; }
|
||||
u8* GetL1Cache() { return m_l1_cache; }
|
||||
u8*& GetFakeVMEM() { return m_fake_vmem; }
|
||||
|
||||
MMIO::Mapping* GetMMIOMapping() const { return m_mmio_mapping.get(); }
|
||||
|
||||
// Init and Shutdown
|
||||
bool IsInitialized();
|
||||
bool IsInitialized() const { return m_is_initialized; }
|
||||
void Init();
|
||||
void Shutdown();
|
||||
bool InitFastmemArena();
|
||||
|
@ -74,15 +100,15 @@ 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);
|
||||
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);
|
||||
u16 Read_U16(u32 address);
|
||||
u32 Read_U32(u32 address);
|
||||
u64 Read_U64(u32 address);
|
||||
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);
|
||||
|
@ -92,7 +118,7 @@ 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)
|
||||
void CopyFromEmuSwapped(T* data, u32 address, size_t size) const
|
||||
{
|
||||
const T* src = reinterpret_cast<T*>(GetPointerForRange(address, size));
|
||||
|
||||
|
@ -114,4 +140,104 @@ void CopyToEmuSwapped(u32 address, const T* data, size_t size)
|
|||
for (size_t i = 0; i < size / sizeof(T); i++)
|
||||
dest[i] = Common::FromBigEndian(data[i]);
|
||||
}
|
||||
|
||||
private:
|
||||
// Base is a pointer to the base of the memory map. Yes, some MMU tricks
|
||||
// are used to set up a full GC or Wii memory map in process memory.
|
||||
// In 64-bit, this might point to "high memory" (above the 32-bit limit),
|
||||
// so be sure to load it into a 64-bit register.
|
||||
u8* m_physical_base = nullptr;
|
||||
u8* m_logical_base = nullptr;
|
||||
|
||||
// This page table is used for a "soft MMU" implementation when
|
||||
// setting up the full memory map in process memory isn't possible.
|
||||
u8* m_physical_page_mappings_base = nullptr;
|
||||
u8* m_logical_page_mappings_base = nullptr;
|
||||
|
||||
// The actual memory used for backing the memory map.
|
||||
u8* m_ram;
|
||||
u8* m_exram;
|
||||
u8* m_l1_cache;
|
||||
u8* m_fake_vmem;
|
||||
|
||||
// m_ram_size is the amount allocated by the emulator, whereas m_ram_size_real
|
||||
// is what will be reported in lowmem, and thus used by emulated software.
|
||||
// Note: Writing to lowmem is done by IPL. If using retail IPL, it will
|
||||
// always be set to 24MB.
|
||||
u32 m_ram_size_real;
|
||||
u32 m_ram_size;
|
||||
u32 m_ram_mask;
|
||||
u32 m_fakevmem_size;
|
||||
u32 m_fakevmem_mask;
|
||||
u32 m_l1_cache_size;
|
||||
u32 m_l1_cache_mask;
|
||||
// m_exram_size is the amount allocated by the emulator, whereas m_exram_size_real
|
||||
// is what gets used by emulated software. If using retail IOS, it will
|
||||
// always be set to 64MB.
|
||||
u32 m_exram_size_real;
|
||||
u32 m_exram_size;
|
||||
u32 m_exram_mask;
|
||||
|
||||
bool m_is_fastmem_arena_initialized = false;
|
||||
|
||||
// STATE_TO_SAVE
|
||||
// Save the Init(), Shutdown() state
|
||||
bool m_is_initialized = false;
|
||||
// END STATE_TO_SAVE
|
||||
|
||||
// MMIO mapping object.
|
||||
std::unique_ptr<MMIO::Mapping> m_mmio_mapping;
|
||||
|
||||
// The MemArena class
|
||||
Common::MemArena m_arena;
|
||||
|
||||
// Dolphin allocates memory to represent four regions:
|
||||
// - 32MB RAM (actually 24MB on hardware), available on GameCube and Wii
|
||||
// - 64MB "EXRAM", RAM only available on Wii
|
||||
// - 32MB FakeVMem, allocated in GameCube mode when MMU support is turned off.
|
||||
// This is used to approximate the behavior of a common library which pages
|
||||
// memory to and from the DSP's dedicated RAM. The DSP's RAM (ARAM) isn't
|
||||
// directly addressable on GameCube.
|
||||
// - 256KB Locked L1, to represent cache lines allocated out of the L1 data
|
||||
// cache in Locked L1 mode. Dolphin does not emulate this hardware feature
|
||||
// accurately; it just pretends there is extra memory at 0xE0000000.
|
||||
//
|
||||
// The 4GB starting at m_physical_base represents access from the CPU
|
||||
// with address translation turned off. (This is only used by the CPU;
|
||||
// other devices, like the GPU, use other rules, approximated by
|
||||
// Memory::GetPointer.) This memory is laid out as follows:
|
||||
// [0x00000000, 0x02000000) - 32MB RAM
|
||||
// [0x02000000, 0x08000000) - Mirrors of 32MB RAM (not handled here)
|
||||
// [0x08000000, 0x0C000000) - EFB "mapping" (not handled here)
|
||||
// [0x0C000000, 0x0E000000) - MMIO etc. (not handled here)
|
||||
// [0x10000000, 0x14000000) - 64MB RAM (Wii-only; slightly slower)
|
||||
// [0x7E000000, 0x80000000) - FakeVMEM
|
||||
// [0xE0000000, 0xE0040000) - 256KB locked L1
|
||||
//
|
||||
// The 4GB starting at m_logical_base represents access from the CPU
|
||||
// with address translation turned on. This mapping is computed based
|
||||
// on the BAT registers.
|
||||
//
|
||||
// Each of these 4GB regions is followed by 4GB of empty space so overflows
|
||||
// in address computation in the JIT don't access the wrong memory.
|
||||
//
|
||||
// The neighboring mirrors of RAM ([0x02000000, 0x08000000), etc.) exist because
|
||||
// the bus masks off the bits in question for RAM accesses; using them is a
|
||||
// terrible idea because the CPU cache won't handle them correctly, but a
|
||||
// few buggy games (notably Rogue Squadron 2) use them by accident. They
|
||||
// aren't backed by memory mappings because they are used very rarely.
|
||||
//
|
||||
// Dolphin doesn't emulate the difference between cached and uncached access.
|
||||
//
|
||||
// TODO: The actual size of RAM is 24MB; the other 8MB shouldn't be backed by actual memory.
|
||||
// TODO: Do we want to handle the mirrors of the GC RAM?
|
||||
std::array<PhysicalMemoryRegion, 4> m_physical_regions;
|
||||
|
||||
std::vector<LogicalMemoryView> m_logical_mapped_entries;
|
||||
|
||||
std::array<void*, PowerPC::BAT_PAGE_COUNT> m_physical_page_mappings;
|
||||
std::array<void*, PowerPC::BAT_PAGE_COUNT> m_logical_page_mappings;
|
||||
|
||||
void InitMMIO(bool is_wii);
|
||||
};
|
||||
} // namespace Memory
|
||||
|
|
|
@ -21,14 +21,25 @@
|
|||
#include "Core/HW/WII_IPC.h"
|
||||
#include "Core/IOS/ES/ES.h"
|
||||
#include "Core/IOS/ES/Formats.h"
|
||||
#include "Core/System.h"
|
||||
#include "DiscIO/Volume.h"
|
||||
|
||||
template <u32 addr>
|
||||
class RegisterWrapper
|
||||
{
|
||||
public:
|
||||
operator u32() const { return Memory::mmio_mapping->Read<u32>(addr); }
|
||||
void operator=(u32 rhs) { Memory::mmio_mapping->Write(addr, rhs); }
|
||||
operator u32() const
|
||||
{
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
return memory.GetMMIOMapping()->Read<u32>(addr);
|
||||
}
|
||||
void operator=(u32 rhs)
|
||||
{
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
memory.GetMMIOMapping()->Write(addr, rhs);
|
||||
}
|
||||
};
|
||||
static RegisterWrapper<0x0D806000> DISR;
|
||||
static RegisterWrapper<0x0D806004> DICVR;
|
||||
|
@ -76,7 +87,9 @@ std::optional<IPCReply> DIDevice::IOCtl(const IOCtlRequest& request)
|
|||
// asynchronously. The rest are also treated as async to match this. Only one command can be
|
||||
// executed at a time, so commands are queued until DVDInterface is ready to handle them.
|
||||
|
||||
const u8 command = Memory::Read_U8(request.buffer_in);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
const u8 command = memory.Read_U8(request.buffer_in);
|
||||
if (request.request != command)
|
||||
{
|
||||
WARN_LOG_FMT(IOS_DI,
|
||||
|
@ -128,7 +141,9 @@ std::optional<DIDevice::DIResult> DIDevice::WriteIfFits(const IOCtlRequest& requ
|
|||
}
|
||||
else
|
||||
{
|
||||
Memory::Write_U32(value, request.buffer_out);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
memory.Write_U32(value, request.buffer_out);
|
||||
return DIResult::Success;
|
||||
}
|
||||
}
|
||||
|
@ -152,6 +167,9 @@ std::optional<DIDevice::DIResult> DIDevice::StartIOCtl(const IOCtlRequest& reque
|
|||
return DIResult::SecurityError;
|
||||
}
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
// DVDInterface's ExecuteCommand handles most of the work for most of these.
|
||||
// The IOCtl callback is used to generate a reply afterwards.
|
||||
switch (static_cast<DIIoctl>(request.request))
|
||||
|
@ -169,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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "Core/IOS/ES/Formats.h"
|
||||
#include "Core/IOS/IOSC.h"
|
||||
#include "Core/IOS/Uids.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
namespace IOS::HLE
|
||||
{
|
||||
|
@ -34,7 +35,10 @@ IPCReply ESDevice::GetDeviceId(const IOCtlVRequest& request)
|
|||
const ReturnCode ret = GetDeviceId(&device_id);
|
||||
if (ret != IPC_SUCCESS)
|
||||
return IPCReply(ret);
|
||||
Memory::Write_U32(device_id, request.io_vectors[0].address);
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
memory.Write_U32(device_id, request.io_vectors[0].address);
|
||||
return IPCReply(IPC_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -43,11 +47,13 @@ IPCReply ESDevice::Encrypt(u32 uid, const IOCtlVRequest& request)
|
|||
if (!request.HasNumberOfValidVectors(3, 2))
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
u32 keyIndex = Memory::Read_U32(request.in_vectors[0].address);
|
||||
u8* source = Memory::GetPointer(request.in_vectors[2].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
u32 keyIndex = memory.Read_U32(request.in_vectors[0].address);
|
||||
u8* source = memory.GetPointer(request.in_vectors[2].address);
|
||||
u32 size = request.in_vectors[2].size;
|
||||
u8* iv = Memory::GetPointer(request.io_vectors[0].address);
|
||||
u8* destination = Memory::GetPointer(request.io_vectors[1].address);
|
||||
u8* iv = memory.GetPointer(request.io_vectors[0].address);
|
||||
u8* destination = memory.GetPointer(request.io_vectors[1].address);
|
||||
|
||||
// TODO: Check whether the active title is allowed to encrypt.
|
||||
|
||||
|
@ -60,11 +66,13 @@ IPCReply ESDevice::Decrypt(u32 uid, const IOCtlVRequest& request)
|
|||
if (!request.HasNumberOfValidVectors(3, 2))
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
u32 keyIndex = Memory::Read_U32(request.in_vectors[0].address);
|
||||
u8* source = Memory::GetPointer(request.in_vectors[2].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
u32 keyIndex = memory.Read_U32(request.in_vectors[0].address);
|
||||
u8* source = memory.GetPointer(request.in_vectors[2].address);
|
||||
u32 size = request.in_vectors[2].size;
|
||||
u8* iv = Memory::GetPointer(request.io_vectors[0].address);
|
||||
u8* destination = Memory::GetPointer(request.io_vectors[1].address);
|
||||
u8* iv = memory.GetPointer(request.io_vectors[0].address);
|
||||
u8* destination = memory.GetPointer(request.io_vectors[1].address);
|
||||
|
||||
// TODO: Check whether the active title is allowed to decrypt.
|
||||
|
||||
|
@ -92,8 +100,10 @@ IPCReply ESDevice::GetDeviceCertificate(const IOCtlVRequest& request)
|
|||
|
||||
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETDEVICECERT");
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
const IOS::CertECC cert = m_ios.GetIOSC().GetDeviceCertificate();
|
||||
Memory::CopyToEmu(request.io_vectors[0].address, &cert, sizeof(cert));
|
||||
memory.CopyToEmu(request.io_vectors[0].address, &cert, sizeof(cert));
|
||||
return IPCReply(IPC_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -103,10 +113,12 @@ IPCReply ESDevice::Sign(const IOCtlVRequest& request)
|
|||
return IPCReply(ES_EINVAL);
|
||||
|
||||
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_SIGN");
|
||||
u8* ap_cert_out = Memory::GetPointer(request.io_vectors[1].address);
|
||||
u8* data = Memory::GetPointer(request.in_vectors[0].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
u8* ap_cert_out = memory.GetPointer(request.io_vectors[1].address);
|
||||
u8* data = memory.GetPointer(request.in_vectors[0].address);
|
||||
u32 data_size = request.in_vectors[0].size;
|
||||
u8* sig_out = Memory::GetPointer(request.io_vectors[0].address);
|
||||
u8* sig_out = memory.GetPointer(request.io_vectors[0].address);
|
||||
|
||||
if (!m_title_context.active)
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
@ -193,14 +205,17 @@ IPCReply ESDevice::VerifySign(const IOCtlVRequest& request)
|
|||
if (request.in_vectors[1].size != sizeof(Common::ec::Signature))
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
std::vector<u8> hash(request.in_vectors[0].size);
|
||||
Memory::CopyFromEmu(hash.data(), request.in_vectors[0].address, hash.size());
|
||||
memory.CopyFromEmu(hash.data(), request.in_vectors[0].address, hash.size());
|
||||
|
||||
std::vector<u8> ecc_signature(request.in_vectors[1].size);
|
||||
Memory::CopyFromEmu(ecc_signature.data(), request.in_vectors[1].address, ecc_signature.size());
|
||||
memory.CopyFromEmu(ecc_signature.data(), request.in_vectors[1].address, ecc_signature.size());
|
||||
|
||||
std::vector<u8> certs(request.in_vectors[2].size);
|
||||
Memory::CopyFromEmu(certs.data(), request.in_vectors[2].address, certs.size());
|
||||
memory.CopyFromEmu(certs.data(), request.in_vectors[2].address, certs.size());
|
||||
|
||||
return IPCReply(VerifySign(hash, ecc_signature, certs));
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "Core/IOS/ES/Formats.h"
|
||||
#include "Core/IOS/FS/FileSystemProxy.h"
|
||||
#include "Core/IOS/Uids.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
namespace IOS::HLE
|
||||
{
|
||||
|
@ -56,8 +57,10 @@ IPCReply ESDevice::OpenContent(u32 uid, const IOCtlVRequest& request)
|
|||
return ES_EINVAL;
|
||||
}
|
||||
|
||||
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
|
||||
const u32 content_index = Memory::Read_U32(request.in_vectors[2].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||
const u32 content_index = memory.Read_U32(request.in_vectors[2].address);
|
||||
// TODO: check the ticket view, check permissions.
|
||||
|
||||
const auto tmd = FindInstalledTMD(title_id, ticks);
|
||||
|
@ -74,7 +77,9 @@ IPCReply ESDevice::OpenActiveTitleContent(u32 caller_uid, const IOCtlVRequest& r
|
|||
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u32))
|
||||
return ES_EINVAL;
|
||||
|
||||
const u32 content_index = Memory::Read_U32(request.in_vectors[0].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
const u32 content_index = memory.Read_U32(request.in_vectors[0].address);
|
||||
|
||||
if (!m_title_context.active)
|
||||
return ES_EINVAL;
|
||||
|
@ -109,13 +114,15 @@ IPCReply ESDevice::ReadContent(u32 uid, const IOCtlVRequest& request)
|
|||
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
|
||||
return ES_EINVAL;
|
||||
|
||||
const u32 cfd = Memory::Read_U32(request.in_vectors[0].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
const u32 cfd = memory.Read_U32(request.in_vectors[0].address);
|
||||
const u32 size = request.io_vectors[0].size;
|
||||
const u32 addr = request.io_vectors[0].address;
|
||||
|
||||
INFO_LOG_FMT(IOS_ES, "ReadContent(uid={:#x}, cfd={}, size={}, addr={:08x})", uid, cfd, size,
|
||||
addr);
|
||||
return ReadContent(cfd, Memory::GetPointer(addr), size, uid, ticks);
|
||||
return ReadContent(cfd, memory.GetPointer(addr), size, uid, ticks);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -142,7 +149,9 @@ IPCReply ESDevice::CloseContent(u32 uid, const IOCtlVRequest& request)
|
|||
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u32))
|
||||
return ES_EINVAL;
|
||||
|
||||
const u32 cfd = Memory::Read_U32(request.in_vectors[0].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
const u32 cfd = memory.Read_U32(request.in_vectors[0].address);
|
||||
return CloseContent(cfd, uid, ticks);
|
||||
});
|
||||
}
|
||||
|
@ -167,9 +176,11 @@ IPCReply ESDevice::SeekContent(u32 uid, const IOCtlVRequest& request)
|
|||
if (!request.HasNumberOfValidVectors(3, 0))
|
||||
return ES_EINVAL;
|
||||
|
||||
const u32 cfd = Memory::Read_U32(request.in_vectors[0].address);
|
||||
const u32 offset = Memory::Read_U32(request.in_vectors[1].address);
|
||||
const auto mode = static_cast<SeekMode>(Memory::Read_U32(request.in_vectors[2].address));
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
const u32 cfd = memory.Read_U32(request.in_vectors[0].address);
|
||||
const u32 offset = memory.Read_U32(request.in_vectors[1].address);
|
||||
const auto mode = static_cast<SeekMode>(memory.Read_U32(request.in_vectors[2].address));
|
||||
|
||||
return SeekContent(cfd, offset, mode, uid, ticks);
|
||||
});
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "Common/Logging/Log.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/IOS/ES/Formats.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
namespace IOS::HLE
|
||||
{
|
||||
|
@ -21,7 +22,9 @@ IPCReply ESDevice::GetStoredContentsCount(const ES::TMDReader& tmd, const IOCtlV
|
|||
return IPCReply(ES_EINVAL);
|
||||
|
||||
const u16 num_contents = static_cast<u16>(GetStoredContentsFromTMD(tmd).size());
|
||||
Memory::Write_U32(num_contents, request.io_vectors[0].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
memory.Write_U32(num_contents, request.io_vectors[0].address);
|
||||
|
||||
INFO_LOG_FMT(IOS_ES, "GetStoredContentsCount ({:#x}): {} content(s) for {:016x}",
|
||||
request.request, num_contents, tmd.GetTitleId());
|
||||
|
@ -35,16 +38,18 @@ IPCReply ESDevice::GetStoredContents(const ES::TMDReader& tmd, const IOCtlVReque
|
|||
if (!tmd.IsValid())
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
if (request.in_vectors[1].size != sizeof(u32) ||
|
||||
request.io_vectors[0].size != Memory::Read_U32(request.in_vectors[1].address) * sizeof(u32))
|
||||
request.io_vectors[0].size != memory.Read_U32(request.in_vectors[1].address) * sizeof(u32))
|
||||
{
|
||||
return IPCReply(ES_EINVAL);
|
||||
}
|
||||
|
||||
const auto contents = GetStoredContentsFromTMD(tmd);
|
||||
const u32 max_content_count = Memory::Read_U32(request.in_vectors[1].address);
|
||||
const u32 max_content_count = memory.Read_U32(request.in_vectors[1].address);
|
||||
for (u32 i = 0; i < std::min(static_cast<u32>(contents.size()), max_content_count); ++i)
|
||||
Memory::Write_U32(contents[i].id, request.io_vectors[0].address + i * sizeof(u32));
|
||||
memory.Write_U32(contents[i].id, request.io_vectors[0].address + i * sizeof(u32));
|
||||
|
||||
return IPCReply(IPC_SUCCESS);
|
||||
}
|
||||
|
@ -54,7 +59,9 @@ IPCReply ESDevice::GetStoredContentsCount(const IOCtlVRequest& request)
|
|||
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u64))
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||
const ES::TMDReader tmd = FindInstalledTMD(title_id);
|
||||
if (!tmd.IsValid())
|
||||
return IPCReply(FS_ENOENT);
|
||||
|
@ -66,7 +73,9 @@ IPCReply ESDevice::GetStoredContents(const IOCtlVRequest& request)
|
|||
if (!request.HasNumberOfValidVectors(2, 1) || request.in_vectors[0].size != sizeof(u64))
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||
const ES::TMDReader tmd = FindInstalledTMD(title_id);
|
||||
if (!tmd.IsValid())
|
||||
return IPCReply(FS_ENOENT);
|
||||
|
@ -79,7 +88,9 @@ IPCReply ESDevice::GetTMDStoredContentsCount(const IOCtlVRequest& request)
|
|||
return IPCReply(ES_EINVAL);
|
||||
|
||||
std::vector<u8> tmd_bytes(request.in_vectors[0].size);
|
||||
Memory::CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
memory.CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
|
||||
return GetStoredContentsCount(ES::TMDReader{std::move(tmd_bytes)}, request);
|
||||
}
|
||||
|
||||
|
@ -89,7 +100,9 @@ IPCReply ESDevice::GetTMDStoredContents(const IOCtlVRequest& request)
|
|||
return IPCReply(ES_EINVAL);
|
||||
|
||||
std::vector<u8> tmd_bytes(request.in_vectors[0].size);
|
||||
Memory::CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
memory.CopyFromEmu(tmd_bytes.data(), request.in_vectors[0].address, tmd_bytes.size());
|
||||
|
||||
const ES::TMDReader tmd{std::move(tmd_bytes)};
|
||||
if (!tmd.IsValid())
|
||||
|
@ -112,7 +125,9 @@ IPCReply ESDevice::GetTitleCount(const std::vector<u64>& titles, const IOCtlVReq
|
|||
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != 4)
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
Memory::Write_U32(static_cast<u32>(titles.size()), request.io_vectors[0].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
memory.Write_U32(static_cast<u32>(titles.size()), request.io_vectors[0].address);
|
||||
|
||||
return IPCReply(IPC_SUCCESS);
|
||||
}
|
||||
|
@ -122,10 +137,12 @@ IPCReply ESDevice::GetTitles(const std::vector<u64>& titles, const IOCtlVRequest
|
|||
if (!request.HasNumberOfValidVectors(1, 1))
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
const size_t max_count = Memory::Read_U32(request.in_vectors[0].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
const size_t max_count = memory.Read_U32(request.in_vectors[0].address);
|
||||
for (size_t i = 0; i < std::min(max_count, titles.size()); i++)
|
||||
{
|
||||
Memory::Write_U64(titles[i], request.io_vectors[0].address + static_cast<u32>(i) * sizeof(u64));
|
||||
memory.Write_U64(titles[i], request.io_vectors[0].address + static_cast<u32>(i) * sizeof(u64));
|
||||
INFO_LOG_FMT(IOS_ES, " title {:016x}", titles[i]);
|
||||
}
|
||||
return IPCReply(IPC_SUCCESS);
|
||||
|
@ -148,13 +165,15 @@ IPCReply ESDevice::GetStoredTMDSize(const IOCtlVRequest& request)
|
|||
if (!request.HasNumberOfValidVectors(1, 1))
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||
const ES::TMDReader tmd = FindInstalledTMD(title_id);
|
||||
if (!tmd.IsValid())
|
||||
return IPCReply(FS_ENOENT);
|
||||
|
||||
const u32 tmd_size = static_cast<u32>(tmd.GetBytes().size());
|
||||
Memory::Write_U32(tmd_size, request.io_vectors[0].address);
|
||||
memory.Write_U32(tmd_size, request.io_vectors[0].address);
|
||||
|
||||
INFO_LOG_FMT(IOS_ES, "GetStoredTMDSize: {} bytes for {:016x}", tmd_size, title_id);
|
||||
|
||||
|
@ -166,19 +185,21 @@ IPCReply ESDevice::GetStoredTMD(const IOCtlVRequest& request)
|
|||
if (!request.HasNumberOfValidVectors(2, 1))
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||
const ES::TMDReader tmd = FindInstalledTMD(title_id);
|
||||
if (!tmd.IsValid())
|
||||
return IPCReply(FS_ENOENT);
|
||||
|
||||
// TODO: actually use this param in when writing to the outbuffer :/
|
||||
const u32 MaxCount = Memory::Read_U32(request.in_vectors[1].address);
|
||||
const u32 MaxCount = memory.Read_U32(request.in_vectors[1].address);
|
||||
|
||||
const std::vector<u8>& raw_tmd = tmd.GetBytes();
|
||||
if (raw_tmd.size() != request.io_vectors[0].size)
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
Memory::CopyToEmu(request.io_vectors[0].address, raw_tmd.data(), raw_tmd.size());
|
||||
memory.CopyToEmu(request.io_vectors[0].address, raw_tmd.data(), raw_tmd.size());
|
||||
|
||||
INFO_LOG_FMT(IOS_ES, "GetStoredTMD: title {:016x} (buffer size: {})", title_id, MaxCount);
|
||||
return IPCReply(IPC_SUCCESS);
|
||||
|
@ -204,7 +225,9 @@ IPCReply ESDevice::GetBoot2Version(const IOCtlVRequest& request)
|
|||
INFO_LOG_FMT(IOS_ES, "IOCTL_ES_GETBOOT2VERSION");
|
||||
|
||||
// as of 26/02/2012, this was latest bootmii version
|
||||
Memory::Write_U32(4, request.io_vectors[0].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
memory.Write_U32(4, request.io_vectors[0].address);
|
||||
return IPCReply(IPC_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -214,7 +237,9 @@ IPCReply ESDevice::GetSharedContentsCount(const IOCtlVRequest& request) const
|
|||
return IPCReply(ES_EINVAL);
|
||||
|
||||
const u32 count = GetSharedContentsCount();
|
||||
Memory::Write_U32(count, request.io_vectors[0].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
memory.Write_U32(count, request.io_vectors[0].address);
|
||||
|
||||
INFO_LOG_FMT(IOS_ES, "GetSharedContentsCount: {} contents", count);
|
||||
return IPCReply(IPC_SUCCESS);
|
||||
|
@ -225,13 +250,15 @@ IPCReply ESDevice::GetSharedContents(const IOCtlVRequest& request) const
|
|||
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
const u32 max_count = Memory::Read_U32(request.in_vectors[0].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
const u32 max_count = memory.Read_U32(request.in_vectors[0].address);
|
||||
if (request.io_vectors[0].size != 20 * max_count)
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
const std::vector<std::array<u8, 20>> hashes = GetSharedContents();
|
||||
const u32 count = std::min(static_cast<u32>(hashes.size()), max_count);
|
||||
Memory::CopyToEmu(request.io_vectors[0].address, hashes.data(), 20 * count);
|
||||
memory.CopyToEmu(request.io_vectors[0].address, hashes.data(), 20 * count);
|
||||
|
||||
INFO_LOG_FMT(IOS_ES, "GetSharedContents: {} contents ({} requested)", count, max_count);
|
||||
return IPCReply(IPC_SUCCESS);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "Core/IOS/ES/Formats.h"
|
||||
#include "Core/IOS/FS/FileSystem.h"
|
||||
#include "Core/IOS/Uids.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
namespace IOS::HLE
|
||||
{
|
||||
|
@ -97,10 +98,13 @@ IPCReply ESDevice::ImportTicket(const IOCtlVRequest& request)
|
|||
if (!request.HasNumberOfValidVectors(3, 0))
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
std::vector<u8> bytes(request.in_vectors[0].size);
|
||||
Memory::CopyFromEmu(bytes.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
||||
memory.CopyFromEmu(bytes.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
||||
std::vector<u8> cert_chain(request.in_vectors[1].size);
|
||||
Memory::CopyFromEmu(cert_chain.data(), request.in_vectors[1].address, request.in_vectors[1].size);
|
||||
memory.CopyFromEmu(cert_chain.data(), request.in_vectors[1].address, request.in_vectors[1].size);
|
||||
return IPCReply(ImportTicket(bytes, cert_chain));
|
||||
}
|
||||
|
||||
|
@ -187,8 +191,11 @@ IPCReply ESDevice::ImportTmd(Context& context, const IOCtlVRequest& request)
|
|||
if (!ES::IsValidTMDSize(request.in_vectors[0].size))
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
std::vector<u8> tmd(request.in_vectors[0].size);
|
||||
Memory::CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
||||
memory.CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
||||
return IPCReply(ImportTmd(context, tmd, m_title_context.tmd.GetTitleId(),
|
||||
m_title_context.tmd.GetTitleFlags()));
|
||||
}
|
||||
|
@ -273,10 +280,13 @@ IPCReply ESDevice::ImportTitleInit(Context& context, const IOCtlVRequest& reques
|
|||
if (!ES::IsValidTMDSize(request.in_vectors[0].size))
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
std::vector<u8> tmd(request.in_vectors[0].size);
|
||||
Memory::CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
||||
memory.CopyFromEmu(tmd.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
||||
std::vector<u8> certs(request.in_vectors[1].size);
|
||||
Memory::CopyFromEmu(certs.data(), request.in_vectors[1].address, request.in_vectors[1].size);
|
||||
memory.CopyFromEmu(certs.data(), request.in_vectors[1].address, request.in_vectors[1].size);
|
||||
return IPCReply(ImportTitleInit(context, tmd, certs));
|
||||
}
|
||||
|
||||
|
@ -328,8 +338,11 @@ IPCReply ESDevice::ImportContentBegin(Context& context, const IOCtlVRequest& req
|
|||
if (!request.HasNumberOfValidVectors(2, 0))
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
|
||||
u32 content_id = Memory::Read_U32(request.in_vectors[1].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||
u32 content_id = memory.Read_U32(request.in_vectors[1].address);
|
||||
return IPCReply(ImportContentBegin(context, title_id, content_id));
|
||||
}
|
||||
|
||||
|
@ -347,8 +360,11 @@ IPCReply ESDevice::ImportContentData(Context& context, const IOCtlVRequest& requ
|
|||
if (!request.HasNumberOfValidVectors(2, 0))
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
u32 content_fd = Memory::Read_U32(request.in_vectors[0].address);
|
||||
u8* data_start = Memory::GetPointer(request.in_vectors[1].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
u32 content_fd = memory.Read_U32(request.in_vectors[0].address);
|
||||
u8* data_start = memory.GetPointer(request.in_vectors[1].address);
|
||||
return IPCReply(ImportContentData(context, content_fd, data_start, request.in_vectors[1].size));
|
||||
}
|
||||
|
||||
|
@ -430,7 +446,10 @@ IPCReply ESDevice::ImportContentEnd(Context& context, const IOCtlVRequest& reque
|
|||
if (!request.HasNumberOfValidVectors(1, 0))
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
u32 content_fd = Memory::Read_U32(request.in_vectors[0].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
u32 content_fd = memory.Read_U32(request.in_vectors[0].address);
|
||||
return IPCReply(ImportContentEnd(context, content_fd));
|
||||
}
|
||||
|
||||
|
@ -542,7 +561,10 @@ IPCReply ESDevice::DeleteTitle(const IOCtlVRequest& request)
|
|||
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 8)
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||
return IPCReply(DeleteTitle(title_id));
|
||||
}
|
||||
|
||||
|
@ -595,7 +617,10 @@ IPCReply ESDevice::DeleteTicket(const IOCtlVRequest& request)
|
|||
{
|
||||
return IPCReply(ES_EINVAL);
|
||||
}
|
||||
return IPCReply(DeleteTicket(Memory::GetPointer(request.in_vectors[0].address)));
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
return IPCReply(DeleteTicket(memory.GetPointer(request.in_vectors[0].address)));
|
||||
}
|
||||
|
||||
ReturnCode ESDevice::DeleteTitleContent(u64 title_id) const
|
||||
|
@ -621,7 +646,10 @@ IPCReply ESDevice::DeleteTitleContent(const IOCtlVRequest& request)
|
|||
{
|
||||
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sizeof(u64))
|
||||
return IPCReply(ES_EINVAL);
|
||||
return IPCReply(DeleteTitleContent(Memory::Read_U64(request.in_vectors[0].address)));
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
return IPCReply(DeleteTitleContent(memory.Read_U64(request.in_vectors[0].address)));
|
||||
}
|
||||
|
||||
ReturnCode ESDevice::DeleteContent(u64 title_id, u32 content_id) const
|
||||
|
@ -649,8 +677,11 @@ IPCReply ESDevice::DeleteContent(const IOCtlVRequest& request)
|
|||
{
|
||||
return IPCReply(ES_EINVAL);
|
||||
}
|
||||
return IPCReply(DeleteContent(Memory::Read_U64(request.in_vectors[0].address),
|
||||
Memory::Read_U32(request.in_vectors[1].address)));
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
return IPCReply(DeleteContent(memory.Read_U64(request.in_vectors[0].address),
|
||||
memory.Read_U32(request.in_vectors[1].address)));
|
||||
}
|
||||
|
||||
ReturnCode ESDevice::ExportTitleInit(Context& context, u64 title_id, u8* tmd_bytes, u32 tmd_size,
|
||||
|
@ -687,8 +718,11 @@ IPCReply ESDevice::ExportTitleInit(Context& context, const IOCtlVRequest& reques
|
|||
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != 8)
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
|
||||
u8* tmd_bytes = Memory::GetPointer(request.io_vectors[0].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||
u8* tmd_bytes = memory.GetPointer(request.io_vectors[0].address);
|
||||
const u32 tmd_size = request.io_vectors[0].size;
|
||||
|
||||
return IPCReply(ExportTitleInit(context, title_id, tmd_bytes, tmd_size,
|
||||
|
@ -733,8 +767,11 @@ IPCReply ESDevice::ExportContentBegin(Context& context, const IOCtlVRequest& req
|
|||
request.in_vectors[1].size != 4)
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
const u64 title_id = Memory::Read_U64(request.in_vectors[0].address);
|
||||
const u32 content_id = Memory::Read_U32(request.in_vectors[1].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
const u64 title_id = memory.Read_U64(request.in_vectors[0].address);
|
||||
const u32 content_id = memory.Read_U32(request.in_vectors[1].address);
|
||||
|
||||
return IPCReply(ExportContentBegin(context, title_id, content_id));
|
||||
}
|
||||
|
@ -781,8 +818,11 @@ IPCReply ESDevice::ExportContentData(Context& context, const IOCtlVRequest& requ
|
|||
return IPCReply(ES_EINVAL);
|
||||
}
|
||||
|
||||
const u32 content_fd = Memory::Read_U32(request.in_vectors[0].address);
|
||||
u8* data = Memory::GetPointer(request.io_vectors[0].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
const u32 content_fd = memory.Read_U32(request.in_vectors[0].address);
|
||||
u8* data = memory.GetPointer(request.io_vectors[0].address);
|
||||
const u32 bytes_to_read = request.io_vectors[0].size;
|
||||
|
||||
return IPCReply(ExportContentData(context, content_fd, data, bytes_to_read));
|
||||
|
@ -800,7 +840,10 @@ IPCReply ESDevice::ExportContentEnd(Context& context, const IOCtlVRequest& reque
|
|||
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != 4)
|
||||
return IPCReply(ES_EINVAL);
|
||||
|
||||
const u32 content_fd = Memory::Read_U32(request.in_vectors[0].address);
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
const u32 content_fd = memory.Read_U32(request.in_vectors[0].address);
|
||||
return IPCReply(ExportContentEnd(context, content_fd));
|
||||
}
|
||||
|
||||
|
@ -857,7 +900,11 @@ IPCReply ESDevice::DeleteSharedContent(const IOCtlVRequest& request)
|
|||
std::array<u8, 20> sha1;
|
||||
if (!request.HasNumberOfValidVectors(1, 0) || request.in_vectors[0].size != sha1.size())
|
||||
return IPCReply(ES_EINVAL);
|
||||
Memory::CopyFromEmu(sha1.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
||||
|
||||
auto& system = Core::System::GetInstance();
|
||||
auto& memory = system.GetMemory();
|
||||
|
||||
memory.CopyFromEmu(sha1.data(), request.in_vectors[0].address, request.in_vectors[0].size);
|
||||
return IPCReply(DeleteSharedContent(sha1));
|
||||
}
|
||||
} // namespace IOS::HLE
|
||||
|
|
|
@ -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),
|
||||
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,7 +397,9 @@ 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()),
|
||||
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
|
||||
|
|
|
@ -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(¶ms, request.buffer_in, sizeof(params));
|
||||
memory.CopyFromEmu(¶ms, 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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,12 +565,12 @@ 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,
|
||||
memory.CopyToEmu(request.buffer_out + 2, &sa.sa_data,
|
||||
std::min<size_t>(sizeof(sa.sa_data), request.buffer_out_size - 2));
|
||||
}
|
||||
|
||||
|
@ -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,12 +592,12 @@ 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,
|
||||
memory.CopyToEmu(request.buffer_out + 2, &sa.sa_data,
|
||||
std::min<size_t>(sizeof(sa.sa_data), request.buffer_out_size - 2));
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
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 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,
|
||||
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,
|
||||
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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,7 +283,7 @@ 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,
|
||||
memory.CopyToEmu(m_devicechange_hook_request->buffer_out + sizeof(entry) * num_devices, &entry,
|
||||
sizeof(entry));
|
||||
++num_devices;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,13 +157,13 @@ 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],
|
||||
memory.CopyToEmu(request.buffer_out + 64 + 8 * static_cast<u8>(i), &endpoints[i],
|
||||
sizeof(endpoints[i]));
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,7 +263,9 @@ void LoadIndexedXF(CPArray array, u32 index, u16 address, u8 size)
|
|||
}
|
||||
else
|
||||
{
|
||||
newData = (u32*)Memory::GetPointer(g_main_cp_state.array_bases[array] +
|
||||
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;
|
||||
|
@ -284,7 +287,9 @@ 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] +
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue