Merge pull request #28 from bunnei/shared-memory
Shared memory - adds preliminary support for shared memory kernel objects and correct block mapping.
This commit is contained in:
commit
6084084a5d
|
@ -38,6 +38,7 @@ set(SRCS core.cpp
|
||||||
hle/kernel/event.cpp
|
hle/kernel/event.cpp
|
||||||
hle/kernel/kernel.cpp
|
hle/kernel/kernel.cpp
|
||||||
hle/kernel/mutex.cpp
|
hle/kernel/mutex.cpp
|
||||||
|
hle/kernel/shared_memory.cpp
|
||||||
hle/kernel/thread.cpp
|
hle/kernel/thread.cpp
|
||||||
hle/service/apt.cpp
|
hle/service/apt.cpp
|
||||||
hle/service/fs.cpp
|
hle/service/fs.cpp
|
||||||
|
@ -85,6 +86,7 @@ set(HEADERS core.h
|
||||||
hle/kernel/archive.h
|
hle/kernel/archive.h
|
||||||
hle/kernel/kernel.h
|
hle/kernel/kernel.h
|
||||||
hle/kernel/mutex.h
|
hle/kernel/mutex.h
|
||||||
|
hle/kernel/shared_memory.h
|
||||||
hle/kernel/thread.h
|
hle/kernel/thread.h
|
||||||
hle/function_wrappers.h
|
hle/function_wrappers.h
|
||||||
hle/service/apt.h
|
hle/service/apt.h
|
||||||
|
|
|
@ -170,6 +170,7 @@
|
||||||
<ClCompile Include="hle\kernel\event.cpp" />
|
<ClCompile Include="hle\kernel\event.cpp" />
|
||||||
<ClCompile Include="hle\kernel\kernel.cpp" />
|
<ClCompile Include="hle\kernel\kernel.cpp" />
|
||||||
<ClCompile Include="hle\kernel\mutex.cpp" />
|
<ClCompile Include="hle\kernel\mutex.cpp" />
|
||||||
|
<ClCompile Include="hle\kernel\shared_memory.cpp" />
|
||||||
<ClCompile Include="hle\kernel\thread.cpp" />
|
<ClCompile Include="hle\kernel\thread.cpp" />
|
||||||
<ClCompile Include="hle\service\apt.cpp" />
|
<ClCompile Include="hle\service\apt.cpp" />
|
||||||
<ClCompile Include="hle\service\fs.cpp" />
|
<ClCompile Include="hle\service\fs.cpp" />
|
||||||
|
@ -222,6 +223,7 @@
|
||||||
<ClInclude Include="hle\kernel\event.h" />
|
<ClInclude Include="hle\kernel\event.h" />
|
||||||
<ClInclude Include="hle\kernel\kernel.h" />
|
<ClInclude Include="hle\kernel\kernel.h" />
|
||||||
<ClInclude Include="hle\kernel\mutex.h" />
|
<ClInclude Include="hle\kernel\mutex.h" />
|
||||||
|
<ClInclude Include="hle\kernel\shared_memory.h" />
|
||||||
<ClInclude Include="hle\kernel\thread.h" />
|
<ClInclude Include="hle\kernel\thread.h" />
|
||||||
<ClInclude Include="hle\service\apt.h" />
|
<ClInclude Include="hle\service\apt.h" />
|
||||||
<ClInclude Include="hle\service\fs.h" />
|
<ClInclude Include="hle\service\fs.h" />
|
||||||
|
|
|
@ -179,6 +179,9 @@
|
||||||
<ClCompile Include="file_sys\archive_romfs.cpp">
|
<ClCompile Include="file_sys\archive_romfs.cpp">
|
||||||
<Filter>file_sys</Filter>
|
<Filter>file_sys</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="hle\kernel\shared_memory.cpp">
|
||||||
|
<Filter>hle\kernel</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="arm\disassembler\arm_disasm.h">
|
<ClInclude Include="arm\disassembler\arm_disasm.h">
|
||||||
|
@ -320,6 +323,9 @@
|
||||||
<ClInclude Include="file_sys\archive_romfs.h">
|
<ClInclude Include="file_sys\archive_romfs.h">
|
||||||
<Filter>file_sys</Filter>
|
<Filter>file_sys</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="hle\kernel\shared_memory.h">
|
||||||
|
<Filter>hle\kernel</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Text Include="CMakeLists.txt" />
|
<Text Include="CMakeLists.txt" />
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
// Copyright 2014 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "common/common.h"
|
||||||
|
|
||||||
|
#include "core/mem_map.h"
|
||||||
|
#include "core/hle/kernel/shared_memory.h"
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
|
||||||
|
class SharedMemory : public Object {
|
||||||
|
public:
|
||||||
|
const char* GetTypeName() const { return "SharedMemory"; }
|
||||||
|
|
||||||
|
static Kernel::HandleType GetStaticHandleType() { return Kernel::HandleType::SharedMemory; }
|
||||||
|
Kernel::HandleType GetHandleType() const { return Kernel::HandleType::SharedMemory; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for kernel object to synchronize
|
||||||
|
* @param wait Boolean wait set if current thread should wait as a result of sync operation
|
||||||
|
* @return Result of operation, 0 on success, otherwise error code
|
||||||
|
*/
|
||||||
|
Result WaitSynchronization(bool* wait) {
|
||||||
|
// TODO(bunnei): ImplementMe
|
||||||
|
ERROR_LOG(OSHLE, "(UNIMPLEMENTED)");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 base_address; ///< Address of shared memory block in RAM
|
||||||
|
MemoryPermission permissions; ///< Permissions of shared memory block (SVC field)
|
||||||
|
MemoryPermission other_permissions; ///< Other permissions of shared memory block (SVC field)
|
||||||
|
std::string name; ///< Name of shared memory object (optional)
|
||||||
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a shared memory object
|
||||||
|
* @param handle Handle of newly created shared memory object
|
||||||
|
* @param name Name of shared memory object
|
||||||
|
* @return Pointer to newly created shared memory object
|
||||||
|
*/
|
||||||
|
SharedMemory* CreateSharedMemory(Handle& handle, const std::string& name) {
|
||||||
|
SharedMemory* shared_memory = new SharedMemory;
|
||||||
|
handle = Kernel::g_object_pool.Create(shared_memory);
|
||||||
|
shared_memory->name = name;
|
||||||
|
return shared_memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a shared memory object
|
||||||
|
* @param name Optional name of shared memory object
|
||||||
|
* @return Handle of newly created shared memory object
|
||||||
|
*/
|
||||||
|
Handle CreateSharedMemory(const std::string& name) {
|
||||||
|
Handle handle;
|
||||||
|
CreateSharedMemory(handle, name);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps a shared memory block to an address in system memory
|
||||||
|
* @param handle Shared memory block handle
|
||||||
|
* @param address Address in system memory to map shared memory block to
|
||||||
|
* @param permissions Memory block map permissions (specified by SVC field)
|
||||||
|
* @param other_permissions Memory block map other permissions (specified by SVC field)
|
||||||
|
* @return Result of operation, 0 on success, otherwise error code
|
||||||
|
*/
|
||||||
|
Result MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions,
|
||||||
|
MemoryPermission other_permissions) {
|
||||||
|
|
||||||
|
if (address < Memory::SHARED_MEMORY_VADDR || address >= Memory::SHARED_MEMORY_VADDR_END) {
|
||||||
|
ERROR_LOG(KERNEL, "cannot map handle=0x%08X, address=0x%08X outside of shared mem bounds!",
|
||||||
|
handle);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
SharedMemory* shared_memory = Kernel::g_object_pool.GetFast<SharedMemory>(handle);
|
||||||
|
_assert_msg_(KERNEL, (shared_memory != nullptr), "handle 0x%08X is not valid!", handle);
|
||||||
|
|
||||||
|
shared_memory->base_address = address;
|
||||||
|
shared_memory->permissions = permissions;
|
||||||
|
shared_memory->other_permissions = other_permissions;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a pointer to the shared memory block
|
||||||
|
* @param handle Shared memory block handle
|
||||||
|
* @param offset Offset from the start of the shared memory block to get pointer
|
||||||
|
* @return Pointer to the shared memory block from the specified offset
|
||||||
|
*/
|
||||||
|
u8* GetSharedMemoryPointer(Handle handle, u32 offset) {
|
||||||
|
SharedMemory* shared_memory = Kernel::g_object_pool.GetFast<SharedMemory>(handle);
|
||||||
|
_assert_msg_(KERNEL, (shared_memory != nullptr), "handle 0x%08X is not valid!", handle);
|
||||||
|
|
||||||
|
if (0 != shared_memory->base_address)
|
||||||
|
return Memory::GetPointer(shared_memory->base_address + offset);
|
||||||
|
|
||||||
|
ERROR_LOG(KERNEL, "memory block handle=0x%08X not mapped!", handle);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
|
@ -0,0 +1,48 @@
|
||||||
|
// Copyright 2014 Citra Emulator Project
|
||||||
|
// Licensed under GPLv2
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
#include "core/hle/kernel/kernel.h"
|
||||||
|
|
||||||
|
namespace Kernel {
|
||||||
|
|
||||||
|
/// Permissions for mapped shared memory blocks
|
||||||
|
enum class MemoryPermission : u32 {
|
||||||
|
None = 0,
|
||||||
|
Read = (1u << 0),
|
||||||
|
Write = (1u << 1),
|
||||||
|
ReadWrite = (Read | Write),
|
||||||
|
DontCare = (1u << 28)
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a shared memory object
|
||||||
|
* @param name Optional name of shared memory object
|
||||||
|
* @return Handle of newly created shared memory object
|
||||||
|
*/
|
||||||
|
Handle CreateSharedMemory(const std::string& name="Unknown");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps a shared memory block to an address in system memory
|
||||||
|
* @param handle Shared memory block handle
|
||||||
|
* @param address Address in system memory to map shared memory block to
|
||||||
|
* @param permissions Memory block map permissions (specified by SVC field)
|
||||||
|
* @param other_permissions Memory block map other permissions (specified by SVC field)
|
||||||
|
* @return Result of operation, 0 on success, otherwise error code
|
||||||
|
*/
|
||||||
|
Result MapSharedMemory(u32 handle, u32 address, MemoryPermission permissions,
|
||||||
|
MemoryPermission other_permissions);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a pointer to the shared memory block
|
||||||
|
* @param handle Shared memory block handle
|
||||||
|
* @param offset Offset from the start of the shared memory block to get pointer
|
||||||
|
* @return Pointer to the shared memory block from the specified offset
|
||||||
|
*/
|
||||||
|
u8* GetSharedMemoryPointer(Handle handle, u32 offset);
|
||||||
|
|
||||||
|
} // namespace
|
|
@ -9,6 +9,7 @@
|
||||||
#include "core/mem_map.h"
|
#include "core/mem_map.h"
|
||||||
#include "core/hle/hle.h"
|
#include "core/hle/hle.h"
|
||||||
#include "core/hle/kernel/event.h"
|
#include "core/hle/kernel/event.h"
|
||||||
|
#include "core/hle/kernel/shared_memory.h"
|
||||||
#include "core/hle/service/gsp.h"
|
#include "core/hle/service/gsp.h"
|
||||||
|
|
||||||
#include "core/hw/gpu.h"
|
#include "core/hw/gpu.h"
|
||||||
|
@ -36,14 +37,24 @@ union GX_CmdBufferHeader {
|
||||||
BitField<8,8,u32> number_commands;
|
BitField<8,8,u32> number_commands;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Gets the address of the start (header) of a command buffer in GSP shared memory
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
static inline u32 GX_GetCmdBufferAddress(u32 thread_id) {
|
// Namespace GSP_GPU
|
||||||
return (0x10002000 + 0x800 + (thread_id * 0x200));
|
|
||||||
}
|
namespace GSP_GPU {
|
||||||
|
|
||||||
|
Handle g_event = 0;
|
||||||
|
Handle g_shared_memory = 0;
|
||||||
|
|
||||||
|
u32 g_thread_id = 0;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
REG_FRAMEBUFFER_1 = 0x00400468,
|
||||||
|
REG_FRAMEBUFFER_2 = 0x00400494,
|
||||||
|
};
|
||||||
|
|
||||||
/// Gets a pointer to the start (header) of a command buffer in GSP shared memory
|
/// Gets a pointer to the start (header) of a command buffer in GSP shared memory
|
||||||
static inline u8* GX_GetCmdBufferPointer(u32 thread_id, u32 offset=0) {
|
static inline u8* GX_GetCmdBufferPointer(u32 thread_id, u32 offset=0) {
|
||||||
return Memory::GetPointer(GX_GetCmdBufferAddress(thread_id) + offset);
|
return Kernel::GetSharedMemoryPointer(g_shared_memory, 0x800 + (thread_id * 0x200) + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finishes execution of a GSP command
|
/// Finishes execution of a GSP command
|
||||||
|
@ -56,19 +67,6 @@ void GX_FinishCommand(u32 thread_id) {
|
||||||
// TODO: Increment header->index?
|
// TODO: Increment header->index?
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
// Namespace GSP_GPU
|
|
||||||
|
|
||||||
namespace GSP_GPU {
|
|
||||||
|
|
||||||
Handle g_event_handle = 0;
|
|
||||||
u32 g_thread_id = 0;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
REG_FRAMEBUFFER_1 = 0x00400468,
|
|
||||||
REG_FRAMEBUFFER_2 = 0x00400494,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Read a GSP GPU hardware register
|
/// Read a GSP GPU hardware register
|
||||||
void ReadHWRegs(Service::Interface* self) {
|
void ReadHWRegs(Service::Interface* self) {
|
||||||
static const u32 framebuffer_1[] = {GPU::PADDR_VRAM_TOP_LEFT_FRAME1, GPU::PADDR_VRAM_TOP_RIGHT_FRAME1};
|
static const u32 framebuffer_1[] = {GPU::PADDR_VRAM_TOP_LEFT_FRAME1, GPU::PADDR_VRAM_TOP_RIGHT_FRAME1};
|
||||||
|
@ -103,24 +101,34 @@ void ReadHWRegs(Service::Interface* self) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GSP_GPU::RegisterInterruptRelayQueue service function
|
||||||
|
* Inputs:
|
||||||
|
* 1 : "Flags" field, purpose is unknown
|
||||||
|
* 3 : Handle to GSP synchronization event
|
||||||
|
* Outputs:
|
||||||
|
* 0 : Result of function, 0 on success, otherwise error code
|
||||||
|
* 2 : Thread index into GSP command buffer
|
||||||
|
* 4 : Handle to GSP shared memory
|
||||||
|
*/
|
||||||
void RegisterInterruptRelayQueue(Service::Interface* self) {
|
void RegisterInterruptRelayQueue(Service::Interface* self) {
|
||||||
u32* cmd_buff = Service::GetCommandBuffer();
|
u32* cmd_buff = Service::GetCommandBuffer();
|
||||||
u32 flags = cmd_buff[1];
|
u32 flags = cmd_buff[1];
|
||||||
u32 event_handle = cmd_buff[3];
|
g_event = cmd_buff[3];
|
||||||
|
|
||||||
_assert_msg_(GSP, (event_handle != 0), "called, but event is nullptr!");
|
_assert_msg_(GSP, (g_event != 0), "handle is not valid!");
|
||||||
|
|
||||||
g_event_handle = event_handle;
|
Kernel::SetEventLocked(g_event, false);
|
||||||
|
|
||||||
Kernel::SetEventLocked(event_handle, false);
|
|
||||||
|
|
||||||
// Hack - This function will permanently set the state of the GSP event such that GPU command
|
// Hack - This function will permanently set the state of the GSP event such that GPU command
|
||||||
// synchronization barriers always passthrough. Correct solution would be to set this after the
|
// synchronization barriers always passthrough. Correct solution would be to set this after the
|
||||||
// GPU as processed all queued up commands, but due to the emulator being single-threaded they
|
// GPU as processed all queued up commands, but due to the emulator being single-threaded they
|
||||||
// will always be ready.
|
// will always be ready.
|
||||||
Kernel::SetPermanentLock(event_handle, true);
|
Kernel::SetPermanentLock(g_event, true);
|
||||||
|
|
||||||
|
cmd_buff[0] = 0; // Result - no error
|
||||||
cmd_buff[2] = g_thread_id; // ThreadID
|
cmd_buff[2] = g_thread_id; // ThreadID
|
||||||
|
cmd_buff[4] = g_shared_memory; // GSP shared memory
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -208,6 +216,7 @@ const Interface::FunctionInfo FunctionTable[] = {
|
||||||
|
|
||||||
Interface::Interface() {
|
Interface::Interface() {
|
||||||
Register(FunctionTable, ARRAY_SIZE(FunctionTable));
|
Register(FunctionTable, ARRAY_SIZE(FunctionTable));
|
||||||
|
g_shared_memory = Kernel::CreateSharedMemory("GSPSharedMem");
|
||||||
}
|
}
|
||||||
|
|
||||||
Interface::~Interface() {
|
Interface::~Interface() {
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "core/hle/kernel/event.h"
|
#include "core/hle/kernel/event.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
#include "core/hle/kernel/mutex.h"
|
#include "core/hle/kernel/mutex.h"
|
||||||
|
#include "core/hle/kernel/shared_memory.h"
|
||||||
#include "core/hle/kernel/thread.h"
|
#include "core/hle/kernel/thread.h"
|
||||||
|
|
||||||
#include "core/hle/function_wrappers.h"
|
#include "core/hle/function_wrappers.h"
|
||||||
|
@ -28,11 +29,6 @@ enum ControlMemoryOperation {
|
||||||
MEMORY_OPERATION_GSP_HEAP = 0x00010003,
|
MEMORY_OPERATION_GSP_HEAP = 0x00010003,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum MapMemoryPermission {
|
|
||||||
MEMORY_PERMISSION_UNMAP = 0x00000000,
|
|
||||||
MEMORY_PERMISSION_NORMAL = 0x00000001,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Map application or GSP heap memory
|
/// Map application or GSP heap memory
|
||||||
Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) {
|
Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 size, u32 permissions) {
|
||||||
DEBUG_LOG(SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X",
|
DEBUG_LOG(SVC,"called operation=0x%08X, addr0=0x%08X, addr1=0x%08X, size=%08X, permissions=0x%08X",
|
||||||
|
@ -58,17 +54,21 @@ Result ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 addr1, u32 siz
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Maps a memory block to specified address
|
/// Maps a memory block to specified address
|
||||||
Result MapMemoryBlock(Handle memblock, u32 addr, u32 mypermissions, u32 otherpermission) {
|
Result MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 other_permissions) {
|
||||||
DEBUG_LOG(SVC, "called memblock=0x08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d",
|
DEBUG_LOG(SVC, "called memblock=0x08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d",
|
||||||
memblock, addr, mypermissions, otherpermission);
|
handle, addr, permissions, other_permissions);
|
||||||
switch (mypermissions) {
|
|
||||||
case MEMORY_PERMISSION_NORMAL:
|
Kernel::MemoryPermission permissions_type = static_cast<Kernel::MemoryPermission>(permissions);
|
||||||
case MEMORY_PERMISSION_NORMAL + 1:
|
switch (permissions_type) {
|
||||||
case MEMORY_PERMISSION_NORMAL + 2:
|
case Kernel::MemoryPermission::Read:
|
||||||
Memory::MapBlock_Shared(memblock, addr, mypermissions);
|
case Kernel::MemoryPermission::Write:
|
||||||
|
case Kernel::MemoryPermission::ReadWrite:
|
||||||
|
case Kernel::MemoryPermission::DontCare:
|
||||||
|
Kernel::MapSharedMemory(handle, addr, permissions_type,
|
||||||
|
static_cast<Kernel::MemoryPermission>(other_permissions));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ERROR_LOG(OSHLE, "unknown permissions=0x%08X", mypermissions);
|
ERROR_LOG(OSHLE, "unknown permissions=0x%08X", permissions);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,6 +128,12 @@ extern u8* g_exefs_code; ///< ExeFS:/.code is loaded here
|
||||||
void Init();
|
void Init();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline void Read(T &var, const u32 addr);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline void Write(u32 addr, const T data);
|
||||||
|
|
||||||
u8 Read8(const u32 addr);
|
u8 Read8(const u32 addr);
|
||||||
u16 Read16(const u32 addr);
|
u16 Read16(const u32 addr);
|
||||||
u32 Read32(const u32 addr);
|
u32 Read32(const u32 addr);
|
||||||
|
@ -143,14 +149,6 @@ void WriteBlock(const u32 addr, const u8* data, const int size);
|
||||||
|
|
||||||
u8* GetPointer(const u32 Address);
|
u8* GetPointer(const u32 Address);
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps a block of memory in shared memory
|
|
||||||
* @param handle Handle to map memory block for
|
|
||||||
* @param addr Address to map memory block to
|
|
||||||
* @param permissions Memory map permissions
|
|
||||||
*/
|
|
||||||
u32 MapBlock_Shared(u32 handle, u32 addr,u32 permissions) ;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps a block of memory on the heap
|
* Maps a block of memory on the heap
|
||||||
* @param size Size of block in bytes
|
* @param size Size of block in bytes
|
||||||
|
|
|
@ -41,7 +41,7 @@ u32 _VirtualAddress(const u32 addr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline void _Read(T &var, const u32 addr) {
|
inline void Read(T &var, const u32 addr) {
|
||||||
// TODO: Figure out the fastest order of tests for both read and write (they are probably different).
|
// TODO: Figure out the fastest order of tests for both read and write (they are probably different).
|
||||||
// TODO: Make sure this represents the mirrors in a correct way.
|
// TODO: Make sure this represents the mirrors in a correct way.
|
||||||
// Could just do a base-relative read, too.... TODO
|
// Could just do a base-relative read, too.... TODO
|
||||||
|
@ -91,7 +91,7 @@ inline void _Read(T &var, const u32 addr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline void _Write(u32 addr, const T data) {
|
inline void Write(u32 addr, const T data) {
|
||||||
u32 vaddr = _VirtualAddress(addr);
|
u32 vaddr = _VirtualAddress(addr);
|
||||||
|
|
||||||
// Kernel memory command buffer
|
// Kernel memory command buffer
|
||||||
|
@ -177,28 +177,6 @@ u8 *GetPointer(const u32 addr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps a block of memory in shared memory
|
|
||||||
* @param handle Handle to map memory block for
|
|
||||||
* @param addr Address to map memory block to
|
|
||||||
* @param permissions Memory map permissions
|
|
||||||
*/
|
|
||||||
u32 MapBlock_Shared(u32 handle, u32 addr,u32 permissions) {
|
|
||||||
MemoryBlock block;
|
|
||||||
|
|
||||||
block.handle = handle;
|
|
||||||
block.base_address = addr;
|
|
||||||
block.permissions = permissions;
|
|
||||||
|
|
||||||
if (g_shared_map.size() > 0) {
|
|
||||||
const MemoryBlock last_block = g_shared_map.rbegin()->second;
|
|
||||||
block.address = last_block.address + last_block.size;
|
|
||||||
}
|
|
||||||
g_shared_map[block.GetVirtualAddress()] = block;
|
|
||||||
|
|
||||||
return block.GetVirtualAddress();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps a block of memory on the heap
|
* Maps a block of memory on the heap
|
||||||
* @param size Size of block in bytes
|
* @param size Size of block in bytes
|
||||||
|
@ -247,25 +225,25 @@ u32 MapBlock_HeapGSP(u32 size, u32 operation, u32 permissions) {
|
||||||
|
|
||||||
u8 Read8(const u32 addr) {
|
u8 Read8(const u32 addr) {
|
||||||
u8 _var = 0;
|
u8 _var = 0;
|
||||||
_Read<u8>(_var, addr);
|
Read<u8>(_var, addr);
|
||||||
return (u8)_var;
|
return (u8)_var;
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 Read16(const u32 addr) {
|
u16 Read16(const u32 addr) {
|
||||||
u16_le _var = 0;
|
u16_le _var = 0;
|
||||||
_Read<u16_le>(_var, addr);
|
Read<u16_le>(_var, addr);
|
||||||
return (u16)_var;
|
return (u16)_var;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Read32(const u32 addr) {
|
u32 Read32(const u32 addr) {
|
||||||
u32_le _var = 0;
|
u32_le _var = 0;
|
||||||
_Read<u32_le>(_var, addr);
|
Read<u32_le>(_var, addr);
|
||||||
return _var;
|
return _var;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 Read64(const u32 addr) {
|
u64 Read64(const u32 addr) {
|
||||||
u64_le _var = 0;
|
u64_le _var = 0;
|
||||||
_Read<u64_le>(_var, addr);
|
Read<u64_le>(_var, addr);
|
||||||
return _var;
|
return _var;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,19 +256,19 @@ u32 Read16_ZX(const u32 addr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write8(const u32 addr, const u8 data) {
|
void Write8(const u32 addr, const u8 data) {
|
||||||
_Write<u8>(addr, data);
|
Write<u8>(addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write16(const u32 addr, const u16 data) {
|
void Write16(const u32 addr, const u16 data) {
|
||||||
_Write<u16_le>(addr, data);
|
Write<u16_le>(addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write32(const u32 addr, const u32 data) {
|
void Write32(const u32 addr, const u32 data) {
|
||||||
_Write<u32_le>(addr, data);
|
Write<u32_le>(addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Write64(const u32 addr, const u64 data) {
|
void Write64(const u32 addr, const u64 data) {
|
||||||
_Write<u64_le>(addr, data);
|
Write<u64_le>(addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteBlock(const u32 addr, const u8* data, const int size) {
|
void WriteBlock(const u32 addr, const u8* data, const int size) {
|
||||||
|
|
Reference in New Issue