tinysmb devoptab fix - allow fread sizes > 7236
[libogc.git] / libogc / gx.c
blob94b710922ecebf353bac8669993f4854d3acfc46
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 #include "gx_regdef.h"
16 //#define _GP_DEBUG
17 #define TEXCACHE_TESTING
20 #define GX_FINISH 2
21 #define LARGE_NUMBER (1024*1024)
23 #define _SHIFTL(v, s, w) \
24 ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
25 #define _SHIFTR(v, s, w) \
26 ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
28 #define GX_LOAD_BP_REG(x) \
29 do { \
30 FIFO_PUTU8(0x61); \
31 FIFO_PUTU32((x)); \
32 } 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)
41 #define GX_LOAD_XF_REG(x, y) \
42 do { \
43 FIFO_PUTU8(0x10); \
44 FIFO_PUTU32(((x)&0xffff)); \
45 FIFO_PUTU32((y)); \
46 } while(0)
48 #define GX_LOAD_XF_REGS(x, n) \
49 do { \
50 FIFO_PUTU8(0x10); \
51 FIFO_PUTU32((((((n)&0xffff)-1)<<16)|((x)&0xffff))); \
52 } while(0)
54 #define XY(x, y) (((y) << 10) | (x))
56 #define GX_DEFAULT_BG {64,64,64,255}
57 #define BLACK {0,0,0,0}
58 #define WHITE {255,255,255,255}
60 static GXFifoObj _gpfifo;
61 static GXFifoObj _cpufifo;
62 static GXFifoObj _gxfifoobj;
63 static GXFifoObj _gx_dl_fifoobj;
64 static GXFifoObj _gx_old_cpufifo;
65 static void *_gxcurrbp = NULL;
66 static lwp_t _gxcurrentlwp = LWP_THREAD_NULL;
68 static u32 _gxcpufifoready = 0;
69 static u32 _gxgpfifoready = 0;
70 static u32 _cpgplinked = 0;
71 static u16 _gxgpstatus = 0;
72 static vu32 _gxoverflowsuspend = 0;
73 static vu32 _gxoverflowcount = 0;
74 static vu32 _gxfinished = 0;
75 static lwpq_t _gxwaitfinish;
77 static GXBreakPtCallback breakPtCB = NULL;
78 static GXDrawDoneCallback drawDoneCB = NULL;
79 static GXDrawSyncCallback tokenCB = NULL;
81 static GXTexRegionCallback regionCB = NULL;
82 static GXTlutRegionCallback tlut_regionCB = NULL;
84 static vu32* const _piReg = (u32*)0xCC003000;
85 static vu16* const _cpReg = (u16*)0xCC000000;
86 static vu16* const _peReg = (u16*)0xCC001000;
87 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};
98 #if defined(HW_RVL)
99 static u32 _gxtexregionaddrtable[48] =
101 0x00000000,0x00010000,0x00020000,0x00030000,
102 0x00040000,0x00050000,0x00060000,0x00070000,
103 0x00008000,0x00018000,0x00028000,0x00038000,
104 0x00048000,0x00058000,0x00068000,0x00078000,
105 0x00000000,0x00090000,0x00020000,0x000B0000,
106 0x00040000,0x00098000,0x00060000,0x000B8000,
107 0x00080000,0x00010000,0x000A0000,0x00030000,
108 0x00088000,0x00050000,0x000A8000,0x00070000,
109 0x00000000,0x00090000,0x00020000,0x000B0000,
110 0x00040000,0x00090000,0x00060000,0x000B0000,
111 0x00080000,0x00010000,0x000A0000,0x00030000,
112 0x00080000,0x00050000,0x000A0000,0x00070000
114 #endif
117 extern u8 __gxregs[];
118 static struct __gx_regdef *__gx = (struct __gx_regdef*)__gxregs;
119 static u8 _gx_saved_data[STRUCT_REGDEF_SIZE] ATTRIBUTE_ALIGN(32);
121 extern void __UnmaskIrq(u32);
122 extern void __MaskIrq(u32);
124 static s32 __gx_onreset(s32 final);
126 static sys_resetinfo __gx_resetinfo = {
128 __gx_onreset,
132 #ifdef _GP_DEBUG
133 extern int printk(const char *fmt,...);
134 #endif
136 static __inline__ BOOL IsWriteGatherBufferEmpty()
138 return !(mfwpar()&1);
141 static __inline__ void DisableWriteGatherPipe()
143 mthid2((mfhid2()&~0x40000000));
146 static __inline__ void EnableWriteGatherPipe()
148 mtwpar(0x0C008000);
149 mthid2((mfhid2()|0x40000000));
152 static __inline__ void __GX_ResetWriteGatherPipe()
154 while(mfwpar()&1);
155 mtwpar(0x0C008000);
158 static __inline__ void __GX_FifoLink(u8 enable)
160 __gx->cpCRreg = ((__gx->cpCRreg&~0x10)|(_SHIFTL(enable,4,1)));
161 _cpReg[1] = __gx->cpCRreg;
164 static __inline__ void __GX_WriteFifoIntReset(u8 inthi,u8 intlo)
166 __gx->cpCLreg = ((__gx->cpCLreg&~0x03)|(_SHIFTL(intlo,1,1))|(inthi&1));
167 _cpReg[2] = __gx->cpCLreg;
170 static __inline__ void __GX_WriteFifoIntEnable(u8 inthi, u8 intlo)
172 __gx->cpCRreg = ((__gx->cpCRreg&~0x0C)|(_SHIFTL(intlo,3,1))|(_SHIFTL(inthi,2,1)));
173 _cpReg[1] = __gx->cpCRreg;
176 static __inline__ void __GX_FifoReadEnable()
178 __gx->cpCRreg = ((__gx->cpCRreg&~0x01)|1);
179 _cpReg[1] = __gx->cpCRreg;
182 static __inline__ void __GX_FifoReadDisable()
184 __gx->cpCRreg = ((__gx->cpCRreg&~0x01)|0);
185 _cpReg[1] = __gx->cpCRreg;
188 static s32 __gx_onreset(s32 final)
190 if(final==FALSE) {
191 GX_Flush();
192 GX_AbortFrame();
194 return 1;
197 static u32 __GX_IsGPCPUFifoLinked()
199 return _cpgplinked;
202 static u32 __GX_IsGPFifoReady()
204 return _gxgpfifoready;
207 static u32 __GX_IsCPUFifoReady()
209 return _gxcpufifoready;
212 static u32 __GX_CPGPLinkCheck()
214 struct __gxfifo *gpfifo = (struct __gxfifo*)&_gpfifo;
215 struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
217 if(!_gxcpufifoready || !_gxgpfifoready) return 0;
219 if((cpufifo->buf_start==gpfifo->buf_start)&&(cpufifo->buf_end==gpfifo->buf_end)) return 1;
221 return 0;
224 static void __GX_InitRevBits()
226 s32 i;
228 i=0;
229 while(i<8) {
230 __gx->VAT0reg[i] = 0x40000000;
231 __gx->VAT1reg[i] = 0x80000000;
232 GX_LOAD_CP_REG((0x0080|i),__gx->VAT1reg[i]);
233 i++;
236 GX_LOAD_XF_REG(0x1000,0x3f);
237 GX_LOAD_XF_REG(0x1012,0x01);
239 GX_LOAD_BP_REG(0x5800000f);
243 static void __GX_WaitAbort(u32 delay)
245 u64 start,end;
247 start = gettime();
248 while(1) {
249 end = gettime();
250 if(diff_ticks(start,end)>=(u64)delay) break;
254 static u32 __GX_ReadMemCounterU32(u32 reg)
256 u16 lcnt,ucnt,tmp;
258 tmp = _memReg[reg];
259 do {
260 ucnt = tmp;
261 lcnt = _memReg[reg+1];
262 tmp = _memReg[reg];
263 } while(tmp!=ucnt);
264 return (u32)((ucnt<<16)|lcnt);
267 static void __GX_WaitAbortPixelEngine()
269 u32 cnt,tmp;
271 cnt = __GX_ReadMemCounterU32(39);
272 do {
273 tmp = cnt;
274 __GX_WaitAbort(8);
275 cnt = __GX_ReadMemCounterU32(39);
276 } while(cnt!=tmp);
279 static void __GX_Abort()
281 if(__gx->gxFifoInited && __GX_IsGPFifoReady())
282 __GX_WaitAbortPixelEngine();
284 _piReg[6] = 1;
285 __GX_WaitAbort(50);
287 _piReg[6] = 0;
288 __GX_WaitAbort(5);
291 static void __GX_SaveFifo()
293 s32 rdwt_dst;
294 u32 level,val;
295 struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
296 struct __gxfifo *gpfifo = (struct __gxfifo*)&_gpfifo;
298 _CPU_ISR_Disable(level);
300 if(_gxcpufifoready) {
301 val = _piReg[0x05];
302 cpufifo->wt_ptr = (u32)MEM_PHYSICAL_TO_K0((val&0x1FFFFFE0));
303 cpufifo->fifo_wrap = ((val&0x20000000)==0x20000000);
306 if(_gxgpfifoready) {
307 gpfifo->rd_ptr = (u32)MEM_PHYSICAL_TO_K0(_SHIFTL(_cpReg[29],16,16)|(_cpReg[28]&0xffff));
308 gpfifo->rdwt_dst = (_SHIFTL(_cpReg[25],16,16)|(_cpReg[24]&0xffff));
311 if(_cpgplinked) {
312 cpufifo->rd_ptr = gpfifo->rd_ptr;
313 cpufifo->rdwt_dst = gpfifo->rdwt_dst;
314 gpfifo->wt_ptr = cpufifo->wt_ptr;
315 } else if(_gxcpufifoready) {
316 rdwt_dst = (cpufifo->wt_ptr - cpufifo->rd_ptr);
317 if(rdwt_dst<0) cpufifo->rdwt_dst = (cpufifo->rdwt_dst + cpufifo->size);
318 else cpufifo->rdwt_dst = rdwt_dst;
321 _CPU_ISR_Restore(level);
324 static void __GX_CleanGPFifo()
326 u32 level;
327 struct __gxfifo *gpfifo = (struct __gxfifo*)&_gpfifo;
328 struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
330 if(!_gxgpfifoready) return;
332 _CPU_ISR_Disable(level);
333 __GX_FifoReadDisable();
334 __GX_WriteFifoIntEnable(FALSE,FALSE);
336 gpfifo->rd_ptr = gpfifo->wt_ptr;
337 gpfifo->rdwt_dst = 0;
339 /* setup rd<->wd dist */
340 _cpReg[24] = _SHIFTL(gpfifo->rdwt_dst,0,16);
341 _cpReg[25] = _SHIFTR(gpfifo->rdwt_dst,16,16);
343 /* setup wt ptr */
344 _cpReg[26] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->wt_ptr),0,16);
345 _cpReg[27] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->wt_ptr),16,16);
347 /* setup rd ptr */
348 _cpReg[28] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->rd_ptr),0,16);
349 _cpReg[29] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->rd_ptr),16,16);
350 ppcsync();
352 if(_cpgplinked) {
353 cpufifo->rd_ptr = gpfifo->rd_ptr;
354 cpufifo->wt_ptr = gpfifo->wt_ptr;
355 cpufifo->rdwt_dst = gpfifo->rdwt_dst;
357 _piReg[5] = (cpufifo->wt_ptr&0x1FFFFFE0);
358 __GX_WriteFifoIntEnable(TRUE,FALSE);
359 __GX_FifoLink(TRUE);
361 __gx->cpCRreg &= ~0x22;
362 _cpReg[1] = __gx->cpCRreg;
363 breakPtCB = NULL;
365 __GX_WriteFifoIntReset(TRUE,TRUE);
366 __GX_FifoReadEnable();
367 _CPU_ISR_Restore(level);
370 static void __GXOverflowHandler()
372 if(!_gxoverflowsuspend) {
373 _gxoverflowsuspend = 1;
374 _gxoverflowcount++;
375 __GX_WriteFifoIntEnable(GX_DISABLE,GX_ENABLE);
376 __GX_WriteFifoIntReset(GX_TRUE,GX_FALSE);
377 LWP_SuspendThread(_gxcurrentlwp);
381 static void __GXUnderflowHandler()
383 if(_gxoverflowsuspend) {
384 _gxoverflowsuspend = 0;
385 LWP_ResumeThread(_gxcurrentlwp);
386 __GX_WriteFifoIntReset(GX_TRUE,GX_TRUE);
387 __GX_WriteFifoIntEnable(GX_ENABLE,GX_DISABLE);
391 static void __GXCPInterruptHandler(u32 irq,void *ctx)
393 __gx->cpSRreg = _cpReg[0];
395 if((__gx->cpCRreg&0x08) && (__gx->cpSRreg&0x02))
396 __GXUnderflowHandler();
398 if((__gx->cpCRreg&0x04) && (__gx->cpSRreg&0x01))
399 __GXOverflowHandler();
401 if((__gx->cpCRreg&0x20) && (__gx->cpSRreg&0x10)) {
402 __gx->cpCRreg &= ~0x20;
403 _cpReg[1] = __gx->cpCRreg;
404 if(breakPtCB)
405 breakPtCB();
409 static void __GXTokenInterruptHandler(u32 irq,void *ctx)
411 u16 token = _peReg[7];
413 if(tokenCB)
414 tokenCB(token);
416 _peReg[5] = (_peReg[5]&~0x04)|0x04;
419 static void __GXFinishInterruptHandler(u32 irq,void *ctx)
421 #ifdef _GP_DEBUG
422 printf("__GXFinishInterruptHandler()\n");
423 #endif
424 _peReg[5] = (_peReg[5]&~0x08)|0x08;
425 _gxfinished = 1;
427 if(drawDoneCB)
428 drawDoneCB();
430 LWP_ThreadBroadcast(_gxwaitfinish);
433 static void __GX_PEInit()
435 IRQ_Request(IRQ_PI_PETOKEN,__GXTokenInterruptHandler,NULL);
436 __UnmaskIrq(IRQMASK(IRQ_PI_PETOKEN));
438 IRQ_Request(IRQ_PI_PEFINISH,__GXFinishInterruptHandler,NULL);
439 __UnmaskIrq(IRQMASK(IRQ_PI_PEFINISH));
441 _peReg[5] = 0x0F;
444 static void __GX_FifoInit()
446 IRQ_Request(IRQ_PI_CP,__GXCPInterruptHandler,NULL);
447 __UnmaskIrq(IRQMASK(IRQ_PI_CP));
449 memset(&_cpufifo,0,sizeof(GXFifoObj));
450 memset(&_gpfifo,0,sizeof(GXFifoObj));
452 _gxcpufifoready = 0;
453 _gxgpfifoready = 0;
454 _cpgplinked = 0;
455 _gxoverflowsuspend = 0;
456 _gxcurrentlwp = LWP_GetSelf();
459 static void __GX_SetTmemConfig(u8 nr)
461 if(nr==0) {
462 // Set_TextureImage0-3, GXTexMapID=0-3 tmem_offset=00000000, cache_width=32 kb, cache_height=32 kb, image_type=cached
463 GX_LOAD_BP_REG(0x8c0d8000);
464 GX_LOAD_BP_REG(0x900dc000);
465 GX_LOAD_BP_REG(0x8d0d8400);
466 GX_LOAD_BP_REG(0x910dc400);
467 GX_LOAD_BP_REG(0x8e0d8800);
468 GX_LOAD_BP_REG(0x920dc800);
469 GX_LOAD_BP_REG(0x8f0d8c00);
470 GX_LOAD_BP_REG(0x930dcc00);
472 // Set_TextureImage0-3, GXTexMapID=4-7 tmem_offset=00010000, cache_width=32 kb, cache_height=32 kb, image_type=cached
473 GX_LOAD_BP_REG(0xac0d9000);
474 GX_LOAD_BP_REG(0xb00dd000);
475 GX_LOAD_BP_REG(0xad0d9400);
476 GX_LOAD_BP_REG(0xb10dd400);
477 GX_LOAD_BP_REG(0xae0d9800);
478 GX_LOAD_BP_REG(0xb20dd800);
479 GX_LOAD_BP_REG(0xaf0d9c00);
480 GX_LOAD_BP_REG(0xb30ddc00);
482 return;
485 if(nr==1) {
486 // Set_TextureImage0-3, GXTexMapID=0-3 tmem_offset=00000000, cache_width=32 kb, cache_height=32 kb, image_type=cached
487 GX_LOAD_BP_REG(0x8c0d8000);
488 GX_LOAD_BP_REG(0x900dc000);
489 GX_LOAD_BP_REG(0x8d0d8800);
490 GX_LOAD_BP_REG(0x910dc800);
491 GX_LOAD_BP_REG(0x8e0d9000);
492 GX_LOAD_BP_REG(0x920dd000);
493 GX_LOAD_BP_REG(0x8f0d9800);
494 GX_LOAD_BP_REG(0x930dd800);
496 // Set_TextureImage0-3, GXTexMapID=4-7 tmem_offset=00010000, cache_width=32 kb, cache_height=32 kb, image_type=cached
497 GX_LOAD_BP_REG(0xac0da000);
498 GX_LOAD_BP_REG(0xb00de000);
499 GX_LOAD_BP_REG(0xad0da800);
500 GX_LOAD_BP_REG(0xb10de800);
501 GX_LOAD_BP_REG(0xae0db000);
502 GX_LOAD_BP_REG(0xb20df000);
503 GX_LOAD_BP_REG(0xaf0db800);
504 GX_LOAD_BP_REG(0xb30df800);
506 return;
509 if(nr==2) {
510 // Set_TextureImage0-3, GXTexMapID=0-3 tmem_offset=00000000, cache_width=32 kb, cache_height=32 kb, image_type=cached
511 GX_LOAD_BP_REG(0x8c0d8000);
512 GX_LOAD_BP_REG(0x900dc000);
513 GX_LOAD_BP_REG(0x8d0d8800);
514 GX_LOAD_BP_REG(0x910dc800);
515 GX_LOAD_BP_REG(0x8e0d9000);
516 GX_LOAD_BP_REG(0x920dd000);
517 GX_LOAD_BP_REG(0x8f0d9800);
518 GX_LOAD_BP_REG(0x930dd800);
520 // Set_TextureImage0-3, GXTexMapID=4-7 tmem_offset=00010000, cache_width=32 kb, cache_height=32 kb, image_type=cached
521 GX_LOAD_BP_REG(0xac0da000);
522 GX_LOAD_BP_REG(0xb00dc400);
523 GX_LOAD_BP_REG(0xad0da800);
524 GX_LOAD_BP_REG(0xb10dcc00);
525 GX_LOAD_BP_REG(0xae0db000);
526 GX_LOAD_BP_REG(0xb20dd400);
527 GX_LOAD_BP_REG(0xaf0db800);
528 GX_LOAD_BP_REG(0xb30ddc00);
530 return;
534 #if defined(HW_RVL)
535 static GXTexRegion* __GXDefTexRegionCallback(GXTexObj *obj,u8 mapid)
537 u32 fmt,mipmap;
538 GXTexRegion *ret = NULL;
540 fmt = GX_GetTexObjFmt(obj);
541 mipmap = GX_GetTexObjMipMap(obj);
542 if(fmt>=GX_TF_CI4 && fmt<=GX_TF_CI14)
543 return &__gx->texRegion[mapid];
544 else if(fmt==GX_TF_CMPR)
545 ret = &__gx->texRegion[mapid];
546 else
547 ret = &__gx->texRegion[mapid+8];
549 if(mipmap) ret = &__gx->texRegion[mapid+16];
551 return ret;
553 #else
554 static GXTexRegion* __GXDefTexRegionCallback(GXTexObj *obj,u8 mapid)
556 u32 fmt;
557 u32 idx;
558 static u32 regionA = 0;
559 static u32 regionB = 0;
560 GXTexRegion *ret = NULL;
562 fmt = GX_GetTexObjFmt(obj);
563 if(fmt==0x0008 || fmt==0x0009 || fmt==0x000a) {
564 idx = regionB++;
565 ret = &__gx->texRegion[(idx&3)+8];
566 } else {
567 idx = regionA++;
568 ret = &__gx->texRegion[(idx&7)];
570 return ret;
572 #endif
574 static GXTlutRegion* __GXDefTlutRegionCallback(u32 tlut_name)
576 return &__gx->tlutRegion[tlut_name];
579 static void __GX_InitGX()
581 s32 i;
582 u32 flag;
583 GXRModeObj *rmode;
584 Mtx identity_matrix =
586 {1,0,0,0},
587 {0,1,0,0},
588 {0,0,1,0}
591 rmode = VIDEO_GetPreferredMode(NULL);
593 GX_SetCopyClear((GXColor)BLACK,0xffffff);
594 GX_SetTexCoordGen(GX_TEXCOORD0,GX_TG_MTX2x4,GX_TG_TEX0,GX_IDENTITY);
595 GX_SetTexCoordGen(GX_TEXCOORD1,GX_TG_MTX2x4,GX_TG_TEX1,GX_IDENTITY);
596 GX_SetTexCoordGen(GX_TEXCOORD2,GX_TG_MTX2x4,GX_TG_TEX2,GX_IDENTITY);
597 GX_SetTexCoordGen(GX_TEXCOORD3,GX_TG_MTX2x4,GX_TG_TEX3,GX_IDENTITY);
598 GX_SetTexCoordGen(GX_TEXCOORD4,GX_TG_MTX2x4,GX_TG_TEX4,GX_IDENTITY);
599 GX_SetTexCoordGen(GX_TEXCOORD5,GX_TG_MTX2x4,GX_TG_TEX5,GX_IDENTITY);
600 GX_SetTexCoordGen(GX_TEXCOORD6,GX_TG_MTX2x4,GX_TG_TEX6,GX_IDENTITY);
601 GX_SetTexCoordGen(GX_TEXCOORD7,GX_TG_MTX2x4,GX_TG_TEX7,GX_IDENTITY);
602 GX_SetNumTexGens(1);
603 GX_ClearVtxDesc();
604 GX_InvVtxCache();
606 GX_SetLineWidth(6,GX_TO_ZERO);
607 GX_SetPointSize(6,GX_TO_ZERO);
609 GX_EnableTexOffsets(GX_TEXCOORD0,GX_DISABLE,GX_DISABLE);
610 GX_EnableTexOffsets(GX_TEXCOORD1,GX_DISABLE,GX_DISABLE);
611 GX_EnableTexOffsets(GX_TEXCOORD2,GX_DISABLE,GX_DISABLE);
612 GX_EnableTexOffsets(GX_TEXCOORD3,GX_DISABLE,GX_DISABLE);
613 GX_EnableTexOffsets(GX_TEXCOORD4,GX_DISABLE,GX_DISABLE);
614 GX_EnableTexOffsets(GX_TEXCOORD5,GX_DISABLE,GX_DISABLE);
615 GX_EnableTexOffsets(GX_TEXCOORD6,GX_DISABLE,GX_DISABLE);
616 GX_EnableTexOffsets(GX_TEXCOORD7,GX_DISABLE,GX_DISABLE);
618 GX_LoadPosMtxImm(identity_matrix,GX_PNMTX0);
619 GX_LoadNrmMtxImm(identity_matrix,GX_PNMTX0);
620 GX_SetCurrentMtx(GX_PNMTX0);
621 GX_LoadTexMtxImm(identity_matrix,GX_IDENTITY,GX_MTX3x4);
622 GX_LoadTexMtxImm(identity_matrix,GX_DTTIDENTITY,GX_MTX3x4);
624 GX_SetViewport(0,0,rmode->fbWidth,rmode->efbHeight,0,1);
625 GX_SetCoPlanar(GX_DISABLE);
626 GX_SetCullMode(GX_CULL_BACK);
627 GX_SetClipMode(GX_CLIP_DISABLE);
629 GX_SetScissor(0,0,rmode->fbWidth,rmode->efbHeight);
630 GX_SetScissorBoxOffset(0,0);
632 GX_SetNumChans(0);
634 GX_SetChanCtrl(GX_COLOR0A0,GX_DISABLE,GX_SRC_REG,GX_SRC_VTX,GX_LIGHTNULL,GX_DF_NONE,GX_AF_NONE);
635 GX_SetChanAmbColor(GX_COLOR0A0,(GXColor)BLACK);
636 GX_SetChanMatColor(GX_COLOR0A0,(GXColor)WHITE);
638 GX_SetChanCtrl(GX_COLOR1A1,GX_DISABLE,GX_SRC_REG,GX_SRC_VTX,GX_LIGHTNULL,GX_DF_NONE,GX_AF_NONE);
639 GX_SetChanAmbColor(GX_COLOR1A1,(GXColor)BLACK);
640 GX_SetChanMatColor(GX_COLOR1A1,(GXColor)WHITE);
642 GX_InvalidateTexAll();
643 GX_SetTexRegionCallback(__GXDefTexRegionCallback);
644 GX_SetTlutRegionCallback(__GXDefTlutRegionCallback);
646 GX_SetTevOrder(GX_TEVSTAGE0,GX_TEXCOORD0,GX_TEXMAP0,GX_COLOR0A0);
647 GX_SetTevOrder(GX_TEVSTAGE1,GX_TEXCOORD1,GX_TEXMAP1,GX_COLOR0A0);
648 GX_SetTevOrder(GX_TEVSTAGE2,GX_TEXCOORD2,GX_TEXMAP2,GX_COLOR0A0);
649 GX_SetTevOrder(GX_TEVSTAGE3,GX_TEXCOORD3,GX_TEXMAP3,GX_COLOR0A0);
650 GX_SetTevOrder(GX_TEVSTAGE4,GX_TEXCOORD4,GX_TEXMAP4,GX_COLOR0A0);
651 GX_SetTevOrder(GX_TEVSTAGE5,GX_TEXCOORD5,GX_TEXMAP5,GX_COLOR0A0);
652 GX_SetTevOrder(GX_TEVSTAGE6,GX_TEXCOORD6,GX_TEXMAP6,GX_COLOR0A0);
653 GX_SetTevOrder(GX_TEVSTAGE7,GX_TEXCOORD7,GX_TEXMAP7,GX_COLOR0A0);
654 GX_SetTevOrder(GX_TEVSTAGE8,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
655 GX_SetTevOrder(GX_TEVSTAGE9,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
656 GX_SetTevOrder(GX_TEVSTAGE10,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
657 GX_SetTevOrder(GX_TEVSTAGE11,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
658 GX_SetTevOrder(GX_TEVSTAGE12,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
659 GX_SetTevOrder(GX_TEVSTAGE13,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
660 GX_SetTevOrder(GX_TEVSTAGE14,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
661 GX_SetTevOrder(GX_TEVSTAGE15,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
662 GX_SetNumTevStages(1);
663 GX_SetTevOp(GX_TEVSTAGE0,GX_REPLACE);
664 GX_SetAlphaCompare(GX_ALWAYS,0,GX_AOP_AND,GX_ALWAYS,0);
665 GX_SetZTexture(GX_ZT_DISABLE,GX_TF_Z8,0);
666 for(i=0;i<GX_MAX_TEVSTAGE;i++) {
667 GX_SetTevKColorSel(i,GX_TEV_KCSEL_1_4);
668 GX_SetTevKAlphaSel(i,GX_TEV_KASEL_1);
669 GX_SetTevSwapMode(i,GX_TEV_SWAP0,GX_TEV_SWAP0);
672 GX_SetTevSwapModeTable(GX_TEV_SWAP0,GX_CH_RED,GX_CH_GREEN,GX_CH_BLUE,GX_CH_ALPHA);
673 GX_SetTevSwapModeTable(GX_TEV_SWAP1,GX_CH_RED,GX_CH_RED,GX_CH_RED,GX_CH_ALPHA);
674 GX_SetTevSwapModeTable(GX_TEV_SWAP2,GX_CH_GREEN,GX_CH_GREEN,GX_CH_GREEN,GX_CH_ALPHA);
675 GX_SetTevSwapModeTable(GX_TEV_SWAP3,GX_CH_BLUE,GX_CH_BLUE,GX_CH_BLUE,GX_CH_ALPHA);
676 for(i=0;i<GX_MAX_TEVSTAGE;i++) {
677 GX_SetTevDirect(i);
680 GX_SetNumIndStages(0);
681 GX_SetIndTexCoordScale(GX_INDTEXSTAGE0,GX_ITS_1,GX_ITS_1);
682 GX_SetIndTexCoordScale(GX_INDTEXSTAGE1,GX_ITS_1,GX_ITS_1);
683 GX_SetIndTexCoordScale(GX_INDTEXSTAGE2,GX_ITS_1,GX_ITS_1);
684 GX_SetIndTexCoordScale(GX_INDTEXSTAGE3,GX_ITS_1,GX_ITS_1);
686 GX_SetFog(GX_FOG_NONE,0,1,0.1,1,(GXColor)BLACK);
687 GX_SetFogRangeAdj(GX_DISABLE,0,NULL);
689 GX_SetBlendMode(GX_BM_NONE,GX_BL_SRCALPHA,GX_BL_INVSRCALPHA,GX_LO_CLEAR);
690 GX_SetColorUpdate(GX_ENABLE);
691 GX_SetAlphaUpdate(GX_ENABLE);
692 GX_SetZMode(GX_ENABLE,GX_LEQUAL,GX_TRUE);
693 GX_SetZCompLoc(GX_TRUE);
694 GX_SetDither(GX_ENABLE);
695 GX_SetDstAlpha(GX_DISABLE,0);
696 GX_SetPixelFmt(GX_PF_RGB8_Z24,GX_ZC_LINEAR);
698 GX_SetFieldMask(GX_ENABLE,GX_ENABLE);
700 flag = 0;
701 if(rmode->viHeight==(rmode->xfbHeight<<1)) flag = 1;
702 GX_SetFieldMode(rmode->field_rendering,flag);
704 GX_SetCopyClear((GXColor)GX_DEFAULT_BG,0x00ffffff);
705 GX_SetDispCopySrc(0,0,rmode->fbWidth,rmode->efbHeight);
706 GX_SetDispCopyDst(rmode->fbWidth,rmode->efbHeight);
707 GX_SetDispCopyYScale(1.0);
708 GX_SetCopyClamp(GX_CLAMP_TOP|GX_CLAMP_BOTTOM);
709 GX_SetCopyFilter(GX_FALSE,NULL,GX_FALSE,NULL);
710 GX_SetDispCopyGamma(GX_GM_1_0);
711 GX_SetDispCopyFrame2Field(GX_COPY_PROGRESSIVE);
712 GX_ClearBoundingBox();
714 GX_PokeColorUpdate(GX_TRUE);
715 GX_PokeAlphaUpdate(GX_TRUE);
716 GX_PokeDither(GX_FALSE);
717 GX_PokeBlendMode(GX_BM_NONE,GX_BL_ZERO,GX_BL_ONE,GX_LO_SET);
718 GX_PokeAlphaMode(GX_ALWAYS,0);
719 GX_PokeAlphaRead(GX_READ_FF);
720 GX_PokeDstAlpha(GX_DISABLE,0);
721 GX_PokeZMode(GX_TRUE,GX_ALWAYS,GX_TRUE);
723 GX_SetGPMetric(GX_PERF0_NONE,GX_PERF1_NONE);
724 GX_ClearGPMetric();
727 static void __GX_FlushTextureState()
729 GX_LOAD_BP_REG(__gx->tevIndMask);
732 static void __GX_XfVtxSpecs()
734 u32 xfvtxspecs = 0;
735 u32 nrms,texs,cols;
737 cols = 0;
738 if(__gx->vcdLo&0x6000) cols++;
739 if(__gx->vcdLo&0x18000) cols++;
741 nrms = 0;
742 if(__gx->vcdNrms==1) nrms = 1;
743 else if(__gx->vcdNrms==2) nrms = 2;
745 texs = 0;
746 if(__gx->vcdHi&0x3) texs++;
747 if(__gx->vcdHi&0xc) texs++;
748 if(__gx->vcdHi&0x30) texs++;
749 if(__gx->vcdHi&0xc0) texs++;
750 if(__gx->vcdHi&0x300) texs++;
751 if(__gx->vcdHi&0xc00) texs++;
752 if(__gx->vcdHi&0x3000) texs++;
753 if(__gx->vcdHi&0xc000) texs++;
755 xfvtxspecs = (_SHIFTL(texs,4,4))|(_SHIFTL(nrms,2,2))|(cols&0x3);
756 GX_LOAD_XF_REG(0x1008,xfvtxspecs);
759 static void __GX_SetMatrixIndex(u32 mtx)
761 if(mtx<5) {
762 GX_LOAD_CP_REG(0x30,__gx->mtxIdxLo);
763 GX_LOAD_XF_REG(0x1018,__gx->mtxIdxLo);
764 } else {
765 GX_LOAD_CP_REG(0x40,__gx->mtxIdxHi);
766 GX_LOAD_XF_REG(0x1019,__gx->mtxIdxHi);
770 static void __GX_SendFlushPrim()
772 u32 tmp,tmp2,cnt;
774 tmp = (__gx->xfFlush*__gx->xfFlushExp);
776 FIFO_PUTU8(0x98);
777 FIFO_PUTU16(__gx->xfFlush);
779 tmp2 = (tmp+3)/4;
780 if(tmp>0) {
781 cnt = tmp2/8;
782 while(cnt) {
783 FIFO_PUTU32(0);
784 FIFO_PUTU32(0);
785 FIFO_PUTU32(0);
786 FIFO_PUTU32(0);
787 FIFO_PUTU32(0);
788 FIFO_PUTU32(0);
789 FIFO_PUTU32(0);
790 FIFO_PUTU32(0);
791 cnt--;
793 tmp2 &= 0x0007;
794 if(tmp2) {
795 while(tmp2) {
796 FIFO_PUTU32(0);
797 tmp2--;
801 __gx->xfFlush = 1;
804 static void __GX_SetVCD()
806 GX_LOAD_CP_REG(0x50,__gx->vcdLo);
807 GX_LOAD_CP_REG(0x60,__gx->vcdHi);
808 __GX_XfVtxSpecs();
811 static void __GX_SetVAT()
813 u8 setvtx = 0;
814 s32 i;
816 for(i=0;i<8;i++) {
817 setvtx = (1<<i);
818 if(__gx->VATTable&setvtx) {
819 GX_LOAD_CP_REG((0x70+(i&7)),__gx->VAT0reg[i]);
820 GX_LOAD_CP_REG((0x80+(i&7)),__gx->VAT1reg[i]);
821 GX_LOAD_CP_REG((0x90+(i&7)),__gx->VAT2reg[i]);
824 __gx->VATTable = 0;
827 static void __SetSURegs(u8 texmap,u8 texcoord)
829 u32 reg;
830 u16 wd,ht;
831 u8 wrap_s,wrap_t;
833 wd = __gx->texMapSize[texmap]&0x3ff;
834 ht = _SHIFTR(__gx->texMapSize[texmap],10,10);
835 wrap_s = __gx->texMapWrap[texmap]&3;
836 wrap_t = _SHIFTR(__gx->texMapWrap[texmap],2,2);
838 reg = (texcoord&0x7);
839 __gx->suSsize[reg] = (__gx->suSsize[reg]&~0x0000ffff)|wd;
840 __gx->suTsize[reg] = (__gx->suTsize[reg]&~0x0000ffff)|ht;
841 __gx->suSsize[reg] = (__gx->suSsize[reg]&~0x00010000)|(_SHIFTL(wrap_s,16,1));
842 __gx->suTsize[reg] = (__gx->suTsize[reg]&~0x00010000)|(_SHIFTL(wrap_t,16,1));
844 GX_LOAD_BP_REG(__gx->suSsize[reg]);
845 GX_LOAD_BP_REG(__gx->suTsize[reg]);
848 static void __GX_SetSUTexRegs()
850 u32 i;
851 u32 indtev,dirtev;
852 u8 texcoord,texmap;
853 u32 tevreg,tevm,texcm;
855 dirtev = (_SHIFTR(__gx->genMode,10,4))+1;
856 indtev = _SHIFTR(__gx->genMode,16,3);
858 //indirect texture order
859 for(i=0;i<indtev;i++) {
860 switch(i) {
861 case GX_INDTEXSTAGE0:
862 texmap = __gx->tevRasOrder[2]&7;
863 texcoord = _SHIFTR(__gx->tevRasOrder[2],3,3);
864 break;
865 case GX_INDTEXSTAGE1:
866 texmap = _SHIFTR(__gx->tevRasOrder[2],6,3);
867 texcoord = _SHIFTR(__gx->tevRasOrder[2],9,3);
868 break;
869 case GX_INDTEXSTAGE2:
870 texmap = _SHIFTR(__gx->tevRasOrder[2],12,3);
871 texcoord = _SHIFTR(__gx->tevRasOrder[2],15,3);
872 break;
873 case GX_INDTEXSTAGE3:
874 texmap = _SHIFTR(__gx->tevRasOrder[2],18,3);
875 texcoord = _SHIFTR(__gx->tevRasOrder[2],21,3);
876 break;
877 default:
878 texmap = 0;
879 texcoord = 0;
880 break;
883 texcm = _SHIFTL(1,texcoord,1);
884 if(!(__gx->texCoordManually&texcm))
885 __SetSURegs(texmap,texcoord);
888 //direct texture order
889 for(i=0;i<dirtev;i++) {
890 tevreg = 3+(_SHIFTR(i,1,3));
891 texmap = (__gx->tevTexMap[i]&0xff);
893 if(i&1) texcoord = _SHIFTR(__gx->tevRasOrder[tevreg],15,3);
894 else texcoord = _SHIFTR(__gx->tevRasOrder[tevreg],3,3);
896 tevm = _SHIFTL(1,i,1);
897 texcm = _SHIFTL(1,texcoord,1);
898 if(texmap!=0xff && (__gx->tevTexCoordEnable&tevm) && !(__gx->texCoordManually&texcm)) {
899 __SetSURegs(texmap,texcoord);
904 static void __GX_SetGenMode()
906 GX_LOAD_BP_REG(__gx->genMode);
907 __gx->xfFlush = 0;
910 static void __GX_UpdateBPMask()
912 #if defined(HW_DOL)
913 u32 i;
914 u32 nbmp,nres;
915 u8 ntexmap;
917 nbmp = _SHIFTR(__gx->genMode,16,3);
919 nres = 0;
920 for(i=0;i<nbmp;i++) {
921 switch(i) {
922 case GX_INDTEXSTAGE0:
923 ntexmap = __gx->tevRasOrder[2]&7;
924 break;
925 case GX_INDTEXSTAGE1:
926 ntexmap = _SHIFTR(__gx->tevRasOrder[2],6,3);
927 break;
928 case GX_INDTEXSTAGE2:
929 ntexmap = _SHIFTR(__gx->tevRasOrder[2],12,3);
930 break;
931 case GX_INDTEXSTAGE3:
932 ntexmap = _SHIFTR(__gx->tevRasOrder[2],18,3);
933 break;
934 default:
935 ntexmap = 0;
936 break;
938 nres |= (1<<ntexmap);
941 if((__gx->tevIndMask&0xff)!=nres) {
942 __gx->tevIndMask = (__gx->tevIndMask&~0xff)|(nres&0xff);
943 GX_LOAD_BP_REG(__gx->tevIndMask);
945 #endif
948 static void __GX_SetIndirectMask(u32 mask)
950 __gx->tevIndMask = ((__gx->tevIndMask&~0xff)|(mask&0xff));
951 GX_LOAD_BP_REG(__gx->tevIndMask);
954 static void __GX_SetTexCoordGen()
956 u32 i,mask;
957 u32 texcoord;
959 if(__gx->dirtyState&0x02000000) GX_LOAD_XF_REG(0x103f,(__gx->genMode&0xf));
961 i = 0;
962 texcoord = 0x1040;
963 mask = _SHIFTR(__gx->dirtyState,16,8);
964 while(mask) {
965 if(mask&0x0001) {
966 GX_LOAD_XF_REG(texcoord,__gx->texCoordGen[i]);
967 GX_LOAD_XF_REG((texcoord+0x10),__gx->texCoordGen2[i]);
969 mask >>= 1;
970 texcoord++;
971 i++;
975 static void __GX_SetChanColor()
977 if(__gx->dirtyState&0x0100)
978 GX_LOAD_XF_REG(0x100a,__gx->chnAmbColor[0]);
979 if(__gx->dirtyState&0x0200)
980 GX_LOAD_XF_REG(0x100b,__gx->chnAmbColor[1]);
981 if(__gx->dirtyState&0x0400)
982 GX_LOAD_XF_REG(0x100c,__gx->chnMatColor[0]);
983 if(__gx->dirtyState&0x0800)
984 GX_LOAD_XF_REG(0x100d,__gx->chnMatColor[1]);
987 static void __GX_SetChanCntrl()
989 u32 i,chan,mask;
991 if(__gx->dirtyState&0x01000000) GX_LOAD_XF_REG(0x1009,(_SHIFTR(__gx->genMode,4,3)));
993 i = 0;
994 chan = 0x100e;
995 mask = _SHIFTR(__gx->dirtyState,12,4);
996 while(mask) {
997 if(mask&0x0001) GX_LOAD_XF_REG(chan,__gx->chnCntrl[i]);
999 mask >>= 1;
1000 chan++;
1001 i++;
1005 static void __GX_SetDirtyState()
1007 if(__gx->dirtyState&0x0001) {
1008 __GX_SetSUTexRegs();
1010 if(__gx->dirtyState&0x0002) {
1011 __GX_UpdateBPMask();
1013 if(__gx->dirtyState&0x0004) {
1014 __GX_SetGenMode();
1016 if(__gx->dirtyState&0x0008) {
1017 __GX_SetVCD();
1019 if(__gx->dirtyState&0x0010) {
1020 __GX_SetVAT();
1022 if(__gx->dirtyState&~0xff) {
1023 if(__gx->dirtyState&0x0f00) {
1024 __GX_SetChanColor();
1026 if(__gx->dirtyState&0x0100f000) {
1027 __GX_SetChanCntrl();
1029 if(__gx->dirtyState&0x02ff0000) {
1030 __GX_SetTexCoordGen();
1032 if(__gx->dirtyState&0x04000000) {
1033 __GX_SetMatrixIndex(0);
1034 __GX_SetMatrixIndex(5);
1037 __gx->dirtyState = 0;
1040 static u32 __GX_GetNumXfbLines(u16 efbHeight,u32 yscale)
1042 u32 tmp,tmp1;
1044 tmp = (((efbHeight-1)<<8)/yscale)+1;
1045 if(yscale>128 && yscale<256) {
1046 while(yscale&0x01) yscale >>= 1;
1047 tmp1 = yscale*(efbHeight/yscale);
1048 if(!(efbHeight-tmp1)) tmp++;
1050 if(tmp>1024) tmp = 1024;
1052 return tmp;
1055 GXFifoObj* GX_Init(void *base,u32 size)
1057 s32 i,re0,re1;
1058 #if defined(HW_RVL)
1059 u32 tmem;
1060 #else
1061 u32 tmem_even,tmem_odd;
1062 #endif
1063 u32 divis,res;
1064 u32 divid = TB_BUS_CLOCK;
1065 GXTexRegion *region = NULL;
1066 GXTlutRegion *tregion = NULL;
1068 LWP_InitQueue(&_gxwaitfinish);
1069 SYS_RegisterResetFunc(&__gx_resetinfo);
1071 memset(__gxregs,0,STRUCT_REGDEF_SIZE);
1073 __GX_FifoInit();
1074 GX_InitFifoBase(&_gxfifoobj,base,size);
1075 GX_SetCPUFifo(&_gxfifoobj);
1076 GX_SetGPFifo(&_gxfifoobj);
1077 __GX_PEInit();
1078 EnableWriteGatherPipe();
1080 __gx->gxFifoInited = 1;
1082 __gx->tevIndMask = 0xff;
1083 __gx->tevIndMask = (__gx->tevIndMask&~0xff000000)|(_SHIFTL(0x0f,24,8));
1085 i=0;
1086 re0 = 0xc0;
1087 re1 = 0xc1;
1088 while(i<16) {
1089 __gx->tevColorEnv[i] = (__gx->tevColorEnv[i]&~0xff000000)|(_SHIFTL(re0,24,8));
1090 __gx->tevAlphaEnv[i] = (__gx->tevAlphaEnv[i]&~0xff000000)|(_SHIFTL(re1,24,8));
1091 re0 += 2; re1 += 2; i++;
1094 __gx->texCoordManually = 0;
1095 __gx->dirtyState = 0;
1097 __gx->saveDLctx = 1;
1098 __gx->gxFifoUnlinked = 0;
1100 __gx->sciTLcorner = (__gx->sciTLcorner&~0xff000000)|(_SHIFTL(0x20,24,8));
1101 __gx->sciBRcorner = (__gx->sciBRcorner&~0xff000000)|(_SHIFTL(0x21,24,8));
1102 __gx->lpWidth = (__gx->lpWidth&~0xff000000)|(_SHIFTL(0x22,24,8));
1103 __gx->genMode = (__gx->genMode&~0xff000000)|(_SHIFTL(0x00,24,8));
1105 i=0;
1106 re0 = 0x30;
1107 re1 = 0x31;
1108 while(i<8) {
1109 __gx->suSsize[i] = (__gx->suSsize[i]&~0xff000000)|(_SHIFTL(re0,24,8));
1110 __gx->suTsize[i] = (__gx->suTsize[i]&~0xff000000)|(_SHIFTL(re1,24,8));
1111 re0 += 2; re1 += 2; i++;
1114 __gx->peZMode = (__gx->peZMode&~0xff000000)|(_SHIFTL(0x40,24,8));
1115 __gx->peCMode0 = (__gx->peCMode0&~0xff000000)|(_SHIFTL(0x41,24,8));
1116 __gx->peCMode1 = (__gx->peCMode1&~0xff000000)|(_SHIFTL(0x42,24,8));
1117 __gx->peCntrl = (__gx->peCntrl&~0xff000000)|(_SHIFTL(0x43,24,8));
1119 i=0;
1120 re0 = 0x25;
1121 while(i<11) {
1122 __gx->tevRasOrder[i] = (__gx->tevRasOrder[i]&~0xff000000)|(_SHIFTL(re0,24,8));
1123 re0++; i++;
1126 divis = 500;
1127 res = (u32)(divid/divis);
1128 __GX_FlushTextureState();
1129 GX_LOAD_BP_REG(0x69000000|((_SHIFTR(res,11,24))|0x0400));
1131 divis = 4224;
1132 res = (u32)(res/divis);
1133 __GX_FlushTextureState();
1134 GX_LOAD_BP_REG(0x46000000|(res|0x0200));
1136 i=0;
1137 re0 = 0xf6;
1138 while(i<8) {
1139 __gx->tevSwapModeTable[i] = (__gx->tevSwapModeTable[i]&~0xff000000)|(_SHIFTL(re0,24,8));
1140 re0++; i++;
1143 __gx->tevTexCoordEnable = 0;
1144 __gx->perf0Mode = GX_PERF0_NONE;
1145 __gx->perf1Mode = GX_PERF1_NONE;
1146 __gx->cpPerfMode = 0;
1148 __GX_InitRevBits();
1150 i=0;
1151 while(i<16) {
1152 __gx->tevTexMap[i] = 0xff;
1153 i++;
1156 #if defined(HW_RVL)
1157 i = 0;
1158 while(i<8) {
1159 region = &__gx->texRegion[i];
1160 GX_InitTexCacheRegion(region,GX_FALSE,_gxtexregionaddrtable[i+0],GX_TEXCACHE_32K,_gxtexregionaddrtable[i+8],GX_TEXCACHE_32K);
1162 region = &__gx->texRegion[i+8];
1163 GX_InitTexCacheRegion(region,GX_FALSE,_gxtexregionaddrtable[i+16],GX_TEXCACHE_32K,_gxtexregionaddrtable[i+24],GX_TEXCACHE_32K);
1165 region = &__gx->texRegion[i+16];
1166 GX_InitTexCacheRegion(region,GX_TRUE,_gxtexregionaddrtable[i+32],GX_TEXCACHE_32K,_gxtexregionaddrtable[i+40],GX_TEXCACHE_32K);
1168 i++;
1171 i=0;
1172 while(i<16) {
1173 tmem = 0x000C0000+(i<<13);
1174 tregion = &__gx->tlutRegion[i];
1175 GX_InitTlutRegion(tregion,tmem,GX_TLUT_256);
1176 i++;
1179 i=0;
1180 while(i<4) {
1181 tmem = 0x000E0000+(i<<15);
1182 tregion = &__gx->tlutRegion[i+16];
1183 GX_InitTlutRegion(tregion,tmem,GX_TLUT_1K);
1184 i++;
1186 #else
1187 for(i=0;i<8;i++) {
1188 tmem_even = tmem_odd = (i<<15);
1189 region = &__gx->texRegion[i];
1190 GX_InitTexCacheRegion(region,GX_FALSE,tmem_even,GX_TEXCACHE_32K,(tmem_odd+0x00080000),GX_TEXCACHE_32K);
1192 for(i=0;i<4;i++) {
1193 tmem_even = ((0x08+(i<<1))<<15);
1194 tmem_odd = ((0x09+(i<<1))<<15);
1195 region = &__gx->texRegion[i+8];
1196 GX_InitTexCacheRegion(region,GX_FALSE,tmem_even,GX_TEXCACHE_32K,tmem_odd,GX_TEXCACHE_32K);
1198 for(i=0;i<16;i++) {
1199 tmem_even = (i<<13)+0x000C0000;
1200 tregion = &__gx->tlutRegion[i];
1201 GX_InitTlutRegion(tregion,tmem_even,GX_TLUT_256);
1203 for(i=0;i<4;i++) {
1204 tmem_even = (i<<15)+0x000E0000;
1205 tregion = &__gx->tlutRegion[i+16];
1206 GX_InitTlutRegion(tregion,tmem_even,GX_TLUT_1K);
1208 #endif
1209 _cpReg[3] = 0;
1210 GX_LOAD_CP_REG(0x20,0x00000000);
1211 GX_LOAD_XF_REG(0x1006,0x0);
1213 GX_LOAD_BP_REG(0x23000000);
1214 GX_LOAD_BP_REG(0x24000000);
1215 GX_LOAD_BP_REG(0x67000000);
1217 __GX_SetIndirectMask(0);
1218 #if defined(HW_RVL)
1219 __GX_SetTmemConfig(2);
1220 #else
1221 __GX_SetTmemConfig(0);
1222 #endif
1223 __GX_InitGX();
1225 return &_gxfifoobj;
1228 void GX_InitFifoBase(GXFifoObj *fifo,void *base,u32 size)
1230 struct __gxfifo *ptr = (struct __gxfifo*)fifo;
1232 if(!ptr || size<GX_FIFO_MINSIZE) return;
1234 ptr->buf_start = (u32)base;
1235 ptr->buf_end = (u32)base + size - 4;
1236 ptr->size = size;
1237 ptr->rdwt_dst = 0;
1239 GX_InitFifoLimits(fifo,(size-GX_FIFO_HIWATERMARK),((size>>1)&0x7fffffe0));
1240 GX_InitFifoPtrs(fifo,base,base);
1243 void GX_InitFifoLimits(GXFifoObj *fifo,u32 hiwatermark,u32 lowatermark)
1245 struct __gxfifo *ptr = (struct __gxfifo*)fifo;
1247 ptr->hi_mark = hiwatermark;
1248 ptr->lo_mark = lowatermark;
1251 void GX_InitFifoPtrs(GXFifoObj *fifo,void *rd_ptr,void *wt_ptr)
1253 u32 level;
1254 s32 rdwt_dst;
1255 struct __gxfifo *ptr = (struct __gxfifo*)fifo;
1257 _CPU_ISR_Disable(level);
1258 rdwt_dst = wt_ptr-rd_ptr;
1259 ptr->rd_ptr = (u32)rd_ptr;
1260 ptr->wt_ptr = (u32)wt_ptr;
1261 ptr->rdwt_dst = rdwt_dst;
1262 if(rdwt_dst<0) {
1263 rdwt_dst += ptr->size;
1264 ptr->rd_ptr = rdwt_dst;
1266 _CPU_ISR_Restore(level);
1269 void GX_GetFifoPtrs(GXFifoObj *fifo,void **rd_ptr,void **wt_ptr)
1271 s32 rdwt_dst;
1272 struct __gxfifo *ptr = (struct __gxfifo*)fifo;
1273 struct __gxfifo *gpfifo = (struct __gxfifo*)&_gpfifo;
1274 struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
1276 if(cpufifo->cpufifo_ready) ptr->wt_ptr = (u32)MEM_PHYSICAL_TO_K0((_piReg[5]&~0x04000000));
1277 if(gpfifo->gpfifo_ready) {
1278 ptr->rd_ptr = MEM_VIRTUAL_TO_PHYSICAL(_SHIFTL(_cpReg[29],16,16)|(_cpReg[28]&0xffff));
1279 ptr->rdwt_dst = (_SHIFTL(_cpReg[25],16,16)|(_cpReg[24]&0xffff));
1280 } else {
1281 rdwt_dst = (ptr->wt_ptr - ptr->rd_ptr);
1282 if(rdwt_dst<0) ptr->rdwt_dst += ptr->size;
1283 else ptr->rdwt_dst = rdwt_dst;
1285 *rd_ptr = (void*)ptr->rd_ptr;
1286 *wt_ptr = (void*)ptr->wt_ptr;
1289 void GX_SetCPUFifo(GXFifoObj *fifo)
1291 u32 level;
1292 struct __gxfifo *ptr = (struct __gxfifo*)fifo;
1293 struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
1295 _CPU_ISR_Disable(level);
1296 if(!fifo) {
1297 _gxcpufifoready = 0;
1298 _cpgplinked = 0;
1299 cpufifo->gpfifo_ready = 0;
1300 cpufifo->cpufifo_ready = 0;
1301 _CPU_ISR_Restore(level);
1302 return;
1305 cpufifo->buf_start = ptr->buf_start;
1306 cpufifo->buf_end = ptr->buf_end;
1307 cpufifo->size = ptr->size;
1308 cpufifo->hi_mark = ptr->hi_mark;
1309 cpufifo->lo_mark = ptr->lo_mark;
1310 cpufifo->rd_ptr = ptr->rd_ptr;
1311 cpufifo->wt_ptr = ptr->wt_ptr;
1312 cpufifo->rdwt_dst = ptr->rdwt_dst;
1313 cpufifo->fifo_wrap = ptr->fifo_wrap;
1314 cpufifo->gpfifo_ready = ptr->gpfifo_ready;
1315 cpufifo->cpufifo_ready = 1;
1317 _gxcpufifoready = 1;
1318 if(__GX_CPGPLinkCheck()) {
1319 _cpgplinked = 1;
1320 cpufifo->gpfifo_ready = 1;
1322 _piReg[3] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_start);
1323 _piReg[4] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_end);
1324 _piReg[5] = (cpufifo->wt_ptr&0x1FFFFFE0);
1326 __GX_WriteFifoIntReset(GX_TRUE,GX_TRUE);
1327 __GX_WriteFifoIntEnable(GX_ENABLE,GX_DISABLE);
1328 __GX_FifoLink(GX_TRUE);
1330 _CPU_ISR_Restore(level);
1331 return;
1334 if(_cpgplinked) {
1335 __GX_FifoLink(GX_FALSE);
1336 _cpgplinked = 0;
1339 __GX_WriteFifoIntEnable(GX_DISABLE,GX_DISABLE);
1341 _piReg[3] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_start);
1342 _piReg[4] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_end);
1343 _piReg[5] = (cpufifo->wt_ptr&0x1FFFFFE0);
1344 ppcsync();
1346 _CPU_ISR_Restore(level);
1349 void GX_GetCPUFifo(GXFifoObj *fifo)
1351 struct __gxfifo* ptr = (struct __gxfifo*)fifo;
1352 struct __gxfifo* cpufifo = (struct __gxfifo*)&_cpufifo;
1354 if(!_gxcpufifoready) return;
1356 GX_Flush();
1357 __GX_SaveFifo();
1359 ptr->buf_start = cpufifo->buf_start;
1360 ptr->buf_end = cpufifo->buf_end;
1361 ptr->size = cpufifo->size;
1362 ptr->rd_ptr = cpufifo->rd_ptr;
1363 ptr->wt_ptr = cpufifo->wt_ptr;
1364 ptr->rdwt_dst = cpufifo->rdwt_dst;
1365 ptr->hi_mark = cpufifo->hi_mark;
1366 ptr->lo_mark = cpufifo->lo_mark;
1367 ptr->fifo_wrap = cpufifo->fifo_wrap;
1368 ptr->cpufifo_ready = cpufifo->cpufifo_ready;
1369 ptr->gpfifo_ready = cpufifo->gpfifo_ready;
1372 void GX_SetGPFifo(GXFifoObj *fifo)
1374 u32 level;
1375 struct __gxfifo *ptr = (struct __gxfifo*)fifo;
1376 struct __gxfifo *gpfifo = (struct __gxfifo*)&_gpfifo;
1378 _CPU_ISR_Disable(level);
1379 __GX_FifoReadDisable();
1380 __GX_WriteFifoIntEnable(GX_DISABLE,GX_DISABLE);
1382 if(!fifo) {
1383 _gxgpfifoready = 0;
1384 _cpgplinked = 0;
1385 gpfifo->cpufifo_ready = 0;
1386 gpfifo->gpfifo_ready = 0;
1387 __GX_FifoLink(GX_FALSE);
1388 _CPU_ISR_Restore(level);
1389 return;
1392 gpfifo->buf_start = ptr->buf_start;
1393 gpfifo->buf_end = ptr->buf_end;
1394 gpfifo->size = ptr->size;
1395 gpfifo->hi_mark = ptr->hi_mark;
1396 gpfifo->lo_mark = ptr->lo_mark;
1397 gpfifo->rd_ptr = ptr->rd_ptr;
1398 gpfifo->wt_ptr = ptr->wt_ptr;
1399 gpfifo->rdwt_dst = ptr->rdwt_dst;
1400 gpfifo->fifo_wrap = ptr->fifo_wrap;
1401 gpfifo->cpufifo_ready = ptr->cpufifo_ready;
1402 gpfifo->gpfifo_ready = 1;
1403 _gxgpfifoready = 1;
1405 /* setup fifo base */
1406 _cpReg[16] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->buf_start),0,16);
1407 _cpReg[17] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->buf_start),16,16);
1409 /* setup fifo end */
1410 _cpReg[18] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->buf_end),0,16);
1411 _cpReg[19] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->buf_end),16,16);
1413 /* setup hiwater mark */
1414 _cpReg[20] = _SHIFTL(gpfifo->hi_mark,0,16);
1415 _cpReg[21] = _SHIFTR(gpfifo->hi_mark,16,16);
1417 /* setup lowater mark */
1418 _cpReg[22] = _SHIFTL(gpfifo->lo_mark,0,16);
1419 _cpReg[23] = _SHIFTR(gpfifo->lo_mark,16,16);
1421 /* setup rd<->wd dist */
1422 _cpReg[24] = _SHIFTL(gpfifo->rdwt_dst,0,16);
1423 _cpReg[25] = _SHIFTR(gpfifo->rdwt_dst,16,16);
1425 /* setup wt ptr */
1426 _cpReg[26] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->wt_ptr),0,16);
1427 _cpReg[27] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->wt_ptr),16,16);
1429 /* setup rd ptr */
1430 _cpReg[28] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->rd_ptr),0,16);
1431 _cpReg[29] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->rd_ptr),16,16);
1432 ppcsync();
1434 if(__GX_CPGPLinkCheck()) {
1435 _cpgplinked = 1;
1436 gpfifo->cpufifo_ready = 1;
1437 __GX_WriteFifoIntEnable(GX_ENABLE,GX_DISABLE);
1438 __GX_FifoLink(GX_TRUE);
1439 } else {
1440 _cpgplinked = 0;
1441 gpfifo->cpufifo_ready = 0;
1442 __GX_WriteFifoIntEnable(GX_DISABLE,GX_DISABLE);
1443 __GX_FifoLink(GX_FALSE);
1446 __GX_WriteFifoIntReset(GX_TRUE,GX_TRUE);
1447 __GX_FifoReadEnable();
1448 _CPU_ISR_Restore(level);
1451 void GX_GetGPFifo(GXFifoObj *fifo)
1453 struct __gxfifo* ptr = (struct __gxfifo*)fifo;
1454 struct __gxfifo* gpfifo = (struct __gxfifo*)&_gpfifo;
1456 if(!_gxgpfifoready) return;
1458 __GX_SaveFifo();
1460 ptr->buf_start = gpfifo->buf_start;
1461 ptr->buf_end = gpfifo->buf_end;
1462 ptr->size = gpfifo->size;
1463 ptr->rd_ptr = gpfifo->rd_ptr;
1464 ptr->wt_ptr = gpfifo->wt_ptr;
1465 ptr->rdwt_dst = gpfifo->rdwt_dst;
1466 ptr->hi_mark = gpfifo->hi_mark;
1467 ptr->lo_mark = gpfifo->lo_mark;
1468 ptr->fifo_wrap = gpfifo->fifo_wrap;
1469 ptr->gpfifo_ready = gpfifo->gpfifo_ready;
1470 ptr->cpufifo_ready = gpfifo->cpufifo_ready;
1473 u32 GX_GetOverflowCount()
1475 return _gxoverflowcount;
1478 u32 GX_ResetOverflowCount()
1480 u32 ret = _gxoverflowcount;
1481 _gxoverflowcount = 0;
1482 return ret;
1485 lwp_t GX_GetCurrentGXThread()
1487 return _gxcurrentlwp;
1490 lwp_t GX_SetCurrentGXThread()
1492 u32 level;
1494 _CPU_ISR_Disable(level);
1495 lwp_t ret = _gxcurrentlwp;
1496 _gxcurrentlwp = LWP_GetSelf();
1497 _CPU_ISR_Restore(level);
1499 return ret;
1502 volatile void* GX_RedirectWriteGatherPipe(void *ptr)
1504 u32 level;
1505 struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
1507 _CPU_ISR_Disable(level);
1508 GX_Flush();
1509 while(!IsWriteGatherBufferEmpty());
1511 mtwpar(0x0C008000);
1512 if(_cpgplinked) {
1513 __GX_FifoLink(GX_FALSE);
1514 __GX_WriteFifoIntEnable(GX_DISABLE,GX_DISABLE);
1516 cpufifo->wt_ptr = (u32)MEM_PHYSICAL_TO_K0(_piReg[5]&~0x04000000);
1518 _piReg[3] = 0;
1519 _piReg[4] = 0x04000000;
1520 _piReg[5] = (((u32)ptr&0x3FFFFFE0)&~0x04000000);
1521 _sync();
1523 _CPU_ISR_Restore(level);
1525 return (volatile void*)0x0C008000;
1528 void GX_RestoreWriteGatherPipe()
1530 u32 level;
1531 struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
1533 _CPU_ISR_Disable(level);
1535 FIFO_PUTU32(0);
1536 FIFO_PUTU32(0);
1537 FIFO_PUTU32(0);
1538 FIFO_PUTU32(0);
1539 FIFO_PUTU32(0);
1540 FIFO_PUTU32(0);
1541 FIFO_PUTU32(0);
1542 FIFO_PUTU32(0);
1544 ppcsync();
1545 while(!IsWriteGatherBufferEmpty());
1547 mtwpar(0x0C008000);
1548 _piReg[3] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_start);
1549 _piReg[4] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_end);
1550 _piReg[5] = (((u32)cpufifo->wt_ptr&0x3FFFFFE0)&~0x04000000);
1551 if(_cpgplinked) {
1552 __GX_WriteFifoIntReset(GX_TRUE,GX_TRUE);
1553 __GX_WriteFifoIntEnable(GX_ENABLE,GX_DISABLE);
1554 __GX_FifoLink(GX_TRUE);
1556 _CPU_ISR_Restore(level);
1559 void GX_Flush()
1561 if(__gx->dirtyState)
1562 __GX_SetDirtyState();
1564 FIFO_PUTU32(0);
1565 FIFO_PUTU32(0);
1566 FIFO_PUTU32(0);
1567 FIFO_PUTU32(0);
1568 FIFO_PUTU32(0);
1569 FIFO_PUTU32(0);
1570 FIFO_PUTU32(0);
1571 FIFO_PUTU32(0);
1573 ppcsync();
1576 void GX_EnableBreakPt(void *break_pt)
1578 u32 level = 0;
1579 _CPU_ISR_Disable(level);
1580 __GX_FifoReadDisable();
1581 _cpReg[30] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(break_pt),0,16);
1582 _cpReg[31] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(break_pt),16,16);
1583 __gx->cpCRreg = (__gx->cpCRreg&~0x22)|0x22;
1584 _cpReg[1] = __gx->cpCRreg;
1585 _gxcurrbp = break_pt;
1586 __GX_FifoReadEnable();
1587 _CPU_ISR_Restore(level);
1590 void GX_DisableBreakPt()
1592 u32 level = 0;
1593 _CPU_ISR_Disable(level);
1594 __gx->cpCRreg = (__gx->cpCRreg&~0x22);
1595 _cpReg[1] = __gx->cpCRreg;
1596 _gxcurrbp = NULL;
1597 _CPU_ISR_Restore(level);
1600 #if defined(HW_DOL)
1601 void GX_AbortFrame()
1603 _piReg[6] = 1;
1604 __GX_WaitAbort(50);
1605 _piReg[6] = 0;
1606 __GX_WaitAbort(5);
1608 if(__GX_IsGPFifoReady())
1609 __GX_CleanGPFifo();
1611 #elif defined(HW_RVL)
1612 void GX_AbortFrame()
1614 __GX_Abort();
1615 if(__GX_IsGPFifoReady()) {
1616 __GX_CleanGPFifo();
1617 __GX_InitRevBits();
1619 __gx->dirtyState = 0;
1620 GX_Flush();
1623 #endif
1625 void GX_SetDrawSync(u16 token)
1627 u32 level = 0;
1628 _CPU_ISR_Disable(level);
1629 GX_LOAD_BP_REG(0x48000000 | token);
1630 GX_LOAD_BP_REG(0x47000000 | token);
1631 GX_Flush();
1632 _CPU_ISR_Restore(level);
1635 u16 GX_GetDrawSync()
1637 return _peReg[7];
1640 void GX_SetDrawDone()
1642 u32 level;
1643 _CPU_ISR_Disable(level);
1644 GX_LOAD_BP_REG(0x45000002); // set draw done!
1645 GX_Flush();
1646 _gxfinished = 0;
1647 _CPU_ISR_Restore(level);
1651 void GX_WaitDrawDone()
1653 u32 level;
1654 #ifdef _GP_DEBUG
1655 printf("GX_WaitDrawDone()\n\n");
1656 #endif
1657 _CPU_ISR_Disable(level);
1658 while(!_gxfinished)
1659 LWP_ThreadSleep(_gxwaitfinish);
1660 _CPU_ISR_Restore(level);
1663 void GX_DrawDone()
1665 u32 level;
1667 _CPU_ISR_Disable(level);
1668 GX_LOAD_BP_REG(0x45000002); // set draw done!
1669 GX_Flush();
1671 _gxfinished = 0;
1672 _CPU_ISR_Flash(level);
1674 while(!_gxfinished)
1675 LWP_ThreadSleep(_gxwaitfinish);
1676 _CPU_ISR_Restore(level);
1679 GXDrawDoneCallback GX_SetDrawDoneCallback(GXDrawDoneCallback cb)
1681 u32 level;
1683 _CPU_ISR_Disable(level);
1684 GXDrawDoneCallback ret = drawDoneCB;
1685 drawDoneCB = cb;
1686 _CPU_ISR_Restore(level);
1687 return ret;
1690 GXDrawSyncCallback GX_SetDrawSyncCallback(GXDrawSyncCallback cb)
1692 u32 level;
1694 _CPU_ISR_Disable(level);
1695 GXDrawSyncCallback ret = tokenCB;
1696 tokenCB = cb;
1697 _CPU_ISR_Restore(level);
1698 return ret;
1701 GXBreakPtCallback GX_SetBreakPtCallback(GXBreakPtCallback cb)
1703 u32 level;
1705 _CPU_ISR_Disable(level);
1706 GXBreakPtCallback ret = breakPtCB;
1707 breakPtCB = cb;
1708 _CPU_ISR_Restore(level);
1709 return ret;
1712 void GX_PixModeSync()
1714 GX_LOAD_BP_REG(__gx->peCntrl);
1717 void GX_TexModeSync()
1719 GX_LOAD_BP_REG(0x63000000);
1722 void GX_SetMisc(u32 token,u32 value)
1724 u32 cnt;
1726 if(token==GX_MT_XF_FLUSH) {
1727 __gx->xfFlushSafe = value;
1728 cnt = cntlzw(__gx->xfFlushSafe);
1729 __gx->xfFlushExp = _SHIFTR(cnt,5,16);
1731 __gx->xfFlush = 1;
1732 if(!__gx->xfFlushSafe) return;
1734 __gx->dirtyState |= 0x0008;
1735 } else if(token==GX_MT_DL_SAVE_CTX) {
1736 __gx->saveDLctx = (value&0xff);
1738 return;
1741 void GX_SetViewportJitter(f32 xOrig,f32 yOrig,f32 wd,f32 ht,f32 nearZ,f32 farZ,u32 field)
1743 f32 x0,y0,x1,y1,n,f,z;
1744 static f32 Xfactor = 0.5;
1745 static f32 Yfactor = 342.0;
1746 static f32 Zfactor = 16777215.0;
1748 if(!field) yOrig -= Xfactor;
1750 x0 = wd*Xfactor;
1751 y0 = (-ht)*Xfactor;
1752 x1 = (xOrig+(wd*Xfactor))+Yfactor;
1753 y1 = (yOrig+(ht*Xfactor))+Yfactor;
1754 n = Zfactor*nearZ;
1755 f = Zfactor*farZ;
1756 z = f-n;
1758 GX_LOAD_XF_REGS(0x101a,6);
1759 FIFO_PUTF32(x0);
1760 FIFO_PUTF32(y0);
1761 FIFO_PUTF32(z);
1762 FIFO_PUTF32(x1);
1763 FIFO_PUTF32(y1);
1764 FIFO_PUTF32(f);
1767 void GX_SetViewport(f32 xOrig,f32 yOrig,f32 wd,f32 ht,f32 nearZ,f32 farZ)
1769 GX_SetViewportJitter(xOrig,yOrig,wd,ht,nearZ,farZ,1);
1772 void GX_LoadProjectionMtx(Mtx44 mt,u8 type)
1774 f32 tmp[7];
1776 ((u32*)((void*)tmp))[6] = (u32)type;
1777 tmp[0] = mt[0][0];
1778 tmp[2] = mt[1][1];
1779 tmp[4] = mt[2][2];
1780 tmp[5] = mt[2][3];
1782 switch(type) {
1783 case GX_PERSPECTIVE:
1784 tmp[1] = mt[0][2];
1785 tmp[3] = mt[1][2];
1786 break;
1787 case GX_ORTHOGRAPHIC:
1788 tmp[1] = mt[0][3];
1789 tmp[3] = mt[1][3];
1790 break;
1793 GX_LOAD_XF_REGS(0x1020,7);
1794 FIFO_PUTF32(tmp[0]);
1795 FIFO_PUTF32(tmp[1]);
1796 FIFO_PUTF32(tmp[2]);
1797 FIFO_PUTF32(tmp[3]);
1798 FIFO_PUTF32(tmp[4]);
1799 FIFO_PUTF32(tmp[5]);
1800 FIFO_PUTF32(tmp[6]);
1803 static void __GetImageTileCount(u32 fmt,u16 wd,u16 ht,u32 *xtiles,u32 *ytiles,u32 *zplanes)
1805 u32 xshift,yshift,tile;
1807 switch(fmt) {
1808 case GX_TF_I4:
1809 case GX_TF_IA4:
1810 case GX_CTF_R4:
1811 case GX_CTF_RA4:
1812 case GX_CTF_Z4:
1813 xshift = 3;
1814 yshift = 3;
1815 break;
1816 case GX_TF_Z8:
1817 case GX_TF_I8:
1818 case GX_TF_IA8:
1819 case GX_CTF_RA8:
1820 case GX_CTF_A8:
1821 case GX_CTF_R8:
1822 case GX_CTF_G8:
1823 case GX_CTF_B8:
1824 case GX_CTF_RG8:
1825 case GX_CTF_GB8:
1826 case GX_CTF_Z8M:
1827 case GX_CTF_Z8L:
1828 xshift = 3;
1829 yshift = 2;
1830 break;
1831 case GX_TF_Z16:
1832 case GX_TF_Z24X8:
1833 case GX_CTF_Z16L:
1834 case GX_TF_RGB565:
1835 case GX_TF_RGB5A3:
1836 case GX_TF_RGBA8:
1837 xshift = 2;
1838 yshift = 2;
1839 break;
1840 default:
1841 xshift = 0;
1842 yshift = 0;
1843 break;
1846 if(!(wd&0xffff)) wd = 1;
1847 if(!(ht&0xffff)) ht = 1;
1849 wd &= 0xffff;
1850 tile = (wd+((1<<xshift)-1))>>xshift;
1851 *xtiles = tile;
1853 ht &= 0xffff;
1854 tile = (ht+((1<<yshift)-1))>>yshift;
1855 *ytiles = tile;
1857 *zplanes = 1;
1858 if(fmt==GX_TF_RGBA8 || fmt==GX_TF_Z24X8) *zplanes = 2;
1861 void GX_SetCopyClear(GXColor color,u32 zvalue)
1863 u32 val;
1865 val = (_SHIFTL(color.a,8,8))|(color.r&0xff);
1866 GX_LOAD_BP_REG(0x4f000000|val);
1868 val = (_SHIFTL(color.g,8,8))|(color.b&0xff);
1869 GX_LOAD_BP_REG(0x50000000|val);
1871 val = zvalue&0x00ffffff;
1872 GX_LOAD_BP_REG(0x51000000|val);
1875 void GX_SetCopyClamp(u8 clamp)
1877 __gx->dispCopyCntrl = (__gx->dispCopyCntrl&~1)|(clamp&1);
1878 __gx->dispCopyCntrl = (__gx->dispCopyCntrl&~2)|(clamp&2);
1881 void GX_SetDispCopyGamma(u8 gamma)
1883 __gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0x180)|(_SHIFTL(gamma,7,2));
1886 void GX_SetCopyFilter(u8 aa,u8 sample_pattern[12][2],u8 vf,u8 vfilter[7])
1888 u32 reg01=0,reg02=0,reg03=0,reg04=0,reg53=0,reg54=0;
1890 if(aa) {
1891 reg01 = sample_pattern[0][0]&0xf;
1892 reg01 = (reg01&~0xf0)|(_SHIFTL(sample_pattern[0][1],4,4));
1893 reg01 = (reg01&~0xf00)|(_SHIFTL(sample_pattern[1][0],8,4));
1894 reg01 = (reg01&~0xf000)|(_SHIFTL(sample_pattern[1][1],12,4));
1895 reg01 = (reg01&~0xf0000)|(_SHIFTL(sample_pattern[2][0],16,4));
1896 reg01 = (reg01&~0xf00000)|(_SHIFTL(sample_pattern[2][1],20,4));
1897 reg01 = (reg01&~0xff000000)|(_SHIFTL(0x01,24,8));
1899 reg02 = sample_pattern[3][0]&0xf;
1900 reg02 = (reg02&~0xf0)|(_SHIFTL(sample_pattern[3][1],4,4));
1901 reg02 = (reg02&~0xf00)|(_SHIFTL(sample_pattern[4][0],8,4));
1902 reg02 = (reg02&~0xf000)|(_SHIFTL(sample_pattern[4][1],12,4));
1903 reg02 = (reg02&~0xf0000)|(_SHIFTL(sample_pattern[5][0],16,4));
1904 reg02 = (reg02&~0xf00000)|(_SHIFTL(sample_pattern[5][1],20,4));
1905 reg02 = (reg02&~0xff000000)|(_SHIFTL(0x02,24,8));
1907 reg03 = sample_pattern[6][0]&0xf;
1908 reg03 = (reg03&~0xf0)|(_SHIFTL(sample_pattern[6][1],4,4));
1909 reg03 = (reg03&~0xf00)|(_SHIFTL(sample_pattern[7][0],8,4));
1910 reg03 = (reg03&~0xf000)|(_SHIFTL(sample_pattern[7][1],12,4));
1911 reg03 = (reg03&~0xf0000)|(_SHIFTL(sample_pattern[8][0],16,4));
1912 reg03 = (reg03&~0xf00000)|(_SHIFTL(sample_pattern[8][1],20,4));
1913 reg03 = (reg03&~0xff000000)|(_SHIFTL(0x03,24,8));
1915 reg04 = sample_pattern[9][0]&0xf;
1916 reg04 = (reg04&~0xf0)|(_SHIFTL(sample_pattern[9][1],4,4));
1917 reg04 = (reg04&~0xf00)|(_SHIFTL(sample_pattern[10][0],8,4));
1918 reg04 = (reg04&~0xf000)|(_SHIFTL(sample_pattern[10][1],12,4));
1919 reg04 = (reg04&~0xf0000)|(_SHIFTL(sample_pattern[11][0],16,4));
1920 reg04 = (reg04&~0xf00000)|(_SHIFTL(sample_pattern[11][1],20,4));
1921 reg04 = (reg04&~0xff000000)|(_SHIFTL(0x04,24,8));
1922 } else {
1923 reg01 = 0x01666666;
1924 reg02 = 0x02666666;
1925 reg03 = 0x03666666;
1926 reg04 = 0x04666666;
1928 GX_LOAD_BP_REG(reg01);
1929 GX_LOAD_BP_REG(reg02);
1930 GX_LOAD_BP_REG(reg03);
1931 GX_LOAD_BP_REG(reg04);
1933 reg53 = 0x53595000;
1934 reg54 = 0x54000015;
1935 if(vf) {
1936 reg53 = 0x53000000|(vfilter[0]&0x3f);
1937 reg53 = (reg53&~0xfc0)|(_SHIFTL(vfilter[1],6,6));
1938 reg53 = (reg53&~0x3f000)|(_SHIFTL(vfilter[2],12,6));
1939 reg53 = (reg53&~0xfc0000)|(_SHIFTL(vfilter[3],18,6));
1941 reg54 = 0x54000000|(vfilter[4]&0x3f);
1942 reg54 = (reg54&~0xfc0)|(_SHIFTL(vfilter[5],6,6));
1943 reg54 = (reg54&~0x3f000)|(_SHIFTL(vfilter[6],12,6));
1945 GX_LOAD_BP_REG(reg53);
1946 GX_LOAD_BP_REG(reg54);
1949 void GX_SetDispCopyFrame2Field(u8 mode)
1951 __gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0x3000)|(_SHIFTL(mode,12,2));
1954 u32 GX_SetDispCopyYScale(f32 yscale)
1956 u32 ht,yScale = 0;
1958 yScale = ((u32)(256.0f/yscale))&0x1ff;
1959 GX_LOAD_BP_REG(0x4e000000|yScale);
1961 __gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0x400)|(_SHIFTL(((256-yScale)>0),10,1));
1962 ht = _SHIFTR(__gx->dispCopyWH,12,10)+1;
1963 return __GX_GetNumXfbLines(ht,yScale);
1966 void GX_SetDispCopyDst(u16 wd,u16 ht)
1968 __gx->dispCopyDst = (__gx->dispCopyDst&~0x3ff)|(_SHIFTR(wd,4,10));
1969 __gx->dispCopyDst = (__gx->dispCopyDst&~0xff000000)|(_SHIFTL(0x4d,24,8));
1972 void GX_SetDispCopySrc(u16 left,u16 top,u16 wd,u16 ht)
1974 __gx->dispCopyTL = (__gx->dispCopyTL&~0x00ffffff)|XY(left,top);
1975 __gx->dispCopyTL = (__gx->dispCopyTL&~0xff000000)|(_SHIFTL(0x49,24,8));
1976 __gx->dispCopyWH = (__gx->dispCopyWH&~0x00ffffff)|XY((wd-1),(ht-1));
1977 __gx->dispCopyWH = (__gx->dispCopyWH&~0xff000000)|(_SHIFTL(0x4a,24,8));
1980 void GX_CopyDisp(void *dest,u8 clear)
1982 u8 clflag;
1983 u32 val;
1985 if(clear) {
1986 val= (__gx->peZMode&~0xf)|0xf;
1987 GX_LOAD_BP_REG(val);
1988 val = (__gx->peCMode0&~0x3);
1989 GX_LOAD_BP_REG(val);
1992 clflag = 0;
1993 if(clear || (__gx->peCntrl&0x7)==0x0003) {
1994 if(__gx->peCntrl&0x40) {
1995 clflag = 1;
1996 val = (__gx->peCntrl&~0x40);
1997 GX_LOAD_BP_REG(val);
2001 GX_LOAD_BP_REG(__gx->dispCopyTL); // set source top
2002 GX_LOAD_BP_REG(__gx->dispCopyWH);
2004 GX_LOAD_BP_REG(__gx->dispCopyDst);
2006 val = 0x4b000000|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(dest),5,24));
2007 GX_LOAD_BP_REG(val);
2009 __gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0x800)|(_SHIFTL(clear,11,1));
2010 __gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0x4000)|0x4000;
2011 __gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0xff000000)|(_SHIFTL(0x52,24,8));
2013 GX_LOAD_BP_REG(__gx->dispCopyCntrl);
2015 if(clear) {
2016 GX_LOAD_BP_REG(__gx->peZMode);
2017 GX_LOAD_BP_REG(__gx->peCMode0);
2019 if(clflag) GX_LOAD_BP_REG(__gx->peCntrl);
2022 void GX_CopyTex(void *dest,u8 clear)
2024 u8 clflag;
2025 u32 val;
2027 if(clear) {
2028 val = (__gx->peZMode&~0xf)|0xf;
2029 GX_LOAD_BP_REG(val);
2030 val = (__gx->peCMode0&~0x3);
2031 GX_LOAD_BP_REG(val);
2034 clflag = 0;
2035 val = __gx->peCntrl;
2036 if(__gx->texCopyZTex && (val&0x7)!=0x0003) {
2037 clflag = 1;
2038 val = (val&~0x7)|0x0003;
2040 if(clear || (val&0x7)==0x0003) {
2041 if(val&0x40) {
2042 clflag = 1;
2043 val = (val&~0x40);
2046 if(clflag) GX_LOAD_BP_REG(val);
2048 val = 0x4b000000|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(dest),5,24));
2050 GX_LOAD_BP_REG(__gx->texCopyTL);
2051 GX_LOAD_BP_REG(__gx->texCopyWH);
2052 GX_LOAD_BP_REG(__gx->texCopyDst);
2053 GX_LOAD_BP_REG(val);
2055 __gx->texCopyCntrl = (__gx->texCopyCntrl&~0x800)|(_SHIFTL(clear,11,1));
2056 __gx->texCopyCntrl = (__gx->texCopyCntrl&~0x4000);
2057 __gx->texCopyCntrl = (__gx->texCopyCntrl&~0xff000000)|(_SHIFTL(0x52,24,8));
2058 GX_LOAD_BP_REG(__gx->texCopyCntrl);
2060 if(clear) {
2061 GX_LOAD_BP_REG(__gx->peZMode);
2062 GX_LOAD_BP_REG(__gx->peCMode0);
2064 if(clflag) GX_LOAD_BP_REG(__gx->peCntrl);
2067 void GX_SetTexCopySrc(u16 left,u16 top,u16 wd,u16 ht)
2069 __gx->texCopyTL = (__gx->texCopyTL&~0x00ffffff)|XY(left,top);
2070 __gx->texCopyTL = (__gx->texCopyTL&~0xff000000)|(_SHIFTL(0x49,24,8));
2071 __gx->texCopyWH = (__gx->texCopyWH&~0x00ffffff)|XY((wd-1),(ht-1));
2072 __gx->texCopyWH = (__gx->texCopyWH&~0xff000000)|(_SHIFTL(0x4a,24,8));
2075 void GX_SetTexCopyDst(u16 wd,u16 ht,u32 fmt,u8 mipmap)
2077 u8 lfmt = fmt&0xf;
2078 u32 xtiles,ytiles,zplanes;
2080 __GetImageTileCount(fmt,wd,ht,&xtiles,&ytiles,&zplanes);
2081 __gx->texCopyDst = (__gx->texCopyDst&~0x3ff)|((xtiles*zplanes)&0x3ff);
2083 if(fmt==GX_TF_Z16) lfmt = 11;
2084 if(fmt==GX_CTF_YUVA8 || (fmt>=GX_TF_I4 && fmt<GX_TF_RGB565)) __gx->texCopyCntrl = (__gx->texCopyCntrl&~0x18000)|0x18000;
2085 else __gx->texCopyCntrl = (__gx->texCopyCntrl&~0x18000)|0x10000;
2087 __gx->texCopyCntrl = (__gx->texCopyCntrl&~0x8)|(lfmt&0x8);
2088 __gx->texCopyCntrl = (__gx->texCopyCntrl&~0x200)|(_SHIFTL(mipmap,9,1));
2089 __gx->texCopyCntrl = (__gx->texCopyCntrl&~0x70)|(_SHIFTL(lfmt,4,3));
2091 __gx->texCopyDst = (__gx->texCopyDst&~0xff000000)|(_SHIFTL(0x4d,24,8));
2093 __gx->texCopyZTex = ((fmt&_GX_TF_ZTF)==_GX_TF_ZTF);
2096 void GX_ClearBoundingBox()
2098 GX_LOAD_BP_REG(0x550003ff);
2099 GX_LOAD_BP_REG(0x560003ff);
2102 void GX_BeginDispList(void *list,u32 size)
2104 struct __gxfifo *fifo;
2106 if(__gx->dirtyState)
2107 __GX_SetDirtyState();
2109 if(__gx->saveDLctx)
2110 memcpy(_gx_saved_data,__gxregs,STRUCT_REGDEF_SIZE);
2112 fifo = (struct __gxfifo*)&_gx_dl_fifoobj;
2113 fifo->buf_start = (u32)list;
2114 fifo->buf_end = (u32)list + size - 4;
2115 fifo->size = size;
2117 fifo->rd_ptr = (u32)list;
2118 fifo->wt_ptr = (u32)list;
2119 fifo->rdwt_dst = 0;
2121 __gx->gxFifoUnlinked = 1;
2123 GX_GetCPUFifo(&_gx_old_cpufifo);
2124 GX_SetCPUFifo(&_gx_dl_fifoobj);
2125 __GX_ResetWriteGatherPipe();
2128 u32 GX_EndDispList()
2130 u32 level,ret = 0;
2131 struct __gxfifo *fifo;
2133 GX_GetCPUFifo(&_gx_dl_fifoobj);
2134 GX_SetCPUFifo(&_gx_old_cpufifo);
2136 if(__gx->saveDLctx) {
2137 _CPU_ISR_Disable(level);
2138 memcpy(__gxregs,_gx_saved_data,STRUCT_REGDEF_SIZE);
2139 _CPU_ISR_Restore(level);
2142 __gx->gxFifoUnlinked = 0;
2144 fifo = (struct __gxfifo*)&_gx_dl_fifoobj;
2145 ret = fifo->rdwt_dst;
2147 return ret;
2150 void GX_CallDispList(void *list,u32 nbytes)
2152 if(__gx->dirtyState)
2153 __GX_SetDirtyState();
2155 if(!__gx->vcdClear)
2156 __GX_SendFlushPrim();
2158 FIFO_PUTU8(0x40); //call displaylist
2159 FIFO_PUTU32(MEM_VIRTUAL_TO_PHYSICAL(list));
2160 FIFO_PUTU32(nbytes);
2163 void GX_SetChanCtrl(s32 channel,u8 enable,u8 ambsrc,u8 matsrc,u8 litmask,u8 diff_fn,u8 attn_fn)
2165 u32 reg,difffn = (attn_fn==GX_AF_SPEC)?GX_DF_NONE:diff_fn;
2166 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));
2168 reg = (channel&0x03);
2169 __gx->chnCntrl[reg] = val;
2170 __gx->dirtyState |= (0x1000<<reg);
2172 if(channel==GX_COLOR0A0) {
2173 __gx->chnCntrl[2] = val;
2174 __gx->dirtyState |= 0x5000;
2175 } else {
2176 __gx->chnCntrl[3] = val;
2177 __gx->dirtyState |= 0xa000;
2181 void GX_SetChanAmbColor(s32 channel,GXColor color)
2183 u32 reg,val = (_SHIFTL(color.r,24,8))|(_SHIFTL(color.g,16,8))|(_SHIFTL(color.b,8,8))|0x00;
2184 switch(channel) {
2185 case GX_COLOR0:
2186 reg = 0;
2187 val |= (__gx->chnAmbColor[0]&0xff);
2188 break;
2189 case GX_COLOR1:
2190 reg = 1;
2191 val |= (__gx->chnAmbColor[1]&0xff);
2192 break;
2193 case GX_ALPHA0:
2194 reg = 0;
2195 val = ((__gx->chnAmbColor[0]&~0xff)|(color.a&0xff));
2196 break;
2197 case GX_ALPHA1:
2198 reg = 1;
2199 val = ((__gx->chnAmbColor[1]&~0xff)|(color.a&0xff));
2200 break;
2201 case GX_COLOR0A0:
2202 reg = 0;
2203 val |= (color.a&0xFF);
2204 break;
2205 case GX_COLOR1A1:
2206 reg = 1;
2207 val |= (color.a&0xFF);
2208 break;
2209 default:
2210 return;
2213 __gx->chnAmbColor[reg] = val;
2214 __gx->dirtyState |= (0x0100<<reg);
2217 void GX_SetChanMatColor(s32 channel,GXColor color)
2219 u32 reg,val = (_SHIFTL(color.r,24,8))|(_SHIFTL(color.g,16,8))|(_SHIFTL(color.b,8,8))|0x00;
2220 switch(channel) {
2221 case GX_COLOR0:
2222 reg = 0;
2223 val |= (__gx->chnMatColor[0]&0xff);
2224 break;
2225 case GX_COLOR1:
2226 reg = 1;
2227 val |= (__gx->chnMatColor[1]&0xff);
2228 break;
2229 case GX_ALPHA0:
2230 reg = 0;
2231 val = ((__gx->chnMatColor[0]&~0xff)|(color.a&0xff));
2232 break;
2233 case GX_ALPHA1:
2234 reg = 1;
2235 val = ((__gx->chnMatColor[1]&~0xff)|(color.a&0xff));
2236 break;
2237 case GX_COLOR0A0:
2238 reg = 0;
2239 val |= (color.a&0xFF);
2240 break;
2241 case GX_COLOR1A1:
2242 reg = 1;
2243 val |= (color.a&0xFF);
2244 break;
2245 default:
2246 return;
2249 __gx->chnMatColor[reg] = val;
2250 __gx->dirtyState |= (0x0400<<reg);
2253 void GX_SetArray(u32 attr,void *ptr,u8 stride)
2255 u32 idx = 0;
2257 if(attr==GX_VA_NBT) attr = GX_VA_NRM;
2258 if(attr>=GX_VA_POS && attr<=GX_LITMTXARRAY) {
2259 idx = attr-GX_VA_POS;
2260 GX_LOAD_CP_REG((0xA0+idx),(u32)MEM_VIRTUAL_TO_PHYSICAL(ptr));
2261 GX_LOAD_CP_REG((0xB0+idx),(u32)stride);
2265 static __inline__ void __SETVCDATTR(u8 attr,u8 type)
2267 switch(attr) {
2268 case GX_VA_PTNMTXIDX:
2269 __gx->vcdLo = (__gx->vcdLo&~0x1)|(type&0x1);
2270 break;
2271 case GX_VA_TEX0MTXIDX:
2272 __gx->vcdLo = (__gx->vcdLo&~0x2)|(_SHIFTL(type,1,1));
2273 break;
2274 case GX_VA_TEX1MTXIDX:
2275 __gx->vcdLo = (__gx->vcdLo&~0x4)|(_SHIFTL(type,2,1));
2276 break;
2277 case GX_VA_TEX2MTXIDX:
2278 __gx->vcdLo = (__gx->vcdLo&~0x8)|(_SHIFTL(type,3,1));
2279 break;
2280 case GX_VA_TEX3MTXIDX:
2281 __gx->vcdLo = (__gx->vcdLo&~0x10)|(_SHIFTL(type,4,1));
2282 break;
2283 case GX_VA_TEX4MTXIDX:
2284 __gx->vcdLo = (__gx->vcdLo&~0x20)|(_SHIFTL(type,5,1));
2285 break;
2286 case GX_VA_TEX5MTXIDX:
2287 __gx->vcdLo = (__gx->vcdLo&~0x40)|(_SHIFTL(type,6,1));
2288 break;
2289 case GX_VA_TEX6MTXIDX:
2290 __gx->vcdLo = (__gx->vcdLo&~0x80)|(_SHIFTL(type,7,1));
2291 break;
2292 case GX_VA_TEX7MTXIDX:
2293 __gx->vcdLo = (__gx->vcdLo&~0x100)|(_SHIFTL(type,8,1));
2294 break;
2295 case GX_VA_POS:
2296 __gx->vcdLo = (__gx->vcdLo&~0x600)|(_SHIFTL(type,9,2));
2297 break;
2298 case GX_VA_NRM:
2299 __gx->vcdLo = (__gx->vcdLo&~0x1800)|(_SHIFTL(type,11,2));
2300 __gx->vcdNrms = 1;
2301 break;
2302 case GX_VA_NBT:
2303 __gx->vcdLo = (__gx->vcdLo&~0x1800)|(_SHIFTL(type,11,2));
2304 __gx->vcdNrms = 2;
2305 break;
2306 case GX_VA_CLR0:
2307 __gx->vcdLo = (__gx->vcdLo&~0x6000)|(_SHIFTL(type,13,2));
2308 break;
2309 case GX_VA_CLR1:
2310 __gx->vcdLo = (__gx->vcdLo&~0x18000)|(_SHIFTL(type,15,2));
2311 break;
2312 case GX_VA_TEX0:
2313 __gx->vcdHi = (__gx->vcdHi&~0x3)|(type&0x3);
2314 break;
2315 case GX_VA_TEX1:
2316 __gx->vcdHi = (__gx->vcdHi&~0xc)|(_SHIFTL(type,2,2));
2317 break;
2318 case GX_VA_TEX2:
2319 __gx->vcdHi = (__gx->vcdHi&~0x30)|(_SHIFTL(type,4,2));
2320 break;
2321 case GX_VA_TEX3:
2322 __gx->vcdHi = (__gx->vcdHi&~0xc0)|(_SHIFTL(type,6,2));
2323 break;
2324 case GX_VA_TEX4:
2325 __gx->vcdHi = (__gx->vcdHi&~0x300)|(_SHIFTL(type,8,2));
2326 break;
2327 case GX_VA_TEX5:
2328 __gx->vcdHi = (__gx->vcdHi&~0xc00)|(_SHIFTL(type,10,2));
2329 break;
2330 case GX_VA_TEX6:
2331 __gx->vcdHi = (__gx->vcdHi&~0x3000)|(_SHIFTL(type,12,2));
2332 break;
2333 case GX_VA_TEX7:
2334 __gx->vcdHi = (__gx->vcdHi&~0xc000)|(_SHIFTL(type,14,2));
2335 break;
2339 void GX_SetVtxDesc(u8 attr,u8 type)
2341 __SETVCDATTR(attr,type);
2342 __gx->dirtyState |= 0x0008;
2345 void GX_SetVtxDescv(GXVtxDesc *attr_list)
2347 u32 i;
2349 if(!attr_list) return;
2351 for(i=0;i<GX_MAX_VTXDESC_LISTSIZE;i++){
2352 if(attr_list[i].attr==GX_VA_NULL) break;
2354 __SETVCDATTR(attr_list[i].attr,attr_list[i].type);
2356 __gx->dirtyState |= 0x0008;
2359 static __inline__ void __SETVCDFMT(u8 vtxfmt,u32 vtxattr,u32 comptype,u32 compsize,u32 frac)
2361 u8 vat = (vtxfmt&7);
2363 if(vtxattr==GX_VA_POS && (comptype==GX_POS_XY || comptype==GX_POS_XYZ)
2364 && (compsize>=GX_U8 && compsize<=GX_F32)) {
2365 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1)|(comptype&1);
2366 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0xe)|(_SHIFTL(compsize,1,3));
2367 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1f0)|(_SHIFTL(frac,4,5));
2368 if(frac)
2369 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2370 } else if(vtxattr==GX_VA_NRM && comptype==GX_NRM_XYZ
2371 && (compsize==GX_S8 || compsize==GX_S16 || compsize==GX_F32)) {
2372 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x200);
2373 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1C00)|(_SHIFTL(compsize,10,3));
2374 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x80000000);
2375 } else if(vtxattr==GX_VA_NBT && (comptype==GX_NRM_NBT || comptype==GX_NRM_NBT3)
2376 && (compsize==GX_S8 || compsize==GX_S16 || compsize==GX_F32)) {
2377 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x200)|0x200;
2378 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1C00)|(_SHIFTL(compsize,10,3));
2379 if(comptype==GX_NRM_NBT3)
2380 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x80000000)|0x80000000;
2381 } else if(vtxattr==GX_VA_CLR0 && (comptype==GX_CLR_RGB || comptype==GX_CLR_RGBA)
2382 && (compsize>=GX_RGB565 && compsize<=GX_RGBA8)) {
2383 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x2000)|(_SHIFTL(comptype,13,1));
2384 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1C000)|(_SHIFTL(compsize,14,3));
2385 } else if(vtxattr==GX_VA_CLR1 && (comptype==GX_CLR_RGB || comptype==GX_CLR_RGBA)
2386 && (compsize>=GX_RGB565 && compsize<=GX_RGBA8)) {
2387 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x20000)|(_SHIFTL(comptype,17,1));
2388 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1C0000)|(_SHIFTL(compsize,18,3));
2389 } else if(vtxattr==GX_VA_TEX0 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2390 && (compsize>=GX_U8 && compsize<=GX_F32)) {
2391 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x200000)|(_SHIFTL(comptype,21,1));
2392 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1C00000)|(_SHIFTL(compsize,22,3));
2393 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x3E000000)|(_SHIFTL(frac,25,5));
2394 if(frac)
2395 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2396 } else if(vtxattr==GX_VA_TEX1 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2397 && (compsize>=GX_U8 && compsize<=GX_F32)) {
2398 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x1)|(comptype&1);
2399 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0xe)|(_SHIFTL(compsize,1,3));
2400 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x1F0)|(_SHIFTL(frac,4,5));
2401 if(frac)
2402 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2403 } else if(vtxattr==GX_VA_TEX2 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2404 && (compsize>=GX_U8 && compsize<=GX_F32)) {
2405 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x200)|(_SHIFTL(comptype,9,1));
2406 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x1C00)|(_SHIFTL(compsize,10,3));
2407 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x3E000)|(_SHIFTL(frac,13,5));
2408 if(frac)
2409 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2410 } else if(vtxattr==GX_VA_TEX3 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2411 && (compsize>=GX_U8 && compsize<=GX_F32)) {
2412 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x40000)|(_SHIFTL(comptype,18,1));
2413 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x380000)|(_SHIFTL(compsize,19,3));
2414 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x7C00000)|(_SHIFTL(frac,22,5));
2415 if(frac)
2416 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2417 } else if(vtxattr==GX_VA_TEX4 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2418 && (compsize>=GX_U8 && compsize<=GX_F32)) {
2419 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x8000000)|(_SHIFTL(comptype,27,1));
2420 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x70000000)|(_SHIFTL(compsize,28,3));
2421 __gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x1f)|(frac&0x1f);
2422 if(frac)
2423 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2424 } else if(vtxattr==GX_VA_TEX5 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2425 && (compsize>=GX_U8 && compsize<=GX_F32)) {
2426 __gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x20)|(_SHIFTL(comptype,5,1));
2427 __gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x1C0)|(_SHIFTL(compsize,6,3));
2428 __gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x3E00)|(_SHIFTL(frac,9,5));
2429 if(frac)
2430 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2431 } else if(vtxattr==GX_VA_TEX6 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2432 && (compsize>=GX_U8 && compsize<=GX_F32)) {
2433 __gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x4000)|(_SHIFTL(comptype,14,1));
2434 __gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x38000)|(_SHIFTL(compsize,15,3));
2435 __gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x7C0000)|(_SHIFTL(frac,18,5));
2436 if(frac)
2437 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2438 } else if(vtxattr==GX_VA_TEX7 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2439 && (compsize>=GX_U8 && compsize<=GX_F32)) {
2440 __gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x800000)|(_SHIFTL(comptype,23,1));
2441 __gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x7000000)|(_SHIFTL(compsize,24,3));
2442 __gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0xF8000000)|(_SHIFTL(frac,27,5));
2443 if(frac)
2444 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2448 void GX_SetVtxAttrFmt(u8 vtxfmt,u32 vtxattr,u32 comptype,u32 compsize,u32 frac)
2450 __SETVCDFMT(vtxfmt,vtxattr,comptype,compsize,frac);
2451 __gx->VATTable |= (1<<vtxfmt);
2452 __gx->dirtyState |= 0x0010;
2455 void GX_SetVtxAttrFmtv(u8 vtxfmt,GXVtxAttrFmt *attr_list)
2457 u32 i;
2459 for(i=0;i<GX_MAX_VTXATTRFMT_LISTSIZE;i++) {
2460 if(attr_list[i].vtxattr==GX_VA_NULL) break;
2462 __SETVCDFMT(vtxfmt,attr_list[i].vtxattr,attr_list[i].comptype,attr_list[i].compsize,attr_list[i].frac);
2464 __gx->VATTable |= (1<<vtxfmt);
2465 __gx->dirtyState |= 0x0010;
2468 void GX_Begin(u8 primitve,u8 vtxfmt,u16 vtxcnt)
2470 u8 reg = primitve|(vtxfmt&7);
2472 if(__gx->dirtyState)
2473 __GX_SetDirtyState();
2475 FIFO_PUTU8(reg);
2476 FIFO_PUTU16(vtxcnt);
2479 void GX_SetTexCoordGen(u16 texcoord,u32 tgen_typ,u32 tgen_src,u32 mtxsrc)
2481 GX_SetTexCoordGen2(texcoord,tgen_typ,tgen_src,mtxsrc,GX_FALSE,GX_DTTIDENTITY);
2484 void GX_SetTexCoordGen2(u16 texcoord,u32 tgen_typ,u32 tgen_src,u32 mtxsrc,u32 normalize,u32 postmtx)
2486 u32 txc;
2487 u32 texcoords;
2488 u8 vtxrow,stq;
2490 if(texcoord>=GX_MAXCOORD) return;
2492 stq = 0;
2493 switch(tgen_src) {
2494 case GX_TG_POS:
2495 vtxrow = 0;
2496 stq = 1;
2497 break;
2498 case GX_TG_NRM:
2499 vtxrow = 1;
2500 stq = 1;
2501 break;
2502 case GX_TG_BINRM:
2503 vtxrow = 3;
2504 stq = 1;
2505 break;
2506 case GX_TG_TANGENT:
2507 vtxrow = 4;
2508 stq = 1;
2509 break;
2510 case GX_TG_COLOR0:
2511 vtxrow = 2;
2512 break;
2513 case GX_TG_COLOR1:
2514 vtxrow = 2;
2515 break;
2516 case GX_TG_TEX0:
2517 vtxrow = 5;
2518 break;
2519 case GX_TG_TEX1:
2520 vtxrow = 6;
2521 break;
2522 case GX_TG_TEX2:
2523 vtxrow = 7;
2524 break;
2525 case GX_TG_TEX3:
2526 vtxrow = 8;
2527 break;
2528 case GX_TG_TEX4:
2529 vtxrow = 9;
2530 break;
2531 case GX_TG_TEX5:
2532 vtxrow = 10;
2533 break;
2534 case GX_TG_TEX6:
2535 vtxrow = 11;
2536 break;
2537 case GX_TG_TEX7:
2538 vtxrow = 12;
2539 break;
2540 default:
2541 vtxrow = 5;
2542 break;
2545 texcoords = 0;
2546 txc = (texcoord&7);
2547 if((tgen_typ==GX_TG_MTX3x4 || tgen_typ==GX_TG_MTX2x4))
2549 if(tgen_typ==GX_TG_MTX3x4) texcoords = 0x02;
2551 texcoords |= (_SHIFTL(stq,2,1));
2552 texcoords |= (_SHIFTL(vtxrow,7,5));
2553 } else if((tgen_typ>=GX_TG_BUMP0 && tgen_typ<=GX_TG_BUMP7))
2555 tgen_src -= GX_TG_TEXCOORD0;
2556 tgen_typ -= GX_TG_BUMP0;
2558 texcoords = 0x10;
2559 texcoords |= (_SHIFTL(stq,2,1));
2560 texcoords |= (_SHIFTL(vtxrow,7,5));
2561 texcoords |= (_SHIFTL(tgen_src,12,3));
2562 texcoords |= (_SHIFTL(tgen_typ,15,3));
2563 } else if(tgen_typ==GX_TG_SRTG) {
2564 if(tgen_src==GX_TG_COLOR0) texcoords = 0x20;
2565 else if(tgen_src==GX_TG_COLOR1) texcoords = 0x30;
2566 texcoords |= (_SHIFTL(stq,2,1));
2567 texcoords |= (_SHIFTL(2,7,5));
2570 postmtx -= GX_DTTMTX0;
2571 __gx->texCoordGen[txc] = texcoords;
2572 __gx->texCoordGen2[txc] = ((_SHIFTL(normalize,8,1))|(postmtx&0x3f));
2574 switch(texcoord) {
2575 case GX_TEXCOORD0:
2576 __gx->mtxIdxLo = (__gx->mtxIdxLo&~0xfc0)|(_SHIFTL(mtxsrc,6,6));
2577 break;
2578 case GX_TEXCOORD1:
2579 __gx->mtxIdxLo = (__gx->mtxIdxLo&~0x3f000)|(_SHIFTL(mtxsrc,12,6));
2580 break;
2581 case GX_TEXCOORD2:
2582 __gx->mtxIdxLo = (__gx->mtxIdxLo&~0xfc0000)|(_SHIFTL(mtxsrc,18,6));
2583 break;
2584 case GX_TEXCOORD3:
2585 __gx->mtxIdxLo = (__gx->mtxIdxLo&~0x3f000000)|(_SHIFTL(mtxsrc,24,6));
2586 break;
2587 case GX_TEXCOORD4:
2588 __gx->mtxIdxHi = (__gx->mtxIdxHi&~0x3f)|(mtxsrc&0x3f);
2589 break;
2590 case GX_TEXCOORD5:
2591 __gx->mtxIdxHi = (__gx->mtxIdxHi&~0xfc0)|(_SHIFTL(mtxsrc,6,6));
2592 break;
2593 case GX_TEXCOORD6:
2594 __gx->mtxIdxHi = (__gx->mtxIdxHi&~0x3f000)|(_SHIFTL(mtxsrc,12,6));
2595 break;
2596 case GX_TEXCOORD7:
2597 __gx->mtxIdxHi = (__gx->mtxIdxHi&~0xfc0000)|(_SHIFTL(mtxsrc,18,6));
2598 break;
2600 __gx->dirtyState |= (0x04000000|(0x00010000<<texcoord));
2603 void GX_SetZTexture(u8 op,u8 fmt,u32 bias)
2605 u32 val = 0;
2607 if(fmt==GX_TF_Z8) fmt = 0;
2608 else if(fmt==GX_TF_Z16) fmt = 1;
2609 else fmt = 2;
2611 val = (u32)(_SHIFTL(op,2,2))|(fmt&3);
2612 GX_LOAD_BP_REG(0xF4000000|(bias&0x00FFFFFF));
2613 GX_LOAD_BP_REG(0xF5000000|(val&0x00FFFFFF));
2616 static inline void WriteMtxPS4x3(register Mtx mt,register void *wgpipe)
2618 register f32 tmp0,tmp1,tmp2,tmp3,tmp4,tmp5;
2619 __asm__ __volatile__ (
2620 "psq_l %0,0(%6),0,0\n\
2621 psq_l %1,8(%6),0,0\n\
2622 psq_l %2,16(%6),0,0\n\
2623 psq_l %3,24(%6),0,0\n\
2624 psq_l %4,32(%6),0,0\n\
2625 psq_l %5,40(%6),0,0\n\
2626 psq_st %0,0(%7),0,0\n\
2627 psq_st %1,0(%7),0,0\n\
2628 psq_st %2,0(%7),0,0\n\
2629 psq_st %3,0(%7),0,0\n\
2630 psq_st %4,0(%7),0,0\n\
2631 psq_st %5,0(%7),0,0"
2632 : "=&f"(tmp0),"=&f"(tmp1),"=&f"(tmp2),"=&f"(tmp3),"=&f"(tmp4),"=&f"(tmp5)
2633 : "b"(mt), "b"(wgpipe)
2634 : "memory"
2638 static inline void WriteMtxPS3x3from4x3(register Mtx mt,register void *wgpipe)
2640 register f32 tmp0,tmp1,tmp2,tmp3,tmp4,tmp5;
2641 __asm__ __volatile__
2642 ("psq_l %0,0(%6),0,0\n\
2643 lfs %1,8(%6)\n\
2644 psq_l %2,16(%6),0,0\n\
2645 lfs %3,24(%6)\n\
2646 psq_l %4,32(%6),0,0\n\
2647 lfs %5,40(%6)\n\
2648 psq_st %0,0(%7),0,0\n\
2649 stfs %1,0(%7)\n\
2650 psq_st %2,0(%7),0,0\n\
2651 stfs %3,0(%7)\n\
2652 psq_st %4,0(%7),0,0\n\
2653 stfs %5,0(%7)"
2654 : "=&f"(tmp0),"=&f"(tmp1),"=&f"(tmp2),"=&f"(tmp3),"=&f"(tmp4),"=&f"(tmp5)
2655 : "b"(mt), "b"(wgpipe)
2656 : "memory"
2660 static inline void WriteMtxPS3x3(register Mtx33 mt,register void *wgpipe)
2662 register f32 tmp0,tmp1,tmp2,tmp3,tmp4;
2663 __asm__ __volatile__
2664 ("psq_l %0,0(%5),0,0\n\
2665 psq_l %1,8(%5),0,0\n\
2666 psq_l %2,16(%5),0,0\n\
2667 psq_l %3,24(%5),0,0\n\
2668 lfs %4,32(%5)\n\
2669 psq_st %0,0(%6),0,0\n\
2670 psq_st %1,0(%6),0,0\n\
2671 psq_st %2,0(%6),0,0\n\
2672 psq_st %3,0(%6),0,0\n\
2673 stfs %4,0(%6)"
2674 : "=&f"(tmp0),"=&f"(tmp1),"=&f"(tmp2),"=&f"(tmp3),"=&f"(tmp4)
2675 : "b"(mt), "b"(wgpipe)
2676 : "memory"
2680 static inline void WriteMtxPS4x2(register Mtx mt,register void *wgpipe)
2682 register f32 tmp0,tmp1,tmp2,tmp3;
2683 __asm__ __volatile__
2684 ("psq_l %0,0(%4),0,0\n\
2685 psq_l %1,8(%4),0,0\n\
2686 psq_l %2,16(%4),0,0\n\
2687 psq_l %3,24(%4),0,0\n\
2688 psq_st %0,0(%5),0,0\n\
2689 psq_st %1,0(%5),0,0\n\
2690 psq_st %2,0(%5),0,0\n\
2691 psq_st %3,0(%5),0,0"
2692 : "=&f"(tmp0),"=&f"(tmp1),"=&f"(tmp2),"=&f"(tmp3)
2693 : "b"(mt), "b"(wgpipe)
2694 : "memory"
2698 void GX_LoadPosMtxImm(Mtx mt,u32 pnidx)
2700 GX_LOAD_XF_REGS((0x0000|(_SHIFTL(pnidx,2,8))),12);
2701 WriteMtxPS4x3(mt,(void*)WGPIPE);
2704 void GX_LoadPosMtxIdx(u16 mtxidx,u32 pnidx)
2706 FIFO_PUTU8(0x20);
2707 FIFO_PUTU32(((_SHIFTL(mtxidx,16,16))|0xb000|(_SHIFTL(pnidx,2,8))));
2710 void GX_LoadNrmMtxImm(Mtx mt,u32 pnidx)
2712 GX_LOAD_XF_REGS((0x0400|(pnidx*3)),9);
2713 WriteMtxPS3x3from4x3(mt,(void*)WGPIPE);
2716 void GX_LoadNrmMtxImm3x3(Mtx33 mt,u32 pnidx)
2718 GX_LOAD_XF_REGS((0x0400|(pnidx*3)),9);
2719 WriteMtxPS3x3(mt,(void*)WGPIPE);
2722 void GX_LoadNrmMtxIdx3x3(u16 mtxidx,u32 pnidx)
2724 FIFO_PUTU8(0x28);
2725 FIFO_PUTU32(((_SHIFTL(mtxidx,16,16))|0x8000|(0x0400|(pnidx*3))));
2728 void GX_LoadTexMtxImm(Mtx mt,u32 texidx,u8 type)
2730 u32 addr = 0;
2731 u32 rows = (type==GX_MTX2x4)?2:3;
2733 if(texidx<GX_DTTMTX0) addr = (_SHIFTL(texidx,2,8));
2734 else {
2735 texidx -= GX_DTTMTX0;
2736 addr = 0x0500 + (_SHIFTL(texidx,2,8));
2739 GX_LOAD_XF_REGS(addr,(rows*4));
2740 if(type==GX_MTX2x4)
2741 WriteMtxPS4x2(mt,(void*)WGPIPE);
2742 else
2743 WriteMtxPS4x3(mt,(void*)WGPIPE);
2746 void GX_LoadTexMtxIdx(u16 mtxidx,u32 texidx,u8 type)
2748 u32 addr,size = (type==GX_MTX2x4)?7:11;
2750 if(texidx<GX_DTTMTX0) addr = 0x0000|(_SHIFTL(texidx,2,8));
2751 else addr = 0x0500|(_SHIFTL((texidx-GX_DTTMTX0),2,8));
2753 FIFO_PUTU8(0x30);
2754 FIFO_PUTU32(((_SHIFTL(mtxidx,16,16))|(_SHIFTL(size,12,4))|addr));
2757 void GX_SetCurrentMtx(u32 mtx)
2759 __gx->mtxIdxLo = (__gx->mtxIdxLo&~0x3f)|(mtx&0x3f);
2760 __gx->dirtyState |= 0x04000000;
2763 void GX_SetNumTexGens(u32 nr)
2765 __gx->genMode = (__gx->genMode&~0xf)|(nr&0xf);
2766 __gx->dirtyState |= 0x02000004;
2769 void GX_InvVtxCache()
2771 FIFO_PUTU8(0x48); // vertex cache weg
2774 void GX_SetZMode(u8 enable,u8 func,u8 update_enable)
2776 __gx->peZMode = (__gx->peZMode&~0x1)|(enable&1);
2777 __gx->peZMode = (__gx->peZMode&~0xe)|(_SHIFTL(func,1,3));
2778 __gx->peZMode = (__gx->peZMode&~0x10)|(_SHIFTL(update_enable,4,1));
2779 GX_LOAD_BP_REG(__gx->peZMode);
2782 static void __GetTexTileShift(u32 fmt,u32 *xshift,u32 *yshift)
2784 switch(fmt) {
2785 case GX_TF_I4:
2786 case GX_TF_IA4:
2787 case GX_CTF_R4:
2788 case GX_CTF_RA4:
2789 case GX_CTF_Z4:
2790 *xshift = 3;
2791 *yshift = 3;
2792 break;
2793 case GX_TF_Z8:
2794 case GX_TF_I8:
2795 case GX_TF_IA8:
2796 case GX_CTF_RA8:
2797 case GX_CTF_A8:
2798 case GX_CTF_R8:
2799 case GX_CTF_G8:
2800 case GX_CTF_B8:
2801 case GX_CTF_RG8:
2802 case GX_CTF_GB8:
2803 case GX_CTF_Z8M:
2804 case GX_CTF_Z8L:
2805 *xshift = 3;
2806 *yshift = 2;
2807 break;
2808 case GX_TF_Z16:
2809 case GX_TF_Z24X8:
2810 case GX_CTF_Z16L:
2811 case GX_TF_RGB565:
2812 case GX_TF_RGB5A3:
2813 case GX_TF_RGBA8:
2814 *xshift = 2;
2815 *yshift = 2;
2816 break;
2817 default:
2818 *xshift = 0;
2819 *yshift = 0;
2820 break;
2824 u32 GX_GetTexObjFmt(GXTexObj *obj)
2826 return ((struct __gx_texobj*)obj)->tex_fmt;
2829 u32 GX_GetTexObjMipMap(GXTexObj *obj)
2831 return (((struct __gx_texobj*)obj)->tex_flag&0x01);
2834 u32 GX_GetTexBufferSize(u16 wd,u16 ht,u32 fmt,u8 mipmap,u8 maxlod)
2836 u32 xshift,yshift,xtiles,ytiles,bitsize,size;
2838 switch(fmt) {
2839 case GX_TF_I4:
2840 case GX_TF_IA4:
2841 case GX_TF_CMPR:
2842 case GX_CTF_R4:
2843 case GX_CTF_RA4:
2844 case GX_CTF_Z4:
2845 xshift = 3;
2846 yshift = 3;
2847 break;
2848 case GX_TF_Z8:
2849 case GX_TF_I8:
2850 case GX_CTF_RA8:
2851 case GX_CTF_A8:
2852 case GX_CTF_R8:
2853 case GX_CTF_G8:
2854 case GX_CTF_B8:
2855 case GX_CTF_RG8:
2856 case GX_CTF_GB8:
2857 case GX_CTF_Z8M:
2858 case GX_CTF_Z8L:
2859 xshift = 3;
2860 yshift = 2;
2861 break;
2862 case GX_TF_IA8:
2863 case GX_TF_Z16:
2864 case GX_TF_Z24X8:
2865 case GX_TF_RGB565:
2866 case GX_TF_RGB5A3:
2867 case GX_TF_RGBA8:
2868 case GX_CTF_Z16L:
2869 xshift = 2;
2870 yshift = 2;
2871 break;
2872 default:
2873 xshift = 2;
2874 yshift = 2;
2875 break;
2878 bitsize = 32;
2879 if(fmt==GX_TF_RGBA8 || fmt==GX_TF_Z24X8) bitsize = 64;
2881 size = 0;
2882 if(mipmap) {
2883 u32 cnt = (maxlod&0xff);
2884 while(cnt) {
2885 u32 w = wd&0xffff;
2886 u32 h = ht&0xffff;
2887 xtiles = ((w+(1<<xshift))-1)>>xshift;
2888 ytiles = ((h+(1<<yshift))-1)>>yshift;
2889 if(cnt==0) return size;
2891 size += ((xtiles*ytiles)*bitsize);
2892 if(w==0x0001 && h==0x0001) return size;
2893 if(wd>0x0001) wd = (w>>1);
2894 else wd = 0x0001;
2895 if(ht>0x0001) ht = (h>>1);
2896 else ht = 0x0001;
2898 --cnt;
2900 return size;
2903 wd &= 0xffff;
2904 xtiles = (wd+((1<<xshift)-1))>>xshift;
2906 ht &= 0xffff;
2907 ytiles = (ht+((1<<yshift)-1))>>yshift;
2909 size = ((xtiles*ytiles)*bitsize);
2911 return size;
2914 void GX_InitTexCacheRegion(GXTexRegion *region,u8 is32bmipmap,u32 tmem_even,u8 size_even,u32 tmem_odd,u8 size_odd)
2916 u32 sze = 0;
2917 struct __gx_texregion *ptr = (struct __gx_texregion*)region;
2919 switch(size_even) {
2920 case GX_TEXCACHE_32K:
2921 sze = 3;
2922 break;
2923 case GX_TEXCACHE_128K:
2924 sze = 4;
2925 break;
2926 case GX_TEXCACHE_512K:
2927 sze = 5;
2928 break;
2929 default:
2930 sze = 3;
2931 break;
2933 ptr->tmem_even = 0;
2934 ptr->tmem_even = (ptr->tmem_even&~0x7fff)|(_SHIFTR(tmem_even,5,15));
2935 ptr->tmem_even = (ptr->tmem_even&~0x38000)|(_SHIFTL(sze,15,3));
2936 ptr->tmem_even = (ptr->tmem_even&~0x1C0000)|(_SHIFTL(sze,18,3));
2938 switch(size_odd) {
2939 case GX_TEXCACHE_32K:
2940 sze = 3;
2941 break;
2942 case GX_TEXCACHE_128K:
2943 sze = 4;
2944 break;
2945 case GX_TEXCACHE_512K:
2946 sze = 5;
2947 break;
2948 default:
2949 sze = 3;
2950 break;
2952 ptr->tmem_odd = 0;
2953 ptr->tmem_odd = (ptr->tmem_odd&~0x7fff)|(_SHIFTR(tmem_odd,5,15));
2954 ptr->tmem_odd = (ptr->tmem_odd&~0x38000)|(_SHIFTL(sze,15,3));
2955 ptr->tmem_odd = (ptr->tmem_odd&~0x1C0000)|(_SHIFTL(sze,18,3));
2957 ptr->ismipmap = is32bmipmap;
2958 ptr->iscached = 1;
2961 void GX_InitTexPreloadRegion(GXTexRegion *region,u32 tmem_even,u32 size_even,u32 tmem_odd,u32 size_odd)
2963 struct __gx_texregion *ptr = (struct __gx_texregion*)region;
2965 ptr->tmem_even = 0;
2966 ptr->tmem_even = (ptr->tmem_even&~0x7FFF)|(_SHIFTR(tmem_even,5,15));
2967 ptr->tmem_even = (ptr->tmem_even&~0x200000)|0x200000;
2969 ptr->tmem_odd = 0;
2970 ptr->tmem_odd = (ptr->tmem_odd&~0x7FFF)|(_SHIFTR(tmem_odd,5,15));
2972 ptr->size_even = _SHIFTR(size_even,5,16);
2973 ptr->size_odd = _SHIFTR(size_odd,5,16);
2975 ptr->ismipmap = 0;
2976 ptr->iscached = 0;
2979 void GX_InitTlutRegion(GXTlutRegion *region,u32 tmem_addr,u8 tlut_sz)
2981 struct __gx_tlutregion *ptr = (struct __gx_tlutregion*)region;
2983 tmem_addr -= 0x80000;
2985 ptr->tmem_addr_conf = 0;
2986 ptr->tmem_addr_conf = (ptr->tmem_addr_conf&~0x3ff)|(_SHIFTR(tmem_addr,9,10));
2987 ptr->tmem_addr_conf = (ptr->tmem_addr_conf&~0x1FFC00)|(_SHIFTL(tlut_sz,10,10));
2988 ptr->tmem_addr_conf = (ptr->tmem_addr_conf&~0xff000000)|(_SHIFTL(0x65,24,8));
2991 void GX_InitTexObj(GXTexObj *obj,void *img_ptr,u16 wd,u16 ht,u8 fmt,u8 wrap_s,u8 wrap_t,u8 mipmap)
2993 u32 nwd,nht;
2994 u32 xshift,yshift;
2995 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
2997 if(!obj) return;
2999 memset(obj,0,sizeof(GXTexObj));
3001 ptr->tex_filt = (ptr->tex_filt&~0x03)|(wrap_s&3);
3002 ptr->tex_filt = (ptr->tex_filt&~0x0c)|(_SHIFTL(wrap_t,2,2));
3003 ptr->tex_filt = (ptr->tex_filt&~0x10)|0x10;
3005 if(mipmap) {
3006 ptr->tex_flag |= 0x01;
3007 if(fmt==GX_TF_CI4 || fmt==GX_TF_CI8 || fmt==GX_TF_CI14)
3008 ptr->tex_filt = (ptr->tex_filt&~0xe0)|0x00a0;
3009 else
3010 ptr->tex_filt = (ptr->tex_filt&~0xe0)|0x00c0;
3011 } else
3012 ptr->tex_filt= (ptr->tex_filt&~0xE0)|0x0080;
3014 ptr->tex_fmt = fmt;
3015 ptr->tex_size = (ptr->tex_size&~0x3ff)|((wd-1)&0x3ff);
3016 ptr->tex_size = (ptr->tex_size&~0xFFC00)|(_SHIFTL((ht-1),10,10));
3017 ptr->tex_size = (ptr->tex_size&~0xF00000)|(_SHIFTL(fmt,20,4));
3018 ptr->tex_maddr = (ptr->tex_maddr&~0x01ffffff)|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(img_ptr),5,24));
3020 switch(fmt) {
3021 case GX_TF_I4:
3022 case GX_TF_CI4:
3023 case GX_TF_IA4:
3024 xshift = 3;
3025 yshift = 3;
3026 ptr->tex_tile_type = 1;
3027 break;
3028 case GX_TF_I8:
3029 case GX_TF_CI8:
3030 xshift = 3;
3031 yshift = 2;
3032 ptr->tex_tile_type = 2;
3033 break;
3034 case GX_TF_IA8:
3035 case GX_TF_RGB565:
3036 case GX_TF_RGB5A3:
3037 case GX_TF_RGBA8:
3038 xshift = 2;
3039 yshift = 2;
3040 ptr->tex_tile_type = 2;
3041 break;
3042 case GX_TF_CI14:
3043 xshift = 2;
3044 yshift = 2;
3045 ptr->tex_tile_type = 3;
3046 break;
3047 case GX_TF_CMPR:
3048 xshift = 3;
3049 yshift = 3;
3050 ptr->tex_tile_type = 0;
3051 break;
3052 default:
3053 xshift = 2;
3054 yshift = 2;
3055 ptr->tex_tile_type = 2;
3056 break;
3059 nwd = ((wd+(1<<xshift))-1)>>xshift;
3060 nht = ((ht+(1<<yshift))-1)>>yshift;
3061 ptr->tex_tile_cnt = (nwd*nht)&0x7fff;
3063 ptr->tex_flag |= 0x0002;
3066 void GX_InitTexObjCI(GXTexObj *obj,void *img_ptr,u16 wd,u16 ht,u8 fmt,u8 wrap_s,u8 wrap_t,u8 mipmap,u32 tlut_name)
3068 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3070 GX_InitTexObj(obj,img_ptr,wd,ht,fmt,wrap_s,wrap_t,mipmap);
3071 ptr->tex_flag &= ~0x02;
3072 ptr->tex_tlut = tlut_name;
3075 void GX_InitTexObjLOD(GXTexObj *obj,u8 minfilt,u8 magfilt,f32 minlod,f32 maxlod,f32 lodbias,u8 biasclamp,u8 edgelod,u8 maxaniso)
3077 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3078 static u8 GX2HWFiltConv[] = {0x00,0x04,0x01,0x05,0x02,0x06,0x00,0x00};
3079 //static u8 HW2GXFiltConv[] = {0x00,0x02,0x04,0x00,0x01,0x03,0x05,0x00};
3081 if(lodbias<-4.0f) lodbias = -4.0f;
3082 else if(lodbias==4.0f) lodbias = 3.99f;
3084 ptr->tex_filt = (ptr->tex_filt&~0x1fe00)|(_SHIFTL(((u32)(32.0f*lodbias)),9,8));
3085 ptr->tex_filt = (ptr->tex_filt&~0x10)|(_SHIFTL((magfilt==GX_LINEAR?1:0),4,1));
3086 ptr->tex_filt = (ptr->tex_filt&~0xe0)|(_SHIFTL(GX2HWFiltConv[minfilt],5,3));
3087 ptr->tex_filt = (ptr->tex_filt&~0x100)|(_SHIFTL(!(edgelod&0xff),8,1));
3088 ptr->tex_filt = (ptr->tex_filt&~0x180000)|(_SHIFTL(maxaniso,19,2));
3089 ptr->tex_filt = (ptr->tex_filt&~0x200000)|(_SHIFTL(biasclamp,21,1));
3091 if(minlod<0.0f) minlod = 0.0f;
3092 else if(minlod>10.0f) minlod = 10.0f;
3094 if(maxlod<0.0f) maxlod = 0.0f;
3095 else if(maxlod>10.0f) maxlod = 10.0f;
3097 ptr->tex_lod = (ptr->tex_lod&~0xff)|(((u32)(16.0f*minlod))&0xff);
3098 ptr->tex_lod = (ptr->tex_lod&~0xff00)|(_SHIFTL(((u32)(16.0f*maxlod)),8,8));
3101 void GX_InitTexObjData(GXTexObj *obj,void *img_ptr)
3103 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3104 ptr->tex_maddr = (ptr->tex_maddr&~0x01ffffff)|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(img_ptr),5,24));
3107 void GX_InitTexObjTlut(GXTexObj *obj,u32 tlut_name)
3109 ((struct __gx_texobj*)obj)->tex_tlut = tlut_name;
3112 void GX_InitTexObjWrapMode(GXTexObj *obj,u8 wrap_s,u8 wrap_t)
3114 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3116 ptr->tex_filt = (ptr->tex_filt&~0x03)|(wrap_s&3);
3117 ptr->tex_filt = (ptr->tex_filt&~0x0c)|(_SHIFTL(wrap_t,2,2));
3120 void GX_InitTexObjFilterMode(GXTexObj *obj,u8 minfilt,u8 magfilt)
3122 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3123 static u8 GX2HWFiltConv[] = {0x00,0x04,0x01,0x05,0x02,0x06,0x00,0x00};
3125 ptr->tex_filt = (ptr->tex_filt&~0x10)|(_SHIFTL((magfilt==GX_LINEAR?1:0),4,1));
3126 ptr->tex_filt = (ptr->tex_filt&~0xe0)|(_SHIFTL(GX2HWFiltConv[minfilt],5,3));
3129 void GX_InitTexObjMinLOD(GXTexObj *obj,f32 minlod)
3131 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3133 if(minlod<0.0f) minlod = 0.0f;
3134 else if(minlod>10.0f) minlod = 10.0f;
3136 ptr->tex_lod = (ptr->tex_lod&~0xff)|(((u32)(16.0f*minlod))&0xff);
3139 void GX_InitTexObjMaxLOD(GXTexObj *obj,f32 maxlod)
3141 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3143 if(maxlod<0.0f) maxlod = 0.0f;
3144 else if(maxlod>10.0f) maxlod = 10.0f;
3146 ptr->tex_lod = (ptr->tex_lod&~0xff00)|(_SHIFTL(((u32)(16.0f*maxlod)),8,8));
3149 void GX_InitTexObjLODBias(GXTexObj *obj,f32 lodbias)
3151 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3153 if(lodbias<-4.0f) lodbias = -4.0f;
3154 else if(lodbias==4.0f) lodbias = 3.99f;
3156 ptr->tex_filt = (ptr->tex_filt&~0x1fe00)|(_SHIFTL(((u32)(32.0f*lodbias)),9,8));
3159 void GX_InitTexObjBiasClamp(GXTexObj *obj,u8 biasclamp)
3161 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3162 ptr->tex_filt = (ptr->tex_filt&~0x200000)|(_SHIFTL(biasclamp,21,1));
3165 void GX_InitTexObjEdgeLOD(GXTexObj *obj,u8 edgelod)
3167 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3168 ptr->tex_filt = (ptr->tex_filt&~0x100)|(_SHIFTL(!(edgelod&0xff),8,1));
3171 void GX_InitTexObjMaxAniso(GXTexObj *obj,u8 maxaniso)
3173 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3174 ptr->tex_filt = (ptr->tex_filt&~0x180000)|(_SHIFTL(maxaniso,19,2));
3177 void GX_InitTlutObj(GXTlutObj *obj,void *lut,u8 fmt,u16 entries)
3179 struct __gx_tlutobj *ptr = (struct __gx_tlutobj*)obj;
3181 memset(obj,0,sizeof(GXTlutObj));
3183 ptr->tlut_fmt = _SHIFTL(fmt,10,2);
3184 ptr->tlut_maddr = (ptr->tlut_maddr&~0x00ffffff)|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(lut),5,24));
3185 ptr->tlut_maddr = (ptr->tlut_maddr&~0xff000000)|(_SHIFTL(0x64,24,8));
3186 ptr->tlut_nentries = entries;
3189 void GX_LoadTexObj(GXTexObj *obj,u8 mapid)
3191 GXTexRegion *region = NULL;
3193 if(regionCB)
3194 region = regionCB(obj,mapid);
3196 GX_LoadTexObjPreloaded(obj,region,mapid);
3199 void GX_LoadTexObjPreloaded(GXTexObj *obj,GXTexRegion *region,u8 mapid)
3201 u8 type;
3202 struct __gx_tlutregion *tlut = NULL;
3203 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3204 struct __gx_texregion *reg = (struct __gx_texregion*)region;
3206 ptr->tex_filt = (ptr->tex_filt&~0xff000000)|(_SHIFTL(_gxtexmode0ids[mapid],24,8));
3207 ptr->tex_lod = (ptr->tex_lod&~0xff000000)|(_SHIFTL(_gxtexmode1ids[mapid],24,8));
3208 ptr->tex_size = (ptr->tex_size&~0xff000000)|(_SHIFTL(_gxteximg0ids[mapid],24,8));
3209 ptr->tex_maddr = (ptr->tex_maddr&~0xff000000)|(_SHIFTL(_gxteximg3ids[mapid],24,8));
3211 reg->tmem_even = (reg->tmem_even&~0xff000000)|(_SHIFTL(_gxteximg1ids[mapid],24,8));
3212 reg->tmem_odd = (reg->tmem_odd&~0xff000000)|(_SHIFTL(_gxteximg2ids[mapid],24,8));
3214 GX_LOAD_BP_REG(ptr->tex_filt);
3215 GX_LOAD_BP_REG(ptr->tex_lod);
3216 GX_LOAD_BP_REG(ptr->tex_size);
3218 GX_LOAD_BP_REG(reg->tmem_even);
3219 GX_LOAD_BP_REG(reg->tmem_odd);
3221 GX_LOAD_BP_REG(ptr->tex_maddr);
3223 type = ptr->tex_flag;
3224 if(!(type&0x02)) {
3225 if(tlut_regionCB)
3226 tlut = (struct __gx_tlutregion*)tlut_regionCB(ptr->tex_tlut);
3227 tlut->tmem_addr_base = (tlut->tmem_addr_base&~0xff000000)|(_SHIFTL(_gxtextlutids[mapid],24,8));
3228 GX_LOAD_BP_REG(tlut->tmem_addr_base);
3231 __gx->texMapSize[mapid] = ptr->tex_size;
3232 __gx->texMapWrap[mapid] = ptr->tex_filt;
3234 __gx->dirtyState |= 0x0001;
3237 void GX_PreloadEntireTexture(GXTexObj *obj,GXTexRegion *region)
3239 u32 i,fmt;
3240 s32 wd,ht;
3241 u16 cnt = 0;
3242 u32 regA = 0;
3243 u32 regB = 0;
3244 u32 regC = 0;
3245 u32 regD = 0;
3246 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3247 struct __gx_texregion *reg = (struct __gx_texregion*)region;
3249 regA = (regA&~0xff000000)|(_SHIFTL(0x60,24,8));
3250 regA = (regA&~0x00ffffff)|(ptr->tex_maddr&~0xff000000);
3252 regB = (regB&~0xff000000)|(_SHIFTL(0x61,24,8));
3253 regB = (regB&~0x00007fff)|(reg->tmem_even&0x00007fff);
3255 regC = (regC&~0xff000000)|(_SHIFTL(0x62,24,8));
3256 regC = (regC&~0x00007fff)|(reg->tmem_odd&0x00007fff);
3258 regD = (regD&~0xff000000)|(_SHIFTL(0x63,24,8));
3259 regB = (regD&~0x00007fff)|(ptr->tex_tile_cnt&0x00007fff);
3261 fmt = _SHIFTR(ptr->tex_size,20,4);
3263 __GX_FlushTextureState();
3264 GX_LOAD_BP_REG(regA);
3265 GX_LOAD_BP_REG(regB);
3266 GX_LOAD_BP_REG(regC);
3267 GX_LOAD_BP_REG(regD);
3269 if(ptr->tex_flag&0x01) {
3270 wd = (ptr->tex_size&0x3ff)+1;
3271 ht = _SHIFTR(ptr->tex_size,10,10)+1;
3272 if(wd>ht)
3273 cnt = (31 - (cntlzw(wd)));
3274 else
3275 cnt = (31 - (cntlzw(ht)));
3278 if(cnt>0) {
3279 u32 tmem_even,tmem_odd,maddr;
3280 u32 tile_cnt = ptr->tex_tile_cnt;
3282 tmem_even = (reg->tmem_even&0xffff);
3283 tmem_odd = (reg->tmem_odd&0xffff);
3284 maddr = (ptr->tex_maddr&~0xff000000);
3286 i = 0;
3287 while(cnt) {
3288 u32 w,h;
3289 u32 te,to;
3290 u32 xshift,yshift;
3292 if(fmt==GX_TF_RGBA8) {
3293 tmem_even += tile_cnt;
3294 tmem_odd += tile_cnt;
3295 maddr += (tile_cnt<<1);
3296 } else {
3297 maddr += tile_cnt;
3298 if(i&1) tmem_odd += tile_cnt;
3299 else tmem_even += tile_cnt;
3302 te = tmem_even;
3303 to = tmem_odd;
3304 if(i&1) {
3305 te = tmem_odd;
3306 to = tmem_even;
3309 w = wd>>(i+1);
3310 h = wd>>(i+1);
3311 switch(ptr->tex_fmt) {
3312 case GX_TF_I4:
3313 case GX_TF_IA4:
3314 case GX_TF_CI4:
3315 case GX_TF_CMPR:
3316 xshift = 3;
3317 yshift = 3;
3318 break;
3319 case GX_TF_I8:
3320 case GX_TF_CI8:
3321 xshift = 3;
3322 yshift = 2;
3323 break;
3324 case GX_TF_IA8:
3325 case GX_TF_RGB5A3:
3326 case GX_TF_RGB565:
3327 case GX_TF_CI14:
3328 xshift = 2;
3329 yshift = 2;
3330 break;
3331 default:
3332 xshift = 0;
3333 yshift = 0;
3334 break;
3337 if(!w) w = 1;
3338 if(!h) h = 1;
3340 regA = ((regA&~0x00ffffff)|(maddr&0x00ffffff));
3341 GX_LOAD_BP_REG(regA);
3343 regB = ((regB&~0x00007fff)|(te&0x00007fff));
3344 GX_LOAD_BP_REG(regB);
3346 regC = ((regC&~0x00007fff)|(to&0x00007fff));
3347 GX_LOAD_BP_REG(regC);
3349 tile_cnt = (((w+(1<<xshift))-1)>>xshift)*(((h+(1<<yshift))-1)>>yshift);
3350 regD = ((regD&~0x00007fff)|(tile_cnt&0x00007fff));
3351 GX_LOAD_BP_REG(regD);
3353 ++i;
3354 --cnt;
3357 __GX_FlushTextureState();
3360 void GX_InvalidateTexAll()
3362 __GX_FlushTextureState();
3363 GX_LOAD_BP_REG(0x66001000);
3364 GX_LOAD_BP_REG(0x66001100);
3365 __GX_FlushTextureState();
3368 void GX_InvalidateTexRegion(GXTexRegion *region)
3370 u8 ismipmap;
3371 s32 cw_e,ch_e,cw_o,ch_o;
3372 u32 size,tmp,regvalA = 0,regvalB = 0;
3373 struct __gx_texregion *ptr = (struct __gx_texregion*)region;
3375 cw_e = (_SHIFTR(ptr->tmem_even,15,3))-1;
3376 ch_e = (_SHIFTR(ptr->tmem_even,18,3))-1;
3378 cw_o = (_SHIFTR(ptr->tmem_odd,15,3))-1;
3379 ch_o = (_SHIFTR(ptr->tmem_odd,18,3))-1;
3381 if(cw_e<0) cw_e = 0;
3382 if(ch_e<0) ch_e = 0;
3383 if(cw_o<0) cw_o = 0;
3384 if(ch_o<0) ch_o = 0;
3386 ismipmap = ptr->ismipmap;
3388 tmp = size = cw_e+ch_e;
3389 if(ismipmap) size = tmp+(cw_o+ch_o-2);
3390 regvalA = _SHIFTR((ptr->tmem_even&0x7fff),6,24)|(_SHIFTL(size,9,24))|(_SHIFTL(0x66,24,8));
3392 if(cw_o!=0) {
3393 size = cw_o+ch_o;
3394 if(ismipmap) size += (tmp-2);
3395 regvalB = _SHIFTR((ptr->tmem_odd&0x7fff),6,24)|(_SHIFTL(size,9,24))|(_SHIFTL(0x66,24,8));
3397 __GX_FlushTextureState();
3398 GX_LOAD_BP_REG(regvalA);
3399 if(ismipmap) GX_LOAD_BP_REG(regvalB);
3400 __GX_FlushTextureState();
3403 void GX_LoadTlut(GXTlutObj *obj,u32 tlut_name)
3405 struct __gx_tlutregion *region = NULL;
3406 struct __gx_tlutobj *ptr = (struct __gx_tlutobj*)obj;
3408 if(tlut_regionCB)
3409 region = (struct __gx_tlutregion*)tlut_regionCB(tlut_name);
3411 __GX_FlushTextureState();
3412 GX_LOAD_BP_REG(ptr->tlut_maddr);
3413 GX_LOAD_BP_REG(region->tmem_addr_conf);
3414 __GX_FlushTextureState();
3416 region->tmem_addr_base = (ptr->tlut_fmt&~0x3ff)|(region->tmem_addr_conf&0x3ff);
3417 region->tlut_maddr = ptr->tlut_maddr;
3418 region->tlut_nentries = ptr->tlut_nentries;
3421 void GX_SetTexCoorScaleManually(u8 texcoord,u8 enable,u16 ss,u16 ts)
3423 u32 reg;
3425 __gx->texCoordManually = (__gx->texCoordManually&~(_SHIFTL(1,texcoord,1)))|(_SHIFTL(enable,texcoord,1));
3426 if(!enable) return;
3428 reg = (texcoord&0x7);
3429 __gx->suSsize[reg] = (__gx->suSsize[reg]&~0xffff)|((ss-1)&0xffff);
3430 __gx->suTsize[reg] = (__gx->suTsize[reg]&~0xffff)|((ts-1)&0xffff);
3432 GX_LOAD_BP_REG(__gx->suSsize[reg]);
3433 GX_LOAD_BP_REG(__gx->suTsize[reg]);
3436 void GX_SetTexCoordCylWrap(u8 texcoord,u8 s_enable,u8 t_enable)
3438 u32 reg;
3440 reg = (texcoord&0x7);
3441 __gx->suSsize[reg] = (__gx->suSsize[reg]&~0x20000)|(_SHIFTL(s_enable,17,1));
3442 __gx->suTsize[reg] = (__gx->suTsize[reg]&~0x20000)|(_SHIFTL(t_enable,17,1));
3444 if(!(__gx->texCoordManually&(_SHIFTL(1,texcoord,1)))) return;
3446 GX_LOAD_BP_REG(__gx->suSsize[reg]);
3447 GX_LOAD_BP_REG(__gx->suTsize[reg]);
3450 void GX_SetTexCoordBias(u8 texcoord,u8 s_enable,u8 t_enable)
3452 u32 reg;
3454 reg = (texcoord&0x7);
3455 __gx->suSsize[reg] = (__gx->suSsize[reg]&~0x10000)|(_SHIFTL(s_enable,16,1));
3456 __gx->suTsize[reg] = (__gx->suTsize[reg]&~0x10000)|(_SHIFTL(t_enable,16,1));
3458 if(!(__gx->texCoordManually&(_SHIFTL(1,texcoord,1)))) return;
3460 GX_LOAD_BP_REG(__gx->suSsize[reg]);
3461 GX_LOAD_BP_REG(__gx->suTsize[reg]);
3464 GXTexRegionCallback GX_SetTexRegionCallback(GXTexRegionCallback cb)
3466 u32 level;
3467 GXTexRegionCallback ret;
3469 _CPU_ISR_Disable(level);
3470 ret = regionCB;
3471 regionCB = cb;
3472 _CPU_ISR_Restore(level);
3474 return ret;
3477 GXTlutRegionCallback GX_SetTlutRegionCallback(GXTlutRegionCallback cb)
3479 u32 level;
3480 GXTlutRegionCallback ret;
3482 _CPU_ISR_Disable(level);
3483 ret = tlut_regionCB;
3484 tlut_regionCB = cb;
3485 _CPU_ISR_Restore(level);
3487 return ret;
3490 void GX_SetBlendMode(u8 type,u8 src_fact,u8 dst_fact,u8 op)
3492 __gx->peCMode0 = (__gx->peCMode0&~0x1);
3493 if(type==GX_BM_BLEND || type==GX_BM_SUBSTRACT) __gx->peCMode0 |= 0x1;
3495 __gx->peCMode0 = (__gx->peCMode0&~0x800);
3496 if(type==GX_BM_SUBSTRACT) __gx->peCMode0 |= 0x800;
3498 __gx->peCMode0 = (__gx->peCMode0&~0x2);
3499 if(type==GX_BM_LOGIC) __gx->peCMode0 |= 0x2;
3501 __gx->peCMode0 = (__gx->peCMode0&~0xF000)|(_SHIFTL(op,12,4));
3502 __gx->peCMode0 = (__gx->peCMode0&~0xE0)|(_SHIFTL(dst_fact,5,3));
3503 __gx->peCMode0 = (__gx->peCMode0&~0x700)|(_SHIFTL(src_fact,8,3));
3505 GX_LOAD_BP_REG(__gx->peCMode0);
3508 void GX_ClearVtxDesc()
3510 __gx->vcdNrms = 0;
3511 __gx->vcdClear = ((__gx->vcdClear&~0x0600)|0x0200);
3512 __gx->vcdLo = __gx->vcdHi = 0;
3513 __gx->dirtyState |= 0x0008;
3516 void GX_SetLineWidth(u8 width,u8 fmt)
3518 __gx->lpWidth = (__gx->lpWidth&~0xff)|(width&0xff);
3519 __gx->lpWidth = (__gx->lpWidth&~0x70000)|(_SHIFTL(fmt,16,3));
3520 GX_LOAD_BP_REG(__gx->lpWidth);
3523 void GX_SetPointSize(u8 width,u8 fmt)
3525 __gx->lpWidth = (__gx->lpWidth&~0xFF00)|(_SHIFTL(width,8,8));
3526 __gx->lpWidth = (__gx->lpWidth&~0x380000)|(_SHIFTL(fmt,19,3));
3527 GX_LOAD_BP_REG(__gx->lpWidth);
3530 void GX_SetTevColor(u8 tev_regid,GXColor color)
3532 u32 reg;
3534 reg = (_SHIFTL((0xe0+(tev_regid<<1)),24,8)|(_SHIFTL(color.a,12,8))|(color.r&0xff));
3535 GX_LOAD_BP_REG(reg);
3537 reg = (_SHIFTL((0xe1+(tev_regid<<1)),24,8)|(_SHIFTL(color.g,12,8))|(color.b&0xff));
3538 GX_LOAD_BP_REG(reg);
3540 //this two calls should obviously flush the Write Gather Pipe.
3541 GX_LOAD_BP_REG(reg);
3542 GX_LOAD_BP_REG(reg);
3545 void GX_SetTevColorS10(u8 tev_regid,GXColorS10 color)
3547 u32 reg;
3549 reg = (_SHIFTL((0xe0+(tev_regid<<1)),24,8)|(_SHIFTL(color.a,12,11))|(color.r&0x7ff));
3550 GX_LOAD_BP_REG(reg);
3552 reg = (_SHIFTL((0xe1+(tev_regid<<1)),24,8)|(_SHIFTL(color.g,12,11))|(color.b&0x7ff));
3553 GX_LOAD_BP_REG(reg);
3555 //this two calls should obviously flush the Write Gather Pipe.
3556 GX_LOAD_BP_REG(reg);
3557 GX_LOAD_BP_REG(reg);
3560 void GX_SetTevKColor(u8 tev_kregid,GXColor color)
3562 u32 reg;
3564 reg = (_SHIFTL((0xe0+(tev_kregid<<1)),24,8)|(_SHIFTL(1,23,1))|(_SHIFTL(color.a,12,8))|(color.r&0xff));
3565 GX_LOAD_BP_REG(reg);
3567 reg = (_SHIFTL((0xe1+(tev_kregid<<1)),24,8)|(_SHIFTL(1,23,1))|(_SHIFTL(color.g,12,8))|(color.b&0xff));
3568 GX_LOAD_BP_REG(reg);
3570 //this two calls should obviously flush the Write Gather Pipe.
3571 GX_LOAD_BP_REG(reg);
3572 GX_LOAD_BP_REG(reg);
3575 void GX_SetTevKColorS10(u8 tev_kregid,GXColorS10 color)
3577 u32 reg;
3579 reg = (_SHIFTL((0xe0+(tev_kregid<<1)),24,8)|(_SHIFTL(1,23,1))|(_SHIFTL(color.a,12,11))|(color.r&0x7ff));
3580 GX_LOAD_BP_REG(reg);
3582 reg = (_SHIFTL((0xe1+(tev_kregid<<1)),24,8)|(_SHIFTL(1,23,1))|(_SHIFTL(color.g,12,11))|(color.b&0x7ff));
3583 GX_LOAD_BP_REG(reg);
3585 //this two calls should obviously flush the Write Gather Pipe.
3586 GX_LOAD_BP_REG(reg);
3587 GX_LOAD_BP_REG(reg);
3590 void GX_SetTevOp(u8 tevstage,u8 mode)
3592 u8 defcolor = GX_CC_RASC;
3593 u8 defalpha = GX_CA_RASA;
3595 if(tevstage!=GX_TEVSTAGE0) {
3596 defcolor = GX_CC_CPREV;
3597 defalpha = GX_CA_APREV;
3600 switch(mode) {
3601 case GX_MODULATE:
3602 GX_SetTevColorIn(tevstage,GX_CC_ZERO,GX_CC_TEXC,defcolor,GX_CC_ZERO);
3603 GX_SetTevAlphaIn(tevstage,GX_CA_ZERO,GX_CA_TEXA,defalpha,GX_CA_ZERO);
3604 break;
3605 case GX_DECAL:
3606 GX_SetTevColorIn(tevstage,defcolor,GX_CC_TEXC,GX_CC_TEXA,GX_CC_ZERO);
3607 GX_SetTevAlphaIn(tevstage,GX_CA_ZERO,GX_CA_ZERO,GX_CA_ZERO,defalpha);
3608 break;
3609 case GX_BLEND:
3610 GX_SetTevColorIn(tevstage,defcolor,GX_CC_ONE,GX_CC_TEXC,GX_CC_ZERO);
3611 GX_SetTevAlphaIn(tevstage,GX_CA_ZERO,GX_CA_TEXA,defalpha,GX_CA_RASA);
3612 break;
3613 case GX_REPLACE:
3614 GX_SetTevColorIn(tevstage,GX_CC_ZERO,GX_CC_ZERO,GX_CC_ZERO,GX_CC_TEXC);
3615 GX_SetTevAlphaIn(tevstage,GX_CA_ZERO,GX_CA_ZERO,GX_CA_ZERO,GX_CA_TEXA);
3616 break;
3617 case GX_PASSCLR:
3618 GX_SetTevColorIn(tevstage,GX_CC_ZERO,GX_CC_ZERO,GX_CC_ZERO,defcolor);
3619 GX_SetTevAlphaIn(tevstage,GX_CC_A2,GX_CC_A2,GX_CC_A2,defalpha);
3620 break;
3622 GX_SetTevColorOp(tevstage,GX_TEV_ADD,GX_TB_ZERO,GX_CS_SCALE_1,GX_TRUE,GX_TEVPREV);
3623 GX_SetTevAlphaOp(tevstage,GX_TEV_ADD,GX_TB_ZERO,GX_CS_SCALE_1,GX_TRUE,GX_TEVPREV);
3626 void GX_SetTevColorIn(u8 tevstage,u8 a,u8 b,u8 c,u8 d)
3628 u32 reg = (tevstage&0xf);
3629 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0xF000)|(_SHIFTL(a,12,4));
3630 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0xF00)|(_SHIFTL(b,8,4));
3631 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0xF0)|(_SHIFTL(c,4,4));
3632 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0xf)|(d&0xf);
3634 GX_LOAD_BP_REG(__gx->tevColorEnv[reg]);
3637 void GX_SetTevAlphaIn(u8 tevstage,u8 a,u8 b,u8 c,u8 d)
3639 u32 reg = (tevstage&0xf);
3640 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0xE000)|(_SHIFTL(a,13,3));
3641 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x1C00)|(_SHIFTL(b,10,3));
3642 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x380)|(_SHIFTL(c,7,3));
3643 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x70)|(_SHIFTL(d,4,3));
3645 GX_LOAD_BP_REG(__gx->tevAlphaEnv[reg]);
3648 void GX_SetTevColorOp(u8 tevstage,u8 tevop,u8 tevbias,u8 tevscale,u8 clamp,u8 tevregid)
3650 /* set tev op add/sub*/
3651 u32 reg = (tevstage&0xf);
3652 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x40000)|(_SHIFTL(tevop,18,1));
3653 if(tevop<=GX_TEV_SUB) {
3654 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x300000)|(_SHIFTL(tevscale,20,2));
3655 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x30000)|(_SHIFTL(tevbias,16,2));
3656 } else {
3657 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x300000)|((_SHIFTL(tevop,19,4))&0x300000);
3658 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x30000)|0x30000;
3660 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x80000)|(_SHIFTL(clamp,19,1));
3661 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0xC00000)|(_SHIFTL(tevregid,22,2));
3663 GX_LOAD_BP_REG(__gx->tevColorEnv[reg]);
3666 void GX_SetTevAlphaOp(u8 tevstage,u8 tevop,u8 tevbias,u8 tevscale,u8 clamp,u8 tevregid)
3668 /* set tev op add/sub*/
3669 u32 reg = (tevstage&0xf);
3670 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x40000)|(_SHIFTL(tevop,18,1));
3671 if(tevop<=GX_TEV_SUB) {
3672 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x300000)|(_SHIFTL(tevscale,20,2));
3673 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x30000)|(_SHIFTL(tevbias,16,2));
3674 } else {
3675 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x300000)|((_SHIFTL(tevop,19,4))&0x300000);
3676 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x30000)|0x30000;
3678 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x80000)|(_SHIFTL(clamp,19,1));
3679 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0xC00000)|(_SHIFTL(tevregid,22,2));
3681 GX_LOAD_BP_REG(__gx->tevAlphaEnv[reg]);
3684 void GX_SetCullMode(u8 mode)
3686 static u8 cm2hw[] = { 0, 2, 1, 3 };
3688 __gx->genMode = (__gx->genMode&~0xC000)|(_SHIFTL(cm2hw[mode],14,2));
3689 __gx->dirtyState |= 0x0004;
3692 void GX_SetCoPlanar(u8 enable)
3694 __gx->genMode = (__gx->genMode&~0x80000)|(_SHIFTL(enable,19,1));
3695 GX_LOAD_BP_REG(0xFE080000);
3696 GX_LOAD_BP_REG(__gx->genMode);
3699 void GX_EnableTexOffsets(u8 coord,u8 line_enable,u8 point_enable)
3701 u32 reg = (coord&0x7);
3702 __gx->suSsize[reg] = (__gx->suSsize[reg]&~0x40000)|(_SHIFTL(line_enable,18,1));
3703 __gx->suSsize[reg] = (__gx->suSsize[reg]&~0x80000)|(_SHIFTL(point_enable,19,1));
3704 GX_LOAD_BP_REG(__gx->suSsize[reg]);
3707 void GX_SetClipMode(u8 mode)
3709 GX_LOAD_XF_REG(0x1005,(mode&1));
3712 void GX_SetScissor(u32 xOrigin,u32 yOrigin,u32 wd,u32 ht)
3714 u32 xo = xOrigin+0x156;
3715 u32 yo = yOrigin+0x156;
3716 u32 nwd = xo+(wd-1);
3717 u32 nht = yo+(ht-1);
3719 __gx->sciTLcorner = (__gx->sciTLcorner&~0x7ff)|(yo&0x7ff);
3720 __gx->sciTLcorner = (__gx->sciTLcorner&~0x7FF000)|(_SHIFTL(xo,12,11));
3722 __gx->sciBRcorner = (__gx->sciBRcorner&~0x7ff)|(nht&0xfff);
3723 __gx->sciBRcorner = (__gx->sciBRcorner&~0x7FF000)|(_SHIFTL(nwd,12,11));
3725 GX_LOAD_BP_REG(__gx->sciTLcorner);
3726 GX_LOAD_BP_REG(__gx->sciBRcorner);
3729 void GX_SetScissorBoxOffset(s32 xoffset,s32 yoffset)
3731 s32 xoff = _SHIFTR((xoffset+0x156),1,24);
3732 s32 yoff = _SHIFTR((yoffset+0x156),1,24);
3734 GX_LOAD_BP_REG((0x59000000|(_SHIFTL(yoff,10,10))|(xoff&0x3ff)));
3737 void GX_SetNumChans(u8 num)
3739 __gx->genMode = (__gx->genMode&~0x70)|(_SHIFTL(num,4,3));
3740 __gx->dirtyState |= 0x01000004;
3743 void GX_SetTevOrder(u8 tevstage,u8 texcoord,u32 texmap,u8 color)
3745 u8 colid;
3746 u32 texm,texc,tmp;
3747 u32 reg = 3+(_SHIFTR(tevstage,1,3));
3749 __gx->tevTexMap[(tevstage&0xf)] = texmap;
3751 texm = (texmap&~0x100);
3752 if(texm>=GX_MAX_TEXMAP) texm = 0;
3753 if(texcoord>=GX_MAXCOORD) {
3754 texc = 0;
3755 __gx->tevTexCoordEnable &= ~(_SHIFTL(1,tevstage,1));
3756 } else {
3757 texc = texcoord;
3758 __gx->tevTexCoordEnable |= (_SHIFTL(1,tevstage,1));
3761 if(tevstage&1) {
3762 __gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x7000)|(_SHIFTL(texm,12,3));
3763 __gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x38000)|(_SHIFTL(texc,15,3));
3765 colid = GX_BUMP;
3766 if(color!=GX_COLORNULL) colid = _gxtevcolid[color];
3767 __gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x380000)|(_SHIFTL(colid,19,3));
3769 tmp = 1;
3770 if(texmap==GX_TEXMAP_NULL || texmap&0x100) tmp = 0;
3771 __gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x40000)|(_SHIFTL(tmp,18,1));
3772 } else {
3773 __gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x7)|(texm&0x7);
3774 __gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x38)|(_SHIFTL(texc,3,3));
3776 colid = GX_BUMP;
3777 if(color!=GX_COLORNULL) colid = _gxtevcolid[color];
3778 __gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x380)|(_SHIFTL(colid,7,3));
3780 tmp = 1;
3781 if(texmap==GX_TEXMAP_NULL || texmap&0x100) tmp = 0;
3782 __gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x40)|(_SHIFTL(tmp,6,1));
3784 GX_LOAD_BP_REG(__gx->tevRasOrder[reg]);
3785 __gx->dirtyState |= 0x0001;
3788 void GX_SetNumTevStages(u8 num)
3790 __gx->genMode = (__gx->genMode&~0x3C00)|(_SHIFTL((num-1),10,4));
3791 __gx->dirtyState |= 0x0004;
3794 void GX_SetAlphaCompare(u8 comp0,u8 ref0,u8 aop,u8 comp1,u8 ref1)
3796 u32 val = 0;
3797 val = (_SHIFTL(aop,22,2))|(_SHIFTL(comp1,19,3))|(_SHIFTL(comp0,16,3))|(_SHIFTL(ref1,8,8))|(ref0&0xff);
3798 GX_LOAD_BP_REG(0xf3000000|val);
3801 void GX_SetTevKColorSel(u8 tevstage,u8 sel)
3803 u32 reg = (_SHIFTR(tevstage,1,3));
3805 if(tevstage&1)
3806 __gx->tevSwapModeTable[reg] = (__gx->tevSwapModeTable[reg]&~0x7C000)|(_SHIFTL(sel,14,5));
3807 else
3808 __gx->tevSwapModeTable[reg] = (__gx->tevSwapModeTable[reg]&~0x1F0)|(_SHIFTL(sel,4,5));
3809 GX_LOAD_BP_REG(__gx->tevSwapModeTable[reg]);
3812 void GX_SetTevKAlphaSel(u8 tevstage,u8 sel)
3814 u32 reg = (_SHIFTR(tevstage,1,3));
3816 if(tevstage&1)
3817 __gx->tevSwapModeTable[reg] = (__gx->tevSwapModeTable[reg]&~0xF80000)|(_SHIFTL(sel,19,5));
3818 else
3819 __gx->tevSwapModeTable[reg] = (__gx->tevSwapModeTable[reg]&~0x3E00)|(_SHIFTL(sel,9,5));
3820 GX_LOAD_BP_REG(__gx->tevSwapModeTable[reg]);
3823 void GX_SetTevSwapMode(u8 tevstage,u8 ras_sel,u8 tex_sel)
3825 u32 reg = (tevstage&0xf);
3826 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x3)|(ras_sel&0x3);
3827 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0xC)|(_SHIFTL(tex_sel,2,2));
3828 GX_LOAD_BP_REG(__gx->tevAlphaEnv[reg]);
3831 void GX_SetTevSwapModeTable(u8 swapid,u8 r,u8 g,u8 b,u8 a)
3833 u32 regA = 0+(_SHIFTL(swapid,1,3));
3834 u32 regB = 1+(_SHIFTL(swapid,1,3));
3836 __gx->tevSwapModeTable[regA] = (__gx->tevSwapModeTable[regA]&~0x3)|(r&0x3);
3837 __gx->tevSwapModeTable[regA] = (__gx->tevSwapModeTable[regA]&~0xC)|(_SHIFTL(g,2,2));
3838 GX_LOAD_BP_REG(__gx->tevSwapModeTable[regA]);
3840 __gx->tevSwapModeTable[regB] = (__gx->tevSwapModeTable[regB]&~0x3)|(b&0x3);
3841 __gx->tevSwapModeTable[regB] = (__gx->tevSwapModeTable[regB]&~0xC)|(_SHIFTL(a,2,2));
3842 GX_LOAD_BP_REG(__gx->tevSwapModeTable[regB]);
3845 void GX_SetTevIndirect(u8 tevstage,u8 indtexid,u8 format,u8 bias,u8 mtxid,u8 wrap_s,u8 wrap_t,u8 addprev,u8 utclod,u8 a)
3847 u32 val = (0x10000000|(_SHIFTL(tevstage,24,4)))|(indtexid&3)|(_SHIFTL(format,2,2))|(_SHIFTL(bias,4,3))|(_SHIFTL(a,7,2))|(_SHIFTL(mtxid,9,4))|(_SHIFTL(wrap_s,13,3))|(_SHIFTL(wrap_t,16,3))|(_SHIFTL(utclod,19,1))|(_SHIFTL(addprev,20,1));
3848 GX_LOAD_BP_REG(val);
3851 void GX_SetTevDirect(u8 tevstage)
3853 GX_SetTevIndirect(tevstage,GX_INDTEXSTAGE0,GX_ITF_8,GX_ITB_NONE,GX_ITM_OFF,GX_ITW_OFF,GX_ITW_OFF,GX_FALSE,GX_FALSE,GX_ITBA_OFF);
3856 void GX_SetNumIndStages(u8 nstages)
3858 __gx->genMode = (__gx->genMode&~0x70000)|(_SHIFTL(nstages,16,3));
3859 __gx->dirtyState |= 0x0006;
3862 void GX_SetIndTexMatrix(u8 indtexmtx,f32 offset_mtx[2][3],s8 scale_exp)
3864 u32 ma,mb;
3865 u32 val,s,idx;
3867 if(indtexmtx>0x00 && indtexmtx<0x04) indtexmtx -= 0x01;
3868 else if(indtexmtx>0x04 && indtexmtx<0x08) indtexmtx -= 0x05;
3869 else if(indtexmtx>0x08 && indtexmtx<0x0C) indtexmtx -= 0x09;
3870 else indtexmtx = 0x00;
3872 s = (scale_exp+17);
3873 idx = ((indtexmtx<<2)-indtexmtx);
3875 ma = (u32)(offset_mtx[0][0]*1024.0F);
3876 mb = (u32)(offset_mtx[1][0]*1024.0F);
3877 val = (_SHIFTL((0x06+idx),24,8)|_SHIFTL(s,22,2)|_SHIFTL(mb,11,11)|_SHIFTL(ma,0,11));
3878 GX_LOAD_BP_REG(val);
3880 ma = (u32)(offset_mtx[0][1]*1024.0F);
3881 mb = (u32)(offset_mtx[1][1]*1024.0F);
3882 val = (_SHIFTL((0x07+idx),24,8)|_SHIFTL((s>>2),22,2)|_SHIFTL(mb,11,11)|_SHIFTL(ma,0,11));
3883 GX_LOAD_BP_REG(val);
3885 ma = (u32)(offset_mtx[0][2]*1024.0F);
3886 mb = (u32)(offset_mtx[1][2]*1024.0F);
3887 val = (_SHIFTL((0x08+idx),24,8)|_SHIFTL((s>>4),22,2)|_SHIFTL(mb,11,11)|_SHIFTL(ma,0,11));
3888 GX_LOAD_BP_REG(val);
3891 void GX_SetTevIndBumpST(u8 tevstage,u8 indstage,u8 mtx_sel)
3893 u8 sel_s,sel_t;
3895 switch(mtx_sel) {
3896 case GX_ITM_0:
3897 sel_s = GX_ITM_S0;
3898 sel_t = GX_ITM_T0;
3899 break;
3900 case GX_ITM_1:
3901 sel_s = GX_ITM_S1;
3902 sel_t = GX_ITM_T1;
3903 break;
3904 case GX_ITM_2:
3905 sel_s = GX_ITM_S2;
3906 sel_t = GX_ITM_T2;
3907 break;
3908 default:
3909 sel_s = GX_ITM_OFF;
3910 sel_t = GX_ITM_OFF;
3911 break;
3914 GX_SetTevIndirect((tevstage+0),indstage,GX_ITF_8,GX_ITB_ST,sel_s,GX_ITW_0,GX_ITW_0,GX_FALSE,GX_FALSE,GX_ITBA_OFF);
3915 GX_SetTevIndirect((tevstage+1),indstage,GX_ITF_8,GX_ITB_ST,sel_t,GX_ITW_0,GX_ITW_0,GX_TRUE,GX_FALSE,GX_ITBA_OFF);
3916 GX_SetTevIndirect((tevstage+2),indstage,GX_ITF_8,GX_ITB_NONE,GX_ITM_OFF,GX_ITW_OFF,GX_ITW_OFF,GX_TRUE,GX_FALSE,GX_ITBA_OFF);
3919 void GX_SetTevIndBumpXYZ(u8 tevstage,u8 indstage,u8 mtx_sel)
3921 GX_SetTevIndirect(tevstage,indstage,GX_ITF_8,GX_ITB_STU,mtx_sel,GX_ITW_OFF,GX_ITW_OFF,GX_FALSE,GX_FALSE,GX_ITBA_OFF);
3924 void GX_SetIndTexCoordScale(u8 indtexid,u8 scale_s,u8 scale_t)
3926 switch(indtexid) {
3927 case GX_INDTEXSTAGE0:
3928 __gx->tevRasOrder[0] = (__gx->tevRasOrder[0]&~0x0f)|(scale_s&0x0f);
3929 __gx->tevRasOrder[0] = (__gx->tevRasOrder[0]&~0xF0)|(_SHIFTL(scale_t,4,4));
3930 GX_LOAD_BP_REG(__gx->tevRasOrder[0]);
3931 break;
3932 case GX_INDTEXSTAGE1:
3933 __gx->tevRasOrder[0] = (__gx->tevRasOrder[0]&~0xF00)|(_SHIFTL(scale_s,8,4));
3934 __gx->tevRasOrder[0] = (__gx->tevRasOrder[0]&~0xF000)|(_SHIFTL(scale_t,12,4));
3935 GX_LOAD_BP_REG(__gx->tevRasOrder[0]);
3936 break;
3937 case GX_INDTEXSTAGE2:
3938 __gx->tevRasOrder[1] = (__gx->tevRasOrder[1]&~0x0f)|(scale_s&0x0f);
3939 __gx->tevRasOrder[1] = (__gx->tevRasOrder[1]&~0xF0)|(_SHIFTL(scale_t,4,4));
3940 GX_LOAD_BP_REG(__gx->tevRasOrder[1]);
3941 break;
3942 case GX_INDTEXSTAGE3:
3943 __gx->tevRasOrder[1] = (__gx->tevRasOrder[1]&~0xF00)|(_SHIFTL(scale_s,8,4));
3944 __gx->tevRasOrder[1] = (__gx->tevRasOrder[1]&~0xF000)|(_SHIFTL(scale_t,12,4));
3945 GX_LOAD_BP_REG(__gx->tevRasOrder[1]);
3946 break;
3950 void GX_SetTevIndTile(u8 tevstage,u8 indtexid,u16 tilesize_x,u16 tilesize_y,u16 tilespacing_x,u16 tilespacing_y,u8 indtexfmt,u8 indtexmtx,u8 bias_sel,u8 alpha_sel)
3952 s32 wrap_s,wrap_t;
3953 f32 offset_mtx[2][3];
3954 f64 fdspace_x,fdspace_y;
3955 u32 fbuf_x[2] = { 0x43300000,tilespacing_x };
3956 u32 fbuf_y[2] = { 0x43300000,tilespacing_y };
3958 wrap_s = GX_ITW_OFF;
3959 if(tilesize_x==0x0010) wrap_s = GX_ITW_16;
3960 else if(tilesize_x==0x0020) wrap_s = GX_ITW_32;
3961 else if(tilesize_x==0x0040) wrap_s = GX_ITW_64;
3962 else if(tilesize_x==0x0080) wrap_s = GX_ITW_128;
3963 else if(tilesize_x==0x0100) wrap_s = GX_ITW_256;
3965 wrap_t = GX_ITW_OFF;
3966 if(tilesize_y==0x0010) wrap_t = GX_ITW_16;
3967 else if(tilesize_y==0x0020) wrap_t = GX_ITW_32;
3968 else if(tilesize_y==0x0040) wrap_t = GX_ITW_64;
3969 else if(tilesize_y==0x0080) wrap_t = GX_ITW_128;
3970 else if(tilesize_y==0x0100) wrap_t = GX_ITW_256;
3972 fdspace_x = *(f64*)((void*)fbuf_x);
3973 fdspace_y = *(f64*)((void*)fbuf_y);
3975 offset_mtx[0][0] = (f32)((fdspace_x - 4503599627370496.0F)*0.00097656250F);
3976 offset_mtx[0][1] = 0.0F;
3977 offset_mtx[0][2] = 0.0F;
3978 offset_mtx[1][0] = 0.0F;
3979 offset_mtx[1][1] = (f32)((fdspace_y - 4503599627370496.0F)*0.00097656250F);
3980 offset_mtx[1][2] = 0.0F;
3982 GX_SetIndTexMatrix(indtexmtx,offset_mtx,10);
3983 GX_SetTevIndirect(tevstage,indtexid,indtexfmt,bias_sel,indtexmtx,wrap_s,wrap_t,GX_FALSE,GX_TRUE,alpha_sel);
3986 void GX_SetFog(u8 type,f32 startz,f32 endz,f32 nearz,f32 farz,GXColor col)
3988 f32 A, B, B_mant, C, A_f;
3989 u32 b_expn, b_m, a_hex, c_hex,proj = 0;
3992 proj = (u32)((type >> 3) & 0x01);
3994 // Calculate constants a, b, and c (TEV HW requirements).
3995 if(proj) { // Orthographic Fog Type
3996 if((farz==nearz) || (endz==startz)) {
3997 // take care of the odd-ball case.
3998 A_f = 0.0f;
3999 C = 0.0f;
4000 } else {
4001 A = 1.0f/(endz-startz);
4002 A_f = (farz-nearz) * A;
4003 C = (startz-nearz) * A;
4006 b_expn = 0;
4007 b_m = 0;
4008 } else { // Perspective Fog Type
4009 // Calculate constants a, b, and c (TEV HW requirements).
4010 if((farz==nearz) || (endz==startz)) {
4011 // take care of the odd-ball case.
4012 A = 0.0f;
4013 B = 0.5f;
4014 C = 0.0f;
4015 } else {
4016 A = (farz*nearz)/((farz-nearz)*(endz-startz));
4017 B = farz/(farz-nearz);
4018 C = startz/(endz-startz);
4021 B_mant = B;
4022 b_expn = 1;
4023 while(B_mant>1.0) {
4024 B_mant /= 2;
4025 b_expn++;
4028 while((B_mant>0) && (B_mant<0.5)) {
4029 B_mant *= 2;
4030 b_expn--;
4033 A_f = A/(1<<(b_expn));
4034 b_m = (u32)(B_mant * 8388638);
4036 a_hex = (*(u32*)((void*)&A_f));
4037 c_hex = (*(u32*)((void*)&C));
4039 GX_LOAD_BP_REG(0xee000000|(a_hex>>12));
4040 GX_LOAD_BP_REG(0xef000000|b_m);
4041 GX_LOAD_BP_REG(0xf0000000|b_expn);
4042 GX_LOAD_BP_REG(0xf1000000|((type<<21)|(proj<<20)|(c_hex>>12)));
4043 GX_LOAD_BP_REG(0xf2000000|(_SHIFTL(col.r,16,8)|_SHIFTL(col.g,8,8)|(col.b&0xff)));
4046 void GX_SetFogRangeAdj(u8 enable,u16 center,GXFogAdjTbl *table)
4048 GX_LOAD_BP_REG(0xe8000156);
4051 void GX_SetColorUpdate(u8 enable)
4053 __gx->peCMode0 = (__gx->peCMode0&~0x8)|(_SHIFTL(enable,3,1));
4054 GX_LOAD_BP_REG(__gx->peCMode0);
4057 void GX_SetAlphaUpdate(u8 enable)
4059 __gx->peCMode0 = (__gx->peCMode0&~0x10)|(_SHIFTL(enable,4,1));
4060 GX_LOAD_BP_REG(__gx->peCMode0);
4063 void GX_SetZCompLoc(u8 before_tex)
4065 __gx->peCntrl = (__gx->peCntrl&~0x40)|(_SHIFTL(before_tex,6,1));
4066 GX_LOAD_BP_REG(__gx->peCntrl);
4069 void GX_SetPixelFmt(u8 pix_fmt,u8 z_fmt)
4071 u8 ms_en = 0;
4072 u32 realfmt[8] = {0,1,2,3,4,4,4,5};
4074 __gx->peCntrl = (__gx->peCntrl&~0x7)|(realfmt[pix_fmt]&0x7);
4075 __gx->peCntrl = (__gx->peCntrl&~0x38)|(_SHIFTL(z_fmt,3,3));
4076 GX_LOAD_BP_REG(__gx->peCntrl);
4077 __gx->dirtyState |= 0x0004;
4079 if(pix_fmt==GX_PF_RGB565_Z16) ms_en = 1;
4080 __gx->genMode = (__gx->genMode&~0x200)|(_SHIFTL(ms_en,9,1));
4082 if(realfmt[pix_fmt]==GX_PF_Y8) {
4083 pix_fmt -= GX_PF_Y8;
4084 __gx->peCMode1 = (__gx->peCMode1&~0xC00)|(_SHIFTL(pix_fmt,10,2));
4085 GX_LOAD_BP_REG(__gx->peCMode1);
4089 void GX_SetDither(u8 dither)
4091 __gx->peCMode0 = (__gx->peCMode0&~0x4)|(_SHIFTL(dither,2,1));
4092 GX_LOAD_BP_REG(__gx->peCMode0);
4095 void GX_SetDstAlpha(u8 enable,u8 a)
4097 __gx->peCMode1 = (__gx->peCMode1&~0xff)|(a&0xff);
4098 __gx->peCMode1 = (__gx->peCMode1&~0x100)|(_SHIFTL(enable,8,1));
4099 GX_LOAD_BP_REG(__gx->peCMode1);
4102 void GX_SetFieldMask(u8 even_mask,u8 odd_mask)
4104 u32 val = 0;
4106 val = (_SHIFTL(even_mask,1,1))|(odd_mask&1);
4107 GX_LOAD_BP_REG(0x44000000|val);
4110 void GX_SetFieldMode(u8 field_mode,u8 half_aspect_ratio)
4112 __gx->lpWidth = (__gx->lpWidth&~0x400000)|(_SHIFTL(half_aspect_ratio,22,1));
4113 GX_LOAD_BP_REG(__gx->lpWidth);
4115 __GX_FlushTextureState();
4116 GX_LOAD_BP_REG(0x68000000|(field_mode&1));
4117 __GX_FlushTextureState();
4120 void GX_PokeAlphaMode(u8 func,u8 threshold)
4122 _peReg[3] = (_SHIFTL(func,8,8))|(threshold&0xFF);
4125 void GX_PokeAlphaRead(u8 mode)
4127 _peReg[4] = (mode&~0x4)|0x4;
4130 void GX_PokeDstAlpha(u8 enable,u8 a)
4132 _peReg[2] = (_SHIFTL(enable,8,1))|(a&0xff);
4135 void GX_PokeAlphaUpdate(u8 update_enable)
4137 _peReg[1] = (_peReg[1]&~0x10)|(_SHIFTL(update_enable,4,1));
4140 void GX_PokeColorUpdate(u8 update_enable)
4142 _peReg[1] = (_peReg[1]&~0x8)|(_SHIFTL(update_enable,3,1));
4145 void GX_PokeDither(u8 dither)
4147 _peReg[1] = (_peReg[1]&~0x4)|(_SHIFTL(dither,2,1));
4150 void GX_PokeBlendMode(u8 type,u8 src_fact,u8 dst_fact,u8 op)
4152 u32 regval = _peReg[1];
4154 regval = (regval&~0x1);
4155 if(type==GX_BM_BLEND || type==GX_BM_SUBSTRACT) regval |= 0x1;
4157 regval = (regval&~0x800);
4158 if(type==GX_BM_SUBSTRACT) regval |= 0x800;
4160 regval = (regval&~0x2);
4161 if(type==GX_BM_LOGIC) regval |= 0x2;
4163 regval = (regval&~0xF000)|(_SHIFTL(op,12,4));
4164 regval = (regval&~0xE0)|(_SHIFTL(dst_fact,5,3));
4165 regval = (regval&~0x700)|(_SHIFTL(src_fact,8,3));
4167 regval |= 0x41000000;
4168 _peReg[1] = (u16)regval;
4171 void GX_PokeARGB(u16 x,u16 y,GXColor color)
4173 u32 regval;
4175 regval = 0xc8000000|(_SHIFTL(x,2,10));
4176 regval = (regval&~0x3FF000)|(_SHIFTL(y,12,10));
4177 *(u32*)regval = _SHIFTL(color.a,24,8)|_SHIFTL(color.r,16,8)|_SHIFTL(color.g,8,8)|(color.b&0xff);
4180 void GX_PeekARGB(u16 x,u16 y,GXColor *color)
4182 u32 regval,val;
4184 regval = 0xc8000000|(_SHIFTL(x,2,10));
4185 regval = (regval&~0x3FF000)|(_SHIFTL(y,12,10));
4186 val = *(u32*)regval;
4187 color->a = _SHIFTR(val,24,8);
4188 color->r = _SHIFTR(val,16,8);
4189 color->g = _SHIFTR(val,8,8);
4190 color->b = val&0xff;
4193 void GX_PokeZ(u16 x,u16 y,u32 z)
4195 u32 regval;
4197 regval = 0xc8000000|(_SHIFTL(x,2,10));
4198 regval = (regval&~0x3FF000)|(_SHIFTL(y,12,10));
4199 regval = (regval&~0xC00000)|0x400000;
4200 *(u32*)regval = z;
4203 void GX_PeekZ(u16 x,u16 y,u32 *z)
4205 u32 regval;
4207 regval = 0xc8000000|(_SHIFTL(x,2,10));
4208 regval = (regval&~0x3FF000)|(_SHIFTL(y,12,10));
4209 regval = (regval&~0xC00000)|0x400000;
4210 *z = *(u32*)regval;
4213 void GX_PokeZMode(u8 comp_enable,u8 func,u8 update_enable)
4215 u16 regval;
4216 regval = comp_enable&0x1;
4217 regval = (regval&~0xE)|(_SHIFTL(func,1,3));
4218 regval = (regval&0x10)|(_SHIFTL(update_enable,4,1));
4219 _peReg[0] = regval;
4222 void GX_SetIndTexOrder(u8 indtexstage,u8 texcoord,u8 texmap)
4224 switch(indtexstage) {
4225 case GX_INDTEXSTAGE0:
4226 __gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x7)|(texmap&0x7);
4227 __gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x38)|(_SHIFTL(texcoord,3,3));
4228 break;
4229 case GX_INDTEXSTAGE1:
4230 __gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x1C0)|(_SHIFTL(texmap,6,3));
4231 __gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0xE00)|(_SHIFTL(texcoord,9,3));
4232 break;
4233 case GX_INDTEXSTAGE2:
4234 __gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x7000)|(_SHIFTL(texmap,12,3));
4235 __gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x38000)|(_SHIFTL(texcoord,15,3));
4236 break;
4237 case GX_INDTEXSTAGE3:
4238 __gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x1C0000)|(_SHIFTL(texmap,18,3));
4239 __gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0xE00000)|(_SHIFTL(texcoord,21,3));
4240 break;
4242 GX_LOAD_BP_REG(__gx->tevRasOrder[2]);
4243 __gx->dirtyState |= 0x0003;
4246 void GX_InitLightPos(GXLightObj *lit_obj,f32 x,f32 y,f32 z)
4248 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4250 lit->px = x;
4251 lit->py = y;
4252 lit->pz = z;
4255 void GX_InitLightColor(GXLightObj *lit_obj,GXColor col)
4257 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4258 lit->col = ((_SHIFTL(col.r,24,8))|(_SHIFTL(col.g,16,8))|(_SHIFTL(col.b,8,8))|(col.a&0xff));
4261 void GX_LoadLightObj(GXLightObj *lit_obj,u8 lit_id)
4263 u32 id;
4264 u16 reg;
4265 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4267 switch(lit_id) {
4268 case GX_LIGHT0:
4269 id = 0;
4270 break;
4271 case GX_LIGHT1:
4272 id = 1;
4273 break;
4274 case GX_LIGHT2:
4275 id = 2;
4276 break;
4277 case GX_LIGHT3:
4278 id = 3;
4279 break;
4280 case GX_LIGHT4:
4281 id = 4;
4282 break;
4283 case GX_LIGHT5:
4284 id = 5;
4285 break;
4286 case GX_LIGHT6:
4287 id = 6;
4288 break;
4289 case GX_LIGHT7:
4290 id = 7;
4291 break;
4292 default:
4293 id = 0;
4294 break;
4297 reg = 0x600|(_SHIFTL(id,4,8));
4298 GX_LOAD_XF_REGS(reg,16);
4299 FIFO_PUTU32(0);
4300 FIFO_PUTU32(0);
4301 FIFO_PUTU32(0);
4302 FIFO_PUTU32(lit->col);
4303 FIFO_PUTF32(lit->a0);
4304 FIFO_PUTF32(lit->a1);
4305 FIFO_PUTF32(lit->a2);
4306 FIFO_PUTF32(lit->k0);
4307 FIFO_PUTF32(lit->k1);
4308 FIFO_PUTF32(lit->k2);
4309 FIFO_PUTF32(lit->px);
4310 FIFO_PUTF32(lit->py);
4311 FIFO_PUTF32(lit->pz);
4312 FIFO_PUTF32(lit->nx);
4313 FIFO_PUTF32(lit->ny);
4314 FIFO_PUTF32(lit->nz);
4317 void GX_LoadLightObjIdx(u32 litobjidx,u8 litid)
4319 u32 reg;
4320 u32 idx = 0;
4322 switch(litid) {
4323 case GX_LIGHT0:
4324 idx = 0;
4325 break;
4326 case GX_LIGHT1:
4327 idx = 1;
4328 break;
4329 case GX_LIGHT2:
4330 idx = 2;
4331 break;
4332 case GX_LIGHT3:
4333 idx = 3;
4334 break;
4335 case GX_LIGHT4:
4336 idx = 4;
4337 break;
4338 case GX_LIGHT5:
4339 idx = 5;
4340 break;
4341 case GX_LIGHT6:
4342 idx = 6;
4343 break;
4344 case GX_LIGHT7:
4345 idx = 7;
4346 break;
4347 default:
4348 idx = 0;
4349 break;
4353 reg = 0xf600|(_SHIFTL(idx,4,8));
4354 reg = (reg&~0xffff0000)|(_SHIFTL(litobjidx,16,16));
4356 FIFO_PUTU8(0x38);
4357 FIFO_PUTU32(reg);
4360 void GX_InitLightDir(GXLightObj *lit_obj,f32 nx,f32 ny,f32 nz)
4362 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4364 lit->nx = -(nx);
4365 lit->ny = -(ny);
4366 lit->nz = -(nz);
4369 void GX_InitLightDistAttn(GXLightObj *lit_obj,f32 ref_dist,f32 ref_brite,u8 dist_fn)
4371 f32 k0,k1,k2;
4372 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4374 if(ref_dist<0.0f ||
4375 ref_brite<0.0f || ref_brite>=1.0f) dist_fn = GX_DA_OFF;
4377 switch(dist_fn) {
4378 case GX_DA_GENTLE:
4379 k0 = 1.0f;
4380 k1 = (1.0f-ref_brite)/(ref_brite*ref_dist);
4381 k2 = 0.0f;
4382 break;
4383 case GX_DA_MEDIUM:
4384 k0 = 1.0f;
4385 k1 = 0.5f*(1.0f-ref_brite)/(ref_brite*ref_dist);
4386 k2 = 0.5f*(1.0f-ref_brite)/(ref_brite*ref_dist*ref_dist);
4387 break;
4388 case GX_DA_STEEP:
4389 k0 = 1.0f;
4390 k1 = 0.0f;
4391 k2 = (1.0f-ref_brite)/(ref_brite*ref_dist*ref_dist);
4392 break;
4393 case GX_DA_OFF:
4394 default:
4395 k0 = 1.0f;
4396 k1 = 0.0f;
4397 k2 = 0.0f;
4398 break;
4401 lit->k0 = k0;
4402 lit->k1 = k1;
4403 lit->k2 = k2;
4406 void GX_InitLightAttn(GXLightObj *lit_obj,f32 a0,f32 a1,f32 a2,f32 k0,f32 k1,f32 k2)
4408 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4410 lit->a0 = a0;
4411 lit->a1 = a1;
4412 lit->a2 = a2;
4413 lit->k0 = k0;
4414 lit->k1 = k1;
4415 lit->k2 = k2;
4418 void GX_InitLightAttnA(GXLightObj *lit_obj,f32 a0,f32 a1,f32 a2)
4420 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4422 lit->a0 = a0;
4423 lit->a1 = a1;
4424 lit->a2 = a2;
4427 void GX_InitLightAttnK(GXLightObj *lit_obj,f32 k0,f32 k1,f32 k2)
4429 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4431 lit->k0 = k0;
4432 lit->k1 = k1;
4433 lit->k2 = k2;
4436 void GX_InitSpecularDirHA(GXLightObj *lit_obj,f32 nx,f32 ny,f32 nz,f32 hx,f32 hy,f32 hz)
4438 f32 px, py, pz;
4439 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4441 px = (nx * LARGE_NUMBER);
4442 py = (ny * LARGE_NUMBER);
4443 pz = (nz * LARGE_NUMBER);
4445 lit->px = px;
4446 lit->py = py;
4447 lit->pz = pz;
4448 lit->nx = hx;
4449 lit->ny = hy;
4450 lit->nz = hz;
4453 void GX_InitSpecularDir(GXLightObj *lit_obj,f32 nx,f32 ny,f32 nz)
4455 f32 px, py, pz;
4456 f32 hx, hy, hz, mag;
4457 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4459 // Compute half-angle vector
4460 hx = -nx;
4461 hy = -ny;
4462 hz = (-nz + 1.0f);
4463 mag = ((hx * hx) + (hy * hy) + (hz * hz));
4464 if(mag!=0.0f) mag = 1.0f / sqrtf(mag);
4466 hx *= mag;
4467 hy *= mag;
4468 hz *= mag;
4470 px = (nx * LARGE_NUMBER);
4471 py = (ny * LARGE_NUMBER);
4472 pz = (nz * LARGE_NUMBER);
4474 lit->px = px;
4475 lit->py = py;
4476 lit->pz = pz;
4477 lit->nx = hx;
4478 lit->ny = hy;
4479 lit->nz = hz;
4482 void GX_InitLightSpot(GXLightObj *lit_obj,f32 cut_off,u8 spotfn)
4484 f32 r,d,cr,a0,a1,a2;
4485 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4487 if(cut_off<0.0f || cut_off>90.0f) spotfn = GX_SP_OFF;
4489 r = (cut_off*M_PI)/180.0f;
4490 cr = cosf(r);
4492 switch(spotfn) {
4493 case GX_SP_FLAT:
4494 a0 = -1000.0f*cr;
4495 a1 = 1000.0f;
4496 a2 = 0.0f;
4497 break;
4498 case GX_SP_COS:
4499 a0 = -cr/(1.0f-cr);
4500 a1 = 1.0f/(1.0f-cr);
4501 a2 = 0.0f;
4502 break;
4503 case GX_SP_COS2:
4504 a0 = 0.0f;
4505 a1 = -cr/(1.0f-cr);
4506 a2 = 1.0f/(1.0f-cr);
4507 break;
4508 case GX_SP_SHARP:
4509 d = (1.0f-cr)*(1.0f-cr);
4510 a0 = cr*(cr-2.0f);
4511 a1 = 2.0f/d;
4512 a2 = -1.0/d;
4513 break;
4514 case GX_SP_RING1:
4515 d = (1.0f-cr)*(1.0f-cr);
4516 a0 = -4.0f*cr/d;
4517 a1 = 4.0f*(1.0f+cr)/d;
4518 a2 = -4.0f/d;
4519 break;
4520 case GX_SP_RING2:
4521 d = (1.0f-cr)*(1.0f-cr);
4522 a0 = 1.0f-2.0f*cr*cr/d;
4523 a1 = 4.0f*cr/d;
4524 a2 = -2.0f/d;
4525 break;
4526 case GX_SP_OFF:
4527 default:
4528 a0 = 1.0f;
4529 a1 = 0.0f;
4530 a2 = 0.0f;
4531 break;
4534 lit->a0 = a0;
4535 lit->a1 = a1;
4536 lit->a2 = a2;
4539 void GX_SetGPMetric(u32 perf0,u32 perf1)
4541 // check last setted perf0 counters
4542 if(__gx->perf0Mode>=GX_PERF0_TRIANGLES && __gx->perf0Mode<GX_PERF0_QUAD_0CVG)
4543 GX_LOAD_BP_REG(0x23000000);
4544 else if(__gx->perf0Mode>=GX_PERF0_QUAD_0CVG && __gx->perf0Mode<GX_PERF0_CLOCKS)
4545 GX_LOAD_BP_REG(0x24000000);
4546 else if(__gx->perf0Mode>=GX_PERF0_VERTICES && __gx->perf0Mode<=GX_PERF0_CLOCKS)
4547 GX_LOAD_XF_REG(0x1006,0);
4549 // check last setted perf1 counters
4550 if(__gx->perf1Mode>=GX_PERF1_VC_ELEMQ_FULL && __gx->perf1Mode<GX_PERF1_FIFO_REQ) {
4551 __gx->cpPerfMode = (__gx->cpPerfMode&~0xf0);
4552 GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4553 } else if(__gx->perf1Mode>=GX_PERF1_FIFO_REQ && __gx->perf1Mode<GX_PERF1_CLOCKS) {
4554 _cpReg[3] = 0;
4555 } else if(__gx->perf1Mode>=GX_PERF1_TEXELS && __gx->perf1Mode<=GX_PERF1_CLOCKS) {
4556 GX_LOAD_BP_REG(0x67000000);
4559 __gx->perf0Mode = perf0;
4560 switch(__gx->perf0Mode) {
4561 case GX_PERF0_CLOCKS:
4562 GX_LOAD_XF_REG(0x1006,0x00000273);
4563 break;
4564 case GX_PERF0_VERTICES:
4565 GX_LOAD_XF_REG(0x1006,0x0000014a);
4566 break;
4567 case GX_PERF0_CLIP_VTX:
4568 GX_LOAD_XF_REG(0x1006,0x0000016b);
4569 break;
4570 case GX_PERF0_CLIP_CLKS:
4571 GX_LOAD_XF_REG(0x1006,0x00000084);
4572 break;
4573 case GX_PERF0_XF_WAIT_IN:
4574 GX_LOAD_XF_REG(0x1006,0x000000c6);
4575 break;
4576 case GX_PERF0_XF_WAIT_OUT:
4577 GX_LOAD_XF_REG(0x1006,0x00000210);
4578 break;
4579 case GX_PERF0_XF_XFRM_CLKS:
4580 GX_LOAD_XF_REG(0x1006,0x00000252);
4581 break;
4582 case GX_PERF0_XF_LIT_CLKS:
4583 GX_LOAD_XF_REG(0x1006,0x00000231);
4584 break;
4585 case GX_PERF0_XF_BOT_CLKS:
4586 GX_LOAD_XF_REG(0x1006,0x000001ad);
4587 break;
4588 case GX_PERF0_XF_REGLD_CLKS:
4589 GX_LOAD_XF_REG(0x1006,0x000001ce);
4590 break;
4591 case GX_PERF0_XF_REGRD_CLKS:
4592 GX_LOAD_XF_REG(0x1006,0x00000021);
4593 break;
4594 case GX_PERF0_CLIP_RATIO:
4595 GX_LOAD_XF_REG(0x1006,0x00000153);
4596 break;
4597 case GX_PERF0_TRIANGLES:
4598 GX_LOAD_BP_REG(0x2300AE7F);
4599 break;
4600 case GX_PERF0_TRIANGLES_CULLED:
4601 GX_LOAD_BP_REG(0x23008E7F);
4602 break;
4603 case GX_PERF0_TRIANGLES_PASSED:
4604 GX_LOAD_BP_REG(0x23009E7F);
4605 break;
4606 case GX_PERF0_TRIANGLES_SCISSORED:
4607 GX_LOAD_BP_REG(0x23001E7F);
4608 break;
4609 case GX_PERF0_TRIANGLES_0TEX:
4610 GX_LOAD_BP_REG(0x2300AC3F);
4611 break;
4612 case GX_PERF0_TRIANGLES_1TEX:
4613 GX_LOAD_BP_REG(0x2300AC7F);
4614 break;
4615 case GX_PERF0_TRIANGLES_2TEX:
4616 GX_LOAD_BP_REG(0x2300ACBF);
4617 break;
4618 case GX_PERF0_TRIANGLES_3TEX:
4619 GX_LOAD_BP_REG(0x2300ACFF);
4620 break;
4621 case GX_PERF0_TRIANGLES_4TEX:
4622 GX_LOAD_BP_REG(0x2300AD3F);
4623 break;
4624 case GX_PERF0_TRIANGLES_5TEX:
4625 GX_LOAD_BP_REG(0x2300AD7F);
4626 break;
4627 case GX_PERF0_TRIANGLES_6TEX:
4628 GX_LOAD_BP_REG(0x2300ADBF);
4629 break;
4630 case GX_PERF0_TRIANGLES_7TEX:
4631 GX_LOAD_BP_REG(0x2300ADFF);
4632 break;
4633 case GX_PERF0_TRIANGLES_8TEX:
4634 GX_LOAD_BP_REG(0x2300AE3F);
4635 break;
4636 case GX_PERF0_TRIANGLES_0CLR:
4637 GX_LOAD_BP_REG(0x2300A27F);
4638 break;
4639 case GX_PERF0_TRIANGLES_1CLR:
4640 GX_LOAD_BP_REG(0x2300A67F);
4641 break;
4642 case GX_PERF0_TRIANGLES_2CLR:
4643 GX_LOAD_BP_REG(0x2300AA7F);
4644 break;
4645 case GX_PERF0_QUAD_0CVG:
4646 GX_LOAD_BP_REG(0x2402C0C6);
4647 break;
4648 case GX_PERF0_QUAD_NON0CVG:
4649 GX_LOAD_BP_REG(0x2402C16B);
4650 break;
4651 case GX_PERF0_QUAD_1CVG:
4652 GX_LOAD_BP_REG(0x2402C0E7);
4653 break;
4654 case GX_PERF0_QUAD_2CVG:
4655 GX_LOAD_BP_REG(0x2402C108);
4656 break;
4657 case GX_PERF0_QUAD_3CVG:
4658 GX_LOAD_BP_REG(0x2402C129);
4659 break;
4660 case GX_PERF0_QUAD_4CVG:
4661 GX_LOAD_BP_REG(0x2402C14A);
4662 break;
4663 case GX_PERF0_AVG_QUAD_CNT:
4664 GX_LOAD_BP_REG(0x2402C1AD);
4665 break;
4666 case GX_PERF0_NONE:
4667 break;
4670 __gx->perf1Mode = perf1;
4671 switch(__gx->perf1Mode) {
4672 case GX_PERF1_CLOCKS:
4673 GX_LOAD_BP_REG(0x67000042);
4674 break;
4675 case GX_PERF1_TEXELS:
4676 GX_LOAD_BP_REG(0x67000084);
4677 break;
4678 case GX_PERF1_TX_IDLE:
4679 GX_LOAD_BP_REG(0x67000063);
4680 break;
4681 case GX_PERF1_TX_REGS:
4682 GX_LOAD_BP_REG(0x67000129);
4683 break;
4684 case GX_PERF1_TX_MEMSTALL:
4685 GX_LOAD_BP_REG(0x67000252);
4686 break;
4687 case GX_PERF1_TC_CHECK1_2:
4688 GX_LOAD_BP_REG(0x67000021);
4689 break;
4690 case GX_PERF1_TC_CHECK3_4:
4691 GX_LOAD_BP_REG(0x6700014b);
4692 break;
4693 case GX_PERF1_TC_CHECK5_6:
4694 GX_LOAD_BP_REG(0x6700018d);
4695 break;
4696 case GX_PERF1_TC_CHECK7_8:
4697 GX_LOAD_BP_REG(0x670001cf);
4698 break;
4699 case GX_PERF1_TC_MISS:
4700 GX_LOAD_BP_REG(0x67000211);
4701 break;
4702 case GX_PERF1_VC_ELEMQ_FULL:
4703 __gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x20;
4704 GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4705 break;
4706 case GX_PERF1_VC_MISSQ_FULL:
4707 __gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x30;
4708 GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4709 break;
4710 case GX_PERF1_VC_MEMREQ_FULL:
4711 __gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x40;
4712 GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4713 break;
4714 case GX_PERF1_VC_STATUS7:
4715 __gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x50;
4716 GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4717 break;
4718 case GX_PERF1_VC_MISSREP_FULL:
4719 __gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x60;
4720 GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4721 break;
4722 case GX_PERF1_VC_STREAMBUF_LOW:
4723 __gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x70;
4724 GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4725 break;
4726 case GX_PERF1_VC_ALL_STALLS:
4727 __gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x90;
4728 GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4729 break;
4730 case GX_PERF1_VERTICES:
4731 __gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x80;
4732 GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4733 break;
4734 case GX_PERF1_FIFO_REQ:
4735 _cpReg[3] = 2;
4736 break;
4737 case GX_PERF1_CALL_REQ:
4738 _cpReg[3] = 3;
4739 break;
4740 case GX_PERF1_VC_MISS_REQ:
4741 _cpReg[3] = 4;
4742 break;
4743 case GX_PERF1_CP_ALL_REQ:
4744 _cpReg[3] = 5;
4745 break;
4746 case GX_PERF1_NONE:
4747 break;
4752 void GX_ClearGPMetric()
4754 _cpReg[2] = 4;
4757 void GX_InitXfRasMetric()
4759 GX_LOAD_BP_REG(0x2402C022);
4760 GX_LOAD_XF_REG(0x1006,0x31000);
4763 void GX_ReadXfRasMetric(u32 *xfwaitin,u32 *xfwaitout,u32 *rasbusy,u32 *clks)
4765 *rasbusy = _SHIFTL(_cpReg[33],16,16)|(_cpReg[32]&0xffff);
4766 *clks = _SHIFTL(_cpReg[35],16,16)|(_cpReg[34]&0xffff);
4767 *xfwaitin = _SHIFTL(_cpReg[37],16,16)|(_cpReg[36]&0xffff);
4768 *xfwaitout = _SHIFTL(_cpReg[39],16,16)|(_cpReg[38]&0xffff);
4771 u32 GX_ReadClksPerVtx()
4773 GX_DrawDone();
4774 _cpReg[49] = 0x1007;
4775 _cpReg[48] = 0x1007;
4776 return (_cpReg[50]<<8);
4779 void GX_ClearVCacheMetric()
4781 GX_LOAD_CP_REG(0,0);
4784 void GX_ReadVCacheMetric(u32 *check,u32 *miss,u32 *stall)
4786 *check = _SHIFTL(_cpReg[41],16,16)|(_cpReg[40]&0xffff);
4787 *miss = _SHIFTL(_cpReg[43],16,16)|(_cpReg[42]&0xffff);
4788 *stall = _SHIFTL(_cpReg[45],16,16)|(_cpReg[44]&0xffff);
4791 void GX_SetVCacheMetric(u32 attr)
4795 void GX_GetGPStatus(u8 *overhi,u8 *underlow,u8 *readIdle,u8 *cmdIdle,u8 *brkpt)
4797 _gxgpstatus = _cpReg[0];
4798 *overhi = !!(_gxgpstatus&1);
4799 *underlow = !!(_gxgpstatus&2);
4800 *readIdle = !!(_gxgpstatus&4);
4801 *cmdIdle = !!(_gxgpstatus&8);
4802 *brkpt = !!(_gxgpstatus&16);
4805 void GX_ReadGPMetric(u32 *cnt0,u32 *cnt1)
4807 u32 tmp,reg1,reg2,reg3,reg4;
4809 reg1 = (_SHIFTL(_cpReg[33],16,16))|(_cpReg[32]&0xffff);
4810 reg2 = (_SHIFTL(_cpReg[35],16,16))|(_cpReg[34]&0xffff);
4811 reg3 = (_SHIFTL(_cpReg[37],16,16))|(_cpReg[36]&0xffff);
4812 reg4 = (_SHIFTL(_cpReg[39],16,16))|(_cpReg[38]&0xffff);
4814 *cnt0 = 0;
4815 if(__gx->perf0Mode==GX_PERF0_CLIP_RATIO) {
4816 tmp = reg2*1000;
4817 *cnt0 = tmp/reg1;
4818 } else if(__gx->perf0Mode>=GX_PERF0_VERTICES && __gx->perf0Mode<GX_PERF0_NONE) *cnt0 = reg1;
4820 //further implementation needed.....
4821 // cnt1 fails....
4824 void GX_AdjustForOverscan(GXRModeObj *rmin,GXRModeObj *rmout,u16 hor,u16 ver)
4826 if(rmin!=rmout) memcpy(rmout,rmin,sizeof(GXRModeObj));
4828 rmout->fbWidth = rmin->fbWidth-(hor<<1);
4829 rmout->efbHeight = rmin->efbHeight-((rmin->efbHeight*(ver<<1))/rmin->xfbHeight);
4830 if(rmin->xfbMode==VI_XFBMODE_SF && !(rmin->viTVMode&VI_PROGRESSIVE)) rmout->xfbHeight = rmin->xfbHeight-ver;
4831 else rmout->xfbHeight = rmin->xfbHeight-(ver<<1);
4833 rmout->viWidth = rmin->viWidth-(hor<<1);
4834 if(rmin->viTVMode&VI_PROGRESSIVE) rmout->viHeight = rmin->viHeight-(ver<<2);
4835 else rmout->viHeight = rmin->viHeight-(ver<<1);
4837 rmout->viXOrigin += hor;
4838 rmout->viYOrigin += ver;
4841 f32 GX_GetYScaleFactor(u16 efbHeight,u16 xfbHeight)
4843 u32 yScale,xfblines,cnt;
4844 f32 yscale;
4846 yscale = (f32)efbHeight/(f32)xfbHeight;
4847 yScale = (u32)((f32)256.0/yscale)&0x1ff;
4849 cnt = xfbHeight;
4850 xfblines = __GX_GetNumXfbLines(efbHeight,yScale);
4851 while(xfblines>=xfbHeight) {
4852 yscale = (f32)(cnt--)/(f32)efbHeight;
4853 yScale = (u32)((f32)256.0/yscale)&0x1ff;
4854 xfblines = __GX_GetNumXfbLines(efbHeight,yScale);
4857 while(xfblines<xfbHeight) {
4858 yscale = (f32)(cnt++)/(f32)efbHeight;
4859 yScale = (u32)((f32)256.0/yscale)&0x1ff;
4860 xfblines = __GX_GetNumXfbLines(efbHeight,yScale);
4862 return yscale;
4865 #undef LARGE_NUMBER