From b456955688106ff24f3812a43c21c519c7b7c21c Mon Sep 17 00:00:00 2001 From: eladash Date: Sat, 2 Jun 2018 18:59:52 +0300 Subject: [PATCH] rsx: fix hardcoded rsx allocation address --- rpcs3/Emu/Cell/Modules/cellGcmSys.cpp | 32 ++++++++++++------- rpcs3/Emu/Cell/lv2/sys_mmapper.cpp | 8 ++--- rpcs3/Emu/Cell/lv2/sys_rsx.cpp | 45 ++++++++++++++++++--------- rpcs3/Emu/Cell/lv2/sys_rsx.h | 3 +- rpcs3/Emu/Cell/lv2/sys_vm.cpp | 2 +- rpcs3/Emu/Memory/vm.cpp | 1 - rpcs3/Emu/RSX/RSXThread.cpp | 8 ++--- rpcs3/Emu/RSX/rsx_methods.cpp | 2 +- 8 files changed, 63 insertions(+), 38 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp b/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp index df5db6ba64..f84baa74d5 100644 --- a/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp @@ -102,7 +102,7 @@ vm::ptr cellGcmGetReportDataAddressLocation(u32 index, u32 lo cellGcmSys.error("cellGcmGetReportDataAddressLocation: Wrong local index (%d)", index); return vm::null; } - return vm::ptr::make(0x40301400 + index * 0x10); + return vm::ptr::make(fxm::get()->gcm_info.label_addr + 0x1400 + index * 0x10); } if (location == CELL_GCM_LOCATION_MAIN) { @@ -125,7 +125,7 @@ u64 cellGcmGetTimeStamp(u32 index) cellGcmSys.error("cellGcmGetTimeStamp: Wrong local index (%d)", index); return 0; } - return vm::read64(0x40301400 + index * 0x10); + return vm::read64(fxm::get()->gcm_info.label_addr + 0x1400 + index * 0x10); } u32 cellGcmGetCurrentField() @@ -152,7 +152,7 @@ u32 cellGcmGetNotifyDataAddress(u32 index) */ vm::ptr _cellGcmFunc12() { - return vm::ptr::make(0x40301400); // TODO + return vm::ptr::make(fxm::get()->gcm_info.label_addr + 0x1400); // TODO } u32 cellGcmGetReport(u32 type, u32 index) @@ -180,7 +180,7 @@ u32 cellGcmGetReportDataAddress(u32 index) cellGcmSys.error("cellGcmGetReportDataAddress: Wrong local index (%d)", index); return 0; } - return 0x40301400 + index * 0x10; + return fxm::get()->gcm_info.label_addr + 0x1400 + index * 0x10; } u32 cellGcmGetReportDataLocation(u32 index, u32 location) @@ -200,7 +200,7 @@ u64 cellGcmGetTimeStampLocation(u32 index, u32 location) cellGcmSys.error("cellGcmGetTimeStampLocation: Wrong local index (%d)", index); return 0; } - return vm::read64(0x40301400 + index * 0x10); + return vm::read64(fxm::get()->gcm_info.label_addr + 0x1400 + index * 0x10); } if (location == CELL_GCM_LOCATION_MAIN) { @@ -390,16 +390,25 @@ s32 _cellGcmInitBody(vm::pptr context, u32 cmdSize, u32 ioSi // Create contexts - u32 addr = vm::falloc(0x40000000, 0x400000); - if (addr == 0 || addr != 0x40000000) - fmt::throw_exception("Failed to alloc 0x40000000."); + u32 rsx_ctxaddr = 0; + for (u32 addr = 0x40000000; addr < 0xC0000000; addr += 0x10000000) + { + if (vm::map(addr, 0x10000000, 0x400)) + { + rsx_ctxaddr = addr; + break; + } + } + + if (!rsx_ctxaddr || vm::falloc(rsx_ctxaddr, 0x400000) != rsx_ctxaddr) + fmt::throw_exception("Failed to alloc rsx context."); g_defaultCommandBufferBegin = ioAddress; g_defaultCommandBufferFragmentCount = cmdSize / (32 * 1024); - m_config->gcm_info.context_addr = 0x40000000; - m_config->gcm_info.control_addr = 0x40100000; - m_config->gcm_info.label_addr = 0x40300000; + m_config->gcm_info.context_addr = rsx_ctxaddr; + m_config->gcm_info.control_addr = rsx_ctxaddr + 0x100000; + m_config->gcm_info.label_addr = rsx_ctxaddr + 0x300000; m_config->current_context.begin.set(g_defaultCommandBufferBegin + 4096); // 4 kb reserved at the beginning m_config->current_context.end.set(g_defaultCommandBufferBegin + 32 * 1024 - 4); // 4b at the end for jump @@ -427,6 +436,7 @@ s32 _cellGcmInitBody(vm::pptr context, u32 cmdSize, u32 ioSi render->main_mem_addr = 0; render->isHLE = true; render->label_addr = m_config->gcm_info.label_addr; + render->ctxt_addr = m_config->gcm_info.context_addr; render->init(ioAddress, ioSize, m_config->gcm_info.control_addr - 0x40, local_addr); return CELL_OK; diff --git a/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp b/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp index 571b3164aa..86f54df6ba 100644 --- a/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp @@ -45,7 +45,7 @@ error_code sys_mmapper_allocate_address(u64 size, u64 flags, u64 alignment, vm:: case 0x40000000: case 0x80000000: { - for (u64 addr = ::align(0x50000000, alignment); addr < 0xC0000000; addr += alignment) + for (u64 addr = ::align(0x40000000, alignment); addr < 0xC0000000; addr += alignment) { if (const auto area = vm::map(static_cast(addr), static_cast(size), flags)) { @@ -272,7 +272,7 @@ error_code sys_mmapper_map_shared_memory(u32 addr, u32 mem_id, u64 flags) const auto area = vm::get(vm::any, addr); - if (!area || addr < 0x50000000 || addr >= 0xC0000000) + if (!area || addr < 0x40000000 || addr >= 0xC0000000) { return CELL_EINVAL; } @@ -320,7 +320,7 @@ error_code sys_mmapper_search_and_map(u32 start_addr, u32 mem_id, u64 flags, vm: const auto area = vm::get(vm::any, start_addr); - if (!area || start_addr < 0x50000000 || start_addr >= 0xC0000000) + if (!area || start_addr < 0x40000000 || start_addr >= 0xC0000000) { return {CELL_EINVAL, start_addr}; } @@ -353,7 +353,7 @@ error_code sys_mmapper_unmap_shared_memory(u32 addr, vm::ptr mem_id) const auto area = vm::get(vm::any, addr); - if (!area || addr < 0x50000000 || addr >= 0xC0000000) + if (!area || addr < 0x40000000 || addr >= 0xC0000000) { return {CELL_EINVAL, addr}; } diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp index 4d0fdcfa8f..c6bf5c09b0 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp @@ -76,19 +76,16 @@ s32 sys_rsx_context_allocate(vm::ptr context_id, vm::ptr lpar_dma_cont 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(); - if (!m_sysrsx) - fmt::throw_exception("sys_rsx_context_allocate called twice."); + auto m_sysrsx = fxm::get(); - u32 addr = vm::falloc(0x40000000, 0x400000); - if (addr == 0 || addr != 0x40000000) - fmt::throw_exception("Failed to alloc 0x40000000."); + if (!m_sysrsx) // TODO: check if called twice + return CELL_EINVAL; *context_id = 0x55555555; - *lpar_dma_control = 0x40100000; - *lpar_driver_info = 0x40200000; - *lpar_reports = 0x40300000; + *lpar_dma_control = m_sysrsx->rsx_context_addr + 0x100000; + *lpar_driver_info = m_sysrsx->rsx_context_addr + 0x200000; + *lpar_reports = m_sysrsx->rsx_context_addr + 0x300000; auto &reports = vm::_ref(*lpar_reports); std::memset(&reports, 0, sizeof(RsxReports)); @@ -149,6 +146,7 @@ s32 sys_rsx_context_allocate(vm::ptr context_id, vm::ptr lpar_dma_cont render->current_display_buffer = 0; render->main_mem_addr = 0; render->label_addr = *lpar_reports; + render->ctxt_addr = m_sysrsx->rsx_context_addr; render->init(0, 0, *lpar_dma_control, 0xC0000000); return CELL_OK; @@ -258,7 +256,7 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6 // 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(0x40300010) = 0; + vm::_ref(render->label_addr + 0x10) = 0; if (a3 == 0) sys_event_port_send(m_sysrsx->rsx_event_port, 0, (1 << 3), 0); if (a3 == 1) @@ -403,13 +401,13 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6 /* * lv2 SysCall 675 (0x2A3): sys_rsx_device_map - * @param a1 (OUT): For example: In vsh.self it is 0x60000000, global semaphore. For a game it is 0x40000000. + * @param a1 (OUT): rsx device map address : 0x40000000, 0x50000000.. 0xB0000000 * @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 dev_addr, vm::ptr a2, u32 dev_id) { - sys_rsx.warning("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(dev_addr=*0x%x, a2=*0x%x, dev_id=0x%x)", dev_addr, a2, dev_id); if (dev_id != 8) { // TODO: lv1 related @@ -419,9 +417,26 @@ s32 sys_rsx_device_map(vm::ptr addr, vm::ptr a2, u32 dev_id) // a2 seems to not be referenced in cellGcmSys, tests show this arg is ignored //*a2 = 0; - *addr = 0x40000000; + auto m_sysrsx = fxm::make(); - return CELL_OK; + if (!m_sysrsx) + { + return CELL_EINVAL; // sys_rsx_device_map called twice + } + + for (u32 addr = 0x40000000; addr < 0xC0000000; addr += 0x10000000) + { + if (vm::map(addr, 0x10000000, 0x400)) + { + vm::falloc(addr, 0x400000); + + m_sysrsx->rsx_context_addr = *dev_addr = addr; + + return CELL_OK; + } + } + + return CELL_ENOMEM; } /* diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.h b/rpcs3/Emu/Cell/lv2/sys_rsx.h index efb66e8f4d..df71049351 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.h +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.h @@ -103,6 +103,7 @@ struct SysRsxConfig { be_t rsx_event_port{ 0 }; u32 driverInfo{ 0 }; + u32 rsx_context_addr{ 0 }; }; // SysCalls @@ -115,6 +116,6 @@ 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::ptr addr, vm::ptr a2, u32 dev_id); +s32 sys_rsx_device_map(vm::ptr dev_addr, vm::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); \ No newline at end of file diff --git a/rpcs3/Emu/Cell/lv2/sys_vm.cpp b/rpcs3/Emu/Cell/lv2/sys_vm.cpp index 86115a4e94..ca882350c3 100644 --- a/rpcs3/Emu/Cell/lv2/sys_vm.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_vm.cpp @@ -21,7 +21,7 @@ error_code sys_vm_memory_map(u32 vsize, u32 psize, u32 cid, u64 flag, u64 policy } // Look for unmapped space (roughly) - for (u32 found = 0x60000000; found <= 0xC0000000 - vsize; found += 0x2000000) + for (u32 found = 0x40000000; found <= 0xC0000000 - vsize; found += 0x1000000) { // Try to map if (const auto area = vm::map(found, vsize, flag)) diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 1ba9dc4356..9650d02a9d 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -798,7 +798,6 @@ namespace vm std::make_shared(0xC0000000, 0x10000000), // video std::make_shared(0xD0000000, 0x10000000), // stack std::make_shared(0xE0000000, 0x20000000), // SPU reserved - std::make_shared(0x40000000, 0x10000000), // rsx contexts std::make_shared(0x30000000, 0x10000000), // main extend }; } diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 92ff99188d..ee12f56001 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -62,7 +62,7 @@ namespace rsx } case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_LOCAL: - return 0x40301400 + offset; + return get_current_renderer()->label_addr + 0x1400 + offset; case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_MAIN: { @@ -82,13 +82,13 @@ namespace rsx case CELL_GCM_CONTEXT_DMA_SEMAPHORE_RW: case CELL_GCM_CONTEXT_DMA_SEMAPHORE_R: - return 0x40300000 + offset; + return get_current_renderer()->label_addr + offset; case CELL_GCM_CONTEXT_DMA_DEVICE_RW: - return 0x40000000 + offset; + return get_current_renderer()->ctxt_addr + offset; case CELL_GCM_CONTEXT_DMA_DEVICE_R: - return 0x40000000 + offset; + return get_current_renderer()->ctxt_addr + offset; default: fmt::throw_exception("Invalid location (offset=0x%x, location=0x%x)" HERE, offset, location); diff --git a/rpcs3/Emu/RSX/rsx_methods.cpp b/rpcs3/Emu/RSX/rsx_methods.cpp index f44eea9c24..d54b57869b 100644 --- a/rpcs3/Emu/RSX/rsx_methods.cpp +++ b/rpcs3/Emu/RSX/rsx_methods.cpp @@ -72,7 +72,7 @@ namespace rsx while (vm::read32(addr) != arg) { // todo: LLE: why does this one keep hanging? is it vsh system semaphore? whats actually pushing this to the command buffer?! - if (addr == 0x40000030) + if (addr == get_current_renderer()->ctxt_addr + 0x30) return; if (Emu.IsStopped())