mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-31 12:31:45 +01:00
Major gcm emulation improvements
Improved RSX DMA support (WIP)
This commit is contained in:
parent
816169fe9e
commit
3352e235b6
@ -12,10 +12,42 @@
|
||||
|
||||
logs::channel cellGcmSys("cellGcmSys", logs::level::notice);
|
||||
|
||||
extern s32 cellGcmCallback(vm::ptr<CellGcmContextData> context, u32 count);
|
||||
extern s32 cellGcmCallback(vm::ptr<rsx::control_t> context, u32 count);
|
||||
extern void ppu_register_function_at(u32 addr, ppu_function_t ptr);
|
||||
|
||||
const u32 tiled_pitches[] = {
|
||||
namespace gcm
|
||||
{
|
||||
struct context_t
|
||||
{
|
||||
vm::ps3::bptr<CellGcmContextCallback> callback;
|
||||
be_t<u32> rtoc;
|
||||
};
|
||||
|
||||
static vm::ptr<context_t> context;
|
||||
static vm::pptr<rsx::context_t> current_context;
|
||||
|
||||
vm::ps3::ptr<CellGcmContextCallback> allocate_callback_function()
|
||||
{
|
||||
u32 address = vm::alloc(sizeof(u32) * 2, vm::main);
|
||||
|
||||
vm::write32(address + sizeof(u32) * 0, ppu_instructions::HACK(FIND_FUNC(cellGcmCallback)));
|
||||
vm::write32(address + sizeof(u32) * 1, ppu_instructions::BLR());
|
||||
ppu_register_function_at(address, BIND_FUNC(cellGcmCallback));
|
||||
|
||||
return vm::cast(address);
|
||||
}
|
||||
|
||||
void initialize(vm::pptr<rsx::context_t> current_context)
|
||||
{
|
||||
gcm::current_context = current_context;
|
||||
|
||||
context = vm::cast(vm::alloc(sizeof(context_t), vm::main));
|
||||
context->callback = allocate_callback_function();
|
||||
context->rtoc = 0xabadcafe;
|
||||
}
|
||||
}
|
||||
|
||||
static const u32 tiled_pitches[] = {
|
||||
0x00000000, 0x00000200, 0x00000300, 0x00000400,
|
||||
0x00000500, 0x00000600, 0x00000700, 0x00000800,
|
||||
0x00000A00, 0x00000C00, 0x00000D00, 0x00000E00,
|
||||
@ -27,16 +59,10 @@ const u32 tiled_pitches[] = {
|
||||
0x00010000
|
||||
};
|
||||
|
||||
u32 local_size = 0;
|
||||
u32 local_addr = 0;
|
||||
u64 system_mode = 0;
|
||||
static u64 g_system_mode = 0;
|
||||
|
||||
CellGcmConfig current_config;
|
||||
CellGcmContextData current_context;
|
||||
gcmInfo gcm_info;
|
||||
|
||||
u32 map_offset_addr = 0;
|
||||
u32 map_offset_pos = 0;
|
||||
static u32 g_map_offset_addr = 0;
|
||||
static u32 g_map_offset_pos = 0;
|
||||
|
||||
// Auxiliary functions
|
||||
|
||||
@ -65,6 +91,19 @@ u32 gcmGetLocalMemorySize(u32 sdk_version)
|
||||
return 0x0E000000; // 224MB
|
||||
}
|
||||
|
||||
s32 gcmMapLocalMemory()
|
||||
{
|
||||
rsx::state.frame_buffer = vm::cast(0xC0000000);
|
||||
rsx::state.frame_buffer_size = 0xf900000; // TODO: Get sdk_version in _cellGcmFunc15 and pass it to gcmGetLocalMemorySize
|
||||
|
||||
if (!vm::falloc(rsx::state.frame_buffer.addr(), rsx::state.frame_buffer_size, vm::video))
|
||||
{
|
||||
return CELL_GCM_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
CellGcmOffsetTable offsetTable;
|
||||
|
||||
void InitOffsetTable()
|
||||
@ -83,30 +122,35 @@ void InitOffsetTable()
|
||||
u32 cellGcmGetLabelAddress(u8 index)
|
||||
{
|
||||
cellGcmSys.trace("cellGcmGetLabelAddress(index=%d)", index);
|
||||
return gcm_info.label_addr + 0x10 * index;
|
||||
return rsx::state.context.ptr(&rsx::context_t::semaphores, index).addr();
|
||||
}
|
||||
|
||||
vm::ptr<CellGcmReportData> cellGcmGetReportDataAddressLocation(u32 index, u32 location)
|
||||
{
|
||||
cellGcmSys.warning("cellGcmGetReportDataAddressLocation(index=%d, location=%d)", index, location);
|
||||
|
||||
if (location == CELL_GCM_LOCATION_LOCAL) {
|
||||
if (index >= 2048) {
|
||||
if (location == CELL_GCM_LOCATION_LOCAL)
|
||||
{
|
||||
if (index >= sizeof(rsx::context_t::reports) / sizeof(*rsx::context_t::reports))
|
||||
{
|
||||
cellGcmSys.error("cellGcmGetReportDataAddressLocation: Wrong local index (%d)", index);
|
||||
return vm::null;
|
||||
}
|
||||
return vm::ptr<CellGcmReportData>::make(0xC0000000 + index * 0x10);
|
||||
|
||||
return rsx::state.context.ptr(&rsx::context_t::reports, index);
|
||||
}
|
||||
|
||||
if (location == CELL_GCM_LOCATION_MAIN) {
|
||||
if (index >= 1024 * 1024) {
|
||||
if (location == CELL_GCM_LOCATION_MAIN)
|
||||
{
|
||||
if (index >= sizeof(rsx::frame_buffer_t::reports) / sizeof(*rsx::frame_buffer_t::reports))
|
||||
{
|
||||
cellGcmSys.error("cellGcmGetReportDataAddressLocation: Wrong main index (%d)", index);
|
||||
return vm::null;
|
||||
}
|
||||
return vm::ptr<CellGcmReportData>::make(RSXIOMem.RealAddr(index * 0x10));
|
||||
|
||||
return rsx::state.frame_buffer.ptr(&rsx::frame_buffer_t::reports, index);
|
||||
}
|
||||
|
||||
cellGcmSys.error("cellGcmGetReportDataAddressLocation: Wrong location (%d)", location);
|
||||
return vm::null;
|
||||
}
|
||||
|
||||
@ -114,11 +158,13 @@ u64 cellGcmGetTimeStamp(u32 index)
|
||||
{
|
||||
cellGcmSys.trace("cellGcmGetTimeStamp(index=%d)", index);
|
||||
|
||||
if (index >= 2048) {
|
||||
if (index >= sizeof(rsx::frame_buffer_t::reports) / sizeof(*rsx::frame_buffer_t::reports))
|
||||
{
|
||||
cellGcmSys.error("cellGcmGetTimeStamp: Wrong local index (%d)", index);
|
||||
return 0;
|
||||
}
|
||||
return vm::read64(0xC0000000 + index * 0x10);
|
||||
|
||||
return rsx::state.frame_buffer->reports[index].timer;
|
||||
}
|
||||
|
||||
s32 cellGcmGetCurrentField()
|
||||
@ -145,7 +191,7 @@ u32 cellGcmGetNotifyDataAddress(u32 index)
|
||||
*/
|
||||
vm::ptr<CellGcmReportData> _cellGcmFunc12()
|
||||
{
|
||||
return vm::ptr<CellGcmReportData>::make(0xC0000000); // TODO
|
||||
return vm::cast(rsx::state.frame_buffer.addr());
|
||||
}
|
||||
|
||||
u32 cellGcmGetReport(u32 type, u32 index)
|
||||
@ -173,7 +219,7 @@ u32 cellGcmGetReportDataAddress(u32 index)
|
||||
cellGcmSys.error("cellGcmGetReportDataAddress: Wrong local index (%d)", index);
|
||||
return 0;
|
||||
}
|
||||
return 0xC0000000 + index * 0x10;
|
||||
return vm::cast(rsx::state.frame_buffer.addr() + index * 0x10);
|
||||
}
|
||||
|
||||
u32 cellGcmGetReportDataLocation(u32 index, u32 location)
|
||||
@ -216,7 +262,7 @@ u32 cellGcmGetControlRegister()
|
||||
{
|
||||
cellGcmSys.trace("cellGcmGetControlRegister()");
|
||||
|
||||
return gcm_info.control_addr;
|
||||
return rsx::state.context.ptr(&rsx::context_t::control).ptr(&rsx::control_t::put).addr();
|
||||
}
|
||||
|
||||
u32 cellGcmGetDefaultCommandWordSize()
|
||||
@ -257,7 +303,7 @@ s32 cellGcmBindTile(u8 index)
|
||||
return CELL_GCM_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
fxm::get<GSRender>()->tiles[index].binded = true;
|
||||
rsx::state.unpacked_tiles[index].binded = true;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -272,7 +318,7 @@ s32 cellGcmBindZcull(u8 index)
|
||||
return CELL_GCM_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
fxm::get<GSRender>()->zculls[index].binded = true;
|
||||
rsx::state.unpacked_zculls[index].binded = true;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -281,14 +327,18 @@ s32 cellGcmGetConfiguration(vm::ptr<CellGcmConfig> config)
|
||||
{
|
||||
cellGcmSys.trace("cellGcmGetConfiguration(config=*0x%x)", config);
|
||||
|
||||
*config = current_config;
|
||||
config->localAddress = rsx::state.frame_buffer.addr();
|
||||
config->localSize = rsx::state.frame_buffer_size;
|
||||
config->ioSize = rsx::state.io_size;
|
||||
config->memoryFrequency = 650000000;
|
||||
config->coreFrequency = 500000000;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellGcmGetFlipStatus()
|
||||
{
|
||||
s32 status = fxm::get<GSRender>()->flip_status;
|
||||
s32 status = rsx::state.flip_status;
|
||||
|
||||
cellGcmSys.trace("cellGcmGetFlipStatus() -> %d", status);
|
||||
|
||||
@ -319,29 +369,40 @@ void _cellGcmFunc15(vm::ptr<CellGcmContextData> context)
|
||||
return;
|
||||
}
|
||||
|
||||
u32 g_defaultCommandBufferBegin, g_defaultCommandBufferFragmentCount;
|
||||
static u32 g_defaultCommandBufferBegin, g_defaultCommandBufferFragmentCount;
|
||||
|
||||
// Called by cellGcmInit
|
||||
s32 _cellGcmInitBody(vm::pptr<CellGcmContextData> context, u32 cmdSize, u32 ioSize, u32 ioAddress)
|
||||
s32 _cellGcmInitBody(vm::pptr<rsx::context_t> context, u32 cmdSize, u32 ioSize, u32 ioAddress)
|
||||
{
|
||||
cellGcmSys.warning("_cellGcmInitBody(context=**0x%x, cmdSize=0x%x, ioSize=0x%x, ioAddress=0x%x)", context, cmdSize, ioSize, ioAddress);
|
||||
|
||||
current_config.ioAddress = 0;
|
||||
current_config.localAddress = 0;
|
||||
local_size = 0;
|
||||
local_addr = 0;
|
||||
InitOffsetTable();
|
||||
|
||||
if (!local_size && !local_addr)
|
||||
if (gcmMapEaIoAddress(ioAddress, 0, ioSize, false) != CELL_OK)
|
||||
{
|
||||
local_size = 0xf900000; // TODO: Get sdk_version in _cellGcmFunc15 and pass it to gcmGetLocalMemorySize
|
||||
local_addr = 0xC0000000;
|
||||
vm::falloc(0xC0000000, local_size, vm::video);
|
||||
cellGcmSys.error("cellGcmInit: CELL_GCM_ERROR_FAILURE");
|
||||
return CELL_GCM_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
cellGcmSys.warning("*** local memory(addr=0x%x, size=0x%x)", local_addr, local_size);
|
||||
gcm::initialize(context);
|
||||
|
||||
InitOffsetTable();
|
||||
if (system_mode == CELL_GCM_SYSTEM_MODE_IOMAP_512MB)
|
||||
rsx::state.device = vm::cast(vm::alloc(sizeof(rsx::device_t), vm::main));
|
||||
rsx::state.context = vm::cast(vm::alloc(sizeof(rsx::context_t), vm::main));
|
||||
|
||||
//rsx::state.io = vm::cast(ioAddress);
|
||||
rsx::state.io_size = cmdSize;
|
||||
rsx::state.display_buffers_count = 0;
|
||||
rsx::state.current_display_buffer = 0;
|
||||
rsx::state.display_buffers = vm::cast(vm::alloc(sizeof(CellGcmDisplayInfo) * 8, vm::main));
|
||||
rsx::state.zculls = vm::cast(vm::alloc(sizeof(CellGcmZcullInfo) * rsx::limits::zculls_count, vm::main));
|
||||
rsx::state.tiles = vm::cast(vm::alloc(sizeof(CellGcmTileInfo) * rsx::limits::tiles_count, vm::main));
|
||||
rsx::state.flip_status = 0;
|
||||
|
||||
gcmMapLocalMemory();
|
||||
|
||||
cellGcmSys.warning("*** local memory(addr=0x%x, size=0x%x)", rsx::state.frame_buffer, rsx::state.frame_buffer_size);
|
||||
|
||||
if (g_system_mode == CELL_GCM_SYSTEM_MODE_IOMAP_512MB)
|
||||
{
|
||||
cellGcmSys.warning("cellGcmInit(): 512MB io address space used");
|
||||
RSXIOMem.SetRange(0, 0x20000000 /*512MB*/);
|
||||
@ -352,59 +413,28 @@ s32 _cellGcmInitBody(vm::pptr<CellGcmContextData> context, u32 cmdSize, u32 ioSi
|
||||
RSXIOMem.SetRange(0, 0x10000000 /*256MB*/);
|
||||
}
|
||||
|
||||
if (gcmMapEaIoAddress(ioAddress, 0, ioSize, false) != CELL_OK)
|
||||
{
|
||||
cellGcmSys.error("cellGcmInit: CELL_GCM_ERROR_FAILURE");
|
||||
return CELL_GCM_ERROR_FAILURE;
|
||||
}
|
||||
g_map_offset_addr = 0;
|
||||
g_map_offset_pos = 0;
|
||||
|
||||
map_offset_addr = 0;
|
||||
map_offset_pos = 0;
|
||||
current_config.ioSize = ioSize;
|
||||
current_config.ioAddress = ioAddress;
|
||||
current_config.localSize = local_size;
|
||||
current_config.localAddress = local_addr;
|
||||
current_config.memoryFrequency = 650000000;
|
||||
current_config.coreFrequency = 500000000;
|
||||
u32 commandBufferPageSize = 32 * 1024;
|
||||
|
||||
// Create contexts
|
||||
g_defaultCommandBufferBegin = ioAddress + 4096;
|
||||
g_defaultCommandBufferFragmentCount = cmdSize / commandBufferPageSize;
|
||||
|
||||
g_defaultCommandBufferBegin = ioAddress;
|
||||
g_defaultCommandBufferFragmentCount = cmdSize / (32 * 1024);
|
||||
rsx::state.context->control.begin = vm::cast(g_defaultCommandBufferBegin);
|
||||
rsx::state.context->control.end = vm::cast(g_defaultCommandBufferBegin + commandBufferPageSize - 4); // 4b at the end for jump
|
||||
rsx::state.context->control.current = rsx::state.context->control.begin;
|
||||
rsx::state.context->control.callback = vm::cast(gcm::context.ptr(&gcm::context_t::callback).addr());
|
||||
rsx::state.context->control.put = 0;
|
||||
rsx::state.context->control.get = 0;
|
||||
rsx::state.context->control.ref = -1;
|
||||
|
||||
gcm_info.context_addr = vm::alloc(0x1000, vm::main);
|
||||
gcm_info.control_addr = vm::alloc(0x1000, vm::main);
|
||||
gcm_info.label_addr = vm::alloc(0x1000, vm::main); // ???
|
||||
//TODO: send new context
|
||||
fxm::get<GSRender>()->init();
|
||||
|
||||
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
|
||||
current_context.current = current_context.begin;
|
||||
current_context.callback.set(gcm_info.context_addr + 0x40);
|
||||
rsx::state.context->semaphores[3].value = 1;
|
||||
|
||||
vm::write32(gcm_info.context_addr + 0x40, gcm_info.context_addr + 0x48);
|
||||
vm::write32(gcm_info.context_addr + 0x44, 0xabadcafe);
|
||||
vm::write32(gcm_info.context_addr + 0x48, ppu_instructions::HACK(FIND_FUNC(cellGcmCallback)));
|
||||
vm::write32(gcm_info.context_addr + 0x4c, ppu_instructions::BLR());
|
||||
ppu_register_function_at(gcm_info.context_addr + 0x48, BIND_FUNC(cellGcmCallback));
|
||||
|
||||
vm::_ref<CellGcmContextData>(gcm_info.context_addr) = current_context;
|
||||
context->set(gcm_info.context_addr);
|
||||
|
||||
auto& ctrl = vm::_ref<CellGcmControl>(gcm_info.control_addr);
|
||||
ctrl.put = 0;
|
||||
ctrl.get = 0;
|
||||
ctrl.ref = -1;
|
||||
|
||||
const auto render = fxm::get<GSRender>();
|
||||
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->label_addr = gcm_info.label_addr;
|
||||
render->init(g_defaultCommandBufferBegin, cmdSize, gcm_info.control_addr, local_addr);
|
||||
*context = rsx::state.context;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -413,7 +443,7 @@ s32 cellGcmResetFlipStatus()
|
||||
{
|
||||
cellGcmSys.trace("cellGcmResetFlipStatus()");
|
||||
|
||||
fxm::get<GSRender>()->flip_status = CELL_GCM_DISPLAY_FLIP_STATUS_WAITING;
|
||||
rsx::state.flip_status = CELL_GCM_DISPLAY_FLIP_STATUS_WAITING;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -427,7 +457,7 @@ s32 cellGcmSetDebugOutputLevel(s32 level)
|
||||
case CELL_GCM_DEBUG_LEVEL0:
|
||||
case CELL_GCM_DEBUG_LEVEL1:
|
||||
case CELL_GCM_DEBUG_LEVEL2:
|
||||
fxm::get<GSRender>()->debug_level = level;
|
||||
rsx::state.debug_level = level;
|
||||
break;
|
||||
|
||||
default: return CELL_EINVAL;
|
||||
@ -446,18 +476,14 @@ s32 cellGcmSetDisplayBuffer(u32 id, u32 offset, u32 pitch, u32 width, u32 height
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
const auto render = fxm::get<GSRender>();
|
||||
rsx::state.display_buffers[id].offset = offset;
|
||||
rsx::state.display_buffers[id].pitch = pitch;
|
||||
rsx::state.display_buffers[id].width = width;
|
||||
rsx::state.display_buffers[id].height = height;
|
||||
|
||||
auto buffers = render->gcm_buffers;
|
||||
|
||||
buffers[id].offset = offset;
|
||||
buffers[id].pitch = pitch;
|
||||
buffers[id].width = width;
|
||||
buffers[id].height = height;
|
||||
|
||||
if (id + 1 > render->gcm_buffers_count)
|
||||
if (id + 1 > rsx::state.display_buffers_count)
|
||||
{
|
||||
render->gcm_buffers_count = id + 1;
|
||||
rsx::state.display_buffers_count = id + 1;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
@ -467,7 +493,7 @@ void cellGcmSetFlipHandler(vm::ptr<void(u32)> handler)
|
||||
{
|
||||
cellGcmSys.warning("cellGcmSetFlipHandler(handler=*0x%x)", handler);
|
||||
|
||||
fxm::get<GSRender>()->flip_handler = handler;
|
||||
rsx::state.flip_handler = handler;
|
||||
}
|
||||
|
||||
s32 cellGcmSetFlipMode(u32 mode)
|
||||
@ -479,7 +505,7 @@ s32 cellGcmSetFlipMode(u32 mode)
|
||||
case CELL_GCM_DISPLAY_HSYNC:
|
||||
case CELL_GCM_DISPLAY_VSYNC:
|
||||
case CELL_GCM_DISPLAY_HSYNC_WITH_NOISE:
|
||||
fxm::get<GSRender>()->flip_mode = mode;
|
||||
rsx::state.flip_mode = mode;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -492,11 +518,10 @@ s32 cellGcmSetFlipMode(u32 mode)
|
||||
void cellGcmSetFlipStatus()
|
||||
{
|
||||
cellGcmSys.warning("cellGcmSetFlipStatus()");
|
||||
|
||||
fxm::get<GSRender>()->flip_status = 0;
|
||||
rsx::state.flip_status = 0;
|
||||
}
|
||||
|
||||
s32 cellGcmSetPrepareFlip(PPUThread& ppu, vm::ptr<CellGcmContextData> ctxt, u32 id)
|
||||
s32 cellGcmSetPrepareFlip(PPUThread& ppu, vm::ptr<rsx::control_t> ctxt, u32 id)
|
||||
{
|
||||
cellGcmSys.trace("cellGcmSetPrepareFlip(ctx=*0x%x, id=0x%x)", ctxt, id);
|
||||
|
||||
@ -508,30 +533,28 @@ s32 cellGcmSetPrepareFlip(PPUThread& ppu, vm::ptr<CellGcmContextData> ctxt, u32
|
||||
|
||||
if (ctxt->current + 2 >= ctxt->end)
|
||||
{
|
||||
if (s32 res = ctxt->callback(ppu, ctxt, 8 /* ??? */))
|
||||
if (s32 res = (*ctxt->callback)(ppu, ctxt.addr(), 8 /* ??? */))
|
||||
{
|
||||
cellGcmSys.error("cellGcmSetPrepareFlip: callback failed (0x%08x)", res);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
const u32 cmd_size = rsx::make_command(ctxt->current, GCM_FLIP_COMMAND, { id });
|
||||
|
||||
if (ctxt.addr() == gcm_info.context_addr)
|
||||
{
|
||||
vm::_ref<CellGcmControl>(gcm_info.control_addr).put += cmd_size;
|
||||
}
|
||||
ctxt->put += rsx::make_command(ctxt->current, GCM_FLIP_COMMAND, { id });
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
s32 cellGcmSetFlip(PPUThread& ppu, vm::ptr<CellGcmContextData> ctxt, u32 id)
|
||||
s32 cellGcmSetFlip(PPUThread& ppu, vm::ptr<rsx::control_t> ctxt, u32 id)
|
||||
{
|
||||
cellGcmSys.trace("cellGcmSetFlip(ctxt=*0x%x, id=0x%x)", ctxt, id);
|
||||
|
||||
if (s32 res = cellGcmSetPrepareFlip(ppu, ctxt, id))
|
||||
{
|
||||
if (res < 0) return CELL_GCM_ERROR_FAILURE;
|
||||
if (res < 0)
|
||||
{
|
||||
return CELL_GCM_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
@ -591,9 +614,7 @@ s32 cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u
|
||||
cellGcmSys.error("cellGcmSetTileInfo: bad compression mode! (%d)", comp);
|
||||
}
|
||||
|
||||
const auto render = fxm::get<GSRender>();
|
||||
|
||||
auto& tile = render->tiles[index];
|
||||
auto& tile = rsx::state.unpacked_tiles[index];
|
||||
tile.location = location;
|
||||
tile.offset = offset;
|
||||
tile.size = size;
|
||||
@ -602,7 +623,7 @@ s32 cellGcmSetTileInfo(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u
|
||||
tile.base = base;
|
||||
tile.bank = bank;
|
||||
|
||||
vm::_ptr<CellGcmTileInfo>(render->tiles_addr)[index] = tile.pack();
|
||||
rsx::state.tiles[index] = tile.pack();
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -610,7 +631,7 @@ void cellGcmSetUserHandler(vm::ptr<void(u32)> handler)
|
||||
{
|
||||
cellGcmSys.warning("cellGcmSetUserHandler(handler=*0x%x)", handler);
|
||||
|
||||
fxm::get<GSRender>()->user_handler = handler;
|
||||
rsx::state.user_handler = handler;
|
||||
}
|
||||
|
||||
s32 cellGcmSetUserCommand()
|
||||
@ -622,7 +643,7 @@ void cellGcmSetVBlankHandler(vm::ptr<void(u32)> handler)
|
||||
{
|
||||
cellGcmSys.warning("cellGcmSetVBlankHandler(handler=*0x%x)", handler);
|
||||
|
||||
fxm::get<GSRender>()->vblank_handler = handler;
|
||||
rsx::state.vblank_handler = handler;
|
||||
}
|
||||
|
||||
s32 cellGcmSetWaitFlip(vm::ptr<CellGcmContextData> ctxt)
|
||||
@ -650,9 +671,7 @@ s32 cellGcmSetZcull(u8 index, u32 offset, u32 width, u32 height, u32 cullStart,
|
||||
return CELL_GCM_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
const auto render = fxm::get<GSRender>();
|
||||
|
||||
auto& zcull = render->zculls[index];
|
||||
auto& zcull = rsx::state.unpacked_zculls[index];
|
||||
zcull.offset = offset;
|
||||
zcull.width = width;
|
||||
zcull.height = height;
|
||||
@ -665,7 +684,7 @@ s32 cellGcmSetZcull(u8 index, u32 offset, u32 width, u32 height, u32 cullStart,
|
||||
zcull.sRef = sRef;
|
||||
zcull.sMask = sMask;
|
||||
|
||||
vm::_ptr<CellGcmZcullInfo>(render->zculls_addr)[index] = zcull.pack();
|
||||
rsx::state.zculls[index] = zcull.pack();
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -679,7 +698,7 @@ s32 cellGcmUnbindTile(u8 index)
|
||||
return CELL_GCM_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
fxm::get<GSRender>()->tiles[index].binded = false;
|
||||
rsx::state.unpacked_tiles[index].binded = false;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -694,37 +713,34 @@ s32 cellGcmUnbindZcull(u8 index)
|
||||
return CELL_EINVAL;
|
||||
}
|
||||
|
||||
fxm::get<GSRender>()->zculls[index].binded = false;
|
||||
rsx::state.unpacked_zculls[index].binded = false;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
u32 cellGcmGetTileInfo()
|
||||
vm::ptr<CellGcmTileInfo> cellGcmGetTileInfo()
|
||||
{
|
||||
cellGcmSys.warning("cellGcmGetTileInfo()");
|
||||
return fxm::get<GSRender>()->tiles_addr;
|
||||
return rsx::state.tiles;
|
||||
}
|
||||
|
||||
u32 cellGcmGetZcullInfo()
|
||||
vm::ptr<CellGcmZcullInfo> cellGcmGetZcullInfo()
|
||||
{
|
||||
cellGcmSys.warning("cellGcmGetZcullInfo()");
|
||||
return fxm::get<GSRender>()->zculls_addr;
|
||||
return rsx::state.zculls;
|
||||
}
|
||||
|
||||
u32 cellGcmGetDisplayInfo()
|
||||
vm::ptr<CellGcmDisplayInfo> cellGcmGetDisplayInfo()
|
||||
{
|
||||
cellGcmSys.warning("cellGcmGetDisplayInfo()");
|
||||
return fxm::get<GSRender>()->gcm_buffers.addr();
|
||||
return rsx::state.display_buffers;
|
||||
}
|
||||
|
||||
s32 cellGcmGetCurrentDisplayBufferId(vm::ptr<u8> id)
|
||||
{
|
||||
cellGcmSys.warning("cellGcmGetCurrentDisplayBufferId(id=*0x%x)", id);
|
||||
|
||||
if ((*id = fxm::get<GSRender>()->gcm_current_buffer) > UINT8_MAX)
|
||||
{
|
||||
throw EXCEPTION("Unexpected");
|
||||
}
|
||||
*id = rsx::state.current_display_buffer;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -756,7 +772,7 @@ u64 cellGcmGetLastFlipTime()
|
||||
{
|
||||
cellGcmSys.trace("cellGcmGetLastFlipTime()");
|
||||
|
||||
return fxm::get<GSRender>()->last_flip_time;
|
||||
return rsx::state.last_flip_time;
|
||||
}
|
||||
|
||||
u64 cellGcmGetLastSecondVTime()
|
||||
@ -769,7 +785,7 @@ u64 cellGcmGetVBlankCount()
|
||||
{
|
||||
cellGcmSys.trace("cellGcmGetVBlankCount()");
|
||||
|
||||
return fxm::get<GSRender>()->vblank_count;
|
||||
return rsx::state.vblank_count;
|
||||
}
|
||||
|
||||
s32 cellGcmSysGetLastVBlankTime()
|
||||
@ -781,7 +797,7 @@ s32 cellGcmInitSystemMode(u64 mode)
|
||||
{
|
||||
cellGcmSys.trace("cellGcmInitSystemMode(mode=0x%x)", mode);
|
||||
|
||||
system_mode = mode;
|
||||
g_system_mode = mode;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -839,7 +855,7 @@ s32 cellGcmAddressToOffset(u32 address, vm::ptr<u32> offset)
|
||||
cellGcmSys.trace("cellGcmAddressToOffset(address=0x%x, offset=*0x%x)", address, offset);
|
||||
|
||||
// Address not on main memory or local memory
|
||||
if (address >= 0xD0000000)
|
||||
if (address >= rsx::state.frame_buffer.addr() + rsx::state.frame_buffer_size)
|
||||
{
|
||||
return CELL_GCM_ERROR_FAILURE;
|
||||
}
|
||||
@ -849,7 +865,7 @@ s32 cellGcmAddressToOffset(u32 address, vm::ptr<u32> offset)
|
||||
// Address in local memory
|
||||
if ((address >> 28) == 0xC)
|
||||
{
|
||||
result = address - 0xC0000000;
|
||||
result = address - rsx::state.frame_buffer.addr();
|
||||
}
|
||||
// Address in main memory else check
|
||||
else
|
||||
@ -946,18 +962,15 @@ s32 cellGcmMapLocalMemory(vm::ptr<u32> address, vm::ptr<u32> size)
|
||||
{
|
||||
cellGcmSys.warning("cellGcmMapLocalMemory(address=*0x%x, size=*0x%x)", address, size);
|
||||
|
||||
if (!local_addr && !local_size && vm::falloc(local_addr = 0xC0000000, local_size = 0xf900000 /* TODO */, vm::video))
|
||||
s32 result = gcmMapLocalMemory();
|
||||
|
||||
if (result == CELL_OK)
|
||||
{
|
||||
*address = local_addr;
|
||||
*size = local_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
cellGcmSys.error("RSX local memory already mapped");
|
||||
return CELL_GCM_ERROR_FAILURE;
|
||||
*address = rsx::state.frame_buffer.addr();
|
||||
*size = rsx::state.frame_buffer_size;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
s32 cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr<u32> offset)
|
||||
@ -989,8 +1002,6 @@ s32 cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr<u32> offset)
|
||||
return CELL_GCM_ERROR_NO_IO_PAGE_TABLE;
|
||||
}
|
||||
|
||||
render->main_mem_addr = render->ioAddress;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -1129,7 +1140,8 @@ s32 cellGcmSetCursorImageOffset(u32 offset)
|
||||
void cellGcmSetDefaultCommandBuffer()
|
||||
{
|
||||
cellGcmSys.warning("cellGcmSetDefaultCommandBuffer()");
|
||||
vm::write32(fxm::get<GSRender>()->ctxt_addr, gcm_info.context_addr);
|
||||
|
||||
*gcm::current_context = rsx::state.context;
|
||||
}
|
||||
|
||||
s32 cellGcmSetDefaultCommandBufferAndSegmentWordSize()
|
||||
@ -1141,19 +1153,21 @@ s32 cellGcmSetDefaultCommandBufferAndSegmentWordSize()
|
||||
// Other
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
s32 _cellGcmSetFlipCommand(PPUThread& ppu, vm::ptr<CellGcmContextData> ctx, u32 id)
|
||||
s32 _cellGcmSetFlipCommand(PPUThread& ppu, vm::ptr<rsx::control_t> ctx, u32 id)
|
||||
{
|
||||
cellGcmSys.trace("cellGcmSetFlipCommand(ctx=*0x%x, id=0x%x)", ctx, id);
|
||||
|
||||
return cellGcmSetPrepareFlip(ppu, ctx, id);
|
||||
}
|
||||
|
||||
s32 _cellGcmSetFlipCommandWithWaitLabel(PPUThread& ppu, vm::ptr<CellGcmContextData> ctx, u32 id, u32 label_index, u32 label_value)
|
||||
s32 _cellGcmSetFlipCommandWithWaitLabel(PPUThread& ppu, vm::ptr<rsx::context_t> 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);
|
||||
|
||||
s32 res = cellGcmSetPrepareFlip(ppu, ctx, id);
|
||||
vm::write32(gcm_info.label_addr + 0x10 * label_index, label_value);
|
||||
s32 res = cellGcmSetPrepareFlip(ppu, ctx.ptr(&rsx::context_t::control), id);
|
||||
ctx->semaphores[label_index].value = label_value;
|
||||
//TODO: time
|
||||
|
||||
return res < 0 ? CELL_GCM_ERROR_FAILURE : CELL_OK;
|
||||
}
|
||||
|
||||
@ -1186,9 +1200,7 @@ s32 cellGcmSetTile(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 co
|
||||
cellGcmSys.error("cellGcmSetTile: bad compression mode! (%d)", comp);
|
||||
}
|
||||
|
||||
const auto render = fxm::get<GSRender>();
|
||||
|
||||
auto& tile = render->tiles[index];
|
||||
auto& tile = rsx::state.unpacked_tiles[index];
|
||||
tile.location = location;
|
||||
tile.offset = offset;
|
||||
tile.size = size;
|
||||
@ -1197,7 +1209,7 @@ s32 cellGcmSetTile(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 co
|
||||
tile.base = base;
|
||||
tile.bank = bank;
|
||||
|
||||
vm::_ptr<CellGcmTileInfo>(render->tiles_addr)[index] = tile.pack();
|
||||
rsx::state.tiles[index] = tile.pack();
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@ -1283,23 +1295,23 @@ static bool isInCommandBufferExcept(u32 getPos, u32 bufferBegin, u32 bufferEnd)
|
||||
return true;
|
||||
}
|
||||
|
||||
s32 cellGcmCallback(vm::ptr<CellGcmContextData> context, u32 count)
|
||||
s32 cellGcmCallback(vm::ptr<rsx::control_t> context, u32 count)
|
||||
{
|
||||
cellGcmSys.trace("cellGcmCallback(context=*0x%x, count=0x%x)", context, count);
|
||||
|
||||
auto& ctrl = vm::_ref<CellGcmControl>(gcm_info.control_addr);
|
||||
auto& ctrl = *context;
|
||||
const std::chrono::time_point<std::chrono::system_clock> enterWait = std::chrono::system_clock::now();
|
||||
// Flush command buffer (ie allow RSX to read up to context->current)
|
||||
ctrl.put.exchange(getOffsetFromAddress(context->current.addr()));
|
||||
ctrl.put.exchange(getOffsetFromAddress(ctrl.current.addr()));
|
||||
|
||||
std::pair<u32, u32> newCommandBuffer = getNextCommandBufferBeginEnd(context->current.addr());
|
||||
std::pair<u32, u32> newCommandBuffer = getNextCommandBufferBeginEnd(ctrl.current.addr());
|
||||
u32 offset = getOffsetFromAddress(newCommandBuffer.first);
|
||||
// Write jump instruction
|
||||
*context->current = CELL_GCM_METHOD_FLAG_JUMP | offset;
|
||||
*ctrl.current = CELL_GCM_METHOD_FLAG_JUMP | offset;
|
||||
// Update current command buffer
|
||||
context->begin.set(newCommandBuffer.first);
|
||||
context->current.set(newCommandBuffer.first);
|
||||
context->end.set(newCommandBuffer.second);
|
||||
ctrl.begin.set(newCommandBuffer.first);
|
||||
ctrl.current.set(newCommandBuffer.first);
|
||||
ctrl.end.set(newCommandBuffer.second);
|
||||
|
||||
// Wait for rsx to "release" the new command buffer
|
||||
while (!Emu.IsStopped())
|
||||
@ -1319,8 +1331,10 @@ s32 cellGcmCallback(vm::ptr<CellGcmContextData> context, u32 count)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
DECLARE(ppu_module_manager::cellGcmSys)("cellGcmSys", []()
|
||||
DECLARE(ppu_module_manager::cellGcmSys)("cellGcmSys", [](ppu_static_module *_this)
|
||||
{
|
||||
//_this->on_load.push(&gcm::initialize);
|
||||
|
||||
// Data Retrieval
|
||||
REG_FUNC(cellGcmSys, cellGcmGetCurrentField);
|
||||
REG_FUNC(cellGcmSys, cellGcmGetLabelAddress);
|
||||
|
@ -496,9 +496,9 @@ void D3D12GSRender::flip(int buffer)
|
||||
if (false)
|
||||
{
|
||||
CellGcmDisplayInfo* buffers = nullptr;// = vm::ps3::_ptr<CellGcmDisplayInfo>(m_gcm_buffers_addr);
|
||||
u32 addr = rsx::get_address(gcm_buffers[gcm_current_buffer].offset, CELL_GCM_LOCATION_LOCAL);
|
||||
w = gcm_buffers[gcm_current_buffer].width;
|
||||
h = gcm_buffers[gcm_current_buffer].height;
|
||||
u32 addr = rsx::get_address(rsx::state.display_buffers[buffer].offset, CELL_GCM_LOCATION_LOCAL);
|
||||
w = rsx::state.display_buffers[buffer].width;
|
||||
h = rsx::state.display_buffers[buffer].height;
|
||||
u8 *src_buffer = vm::ps3::_ptr<u8>(addr);
|
||||
|
||||
row_pitch = align(w * 4, 256);
|
||||
|
@ -326,12 +326,12 @@ void D3D12GSRender::copy_render_target_to_dma_location()
|
||||
|
||||
u32 address_color[] =
|
||||
{
|
||||
rsx::get_address(offset_color[0], context_dma_color[0]),
|
||||
rsx::get_address(offset_color[1], context_dma_color[1]),
|
||||
rsx::get_address(offset_color[2], context_dma_color[2]),
|
||||
rsx::get_address(offset_color[3], context_dma_color[3]),
|
||||
rsx::get_address_dma(offset_color[0], context_dma_color[0]),
|
||||
rsx::get_address_dma(offset_color[1], context_dma_color[1]),
|
||||
rsx::get_address_dma(offset_color[2], context_dma_color[2]),
|
||||
rsx::get_address_dma(offset_color[3], context_dma_color[3]),
|
||||
};
|
||||
u32 address_z = rsx::get_address(offset_zeta, m_context_dma_z);
|
||||
u32 address_z = rsx::get_address_dma(offset_zeta, m_context_dma_z);
|
||||
|
||||
bool need_transfer = false;
|
||||
|
||||
|
@ -590,15 +590,24 @@ enum
|
||||
};
|
||||
|
||||
// GPU Class Handles
|
||||
enum
|
||||
{
|
||||
CELL_GCM_CONTEXT_SURFACE2D = 0x313371C3,
|
||||
CELL_GCM_CONTEXT_SWIZZLE2D = 0x31337A73,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER = 0xFEED0000, // Local memory
|
||||
CELL_GCM_CONTEXT_DMA_MEMORY_HOST_BUFFER = 0xFEED0001, // Main memory
|
||||
CELL_GCM_CONTEXT_SURFACE2D = 0x313371C3,
|
||||
CELL_GCM_CONTEXT_SWIZZLE2D = 0x31337A73,
|
||||
CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_REPORT = 0x66626660,
|
||||
CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_MAIN = 0xBAD68000,
|
||||
CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY0 = 0x66604200,
|
||||
CELL_GCM_CONTEXT_DMA_NOTIFY_MAIN_0 = 0x6660420F,
|
||||
CELL_GCM_CONTEXT_DMA_SEMAPHORE_RW = 0x66606660,
|
||||
CELL_GCM_CONTEXT_DMA_SEMAPHORE_R = 0x66616661,
|
||||
CELL_GCM_CONTEXT_DMA_DEVICE_RW = 0x56616660,
|
||||
CELL_GCM_CONTEXT_DMA_DEVICE_R = 0x56616661
|
||||
};
|
||||
|
||||
struct CellGcmControl
|
||||
@ -627,15 +636,7 @@ struct CellGcmContextData
|
||||
vm::ps3::bptr<u32> begin;
|
||||
vm::ps3::bptr<u32> end;
|
||||
vm::ps3::bptr<u32> current;
|
||||
vm::ps3::bptr<CellGcmContextCallback> callback;
|
||||
};
|
||||
|
||||
struct gcmInfo
|
||||
{
|
||||
u32 config_addr;
|
||||
u32 context_addr;
|
||||
u32 control_addr;
|
||||
u32 label_addr;
|
||||
vm::ps3::bpptr<CellGcmContextCallback> callback;
|
||||
};
|
||||
|
||||
struct CellGcmSurface
|
||||
|
@ -26,13 +26,19 @@ namespace
|
||||
|
||||
u32 get_front_face_ccw(u32 ffv)
|
||||
{
|
||||
rsx::window_origin shader_window_origin = rsx::to_window_origin((rsx::method_registers[NV4097_SET_SHADER_WINDOW] >> 12) & 0xf);
|
||||
|
||||
if (shader_window_origin == rsx::window_origin::bottom)
|
||||
{
|
||||
ffv ^= 1;
|
||||
}
|
||||
|
||||
switch (ffv)
|
||||
{
|
||||
default: // Disgaea 3 pass some garbage value at startup, this is needed to survive.
|
||||
case CELL_GCM_CW: return GL_CW;
|
||||
case CELL_GCM_CCW: return GL_CCW;
|
||||
}
|
||||
throw EXCEPTION("Unknown front face value: 0x%X", ffv);
|
||||
}
|
||||
}
|
||||
|
||||
@ -163,6 +169,7 @@ void GLGSRender::begin()
|
||||
|
||||
if (u32 blend_mrt = rsx::method_registers[NV4097_SET_BLEND_ENABLE_MRT])
|
||||
{
|
||||
__glcheck enable(blend_mrt & 1, GL_BLEND, 0);
|
||||
__glcheck enable(blend_mrt & 2, GL_BLEND, 1);
|
||||
__glcheck enable(blend_mrt & 4, GL_BLEND, 2);
|
||||
__glcheck enable(blend_mrt & 8, GL_BLEND, 3);
|
||||
@ -197,7 +204,7 @@ void GLGSRender::begin()
|
||||
__glcheck glCullFace(rsx::method_registers[NV4097_SET_CULL_FACE]);
|
||||
}
|
||||
|
||||
__glcheck glFrontFace(get_front_face_ccw(rsx::method_registers[NV4097_SET_FRONT_FACE] ^ 1));
|
||||
__glcheck glFrontFace(get_front_face_ccw(rsx::method_registers[NV4097_SET_FRONT_FACE]));
|
||||
|
||||
__glcheck enable(rsx::method_registers[NV4097_SET_POLY_SMOOTH_ENABLE], GL_POLYGON_SMOOTH);
|
||||
|
||||
@ -697,7 +704,9 @@ bool GLGSRender::load_program()
|
||||
RSXFragmentProgram fragment_program = get_current_fragment_program();
|
||||
|
||||
GLProgramBuffer prog_buffer;
|
||||
__glcheck prog_buffer.getGraphicPipelineState(vertex_program, fragment_program, nullptr);
|
||||
m_program = &prog_buffer.getGraphicPipelineState(vertex_program, fragment_program, nullptr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
rsx::program_info info = programs_cache.get(get_raw_program(), rsx::decompile_language::glsl);
|
||||
@ -792,21 +801,21 @@ bool GLGSRender::load_program()
|
||||
|
||||
void GLGSRender::flip(int buffer)
|
||||
{
|
||||
u32 buffer_width = gcm_buffers[buffer].width;
|
||||
u32 buffer_height = gcm_buffers[buffer].height;
|
||||
u32 buffer_pitch = gcm_buffers[buffer].pitch;
|
||||
u32 buffer_width = rsx::state.display_buffers[buffer].width;
|
||||
u32 buffer_height = rsx::state.display_buffers[buffer].height;
|
||||
u32 buffer_pitch = rsx::state.display_buffers[buffer].pitch;
|
||||
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
|
||||
rsx::tiled_region buffer_region = get_tiled_address(gcm_buffers[buffer].offset, CELL_GCM_LOCATION_LOCAL);
|
||||
rsx::tiled_region buffer_region = get_tiled_address(rsx::state.display_buffers[buffer].offset, CELL_GCM_LOCATION_LOCAL);
|
||||
u32 absolute_address = buffer_region.address + buffer_region.base;
|
||||
|
||||
if (0)
|
||||
{
|
||||
LOG_NOTICE(RSX, "flip(%d) -> 0x%x [0x%x]", buffer, absolute_address, rsx::get_address(gcm_buffers[1 - buffer].offset, CELL_GCM_LOCATION_LOCAL));
|
||||
LOG_NOTICE(RSX, "flip(%d) -> 0x%x [0x%x]", buffer, absolute_address, rsx::get_address(rsx::state.display_buffers[1 - buffer].offset, CELL_GCM_LOCATION_LOCAL));
|
||||
}
|
||||
|
||||
gl::texture *render_target_texture = m_rtts.get_texture_from_render_target_if_applicable(absolute_address);
|
||||
|
@ -187,13 +187,13 @@ void GLGSRender::read_buffers()
|
||||
for (int i = index; i < index + count; ++i)
|
||||
{
|
||||
u32 offset = rsx::method_registers[rsx::internals::mr_color_offset[i]];
|
||||
u32 location = rsx::method_registers[rsx::internals::mr_color_dma[i]];
|
||||
u32 dma = rsx::method_registers[rsx::internals::mr_color_dma[i]];
|
||||
u32 pitch = rsx::method_registers[rsx::internals::mr_color_pitch[i]];
|
||||
|
||||
if (pitch <= 64)
|
||||
continue;
|
||||
|
||||
rsx::tiled_region color_buffer = get_tiled_address(offset, location & 0xf);
|
||||
rsx::tiled_region color_buffer = get_tiled_address_dma(offset, dma);
|
||||
u32 texaddr = (u32)((u64)color_buffer.ptr - (u64)vm::base(0));
|
||||
|
||||
bool success = m_gl_texture_cache.explicit_writeback((*std::get<1>(m_rtts.m_bound_render_targets[i])), texaddr, pitch);
|
||||
@ -254,7 +254,7 @@ void GLGSRender::read_buffers()
|
||||
if (pitch <= 64)
|
||||
return;
|
||||
|
||||
u32 depth_address = rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET], rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA]);
|
||||
u32 depth_address = rsx::get_address_dma(rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET], rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA]);
|
||||
bool in_cache = m_gl_texture_cache.explicit_writeback((*std::get<1>(m_rtts.m_bound_depth_stencil)), depth_address, pitch);
|
||||
|
||||
if (in_cache)
|
||||
@ -269,7 +269,7 @@ void GLGSRender::read_buffers()
|
||||
__glcheck pbo_depth.create(m_surface.width * m_surface.height * pixel_size);
|
||||
__glcheck pbo_depth.map([&](GLubyte* pixels)
|
||||
{
|
||||
u32 depth_address = rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET], rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA]);
|
||||
u32 depth_address = rsx::get_address_dma(rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET], rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA]);
|
||||
|
||||
if (m_surface.depth_format == rsx::surface_depth_format::z16)
|
||||
{
|
||||
@ -315,13 +315,13 @@ void GLGSRender::write_buffers()
|
||||
for (int i = index; i < index + count; ++i)
|
||||
{
|
||||
u32 offset = rsx::method_registers[rsx::internals::mr_color_offset[i]];
|
||||
u32 location = rsx::method_registers[rsx::internals::mr_color_dma[i]];
|
||||
u32 dma = rsx::method_registers[rsx::internals::mr_color_dma[i]];
|
||||
u32 pitch = rsx::method_registers[rsx::internals::mr_color_pitch[i]];
|
||||
|
||||
if (pitch <= 64)
|
||||
continue;
|
||||
|
||||
rsx::tiled_region color_buffer = get_tiled_address(offset, location & 0xf);
|
||||
rsx::tiled_region color_buffer = get_tiled_address_dma(offset, dma);
|
||||
u32 texaddr = (u32)((u64)color_buffer.ptr - (u64)vm::base(0));
|
||||
u32 range = pitch * height;
|
||||
|
||||
@ -370,7 +370,7 @@ void GLGSRender::write_buffers()
|
||||
return;
|
||||
|
||||
auto depth_format = rsx::internals::surface_depth_format_to_gl(m_surface.depth_format);
|
||||
u32 depth_address = rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET], rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA]);
|
||||
u32 depth_address = rsx::get_address_dma(rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET], rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA]);
|
||||
u32 range = std::get<1>(m_rtts.m_bound_depth_stencil)->width() * std::get<1>(m_rtts.m_bound_depth_stencil)->height() * 2;
|
||||
|
||||
if (m_surface.depth_format != rsx::surface_depth_format::z16) range *= 2;
|
||||
|
@ -34,6 +34,7 @@ namespace vm { using namespace ps3; }
|
||||
namespace rsx
|
||||
{
|
||||
std::function<bool(u32 addr, bool is_writing)> g_access_violation_handler;
|
||||
state_t state;
|
||||
|
||||
std::string old_shaders_cache::shaders_cache::path_to_root()
|
||||
{
|
||||
@ -97,27 +98,41 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
|
||||
u32 get_address(u32 offset, u32 location)
|
||||
u32 get_address(u32 offset, u8 location)
|
||||
{
|
||||
u32 res = 0;
|
||||
|
||||
switch (location)
|
||||
{
|
||||
case CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER:
|
||||
case CELL_GCM_LOCATION_LOCAL:
|
||||
{
|
||||
//TODO: don't use not named constants like 0xC0000000
|
||||
res = 0xC0000000 + offset;
|
||||
break;
|
||||
return rsx::state.frame_buffer.addr() + offset;
|
||||
|
||||
case CELL_GCM_LOCATION_MAIN:
|
||||
//if (fxm::get<GSRender>()->strict_ordering[offset >> 20])
|
||||
//{
|
||||
// _mm_mfence(); // probably doesn't have any effect on current implementation
|
||||
//}
|
||||
|
||||
if (u32 result = RSXIOMem.RealAddr(offset))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
throw EXCEPTION("%s(offset=0x%x, location=0x%x): RSXIO memory not mapped", __FUNCTION__, offset, location);
|
||||
}
|
||||
|
||||
case CELL_GCM_CONTEXT_DMA_MEMORY_HOST_BUFFER:
|
||||
case CELL_GCM_LOCATION_MAIN:
|
||||
throw EXCEPTION("%s(offset=0x%x, location=0x%x): Invalid location", __FUNCTION__, offset, location);
|
||||
}
|
||||
|
||||
u32 get_address_dma(u32 offset, u32 dma)
|
||||
{
|
||||
switch (dma)
|
||||
{
|
||||
res = (u32)RSXIOMem.RealAddr(offset); // TODO: Error Check?
|
||||
if (res == 0)
|
||||
case CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER:
|
||||
return rsx::state.frame_buffer.addr() + offset;
|
||||
|
||||
case CELL_GCM_CONTEXT_DMA_MEMORY_HOST_BUFFER:
|
||||
if (u32 result = RSXIOMem.RealAddr(offset))
|
||||
{
|
||||
throw EXCEPTION("GetAddress(offset=0x%x, location=0x%x): RSXIO memory not mapped", offset, location);
|
||||
return result;
|
||||
}
|
||||
|
||||
//if (fxm::get<GSRender>()->strict_ordering[offset >> 20])
|
||||
@ -125,15 +140,31 @@ namespace rsx
|
||||
// _mm_mfence(); // probably doesn't have any effect on current implementation
|
||||
//}
|
||||
|
||||
throw EXCEPTION("%s(offset=0x%x, dma=0x%x): RSXIO memory not mapped", __FUNCTION__, offset, dma);
|
||||
|
||||
case CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_REPORT:
|
||||
return rsx::state.frame_buffer.ptr(&rsx::frame_buffer_t::reports).addr() + offset;
|
||||
|
||||
case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_MAIN:
|
||||
return rsx::state.context.ptr(&rsx::context_t::reports).addr() + offset;
|
||||
|
||||
case CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_NOTIFY0:
|
||||
return rsx::state.context.ptr(&rsx::context_t::notifies).addr() + offset;
|
||||
|
||||
case CELL_GCM_CONTEXT_DMA_NOTIFY_MAIN_0:
|
||||
//TODO
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw EXCEPTION("Invalid location (offset=0x%x, location=0x%x)", offset, location);
|
||||
}
|
||||
|
||||
case CELL_GCM_CONTEXT_DMA_SEMAPHORE_RW:
|
||||
case CELL_GCM_CONTEXT_DMA_SEMAPHORE_R:
|
||||
return rsx::state.context.ptr(&rsx::context_t::semaphores).addr() + offset;
|
||||
|
||||
case CELL_GCM_CONTEXT_DMA_DEVICE_RW:
|
||||
case CELL_GCM_CONTEXT_DMA_DEVICE_R:
|
||||
return rsx::state.device.addr() + offset;
|
||||
}
|
||||
|
||||
return res;
|
||||
throw EXCEPTION("%s(offset=0x%x, dma=0x%x): Invalid dma", __FUNCTION__, offset, dma);
|
||||
}
|
||||
|
||||
u32 get_vertex_type_size_on_host(vertex_base_type type, u32 size)
|
||||
@ -377,24 +408,24 @@ namespace rsx
|
||||
|
||||
reset();
|
||||
|
||||
last_flip_time = get_system_time() - 1000000;
|
||||
rsx::state.last_flip_time = get_system_time() - 1000000;
|
||||
|
||||
scope_thread vblank("VBlank Thread", [this]()
|
||||
{
|
||||
const u64 start_time = get_system_time();
|
||||
|
||||
vblank_count = 0;
|
||||
rsx::state.vblank_count = 0;
|
||||
|
||||
// TODO: exit condition
|
||||
while (!Emu.IsStopped())
|
||||
{
|
||||
if (get_system_time() - start_time > vblank_count * 1000000 / 60)
|
||||
if (get_system_time() - start_time > rsx::state.vblank_count * 1000000 / 60)
|
||||
{
|
||||
vblank_count++;
|
||||
rsx::state.vblank_count++;
|
||||
|
||||
if (vblank_handler)
|
||||
if (rsx::state.vblank_handler)
|
||||
{
|
||||
Emu.GetCallbackManager().Async([func = vblank_handler](PPUThread& ppu)
|
||||
Emu.GetCallbackManager().Async([func = rsx::state.vblank_handler](PPUThread& ppu)
|
||||
{
|
||||
func(ppu, 1);
|
||||
});
|
||||
@ -403,17 +434,19 @@ namespace rsx
|
||||
continue;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(1ms); // hack
|
||||
std::this_thread::yield();
|
||||
}
|
||||
});
|
||||
|
||||
auto &ctrl = state.context->control;
|
||||
|
||||
// TODO: exit condition
|
||||
while (true)
|
||||
{
|
||||
CHECK_EMU_STATUS;
|
||||
|
||||
const u32 get = ctrl->get;
|
||||
const u32 put = ctrl->put;
|
||||
const u32 get = ctrl.get;
|
||||
const u32 put = ctrl.put;
|
||||
|
||||
if (put == get || !Emu.IsRunning())
|
||||
{
|
||||
@ -428,7 +461,7 @@ namespace rsx
|
||||
{
|
||||
u32 offs = cmd & 0x1fffffff;
|
||||
//LOG_WARNING(RSX, "rsx jump(0x%x) #addr=0x%x, cmd=0x%x, get=0x%x, put=0x%x", offs, m_ioAddress + get, cmd, get, put);
|
||||
ctrl->get = offs;
|
||||
ctrl.get = offs;
|
||||
continue;
|
||||
}
|
||||
if (cmd & CELL_GCM_METHOD_FLAG_CALL)
|
||||
@ -436,7 +469,7 @@ namespace rsx
|
||||
m_call_stack.push(get + 4);
|
||||
u32 offs = cmd & ~3;
|
||||
//LOG_WARNING(RSX, "rsx call(0x%x) #0x%x - 0x%x", offs, cmd, get);
|
||||
ctrl->get = offs;
|
||||
ctrl.get = offs;
|
||||
continue;
|
||||
}
|
||||
if (cmd == CELL_GCM_METHOD_FLAG_RETURN)
|
||||
@ -444,13 +477,13 @@ namespace rsx
|
||||
u32 get = m_call_stack.top();
|
||||
m_call_stack.pop();
|
||||
//LOG_WARNING(RSX, "rsx return(0x%x)", get);
|
||||
ctrl->get = get;
|
||||
ctrl.get = get;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cmd == 0) //nop
|
||||
{
|
||||
ctrl->get = get + 4;
|
||||
ctrl.get = get + 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -483,7 +516,7 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
|
||||
ctrl->get = get + (count + 1) * 4;
|
||||
ctrl.get = get + (count + 1) * 4;
|
||||
}
|
||||
}
|
||||
|
||||
@ -576,7 +609,7 @@ namespace rsx
|
||||
{
|
||||
if (m_internal_tasks.empty())
|
||||
{
|
||||
std::this_thread::sleep_for(1ms);
|
||||
std::this_thread::yield();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -656,10 +689,10 @@ namespace rsx
|
||||
};
|
||||
return
|
||||
{
|
||||
rsx::get_address(offset_color[0], context_dma_color[0]),
|
||||
rsx::get_address(offset_color[1], context_dma_color[1]),
|
||||
rsx::get_address(offset_color[2], context_dma_color[2]),
|
||||
rsx::get_address(offset_color[3], context_dma_color[3]),
|
||||
context_dma_color[0] ? rsx::get_address_dma(offset_color[0], context_dma_color[0]) : 0,
|
||||
context_dma_color[1] ? rsx::get_address_dma(offset_color[1], context_dma_color[1]) : 0,
|
||||
context_dma_color[2] ? rsx::get_address_dma(offset_color[2], context_dma_color[2]) : 0,
|
||||
context_dma_color[2] ? rsx::get_address_dma(offset_color[3], context_dma_color[3]) : 0,
|
||||
};
|
||||
}
|
||||
|
||||
@ -667,7 +700,7 @@ namespace rsx
|
||||
{
|
||||
u32 m_context_dma_z = rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA];
|
||||
u32 offset_zeta = rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET];
|
||||
return rsx::get_address(offset_zeta, m_context_dma_z);
|
||||
return offset_zeta ? rsx::get_address_dma(offset_zeta, m_context_dma_z) : 0;
|
||||
}
|
||||
|
||||
RSXVertexProgram thread::get_current_vertex_program() const
|
||||
@ -923,10 +956,23 @@ namespace rsx
|
||||
|
||||
method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE] = 0xffffffff;
|
||||
|
||||
method_registers[NV4097_SET_CONTEXT_DMA_REPORT] = CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_REPORT;
|
||||
rsx::method_registers[NV4097_SET_TWO_SIDE_LIGHT_EN] = true;
|
||||
rsx::method_registers[NV4097_SET_ALPHA_FUNC] = CELL_GCM_ALWAYS;
|
||||
|
||||
method_registers[NV4097_SET_CONTEXT_DMA_REPORT] = CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_REPORT;
|
||||
method_registers[NV406E_SET_CONTEXT_DMA_SEMAPHORE] = CELL_GCM_CONTEXT_DMA_SEMAPHORE_RW;
|
||||
|
||||
method_registers[NV3062_SET_CONTEXT_DMA_IMAGE_DESTIN] = CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER;
|
||||
method_registers[NV309E_SET_CONTEXT_DMA_IMAGE] = CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER;
|
||||
method_registers[NV0039_SET_CONTEXT_DMA_BUFFER_IN] = CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER;
|
||||
method_registers[NV0039_SET_CONTEXT_DMA_BUFFER_OUT] = CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER;
|
||||
|
||||
method_registers[NV4097_SET_CONTEXT_DMA_COLOR_A] = CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER;
|
||||
method_registers[NV4097_SET_CONTEXT_DMA_COLOR_B] = CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER;
|
||||
method_registers[NV4097_SET_CONTEXT_DMA_COLOR_C] = CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER;
|
||||
method_registers[NV4097_SET_CONTEXT_DMA_COLOR_D] = CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER;
|
||||
method_registers[NV4097_SET_CONTEXT_DMA_ZETA] = CELL_GCM_CONTEXT_DMA_MEMORY_FRAME_BUFFER;
|
||||
|
||||
// Reset vertex attrib array
|
||||
for (int i = 0; i < limits::vertex_count; i++)
|
||||
{
|
||||
@ -945,14 +991,8 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
|
||||
void thread::init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress)
|
||||
void thread::init()
|
||||
{
|
||||
ctrl = vm::_ptr<CellGcmControl>(ctrlAddress);
|
||||
this->ioAddress = ioAddress;
|
||||
this->ioSize = ioSize;
|
||||
local_mem_addr = localAddress;
|
||||
flip_status = 0;
|
||||
|
||||
m_used_gcm_commands.clear();
|
||||
|
||||
on_init_rsx();
|
||||
@ -961,7 +1001,7 @@ namespace rsx
|
||||
|
||||
GcmTileInfo *thread::find_tile(u32 offset, u32 location)
|
||||
{
|
||||
for (GcmTileInfo &tile : tiles)
|
||||
for (GcmTileInfo &tile : state.unpacked_tiles)
|
||||
{
|
||||
if (!tile.binded || tile.location != location)
|
||||
{
|
||||
@ -977,7 +1017,23 @@ namespace rsx
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
tiled_region thread::get_tiled_address(u32 offset, u32 location)
|
||||
tiled_region thread::get_tiled_address_dma(u32 offset, u32 dma)
|
||||
{
|
||||
u32 address = get_address_dma(offset, dma);
|
||||
|
||||
GcmTileInfo *tile = find_tile(offset, dma & 1);
|
||||
u32 base = 0;
|
||||
|
||||
if (tile)
|
||||
{
|
||||
base = offset - tile->offset;
|
||||
address = get_address_dma(tile->offset, dma);
|
||||
}
|
||||
|
||||
return{ address, base, tile, (u8*)vm::base(address) };
|
||||
}
|
||||
|
||||
tiled_region thread::get_tiled_address(u32 offset, u8 location)
|
||||
{
|
||||
u32 address = get_address(offset, location);
|
||||
|
||||
|
@ -87,6 +87,113 @@ namespace rsx
|
||||
};
|
||||
}
|
||||
|
||||
struct semaphore_t
|
||||
{
|
||||
be_t<u32> value;
|
||||
be_t<u32> padding;
|
||||
be_t<u64> timestamp;
|
||||
};
|
||||
|
||||
struct notify_t
|
||||
{
|
||||
be_t<u64> timestamp;
|
||||
be_t<u64> zero;
|
||||
};
|
||||
|
||||
union device_t
|
||||
{
|
||||
u8 raw[0x1000];
|
||||
};
|
||||
|
||||
union control_t;
|
||||
|
||||
using callback_t = s32(u32, u32);
|
||||
|
||||
union control_t
|
||||
{
|
||||
struct
|
||||
{
|
||||
vm::ps3::bptr<u32> begin;
|
||||
vm::ps3::bptr<u32> end;
|
||||
vm::ps3::bptr<u32> current;
|
||||
vm::ps3::bpptr<callback_t> callback;
|
||||
|
||||
atomic_be_t<u32> put;
|
||||
atomic_be_t<u32> get;
|
||||
atomic_be_t<u32> ref;
|
||||
};
|
||||
|
||||
//for gcm capability
|
||||
struct
|
||||
{
|
||||
CellGcmContextData data;
|
||||
CellGcmControl control;
|
||||
};
|
||||
|
||||
u8 raw[0x1000];
|
||||
};
|
||||
|
||||
union driver_info_t
|
||||
{
|
||||
struct
|
||||
{
|
||||
be_t<u32> version_driver;
|
||||
be_t<u32> version_gpu;
|
||||
be_t<u32> memory_size;
|
||||
be_t<u32> hardware_channel;
|
||||
be_t<u32> nvcore_frequency;
|
||||
be_t<u32> memory_frequency;
|
||||
};
|
||||
|
||||
u8 raw[0x4000];
|
||||
};
|
||||
|
||||
struct context_t
|
||||
{
|
||||
control_t control;
|
||||
driver_info_t driver_info;
|
||||
semaphore_t semaphores[0x100];
|
||||
notify_t notifies[0x40];
|
||||
CellGcmReportData reports[0x800];
|
||||
};
|
||||
|
||||
struct frame_buffer_t
|
||||
{
|
||||
CellGcmReportData reports[0x100000];
|
||||
};
|
||||
|
||||
//TODO: separate gcm and rsx data
|
||||
struct state_t
|
||||
{
|
||||
vm::ps3::ptr<device_t> device;
|
||||
vm::ps3::ptr<context_t> context; //TODO: support for multiply contexts
|
||||
|
||||
vm::ps3::ptr<void(u32)> flip_handler = vm::null;
|
||||
vm::ps3::ptr<void(u32)> user_handler = vm::null;
|
||||
vm::ps3::ptr<void(u32)> vblank_handler = vm::null;
|
||||
|
||||
u64 last_flip_time;
|
||||
u64 vblank_count;
|
||||
u32 flip_status;
|
||||
u32 flip_mode;
|
||||
u32 debug_level;
|
||||
u32 io_size;
|
||||
|
||||
vm::ps3::ptr<frame_buffer_t> frame_buffer;
|
||||
u32 frame_buffer_size;
|
||||
|
||||
vm::ps3::ptr<CellGcmTileInfo> tiles;
|
||||
vm::ps3::ptr<CellGcmZcullInfo> zculls;
|
||||
vm::ps3::ptr<CellGcmDisplayInfo> display_buffers;
|
||||
u32 display_buffers_count;
|
||||
u32 current_display_buffer;
|
||||
|
||||
GcmTileInfo unpacked_tiles[limits::tiles_count];
|
||||
GcmZcullInfo unpacked_zculls[limits::zculls_count];
|
||||
};
|
||||
|
||||
extern state_t state;
|
||||
|
||||
namespace old_shaders_cache
|
||||
{
|
||||
struct decompiled_shader
|
||||
@ -139,7 +246,8 @@ namespace rsx
|
||||
|
||||
u32 get_vertex_type_size_on_host(vertex_base_type type, u32 size);
|
||||
|
||||
u32 get_address(u32 offset, u32 location);
|
||||
u32 get_address(u32 offset, u8 location);
|
||||
u32 get_address_dma(u32 offset, u32 dma);
|
||||
|
||||
struct tiled_region
|
||||
{
|
||||
@ -212,13 +320,8 @@ namespace rsx
|
||||
old_shaders_cache::shaders_cache shaders_cache;
|
||||
rsx::programs_cache programs_cache;
|
||||
|
||||
CellGcmControl* ctrl = nullptr;
|
||||
|
||||
Timer timer_sync;
|
||||
|
||||
GcmTileInfo tiles[limits::tiles_count];
|
||||
GcmZcullInfo zculls[limits::zculls_count];
|
||||
|
||||
rsx::texture textures[limits::textures_count];
|
||||
rsx::vertex_texture vertex_textures[limits::vertex_textures_count];
|
||||
|
||||
@ -260,23 +363,11 @@ namespace rsx
|
||||
void capture_frame(const std::string &name);
|
||||
|
||||
public:
|
||||
u32 ioAddress, ioSize;
|
||||
int flip_status;
|
||||
int flip_mode;
|
||||
int debug_level;
|
||||
int frequency_mode;
|
||||
|
||||
u32 tiles_addr;
|
||||
u32 zculls_addr;
|
||||
vm::ps3::ptr<CellGcmDisplayInfo> gcm_buffers = vm::null;
|
||||
u32 gcm_buffers_count;
|
||||
u32 gcm_current_buffer;
|
||||
u32 ctxt_addr;
|
||||
u32 label_addr;
|
||||
rsx::draw_command draw_command;
|
||||
primitive_type draw_mode;
|
||||
|
||||
u32 local_mem_addr, main_mem_addr;
|
||||
bool strict_ordering[0x1000];
|
||||
|
||||
bool draw_inline_vertex_array;
|
||||
@ -295,13 +386,6 @@ namespace rsx
|
||||
u32 draw_array_first;
|
||||
double fps_limit = 59.94;
|
||||
|
||||
public:
|
||||
u64 last_flip_time;
|
||||
vm::ps3::ptr<void(u32)> flip_handler = vm::null;
|
||||
vm::ps3::ptr<void(u32)> user_handler = vm::null;
|
||||
vm::ps3::ptr<void(u32)> vblank_handler = vm::null;
|
||||
u64 vblank_count;
|
||||
|
||||
public:
|
||||
std::set<u32> m_used_gcm_commands;
|
||||
|
||||
@ -388,9 +472,10 @@ namespace rsx
|
||||
struct raw_program get_raw_program() const;
|
||||
public:
|
||||
void reset();
|
||||
void init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress);
|
||||
void init();
|
||||
|
||||
tiled_region get_tiled_address(u32 offset, u32 location);
|
||||
tiled_region get_tiled_address(u32 offset, u8 location);
|
||||
tiled_region get_tiled_address_dma(u32 offset, u32 dma);
|
||||
GcmTileInfo *find_tile(u32 offset, u32 location);
|
||||
|
||||
u32 ReadIO32(u32 addr);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -32,27 +32,31 @@ namespace rsx
|
||||
|
||||
namespace nv406e
|
||||
{
|
||||
force_inline void set_reference(thread* rsx, u32 arg)
|
||||
force_inline void set_reference(u32 arg)
|
||||
{
|
||||
rsx->ctrl->ref.exchange(arg);
|
||||
rsx::state.context->control.ref.exchange(arg);
|
||||
}
|
||||
|
||||
force_inline void semaphore_acquire(thread* rsx, u32 arg)
|
||||
{
|
||||
//TODO: dma
|
||||
while (vm::ps3::read32(rsx->label_addr + method_registers[NV406E_SEMAPHORE_OFFSET]) != arg)
|
||||
vm::ps3::ptr<rsx::semaphore_t> semaphore = vm::cast(get_address_dma(method_registers[NV406E_SEMAPHORE_OFFSET], method_registers[NV406E_SET_CONTEXT_DMA_SEMAPHORE]));
|
||||
|
||||
while (semaphore->value != arg)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
std::this_thread::sleep_for(1ms);
|
||||
std::this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
force_inline void semaphore_release(thread* rsx, u32 arg)
|
||||
{
|
||||
//TODO: dma
|
||||
vm::ps3::write32(rsx->label_addr + method_registers[NV406E_SEMAPHORE_OFFSET], arg);
|
||||
vm::ps3::ptr<rsx::semaphore_t> semaphore = vm::cast(get_address_dma(method_registers[NV406E_SEMAPHORE_OFFSET], method_registers[NV406E_SET_CONTEXT_DMA_SEMAPHORE]));
|
||||
semaphore->timestamp = rsx->timestamp();
|
||||
semaphore->value = arg;
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,15 +64,16 @@ namespace rsx
|
||||
{
|
||||
force_inline void texture_read_semaphore_release(thread* rsx, u32 arg)
|
||||
{
|
||||
//TODO: dma
|
||||
vm::ps3::write32(rsx->label_addr + method_registers[NV4097_SET_SEMAPHORE_OFFSET], arg);
|
||||
rsx::semaphore_t& result = rsx::state.context->semaphores[method_registers[NV4097_SET_SEMAPHORE_OFFSET] / sizeof(CellGcmReportData)];
|
||||
result.timestamp = rsx->timestamp();
|
||||
result.value = arg;
|
||||
}
|
||||
|
||||
force_inline void back_end_write_semaphore_release(thread* rsx, u32 arg)
|
||||
{
|
||||
//TODO: dma
|
||||
vm::ps3::write32(rsx->label_addr + method_registers[NV4097_SET_SEMAPHORE_OFFSET],
|
||||
(arg & 0xff00ff00) | ((arg & 0xff) << 16) | ((arg >> 16) & 0xff));
|
||||
rsx::semaphore_t& result = rsx::state.context->semaphores[method_registers[NV4097_SET_SEMAPHORE_OFFSET] / sizeof(CellGcmReportData)];
|
||||
result.timestamp = rsx->timestamp();
|
||||
result.value = (arg & 0xff00ff00) | ((arg & 0xff) << 16) | ((arg >> 16) & 0xff);
|
||||
}
|
||||
|
||||
//fire only when all data passed to rsx cmd buffer
|
||||
@ -274,18 +279,8 @@ namespace rsx
|
||||
u8 type = arg >> 24;
|
||||
u32 offset = arg & 0xffffff;
|
||||
u32 report_dma = method_registers[NV4097_SET_CONTEXT_DMA_REPORT];
|
||||
u32 location;
|
||||
|
||||
switch (report_dma)
|
||||
{
|
||||
case CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_REPORT: location = CELL_GCM_LOCATION_LOCAL; break;
|
||||
case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_MAIN: location = CELL_GCM_LOCATION_MAIN; break;
|
||||
default:
|
||||
LOG_WARNING(RSX, "nv4097::get_report: bad report dma: 0x%x", report_dma);
|
||||
return;
|
||||
}
|
||||
|
||||
vm::ps3::ptr<CellGcmReportData> result = vm::cast(get_address(offset, location));
|
||||
vm::ps3::ptr<CellGcmReportData> result = vm::cast(get_address_dma(offset, report_dma));
|
||||
|
||||
result->timer = rsx->timestamp();
|
||||
|
||||
@ -356,7 +351,7 @@ namespace rsx
|
||||
LOG_ERROR(RSX, "%s: y is not null (0x%x)", __FUNCTION__, y);
|
||||
}
|
||||
|
||||
u32 address = get_address(method_registers[NV3062_SET_OFFSET_DESTIN] + (x << 2) + index * 4, method_registers[NV3062_SET_CONTEXT_DMA_IMAGE_DESTIN]);
|
||||
u32 address = get_address_dma(method_registers[NV3062_SET_OFFSET_DESTIN] + (x << 2) + index * 4, method_registers[NV3062_SET_CONTEXT_DMA_IMAGE_DESTIN]);
|
||||
vm::ps3::write32(address, arg);
|
||||
}
|
||||
};
|
||||
@ -438,14 +433,14 @@ namespace rsx
|
||||
//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)
|
||||
{
|
||||
u32 begin = rsx->gcm_buffers[i].offset;
|
||||
u32 begin = state.display_buffers[i].offset;
|
||||
|
||||
if (dst_offset < begin || !begin)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (rsx->gcm_buffers[i].width < 720 || rsx->gcm_buffers[i].height < 480)
|
||||
if (state.display_buffers[i].width < 720 || state.display_buffers[i].height < 480)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -455,7 +450,7 @@ namespace rsx
|
||||
return;
|
||||
}
|
||||
|
||||
u32 end = begin + rsx->gcm_buffers[i].height * rsx->gcm_buffers[i].pitch;
|
||||
u32 end = begin + state.display_buffers[i].height * state.display_buffers[i].pitch;
|
||||
|
||||
if (dst_offset < end)
|
||||
{
|
||||
@ -470,8 +465,8 @@ namespace rsx
|
||||
u32 in_offset = u32(in_x * in_bpp + in_pitch * in_y);
|
||||
u32 out_offset = out_x * out_bpp + out_pitch * out_y;
|
||||
|
||||
tiled_region src_region = rsx->get_tiled_address(src_offset + in_offset, src_dma & 0xf);//get_address(src_offset, src_dma);
|
||||
u32 dst_address = get_address(dst_offset + out_offset, dst_dma);
|
||||
tiled_region src_region = rsx->get_tiled_address_dma(src_offset + in_offset, src_dma);
|
||||
u32 dst_address = get_address_dma(dst_offset + out_offset, dst_dma);
|
||||
|
||||
if (out_pitch == 0)
|
||||
{
|
||||
@ -706,8 +701,8 @@ namespace rsx
|
||||
u32 dst_offset = method_registers[NV0039_OFFSET_OUT];
|
||||
u32 dst_dma = method_registers[NV0039_SET_CONTEXT_DMA_BUFFER_OUT];
|
||||
|
||||
u8 *dst = (u8*)vm::base(get_address(dst_offset, dst_dma));
|
||||
const u8 *src = (u8*)vm::base(get_address(src_offset, src_dma));
|
||||
u8 *dst = (u8*)vm::base(get_address_dma(dst_offset, dst_dma));
|
||||
const u8 *src = (u8*)vm::base(get_address_dma(src_offset, src_dma));
|
||||
|
||||
if (in_pitch == out_pitch && out_pitch == line_length)
|
||||
{
|
||||
@ -739,19 +734,18 @@ namespace rsx
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
rsx->gcm_current_buffer = arg;
|
||||
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();
|
||||
|
||||
rsx->last_flip_time = get_system_time() - 1000000;
|
||||
rsx->gcm_current_buffer = arg;
|
||||
rsx->flip_status = 0;
|
||||
state.last_flip_time = get_system_time() - 1000000;
|
||||
state.current_display_buffer = arg;
|
||||
state.flip_status = 0;
|
||||
|
||||
if (rsx->flip_handler)
|
||||
if (state.flip_handler)
|
||||
{
|
||||
Emu.GetCallbackManager().Async([func = rsx->flip_handler](PPUThread& ppu)
|
||||
Emu.GetCallbackManager().Async([func = state.flip_handler](PPUThread& ppu)
|
||||
{
|
||||
func(ppu, 1);
|
||||
});
|
||||
@ -769,9 +763,9 @@ namespace rsx
|
||||
|
||||
void user_command(thread* rsx, u32 arg)
|
||||
{
|
||||
if (rsx->user_handler)
|
||||
if (state.user_handler)
|
||||
{
|
||||
Emu.GetCallbackManager().Async([func = rsx->user_handler, arg](PPUThread& ppu)
|
||||
Emu.GetCallbackManager().Async([func = state.user_handler, arg](PPUThread& ppu)
|
||||
{
|
||||
func(ppu, arg);
|
||||
});
|
||||
|
@ -344,7 +344,7 @@ void RSXDebugger::OnClickBuffer(wxMouseEvent& event)
|
||||
return;
|
||||
}
|
||||
|
||||
const auto buffers = render->gcm_buffers;
|
||||
const auto buffers = rsx::state.display_buffers;
|
||||
if(!buffers)
|
||||
return;
|
||||
|
||||
@ -587,7 +587,7 @@ void RSXDebugger::GoToGet(wxCommandEvent& event)
|
||||
if (const auto render = fxm::get<GSRender>())
|
||||
{
|
||||
u32 realAddr;
|
||||
if (RSXIOMem.getRealAddr(render->ctrl->get.load(), realAddr))
|
||||
if (RSXIOMem.getRealAddr(rsx::state.context->control.get.load(), realAddr))
|
||||
{
|
||||
m_addr = realAddr;
|
||||
t_addr->SetValue(wxString::Format("%08x", m_addr));
|
||||
@ -602,7 +602,7 @@ void RSXDebugger::GoToPut(wxCommandEvent& event)
|
||||
if (const auto render = fxm::get<GSRender>())
|
||||
{
|
||||
u32 realAddr;
|
||||
if (RSXIOMem.getRealAddr(render->ctrl->put.load(), realAddr))
|
||||
if (RSXIOMem.getRealAddr(rsx::state.context->control.put.load(), realAddr))
|
||||
{
|
||||
m_addr = realAddr;
|
||||
t_addr->SetValue(wxString::Format("%08x", m_addr));
|
||||
@ -678,15 +678,15 @@ void RSXDebugger::GetBuffers()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!vm::check_addr(rsx::state.display_buffers.addr()))
|
||||
return;
|
||||
|
||||
// Draw Buffers
|
||||
// TODO: Currently it only supports color buffers
|
||||
for (u32 bufferId=0; bufferId < render->gcm_buffers_count; bufferId++)
|
||||
for (u32 bufferId=0; bufferId < rsx::state.display_buffers_count; bufferId++)
|
||||
{
|
||||
if(!vm::check_addr(render->gcm_buffers.addr()))
|
||||
continue;
|
||||
|
||||
auto buffers = render->gcm_buffers;
|
||||
u32 RSXbuffer_addr = render->local_mem_addr + buffers[bufferId].offset;
|
||||
auto &buffers = rsx::state.display_buffers;
|
||||
u32 RSXbuffer_addr = rsx::state.frame_buffer.addr() + buffers[bufferId].offset;
|
||||
|
||||
if(!vm::check_addr(RSXbuffer_addr))
|
||||
continue;
|
||||
|
Loading…
x
Reference in New Issue
Block a user