XFMemory.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. // Copyright 2008 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. // X.h defines None to be 0, which causes problems with some of the enums
  5. #undef None
  6. #include <array>
  7. #include "Common/BitField.h"
  8. #include "Common/CommonTypes.h"
  9. #include "Common/EnumFormatter.h"
  10. #include "VideoCommon/CPMemory.h"
  11. constexpr size_t NUM_XF_COLOR_CHANNELS = 2;
  12. // Lighting
  13. // Projection
  14. enum class TexSize : u32
  15. {
  16. ST = 0,
  17. STQ = 1
  18. };
  19. template <>
  20. struct fmt::formatter<TexSize> : EnumFormatter<TexSize::STQ>
  21. {
  22. constexpr formatter() : EnumFormatter({"ST (2x4 matrix)", "STQ (3x4 matrix)"}) {}
  23. };
  24. // Input form
  25. enum class TexInputForm : u32
  26. {
  27. AB11 = 0,
  28. ABC1 = 1
  29. };
  30. template <>
  31. struct fmt::formatter<TexInputForm> : EnumFormatter<TexInputForm::ABC1>
  32. {
  33. constexpr formatter() : EnumFormatter({"AB11", "ABC1"}) {}
  34. };
  35. enum class NormalCount : u32
  36. {
  37. None = 0,
  38. Normal = 1,
  39. NormalTangentBinormal = 2,
  40. // Hardware testing indicates that this beahves the same as NormalTangentBinormal.
  41. // Call of Duty: Black Ops uses this in some cases; see https://bugs.dolphin-emu.org/issues/13070
  42. Invalid = 3,
  43. };
  44. template <>
  45. struct fmt::formatter<NormalCount> : EnumFormatter<NormalCount::Invalid>
  46. {
  47. static constexpr array_type names = {
  48. "None",
  49. "Normal only",
  50. "Normal, tangent, and binormal",
  51. "Invalid (Normal, tangent, and binormal)",
  52. };
  53. constexpr formatter() : EnumFormatter(names) {}
  54. };
  55. // Texture generation type
  56. enum class TexGenType : u32
  57. {
  58. Regular = 0,
  59. EmbossMap = 1, // Used when bump mapping
  60. Color0 = 2,
  61. Color1 = 3
  62. };
  63. template <>
  64. struct fmt::formatter<TexGenType> : EnumFormatter<TexGenType::Color1>
  65. {
  66. static constexpr array_type names = {
  67. "Regular",
  68. "Emboss map (used when bump mapping)",
  69. "Color channel 0",
  70. "Color channel 1",
  71. };
  72. constexpr formatter() : EnumFormatter(names) {}
  73. };
  74. // Source row
  75. enum class SourceRow : u32
  76. {
  77. Geom = 0, // Input is abc
  78. Normal = 1, // Input is abc
  79. Colors = 2,
  80. BinormalT = 3, // Input is abc
  81. BinormalB = 4, // Input is abc
  82. Tex0 = 5,
  83. Tex1 = 6,
  84. Tex2 = 7,
  85. Tex3 = 8,
  86. Tex4 = 9,
  87. Tex5 = 10,
  88. Tex6 = 11,
  89. Tex7 = 12
  90. };
  91. template <>
  92. struct fmt::formatter<SourceRow> : EnumFormatter<SourceRow::Tex7>
  93. {
  94. static constexpr array_type names = {
  95. "Geometry (input is ABC1)",
  96. "Normal (input is ABC1)",
  97. "Colors",
  98. "Binormal T (input is ABC1)",
  99. "Binormal B (input is ABC1)",
  100. "Tex 0",
  101. "Tex 1",
  102. "Tex 2",
  103. "Tex 3",
  104. "Tex 4",
  105. "Tex 5",
  106. "Tex 6",
  107. "Tex 7",
  108. };
  109. constexpr formatter() : EnumFormatter(names) {}
  110. };
  111. enum class MatSource : u32
  112. {
  113. MatColorRegister = 0,
  114. Vertex = 1,
  115. };
  116. template <>
  117. struct fmt::formatter<MatSource> : EnumFormatter<MatSource::Vertex>
  118. {
  119. constexpr formatter() : EnumFormatter({"Material color register", "Vertex color"}) {}
  120. };
  121. enum class AmbSource : u32
  122. {
  123. AmbColorRegister = 0,
  124. Vertex = 1,
  125. };
  126. template <>
  127. struct fmt::formatter<AmbSource> : EnumFormatter<AmbSource::Vertex>
  128. {
  129. constexpr formatter() : EnumFormatter({"Ambient color register", "Vertex color"}) {}
  130. };
  131. // Light diffuse attenuation function
  132. enum class DiffuseFunc : u32
  133. {
  134. None = 0,
  135. Sign = 1,
  136. Clamp = 2
  137. };
  138. template <>
  139. struct fmt::formatter<DiffuseFunc> : EnumFormatter<DiffuseFunc::Clamp>
  140. {
  141. constexpr formatter() : EnumFormatter({"None", "Sign", "Clamp"}) {}
  142. };
  143. // Light attenuation function
  144. enum class AttenuationFunc : u32
  145. {
  146. None = 0, // No attenuation
  147. Spec = 1, // Point light attenuation
  148. Dir = 2, // Directional light attenuation
  149. Spot = 3 // Spot light attenuation
  150. };
  151. template <>
  152. struct fmt::formatter<AttenuationFunc> : EnumFormatter<AttenuationFunc::Spot>
  153. {
  154. static constexpr array_type names = {
  155. "No attenuation",
  156. "Point light attenuation",
  157. "Directional light attenuation",
  158. "Spot light attenuation",
  159. };
  160. constexpr formatter() : EnumFormatter(names) {}
  161. };
  162. // Projection type
  163. enum class ProjectionType : u32
  164. {
  165. Perspective = 0,
  166. Orthographic = 1
  167. };
  168. template <>
  169. struct fmt::formatter<ProjectionType> : EnumFormatter<ProjectionType::Orthographic>
  170. {
  171. constexpr formatter() : EnumFormatter({"Perspective", "Orthographic"}) {}
  172. };
  173. // Registers and register ranges
  174. enum
  175. {
  176. XFMEM_POSMATRICES = 0x000,
  177. XFMEM_POSMATRICES_END = 0x100,
  178. XFMEM_NORMALMATRICES = 0x400,
  179. XFMEM_NORMALMATRICES_END = 0x460,
  180. XFMEM_POSTMATRICES = 0x500,
  181. XFMEM_POSTMATRICES_END = 0x600,
  182. XFMEM_LIGHTS = 0x600,
  183. XFMEM_LIGHTS_END = 0x680,
  184. XFMEM_REGISTERS_START = 0x1000,
  185. XFMEM_ERROR = 0x1000,
  186. XFMEM_DIAG = 0x1001,
  187. XFMEM_STATE0 = 0x1002,
  188. XFMEM_STATE1 = 0x1003,
  189. XFMEM_CLOCK = 0x1004,
  190. XFMEM_CLIPDISABLE = 0x1005,
  191. XFMEM_SETGPMETRIC = 0x1006, // Perf0 according to YAGCD
  192. XFMEM_UNKNOWN_1007 = 0x1007, // Perf1 according to YAGCD
  193. XFMEM_VTXSPECS = 0x1008,
  194. XFMEM_SETNUMCHAN = 0x1009,
  195. XFMEM_SETCHAN0_AMBCOLOR = 0x100a,
  196. XFMEM_SETCHAN1_AMBCOLOR = 0x100b,
  197. XFMEM_SETCHAN0_MATCOLOR = 0x100c,
  198. XFMEM_SETCHAN1_MATCOLOR = 0x100d,
  199. XFMEM_SETCHAN0_COLOR = 0x100e,
  200. XFMEM_SETCHAN1_COLOR = 0x100f,
  201. XFMEM_SETCHAN0_ALPHA = 0x1010,
  202. XFMEM_SETCHAN1_ALPHA = 0x1011,
  203. XFMEM_DUALTEX = 0x1012,
  204. XFMEM_UNKNOWN_GROUP_1_START = 0x1013,
  205. XFMEM_UNKNOWN_GROUP_1_END = 0x1017,
  206. XFMEM_SETMATRIXINDA = 0x1018,
  207. XFMEM_SETMATRIXINDB = 0x1019,
  208. XFMEM_SETVIEWPORT = 0x101a,
  209. XFMEM_SETZSCALE = 0x101c,
  210. XFMEM_SETZOFFSET = 0x101f,
  211. XFMEM_SETPROJECTION = 0x1020,
  212. // XFMEM_SETPROJECTIONB = 0x1021,
  213. // XFMEM_SETPROJECTIONC = 0x1022,
  214. // XFMEM_SETPROJECTIOND = 0x1023,
  215. // XFMEM_SETPROJECTIONE = 0x1024,
  216. // XFMEM_SETPROJECTIONF = 0x1025,
  217. // XFMEM_SETPROJECTIONORTHO = 0x1026,
  218. XFMEM_UNKNOWN_GROUP_2_START = 0x1027,
  219. XFMEM_UNKNOWN_GROUP_2_END = 0x103e,
  220. XFMEM_SETNUMTEXGENS = 0x103f,
  221. XFMEM_SETTEXMTXINFO = 0x1040,
  222. XFMEM_UNKNOWN_GROUP_3_START = 0x1048,
  223. XFMEM_UNKNOWN_GROUP_3_END = 0x104f,
  224. XFMEM_SETPOSTMTXINFO = 0x1050,
  225. XFMEM_REGISTERS_END = 0x1058,
  226. };
  227. union LitChannel
  228. {
  229. BitField<0, 1, MatSource> matsource;
  230. BitField<1, 1, bool, u32> enablelighting;
  231. BitField<2, 4, u32> lightMask0_3;
  232. BitField<6, 1, AmbSource> ambsource;
  233. BitField<7, 2, DiffuseFunc> diffusefunc;
  234. BitField<9, 2, AttenuationFunc> attnfunc;
  235. BitField<11, 4, u32> lightMask4_7;
  236. u32 hex;
  237. unsigned int GetFullLightMask() const
  238. {
  239. return enablelighting ? (lightMask0_3 | (lightMask4_7 << 4)) : 0;
  240. }
  241. };
  242. template <>
  243. struct fmt::formatter<LitChannel>
  244. {
  245. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  246. template <typename FormatContext>
  247. auto format(const LitChannel& chan, FormatContext& ctx) const
  248. {
  249. return fmt::format_to(
  250. ctx.out(),
  251. "Material source: {0}\nEnable lighting: {1}\nLight mask: {2:x} ({2:08b})\n"
  252. "Ambient source: {3}\nDiffuse function: {4}\nAttenuation function: {5}",
  253. chan.matsource, chan.enablelighting ? "Yes" : "No", chan.GetFullLightMask(), chan.ambsource,
  254. chan.diffusefunc, chan.attnfunc);
  255. }
  256. };
  257. union ClipDisable
  258. {
  259. BitField<0, 1, bool, u32> disable_clipping_detection;
  260. BitField<1, 1, bool, u32> disable_trivial_rejection;
  261. BitField<2, 1, bool, u32> disable_cpoly_clipping_acceleration;
  262. u32 hex;
  263. };
  264. template <>
  265. struct fmt::formatter<ClipDisable>
  266. {
  267. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  268. template <typename FormatContext>
  269. auto format(const ClipDisable& cd, FormatContext& ctx) const
  270. {
  271. return fmt::format_to(ctx.out(),
  272. "Disable clipping detection: {}\n"
  273. "Disable trivial rejection: {}\n"
  274. "Disable cpoly clipping acceleration: {}",
  275. cd.disable_clipping_detection ? "Yes" : "No",
  276. cd.disable_trivial_rejection ? "Yes" : "No",
  277. cd.disable_cpoly_clipping_acceleration ? "Yes" : "No");
  278. }
  279. };
  280. union INVTXSPEC
  281. {
  282. BitField<0, 2, u32> numcolors;
  283. BitField<2, 2, NormalCount> numnormals;
  284. BitField<4, 4, u32> numtextures;
  285. u32 hex;
  286. };
  287. template <>
  288. struct fmt::formatter<INVTXSPEC>
  289. {
  290. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  291. template <typename FormatContext>
  292. auto format(const INVTXSPEC& spec, FormatContext& ctx) const
  293. {
  294. return fmt::format_to(ctx.out(), "Num colors: {}\nNum normals: {}\nNum textures: {}",
  295. spec.numcolors, spec.numnormals, spec.numtextures);
  296. }
  297. };
  298. union TexMtxInfo
  299. {
  300. BitField<0, 1, u32> unknown;
  301. BitField<1, 1, TexSize> projection;
  302. BitField<2, 1, TexInputForm> inputform;
  303. BitField<3, 1, u32> unknown2;
  304. BitField<4, 3, TexGenType> texgentype;
  305. BitField<7, 5, SourceRow> sourcerow;
  306. BitField<12, 3, u32> embosssourceshift; // what generated texcoord to use
  307. BitField<15, 3, u32> embosslightshift; // light index that is used
  308. u32 hex;
  309. };
  310. template <>
  311. struct fmt::formatter<TexMtxInfo>
  312. {
  313. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  314. template <typename FormatContext>
  315. auto format(const TexMtxInfo& i, FormatContext& ctx) const
  316. {
  317. return fmt::format_to(ctx.out(),
  318. "Projection: {}\nInput form: {}\nTex gen type: {}\n"
  319. "Source row: {}\nEmboss source shift: {}\nEmboss light shift: {}",
  320. i.projection, i.inputform, i.texgentype, i.sourcerow, i.embosssourceshift,
  321. i.embosslightshift);
  322. }
  323. };
  324. union PostMtxInfo
  325. {
  326. BitField<0, 6, u32> index; // base row of dual transform matrix
  327. BitField<6, 2, u32> unused; //
  328. BitField<8, 1, bool, u32> normalize; // normalize before send operation
  329. u32 hex;
  330. };
  331. template <>
  332. struct fmt::formatter<PostMtxInfo>
  333. {
  334. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  335. template <typename FormatContext>
  336. auto format(const PostMtxInfo& i, FormatContext& ctx) const
  337. {
  338. return fmt::format_to(ctx.out(), "Index: {}\nNormalize before send operation: {}", i.index,
  339. i.normalize ? "Yes" : "No");
  340. }
  341. };
  342. union NumColorChannel
  343. {
  344. BitField<0, 2, u32> numColorChans;
  345. u32 hex;
  346. };
  347. union NumTexGen
  348. {
  349. BitField<0, 4, u32> numTexGens;
  350. u32 hex;
  351. };
  352. union DualTexInfo
  353. {
  354. BitField<0, 1, bool, u32> enabled;
  355. u32 hex;
  356. };
  357. struct Light
  358. {
  359. u32 useless[3];
  360. u8 color[4];
  361. float cosatt[3]; // cos attenuation
  362. float distatt[3]; // dist attenuation
  363. union
  364. {
  365. struct
  366. {
  367. float dpos[3];
  368. float ddir[3]; // specular lights only
  369. };
  370. struct
  371. {
  372. float sdir[3];
  373. float shalfangle[3]; // specular lights only
  374. };
  375. };
  376. };
  377. struct Viewport
  378. {
  379. float wd;
  380. float ht;
  381. float zRange;
  382. float xOrig;
  383. float yOrig;
  384. float farZ;
  385. };
  386. struct Projection
  387. {
  388. using Raw = std::array<float, 6>;
  389. Raw rawProjection;
  390. ProjectionType type;
  391. };
  392. struct alignas(16) XFMemory
  393. {
  394. float posMatrices[256]; // 0x0000 - 0x00ff
  395. u32 unk0[768]; // 0x0100 - 0x03ff
  396. float normalMatrices[96]; // 0x0400 - 0x045f
  397. u32 unk1[160]; // 0x0460 - 0x04ff
  398. float postMatrices[256]; // 0x0500 - 0x05ff
  399. Light lights[8]; // 0x0600 - 0x067f
  400. u32 unk2[2432]; // 0x0680 - 0x0fff
  401. u32 error; // 0x1000
  402. u32 diag; // 0x1001
  403. u32 state0; // 0x1002
  404. u32 state1; // 0x1003
  405. u32 xfClock; // 0x1004
  406. ClipDisable clipDisable; // 0x1005
  407. u32 perf0; // 0x1006
  408. u32 perf1; // 0x1007
  409. INVTXSPEC invtxspec; // 0x1008
  410. NumColorChannel numChan; // 0x1009
  411. u32 ambColor[NUM_XF_COLOR_CHANNELS]; // 0x100a, 0x100b
  412. u32 matColor[NUM_XF_COLOR_CHANNELS]; // 0x100c, 0x100d
  413. LitChannel color[NUM_XF_COLOR_CHANNELS]; // 0x100e, 0x100f
  414. LitChannel alpha[NUM_XF_COLOR_CHANNELS]; // 0x1010, 0x1011
  415. DualTexInfo dualTexTrans; // 0x1012
  416. u32 unk3; // 0x1013
  417. u32 unk4; // 0x1014
  418. u32 unk5; // 0x1015
  419. u32 unk6; // 0x1016
  420. u32 unk7; // 0x1017
  421. TMatrixIndexA MatrixIndexA; // 0x1018
  422. TMatrixIndexB MatrixIndexB; // 0x1019
  423. Viewport viewport; // 0x101a - 0x101f
  424. Projection projection; // 0x1020 - 0x1026
  425. u32 unk8[24]; // 0x1027 - 0x103e
  426. NumTexGen numTexGen; // 0x103f
  427. TexMtxInfo texMtxInfo[8]; // 0x1040 - 0x1047
  428. u32 unk9[8]; // 0x1048 - 0x104f
  429. PostMtxInfo postMtxInfo[8]; // 0x1050 - 0x1057
  430. };
  431. static_assert(sizeof(XFMemory) == sizeof(u32) * XFMEM_REGISTERS_END);
  432. extern XFMemory xfmem;
  433. void LoadXFReg(u16 base_address, u8 transfer_size, const u8* data);
  434. void LoadIndexedXF(CPArray array, u32 index, u16 address, u8 size);
  435. void PreprocessIndexedXF(CPArray array, u32 index, u16 address, u8 size);