diff --git a/rpcs3/Emu/Cell/Modules/cellSpurs.cpp b/rpcs3/Emu/Cell/Modules/cellSpurs.cpp index 6cb515683d..a12e591c7a 100644 --- a/rpcs3/Emu/Cell/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/Cell/Modules/cellSpurs.cpp @@ -880,7 +880,7 @@ s32 _spurs::stop_event_helper(ppu_thread& ppu, vm::ptr 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 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) diff --git a/rpcs3/Emu/Cell/lv2/sys_prx.cpp b/rpcs3/Emu/Cell/lv2/sys_prx.cpp index bf80f0c0ab..43d7497da3 100644 --- a/rpcs3/Emu/Cell/lv2/sys_prx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_prx.cpp @@ -24,7 +24,7 @@ static const std::unordered_map s_prx_ignore { "/dev_flash/sys/external/libaudio.sprx", 0 }, { "/dev_flash/sys/external/libbeisobmf.sprx", 0 }, { "/dev_flash/sys/external/libcamera.sprx", 0 }, - { "/dev_flash/sys/external/libgcm_sys.sprx", 0 }, + //{ "/dev_flash/sys/external/libgcm_sys.sprx", 0 }, { "/dev_flash/sys/external/libgem.sprx", 0 }, { "/dev_flash/sys/external/libio.sprx", 0 }, { "/dev_flash/sys/external/libmedi.sprx", 0 }, diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp index 2cb5ba9945..5ac5cbd060 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp @@ -1,14 +1,75 @@ #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"); +struct RsxDriverInfo { + be_t version_driver; + be_t version_gpu; + be_t memory_size; + be_t hardware_channel; + be_t nvcore_frequency; + be_t memory_frequency; + u8 unk[0x10A8]; + struct Head { + be_t flip; + be_t unk[4]; + be_t unk1; + be_t unk2[5]; + be_t unk3; + be_t unk4[4]; + } head[8]; + be_t handlers; + be_t unk1; + be_t unk2; + be_t unk3; + be_t handler_queue; +}; + +struct RsxDmaControl { + u8 resv[0x40]; + be_t put; + be_t get; + be_t ref; + be_t unk[2]; + be_t unk1; +}; + +struct RsxSemaphore { + be_t val; + be_t pad; + be_t timestamp; +}; + +struct RsxNotify { + be_t timestamp; + be_t zero; +}; + +struct RsxReport { + be_t timestamp; + be_t val; + be_t pad; +}; + +struct RsxReports { + RsxSemaphore semaphore[0x100]; + RsxNotify notify[64]; + RsxReport report[2048]; +}; + +be_t g_rsx_event_port; +u32 g_driverInfo; + s32 sys_rsx_device_open() { sys_rsx.todo("sys_rsx_device_open()"); @@ -37,6 +98,9 @@ s32 sys_rsx_memory_allocate(vm::ptr mem_handle, vm::ptr mem_addr, u32 { 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); + *mem_handle = 1; + *mem_addr = vm::falloc(0xC0000000, size, vm::video); + return CELL_OK; } @@ -60,10 +124,62 @@ 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 context_id, vm::ptr lpar_dma_control, vm::ptr lpar_driver_info, vm::ptr lpar_reports, u64 mem_ctx, u64 system_mode) +s32 sys_rsx_context_allocate(vm::ptr context_id, vm::ptr lpar_dma_control, vm::ptr lpar_driver_info, vm::ptr 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)", - context_id, lpar_dma_control, lpar_driver_info, lpar_reports, mem_ctx, 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)", + context_id, lpar_dma_control, lpar_driver_info, lpar_reports, mem_ctx, system_mode); + + vm::falloc(0x40000000, 0x10000000, vm::rsx_context); + + *context_id = 0x55555555; + + *lpar_dma_control = 0x40100000; + *lpar_driver_info = 0x40200000; + *lpar_reports = 0x40300000; + + auto &driverInfo = vm::_ref(*lpar_driver_info); + driverInfo.version_driver = 0x211; + driverInfo.version_gpu = 0x5c; + driverInfo.memory_size = 0xFE00000; + driverInfo.nvcore_frequency = 500000000; + driverInfo.memory_frequency = 650000000; + + g_driverInfo = *lpar_driver_info; + + auto &dmaControl = vm::_ref(*lpar_dma_control); + dmaControl.get = 0; + dmaControl.put = 0; + + 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(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); + + g_rsx_event_port = queueId->value(); + + const auto render = fxm::get(); + render->ctrl = vm::_ptr(*lpar_dma_control); + //render->intr_thread = idm::make_ptr("_gcm_intr_thread", 1, 0x4000); + //render->intr_thread->run(); + //render->ctxt_addr = 0; + render->gcm_buffers.set(vm::alloc(sizeof(CellGcmDisplayInfo) * 8, vm::main)); + render->zculls_addr = vm::alloc(sizeof(CellGcmZcullInfo) * 8, vm::main); + render->tiles_addr = vm::alloc(sizeof(CellGcmTileInfo) * 15, vm::main); + render->gcm_buffers_count = 7; + render->gcm_current_buffer = 0; + render->main_mem_addr = 0; + render->label_addr = *lpar_reports; + render->init(0x30100000, 0x200000, *lpar_dma_control, 0xC0000000); return CELL_OK; } @@ -90,8 +206,10 @@ 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; + if (RSXIOMem.Map(ea, size, io)) + return CELL_OK; + LOG_ERROR(RSX, "rsx_iomap failed"); + return CELL_EINVAL; } /* @@ -101,11 +219,13 @@ 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.todo("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; + LOG_ERROR(RSX, "rsx_iounmap failed"); + return CELL_EINVAL; } /* @@ -120,33 +240,64 @@ 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) { 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); - + const auto render = fxm::get(); + auto &driverInfo = vm::_ref(g_driverInfo); switch(package_id) { case 0x001: // FIFO + render->ctrl->get = a3; + render->ctrl->put = a4; break; case 0x100: // Display mode set - break; - - case 0x101: // Display sync + case 0x101: // Display sync break; case 0x102: // Display flip + driverInfo.head[a3].flip |= 0x80000000; + if (a3 == 0) + sys_event_port_send(g_rsx_event_port, 0, (1 << 3), 0); + if (a3 == 1) + sys_event_port_send(g_rsx_event_port, 0, (1 << 4), 0); break; - case 0x103: // ? + case 0x103: // Display Queue + driverInfo.head[a3].flip |= 0x40000000 | (1 << a4); + if (a3 == 0) + sys_event_port_send(g_rsx_event_port, 0, (1 << 5), 0); + if (a3 == 1) + sys_event_port_send(g_rsx_event_port, 0, (1 << 6), 0); break; case 0x104: // Display buffer - break; + { + 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->gcm_buffers[id].width = width; + render->gcm_buffers[id].height = height; + render->gcm_buffers[id].pitch = pitch; + render->gcm_buffers[id].offset = offset; + } + break; case 0x106: // ? (Used by cellGcmInitPerfMon) break; case 0x10a: // ? + if (a3 > 7) + return -17; + driverInfo.head[a3].flip &= a4; + driverInfo.head[a3].flip |= a5; break; + case 0x10D: // ? + break; + case 0x300: // Tiles break; @@ -162,6 +313,9 @@ 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; + default: return CELL_EINVAL; } @@ -175,19 +329,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 addr, vm::ptr a2, u32 dev_id) +s32 sys_rsx_device_map(vm::ptr addr, vm::ptr 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); - 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; } diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.h b/rpcs3/Emu/Cell/lv2/sys_rsx.h index 91caa0b307..115454266f 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.h +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.h @@ -5,11 +5,11 @@ s32 sys_rsx_device_open(); s32 sys_rsx_device_close(); s32 sys_rsx_memory_allocate(vm::ps3::ptr mem_handle, vm::ps3::ptr 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 context_id, vm::ps3::ptr lpar_dma_control, vm::ps3::ptr lpar_driver_info, vm::ps3::ptr lpar_reports, u64 mem_ctx, u64 system_mode); +s32 sys_rsx_context_allocate(vm::ps3::ptr context_id, vm::ps3::ptr lpar_dma_control, vm::ps3::ptr lpar_driver_info, vm::ps3::ptr 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 addr, vm::ps3::ptr a2, u32 dev_id); +s32 sys_rsx_device_map(vm::ps3::ptr addr, vm::ps3::ptr 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); diff --git a/rpcs3/Emu/Memory/Memory.cpp b/rpcs3/Emu/Memory/Memory.cpp index 8b1015ebde..d4886ba735 100644 --- a/rpcs3/Emu/Memory/Memory.cpp +++ b/rpcs3/Emu/Memory/Memory.cpp @@ -55,13 +55,13 @@ bool VirtualMemoryBlock::Map(u32 realaddr, u32 size, u32 addr) return false; } - for (u32 i = 0; i= m_mapped_memory[i].addr && addr + size - 1 <= m_mapped_memory[i].addr + m_mapped_memory[i].size - 1) { return false; } - } + }*/ m_mapped_memory.emplace_back(addr, realaddr, size); return true; diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 4bbcb96de2..9933be6b74 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -781,6 +781,7 @@ namespace vm { std::make_shared(0x00010000, 0x1FFF0000), // main std::make_shared(0x20000000, 0x10000000), // user + std::make_shared(0x40000000, 0x30000000), // rsx contexts std::make_shared(0xC0000000, 0x10000000), // video std::make_shared(0xD0000000, 0x10000000), // stack std::make_shared(0xE0000000, 0x20000000), // SPU reserved diff --git a/rpcs3/Emu/Memory/vm.h b/rpcs3/Emu/Memory/vm.h index b0bd873d18..255dd26979 100644 --- a/rpcs3/Emu/Memory/vm.h +++ b/rpcs3/Emu/Memory/vm.h @@ -16,6 +16,7 @@ namespace vm { main, user_space, + rsx_context, video, stack, diff --git a/rpcs3/Emu/RSX/GCM.h b/rpcs3/Emu/RSX/GCM.h index 99bce3daf7..e2bc14a168 100644 --- a/rpcs3/Emu/RSX/GCM.h +++ b/rpcs3/Emu/RSX/GCM.h @@ -7,11 +7,21 @@ struct CellGcmControl { - atomic_be_t put; - atomic_be_t get; - atomic_be_t ref; + u8 resv[0x40]; + atomic_be_t put; + atomic_be_t get; + atomic_be_t ref; + be_t unk[2]; + be_t unk1; }; +/*struct CellGcmControl +{ + atomic_be_t put; + atomic_be_t get; + atomic_be_t ref; +};*/ + struct CellGcmConfig { be_t localAddress; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 98a37465e4..07293c4247 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -57,8 +57,9 @@ namespace rsx //} } - case CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_REPORT: - return 0x100000 + offset; // TODO: Properly implement + case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_LOCAL: + return 0x40300000 + offset; + //return 0x100000 + offset; // TODO: Properly implement case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_MAIN: return 0x800 + offset; // TODO: Properly implement @@ -71,13 +72,16 @@ namespace rsx case CELL_GCM_CONTEXT_DMA_SEMAPHORE_RW: case CELL_GCM_CONTEXT_DMA_SEMAPHORE_R: - return 0x100 + offset; // TODO: Properly implement + return 0x40100000 + offset; + //return 0x100 + offset; // TODO: Properly implement case CELL_GCM_CONTEXT_DMA_DEVICE_RW: - fmt::throw_exception("Unimplemented CELL_GCM_CONTEXT_DMA_DEVICE_RW (offset=0x%x, location=0x%x)" HERE, offset, location); + return 0x40000000 + offset; + //fmt::throw_exception("Unimplemented CELL_GCM_CONTEXT_DMA_DEVICE_RW (offset=0x%x, location=0x%x)" HERE, offset, location); case CELL_GCM_CONTEXT_DMA_DEVICE_R: - fmt::throw_exception("Unimplemented CELL_GCM_CONTEXT_DMA_DEVICE_R (offset=0x%x, location=0x%x)" HERE, offset, location); + return 0x40000000 + offset; + //fmt::throw_exception("Unimplemented CELL_GCM_CONTEXT_DMA_DEVICE_R (offset=0x%x, location=0x%x)" HERE, offset, location); default: fmt::throw_exception("Invalid location (offset=0x%x, location=0x%x)" HERE, offset, location); @@ -500,7 +504,7 @@ namespace rsx u32 reg = ((cmd & RSX_METHOD_NON_INCREMENT_CMD_MASK) == RSX_METHOD_NON_INCREMENT_CMD) ? first_cmd : first_cmd + i; u32 value = args[i]; - //LOG_NOTICE(RSX, "%s(0x%x) = 0x%x", get_method_name(reg).c_str(), reg, value); + //LOG_WARNING(RSX, "%s(0x%x) = 0x%x", get_method_name(reg).c_str(), reg, value); method_registers.decode(reg, value); diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 9f3a12cdbf..9869e48b58 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -142,6 +142,8 @@ namespace rsx u32 gcm_current_buffer; u32 ctxt_addr; u32 label_addr; + u32 nv406e_semaphore_addr; + u32 nv4097_semaphore_index; u32 local_mem_addr, main_mem_addr; bool strict_ordering[0x1000]; diff --git a/rpcs3/Emu/RSX/gcm_enums.cpp b/rpcs3/Emu/RSX/gcm_enums.cpp index f2573841db..cd667e6090 100644 --- a/rpcs3/Emu/RSX/gcm_enums.cpp +++ b/rpcs3/Emu/RSX/gcm_enums.cpp @@ -968,7 +968,7 @@ rsx::blit_engine::context_dma rsx::blit_engine::to_context_dma(u32 in) { switch (in) { - case CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_REPORT: return rsx::blit_engine::context_dma::to_memory_get_report; + case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_LOCAL: return rsx::blit_engine::context_dma::to_memory_get_report; case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_MAIN: return rsx::blit_engine::context_dma::report_location_main; case CELL_GCM_CONTEXT_DMA_MEMORY_HOST_BUFFER: return rsx::blit_engine::context_dma::memory_host_buffer; } diff --git a/rpcs3/Emu/RSX/gcm_enums.h b/rpcs3/Emu/RSX/gcm_enums.h index ae22ce2040..f8e1066cb8 100644 --- a/rpcs3/Emu/RSX/gcm_enums.h +++ b/rpcs3/Emu/RSX/gcm_enums.h @@ -704,7 +704,7 @@ enum { CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER = 0xFEED0000, // Local memory CELL_GCM_CONTEXT_DMA_MEMORY_HOST_BUFFER = 0xFEED0001, // Main memory - CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_REPORT = 0x66626660, + CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_LOCAL = 0x66626660, CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_MAIN = 0xBAD68000, CELL_GCM_CONTEXT_DMA_NOTIFY_MAIN_0 = 0x6660420F, diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index 93fc7f5b81..c8697cd9a7 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -6,12 +6,15 @@ #include "rsx_utils.h" #include "rsx_decode.h" #include "Emu/Cell/PPUCallback.h" +#include "Emu/Cell/lv2/sys_rsx.h" #include #include #include +#include + template <> void fmt_class_string::format(std::string& out, u64 arg) { @@ -58,11 +61,20 @@ namespace rsx rsx->ctrl->ref.exchange(arg); } + void set_context_dma_semaphore(thread* rsx, u32 _reg, u32 arg) + { + LOG_ERROR(RSX, "dmaSemaphore: 0x%x", arg); + rsx->nv406e_semaphore_addr = arg; + } + void semaphore_acquire(thread* rsx, u32 _reg, u32 arg) { //TODO: dma - while (vm::ps3::read32(rsx->label_addr + method_registers.semaphore_offset_406e()) != arg) + //while (vm::ps3::read32(rsx->label_addr + method_registers.semaphore_offset_406e()) != arg) + const u32 addr = get_address(method_registers.semaphore_offset_406e(), rsx->nv406e_semaphore_addr); + while (vm::ps3::read32(addr) != arg) { + break; if (Emu.IsStopped()) break; @@ -73,10 +85,51 @@ namespace rsx void semaphore_release(thread* rsx, u32 _reg, u32 arg) { //TODO: dma - vm::ps3::write32(rsx->label_addr + method_registers.semaphore_offset_406e(), arg); + //vm::ps3::write32(rsx->label_addr + method_registers.semaphore_offset_406e(), arg); + const u32 addr = get_address(method_registers.semaphore_offset_406e(), rsx->nv406e_semaphore_addr); + vm::ps3::write32(addr, arg); } } + struct RsxSemaphore { + be_t val; + be_t pad; + be_t timestamp; + }; + + struct RsxNotify { + be_t timestamp; + be_t zero; + }; + + struct RsxReport { + be_t timestamp; + be_t val; + be_t pad; + }; + + struct RsxReports { + RsxSemaphore semaphore[0x100]; + RsxNotify notify[64]; + RsxReport report[2048]; + }; + + u64 ptimer_gettime() { + static struct PerformanceFreqHolder { + u64 value; + PerformanceFreqHolder() { + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + value = freq.QuadPart; + } + } freq; + + LARGE_INTEGER cycle; + QueryPerformanceCounter(&cycle); + const u64 sec = cycle.QuadPart / freq.value; + return sec * 1000000000 + (cycle.QuadPart % freq.value) * 1000000000 / freq.value; + } + namespace nv4097 { void clear(thread* rsx, u32 _reg, u32 arg) @@ -93,6 +146,11 @@ namespace rsx } } + /*void set_context_dma_semaphore(thread* rsx, u32 _reg, u32 arg) + { + rsx->nv4097_semaphore_index = arg >> 4; + }*/ + void texture_read_semaphore_release(thread* rsx, u32 _reg, u32 arg) { if (!rsx->do_method(NV4097_TEXTURE_READ_SEMAPHORE_RELEASE, arg)) @@ -101,7 +159,15 @@ namespace rsx } //TODO: dma - vm::ps3::write32(rsx->label_addr + method_registers.semaphore_offset_4097(), arg); + //vm::ps3::write32(rsx->label_addr + method_registers.semaphore_offset_4097(), arg); + //const u32 addr = get_address(method_registers.semaphore_offset_4097(), rsx->nv4097_semaphore_index); + //vm::ps3::write32(addr, arg); + const u32 index = method_registers.semaphore_offset_4097() >> 4; + LOG_ERROR(RSX, "readrelease: 0x%x, 0x%x, addr:0x%x", arg, index, rsx->label_addr); + auto& sema = vm::ps3::_ref(rsx->label_addr); + sema.semaphore[index].val = arg; + sema.semaphore[index].pad = 0; + sema.semaphore[index].timestamp = ptimer_gettime(); } void back_end_write_semaphore_release(thread* rsx, u32 _reg, u32 arg) @@ -112,8 +178,18 @@ namespace rsx } //TODO: dma - vm::ps3::write32(rsx->label_addr + method_registers.semaphore_offset_4097(), - (arg & 0xff00ff00) | ((arg & 0xff) << 16) | ((arg >> 16) & 0xff)); + //vm::ps3::write32(rsx->label_addr + method_registers.semaphore_offset_4097(), + // (arg & 0xff00ff00) | ((arg & 0xff) << 16) | ((arg >> 16) & 0xff)); + //const u32 addr = get_address(method_registers.semaphore_offset_4097(), rsx->nv4097_semaphore_addr); + //vm::ps3::write32(addr, (arg & 0xff00ff00) | ((arg & 0xff) << 16) | ((arg >> 16) & 0xff)); + const u32 index = method_registers.semaphore_offset_4097() >> 4; + u32 val = (arg & 0xff00ff00) | ((arg & 0xff) << 16) | ((arg >> 16) & 0xff); + LOG_ERROR(RSX, "wriuterelease: 0x%x, 0x%x, addr:0x%x", val, index, rsx->label_addr); + auto& sema = vm::ps3::_ref(rsx->label_addr); + sema.semaphore[index].val = val; + sema.semaphore[index].pad = 0; + sema.semaphore[index].timestamp = ptimer_gettime(); + } template @@ -472,6 +548,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) @@ -900,6 +977,28 @@ namespace rsx } } + namespace gcm + { + template + struct driver_flip + { + static void impl(thread* rsx, u32 _reg, u32 arg) + { + sys_rsx_context_attribute(0x55555555, 0x102, index, arg, 0, 0); + } + }; + + template + 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 @@ -971,7 +1070,7 @@ namespace rsx registers[NV4097_SET_SURFACE_FORMAT] = (8 << 0) | (2 << 5) | (0 << 12) | (1 << 16) | (1 << 24); // rsx dma initial values - registers[NV4097_SET_CONTEXT_DMA_REPORT] = CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_REPORT; + registers[NV4097_SET_CONTEXT_DMA_REPORT] = CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_LOCAL; registers[NV406E_SET_CONTEXT_DMA_SEMAPHORE] = CELL_GCM_CONTEXT_DMA_SEMAPHORE_RW; registers[NV3062_SET_CONTEXT_DMA_IMAGE_DESTIN] = CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER; registers[NV309E_SET_CONTEXT_DMA_IMAGE] = CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER; @@ -1081,10 +1180,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; @@ -1153,6 +1259,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; @@ -1362,6 +1469,8 @@ namespace rsx bind_array(); bind_array(); + bind_array<(0x400 >> 2), 1, 0x10, nullptr>(); + bind_array<(0x440 >> 2), 1, 0x20, nullptr>(); bind_array(); bind_array(); bind_array(); @@ -1384,6 +1493,7 @@ namespace rsx // NV406E bind(); + bind(); bind(); bind(); @@ -1398,6 +1508,7 @@ namespace rsx */ // NV4097 + //bind(); bind(); bind(); bind(); @@ -1459,6 +1570,9 @@ namespace rsx bind(); bind_array(); + bind_range(); + bind_range(); + return true; }(); }