diff options
| author | archshift <admin@archshift.com> | 2014-10-12 22:40:26 -0700 | 
|---|---|---|
| committer | archshift <admin@archshift.com> | 2015-03-09 15:51:41 -0700 | 
| commit | 041e99b6132775ff52822060512b8384b735e582 (patch) | |
| tree | cd8dee92a0b578e512a188cd7e70239b627a5341 /src/core/hw | |
| parent | 47010fea3126bfe0b675810ea9471a25191d548f (diff) | |
Added LCD registers, and implementation for color filling in OGL code.
Diffstat (limited to 'src/core/hw')
| -rw-r--r-- | src/core/hw/gpu.h | 2 | ||||
| -rw-r--r-- | src/core/hw/hw.cpp | 12 | ||||
| -rw-r--r-- | src/core/hw/hw.h | 8 | ||||
| -rw-r--r-- | src/core/hw/lcd.cpp | 66 | ||||
| -rw-r--r-- | src/core/hw/lcd.h | 88 | 
5 files changed, 167 insertions, 9 deletions
diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h index 737b1e968..76f4d66fe 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 bf4722cf7..bed50af50 100644 --- a/src/core/hw/hw.cpp +++ b/src/core/hw/hw.cpp @@ -6,17 +6,19 @@  #include "core/hw/hw.h"  #include "core/hw/gpu.h" +#include "core/hw/lcd.h"  namespace HW {  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);      } @@ -25,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);      } @@ -54,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 6feeba08c..d65608910 100644 --- a/src/core/hw/hw.h +++ b/src/core/hw/hw.h @@ -8,8 +8,8 @@  namespace HW { -enum { -    VADDR_IO        = 0x1EC00000, +/// Beginnings of IO register regions, in the user VA space. +enum : u32 {      VADDR_HASH      = 0x1EC01000,      VADDR_CSND      = 0x1EC03000,      VADDR_DSP       = 0x1EC40000, @@ -25,9 +25,7 @@ enum {      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_PXI       = 0x1EC63000,      VADDR_LCD       = 0x1ED02000,      VADDR_DSP_2     = 0x1ED03000,      VADDR_HASH_2    = 0x1EE01000, 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  | 
