123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772 |
- // Copyright 2008 Dolphin Emulator Project
- // SPDX-License-Identifier: GPL-2.0-or-later
- #pragma once
- #include <array>
- #include <string>
- #include <type_traits>
- #include <utility>
- #include "Common/BitField.h"
- #include "Common/BitSet.h"
- #include "Common/CommonTypes.h"
- #include "Common/EnumFormatter.h"
- #include "Common/EnumMap.h"
- #include "Common/MsgHandler.h"
- enum
- {
- // These commands use the high nybble for the command itself, and the lower nybble is an argument.
- // TODO: However, Dolphin's implementation (in LoadCPReg) and YAGCD disagree about what values are
- // valid for the lower nybble.
- // YAGCD mentions 0x20 as "?", and does not mention the others
- // Libogc has 0x00 and 0x20, where 0x00 is tied to GX_ClearVCacheMetric and 0x20 related to
- // cpPerfMode. 0x10 may be GX_SetVCacheMetric, but that function is empty. In any case, these all
- // are probably for perf queries, and no title seems to actually need a full implementation.
- UNKNOWN_00 = 0x00,
- UNKNOWN_10 = 0x10,
- UNKNOWN_20 = 0x20,
- // YAGCD says 0x30 only; LoadCPReg allows any
- MATINDEX_A = 0x30,
- // YAGCD says 0x40 only; LoadCPReg allows any
- MATINDEX_B = 0x40,
- // YAGCD says 0x50-0x57 for distinct VCDs; LoadCPReg allows any for a single VCD
- VCD_LO = 0x50,
- // YAGCD says 0x60-0x67 for distinct VCDs; LoadCPReg allows any for a single VCD
- VCD_HI = 0x60,
- // YAGCD and LoadCPReg both agree that only 0x70-0x77 are valid
- CP_VAT_REG_A = 0x70,
- // YAGCD and LoadCPReg both agree that only 0x80-0x87 are valid
- CP_VAT_REG_B = 0x80,
- // YAGCD and LoadCPReg both agree that only 0x90-0x97 are valid
- CP_VAT_REG_C = 0x90,
- // YAGCD and LoadCPReg agree that 0xa0-0xaf are valid
- ARRAY_BASE = 0xa0,
- // YAGCD and LoadCPReg agree that 0xb0-0xbf are valid
- ARRAY_STRIDE = 0xb0,
- CP_COMMAND_MASK = 0xf0,
- CP_NUM_VAT_REG = 0x08,
- CP_VAT_MASK = 0x07,
- CP_NUM_ARRAYS = 0x10,
- CP_ARRAY_MASK = 0x0f,
- };
- // Vertex array numbers
- enum class CPArray : u8
- {
- Position = 0,
- Normal = 1,
- Color0 = 2,
- Color1 = 3,
- TexCoord0 = 4,
- TexCoord1 = 5,
- TexCoord2 = 6,
- TexCoord3 = 7,
- TexCoord4 = 8,
- TexCoord5 = 9,
- TexCoord6 = 10,
- TexCoord7 = 11,
- XF_A = 12, // Usually used for position matrices
- XF_B = 13, // Usually used for normal matrices
- XF_C = 14, // Usually used for tex coord matrices
- XF_D = 15, // Usually used for light objects
- };
- template <>
- struct fmt::formatter<CPArray> : EnumFormatter<CPArray::XF_D>
- {
- static constexpr array_type names = {"Position", "Normal", "Color 0", "Color 1",
- "Tex Coord 0", "Tex Coord 1", "Tex Coord 2", "Tex Coord 3",
- "Tex Coord 4", "Tex Coord 5", "Tex Coord 6", "Tex Coord 7",
- "XF A", "XF B", "XF C", "XF D"};
- constexpr formatter() : EnumFormatter(names) {}
- };
- // Intended for offsetting from Color0/TexCoord0
- constexpr CPArray operator+(CPArray array, u8 offset)
- {
- return static_cast<CPArray>(static_cast<u8>(array) + offset);
- }
- // Number of arrays related to vertex components (position, normal, color, tex coord)
- // Excludes the 4 arrays used for indexed XF loads
- constexpr u8 NUM_VERTEX_COMPONENT_ARRAYS = 12;
- // Vertex components
- enum class VertexComponentFormat
- {
- NotPresent = 0,
- Direct = 1,
- Index8 = 2,
- Index16 = 3,
- };
- template <>
- struct fmt::formatter<VertexComponentFormat> : EnumFormatter<VertexComponentFormat::Index16>
- {
- constexpr formatter() : EnumFormatter({"Not present", "Direct", "8-bit index", "16-bit index"}) {}
- };
- constexpr bool IsIndexed(VertexComponentFormat format)
- {
- return format == VertexComponentFormat::Index8 || format == VertexComponentFormat::Index16;
- }
- enum class ComponentFormat
- {
- UByte = 0, // Invalid for normals
- Byte = 1,
- UShort = 2, // Invalid for normals
- Short = 3,
- Float = 4,
- // Known to be used by Fifa Street and Def Jam: Fight for New York
- // See https://bugs.dolphin-emu.org/issues/12719
- // Assumed to behave the same as float, but further testing is needed
- InvalidFloat5 = 5,
- // Not known to be used
- InvalidFloat6 = 6,
- InvalidFloat7 = 7,
- };
- // NOTE: don't include the invalid formats here, so that EnumFormatter marks them as invalid
- // (EnumFormatter also handles bounds-checking).
- template <>
- struct fmt::formatter<ComponentFormat> : EnumFormatter<ComponentFormat::Float>
- {
- static constexpr array_type names = {"Unsigned Byte", "Byte", "Unsigned Short", "Short", "Float"};
- constexpr formatter() : EnumFormatter(names) {}
- };
- constexpr u32 GetElementSize(ComponentFormat format)
- {
- switch (format)
- {
- case ComponentFormat::UByte:
- case ComponentFormat::Byte:
- return 1;
- case ComponentFormat::UShort:
- case ComponentFormat::Short:
- return 2;
- case ComponentFormat::Float:
- case ComponentFormat::InvalidFloat5:
- case ComponentFormat::InvalidFloat6:
- case ComponentFormat::InvalidFloat7:
- return 4;
- default:
- PanicAlertFmt("Unknown format {}", format);
- return 0;
- }
- }
- enum class CoordComponentCount
- {
- XY = 0,
- XYZ = 1,
- };
- template <>
- struct fmt::formatter<CoordComponentCount> : EnumFormatter<CoordComponentCount::XYZ>
- {
- constexpr formatter() : EnumFormatter({"2 (x, y)", "3 (x, y, z)"}) {}
- };
- enum class NormalComponentCount
- {
- N = 0,
- NTB = 1,
- };
- template <>
- struct fmt::formatter<NormalComponentCount> : EnumFormatter<NormalComponentCount::NTB>
- {
- constexpr formatter() : EnumFormatter({"1 (normal)", "3 (normal, tangent, binormal)"}) {}
- };
- enum class ColorComponentCount
- {
- RGB = 0,
- RGBA = 1,
- };
- template <>
- struct fmt::formatter<ColorComponentCount> : EnumFormatter<ColorComponentCount::RGBA>
- {
- constexpr formatter() : EnumFormatter({"3 (r, g, b)", "4 (r, g, b, a)"}) {}
- };
- enum class ColorFormat
- {
- RGB565 = 0, // 16b
- RGB888 = 1, // 24b
- RGB888x = 2, // 32b
- RGBA4444 = 3, // 16b
- RGBA6666 = 4, // 24b
- RGBA8888 = 5, // 32b
- };
- template <>
- struct fmt::formatter<ColorFormat> : EnumFormatter<ColorFormat::RGBA8888>
- {
- static constexpr array_type names = {
- "RGB 16 bits 565", "RGB 24 bits 888", "RGB 32 bits 888x",
- "RGBA 16 bits 4444", "RGBA 24 bits 6666", "RGBA 32 bits 8888",
- };
- constexpr formatter() : EnumFormatter(names) {}
- };
- enum class TexComponentCount
- {
- S = 0,
- ST = 1,
- };
- template <>
- struct fmt::formatter<TexComponentCount> : EnumFormatter<TexComponentCount::ST>
- {
- constexpr formatter() : EnumFormatter({"1 (s)", "2 (s, t)"}) {}
- };
- struct TVtxDesc
- {
- union Low
- {
- // false: not present
- // true: present
- BitField<0, 1, bool, u32> PosMatIdx;
- BitField<1, 1, bool, u32> Tex0MatIdx;
- BitField<2, 1, bool, u32> Tex1MatIdx;
- BitField<3, 1, bool, u32> Tex2MatIdx;
- BitField<4, 1, bool, u32> Tex3MatIdx;
- BitField<5, 1, bool, u32> Tex4MatIdx;
- BitField<6, 1, bool, u32> Tex5MatIdx;
- BitField<7, 1, bool, u32> Tex6MatIdx;
- BitField<8, 1, bool, u32> Tex7MatIdx;
- BitFieldArray<1, 1, 8, bool, u32> TexMatIdx;
- BitField<9, 2, VertexComponentFormat> Position;
- BitField<11, 2, VertexComponentFormat> Normal;
- BitField<13, 2, VertexComponentFormat> Color0;
- BitField<15, 2, VertexComponentFormat> Color1;
- BitFieldArray<13, 2, 2, VertexComponentFormat> Color;
- u32 Hex = 0;
- };
- union High
- {
- BitField<0, 2, VertexComponentFormat> Tex0Coord;
- BitField<2, 2, VertexComponentFormat> Tex1Coord;
- BitField<4, 2, VertexComponentFormat> Tex2Coord;
- BitField<6, 2, VertexComponentFormat> Tex3Coord;
- BitField<8, 2, VertexComponentFormat> Tex4Coord;
- BitField<10, 2, VertexComponentFormat> Tex5Coord;
- BitField<12, 2, VertexComponentFormat> Tex6Coord;
- BitField<14, 2, VertexComponentFormat> Tex7Coord;
- BitFieldArray<0, 2, 8, VertexComponentFormat> TexCoord;
- u32 Hex = 0;
- };
- Low low;
- High high;
- };
- template <>
- struct fmt::formatter<TVtxDesc::Low>
- {
- constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
- template <typename FormatContext>
- auto format(const TVtxDesc::Low& desc, FormatContext& ctx) const
- {
- static constexpr std::array<const char*, 2> present = {"Not present", "Present"};
- return fmt::format_to(
- ctx.out(),
- "Position and normal matrix index: {}\n"
- "Texture Coord 0 matrix index: {}\n"
- "Texture Coord 1 matrix index: {}\n"
- "Texture Coord 2 matrix index: {}\n"
- "Texture Coord 3 matrix index: {}\n"
- "Texture Coord 4 matrix index: {}\n"
- "Texture Coord 5 matrix index: {}\n"
- "Texture Coord 6 matrix index: {}\n"
- "Texture Coord 7 matrix index: {}\n"
- "Position: {}\n"
- "Normal: {}\n"
- "Color 0: {}\n"
- "Color 1: {}",
- present[desc.PosMatIdx], present[desc.Tex0MatIdx], present[desc.Tex1MatIdx],
- present[desc.Tex2MatIdx], present[desc.Tex3MatIdx], present[desc.Tex4MatIdx],
- present[desc.Tex5MatIdx], present[desc.Tex6MatIdx], present[desc.Tex7MatIdx], desc.Position,
- desc.Normal, desc.Color0, desc.Color1);
- }
- };
- template <>
- struct fmt::formatter<TVtxDesc::High>
- {
- constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
- template <typename FormatContext>
- auto format(const TVtxDesc::High& desc, FormatContext& ctx) const
- {
- return fmt::format_to(ctx.out(),
- "Texture Coord 0: {}\n"
- "Texture Coord 1: {}\n"
- "Texture Coord 2: {}\n"
- "Texture Coord 3: {}\n"
- "Texture Coord 4: {}\n"
- "Texture Coord 5: {}\n"
- "Texture Coord 6: {}\n"
- "Texture Coord 7: {}",
- desc.Tex0Coord, desc.Tex1Coord, desc.Tex2Coord, desc.Tex3Coord,
- desc.Tex4Coord, desc.Tex5Coord, desc.Tex6Coord, desc.Tex7Coord);
- }
- };
- template <>
- struct fmt::formatter<TVtxDesc>
- {
- constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
- template <typename FormatContext>
- auto format(const TVtxDesc& desc, FormatContext& ctx) const
- {
- return fmt::format_to(ctx.out(), "{}\n{}", desc.low, desc.high);
- }
- };
- union UVAT_group0
- {
- u32 Hex = 0;
- // 0:8
- BitField<0, 1, CoordComponentCount> PosElements;
- BitField<1, 3, ComponentFormat> PosFormat;
- BitField<4, 5, u32> PosFrac;
- // 9:12
- BitField<9, 1, NormalComponentCount> NormalElements;
- BitField<10, 3, ComponentFormat> NormalFormat;
- // 13:16
- BitField<13, 1, ColorComponentCount> Color0Elements;
- BitField<14, 3, ColorFormat> Color0Comp;
- // 17:20
- BitField<17, 1, ColorComponentCount> Color1Elements;
- BitField<18, 3, ColorFormat> Color1Comp;
- // 21:29
- BitField<21, 1, TexComponentCount> Tex0CoordElements;
- BitField<22, 3, ComponentFormat> Tex0CoordFormat;
- BitField<25, 5, u8, u32> Tex0Frac;
- // 30:31
- BitField<30, 1, bool, u32> ByteDequant;
- BitField<31, 1, bool, u32> NormalIndex3;
- };
- template <>
- struct fmt::formatter<UVAT_group0>
- {
- constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
- template <typename FormatContext>
- auto format(const UVAT_group0& g0, FormatContext& ctx) const
- {
- static constexpr std::array<const char*, 2> byte_dequant = {
- "shift does not apply to u8/s8 components", "shift applies to u8/s8 components"};
- static constexpr std::array<const char*, 2> normalindex3 = {
- "single index shared by normal, tangent, and binormal",
- "three indices, one each for normal, tangent, and binormal"};
- return fmt::format_to(ctx.out(),
- "Position elements: {}\n"
- "Position format: {}\n"
- "Position shift: {} ({})\n"
- "Normal elements: {}\n"
- "Normal format: {}\n"
- "Color 0 elements: {}\n"
- "Color 0 format: {}\n"
- "Color 1 elements: {}\n"
- "Color 1 format: {}\n"
- "Texture coord 0 elements: {}\n"
- "Texture coord 0 format: {}\n"
- "Texture coord 0 shift: {} ({})\n"
- "Byte dequant: {}\n"
- "Normal index 3: {}",
- g0.PosElements, g0.PosFormat, g0.PosFrac, 1.f / (1 << g0.PosFrac),
- g0.NormalElements, g0.NormalFormat, g0.Color0Elements, g0.Color0Comp,
- g0.Color1Elements, g0.Color1Comp, g0.Tex0CoordElements,
- g0.Tex0CoordFormat, g0.Tex0Frac, 1.f / (1 << g0.Tex0Frac),
- byte_dequant[g0.ByteDequant], normalindex3[g0.NormalIndex3]);
- }
- };
- union UVAT_group1
- {
- u32 Hex = 0;
- // 0:8
- BitField<0, 1, TexComponentCount> Tex1CoordElements;
- BitField<1, 3, ComponentFormat> Tex1CoordFormat;
- BitField<4, 5, u8, u32> Tex1Frac;
- // 9:17
- BitField<9, 1, TexComponentCount> Tex2CoordElements;
- BitField<10, 3, ComponentFormat> Tex2CoordFormat;
- BitField<13, 5, u8, u32> Tex2Frac;
- // 18:26
- BitField<18, 1, TexComponentCount> Tex3CoordElements;
- BitField<19, 3, ComponentFormat> Tex3CoordFormat;
- BitField<22, 5, u8, u32> Tex3Frac;
- // 27:30
- BitField<27, 1, TexComponentCount> Tex4CoordElements;
- BitField<28, 3, ComponentFormat> Tex4CoordFormat;
- // 31
- BitField<31, 1, bool, u32> VCacheEnhance;
- };
- template <>
- struct fmt::formatter<UVAT_group1>
- {
- constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
- template <typename FormatContext>
- auto format(const UVAT_group1& g1, FormatContext& ctx) const
- {
- return fmt::format_to(
- ctx.out(),
- "Texture coord 1 elements: {}\n"
- "Texture coord 1 format: {}\n"
- "Texture coord 1 shift: {} ({})\n"
- "Texture coord 2 elements: {}\n"
- "Texture coord 2 format: {}\n"
- "Texture coord 2 shift: {} ({})\n"
- "Texture coord 3 elements: {}\n"
- "Texture coord 3 format: {}\n"
- "Texture coord 3 shift: {} ({})\n"
- "Texture coord 4 elements: {}\n"
- "Texture coord 4 format: {}\n"
- "Enhance VCache (must always be on): {}",
- g1.Tex1CoordElements, g1.Tex1CoordFormat, g1.Tex1Frac, 1.f / (1 << g1.Tex1Frac),
- g1.Tex2CoordElements, g1.Tex2CoordFormat, g1.Tex2Frac, 1.f / (1 << g1.Tex2Frac),
- g1.Tex3CoordElements, g1.Tex3CoordFormat, g1.Tex3Frac, 1.f / (1 << g1.Tex3Frac),
- g1.Tex4CoordElements, g1.Tex4CoordFormat, g1.VCacheEnhance ? "Yes" : "No");
- }
- };
- union UVAT_group2
- {
- u32 Hex = 0;
- // 0:4
- BitField<0, 5, u8, u32> Tex4Frac;
- // 5:13
- BitField<5, 1, TexComponentCount> Tex5CoordElements;
- BitField<6, 3, ComponentFormat> Tex5CoordFormat;
- BitField<9, 5, u8, u32> Tex5Frac;
- // 14:22
- BitField<14, 1, TexComponentCount> Tex6CoordElements;
- BitField<15, 3, ComponentFormat> Tex6CoordFormat;
- BitField<18, 5, u8, u32> Tex6Frac;
- // 23:31
- BitField<23, 1, TexComponentCount> Tex7CoordElements;
- BitField<24, 3, ComponentFormat> Tex7CoordFormat;
- BitField<27, 5, u8, u32> Tex7Frac;
- };
- template <>
- struct fmt::formatter<UVAT_group2>
- {
- constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
- template <typename FormatContext>
- auto format(const UVAT_group2& g2, FormatContext& ctx) const
- {
- return fmt::format_to(ctx.out(),
- "Texture coord 4 shift: {} ({})\n"
- "Texture coord 5 elements: {}\n"
- "Texture coord 5 format: {}\n"
- "Texture coord 5 shift: {} ({})\n"
- "Texture coord 6 elements: {}\n"
- "Texture coord 6 format: {}\n"
- "Texture coord 6 shift: {} ({})\n"
- "Texture coord 7 elements: {}\n"
- "Texture coord 7 format: {}\n"
- "Texture coord 7 shift: {} ({})",
- g2.Tex4Frac, 1.f / (1 << g2.Tex4Frac), g2.Tex5CoordElements,
- g2.Tex5CoordFormat, g2.Tex5Frac, 1.f / (1 << g2.Tex5Frac),
- g2.Tex6CoordElements, g2.Tex6CoordFormat, g2.Tex6Frac,
- 1.f / (1 << g2.Tex6Frac), g2.Tex7CoordElements, g2.Tex7CoordFormat,
- g2.Tex7Frac, 1.f / (1 << g2.Tex7Frac));
- }
- };
- struct VAT
- {
- UVAT_group0 g0;
- UVAT_group1 g1;
- UVAT_group2 g2;
- constexpr ColorComponentCount GetColorElements(size_t idx) const
- {
- switch (idx)
- {
- case 0:
- return g0.Color0Elements;
- case 1:
- return g0.Color1Elements;
- default:
- PanicAlertFmt("Invalid color index {}", idx);
- return ColorComponentCount::RGB;
- }
- }
- constexpr ColorFormat GetColorFormat(size_t idx) const
- {
- switch (idx)
- {
- case 0:
- return g0.Color0Comp;
- case 1:
- return g0.Color1Comp;
- default:
- PanicAlertFmt("Invalid color index {}", idx);
- return ColorFormat::RGB565;
- }
- }
- constexpr TexComponentCount GetTexElements(size_t idx) const
- {
- switch (idx)
- {
- case 0:
- return g0.Tex0CoordElements;
- case 1:
- return g1.Tex1CoordElements;
- case 2:
- return g1.Tex2CoordElements;
- case 3:
- return g1.Tex3CoordElements;
- case 4:
- return g1.Tex4CoordElements;
- case 5:
- return g2.Tex5CoordElements;
- case 6:
- return g2.Tex6CoordElements;
- case 7:
- return g2.Tex7CoordElements;
- default:
- PanicAlertFmt("Invalid tex coord index {}", idx);
- return TexComponentCount::S;
- }
- }
- constexpr ComponentFormat GetTexFormat(size_t idx) const
- {
- switch (idx)
- {
- case 0:
- return g0.Tex0CoordFormat;
- case 1:
- return g1.Tex1CoordFormat;
- case 2:
- return g1.Tex2CoordFormat;
- case 3:
- return g1.Tex3CoordFormat;
- case 4:
- return g1.Tex4CoordFormat;
- case 5:
- return g2.Tex5CoordFormat;
- case 6:
- return g2.Tex6CoordFormat;
- case 7:
- return g2.Tex7CoordFormat;
- default:
- PanicAlertFmt("Invalid tex coord index {}", idx);
- return ComponentFormat::UByte;
- }
- }
- constexpr u8 GetTexFrac(size_t idx) const
- {
- switch (idx)
- {
- case 0:
- return g0.Tex0Frac;
- case 1:
- return g1.Tex1Frac;
- case 2:
- return g1.Tex2Frac;
- case 3:
- return g1.Tex3Frac;
- case 4:
- return g2.Tex4Frac;
- case 5:
- return g2.Tex5Frac;
- case 6:
- return g2.Tex6Frac;
- case 7:
- return g2.Tex7Frac;
- default:
- PanicAlertFmt("Invalid tex coord index {}", idx);
- return 0;
- }
- }
- void SetTexElements(size_t idx, TexComponentCount value)
- {
- switch (idx)
- {
- case 0:
- g0.Tex0CoordElements = value;
- return;
- case 1:
- g1.Tex1CoordElements = value;
- return;
- case 2:
- g1.Tex2CoordElements = value;
- return;
- case 3:
- g1.Tex3CoordElements = value;
- return;
- case 4:
- g1.Tex4CoordElements = value;
- return;
- case 5:
- g2.Tex5CoordElements = value;
- return;
- case 6:
- g2.Tex6CoordElements = value;
- return;
- case 7:
- g2.Tex7CoordElements = value;
- return;
- default:
- PanicAlertFmt("Invalid tex coord index {}", idx);
- }
- }
- void SetTexFormat(size_t idx, ComponentFormat value)
- {
- switch (idx)
- {
- case 0:
- g0.Tex0CoordFormat = value;
- return;
- case 1:
- g1.Tex1CoordFormat = value;
- return;
- case 2:
- g1.Tex2CoordFormat = value;
- return;
- case 3:
- g1.Tex3CoordFormat = value;
- return;
- case 4:
- g1.Tex4CoordFormat = value;
- return;
- case 5:
- g2.Tex5CoordFormat = value;
- return;
- case 6:
- g2.Tex6CoordFormat = value;
- return;
- case 7:
- g2.Tex7CoordFormat = value;
- return;
- default:
- PanicAlertFmt("Invalid tex coord index {}", idx);
- }
- }
- void SetTexFrac(size_t idx, u8 value)
- {
- switch (idx)
- {
- case 0:
- g0.Tex0Frac = value;
- return;
- case 1:
- g1.Tex1Frac = value;
- return;
- case 2:
- g1.Tex2Frac = value;
- return;
- case 3:
- g1.Tex3Frac = value;
- return;
- case 4:
- g2.Tex4Frac = value;
- return;
- case 5:
- g2.Tex5Frac = value;
- return;
- case 6:
- g2.Tex6Frac = value;
- return;
- case 7:
- g2.Tex7Frac = value;
- return;
- default:
- PanicAlertFmt("Invalid tex coord index {}", idx);
- }
- }
- };
- template <>
- struct fmt::formatter<VAT>
- {
- constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
- template <typename FormatContext>
- auto format(const VAT& vat, FormatContext& ctx) const
- {
- return fmt::format_to(ctx.out(), "{}\n{}\n{}", vat.g0, vat.g1, vat.g2);
- }
- };
- // Matrix indices
- union TMatrixIndexA
- {
- BitField<0, 6, u32> PosNormalMtxIdx;
- BitField<6, 6, u32> Tex0MtxIdx;
- BitField<12, 6, u32> Tex1MtxIdx;
- BitField<18, 6, u32> Tex2MtxIdx;
- BitField<24, 6, u32> Tex3MtxIdx;
- u32 Hex;
- };
- template <>
- struct fmt::formatter<TMatrixIndexA>
- {
- constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
- template <typename FormatContext>
- auto format(const TMatrixIndexA& m, FormatContext& ctx) const
- {
- return fmt::format_to(ctx.out(), "PosNormal: {}\nTex0: {}\nTex1: {}\nTex2: {}\nTex3: {}",
- m.PosNormalMtxIdx, m.Tex0MtxIdx, m.Tex1MtxIdx, m.Tex2MtxIdx,
- m.Tex3MtxIdx);
- }
- };
- union TMatrixIndexB
- {
- BitField<0, 6, u32> Tex4MtxIdx;
- BitField<6, 6, u32> Tex5MtxIdx;
- BitField<12, 6, u32> Tex6MtxIdx;
- BitField<18, 6, u32> Tex7MtxIdx;
- u32 Hex;
- };
- template <>
- struct fmt::formatter<TMatrixIndexB>
- {
- constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
- template <typename FormatContext>
- auto format(const TMatrixIndexB& m, FormatContext& ctx) const
- {
- return fmt::format_to(ctx.out(), "Tex4: {}\nTex5: {}\nTex6: {}\nTex7: {}", m.Tex4MtxIdx,
- m.Tex5MtxIdx, m.Tex6MtxIdx, m.Tex7MtxIdx);
- }
- };
- class VertexLoaderBase;
- // STATE_TO_SAVE
- struct CPState final
- {
- CPState() = default;
- explicit CPState(const u32* memory);
- // Mutates the CP state based on the given command and value.
- void LoadCPReg(u8 sub_cmd, u32 value);
- // Fills memory with data from CP regs. There should be space for 0x100 values in memory.
- void FillCPMemoryArray(u32* memory) const;
- Common::EnumMap<u32, CPArray::XF_D> array_bases;
- Common::EnumMap<u32, CPArray::XF_D> array_strides;
- TMatrixIndexA matrix_index_a{};
- TMatrixIndexB matrix_index_b{};
- TVtxDesc vtx_desc;
- // Most games only use the first VtxAttr and simply reconfigure it all the time as needed.
- std::array<VAT, CP_NUM_VAT_REG> vtx_attr{};
- };
- static_assert(std::is_trivially_copyable_v<CPState>);
- class PointerWrap;
- extern CPState g_main_cp_state;
- extern CPState g_preprocess_cp_state;
- void CopyPreprocessCPStateFromMain();
- std::pair<std::string, std::string> GetCPRegInfo(u8 cmd, u32 value);
|