diff options
| author | 2015-04-18 02:37:41 +0200 | |
|---|---|---|
| committer | 2015-07-13 22:27:20 +0200 | |
| commit | 93d66475d491f0ed0070da0fc3bcc2d9bb066233 (patch) | |
| tree | c09bff61604139936dede802ac03ec770dec1e3d /src/core/hw/gpu.cpp | |
| parent | FileUtil: Add a WriteObject method for writing a single, POD-type object. (diff) | |
| download | yuzu-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.cpp | 61 |
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 | } |