mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-21 03:55:32 +00:00
sys_rsx: implement support for lle-gcm
This commit is contained in:
parent
d9a693019b
commit
21dd715b42
9 changed files with 349 additions and 59 deletions
|
@ -425,6 +425,7 @@ s32 _cellGcmInitBody(vm::pptr<CellGcmContextData> context, u32 cmdSize, u32 ioSi
|
|||
render->intr_thread = idm::make_ptr<ppu_thread>("_gcm_intr_thread", 1, 0x4000);
|
||||
render->intr_thread->run();
|
||||
render->main_mem_addr = 0;
|
||||
render->isHLE = true;
|
||||
render->label_addr = m_config->gcm_info.label_addr;
|
||||
render->init(ioAddress, ioSize, m_config->gcm_info.control_addr - 0x40, local_addr);
|
||||
|
||||
|
|
|
@ -880,7 +880,7 @@ s32 _spurs::stop_event_helper(ppu_thread& ppu, vm::ptr<CellSpurs> spurs)
|
|||
return CELL_SPURS_CORE_ERROR_STAT;
|
||||
}
|
||||
|
||||
if (sys_event_port_send(ppu, spurs->eventPort, 0, 1, 0) != CELL_OK)
|
||||
if (sys_event_port_send(spurs->eventPort, 0, 1, 0) != CELL_OK)
|
||||
{
|
||||
return CELL_SPURS_CORE_ERROR_STAT;
|
||||
}
|
||||
|
@ -2794,7 +2794,7 @@ s32 cellSpursEventFlagSet(ppu_thread& ppu, vm::ptr<CellSpursEventFlag> eventFlag
|
|||
// Signal the PPU thread to be woken up
|
||||
eventFlag->pendingRecvTaskEvents[ppuWaitSlot] = ppuEvents;
|
||||
|
||||
CHECK_SUCCESS(sys_event_port_send(ppu, eventFlag->eventPortId, 0, 0, 0));
|
||||
CHECK_SUCCESS(sys_event_port_send(eventFlag->eventPortId, 0, 0, 0));
|
||||
}
|
||||
|
||||
if (pendingRecv)
|
||||
|
|
|
@ -418,7 +418,7 @@ error_code sys_event_port_disconnect(u32 eport_id)
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code sys_event_port_send(ppu_thread& ppu, u32 eport_id, u64 data1, u64 data2, u64 data3)
|
||||
error_code sys_event_port_send(u32 eport_id, u64 data1, u64 data2, u64 data3)
|
||||
{
|
||||
sys_event.trace("sys_event_port_send(eport_id=0x%x, data1=0x%llx, data2=0x%llx, data3=0x%llx)", eport_id, data1, data2, data3);
|
||||
|
||||
|
|
|
@ -137,4 +137,4 @@ error_code sys_event_port_create(vm::ps3::ptr<u32> eport_id, s32 port_type, u64
|
|||
error_code sys_event_port_destroy(u32 eport_id);
|
||||
error_code sys_event_port_connect_local(u32 event_port_id, u32 event_queue_id);
|
||||
error_code sys_event_port_disconnect(u32 eport_id);
|
||||
error_code sys_event_port_send(ppu_thread& ppu, u32 event_port_id, u64 data1, u64 data2, u64 data3);
|
||||
error_code sys_event_port_send(u32 event_port_id, u64 data1, u64 data2, u64 data3);
|
||||
|
|
|
@ -1,14 +1,28 @@
|
|||
#include "stdafx.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/RSX/GSRender.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "sys_rsx.h"
|
||||
#include "sys_event.h"
|
||||
|
||||
namespace vm { using namespace ps3; }
|
||||
|
||||
logs::channel sys_rsx("sys_rsx");
|
||||
|
||||
extern u64 get_timebased_time();
|
||||
|
||||
struct SysRsxConfig {
|
||||
be_t<u32> rsx_event_port{ 0 };
|
||||
u32 driverInfo{ 0 };
|
||||
};
|
||||
|
||||
u64 rsxTimeStamp() {
|
||||
return get_timebased_time();
|
||||
}
|
||||
|
||||
s32 sys_rsx_device_open()
|
||||
{
|
||||
sys_rsx.todo("sys_rsx_device_open()");
|
||||
|
@ -35,7 +49,10 @@ s32 sys_rsx_device_close()
|
|||
*/
|
||||
s32 sys_rsx_memory_allocate(vm::ptr<u32> mem_handle, vm::ptr<u64> mem_addr, u32 size, u64 flags, u64 a5, u64 a6, u64 a7)
|
||||
{
|
||||
sys_rsx.todo("sys_rsx_memory_allocate(mem_handle=*0x%x, mem_addr=*0x%x, size=0x%x, flags=0x%llx, a5=0x%llx, a6=0x%llx, a7=0x%llx)", mem_handle, mem_addr, size, flags, a5, a6, a7);
|
||||
sys_rsx.warning("sys_rsx_memory_allocate(mem_handle=*0x%x, mem_addr=*0x%x, size=0x%x, flags=0x%llx, a5=0x%llx, a6=0x%llx, a7=0x%llx)", mem_handle, mem_addr, size, flags, a5, a6, a7);
|
||||
|
||||
*mem_handle = 1;
|
||||
*mem_addr = vm::falloc(0xC0000000, size, vm::video);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -60,11 +77,86 @@ s32 sys_rsx_memory_free(u32 mem_handle)
|
|||
* @param mem_ctx (IN): mem_ctx given by sys_rsx_memory_allocate
|
||||
* @param system_mode (IN):
|
||||
*/
|
||||
s32 sys_rsx_context_allocate(vm::ptr<u32> context_id, vm::ptr<u32> lpar_dma_control, vm::ptr<u32> lpar_driver_info, vm::ptr<u32> lpar_reports, u64 mem_ctx, u64 system_mode)
|
||||
s32 sys_rsx_context_allocate(vm::ptr<u32> context_id, vm::ptr<u64> lpar_dma_control, vm::ptr<u64> lpar_driver_info, vm::ptr<u64> lpar_reports, u64 mem_ctx, u64 system_mode)
|
||||
{
|
||||
sys_rsx.todo("sys_rsx_context_allocate(context_id=*0x%x, lpar_dma_control=*0x%x, lpar_driver_info=*0x%x, lpar_reports=*0x%x, mem_ctx=0x%llx, system_mode=0x%llx)",
|
||||
sys_rsx.warning("sys_rsx_context_allocate(context_id=*0x%x, lpar_dma_control=*0x%x, lpar_driver_info=*0x%x, lpar_reports=*0x%x, mem_ctx=0x%llx, system_mode=0x%llx)",
|
||||
context_id, lpar_dma_control, lpar_driver_info, lpar_reports, mem_ctx, system_mode);
|
||||
|
||||
auto m_sysrsx = fxm::make<SysRsxConfig>();
|
||||
if (!m_sysrsx)
|
||||
fmt::throw_exception("sys_rsx_context_allocate called twice.");
|
||||
|
||||
u32 addr = vm::falloc(0x40000000, 0x400000);
|
||||
if (addr == 0 || addr != 0x40000000)
|
||||
fmt::throw_exception("Failed to alloc 0x40000000.");
|
||||
|
||||
*context_id = 0x55555555;
|
||||
|
||||
*lpar_dma_control = 0x40100000;
|
||||
*lpar_driver_info = 0x40200000;
|
||||
*lpar_reports = 0x40300000;
|
||||
|
||||
auto &reports = vm::_ref<RsxReports>(*lpar_reports);
|
||||
std::memset(&reports, 0, sizeof(RsxReports));
|
||||
|
||||
for (int i = 0; i < 64; ++i)
|
||||
reports.notify[i].timestamp = (u64)-1;
|
||||
|
||||
for (int i = 0; i < 256; ++i) {
|
||||
reports.semaphore[i].val = 0x1337C0D3;
|
||||
reports.semaphore[i].pad = 0x1337BABE;
|
||||
reports.semaphore[i].timestamp = (u64)-1; // technically different but should be fine
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2048; ++i)
|
||||
reports.report[i].timestamp = (u64)-1;
|
||||
|
||||
auto &driverInfo = vm::_ref<RsxDriverInfo>(*lpar_driver_info);
|
||||
|
||||
std::memset(&driverInfo, 0, sizeof(RsxDriverInfo));
|
||||
|
||||
driverInfo.version_driver = 0x211;
|
||||
driverInfo.version_gpu = 0x5c;
|
||||
driverInfo.memory_size = 0xFE00000;
|
||||
driverInfo.nvcore_frequency = 500000000; // 0x1DCD6500
|
||||
driverInfo.memory_frequency = 650000000; // 0x26BE3680
|
||||
driverInfo.reportsNotifyOffset = 0x1000;
|
||||
driverInfo.reportsOffset = 0;
|
||||
driverInfo.reportsReportOffset = 0x1400;
|
||||
driverInfo.systemModeFlags = system_mode;
|
||||
driverInfo.hardware_channel = 1; // * i think* this 1 for games, 0 for vsh
|
||||
|
||||
m_sysrsx->driverInfo = *lpar_driver_info;
|
||||
|
||||
auto &dmaControl = vm::_ref<RsxDmaControl>(*lpar_dma_control);
|
||||
dmaControl.get = 0;
|
||||
dmaControl.put = 0;
|
||||
dmaControl.ref = 0xFFFFFFFF;
|
||||
|
||||
if (false/*system_mode == CELL_GCM_SYSTEM_MODE_IOMAP_512MB*/)
|
||||
RSXIOMem.SetRange(0, 0x20000000 /*512MB*/);
|
||||
else
|
||||
RSXIOMem.SetRange(0, 0x10000000 /*256MB*/);
|
||||
|
||||
sys_event_queue_attribute_t attr;
|
||||
attr.protocol = SYS_SYNC_PRIORITY;
|
||||
attr.type = SYS_PPU_QUEUE;
|
||||
auto queueId = vm::make_var<u32>(0);
|
||||
sys_event_queue_create(queueId, vm::make_var(attr), 0, 0x20);
|
||||
driverInfo.handler_queue = queueId->value();
|
||||
|
||||
sys_event_port_create(queueId, SYS_EVENT_PORT_LOCAL, 0);
|
||||
sys_event_port_connect_local(queueId->value(), driverInfo.handler_queue);
|
||||
|
||||
m_sysrsx->rsx_event_port = queueId->value();
|
||||
|
||||
const auto render = fxm::get<GSRender>();
|
||||
render->display_buffers_count = 0;
|
||||
render->current_display_buffer = 0;
|
||||
render->main_mem_addr = 0;
|
||||
render->label_addr = *lpar_reports;
|
||||
render->init(0, 0, *lpar_dma_control, 0xC0000000);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -89,9 +181,11 @@ s32 sys_rsx_context_free(u32 context_id)
|
|||
*/
|
||||
s32 sys_rsx_context_iomap(u32 context_id, u32 io, u32 ea, u32 size, u64 flags)
|
||||
{
|
||||
sys_rsx.todo("sys_rsx_context_iomap(context_id=0x%x, io=0x%x, ea=0x%x, size=0x%x, flags=0x%llx)", context_id, io, ea, size, flags);
|
||||
|
||||
return CELL_OK;
|
||||
sys_rsx.warning("sys_rsx_context_iomap(context_id=0x%x, io=0x%x, ea=0x%x, size=0x%x, flags=0x%llx)", context_id, io, ea, size, flags);
|
||||
if (size == 0) return CELL_OK;
|
||||
if (RSXIOMem.Map(ea, size, io))
|
||||
return CELL_OK;
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -101,58 +195,142 @@ s32 sys_rsx_context_iomap(u32 context_id, u32 io, u32 ea, u32 size, u64 flags)
|
|||
* @param io_addr (IN): IO address. E.g. 0x00600000 (Start page 6)
|
||||
* @param size (IN): Size to unmap in byte. E.g. 0x00200000
|
||||
*/
|
||||
s32 sys_rsx_context_iounmap(u32 context_id, u32 a2, u32 io_addr, u32 size)
|
||||
s32 sys_rsx_context_iounmap(u32 context_id, u32 io_addr, u32 a3, u32 size)
|
||||
{
|
||||
sys_rsx.todo("sys_rsx_context_iounmap(context_id=0x%x, a2=0x%x, io_addr=0x%x, size=0x%x)", context_id, a2, io_addr, size);
|
||||
|
||||
return CELL_OK;
|
||||
sys_rsx.warning("sys_rsx_context_iounmap(context_id=0x%x, io_addr=0x%x, a3=0x%x, size=0x%x)", context_id, io_addr, a3, size);
|
||||
if (RSXIOMem.UnmapAddress(io_addr, size))
|
||||
return CELL_OK;
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* lv2 SysCall 674 (0x2A2): sys_rsx_context_attribute
|
||||
* @param context_id (IN): RSX context, e.g. 0x55555555
|
||||
* @param package_id (IN):
|
||||
* @param a3 (IN):
|
||||
* @param a4 (IN):
|
||||
* @param a5 (IN):
|
||||
* @param a6 (IN):
|
||||
* @param package_id (IN):
|
||||
* @param a3 (IN):
|
||||
* @param a4 (IN):
|
||||
* @param a5 (IN):
|
||||
* @param a6 (IN):
|
||||
*/
|
||||
s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u64 a5, u64 a6)
|
||||
{
|
||||
sys_rsx.todo("sys_rsx_context_attribute(context_id=0x%x, package_id=0x%x, a3=0x%llx, a4=0x%llx, a5=0x%llx, a6=0x%llx)", context_id, package_id, a3, a4, a5, a6);
|
||||
// Flip/queue/user command/vblank as trace to help with log spam
|
||||
if (package_id == 0x102 || package_id == 0x103 || package_id == 0xFED || package_id == 0xFEF)
|
||||
sys_rsx.trace("sys_rsx_context_attribute(context_id=0x%x, package_id=0x%x, a3=0x%llx, a4=0x%llx, a5=0x%llx, a6=0x%llx)", context_id, package_id, a3, a4, a5, a6);
|
||||
else
|
||||
sys_rsx.warning("sys_rsx_context_attribute(context_id=0x%x, package_id=0x%x, a3=0x%llx, a4=0x%llx, a5=0x%llx, a6=0x%llx)", context_id, package_id, a3, a4, a5, a6);
|
||||
|
||||
switch(package_id)
|
||||
// todo: these event ports probly 'shouldnt' be here as i think its supposed to be interrupts that are sent from rsx somewhere in lv1
|
||||
|
||||
const auto render = fxm::get<GSRender>();
|
||||
|
||||
//hle protection
|
||||
if (render->isHLE)
|
||||
return 0;
|
||||
|
||||
auto m_sysrsx = fxm::get<SysRsxConfig>();
|
||||
|
||||
auto &driverInfo = vm::_ref<RsxDriverInfo>(m_sysrsx->driverInfo);
|
||||
switch (package_id)
|
||||
{
|
||||
case 0x001: // FIFO
|
||||
break;
|
||||
|
||||
case 0x100: // Display mode set
|
||||
render->ctrl->get = a3;
|
||||
render->ctrl->put = a4;
|
||||
break;
|
||||
|
||||
case 0x101: // Display sync
|
||||
case 0x100: // Display mode set
|
||||
break;
|
||||
case 0x101: // Display sync set, cellGcmSetFlipMode
|
||||
// a4 == 2 is vsync, a4 == 1 is hsync
|
||||
render->requested_vsync.store(a4 == 2);
|
||||
break;
|
||||
|
||||
case 0x102: // Display flip
|
||||
driverInfo.head[a3].flipFlags |= 0x80000000;
|
||||
driverInfo.head[a3].lastFlipTime = rsxTimeStamp(); // should rsxthread set this?
|
||||
// lets give this a shot for giving bufferid back to gcm
|
||||
driverInfo.head[a3].flipBufferId = driverInfo.head[a3].queuedBufferId;
|
||||
// seems gcmSysWaitLabel uses this offset, so lets set it to 0 every flip
|
||||
vm::_ref<u32>(0x40300010) = 0;
|
||||
if (a3 == 0)
|
||||
sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 3), 0);
|
||||
if (a3 == 1)
|
||||
sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 4), 0);
|
||||
break;
|
||||
|
||||
case 0x103: // ?
|
||||
case 0x103: // Display Queue
|
||||
driverInfo.head[a3].queuedBufferId = a4;
|
||||
driverInfo.head[a3].flipFlags |= 0x40000000 | (1 << a4);
|
||||
if (a3 == 0)
|
||||
sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 5), 0);
|
||||
if (a3 == 1)
|
||||
sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 6), 0);
|
||||
break;
|
||||
|
||||
case 0x104: // Display buffer
|
||||
{
|
||||
u8 id = a3 & 0xFF;
|
||||
u32 width = (a4 >> 32) & 0xFFFFFFFF;
|
||||
u32 height = a4 & 0xFFFFFFFF;
|
||||
u32 pitch = (a5 >> 32) & 0xFFFFFFFF;
|
||||
u32 offset = a5 & 0xFFFFFFFF;
|
||||
if (id > 7)
|
||||
return -17;
|
||||
render->display_buffers[id].width = width;
|
||||
render->display_buffers[id].height = height;
|
||||
render->display_buffers[id].pitch = pitch;
|
||||
render->display_buffers[id].offset = offset;
|
||||
|
||||
render->display_buffers_count = std::max((u32)id + 1, render->display_buffers_count);
|
||||
}
|
||||
break;
|
||||
case 0x105: // destroy buffer?
|
||||
break;
|
||||
|
||||
case 0x106: // ? (Used by cellGcmInitPerfMon)
|
||||
break;
|
||||
case 0x108: // cellGcmSetSecondVFrequency
|
||||
// a4 == 3, CELL_GCM_DISPLAY_FREQUENCY_59_94HZ
|
||||
// a4 == 2, CELL_GCM_DISPLAY_FREQUENCY_SCANOUT
|
||||
// a4 == 4, CELL_GCM_DISPLAY_FREQUENCY_DISABLE
|
||||
// Note: Scanout/59_94 is ignored currently as we report refresh rate of 59_94hz as it is, so the difference doesnt matter
|
||||
render->enable_second_vhandler.store(a4 != 4);
|
||||
break;
|
||||
case 0x10a: // ? Involved in managing flip status through cellGcmResetFlipStatus
|
||||
{
|
||||
if (a3 > 7)
|
||||
return -17;
|
||||
u32 flipStatus = driverInfo.head[a3].flipFlags;
|
||||
flipStatus = (flipStatus & a4) | a5;
|
||||
driverInfo.head[a3].flipFlags = flipStatus;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x10a: // ?
|
||||
case 0x10D: // Called by cellGcmInitCursor
|
||||
break;
|
||||
|
||||
case 0x300: // Tiles
|
||||
break;
|
||||
{
|
||||
//a4 high bits = ret.tile = (location + 1) | (bank << 4) | ((offset / 0x10000) << 16) | (location << 31);
|
||||
//a4 low bits = ret.limit = ((offset + size - 1) / 0x10000) << 16 | (location << 31);
|
||||
//a5 high bits = ret.pitch = (pitch / 0x100) << 8;
|
||||
//a5 low bits = ret.format = base | ((base + ((size - 1) / 0x10000)) << 13) | (comp << 26) | (1 << 30);
|
||||
|
||||
auto& tile = render->tiles[a3];
|
||||
tile.location = ((a4 >> 32) & 0xF) - 1;
|
||||
tile.offset = ((((a4 >> 32) & 0xFFFFFFFF) >> 16) * 0x10000);
|
||||
tile.size = ((((a4 & 0x7FFFFFFF) >> 16) + 1) * 0x10000) - tile.offset;
|
||||
tile.pitch = (((a5 >> 32) & 0xFFFFFFFF) >> 8) * 0x100;
|
||||
tile.comp = ((a5 & 0xFFFFFFFF) >> 26) & 0xF;
|
||||
tile.base = (a5 & 0xFFFFFFFF) & 0x7FF;
|
||||
tile.bank = (((a4 >> 32) & 0xFFFFFFFF) >> 4) & 0xF;
|
||||
tile.binded = a5 != 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x301: // Depth-buffer (Z-cull)
|
||||
break;
|
||||
|
||||
case 0x302: // something with zcull
|
||||
break;
|
||||
case 0x600: // Framebuffer setup
|
||||
break;
|
||||
|
||||
|
@ -162,6 +340,24 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6
|
|||
case 0x602: // Framebuffer blit sync
|
||||
break;
|
||||
|
||||
case 0x603: // Framebuffer close
|
||||
break;
|
||||
|
||||
case 0xFED: // hack: vblank command
|
||||
// todo: this is wrong and should be 'second' vblank handler and freq, but since currently everything is reported as being 59.94, this should be fine
|
||||
driverInfo.head[a3].vBlankCount++;
|
||||
driverInfo.head[a3].lastSecondVTime = rsxTimeStamp();
|
||||
sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 1), 0);
|
||||
if (render->enable_second_vhandler)
|
||||
sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 11), 0); // second vhandler
|
||||
break;
|
||||
case 0xFEF: // hack: user command
|
||||
// 'custom' invalid package id for now
|
||||
// as i think we need custom lv1 interrupts to handle this accurately
|
||||
// this also should probly be set by rsxthread
|
||||
driverInfo.userCmdParam = a4;
|
||||
sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 7), 0);
|
||||
break;
|
||||
default:
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
@ -175,19 +371,19 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6
|
|||
* @param a2 (OUT): Unused?
|
||||
* @param dev_id (IN): An immediate value and always 8. (cellGcmInitPerfMon uses 11, 10, 9, 7, 12 successively).
|
||||
*/
|
||||
s32 sys_rsx_device_map(vm::ptr<u32> addr, vm::ptr<u32> a2, u32 dev_id)
|
||||
s32 sys_rsx_device_map(vm::ptr<u64> addr, vm::ptr<u64> a2, u32 dev_id)
|
||||
{
|
||||
sys_rsx.todo("sys_rsx_device_map(addr=*0x%x, a2=*0x%x, dev_id=0x%x)", addr, a2, dev_id);
|
||||
sys_rsx.warning("sys_rsx_device_map(addr=*0x%x, a2=*0x%x, dev_id=0x%x)", addr, a2, dev_id);
|
||||
|
||||
if (dev_id > 15) {
|
||||
// TODO: Throw RSX error
|
||||
return CELL_EINVAL;
|
||||
if (dev_id != 8) {
|
||||
// TODO: lv1 related
|
||||
fmt::throw_exception("sys_rsx_device_map: Invalid dev_id %d", dev_id);
|
||||
}
|
||||
|
||||
if (dev_id == 0 || dev_id > 8) {
|
||||
// TODO: lv1 related so we may ignore it.
|
||||
// if (something) { return CELL_EPERM; }
|
||||
}
|
||||
// a2 seems to not be referenced in cellGcmSys
|
||||
*a2 = 0;
|
||||
|
||||
*addr = 0x40000000;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -203,9 +399,12 @@ s32 sys_rsx_device_unmap(u32 dev_id)
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sys_rsx_attribute(u32 a1, u32 a2, u32 a3, u32 a4, u32 a5)
|
||||
/*
|
||||
* lv2 SysCall 677 (0x2A5): sys_rsx_attribute
|
||||
*/
|
||||
s32 sys_rsx_attribute(u32 packageId, u32 a2, u32 a3, u32 a4, u32 a5)
|
||||
{
|
||||
sys_rsx.todo("sys_rsx_attribute(a1=0x%x, a2=0x%x, a3=0x%x, a4=0x%x, a5=0x%x)", a1, a2, a3, a4, a5);
|
||||
sys_rsx.warning("sys_rsx_attribute(packageId=0x%x, a2=0x%x, a3=0x%x, a4=0x%x, a5=0x%x)", packageId, a2, a3, a4, a5);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,54 @@
|
|||
#pragma once
|
||||
|
||||
struct RsxDriverInfo {
|
||||
be_t<u32> version_driver; // 0x0
|
||||
be_t<u32> version_gpu; // 0x4
|
||||
be_t<u32> memory_size; // 0x8
|
||||
be_t<u32> hardware_channel; // 0xC
|
||||
be_t<u32> nvcore_frequency; // 0x10
|
||||
be_t<u32> memory_frequency; // 0x14
|
||||
be_t<u32> unk1[4]; // 0x18 - 0x24
|
||||
be_t<u32> unk2; // 0x28 -- pgraph stuff
|
||||
be_t<u32> reportsNotifyOffset;// 0x2C offset to notify memory
|
||||
be_t<u32> reportsOffset; // 0x30 offset to reports memory
|
||||
be_t<u32> reportsReportOffset;// 0x34 offset to reports in reports memory
|
||||
be_t<u32> unk3[6]; // 0x38-0x54
|
||||
be_t<u32> systemModeFlags; // 0x54
|
||||
u8 unk4[0x1064]; // 0x10B8
|
||||
struct Head {
|
||||
be_t<u64> lastFlipTime; // 0x0 last flip time
|
||||
be_t<u32> flipFlags; // 0x8 flags to handle flip/queue
|
||||
be_t<u32> unk1; // 0xC
|
||||
be_t<u32> flipBufferId; // 0x10
|
||||
be_t<u32> queuedBufferId; // 0x14 todo: this is definately not this variable but its 'unused' so im using it for queueId to pass to flip handler
|
||||
be_t<u32> unk3; // 0x18
|
||||
be_t<u32> unk6; // 0x18 possible low bits of time stamp? used in getlastVBlankTime
|
||||
be_t<u64> lastSecondVTime; // 0x20 last time for second vhandler freq
|
||||
be_t<u64> unk4; // 0x28
|
||||
be_t<u64> vBlankCount; // 0x30
|
||||
be_t<u32> unk; // 0x38 possible u32, 'flip field', top/bottom for interlaced
|
||||
be_t<u32> unk5; // 0x3C possible high bits of time stamp? used in getlastVBlankTime
|
||||
} head[8]; // size = 0x40, 0x200
|
||||
be_t<u32> unk7; // 0x12B8
|
||||
be_t<u32> unk8; // 0x12BC
|
||||
be_t<u32> handlers; // 0x12C0 -- flags showing which handlers are set
|
||||
be_t<u32> unk9; // 0x12C4
|
||||
be_t<u32> unk10; // 0x12C8
|
||||
be_t<u32> userCmdParam; // 0x12CC
|
||||
be_t<u32> handler_queue; // 0x12D0
|
||||
be_t<u32> unk11; // 0x12D4
|
||||
be_t<u32> unk12; // 0x12D8
|
||||
be_t<u32> unk13; // 0x12DC
|
||||
be_t<u32> unk14; // 0x12E0
|
||||
be_t<u32> unk15; // 0x12E4
|
||||
be_t<u32> unk16; // 0x12E8
|
||||
be_t<u32> unk17; // 0x12F0
|
||||
be_t<u32> lastError; // 0x12F4 error param for cellGcmSetGraphicsHandler
|
||||
// todo: theres more to this
|
||||
};
|
||||
static_assert(sizeof(RsxDriverInfo) == 0x12F8, "rsxSizeTest");
|
||||
static_assert(sizeof(RsxDriverInfo::Head) == 0x40, "rsxHeadSizeTest");
|
||||
|
||||
struct RsxDmaControl {
|
||||
u8 resv[0x40];
|
||||
atomic_be_t<u32> put;
|
||||
|
@ -44,11 +93,11 @@ s32 sys_rsx_device_open();
|
|||
s32 sys_rsx_device_close();
|
||||
s32 sys_rsx_memory_allocate(vm::ps3::ptr<u32> mem_handle, vm::ps3::ptr<u64> mem_addr, u32 size, u64 flags, u64 a5, u64 a6, u64 a7);
|
||||
s32 sys_rsx_memory_free(u32 mem_handle);
|
||||
s32 sys_rsx_context_allocate(vm::ps3::ptr<u32> context_id, vm::ps3::ptr<u32> lpar_dma_control, vm::ps3::ptr<u32> lpar_driver_info, vm::ps3::ptr<u32> lpar_reports, u64 mem_ctx, u64 system_mode);
|
||||
s32 sys_rsx_context_allocate(vm::ps3::ptr<u32> context_id, vm::ps3::ptr<u64> lpar_dma_control, vm::ps3::ptr<u64> lpar_driver_info, vm::ps3::ptr<u64> lpar_reports, u64 mem_ctx, u64 system_mode);
|
||||
s32 sys_rsx_context_free(u32 context_id);
|
||||
s32 sys_rsx_context_iomap(u32 context_id, u32 io, u32 ea, u32 size, u64 flags);
|
||||
s32 sys_rsx_context_iounmap(u32 context_id, u32 a2, u32 io_addr, u32 size);
|
||||
s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u64 a5, u64 a6);
|
||||
s32 sys_rsx_device_map(vm::ps3::ptr<u32> addr, vm::ps3::ptr<u32> a2, u32 dev_id);
|
||||
s32 sys_rsx_device_map(vm::ps3::ptr<u64> addr, vm::ps3::ptr<u64> a2, u32 dev_id);
|
||||
s32 sys_rsx_device_unmap(u32 dev_id);
|
||||
s32 sys_rsx_attribute(u32 a1, u32 a2, u32 a3, u32 a4, u32 a5);
|
||||
s32 sys_rsx_attribute(u32 a1, u32 a2, u32 a3, u32 a4, u32 a5);
|
|
@ -388,7 +388,7 @@ namespace rsx
|
|||
if (get_system_time() - start_time > vblank_count * 1000000 / 60)
|
||||
{
|
||||
vblank_count++;
|
||||
|
||||
sys_rsx_context_attribute(0x55555555, 0xFED, 1, 0, 0, 0);
|
||||
if (vblank_handler)
|
||||
{
|
||||
intr_thread->cmd_list
|
||||
|
@ -403,6 +403,8 @@ namespace rsx
|
|||
|
||||
continue;
|
||||
}
|
||||
while (Emu.IsPaused())
|
||||
std::this_thread::sleep_for(10ms);
|
||||
|
||||
std::this_thread::sleep_for(1ms); // hack
|
||||
}
|
||||
|
|
|
@ -131,11 +131,15 @@ namespace rsx
|
|||
public:
|
||||
std::shared_ptr<class ppu_thread> intr_thread;
|
||||
|
||||
// I hate this flag, but until hle is closer to lle, its needed
|
||||
bool isHLE{ false };
|
||||
|
||||
u32 ioAddress, ioSize;
|
||||
u32 flip_status;
|
||||
int debug_level;
|
||||
|
||||
atomic_t<bool> requested_vsync{false};
|
||||
atomic_t<bool> enable_second_vhandler{false};
|
||||
|
||||
RsxDisplayInfo display_buffers[8];
|
||||
u32 display_buffers_count{0};
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "rsx_utils.h"
|
||||
#include "rsx_decode.h"
|
||||
#include "Emu/Cell/PPUCallback.h"
|
||||
#include "Emu/Cell/lv2/sys_rsx.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <cereal/archives/binary.hpp>
|
||||
|
@ -485,6 +486,7 @@ namespace rsx
|
|||
if (in_origin != blit_engine::transfer_origin::corner)
|
||||
{
|
||||
LOG_ERROR(RSX, "NV3089_IMAGE_IN_SIZE: unknown origin (%d)", (u8)in_origin);
|
||||
return;
|
||||
}
|
||||
|
||||
if (operation != rsx::blit_engine::transfer_operation::srccopy)
|
||||
|
@ -879,7 +881,8 @@ namespace rsx
|
|||
rsx->flip(arg);
|
||||
// After each flip PS3 system is executing a routine that changes registers value to some default.
|
||||
// Some game use this default state (SH3).
|
||||
rsx->reset();
|
||||
if (rsx->isHLE)
|
||||
rsx->reset();
|
||||
|
||||
rsx->last_flip_time = get_system_time() - 1000000;
|
||||
rsx->flip_status = CELL_GCM_DISPLAY_FLIP_STATUS_DONE;
|
||||
|
@ -899,6 +902,7 @@ namespace rsx
|
|||
|
||||
void user_command(thread* rsx, u32, u32 arg)
|
||||
{
|
||||
sys_rsx_context_attribute(0x55555555, 0xFEF, 0, arg, 0, 0);
|
||||
if (rsx->user_handler)
|
||||
{
|
||||
rsx->intr_thread->cmd_list
|
||||
|
@ -912,6 +916,31 @@ namespace rsx
|
|||
}
|
||||
}
|
||||
|
||||
namespace gcm
|
||||
{
|
||||
// not entirely sure which one should actually do the flip, or if these should be handled seperately,
|
||||
// so for now lets flip in queue and just let the driver deal with it
|
||||
template<u32 index>
|
||||
struct driver_flip
|
||||
{
|
||||
static void impl(thread* rsx, u32 _reg, u32 arg)
|
||||
{
|
||||
rsx->reset();
|
||||
sys_rsx_context_attribute(0x55555555, 0x102, index, arg, 0, 0);
|
||||
}
|
||||
};
|
||||
|
||||
template<u32 index>
|
||||
struct queue_flip
|
||||
{
|
||||
static void impl(thread* rsx, u32 _reg, u32 arg)
|
||||
{
|
||||
flip_command(rsx, _reg, arg);
|
||||
sys_rsx_context_attribute(0x55555555, 0x103, index, arg, 0, 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void rsx_state::reset()
|
||||
{
|
||||
//setup method registers
|
||||
|
@ -1093,10 +1122,17 @@ namespace rsx
|
|||
methods[NV4097_SET_SURFACE_COLOR_BOFFSET] = nullptr;
|
||||
methods[NV4097_SET_SURFACE_PITCH_B] = nullptr;
|
||||
methods[NV4097_SET_SURFACE_COLOR_TARGET] = nullptr;
|
||||
methods[0x224 >> 2] = nullptr;
|
||||
methods[0x228 >> 2] = nullptr;
|
||||
methods[0x230 >> 2] = nullptr;
|
||||
methods[NV4097_SET_SURFACE_PITCH_Z] = nullptr;
|
||||
methods[NV4097_INVALIDATE_ZCULL] = nullptr;
|
||||
methods[NV4097_SET_CYLINDRICAL_WRAP] = nullptr;
|
||||
methods[NV4097_SET_CYLINDRICAL_WRAP1] = nullptr;
|
||||
methods[0x240 >> 2] = nullptr;
|
||||
methods[0x244 >> 2] = nullptr;
|
||||
methods[0x248 >> 2] = nullptr;
|
||||
methods[0x24C >> 2] = nullptr;
|
||||
methods[NV4097_SET_SURFACE_PITCH_C] = nullptr;
|
||||
methods[NV4097_SET_SURFACE_PITCH_D] = nullptr;
|
||||
methods[NV4097_SET_SURFACE_COLOR_COFFSET] = nullptr;
|
||||
|
@ -1165,6 +1201,7 @@ namespace rsx
|
|||
methods[NV4097_SET_FOG_MODE] = nullptr;
|
||||
methods[NV4097_SET_FOG_PARAMS] = nullptr;
|
||||
methods[NV4097_SET_FOG_PARAMS + 1] = nullptr;
|
||||
methods[0x8d8 >> 2] = nullptr;
|
||||
methods[NV4097_SET_SHADER_PROGRAM] = nullptr;
|
||||
methods[NV4097_SET_VERTEX_TEXTURE_OFFSET] = nullptr;
|
||||
methods[NV4097_SET_VERTEX_TEXTURE_FORMAT] = nullptr;
|
||||
|
@ -1248,6 +1285,7 @@ namespace rsx
|
|||
methods[NV4097_SET_TEXTURE_BORDER_COLOR] = nullptr;
|
||||
methods[NV4097_SET_VERTEX_DATA4F_M] = nullptr;
|
||||
methods[NV4097_SET_COLOR_KEY_COLOR] = nullptr;
|
||||
methods[0x1d04 >> 2] = nullptr;
|
||||
methods[NV4097_SET_SHADER_CONTROL] = nullptr;
|
||||
methods[NV4097_SET_INDEXED_CONSTANT_READ_LIMITS] = nullptr;
|
||||
methods[NV4097_SET_SEMAPHORE_OFFSET] = nullptr;
|
||||
|
@ -1374,6 +1412,8 @@ namespace rsx
|
|||
bind_array<GCM_FLIP_HEAD, 1, 2, nullptr>();
|
||||
bind_array<GCM_DRIVER_QUEUE, 1, 8, nullptr>();
|
||||
|
||||
bind_array<(0x400 >> 2), 1, 0x10, nullptr>();
|
||||
bind_array<(0x440 >> 2), 1, 0x20, nullptr>();
|
||||
bind_array<NV4097_SET_ANISO_SPREAD, 1, 16, nullptr>();
|
||||
bind_array<NV4097_SET_VERTEX_TEXTURE_OFFSET, 1, 8 * 4, nullptr>();
|
||||
bind_array<NV4097_SET_VERTEX_DATA_SCALED4S_M, 1, 32, nullptr>();
|
||||
|
@ -1399,16 +1439,6 @@ namespace rsx
|
|||
bind<NV406E_SEMAPHORE_ACQUIRE, nv406e::semaphore_acquire>();
|
||||
bind<NV406E_SEMAPHORE_RELEASE, nv406e::semaphore_release>();
|
||||
|
||||
/*
|
||||
|
||||
// Store previous fbo addresses to detect RTT config changes.
|
||||
std::array<u32, 4> m_previous_color_address = {};
|
||||
u32 m_previous_address_z = 0;
|
||||
u32 m_previous_target = 0;
|
||||
u32 m_previous_clip_horizontal = 0;
|
||||
u32 m_previous_clip_vertical = 0;
|
||||
*/
|
||||
|
||||
// NV4097
|
||||
bind<NV4097_TEXTURE_READ_SEMAPHORE_RELEASE, nv4097::texture_read_semaphore_release>();
|
||||
bind<NV4097_BACK_END_WRITE_SEMAPHORE_RELEASE, nv4097::back_end_write_semaphore_release>();
|
||||
|
@ -1467,9 +1497,14 @@ namespace rsx
|
|||
//NV0039
|
||||
bind<NV0039_BUFFER_NOTIFY, nv0039::buffer_notify>();
|
||||
|
||||
// lv1 hypervisor
|
||||
bind_array<GCM_SET_USER_COMMAND, 1, 2, user_command>();
|
||||
bind_range<GCM_FLIP_HEAD, 1, 2, gcm::driver_flip>();
|
||||
bind_range<GCM_DRIVER_QUEUE, 1, 8, gcm::queue_flip>();
|
||||
|
||||
// custom methods
|
||||
bind<GCM_FLIP_COMMAND, flip_command>();
|
||||
bind_array<GCM_SET_USER_COMMAND, 1, 2, user_command>();
|
||||
|
||||
|
||||
return true;
|
||||
}();
|
||||
|
|
Loading…
Add table
Reference in a new issue