summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Tony Wasserka2014-07-16 11:27:58 +0200
committerGravatar Tony Wasserka2014-07-23 00:33:08 +0200
commit246cb75584af281596b938f898e8a3aedbcdb62a (patch)
treee87322b8dbcf7e7d2975bc6874f0fd3487a46eb7 /src
parentGPU: Make use of RegisterSet. (diff)
downloadyuzu-246cb75584af281596b938f898e8a3aedbcdb62a.tar.gz
yuzu-246cb75584af281596b938f898e8a3aedbcdb62a.tar.xz
yuzu-246cb75584af281596b938f898e8a3aedbcdb62a.zip
RegisterSet: Simplify code by using structs for register definition instead of unions.
Diffstat (limited to 'src')
-rw-r--r--src/common/register_set.h14
-rw-r--r--src/core/hw/gpu.cpp102
-rw-r--r--src/core/hw/gpu.h154
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp18
4 files changed, 140 insertions, 148 deletions
diff --git a/src/common/register_set.h b/src/common/register_set.h
index 0418551b3..ba19a2614 100644
--- a/src/common/register_set.h
+++ b/src/common/register_set.h
@@ -34,7 +34,7 @@
34/* 34/*
35 * Standardized way to define a group of registers and corresponding data structures. To define 35 * Standardized way to define a group of registers and corresponding data structures. To define
36 * a new register set, first define struct containing an enumeration called "Id" containing 36 * a new register set, first define struct containing an enumeration called "Id" containing
37 * all register IDs and a template union called "Struct". Specialize the Struct union for any 37 * all register IDs and a template struct called "Struct". Specialize the Struct struct for any
38 * register ID which needs to be accessed in a specialized way. You can then declare the object 38 * register ID which needs to be accessed in a specialized way. You can then declare the object
39 * containing all register values using the RegisterSet<BaseType, DefiningStruct> type, where 39 * containing all register values using the RegisterSet<BaseType, DefiningStruct> type, where
40 * BaseType is the underlying type of each register (e.g. u32). 40 * BaseType is the underlying type of each register (e.g. u32).
@@ -54,7 +54,7 @@
54 * 54 *
55 * // declare register definition structures 55 * // declare register definition structures
56 * template<Id id> 56 * template<Id id>
57 * union Struct; 57 * struct Struct;
58 * }; 58 * };
59 * 59 *
60 * // Define register set object 60 * // Define register set object
@@ -62,9 +62,11 @@
62 * 62 *
63 * // define register definition structures 63 * // define register definition structures
64 * template<> 64 * template<>
65 * union Regs::Struct<Regs::Value1> { 65 * struct Regs::Struct<Regs::Value1> {
66 * BitField<0, 4, u32> some_field; 66 * union {
67 * BitField<4, 3, u32> some_other_field; 67 * BitField<0, 4, u32> some_field;
68 * BitField<4, 3, u32> some_other_field;
69 * };
68 * }; 70 * };
69 * 71 *
70 * Usage in external code (within SomeNamespace scope): 72 * Usage in external code (within SomeNamespace scope):
@@ -77,7 +79,7 @@
77 * 79 *
78 * 80 *
79 * @tparam BaseType Base type used for storing individual registers, e.g. u32 81 * @tparam BaseType Base type used for storing individual registers, e.g. u32
80 * @tparam RegDefinition Class defining an enumeration called "Id" and a template<Id id> union, as described above. 82 * @tparam RegDefinition Class defining an enumeration called "Id" and a template<Id id> struct, as described above.
81 * @note RegDefinition::Id needs to have an enum value called NumIds defining the number of registers to be allocated. 83 * @note RegDefinition::Id needs to have an enum value called NumIds defining the number of registers to be allocated.
82 */ 84 */
83template<typename BaseType, typename RegDefinition> 85template<typename BaseType, typename RegDefinition>
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index 372e4f4cc..edffa25c5 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -30,14 +30,14 @@ void SetFramebufferLocation(const FramebufferLocation mode) {
30 auto& framebuffer_top = g_regs.Get<Regs::FramebufferTop>(); 30 auto& framebuffer_top = g_regs.Get<Regs::FramebufferTop>();
31 auto& framebuffer_sub = g_regs.Get<Regs::FramebufferBottom>(); 31 auto& framebuffer_sub = g_regs.Get<Regs::FramebufferBottom>();
32 32
33 framebuffer_top.data.address_left1 = PADDR_TOP_LEFT_FRAME1; 33 framebuffer_top.address_left1 = PADDR_TOP_LEFT_FRAME1;
34 framebuffer_top.data.address_left2 = PADDR_TOP_LEFT_FRAME2; 34 framebuffer_top.address_left2 = PADDR_TOP_LEFT_FRAME2;
35 framebuffer_top.data.address_right1 = PADDR_TOP_RIGHT_FRAME1; 35 framebuffer_top.address_right1 = PADDR_TOP_RIGHT_FRAME1;
36 framebuffer_top.data.address_right2 = PADDR_TOP_RIGHT_FRAME2; 36 framebuffer_top.address_right2 = PADDR_TOP_RIGHT_FRAME2;
37 framebuffer_sub.data.address_left1 = PADDR_SUB_FRAME1; 37 framebuffer_sub.address_left1 = PADDR_SUB_FRAME1;
38 //framebuffer_sub.data.address_left2 = unknown; 38 //framebuffer_sub.address_left2 = unknown;
39 framebuffer_sub.data.address_right1 = PADDR_SUB_FRAME2; 39 framebuffer_sub.address_right1 = PADDR_SUB_FRAME2;
40 //framebuffer_sub.data.address_right2 = unknown; 40 //framebuffer_sub.address_right2 = unknown;
41 break; 41 break;
42 } 42 }
43 43
@@ -46,14 +46,14 @@ void SetFramebufferLocation(const FramebufferLocation mode) {
46 auto& framebuffer_top = g_regs.Get<Regs::FramebufferTop>(); 46 auto& framebuffer_top = g_regs.Get<Regs::FramebufferTop>();
47 auto& framebuffer_sub = g_regs.Get<Regs::FramebufferBottom>(); 47 auto& framebuffer_sub = g_regs.Get<Regs::FramebufferBottom>();
48 48
49 framebuffer_top.data.address_left1 = PADDR_VRAM_TOP_LEFT_FRAME1; 49 framebuffer_top.address_left1 = PADDR_VRAM_TOP_LEFT_FRAME1;
50 framebuffer_top.data.address_left2 = PADDR_VRAM_TOP_LEFT_FRAME2; 50 framebuffer_top.address_left2 = PADDR_VRAM_TOP_LEFT_FRAME2;
51 framebuffer_top.data.address_right1 = PADDR_VRAM_TOP_RIGHT_FRAME1; 51 framebuffer_top.address_right1 = PADDR_VRAM_TOP_RIGHT_FRAME1;
52 framebuffer_top.data.address_right2 = PADDR_VRAM_TOP_RIGHT_FRAME2; 52 framebuffer_top.address_right2 = PADDR_VRAM_TOP_RIGHT_FRAME2;
53 framebuffer_sub.data.address_left1 = PADDR_VRAM_SUB_FRAME1; 53 framebuffer_sub.address_left1 = PADDR_VRAM_SUB_FRAME1;
54 //framebuffer_sub.data.address_left2 = unknown; 54 //framebuffer_sub.address_left2 = unknown;
55 framebuffer_sub.data.address_right1 = PADDR_VRAM_SUB_FRAME2; 55 framebuffer_sub.address_right1 = PADDR_VRAM_SUB_FRAME2;
56 //framebuffer_sub.data.address_right2 = unknown; 56 //framebuffer_sub.address_right2 = unknown;
57 break; 57 break;
58 } 58 }
59 } 59 }
@@ -135,14 +135,14 @@ inline void Write(u32 addr, const T data) {
135 const auto& config = g_regs.Get<Regs::MemoryFill>(static_cast<Regs::Id>(index - 3)); 135 const auto& config = g_regs.Get<Regs::MemoryFill>(static_cast<Regs::Id>(index - 3));
136 136
137 // TODO: Not sure if this check should be done at GSP level instead 137 // TODO: Not sure if this check should be done at GSP level instead
138 if (config.data.address_start) { 138 if (config.address_start) {
139 // TODO: Not sure if this algorithm is correct, particularly because it doesn't use the size member at all 139 // TODO: Not sure if this algorithm is correct, particularly because it doesn't use the size member at all
140 u32* start = (u32*)Memory::GetPointer(config.data.GetStartAddress()); 140 u32* start = (u32*)Memory::GetPointer(config.GetStartAddress());
141 u32* end = (u32*)Memory::GetPointer(config.data.GetEndAddress()); 141 u32* end = (u32*)Memory::GetPointer(config.GetEndAddress());
142 for (u32* ptr = start; ptr < end; ++ptr) 142 for (u32* ptr = start; ptr < end; ++ptr)
143 *ptr = bswap32(config.data.value); // TODO: This is just a workaround to missing framebuffer format emulation 143 *ptr = bswap32(config.value); // TODO: This is just a workaround to missing framebuffer format emulation
144 144
145 DEBUG_LOG(GPU, "MemoryFill from %x to %x", config.data.GetStartAddress(), config.data.GetEndAddress()); 145 DEBUG_LOG(GPU, "MemoryFill from %x to %x", config.GetStartAddress(), config.GetEndAddress());
146 } 146 }
147 break; 147 break;
148 } 148 }
@@ -150,20 +150,20 @@ inline void Write(u32 addr, const T data) {
150 case Regs::DisplayTransfer + 6: 150 case Regs::DisplayTransfer + 6:
151 { 151 {
152 const auto& config = g_regs.Get<Regs::DisplayTransfer>(); 152 const auto& config = g_regs.Get<Regs::DisplayTransfer>();
153 if (config.data.trigger & 1) { 153 if (config.trigger & 1) {
154 u8* source_pointer = Memory::GetPointer(config.data.GetPhysicalInputAddress()); 154 u8* source_pointer = Memory::GetPointer(config.GetPhysicalInputAddress());
155 u8* dest_pointer = Memory::GetPointer(config.data.GetPhysicalOutputAddress()); 155 u8* dest_pointer = Memory::GetPointer(config.GetPhysicalOutputAddress());
156 156
157 for (int y = 0; y < config.data.output_height; ++y) { 157 for (int y = 0; y < config.output_height; ++y) {
158 // TODO: Why does the register seem to hold twice the framebuffer width? 158 // TODO: Why does the register seem to hold twice the framebuffer width?
159 for (int x = 0; x < config.data.output_width / 2; ++x) { 159 for (int x = 0; x < config.output_width / 2; ++x) {
160 int source[4] = { 0, 0, 0, 0}; // rgba; 160 int source[4] = { 0, 0, 0, 0}; // rgba;
161 161
162 switch (config.data.input_format) { 162 switch (config.input_format) {
163 case Regs::FramebufferFormat::RGBA8: 163 case Regs::FramebufferFormat::RGBA8:
164 { 164 {
165 // TODO: Most likely got the component order messed up. 165 // TODO: Most likely got the component order messed up.
166 u8* srcptr = source_pointer + x * 4 + y * config.data.input_width * 4 / 2; 166 u8* srcptr = source_pointer + x * 4 + y * config.input_width * 4 / 2;
167 source[0] = srcptr[0]; // blue 167 source[0] = srcptr[0]; // blue
168 source[1] = srcptr[1]; // green 168 source[1] = srcptr[1]; // green
169 source[2] = srcptr[2]; // red 169 source[2] = srcptr[2]; // red
@@ -172,15 +172,15 @@ inline void Write(u32 addr, const T data) {
172 } 172 }
173 173
174 default: 174 default:
175 ERROR_LOG(GPU, "Unknown source framebuffer format %x", config.data.input_format.Value()); 175 ERROR_LOG(GPU, "Unknown source framebuffer format %x", config.input_format.Value());
176 break; 176 break;
177 } 177 }
178 178
179 switch (config.data.output_format) { 179 switch (config.output_format) {
180 /*case Regs::FramebufferFormat::RGBA8: 180 /*case Regs::FramebufferFormat::RGBA8:
181 { 181 {
182 // TODO: Untested 182 // TODO: Untested
183 u8* dstptr = (u32*)(dest_pointer + x * 4 + y * config.data.output_width * 4); 183 u8* dstptr = (u32*)(dest_pointer + x * 4 + y * config.output_width * 4);
184 dstptr[0] = source[0]; 184 dstptr[0] = source[0];
185 dstptr[1] = source[1]; 185 dstptr[1] = source[1];
186 dstptr[2] = source[2]; 186 dstptr[2] = source[2];
@@ -190,7 +190,7 @@ inline void Write(u32 addr, const T data) {
190 190
191 case Regs::FramebufferFormat::RGB8: 191 case Regs::FramebufferFormat::RGB8:
192 { 192 {
193 u8* dstptr = dest_pointer + x * 3 + y * config.data.output_width * 3 / 2; 193 u8* dstptr = dest_pointer + x * 3 + y * config.output_width * 3 / 2;
194 dstptr[0] = source[0]; // blue 194 dstptr[0] = source[0]; // blue
195 dstptr[1] = source[1]; // green 195 dstptr[1] = source[1]; // green
196 dstptr[2] = source[2]; // red 196 dstptr[2] = source[2]; // red
@@ -198,17 +198,17 @@ inline void Write(u32 addr, const T data) {
198 } 198 }
199 199
200 default: 200 default:
201 ERROR_LOG(GPU, "Unknown destination framebuffer format %x", config.data.output_format.Value()); 201 ERROR_LOG(GPU, "Unknown destination framebuffer format %x", config.output_format.Value());
202 break; 202 break;
203 } 203 }
204 } 204 }
205 } 205 }
206 206
207 DEBUG_LOG(GPU, "DisplayTriggerTransfer: %x bytes from %x(%xx%x)-> %x(%xx%x), dst format %x", 207 DEBUG_LOG(GPU, "DisplayTriggerTransfer: %x bytes from %x(%xx%x)-> %x(%xx%x), dst format %x",
208 config.data.output_height * config.data.output_width * 4, 208 config.output_height * config.output_width * 4,
209 config.data.GetPhysicalInputAddress(), (int)config.data.input_width, (int)config.data.input_height, 209 config.GetPhysicalInputAddress(), (int)config.input_width, (int)config.input_height,
210 config.data.GetPhysicalOutputAddress(), (int)config.data.output_width, (int)config.data.output_height, 210 config.GetPhysicalOutputAddress(), (int)config.output_width, (int)config.output_height,
211 config.data.output_format.Value()); 211 config.output_format.Value());
212 } 212 }
213 break; 213 break;
214 } 214 }
@@ -216,10 +216,10 @@ inline void Write(u32 addr, const T data) {
216 case Regs::CommandProcessor + 4: 216 case Regs::CommandProcessor + 4:
217 { 217 {
218 const auto& config = g_regs.Get<Regs::CommandProcessor>(); 218 const auto& config = g_regs.Get<Regs::CommandProcessor>();
219 if (config.data.trigger & 1) 219 if (config.trigger & 1)
220 { 220 {
221 // u32* buffer = (u32*)Memory::GetPointer(config.data.address << 3); 221 // u32* buffer = (u32*)Memory::GetPointer(config.address << 3);
222 ERROR_LOG(GPU, "Beginning %x bytes of commands from address %x", config.data.size, config.data.address << 3); 222 ERROR_LOG(GPU, "Beginning %x bytes of commands from address %x", config.size, config.address << 3);
223 // TODO: Process command list! 223 // TODO: Process command list!
224 } 224 }
225 break; 225 break;
@@ -263,17 +263,17 @@ void Init() {
263 auto& framebuffer_top = g_regs.Get<Regs::FramebufferTop>(); 263 auto& framebuffer_top = g_regs.Get<Regs::FramebufferTop>();
264 auto& framebuffer_sub = g_regs.Get<Regs::FramebufferBottom>(); 264 auto& framebuffer_sub = g_regs.Get<Regs::FramebufferBottom>();
265 // TODO: Width should be 240 instead? 265 // TODO: Width should be 240 instead?
266 framebuffer_top.data.width = 480; 266 framebuffer_top.width = 480;
267 framebuffer_top.data.height = 400; 267 framebuffer_top.height = 400;
268 framebuffer_top.data.stride = 480*3; 268 framebuffer_top.stride = 480*3;
269 framebuffer_top.data.color_format = Regs::FramebufferFormat::RGB8; 269 framebuffer_top.color_format = Regs::FramebufferFormat::RGB8;
270 framebuffer_top.data.active_fb = 0; 270 framebuffer_top.active_fb = 0;
271 271
272 framebuffer_sub.data.width = 480; 272 framebuffer_sub.width = 480;
273 framebuffer_sub.data.height = 400; 273 framebuffer_sub.height = 400;
274 framebuffer_sub.data.stride = 480*3; 274 framebuffer_sub.stride = 480*3;
275 framebuffer_sub.data.color_format = Regs::FramebufferFormat::RGB8; 275 framebuffer_sub.color_format = Regs::FramebufferFormat::RGB8;
276 framebuffer_sub.data.active_fb = 0; 276 framebuffer_sub.active_fb = 0;
277 277
278 NOTICE_LOG(GPU, "initialized OK"); 278 NOTICE_LOG(GPU, "initialized OK");
279} 279}
diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h
index ce524bd02..4ef0a047f 100644
--- a/src/core/hw/gpu.h
+++ b/src/core/hw/gpu.h
@@ -29,7 +29,7 @@ struct Regs {
29 }; 29 };
30 30
31 template<Id id> 31 template<Id id>
32 union Struct; 32 struct Struct;
33 33
34 enum class FramebufferFormat : u32 { 34 enum class FramebufferFormat : u32 {
35 RGBA8 = 0, 35 RGBA8 = 0,
@@ -38,128 +38,118 @@ struct Regs {
38 RGB5A1 = 3, 38 RGB5A1 = 3,
39 RGBA4 = 4, 39 RGBA4 = 4,
40 }; 40 };
41
42}; 41};
43 42
44template<> 43template<>
45union Regs::Struct<Regs::MemoryFill> { 44struct Regs::Struct<Regs::MemoryFill> {
46 struct { 45 u32 address_start;
47 u32 address_start; 46 u32 address_end; // ?
48 u32 address_end; // ? 47 u32 size;
49 u32 size; 48 u32 value; // ?
50 u32 value; // ? 49
51 50 inline u32 GetStartAddress() const {
52 inline u32 GetStartAddress() const { 51 return address_start * 8;
53 return address_start * 8; 52 }
54 } 53
55 54 inline u32 GetEndAddress() const {
56 inline u32 GetEndAddress() const { 55 return address_end * 8;
57 return address_end * 8; 56 }
58 }
59 } data;
60}; 57};
61static_assert(sizeof(Regs::Struct<Regs::MemoryFill>) == 0x10, "Structure size and register block length don't match"); 58static_assert(sizeof(Regs::Struct<Regs::MemoryFill>) == 0x10, "Structure size and register block length don't match");
62 59
63template<> 60template<>
64union Regs::Struct<Regs::FramebufferTop> { 61struct Regs::Struct<Regs::FramebufferTop> {
65 using Format = Regs::FramebufferFormat; 62 using Format = Regs::FramebufferFormat;
66 63
67 struct { 64 union {
68 union { 65 u32 size;
69 u32 size;
70 66
71 BitField< 0, 16, u32> width; 67 BitField< 0, 16, u32> width;
72 BitField<16, 16, u32> height; 68 BitField<16, 16, u32> height;
73 }; 69 };
74 70
75 u32 pad0[2]; 71 u32 pad0[2];
76 72
77 u32 address_left1; 73 u32 address_left1;
78 u32 address_left2; 74 u32 address_left2;
79 75
80 union { 76 union {
81 u32 format; 77 u32 format;
82 78
83 BitField< 0, 3, Format> color_format; 79 BitField< 0, 3, Format> color_format;
84 }; 80 };
85 81
86 u32 pad1; 82 u32 pad1;
87 83
88 union { 84 union {
89 u32 active_fb; 85 u32 active_fb;
90 86
91 BitField<0, 1, u32> second_fb_active; 87 BitField<0, 1, u32> second_fb_active;
92 }; 88 };
93 89
94 u32 pad2[5]; 90 u32 pad2[5];
95 91
96 u32 stride; 92 u32 stride;
97 93
98 u32 address_right1; 94 u32 address_right1;
99 u32 address_right2; 95 u32 address_right2;
100 } data;
101}; 96};
97
102template<> 98template<>
103union Regs::Struct<Regs::FramebufferBottom> { 99struct Regs::Struct<Regs::FramebufferBottom> : public Regs::Struct<Regs::FramebufferTop> {
104 using Type = decltype(Regs::Struct<Regs::FramebufferTop>::data);
105 Type data;
106}; 100};
107static_assert(sizeof(Regs::Struct<Regs::FramebufferTop>) == 0x40, "Structure size and register block length don't match"); 101static_assert(sizeof(Regs::Struct<Regs::FramebufferTop>) == 0x40, "Structure size and register block length don't match");
108 102
109template<> 103template<>
110union Regs::Struct<Regs::DisplayTransfer> { 104struct Regs::Struct<Regs::DisplayTransfer> {
111 using Format = Regs::FramebufferFormat; 105 using Format = Regs::FramebufferFormat;
112 106
113 struct { 107 u32 input_address;
114 u32 input_address; 108 u32 output_address;
115 u32 output_address;
116 109
117 inline u32 GetPhysicalInputAddress() const { 110 inline u32 GetPhysicalInputAddress() const {
118 return input_address * 8; 111 return input_address * 8;
119 } 112 }
120 113
121 inline u32 GetPhysicalOutputAddress() const { 114 inline u32 GetPhysicalOutputAddress() const {
122 return output_address * 8; 115 return output_address * 8;
123 } 116 }
124 117
125 union { 118 union {
126 u32 output_size; 119 u32 output_size;
127 120
128 BitField< 0, 16, u32> output_width; 121 BitField< 0, 16, u32> output_width;
129 BitField<16, 16, u32> output_height; 122 BitField<16, 16, u32> output_height;
130 }; 123 };
131 124
132 union { 125 union {
133 u32 input_size; 126 u32 input_size;
134 127
135 BitField< 0, 16, u32> input_width; 128 BitField< 0, 16, u32> input_width;
136 BitField<16, 16, u32> input_height; 129 BitField<16, 16, u32> input_height;
137 }; 130 };
138 131
139 union { 132 union {
140 u32 flags; 133 u32 flags;
141 134
142 BitField< 0, 1, u32> flip_data; 135 BitField< 0, 1, u32> flip_data;
143 BitField< 8, 3, Format> input_format; 136 BitField< 8, 3, Format> input_format;
144 BitField<12, 3, Format> output_format; 137 BitField<12, 3, Format> output_format;
145 BitField<16, 1, u32> output_tiled; 138 BitField<16, 1, u32> output_tiled;
146 }; 139 };
147 140
148 u32 unknown; 141 u32 unknown;
149 u32 trigger; 142 u32 trigger;
150 } data;
151}; 143};
152static_assert(sizeof(Regs::Struct<Regs::DisplayTransfer>) == 0x1C, "Structure size and register block length don't match"); 144static_assert(sizeof(Regs::Struct<Regs::DisplayTransfer>) == 0x1C, "Structure size and register block length don't match");
153 145
154template<> 146template<>
155union Regs::Struct<Regs::CommandProcessor> { 147struct Regs::Struct<Regs::CommandProcessor> {
156 struct { 148 u32 size;
157 u32 size; 149 u32 pad0;
158 u32 pad0; 150 u32 address;
159 u32 address; 151 u32 pad1;
160 u32 pad1; 152 u32 trigger;
161 u32 trigger;
162 } data;
163}; 153};
164static_assert(sizeof(Regs::Struct<Regs::CommandProcessor>) == 0x14, "Structure size and register block length don't match"); 154static_assert(sizeof(Regs::Struct<Regs::CommandProcessor>) == 0x14, "Structure size and register block length don't match");
165 155
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 8d9d61ae8..50f820e4a 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -80,17 +80,17 @@ void RendererOpenGL::RenderXFB(const common::Rect& src_rect, const common::Rect&
80 80
81 const auto& framebuffer_top = GPU::g_regs.Get<GPU::Regs::FramebufferTop>(); 81 const auto& framebuffer_top = GPU::g_regs.Get<GPU::Regs::FramebufferTop>();
82 const auto& framebuffer_sub = GPU::g_regs.Get<GPU::Regs::FramebufferBottom>(); 82 const auto& framebuffer_sub = GPU::g_regs.Get<GPU::Regs::FramebufferBottom>();
83 const u32 active_fb_top = (framebuffer_top.data.active_fb == 1) 83 const u32 active_fb_top = (framebuffer_top.active_fb == 1)
84 ? framebuffer_top.data.address_left2 84 ? framebuffer_top.address_left2
85 : framebuffer_top.data.address_left1; 85 : framebuffer_top.address_left1;
86 const u32 active_fb_sub = (framebuffer_sub.data.active_fb == 1) 86 const u32 active_fb_sub = (framebuffer_sub.active_fb == 1)
87 ? framebuffer_sub.data.address_left2 87 ? framebuffer_sub.address_left2
88 : framebuffer_sub.data.address_left1; 88 : framebuffer_sub.address_left1;
89 89
90 DEBUG_LOG(GPU, "RenderXFB: %x bytes from %x(%xx%x), fmt %x", 90 DEBUG_LOG(GPU, "RenderXFB: %x bytes from %x(%xx%x), fmt %x",
91 framebuffer_top.data.stride * framebuffer_top.data.height, 91 framebuffer_top.stride * framebuffer_top.height,
92 GPU::GetFramebufferAddr(active_fb_top), (int)framebuffer_top.data.width, 92 GPU::GetFramebufferAddr(active_fb_top), (int)framebuffer_top.width,
93 (int)framebuffer_top.data.height, (int)framebuffer_top.data.format); 93 (int)framebuffer_top.height, (int)framebuffer_top.format);
94 94
95 // TODO: This should consider the GPU registers for framebuffer width, height and stride. 95 // TODO: This should consider the GPU registers for framebuffer width, height and stride.
96 FlipFramebuffer(GPU::GetFramebufferPointer(active_fb_top), m_xfb_top_flipped); 96 FlipFramebuffer(GPU::GetFramebufferPointer(active_fb_top), m_xfb_top_flipped);