diff options
| author | 2014-06-04 18:30:23 +0200 | |
|---|---|---|
| committer | 2014-07-23 00:33:08 +0200 | |
| commit | baf0aa04f50dff257b57fa78786e53b97c1e6abb (patch) | |
| tree | 3dc92a276f58d1099eb19dd2b5fcb52c69a8da9a /src/core/hw/gpu.cpp | |
| parent | GPU: Add proper framebuffer register handling. (diff) | |
| download | yuzu-baf0aa04f50dff257b57fa78786e53b97c1e6abb.tar.gz yuzu-baf0aa04f50dff257b57fa78786e53b97c1e6abb.tar.xz yuzu-baf0aa04f50dff257b57fa78786e53b97c1e6abb.zip | |
GPU: Emulate memory fills.
Diffstat (limited to 'src/core/hw/gpu.cpp')
| -rw-r--r-- | src/core/hw/gpu.cpp | 56 |
1 files changed, 54 insertions, 2 deletions
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index fad3439c8..230a12d46 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp | |||
| @@ -84,6 +84,26 @@ const u8* GetFramebufferPointer(const u32 address) { | |||
| 84 | template <typename T> | 84 | template <typename T> |
| 85 | inline void Read(T &var, const u32 addr) { | 85 | inline void Read(T &var, const u32 addr) { |
| 86 | switch (addr) { | 86 | switch (addr) { |
| 87 | case Registers::MemoryFillStart1: | ||
| 88 | case Registers::MemoryFillStart2: | ||
| 89 | var = g_regs.memory_fill[(addr - Registers::MemoryFillStart1) / 0x10].address_start; | ||
| 90 | break; | ||
| 91 | |||
| 92 | case Registers::MemoryFillEnd1: | ||
| 93 | case Registers::MemoryFillEnd2: | ||
| 94 | var = g_regs.memory_fill[(addr - Registers::MemoryFillEnd1) / 0x10].address_end; | ||
| 95 | break; | ||
| 96 | |||
| 97 | case Registers::MemoryFillSize1: | ||
| 98 | case Registers::MemoryFillSize2: | ||
| 99 | var = g_regs.memory_fill[(addr - Registers::MemoryFillSize1) / 0x10].size; | ||
| 100 | break; | ||
| 101 | |||
| 102 | case Registers::MemoryFillValue1: | ||
| 103 | case Registers::MemoryFillValue2: | ||
| 104 | var = g_regs.memory_fill[(addr - Registers::MemoryFillValue1) / 0x10].value; | ||
| 105 | break; | ||
| 106 | |||
| 87 | case Registers::FramebufferTopSize: | 107 | case Registers::FramebufferTopSize: |
| 88 | var = g_regs.top_framebuffer.size; | 108 | var = g_regs.top_framebuffer.size; |
| 89 | break; | 109 | break; |
| @@ -194,6 +214,40 @@ inline void Read(T &var, const u32 addr) { | |||
| 194 | template <typename T> | 214 | template <typename T> |
| 195 | inline void Write(u32 addr, const T data) { | 215 | inline void Write(u32 addr, const T data) { |
| 196 | switch (static_cast<Registers::Id>(addr)) { | 216 | switch (static_cast<Registers::Id>(addr)) { |
| 217 | case Registers::MemoryFillStart1: | ||
| 218 | case Registers::MemoryFillStart2: | ||
| 219 | g_regs.memory_fill[(addr - Registers::MemoryFillStart1) / 0x10].address_start = data; | ||
| 220 | break; | ||
| 221 | |||
| 222 | case Registers::MemoryFillEnd1: | ||
| 223 | case Registers::MemoryFillEnd2: | ||
| 224 | g_regs.memory_fill[(addr - Registers::MemoryFillEnd1) / 0x10].address_end = data; | ||
| 225 | break; | ||
| 226 | |||
| 227 | case Registers::MemoryFillSize1: | ||
| 228 | case Registers::MemoryFillSize2: | ||
| 229 | g_regs.memory_fill[(addr - Registers::MemoryFillSize1) / 0x10].size = data; | ||
| 230 | break; | ||
| 231 | |||
| 232 | case Registers::MemoryFillValue1: | ||
| 233 | case Registers::MemoryFillValue2: | ||
| 234 | { | ||
| 235 | Registers::MemoryFillConfig& config = g_regs.memory_fill[(addr - Registers::MemoryFillValue1) / 0x10]; | ||
| 236 | config.value = data; | ||
| 237 | |||
| 238 | // TODO: Not sure if this check should be done at GSP level instead | ||
| 239 | if (config.address_start) { | ||
| 240 | // TODO: Not sure if this algorithm is correct, particularly because it doesn't use the size member at all | ||
| 241 | u32* start = (u32*)Memory::GetPointer(config.GetStartAddress()); | ||
| 242 | u32* end = (u32*)Memory::GetPointer(config.GetEndAddress()); | ||
| 243 | for (u32* ptr = start; ptr < end; ++ptr) | ||
| 244 | *ptr = bswap32(config.value); // TODO: This is just a workaround to missing framebuffer format emulation | ||
| 245 | |||
| 246 | DEBUG_LOG(GPU, "MemoryFill from %x to %x", config.GetStartAddress(), config.GetEndAddress()); | ||
| 247 | } | ||
| 248 | break; | ||
| 249 | } | ||
| 250 | |||
| 197 | // TODO: Framebuffer registers!! | 251 | // TODO: Framebuffer registers!! |
| 198 | case Registers::FramebufferTopSwapBuffers: | 252 | case Registers::FramebufferTopSwapBuffers: |
| 199 | g_regs.top_framebuffer.active_fb = data; | 253 | g_regs.top_framebuffer.active_fb = data; |
| @@ -240,8 +294,6 @@ inline void Write(u32 addr, const T data) { | |||
| 240 | g_regs.display_transfer.output_width * 4); | 294 | g_regs.display_transfer.output_width * 4); |
| 241 | } | 295 | } |
| 242 | 296 | ||
| 243 | // Clear previous contents until we implement proper buffer clearing | ||
| 244 | memset(source_pointer, 0x20, g_regs.display_transfer.input_width*g_regs.display_transfer.input_height*4); | ||
| 245 | DEBUG_LOG(GPU, "DisplayTriggerTransfer: %x bytes from %x(%xx%x)-> %x(%xx%x), dst format %x", | 297 | DEBUG_LOG(GPU, "DisplayTriggerTransfer: %x bytes from %x(%xx%x)-> %x(%xx%x), dst format %x", |
| 246 | g_regs.display_transfer.output_height * g_regs.display_transfer.output_width * 4, | 298 | g_regs.display_transfer.output_height * g_regs.display_transfer.output_width * 4, |
| 247 | g_regs.display_transfer.GetPhysicalInputAddress(), (int)g_regs.display_transfer.input_width, (int)g_regs.display_transfer.input_height, | 299 | g_regs.display_transfer.GetPhysicalInputAddress(), (int)g_regs.display_transfer.input_width, (int)g_regs.display_transfer.input_height, |