mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	GSP: Implement ReadHWRegs and WriteHWRegs properly.
This commit is contained in:
		
							parent
							
								
									994d29f416
								
							
						
					
					
						commit
						cb8f49b7ea
					
				
					 1 changed files with 51 additions and 32 deletions
				
			
		|  | @ -47,11 +47,6 @@ Handle g_shared_memory = 0; | ||||||
| 
 | 
 | ||||||
| u32 g_thread_id = 0; | u32 g_thread_id = 0; | ||||||
| 
 | 
 | ||||||
| enum { |  | ||||||
|     REG_FRAMEBUFFER_1   = 0x00400468, |  | ||||||
|     REG_FRAMEBUFFER_2   = 0x00400494, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| /// Gets a pointer to the start (header) of a command buffer in GSP shared memory
 | /// Gets a pointer to the start (header) of a command buffer in GSP shared memory
 | ||||||
| static inline u8* GX_GetCmdBufferPointer(u32 thread_id, u32 offset=0) { | static inline u8* GX_GetCmdBufferPointer(u32 thread_id, u32 offset=0) { | ||||||
|     return Kernel::GetSharedMemoryPointer(g_shared_memory, 0x800 + (thread_id * 0x200) + offset); |     return Kernel::GetSharedMemoryPointer(g_shared_memory, 0x800 + (thread_id * 0x200) + offset); | ||||||
|  | @ -67,38 +62,62 @@ void GX_FinishCommand(u32 thread_id) { | ||||||
|     // TODO: Increment header->index?
 |     // TODO: Increment header->index?
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Read a GSP GPU hardware register
 | /// Write a GSP GPU hardware register
 | ||||||
| void ReadHWRegs(Service::Interface* self) { | void WriteHWRegs(Service::Interface* self) { | ||||||
|     static const u32 framebuffer_1[] = {GPU::PADDR_VRAM_TOP_LEFT_FRAME1, GPU::PADDR_VRAM_TOP_RIGHT_FRAME1}; |  | ||||||
|     static const u32 framebuffer_2[] = {GPU::PADDR_VRAM_TOP_LEFT_FRAME2, GPU::PADDR_VRAM_TOP_RIGHT_FRAME2}; |  | ||||||
| 
 |  | ||||||
|     u32* cmd_buff = Service::GetCommandBuffer(); |     u32* cmd_buff = Service::GetCommandBuffer(); | ||||||
|     u32 reg_addr = cmd_buff[1]; |     u32 reg_addr = cmd_buff[1]; | ||||||
|     u32 size = cmd_buff[2]; |     u32 size = cmd_buff[2]; | ||||||
|     u32* dst = (u32*)Memory::GetPointer(cmd_buff[0x41]); |  | ||||||
| 
 | 
 | ||||||
|     switch (reg_addr) { |     // TODO: Return proper error codes
 | ||||||
| 
 |     if (reg_addr + size >= 0x420000) { | ||||||
|     // NOTE: Calling SetFramebufferLocation here is a hack... Not sure the correct way yet to set 
 |         ERROR_LOG(GPU, "Write address out of range! (address=0x%08x, size=0x%08x)", reg_addr, size); | ||||||
|     // whether the framebuffers should be in VRAM or GSP heap, but from what I understand, if the 
 |         return; | ||||||
|     // user application is reading from either of these registers, then its going to be in VRAM.
 |  | ||||||
| 
 |  | ||||||
|     // Top framebuffer 1 addresses
 |  | ||||||
|     case REG_FRAMEBUFFER_1: |  | ||||||
|         GPU::SetFramebufferLocation(GPU::FRAMEBUFFER_LOCATION_VRAM); |  | ||||||
|         memcpy(dst, framebuffer_1, size); |  | ||||||
|         break; |  | ||||||
| 
 |  | ||||||
|     // Top framebuffer 2 addresses
 |  | ||||||
|     case REG_FRAMEBUFFER_2: |  | ||||||
|         GPU::SetFramebufferLocation(GPU::FRAMEBUFFER_LOCATION_VRAM); |  | ||||||
|         memcpy(dst, framebuffer_2, size); |  | ||||||
|         break; |  | ||||||
| 
 |  | ||||||
|     default: |  | ||||||
|         ERROR_LOG(GSP, "unknown register read at address %08X", reg_addr); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     // size should be word-aligned
 | ||||||
|  |     if ((size % 4) != 0) { | ||||||
|  |         ERROR_LOG(GPU, "Invalid size 0x%08x", size); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     u32* src = (u32*)Memory::GetPointer(cmd_buff[0x4]); | ||||||
|  | 
 | ||||||
|  |     while (size > 0) { | ||||||
|  |         GPU::Write<u32>(reg_addr + 0x1EB00000, *src); | ||||||
|  | 
 | ||||||
|  |         size -= 4; | ||||||
|  |         ++src; | ||||||
|  |         reg_addr += 4; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Read a GSP GPU hardware register
 | ||||||
|  | void ReadHWRegs(Service::Interface* self) { | ||||||
|  |     u32* cmd_buff = Service::GetCommandBuffer(); | ||||||
|  |     u32 reg_addr = cmd_buff[1]; | ||||||
|  |     u32 size = cmd_buff[2]; | ||||||
|  | 
 | ||||||
|  |     // TODO: Return proper error codes
 | ||||||
|  |     if (reg_addr + size >= 0x420000) { | ||||||
|  |         ERROR_LOG(GPU, "Read address out of range! (address=0x%08x, size=0x%08x)", reg_addr, size); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // size should be word-aligned
 | ||||||
|  |     if ((size % 4) != 0) { | ||||||
|  |         ERROR_LOG(GPU, "Invalid size 0x%08x", size); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     u32* dst = (u32*)Memory::GetPointer(cmd_buff[0x41]); | ||||||
|  | 
 | ||||||
|  |     while (size > 0) { | ||||||
|  |         GPU::Read<u32>(*dst, reg_addr + 0x1EB00000); | ||||||
|  | 
 | ||||||
|  |         size -= 4; | ||||||
|  |         ++dst; | ||||||
|  |         reg_addr += 4; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  | @ -179,7 +198,7 @@ void TriggerCmdReqQueue(Service::Interface* self) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const Interface::FunctionInfo FunctionTable[] = { | const Interface::FunctionInfo FunctionTable[] = { | ||||||
|     {0x00010082, nullptr,                       "WriteHWRegs"}, |     {0x00010082, WriteHWRegs,                   "WriteHWRegs"}, | ||||||
|     {0x00020084, nullptr,                       "WriteHWRegsWithMask"}, |     {0x00020084, nullptr,                       "WriteHWRegsWithMask"}, | ||||||
|     {0x00030082, nullptr,                       "WriteHWRegRepeat"}, |     {0x00030082, nullptr,                       "WriteHWRegRepeat"}, | ||||||
|     {0x00040080, ReadHWRegs,                    "ReadHWRegs"}, |     {0x00040080, ReadHWRegs,                    "ReadHWRegs"}, | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue