rsx/gcm: Implement rsx dma. Refactor gcm/rsx to not be as codependent

This commit is contained in:
Jake 2017-07-25 21:33:32 -05:00 committed by Ivan
parent 607d2486ea
commit d9a693019b
14 changed files with 315 additions and 181 deletions

View file

@ -26,16 +26,19 @@ const u32 tiled_pitches[] = {
0x00010000 0x00010000
}; };
struct CellGcmSysConfig {
u32 zculls_addr;
vm::ptr<CellGcmDisplayInfo> gcm_buffers{ vm::null };
u32 tiles_addr;
u32 ctxt_addr;
CellGcmConfig current_config;
CellGcmContextData current_context;
gcmInfo gcm_info;
};
u64 system_mode = 0;
u32 local_size = 0; u32 local_size = 0;
u32 local_addr = 0; u32 local_addr = 0;
u64 system_mode = 0;
CellGcmConfig current_config;
CellGcmContextData current_context;
gcmInfo gcm_info;
u32 map_offset_addr = 0;
u32 map_offset_pos = 0;
// Auxiliary functions // Auxiliary functions
@ -82,7 +85,12 @@ void InitOffsetTable()
u32 cellGcmGetLabelAddress(u8 index) u32 cellGcmGetLabelAddress(u8 index)
{ {
cellGcmSys.trace("cellGcmGetLabelAddress(index=%d)", index); cellGcmSys.trace("cellGcmGetLabelAddress(index=%d)", index);
return gcm_info.label_addr + 0x10 * index; const auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return 0;
return m_config->gcm_info.label_addr + 0x10 * index;
} }
vm::ptr<CellGcmReportData> cellGcmGetReportDataAddressLocation(u32 index, u32 location) vm::ptr<CellGcmReportData> cellGcmGetReportDataAddressLocation(u32 index, u32 location)
@ -94,7 +102,7 @@ vm::ptr<CellGcmReportData> cellGcmGetReportDataAddressLocation(u32 index, u32 lo
cellGcmSys.error("cellGcmGetReportDataAddressLocation: Wrong local index (%d)", index); cellGcmSys.error("cellGcmGetReportDataAddressLocation: Wrong local index (%d)", index);
return vm::null; return vm::null;
} }
return vm::ptr<CellGcmReportData>::make(0xC0000000 + index * 0x10); return vm::ptr<CellGcmReportData>::make(0x40301400 + index * 0x10);
} }
if (location == CELL_GCM_LOCATION_MAIN) { if (location == CELL_GCM_LOCATION_MAIN) {
@ -117,7 +125,7 @@ u64 cellGcmGetTimeStamp(u32 index)
cellGcmSys.error("cellGcmGetTimeStamp: Wrong local index (%d)", index); cellGcmSys.error("cellGcmGetTimeStamp: Wrong local index (%d)", index);
return 0; return 0;
} }
return vm::read64(0xC0000000 + index * 0x10); return vm::read64(0x40301400 + index * 0x10);
} }
u32 cellGcmGetCurrentField() u32 cellGcmGetCurrentField()
@ -144,7 +152,7 @@ u32 cellGcmGetNotifyDataAddress(u32 index)
*/ */
vm::ptr<CellGcmReportData> _cellGcmFunc12() vm::ptr<CellGcmReportData> _cellGcmFunc12()
{ {
return vm::ptr<CellGcmReportData>::make(0xC0000000); // TODO return vm::ptr<CellGcmReportData>::make(0x40301400); // TODO
} }
u32 cellGcmGetReport(u32 type, u32 index) u32 cellGcmGetReport(u32 type, u32 index)
@ -172,7 +180,7 @@ u32 cellGcmGetReportDataAddress(u32 index)
cellGcmSys.error("cellGcmGetReportDataAddress: Wrong local index (%d)", index); cellGcmSys.error("cellGcmGetReportDataAddress: Wrong local index (%d)", index);
return 0; return 0;
} }
return 0xC0000000 + index * 0x10; return 0x40301400 + index * 0x10;
} }
u32 cellGcmGetReportDataLocation(u32 index, u32 location) u32 cellGcmGetReportDataLocation(u32 index, u32 location)
@ -192,7 +200,7 @@ u64 cellGcmGetTimeStampLocation(u32 index, u32 location)
cellGcmSys.error("cellGcmGetTimeStampLocation: Wrong local index (%d)", index); cellGcmSys.error("cellGcmGetTimeStampLocation: Wrong local index (%d)", index);
return 0; return 0;
} }
return vm::read64(0xC0000000 + index * 0x10); return vm::read64(0x40301400 + index * 0x10);
} }
if (location == CELL_GCM_LOCATION_MAIN) { if (location == CELL_GCM_LOCATION_MAIN) {
@ -214,20 +222,31 @@ u64 cellGcmGetTimeStampLocation(u32 index, u32 location)
u32 cellGcmGetControlRegister() u32 cellGcmGetControlRegister()
{ {
cellGcmSys.trace("cellGcmGetControlRegister()"); cellGcmSys.trace("cellGcmGetControlRegister()");
const auto m_config = fxm::get<CellGcmSysConfig>();
return gcm_info.control_addr; if (!m_config)
return 0;
return m_config->gcm_info.control_addr;
} }
u32 cellGcmGetDefaultCommandWordSize() u32 cellGcmGetDefaultCommandWordSize()
{ {
cellGcmSys.trace("cellGcmGetDefaultCommandWordSize()"); cellGcmSys.trace("cellGcmGetDefaultCommandWordSize()");
return gcm_info.command_size; const auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return 0;
return m_config->gcm_info.command_size;
} }
u32 cellGcmGetDefaultSegmentWordSize() u32 cellGcmGetDefaultSegmentWordSize()
{ {
cellGcmSys.trace("cellGcmGetDefaultSegmentWordSize()"); cellGcmSys.trace("cellGcmGetDefaultSegmentWordSize()");
return gcm_info.segment_size; const auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return 0;
return m_config->gcm_info.segment_size;
} }
s32 cellGcmInitDefaultFifoMode(s32 mode) s32 cellGcmInitDefaultFifoMode(s32 mode)
@ -280,8 +299,10 @@ s32 cellGcmBindZcull(u8 index, u32 offset, u32 width, u32 height, u32 cullStart,
void cellGcmGetConfiguration(vm::ptr<CellGcmConfig> config) void cellGcmGetConfiguration(vm::ptr<CellGcmConfig> config)
{ {
cellGcmSys.trace("cellGcmGetConfiguration(config=*0x%x)", config); cellGcmSys.trace("cellGcmGetConfiguration(config=*0x%x)", config);
const auto m_config = fxm::get<CellGcmSysConfig>();
*config = current_config; if (m_config)
*config = m_config->current_config;
} }
u32 cellGcmGetFlipStatus() u32 cellGcmGetFlipStatus()
@ -297,9 +318,9 @@ u32 cellGcmGetTiledPitchSize(u32 size)
{ {
cellGcmSys.trace("cellGcmGetTiledPitchSize(size=%d)", size); cellGcmSys.trace("cellGcmGetTiledPitchSize(size=%d)", size);
for (size_t i=0; i < sizeof(tiled_pitches) / sizeof(tiled_pitches[0]) - 1; i++) { for (size_t i = 0; i < sizeof(tiled_pitches) / sizeof(tiled_pitches[0]) - 1; i++) {
if (tiled_pitches[i] < size && size <= tiled_pitches[i+1]) { if (tiled_pitches[i] < size && size <= tiled_pitches[i + 1]) {
return tiled_pitches[i+1]; return tiled_pitches[i + 1];
} }
} }
return 0; return 0;
@ -324,8 +345,12 @@ s32 _cellGcmInitBody(vm::pptr<CellGcmContextData> context, u32 cmdSize, u32 ioSi
{ {
cellGcmSys.warning("_cellGcmInitBody(context=**0x%x, cmdSize=0x%x, ioSize=0x%x, ioAddress=0x%x)", context, cmdSize, ioSize, ioAddress); cellGcmSys.warning("_cellGcmInitBody(context=**0x%x, cmdSize=0x%x, ioSize=0x%x, ioAddress=0x%x)", context, cmdSize, ioSize, ioAddress);
current_config.ioAddress = 0; auto m_config = fxm::make<CellGcmSysConfig>();
current_config.localAddress = 0; if (!m_config)
return CELL_GCM_ERROR_FAILURE;
m_config->current_config.ioAddress = 0;
m_config->current_config.localAddress = 0;
local_size = 0; local_size = 0;
local_addr = 0; local_addr = 0;
@ -356,33 +381,42 @@ s32 _cellGcmInitBody(vm::pptr<CellGcmContextData> context, u32 cmdSize, u32 ioSi
return CELL_GCM_ERROR_FAILURE; return CELL_GCM_ERROR_FAILURE;
} }
map_offset_addr = 0; m_config->current_config.ioSize = ioSize;
map_offset_pos = 0; m_config->current_config.ioAddress = ioAddress;
current_config.ioSize = ioSize; m_config->current_config.localSize = local_size;
current_config.ioAddress = ioAddress; m_config->current_config.localAddress = local_addr;
current_config.localSize = local_size; m_config->current_config.memoryFrequency = 650000000;
current_config.localAddress = local_addr; m_config->current_config.coreFrequency = 500000000;
current_config.memoryFrequency = 650000000;
current_config.coreFrequency = 500000000;
// Create contexts // Create contexts
u32 addr = vm::falloc(0x40000000, 0x400000);
if (addr == 0 || addr != 0x40000000)
fmt::throw_exception("Failed to alloc 0x40000000.");
g_defaultCommandBufferBegin = ioAddress; g_defaultCommandBufferBegin = ioAddress;
g_defaultCommandBufferFragmentCount = cmdSize / (32 * 1024); g_defaultCommandBufferFragmentCount = cmdSize / (32 * 1024);
gcm_info.context_addr = vm::alloc(0x1000, vm::main); m_config->gcm_info.context_addr = 0x40000000;
gcm_info.control_addr = vm::alloc(0x1000, vm::main); m_config->gcm_info.control_addr = 0x40100000;
gcm_info.label_addr = vm::alloc(0x1000, vm::main); // ??? m_config->gcm_info.label_addr = 0x40300000;
current_context.begin.set(g_defaultCommandBufferBegin + 4096); // 4 kb reserved at the beginning m_config->current_context.begin.set(g_defaultCommandBufferBegin + 4096); // 4 kb reserved at the beginning
current_context.end.set(g_defaultCommandBufferBegin + 32 * 1024 - 4); // 4b at the end for jump m_config->current_context.end.set(g_defaultCommandBufferBegin + 32 * 1024 - 4); // 4b at the end for jump
current_context.current = current_context.begin; m_config->current_context.current = m_config->current_context.begin;
current_context.callback.set(ppu_function_manager::addr + 8 * FIND_FUNC(cellGcmCallback)); m_config->current_context.callback.set(ppu_function_manager::addr + 8 * FIND_FUNC(cellGcmCallback));
vm::_ref<CellGcmContextData>(gcm_info.context_addr) = current_context; m_config->ctxt_addr = context.addr();
context->set(gcm_info.context_addr); m_config->gcm_buffers.set(vm::alloc(sizeof(CellGcmDisplayInfo) * 8, vm::main));
m_config->zculls_addr = vm::alloc(sizeof(CellGcmZcullInfo) * 8, vm::main);
m_config->tiles_addr = vm::alloc(sizeof(CellGcmTileInfo) * 15, vm::main);
auto& ctrl = vm::_ref<CellGcmControl>(gcm_info.control_addr); vm::_ref<CellGcmContextData>(m_config->gcm_info.context_addr) = m_config->current_context;
context->set(m_config->gcm_info.context_addr);
// 0x40 is to offset CellGcmControl from RsxDmaControl
m_config->gcm_info.control_addr += 0x40;
auto& ctrl = vm::_ref<CellGcmControl>(m_config->gcm_info.control_addr);
ctrl.put = 0; ctrl.put = 0;
ctrl.get = 0; ctrl.get = 0;
ctrl.ref = -1; ctrl.ref = -1;
@ -390,15 +424,9 @@ s32 _cellGcmInitBody(vm::pptr<CellGcmContextData> context, u32 cmdSize, u32 ioSi
const auto render = fxm::get<GSRender>(); const auto render = fxm::get<GSRender>();
render->intr_thread = idm::make_ptr<ppu_thread>("_gcm_intr_thread", 1, 0x4000); render->intr_thread = idm::make_ptr<ppu_thread>("_gcm_intr_thread", 1, 0x4000);
render->intr_thread->run(); render->intr_thread->run();
render->ctxt_addr = context.addr();
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 = 0;
render->gcm_current_buffer = 0;
render->main_mem_addr = 0; render->main_mem_addr = 0;
render->label_addr = gcm_info.label_addr; render->label_addr = m_config->gcm_info.label_addr;
render->init(g_defaultCommandBufferBegin, cmdSize, gcm_info.control_addr, local_addr); render->init(ioAddress, ioSize, m_config->gcm_info.control_addr - 0x40, local_addr);
return CELL_OK; return CELL_OK;
} }
@ -431,6 +459,10 @@ s32 cellGcmSetDisplayBuffer(u8 id, u32 offset, u32 pitch, u32 width, u32 height)
{ {
cellGcmSys.trace("cellGcmSetDisplayBuffer(id=0x%x, offset=0x%x, pitch=%d, width=%d, height=%d)", id, offset, width ? pitch / width : pitch, width, height); cellGcmSys.trace("cellGcmSetDisplayBuffer(id=0x%x, offset=0x%x, pitch=%d, width=%d, height=%d)", id, offset, width ? pitch / width : pitch, width, height);
auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return CELL_GCM_ERROR_FAILURE;
if (id > 7) if (id > 7)
{ {
cellGcmSys.error("cellGcmSetDisplayBuffer: CELL_GCM_ERROR_FAILURE"); cellGcmSys.error("cellGcmSetDisplayBuffer: CELL_GCM_ERROR_FAILURE");
@ -439,16 +471,21 @@ s32 cellGcmSetDisplayBuffer(u8 id, u32 offset, u32 pitch, u32 width, u32 height)
const auto render = fxm::get<GSRender>(); const auto render = fxm::get<GSRender>();
auto buffers = render->gcm_buffers; auto buffers = render->display_buffers;
buffers[id].offset = offset; buffers[id].offset = offset;
buffers[id].pitch = pitch; buffers[id].pitch = pitch;
buffers[id].width = width; buffers[id].width = width;
buffers[id].height = height; buffers[id].height = height;
if (id + 1 > render->gcm_buffers_count) m_config->gcm_buffers[id].offset = offset;
m_config->gcm_buffers[id].pitch = pitch;
m_config->gcm_buffers[id].width = width;
m_config->gcm_buffers[id].height = height;
if (id + 1 > render->display_buffers_count)
{ {
render->gcm_buffers_count = id + 1; render->display_buffers_count = id + 1;
} }
return CELL_OK; return CELL_OK;
@ -465,17 +502,7 @@ void cellGcmSetFlipMode(u32 mode)
{ {
cellGcmSys.warning("cellGcmSetFlipMode(mode=%d)", mode); cellGcmSys.warning("cellGcmSetFlipMode(mode=%d)", mode);
switch (mode) fxm::get<GSRender>()->requested_vsync.store(mode == CELL_GCM_DISPLAY_VSYNC);
{
case CELL_GCM_DISPLAY_HSYNC:
case CELL_GCM_DISPLAY_VSYNC:
case CELL_GCM_DISPLAY_HSYNC_WITH_NOISE:
fxm::get<GSRender>()->flip_mode = mode;
break;
default:
break;
}
} }
void cellGcmSetFlipStatus() void cellGcmSetFlipStatus()
@ -488,6 +515,9 @@ void cellGcmSetFlipStatus()
s32 cellGcmSetPrepareFlip(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctxt, u32 id) s32 cellGcmSetPrepareFlip(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctxt, u32 id)
{ {
cellGcmSys.trace("cellGcmSetPrepareFlip(ctxt=*0x%x, id=0x%x)", ctxt, id); cellGcmSys.trace("cellGcmSetPrepareFlip(ctxt=*0x%x, id=0x%x)", ctxt, id);
auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return CELL_GCM_ERROR_FAILURE;
if (id > 7) if (id > 7)
{ {
@ -506,9 +536,9 @@ s32 cellGcmSetPrepareFlip(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctxt, u32
const u32 cmd_size = rsx::make_command(ctxt->current, GCM_FLIP_COMMAND, { id }); const u32 cmd_size = rsx::make_command(ctxt->current, GCM_FLIP_COMMAND, { id });
if (ctxt.addr() == gcm_info.context_addr) if (ctxt.addr() == m_config->gcm_info.context_addr)
{ {
vm::_ref<CellGcmControl>(gcm_info.control_addr).put += cmd_size; vm::_ref<CellGcmControl>(m_config->gcm_info.control_addr).put += cmd_size;
} }
return id; return id;
@ -535,15 +565,12 @@ void cellGcmSetSecondVFrequency(u32 freq)
switch (freq) switch (freq)
{ {
case CELL_GCM_DISPLAY_FREQUENCY_59_94HZ: case CELL_GCM_DISPLAY_FREQUENCY_59_94HZ:
render->frequency_mode = freq;
render->fps_limit = 59.94; render->fps_limit = 59.94;
break; break;
case CELL_GCM_DISPLAY_FREQUENCY_SCANOUT: case CELL_GCM_DISPLAY_FREQUENCY_SCANOUT:
render->frequency_mode = freq;
cellGcmSys.todo("Unimplemented display frequency: Scanout"); cellGcmSys.todo("Unimplemented display frequency: Scanout");
break; break;
case CELL_GCM_DISPLAY_FREQUENCY_DISABLE: case CELL_GCM_DISPLAY_FREQUENCY_DISABLE:
render->frequency_mode = freq;
cellGcmSys.todo("Unimplemented display frequency: Disabled"); cellGcmSys.todo("Unimplemented display frequency: Disabled");
break; break;
default: default:
@ -557,6 +584,10 @@ s32 cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u
cellGcmSys.warning("cellGcmSetTileInfo(index=%d, location=%d, offset=%d, size=%d, pitch=%d, comp=%d, base=%d, bank=%d)", cellGcmSys.warning("cellGcmSetTileInfo(index=%d, location=%d, offset=%d, size=%d, pitch=%d, comp=%d, base=%d, bank=%d)",
index, location, offset, size, pitch, comp, base, bank); index, location, offset, size, pitch, comp, base, bank);
auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return CELL_GCM_ERROR_FAILURE;
if (index >= rsx::limits::tiles_count || base >= 2048 || bank >= 4) if (index >= rsx::limits::tiles_count || base >= 2048 || bank >= 4)
{ {
cellGcmSys.error("cellGcmSetTileInfo: CELL_GCM_ERROR_INVALID_VALUE"); cellGcmSys.error("cellGcmSetTileInfo: CELL_GCM_ERROR_INVALID_VALUE");
@ -591,7 +622,7 @@ s32 cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u
tile.base = base; tile.base = base;
tile.bank = bank; tile.bank = bank;
vm::_ptr<CellGcmTileInfo>(render->tiles_addr)[index] = tile.pack(); vm::_ptr<CellGcmTileInfo>(m_config->tiles_addr)[index] = tile.pack();
return CELL_OK; return CELL_OK;
} }
@ -633,6 +664,10 @@ void cellGcmSetZcull(u8 index, u32 offset, u32 width, u32 height, u32 cullStart,
cellGcmSys.todo("cellGcmSetZcull(index=%d, offset=0x%x, width=%d, height=%d, cullStart=0x%x, zFormat=0x%x, aaFormat=0x%x, zCullDir=0x%x, zCullFormat=0x%x, sFunc=0x%x, sRef=0x%x, sMask=0x%x)", cellGcmSys.todo("cellGcmSetZcull(index=%d, offset=0x%x, width=%d, height=%d, cullStart=0x%x, zFormat=0x%x, aaFormat=0x%x, zCullDir=0x%x, zCullFormat=0x%x, sFunc=0x%x, sRef=0x%x, sMask=0x%x)",
index, offset, width, height, cullStart, zFormat, aaFormat, zCullDir, zCullFormat, sFunc, sRef, sMask); index, offset, width, height, cullStart, zFormat, aaFormat, zCullDir, zCullFormat, sFunc, sRef, sMask);
auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return;
if (index >= rsx::limits::zculls_count) if (index >= rsx::limits::zculls_count)
{ {
cellGcmSys.error("cellGcmSetZcull: CELL_GCM_ERROR_INVALID_VALUE"); cellGcmSys.error("cellGcmSetZcull: CELL_GCM_ERROR_INVALID_VALUE");
@ -654,7 +689,7 @@ void cellGcmSetZcull(u8 index, u32 offset, u32 width, u32 height, u32 cullStart,
zcull.sRef = sRef; zcull.sRef = sRef;
zcull.sMask = sMask; zcull.sMask = sMask;
vm::_ptr<CellGcmZcullInfo>(render->zculls_addr)[index] = zcull.pack(); vm::_ptr<CellGcmZcullInfo>(m_config->zculls_addr)[index] = zcull.pack();
} }
s32 cellGcmUnbindTile(u8 index) s32 cellGcmUnbindTile(u8 index)
@ -690,26 +725,35 @@ s32 cellGcmUnbindZcull(u8 index)
u32 cellGcmGetTileInfo() u32 cellGcmGetTileInfo()
{ {
cellGcmSys.warning("cellGcmGetTileInfo()"); cellGcmSys.warning("cellGcmGetTileInfo()");
return fxm::get<GSRender>()->tiles_addr; auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return 0;
return m_config->tiles_addr;
} }
u32 cellGcmGetZcullInfo() u32 cellGcmGetZcullInfo()
{ {
cellGcmSys.warning("cellGcmGetZcullInfo()"); cellGcmSys.warning("cellGcmGetZcullInfo()");
return fxm::get<GSRender>()->zculls_addr; auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return 0;
return m_config->zculls_addr;
} }
u32 cellGcmGetDisplayInfo() u32 cellGcmGetDisplayInfo()
{ {
cellGcmSys.warning("cellGcmGetDisplayInfo()"); cellGcmSys.warning("cellGcmGetDisplayInfo()");
return fxm::get<GSRender>()->gcm_buffers.addr(); auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return 0;
return m_config->gcm_buffers.addr();
} }
s32 cellGcmGetCurrentDisplayBufferId(vm::ptr<u8> id) s32 cellGcmGetCurrentDisplayBufferId(vm::ptr<u8> id)
{ {
cellGcmSys.warning("cellGcmGetCurrentDisplayBufferId(id=*0x%x)", id); cellGcmSys.warning("cellGcmGetCurrentDisplayBufferId(id=*0x%x)", id);
if ((*id = fxm::get<GSRender>()->gcm_current_buffer) > UINT8_MAX) if ((*id = fxm::get<GSRender>()->current_display_buffer) > UINT8_MAX)
{ {
fmt::throw_exception("Unexpected" HERE); fmt::throw_exception("Unexpected" HERE);
} }
@ -898,7 +942,6 @@ s32 gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict)
{ {
offsetTable.ioAddress[(ea >> 20) + i] = (io >> 20) + i; offsetTable.ioAddress[(ea >> 20) + i] = (io >> 20) + i;
offsetTable.eaAddress[(io >> 20) + i] = (ea >> 20) + i; offsetTable.eaAddress[(io >> 20) + i] = (ea >> 20) + i;
render->strict_ordering[(io >> 20) + i] = is_strict;
} }
} }
else else
@ -948,6 +991,7 @@ s32 cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr<u32> offset)
{ {
cellGcmSys.warning("cellGcmMapMainMemory(ea=0x%x, size=0x%x, offset=*0x%x)", ea, size, offset); cellGcmSys.warning("cellGcmMapMainMemory(ea=0x%x, size=0x%x, offset=*0x%x)", ea, size, offset);
if (size == 0) return CELL_OK;
if ((ea & 0xFFFFF) || (size & 0xFFFFF)) return CELL_GCM_ERROR_FAILURE; if ((ea & 0xFFFFF) || (size & 0xFFFFF)) return CELL_GCM_ERROR_FAILURE;
u32 io = RSXIOMem.Map(ea, size); u32 io = RSXIOMem.Map(ea, size);
@ -962,7 +1006,6 @@ s32 cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr<u32> offset)
{ {
offsetTable.ioAddress[(ea >> 20) + i] = (u16)((io >> 20) + i); offsetTable.ioAddress[(ea >> 20) + i] = (u16)((io >> 20) + i);
offsetTable.eaAddress[(io >> 20) + i] = (u16)((ea >> 20) + i); offsetTable.eaAddress[(io >> 20) + i] = (u16)((ea >> 20) + i);
render->strict_ordering[(io >> 20) + i] = false;
} }
*offset = io; *offset = io;
@ -1113,23 +1156,27 @@ s32 cellGcmSetCursorImageOffset(u32 offset)
void cellGcmSetDefaultCommandBuffer() void cellGcmSetDefaultCommandBuffer()
{ {
cellGcmSys.warning("cellGcmSetDefaultCommandBuffer()"); cellGcmSys.warning("cellGcmSetDefaultCommandBuffer()");
vm::write32(fxm::get<GSRender>()->ctxt_addr, gcm_info.context_addr); auto m_config = fxm::get<CellGcmSysConfig>();
if (m_config)
vm::write32(m_config->ctxt_addr, m_config->gcm_info.context_addr);
} }
s32 cellGcmSetDefaultCommandBufferAndSegmentWordSize(u32 bufferSize, u32 segmentSize) s32 cellGcmSetDefaultCommandBufferAndSegmentWordSize(u32 bufferSize, u32 segmentSize)
{ {
cellGcmSys.warning("cellGcmSetDefaultCommandBufferAndSegmentWordSize(bufferSize=0x%x, segmentSize=0x%x)", bufferSize, segmentSize); cellGcmSys.warning("cellGcmSetDefaultCommandBufferAndSegmentWordSize(bufferSize=0x%x, segmentSize=0x%x)", bufferSize, segmentSize);
auto m_config = fxm::get<CellGcmSysConfig>();
const auto& put = vm::_ref<CellGcmControl>(gcm_info.control_addr).put; if (!m_config)
const auto& get = vm::_ref<CellGcmControl>(gcm_info.control_addr).get; return CELL_GCM_ERROR_FAILURE;
const auto& put = vm::_ref<CellGcmControl>(m_config->gcm_info.control_addr).put;
const auto& get = vm::_ref<CellGcmControl>(m_config->gcm_info.control_addr).get;
if (put != 0x1000 || get != 0x1000 || bufferSize < segmentSize * 2) if (put != 0x1000 || get != 0x1000 || bufferSize < segmentSize * 2)
{ {
return CELL_GCM_ERROR_FAILURE; return CELL_GCM_ERROR_FAILURE;
} }
gcm_info.command_size = bufferSize; m_config->gcm_info.command_size = bufferSize;
gcm_info.segment_size = segmentSize; m_config->gcm_info.segment_size = segmentSize;
return CELL_OK; return CELL_OK;
} }
@ -1148,9 +1195,11 @@ s32 _cellGcmSetFlipCommand(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctx, u32
s32 _cellGcmSetFlipCommandWithWaitLabel(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctx, u32 id, u32 label_index, u32 label_value) s32 _cellGcmSetFlipCommandWithWaitLabel(ppu_thread& ppu, vm::ptr<CellGcmContextData> ctx, u32 id, u32 label_index, u32 label_value)
{ {
cellGcmSys.trace("cellGcmSetFlipCommandWithWaitLabel(ctx=*0x%x, id=0x%x, label_index=0x%x, label_value=0x%x)", ctx, id, label_index, label_value); cellGcmSys.trace("cellGcmSetFlipCommandWithWaitLabel(ctx=*0x%x, id=0x%x, label_index=0x%x, label_value=0x%x)", ctx, id, label_index, label_value);
auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return CELL_GCM_ERROR_FAILURE;
s32 res = cellGcmSetPrepareFlip(ppu, ctx, id); s32 res = cellGcmSetPrepareFlip(ppu, ctx, id);
vm::write32(gcm_info.label_addr + 0x10 * label_index, label_value); vm::write32(m_config->gcm_info.label_addr + 0x10 * label_index, label_value);
return res < 0 ? CELL_GCM_ERROR_FAILURE : CELL_OK; return res < 0 ? CELL_GCM_ERROR_FAILURE : CELL_OK;
} }
@ -1159,6 +1208,10 @@ s32 cellGcmSetTile(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 co
cellGcmSys.warning("cellGcmSetTile(index=%d, location=%d, offset=%d, size=%d, pitch=%d, comp=%d, base=%d, bank=%d)", cellGcmSys.warning("cellGcmSetTile(index=%d, location=%d, offset=%d, size=%d, pitch=%d, comp=%d, base=%d, bank=%d)",
index, location, offset, size, pitch, comp, base, bank); index, location, offset, size, pitch, comp, base, bank);
auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return CELL_GCM_ERROR_FAILURE;
// Copied form cellGcmSetTileInfo // Copied form cellGcmSetTileInfo
if (index >= rsx::limits::tiles_count || base >= 2048 || bank >= 4) if (index >= rsx::limits::tiles_count || base >= 2048 || bank >= 4)
{ {
@ -1194,7 +1247,7 @@ s32 cellGcmSetTile(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 co
tile.base = base; tile.base = base;
tile.bank = bank; tile.bank = bank;
vm::_ptr<CellGcmTileInfo>(render->tiles_addr)[index] = tile.pack(); vm::_ptr<CellGcmTileInfo>(m_config->tiles_addr)[index] = tile.pack();
return CELL_OK; return CELL_OK;
} }
@ -1286,8 +1339,11 @@ static bool isInCommandBufferExcept(u32 getPos, u32 bufferBegin, u32 bufferEnd)
s32 cellGcmCallback(ppu_thread& ppu, vm::ptr<CellGcmContextData> context, u32 count) s32 cellGcmCallback(ppu_thread& ppu, vm::ptr<CellGcmContextData> context, u32 count)
{ {
cellGcmSys.trace("cellGcmCallback(context=*0x%x, count=0x%x)", context, count); cellGcmSys.trace("cellGcmCallback(context=*0x%x, count=0x%x)", context, count);
auto m_config = fxm::get<CellGcmSysConfig>();
if (!m_config)
return CELL_GCM_ERROR_FAILURE;
auto& ctrl = vm::_ref<CellGcmControl>(gcm_info.control_addr); auto& ctrl = vm::_ref<CellGcmControl>(m_config->gcm_info.control_addr);
// Flush command buffer (ie allow RSX to read up to context->current) // Flush command buffer (ie allow RSX to read up to context->current)
ctrl.put.exchange(getOffsetFromAddress(context->current.addr())); ctrl.put.exchange(getOffsetFromAddress(context->current.addr()));

View file

@ -1,5 +1,44 @@
#pragma once #pragma once
struct RsxDmaControl {
u8 resv[0x40];
atomic_be_t<u32> put;
atomic_be_t<u32> get;
atomic_be_t<u32> ref;
be_t<u32> unk[2];
be_t<u32> unk1;
};
struct RsxSemaphore {
be_t<u32> val;
be_t<u32> pad;
be_t<u64> timestamp;
};
struct RsxNotify {
be_t<u64> timestamp;
be_t<u64> zero;
};
struct RsxReport {
be_t<u64> timestamp;
be_t<u32> val;
be_t<u32> pad;
};
struct RsxReports {
RsxSemaphore semaphore[0x100];
RsxNotify notify[64];
RsxReport report[2048];
};
struct RsxDisplayInfo {
be_t<u32> offset;
be_t<u32> pitch;
be_t<u32> width;
be_t<u32> height;
};
// SysCalls // SysCalls
s32 sys_rsx_device_open(); s32 sys_rsx_device_open();
s32 sys_rsx_device_close(); s32 sys_rsx_device_close();

View file

@ -786,6 +786,7 @@ namespace vm
std::make_shared<block_t>(0xC0000000, 0x10000000), // video std::make_shared<block_t>(0xC0000000, 0x10000000), // video
std::make_shared<block_t>(0xD0000000, 0x10000000), // stack std::make_shared<block_t>(0xD0000000, 0x10000000), // stack
std::make_shared<block_t>(0xE0000000, 0x20000000), // SPU reserved std::make_shared<block_t>(0xE0000000, 0x20000000), // SPU reserved
std::make_shared<block_t>(0x40000000, 0x10000000), // rsx contexts
}; };
} }
} }

View file

@ -523,10 +523,9 @@ void D3D12GSRender::flip(int buffer)
size_t offset = 0; size_t offset = 0;
if (false) if (false)
{ {
CellGcmDisplayInfo* buffers = nullptr;// = vm::ps3::_ptr<CellGcmDisplayInfo>(m_gcm_buffers_addr); u32 addr = rsx::get_address(display_buffers[current_display_buffer].offset, CELL_GCM_LOCATION_LOCAL);
u32 addr = rsx::get_address(gcm_buffers[gcm_current_buffer].offset, CELL_GCM_LOCATION_LOCAL); w = display_buffers[current_display_buffer].width;
w = gcm_buffers[gcm_current_buffer].width; h = display_buffers[current_display_buffer].height;
h = gcm_buffers[gcm_current_buffer].height;
u8 *src_buffer = vm::ps3::_ptr<u8>(addr); u8 *src_buffer = vm::ps3::_ptr<u8>(addr);
row_pitch = align(w * 4, 256); row_pitch = align(w * 4, 256);

View file

@ -985,9 +985,9 @@ void GLGSRender::flip(int buffer)
return; return;
} }
u32 buffer_width = gcm_buffers[buffer].width; u32 buffer_width = display_buffers[buffer].width;
u32 buffer_height = gcm_buffers[buffer].height; u32 buffer_height = display_buffers[buffer].height;
u32 buffer_pitch = gcm_buffers[buffer].pitch; u32 buffer_pitch = display_buffers[buffer].pitch;
// Calculate blit coordinates // Calculate blit coordinates
coordi aspect_ratio; coordi aspect_ratio;
@ -1016,7 +1016,7 @@ void GLGSRender::flip(int buffer)
aspect_ratio.size = new_size; aspect_ratio.size = new_size;
// Find the source image // Find the source image
rsx::tiled_region buffer_region = get_tiled_address(gcm_buffers[buffer].offset, CELL_GCM_LOCATION_LOCAL); rsx::tiled_region buffer_region = get_tiled_address(display_buffers[buffer].offset, CELL_GCM_LOCATION_LOCAL);
u32 absolute_address = buffer_region.address + buffer_region.base; u32 absolute_address = buffer_region.address + buffer_region.base;
gl::texture *render_target_texture = m_rtts.get_texture_from_render_target_if_applicable(absolute_address); gl::texture *render_target_texture = m_rtts.get_texture_from_render_target_if_applicable(absolute_address);

View file

@ -50,34 +50,36 @@ namespace rsx
} }
fmt::throw_exception("GetAddress(offset=0x%x, location=0x%x): RSXIO memory not mapped" HERE, offset, location); fmt::throw_exception("GetAddress(offset=0x%x, location=0x%x): RSXIO memory not mapped" HERE, offset, location);
//if (fxm::get<GSRender>()->strict_ordering[offset >> 20])
//{
// _mm_mfence(); // probably doesn't have any effect on current implementation
//}
} }
case CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_REPORT: case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_LOCAL:
return 0x100000 + offset; // TODO: Properly implement return 0x40301400 + offset;
case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_MAIN: case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_MAIN:
return 0x800 + offset; // TODO: Properly implement {
if (u32 result = RSXIOMem.RealAddr(0x0e000000 + offset))
{
return result;
}
fmt::throw_exception("GetAddress(offset=0x%x, location=0x%x): RSXIO memory not mapped" HERE, offset, location);
}
case CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY0: case CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY0:
return 0x40 + offset; // TODO: Properly implement fmt::throw_exception("Unimplemented 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: 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("Unimplemented 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_RW:
case CELL_GCM_CONTEXT_DMA_SEMAPHORE_R: case CELL_GCM_CONTEXT_DMA_SEMAPHORE_R:
return 0x100 + offset; // TODO: Properly implement return 0x40300000 + offset;
case CELL_GCM_CONTEXT_DMA_DEVICE_RW: 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;
case CELL_GCM_CONTEXT_DMA_DEVICE_R: 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;
default: default:
fmt::throw_exception("Invalid location (offset=0x%x, location=0x%x)" HERE, offset, location); fmt::throw_exception("Invalid location (offset=0x%x, location=0x%x)" HERE, offset, location);
@ -1069,9 +1071,9 @@ namespace rsx
rsx::method_registers.reset(); rsx::method_registers.reset();
} }
void thread::init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress) void thread::init(u32 ioAddress, u32 ioSize, u32 ctrlAddress, u32 localAddress)
{ {
ctrl = vm::_ptr<CellGcmControl>(ctrlAddress); ctrl = vm::_ptr<RsxDmaControl>(ctrlAddress);
this->ioAddress = ioAddress; this->ioAddress = ioAddress;
this->ioSize = ioSize; this->ioSize = ioSize;
local_mem_addr = localAddress; local_mem_addr = localAddress;

View file

@ -22,6 +22,8 @@
#include "Utilities/variant.hpp" #include "Utilities/variant.hpp"
#include "define_new_memleakdetect.h" #include "define_new_memleakdetect.h"
#include "Emu/Cell/lv2/sys_rsx.h"
extern u64 get_system_time(); extern u64 get_system_time();
extern bool user_asked_for_frame_capture; extern bool user_asked_for_frame_capture;
@ -113,7 +115,7 @@ namespace rsx
std::vector<u32> element_push_buffer; std::vector<u32> element_push_buffer;
public: public:
CellGcmControl* ctrl = nullptr; RsxDmaControl* ctrl = nullptr;
Timer timer_sync; Timer timer_sync;
@ -131,20 +133,17 @@ namespace rsx
u32 ioAddress, ioSize; u32 ioAddress, ioSize;
u32 flip_status; u32 flip_status;
int flip_mode;
int debug_level; int debug_level;
int frequency_mode;
u32 tiles_addr; atomic_t<bool> requested_vsync{false};
u32 zculls_addr;
vm::ps3::ptr<CellGcmDisplayInfo> gcm_buffers = vm::null; RsxDisplayInfo display_buffers[8];
u32 gcm_buffers_count; u32 display_buffers_count{0};
u32 gcm_current_buffer; u32 current_display_buffer{0};
u32 ctxt_addr; u32 ctxt_addr;
u32 label_addr; u32 label_addr;
u32 local_mem_addr, main_mem_addr; u32 local_mem_addr, main_mem_addr;
bool strict_ordering[0x1000];
bool m_rtts_dirty; bool m_rtts_dirty;
bool m_transform_constants_dirty; bool m_transform_constants_dirty;
@ -345,7 +344,7 @@ namespace rsx
public: public:
void reset(); void reset();
void init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress); void init(u32 ioAddress, u32 ioSize, u32 ctrlAddress, u32 localAddress);
tiled_region get_tiled_address(u32 offset, u32 location); tiled_region get_tiled_address(u32 offset, u32 location);
GcmTileInfo *find_tile(u32 offset, u32 location); GcmTileInfo *find_tile(u32 offset, u32 location);

View file

@ -2143,9 +2143,9 @@ void VKGSRender::flip(int buffer)
if (!resize_screen) if (!resize_screen)
{ {
u32 buffer_width = gcm_buffers[buffer].width; u32 buffer_width = display_buffers[buffer].width;
u32 buffer_height = gcm_buffers[buffer].height; u32 buffer_height = display_buffers[buffer].height;
u32 buffer_pitch = gcm_buffers[buffer].pitch; u32 buffer_pitch = display_buffers[buffer].pitch;
areai screen_area = coordi({}, { (int)buffer_width, (int)buffer_height }); areai screen_area = coordi({}, { (int)buffer_width, (int)buffer_height });

View file

@ -968,7 +968,7 @@ rsx::blit_engine::context_dma rsx::blit_engine::to_context_dma(u32 in)
{ {
switch (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_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; case CELL_GCM_CONTEXT_DMA_MEMORY_HOST_BUFFER: return rsx::blit_engine::context_dma::memory_host_buffer;
} }

View file

@ -704,7 +704,7 @@ enum
{ {
CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER = 0xFEED0000, // Local memory CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER = 0xFEED0000, // Local memory
CELL_GCM_CONTEXT_DMA_MEMORY_HOST_BUFFER = 0xFEED0001, // Main 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_REPORT_LOCATION_MAIN = 0xBAD68000,
CELL_GCM_CONTEXT_DMA_NOTIFY_MAIN_0 = 0x6660420F, CELL_GCM_CONTEXT_DMA_NOTIFY_MAIN_0 = 0x6660420F,

View file

@ -1988,6 +1988,32 @@ struct registers_decoder<NV4097_SET_TRANSFORM_PROGRAM_START>
} }
}; };
template<>
struct registers_decoder<NV406E_SET_CONTEXT_DMA_SEMAPHORE>
{
struct decoded_type
{
private:
union
{
u32 raw_value;
} m_data;
public:
decoded_type(u32 raw_value) { m_data.raw_value = raw_value; }
u32 context_dma() const
{
return m_data.raw_value;
}
};
static std::string dump(decoded_type &&decoded_values)
{
return "NV406E semaphore: context = " + std::to_string(decoded_values.context_dma());
}
};
template<> template<>
struct registers_decoder<NV406E_SEMAPHORE_OFFSET> struct registers_decoder<NV406E_SEMAPHORE_OFFSET>
{ {
@ -4600,7 +4626,7 @@ constexpr std::integer_sequence<u32, NV4097_SET_VIEWPORT_HORIZONTAL, NV4097_SET_
NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK, NV4097_SET_SHADER_CONTROL, NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK, NV4097_SET_SHADER_CONTROL,
NV4097_SET_VERTEX_DATA_BASE_OFFSET, NV4097_SET_INDEX_ARRAY_ADDRESS, NV4097_SET_VERTEX_DATA_BASE_OFFSET, NV4097_SET_INDEX_ARRAY_ADDRESS,
NV4097_SET_VERTEX_DATA_BASE_INDEX, NV4097_SET_SHADER_PROGRAM, NV4097_SET_VERTEX_DATA_BASE_INDEX, NV4097_SET_SHADER_PROGRAM,
NV4097_SET_TRANSFORM_PROGRAM_START, NV406E_SEMAPHORE_OFFSET, NV4097_SET_SEMAPHORE_OFFSET, NV4097_SET_TRANSFORM_PROGRAM_START, NV406E_SET_CONTEXT_DMA_SEMAPHORE, NV406E_SEMAPHORE_OFFSET, NV4097_SET_SEMAPHORE_OFFSET,
NV3089_IMAGE_IN_OFFSET, NV3062_SET_OFFSET_DESTIN, NV309E_SET_OFFSET, NV3089_DS_DX, NV3089_DT_DY, NV3089_IMAGE_IN_OFFSET, NV3062_SET_OFFSET_DESTIN, NV309E_SET_OFFSET, NV3089_DS_DX, NV3089_DT_DY,
NV0039_PITCH_IN, NV0039_PITCH_OUT, NV0039_LINE_LENGTH_IN, NV0039_LINE_COUNT, NV0039_OFFSET_OUT, NV0039_PITCH_IN, NV0039_PITCH_OUT, NV0039_LINE_LENGTH_IN, NV0039_LINE_COUNT, NV0039_OFFSET_OUT,
NV0039_OFFSET_IN, NV4097_SET_VERTEX_ATTRIB_INPUT_MASK, NV4097_SET_FREQUENCY_DIVIDER_OPERATION, NV0039_OFFSET_IN, NV4097_SET_VERTEX_ATTRIB_INPUT_MASK, NV4097_SET_FREQUENCY_DIVIDER_OPERATION,

View file

@ -60,9 +60,13 @@ namespace rsx
void semaphore_acquire(thread* rsx, u32 _reg, u32 arg) void semaphore_acquire(thread* rsx, u32 _reg, u32 arg)
{ {
//TODO: dma const u32 addr = get_address(method_registers.semaphore_offset_406e(), method_registers.semaphore_context_dma_406e());
while (vm::ps3::read32(rsx->label_addr + method_registers.semaphore_offset_406e()) != arg) while (vm::ps3::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)
break;
if (Emu.IsStopped()) if (Emu.IsStopped())
break; break;
@ -72,8 +76,8 @@ namespace rsx
void semaphore_release(thread* rsx, u32 _reg, u32 arg) void semaphore_release(thread* rsx, u32 _reg, u32 arg)
{ {
//TODO: dma const u32 addr = get_address(method_registers.semaphore_offset_406e(), method_registers.semaphore_context_dma_406e());
vm::ps3::write32(rsx->label_addr + method_registers.semaphore_offset_406e(), arg); vm::ps3::write32(addr, arg);
} }
} }
@ -100,8 +104,12 @@ namespace rsx
// //
} }
//TODO: dma const u32 index = method_registers.semaphore_offset_4097() >> 4;
vm::ps3::write32(rsx->label_addr + method_registers.semaphore_offset_4097(), arg);
auto& sema = vm::ps3::_ref<RsxReports>(rsx->label_addr);
sema.semaphore[index].val = arg;
sema.semaphore[index].pad = 0;
sema.semaphore[index].timestamp = rsx->timestamp();
} }
void back_end_write_semaphore_release(thread* rsx, u32 _reg, u32 arg) void back_end_write_semaphore_release(thread* rsx, u32 _reg, u32 arg)
@ -111,9 +119,13 @@ namespace rsx
// //
} }
//TODO: dma const u32 index = method_registers.semaphore_offset_4097() >> 4;
vm::ps3::write32(rsx->label_addr + method_registers.semaphore_offset_4097(), u32 val = (arg & 0xff00ff00) | ((arg & 0xff) << 16) | ((arg >> 16) & 0xff);
(arg & 0xff00ff00) | ((arg & 0xff) << 16) | ((arg >> 16) & 0xff));
auto& sema = vm::ps3::_ref<RsxReports>(rsx->label_addr);
sema.semaphore[index].val = val;
sema.semaphore[index].pad = 0;
sema.semaphore[index].timestamp = rsx->timestamp();
} }
template<u32 id, u32 index, int count, typename type> template<u32 id, u32 index, int count, typename type>
@ -323,10 +335,9 @@ namespace rsx
switch (report_dma) switch (report_dma)
{ {
case blit_engine::context_dma::to_memory_get_report: location = CELL_GCM_LOCATION_LOCAL; break; case blit_engine::context_dma::to_memory_get_report: location = CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_LOCAL; break;
case blit_engine::context_dma::report_location_main: case blit_engine::context_dma::report_location_main: location = CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_MAIN; break;
case blit_engine::context_dma::memory_host_buffer: case blit_engine::context_dma::memory_host_buffer: location = CELL_GCM_CONTEXT_DMA_MEMORY_HOST_BUFFER; break;
location = CELL_GCM_LOCATION_MAIN; break;
default: default:
LOG_WARNING(RSX, "nv4097::get_report: bad report dma: 0x%x", (u8)report_dma); LOG_WARNING(RSX, "nv4097::get_report: bad report dma: 0x%x", (u8)report_dma);
return; return;
@ -339,12 +350,14 @@ namespace rsx
switch (type) switch (type)
{ {
case CELL_GCM_ZPASS_PIXEL_CNT: case CELL_GCM_ZPASS_PIXEL_CNT:
// todo: actual zculling, here we just report max, which seems to be enough for most games, but causes them to render *everything*
result->value = 0xFFFFFFFF;
break;
case CELL_GCM_ZCULL_STATS: case CELL_GCM_ZCULL_STATS:
case CELL_GCM_ZCULL_STATS1: case CELL_GCM_ZCULL_STATS1:
case CELL_GCM_ZCULL_STATS2: case CELL_GCM_ZCULL_STATS2:
case CELL_GCM_ZCULL_STATS3: case CELL_GCM_ZCULL_STATS3:
result->value = 0; result->value = 0;
LOG_WARNING(RSX, "NV4097_GET_REPORT: Unimplemented type %d", type);
break; break;
default: default:
@ -352,8 +365,8 @@ namespace rsx
LOG_ERROR(RSX, "NV4097_GET_REPORT: Bad type %d", type); LOG_ERROR(RSX, "NV4097_GET_REPORT: Bad type %d", type);
break; break;
} }
// This padding is needed to be set to 0, as games may use it for sync
//result->padding = 0; result->padding = 0;
} }
void clear_report_value(thread* rsx, u32 _reg, u32 arg) void clear_report_value(thread* rsx, u32 _reg, u32 arg)
@ -514,14 +527,14 @@ namespace rsx
//HACK: it's extension of the flip-hack. remove this when textures cache would be properly implemented //HACK: it's extension of the flip-hack. remove this when textures cache would be properly implemented
for (int i = 0; i < rsx::limits::color_buffers_count; ++i) for (int i = 0; i < rsx::limits::color_buffers_count; ++i)
{ {
u32 begin = rsx->gcm_buffers[i].offset; u32 begin = rsx->display_buffers[i].offset;
if (dst_offset < begin || !begin) if (dst_offset < begin || !begin)
{ {
continue; continue;
} }
if (rsx->gcm_buffers[i].width < 720 || rsx->gcm_buffers[i].height < 480) if (rsx->display_buffers[i].width < 720 || rsx->display_buffers[i].height < 480)
{ {
continue; continue;
} }
@ -531,7 +544,7 @@ namespace rsx
return; return;
} }
u32 end = begin + rsx->gcm_buffers[i].height * rsx->gcm_buffers[i].pitch; u32 end = begin + rsx->display_buffers[i].height * rsx->display_buffers[i].pitch;
if (dst_offset < end) if (dst_offset < end)
{ {
@ -862,14 +875,13 @@ namespace rsx
rsx->timer_sync.Start(); rsx->timer_sync.Start();
} }
rsx->gcm_current_buffer = arg; rsx->current_display_buffer = arg;
rsx->flip(arg); rsx->flip(arg);
// After each flip PS3 system is executing a routine that changes registers value to some default. // After each flip PS3 system is executing a routine that changes registers value to some default.
// Some game use this default state (SH3). // Some game use this default state (SH3).
rsx->reset(); rsx->reset();
rsx->last_flip_time = get_system_time() - 1000000; rsx->last_flip_time = get_system_time() - 1000000;
rsx->gcm_current_buffer = arg;
rsx->flip_status = CELL_GCM_DISPLAY_FLIP_STATUS_DONE; rsx->flip_status = CELL_GCM_DISPLAY_FLIP_STATUS_DONE;
if (rsx->flip_handler) if (rsx->flip_handler)
@ -971,7 +983,7 @@ namespace rsx
registers[NV4097_SET_SURFACE_FORMAT] = (8 << 0) | (2 << 5) | (0 << 12) | (1 << 16) | (1 << 24); registers[NV4097_SET_SURFACE_FORMAT] = (8 << 0) | (2 << 5) | (0 << 12) | (1 << 16) | (1 << 24);
// rsx dma initial values // 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[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[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; registers[NV309E_SET_CONTEXT_DMA_IMAGE] = CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER;

View file

@ -889,6 +889,11 @@ namespace rsx
return decode<NV4097_SET_BEGIN_END>().primitive(); return decode<NV4097_SET_BEGIN_END>().primitive();
} }
u32 semaphore_context_dma_406e() const
{
return decode<NV406E_SET_CONTEXT_DMA_SEMAPHORE>().context_dma();
}
u32 semaphore_offset_406e() const u32 semaphore_offset_406e() const
{ {
return decode<NV406E_SEMAPHORE_OFFSET>().semaphore_offset(); return decode<NV406E_SEMAPHORE_OFFSET>().semaphore_offset();

View file

@ -411,9 +411,7 @@ void Buffer::mouseDoubleClickEvent(QMouseEvent* event)
return; return;
} }
const auto buffers = render->gcm_buffers; const auto buffers = render->display_buffers;
if (!buffers)
return;
// TODO: Is there any better way to choose the color buffers // TODO: Is there any better way to choose the color buffers
#define SHOW_BUFFER(id) \ #define SHOW_BUFFER(id) \
@ -705,12 +703,9 @@ void rsx_debugger::GetBuffers()
// Draw Buffers // Draw Buffers
// TODO: Currently it only supports color buffers // TODO: Currently it only supports color buffers
for (u32 bufferId=0; bufferId < render->gcm_buffers_count; bufferId++) for (u32 bufferId=0; bufferId < render->display_buffers_count; bufferId++)
{ {
if(!vm::check_addr(render->gcm_buffers.addr())) auto buffers = render->display_buffers;
continue;
auto buffers = render->gcm_buffers;
u32 RSXbuffer_addr = render->local_mem_addr + buffers[bufferId].offset; u32 RSXbuffer_addr = render->local_mem_addr + buffers[bufferId].offset;
if(!vm::check_addr(RSXbuffer_addr)) if(!vm::check_addr(RSXbuffer_addr))