more usb compatiblity changes from rodries
[libogc.git] / libogc / gx.c
blobdc5000838c467e7d84295074f679a530eeb3a89a
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
22 #if defined(HW_DOL)
23 #define LARGE_NUMBER (-1048576.0f)
24 #elif defined(HW_RVL)
25 #define LARGE_NUMBER (-1.0e+18f)
26 #endif
28 #define _SHIFTL(v, s, w) \
29 ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
30 #define _SHIFTR(v, s, w) \
31 ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
33 #define GX_LOAD_BP_REG(x) \
34 do { \
35 wgPipe->U8 = 0x61; \
36 wgPipe->U32 = (u32)(x); \
37 } while(0)
39 #define GX_LOAD_CP_REG(x, y) \
40 do { \
41 wgPipe->U8 = 0x08; \
42 wgPipe->U8 = (u8)(x); \
43 wgPipe->U32 = (u32)(y); \
44 } while(0)
46 #define GX_LOAD_XF_REG(x, y) \
47 do { \
48 wgPipe->U8 = 0x10; \
49 wgPipe->U32 = (u32)((x)&0xffff); \
50 wgPipe->U32 = (u32)(y); \
51 } while(0)
53 #define GX_LOAD_XF_REGS(x, n) \
54 do { \
55 wgPipe->U8 = 0x10; \
56 wgPipe->U32 = (u32)(((((n)&0xffff)-1)<<16)|((x)&0xffff)); \
57 } while(0)
59 #define XY(x, y) (((y) << 10) | (x))
61 #define GX_DEFAULT_BG {64,64,64,255}
62 #define BLACK {0,0,0,0}
63 #define WHITE {255,255,255,255}
65 WGPipe* const wgPipe = (WGPipe*)0xCC008000;
67 static GXFifoObj _gpfifo;
68 static GXFifoObj _cpufifo;
69 static GXFifoObj _gxfifoobj;
70 static GXFifoObj _gx_dl_fifoobj;
71 static GXFifoObj _gx_old_cpufifo;
72 static void *_gxcurrbp = NULL;
73 static lwp_t _gxcurrentlwp = LWP_THREAD_NULL;
75 static u32 _gxcpufifoready = 0;
76 static u32 _gxgpfifoready = 0;
77 static u32 _cpgplinked = 0;
78 static u16 _gxgpstatus = 0;
79 static vu32 _gxoverflowsuspend = 0;
80 static vu32 _gxoverflowcount = 0;
81 static vu32 _gxfinished = 0;
82 static lwpq_t _gxwaitfinish;
84 static GXBreakPtCallback breakPtCB = NULL;
85 static GXDrawDoneCallback drawDoneCB = NULL;
86 static GXDrawSyncCallback tokenCB = NULL;
88 static GXTexRegionCallback regionCB = NULL;
89 static GXTlutRegionCallback tlut_regionCB = NULL;
91 static vu32* const _piReg = (u32*)0xCC003000;
92 static vu16* const _cpReg = (u16*)0xCC000000;
93 static vu16* const _peReg = (u16*)0xCC001000;
94 static vu16* const _memReg = (u16*)0xCC004000;
96 static u8 _gxtevcolid[9] = {0,1,0,1,0,1,7,5,6};
97 static u8 _gxtexmode0ids[8] = {0x80,0x81,0x82,0x83,0xA0,0xA1,0xA2,0xA3};
98 static u8 _gxtexmode1ids[8] = {0x84,0x85,0x86,0x87,0xA4,0xA5,0xA6,0xA7};
99 static u8 _gxteximg0ids[8] = {0x88,0x89,0x8A,0x8B,0xA8,0xA9,0xAA,0xAB};
100 static u8 _gxteximg1ids[8] = {0x8C,0x8D,0x8E,0x8F,0xAC,0xAD,0xAE,0xAF};
101 static u8 _gxteximg2ids[8] = {0x90,0x91,0x92,0x93,0xB0,0xB1,0xB2,0xB3};
102 static u8 _gxteximg3ids[8] = {0x94,0x95,0x96,0x97,0xB4,0xB5,0xB6,0xB7};
103 static u8 _gxtextlutids[8] = {0x98,0x99,0x9A,0x9B,0xB8,0xB9,0xBA,0xBB};
105 #if defined(HW_RVL)
106 static u32 _gxtexregionaddrtable[48] =
108 0x00000000,0x00010000,0x00020000,0x00030000,
109 0x00040000,0x00050000,0x00060000,0x00070000,
110 0x00008000,0x00018000,0x00028000,0x00038000,
111 0x00048000,0x00058000,0x00068000,0x00078000,
112 0x00000000,0x00090000,0x00020000,0x000B0000,
113 0x00040000,0x00098000,0x00060000,0x000B8000,
114 0x00080000,0x00010000,0x000A0000,0x00030000,
115 0x00088000,0x00050000,0x000A8000,0x00070000,
116 0x00000000,0x00090000,0x00020000,0x000B0000,
117 0x00040000,0x00090000,0x00060000,0x000B0000,
118 0x00080000,0x00010000,0x000A0000,0x00030000,
119 0x00080000,0x00050000,0x000A0000,0x00070000
121 #endif
124 extern u8 __gxregs[];
125 static struct __gx_regdef *__gx = (struct __gx_regdef*)__gxregs;
126 static u8 _gx_saved_data[STRUCT_REGDEF_SIZE] ATTRIBUTE_ALIGN(32);
128 static s32 __gx_onreset(s32 final);
130 static sys_resetinfo __gx_resetinfo = {
132 __gx_onreset,
136 #ifdef _GP_DEBUG
137 extern int printk(const char *fmt,...);
138 #endif
140 static __inline__ BOOL IsWriteGatherBufferEmpty()
142 return !(mfwpar()&1);
145 static __inline__ void DisableWriteGatherPipe()
147 mthid2((mfhid2()&~0x40000000));
150 static __inline__ void EnableWriteGatherPipe()
152 mtwpar(0x0C008000);
153 mthid2((mfhid2()|0x40000000));
156 static __inline__ void __GX_ResetWriteGatherPipe()
158 while(mfwpar()&1);
159 mtwpar(0x0C008000);
162 static __inline__ void __GX_FifoLink(u8 enable)
164 __gx->cpCRreg = ((__gx->cpCRreg&~0x10)|(_SHIFTL(enable,4,1)));
165 _cpReg[1] = __gx->cpCRreg;
168 static __inline__ void __GX_WriteFifoIntReset(u8 inthi,u8 intlo)
170 __gx->cpCLreg = ((__gx->cpCLreg&~0x03)|(_SHIFTL(intlo,1,1))|(inthi&1));
171 _cpReg[2] = __gx->cpCLreg;
174 static __inline__ void __GX_WriteFifoIntEnable(u8 inthi, u8 intlo)
176 __gx->cpCRreg = ((__gx->cpCRreg&~0x0C)|(_SHIFTL(intlo,3,1))|(_SHIFTL(inthi,2,1)));
177 _cpReg[1] = __gx->cpCRreg;
180 static __inline__ void __GX_FifoReadEnable()
182 __gx->cpCRreg = ((__gx->cpCRreg&~0x01)|1);
183 _cpReg[1] = __gx->cpCRreg;
186 static __inline__ void __GX_FifoReadDisable()
188 __gx->cpCRreg = ((__gx->cpCRreg&~0x01)|0);
189 _cpReg[1] = __gx->cpCRreg;
192 static s32 __gx_onreset(s32 final)
194 if(final==FALSE) {
195 GX_Flush();
196 GX_AbortFrame();
198 return 1;
201 static u32 __GX_IsGPCPUFifoLinked()
203 return _cpgplinked;
206 static u32 __GX_IsGPFifoReady()
208 return _gxgpfifoready;
211 static u32 __GX_IsCPUFifoReady()
213 return _gxcpufifoready;
216 static u32 __GX_CPGPLinkCheck()
218 struct __gxfifo *gpfifo = (struct __gxfifo*)&_gpfifo;
219 struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
221 if(!_gxcpufifoready || !_gxgpfifoready) return 0;
223 if((cpufifo->buf_start==gpfifo->buf_start)&&(cpufifo->buf_end==gpfifo->buf_end)) return 1;
225 return 0;
228 static void __GX_InitRevBits()
230 s32 i;
232 i=0;
233 while(i<8) {
234 __gx->VAT0reg[i] = 0x40000000;
235 __gx->VAT1reg[i] = 0x80000000;
236 GX_LOAD_CP_REG((0x0080|i),__gx->VAT1reg[i]);
237 i++;
240 GX_LOAD_XF_REG(0x1000,0x3f);
241 GX_LOAD_XF_REG(0x1012,0x01);
243 GX_LOAD_BP_REG(0x5800000f);
247 static void __GX_WaitAbort(u32 delay)
249 u64 start,end;
251 start = gettime();
252 while(1) {
253 end = gettime();
254 if(diff_ticks(start,end)>=(u64)delay) break;
258 static u32 __GX_ReadMemCounterU32(u32 reg)
260 u16 lcnt,ucnt,tmp;
262 tmp = _memReg[reg];
263 do {
264 ucnt = tmp;
265 lcnt = _memReg[reg+1];
266 tmp = _memReg[reg];
267 } while(tmp!=ucnt);
268 return (u32)((ucnt<<16)|lcnt);
271 static void __GX_WaitAbortPixelEngine()
273 u32 cnt,tmp;
275 cnt = __GX_ReadMemCounterU32(39);
276 do {
277 tmp = cnt;
278 __GX_WaitAbort(8);
279 cnt = __GX_ReadMemCounterU32(39);
280 } while(cnt!=tmp);
283 static void __GX_Abort()
285 if(__gx->gxFifoInited && __GX_IsGPFifoReady())
286 __GX_WaitAbortPixelEngine();
288 _piReg[6] = 1;
289 __GX_WaitAbort(50);
291 _piReg[6] = 0;
292 __GX_WaitAbort(5);
295 static void __GX_SaveFifo()
297 s32 rdwt_dst;
298 u32 level,val;
299 struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
300 struct __gxfifo *gpfifo = (struct __gxfifo*)&_gpfifo;
302 _CPU_ISR_Disable(level);
304 if(_gxcpufifoready) {
305 val = _piReg[0x05];
306 cpufifo->wt_ptr = (u32)MEM_PHYSICAL_TO_K0((val&0x1FFFFFE0));
307 cpufifo->fifo_wrap = ((val&0x20000000)==0x20000000);
310 if(_gxgpfifoready) {
311 gpfifo->rd_ptr = (u32)MEM_PHYSICAL_TO_K0(_SHIFTL(_cpReg[29],16,16)|(_cpReg[28]&0xffff));
312 gpfifo->rdwt_dst = (_SHIFTL(_cpReg[25],16,16)|(_cpReg[24]&0xffff));
315 if(_cpgplinked) {
316 cpufifo->rd_ptr = gpfifo->rd_ptr;
317 cpufifo->rdwt_dst = gpfifo->rdwt_dst;
318 gpfifo->wt_ptr = cpufifo->wt_ptr;
319 } else if(_gxcpufifoready) {
320 rdwt_dst = (cpufifo->wt_ptr - cpufifo->rd_ptr);
321 if(rdwt_dst<0) cpufifo->rdwt_dst = (cpufifo->rdwt_dst + cpufifo->size);
322 else cpufifo->rdwt_dst = rdwt_dst;
325 _CPU_ISR_Restore(level);
328 static void __GX_CleanGPFifo()
330 u32 level;
331 struct __gxfifo *gpfifo = (struct __gxfifo*)&_gpfifo;
332 struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
334 if(!_gxgpfifoready) return;
336 _CPU_ISR_Disable(level);
337 __GX_FifoReadDisable();
338 __GX_WriteFifoIntEnable(FALSE,FALSE);
340 gpfifo->rd_ptr = gpfifo->wt_ptr;
341 gpfifo->rdwt_dst = 0;
343 /* setup rd<->wd dist */
344 _cpReg[24] = _SHIFTL(gpfifo->rdwt_dst,0,16);
345 _cpReg[25] = _SHIFTR(gpfifo->rdwt_dst,16,16);
347 /* setup wt ptr */
348 _cpReg[26] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->wt_ptr),0,16);
349 _cpReg[27] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->wt_ptr),16,16);
351 /* setup rd ptr */
352 _cpReg[28] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->rd_ptr),0,16);
353 _cpReg[29] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->rd_ptr),16,16);
354 ppcsync();
356 if(_cpgplinked) {
357 cpufifo->rd_ptr = gpfifo->rd_ptr;
358 cpufifo->wt_ptr = gpfifo->wt_ptr;
359 cpufifo->rdwt_dst = gpfifo->rdwt_dst;
361 _piReg[5] = (cpufifo->wt_ptr&0x1FFFFFE0);
362 __GX_WriteFifoIntEnable(TRUE,FALSE);
363 __GX_FifoLink(TRUE);
365 __gx->cpCRreg &= ~0x22;
366 _cpReg[1] = __gx->cpCRreg;
367 breakPtCB = NULL;
369 __GX_WriteFifoIntReset(TRUE,TRUE);
370 __GX_FifoReadEnable();
371 _CPU_ISR_Restore(level);
374 static void __GXOverflowHandler()
376 if(!_gxoverflowsuspend) {
377 _gxoverflowsuspend = 1;
378 _gxoverflowcount++;
379 __GX_WriteFifoIntEnable(GX_DISABLE,GX_ENABLE);
380 __GX_WriteFifoIntReset(GX_TRUE,GX_FALSE);
381 LWP_SuspendThread(_gxcurrentlwp);
385 static void __GXUnderflowHandler()
387 if(_gxoverflowsuspend) {
388 _gxoverflowsuspend = 0;
389 LWP_ResumeThread(_gxcurrentlwp);
390 __GX_WriteFifoIntReset(GX_TRUE,GX_TRUE);
391 __GX_WriteFifoIntEnable(GX_ENABLE,GX_DISABLE);
395 static void __GXCPInterruptHandler(u32 irq,void *ctx)
397 __gx->cpSRreg = _cpReg[0];
399 if((__gx->cpCRreg&0x08) && (__gx->cpSRreg&0x02))
400 __GXUnderflowHandler();
402 if((__gx->cpCRreg&0x04) && (__gx->cpSRreg&0x01))
403 __GXOverflowHandler();
405 if((__gx->cpCRreg&0x20) && (__gx->cpSRreg&0x10)) {
406 __gx->cpCRreg &= ~0x20;
407 _cpReg[1] = __gx->cpCRreg;
408 if(breakPtCB)
409 breakPtCB();
413 static void __GXTokenInterruptHandler(u32 irq,void *ctx)
415 u16 token = _peReg[7];
417 if(tokenCB)
418 tokenCB(token);
420 _peReg[5] = (_peReg[5]&~0x04)|0x04;
423 static void __GXFinishInterruptHandler(u32 irq,void *ctx)
425 #ifdef _GP_DEBUG
426 printf("__GXFinishInterruptHandler()\n");
427 #endif
428 _peReg[5] = (_peReg[5]&~0x08)|0x08;
429 _gxfinished = 1;
431 if(drawDoneCB)
432 drawDoneCB();
434 LWP_ThreadBroadcast(_gxwaitfinish);
437 static void __GX_PEInit()
439 IRQ_Request(IRQ_PI_PETOKEN,__GXTokenInterruptHandler,NULL);
440 __UnmaskIrq(IRQMASK(IRQ_PI_PETOKEN));
442 IRQ_Request(IRQ_PI_PEFINISH,__GXFinishInterruptHandler,NULL);
443 __UnmaskIrq(IRQMASK(IRQ_PI_PEFINISH));
445 _peReg[5] = 0x0F;
448 static void __GX_FifoInit()
450 IRQ_Request(IRQ_PI_CP,__GXCPInterruptHandler,NULL);
451 __UnmaskIrq(IRQMASK(IRQ_PI_CP));
453 memset(&_cpufifo,0,sizeof(GXFifoObj));
454 memset(&_gpfifo,0,sizeof(GXFifoObj));
456 _gxcpufifoready = 0;
457 _gxgpfifoready = 0;
458 _cpgplinked = 0;
459 _gxoverflowsuspend = 0;
460 _gxcurrentlwp = LWP_GetSelf();
463 static void __GX_SetTmemConfig(u8 nr)
465 if(nr==0) {
466 // Set_TextureImage0-3, GXTexMapID=0-3 tmem_offset=00000000, cache_width=32 kb, cache_height=32 kb, image_type=cached
467 GX_LOAD_BP_REG(0x8c0d8000);
468 GX_LOAD_BP_REG(0x900dc000);
469 GX_LOAD_BP_REG(0x8d0d8400);
470 GX_LOAD_BP_REG(0x910dc400);
471 GX_LOAD_BP_REG(0x8e0d8800);
472 GX_LOAD_BP_REG(0x920dc800);
473 GX_LOAD_BP_REG(0x8f0d8c00);
474 GX_LOAD_BP_REG(0x930dcc00);
476 // Set_TextureImage0-3, GXTexMapID=4-7 tmem_offset=00010000, cache_width=32 kb, cache_height=32 kb, image_type=cached
477 GX_LOAD_BP_REG(0xac0d9000);
478 GX_LOAD_BP_REG(0xb00dd000);
479 GX_LOAD_BP_REG(0xad0d9400);
480 GX_LOAD_BP_REG(0xb10dd400);
481 GX_LOAD_BP_REG(0xae0d9800);
482 GX_LOAD_BP_REG(0xb20dd800);
483 GX_LOAD_BP_REG(0xaf0d9c00);
484 GX_LOAD_BP_REG(0xb30ddc00);
486 return;
489 if(nr==1) {
490 // Set_TextureImage0-3, GXTexMapID=0-3 tmem_offset=00000000, cache_width=32 kb, cache_height=32 kb, image_type=cached
491 GX_LOAD_BP_REG(0x8c0d8000);
492 GX_LOAD_BP_REG(0x900dc000);
493 GX_LOAD_BP_REG(0x8d0d8800);
494 GX_LOAD_BP_REG(0x910dc800);
495 GX_LOAD_BP_REG(0x8e0d9000);
496 GX_LOAD_BP_REG(0x920dd000);
497 GX_LOAD_BP_REG(0x8f0d9800);
498 GX_LOAD_BP_REG(0x930dd800);
500 // Set_TextureImage0-3, GXTexMapID=4-7 tmem_offset=00010000, cache_width=32 kb, cache_height=32 kb, image_type=cached
501 GX_LOAD_BP_REG(0xac0da000);
502 GX_LOAD_BP_REG(0xb00de000);
503 GX_LOAD_BP_REG(0xad0da800);
504 GX_LOAD_BP_REG(0xb10de800);
505 GX_LOAD_BP_REG(0xae0db000);
506 GX_LOAD_BP_REG(0xb20df000);
507 GX_LOAD_BP_REG(0xaf0db800);
508 GX_LOAD_BP_REG(0xb30df800);
510 return;
513 if(nr==2) {
514 // Set_TextureImage0-3, GXTexMapID=0-3 tmem_offset=00000000, cache_width=32 kb, cache_height=32 kb, image_type=cached
515 GX_LOAD_BP_REG(0x8c0d8000);
516 GX_LOAD_BP_REG(0x900dc000);
517 GX_LOAD_BP_REG(0x8d0d8800);
518 GX_LOAD_BP_REG(0x910dc800);
519 GX_LOAD_BP_REG(0x8e0d9000);
520 GX_LOAD_BP_REG(0x920dd000);
521 GX_LOAD_BP_REG(0x8f0d9800);
522 GX_LOAD_BP_REG(0x930dd800);
524 // Set_TextureImage0-3, GXTexMapID=4-7 tmem_offset=00010000, cache_width=32 kb, cache_height=32 kb, image_type=cached
525 GX_LOAD_BP_REG(0xac0da000);
526 GX_LOAD_BP_REG(0xb00dc400);
527 GX_LOAD_BP_REG(0xad0da800);
528 GX_LOAD_BP_REG(0xb10dcc00);
529 GX_LOAD_BP_REG(0xae0db000);
530 GX_LOAD_BP_REG(0xb20dd400);
531 GX_LOAD_BP_REG(0xaf0db800);
532 GX_LOAD_BP_REG(0xb30ddc00);
534 return;
538 #if defined(HW_RVL)
539 static GXTexRegion* __GXDefTexRegionCallback(GXTexObj *obj,u8 mapid)
541 u32 fmt,mipmap;
542 GXTexRegion *ret = NULL;
544 fmt = GX_GetTexObjFmt(obj);
545 mipmap = GX_GetTexObjMipMap(obj);
546 if(fmt>=GX_TF_CI4 && fmt<=GX_TF_CI14)
547 return &__gx->texRegion[mapid];
548 else if(fmt==GX_TF_CMPR)
549 ret = &__gx->texRegion[mapid];
550 else
551 ret = &__gx->texRegion[mapid+8];
553 if(mipmap) ret = &__gx->texRegion[mapid+16];
555 return ret;
557 #else
558 static GXTexRegion* __GXDefTexRegionCallback(GXTexObj *obj,u8 mapid)
560 u32 fmt;
561 u32 idx;
562 static u32 regionA = 0;
563 static u32 regionB = 0;
564 GXTexRegion *ret = NULL;
566 fmt = GX_GetTexObjFmt(obj);
567 if(fmt==0x0008 || fmt==0x0009 || fmt==0x000a) {
568 idx = regionB++;
569 ret = &__gx->texRegion[(idx&3)+8];
570 } else {
571 idx = regionA++;
572 ret = &__gx->texRegion[(idx&7)];
574 return ret;
576 #endif
578 static GXTlutRegion* __GXDefTlutRegionCallback(u32 tlut_name)
580 return &__gx->tlutRegion[tlut_name];
583 static void __GX_InitGX()
585 s32 i;
586 u32 flag;
587 GXRModeObj *rmode;
588 Mtx identity_matrix =
590 {1,0,0,0},
591 {0,1,0,0},
592 {0,0,1,0}
595 rmode = VIDEO_GetPreferredMode(NULL);
597 GX_SetCopyClear((GXColor)BLACK,0xffffff);
598 GX_SetTexCoordGen(GX_TEXCOORD0,GX_TG_MTX2x4,GX_TG_TEX0,GX_IDENTITY);
599 GX_SetTexCoordGen(GX_TEXCOORD1,GX_TG_MTX2x4,GX_TG_TEX1,GX_IDENTITY);
600 GX_SetTexCoordGen(GX_TEXCOORD2,GX_TG_MTX2x4,GX_TG_TEX2,GX_IDENTITY);
601 GX_SetTexCoordGen(GX_TEXCOORD3,GX_TG_MTX2x4,GX_TG_TEX3,GX_IDENTITY);
602 GX_SetTexCoordGen(GX_TEXCOORD4,GX_TG_MTX2x4,GX_TG_TEX4,GX_IDENTITY);
603 GX_SetTexCoordGen(GX_TEXCOORD5,GX_TG_MTX2x4,GX_TG_TEX5,GX_IDENTITY);
604 GX_SetTexCoordGen(GX_TEXCOORD6,GX_TG_MTX2x4,GX_TG_TEX6,GX_IDENTITY);
605 GX_SetTexCoordGen(GX_TEXCOORD7,GX_TG_MTX2x4,GX_TG_TEX7,GX_IDENTITY);
606 GX_SetNumTexGens(1);
607 GX_ClearVtxDesc();
608 GX_InvVtxCache();
610 GX_SetLineWidth(6,GX_TO_ZERO);
611 GX_SetPointSize(6,GX_TO_ZERO);
613 GX_EnableTexOffsets(GX_TEXCOORD0,GX_DISABLE,GX_DISABLE);
614 GX_EnableTexOffsets(GX_TEXCOORD1,GX_DISABLE,GX_DISABLE);
615 GX_EnableTexOffsets(GX_TEXCOORD2,GX_DISABLE,GX_DISABLE);
616 GX_EnableTexOffsets(GX_TEXCOORD3,GX_DISABLE,GX_DISABLE);
617 GX_EnableTexOffsets(GX_TEXCOORD4,GX_DISABLE,GX_DISABLE);
618 GX_EnableTexOffsets(GX_TEXCOORD5,GX_DISABLE,GX_DISABLE);
619 GX_EnableTexOffsets(GX_TEXCOORD6,GX_DISABLE,GX_DISABLE);
620 GX_EnableTexOffsets(GX_TEXCOORD7,GX_DISABLE,GX_DISABLE);
622 GX_LoadPosMtxImm(identity_matrix,GX_PNMTX0);
623 GX_LoadNrmMtxImm(identity_matrix,GX_PNMTX0);
624 GX_SetCurrentMtx(GX_PNMTX0);
625 GX_LoadTexMtxImm(identity_matrix,GX_IDENTITY,GX_MTX3x4);
626 GX_LoadTexMtxImm(identity_matrix,GX_DTTIDENTITY,GX_MTX3x4);
628 GX_SetViewport(0,0,rmode->fbWidth,rmode->efbHeight,0,1);
629 GX_SetCoPlanar(GX_DISABLE);
630 GX_SetCullMode(GX_CULL_BACK);
631 GX_SetClipMode(GX_CLIP_ENABLE);
633 GX_SetScissor(0,0,rmode->fbWidth,rmode->efbHeight);
634 GX_SetScissorBoxOffset(0,0);
636 GX_SetNumChans(0);
638 GX_SetChanCtrl(GX_COLOR0A0,GX_DISABLE,GX_SRC_REG,GX_SRC_VTX,GX_LIGHTNULL,GX_DF_NONE,GX_AF_NONE);
639 GX_SetChanAmbColor(GX_COLOR0A0,(GXColor)BLACK);
640 GX_SetChanMatColor(GX_COLOR0A0,(GXColor)WHITE);
642 GX_SetChanCtrl(GX_COLOR1A1,GX_DISABLE,GX_SRC_REG,GX_SRC_VTX,GX_LIGHTNULL,GX_DF_NONE,GX_AF_NONE);
643 GX_SetChanAmbColor(GX_COLOR1A1,(GXColor)BLACK);
644 GX_SetChanMatColor(GX_COLOR1A1,(GXColor)WHITE);
646 GX_InvalidateTexAll();
647 GX_SetTexRegionCallback(__GXDefTexRegionCallback);
648 GX_SetTlutRegionCallback(__GXDefTlutRegionCallback);
650 GX_SetTevOrder(GX_TEVSTAGE0,GX_TEXCOORD0,GX_TEXMAP0,GX_COLOR0A0);
651 GX_SetTevOrder(GX_TEVSTAGE1,GX_TEXCOORD1,GX_TEXMAP1,GX_COLOR0A0);
652 GX_SetTevOrder(GX_TEVSTAGE2,GX_TEXCOORD2,GX_TEXMAP2,GX_COLOR0A0);
653 GX_SetTevOrder(GX_TEVSTAGE3,GX_TEXCOORD3,GX_TEXMAP3,GX_COLOR0A0);
654 GX_SetTevOrder(GX_TEVSTAGE4,GX_TEXCOORD4,GX_TEXMAP4,GX_COLOR0A0);
655 GX_SetTevOrder(GX_TEVSTAGE5,GX_TEXCOORD5,GX_TEXMAP5,GX_COLOR0A0);
656 GX_SetTevOrder(GX_TEVSTAGE6,GX_TEXCOORD6,GX_TEXMAP6,GX_COLOR0A0);
657 GX_SetTevOrder(GX_TEVSTAGE7,GX_TEXCOORD7,GX_TEXMAP7,GX_COLOR0A0);
658 GX_SetTevOrder(GX_TEVSTAGE8,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
659 GX_SetTevOrder(GX_TEVSTAGE9,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
660 GX_SetTevOrder(GX_TEVSTAGE10,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
661 GX_SetTevOrder(GX_TEVSTAGE11,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
662 GX_SetTevOrder(GX_TEVSTAGE12,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
663 GX_SetTevOrder(GX_TEVSTAGE13,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
664 GX_SetTevOrder(GX_TEVSTAGE14,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
665 GX_SetTevOrder(GX_TEVSTAGE15,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
666 GX_SetNumTevStages(1);
667 GX_SetTevOp(GX_TEVSTAGE0,GX_REPLACE);
668 GX_SetAlphaCompare(GX_ALWAYS,0,GX_AOP_AND,GX_ALWAYS,0);
669 GX_SetZTexture(GX_ZT_DISABLE,GX_TF_Z8,0);
670 for(i=0;i<GX_MAX_TEVSTAGE;i++) {
671 GX_SetTevKColorSel(i,GX_TEV_KCSEL_1_4);
672 GX_SetTevKAlphaSel(i,GX_TEV_KASEL_1);
673 GX_SetTevSwapMode(i,GX_TEV_SWAP0,GX_TEV_SWAP0);
676 GX_SetTevSwapModeTable(GX_TEV_SWAP0,GX_CH_RED,GX_CH_GREEN,GX_CH_BLUE,GX_CH_ALPHA);
677 GX_SetTevSwapModeTable(GX_TEV_SWAP1,GX_CH_RED,GX_CH_RED,GX_CH_RED,GX_CH_ALPHA);
678 GX_SetTevSwapModeTable(GX_TEV_SWAP2,GX_CH_GREEN,GX_CH_GREEN,GX_CH_GREEN,GX_CH_ALPHA);
679 GX_SetTevSwapModeTable(GX_TEV_SWAP3,GX_CH_BLUE,GX_CH_BLUE,GX_CH_BLUE,GX_CH_ALPHA);
680 for(i=0;i<GX_MAX_TEVSTAGE;i++) {
681 GX_SetTevDirect(i);
684 GX_SetNumIndStages(0);
685 GX_SetIndTexCoordScale(GX_INDTEXSTAGE0,GX_ITS_1,GX_ITS_1);
686 GX_SetIndTexCoordScale(GX_INDTEXSTAGE1,GX_ITS_1,GX_ITS_1);
687 GX_SetIndTexCoordScale(GX_INDTEXSTAGE2,GX_ITS_1,GX_ITS_1);
688 GX_SetIndTexCoordScale(GX_INDTEXSTAGE3,GX_ITS_1,GX_ITS_1);
690 GX_SetFog(GX_FOG_NONE,0,1,0.1,1,(GXColor)BLACK);
691 GX_SetFogRangeAdj(GX_DISABLE,0,NULL);
693 GX_SetBlendMode(GX_BM_NONE,GX_BL_SRCALPHA,GX_BL_INVSRCALPHA,GX_LO_CLEAR);
694 GX_SetColorUpdate(GX_ENABLE);
695 GX_SetAlphaUpdate(GX_ENABLE);
696 GX_SetZMode(GX_ENABLE,GX_LEQUAL,GX_TRUE);
697 GX_SetZCompLoc(GX_TRUE);
698 GX_SetDither(GX_ENABLE);
699 GX_SetDstAlpha(GX_DISABLE,0);
700 GX_SetPixelFmt(GX_PF_RGB8_Z24,GX_ZC_LINEAR);
702 GX_SetFieldMask(GX_ENABLE,GX_ENABLE);
704 flag = 0;
705 if(rmode->viHeight==(rmode->xfbHeight<<1)) flag = 1;
706 GX_SetFieldMode(rmode->field_rendering,flag);
708 GX_SetCopyClear((GXColor)GX_DEFAULT_BG,0x00ffffff);
709 GX_SetDispCopySrc(0,0,rmode->fbWidth,rmode->efbHeight);
710 GX_SetDispCopyDst(rmode->fbWidth,rmode->efbHeight);
711 GX_SetDispCopyYScale(1.0);
712 GX_SetCopyClamp(GX_CLAMP_TOP|GX_CLAMP_BOTTOM);
713 GX_SetCopyFilter(GX_FALSE,NULL,GX_FALSE,NULL);
714 GX_SetDispCopyGamma(GX_GM_1_0);
715 GX_SetDispCopyFrame2Field(GX_COPY_PROGRESSIVE);
716 GX_ClearBoundingBox();
718 GX_PokeColorUpdate(GX_TRUE);
719 GX_PokeAlphaUpdate(GX_TRUE);
720 GX_PokeDither(GX_FALSE);
721 GX_PokeBlendMode(GX_BM_NONE,GX_BL_ZERO,GX_BL_ONE,GX_LO_SET);
722 GX_PokeAlphaMode(GX_ALWAYS,0);
723 GX_PokeAlphaRead(GX_READ_FF);
724 GX_PokeDstAlpha(GX_DISABLE,0);
725 GX_PokeZMode(GX_TRUE,GX_ALWAYS,GX_TRUE);
727 GX_SetGPMetric(GX_PERF0_NONE,GX_PERF1_NONE);
728 GX_ClearGPMetric();
731 static void __GX_FlushTextureState()
733 GX_LOAD_BP_REG(__gx->tevIndMask);
736 static void __GX_XfVtxSpecs()
738 u32 xfvtxspecs = 0;
739 u32 nrms,texs,cols;
741 cols = 0;
742 if(__gx->vcdLo&0x6000) cols++;
743 if(__gx->vcdLo&0x18000) cols++;
745 nrms = 0;
746 if(__gx->vcdNrms==1) nrms = 1;
747 else if(__gx->vcdNrms==2) nrms = 2;
749 texs = 0;
750 if(__gx->vcdHi&0x3) texs++;
751 if(__gx->vcdHi&0xc) texs++;
752 if(__gx->vcdHi&0x30) texs++;
753 if(__gx->vcdHi&0xc0) texs++;
754 if(__gx->vcdHi&0x300) texs++;
755 if(__gx->vcdHi&0xc00) texs++;
756 if(__gx->vcdHi&0x3000) texs++;
757 if(__gx->vcdHi&0xc000) texs++;
759 xfvtxspecs = (_SHIFTL(texs,4,4))|(_SHIFTL(nrms,2,2))|(cols&0x3);
760 GX_LOAD_XF_REG(0x1008,xfvtxspecs);
763 static void __GX_SetMatrixIndex(u32 mtx)
765 if(mtx<5) {
766 GX_LOAD_CP_REG(0x30,__gx->mtxIdxLo);
767 GX_LOAD_XF_REG(0x1018,__gx->mtxIdxLo);
768 } else {
769 GX_LOAD_CP_REG(0x40,__gx->mtxIdxHi);
770 GX_LOAD_XF_REG(0x1019,__gx->mtxIdxHi);
774 static void __GX_SendFlushPrim()
776 u32 tmp,tmp2,cnt;
778 tmp = (__gx->xfFlush*__gx->xfFlushExp);
780 wgPipe->U8 = 0x98;
781 wgPipe->U16 = __gx->xfFlush;
783 tmp2 = (tmp+3)/4;
784 if(tmp>0) {
785 cnt = tmp2/8;
786 while(cnt) {
787 wgPipe->U32 = 0;
788 wgPipe->U32 = 0;
789 wgPipe->U32 = 0;
790 wgPipe->U32 = 0;
791 wgPipe->U32 = 0;
792 wgPipe->U32 = 0;
793 wgPipe->U32 = 0;
794 wgPipe->U32 = 0;
795 cnt--;
797 tmp2 &= 0x0007;
798 if(tmp2) {
799 while(tmp2) {
800 wgPipe->U32 = 0;
801 tmp2--;
805 __gx->xfFlush = 1;
808 static void __GX_SetVCD()
810 GX_LOAD_CP_REG(0x50,__gx->vcdLo);
811 GX_LOAD_CP_REG(0x60,__gx->vcdHi);
812 __GX_XfVtxSpecs();
815 static void __GX_SetVAT()
817 u8 setvtx = 0;
818 s32 i;
820 for(i=0;i<8;i++) {
821 setvtx = (1<<i);
822 if(__gx->VATTable&setvtx) {
823 GX_LOAD_CP_REG((0x70+(i&7)),__gx->VAT0reg[i]);
824 GX_LOAD_CP_REG((0x80+(i&7)),__gx->VAT1reg[i]);
825 GX_LOAD_CP_REG((0x90+(i&7)),__gx->VAT2reg[i]);
828 __gx->VATTable = 0;
831 static void __SetSURegs(u8 texmap,u8 texcoord)
833 u32 reg;
834 u16 wd,ht;
835 u8 wrap_s,wrap_t;
837 wd = __gx->texMapSize[texmap]&0x3ff;
838 ht = _SHIFTR(__gx->texMapSize[texmap],10,10);
839 wrap_s = __gx->texMapWrap[texmap]&3;
840 wrap_t = _SHIFTR(__gx->texMapWrap[texmap],2,2);
842 reg = (texcoord&0x7);
843 __gx->suSsize[reg] = (__gx->suSsize[reg]&~0x0000ffff)|wd;
844 __gx->suTsize[reg] = (__gx->suTsize[reg]&~0x0000ffff)|ht;
845 __gx->suSsize[reg] = (__gx->suSsize[reg]&~0x00010000)|(_SHIFTL(wrap_s,16,1));
846 __gx->suTsize[reg] = (__gx->suTsize[reg]&~0x00010000)|(_SHIFTL(wrap_t,16,1));
848 GX_LOAD_BP_REG(__gx->suSsize[reg]);
849 GX_LOAD_BP_REG(__gx->suTsize[reg]);
852 static void __GX_SetSUTexRegs()
854 u32 i;
855 u32 indtev,dirtev;
856 u8 texcoord,texmap;
857 u32 tevreg,tevm,texcm;
859 dirtev = (_SHIFTR(__gx->genMode,10,4))+1;
860 indtev = _SHIFTR(__gx->genMode,16,3);
862 //indirect texture order
863 for(i=0;i<indtev;i++) {
864 switch(i) {
865 case GX_INDTEXSTAGE0:
866 texmap = __gx->tevRasOrder[2]&7;
867 texcoord = _SHIFTR(__gx->tevRasOrder[2],3,3);
868 break;
869 case GX_INDTEXSTAGE1:
870 texmap = _SHIFTR(__gx->tevRasOrder[2],6,3);
871 texcoord = _SHIFTR(__gx->tevRasOrder[2],9,3);
872 break;
873 case GX_INDTEXSTAGE2:
874 texmap = _SHIFTR(__gx->tevRasOrder[2],12,3);
875 texcoord = _SHIFTR(__gx->tevRasOrder[2],15,3);
876 break;
877 case GX_INDTEXSTAGE3:
878 texmap = _SHIFTR(__gx->tevRasOrder[2],18,3);
879 texcoord = _SHIFTR(__gx->tevRasOrder[2],21,3);
880 break;
881 default:
882 texmap = 0;
883 texcoord = 0;
884 break;
887 texcm = _SHIFTL(1,texcoord,1);
888 if(!(__gx->texCoordManually&texcm))
889 __SetSURegs(texmap,texcoord);
892 //direct texture order
893 for(i=0;i<dirtev;i++) {
894 tevreg = 3+(_SHIFTR(i,1,3));
895 texmap = (__gx->tevTexMap[i]&0xff);
897 if(i&1) texcoord = _SHIFTR(__gx->tevRasOrder[tevreg],15,3);
898 else texcoord = _SHIFTR(__gx->tevRasOrder[tevreg],3,3);
900 tevm = _SHIFTL(1,i,1);
901 texcm = _SHIFTL(1,texcoord,1);
902 if(texmap!=0xff && (__gx->tevTexCoordEnable&tevm) && !(__gx->texCoordManually&texcm)) {
903 __SetSURegs(texmap,texcoord);
908 static void __GX_SetGenMode()
910 GX_LOAD_BP_REG(__gx->genMode);
911 __gx->xfFlush = 0;
914 static void __GX_UpdateBPMask()
916 #if defined(HW_DOL)
917 u32 i;
918 u32 nbmp,nres;
919 u8 ntexmap;
921 nbmp = _SHIFTR(__gx->genMode,16,3);
923 nres = 0;
924 for(i=0;i<nbmp;i++) {
925 switch(i) {
926 case GX_INDTEXSTAGE0:
927 ntexmap = __gx->tevRasOrder[2]&7;
928 break;
929 case GX_INDTEXSTAGE1:
930 ntexmap = _SHIFTR(__gx->tevRasOrder[2],6,3);
931 break;
932 case GX_INDTEXSTAGE2:
933 ntexmap = _SHIFTR(__gx->tevRasOrder[2],12,3);
934 break;
935 case GX_INDTEXSTAGE3:
936 ntexmap = _SHIFTR(__gx->tevRasOrder[2],18,3);
937 break;
938 default:
939 ntexmap = 0;
940 break;
942 nres |= (1<<ntexmap);
945 if((__gx->tevIndMask&0xff)!=nres) {
946 __gx->tevIndMask = (__gx->tevIndMask&~0xff)|(nres&0xff);
947 GX_LOAD_BP_REG(__gx->tevIndMask);
949 #endif
952 static void __GX_SetIndirectMask(u32 mask)
954 __gx->tevIndMask = ((__gx->tevIndMask&~0xff)|(mask&0xff));
955 GX_LOAD_BP_REG(__gx->tevIndMask);
958 static void __GX_SetTexCoordGen()
960 u32 i,mask;
961 u32 texcoord;
963 if(__gx->dirtyState&0x02000000) GX_LOAD_XF_REG(0x103f,(__gx->genMode&0xf));
965 i = 0;
966 texcoord = 0x1040;
967 mask = _SHIFTR(__gx->dirtyState,16,8);
968 while(mask) {
969 if(mask&0x0001) {
970 GX_LOAD_XF_REG(texcoord,__gx->texCoordGen[i]);
971 GX_LOAD_XF_REG((texcoord+0x10),__gx->texCoordGen2[i]);
973 mask >>= 1;
974 texcoord++;
975 i++;
979 static void __GX_SetChanColor()
981 if(__gx->dirtyState&0x0100)
982 GX_LOAD_XF_REG(0x100a,__gx->chnAmbColor[0]);
983 if(__gx->dirtyState&0x0200)
984 GX_LOAD_XF_REG(0x100b,__gx->chnAmbColor[1]);
985 if(__gx->dirtyState&0x0400)
986 GX_LOAD_XF_REG(0x100c,__gx->chnMatColor[0]);
987 if(__gx->dirtyState&0x0800)
988 GX_LOAD_XF_REG(0x100d,__gx->chnMatColor[1]);
991 static void __GX_SetChanCntrl()
993 u32 i,chan,mask;
995 if(__gx->dirtyState&0x01000000) GX_LOAD_XF_REG(0x1009,(_SHIFTR(__gx->genMode,4,3)));
997 i = 0;
998 chan = 0x100e;
999 mask = _SHIFTR(__gx->dirtyState,12,4);
1000 while(mask) {
1001 if(mask&0x0001) GX_LOAD_XF_REG(chan,__gx->chnCntrl[i]);
1003 mask >>= 1;
1004 chan++;
1005 i++;
1009 static void __GX_SetDirtyState()
1011 if(__gx->dirtyState&0x0001) {
1012 __GX_SetSUTexRegs();
1014 if(__gx->dirtyState&0x0002) {
1015 __GX_UpdateBPMask();
1017 if(__gx->dirtyState&0x0004) {
1018 __GX_SetGenMode();
1020 if(__gx->dirtyState&0x0008) {
1021 __GX_SetVCD();
1023 if(__gx->dirtyState&0x0010) {
1024 __GX_SetVAT();
1026 if(__gx->dirtyState&~0xff) {
1027 if(__gx->dirtyState&0x0f00) {
1028 __GX_SetChanColor();
1030 if(__gx->dirtyState&0x0100f000) {
1031 __GX_SetChanCntrl();
1033 if(__gx->dirtyState&0x02ff0000) {
1034 __GX_SetTexCoordGen();
1036 if(__gx->dirtyState&0x04000000) {
1037 __GX_SetMatrixIndex(0);
1038 __GX_SetMatrixIndex(5);
1041 __gx->dirtyState = 0;
1044 static u32 __GX_GetNumXfbLines(u16 efbHeight,u32 yscale)
1046 u32 tmp,tmp1;
1048 tmp = (((efbHeight-1)<<8)/yscale)+1;
1049 if(yscale>128 && yscale<256) {
1050 while(yscale&0x01) yscale >>= 1;
1051 tmp1 = yscale*(efbHeight/yscale);
1052 if(!(efbHeight-tmp1)) tmp++;
1054 if(tmp>1024) tmp = 1024;
1056 return tmp;
1059 GXFifoObj* GX_Init(void *base,u32 size)
1061 s32 i,re0,re1;
1062 #if defined(HW_RVL)
1063 u32 tmem;
1064 #else
1065 u32 tmem_even,tmem_odd;
1066 #endif
1067 u32 divis,res;
1068 u32 divid = TB_BUS_CLOCK;
1069 GXTexRegion *region = NULL;
1070 GXTlutRegion *tregion = NULL;
1072 LWP_InitQueue(&_gxwaitfinish);
1073 SYS_RegisterResetFunc(&__gx_resetinfo);
1075 memset(__gxregs,0,STRUCT_REGDEF_SIZE);
1077 __GX_FifoInit();
1078 GX_InitFifoBase(&_gxfifoobj,base,size);
1079 GX_SetCPUFifo(&_gxfifoobj);
1080 GX_SetGPFifo(&_gxfifoobj);
1081 __GX_PEInit();
1082 EnableWriteGatherPipe();
1084 __gx->gxFifoInited = 1;
1086 __gx->tevIndMask = 0xff;
1087 __gx->tevIndMask = (__gx->tevIndMask&~0xff000000)|(_SHIFTL(0x0f,24,8));
1089 i=0;
1090 re0 = 0xc0;
1091 re1 = 0xc1;
1092 while(i<16) {
1093 __gx->tevColorEnv[i] = (__gx->tevColorEnv[i]&~0xff000000)|(_SHIFTL(re0,24,8));
1094 __gx->tevAlphaEnv[i] = (__gx->tevAlphaEnv[i]&~0xff000000)|(_SHIFTL(re1,24,8));
1095 re0 += 2; re1 += 2; i++;
1098 __gx->texCoordManually = 0;
1099 __gx->dirtyState = 0;
1101 __gx->saveDLctx = 1;
1102 __gx->gxFifoUnlinked = 0;
1104 __gx->sciTLcorner = (__gx->sciTLcorner&~0xff000000)|(_SHIFTL(0x20,24,8));
1105 __gx->sciBRcorner = (__gx->sciBRcorner&~0xff000000)|(_SHIFTL(0x21,24,8));
1106 __gx->lpWidth = (__gx->lpWidth&~0xff000000)|(_SHIFTL(0x22,24,8));
1107 __gx->genMode = (__gx->genMode&~0xff000000)|(_SHIFTL(0x00,24,8));
1109 i=0;
1110 re0 = 0x30;
1111 re1 = 0x31;
1112 while(i<8) {
1113 __gx->suSsize[i] = (__gx->suSsize[i]&~0xff000000)|(_SHIFTL(re0,24,8));
1114 __gx->suTsize[i] = (__gx->suTsize[i]&~0xff000000)|(_SHIFTL(re1,24,8));
1115 re0 += 2; re1 += 2; i++;
1118 __gx->peZMode = (__gx->peZMode&~0xff000000)|(_SHIFTL(0x40,24,8));
1119 __gx->peCMode0 = (__gx->peCMode0&~0xff000000)|(_SHIFTL(0x41,24,8));
1120 __gx->peCMode1 = (__gx->peCMode1&~0xff000000)|(_SHIFTL(0x42,24,8));
1121 __gx->peCntrl = (__gx->peCntrl&~0xff000000)|(_SHIFTL(0x43,24,8));
1123 i=0;
1124 re0 = 0x25;
1125 while(i<11) {
1126 __gx->tevRasOrder[i] = (__gx->tevRasOrder[i]&~0xff000000)|(_SHIFTL(re0,24,8));
1127 re0++; i++;
1130 divis = 500;
1131 res = (u32)(divid/divis);
1132 __GX_FlushTextureState();
1133 GX_LOAD_BP_REG(0x69000000|((_SHIFTR(res,11,24))|0x0400));
1135 divis = 4224;
1136 res = (u32)(res/divis);
1137 __GX_FlushTextureState();
1138 GX_LOAD_BP_REG(0x46000000|(res|0x0200));
1140 i=0;
1141 re0 = 0xf6;
1142 while(i<8) {
1143 __gx->tevSwapModeTable[i] = (__gx->tevSwapModeTable[i]&~0xff000000)|(_SHIFTL(re0,24,8));
1144 re0++; i++;
1147 __gx->tevTexCoordEnable = 0;
1148 __gx->perf0Mode = GX_PERF0_NONE;
1149 __gx->perf1Mode = GX_PERF1_NONE;
1150 __gx->cpPerfMode = 0;
1152 __GX_InitRevBits();
1154 i=0;
1155 while(i<16) {
1156 __gx->tevTexMap[i] = 0xff;
1157 i++;
1160 #if defined(HW_RVL)
1161 i = 0;
1162 while(i<8) {
1163 region = &__gx->texRegion[i];
1164 GX_InitTexCacheRegion(region,GX_FALSE,_gxtexregionaddrtable[i+0],GX_TEXCACHE_32K,_gxtexregionaddrtable[i+8],GX_TEXCACHE_32K);
1166 region = &__gx->texRegion[i+8];
1167 GX_InitTexCacheRegion(region,GX_FALSE,_gxtexregionaddrtable[i+16],GX_TEXCACHE_32K,_gxtexregionaddrtable[i+24],GX_TEXCACHE_32K);
1169 region = &__gx->texRegion[i+16];
1170 GX_InitTexCacheRegion(region,GX_TRUE,_gxtexregionaddrtable[i+32],GX_TEXCACHE_32K,_gxtexregionaddrtable[i+40],GX_TEXCACHE_32K);
1172 i++;
1175 i=0;
1176 while(i<16) {
1177 tmem = 0x000C0000+(i<<13);
1178 tregion = &__gx->tlutRegion[i];
1179 GX_InitTlutRegion(tregion,tmem,GX_TLUT_256);
1180 i++;
1183 i=0;
1184 while(i<4) {
1185 tmem = 0x000E0000+(i<<15);
1186 tregion = &__gx->tlutRegion[i+16];
1187 GX_InitTlutRegion(tregion,tmem,GX_TLUT_1K);
1188 i++;
1190 #else
1191 for(i=0;i<8;i++) {
1192 tmem_even = tmem_odd = (i<<15);
1193 region = &__gx->texRegion[i];
1194 GX_InitTexCacheRegion(region,GX_FALSE,tmem_even,GX_TEXCACHE_32K,(tmem_odd+0x00080000),GX_TEXCACHE_32K);
1196 for(i=0;i<4;i++) {
1197 tmem_even = ((0x08+(i<<1))<<15);
1198 tmem_odd = ((0x09+(i<<1))<<15);
1199 region = &__gx->texRegion[i+8];
1200 GX_InitTexCacheRegion(region,GX_FALSE,tmem_even,GX_TEXCACHE_32K,tmem_odd,GX_TEXCACHE_32K);
1202 for(i=0;i<16;i++) {
1203 tmem_even = (i<<13)+0x000C0000;
1204 tregion = &__gx->tlutRegion[i];
1205 GX_InitTlutRegion(tregion,tmem_even,GX_TLUT_256);
1207 for(i=0;i<4;i++) {
1208 tmem_even = (i<<15)+0x000E0000;
1209 tregion = &__gx->tlutRegion[i+16];
1210 GX_InitTlutRegion(tregion,tmem_even,GX_TLUT_1K);
1212 #endif
1213 _cpReg[3] = 0;
1214 GX_LOAD_CP_REG(0x20,0x00000000);
1215 GX_LOAD_XF_REG(0x1006,0x0);
1217 GX_LOAD_BP_REG(0x23000000);
1218 GX_LOAD_BP_REG(0x24000000);
1219 GX_LOAD_BP_REG(0x67000000);
1221 __GX_SetIndirectMask(0);
1222 #if defined(HW_RVL)
1223 __GX_SetTmemConfig(2);
1224 #else
1225 __GX_SetTmemConfig(0);
1226 #endif
1227 __GX_InitGX();
1229 return &_gxfifoobj;
1232 void GX_InitFifoBase(GXFifoObj *fifo,void *base,u32 size)
1234 struct __gxfifo *ptr = (struct __gxfifo*)fifo;
1236 if(!ptr || size<GX_FIFO_MINSIZE) return;
1238 ptr->buf_start = (u32)base;
1239 ptr->buf_end = (u32)base + size - 4;
1240 ptr->size = size;
1241 ptr->rdwt_dst = 0;
1243 GX_InitFifoLimits(fifo,(size-GX_FIFO_HIWATERMARK),((size>>1)&0x7fffffe0));
1244 GX_InitFifoPtrs(fifo,base,base);
1247 void GX_InitFifoLimits(GXFifoObj *fifo,u32 hiwatermark,u32 lowatermark)
1249 struct __gxfifo *ptr = (struct __gxfifo*)fifo;
1251 ptr->hi_mark = hiwatermark;
1252 ptr->lo_mark = lowatermark;
1255 void GX_InitFifoPtrs(GXFifoObj *fifo,void *rd_ptr,void *wt_ptr)
1257 u32 level;
1258 s32 rdwt_dst;
1259 struct __gxfifo *ptr = (struct __gxfifo*)fifo;
1261 _CPU_ISR_Disable(level);
1262 rdwt_dst = wt_ptr-rd_ptr;
1263 ptr->rd_ptr = (u32)rd_ptr;
1264 ptr->wt_ptr = (u32)wt_ptr;
1265 ptr->rdwt_dst = rdwt_dst;
1266 if(rdwt_dst<0) {
1267 rdwt_dst += ptr->size;
1268 ptr->rd_ptr = rdwt_dst;
1270 _CPU_ISR_Restore(level);
1273 void GX_GetFifoPtrs(GXFifoObj *fifo,void **rd_ptr,void **wt_ptr)
1275 struct __gxfifo *ptr = (struct __gxfifo*)fifo;
1276 *rd_ptr = (void*)ptr->rd_ptr;
1277 *wt_ptr = (void*)ptr->wt_ptr;
1280 void GX_SetCPUFifo(GXFifoObj *fifo)
1282 u32 level;
1283 struct __gxfifo *ptr = (struct __gxfifo*)fifo;
1284 struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
1286 _CPU_ISR_Disable(level);
1287 if(!fifo) {
1288 _gxcpufifoready = 0;
1289 _cpgplinked = 0;
1290 cpufifo->gpfifo_ready = 0;
1291 cpufifo->cpufifo_ready = 0;
1292 _CPU_ISR_Restore(level);
1293 return;
1296 cpufifo->buf_start = ptr->buf_start;
1297 cpufifo->buf_end = ptr->buf_end;
1298 cpufifo->size = ptr->size;
1299 cpufifo->hi_mark = ptr->hi_mark;
1300 cpufifo->lo_mark = ptr->lo_mark;
1301 cpufifo->rd_ptr = ptr->rd_ptr;
1302 cpufifo->wt_ptr = ptr->wt_ptr;
1303 cpufifo->rdwt_dst = ptr->rdwt_dst;
1304 cpufifo->fifo_wrap = ptr->fifo_wrap;
1305 cpufifo->gpfifo_ready = ptr->gpfifo_ready;
1306 cpufifo->cpufifo_ready = 1;
1308 _gxcpufifoready = 1;
1309 if(__GX_CPGPLinkCheck()) {
1310 _cpgplinked = 1;
1311 cpufifo->gpfifo_ready = 1;
1313 _piReg[3] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_start);
1314 _piReg[4] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_end);
1315 _piReg[5] = (cpufifo->wt_ptr&0x1FFFFFE0);
1317 __GX_WriteFifoIntReset(GX_TRUE,GX_TRUE);
1318 __GX_WriteFifoIntEnable(GX_ENABLE,GX_DISABLE);
1319 __GX_FifoLink(GX_TRUE);
1321 _CPU_ISR_Restore(level);
1322 return;
1325 if(_cpgplinked) {
1326 __GX_FifoLink(GX_FALSE);
1327 _cpgplinked = 0;
1330 __GX_WriteFifoIntEnable(GX_DISABLE,GX_DISABLE);
1332 _piReg[3] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_start);
1333 _piReg[4] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_end);
1334 _piReg[5] = (cpufifo->wt_ptr&0x1FFFFFE0);
1335 ppcsync();
1337 _CPU_ISR_Restore(level);
1340 void GX_GetCPUFifo(GXFifoObj *fifo)
1342 struct __gxfifo* ptr = (struct __gxfifo*)fifo;
1343 struct __gxfifo* cpufifo = (struct __gxfifo*)&_cpufifo;
1345 if(!_gxcpufifoready) return;
1347 GX_Flush();
1348 __GX_SaveFifo();
1350 ptr->buf_start = cpufifo->buf_start;
1351 ptr->buf_end = cpufifo->buf_end;
1352 ptr->size = cpufifo->size;
1353 ptr->rd_ptr = cpufifo->rd_ptr;
1354 ptr->wt_ptr = cpufifo->wt_ptr;
1355 ptr->rdwt_dst = cpufifo->rdwt_dst;
1356 ptr->hi_mark = cpufifo->hi_mark;
1357 ptr->lo_mark = cpufifo->lo_mark;
1358 ptr->fifo_wrap = cpufifo->fifo_wrap;
1359 ptr->cpufifo_ready = cpufifo->cpufifo_ready;
1360 ptr->gpfifo_ready = cpufifo->gpfifo_ready;
1363 void GX_SetGPFifo(GXFifoObj *fifo)
1365 u32 level;
1366 struct __gxfifo *ptr = (struct __gxfifo*)fifo;
1367 struct __gxfifo *gpfifo = (struct __gxfifo*)&_gpfifo;
1369 _CPU_ISR_Disable(level);
1370 __GX_FifoReadDisable();
1371 __GX_WriteFifoIntEnable(GX_DISABLE,GX_DISABLE);
1373 if(!fifo) {
1374 _gxgpfifoready = 0;
1375 _cpgplinked = 0;
1376 gpfifo->cpufifo_ready = 0;
1377 gpfifo->gpfifo_ready = 0;
1378 __GX_FifoLink(GX_FALSE);
1379 _CPU_ISR_Restore(level);
1380 return;
1383 gpfifo->buf_start = ptr->buf_start;
1384 gpfifo->buf_end = ptr->buf_end;
1385 gpfifo->size = ptr->size;
1386 gpfifo->hi_mark = ptr->hi_mark;
1387 gpfifo->lo_mark = ptr->lo_mark;
1388 gpfifo->rd_ptr = ptr->rd_ptr;
1389 gpfifo->wt_ptr = ptr->wt_ptr;
1390 gpfifo->rdwt_dst = ptr->rdwt_dst;
1391 gpfifo->fifo_wrap = ptr->fifo_wrap;
1392 gpfifo->cpufifo_ready = ptr->cpufifo_ready;
1393 gpfifo->gpfifo_ready = 1;
1394 _gxgpfifoready = 1;
1396 /* setup fifo base */
1397 _cpReg[16] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->buf_start),0,16);
1398 _cpReg[17] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->buf_start),16,16);
1400 /* setup fifo end */
1401 _cpReg[18] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->buf_end),0,16);
1402 _cpReg[19] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->buf_end),16,16);
1404 /* setup hiwater mark */
1405 _cpReg[20] = _SHIFTL(gpfifo->hi_mark,0,16);
1406 _cpReg[21] = _SHIFTR(gpfifo->hi_mark,16,16);
1408 /* setup lowater mark */
1409 _cpReg[22] = _SHIFTL(gpfifo->lo_mark,0,16);
1410 _cpReg[23] = _SHIFTR(gpfifo->lo_mark,16,16);
1412 /* setup rd<->wd dist */
1413 _cpReg[24] = _SHIFTL(gpfifo->rdwt_dst,0,16);
1414 _cpReg[25] = _SHIFTR(gpfifo->rdwt_dst,16,16);
1416 /* setup wt ptr */
1417 _cpReg[26] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->wt_ptr),0,16);
1418 _cpReg[27] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->wt_ptr),16,16);
1420 /* setup rd ptr */
1421 _cpReg[28] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->rd_ptr),0,16);
1422 _cpReg[29] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->rd_ptr),16,16);
1423 ppcsync();
1425 if(__GX_CPGPLinkCheck()) {
1426 _cpgplinked = 1;
1427 gpfifo->cpufifo_ready = 1;
1428 __GX_WriteFifoIntEnable(GX_ENABLE,GX_DISABLE);
1429 __GX_FifoLink(GX_TRUE);
1430 } else {
1431 _cpgplinked = 0;
1432 gpfifo->cpufifo_ready = 0;
1433 __GX_WriteFifoIntEnable(GX_DISABLE,GX_DISABLE);
1434 __GX_FifoLink(GX_FALSE);
1437 __GX_WriteFifoIntReset(GX_TRUE,GX_TRUE);
1438 __GX_FifoReadEnable();
1439 _CPU_ISR_Restore(level);
1442 void GX_GetGPFifo(GXFifoObj *fifo)
1444 struct __gxfifo* ptr = (struct __gxfifo*)fifo;
1445 struct __gxfifo* gpfifo = (struct __gxfifo*)&_gpfifo;
1447 if(!_gxgpfifoready) return;
1449 __GX_SaveFifo();
1451 ptr->buf_start = gpfifo->buf_start;
1452 ptr->buf_end = gpfifo->buf_end;
1453 ptr->size = gpfifo->size;
1454 ptr->rd_ptr = gpfifo->rd_ptr;
1455 ptr->wt_ptr = gpfifo->wt_ptr;
1456 ptr->rdwt_dst = gpfifo->rdwt_dst;
1457 ptr->hi_mark = gpfifo->hi_mark;
1458 ptr->lo_mark = gpfifo->lo_mark;
1459 ptr->fifo_wrap = gpfifo->fifo_wrap;
1460 ptr->gpfifo_ready = gpfifo->gpfifo_ready;
1461 ptr->cpufifo_ready = gpfifo->cpufifo_ready;
1464 void* GX_GetFifoBase(GXFifoObj *fifo)
1466 return (void*)((struct __gxfifo*)fifo)->buf_start;
1469 u32 GX_GetFifoSize(GXFifoObj *fifo)
1471 return ((struct __gxfifo*)fifo)->size;
1474 u32 GX_GetFifoCount(GXFifoObj *fifo)
1476 return ((struct __gxfifo*)fifo)->rdwt_dst;
1479 u8 GX_GetFifoWrap(GXFifoObj *fifo)
1481 return ((struct __gxfifo*)fifo)->fifo_wrap;
1484 u32 GX_GetOverflowCount()
1486 return _gxoverflowcount;
1489 u32 GX_ResetOverflowCount()
1491 u32 ret = _gxoverflowcount;
1492 _gxoverflowcount = 0;
1493 return ret;
1496 lwp_t GX_GetCurrentGXThread()
1498 return _gxcurrentlwp;
1501 lwp_t GX_SetCurrentGXThread()
1503 u32 level;
1505 _CPU_ISR_Disable(level);
1506 lwp_t ret = _gxcurrentlwp;
1507 _gxcurrentlwp = LWP_GetSelf();
1508 _CPU_ISR_Restore(level);
1510 return ret;
1513 volatile void* GX_RedirectWriteGatherPipe(void *ptr)
1515 u32 level;
1516 struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
1518 _CPU_ISR_Disable(level);
1519 GX_Flush();
1520 while(!IsWriteGatherBufferEmpty());
1522 mtwpar(0x0C008000);
1523 if(_cpgplinked) {
1524 __GX_FifoLink(GX_FALSE);
1525 __GX_WriteFifoIntEnable(GX_DISABLE,GX_DISABLE);
1527 cpufifo->wt_ptr = (u32)MEM_PHYSICAL_TO_K0(_piReg[5]&~0x04000000);
1529 _piReg[3] = 0;
1530 _piReg[4] = 0x04000000;
1531 _piReg[5] = (((u32)ptr&0x3FFFFFE0)&~0x04000000);
1532 _sync();
1534 _CPU_ISR_Restore(level);
1536 return (volatile void*)0x0C008000;
1539 void GX_RestoreWriteGatherPipe()
1541 u32 level;
1542 struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
1544 _CPU_ISR_Disable(level);
1546 wgPipe->U32 = 0;
1547 wgPipe->U32 = 0;
1548 wgPipe->U32 = 0;
1549 wgPipe->U32 = 0;
1550 wgPipe->U32 = 0;
1551 wgPipe->U32 = 0;
1552 wgPipe->U32 = 0;
1553 wgPipe->U32 = 0;
1555 ppcsync();
1556 while(!IsWriteGatherBufferEmpty());
1558 mtwpar(0x0C008000);
1559 _piReg[3] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_start);
1560 _piReg[4] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_end);
1561 _piReg[5] = (((u32)cpufifo->wt_ptr&0x3FFFFFE0)&~0x04000000);
1562 if(_cpgplinked) {
1563 __GX_WriteFifoIntReset(GX_TRUE,GX_TRUE);
1564 __GX_WriteFifoIntEnable(GX_ENABLE,GX_DISABLE);
1565 __GX_FifoLink(GX_TRUE);
1567 _CPU_ISR_Restore(level);
1570 void GX_Flush()
1572 if(__gx->dirtyState)
1573 __GX_SetDirtyState();
1575 wgPipe->U32 = 0;
1576 wgPipe->U32 = 0;
1577 wgPipe->U32 = 0;
1578 wgPipe->U32 = 0;
1579 wgPipe->U32 = 0;
1580 wgPipe->U32 = 0;
1581 wgPipe->U32 = 0;
1582 wgPipe->U32 = 0;
1584 ppcsync();
1587 void GX_EnableBreakPt(void *break_pt)
1589 u32 level = 0;
1590 _CPU_ISR_Disable(level);
1591 __GX_FifoReadDisable();
1592 _cpReg[30] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(break_pt),0,16);
1593 _cpReg[31] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(break_pt),16,16);
1594 __gx->cpCRreg = (__gx->cpCRreg&~0x22)|0x22;
1595 _cpReg[1] = __gx->cpCRreg;
1596 _gxcurrbp = break_pt;
1597 __GX_FifoReadEnable();
1598 _CPU_ISR_Restore(level);
1601 void GX_DisableBreakPt()
1603 u32 level = 0;
1604 _CPU_ISR_Disable(level);
1605 __gx->cpCRreg = (__gx->cpCRreg&~0x22);
1606 _cpReg[1] = __gx->cpCRreg;
1607 _gxcurrbp = NULL;
1608 _CPU_ISR_Restore(level);
1611 #if defined(HW_DOL)
1612 void GX_AbortFrame()
1614 _piReg[6] = 1;
1615 __GX_WaitAbort(50);
1616 _piReg[6] = 0;
1617 __GX_WaitAbort(5);
1619 if(__GX_IsGPFifoReady())
1620 __GX_CleanGPFifo();
1622 #elif defined(HW_RVL)
1623 void GX_AbortFrame()
1625 __GX_Abort();
1626 if(__GX_IsGPFifoReady()) {
1627 __GX_CleanGPFifo();
1628 __GX_InitRevBits();
1630 __gx->dirtyState = 0;
1631 GX_Flush();
1634 #endif
1636 void GX_SetDrawSync(u16 token)
1638 u32 level = 0;
1639 _CPU_ISR_Disable(level);
1640 GX_LOAD_BP_REG(0x48000000 | token);
1641 GX_LOAD_BP_REG(0x47000000 | token);
1642 GX_Flush();
1643 _CPU_ISR_Restore(level);
1646 u16 GX_GetDrawSync()
1648 return _peReg[7];
1651 void GX_SetDrawDone()
1653 u32 level;
1654 _CPU_ISR_Disable(level);
1655 GX_LOAD_BP_REG(0x45000002); // set draw done!
1656 GX_Flush();
1657 _gxfinished = 0;
1658 _CPU_ISR_Restore(level);
1662 void GX_WaitDrawDone()
1664 u32 level;
1665 #ifdef _GP_DEBUG
1666 printf("GX_WaitDrawDone()\n\n");
1667 #endif
1668 _CPU_ISR_Disable(level);
1669 while(!_gxfinished)
1670 LWP_ThreadSleep(_gxwaitfinish);
1671 _CPU_ISR_Restore(level);
1674 void GX_DrawDone()
1676 u32 level;
1678 _CPU_ISR_Disable(level);
1679 GX_LOAD_BP_REG(0x45000002); // set draw done!
1680 GX_Flush();
1682 _gxfinished = 0;
1683 _CPU_ISR_Flash(level);
1685 while(!_gxfinished)
1686 LWP_ThreadSleep(_gxwaitfinish);
1687 _CPU_ISR_Restore(level);
1690 GXDrawDoneCallback GX_SetDrawDoneCallback(GXDrawDoneCallback cb)
1692 u32 level;
1694 _CPU_ISR_Disable(level);
1695 GXDrawDoneCallback ret = drawDoneCB;
1696 drawDoneCB = cb;
1697 _CPU_ISR_Restore(level);
1698 return ret;
1701 GXDrawSyncCallback GX_SetDrawSyncCallback(GXDrawSyncCallback cb)
1703 u32 level;
1705 _CPU_ISR_Disable(level);
1706 GXDrawSyncCallback ret = tokenCB;
1707 tokenCB = cb;
1708 _CPU_ISR_Restore(level);
1709 return ret;
1712 GXBreakPtCallback GX_SetBreakPtCallback(GXBreakPtCallback cb)
1714 u32 level;
1716 _CPU_ISR_Disable(level);
1717 GXBreakPtCallback ret = breakPtCB;
1718 breakPtCB = cb;
1719 _CPU_ISR_Restore(level);
1720 return ret;
1723 void GX_PixModeSync()
1725 GX_LOAD_BP_REG(__gx->peCntrl);
1728 void GX_TexModeSync()
1730 GX_LOAD_BP_REG(0x63000000);
1733 void GX_SetMisc(u32 token,u32 value)
1735 u32 cnt;
1737 if(token==GX_MT_XF_FLUSH) {
1738 __gx->xfFlushSafe = value;
1739 cnt = cntlzw(__gx->xfFlushSafe);
1740 __gx->xfFlushExp = _SHIFTR(cnt,5,16);
1742 __gx->xfFlush = 1;
1743 if(!__gx->xfFlushSafe) return;
1745 __gx->dirtyState |= 0x0008;
1746 } else if(token==GX_MT_DL_SAVE_CTX) {
1747 __gx->saveDLctx = (value&0xff);
1749 return;
1752 void GX_SetViewportJitter(f32 xOrig,f32 yOrig,f32 wd,f32 ht,f32 nearZ,f32 farZ,u32 field)
1754 f32 x0,y0,x1,y1,n,f,z;
1755 static f32 Xfactor = 0.5;
1756 static f32 Yfactor = 342.0;
1757 static f32 Zfactor = 16777215.0;
1759 if(!field) yOrig -= Xfactor;
1761 x0 = wd*Xfactor;
1762 y0 = (-ht)*Xfactor;
1763 x1 = (xOrig+(wd*Xfactor))+Yfactor;
1764 y1 = (yOrig+(ht*Xfactor))+Yfactor;
1765 n = Zfactor*nearZ;
1766 f = Zfactor*farZ;
1767 z = f-n;
1769 GX_LOAD_XF_REGS(0x101a,6);
1770 wgPipe->F32 = x0;
1771 wgPipe->F32 = y0;
1772 wgPipe->F32 = z;
1773 wgPipe->F32 = x1;
1774 wgPipe->F32 = y1;
1775 wgPipe->F32 = f;
1778 void GX_SetViewport(f32 xOrig,f32 yOrig,f32 wd,f32 ht,f32 nearZ,f32 farZ)
1780 GX_SetViewportJitter(xOrig,yOrig,wd,ht,nearZ,farZ,1);
1783 void GX_LoadProjectionMtx(Mtx44 mt,u8 type)
1785 f32 tmp[7];
1787 ((u32*)((void*)tmp))[6] = (u32)type;
1788 tmp[0] = mt[0][0];
1789 tmp[2] = mt[1][1];
1790 tmp[4] = mt[2][2];
1791 tmp[5] = mt[2][3];
1793 switch(type) {
1794 case GX_PERSPECTIVE:
1795 tmp[1] = mt[0][2];
1796 tmp[3] = mt[1][2];
1797 break;
1798 case GX_ORTHOGRAPHIC:
1799 tmp[1] = mt[0][3];
1800 tmp[3] = mt[1][3];
1801 break;
1804 GX_LOAD_XF_REGS(0x1020,7);
1805 wgPipe->F32 = tmp[0];
1806 wgPipe->F32 = tmp[1];
1807 wgPipe->F32 = tmp[2];
1808 wgPipe->F32 = tmp[3];
1809 wgPipe->F32 = tmp[4];
1810 wgPipe->F32 = tmp[5];
1811 wgPipe->F32 = tmp[6];
1814 static void __GetImageTileCount(u32 fmt,u16 wd,u16 ht,u32 *xtiles,u32 *ytiles,u32 *zplanes)
1816 u32 xshift,yshift,tile;
1818 switch(fmt) {
1819 case GX_TF_I4:
1820 case GX_TF_IA4:
1821 case GX_CTF_R4:
1822 case GX_CTF_RA4:
1823 case GX_CTF_Z4:
1824 xshift = 3;
1825 yshift = 3;
1826 break;
1827 case GX_TF_Z8:
1828 case GX_TF_I8:
1829 case GX_TF_IA8:
1830 case GX_CTF_RA8:
1831 case GX_CTF_A8:
1832 case GX_CTF_R8:
1833 case GX_CTF_G8:
1834 case GX_CTF_B8:
1835 case GX_CTF_RG8:
1836 case GX_CTF_GB8:
1837 case GX_CTF_Z8M:
1838 case GX_CTF_Z8L:
1839 xshift = 3;
1840 yshift = 2;
1841 break;
1842 case GX_TF_Z16:
1843 case GX_TF_Z24X8:
1844 case GX_CTF_Z16L:
1845 case GX_TF_RGB565:
1846 case GX_TF_RGB5A3:
1847 case GX_TF_RGBA8:
1848 xshift = 2;
1849 yshift = 2;
1850 break;
1851 default:
1852 xshift = 0;
1853 yshift = 0;
1854 break;
1857 if(!(wd&0xffff)) wd = 1;
1858 if(!(ht&0xffff)) ht = 1;
1860 wd &= 0xffff;
1861 tile = (wd+((1<<xshift)-1))>>xshift;
1862 *xtiles = tile;
1864 ht &= 0xffff;
1865 tile = (ht+((1<<yshift)-1))>>yshift;
1866 *ytiles = tile;
1868 *zplanes = 1;
1869 if(fmt==GX_TF_RGBA8 || fmt==GX_TF_Z24X8) *zplanes = 2;
1872 void GX_SetCopyClear(GXColor color,u32 zvalue)
1874 u32 val;
1876 val = (_SHIFTL(color.a,8,8))|(color.r&0xff);
1877 GX_LOAD_BP_REG(0x4f000000|val);
1879 val = (_SHIFTL(color.g,8,8))|(color.b&0xff);
1880 GX_LOAD_BP_REG(0x50000000|val);
1882 val = zvalue&0x00ffffff;
1883 GX_LOAD_BP_REG(0x51000000|val);
1886 void GX_SetCopyClamp(u8 clamp)
1888 __gx->dispCopyCntrl = (__gx->dispCopyCntrl&~1)|(clamp&1);
1889 __gx->dispCopyCntrl = (__gx->dispCopyCntrl&~2)|(clamp&2);
1892 void GX_SetDispCopyGamma(u8 gamma)
1894 __gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0x180)|(_SHIFTL(gamma,7,2));
1897 void GX_SetCopyFilter(u8 aa,u8 sample_pattern[12][2],u8 vf,u8 vfilter[7])
1899 u32 reg01=0,reg02=0,reg03=0,reg04=0,reg53=0,reg54=0;
1901 if(aa) {
1902 reg01 = sample_pattern[0][0]&0xf;
1903 reg01 = (reg01&~0xf0)|(_SHIFTL(sample_pattern[0][1],4,4));
1904 reg01 = (reg01&~0xf00)|(_SHIFTL(sample_pattern[1][0],8,4));
1905 reg01 = (reg01&~0xf000)|(_SHIFTL(sample_pattern[1][1],12,4));
1906 reg01 = (reg01&~0xf0000)|(_SHIFTL(sample_pattern[2][0],16,4));
1907 reg01 = (reg01&~0xf00000)|(_SHIFTL(sample_pattern[2][1],20,4));
1908 reg01 = (reg01&~0xff000000)|(_SHIFTL(0x01,24,8));
1910 reg02 = sample_pattern[3][0]&0xf;
1911 reg02 = (reg02&~0xf0)|(_SHIFTL(sample_pattern[3][1],4,4));
1912 reg02 = (reg02&~0xf00)|(_SHIFTL(sample_pattern[4][0],8,4));
1913 reg02 = (reg02&~0xf000)|(_SHIFTL(sample_pattern[4][1],12,4));
1914 reg02 = (reg02&~0xf0000)|(_SHIFTL(sample_pattern[5][0],16,4));
1915 reg02 = (reg02&~0xf00000)|(_SHIFTL(sample_pattern[5][1],20,4));
1916 reg02 = (reg02&~0xff000000)|(_SHIFTL(0x02,24,8));
1918 reg03 = sample_pattern[6][0]&0xf;
1919 reg03 = (reg03&~0xf0)|(_SHIFTL(sample_pattern[6][1],4,4));
1920 reg03 = (reg03&~0xf00)|(_SHIFTL(sample_pattern[7][0],8,4));
1921 reg03 = (reg03&~0xf000)|(_SHIFTL(sample_pattern[7][1],12,4));
1922 reg03 = (reg03&~0xf0000)|(_SHIFTL(sample_pattern[8][0],16,4));
1923 reg03 = (reg03&~0xf00000)|(_SHIFTL(sample_pattern[8][1],20,4));
1924 reg03 = (reg03&~0xff000000)|(_SHIFTL(0x03,24,8));
1926 reg04 = sample_pattern[9][0]&0xf;
1927 reg04 = (reg04&~0xf0)|(_SHIFTL(sample_pattern[9][1],4,4));
1928 reg04 = (reg04&~0xf00)|(_SHIFTL(sample_pattern[10][0],8,4));
1929 reg04 = (reg04&~0xf000)|(_SHIFTL(sample_pattern[10][1],12,4));
1930 reg04 = (reg04&~0xf0000)|(_SHIFTL(sample_pattern[11][0],16,4));
1931 reg04 = (reg04&~0xf00000)|(_SHIFTL(sample_pattern[11][1],20,4));
1932 reg04 = (reg04&~0xff000000)|(_SHIFTL(0x04,24,8));
1933 } else {
1934 reg01 = 0x01666666;
1935 reg02 = 0x02666666;
1936 reg03 = 0x03666666;
1937 reg04 = 0x04666666;
1939 GX_LOAD_BP_REG(reg01);
1940 GX_LOAD_BP_REG(reg02);
1941 GX_LOAD_BP_REG(reg03);
1942 GX_LOAD_BP_REG(reg04);
1944 reg53 = 0x53595000;
1945 reg54 = 0x54000015;
1946 if(vf) {
1947 reg53 = 0x53000000|(vfilter[0]&0x3f);
1948 reg53 = (reg53&~0xfc0)|(_SHIFTL(vfilter[1],6,6));
1949 reg53 = (reg53&~0x3f000)|(_SHIFTL(vfilter[2],12,6));
1950 reg53 = (reg53&~0xfc0000)|(_SHIFTL(vfilter[3],18,6));
1952 reg54 = 0x54000000|(vfilter[4]&0x3f);
1953 reg54 = (reg54&~0xfc0)|(_SHIFTL(vfilter[5],6,6));
1954 reg54 = (reg54&~0x3f000)|(_SHIFTL(vfilter[6],12,6));
1956 GX_LOAD_BP_REG(reg53);
1957 GX_LOAD_BP_REG(reg54);
1960 void GX_SetDispCopyFrame2Field(u8 mode)
1962 __gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0x3000)|(_SHIFTL(mode,12,2));
1965 u32 GX_SetDispCopyYScale(f32 yscale)
1967 u32 ht,yScale = 0;
1969 yScale = ((u32)(256.0f/yscale))&0x1ff;
1970 GX_LOAD_BP_REG(0x4e000000|yScale);
1972 __gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0x400)|(_SHIFTL(((256-yScale)>0),10,1));
1973 ht = _SHIFTR(__gx->dispCopyWH,12,10)+1;
1974 return __GX_GetNumXfbLines(ht,yScale);
1977 void GX_SetDispCopyDst(u16 wd,u16 ht)
1979 __gx->dispCopyDst = (__gx->dispCopyDst&~0x3ff)|(_SHIFTR(wd,4,10));
1980 __gx->dispCopyDst = (__gx->dispCopyDst&~0xff000000)|(_SHIFTL(0x4d,24,8));
1983 void GX_SetDispCopySrc(u16 left,u16 top,u16 wd,u16 ht)
1985 __gx->dispCopyTL = (__gx->dispCopyTL&~0x00ffffff)|XY(left,top);
1986 __gx->dispCopyTL = (__gx->dispCopyTL&~0xff000000)|(_SHIFTL(0x49,24,8));
1987 __gx->dispCopyWH = (__gx->dispCopyWH&~0x00ffffff)|XY((wd-1),(ht-1));
1988 __gx->dispCopyWH = (__gx->dispCopyWH&~0xff000000)|(_SHIFTL(0x4a,24,8));
1991 void GX_CopyDisp(void *dest,u8 clear)
1993 u8 clflag;
1994 u32 val;
1996 if(clear) {
1997 val= (__gx->peZMode&~0xf)|0xf;
1998 GX_LOAD_BP_REG(val);
1999 val = (__gx->peCMode0&~0x3);
2000 GX_LOAD_BP_REG(val);
2003 clflag = 0;
2004 if(clear || (__gx->peCntrl&0x7)==0x0003) {
2005 if(__gx->peCntrl&0x40) {
2006 clflag = 1;
2007 val = (__gx->peCntrl&~0x40);
2008 GX_LOAD_BP_REG(val);
2012 GX_LOAD_BP_REG(__gx->dispCopyTL); // set source top
2013 GX_LOAD_BP_REG(__gx->dispCopyWH);
2015 GX_LOAD_BP_REG(__gx->dispCopyDst);
2017 val = 0x4b000000|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(dest),5,24));
2018 GX_LOAD_BP_REG(val);
2020 __gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0x800)|(_SHIFTL(clear,11,1));
2021 __gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0x4000)|0x4000;
2022 __gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0xff000000)|(_SHIFTL(0x52,24,8));
2024 GX_LOAD_BP_REG(__gx->dispCopyCntrl);
2026 if(clear) {
2027 GX_LOAD_BP_REG(__gx->peZMode);
2028 GX_LOAD_BP_REG(__gx->peCMode0);
2030 if(clflag) GX_LOAD_BP_REG(__gx->peCntrl);
2033 void GX_CopyTex(void *dest,u8 clear)
2035 u8 clflag;
2036 u32 val;
2038 if(clear) {
2039 val = (__gx->peZMode&~0xf)|0xf;
2040 GX_LOAD_BP_REG(val);
2041 val = (__gx->peCMode0&~0x3);
2042 GX_LOAD_BP_REG(val);
2045 clflag = 0;
2046 val = __gx->peCntrl;
2047 if(__gx->texCopyZTex && (val&0x7)!=0x0003) {
2048 clflag = 1;
2049 val = (val&~0x7)|0x0003;
2051 if(clear || (val&0x7)==0x0003) {
2052 if(val&0x40) {
2053 clflag = 1;
2054 val = (val&~0x40);
2057 if(clflag) GX_LOAD_BP_REG(val);
2059 val = 0x4b000000|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(dest),5,24));
2061 GX_LOAD_BP_REG(__gx->texCopyTL);
2062 GX_LOAD_BP_REG(__gx->texCopyWH);
2063 GX_LOAD_BP_REG(__gx->texCopyDst);
2064 GX_LOAD_BP_REG(val);
2066 __gx->texCopyCntrl = (__gx->texCopyCntrl&~0x800)|(_SHIFTL(clear,11,1));
2067 __gx->texCopyCntrl = (__gx->texCopyCntrl&~0x4000);
2068 __gx->texCopyCntrl = (__gx->texCopyCntrl&~0xff000000)|(_SHIFTL(0x52,24,8));
2069 GX_LOAD_BP_REG(__gx->texCopyCntrl);
2071 if(clear) {
2072 GX_LOAD_BP_REG(__gx->peZMode);
2073 GX_LOAD_BP_REG(__gx->peCMode0);
2075 if(clflag) GX_LOAD_BP_REG(__gx->peCntrl);
2078 void GX_SetTexCopySrc(u16 left,u16 top,u16 wd,u16 ht)
2080 __gx->texCopyTL = (__gx->texCopyTL&~0x00ffffff)|XY(left,top);
2081 __gx->texCopyTL = (__gx->texCopyTL&~0xff000000)|(_SHIFTL(0x49,24,8));
2082 __gx->texCopyWH = (__gx->texCopyWH&~0x00ffffff)|XY((wd-1),(ht-1));
2083 __gx->texCopyWH = (__gx->texCopyWH&~0xff000000)|(_SHIFTL(0x4a,24,8));
2086 void GX_SetTexCopyDst(u16 wd,u16 ht,u32 fmt,u8 mipmap)
2088 u8 lfmt = fmt&0xf;
2089 u32 xtiles,ytiles,zplanes;
2091 __GetImageTileCount(fmt,wd,ht,&xtiles,&ytiles,&zplanes);
2092 __gx->texCopyDst = (__gx->texCopyDst&~0x3ff)|((xtiles*zplanes)&0x3ff);
2094 if(fmt==GX_TF_Z16) lfmt = 11;
2095 if(fmt==GX_CTF_YUVA8 || (fmt>=GX_TF_I4 && fmt<GX_TF_RGB565)) __gx->texCopyCntrl = (__gx->texCopyCntrl&~0x18000)|0x18000;
2096 else __gx->texCopyCntrl = (__gx->texCopyCntrl&~0x18000)|0x10000;
2098 __gx->texCopyCntrl = (__gx->texCopyCntrl&~0x8)|(lfmt&0x8);
2099 __gx->texCopyCntrl = (__gx->texCopyCntrl&~0x200)|(_SHIFTL(mipmap,9,1));
2100 __gx->texCopyCntrl = (__gx->texCopyCntrl&~0x70)|(_SHIFTL(lfmt,4,3));
2102 __gx->texCopyDst = (__gx->texCopyDst&~0xff000000)|(_SHIFTL(0x4d,24,8));
2104 __gx->texCopyZTex = ((fmt&_GX_TF_ZTF)==_GX_TF_ZTF);
2107 void GX_ClearBoundingBox()
2109 GX_LOAD_BP_REG(0x550003ff);
2110 GX_LOAD_BP_REG(0x560003ff);
2113 void GX_BeginDispList(void *list,u32 size)
2115 struct __gxfifo *fifo;
2117 if(__gx->dirtyState)
2118 __GX_SetDirtyState();
2120 if(__gx->saveDLctx)
2121 memcpy(_gx_saved_data,__gxregs,STRUCT_REGDEF_SIZE);
2123 fifo = (struct __gxfifo*)&_gx_dl_fifoobj;
2124 fifo->buf_start = (u32)list;
2125 fifo->buf_end = (u32)list + size - 4;
2126 fifo->size = size;
2128 fifo->rd_ptr = (u32)list;
2129 fifo->wt_ptr = (u32)list;
2130 fifo->rdwt_dst = 0;
2132 __gx->gxFifoUnlinked = 1;
2134 GX_GetCPUFifo(&_gx_old_cpufifo);
2135 GX_SetCPUFifo(&_gx_dl_fifoobj);
2136 __GX_ResetWriteGatherPipe();
2139 u32 GX_EndDispList()
2141 u32 level;
2142 u8 wrap = 0;
2144 GX_GetCPUFifo(&_gx_dl_fifoobj);
2145 GX_SetCPUFifo(&_gx_old_cpufifo);
2147 if(__gx->saveDLctx) {
2148 _CPU_ISR_Disable(level);
2149 memcpy(__gxregs,_gx_saved_data,STRUCT_REGDEF_SIZE);
2150 _CPU_ISR_Restore(level);
2153 __gx->gxFifoUnlinked = 0;
2155 wrap = GX_GetFifoWrap(&_gx_dl_fifoobj);
2156 if(wrap) return 0;
2158 return GX_GetFifoCount(&_gx_dl_fifoobj);
2161 void GX_CallDispList(void *list,u32 nbytes)
2163 if(__gx->dirtyState)
2164 __GX_SetDirtyState();
2166 if(!__gx->vcdClear)
2167 __GX_SendFlushPrim();
2169 wgPipe->U8 = 0x40; //call displaylist
2170 wgPipe->U32 = MEM_VIRTUAL_TO_PHYSICAL(list);
2171 wgPipe->U32 = nbytes;
2174 void GX_SetChanCtrl(s32 channel,u8 enable,u8 ambsrc,u8 matsrc,u8 litmask,u8 diff_fn,u8 attn_fn)
2176 u32 reg,difffn = (attn_fn==GX_AF_SPEC)?GX_DF_NONE:diff_fn;
2177 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));
2179 reg = (channel&0x03);
2180 __gx->chnCntrl[reg] = val;
2181 __gx->dirtyState |= (0x1000<<reg);
2183 if(channel==GX_COLOR0A0) {
2184 __gx->chnCntrl[2] = val;
2185 __gx->dirtyState |= 0x5000;
2186 } else {
2187 __gx->chnCntrl[3] = val;
2188 __gx->dirtyState |= 0xa000;
2192 void GX_SetChanAmbColor(s32 channel,GXColor color)
2194 u32 reg,val = (_SHIFTL(color.r,24,8))|(_SHIFTL(color.g,16,8))|(_SHIFTL(color.b,8,8))|0x00;
2195 switch(channel) {
2196 case GX_COLOR0:
2197 reg = 0;
2198 val |= (__gx->chnAmbColor[0]&0xff);
2199 break;
2200 case GX_COLOR1:
2201 reg = 1;
2202 val |= (__gx->chnAmbColor[1]&0xff);
2203 break;
2204 case GX_ALPHA0:
2205 reg = 0;
2206 val = ((__gx->chnAmbColor[0]&~0xff)|(color.a&0xff));
2207 break;
2208 case GX_ALPHA1:
2209 reg = 1;
2210 val = ((__gx->chnAmbColor[1]&~0xff)|(color.a&0xff));
2211 break;
2212 case GX_COLOR0A0:
2213 reg = 0;
2214 val |= (color.a&0xFF);
2215 break;
2216 case GX_COLOR1A1:
2217 reg = 1;
2218 val |= (color.a&0xFF);
2219 break;
2220 default:
2221 return;
2224 __gx->chnAmbColor[reg] = val;
2225 __gx->dirtyState |= (0x0100<<reg);
2228 void GX_SetChanMatColor(s32 channel,GXColor color)
2230 u32 reg,val = (_SHIFTL(color.r,24,8))|(_SHIFTL(color.g,16,8))|(_SHIFTL(color.b,8,8))|0x00;
2231 switch(channel) {
2232 case GX_COLOR0:
2233 reg = 0;
2234 val |= (__gx->chnMatColor[0]&0xff);
2235 break;
2236 case GX_COLOR1:
2237 reg = 1;
2238 val |= (__gx->chnMatColor[1]&0xff);
2239 break;
2240 case GX_ALPHA0:
2241 reg = 0;
2242 val = ((__gx->chnMatColor[0]&~0xff)|(color.a&0xff));
2243 break;
2244 case GX_ALPHA1:
2245 reg = 1;
2246 val = ((__gx->chnMatColor[1]&~0xff)|(color.a&0xff));
2247 break;
2248 case GX_COLOR0A0:
2249 reg = 0;
2250 val |= (color.a&0xFF);
2251 break;
2252 case GX_COLOR1A1:
2253 reg = 1;
2254 val |= (color.a&0xFF);
2255 break;
2256 default:
2257 return;
2260 __gx->chnMatColor[reg] = val;
2261 __gx->dirtyState |= (0x0400<<reg);
2264 void GX_SetArray(u32 attr,void *ptr,u8 stride)
2266 u32 idx = 0;
2268 if(attr==GX_VA_NBT) attr = GX_VA_NRM;
2269 if(attr>=GX_VA_POS && attr<=GX_LIGHTARRAY) {
2270 idx = attr-GX_VA_POS;
2271 GX_LOAD_CP_REG((0xA0+idx),(u32)MEM_VIRTUAL_TO_PHYSICAL(ptr));
2272 GX_LOAD_CP_REG((0xB0+idx),(u32)stride);
2276 static __inline__ void __SETVCDATTR(u8 attr,u8 type)
2278 switch(attr) {
2279 case GX_VA_PTNMTXIDX:
2280 __gx->vcdLo = (__gx->vcdLo&~0x1)|(type&0x1);
2281 break;
2282 case GX_VA_TEX0MTXIDX:
2283 __gx->vcdLo = (__gx->vcdLo&~0x2)|(_SHIFTL(type,1,1));
2284 break;
2285 case GX_VA_TEX1MTXIDX:
2286 __gx->vcdLo = (__gx->vcdLo&~0x4)|(_SHIFTL(type,2,1));
2287 break;
2288 case GX_VA_TEX2MTXIDX:
2289 __gx->vcdLo = (__gx->vcdLo&~0x8)|(_SHIFTL(type,3,1));
2290 break;
2291 case GX_VA_TEX3MTXIDX:
2292 __gx->vcdLo = (__gx->vcdLo&~0x10)|(_SHIFTL(type,4,1));
2293 break;
2294 case GX_VA_TEX4MTXIDX:
2295 __gx->vcdLo = (__gx->vcdLo&~0x20)|(_SHIFTL(type,5,1));
2296 break;
2297 case GX_VA_TEX5MTXIDX:
2298 __gx->vcdLo = (__gx->vcdLo&~0x40)|(_SHIFTL(type,6,1));
2299 break;
2300 case GX_VA_TEX6MTXIDX:
2301 __gx->vcdLo = (__gx->vcdLo&~0x80)|(_SHIFTL(type,7,1));
2302 break;
2303 case GX_VA_TEX7MTXIDX:
2304 __gx->vcdLo = (__gx->vcdLo&~0x100)|(_SHIFTL(type,8,1));
2305 break;
2306 case GX_VA_POS:
2307 __gx->vcdLo = (__gx->vcdLo&~0x600)|(_SHIFTL(type,9,2));
2308 break;
2309 case GX_VA_NRM:
2310 __gx->vcdLo = (__gx->vcdLo&~0x1800)|(_SHIFTL(type,11,2));
2311 __gx->vcdNrms = 1;
2312 break;
2313 case GX_VA_NBT:
2314 __gx->vcdLo = (__gx->vcdLo&~0x1800)|(_SHIFTL(type,11,2));
2315 __gx->vcdNrms = 2;
2316 break;
2317 case GX_VA_CLR0:
2318 __gx->vcdLo = (__gx->vcdLo&~0x6000)|(_SHIFTL(type,13,2));
2319 break;
2320 case GX_VA_CLR1:
2321 __gx->vcdLo = (__gx->vcdLo&~0x18000)|(_SHIFTL(type,15,2));
2322 break;
2323 case GX_VA_TEX0:
2324 __gx->vcdHi = (__gx->vcdHi&~0x3)|(type&0x3);
2325 break;
2326 case GX_VA_TEX1:
2327 __gx->vcdHi = (__gx->vcdHi&~0xc)|(_SHIFTL(type,2,2));
2328 break;
2329 case GX_VA_TEX2:
2330 __gx->vcdHi = (__gx->vcdHi&~0x30)|(_SHIFTL(type,4,2));
2331 break;
2332 case GX_VA_TEX3:
2333 __gx->vcdHi = (__gx->vcdHi&~0xc0)|(_SHIFTL(type,6,2));
2334 break;
2335 case GX_VA_TEX4:
2336 __gx->vcdHi = (__gx->vcdHi&~0x300)|(_SHIFTL(type,8,2));
2337 break;
2338 case GX_VA_TEX5:
2339 __gx->vcdHi = (__gx->vcdHi&~0xc00)|(_SHIFTL(type,10,2));
2340 break;
2341 case GX_VA_TEX6:
2342 __gx->vcdHi = (__gx->vcdHi&~0x3000)|(_SHIFTL(type,12,2));
2343 break;
2344 case GX_VA_TEX7:
2345 __gx->vcdHi = (__gx->vcdHi&~0xc000)|(_SHIFTL(type,14,2));
2346 break;
2350 void GX_SetVtxDesc(u8 attr,u8 type)
2352 __SETVCDATTR(attr,type);
2353 __gx->dirtyState |= 0x0008;
2356 void GX_SetVtxDescv(GXVtxDesc *attr_list)
2358 u32 i;
2360 if(!attr_list) return;
2362 for(i=0;i<GX_MAX_VTXDESC_LISTSIZE;i++){
2363 if(attr_list[i].attr==GX_VA_NULL) break;
2365 __SETVCDATTR(attr_list[i].attr,attr_list[i].type);
2367 __gx->dirtyState |= 0x0008;
2370 void GX_GetVtxDescv(GXVtxDesc *attr_list)
2372 u32 count;
2374 // Clear everything first
2375 for(count=0;count<GX_MAX_VTXDESC_LISTSIZE;count++) {
2376 attr_list[count].attr = GX_VA_NULL;
2377 attr_list[count].type = 0;
2380 count = 0;
2381 if(__gx->vcdLo&0x1) {
2382 attr_list[count].attr = GX_VA_PTNMTXIDX;
2383 attr_list[count].type = __gx->vcdLo&0x1;
2384 count++;
2387 if(__gx->vcdLo&0x2) {
2388 attr_list[count].attr = GX_VA_TEX0MTXIDX;
2389 attr_list[count].type = _SHIFTR(__gx->vcdLo&0x2,1,1);
2390 count++;
2393 if(__gx->vcdLo&0x4) {
2394 attr_list[count].attr = GX_VA_TEX1MTXIDX;
2395 attr_list[count].type = _SHIFTR(__gx->vcdLo&0x4,2,1);
2396 count++;
2399 if(__gx->vcdLo&0x8) {
2400 attr_list[count].attr = GX_VA_TEX2MTXIDX;
2401 attr_list[count].type = _SHIFTR(__gx->vcdLo&0x8,3,1);
2402 count++;
2405 if(__gx->vcdLo&0x10) {
2406 attr_list[count].attr = GX_VA_TEX3MTXIDX;
2407 attr_list[count].type = _SHIFTR(__gx->vcdLo&0x10,4,1);
2408 count++;
2411 if(__gx->vcdLo&0x20) {
2412 attr_list[count].attr = GX_VA_TEX4MTXIDX;
2413 attr_list[count].type = _SHIFTR(__gx->vcdLo&0x20,5,1);
2414 count++;
2417 if(__gx->vcdLo&0x40) {
2418 attr_list[count].attr = GX_VA_TEX5MTXIDX;
2419 attr_list[count].type = _SHIFTR(__gx->vcdLo&0x40,6,1);
2420 count++;
2423 if(__gx->vcdLo&0x80) {
2424 attr_list[count].attr = GX_VA_TEX6MTXIDX;
2425 attr_list[count].type = _SHIFTR(__gx->vcdLo&0x80,7,1);
2426 count++;
2429 if(__gx->vcdLo&0x100) {
2430 attr_list[count].attr = GX_VA_TEX7MTXIDX;
2431 attr_list[count].type = _SHIFTR(__gx->vcdLo&0x100,8,1);
2432 count++;
2435 if(__gx->vcdLo&0x600) {
2436 attr_list[count].attr = GX_VA_POS;
2437 attr_list[count].type = _SHIFTR(__gx->vcdLo&0x600,9,2);
2438 count++;
2441 if(__gx->vcdLo&0x1800) {
2442 if(__gx->vcdNrms==1) {
2443 attr_list[count].attr = GX_VA_NRM;
2444 attr_list[count].type = _SHIFTR(__gx->vcdLo&0x1800,11,2);
2445 count++;
2446 } else if(__gx->vcdNrms==2){
2447 attr_list[count].attr = GX_VA_NBT;
2448 attr_list[count].type = _SHIFTR(__gx->vcdLo&0x1800,11,2);
2449 count++;
2453 if(__gx->vcdLo&0x6000) {
2454 attr_list[count].attr = GX_VA_CLR0;
2455 attr_list[count].type = _SHIFTR(__gx->vcdLo&0x6000,13,2);
2456 count++;
2459 if(__gx->vcdLo&0x18000) {
2460 attr_list[count].attr = GX_VA_CLR1;
2461 attr_list[count].type = _SHIFTR(__gx->vcdLo&0x18000,15,2);
2462 count++;
2465 if(__gx->vcdHi&0x3) {
2466 attr_list[count].attr = GX_VA_TEX0;
2467 attr_list[count].type = __gx->vcdHi&0x3;
2468 count++;
2471 if(__gx->vcdHi&0xc) {
2472 attr_list[count].attr = GX_VA_TEX1;
2473 attr_list[count].type = _SHIFTR(__gx->vcdHi&0xc,2,2);
2474 count++;
2477 if(__gx->vcdHi&0x30) {
2478 attr_list[count].attr = GX_VA_TEX2;
2479 attr_list[count].type = _SHIFTR(__gx->vcdHi&0x30,4,2);
2480 count++;
2483 if(__gx->vcdHi&0xc0) {
2484 attr_list[count].attr = GX_VA_TEX3;
2485 attr_list[count].type = _SHIFTR(__gx->vcdHi&0xc0,6,2);
2486 count++;
2489 if(__gx->vcdHi&0x300) {
2490 attr_list[count].attr = GX_VA_TEX4;
2491 attr_list[count].type = _SHIFTR(__gx->vcdHi&0x300,8,2);
2492 count++;
2495 if(__gx->vcdHi&0xc00) {
2496 attr_list[count].attr = GX_VA_TEX5;
2497 attr_list[count].type = _SHIFTR(__gx->vcdHi&0xc00,10,2);
2498 count++;
2501 if(__gx->vcdHi&0x3000) {
2502 attr_list[count].attr = GX_VA_TEX6;
2503 attr_list[count].type = _SHIFTR(__gx->vcdHi&0x3000,12,2);
2504 count++;
2507 if(__gx->vcdHi&0xc000) {
2508 attr_list[count].attr = GX_VA_TEX7;
2509 attr_list[count].type = _SHIFTR(__gx->vcdHi&0xc000,14,2);
2510 count++;
2514 static __inline__ void __SETVCDFMT(u8 vtxfmt,u32 vtxattr,u32 comptype,u32 compsize,u32 frac)
2516 u8 vat = (vtxfmt&7);
2518 if(vtxattr==GX_VA_POS && (comptype==GX_POS_XY || comptype==GX_POS_XYZ)
2519 && (compsize>=GX_U8 && compsize<=GX_F32)) {
2520 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1)|(comptype&1);
2521 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0xe)|(_SHIFTL(compsize,1,3));
2522 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1f0)|(_SHIFTL(frac,4,5));
2523 if(frac)
2524 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2525 } else if(vtxattr==GX_VA_NRM && comptype==GX_NRM_XYZ
2526 && (compsize==GX_S8 || compsize==GX_S16 || compsize==GX_F32)) {
2527 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x200);
2528 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1C00)|(_SHIFTL(compsize,10,3));
2529 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x80000000);
2530 } else if(vtxattr==GX_VA_NBT && (comptype==GX_NRM_NBT || comptype==GX_NRM_NBT3)
2531 && (compsize==GX_S8 || compsize==GX_S16 || compsize==GX_F32)) {
2532 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x200)|0x200;
2533 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1C00)|(_SHIFTL(compsize,10,3));
2534 if(comptype==GX_NRM_NBT3)
2535 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x80000000)|0x80000000;
2536 } else if(vtxattr==GX_VA_CLR0 && (comptype==GX_CLR_RGB || comptype==GX_CLR_RGBA)
2537 && (compsize>=GX_RGB565 && compsize<=GX_RGBA8)) {
2538 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x2000)|(_SHIFTL(comptype,13,1));
2539 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1C000)|(_SHIFTL(compsize,14,3));
2540 } else if(vtxattr==GX_VA_CLR1 && (comptype==GX_CLR_RGB || comptype==GX_CLR_RGBA)
2541 && (compsize>=GX_RGB565 && compsize<=GX_RGBA8)) {
2542 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x20000)|(_SHIFTL(comptype,17,1));
2543 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1C0000)|(_SHIFTL(compsize,18,3));
2544 } else if(vtxattr==GX_VA_TEX0 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2545 && (compsize>=GX_U8 && compsize<=GX_F32)) {
2546 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x200000)|(_SHIFTL(comptype,21,1));
2547 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1C00000)|(_SHIFTL(compsize,22,3));
2548 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x3E000000)|(_SHIFTL(frac,25,5));
2549 if(frac)
2550 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2551 } else if(vtxattr==GX_VA_TEX1 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2552 && (compsize>=GX_U8 && compsize<=GX_F32)) {
2553 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x1)|(comptype&1);
2554 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0xe)|(_SHIFTL(compsize,1,3));
2555 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x1F0)|(_SHIFTL(frac,4,5));
2556 if(frac)
2557 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2558 } else if(vtxattr==GX_VA_TEX2 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2559 && (compsize>=GX_U8 && compsize<=GX_F32)) {
2560 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x200)|(_SHIFTL(comptype,9,1));
2561 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x1C00)|(_SHIFTL(compsize,10,3));
2562 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x3E000)|(_SHIFTL(frac,13,5));
2563 if(frac)
2564 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2565 } else if(vtxattr==GX_VA_TEX3 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2566 && (compsize>=GX_U8 && compsize<=GX_F32)) {
2567 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x40000)|(_SHIFTL(comptype,18,1));
2568 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x380000)|(_SHIFTL(compsize,19,3));
2569 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x7C00000)|(_SHIFTL(frac,22,5));
2570 if(frac)
2571 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2572 } else if(vtxattr==GX_VA_TEX4 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2573 && (compsize>=GX_U8 && compsize<=GX_F32)) {
2574 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x8000000)|(_SHIFTL(comptype,27,1));
2575 __gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x70000000)|(_SHIFTL(compsize,28,3));
2576 __gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x1f)|(frac&0x1f);
2577 if(frac)
2578 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2579 } else if(vtxattr==GX_VA_TEX5 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2580 && (compsize>=GX_U8 && compsize<=GX_F32)) {
2581 __gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x20)|(_SHIFTL(comptype,5,1));
2582 __gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x1C0)|(_SHIFTL(compsize,6,3));
2583 __gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x3E00)|(_SHIFTL(frac,9,5));
2584 if(frac)
2585 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2586 } else if(vtxattr==GX_VA_TEX6 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2587 && (compsize>=GX_U8 && compsize<=GX_F32)) {
2588 __gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x4000)|(_SHIFTL(comptype,14,1));
2589 __gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x38000)|(_SHIFTL(compsize,15,3));
2590 __gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x7C0000)|(_SHIFTL(frac,18,5));
2591 if(frac)
2592 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2593 } else if(vtxattr==GX_VA_TEX7 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2594 && (compsize>=GX_U8 && compsize<=GX_F32)) {
2595 __gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x800000)|(_SHIFTL(comptype,23,1));
2596 __gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x7000000)|(_SHIFTL(compsize,24,3));
2597 __gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0xF8000000)|(_SHIFTL(frac,27,5));
2598 if(frac)
2599 __gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2603 void GX_SetVtxAttrFmt(u8 vtxfmt,u32 vtxattr,u32 comptype,u32 compsize,u32 frac)
2605 __SETVCDFMT(vtxfmt,vtxattr,comptype,compsize,frac);
2606 __gx->VATTable |= (1<<vtxfmt);
2607 __gx->dirtyState |= 0x0010;
2610 void GX_SetVtxAttrFmtv(u8 vtxfmt,GXVtxAttrFmt *attr_list)
2612 u32 i;
2614 for(i=0;i<GX_MAX_VTXATTRFMT_LISTSIZE;i++) {
2615 if(attr_list[i].vtxattr==GX_VA_NULL) break;
2617 __SETVCDFMT(vtxfmt,attr_list[i].vtxattr,attr_list[i].comptype,attr_list[i].compsize,attr_list[i].frac);
2619 __gx->VATTable |= (1<<vtxfmt);
2620 __gx->dirtyState |= 0x0010;
2623 void GX_Begin(u8 primitve,u8 vtxfmt,u16 vtxcnt)
2625 u8 reg = primitve|(vtxfmt&7);
2627 if(__gx->dirtyState)
2628 __GX_SetDirtyState();
2630 wgPipe->U8 = reg;
2631 wgPipe->U16 = vtxcnt;
2634 void GX_SetTexCoordGen(u16 texcoord,u32 tgen_typ,u32 tgen_src,u32 mtxsrc)
2636 GX_SetTexCoordGen2(texcoord,tgen_typ,tgen_src,mtxsrc,GX_FALSE,GX_DTTIDENTITY);
2639 void GX_SetTexCoordGen2(u16 texcoord,u32 tgen_typ,u32 tgen_src,u32 mtxsrc,u32 normalize,u32 postmtx)
2641 u32 txc;
2642 u32 texcoords;
2643 u8 vtxrow,stq;
2645 if(texcoord>=GX_MAXCOORD) return;
2647 stq = 0;
2648 switch(tgen_src) {
2649 case GX_TG_POS:
2650 vtxrow = 0;
2651 stq = 1;
2652 break;
2653 case GX_TG_NRM:
2654 vtxrow = 1;
2655 stq = 1;
2656 break;
2657 case GX_TG_BINRM:
2658 vtxrow = 3;
2659 stq = 1;
2660 break;
2661 case GX_TG_TANGENT:
2662 vtxrow = 4;
2663 stq = 1;
2664 break;
2665 case GX_TG_COLOR0:
2666 vtxrow = 2;
2667 break;
2668 case GX_TG_COLOR1:
2669 vtxrow = 2;
2670 break;
2671 case GX_TG_TEX0:
2672 vtxrow = 5;
2673 break;
2674 case GX_TG_TEX1:
2675 vtxrow = 6;
2676 break;
2677 case GX_TG_TEX2:
2678 vtxrow = 7;
2679 break;
2680 case GX_TG_TEX3:
2681 vtxrow = 8;
2682 break;
2683 case GX_TG_TEX4:
2684 vtxrow = 9;
2685 break;
2686 case GX_TG_TEX5:
2687 vtxrow = 10;
2688 break;
2689 case GX_TG_TEX6:
2690 vtxrow = 11;
2691 break;
2692 case GX_TG_TEX7:
2693 vtxrow = 12;
2694 break;
2695 default:
2696 vtxrow = 5;
2697 break;
2700 texcoords = 0;
2701 txc = (texcoord&7);
2702 if((tgen_typ==GX_TG_MTX3x4 || tgen_typ==GX_TG_MTX2x4))
2704 if(tgen_typ==GX_TG_MTX3x4) texcoords = 0x02;
2706 texcoords |= (_SHIFTL(stq,2,1));
2707 texcoords |= (_SHIFTL(vtxrow,7,5));
2708 } else if((tgen_typ>=GX_TG_BUMP0 && tgen_typ<=GX_TG_BUMP7))
2710 tgen_src -= GX_TG_TEXCOORD0;
2711 tgen_typ -= GX_TG_BUMP0;
2713 texcoords = 0x10;
2714 texcoords |= (_SHIFTL(stq,2,1));
2715 texcoords |= (_SHIFTL(vtxrow,7,5));
2716 texcoords |= (_SHIFTL(tgen_src,12,3));
2717 texcoords |= (_SHIFTL(tgen_typ,15,3));
2718 } else if(tgen_typ==GX_TG_SRTG) {
2719 if(tgen_src==GX_TG_COLOR0) texcoords = 0x20;
2720 else if(tgen_src==GX_TG_COLOR1) texcoords = 0x30;
2721 texcoords |= (_SHIFTL(stq,2,1));
2722 texcoords |= (_SHIFTL(2,7,5));
2725 postmtx -= GX_DTTMTX0;
2726 __gx->texCoordGen[txc] = texcoords;
2727 __gx->texCoordGen2[txc] = ((_SHIFTL(normalize,8,1))|(postmtx&0x3f));
2729 switch(texcoord) {
2730 case GX_TEXCOORD0:
2731 __gx->mtxIdxLo = (__gx->mtxIdxLo&~0xfc0)|(_SHIFTL(mtxsrc,6,6));
2732 break;
2733 case GX_TEXCOORD1:
2734 __gx->mtxIdxLo = (__gx->mtxIdxLo&~0x3f000)|(_SHIFTL(mtxsrc,12,6));
2735 break;
2736 case GX_TEXCOORD2:
2737 __gx->mtxIdxLo = (__gx->mtxIdxLo&~0xfc0000)|(_SHIFTL(mtxsrc,18,6));
2738 break;
2739 case GX_TEXCOORD3:
2740 __gx->mtxIdxLo = (__gx->mtxIdxLo&~0x3f000000)|(_SHIFTL(mtxsrc,24,6));
2741 break;
2742 case GX_TEXCOORD4:
2743 __gx->mtxIdxHi = (__gx->mtxIdxHi&~0x3f)|(mtxsrc&0x3f);
2744 break;
2745 case GX_TEXCOORD5:
2746 __gx->mtxIdxHi = (__gx->mtxIdxHi&~0xfc0)|(_SHIFTL(mtxsrc,6,6));
2747 break;
2748 case GX_TEXCOORD6:
2749 __gx->mtxIdxHi = (__gx->mtxIdxHi&~0x3f000)|(_SHIFTL(mtxsrc,12,6));
2750 break;
2751 case GX_TEXCOORD7:
2752 __gx->mtxIdxHi = (__gx->mtxIdxHi&~0xfc0000)|(_SHIFTL(mtxsrc,18,6));
2753 break;
2755 __gx->dirtyState |= (0x04000000|(0x00010000<<texcoord));
2758 void GX_SetZTexture(u8 op,u8 fmt,u32 bias)
2760 u32 val = 0;
2762 if(fmt==GX_TF_Z8) fmt = 0;
2763 else if(fmt==GX_TF_Z16) fmt = 1;
2764 else fmt = 2;
2766 val = (u32)(_SHIFTL(op,2,2))|(fmt&3);
2767 GX_LOAD_BP_REG(0xF4000000|(bias&0x00FFFFFF));
2768 GX_LOAD_BP_REG(0xF5000000|(val&0x00FFFFFF));
2771 static inline void WriteMtxPS4x3(register Mtx mt,register void *wgpipe)
2773 register f32 tmp0,tmp1,tmp2,tmp3,tmp4,tmp5;
2774 __asm__ __volatile__ (
2775 "psq_l %0,0(%6),0,0\n\
2776 psq_l %1,8(%6),0,0\n\
2777 psq_l %2,16(%6),0,0\n\
2778 psq_l %3,24(%6),0,0\n\
2779 psq_l %4,32(%6),0,0\n\
2780 psq_l %5,40(%6),0,0\n\
2781 psq_st %0,0(%7),0,0\n\
2782 psq_st %1,0(%7),0,0\n\
2783 psq_st %2,0(%7),0,0\n\
2784 psq_st %3,0(%7),0,0\n\
2785 psq_st %4,0(%7),0,0\n\
2786 psq_st %5,0(%7),0,0"
2787 : "=&f"(tmp0),"=&f"(tmp1),"=&f"(tmp2),"=&f"(tmp3),"=&f"(tmp4),"=&f"(tmp5)
2788 : "b"(mt), "b"(wgpipe)
2789 : "memory"
2793 static inline void WriteMtxPS3x3from4x3(register Mtx mt,register void *wgpipe)
2795 register f32 tmp0,tmp1,tmp2,tmp3,tmp4,tmp5;
2796 __asm__ __volatile__
2797 ("psq_l %0,0(%6),0,0\n\
2798 lfs %1,8(%6)\n\
2799 psq_l %2,16(%6),0,0\n\
2800 lfs %3,24(%6)\n\
2801 psq_l %4,32(%6),0,0\n\
2802 lfs %5,40(%6)\n\
2803 psq_st %0,0(%7),0,0\n\
2804 stfs %1,0(%7)\n\
2805 psq_st %2,0(%7),0,0\n\
2806 stfs %3,0(%7)\n\
2807 psq_st %4,0(%7),0,0\n\
2808 stfs %5,0(%7)"
2809 : "=&f"(tmp0),"=&f"(tmp1),"=&f"(tmp2),"=&f"(tmp3),"=&f"(tmp4),"=&f"(tmp5)
2810 : "b"(mt), "b"(wgpipe)
2811 : "memory"
2815 static inline void WriteMtxPS3x3(register Mtx33 mt,register void *wgpipe)
2817 register f32 tmp0,tmp1,tmp2,tmp3,tmp4;
2818 __asm__ __volatile__
2819 ("psq_l %0,0(%5),0,0\n\
2820 psq_l %1,8(%5),0,0\n\
2821 psq_l %2,16(%5),0,0\n\
2822 psq_l %3,24(%5),0,0\n\
2823 lfs %4,32(%5)\n\
2824 psq_st %0,0(%6),0,0\n\
2825 psq_st %1,0(%6),0,0\n\
2826 psq_st %2,0(%6),0,0\n\
2827 psq_st %3,0(%6),0,0\n\
2828 stfs %4,0(%6)"
2829 : "=&f"(tmp0),"=&f"(tmp1),"=&f"(tmp2),"=&f"(tmp3),"=&f"(tmp4)
2830 : "b"(mt), "b"(wgpipe)
2831 : "memory"
2835 static inline void WriteMtxPS4x2(register Mtx mt,register void *wgpipe)
2837 register f32 tmp0,tmp1,tmp2,tmp3;
2838 __asm__ __volatile__
2839 ("psq_l %0,0(%4),0,0\n\
2840 psq_l %1,8(%4),0,0\n\
2841 psq_l %2,16(%4),0,0\n\
2842 psq_l %3,24(%4),0,0\n\
2843 psq_st %0,0(%5),0,0\n\
2844 psq_st %1,0(%5),0,0\n\
2845 psq_st %2,0(%5),0,0\n\
2846 psq_st %3,0(%5),0,0"
2847 : "=&f"(tmp0),"=&f"(tmp1),"=&f"(tmp2),"=&f"(tmp3)
2848 : "b"(mt), "b"(wgpipe)
2849 : "memory"
2853 void GX_LoadPosMtxImm(Mtx mt,u32 pnidx)
2855 GX_LOAD_XF_REGS((0x0000|(_SHIFTL(pnidx,2,8))),12);
2856 WriteMtxPS4x3(mt,(void*)wgPipe);
2859 void GX_LoadPosMtxIdx(u16 mtxidx,u32 pnidx)
2861 wgPipe->U8 = 0x20;
2862 wgPipe->U32 = ((_SHIFTL(mtxidx,16,16))|0xb000|(_SHIFTL(pnidx,2,8)));
2865 void GX_LoadNrmMtxImm(Mtx mt,u32 pnidx)
2867 GX_LOAD_XF_REGS((0x0400|(pnidx*3)),9);
2868 WriteMtxPS3x3from4x3(mt,(void*)wgPipe);
2871 void GX_LoadNrmMtxImm3x3(Mtx33 mt,u32 pnidx)
2873 GX_LOAD_XF_REGS((0x0400|(pnidx*3)),9);
2874 WriteMtxPS3x3(mt,(void*)wgPipe);
2877 void GX_LoadNrmMtxIdx3x3(u16 mtxidx,u32 pnidx)
2879 wgPipe->U8 = 0x28;
2880 wgPipe->U32 = ((_SHIFTL(mtxidx,16,16))|0x8000|(0x0400|(pnidx*3)));
2883 void GX_LoadTexMtxImm(Mtx mt,u32 texidx,u8 type)
2885 u32 addr = 0;
2886 u32 rows = (type==GX_MTX2x4)?2:3;
2888 if(texidx<GX_DTTMTX0) addr = (_SHIFTL(texidx,2,8));
2889 else {
2890 texidx -= GX_DTTMTX0;
2891 addr = 0x0500 + (_SHIFTL(texidx,2,8));
2894 GX_LOAD_XF_REGS(addr,(rows*4));
2895 if(type==GX_MTX2x4)
2896 WriteMtxPS4x2(mt,(void*)wgPipe);
2897 else
2898 WriteMtxPS4x3(mt,(void*)wgPipe);
2901 void GX_LoadTexMtxIdx(u16 mtxidx,u32 texidx,u8 type)
2903 u32 addr,size = (type==GX_MTX2x4)?7:11;
2905 if(texidx<GX_DTTMTX0) addr = 0x0000|(_SHIFTL(texidx,2,8));
2906 else addr = 0x0500|(_SHIFTL((texidx-GX_DTTMTX0),2,8));
2908 wgPipe->U8 = 0x30;
2909 wgPipe->U32 = ((_SHIFTL(mtxidx,16,16))|(_SHIFTL(size,12,4))|addr);
2912 void GX_SetCurrentMtx(u32 mtx)
2914 __gx->mtxIdxLo = (__gx->mtxIdxLo&~0x3f)|(mtx&0x3f);
2915 __gx->dirtyState |= 0x04000000;
2918 void GX_SetNumTexGens(u32 nr)
2920 __gx->genMode = (__gx->genMode&~0xf)|(nr&0xf);
2921 __gx->dirtyState |= 0x02000004;
2924 void GX_InvVtxCache()
2926 wgPipe->U8 = 0x48; // vertex cache weg
2929 void GX_SetZMode(u8 enable,u8 func,u8 update_enable)
2931 __gx->peZMode = (__gx->peZMode&~0x1)|(enable&1);
2932 __gx->peZMode = (__gx->peZMode&~0xe)|(_SHIFTL(func,1,3));
2933 __gx->peZMode = (__gx->peZMode&~0x10)|(_SHIFTL(update_enable,4,1));
2934 GX_LOAD_BP_REG(__gx->peZMode);
2937 static void __GetTexTileShift(u32 fmt,u32 *xshift,u32 *yshift)
2939 switch(fmt) {
2940 case GX_TF_I4:
2941 case GX_TF_IA4:
2942 case GX_CTF_R4:
2943 case GX_CTF_RA4:
2944 case GX_CTF_Z4:
2945 *xshift = 3;
2946 *yshift = 3;
2947 break;
2948 case GX_TF_Z8:
2949 case GX_TF_I8:
2950 case GX_TF_IA8:
2951 case GX_CTF_RA8:
2952 case GX_CTF_A8:
2953 case GX_CTF_R8:
2954 case GX_CTF_G8:
2955 case GX_CTF_B8:
2956 case GX_CTF_RG8:
2957 case GX_CTF_GB8:
2958 case GX_CTF_Z8M:
2959 case GX_CTF_Z8L:
2960 *xshift = 3;
2961 *yshift = 2;
2962 break;
2963 case GX_TF_Z16:
2964 case GX_TF_Z24X8:
2965 case GX_CTF_Z16L:
2966 case GX_TF_RGB565:
2967 case GX_TF_RGB5A3:
2968 case GX_TF_RGBA8:
2969 *xshift = 2;
2970 *yshift = 2;
2971 break;
2972 default:
2973 *xshift = 0;
2974 *yshift = 0;
2975 break;
2979 u32 GX_GetTexObjFmt(GXTexObj *obj)
2981 return ((struct __gx_texobj*)obj)->tex_fmt;
2984 u32 GX_GetTexObjMipMap(GXTexObj *obj)
2986 return (((struct __gx_texobj*)obj)->tex_flag&0x01);
2989 u32 GX_GetTexBufferSize(u16 wd,u16 ht,u32 fmt,u8 mipmap,u8 maxlod)
2991 u32 xshift,yshift,xtiles,ytiles,bitsize,size;
2993 switch(fmt) {
2994 case GX_TF_I4:
2995 case GX_TF_CMPR:
2996 case GX_CTF_R4:
2997 case GX_CTF_RA4:
2998 case GX_CTF_Z4:
2999 xshift = 3;
3000 yshift = 3;
3001 break;
3002 case GX_TF_Z8:
3003 case GX_TF_I8:
3004 case GX_TF_IA4:
3005 case GX_CTF_A8:
3006 case GX_CTF_R8:
3007 case GX_CTF_G8:
3008 case GX_CTF_B8:
3009 case GX_CTF_RG8:
3010 case GX_CTF_GB8:
3011 case GX_CTF_Z8M:
3012 case GX_CTF_Z8L:
3013 xshift = 3;
3014 yshift = 2;
3015 break;
3016 case GX_TF_IA8:
3017 case GX_TF_Z16:
3018 case GX_TF_Z24X8:
3019 case GX_TF_RGB565:
3020 case GX_TF_RGB5A3:
3021 case GX_TF_RGBA8:
3022 case GX_CTF_Z16L:
3023 case GX_CTF_RA8:
3024 xshift = 2;
3025 yshift = 2;
3026 break;
3027 default:
3028 xshift = 2;
3029 yshift = 2;
3030 break;
3033 bitsize = 32;
3034 if(fmt==GX_TF_RGBA8 || fmt==GX_TF_Z24X8) bitsize = 64;
3036 size = 0;
3037 if(mipmap) {
3038 u32 cnt = (maxlod&0xff);
3039 while(cnt) {
3040 u32 w = wd&0xffff;
3041 u32 h = ht&0xffff;
3042 xtiles = ((w+(1<<xshift))-1)>>xshift;
3043 ytiles = ((h+(1<<yshift))-1)>>yshift;
3044 if(cnt==0) return size;
3046 size += ((xtiles*ytiles)*bitsize);
3047 if(w==0x0001 && h==0x0001) return size;
3048 if(wd>0x0001) wd = (w>>1);
3049 else wd = 0x0001;
3050 if(ht>0x0001) ht = (h>>1);
3051 else ht = 0x0001;
3053 --cnt;
3055 return size;
3058 wd &= 0xffff;
3059 xtiles = (wd+((1<<xshift)-1))>>xshift;
3061 ht &= 0xffff;
3062 ytiles = (ht+((1<<yshift)-1))>>yshift;
3064 size = ((xtiles*ytiles)*bitsize);
3066 return size;
3069 void GX_InitTexCacheRegion(GXTexRegion *region,u8 is32bmipmap,u32 tmem_even,u8 size_even,u32 tmem_odd,u8 size_odd)
3071 u32 sze = 0;
3072 struct __gx_texregion *ptr = (struct __gx_texregion*)region;
3074 switch(size_even) {
3075 case GX_TEXCACHE_32K:
3076 sze = 3;
3077 break;
3078 case GX_TEXCACHE_128K:
3079 sze = 4;
3080 break;
3081 case GX_TEXCACHE_512K:
3082 sze = 5;
3083 break;
3084 default:
3085 sze = 3;
3086 break;
3088 ptr->tmem_even = 0;
3089 ptr->tmem_even = (ptr->tmem_even&~0x7fff)|(_SHIFTR(tmem_even,5,15));
3090 ptr->tmem_even = (ptr->tmem_even&~0x38000)|(_SHIFTL(sze,15,3));
3091 ptr->tmem_even = (ptr->tmem_even&~0x1C0000)|(_SHIFTL(sze,18,3));
3093 switch(size_odd) {
3094 case GX_TEXCACHE_32K:
3095 sze = 3;
3096 break;
3097 case GX_TEXCACHE_128K:
3098 sze = 4;
3099 break;
3100 case GX_TEXCACHE_512K:
3101 sze = 5;
3102 break;
3103 default:
3104 sze = 3;
3105 break;
3107 ptr->tmem_odd = 0;
3108 ptr->tmem_odd = (ptr->tmem_odd&~0x7fff)|(_SHIFTR(tmem_odd,5,15));
3109 ptr->tmem_odd = (ptr->tmem_odd&~0x38000)|(_SHIFTL(sze,15,3));
3110 ptr->tmem_odd = (ptr->tmem_odd&~0x1C0000)|(_SHIFTL(sze,18,3));
3112 ptr->ismipmap = is32bmipmap;
3113 ptr->iscached = 1;
3116 void GX_InitTexPreloadRegion(GXTexRegion *region,u32 tmem_even,u32 size_even,u32 tmem_odd,u32 size_odd)
3118 struct __gx_texregion *ptr = (struct __gx_texregion*)region;
3120 ptr->tmem_even = 0;
3121 ptr->tmem_even = (ptr->tmem_even&~0x7FFF)|(_SHIFTR(tmem_even,5,15));
3122 ptr->tmem_even = (ptr->tmem_even&~0x200000)|0x200000;
3124 ptr->tmem_odd = 0;
3125 ptr->tmem_odd = (ptr->tmem_odd&~0x7FFF)|(_SHIFTR(tmem_odd,5,15));
3127 ptr->size_even = _SHIFTR(size_even,5,16);
3128 ptr->size_odd = _SHIFTR(size_odd,5,16);
3130 ptr->ismipmap = 0;
3131 ptr->iscached = 0;
3134 void GX_InitTlutRegion(GXTlutRegion *region,u32 tmem_addr,u8 tlut_sz)
3136 struct __gx_tlutregion *ptr = (struct __gx_tlutregion*)region;
3138 tmem_addr -= 0x80000;
3140 ptr->tmem_addr_conf = 0;
3141 ptr->tmem_addr_conf = (ptr->tmem_addr_conf&~0x3ff)|(_SHIFTR(tmem_addr,9,10));
3142 ptr->tmem_addr_conf = (ptr->tmem_addr_conf&~0x1FFC00)|(_SHIFTL(tlut_sz,10,10));
3143 ptr->tmem_addr_conf = (ptr->tmem_addr_conf&~0xff000000)|(_SHIFTL(0x65,24,8));
3146 void GX_InitTexObj(GXTexObj *obj,void *img_ptr,u16 wd,u16 ht,u8 fmt,u8 wrap_s,u8 wrap_t,u8 mipmap)
3148 u32 nwd,nht;
3149 u32 xshift,yshift;
3150 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3152 if(!obj) return;
3154 memset(obj,0,sizeof(GXTexObj));
3156 ptr->tex_filt = (ptr->tex_filt&~0x03)|(wrap_s&3);
3157 ptr->tex_filt = (ptr->tex_filt&~0x0c)|(_SHIFTL(wrap_t,2,2));
3158 ptr->tex_filt = (ptr->tex_filt&~0x10)|0x10;
3160 if(mipmap) {
3161 ptr->tex_flag |= 0x01;
3162 if(fmt==GX_TF_CI4 || fmt==GX_TF_CI8 || fmt==GX_TF_CI14)
3163 ptr->tex_filt = (ptr->tex_filt&~0xe0)|0x00a0;
3164 else
3165 ptr->tex_filt = (ptr->tex_filt&~0xe0)|0x00c0;
3166 } else
3167 ptr->tex_filt= (ptr->tex_filt&~0xE0)|0x0080;
3169 ptr->tex_fmt = fmt;
3170 ptr->tex_size = (ptr->tex_size&~0x3ff)|((wd-1)&0x3ff);
3171 ptr->tex_size = (ptr->tex_size&~0xFFC00)|(_SHIFTL((ht-1),10,10));
3172 ptr->tex_size = (ptr->tex_size&~0xF00000)|(_SHIFTL(fmt,20,4));
3173 ptr->tex_maddr = (ptr->tex_maddr&~0x01ffffff)|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(img_ptr),5,24));
3175 switch(fmt) {
3176 case GX_TF_I4:
3177 case GX_TF_CI4:
3178 xshift = 3;
3179 yshift = 3;
3180 ptr->tex_tile_type = 1;
3181 break;
3182 case GX_TF_I8:
3183 case GX_TF_IA4:
3184 case GX_TF_CI8:
3185 xshift = 3;
3186 yshift = 2;
3187 ptr->tex_tile_type = 2;
3188 break;
3189 case GX_TF_IA8:
3190 case GX_TF_RGB565:
3191 case GX_TF_RGB5A3:
3192 case GX_TF_RGBA8:
3193 xshift = 2;
3194 yshift = 2;
3195 ptr->tex_tile_type = 2;
3196 break;
3197 case GX_TF_CI14:
3198 xshift = 2;
3199 yshift = 2;
3200 ptr->tex_tile_type = 3;
3201 break;
3202 case GX_TF_CMPR:
3203 xshift = 3;
3204 yshift = 3;
3205 ptr->tex_tile_type = 0;
3206 break;
3207 default:
3208 xshift = 2;
3209 yshift = 2;
3210 ptr->tex_tile_type = 2;
3211 break;
3214 nwd = ((wd+(1<<xshift))-1)>>xshift;
3215 nht = ((ht+(1<<yshift))-1)>>yshift;
3216 ptr->tex_tile_cnt = (nwd*nht)&0x7fff;
3218 ptr->tex_flag |= 0x0002;
3221 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)
3223 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3225 GX_InitTexObj(obj,img_ptr,wd,ht,fmt,wrap_s,wrap_t,mipmap);
3226 ptr->tex_flag &= ~0x02;
3227 ptr->tex_tlut = tlut_name;
3230 void GX_InitTexObjLOD(GXTexObj *obj,u8 minfilt,u8 magfilt,f32 minlod,f32 maxlod,f32 lodbias,u8 biasclamp,u8 edgelod,u8 maxaniso)
3232 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3233 static u8 GX2HWFiltConv[] = {0x00,0x04,0x01,0x05,0x02,0x06,0x00,0x00};
3234 //static u8 HW2GXFiltConv[] = {0x00,0x02,0x04,0x00,0x01,0x03,0x05,0x00};
3236 if(lodbias<-4.0f) lodbias = -4.0f;
3237 else if(lodbias==4.0f) lodbias = 3.99f;
3239 ptr->tex_filt = (ptr->tex_filt&~0x1fe00)|(_SHIFTL(((u32)(32.0f*lodbias)),9,8));
3240 ptr->tex_filt = (ptr->tex_filt&~0x10)|(_SHIFTL((magfilt==GX_LINEAR?1:0),4,1));
3241 ptr->tex_filt = (ptr->tex_filt&~0xe0)|(_SHIFTL(GX2HWFiltConv[minfilt],5,3));
3242 ptr->tex_filt = (ptr->tex_filt&~0x100)|(_SHIFTL(!(edgelod&0xff),8,1));
3243 ptr->tex_filt = (ptr->tex_filt&~0x180000)|(_SHIFTL(maxaniso,19,2));
3244 ptr->tex_filt = (ptr->tex_filt&~0x200000)|(_SHIFTL(biasclamp,21,1));
3246 if(minlod<0.0f) minlod = 0.0f;
3247 else if(minlod>10.0f) minlod = 10.0f;
3249 if(maxlod<0.0f) maxlod = 0.0f;
3250 else if(maxlod>10.0f) maxlod = 10.0f;
3252 ptr->tex_lod = (ptr->tex_lod&~0xff)|(((u32)(16.0f*minlod))&0xff);
3253 ptr->tex_lod = (ptr->tex_lod&~0xff00)|(_SHIFTL(((u32)(16.0f*maxlod)),8,8));
3256 void GX_InitTexObjData(GXTexObj *obj,void *img_ptr)
3258 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3259 ptr->tex_maddr = (ptr->tex_maddr&~0x01ffffff)|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(img_ptr),5,24));
3262 void GX_InitTexObjTlut(GXTexObj *obj,u32 tlut_name)
3264 ((struct __gx_texobj*)obj)->tex_tlut = tlut_name;
3267 void GX_InitTexObjWrapMode(GXTexObj *obj,u8 wrap_s,u8 wrap_t)
3269 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3271 ptr->tex_filt = (ptr->tex_filt&~0x03)|(wrap_s&3);
3272 ptr->tex_filt = (ptr->tex_filt&~0x0c)|(_SHIFTL(wrap_t,2,2));
3275 void GX_InitTexObjFilterMode(GXTexObj *obj,u8 minfilt,u8 magfilt)
3277 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3278 static u8 GX2HWFiltConv[] = {0x00,0x04,0x01,0x05,0x02,0x06,0x00,0x00};
3280 ptr->tex_filt = (ptr->tex_filt&~0x10)|(_SHIFTL((magfilt==GX_LINEAR?1:0),4,1));
3281 ptr->tex_filt = (ptr->tex_filt&~0xe0)|(_SHIFTL(GX2HWFiltConv[minfilt],5,3));
3284 void GX_InitTexObjMinLOD(GXTexObj *obj,f32 minlod)
3286 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3288 if(minlod<0.0f) minlod = 0.0f;
3289 else if(minlod>10.0f) minlod = 10.0f;
3291 ptr->tex_lod = (ptr->tex_lod&~0xff)|(((u32)(16.0f*minlod))&0xff);
3294 void GX_InitTexObjMaxLOD(GXTexObj *obj,f32 maxlod)
3296 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3298 if(maxlod<0.0f) maxlod = 0.0f;
3299 else if(maxlod>10.0f) maxlod = 10.0f;
3301 ptr->tex_lod = (ptr->tex_lod&~0xff00)|(_SHIFTL(((u32)(16.0f*maxlod)),8,8));
3304 void GX_InitTexObjLODBias(GXTexObj *obj,f32 lodbias)
3306 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3308 if(lodbias<-4.0f) lodbias = -4.0f;
3309 else if(lodbias==4.0f) lodbias = 3.99f;
3311 ptr->tex_filt = (ptr->tex_filt&~0x1fe00)|(_SHIFTL(((u32)(32.0f*lodbias)),9,8));
3314 void GX_InitTexObjBiasClamp(GXTexObj *obj,u8 biasclamp)
3316 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3317 ptr->tex_filt = (ptr->tex_filt&~0x200000)|(_SHIFTL(biasclamp,21,1));
3320 void GX_InitTexObjEdgeLOD(GXTexObj *obj,u8 edgelod)
3322 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3323 ptr->tex_filt = (ptr->tex_filt&~0x100)|(_SHIFTL(!(edgelod&0xff),8,1));
3326 void GX_InitTexObjMaxAniso(GXTexObj *obj,u8 maxaniso)
3328 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3329 ptr->tex_filt = (ptr->tex_filt&~0x180000)|(_SHIFTL(maxaniso,19,2));
3332 void GX_InitTexObjUserData(GXTexObj *obj,void *userdata)
3334 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3335 ptr->usr_data = (u32)userdata;
3338 void* GX_GetTexObjUserData(GXTexObj *obj)
3340 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3341 return (void*)ptr->usr_data;
3344 void GX_InitTlutObj(GXTlutObj *obj,void *lut,u8 fmt,u16 entries)
3346 struct __gx_tlutobj *ptr = (struct __gx_tlutobj*)obj;
3348 memset(obj,0,sizeof(GXTlutObj));
3350 ptr->tlut_fmt = _SHIFTL(fmt,10,2);
3351 ptr->tlut_maddr = (ptr->tlut_maddr&~0x00ffffff)|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(lut),5,24));
3352 ptr->tlut_maddr = (ptr->tlut_maddr&~0xff000000)|(_SHIFTL(0x64,24,8));
3353 ptr->tlut_nentries = entries;
3356 void GX_LoadTexObj(GXTexObj *obj,u8 mapid)
3358 GXTexRegion *region = NULL;
3360 if(regionCB)
3361 region = regionCB(obj,mapid);
3363 GX_LoadTexObjPreloaded(obj,region,mapid);
3366 void GX_LoadTexObjPreloaded(GXTexObj *obj,GXTexRegion *region,u8 mapid)
3368 u8 type;
3369 struct __gx_tlutregion *tlut = NULL;
3370 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3371 struct __gx_texregion *reg = (struct __gx_texregion*)region;
3373 ptr->tex_filt = (ptr->tex_filt&~0xff000000)|(_SHIFTL(_gxtexmode0ids[mapid],24,8));
3374 ptr->tex_lod = (ptr->tex_lod&~0xff000000)|(_SHIFTL(_gxtexmode1ids[mapid],24,8));
3375 ptr->tex_size = (ptr->tex_size&~0xff000000)|(_SHIFTL(_gxteximg0ids[mapid],24,8));
3376 ptr->tex_maddr = (ptr->tex_maddr&~0xff000000)|(_SHIFTL(_gxteximg3ids[mapid],24,8));
3378 reg->tmem_even = (reg->tmem_even&~0xff000000)|(_SHIFTL(_gxteximg1ids[mapid],24,8));
3379 reg->tmem_odd = (reg->tmem_odd&~0xff000000)|(_SHIFTL(_gxteximg2ids[mapid],24,8));
3381 GX_LOAD_BP_REG(ptr->tex_filt);
3382 GX_LOAD_BP_REG(ptr->tex_lod);
3383 GX_LOAD_BP_REG(ptr->tex_size);
3385 GX_LOAD_BP_REG(reg->tmem_even);
3386 GX_LOAD_BP_REG(reg->tmem_odd);
3388 GX_LOAD_BP_REG(ptr->tex_maddr);
3390 type = ptr->tex_flag;
3391 if(!(type&0x02)) {
3392 if(tlut_regionCB)
3393 tlut = (struct __gx_tlutregion*)tlut_regionCB(ptr->tex_tlut);
3394 tlut->tmem_addr_base = (tlut->tmem_addr_base&~0xff000000)|(_SHIFTL(_gxtextlutids[mapid],24,8));
3395 GX_LOAD_BP_REG(tlut->tmem_addr_base);
3398 __gx->texMapSize[mapid] = ptr->tex_size;
3399 __gx->texMapWrap[mapid] = ptr->tex_filt;
3401 __gx->dirtyState |= 0x0001;
3404 void GX_PreloadEntireTexture(GXTexObj *obj,GXTexRegion *region)
3406 u32 i,fmt;
3407 s32 wd,ht;
3408 u16 cnt = 0;
3409 u32 regA = 0;
3410 u32 regB = 0;
3411 u32 regC = 0;
3412 u32 regD = 0;
3413 struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3414 struct __gx_texregion *reg = (struct __gx_texregion*)region;
3416 regA = (regA&~0xff000000)|(_SHIFTL(0x60,24,8));
3417 regA = (regA&~0x00ffffff)|(ptr->tex_maddr&~0xff000000);
3419 regB = (regB&~0xff000000)|(_SHIFTL(0x61,24,8));
3420 regB = (regB&~0x00007fff)|(reg->tmem_even&0x00007fff);
3422 regC = (regC&~0xff000000)|(_SHIFTL(0x62,24,8));
3423 regC = (regC&~0x00007fff)|(reg->tmem_odd&0x00007fff);
3425 regD = (regD&~0xff000000)|(_SHIFTL(0x63,24,8));
3426 regD = (regD&~0x00007fff)|(ptr->tex_tile_cnt&0x00007fff);
3427 regD = (regD&~0x00018000)|(_SHIFTL(ptr->tex_tile_type,15,2));
3429 fmt = _SHIFTR(ptr->tex_size,20,4);
3431 __GX_FlushTextureState();
3432 GX_LOAD_BP_REG(regA);
3433 GX_LOAD_BP_REG(regB);
3434 GX_LOAD_BP_REG(regC);
3435 GX_LOAD_BP_REG(regD);
3437 if(ptr->tex_flag&0x01) {
3438 wd = (ptr->tex_size&0x3ff)+1;
3439 ht = _SHIFTR(ptr->tex_size,10,10)+1;
3440 if(wd>ht)
3441 cnt = (31 - (cntlzw(wd)));
3442 else
3443 cnt = (31 - (cntlzw(ht)));
3446 if(cnt>0) {
3447 u32 tmem_even,tmem_odd,maddr;
3448 u32 tile_cnt = ptr->tex_tile_cnt;
3450 tmem_even = (reg->tmem_even&0xffff);
3451 tmem_odd = (reg->tmem_odd&0xffff);
3452 maddr = (ptr->tex_maddr&~0xff000000);
3454 i = 0;
3455 while(cnt) {
3456 u32 w,h;
3457 u32 te,to;
3458 u32 xshift,yshift;
3460 if(fmt==GX_TF_RGBA8) {
3461 tmem_even += tile_cnt;
3462 tmem_odd += tile_cnt;
3463 maddr += (tile_cnt<<1);
3464 } else {
3465 maddr += tile_cnt;
3466 if(i&1) tmem_odd += tile_cnt;
3467 else tmem_even += tile_cnt;
3470 te = tmem_even;
3471 to = tmem_odd;
3472 if(i&1) {
3473 te = tmem_odd;
3474 to = tmem_even;
3477 w = wd>>(i+1);
3478 h = wd>>(i+1);
3479 switch(ptr->tex_fmt) {
3480 case GX_TF_I4:
3481 case GX_TF_IA4:
3482 case GX_TF_CI4:
3483 case GX_TF_CMPR:
3484 xshift = 3;
3485 yshift = 3;
3486 break;
3487 case GX_TF_I8:
3488 case GX_TF_CI8:
3489 xshift = 3;
3490 yshift = 2;
3491 break;
3492 case GX_TF_IA8:
3493 case GX_TF_RGB5A3:
3494 case GX_TF_RGB565:
3495 case GX_TF_CI14:
3496 xshift = 2;
3497 yshift = 2;
3498 break;
3499 default:
3500 xshift = 0;
3501 yshift = 0;
3502 break;
3505 if(!w) w = 1;
3506 if(!h) h = 1;
3508 regA = ((regA&~0x00ffffff)|(maddr&0x00ffffff));
3509 GX_LOAD_BP_REG(regA);
3511 regB = ((regB&~0x00007fff)|(te&0x00007fff));
3512 GX_LOAD_BP_REG(regB);
3514 regC = ((regC&~0x00007fff)|(to&0x00007fff));
3515 GX_LOAD_BP_REG(regC);
3517 tile_cnt = (((w+(1<<xshift))-1)>>xshift)*(((h+(1<<yshift))-1)>>yshift);
3518 regD = ((regD&~0x00007fff)|(tile_cnt&0x00007fff));
3519 GX_LOAD_BP_REG(regD);
3521 ++i;
3522 --cnt;
3525 __GX_FlushTextureState();
3528 void GX_InvalidateTexAll()
3530 __GX_FlushTextureState();
3531 GX_LOAD_BP_REG(0x66001000);
3532 GX_LOAD_BP_REG(0x66001100);
3533 __GX_FlushTextureState();
3536 void GX_InvalidateTexRegion(GXTexRegion *region)
3538 u8 ismipmap;
3539 s32 cw_e,ch_e,cw_o,ch_o;
3540 u32 size,tmp,regvalA = 0,regvalB = 0;
3541 struct __gx_texregion *ptr = (struct __gx_texregion*)region;
3543 cw_e = (_SHIFTR(ptr->tmem_even,15,3))-1;
3544 ch_e = (_SHIFTR(ptr->tmem_even,18,3))-1;
3546 cw_o = (_SHIFTR(ptr->tmem_odd,15,3))-1;
3547 ch_o = (_SHIFTR(ptr->tmem_odd,18,3))-1;
3549 if(cw_e<0) cw_e = 0;
3550 if(ch_e<0) ch_e = 0;
3551 if(cw_o<0) cw_o = 0;
3552 if(ch_o<0) ch_o = 0;
3554 ismipmap = ptr->ismipmap;
3556 tmp = size = cw_e+ch_e;
3557 if(ismipmap) size = (tmp+cw_o+ch_o)-2;
3558 regvalA = _SHIFTR((ptr->tmem_even&0x7fff),6,9)|(_SHIFTL(size,9,4))|(_SHIFTL(0x66,24,8));
3560 if(cw_o!=0) {
3561 size = cw_o+ch_o;
3562 if(ismipmap) size += (tmp-2);
3563 regvalB = _SHIFTR((ptr->tmem_odd&0x7fff),6,9)|(_SHIFTL(size,9,4))|(_SHIFTL(0x66,24,8));
3565 __GX_FlushTextureState();
3566 GX_LOAD_BP_REG(regvalA);
3567 if(cw_o!=0) GX_LOAD_BP_REG(regvalB);
3568 __GX_FlushTextureState();
3571 void GX_LoadTlut(GXTlutObj *obj,u32 tlut_name)
3573 struct __gx_tlutregion *region = NULL;
3574 struct __gx_tlutobj *ptr = (struct __gx_tlutobj*)obj;
3576 if(tlut_regionCB)
3577 region = (struct __gx_tlutregion*)tlut_regionCB(tlut_name);
3579 __GX_FlushTextureState();
3580 GX_LOAD_BP_REG(ptr->tlut_maddr);
3581 GX_LOAD_BP_REG(region->tmem_addr_conf);
3582 __GX_FlushTextureState();
3584 region->tmem_addr_base = (ptr->tlut_fmt&~0x3ff)|(region->tmem_addr_conf&0x3ff);
3585 region->tlut_maddr = ptr->tlut_maddr;
3586 region->tlut_nentries = ptr->tlut_nentries;
3589 void GX_SetTexCoordScaleManually(u8 texcoord,u8 enable,u16 ss,u16 ts)
3591 u32 reg;
3593 __gx->texCoordManually = (__gx->texCoordManually&~(_SHIFTL(1,texcoord,1)))|(_SHIFTL(enable,texcoord,1));
3594 if(!enable) return;
3596 reg = (texcoord&0x7);
3597 __gx->suSsize[reg] = (__gx->suSsize[reg]&~0xffff)|((ss-1)&0xffff);
3598 __gx->suTsize[reg] = (__gx->suTsize[reg]&~0xffff)|((ts-1)&0xffff);
3600 GX_LOAD_BP_REG(__gx->suSsize[reg]);
3601 GX_LOAD_BP_REG(__gx->suTsize[reg]);
3604 void GX_SetTexCoordCylWrap(u8 texcoord,u8 s_enable,u8 t_enable)
3606 u32 reg;
3608 reg = (texcoord&0x7);
3609 __gx->suSsize[reg] = (__gx->suSsize[reg]&~0x20000)|(_SHIFTL(s_enable,17,1));
3610 __gx->suTsize[reg] = (__gx->suTsize[reg]&~0x20000)|(_SHIFTL(t_enable,17,1));
3612 if(!(__gx->texCoordManually&(_SHIFTL(1,texcoord,1)))) return;
3614 GX_LOAD_BP_REG(__gx->suSsize[reg]);
3615 GX_LOAD_BP_REG(__gx->suTsize[reg]);
3618 void GX_SetTexCoordBias(u8 texcoord,u8 s_enable,u8 t_enable)
3620 u32 reg;
3622 reg = (texcoord&0x7);
3623 __gx->suSsize[reg] = (__gx->suSsize[reg]&~0x10000)|(_SHIFTL(s_enable,16,1));
3624 __gx->suTsize[reg] = (__gx->suTsize[reg]&~0x10000)|(_SHIFTL(t_enable,16,1));
3626 if(!(__gx->texCoordManually&(_SHIFTL(1,texcoord,1)))) return;
3628 GX_LOAD_BP_REG(__gx->suSsize[reg]);
3629 GX_LOAD_BP_REG(__gx->suTsize[reg]);
3632 GXTexRegionCallback GX_SetTexRegionCallback(GXTexRegionCallback cb)
3634 u32 level;
3635 GXTexRegionCallback ret;
3637 _CPU_ISR_Disable(level);
3638 ret = regionCB;
3639 regionCB = cb;
3640 _CPU_ISR_Restore(level);
3642 return ret;
3645 GXTlutRegionCallback GX_SetTlutRegionCallback(GXTlutRegionCallback cb)
3647 u32 level;
3648 GXTlutRegionCallback ret;
3650 _CPU_ISR_Disable(level);
3651 ret = tlut_regionCB;
3652 tlut_regionCB = cb;
3653 _CPU_ISR_Restore(level);
3655 return ret;
3658 void GX_SetBlendMode(u8 type,u8 src_fact,u8 dst_fact,u8 op)
3660 __gx->peCMode0 = (__gx->peCMode0&~0x1);
3661 if(type==GX_BM_BLEND || type==GX_BM_SUBTRACT) __gx->peCMode0 |= 0x1;
3663 __gx->peCMode0 = (__gx->peCMode0&~0x800);
3664 if(type==GX_BM_SUBTRACT) __gx->peCMode0 |= 0x800;
3666 __gx->peCMode0 = (__gx->peCMode0&~0x2);
3667 if(type==GX_BM_LOGIC) __gx->peCMode0 |= 0x2;
3669 __gx->peCMode0 = (__gx->peCMode0&~0xF000)|(_SHIFTL(op,12,4));
3670 __gx->peCMode0 = (__gx->peCMode0&~0xE0)|(_SHIFTL(dst_fact,5,3));
3671 __gx->peCMode0 = (__gx->peCMode0&~0x700)|(_SHIFTL(src_fact,8,3));
3673 GX_LOAD_BP_REG(__gx->peCMode0);
3676 void GX_ClearVtxDesc()
3678 __gx->vcdNrms = 0;
3679 __gx->vcdClear = ((__gx->vcdClear&~0x0600)|0x0200);
3680 __gx->vcdLo = __gx->vcdHi = 0;
3681 __gx->dirtyState |= 0x0008;
3684 void GX_SetLineWidth(u8 width,u8 fmt)
3686 __gx->lpWidth = (__gx->lpWidth&~0xff)|(width&0xff);
3687 __gx->lpWidth = (__gx->lpWidth&~0x70000)|(_SHIFTL(fmt,16,3));
3688 GX_LOAD_BP_REG(__gx->lpWidth);
3691 void GX_SetPointSize(u8 width,u8 fmt)
3693 __gx->lpWidth = (__gx->lpWidth&~0xFF00)|(_SHIFTL(width,8,8));
3694 __gx->lpWidth = (__gx->lpWidth&~0x380000)|(_SHIFTL(fmt,19,3));
3695 GX_LOAD_BP_REG(__gx->lpWidth);
3698 void GX_SetTevColor(u8 tev_regid,GXColor color)
3700 u32 reg;
3702 reg = (_SHIFTL((0xe0+(tev_regid<<1)),24,8)|(_SHIFTL(color.a,12,8))|(color.r&0xff));
3703 GX_LOAD_BP_REG(reg);
3705 reg = (_SHIFTL((0xe1+(tev_regid<<1)),24,8)|(_SHIFTL(color.g,12,8))|(color.b&0xff));
3706 GX_LOAD_BP_REG(reg);
3708 //this two calls should obviously flush the Write Gather Pipe.
3709 GX_LOAD_BP_REG(reg);
3710 GX_LOAD_BP_REG(reg);
3713 void GX_SetTevColorS10(u8 tev_regid,GXColorS10 color)
3715 u32 reg;
3717 reg = (_SHIFTL((0xe0+(tev_regid<<1)),24,8)|(_SHIFTL(color.a,12,11))|(color.r&0x7ff));
3718 GX_LOAD_BP_REG(reg);
3720 reg = (_SHIFTL((0xe1+(tev_regid<<1)),24,8)|(_SHIFTL(color.g,12,11))|(color.b&0x7ff));
3721 GX_LOAD_BP_REG(reg);
3723 //this two calls should obviously flush the Write Gather Pipe.
3724 GX_LOAD_BP_REG(reg);
3725 GX_LOAD_BP_REG(reg);
3728 void GX_SetTevKColor(u8 tev_kregid,GXColor color)
3730 u32 reg;
3732 reg = (_SHIFTL((0xe0+(tev_kregid<<1)),24,8)|(_SHIFTL(1,23,1))|(_SHIFTL(color.a,12,8))|(color.r&0xff));
3733 GX_LOAD_BP_REG(reg);
3735 reg = (_SHIFTL((0xe1+(tev_kregid<<1)),24,8)|(_SHIFTL(1,23,1))|(_SHIFTL(color.g,12,8))|(color.b&0xff));
3736 GX_LOAD_BP_REG(reg);
3738 //this two calls should obviously flush the Write Gather Pipe.
3739 GX_LOAD_BP_REG(reg);
3740 GX_LOAD_BP_REG(reg);
3743 void GX_SetTevKColorS10(u8 tev_kregid,GXColorS10 color)
3745 u32 reg;
3747 reg = (_SHIFTL((0xe0+(tev_kregid<<1)),24,8)|(_SHIFTL(1,23,1))|(_SHIFTL(color.a,12,11))|(color.r&0x7ff));
3748 GX_LOAD_BP_REG(reg);
3750 reg = (_SHIFTL((0xe1+(tev_kregid<<1)),24,8)|(_SHIFTL(1,23,1))|(_SHIFTL(color.g,12,11))|(color.b&0x7ff));
3751 GX_LOAD_BP_REG(reg);
3753 //this two calls should obviously flush the Write Gather Pipe.
3754 GX_LOAD_BP_REG(reg);
3755 GX_LOAD_BP_REG(reg);
3758 void GX_SetTevOp(u8 tevstage,u8 mode)
3760 u8 defcolor = GX_CC_RASC;
3761 u8 defalpha = GX_CA_RASA;
3763 if(tevstage!=GX_TEVSTAGE0) {
3764 defcolor = GX_CC_CPREV;
3765 defalpha = GX_CA_APREV;
3768 switch(mode) {
3769 case GX_MODULATE:
3770 GX_SetTevColorIn(tevstage,GX_CC_ZERO,GX_CC_TEXC,defcolor,GX_CC_ZERO);
3771 GX_SetTevAlphaIn(tevstage,GX_CA_ZERO,GX_CA_TEXA,defalpha,GX_CA_ZERO);
3772 break;
3773 case GX_DECAL:
3774 GX_SetTevColorIn(tevstage,defcolor,GX_CC_TEXC,GX_CC_TEXA,GX_CC_ZERO);
3775 GX_SetTevAlphaIn(tevstage,GX_CA_ZERO,GX_CA_ZERO,GX_CA_ZERO,defalpha);
3776 break;
3777 case GX_BLEND:
3778 GX_SetTevColorIn(tevstage,defcolor,GX_CC_ONE,GX_CC_TEXC,GX_CC_ZERO);
3779 GX_SetTevAlphaIn(tevstage,GX_CA_ZERO,GX_CA_TEXA,defalpha,GX_CA_RASA);
3780 break;
3781 case GX_REPLACE:
3782 GX_SetTevColorIn(tevstage,GX_CC_ZERO,GX_CC_ZERO,GX_CC_ZERO,GX_CC_TEXC);
3783 GX_SetTevAlphaIn(tevstage,GX_CA_ZERO,GX_CA_ZERO,GX_CA_ZERO,GX_CA_TEXA);
3784 break;
3785 case GX_PASSCLR:
3786 GX_SetTevColorIn(tevstage,GX_CC_ZERO,GX_CC_ZERO,GX_CC_ZERO,defcolor);
3787 GX_SetTevAlphaIn(tevstage,GX_CC_A2,GX_CC_A2,GX_CC_A2,defalpha);
3788 break;
3790 GX_SetTevColorOp(tevstage,GX_TEV_ADD,GX_TB_ZERO,GX_CS_SCALE_1,GX_TRUE,GX_TEVPREV);
3791 GX_SetTevAlphaOp(tevstage,GX_TEV_ADD,GX_TB_ZERO,GX_CS_SCALE_1,GX_TRUE,GX_TEVPREV);
3794 void GX_SetTevColorIn(u8 tevstage,u8 a,u8 b,u8 c,u8 d)
3796 u32 reg = (tevstage&0xf);
3797 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0xF000)|(_SHIFTL(a,12,4));
3798 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0xF00)|(_SHIFTL(b,8,4));
3799 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0xF0)|(_SHIFTL(c,4,4));
3800 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0xf)|(d&0xf);
3802 GX_LOAD_BP_REG(__gx->tevColorEnv[reg]);
3805 void GX_SetTevAlphaIn(u8 tevstage,u8 a,u8 b,u8 c,u8 d)
3807 u32 reg = (tevstage&0xf);
3808 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0xE000)|(_SHIFTL(a,13,3));
3809 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x1C00)|(_SHIFTL(b,10,3));
3810 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x380)|(_SHIFTL(c,7,3));
3811 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x70)|(_SHIFTL(d,4,3));
3813 GX_LOAD_BP_REG(__gx->tevAlphaEnv[reg]);
3816 void GX_SetTevColorOp(u8 tevstage,u8 tevop,u8 tevbias,u8 tevscale,u8 clamp,u8 tevregid)
3818 /* set tev op add/sub*/
3819 u32 reg = (tevstage&0xf);
3820 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x40000)|(_SHIFTL(tevop,18,1));
3821 if(tevop<=GX_TEV_SUB) {
3822 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x300000)|(_SHIFTL(tevscale,20,2));
3823 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x30000)|(_SHIFTL(tevbias,16,2));
3824 } else {
3825 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x300000)|((_SHIFTL(tevop,19,4))&0x300000);
3826 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x30000)|0x30000;
3828 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x80000)|(_SHIFTL(clamp,19,1));
3829 __gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0xC00000)|(_SHIFTL(tevregid,22,2));
3831 GX_LOAD_BP_REG(__gx->tevColorEnv[reg]);
3834 void GX_SetTevAlphaOp(u8 tevstage,u8 tevop,u8 tevbias,u8 tevscale,u8 clamp,u8 tevregid)
3836 /* set tev op add/sub*/
3837 u32 reg = (tevstage&0xf);
3838 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x40000)|(_SHIFTL(tevop,18,1));
3839 if(tevop<=GX_TEV_SUB) {
3840 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x300000)|(_SHIFTL(tevscale,20,2));
3841 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x30000)|(_SHIFTL(tevbias,16,2));
3842 } else {
3843 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x300000)|((_SHIFTL(tevop,19,4))&0x300000);
3844 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x30000)|0x30000;
3846 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x80000)|(_SHIFTL(clamp,19,1));
3847 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0xC00000)|(_SHIFTL(tevregid,22,2));
3849 GX_LOAD_BP_REG(__gx->tevAlphaEnv[reg]);
3852 void GX_SetCullMode(u8 mode)
3854 static u8 cm2hw[] = { 0, 2, 1, 3 };
3856 __gx->genMode = (__gx->genMode&~0xC000)|(_SHIFTL(cm2hw[mode],14,2));
3857 __gx->dirtyState |= 0x0004;
3860 void GX_SetCoPlanar(u8 enable)
3862 __gx->genMode = (__gx->genMode&~0x80000)|(_SHIFTL(enable,19,1));
3863 GX_LOAD_BP_REG(0xFE080000);
3864 GX_LOAD_BP_REG(__gx->genMode);
3867 void GX_EnableTexOffsets(u8 coord,u8 line_enable,u8 point_enable)
3869 u32 reg = (coord&0x7);
3870 __gx->suSsize[reg] = (__gx->suSsize[reg]&~0x40000)|(_SHIFTL(line_enable,18,1));
3871 __gx->suSsize[reg] = (__gx->suSsize[reg]&~0x80000)|(_SHIFTL(point_enable,19,1));
3872 GX_LOAD_BP_REG(__gx->suSsize[reg]);
3875 void GX_SetClipMode(u8 mode)
3877 GX_LOAD_XF_REG(0x1005,(mode&1));
3880 void GX_SetScissor(u32 xOrigin,u32 yOrigin,u32 wd,u32 ht)
3882 u32 xo = xOrigin+0x156;
3883 u32 yo = yOrigin+0x156;
3884 u32 nwd = xo+(wd-1);
3885 u32 nht = yo+(ht-1);
3887 __gx->sciTLcorner = (__gx->sciTLcorner&~0x7ff)|(yo&0x7ff);
3888 __gx->sciTLcorner = (__gx->sciTLcorner&~0x7FF000)|(_SHIFTL(xo,12,11));
3890 __gx->sciBRcorner = (__gx->sciBRcorner&~0x7ff)|(nht&0xfff);
3891 __gx->sciBRcorner = (__gx->sciBRcorner&~0x7FF000)|(_SHIFTL(nwd,12,11));
3893 GX_LOAD_BP_REG(__gx->sciTLcorner);
3894 GX_LOAD_BP_REG(__gx->sciBRcorner);
3897 void GX_SetScissorBoxOffset(s32 xoffset,s32 yoffset)
3899 s32 xoff = _SHIFTR((xoffset+0x156),1,24);
3900 s32 yoff = _SHIFTR((yoffset+0x156),1,24);
3902 GX_LOAD_BP_REG((0x59000000|(_SHIFTL(yoff,10,10))|(xoff&0x3ff)));
3905 void GX_SetNumChans(u8 num)
3907 __gx->genMode = (__gx->genMode&~0x70)|(_SHIFTL(num,4,3));
3908 __gx->dirtyState |= 0x01000004;
3911 void GX_SetTevOrder(u8 tevstage,u8 texcoord,u32 texmap,u8 color)
3913 u8 colid;
3914 u32 texm,texc,tmp;
3915 u32 reg = 3+(_SHIFTR(tevstage,1,3));
3917 __gx->tevTexMap[(tevstage&0xf)] = texmap;
3919 texm = (texmap&~0x100);
3920 if(texm>=GX_MAX_TEXMAP) texm = 0;
3921 if(texcoord>=GX_MAXCOORD) {
3922 texc = 0;
3923 __gx->tevTexCoordEnable &= ~(_SHIFTL(1,tevstage,1));
3924 } else {
3925 texc = texcoord;
3926 __gx->tevTexCoordEnable |= (_SHIFTL(1,tevstage,1));
3929 if(tevstage&1) {
3930 __gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x7000)|(_SHIFTL(texm,12,3));
3931 __gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x38000)|(_SHIFTL(texc,15,3));
3933 colid = GX_ALPHA_BUMP;
3934 if(color!=GX_COLORNULL) colid = _gxtevcolid[color];
3935 __gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x380000)|(_SHIFTL(colid,19,3));
3937 tmp = 1;
3938 if(texmap==GX_TEXMAP_NULL || texmap&0x100) tmp = 0;
3939 __gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x40000)|(_SHIFTL(tmp,18,1));
3940 } else {
3941 __gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x7)|(texm&0x7);
3942 __gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x38)|(_SHIFTL(texc,3,3));
3944 colid = GX_ALPHA_BUMP;
3945 if(color!=GX_COLORNULL) colid = _gxtevcolid[color];
3946 __gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x380)|(_SHIFTL(colid,7,3));
3948 tmp = 1;
3949 if(texmap==GX_TEXMAP_NULL || texmap&0x100) tmp = 0;
3950 __gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x40)|(_SHIFTL(tmp,6,1));
3952 GX_LOAD_BP_REG(__gx->tevRasOrder[reg]);
3953 __gx->dirtyState |= 0x0001;
3956 void GX_SetNumTevStages(u8 num)
3958 __gx->genMode = (__gx->genMode&~0x3C00)|(_SHIFTL((num-1),10,4));
3959 __gx->dirtyState |= 0x0004;
3962 void GX_SetAlphaCompare(u8 comp0,u8 ref0,u8 aop,u8 comp1,u8 ref1)
3964 u32 val = 0;
3965 val = (_SHIFTL(aop,22,2))|(_SHIFTL(comp1,19,3))|(_SHIFTL(comp0,16,3))|(_SHIFTL(ref1,8,8))|(ref0&0xff);
3966 GX_LOAD_BP_REG(0xf3000000|val);
3969 void GX_SetTevKColorSel(u8 tevstage,u8 sel)
3971 u32 reg = (_SHIFTR(tevstage,1,3));
3973 if(tevstage&1)
3974 __gx->tevSwapModeTable[reg] = (__gx->tevSwapModeTable[reg]&~0x7C000)|(_SHIFTL(sel,14,5));
3975 else
3976 __gx->tevSwapModeTable[reg] = (__gx->tevSwapModeTable[reg]&~0x1F0)|(_SHIFTL(sel,4,5));
3977 GX_LOAD_BP_REG(__gx->tevSwapModeTable[reg]);
3980 void GX_SetTevKAlphaSel(u8 tevstage,u8 sel)
3982 u32 reg = (_SHIFTR(tevstage,1,3));
3984 if(tevstage&1)
3985 __gx->tevSwapModeTable[reg] = (__gx->tevSwapModeTable[reg]&~0xF80000)|(_SHIFTL(sel,19,5));
3986 else
3987 __gx->tevSwapModeTable[reg] = (__gx->tevSwapModeTable[reg]&~0x3E00)|(_SHIFTL(sel,9,5));
3988 GX_LOAD_BP_REG(__gx->tevSwapModeTable[reg]);
3991 void GX_SetTevSwapMode(u8 tevstage,u8 ras_sel,u8 tex_sel)
3993 u32 reg = (tevstage&0xf);
3994 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x3)|(ras_sel&0x3);
3995 __gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0xC)|(_SHIFTL(tex_sel,2,2));
3996 GX_LOAD_BP_REG(__gx->tevAlphaEnv[reg]);
3999 void GX_SetTevSwapModeTable(u8 swapid,u8 r,u8 g,u8 b,u8 a)
4001 u32 regA = 0+(_SHIFTL(swapid,1,3));
4002 u32 regB = 1+(_SHIFTL(swapid,1,3));
4004 __gx->tevSwapModeTable[regA] = (__gx->tevSwapModeTable[regA]&~0x3)|(r&0x3);
4005 __gx->tevSwapModeTable[regA] = (__gx->tevSwapModeTable[regA]&~0xC)|(_SHIFTL(g,2,2));
4006 GX_LOAD_BP_REG(__gx->tevSwapModeTable[regA]);
4008 __gx->tevSwapModeTable[regB] = (__gx->tevSwapModeTable[regB]&~0x3)|(b&0x3);
4009 __gx->tevSwapModeTable[regB] = (__gx->tevSwapModeTable[regB]&~0xC)|(_SHIFTL(a,2,2));
4010 GX_LOAD_BP_REG(__gx->tevSwapModeTable[regB]);
4013 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)
4015 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));
4016 GX_LOAD_BP_REG(val);
4019 void GX_SetTevDirect(u8 tevstage)
4021 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);
4024 void GX_SetNumIndStages(u8 nstages)
4026 __gx->genMode = (__gx->genMode&~0x70000)|(_SHIFTL(nstages,16,3));
4027 __gx->dirtyState |= 0x0006;
4030 void GX_SetIndTexMatrix(u8 indtexmtx,f32 offset_mtx[2][3],s8 scale_exp)
4032 u32 ma,mb;
4033 u32 val,s,idx;
4035 if(indtexmtx>0x00 && indtexmtx<0x04) indtexmtx -= 0x01;
4036 else if(indtexmtx>0x04 && indtexmtx<0x08) indtexmtx -= 0x05;
4037 else if(indtexmtx>0x08 && indtexmtx<0x0C) indtexmtx -= 0x09;
4038 else indtexmtx = 0x00;
4040 s = (scale_exp+17);
4041 idx = ((indtexmtx<<2)-indtexmtx);
4043 ma = (u32)(offset_mtx[0][0]*1024.0F);
4044 mb = (u32)(offset_mtx[1][0]*1024.0F);
4045 val = (_SHIFTL((0x06+idx),24,8)|_SHIFTL(s,22,2)|_SHIFTL(mb,11,11)|_SHIFTL(ma,0,11));
4046 GX_LOAD_BP_REG(val);
4048 ma = (u32)(offset_mtx[0][1]*1024.0F);
4049 mb = (u32)(offset_mtx[1][1]*1024.0F);
4050 val = (_SHIFTL((0x07+idx),24,8)|_SHIFTL((s>>2),22,2)|_SHIFTL(mb,11,11)|_SHIFTL(ma,0,11));
4051 GX_LOAD_BP_REG(val);
4053 ma = (u32)(offset_mtx[0][2]*1024.0F);
4054 mb = (u32)(offset_mtx[1][2]*1024.0F);
4055 val = (_SHIFTL((0x08+idx),24,8)|_SHIFTL((s>>4),22,2)|_SHIFTL(mb,11,11)|_SHIFTL(ma,0,11));
4056 GX_LOAD_BP_REG(val);
4059 void GX_SetTevIndBumpST(u8 tevstage,u8 indstage,u8 mtx_sel)
4061 u8 sel_s,sel_t;
4063 switch(mtx_sel) {
4064 case GX_ITM_0:
4065 sel_s = GX_ITM_S0;
4066 sel_t = GX_ITM_T0;
4067 break;
4068 case GX_ITM_1:
4069 sel_s = GX_ITM_S1;
4070 sel_t = GX_ITM_T1;
4071 break;
4072 case GX_ITM_2:
4073 sel_s = GX_ITM_S2;
4074 sel_t = GX_ITM_T2;
4075 break;
4076 default:
4077 sel_s = GX_ITM_OFF;
4078 sel_t = GX_ITM_OFF;
4079 break;
4082 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);
4083 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);
4084 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);
4087 void GX_SetTevIndBumpXYZ(u8 tevstage,u8 indstage,u8 mtx_sel)
4089 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);
4092 void GX_SetTevIndRepeat(u8 tevstage)
4094 GX_SetTevIndirect(tevstage,GX_INDTEXSTAGE0,GX_ITF_8,GX_ITB_NONE,GX_ITM_OFF,GX_ITW_0,GX_ITW_0,GX_TRUE,GX_FALSE,GX_ITBA_OFF);
4097 void GX_SetIndTexCoordScale(u8 indtexid,u8 scale_s,u8 scale_t)
4099 switch(indtexid) {
4100 case GX_INDTEXSTAGE0:
4101 __gx->tevRasOrder[0] = (__gx->tevRasOrder[0]&~0x0f)|(scale_s&0x0f);
4102 __gx->tevRasOrder[0] = (__gx->tevRasOrder[0]&~0xF0)|(_SHIFTL(scale_t,4,4));
4103 GX_LOAD_BP_REG(__gx->tevRasOrder[0]);
4104 break;
4105 case GX_INDTEXSTAGE1:
4106 __gx->tevRasOrder[0] = (__gx->tevRasOrder[0]&~0xF00)|(_SHIFTL(scale_s,8,4));
4107 __gx->tevRasOrder[0] = (__gx->tevRasOrder[0]&~0xF000)|(_SHIFTL(scale_t,12,4));
4108 GX_LOAD_BP_REG(__gx->tevRasOrder[0]);
4109 break;
4110 case GX_INDTEXSTAGE2:
4111 __gx->tevRasOrder[1] = (__gx->tevRasOrder[1]&~0x0f)|(scale_s&0x0f);
4112 __gx->tevRasOrder[1] = (__gx->tevRasOrder[1]&~0xF0)|(_SHIFTL(scale_t,4,4));
4113 GX_LOAD_BP_REG(__gx->tevRasOrder[1]);
4114 break;
4115 case GX_INDTEXSTAGE3:
4116 __gx->tevRasOrder[1] = (__gx->tevRasOrder[1]&~0xF00)|(_SHIFTL(scale_s,8,4));
4117 __gx->tevRasOrder[1] = (__gx->tevRasOrder[1]&~0xF000)|(_SHIFTL(scale_t,12,4));
4118 GX_LOAD_BP_REG(__gx->tevRasOrder[1]);
4119 break;
4123 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)
4125 s32 wrap_s,wrap_t;
4126 f32 offset_mtx[2][3];
4127 f64 fdspace_x,fdspace_y;
4128 u32 fbuf_x[2] = { 0x43300000,tilespacing_x };
4129 u32 fbuf_y[2] = { 0x43300000,tilespacing_y };
4131 wrap_s = GX_ITW_OFF;
4132 if(tilesize_x==0x0010) wrap_s = GX_ITW_16;
4133 else if(tilesize_x==0x0020) wrap_s = GX_ITW_32;
4134 else if(tilesize_x==0x0040) wrap_s = GX_ITW_64;
4135 else if(tilesize_x==0x0080) wrap_s = GX_ITW_128;
4136 else if(tilesize_x==0x0100) wrap_s = GX_ITW_256;
4138 wrap_t = GX_ITW_OFF;
4139 if(tilesize_y==0x0010) wrap_t = GX_ITW_16;
4140 else if(tilesize_y==0x0020) wrap_t = GX_ITW_32;
4141 else if(tilesize_y==0x0040) wrap_t = GX_ITW_64;
4142 else if(tilesize_y==0x0080) wrap_t = GX_ITW_128;
4143 else if(tilesize_y==0x0100) wrap_t = GX_ITW_256;
4145 fdspace_x = *(f64*)((void*)fbuf_x);
4146 fdspace_y = *(f64*)((void*)fbuf_y);
4148 offset_mtx[0][0] = (f32)((fdspace_x - 4503599627370496.0F)*0.00097656250F);
4149 offset_mtx[0][1] = 0.0F;
4150 offset_mtx[0][2] = 0.0F;
4151 offset_mtx[1][0] = 0.0F;
4152 offset_mtx[1][1] = (f32)((fdspace_y - 4503599627370496.0F)*0.00097656250F);
4153 offset_mtx[1][2] = 0.0F;
4155 GX_SetIndTexMatrix(indtexmtx,offset_mtx,10);
4156 GX_SetTevIndirect(tevstage,indtexid,indtexfmt,bias_sel,indtexmtx,wrap_s,wrap_t,GX_FALSE,GX_TRUE,alpha_sel);
4159 void GX_SetFog(u8 type,f32 startz,f32 endz,f32 nearz,f32 farz,GXColor col)
4161 f32 A, B, B_mant, C, A_f;
4162 u32 b_expn, b_m, a_hex, c_hex,val,proj = 0;
4163 union ieee32 { f32 f; u32 i; } v;
4165 proj = _SHIFTR(type,3,1);
4167 // Calculate constants a, b, and c (TEV HW requirements).
4168 if(proj) { // Orthographic Fog Type
4169 if((farz==nearz) || (endz==startz)) {
4170 // take care of the odd-ball case.
4171 A_f = 0.0f;
4172 C = 0.0f;
4173 } else {
4174 A = 1.0f/(endz-startz);
4175 A_f = (farz-nearz) * A;
4176 C = (startz-nearz) * A;
4179 b_expn = 0;
4180 b_m = 0;
4181 } else { // Perspective Fog Type
4182 // Calculate constants a, b, and c (TEV HW requirements).
4183 if((farz==nearz) || (endz==startz)) {
4184 // take care of the odd-ball case.
4185 A = 0.0f;
4186 B = 0.5f;
4187 C = 0.0f;
4188 } else {
4189 A = (farz*nearz)/((farz-nearz)*(endz-startz));
4190 B = farz/(farz-nearz);
4191 C = startz/(endz-startz);
4194 B_mant = B;
4195 b_expn = 1;
4196 while(B_mant>1.0f) {
4197 B_mant /= 2.0f;
4198 b_expn++;
4201 while((B_mant>0.0f) && (B_mant<0.5f)) {
4202 B_mant *= 2.0f;
4203 b_expn--;
4206 A_f = A/(1<<(b_expn));
4207 b_m = (u32)(B_mant * 8388638.0f);
4209 v.f = A_f;
4210 a_hex = v.i;
4212 v.f = C;
4213 c_hex = v.i;
4215 val = 0xee000000|(_SHIFTR(a_hex,12,20));
4216 GX_LOAD_BP_REG(val);
4218 val = 0xef000000|(b_m&0x00ffffff);
4219 GX_LOAD_BP_REG(val);
4221 val = 0xf0000000|(b_expn&0x1f);
4222 GX_LOAD_BP_REG(val);
4224 val = 0xf1000000|(_SHIFTL(type,21,3))|(_SHIFTL(proj,20,1))|(_SHIFTR(c_hex,12,20));
4225 GX_LOAD_BP_REG(val);
4227 val = 0xf2000000|(_SHIFTL(col.r,16,8))|(_SHIFTL(col.g,8,8))|(col.b&0xff);
4228 GX_LOAD_BP_REG(val);
4231 void GX_InitFogAdjTable(GXFogAdjTbl *table,u16 width,f32 projmtx[4][4])
4233 u32 i,val7;
4234 f32 val0,val1,val2,val4,val5,val6;
4236 if(projmtx[3][3]==0.0f) {
4237 val0 = projmtx[2][3]/(projmtx[2][2] - 1.0f);
4238 val1 = val0/projmtx[0][0];
4239 } else {
4240 val1 = 1.0f/projmtx[0][0];
4241 val0 = val1*1.7320499f;
4244 val2 = val0*val0;
4245 val4 = 2.0f/(f32)width;
4246 for(i=0;i<10;i++) {
4247 val5 = (i+1)*32.0f;
4248 val5 *= val4;
4249 val5 *= val1;
4250 val5 *= val5;
4251 val5 /= val2;
4252 val6 = sqrtf(val5 + 1.0f);
4253 val7 = (u32)(val6*256.0f);
4254 table->r[i] = (val7&0x0fff);
4258 void GX_SetFogRangeAdj(u8 enable,u16 center,GXFogAdjTbl *table)
4260 u32 val;
4262 if(enable) {
4263 val = 0xe9000000|(_SHIFTL(table->r[1],12,12))|(table->r[0]&0x0fff);
4264 GX_LOAD_BP_REG(val);
4266 val = 0xea000000|(_SHIFTL(table->r[3],12,12))|(table->r[2]&0x0fff);
4267 GX_LOAD_BP_REG(val);
4269 val = 0xeb000000|(_SHIFTL(table->r[5],12,12))|(table->r[4]&0x0fff);
4270 GX_LOAD_BP_REG(val);
4272 val = 0xec000000|(_SHIFTL(table->r[7],12,12))|(table->r[6]&0x0fff);
4273 GX_LOAD_BP_REG(val);
4275 val = 0xed000000|(_SHIFTL(table->r[9],12,12))|(table->r[8]&0x0fff);
4276 GX_LOAD_BP_REG(val);
4278 val = 0xe8000000|(_SHIFTL(enable,10,1))|((center + 342)&0x03ff);
4279 GX_LOAD_BP_REG(val);
4282 void GX_SetFogColor(GXColor color)
4284 GX_LOAD_BP_REG(0xf2000000|(_SHIFTL(color.r,16,8)|_SHIFTL(color.g,8,8)|(color.b&0xff)));
4287 void GX_SetColorUpdate(u8 enable)
4289 __gx->peCMode0 = (__gx->peCMode0&~0x8)|(_SHIFTL(enable,3,1));
4290 GX_LOAD_BP_REG(__gx->peCMode0);
4293 void GX_SetAlphaUpdate(u8 enable)
4295 __gx->peCMode0 = (__gx->peCMode0&~0x10)|(_SHIFTL(enable,4,1));
4296 GX_LOAD_BP_REG(__gx->peCMode0);
4299 void GX_SetZCompLoc(u8 before_tex)
4301 __gx->peCntrl = (__gx->peCntrl&~0x40)|(_SHIFTL(before_tex,6,1));
4302 GX_LOAD_BP_REG(__gx->peCntrl);
4305 void GX_SetPixelFmt(u8 pix_fmt,u8 z_fmt)
4307 u8 ms_en = 0;
4308 u32 realfmt[8] = {0,1,2,3,4,4,4,5};
4310 __gx->peCntrl = (__gx->peCntrl&~0x7)|(realfmt[pix_fmt]&0x7);
4311 __gx->peCntrl = (__gx->peCntrl&~0x38)|(_SHIFTL(z_fmt,3,3));
4312 GX_LOAD_BP_REG(__gx->peCntrl);
4313 __gx->dirtyState |= 0x0004;
4315 if(pix_fmt==GX_PF_RGB565_Z16) ms_en = 1;
4316 __gx->genMode = (__gx->genMode&~0x200)|(_SHIFTL(ms_en,9,1));
4318 if(realfmt[pix_fmt]==GX_PF_Y8) {
4319 pix_fmt -= GX_PF_Y8;
4320 __gx->peCMode1 = (__gx->peCMode1&~0xC00)|(_SHIFTL(pix_fmt,10,2));
4321 GX_LOAD_BP_REG(__gx->peCMode1);
4325 void GX_SetDither(u8 dither)
4327 __gx->peCMode0 = (__gx->peCMode0&~0x4)|(_SHIFTL(dither,2,1));
4328 GX_LOAD_BP_REG(__gx->peCMode0);
4331 void GX_SetDstAlpha(u8 enable,u8 a)
4333 __gx->peCMode1 = (__gx->peCMode1&~0xff)|(a&0xff);
4334 __gx->peCMode1 = (__gx->peCMode1&~0x100)|(_SHIFTL(enable,8,1));
4335 GX_LOAD_BP_REG(__gx->peCMode1);
4338 void GX_SetFieldMask(u8 even_mask,u8 odd_mask)
4340 u32 val = 0;
4342 val = (_SHIFTL(even_mask,1,1))|(odd_mask&1);
4343 GX_LOAD_BP_REG(0x44000000|val);
4346 void GX_SetFieldMode(u8 field_mode,u8 half_aspect_ratio)
4348 __gx->lpWidth = (__gx->lpWidth&~0x400000)|(_SHIFTL(half_aspect_ratio,22,1));
4349 GX_LOAD_BP_REG(__gx->lpWidth);
4351 __GX_FlushTextureState();
4352 GX_LOAD_BP_REG(0x68000000|(field_mode&1));
4353 __GX_FlushTextureState();
4356 void GX_PokeAlphaMode(u8 func,u8 threshold)
4358 _peReg[3] = (_SHIFTL(func,8,8))|(threshold&0xFF);
4361 void GX_PokeAlphaRead(u8 mode)
4363 _peReg[4] = (mode&~0x4)|0x4;
4366 void GX_PokeDstAlpha(u8 enable,u8 a)
4368 _peReg[2] = (_SHIFTL(enable,8,1))|(a&0xff);
4371 void GX_PokeAlphaUpdate(u8 update_enable)
4373 _peReg[1] = (_peReg[1]&~0x10)|(_SHIFTL(update_enable,4,1));
4376 void GX_PokeColorUpdate(u8 update_enable)
4378 _peReg[1] = (_peReg[1]&~0x8)|(_SHIFTL(update_enable,3,1));
4381 void GX_PokeDither(u8 dither)
4383 _peReg[1] = (_peReg[1]&~0x4)|(_SHIFTL(dither,2,1));
4386 void GX_PokeBlendMode(u8 type,u8 src_fact,u8 dst_fact,u8 op)
4388 u32 regval = _peReg[1];
4390 regval = (regval&~0x1);
4391 if(type==GX_BM_BLEND || type==GX_BM_SUBTRACT) regval |= 0x1;
4393 regval = (regval&~0x800);
4394 if(type==GX_BM_SUBTRACT) regval |= 0x800;
4396 regval = (regval&~0x2);
4397 if(type==GX_BM_LOGIC) regval |= 0x2;
4399 regval = (regval&~0xF000)|(_SHIFTL(op,12,4));
4400 regval = (regval&~0xE0)|(_SHIFTL(dst_fact,5,3));
4401 regval = (regval&~0x700)|(_SHIFTL(src_fact,8,3));
4403 regval |= 0x41000000;
4404 _peReg[1] = (u16)regval;
4407 void GX_PokeARGB(u16 x,u16 y,GXColor color)
4409 u32 regval;
4411 regval = 0xc8000000|(_SHIFTL(x,2,10));
4412 regval = (regval&~0x3FF000)|(_SHIFTL(y,12,10));
4413 *(u32*)regval = _SHIFTL(color.a,24,8)|_SHIFTL(color.r,16,8)|_SHIFTL(color.g,8,8)|(color.b&0xff);
4416 void GX_PeekARGB(u16 x,u16 y,GXColor *color)
4418 u32 regval,val;
4420 regval = 0xc8000000|(_SHIFTL(x,2,10));
4421 regval = (regval&~0x3FF000)|(_SHIFTL(y,12,10));
4422 val = *(u32*)regval;
4423 color->a = _SHIFTR(val,24,8);
4424 color->r = _SHIFTR(val,16,8);
4425 color->g = _SHIFTR(val,8,8);
4426 color->b = val&0xff;
4429 void GX_PokeZ(u16 x,u16 y,u32 z)
4431 u32 regval;
4433 regval = 0xc8000000|(_SHIFTL(x,2,10));
4434 regval = (regval&~0x3FF000)|(_SHIFTL(y,12,10));
4435 regval = (regval&~0xC00000)|0x400000;
4436 *(u32*)regval = z;
4439 void GX_PeekZ(u16 x,u16 y,u32 *z)
4441 u32 regval;
4443 regval = 0xc8000000|(_SHIFTL(x,2,10));
4444 regval = (regval&~0x3FF000)|(_SHIFTL(y,12,10));
4445 regval = (regval&~0xC00000)|0x400000;
4446 *z = *(u32*)regval;
4449 void GX_PokeZMode(u8 comp_enable,u8 func,u8 update_enable)
4451 u16 regval;
4452 regval = comp_enable&0x1;
4453 regval = (regval&~0xE)|(_SHIFTL(func,1,3));
4454 regval = (regval&0x10)|(_SHIFTL(update_enable,4,1));
4455 _peReg[0] = regval;
4458 void GX_SetIndTexOrder(u8 indtexstage,u8 texcoord,u8 texmap)
4460 switch(indtexstage) {
4461 case GX_INDTEXSTAGE0:
4462 __gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x7)|(texmap&0x7);
4463 __gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x38)|(_SHIFTL(texcoord,3,3));
4464 break;
4465 case GX_INDTEXSTAGE1:
4466 __gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x1C0)|(_SHIFTL(texmap,6,3));
4467 __gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0xE00)|(_SHIFTL(texcoord,9,3));
4468 break;
4469 case GX_INDTEXSTAGE2:
4470 __gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x7000)|(_SHIFTL(texmap,12,3));
4471 __gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x38000)|(_SHIFTL(texcoord,15,3));
4472 break;
4473 case GX_INDTEXSTAGE3:
4474 __gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x1C0000)|(_SHIFTL(texmap,18,3));
4475 __gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0xE00000)|(_SHIFTL(texcoord,21,3));
4476 break;
4478 GX_LOAD_BP_REG(__gx->tevRasOrder[2]);
4479 __gx->dirtyState |= 0x0003;
4482 void GX_InitLightPos(GXLightObj *lit_obj,f32 x,f32 y,f32 z)
4484 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4486 lit->px = x;
4487 lit->py = y;
4488 lit->pz = z;
4491 void GX_InitLightColor(GXLightObj *lit_obj,GXColor col)
4493 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4494 lit->col = ((_SHIFTL(col.r,24,8))|(_SHIFTL(col.g,16,8))|(_SHIFTL(col.b,8,8))|(col.a&0xff));
4497 void GX_LoadLightObj(GXLightObj *lit_obj,u8 lit_id)
4499 u32 id;
4500 u16 reg;
4501 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4503 switch(lit_id) {
4504 case GX_LIGHT0:
4505 id = 0;
4506 break;
4507 case GX_LIGHT1:
4508 id = 1;
4509 break;
4510 case GX_LIGHT2:
4511 id = 2;
4512 break;
4513 case GX_LIGHT3:
4514 id = 3;
4515 break;
4516 case GX_LIGHT4:
4517 id = 4;
4518 break;
4519 case GX_LIGHT5:
4520 id = 5;
4521 break;
4522 case GX_LIGHT6:
4523 id = 6;
4524 break;
4525 case GX_LIGHT7:
4526 id = 7;
4527 break;
4528 default:
4529 id = 0;
4530 break;
4533 reg = 0x600|(_SHIFTL(id,4,8));
4534 GX_LOAD_XF_REGS(reg,16);
4535 wgPipe->U32 = 0;
4536 wgPipe->U32 = 0;
4537 wgPipe->U32 = 0;
4538 wgPipe->U32 = lit->col;
4539 wgPipe->F32 = lit->a0;
4540 wgPipe->F32 = lit->a1;
4541 wgPipe->F32 = lit->a2;
4542 wgPipe->F32 = lit->k0;
4543 wgPipe->F32 = lit->k1;
4544 wgPipe->F32 = lit->k2;
4545 wgPipe->F32 = lit->px;
4546 wgPipe->F32 = lit->py;
4547 wgPipe->F32 = lit->pz;
4548 wgPipe->F32 = lit->nx;
4549 wgPipe->F32 = lit->ny;
4550 wgPipe->F32 = lit->nz;
4553 void GX_LoadLightObjIdx(u32 litobjidx,u8 litid)
4555 u32 reg;
4556 u32 idx = 0;
4558 switch(litid) {
4559 case GX_LIGHT0:
4560 idx = 0;
4561 break;
4562 case GX_LIGHT1:
4563 idx = 1;
4564 break;
4565 case GX_LIGHT2:
4566 idx = 2;
4567 break;
4568 case GX_LIGHT3:
4569 idx = 3;
4570 break;
4571 case GX_LIGHT4:
4572 idx = 4;
4573 break;
4574 case GX_LIGHT5:
4575 idx = 5;
4576 break;
4577 case GX_LIGHT6:
4578 idx = 6;
4579 break;
4580 case GX_LIGHT7:
4581 idx = 7;
4582 break;
4583 default:
4584 idx = 0;
4585 break;
4589 reg = 0xf600|(_SHIFTL(idx,4,8));
4590 reg = (reg&~0xffff0000)|(_SHIFTL(litobjidx,16,16));
4592 wgPipe->U8 = 0x38;
4593 wgPipe->U32 = reg;
4596 void GX_InitLightDir(GXLightObj *lit_obj,f32 nx,f32 ny,f32 nz)
4598 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4600 lit->nx = -(nx);
4601 lit->ny = -(ny);
4602 lit->nz = -(nz);
4605 void GX_InitLightDistAttn(GXLightObj *lit_obj,f32 ref_dist,f32 ref_brite,u8 dist_fn)
4607 f32 k0,k1,k2;
4608 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4610 if(ref_dist<0.0f ||
4611 ref_brite<0.0f || ref_brite>=1.0f) dist_fn = GX_DA_OFF;
4613 switch(dist_fn) {
4614 case GX_DA_GENTLE:
4615 k0 = 1.0f;
4616 k1 = (1.0f-ref_brite)/(ref_brite*ref_dist);
4617 k2 = 0.0f;
4618 break;
4619 case GX_DA_MEDIUM:
4620 k0 = 1.0f;
4621 k1 = 0.5f*(1.0f-ref_brite)/(ref_brite*ref_dist);
4622 k2 = 0.5f*(1.0f-ref_brite)/(ref_brite*ref_dist*ref_dist);
4623 break;
4624 case GX_DA_STEEP:
4625 k0 = 1.0f;
4626 k1 = 0.0f;
4627 k2 = (1.0f-ref_brite)/(ref_brite*ref_dist*ref_dist);
4628 break;
4629 case GX_DA_OFF:
4630 default:
4631 k0 = 1.0f;
4632 k1 = 0.0f;
4633 k2 = 0.0f;
4634 break;
4637 lit->k0 = k0;
4638 lit->k1 = k1;
4639 lit->k2 = k2;
4642 void GX_InitLightAttn(GXLightObj *lit_obj,f32 a0,f32 a1,f32 a2,f32 k0,f32 k1,f32 k2)
4644 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4646 lit->a0 = a0;
4647 lit->a1 = a1;
4648 lit->a2 = a2;
4649 lit->k0 = k0;
4650 lit->k1 = k1;
4651 lit->k2 = k2;
4654 void GX_InitLightAttnA(GXLightObj *lit_obj,f32 a0,f32 a1,f32 a2)
4656 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4658 lit->a0 = a0;
4659 lit->a1 = a1;
4660 lit->a2 = a2;
4663 void GX_InitLightAttnK(GXLightObj *lit_obj,f32 k0,f32 k1,f32 k2)
4665 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4667 lit->k0 = k0;
4668 lit->k1 = k1;
4669 lit->k2 = k2;
4672 void GX_InitSpecularDirHA(GXLightObj *lit_obj,f32 nx,f32 ny,f32 nz,f32 hx,f32 hy,f32 hz)
4674 f32 px, py, pz;
4675 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4677 px = (nx * LARGE_NUMBER);
4678 py = (ny * LARGE_NUMBER);
4679 pz = (nz * LARGE_NUMBER);
4681 lit->px = px;
4682 lit->py = py;
4683 lit->pz = pz;
4684 lit->nx = hx;
4685 lit->ny = hy;
4686 lit->nz = hz;
4689 void GX_InitSpecularDir(GXLightObj *lit_obj,f32 nx,f32 ny,f32 nz)
4691 f32 px, py, pz;
4692 f32 hx, hy, hz, mag;
4693 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4695 // Compute half-angle vector
4696 hx = -nx;
4697 hy = -ny;
4698 hz = (-nz + 1.0f);
4699 mag = ((hx * hx) + (hy * hy) + (hz * hz));
4700 if(mag!=0.0f) mag = 1.0f / sqrtf(mag);
4702 hx *= mag;
4703 hy *= mag;
4704 hz *= mag;
4706 px = (nx * LARGE_NUMBER);
4707 py = (ny * LARGE_NUMBER);
4708 pz = (nz * LARGE_NUMBER);
4710 lit->px = px;
4711 lit->py = py;
4712 lit->pz = pz;
4713 lit->nx = hx;
4714 lit->ny = hy;
4715 lit->nz = hz;
4718 void GX_InitLightSpot(GXLightObj *lit_obj,f32 cut_off,u8 spotfn)
4720 f32 r,d,cr,a0,a1,a2;
4721 struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4723 if(cut_off<0.0f || cut_off>90.0f) spotfn = GX_SP_OFF;
4725 r = (cut_off*M_PI)/180.0f;
4726 cr = cosf(r);
4728 switch(spotfn) {
4729 case GX_SP_FLAT:
4730 a0 = -1000.0f*cr;
4731 a1 = 1000.0f;
4732 a2 = 0.0f;
4733 break;
4734 case GX_SP_COS:
4735 a0 = -cr/(1.0f-cr);
4736 a1 = 1.0f/(1.0f-cr);
4737 a2 = 0.0f;
4738 break;
4739 case GX_SP_COS2:
4740 a0 = 0.0f;
4741 a1 = -cr/(1.0f-cr);
4742 a2 = 1.0f/(1.0f-cr);
4743 break;
4744 case GX_SP_SHARP:
4745 d = (1.0f-cr)*(1.0f-cr);
4746 a0 = cr*(cr-2.0f);
4747 a1 = 2.0f/d;
4748 a2 = -1.0/d;
4749 break;
4750 case GX_SP_RING1:
4751 d = (1.0f-cr)*(1.0f-cr);
4752 a0 = -4.0f*cr/d;
4753 a1 = 4.0f*(1.0f+cr)/d;
4754 a2 = -4.0f/d;
4755 break;
4756 case GX_SP_RING2:
4757 d = (1.0f-cr)*(1.0f-cr);
4758 a0 = 1.0f-2.0f*cr*cr/d;
4759 a1 = 4.0f*cr/d;
4760 a2 = -2.0f/d;
4761 break;
4762 case GX_SP_OFF:
4763 default:
4764 a0 = 1.0f;
4765 a1 = 0.0f;
4766 a2 = 0.0f;
4767 break;
4770 lit->a0 = a0;
4771 lit->a1 = a1;
4772 lit->a2 = a2;
4775 void GX_SetGPMetric(u32 perf0,u32 perf1)
4777 // check last setted perf0 counters
4778 if(__gx->perf0Mode>=GX_PERF0_TRIANGLES && __gx->perf0Mode<GX_PERF0_QUAD_0CVG)
4779 GX_LOAD_BP_REG(0x23000000);
4780 else if(__gx->perf0Mode>=GX_PERF0_QUAD_0CVG && __gx->perf0Mode<GX_PERF0_CLOCKS)
4781 GX_LOAD_BP_REG(0x24000000);
4782 else if(__gx->perf0Mode>=GX_PERF0_VERTICES && __gx->perf0Mode<=GX_PERF0_CLOCKS)
4783 GX_LOAD_XF_REG(0x1006,0);
4785 // check last setted perf1 counters
4786 if(__gx->perf1Mode>=GX_PERF1_VC_ELEMQ_FULL && __gx->perf1Mode<GX_PERF1_FIFO_REQ) {
4787 __gx->cpPerfMode = (__gx->cpPerfMode&~0xf0);
4788 GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4789 } else if(__gx->perf1Mode>=GX_PERF1_FIFO_REQ && __gx->perf1Mode<GX_PERF1_CLOCKS) {
4790 _cpReg[3] = 0;
4791 } else if(__gx->perf1Mode>=GX_PERF1_TEXELS && __gx->perf1Mode<=GX_PERF1_CLOCKS) {
4792 GX_LOAD_BP_REG(0x67000000);
4795 __gx->perf0Mode = perf0;
4796 switch(__gx->perf0Mode) {
4797 case GX_PERF0_CLOCKS:
4798 GX_LOAD_XF_REG(0x1006,0x00000273);
4799 break;
4800 case GX_PERF0_VERTICES:
4801 GX_LOAD_XF_REG(0x1006,0x0000014a);
4802 break;
4803 case GX_PERF0_CLIP_VTX:
4804 GX_LOAD_XF_REG(0x1006,0x0000016b);
4805 break;
4806 case GX_PERF0_CLIP_CLKS:
4807 GX_LOAD_XF_REG(0x1006,0x00000084);
4808 break;
4809 case GX_PERF0_XF_WAIT_IN:
4810 GX_LOAD_XF_REG(0x1006,0x000000c6);
4811 break;
4812 case GX_PERF0_XF_WAIT_OUT:
4813 GX_LOAD_XF_REG(0x1006,0x00000210);
4814 break;
4815 case GX_PERF0_XF_XFRM_CLKS:
4816 GX_LOAD_XF_REG(0x1006,0x00000252);
4817 break;
4818 case GX_PERF0_XF_LIT_CLKS:
4819 GX_LOAD_XF_REG(0x1006,0x00000231);
4820 break;
4821 case GX_PERF0_XF_BOT_CLKS:
4822 GX_LOAD_XF_REG(0x1006,0x000001ad);
4823 break;
4824 case GX_PERF0_XF_REGLD_CLKS:
4825 GX_LOAD_XF_REG(0x1006,0x000001ce);
4826 break;
4827 case GX_PERF0_XF_REGRD_CLKS:
4828 GX_LOAD_XF_REG(0x1006,0x00000021);
4829 break;
4830 case GX_PERF0_CLIP_RATIO:
4831 GX_LOAD_XF_REG(0x1006,0x00000153);
4832 break;
4833 case GX_PERF0_TRIANGLES:
4834 GX_LOAD_BP_REG(0x2300AE7F);
4835 break;
4836 case GX_PERF0_TRIANGLES_CULLED:
4837 GX_LOAD_BP_REG(0x23008E7F);
4838 break;
4839 case GX_PERF0_TRIANGLES_PASSED:
4840 GX_LOAD_BP_REG(0x23009E7F);
4841 break;
4842 case GX_PERF0_TRIANGLES_SCISSORED:
4843 GX_LOAD_BP_REG(0x23001E7F);
4844 break;
4845 case GX_PERF0_TRIANGLES_0TEX:
4846 GX_LOAD_BP_REG(0x2300AC3F);
4847 break;
4848 case GX_PERF0_TRIANGLES_1TEX:
4849 GX_LOAD_BP_REG(0x2300AC7F);
4850 break;
4851 case GX_PERF0_TRIANGLES_2TEX:
4852 GX_LOAD_BP_REG(0x2300ACBF);
4853 break;
4854 case GX_PERF0_TRIANGLES_3TEX:
4855 GX_LOAD_BP_REG(0x2300ACFF);
4856 break;
4857 case GX_PERF0_TRIANGLES_4TEX:
4858 GX_LOAD_BP_REG(0x2300AD3F);
4859 break;
4860 case GX_PERF0_TRIANGLES_5TEX:
4861 GX_LOAD_BP_REG(0x2300AD7F);
4862 break;
4863 case GX_PERF0_TRIANGLES_6TEX:
4864 GX_LOAD_BP_REG(0x2300ADBF);
4865 break;
4866 case GX_PERF0_TRIANGLES_7TEX:
4867 GX_LOAD_BP_REG(0x2300ADFF);
4868 break;
4869 case GX_PERF0_TRIANGLES_8TEX:
4870 GX_LOAD_BP_REG(0x2300AE3F);
4871 break;
4872 case GX_PERF0_TRIANGLES_0CLR:
4873 GX_LOAD_BP_REG(0x2300A27F);
4874 break;
4875 case GX_PERF0_TRIANGLES_1CLR:
4876 GX_LOAD_BP_REG(0x2300A67F);
4877 break;
4878 case GX_PERF0_TRIANGLES_2CLR:
4879 GX_LOAD_BP_REG(0x2300AA7F);
4880 break;
4881 case GX_PERF0_QUAD_0CVG:
4882 GX_LOAD_BP_REG(0x2402C0C6);
4883 break;
4884 case GX_PERF0_QUAD_NON0CVG:
4885 GX_LOAD_BP_REG(0x2402C16B);
4886 break;
4887 case GX_PERF0_QUAD_1CVG:
4888 GX_LOAD_BP_REG(0x2402C0E7);
4889 break;
4890 case GX_PERF0_QUAD_2CVG:
4891 GX_LOAD_BP_REG(0x2402C108);
4892 break;
4893 case GX_PERF0_QUAD_3CVG:
4894 GX_LOAD_BP_REG(0x2402C129);
4895 break;
4896 case GX_PERF0_QUAD_4CVG:
4897 GX_LOAD_BP_REG(0x2402C14A);
4898 break;
4899 case GX_PERF0_AVG_QUAD_CNT:
4900 GX_LOAD_BP_REG(0x2402C1AD);
4901 break;
4902 case GX_PERF0_NONE:
4903 break;
4906 __gx->perf1Mode = perf1;
4907 switch(__gx->perf1Mode) {
4908 case GX_PERF1_CLOCKS:
4909 GX_LOAD_BP_REG(0x67000042);
4910 break;
4911 case GX_PERF1_TEXELS:
4912 GX_LOAD_BP_REG(0x67000084);
4913 break;
4914 case GX_PERF1_TX_IDLE:
4915 GX_LOAD_BP_REG(0x67000063);
4916 break;
4917 case GX_PERF1_TX_REGS:
4918 GX_LOAD_BP_REG(0x67000129);
4919 break;
4920 case GX_PERF1_TX_MEMSTALL:
4921 GX_LOAD_BP_REG(0x67000252);
4922 break;
4923 case GX_PERF1_TC_CHECK1_2:
4924 GX_LOAD_BP_REG(0x67000021);
4925 break;
4926 case GX_PERF1_TC_CHECK3_4:
4927 GX_LOAD_BP_REG(0x6700014b);
4928 break;
4929 case GX_PERF1_TC_CHECK5_6:
4930 GX_LOAD_BP_REG(0x6700018d);
4931 break;
4932 case GX_PERF1_TC_CHECK7_8:
4933 GX_LOAD_BP_REG(0x670001cf);
4934 break;
4935 case GX_PERF1_TC_MISS:
4936 GX_LOAD_BP_REG(0x67000211);
4937 break;
4938 case GX_PERF1_VC_ELEMQ_FULL:
4939 __gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x20;
4940 GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4941 break;
4942 case GX_PERF1_VC_MISSQ_FULL:
4943 __gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x30;
4944 GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4945 break;
4946 case GX_PERF1_VC_MEMREQ_FULL:
4947 __gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x40;
4948 GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4949 break;
4950 case GX_PERF1_VC_STATUS7:
4951 __gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x50;
4952 GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4953 break;
4954 case GX_PERF1_VC_MISSREP_FULL:
4955 __gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x60;
4956 GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4957 break;
4958 case GX_PERF1_VC_STREAMBUF_LOW:
4959 __gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x70;
4960 GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4961 break;
4962 case GX_PERF1_VC_ALL_STALLS:
4963 __gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x90;
4964 GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4965 break;
4966 case GX_PERF1_VERTICES:
4967 __gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x80;
4968 GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4969 break;
4970 case GX_PERF1_FIFO_REQ:
4971 _cpReg[3] = 2;
4972 break;
4973 case GX_PERF1_CALL_REQ:
4974 _cpReg[3] = 3;
4975 break;
4976 case GX_PERF1_VC_MISS_REQ:
4977 _cpReg[3] = 4;
4978 break;
4979 case GX_PERF1_CP_ALL_REQ:
4980 _cpReg[3] = 5;
4981 break;
4982 case GX_PERF1_NONE:
4983 break;
4988 void GX_ClearGPMetric()
4990 _cpReg[2] = 4;
4993 void GX_InitXfRasMetric()
4995 GX_LOAD_BP_REG(0x2402C022);
4996 GX_LOAD_XF_REG(0x1006,0x31000);
4999 void GX_ReadXfRasMetric(u32 *xfwaitin,u32 *xfwaitout,u32 *rasbusy,u32 *clks)
5001 *rasbusy = _SHIFTL(_cpReg[33],16,16)|(_cpReg[32]&0xffff);
5002 *clks = _SHIFTL(_cpReg[35],16,16)|(_cpReg[34]&0xffff);
5003 *xfwaitin = _SHIFTL(_cpReg[37],16,16)|(_cpReg[36]&0xffff);
5004 *xfwaitout = _SHIFTL(_cpReg[39],16,16)|(_cpReg[38]&0xffff);
5007 u32 GX_ReadClksPerVtx()
5009 GX_DrawDone();
5010 _cpReg[49] = 0x1007;
5011 _cpReg[48] = 0x1007;
5012 return (_cpReg[50]<<8);
5015 void GX_ClearVCacheMetric()
5017 GX_LOAD_CP_REG(0,0);
5020 void GX_ReadVCacheMetric(u32 *check,u32 *miss,u32 *stall)
5022 *check = _SHIFTL(_cpReg[41],16,16)|(_cpReg[40]&0xffff);
5023 *miss = _SHIFTL(_cpReg[43],16,16)|(_cpReg[42]&0xffff);
5024 *stall = _SHIFTL(_cpReg[45],16,16)|(_cpReg[44]&0xffff);
5027 void GX_SetVCacheMetric(u32 attr)
5031 void GX_GetGPStatus(u8 *overhi,u8 *underlow,u8 *readIdle,u8 *cmdIdle,u8 *brkpt)
5033 _gxgpstatus = _cpReg[0];
5034 *overhi = !!(_gxgpstatus&1);
5035 *underlow = !!(_gxgpstatus&2);
5036 *readIdle = !!(_gxgpstatus&4);
5037 *cmdIdle = !!(_gxgpstatus&8);
5038 *brkpt = !!(_gxgpstatus&16);
5041 void GX_ReadGPMetric(u32 *cnt0,u32 *cnt1)
5043 u32 tmp,reg1,reg2,reg3,reg4;
5045 reg1 = (_SHIFTL(_cpReg[33],16,16))|(_cpReg[32]&0xffff);
5046 reg2 = (_SHIFTL(_cpReg[35],16,16))|(_cpReg[34]&0xffff);
5047 reg3 = (_SHIFTL(_cpReg[37],16,16))|(_cpReg[36]&0xffff);
5048 reg4 = (_SHIFTL(_cpReg[39],16,16))|(_cpReg[38]&0xffff);
5050 *cnt0 = 0;
5051 if(__gx->perf0Mode==GX_PERF0_CLIP_RATIO) {
5052 tmp = reg2*1000;
5053 *cnt0 = tmp/reg1;
5054 } else if(__gx->perf0Mode>=GX_PERF0_VERTICES && __gx->perf0Mode<GX_PERF0_NONE) *cnt0 = reg1;
5056 //further implementation needed.....
5057 // cnt1 fails....
5060 void GX_AdjustForOverscan(GXRModeObj *rmin,GXRModeObj *rmout,u16 hor,u16 ver)
5062 if(rmin!=rmout) memcpy(rmout,rmin,sizeof(GXRModeObj));
5064 rmout->fbWidth = rmin->fbWidth-(hor<<1);
5065 rmout->efbHeight = rmin->efbHeight-((rmin->efbHeight*(ver<<1))/rmin->xfbHeight);
5066 if(rmin->xfbMode==VI_XFBMODE_SF && !(rmin->viTVMode&VI_PROGRESSIVE)) rmout->xfbHeight = rmin->xfbHeight-ver;
5067 else rmout->xfbHeight = rmin->xfbHeight-(ver<<1);
5069 rmout->viWidth = rmin->viWidth-(hor<<1);
5070 if(rmin->viTVMode&VI_PROGRESSIVE) rmout->viHeight = rmin->viHeight-(ver<<2);
5071 else rmout->viHeight = rmin->viHeight-(ver<<1);
5073 rmout->viXOrigin += hor;
5074 rmout->viYOrigin += ver;
5077 f32 GX_GetYScaleFactor(u16 efbHeight,u16 xfbHeight)
5079 u32 yScale,xfblines,cnt;
5080 f32 yscale;
5082 yscale = (f32)efbHeight/(f32)xfbHeight;
5083 yScale = (u32)((f32)256.0/yscale)&0x1ff;
5085 cnt = xfbHeight;
5086 xfblines = __GX_GetNumXfbLines(efbHeight,yScale);
5087 while(xfblines>=xfbHeight) {
5088 yscale = (f32)(cnt--)/(f32)efbHeight;
5089 yScale = (u32)((f32)256.0/yscale)&0x1ff;
5090 xfblines = __GX_GetNumXfbLines(efbHeight,yScale);
5093 while(xfblines<xfbHeight) {
5094 yscale = (f32)(cnt++)/(f32)efbHeight;
5095 yScale = (u32)((f32)256.0/yscale)&0x1ff;
5096 xfblines = __GX_GetNumXfbLines(efbHeight,yScale);
5098 return yscale;
5101 void GX_ReadBoundingBox(u16 *top,u16 *bottom,u16 *left,u16 *right)
5103 *left = _peReg[8];
5104 *right = _peReg[9];
5105 *top = _peReg[10];
5106 *bottom = _peReg[11];
5109 #undef LARGE_NUMBER