diff options
Diffstat (limited to 'src/core/hw')
-rw-r--r-- | src/core/hw/hw.cpp | 76 | ||||
-rw-r--r-- | src/core/hw/lcd.cpp | 103 | ||||
-rw-r--r-- | src/core/hw/lcd.h | 73 |
3 files changed, 206 insertions, 46 deletions
diff --git a/src/core/hw/hw.cpp b/src/core/hw/hw.cpp index 16bd70125..85669ae7f 100644 --- a/src/core/hw/hw.cpp +++ b/src/core/hw/hw.cpp @@ -12,49 +12,42 @@ namespace HW { enum { - ADDRESS_CONFIG = 0x10000000, - ADDRESS_IRQ = 0x10001000, - ADDRESS_NDMA = 0x10002000, - ADDRESS_TIMER = 0x10003000, - ADDRESS_CTRCARD = 0x10004000, - ADDRESS_CTRCARD_2 = 0x10005000, - ADDRESS_SDMC_NAND = 0x10006000, - ADDRESS_SDMC_NAND_2 = 0x10007000, // Apparently not used on retail - ADDRESS_PXI = 0x10008000, - ADDRESS_AES = 0x10009000, - ADDRESS_SHA = 0x1000A000, - ADDRESS_RSA = 0x1000B000, - ADDRESS_XDMA = 0x1000C000, - ADDRESS_SPICARD = 0x1000D800, - ADDRESS_CONFIG_2 = 0x10010000, - ADDRESS_HASH = 0x10101000, - ADDRESS_CSND = 0x10103000, - ADDRESS_DSP = 0x10140000, - ADDRESS_PDN = 0x10141000, - ADDRESS_CODEC = 0x10141000, - ADDRESS_SPI = 0x10142000, - ADDRESS_SPI_2 = 0x10143000, - ADDRESS_I2C = 0x10144000, - ADDRESS_CODEC_2 = 0x10145000, - ADDRESS_HID = 0x10146000, - ADDRESS_PAD = 0x10146000, - ADDRESS_PTM = 0x10146000, - ADDRESS_I2C_2 = 0x10148000, - ADDRESS_SPI_3 = 0x10160000, - ADDRESS_I2C_3 = 0x10161000, - ADDRESS_MIC = 0x10162000, - ADDRESS_PXI_2 = 0x10163000, - ADDRESS_NTRCARD = 0x10164000, - ADDRESS_DSP_2 = 0x10203000, - ADDRESS_HASH_2 = 0x10301000, + VADDR_HASH = 0x1EC01000, + VADDR_CSND = 0x1EC03000, + VADDR_DSP = 0x1EC40000, + VADDR_PDN = 0x1EC41000, + VADDR_CODEC = 0x1EC41000, + VADDR_SPI = 0x1EC42000, + VADDR_SPI_2 = 0x1EC43000, // Only used under TWL_FIRM? + VADDR_I2C = 0x1EC44000, + VADDR_CODEC_2 = 0x1EC45000, + VADDR_HID = 0x1EC46000, + VADDR_PAD = 0x1EC46000, + VADDR_PTM = 0x1EC46000, + VADDR_GPIO = 0x1EC47000, + VADDR_I2C_2 = 0x1EC48000, + VADDR_SPI_3 = 0x1EC60000, + VADDR_I2C_3 = 0x1EC61000, + VADDR_MIC = 0x1EC62000, + VADDR_PXI = 0x1EC63000, // 0xFFFD2000 + //VADDR_NTRCARD + VADDR_CDMA = 0xFFFDA000, // CoreLink DMA-330? Info + VADDR_DSP_2 = 0x1ED03000, + VADDR_HASH_2 = 0x1EE01000, + VADDR_LCD = 0x1EF00000, }; template <typename T> inline void Read(T &var, const u32 addr) { switch (addr & 0xFFFFF000) { - case ADDRESS_NDMA: - NDMA::Read(var, addr); + // TODO(bunnei): What is the virtual address of NDMA? + // case VADDR_NDMA: + // NDMA::Read(var, addr); + // break; + + case VADDR_LCD: + LCD::Read(var, addr); break; default: @@ -66,8 +59,13 @@ template <typename T> inline void Write(u32 addr, const T data) { switch (addr & 0xFFFFF000) { - case ADDRESS_NDMA: - NDMA::Write(addr, data); + // TODO(bunnei): What is the virtual address of NDMA? + // case VADDR_NDMA + // NDMA::Write(addr, data); + // break; + + case VADDR_LCD: + LCD::Write(addr, data); break; default: diff --git a/src/core/hw/lcd.cpp b/src/core/hw/lcd.cpp index 3013673f8..6468053f2 100644 --- a/src/core/hw/lcd.cpp +++ b/src/core/hw/lcd.cpp @@ -6,24 +6,126 @@ #include "common/log.h" #include "core/core.h" +#include "core/mem_map.h" #include "core/hw/lcd.h" #include "video_core/video_core.h" namespace LCD { +Registers g_regs; + static const u32 kFrameTicks = 268123480 / 60; ///< 268MHz / 60 frames per second u64 g_last_ticks = 0; ///< Last CPU ticks +/** + * Sets whether the framebuffers are in the GSP heap (FCRAM) or VRAM + * @param + */ +void SetFramebufferLocation(const FramebufferLocation mode) { + switch (mode) { + case FRAMEBUFFER_LOCATION_FCRAM: + g_regs.framebuffer_top_left_1 = PADDR_TOP_LEFT_FRAME1; + g_regs.framebuffer_top_left_2 = PADDR_TOP_LEFT_FRAME2; + g_regs.framebuffer_top_right_1 = PADDR_TOP_RIGHT_FRAME1; + g_regs.framebuffer_top_right_2 = PADDR_TOP_RIGHT_FRAME2; + g_regs.framebuffer_sub_left_1 = PADDR_SUB_FRAME1; + //g_regs.framebuffer_sub_left_2 = unknown; + g_regs.framebuffer_sub_right_1 = PADDR_SUB_FRAME2; + //g_regs.framebufferr_sub_right_2 = unknown; + break; + + case FRAMEBUFFER_LOCATION_VRAM: + g_regs.framebuffer_top_left_1 = PADDR_VRAM_TOP_LEFT_FRAME1; + g_regs.framebuffer_top_left_2 = PADDR_VRAM_TOP_LEFT_FRAME2; + g_regs.framebuffer_top_right_1 = PADDR_VRAM_TOP_RIGHT_FRAME1; + g_regs.framebuffer_top_right_2 = PADDR_VRAM_TOP_RIGHT_FRAME2; + g_regs.framebuffer_sub_left_1 = PADDR_VRAM_SUB_FRAME1; + //g_regs.framebuffer_sub_left_2 = unknown; + g_regs.framebuffer_sub_right_1 = PADDR_VRAM_SUB_FRAME2; + //g_regs.framebufferr_sub_right_2 = unknown; + break; + } +} + +/** + * Gets the location of the framebuffers + * @return Location of framebuffers as FramebufferLocation enum + */ +const FramebufferLocation GetFramebufferLocation() { + if ((g_regs.framebuffer_top_right_1 & ~Memory::VRAM_MASK) == Memory::VRAM_PADDR) { + return FRAMEBUFFER_LOCATION_VRAM; + } else if ((g_regs.framebuffer_top_right_1 & ~Memory::FCRAM_MASK) == Memory::FCRAM_PADDR) { + return FRAMEBUFFER_LOCATION_FCRAM; + } else { + ERROR_LOG(LCD, "unknown framebuffer location!"); + } + return FRAMEBUFFER_LOCATION_UNKNOWN; +} + +/** + * 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) { + switch (GetFramebufferLocation()) { + case FRAMEBUFFER_LOCATION_FCRAM: + return (const u8*)Memory::GetPointer(Memory::VirtualAddressFromPhysical_FCRAM(address)); + case FRAMEBUFFER_LOCATION_VRAM: + return (const u8*)Memory::GetPointer(Memory::VirtualAddressFromPhysical_VRAM(address)); + default: + ERROR_LOG(LCD, "unknown framebuffer location"); + } + return NULL; +} + template <typename T> inline void Read(T &var, const u32 addr) { + switch (addr) { + case REG_FRAMEBUFFER_TOP_LEFT_1: + var = g_regs.framebuffer_top_left_1; + break; + case REG_FRAMEBUFFER_TOP_LEFT_2: + var = g_regs.framebuffer_top_left_2; + break; + case REG_FRAMEBUFFER_TOP_RIGHT_1: + var = g_regs.framebuffer_top_right_1; + break; + case REG_FRAMEBUFFER_TOP_RIGHT_2: + var = g_regs.framebuffer_top_right_2; + break; + case REG_FRAMEBUFFER_SUB_LEFT_1: + var = g_regs.framebuffer_sub_left_1; + break; + case REG_FRAMEBUFFER_SUB_RIGHT_1: + var = g_regs.framebuffer_sub_right_1; + break; + default: + ERROR_LOG(LCD, "unknown Read%d @ 0x%08X", sizeof(var) * 8, addr); + break; + } + } template <typename T> inline void Write(u32 addr, const T data) { + ERROR_LOG(LCD, "unknown Write%d 0x%08X @ 0x%08X", sizeof(data) * 8, data, addr); } +// Explicitly instantiate template functions because we aren't defining this in the header: + +template void Read<u64>(u64 &var, const u32 addr); +template void Read<u32>(u32 &var, const u32 addr); +template void Read<u16>(u16 &var, const u32 addr); +template void Read<u8>(u8 &var, const u32 addr); + +template void Write<u64>(u32 addr, const u64 data); +template void Write<u32>(u32 addr, const u32 data); +template void Write<u16>(u32 addr, const u16 data); +template void Write<u8>(u32 addr, const u8 data); + /// Update hardware void Update() { u64 current_ticks = Core::g_app_core->GetTicks(); @@ -37,6 +139,7 @@ void Update() { /// Initialize hardware void Init() { g_last_ticks = Core::g_app_core->GetTicks(); + SetFramebufferLocation(FRAMEBUFFER_LOCATION_FCRAM); NOTICE_LOG(LCD, "initialized OK"); } diff --git a/src/core/hw/lcd.h b/src/core/hw/lcd.h index 386ed6004..2dd3b4adc 100644 --- a/src/core/hw/lcd.h +++ b/src/core/hw/lcd.h @@ -8,6 +8,19 @@ namespace LCD { +struct Registers { + u32 framebuffer_top_left_1; + u32 framebuffer_top_left_2; + u32 framebuffer_top_right_1; + u32 framebuffer_top_right_2; + u32 framebuffer_sub_left_1; + u32 framebuffer_sub_left_2; + u32 framebuffer_sub_right_1; + u32 framebuffer_sub_right_2; +}; + +extern Registers g_regs; + enum { TOP_ASPECT_X = 0x5, TOP_ASPECT_Y = 0x3, @@ -16,15 +29,61 @@ enum { TOP_WIDTH = 400, BOTTOM_WIDTH = 320, - FRAMEBUFFER_SEL = 0x20184E59, - TOP_LEFT_FRAME1 = 0x20184E60, - TOP_LEFT_FRAME2 = 0x201CB370, - TOP_RIGHT_FRAME1 = 0x20282160, - TOP_RIGHT_FRAME2 = 0x202C8670, - SUB_FRAME1 = 0x202118E0, - SUB_FRAME2 = 0x20249CF0, + // Physical addresses in FCRAM used by ARM9 applications - these are correct for real hardware + PADDR_FRAMEBUFFER_SEL = 0x20184E59, + 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 - I'm not sure how these are actually allocated (so not real) + PADDR_VRAM_FRAMEBUFFER_SEL = 0x18184E59, + PADDR_VRAM_TOP_LEFT_FRAME1 = 0x18184E60, + 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, +}; + +enum { + REG_FRAMEBUFFER_TOP_LEFT_1 = 0x1EF00468, // Main LCD, first framebuffer for 3D left + REG_FRAMEBUFFER_TOP_LEFT_2 = 0x1EF0046C, // Main LCD, second framebuffer for 3D left + REG_FRAMEBUFFER_TOP_RIGHT_1 = 0x1EF00494, // Main LCD, first framebuffer for 3D right + REG_FRAMEBUFFER_TOP_RIGHT_2 = 0x1EF00498, // Main LCD, second framebuffer for 3D right + REG_FRAMEBUFFER_SUB_LEFT_1 = 0x1EF00568, // Sub LCD, first framebuffer + REG_FRAMEBUFFER_SUB_LEFT_2 = 0x1EF0056C, // Sub LCD, second framebuffer + REG_FRAMEBUFFER_SUB_RIGHT_1 = 0x1EF00594, // Sub LCD, unused first framebuffer + REG_FRAMEBUFFER_SUB_RIGHT_2 = 0x1EF00598, // Sub LCD, unused second framebuffer +}; + +/// 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); + +/** + * Gets the location of the framebuffers + */ +const FramebufferLocation GetFramebufferLocation(); + template <typename T> inline void Read(T &var, const u32 addr); |