Adding some comments.
This commit is contained in:
parent
66cab7b76e
commit
249b952de9
|
@ -25,6 +25,9 @@ bool IsDebuggerAttached();
|
||||||
// If no debugger is present, a signal will be raised.
|
// If no debugger is present, a signal will be raised.
|
||||||
void Break();
|
void Break();
|
||||||
|
|
||||||
|
// Prints a message to the attached debugger.
|
||||||
|
// This bypasses the normal logging mechanism. If no debugger is attached it's
|
||||||
|
// likely to no-op.
|
||||||
void DebugPrint(const char* fmt, ...);
|
void DebugPrint(const char* fmt, ...);
|
||||||
|
|
||||||
} // namespace debugging
|
} // namespace debugging
|
||||||
|
|
|
@ -20,16 +20,34 @@
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace filesystem {
|
namespace filesystem {
|
||||||
|
|
||||||
|
// Canonicalizes a path, removing ..'s.
|
||||||
std::string CanonicalizePath(const std::string& original_path);
|
std::string CanonicalizePath(const std::string& original_path);
|
||||||
|
|
||||||
|
// Returns true of the specified path exists as either a directory or file.
|
||||||
bool PathExists(const std::wstring& path);
|
bool PathExists(const std::wstring& path);
|
||||||
|
|
||||||
|
// Creates the parent folder of the specified path if needed.
|
||||||
|
// This can be used to ensure the destination path for a new file exists before
|
||||||
|
// attempting to create it.
|
||||||
bool CreateParentFolder(const std::wstring& path);
|
bool CreateParentFolder(const std::wstring& path);
|
||||||
|
|
||||||
|
// Creates a folder at the specified path.
|
||||||
|
// Returns true if the path was created.
|
||||||
bool CreateFolder(const std::wstring& path);
|
bool CreateFolder(const std::wstring& path);
|
||||||
|
|
||||||
|
// Recursively deletes the files and folders at the specified path.
|
||||||
|
// Returns true if the path was found and removed.
|
||||||
bool DeleteFolder(const std::wstring& path);
|
bool DeleteFolder(const std::wstring& path);
|
||||||
|
|
||||||
|
// Returns true if the given path exists and is a folder.
|
||||||
bool IsFolder(const std::wstring& path);
|
bool IsFolder(const std::wstring& path);
|
||||||
|
|
||||||
|
// Opens the file at the given path with the specified mode.
|
||||||
|
// This behaves like fopen and the returned handle can be used with stdio.
|
||||||
FILE* OpenFile(const std::wstring& path, const char* mode);
|
FILE* OpenFile(const std::wstring& path, const char* mode);
|
||||||
|
|
||||||
|
// Deletes the file at the given path.
|
||||||
|
// Returns true if the file was found and removed.
|
||||||
bool DeleteFile(const std::wstring& path);
|
bool DeleteFile(const std::wstring& path);
|
||||||
|
|
||||||
struct FileAccess {
|
struct FileAccess {
|
||||||
|
|
|
@ -95,9 +95,8 @@ X_STATUS Emulator::Setup(
|
||||||
|
|
||||||
// Create memory system first, as it is required for other systems.
|
// Create memory system first, as it is required for other systems.
|
||||||
memory_ = std::make_unique<Memory>();
|
memory_ = std::make_unique<Memory>();
|
||||||
result = memory_->Initialize();
|
if (!memory_->Initialize()) {
|
||||||
if (result) {
|
return false;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shared export resolver used to attach and query for HLE exports.
|
// Shared export resolver used to attach and query for HLE exports.
|
||||||
|
|
|
@ -43,33 +43,57 @@ class Window;
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
|
|
||||||
|
// The main type that runs the whole emulator.
|
||||||
|
// This is responsible for initializing and managing all the various subsystems.
|
||||||
class Emulator {
|
class Emulator {
|
||||||
public:
|
public:
|
||||||
explicit Emulator(const std::wstring& command_line);
|
explicit Emulator(const std::wstring& command_line);
|
||||||
~Emulator();
|
~Emulator();
|
||||||
|
|
||||||
|
// Full command line used when launching the process.
|
||||||
const std::wstring& command_line() const { return command_line_; }
|
const std::wstring& command_line() const { return command_line_; }
|
||||||
|
|
||||||
|
// Window used for displaying graphical output.
|
||||||
ui::Window* display_window() const { return display_window_; }
|
ui::Window* display_window() const { return display_window_; }
|
||||||
|
|
||||||
|
// Guest memory system modelling the RAM (both virtual and physical) of the
|
||||||
|
// system.
|
||||||
Memory* memory() const { return memory_.get(); }
|
Memory* memory() const { return memory_.get(); }
|
||||||
|
|
||||||
|
// Active debugger, which may or may not be attached.
|
||||||
debug::Debugger* debugger() const { return debugger_.get(); }
|
debug::Debugger* debugger() const { return debugger_.get(); }
|
||||||
|
|
||||||
|
// Virtualized processor that can execute PPC code.
|
||||||
cpu::Processor* processor() const { return processor_.get(); }
|
cpu::Processor* processor() const { return processor_.get(); }
|
||||||
|
|
||||||
|
// Audio hardware emulation for decoding and playback.
|
||||||
apu::AudioSystem* audio_system() const { return audio_system_.get(); }
|
apu::AudioSystem* audio_system() const { return audio_system_.get(); }
|
||||||
|
|
||||||
|
// GPU emulation for command list processing.
|
||||||
gpu::GraphicsSystem* graphics_system() const {
|
gpu::GraphicsSystem* graphics_system() const {
|
||||||
return graphics_system_.get();
|
return graphics_system_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Human-interface Device (HID) adapters for controllers.
|
||||||
hid::InputSystem* input_system() const { return input_system_.get(); }
|
hid::InputSystem* input_system() const { return input_system_.get(); }
|
||||||
|
|
||||||
|
// Kernel function export table used to resolve exports when JITing code.
|
||||||
cpu::ExportResolver* export_resolver() const {
|
cpu::ExportResolver* export_resolver() const {
|
||||||
return export_resolver_.get();
|
return export_resolver_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// File systems mapped to disc images, folders, etc for games and save data.
|
||||||
vfs::VirtualFileSystem* file_system() const { return file_system_.get(); }
|
vfs::VirtualFileSystem* file_system() const { return file_system_.get(); }
|
||||||
|
|
||||||
|
// The 'kernel', tracking all kernel objects and other state.
|
||||||
|
// This is effectively the guest operating system.
|
||||||
kernel::KernelState* kernel_state() const { return kernel_state_.get(); }
|
kernel::KernelState* kernel_state() const { return kernel_state_.get(); }
|
||||||
|
|
||||||
|
// Initializes the emulator and configures all components.
|
||||||
|
// The given window is used for display and the provided functions are used
|
||||||
|
// to create subsystems as required.
|
||||||
|
// Once this function returns a game can be launched using one of the Launch
|
||||||
|
// functions.
|
||||||
X_STATUS Setup(
|
X_STATUS Setup(
|
||||||
ui::Window* display_window,
|
ui::Window* display_window,
|
||||||
std::function<std::unique_ptr<apu::AudioSystem>(cpu::Processor*)>
|
std::function<std::unique_ptr<apu::AudioSystem>(cpu::Processor*)>
|
||||||
|
@ -79,9 +103,19 @@ class Emulator {
|
||||||
std::function<std::vector<std::unique_ptr<hid::InputDriver>>(ui::Window*)>
|
std::function<std::vector<std::unique_ptr<hid::InputDriver>>(ui::Window*)>
|
||||||
input_driver_factory);
|
input_driver_factory);
|
||||||
|
|
||||||
|
// Launches a game from the given file path.
|
||||||
|
// This will attempt to infer the type of the given file (such as an iso, etc)
|
||||||
|
// using heuristics.
|
||||||
X_STATUS LaunchPath(std::wstring path);
|
X_STATUS LaunchPath(std::wstring path);
|
||||||
|
|
||||||
|
// Launches a game from a .xex file by mounting the containing folder as if it
|
||||||
|
// was an extracted STFS container.
|
||||||
X_STATUS LaunchXexFile(std::wstring path);
|
X_STATUS LaunchXexFile(std::wstring path);
|
||||||
|
|
||||||
|
// Launches a game from a disc image file (.iso, etc).
|
||||||
X_STATUS LaunchDiscImage(std::wstring path);
|
X_STATUS LaunchDiscImage(std::wstring path);
|
||||||
|
|
||||||
|
// Launches a game from an STFS container file.
|
||||||
X_STATUS LaunchStfsContainer(std::wstring path);
|
X_STATUS LaunchStfsContainer(std::wstring path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -115,7 +115,7 @@ Memory::~Memory() {
|
||||||
physical_membase_ = nullptr;
|
physical_membase_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Memory::Initialize() {
|
bool Memory::Initialize() {
|
||||||
file_name_ = std::wstring(L"Local\\xenia_memory_") +
|
file_name_ = std::wstring(L"Local\\xenia_memory_") +
|
||||||
std::to_wstring(Clock::QueryHostTickCount());
|
std::to_wstring(Clock::QueryHostTickCount());
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ int Memory::Initialize() {
|
||||||
if (!mapping_) {
|
if (!mapping_) {
|
||||||
XELOGE("Unable to reserve the 4gb guest address space.");
|
XELOGE("Unable to reserve the 4gb guest address space.");
|
||||||
assert_not_null(mapping_);
|
assert_not_null(mapping_);
|
||||||
return 1;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attempt to create our views. This may fail at the first address
|
// Attempt to create our views. This may fail at the first address
|
||||||
|
@ -144,7 +144,7 @@ int Memory::Initialize() {
|
||||||
if (!mapping_base_) {
|
if (!mapping_base_) {
|
||||||
XELOGE("Unable to find a continuous block in the 64bit address space.");
|
XELOGE("Unable to find a continuous block in the 64bit address space.");
|
||||||
assert_always();
|
assert_always();
|
||||||
return 1;
|
return false;
|
||||||
}
|
}
|
||||||
virtual_membase_ = mapping_base_;
|
virtual_membase_ = mapping_base_;
|
||||||
physical_membase_ = mapping_base_ + 0x100000000ull;
|
physical_membase_ = mapping_base_ + 0x100000000ull;
|
||||||
|
@ -189,7 +189,7 @@ int Memory::Initialize() {
|
||||||
if (!mmio_handler_) {
|
if (!mmio_handler_) {
|
||||||
XELOGE("Unable to install MMIO handlers");
|
XELOGE("Unable to install MMIO handlers");
|
||||||
assert_always();
|
assert_always();
|
||||||
return 1;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ?
|
// ?
|
||||||
|
@ -197,7 +197,7 @@ int Memory::Initialize() {
|
||||||
heaps_.vA0000000.Alloc(0x340000, 64 * 1024, kMemoryAllocationReserve,
|
heaps_.vA0000000.Alloc(0x340000, 64 * 1024, kMemoryAllocationReserve,
|
||||||
kMemoryProtectNoAccess, true, &unk_phys_alloc);
|
kMemoryProtectNoAccess, true, &unk_phys_alloc);
|
||||||
|
|
||||||
return 0;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
|
|
|
@ -63,45 +63,85 @@ struct HeapAllocationInfo {
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Describes a single page in the page table.
|
||||||
union PageEntry {
|
union PageEntry {
|
||||||
struct {
|
struct {
|
||||||
uint32_t base_address : 20; // in 4k pages
|
// Base address of the allocated region in 4k pages.
|
||||||
uint32_t region_page_count : 20; // in 4k pages
|
uint32_t base_address : 20;
|
||||||
|
// Total number of pages in the allocated region in 4k pages.
|
||||||
|
uint32_t region_page_count : 20;
|
||||||
|
// Protection bits specified during region allocation.
|
||||||
|
// Composed of bits from MemoryProtectFlag.
|
||||||
uint32_t allocation_protect : 4;
|
uint32_t allocation_protect : 4;
|
||||||
|
// Current protection bits as of the last Protect.
|
||||||
|
// Composed of bits from MemoryProtectFlag.
|
||||||
uint32_t current_protect : 4;
|
uint32_t current_protect : 4;
|
||||||
|
// Allocation state of the page as a MemoryAllocationFlag bit mask.
|
||||||
uint32_t state : 2;
|
uint32_t state : 2;
|
||||||
uint32_t reserved : 14;
|
uint32_t reserved : 14;
|
||||||
};
|
};
|
||||||
uint64_t qword;
|
uint64_t qword;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Heap abstraction for page-based allocation.
|
||||||
class BaseHeap {
|
class BaseHeap {
|
||||||
public:
|
public:
|
||||||
virtual ~BaseHeap();
|
virtual ~BaseHeap();
|
||||||
|
|
||||||
|
// Size of each page within the heap range in bytes.
|
||||||
uint32_t page_size() const { return page_size_; }
|
uint32_t page_size() const { return page_size_; }
|
||||||
|
|
||||||
|
// Disposes and decommits all memory and clears the page table.
|
||||||
virtual void Dispose();
|
virtual void Dispose();
|
||||||
|
|
||||||
|
// Dumps information about all allocations within the heap to the log.
|
||||||
void DumpMap();
|
void DumpMap();
|
||||||
|
|
||||||
|
// Allocates pages with the given properties and allocation strategy.
|
||||||
|
// This can reserve and commit the pages as well as set protection modes.
|
||||||
|
// This will fail if not enough contiguous pages can be found.
|
||||||
virtual bool Alloc(uint32_t size, uint32_t alignment,
|
virtual bool Alloc(uint32_t size, uint32_t alignment,
|
||||||
uint32_t allocation_type, uint32_t protect, bool top_down,
|
uint32_t allocation_type, uint32_t protect, bool top_down,
|
||||||
uint32_t* out_address);
|
uint32_t* out_address);
|
||||||
|
|
||||||
|
// Allocates pages at the given address.
|
||||||
|
// This can reserve and commit the pages as well as set protection modes.
|
||||||
|
// This will fail if the pages are already allocated.
|
||||||
virtual bool AllocFixed(uint32_t base_address, uint32_t size,
|
virtual bool AllocFixed(uint32_t base_address, uint32_t size,
|
||||||
uint32_t alignment, uint32_t allocation_type,
|
uint32_t alignment, uint32_t allocation_type,
|
||||||
uint32_t protect);
|
uint32_t protect);
|
||||||
|
|
||||||
|
// Allocates pages at an address within the given address range.
|
||||||
|
// This can reserve and commit the pages as well as set protection modes.
|
||||||
|
// This will fail if not enough contiguous pages can be found.
|
||||||
virtual bool AllocRange(uint32_t low_address, uint32_t high_address,
|
virtual bool AllocRange(uint32_t low_address, uint32_t high_address,
|
||||||
uint32_t size, uint32_t alignment,
|
uint32_t size, uint32_t alignment,
|
||||||
uint32_t allocation_type, uint32_t protect,
|
uint32_t allocation_type, uint32_t protect,
|
||||||
bool top_down, uint32_t* out_address);
|
bool top_down, uint32_t* out_address);
|
||||||
|
|
||||||
|
// Decommits pages in the given range.
|
||||||
|
// Partial overlapping pages will also be decommitted.
|
||||||
virtual bool Decommit(uint32_t address, uint32_t size);
|
virtual bool Decommit(uint32_t address, uint32_t size);
|
||||||
|
|
||||||
|
// Decommits and releases pages in the given range.
|
||||||
|
// Partial overlapping pages will also be released.
|
||||||
virtual bool Release(uint32_t address, uint32_t* out_region_size = nullptr);
|
virtual bool Release(uint32_t address, uint32_t* out_region_size = nullptr);
|
||||||
|
|
||||||
|
// Modifies the protection mode of pages within the given range.
|
||||||
virtual bool Protect(uint32_t address, uint32_t size, uint32_t protect);
|
virtual bool Protect(uint32_t address, uint32_t size, uint32_t protect);
|
||||||
|
|
||||||
|
// Queries information about the given region of pages.
|
||||||
bool QueryRegionInfo(uint32_t base_address, HeapAllocationInfo* out_info);
|
bool QueryRegionInfo(uint32_t base_address, HeapAllocationInfo* out_info);
|
||||||
|
|
||||||
|
// Queries the size of the region containing the given address.
|
||||||
bool QuerySize(uint32_t address, uint32_t* out_size);
|
bool QuerySize(uint32_t address, uint32_t* out_size);
|
||||||
|
|
||||||
|
// Queries the current protection mode of the region containing the given
|
||||||
|
// address.
|
||||||
bool QueryProtect(uint32_t address, uint32_t* out_protect);
|
bool QueryProtect(uint32_t address, uint32_t* out_protect);
|
||||||
|
|
||||||
|
// Gets the physical address of a virtual address.
|
||||||
|
// This is only valid if the page is backed by a physical allocation.
|
||||||
uint32_t GetPhysicalAddress(uint32_t address);
|
uint32_t GetPhysicalAddress(uint32_t address);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -118,20 +158,30 @@ class BaseHeap {
|
||||||
std::vector<PageEntry> page_table_;
|
std::vector<PageEntry> page_table_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Normal heap allowing allocations from guest virtual address ranges.
|
||||||
class VirtualHeap : public BaseHeap {
|
class VirtualHeap : public BaseHeap {
|
||||||
public:
|
public:
|
||||||
VirtualHeap();
|
VirtualHeap();
|
||||||
~VirtualHeap() override;
|
~VirtualHeap() override;
|
||||||
|
|
||||||
|
// Initializes the heap properties and allocates the page table.
|
||||||
void Initialize(uint8_t* membase, uint32_t heap_base, uint32_t heap_size,
|
void Initialize(uint8_t* membase, uint32_t heap_base, uint32_t heap_size,
|
||||||
uint32_t page_size);
|
uint32_t page_size);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A heap for ranges of memory that are mapped to physical ranges.
|
||||||
|
// Physical ranges are used by the audio and graphics subsystems representing
|
||||||
|
// hardware wired directly to memory in the console.
|
||||||
|
//
|
||||||
|
// The physical heap and the behavior of sharing pages with virtual pages is
|
||||||
|
// implemented by having a 'parent' heap that is used to perform allocation in
|
||||||
|
// the guest virtual address space 1:1 with the physical address space.
|
||||||
class PhysicalHeap : public BaseHeap {
|
class PhysicalHeap : public BaseHeap {
|
||||||
public:
|
public:
|
||||||
PhysicalHeap();
|
PhysicalHeap();
|
||||||
~PhysicalHeap() override;
|
~PhysicalHeap() override;
|
||||||
|
|
||||||
|
// Initializes the heap properties and allocates the page table.
|
||||||
void Initialize(uint8_t* membase, uint32_t heap_base, uint32_t heap_size,
|
void Initialize(uint8_t* membase, uint32_t heap_base, uint32_t heap_size,
|
||||||
uint32_t page_size, VirtualHeap* parent_heap);
|
uint32_t page_size, VirtualHeap* parent_heap);
|
||||||
|
|
||||||
|
@ -152,16 +202,40 @@ class PhysicalHeap : public BaseHeap {
|
||||||
VirtualHeap* parent_heap_;
|
VirtualHeap* parent_heap_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Models the entire guest memory system on the console.
|
||||||
|
// This exposes interfaces to both virtual and physical memory and a TLB and
|
||||||
|
// page table for allocation, mapping, and protection.
|
||||||
|
//
|
||||||
|
// The memory is backed by a memory mapped file and is placed at a stable
|
||||||
|
// fixed address in the host address space (like 0x100000000). This allows
|
||||||
|
// efficient guest<->host address translations as well as easy sharing of the
|
||||||
|
// memory across various subsystems.
|
||||||
|
//
|
||||||
|
// The guest memory address space is split into several ranges that have varying
|
||||||
|
// properties such as page sizes, caching strategies, protections, and
|
||||||
|
// overlap with other ranges. Each range is represented by a BaseHeap of either
|
||||||
|
// VirtualHeap or PhysicalHeap depending on type. Heaps model the page tables
|
||||||
|
// and can handle reservation and committing of requested pages.
|
||||||
class Memory {
|
class Memory {
|
||||||
public:
|
public:
|
||||||
Memory();
|
Memory();
|
||||||
~Memory();
|
~Memory();
|
||||||
|
|
||||||
int Initialize();
|
// Initializes the memory system.
|
||||||
|
// This may fail if the host address space could not be reserved or the
|
||||||
|
// mapping to the file system fails.
|
||||||
|
bool Initialize();
|
||||||
|
|
||||||
|
// Full file name and path of the memory-mapped file backing all memory.
|
||||||
const std::wstring& file_name() const { return file_name_; }
|
const std::wstring& file_name() const { return file_name_; }
|
||||||
|
|
||||||
|
// Base address of virtual memory in the host address space.
|
||||||
|
// This is often something like 0x100000000.
|
||||||
inline uint8_t* virtual_membase() const { return virtual_membase_; }
|
inline uint8_t* virtual_membase() const { return virtual_membase_; }
|
||||||
|
|
||||||
|
// Translates a guest virtual address to a host address that can be accessed
|
||||||
|
// as a normal pointer.
|
||||||
|
// Note that the contents at the specified host address are big-endian.
|
||||||
inline uint8_t* TranslateVirtual(uint32_t guest_address) const {
|
inline uint8_t* TranslateVirtual(uint32_t guest_address) const {
|
||||||
return virtual_membase_ + guest_address;
|
return virtual_membase_ + guest_address;
|
||||||
}
|
}
|
||||||
|
@ -170,7 +244,13 @@ class Memory {
|
||||||
return reinterpret_cast<T>(virtual_membase_ + guest_address);
|
return reinterpret_cast<T>(virtual_membase_ + guest_address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Base address of physical memory in the host address space.
|
||||||
|
// This is often something like 0x200000000.
|
||||||
inline uint8_t* physical_membase() const { return physical_membase_; }
|
inline uint8_t* physical_membase() const { return physical_membase_; }
|
||||||
|
|
||||||
|
// Translates a guest physical address to a host address that can be accessed
|
||||||
|
// as a normal pointer.
|
||||||
|
// Note that the contents at the specified host address are big-endian.
|
||||||
inline uint8_t* TranslatePhysical(uint32_t guest_address) const {
|
inline uint8_t* TranslatePhysical(uint32_t guest_address) const {
|
||||||
return physical_membase_ + (guest_address & 0x1FFFFFFF);
|
return physical_membase_ + (guest_address & 0x1FFFFFFF);
|
||||||
}
|
}
|
||||||
|
@ -179,32 +259,62 @@ class Memory {
|
||||||
return reinterpret_cast<T>(physical_membase_ +
|
return reinterpret_cast<T>(physical_membase_ +
|
||||||
(guest_address & 0x1FFFFFFF));
|
(guest_address & 0x1FFFFFFF));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(benvanik): make poly memory utils for these.
|
// Zeros out a range of memory at the given guest address.
|
||||||
void Zero(uint32_t address, uint32_t size);
|
void Zero(uint32_t address, uint32_t size);
|
||||||
|
|
||||||
|
// Fills a range of guest memory with the given byte value.
|
||||||
void Fill(uint32_t address, uint32_t size, uint8_t value);
|
void Fill(uint32_t address, uint32_t size, uint8_t value);
|
||||||
|
|
||||||
|
// Copies a non-overlapping range of guest memory (like a memcpy).
|
||||||
void Copy(uint32_t dest, uint32_t src, uint32_t size);
|
void Copy(uint32_t dest, uint32_t src, uint32_t size);
|
||||||
|
|
||||||
|
// Searches the given range of guest memory for a run of dword values in
|
||||||
|
// big-endian order.
|
||||||
uint32_t SearchAligned(uint32_t start, uint32_t end, const uint32_t* values,
|
uint32_t SearchAligned(uint32_t start, uint32_t end, const uint32_t* values,
|
||||||
size_t value_count);
|
size_t value_count);
|
||||||
|
|
||||||
|
// Defines a memory-mapped IO (MMIO) virtual address range that when accessed
|
||||||
|
// will trigger the specified read and write callbacks for dword read/writes.
|
||||||
bool AddVirtualMappedRange(uint32_t virtual_address, uint32_t mask,
|
bool AddVirtualMappedRange(uint32_t virtual_address, uint32_t mask,
|
||||||
uint32_t size, void* context,
|
uint32_t size, void* context,
|
||||||
cpu::MMIOReadCallback read_callback,
|
cpu::MMIOReadCallback read_callback,
|
||||||
cpu::MMIOWriteCallback write_callback);
|
cpu::MMIOWriteCallback write_callback);
|
||||||
|
|
||||||
|
// Gets the defined MMIO range for the given virtual address, if any.
|
||||||
cpu::MMIORange* LookupVirtualMappedRange(uint32_t virtual_address);
|
cpu::MMIORange* LookupVirtualMappedRange(uint32_t virtual_address);
|
||||||
|
|
||||||
|
// Adds a write watch for the given physical address range that will trigger
|
||||||
|
// the specified callback whenever any bytes are written in that range.
|
||||||
|
// The returned handle can be used with CancelWriteWatch to remove the watch
|
||||||
|
// if it is no longer required.
|
||||||
|
//
|
||||||
|
// This has a significant performance penalty for writes in in the range or
|
||||||
|
// nearby (sharing 64KiB pages).
|
||||||
uintptr_t AddPhysicalWriteWatch(uint32_t physical_address, uint32_t length,
|
uintptr_t AddPhysicalWriteWatch(uint32_t physical_address, uint32_t length,
|
||||||
cpu::WriteWatchCallback callback,
|
cpu::WriteWatchCallback callback,
|
||||||
void* callback_context, void* callback_data);
|
void* callback_context, void* callback_data);
|
||||||
|
|
||||||
|
// Cancels a write watch requested with AddPhysicalWriteWatch.
|
||||||
void CancelWriteWatch(uintptr_t watch_handle);
|
void CancelWriteWatch(uintptr_t watch_handle);
|
||||||
|
|
||||||
|
// Allocates virtual memory from the 'system' heap.
|
||||||
|
// System memory is kept separate from game memory but is still accessible
|
||||||
|
// using normal guest virtual addresses. Kernel structures and other internal
|
||||||
|
// 'system' allocations should come from this heap when possible.
|
||||||
uint32_t SystemHeapAlloc(uint32_t size, uint32_t alignment = 0x20,
|
uint32_t SystemHeapAlloc(uint32_t size, uint32_t alignment = 0x20,
|
||||||
uint32_t system_heap_flags = kSystemHeapDefault);
|
uint32_t system_heap_flags = kSystemHeapDefault);
|
||||||
|
|
||||||
|
// Frees memory allocated with SystemHeapAlloc.
|
||||||
void SystemHeapFree(uint32_t address);
|
void SystemHeapFree(uint32_t address);
|
||||||
|
|
||||||
|
// Gets the heap for the address space containing the given address.
|
||||||
BaseHeap* LookupHeap(uint32_t address);
|
BaseHeap* LookupHeap(uint32_t address);
|
||||||
|
|
||||||
|
// Gets the heap with the given properties.
|
||||||
BaseHeap* LookupHeapByType(bool physical, uint32_t page_size);
|
BaseHeap* LookupHeapByType(bool physical, uint32_t page_size);
|
||||||
|
|
||||||
|
// Dumps a map of all allocated memory to the log.
|
||||||
void DumpMap();
|
void DumpMap();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in New Issue