summaryrefslogtreecommitdiff
path: root/src/core/hw/gpu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hw/gpu.cpp')
-rw-r--r--src/core/hw/gpu.cpp110
1 files changed, 23 insertions, 87 deletions
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index fd40f8ac0..87cf93bac 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -14,6 +14,7 @@
14 14
15#include "core/hw/gpu.h" 15#include "core/hw/gpu.h"
16 16
17#include "video_core/command_processor.h"
17#include "video_core/video_core.h" 18#include "video_core/video_core.h"
18 19
19 20
@@ -24,83 +25,6 @@ Regs g_regs;
24u32 g_cur_line = 0; ///< Current vertical screen line 25u32 g_cur_line = 0; ///< Current vertical screen line
25u64 g_last_line_ticks = 0; ///< CPU tick count from last vertical screen line 26u64 g_last_line_ticks = 0; ///< CPU tick count from last vertical screen line
26 27
27/**
28 * Sets whether the framebuffers are in the GSP heap (FCRAM) or VRAM
29 * @param
30 */
31void SetFramebufferLocation(const FramebufferLocation mode) {
32 switch (mode) {
33 case FRAMEBUFFER_LOCATION_FCRAM:
34 {
35 auto& framebuffer_top = g_regs.framebuffer_config[0];
36 auto& framebuffer_sub = g_regs.framebuffer_config[1];
37
38 framebuffer_top.address_left1 = PADDR_TOP_LEFT_FRAME1;
39 framebuffer_top.address_left2 = PADDR_TOP_LEFT_FRAME2;
40 framebuffer_top.address_right1 = PADDR_TOP_RIGHT_FRAME1;
41 framebuffer_top.address_right2 = PADDR_TOP_RIGHT_FRAME2;
42 framebuffer_sub.address_left1 = PADDR_SUB_FRAME1;
43 //framebuffer_sub.address_left2 = unknown;
44 framebuffer_sub.address_right1 = PADDR_SUB_FRAME2;
45 //framebuffer_sub.address_right2 = unknown;
46 break;
47 }
48
49 case FRAMEBUFFER_LOCATION_VRAM:
50 {
51 auto& framebuffer_top = g_regs.framebuffer_config[0];
52 auto& framebuffer_sub = g_regs.framebuffer_config[1];
53
54 framebuffer_top.address_left1 = PADDR_VRAM_TOP_LEFT_FRAME1;
55 framebuffer_top.address_left2 = PADDR_VRAM_TOP_LEFT_FRAME2;
56 framebuffer_top.address_right1 = PADDR_VRAM_TOP_RIGHT_FRAME1;
57 framebuffer_top.address_right2 = PADDR_VRAM_TOP_RIGHT_FRAME2;
58 framebuffer_sub.address_left1 = PADDR_VRAM_SUB_FRAME1;
59 //framebuffer_sub.address_left2 = unknown;
60 framebuffer_sub.address_right1 = PADDR_VRAM_SUB_FRAME2;
61 //framebuffer_sub.address_right2 = unknown;
62 break;
63 }
64 }
65}
66
67/**
68 * Gets the location of the framebuffers
69 * @return Location of framebuffers as FramebufferLocation enum
70 */
71FramebufferLocation GetFramebufferLocation(u32 address) {
72 if ((address & ~Memory::VRAM_MASK) == Memory::VRAM_PADDR) {
73 return FRAMEBUFFER_LOCATION_VRAM;
74 } else if ((address & ~Memory::FCRAM_MASK) == Memory::FCRAM_PADDR) {
75 return FRAMEBUFFER_LOCATION_FCRAM;
76 } else {
77 ERROR_LOG(GPU, "unknown framebuffer location!");
78 }
79 return FRAMEBUFFER_LOCATION_UNKNOWN;
80}
81
82u32 GetFramebufferAddr(const u32 address) {
83 switch (GetFramebufferLocation(address)) {
84 case FRAMEBUFFER_LOCATION_FCRAM:
85 return Memory::VirtualAddressFromPhysical_FCRAM(address);
86 case FRAMEBUFFER_LOCATION_VRAM:
87 return Memory::VirtualAddressFromPhysical_VRAM(address);
88 default:
89 ERROR_LOG(GPU, "unknown framebuffer location");
90 }
91 return 0;
92}
93
94/**
95 * Gets a read-only pointer to a framebuffer in memory
96 * @param address Physical address of framebuffer
97 * @return Returns const pointer to raw framebuffer
98 */
99const u8* GetFramebufferPointer(const u32 address) {
100 u32 addr = GetFramebufferAddr(address);
101 return (addr != 0) ? Memory::GetPointer(addr) : nullptr;
102}
103
104template <typename T> 28template <typename T>
105inline void Read(T &var, const u32 raw_addr) { 29inline void Read(T &var, const u32 raw_addr) {
106 u32 addr = raw_addr - 0x1EF00000; 30 u32 addr = raw_addr - 0x1EF00000;
@@ -141,8 +65,8 @@ inline void Write(u32 addr, const T data) {
141 // TODO: Not sure if this check should be done at GSP level instead 65 // TODO: Not sure if this check should be done at GSP level instead
142 if (config.address_start) { 66 if (config.address_start) {
143 // TODO: Not sure if this algorithm is correct, particularly because it doesn't use the size member at all 67 // TODO: Not sure if this algorithm is correct, particularly because it doesn't use the size member at all
144 u32* start = (u32*)Memory::GetPointer(config.GetStartAddress()); 68 u32* start = (u32*)Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetStartAddress()));
145 u32* end = (u32*)Memory::GetPointer(config.GetEndAddress()); 69 u32* end = (u32*)Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetEndAddress()));
146 for (u32* ptr = start; ptr < end; ++ptr) 70 for (u32* ptr = start; ptr < end; ++ptr)
147 *ptr = bswap32(config.value); // TODO: This is just a workaround to missing framebuffer format emulation 71 *ptr = bswap32(config.value); // TODO: This is just a workaround to missing framebuffer format emulation
148 72
@@ -155,8 +79,8 @@ inline void Write(u32 addr, const T data) {
155 { 79 {
156 const auto& config = g_regs.display_transfer_config; 80 const auto& config = g_regs.display_transfer_config;
157 if (config.trigger & 1) { 81 if (config.trigger & 1) {
158 u8* source_pointer = Memory::GetPointer(config.GetPhysicalInputAddress()); 82 u8* source_pointer = Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalInputAddress()));
159 u8* dest_pointer = Memory::GetPointer(config.GetPhysicalOutputAddress()); 83 u8* dest_pointer = Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalOutputAddress()));
160 84
161 for (int y = 0; y < config.output_height; ++y) { 85 for (int y = 0; y < config.output_height; ++y) {
162 // TODO: Why does the register seem to hold twice the framebuffer width? 86 // TODO: Why does the register seem to hold twice the framebuffer width?
@@ -220,14 +144,15 @@ inline void Write(u32 addr, const T data) {
220 break; 144 break;
221 } 145 }
222 146
147 // Seems like writing to this register triggers processing
223 case GPU_REG_INDEX(command_processor_config.trigger): 148 case GPU_REG_INDEX(command_processor_config.trigger):
224 { 149 {
225 const auto& config = g_regs.command_processor_config; 150 const auto& config = g_regs.command_processor_config;
226 if (config.trigger & 1) 151 if (config.trigger & 1)
227 { 152 {
228 // u32* buffer = (u32*)Memory::GetPointer(config.GetPhysicalAddress()); 153 u32* buffer = (u32*)Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalAddress()));
229 ERROR_LOG(GPU, "Beginning 0x%08x bytes of commands from address 0x%08x", config.size, config.GetPhysicalAddress()); 154 u32 size = config.size << 3;
230 // TODO: Process command list! 155 Pica::CommandProcessor::ProcessCommandList(buffer, size);
231 } 156 }
232 break; 157 break;
233 } 158 }
@@ -276,11 +201,22 @@ void Init() {
276 g_cur_line = 0; 201 g_cur_line = 0;
277 g_last_line_ticks = Core::g_app_core->GetTicks(); 202 g_last_line_ticks = Core::g_app_core->GetTicks();
278 203
279// SetFramebufferLocation(FRAMEBUFFER_LOCATION_FCRAM);
280 SetFramebufferLocation(FRAMEBUFFER_LOCATION_VRAM);
281
282 auto& framebuffer_top = g_regs.framebuffer_config[0]; 204 auto& framebuffer_top = g_regs.framebuffer_config[0];
283 auto& framebuffer_sub = g_regs.framebuffer_config[1]; 205 auto& framebuffer_sub = g_regs.framebuffer_config[1];
206
207 // Setup default framebuffer addresses (located in VRAM)
208 // .. or at least these are the ones used by system applets.
209 // There's probably a smarter way to come up with addresses
210 // like this which does not require hardcoding.
211 framebuffer_top.address_left1 = 0x181E6000;
212 framebuffer_top.address_left2 = 0x1822C800;
213 framebuffer_top.address_right1 = 0x18273000;
214 framebuffer_top.address_right2 = 0x182B9800;
215 framebuffer_sub.address_left1 = 0x1848F000;
216 //framebuffer_sub.address_left2 = unknown;
217 framebuffer_sub.address_right1 = 0x184C7800;
218 //framebuffer_sub.address_right2 = unknown;
219
284 // TODO: Width should be 240 instead? 220 // TODO: Width should be 240 instead?
285 framebuffer_top.width = 480; 221 framebuffer_top.width = 480;
286 framebuffer_top.height = 400; 222 framebuffer_top.height = 400;