Merge pull request #10549 from Pokechu22/sw-tev-enum-map
Refactor various bits of graphics code for readability
This commit is contained in:
commit
2dfe91336a
|
@ -58,7 +58,7 @@ public:
|
|||
constexpr V& operator[](BitField<position, bits, T, StorageType> key)
|
||||
{
|
||||
static_assert(1 << bits == s_size, "Unsafe indexing into EnumMap (may go out of bounds)");
|
||||
return m_array[static_cast<std::size_t>(key.value())];
|
||||
return m_array[static_cast<std::size_t>(key.Value())];
|
||||
}
|
||||
|
||||
constexpr bool InBounds(T key) const { return static_cast<std::size_t>(key) < s_size; }
|
||||
|
|
|
@ -224,7 +224,7 @@ public:
|
|||
const auto [name, desc] = GetXFTransferInfo(address, count, data);
|
||||
ASSERT(!name.empty());
|
||||
|
||||
const u32 command = address | (count << 16);
|
||||
const u32 command = address | ((count - 1) << 16);
|
||||
|
||||
text = QStringLiteral("XF %1 ").arg(command, 8, 16, QLatin1Char('0'));
|
||||
|
||||
|
|
|
@ -108,8 +108,6 @@ static std::vector<BPFunctions::ScissorRect> scissors;
|
|||
|
||||
void Init()
|
||||
{
|
||||
tev.Init();
|
||||
|
||||
// The other slopes are set each for each primitive drawn, but zfreeze means that the z slope
|
||||
// needs to be set to an (untested) default value.
|
||||
ZSlope = Slope();
|
||||
|
@ -142,9 +140,9 @@ static inline int iround(float x)
|
|||
return t;
|
||||
}
|
||||
|
||||
void SetTevReg(int reg, int comp, s16 color)
|
||||
void SetTevKonstColors()
|
||||
{
|
||||
tev.SetRegColor(reg, comp, color);
|
||||
tev.SetKonstColors();
|
||||
}
|
||||
|
||||
static void Draw(s32 x, s32 y, s32 xi, s32 yi)
|
||||
|
@ -288,13 +286,10 @@ static void BuildBlock(s32 blockX, s32 blockY)
|
|||
}
|
||||
}
|
||||
|
||||
u32 indref = bpmem.tevindref.hex;
|
||||
for (unsigned int i = 0; i < bpmem.genMode.numindstages; i++)
|
||||
{
|
||||
u32 texmap = indref & 7;
|
||||
indref >>= 3;
|
||||
u32 texcoord = indref & 7;
|
||||
indref >>= 3;
|
||||
u32 texmap = bpmem.tevindref.getTexMap(i);
|
||||
u32 texcoord = bpmem.tevindref.getTexCoord(i);
|
||||
|
||||
CalculateLOD(&rasterBlock.IndirectLod[i], &rasterBlock.IndirectLinear[i], texmap, texcoord);
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ void UpdateZSlope(const OutputVertexData* v0, const OutputVertexData* v1,
|
|||
void DrawTriangleFrontFace(const OutputVertexData* v0, const OutputVertexData* v1,
|
||||
const OutputVertexData* v2);
|
||||
|
||||
void SetTevReg(int reg, int comp, s16 color);
|
||||
void SetTevKonstColors();
|
||||
|
||||
struct RasterBlockPixel
|
||||
{
|
||||
|
|
|
@ -67,15 +67,7 @@ void SWVertexLoader::DrawCurrentBatch(u32 base_index, u32 num_indices, u32 base_
|
|||
g_renderer->BBoxFlush();
|
||||
|
||||
m_setup_unit.Init(primitive_type);
|
||||
|
||||
// set all states with are stored within video sw
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Rasterizer::SetTevReg(i, Tev::RED_C, PixelShaderManager::constants.kcolors[i][0]);
|
||||
Rasterizer::SetTevReg(i, Tev::GRN_C, PixelShaderManager::constants.kcolors[i][1]);
|
||||
Rasterizer::SetTevReg(i, Tev::BLU_C, PixelShaderManager::constants.kcolors[i][2]);
|
||||
Rasterizer::SetTevReg(i, Tev::ALP_C, PixelShaderManager::constants.kcolors[i][3]);
|
||||
}
|
||||
Rasterizer::SetTevKonstColors();
|
||||
|
||||
for (u32 i = 0; i < m_index_generator.GetIndexLen(); i++)
|
||||
{
|
||||
|
|
|
@ -27,190 +27,49 @@
|
|||
#define ALLOW_TEV_DUMPS 0
|
||||
#endif
|
||||
|
||||
void Tev::Init()
|
||||
{
|
||||
FixedConstants[0] = 0;
|
||||
FixedConstants[1] = 32;
|
||||
FixedConstants[2] = 64;
|
||||
FixedConstants[3] = 96;
|
||||
FixedConstants[4] = 128;
|
||||
FixedConstants[5] = 159;
|
||||
FixedConstants[6] = 191;
|
||||
FixedConstants[7] = 223;
|
||||
FixedConstants[8] = 255;
|
||||
|
||||
for (s16& comp : Zero16)
|
||||
{
|
||||
comp = 0;
|
||||
}
|
||||
|
||||
m_ColorInputLUT[0][RED_INP] = &Reg[0][RED_C];
|
||||
m_ColorInputLUT[0][GRN_INP] = &Reg[0][GRN_C];
|
||||
m_ColorInputLUT[0][BLU_INP] = &Reg[0][BLU_C]; // prev.rgb
|
||||
m_ColorInputLUT[1][RED_INP] = &Reg[0][ALP_C];
|
||||
m_ColorInputLUT[1][GRN_INP] = &Reg[0][ALP_C];
|
||||
m_ColorInputLUT[1][BLU_INP] = &Reg[0][ALP_C]; // prev.aaa
|
||||
m_ColorInputLUT[2][RED_INP] = &Reg[1][RED_C];
|
||||
m_ColorInputLUT[2][GRN_INP] = &Reg[1][GRN_C];
|
||||
m_ColorInputLUT[2][BLU_INP] = &Reg[1][BLU_C]; // c0.rgb
|
||||
m_ColorInputLUT[3][RED_INP] = &Reg[1][ALP_C];
|
||||
m_ColorInputLUT[3][GRN_INP] = &Reg[1][ALP_C];
|
||||
m_ColorInputLUT[3][BLU_INP] = &Reg[1][ALP_C]; // c0.aaa
|
||||
m_ColorInputLUT[4][RED_INP] = &Reg[2][RED_C];
|
||||
m_ColorInputLUT[4][GRN_INP] = &Reg[2][GRN_C];
|
||||
m_ColorInputLUT[4][BLU_INP] = &Reg[2][BLU_C]; // c1.rgb
|
||||
m_ColorInputLUT[5][RED_INP] = &Reg[2][ALP_C];
|
||||
m_ColorInputLUT[5][GRN_INP] = &Reg[2][ALP_C];
|
||||
m_ColorInputLUT[5][BLU_INP] = &Reg[2][ALP_C]; // c1.aaa
|
||||
m_ColorInputLUT[6][RED_INP] = &Reg[3][RED_C];
|
||||
m_ColorInputLUT[6][GRN_INP] = &Reg[3][GRN_C];
|
||||
m_ColorInputLUT[6][BLU_INP] = &Reg[3][BLU_C]; // c2.rgb
|
||||
m_ColorInputLUT[7][RED_INP] = &Reg[3][ALP_C];
|
||||
m_ColorInputLUT[7][GRN_INP] = &Reg[3][ALP_C];
|
||||
m_ColorInputLUT[7][BLU_INP] = &Reg[3][ALP_C]; // c2.aaa
|
||||
m_ColorInputLUT[8][RED_INP] = &TexColor[RED_C];
|
||||
m_ColorInputLUT[8][GRN_INP] = &TexColor[GRN_C];
|
||||
m_ColorInputLUT[8][BLU_INP] = &TexColor[BLU_C]; // tex.rgb
|
||||
m_ColorInputLUT[9][RED_INP] = &TexColor[ALP_C];
|
||||
m_ColorInputLUT[9][GRN_INP] = &TexColor[ALP_C];
|
||||
m_ColorInputLUT[9][BLU_INP] = &TexColor[ALP_C]; // tex.aaa
|
||||
m_ColorInputLUT[10][RED_INP] = &RasColor[RED_C];
|
||||
m_ColorInputLUT[10][GRN_INP] = &RasColor[GRN_C];
|
||||
m_ColorInputLUT[10][BLU_INP] = &RasColor[BLU_C]; // ras.rgb
|
||||
m_ColorInputLUT[11][RED_INP] = &RasColor[ALP_C];
|
||||
m_ColorInputLUT[11][GRN_INP] = &RasColor[ALP_C];
|
||||
m_ColorInputLUT[11][BLU_INP] = &RasColor[ALP_C]; // ras.rgb
|
||||
m_ColorInputLUT[12][RED_INP] = &FixedConstants[8];
|
||||
m_ColorInputLUT[12][GRN_INP] = &FixedConstants[8];
|
||||
m_ColorInputLUT[12][BLU_INP] = &FixedConstants[8]; // one
|
||||
m_ColorInputLUT[13][RED_INP] = &FixedConstants[4];
|
||||
m_ColorInputLUT[13][GRN_INP] = &FixedConstants[4];
|
||||
m_ColorInputLUT[13][BLU_INP] = &FixedConstants[4]; // half
|
||||
m_ColorInputLUT[14][RED_INP] = &StageKonst[RED_C];
|
||||
m_ColorInputLUT[14][GRN_INP] = &StageKonst[GRN_C];
|
||||
m_ColorInputLUT[14][BLU_INP] = &StageKonst[BLU_C]; // konst
|
||||
m_ColorInputLUT[15][RED_INP] = &FixedConstants[0];
|
||||
m_ColorInputLUT[15][GRN_INP] = &FixedConstants[0];
|
||||
m_ColorInputLUT[15][BLU_INP] = &FixedConstants[0]; // zero
|
||||
|
||||
m_AlphaInputLUT[0] = &Reg[0][ALP_C]; // prev
|
||||
m_AlphaInputLUT[1] = &Reg[1][ALP_C]; // c0
|
||||
m_AlphaInputLUT[2] = &Reg[2][ALP_C]; // c1
|
||||
m_AlphaInputLUT[3] = &Reg[3][ALP_C]; // c2
|
||||
m_AlphaInputLUT[4] = &TexColor[ALP_C]; // tex
|
||||
m_AlphaInputLUT[5] = &RasColor[ALP_C]; // ras
|
||||
m_AlphaInputLUT[6] = &StageKonst[ALP_C]; // konst
|
||||
m_AlphaInputLUT[7] = &Zero16[ALP_C]; // zero
|
||||
|
||||
for (int comp = 0; comp < 4; comp++)
|
||||
{
|
||||
m_KonstLUT[0][comp] = &FixedConstants[8];
|
||||
m_KonstLUT[1][comp] = &FixedConstants[7];
|
||||
m_KonstLUT[2][comp] = &FixedConstants[6];
|
||||
m_KonstLUT[3][comp] = &FixedConstants[5];
|
||||
m_KonstLUT[4][comp] = &FixedConstants[4];
|
||||
m_KonstLUT[5][comp] = &FixedConstants[3];
|
||||
m_KonstLUT[6][comp] = &FixedConstants[2];
|
||||
m_KonstLUT[7][comp] = &FixedConstants[1];
|
||||
|
||||
// These are "invalid" values, not meant to be used. On hardware,
|
||||
// they all output zero.
|
||||
for (int i = 8; i < 16; ++i)
|
||||
{
|
||||
m_KonstLUT[i][comp] = &FixedConstants[0];
|
||||
}
|
||||
|
||||
if (comp != ALP_C)
|
||||
{
|
||||
m_KonstLUT[12][comp] = &KonstantColors[0][comp];
|
||||
m_KonstLUT[13][comp] = &KonstantColors[1][comp];
|
||||
m_KonstLUT[14][comp] = &KonstantColors[2][comp];
|
||||
m_KonstLUT[15][comp] = &KonstantColors[3][comp];
|
||||
}
|
||||
|
||||
m_KonstLUT[16][comp] = &KonstantColors[0][RED_C];
|
||||
m_KonstLUT[17][comp] = &KonstantColors[1][RED_C];
|
||||
m_KonstLUT[18][comp] = &KonstantColors[2][RED_C];
|
||||
m_KonstLUT[19][comp] = &KonstantColors[3][RED_C];
|
||||
m_KonstLUT[20][comp] = &KonstantColors[0][GRN_C];
|
||||
m_KonstLUT[21][comp] = &KonstantColors[1][GRN_C];
|
||||
m_KonstLUT[22][comp] = &KonstantColors[2][GRN_C];
|
||||
m_KonstLUT[23][comp] = &KonstantColors[3][GRN_C];
|
||||
m_KonstLUT[24][comp] = &KonstantColors[0][BLU_C];
|
||||
m_KonstLUT[25][comp] = &KonstantColors[1][BLU_C];
|
||||
m_KonstLUT[26][comp] = &KonstantColors[2][BLU_C];
|
||||
m_KonstLUT[27][comp] = &KonstantColors[3][BLU_C];
|
||||
m_KonstLUT[28][comp] = &KonstantColors[0][ALP_C];
|
||||
m_KonstLUT[29][comp] = &KonstantColors[1][ALP_C];
|
||||
m_KonstLUT[30][comp] = &KonstantColors[2][ALP_C];
|
||||
m_KonstLUT[31][comp] = &KonstantColors[3][ALP_C];
|
||||
}
|
||||
|
||||
m_BiasLUT[0] = 0;
|
||||
m_BiasLUT[1] = 128;
|
||||
m_BiasLUT[2] = -128;
|
||||
m_BiasLUT[3] = 0;
|
||||
|
||||
m_ScaleLShiftLUT[0] = 0;
|
||||
m_ScaleLShiftLUT[1] = 1;
|
||||
m_ScaleLShiftLUT[2] = 2;
|
||||
m_ScaleLShiftLUT[3] = 0;
|
||||
|
||||
m_ScaleRShiftLUT[0] = 0;
|
||||
m_ScaleRShiftLUT[1] = 0;
|
||||
m_ScaleRShiftLUT[2] = 0;
|
||||
m_ScaleRShiftLUT[3] = 1;
|
||||
}
|
||||
|
||||
static inline s16 Clamp255(s16 in)
|
||||
{
|
||||
return in > 255 ? 255 : (in < 0 ? 0 : in);
|
||||
return std::clamp<s16>(in, 0, 255);
|
||||
}
|
||||
|
||||
static inline s16 Clamp1024(s16 in)
|
||||
{
|
||||
return in > 1023 ? 1023 : (in < -1024 ? -1024 : in);
|
||||
return std::clamp<s16>(in, -1024, 1023);
|
||||
}
|
||||
|
||||
void Tev::SetRasColor(RasColorChan colorChan, int swaptable)
|
||||
void Tev::SetRasColor(RasColorChan colorChan, u32 swaptable)
|
||||
{
|
||||
switch (colorChan)
|
||||
{
|
||||
case RasColorChan::Color0:
|
||||
{
|
||||
const u8* color = Color[0];
|
||||
RasColor[RED_C] = color[bpmem.tevksel[swaptable].swap1];
|
||||
RasColor[GRN_C] = color[bpmem.tevksel[swaptable].swap2];
|
||||
swaptable++;
|
||||
RasColor[BLU_C] = color[bpmem.tevksel[swaptable].swap1];
|
||||
RasColor[ALP_C] = color[bpmem.tevksel[swaptable].swap2];
|
||||
const auto& swap = bpmem.tevksel.GetSwapTable(swaptable);
|
||||
RasColor.r = color[u32(swap[ColorChannel::Red])];
|
||||
RasColor.g = color[u32(swap[ColorChannel::Green])];
|
||||
RasColor.b = color[u32(swap[ColorChannel::Blue])];
|
||||
RasColor.a = color[u32(swap[ColorChannel::Alpha])];
|
||||
}
|
||||
break;
|
||||
case RasColorChan::Color1:
|
||||
{
|
||||
const u8* color = Color[1];
|
||||
RasColor[RED_C] = color[bpmem.tevksel[swaptable].swap1];
|
||||
RasColor[GRN_C] = color[bpmem.tevksel[swaptable].swap2];
|
||||
swaptable++;
|
||||
RasColor[BLU_C] = color[bpmem.tevksel[swaptable].swap1];
|
||||
RasColor[ALP_C] = color[bpmem.tevksel[swaptable].swap2];
|
||||
const auto& swap = bpmem.tevksel.GetSwapTable(swaptable);
|
||||
RasColor.r = color[u32(swap[ColorChannel::Red])];
|
||||
RasColor.g = color[u32(swap[ColorChannel::Green])];
|
||||
RasColor.b = color[u32(swap[ColorChannel::Blue])];
|
||||
RasColor.a = color[u32(swap[ColorChannel::Alpha])];
|
||||
}
|
||||
break;
|
||||
case RasColorChan::AlphaBump:
|
||||
{
|
||||
for (s16& comp : RasColor)
|
||||
{
|
||||
comp = AlphaBump;
|
||||
}
|
||||
RasColor = TevColor::All(AlphaBump);
|
||||
}
|
||||
break;
|
||||
case RasColorChan::NormalizedAlphaBump:
|
||||
{
|
||||
const u8 normalized = AlphaBump | AlphaBump >> 5;
|
||||
for (s16& comp : RasColor)
|
||||
{
|
||||
comp = normalized;
|
||||
}
|
||||
RasColor = TevColor::All(normalized);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -218,10 +77,7 @@ void Tev::SetRasColor(RasColorChan colorChan, int swaptable)
|
|||
if (colorChan != RasColorChan::Zero)
|
||||
PanicAlertFmt("Invalid ras color channel: {}", colorChan);
|
||||
|
||||
for (s16& comp : RasColor)
|
||||
{
|
||||
comp = 0;
|
||||
}
|
||||
RasColor = TevColor::All(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -236,17 +92,15 @@ void Tev::DrawColorRegular(const TevStageCombiner::ColorCombiner& cc, const Inpu
|
|||
const u16 c = InputReg.c + (InputReg.c >> 7);
|
||||
|
||||
s32 temp = InputReg.a * (256 - c) + (InputReg.b * c);
|
||||
temp <<= m_ScaleLShiftLUT[u32(cc.scale.Value())];
|
||||
temp <<= s_ScaleLShiftLUT[cc.scale];
|
||||
temp += (cc.scale == TevScale::Divide2) ? 0 : (cc.op == TevOp::Sub) ? 127 : 128;
|
||||
temp >>= 8;
|
||||
temp = cc.op == TevOp::Sub ? -temp : temp;
|
||||
|
||||
s32 result = ((InputReg.d + m_BiasLUT[u32(cc.bias.Value())])
|
||||
<< m_ScaleLShiftLUT[u32(cc.scale.Value())]) +
|
||||
temp;
|
||||
result = result >> m_ScaleRShiftLUT[u32(cc.scale.Value())];
|
||||
s32 result = ((InputReg.d + s_BiasLUT[cc.bias]) << s_ScaleLShiftLUT[cc.scale]) + temp;
|
||||
result = result >> s_ScaleRShiftLUT[cc.scale];
|
||||
|
||||
Reg[u32(cc.dest.Value())][i] = result;
|
||||
Reg[cc.dest][i] = result;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -283,9 +137,9 @@ void Tev::DrawColorCompare(const TevStageCombiner::ColorCombiner& cc, const Inpu
|
|||
}
|
||||
|
||||
if (cc.comparison == TevComparison::GT)
|
||||
Reg[u32(cc.dest.Value())][i] = inputs[i].d + ((a > b) ? inputs[i].c : 0);
|
||||
Reg[cc.dest][i] = inputs[i].d + ((a > b) ? inputs[i].c : 0);
|
||||
else
|
||||
Reg[u32(cc.dest.Value())][i] = inputs[i].d + ((a == b) ? inputs[i].c : 0);
|
||||
Reg[cc.dest][i] = inputs[i].d + ((a == b) ? inputs[i].c : 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -296,16 +150,14 @@ void Tev::DrawAlphaRegular(const TevStageCombiner::AlphaCombiner& ac, const Inpu
|
|||
const u16 c = InputReg.c + (InputReg.c >> 7);
|
||||
|
||||
s32 temp = InputReg.a * (256 - c) + (InputReg.b * c);
|
||||
temp <<= m_ScaleLShiftLUT[u32(ac.scale.Value())];
|
||||
temp <<= s_ScaleLShiftLUT[ac.scale];
|
||||
temp += (ac.scale == TevScale::Divide2) ? 0 : (ac.op == TevOp::Sub) ? 127 : 128;
|
||||
temp = ac.op == TevOp::Sub ? (-temp >> 8) : (temp >> 8);
|
||||
|
||||
s32 result =
|
||||
((InputReg.d + m_BiasLUT[u32(ac.bias.Value())]) << m_ScaleLShiftLUT[u32(ac.scale.Value())]) +
|
||||
temp;
|
||||
result = result >> m_ScaleRShiftLUT[u32(ac.scale.Value())];
|
||||
s32 result = ((InputReg.d + s_BiasLUT[ac.bias]) << s_ScaleLShiftLUT[ac.scale]) + temp;
|
||||
result = result >> s_ScaleRShiftLUT[ac.scale];
|
||||
|
||||
Reg[u32(ac.dest.Value())][ALP_C] = result;
|
||||
Reg[ac.dest].a = result;
|
||||
}
|
||||
|
||||
void Tev::DrawAlphaCompare(const TevStageCombiner::AlphaCombiner& ac, const InputRegType inputs[4])
|
||||
|
@ -339,9 +191,9 @@ void Tev::DrawAlphaCompare(const TevStageCombiner::AlphaCombiner& ac, const Inpu
|
|||
}
|
||||
|
||||
if (ac.comparison == TevComparison::GT)
|
||||
Reg[u32(ac.dest.Value())][ALP_C] = inputs[ALP_C].d + ((a > b) ? inputs[ALP_C].c : 0);
|
||||
Reg[ac.dest].a = inputs[ALP_C].d + ((a > b) ? inputs[ALP_C].c : 0);
|
||||
else
|
||||
Reg[u32(ac.dest.Value())][ALP_C] = inputs[ALP_C].d + ((a == b) ? inputs[ALP_C].c : 0);
|
||||
Reg[ac.dest].a = inputs[ALP_C].d + ((a == b) ? inputs[ALP_C].c : 0);
|
||||
}
|
||||
|
||||
static bool AlphaCompare(int alpha, int ref, CompareMode comp)
|
||||
|
@ -548,10 +400,10 @@ void Tev::Draw()
|
|||
// initial color values
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
Reg[i][RED_C] = PixelShaderManager::constants.colors[i][0];
|
||||
Reg[i][GRN_C] = PixelShaderManager::constants.colors[i][1];
|
||||
Reg[i][BLU_C] = PixelShaderManager::constants.colors[i][2];
|
||||
Reg[i][ALP_C] = PixelShaderManager::constants.colors[i][3];
|
||||
Reg[static_cast<TevOutput>(i)].r = PixelShaderManager::constants.colors[i][0];
|
||||
Reg[static_cast<TevOutput>(i)].g = PixelShaderManager::constants.colors[i][1];
|
||||
Reg[static_cast<TevOutput>(i)].b = PixelShaderManager::constants.colors[i][2];
|
||||
Reg[static_cast<TevOutput>(i)].a = PixelShaderManager::constants.colors[i][3];
|
||||
}
|
||||
|
||||
for (unsigned int stageNum = 0; stageNum < bpmem.genMode.numindstages; stageNum++)
|
||||
|
@ -593,7 +445,6 @@ void Tev::Draw()
|
|||
const int stageNum2 = stageNum >> 1;
|
||||
const int stageOdd = stageNum & 1;
|
||||
const TwoTevStageOrders& order = bpmem.tevorders[stageNum2];
|
||||
const TevKSel& kSel = bpmem.tevksel[stageNum2];
|
||||
|
||||
// stage combiners
|
||||
const TevStageCombiner::ColorCombiner& cc = bpmem.combiners[stageNum].colorC;
|
||||
|
@ -632,39 +483,42 @@ void Tev::Draw()
|
|||
DebugUtil::DrawTempBuffer(texel, DIRECT_TFETCH + stageNum);
|
||||
#endif
|
||||
|
||||
int swaptable = ac.tswap * 2;
|
||||
|
||||
TexColor[RED_C] = texel[bpmem.tevksel[swaptable].swap1];
|
||||
TexColor[GRN_C] = texel[bpmem.tevksel[swaptable].swap2];
|
||||
swaptable++;
|
||||
TexColor[BLU_C] = texel[bpmem.tevksel[swaptable].swap1];
|
||||
TexColor[ALP_C] = texel[bpmem.tevksel[swaptable].swap2];
|
||||
const auto& swap = bpmem.tevksel.GetSwapTable(ac.tswap);
|
||||
TexColor.r = texel[u32(swap[ColorChannel::Red])];
|
||||
TexColor.g = texel[u32(swap[ColorChannel::Green])];
|
||||
TexColor.b = texel[u32(swap[ColorChannel::Blue])];
|
||||
TexColor.a = texel[u32(swap[ColorChannel::Alpha])];
|
||||
}
|
||||
|
||||
// set konst for this stage
|
||||
const auto kc = u32(kSel.getKC(stageOdd));
|
||||
const auto ka = u32(kSel.getKA(stageOdd));
|
||||
StageKonst[RED_C] = *(m_KonstLUT[kc][RED_C]);
|
||||
StageKonst[GRN_C] = *(m_KonstLUT[kc][GRN_C]);
|
||||
StageKonst[BLU_C] = *(m_KonstLUT[kc][BLU_C]);
|
||||
StageKonst[ALP_C] = *(m_KonstLUT[ka][ALP_C]);
|
||||
const auto kc = bpmem.tevksel.GetKonstColor(stageNum);
|
||||
const auto ka = bpmem.tevksel.GetKonstAlpha(stageNum);
|
||||
StageKonst.r = m_KonstLUT[kc].r;
|
||||
StageKonst.g = m_KonstLUT[kc].g;
|
||||
StageKonst.b = m_KonstLUT[kc].b;
|
||||
StageKonst.a = m_KonstLUT[ka].a;
|
||||
|
||||
// set color
|
||||
SetRasColor(order.getColorChan(stageOdd), ac.rswap * 2);
|
||||
SetRasColor(order.getColorChan(stageOdd), ac.rswap);
|
||||
|
||||
// combine inputs
|
||||
InputRegType inputs[4];
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
inputs[BLU_C + i].a = *m_ColorInputLUT[u32(cc.a.Value())][i];
|
||||
inputs[BLU_C + i].b = *m_ColorInputLUT[u32(cc.b.Value())][i];
|
||||
inputs[BLU_C + i].c = *m_ColorInputLUT[u32(cc.c.Value())][i];
|
||||
inputs[BLU_C + i].d = *m_ColorInputLUT[u32(cc.d.Value())][i];
|
||||
}
|
||||
inputs[ALP_C].a = *m_AlphaInputLUT[u32(ac.a.Value())];
|
||||
inputs[ALP_C].b = *m_AlphaInputLUT[u32(ac.b.Value())];
|
||||
inputs[ALP_C].c = *m_AlphaInputLUT[u32(ac.c.Value())];
|
||||
inputs[ALP_C].d = *m_AlphaInputLUT[u32(ac.d.Value())];
|
||||
inputs[BLU_C].a = m_ColorInputLUT[cc.a].b;
|
||||
inputs[BLU_C].b = m_ColorInputLUT[cc.b].b;
|
||||
inputs[BLU_C].c = m_ColorInputLUT[cc.c].b;
|
||||
inputs[BLU_C].d = m_ColorInputLUT[cc.d].b;
|
||||
inputs[GRN_C].a = m_ColorInputLUT[cc.a].g;
|
||||
inputs[GRN_C].b = m_ColorInputLUT[cc.b].g;
|
||||
inputs[GRN_C].c = m_ColorInputLUT[cc.c].g;
|
||||
inputs[GRN_C].d = m_ColorInputLUT[cc.d].g;
|
||||
inputs[RED_C].a = m_ColorInputLUT[cc.a].r;
|
||||
inputs[RED_C].b = m_ColorInputLUT[cc.b].r;
|
||||
inputs[RED_C].c = m_ColorInputLUT[cc.c].r;
|
||||
inputs[RED_C].d = m_ColorInputLUT[cc.d].r;
|
||||
inputs[ALP_C].a = m_AlphaInputLUT[ac.a].a;
|
||||
inputs[ALP_C].b = m_AlphaInputLUT[ac.b].a;
|
||||
inputs[ALP_C].c = m_AlphaInputLUT[ac.c].a;
|
||||
inputs[ALP_C].d = m_AlphaInputLUT[ac.d].a;
|
||||
|
||||
if (cc.bias != TevBias::Compare)
|
||||
DrawColorRegular(cc, inputs);
|
||||
|
@ -673,15 +527,15 @@ void Tev::Draw()
|
|||
|
||||
if (cc.clamp)
|
||||
{
|
||||
Reg[u32(cc.dest.Value())][RED_C] = Clamp255(Reg[u32(cc.dest.Value())][RED_C]);
|
||||
Reg[u32(cc.dest.Value())][GRN_C] = Clamp255(Reg[u32(cc.dest.Value())][GRN_C]);
|
||||
Reg[u32(cc.dest.Value())][BLU_C] = Clamp255(Reg[u32(cc.dest.Value())][BLU_C]);
|
||||
Reg[cc.dest].r = Clamp255(Reg[cc.dest].r);
|
||||
Reg[cc.dest].g = Clamp255(Reg[cc.dest].g);
|
||||
Reg[cc.dest].b = Clamp255(Reg[cc.dest].b);
|
||||
}
|
||||
else
|
||||
{
|
||||
Reg[u32(cc.dest.Value())][RED_C] = Clamp1024(Reg[u32(cc.dest.Value())][RED_C]);
|
||||
Reg[u32(cc.dest.Value())][GRN_C] = Clamp1024(Reg[u32(cc.dest.Value())][GRN_C]);
|
||||
Reg[u32(cc.dest.Value())][BLU_C] = Clamp1024(Reg[u32(cc.dest.Value())][BLU_C]);
|
||||
Reg[cc.dest].r = Clamp1024(Reg[cc.dest].r);
|
||||
Reg[cc.dest].g = Clamp1024(Reg[cc.dest].g);
|
||||
Reg[cc.dest].b = Clamp1024(Reg[cc.dest].b);
|
||||
}
|
||||
|
||||
if (ac.bias != TevBias::Compare)
|
||||
|
@ -690,14 +544,15 @@ void Tev::Draw()
|
|||
DrawAlphaCompare(ac, inputs);
|
||||
|
||||
if (ac.clamp)
|
||||
Reg[u32(ac.dest.Value())][ALP_C] = Clamp255(Reg[u32(ac.dest.Value())][ALP_C]);
|
||||
Reg[ac.dest].a = Clamp255(Reg[ac.dest].a);
|
||||
else
|
||||
Reg[u32(ac.dest.Value())][ALP_C] = Clamp1024(Reg[u32(ac.dest.Value())][ALP_C]);
|
||||
Reg[ac.dest].a = Clamp1024(Reg[ac.dest].a);
|
||||
|
||||
#if ALLOW_TEV_DUMPS
|
||||
if (g_ActiveConfig.bDumpTevStages)
|
||||
{
|
||||
u8 stage[4] = {(u8)Reg[0][RED_C], (u8)Reg[0][GRN_C], (u8)Reg[0][BLU_C], (u8)Reg[0][ALP_C]};
|
||||
u8 stage[4] = {(u8)Reg[cc.dest].r, (u8)Reg[cc.dest].g, (u8)Reg[cc.dest].b,
|
||||
(u8)Reg[ac.dest].a};
|
||||
DebugUtil::DrawTempBuffer(stage, DIRECT + stageNum);
|
||||
}
|
||||
#endif
|
||||
|
@ -706,10 +561,10 @@ void Tev::Draw()
|
|||
// convert to 8 bits per component
|
||||
// the results of the last tev stage are put onto the screen,
|
||||
// regardless of the used destination register - TODO: Verify!
|
||||
const u32 color_index = u32(bpmem.combiners[bpmem.genMode.numtevstages].colorC.dest.Value());
|
||||
const u32 alpha_index = u32(bpmem.combiners[bpmem.genMode.numtevstages].alphaC.dest.Value());
|
||||
u8 output[4] = {(u8)Reg[alpha_index][ALP_C], (u8)Reg[color_index][BLU_C],
|
||||
(u8)Reg[color_index][GRN_C], (u8)Reg[color_index][RED_C]};
|
||||
const auto& color_index = bpmem.combiners[bpmem.genMode.numtevstages].colorC.dest;
|
||||
const auto& alpha_index = bpmem.combiners[bpmem.genMode.numtevstages].alphaC.dest;
|
||||
u8 output[4] = {(u8)Reg[alpha_index].a, (u8)Reg[color_index].b, (u8)Reg[color_index].g,
|
||||
(u8)Reg[color_index].r};
|
||||
|
||||
if (!TevAlphaTest(output[ALP_C]))
|
||||
return;
|
||||
|
@ -882,7 +737,13 @@ void Tev::Draw()
|
|||
EfbInterface::BlendTev(Position[0], Position[1], output);
|
||||
}
|
||||
|
||||
void Tev::SetRegColor(int reg, int comp, s16 color)
|
||||
void Tev::SetKonstColors()
|
||||
{
|
||||
KonstantColors[reg][comp] = color;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
KonstantColors[i].r = PixelShaderManager::constants.kcolors[i][0];
|
||||
KonstantColors[i].g = PixelShaderManager::constants.kcolors[i][1];
|
||||
KonstantColors[i].b = PixelShaderManager::constants.kcolors[i][2];
|
||||
KonstantColors[i].a = PixelShaderManager::constants.kcolors[i][3];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,90 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
||||
#include "Common/EnumMap.h"
|
||||
#include "VideoCommon/BPMemory.h"
|
||||
|
||||
class Tev
|
||||
{
|
||||
struct TevColor
|
||||
{
|
||||
constexpr TevColor() = default;
|
||||
constexpr explicit TevColor(s16 a, s16 b, s16 g, s16 r) : a(a), b(b), g(g), r(r) {}
|
||||
|
||||
s16 a = 0;
|
||||
s16 b = 0;
|
||||
s16 g = 0;
|
||||
s16 r = 0;
|
||||
|
||||
constexpr static TevColor All(s16 value) { return TevColor(value, value, value, value); }
|
||||
|
||||
constexpr s16& operator[](int index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case ALP_C:
|
||||
return a;
|
||||
case BLU_C:
|
||||
return b;
|
||||
case GRN_C:
|
||||
return g;
|
||||
case RED_C:
|
||||
return r;
|
||||
default:
|
||||
// invalid
|
||||
return a;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct TevColorRef
|
||||
{
|
||||
constexpr explicit TevColorRef(const s16& r, const s16& g, const s16& b) : r(r), g(g), b(b) {}
|
||||
|
||||
const s16& r;
|
||||
const s16& g;
|
||||
const s16& b;
|
||||
|
||||
constexpr static TevColorRef Color(const TevColor& color)
|
||||
{
|
||||
return TevColorRef(color.r, color.g, color.b);
|
||||
}
|
||||
constexpr static TevColorRef All(const s16& value) { return TevColorRef(value, value, value); }
|
||||
constexpr static TevColorRef Alpha(const TevColor& color) { return All(color.a); }
|
||||
};
|
||||
|
||||
struct TevAlphaRef
|
||||
{
|
||||
constexpr explicit TevAlphaRef(const TevColor& color) : a(color.a) {}
|
||||
constexpr explicit TevAlphaRef(const s16& a) : a(a) {}
|
||||
|
||||
const s16& a;
|
||||
};
|
||||
|
||||
struct TevKonstRef
|
||||
{
|
||||
constexpr explicit TevKonstRef(const s16& a, const s16& r, const s16& g, const s16& b)
|
||||
: a(a), r(r), g(g), b(b)
|
||||
{
|
||||
}
|
||||
|
||||
const s16& a;
|
||||
const s16& r;
|
||||
const s16& g;
|
||||
const s16& b;
|
||||
|
||||
constexpr static TevKonstRef Value(const s16& value)
|
||||
{
|
||||
return TevKonstRef(value, value, value, value);
|
||||
}
|
||||
constexpr static TevKonstRef Konst(const s16& alpha, const TevColor& color)
|
||||
{
|
||||
return TevKonstRef(alpha, color.r, color.g, color.b);
|
||||
}
|
||||
};
|
||||
|
||||
struct InputRegType
|
||||
{
|
||||
unsigned a : 8;
|
||||
|
@ -22,32 +102,96 @@ class Tev
|
|||
};
|
||||
|
||||
// color order: ABGR
|
||||
s16 Reg[4][4];
|
||||
s16 KonstantColors[4][4];
|
||||
s16 TexColor[4];
|
||||
s16 RasColor[4];
|
||||
s16 StageKonst[4];
|
||||
s16 Zero16[4];
|
||||
Common::EnumMap<TevColor, TevOutput::Color2> Reg;
|
||||
std::array<TevColor, 4> KonstantColors;
|
||||
TevColor TexColor;
|
||||
TevColor RasColor;
|
||||
TevColor StageKonst;
|
||||
|
||||
// Fixed constants, corresponding to KonstSel
|
||||
static constexpr s16 V0 = 0;
|
||||
static constexpr s16 V1_8 = 32;
|
||||
static constexpr s16 V1_4 = 64;
|
||||
static constexpr s16 V3_8 = 96;
|
||||
static constexpr s16 V1_2 = 128;
|
||||
static constexpr s16 V5_8 = 159;
|
||||
static constexpr s16 V3_4 = 191;
|
||||
static constexpr s16 V7_8 = 223;
|
||||
static constexpr s16 V1 = 255;
|
||||
|
||||
s16 FixedConstants[9];
|
||||
u8 AlphaBump;
|
||||
u8 IndirectTex[4][4];
|
||||
TextureCoordinateType TexCoord;
|
||||
|
||||
s16* m_ColorInputLUT[16][3];
|
||||
s16* m_AlphaInputLUT[8]; // values must point to ABGR color
|
||||
s16* m_KonstLUT[32][4];
|
||||
s16 m_BiasLUT[4];
|
||||
u8 m_ScaleLShiftLUT[4];
|
||||
u8 m_ScaleRShiftLUT[4];
|
||||
|
||||
// enumeration for color input LUT
|
||||
enum
|
||||
{
|
||||
BLU_INP,
|
||||
GRN_INP,
|
||||
RED_INP
|
||||
const Common::EnumMap<TevColorRef, TevColorArg::Zero> m_ColorInputLUT{
|
||||
TevColorRef::Color(Reg[TevOutput::Prev]), // prev.rgb
|
||||
TevColorRef::Alpha(Reg[TevOutput::Prev]), // prev.aaa
|
||||
TevColorRef::Color(Reg[TevOutput::Color0]), // c0.rgb
|
||||
TevColorRef::Alpha(Reg[TevOutput::Color0]), // c0.aaa
|
||||
TevColorRef::Color(Reg[TevOutput::Color1]), // c1.rgb
|
||||
TevColorRef::Alpha(Reg[TevOutput::Color1]), // c1.aaa
|
||||
TevColorRef::Color(Reg[TevOutput::Color2]), // c2.rgb
|
||||
TevColorRef::Alpha(Reg[TevOutput::Color2]), // c2.aaa
|
||||
TevColorRef::Color(TexColor), // tex.rgb
|
||||
TevColorRef::Alpha(TexColor), // tex.aaa
|
||||
TevColorRef::Color(RasColor), // ras.rgb
|
||||
TevColorRef::Alpha(RasColor), // ras.aaa
|
||||
TevColorRef::All(V1), // one
|
||||
TevColorRef::All(V1_2), // half
|
||||
TevColorRef::Color(StageKonst), // konst
|
||||
TevColorRef::All(V0), // zero
|
||||
};
|
||||
const Common::EnumMap<TevAlphaRef, TevAlphaArg::Zero> m_AlphaInputLUT{
|
||||
TevAlphaRef(Reg[TevOutput::Prev]), // prev
|
||||
TevAlphaRef(Reg[TevOutput::Color0]), // c0
|
||||
TevAlphaRef(Reg[TevOutput::Color1]), // c1
|
||||
TevAlphaRef(Reg[TevOutput::Color2]), // c2
|
||||
TevAlphaRef(TexColor), // tex
|
||||
TevAlphaRef(RasColor), // ras
|
||||
TevAlphaRef(StageKonst), // konst
|
||||
TevAlphaRef(V0), // zero
|
||||
};
|
||||
const Common::EnumMap<TevKonstRef, KonstSel::K3_A> m_KonstLUT{
|
||||
TevKonstRef::Value(V1), // 1
|
||||
TevKonstRef::Value(V7_8), // 7/8
|
||||
TevKonstRef::Value(V3_4), // 3/4
|
||||
TevKonstRef::Value(V5_8), // 5/8
|
||||
TevKonstRef::Value(V1_2), // 1/2
|
||||
TevKonstRef::Value(V3_8), // 3/8
|
||||
TevKonstRef::Value(V1_4), // 1/4
|
||||
TevKonstRef::Value(V1_8), // 1/8
|
||||
|
||||
// These are "invalid" values, not meant to be used. On hardware,
|
||||
// they all output zero.
|
||||
TevKonstRef::Value(V0), TevKonstRef::Value(V0), TevKonstRef::Value(V0),
|
||||
TevKonstRef::Value(V0),
|
||||
|
||||
// These values are valid for RGB only; they're invalid for alpha
|
||||
TevKonstRef::Konst(V0, KonstantColors[0]), // Konst 0 RGB
|
||||
TevKonstRef::Konst(V0, KonstantColors[1]), // Konst 1 RGB
|
||||
TevKonstRef::Konst(V0, KonstantColors[2]), // Konst 2 RGB
|
||||
TevKonstRef::Konst(V0, KonstantColors[3]), // Konst 3 RGB
|
||||
|
||||
TevKonstRef::Value(KonstantColors[0].r), // Konst 0 Red
|
||||
TevKonstRef::Value(KonstantColors[1].r), // Konst 1 Red
|
||||
TevKonstRef::Value(KonstantColors[2].r), // Konst 2 Red
|
||||
TevKonstRef::Value(KonstantColors[3].r), // Konst 3 Red
|
||||
TevKonstRef::Value(KonstantColors[0].g), // Konst 0 Green
|
||||
TevKonstRef::Value(KonstantColors[1].g), // Konst 1 Green
|
||||
TevKonstRef::Value(KonstantColors[2].g), // Konst 2 Green
|
||||
TevKonstRef::Value(KonstantColors[3].g), // Konst 3 Green
|
||||
TevKonstRef::Value(KonstantColors[0].b), // Konst 0 Blue
|
||||
TevKonstRef::Value(KonstantColors[1].b), // Konst 1 Blue
|
||||
TevKonstRef::Value(KonstantColors[2].b), // Konst 2 Blue
|
||||
TevKonstRef::Value(KonstantColors[3].b), // Konst 3 Blue
|
||||
TevKonstRef::Value(KonstantColors[0].a), // Konst 0 Alpha
|
||||
TevKonstRef::Value(KonstantColors[1].a), // Konst 1 Alpha
|
||||
TevKonstRef::Value(KonstantColors[2].a), // Konst 2 Alpha
|
||||
TevKonstRef::Value(KonstantColors[3].a), // Konst 3 Alpha
|
||||
};
|
||||
static constexpr Common::EnumMap<s16, TevBias::Compare> s_BiasLUT{0, 128, -128, 0};
|
||||
static constexpr Common::EnumMap<u8, TevScale::Divide2> s_ScaleLShiftLUT{0, 1, 2, 0};
|
||||
static constexpr Common::EnumMap<u8, TevScale::Divide2> s_ScaleRShiftLUT{0, 0, 0, 1};
|
||||
|
||||
enum BufferBase
|
||||
{
|
||||
|
@ -56,7 +200,7 @@ class Tev
|
|||
INDIRECT = 32
|
||||
};
|
||||
|
||||
void SetRasColor(RasColorChan colorChan, int swaptable);
|
||||
void SetRasColor(RasColorChan colorChan, u32 swaptable);
|
||||
|
||||
void DrawColorRegular(const TevStageCombiner::ColorCombiner& cc, const InputRegType inputs[4]);
|
||||
void DrawColorCompare(const TevStageCombiner::ColorCombiner& cc, const InputRegType inputs[4]);
|
||||
|
@ -82,9 +226,6 @@ public:
|
|||
RED_C
|
||||
};
|
||||
|
||||
void Init();
|
||||
|
||||
void SetKonstColors();
|
||||
void Draw();
|
||||
|
||||
void SetRegColor(int reg, int comp, s16 color);
|
||||
};
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "Common/BitUtils.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/EnumFormatter.h"
|
||||
#include "Common/EnumMap.h"
|
||||
#include "Common/Inline.h"
|
||||
|
||||
// X.h defines None to be 0 and Always to be 2, which causes problems with some of the enums
|
||||
|
@ -683,8 +684,8 @@ struct fmt::formatter<TevStageCombiner::AlphaCombiner>
|
|||
"Clamp: {}\n"
|
||||
"Scale factor: {} / Compare mode: {}\n"
|
||||
"Dest: {}\n"
|
||||
"Ras sel: {}\n"
|
||||
"Tex sel: {}",
|
||||
"Rasterized color swaptable: {}\n"
|
||||
"Texture color swaptable: {}",
|
||||
ac.a, ac.b, ac.c, ac.d, ac.bias, ac.op, ac.comparison,
|
||||
ac.clamp ? "Yes" : "No", ac.scale, ac.compare_mode, ac.dest, ac.rswap,
|
||||
ac.tswap);
|
||||
|
@ -777,69 +778,82 @@ struct fmt::formatter<RasColorChan> : EnumFormatter<RasColorChan::Zero>
|
|||
|
||||
union TwoTevStageOrders
|
||||
{
|
||||
BitField<0, 3, u32> texmap0; // Indirect tex stage texmap
|
||||
BitField<3, 3, u32> texcoord0;
|
||||
BitField<6, 1, bool, u32> enable0; // true if should read from texture
|
||||
BitField<7, 3, RasColorChan> colorchan0;
|
||||
BitField<0, 3, u32> texmap_even;
|
||||
BitField<3, 3, u32> texcoord_even;
|
||||
BitField<6, 1, bool, u32> enable_tex_even; // true if should read from texture
|
||||
BitField<7, 3, RasColorChan> colorchan_even;
|
||||
|
||||
BitField<12, 3, u32> texmap1;
|
||||
BitField<15, 3, u32> texcoord1;
|
||||
BitField<18, 1, bool, u32> enable1; // true if should read from texture
|
||||
BitField<19, 3, RasColorChan> colorchan1;
|
||||
BitField<12, 3, u32> texmap_odd;
|
||||
BitField<15, 3, u32> texcoord_odd;
|
||||
BitField<18, 1, bool, u32> enable_tex_odd; // true if should read from texture
|
||||
BitField<19, 3, RasColorChan> colorchan_odd;
|
||||
|
||||
u32 hex;
|
||||
u32 getTexMap(int i) const { return i ? texmap1.Value() : texmap0.Value(); }
|
||||
u32 getTexCoord(int i) const { return i ? texcoord1.Value() : texcoord0.Value(); }
|
||||
u32 getEnable(int i) const { return i ? enable1.Value() : enable0.Value(); }
|
||||
RasColorChan getColorChan(int i) const { return i ? colorchan1.Value() : colorchan0.Value(); }
|
||||
u32 getTexMap(int i) const { return i ? texmap_odd.Value() : texmap_even.Value(); }
|
||||
u32 getTexCoord(int i) const { return i ? texcoord_odd.Value() : texcoord_even.Value(); }
|
||||
u32 getEnable(int i) const { return i ? enable_tex_odd.Value() : enable_tex_even.Value(); }
|
||||
RasColorChan getColorChan(int i) const
|
||||
{
|
||||
return i ? colorchan_odd.Value() : colorchan_even.Value();
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct fmt::formatter<TwoTevStageOrders>
|
||||
struct fmt::formatter<std::pair<u8, TwoTevStageOrders>>
|
||||
{
|
||||
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
|
||||
template <typename FormatContext>
|
||||
auto format(const TwoTevStageOrders& stages, FormatContext& ctx) const
|
||||
auto format(const std::pair<u8, TwoTevStageOrders>& p, FormatContext& ctx) const
|
||||
{
|
||||
const auto& [cmd, stages] = p;
|
||||
const u8 stage_even = (cmd - BPMEM_TREF) * 2;
|
||||
const u8 stage_odd = stage_even + 1;
|
||||
|
||||
return fmt::format_to(ctx.out(),
|
||||
"Stage 0 texmap: {}\nStage 0 tex coord: {}\n"
|
||||
"Stage 0 enable texmap: {}\nStage 0 color channel: {}\n"
|
||||
"Stage 1 texmap: {}\nStage 1 tex coord: {}\n"
|
||||
"Stage 1 enable texmap: {}\nStage 1 color channel: {}\n",
|
||||
stages.texmap0, stages.texcoord0, stages.enable0 ? "Yes" : "No",
|
||||
stages.colorchan0, stages.texmap1, stages.texcoord1,
|
||||
stages.enable1 ? "Yes" : "No", stages.colorchan1);
|
||||
"Stage {0} texmap: {1}\nStage {0} tex coord: {2}\n"
|
||||
"Stage {0} enable texmap: {3}\nStage {0} rasterized color channel: {4}\n"
|
||||
"Stage {5} texmap: {6}\nStage {5} tex coord: {7}\n"
|
||||
"Stage {5} enable texmap: {8}\nStage {5} rasterized color channel: {9}\n",
|
||||
stage_even, stages.texmap_even, stages.texcoord_even,
|
||||
stages.enable_tex_even ? "Yes" : "No", stages.colorchan_even, stage_odd,
|
||||
stages.texmap_odd, stages.texcoord_odd,
|
||||
stages.enable_tex_odd ? "Yes" : "No", stages.colorchan_odd);
|
||||
}
|
||||
};
|
||||
|
||||
union TEXSCALE
|
||||
{
|
||||
BitField<0, 4, u32> ss0; // Indirect tex stage 0, 2^(-ss0)
|
||||
BitField<4, 4, u32> ts0; // Indirect tex stage 0
|
||||
BitField<8, 4, u32> ss1; // Indirect tex stage 1
|
||||
BitField<12, 4, u32> ts1; // Indirect tex stage 1
|
||||
BitField<0, 4, u32> ss0; // Indirect tex stage 0 or 2, 2^(-ss0)
|
||||
BitField<4, 4, u32> ts0; // Indirect tex stage 0 or 2
|
||||
BitField<8, 4, u32> ss1; // Indirect tex stage 1 or 3
|
||||
BitField<12, 4, u32> ts1; // Indirect tex stage 1 or 3
|
||||
u32 hex;
|
||||
};
|
||||
template <>
|
||||
struct fmt::formatter<TEXSCALE>
|
||||
struct fmt::formatter<std::pair<u8, TEXSCALE>>
|
||||
{
|
||||
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
|
||||
template <typename FormatContext>
|
||||
auto format(const TEXSCALE& scale, FormatContext& ctx) const
|
||||
auto format(const std::pair<u8, TEXSCALE>& p, FormatContext& ctx) const
|
||||
{
|
||||
const auto& [cmd, scale] = p;
|
||||
const u8 even = (cmd - BPMEM_RAS1_SS0) * 2;
|
||||
const u8 odd_ = even + 1;
|
||||
|
||||
return fmt::format_to(ctx.out(),
|
||||
"Even stage S scale: {} ({})\n"
|
||||
"Even stage T scale: {} ({})\n"
|
||||
"Odd stage S scale: {} ({})\n"
|
||||
"Odd stage T scale: {} ({})",
|
||||
scale.ss0, 1.f / (1 << scale.ss0), scale.ts0, 1.f / (1 << scale.ts0),
|
||||
scale.ss1, 1.f / (1 << scale.ss1), scale.ts1, 1.f / (1 << scale.ts1));
|
||||
"Indirect stage {0} S coord scale: {1} ({2})\n"
|
||||
"Indirect stage {0} T coord scale: {3} ({4})\n"
|
||||
"Indirect stage {5} S coord scale: {6} ({7})\n"
|
||||
"Indirect stage {5} T coord scale: {8} ({9})",
|
||||
even, 1.f / (1 << scale.ss0), scale.ss0, 1.f / (1 << scale.ts0),
|
||||
scale.ts0, odd_, 1.f / (1 << scale.ss1), scale.ss1,
|
||||
1.f / (1 << scale.ts1), scale.ts1);
|
||||
}
|
||||
};
|
||||
|
||||
union RAS1_IREF
|
||||
{
|
||||
BitField<0, 3, u32> bi0; // Indirect tex stage 0 ntexmap
|
||||
BitField<3, 3, u32> bc0; // Indirect tex stage 0 ntexcoord
|
||||
BitField<0, 3, u32> bi0; // Indirect tex stage 0 texmap
|
||||
BitField<3, 3, u32> bc0; // Indirect tex stage 0 tex coord
|
||||
BitField<6, 3, u32> bi1;
|
||||
BitField<9, 3, u32> bc1;
|
||||
BitField<12, 3, u32> bi2;
|
||||
|
@ -858,12 +872,11 @@ struct fmt::formatter<RAS1_IREF>
|
|||
template <typename FormatContext>
|
||||
auto format(const RAS1_IREF& indref, FormatContext& ctx) const
|
||||
{
|
||||
// The field names here are suspicious, since there is no bi3 or bc2
|
||||
return fmt::format_to(ctx.out(),
|
||||
"Stage 0 ntexmap: {}\nStage 0 ntexcoord: {}\n"
|
||||
"Stage 1 ntexmap: {}\nStage 1 ntexcoord: {}\n"
|
||||
"Stage 2 ntexmap: {}\nStage 2 ntexcoord: {}\n"
|
||||
"Stage 3 ntexmap: {}\nStage 3 ntexcoord: {}",
|
||||
"Indirect stage 0 texmap: {}\nIndirect stage 0 tex coord: {}\n"
|
||||
"Indirect stage 1 texmap: {}\nIndirect stage 1 tex coord: {}\n"
|
||||
"Indirect stage 2 texmap: {}\nIndirect stage 2 tex coord: {}\n"
|
||||
"Indirect stage 3 texmap: {}\nIndirect stage 3 tex coord: {}",
|
||||
indref.bi0, indref.bc0, indref.bi1, indref.bc1, indref.bi2, indref.bc2,
|
||||
indref.bi3, indref.bc3);
|
||||
}
|
||||
|
@ -1743,21 +1756,27 @@ union TCInfo
|
|||
u32 hex;
|
||||
};
|
||||
template <>
|
||||
struct fmt::formatter<TCInfo>
|
||||
struct fmt::formatter<std::pair<bool, TCInfo>>
|
||||
{
|
||||
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
|
||||
template <typename FormatContext>
|
||||
auto format(const TCInfo& info, FormatContext& ctx) const
|
||||
auto format(const std::pair<bool, TCInfo>& p, FormatContext& ctx) const
|
||||
{
|
||||
return fmt::format_to(ctx.out(),
|
||||
"Scale: {}\n"
|
||||
"Range bias: {}\n"
|
||||
"Cylindric wrap: {}\n"
|
||||
"Use line offset: {} (s only)\n"
|
||||
"Use point offset: {} (s only)",
|
||||
info.scale_minus_1 + 1, info.range_bias ? "Yes" : "No",
|
||||
info.cylindric_wrap ? "Yes" : "No", info.line_offset ? "Yes" : "No",
|
||||
info.point_offset ? "Yes" : "No");
|
||||
const auto& [is_s, info] = p;
|
||||
auto out = fmt::format_to(ctx.out(),
|
||||
"{0} coord scale: {1}\n"
|
||||
"{0} coord range bias: {2}\n"
|
||||
"{0} coord cylindric wrap: {3}",
|
||||
is_s ? 'S' : 'T', info.scale_minus_1 + 1,
|
||||
info.range_bias ? "Yes" : "No", info.cylindric_wrap ? "Yes" : "No");
|
||||
if (is_s)
|
||||
{
|
||||
out = fmt::format_to(out,
|
||||
"\nUse line offset: {}"
|
||||
"\nUse point offset: {}",
|
||||
info.line_offset ? "Yes" : "No", info.point_offset ? "Yes" : "No");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1834,6 +1853,19 @@ struct fmt::formatter<TevReg>
|
|||
}
|
||||
};
|
||||
|
||||
enum class ColorChannel : u32
|
||||
{
|
||||
Red = 0,
|
||||
Green = 1,
|
||||
Blue = 2,
|
||||
Alpha = 3,
|
||||
};
|
||||
template <>
|
||||
struct fmt::formatter<ColorChannel> : EnumFormatter<ColorChannel::Alpha>
|
||||
{
|
||||
formatter() : EnumFormatter({"Red", "Green", "Blue", "Alpha"}) {}
|
||||
};
|
||||
|
||||
enum class KonstSel : u32
|
||||
{
|
||||
V1 = 0,
|
||||
|
@ -1908,29 +1940,65 @@ struct fmt::formatter<KonstSel> : EnumFormatter<KonstSel::K3_A>
|
|||
|
||||
union TevKSel
|
||||
{
|
||||
BitField<0, 2, u32> swap1;
|
||||
BitField<2, 2, u32> swap2;
|
||||
BitField<4, 5, KonstSel> kcsel0;
|
||||
BitField<9, 5, KonstSel> kasel0;
|
||||
BitField<14, 5, KonstSel> kcsel1;
|
||||
BitField<19, 5, KonstSel> kasel1;
|
||||
BitField<0, 2, ColorChannel> swap_rb; // Odd ksel number: red; even: blue
|
||||
BitField<2, 2, ColorChannel> swap_ga; // Odd ksel number: green; even: alpha
|
||||
BitField<4, 5, KonstSel> kcsel_even;
|
||||
BitField<9, 5, KonstSel> kasel_even;
|
||||
BitField<14, 5, KonstSel> kcsel_odd;
|
||||
BitField<19, 5, KonstSel> kasel_odd;
|
||||
u32 hex;
|
||||
|
||||
KonstSel getKC(int i) const { return i ? kcsel1.Value() : kcsel0.Value(); }
|
||||
KonstSel getKA(int i) const { return i ? kasel1.Value() : kasel0.Value(); }
|
||||
};
|
||||
template <>
|
||||
struct fmt::formatter<TevKSel>
|
||||
struct fmt::formatter<std::pair<u8, TevKSel>>
|
||||
{
|
||||
constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
|
||||
template <typename FormatContext>
|
||||
auto format(const TevKSel& ksel, FormatContext& ctx) const
|
||||
auto format(const std::pair<u8, TevKSel>& p, FormatContext& ctx) const
|
||||
{
|
||||
const auto& [cmd, ksel] = p;
|
||||
const u8 swap_number = (cmd - BPMEM_TEV_KSEL) / 2;
|
||||
const bool swap_ba = (cmd - BPMEM_TEV_KSEL) & 1;
|
||||
const u8 even_stage = (cmd - BPMEM_TEV_KSEL) * 2;
|
||||
const u8 odd_stage = even_stage + 1;
|
||||
|
||||
return fmt::format_to(ctx.out(),
|
||||
"Swap 1: {}\nSwap 2: {}\nColor sel 0: {}\nAlpha sel 0: {}\n"
|
||||
"Color sel 1: {}\nAlpha sel 1: {}",
|
||||
ksel.swap1, ksel.swap2, ksel.kcsel0, ksel.kasel0, ksel.kcsel1,
|
||||
ksel.kasel1);
|
||||
"Swap table {0}: {1} channel comes from input's {2} channel\n"
|
||||
"Swap table {0}: {3} channel comes from input's {4} channel\n"
|
||||
"TEV stage {5} konst color: {6}\n"
|
||||
"TEV stage {5} konst alpha: {7}\n"
|
||||
"TEV stage {8} konst color: {9}\n"
|
||||
"TEV stage {8} konst alpha: {10}",
|
||||
swap_number, swap_ba ? "Blue" : "Red", ksel.swap_rb,
|
||||
swap_ba ? "Alpha" : "Green", ksel.swap_ga, even_stage, ksel.kcsel_even,
|
||||
ksel.kasel_even, odd_stage, ksel.kcsel_odd, ksel.kasel_odd);
|
||||
}
|
||||
};
|
||||
|
||||
struct AllTevKSels
|
||||
{
|
||||
std::array<TevKSel, 8> ksel;
|
||||
|
||||
KonstSel GetKonstColor(u32 tev_stage) const
|
||||
{
|
||||
const u32 ksel_num = tev_stage >> 1;
|
||||
const bool odd = tev_stage & 1;
|
||||
const auto& cur_ksel = ksel[ksel_num];
|
||||
return odd ? cur_ksel.kcsel_odd.Value() : cur_ksel.kcsel_even.Value();
|
||||
}
|
||||
KonstSel GetKonstAlpha(u32 tev_stage) const
|
||||
{
|
||||
const u32 ksel_num = tev_stage >> 1;
|
||||
const bool odd = tev_stage & 1;
|
||||
const auto& cur_ksel = ksel[ksel_num];
|
||||
return odd ? cur_ksel.kasel_odd.Value() : cur_ksel.kasel_even.Value();
|
||||
}
|
||||
Common::EnumMap<ColorChannel, ColorChannel::Alpha> GetSwapTable(u32 swap_table_id) const
|
||||
{
|
||||
const u32 rg_ksel_num = swap_table_id << 1;
|
||||
const u32 ba_ksel_num = rg_ksel_num + 1;
|
||||
const auto& rg_ksel = ksel[rg_ksel_num];
|
||||
const auto& ba_ksel = ksel[ba_ksel_num];
|
||||
return {rg_ksel.swap_rb, rg_ksel.swap_ga, ba_ksel.swap_rb, ba_ksel.swap_ga};
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2350,70 +2418,70 @@ enum class EmulatedZ : u32
|
|||
|
||||
struct BPMemory
|
||||
{
|
||||
GenMode genMode;
|
||||
u32 display_copy_filter[4]; // 01-04
|
||||
u32 unknown; // 05
|
||||
GenMode genMode; // 0x00
|
||||
u32 display_copy_filter[4]; // 0x01-0x04
|
||||
u32 unknown; // 0x05
|
||||
// indirect matrices (set by GXSetIndTexMtx, selected by TevStageIndirect::matrix_index)
|
||||
// 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
|
||||
ScissorPos scissorTL; // 20
|
||||
ScissorPos 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
|
||||
CopyFilterCoefficients copyfilter; // 53,54
|
||||
u32 boundbox0; // 55
|
||||
u32 boundbox1; // 56
|
||||
u32 unknown7[2]; // 57,58
|
||||
ScissorOffset 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
|
||||
AllTexUnits tex; // 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
|
||||
IND_MTX indmtx[3]; // 0x06-0x0e: GXSetIndTexMtx, 2x3 matrices
|
||||
IND_IMASK imask; // 0x0f
|
||||
TevStageIndirect tevind[16]; // 0x10-0x1f: GXSetTevIndirect
|
||||
ScissorPos scissorTL; // 0x20
|
||||
ScissorPos scissorBR; // 0x21
|
||||
LPSize lineptwidth; // 0x22
|
||||
u32 sucounter; // 0x23
|
||||
u32 rascounter; // 0x24
|
||||
TEXSCALE texscale[2]; // 0x25,0x26: GXSetIndTexCoordScale
|
||||
RAS1_IREF tevindref; // 0x27: GXSetIndTexOrder
|
||||
TwoTevStageOrders tevorders[8]; // 0x28-0x2f
|
||||
TCoordInfo texcoords[8]; // 0x30-0x4f: s,t,s,t,s,t,s,t...
|
||||
ZMode zmode; // 0x40
|
||||
BlendMode blendmode; // 0x41
|
||||
ConstantAlpha dstalpha; // 0x42
|
||||
PEControl zcontrol; // 0x43: GXSetZCompLoc, GXPixModeSync
|
||||
FieldMask fieldmask; // 0x44
|
||||
u32 drawdone; // 0x45: bit1=1 if end of list
|
||||
u32 unknown5; // 0x46: clock?
|
||||
u32 petoken; // 0x47
|
||||
u32 petokenint; // 0x48
|
||||
X10Y10 copyTexSrcXY; // 0x49
|
||||
X10Y10 copyTexSrcWH; // 0x4a
|
||||
u32 copyTexDest; // 0x4b: CopyAddress (GXDispCopy and GXTexCopy use it)
|
||||
u32 unknown6; // 0x4c
|
||||
// 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 copyMipMapStrideChannels; // 0x4d
|
||||
u32 dispcopyyscale; // 0x4e
|
||||
u32 clearcolorAR; // 0x4f
|
||||
u32 clearcolorGB; // 0x50
|
||||
u32 clearZValue; // 0x51
|
||||
UPE_Copy triggerEFBCopy; // 0x52
|
||||
CopyFilterCoefficients copyfilter; // 0x53,0x54
|
||||
u32 boundbox0; // 0x55
|
||||
u32 boundbox1; // 0x56
|
||||
u32 unknown7[2]; // 0x57,0x58
|
||||
ScissorOffset scissorOffset; // 0x59
|
||||
u32 unknown8[6]; // 0x5a-0x5f
|
||||
BPS_TmemConfig tmem_config; // 0x60-0x66
|
||||
u32 metric; // 0x67
|
||||
FieldMode fieldmode; // 0x68
|
||||
u32 unknown10[7]; // 0x69-0x6f
|
||||
u32 unknown11[16]; // 0x70-0x7f
|
||||
AllTexUnits tex; // 0x80-0xbf
|
||||
TevStageCombiner combiners[16]; // 0xc0-0xdf
|
||||
TevReg tevregs[4]; // 0xe0-0xe7
|
||||
FogRangeParams fogRange; // 0xe8-0xed
|
||||
FogParams fog; // 0xee-0xf2
|
||||
AlphaTest alpha_test; // 0xf3
|
||||
ZTex1 ztex1; // 0xf4
|
||||
ZTex2 ztex2; // 0xf5
|
||||
AllTevKSels tevksel; // 0xf6-0xfd
|
||||
u32 bpMask; // 0xfe
|
||||
u32 unknown18; // 0xff
|
||||
|
||||
EmulatedZ GetEmulatedZ() const
|
||||
{
|
||||
|
|
|
@ -811,7 +811,7 @@ std::pair<std::string, std::string> GetBPRegInfo(u8 cmd, u32 cmddata)
|
|||
case BPMEM_IND_CMD + 13:
|
||||
case BPMEM_IND_CMD + 14:
|
||||
case BPMEM_IND_CMD + 15:
|
||||
return std::make_pair(fmt::format("BPMEM_IND_CMD command {}", cmd - BPMEM_IND_CMD),
|
||||
return std::make_pair(fmt::format("BPMEM_IND_CMD number {}", cmd - BPMEM_IND_CMD),
|
||||
fmt::to_string(TevStageIndirect{.fullhex = cmddata}));
|
||||
|
||||
case BPMEM_SCISSORTL: // 0x20
|
||||
|
@ -832,14 +832,12 @@ std::pair<std::string, std::string> GetBPRegInfo(u8 cmd, u32 cmddata)
|
|||
// TODO: Description
|
||||
|
||||
case BPMEM_RAS1_SS0: // 0x25
|
||||
return std::make_pair(
|
||||
RegName(BPMEM_RAS1_SS0),
|
||||
fmt::format("Indirect texture stages 0 and 1:\n{}", TEXSCALE{.hex = cmddata}));
|
||||
return std::make_pair(RegName(BPMEM_RAS1_SS0),
|
||||
fmt::to_string(std::make_pair(cmd, TEXSCALE{.hex = cmddata})));
|
||||
|
||||
case BPMEM_RAS1_SS1: // 0x26
|
||||
return std::make_pair(
|
||||
RegName(BPMEM_RAS1_SS1),
|
||||
fmt::format("Indirect texture stages 2 and 3:\n{}", TEXSCALE{.hex = cmddata}));
|
||||
return std::make_pair(RegName(BPMEM_RAS1_SS1),
|
||||
fmt::to_string(std::make_pair(cmd, TEXSCALE{.hex = cmddata})));
|
||||
|
||||
case BPMEM_IREF: // 0x27
|
||||
return std::make_pair(RegName(BPMEM_IREF), fmt::to_string(RAS1_IREF{.hex = cmddata}));
|
||||
|
@ -853,7 +851,7 @@ std::pair<std::string, std::string> GetBPRegInfo(u8 cmd, u32 cmddata)
|
|||
case BPMEM_TREF + 6:
|
||||
case BPMEM_TREF + 7:
|
||||
return std::make_pair(fmt::format("BPMEM_TREF number {}", cmd - BPMEM_TREF),
|
||||
fmt::to_string(TwoTevStageOrders{.hex = cmddata}));
|
||||
fmt::to_string(std::make_pair(cmd, TwoTevStageOrders{.hex = cmddata})));
|
||||
|
||||
case BPMEM_SU_SSIZE: // 0x30
|
||||
case BPMEM_SU_SSIZE + 2:
|
||||
|
@ -864,7 +862,7 @@ std::pair<std::string, std::string> GetBPRegInfo(u8 cmd, u32 cmddata)
|
|||
case BPMEM_SU_SSIZE + 12:
|
||||
case BPMEM_SU_SSIZE + 14:
|
||||
return std::make_pair(fmt::format("BPMEM_SU_SSIZE number {}", (cmd - BPMEM_SU_SSIZE) / 2),
|
||||
fmt::format("S size info:\n{}", TCInfo{.hex = cmddata}));
|
||||
fmt::to_string(std::make_pair(true, TCInfo{.hex = cmddata})));
|
||||
|
||||
case BPMEM_SU_TSIZE: // 0x31
|
||||
case BPMEM_SU_TSIZE + 2:
|
||||
|
@ -875,7 +873,7 @@ std::pair<std::string, std::string> GetBPRegInfo(u8 cmd, u32 cmddata)
|
|||
case BPMEM_SU_TSIZE + 12:
|
||||
case BPMEM_SU_TSIZE + 14:
|
||||
return std::make_pair(fmt::format("BPMEM_SU_TSIZE number {}", (cmd - BPMEM_SU_TSIZE) / 2),
|
||||
fmt::format("T size info:\n{}", TCInfo{.hex = cmddata}));
|
||||
fmt::to_string(std::make_pair(false, TCInfo{.hex = cmddata})));
|
||||
|
||||
case BPMEM_ZMODE: // 0x40
|
||||
return std::make_pair(RegName(BPMEM_ZMODE), fmt::format("Z mode: {}", ZMode{.hex = cmddata}));
|
||||
|
@ -1249,7 +1247,7 @@ std::pair<std::string, std::string> GetBPRegInfo(u8 cmd, u32 cmddata)
|
|||
case BPMEM_TEV_KSEL + 6:
|
||||
case BPMEM_TEV_KSEL + 7:
|
||||
return std::make_pair(fmt::format("BPMEM_TEV_KSEL number {}", cmd - BPMEM_TEV_KSEL),
|
||||
fmt::to_string(TevKSel{.hex = cmddata}));
|
||||
fmt::to_string(std::make_pair(cmd, TevKSel{.hex = cmddata})));
|
||||
|
||||
case BPMEM_BP_MASK: // 0xFE
|
||||
return std::make_pair(RegName(BPMEM_BP_MASK),
|
||||
|
|
|
@ -167,6 +167,8 @@ constexpr Common::EnumMap<const char*, TevOutput::Color2> tev_a_output_table{
|
|||
"c2.a",
|
||||
};
|
||||
|
||||
constexpr Common::EnumMap<char, ColorChannel::Alpha> rgba_swizzle{'r', 'g', 'b', 'a'};
|
||||
|
||||
PixelShaderUid GetPixelShaderUid()
|
||||
{
|
||||
PixelShaderUid out;
|
||||
|
@ -254,22 +256,22 @@ PixelShaderUid GetPixelShaderUid()
|
|||
ac.a == TevAlphaArg::RasAlpha || ac.b == TevAlphaArg::RasAlpha ||
|
||||
ac.c == TevAlphaArg::RasAlpha || ac.d == TevAlphaArg::RasAlpha)
|
||||
{
|
||||
const int i = bpmem.combiners[n].alphaC.rswap;
|
||||
uid_data->stagehash[n].tevksel_swap1a = bpmem.tevksel[i * 2].swap1;
|
||||
uid_data->stagehash[n].tevksel_swap2a = bpmem.tevksel[i * 2].swap2;
|
||||
uid_data->stagehash[n].tevksel_swap1b = bpmem.tevksel[i * 2 + 1].swap1;
|
||||
uid_data->stagehash[n].tevksel_swap2b = bpmem.tevksel[i * 2 + 1].swap2;
|
||||
const auto ras_swap_table = bpmem.tevksel.GetSwapTable(bpmem.combiners[n].alphaC.rswap);
|
||||
uid_data->stagehash[n].ras_swap_r = ras_swap_table[ColorChannel::Red];
|
||||
uid_data->stagehash[n].ras_swap_g = ras_swap_table[ColorChannel::Green];
|
||||
uid_data->stagehash[n].ras_swap_b = ras_swap_table[ColorChannel::Blue];
|
||||
uid_data->stagehash[n].ras_swap_a = ras_swap_table[ColorChannel::Alpha];
|
||||
uid_data->stagehash[n].tevorders_colorchan = bpmem.tevorders[n / 2].getColorChan(n & 1);
|
||||
}
|
||||
|
||||
uid_data->stagehash[n].tevorders_enable = bpmem.tevorders[n / 2].getEnable(n & 1);
|
||||
if (uid_data->stagehash[n].tevorders_enable)
|
||||
{
|
||||
const int i = bpmem.combiners[n].alphaC.tswap;
|
||||
uid_data->stagehash[n].tevksel_swap1c = bpmem.tevksel[i * 2].swap1;
|
||||
uid_data->stagehash[n].tevksel_swap2c = bpmem.tevksel[i * 2].swap2;
|
||||
uid_data->stagehash[n].tevksel_swap1d = bpmem.tevksel[i * 2 + 1].swap1;
|
||||
uid_data->stagehash[n].tevksel_swap2d = bpmem.tevksel[i * 2 + 1].swap2;
|
||||
const auto tex_swap_table = bpmem.tevksel.GetSwapTable(bpmem.combiners[n].alphaC.tswap);
|
||||
uid_data->stagehash[n].tex_swap_r = tex_swap_table[ColorChannel::Red];
|
||||
uid_data->stagehash[n].tex_swap_g = tex_swap_table[ColorChannel::Green];
|
||||
uid_data->stagehash[n].tex_swap_b = tex_swap_table[ColorChannel::Blue];
|
||||
uid_data->stagehash[n].tex_swap_a = tex_swap_table[ColorChannel::Alpha];
|
||||
uid_data->stagehash[n].tevorders_texmap = bpmem.tevorders[n / 2].getTexMap(n & 1);
|
||||
}
|
||||
|
||||
|
@ -277,8 +279,8 @@ PixelShaderUid GetPixelShaderUid()
|
|||
cc.d == TevColorArg::Konst || ac.a == TevAlphaArg::Konst || ac.b == TevAlphaArg::Konst ||
|
||||
ac.c == TevAlphaArg::Konst || ac.d == TevAlphaArg::Konst)
|
||||
{
|
||||
uid_data->stagehash[n].tevksel_kc = bpmem.tevksel[n / 2].getKC(n & 1);
|
||||
uid_data->stagehash[n].tevksel_ka = bpmem.tevksel[n / 2].getKA(n & 1);
|
||||
uid_data->stagehash[n].tevksel_kc = bpmem.tevksel.GetKonstColor(n);
|
||||
uid_data->stagehash[n].tevksel_ka = bpmem.tevksel.GetKonstAlpha(n);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1412,30 +1414,18 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
|||
ac.c == TevAlphaArg::RasAlpha || ac.d == TevAlphaArg::RasAlpha)
|
||||
{
|
||||
// Generate swizzle string to represent the Ras color channel swapping
|
||||
const char rasswap[5] = {
|
||||
"rgba"[stage.tevksel_swap1a],
|
||||
"rgba"[stage.tevksel_swap2a],
|
||||
"rgba"[stage.tevksel_swap1b],
|
||||
"rgba"[stage.tevksel_swap2b],
|
||||
'\0',
|
||||
};
|
||||
|
||||
out.Write("\trastemp = {}.{};\n", tev_ras_table[stage.tevorders_colorchan], rasswap);
|
||||
out.Write("\trastemp = {}.{}{}{}{};\n", tev_ras_table[stage.tevorders_colorchan],
|
||||
rgba_swizzle[stage.ras_swap_r], rgba_swizzle[stage.ras_swap_g],
|
||||
rgba_swizzle[stage.ras_swap_b], rgba_swizzle[stage.ras_swap_a]);
|
||||
}
|
||||
|
||||
if (stage.tevorders_enable && uid_data->genMode_numtexgens > 0)
|
||||
{
|
||||
// Generate swizzle string to represent the texture color channel swapping
|
||||
const char texswap[5] = {
|
||||
"rgba"[stage.tevksel_swap1c],
|
||||
"rgba"[stage.tevksel_swap2c],
|
||||
"rgba"[stage.tevksel_swap1d],
|
||||
"rgba"[stage.tevksel_swap2d],
|
||||
'\0',
|
||||
};
|
||||
|
||||
out.Write("\ttextemp = sampleTextureWrapper({0}u, tevcoord.xy, layer).{1};\n",
|
||||
stage.tevorders_texmap, texswap);
|
||||
out.Write("\ttextemp = sampleTextureWrapper({}u, tevcoord.xy, layer).{}{}{}{};\n",
|
||||
stage.tevorders_texmap, rgba_swizzle[stage.tex_swap_r],
|
||||
rgba_swizzle[stage.tex_swap_g], rgba_swizzle[stage.tex_swap_b],
|
||||
rgba_swizzle[stage.tex_swap_a]);
|
||||
}
|
||||
else if (uid_data->genMode_numtexgens == 0)
|
||||
{
|
||||
|
|
|
@ -125,7 +125,7 @@ struct pixel_shader_uid_data
|
|||
{
|
||||
// TODO: Can save a lot space by removing the padding bits
|
||||
u32 cc : 24;
|
||||
u32 ac : 24; // tswap and rswap are left blank (encoded into the tevksel fields below)
|
||||
u32 ac : 24; // tswap and rswap are left blank (decoded into the swap fields below)
|
||||
|
||||
u32 tevorders_texmap : 3;
|
||||
u32 tevorders_texcoord : 3;
|
||||
|
@ -133,18 +133,19 @@ struct pixel_shader_uid_data
|
|||
RasColorChan tevorders_colorchan : 3;
|
||||
u32 pad1 : 7;
|
||||
|
||||
// TODO: Clean up the swapXY mess
|
||||
// TODO: We could save space by storing the 4 swap tables elsewhere and only storing references
|
||||
// to which table is used (the tswap and rswap fields), instead of duplicating them here
|
||||
u32 tevind : 21;
|
||||
u32 tevksel_swap1a : 2;
|
||||
u32 tevksel_swap2a : 2;
|
||||
u32 tevksel_swap1b : 2;
|
||||
u32 tevksel_swap2b : 2;
|
||||
ColorChannel ras_swap_r : 2;
|
||||
ColorChannel ras_swap_g : 2;
|
||||
ColorChannel ras_swap_b : 2;
|
||||
ColorChannel ras_swap_a : 2;
|
||||
u32 pad2 : 2;
|
||||
|
||||
u32 tevksel_swap1c : 2;
|
||||
u32 tevksel_swap2c : 2;
|
||||
u32 tevksel_swap1d : 2;
|
||||
u32 tevksel_swap2d : 2;
|
||||
ColorChannel tex_swap_r : 2;
|
||||
ColorChannel tex_swap_g : 2;
|
||||
ColorChannel tex_swap_b : 2;
|
||||
ColorChannel tex_swap_a : 2;
|
||||
KonstSel tevksel_kc : 5;
|
||||
KonstSel tevksel_ka : 5;
|
||||
u32 pad3 : 14;
|
||||
|
|
|
@ -271,12 +271,12 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
|||
" // AKA: Color Channel Swapping\n"
|
||||
"\n"
|
||||
" int4 ret;\n");
|
||||
out.Write(" ret.r = color[{}];\n", BitfieldExtract<&TevKSel::swap1>("bpmem_tevksel(s * 2u)"));
|
||||
out.Write(" ret.g = color[{}];\n", BitfieldExtract<&TevKSel::swap2>("bpmem_tevksel(s * 2u)"));
|
||||
out.Write(" ret.r = color[{}];\n", BitfieldExtract<&TevKSel::swap_rb>("bpmem_tevksel(s * 2u)"));
|
||||
out.Write(" ret.g = color[{}];\n", BitfieldExtract<&TevKSel::swap_ga>("bpmem_tevksel(s * 2u)"));
|
||||
out.Write(" ret.b = color[{}];\n",
|
||||
BitfieldExtract<&TevKSel::swap1>("bpmem_tevksel(s * 2u + 1u)"));
|
||||
BitfieldExtract<&TevKSel::swap_rb>("bpmem_tevksel(s * 2u + 1u)"));
|
||||
out.Write(" ret.a = color[{}];\n",
|
||||
BitfieldExtract<&TevKSel::swap2>("bpmem_tevksel(s * 2u + 1u)"));
|
||||
BitfieldExtract<&TevKSel::swap_ga>("bpmem_tevksel(s * 2u + 1u)"));
|
||||
out.Write(" return ret;\n"
|
||||
"}}\n\n");
|
||||
|
||||
|
@ -581,7 +581,8 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
|||
" ss.order = bpmem_tevorder(stage>>1);\n"
|
||||
" if ((stage & 1u) == 1u)\n"
|
||||
" ss.order = ss.order >> {};\n\n",
|
||||
int(TwoTevStageOrders().enable1.StartBit() - TwoTevStageOrders().enable0.StartBit()));
|
||||
int(TwoTevStageOrders().enable_tex_odd.StartBit() -
|
||||
TwoTevStageOrders().enable_tex_even.StartBit()));
|
||||
|
||||
// Disable texturing when there are no texgens (for now)
|
||||
if (numTexgen != 0)
|
||||
|
@ -596,11 +597,11 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
|||
|
||||
out.Write("\n"
|
||||
" uint tex_coord = {};\n",
|
||||
BitfieldExtract<&TwoTevStageOrders::texcoord0>("ss.order"));
|
||||
BitfieldExtract<&TwoTevStageOrders::texcoord_even>("ss.order"));
|
||||
out.Write(" int2 fixedPoint_uv = getTexCoord(tex_coord);\n"
|
||||
"\n"
|
||||
" bool texture_enabled = (ss.order & {}u) != 0u;\n",
|
||||
1 << TwoTevStageOrders().enable0.StartBit());
|
||||
1 << TwoTevStageOrders().enable_tex_even.StartBit());
|
||||
out.Write("\n"
|
||||
" // Indirect textures\n"
|
||||
" uint tevind = bpmem_tevind(stage);\n"
|
||||
|
@ -712,7 +713,7 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
|||
" // Sample texture for stage\n"
|
||||
" if (texture_enabled) {{\n"
|
||||
" uint sampler_num = {};\n",
|
||||
BitfieldExtract<&TwoTevStageOrders::texmap0>("ss.order"));
|
||||
BitfieldExtract<&TwoTevStageOrders::texmap_even>("ss.order"));
|
||||
out.Write("\n"
|
||||
" int4 color = sampleTextureWrapper(sampler_num, tevcoord.xy, layer);\n"
|
||||
" uint swap = {};\n",
|
||||
|
@ -1216,13 +1217,13 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
|||
"int4 getRasColor(State s, StageState ss, float4 colors_0, float4 colors_1) {{\n"
|
||||
" // Select Ras for stage\n"
|
||||
" uint ras = {};\n",
|
||||
BitfieldExtract<&TwoTevStageOrders::colorchan0>("ss.order"));
|
||||
BitfieldExtract<&TwoTevStageOrders::colorchan_even>("ss.order"));
|
||||
out.Write(" if (ras < 2u) {{ // Lighting Channel 0 or 1\n"
|
||||
" int4 color = iround(((ras == 0u) ? colors_0 : colors_1) * 255.0);\n"
|
||||
" uint swap = {};\n",
|
||||
BitfieldExtract<&TevStageCombiner::AlphaCombiner::rswap>("ss.ac"));
|
||||
out.Write(" return Swizzle(swap, color);\n");
|
||||
out.Write(" }} else if (ras == 5u) {{ // Alpha Bumb\n"
|
||||
out.Write(" }} else if (ras == 5u) {{ // Alpha Bump\n"
|
||||
" return int4(s.AlphaBump, s.AlphaBump, s.AlphaBump, s.AlphaBump);\n"
|
||||
" }} else if (ras == 6u) {{ // Normalzied Alpha Bump\n"
|
||||
" int normalized = s.AlphaBump | s.AlphaBump >> 5;\n"
|
||||
|
@ -1239,12 +1240,12 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
|
|||
" uint tevksel = bpmem_tevksel(ss.stage>>1);\n"
|
||||
" if ((ss.stage & 1u) == 0u)\n"
|
||||
" return int4(konstLookup[{}].rgb, konstLookup[{}].a);\n",
|
||||
BitfieldExtract<&TevKSel::kcsel0>("tevksel"),
|
||||
BitfieldExtract<&TevKSel::kasel0>("tevksel"));
|
||||
BitfieldExtract<&TevKSel::kcsel_even>("tevksel"),
|
||||
BitfieldExtract<&TevKSel::kasel_even>("tevksel"));
|
||||
out.Write(" else\n"
|
||||
" return int4(konstLookup[{}].rgb, konstLookup[{}].a);\n",
|
||||
BitfieldExtract<&TevKSel::kcsel1>("tevksel"),
|
||||
BitfieldExtract<&TevKSel::kasel1>("tevksel"));
|
||||
BitfieldExtract<&TevKSel::kcsel_odd>("tevksel"),
|
||||
BitfieldExtract<&TevKSel::kasel_odd>("tevksel"));
|
||||
out.Write("}}\n");
|
||||
|
||||
return out;
|
||||
|
|
|
@ -321,17 +321,17 @@ std::pair<std::string, std::string> GetXFRegInfo(u32 address, u32 value)
|
|||
|
||||
case XFMEM_SETCHAN0_AMBCOLOR:
|
||||
return std::make_pair(RegName(XFMEM_SETCHAN0_AMBCOLOR),
|
||||
fmt::format("Channel 0 Ambient Color: {:06x}", value));
|
||||
fmt::format("Channel 0 Ambient Color: {:08x}", value));
|
||||
case XFMEM_SETCHAN1_AMBCOLOR:
|
||||
return std::make_pair(RegName(XFMEM_SETCHAN1_AMBCOLOR),
|
||||
fmt::format("Channel 1 Ambient Color: {:06x}", value));
|
||||
fmt::format("Channel 1 Ambient Color: {:08x}", value));
|
||||
|
||||
case XFMEM_SETCHAN0_MATCOLOR:
|
||||
return std::make_pair(RegName(XFMEM_SETCHAN0_MATCOLOR),
|
||||
fmt::format("Channel 0 Material Color: {:06x}", value));
|
||||
fmt::format("Channel 0 Material Color: {:08x}", value));
|
||||
case XFMEM_SETCHAN1_MATCOLOR:
|
||||
return std::make_pair(RegName(XFMEM_SETCHAN1_MATCOLOR),
|
||||
fmt::format("Channel 1 Material Color: {:06x}", value));
|
||||
fmt::format("Channel 1 Material Color: {:08x}", value));
|
||||
|
||||
case XFMEM_SETCHAN0_COLOR: // Channel Color
|
||||
return std::make_pair(RegName(XFMEM_SETCHAN0_COLOR),
|
||||
|
@ -474,8 +474,8 @@ std::string GetXFMemName(u32 address)
|
|||
}
|
||||
else if (address >= XFMEM_POSTMATRICES && address < XFMEM_POSTMATRICES_END)
|
||||
{
|
||||
const u32 row = (address - XFMEM_POSMATRICES) / 4;
|
||||
const u32 col = (address - XFMEM_POSMATRICES) % 4;
|
||||
const u32 row = (address - XFMEM_POSTMATRICES) / 4;
|
||||
const u32 col = (address - XFMEM_POSTMATRICES) % 4;
|
||||
return fmt::format("Post matrix row {:2d} col {:2d}", row, col);
|
||||
}
|
||||
else if (address >= XFMEM_LIGHTS && address < XFMEM_LIGHTS_END)
|
||||
|
@ -508,9 +508,9 @@ std::string GetXFMemName(u32 address)
|
|||
case 15:
|
||||
// Yagcd says light dir or "1/2 angle", dolphin has union for ddir or shalfangle.
|
||||
// It would make sense if d stood for direction and s for specular, but it's ddir and
|
||||
// shalfhangle that have the comment "specular lights only", both at the same offset,
|
||||
// shalfangle that have the comment "specular lights only", both at the same offset,
|
||||
// while dpos and sdir have none...
|
||||
return fmt::format("Light {0} {1} direction or half hangle {1}", light, "xyz"[offset - 13]);
|
||||
return fmt::format("Light {0} {1} direction or half angle {1}", light, "xyz"[offset - 13]);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue