PageRenderTime 56ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/ogc_patches/gx.c

http://mupen64gc.googlecode.com/
C | 2808 lines | 2369 code | 420 blank | 19 comment | 268 complexity | e97ff188087c22c526bbe6f761f3fcea MD5 | raw file
Possible License(s): GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <errno.h>
  4. #include <math.h>
  5. #include "asm.h"
  6. #include "processor.h"
  7. #include "irq.h"
  8. #include "lwp.h"
  9. #include "system.h"
  10. #include "video.h"
  11. #include "video_types.h"
  12. #include "lwp_watchdog.h"
  13. #include "gx.h"
  14. //#define _GP_DEBUG
  15. #define GX_FINISH 2
  16. #define BIG_NUMBER (1024*1024)
  17. #define WGPIPE (0xCC008000)
  18. #define _SHIFTL(v, s, w) \
  19. ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
  20. #define _SHIFTR(v, s, w) \
  21. ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
  22. #define FIFO_PUTU8(x) *(vu8*)WGPIPE = (u8)(x)
  23. #define FIFO_PUTS8(x) *(vs8*)WGPIPE = (s8)(x)
  24. #define FIFO_PUTU16(x) *(vu16*)WGPIPE = (u16)(x)
  25. #define FIFO_PUTS16(x) *(vs16*)WGPIPE = (s16)(x)
  26. #define FIFO_PUTU32(x) *(vu32*)WGPIPE = (u32)(x)
  27. #define FIFO_PUTS32(x) *(vs32*)WGPIPE = (s32)(x)
  28. #define FIFO_PUTF32(x) *(vf32*)WGPIPE = (f32)(x)
  29. #define GX_LOAD_BP_REG(x) \
  30. do { \
  31. FIFO_PUTU8(0x61); \
  32. FIFO_PUTU32((x)); \
  33. } while(0)
  34. #define GX_LOAD_CP_REG(x, y) \
  35. do { \
  36. FIFO_PUTU8(0x08); \
  37. FIFO_PUTU8((x)); \
  38. FIFO_PUTU32((y)); \
  39. } while(0)
  40. #define GX_LOAD_XF_REG(x, y) \
  41. do { \
  42. FIFO_PUTU8(0x10); \
  43. FIFO_PUTU32(((x)&0xffff)); \
  44. FIFO_PUTU32((y)); \
  45. } while(0)
  46. #define GX_LOAD_XF_REGS(x, n) \
  47. do { \
  48. FIFO_PUTU8(0x10); \
  49. FIFO_PUTU32((((((n)&0xffff)-1)<<16)|((x)&0xffff))); \
  50. } while(0)
  51. #define XY(x, y) (((y) << 10) | (x))
  52. #define GX_DEFAULT_BG {64,64,64,255}
  53. #define BLACK {0,0,0,0}
  54. #define WHITE {255,255,255,255}
  55. struct __gxfifo {
  56. u32 buf_start;
  57. u32 buf_end;
  58. u32 size;
  59. u32 hi_mark;
  60. u32 lo_mark;
  61. u32 rd_ptr;
  62. u32 wt_ptr;
  63. u32 rdwt_dst;
  64. u8 pad0[96];
  65. };
  66. static GXFifoObj _gxdefiniobj;
  67. static void *_gxcurrbp = NULL;
  68. static lwp_t _gxcurrentlwp = LWP_THREAD_NULL;
  69. static u8 _gxcpufifoready = 0;
  70. static u8 _gxgpfifoready = 0;
  71. static u8 _cpgplinked = 0;
  72. static u16 _gxgpstatus = 0;
  73. static vu32 _gxoverflowsuspend = 0;
  74. static vu32 _gxoverflowcount = 0;
  75. static vu32 _gxfinished = 0;
  76. static lwpq_t _gxwaitfinish;
  77. static struct __gxfifo *_gpfifo = NULL;
  78. static struct __gxfifo *_cpufifo = NULL;
  79. static GXFifoObj *_gxoldcpufifo = NULL;
  80. static GXBreakPtCallback breakPtCB = NULL;
  81. static GXDrawDoneCallback drawDoneCB = NULL;
  82. static GXDrawSyncCallback tokenCB = NULL;
  83. static GXTexRegionCallback regionCB = NULL;
  84. static GXTlutRegionCallback tlut_regionCB = NULL;
  85. static vu32* const _piReg = (u32*)0xCC003000;
  86. static vu16* const _cpReg = (u16*)0xCC000000;
  87. static vu16* const _peReg = (u16*)0xCC001000;
  88. static vu16* const _memReg = (u16*)0xCC004000;
  89. static u8 _gxtevcolid[9] = {0,1,0,1,0,1,7,5,6};
  90. static u8 _gxtexmode0ids[8] = {0x80,0x81,0x82,0x83,0xA0,0xA1,0xA2,0xA3};
  91. static u8 _gxtexmode1ids[8] = {0x84,0x85,0x86,0x87,0xA4,0xA5,0xA6,0xA7};
  92. static u8 _gxteximg0ids[8] = {0x88,0x89,0x8A,0x8B,0xA8,0xA9,0xAA,0xAB};
  93. static u8 _gxteximg1ids[8] = {0x8C,0x8D,0x8E,0x8F,0xAC,0xAD,0xAE,0xAF};
  94. static u8 _gxteximg2ids[8] = {0x90,0x91,0x92,0x93,0xB0,0xB1,0xB2,0xB3};
  95. static u8 _gxteximg3ids[8] = {0x94,0x95,0x96,0x97,0xB4,0xB5,0xB6,0xB7};
  96. static u8 _gxtextlutids[8] = {0x98,0x99,0x9A,0x9B,0xB8,0xB9,0xBA,0xBB};
  97. #ifdef TEXCACHE_TESTING
  98. static u32 _gxtexregionaddrtable[48] =
  99. {
  100. 0x00000000,0x00010000,0x00020000,0x00030000,
  101. 0x00040000,0x00050000,0x00060000,0x00070000,
  102. 0x00008000,0x00018000,0x00028000,0x00038000,
  103. 0x00048000,0x00058000,0x00068000,0x00078000,
  104. 0x00000000,0x00090000,0x00020000,0x000B0000,
  105. 0x00040000,0x00098000,0x00060000,0x000B8000,
  106. 0x00080000,0x00010000,0x000A0000,0x00030000,
  107. 0x00088000,0x00050000,0x000A8000,0x00070000,
  108. 0x00000000,0x00090000,0x00020000,0x000B0000,
  109. 0x00040000,0x00090000,0x00060000,0x000B0000,
  110. 0x00080000,0x00010000,0x000A0000,0x00030000,
  111. 0x00080000,0x00050000,0x000A0000,0x00070000
  112. };
  113. #endif
  114. struct __gxfifo _gx_dl_fifo;
  115. u8 _gx_saved_data[1280];
  116. extern u8 __gxregs[];
  117. static u32 *_gx = (u32*)__gxregs;
  118. extern void __UnmaskIrq(u32);
  119. extern void __MaskIrq(u32);
  120. extern long long gettime();
  121. static s32 __gx_onreset(s32 final);
  122. static sys_resetinfo __gx_resetinfo = {
  123. {},
  124. __gx_onreset,
  125. 127
  126. };
  127. #ifdef _GP_DEBUG
  128. extern int printk(const char *fmt,...);
  129. #endif
  130. static __inline__ s32 IsWriteGatherBufferEmpty()
  131. {
  132. _sync();
  133. return (mfwpar()&0x0001);
  134. }
  135. static __inline__ void DisableWriteGatherPipe()
  136. {
  137. mthid2((mfhid2()&~0x40000000));
  138. }
  139. static __inline__ void EnableWriteGatherPipe()
  140. {
  141. mtwpar(0x0C008000);
  142. mthid2((mfhid2()|0x40000000));
  143. }
  144. static __inline__ void __GX_FifoLink(u8 enable)
  145. {
  146. ((u16*)_gx)[1] = ((((u16*)_gx)[1]&~0x10)|(_SHIFTL(enable,4,1)));
  147. _cpReg[1] = ((u16*)_gx)[1];
  148. }
  149. static __inline__ void __GX_WriteFifoIntReset(u8 inthi,u8 intlo)
  150. {
  151. ((u16*)_gx)[2] = ((((u16*)_gx)[2]&~0x03)|(_SHIFTL(intlo,1,1))|(inthi&1));
  152. _cpReg[2] = ((u16*)_gx)[2];
  153. }
  154. static __inline__ void __GX_WriteFifoIntEnable(u8 inthi, u8 intlo)
  155. {
  156. ((u16*)_gx)[1] = ((((u16*)_gx)[1]&~0x0C)|(_SHIFTL(intlo,3,1))|(_SHIFTL(inthi,2,1)));
  157. _cpReg[1] = ((u16*)_gx)[1];
  158. }
  159. static __inline__ void __GX_FifoReadEnable()
  160. {
  161. ((u16*)_gx)[1] = ((((u16*)_gx)[1]&~0x01)|1);
  162. _cpReg[1] = ((u16*)_gx)[1];
  163. }
  164. static __inline__ void __GX_FifoReadDisable()
  165. {
  166. ((u16*)_gx)[1] = ((((u16*)_gx)[1]&~0x01)|0);
  167. _cpReg[1] = ((u16*)_gx)[1];
  168. }
  169. static s32 __gx_onreset(s32 final)
  170. {
  171. if(final==FALSE) {
  172. GX_Flush();
  173. GX_AbortFrame();
  174. }
  175. return 1;
  176. }
  177. static u8 __GX_IsGPCPUFifoLinked()
  178. {
  179. return _cpgplinked;
  180. }
  181. static u8 __GX_IsGPFifoReady()
  182. {
  183. return _gxgpfifoready;
  184. }
  185. static u8 __GX_IsCPUFifoReady()
  186. {
  187. return _gxcpufifoready;
  188. }
  189. static void __GX_InitRevBits()
  190. {
  191. s32 i;
  192. i=0;
  193. while(i<8) {
  194. _gx[0x10+i] = 0x40000000;
  195. _gx[0x18+i] = 0x80000000;
  196. GX_LOAD_CP_REG((0x0080|i),_gx[0x18+i]);
  197. i++;
  198. }
  199. GX_LOAD_XF_REG(0x1000,0x3f);
  200. GX_LOAD_XF_REG(0x1012,0x01);
  201. GX_LOAD_BP_REG(0x5800000f);
  202. }
  203. static void __GX_WaitAbort(u32 delay)
  204. {
  205. u64 start,end;
  206. start = gettime();
  207. while(1) {
  208. end = gettime();
  209. if(diff_ticks(start,end)>=(u64)delay) break;
  210. };
  211. }
  212. static u32 __GX_ReadMemCounterU32(u32 reg)
  213. {
  214. u16 lcnt,ucnt,tmp;
  215. tmp = _memReg[reg];
  216. do {
  217. ucnt = tmp;
  218. lcnt = _memReg[reg+1];
  219. tmp = _memReg[reg];
  220. } while(tmp!=ucnt);
  221. return (u32)((ucnt<<16)|lcnt);
  222. }
  223. static void __GX_WaitAbortPixelEngine()
  224. {
  225. u32 cnt,tmp;
  226. cnt = __GX_ReadMemCounterU32(39);
  227. do {
  228. tmp = cnt;
  229. __GX_WaitAbort(8);
  230. cnt = __GX_ReadMemCounterU32(39);
  231. } while(cnt!=tmp);
  232. }
  233. static void __GX_Abort()
  234. {
  235. if(_gx[0x1ff] && __GX_IsGPFifoReady())
  236. __GX_WaitAbortPixelEngine();
  237. _piReg[6] = 1;
  238. __GX_WaitAbort(50);
  239. _piReg[6] = 0;
  240. __GX_WaitAbort(5);
  241. }
  242. static void __GX_SaveCPUFifoAux(struct __gxfifo *fifo)
  243. {
  244. u32 level;
  245. _CPU_ISR_Disable(level);
  246. GX_Flush();
  247. fifo->buf_start = (u32)MEM_PHYSICAL_TO_K0(_piReg[0x03]);
  248. fifo->buf_end = (u32)MEM_PHYSICAL_TO_K0(_piReg[0x04]);
  249. fifo->wt_ptr = (u32)MEM_PHYSICAL_TO_K0(((_piReg[0x05]&~0x04000000)));
  250. if(_cpgplinked) {
  251. fifo->rd_ptr = (u32)MEM_PHYSICAL_TO_K0(_SHIFTL(_cpReg[29],16,16)|(_cpReg[28]&0xffff));
  252. fifo->rdwt_dst = (_SHIFTL(_cpReg[25],16,16)|(_cpReg[24]&0xffff));
  253. } else {
  254. fifo->rdwt_dst = (fifo->wt_ptr - fifo->rd_ptr);
  255. if(fifo->rdwt_dst<0) fifo->rdwt_dst = (fifo->rdwt_dst + fifo->size);
  256. }
  257. _CPU_ISR_Restore(level);
  258. }
  259. static void __GX_CleanGPFifo()
  260. {
  261. u32 level;
  262. if(!_gxgpfifoready) return;
  263. _CPU_ISR_Disable(level);
  264. __GX_FifoReadDisable();
  265. __GX_WriteFifoIntEnable(FALSE,FALSE);
  266. _gpfifo->rd_ptr = _gpfifo->wt_ptr;
  267. _gpfifo->rdwt_dst = 0;
  268. /* setup rd<->wd dist */
  269. _cpReg[24] = _SHIFTL(_gpfifo->rdwt_dst,0,16);
  270. _cpReg[25] = _SHIFTR(_gpfifo->rdwt_dst,16,16);
  271. /* setup wt ptr */
  272. _cpReg[26] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(_gpfifo->wt_ptr),0,16);
  273. _cpReg[27] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(_gpfifo->wt_ptr),16,16);
  274. /* setup rd ptr */
  275. _cpReg[28] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(_gpfifo->rd_ptr),0,16);
  276. _cpReg[29] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(_gpfifo->rd_ptr),16,16);
  277. ppcsync();
  278. if(_cpgplinked) {
  279. _cpufifo->rd_ptr = _gpfifo->rd_ptr;
  280. _cpufifo->wt_ptr = _gpfifo->wt_ptr;
  281. _cpufifo->rdwt_dst = _gpfifo->rdwt_dst;
  282. _piReg[5] = (_cpufifo->wt_ptr&0x1FFFFFE0);
  283. __GX_WriteFifoIntEnable(TRUE,FALSE);
  284. __GX_FifoLink(TRUE);
  285. }
  286. ((u16*)_gx)[1] &= ~0x22;
  287. _cpReg[1] = ((u16*)_gx)[1];
  288. breakPtCB = NULL;
  289. __GX_WriteFifoIntReset(TRUE,TRUE);
  290. __GX_FifoReadEnable();
  291. _CPU_ISR_Restore(level);
  292. }
  293. static void __GXOverflowHandler()
  294. {
  295. if(!_gxoverflowsuspend) {
  296. _gxoverflowsuspend = 1;
  297. _gxoverflowcount++;
  298. __GX_WriteFifoIntEnable(GX_DISABLE,GX_ENABLE);
  299. __GX_WriteFifoIntReset(GX_TRUE,GX_FALSE);
  300. LWP_SuspendThread(_gxcurrentlwp);
  301. }
  302. }
  303. static void __GXUnderflowHandler()
  304. {
  305. if(_gxoverflowsuspend) {
  306. _gxoverflowsuspend = 0;
  307. LWP_ResumeThread(_gxcurrentlwp);
  308. __GX_WriteFifoIntReset(GX_TRUE,GX_TRUE);
  309. __GX_WriteFifoIntEnable(GX_ENABLE,GX_DISABLE);
  310. }
  311. }
  312. static void __GXCPInterruptHandler(u32 irq,void *ctx)
  313. {
  314. ((u16*)_gx)[0] = _cpReg[0];
  315. if((((u16*)_gx)[1]&0x08) && (((u16*)_gx)[0]&0x02))
  316. __GXUnderflowHandler();
  317. if((((u16*)_gx)[1]&0x04) && (((u16*)_gx)[0]&0x01))
  318. __GXOverflowHandler();
  319. if((((u16*)_gx)[1]&0x20) && (((u16*)_gx)[0]&0x10)) {
  320. ((u16*)_gx)[1] &= ~0x20;
  321. _cpReg[1] = ((u16*)_gx)[1];
  322. if(breakPtCB)
  323. breakPtCB();
  324. }
  325. }
  326. static void __GXTokenInterruptHandler(u32 irq,void *ctx)
  327. {
  328. u16 token = _peReg[7];
  329. if(tokenCB)
  330. tokenCB(token);
  331. _peReg[5] = (_peReg[5]&~0x04)|0x04;
  332. }
  333. static void __GXFinishInterruptHandler(u32 irq,void *ctx)
  334. {
  335. #ifdef _GP_DEBUG
  336. printf("__GXFinishInterruptHandler()\n");
  337. #endif
  338. _peReg[5] = (_peReg[5]&~0x08)|0x08;
  339. _gxfinished = 1;
  340. if(drawDoneCB)
  341. drawDoneCB();
  342. LWP_ThreadBroadcast(_gxwaitfinish);
  343. }
  344. static void __GX_PEInit()
  345. {
  346. IRQ_Request(IRQ_PI_PETOKEN,__GXTokenInterruptHandler,NULL);
  347. __UnmaskIrq(IRQMASK(IRQ_PI_PETOKEN));
  348. IRQ_Request(IRQ_PI_PEFINISH,__GXFinishInterruptHandler,NULL);
  349. __UnmaskIrq(IRQMASK(IRQ_PI_PEFINISH));
  350. _peReg[5] = 0x0F;
  351. }
  352. static void __GX_FifoInit()
  353. {
  354. IRQ_Request(IRQ_PI_CP,__GXCPInterruptHandler,NULL);
  355. __UnmaskIrq(IRQMASK(IRQ_PI_CP));
  356. _gxcpufifoready = 0;
  357. _gxgpfifoready = 0;
  358. _gxoverflowsuspend = 0;
  359. _cpufifo = NULL;
  360. _gpfifo = NULL;
  361. _gxcurrentlwp = LWP_GetSelf();
  362. }
  363. static void __GX_SetTmemConfig(u8 nr)
  364. {
  365. if(nr==0) {
  366. // Set_TextureImage0-3, GXTexMapID=0-3 tmem_offset=00000000, cache_width=32 kb, cache_height=32 kb, image_type=cached
  367. GX_LOAD_BP_REG(0x8c0d8000);
  368. GX_LOAD_BP_REG(0x900dc000);
  369. GX_LOAD_BP_REG(0x8d0d8400);
  370. GX_LOAD_BP_REG(0x910dc400);
  371. GX_LOAD_BP_REG(0x8e0d8800);
  372. GX_LOAD_BP_REG(0x920dc800);
  373. GX_LOAD_BP_REG(0x8f0d8c00);
  374. GX_LOAD_BP_REG(0x930dcc00);
  375. // Set_TextureImage0-3, GXTexMapID=4-7 tmem_offset=00010000, cache_width=32 kb, cache_height=32 kb, image_type=cached
  376. GX_LOAD_BP_REG(0xac0d9000);
  377. GX_LOAD_BP_REG(0xb00dd000);
  378. GX_LOAD_BP_REG(0xad0d9400);
  379. GX_LOAD_BP_REG(0xb10dd400);
  380. GX_LOAD_BP_REG(0xae0d9800);
  381. GX_LOAD_BP_REG(0xb20dd800);
  382. GX_LOAD_BP_REG(0xaf0d9c00);
  383. GX_LOAD_BP_REG(0xb30ddc00);
  384. return;
  385. }
  386. if(nr==1) {
  387. // Set_TextureImage0-3, GXTexMapID=0-3 tmem_offset=00000000, cache_width=32 kb, cache_height=32 kb, image_type=cached
  388. GX_LOAD_BP_REG(0x8c0d8000);
  389. GX_LOAD_BP_REG(0x900dc000);
  390. GX_LOAD_BP_REG(0x8d0d8800);
  391. GX_LOAD_BP_REG(0x910dc800);
  392. GX_LOAD_BP_REG(0x8e0d9000);
  393. GX_LOAD_BP_REG(0x920dd000);
  394. GX_LOAD_BP_REG(0x8f0d9800);
  395. GX_LOAD_BP_REG(0x930dd800);
  396. // Set_TextureImage0-3, GXTexMapID=4-7 tmem_offset=00010000, cache_width=32 kb, cache_height=32 kb, image_type=cached
  397. GX_LOAD_BP_REG(0xac0da000);
  398. GX_LOAD_BP_REG(0xb00de000);
  399. GX_LOAD_BP_REG(0xad0da800);
  400. GX_LOAD_BP_REG(0xb10de800);
  401. GX_LOAD_BP_REG(0xae0db000);
  402. GX_LOAD_BP_REG(0xb20df000);
  403. GX_LOAD_BP_REG(0xaf0db800);
  404. GX_LOAD_BP_REG(0xb30df800);
  405. return;
  406. }
  407. if(nr==2) {
  408. // Set_TextureImage0-3, GXTexMapID=0-3 tmem_offset=00000000, cache_width=32 kb, cache_height=32 kb, image_type=cached
  409. GX_LOAD_BP_REG(0x8c0d8000);
  410. GX_LOAD_BP_REG(0x900dc000);
  411. GX_LOAD_BP_REG(0x8d0d8800);
  412. GX_LOAD_BP_REG(0x910dc800);
  413. GX_LOAD_BP_REG(0x8e0d9000);
  414. GX_LOAD_BP_REG(0x920dd000);
  415. GX_LOAD_BP_REG(0x8f0d9800);
  416. GX_LOAD_BP_REG(0x930dd800);
  417. // Set_TextureImage0-3, GXTexMapID=4-7 tmem_offset=00010000, cache_width=32 kb, cache_height=32 kb, image_type=cached
  418. GX_LOAD_BP_REG(0xac0da000);
  419. GX_LOAD_BP_REG(0xb00dc400);
  420. GX_LOAD_BP_REG(0xad0da800);
  421. GX_LOAD_BP_REG(0xb10dcc00);
  422. GX_LOAD_BP_REG(0xae0db000);
  423. GX_LOAD_BP_REG(0xb20dd400);
  424. GX_LOAD_BP_REG(0xaf0db800);
  425. GX_LOAD_BP_REG(0xb30ddc00);
  426. return;
  427. }
  428. }
  429. static GXTexRegion* __GXDefRegionCallback(GXTexObj *obj,u8 mapid)
  430. {
  431. u8 fmt;
  432. u32 idx;
  433. static u32 regionA = 0;
  434. static u32 regionB = 0;
  435. GXTexRegion *ret = NULL;
  436. fmt = GX_GetTexFmt(obj);
  437. if(fmt==0x0008 || fmt==0x0009 || fmt==0x000a) {
  438. idx = regionB++;
  439. ret = (GXTexRegion*)(&_gx[0x120+((idx&0x3)*(sizeof(GXTexRegion)>>2))]);
  440. } else {
  441. idx = regionA++;
  442. ret = (GXTexRegion*)(&_gx[0x100+((idx&0x7)*(sizeof(GXTexRegion)>>2))]);
  443. }
  444. return ret;
  445. }
  446. static GXTlutRegion* __GXDefTlutRegionCallback(u32 tlut_name)
  447. {
  448. return (GXTlutRegion*)(&_gx[0x150+(tlut_name*(sizeof(GXTlutRegion)>>2))]);
  449. }
  450. static void __GX_InitGX()
  451. {
  452. s32 i;
  453. u32 flag;
  454. GXRModeObj *rmode;
  455. Mtx identity_matrix =
  456. {
  457. {1,0,0,0},
  458. {0,1,0,0},
  459. {0,0,1,0}
  460. };
  461. rmode = VIDEO_GetPreferredMode(NULL);
  462. GX_SetCopyClear((GXColor)BLACK,0xffffff);
  463. GX_SetTexCoordGen(GX_TEXCOORD0,GX_TG_MTX2x4,GX_TG_TEX0,GX_IDENTITY);
  464. GX_SetTexCoordGen(GX_TEXCOORD1,GX_TG_MTX2x4,GX_TG_TEX1,GX_IDENTITY);
  465. GX_SetTexCoordGen(GX_TEXCOORD2,GX_TG_MTX2x4,GX_TG_TEX2,GX_IDENTITY);
  466. GX_SetTexCoordGen(GX_TEXCOORD3,GX_TG_MTX2x4,GX_TG_TEX3,GX_IDENTITY);
  467. GX_SetTexCoordGen(GX_TEXCOORD4,GX_TG_MTX2x4,GX_TG_TEX4,GX_IDENTITY);
  468. GX_SetTexCoordGen(GX_TEXCOORD5,GX_TG_MTX2x4,GX_TG_TEX5,GX_IDENTITY);
  469. GX_SetTexCoordGen(GX_TEXCOORD6,GX_TG_MTX2x4,GX_TG_TEX6,GX_IDENTITY);
  470. GX_SetTexCoordGen(GX_TEXCOORD7,GX_TG_MTX2x4,GX_TG_TEX7,GX_IDENTITY);
  471. GX_SetNumTexGens(1);
  472. GX_ClearVtxDesc();
  473. GX_InvVtxCache();
  474. GX_SetLineWidth(6,GX_TO_ZERO);
  475. GX_SetPointSize(6,GX_TO_ZERO);
  476. GX_EnableTexOffsets(GX_TEXCOORD0,GX_DISABLE,GX_DISABLE);
  477. GX_EnableTexOffsets(GX_TEXCOORD1,GX_DISABLE,GX_DISABLE);
  478. GX_EnableTexOffsets(GX_TEXCOORD2,GX_DISABLE,GX_DISABLE);
  479. GX_EnableTexOffsets(GX_TEXCOORD3,GX_DISABLE,GX_DISABLE);
  480. GX_EnableTexOffsets(GX_TEXCOORD4,GX_DISABLE,GX_DISABLE);
  481. GX_EnableTexOffsets(GX_TEXCOORD5,GX_DISABLE,GX_DISABLE);
  482. GX_EnableTexOffsets(GX_TEXCOORD6,GX_DISABLE,GX_DISABLE);
  483. GX_EnableTexOffsets(GX_TEXCOORD7,GX_DISABLE,GX_DISABLE);
  484. GX_LoadPosMtxImm(identity_matrix,GX_PNMTX0);
  485. GX_LoadNrmMtxImm(identity_matrix,GX_PNMTX0);
  486. GX_SetCurrentMtx(GX_PNMTX0);
  487. GX_LoadTexMtxImm(identity_matrix,GX_IDENTITY,GX_MTX3x4);
  488. GX_LoadTexMtxImm(identity_matrix,GX_DTTIDENTITY,GX_MTX3x4);
  489. GX_SetViewport(0,0,rmode->fbWidth,rmode->efbHeight,0,1);
  490. GX_SetCoPlanar(GX_DISABLE);
  491. GX_SetCullMode(GX_CULL_BACK);
  492. GX_SetClipMode(GX_CLIP_DISABLE);
  493. GX_SetScissor(0,0,rmode->fbWidth,rmode->efbHeight);
  494. GX_SetScissorBoxOffset(0,0);
  495. GX_SetNumChans(0);
  496. GX_SetChanCtrl(GX_COLOR0A0,GX_DISABLE,GX_SRC_REG,GX_SRC_VTX,GX_LIGHTNULL,GX_DF_NONE,GX_AF_NONE);
  497. GX_SetChanAmbColor(GX_COLOR0A0,(GXColor)BLACK);
  498. GX_SetChanMatColor(GX_COLOR0A0,(GXColor)WHITE);
  499. GX_SetChanCtrl(GX_COLOR1A1,GX_DISABLE,GX_SRC_REG,GX_SRC_VTX,GX_LIGHTNULL,GX_DF_NONE,GX_AF_NONE);
  500. GX_SetChanAmbColor(GX_COLOR1A1,(GXColor)BLACK);
  501. GX_SetChanMatColor(GX_COLOR1A1,(GXColor)WHITE);
  502. GX_InvalidateTexAll();
  503. GX_SetTexRegionCallback(__GXDefRegionCallback);
  504. GX_SetTlutRegionCallback(__GXDefTlutRegionCallback);
  505. GX_SetTevOrder(GX_TEVSTAGE0,GX_TEXCOORD0,GX_TEXMAP0,GX_COLOR0A0);
  506. GX_SetTevOrder(GX_TEVSTAGE1,GX_TEXCOORD1,GX_TEXMAP1,GX_COLOR0A0);
  507. GX_SetTevOrder(GX_TEVSTAGE2,GX_TEXCOORD2,GX_TEXMAP2,GX_COLOR0A0);
  508. GX_SetTevOrder(GX_TEVSTAGE3,GX_TEXCOORD3,GX_TEXMAP3,GX_COLOR0A0);
  509. GX_SetTevOrder(GX_TEVSTAGE4,GX_TEXCOORD4,GX_TEXMAP4,GX_COLOR0A0);
  510. GX_SetTevOrder(GX_TEVSTAGE5,GX_TEXCOORD5,GX_TEXMAP5,GX_COLOR0A0);
  511. GX_SetTevOrder(GX_TEVSTAGE6,GX_TEXCOORD6,GX_TEXMAP6,GX_COLOR0A0);
  512. GX_SetTevOrder(GX_TEVSTAGE7,GX_TEXCOORD7,GX_TEXMAP7,GX_COLOR0A0);
  513. GX_SetTevOrder(GX_TEVSTAGE8,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
  514. GX_SetTevOrder(GX_TEVSTAGE9,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
  515. GX_SetTevOrder(GX_TEVSTAGE10,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
  516. GX_SetTevOrder(GX_TEVSTAGE11,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
  517. GX_SetTevOrder(GX_TEVSTAGE12,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
  518. GX_SetTevOrder(GX_TEVSTAGE13,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
  519. GX_SetTevOrder(GX_TEVSTAGE14,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
  520. GX_SetTevOrder(GX_TEVSTAGE15,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
  521. GX_SetNumTevStages(1);
  522. GX_SetTevOp(GX_TEVSTAGE0,GX_REPLACE);
  523. GX_SetAlphaCompare(GX_ALWAYS,0,GX_AOP_AND,GX_ALWAYS,0);
  524. GX_SetZTexture(GX_ZT_DISABLE,GX_TF_Z8,0);
  525. for(i=0;i<GX_MAX_TEVSTAGE;i++) {
  526. GX_SetTevKColorSel(i,GX_TEV_KCSEL_1_4);
  527. GX_SetTevKAlphaSel(i,GX_TEV_KASEL_1);
  528. GX_SetTevSwapMode(i,GX_TEV_SWAP0,GX_TEV_SWAP0);
  529. }
  530. GX_SetTevSwapModeTable(GX_TEV_SWAP0,GX_CH_RED,GX_CH_GREEN,GX_CH_BLUE,GX_CH_ALPHA);
  531. GX_SetTevSwapModeTable(GX_TEV_SWAP1,GX_CH_RED,GX_CH_RED,GX_CH_RED,GX_CH_ALPHA);
  532. GX_SetTevSwapModeTable(GX_TEV_SWAP2,GX_CH_GREEN,GX_CH_GREEN,GX_CH_GREEN,GX_CH_ALPHA);
  533. GX_SetTevSwapModeTable(GX_TEV_SWAP3,GX_CH_BLUE,GX_CH_BLUE,GX_CH_BLUE,GX_CH_ALPHA);
  534. for(i=0;i<GX_MAX_TEVSTAGE;i++) {
  535. GX_SetTevDirect(i);
  536. }
  537. GX_SetNumIndStages(0);
  538. GX_SetIndTexCoordScale(GX_INDTEXSTAGE0,GX_ITS_1,GX_ITS_1);
  539. GX_SetIndTexCoordScale(GX_INDTEXSTAGE1,GX_ITS_1,GX_ITS_1);
  540. GX_SetIndTexCoordScale(GX_INDTEXSTAGE2,GX_ITS_1,GX_ITS_1);
  541. GX_SetIndTexCoordScale(GX_INDTEXSTAGE3,GX_ITS_1,GX_ITS_1);
  542. GX_SetFog(GX_FOG_NONE,0,1,0.1,1,(GXColor)BLACK);
  543. GX_SetFogRangeAdj(GX_DISABLE,0,NULL);
  544. GX_SetBlendMode(GX_BM_NONE,GX_BL_SRCALPHA,GX_BL_INVSRCALPHA,GX_LO_CLEAR);
  545. GX_SetColorUpdate(GX_ENABLE);
  546. GX_SetAlphaUpdate(GX_ENABLE);
  547. GX_SetZMode(GX_ENABLE,GX_LEQUAL,GX_TRUE);
  548. GX_SetZCompLoc(GX_TRUE);
  549. GX_SetDither(GX_ENABLE);
  550. GX_SetDstAlpha(GX_DISABLE,0);
  551. GX_SetPixelFmt(GX_PF_RGB8_Z24,GX_ZC_LINEAR);
  552. GX_SetFieldMask(GX_ENABLE,GX_ENABLE);
  553. flag = 0;
  554. if(rmode->viHeight==(rmode->xfbHeight<<1)) flag = 1;
  555. GX_SetFieldMode(rmode->field_rendering,flag);
  556. GX_SetCopyClear((GXColor)GX_DEFAULT_BG,0x00ffffff);
  557. GX_SetDispCopySrc(0,0,rmode->fbWidth,rmode->efbHeight);
  558. GX_SetDispCopyDst(rmode->fbWidth,rmode->efbHeight);
  559. GX_SetDispCopyYScale(1.0);
  560. GX_SetCopyClamp(GX_CLAMP_TOP|GX_CLAMP_BOTTOM);
  561. GX_SetCopyFilter(GX_FALSE,NULL,GX_FALSE,NULL);
  562. GX_SetDispCopyGamma(GX_GM_1_0);
  563. GX_SetDispCopyFrame2Field(GX_COPY_PROGRESSIVE);
  564. GX_ClearBoundingBox();
  565. GX_PokeColorUpdate(GX_TRUE);
  566. GX_PokeAlphaUpdate(GX_TRUE);
  567. GX_PokeDither(GX_FALSE);
  568. GX_PokeBlendMode(GX_BM_NONE,GX_BL_ZERO,GX_BL_ONE,GX_LO_SET);
  569. GX_PokeAlphaMode(GX_ALWAYS,0);
  570. GX_PokeAlphaRead(GX_READ_FF);
  571. GX_PokeDstAlpha(GX_DISABLE,0);
  572. GX_PokeZMode(GX_TRUE,GX_ALWAYS,GX_TRUE);
  573. GX_SetGPMetric(GX_PERF0_NONE,GX_PERF1_NONE);
  574. GX_ClearGPMetric();
  575. }
  576. static void __GX_FlushTextureState()
  577. {
  578. GX_LOAD_BP_REG(_gx[0xaf]);
  579. }
  580. static void __GX_XfVtxSpecs()
  581. {
  582. u32 xfvtxspecs = 0;
  583. u32 nrms,texs,cols;
  584. cols = 0;
  585. if(_gx[0x06]&0x6000) cols++;
  586. if(_gx[0x06]&0x18000) cols++;
  587. nrms = 0;
  588. if(_gx[0x08]==1) nrms = 1;
  589. else if(_gx[0x08]==2) nrms = 2;
  590. texs = 0;
  591. if(_gx[0x07]&0x3) texs++;
  592. if(_gx[0x07]&0xc) texs++;
  593. if(_gx[0x07]&0x30) texs++;
  594. if(_gx[0x07]&0xc0) texs++;
  595. if(_gx[0x07]&0x300) texs++;
  596. if(_gx[0x07]&0xc00) texs++;
  597. if(_gx[0x07]&0x3000) texs++;
  598. if(_gx[0x07]&0xc000) texs++;
  599. xfvtxspecs = (_SHIFTL(texs,4,4))|(_SHIFTL(nrms,2,2))|(cols&0x3);
  600. GX_LOAD_XF_REG(0x1008,xfvtxspecs);
  601. }
  602. static void __GX_SetMatrixIndex(u32 mtx)
  603. {
  604. if(mtx<5) {
  605. GX_LOAD_CP_REG(0x30,_gx[0x03]);
  606. GX_LOAD_XF_REG(0x1018,_gx[0x03]);
  607. } else {
  608. GX_LOAD_CP_REG(0x40,_gx[0x04]);
  609. GX_LOAD_XF_REG(0x1019,_gx[0x04]);
  610. }
  611. }
  612. static void __GX_SendFlushPrim()
  613. {
  614. u32 tmp,tmp2,cnt;
  615. tmp = ((u16*)_gx)[30]*((u16*)_gx)[31];
  616. FIFO_PUTU8(0x98);
  617. FIFO_PUTU16(((u16*)_gx)[30]);
  618. tmp2 = (tmp+3)/4;
  619. if(tmp>0) {
  620. cnt = tmp2/8;
  621. while(cnt) {
  622. FIFO_PUTU32(0);
  623. FIFO_PUTU32(0);
  624. FIFO_PUTU32(0);
  625. FIFO_PUTU32(0);
  626. FIFO_PUTU32(0);
  627. FIFO_PUTU32(0);
  628. FIFO_PUTU32(0);
  629. FIFO_PUTU32(0);
  630. cnt--;
  631. }
  632. tmp2 &= 0x0007;
  633. if(tmp2) {
  634. while(tmp2) {
  635. FIFO_PUTU32(0);
  636. tmp2--;
  637. }
  638. }
  639. }
  640. ((u16*)_gx)[29] = 1;
  641. }
  642. static void __GX_SetVCD()
  643. {
  644. GX_LOAD_CP_REG(0x50,_gx[0x06]);
  645. GX_LOAD_CP_REG(0x60,_gx[0x07]);
  646. __GX_XfVtxSpecs();
  647. }
  648. static void __GX_SetVAT()
  649. {
  650. u8 setvtx = 0;
  651. s32 i;
  652. for(i=0;i<8;i++) {
  653. setvtx = (1<<i);
  654. if(_gx[0x02]&setvtx) {
  655. GX_LOAD_CP_REG((0x70|(i&7)),_gx[0x10+i]);
  656. GX_LOAD_CP_REG((0x80|(i&7)),_gx[0x18+i]);
  657. GX_LOAD_CP_REG((0x90|(i&7)),_gx[0x20+i]);
  658. }
  659. }
  660. _gx[0x02] = 0;
  661. }
  662. static void __SetSURegs(u8 texmap,u8 texcoord)
  663. {
  664. u16 wd,ht;
  665. u8 wrap_s,wrap_t;
  666. u32 regA,regB;
  667. wd = _gx[0x40+texmap]&0x3ff;
  668. ht = _SHIFTR(_gx[0x40+texmap],10,10);
  669. wrap_s = _gx[0x50+texmap]&3;
  670. wrap_t = _SHIFTR(_gx[0x50+texmap],2,2);
  671. regA = 0xa0+(texcoord&0x7);
  672. regB = 0xb0+(texcoord&0x7);
  673. _gx[regA] = (_gx[regA]&~0x0000ffff)|wd;
  674. _gx[regB] = (_gx[regB]&~0x0000ffff)|ht;
  675. _gx[regA] = (_gx[regA]&~0x00010000)|(_SHIFTL(wrap_s,16,1));
  676. _gx[regB] = (_gx[regB]&~0x00010000)|(_SHIFTL(wrap_t,16,1));
  677. GX_LOAD_BP_REG(_gx[regA]);
  678. GX_LOAD_BP_REG(_gx[regB]);
  679. }
  680. static void __GX_SetSUTexRegs()
  681. {
  682. u32 i;
  683. u32 indtev,dirtev;
  684. u8 texcoord,texmap;
  685. u32 tevreg,tevm,texcm;
  686. dirtev = (_SHIFTR(_gx[0xac],10,4))+1;
  687. indtev = _SHIFTR(_gx[0xac],16,3);
  688. //indirect texture order
  689. for(i=0;i<indtev;i++) {
  690. switch(i) {
  691. case GX_INDTEXSTAGE0:
  692. texmap = _gx[0xc2]&7;
  693. texcoord = _SHIFTR(_gx[0xc2],3,3);
  694. break;
  695. case GX_INDTEXSTAGE1:
  696. texmap = _SHIFTR(_gx[0xc2],6,3);
  697. texcoord = _SHIFTR(_gx[0xc2],9,3);
  698. break;
  699. case GX_INDTEXSTAGE2:
  700. texmap = _SHIFTR(_gx[0xc2],12,3);
  701. texcoord = _SHIFTR(_gx[0xc2],15,3);
  702. break;
  703. case GX_INDTEXSTAGE3:
  704. texmap = _SHIFTR(_gx[0xc2],18,3);
  705. texcoord = _SHIFTR(_gx[0xc2],21,3);
  706. break;
  707. default:
  708. texmap = 0;
  709. texcoord = 0;
  710. break;
  711. }
  712. texcm = _SHIFTL(1,texcoord,1);
  713. if(!(_gx[0x05]&texcm))
  714. __SetSURegs(texmap,texcoord);
  715. }
  716. //direct texture order
  717. for(i=0;i<dirtev;i++) {
  718. tevreg = 0xc3+(_SHIFTR(i,1,3));
  719. texmap = (_gx[0x30+i]&0xff);
  720. if(i&1) texcoord = _SHIFTR(_gx[tevreg],15,3);
  721. else texcoord = _SHIFTR(_gx[tevreg],3,3);
  722. tevm = _SHIFTL(1,i,1);
  723. texcm = _SHIFTL(1,texcoord,1);
  724. if(texmap!=0xff && (_gx[0x0a]&tevm) && !(_gx[0x05]&texcm)) {
  725. __SetSURegs(texmap,texcoord);
  726. }
  727. }
  728. }
  729. static void __GX_SetGenMode()
  730. {
  731. GX_LOAD_BP_REG(_gx[0xac]);
  732. ((u16*)_gx)[29] = 0;
  733. }
  734. static void __GX_UpdateBPMask()
  735. {
  736. #if defined(HW_DOL)
  737. u32 i;
  738. u32 nbmp,nres;
  739. u8 ntexmap;
  740. nbmp = _SHIFTR(_gx[0xac],16,3);
  741. nres = 0;
  742. for(i=0;i<nbmp;i++) {
  743. switch(i) {
  744. case GX_INDTEXSTAGE0:
  745. ntexmap = _gx[0xc2]&7;
  746. break;
  747. case GX_INDTEXSTAGE1:
  748. ntexmap = _SHIFTR(_gx[0xc2],6,3);
  749. break;
  750. case GX_INDTEXSTAGE2:
  751. ntexmap = _SHIFTR(_gx[0xc2],12,3);
  752. break;
  753. case GX_INDTEXSTAGE3:
  754. ntexmap = _SHIFTR(_gx[0xc2],18,3);
  755. break;
  756. default:
  757. ntexmap = 0;
  758. break;
  759. }
  760. nres |= (1<<ntexmap);
  761. }
  762. if((_gx[0xaf]&0xff)!=nres) {
  763. _gx[0xaf] = (_gx[0xaf]&~0xff)|(nres&0xff);
  764. GX_LOAD_BP_REG(_gx[0xaf]);
  765. }
  766. #endif
  767. }
  768. static void __GX_SetIndirectMask(u32 mask)
  769. {
  770. _gx[0xaf] = ((_gx[0xaf]&~0xff)|(mask&0xff));
  771. GX_LOAD_BP_REG(_gx[0xaf]);
  772. }
  773. static void __GX_SetTexCoordGen()
  774. {
  775. u32 i,mask;
  776. u32 texcoord;
  777. if(_gx[0x09]&0x02000000) GX_LOAD_XF_REG(0x103f,(_gx[0xac]&0xf));
  778. i = 0;
  779. texcoord = 0x1040;
  780. mask = _SHIFTR(_gx[0x09],16,8);
  781. while(mask) {
  782. if(mask&0x0001) {
  783. GX_LOAD_XF_REG(texcoord,_gx[0xe0+(i<<1)]);
  784. GX_LOAD_XF_REG((texcoord+0x10),_gx[0xe1+(i<<1)]);
  785. }
  786. mask >>= 1;
  787. texcoord++;
  788. i++;
  789. }
  790. }
  791. static void __GX_SetChanColor()
  792. {
  793. if(_gx[0x09]&0x0100)
  794. GX_LOAD_XF_REG(0x100a,_gx[0xf0]);
  795. if(_gx[0x09]&0x0200)
  796. GX_LOAD_XF_REG(0x100b,_gx[0xf1]);
  797. if(_gx[0x09]&0x0400)
  798. GX_LOAD_XF_REG(0x100c,_gx[0xf2]);
  799. if(_gx[0x09]&0x0800)
  800. GX_LOAD_XF_REG(0x100d,_gx[0xf3]);
  801. }
  802. static void __GX_SetChanCntrl()
  803. {
  804. u32 i,chan,mask;
  805. if(_gx[0x09]&0x01000000) GX_LOAD_XF_REG(0x1009,(_SHIFTR(_gx[0xac],4,3)));
  806. i = 0;
  807. chan = 0x100e;
  808. mask = _SHIFTR(_gx[0x09],12,4);
  809. while(mask) {
  810. if(mask&0x0001) GX_LOAD_XF_REG(chan,_gx[0xf4+i]);
  811. mask >>= 1;
  812. chan++;
  813. i++;
  814. }
  815. }
  816. static void __GX_SetDirtyState()
  817. {
  818. if(_gx[0x09]&0x0001) {
  819. __GX_SetSUTexRegs();
  820. }
  821. if(_gx[0x09]&0x0002) {
  822. __GX_UpdateBPMask();
  823. }
  824. if(_gx[0x09]&0x0004) {
  825. __GX_SetGenMode();
  826. }
  827. if(_gx[0x09]&0x0008) {
  828. __GX_SetVCD();
  829. }
  830. if(_gx[0x09]&0x0010) {
  831. __GX_SetVAT();
  832. }
  833. if(_gx[0x09]&~0xff) {
  834. if(_gx[0x09]&0x0f00) {
  835. __GX_SetChanColor();
  836. }
  837. if(_gx[0x09]&0x0100f000) {
  838. __GX_SetChanCntrl();
  839. }
  840. if(_gx[0x09]&0x02ff0000) {
  841. __GX_SetTexCoordGen();
  842. }
  843. if(_gx[0x09]&0x04000000) {
  844. __GX_SetMatrixIndex(0);
  845. __GX_SetMatrixIndex(5);
  846. }
  847. }
  848. _gx[0x09] = 0;
  849. }
  850. static u32 __GX_GetNumXfbLines(u16 efbHeight,u32 yscale)
  851. {
  852. u32 tmp,tmp1;
  853. tmp = (((efbHeight-1)<<8)/yscale)+1;
  854. if(yscale>128 && yscale<256) {
  855. while(yscale&0x01) yscale >>= 1;
  856. tmp1 = yscale*(efbHeight/yscale);
  857. if(!(efbHeight-tmp1)) tmp++;
  858. }
  859. if(tmp>1024) tmp = 1024;
  860. return tmp;
  861. }
  862. GXFifoObj* GX_Init(void *base,u32 size)
  863. {
  864. s32 i,re0,re1,addr;
  865. #ifdef TEXCACHE_TESTING
  866. u32 tmem;
  867. #else
  868. u32 tmem_even,tmem_odd;
  869. #endif
  870. u32 divis,res;
  871. u32 divid = TB_BUS_CLOCK;
  872. GXTexRegion *region = NULL;
  873. GXTlutRegion *tregion = NULL;
  874. LWP_InitQueue(&_gxwaitfinish);
  875. SYS_RegisterResetFunc(&__gx_resetinfo);
  876. memset(_gx,0,2048);
  877. __GX_FifoInit();
  878. GX_InitFifoBase(&_gxdefiniobj,base,size);
  879. GX_SetCPUFifo(&_gxdefiniobj);
  880. GX_SetGPFifo(&_gxdefiniobj);
  881. __GX_PEInit();
  882. EnableWriteGatherPipe();
  883. _gx[0x1ff] = 1;
  884. _gx[0xaf] = 0xff;
  885. _gx[0xaf] = (_gx[0xaf]&~0xff000000)|(_SHIFTL(0x0f,24,8));
  886. i=0;
  887. re0 = 0xc0;
  888. re1 = 0xc1;
  889. while(i<16) {
  890. addr = 0x80+i;
  891. _gx[addr] = (_gx[addr]&~0xff000000)|(_SHIFTL(re0,24,8));
  892. addr = 0x90+i;
  893. _gx[addr] = (_gx[addr]&~0xff000000)|(_SHIFTL(re1,24,8));
  894. re0 += 2; re1 += 2; i++;
  895. }
  896. _gx[0x05] = 0;
  897. _gx[0x09] = 0;
  898. ((u8*)_gx)[0x371] = 1;
  899. ((u8*)_gx)[0x372] = 0;
  900. _gx[0xa8] = (_gx[0xa8]&~0xff000000)|(_SHIFTL(0x20,24,8));
  901. _gx[0xa9] = (_gx[0xa9]&~0xff000000)|(_SHIFTL(0x21,24,8));
  902. _gx[0xaa] = (_gx[0xaa]&~0xff000000)|(_SHIFTL(0x22,24,8));
  903. _gx[0xac] = (_gx[0xac]&~0xff000000)|(_SHIFTL(0x00,24,8));
  904. i=0;
  905. re0 = 0x30;
  906. re1 = 0x31;
  907. while(i<8) {
  908. addr = 0xa0+i;
  909. _gx[addr] = (_gx[addr]&~0xff000000)|(_SHIFTL(re0,24,8));
  910. addr = 0xb0+i;
  911. _gx[addr] = (_gx[addr]&~0xff000000)|(_SHIFTL(re1,24,8));
  912. re0 += 2; re1 += 2; i++;
  913. }
  914. _gx[0xb8] = (_gx[0xb8]&~0xff000000)|(_SHIFTL(0x40,24,8));
  915. _gx[0xb9] = (_gx[0xb9]&~0xff000000)|(_SHIFTL(0x41,24,8));
  916. _gx[0xba] = (_gx[0xba]&~0xff000000)|(_SHIFTL(0x42,24,8));
  917. _gx[0xbb] = (_gx[0xbb]&~0xff000000)|(_SHIFTL(0x43,24,8));
  918. i=0;
  919. re0 = 0x25;
  920. while(i<11) {
  921. addr = 0xc0+i;
  922. _gx[addr] = (_gx[addr]&~0xff000000)|(_SHIFTL(re0,24,8));
  923. re0++; i++;
  924. }
  925. divis = 500;
  926. res = (u32)(divid/divis);
  927. __GX_FlushTextureState();
  928. GX_LOAD_BP_REG(0x69000000|((_SHIFTR(res,11,24))|0x0400));
  929. divis = 4224;
  930. res = (u32)(res/divis);
  931. __GX_FlushTextureState();
  932. GX_LOAD_BP_REG(0x46000000|(res|0x0200));
  933. i=0;
  934. re0 = 0xf6;
  935. while(i<8) {
  936. addr = 0xd0+i;
  937. _gx[addr] = (_gx[addr]&~0xff000000)|(_SHIFTL(re0,24,8));
  938. re0++; i++;
  939. }
  940. _gx[0x0a] = 0;
  941. _gx[0x0b] = GX_PERF0_NONE;
  942. _gx[0x0c] = GX_PERF1_NONE;
  943. _gx[0x0d] = 0;
  944. __GX_InitRevBits();
  945. i=0;
  946. while(i<16) {
  947. _gx[0x30+i] = 0xff;
  948. i++;
  949. }
  950. #ifdef TEXCACHE_TESTING
  951. i = 0;
  952. while(i<8) {
  953. region = (GXTexRegion*)(&_gx[0x100+(i*(sizeof(GXTexRegion)>>2))]);
  954. GX_InitTexCacheRegion(region,GX_FALSE,_gxtexregionaddrtable[i+0],GX_TEXCACHE_32K,_gxtexregionaddrtable[i+8],GX_TEXCACHE_32K);
  955. region = (GXTexRegion*)(&_gx[0x120+(i*(sizeof(GXTexRegion)>>2))]);
  956. GX_InitTexCacheRegion(region,GX_FALSE,_gxtexregionaddrtable[i+16],GX_TEXCACHE_32K,_gxtexregionaddrtable[i+24],GX_TEXCACHE_32K);
  957. region = (GXTexRegion*)(&_gx[0x140+(i*(sizeof(GXTexRegion)>>2))]);
  958. GX_InitTexCacheRegion(region,GX_TRUE,_gxtexregionaddrtable[i+32],GX_TEXCACHE_32K,_gxtexregionaddrtable[i+40],GX_TEXCACHE_32K);
  959. i++;
  960. }
  961. i=0;
  962. while(i<16) {
  963. tmem = 0x000C0000+(i<<13);
  964. tregion = (GXTlutRegion*)(&_gx[0x160+(i*(sizeof(GXTlutRegion)>>2))]);
  965. GX_InitTlutRegion(tregion,tmem,GX_TLUT_256);
  966. i++;
  967. }
  968. i=0;
  969. while(i<4) {
  970. tmem = 0x000E0000+(i<<15);
  971. tregion = (GXTlutRegion*)(&_gx[0x160+((i+16)*(sizeof(GXTlutRegion)>>2))]);
  972. GX_InitTlutRegion(tregion,tmem,GX_TLUT_1K);
  973. i++;
  974. }
  975. #else
  976. for(i=0;i<8;i++) {
  977. tmem_even = tmem_odd = (i<<15);
  978. region = (GXTexRegion*)(&_gx[0x100+(i*(sizeof(GXTexRegion)>>2))]);
  979. GX_InitTexCacheRegion(region,GX_FALSE,tmem_even,GX_TEXCACHE_32K,(tmem_odd+0x00080000),GX_TEXCACHE_32K);
  980. }
  981. for(i=0;i<4;i++) {
  982. tmem_even = ((0x08+(i<<1))<<15);
  983. tmem_odd = ((0x09+(i<<1))<<15);
  984. region = (GXTexRegion*)(&_gx[0x120+(i*(sizeof(GXTexRegion)>>2))]);
  985. GX_InitTexCacheRegion(region,GX_FALSE,tmem_even,GX_TEXCACHE_32K,tmem_odd,GX_TEXCACHE_32K);
  986. }
  987. for(i=0;i<16;i++) {
  988. tmem_even = (i<<13)+0x000C0000;
  989. tregion = (GXTlutRegion*)(&_gx[0x150+(i*(sizeof(GXTlutRegion)>>2))]);
  990. GX_InitTlutRegion(tregion,tmem_even,GX_TLUT_256);
  991. }
  992. for(i=0;i<4;i++) {
  993. tmem_even = (i<<15)+0x000E0000;
  994. tregion = (GXTlutRegion*)(&_gx[0x150+((i+16)*(sizeof(GXTlutRegion)>>2))]);
  995. GX_InitTlutRegion(tregion,tmem_even,GX_TLUT_1K);
  996. }
  997. #endif
  998. _cpReg[3] = 0;
  999. GX_LOAD_CP_REG(0x20,0x00000000);
  1000. GX_LOAD_XF_REG(0x1006,0x0);
  1001. GX_LOAD_BP_REG(0x23000000);
  1002. GX_LOAD_BP_REG(0x24000000);
  1003. GX_LOAD_BP_REG(0x67000000);
  1004. __GX_SetIndirectMask(0);
  1005. #ifdef TEXCACHE_TESTING
  1006. __GX_SetTmemConfig(2);
  1007. #else
  1008. __GX_SetTmemConfig(0);
  1009. #endif
  1010. __GX_InitGX();
  1011. return &_gxdefiniobj;
  1012. }
  1013. void GX_InitFifoBase(GXFifoObj *fifo,void *base,u32 size)
  1014. {
  1015. struct __gxfifo *ptr = (struct __gxfifo*)fifo;
  1016. if(!ptr || size<GX_FIFO_MINSIZE || ptr==_cpufifo || ptr==_gpfifo) return;
  1017. ptr->buf_start = (u32)base;
  1018. ptr->buf_end = (u32)base + size - 4;
  1019. ptr->size = size;
  1020. ptr->rdwt_dst = 0;
  1021. GX_InitFifoLimits(fifo,(size-GX_FIFO_HIWATERMARK),((size>>1)&0x7fffffe0));
  1022. GX_InitFifoPtrs(fifo,base,base);
  1023. }
  1024. void GX_InitFifoLimits(GXFifoObj *fifo,u32 hiwatermark,u32 lowatermark)
  1025. {
  1026. struct __gxfifo *ptr = (struct __gxfifo*)fifo;
  1027. ptr->hi_mark = hiwatermark;
  1028. ptr->lo_mark = lowatermark;
  1029. }
  1030. void GX_InitFifoPtrs(GXFifoObj *fifo,void *rd_ptr,void *wt_ptr)
  1031. {
  1032. u32 level;
  1033. s32 rdwt_dst;
  1034. struct __gxfifo *ptr = (struct __gxfifo*)fifo;
  1035. _CPU_ISR_Disable(level);
  1036. rdwt_dst = wt_ptr-rd_ptr;
  1037. ptr->rd_ptr = (u32)rd_ptr;
  1038. ptr->wt_ptr = (u32)wt_ptr;
  1039. ptr->rdwt_dst = rdwt_dst;
  1040. if(rdwt_dst<0) {
  1041. rdwt_dst += ptr->size;
  1042. ptr->rd_ptr = rdwt_dst;
  1043. }
  1044. _CPU_ISR_Restore(level);
  1045. }
  1046. void GX_GetFifoPtrs(GXFifoObj *fifo,void **rd_ptr,void **wt_ptr)
  1047. {
  1048. struct __gxfifo *ptr = (struct __gxfifo*)fifo;
  1049. if(_cpufifo==ptr) ptr->wt_ptr = (u32)MEM_PHYSICAL_TO_K0((_piReg[5]&~0x04000000));
  1050. if(_gpfifo==ptr) {
  1051. ptr->rd_ptr = MEM_VIRTUAL_TO_PHYSICAL(_SHIFTL(_cpReg[29],16,16)|(_cpReg[28]&0xffff));
  1052. ptr->rdwt_dst = (_SHIFTL(_cpReg[25],16,16)|(_cpReg[24]&0xffff));
  1053. } else {
  1054. ptr->rdwt_dst = (ptr->wt_ptr - ptr->rd_ptr);
  1055. if(ptr->rd_ptr<0) ptr->rdwt_dst += ptr->size;
  1056. }
  1057. *rd_ptr = (void*)ptr->rd_ptr;
  1058. *wt_ptr = (void*)ptr->wt_ptr;
  1059. }
  1060. void GX_SetCPUFifo(GXFifoObj *fifo)
  1061. {
  1062. u32 level;
  1063. _CPU_ISR_Disable(level);
  1064. _gxcpufifoready = 0;
  1065. _cpufifo = (struct __gxfifo*)fifo;
  1066. if(_cpufifo==_gpfifo) {
  1067. _piReg[3] = MEM_VIRTUAL_TO_PHYSICAL(_cpufifo->buf_start);
  1068. _piReg[4] = MEM_VIRTUAL_TO_PHYSICAL(_cpufifo->buf_end);
  1069. _piReg[5] = (_cpufifo->wt_ptr&0x1FFFFFE0);
  1070. _cpgplinked = 1;
  1071. __GX_WriteFifoIntReset(GX_TRUE,GX_TRUE);
  1072. __GX_WriteFifoIntEnable(GX_ENABLE,GX_DISABLE);
  1073. __GX_FifoLink(GX_TRUE);
  1074. _CPU_ISR_Restore(level);
  1075. return;
  1076. }
  1077. if(_cpgplinked) {
  1078. __GX_FifoLink(GX_FALSE);
  1079. _cpgplinked = 0;
  1080. }
  1081. __GX_WriteFifoIntEnable(GX_DISABLE,GX_DISABLE);
  1082. _piReg[3] = MEM_VIRTUAL_TO_PHYSICAL(_cpufifo->buf_start);
  1083. _piReg[4] = MEM_VIRTUAL_TO_PHYSICAL(_cpufifo->buf_end);
  1084. _piReg[5] = (_cpufifo->wt_ptr&0x1FFFFFE0);
  1085. _gxcpufifoready = 1;
  1086. _CPU_ISR_Restore(level);
  1087. }
  1088. GXFifoObj* GX_GetCPUFifo()
  1089. {
  1090. return (GXFifoObj*)_cpufifo;
  1091. }
  1092. void GX_SetGPFifo(GXFifoObj *fifo)
  1093. {
  1094. u32 level;
  1095. _CPU_ISR_Disable(level);
  1096. _gxgpfifoready = 0;
  1097. __GX_FifoReadDisable();
  1098. __GX_WriteFifoIntEnable(GX_DISABLE,GX_DISABLE);
  1099. _gpfifo = (struct __gxfifo*)fifo;
  1100. /* setup fifo base */
  1101. _cpReg[16] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(_gpfifo->buf_start),0,16);
  1102. _cpReg[17] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(_gpfifo->buf_start),16,16);
  1103. /* setup fifo end */
  1104. _cpReg[18] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(_gpfifo->buf_end),0,16);
  1105. _cpReg[19] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(_gpfifo->buf_end),16,16);
  1106. /* setup hiwater mark */
  1107. _cpReg[20] = _SHIFTL(_gpfifo->hi_mark,0,16);
  1108. _cpReg[21] = _SHIFTR(_gpfifo->hi_mark,16,16);
  1109. /* setup lowater mark */
  1110. _cpReg[22] = _SHIFTL(_gpfifo->lo_mark,0,16);
  1111. _cpReg[23] = _SHIFTR(_gpfifo->lo_mark,16,16);
  1112. /* setup rd<->wd dist */
  1113. _cpReg[24] = _SHIFTL(_gpfifo->rdwt_dst,0,16);
  1114. _cpReg[25] = _SHIFTR(_gpfifo->rdwt_dst,16,16);
  1115. /* setup wt ptr */
  1116. _cpReg[26] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(_gpfifo->wt_ptr),0,16);
  1117. _cpReg[27] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(_gpfifo->wt_ptr),16,16);
  1118. /* setup rd ptr */
  1119. _cpReg[28] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(_gpfifo->rd_ptr),0,16);
  1120. _cpReg[29] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(_gpfifo->rd_ptr),16,16);
  1121. if(_cpufifo==_gpfifo) {
  1122. _cpgplinked = 1;
  1123. __GX_WriteFifoIntEnable(GX_ENABLE,GX_DISABLE);
  1124. __GX_FifoLink(GX_TRUE);
  1125. } else {
  1126. _cpgplinked = 0;
  1127. __GX_WriteFifoIntEnable(GX_DISABLE,GX_DISABLE);
  1128. __GX_FifoLink(GX_FALSE);
  1129. }
  1130. __GX_WriteFifoIntReset(GX_TRUE,GX_TRUE);
  1131. __GX_FifoReadEnable();
  1132. _gxgpfifoready = 1;
  1133. _CPU_ISR_Restore(level);
  1134. }
  1135. GXFifoObj* GX_GetGPFifo()
  1136. {
  1137. return (GXFifoObj*)_gpfifo;
  1138. }
  1139. void GX_SaveCPUFifo(GXFifoObj *fifo)
  1140. {
  1141. struct __gxfifo *ptr = (struct __gxfifo*)fifo;
  1142. __GX_SaveCPUFifoAux(ptr);
  1143. }
  1144. u32 GX_GetOverflowCount()
  1145. {
  1146. return _gxoverflowcount;
  1147. }
  1148. u32 GX_ResetOverflowCount()
  1149. {
  1150. u32 ret = _gxoverflowcount;
  1151. _gxoverflowcount = 0;
  1152. return ret;
  1153. }
  1154. lwp_t GX_GetCurrentGXThread()
  1155. {
  1156. return _gxcurrentlwp;
  1157. }
  1158. lwp_t GX_SetCurrentGXThread()
  1159. {
  1160. u32 level;
  1161. _CPU_ISR_Disable(level);
  1162. lwp_t ret = _gxcurrentlwp;
  1163. _gxcurrentlwp = LWP_GetSelf();
  1164. _CPU_ISR_Restore(level);
  1165. return ret;
  1166. }
  1167. volatile void* GX_RedirectWriteGatherPipe(void *ptr)
  1168. {
  1169. u32 level;
  1170. _CPU_ISR_Disable(level);
  1171. GX_Flush();
  1172. while(!IsWriteGatherBufferEmpty());
  1173. mtwpar(0x0C008000);
  1174. if(_cpgplinked) {
  1175. __GX_FifoLink(GX_FALSE);
  1176. __GX_WriteFifoIntEnable(GX_DISABLE,GX_DISABLE);
  1177. }
  1178. _cpufifo->wt_ptr = (u32)MEM_PHYSICAL_TO_K0(_piReg[5]&~0x04000000);
  1179. _piReg[3] = 0;
  1180. _piReg[4] = 0x04000000;
  1181. _piReg[5] = (((u32)ptr&0x3FFFFFE0)&~0x04000000);
  1182. _sync();
  1183. _CPU_ISR_Restore(level);
  1184. return (volatile void*)0x0C008000;
  1185. }
  1186. void GX_RestoreWriteGatherPipe()
  1187. {
  1188. u32 level;
  1189. _CPU_ISR_Disable(level);
  1190. FIFO_PUTU32(0);
  1191. FIFO_PUTU32(0);
  1192. FIFO_PUTU32(0);
  1193. FIFO_PUTU32(0);
  1194. FIFO_PUTU32(0);
  1195. FIFO_PUTU32(0);
  1196. FIFO_PUTU32(0);
  1197. FIFO_PUTU32(0);
  1198. ppcsync();
  1199. while(!IsWriteGatherBufferEmpty());
  1200. mtwpar(0x0C008000);
  1201. _piReg[3] = MEM_VIRTUAL_TO_PHYSICAL(_cpufifo->buf_start);
  1202. _piReg[4] = MEM_VIRTUAL_TO_PHYSICAL(_cpufifo->buf_end);
  1203. _piReg[5] = (((u32)_cpufifo->wt_ptr&0x3FFFFFE0)&~0x04000000);
  1204. if(_cpgplinked) {
  1205. __GX_WriteFifoIntReset(GX_TRUE,GX_TRUE);
  1206. __GX_WriteFifoIntEnable(GX_ENABLE,GX_DISABLE);
  1207. __GX_FifoLink(GX_TRUE);
  1208. }
  1209. _sync();
  1210. _CPU_ISR_Restore(level);
  1211. }
  1212. void GX_Flush()
  1213. {
  1214. if(_gx[0x09])
  1215. __GX_SetDirtyState();
  1216. FIFO_PUTU32(0);
  1217. FIFO_PUTU32(0);
  1218. FIFO_PUTU32(0);
  1219. FIFO_PUTU32(0);
  1220. FIFO_PUTU32(0);
  1221. FIFO_PUTU32(0);
  1222. FIFO_PUTU32(0);
  1223. FIFO_PUTU32(0);
  1224. ppcsync();
  1225. }
  1226. void GX_EnableBreakPt(void *break_pt)
  1227. {
  1228. u32 level = 0;
  1229. _CPU_ISR_Disable(level);
  1230. __GX_FifoReadDisable();
  1231. _cpReg[30] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(break_pt),0,16);
  1232. _cpReg[31] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(break_pt),16,16);
  1233. ((u16*)_gx)[1] = (((u16*)_gx)[1]&~0x22)|0x22;
  1234. _cpReg[1] = ((u16*)_gx)[1];
  1235. _gxcurrbp = break_pt;
  1236. __GX_FifoReadEnable();
  1237. _CPU_ISR_Restore(level);
  1238. }
  1239. void GX_DisableBreakPt()
  1240. {
  1241. u32 level = 0;
  1242. _CPU_ISR_Disable(level);
  1243. ((u16*)_gx)[1] = (((u16*)_gx)[1]&~0x22);
  1244. _cpReg[1] = ((u16*)_gx)[1];
  1245. _gxcurrbp = NULL;
  1246. _CPU_ISR_Restore(level);
  1247. }
  1248. #if defined(HW_DOL)
  1249. void GX_AbortFrame()
  1250. {
  1251. _piReg[6] = 1;
  1252. __GX_WaitAbort(50);
  1253. _piReg[6] = 0;
  1254. __GX_WaitAbort(5);
  1255. if(__GX_IsGPFifoReady())
  1256. __GX_CleanGPFifo();
  1257. }
  1258. #elif defined(HW_RVL)
  1259. void GX_AbortFrame()
  1260. {
  1261. __GX_Abort();
  1262. if(__GX_IsGPFifoReady()) {
  1263. __GX_CleanGPFifo();
  1264. __GX_InitRevBits();
  1265. _gx[0x09] = 0;
  1266. GX_Flush();
  1267. }
  1268. }
  1269. #endif
  1270. void GX_SetDrawSync(u16 token)
  1271. {
  1272. u32 level = 0;
  1273. _CPU_ISR_Disable(level);
  1274. GX_LOAD_BP_REG(0x48000000 | token);
  1275. GX_LOAD_BP_REG(0x47000000 | token);
  1276. GX_Flush();
  1277. _CPU_ISR_Restore(level);
  1278. }
  1279. u16 GX_GetDrawSync()
  1280. {
  1281. return _peReg[7];
  1282. }
  1283. void GX_SetDrawDone()
  1284. {
  1285. u32 level;
  1286. _CPU_ISR_Disable(level);
  1287. GX_LOAD_BP_REG(0x45000002); // set draw done!
  1288. GX_Flush();
  1289. _gxfinished = 0;
  1290. _CPU_ISR_Restore(level);
  1291. }
  1292. void GX_WaitDrawDone()
  1293. {
  1294. u32 level;
  1295. #ifdef _GP_DEBUG
  1296. printf("GX_WaitDrawDone()\n\n");
  1297. #endif
  1298. _CPU_ISR_Disable(level);
  1299. while(!_gxfinished)
  1300. LWP_ThreadSleep(_gxwaitfinish);
  1301. _CPU_ISR_Restore(level);
  1302. }
  1303. void GX_DrawDone()
  1304. {
  1305. u32 level;
  1306. _CPU_ISR_Disable(level);
  1307. GX_LOAD_BP_REG(0x45000002); // set draw done!
  1308. GX_Flush();
  1309. _gxfinished = 0;
  1310. _CPU_ISR_Flash(level);
  1311. while(!_gxfinished)
  1312. LWP_ThreadSleep(_gxwaitfinish);
  1313. _CPU_ISR_Restore(level);
  1314. }
  1315. GXDrawDoneCallback GX_SetDrawDoneCallback(GXDrawDoneCallback cb)
  1316. {
  1317. u32 level;
  1318. _CPU_ISR_Disable(level);
  1319. GXDrawDoneCallback ret = drawDoneCB;
  1320. drawDoneCB = cb;
  1321. _CPU_ISR_Restore(level);
  1322. return ret;
  1323. }
  1324. GXDrawSyncCallback GX_SetDrawSyncCallback(GXDrawSyncCallback cb)
  1325. {
  1326. u32 level;
  1327. _CPU_ISR_Disable(level);
  1328. GXDrawSyncCallback ret = tokenCB;
  1329. tokenCB = cb;
  1330. _CPU_ISR_Restore(level);
  1331. return ret;
  1332. }
  1333. GXBreakPtCallback GX_SetBreakPtCallback(GXBreakPtCallback cb)
  1334. {
  1335. u32 level;
  1336. _CPU_ISR_Disable(level);
  1337. GXBreakPtCallback ret = breakPtCB;
  1338. breakPtCB = cb;
  1339. _CPU_ISR_Restore(level);
  1340. return ret;
  1341. }
  1342. void GX_PixModeSync()
  1343. {
  1344. GX_LOAD_BP_REG(_gx[0xbb]);
  1345. }
  1346. void GX_TexModeSync()
  1347. {
  1348. GX_LOAD_BP_REG(0x63000000);
  1349. }
  1350. void GX_SetMisc(u32 token,u32 value)
  1351. {
  1352. u32 cnt;
  1353. if(token==GX_MT_XF_FLUSH) {
  1354. ((u16*)_gx)[30] = value;
  1355. cnt = cntlzw(((u16*)_gx)[30]);
  1356. ((u16*)_gx)[28] = _SHIFTR(cnt,5,16);
  1357. ((u16*)_gx)[29] = 1;
  1358. if(!((u16*)_gx)[30]) return;
  1359. _gx[0x09] |= 0x0008;
  1360. } else if(token==GX_MT_DL_SAVE_CTX) {
  1361. ((u8*)_gx)[0x371] = (value&0xff);
  1362. }
  1363. return;
  1364. }
  1365. void GX_SetViewportJitter(f32 xOrig,f32 yOrig,f32 wd,f32 ht,f32 nearZ,f32 farZ,u32 field)
  1366. {
  1367. f32 x0,y0,x1,y1,n,f,z;
  1368. static f32 Xfactor = 0.5;
  1369. static f32 Yfactor = 342.0;
  1370. static f32 Zfactor = 16777215.0;
  1371. if(!field) yOrig -= Xfactor;
  1372. x0 = wd*Xfactor;
  1373. y0 = (-ht)*Xfactor;
  1374. x1 = (xOrig+(wd*Xfactor))+Yfactor;
  1375. y1 = (yOrig+(ht*Xfactor))+Yfactor;
  1376. n = Zfactor*nearZ;
  1377. f = Zfactor*farZ;
  1378. z = f-n;
  1379. GX_LOAD_XF_REGS(0x101a,6);
  1380. FIFO_PUTF32(x0);
  1381. FIFO_PUTF32(y0);
  1382. FIFO_PUTF32(z);
  1383. FIFO_PUTF32(x1);
  1384. FIFO_PUTF32(y1);
  1385. FIFO_PUTF32(f);
  1386. }
  1387. void GX_SetViewport(f32 xOrig,f32 yOrig,f32 wd,f32 ht,f32 nearZ,f32 farZ)
  1388. {
  1389. GX_SetViewportJitter(xOrig,yOrig,wd,ht,nearZ,farZ,1);
  1390. }
  1391. void GX_LoadProjectionMtx(Mtx44 mt,u8 type)
  1392. {
  1393. f32 tmp[7];
  1394. ((u32*)((void*)tmp))[6] = (u32)type;
  1395. tmp[0] = mt[0][0];
  1396. tmp[2] = mt[1][1];
  1397. tmp[4] = mt[2][2];
  1398. tmp[5] = mt[2][3];
  1399. switch(type) {
  1400. case GX_PERSPECTIVE:
  1401. tmp[1] = mt[0][2];
  1402. tmp[3] = mt[1][2];
  1403. break;
  1404. case GX_ORTHOGRAPHIC:
  1405. tmp[1] = mt[0][3];
  1406. tmp[3] = mt[1][3];
  1407. break;
  1408. }
  1409. GX_LOAD_XF_REGS(0x1020,7);
  1410. FIFO_PUTF32(tmp[0]);
  1411. FIFO_PUTF32(tmp[1]);
  1412. FIFO_PUTF32(tmp[2]);
  1413. FIFO_PUTF32(tmp[3]);
  1414. FIFO_PUTF32(tmp[4]);
  1415. FIFO_PUTF32(tmp[5]);
  1416. FIFO_PUTF32(tmp[6]);
  1417. }
  1418. static void __GetImageTileCount(u32 fmt,u16 wd,u16 ht,u32 *xtiles,u32 *ytiles,u32 *zplanes)
  1419. {
  1420. u32 xshift,yshift,tile;
  1421. switch(fmt) {
  1422. case GX_TF_I4:
  1423. case GX_TF_IA4:
  1424. case GX_CTF_R4:
  1425. case GX_CTF_RA4:
  1426. case GX_CTF_Z4:
  1427. xshift = 3;
  1428. yshift = 3;
  1429. break;
  1430. case GX_TF_Z8:
  1431. case GX_TF_I8:
  1432. case GX_TF_IA8:
  1433. case GX_CTF_RA8:
  1434. case GX_CTF_A8:
  1435. case GX_CTF_R8:
  1436. case GX_CTF_G8:
  1437. case GX_CTF_B8:
  1438. case GX_CTF_RG8:
  1439. case GX_CTF_GB8:
  1440. case GX_CTF_Z8M:
  1441. case GX_CTF_Z8L:
  1442. xshift = 3;
  1443. yshift = 2;
  1444. break;
  1445. case GX_TF_Z16:
  1446. case GX_TF_Z24X8:
  1447. case GX_CTF_Z16L:
  1448. case GX_TF_RGB565:
  1449. case GX_TF_RGB5A3:
  1450. case GX_TF_RGBA8:
  1451. xshift = 2;
  1452. yshift = 2;
  1453. break;
  1454. default:
  1455. xshift = 0;
  1456. yshift = 0;
  1457. break;
  1458. }
  1459. if(!(wd&0xffff)) wd = 1;
  1460. if(!(ht&0xffff)) ht = 1;
  1461. wd &= 0xffff;
  1462. tile = (wd+((1<<xshift)-1))>>xshift;
  1463. *xtiles = tile;
  1464. ht &= 0xffff;
  1465. tile = (ht+((1<<yshift)-1))>>yshift;
  1466. *ytiles = tile;
  1467. *zplanes = 1;
  1468. if(fmt==GX_TF_RGBA8 || fmt==GX_TF_Z24X8) *zplanes = 2;
  1469. }
  1470. void GX_SetCopyClear(GXColor color,u32 zvalue)
  1471. {
  1472. u32 val;
  1473. val = (_SHIFTL(color.a,8,8))|(color.r&0xff);
  1474. GX_LOAD_BP_REG(0x4f000000|val);
  1475. val = (_SHIFTL(color.g,8,8))|(color.b&0xff);
  1476. GX_LOAD_BP_REG(0x50000000|val);
  1477. val = zvalue&0x00ffffff;
  1478. GX_LOAD_BP_REG(0x51000000|val);
  1479. }
  1480. void GX_SetCopyClamp(u8 clamp)
  1481. {
  1482. _gx[0xab] = (_gx[0xab]&~1)|(clamp&1);
  1483. _gx[0xab] = (_gx[0xab]&~2)|(clamp&2);
  1484. }
  1485. void GX_SetDispCopyGamma(u8 gamma)
  1486. {
  1487. _gx[0xab] = (_gx[0xab]&~0x180)|(_SHIFTL(gamma,7,2));
  1488. }
  1489. void GX_SetCopyFilter(u8 aa,u8 sample_pattern[12][2],u8 vf,u8 vfilter[7])
  1490. {
  1491. u32 reg01=0,reg02=0,reg03=0,reg04=0,reg53=0,reg54=0;
  1492. if(aa) {
  1493. reg01 = sample_pattern[0][0]&0xf;
  1494. reg01 = (reg01&~0xf0)|(_SHIFTL(sample_pattern[0][1],4,4));
  1495. reg01 = (reg01&~0xf00)|(_SHIFTL(sample_pattern[1][0],8,4));
  1496. reg01 = (reg01&~0xf000)|(_SHIFTL(sample_pattern[1][1],12,4));
  1497. reg01 = (reg01&~0xf0000)|(_SHIFTL(sample_pattern[2][0],16,4));
  1498. reg01 = (reg01&~0xf00000)|(_SHIFTL(sample_pattern[2][1],20,4));
  1499. reg01 = (reg01&~0xff000000)|(_SHIFTL(0x01,24,8));
  1500. reg02 = sample_pattern[3][0]&0xf;
  1501. reg02 = (reg02&~0xf0)|(_SHIFTL(sample_pattern[3][1],4,4));
  1502. reg02 = (reg02&~0xf00)|(_SHIFTL(sample_pattern[4][0],8,4));
  1503. reg02 = (reg02&~0xf000)|(_SHIFTL(sample_pattern[4][1],12,4));
  1504. reg02 = (reg02&~0xf0000)|(_SHIFTL(sample_pattern[5][0],16,4));
  1505. reg02 = (reg02&~0xf00000)|(_SHIFTL(sample_pattern[5][1],20,4));
  1506. reg02 = (reg02&~0xff000000)|(_SHIFTL(0x02,24,8));
  1507. reg03 = sample_pattern[6][0]&0xf;
  1508. reg03 = (reg03&~0xf0)|(_SHIFTL(sample_pattern[6][1],4,4));
  1509. reg03 = (reg03&~0xf00)|(_SHIFTL(sample_pattern[7][0],8,4));
  1510. reg03 = (reg03&~0xf000)|(_SHIFTL(sample_pattern[7][1],12,4));
  1511. reg03 = (reg03&~0xf0000)|(_SHIFTL(sample_pattern[8][0],16,4));
  1512. reg03 = (reg03&~0xf00000)|(_SHIFTL(sample_pattern[8][1],20,4));
  1513. reg03 = (reg03&~0xff000000)|(_SHIFTL(0x03,24,8));
  1514. reg04 = sample_pattern[9][0]&0xf;
  1515. reg04 = (reg04&~0xf0)|(_SHIFTL(sample_pattern[9][1],4,4));
  1516. reg04 = (reg04&~0xf00)|(_SHIFTL(sample_pattern[10][0],8,4));
  1517. reg04 = (reg04&~0xf000)|(_SHIFTL(sample_pattern[10][1],12,4));
  1518. reg04 = (reg04&~0xf0000)|(_SHIFTL(sample_pattern[11][0],16,4));
  1519. reg04 = (reg04&~0xf00000)|(_SHIFTL(sample_pattern[11][1],20,4));
  1520. reg04 = (reg04&~0xff000000)|(_SHIFTL(0x04,24,8));
  1521. } else {
  1522. reg01 = 0x01666666;
  1523. reg02 = 0x02666666;
  1524. reg03 = 0x03666666;
  1525. reg04 = 0x04666666;
  1526. }
  1527. GX_LOAD_BP_REG(reg01);
  1528. GX_LOAD_BP_REG(reg02);
  1529. GX_LOAD_BP_REG(reg03);
  1530. GX_LOAD_BP_REG(reg04);
  1531. reg53 = 0x53595000;
  1532. reg54 = 0x54000015;
  1533. if(vf) {
  1534. reg53 = 0x53000000|(vfilter[0]&0x3f);
  1535. reg53 = (reg53&~0xfc0)|(_SHIFTL(vfilter[1],6,6));
  1536. reg53 = (reg53&~0x3f000)|(_SHIFTL(vfilter[2],12,6));
  1537. reg53 = (reg53&~0xfc0000)|(_SHIFTL(vfilter[3],18,6));
  1538. reg54 = 0x54000000|(vfilter[4]&0x3f);
  1539. reg54 = (reg54&~0xfc0)|(_SHIFTL(vfilter[5],6,6));
  1540. reg54 = (reg54&~0x3f000)|(_SHIFTL(vfilter[6],12,6));
  1541. }
  1542. GX_LOAD_BP_REG(reg53);
  1543. GX_LOAD_BP_REG(reg54);
  1544. }
  1545. void GX_SetDispCopyFrame2Field(u8 mode)
  1546. {
  1547. _gx[0xab] = (_gx[0xab]&~0x3000)|(_SHIFTL(mode,12,2));
  1548. }
  1549. u32 GX_SetDispCopyYScale(f32 yscale)
  1550. {
  1551. u32 ht,yScale = 0;
  1552. yScale = ((u32)(256.0f/yscale))&0x1ff;
  1553. GX_LOAD_BP_REG(0x4e000000|yScale);
  1554. _gx[0xab] = (_gx[0xab]&~0x400)|(_SHIFTL(((256-yScale)>0),10,1));
  1555. ht = _SHIFTR(_gx[0xcc],12,10)+1;
  1556. return __GX_GetNumXfbLines(ht,yScale);
  1557. }
  1558. void GX_SetDispCopyDst(u16 wd,u16 ht)
  1559. {
  1560. _gx[0xcd] = (_gx[0xcd]&~0x3ff)|(_SHIFTR(wd,4,10));
  1561. _gx[0xcd] = (_gx[0xcd]&~0xff000000)|(_SHIFTL(0x4d,24,8));
  1562. }
  1563. void GX_SetDispCopySrc(u16 left,u16 top,u16 wd,u16 ht)
  1564. {
  1565. _gx[0xcb] = (_gx[0xcb]&~0x00ffffff)|XY(left,top);
  1566. _gx[0xcb] = (_gx[0xcb]&~0xff000000)|(_SHIFTL(0x49,24,8));
  1567. _gx[0xcc] = (_gx[0xcc]&~0x00ffffff)|XY((wd-1),(ht-1));
  1568. _gx[0xcc] = (_gx[0xcc]&~0xff000000)|(_SHIFTL(0x4a,24,8));
  1569. }
  1570. void GX_CopyDisp(void *dest,u8 clear)
  1571. {
  1572. u8 clflag;
  1573. u32 val;
  1574. if(clear) {
  1575. val= (_gx[0xb8]&~0xf)|0xf;
  1576. GX_LOAD_BP_REG(val);
  1577. val = (_gx[0xb9]&~0x3);
  1578. GX_LOAD_BP_REG(val);
  1579. }
  1580. clflag = 0;
  1581. if(clear || (_gx[0xbb]&0x7)==0x0003) {
  1582. if(_gx[0xbb]&0x40) {
  1583. clflag = 1;
  1584. val = (_gx[0xbb]&~0x40);
  1585. GX_LOAD_BP_REG(val);
  1586. }
  1587. }
  1588. GX_LOAD_BP_REG(_gx[0xcb]); // set source top
  1589. GX_LOAD_BP_REG(_gx[0xcc]);
  1590. GX_LOAD_BP_REG(_gx[0xcd]);
  1591. val = 0x4b000000|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(dest),5,24));
  1592. GX_LOAD_BP_REG(val);
  1593. _gx[0xab] = (_gx[0xab]&~0x800)|(_SHIFTL(clear,11,1));
  1594. _gx[0xab] = (_gx[0xab]&~0x4000)|0x4000;
  1595. _gx[0xab] = (_gx[0xab]&~0xff000000)|(_SHIFTL(0x52,24,8));
  1596. GX_LOAD_BP_REG(_gx[0xab]);
  1597. if(clear) {
  1598. GX_LOAD_BP_REG(_gx[0xb8]);
  1599. GX_LOAD_BP_REG(_gx[0xb9]);
  1600. }
  1601. if(clflag) GX_LOAD_BP_REG(_gx[0xbb]);
  1602. }
  1603. void GX_CopyTex(void *dest,u8 clear)
  1604. {
  1605. u8 clflag;
  1606. u32 val;
  1607. if(clear) {
  1608. val = (_gx[0xb8]&~0xf)|0xf;
  1609. GX_LOAD_BP_REG(val);
  1610. val = (_gx[0xb9]&~0x3);
  1611. GX_LOAD_BP_REG(val);
  1612. }
  1613. clflag = 0;
  1614. val = _gx[0xbb];
  1615. if(((u8*)_gx)[0x370] && (val&0x7)!=0x0003) {
  1616. clflag = 1;
  1617. val = (val&~0x7)|0x0003;
  1618. }
  1619. if(clear || (val&0x7)==0x0003) {
  1620. if(val&0x40) {
  1621. clflag = 1;
  1622. val = (val&~0x40);
  1623. }
  1624. }
  1625. if(clflag) GX_LOAD_BP_REG(val);
  1626. val = 0x4b000000|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(dest),5,24));
  1627. GX_LOAD_BP_REG(_gx[0xd8]);
  1628. GX_LOAD_BP_REG(_gx[0xd9]);
  1629. GX_LOAD_BP_REG(_gx[0xda]);
  1630. GX_LOAD_BP_REG(val);
  1631. _gx[0xdb] = (_gx[0xdb]&~0x800)|(_SHIFTL(clear,11,1));
  1632. _gx[0xdb] = (_gx[0xdb]&~0x4000);
  1633. _gx[0xdb] = (_gx[0xdb]&~0xff000000)|(_SHIFTL(0x52,24,8));
  1634. GX_LOAD_BP_REG(_gx[0xdb]);
  1635. if(clear) {
  1636. GX_LOAD_BP_REG(_gx[0xb8]);
  1637. GX_LOAD_BP_REG(_gx[0xb9]);
  1638. }
  1639. if(clflag) GX_LOAD_BP_REG(_gx[0xbb]);
  1640. }
  1641. void GX_SetTexCopySrc(u16 left,u16 top,u16 wd,u16 ht)
  1642. {
  1643. _gx[0xd8] = (_gx[0xd8]&~0x00ffffff)|XY(left,top);
  1644. _gx[0xd8] = (_gx[0xd8]&~0xff000000)|(_SHIFTL(0x49,24,8));
  1645. _gx[0xd9] = (_gx[0xd9]&~0x00ffffff)|XY((wd-1),(ht-1));
  1646. _gx[0xd9] = (_gx[0xd9]&~0xff000000)|(_SHIFTL(0x4a,24,8));
  1647. }
  1648. void GX_SetTexCopyDst(u16 wd,u16 ht,u32 fmt,u8 mipmap)
  1649. {
  1650. u8 lfmt = fmt&0xf;
  1651. u32 xtiles,ytiles,zplanes;
  1652. __GetImageTileCount(fmt,wd,ht,&xtiles,&ytiles,&zplanes);
  1653. _gx[0xda] = (_gx[0xda]&~0x3ff)|((xtiles*zplanes)&0x3ff);
  1654. if(fmt==GX_TF_Z16) lfmt = 11;
  1655. if(fmt==GX_CTF_YUVA8 || (fmt>=GX_TF_I4 && fmt<GX_TF_RGB565)) _gx[0xdb] = (_gx[0xdb]&~0x18000)|0x18000;
  1656. else _gx[0xdb] = (_gx[0xdb]&~0x18000)|0x10000;
  1657. _gx[0xdb] = (_gx[0xdb]&~0x8)|(lfmt&0x8);
  1658. _gx[0xdb] = (_gx[0xdb]&~0x200)|(_SHIFTL(mipmap,9,1));
  1659. _gx[0xdb] = (_gx[0xdb]&~0x70)|(_SHIFTL(lfmt,4,3));
  1660. _gx[0xda] = (_gx[0xda]&~0xff000000)|(_SHIFTL(0x4d,24,8));
  1661. ((u8*)_gx)[0x370] = 0;
  1662. ((u8*)_gx)[0x370] = ((fmt&0x10)-16)?0:1;
  1663. }
  1664. void GX_ClearBoundingBox()
  1665. {
  1666. GX_LOAD_BP_REG(0x550003ff);
  1667. GX_LOAD_BP_REG(0x560003ff);
  1668. }
  1669. void GX_BeginDispList(void *list,u32 size)
  1670. {
  1671. GXFifoObj *curr_fifo;
  1672. curr_fifo = GX_GetCPUFifo();
  1673. if(_gx[0x09])
  1674. __GX_SetDirtyState();
  1675. if(((u8*)_gx)[0x371])
  1676. memcpy(_gx_saved_data,_gx,1280);
  1677. _gx_dl_fifo.buf_start = (u32)list;
  1678. _gx_dl_fifo.buf_end = (u32)list + size - 4;
  1679. _gx_dl_fifo.size = size;
  1680. _gx_dl_fifo.rd_ptr = (u32)list;
  1681. _gx_dl_fifo.wt_ptr = (u32)list;
  1682. _gx_dl_fifo.rdwt_dst = 0;
  1683. ((u8*)_gx)[0x372] = 1;
  1684. GX_SaveCPUFifo(curr_fifo);
  1685. _gxoldcpufifo = curr_fifo;
  1686. GX_SetGPFifo((GXFifoObj*)&_gx_dl_fifo);
  1687. }
  1688. u32 GX_EndDispList()
  1689. {
  1690. u32 val;
  1691. u32 level,ret = 0;
  1692. if(_gx[0x09])
  1693. __GX_SetDirtyState();
  1694. __GX_SaveCPUFifoAux(&_gx_dl_fifo);
  1695. GX_SetCPUFifo(_gxoldcpufifo);
  1696. val = _SHIFTR(_piReg[5],26,1);
  1697. if(((u8*)_gx)[0x371]) {
  1698. _CPU_ISR_Disable(level);
  1699. memcpy(_gx,_gx_saved_data,1272);
  1700. _CPU_ISR_Restore(level);
  1701. }
  1702. ((u8*)_gx)[0x372] = 0;
  1703. if( _SHIFTR(_piReg[5],26,1)) ret = _gx_dl_fifo.rdwt_dst;
  1704. return ret;
  1705. }
  1706. void GX_CallDispList(void *list,u32 nbytes)
  1707. {
  1708. if(_gx[0x09])
  1709. __GX_SetDirtyState();
  1710. if(!_gx[0xf8])
  1711. __GX_SendFlushPrim();
  1712. FIFO_PUTU8(0x40); //call displaylist
  1713. FIFO_PUTU32(MEM_VIRTUAL_TO_PHYSICAL(list));
  1714. FIFO_PUTU32(nbytes);
  1715. }
  1716. void GX_SetChanCtrl(s32 channel,u8 enable,u8 ambsrc,u8 matsrc,u8 litmask,u8 diff_fn,u8 attn_fn)
  1717. {
  1718. u32 reg,difffn = (attn_fn==GX_AF_SPEC)?GX_DF_NONE:diff_fn;
  1719. u32 val = (matsrc&1)|(_SHIFTL(enable,1,1))|(_SHIFTL(litmask,2,4))|(_SHIFTL(ambsrc,6,1))|(_SHIFTL(difffn,7,2))|(_SHIFTL(((GX_AF_NONE-attn_fn)>0),9,1))|(_SHIFTL((attn_fn&1),10,1))|(_SHIFTL((_SHIFTR(litmask,4,4)),11,4));
  1720. reg = (channel&0x03);
  1721. _gx[0xf4+reg] = val;
  1722. _gx[0x09] |= (0x1000<<reg);
  1723. if(channel==GX_COLOR0A0) {
  1724. _gx[0xf6] = val;
  1725. _gx[0x09] |= 0x5000;
  1726. } else {
  1727. _gx[0xf7] = val;
  1728. _gx[0x09] |= 0xa000;
  1729. }
  1730. }
  1731. void GX_SetChanAmbColor(s32 channel,GXColor color)
  1732. {
  1733. u32 reg,val = (_SHIFTL(color.r,24,8))|(_SHIFTL(color.g,16,8))|(_SHIFTL(color.b,8,8))|0x00;
  1734. switch(channel) {
  1735. case GX_COLOR0:
  1736. reg = 0;
  1737. val |= (_gx[0xf0]&0xff);
  1738. break;
  1739. case GX_COLOR1:
  1740. reg = 1;
  1741. val |= (_gx[0xf1]&0xff);
  1742. break;
  1743. case GX_ALPHA0:
  1744. reg = 0;
  1745. val = ((_gx[0xf0]&~0xff)|(color.a&0xff));
  1746. break;
  1747. case GX_ALPHA1:
  1748. reg = 1;
  1749. val = ((_gx[0xf1]&~0xff)|(color.a&0xff));
  1750. break;
  1751. case GX_COLOR0A0:
  1752. reg = 0;
  1753. val |= (color.a&0xFF);
  1754. break;
  1755. case GX_COLOR1A1:
  1756. reg = 1;
  1757. val |= (color.a&0xFF);
  1758. break;
  1759. default:
  1760. return;
  1761. }
  1762. _gx[0xf0+reg] = val;
  1763. _gx[0x09] |= (0x0100<<reg);
  1764. }
  1765. void GX_SetChanMatColor(s32 channel,GXColor color)
  1766. {
  1767. u32 reg,val = (_SHIFTL(color.r,24,8))|(_SHIFTL(color.g,16,8))|(_SHIFTL(color.b,8,8))|0x00;
  1768. switch(channel) {
  1769. case GX_COLOR0:
  1770. reg = 0;
  1771. val |= (_gx[0xf2]&0xff);
  1772. break;
  1773. case GX_COLOR1:
  1774. reg = 1;
  1775. val |= (_gx[0xf3]&0xff);
  1776. break;
  1777. case GX_ALPHA0:
  1778. reg = 0;
  1779. val = ((_gx[0xf2]&~0xff)|(color.a&0xff));
  1780. break;
  1781. case GX_ALPHA1:
  1782. reg = 1;
  1783. val = ((_gx[0xf3]&~0xff)|(color.a&0xff));
  1784. break;
  1785. case GX_COLOR0A0:
  1786. reg = 0;
  1787. val |= (color.a&0xFF);
  1788. break;
  1789. case GX_COLOR1A1:
  1790. reg = 1;
  1791. val |= (color.a&0xFF);
  1792. break;
  1793. default:
  1794. return;
  1795. }
  1796. _gx[0xf2+reg] = val;
  1797. _gx[0x09]

Large files files are truncated, but you can click here to view the full file