diff options
| author | 2014-08-03 01:46:47 +0200 | |
|---|---|---|
| committer | 2014-08-12 13:32:56 +0200 | |
| commit | 7b6a7d7dfb92d7a6d3537ea8b0339c2170d7eb84 (patch) | |
| tree | 2b005f3358a228136e7711ddac790ed54bb67b1f /src | |
| parent | GSP: Fix a major regression introduced in ffda035c, due to which no display t... (diff) | |
| download | yuzu-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.cpp | 18 | ||||
| -rw-r--r-- | src/core/hw/gpu.cpp | 102 | ||||
| -rw-r--r-- | src/core/hw/gpu.h | 66 | ||||
| -rw-r--r-- | src/core/mem_map.cpp | 4 | ||||
| -rw-r--r-- | src/core/mem_map.h | 22 | ||||
| -rw-r--r-- | src/core/mem_map_funcs.cpp | 68 | ||||
| -rw-r--r-- | src/video_core/pica.h | 2 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 14 |
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; | |||
| 24 | u32 g_cur_line = 0; ///< Current vertical screen line | 24 | u32 g_cur_line = 0; ///< Current vertical screen line |
| 25 | u64 g_last_line_ticks = 0; ///< CPU tick count from last vertical screen line | 25 | u64 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 | */ | ||
| 31 | void 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 | */ | ||
| 71 | FramebufferLocation 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 | |||
| 82 | u32 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 | */ | ||
| 99 | const u8* GetFramebufferPointer(const u32 address) { | ||
| 100 | u32 addr = GetFramebufferAddr(address); | ||
| 101 | return (addr != 0) ? Memory::GetPointer(addr) : nullptr; | ||
| 102 | } | ||
| 103 | |||
| 104 | template <typename T> | 27 | template <typename T> |
| 105 | inline void Read(T &var, const u32 raw_addr) { | 28 | inline 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 | ||
| 250 | extern Regs g_regs; | 250 | extern Regs g_regs; |
| 251 | 251 | ||
| 252 | enum { | ||
| 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 | ||
| 292 | enum 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 | */ | ||
| 302 | void 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 | */ | ||
| 309 | const u8* GetFramebufferPointer(const u32 address); | ||
| 310 | |||
| 311 | u32 GetFramebufferAddr(const u32 address); | ||
| 312 | |||
| 313 | /** | ||
| 314 | * Gets the location of the framebuffers | ||
| 315 | */ | ||
| 316 | FramebufferLocation GetFramebufferLocation(u32 address); | ||
| 317 | |||
| 318 | template <typename T> | 252 | template <typename T> |
| 319 | void Read(T &var, const u32 addr); | 253 | void 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 | ||
| 79 | void Shutdown() { | 79 | void 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 { | |||
| 14 | enum { | 14 | enum { |
| 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. |
| 115 | extern u8 *g_base; | 113 | extern 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 | ||
| 148 | void WriteBlock(const u32 addr, const u8* data, const int size); | 146 | void WriteBlock(const u32 addr, const u8* data, const int size); |
| 149 | 147 | ||
| 150 | u8* GetPointer(const u32 Address); | 148 | u8* 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 | ||
| 172 | inline const u32 VirtualAddressFromPhysical_FCRAM(const u32 address) { | 170 | /// Converts a physical address to virtual address |
| 173 | return ((address & FCRAM_MASK) | FCRAM_VADDR); | 171 | u32 PhysicalToVirtualAddress(const u32 addr); |
| 174 | } | ||
| 175 | |||
| 176 | inline const u32 VirtualAddressFromPhysical_IO(const u32 address) { | ||
| 177 | return (address + 0x0EB00000); | ||
| 178 | } | ||
| 179 | 172 | ||
| 180 | inline const u32 VirtualAddressFromPhysical_VRAM(const u32 address) { | 173 | /// Converts a virtual address to physical address |
| 181 | return (address + 0x07000000); | 174 | u32 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; | |||
| 17 | std::map<u32, MemoryBlock> g_heap_gsp_map; | 17 | std::map<u32, MemoryBlock> g_heap_gsp_map; |
| 18 | std::map<u32, MemoryBlock> g_shared_map; | 18 | std::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 |
| 21 | u32 _VirtualAddress(const u32 addr) { | 21 | u32 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 | ||
| 37 | u32 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 | ||
| 43 | template <typename T> | 52 | template <typename T> |
| 44 | inline void Read(T &var, const u32 addr) { | 53 | inline 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 | ||
| 93 | template <typename T> | 100 | template <typename T> |
| 94 | inline void Write(u32 addr, const T data) { | 101 | inline 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 | ||
| 143 | u8 *GetPointer(const u32 addr) { | 149 | u8 *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 | */ |
| 186 | u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions) { | 190 | u32 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 | */ |
| 209 | u32 MapBlock_HeapGSP(u32 size, u32 operation, u32 permissions) { | 213 | u32 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 | // ------------------------ |