From bd798390d5c3d1bf9084abe9839597162608f575 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Wed, 23 Jul 2014 14:42:15 +0200 Subject: GSP: Fix a major regression introduced in ffda035c, due to which no display transfers were triggered at all anymore. --- src/core/hle/service/gsp.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'src/core') diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp index 08e65612e..e2b0a48a7 100644 --- a/src/core/hle/service/gsp.cpp +++ b/src/core/hle/service/gsp.cpp @@ -32,7 +32,7 @@ static inline u8* GetCommandBuffer(u32 thread_id) { if (0 == g_shared_memory) return nullptr; - return Kernel::GetSharedMemoryPointer(g_shared_memory, + return Kernel::GetSharedMemoryPointer(g_shared_memory, 0x800 + (thread_id * sizeof(CommandBuffer))); } @@ -205,8 +205,16 @@ void ExecuteCommand(const Command& command) { break; } - // TODO: Check if texture copies are implemented correctly.. case CommandId::SET_DISPLAY_TRANSFER: + { + auto& params = command.image_copy; + WriteGPURegister(GPU_REG_INDEX(display_transfer_config.input_address), params.in_buffer_address >> 3); + WriteGPURegister(GPU_REG_INDEX(display_transfer_config.output_address), params.out_buffer_address >> 3); + WriteGPURegister(GPU_REG_INDEX(display_transfer_config.input_size), params.in_buffer_size); + WriteGPURegister(GPU_REG_INDEX(display_transfer_config.output_size), params.out_buffer_size); + WriteGPURegister(GPU_REG_INDEX(display_transfer_config.flags), params.flags); + WriteGPURegister(GPU_REG_INDEX(display_transfer_config.trigger), 1); + // TODO(bunnei): Signalling all of these interrupts here is totally wrong, but it seems to // work well enough for running demos. Need to figure out how these all work and trigger // them correctly. @@ -216,7 +224,9 @@ void ExecuteCommand(const Command& command) { SignalInterrupt(InterruptId::P3D); SignalInterrupt(InterruptId::DMA); break; + } + // TODO: Check if texture copies are implemented correctly.. case CommandId::SET_TEXTURE_COPY: { auto& params = command.image_copy; @@ -226,8 +236,7 @@ void ExecuteCommand(const Command& command) { WriteGPURegister(GPU_REG_INDEX(display_transfer_config.output_size), params.out_buffer_size); WriteGPURegister(GPU_REG_INDEX(display_transfer_config.flags), params.flags); - // TODO: Should this only be ORed with 1 for texture copies? - // trigger transfer + // TODO: Should this register be set to 1 or should instead its value be OR-ed with 1? WriteGPURegister(GPU_REG_INDEX(display_transfer_config.trigger), 1); break; } -- cgit v1.2.3 From 7b6a7d7dfb92d7a6d3537ea8b0339c2170d7eb84 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Sun, 3 Aug 2014 01:46:47 +0200 Subject: 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. --- src/core/hle/service/gsp.cpp | 18 ++-- src/core/hw/gpu.cpp | 102 ++++----------------- src/core/hw/gpu.h | 66 ------------- src/core/mem_map.cpp | 4 +- src/core/mem_map.h | 22 ++--- src/core/mem_map_funcs.cpp | 68 +++++++------- src/video_core/pica.h | 2 +- src/video_core/renderer_opengl/renderer_opengl.cpp | 14 +-- 8 files changed, 80 insertions(+), 216 deletions(-) (limited to 'src/core') 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) { case CommandId::SET_COMMAND_LIST_LAST: { auto& params = command.set_command_list_last; - WriteGPURegister(GPU_REG_INDEX(command_processor_config.address), params.address >> 3); + WriteGPURegister(GPU_REG_INDEX(command_processor_config.address), Memory::VirtualToPhysicalAddress(params.address) >> 3); WriteGPURegister(GPU_REG_INDEX(command_processor_config.size), params.size >> 3); // 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) { case CommandId::SET_MEMORY_FILL: { auto& params = command.memory_fill; - WriteGPURegister(GPU_REG_INDEX(memory_fill_config[0].address_start), params.start1 >> 3); - WriteGPURegister(GPU_REG_INDEX(memory_fill_config[0].address_end), params.end1 >> 3); + WriteGPURegister(GPU_REG_INDEX(memory_fill_config[0].address_start), Memory::VirtualToPhysicalAddress(params.start1) >> 3); + WriteGPURegister(GPU_REG_INDEX(memory_fill_config[0].address_end), Memory::VirtualToPhysicalAddress(params.end1) >> 3); WriteGPURegister(GPU_REG_INDEX(memory_fill_config[0].size), params.end1 - params.start1); WriteGPURegister(GPU_REG_INDEX(memory_fill_config[0].value), params.value1); - WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].address_start), params.start2 >> 3); - WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].address_end), params.end2 >> 3); + WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].address_start), Memory::VirtualToPhysicalAddress(params.start2) >> 3); + WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].address_end), Memory::VirtualToPhysicalAddress(params.end2) >> 3); WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].size), params.end2 - params.start2); WriteGPURegister(GPU_REG_INDEX(memory_fill_config[1].value), params.value2); break; @@ -208,8 +208,8 @@ void ExecuteCommand(const Command& command) { case CommandId::SET_DISPLAY_TRANSFER: { auto& params = command.image_copy; - WriteGPURegister(GPU_REG_INDEX(display_transfer_config.input_address), params.in_buffer_address >> 3); - WriteGPURegister(GPU_REG_INDEX(display_transfer_config.output_address), params.out_buffer_address >> 3); + WriteGPURegister(GPU_REG_INDEX(display_transfer_config.input_address), Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3); + WriteGPURegister(GPU_REG_INDEX(display_transfer_config.output_address), Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3); WriteGPURegister(GPU_REG_INDEX(display_transfer_config.input_size), params.in_buffer_size); WriteGPURegister(GPU_REG_INDEX(display_transfer_config.output_size), params.out_buffer_size); WriteGPURegister(GPU_REG_INDEX(display_transfer_config.flags), params.flags); @@ -230,8 +230,8 @@ void ExecuteCommand(const Command& command) { case CommandId::SET_TEXTURE_COPY: { auto& params = command.image_copy; - WriteGPURegister(GPU_REG_INDEX(display_transfer_config.input_address), params.in_buffer_address >> 3); - WriteGPURegister(GPU_REG_INDEX(display_transfer_config.output_address), params.out_buffer_address >> 3); + WriteGPURegister(GPU_REG_INDEX(display_transfer_config.input_address), Memory::VirtualToPhysicalAddress(params.in_buffer_address) >> 3); + WriteGPURegister(GPU_REG_INDEX(display_transfer_config.output_address), Memory::VirtualToPhysicalAddress(params.out_buffer_address) >> 3); WriteGPURegister(GPU_REG_INDEX(display_transfer_config.input_size), params.in_buffer_size); WriteGPURegister(GPU_REG_INDEX(display_transfer_config.output_size), params.out_buffer_size); 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; u32 g_cur_line = 0; ///< Current vertical screen line u64 g_last_line_ticks = 0; ///< CPU tick count from last vertical screen line -/** - * Sets whether the framebuffers are in the GSP heap (FCRAM) or VRAM - * @param - */ -void SetFramebufferLocation(const FramebufferLocation mode) { - switch (mode) { - case FRAMEBUFFER_LOCATION_FCRAM: - { - auto& framebuffer_top = g_regs.framebuffer_config[0]; - auto& framebuffer_sub = g_regs.framebuffer_config[1]; - - framebuffer_top.address_left1 = PADDR_TOP_LEFT_FRAME1; - framebuffer_top.address_left2 = PADDR_TOP_LEFT_FRAME2; - framebuffer_top.address_right1 = PADDR_TOP_RIGHT_FRAME1; - framebuffer_top.address_right2 = PADDR_TOP_RIGHT_FRAME2; - framebuffer_sub.address_left1 = PADDR_SUB_FRAME1; - //framebuffer_sub.address_left2 = unknown; - framebuffer_sub.address_right1 = PADDR_SUB_FRAME2; - //framebuffer_sub.address_right2 = unknown; - break; - } - - case FRAMEBUFFER_LOCATION_VRAM: - { - auto& framebuffer_top = g_regs.framebuffer_config[0]; - auto& framebuffer_sub = g_regs.framebuffer_config[1]; - - framebuffer_top.address_left1 = PADDR_VRAM_TOP_LEFT_FRAME1; - framebuffer_top.address_left2 = PADDR_VRAM_TOP_LEFT_FRAME2; - framebuffer_top.address_right1 = PADDR_VRAM_TOP_RIGHT_FRAME1; - framebuffer_top.address_right2 = PADDR_VRAM_TOP_RIGHT_FRAME2; - framebuffer_sub.address_left1 = PADDR_VRAM_SUB_FRAME1; - //framebuffer_sub.address_left2 = unknown; - framebuffer_sub.address_right1 = PADDR_VRAM_SUB_FRAME2; - //framebuffer_sub.address_right2 = unknown; - break; - } - } -} - -/** - * Gets the location of the framebuffers - * @return Location of framebuffers as FramebufferLocation enum - */ -FramebufferLocation GetFramebufferLocation(u32 address) { - if ((address & ~Memory::VRAM_MASK) == Memory::VRAM_PADDR) { - return FRAMEBUFFER_LOCATION_VRAM; - } else if ((address & ~Memory::FCRAM_MASK) == Memory::FCRAM_PADDR) { - return FRAMEBUFFER_LOCATION_FCRAM; - } else { - ERROR_LOG(GPU, "unknown framebuffer location!"); - } - return FRAMEBUFFER_LOCATION_UNKNOWN; -} - -u32 GetFramebufferAddr(const u32 address) { - switch (GetFramebufferLocation(address)) { - case FRAMEBUFFER_LOCATION_FCRAM: - return Memory::VirtualAddressFromPhysical_FCRAM(address); - case FRAMEBUFFER_LOCATION_VRAM: - return Memory::VirtualAddressFromPhysical_VRAM(address); - default: - ERROR_LOG(GPU, "unknown framebuffer location"); - } - return 0; -} - -/** - * Gets a read-only pointer to a framebuffer in memory - * @param address Physical address of framebuffer - * @return Returns const pointer to raw framebuffer - */ -const u8* GetFramebufferPointer(const u32 address) { - u32 addr = GetFramebufferAddr(address); - return (addr != 0) ? Memory::GetPointer(addr) : nullptr; -} - template inline void Read(T &var, const u32 raw_addr) { u32 addr = raw_addr - 0x1EF00000; @@ -141,8 +64,8 @@ inline void Write(u32 addr, const T data) { // TODO: Not sure if this check should be done at GSP level instead if (config.address_start) { // TODO: Not sure if this algorithm is correct, particularly because it doesn't use the size member at all - u32* start = (u32*)Memory::GetPointer(config.GetStartAddress()); - u32* end = (u32*)Memory::GetPointer(config.GetEndAddress()); + u32* start = (u32*)Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetStartAddress())); + u32* end = (u32*)Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetEndAddress())); for (u32* ptr = start; ptr < end; ++ptr) *ptr = bswap32(config.value); // TODO: This is just a workaround to missing framebuffer format emulation @@ -155,8 +78,8 @@ inline void Write(u32 addr, const T data) { { const auto& config = g_regs.display_transfer_config; if (config.trigger & 1) { - u8* source_pointer = Memory::GetPointer(config.GetPhysicalInputAddress()); - u8* dest_pointer = Memory::GetPointer(config.GetPhysicalOutputAddress()); + u8* source_pointer = Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalInputAddress())); + u8* dest_pointer = Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalOutputAddress())); for (int y = 0; y < config.output_height; ++y) { // TODO: Why does the register seem to hold twice the framebuffer width? @@ -276,11 +199,22 @@ void Init() { g_cur_line = 0; g_last_line_ticks = Core::g_app_core->GetTicks(); -// SetFramebufferLocation(FRAMEBUFFER_LOCATION_FCRAM); - SetFramebufferLocation(FRAMEBUFFER_LOCATION_VRAM); - auto& framebuffer_top = g_regs.framebuffer_config[0]; auto& framebuffer_sub = g_regs.framebuffer_config[1]; + + // Setup default framebuffer addresses (located in VRAM) + // .. or at least these are the ones used by system applets. + // There's probably a smarter way to come up with addresses + // like this which does not require hardcoding. + framebuffer_top.address_left1 = 0x181E6000; + framebuffer_top.address_left2 = 0x1822C800; + framebuffer_top.address_right1 = 0x18273000; + framebuffer_top.address_right2 = 0x182B9800; + framebuffer_sub.address_left1 = 0x1848F000; + //framebuffer_sub.address_left2 = unknown; + framebuffer_sub.address_right1 = 0x184C7800; + //framebuffer_sub.address_right2 = unknown; + // TODO: Width should be 240 instead? framebuffer_top.width = 480; 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 extern Regs g_regs; -enum { - TOP_ASPECT_X = 0x5, - TOP_ASPECT_Y = 0x3, - - TOP_HEIGHT = 240, - TOP_WIDTH = 400, - BOTTOM_WIDTH = 320, - - // Physical addresses in FCRAM (chosen arbitrarily) - PADDR_TOP_LEFT_FRAME1 = 0x201D4C00, - PADDR_TOP_LEFT_FRAME2 = 0x202D4C00, - PADDR_TOP_RIGHT_FRAME1 = 0x203D4C00, - PADDR_TOP_RIGHT_FRAME2 = 0x204D4C00, - PADDR_SUB_FRAME1 = 0x205D4C00, - PADDR_SUB_FRAME2 = 0x206D4C00, - // Physical addresses in FCRAM used by ARM9 applications -/* PADDR_TOP_LEFT_FRAME1 = 0x20184E60, - PADDR_TOP_LEFT_FRAME2 = 0x201CB370, - PADDR_TOP_RIGHT_FRAME1 = 0x20282160, - PADDR_TOP_RIGHT_FRAME2 = 0x202C8670, - PADDR_SUB_FRAME1 = 0x202118E0, - PADDR_SUB_FRAME2 = 0x20249CF0,*/ - - // Physical addresses in VRAM - // TODO: These should just be deduced from the ones above - PADDR_VRAM_TOP_LEFT_FRAME1 = 0x181D4C00, - PADDR_VRAM_TOP_LEFT_FRAME2 = 0x182D4C00, - PADDR_VRAM_TOP_RIGHT_FRAME1 = 0x183D4C00, - PADDR_VRAM_TOP_RIGHT_FRAME2 = 0x184D4C00, - PADDR_VRAM_SUB_FRAME1 = 0x185D4C00, - PADDR_VRAM_SUB_FRAME2 = 0x186D4C00, - // Physical addresses in VRAM used by ARM9 applications -/* PADDR_VRAM_TOP_LEFT_FRAME2 = 0x181CB370, - PADDR_VRAM_TOP_RIGHT_FRAME1 = 0x18282160, - PADDR_VRAM_TOP_RIGHT_FRAME2 = 0x182C8670, - PADDR_VRAM_SUB_FRAME1 = 0x182118E0, - PADDR_VRAM_SUB_FRAME2 = 0x18249CF0,*/ -}; - -/// Framebuffer location -enum FramebufferLocation { - FRAMEBUFFER_LOCATION_UNKNOWN, ///< Framebuffer location is unknown - FRAMEBUFFER_LOCATION_FCRAM, ///< Framebuffer is in the GSP heap - FRAMEBUFFER_LOCATION_VRAM, ///< Framebuffer is in VRAM -}; - -/** - * Sets whether the framebuffers are in the GSP heap (FCRAM) or VRAM - * @param - */ -void SetFramebufferLocation(const FramebufferLocation mode); - -/** - * Gets a read-only pointer to a framebuffer in memory - * @param address Physical address of framebuffer - * @return Returns const pointer to raw framebuffer - */ -const u8* GetFramebufferPointer(const u32 address); - -u32 GetFramebufferAddr(const u32 address); - -/** - * Gets the location of the framebuffers - */ -FramebufferLocation GetFramebufferLocation(u32 address); - template void Read(T &var, const u32 addr); 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() { g_base = MemoryMap_Setup(g_views, kNumMemViews, flags, &g_arena); - NOTICE_LOG(MEMMAP, "initialized OK, RAM at %p (mirror at 0 @ %p)", g_heap, + NOTICE_LOG(MEMMAP, "initialized OK, RAM at %p (mirror at 0 @ %p)", g_heap, g_physical_fcram); } void Shutdown() { u32 flags = 0; MemoryMap_Shutdown(g_views, kNumMemViews, flags, &g_arena); - + g_arena.ReleaseSpace(); g_base = NULL; 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 { enum { BOOTROM_SIZE = 0x00010000, ///< Bootrom (super secret code/data @ 0x8000) size MPCORE_PRIV_SIZE = 0x00002000, ///< MPCore private memory region size - VRAM_SIZE = 0x00600000, ///< VRAM size DSP_SIZE = 0x00080000, ///< DSP memory size AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size @@ -23,8 +22,6 @@ enum { FCRAM_PADDR_END = (FCRAM_PADDR + FCRAM_SIZE), ///< FCRAM end of physical space FCRAM_VADDR = 0x08000000, ///< FCRAM virtual address FCRAM_VADDR_END = (FCRAM_VADDR + FCRAM_SIZE), ///< FCRAM end of virtual space - FCRAM_VADDR_FW0B = 0xF0000000, ///< FCRAM adress for firmare FW0B - FCRAM_VADDR_FW0B_END = (FCRAM_VADDR_FW0B + FCRAM_SIZE), ///< FCRAM adress end for FW0B FCRAM_MASK = (FCRAM_SIZE - 1), ///< FCRAM mask SHARED_MEMORY_SIZE = 0x04000000, ///< Shared memory size @@ -73,6 +70,7 @@ enum { HARDWARE_IO_PADDR_END = (HARDWARE_IO_PADDR + HARDWARE_IO_SIZE), HARDWARE_IO_VADDR_END = (HARDWARE_IO_VADDR + HARDWARE_IO_SIZE), + VRAM_SIZE = 0x00600000, VRAM_PADDR = 0x18000000, VRAM_VADDR = 0x1F000000, VRAM_PADDR_END = (VRAM_PADDR + VRAM_SIZE), @@ -112,7 +110,7 @@ struct MemoryBlock { // In 64-bit, this might point to "high memory" (above the 32-bit limit), // so be sure to load it into a 64-bit register. -extern u8 *g_base; +extern u8 *g_base; // These are guaranteed to point to "low memory" addresses (sub-32-bit). // 64-bit: Pointers to low-mem (sub-0x10000000) mirror @@ -147,7 +145,7 @@ void Write32(const u32 addr, const u32 data); void WriteBlock(const u32 addr, const u8* data, const int size); -u8* GetPointer(const u32 Address); +u8* GetPointer(const u32 virtual_address); /** * Maps a block of memory on the heap @@ -169,16 +167,10 @@ inline const char* GetCharPointer(const u32 address) { return (const char *)GetPointer(address); } -inline const u32 VirtualAddressFromPhysical_FCRAM(const u32 address) { - return ((address & FCRAM_MASK) | FCRAM_VADDR); -} - -inline const u32 VirtualAddressFromPhysical_IO(const u32 address) { - return (address + 0x0EB00000); -} +/// Converts a physical address to virtual address +u32 PhysicalToVirtualAddress(const u32 addr); -inline const u32 VirtualAddressFromPhysical_VRAM(const u32 address) { - return (address + 0x07000000); -} +/// Converts a virtual address to physical address +u32 VirtualToPhysicalAddress(const u32 addr); } // 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 g_heap_map; std::map g_heap_gsp_map; std::map g_shared_map; -/// Convert a physical address (or firmware-specific virtual address) to primary virtual address -u32 _VirtualAddress(const u32 addr) { - // Our memory interface read/write functions assume virtual addresses. Put any physical address - // to virtual address translations here. This is obviously quite hacky... But we're not doing - // any MMU emulation yet or anything - if ((addr >= FCRAM_PADDR) && (addr < FCRAM_PADDR_END)) { - return VirtualAddressFromPhysical_FCRAM(addr); - - // Virtual address mapping FW0B - } else if ((addr >= FCRAM_VADDR_FW0B) && (addr < FCRAM_VADDR_FW0B_END)) { - return VirtualAddressFromPhysical_FCRAM(addr); - - // Hardware IO - // TODO(bunnei): FixMe - // This isn't going to work... The physical address of HARDWARE_IO conflicts with the virtual - // address of shared memory. - //} else if ((addr >= HARDWARE_IO_PADDR) && (addr < HARDWARE_IO_PADDR_END)) { - // return (addr + 0x0EB00000); +/// Convert a physical address to virtual address +u32 PhysicalToVirtualAddress(const u32 addr) { + // Our memory interface read/write functions assume virtual addresses. Put any physical address + // to virtual address translations here. This is quite hacky, but necessary until we implement + // proper MMU emulation. + // TODO: Screw it, I'll let bunnei figure out how to do this properly. + if ((addr >= VRAM_PADDR) && (addr < VRAM_PADDR_END)) { + return addr - VRAM_PADDR + VRAM_VADDR; + }else if ((addr >= FCRAM_PADDR) && (addr < FCRAM_PADDR_END)) { + return addr - FCRAM_PADDR + FCRAM_VADDR; + } + + ERROR_LOG(MEMMAP, "Unknown physical address @ 0x%08x", addr); + return addr; +} +/// Convert a physical address to virtual address +u32 VirtualToPhysicalAddress(const u32 addr) { + // Our memory interface read/write functions assume virtual addresses. Put any physical address + // to virtual address translations here. This is quite hacky, but necessary until we implement + // proper MMU emulation. + // TODO: Screw it, I'll let bunnei figure out how to do this properly. + if ((addr >= VRAM_VADDR) && (addr < VRAM_VADDR_END)) { + return addr - 0x07000000; + } else if ((addr >= FCRAM_VADDR) && (addr < FCRAM_VADDR_END)) { + return addr - FCRAM_VADDR + FCRAM_PADDR; } + + ERROR_LOG(MEMMAP, "Unknown virtual address @ 0x%08x", addr); return addr; } template -inline void Read(T &var, const u32 addr) { +inline void Read(T &var, const u32 vaddr) { // TODO: Figure out the fastest order of tests for both read and write (they are probably different). // TODO: Make sure this represents the mirrors in a correct way. // Could just do a base-relative read, too.... TODO - const u32 vaddr = _VirtualAddress(addr); - // Kernel memory command buffer if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) { var = *((const T*)&g_kernel_mem[vaddr & KERNEL_MEMORY_MASK]); @@ -91,9 +98,8 @@ inline void Read(T &var, const u32 addr) { } template -inline void Write(u32 addr, const T data) { - u32 vaddr = _VirtualAddress(addr); - +inline void Write(u32 vaddr, const T data) { + // Kernel memory command buffer if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) { *(T*)&g_kernel_mem[vaddr & KERNEL_MEMORY_MASK] = data; @@ -133,16 +139,14 @@ inline void Write(u32 addr, const T data) { // _assert_msg_(MEMMAP, false, "umimplemented write to Configuration Memory"); //} else if ((vaddr & 0xFFFFF000) == 0x1FF81000) { // _assert_msg_(MEMMAP, false, "umimplemented write to shared page"); - + // Error out... } else { ERROR_LOG(MEMMAP, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8, data, vaddr); } } -u8 *GetPointer(const u32 addr) { - const u32 vaddr = _VirtualAddress(addr); - +u8 *GetPointer(const u32 vaddr) { // Kernel memory command buffer if (vaddr >= KERNEL_MEMORY_VADDR && vaddr < KERNEL_MEMORY_VADDR_END) { return g_kernel_mem + (vaddr & KERNEL_MEMORY_MASK); @@ -185,12 +189,12 @@ u8 *GetPointer(const u32 addr) { */ u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions) { MemoryBlock block; - + block.base_address = HEAP_VADDR; block.size = size; block.operation = operation; block.permissions = permissions; - + if (g_heap_map.size() > 0) { const MemoryBlock last_block = g_heap_map.rbegin()->second; block.address = last_block.address + last_block.size; @@ -208,12 +212,12 @@ u32 MapBlock_Heap(u32 size, u32 operation, u32 permissions) { */ u32 MapBlock_HeapGSP(u32 size, u32 operation, u32 permissions) { MemoryBlock block; - + block.base_address = HEAP_GSP_VADDR; block.size = size; block.operation = operation; block.permissions = permissions; - + if (g_heap_gsp_map.size() > 0) { const MemoryBlock last_block = g_heap_gsp_map.rbegin()->second; 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 { INSERT_PADDING_WORDS(0x41); BitField<0, 24, u32> viewport_size_x; - INSERT_PADDING_WORDS(1); + INSERT_PADDING_WORDS(0x1); BitField<0, 24, u32> viewport_size_y; 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& const auto& framebuffer_top = GPU::g_regs.framebuffer_config[0]; const auto& framebuffer_sub = GPU::g_regs.framebuffer_config[1]; const u32 active_fb_top = (framebuffer_top.active_fb == 1) - ? framebuffer_top.address_left2 - : framebuffer_top.address_left1; + ? Memory::PhysicalToVirtualAddress(framebuffer_top.address_left2) + : Memory::PhysicalToVirtualAddress(framebuffer_top.address_left1); const u32 active_fb_sub = (framebuffer_sub.active_fb == 1) - ? framebuffer_sub.address_left2 - : framebuffer_sub.address_left1; + ? Memory::PhysicalToVirtualAddress(framebuffer_sub.address_left2) + : Memory::PhysicalToVirtualAddress(framebuffer_sub.address_left1); DEBUG_LOG(GPU, "RenderXFB: 0x%08x bytes from 0x%08x(%dx%d), fmt %x", framebuffer_top.stride * framebuffer_top.height, - GPU::GetFramebufferAddr(active_fb_top), (int)framebuffer_top.width, + active_fb_top, (int)framebuffer_top.width, (int)framebuffer_top.height, (int)framebuffer_top.format); // TODO: This should consider the GPU registers for framebuffer width, height and stride. - FlipFramebuffer(GPU::GetFramebufferPointer(active_fb_top), m_xfb_top_flipped); - FlipFramebuffer(GPU::GetFramebufferPointer(active_fb_sub), m_xfb_bottom_flipped); + FlipFramebuffer(Memory::GetPointer(active_fb_top), m_xfb_top_flipped); + FlipFramebuffer(Memory::GetPointer(active_fb_sub), m_xfb_bottom_flipped); // Blit the top framebuffer // ------------------------ -- cgit v1.2.3 From 76a586de4952df6d8dd9db9d97716c00690cebdd Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Sat, 26 Jul 2014 14:42:46 +0200 Subject: Pica: Add command processor. --- src/citra_qt/debugger/graphics_cmdlists.cpp | 2 +- src/core/hw/gpu.cpp | 8 ++-- src/video_core/CMakeLists.txt | 7 +++- src/video_core/command_processor.cpp | 60 +++++++++++++++++++++++++++++ src/video_core/command_processor.h | 31 +++++++++++++++ src/video_core/gpu_debugger.h | 8 ++-- src/video_core/pica.h | 2 + src/video_core/video_core.vcxproj | 2 + src/video_core/video_core.vcxproj.filters | 2 + 9 files changed, 113 insertions(+), 9 deletions(-) create mode 100644 src/video_core/command_processor.cpp create mode 100644 src/video_core/command_processor.h (limited to 'src/core') diff --git a/src/citra_qt/debugger/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics_cmdlists.cpp index 30b8b5dae..e98560a19 100644 --- a/src/citra_qt/debugger/graphics_cmdlists.cpp +++ b/src/citra_qt/debugger/graphics_cmdlists.cpp @@ -78,7 +78,7 @@ QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const // index refers to a specific command const GraphicsDebugger::PicaCommandList& cmdlist = command_lists[item->parent->index].second; const GraphicsDebugger::PicaCommand& cmd = cmdlist[item->index]; - const Pica::CommandHeader& header = cmd.GetHeader(); + const Pica::CommandProcessor::CommandHeader& header = cmd.GetHeader(); if (role == Qt::DisplayRole) { QString content; diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index 591997aa3..87cf93bac 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp @@ -14,6 +14,7 @@ #include "core/hw/gpu.h" +#include "video_core/command_processor.h" #include "video_core/video_core.h" @@ -143,14 +144,15 @@ inline void Write(u32 addr, const T data) { break; } + // Seems like writing to this register triggers processing case GPU_REG_INDEX(command_processor_config.trigger): { const auto& config = g_regs.command_processor_config; if (config.trigger & 1) { - // u32* buffer = (u32*)Memory::GetPointer(config.GetPhysicalAddress()); - ERROR_LOG(GPU, "Beginning 0x%08x bytes of commands from address 0x%08x", config.size, config.GetPhysicalAddress()); - // TODO: Process command list! + u32* buffer = (u32*)Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalAddress())); + u32 size = config.size << 3; + Pica::CommandProcessor::ProcessCommandList(buffer, size); } break; } diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 2503b9d18..8977c8dca 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -1,11 +1,14 @@ -set(SRCS video_core.cpp +set(SRCS command_processor.cpp utils.cpp + video_core.cpp renderer_opengl/renderer_opengl.cpp) -set(HEADERS math.h +set(HEADERS command_processor.h + math.h utils.h video_core.h renderer_base.h + video_core.h renderer_opengl/renderer_opengl.h) add_library(video_core STATIC ${SRCS} ${HEADERS}) diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp new file mode 100644 index 000000000..515c407ea --- /dev/null +++ b/src/video_core/command_processor.cpp @@ -0,0 +1,60 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#include "pica.h" +#include "command_processor.h" + + +namespace Pica { + +Regs registers; + +namespace CommandProcessor { + +static inline void WritePicaReg(u32 id, u32 value) { + u32 old_value = registers[id]; + registers[id] = value; + + switch(id) { + // TODO: Perform actions for anything which requires special treatment here... + + default: + break; + } +} + +static std::ptrdiff_t ExecuteCommandBlock(const u32* first_command_word) { + const CommandHeader& header = *(const CommandHeader*)(&first_command_word[1]); + + u32* read_pointer = (u32*)first_command_word; + + // TODO: Take parameter mask into consideration! + + WritePicaReg(header.cmd_id, *read_pointer); + read_pointer += 2; + + for (int i = 1; i < 1+header.extra_data_length; ++i) { + u32 cmd = header.cmd_id + ((header.group_commands) ? i : 0); + WritePicaReg(cmd, *read_pointer); + ++read_pointer; + } + + // align read pointer to 8 bytes + if ((first_command_word - read_pointer) % 2) + ++read_pointer; + + return read_pointer - first_command_word; +} + +void ProcessCommandList(const u32* list, u32 size) { + u32* read_pointer = (u32*)list; + + while (read_pointer < list + size) { + read_pointer += ExecuteCommandBlock(read_pointer); + } +} + +} // namespace + +} // namespace diff --git a/src/video_core/command_processor.h b/src/video_core/command_processor.h new file mode 100644 index 000000000..6b6241a25 --- /dev/null +++ b/src/video_core/command_processor.h @@ -0,0 +1,31 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 +// Refer to the license.txt file included. + +#pragma once + +#include "common/bit_field.h" +#include "common/common_types.h" + +#include "pica.h" + +namespace Pica { + +namespace CommandProcessor { + +union CommandHeader { + u32 hex; + + BitField< 0, 16, u32> cmd_id; + BitField<16, 4, u32> parameter_mask; + BitField<20, 11, u32> extra_data_length; + BitField<31, 1, u32> group_commands; +}; +static_assert(std::is_standard_layout::value == true, "CommandHeader does not use standard layout"); +static_assert(sizeof(CommandHeader) == sizeof(u32), "CommandHeader has incorrect size!"); + +void ProcessCommandList(const u32* list, u32 size); + +} // namespace + +} // namespace diff --git a/src/video_core/gpu_debugger.h b/src/video_core/gpu_debugger.h index 5d85f90b9..2ba873457 100644 --- a/src/video_core/gpu_debugger.h +++ b/src/video_core/gpu_debugger.h @@ -11,6 +11,8 @@ #include "common/log.h" #include "core/hle/service/gsp.h" + +#include "command_processor.h" #include "pica.h" class GraphicsDebugger @@ -20,10 +22,10 @@ public: // A vector of commands represented by their raw byte sequence struct PicaCommand : public std::vector { - const Pica::CommandHeader& GetHeader() const + const Pica::CommandProcessor::CommandHeader& GetHeader() const { const u32& val = at(1); - return *(Pica::CommandHeader*)&val; + return *(Pica::CommandProcessor::CommandHeader*)&val; } }; @@ -99,7 +101,7 @@ public: PicaCommandList cmdlist; for (u32* parse_pointer = command_list; parse_pointer < command_list + size_in_words;) { - const Pica::CommandHeader header = static_cast(parse_pointer[1]); + const Pica::CommandProcessor::CommandHeader& header = *(Pica::CommandProcessor::CommandHeader*)(&parse_pointer[1]); cmdlist.push_back(PicaCommand()); auto& cmd = cmdlist.back(); diff --git a/src/video_core/pica.h b/src/video_core/pica.h index 24b39a3ad..0e231c6c9 100644 --- a/src/video_core/pica.h +++ b/src/video_core/pica.h @@ -161,6 +161,8 @@ ASSERT_REG_POSITION(vertex_descriptor, 0x200); // The total number of registers is chosen arbitrarily, but let's make sure it's not some odd value anyway. static_assert(sizeof(Regs) == 0x300 * sizeof(u32), "Invalid total size of register set"); +extern Regs registers; // TODO: Not sure if we want to have one global instance for this + struct float24 { static float24 FromFloat32(float val) { diff --git a/src/video_core/video_core.vcxproj b/src/video_core/video_core.vcxproj index 2dbfc68dd..28eb21284 100644 --- a/src/video_core/video_core.vcxproj +++ b/src/video_core/video_core.vcxproj @@ -20,10 +20,12 @@ + + diff --git a/src/video_core/video_core.vcxproj.filters b/src/video_core/video_core.vcxproj.filters index b42823d2a..713458fcf 100644 --- a/src/video_core/video_core.vcxproj.filters +++ b/src/video_core/video_core.vcxproj.filters @@ -9,6 +9,7 @@ renderer_opengl + @@ -16,6 +17,7 @@ renderer_opengl + -- cgit v1.2.3