diff options
| author | 2014-08-03 01:46:47 +0200 | |
|---|---|---|
| committer | 2014-08-12 13:32:56 +0200 | |
| commit | 7b6a7d7dfb92d7a6d3537ea8b0339c2170d7eb84 (patch) | |
| tree | 2b005f3358a228136e7711ddac790ed54bb67b1f /src/core/hw/gpu.cpp | |
| 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/core/hw/gpu.cpp')
| -rw-r--r-- | src/core/hw/gpu.cpp | 102 |
1 files changed, 18 insertions, 84 deletions
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; |