diff --git a/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp b/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp index 75a6b6e683..c6aada414c 100644 --- a/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp @@ -428,6 +428,7 @@ s32 _cellGcmInitBody(ppu_thread& ppu, vm::pptr context, u32 render->isHLE = true; render->label_addr = gcm_cfg->gcm_info.label_addr; render->device_addr = gcm_cfg->gcm_info.context_addr; + render->local_mem_size = local_size; render->init(gcm_cfg->gcm_info.control_addr - 0x40); return CELL_OK; diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp index 8406d66e1e..624cf25094 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp @@ -210,6 +210,7 @@ error_code sys_rsx_context_allocate(vm::ptr context_id, vm::ptr lpar_d render->current_display_buffer = 0; render->label_addr = *lpar_reports; render->device_addr = rsx_cfg->device_addr; + render->local_mem_size = rsx_cfg->memory_size; render->init(*lpar_dma_control); rsx_cfg->context_base = context_base; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 4043569cc1..e4b741f938 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -48,13 +48,19 @@ namespace rsx u32 get_address(u32 offset, u32 location) { + const auto render = get_current_renderer(); switch (location) { case CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER: case CELL_GCM_LOCATION_LOCAL: { - return rsx::constants::local_mem_base + offset; + if (offset < render->local_mem_size) + { + return rsx::constants::local_mem_base + offset; + } + + fmt::throw_exception("GetAddress(offset=0x%x, location=0x%x): Local RSX offset out of range" HERE, offset, location); } case CELL_GCM_CONTEXT_DMA_MEMORY_HOST_BUFFER: @@ -69,7 +75,14 @@ namespace rsx } case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_LOCAL: - return get_current_renderer()->label_addr + 0x1400 + offset; + { + if (offset < sizeof(RsxReports::report) /*&& (offset % 0x10) == 0*/) + { + return render->label_addr + 0x1400 + offset; + } + + fmt::throw_exception("GetAddress(offset=0x%x, location=0x%x): Local RSX REPORT offset out of range" HERE, offset, location); + } case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_MAIN: { @@ -81,21 +94,36 @@ namespace rsx fmt::throw_exception("GetAddress(offset=0x%x, location=0x%x): RSXIO memory not mapped" HERE, offset, location); } + // They are handled elsewhere for targeted methods, so it's unexpected for them to be passed here case CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY0: - fmt::throw_exception("Unimplemented CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY0 (offset=0x%x, location=0x%x)" HERE, offset, location); + fmt::throw_exception("Unexpected CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY0 (offset=0x%x, location=0x%x)" HERE, offset, location); case CELL_GCM_CONTEXT_DMA_NOTIFY_MAIN_0: - fmt::throw_exception("Unimplemented CELL_GCM_CONTEXT_DMA_NOTIFY_MAIN_0 (offset=0x%x, location=0x%x)" HERE, offset, location); + fmt::throw_exception("Unexpected CELL_GCM_CONTEXT_DMA_NOTIFY_MAIN_0 (offset=0x%x, location=0x%x)" HERE, offset, location); case CELL_GCM_CONTEXT_DMA_SEMAPHORE_RW: case CELL_GCM_CONTEXT_DMA_SEMAPHORE_R: - return get_current_renderer()->label_addr + offset; + { + if (offset < sizeof(RsxReports::semaphore) /*&& (offset % 0x10) == 0*/) + { + return render->label_addr + offset; + } + + fmt::throw_exception("GetAddress(offset=0x%x, location=0x%x): DMA SEMAPHORE offset out of range" HERE, offset, location); + } case CELL_GCM_CONTEXT_DMA_DEVICE_RW: - return get_current_renderer()->device_addr + offset; - case CELL_GCM_CONTEXT_DMA_DEVICE_R: - return get_current_renderer()->device_addr + offset; + { + if (offset < 0x100000 /*&& (offset % 0x10) == 0*/) + { + return render->device_addr + offset; + } + + // TODO: What happens here? It could wrap around or access other segments of rsx internal memory etc + // Or can simply throw access violation error + fmt::throw_exception("GetAddress(offset=0x%x, location=0x%x): DMA DEVICE offset out of range" HERE, offset, location); + } default: { diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 72960c60ca..f935f0af80 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -656,6 +656,7 @@ namespace rsx u32 label_addr; u32 main_mem_size{0}; + u32 local_mem_size{0}; bool m_rtts_dirty; bool m_textures_dirty[16];