summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Tony Wasserka2014-08-03 01:46:47 +0200
committerGravatar Tony Wasserka2014-08-12 13:32:56 +0200
commit7b6a7d7dfb92d7a6d3537ea8b0339c2170d7eb84 (patch)
tree2b005f3358a228136e7711ddac790ed54bb67b1f /src
parentGSP: Fix a major regression introduced in ffda035c, due to which no display t... (diff)
downloadyuzu-7b6a7d7dfb92d7a6d3537ea8b0339c2170d7eb84.tar.gz
yuzu-7b6a7d7dfb92d7a6d3537ea8b0339c2170d7eb84.tar.xz
yuzu-7b6a7d7dfb92d7a6d3537ea8b0339c2170d7eb84.zip
Pica/GPU: Change hardware registers to use physical addresses rather than virtual ones.
This cleans up the mess that address reading/writing had become and makes the code a *lot* more sensible. This adds a physical<->virtual address converter to mem_map.h. For further accuracy, we will want to properly extend this to support a wider range of address regions. For now, this makes simply homebrew applications work in a good manner though.
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/service/gsp.cpp18
-rw-r--r--src/core/hw/gpu.cpp102
-rw-r--r--src/core/hw/gpu.h66
-rw-r--r--src/core/mem_map.cpp4
-rw-r--r--src/core/mem_map.h22
-rw-r--r--src/core/mem_map_funcs.cpp68
-rw-r--r--src/video_core/pica.h2
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp14
8 files changed, 80 insertions, 216 deletions
diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp
index e2b0a48a7..635f50a53 100644
--- a/src/core/hle/service/gsp.cpp
+++ b/src/core/hle/service/gsp.cpp
@@ -173,7 +173,7 @@ void ExecuteCommand(const Command& command) {
173 case CommandId::SET_COMMAND_LIST_LAST: 173 case CommandId::SET_COMMAND_LIST_LAST:
174 { 174 {
175 auto& params = command.set_command_list_last; 175 auto& params = command.set_command_list_last;
176 WriteGPURegister(GPU_REG_INDEX(command_processor_config.address), params.address >> 3); 176 WriteGPURegister(GPU_REG_INDEX(command_processor_config.address), Memory::VirtualToPhysicalAddress(params.address) >> 3);
177 WriteGPURegister(GPU_REG_INDEX(command_processor_config.size), params.size >> 3); 177 WriteGPURegister(GPU_REG_INDEX(command_processor_config.size), params.size >> 3);
178 178
179 // TODO: Not sure if we are supposed to always write this .. seems to trigger processing though 179 // TODO: Not sure if we are supposed to always write this .. seems to trigger processing though
@@ -193,13 +193,13 @@ void ExecuteCommand(const Command& command) {
193 case CommandId::SET_MEMORY_FILL: 193 case CommandId::SET_MEMORY_FILL:
194 { 194 {
195 auto& params = command.memory_fill; 195 auto& params = command.memory_fill;
196 WriteGPURegister(GPU_REG_INDEX(memory_fill_config[0].address_start), params.start1 >> 3); 196 WriteGPURegister(GPU_REG_INDEX(memory_fill_config[0].address_start), Memory::VirtualToPhysicalAddress(params.start1) >> 3);
197 WriteGPURegister(GPU_REG_INDEX(memory_fill_config[0].address_end), params.end1 >> 3); 197 WriteGPURegister(GPU_REG_INDEX(memory_fill_config[0].address_end), Memory::VirtualToPhysicalAddress(params.end1) >> 3);
198 WriteGPURegister(GPU_REG_INDEX(memory_fill_config[0].size), params.end1 - params.start1); 198 WriteGPURegister(GPU_REG_INDEX(memory_fill_config[0].size), params.end1 - params.start1);
199 WriteGPURegister(GPU_REG_INDEX(memory_fill_config[0].value), params.value1); 199 WriteGPURegister(GPU_REG_INDEX(memory_fill_config[0].value), params.value1);
200 200
201 WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].address_start), params.start2 >> 3); 201 WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].address_start), Memory::VirtualToPhysicalAddress(params.start2) >> 3);
202 WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].address_end), params.end2 >> 3); 202 WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].address_end), Memory::VirtualToPhysicalAddress(params.end2) >> 3);
203 WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].size), params.end2 - params.start2); 203 WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].size), params.end2 - params.start2);
204 WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].value), params.value2); 204 WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].value), params.value2);
205 break; 205 break;
@@ -208,8 +208,8 @@ void ExecuteCommand(const Command& command) {
208 case CommandId::SET_DISPLAY_TRANSFER: 208 case CommandId::SET_DISPLAY_TRANSFER:
209 { 209 {
210 auto& params = command.image_copy; 210 auto& params = command.image_copy;
211 WriteGPURegister(GPU_REG_INDEX(display_transfer_config.input_address), params.in_buffer_address >> 3); 211 WriteGPURegister(GPU_REG_INDEX(display_transfer_config.input_address), Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3);
212 WriteGPURegister(GPU_REG_INDEX(display_transfer_config.output_address), params.out_buffer_address >> 3); 212 WriteGPURegister(GPU_REG_INDEX(display_transfer_config.output_address), Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3);
213 WriteGPURegister(GPU_REG_INDEX(display_transfer_config.input_size), params.in_buffer_size); 213 WriteGPURegister(GPU_REG_INDEX(display_transfer_config.input_size), params.in_buffer_size);
214 WriteGPURegister(GPU_REG_INDEX(display_transfer_config.output_size), params.out_buffer_size); 214 WriteGPURegister(GPU_REG_INDEX(display_transfer_config.output_size), params.out_buffer_size);
215 WriteGPURegister(GPU_REG_INDEX(display_transfer_config.flags), params.flags); 215 WriteGPURegister(GPU_REG_INDEX(display_transfer_config.flags), params.flags);
@@ -230,8 +230,8 @@ void ExecuteCommand(const Command& command) {
230 case CommandId::SET_TEXTURE_COPY: 230 case CommandId::SET_TEXTURE_COPY:
231 { 231 {
232 auto& params = command.image_copy; 232 auto& params = command.image_copy;
233 WriteGPURegister(GPU_REG_INDEX(display_transfer_config.input_address), params.in_buffer_address >> 3); 233 WriteGPURegister(GPU_REG_INDEX(display_transfer_config.input_address), Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3);
234 WriteGPURegister(GPU_REG_INDEX(display_transfer_config.output_address), params.out_buffer_address >> 3); 234 WriteGPURegister(GPU_REG_INDEX(display_transfer_config.output_address), Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3);
235 WriteGPURegister(GPU_REG_INDEX(display_transfer_config.input_size), params.in_buffer_size); 235 WriteGPURegister(GPU_REG_INDEX(display_transfer_config.input_size), params.in_buffer_size);
236 WriteGPURegister(GPU_REG_INDEX(display_transfer_config.output_size), params.out_buffer_size); 236 WriteGPURegister(GPU_REG_INDEX(display_transfer_config.output_size), params.out_buffer_size);
237 WriteGPURegister(GPU_REG_INDEX(display_transfer_config.flags), params.flags); 237 WriteGPURegister(GPU_REG_INDEX(display_transfer_config.flags), params.flags);
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index fd40f8ac0..591997aa3 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -24,83 +24,6 @@ Regs g_regs;
24u32 g_cur_line = 0; ///< Current vertical screen line 24u32 g_cur_line = 0; ///< Current vertical screen line
25u64 g_last_line_ticks = 0; ///< CPU tick count from last vertical screen line 25u64 g_last_line_ticks = 0; ///< CPU tick count from last vertical screen line
26 26
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> 27template <typename T>
105inline void Read(T &var, const u32 raw_addr) { 28inline void Read(T &var, const u32 raw_addr) {
106 u32 addr = raw_addr - 0x1EF00000; 29 u32 addr = raw_addr - 0x1EF00000;
@@ -141,8 +64,8 @@ inline void Write(u32 addr, const T data) {
141 // TODO: Not sure if this check should be done at GSP level instead 64 // TODO: Not sure if this check should be done at GSP level instead
142 if (config.address_start) { 65 if (config.address_start) {
143 // TODO: Not sure if this algorithm is correct, particularly because it doesn't use the size member at all 66 // 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()); 67 u32* start = (u32*)Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetStartAddress()));
145 u32* end = (u32*)Memory::GetPointer(config.GetEndAddress()); 68 u32* end = (u32*)Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetEndAddress()));
146 for (u32* ptr = start; ptr < end; ++ptr) 69 for (u32* ptr = start; ptr < end; ++ptr)
147 *ptr = bswap32(config.value); // TODO: This is just a workaround to missing framebuffer format emulation 70 *ptr = bswap32(config.value); // TODO: This is just a workaround to missing framebuffer format emulation
148 71
@@ -155,8 +78,8 @@ inline void Write(u32 addr, const T data) {
155 { 78 {
156 const auto& config = g_regs.display_transfer_config; 79 const auto& config = g_regs.display_transfer_config;
157 if (config.trigger & 1) { 80 if (config.trigger & 1) {
158 u8* source_pointer = Memory::GetPointer(config.GetPhysicalInputAddress()); 81 u8* source_pointer = Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalInputAddress()));
159 u8* dest_pointer = Memory::GetPointer(config.GetPhysicalOutputAddress()); 82 u8* dest_pointer = Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalOutputAddress()));
160 83
161 for (int y = 0; y < config.output_height; ++y) { 84 for (int y = 0; y < config.output_height; ++y) {
162 // TODO: Why does the register seem to hold twice the framebuffer width? 85 // TODO: Why does the register seem to hold twice the framebuffer width?
@@ -276,11 +199,22 @@ void Init() {
276 g_cur_line = 0; 199 g_cur_line = 0;
277 g_last_line_ticks = Core::g_app_core->GetTicks(); 200 g_last_line_ticks = Core::g_app_core->GetTicks();
278 201
279// SetFramebufferLocation(FRAMEBUFFER_LOCATION_FCRAM);
280 SetFramebufferLocation(FRAMEBUFFER_LOCATION_VRAM);
281
282 auto& framebuffer_top = g_regs.framebuffer_config[0]; 202 auto& framebuffer_top = g_regs.framebuffer_config[0];
283 auto& framebuffer_sub = g_regs.framebuffer_config[1]; 203 auto& framebuffer_sub = g_regs.framebuffer_config[1];
204
205 // Setup default framebuffer addresses (located in VRAM)
206 // .. or at least these are the ones used by system applets.
207 // There's probably a smarter way to come up with addresses
208 // like this which does not require hardcoding.
209 framebuffer_top.address_left1 = 0x181E6000;
210 framebuffer_top.address_left2 = 0x1822C800;
211 framebuffer_top.address_right1 = 0x18273000;
212 framebuffer_top.address_right2 = 0x182B9800;
213 framebuffer_sub.address_left1 = 0x1848F000;
214 //framebuffer_sub.address_left2 = unknown;
215 framebuffer_sub.address_right1 = 0x184C7800;
216 //framebuffer_sub.address_right2 = unknown;
217
284 // TODO: Width should be 240 instead? 218 // TODO: Width should be 240 instead?
285 framebuffer_top.width = 480; 219 framebuffer_top.width = 480;
286 framebuffer_top.height = 400; 220 framebuffer_top.height = 400;
diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h
index 3065da891..d20311a00 100644
--- a/src/core/hw/gpu.h
+++ b/src/core/hw/gpu.h
@@ -249,72 +249,6 @@ static_assert(sizeof(Regs) == 0x1000 * sizeof(u32), "Invalid total size of regis
249 249
250extern Regs g_regs; 250extern Regs g_regs;
251 251
252enum {
253 TOP_ASPECT_X = 0x5,
254 TOP_ASPECT_Y = 0x3,
255
256 TOP_HEIGHT = 240,
257 TOP_WIDTH = 400,
258 BOTTOM_WIDTH = 320,
259
260 // Physical addresses in FCRAM (chosen arbitrarily)
261 PADDR_TOP_LEFT_FRAME1 = 0x201D4C00,
262 PADDR_TOP_LEFT_FRAME2 = 0x202D4C00,
263 PADDR_TOP_RIGHT_FRAME1 = 0x203D4C00,
264 PADDR_TOP_RIGHT_FRAME2 = 0x204D4C00,
265 PADDR_SUB_FRAME1 = 0x205D4C00,
266 PADDR_SUB_FRAME2 = 0x206D4C00,
267 // Physical addresses in FCRAM used by ARM9 applications
268/* PADDR_TOP_LEFT_FRAME1 = 0x20184E60,
269 PADDR_TOP_LEFT_FRAME2 = 0x201CB370,
270 PADDR_TOP_RIGHT_FRAME1 = 0x20282160,
271 PADDR_TOP_RIGHT_FRAME2 = 0x202C8670,
272 PADDR_SUB_FRAME1 = 0x202118E0,
273 PADDR_SUB_FRAME2 = 0x20249CF0,*/
274
275 // Physical addresses in VRAM
276 // TODO: These should just be deduced from the ones above
277 PADDR_VRAM_TOP_LEFT_FRAME1 = 0x181D4C00,
278 PADDR_VRAM_TOP_LEFT_FRAME2 = 0x182D4C00,
279 PADDR_VRAM_TOP_RIGHT_FRAME1 = 0x183D4C00,
280 PADDR_VRAM_TOP_RIGHT_FRAME2 = 0x184D4C00,
281 PADDR_VRAM_SUB_FRAME1 = 0x185D4C00,
282 PADDR_VRAM_SUB_FRAME2 = 0x186D4C00,
283 // Physical addresses in VRAM used by ARM9 applications
284/* PADDR_VRAM_TOP_LEFT_FRAME2 = 0x181CB370,
285 PADDR_VRAM_TOP_RIGHT_FRAME1 = 0x18282160,
286 PADDR_VRAM_TOP_RIGHT_FRAME2 = 0x182C8670,
287 PADDR_VRAM_SUB_FRAME1 = 0x182118E0,
288 PADDR_VRAM_SUB_FRAME2 = 0x18249CF0,*/
289};
290
291/// Framebuffer location
292enum FramebufferLocation {
293 FRAMEBUFFER_LOCATION_UNKNOWN, ///< Framebuffer location is unknown
294 FRAMEBUFFER_LOCATION_FCRAM, ///< Framebuffer is in the GSP heap
295 FRAMEBUFFER_LOCATION_VRAM, ///< Framebuffer is in VRAM
296};
297
298/**
299 * Sets whether the framebuffers are in the GSP heap (FCRAM) or VRAM
300 * @param
301 */
302void SetFramebufferLocation(const FramebufferLocation mode);
303
304/**
305 * Gets a read-only pointer to a framebuffer in memory
306 * @param address Physical address of framebuffer
307 * @return Returns const pointer to raw framebuffer
308 */
309const u8* GetFramebufferPointer(const u32 address);
310
311u32 GetFramebufferAddr(const u32 address);
312
313/**
314 * Gets the location of the framebuffers
315 */
316FramebufferLocation GetFramebufferLocation(u32 address);
317
318template <typename T> 252template <typename T>
319void Read(T &var, const u32 addr); 253void Read(T &var, const u32 addr);
320 254
diff --git a/src/core/mem_map.cpp b/src/core/mem_map.cpp
index c45746be9..14fc01471 100644
--- a/src/core/mem_map.cpp
+++ b/src/core/mem_map.cpp
@@ -72,14 +72,14 @@ void Init() {
72 72
73 g_base = MemoryMap_Setup(g_views, kNumMemViews, flags, &g_arena); 73 g_base = MemoryMap_Setup(g_views, kNumMemViews, flags, &g_arena);
74 74
75 NOTICE_LOG(MEMMAP, "initialized OK, RAM at %p (mirror at 0 @ %p)", g_heap, 75 NOTICE_LOG(MEMMAP, "initialized OK, RAM at %p (mirror at 0 @ %p)", g_heap,
76 g_physical_fcram); 76 g_physical_fcram);
77} 77}
78 78
79void Shutdown() { 79void Shutdown() {
80 u32 flags = 0; 80 u32 flags = 0;
81 MemoryMap_Shutdown(g_views, kNumMemViews, flags, &g_arena); 81 MemoryMap_Shutdown(g_views, kNumMemViews, flags, &g_arena);
82 82
83 g_arena.ReleaseSpace(); 83 g_arena.ReleaseSpace();
84 g_base = NULL; 84 g_base = NULL;
85 85
diff --git a/src/core/mem_map.h b/src/core/mem_map.h
index 12941f558..3c7810573 100644
--- a/src/core/mem_map.h
+++ b/src/core/mem_map.h
@@ -14,7 +14,6 @@ namespace Memory {
14enum { 14enum {
15 BOOTROM_SIZE = 0x00010000, ///< Bootrom (super secret code/data @ 0x8000) size 15 BOOTROM_SIZE = 0x00010000, ///< Bootrom (super secret code/data @ 0x8000) size
16 MPCORE_PRIV_SIZE = 0x00002000, ///< MPCore private memory region size 16 MPCORE_PRIV_SIZE = 0x00002000, ///< MPCore private memory region size
17 VRAM_SIZE = 0x00600000, ///< VRAM size
18 DSP_SIZE = 0x00080000, ///< DSP memory size 17 DSP_SIZE = 0x00080000, ///< DSP memory size
19 AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size 18 AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size
20 19
@@ -23,8 +22,6 @@ enum {
23 FCRAM_PADDR_END = (FCRAM_PADDR + FCRAM_SIZE), ///< FCRAM end of physical space 22 FCRAM_PADDR_END = (FCRAM_PADDR + FCRAM_SIZE), ///< FCRAM end of physical space
24 FCRAM_VADDR = 0x08000000, ///< FCRAM virtual address 23 FCRAM_VADDR = 0x08000000, ///< FCRAM virtual address
25 FCRAM_VADDR_END = (FCRAM_VADDR + FCRAM_SIZE), ///< FCRAM end of virtual space 24 FCRAM_VADDR_END = (FCRAM_VADDR + FCRAM_SIZE), ///< FCRAM end of virtual space
26 FCRAM_VADDR_FW0B = 0xF0000000, ///< FCRAM adress for firmare FW0B
27 FCRAM_VADDR_FW0B_END = (FCRAM_VADDR_FW0B + FCRAM_SIZE), ///< FCRAM adress end for FW0B
28 FCRAM_MASK = (FCRAM_SIZE - 1), ///< FCRAM mask 25 FCRAM_MASK = (FCRAM_SIZE - 1), ///< FCRAM mask
29 26
30 SHARED_MEMORY_SIZE = 0x04000000, ///< Shared memory size 27 SHARED_MEMORY_SIZE = 0x04000000, ///< Shared memory size
@@ -73,6 +70,7 @@ enum {
73 HARDWARE_IO_PADDR_END = (HARDWARE_IO_PADDR + HARDWARE_IO_SIZE), 70 HARDWARE_IO_PADDR_END = (HARDWARE_IO_PADDR + HARDWARE_IO_SIZE),
74 HARDWARE_IO_VADDR_END = (HARDWARE_IO_VADDR + HARDWARE_IO_SIZE), 71 HARDWARE_IO_VADDR_END = (HARDWARE_IO_VADDR + HARDWARE_IO_SIZE),
75 72
73 VRAM_SIZE = 0x00600000,
76 VRAM_PADDR = 0x18000000, 74 VRAM_PADDR = 0x18000000,
77 VRAM_VADDR = 0x1F000000, 75 VRAM_VADDR = 0x1F000000,
78 VRAM_PADDR_END = (VRAM_PADDR + VRAM_SIZE), 76 VRAM_PADDR_END = (VRAM_PADDR + VRAM_SIZE),
@@ -112,7 +110,7 @@ struct MemoryBlock {
112 110
113// In 64-bit, this might point to "high memory" (above the 32-bit limit), 111// In 64-bit, this might point to "high memory" (above the 32-bit limit),
114// so be sure to load it into a 64-bit register. 112// so be sure to load it into a 64-bit register.
115extern u8 *g_base; 113extern u8 *g_base;
116 114
117// These are guaranteed to point to "low memory" addresses (sub-32-bit). 115// These are guaranteed to point to "low memory" addresses (sub-32-bit).
118// 64-bit: Pointers to low-mem (sub-0x10000000) mirror 116// 64-bit: Pointers to low-mem (sub-0x10000000) mirror
@@ -147,7 +145,7 @@ void Write32(const u32 addr, const u32 data);
147 145
148void WriteBlock(const u32 addr, const u8* data, const int size); 146void WriteBlock(const u32 addr, const u8* data, const int size);
149 147
150u8* GetPointer(const u32 Address); 148u8* GetPointer(const u32 virtual_address);
151 149
152/** 150/**
153 * Maps a block of memory on the heap 151 * Maps a block of memory on the heap
@@ -169,16 +167,10 @@ inline const char* GetCharPointer(const u32 address) {
169 return (const char *)GetPointer(address); 167 return (const char *)GetPointer(address);
170} 168}
171 169
172inline const u32 VirtualAddressFromPhysical_FCRAM(const u32 address) { 170/// Converts a physical address to virtual address
173 return ((address & FCRAM_MASK) | FCRAM_VADDR); 171u32 PhysicalToVirtualAddress(const u32 addr);
174}
175
176inline const u32 VirtualAddressFromPhysical_IO(const u32 address) {
177 return (address + 0x0EB00000);
178}
179 172
180inline const u32 VirtualAddressFromPhysical_VRAM(const u32 address) { 173/// Converts a virtual address to physical address
181 return (address + 0x07000000); 174u32 VirtualToPhysicalAddress(const u32 addr);
182}
183 175
184} // namespace 176} // namespace
diff --git a/src/core/mem_map_funcs.cpp b/src/core/mem_map_funcs.cpp
index 305be8468..5772cca52 100644
--- a/src/core/mem_map_funcs.cpp
+++ b/src/core/mem_map_funcs.cpp
@@ -17,37 +17,44 @@ std::map<u32, MemoryBlock> g_heap_map;
17std::map<u32, MemoryBlock> g_heap_gsp_map; 17std::map<u32, MemoryBlock> g_heap_gsp_map;
18std::map<u32, MemoryBlock> g_shared_map; 18std::map<u32, MemoryBlock> g_shared_map;
19 19
20/// Convert a physical address (or firmware-specific virtual address) to primary virtual address 20/// Convert a physical address to virtual address
21u32 _VirtualAddress(const u32 addr) { 21u32 PhysicalToVirtualAddress(const u32 addr) {
22 // Our memory interface read/write functions assume virtual addresses. Put any physical address 22 // Our memory interface read/write functions assume virtual addresses. Put any physical address
23 // to virtual address translations here. This is obviously quite hacky... But we're not doing 23 // to virtual address translations here. This is quite hacky, but necessary until we implement
24 // any MMU emulation yet or anything 24 // proper MMU emulation.
25 if ((addr >= FCRAM_PADDR) && (addr < FCRAM_PADDR_END)) { 25 // TODO: Screw it, I'll let bunnei figure out how to do this properly.
26 return VirtualAddressFromPhysical_FCRAM(addr); 26 if ((addr >= VRAM_PADDR) && (addr < VRAM_PADDR_END)) {
27 27 return addr - VRAM_PADDR + VRAM_VADDR;
28 // Virtual address mapping FW0B 28 }else if ((addr >= FCRAM_PADDR) && (addr < FCRAM_PADDR_END)) {
29 } else if ((addr >= FCRAM_VADDR_FW0B) && (addr < FCRAM_VADDR_FW0B_END)) { 29 return addr - FCRAM_PADDR + FCRAM_VADDR;
30 return VirtualAddressFromPhysical_FCRAM(addr); 30 }
31 31
32 // Hardware IO 32 ERROR_LOG(MEMMAP, "Unknown physical address @ 0x%08x", addr);
33 // TODO(bunnei): FixMe 33 return addr;
34 // This isn't going to work... The physical address of HARDWARE_IO conflicts with the virtual 34}
35 // address of shared memory.
36 //} else if ((addr >= HARDWARE_IO_PADDR) && (addr < HARDWARE_IO_PADDR_END)) {
37 // return (addr + 0x0EB00000);
38 35
36/// Convert a physical address to virtual address
37u32 VirtualToPhysicalAddress(const u32 addr) {
38 // Our memory interface read/write functions assume virtual addresses. Put any physical address
39 // to virtual address translations here. This is quite hacky, but necessary until we implement
40 // proper MMU emulation.
41 // TODO: Screw it, I'll let bunnei figure out how to do this properly.
42 if ((addr >= VRAM_VADDR) && (addr < VRAM_VADDR_END)) {
43 return addr - 0x07000000;
44 } else if ((addr >= FCRAM_VADDR) && (addr < FCRAM_VADDR_END)) {
45 return addr - FCRAM_VADDR + FCRAM_PADDR;
39 } 46 }
47
48 ERROR_LOG(MEMMAP, "Unknown virtual address @ 0x%08x", addr);
40 return addr; 49 return addr;
41} 50}
42 51
43template <typename T> 52template <typename T>
44inline void Read(T &var, const u32 addr) { 53inline void Read(T &var, const u32 vaddr) {
45 // TODO: Figure out the fastest order of tests for both read and write (they are probably different). 54 // TODO: Figure out the fastest order of tests for both read and write (they are probably different).
46 // TODO: Make sure this represents the mirrors in a correct way. 55 // TODO: Make sure this represents the mirrors in a correct way.
47 // Could just do a base-relative read, too.... TODO 56 // Could just do a base-relative read, too.... TODO
48 57
49 const u32 vaddr = _VirtualAddress(addr);
50
51 // Kernel memory command buffer 58 // Kernel memory command buffer
52 if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) { 59 if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) {
53 var = *((const T*)&g_kernel_mem[vaddr & KERNEL_MEMORY_MASK]); 60 var = *((const T*)&g_kernel_mem[vaddr & KERNEL_MEMORY_MASK]);
@@ -91,9 +98,8 @@ inline void Read(T &var, const u32 addr) {
91} 98}
92 99
93template <typename T> 100template <typename T>
94inline void Write(u32 addr, const T data) { 101inline void Write(u32 vaddr, const T data) {
95 u32 vaddr = _VirtualAddress(addr); 102
96
97 // Kernel memory command buffer 103 // Kernel memory command buffer
98 if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) { 104 if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) {
99 *(T*)&g_kernel_mem[vaddr & KERNEL_MEMORY_MASK] = data; 105 *(T*)&g_kernel_mem[vaddr & KERNEL_MEMORY_MASK] = data;
@@ -133,16 +139,14 @@ inline void Write(u32 addr, const T data) {
133 // _assert_msg_(MEMMAP, false, "umimplemented write to Configuration Memory"); 139 // _assert_msg_(MEMMAP, false, "umimplemented write to Configuration Memory");
134 //} else if ((vaddr & 0xFFFFF000) == 0x1FF81000) { 140 //} else if ((vaddr & 0xFFFFF000) == 0x1FF81000) {
135 // _assert_msg_(MEMMAP, false, "umimplemented write to shared page"); 141 // _assert_msg_(MEMMAP, false, "umimplemented write to shared page");
136 142
137 // Error out... 143 // Error out...
138 } else { 144 } else {
139 ERROR_LOG(MEMMAP, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8, data, vaddr); 145 ERROR_LOG(MEMMAP, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8, data, vaddr);
140 } 146 }
141} 147}
142 148
143u8 *GetPointer(const u32 addr) { 149u8 *GetPointer(const u32 vaddr) {
144 const u32 vaddr = _VirtualAddress(addr);
145
146 // Kernel memory command buffer 150 // Kernel memory command buffer
147 if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) { 151 if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) {
148 return g_kernel_mem + (vaddr & KERNEL_MEMORY_MASK); 152 return g_kernel_mem + (vaddr & KERNEL_MEMORY_MASK);
@@ -185,12 +189,12 @@ u8 *GetPointer(const u32 addr) {
185 */ 189 */
186u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions) { 190u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions) {
187 MemoryBlock block; 191 MemoryBlock block;
188 192
189 block.base_address = HEAP_VADDR; 193 block.base_address = HEAP_VADDR;
190 block.size = size; 194 block.size = size;
191 block.operation = operation; 195 block.operation = operation;
192 block.permissions = permissions; 196 block.permissions = permissions;
193 197
194 if (g_heap_map.size() > 0) { 198 if (g_heap_map.size() > 0) {
195 const MemoryBlock last_block = g_heap_map.rbegin()->second; 199 const MemoryBlock last_block = g_heap_map.rbegin()->second;
196 block.address = last_block.address + last_block.size; 200 block.address = last_block.address + last_block.size;
@@ -208,12 +212,12 @@ u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions) {
208 */ 212 */
209u32 MapBlock_HeapGSP(u32 size, u32 operation, u32 permissions) { 213u32 MapBlock_HeapGSP(u32 size, u32 operation, u32 permissions) {
210 MemoryBlock block; 214 MemoryBlock block;
211 215
212 block.base_address = HEAP_GSP_VADDR; 216 block.base_address = HEAP_GSP_VADDR;
213 block.size = size; 217 block.size = size;
214 block.operation = operation; 218 block.operation = operation;
215 block.permissions = permissions; 219 block.permissions = permissions;
216 220
217 if (g_heap_gsp_map.size() > 0) { 221 if (g_heap_gsp_map.size() > 0) {
218 const MemoryBlock last_block = g_heap_gsp_map.rbegin()->second; 222 const MemoryBlock last_block = g_heap_gsp_map.rbegin()->second;
219 block.address = last_block.address + last_block.size; 223 block.address = last_block.address + last_block.size;
diff --git a/src/video_core/pica.h b/src/video_core/pica.h
index d64559d72..858335d44 100644
--- a/src/video_core/pica.h
+++ b/src/video_core/pica.h
@@ -45,7 +45,7 @@ struct Regs {
45 INSERT_PADDING_WORDS(0x41); 45 INSERT_PADDING_WORDS(0x41);
46 46
47 BitField<0, 24, u32> viewport_size_x; 47 BitField<0, 24, u32> viewport_size_x;
48 INSERT_PADDING_WORDS(1); 48 INSERT_PADDING_WORDS(0x1);
49 BitField<0, 24, u32> viewport_size_y; 49 BitField<0, 24, u32> viewport_size_y;
50 50
51 INSERT_PADDING_WORDS(0x1bc); 51 INSERT_PADDING_WORDS(0x1bc);
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 02b174562..f11a64fad 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -81,20 +81,20 @@ void RendererOpenGL::RenderXFB(const common::Rect& src_rect, const common::Rect&
81 const auto& framebuffer_top = GPU::g_regs.framebuffer_config[0]; 81 const auto& framebuffer_top = GPU::g_regs.framebuffer_config[0];
82 const auto& framebuffer_sub = GPU::g_regs.framebuffer_config[1]; 82 const auto& framebuffer_sub = GPU::g_regs.framebuffer_config[1];
83 const u32 active_fb_top = (framebuffer_top.active_fb == 1) 83 const u32 active_fb_top = (framebuffer_top.active_fb == 1)
84 ? framebuffer_top.address_left2 84 ? Memory::PhysicalToVirtualAddress(framebuffer_top.address_left2)
85 : framebuffer_top.address_left1; 85 : Memory::PhysicalToVirtualAddress(framebuffer_top.address_left1);
86 const u32 active_fb_sub = (framebuffer_sub.active_fb == 1) 86 const u32 active_fb_sub = (framebuffer_sub.active_fb == 1)
87 ? framebuffer_sub.address_left2 87 ? Memory::PhysicalToVirtualAddress(framebuffer_sub.address_left2)
88 : framebuffer_sub.address_left1; 88 : Memory::PhysicalToVirtualAddress(framebuffer_sub.address_left1);
89 89
90 DEBUG_LOG(GPU, "RenderXFB: 0x%08x bytes from 0x%08x(%dx%d), fmt %x", 90 DEBUG_LOG(GPU, "RenderXFB: 0x%08x bytes from 0x%08x(%dx%d), fmt %x",
91 framebuffer_top.stride * framebuffer_top.height, 91 framebuffer_top.stride * framebuffer_top.height,
92 GPU::GetFramebufferAddr(active_fb_top), (int)framebuffer_top.width, 92 active_fb_top, (int)framebuffer_top.width,
93 (int)framebuffer_top.height, (int)framebuffer_top.format); 93 (int)framebuffer_top.height, (int)framebuffer_top.format);
94 94
95 // TODO: This should consider the GPU registers for framebuffer width, height and stride. 95 // TODO: This should consider the GPU registers for framebuffer width, height and stride.
96 FlipFramebuffer(GPU::GetFramebufferPointer(active_fb_top), m_xfb_top_flipped); 96 FlipFramebuffer(Memory::GetPointer(active_fb_top), m_xfb_top_flipped);
97 FlipFramebuffer(GPU::GetFramebufferPointer(active_fb_sub), m_xfb_bottom_flipped); 97 FlipFramebuffer(Memory::GetPointer(active_fb_sub), m_xfb_bottom_flipped);
98 98
99 // Blit the top framebuffer 99 // Blit the top framebuffer
100 // ------------------------ 100 // ------------------------