mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	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.
This commit is contained in:
		
							parent
							
								
									bd798390d5
								
							
						
					
					
						commit
						7b6a7d7dfb
					
				
					 8 changed files with 81 additions and 217 deletions
				
			
		|  | @ -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); | ||||
|  |  | |||
|  | @ -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 <typename T> | ||||
| 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; | ||||
|  |  | |||
|  | @ -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 <typename T> | ||||
| void Read(T &var, const u32 addr); | ||||
| 
 | ||||
|  |  | |||
|  | @ -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; | ||||
| 
 | ||||
|  |  | |||
|  | @ -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); | ||||
| } | ||||
| /// Converts a physical address to virtual address
 | ||||
| u32 PhysicalToVirtualAddress(const u32 addr); | ||||
| 
 | ||||
| inline const u32 VirtualAddressFromPhysical_IO(const u32 address) { | ||||
|     return (address + 0x0EB00000); | ||||
| } | ||||
| 
 | ||||
| inline const u32 VirtualAddressFromPhysical_VRAM(const u32 address) { | ||||
|     return (address + 0x07000000); | ||||
| } | ||||
| /// Converts a virtual address to physical address
 | ||||
| u32 VirtualToPhysicalAddress(const u32 addr); | ||||
| 
 | ||||
| } // namespace
 | ||||
|  |  | |||
|  | @ -17,37 +17,44 @@ std::map<u32, MemoryBlock> g_heap_map; | |||
| std::map<u32, MemoryBlock> g_heap_gsp_map; | ||||
| std::map<u32, MemoryBlock> 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 <typename T> | ||||
| 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 <typename T> | ||||
| 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; | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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
 | ||||
|     // ------------------------
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue