CPMemory.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. // Copyright 2008 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <array>
  5. #include <string>
  6. #include <type_traits>
  7. #include <utility>
  8. #include "Common/BitField.h"
  9. #include "Common/BitSet.h"
  10. #include "Common/CommonTypes.h"
  11. #include "Common/EnumFormatter.h"
  12. #include "Common/EnumMap.h"
  13. #include "Common/MsgHandler.h"
  14. enum
  15. {
  16. // These commands use the high nybble for the command itself, and the lower nybble is an argument.
  17. // TODO: However, Dolphin's implementation (in LoadCPReg) and YAGCD disagree about what values are
  18. // valid for the lower nybble.
  19. // YAGCD mentions 0x20 as "?", and does not mention the others
  20. // Libogc has 0x00 and 0x20, where 0x00 is tied to GX_ClearVCacheMetric and 0x20 related to
  21. // cpPerfMode. 0x10 may be GX_SetVCacheMetric, but that function is empty. In any case, these all
  22. // are probably for perf queries, and no title seems to actually need a full implementation.
  23. UNKNOWN_00 = 0x00,
  24. UNKNOWN_10 = 0x10,
  25. UNKNOWN_20 = 0x20,
  26. // YAGCD says 0x30 only; LoadCPReg allows any
  27. MATINDEX_A = 0x30,
  28. // YAGCD says 0x40 only; LoadCPReg allows any
  29. MATINDEX_B = 0x40,
  30. // YAGCD says 0x50-0x57 for distinct VCDs; LoadCPReg allows any for a single VCD
  31. VCD_LO = 0x50,
  32. // YAGCD says 0x60-0x67 for distinct VCDs; LoadCPReg allows any for a single VCD
  33. VCD_HI = 0x60,
  34. // YAGCD and LoadCPReg both agree that only 0x70-0x77 are valid
  35. CP_VAT_REG_A = 0x70,
  36. // YAGCD and LoadCPReg both agree that only 0x80-0x87 are valid
  37. CP_VAT_REG_B = 0x80,
  38. // YAGCD and LoadCPReg both agree that only 0x90-0x97 are valid
  39. CP_VAT_REG_C = 0x90,
  40. // YAGCD and LoadCPReg agree that 0xa0-0xaf are valid
  41. ARRAY_BASE = 0xa0,
  42. // YAGCD and LoadCPReg agree that 0xb0-0xbf are valid
  43. ARRAY_STRIDE = 0xb0,
  44. CP_COMMAND_MASK = 0xf0,
  45. CP_NUM_VAT_REG = 0x08,
  46. CP_VAT_MASK = 0x07,
  47. CP_NUM_ARRAYS = 0x10,
  48. CP_ARRAY_MASK = 0x0f,
  49. };
  50. // Vertex array numbers
  51. enum class CPArray : u8
  52. {
  53. Position = 0,
  54. Normal = 1,
  55. Color0 = 2,
  56. Color1 = 3,
  57. TexCoord0 = 4,
  58. TexCoord1 = 5,
  59. TexCoord2 = 6,
  60. TexCoord3 = 7,
  61. TexCoord4 = 8,
  62. TexCoord5 = 9,
  63. TexCoord6 = 10,
  64. TexCoord7 = 11,
  65. XF_A = 12, // Usually used for position matrices
  66. XF_B = 13, // Usually used for normal matrices
  67. XF_C = 14, // Usually used for tex coord matrices
  68. XF_D = 15, // Usually used for light objects
  69. };
  70. template <>
  71. struct fmt::formatter<CPArray> : EnumFormatter<CPArray::XF_D>
  72. {
  73. static constexpr array_type names = {"Position", "Normal", "Color 0", "Color 1",
  74. "Tex Coord 0", "Tex Coord 1", "Tex Coord 2", "Tex Coord 3",
  75. "Tex Coord 4", "Tex Coord 5", "Tex Coord 6", "Tex Coord 7",
  76. "XF A", "XF B", "XF C", "XF D"};
  77. constexpr formatter() : EnumFormatter(names) {}
  78. };
  79. // Intended for offsetting from Color0/TexCoord0
  80. constexpr CPArray operator+(CPArray array, u8 offset)
  81. {
  82. return static_cast<CPArray>(static_cast<u8>(array) + offset);
  83. }
  84. // Number of arrays related to vertex components (position, normal, color, tex coord)
  85. // Excludes the 4 arrays used for indexed XF loads
  86. constexpr u8 NUM_VERTEX_COMPONENT_ARRAYS = 12;
  87. // Vertex components
  88. enum class VertexComponentFormat
  89. {
  90. NotPresent = 0,
  91. Direct = 1,
  92. Index8 = 2,
  93. Index16 = 3,
  94. };
  95. template <>
  96. struct fmt::formatter<VertexComponentFormat> : EnumFormatter<VertexComponentFormat::Index16>
  97. {
  98. constexpr formatter() : EnumFormatter({"Not present", "Direct", "8-bit index", "16-bit index"}) {}
  99. };
  100. constexpr bool IsIndexed(VertexComponentFormat format)
  101. {
  102. return format == VertexComponentFormat::Index8 || format == VertexComponentFormat::Index16;
  103. }
  104. enum class ComponentFormat
  105. {
  106. UByte = 0, // Invalid for normals
  107. Byte = 1,
  108. UShort = 2, // Invalid for normals
  109. Short = 3,
  110. Float = 4,
  111. // Known to be used by Fifa Street and Def Jam: Fight for New York
  112. // See https://bugs.dolphin-emu.org/issues/12719
  113. // Assumed to behave the same as float, but further testing is needed
  114. InvalidFloat5 = 5,
  115. // Not known to be used
  116. InvalidFloat6 = 6,
  117. InvalidFloat7 = 7,
  118. };
  119. // NOTE: don't include the invalid formats here, so that EnumFormatter marks them as invalid
  120. // (EnumFormatter also handles bounds-checking).
  121. template <>
  122. struct fmt::formatter<ComponentFormat> : EnumFormatter<ComponentFormat::Float>
  123. {
  124. static constexpr array_type names = {"Unsigned Byte", "Byte", "Unsigned Short", "Short", "Float"};
  125. constexpr formatter() : EnumFormatter(names) {}
  126. };
  127. constexpr u32 GetElementSize(ComponentFormat format)
  128. {
  129. switch (format)
  130. {
  131. case ComponentFormat::UByte:
  132. case ComponentFormat::Byte:
  133. return 1;
  134. case ComponentFormat::UShort:
  135. case ComponentFormat::Short:
  136. return 2;
  137. case ComponentFormat::Float:
  138. case ComponentFormat::InvalidFloat5:
  139. case ComponentFormat::InvalidFloat6:
  140. case ComponentFormat::InvalidFloat7:
  141. return 4;
  142. default:
  143. PanicAlertFmt("Unknown format {}", format);
  144. return 0;
  145. }
  146. }
  147. enum class CoordComponentCount
  148. {
  149. XY = 0,
  150. XYZ = 1,
  151. };
  152. template <>
  153. struct fmt::formatter<CoordComponentCount> : EnumFormatter<CoordComponentCount::XYZ>
  154. {
  155. constexpr formatter() : EnumFormatter({"2 (x, y)", "3 (x, y, z)"}) {}
  156. };
  157. enum class NormalComponentCount
  158. {
  159. N = 0,
  160. NTB = 1,
  161. };
  162. template <>
  163. struct fmt::formatter<NormalComponentCount> : EnumFormatter<NormalComponentCount::NTB>
  164. {
  165. constexpr formatter() : EnumFormatter({"1 (normal)", "3 (normal, tangent, binormal)"}) {}
  166. };
  167. enum class ColorComponentCount
  168. {
  169. RGB = 0,
  170. RGBA = 1,
  171. };
  172. template <>
  173. struct fmt::formatter<ColorComponentCount> : EnumFormatter<ColorComponentCount::RGBA>
  174. {
  175. constexpr formatter() : EnumFormatter({"3 (r, g, b)", "4 (r, g, b, a)"}) {}
  176. };
  177. enum class ColorFormat
  178. {
  179. RGB565 = 0, // 16b
  180. RGB888 = 1, // 24b
  181. RGB888x = 2, // 32b
  182. RGBA4444 = 3, // 16b
  183. RGBA6666 = 4, // 24b
  184. RGBA8888 = 5, // 32b
  185. };
  186. template <>
  187. struct fmt::formatter<ColorFormat> : EnumFormatter<ColorFormat::RGBA8888>
  188. {
  189. static constexpr array_type names = {
  190. "RGB 16 bits 565", "RGB 24 bits 888", "RGB 32 bits 888x",
  191. "RGBA 16 bits 4444", "RGBA 24 bits 6666", "RGBA 32 bits 8888",
  192. };
  193. constexpr formatter() : EnumFormatter(names) {}
  194. };
  195. enum class TexComponentCount
  196. {
  197. S = 0,
  198. ST = 1,
  199. };
  200. template <>
  201. struct fmt::formatter<TexComponentCount> : EnumFormatter<TexComponentCount::ST>
  202. {
  203. constexpr formatter() : EnumFormatter({"1 (s)", "2 (s, t)"}) {}
  204. };
  205. struct TVtxDesc
  206. {
  207. union Low
  208. {
  209. // false: not present
  210. // true: present
  211. BitField<0, 1, bool, u32> PosMatIdx;
  212. BitField<1, 1, bool, u32> Tex0MatIdx;
  213. BitField<2, 1, bool, u32> Tex1MatIdx;
  214. BitField<3, 1, bool, u32> Tex2MatIdx;
  215. BitField<4, 1, bool, u32> Tex3MatIdx;
  216. BitField<5, 1, bool, u32> Tex4MatIdx;
  217. BitField<6, 1, bool, u32> Tex5MatIdx;
  218. BitField<7, 1, bool, u32> Tex6MatIdx;
  219. BitField<8, 1, bool, u32> Tex7MatIdx;
  220. BitFieldArray<1, 1, 8, bool, u32> TexMatIdx;
  221. BitField<9, 2, VertexComponentFormat> Position;
  222. BitField<11, 2, VertexComponentFormat> Normal;
  223. BitField<13, 2, VertexComponentFormat> Color0;
  224. BitField<15, 2, VertexComponentFormat> Color1;
  225. BitFieldArray<13, 2, 2, VertexComponentFormat> Color;
  226. u32 Hex = 0;
  227. };
  228. union High
  229. {
  230. BitField<0, 2, VertexComponentFormat> Tex0Coord;
  231. BitField<2, 2, VertexComponentFormat> Tex1Coord;
  232. BitField<4, 2, VertexComponentFormat> Tex2Coord;
  233. BitField<6, 2, VertexComponentFormat> Tex3Coord;
  234. BitField<8, 2, VertexComponentFormat> Tex4Coord;
  235. BitField<10, 2, VertexComponentFormat> Tex5Coord;
  236. BitField<12, 2, VertexComponentFormat> Tex6Coord;
  237. BitField<14, 2, VertexComponentFormat> Tex7Coord;
  238. BitFieldArray<0, 2, 8, VertexComponentFormat> TexCoord;
  239. u32 Hex = 0;
  240. };
  241. Low low;
  242. High high;
  243. };
  244. template <>
  245. struct fmt::formatter<TVtxDesc::Low>
  246. {
  247. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  248. template <typename FormatContext>
  249. auto format(const TVtxDesc::Low& desc, FormatContext& ctx) const
  250. {
  251. static constexpr std::array<const char*, 2> present = {"Not present", "Present"};
  252. return fmt::format_to(
  253. ctx.out(),
  254. "Position and normal matrix index: {}\n"
  255. "Texture Coord 0 matrix index: {}\n"
  256. "Texture Coord 1 matrix index: {}\n"
  257. "Texture Coord 2 matrix index: {}\n"
  258. "Texture Coord 3 matrix index: {}\n"
  259. "Texture Coord 4 matrix index: {}\n"
  260. "Texture Coord 5 matrix index: {}\n"
  261. "Texture Coord 6 matrix index: {}\n"
  262. "Texture Coord 7 matrix index: {}\n"
  263. "Position: {}\n"
  264. "Normal: {}\n"
  265. "Color 0: {}\n"
  266. "Color 1: {}",
  267. present[desc.PosMatIdx], present[desc.Tex0MatIdx], present[desc.Tex1MatIdx],
  268. present[desc.Tex2MatIdx], present[desc.Tex3MatIdx], present[desc.Tex4MatIdx],
  269. present[desc.Tex5MatIdx], present[desc.Tex6MatIdx], present[desc.Tex7MatIdx], desc.Position,
  270. desc.Normal, desc.Color0, desc.Color1);
  271. }
  272. };
  273. template <>
  274. struct fmt::formatter<TVtxDesc::High>
  275. {
  276. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  277. template <typename FormatContext>
  278. auto format(const TVtxDesc::High& desc, FormatContext& ctx) const
  279. {
  280. return fmt::format_to(ctx.out(),
  281. "Texture Coord 0: {}\n"
  282. "Texture Coord 1: {}\n"
  283. "Texture Coord 2: {}\n"
  284. "Texture Coord 3: {}\n"
  285. "Texture Coord 4: {}\n"
  286. "Texture Coord 5: {}\n"
  287. "Texture Coord 6: {}\n"
  288. "Texture Coord 7: {}",
  289. desc.Tex0Coord, desc.Tex1Coord, desc.Tex2Coord, desc.Tex3Coord,
  290. desc.Tex4Coord, desc.Tex5Coord, desc.Tex6Coord, desc.Tex7Coord);
  291. }
  292. };
  293. template <>
  294. struct fmt::formatter<TVtxDesc>
  295. {
  296. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  297. template <typename FormatContext>
  298. auto format(const TVtxDesc& desc, FormatContext& ctx) const
  299. {
  300. return fmt::format_to(ctx.out(), "{}\n{}", desc.low, desc.high);
  301. }
  302. };
  303. union UVAT_group0
  304. {
  305. u32 Hex = 0;
  306. // 0:8
  307. BitField<0, 1, CoordComponentCount> PosElements;
  308. BitField<1, 3, ComponentFormat> PosFormat;
  309. BitField<4, 5, u32> PosFrac;
  310. // 9:12
  311. BitField<9, 1, NormalComponentCount> NormalElements;
  312. BitField<10, 3, ComponentFormat> NormalFormat;
  313. // 13:16
  314. BitField<13, 1, ColorComponentCount> Color0Elements;
  315. BitField<14, 3, ColorFormat> Color0Comp;
  316. // 17:20
  317. BitField<17, 1, ColorComponentCount> Color1Elements;
  318. BitField<18, 3, ColorFormat> Color1Comp;
  319. // 21:29
  320. BitField<21, 1, TexComponentCount> Tex0CoordElements;
  321. BitField<22, 3, ComponentFormat> Tex0CoordFormat;
  322. BitField<25, 5, u8, u32> Tex0Frac;
  323. // 30:31
  324. BitField<30, 1, bool, u32> ByteDequant;
  325. BitField<31, 1, bool, u32> NormalIndex3;
  326. };
  327. template <>
  328. struct fmt::formatter<UVAT_group0>
  329. {
  330. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  331. template <typename FormatContext>
  332. auto format(const UVAT_group0& g0, FormatContext& ctx) const
  333. {
  334. static constexpr std::array<const char*, 2> byte_dequant = {
  335. "shift does not apply to u8/s8 components", "shift applies to u8/s8 components"};
  336. static constexpr std::array<const char*, 2> normalindex3 = {
  337. "single index shared by normal, tangent, and binormal",
  338. "three indices, one each for normal, tangent, and binormal"};
  339. return fmt::format_to(ctx.out(),
  340. "Position elements: {}\n"
  341. "Position format: {}\n"
  342. "Position shift: {} ({})\n"
  343. "Normal elements: {}\n"
  344. "Normal format: {}\n"
  345. "Color 0 elements: {}\n"
  346. "Color 0 format: {}\n"
  347. "Color 1 elements: {}\n"
  348. "Color 1 format: {}\n"
  349. "Texture coord 0 elements: {}\n"
  350. "Texture coord 0 format: {}\n"
  351. "Texture coord 0 shift: {} ({})\n"
  352. "Byte dequant: {}\n"
  353. "Normal index 3: {}",
  354. g0.PosElements, g0.PosFormat, g0.PosFrac, 1.f / (1 << g0.PosFrac),
  355. g0.NormalElements, g0.NormalFormat, g0.Color0Elements, g0.Color0Comp,
  356. g0.Color1Elements, g0.Color1Comp, g0.Tex0CoordElements,
  357. g0.Tex0CoordFormat, g0.Tex0Frac, 1.f / (1 << g0.Tex0Frac),
  358. byte_dequant[g0.ByteDequant], normalindex3[g0.NormalIndex3]);
  359. }
  360. };
  361. union UVAT_group1
  362. {
  363. u32 Hex = 0;
  364. // 0:8
  365. BitField<0, 1, TexComponentCount> Tex1CoordElements;
  366. BitField<1, 3, ComponentFormat> Tex1CoordFormat;
  367. BitField<4, 5, u8, u32> Tex1Frac;
  368. // 9:17
  369. BitField<9, 1, TexComponentCount> Tex2CoordElements;
  370. BitField<10, 3, ComponentFormat> Tex2CoordFormat;
  371. BitField<13, 5, u8, u32> Tex2Frac;
  372. // 18:26
  373. BitField<18, 1, TexComponentCount> Tex3CoordElements;
  374. BitField<19, 3, ComponentFormat> Tex3CoordFormat;
  375. BitField<22, 5, u8, u32> Tex3Frac;
  376. // 27:30
  377. BitField<27, 1, TexComponentCount> Tex4CoordElements;
  378. BitField<28, 3, ComponentFormat> Tex4CoordFormat;
  379. // 31
  380. BitField<31, 1, bool, u32> VCacheEnhance;
  381. };
  382. template <>
  383. struct fmt::formatter<UVAT_group1>
  384. {
  385. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  386. template <typename FormatContext>
  387. auto format(const UVAT_group1& g1, FormatContext& ctx) const
  388. {
  389. return fmt::format_to(
  390. ctx.out(),
  391. "Texture coord 1 elements: {}\n"
  392. "Texture coord 1 format: {}\n"
  393. "Texture coord 1 shift: {} ({})\n"
  394. "Texture coord 2 elements: {}\n"
  395. "Texture coord 2 format: {}\n"
  396. "Texture coord 2 shift: {} ({})\n"
  397. "Texture coord 3 elements: {}\n"
  398. "Texture coord 3 format: {}\n"
  399. "Texture coord 3 shift: {} ({})\n"
  400. "Texture coord 4 elements: {}\n"
  401. "Texture coord 4 format: {}\n"
  402. "Enhance VCache (must always be on): {}",
  403. g1.Tex1CoordElements, g1.Tex1CoordFormat, g1.Tex1Frac, 1.f / (1 << g1.Tex1Frac),
  404. g1.Tex2CoordElements, g1.Tex2CoordFormat, g1.Tex2Frac, 1.f / (1 << g1.Tex2Frac),
  405. g1.Tex3CoordElements, g1.Tex3CoordFormat, g1.Tex3Frac, 1.f / (1 << g1.Tex3Frac),
  406. g1.Tex4CoordElements, g1.Tex4CoordFormat, g1.VCacheEnhance ? "Yes" : "No");
  407. }
  408. };
  409. union UVAT_group2
  410. {
  411. u32 Hex = 0;
  412. // 0:4
  413. BitField<0, 5, u8, u32> Tex4Frac;
  414. // 5:13
  415. BitField<5, 1, TexComponentCount> Tex5CoordElements;
  416. BitField<6, 3, ComponentFormat> Tex5CoordFormat;
  417. BitField<9, 5, u8, u32> Tex5Frac;
  418. // 14:22
  419. BitField<14, 1, TexComponentCount> Tex6CoordElements;
  420. BitField<15, 3, ComponentFormat> Tex6CoordFormat;
  421. BitField<18, 5, u8, u32> Tex6Frac;
  422. // 23:31
  423. BitField<23, 1, TexComponentCount> Tex7CoordElements;
  424. BitField<24, 3, ComponentFormat> Tex7CoordFormat;
  425. BitField<27, 5, u8, u32> Tex7Frac;
  426. };
  427. template <>
  428. struct fmt::formatter<UVAT_group2>
  429. {
  430. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  431. template <typename FormatContext>
  432. auto format(const UVAT_group2& g2, FormatContext& ctx) const
  433. {
  434. return fmt::format_to(ctx.out(),
  435. "Texture coord 4 shift: {} ({})\n"
  436. "Texture coord 5 elements: {}\n"
  437. "Texture coord 5 format: {}\n"
  438. "Texture coord 5 shift: {} ({})\n"
  439. "Texture coord 6 elements: {}\n"
  440. "Texture coord 6 format: {}\n"
  441. "Texture coord 6 shift: {} ({})\n"
  442. "Texture coord 7 elements: {}\n"
  443. "Texture coord 7 format: {}\n"
  444. "Texture coord 7 shift: {} ({})",
  445. g2.Tex4Frac, 1.f / (1 << g2.Tex4Frac), g2.Tex5CoordElements,
  446. g2.Tex5CoordFormat, g2.Tex5Frac, 1.f / (1 << g2.Tex5Frac),
  447. g2.Tex6CoordElements, g2.Tex6CoordFormat, g2.Tex6Frac,
  448. 1.f / (1 << g2.Tex6Frac), g2.Tex7CoordElements, g2.Tex7CoordFormat,
  449. g2.Tex7Frac, 1.f / (1 << g2.Tex7Frac));
  450. }
  451. };
  452. struct VAT
  453. {
  454. UVAT_group0 g0;
  455. UVAT_group1 g1;
  456. UVAT_group2 g2;
  457. constexpr ColorComponentCount GetColorElements(size_t idx) const
  458. {
  459. switch (idx)
  460. {
  461. case 0:
  462. return g0.Color0Elements;
  463. case 1:
  464. return g0.Color1Elements;
  465. default:
  466. PanicAlertFmt("Invalid color index {}", idx);
  467. return ColorComponentCount::RGB;
  468. }
  469. }
  470. constexpr ColorFormat GetColorFormat(size_t idx) const
  471. {
  472. switch (idx)
  473. {
  474. case 0:
  475. return g0.Color0Comp;
  476. case 1:
  477. return g0.Color1Comp;
  478. default:
  479. PanicAlertFmt("Invalid color index {}", idx);
  480. return ColorFormat::RGB565;
  481. }
  482. }
  483. constexpr TexComponentCount GetTexElements(size_t idx) const
  484. {
  485. switch (idx)
  486. {
  487. case 0:
  488. return g0.Tex0CoordElements;
  489. case 1:
  490. return g1.Tex1CoordElements;
  491. case 2:
  492. return g1.Tex2CoordElements;
  493. case 3:
  494. return g1.Tex3CoordElements;
  495. case 4:
  496. return g1.Tex4CoordElements;
  497. case 5:
  498. return g2.Tex5CoordElements;
  499. case 6:
  500. return g2.Tex6CoordElements;
  501. case 7:
  502. return g2.Tex7CoordElements;
  503. default:
  504. PanicAlertFmt("Invalid tex coord index {}", idx);
  505. return TexComponentCount::S;
  506. }
  507. }
  508. constexpr ComponentFormat GetTexFormat(size_t idx) const
  509. {
  510. switch (idx)
  511. {
  512. case 0:
  513. return g0.Tex0CoordFormat;
  514. case 1:
  515. return g1.Tex1CoordFormat;
  516. case 2:
  517. return g1.Tex2CoordFormat;
  518. case 3:
  519. return g1.Tex3CoordFormat;
  520. case 4:
  521. return g1.Tex4CoordFormat;
  522. case 5:
  523. return g2.Tex5CoordFormat;
  524. case 6:
  525. return g2.Tex6CoordFormat;
  526. case 7:
  527. return g2.Tex7CoordFormat;
  528. default:
  529. PanicAlertFmt("Invalid tex coord index {}", idx);
  530. return ComponentFormat::UByte;
  531. }
  532. }
  533. constexpr u8 GetTexFrac(size_t idx) const
  534. {
  535. switch (idx)
  536. {
  537. case 0:
  538. return g0.Tex0Frac;
  539. case 1:
  540. return g1.Tex1Frac;
  541. case 2:
  542. return g1.Tex2Frac;
  543. case 3:
  544. return g1.Tex3Frac;
  545. case 4:
  546. return g2.Tex4Frac;
  547. case 5:
  548. return g2.Tex5Frac;
  549. case 6:
  550. return g2.Tex6Frac;
  551. case 7:
  552. return g2.Tex7Frac;
  553. default:
  554. PanicAlertFmt("Invalid tex coord index {}", idx);
  555. return 0;
  556. }
  557. }
  558. void SetTexElements(size_t idx, TexComponentCount value)
  559. {
  560. switch (idx)
  561. {
  562. case 0:
  563. g0.Tex0CoordElements = value;
  564. return;
  565. case 1:
  566. g1.Tex1CoordElements = value;
  567. return;
  568. case 2:
  569. g1.Tex2CoordElements = value;
  570. return;
  571. case 3:
  572. g1.Tex3CoordElements = value;
  573. return;
  574. case 4:
  575. g1.Tex4CoordElements = value;
  576. return;
  577. case 5:
  578. g2.Tex5CoordElements = value;
  579. return;
  580. case 6:
  581. g2.Tex6CoordElements = value;
  582. return;
  583. case 7:
  584. g2.Tex7CoordElements = value;
  585. return;
  586. default:
  587. PanicAlertFmt("Invalid tex coord index {}", idx);
  588. }
  589. }
  590. void SetTexFormat(size_t idx, ComponentFormat value)
  591. {
  592. switch (idx)
  593. {
  594. case 0:
  595. g0.Tex0CoordFormat = value;
  596. return;
  597. case 1:
  598. g1.Tex1CoordFormat = value;
  599. return;
  600. case 2:
  601. g1.Tex2CoordFormat = value;
  602. return;
  603. case 3:
  604. g1.Tex3CoordFormat = value;
  605. return;
  606. case 4:
  607. g1.Tex4CoordFormat = value;
  608. return;
  609. case 5:
  610. g2.Tex5CoordFormat = value;
  611. return;
  612. case 6:
  613. g2.Tex6CoordFormat = value;
  614. return;
  615. case 7:
  616. g2.Tex7CoordFormat = value;
  617. return;
  618. default:
  619. PanicAlertFmt("Invalid tex coord index {}", idx);
  620. }
  621. }
  622. void SetTexFrac(size_t idx, u8 value)
  623. {
  624. switch (idx)
  625. {
  626. case 0:
  627. g0.Tex0Frac = value;
  628. return;
  629. case 1:
  630. g1.Tex1Frac = value;
  631. return;
  632. case 2:
  633. g1.Tex2Frac = value;
  634. return;
  635. case 3:
  636. g1.Tex3Frac = value;
  637. return;
  638. case 4:
  639. g2.Tex4Frac = value;
  640. return;
  641. case 5:
  642. g2.Tex5Frac = value;
  643. return;
  644. case 6:
  645. g2.Tex6Frac = value;
  646. return;
  647. case 7:
  648. g2.Tex7Frac = value;
  649. return;
  650. default:
  651. PanicAlertFmt("Invalid tex coord index {}", idx);
  652. }
  653. }
  654. };
  655. template <>
  656. struct fmt::formatter<VAT>
  657. {
  658. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  659. template <typename FormatContext>
  660. auto format(const VAT& vat, FormatContext& ctx) const
  661. {
  662. return fmt::format_to(ctx.out(), "{}\n{}\n{}", vat.g0, vat.g1, vat.g2);
  663. }
  664. };
  665. // Matrix indices
  666. union TMatrixIndexA
  667. {
  668. BitField<0, 6, u32> PosNormalMtxIdx;
  669. BitField<6, 6, u32> Tex0MtxIdx;
  670. BitField<12, 6, u32> Tex1MtxIdx;
  671. BitField<18, 6, u32> Tex2MtxIdx;
  672. BitField<24, 6, u32> Tex3MtxIdx;
  673. u32 Hex;
  674. };
  675. template <>
  676. struct fmt::formatter<TMatrixIndexA>
  677. {
  678. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  679. template <typename FormatContext>
  680. auto format(const TMatrixIndexA& m, FormatContext& ctx) const
  681. {
  682. return fmt::format_to(ctx.out(), "PosNormal: {}\nTex0: {}\nTex1: {}\nTex2: {}\nTex3: {}",
  683. m.PosNormalMtxIdx, m.Tex0MtxIdx, m.Tex1MtxIdx, m.Tex2MtxIdx,
  684. m.Tex3MtxIdx);
  685. }
  686. };
  687. union TMatrixIndexB
  688. {
  689. BitField<0, 6, u32> Tex4MtxIdx;
  690. BitField<6, 6, u32> Tex5MtxIdx;
  691. BitField<12, 6, u32> Tex6MtxIdx;
  692. BitField<18, 6, u32> Tex7MtxIdx;
  693. u32 Hex;
  694. };
  695. template <>
  696. struct fmt::formatter<TMatrixIndexB>
  697. {
  698. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  699. template <typename FormatContext>
  700. auto format(const TMatrixIndexB& m, FormatContext& ctx) const
  701. {
  702. return fmt::format_to(ctx.out(), "Tex4: {}\nTex5: {}\nTex6: {}\nTex7: {}", m.Tex4MtxIdx,
  703. m.Tex5MtxIdx, m.Tex6MtxIdx, m.Tex7MtxIdx);
  704. }
  705. };
  706. class VertexLoaderBase;
  707. // STATE_TO_SAVE
  708. struct CPState final
  709. {
  710. CPState() = default;
  711. explicit CPState(const u32* memory);
  712. // Mutates the CP state based on the given command and value.
  713. void LoadCPReg(u8 sub_cmd, u32 value);
  714. // Fills memory with data from CP regs. There should be space for 0x100 values in memory.
  715. void FillCPMemoryArray(u32* memory) const;
  716. Common::EnumMap<u32, CPArray::XF_D> array_bases;
  717. Common::EnumMap<u32, CPArray::XF_D> array_strides;
  718. TMatrixIndexA matrix_index_a{};
  719. TMatrixIndexB matrix_index_b{};
  720. TVtxDesc vtx_desc;
  721. // Most games only use the first VtxAttr and simply reconfigure it all the time as needed.
  722. std::array<VAT, CP_NUM_VAT_REG> vtx_attr{};
  723. };
  724. static_assert(std::is_trivially_copyable_v<CPState>);
  725. class PointerWrap;
  726. extern CPState g_main_cp_state;
  727. extern CPState g_preprocess_cp_state;
  728. void CopyPreprocessCPStateFromMain();
  729. std::pair<std::string, std::string> GetCPRegInfo(u8 cmd, u32 value);