summaryrefslogtreecommitdiff
path: root/src/core/hw/gpu.cpp
diff options
context:
space:
mode:
authorGravatar Tony Wasserka2015-04-18 02:37:41 +0200
committerGravatar Tony Wasserka2015-07-13 22:27:20 +0200
commit93d66475d491f0ed0070da0fc3bcc2d9bb066233 (patch)
treec09bff61604139936dede802ac03ec770dec1e3d /src/core/hw/gpu.cpp
parentFileUtil: Add a WriteObject method for writing a single, POD-type object. (diff)
downloadyuzu-93d66475d491f0ed0070da0fc3bcc2d9bb066233.tar.gz
yuzu-93d66475d491f0ed0070da0fc3bcc2d9bb066233.tar.xz
yuzu-93d66475d491f0ed0070da0fc3bcc2d9bb066233.zip
GPU: Be robust against nullptr addresses; properly reset busy bits in the trigger registers.
Diffstat (limited to 'src/core/hw/gpu.cpp')
-rw-r--r--src/core/hw/gpu.cpp61
1 files changed, 34 insertions, 27 deletions
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index a1789f9c7..796493378 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -101,39 +101,43 @@ inline void Write(u32 addr, const T data) {
101 const bool is_second_filler = (index != GPU_REG_INDEX(memory_fill_config[0].trigger)); 101 const bool is_second_filler = (index != GPU_REG_INDEX(memory_fill_config[0].trigger));
102 auto& config = g_regs.memory_fill_config[is_second_filler]; 102 auto& config = g_regs.memory_fill_config[is_second_filler];
103 103
104 if (config.address_start && config.trigger) { 104 if (config.trigger) {
105 u8* start = Memory::GetPhysicalPointer(config.GetStartAddress()); 105 if (config.address_start) { // Some games pass invalid values here
106 u8* end = Memory::GetPhysicalPointer(config.GetEndAddress()); 106 u8* start = Memory::GetPhysicalPointer(config.GetStartAddress());
107 107 u8* end = Memory::GetPhysicalPointer(config.GetEndAddress());
108 if (config.fill_24bit) { 108
109 // fill with 24-bit values 109 if (config.fill_24bit) {
110 for (u8* ptr = start; ptr < end; ptr += 3) { 110 // fill with 24-bit values
111 ptr[0] = config.value_24bit_r; 111 for (u8* ptr = start; ptr < end; ptr += 3) {
112 ptr[1] = config.value_24bit_g; 112 ptr[0] = config.value_24bit_r;
113 ptr[2] = config.value_24bit_b; 113 ptr[1] = config.value_24bit_g;
114 ptr[2] = config.value_24bit_b;
115 }
116 } else if (config.fill_32bit) {
117 // fill with 32-bit values
118 for (u32* ptr = (u32*)start; ptr < (u32*)end; ++ptr)
119 *ptr = config.value_32bit;
120 } else {
121 // fill with 16-bit values
122 for (u16* ptr = (u16*)start; ptr < (u16*)end; ++ptr)
123 *ptr = config.value_16bit;
114 } 124 }
115 } else if (config.fill_32bit) {
116 // fill with 32-bit values
117 for (u32* ptr = (u32*)start; ptr < (u32*)end; ++ptr)
118 *ptr = config.value_32bit;
119 } else {
120 // fill with 16-bit values
121 for (u16* ptr = (u16*)start; ptr < (u16*)end; ++ptr)
122 *ptr = config.value_16bit;
123 }
124 125
125 LOG_TRACE(HW_GPU, "MemoryFill from 0x%08x to 0x%08x", config.GetStartAddress(), config.GetEndAddress()); 126 LOG_TRACE(HW_GPU, "MemoryFill from 0x%08x to 0x%08x", config.GetStartAddress(), config.GetEndAddress());
126 127
127 config.trigger = 0; 128 if (!is_second_filler) {
128 config.finished = 1; 129 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC0);
130 } else {
131 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC1);
132 }
129 133
130 if (!is_second_filler) { 134 VideoCore::g_renderer->hw_rasterizer->NotifyFlush(config.GetStartAddress(), config.GetEndAddress() - config.GetStartAddress());
131 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC0);
132 } else {
133 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC1);
134 } 135 }
135 136
136 VideoCore::g_renderer->hw_rasterizer->NotifyFlush(config.GetStartAddress(), config.GetEndAddress() - config.GetStartAddress()); 137 // Reset "trigger" flag and set the "finish" flag
138 // NOTE: This was confirmed to happen on hardware even if "address_start" is zero.
139 config.trigger = 0;
140 config.finished = 1;
137 } 141 }
138 break; 142 break;
139 } 143 }
@@ -270,6 +274,7 @@ inline void Write(u32 addr, const T data) {
270 config.GetPhysicalOutputAddress(), output_width, output_height, 274 config.GetPhysicalOutputAddress(), output_width, output_height,
271 config.output_format.Value(), config.flags); 275 config.output_format.Value(), config.flags);
272 276
277 g_regs.display_transfer_config.trigger = 0;
273 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF); 278 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF);
274 279
275 VideoCore::g_renderer->hw_rasterizer->NotifyFlush(config.GetPhysicalOutputAddress(), output_size); 280 VideoCore::g_renderer->hw_rasterizer->NotifyFlush(config.GetPhysicalOutputAddress(), output_size);
@@ -285,6 +290,8 @@ inline void Write(u32 addr, const T data) {
285 { 290 {
286 u32* buffer = (u32*)Memory::GetPhysicalPointer(config.GetPhysicalAddress()); 291 u32* buffer = (u32*)Memory::GetPhysicalPointer(config.GetPhysicalAddress());
287 Pica::CommandProcessor::ProcessCommandList(buffer, config.size); 292 Pica::CommandProcessor::ProcessCommandList(buffer, config.size);
293
294 g_regs.command_processor_config.trigger = 0;
288 } 295 }
289 break; 296 break;
290 } 297 }