| @@ -162,6 +162,7 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) { | ||||
|  | ||||
|     _assert_msg_(GSP, (g_interrupt_event != 0), "handle is not valid!"); | ||||
|  | ||||
|     cmd_buff[1] = 0x2A07; // Value verified by 3dmoo team, purpose unknown, but needed for GSP init | ||||
|     cmd_buff[2] = g_thread_id++; // Thread ID | ||||
|     cmd_buff[4] = g_shared_memory; // GSP shared memory | ||||
|  | ||||
| @@ -172,6 +173,7 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) { | ||||
|  * Signals that the specified interrupt type has occurred to userland code | ||||
|  * @param interrupt_id ID of interrupt that is being signalled | ||||
|  * @todo This should probably take a thread_id parameter and only signal this thread? | ||||
|  * @todo This probably does not belong in the GSP module, instead move to video_core | ||||
|  */ | ||||
| void SignalInterrupt(InterruptId interrupt_id) { | ||||
|     if (0 == g_interrupt_event) { | ||||
| @@ -210,6 +212,7 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | ||||
|         memcpy(Memory::GetPointer(command.dma_request.dest_address), | ||||
|                Memory::GetPointer(command.dma_request.source_address), | ||||
|                command.dma_request.size); | ||||
|         SignalInterrupt(InterruptId::DMA); | ||||
|         break; | ||||
|  | ||||
|     // ctrulib homebrew sends all relevant command list data with this command, | ||||
| @@ -218,13 +221,13 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | ||||
|     case CommandId::SET_COMMAND_LIST_LAST: | ||||
|     { | ||||
|         auto& params = command.set_command_list_last; | ||||
|  | ||||
|         WriteGPURegister(GPU_REG_INDEX(command_processor_config.address), Memory::VirtualToPhysicalAddress(params.address) >> 3); | ||||
|         WriteGPURegister(GPU_REG_INDEX(command_processor_config.size), params.size >> 3); | ||||
|         WriteGPURegister(GPU_REG_INDEX(command_processor_config.size), params.size); | ||||
|  | ||||
|         // TODO: Not sure if we are supposed to always write this .. seems to trigger processing though | ||||
|         WriteGPURegister(GPU_REG_INDEX(command_processor_config.trigger), 1); | ||||
|  | ||||
|         SignalInterrupt(InterruptId::P3D); | ||||
|         break; | ||||
|     } | ||||
|  | ||||
| @@ -242,6 +245,8 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | ||||
|         WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].address_end), Memory::VirtualToPhysicalAddress(params.end2) >> 3); | ||||
|         WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].size), params.end2 - params.start2); | ||||
|         WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].value), params.value2); | ||||
|  | ||||
|         SignalInterrupt(InterruptId::PSC0); | ||||
|         break; | ||||
|     } | ||||
|  | ||||
| @@ -255,14 +260,9 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | ||||
|         WriteGPURegister(GPU_REG_INDEX(display_transfer_config.flags), params.flags); | ||||
|         WriteGPURegister(GPU_REG_INDEX(display_transfer_config.trigger), 1); | ||||
|  | ||||
|         // TODO(bunnei): Signalling all of these interrupts here is totally wrong, but it seems to | ||||
|         // work well enough for running demos. Need to figure out how these all work and trigger | ||||
|         // them correctly. | ||||
|         SignalInterrupt(InterruptId::PSC0); | ||||
|         // TODO(bunnei): Determine if these interrupts should be signalled here. | ||||
|         SignalInterrupt(InterruptId::PSC1); | ||||
|         SignalInterrupt(InterruptId::PPF); | ||||
|         SignalInterrupt(InterruptId::P3D); | ||||
|         SignalInterrupt(InterruptId::DMA); | ||||
|  | ||||
|         // Update framebuffer information if requested | ||||
|         for (int screen_id = 0; screen_id < 2; ++screen_id) { | ||||
| @@ -305,6 +305,8 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | ||||
| /// This triggers handling of the GX command written to the command buffer in shared memory. | ||||
| static void TriggerCmdReqQueue(Service::Interface* self) { | ||||
|  | ||||
|     DEBUG_LOG(GSP, "called"); | ||||
|  | ||||
|     // Iterate through each thread's command queue... | ||||
|     for (unsigned thread_id = 0; thread_id < 0x4; ++thread_id) { | ||||
|         CommandBuffer* command_buffer = (CommandBuffer*)GetCommandBuffer(thread_id); | ||||
| @@ -320,6 +322,9 @@ static void TriggerCmdReqQueue(Service::Interface* self) { | ||||
|             command_buffer->number_commands = command_buffer->number_commands - 1; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     u32* cmd_buff = Service::GetCommandBuffer(); | ||||
|     cmd_buff[1] = 0; // No error | ||||
| } | ||||
|  | ||||
| const Interface::FunctionInfo FunctionTable[] = { | ||||
|   | ||||
| @@ -154,8 +154,7 @@ inline void Write(u32 addr, const T data) { | ||||
|         if (config.trigger & 1) | ||||
|         { | ||||
|             u32* buffer = (u32*)Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalAddress())); | ||||
|             u32 size = config.size << 3; | ||||
|             Pica::CommandProcessor::ProcessCommandList(buffer, size); | ||||
|             Pica::CommandProcessor::ProcessCommandList(buffer, config.size); | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
|   | ||||
| @@ -169,7 +169,7 @@ struct Regs { | ||||
|     INSERT_PADDING_WORDS(0x331); | ||||
|  | ||||
|     struct { | ||||
|         // command list size | ||||
|         // command list size (in bytes) | ||||
|         u32 size; | ||||
|  | ||||
|         INSERT_PADDING_WORDS(0x1); | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
| #include "pica.h" | ||||
| #include "primitive_assembly.h" | ||||
| #include "vertex_shader.h" | ||||
| #include "core/hle/service/gsp_gpu.h" | ||||
|  | ||||
| #include "debug_utils/debug_utils.h" | ||||
|  | ||||
| @@ -40,6 +41,11 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | ||||
|     DebugUtils::OnPicaRegWrite(id, registers[id]); | ||||
|  | ||||
|     switch(id) { | ||||
|         // Trigger IRQ | ||||
|         case PICA_REG_INDEX(trigger_irq): | ||||
|             GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::P3D); | ||||
|             return; | ||||
|  | ||||
|         // It seems like these trigger vertex rendering | ||||
|         case PICA_REG_INDEX(trigger_draw): | ||||
|         case PICA_REG_INDEX(trigger_draw_indexed): | ||||
| @@ -272,8 +278,9 @@ static std::ptrdiff_t ExecuteCommandBlock(const u32* first_command_word) { | ||||
|  | ||||
| void ProcessCommandList(const u32* list, u32 size) { | ||||
|     u32* read_pointer = (u32*)list; | ||||
|     u32 list_length = size / sizeof(u32); | ||||
|  | ||||
|     while (read_pointer < list + size) { | ||||
|     while (read_pointer < list + list_length) { | ||||
|         read_pointer += ExecuteCommandBlock(read_pointer); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -45,10 +45,16 @@ struct Regs { | ||||
| #define INSERT_PADDING_WORDS_HELPER2(x, y) INSERT_PADDING_WORDS_HELPER1(x, y) | ||||
| #define INSERT_PADDING_WORDS(num_words) u32 INSERT_PADDING_WORDS_HELPER2(pad, __LINE__)[(num_words)]; | ||||
|  | ||||
|     INSERT_PADDING_WORDS(0x41); | ||||
|     INSERT_PADDING_WORDS(0x10); | ||||
|  | ||||
|     u32 trigger_irq; | ||||
|  | ||||
|     INSERT_PADDING_WORDS(0x30); | ||||
|  | ||||
|     BitField<0, 24, u32> viewport_size_x; | ||||
|  | ||||
|     INSERT_PADDING_WORDS(0x1); | ||||
|  | ||||
|     BitField<0, 24, u32> viewport_size_y; | ||||
|  | ||||
|     INSERT_PADDING_WORDS(0x9); | ||||
| @@ -544,6 +550,7 @@ struct Regs { | ||||
|                     map.insert({i, #name + std::string("+") + std::to_string(i-PICA_REG_INDEX(name))});       \ | ||||
|             } while(false) | ||||
|  | ||||
|         ADD_FIELD(trigger_irq); | ||||
|         ADD_FIELD(viewport_size_x); | ||||
|         ADD_FIELD(viewport_size_y); | ||||
|         ADD_FIELD(viewport_depth_range); | ||||
| @@ -607,6 +614,7 @@ private: | ||||
| #ifndef _MSC_VER | ||||
| #define ASSERT_REG_POSITION(field_name, position) static_assert(offsetof(Regs, field_name) == position * 4, "Field "#field_name" has invalid position") | ||||
|  | ||||
| ASSERT_REG_POSITION(trigger_irq, 0x10); | ||||
| ASSERT_REG_POSITION(viewport_size_x, 0x41); | ||||
| ASSERT_REG_POSITION(viewport_size_y, 0x43); | ||||
| ASSERT_REG_POSITION(viewport_depth_range, 0x4d); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user