summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar archshift2014-10-12 22:40:26 -0700
committerGravatar archshift2015-03-09 15:51:41 -0700
commit041e99b6132775ff52822060512b8384b735e582 (patch)
treecd8dee92a0b578e512a188cd7e70239b627a5341 /src/core
parentImplement SetLcdForceBlack, move register enum to hw.h (diff)
downloadyuzu-041e99b6132775ff52822060512b8384b735e582.tar.gz
yuzu-041e99b6132775ff52822060512b8384b735e582.tar.xz
yuzu-041e99b6132775ff52822060512b8384b735e582.zip
Added LCD registers, and implementation for color filling in OGL code.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/service/gsp_gpu.cpp32
-rw-r--r--src/core/hw/gpu.h2
-rw-r--r--src/core/hw/hw.cpp12
-rw-r--r--src/core/hw/hw.h8
-rw-r--r--src/core/hw/lcd.cpp66
-rw-r--r--src/core/hw/lcd.h88
7 files changed, 184 insertions, 26 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 212da25c5..33e5be3a4 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -87,6 +87,7 @@ set(SRCS
87 hle/svc.cpp 87 hle/svc.cpp
88 hw/gpu.cpp 88 hw/gpu.cpp
89 hw/hw.cpp 89 hw/hw.cpp
90 hw/lcd.cpp
90 loader/elf.cpp 91 loader/elf.cpp
91 loader/loader.cpp 92 loader/loader.cpp
92 loader/ncch.cpp 93 loader/ncch.cpp
@@ -196,6 +197,7 @@ set(HEADERS
196 hle/svc.h 197 hle/svc.h
197 hw/gpu.h 198 hw/gpu.h
198 hw/hw.h 199 hw/hw.h
200 hw/lcd.h
199 loader/elf.h 201 loader/elf.h
200 loader/loader.h 202 loader/loader.h
201 loader/ncch.h 203 loader/ncch.h
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 3b4a7b664..cff585698 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -11,12 +11,16 @@
11#include "gsp_gpu.h" 11#include "gsp_gpu.h"
12#include "core/hw/hw.h" 12#include "core/hw/hw.h"
13#include "core/hw/gpu.h" 13#include "core/hw/gpu.h"
14#include "core/hw/lcd.h"
14 15
15#include "video_core/gpu_debugger.h" 16#include "video_core/gpu_debugger.h"
16 17
17// Main graphics debugger object - TODO: Here is probably not the best place for this 18// Main graphics debugger object - TODO: Here is probably not the best place for this
18GraphicsDebugger g_debugger; 19GraphicsDebugger g_debugger;
19 20
21// Beginning address of HW regs
22const static u32 REGS_BEGIN = 0x1EB00000;
23
20//////////////////////////////////////////////////////////////////////////////////////////////////// 24////////////////////////////////////////////////////////////////////////////////////////////////////
21// Namespace GSP_GPU 25// Namespace GSP_GPU
22 26
@@ -87,7 +91,7 @@ static void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) {
87 return; 91 return;
88 92
89 while (size_in_bytes > 0) { 93 while (size_in_bytes > 0) {
90 HW::Write<u32>(base_address + 0x1EB00000, *data); 94 HW::Write<u32>(base_address + REGS_BEGIN, *data);
91 95
92 size_in_bytes -= 4; 96 size_in_bytes -= 4;
93 ++data; 97 ++data;
@@ -130,7 +134,7 @@ static void WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, const u32*
130 return; 134 return;
131 135
132 while (size_in_bytes > 0) { 136 while (size_in_bytes > 0) {
133 const u32 reg_address = base_address + 0x1EB00000; 137 const u32 reg_address = base_address + REGS_BEGIN;
134 138
135 u32 reg_value; 139 u32 reg_value;
136 HW::Read<u32>(reg_value, reg_address); 140 HW::Read<u32>(reg_value, reg_address);
@@ -190,7 +194,7 @@ static void ReadHWRegs(Service::Interface* self) {
190 u32* dst = (u32*)Memory::GetPointer(cmd_buff[0x41]); 194 u32* dst = (u32*)Memory::GetPointer(cmd_buff[0x41]);
191 195
192 while (size > 0) { 196 while (size > 0) {
193 HW::Read<u32>(*dst, reg_addr + 0x1EB00000); 197 HW::Read<u32>(*dst, reg_addr + REGS_BEGIN);
194 198
195 size -= 4; 199 size -= 4;
196 ++dst; 200 ++dst;
@@ -439,24 +443,18 @@ static void ExecuteCommand(const Command& command, u32 thread_id) {
439 * Outputs: 443 * Outputs:
440 * 1: Result code 444 * 1: Result code
441 */ 445 */
442void SetLcdForceBlack(Service::Interface* self) { 446static void SetLcdForceBlack(Service::Interface* self) {
443 // TODO: currently has no effect, as LCD reg writes have nowhere to go.
444
445 u32* cmd_buff = Kernel::GetCommandBuffer(); 447 u32* cmd_buff = Kernel::GetCommandBuffer();
448
446 bool enable_black = cmd_buff[1] != 0; 449 bool enable_black = cmd_buff[1] != 0;
447 u32 data = 0; 450 LCD::Regs::ColorFill data = {0};
448 451
449 if (enable_black) { 452 // Since data is already zeroed, there is no need to explicitly set
450 // Sets bit 24 to 1, enabling the fill 453 // the color to black (all zero).
451 // Since data is already 0x00000000, there is no need to explicitly set 454 data.is_enabled = enable_black;
452 // bits 0-23 to zero (black), or bit 24 to 0 (fill disabled).
453 data |= (1 << 24);
454 }
455 455
456 u32 data_main = data; 456 LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_top), data.raw); // Top LCD
457 u32 data_sub = data; 457 LCD::Write(HW::VADDR_LCD + 4 * LCD_REG_INDEX(color_fill_bottom), data.raw); // Bottom LCD
458 WriteHWRegs(0x202204, 4, &data_main); // Main LCD
459 WriteHWRegs(0x202A04, 4, &data_sub); // Sub LCD
460 458
461 cmd_buff[1] = RESULT_SUCCESS.raw; 459 cmd_buff[1] = RESULT_SUCCESS.raw;
462} 460}
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 {
246 return content[index]; 246 return content[index];
247 } 247 }
248 248
249#undef ASSERT_MEMBER_SIZE
250
249private: 251private:
250 /* 252 /*
251 * Most physical addresses which GPU registers refer to are 8-byte aligned. 253 * 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 @@
6 6
7#include "core/hw/hw.h" 7#include "core/hw/hw.h"
8#include "core/hw/gpu.h" 8#include "core/hw/gpu.h"
9#include "core/hw/lcd.h"
9 10
10namespace HW { 11namespace HW {
11 12
12template <typename T> 13template <typename T>
13inline void Read(T &var, const u32 addr) { 14inline void Read(T &var, const u32 addr) {
14 switch (addr & 0xFFFFF000) { 15 switch (addr & 0xFFFFF000) {
15
16 case VADDR_GPU: 16 case VADDR_GPU:
17 GPU::Read(var, addr); 17 GPU::Read(var, addr);
18 break; 18 break;
19 19 case VADDR_LCD:
20 LCD::Write(var, addr);
21 break;
20 default: 22 default:
21 LOG_ERROR(HW_Memory, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, addr); 23 LOG_ERROR(HW_Memory, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, addr);
22 } 24 }
@@ -25,11 +27,12 @@ inline void Read(T &var, const u32 addr) {
25template <typename T> 27template <typename T>
26inline void Write(u32 addr, const T data) { 28inline void Write(u32 addr, const T data) {
27 switch (addr & 0xFFFFF000) { 29 switch (addr & 0xFFFFF000) {
28
29 case VADDR_GPU: 30 case VADDR_GPU:
30 GPU::Write(addr, data); 31 GPU::Write(addr, data);
31 break; 32 break;
32 33 case VADDR_LCD:
34 LCD::Write(addr, data);
35 break;
33 default: 36 default:
34 LOG_ERROR(HW_Memory, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr); 37 LOG_ERROR(HW_Memory, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr);
35 } 38 }
@@ -54,6 +57,7 @@ void Update() {
54/// Initialize hardware 57/// Initialize hardware
55void Init() { 58void Init() {
56 GPU::Init(); 59 GPU::Init();
60 LCD::Init();
57 LOG_DEBUG(HW, "initialized OK"); 61 LOG_DEBUG(HW, "initialized OK");
58} 62}
59 63
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 @@
8 8
9namespace HW { 9namespace HW {
10 10
11enum { 11/// Beginnings of IO register regions, in the user VA space.
12 VADDR_IO = 0x1EC00000, 12enum : u32 {
13 VADDR_HASH = 0x1EC01000, 13 VADDR_HASH = 0x1EC01000,
14 VADDR_CSND = 0x1EC03000, 14 VADDR_CSND = 0x1EC03000,
15 VADDR_DSP = 0x1EC40000, 15 VADDR_DSP = 0x1EC40000,
@@ -25,9 +25,7 @@ enum {
25 VADDR_SPI_3 = 0x1EC60000, 25 VADDR_SPI_3 = 0x1EC60000,
26 VADDR_I2C_3 = 0x1EC61000, 26 VADDR_I2C_3 = 0x1EC61000,
27 VADDR_MIC = 0x1EC62000, 27 VADDR_MIC = 0x1EC62000,
28 VADDR_PXI = 0x1EC63000, // 0xFFFD2000 28 VADDR_PXI = 0x1EC63000,
29 //VADDR_NTRCARD
30 VADDR_CDMA = 0xFFFDA000, // CoreLink DMA-330? Info
31 VADDR_LCD = 0x1ED02000, 29 VADDR_LCD = 0x1ED02000,
32 VADDR_DSP_2 = 0x1ED03000, 30 VADDR_DSP_2 = 0x1ED03000,
33 VADDR_HASH_2 = 0x1EE01000, 31 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 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/common_types.h"
6
7#include "core/arm/arm_interface.h"
8#include "core/hle/hle.h"
9#include "core/hw/hw.h"
10#include "core/hw/lcd.h"
11
12namespace LCD {
13
14Regs g_regs;
15
16template <typename T>
17inline void Read(T &var, const u32 raw_addr) {
18 u32 addr = raw_addr - HW::VADDR_LCD;
19 u32 index = addr / 4;
20
21 // Reads other than u32 are untested, so I'd rather have them abort than silently fail
22 if (index >= 0x400 || !std::is_same<T, u32>::value) {
23 LOG_ERROR(HW_LCD, "unknown Read%lu @ 0x%08X", sizeof(var) * 8, addr);
24 return;
25 }
26
27 var = g_regs[index];
28}
29
30template <typename T>
31inline void Write(u32 addr, const T data) {
32 addr -= HW::VADDR_LCD;
33 u32 index = addr / 4;
34
35 // Writes other than u32 are untested, so I'd rather have them abort than silently fail
36 if (index >= 0x400 || !std::is_same<T, u32>::value) {
37 LOG_ERROR(HW_LCD, "unknown Write%lu 0x%08X @ 0x%08X", sizeof(data) * 8, (u32)data, addr);
38 return;
39 }
40
41 g_regs[index] = static_cast<u32>(data);
42}
43
44// Explicitly instantiate template functions because we aren't defining this in the header:
45
46template void Read<u64>(u64 &var, const u32 addr);
47template void Read<u32>(u32 &var, const u32 addr);
48template void Read<u16>(u16 &var, const u32 addr);
49template void Read<u8>(u8 &var, const u32 addr);
50
51template void Write<u64>(u32 addr, const u64 data);
52template void Write<u32>(u32 addr, const u32 data);
53template void Write<u16>(u32 addr, const u16 data);
54template void Write<u8>(u32 addr, const u8 data);
55
56/// Initialize hardware
57void Init() {
58 LOG_DEBUG(HW_LCD, "initialized OK");
59}
60
61/// Shutdown hardware
62void Shutdown() {
63 LOG_DEBUG(HW_LCD, "shutdown OK");
64}
65
66} // 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 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <cstddef>
8
9#include "common/common_types.h"
10#include "common/bit_field.h"
11
12#define LCD_REG_INDEX(field_name) (offsetof(LCD::Regs, field_name) / sizeof(u32))
13
14namespace LCD {
15
16struct Regs {
17
18 union ColorFill {
19 u32 raw;
20
21 BitField<0, 8, u32> color_r;
22 BitField<8, 8, u32> color_g;
23 BitField<16, 8, u32> color_b;
24 BitField<24, 1, u32> is_enabled;
25 };
26
27 INSERT_PADDING_WORDS(0x81);
28 ColorFill color_fill_top;
29 INSERT_PADDING_WORDS(0xE);
30 u32 backlight_top;
31
32 INSERT_PADDING_WORDS(0x1F0);
33
34 ColorFill color_fill_bottom;
35 INSERT_PADDING_WORDS(0xE);
36 u32 backlight_bottom;
37 INSERT_PADDING_WORDS(0x16F);
38
39 static inline size_t NumIds() {
40 return sizeof(Regs) / sizeof(u32);
41 }
42
43 u32& operator [] (int index) const {
44 u32* content = (u32*)this;
45 return content[index];
46 }
47
48 u32& operator [] (int index) {
49 u32* content = (u32*)this;
50 return content[index];
51 }
52
53#undef ASSERT_MEMBER_SIZE
54
55};
56static_assert(std::is_standard_layout<Regs>::value, "Structure does not use standard layout");
57
58// TODO: MSVC does not support using offsetof() on non-static data members even though this
59// is technically allowed since C++11. This macro should be enabled once MSVC adds
60// support for that.
61#ifndef _MSC_VER
62#define ASSERT_REG_POSITION(field_name, position) \
63 static_assert(offsetof(Regs, field_name) == position * 4, \
64 "Field "#field_name" has invalid position")
65
66ASSERT_REG_POSITION(color_fill_top, 0x81);
67ASSERT_REG_POSITION(backlight_top, 0x90);
68ASSERT_REG_POSITION(color_fill_bottom, 0x281);
69ASSERT_REG_POSITION(backlight_bottom, 0x290);
70
71#undef ASSERT_REG_POSITION
72#endif // !defined(_MSC_VER)
73
74extern Regs g_regs;
75
76template <typename T>
77void Read(T &var, const u32 addr);
78
79template <typename T>
80void Write(u32 addr, const T data);
81
82/// Initialize hardware
83void Init();
84
85/// Shutdown hardware
86void Shutdown();
87
88} // namespace