forked from dolphin-emu/dolphin
		
	BreakBeforeBraces: Allman apparently includes all styles, except for AfterUnion (which is false) when using clang-format -dump-config
		
			
				
	
	
		
			1128 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1128 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // Copyright 2009 Dolphin Emulator Project
 | |
| // Licensed under GPLv2+
 | |
| // Refer to the license.txt file included.
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include <string>
 | |
| 
 | |
| #include "Common/BitField.h"
 | |
| #include "Common/CommonTypes.h"
 | |
| 
 | |
| #pragma pack(4)
 | |
| 
 | |
| enum
 | |
| {
 | |
|   BPMEM_GENMODE = 0x00,
 | |
|   BPMEM_DISPLAYCOPYFILTER = 0x01,  // 0x01 + 4
 | |
|   BPMEM_IND_MTXA = 0x06,           // 0x06 + (3 * 3)
 | |
|   BPMEM_IND_MTXB = 0x07,           // 0x07 + (3 * 3)
 | |
|   BPMEM_IND_MTXC = 0x08,           // 0x08 + (3 * 3)
 | |
|   BPMEM_IND_IMASK = 0x0F,
 | |
|   BPMEM_IND_CMD = 0x10,  // 0x10 + 16
 | |
|   BPMEM_SCISSORTL = 0x20,
 | |
|   BPMEM_SCISSORBR = 0x21,
 | |
|   BPMEM_LINEPTWIDTH = 0x22,
 | |
|   BPMEM_PERF0_TRI = 0x23,
 | |
|   BPMEM_PERF0_QUAD = 0x24,
 | |
|   BPMEM_RAS1_SS0 = 0x25,
 | |
|   BPMEM_RAS1_SS1 = 0x26,
 | |
|   BPMEM_IREF = 0x27,
 | |
|   BPMEM_TREF = 0x28,      // 0x28 + 8
 | |
|   BPMEM_SU_SSIZE = 0x30,  // 0x30 + (2 * 8)
 | |
|   BPMEM_SU_TSIZE = 0x31,  // 0x31 + (2 * 8)
 | |
|   BPMEM_ZMODE = 0x40,
 | |
|   BPMEM_BLENDMODE = 0x41,
 | |
|   BPMEM_CONSTANTALPHA = 0x42,
 | |
|   BPMEM_ZCOMPARE = 0x43,
 | |
|   BPMEM_FIELDMASK = 0x44,
 | |
|   BPMEM_SETDRAWDONE = 0x45,
 | |
|   BPMEM_BUSCLOCK0 = 0x46,
 | |
|   BPMEM_PE_TOKEN_ID = 0x47,
 | |
|   BPMEM_PE_TOKEN_INT_ID = 0x48,
 | |
|   BPMEM_EFB_TL = 0x49,
 | |
|   BPMEM_EFB_BR = 0x4A,
 | |
|   BPMEM_EFB_ADDR = 0x4B,
 | |
|   BPMEM_MIPMAP_STRIDE = 0x4D,
 | |
|   BPMEM_COPYYSCALE = 0x4E,
 | |
|   BPMEM_CLEAR_AR = 0x4F,
 | |
|   BPMEM_CLEAR_GB = 0x50,
 | |
|   BPMEM_CLEAR_Z = 0x51,
 | |
|   BPMEM_TRIGGER_EFB_COPY = 0x52,
 | |
|   BPMEM_COPYFILTER0 = 0x53,
 | |
|   BPMEM_COPYFILTER1 = 0x54,
 | |
|   BPMEM_CLEARBBOX1 = 0x55,
 | |
|   BPMEM_CLEARBBOX2 = 0x56,
 | |
|   BPMEM_CLEAR_PIXEL_PERF = 0x57,
 | |
|   BPMEM_REVBITS = 0x58,
 | |
|   BPMEM_SCISSOROFFSET = 0x59,
 | |
|   BPMEM_PRELOAD_ADDR = 0x60,
 | |
|   BPMEM_PRELOAD_TMEMEVEN = 0x61,
 | |
|   BPMEM_PRELOAD_TMEMODD = 0x62,
 | |
|   BPMEM_PRELOAD_MODE = 0x63,
 | |
|   BPMEM_LOADTLUT0 = 0x64,
 | |
|   BPMEM_LOADTLUT1 = 0x65,
 | |
|   BPMEM_TEXINVALIDATE = 0x66,
 | |
|   BPMEM_PERF1 = 0x67,
 | |
|   BPMEM_FIELDMODE = 0x68,
 | |
|   BPMEM_BUSCLOCK1 = 0x69,
 | |
|   BPMEM_TX_SETMODE0 = 0x80,     // 0x80 + 4
 | |
|   BPMEM_TX_SETMODE1 = 0x84,     // 0x84 + 4
 | |
|   BPMEM_TX_SETIMAGE0 = 0x88,    // 0x88 + 4
 | |
|   BPMEM_TX_SETIMAGE1 = 0x8C,    // 0x8C + 4
 | |
|   BPMEM_TX_SETIMAGE2 = 0x90,    // 0x90 + 4
 | |
|   BPMEM_TX_SETIMAGE3 = 0x94,    // 0x94 + 4
 | |
|   BPMEM_TX_SETTLUT = 0x98,      // 0x98 + 4
 | |
|   BPMEM_TX_SETMODE0_4 = 0xA0,   // 0xA0 + 4
 | |
|   BPMEM_TX_SETMODE1_4 = 0xA4,   // 0xA4 + 4
 | |
|   BPMEM_TX_SETIMAGE0_4 = 0xA8,  // 0xA8 + 4
 | |
|   BPMEM_TX_SETIMAGE1_4 = 0xAC,  // 0xA4 + 4
 | |
|   BPMEM_TX_SETIMAGE2_4 = 0xB0,  // 0xB0 + 4
 | |
|   BPMEM_TX_SETIMAGE3_4 = 0xB4,  // 0xB4 + 4
 | |
|   BPMEM_TX_SETTLUT_4 = 0xB8,    // 0xB8 + 4
 | |
|   BPMEM_TEV_COLOR_ENV = 0xC0,   // 0xC0 + (2 * 16)
 | |
|   BPMEM_TEV_ALPHA_ENV = 0xC1,   // 0xC1 + (2 * 16)
 | |
|   BPMEM_TEV_COLOR_RA = 0xE0,    // 0xE0 + (2 * 4)
 | |
|   BPMEM_TEV_COLOR_BG = 0xE1,    // 0xE1 + (2 * 4)
 | |
|   BPMEM_FOGRANGE = 0xE8,        // 0xE8 + 6
 | |
|   BPMEM_FOGPARAM0 = 0xEE,
 | |
|   BPMEM_FOGBMAGNITUDE = 0xEF,
 | |
|   BPMEM_FOGBEXPONENT = 0xF0,
 | |
|   BPMEM_FOGPARAM3 = 0xF1,
 | |
|   BPMEM_FOGCOLOR = 0xF2,
 | |
|   BPMEM_ALPHACOMPARE = 0xF3,
 | |
|   BPMEM_BIAS = 0xF4,
 | |
|   BPMEM_ZTEX2 = 0xF5,
 | |
|   BPMEM_TEV_KSEL = 0xF6,  // 0xF6 + 8
 | |
|   BPMEM_BP_MASK = 0xFE,
 | |
| };
 | |
| 
 | |
| // Tev/combiner things
 | |
| 
 | |
| // TEV scaling type
 | |
| enum : u32
 | |
| {
 | |
|   TEVSCALE_1 = 0,
 | |
|   TEVSCALE_2 = 1,
 | |
|   TEVSCALE_4 = 2,
 | |
|   TEVDIVIDE_2 = 3
 | |
| };
 | |
| 
 | |
| enum : u32
 | |
| {
 | |
|   TEVCMP_R8 = 0,
 | |
|   TEVCMP_GR16 = 1,
 | |
|   TEVCMP_BGR24 = 2,
 | |
|   TEVCMP_RGB8 = 3
 | |
| };
 | |
| 
 | |
| // TEV combiner operator
 | |
| enum : u32
 | |
| {
 | |
|   TEVOP_ADD = 0,
 | |
|   TEVOP_SUB = 1,
 | |
|   TEVCMP_R8_GT = 8,
 | |
|   TEVCMP_R8_EQ = 9,
 | |
|   TEVCMP_GR16_GT = 10,
 | |
|   TEVCMP_GR16_EQ = 11,
 | |
|   TEVCMP_BGR24_GT = 12,
 | |
|   TEVCMP_BGR24_EQ = 13,
 | |
|   TEVCMP_RGB8_GT = 14,
 | |
|   TEVCMP_RGB8_EQ = 15,
 | |
|   TEVCMP_A8_GT = TEVCMP_RGB8_GT,
 | |
|   TEVCMP_A8_EQ = TEVCMP_RGB8_EQ
 | |
| };
 | |
| 
 | |
| // TEV color combiner input
 | |
| enum : u32
 | |
| {
 | |
|   TEVCOLORARG_CPREV = 0,
 | |
|   TEVCOLORARG_APREV = 1,
 | |
|   TEVCOLORARG_C0 = 2,
 | |
|   TEVCOLORARG_A0 = 3,
 | |
|   TEVCOLORARG_C1 = 4,
 | |
|   TEVCOLORARG_A1 = 5,
 | |
|   TEVCOLORARG_C2 = 6,
 | |
|   TEVCOLORARG_A2 = 7,
 | |
|   TEVCOLORARG_TEXC = 8,
 | |
|   TEVCOLORARG_TEXA = 9,
 | |
|   TEVCOLORARG_RASC = 10,
 | |
|   TEVCOLORARG_RASA = 11,
 | |
|   TEVCOLORARG_ONE = 12,
 | |
|   TEVCOLORARG_HALF = 13,
 | |
|   TEVCOLORARG_KONST = 14,
 | |
|   TEVCOLORARG_ZERO = 15
 | |
| };
 | |
| 
 | |
| // TEV alpha combiner input
 | |
| enum : u32
 | |
| {
 | |
|   TEVALPHAARG_APREV = 0,
 | |
|   TEVALPHAARG_A0 = 1,
 | |
|   TEVALPHAARG_A1 = 2,
 | |
|   TEVALPHAARG_A2 = 3,
 | |
|   TEVALPHAARG_TEXA = 4,
 | |
|   TEVALPHAARG_RASA = 5,
 | |
|   TEVALPHAARG_KONST = 6,
 | |
|   TEVALPHAARG_ZERO = 7
 | |
| };
 | |
| 
 | |
| // TEV output registers
 | |
| enum : u32
 | |
| {
 | |
|   GX_TEVPREV = 0,
 | |
|   GX_TEVREG0 = 1,
 | |
|   GX_TEVREG1 = 2,
 | |
|   GX_TEVREG2 = 3
 | |
| };
 | |
| 
 | |
| // Z-texture formats
 | |
| enum : u32
 | |
| {
 | |
|   TEV_ZTEX_TYPE_U8 = 0,
 | |
|   TEV_ZTEX_TYPE_U16 = 1,
 | |
|   TEV_ZTEX_TYPE_U24 = 2
 | |
| };
 | |
| 
 | |
| // Z texture operator
 | |
| enum : u32
 | |
| {
 | |
|   ZTEXTURE_DISABLE = 0,
 | |
|   ZTEXTURE_ADD = 1,
 | |
|   ZTEXTURE_REPLACE = 2
 | |
| };
 | |
| 
 | |
| // TEV bias value
 | |
| enum : u32
 | |
| {
 | |
|   TEVBIAS_ZERO = 0,
 | |
|   TEVBIAS_ADDHALF = 1,
 | |
|   TEVBIAS_SUBHALF = 2,
 | |
|   TEVBIAS_COMPARE = 3
 | |
| };
 | |
| 
 | |
| // Indirect texture format
 | |
| enum : u32
 | |
| {
 | |
|   ITF_8 = 0,
 | |
|   ITF_5 = 1,
 | |
|   ITF_4 = 2,
 | |
|   ITF_3 = 3
 | |
| };
 | |
| 
 | |
| // Indirect texture bias
 | |
| enum : u32
 | |
| {
 | |
|   ITB_NONE = 0,
 | |
|   ITB_S = 1,
 | |
|   ITB_T = 2,
 | |
|   ITB_ST = 3,
 | |
|   ITB_U = 4,
 | |
|   ITB_SU = 5,
 | |
|   ITB_TU = 6,
 | |
|   ITB_STU = 7
 | |
| };
 | |
| 
 | |
| // Indirect texture bump alpha
 | |
| enum : u32
 | |
| {
 | |
|   ITBA_OFF = 0,
 | |
|   ITBA_S = 1,
 | |
|   ITBA_T = 2,
 | |
|   ITBA_U = 3
 | |
| };
 | |
| 
 | |
| // Indirect texture wrap value
 | |
| enum : u32
 | |
| {
 | |
|   ITW_OFF = 0,
 | |
|   ITW_256 = 1,
 | |
|   ITW_128 = 2,
 | |
|   ITW_64 = 3,
 | |
|   ITW_32 = 4,
 | |
|   ITW_16 = 5,
 | |
|   ITW_0 = 6
 | |
| };
 | |
| 
 | |
| union IND_MTXA
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     s32 ma : 11;
 | |
|     s32 mb : 11;
 | |
|     u32 s0 : 2;  // bits 0-1 of scale factor
 | |
|     u32 rid : 8;
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| union IND_MTXB
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     s32 mc : 11;
 | |
|     s32 md : 11;
 | |
|     u32 s1 : 2;  // bits 2-3 of scale factor
 | |
|     u32 rid : 8;
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| union IND_MTXC
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     s32 me : 11;
 | |
|     s32 mf : 11;
 | |
|     u32 s2 : 2;  // bits 4-5 of scale factor
 | |
|     u32 rid : 8;
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| struct IND_MTX
 | |
| {
 | |
|   IND_MTXA col0;
 | |
|   IND_MTXB col1;
 | |
|   IND_MTXC col2;
 | |
| };
 | |
| 
 | |
| union IND_IMASK
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 mask : 24;
 | |
|     u32 rid : 8;
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| struct TevStageCombiner
 | |
| {
 | |
|   union ColorCombiner
 | |
|   {
 | |
|     struct  // abc=8bit,d=10bit
 | |
|     {
 | |
|       u32 d : 4;  // TEVSELCC_X
 | |
|       u32 c : 4;  // TEVSELCC_X
 | |
|       u32 b : 4;  // TEVSELCC_X
 | |
|       u32 a : 4;  // TEVSELCC_X
 | |
| 
 | |
|       u32 bias : 2;
 | |
|       u32 op : 1;
 | |
|       u32 clamp : 1;
 | |
| 
 | |
|       u32 shift : 2;
 | |
|       u32 dest : 2;  // 1,2,3
 | |
|     };
 | |
|     u32 hex;
 | |
|   };
 | |
|   union AlphaCombiner
 | |
|   {
 | |
|     struct
 | |
|     {
 | |
|       u32 rswap : 2;
 | |
|       u32 tswap : 2;
 | |
|       u32 d : 3;  // TEVSELCA_
 | |
|       u32 c : 3;  // TEVSELCA_
 | |
|       u32 b : 3;  // TEVSELCA_
 | |
|       u32 a : 3;  // TEVSELCA_
 | |
| 
 | |
|       u32 bias : 2;  // GXTevBias
 | |
|       u32 op : 1;
 | |
|       u32 clamp : 1;
 | |
| 
 | |
|       u32 shift : 2;
 | |
|       u32 dest : 2;  // 1,2,3
 | |
|     };
 | |
|     u32 hex;
 | |
|   };
 | |
| 
 | |
|   ColorCombiner colorC;
 | |
|   AlphaCombiner alphaC;
 | |
| };
 | |
| 
 | |
| // several discoveries:
 | |
| // GXSetTevIndBumpST(tevstage, indstage, matrixind)
 | |
| //  if ( matrix == 2 ) realmat = 6; // 10
 | |
| //  else if ( matrix == 3 ) realmat = 7; // 11
 | |
| //  else if ( matrix == 1 ) realmat = 5; // 9
 | |
| //  GXSetTevIndirect(tevstage, indstage, 0, 3, realmat, 6, 6, 0, 0, 0)
 | |
| //  GXSetTevIndirect(tevstage+1, indstage, 0, 3, realmat+4, 6, 6, 1, 0, 0)
 | |
| //  GXSetTevIndirect(tevstage+2, indstage, 0, 0, 0, 0, 0, 1, 0, 0)
 | |
| 
 | |
| union TevStageIndirect
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 bt : 2;          // Indirect tex stage ID
 | |
|     u32 fmt : 2;         // Format: ITF_X
 | |
|     u32 bias : 3;        // ITB_X
 | |
|     u32 bs : 2;          // ITBA_X, indicates which coordinate will become the 'bump alpha'
 | |
|     u32 mid : 4;         // Matrix ID to multiply offsets with
 | |
|     u32 sw : 3;          // ITW_X, wrapping factor for S of regular coord
 | |
|     u32 tw : 3;          // ITW_X, wrapping factor for T of regular coord
 | |
|     u32 lb_utclod : 1;   // Use modified or unmodified texture coordinates for LOD computation
 | |
|     u32 fb_addprev : 1;  // 1 if the texture coordinate results from the previous TEV stage should
 | |
|                          // be added
 | |
|     u32 pad0 : 3;
 | |
|     u32 rid : 8;
 | |
|   };
 | |
|   struct
 | |
|   {
 | |
|     u32 hex : 21;
 | |
|     u32 unused : 11;
 | |
|   };
 | |
| 
 | |
|   // If bs and mid are zero, the result of the stage is independent of
 | |
|   // the texture sample data, so we can skip sampling the texture.
 | |
|   bool IsActive() { return bs != ITBA_OFF || mid != 0; }
 | |
| };
 | |
| 
 | |
| union TwoTevStageOrders
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 texmap0 : 3;  // Indirect tex stage texmap
 | |
|     u32 texcoord0 : 3;
 | |
|     u32 enable0 : 1;     // 1 if should read from texture
 | |
|     u32 colorchan0 : 3;  // RAS1_CC_X
 | |
| 
 | |
|     u32 pad0 : 2;
 | |
| 
 | |
|     u32 texmap1 : 3;
 | |
|     u32 texcoord1 : 3;
 | |
|     u32 enable1 : 1;     // 1 if should read from texture
 | |
|     u32 colorchan1 : 3;  // RAS1_CC_X
 | |
| 
 | |
|     u32 pad1 : 2;
 | |
|     u32 rid : 8;
 | |
|   };
 | |
|   u32 hex;
 | |
|   int getTexMap(int i) const { return i ? texmap1 : texmap0; }
 | |
|   int getTexCoord(int i) const { return i ? texcoord1 : texcoord0; }
 | |
|   int getEnable(int i) const { return i ? enable1 : enable0; }
 | |
|   int getColorChan(int i) const { return i ? colorchan1 : colorchan0; }
 | |
| };
 | |
| 
 | |
| union TEXSCALE
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 ss0 : 4;  // Indirect tex stage 0, 2^(-ss0)
 | |
|     u32 ts0 : 4;  // Indirect tex stage 0
 | |
|     u32 ss1 : 4;  // Indirect tex stage 1
 | |
|     u32 ts1 : 4;  // Indirect tex stage 1
 | |
|     u32 pad : 8;
 | |
|     u32 rid : 8;
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| union RAS1_IREF
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 bi0 : 3;  // Indirect tex stage 0 ntexmap
 | |
|     u32 bc0 : 3;  // Indirect tex stage 0 ntexcoord
 | |
|     u32 bi1 : 3;
 | |
|     u32 bc1 : 3;
 | |
|     u32 bi2 : 3;
 | |
|     u32 bc3 : 3;
 | |
|     u32 bi4 : 3;
 | |
|     u32 bc4 : 3;
 | |
|     u32 rid : 8;
 | |
|   };
 | |
|   u32 hex;
 | |
| 
 | |
|   u32 getTexCoord(int i) { return (hex >> (6 * i + 3)) & 7; }
 | |
|   u32 getTexMap(int i) { return (hex >> (6 * i)) & 7; }
 | |
| };
 | |
| 
 | |
| // Texture structs
 | |
| 
 | |
| union TexMode0
 | |
| {
 | |
|   enum TextureFilter : u32
 | |
|   {
 | |
|     TEXF_NONE = 0,
 | |
|     TEXF_POINT = 1,
 | |
|     TEXF_LINEAR = 2
 | |
|   };
 | |
| 
 | |
|   struct
 | |
|   {
 | |
|     u32 wrap_s : 2;
 | |
|     u32 wrap_t : 2;
 | |
|     u32 mag_filter : 1;
 | |
|     u32 min_filter : 3;
 | |
|     u32 diag_lod : 1;
 | |
|     s32 lod_bias : 8;
 | |
|     u32 pad0 : 2;
 | |
|     u32 max_aniso : 2;
 | |
|     u32 lod_clamp : 1;
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| union TexMode1
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 min_lod : 8;
 | |
|     u32 max_lod : 8;
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| union TexImage0
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 width : 10;   // Actually w-1
 | |
|     u32 height : 10;  // Actually h-1
 | |
|     u32 format : 4;
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| union TexImage1
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 tmem_even : 15;  // TMEM line index for even LODs
 | |
|     u32 cache_width : 3;
 | |
|     u32 cache_height : 3;
 | |
|     u32 image_type : 1;  // 1 if this texture is managed manually (0 means we'll autofetch the
 | |
|                          // texture data whenever it changes)
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| union TexImage2
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 tmem_odd : 15;  // tmem line index for odd LODs
 | |
|     u32 cache_width : 3;
 | |
|     u32 cache_height : 3;
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| union TexImage3
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 image_base : 24;  // address in memory >> 5 (was 20 for GC)
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| union TexTLUT
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 tmem_offset : 10;
 | |
|     u32 tlut_format : 2;
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| union ZTex1
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 bias : 24;
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| union ZTex2
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 type : 2;  // TEV_Z_TYPE_X
 | |
|     u32 op : 2;    // GXZTexOp
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| struct FourTexUnits
 | |
| {
 | |
|   TexMode0 texMode0[4];
 | |
|   TexMode1 texMode1[4];
 | |
|   TexImage0 texImage0[4];
 | |
|   TexImage1 texImage1[4];
 | |
|   TexImage2 texImage2[4];
 | |
|   TexImage3 texImage3[4];
 | |
|   TexTLUT texTlut[4];
 | |
|   u32 unknown[4];
 | |
| };
 | |
| 
 | |
| // Geometry/other structs
 | |
| 
 | |
| union GenMode
 | |
| {
 | |
|   enum CullMode : u32
 | |
|   {
 | |
|     CULL_NONE = 0,
 | |
|     CULL_BACK = 1,   // cull back-facing primitives
 | |
|     CULL_FRONT = 2,  // cull front-facing primitives
 | |
|     CULL_ALL = 3,    // cull all primitives
 | |
|   };
 | |
| 
 | |
|   BitField<0, 4, u32> numtexgens;
 | |
|   BitField<4, 3, u32> numcolchans;
 | |
|   // 1 bit unused?
 | |
|   BitField<8, 1, u32> flat_shading;  // unconfirmed
 | |
|   BitField<9, 1, u32> multisampling;
 | |
|   BitField<10, 4, u32> numtevstages;
 | |
|   BitField<14, 2, CullMode> cullmode;
 | |
|   BitField<16, 3, u32> numindstages;
 | |
|   BitField<19, 1, u32> zfreeze;
 | |
| 
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| union LPSize
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 linesize : 8;   // in 1/6th pixels
 | |
|     u32 pointsize : 8;  // in 1/6th pixels
 | |
|     u32 lineoff : 3;
 | |
|     u32 pointoff : 3;
 | |
|     u32 lineaspect : 1;  // interlacing: adjust for pixels having AR of 1/2
 | |
|     u32 padding : 1;
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| union X12Y12
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 y : 12;
 | |
|     u32 x : 12;
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| union X10Y10
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 x : 10;
 | |
|     u32 y : 10;
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| // Framebuffer/pixel stuff (incl fog)
 | |
| 
 | |
| union BlendMode
 | |
| {
 | |
|   enum BlendFactor : u32
 | |
|   {
 | |
|     ZERO = 0,
 | |
|     ONE = 1,
 | |
|     SRCCLR = 2,             // for dst factor
 | |
|     INVSRCCLR = 3,          // for dst factor
 | |
|     DSTCLR = SRCCLR,        // for src factor
 | |
|     INVDSTCLR = INVSRCCLR,  // for src factor
 | |
|     SRCALPHA = 4,
 | |
|     INVSRCALPHA = 5,
 | |
|     DSTALPHA = 6,
 | |
|     INVDSTALPHA = 7
 | |
|   };
 | |
| 
 | |
|   enum LogicOp : u32
 | |
|   {
 | |
|     CLEAR = 0,
 | |
|     AND = 1,
 | |
|     AND_REVERSE = 2,
 | |
|     COPY = 3,
 | |
|     AND_INVERTED = 4,
 | |
|     NOOP = 5,
 | |
|     XOR = 6,
 | |
|     OR = 7,
 | |
|     NOR = 8,
 | |
|     EQUIV = 9,
 | |
|     INVERT = 10,
 | |
|     OR_REVERSE = 11,
 | |
|     COPY_INVERTED = 12,
 | |
|     OR_INVERTED = 13,
 | |
|     NAND = 14,
 | |
|     SET = 15
 | |
|   };
 | |
| 
 | |
|   BitField<0, 1, u32> blendenable;
 | |
|   BitField<1, 1, u32> logicopenable;
 | |
|   BitField<2, 1, u32> dither;
 | |
|   BitField<3, 1, u32> colorupdate;
 | |
|   BitField<4, 1, u32> alphaupdate;
 | |
|   BitField<5, 3, BlendFactor> dstfactor;
 | |
|   BitField<8, 3, BlendFactor> srcfactor;
 | |
|   BitField<11, 1, u32> subtract;
 | |
|   BitField<12, 4, LogicOp> logicmode;
 | |
| 
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| union FogParam0
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 mantissa : 11;
 | |
|     u32 exponent : 8;
 | |
|     u32 sign : 1;
 | |
|   };
 | |
| 
 | |
|   float GetA()
 | |
|   {
 | |
|     union
 | |
|     {
 | |
|       u32 i;
 | |
|       float f;
 | |
|     } dummy;
 | |
|     dummy.i = ((u32)sign << 31) | ((u32)exponent << 23) |
 | |
|               ((u32)mantissa << 12);  // scale mantissa from 11 to 23 bits
 | |
|     return dummy.f;
 | |
|   }
 | |
| 
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| union FogParam3
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 c_mant : 11;
 | |
|     u32 c_exp : 8;
 | |
|     u32 c_sign : 1;
 | |
|     u32 proj : 1;  // 0 - perspective, 1 - orthographic
 | |
|     u32 fsel : 3;  // 0 - off, 2 - linear, 4 - exp, 5 - exp2, 6 - backward exp, 7 - backward exp2
 | |
|   };
 | |
| 
 | |
|   // amount to subtract from eyespacez after range adjustment
 | |
|   float GetC()
 | |
|   {
 | |
|     union
 | |
|     {
 | |
|       u32 i;
 | |
|       float f;
 | |
|     } dummy;
 | |
|     dummy.i = ((u32)c_sign << 31) | ((u32)c_exp << 23) |
 | |
|               ((u32)c_mant << 12);  // scale mantissa from 11 to 23 bits
 | |
|     return dummy.f;
 | |
|   }
 | |
| 
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| union FogRangeKElement
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 HI : 12;
 | |
|     u32 LO : 12;
 | |
|     u32 regid : 8;
 | |
|   };
 | |
| 
 | |
|   // TODO: Which scaling coefficient should we use here? This is just a guess!
 | |
|   float GetValue(int i) { return (i ? HI : LO) / 256.f; }
 | |
|   u32 HEX;
 | |
| };
 | |
| 
 | |
| struct FogRangeParams
 | |
| {
 | |
|   union RangeBase
 | |
|   {
 | |
|     struct
 | |
|     {
 | |
|       u32 Center : 10;  // viewport center + 342
 | |
|       u32 Enabled : 1;
 | |
|       u32 unused : 13;
 | |
|       u32 regid : 8;
 | |
|     };
 | |
|     u32 hex;
 | |
|   };
 | |
|   RangeBase Base;
 | |
|   FogRangeKElement K[5];
 | |
| };
 | |
| // final eq: ze = A/(B_MAG - (Zs>>B_SHF));
 | |
| struct FogParams
 | |
| {
 | |
|   FogParam0 a;
 | |
|   u32 b_magnitude;
 | |
|   u32 b_shift;  // b's exp + 1?
 | |
|   FogParam3 c_proj_fsel;
 | |
| 
 | |
|   union FogColor
 | |
|   {
 | |
|     struct
 | |
|     {
 | |
|       u32 b : 8;
 | |
|       u32 g : 8;
 | |
|       u32 r : 8;
 | |
|     };
 | |
|     u32 hex;
 | |
|   };
 | |
| 
 | |
|   FogColor color;  // 0:b 8:g 16:r - nice!
 | |
| };
 | |
| 
 | |
| union ZMode
 | |
| {
 | |
|   enum CompareMode : u32
 | |
|   {
 | |
|     NEVER = 0,
 | |
|     LESS = 1,
 | |
|     EQUAL = 2,
 | |
|     LEQUAL = 3,
 | |
|     GREATER = 4,
 | |
|     NEQUAL = 5,
 | |
|     GEQUAL = 6,
 | |
|     ALWAYS = 7
 | |
|   };
 | |
| 
 | |
|   BitField<0, 1, u32> testenable;
 | |
|   BitField<1, 3, CompareMode> func;
 | |
|   BitField<4, 1, u32> updateenable;
 | |
| 
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| union ConstantAlpha
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 alpha : 8;
 | |
|     u32 enable : 1;
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| union FieldMode
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 texLOD : 1;  // adjust vert tex LOD computation to account for interlacing
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| union FieldMask
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     // If bit is not set, do not write field to EFB
 | |
|     u32 odd : 1;
 | |
|     u32 even : 1;
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| union PEControl
 | |
| {
 | |
|   enum PixelFormat : u32
 | |
|   {
 | |
|     RGB8_Z24 = 0,
 | |
|     RGBA6_Z24 = 1,
 | |
|     RGB565_Z16 = 2,
 | |
|     Z24 = 3,
 | |
|     Y8 = 4,
 | |
|     U8 = 5,
 | |
|     V8 = 6,
 | |
|     YUV420 = 7,
 | |
|     INVALID_FMT = 0xffffffff,  // Used by Dolphin to represent a missing value.
 | |
|   };
 | |
| 
 | |
|   enum DepthFormat : u32
 | |
|   {
 | |
|     ZLINEAR = 0,
 | |
|     ZNEAR = 1,
 | |
|     ZMID = 2,
 | |
|     ZFAR = 3,
 | |
| 
 | |
|     // It seems these Z formats aren't supported/were removed ?
 | |
|     ZINV_LINEAR = 4,
 | |
|     ZINV_NEAR = 5,
 | |
|     ZINV_MID = 6,
 | |
|     ZINV_FAR = 7
 | |
|   };
 | |
| 
 | |
|   BitField<0, 3, PixelFormat> pixel_format;
 | |
|   BitField<3, 3, DepthFormat> zformat;
 | |
|   BitField<6, 1, u32> early_ztest;
 | |
| 
 | |
|   u32 hex;
 | |
| };
 | |
| 
 | |
| // Texture coordinate stuff
 | |
| 
 | |
| union TCInfo
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 scale_minus_1 : 16;
 | |
|     u32 range_bias : 1;
 | |
|     u32 cylindric_wrap : 1;
 | |
|     // These bits only have effect in the s field of TCoordInfo
 | |
|     u32 line_offset : 1;
 | |
|     u32 point_offset : 1;
 | |
|   };
 | |
|   u32 hex;
 | |
| };
 | |
| struct TCoordInfo
 | |
| {
 | |
|   TCInfo s;
 | |
|   TCInfo t;
 | |
| };
 | |
| 
 | |
| union TevReg
 | |
| {
 | |
|   u64 hex;
 | |
| 
 | |
|   // Access to individual registers
 | |
|   BitField<0, 32, u64> low;
 | |
|   BitField<32, 32, u64> high;
 | |
| 
 | |
|   // TODO: Check if Konst uses all 11 bits or just 8
 | |
| 
 | |
|   // Low register
 | |
|   BitField<0, 11, s64> red;
 | |
| 
 | |
|   BitField<12, 11, s64> alpha;
 | |
|   BitField<23, 1, u64> type_ra;
 | |
| 
 | |
|   // High register
 | |
|   BitField<32, 11, s64> blue;
 | |
| 
 | |
|   BitField<44, 11, s64> green;
 | |
|   BitField<55, 1, u64> type_bg;
 | |
| };
 | |
| 
 | |
| union TevKSel
 | |
| {
 | |
|   struct
 | |
|   {
 | |
|     u32 swap1 : 2;
 | |
|     u32 swap2 : 2;
 | |
|     u32 kcsel0 : 5;
 | |
|     u32 kasel0 : 5;
 | |
|     u32 kcsel1 : 5;
 | |
|     u32 kasel1 : 5;
 | |
|   };
 | |
|   u32 hex;
 | |
| 
 | |
|   int getKC(int i) { return i ? kcsel1 : kcsel0; }
 | |
|   int getKA(int i) { return i ? kasel1 : kasel0; }
 | |
| };
 | |
| 
 | |
| union AlphaTest
 | |
| {
 | |
|   enum CompareMode : u32
 | |
|   {
 | |
|     NEVER = 0,
 | |
|     LESS = 1,
 | |
|     EQUAL = 2,
 | |
|     LEQUAL = 3,
 | |
|     GREATER = 4,
 | |
|     NEQUAL = 5,
 | |
|     GEQUAL = 6,
 | |
|     ALWAYS = 7
 | |
|   };
 | |
| 
 | |
|   enum Op : u32
 | |
|   {
 | |
|     AND = 0,
 | |
|     OR = 1,
 | |
|     XOR = 2,
 | |
|     XNOR = 3
 | |
|   };
 | |
| 
 | |
|   BitField<0, 8, u32> ref0;
 | |
|   BitField<8, 8, u32> ref1;
 | |
|   BitField<16, 3, CompareMode> comp0;
 | |
|   BitField<19, 3, CompareMode> comp1;
 | |
|   BitField<22, 2, Op> logic;
 | |
| 
 | |
|   u32 hex;
 | |
| 
 | |
|   enum TEST_RESULT
 | |
|   {
 | |
|     UNDETERMINED = 0,
 | |
|     FAIL = 1,
 | |
|     PASS = 2,
 | |
|   };
 | |
| 
 | |
|   __forceinline TEST_RESULT TestResult() const
 | |
|   {
 | |
|     switch (logic)
 | |
|     {
 | |
|     case AND:
 | |
|       if (comp0 == ALWAYS && comp1 == ALWAYS)
 | |
|         return PASS;
 | |
|       if (comp0 == NEVER || comp1 == NEVER)
 | |
|         return FAIL;
 | |
|       break;
 | |
| 
 | |
|     case OR:
 | |
|       if (comp0 == ALWAYS || comp1 == ALWAYS)
 | |
|         return PASS;
 | |
|       if (comp0 == NEVER && comp1 == NEVER)
 | |
|         return FAIL;
 | |
|       break;
 | |
| 
 | |
|     case XOR:
 | |
|       if ((comp0 == ALWAYS && comp1 == NEVER) || (comp0 == NEVER && comp1 == ALWAYS))
 | |
|         return PASS;
 | |
|       if ((comp0 == ALWAYS && comp1 == ALWAYS) || (comp0 == NEVER && comp1 == NEVER))
 | |
|         return FAIL;
 | |
|       break;
 | |
| 
 | |
|     case XNOR:
 | |
|       if ((comp0 == ALWAYS && comp1 == NEVER) || (comp0 == NEVER && comp1 == ALWAYS))
 | |
|         return FAIL;
 | |
|       if ((comp0 == ALWAYS && comp1 == ALWAYS) || (comp0 == NEVER && comp1 == NEVER))
 | |
|         return PASS;
 | |
|       break;
 | |
| 
 | |
|     default:
 | |
|       return UNDETERMINED;
 | |
|     }
 | |
|     return UNDETERMINED;
 | |
|   }
 | |
| };
 | |
| 
 | |
| union UPE_Copy
 | |
| {
 | |
|   u32 Hex;
 | |
| 
 | |
|   BitField<0, 1, u32> clamp0;               // if set clamp top
 | |
|   BitField<1, 1, u32> clamp1;               // if set clamp bottom
 | |
|   BitField<2, 1, u32> yuv;                  // if set, color conversion from RGB to YUV
 | |
|   BitField<3, 4, u32> target_pixel_format;  // realformat is (fmt/2)+((fmt&1)*8).... for some reason
 | |
|                                             // the msb is the lsb (pattern: cycling right shift)
 | |
|   BitField<7, 2, u32> gamma;  // gamma correction.. 0 = 1.0 ; 1 = 1.7 ; 2 = 2.2 ; 3 is reserved
 | |
|   BitField<9, 1, u32>
 | |
|       half_scale;  // "mipmap" filter... 0 = no filter (scale 1:1) ; 1 = box filter (scale 2:1)
 | |
|   BitField<10, 1, u32> scale_invert;  // if set vertical scaling is on
 | |
|   BitField<11, 1, u32> clear;
 | |
|   BitField<12, 2, u32> frame_to_field;  // 0 progressive ; 1 is reserved ; 2 = interlaced (even
 | |
|                                         // lines) ; 3 = interlaced 1 (odd lines)
 | |
|   BitField<14, 1, u32> copy_to_xfb;
 | |
|   BitField<15, 1, u32> intensity_fmt;  // if set, is an intensity format (I4,I8,IA4,IA8)
 | |
|   BitField<16, 1, u32>
 | |
|       auto_conv;  // if 0 automatic color conversion by texture format and pixel type
 | |
| 
 | |
|   u32 tp_realFormat() { return target_pixel_format / 2 + (target_pixel_format & 1) * 8; }
 | |
| };
 | |
| 
 | |
| union BPU_PreloadTileInfo
 | |
| {
 | |
|   u32 hex;
 | |
|   struct
 | |
|   {
 | |
|     u32 count : 15;
 | |
|     u32 type : 2;
 | |
|   };
 | |
| };
 | |
| 
 | |
| struct BPS_TmemConfig
 | |
| {
 | |
|   u32 preload_addr;
 | |
|   u32 preload_tmem_even;
 | |
|   u32 preload_tmem_odd;
 | |
|   BPU_PreloadTileInfo preload_tile_info;
 | |
|   u32 tlut_src;
 | |
|   u32 tlut_dest;
 | |
|   u32 texinvalidate;
 | |
| };
 | |
| 
 | |
| // All of BP memory
 | |
| 
 | |
| struct BPCmd
 | |
| {
 | |
|   int address;
 | |
|   int changes;
 | |
|   int newvalue;
 | |
| };
 | |
| 
 | |
| struct BPMemory
 | |
| {
 | |
|   GenMode genMode;
 | |
|   u32 display_copy_filter[4];  // 01-04
 | |
|   u32 unknown;                 // 05
 | |
|   // indirect matrices (set by GXSetIndTexMtx, selected by TevStageIndirect::mid)
 | |
|   // abc form a 2x3 offset matrix, there's 3 such matrices
 | |
|   // the 3 offset matrices can either be indirect type, S-type, or T-type
 | |
|   // 6bit scale factor s is distributed across IND_MTXA/B/C.
 | |
|   // before using matrices scale by 2^-(s-17)
 | |
|   IND_MTX indmtx[3];               // 06-0e GXSetIndTexMtx, 2x3 matrices
 | |
|   IND_IMASK imask;                 // 0f
 | |
|   TevStageIndirect tevind[16];     // 10 GXSetTevIndirect
 | |
|   X12Y12 scissorTL;                // 20
 | |
|   X12Y12 scissorBR;                // 21
 | |
|   LPSize lineptwidth;              // 22 line and point width
 | |
|   u32 sucounter;                   // 23
 | |
|   u32 rascounter;                  // 24
 | |
|   TEXSCALE texscale[2];            // 25-26 GXSetIndTexCoordScale
 | |
|   RAS1_IREF tevindref;             // 27 GXSetIndTexOrder
 | |
|   TwoTevStageOrders tevorders[8];  // 28-2F
 | |
|   TCoordInfo texcoords[8];         // 0x30 s,t,s,t,s,t,s,t...
 | |
|   ZMode zmode;                     // 40
 | |
|   BlendMode blendmode;             // 41
 | |
|   ConstantAlpha dstalpha;          // 42
 | |
|   PEControl zcontrol;              // 43 GXSetZCompLoc, GXPixModeSync
 | |
|   FieldMask fieldmask;             // 44
 | |
|   u32 drawdone;                    // 45, bit1=1 if end of list
 | |
|   u32 unknown5;                    // 46 clock?
 | |
|   u32 petoken;                     // 47
 | |
|   u32 petokenint;                  // 48
 | |
|   X10Y10 copyTexSrcXY;             // 49
 | |
|   X10Y10 copyTexSrcWH;             // 4a
 | |
|   u32 copyTexDest;                 // 4b// 4b == CopyAddress (GXDispCopy and GXTexCopy use it)
 | |
|   u32 unknown6;                    // 4c
 | |
|   u32 copyMipMapStrideChannels;  // 4d usually set to 4 when dest is single channel, 8 when dest is
 | |
|                                  // 2 channel, 16 when dest is RGBA
 | |
|   // also, doubles whenever mipmap box filter option is set (excent on RGBA). Probably to do with
 | |
|   // number of bytes to look at when smoothing
 | |
|   u32 dispcopyyscale;              // 4e
 | |
|   u32 clearcolorAR;                // 4f
 | |
|   u32 clearcolorGB;                // 50
 | |
|   u32 clearZValue;                 // 51
 | |
|   UPE_Copy triggerEFBCopy;         // 52
 | |
|   u32 copyfilter[2];               // 53,54
 | |
|   u32 boundbox0;                   // 55
 | |
|   u32 boundbox1;                   // 56
 | |
|   u32 unknown7[2];                 // 57,58
 | |
|   X10Y10 scissorOffset;            // 59
 | |
|   u32 unknown8[6];                 // 5a,5b,5c,5d, 5e,5f
 | |
|   BPS_TmemConfig tmem_config;      // 60-66
 | |
|   u32 metric;                      // 67
 | |
|   FieldMode fieldmode;             // 68
 | |
|   u32 unknown10[7];                // 69-6F
 | |
|   u32 unknown11[16];               // 70-7F
 | |
|   FourTexUnits tex[2];             // 80-bf
 | |
|   TevStageCombiner combiners[16];  // 0xC0-0xDF
 | |
|   TevReg tevregs[4];               // 0xE0
 | |
|   FogRangeParams fogRange;         // 0xE8
 | |
|   FogParams fog;                   // 0xEE,0xEF,0xF0,0xF1,0xF2
 | |
|   AlphaTest alpha_test;            // 0xF3
 | |
|   ZTex1 ztex1;                     // 0xf4,0xf5
 | |
|   ZTex2 ztex2;
 | |
|   TevKSel tevksel[8];  // 0xf6,0xf7,f8,f9,fa,fb,fc,fd
 | |
|   u32 bpMask;          // 0xFE
 | |
|   u32 unknown18;       // ff
 | |
| 
 | |
|   bool UseEarlyDepthTest() const { return zcontrol.early_ztest && zmode.testenable; }
 | |
|   bool UseLateDepthTest() const { return !zcontrol.early_ztest && zmode.testenable; }
 | |
| };
 | |
| 
 | |
| #pragma pack()
 | |
| 
 | |
| extern BPMemory bpmem;
 | |
| 
 | |
| void LoadBPReg(u32 value0);
 | |
| void LoadBPRegPreprocess(u32 value0);
 | |
| 
 | |
| void GetBPRegInfo(const u8* data, std::string* name, std::string* desc);
 |