mirror of
				https://git.suyu.dev/suyu/suyu.git
				synced 2025-11-04 12:34:39 +08: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
					
				@ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user