GSLocalMemory.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:84k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 Gabest
  3.  * http://www.gabest.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *   
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *   
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  * Special Notes: 
  21.  *
  22.  * Based on Page.c from GSSoft
  23.  * Copyright (C) 2002-2004 GSsoft Team
  24.  *
  25.  */
  26.  
  27. #include "StdAfx.h"
  28. #include "GSLocalMemory.h"
  29. #include "x86.h"
  30. //
  31. static class cdscd
  32. {
  33. CString toBin(UINT64 n, int bits)
  34. {
  35. CString str;
  36. while(bits-- > 0) str += n&(1i64<<bits) ? '1' : '0';
  37. return str;
  38. }
  39. public:
  40. cdscd()
  41. {
  42. return;
  43. /*
  44. union
  45. {
  46. struct {DWORD mant:23; DWORD exp:8; DWORD sign:1;} fi;
  47. DWORD i;
  48. float f;
  49. } nf, nf2;
  50. union
  51. {
  52. struct {UINT64 mant:52; UINT64 exp:11; UINT64 sign:1;} di;
  53. UINT64 i;
  54. double d;
  55. } nd;
  56. nd.di.mant = 0;
  57. nd.di.exp = 1023+128;
  58. nd.di.sign = 0;
  59. nd.d = pow(2.0, 128);
  60. TRACE(_T("%016I64x (%I64x:%I64x:%I64x), %fn"), nd.i, nd.di.sign, nd.di.exp, nd.di.mant, nd.d);
  61. */
  62. /*
  63. unsigned int control_word = 0;
  64. int err;
  65. // nd.d = 0;
  66. // TRACE(_T("%016I64x (%I64x:%I64x:%I64x), %fn"), nd.i, nd.di.sign, nd.di.exp, nd.di.mant, nd.d);
  67. // nf.f = nd.d;
  68. // TRACE(_T("%08x (%x:%x:%x), %fn"), nf.i, nf.fi.sign, nf.fi.exp, nf.fi.mant, nf.f);
  69. nf2.fi.sign = 0;
  70. nf2.fi.exp = 0x7f;
  71. nf2.fi.mant = 1;
  72. //err = _controlfp_s(&control_word, _RC_CHOP, _MCW_RC);
  73. nf.f = 0;
  74. for(int i = 0; i < 20; i++)
  75. {
  76. nd.d = (double)nf.f + (double)nf2.f;
  77. TRACE(_T("%016I64x (%I64x:%03I64x:%s), %fn"), nd.i, nd.di.sign, nd.di.exp, toBin(nd.di.mant, 52), nd.d);
  78. *((UINT64*)&nd.d) &= ~(1ui64<<(52-24));
  79. TRACE(_T("%016I64x (%I64x:%03I64x:%s), %fn"), nd.i, nd.di.sign, nd.di.exp, toBin(nd.di.mant, 52), nd.d);
  80. nf.f = (float)nd.d;
  81. TRACE(_T("%08x         (%x:%02x :%s                             ), %fn"), nf.i, nf.fi.sign, nf.fi.exp, toBin(nf.fi.mant, 23), nf.f);
  82. }
  83. */
  84. /*
  85. GSLocalMemory lm;
  86. for(int i = 0; i < 1024*1024; i++)
  87. ((DWORD*)lm.GetVM())[i] = rand()*0x12345678;
  88. GIFRegTEX0 TEX0;
  89. TEX0.TBP0 = 0;
  90. TEX0.TBW = 16;
  91. GIFRegTEXA TEXA;
  92. TEXA.AEM = 0; // 1
  93. __declspec(align(32)) static DWORD dst[1024*1024];
  94. for(int j = 0; j < 10; j++)
  95. {
  96. clock_t start = clock();
  97. for(int i = 0; i < 1000; i++)
  98. {
  99. lm.unSwizzleTexture32(CRect(0,0,1024,1024), (BYTE*)dst, 1024*4, TEX0, TEXA);
  100. }
  101. clock_t diff = clock() - start;
  102. CString str;
  103. str.Format(_T("%d"), diff);
  104. AfxMessageBox(str);
  105. }
  106. */
  107. /*
  108. __declspec(align(16)) static vertex_t v[100000];
  109. for(int i = 0; i < countof(v); i++)
  110. {
  111. v[i].u = 1.0f*rand() - RAND_MAX/2;
  112. v[i].v = 1.0f*rand() - RAND_MAX/2;
  113. }
  114. for(int j = 0; j < 10; j++)
  115. {
  116. clock_t start = clock();
  117. uvmm_t uvmm;
  118. for(int i = 0; i < 1000; i++)
  119. UVMinMax_sse2(countof(v), v, &uvmm);
  120. clock_t diff = clock() - start;
  121. CString str;
  122. str.Format(_T("%d, u %.2f %.2f, v %.2f %.2f"), diff, uvmm.umin, uvmm.umax, uvmm.vmin, uvmm.vmax);
  123. AfxMessageBox(str);
  124. }
  125. */
  126. /*
  127. GIFRegTEX0 TEX0;
  128. GIFRegTEXCLUT TEXCLUT;
  129. TEX0.PSM = PSM_PSMT8;
  130. TEX0.CLD = 1;
  131. TEX0.CSA = 0;
  132. TEX0.CPSM = PSM_PSMCT32; // PSM_PSMCT16S
  133. TEX0.CBP = 0;
  134. TEX0.CSM = 0; // 0
  135. TEXCLUT.CBW = 1;
  136. TEXCLUT.COU = 0;
  137. TEXCLUT.COV = 0;
  138. for(int j = 0; j < 10; j++)
  139. {
  140. clock_t start = clock();
  141. for(int i = 0; i < 10000000; i++)
  142. lm.WriteCLUT(TEX0, TEXCLUT);
  143. clock_t diff = clock() - start;
  144. CString str;
  145. str.Format(_T("%d"), diff);
  146. AfxMessageBox(str);
  147. }
  148. */
  149. /*
  150. GIFRegTEXA TEXA;
  151. TEXA.AEM = 0; // 1
  152. TEXA.TA0 = 0x7f;
  153. TEXA.TA1 = 0x80;
  154. int w = 1024*1024;
  155. WORD* src = (WORD*)lm.GetVM();
  156. DWORD* dst = (DWORD*)_aligned_malloc(w*4, 16);
  157. for(int j = 0; j < 10; j++)
  158. {
  159. clock_t start = clock();
  160. for(int i = 0; i < 1000; i++)
  161. {
  162. //Expand16_sse2(src, dst, w, &TEXA);
  163. Expand16_c(src, dst, w, &TEXA);
  164. }
  165. clock_t diff = clock() - start;
  166. CString str;
  167. str.Format(_T("%d"), diff);
  168. AfxMessageBox(str);
  169. }
  170. _aligned_free(dst);
  171. */
  172. }
  173. } sddscsd;
  174. //
  175. #define ASSERT_BLOCK(r, w, h) 
  176. ASSERT((r).Width() >= w && (r).Height() >= h && !((r).left&(w-1)) && !((r).top&(h-1)) && !((r).right&(w-1)) && !((r).bottom&(h-1))); 
  177. #if defined(_M_AMD64) || _M_IX86_FP >= 2
  178. #define BLOCK_PREFETCH(mem) 
  179. _mm_prefetch(&mem[16*0], _MM_HINT_T0); 
  180. _mm_prefetch(&mem[16*2], _MM_HINT_T0); 
  181. _mm_prefetch(&mem[16*4], _MM_HINT_T0); 
  182. _mm_prefetch(&mem[16*6], _MM_HINT_T0); 
  183. _mm_prefetch(&mem[16*8], _MM_HINT_T0); 
  184. _mm_prefetch(&mem[16*10], _MM_HINT_T0); 
  185. _mm_prefetch(&mem[16*12], _MM_HINT_T0); 
  186. _mm_prefetch(&mem[16*14], _MM_HINT_T0); 
  187. #define BLOCK_PREFETCH_32(x, y, w) {const char* next = (const char*)&m_vm32[blockAddress32(x + (w), y, TEX0.TBP0, TEX0.TBW)]; BLOCK_PREFETCH(next);}
  188. #define BLOCK_PREFETCH_16(x, y, w) {const char* next = (const char*)&m_vm16[blockAddress16(x + (w), y, TEX0.TBP0, TEX0.TBW)]; BLOCK_PREFETCH(next);}
  189. #define BLOCK_PREFETCH_16S(x, y, w) {const char* next = (const char*)&m_vm16[blockAddress16S(x + (w), y, TEX0.TBP0, TEX0.TBW)]; BLOCK_PREFETCH(next);}
  190. #define BLOCK_PREFETCH_8(x, y, w) {const char* next = (const char*)&m_vm8[blockAddress8(x + (w), y, TEX0.TBP0, TEX0.TBW)]; BLOCK_PREFETCH(next);}
  191. #define BLOCK_PREFETCH_4(x, y, w) {const char* next = (const char*)&m_vm8[blockAddress4(x + (w), y, TEX0.TBP0, TEX0.TBW)>>1]; BLOCK_PREFETCH(next);}
  192. #else 
  193. #define BLOCK_PREFETCH_32(x, y, w)
  194. #define BLOCK_PREFETCH_16(x, y, w)
  195. #define BLOCK_PREFETCH_16S(x, y, w)
  196. #define BLOCK_PREFETCH_8(x, y, w)
  197. #define BLOCK_PREFETCH_4(x, y, w)
  198. #endif
  199. #define FOREACH_BLOCK_START(r, w, h, t) 
  200. for(int y = (r).top; y < (r).bottom; y += (h)) 
  201. {  ASSERT_BLOCK(r, w, h); 
  202. BYTE* ptr = dst + (y-(r).top)*dstpitch; 
  203. for(int x = (r).left; x < (r).right; x += (w)) 
  204. BLOCK_PREFETCH_##t##(x + (w), y, w) 
  205. #define FOREACH_BLOCK_END }}
  206. //
  207. DWORD GSLocalMemory::pageOffset32[32][32][64];
  208. DWORD GSLocalMemory::pageOffset32Z[32][32][64];
  209. DWORD GSLocalMemory::pageOffset16[32][64][64];
  210. DWORD GSLocalMemory::pageOffset16S[32][64][64];
  211. DWORD GSLocalMemory::pageOffset16Z[32][64][64];
  212. DWORD GSLocalMemory::pageOffset16SZ[32][64][64];
  213. DWORD GSLocalMemory::pageOffset8[32][64][128];
  214. DWORD GSLocalMemory::pageOffset4[32][128][128];
  215. int GSLocalMemory::rowOffset32[2048];
  216. int GSLocalMemory::rowOffset32Z[2048];
  217. int GSLocalMemory::rowOffset16[2048];
  218. int GSLocalMemory::rowOffset16S[2048];
  219. int GSLocalMemory::rowOffset16Z[2048];
  220. int GSLocalMemory::rowOffset16SZ[2048];
  221. int GSLocalMemory::rowOffset8[2][2048];
  222. int GSLocalMemory::rowOffset4[2][2048];
  223. //
  224. DWORD GSLocalMemory::m_xtbl[1024];
  225. DWORD GSLocalMemory::m_ytbl[1024]; 
  226. //
  227. GSLocalMemory::psmtbl_t GSLocalMemory::m_psmtbl[64];
  228. //
  229. GSLocalMemory::GSLocalMemory()
  230. : m_fCLUTMayBeDirty(true)
  231. {
  232. int len = 1024*1024*4*2; // *2 for safety...
  233. m_vm8 = (BYTE*)_aligned_malloc(len, 16);
  234. memset(m_vm8, 0, len);
  235. m_pCLUT = (WORD*)_aligned_malloc(256*2*sizeof(WORD)*2, 16);
  236. m_pCLUT32 = (DWORD*)_aligned_malloc(256*sizeof(DWORD), 16);
  237. m_pCLUT64 = (UINT64*)_aligned_malloc(256*sizeof(UINT64), 16);
  238. for(int bp = 0; bp < 32; bp++)
  239. {
  240. for(int y = 0; y < 32; y++) for(int x = 0; x < 64; x++)
  241. {
  242. pageOffset32[bp][y][x] = pixelAddressOrg32(x, y, bp, 0);
  243. pageOffset32Z[bp][y][x] = pixelAddressOrg32Z(x, y, bp, 0);
  244. }
  245. for(int y = 0; y < 64; y++) for(int x = 0; x < 64; x++) 
  246. {
  247. pageOffset16[bp][y][x] = pixelAddressOrg16(x, y, bp, 0);
  248. pageOffset16S[bp][y][x] = pixelAddressOrg16S(x, y, bp, 0);
  249. pageOffset16Z[bp][y][x] = pixelAddressOrg16Z(x, y, bp, 0);
  250. pageOffset16SZ[bp][y][x] = pixelAddressOrg16SZ(x, y, bp, 0);
  251. }
  252. for(int y = 0; y < 64; y++) for(int x = 0; x < 128; x++)
  253. {
  254. pageOffset8[bp][y][x] = pixelAddressOrg8(x, y, bp, 0);
  255. }
  256. for(int y = 0; y < 128; y++) for(int x = 0; x < 128; x++)
  257. {
  258. pageOffset4[bp][y][x] = pixelAddressOrg4(x, y, bp, 0);
  259. }
  260. }
  261. {
  262. for(int x = 0; x < countof(rowOffset32); x++)
  263. rowOffset32[x] = (int)pixelAddress32(x, 0, 0, 32) - (int)pixelAddress32(0, 0, 0, 32);
  264. for(int x = 0; x < countof(rowOffset32Z); x++)
  265. rowOffset32Z[x] = (int)pixelAddress32Z(x, 0, 0, 32) - (int)pixelAddress32Z(0, 0, 0, 32);
  266. for(int x = 0; x < countof(rowOffset16); x++)
  267. rowOffset16[x] = (int)pixelAddress16(x, 0, 0, 32) - (int)pixelAddress16(0, 0, 0, 32);
  268. for(int x = 0; x < countof(rowOffset16S); x++)
  269. rowOffset16S[x] = (int)pixelAddress16S(x, 0, 0, 32) - (int)pixelAddress16S(0, 0, 0, 32);
  270. for(int x = 0; x < countof(rowOffset16Z); x++)
  271. rowOffset16Z[x] = (int)pixelAddress16Z(x, 0, 0, 32) - (int)pixelAddress16Z(0, 0, 0, 32);
  272. for(int x = 0; x < countof(rowOffset16SZ); x++)
  273. rowOffset16SZ[x] = (int)pixelAddress16SZ(x, 0, 0, 32) - (int)pixelAddress16SZ(0, 0, 0, 32);
  274. for(int x = 0; x < countof(rowOffset8[0]); x++)
  275. rowOffset8[0][x] = (int)pixelAddress8(x, 0, 0, 32) - (int)pixelAddress8(0, 0, 0, 32),
  276. rowOffset8[1][x] = (int)pixelAddress8(x, 2, 0, 32) - (int)pixelAddress8(0, 2, 0, 32);
  277. for(int x = 0; x < countof(rowOffset4[0]); x++)
  278. rowOffset4[0][x] = (int)pixelAddress4(x, 0, 0, 32) - (int)pixelAddress4(0, 0, 0, 32),
  279. rowOffset4[1][x] = (int)pixelAddress4(x, 2, 0, 32) - (int)pixelAddress4(0, 2, 0, 32);
  280. }
  281. for(int i = 0; i < countof(m_psmtbl); i++)
  282. {
  283. m_psmtbl[i].pa = &GSLocalMemory::pixelAddress32;
  284. m_psmtbl[i].ba = &GSLocalMemory::blockAddress32;
  285. m_psmtbl[i].pga = &GSLocalMemory::pageAddress32;
  286. m_psmtbl[i].rp = &GSLocalMemory::readPixel32;
  287. m_psmtbl[i].rpa = &GSLocalMemory::readPixel32;
  288. m_psmtbl[i].wp = &GSLocalMemory::writePixel32;
  289. m_psmtbl[i].wpa = &GSLocalMemory::writePixel32;
  290. m_psmtbl[i].rt = m_psmtbl[i].rtNP = m_psmtbl[i].rtP = &GSLocalMemory::readTexel32;
  291. m_psmtbl[i].rta = &GSLocalMemory::readTexel32;
  292. m_psmtbl[i].wfa = &GSLocalMemory::writePixel32;
  293. m_psmtbl[i].st = &GSLocalMemory::SwizzleTexture32;
  294. m_psmtbl[i].ust = m_psmtbl[i].ustP = m_psmtbl[i].ustNP = &GSLocalMemory::unSwizzleTexture32;
  295. m_psmtbl[i].bpp = m_psmtbl[i].trbpp = 32;
  296. m_psmtbl[i].pal = 0;
  297. m_psmtbl[i].bs = CSize(8, 8);
  298. for(int j = 0; j < 8; j++) m_psmtbl[i].rowOffset[j] = rowOffset32;
  299. }
  300. m_psmtbl[PSM_PSMCT16].pa = &GSLocalMemory::pixelAddress16;
  301. m_psmtbl[PSM_PSMCT16S].pa = &GSLocalMemory::pixelAddress16S;
  302. m_psmtbl[PSM_PSMT8].pa = &GSLocalMemory::pixelAddress8;
  303. m_psmtbl[PSM_PSMT4].pa = &GSLocalMemory::pixelAddress4;
  304. m_psmtbl[PSM_PSMZ32].pa = &GSLocalMemory::pixelAddress32Z;
  305. m_psmtbl[PSM_PSMZ24].pa = &GSLocalMemory::pixelAddress32Z;
  306. m_psmtbl[PSM_PSMZ16].pa = &GSLocalMemory::pixelAddress16Z;
  307. m_psmtbl[PSM_PSMZ16S].pa = &GSLocalMemory::pixelAddress16SZ;
  308. m_psmtbl[PSM_PSMCT16].ba = &GSLocalMemory::blockAddress16;
  309. m_psmtbl[PSM_PSMCT16S].ba = &GSLocalMemory::blockAddress16S;
  310. m_psmtbl[PSM_PSMT8].ba = &GSLocalMemory::blockAddress8;
  311. m_psmtbl[PSM_PSMT4].ba = &GSLocalMemory::blockAddress4;
  312. m_psmtbl[PSM_PSMZ32].ba = &GSLocalMemory::blockAddress32Z;
  313. m_psmtbl[PSM_PSMZ24].ba = &GSLocalMemory::blockAddress32Z;
  314. m_psmtbl[PSM_PSMZ16].ba = &GSLocalMemory::blockAddress16Z;
  315. m_psmtbl[PSM_PSMZ16S].ba = &GSLocalMemory::blockAddress16SZ;
  316. m_psmtbl[PSM_PSMCT16].pga = &GSLocalMemory::pageAddress16;
  317. m_psmtbl[PSM_PSMCT16S].pga = &GSLocalMemory::pageAddress16;
  318. m_psmtbl[PSM_PSMZ16].pga = &GSLocalMemory::pageAddress16;
  319. m_psmtbl[PSM_PSMZ16S].pga = &GSLocalMemory::pageAddress16;
  320. m_psmtbl[PSM_PSMT8].pga = &GSLocalMemory::pageAddress8;
  321. m_psmtbl[PSM_PSMT4].pga = &GSLocalMemory::pageAddress4;
  322. m_psmtbl[PSM_PSMCT24].rp = &GSLocalMemory::readPixel24;
  323. m_psmtbl[PSM_PSMCT16].rp = &GSLocalMemory::readPixel16;
  324. m_psmtbl[PSM_PSMCT16S].rp = &GSLocalMemory::readPixel16S;
  325. m_psmtbl[PSM_PSMT8].rp = &GSLocalMemory::readPixel8;
  326. m_psmtbl[PSM_PSMT4].rp = &GSLocalMemory::readPixel4;
  327. m_psmtbl[PSM_PSMT8H].rp = &GSLocalMemory::readPixel8H;
  328. m_psmtbl[PSM_PSMT4HL].rp = &GSLocalMemory::readPixel4HL;
  329. m_psmtbl[PSM_PSMT4HH].rp = &GSLocalMemory::readPixel4HH;
  330. m_psmtbl[PSM_PSMZ32].rp = &GSLocalMemory::readPixel32Z;
  331. m_psmtbl[PSM_PSMZ24].rp = &GSLocalMemory::readPixel24Z;
  332. m_psmtbl[PSM_PSMZ16].rp = &GSLocalMemory::readPixel16Z;
  333. m_psmtbl[PSM_PSMZ16S].rp = &GSLocalMemory::readPixel16SZ;
  334. m_psmtbl[PSM_PSMCT24].rpa = &GSLocalMemory::readPixel24;
  335. m_psmtbl[PSM_PSMCT16].rpa = &GSLocalMemory::readPixel16;
  336. m_psmtbl[PSM_PSMCT16S].rpa = &GSLocalMemory::readPixel16S;
  337. m_psmtbl[PSM_PSMT8].rpa = &GSLocalMemory::readPixel8;
  338. m_psmtbl[PSM_PSMT4].rpa = &GSLocalMemory::readPixel4;
  339. m_psmtbl[PSM_PSMT8H].rpa = &GSLocalMemory::readPixel8H;
  340. m_psmtbl[PSM_PSMT4HL].rpa = &GSLocalMemory::readPixel4HL;
  341. m_psmtbl[PSM_PSMT4HH].rpa = &GSLocalMemory::readPixel4HH;
  342. m_psmtbl[PSM_PSMZ32].rpa = &GSLocalMemory::readPixel32Z;
  343. m_psmtbl[PSM_PSMZ24].rpa = &GSLocalMemory::readPixel24Z;
  344. m_psmtbl[PSM_PSMZ16].rpa = &GSLocalMemory::readPixel16Z;
  345. m_psmtbl[PSM_PSMZ16S].rpa = &GSLocalMemory::readPixel16SZ;
  346. m_psmtbl[PSM_PSMCT32].wp = &GSLocalMemory::writePixel32;
  347. m_psmtbl[PSM_PSMCT24].wp = &GSLocalMemory::writePixel24;
  348. m_psmtbl[PSM_PSMCT16].wp = &GSLocalMemory::writePixel16;
  349. m_psmtbl[PSM_PSMCT16S].wp = &GSLocalMemory::writePixel16S;
  350. m_psmtbl[PSM_PSMT8].wp = &GSLocalMemory::writePixel8;
  351. m_psmtbl[PSM_PSMT4].wp = &GSLocalMemory::writePixel4;
  352. m_psmtbl[PSM_PSMT8H].wp = &GSLocalMemory::writePixel8H;
  353. m_psmtbl[PSM_PSMT4HL].wp = &GSLocalMemory::writePixel4HL;
  354. m_psmtbl[PSM_PSMT4HH].wp = &GSLocalMemory::writePixel4HH;
  355. m_psmtbl[PSM_PSMZ32].wp = &GSLocalMemory::writePixel32Z;
  356. m_psmtbl[PSM_PSMZ24].wp = &GSLocalMemory::writePixel24Z;
  357. m_psmtbl[PSM_PSMZ16].wp = &GSLocalMemory::writePixel16Z;
  358. m_psmtbl[PSM_PSMZ16S].wp = &GSLocalMemory::writePixel16SZ;
  359. m_psmtbl[PSM_PSMCT32].wpa = &GSLocalMemory::writePixel32;
  360. m_psmtbl[PSM_PSMCT24].wpa = &GSLocalMemory::writePixel24;
  361. m_psmtbl[PSM_PSMCT16].wpa = &GSLocalMemory::writePixel16;
  362. m_psmtbl[PSM_PSMCT16S].wpa = &GSLocalMemory::writePixel16S;
  363. m_psmtbl[PSM_PSMT8].wpa = &GSLocalMemory::writePixel8;
  364. m_psmtbl[PSM_PSMT4].wpa = &GSLocalMemory::writePixel4;
  365. m_psmtbl[PSM_PSMT8H].wpa = &GSLocalMemory::writePixel8H;
  366. m_psmtbl[PSM_PSMT4HL].wpa = &GSLocalMemory::writePixel4HL;
  367. m_psmtbl[PSM_PSMT4HH].wpa = &GSLocalMemory::writePixel4HH;
  368. m_psmtbl[PSM_PSMZ32].wpa = &GSLocalMemory::writePixel32Z;
  369. m_psmtbl[PSM_PSMZ24].wpa = &GSLocalMemory::writePixel24Z;
  370. m_psmtbl[PSM_PSMZ16].wpa = &GSLocalMemory::writePixel16Z;
  371. m_psmtbl[PSM_PSMZ16S].wpa = &GSLocalMemory::writePixel16SZ;
  372. m_psmtbl[PSM_PSMCT24].rt = &GSLocalMemory::readTexel24;
  373. m_psmtbl[PSM_PSMCT16].rt = &GSLocalMemory::readTexel16;
  374. m_psmtbl[PSM_PSMCT16S].rt = &GSLocalMemory::readTexel16S;
  375. m_psmtbl[PSM_PSMT8].rt = &GSLocalMemory::readTexel8;
  376. m_psmtbl[PSM_PSMT4].rt = &GSLocalMemory::readTexel4;
  377. m_psmtbl[PSM_PSMT8H].rt = &GSLocalMemory::readTexel8H;
  378. m_psmtbl[PSM_PSMT4HL].rt = &GSLocalMemory::readTexel4HL;
  379. m_psmtbl[PSM_PSMT4HH].rt = &GSLocalMemory::readTexel4HH;
  380. m_psmtbl[PSM_PSMCT24].rta = &GSLocalMemory::readTexel24;
  381. m_psmtbl[PSM_PSMCT16].rta = &GSLocalMemory::readTexel16;
  382. m_psmtbl[PSM_PSMCT16S].rta = &GSLocalMemory::readTexel16S;
  383. m_psmtbl[PSM_PSMT8].rta = &GSLocalMemory::readTexel8;
  384. m_psmtbl[PSM_PSMT4].rta = &GSLocalMemory::readTexel4;
  385. m_psmtbl[PSM_PSMT8H].rta = &GSLocalMemory::readTexel8H;
  386. m_psmtbl[PSM_PSMT4HL].rta = &GSLocalMemory::readTexel4HL;
  387. m_psmtbl[PSM_PSMT4HH].rta = &GSLocalMemory::readTexel4HH;
  388. m_psmtbl[PSM_PSMCT24].wfa = &GSLocalMemory::writePixel24;
  389. m_psmtbl[PSM_PSMCT16].wfa = &GSLocalMemory::writeFrame16;
  390. m_psmtbl[PSM_PSMCT16S].wfa = &GSLocalMemory::writeFrame16S;
  391. m_psmtbl[PSM_PSMCT16].rtP = &GSLocalMemory::readTexel16P;
  392. m_psmtbl[PSM_PSMCT16S].rtP = &GSLocalMemory::readTexel16SP;
  393. m_psmtbl[PSM_PSMT8].rtP = &GSLocalMemory::readTexel8P;
  394. m_psmtbl[PSM_PSMT4].rtP = &GSLocalMemory::readTexel4P;
  395. m_psmtbl[PSM_PSMT8H].rtP = &GSLocalMemory::readTexel8HP;
  396. m_psmtbl[PSM_PSMT4HL].rtP = &GSLocalMemory::readTexel4HLP;
  397. m_psmtbl[PSM_PSMT4HH].rtP = &GSLocalMemory::readTexel4HHP;
  398. m_psmtbl[PSM_PSMCT16].rtNP = &GSLocalMemory::readTexel16P;
  399. m_psmtbl[PSM_PSMCT16S].rtNP = &GSLocalMemory::readTexel16SP;
  400. m_psmtbl[PSM_PSMT8].rtNP = &GSLocalMemory::readTexel8;
  401. m_psmtbl[PSM_PSMT4].rtNP = &GSLocalMemory::readTexel4;
  402. m_psmtbl[PSM_PSMT8H].rtNP = &GSLocalMemory::readTexel8H;
  403. m_psmtbl[PSM_PSMT4HL].rtNP = &GSLocalMemory::readTexel4HL;
  404. m_psmtbl[PSM_PSMT4HH].rtNP = &GSLocalMemory::readTexel4HH;
  405. m_psmtbl[PSM_PSMCT24].st = &GSLocalMemory::SwizzleTexture24;
  406. m_psmtbl[PSM_PSMCT16].st = &GSLocalMemory::SwizzleTexture16;
  407. m_psmtbl[PSM_PSMCT16S].st = &GSLocalMemory::SwizzleTexture16S;
  408. m_psmtbl[PSM_PSMT8].st = &GSLocalMemory::SwizzleTexture8;
  409. m_psmtbl[PSM_PSMT4].st = &GSLocalMemory::SwizzleTexture4;
  410. m_psmtbl[PSM_PSMT8H].st = &GSLocalMemory::SwizzleTexture8H;
  411. m_psmtbl[PSM_PSMT4HL].st = &GSLocalMemory::SwizzleTexture4HL;
  412. m_psmtbl[PSM_PSMT4HH].st = &GSLocalMemory::SwizzleTexture4HH;
  413. m_psmtbl[PSM_PSMCT24].ust = &GSLocalMemory::unSwizzleTexture24;
  414. m_psmtbl[PSM_PSMCT16].ust = &GSLocalMemory::unSwizzleTexture16;
  415. m_psmtbl[PSM_PSMCT16S].ust = &GSLocalMemory::unSwizzleTexture16S;
  416. m_psmtbl[PSM_PSMT8].ust = &GSLocalMemory::unSwizzleTexture8;
  417. m_psmtbl[PSM_PSMT4].ust = &GSLocalMemory::unSwizzleTexture4;
  418. m_psmtbl[PSM_PSMT8H].ust = &GSLocalMemory::unSwizzleTexture8H;
  419. m_psmtbl[PSM_PSMT4HL].ust = &GSLocalMemory::unSwizzleTexture4HL;
  420. m_psmtbl[PSM_PSMT4HH].ust = &GSLocalMemory::unSwizzleTexture4HH;
  421. m_psmtbl[PSM_PSMCT16].ustP = &GSLocalMemory::unSwizzleTexture16P;
  422. m_psmtbl[PSM_PSMCT16S].ustP = &GSLocalMemory::unSwizzleTexture16SP;
  423. m_psmtbl[PSM_PSMT8].ustP = &GSLocalMemory::unSwizzleTexture8P;
  424. m_psmtbl[PSM_PSMT4].ustP = &GSLocalMemory::unSwizzleTexture4P;
  425. m_psmtbl[PSM_PSMT8H].ustP = &GSLocalMemory::unSwizzleTexture8HP;
  426. m_psmtbl[PSM_PSMT4HL].ustP = &GSLocalMemory::unSwizzleTexture4HLP;
  427. m_psmtbl[PSM_PSMT4HH].ustP = &GSLocalMemory::unSwizzleTexture4HHP;
  428. m_psmtbl[PSM_PSMCT16].ustNP = &GSLocalMemory::unSwizzleTexture16P;
  429. m_psmtbl[PSM_PSMCT16S].ustNP = &GSLocalMemory::unSwizzleTexture16SP;
  430. m_psmtbl[PSM_PSMT8].ustNP = &GSLocalMemory::unSwizzleTexture8NP;
  431. m_psmtbl[PSM_PSMT4].ustNP = &GSLocalMemory::unSwizzleTexture4NP;
  432. m_psmtbl[PSM_PSMT8H].ustNP = &GSLocalMemory::unSwizzleTexture8HNP;
  433. m_psmtbl[PSM_PSMT4HL].ustNP = &GSLocalMemory::unSwizzleTexture4HLNP;
  434. m_psmtbl[PSM_PSMT4HH].ustNP = &GSLocalMemory::unSwizzleTexture4HHNP;
  435. m_psmtbl[PSM_PSMT8].pal = m_psmtbl[PSM_PSMT8H].pal = 256;
  436. m_psmtbl[PSM_PSMT4].pal = m_psmtbl[PSM_PSMT4HL].pal = m_psmtbl[PSM_PSMT4HH].pal = 16;
  437. m_psmtbl[PSM_PSMCT16].bpp = m_psmtbl[PSM_PSMCT16S].bpp = 16;
  438. m_psmtbl[PSM_PSMT8].bpp = 8;
  439. m_psmtbl[PSM_PSMT4].bpp = 4;
  440. m_psmtbl[PSM_PSMZ16].bpp = m_psmtbl[PSM_PSMZ16S].bpp = 16;
  441. m_psmtbl[PSM_PSMCT24].trbpp = 24;
  442. m_psmtbl[PSM_PSMCT16].trbpp = m_psmtbl[PSM_PSMCT16S].trbpp = 16;
  443. m_psmtbl[PSM_PSMT8].trbpp = m_psmtbl[PSM_PSMT8H].trbpp = 8;
  444. m_psmtbl[PSM_PSMT4].trbpp = m_psmtbl[PSM_PSMT4HL].trbpp = m_psmtbl[PSM_PSMT4HH].trbpp = 4;
  445. m_psmtbl[PSM_PSMZ24].trbpp = 24;
  446. m_psmtbl[PSM_PSMZ16].trbpp = m_psmtbl[PSM_PSMZ16S].trbpp = 16;
  447. m_psmtbl[PSM_PSMCT16].bs = m_psmtbl[PSM_PSMCT16S].bs = CSize(16, 8);
  448. m_psmtbl[PSM_PSMT8].bs = CSize(16, 16);
  449. m_psmtbl[PSM_PSMT4].bs = CSize(32, 32);
  450. m_psmtbl[PSM_PSMZ16].bs = m_psmtbl[PSM_PSMZ16S].bs = CSize(16, 8);
  451. for(int i = 0; i < 8; i++) m_psmtbl[PSM_PSMCT16].rowOffset[i] = rowOffset16;
  452. for(int i = 0; i < 8; i++) m_psmtbl[PSM_PSMCT16S].rowOffset[i] = rowOffset16S;
  453. for(int i = 0; i < 8; i++) m_psmtbl[PSM_PSMT8].rowOffset[i] = rowOffset8[((i+2)>>2)&1];
  454. for(int i = 0; i < 8; i++) m_psmtbl[PSM_PSMT4].rowOffset[i] = rowOffset4[((i+2)>>2)&1];
  455. for(int i = 0; i < 8; i++) m_psmtbl[PSM_PSMZ32].rowOffset[i] = rowOffset32Z;
  456. for(int i = 0; i < 8; i++) m_psmtbl[PSM_PSMZ24].rowOffset[i] = rowOffset32Z;
  457. for(int i = 0; i < 8; i++) m_psmtbl[PSM_PSMZ16].rowOffset[i] = rowOffset16Z;
  458. for(int i = 0; i < 8; i++) m_psmtbl[PSM_PSMZ16S].rowOffset[i] = rowOffset16SZ;
  459. #ifdef _OPENMP
  460. // need real cpus, with HT it is only going to be slower now
  461. omp_set_num_threads(omp_get_num_procs());
  462. #endif
  463. /*
  464. // return; 
  465. // omp_set_num_threads(2);
  466. //
  467. {
  468. int tmpsize = 1024*1024*2;
  469. BYTE* tmp1 = new BYTE[tmpsize];
  470. BYTE* tmp2 = new BYTE[tmpsize];
  471. for(int i = 0; i < 1024*1024; i++)
  472. ((DWORD*)GetVM())[i] = rand()*0x12345678;
  473. GIFRegTEX0 TEX0;
  474. TEX0.TBP0 = 0;
  475. TEX0.TBW = 16;
  476. GIFRegTEXA TEXA;
  477. TEXA.AEM = 0; // 1
  478. __declspec(align(32)) static DWORD dst[1024*1024];
  479. int nthreads[] = {1,2,4,8};
  480. for(int j = 0; j < countof(nthreads); j++)
  481. {
  482. omp_set_num_threads(nthreads[j]);
  483. clock_t start = clock();
  484. for(int i = 0; i < 1000; i++)
  485. {
  486. unSwizzleTexture32(CRect(0,0,1024,1024), (BYTE*)dst, 1024*4, TEX0, TEXA);
  487. // for(int k = 0; k < tmpsize; k++) tmp2[k] = tmp1[k];
  488. }
  489. clock_t diff = clock() - start;
  490. CString str;
  491. str.Format(_T("%d threads: %d ms"), nthreads[j], diff);
  492. AfxMessageBox(str);
  493. }
  494. omp_set_num_threads(2);
  495. delete [] tmp1;
  496. delete [] tmp2;
  497. }
  498. */
  499. }
  500. GSLocalMemory::~GSLocalMemory()
  501. {
  502. _aligned_free(m_vm8);
  503. _aligned_free(m_pCLUT);
  504. _aligned_free(m_pCLUT32);
  505. _aligned_free(m_pCLUT64);
  506. }
  507. ////////////////////
  508. void GSLocalMemory::RoundDown(CSize& s, CSize bs)
  509. {
  510. s.cx &= ~(bs.cx-1);
  511. s.cy &= ~(bs.cy-1);
  512. }
  513. void GSLocalMemory::RoundUp(CSize& s, CSize bs)
  514. {
  515. s.cx = (s.cx + (bs.cx-1)) & ~(bs.cx-1);
  516. s.cy = (s.cy + (bs.cy-1)) & ~(bs.cy-1);
  517. }
  518. ////////////////////
  519. DWORD __fastcall GSLocalMemory::pageAddress32(int x, int y, DWORD bp, DWORD bw)
  520. {
  521. return ((bp >> 5) + (y >> 5) * bw + (x >> 6)) << 11; 
  522. }
  523. DWORD __fastcall GSLocalMemory::pageAddress16(int x, int y, DWORD bp, DWORD bw)
  524. {
  525. return ((bp >> 5) + (y >> 6) * bw + (x >> 6)) << 12;
  526. }
  527. DWORD __fastcall GSLocalMemory::pageAddress8(int x, int y, DWORD bp, DWORD bw)
  528. {
  529. return ((bp >> 5) + (y >> 6) * ((bw+1)>>1) + (x >> 7)) << 13; 
  530. }
  531. DWORD __fastcall GSLocalMemory::pageAddress4(int x, int y, DWORD bp, DWORD bw)
  532. {
  533. return ((bp >> 5) + (y >> 7) * ((bw+1)>>1) + (x >> 7)) << 14;
  534. }
  535. ////////////////////
  536. DWORD __fastcall GSLocalMemory::blockAddress32(int x, int y, DWORD bp, DWORD bw)
  537. {
  538. DWORD page = bp + (y & ~0x1f) * bw + ((x >> 1) & ~0x1f);
  539. DWORD block = blockTable32[(y >> 3) & 3][(x >> 3) & 7];
  540. return (page + block) << 6;
  541. }
  542. DWORD __fastcall GSLocalMemory::blockAddress16(int x, int y, DWORD bp, DWORD bw)
  543. {
  544. DWORD page = bp + ((y >> 1) & ~0x1f) * bw + ((x >> 1) & ~0x1f); 
  545. DWORD block = blockTable16[(y >> 3) & 7][(x >> 4) & 3];
  546. return (page + block) << 7;
  547. }
  548. DWORD __fastcall GSLocalMemory::blockAddress16S(int x, int y, DWORD bp, DWORD bw)
  549. {
  550. DWORD page = bp + ((y >> 1) & ~0x1f) * bw + ((x >> 1) & ~0x1f); 
  551. DWORD block = blockTable16S[(y >> 3) & 7][(x >> 4) & 3];
  552. return (page + block) << 7;
  553. }
  554. DWORD __fastcall GSLocalMemory::blockAddress8(int x, int y, DWORD bp, DWORD bw)
  555. {
  556. DWORD page = bp + ((y >> 1) & ~0x1f) * ((bw+1)>>1) + ((x >> 2) & ~0x1f); 
  557. DWORD block = blockTable8[(y >> 4) & 3][(x >> 4) & 7];
  558. return (page + block) << 8;
  559. }
  560. DWORD __fastcall GSLocalMemory::blockAddress4(int x, int y, DWORD bp, DWORD bw)
  561. {
  562. DWORD page = bp + ((y >> 2) & ~0x1f) * ((bw+1)>>1) + ((x >> 2) & ~0x1f); 
  563. DWORD block = blockTable4[(y >> 4) & 7][(x >> 5) & 3];
  564. return (page + block) << 9;
  565. }
  566. DWORD __fastcall GSLocalMemory::blockAddress32Z(int x, int y, DWORD bp, DWORD bw)
  567. {
  568. DWORD page = bp + (y & ~0x1f) * bw + ((x >> 1) & ~0x1f); 
  569. DWORD block = blockTable32Z[(y >> 3) & 3][(x >> 3) & 7];
  570. return (page + block) << 6;
  571. }
  572. DWORD __fastcall GSLocalMemory::blockAddress16Z(int x, int y, DWORD bp, DWORD bw)
  573. {
  574. DWORD page = bp + ((y >> 1) & ~0x1f) * bw + ((x >> 1) & ~0x1f); 
  575. DWORD block = blockTable16Z[(y >> 3) & 7][(x >> 4) & 3];
  576. return (page + block) << 7;
  577. }
  578. DWORD __fastcall GSLocalMemory::blockAddress16SZ(int x, int y, DWORD bp, DWORD bw)
  579. {
  580. DWORD page = bp + ((y >> 1) & ~0x1f) * bw + ((x >> 1) & ~0x1f); 
  581. DWORD block = blockTable16SZ[(y >> 3) & 7][(x >> 4) & 3];
  582. return (page + block) << 7;
  583. }
  584. ////////////////////
  585. DWORD __fastcall GSLocalMemory::pixelAddressOrg32(int x, int y, DWORD bp, DWORD bw)
  586. {
  587. // DWORD page = (bp >> 5) + (y >> 5) * bw + (x >> 6); 
  588. // DWORD block = (bp & 0x1f) + blockTable32[(y >> 3) & 3][(x >> 3) & 7];
  589. // DWORD word = (((page << 5) + block) << 6) + columnTable32[y & 7][x & 7];
  590. DWORD page = bp + (y & ~0x1f) * bw + ((x >> 1) & ~0x1f);
  591. DWORD block = blockTable32[(y >> 3) & 3][(x >> 3) & 7];
  592. DWORD word = ((page + block) << 6) + columnTable32[y & 7][x & 7];
  593. ASSERT(word < 1024*1024);
  594. return word;
  595. }
  596. DWORD __fastcall GSLocalMemory::pixelAddressOrg16(int x, int y, DWORD bp, DWORD bw)
  597. {
  598. // DWORD page = (bp >> 5) + (y >> 6) * bw + (x >> 6); 
  599. // DWORD block = (bp & 0x1f) + blockTable16[(y >> 3) & 7][(x >> 4) & 3];
  600. // DWORD word = (((page << 5) + block) << 7) + columnTable16[y & 7][x & 15];
  601. DWORD page = bp + ((y >> 1) & ~0x1f) * bw + ((x >> 1) & ~0x1f); 
  602. DWORD block = blockTable16[(y >> 3) & 7][(x >> 4) & 3];
  603. DWORD word = ((page + block) << 7) + columnTable16[y & 7][x & 15];
  604. ASSERT(word < 1024*1024*2);
  605. return word;
  606. }
  607. DWORD __fastcall GSLocalMemory::pixelAddressOrg16S(int x, int y, DWORD bp, DWORD bw)
  608. {
  609. // DWORD page = (bp >> 5) + (y >> 6) * bw + (x >> 6); 
  610. // DWORD block = (bp & 0x1f) + blockTable16S[(y >> 3) & 7][(x >> 4) & 3];
  611. // DWORD word = (((page << 5) + block) << 7) + columnTable16[y & 7][x & 15];
  612. DWORD page = bp + ((y >> 1) & ~0x1f) * bw + ((x >> 1) & ~0x1f); 
  613. DWORD block = blockTable16S[(y >> 3) & 7][(x >> 4) & 3];
  614. DWORD word = ((page + block) << 7) + columnTable16[y & 7][x & 15];
  615. ASSERT(word < 1024*1024*2);
  616. return word;
  617. }
  618. DWORD __fastcall GSLocalMemory::pixelAddressOrg8(int x, int y, DWORD bp, DWORD bw)
  619. {
  620. // DWORD page = (bp >> 5) + (y >> 6) * ((bw+1)>>1) + (x >> 7); 
  621. // DWORD block = (bp & 0x1f) + blockTable8[(y >> 4) & 3][(x >> 4) & 7];
  622. // DWORD word = (((page << 5) + block) << 8) + columnTable8[y & 15][x & 15];
  623. DWORD page = bp + ((y >> 1) & ~0x1f) * ((bw+1)>>1) + ((x >> 2) & ~0x1f); 
  624. DWORD block = blockTable8[(y >> 4) & 3][(x >> 4) & 7];
  625. DWORD word = ((page + block) << 8) + columnTable8[y & 15][x & 15];
  626. // ASSERT(word < 1024*1024*4);
  627. return word;
  628. }
  629. DWORD __fastcall GSLocalMemory::pixelAddressOrg4(int x, int y, DWORD bp, DWORD bw)
  630. {
  631. // DWORD page = (bp >> 5) + (y >> 7) * ((bw+1)>>1) + (x >> 7);
  632. // DWORD block = (bp & 0x1f) + blockTable4[(y >> 4) & 7][(x >> 5) & 3];
  633. // DWORD word = (((page << 5) + block) << 9) + columnTable4[y & 15][x & 31];
  634. DWORD page = bp + ((y >> 2) & ~0x1f) * ((bw+1)>>1) + ((x >> 2) & ~0x1f); 
  635. DWORD block = blockTable4[(y >> 4) & 7][(x >> 5) & 3];
  636. DWORD word = ((page + block) << 9) + columnTable4[y & 15][x & 31];
  637. ASSERT(word < 1024*1024*8);
  638. return word;
  639. }
  640. DWORD __fastcall GSLocalMemory::pixelAddressOrg32Z(int x, int y, DWORD bp, DWORD bw)
  641. {
  642. // DWORD page = (bp >> 5) + (y >> 5) * bw + (x >> 6); 
  643. // DWORD block = (bp & 0x1f) + blockTable32Z[(y >> 3) & 3][(x >> 3) & 7];
  644. // DWORD word = (((page << 5) + block) << 6) + ((y & 7) << 3) + (x & 7);
  645. DWORD page = bp + (y & ~0x1f) * bw + ((x >> 1) & ~0x1f); 
  646. DWORD block = blockTable32Z[(y >> 3) & 3][(x >> 3) & 7];
  647. DWORD word = ((page + block) << 6) + ((y & 7) << 3) + (x & 7);
  648. ASSERT(word < 1024*1024);
  649. return word;
  650. }
  651. DWORD __fastcall GSLocalMemory::pixelAddressOrg16Z(int x, int y, DWORD bp, DWORD bw)
  652. {
  653. // DWORD page = (bp >> 5) + (y >> 6) * bw + (x >> 6); 
  654. // DWORD block = (bp & 0x1f) + blockTable16Z[(y >> 3) & 7][(x >> 4) & 3];
  655. // DWORD word = (((page << 5) + block) << 7) + ((y & 7) << 4) + (x & 15);
  656. DWORD page = bp + ((y >> 1) & ~0x1f) * bw + ((x >> 1) & ~0x1f); 
  657. DWORD block = blockTable16Z[(y >> 3) & 7][(x >> 4) & 3];
  658. DWORD word = ((page + block) << 7) + ((y & 7) << 4) + (x & 15);
  659. ASSERT(word < 1024*1024*2);
  660. return word;
  661. }
  662. DWORD __fastcall GSLocalMemory::pixelAddressOrg16SZ(int x, int y, DWORD bp, DWORD bw)
  663. {
  664. // DWORD page = (bp >> 5) + (y >> 6) * bw + (x >> 6); 
  665. // DWORD block = (bp & 0x1f) + blockTable16SZ[(y >> 3) & 7][(x >> 4) & 3];
  666. // DWORD word = (((page << 5) + block) << 7) + ((y & 7) << 4) + (x & 15);
  667. DWORD page = bp + ((y >> 1) & ~0x1f) * bw + ((x >> 1) & ~0x1f); 
  668. DWORD block = blockTable16SZ[(y >> 3) & 7][(x >> 4) & 3];
  669. DWORD word = ((page + block) << 7) + ((y & 7) << 4) + (x & 15);
  670. ASSERT(word < 1024*1024*2);
  671. return word;
  672. }
  673. ////////////////////
  674. DWORD __fastcall GSLocalMemory::pixelAddress32(int x, int y, DWORD bp, DWORD bw)
  675. {
  676. DWORD page = (bp >> 5) + (y >> 5) * bw + (x >> 6); 
  677. DWORD word = (page << 11) + pageOffset32[bp & 0x1f][y & 0x1f][x & 0x3f];
  678. ASSERT(word < 1024*1024);
  679. return word;
  680. }
  681. DWORD __fastcall GSLocalMemory::pixelAddress16(int x, int y, DWORD bp, DWORD bw)
  682. {
  683. DWORD page = (bp >> 5) + (y >> 6) * bw + (x >> 6); 
  684. DWORD word = (page << 12) + pageOffset16[bp & 0x1f][y & 0x3f][x & 0x3f];
  685. ASSERT(word < 1024*1024*2);
  686. return word;
  687. }
  688. DWORD __fastcall GSLocalMemory::pixelAddress16S(int x, int y, DWORD bp, DWORD bw)
  689. {
  690. DWORD page = (bp >> 5) + (y >> 6) * bw + (x >> 6); 
  691. DWORD word = (page << 12) + pageOffset16S[bp & 0x1f][y & 0x3f][x & 0x3f];
  692. ASSERT(word < 1024*1024*2);
  693. return word;
  694. }
  695. DWORD __fastcall GSLocalMemory::pixelAddress8(int x, int y, DWORD bp, DWORD bw)
  696. {
  697. DWORD page = (bp >> 5) + (y >> 6) * ((bw+1)>>1) + (x >> 7); 
  698. DWORD word = (page << 13) + pageOffset8[bp & 0x1f][y & 0x3f][x & 0x7f];
  699. ASSERT(word < 1024*1024*4);
  700. return word;
  701. }
  702. DWORD __fastcall GSLocalMemory::pixelAddress4(int x, int y, DWORD bp, DWORD bw)
  703. {
  704. DWORD page = (bp >> 5) + (y >> 7) * ((bw+1)>>1) + (x >> 7);
  705. DWORD word = (page << 14) + pageOffset4[bp & 0x1f][y & 0x7f][x & 0x7f];
  706. ASSERT(word < 1024*1024*8);
  707. return word;
  708. }
  709. DWORD __fastcall GSLocalMemory::pixelAddress32Z(int x, int y, DWORD bp, DWORD bw)
  710. {
  711. DWORD page = (bp >> 5) + (y >> 5) * bw + (x >> 6); 
  712. DWORD word = (page << 11) + pageOffset32Z[bp & 0x1f][y & 0x1f][x & 0x3f];
  713. ASSERT(word < 1024*1024);
  714. return word;
  715. }
  716. DWORD __fastcall GSLocalMemory::pixelAddress16Z(int x, int y, DWORD bp, DWORD bw)
  717. {
  718. DWORD page = (bp >> 5) + (y >> 6) * bw + (x >> 6); 
  719. DWORD word = (page << 12) + pageOffset16Z[bp & 0x1f][y & 0x3f][x & 0x3f];
  720. ASSERT(word < 1024*1024*2);
  721. return word;
  722. }
  723. DWORD __fastcall GSLocalMemory::pixelAddress16SZ(int x, int y, DWORD bp, DWORD bw)
  724. {
  725. DWORD page = (bp >> 5) + (y >> 6) * bw + (x >> 6); 
  726. DWORD word = (page << 12) + pageOffset16SZ[bp & 0x1f][y & 0x3f][x & 0x3f];
  727. ASSERT(word < 1024*1024*2);
  728. return word;
  729. }
  730. ////////////////////
  731. void GSLocalMemory::writePixel32(int x, int y, DWORD c, DWORD bp, DWORD bw)
  732. {
  733. DWORD addr = pixelAddress32(x, y, bp, bw);
  734. m_vm32[addr] = c;
  735. }
  736. void GSLocalMemory::writePixel24(int x, int y, DWORD c, DWORD bp, DWORD bw)
  737. {
  738. DWORD addr = pixelAddress32(x, y, bp, bw);
  739. m_vm32[addr] = (m_vm32[addr] & 0xff000000) | (c & 0x00ffffff);
  740. }
  741. void GSLocalMemory::writePixel16(int x, int y, DWORD c, DWORD bp, DWORD bw)
  742. {
  743. DWORD addr = pixelAddress16(x, y, bp, bw);
  744. m_vm16[addr] = (WORD)c;
  745. }
  746. void GSLocalMemory::writePixel16S(int x, int y, DWORD c, DWORD bp, DWORD bw)
  747. {
  748. DWORD addr = pixelAddress16S(x, y, bp, bw);
  749. m_vm16[addr] = (WORD)c;
  750. }
  751. void GSLocalMemory::writePixel8(int x, int y, DWORD c, DWORD bp, DWORD bw)
  752. {
  753. DWORD addr = pixelAddress8(x, y, bp, bw);
  754. m_vm8[addr] = (BYTE)c;
  755. }
  756. void GSLocalMemory::writePixel8H(int x, int y, DWORD c, DWORD bp, DWORD bw)
  757. {
  758. DWORD addr = pixelAddress32(x, y, bp, bw);
  759. m_vm32[addr] = (m_vm32[addr] & 0x00ffffff) | (c << 24);
  760. }
  761. void GSLocalMemory::writePixel4(int x, int y, DWORD c, DWORD bp, DWORD bw)
  762. {
  763. DWORD addr = pixelAddress4(x, y, bp, bw);
  764. int shift = (addr&1) << 2; addr >>= 1;
  765. m_vm8[addr] = (BYTE)((m_vm8[addr] & (0xf0 >> shift)) | ((c & 0x0f) << shift));
  766. }
  767. void GSLocalMemory::writePixel4HL(int x, int y, DWORD c, DWORD bp, DWORD bw)
  768. {
  769. DWORD addr = pixelAddress32(x, y, bp, bw);
  770. m_vm32[addr] = (m_vm32[addr] & 0xf0ffffff) | ((c & 0x0f) << 24);
  771. }
  772. void GSLocalMemory::writePixel4HH(int x, int y, DWORD c, DWORD bp, DWORD bw)
  773. {
  774. DWORD addr = pixelAddress32(x, y, bp, bw);
  775. m_vm32[addr] = (m_vm32[addr] & 0x0fffffff) | ((c & 0x0f) << 28);
  776. }
  777. void GSLocalMemory::writePixel32Z(int x, int y, DWORD c, DWORD bp, DWORD bw)
  778. {
  779. DWORD addr = pixelAddress32Z(x, y, bp, bw);
  780. m_vm32[addr] = c;
  781. }
  782. void GSLocalMemory::writePixel24Z(int x, int y, DWORD c, DWORD bp, DWORD bw)
  783. {
  784. DWORD addr = pixelAddress32Z(x, y, bp, bw);
  785. m_vm32[addr] = (m_vm32[addr] & 0xff000000) | (c & 0x00ffffff);
  786. }
  787. void GSLocalMemory::writePixel16Z(int x, int y, DWORD c, DWORD bp, DWORD bw)
  788. {
  789. DWORD addr = pixelAddress16Z(x, y, bp, bw);
  790. m_vm16[addr] = (WORD)c;
  791. }
  792. void GSLocalMemory::writePixel16SZ(int x, int y, DWORD c, DWORD bp, DWORD bw)
  793. {
  794. DWORD addr = pixelAddress16SZ(x, y, bp, bw);
  795. m_vm16[addr] = (WORD)c;
  796. }
  797. ////////////////////
  798. void GSLocalMemory::writeFrame16(int x, int y, DWORD c, DWORD bp, DWORD bw)
  799. {
  800. c = ((c>>16)&0x8000)|((c>>9)&0x7c00)|((c>>6)&0x03e0)|((c>>3)&0x001f);
  801. writePixel16(x, y, c, bp, bw);
  802. }
  803. void GSLocalMemory::writeFrame16S(int x, int y, DWORD c, DWORD bp, DWORD bw)
  804. {
  805. c = ((c>>16)&0x8000)|((c>>9)&0x7c00)|((c>>6)&0x03e0)|((c>>3)&0x001f);
  806. writePixel16S(x, y, c, bp, bw);
  807. }
  808. ////////////////////
  809. DWORD GSLocalMemory::readPixel32(int x, int y, DWORD bp, DWORD bw)
  810. {
  811. return m_vm32[pixelAddress32(x, y, bp, bw)];
  812. }
  813. DWORD GSLocalMemory::readPixel24(int x, int y, DWORD bp, DWORD bw)
  814. {
  815. return m_vm32[pixelAddress32(x, y, bp, bw)] & 0x00ffffff;
  816. }
  817. DWORD GSLocalMemory::readPixel16(int x, int y, DWORD bp, DWORD bw)
  818. {
  819. return (DWORD)m_vm16[pixelAddress16(x, y, bp, bw)];
  820. }
  821. DWORD GSLocalMemory::readPixel16S(int x, int y, DWORD bp, DWORD bw)
  822. {
  823. return (DWORD)m_vm16[pixelAddress16S(x, y, bp, bw)];
  824. }
  825. DWORD GSLocalMemory::readPixel8(int x, int y, DWORD bp, DWORD bw)
  826. {
  827. return (DWORD)m_vm8[pixelAddress8(x, y, bp, bw)];
  828. }
  829. DWORD GSLocalMemory::readPixel8H(int x, int y, DWORD bp, DWORD bw)
  830. {
  831. return m_vm32[pixelAddress32(x, y, bp, bw)] >> 24;
  832. }
  833. DWORD GSLocalMemory::readPixel4(int x, int y, DWORD bp, DWORD bw)
  834. {
  835. DWORD addr = pixelAddress4(x, y, bp, bw);
  836. return (m_vm8[addr>>1] >> ((addr&1) << 2)) & 0x0f;
  837. }
  838. DWORD GSLocalMemory::readPixel4HL(int x, int y, DWORD bp, DWORD bw)
  839. {
  840. return (m_vm32[pixelAddress32(x, y, bp, bw)] >> 24) & 0x0f;
  841. }
  842. DWORD GSLocalMemory::readPixel4HH(int x, int y, DWORD bp, DWORD bw)
  843. {
  844. return (m_vm32[pixelAddress32(x, y, bp, bw)] >> 28) & 0x0f;
  845. }
  846. DWORD GSLocalMemory::readPixel32Z(int x, int y, DWORD bp, DWORD bw)
  847. {
  848. return m_vm32[pixelAddress32Z(x, y, bp, bw)];
  849. }
  850. DWORD GSLocalMemory::readPixel24Z(int x, int y, DWORD bp, DWORD bw)
  851. {
  852. return m_vm32[pixelAddress32Z(x, y, bp, bw)] & 0x00ffffff;
  853. }
  854. DWORD GSLocalMemory::readPixel16Z(int x, int y, DWORD bp, DWORD bw)
  855. {
  856. return (DWORD)m_vm16[pixelAddress16Z(x, y, bp, bw)];
  857. }
  858. DWORD GSLocalMemory::readPixel16SZ(int x, int y, DWORD bp, DWORD bw)
  859. {
  860. return (DWORD)m_vm16[pixelAddress16SZ(x, y, bp, bw)];
  861. }
  862. ////////////////////
  863. /*
  864. void GSLocalMemory::writePixel32(DWORD addr, DWORD c)
  865. {
  866. m_vm32[addr] = c;
  867. }
  868. void GSLocalMemory::writePixel24(DWORD addr, DWORD c)
  869. {
  870. m_vm32[addr] = (m_vm32[addr] & 0xff000000) | (c & 0x00ffffff);
  871. }
  872. void GSLocalMemory::writePixel16(DWORD addr, DWORD c)
  873. {
  874. m_vm16[addr] = (WORD)c;
  875. }
  876. void GSLocalMemory::writePixel16S(DWORD addr, DWORD c)
  877. {
  878. m_vm16[addr] = (WORD)c;
  879. }
  880. void GSLocalMemory::writePixel8(DWORD addr, DWORD c)
  881. {
  882. m_vm8[addr] = (BYTE)c;
  883. }
  884. void GSLocalMemory::writePixel8H(DWORD addr, DWORD c)
  885. {
  886. m_vm32[addr] = (m_vm32[addr] & 0x00ffffff) | (c << 24);
  887. }
  888. void GSLocalMemory::writePixel4(DWORD addr, DWORD c)
  889. {
  890. int shift = (addr&1) << 2; addr >>= 1;
  891. m_vm8[addr] = (BYTE)((m_vm8[addr] & (0xf0 >> shift)) | ((c & 0x0f) << shift));
  892. }
  893. void GSLocalMemory::writePixel4HL(DWORD addr, DWORD c)
  894. {
  895. m_vm32[addr] = (m_vm32[addr] & 0xf0ffffff) | ((c & 0x0f) << 24);
  896. }
  897. void GSLocalMemory::writePixel4HH(DWORD addr, DWORD c)
  898. {
  899. m_vm32[addr] = (m_vm32[addr] & 0x0fffffff) | ((c & 0x0f) << 28);
  900. }
  901. void GSLocalMemory::writePixel32Z(DWORD addr, DWORD c)
  902. {
  903. m_vm32[addr] = c;
  904. }
  905. void GSLocalMemory::writePixel24Z(DWORD addr, DWORD c)
  906. {
  907. m_vm32[addr] = (m_vm32[addr] & 0xff000000) | (c & 0x00ffffff);
  908. }
  909. void GSLocalMemory::writePixel16Z(DWORD addr, DWORD c)
  910. {
  911. m_vm16[addr] = (WORD)c;
  912. }
  913. void GSLocalMemory::writePixel16SZ(DWORD addr, DWORD c)
  914. {
  915. m_vm16[addr] = (WORD)c;
  916. }
  917. ////////////////////
  918. void GSLocalMemory::writeFrame16(DWORD addr, DWORD c)
  919. {
  920. writePixel16(addr, ((c>>16)&0x8000)|((c>>9)&0x7c00)|((c>>6)&0x03e0)|((c>>3)&0x001f));
  921. }
  922. void GSLocalMemory::writeFrame16S(DWORD addr, DWORD c)
  923. {
  924. writePixel16S(addr, ((c>>16)&0x8000)|((c>>9)&0x7c00)|((c>>6)&0x03e0)|((c>>3)&0x001f));
  925. }
  926. ////////////////////
  927. DWORD GSLocalMemory::readPixel32(DWORD addr)
  928. {
  929. return m_vm32[addr];
  930. }
  931. DWORD GSLocalMemory::readPixel24(DWORD addr)
  932. {
  933. return m_vm32[addr] & 0x00ffffff;
  934. }
  935. DWORD GSLocalMemory::readPixel16(DWORD addr)
  936. {
  937. return (DWORD)m_vm16[addr];
  938. }
  939. DWORD GSLocalMemory::readPixel16S(DWORD addr)
  940. {
  941. return (DWORD)m_vm16[addr];
  942. }
  943. DWORD GSLocalMemory::readPixel8(DWORD addr)
  944. {
  945. return (DWORD)m_vm8[addr];
  946. }
  947. DWORD GSLocalMemory::readPixel8H(DWORD addr)
  948. {
  949. return m_vm32[addr] >> 24;
  950. }
  951. DWORD GSLocalMemory::readPixel4(DWORD addr)
  952. {
  953. return (m_vm8[addr>>1] >> ((addr&1) << 2)) & 0x0f;
  954. }
  955. DWORD GSLocalMemory::readPixel4HL(DWORD addr)
  956. {
  957. return (m_vm32[addr] >> 24) & 0x0f;
  958. }
  959. DWORD GSLocalMemory::readPixel4HH(DWORD addr)
  960. {
  961. return (m_vm32[addr] >> 28) & 0x0f;
  962. }
  963. DWORD GSLocalMemory::readPixel32Z(DWORD addr)
  964. {
  965. return m_vm32[addr];
  966. }
  967. DWORD GSLocalMemory::readPixel24Z(DWORD addr)
  968. {
  969. return m_vm32[addr] & 0x00ffffff;
  970. }
  971. DWORD GSLocalMemory::readPixel16Z(DWORD addr)
  972. {
  973. return (DWORD)m_vm16[addr];
  974. }
  975. DWORD GSLocalMemory::readPixel16SZ(DWORD addr)
  976. {
  977. return (DWORD)m_vm16[addr];
  978. }
  979. */
  980. ////////////////////
  981. bool GSLocalMemory::FillRect(CRect& r, DWORD c, DWORD psm, DWORD fbp, DWORD fbw)
  982. {
  983. const psmtbl_t& tbl = m_psmtbl[psm];
  984. writePixel wp = tbl.wp;
  985. pixelAddress ba = tbl.ba;
  986. int w = tbl.bs.cx;
  987. int h = tbl.bs.cy;
  988. int bpp = tbl.bpp;
  989. int shift = 0;
  990. switch(bpp)
  991. {
  992. case 32: shift = 0; break;
  993. case 16: shift = 1; c = (c&0xffff)*0x00010001; break;
  994. case 8: shift = 2; c = (c&0xff)*0x01010101; break;
  995. case 4: shift = 3; c = (c&0xf)*0x11111111; break;
  996. }
  997. CRect clip((r.left+(w-1))&~(w-1), (r.top+(h-1))&~(h-1), r.right&~(w-1), r.bottom&~(h-1));
  998. for(int y = r.top; y < clip.top; y++)
  999. for(int x = r.left; x < r.right; x++)
  1000. (this->*wp)(x, y, c, fbp, fbw);
  1001. for(int y = clip.top; y < clip.bottom; y += h)
  1002. {
  1003. for(int ys = y, ye = y + h; ys < ye; ys++)
  1004. {
  1005. for(int x = r.left; x < clip.left; x++)
  1006. (this->*wp)(x, ys, c, fbp, fbw);
  1007. for(int x = clip.right; x < r.right; x++)
  1008. (this->*wp)(x, ys, c, fbp, fbw);
  1009. }
  1010. }
  1011. if(psm == PSM_PSMCT24 || psm == PSM_PSMZ24)
  1012. {
  1013. c &= 0x00ffffff;
  1014. for(int y = clip.top; y < clip.bottom; y += h)
  1015. {
  1016. for(int x = clip.left; x < clip.right; x += w)
  1017. {
  1018. DWORD* p = &m_vm32[ba(x, y, fbp, fbw)];
  1019. for(int i = 0; i < 64; i++)
  1020. p[i] = (p[i]&0xff000000) | c;
  1021. }
  1022. }
  1023. }
  1024. else
  1025. {
  1026. for(int y = clip.top; y < clip.bottom; y += h)
  1027. for(int x = clip.left; x < clip.right; x += w)
  1028. memsetd(&m_vm8[ba(x, y, fbp, fbw) << 2 >> shift], c, 64);
  1029. }
  1030. for(int y = clip.bottom; y < r.bottom; y++)
  1031. for(int x = r.left; x < r.right; x++)
  1032. (this->*wp)(x, y, c, fbp, fbw);
  1033. return(true);
  1034. }
  1035. ////////////////////
  1036. void GSLocalMemory::WriteCLUT(GIFRegTEX0 TEX0, GIFRegTEXCLUT TEXCLUT)
  1037. {
  1038. switch(TEX0.CLD)
  1039. {
  1040. default:
  1041. case 0: return;
  1042. case 1: break;
  1043. case 2: m_CBP[0] = TEX0.CBP; break;
  1044. case 3: m_CBP[1] = TEX0.CBP; break;
  1045. case 4: if(m_CBP[0] == TEX0.CBP) return; break;
  1046. case 5: if(m_CBP[1] == TEX0.CBP) return; break;
  1047. }
  1048. {
  1049. if(!m_fCLUTMayBeDirty && m_prevTEX0.i64 == TEX0.i64 && m_prevTEXCLUT.i64 == TEXCLUT.i64)
  1050. return;
  1051. m_prevTEX0 = TEX0;
  1052. m_prevTEXCLUT = TEXCLUT;
  1053. m_fCLUTMayBeDirty = false;
  1054. }
  1055. DWORD bp = TEX0.CBP;
  1056. DWORD bw = TEX0.CSM == 0 ? 1 : TEXCLUT.CBW;
  1057. WORD* pCLUT = m_pCLUT + (TEX0.CSA<<4);
  1058. // NOTE: TEX0.CPSM == PSM_PSMCT24 is non-standard, KH uses it
  1059. if(TEX0.CSM == 0)
  1060. {
  1061. if(TEX0.CPSM == PSM_PSMCT16 || TEX0.CPSM == PSM_PSMCT16S)
  1062. {
  1063. WORD* vm = &m_vm16[TEX0.CPSM == PSM_PSMCT16 ? blockAddress16(0, 0, bp, bw) : blockAddress16S(0, 0, bp, bw)];
  1064. if(TEX0.PSM == PSM_PSMT8 || TEX0.PSM == PSM_PSMT8H)
  1065. {
  1066. WriteCLUT_T16_I8_CSM1(vm, pCLUT);
  1067. }
  1068. else if(TEX0.PSM == PSM_PSMT4HH || TEX0.PSM == PSM_PSMT4HL || TEX0.PSM == PSM_PSMT4)
  1069. {
  1070. WriteCLUT_T16_I4_CSM1(vm, pCLUT);
  1071. }
  1072. }
  1073. else if(TEX0.CPSM == PSM_PSMCT32 || TEX0.CPSM == PSM_PSMCT24)
  1074. {
  1075. DWORD* vm = &m_vm32[blockAddress32(0, 0, bp, bw)];
  1076. if(TEX0.PSM == PSM_PSMT8 || TEX0.PSM == PSM_PSMT8H)
  1077. {
  1078. WriteCLUT_T32_I8_CSM1(vm, pCLUT);
  1079. }
  1080. else if(TEX0.PSM == PSM_PSMT4HH || TEX0.PSM == PSM_PSMT4HL || TEX0.PSM == PSM_PSMT4)
  1081. {
  1082. WriteCLUT_T32_I4_CSM1(vm, pCLUT);
  1083. }
  1084. }
  1085. }
  1086. else
  1087. {
  1088. readPixel rp = m_psmtbl[TEX0.CPSM].rp;
  1089. int nPaletteEntries = m_psmtbl[TEX0.PSM].pal;
  1090. ASSERT(nPaletteEntries == 0 || TEX0.CPSM == PSM_PSMCT16); // this is the only allowed format for CSM2, but we implement all of them, just in case...
  1091. if(TEX0.CPSM == PSM_PSMCT16 || TEX0.CPSM == PSM_PSMCT16S)
  1092. {
  1093. for(int i = 0; i < nPaletteEntries; i++)
  1094. {
  1095. pCLUT[i] = (WORD)(this->*rp)((TEXCLUT.COU<<4) + i, TEXCLUT.COV, bp, bw);
  1096. }
  1097. }
  1098. else if(TEX0.CPSM == PSM_PSMCT32 || TEX0.CPSM == PSM_PSMCT24)
  1099. {
  1100. for(int i = 0; i < nPaletteEntries; i++)
  1101. {
  1102. DWORD dw = (this->*rp)((TEXCLUT.COU<<4) + i, TEXCLUT.COV, bp, bw);
  1103. pCLUT[i] = (WORD)(dw & 0xffff);
  1104. pCLUT[i+256] = (WORD)(dw >> 16);
  1105. }
  1106. }
  1107. }
  1108. }
  1109. //
  1110. void GSLocalMemory::ReadCLUT(GIFRegTEX0 TEX0, GIFRegTEXA TEXA, DWORD* pCLUT32)
  1111. {
  1112. ASSERT(pCLUT32);
  1113. WORD* pCLUT = m_pCLUT + (TEX0.CSA<<4);
  1114. if(TEX0.CPSM == PSM_PSMCT32)
  1115. {
  1116. switch(TEX0.PSM)
  1117. {
  1118. case PSM_PSMT8:
  1119. case PSM_PSMT8H:
  1120. ReadCLUT32_T32_I8(pCLUT, pCLUT32);
  1121. break;
  1122. case PSM_PSMT4:
  1123. case PSM_PSMT4HL:
  1124. case PSM_PSMT4HH:
  1125. ReadCLUT32_T32_I4(pCLUT, pCLUT32);
  1126. break;
  1127. }
  1128. }
  1129. else if(TEX0.CPSM == PSM_PSMCT16 || TEX0.CPSM == PSM_PSMCT16S)
  1130. {
  1131. switch(TEX0.PSM)
  1132. {
  1133. case PSM_PSMT8:
  1134. case PSM_PSMT8H:
  1135. ReadCLUT32_T16_I8(pCLUT, pCLUT32);
  1136. break;
  1137. case PSM_PSMT4:
  1138. case PSM_PSMT4HL:
  1139. case PSM_PSMT4HH:
  1140. ReadCLUT32_T16_I4(pCLUT, pCLUT32);
  1141. break;
  1142. }
  1143. }
  1144. }
  1145. void GSLocalMemory::SetupCLUT(GIFRegTEX0 TEX0, GIFRegTEXA TEXA)
  1146. {
  1147. // TODO: cache m_pCLUT*
  1148. ReadCLUT(TEX0, TEXA, m_pCLUT32);
  1149. switch(TEX0.PSM)
  1150. {
  1151. case PSM_PSMT4:
  1152. case PSM_PSMT4HL:
  1153. case PSM_PSMT4HH:
  1154. // sse2?
  1155. if(TEX0.CPSM == PSM_PSMCT32)
  1156. {
  1157. for(int j = 0, k = 0; j < 16; j++)
  1158. for(int i = 0; i < 16; i++, k++)
  1159. m_pCLUT64[k] = ((UINT64)m_pCLUT32[j] << 32) | m_pCLUT32[i];
  1160. }
  1161. else
  1162. {
  1163. for(int j = 0, k = 0; j < 16; j++)
  1164. for(int i = 0; i < 16; i++, k++)
  1165. m_pCLUT64[k] = ((UINT64)m_pCLUT32[j] << 16) | (m_pCLUT32[i]&0xffff);
  1166. }
  1167. break;
  1168. }
  1169. }
  1170. //
  1171. void GSLocalMemory::ReadCLUT32(GIFRegTEX0 TEX0, GIFRegTEXA TEXA, DWORD* pCLUT32)
  1172. {
  1173. ASSERT(pCLUT32);
  1174. WORD* pCLUT = m_pCLUT + (TEX0.CSA<<4);
  1175. if(TEX0.CPSM == PSM_PSMCT32)
  1176. {
  1177. switch(TEX0.PSM)
  1178. {
  1179. case PSM_PSMT8:
  1180. case PSM_PSMT8H:
  1181. ReadCLUT32_T32_I8(pCLUT, pCLUT32);
  1182. break;
  1183. case PSM_PSMT4:
  1184. case PSM_PSMT4HL:
  1185. case PSM_PSMT4HH:
  1186. ReadCLUT32_T32_I4(pCLUT, pCLUT32);
  1187. break;
  1188. }
  1189. }
  1190. else if(TEX0.CPSM == PSM_PSMCT16 || TEX0.CPSM == PSM_PSMCT16S)
  1191. {
  1192. Expand16(pCLUT, pCLUT32, m_psmtbl[TEX0.PSM].pal, &TEXA);
  1193. }
  1194. }
  1195. void GSLocalMemory::SetupCLUT32(GIFRegTEX0 TEX0, GIFRegTEXA TEXA)
  1196. {
  1197. // TODO: cache m_pCLUT*
  1198. ReadCLUT32(TEX0, TEXA, m_pCLUT32);
  1199. switch(TEX0.PSM)
  1200. {
  1201. case PSM_PSMT4:
  1202. case PSM_PSMT4HL:
  1203. case PSM_PSMT4HH:
  1204. // sse2?
  1205. for(int j = 0, k = 0; j < 16; j++)
  1206. for(int i = 0; i < 16; i++, k++)
  1207. m_pCLUT64[k] = ((UINT64)m_pCLUT32[j] << 32) | m_pCLUT32[i];
  1208. break;
  1209. }
  1210. }
  1211. void GSLocalMemory::CopyCLUT32(DWORD* pCLUT32, int nPaletteEntries)
  1212. {
  1213. memcpy(pCLUT32, m_pCLUT32, sizeof(DWORD)*nPaletteEntries);
  1214. }
  1215. ////////////////////
  1216. DWORD GSLocalMemory::readTexel32(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1217. {
  1218. return m_vm32[pixelAddress32(x, y, TEX0.TBP0, TEX0.TBW)];
  1219. }
  1220. DWORD GSLocalMemory::readTexel24(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1221. {
  1222. return Expand24To32(m_vm32[pixelAddress32(x, y, TEX0.TBP0, TEX0.TBW)], TEX0.ai32[1]&4, TEXA);
  1223. }
  1224. DWORD GSLocalMemory::readTexel16(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1225. {
  1226. return Expand16To32(m_vm16[pixelAddress16(x, y, TEX0.TBP0, TEX0.TBW)], TEXA);
  1227. }
  1228. DWORD GSLocalMemory::readTexel16S(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1229. {
  1230. return Expand16To32(m_vm16[pixelAddress16S(x, y, TEX0.TBP0, TEX0.TBW)], TEXA);
  1231. }
  1232. DWORD GSLocalMemory::readTexel8(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1233. {
  1234. return m_pCLUT32[readPixel8(x, y, TEX0.TBP0, TEX0.TBW)];
  1235. }
  1236. DWORD GSLocalMemory::readTexel8H(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1237. {
  1238. return m_pCLUT32[readPixel8H(x, y, TEX0.TBP0, TEX0.TBW)];
  1239. }
  1240. DWORD GSLocalMemory::readTexel4(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1241. {
  1242. return m_pCLUT32[readPixel4(x, y, TEX0.TBP0, TEX0.TBW)];
  1243. }
  1244. DWORD GSLocalMemory::readTexel4HL(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1245. {
  1246. return m_pCLUT32[readPixel4HL(x, y, TEX0.TBP0, TEX0.TBW)];
  1247. }
  1248. DWORD GSLocalMemory::readTexel4HH(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1249. {
  1250. return m_pCLUT32[readPixel4HH(x, y, TEX0.TBP0, TEX0.TBW)];
  1251. }
  1252. ////////////////////
  1253. /*
  1254. DWORD GSLocalMemory::readTexel32(DWORD addr, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1255. {
  1256. return m_vm32[addr];
  1257. }
  1258. DWORD GSLocalMemory::readTexel24(DWORD addr, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1259. {
  1260. return Expand24To32(m_vm32[addr], TEX0.ai32[1]&4, TEXA);
  1261. }
  1262. DWORD GSLocalMemory::readTexel16(DWORD addr, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1263. {
  1264. return Expand16To32(m_vm16[addr], TEXA);
  1265. }
  1266. DWORD GSLocalMemory::readTexel16S(DWORD addr, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1267. {
  1268. return Expand16To32(m_vm16[addr], TEXA);
  1269. }
  1270. DWORD GSLocalMemory::readTexel8(DWORD addr, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1271. {
  1272. return m_pCLUT32[readPixel8(addr)];
  1273. }
  1274. DWORD GSLocalMemory::readTexel8H(DWORD addr, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1275. {
  1276. return m_pCLUT32[readPixel8H(addr)];
  1277. }
  1278. DWORD GSLocalMemory::readTexel4(DWORD addr, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1279. {
  1280. return m_pCLUT32[readPixel4(addr)];
  1281. }
  1282. DWORD GSLocalMemory::readTexel4HL(DWORD addr, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1283. {
  1284. return m_pCLUT32[readPixel4HL(addr)];
  1285. }
  1286. DWORD GSLocalMemory::readTexel4HH(DWORD addr, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1287. {
  1288. return m_pCLUT32[readPixel4HH(addr)];
  1289. }
  1290. */
  1291. ////////////////////
  1292. static void SwizzleTextureStep(int& tx, int& ty, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG)
  1293. {
  1294. // if(ty == TRXREG.RRH && tx == TRXPOS.DSAX) ASSERT(0);
  1295. if(++tx == TRXREG.RRW)
  1296. {
  1297. tx = TRXPOS.DSAX;
  1298. ty++;
  1299. }
  1300. }
  1301. #define IsTopLeftAligned(dsax, tx, ty, bw, bh) 
  1302. (((dsax) & ((bw)-1)) == 0 && ((tx) & ((bw)-1)) == 0 && (dsax) == (tx) && ((ty) & ((bh)-1)) == 0)
  1303. void GSLocalMemory::SwizzleTexture32(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG)
  1304. {
  1305. if(TRXREG.RRW == 0) return;
  1306. int tw = TRXREG.RRW, srcpitch = (TRXREG.RRW - TRXPOS.DSAX)*4;
  1307. int th = len / srcpitch;
  1308. bool fTopLeftAligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 8);
  1309. if(!fTopLeftAligned || (tw & 7) || (th & 7) || (len % srcpitch))
  1310. {
  1311. if(fTopLeftAligned && tw >= 8 && th >= 8)
  1312. {
  1313. int twa = tw & ~7;
  1314. int tha = th & ~7;
  1315. len -= tha * srcpitch;
  1316. th -= tha;
  1317. for(int j = 0; j < tha; j += 8)
  1318. {
  1319. for(int x = tx; x < twa; x += 8)
  1320. SwizzleBlock32u((BYTE*)&m_vm32[blockAddress32(x, ty, BITBLTBUF.DBP, BITBLTBUF.DBW)], src + (x - tx)*4, srcpitch);
  1321. for(int i = 0; i < 8; i++, ty++, src += srcpitch)
  1322. for(int x = twa; x < tw; x++)
  1323. writePixel32(x, ty, ((DWORD*)src)[x - tx], BITBLTBUF.DBP, BITBLTBUF.DBW);
  1324. }
  1325. }
  1326. if(len > 0 && tw >= 8 && th >= 2 && IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 2))
  1327. {
  1328. int twa = tw & ~7;
  1329. int tha = th & ~1;
  1330. len -= tha * srcpitch;
  1331. th -= tha;
  1332. for(int j = 0; j < tha; j += 2)
  1333. {
  1334. for(int x = tx; x < twa; x += 8)
  1335. SwizzleColumn32(ty, (BYTE*)&m_vm32[blockAddress32(x, ty&~7, BITBLTBUF.DBP, BITBLTBUF.DBW)], src + (x - tx)*4, srcpitch);
  1336. for(int i = 0; i < 2; i++, ty++, src += srcpitch)
  1337. for(int x = twa; x < tw; x++)
  1338. writePixel32(x, ty, ((DWORD*)src)[x - tx], BITBLTBUF.DBP, BITBLTBUF.DBW);
  1339. }
  1340. }
  1341. SwizzleTextureX(tx, ty, src, len, BITBLTBUF, TRXPOS, TRXREG);
  1342. }
  1343. else
  1344. {
  1345. th += ty;
  1346. if((DWORD_PTR)src & 0xf)
  1347. {
  1348. for(int y = ty; y < th; y += 8, src += srcpitch*8)
  1349. for(int x = tx; x < tw; x += 8)
  1350. SwizzleBlock32u((BYTE*)&m_vm32[blockAddress32(x, y, BITBLTBUF.DBP, BITBLTBUF.DBW)], src + (x - tx)*4, srcpitch);
  1351. }
  1352. else
  1353. {
  1354. for(int y = ty; y < th; y += 8, src += srcpitch*8)
  1355. for(int x = tx; x < tw; x += 8)
  1356. SwizzleBlock32((BYTE*)&m_vm32[blockAddress32(x, y, BITBLTBUF.DBP, BITBLTBUF.DBW)], src + (x - tx)*4, srcpitch);
  1357. }
  1358. ty = th;
  1359. }
  1360. }
  1361. void GSLocalMemory::SwizzleTexture24(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG)
  1362. {
  1363. if(TRXREG.RRW == 0) return;
  1364. int tw = TRXREG.RRW, srcpitch = (TRXREG.RRW - TRXPOS.DSAX)*3;
  1365. int th = len / srcpitch;
  1366. bool fTopLeftAligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 8);
  1367. if(!fTopLeftAligned || (tw & 7) || (th & 7) || (len % srcpitch))
  1368. {
  1369. // TODO
  1370. SwizzleTextureX(tx, ty, src, len, BITBLTBUF, TRXPOS, TRXREG);
  1371. }
  1372. else
  1373. {
  1374. __declspec(align(16)) DWORD block[8*8];
  1375. th += ty;
  1376. for(int y = ty; y < th; y += 8, src += srcpitch*8)
  1377. {
  1378. for(int x = tx; x < tw; x += 8)
  1379. {
  1380. BYTE* s = src + (x - tx)*3;
  1381. DWORD* d = block;
  1382. for(int j = 0, diff = srcpitch - 8*3; j < 8; j++, s += diff, d += 8)
  1383. for(int i = 0; i < 8; i++, s += 3)
  1384. d[i] = (s[2]<<16)|(s[1]<<8)|s[0];
  1385. SwizzleBlock32((BYTE*)&m_vm32[blockAddress32(x, y, BITBLTBUF.DBP, BITBLTBUF.DBW)], (BYTE*)block, sizeof(block)/8, 0x00ffffff);
  1386. }
  1387. }
  1388. ty = th;
  1389. }
  1390. }
  1391. void GSLocalMemory::SwizzleTexture16(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG)
  1392. {
  1393. if(TRXREG.RRW == 0) return;
  1394. int tw = TRXREG.RRW, srcpitch = (TRXREG.RRW - TRXPOS.DSAX)*2;
  1395. int th = len / srcpitch;
  1396. bool fTopLeftAligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 16, 8);
  1397. if(!fTopLeftAligned || (tw & 15) || (th & 7) || (len % srcpitch))
  1398. {
  1399. if(fTopLeftAligned && tw >= 16 && th >= 8)
  1400. {
  1401. int twa = tw & ~15;
  1402. int tha = th & ~7;
  1403. len -= tha * srcpitch;
  1404. th -= tha;
  1405. for(int j = 0; j < tha; j += 8)
  1406. {
  1407. for(int x = tx; x < twa; x += 16)
  1408. SwizzleBlock16u((BYTE*)&m_vm16[blockAddress16(x, ty, BITBLTBUF.DBP, BITBLTBUF.DBW)], src + (x - tx)*2, srcpitch);
  1409. for(int i = 0; i < 8; i++, ty++, src += srcpitch)
  1410. for(int x = twa; x < tw; x++)
  1411. writePixel16(x, ty, ((WORD*)src)[x - tx], BITBLTBUF.DBP, BITBLTBUF.DBW);
  1412. }
  1413. }
  1414. if(len > 0 && tw >= 16 && th >= 2 && IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 16, 2))
  1415. {
  1416. int twa = tw & ~15;
  1417. int tha = th & ~1;
  1418. len -= tha * srcpitch;
  1419. th -= tha;
  1420. for(int j = 0; j < tha; j += 2)
  1421. {
  1422. for(int x = tx; x < twa; x += 16)
  1423. SwizzleColumn16(ty, (BYTE*)&m_vm16[blockAddress16(x, ty&~7, BITBLTBUF.DBP, BITBLTBUF.DBW)], src + (x - tx)*2, srcpitch);
  1424. for(int i = 0; i < 2; i++, ty++, src += srcpitch)
  1425. for(int x = twa; x < tw; x++)
  1426. writePixel16(x, ty, ((WORD*)src)[x - tx], BITBLTBUF.DBP, BITBLTBUF.DBW);
  1427. }
  1428. }
  1429. SwizzleTextureX(tx, ty, src, len, BITBLTBUF, TRXPOS, TRXREG);
  1430. }
  1431. else
  1432. {
  1433. th += ty;
  1434. if((DWORD_PTR)src & 0xf)
  1435. {
  1436. for(int y = ty; y < th; y += 8, src += srcpitch*8)
  1437. for(int x = tx; x < tw; x += 16)
  1438. SwizzleBlock16u((BYTE*)&m_vm16[blockAddress16(x, y, BITBLTBUF.DBP, BITBLTBUF.DBW)], src + (x - tx)*2, srcpitch);
  1439. }
  1440. else
  1441. {
  1442. for(int y = ty; y < th; y += 8, src += srcpitch*8)
  1443. for(int x = tx; x < tw; x += 16)
  1444. SwizzleBlock16((BYTE*)&m_vm16[blockAddress16(x, y, BITBLTBUF.DBP, BITBLTBUF.DBW)], src + (x - tx)*2, srcpitch);
  1445. }
  1446. ty = th;
  1447. }
  1448. }
  1449. void GSLocalMemory::SwizzleTexture16S(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG)
  1450. {
  1451. if(TRXREG.RRW == 0) return;
  1452. int tw = TRXREG.RRW, srcpitch = (TRXREG.RRW - TRXPOS.DSAX)*2;
  1453. int th = len / srcpitch;
  1454. bool fTopLeftAligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 16, 8);
  1455. if(!fTopLeftAligned || (tw & 15) || (th & 7) || (len % srcpitch))
  1456. {
  1457. if(fTopLeftAligned && tw >= 16 && th >= 8)
  1458. {
  1459. int twa = tw & ~15;
  1460. int tha = th & ~7;
  1461. len -= tha * srcpitch;
  1462. th -= tha;
  1463. for(int j = 0; j < tha; j += 8)
  1464. {
  1465. for(int x = tx; x < twa; x += 16)
  1466. SwizzleBlock16u((BYTE*)&m_vm16[blockAddress16S(x, ty, BITBLTBUF.DBP, BITBLTBUF.DBW)], src + (x - tx)*2, srcpitch);
  1467. for(int i = 0; i < 8; i++, ty++, src += srcpitch)
  1468. for(int x = twa; x < tw; x++)
  1469. writePixel16S(x, ty, ((WORD*)src)[x - tx], BITBLTBUF.DBP, BITBLTBUF.DBW);
  1470. }
  1471. }
  1472. if(len > 0 && tw >= 16 && th >= 2 && IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 16, 2))
  1473. {
  1474. int twa = tw & ~15;
  1475. int tha = th & ~1;
  1476. len -= tha * srcpitch;
  1477. th -= tha;
  1478. for(int j = 0; j < tha; j += 2)
  1479. {
  1480. for(int x = tx; x < twa; x += 16)
  1481. SwizzleColumn16(ty, (BYTE*)&m_vm16[blockAddress16S(x, ty&~7, BITBLTBUF.DBP, BITBLTBUF.DBW)], src + (x - tx)*2, srcpitch);
  1482. for(int i = 0; i < 2; i++, ty++, src += srcpitch)
  1483. for(int x = twa; x < tw; x++)
  1484. writePixel16S(x, ty, ((WORD*)src)[x - tx], BITBLTBUF.DBP, BITBLTBUF.DBW);
  1485. }
  1486. }
  1487. SwizzleTextureX(tx, ty, src, len, BITBLTBUF, TRXPOS, TRXREG);
  1488. }
  1489. else
  1490. {
  1491. th += ty;
  1492. if((DWORD_PTR)src & 0xf)
  1493. {
  1494. for(int y = ty; y < th; y += 8, src += srcpitch*8)
  1495. for(int x = tx; x < tw; x += 16)
  1496. SwizzleBlock16((BYTE*)&m_vm16[blockAddress16S(x, y, BITBLTBUF.DBP, BITBLTBUF.DBW)], src + (x - tx)*2, srcpitch);
  1497. }
  1498. else
  1499. {
  1500. for(int y = ty; y < th; y += 8, src += srcpitch*8)
  1501. for(int x = tx; x < tw; x += 16)
  1502. SwizzleBlock16((BYTE*)&m_vm16[blockAddress16S(x, y, BITBLTBUF.DBP, BITBLTBUF.DBW)], src + (x - tx)*2, srcpitch);
  1503. }
  1504. ty = th;
  1505. }
  1506. }
  1507. void GSLocalMemory::SwizzleTexture8(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG)
  1508. {
  1509. if(TRXREG.RRW == 0) return;
  1510. int tw = TRXREG.RRW, srcpitch = TRXREG.RRW - TRXPOS.DSAX;
  1511. int th = len / srcpitch;
  1512. bool fTopLeftAligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 16, 16);
  1513. if(!fTopLeftAligned || (tw & 15) || (th & 15) || (len % srcpitch))
  1514. {
  1515. if(fTopLeftAligned && tw >= 16 && th >= 16)
  1516. {
  1517. int twa = tw & ~15;
  1518. int tha = th & ~15;
  1519. len -= tha * srcpitch;
  1520. th -= tha;
  1521. for(int j = 0; j < tha; j += 16)
  1522. {
  1523. for(int x = tx; x < twa; x += 16)
  1524. SwizzleBlock8u((BYTE*)&m_vm8[blockAddress8(x, ty, BITBLTBUF.DBP, BITBLTBUF.DBW)], src + (x - tx), srcpitch);
  1525. for(int i = 0; i < 16; i++, ty++, src += srcpitch)
  1526. for(int x = twa; x < tw; x++)
  1527. writePixel8(x, ty, src[x - tx], BITBLTBUF.DBP, BITBLTBUF.DBW);
  1528. }
  1529. }
  1530. if(len > 0 && tw >= 16 && th >= 4 && IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 16, 4))
  1531. {
  1532. int twa = tw & ~15;
  1533. int tha = th & ~3;
  1534. len -= tha * srcpitch;
  1535. th -= tha;
  1536. for(int j = 0; j < tha; j += 4)
  1537. {
  1538. for(int x = tx; x < twa; x += 16)
  1539. SwizzleColumn8(ty, (BYTE*)&m_vm8[blockAddress8(x, ty&~15, BITBLTBUF.DBP, BITBLTBUF.DBW)], src + (x - tx), srcpitch);
  1540. for(int i = 0; i < 4; i++, ty++, src += srcpitch)
  1541. for(int x = twa; x < tw; x++)
  1542. writePixel8(x, ty, src[x - tx], BITBLTBUF.DBP, BITBLTBUF.DBW);
  1543. }
  1544. }
  1545. SwizzleTextureX(tx, ty, src, len, BITBLTBUF, TRXPOS, TRXREG);
  1546. }
  1547. else
  1548. {
  1549. th += ty;
  1550. if((DWORD_PTR)src & 0xf)
  1551. {
  1552. for(int y = ty; y < th; y += 16, src += srcpitch*16)
  1553. for(int x = tx; x < tw; x += 16)
  1554. SwizzleBlock8u((BYTE*)&m_vm8[blockAddress8(x, y, BITBLTBUF.DBP, BITBLTBUF.DBW)], src + (x - tx), srcpitch);
  1555. }
  1556. else
  1557. {
  1558. for(int y = ty; y < th; y += 16, src += srcpitch*16)
  1559. for(int x = tx; x < tw; x += 16)
  1560. SwizzleBlock8((BYTE*)&m_vm8[blockAddress8(x, y, BITBLTBUF.DBP, BITBLTBUF.DBW)], src + (x - tx), srcpitch);
  1561. }
  1562. ty = th;
  1563. }
  1564. }
  1565. void GSLocalMemory::SwizzleTexture8H(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG)
  1566. {
  1567. if(TRXREG.RRW == 0) return;
  1568. int tw = TRXREG.RRW, srcpitch = TRXREG.RRW - TRXPOS.DSAX;
  1569. int th = len / srcpitch;
  1570. bool fTopLeftAligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 8);
  1571. if(!fTopLeftAligned || (tw & 7) || (th & 7) || (len % srcpitch))
  1572. {
  1573. // TODO
  1574. SwizzleTextureX(tx, ty, src, len, BITBLTBUF, TRXPOS, TRXREG);
  1575. }
  1576. else
  1577. {
  1578. __declspec(align(16)) DWORD block[8*8];
  1579. th += ty;
  1580. for(int y = ty; y < th; y += 8, src += srcpitch*8)
  1581. {
  1582. for(int x = tx; x < tw; x += 8)
  1583. {
  1584. BYTE* s = src + (x - tx);
  1585. DWORD* d = block;
  1586. for(int j = 0; j < 8; j++, s += srcpitch, d += 8)
  1587. for(int i = 0; i < 8; i++)
  1588. d[i] = s[i] << 24;
  1589. SwizzleBlock32((BYTE*)&m_vm32[blockAddress32(x, y, BITBLTBUF.DBP, BITBLTBUF.DBW)], (BYTE*)block, sizeof(block)/8, 0xff000000);
  1590. }
  1591. }
  1592. ty = th;
  1593. }
  1594. }
  1595. void GSLocalMemory::SwizzleTexture4(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG)
  1596. {
  1597. if(TRXREG.RRW == 0) return;
  1598. int tw = TRXREG.RRW, srcpitch = (TRXREG.RRW - TRXPOS.DSAX)/2;
  1599. int th = len / srcpitch;
  1600. bool fTopLeftAligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 32, 16);
  1601. if(!fTopLeftAligned || (tw & 31) || (th & 15) || (len % srcpitch))
  1602. {
  1603. if(fTopLeftAligned && tw >= 32 && th >= 16)
  1604. {
  1605. int twa = tw & ~31;
  1606. int tha = th & ~15;
  1607. len -= tha * srcpitch;
  1608. th -= tha;
  1609. for(int j = 0; j < tha; j += 16)
  1610. {
  1611. for(int x = tx; x < twa; x += 32)
  1612. SwizzleBlock4u((BYTE*)&m_vm8[blockAddress4(x, ty, BITBLTBUF.DBP, BITBLTBUF.DBW)>>1], src + (x - tx)/2, srcpitch);
  1613. for(int i = 0; i < 16; i++, ty++, src += srcpitch)
  1614. {
  1615. BYTE* s = src + (twa - tx)/2;
  1616. for(int x = twa; x < tw; x += 2, s++)
  1617. {
  1618. writePixel4(x, ty, *s&0xf, BITBLTBUF.DBP, BITBLTBUF.DBW),
  1619. writePixel4(x+1, ty, *s>>4, BITBLTBUF.DBP, BITBLTBUF.DBW);
  1620. }
  1621. }
  1622. }
  1623. }
  1624. if(len > 0 && tw >= 32 && th >= 4 && IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 32, 4))
  1625. {
  1626. int twa = tw & ~31;
  1627. int tha = th & ~3;
  1628. len -= tha * srcpitch;
  1629. th -= tha;
  1630. for(int j = 0; j < tha; j += 4)
  1631. {
  1632. for(int x = tx; x < twa; x += 32)
  1633. SwizzleColumn4(ty, (BYTE*)&m_vm8[blockAddress4(x, ty&~15, BITBLTBUF.DBP, BITBLTBUF.DBW)>>1], src + (x - tx)/2, srcpitch);
  1634. for(int i = 0; i < 4; i++, ty++, src += srcpitch)
  1635. {
  1636. BYTE* s = src + (twa - tx)/2;
  1637. for(int x = twa; x < tw; x += 2, s++)
  1638. {
  1639. writePixel4(x, ty, *s&0xf, BITBLTBUF.DBP, BITBLTBUF.DBW),
  1640. writePixel4(x+1, ty, *s>>4, BITBLTBUF.DBP, BITBLTBUF.DBW);
  1641. }
  1642. }
  1643. }
  1644. }
  1645. SwizzleTextureX(tx, ty, src, len, BITBLTBUF, TRXPOS, TRXREG);
  1646. }
  1647. else
  1648. {
  1649. th += ty;
  1650. if((DWORD_PTR)src & 0xf)
  1651. {
  1652. for(int y = ty; y < th; y += 16, src += srcpitch*16)
  1653. for(int x = tx; x < tw; x += 32)
  1654. SwizzleBlock4u((BYTE*)&m_vm8[blockAddress4(x, y, BITBLTBUF.DBP, BITBLTBUF.DBW)>>1], src + (x - tx)/2, srcpitch);
  1655. }
  1656. else
  1657. {
  1658. for(int y = ty; y < th; y += 16, src += srcpitch*16)
  1659. for(int x = tx; x < tw; x += 32)
  1660. SwizzleBlock4((BYTE*)&m_vm8[blockAddress4(x, y, BITBLTBUF.DBP, BITBLTBUF.DBW)>>1], src + (x - tx)/2, srcpitch);
  1661. }
  1662. ty = th;
  1663. }
  1664. }
  1665. void GSLocalMemory::SwizzleTexture4HL(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG)
  1666. {
  1667. if(TRXREG.RRW == 0) return;
  1668. int tw = TRXREG.RRW, srcpitch = (TRXREG.RRW - TRXPOS.DSAX)/2;
  1669. int th = len / srcpitch;
  1670. bool fTopLeftAligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 8);
  1671. if(!fTopLeftAligned || (tw & 7) || (th & 7) || (len % srcpitch))
  1672. {
  1673. // TODO
  1674. SwizzleTextureX(tx, ty, src, len, BITBLTBUF, TRXPOS, TRXREG);
  1675. }
  1676. else
  1677. {
  1678. __declspec(align(16)) DWORD block[8*8];
  1679. th += ty;
  1680. for(int y = ty; y < th; y += 8, src += srcpitch*8)
  1681. {
  1682. for(int x = tx; x < tw; x += 8)
  1683. {
  1684. BYTE* s = src + (x - tx)/2;
  1685. DWORD* d = block;
  1686. for(int j = 0; j < 8; j++, s += srcpitch, d += 8)
  1687. for(int i = 0; i < 8/2; i++)
  1688. d[i*2] = (s[i]&0x0f) << 24, 
  1689. d[i*2+1] = (s[i]&0xf0) << 20;
  1690. SwizzleBlock32((BYTE*)&m_vm32[blockAddress32(x, y, BITBLTBUF.DBP, BITBLTBUF.DBW)], (BYTE*)block, sizeof(block)/8, 0x0f000000);
  1691. }
  1692. }
  1693. ty = th;
  1694. }
  1695. }
  1696. void GSLocalMemory::SwizzleTexture4HH(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG)
  1697. {
  1698. if(TRXREG.RRW == 0) return;
  1699. int tw = TRXREG.RRW, srcpitch = (TRXREG.RRW - TRXPOS.DSAX)/2;
  1700. int th = len / srcpitch;
  1701. bool fTopLeftAligned = IsTopLeftAligned(TRXPOS.DSAX, tx, ty, 8, 8);
  1702. if(!fTopLeftAligned || (tw & 7) || (th & 7) || (len % srcpitch))
  1703. {
  1704. // TODO
  1705. SwizzleTextureX(tx, ty, src, len, BITBLTBUF, TRXPOS, TRXREG);
  1706. }
  1707. else
  1708. {
  1709. __declspec(align(16)) DWORD block[8*8];
  1710. th += ty;
  1711. for(int y = ty; y < th; y += 8, src += srcpitch*8)
  1712. {
  1713. for(int x = tx; x < tw; x += 8)
  1714. {
  1715. BYTE* s = src + (x - tx)/2;
  1716. DWORD* d = block;
  1717. for(int j = 0; j < 8; j++, s += srcpitch, d += 8)
  1718. for(int i = 0; i < 8/2; i++)
  1719. d[i*2] = (s[i]&0x0f) << 28, 
  1720. d[i*2+1] = (s[i]&0xf0) << 24;
  1721. SwizzleBlock32((BYTE*)&m_vm32[blockAddress32(x, y, BITBLTBUF.DBP, BITBLTBUF.DBW)], (BYTE*)block, sizeof(block)/8, 0xf0000000);
  1722. }
  1723. }
  1724. ty = th;
  1725. }
  1726. }
  1727. void GSLocalMemory::SwizzleTextureX(int& tx, int& ty, BYTE* src, int len, GIFRegBITBLTBUF& BITBLTBUF, GIFRegTRXPOS& TRXPOS, GIFRegTRXREG& TRXREG)
  1728. {
  1729. if(len <= 0) return;
  1730. BYTE* pb = (BYTE*)src;
  1731. WORD* pw = (WORD*)src;
  1732. DWORD* pd = (DWORD*)src;
  1733. // if(ty >= (int)TRXREG.RRH) {ASSERT(0); return;}
  1734. switch(BITBLTBUF.DPSM)
  1735. {
  1736. case PSM_PSMCT32:
  1737. for(len /= 4; len-- > 0; SwizzleTextureStep(tx, ty, TRXPOS, TRXREG), pd++)
  1738. writePixel32(tx, ty, *pd, BITBLTBUF.DBP, BITBLTBUF.DBW);
  1739. break;
  1740. case PSM_PSMCT24:
  1741. for(len /= 3; len-- > 0; SwizzleTextureStep(tx, ty, TRXPOS, TRXREG), pb+=3)
  1742. writePixel24(tx, ty, *(DWORD*)pb, BITBLTBUF.DBP, BITBLTBUF.DBW);
  1743. break;
  1744. case PSM_PSMCT16:
  1745. for(len /= 2; len-- > 0; SwizzleTextureStep(tx, ty, TRXPOS, TRXREG), pw++)
  1746. writePixel16(tx, ty, *pw, BITBLTBUF.DBP, BITBLTBUF.DBW);
  1747. break;
  1748. case PSM_PSMCT16S:
  1749. for(len /= 2; len-- > 0; SwizzleTextureStep(tx, ty, TRXPOS, TRXREG), pw++)
  1750. writePixel16S(tx, ty, *pw, BITBLTBUF.DBP, BITBLTBUF.DBW);
  1751. break;
  1752. case PSM_PSMT8:
  1753. for(; len-- > 0; SwizzleTextureStep(tx, ty, TRXPOS, TRXREG), pb++)
  1754. writePixel8(tx, ty, *pb, BITBLTBUF.DBP, BITBLTBUF.DBW);
  1755. break;
  1756. case PSM_PSMT4:
  1757. for(; len-- > 0; SwizzleTextureStep(tx, ty, TRXPOS, TRXREG), SwizzleTextureStep(tx, ty, TRXPOS, TRXREG), pb++)
  1758. writePixel4(tx, ty, *pb&0xf, BITBLTBUF.DBP, BITBLTBUF.DBW),
  1759. writePixel4(tx+1, ty, *pb>>4, BITBLTBUF.DBP, BITBLTBUF.DBW);
  1760. break;
  1761. case PSM_PSMT8H:
  1762. for(; len-- > 0; SwizzleTextureStep(tx, ty, TRXPOS, TRXREG), pb++)
  1763. writePixel8H(tx, ty, *pb, BITBLTBUF.DBP, BITBLTBUF.DBW);
  1764. break;
  1765. case PSM_PSMT4HL:
  1766. for(; len-- > 0; SwizzleTextureStep(tx, ty, TRXPOS, TRXREG), SwizzleTextureStep(tx, ty, TRXPOS, TRXREG), pb++)
  1767. writePixel4HL(tx, ty, *pb&0xf, BITBLTBUF.DBP, BITBLTBUF.DBW),
  1768. writePixel4HL(tx+1, ty, *pb>>4, BITBLTBUF.DBP, BITBLTBUF.DBW);
  1769. break;
  1770. case PSM_PSMT4HH:
  1771. for(; len-- > 0; SwizzleTextureStep(tx, ty, TRXPOS, TRXREG), SwizzleTextureStep(tx, ty, TRXPOS, TRXREG), pb++)
  1772. writePixel4HH(tx, ty, *pb&0xf, BITBLTBUF.DBP, BITBLTBUF.DBW),
  1773. writePixel4HH(tx+1, ty, *pb>>4, BITBLTBUF.DBP, BITBLTBUF.DBW);
  1774. break;
  1775. case PSM_PSMZ32:
  1776. for(len /= 4; len-- > 0; SwizzleTextureStep(tx, ty, TRXPOS, TRXREG), pd++)
  1777. writePixel32Z(tx, ty, *pd, BITBLTBUF.DBP, BITBLTBUF.DBW);
  1778. break;
  1779. case PSM_PSMZ24:
  1780. for(len /= 3; len-- > 0; SwizzleTextureStep(tx, ty, TRXPOS, TRXREG), pb+=3)
  1781. writePixel24Z(tx, ty, *(DWORD*)pb, BITBLTBUF.DBP, BITBLTBUF.DBW);
  1782. break;
  1783. case PSM_PSMZ16:
  1784. for(len /= 2; len-- > 0; SwizzleTextureStep(tx, ty, TRXPOS, TRXREG), pw++)
  1785. writePixel16Z(tx, ty, *pw, BITBLTBUF.DBP, BITBLTBUF.DBW);
  1786. break;
  1787. case PSM_PSMZ16S:
  1788. for(len /= 2; len-- > 0; SwizzleTextureStep(tx, ty, TRXPOS, TRXREG), pw++)
  1789. writePixel16SZ(tx, ty, *pw, BITBLTBUF.DBP, BITBLTBUF.DBW);
  1790. break;
  1791. }
  1792. }
  1793. ///////////////////
  1794. void GSLocalMemory::unSwizzleTexture32(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1795. {
  1796. #pragma omp parallel
  1797. {
  1798. #pragma omp for
  1799. FOREACH_BLOCK_START(r, 8, 8, 32)
  1800. {
  1801. unSwizzleBlock32((BYTE*)&m_vm32[blockAddress32(x, y, TEX0.TBP0, TEX0.TBW)], ptr + (x-r.left)*4, dstpitch);
  1802. }
  1803. FOREACH_BLOCK_END
  1804. }
  1805. }
  1806. void GSLocalMemory::unSwizzleTexture24(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1807. {
  1808. #pragma omp parallel
  1809. {
  1810. #pragma omp for
  1811. FOREACH_BLOCK_START(r, 8, 8, 32)
  1812. {
  1813. __declspec(align(16)) DWORD block[8*8];
  1814. unSwizzleBlock32((BYTE*)&m_vm32[blockAddress32(x, y, TEX0.TBP0, TEX0.TBW)], (BYTE*)block, sizeof(block)/8);
  1815. ExpandBlock24(block, (DWORD*)ptr + (x-r.left), dstpitch, &TEXA);
  1816. }
  1817. FOREACH_BLOCK_END
  1818. }
  1819. }
  1820. void GSLocalMemory::unSwizzleTexture16(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1821. {
  1822. #pragma omp parallel
  1823. {
  1824. #pragma omp for
  1825. FOREACH_BLOCK_START(r, 16, 8, 16)
  1826. {
  1827. __declspec(align(16)) WORD block[16*8];
  1828. unSwizzleBlock16((BYTE*)&m_vm16[blockAddress16(x, y, TEX0.TBP0, TEX0.TBW)], (BYTE*)block, sizeof(block)/8);
  1829. ExpandBlock16(block, (DWORD*)ptr + (x-r.left), dstpitch, &TEXA);
  1830. }
  1831. FOREACH_BLOCK_END
  1832. }
  1833. }
  1834. void GSLocalMemory::unSwizzleTexture16S(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1835. {
  1836. #pragma omp parallel
  1837. {
  1838. #pragma omp for
  1839. FOREACH_BLOCK_START(r, 16, 8, 16S)
  1840. {
  1841. __declspec(align(16)) WORD block[16*8];
  1842. unSwizzleBlock16((BYTE*)&m_vm16[blockAddress16S(x, y, TEX0.TBP0, TEX0.TBW)], (BYTE*)block, sizeof(block)/8);
  1843. ExpandBlock16(block, (DWORD*)ptr + (x-r.left), dstpitch, &TEXA);
  1844. }
  1845. FOREACH_BLOCK_END
  1846. }
  1847. }
  1848. void GSLocalMemory::unSwizzleTexture8(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1849. {
  1850. #pragma omp parallel
  1851. {
  1852. #pragma omp for
  1853. FOREACH_BLOCK_START(r, 16, 16, 8)
  1854. {
  1855. __declspec(align(16)) BYTE block[16*16];
  1856. unSwizzleBlock8((BYTE*)&m_vm8[blockAddress8(x, y, TEX0.TBP0, TEX0.TBW)], (BYTE*)block, sizeof(block)/16);
  1857. BYTE* s = block;
  1858. BYTE* d = ptr + (x-r.left)*4;
  1859. for(int j = 0; j < 16; j++, s += 16, d += dstpitch)
  1860. for(int i = 0; i < 16; i++)
  1861. ((DWORD*)d)[i] = m_pCLUT32[s[i]];
  1862. }
  1863. FOREACH_BLOCK_END
  1864. }
  1865. }
  1866. void GSLocalMemory::unSwizzleTexture8H(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1867. {
  1868. #pragma omp parallel
  1869. {
  1870. #pragma omp for
  1871. FOREACH_BLOCK_START(r, 8, 8, 32)
  1872. {
  1873. __declspec(align(16)) DWORD block[8*8];
  1874. unSwizzleBlock32((BYTE*)&m_vm32[blockAddress32(x, y, TEX0.TBP0, TEX0.TBW)], (BYTE*)block, sizeof(block)/8);
  1875. DWORD* s = block;
  1876. BYTE* d = ptr + (x-r.left)*4;
  1877. for(int j = 0; j < 8; j++, s += 8, d += dstpitch)
  1878. for(int i = 0; i < 8; i++)
  1879. ((DWORD*)d)[i] = m_pCLUT32[s[i] >> 24];
  1880. }
  1881. FOREACH_BLOCK_END
  1882. }
  1883. }
  1884. void GSLocalMemory::unSwizzleTexture4(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1885. {
  1886. #pragma omp parallel
  1887. {
  1888. #pragma omp for
  1889. FOREACH_BLOCK_START(r, 32, 16, 4)
  1890. {
  1891. __declspec(align(16)) BYTE block[(32/2)*16];
  1892. unSwizzleBlock4((BYTE*)&m_vm8[blockAddress4(x, y, TEX0.TBP0, TEX0.TBW)>>1], (BYTE*)block, sizeof(block)/16);
  1893. BYTE* s = block;
  1894. BYTE* d = ptr + (x-r.left)*4;
  1895. for(int j = 0; j < 16; j++, s += 32/2, d += dstpitch)
  1896. for(int i = 0; i < 32/2; i++)
  1897. ((UINT64*)d)[i] = m_pCLUT64[s[i]];
  1898. }
  1899. FOREACH_BLOCK_END
  1900. }
  1901. }
  1902. void GSLocalMemory::unSwizzleTexture4HL(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1903. {
  1904. #pragma omp parallel
  1905. {
  1906. #pragma omp for
  1907. FOREACH_BLOCK_START(r, 8, 8, 32)
  1908. {
  1909. __declspec(align(16)) DWORD block[8*8];
  1910. unSwizzleBlock32((BYTE*)&m_vm32[blockAddress32(x, y, TEX0.TBP0, TEX0.TBW)], (BYTE*)block, sizeof(block)/8);
  1911. DWORD* s = block;
  1912. BYTE* d = ptr + (x-r.left)*4;
  1913. for(int j = 0; j < 8; j++, s += 8, d += dstpitch)
  1914. for(int i = 0; i < 8; i++)
  1915. ((DWORD*)d)[i] = m_pCLUT32[(s[i] >> 24)&0x0f];
  1916. }
  1917. FOREACH_BLOCK_END
  1918. }
  1919. }
  1920. void GSLocalMemory::unSwizzleTexture4HH(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1921. {
  1922. #pragma omp parallel
  1923. {
  1924. #pragma omp for
  1925. FOREACH_BLOCK_START(r, 8, 8, 32)
  1926. {
  1927. __declspec(align(16)) DWORD block[8*8];
  1928. unSwizzleBlock32((BYTE*)&m_vm32[blockAddress32(x, y, TEX0.TBP0, TEX0.TBW)], (BYTE*)block, sizeof(block)/8);
  1929. DWORD* s = block;
  1930. BYTE* d = ptr + (x-r.left)*4;
  1931. for(int j = 0; j < 8; j++, s += 8, d += dstpitch)
  1932. for(int i = 0; i < 8; i++)
  1933. ((DWORD*)d)[i] = m_pCLUT32[s[i] >> 28];
  1934. }
  1935. FOREACH_BLOCK_END
  1936. }
  1937. }
  1938. ///////////////////
  1939. void GSLocalMemory::ReadTexture(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA, GIFRegCLAMP& CLAMP)
  1940. {
  1941. unSwizzleTexture st = m_psmtbl[TEX0.PSM].ust;
  1942. readTexel rt = m_psmtbl[TEX0.PSM].rt;
  1943. CSize bs = m_psmtbl[TEX0.PSM].bs;
  1944. if(r.Width() < bs.cx || r.Height() < bs.cy 
  1945. || (r.left & (bs.cx-1)) || (r.top & (bs.cy-1)) 
  1946. || (r.right & (bs.cx-1)) || (r.bottom & (bs.cy-1)) 
  1947. || (CLAMP.WMS&2) || (CLAMP.WMT&2))
  1948. {
  1949. ReadTexture<DWORD>(r, dst, dstpitch, TEX0, TEXA, CLAMP, rt, st);
  1950. }
  1951. else
  1952. {
  1953. (this->*st)(r, dst, dstpitch, TEX0, TEXA);
  1954. }
  1955. }
  1956. ////////////////////
  1957. DWORD GSLocalMemory::readTexel16P(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1958. {
  1959. return readPixel16(x, y, TEX0.TBP0, TEX0.TBW);
  1960. }
  1961. DWORD GSLocalMemory::readTexel16SP(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1962. {
  1963. return readPixel16S(x, y, TEX0.TBP0, TEX0.TBW);
  1964. }
  1965. DWORD GSLocalMemory::readTexel8P(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1966. {
  1967. return readPixel8(x, y, TEX0.TBP0, TEX0.TBW);
  1968. }
  1969. DWORD GSLocalMemory::readTexel8HP(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1970. {
  1971. return readPixel8H(x, y, TEX0.TBP0, TEX0.TBW);
  1972. }
  1973. DWORD GSLocalMemory::readTexel4P(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1974. {
  1975. return readPixel4(x, y, TEX0.TBP0, TEX0.TBW);
  1976. }
  1977. DWORD GSLocalMemory::readTexel4HLP(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1978. {
  1979. return readPixel4HL(x, y, TEX0.TBP0, TEX0.TBW);
  1980. }
  1981. DWORD GSLocalMemory::readTexel4HHP(int x, int y, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1982. {
  1983. return readPixel4HH(x, y, TEX0.TBP0, TEX0.TBW);
  1984. }
  1985. ///////////////////
  1986. void GSLocalMemory::unSwizzleTexture16P(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1987. {
  1988. #pragma omp parallel
  1989. {
  1990. #pragma omp for
  1991. FOREACH_BLOCK_START(r, 16, 8, 16)
  1992. {
  1993. unSwizzleBlock16((BYTE*)&m_vm16[blockAddress16(x, y, TEX0.TBP0, TEX0.TBW)], ptr + (x-r.left)*2, dstpitch);
  1994. }
  1995. FOREACH_BLOCK_END
  1996. }
  1997. }
  1998. void GSLocalMemory::unSwizzleTexture16SP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  1999. {
  2000. #pragma omp parallel
  2001. {
  2002. #pragma omp for
  2003. FOREACH_BLOCK_START(r, 16, 8, 16S)
  2004. {
  2005. unSwizzleBlock16((BYTE*)&m_vm16[blockAddress16S(x, y, TEX0.TBP0, TEX0.TBW)], ptr + (x-r.left)*2, dstpitch);
  2006. }
  2007. FOREACH_BLOCK_END
  2008. }
  2009. }
  2010. void GSLocalMemory::unSwizzleTexture8P(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  2011. {
  2012. #pragma omp parallel
  2013. {
  2014. #pragma omp for
  2015. FOREACH_BLOCK_START(r, 16, 16, 8)
  2016. {
  2017. unSwizzleBlock8((BYTE*)&m_vm8[blockAddress8(x, y, TEX0.TBP0, TEX0.TBW)], ptr + (x-r.left), dstpitch);
  2018. }
  2019. FOREACH_BLOCK_END
  2020. }
  2021. }
  2022. void GSLocalMemory::unSwizzleTexture8HP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  2023. {
  2024. #pragma omp parallel
  2025. {
  2026. #pragma omp for
  2027. FOREACH_BLOCK_START(r, 8, 8, 32)
  2028. {
  2029. unSwizzleBlock8HP((BYTE*)&m_vm32[blockAddress32(x, y, TEX0.TBP0, TEX0.TBW)], ptr + (x-r.left), dstpitch);
  2030. }
  2031. FOREACH_BLOCK_END
  2032. }
  2033. }
  2034. void GSLocalMemory::unSwizzleTexture4P(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  2035. {
  2036. #pragma omp parallel
  2037. {
  2038. #pragma omp for
  2039. FOREACH_BLOCK_START(r, 32, 16, 4)
  2040. {
  2041. unSwizzleBlock4P((BYTE*)&m_vm8[blockAddress4(x, y, TEX0.TBP0, TEX0.TBW)>>1], ptr + (x-r.left), dstpitch);
  2042. }
  2043. FOREACH_BLOCK_END
  2044. }
  2045. }
  2046. void GSLocalMemory::unSwizzleTexture4HLP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  2047. {
  2048. #pragma omp parallel
  2049. {
  2050. #pragma omp for
  2051. FOREACH_BLOCK_START(r, 8, 8, 32)
  2052. {
  2053. unSwizzleBlock4HLP((BYTE*)&m_vm32[blockAddress32(x, y, TEX0.TBP0, TEX0.TBW)], ptr + (x-r.left), dstpitch);
  2054. }
  2055. FOREACH_BLOCK_END
  2056. }
  2057. }
  2058. void GSLocalMemory::unSwizzleTexture4HHP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  2059. {
  2060. #pragma omp parallel
  2061. {
  2062. #pragma omp for
  2063. FOREACH_BLOCK_START(r, 8, 8, 32)
  2064. {
  2065. unSwizzleBlock4HHP((BYTE*)&m_vm32[blockAddress32(x, y, TEX0.TBP0, TEX0.TBW)], ptr + (x-r.left), dstpitch);
  2066. }
  2067. FOREACH_BLOCK_END
  2068. }
  2069. }
  2070. ///////////////////
  2071. void GSLocalMemory::ReadTextureP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA, GIFRegCLAMP& CLAMP)
  2072. {
  2073. unSwizzleTexture st = m_psmtbl[TEX0.PSM].ustP;
  2074. readTexel rt = m_psmtbl[TEX0.PSM].rtP;
  2075. CSize bs = m_psmtbl[TEX0.PSM].bs;
  2076. if(r.Width() < bs.cx || r.Height() < bs.cy 
  2077. || (r.left & (bs.cx-1)) || (r.top & (bs.cy-1)) 
  2078. || (r.right & (bs.cx-1)) || (r.bottom & (bs.cy-1)) 
  2079. || (CLAMP.WMS&2) || (CLAMP.WMT&2))
  2080. {
  2081. switch(TEX0.PSM)
  2082. {
  2083. default:
  2084. case PSM_PSMCT32:
  2085. case PSM_PSMCT24:
  2086. ReadTexture<DWORD>(r, dst, dstpitch, TEX0, TEXA, CLAMP, rt, st);
  2087. break;
  2088. case PSM_PSMCT16:
  2089. case PSM_PSMCT16S:
  2090. ReadTexture<WORD>(r, dst, dstpitch, TEX0, TEXA, CLAMP, rt, st);
  2091. break;
  2092. case PSM_PSMT8:
  2093. case PSM_PSMT8H:
  2094. case PSM_PSMT4:
  2095. case PSM_PSMT4HL:
  2096. case PSM_PSMT4HH:
  2097. ReadTexture<BYTE>(r, dst, dstpitch, TEX0, TEXA, CLAMP, rt, st);
  2098. break;
  2099. }
  2100. }
  2101. else
  2102. {
  2103. (this->*st)(r, dst, dstpitch, TEX0, TEXA);
  2104. }
  2105. }
  2106. ///////////////////
  2107. void GSLocalMemory::unSwizzleTexture8NP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  2108. {
  2109. #pragma omp parallel
  2110. {
  2111. #pragma omp for
  2112. FOREACH_BLOCK_START(r, 16, 16, 8)
  2113. {
  2114. __declspec(align(16)) BYTE block[16*16];
  2115. unSwizzleBlock8((BYTE*)&m_vm8[blockAddress8(x, y, TEX0.TBP0, TEX0.TBW)], (BYTE*)block, sizeof(block)/16);
  2116. BYTE* s = block;
  2117. if(TEX0.CPSM == PSM_PSMCT32)
  2118. {
  2119. BYTE* d = ptr + (x-r.left)*4;
  2120. for(int j = 0; j < 16; j++, s += 16, d += dstpitch)
  2121. for(int i = 0; i < 16; i++)
  2122. ((DWORD*)d)[i] = m_pCLUT32[s[i]];
  2123. }
  2124. else
  2125. {
  2126. BYTE* d = ptr + (x-r.left)*2;
  2127. for(int j = 0; j < 16; j++, s += 16, d += dstpitch)
  2128. for(int i = 0; i < 16; i++)
  2129. ((WORD*)d)[i] = (WORD)m_pCLUT32[s[i]];
  2130. }
  2131. }
  2132. FOREACH_BLOCK_END
  2133. }
  2134. }
  2135. void GSLocalMemory::unSwizzleTexture8HNP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  2136. {
  2137. #pragma omp parallel
  2138. {
  2139. #pragma omp for
  2140. FOREACH_BLOCK_START(r, 8, 8, 32)
  2141. {
  2142. __declspec(align(16)) DWORD block[8*8];
  2143. unSwizzleBlock32((BYTE*)&m_vm32[blockAddress32(x, y, TEX0.TBP0, TEX0.TBW)], (BYTE*)block, sizeof(block)/8);
  2144. DWORD* s = block;
  2145. if(TEX0.CPSM == PSM_PSMCT32)
  2146. {
  2147. BYTE* d = ptr + (x-r.left)*4;
  2148. for(int j = 0; j < 8; j++, s += 8, d += dstpitch)
  2149. for(int i = 0; i < 8; i++)
  2150. ((DWORD*)d)[i] = m_pCLUT32[s[i] >> 24];
  2151. }
  2152. else
  2153. {
  2154. BYTE* d = ptr + (x-r.left)*2;
  2155. for(int j = 0; j < 8; j++, s += 8, d += dstpitch)
  2156. for(int i = 0; i < 8; i++)
  2157. ((WORD*)d)[i] = (WORD)m_pCLUT32[s[i] >> 24];
  2158. }
  2159. }
  2160. FOREACH_BLOCK_END
  2161. }
  2162. }
  2163. void GSLocalMemory::unSwizzleTexture4NP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  2164. {
  2165. #pragma omp parallel
  2166. {
  2167. #pragma omp for
  2168. FOREACH_BLOCK_START(r, 32, 16, 4)
  2169. {
  2170. __declspec(align(16)) BYTE block[(32/2)*16];
  2171. unSwizzleBlock4((BYTE*)&m_vm8[blockAddress4(x, y, TEX0.TBP0, TEX0.TBW)>>1], (BYTE*)block, sizeof(block)/16);
  2172. BYTE* s = block;
  2173. if(TEX0.CPSM == PSM_PSMCT32)
  2174. {
  2175. BYTE* d = ptr + (x-r.left)*4;
  2176. for(int j = 0; j < 16; j++, s += 32/2, d += dstpitch)
  2177. for(int i = 0; i < 32/2; i++)
  2178. ((UINT64*)d)[i] = m_pCLUT64[s[i]];
  2179. }
  2180. else
  2181. {
  2182. BYTE* d = ptr + (x-r.left)*2;
  2183. for(int j = 0; j < 16; j++, s += 32/2, d += dstpitch)
  2184. for(int i = 0; i < 32/2; i++)
  2185. ((DWORD*)d)[i] = (DWORD)m_pCLUT64[s[i]];
  2186. }
  2187. }
  2188. FOREACH_BLOCK_END
  2189. }
  2190. }
  2191. void GSLocalMemory::unSwizzleTexture4HLNP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  2192. {
  2193. #pragma omp parallel
  2194. {
  2195. #pragma omp for
  2196. FOREACH_BLOCK_START(r, 8, 8, 32)
  2197. {
  2198. __declspec(align(16)) DWORD block[8*8];
  2199. unSwizzleBlock32((BYTE*)&m_vm32[blockAddress32(x, y, TEX0.TBP0, TEX0.TBW)], (BYTE*)block, sizeof(block)/8);
  2200. DWORD* s = block;
  2201. if(TEX0.CPSM == PSM_PSMCT32)
  2202. {
  2203. BYTE* d = ptr + (x-r.left)*4;
  2204. for(int j = 0; j < 8; j++, s += 8, d += dstpitch)
  2205. for(int i = 0; i < 8; i++)
  2206. ((DWORD*)d)[i] = m_pCLUT32[(s[i] >> 24)&0x0f];
  2207. }
  2208. else
  2209. {
  2210. BYTE* d = ptr + (x-r.left)*2;
  2211. for(int j = 0; j < 8; j++, s += 8, d += dstpitch)
  2212. for(int i = 0; i < 8; i++)
  2213. ((WORD*)d)[i] = (WORD)m_pCLUT32[(s[i] >> 24)&0x0f];
  2214. }
  2215. }
  2216. FOREACH_BLOCK_END
  2217. }
  2218. }
  2219. void GSLocalMemory::unSwizzleTexture4HHNP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA)
  2220. {
  2221. #pragma omp parallel
  2222. {
  2223. #pragma omp for
  2224. FOREACH_BLOCK_START(r, 8, 8, 32)
  2225. {
  2226. __declspec(align(16)) DWORD block[8*8];
  2227. unSwizzleBlock32((BYTE*)&m_vm32[blockAddress32(x, y, TEX0.TBP0, TEX0.TBW)], (BYTE*)block, sizeof(block)/8);
  2228. DWORD* s = block;
  2229. if(TEX0.CPSM == PSM_PSMCT32)
  2230. {
  2231. BYTE* d = ptr + (x-r.left)*4;
  2232. for(int j = 0; j < 8; j++, s += 8, d += dstpitch)
  2233. for(int i = 0; i < 8; i++)
  2234. ((DWORD*)d)[i] = m_pCLUT32[s[i] >> 28];
  2235. }
  2236. else
  2237. {
  2238. BYTE* d = ptr + (x-r.left)*2;
  2239. for(int j = 0; j < 8; j++, s += 8, d += dstpitch)
  2240. for(int i = 0; i < 8; i++)
  2241. ((WORD*)d)[i] = (WORD)m_pCLUT32[s[i] >> 28];
  2242. }
  2243. }
  2244. FOREACH_BLOCK_END
  2245. }
  2246. }
  2247. ///////////////////
  2248. void GSLocalMemory::ReadTextureNP(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA, GIFRegCLAMP& CLAMP)
  2249. {
  2250. unSwizzleTexture st = m_psmtbl[TEX0.PSM].ustNP;
  2251. readTexel rt = m_psmtbl[TEX0.PSM].rtNP;
  2252. CSize bs = m_psmtbl[TEX0.PSM].bs;
  2253. if(r.Width() < bs.cx || r.Height() < bs.cy 
  2254. || (r.left & (bs.cx-1)) || (r.top & (bs.cy-1)) 
  2255. || (r.right & (bs.cx-1)) || (r.bottom & (bs.cy-1)) 
  2256. || (CLAMP.WMS&2) || (CLAMP.WMT&2))
  2257. {
  2258. switch(TEX0.PSM)
  2259. {
  2260. default:
  2261. case PSM_PSMCT32:
  2262. case PSM_PSMCT24:
  2263. ReadTexture<DWORD>(r, dst, dstpitch, TEX0, TEXA, CLAMP, rt, st);
  2264. break;
  2265. case PSM_PSMCT16:
  2266. case PSM_PSMCT16S:
  2267. ReadTexture<WORD>(r, dst, dstpitch, TEX0, TEXA, CLAMP, rt, st);
  2268. break;
  2269. case PSM_PSMT8:
  2270. case PSM_PSMT8H:
  2271. case PSM_PSMT4:
  2272. case PSM_PSMT4HL:
  2273. case PSM_PSMT4HH:
  2274. switch(TEX0.CPSM)
  2275. {
  2276. default:
  2277. case PSM_PSMCT32:
  2278. ReadTexture<DWORD>(r, dst, dstpitch, TEX0, TEXA, CLAMP, rt, st);
  2279. break;
  2280. case PSM_PSMCT16:
  2281. case PSM_PSMCT16S:
  2282. ReadTexture<WORD>(r, dst, dstpitch, TEX0, TEXA, CLAMP, rt, st);
  2283. break;
  2284. }
  2285. break;
  2286. }
  2287. }
  2288. else
  2289. {
  2290. (this->*st)(r, dst, dstpitch, TEX0, TEXA);
  2291. }
  2292. }
  2293. //
  2294. template<typename DstT> 
  2295. void GSLocalMemory::ReadTexture(const CRect& r, BYTE* dst, int dstpitch, GIFRegTEX0& TEX0, GIFRegTEXA& TEXA, GIFRegCLAMP& CLAMP, readTexel rt, unSwizzleTexture st)
  2296. {
  2297. // this function is not thread safe!
  2298. CSize bs = m_psmtbl[TEX0.PSM].bs;
  2299. CRect cr(
  2300. (r.left + (bs.cx-1)) & ~(bs.cx-1), 
  2301. (r.top + (bs.cy-1)) & ~(bs.cy-1), 
  2302. r.right & ~(bs.cx-1), 
  2303. r.bottom & ~(bs.cy-1));
  2304. bool fAligned = ((DWORD_PTR)(dst + (cr.left-r.left)*sizeof(DstT)) & 0xf) == 0;
  2305. if((CLAMP.WMS&2) || (CLAMP.WMT&2))
  2306. {
  2307. DWORD wms = CLAMP.WMS, wmt = CLAMP.WMT;
  2308. DWORD minu = CLAMP.MINU, maxu = CLAMP.MAXU;
  2309. DWORD minv = CLAMP.MINV, maxv = CLAMP.MAXV;
  2310. switch(wms)
  2311. {
  2312. default: for(int x = r.left; x < r.right; x++) m_xtbl[x] = x; break;
  2313. case 2: for(int x = r.left; x < r.right; x++) m_xtbl[x] = x < minu ? minu : x > maxu ? maxu : x; break;
  2314. case 3: for(int x = r.left; x < r.right; x++) m_xtbl[x] = (x & minu) | maxu; break;
  2315. }
  2316. switch(wmt)
  2317. {
  2318. default: for(int y = r.top; y < r.bottom; y++) m_ytbl[y] = y; break;
  2319. case 2: for(int y = r.top; y < r.bottom; y++) m_ytbl[y] = y < minv ? minv : y > maxv ? maxv : y;  break;
  2320. case 3: for(int y = r.top; y < r.bottom; y++) m_ytbl[y] = (y & minv) | maxv; break;
  2321. }
  2322. if(fAligned && wms <= 2 && wmt <= 2)
  2323. {
  2324. // TODO: read clamped areas only once
  2325. for(int y = r.top; y < cr.top; y++, dst += dstpitch)
  2326. for(int x = r.left, i = 0; x < r.right; x++, i++)
  2327. ((DstT*)dst)[i] = (DstT)(this->*rt)(m_xtbl[x], m_ytbl[y], TEX0, TEXA);
  2328. if(!cr.IsRectEmpty())
  2329. (this->*st)(cr, dst + (cr.left - r.left)*sizeof(DstT), dstpitch, TEX0, TEXA);
  2330. for(int y = cr.top; y < cr.bottom; y++, dst += dstpitch)
  2331. {
  2332. for(int x = r.left, i = 0; x < cr.left; x++, i++)
  2333. ((DstT*)dst)[i] = (DstT)(this->*rt)(m_xtbl[x], m_ytbl[y], TEX0, TEXA);
  2334. for(int x = cr.right, i = x - r.left; x < r.right; x++, i++)
  2335. ((DstT*)dst)[i] = (DstT)(this->*rt)(m_xtbl[x], m_ytbl[y], TEX0, TEXA);
  2336. }
  2337. for(int y = cr.bottom; y < r.bottom; y++, dst += dstpitch)
  2338. for(int x = r.left, i = 0; x < r.right; x++, i++)
  2339. ((DstT*)dst)[i] = (DstT)(this->*rt)(m_xtbl[x], m_ytbl[y], TEX0, TEXA);
  2340. }
  2341. else
  2342. {
  2343. for(int y = r.top; y < r.bottom; y++, dst += dstpitch)
  2344. for(int x = r.left, i = 0; x < r.right; x++, i++)
  2345. ((DstT*)dst)[i] = (DstT)(this->*rt)(m_xtbl[x], m_ytbl[y], TEX0, TEXA);
  2346. }
  2347. }
  2348. else
  2349. {
  2350. if(fAligned)
  2351. {
  2352. for(int y = r.top; y < cr.top; y++, dst += dstpitch)
  2353. for(int x = r.left, i = 0; x < r.right; x++, i++)
  2354. ((DstT*)dst)[i] = (DstT)(this->*rt)(x, y, TEX0, TEXA);
  2355. if(!cr.IsRectEmpty())
  2356. (this->*st)(cr, dst + (cr.left - r.left)*sizeof(DstT), dstpitch, TEX0, TEXA);
  2357. for(int y = cr.top; y < cr.bottom; y++, dst += dstpitch)
  2358. {
  2359. for(int x = r.left, i = 0; x < cr.left; x++, i++)
  2360. ((DstT*)dst)[i] = (DstT)(this->*rt)(x, y, TEX0, TEXA);
  2361. for(int x = cr.right, i = x - r.left; x < r.right; x++, i++)
  2362. ((DstT*)dst)[i] = (DstT)(this->*rt)(x, y, TEX0, TEXA);
  2363. }
  2364. for(int y = cr.bottom; y < r.bottom; y++, dst += dstpitch)
  2365. for(int x = r.left, i = 0; x < r.right; x++, i++)
  2366. ((DstT*)dst)[i] = (DstT)(this->*rt)(x, y, TEX0, TEXA);
  2367. }
  2368. else
  2369. {
  2370. for(int y = r.top; y < r.bottom; y++, dst += dstpitch)
  2371. for(int x = r.left, i = 0; x < r.right; x++, i++)
  2372. ((DstT*)dst)[i] = (DstT)(this->*rt)(x, y, TEX0, TEXA);
  2373. }
  2374. }
  2375. }
  2376. //
  2377. HRESULT GSLocalMemory::SaveBMP(IDirect3DDevice9* pDev, LPCTSTR fn, DWORD bp, DWORD bw, DWORD psm, int w, int h)
  2378. {
  2379. CComPtr<IDirect3DTexture9> pTexture;
  2380. D3DLOCKED_RECT lr;
  2381. HRESULT hr = pDev->CreateTexture(w, h, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &pTexture, NULL);
  2382. if(FAILED(hr) || FAILED(pTexture->LockRect(0, &lr, NULL, 0))) return E_FAIL;
  2383. readTexel rt = m_psmtbl[psm].rt;
  2384. GIFRegTEX0 TEX0;
  2385. TEX0.TBP0 = bp;
  2386. TEX0.TBW = bw;
  2387. TEX0.PSM = psm;
  2388. GIFRegTEXA TEXA;
  2389. TEXA.AEM = 0;
  2390. TEXA.TA0 = 0;
  2391. TEXA.TA1 = 0x80;
  2392. BYTE* p = (BYTE*)lr.pBits;
  2393. for(int j = 0; j < h; j++, p += lr.Pitch)
  2394. for(int i = 0; i < w; i++)
  2395. ((DWORD*)p)[i] = (this->*rt)(i, j, TEX0, TEXA);
  2396. pTexture->UnlockRect(0);
  2397. return D3DXSaveTextureToFile(fn, D3DXIFF_BMP, pTexture, NULL);
  2398. }