Merge pull request #52 from elisha464/master

More memory mapping functions
This commit is contained in:
DHrpcs3 2014-01-21 13:28:55 -08:00
commit cf740f5129
4 changed files with 203 additions and 89 deletions

View File

@ -543,7 +543,7 @@ VirtualMemoryBlock::VirtualMemoryBlock() : MemoryBlock()
bool VirtualMemoryBlock::IsInMyRange(const u64 addr) bool VirtualMemoryBlock::IsInMyRange(const u64 addr)
{ {
return addr >= GetStartAddr() && addr < GetStartAddr() + GetSize(); return addr >= GetStartAddr() && addr < GetStartAddr() + GetSize() - GetResevedAmount();
} }
bool VirtualMemoryBlock::IsInMyRange(const u64 addr, const u32 size) bool VirtualMemoryBlock::IsInMyRange(const u64 addr, const u32 size)
@ -576,10 +576,11 @@ u64 VirtualMemoryBlock::Map(u64 realaddr, u32 size, u64 addr)
} }
else else
{ {
for(u64 addr = GetStartAddr(); addr <= GetEndAddr() - size;) for(u64 addr = GetStartAddr(); addr <= GetEndAddr() - GetResevedAmount() - size;)
{ {
bool is_good_addr = true; bool is_good_addr = true;
// check if address is already mapped
for(u32 i=0; i<m_mapped_memory.GetCount(); ++i) for(u32 i=0; i<m_mapped_memory.GetCount(); ++i)
{ {
if((addr >= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size) || if((addr >= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size) ||
@ -602,32 +603,34 @@ u64 VirtualMemoryBlock::Map(u64 realaddr, u32 size, u64 addr)
} }
} }
bool VirtualMemoryBlock::UnmapRealAddress(u64 realaddr) u32 VirtualMemoryBlock::UnmapRealAddress(u64 realaddr)
{ {
for(u32 i=0; i<m_mapped_memory.GetCount(); ++i) for(u32 i=0; i<m_mapped_memory.GetCount(); ++i)
{ {
if(m_mapped_memory[i].realAddress == realaddr) if(m_mapped_memory[i].realAddress == realaddr && IsInMyRange(m_mapped_memory[i].addr, m_mapped_memory[i].size))
{ {
u32 size = m_mapped_memory[i].size;
m_mapped_memory.RemoveAt(i); m_mapped_memory.RemoveAt(i);
return true; return size;
} }
} }
return false; return 0;
} }
bool VirtualMemoryBlock::UnmapAddress(u64 addr) u32 VirtualMemoryBlock::UnmapAddress(u64 addr)
{ {
for(u32 i=0; i<m_mapped_memory.GetCount(); ++i) for(u32 i=0; i<m_mapped_memory.GetCount(); ++i)
{ {
if(m_mapped_memory[i].addr == addr) if(m_mapped_memory[i].addr == addr && IsInMyRange(m_mapped_memory[i].addr, m_mapped_memory[i].size))
{ {
u32 size = m_mapped_memory[i].size;
m_mapped_memory.RemoveAt(i); m_mapped_memory.RemoveAt(i);
return true; return size;
} }
} }
return false; return 0;
} }
bool VirtualMemoryBlock::Read8(const u64 addr, u8* value) bool VirtualMemoryBlock::Read8(const u64 addr, u8* value)
@ -731,4 +734,27 @@ void VirtualMemoryBlock::Delete()
m_mapped_memory.Clear(); m_mapped_memory.Clear();
MemoryBlock::Delete(); MemoryBlock::Delete();
}
bool VirtualMemoryBlock::Reserve(u32 size)
{
if(size + GetResevedAmount() > GetEndAddr() - GetStartAddr())
return false;
m_reserve_size += size;
return true;
}
bool VirtualMemoryBlock::Unreserve(u32 size)
{
if(size > GetResevedAmount())
return false;
m_reserve_size -= size;
return true;
}
u32 VirtualMemoryBlock::GetResevedAmount()
{
return m_reserve_size;
} }

View File

@ -226,6 +226,7 @@ private:
class VirtualMemoryBlock : public MemoryBlock class VirtualMemoryBlock : public MemoryBlock
{ {
Array<VirtualMemInfo> m_mapped_memory; Array<VirtualMemInfo> m_mapped_memory;
u32 m_reserve_size;
public: public:
VirtualMemoryBlock(); VirtualMemoryBlock();
@ -239,11 +240,20 @@ public:
// first mappable space is used) // first mappable space is used)
virtual u64 Map(u64 realaddr, u32 size, u64 addr = 0); virtual u64 Map(u64 realaddr, u32 size, u64 addr = 0);
// Unmap real address (please specify only starting point, no midway memory will be unmapped) // Unmap real address (please specify only starting point, no midway memory will be unmapped), returns the size of the unmapped area
virtual bool UnmapRealAddress(u64 realaddr); virtual u32 UnmapRealAddress(u64 realaddr);
// Unmap address (please specify only starting point, no midway memory will be unmapped) // Unmap address (please specify only starting point, no midway memory will be unmapped), returns the size of the unmapped area
virtual bool UnmapAddress(u64 addr); virtual u32 UnmapAddress(u64 addr);
// Reserve a certain amount so no one can use it, returns true on succces, false on failure
virtual bool Reserve(u32 size);
// Unreserve a certain amount of bytes, returns true on succcess, false if size is bigger than the reserved amount
virtual bool Unreserve(u32 size);
// Return the total amount of reserved memory
virtual u32 GetResevedAmount();
virtual bool Read8(const u64 addr, u8* value); virtual bool Read8(const u64 addr, u8* value);
virtual bool Read16(const u64 addr, u16* value); virtual bool Read16(const u64 addr, u16* value);

View File

@ -12,9 +12,11 @@ u32 local_addr = NULL;
enum enum
{ {
CELL_GCM_ERROR_FAILURE = 0x802100ff, CELL_GCM_ERROR_FAILURE = 0x802100ff,
CELL_GCM_ERROR_NO_IO_PAGE_TABLE = 0x80210001,
CELL_GCM_ERROR_INVALID_ENUM = 0x80210002, CELL_GCM_ERROR_INVALID_ENUM = 0x80210002,
CELL_GCM_ERROR_INVALID_VALUE = 0x80210003, CELL_GCM_ERROR_INVALID_VALUE = 0x80210003,
CELL_GCM_ERROR_INVALID_ALIGNMENT = 0x80210004, CELL_GCM_ERROR_INVALID_ALIGNMENT = 0x80210004,
CELL_GCM_ERROR_ADDRESS_OVERWRAP = 0x80210005
}; };
/*------------------------------------------------------------ /*------------------------------------------------------------
@ -28,12 +30,16 @@ struct gcm_offset
}; };
void InitOffsetTable(); void InitOffsetTable();
int cellGcmAddressToOffset(u32 address, mem32_t offset); int32_t cellGcmAddressToOffset(u64 address, mem32_t offset);
u32 cellGcmGetMaxIoMapSize(); uint32_t cellGcmGetMaxIoMapSize();
void cellGcmGetOffsetTable(mem_ptr_t<gcm_offset> table); void cellGcmGetOffsetTable(mem_ptr_t<gcm_offset> table);
int32_t cellGcmIoOffsetToAddress(u32 ioOffset, mem_ptr_t<void*> address); int32_t cellGcmIoOffsetToAddress(u32 ioOffset, u64 address);
int cellGcmMapEaIoAddress(const u32 ea, const u32 io, const u32 size); int32_t cellGcmMapEaIoAddress(const u32 ea, const u32 io, const u32 size);
int32_t cellGcmMapMainMemory(u64 ea, u32 size, mem32_t offset);
int32_t cellGcmReserveIoMapSize(const u32 size);
int32_t cellGcmUnmapEaIoAddress(u64 ea);
int32_t cellGcmUnmapIoAddress(u64 io);
int32_t cellGcmUnreserveIoMapSize(u32 size);
//------------------------------------------------------------ //------------------------------------------------------------
@ -44,19 +50,6 @@ gcmInfo gcm_info;
u32 map_offset_addr = 0; u32 map_offset_addr = 0;
u32 map_offset_pos = 0; u32 map_offset_pos = 0;
int cellGcmMapMainMemory(u32 address, u32 size, mem32_t offset)
{
cellGcmSys.Warning("cellGcmMapMainMemory(address=0x%x,size=0x%x,offset_addr=0x%x)", address, size, offset.GetAddr());
if(!offset.IsGood()) return CELL_EFAULT;
Emu.GetGSManager().GetRender().m_main_mem_addr = Emu.GetGSManager().GetRender().m_ioAddress;
offset = address - Emu.GetGSManager().GetRender().m_main_mem_addr;
Emu.GetGSManager().GetRender().m_main_mem_info.AddCpy(MemInfo(address, size));
return CELL_OK;
}
int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress) int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress)
{ {
cellGcmSys.Warning("cellGcmInit(context_addr=0x%x,cmdSize=0x%x,ioSize=0x%x,ioAddress=0x%x)", context_addr, cmdSize, ioSize, ioAddress); cellGcmSys.Warning("cellGcmInit(context_addr=0x%x,cmdSize=0x%x,ioSize=0x%x,ioAddress=0x%x)", context_addr, cmdSize, ioSize, ioAddress);
@ -82,7 +75,7 @@ int cellGcmInit(u32 context_addr, u32 cmdSize, u32 ioSize, u32 ioAddress)
InitOffsetTable(); InitOffsetTable();
Memory.RSXCMDMem.Alloc(cmdSize); Memory.RSXCMDMem.Alloc(cmdSize);
Memory.MemoryBlocks.push_back(Memory.RSXIOMem.SetRange(0xE0000000, 0x10000000/*256MB*/));//TODO: implement allocateAdressSpace in memoryBase Memory.MemoryBlocks.push_back(Memory.RSXIOMem.SetRange(0xE0000000, 0x10000000/*256MB*/));//TODO: implement allocateAdressSpace in memoryBase
cellGcmMapEaIoAddress(ioAddress, ioSize, 0); cellGcmMapEaIoAddress(ioAddress, 0, ioSize);
u32 ctx_begin = ioAddress/* + 0x1000*/; u32 ctx_begin = ioAddress/* + 0x1000*/;
u32 ctx_size = 0x6ffc; u32 ctx_size = 0x6ffc;
@ -596,61 +589,43 @@ void InitOffsetTable()
} }
} }
int cellGcmAddressToOffset(u32 address, mem32_t offset) int32_t cellGcmAddressToOffset(u64 address, mem32_t offset)
{ {
cellGcmSys.Log("cellGcmAddressToOffset(address=0x%x,offset_addr=0x%x)", address, offset.GetAddr()); cellGcmSys.Warning("cellGcmAddressToOffset(address=0x%x,offset_addr=0x%x)", address, offset.GetAddr());
if(!offset.IsGood()) return CELL_EFAULT;
if(!map_offset_addr)
{
map_offset_addr = Memory.Alloc(4*50, 4);
}
u32 sa; if(address >= 0xD0000000/*not on main memory or local*/)
bool is_main_mem = false; return CELL_GCM_ERROR_FAILURE;
const auto& main_mem_info = Emu.GetGSManager().GetRender().m_main_mem_info;
for(u32 i=0; i<Emu.GetGSManager().GetRender().m_main_mem_info.GetCount(); ++i) u32 result;
// If address is in range of local memory
if(Memory.RSXFBMem.IsInMyRange(address))
{ {
//main memory result = address - Memory.RSXFBMem.GetStartAddr();
if(address >= main_mem_info[i].addr && address < main_mem_info[i].addr + main_mem_info[i].size) }
// else check if the adress (main memory) is mapped in IO
else
{
u16 upper12Bits = Memory.Read16(offsetTable.io + sizeof(u16)*(address >> 20));
if(upper12Bits != 0xFFFF)
{ {
is_main_mem = true; result = (((u64)upper12Bits << 20) | (address & (0xFFFFF)));
break; }
// address is not mapped in IO
else
{
return CELL_GCM_ERROR_FAILURE;
} }
} }
if(is_main_mem) offset = result;
{
//main
sa = Emu.GetGSManager().GetRender().m_main_mem_addr;
//ConLog.Warning("cellGcmAddressToOffset: main memory: offset = 0x%x - 0x%x = 0x%x", address, sa, address - sa);
}
else if(Memory.RSXFBMem.IsMyAddress(address))
{
//local
sa = Emu.GetGSManager().GetRender().m_local_mem_addr;
//ConLog.Warning("cellGcmAddressToOffset: local memory: offset = 0x%x - 0x%x = 0x%x", address, sa, address - sa);
}
else
{
//io
sa = Emu.GetGSManager().GetRender().m_ioAddress;
//ConLog.Warning("cellGcmAddressToOffset: io memory: offset = 0x%x - 0x%x = 0x%x", address, sa, address - sa);
}
offset = address - sa;
//ConLog.Warning("Address To Offset: 0x%x -> 0x%x", address, address - sa);
//Memory.Write16(map_offset_addr + map_offset_pos + 0, ea);
//Memory.Write16(map_offset_addr + map_offset_pos + 2, offset);
//map_offset_pos += 4;
return CELL_OK; return CELL_OK;
} }
u32 cellGcmGetMaxIoMapSize() uint32_t cellGcmGetMaxIoMapSize()
{ {
UNIMPLEMENTED_FUNC(cellGcmSys); return Memory.RSXIOMem.GetEndAddr() - Memory.RSXIOMem.GetStartAddr() - Memory.RSXIOMem.GetResevedAmount();
return 0x10000000;//256MB TODO
} }
void cellGcmGetOffsetTable(mem_ptr_t<gcm_offset> table) void cellGcmGetOffsetTable(mem_ptr_t<gcm_offset> table)
@ -659,7 +634,7 @@ void cellGcmGetOffsetTable(mem_ptr_t<gcm_offset> table)
table->ea = re(offsetTable.ea); table->ea = re(offsetTable.ea);
} }
int32_t cellGcmIoOffsetToAddress(u32 ioOffset, mem_ptr_t<void*> address) int32_t cellGcmIoOffsetToAddress(u32 ioOffset, u64 address)
{ {
u64 realAddr; u64 realAddr;
@ -673,7 +648,7 @@ int32_t cellGcmIoOffsetToAddress(u32 ioOffset, mem_ptr_t<void*> address)
return CELL_OK; return CELL_OK;
} }
int cellGcmMapEaIoAddress(const u32 ea, const u32 io, const u32 size) int32_t cellGcmMapEaIoAddress(const u32 ea, const u32 io, const u32 size)
{ {
cellGcmSys.Warning("cellGcmMapEaIoAddress(ea=0x%x, io=0x%x, size=0x%x)", ea, io, size); cellGcmSys.Warning("cellGcmMapEaIoAddress(ea=0x%x, io=0x%x, size=0x%x)", ea, io, size);
@ -683,10 +658,10 @@ int cellGcmMapEaIoAddress(const u32 ea, const u32 io, const u32 size)
if(Memory.RSXIOMem.Map(ea, size, Memory.RSXIOMem.GetStartAddr() + io)) if(Memory.RSXIOMem.Map(ea, size, Memory.RSXIOMem.GetStartAddr() + io))
{ {
//fill the offset table //fill the offset table
for(int i=0; i<size/(1024*1024); i++) for(u32 i=0; i<(size >> 20); i++)
{ {
Memory.Write16(offsetTable.io + ea/(1024*1024) + i, io/(1024*1024) + i); Memory.Write16(offsetTable.io + ((ea >> 20) + i)*sizeof(u16), (io >> 20) + i);
Memory.Write16(offsetTable.ea + io/(1024*1024) + i, ea/(1024*1024) + i); Memory.Write16(offsetTable.ea + ((io >> 20) + i)*sizeof(u16), (ea >> 20) + i);
} }
} }
else else
@ -694,20 +669,18 @@ int cellGcmMapEaIoAddress(const u32 ea, const u32 io, const u32 size)
return CELL_GCM_ERROR_FAILURE; return CELL_GCM_ERROR_FAILURE;
} }
//Emu.GetGSManager().GetRender().m_ioAddress = io;
Emu.GetGSManager().GetRender().m_report_main_addr = ea;
return CELL_OK; return CELL_OK;
} }
int32_t cellGcmMapLocalMemory(mem_ptr_t<void*> address, mem_ptr_t<uint32_t> size) int32_t cellGcmMapLocalMemory(u64 address, u64 size)
{ {
if(!local_size && !local_addr) if(!local_size && !local_addr)
{ {
local_size = 0xf900000; //TODO local_size = 0xf900000; //TODO
local_addr = Memory.RSXFBMem.GetStartAddr(); local_addr = Memory.RSXFBMem.GetStartAddr();
Memory.RSXFBMem.Alloc(local_size); Memory.RSXFBMem.Alloc(local_size);
Memory.Write32(address.GetAddr(), local_addr); Memory.Write32(address, local_addr);
Memory.Write32(size.GetAddr(), local_size); Memory.Write32(size, local_size);
} }
else else
{ {
@ -718,6 +691,107 @@ int32_t cellGcmMapLocalMemory(mem_ptr_t<void*> address, mem_ptr_t<uint32_t> size
return CELL_OK; return CELL_OK;
} }
int32_t cellGcmMapMainMemory(u64 ea, u32 size, mem32_t offset)
{
cellGcmSys.Warning("cellGcmMapMainMemory(ea=0x%x,size=0x%x,offset_addr=0x%x)", ea, size, offset.GetAddr());
u64 io;
if((ea & 0xFFFFF) || (size & 0xFFFFF)) return CELL_GCM_ERROR_FAILURE;
//check if the mapping was successfull
if(io = Memory.RSXIOMem.Map(ea, size, 0))
{
//fill the offset table
for(u32 i=0; i<(size >> 20); i++)
{
Memory.Write16(offsetTable.io + ((ea >> 20) + i)*sizeof(u16), (io >> 20) + i);
Memory.Write16(offsetTable.ea + ((io >> 20) + i)*sizeof(u16), (ea >> 20) + i);
}
}
else
{
return CELL_GCM_ERROR_NO_IO_PAGE_TABLE;
}
Emu.GetGSManager().GetRender().m_main_mem_addr = Emu.GetGSManager().GetRender().m_ioAddress;
Emu.GetGSManager().GetRender().m_main_mem_info.AddCpy(MemInfo(ea, size));
return CELL_OK;
}
int32_t cellGcmReserveIoMapSize(const u32 size)
{
if(size & 0xFFFFF)
return CELL_GCM_ERROR_INVALID_ALIGNMENT;
if(size > cellGcmGetMaxIoMapSize())
return CELL_GCM_ERROR_INVALID_VALUE;
Memory.RSXIOMem.Reserve(size);
return CELL_OK;
}
int32_t cellGcmUnmapEaIoAddress(u64 ea)
{
u32 size;
if(size = Memory.RSXIOMem.UnmapRealAddress(ea))
{
u64 io;
ea = ea >> 20;
io = Memory.Read16(offsetTable.io + (ea*sizeof(u16)));
for(int i=0; i<size; i++)
{
Memory.Write16(offsetTable.io + ((ea+i)*sizeof(u16)), 0xFFFF);
Memory.Write16(offsetTable.ea + ((io+i)*sizeof(u16)), 0xFFFF);
}
}
else
{
return CELL_GCM_ERROR_FAILURE;
}
return CELL_OK;
}
int32_t cellGcmUnmapIoAddress(u64 io)
{
u32 size;
if(size = Memory.RSXIOMem.UnmapAddress(io))
{
u64 ea;
io = io >> 20;
ea = Memory.Read16(offsetTable.ea + (io*sizeof(u16)));
for(int i=0; i<size; i++)
{
Memory.Write16(offsetTable.io + ((ea+i)*sizeof(u16)), 0xFFFF);
Memory.Write16(offsetTable.ea + ((io+i)*sizeof(u16)), 0xFFFF);
}
}
else
{
return CELL_GCM_ERROR_FAILURE;
}
return CELL_OK;
}
int32_t cellGcmUnreserveIoMapSize(u32 size)
{
if(size & 0xFFFFF)
return CELL_GCM_ERROR_INVALID_ALIGNMENT;
if(size > Memory.RSXIOMem.GetResevedAmount())
return CELL_GCM_ERROR_INVALID_VALUE;
Memory.RSXIOMem.Unreserve(size);
return CELL_OK;
}
//------------------------------------------------------------
void cellGcmSys_init() void cellGcmSys_init()
{ {
current_config.ioAddress = NULL; current_config.ioAddress = NULL;
@ -745,7 +819,6 @@ void cellGcmSys_init()
cellGcmSys.AddFunc(0xd9b7653e, cellGcmUnbindTile); cellGcmSys.AddFunc(0xd9b7653e, cellGcmUnbindTile);
cellGcmSys.AddFunc(0xa75640e8, cellGcmUnbindZcull); cellGcmSys.AddFunc(0xa75640e8, cellGcmUnbindZcull);
cellGcmSys.AddFunc(0xa41ef7e8, cellGcmSetFlipHandler); cellGcmSys.AddFunc(0xa41ef7e8, cellGcmSetFlipHandler);
cellGcmSys.AddFunc(0xa114ec67, cellGcmMapMainMemory);
cellGcmSys.AddFunc(0xf80196c1, cellGcmGetLabelAddress); cellGcmSys.AddFunc(0xf80196c1, cellGcmGetLabelAddress);
cellGcmSys.AddFunc(0x107bf3a1, cellGcmInitCursor); cellGcmSys.AddFunc(0x107bf3a1, cellGcmInitCursor);
cellGcmSys.AddFunc(0x1a0de550, cellGcmSetCursorPosition); cellGcmSys.AddFunc(0x1a0de550, cellGcmSetCursorPosition);
@ -777,4 +850,9 @@ void cellGcmSys_init()
cellGcmSys.AddFunc(0x2a6fba9c, cellGcmIoOffsetToAddress); cellGcmSys.AddFunc(0x2a6fba9c, cellGcmIoOffsetToAddress);
cellGcmSys.AddFunc(0x63441cb4, cellGcmMapEaIoAddress); cellGcmSys.AddFunc(0x63441cb4, cellGcmMapEaIoAddress);
cellGcmSys.AddFunc(0xdb769b32, cellGcmMapLocalMemory); cellGcmSys.AddFunc(0xdb769b32, cellGcmMapLocalMemory);
cellGcmSys.AddFunc(0xa114ec67, cellGcmMapMainMemory);
cellGcmSys.AddFunc(0xa7ede268, cellGcmReserveIoMapSize);
cellGcmSys.AddFunc(0xefd00f54, cellGcmUnmapEaIoAddress);
cellGcmSys.AddFunc(0xdb23e867, cellGcmUnmapIoAddress);
cellGcmSys.AddFunc(0x3b9bd5bd, cellGcmUnreserveIoMapSize);
} }

View File

@ -76,7 +76,7 @@ CCellRescInternal* s_rescInternalInstance = new CCellRescInternal();
// Extern Functions // Extern Functions
extern int cellGcmSetFlipMode(u32 mode); extern int cellGcmSetFlipMode(u32 mode);
extern int cellGcmSetFlipHandler(u32 handler_addr); extern int cellGcmSetFlipHandler(u32 handler_addr);
extern int cellGcmAddressToOffset(u32 address, mem32_t offset); extern int32_t cellGcmAddressToOffset(u64 address, mem32_t offset);
extern int cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height); extern int cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height);
extern int cellGcmSetPrepareFlip(mem_ptr_t<CellGcmContextData> ctx, u32 id); extern int cellGcmSetPrepareFlip(mem_ptr_t<CellGcmContextData> ctx, u32 id);
extern int cellGcmSetSecondVFrequency(u32 freq); extern int cellGcmSetSecondVFrequency(u32 freq);