1 // Copyright 2009 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4 
5 #pragma once
6 
7 #include <array>
8 #include <string>
9 
10 #include "Common/BitField.h"
11 #include "Common/CommonTypes.h"
12 #include "Common/Inline.h"
13 
14 enum class EFBCopyFormat;
15 
16 #pragma pack(4)
17 
18 enum
19 {
20   BPMEM_GENMODE = 0x00,
21   BPMEM_DISPLAYCOPYFILTER = 0x01,  // 0x01 + 4
22   BPMEM_IND_MTXA = 0x06,           // 0x06 + (3 * 3)
23   BPMEM_IND_MTXB = 0x07,           // 0x07 + (3 * 3)
24   BPMEM_IND_MTXC = 0x08,           // 0x08 + (3 * 3)
25   BPMEM_IND_IMASK = 0x0F,
26   BPMEM_IND_CMD = 0x10,  // 0x10 + 16
27   BPMEM_SCISSORTL = 0x20,
28   BPMEM_SCISSORBR = 0x21,
29   BPMEM_LINEPTWIDTH = 0x22,
30   BPMEM_PERF0_TRI = 0x23,
31   BPMEM_PERF0_QUAD = 0x24,
32   BPMEM_RAS1_SS0 = 0x25,
33   BPMEM_RAS1_SS1 = 0x26,
34   BPMEM_IREF = 0x27,
35   BPMEM_TREF = 0x28,      // 0x28 + 8
36   BPMEM_SU_SSIZE = 0x30,  // 0x30 + (2 * 8)
37   BPMEM_SU_TSIZE = 0x31,  // 0x31 + (2 * 8)
38   BPMEM_ZMODE = 0x40,
39   BPMEM_BLENDMODE = 0x41,
40   BPMEM_CONSTANTALPHA = 0x42,
41   BPMEM_ZCOMPARE = 0x43,
42   BPMEM_FIELDMASK = 0x44,
43   BPMEM_SETDRAWDONE = 0x45,
44   BPMEM_BUSCLOCK0 = 0x46,
45   BPMEM_PE_TOKEN_ID = 0x47,
46   BPMEM_PE_TOKEN_INT_ID = 0x48,
47   BPMEM_EFB_TL = 0x49,
48   BPMEM_EFB_BR = 0x4A,
49   BPMEM_EFB_ADDR = 0x4B,
50   BPMEM_MIPMAP_STRIDE = 0x4D,
51   BPMEM_COPYYSCALE = 0x4E,
52   BPMEM_CLEAR_AR = 0x4F,
53   BPMEM_CLEAR_GB = 0x50,
54   BPMEM_CLEAR_Z = 0x51,
55   BPMEM_TRIGGER_EFB_COPY = 0x52,
56   BPMEM_COPYFILTER0 = 0x53,
57   BPMEM_COPYFILTER1 = 0x54,
58   BPMEM_CLEARBBOX1 = 0x55,
59   BPMEM_CLEARBBOX2 = 0x56,
60   BPMEM_CLEAR_PIXEL_PERF = 0x57,
61   BPMEM_REVBITS = 0x58,
62   BPMEM_SCISSOROFFSET = 0x59,
63   BPMEM_PRELOAD_ADDR = 0x60,
64   BPMEM_PRELOAD_TMEMEVEN = 0x61,
65   BPMEM_PRELOAD_TMEMODD = 0x62,
66   BPMEM_PRELOAD_MODE = 0x63,
67   BPMEM_LOADTLUT0 = 0x64,
68   BPMEM_LOADTLUT1 = 0x65,
69   BPMEM_TEXINVALIDATE = 0x66,
70   BPMEM_PERF1 = 0x67,
71   BPMEM_FIELDMODE = 0x68,
72   BPMEM_BUSCLOCK1 = 0x69,
73   BPMEM_TX_SETMODE0 = 0x80,     // 0x80 + 4
74   BPMEM_TX_SETMODE1 = 0x84,     // 0x84 + 4
75   BPMEM_TX_SETIMAGE0 = 0x88,    // 0x88 + 4
76   BPMEM_TX_SETIMAGE1 = 0x8C,    // 0x8C + 4
77   BPMEM_TX_SETIMAGE2 = 0x90,    // 0x90 + 4
78   BPMEM_TX_SETIMAGE3 = 0x94,    // 0x94 + 4
79   BPMEM_TX_SETTLUT = 0x98,      // 0x98 + 4
80   BPMEM_TX_SETMODE0_4 = 0xA0,   // 0xA0 + 4
81   BPMEM_TX_SETMODE1_4 = 0xA4,   // 0xA4 + 4
82   BPMEM_TX_SETIMAGE0_4 = 0xA8,  // 0xA8 + 4
83   BPMEM_TX_SETIMAGE1_4 = 0xAC,  // 0xA4 + 4
84   BPMEM_TX_SETIMAGE2_4 = 0xB0,  // 0xB0 + 4
85   BPMEM_TX_SETIMAGE3_4 = 0xB4,  // 0xB4 + 4
86   BPMEM_TX_SETTLUT_4 = 0xB8,    // 0xB8 + 4
87   BPMEM_TEV_COLOR_ENV = 0xC0,   // 0xC0 + (2 * 16)
88   BPMEM_TEV_ALPHA_ENV = 0xC1,   // 0xC1 + (2 * 16)
89   BPMEM_TEV_COLOR_RA = 0xE0,    // 0xE0 + (2 * 4)
90   BPMEM_TEV_COLOR_BG = 0xE1,    // 0xE1 + (2 * 4)
91   BPMEM_FOGRANGE = 0xE8,        // 0xE8 + 6
92   BPMEM_FOGPARAM0 = 0xEE,
93   BPMEM_FOGBMAGNITUDE = 0xEF,
94   BPMEM_FOGBEXPONENT = 0xF0,
95   BPMEM_FOGPARAM3 = 0xF1,
96   BPMEM_FOGCOLOR = 0xF2,
97   BPMEM_ALPHACOMPARE = 0xF3,
98   BPMEM_BIAS = 0xF4,
99   BPMEM_ZTEX2 = 0xF5,
100   BPMEM_TEV_KSEL = 0xF6,  // 0xF6 + 8
101   BPMEM_BP_MASK = 0xFE,
102 };
103 
104 // Tev/combiner things
105 
106 // TEV scaling type
107 enum : u32
108 {
109   TEVSCALE_1 = 0,
110   TEVSCALE_2 = 1,
111   TEVSCALE_4 = 2,
112   TEVDIVIDE_2 = 3
113 };
114 
115 enum : u32
116 {
117   TEVCMP_R8 = 0,
118   TEVCMP_GR16 = 1,
119   TEVCMP_BGR24 = 2,
120   TEVCMP_RGB8 = 3
121 };
122 
123 // TEV combiner operator
124 enum : u32
125 {
126   TEVOP_ADD = 0,
127   TEVOP_SUB = 1,
128   TEVCMP_R8_GT = 8,
129   TEVCMP_R8_EQ = 9,
130   TEVCMP_GR16_GT = 10,
131   TEVCMP_GR16_EQ = 11,
132   TEVCMP_BGR24_GT = 12,
133   TEVCMP_BGR24_EQ = 13,
134   TEVCMP_RGB8_GT = 14,
135   TEVCMP_RGB8_EQ = 15,
136   TEVCMP_A8_GT = TEVCMP_RGB8_GT,
137   TEVCMP_A8_EQ = TEVCMP_RGB8_EQ
138 };
139 
140 // TEV color combiner input
141 enum : u32
142 {
143   TEVCOLORARG_CPREV = 0,
144   TEVCOLORARG_APREV = 1,
145   TEVCOLORARG_C0 = 2,
146   TEVCOLORARG_A0 = 3,
147   TEVCOLORARG_C1 = 4,
148   TEVCOLORARG_A1 = 5,
149   TEVCOLORARG_C2 = 6,
150   TEVCOLORARG_A2 = 7,
151   TEVCOLORARG_TEXC = 8,
152   TEVCOLORARG_TEXA = 9,
153   TEVCOLORARG_RASC = 10,
154   TEVCOLORARG_RASA = 11,
155   TEVCOLORARG_ONE = 12,
156   TEVCOLORARG_HALF = 13,
157   TEVCOLORARG_KONST = 14,
158   TEVCOLORARG_ZERO = 15
159 };
160 
161 // TEV alpha combiner input
162 enum : u32
163 {
164   TEVALPHAARG_APREV = 0,
165   TEVALPHAARG_A0 = 1,
166   TEVALPHAARG_A1 = 2,
167   TEVALPHAARG_A2 = 3,
168   TEVALPHAARG_TEXA = 4,
169   TEVALPHAARG_RASA = 5,
170   TEVALPHAARG_KONST = 6,
171   TEVALPHAARG_ZERO = 7
172 };
173 
174 // TEV output registers
175 enum : u32
176 {
177   GX_TEVPREV = 0,
178   GX_TEVREG0 = 1,
179   GX_TEVREG1 = 2,
180   GX_TEVREG2 = 3
181 };
182 
183 // Z-texture formats
184 enum : u32
185 {
186   TEV_ZTEX_TYPE_U8 = 0,
187   TEV_ZTEX_TYPE_U16 = 1,
188   TEV_ZTEX_TYPE_U24 = 2
189 };
190 
191 // Z texture operator
192 enum : u32
193 {
194   ZTEXTURE_DISABLE = 0,
195   ZTEXTURE_ADD = 1,
196   ZTEXTURE_REPLACE = 2
197 };
198 
199 // TEV bias value
200 enum : u32
201 {
202   TEVBIAS_ZERO = 0,
203   TEVBIAS_ADDHALF = 1,
204   TEVBIAS_SUBHALF = 2,
205   TEVBIAS_COMPARE = 3
206 };
207 
208 // Indirect texture format
209 enum : u32
210 {
211   ITF_8 = 0,
212   ITF_5 = 1,
213   ITF_4 = 2,
214   ITF_3 = 3
215 };
216 
217 // Indirect texture bias
218 enum : u32
219 {
220   ITB_NONE = 0,
221   ITB_S = 1,
222   ITB_T = 2,
223   ITB_ST = 3,
224   ITB_U = 4,
225   ITB_SU = 5,
226   ITB_TU = 6,
227   ITB_STU = 7
228 };
229 
230 // Indirect texture bump alpha
231 enum : u32
232 {
233   ITBA_OFF = 0,
234   ITBA_S = 1,
235   ITBA_T = 2,
236   ITBA_U = 3
237 };
238 
239 // Indirect texture wrap value
240 enum : u32
241 {
242   ITW_OFF = 0,
243   ITW_256 = 1,
244   ITW_128 = 2,
245   ITW_64 = 3,
246   ITW_32 = 4,
247   ITW_16 = 5,
248   ITW_0 = 6
249 };
250 
251 union IND_MTXA
252 {
253   struct
254   {
255     s32 ma : 11;
256     s32 mb : 11;
257     u32 s0 : 2;  // bits 0-1 of scale factor
258     u32 rid : 8;
259   };
260   u32 hex;
261 };
262 
263 union IND_MTXB
264 {
265   struct
266   {
267     s32 mc : 11;
268     s32 md : 11;
269     u32 s1 : 2;  // bits 2-3 of scale factor
270     u32 rid : 8;
271   };
272   u32 hex;
273 };
274 
275 union IND_MTXC
276 {
277   struct
278   {
279     s32 me : 11;
280     s32 mf : 11;
281     u32 s2 : 2;  // bits 4-5 of scale factor
282     u32 rid : 8;
283   };
284   u32 hex;
285 };
286 
287 struct IND_MTX
288 {
289   IND_MTXA col0;
290   IND_MTXB col1;
291   IND_MTXC col2;
292 };
293 
294 union IND_IMASK
295 {
296   struct
297   {
298     u32 mask : 24;
299     u32 rid : 8;
300   };
301   u32 hex;
302 };
303 
304 struct TevStageCombiner
305 {
306   union ColorCombiner
307   {
308     // abc=8bit,d=10bit
309     BitField<0, 4, u32> d;   // TEVSELCC_X
310     BitField<4, 4, u32> c;   // TEVSELCC_X
311     BitField<8, 4, u32> b;   // TEVSELCC_X
312     BitField<12, 4, u32> a;  // TEVSELCC_X
313 
314     BitField<16, 2, u32> bias;
315     BitField<18, 1, u32> op;
316     BitField<19, 1, u32> clamp;
317 
318     BitField<20, 2, u32> shift;
319     BitField<22, 2, u32> dest;  // 1,2,3
320 
321     u32 hex;
322   };
323   union AlphaCombiner
324   {
325     BitField<0, 2, u32> rswap;
326     BitField<2, 2, u32> tswap;
327     BitField<4, 3, u32> d;   // TEVSELCA_
328     BitField<7, 3, u32> c;   // TEVSELCA_
329     BitField<10, 3, u32> b;  // TEVSELCA_
330     BitField<13, 3, u32> a;  // TEVSELCA_
331 
332     BitField<16, 2, u32> bias;  // GXTevBias
333     BitField<18, 1, u32> op;
334     BitField<19, 1, u32> clamp;
335 
336     BitField<20, 2, u32> shift;
337     BitField<22, 2, u32> dest;  // 1,2,3
338 
339     u32 hex;
340   };
341 
342   ColorCombiner colorC;
343   AlphaCombiner alphaC;
344 };
345 
346 // several discoveries:
347 // GXSetTevIndBumpST(tevstage, indstage, matrixind)
348 //  if ( matrix == 2 ) realmat = 6; // 10
349 //  else if ( matrix == 3 ) realmat = 7; // 11
350 //  else if ( matrix == 1 ) realmat = 5; // 9
351 //  GXSetTevIndirect(tevstage, indstage, 0, 3, realmat, 6, 6, 0, 0, 0)
352 //  GXSetTevIndirect(tevstage+1, indstage, 0, 3, realmat+4, 6, 6, 1, 0, 0)
353 //  GXSetTevIndirect(tevstage+2, indstage, 0, 0, 0, 0, 0, 1, 0, 0)
354 
355 union TevStageIndirect
356 {
357   BitField<0, 2, u32> bt;    // Indirect tex stage ID
358   BitField<2, 2, u32> fmt;   // Format: ITF_X
359   BitField<4, 3, u32> bias;  // ITB_X
360   BitField<7, 2, u32> bs;    // ITBA_X, indicates which coordinate will become the 'bump alpha'
361   BitField<9, 4, u32> mid;   // Matrix ID to multiply offsets with
362   BitField<13, 3, u32> sw;   // ITW_X, wrapping factor for S of regular coord
363   BitField<16, 3, u32> tw;   // ITW_X, wrapping factor for T of regular coord
364   BitField<19, 1, u32> lb_utclod;   // Use modified or unmodified texture
365                                     // coordinates for LOD computation
366   BitField<20, 1, u32> fb_addprev;  // 1 if the texture coordinate results from the previous TEV
367                                     // stage should be added
368 
369   struct
370   {
371     u32 hex : 21;
372     u32 unused : 11;
373   };
374 
375   // If bs and mid are zero, the result of the stage is independent of
376   // the texture sample data, so we can skip sampling the texture.
IsActive()377   bool IsActive() const { return bs != ITBA_OFF || mid != 0; }
378 };
379 
380 union TwoTevStageOrders
381 {
382   BitField<0, 3, u32> texmap0;  // Indirect tex stage texmap
383   BitField<3, 3, u32> texcoord0;
384   BitField<6, 1, u32> enable0;     // 1 if should read from texture
385   BitField<7, 3, u32> colorchan0;  // RAS1_CC_X
386 
387   BitField<12, 3, u32> texmap1;
388   BitField<15, 3, u32> texcoord1;
389   BitField<18, 1, u32> enable1;     // 1 if should read from texture
390   BitField<19, 3, u32> colorchan1;  // RAS1_CC_X
391 
392   BitField<24, 8, u32> rid;
393 
394   u32 hex;
getTexMap(int i)395   u32 getTexMap(int i) const { return i ? texmap1.Value() : texmap0.Value(); }
getTexCoord(int i)396   u32 getTexCoord(int i) const { return i ? texcoord1.Value() : texcoord0.Value(); }
getEnable(int i)397   u32 getEnable(int i) const { return i ? enable1.Value() : enable0.Value(); }
getColorChan(int i)398   u32 getColorChan(int i) const { return i ? colorchan1.Value() : colorchan0.Value(); }
399 };
400 
401 union TEXSCALE
402 {
403   struct
404   {
405     u32 ss0 : 4;  // Indirect tex stage 0, 2^(-ss0)
406     u32 ts0 : 4;  // Indirect tex stage 0
407     u32 ss1 : 4;  // Indirect tex stage 1
408     u32 ts1 : 4;  // Indirect tex stage 1
409     u32 pad : 8;
410     u32 rid : 8;
411   };
412   u32 hex;
413 };
414 
415 union RAS1_IREF
416 {
417   struct
418   {
419     u32 bi0 : 3;  // Indirect tex stage 0 ntexmap
420     u32 bc0 : 3;  // Indirect tex stage 0 ntexcoord
421     u32 bi1 : 3;
422     u32 bc1 : 3;
423     u32 bi2 : 3;
424     u32 bc3 : 3;
425     u32 bi4 : 3;
426     u32 bc4 : 3;
427     u32 rid : 8;
428   };
429   u32 hex;
430 
getTexCoord(int i)431   u32 getTexCoord(int i) const { return (hex >> (6 * i + 3)) & 7; }
getTexMap(int i)432   u32 getTexMap(int i) const { return (hex >> (6 * i)) & 7; }
433 };
434 
435 // Texture structs
436 
437 union TexMode0
438 {
439   enum TextureFilter : u32
440   {
441     TEXF_NONE = 0,
442     TEXF_POINT = 1,
443     TEXF_LINEAR = 2
444   };
445 
446   struct
447   {
448     u32 wrap_s : 2;
449     u32 wrap_t : 2;
450     u32 mag_filter : 1;
451     u32 min_filter : 3;
452     u32 diag_lod : 1;
453     s32 lod_bias : 8;
454     u32 pad0 : 2;
455     u32 max_aniso : 2;
456     u32 lod_clamp : 1;
457   };
458   u32 hex;
459 };
460 union TexMode1
461 {
462   struct
463   {
464     u32 min_lod : 8;
465     u32 max_lod : 8;
466   };
467   u32 hex;
468 };
469 union TexImage0
470 {
471   struct
472   {
473     u32 width : 10;   // Actually w-1
474     u32 height : 10;  // Actually h-1
475     u32 format : 4;
476   };
477   u32 hex;
478 };
479 union TexImage1
480 {
481   struct
482   {
483     u32 tmem_even : 15;  // TMEM line index for even LODs
484     u32 cache_width : 3;
485     u32 cache_height : 3;
486     u32 image_type : 1;  // 1 if this texture is managed manually (0 means we'll autofetch the
487                          // texture data whenever it changes)
488   };
489   u32 hex;
490 };
491 
492 union TexImage2
493 {
494   struct
495   {
496     u32 tmem_odd : 15;  // tmem line index for odd LODs
497     u32 cache_width : 3;
498     u32 cache_height : 3;
499   };
500   u32 hex;
501 };
502 
503 union TexImage3
504 {
505   struct
506   {
507     u32 image_base : 24;  // address in memory >> 5 (was 20 for GC)
508   };
509   u32 hex;
510 };
511 union TexTLUT
512 {
513   struct
514   {
515     u32 tmem_offset : 10;
516     u32 tlut_format : 2;
517   };
518   u32 hex;
519 };
520 
521 union ZTex1
522 {
523   BitField<0, 24, u32> bias;
524   u32 hex;
525 };
526 
527 union ZTex2
528 {
529   BitField<0, 2, u32> type;  // TEV_Z_TYPE_X
530   BitField<2, 2, u32> op;    // GXZTexOp
531   u32 hex;
532 };
533 
534 struct FourTexUnits
535 {
536   TexMode0 texMode0[4];
537   TexMode1 texMode1[4];
538   TexImage0 texImage0[4];
539   TexImage1 texImage1[4];
540   TexImage2 texImage2[4];
541   TexImage3 texImage3[4];
542   TexTLUT texTlut[4];
543   u32 unknown[4];
544 };
545 
546 // Geometry/other structs
547 
548 union GenMode
549 {
550   enum CullMode : u32
551   {
552     CULL_NONE = 0,
553     CULL_BACK = 1,   // cull back-facing primitives
554     CULL_FRONT = 2,  // cull front-facing primitives
555     CULL_ALL = 3,    // cull all primitives
556   };
557 
558   BitField<0, 4, u32> numtexgens;
559   BitField<4, 3, u32> numcolchans;
560   // 1 bit unused?
561   BitField<8, 1, u32> flat_shading;  // unconfirmed
562   BitField<9, 1, u32> multisampling;
563   BitField<10, 4, u32> numtevstages;
564   BitField<14, 2, CullMode> cullmode;
565   BitField<16, 3, u32> numindstages;
566   BitField<19, 1, u32> zfreeze;
567 
568   u32 hex;
569 };
570 
571 union LPSize
572 {
573   struct
574   {
575     u32 linesize : 8;   // in 1/6th pixels
576     u32 pointsize : 8;  // in 1/6th pixels
577     u32 lineoff : 3;
578     u32 pointoff : 3;
579     u32 lineaspect : 1;  // interlacing: adjust for pixels having AR of 1/2
580     u32 padding : 1;
581   };
582   u32 hex;
583 };
584 
585 union X12Y12
586 {
587   struct
588   {
589     u32 y : 12;
590     u32 x : 12;
591   };
592   u32 hex;
593 };
594 union X10Y10
595 {
596   struct
597   {
598     u32 x : 10;
599     u32 y : 10;
600   };
601   u32 hex;
602 };
603 
604 // Framebuffer/pixel stuff (incl fog)
605 
606 union BlendMode
607 {
608   enum BlendFactor : u32
609   {
610     ZERO = 0,
611     ONE = 1,
612     SRCCLR = 2,             // for dst factor
613     INVSRCCLR = 3,          // for dst factor
614     DSTCLR = SRCCLR,        // for src factor
615     INVDSTCLR = INVSRCCLR,  // for src factor
616     SRCALPHA = 4,
617     INVSRCALPHA = 5,
618     DSTALPHA = 6,
619     INVDSTALPHA = 7
620   };
621 
622   enum LogicOp : u32
623   {
624     CLEAR = 0,
625     AND = 1,
626     AND_REVERSE = 2,
627     COPY = 3,
628     AND_INVERTED = 4,
629     NOOP = 5,
630     XOR = 6,
631     OR = 7,
632     NOR = 8,
633     EQUIV = 9,
634     INVERT = 10,
635     OR_REVERSE = 11,
636     COPY_INVERTED = 12,
637     OR_INVERTED = 13,
638     NAND = 14,
639     SET = 15
640   };
641 
642   BitField<0, 1, u32> blendenable;
643   BitField<1, 1, u32> logicopenable;
644   BitField<2, 1, u32> dither;
645   BitField<3, 1, u32> colorupdate;
646   BitField<4, 1, u32> alphaupdate;
647   BitField<5, 3, BlendFactor> dstfactor;
648   BitField<8, 3, BlendFactor> srcfactor;
649   BitField<11, 1, u32> subtract;
650   BitField<12, 4, LogicOp> logicmode;
651 
652   u32 hex;
653 
654   bool UseLogicOp() const;
655 };
656 
657 union FogParam0
658 {
659   BitField<0, 11, u32> mant;
660   BitField<11, 8, u32> exp;
661   BitField<19, 1, u32> sign;
662 
663   u32 hex;
664 };
665 
666 union FogParam3
667 {
668   BitField<0, 11, u32> c_mant;
669   BitField<11, 8, u32> c_exp;
670   BitField<19, 1, u32> c_sign;
671   BitField<20, 1, u32> proj;  // 0 - perspective, 1 - orthographic
672   BitField<21, 3, u32> fsel;  // 0 - off, 2 - linear, 4 - exp, 5 - exp2, 6 -
673                               // backward exp, 7 - backward exp2
674 
675   u32 hex;
676 };
677 
678 union FogRangeKElement
679 {
680   BitField<0, 12, u32> HI;
681   BitField<12, 12, u32> LO;
682   BitField<24, 8, u32> regid;
683 
684   // TODO: Which scaling coefficient should we use here? This is just a guess!
GetValue(int i)685   float GetValue(int i) const { return (i ? HI.Value() : LO.Value()) / 256.f; }
686   u32 HEX;
687 };
688 
689 struct FogRangeParams
690 {
691   union RangeBase
692   {
693     BitField<0, 10, u32> Center;  // viewport center + 342
694     BitField<10, 1, u32> Enabled;
695     BitField<24, 8, u32> regid;
696     u32 hex;
697   };
698   RangeBase Base;
699   FogRangeKElement K[5];
700 };
701 // final eq: ze = A/(B_MAG - (Zs>>B_SHF));
702 struct FogParams
703 {
704   FogParam0 a;
705   u32 b_magnitude;
706   u32 b_shift;  // b's exp + 1?
707   FogParam3 c_proj_fsel;
708 
709   union FogColor
710   {
711     BitField<0, 8, u32> b;
712     BitField<8, 8, u32> g;
713     BitField<16, 8, u32> r;
714     u32 hex;
715   };
716 
717   FogColor color;  // 0:b 8:g 16:r - nice!
718 
719   // Special case where a and c are infinite and the sign matches, resulting in a result of NaN.
720   bool IsNaNCase() const;
721   float GetA() const;
722 
723   // amount to subtract from eyespacez after range adjustment
724   float GetC() const;
725 };
726 
727 union ZMode
728 {
729   enum CompareMode : u32
730   {
731     NEVER = 0,
732     LESS = 1,
733     EQUAL = 2,
734     LEQUAL = 3,
735     GREATER = 4,
736     NEQUAL = 5,
737     GEQUAL = 6,
738     ALWAYS = 7
739   };
740 
741   BitField<0, 1, u32> testenable;
742   BitField<1, 3, CompareMode> func;
743   BitField<4, 1, u32> updateenable;
744 
745   u32 hex;
746 };
747 
748 union ConstantAlpha
749 {
750   BitField<0, 8, u32> alpha;
751   BitField<8, 1, u32> enable;
752   u32 hex;
753 };
754 
755 union FieldMode
756 {
757   struct
758   {
759     u32 texLOD : 1;  // adjust vert tex LOD computation to account for interlacing
760   };
761   u32 hex;
762 };
763 
764 union FieldMask
765 {
766   struct
767   {
768     // If bit is not set, do not write field to EFB
769     u32 odd : 1;
770     u32 even : 1;
771   };
772   u32 hex;
773 };
774 
775 union PEControl
776 {
777   enum PixelFormat : u32
778   {
779     RGB8_Z24 = 0,
780     RGBA6_Z24 = 1,
781     RGB565_Z16 = 2,
782     Z24 = 3,
783     Y8 = 4,
784     U8 = 5,
785     V8 = 6,
786     YUV420 = 7,
787     INVALID_FMT = 0xffffffff,  // Used by Dolphin to represent a missing value.
788   };
789 
790   enum DepthFormat : u32
791   {
792     ZLINEAR = 0,
793     ZNEAR = 1,
794     ZMID = 2,
795     ZFAR = 3,
796 
797     // It seems these Z formats aren't supported/were removed ?
798     ZINV_LINEAR = 4,
799     ZINV_NEAR = 5,
800     ZINV_MID = 6,
801     ZINV_FAR = 7
802   };
803 
804   BitField<0, 3, PixelFormat> pixel_format;
805   BitField<3, 3, DepthFormat> zformat;
806   BitField<6, 1, u32> early_ztest;
807 
808   u32 hex;
809 };
810 
811 // Texture coordinate stuff
812 
813 union TCInfo
814 {
815   struct
816   {
817     u32 scale_minus_1 : 16;
818     u32 range_bias : 1;
819     u32 cylindric_wrap : 1;
820     // These bits only have effect in the s field of TCoordInfo
821     u32 line_offset : 1;
822     u32 point_offset : 1;
823   };
824   u32 hex;
825 };
826 struct TCoordInfo
827 {
828   TCInfo s;
829   TCInfo t;
830 };
831 
832 union TevReg
833 {
834   u64 hex;
835 
836   // Access to individual registers
837   BitField<0, 32, u64> low;
838   BitField<32, 32, u64> high;
839 
840   // TODO: Check if Konst uses all 11 bits or just 8
841 
842   // Low register
843   BitField<0, 11, s64> red;
844 
845   BitField<12, 11, s64> alpha;
846   BitField<23, 1, u64> type_ra;
847 
848   // High register
849   BitField<32, 11, s64> blue;
850 
851   BitField<44, 11, s64> green;
852   BitField<55, 1, u64> type_bg;
853 };
854 
855 union TevKSel
856 {
857   BitField<0, 2, u32> swap1;
858   BitField<2, 2, u32> swap2;
859   BitField<4, 5, u32> kcsel0;
860   BitField<9, 5, u32> kasel0;
861   BitField<14, 5, u32> kcsel1;
862   BitField<19, 5, u32> kasel1;
863   u32 hex;
864 
getKC(int i)865   u32 getKC(int i) const { return i ? kcsel1.Value() : kcsel0.Value(); }
getKA(int i)866   u32 getKA(int i) const { return i ? kasel1.Value() : kasel0.Value(); }
867 };
868 
869 union AlphaTest
870 {
871   enum CompareMode : u32
872   {
873     NEVER = 0,
874     LESS = 1,
875     EQUAL = 2,
876     LEQUAL = 3,
877     GREATER = 4,
878     NEQUAL = 5,
879     GEQUAL = 6,
880     ALWAYS = 7
881   };
882 
883   enum Op : u32
884   {
885     AND = 0,
886     OR = 1,
887     XOR = 2,
888     XNOR = 3
889   };
890 
891   BitField<0, 8, u32> ref0;
892   BitField<8, 8, u32> ref1;
893   BitField<16, 3, CompareMode> comp0;
894   BitField<19, 3, CompareMode> comp1;
895   BitField<22, 2, Op> logic;
896 
897   u32 hex;
898 
899   enum TEST_RESULT
900   {
901     UNDETERMINED = 0,
902     FAIL = 1,
903     PASS = 2,
904   };
905 
TestResult()906   DOLPHIN_FORCE_INLINE TEST_RESULT TestResult() const
907   {
908     switch (logic)
909     {
910     case AND:
911       if (comp0 == ALWAYS && comp1 == ALWAYS)
912         return PASS;
913       if (comp0 == NEVER || comp1 == NEVER)
914         return FAIL;
915       break;
916 
917     case OR:
918       if (comp0 == ALWAYS || comp1 == ALWAYS)
919         return PASS;
920       if (comp0 == NEVER && comp1 == NEVER)
921         return FAIL;
922       break;
923 
924     case XOR:
925       if ((comp0 == ALWAYS && comp1 == NEVER) || (comp0 == NEVER && comp1 == ALWAYS))
926         return PASS;
927       if ((comp0 == ALWAYS && comp1 == ALWAYS) || (comp0 == NEVER && comp1 == NEVER))
928         return FAIL;
929       break;
930 
931     case XNOR:
932       if ((comp0 == ALWAYS && comp1 == NEVER) || (comp0 == NEVER && comp1 == ALWAYS))
933         return FAIL;
934       if ((comp0 == ALWAYS && comp1 == ALWAYS) || (comp0 == NEVER && comp1 == NEVER))
935         return PASS;
936       break;
937 
938     default:
939       return UNDETERMINED;
940     }
941     return UNDETERMINED;
942   }
943 };
944 
945 union UPE_Copy
946 {
947   u32 Hex;
948 
949   BitField<0, 1, u32> clamp_top;            // if set clamp top
950   BitField<1, 1, u32> clamp_bottom;         // if set clamp bottom
951   BitField<2, 1, u32> yuv;                  // if set, color conversion from RGB to YUV
952   BitField<3, 4, u32> target_pixel_format;  // realformat is (fmt/2)+((fmt&1)*8).... for some reason
953                                             // the msb is the lsb (pattern: cycling right shift)
954   BitField<7, 2, u32> gamma;  // gamma correction.. 0 = 1.0 ; 1 = 1.7 ; 2 = 2.2 ; 3 is reserved
955   BitField<9, 1, u32>
956       half_scale;  // "mipmap" filter... 0 = no filter (scale 1:1) ; 1 = box filter (scale 2:1)
957   BitField<10, 1, u32> scale_invert;  // if set vertical scaling is on
958   BitField<11, 1, u32> clear;
959   BitField<12, 2, u32> frame_to_field;  // 0 progressive ; 1 is reserved ; 2 = interlaced (even
960                                         // lines) ; 3 = interlaced 1 (odd lines)
961   BitField<14, 1, u32> copy_to_xfb;
962   BitField<15, 1, u32> intensity_fmt;  // if set, is an intensity format (I4,I8,IA4,IA8)
963   BitField<16, 1, u32>
964       auto_conv;  // if 0 automatic color conversion by texture format and pixel type
965 
tp_realFormat()966   EFBCopyFormat tp_realFormat() const
967   {
968     return static_cast<EFBCopyFormat>(target_pixel_format / 2 + (target_pixel_format & 1) * 8);
969   }
970 };
971 
972 union CopyFilterCoefficients
973 {
974   using Values = std::array<u8, 7>;
975 
976   u64 Hex;
977 
978   BitField<0, 6, u64> w0;
979   BitField<6, 6, u64> w1;
980   BitField<12, 6, u64> w2;
981   BitField<18, 6, u64> w3;
982   BitField<32, 6, u64> w4;
983   BitField<38, 6, u64> w5;
984   BitField<44, 6, u64> w6;
985 
GetCoefficients()986   Values GetCoefficients() const
987   {
988     return {{
989         static_cast<u8>(w0),
990         static_cast<u8>(w1),
991         static_cast<u8>(w2),
992         static_cast<u8>(w3),
993         static_cast<u8>(w4),
994         static_cast<u8>(w5),
995         static_cast<u8>(w6),
996     }};
997   }
998 };
999 
1000 union BPU_PreloadTileInfo
1001 {
1002   u32 hex;
1003   struct
1004   {
1005     u32 count : 15;
1006     u32 type : 2;
1007   };
1008 };
1009 
1010 struct BPS_TmemConfig
1011 {
1012   u32 preload_addr;
1013   u32 preload_tmem_even;
1014   u32 preload_tmem_odd;
1015   BPU_PreloadTileInfo preload_tile_info;
1016   u32 tlut_src;
1017   u32 tlut_dest;
1018   u32 texinvalidate;
1019 };
1020 
1021 // All of BP memory
1022 
1023 struct BPCmd
1024 {
1025   int address;
1026   int changes;
1027   int newvalue;
1028 };
1029 
1030 struct BPMemory
1031 {
1032   GenMode genMode;
1033   u32 display_copy_filter[4];  // 01-04
1034   u32 unknown;                 // 05
1035   // indirect matrices (set by GXSetIndTexMtx, selected by TevStageIndirect::mid)
1036   // abc form a 2x3 offset matrix, there's 3 such matrices
1037   // the 3 offset matrices can either be indirect type, S-type, or T-type
1038   // 6bit scale factor s is distributed across IND_MTXA/B/C.
1039   // before using matrices scale by 2^-(s-17)
1040   IND_MTX indmtx[3];               // 06-0e GXSetIndTexMtx, 2x3 matrices
1041   IND_IMASK imask;                 // 0f
1042   TevStageIndirect tevind[16];     // 10 GXSetTevIndirect
1043   X12Y12 scissorTL;                // 20
1044   X12Y12 scissorBR;                // 21
1045   LPSize lineptwidth;              // 22 line and point width
1046   u32 sucounter;                   // 23
1047   u32 rascounter;                  // 24
1048   TEXSCALE texscale[2];            // 25-26 GXSetIndTexCoordScale
1049   RAS1_IREF tevindref;             // 27 GXSetIndTexOrder
1050   TwoTevStageOrders tevorders[8];  // 28-2F
1051   TCoordInfo texcoords[8];         // 0x30 s,t,s,t,s,t,s,t...
1052   ZMode zmode;                     // 40
1053   BlendMode blendmode;             // 41
1054   ConstantAlpha dstalpha;          // 42
1055   PEControl zcontrol;              // 43 GXSetZCompLoc, GXPixModeSync
1056   FieldMask fieldmask;             // 44
1057   u32 drawdone;                    // 45, bit1=1 if end of list
1058   u32 unknown5;                    // 46 clock?
1059   u32 petoken;                     // 47
1060   u32 petokenint;                  // 48
1061   X10Y10 copyTexSrcXY;             // 49
1062   X10Y10 copyTexSrcWH;             // 4a
1063   u32 copyTexDest;                 // 4b// 4b == CopyAddress (GXDispCopy and GXTexCopy use it)
1064   u32 unknown6;                    // 4c
1065   u32 copyMipMapStrideChannels;  // 4d usually set to 4 when dest is single channel, 8 when dest is
1066                                  // 2 channel, 16 when dest is RGBA
1067   // also, doubles whenever mipmap box filter option is set (excent on RGBA). Probably to do with
1068   // number of bytes to look at when smoothing
1069   u32 dispcopyyscale;                 // 4e
1070   u32 clearcolorAR;                   // 4f
1071   u32 clearcolorGB;                   // 50
1072   u32 clearZValue;                    // 51
1073   UPE_Copy triggerEFBCopy;            // 52
1074   CopyFilterCoefficients copyfilter;  // 53,54
1075   u32 boundbox0;                      // 55
1076   u32 boundbox1;                      // 56
1077   u32 unknown7[2];                    // 57,58
1078   X10Y10 scissorOffset;               // 59
1079   u32 unknown8[6];                    // 5a,5b,5c,5d, 5e,5f
1080   BPS_TmemConfig tmem_config;         // 60-66
1081   u32 metric;                         // 67
1082   FieldMode fieldmode;                // 68
1083   u32 unknown10[7];                   // 69-6F
1084   u32 unknown11[16];                  // 70-7F
1085   FourTexUnits tex[2];                // 80-bf
1086   TevStageCombiner combiners[16];     // 0xC0-0xDF
1087   TevReg tevregs[4];                  // 0xE0
1088   FogRangeParams fogRange;            // 0xE8
1089   FogParams fog;                      // 0xEE,0xEF,0xF0,0xF1,0xF2
1090   AlphaTest alpha_test;               // 0xF3
1091   ZTex1 ztex1;                        // 0xf4,0xf5
1092   ZTex2 ztex2;
1093   TevKSel tevksel[8];  // 0xf6,0xf7,f8,f9,fa,fb,fc,fd
1094   u32 bpMask;          // 0xFE
1095   u32 unknown18;       // ff
1096 
UseEarlyDepthTestBPMemory1097   bool UseEarlyDepthTest() const { return zcontrol.early_ztest && zmode.testenable; }
UseLateDepthTestBPMemory1098   bool UseLateDepthTest() const { return !zcontrol.early_ztest && zmode.testenable; }
1099 };
1100 
1101 #pragma pack()
1102 
1103 extern BPMemory bpmem;
1104 
1105 void LoadBPReg(u32 value0);
1106 void LoadBPRegPreprocess(u32 value0);
1107 
1108 void GetBPRegInfo(const u8* data, std::string* name, std::string* desc);
1109