From ba7397952d00e020dd81d4ea9cbc9c4a91251e25 Mon Sep 17 00:00:00 2001 From: disjtqz Date: Wed, 11 Oct 2023 12:45:21 -0400 Subject: [PATCH] implement missing packet_disassembler code --- src/xenia/gpu/packet_disassembler.cc | 300 +++++++++++++++++++++++---- 1 file changed, 257 insertions(+), 43 deletions(-) diff --git a/src/xenia/gpu/packet_disassembler.cc b/src/xenia/gpu/packet_disassembler.cc index 6bb1a23d9..90eebf9db 100644 --- a/src/xenia/gpu/packet_disassembler.cc +++ b/src/xenia/gpu/packet_disassembler.cc @@ -57,6 +57,7 @@ bool PacketDisassembler::DisasmPacketType0(const uint8_t* base_ptr, uint32_t base_index = (packet & 0x7FFF); uint32_t write_one_reg = (packet >> 15) & 0x1; + out_info->actions.reserve(count); for (uint32_t m = 0; m < count; m++) { uint32_t reg_data = xe::load_and_swap(ptr); uint32_t target_index = write_one_reg ? base_index : base_index + m; @@ -77,7 +78,7 @@ bool PacketDisassembler::DisasmPacketType1(const uint8_t* base_ptr, out_info->count = 1 + 2; auto ptr = base_ptr + 4; - + out_info->actions.reserve(2); uint32_t reg_index_1 = packet & 0x7FF; uint32_t reg_index_2 = (packet >> 11) & 0x7FF; uint32_t reg_data_1 = xe::load_and_swap(ptr); @@ -118,12 +119,19 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, out_info->predicated = true; } + using Type = PacketAction::Type; bool result = true; + + auto& out_actions = out_info->actions; + out_actions.reserve(1); switch (opcode) { case PM4_ME_INIT: { // initialize CP's micro-engine static const PacketTypeInfo op_info = {PacketCategory::kGeneric, "PM4_ME_INIT"}; + + out_actions.emplace_back(PacketAction::MeInit((uint32_t*)ptr, count)); + out_info->type_info = &op_info; break; } @@ -140,12 +148,11 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, static const PacketTypeInfo op_info = {PacketCategory::kGeneric, "PM4_INTERRUPT"}; out_info->type_info = &op_info; - uint32_t cpu_mask = xe::load_and_swap(ptr + 0); - for (int n = 0; n < 6; n++) { - if (cpu_mask & (1 << n)) { - // graphics_system_->DispatchInterruptCallback(1, n); - } - } + + PacketAction intaction; + intaction.type = Type::kGenInterrupt; + intaction.gen_interrupt.cpu_mask = xe::load_and_swap(ptr + 0); + out_actions.emplace_back(std::move(intaction)); break; } case PM4_XE_SWAP: { @@ -156,7 +163,13 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, static const PacketTypeInfo op_info = {PacketCategory::kSwap, "PM4_XE_SWAP"}; out_info->type_info = &op_info; - uint32_t frontbuffer_ptr = xe::load_and_swap(ptr + 0); + + PacketAction xsa; + xsa.type = Type::kXeSwap; + xsa.xe_swap.frontbuffer_ptr = xe::load_and_swap(ptr + 0); + + out_actions.emplace_back(std::move(xsa)); + break; } case PM4_INDIRECT_BUFFER: @@ -165,8 +178,13 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, static const PacketTypeInfo op_info = {PacketCategory::kGeneric, "PM4_INDIRECT_BUFFER"}; out_info->type_info = &op_info; - uint32_t list_ptr = xe::load_and_swap(ptr + 0); - uint32_t list_length = xe::load_and_swap(ptr + 4); + + PacketAction iba; + iba.type = Type::kIndirBuffer; + iba.indir_buffer.list_ptr = xe::load_and_swap(ptr); + iba.indir_buffer.list_length = xe::load_and_swap(ptr + 4); + out_actions.emplace_back(std::move(iba)); + break; } case PM4_WAIT_REG_MEM: { @@ -174,11 +192,18 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, static const PacketTypeInfo op_info = {PacketCategory::kGeneric, "PM4_WAIT_REG_MEM"}; out_info->type_info = &op_info; - uint32_t wait_info = xe::load_and_swap(ptr + 0); - uint32_t poll_reg_addr = xe::load_and_swap(ptr + 4); - uint32_t ref = xe::load_and_swap(ptr + 8); - uint32_t mask = xe::load_and_swap(ptr + 12); - uint32_t wait = xe::load_and_swap(ptr + 16); + + PacketAction wait_action; + wait_action.type = PacketAction::Type::kWaitRegMem; + auto& wrm = wait_action.wait_reg_mem; + wrm.wait_info = xe::load_and_swap(ptr + 0); + wrm.poll_reg_addr = xe::load_and_swap(ptr + 4); + wrm.ref = xe::load_and_swap(ptr + 8); + wrm.mask = xe::load_and_swap(ptr + 12); + wrm.wait = xe::load_and_swap(ptr + 16); + + out_actions.emplace_back(std::move(wait_action)); + break; } case PM4_REG_RMW: { @@ -187,9 +212,17 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, static const PacketTypeInfo op_info = {PacketCategory::kGeneric, "PM4_REG_RMW"}; out_info->type_info = &op_info; + PacketAction rmw_action; + rmw_action.type = PacketAction::Type::kRegRmw; + auto& rmw = rmw_action.reg_rmw; + uint32_t rmw_info = xe::load_and_swap(ptr + 0); - uint32_t and_mask = xe::load_and_swap(ptr + 4); - uint32_t or_mask = xe::load_and_swap(ptr + 8); + + rmw.rmw_info = rmw_info; + + rmw.and_mask = xe::load_and_swap(ptr + 4); + rmw.or_mask = xe::load_and_swap(ptr + 8); + out_actions.emplace_back(std::move(rmw_action)); break; } case PM4_COND_WRITE: { @@ -197,12 +230,19 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, static const PacketTypeInfo op_info = {PacketCategory::kGeneric, "PM4_COND_WRITE"}; out_info->type_info = &op_info; - uint32_t wait_info = xe::load_and_swap(ptr + 0); - uint32_t poll_reg_addr = xe::load_and_swap(ptr + 4); - uint32_t ref = xe::load_and_swap(ptr + 8); - uint32_t mask = xe::load_and_swap(ptr + 12); - uint32_t write_reg_addr = xe::load_and_swap(ptr + 16); - uint32_t write_data = xe::load_and_swap(ptr + 20); + PacketAction cwr_action; + cwr_action.type = PacketAction::Type::kCondWrite; + + auto& cwr = cwr_action.cond_write; + + cwr.wait_info = xe::load_and_swap(ptr + 0); + cwr.poll_reg_addr = xe::load_and_swap(ptr + 4); + cwr.ref = xe::load_and_swap(ptr + 8); + cwr.mask = xe::load_and_swap(ptr + 12); + cwr.write_reg_addr = xe::load_and_swap(ptr + 16); + cwr.write_data = xe::load_and_swap(ptr + 20); + + out_actions.emplace_back(std::move(cwr_action)); break; } case PM4_EVENT_WRITE: { @@ -210,7 +250,12 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, static const PacketTypeInfo op_info = {PacketCategory::kGeneric, "PM4_EVENT_WRITE"}; out_info->type_info = &op_info; - uint32_t initiator = xe::load_and_swap(ptr + 0); + PacketAction evw_action; + evw_action.type = Type::kEventWrite; + evw_action.event_write.initiator = xe::load_and_swap(ptr + 0); + + out_actions.emplace_back(std::move(evw_action)); + break; } case PM4_EVENT_WRITE_SHD: { @@ -218,9 +263,15 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, static const PacketTypeInfo op_info = {PacketCategory::kGeneric, "PM4_EVENT_WRITE_SHD"}; out_info->type_info = &op_info; - uint32_t initiator = xe::load_and_swap(ptr + 0); - uint32_t address = xe::load_and_swap(ptr + 4); - uint32_t value = xe::load_and_swap(ptr + 8); + PacketAction evws_action; + evws_action.type = Type::kEventWriteSHD; + auto& evws = evws_action.event_write_shd; + + evws.initiator = xe::load_and_swap(ptr + 0); + evws.address = xe::load_and_swap(ptr + 4); + evws.value = xe::load_and_swap(ptr + 8); + + out_actions.emplace_back(std::move(evws_action)); break; } case PM4_EVENT_WRITE_EXT: { @@ -228,8 +279,17 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, static const PacketTypeInfo op_info = {PacketCategory::kGeneric, "PM4_EVENT_WRITE_EXT"}; out_info->type_info = &op_info; + + PacketAction eve_action; + eve_action.type = Type::kEventWriteExt; + auto& eve = eve_action.event_write_ext; uint32_t unk0 = xe::load_and_swap(ptr + 0); uint32_t unk1 = xe::load_and_swap(ptr + 4); + + eve.unk0 = unk0; + eve.unk1 = unk1; + out_actions.emplace_back(std::move(eve_action)); + break; } case PM4_DRAW_INDX: { @@ -243,6 +303,16 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, uint32_t index_count = dword1 >> 16; auto prim_type = static_cast(dword1 & 0x3F); uint32_t src_sel = (dword1 >> 6) & 0x3; + + PacketAction di_action; + di_action.type = Type::kDrawIndx; + + auto& di = di_action.draw_indx; + di.dword0 = dword0; + di.dword1 = dword1; + di.index_count = index_count; + di.prim_type = prim_type; + di.src_sel = src_sel; if (src_sel == 0x0) { // Indexed draw. uint32_t guest_base = xe::load_and_swap(ptr + 8); @@ -251,12 +321,18 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, index_size &= 0x00FFFFFF; bool index_32bit = (dword1 >> 11) & 0x1; index_size *= index_32bit ? 4 : 2; + di.index_size = index_size; + di.guest_base = guest_base; + di.endianness = endianness; + } else if (src_sel == 0x2) { // Auto draw. } else { // Unknown source select. assert_always(); } + out_actions.emplace_back(std::move(di_action)); + break; } case PM4_DRAW_INDX_2: { @@ -272,6 +348,24 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, bool index_32bit = (dword0 >> 11) & 0x1; uint32_t indices_size = index_count * (index_32bit ? 4 : 2); auto index_ptr = ptr + 4; + + PacketAction di2_action; + di2_action.type = Type::kDrawIndx2; + di2_action.words.reserve(index_count); + auto& di2 = di2_action.draw_indx2; + + di2.dword0 = dword0; + di2.index_count = index_count; + di2.indices_size = indices_size; + di2.prim_type = prim_type; + di2.src_sel = src_sel; + + if (index_32bit) { + di2_action.InjectBeWords((uint32_t*)index_ptr, index_count); + } else { + di2_action.InjectBeHalfwordsAsWords((uint16_t*)index_ptr, index_count); + } + out_actions.emplace_back(std::move(di2_action)); break; } case PM4_SET_CONSTANT: { @@ -305,10 +399,10 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, result = false; break; } + out_actions.reserve(count - 1); for (uint32_t n = 0; n < count - 1; n++, index++) { uint32_t data = xe::load_and_swap(ptr + 4 + n * 4); - out_info->actions.emplace_back( - PacketAction::RegisterWrite(index, data)); + out_actions.emplace_back(PacketAction::RegisterWrite(index, data)); } break; } @@ -318,10 +412,12 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, out_info->type_info = &op_info; uint32_t offset_type = xe::load_and_swap(ptr + 0); uint32_t index = offset_type & 0xFFFF; + + out_actions.reserve(count - 1); + for (uint32_t n = 0; n < count - 1; n++, index++) { uint32_t data = xe::load_and_swap(ptr + 4 + n * 4); - out_info->actions.emplace_back( - PacketAction::RegisterWrite(index, data)); + out_actions.emplace_back(PacketAction::RegisterWrite(index, data)); } return true; break; @@ -358,12 +454,13 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, assert_always(); return true; } + out_actions.reserve(size_dwords); + for (uint32_t n = 0; n < size_dwords; n++, index++) { // Hrm, ? // xe::load_and_swap(membase_ + GpuToCpu(address + n * 4)); uint32_t data = 0xDEADBEEF; - out_info->actions.emplace_back( - PacketAction::RegisterWrite(index, data)); + out_actions.emplace_back(PacketAction::RegisterWrite(index, data)); } break; } @@ -373,10 +470,12 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, out_info->type_info = &op_info; uint32_t offset_type = xe::load_and_swap(ptr + 0); uint32_t index = offset_type & 0xFFFF; + + out_actions.reserve(count - 1); + for (uint32_t n = 0; n < count - 1; n++, index++) { uint32_t data = xe::load_and_swap(ptr + 4 + n * 4); - out_info->actions.emplace_back( - PacketAction::RegisterWrite(index, data)); + out_actions.emplace_back(PacketAction::RegisterWrite(index, data)); } return true; } @@ -391,6 +490,17 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, uint32_t start_size = xe::load_and_swap(ptr + 4); uint32_t start = start_size >> 16; uint32_t size_dwords = start_size & 0xFFFF; // dwords + + PacketAction iml_action; + iml_action.type = Type::kImLoad; + auto& iml = iml_action.im_load; + iml.addr = addr; + iml.shader_type = shader_type; + iml.size_dwords = size_dwords; + iml.start = start; + + out_actions.emplace_back(std::move(iml_action)); + assert_true(start == 0); break; } @@ -405,6 +515,20 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, uint32_t start_size = dword1; uint32_t start = start_size >> 16; uint32_t size_dwords = start_size & 0xFFFF; // dwords + + PacketAction imi_action; + imi_action.type = Type::kImLoadImmediate; + imi_action.words.reserve(size_dwords); + auto& imi = imi_action.im_load_imm; + imi.shader_type = shader_type; + imi.size_dwords = size_dwords; + imi.start = start; + + imi_action.InjectBeWords(reinterpret_cast(ptr + 8), + size_dwords); + + out_actions.emplace_back(std::move(imi_action)); + assert_true(start == 0); break; } @@ -414,6 +538,12 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, "PM4_INVALIDATE_STATE"}; out_info->type_info = &op_info; uint32_t mask = xe::load_and_swap(ptr + 0); + + PacketAction inv_action; + inv_action.type = Type::kInvalidateState; + inv_action.invalidate_state.state_mask = mask; + + out_actions.emplace_back(std::move(inv_action)); break; } case PM4_SET_BIN_MASK_LO: { @@ -422,7 +552,12 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, out_info->type_info = &op_info; uint32_t value = xe::load_and_swap(ptr); // bin_mask_ = (bin_mask_ & 0xFFFFFFFF00000000ull) | value; - out_info->actions.emplace_back(PacketAction::SetBinMask(value)); + + PacketAction action; + action.type = Type::kSetBinMaskLo; + action.lohi_op.value = value; + out_actions.emplace_back(std::move(action)); + break; } case PM4_SET_BIN_MASK_HI: { @@ -430,8 +565,11 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, "PM4_SET_BIN_MASK_HI"}; out_info->type_info = &op_info; uint32_t value = xe::load_and_swap(ptr); - // bin_mask_ = - // (bin_mask_ & 0xFFFFFFFFull) | (static_cast(value) << 32); + + PacketAction action; + action.type = Type::kSetBinMaskHi; + action.lohi_op.value = value; + out_actions.emplace_back(std::move(action)); break; } case PM4_SET_BIN_SELECT_LO: { @@ -439,8 +577,11 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, "PM4_SET_BIN_SELECT_LO"}; out_info->type_info = &op_info; uint32_t value = xe::load_and_swap(ptr); - // bin_select_ = (bin_select_ & 0xFFFFFFFF00000000ull) | value; - out_info->actions.emplace_back(PacketAction::SetBinSelect(value)); + PacketAction action; + action.type = Type::kSetBinSelectLo; + action.lohi_op.value = value; + out_actions.emplace_back(std::move(action)); + break; } case PM4_SET_BIN_SELECT_HI: { @@ -448,9 +589,82 @@ bool PacketDisassembler::DisasmPacketType3(const uint8_t* base_ptr, "PM4_SET_BIN_SELECT_HI"}; out_info->type_info = &op_info; uint32_t value = xe::load_and_swap(ptr); - // bin_select_ = - // (bin_select_ & 0xFFFFFFFFull) | (static_cast(value) << - // 32); + + PacketAction action; + action.type = Type::kSetBinSelectHi; + action.lohi_op.value = value; + out_actions.emplace_back(std::move(action)); + break; + } + case PM4_CONTEXT_UPDATE: { + uint32_t value = xe::load_and_swap(ptr); + PacketAction ctxu; + ctxu.type = Type::kContextUpdate; + ctxu.context_update.maybe_unused = value; + out_actions.emplace_back(std::move(ctxu)); + break; + } + case PM4_WAIT_FOR_IDLE: { + uint32_t value = xe::load_and_swap(ptr); + PacketAction wfi; + wfi.type = Type::kWaitForIdle; + wfi.wait_for_idle.probably_unused = value; + out_actions.emplace_back(std::move(wfi)); + break; + } + + case PM4_VIZ_QUERY: { + uint32_t value = xe::load_and_swap(ptr); + + PacketAction vzq; + vzq.type = Type::kVizQuery; + vzq.vizquery.dword0 = value; + vzq.vizquery.id = value & 0x3F; + vzq.vizquery.end = !!(value & 0x100); + out_actions.emplace_back(std::move(vzq)); + break; + } + case PM4_EVENT_WRITE_ZPD: { + uint32_t value = xe::load_and_swap(ptr); + + PacketAction evz; + evz.type = Type::kEventWriteZPD; + evz.event_write_zpd.initiator = value; + out_actions.emplace_back(std::move(evz)); + break; + } + case PM4_MEM_WRITE: { + PacketAction mwr; + mwr.type = Type::kMemWrite; + mwr.words.reserve(count - 1); + + uint32_t write_addr = xe::load_and_swap(ptr); + auto endianness = static_cast(write_addr & 0x3); + auto addr = write_addr & ~0x3; + + mwr.mem_write.addr = addr; + mwr.mem_write.endianness = endianness; + + // can't use injectbewords here, have to apply gpuswap to each element + for (uint32_t i = 0; i < count - 1; i++) { + uint32_t write_data = xe::load_and_swap(&ptr[(i + 1) * 4]); + write_data = GpuSwap(write_data, endianness); + mwr.words.push_back(write_data); + write_addr += 4; + } + + out_actions.emplace_back(std::move(mwr)); + break; + } + + case PM4_REG_TO_MEM: { + PacketAction r2m; + r2m.type = Type::kRegToMem; + r2m.reg2mem.reg_addr = xe::load_and_swap(ptr); + uint32_t dword1 = xe::load_and_swap(ptr + 4); + r2m.reg2mem.endianness = static_cast(dword1 & 0x3); + r2m.reg2mem.mem_addr = dword1 & (~3U); + out_actions.emplace_back(std::move(r2m)); break; }