XFStructs.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. // Copyright 2008 Dolphin Emulator Project
  2. // Licensed under GPLv2+
  3. // Refer to the license.txt file included.
  4. #include "Common/Common.h"
  5. #include "Core/HW/Memmap.h"
  6. #include "VideoCommon/CPMemory.h"
  7. #include "VideoCommon/DataReader.h"
  8. #include "VideoCommon/Fifo.h"
  9. #include "VideoCommon/GeometryShaderManager.h"
  10. #include "VideoCommon/PixelShaderManager.h"
  11. #include "VideoCommon/VertexManagerBase.h"
  12. #include "VideoCommon/VertexShaderManager.h"
  13. #include "VideoCommon/VideoCommon.h"
  14. #include "VideoCommon/XFMemory.h"
  15. static void XFMemWritten(u32 transferSize, u32 baseAddress)
  16. {
  17. VertexManager::Flush();
  18. VertexShaderManager::InvalidateXFRange(baseAddress, baseAddress + transferSize);
  19. }
  20. static void XFRegWritten(int transferSize, u32 baseAddress, DataReader src)
  21. {
  22. u32 address = baseAddress;
  23. u32 dataIndex = 0;
  24. while (transferSize > 0 && address < 0x1058)
  25. {
  26. u32 newValue = src.Peek<u32>(dataIndex * sizeof(u32));
  27. u32 nextAddress = address + 1;
  28. switch (address)
  29. {
  30. case XFMEM_ERROR:
  31. case XFMEM_DIAG:
  32. case XFMEM_STATE0: // internal state 0
  33. case XFMEM_STATE1: // internal state 1
  34. case XFMEM_CLOCK:
  35. case XFMEM_SETGPMETRIC:
  36. nextAddress = 0x1007;
  37. break;
  38. case XFMEM_CLIPDISABLE:
  39. //if (data & 1) {} // disable clipping detection
  40. //if (data & 2) {} // disable trivial rejection
  41. //if (data & 4) {} // disable cpoly clipping acceleration
  42. break;
  43. case XFMEM_VTXSPECS: //__GXXfVtxSpecs, wrote 0004
  44. break;
  45. case XFMEM_SETNUMCHAN:
  46. if (xfmem.numChan.numColorChans != (newValue & 3))
  47. VertexManager::Flush();
  48. break;
  49. case XFMEM_SETCHAN0_AMBCOLOR: // Channel Ambient Color
  50. case XFMEM_SETCHAN1_AMBCOLOR:
  51. {
  52. u8 chan = address - XFMEM_SETCHAN0_AMBCOLOR;
  53. if (xfmem.ambColor[chan] != newValue)
  54. {
  55. VertexManager::Flush();
  56. VertexShaderManager::SetMaterialColorChanged(chan, newValue);
  57. }
  58. break;
  59. }
  60. case XFMEM_SETCHAN0_MATCOLOR: // Channel Material Color
  61. case XFMEM_SETCHAN1_MATCOLOR:
  62. {
  63. u8 chan = address - XFMEM_SETCHAN0_MATCOLOR;
  64. if (xfmem.matColor[chan] != newValue)
  65. {
  66. VertexManager::Flush();
  67. VertexShaderManager::SetMaterialColorChanged(chan + 2, newValue);
  68. }
  69. break;
  70. }
  71. case XFMEM_SETCHAN0_COLOR: // Channel Color
  72. case XFMEM_SETCHAN1_COLOR:
  73. case XFMEM_SETCHAN0_ALPHA: // Channel Alpha
  74. case XFMEM_SETCHAN1_ALPHA:
  75. if (((u32*)&xfmem)[address] != (newValue & 0x7fff))
  76. VertexManager::Flush();
  77. break;
  78. case XFMEM_DUALTEX:
  79. if (xfmem.dualTexTrans.enabled != (newValue & 1))
  80. VertexManager::Flush();
  81. break;
  82. case XFMEM_SETMATRIXINDA:
  83. //_assert_msg_(GX_XF, 0, "XF matrixindex0");
  84. VertexShaderManager::SetTexMatrixChangedA(newValue);
  85. break;
  86. case XFMEM_SETMATRIXINDB:
  87. //_assert_msg_(GX_XF, 0, "XF matrixindex1");
  88. VertexShaderManager::SetTexMatrixChangedB(newValue);
  89. break;
  90. case XFMEM_SETVIEWPORT:
  91. case XFMEM_SETVIEWPORT+1:
  92. case XFMEM_SETVIEWPORT+2:
  93. case XFMEM_SETVIEWPORT+3:
  94. case XFMEM_SETVIEWPORT+4:
  95. case XFMEM_SETVIEWPORT+5:
  96. VertexManager::Flush();
  97. VertexShaderManager::SetViewportChanged();
  98. PixelShaderManager::SetViewportChanged();
  99. GeometryShaderManager::SetViewportChanged();
  100. nextAddress = XFMEM_SETVIEWPORT + 6;
  101. break;
  102. case XFMEM_SETPROJECTION:
  103. case XFMEM_SETPROJECTION+1:
  104. case XFMEM_SETPROJECTION+2:
  105. case XFMEM_SETPROJECTION+3:
  106. case XFMEM_SETPROJECTION+4:
  107. case XFMEM_SETPROJECTION+5:
  108. case XFMEM_SETPROJECTION+6:
  109. VertexManager::Flush();
  110. VertexShaderManager::SetProjectionChanged();
  111. GeometryShaderManager::SetProjectionChanged();
  112. nextAddress = XFMEM_SETPROJECTION + 7;
  113. break;
  114. case XFMEM_SETNUMTEXGENS: // GXSetNumTexGens
  115. if (xfmem.numTexGen.numTexGens != (newValue & 15))
  116. VertexManager::Flush();
  117. break;
  118. case XFMEM_SETTEXMTXINFO:
  119. case XFMEM_SETTEXMTXINFO+1:
  120. case XFMEM_SETTEXMTXINFO+2:
  121. case XFMEM_SETTEXMTXINFO+3:
  122. case XFMEM_SETTEXMTXINFO+4:
  123. case XFMEM_SETTEXMTXINFO+5:
  124. case XFMEM_SETTEXMTXINFO+6:
  125. case XFMEM_SETTEXMTXINFO+7:
  126. VertexManager::Flush();
  127. nextAddress = XFMEM_SETTEXMTXINFO + 8;
  128. break;
  129. case XFMEM_SETPOSMTXINFO:
  130. case XFMEM_SETPOSMTXINFO+1:
  131. case XFMEM_SETPOSMTXINFO+2:
  132. case XFMEM_SETPOSMTXINFO+3:
  133. case XFMEM_SETPOSMTXINFO+4:
  134. case XFMEM_SETPOSMTXINFO+5:
  135. case XFMEM_SETPOSMTXINFO+6:
  136. case XFMEM_SETPOSMTXINFO+7:
  137. VertexManager::Flush();
  138. nextAddress = XFMEM_SETPOSMTXINFO + 8;
  139. break;
  140. // --------------
  141. // Unknown Regs
  142. // --------------
  143. // Maybe these are for Normals?
  144. case 0x1048: //xfmem.texcoords[0].nrmmtxinfo.hex = data; break; ??
  145. case 0x1049:
  146. case 0x104a:
  147. case 0x104b:
  148. case 0x104c:
  149. case 0x104d:
  150. case 0x104e:
  151. case 0x104f:
  152. DEBUG_LOG(VIDEO, "Possible Normal Mtx XF reg?: %x=%x", address, newValue);
  153. break;
  154. case 0x1013:
  155. case 0x1014:
  156. case 0x1015:
  157. case 0x1016:
  158. case 0x1017:
  159. default:
  160. WARN_LOG(VIDEO, "Unknown XF Reg: %x=%x", address, newValue);
  161. break;
  162. }
  163. int transferred = nextAddress - address;
  164. address = nextAddress;
  165. transferSize -= transferred;
  166. dataIndex += transferred;
  167. }
  168. }
  169. void LoadXFReg(u32 transferSize, u32 baseAddress, DataReader src)
  170. {
  171. // do not allow writes past registers
  172. if (baseAddress + transferSize > 0x1058)
  173. {
  174. INFO_LOG(VIDEO, "XF load exceeds address space: %x %d bytes", baseAddress, transferSize);
  175. if (baseAddress >= 0x1058)
  176. transferSize = 0;
  177. else
  178. transferSize = 0x1058 - baseAddress;
  179. }
  180. // write to XF mem
  181. if (baseAddress < 0x1000 && transferSize > 0)
  182. {
  183. u32 end = baseAddress + transferSize;
  184. u32 xfMemBase = baseAddress;
  185. u32 xfMemTransferSize = transferSize;
  186. if (end >= 0x1000)
  187. {
  188. xfMemTransferSize = 0x1000 - baseAddress;
  189. baseAddress = 0x1000;
  190. transferSize = end - 0x1000;
  191. }
  192. else
  193. {
  194. transferSize = 0;
  195. }
  196. XFMemWritten(xfMemTransferSize, xfMemBase);
  197. for (u32 i = 0; i < xfMemTransferSize; i++)
  198. {
  199. ((u32*)&xfmem)[xfMemBase + i] = src.Read<u32>();
  200. }
  201. }
  202. // write to XF regs
  203. if (transferSize > 0)
  204. {
  205. XFRegWritten(transferSize, baseAddress, src);
  206. for (u32 i = 0; i < transferSize; i++)
  207. {
  208. ((u32*)&xfmem)[baseAddress + i] = src.Read<u32>();
  209. }
  210. }
  211. }
  212. // TODO - verify that it is correct. Seems to work, though.
  213. void LoadIndexedXF(u32 val, int refarray)
  214. {
  215. int index = val >> 16;
  216. int address = val & 0xFFF; // check mask
  217. int size = ((val >> 12) & 0xF) + 1;
  218. //load stuff from array to address in xf mem
  219. u32* currData = (u32*)(&xfmem) + address;
  220. u32* newData;
  221. if (g_use_deterministic_gpu_thread)
  222. {
  223. newData = (u32*)PopFifoAuxBuffer(size * sizeof(u32));
  224. }
  225. else
  226. {
  227. newData = (u32*)Memory::GetPointer(g_main_cp_state.array_bases[refarray] + g_main_cp_state.array_strides[refarray] * index);
  228. }
  229. bool changed = false;
  230. for (int i = 0; i < size; ++i)
  231. {
  232. if (currData[i] != Common::swap32(newData[i]))
  233. {
  234. changed = true;
  235. XFMemWritten(size, address);
  236. break;
  237. }
  238. }
  239. if (changed)
  240. {
  241. for (int i = 0; i < size; ++i)
  242. currData[i] = Common::swap32(newData[i]);
  243. }
  244. }
  245. void PreprocessIndexedXF(u32 val, int refarray)
  246. {
  247. int index = val >> 16;
  248. int size = ((val >> 12) & 0xF) + 1;
  249. u32* new_data = (u32*)Memory::GetPointer(g_preprocess_cp_state.array_bases[refarray] + g_preprocess_cp_state.array_strides[refarray] * index);
  250. size_t buf_size = size * sizeof(u32);
  251. PushFifoAuxBuffer(new_data, buf_size);
  252. }