BPMemory.h 73 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539
  1. // Copyright 2009 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <array>
  5. #include <string>
  6. #include <utility>
  7. #include "Common/BitField.h"
  8. #include "Common/BitUtils.h"
  9. #include "Common/CommonTypes.h"
  10. #include "Common/EnumFormatter.h"
  11. #include "Common/EnumMap.h"
  12. #include "Common/Inline.h"
  13. // X.h defines None to be 0 and Always to be 2, which causes problems with some of the enums
  14. #undef None
  15. #undef Always
  16. enum class TextureFormat;
  17. enum class EFBCopyFormat;
  18. enum class TLUTFormat;
  19. #pragma pack(4)
  20. enum
  21. {
  22. BPMEM_GENMODE = 0x00,
  23. BPMEM_DISPLAYCOPYFILTER = 0x01, // 0x01 + 4
  24. BPMEM_IND_MTXA = 0x06, // 0x06 + (3 * 3)
  25. BPMEM_IND_MTXB = 0x07, // 0x07 + (3 * 3)
  26. BPMEM_IND_MTXC = 0x08, // 0x08 + (3 * 3)
  27. BPMEM_IND_IMASK = 0x0F,
  28. BPMEM_IND_CMD = 0x10, // 0x10 + 16
  29. BPMEM_SCISSORTL = 0x20,
  30. BPMEM_SCISSORBR = 0x21,
  31. BPMEM_LINEPTWIDTH = 0x22,
  32. BPMEM_PERF0_TRI = 0x23,
  33. BPMEM_PERF0_QUAD = 0x24,
  34. BPMEM_RAS1_SS0 = 0x25,
  35. BPMEM_RAS1_SS1 = 0x26,
  36. BPMEM_IREF = 0x27,
  37. BPMEM_TREF = 0x28, // 0x28 + 8
  38. BPMEM_SU_SSIZE = 0x30, // 0x30 + (2 * 8)
  39. BPMEM_SU_TSIZE = 0x31, // 0x31 + (2 * 8)
  40. BPMEM_ZMODE = 0x40,
  41. BPMEM_BLENDMODE = 0x41,
  42. BPMEM_CONSTANTALPHA = 0x42,
  43. BPMEM_ZCOMPARE = 0x43,
  44. BPMEM_FIELDMASK = 0x44,
  45. BPMEM_SETDRAWDONE = 0x45,
  46. BPMEM_BUSCLOCK0 = 0x46,
  47. BPMEM_PE_TOKEN_ID = 0x47,
  48. BPMEM_PE_TOKEN_INT_ID = 0x48,
  49. BPMEM_EFB_TL = 0x49,
  50. BPMEM_EFB_WH = 0x4A,
  51. BPMEM_EFB_ADDR = 0x4B,
  52. BPMEM_EFB_STRIDE = 0x4D,
  53. BPMEM_COPYYSCALE = 0x4E,
  54. BPMEM_CLEAR_AR = 0x4F,
  55. BPMEM_CLEAR_GB = 0x50,
  56. BPMEM_CLEAR_Z = 0x51,
  57. BPMEM_TRIGGER_EFB_COPY = 0x52,
  58. BPMEM_COPYFILTER0 = 0x53,
  59. BPMEM_COPYFILTER1 = 0x54,
  60. BPMEM_CLEARBBOX1 = 0x55,
  61. BPMEM_CLEARBBOX2 = 0x56,
  62. BPMEM_CLEAR_PIXEL_PERF = 0x57,
  63. BPMEM_REVBITS = 0x58,
  64. BPMEM_SCISSOROFFSET = 0x59,
  65. BPMEM_PRELOAD_ADDR = 0x60,
  66. BPMEM_PRELOAD_TMEMEVEN = 0x61,
  67. BPMEM_PRELOAD_TMEMODD = 0x62,
  68. BPMEM_PRELOAD_MODE = 0x63,
  69. BPMEM_LOADTLUT0 = 0x64,
  70. BPMEM_LOADTLUT1 = 0x65,
  71. BPMEM_TEXINVALIDATE = 0x66,
  72. BPMEM_PERF1 = 0x67,
  73. BPMEM_FIELDMODE = 0x68,
  74. BPMEM_BUSCLOCK1 = 0x69,
  75. BPMEM_TX_SETMODE0 = 0x80, // 0x80 + 4
  76. BPMEM_TX_SETMODE1 = 0x84, // 0x84 + 4
  77. BPMEM_TX_SETIMAGE0 = 0x88, // 0x88 + 4
  78. BPMEM_TX_SETIMAGE1 = 0x8C, // 0x8C + 4
  79. BPMEM_TX_SETIMAGE2 = 0x90, // 0x90 + 4
  80. BPMEM_TX_SETIMAGE3 = 0x94, // 0x94 + 4
  81. BPMEM_TX_SETTLUT = 0x98, // 0x98 + 4
  82. BPMEM_TX_SETMODE0_4 = 0xA0, // 0xA0 + 4
  83. BPMEM_TX_SETMODE1_4 = 0xA4, // 0xA4 + 4
  84. BPMEM_TX_SETIMAGE0_4 = 0xA8, // 0xA8 + 4
  85. BPMEM_TX_SETIMAGE1_4 = 0xAC, // 0xA4 + 4
  86. BPMEM_TX_SETIMAGE2_4 = 0xB0, // 0xB0 + 4
  87. BPMEM_TX_SETIMAGE3_4 = 0xB4, // 0xB4 + 4
  88. BPMEM_TX_SETTLUT_4 = 0xB8, // 0xB8 + 4
  89. BPMEM_TEV_COLOR_ENV = 0xC0, // 0xC0 + (2 * 16)
  90. BPMEM_TEV_ALPHA_ENV = 0xC1, // 0xC1 + (2 * 16)
  91. BPMEM_TEV_COLOR_RA = 0xE0, // 0xE0 + (2 * 4)
  92. BPMEM_TEV_COLOR_BG = 0xE1, // 0xE1 + (2 * 4)
  93. BPMEM_FOGRANGE = 0xE8, // 0xE8 + 6
  94. BPMEM_FOGPARAM0 = 0xEE,
  95. BPMEM_FOGBMAGNITUDE = 0xEF,
  96. BPMEM_FOGBEXPONENT = 0xF0,
  97. BPMEM_FOGPARAM3 = 0xF1,
  98. BPMEM_FOGCOLOR = 0xF2,
  99. BPMEM_ALPHACOMPARE = 0xF3,
  100. BPMEM_BIAS = 0xF4,
  101. BPMEM_ZTEX2 = 0xF5,
  102. BPMEM_TEV_KSEL = 0xF6, // 0xF6 + 8
  103. BPMEM_BP_MASK = 0xFE,
  104. };
  105. // Tev/combiner things
  106. // TEV scaling type
  107. enum class TevScale : u32
  108. {
  109. Scale1 = 0,
  110. Scale2 = 1,
  111. Scale4 = 2,
  112. Divide2 = 3
  113. };
  114. template <>
  115. struct fmt::formatter<TevScale> : EnumFormatter<TevScale::Divide2>
  116. {
  117. constexpr formatter() : EnumFormatter({"1", "2", "4", "0.5"}) {}
  118. };
  119. // TEV combiner operator
  120. enum class TevOp : u32
  121. {
  122. Add = 0,
  123. Sub = 1,
  124. };
  125. template <>
  126. struct fmt::formatter<TevOp> : EnumFormatter<TevOp::Sub>
  127. {
  128. constexpr formatter() : EnumFormatter({"Add", "Subtract"}) {}
  129. };
  130. enum class TevCompareMode : u32
  131. {
  132. R8 = 0,
  133. GR16 = 1,
  134. BGR24 = 2,
  135. RGB8 = 3,
  136. A8 = RGB8,
  137. };
  138. template <>
  139. struct fmt::formatter<TevCompareMode> : EnumFormatter<TevCompareMode::RGB8>
  140. {
  141. constexpr formatter() : EnumFormatter({"R8", "GR16", "BGR24", "RGB8 / A8"}) {}
  142. };
  143. enum class TevComparison : u32
  144. {
  145. GT = 0,
  146. EQ = 1,
  147. };
  148. template <>
  149. struct fmt::formatter<TevComparison> : EnumFormatter<TevComparison::EQ>
  150. {
  151. constexpr formatter() : EnumFormatter({"Greater than", "Equal to"}) {}
  152. };
  153. // TEV color combiner input
  154. enum class TevColorArg : u32
  155. {
  156. PrevColor = 0,
  157. PrevAlpha = 1,
  158. Color0 = 2,
  159. Alpha0 = 3,
  160. Color1 = 4,
  161. Alpha1 = 5,
  162. Color2 = 6,
  163. Alpha2 = 7,
  164. TexColor = 8,
  165. TexAlpha = 9,
  166. RasColor = 10,
  167. RasAlpha = 11,
  168. One = 12,
  169. Half = 13,
  170. Konst = 14,
  171. Zero = 15
  172. };
  173. template <>
  174. struct fmt::formatter<TevColorArg> : EnumFormatter<TevColorArg::Zero>
  175. {
  176. static constexpr array_type names = {
  177. "prev.rgb", "prev.aaa", "c0.rgb", "c0.aaa", "c1.rgb", "c1.aaa", "c2.rgb", "c2.aaa",
  178. "tex.rgb", "tex.aaa", "ras.rgb", "ras.aaa", "ONE", "HALF", "konst.rgb", "ZERO",
  179. };
  180. constexpr formatter() : EnumFormatter(names) {}
  181. };
  182. // TEV alpha combiner input
  183. enum class TevAlphaArg : u32
  184. {
  185. PrevAlpha = 0,
  186. Alpha0 = 1,
  187. Alpha1 = 2,
  188. Alpha2 = 3,
  189. TexAlpha = 4,
  190. RasAlpha = 5,
  191. Konst = 6,
  192. Zero = 7
  193. };
  194. template <>
  195. struct fmt::formatter<TevAlphaArg> : EnumFormatter<TevAlphaArg::Zero>
  196. {
  197. static constexpr array_type names = {
  198. "prev", "c0", "c1", "c2", "tex", "ras", "konst", "ZERO",
  199. };
  200. constexpr formatter() : EnumFormatter(names) {}
  201. };
  202. // TEV output registers
  203. enum class TevOutput : u32
  204. {
  205. Prev = 0,
  206. Color0 = 1,
  207. Color1 = 2,
  208. Color2 = 3,
  209. };
  210. template <>
  211. struct fmt::formatter<TevOutput> : EnumFormatter<TevOutput::Color2>
  212. {
  213. constexpr formatter() : EnumFormatter({"prev", "c0", "c1", "c2"}) {}
  214. };
  215. // Z-texture formats
  216. enum class ZTexFormat : u32
  217. {
  218. U8 = 0,
  219. U16 = 1,
  220. U24 = 2
  221. };
  222. template <>
  223. struct fmt::formatter<ZTexFormat> : EnumFormatter<ZTexFormat::U24>
  224. {
  225. constexpr formatter() : EnumFormatter({"u8", "u16", "u24"}) {}
  226. };
  227. // Z texture operator
  228. enum class ZTexOp : u32
  229. {
  230. Disabled = 0,
  231. Add = 1,
  232. Replace = 2
  233. };
  234. template <>
  235. struct fmt::formatter<ZTexOp> : EnumFormatter<ZTexOp::Replace>
  236. {
  237. constexpr formatter() : EnumFormatter({"Disabled", "Add", "Replace"}) {}
  238. };
  239. // TEV bias value
  240. enum class TevBias : u32
  241. {
  242. Zero = 0,
  243. AddHalf = 1,
  244. SubHalf = 2,
  245. Compare = 3
  246. };
  247. template <>
  248. struct fmt::formatter<TevBias> : EnumFormatter<TevBias::Compare>
  249. {
  250. constexpr formatter() : EnumFormatter({"0", "+0.5", "-0.5", "compare"}) {}
  251. };
  252. // Indirect texture format
  253. enum class IndTexFormat : u32
  254. {
  255. ITF_8 = 0,
  256. ITF_5 = 1,
  257. ITF_4 = 2,
  258. ITF_3 = 3
  259. };
  260. template <>
  261. struct fmt::formatter<IndTexFormat> : EnumFormatter<IndTexFormat::ITF_3>
  262. {
  263. constexpr formatter() : EnumFormatter({"ITF_8", "ITF_5", "ITF_4", "ITF_3"}) {}
  264. };
  265. // Indirect texture bias
  266. enum class IndTexBias : u32
  267. {
  268. None = 0,
  269. S = 1,
  270. T = 2,
  271. ST = 3,
  272. U = 4,
  273. SU = 5,
  274. TU_ = 6, // conflicts with define in PowerPC.h
  275. STU = 7
  276. };
  277. template <>
  278. struct fmt::formatter<IndTexBias> : EnumFormatter<IndTexBias::STU>
  279. {
  280. constexpr formatter() : EnumFormatter({"None", "S", "T", "ST", "U", "SU", "TU", "STU"}) {}
  281. };
  282. enum class IndMtxIndex : u32
  283. {
  284. Off = 0,
  285. Matrix0 = 1,
  286. Matrix1 = 2,
  287. Matrix2 = 3,
  288. };
  289. template <>
  290. struct fmt::formatter<IndMtxIndex> : EnumFormatter<IndMtxIndex::Matrix2>
  291. {
  292. constexpr formatter() : EnumFormatter({"Off", "Matrix 0", "Matrix 1", "Matrix 2"}) {}
  293. };
  294. enum class IndMtxId : u32
  295. {
  296. Indirect = 0,
  297. S = 1,
  298. T = 2,
  299. };
  300. template <>
  301. struct fmt::formatter<IndMtxId> : EnumFormatter<IndMtxId::T>
  302. {
  303. constexpr formatter() : EnumFormatter({"Indirect", "S", "T"}) {}
  304. };
  305. // Indirect texture bump alpha
  306. enum class IndTexBumpAlpha : u32
  307. {
  308. Off = 0,
  309. S = 1,
  310. T = 2,
  311. U = 3
  312. };
  313. template <>
  314. struct fmt::formatter<IndTexBumpAlpha> : EnumFormatter<IndTexBumpAlpha::U>
  315. {
  316. constexpr formatter() : EnumFormatter({"Off", "S", "T", "U"}) {}
  317. };
  318. // Indirect texture wrap value
  319. enum class IndTexWrap : u32
  320. {
  321. ITW_OFF = 0,
  322. ITW_256 = 1,
  323. ITW_128 = 2,
  324. ITW_64 = 3,
  325. ITW_32 = 4,
  326. ITW_16 = 5,
  327. ITW_0 = 6
  328. };
  329. template <>
  330. struct fmt::formatter<IndTexWrap> : EnumFormatter<IndTexWrap::ITW_0>
  331. {
  332. constexpr formatter() : EnumFormatter({"Off", "256", "128", "64", "32", "16", "0"}) {}
  333. };
  334. union IND_MTXA
  335. {
  336. BitField<0, 11, s32> ma;
  337. BitField<11, 11, s32> mb;
  338. BitField<22, 2, u8, u32> s0; // bits 0-1 of scale factor
  339. u32 hex;
  340. };
  341. template <>
  342. struct fmt::formatter<IND_MTXA>
  343. {
  344. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  345. template <typename FormatContext>
  346. auto format(const IND_MTXA& col, FormatContext& ctx) const
  347. {
  348. return fmt::format_to(ctx.out(),
  349. "Row 0 (ma): {} ({})\n"
  350. "Row 1 (mb): {} ({})\n"
  351. "Scale bits: {} (shifted: {})",
  352. col.ma / 1024.0f, col.ma, col.mb / 1024.0f, col.mb, col.s0, col.s0);
  353. }
  354. };
  355. union IND_MTXB
  356. {
  357. BitField<0, 11, s32> mc;
  358. BitField<11, 11, s32> md;
  359. BitField<22, 2, u8, u32> s1; // bits 2-3 of scale factor
  360. u32 hex;
  361. };
  362. template <>
  363. struct fmt::formatter<IND_MTXB>
  364. {
  365. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  366. template <typename FormatContext>
  367. auto format(const IND_MTXB& col, FormatContext& ctx) const
  368. {
  369. return fmt::format_to(ctx.out(),
  370. "Row 0 (mc): {} ({})\n"
  371. "Row 1 (md): {} ({})\n"
  372. "Scale bits: {} (shifted: {})",
  373. col.mc / 1024.0f, col.mc, col.md / 1024.0f, col.md, col.s1, col.s1 << 2);
  374. }
  375. };
  376. union IND_MTXC
  377. {
  378. BitField<0, 11, s32> me;
  379. BitField<11, 11, s32> mf;
  380. BitField<22, 1, u8, u32> s2; // bit 4 of scale factor
  381. // The SDK treats the scale factor as 6 bits, 2 on each column; however, hardware seems to ignore
  382. // the top bit.
  383. BitField<22, 2, u8, u32> sdk_s2;
  384. u32 hex;
  385. };
  386. template <>
  387. struct fmt::formatter<IND_MTXC>
  388. {
  389. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  390. template <typename FormatContext>
  391. auto format(const IND_MTXC& col, FormatContext& ctx) const
  392. {
  393. return fmt::format_to(ctx.out(),
  394. "Row 0 (me): {} ({})\n"
  395. "Row 1 (mf): {} ({})\n"
  396. "Scale bits: {} (shifted: {}), given to SDK as {} ({})",
  397. col.me / 1024.0f, col.me, col.mf / 1024.0f, col.mf, col.s2, col.s2 << 4,
  398. col.sdk_s2, col.sdk_s2 << 4);
  399. }
  400. };
  401. struct IND_MTX
  402. {
  403. IND_MTXA col0;
  404. IND_MTXB col1;
  405. IND_MTXC col2;
  406. u8 GetScale() const { return (col0.s0 << 0) | (col1.s1 << 2) | (col2.s2 << 4); }
  407. };
  408. union IND_IMASK
  409. {
  410. BitField<0, 24, u32> mask;
  411. u32 hex;
  412. };
  413. struct TevStageCombiner
  414. {
  415. union ColorCombiner
  416. {
  417. // abc=8bit,d=10bit
  418. BitField<0, 4, TevColorArg> d;
  419. BitField<4, 4, TevColorArg> c;
  420. BitField<8, 4, TevColorArg> b;
  421. BitField<12, 4, TevColorArg> a;
  422. BitField<16, 2, TevBias> bias;
  423. BitField<18, 1, TevOp> op; // Applies when bias is not compare
  424. BitField<18, 1, TevComparison> comparison; // Applies when bias is compare
  425. BitField<19, 1, bool, u32> clamp;
  426. BitField<20, 2, TevScale> scale; // Applies when bias is not compare
  427. BitField<20, 2, TevCompareMode> compare_mode; // Applies when bias is compare
  428. BitField<22, 2, TevOutput> dest;
  429. u32 hex;
  430. };
  431. union AlphaCombiner
  432. {
  433. BitField<0, 2, u32> rswap;
  434. BitField<2, 2, u32> tswap;
  435. BitField<4, 3, TevAlphaArg> d;
  436. BitField<7, 3, TevAlphaArg> c;
  437. BitField<10, 3, TevAlphaArg> b;
  438. BitField<13, 3, TevAlphaArg> a;
  439. BitField<16, 2, TevBias> bias;
  440. BitField<18, 1, TevOp> op; // Applies when bias is not compare
  441. BitField<18, 1, TevComparison> comparison; // Applies when bias is compare
  442. BitField<19, 1, bool, u32> clamp;
  443. BitField<20, 2, TevScale> scale; // Applies when bias is not compare
  444. BitField<20, 2, TevCompareMode> compare_mode; // Applies when bias is compare
  445. BitField<22, 2, TevOutput> dest;
  446. u32 hex;
  447. };
  448. ColorCombiner colorC;
  449. AlphaCombiner alphaC;
  450. };
  451. template <>
  452. struct fmt::formatter<TevStageCombiner::ColorCombiner>
  453. {
  454. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  455. template <typename FormatContext>
  456. auto format(const TevStageCombiner::ColorCombiner& cc, FormatContext& ctx) const
  457. {
  458. auto out = ctx.out();
  459. if (cc.bias != TevBias::Compare)
  460. {
  461. // Generate an equation view, simplifying out addition of zero and multiplication by 1
  462. // dest = (d (OP) ((1 - c)*a + c*b) + bias) * scale
  463. // or equivalently and more readably when the terms are not constants:
  464. // dest = (d (OP) lerp(a, b, c) + bias) * scale
  465. // Note that lerping is more complex than the first form shows; see PixelShaderGen's
  466. // WriteTevRegular for more details.
  467. static constexpr Common::EnumMap<const char*, TevColorArg::Zero> alt_names = {
  468. "prev.rgb", "prev.aaa", "c0.rgb", "c0.aaa", "c1.rgb", "c1.aaa", "c2.rgb", "c2.aaa",
  469. "tex.rgb", "tex.aaa", "ras.rgb", "ras.aaa", "1", ".5", "konst.rgb", "0",
  470. };
  471. const bool has_d = cc.d != TevColorArg::Zero;
  472. // If c is one, (1 - c) is zero, so (1-c)*a is zero
  473. const bool has_ac = cc.a != TevColorArg::Zero && cc.c != TevColorArg::One;
  474. // If either b or c is zero, b*c is zero
  475. const bool has_bc = cc.b != TevColorArg::Zero && cc.c != TevColorArg::Zero;
  476. const bool has_bias = cc.bias != TevBias::Zero; // != Compare is already known
  477. const bool has_scale = cc.scale != TevScale::Scale1;
  478. const char op = (cc.op == TevOp::Sub ? '-' : '+');
  479. if (cc.dest == TevOutput::Prev)
  480. out = fmt::format_to(out, "dest.rgb = ");
  481. else
  482. out = fmt::format_to(out, "{:n}.rgb = ", cc.dest);
  483. if (has_scale)
  484. out = fmt::format_to(out, "(");
  485. if (has_d)
  486. out = fmt::format_to(out, "{}", alt_names[cc.d]);
  487. if (has_ac || has_bc)
  488. {
  489. if (has_d)
  490. out = fmt::format_to(out, " {} ", op);
  491. else if (cc.op == TevOp::Sub)
  492. out = fmt::format_to(out, "{}", op);
  493. if (has_ac && has_bc)
  494. {
  495. if (cc.c == TevColorArg::Half)
  496. {
  497. // has_a and has_b imply that c is not Zero or One, and Half is the only remaining
  498. // numeric constant. This results in an average.
  499. out = fmt::format_to(out, "({} + {})/2", alt_names[cc.a], alt_names[cc.b]);
  500. }
  501. else
  502. {
  503. out = fmt::format_to(out, "lerp({}, {}, {})", alt_names[cc.a], alt_names[cc.b],
  504. alt_names[cc.c]);
  505. }
  506. }
  507. else if (has_ac)
  508. {
  509. if (cc.c == TevColorArg::Zero)
  510. out = fmt::format_to(out, "{}", alt_names[cc.a]);
  511. else if (cc.c == TevColorArg::Half) // 1 - .5 is .5
  512. out = fmt::format_to(out, ".5*{}", alt_names[cc.a]);
  513. else
  514. out = fmt::format_to(out, "(1 - {})*{}", alt_names[cc.c], alt_names[cc.a]);
  515. }
  516. else // has_bc
  517. {
  518. if (cc.c == TevColorArg::One)
  519. out = fmt::format_to(out, "{}", alt_names[cc.b]);
  520. else
  521. out = fmt::format_to(out, "{}*{}", alt_names[cc.c], alt_names[cc.b]);
  522. }
  523. }
  524. if (has_bias)
  525. {
  526. if (has_ac || has_bc || has_d)
  527. out = fmt::format_to(out, "{}", cc.bias == TevBias::AddHalf ? " + .5" : " - .5");
  528. else
  529. out = fmt::format_to(out, "{}", cc.bias == TevBias::AddHalf ? ".5" : "-.5");
  530. }
  531. else
  532. {
  533. // If nothing has been written so far, add a zero
  534. if (!(has_ac || has_bc || has_d))
  535. out = fmt::format_to(out, "0");
  536. }
  537. if (has_scale)
  538. out = fmt::format_to(out, ") * {:n}", cc.scale);
  539. out = fmt::format_to(out, "\n\n");
  540. }
  541. return fmt::format_to(ctx.out(),
  542. "a: {}\n"
  543. "b: {}\n"
  544. "c: {}\n"
  545. "d: {}\n"
  546. "Bias: {}\n"
  547. "Op: {} / Comparison: {}\n"
  548. "Clamp: {}\n"
  549. "Scale factor: {} / Compare mode: {}\n"
  550. "Dest: {}",
  551. cc.a, cc.b, cc.c, cc.d, cc.bias, cc.op, cc.comparison,
  552. cc.clamp ? "Yes" : "No", cc.scale, cc.compare_mode, cc.dest);
  553. }
  554. };
  555. template <>
  556. struct fmt::formatter<TevStageCombiner::AlphaCombiner>
  557. {
  558. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  559. template <typename FormatContext>
  560. auto format(const TevStageCombiner::AlphaCombiner& ac, FormatContext& ctx) const
  561. {
  562. auto out = ctx.out();
  563. if (ac.bias != TevBias::Compare)
  564. {
  565. // Generate an equation view, simplifying out addition of zero and multiplication by 1
  566. // dest = (d (OP) ((1 - c)*a + c*b) + bias) * scale
  567. // or equivalently and more readably when the terms are not constants:
  568. // dest = (d (OP) lerp(a, b, c) + bias) * scale
  569. // Note that lerping is more complex than the first form shows; see PixelShaderGen's
  570. // WriteTevRegular for more details.
  571. // We don't need an alt_names map here, unlike the color combiner, as the only special term is
  572. // Zero, and we we filter that out below. However, we do need to append ".a" to all
  573. // parameters, to make it explicit that these are operations on the alpha term instead of the
  574. // 4-element vector. We also need to use the :n specifier so that the numeric ID isn't shown.
  575. const bool has_d = ac.d != TevAlphaArg::Zero;
  576. // There is no c value for alpha that results in (1 - c) always being zero
  577. const bool has_ac = ac.a != TevAlphaArg::Zero;
  578. // If either b or c is zero, b*c is zero
  579. const bool has_bc = ac.b != TevAlphaArg::Zero && ac.c != TevAlphaArg::Zero;
  580. const bool has_bias = ac.bias != TevBias::Zero; // != Compare is already known
  581. const bool has_scale = ac.scale != TevScale::Scale1;
  582. const char op = (ac.op == TevOp::Sub ? '-' : '+');
  583. if (ac.dest == TevOutput::Prev)
  584. out = fmt::format_to(out, "dest.a = ");
  585. else
  586. out = fmt::format_to(out, "{:n}.a = ", ac.dest);
  587. if (has_scale)
  588. out = fmt::format_to(out, "(");
  589. if (has_d)
  590. out = fmt::format_to(out, "{:n}.a", ac.d);
  591. if (has_ac || has_bc)
  592. {
  593. if (has_d)
  594. out = fmt::format_to(out, " {} ", op);
  595. else if (ac.op == TevOp::Sub)
  596. out = fmt::format_to(out, "{}", op);
  597. if (has_ac && has_bc)
  598. {
  599. out = fmt::format_to(out, "lerp({:n}.a, {:n}.a, {:n}.a)", ac.a, ac.b, ac.c);
  600. }
  601. else if (has_ac)
  602. {
  603. if (ac.c == TevAlphaArg::Zero)
  604. out = fmt::format_to(out, "{:n}.a", ac.a);
  605. else
  606. out = fmt::format_to(out, "(1 - {:n}.a)*{:n}.a", ac.c, ac.a);
  607. }
  608. else // has_bc
  609. {
  610. out = fmt::format_to(out, "{:n}.a*{:n}.a", ac.c, ac.b);
  611. }
  612. }
  613. if (has_bias)
  614. {
  615. if (has_ac || has_bc || has_d)
  616. out = fmt::format_to(out, "{}", ac.bias == TevBias::AddHalf ? " + .5" : " - .5");
  617. else
  618. out = fmt::format_to(out, "{}", ac.bias == TevBias::AddHalf ? ".5" : "-.5");
  619. }
  620. else
  621. {
  622. // If nothing has been written so far, add a zero
  623. if (!(has_ac || has_bc || has_d))
  624. out = fmt::format_to(out, "0");
  625. }
  626. if (has_scale)
  627. out = fmt::format_to(out, ") * {:n}", ac.scale);
  628. out = fmt::format_to(out, "\n\n");
  629. }
  630. return fmt::format_to(out,
  631. "a: {}\n"
  632. "b: {}\n"
  633. "c: {}\n"
  634. "d: {}\n"
  635. "Bias: {}\n"
  636. "Op: {} / Comparison: {}\n"
  637. "Clamp: {}\n"
  638. "Scale factor: {} / Compare mode: {}\n"
  639. "Dest: {}\n"
  640. "Rasterized color swaptable: {}\n"
  641. "Texture color swaptable: {}",
  642. ac.a, ac.b, ac.c, ac.d, ac.bias, ac.op, ac.comparison,
  643. ac.clamp ? "Yes" : "No", ac.scale, ac.compare_mode, ac.dest, ac.rswap,
  644. ac.tswap);
  645. }
  646. };
  647. // several discoveries:
  648. // GXSetTevIndBumpST(tevstage, indstage, matrixind)
  649. // if ( matrix == 2 ) realmat = 6; // 10
  650. // else if ( matrix == 3 ) realmat = 7; // 11
  651. // else if ( matrix == 1 ) realmat = 5; // 9
  652. // GXSetTevIndirect(tevstage, indstage, 0, 3, realmat, 6, 6, 0, 0, 0)
  653. // GXSetTevIndirect(tevstage+1, indstage, 0, 3, realmat+4, 6, 6, 1, 0, 0)
  654. // GXSetTevIndirect(tevstage+2, indstage, 0, 0, 0, 0, 0, 1, 0, 0)
  655. union TevStageIndirect
  656. {
  657. BitField<0, 2, u32> bt; // Indirect tex stage ID
  658. BitField<2, 2, IndTexFormat> fmt;
  659. BitField<4, 3, IndTexBias> bias;
  660. BitField<4, 1, bool, u32> bias_s;
  661. BitField<5, 1, bool, u32> bias_t;
  662. BitField<6, 1, bool, u32> bias_u;
  663. BitField<7, 2, IndTexBumpAlpha> bs; // Indicates which coordinate will become the 'bump alpha'
  664. // Indicates which indirect matrix is used when matrix_id is Indirect.
  665. // Also always indicates which indirect matrix to use for the scale factor, even with S or T.
  666. BitField<9, 2, IndMtxIndex> matrix_index;
  667. // Should be set to Indirect (0) if matrix_index is Off (0)
  668. BitField<11, 2, IndMtxId> matrix_id;
  669. BitField<13, 3, IndTexWrap> sw; // Wrapping factor for S of regular coord
  670. BitField<16, 3, IndTexWrap> tw; // Wrapping factor for T of regular coord
  671. BitField<19, 1, bool, u32> lb_utclod; // Use modified or unmodified texture
  672. // coordinates for LOD computation
  673. BitField<20, 1, bool, u32> fb_addprev; // true if the texture coordinate results from the
  674. // previous TEV stage should be added
  675. struct
  676. {
  677. u32 hex : 21;
  678. u32 unused : 11;
  679. };
  680. u32 fullhex;
  681. // If bs and matrix are zero, the result of the stage is independent of
  682. // the texture sample data, so we can skip sampling the texture.
  683. bool IsActive() const { return bs != IndTexBumpAlpha::Off || matrix_index != IndMtxIndex::Off; }
  684. };
  685. template <>
  686. struct fmt::formatter<TevStageIndirect>
  687. {
  688. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  689. template <typename FormatContext>
  690. auto format(const TevStageIndirect& tevind, FormatContext& ctx) const
  691. {
  692. return fmt::format_to(ctx.out(),
  693. "Indirect tex stage ID: {}\n"
  694. "Format: {}\n"
  695. "Bias: {}\n"
  696. "Bump alpha: {}\n"
  697. "Offset matrix index: {}\n"
  698. "Offset matrix ID: {}\n"
  699. "Regular coord S wrapping factor: {}\n"
  700. "Regular coord T wrapping factor: {}\n"
  701. "Use modified texture coordinates for LOD computation: {}\n"
  702. "Add texture coordinates from previous TEV stage: {}",
  703. tevind.bt, tevind.fmt, tevind.bias, tevind.bs, tevind.matrix_index,
  704. tevind.matrix_id, tevind.sw, tevind.tw, tevind.lb_utclod ? "Yes" : "No",
  705. tevind.fb_addprev ? "Yes" : "No");
  706. }
  707. };
  708. enum class RasColorChan : u32
  709. {
  710. Color0 = 0,
  711. Color1 = 1,
  712. AlphaBump = 5,
  713. NormalizedAlphaBump = 6,
  714. Zero = 7,
  715. };
  716. template <>
  717. struct fmt::formatter<RasColorChan> : EnumFormatter<RasColorChan::Zero>
  718. {
  719. static constexpr array_type names = {
  720. "Color chan 0", "Color chan 1", nullptr, nullptr,
  721. nullptr, "Alpha bump", "Norm alpha bump", "Zero",
  722. };
  723. constexpr formatter() : EnumFormatter(names) {}
  724. };
  725. union TwoTevStageOrders
  726. {
  727. BitField<0, 3, u32> texmap_even;
  728. BitField<3, 3, u32> texcoord_even;
  729. BitField<6, 1, bool, u32> enable_tex_even; // true if should read from texture
  730. BitField<7, 3, RasColorChan> colorchan_even;
  731. BitField<12, 3, u32> texmap_odd;
  732. BitField<15, 3, u32> texcoord_odd;
  733. BitField<18, 1, bool, u32> enable_tex_odd; // true if should read from texture
  734. BitField<19, 3, RasColorChan> colorchan_odd;
  735. u32 hex;
  736. u32 getTexMap(int i) const { return i ? texmap_odd.Value() : texmap_even.Value(); }
  737. u32 getTexCoord(int i) const { return i ? texcoord_odd.Value() : texcoord_even.Value(); }
  738. u32 getEnable(int i) const { return i ? enable_tex_odd.Value() : enable_tex_even.Value(); }
  739. RasColorChan getColorChan(int i) const
  740. {
  741. return i ? colorchan_odd.Value() : colorchan_even.Value();
  742. }
  743. };
  744. template <>
  745. struct fmt::formatter<std::pair<u8, TwoTevStageOrders>>
  746. {
  747. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  748. template <typename FormatContext>
  749. auto format(const std::pair<u8, TwoTevStageOrders>& p, FormatContext& ctx) const
  750. {
  751. const auto& [cmd, stages] = p;
  752. const u8 stage_even = (cmd - BPMEM_TREF) * 2;
  753. const u8 stage_odd = stage_even + 1;
  754. return fmt::format_to(ctx.out(),
  755. "Stage {0} texmap: {1}\nStage {0} tex coord: {2}\n"
  756. "Stage {0} enable texmap: {3}\nStage {0} rasterized color channel: {4}\n"
  757. "Stage {5} texmap: {6}\nStage {5} tex coord: {7}\n"
  758. "Stage {5} enable texmap: {8}\nStage {5} rasterized color channel: {9}\n",
  759. stage_even, stages.texmap_even, stages.texcoord_even,
  760. stages.enable_tex_even ? "Yes" : "No", stages.colorchan_even, stage_odd,
  761. stages.texmap_odd, stages.texcoord_odd,
  762. stages.enable_tex_odd ? "Yes" : "No", stages.colorchan_odd);
  763. }
  764. };
  765. union TEXSCALE
  766. {
  767. BitField<0, 4, u32> ss0; // Indirect tex stage 0 or 2, 2^(-ss0)
  768. BitField<4, 4, u32> ts0; // Indirect tex stage 0 or 2
  769. BitField<8, 4, u32> ss1; // Indirect tex stage 1 or 3
  770. BitField<12, 4, u32> ts1; // Indirect tex stage 1 or 3
  771. u32 hex;
  772. };
  773. template <>
  774. struct fmt::formatter<std::pair<u8, TEXSCALE>>
  775. {
  776. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  777. template <typename FormatContext>
  778. auto format(const std::pair<u8, TEXSCALE>& p, FormatContext& ctx) const
  779. {
  780. const auto& [cmd, scale] = p;
  781. const u8 even = (cmd - BPMEM_RAS1_SS0) * 2;
  782. const u8 odd_ = even + 1;
  783. return fmt::format_to(ctx.out(),
  784. "Indirect stage {0} S coord scale: {1} ({2})\n"
  785. "Indirect stage {0} T coord scale: {3} ({4})\n"
  786. "Indirect stage {5} S coord scale: {6} ({7})\n"
  787. "Indirect stage {5} T coord scale: {8} ({9})",
  788. even, 1.f / (1 << scale.ss0), scale.ss0, 1.f / (1 << scale.ts0),
  789. scale.ts0, odd_, 1.f / (1 << scale.ss1), scale.ss1,
  790. 1.f / (1 << scale.ts1), scale.ts1);
  791. }
  792. };
  793. union RAS1_IREF
  794. {
  795. BitField<0, 3, u32> bi0; // Indirect tex stage 0 texmap
  796. BitField<3, 3, u32> bc0; // Indirect tex stage 0 tex coord
  797. BitField<6, 3, u32> bi1;
  798. BitField<9, 3, u32> bc1;
  799. BitField<12, 3, u32> bi2;
  800. BitField<15, 3, u32> bc2;
  801. BitField<18, 3, u32> bi3;
  802. BitField<21, 3, u32> bc3;
  803. u32 hex;
  804. u32 getTexCoord(int i) const { return (hex >> (6 * i + 3)) & 7; }
  805. u32 getTexMap(int i) const { return (hex >> (6 * i)) & 7; }
  806. };
  807. template <>
  808. struct fmt::formatter<RAS1_IREF>
  809. {
  810. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  811. template <typename FormatContext>
  812. auto format(const RAS1_IREF& indref, FormatContext& ctx) const
  813. {
  814. return fmt::format_to(ctx.out(),
  815. "Indirect stage 0 texmap: {}\nIndirect stage 0 tex coord: {}\n"
  816. "Indirect stage 1 texmap: {}\nIndirect stage 1 tex coord: {}\n"
  817. "Indirect stage 2 texmap: {}\nIndirect stage 2 tex coord: {}\n"
  818. "Indirect stage 3 texmap: {}\nIndirect stage 3 tex coord: {}",
  819. indref.bi0, indref.bc0, indref.bi1, indref.bc1, indref.bi2, indref.bc2,
  820. indref.bi3, indref.bc3);
  821. }
  822. };
  823. // Texture structs
  824. enum class WrapMode : u32
  825. {
  826. Clamp = 0,
  827. Repeat = 1,
  828. Mirror = 2,
  829. // Hardware testing indicates that WrapMode set to 3 behaves the same as clamp, though this is an
  830. // invalid value
  831. };
  832. template <>
  833. struct fmt::formatter<WrapMode> : EnumFormatter<WrapMode::Mirror>
  834. {
  835. constexpr formatter() : EnumFormatter({"Clamp", "Repeat", "Mirror"}) {}
  836. };
  837. enum class MipMode : u32
  838. {
  839. None = 0,
  840. Point = 1,
  841. Linear = 2,
  842. };
  843. template <>
  844. struct fmt::formatter<MipMode> : EnumFormatter<MipMode::Linear>
  845. {
  846. constexpr formatter() : EnumFormatter({"None", "Mip point", "Mip linear"}) {}
  847. };
  848. enum class FilterMode : u32
  849. {
  850. Near = 0,
  851. Linear = 1,
  852. };
  853. template <>
  854. struct fmt::formatter<FilterMode> : EnumFormatter<FilterMode::Linear>
  855. {
  856. constexpr formatter() : EnumFormatter({"Near", "Linear"}) {}
  857. };
  858. enum class LODType : u32
  859. {
  860. Edge = 0,
  861. Diagonal = 1,
  862. };
  863. template <>
  864. struct fmt::formatter<LODType> : EnumFormatter<LODType::Diagonal>
  865. {
  866. constexpr formatter() : EnumFormatter({"Edge LOD", "Diagonal LOD"}) {}
  867. };
  868. enum class MaxAniso
  869. {
  870. One = 0,
  871. Two = 1,
  872. Four = 2,
  873. };
  874. template <>
  875. struct fmt::formatter<MaxAniso> : EnumFormatter<MaxAniso::Four>
  876. {
  877. constexpr formatter() : EnumFormatter({"1", "2", "4"}) {}
  878. };
  879. union TexMode0
  880. {
  881. BitField<0, 2, WrapMode> wrap_s;
  882. BitField<2, 2, WrapMode> wrap_t;
  883. BitField<4, 1, FilterMode> mag_filter;
  884. BitField<5, 2, MipMode> mipmap_filter;
  885. BitField<7, 1, FilterMode> min_filter;
  886. BitField<8, 1, LODType> diag_lod;
  887. BitField<9, 8, s32> lod_bias;
  888. BitField<19, 2, MaxAniso> max_aniso;
  889. BitField<21, 1, bool, u32> lod_clamp;
  890. u32 hex;
  891. };
  892. template <>
  893. struct fmt::formatter<TexMode0>
  894. {
  895. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  896. template <typename FormatContext>
  897. auto format(const TexMode0& mode, FormatContext& ctx) const
  898. {
  899. return fmt::format_to(ctx.out(),
  900. "Wrap S: {}\n"
  901. "Wrap T: {}\n"
  902. "Mag filter: {}\n"
  903. "Mipmap filter: {}\n"
  904. "Min filter: {}\n"
  905. "LOD type: {}\n"
  906. "LOD bias: {} ({})\n"
  907. "Max anisotropic filtering: {}\n"
  908. "LOD/bias clamp: {}",
  909. mode.wrap_s, mode.wrap_t, mode.mag_filter, mode.mipmap_filter,
  910. mode.min_filter, mode.diag_lod, mode.lod_bias, mode.lod_bias / 32.f,
  911. mode.max_aniso, mode.lod_clamp ? "Yes" : "No");
  912. }
  913. };
  914. union TexMode1
  915. {
  916. BitField<0, 8, u32> min_lod;
  917. BitField<8, 8, u32> max_lod;
  918. u32 hex;
  919. };
  920. template <>
  921. struct fmt::formatter<TexMode1>
  922. {
  923. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  924. template <typename FormatContext>
  925. auto format(const TexMode1& mode, FormatContext& ctx) const
  926. {
  927. return fmt::format_to(ctx.out(), "Min LOD: {} ({})\nMax LOD: {} ({})", mode.min_lod,
  928. mode.min_lod / 16.f, mode.max_lod, mode.max_lod / 16.f);
  929. }
  930. };
  931. union TexImage0
  932. {
  933. BitField<0, 10, u32> width; // Actually w-1
  934. BitField<10, 10, u32> height; // Actually h-1
  935. BitField<20, 4, TextureFormat> format;
  936. u32 hex;
  937. };
  938. template <>
  939. struct fmt::formatter<TexImage0>
  940. {
  941. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  942. template <typename FormatContext>
  943. auto format(const TexImage0& teximg, FormatContext& ctx) const
  944. {
  945. return fmt::format_to(ctx.out(),
  946. "Width: {}\n"
  947. "Height: {}\n"
  948. "Format: {}",
  949. teximg.width + 1, teximg.height + 1, teximg.format);
  950. }
  951. };
  952. union TexImage1
  953. {
  954. BitField<0, 15, u32> tmem_even; // TMEM line index for even LODs
  955. BitField<15, 3, u32> cache_width;
  956. BitField<18, 3, u32> cache_height;
  957. // true if this texture is managed manually (false means we'll
  958. // autofetch the texture data whenever it changes)
  959. BitField<21, 1, bool, u32> cache_manually_managed;
  960. u32 hex;
  961. };
  962. template <>
  963. struct fmt::formatter<TexImage1>
  964. {
  965. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  966. template <typename FormatContext>
  967. auto format(const TexImage1& teximg, FormatContext& ctx) const
  968. {
  969. return fmt::format_to(ctx.out(),
  970. "Even TMEM Line: 0x{:04x} (byte 0x{:05x})\n"
  971. "Even TMEM Width: {}\n"
  972. "Even TMEM Height: {}\n"
  973. "Cache is manually managed: {}",
  974. teximg.tmem_even, teximg.tmem_even * 32, teximg.cache_width,
  975. teximg.cache_height, teximg.cache_manually_managed ? "Yes" : "No");
  976. }
  977. };
  978. union TexImage2
  979. {
  980. BitField<0, 15, u32> tmem_odd; // tmem line index for odd LODs
  981. BitField<15, 3, u32> cache_width;
  982. BitField<18, 3, u32> cache_height;
  983. u32 hex;
  984. };
  985. template <>
  986. struct fmt::formatter<TexImage2>
  987. {
  988. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  989. template <typename FormatContext>
  990. auto format(const TexImage2& teximg, FormatContext& ctx) const
  991. {
  992. return fmt::format_to(ctx.out(),
  993. "Odd TMEM Line: 0x{:04x} (byte 0x{:05x})\n"
  994. "Odd TMEM Width: {}\n"
  995. "Odd TMEM Height: {}",
  996. teximg.tmem_odd, teximg.tmem_odd * 32, teximg.cache_width,
  997. teximg.cache_height);
  998. }
  999. };
  1000. union TexImage3
  1001. {
  1002. BitField<0, 24, u32> image_base; // address in memory >> 5 (was 20 for GC)
  1003. u32 hex;
  1004. };
  1005. template <>
  1006. struct fmt::formatter<TexImage3>
  1007. {
  1008. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1009. template <typename FormatContext>
  1010. auto format(const TexImage3& teximg, FormatContext& ctx) const
  1011. {
  1012. return fmt::format_to(ctx.out(), "Source address (32 byte aligned): 0x{:06x}",
  1013. teximg.image_base << 5);
  1014. }
  1015. };
  1016. union TexTLUT
  1017. {
  1018. BitField<0, 10, u32> tmem_offset;
  1019. BitField<10, 2, TLUTFormat> tlut_format;
  1020. u32 hex;
  1021. };
  1022. template <>
  1023. struct fmt::formatter<TexTLUT>
  1024. {
  1025. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1026. template <typename FormatContext>
  1027. auto format(const TexTLUT& tlut, FormatContext& ctx) const
  1028. {
  1029. return fmt::format_to(ctx.out(), "Tmem address: 0x{:05x}\nFormat: {}", tlut.tmem_offset << 9,
  1030. tlut.tlut_format);
  1031. }
  1032. };
  1033. union ZTex1
  1034. {
  1035. BitField<0, 24, u32> bias;
  1036. u32 hex;
  1037. };
  1038. template <>
  1039. struct fmt::formatter<ZTex1>
  1040. {
  1041. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1042. template <typename FormatContext>
  1043. auto format(const ZTex1& ztex1, FormatContext& ctx) const
  1044. {
  1045. return fmt::format_to(ctx.out(), "Bias: 0x{:06x}", ztex1.bias);
  1046. }
  1047. };
  1048. union ZTex2
  1049. {
  1050. BitField<0, 2, ZTexFormat> type;
  1051. BitField<2, 2, ZTexOp> op;
  1052. u32 hex;
  1053. };
  1054. template <>
  1055. struct fmt::formatter<ZTex2>
  1056. {
  1057. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1058. template <typename FormatContext>
  1059. auto format(const ZTex2& ztex2, FormatContext& ctx) const
  1060. {
  1061. return fmt::format_to(ctx.out(), "Type: {}\nOperation: {}", ztex2.type, ztex2.op);
  1062. }
  1063. };
  1064. // Geometry/other structs
  1065. enum class CullMode : u32
  1066. {
  1067. None = 0,
  1068. Back = 1, // cull back-facing primitives
  1069. Front = 2, // cull front-facing primitives
  1070. All = 3, // cull all primitives
  1071. };
  1072. template <>
  1073. struct fmt::formatter<CullMode> : EnumFormatter<CullMode::All>
  1074. {
  1075. static constexpr array_type names = {
  1076. "None",
  1077. "Back-facing primitives only",
  1078. "Front-facing primitives only",
  1079. "All primitives",
  1080. };
  1081. constexpr formatter() : EnumFormatter(names) {}
  1082. };
  1083. union GenMode
  1084. {
  1085. BitField<0, 4, u32> numtexgens;
  1086. BitField<4, 3, u32> numcolchans;
  1087. BitField<7, 1, u32> unused; // 1 bit unused?
  1088. BitField<8, 1, bool, u32> flat_shading; // unconfirmed
  1089. BitField<9, 1, bool, u32> multisampling;
  1090. // This value is 1 less than the actual number (0-15 map to 1-16).
  1091. // In other words there is always at least 1 tev stage
  1092. BitField<10, 4, u32> numtevstages;
  1093. BitField<14, 2, CullMode> cullmode;
  1094. BitField<16, 3, u32> numindstages;
  1095. BitField<19, 1, bool, u32> zfreeze;
  1096. u32 hex;
  1097. };
  1098. template <>
  1099. struct fmt::formatter<GenMode>
  1100. {
  1101. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1102. template <typename FormatContext>
  1103. auto format(const GenMode& mode, FormatContext& ctx) const
  1104. {
  1105. return fmt::format_to(ctx.out(),
  1106. "Num tex gens: {}\n"
  1107. "Num color channels: {}\n"
  1108. "Unused bit: {}\n"
  1109. "Flat shading (unconfirmed): {}\n"
  1110. "Multisampling: {}\n"
  1111. "Num TEV stages: {}\n"
  1112. "Cull mode: {}\n"
  1113. "Num indirect stages: {}\n"
  1114. "ZFreeze: {}",
  1115. mode.numtexgens, mode.numcolchans, mode.unused,
  1116. mode.flat_shading ? "Yes" : "No", mode.multisampling ? "Yes" : "No",
  1117. mode.numtevstages + 1, mode.cullmode, mode.numindstages,
  1118. mode.zfreeze ? "Yes" : "No");
  1119. }
  1120. };
  1121. enum class AspectRatioAdjustment
  1122. {
  1123. DontAdjust = 0,
  1124. Adjust = 1,
  1125. };
  1126. template <>
  1127. struct fmt::formatter<AspectRatioAdjustment> : EnumFormatter<AspectRatioAdjustment::Adjust>
  1128. {
  1129. constexpr formatter() : EnumFormatter({"Don't adjust", "Adjust"}) {}
  1130. };
  1131. union LPSize
  1132. {
  1133. BitField<0, 8, u32> linesize; // in 1/6th pixels
  1134. BitField<8, 8, u32> pointsize; // in 1/6th pixels
  1135. BitField<16, 3, u32> lineoff;
  1136. BitField<19, 3, u32> pointoff;
  1137. // interlacing: adjust for pixels having AR of 1/2
  1138. BitField<22, 1, AspectRatioAdjustment> adjust_for_aspect_ratio;
  1139. u32 hex;
  1140. };
  1141. template <>
  1142. struct fmt::formatter<LPSize>
  1143. {
  1144. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1145. template <typename FormatContext>
  1146. auto format(const LPSize& lp, FormatContext& ctx) const
  1147. {
  1148. return fmt::format_to(ctx.out(),
  1149. "Line size: {} ({:.3} pixels)\n"
  1150. "Point size: {} ({:.3} pixels)\n"
  1151. "Line offset: {}\n"
  1152. "Point offset: {}\n"
  1153. "Adjust line aspect ratio: {}",
  1154. lp.linesize, lp.linesize / 6.f, lp.pointsize, lp.pointsize / 6.f,
  1155. lp.lineoff, lp.pointoff, lp.adjust_for_aspect_ratio);
  1156. }
  1157. };
  1158. union ScissorPos
  1159. {
  1160. // The top bit is ignored, and not included in the mask used by GX SDK functions
  1161. // (though libogc includes it for the bottom coordinate (only) for some reason)
  1162. // x_full and y_full include that bit for the FIFO analyzer, though it is usually unset.
  1163. // The SDK also adds 342 to these values.
  1164. BitField<0, 11, u32> y;
  1165. BitField<0, 12, u32> y_full;
  1166. BitField<12, 11, u32> x;
  1167. BitField<12, 12, u32> x_full;
  1168. u32 hex;
  1169. };
  1170. template <>
  1171. struct fmt::formatter<ScissorPos>
  1172. {
  1173. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1174. template <typename FormatContext>
  1175. auto format(const ScissorPos& pos, FormatContext& ctx)
  1176. {
  1177. return fmt::format_to(ctx.out(),
  1178. "X: {} (raw: {})\n"
  1179. "Y: {} (raw: {})",
  1180. pos.x - 342, pos.x_full, pos.y - 342, pos.y_full);
  1181. }
  1182. };
  1183. union ScissorOffset
  1184. {
  1185. // The scissor offset ignores the top bit (though it isn't masked off by the GX SDK).
  1186. // Each value is also divided by 2 (so 0-511 map to 0-1022).
  1187. // x_full and y_full include that top bit for the FIFO analyzer, though it is usually unset.
  1188. // The SDK also adds 342 to each value (before dividing it).
  1189. BitField<0, 9, u32> x;
  1190. BitField<0, 10, u32> x_full;
  1191. BitField<10, 9, u32> y;
  1192. BitField<10, 10, u32> y_full;
  1193. u32 hex;
  1194. };
  1195. template <>
  1196. struct fmt::formatter<ScissorOffset>
  1197. {
  1198. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1199. template <typename FormatContext>
  1200. auto format(const ScissorOffset& off, FormatContext& ctx)
  1201. {
  1202. return fmt::format_to(ctx.out(),
  1203. "X: {} (raw: {})\n"
  1204. "Y: {} (raw: {})",
  1205. (off.x << 1) - 342, off.x_full, (off.y << 1) - 342, off.y_full);
  1206. }
  1207. };
  1208. union X10Y10
  1209. {
  1210. BitField<0, 10, u32> x;
  1211. BitField<10, 10, u32> y;
  1212. u32 hex;
  1213. };
  1214. // Framebuffer/pixel stuff (incl fog)
  1215. enum class SrcBlendFactor : u32
  1216. {
  1217. Zero = 0,
  1218. One = 1,
  1219. DstClr = 2,
  1220. InvDstClr = 3,
  1221. SrcAlpha = 4,
  1222. InvSrcAlpha = 5,
  1223. DstAlpha = 6,
  1224. InvDstAlpha = 7
  1225. };
  1226. template <>
  1227. struct fmt::formatter<SrcBlendFactor> : EnumFormatter<SrcBlendFactor::InvDstAlpha>
  1228. {
  1229. static constexpr array_type names = {"0", "1", "dst_color", "1-dst_color",
  1230. "src_alpha", "1-src_alpha", "dst_alpha", "1-dst_alpha"};
  1231. constexpr formatter() : EnumFormatter(names) {}
  1232. };
  1233. enum class DstBlendFactor : u32
  1234. {
  1235. Zero = 0,
  1236. One = 1,
  1237. SrcClr = 2,
  1238. InvSrcClr = 3,
  1239. SrcAlpha = 4,
  1240. InvSrcAlpha = 5,
  1241. DstAlpha = 6,
  1242. InvDstAlpha = 7
  1243. };
  1244. template <>
  1245. struct fmt::formatter<DstBlendFactor> : EnumFormatter<DstBlendFactor::InvDstAlpha>
  1246. {
  1247. static constexpr array_type names = {"0", "1", "src_color", "1-src_color",
  1248. "src_alpha", "1-src_alpha", "dst_alpha", "1-dst_alpha"};
  1249. constexpr formatter() : EnumFormatter(names) {}
  1250. };
  1251. enum class LogicOp : u32
  1252. {
  1253. Clear = 0,
  1254. And = 1,
  1255. AndReverse = 2,
  1256. Copy = 3,
  1257. AndInverted = 4,
  1258. NoOp = 5,
  1259. Xor = 6,
  1260. Or = 7,
  1261. Nor = 8,
  1262. Equiv = 9,
  1263. Invert = 10,
  1264. OrReverse = 11,
  1265. CopyInverted = 12,
  1266. OrInverted = 13,
  1267. Nand = 14,
  1268. Set = 15
  1269. };
  1270. template <>
  1271. struct fmt::formatter<LogicOp> : EnumFormatter<LogicOp::Set>
  1272. {
  1273. static constexpr array_type names = {
  1274. "Clear (0)",
  1275. "And (src & dst)",
  1276. "And Reverse (src & ~dst)",
  1277. "Copy (src)",
  1278. "And Inverted (~src & dst)",
  1279. "NoOp (dst)",
  1280. "Xor (src ^ dst)",
  1281. "Or (src | dst)",
  1282. "Nor (~(src | dst))",
  1283. "Equiv (~(src ^ dst))",
  1284. "Invert (~dst)",
  1285. "Or Reverse (src | ~dst)",
  1286. "Copy Inverted (~src)",
  1287. "Or Inverted (~src | dst)",
  1288. "Nand (~(src & dst))",
  1289. "Set (1)",
  1290. };
  1291. constexpr formatter() : EnumFormatter(names) {}
  1292. };
  1293. union BlendMode
  1294. {
  1295. BitField<0, 1, bool, u32> blendenable;
  1296. BitField<1, 1, bool, u32> logicopenable;
  1297. BitField<2, 1, bool, u32> dither;
  1298. BitField<3, 1, bool, u32> colorupdate;
  1299. BitField<4, 1, bool, u32> alphaupdate;
  1300. BitField<5, 3, DstBlendFactor> dstfactor;
  1301. BitField<8, 3, SrcBlendFactor> srcfactor;
  1302. BitField<11, 1, bool, u32> subtract;
  1303. BitField<12, 4, LogicOp> logicmode;
  1304. u32 hex;
  1305. bool UseLogicOp() const;
  1306. };
  1307. template <>
  1308. struct fmt::formatter<BlendMode>
  1309. {
  1310. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1311. template <typename FormatContext>
  1312. auto format(const BlendMode& mode, FormatContext& ctx) const
  1313. {
  1314. static constexpr std::array<const char*, 2> no_yes = {"No", "Yes"};
  1315. return fmt::format_to(ctx.out(),
  1316. "Enable: {}\n"
  1317. "Logic ops: {}\n"
  1318. "Dither: {}\n"
  1319. "Color write: {}\n"
  1320. "Alpha write: {}\n"
  1321. "Dest factor: {}\n"
  1322. "Source factor: {}\n"
  1323. "Subtract: {}\n"
  1324. "Logic mode: {}",
  1325. no_yes[mode.blendenable], no_yes[mode.logicopenable], no_yes[mode.dither],
  1326. no_yes[mode.colorupdate], no_yes[mode.alphaupdate], mode.dstfactor,
  1327. mode.srcfactor, no_yes[mode.subtract], mode.logicmode);
  1328. }
  1329. };
  1330. union FogParam0
  1331. {
  1332. BitField<0, 11, u32> mant;
  1333. BitField<11, 8, u32> exp;
  1334. BitField<19, 1, u32> sign;
  1335. u32 hex;
  1336. float FloatValue() const;
  1337. };
  1338. template <>
  1339. struct fmt::formatter<FogParam0>
  1340. {
  1341. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1342. template <typename FormatContext>
  1343. auto format(const FogParam0& param, FormatContext& ctx) const
  1344. {
  1345. return fmt::format_to(ctx.out(), "A value: {}\nMantissa: {}\nExponent: {}\nSign: {}",
  1346. param.FloatValue(), param.mant, param.exp, param.sign ? '-' : '+');
  1347. }
  1348. };
  1349. enum class FogProjection : u32
  1350. {
  1351. Perspective = 0,
  1352. Orthographic = 1,
  1353. };
  1354. template <>
  1355. struct fmt::formatter<FogProjection> : EnumFormatter<FogProjection::Orthographic>
  1356. {
  1357. constexpr formatter() : EnumFormatter({"Perspective", "Orthographic"}) {}
  1358. };
  1359. enum class FogType : u32
  1360. {
  1361. Off = 0,
  1362. Linear = 2,
  1363. Exp = 4,
  1364. ExpSq = 5,
  1365. BackwardsExp = 6,
  1366. BackwardsExpSq = 7,
  1367. };
  1368. template <>
  1369. struct fmt::formatter<FogType> : EnumFormatter<FogType::BackwardsExpSq>
  1370. {
  1371. static constexpr array_type names = {
  1372. "Off (no fog)",
  1373. nullptr,
  1374. "Linear fog",
  1375. nullptr,
  1376. "Exponential fog",
  1377. "Exponential-squared fog",
  1378. "Backwards exponential fog",
  1379. "Backwards exponenential-sequared fog",
  1380. };
  1381. constexpr formatter() : EnumFormatter(names) {}
  1382. };
  1383. union FogParam3
  1384. {
  1385. BitField<0, 11, u32> c_mant;
  1386. BitField<11, 8, u32> c_exp;
  1387. BitField<19, 1, u32> c_sign;
  1388. BitField<20, 1, FogProjection> proj;
  1389. BitField<21, 3, FogType> fsel;
  1390. u32 hex;
  1391. float FloatValue() const;
  1392. };
  1393. template <>
  1394. struct fmt::formatter<FogParam3>
  1395. {
  1396. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1397. template <typename FormatContext>
  1398. auto format(const FogParam3& param, FormatContext& ctx) const
  1399. {
  1400. return fmt::format_to(
  1401. ctx.out(), "C value: {}\nMantissa: {}\nExponent: {}\nSign: {}\nProjection: {}\nFsel: {}",
  1402. param.FloatValue(), param.c_mant, param.c_exp, param.c_sign ? '-' : '+', param.proj,
  1403. param.fsel);
  1404. }
  1405. };
  1406. union FogRangeKElement
  1407. {
  1408. BitField<0, 12, u32> HI;
  1409. BitField<12, 12, u32> LO;
  1410. // TODO: Which scaling coefficient should we use here? This is just a guess!
  1411. float GetValue(int i) const { return (i ? HI.Value() : LO.Value()) / 256.f; }
  1412. u32 HEX;
  1413. };
  1414. struct FogRangeParams
  1415. {
  1416. union RangeBase
  1417. {
  1418. BitField<0, 10, u32> Center; // viewport center + 342
  1419. BitField<10, 1, bool, u32> Enabled;
  1420. u32 hex;
  1421. };
  1422. RangeBase Base;
  1423. FogRangeKElement K[5];
  1424. };
  1425. template <>
  1426. struct fmt::formatter<FogRangeParams::RangeBase>
  1427. {
  1428. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1429. template <typename FormatContext>
  1430. auto format(const FogRangeParams::RangeBase& range, FormatContext& ctx) const
  1431. {
  1432. return fmt::format_to(ctx.out(), "Center: {}\nEnabled: {}", range.Center,
  1433. range.Enabled ? "Yes" : "No");
  1434. }
  1435. };
  1436. template <>
  1437. struct fmt::formatter<FogRangeKElement>
  1438. {
  1439. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1440. template <typename FormatContext>
  1441. auto format(const FogRangeKElement& range, FormatContext& ctx) const
  1442. {
  1443. return fmt::format_to(ctx.out(), "High: {}\nLow: {}", range.HI, range.LO);
  1444. }
  1445. };
  1446. // final eq: ze = A/(B_MAG - (Zs>>B_SHF));
  1447. struct FogParams
  1448. {
  1449. FogParam0 a;
  1450. u32 b_magnitude;
  1451. u32 b_shift; // b's exp + 1?
  1452. FogParam3 c_proj_fsel;
  1453. union FogColor
  1454. {
  1455. BitField<0, 8, u32> b;
  1456. BitField<8, 8, u32> g;
  1457. BitField<16, 8, u32> r;
  1458. u32 hex;
  1459. };
  1460. FogColor color; // 0:b 8:g 16:r - nice!
  1461. // Special case where a and c are infinite and the sign matches, resulting in a result of NaN.
  1462. bool IsNaNCase() const;
  1463. float GetA() const;
  1464. // amount to subtract from eyespacez after range adjustment
  1465. float GetC() const;
  1466. };
  1467. template <>
  1468. struct fmt::formatter<FogParams::FogColor>
  1469. {
  1470. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1471. template <typename FormatContext>
  1472. auto format(const FogParams::FogColor& color, FormatContext& ctx) const
  1473. {
  1474. return fmt::format_to(ctx.out(), "Red: {}\nGreen: {}\nBlue: {}", color.r, color.g, color.b);
  1475. }
  1476. };
  1477. enum class CompareMode : u32
  1478. {
  1479. Never = 0,
  1480. Less = 1,
  1481. Equal = 2,
  1482. LEqual = 3,
  1483. Greater = 4,
  1484. NEqual = 5,
  1485. GEqual = 6,
  1486. Always = 7
  1487. };
  1488. template <>
  1489. struct fmt::formatter<CompareMode> : EnumFormatter<CompareMode::Always>
  1490. {
  1491. static constexpr array_type names = {"Never", "Less", "Equal", "LEqual",
  1492. "Greater", "NEqual", "GEqual", "Always"};
  1493. constexpr formatter() : EnumFormatter(names) {}
  1494. };
  1495. union ZMode
  1496. {
  1497. BitField<0, 1, bool, u32> testenable;
  1498. BitField<1, 3, CompareMode> func;
  1499. BitField<4, 1, bool, u32> updateenable;
  1500. u32 hex;
  1501. };
  1502. template <>
  1503. struct fmt::formatter<ZMode>
  1504. {
  1505. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1506. template <typename FormatContext>
  1507. auto format(const ZMode& mode, FormatContext& ctx) const
  1508. {
  1509. return fmt::format_to(ctx.out(),
  1510. "Enable test: {}\n"
  1511. "Compare function: {}\n"
  1512. "Enable updates: {}",
  1513. mode.testenable ? "Yes" : "No", mode.func,
  1514. mode.updateenable ? "Yes" : "No");
  1515. }
  1516. };
  1517. union ConstantAlpha
  1518. {
  1519. BitField<0, 8, u32> alpha;
  1520. BitField<8, 1, bool, u32> enable;
  1521. u32 hex;
  1522. };
  1523. template <>
  1524. struct fmt::formatter<ConstantAlpha>
  1525. {
  1526. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1527. template <typename FormatContext>
  1528. auto format(const ConstantAlpha& c, FormatContext& ctx) const
  1529. {
  1530. return fmt::format_to(ctx.out(),
  1531. "Enable: {}\n"
  1532. "Alpha value: {:02x}",
  1533. c.enable ? "Yes" : "No", c.alpha);
  1534. }
  1535. };
  1536. union FieldMode
  1537. {
  1538. // adjust vertex tex LOD computation to account for interlacing
  1539. BitField<0, 1, AspectRatioAdjustment> texLOD;
  1540. u32 hex;
  1541. };
  1542. template <>
  1543. struct fmt::formatter<FieldMode>
  1544. {
  1545. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1546. template <typename FormatContext>
  1547. auto format(const FieldMode& mode, FormatContext& ctx) const
  1548. {
  1549. return fmt::format_to(
  1550. ctx.out(), "Adjust vertex tex LOD computation to account for interlacing: {}", mode.texLOD);
  1551. }
  1552. };
  1553. enum class FieldMaskState : u32
  1554. {
  1555. Skip = 0,
  1556. Write = 1,
  1557. };
  1558. template <>
  1559. struct fmt::formatter<FieldMaskState> : EnumFormatter<FieldMaskState::Write>
  1560. {
  1561. constexpr formatter() : EnumFormatter({"Skipped", "Written"}) {}
  1562. };
  1563. union FieldMask
  1564. {
  1565. // Fields are written to the EFB only if their bit is set to write.
  1566. BitField<0, 1, FieldMaskState> odd;
  1567. BitField<1, 1, FieldMaskState> even;
  1568. u32 hex;
  1569. };
  1570. template <>
  1571. struct fmt::formatter<FieldMask>
  1572. {
  1573. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1574. template <typename FormatContext>
  1575. auto format(const FieldMask& mask, FormatContext& ctx) const
  1576. {
  1577. return fmt::format_to(ctx.out(), "Odd field: {}\nEven field: {}", mask.odd, mask.even);
  1578. }
  1579. };
  1580. enum class PixelFormat : u32
  1581. {
  1582. RGB8_Z24 = 0,
  1583. RGBA6_Z24 = 1,
  1584. RGB565_Z16 = 2,
  1585. Z24 = 3,
  1586. Y8 = 4,
  1587. U8 = 5,
  1588. V8 = 6,
  1589. YUV420 = 7,
  1590. INVALID_FMT = 0xffffffff, // Used by Dolphin to represent a missing value.
  1591. };
  1592. template <>
  1593. struct fmt::formatter<PixelFormat> : EnumFormatter<PixelFormat::YUV420>
  1594. {
  1595. static constexpr array_type names = {"RGB8_Z24", "RGBA6_Z24", "RGB565_Z16", "Z24",
  1596. "Y8", "U8", "V8", "YUV420"};
  1597. constexpr formatter() : EnumFormatter(names) {}
  1598. };
  1599. enum class DepthFormat : u32
  1600. {
  1601. ZLINEAR = 0,
  1602. ZNEAR = 1,
  1603. ZMID = 2,
  1604. ZFAR = 3,
  1605. // It seems these Z formats aren't supported/were removed ?
  1606. ZINV_LINEAR = 4,
  1607. ZINV_NEAR = 5,
  1608. ZINV_MID = 6,
  1609. ZINV_FAR = 7
  1610. };
  1611. template <>
  1612. struct fmt::formatter<DepthFormat> : EnumFormatter<DepthFormat::ZINV_FAR>
  1613. {
  1614. static constexpr array_type names = {
  1615. "linear", "compressed (near)", "compressed (mid)", "compressed (far)",
  1616. "inv linear", "compressed (inv near)", "compressed (inv mid)", "compressed (inv far)",
  1617. };
  1618. constexpr formatter() : EnumFormatter(names) {}
  1619. };
  1620. union PEControl
  1621. {
  1622. BitField<0, 3, PixelFormat> pixel_format;
  1623. BitField<3, 3, DepthFormat> zformat;
  1624. BitField<6, 1, bool, u32> early_ztest;
  1625. u32 hex;
  1626. };
  1627. template <>
  1628. struct fmt::formatter<PEControl>
  1629. {
  1630. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1631. template <typename FormatContext>
  1632. auto format(const PEControl& config, FormatContext& ctx) const
  1633. {
  1634. return fmt::format_to(ctx.out(),
  1635. "EFB pixel format: {}\n"
  1636. "Depth format: {}\n"
  1637. "Early depth test: {}",
  1638. config.pixel_format, config.zformat, config.early_ztest ? "Yes" : "No");
  1639. }
  1640. };
  1641. // Texture coordinate stuff
  1642. union TCInfo
  1643. {
  1644. BitField<0, 16, u32> scale_minus_1;
  1645. BitField<16, 1, bool, u32> range_bias;
  1646. BitField<17, 1, bool, u32> cylindric_wrap;
  1647. // These bits only have effect in the s field of TCoordInfo
  1648. BitField<18, 1, bool, u32> line_offset;
  1649. BitField<19, 1, bool, u32> point_offset;
  1650. u32 hex;
  1651. };
  1652. template <>
  1653. struct fmt::formatter<std::pair<bool, TCInfo>>
  1654. {
  1655. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1656. template <typename FormatContext>
  1657. auto format(const std::pair<bool, TCInfo>& p, FormatContext& ctx) const
  1658. {
  1659. const auto& [is_s, info] = p;
  1660. auto out = fmt::format_to(ctx.out(),
  1661. "{0} coord scale: {1}\n"
  1662. "{0} coord range bias: {2}\n"
  1663. "{0} coord cylindric wrap: {3}",
  1664. is_s ? 'S' : 'T', info.scale_minus_1 + 1,
  1665. info.range_bias ? "Yes" : "No", info.cylindric_wrap ? "Yes" : "No");
  1666. if (is_s)
  1667. {
  1668. out = fmt::format_to(out,
  1669. "\nUse line offset: {}"
  1670. "\nUse point offset: {}",
  1671. info.line_offset ? "Yes" : "No", info.point_offset ? "Yes" : "No");
  1672. }
  1673. return out;
  1674. }
  1675. };
  1676. struct TCoordInfo
  1677. {
  1678. TCInfo s;
  1679. TCInfo t;
  1680. };
  1681. enum class TevRegType : u32
  1682. {
  1683. Color = 0,
  1684. Constant = 1,
  1685. };
  1686. template <>
  1687. struct fmt::formatter<TevRegType> : EnumFormatter<TevRegType::Constant>
  1688. {
  1689. constexpr formatter() : EnumFormatter({"Color", "Constant"}) {}
  1690. };
  1691. struct TevReg
  1692. {
  1693. // TODO: Check if Konst uses all 11 bits or just 8
  1694. union RA
  1695. {
  1696. u32 hex;
  1697. BitField<0, 11, s32> red;
  1698. BitField<12, 11, s32> alpha;
  1699. BitField<23, 1, TevRegType, u32> type;
  1700. };
  1701. union BG
  1702. {
  1703. u32 hex;
  1704. BitField<0, 11, s32> blue;
  1705. BitField<12, 11, s32> green;
  1706. BitField<23, 1, TevRegType, u32> type;
  1707. };
  1708. RA ra;
  1709. BG bg;
  1710. };
  1711. template <>
  1712. struct fmt::formatter<TevReg::RA>
  1713. {
  1714. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1715. template <typename FormatContext>
  1716. auto format(const TevReg::RA& ra, FormatContext& ctx) const
  1717. {
  1718. return fmt::format_to(ctx.out(), "Type: {}\nAlpha: {:03x}\nRed: {:03x}", ra.type, ra.alpha,
  1719. ra.red);
  1720. }
  1721. };
  1722. template <>
  1723. struct fmt::formatter<TevReg::BG>
  1724. {
  1725. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1726. template <typename FormatContext>
  1727. auto format(const TevReg::BG& bg, FormatContext& ctx) const
  1728. {
  1729. return fmt::format_to(ctx.out(), "Type: {}\nGreen: {:03x}\nBlue: {:03x}", bg.type, bg.green,
  1730. bg.blue);
  1731. }
  1732. };
  1733. template <>
  1734. struct fmt::formatter<TevReg>
  1735. {
  1736. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1737. template <typename FormatContext>
  1738. auto format(const TevReg& reg, FormatContext& ctx) const
  1739. {
  1740. return fmt::format_to(ctx.out(), "{}\n{}", reg.ra, reg.bg);
  1741. }
  1742. };
  1743. enum class ColorChannel : u32
  1744. {
  1745. Red = 0,
  1746. Green = 1,
  1747. Blue = 2,
  1748. Alpha = 3,
  1749. };
  1750. template <>
  1751. struct fmt::formatter<ColorChannel> : EnumFormatter<ColorChannel::Alpha>
  1752. {
  1753. constexpr formatter() : EnumFormatter({"Red", "Green", "Blue", "Alpha"}) {}
  1754. };
  1755. enum class KonstSel : u32
  1756. {
  1757. V1 = 0,
  1758. V7_8 = 1,
  1759. V3_4 = 2,
  1760. V5_8 = 3,
  1761. V1_2 = 4,
  1762. V3_8 = 5,
  1763. V1_4 = 6,
  1764. V1_8 = 7,
  1765. // 8-11 are invalid values that output 0 (8-15 for alpha)
  1766. K0 = 12, // Color only
  1767. K1 = 13, // Color only
  1768. K2 = 14, // Color only
  1769. K3 = 15, // Color only
  1770. K0_R = 16,
  1771. K1_R = 17,
  1772. K2_R = 18,
  1773. K3_R = 19,
  1774. K0_G = 20,
  1775. K1_G = 21,
  1776. K2_G = 22,
  1777. K3_G = 23,
  1778. K0_B = 24,
  1779. K1_B = 25,
  1780. K2_B = 26,
  1781. K3_B = 27,
  1782. K0_A = 28,
  1783. K1_A = 29,
  1784. K2_A = 30,
  1785. K3_A = 31,
  1786. };
  1787. template <>
  1788. struct fmt::formatter<KonstSel> : EnumFormatter<KonstSel::K3_A>
  1789. {
  1790. static constexpr array_type names = {
  1791. "1",
  1792. "7/8",
  1793. "3/4",
  1794. "5/8",
  1795. "1/2",
  1796. "3/8",
  1797. "1/4",
  1798. "1/8",
  1799. nullptr,
  1800. nullptr,
  1801. nullptr,
  1802. nullptr,
  1803. "Konst 0 RGB (invalid for alpha)",
  1804. "Konst 1 RGB (invalid for alpha)",
  1805. "Konst 2 RGB (invalid for alpha)",
  1806. "Konst 3 RGB (invalid for alpha)",
  1807. "Konst 0 Red",
  1808. "Konst 1 Red",
  1809. "Konst 2 Red",
  1810. "Konst 3 Red",
  1811. "Konst 0 Green",
  1812. "Konst 1 Green",
  1813. "Konst 2 Green",
  1814. "Konst 3 Green",
  1815. "Konst 0 Blue",
  1816. "Konst 1 Blue",
  1817. "Konst 2 Blue",
  1818. "Konst 3 Blue",
  1819. "Konst 0 Alpha",
  1820. "Konst 1 Alpha",
  1821. "Konst 2 Alpha",
  1822. "Konst 3 Alpha",
  1823. };
  1824. constexpr formatter() : EnumFormatter(names) {}
  1825. };
  1826. union TevKSel
  1827. {
  1828. BitField<0, 2, ColorChannel> swap_rb; // Odd ksel number: red; even: blue
  1829. BitField<2, 2, ColorChannel> swap_ga; // Odd ksel number: green; even: alpha
  1830. BitField<4, 5, KonstSel> kcsel_even;
  1831. BitField<9, 5, KonstSel> kasel_even;
  1832. BitField<14, 5, KonstSel> kcsel_odd;
  1833. BitField<19, 5, KonstSel> kasel_odd;
  1834. u32 hex;
  1835. };
  1836. template <>
  1837. struct fmt::formatter<std::pair<u8, TevKSel>>
  1838. {
  1839. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1840. template <typename FormatContext>
  1841. auto format(const std::pair<u8, TevKSel>& p, FormatContext& ctx) const
  1842. {
  1843. const auto& [cmd, ksel] = p;
  1844. const u8 swap_number = (cmd - BPMEM_TEV_KSEL) / 2;
  1845. const bool swap_ba = (cmd - BPMEM_TEV_KSEL) & 1;
  1846. const u8 even_stage = (cmd - BPMEM_TEV_KSEL) * 2;
  1847. const u8 odd_stage = even_stage + 1;
  1848. return fmt::format_to(ctx.out(),
  1849. "Swap table {0}: {1} channel comes from input's {2} channel\n"
  1850. "Swap table {0}: {3} channel comes from input's {4} channel\n"
  1851. "TEV stage {5} konst color: {6}\n"
  1852. "TEV stage {5} konst alpha: {7}\n"
  1853. "TEV stage {8} konst color: {9}\n"
  1854. "TEV stage {8} konst alpha: {10}",
  1855. swap_number, swap_ba ? "Blue" : "Red", ksel.swap_rb,
  1856. swap_ba ? "Alpha" : "Green", ksel.swap_ga, even_stage, ksel.kcsel_even,
  1857. ksel.kasel_even, odd_stage, ksel.kcsel_odd, ksel.kasel_odd);
  1858. }
  1859. };
  1860. struct AllTevKSels
  1861. {
  1862. std::array<TevKSel, 8> ksel;
  1863. KonstSel GetKonstColor(u32 tev_stage) const
  1864. {
  1865. const u32 ksel_num = tev_stage >> 1;
  1866. const bool odd = tev_stage & 1;
  1867. const auto& cur_ksel = ksel[ksel_num];
  1868. return odd ? cur_ksel.kcsel_odd.Value() : cur_ksel.kcsel_even.Value();
  1869. }
  1870. KonstSel GetKonstAlpha(u32 tev_stage) const
  1871. {
  1872. const u32 ksel_num = tev_stage >> 1;
  1873. const bool odd = tev_stage & 1;
  1874. const auto& cur_ksel = ksel[ksel_num];
  1875. return odd ? cur_ksel.kasel_odd.Value() : cur_ksel.kasel_even.Value();
  1876. }
  1877. Common::EnumMap<ColorChannel, ColorChannel::Alpha> GetSwapTable(u32 swap_table_id) const
  1878. {
  1879. const u32 rg_ksel_num = swap_table_id << 1;
  1880. const u32 ba_ksel_num = rg_ksel_num + 1;
  1881. const auto& rg_ksel = ksel[rg_ksel_num];
  1882. const auto& ba_ksel = ksel[ba_ksel_num];
  1883. return {rg_ksel.swap_rb, rg_ksel.swap_ga, ba_ksel.swap_rb, ba_ksel.swap_ga};
  1884. }
  1885. };
  1886. enum class AlphaTestOp : u32
  1887. {
  1888. And = 0,
  1889. Or = 1,
  1890. Xor = 2,
  1891. Xnor = 3
  1892. };
  1893. template <>
  1894. struct fmt::formatter<AlphaTestOp> : EnumFormatter<AlphaTestOp::Xnor>
  1895. {
  1896. constexpr formatter() : EnumFormatter({"And", "Or", "Xor", "Xnor"}) {}
  1897. };
  1898. enum class AlphaTestResult
  1899. {
  1900. Undetermined = 0,
  1901. Fail = 1,
  1902. Pass = 2,
  1903. };
  1904. union AlphaTest
  1905. {
  1906. BitField<0, 8, u32> ref0;
  1907. BitField<8, 8, u32> ref1;
  1908. BitField<16, 3, CompareMode> comp0;
  1909. BitField<19, 3, CompareMode> comp1;
  1910. BitField<22, 2, AlphaTestOp> logic;
  1911. u32 hex;
  1912. DOLPHIN_FORCE_INLINE AlphaTestResult TestResult() const
  1913. {
  1914. switch (logic)
  1915. {
  1916. case AlphaTestOp::And:
  1917. if (comp0 == CompareMode::Always && comp1 == CompareMode::Always)
  1918. return AlphaTestResult::Pass;
  1919. if (comp0 == CompareMode::Never || comp1 == CompareMode::Never)
  1920. return AlphaTestResult::Fail;
  1921. break;
  1922. case AlphaTestOp::Or:
  1923. if (comp0 == CompareMode::Always || comp1 == CompareMode::Always)
  1924. return AlphaTestResult::Pass;
  1925. if (comp0 == CompareMode::Never && comp1 == CompareMode::Never)
  1926. return AlphaTestResult::Fail;
  1927. break;
  1928. case AlphaTestOp::Xor:
  1929. if ((comp0 == CompareMode::Always && comp1 == CompareMode::Never) ||
  1930. (comp0 == CompareMode::Never && comp1 == CompareMode::Always))
  1931. return AlphaTestResult::Pass;
  1932. if ((comp0 == CompareMode::Always && comp1 == CompareMode::Always) ||
  1933. (comp0 == CompareMode::Never && comp1 == CompareMode::Never))
  1934. return AlphaTestResult::Fail;
  1935. break;
  1936. case AlphaTestOp::Xnor:
  1937. if ((comp0 == CompareMode::Always && comp1 == CompareMode::Never) ||
  1938. (comp0 == CompareMode::Never && comp1 == CompareMode::Always))
  1939. return AlphaTestResult::Fail;
  1940. if ((comp0 == CompareMode::Always && comp1 == CompareMode::Always) ||
  1941. (comp0 == CompareMode::Never && comp1 == CompareMode::Never))
  1942. return AlphaTestResult::Pass;
  1943. break;
  1944. default:
  1945. return AlphaTestResult::Undetermined;
  1946. }
  1947. return AlphaTestResult::Undetermined;
  1948. }
  1949. };
  1950. template <>
  1951. struct fmt::formatter<AlphaTest>
  1952. {
  1953. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  1954. template <typename FormatContext>
  1955. auto format(const AlphaTest& test, FormatContext& ctx) const
  1956. {
  1957. return fmt::format_to(ctx.out(),
  1958. "Test 1: {} (ref: 0x{:02x})\n"
  1959. "Test 2: {} (ref: 0x{:02x})\n"
  1960. "Logic: {}\n",
  1961. test.comp0, test.ref0, test.comp1, test.ref1, test.logic);
  1962. }
  1963. };
  1964. enum class FrameToField : u32
  1965. {
  1966. Progressive = 0,
  1967. InterlacedEven = 2,
  1968. InterlacedOdd = 3,
  1969. };
  1970. template <>
  1971. struct fmt::formatter<FrameToField> : EnumFormatter<FrameToField::InterlacedOdd>
  1972. {
  1973. static constexpr array_type names = {"Progressive", nullptr, "Interlaced (even lines)",
  1974. "Interlaced (odd lines)"};
  1975. constexpr formatter() : EnumFormatter(names) {}
  1976. };
  1977. enum class GammaCorrection : u32
  1978. {
  1979. Gamma1_0 = 0,
  1980. Gamma1_7 = 1,
  1981. Gamma2_2 = 2,
  1982. // Hardware testing indicates this behaves the same as Gamma2_2
  1983. Invalid2_2 = 3,
  1984. };
  1985. template <>
  1986. struct fmt::formatter<GammaCorrection> : EnumFormatter<GammaCorrection::Invalid2_2>
  1987. {
  1988. constexpr formatter() : EnumFormatter({"1.0", "1.7", "2.2", "Invalid 2.2"}) {}
  1989. };
  1990. union UPE_Copy
  1991. {
  1992. u32 Hex;
  1993. BitField<0, 1, bool, u32> clamp_top; // if set clamp top
  1994. BitField<1, 1, bool, u32> clamp_bottom; // if set clamp bottom
  1995. BitField<2, 1, u32> unknown_bit;
  1996. BitField<3, 4, u32> target_pixel_format; // realformat is (fmt/2)+((fmt&1)*8).... for some reason
  1997. // the msb is the lsb (pattern: cycling right shift)
  1998. BitField<7, 2, GammaCorrection> gamma;
  1999. // "mipmap" filter... false = no filter (scale 1:1) ; true = box filter (scale 2:1)
  2000. BitField<9, 1, bool, u32> half_scale;
  2001. BitField<10, 1, bool, u32> scale_invert; // if set vertical scaling is on
  2002. BitField<11, 1, bool, u32> clear;
  2003. BitField<12, 2, FrameToField> frame_to_field;
  2004. BitField<14, 1, bool, u32> copy_to_xfb;
  2005. BitField<15, 1, bool, u32> intensity_fmt; // if set, is an intensity format (I4,I8,IA4,IA8)
  2006. // if false automatic color conversion by texture format and pixel type
  2007. BitField<16, 1, bool, u32> auto_conv;
  2008. EFBCopyFormat tp_realFormat() const
  2009. {
  2010. return static_cast<EFBCopyFormat>(target_pixel_format / 2 + (target_pixel_format & 1) * 8);
  2011. }
  2012. };
  2013. template <>
  2014. struct fmt::formatter<UPE_Copy>
  2015. {
  2016. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  2017. template <typename FormatContext>
  2018. auto format(const UPE_Copy& copy, FormatContext& ctx) const
  2019. {
  2020. static constexpr std::array<const char*, 2> no_yes = {"No", "Yes"};
  2021. std::string_view clamp;
  2022. if (copy.clamp_top)
  2023. {
  2024. if (copy.clamp_bottom)
  2025. clamp = "Top and Bottom";
  2026. else
  2027. clamp = "Top only";
  2028. }
  2029. else
  2030. {
  2031. if (copy.clamp_bottom)
  2032. clamp = "Bottom only";
  2033. else
  2034. clamp = "None";
  2035. }
  2036. return fmt::format_to(ctx.out(),
  2037. "Clamping: {}\n"
  2038. "Unknown bit: {}\n"
  2039. "Target pixel format: {}\n"
  2040. "Gamma correction: {}\n"
  2041. "Half scale: {}\n"
  2042. "Vertical scaling: {}\n"
  2043. "Clear: {}\n"
  2044. "Frame to field: {}\n"
  2045. "Copy to XFB: {}\n"
  2046. "Intensity format: {}\n"
  2047. "Automatic color conversion: {}",
  2048. clamp, copy.unknown_bit, copy.tp_realFormat(), copy.gamma,
  2049. no_yes[copy.half_scale], no_yes[copy.scale_invert], no_yes[copy.clear],
  2050. copy.frame_to_field, no_yes[copy.copy_to_xfb], no_yes[copy.intensity_fmt],
  2051. no_yes[copy.auto_conv]);
  2052. }
  2053. };
  2054. union CopyFilterCoefficients
  2055. {
  2056. using Values = std::array<u8, 7>;
  2057. u64 Hex;
  2058. BitField<0, 32, u32, u64> Low;
  2059. BitField<0, 6, u64> w0;
  2060. BitField<6, 6, u64> w1;
  2061. BitField<12, 6, u64> w2;
  2062. BitField<18, 6, u64> w3;
  2063. BitField<32, 32, u32, u64> High;
  2064. BitField<32, 6, u64> w4;
  2065. BitField<38, 6, u64> w5;
  2066. BitField<44, 6, u64> w6;
  2067. Values GetCoefficients() const
  2068. {
  2069. return {{
  2070. static_cast<u8>(w0),
  2071. static_cast<u8>(w1),
  2072. static_cast<u8>(w2),
  2073. static_cast<u8>(w3),
  2074. static_cast<u8>(w4),
  2075. static_cast<u8>(w5),
  2076. static_cast<u8>(w6),
  2077. }};
  2078. }
  2079. };
  2080. union BPU_PreloadTileInfo
  2081. {
  2082. BitField<0, 15, u32> count;
  2083. BitField<15, 2, u32> type; // TODO: enum for this?
  2084. u32 hex;
  2085. };
  2086. template <>
  2087. struct fmt::formatter<BPU_PreloadTileInfo>
  2088. {
  2089. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  2090. template <typename FormatContext>
  2091. auto format(const BPU_PreloadTileInfo& info, FormatContext& ctx) const
  2092. {
  2093. if (info.count == 0 && info.type == 0)
  2094. {
  2095. return fmt::format_to(ctx.out(), "GX_TexModeSync (type and count are both 0)");
  2096. }
  2097. else
  2098. {
  2099. return fmt::format_to(ctx.out(), "Type: {}\nCount: 0x{:x} lines (0x{:x} bytes)", info.type,
  2100. info.count, info.count * 32);
  2101. }
  2102. }
  2103. };
  2104. union BPU_LoadTlutInfo
  2105. {
  2106. BitField<0, 10, u32> tmem_addr;
  2107. BitField<10, 11, u32> tmem_line_count;
  2108. u32 hex;
  2109. };
  2110. template <>
  2111. struct fmt::formatter<BPU_LoadTlutInfo>
  2112. {
  2113. constexpr auto parse(format_parse_context& ctx) { return ctx.begin(); }
  2114. template <typename FormatContext>
  2115. auto format(const BPU_LoadTlutInfo& info, FormatContext& ctx) const
  2116. {
  2117. return fmt::format_to(ctx.out(), "Tmem address: 0x{:05x}\nCount: 0x{:x} lines (0x{:x} bytes)",
  2118. info.tmem_addr << 9, info.tmem_line_count, info.tmem_line_count * 32);
  2119. }
  2120. };
  2121. struct BPS_TmemConfig
  2122. {
  2123. u32 preload_addr;
  2124. u32 preload_tmem_even;
  2125. u32 preload_tmem_odd;
  2126. BPU_PreloadTileInfo preload_tile_info;
  2127. u32 tlut_src;
  2128. BPU_LoadTlutInfo tlut_dest;
  2129. u32 texinvalidate;
  2130. };
  2131. union AllTexUnits;
  2132. // The addressing of the texture units is a bit non-obvious.
  2133. // This struct abstracts the complexity away.
  2134. union TexUnitAddress
  2135. {
  2136. enum class Register : u32
  2137. {
  2138. SETMODE0 = 0,
  2139. SETMODE1 = 1,
  2140. SETIMAGE0 = 2,
  2141. SETIMAGE1 = 3,
  2142. SETIMAGE2 = 4,
  2143. SETIMAGE3 = 5,
  2144. SETTLUT = 6,
  2145. UNKNOWN = 7,
  2146. };
  2147. BitField<0, 2, u32> UnitIdLow;
  2148. BitField<2, 3, Register> Reg;
  2149. BitField<5, 1, u32> UnitIdHigh;
  2150. BitField<0, 6, u32> FullAddress;
  2151. u32 hex;
  2152. TexUnitAddress() : hex(0) {}
  2153. TexUnitAddress(u32 unit_id, Register reg = Register::SETMODE0) : hex(0)
  2154. {
  2155. UnitIdLow = unit_id & 3;
  2156. UnitIdHigh = unit_id >> 2;
  2157. Reg = reg;
  2158. }
  2159. static TexUnitAddress FromBPAddress(u32 Address)
  2160. {
  2161. TexUnitAddress Val;
  2162. // Clear upper two bits (which should always be 0x80)
  2163. Val.FullAddress = Address & 0x3f;
  2164. return Val;
  2165. }
  2166. u32 GetUnitID() const { return UnitIdLow | (UnitIdHigh << 2); }
  2167. private:
  2168. friend AllTexUnits;
  2169. size_t GetOffset() const { return FullAddress; }
  2170. size_t GetBPAddress() const { return FullAddress | 0x80; }
  2171. static constexpr size_t ComputeOffset(u32 unit_id)
  2172. {
  2173. // FIXME: Would be nice to construct a TexUnitAddress and get its offset,
  2174. // but that doesn't seem to be possible in c++17
  2175. // So we manually re-implement the calculation
  2176. return (unit_id & 3) | ((unit_id & 4) << 3);
  2177. }
  2178. };
  2179. static_assert(sizeof(TexUnitAddress) == sizeof(u32));
  2180. // A view of the registers of a single TexUnit
  2181. struct TexUnit
  2182. {
  2183. TexMode0 texMode0;
  2184. u32 : 32; // doing u32 : 96 is legal according to the standard, but msvc
  2185. u32 : 32; // doesn't like it. So we stack multiple lines of u32 : 32;
  2186. u32 : 32;
  2187. TexMode1 texMode1;
  2188. u32 : 32;
  2189. u32 : 32;
  2190. u32 : 32;
  2191. TexImage0 texImage0;
  2192. u32 : 32;
  2193. u32 : 32;
  2194. u32 : 32;
  2195. TexImage1 texImage1;
  2196. u32 : 32;
  2197. u32 : 32;
  2198. u32 : 32;
  2199. TexImage2 texImage2;
  2200. u32 : 32;
  2201. u32 : 32;
  2202. u32 : 32;
  2203. TexImage3 texImage3;
  2204. u32 : 32;
  2205. u32 : 32;
  2206. u32 : 32;
  2207. TexTLUT texTlut;
  2208. u32 : 32;
  2209. u32 : 32;
  2210. u32 : 32;
  2211. u32 unknown;
  2212. };
  2213. static_assert(sizeof(TexUnit) == sizeof(u32) * 4 * 7 + sizeof(u32));
  2214. union AllTexUnits
  2215. {
  2216. std::array<u32, 8 * 8> AllRegisters;
  2217. const TexUnit& GetUnit(u32 UnitId) const
  2218. {
  2219. auto address = TexUnitAddress(UnitId);
  2220. const u32* ptr = &AllRegisters[address.GetOffset()];
  2221. return *reinterpret_cast<const TexUnit*>(ptr);
  2222. }
  2223. private:
  2224. // For debuggers since GetUnit can be optimised out in release builds
  2225. template <u32 UnitId>
  2226. struct TexUnitPadding
  2227. {
  2228. static_assert(UnitId != 0, "Can't use 0 as sizeof(std::array<u32, 0>) != 0");
  2229. std::array<u32, TexUnitAddress::ComputeOffset(UnitId)> pad;
  2230. };
  2231. TexUnit tex0;
  2232. struct
  2233. {
  2234. TexUnitPadding<1> pad1;
  2235. TexUnit tex1;
  2236. };
  2237. struct
  2238. {
  2239. TexUnitPadding<2> pad2;
  2240. TexUnit tex2;
  2241. };
  2242. struct
  2243. {
  2244. TexUnitPadding<3> pad3;
  2245. TexUnit tex3;
  2246. };
  2247. struct
  2248. {
  2249. TexUnitPadding<4> pad4;
  2250. TexUnit tex4;
  2251. };
  2252. struct
  2253. {
  2254. TexUnitPadding<5> pad5;
  2255. TexUnit tex5;
  2256. };
  2257. struct
  2258. {
  2259. TexUnitPadding<6> pad6;
  2260. TexUnit tex6;
  2261. };
  2262. struct
  2263. {
  2264. TexUnitPadding<7> pad7;
  2265. TexUnit tex7;
  2266. };
  2267. };
  2268. static_assert(sizeof(AllTexUnits) == 8 * 8 * sizeof(u32));
  2269. // All of BP memory
  2270. struct BPCmd
  2271. {
  2272. int address;
  2273. int changes;
  2274. int newvalue;
  2275. };
  2276. enum class EmulatedZ : u32
  2277. {
  2278. Disabled = 0,
  2279. Early = 1,
  2280. Late = 2,
  2281. ForcedEarly = 3,
  2282. EarlyWithFBFetch = 4,
  2283. EarlyWithZComplocHack = 5,
  2284. };
  2285. struct BPMemory
  2286. {
  2287. GenMode genMode; // 0x00
  2288. u32 display_copy_filter[4]; // 0x01-0x04
  2289. u32 unknown; // 0x05
  2290. // indirect matrices (set by GXSetIndTexMtx, selected by TevStageIndirect::matrix_index)
  2291. // abc form a 2x3 offset matrix, there's 3 such matrices
  2292. // the 3 offset matrices can either be indirect type, S-type, or T-type
  2293. // 6bit scale factor s is distributed across IND_MTXA/B/C.
  2294. // before using matrices scale by 2^-(s-17)
  2295. IND_MTX indmtx[3]; // 0x06-0x0e: GXSetIndTexMtx, 2x3 matrices
  2296. IND_IMASK imask; // 0x0f
  2297. TevStageIndirect tevind[16]; // 0x10-0x1f: GXSetTevIndirect
  2298. ScissorPos scissorTL; // 0x20
  2299. ScissorPos scissorBR; // 0x21
  2300. LPSize lineptwidth; // 0x22
  2301. u32 sucounter; // 0x23
  2302. u32 rascounter; // 0x24
  2303. TEXSCALE texscale[2]; // 0x25,0x26: GXSetIndTexCoordScale
  2304. RAS1_IREF tevindref; // 0x27: GXSetIndTexOrder
  2305. TwoTevStageOrders tevorders[8]; // 0x28-0x2f
  2306. TCoordInfo texcoords[8]; // 0x30-0x3f: s,t,s,t,s,t,s,t...
  2307. ZMode zmode; // 0x40
  2308. BlendMode blendmode; // 0x41
  2309. ConstantAlpha dstalpha; // 0x42
  2310. PEControl zcontrol; // 0x43: GXSetZCompLoc, GXPixModeSync
  2311. FieldMask fieldmask; // 0x44
  2312. u32 drawdone; // 0x45: bit1=1 if end of list
  2313. u32 unknown5; // 0x46: clock?
  2314. u32 petoken; // 0x47
  2315. u32 petokenint; // 0x48
  2316. X10Y10 copyTexSrcXY; // 0x49
  2317. X10Y10 copyTexSrcWH; // 0x4a
  2318. u32 copyTexDest; // 0x4b: CopyAddress (GXDispCopy and GXTexCopy use it)
  2319. u32 unknown6; // 0x4c
  2320. u32 copyDestStride; // 0x4d
  2321. u32 dispcopyyscale; // 0x4e
  2322. u32 clearcolorAR; // 0x4f
  2323. u32 clearcolorGB; // 0x50
  2324. u32 clearZValue; // 0x51
  2325. UPE_Copy triggerEFBCopy; // 0x52
  2326. CopyFilterCoefficients copyfilter; // 0x53,0x54
  2327. u32 boundbox0; // 0x55
  2328. u32 boundbox1; // 0x56
  2329. u32 unknown7[2]; // 0x57,0x58
  2330. ScissorOffset scissorOffset; // 0x59
  2331. u32 unknown8[6]; // 0x5a-0x5f
  2332. BPS_TmemConfig tmem_config; // 0x60-0x66
  2333. u32 metric; // 0x67
  2334. FieldMode fieldmode; // 0x68
  2335. u32 unknown10[7]; // 0x69-0x6f
  2336. u32 unknown11[16]; // 0x70-0x7f
  2337. AllTexUnits tex; // 0x80-0xbf
  2338. TevStageCombiner combiners[16]; // 0xc0-0xdf
  2339. TevReg tevregs[4]; // 0xe0-0xe7
  2340. FogRangeParams fogRange; // 0xe8-0xed
  2341. FogParams fog; // 0xee-0xf2
  2342. AlphaTest alpha_test; // 0xf3
  2343. ZTex1 ztex1; // 0xf4
  2344. ZTex2 ztex2; // 0xf5
  2345. AllTevKSels tevksel; // 0xf6-0xfd
  2346. u32 bpMask; // 0xfe
  2347. u32 unknown18; // 0xff
  2348. EmulatedZ GetEmulatedZ() const
  2349. {
  2350. if (!zmode.testenable)
  2351. return EmulatedZ::Disabled;
  2352. if (zcontrol.early_ztest)
  2353. return EmulatedZ::Early;
  2354. else
  2355. return EmulatedZ::Late;
  2356. }
  2357. };
  2358. #pragma pack()
  2359. extern BPMemory bpmem;
  2360. void LoadBPReg(u8 reg, u32 value, int cycles_into_future);
  2361. void LoadBPRegPreprocess(u8 reg, u32 value, int cycles_into_future);
  2362. std::pair<std::string, std::string> GetBPRegInfo(u8 cmd, u32 cmddata);