diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/hw/gpu.cpp | 9 | ||||
-rw-r--r-- | src/core/hw/gpu.h | 2 | ||||
-rw-r--r-- | src/core/hw/hw.cpp | 38 | ||||
-rw-r--r-- | src/core/hw/hw.h | 24 | ||||
-rw-r--r-- | src/core/hw/lcd.cpp | 66 | ||||
-rw-r--r-- | src/core/hw/lcd.h | 88 |
6 files changed, 192 insertions, 35 deletions
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index b7102b874..30318fc06 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp @@ -15,12 +15,13 @@ #include "core/hle/service/gsp_gpu.h" #include "core/hle/service/dsp_dsp.h" +#include "core/hw/hw.h" #include "core/hw/gpu.h" #include "video_core/command_processor.h" #include "video_core/utils.h" #include "video_core/video_core.h" -#include <video_core/color.h> +#include "video_core/color.h" namespace GPU { @@ -40,7 +41,7 @@ static bool last_skip_frame = false; template <typename T> inline void Read(T &var, const u32 raw_addr) { - u32 addr = raw_addr - 0x1EF00000; + u32 addr = raw_addr - HW::VADDR_GPU; u32 index = addr / 4; // Reads other than u32 are untested, so I'd rather have them abort than silently fail @@ -54,7 +55,7 @@ inline void Read(T &var, const u32 raw_addr) { template <typename T> inline void Write(u32 addr, const T data) { - addr -= 0x1EF00000; + addr -= HW::VADDR_GPU; u32 index = addr / 4; // Writes other than u32 are untested, so I'd rather have them abort than silently fail @@ -313,8 +314,6 @@ void Init() { framebuffer_top.address_right2 = 0x182B9800; framebuffer_sub.address_left1 = 0x1848F000; framebuffer_sub.address_left2 = 0x184C7800; - //framebuffer_sub.address_right1 = unknown; - //framebuffer_sub.address_right2 = unknown; framebuffer_top.width = 240; framebuffer_top.height = 400; diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h index 3e81f03ef..5b7f0a4e9 100644 --- a/src/core/hw/gpu.h +++ b/src/core/hw/gpu.h @@ -246,6 +246,8 @@ struct Regs { return content[index]; } +#undef ASSERT_MEMBER_SIZE + private: /* * Most physical addresses which GPU registers refer to are 8-byte aligned. diff --git a/src/core/hw/hw.cpp b/src/core/hw/hw.cpp index a63ba6eeb..bed50af50 100644 --- a/src/core/hw/hw.cpp +++ b/src/core/hw/hw.cpp @@ -6,43 +6,19 @@ #include "core/hw/hw.h" #include "core/hw/gpu.h" +#include "core/hw/lcd.h" namespace HW { -enum { - 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_GPU = 0x1EF00000, -}; - template <typename T> inline void Read(T &var, const u32 addr) { switch (addr & 0xFFFFF000) { - case VADDR_GPU: GPU::Read(var, addr); break; - + case VADDR_LCD: + LCD::Write(var, addr); + break; default: LOG_ERROR(HW_Memory, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, addr); } @@ -51,11 +27,12 @@ inline void Read(T &var, const u32 addr) { template <typename T> inline void Write(u32 addr, const T data) { switch (addr & 0xFFFFF000) { - case VADDR_GPU: GPU::Write(addr, data); break; - + case VADDR_LCD: + LCD::Write(addr, data); + break; default: LOG_ERROR(HW_Memory, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr); } @@ -80,6 +57,7 @@ void Update() { /// Initialize hardware void Init() { GPU::Init(); + LCD::Init(); LOG_DEBUG(HW, "initialized OK"); } diff --git a/src/core/hw/hw.h b/src/core/hw/hw.h index 991c0a07d..d65608910 100644 --- a/src/core/hw/hw.h +++ b/src/core/hw/hw.h @@ -8,6 +8,30 @@ namespace HW { +/// Beginnings of IO register regions, in the user VA space. +enum : u32 { + 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_GPIO = 0x1EC47000, + VADDR_I2C_2 = 0x1EC48000, + VADDR_SPI_3 = 0x1EC60000, + VADDR_I2C_3 = 0x1EC61000, + VADDR_MIC = 0x1EC62000, + VADDR_PXI = 0x1EC63000, + VADDR_LCD = 0x1ED02000, + VADDR_DSP_2 = 0x1ED03000, + VADDR_HASH_2 = 0x1EE01000, + VADDR_GPU = 0x1EF00000, +}; + template <typename T> void Read(T &var, const u32 addr); diff --git a/src/core/hw/lcd.cpp b/src/core/hw/lcd.cpp new file mode 100644 index 000000000..7986f3ddb --- /dev/null +++ b/src/core/hw/lcd.cpp @@ -0,0 +1,66 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/common_types.h" + +#include "core/arm/arm_interface.h" +#include "core/hle/hle.h" +#include "core/hw/hw.h" +#include "core/hw/lcd.h" + +namespace LCD { + +Regs g_regs; + +template <typename T> +inline void Read(T &var, const u32 raw_addr) { + u32 addr = raw_addr - HW::VADDR_LCD; + u32 index = addr / 4; + + // Reads other than u32 are untested, so I'd rather have them abort than silently fail + if (index >= 0x400 || !std::is_same<T, u32>::value) { + LOG_ERROR(HW_LCD, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, addr); + return; + } + + var = g_regs[index]; +} + +template <typename T> +inline void Write(u32 addr, const T data) { + addr -= HW::VADDR_LCD; + u32 index = addr / 4; + + // Writes other than u32 are untested, so I'd rather have them abort than silently fail + if (index >= 0x400 || !std::is_same<T, u32>::value) { + LOG_ERROR(HW_LCD, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr); + return; + } + + g_regs[index] = static_cast<u32>(data); +} + +// 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); + +/// Initialize hardware +void Init() { + LOG_DEBUG(HW_LCD, "initialized OK"); +} + +/// Shutdown hardware +void Shutdown() { + LOG_DEBUG(HW_LCD, "shutdown OK"); +} + +} // namespace diff --git a/src/core/hw/lcd.h b/src/core/hw/lcd.h new file mode 100644 index 000000000..43893a625 --- /dev/null +++ b/src/core/hw/lcd.h @@ -0,0 +1,88 @@ +// Copyright 2015 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <cstddef> + +#include "common/common_types.h" +#include "common/bit_field.h" + +#define LCD_REG_INDEX(field_name) (offsetof(LCD::Regs, field_name) / sizeof(u32)) + +namespace LCD { + +struct Regs { + + union ColorFill { + u32 raw; + + BitField<0, 8, u32> color_r; + BitField<8, 8, u32> color_g; + BitField<16, 8, u32> color_b; + BitField<24, 1, u32> is_enabled; + }; + + INSERT_PADDING_WORDS(0x81); + ColorFill color_fill_top; + INSERT_PADDING_WORDS(0xE); + u32 backlight_top; + + INSERT_PADDING_WORDS(0x1F0); + + ColorFill color_fill_bottom; + INSERT_PADDING_WORDS(0xE); + u32 backlight_bottom; + INSERT_PADDING_WORDS(0x16F); + + static inline size_t NumIds() { + return sizeof(Regs) / sizeof(u32); + } + + u32& operator [] (int index) const { + u32* content = (u32*)this; + return content[index]; + } + + u32& operator [] (int index) { + u32* content = (u32*)this; + return content[index]; + } + +#undef ASSERT_MEMBER_SIZE + +}; +static_assert(std::is_standard_layout<Regs>::value, "Structure does not use standard layout"); + +// TODO: MSVC does not support using offsetof() on non-static data members even though this +// is technically allowed since C++11. This macro should be enabled once MSVC adds +// support for that. +#ifndef _MSC_VER +#define ASSERT_REG_POSITION(field_name, position) \ + static_assert(offsetof(Regs, field_name) == position * 4, \ + "Field "#field_name" has invalid position") + +ASSERT_REG_POSITION(color_fill_top, 0x81); +ASSERT_REG_POSITION(backlight_top, 0x90); +ASSERT_REG_POSITION(color_fill_bottom, 0x281); +ASSERT_REG_POSITION(backlight_bottom, 0x290); + +#undef ASSERT_REG_POSITION +#endif // !defined(_MSC_VER) + +extern Regs g_regs; + +template <typename T> +void Read(T &var, const u32 addr); + +template <typename T> +void Write(u32 addr, const T data); + +/// Initialize hardware +void Init(); + +/// Shutdown hardware +void Shutdown(); + +} // namespace |