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"
15 
16 #define TEXCACHE_TESTING
17 
18 #define GX_FINISH		2
19 
20 #if defined(HW_DOL)
21 	#define LARGE_NUMBER	(-1048576.0f)
22 #elif defined(HW_RVL)
23 	#define LARGE_NUMBER	(-1.0e+18f)
24 #endif
25 
26 #define _SHIFTL(v, s, w)	\
27     ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
28 #define _SHIFTR(v, s, w)	\
29     ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
30 
31 #define GX_LOAD_BP_REG(x)				\
32 	do {								\
33 		wgPipe->U8 = 0x61;				\
34 		asm volatile ("" ::: "memory" ); \
35 		wgPipe->U32 = (u32)(x);		\
36 		asm volatile ("" ::: "memory" ); \
37 	} while(0)
38 
39 #define GX_LOAD_CP_REG(x, y)			\
40 	do {								\
41 		wgPipe->U8 = 0x08;				\
42 		asm volatile ("" ::: "memory" ); \
43 		wgPipe->U8 = (u8)(x);			\
44 		asm volatile ("" ::: "memory" ); \
45 		wgPipe->U32 = (u32)(y);		\
46 		asm volatile ("" ::: "memory" ); \
47 	} while(0)
48 
49 #define GX_LOAD_XF_REG(x, y)			\
50 	do {								\
51 		wgPipe->U8 = 0x10;				\
52 		asm volatile ("" ::: "memory" ); \
53 		wgPipe->U32 = (u32)((x)&0xffff);		\
54 		asm volatile ("" ::: "memory" ); \
55 		wgPipe->U32 = (u32)(y);		\
56 		asm volatile ("" ::: "memory" ); \
57 	} while(0)
58 
59 #define GX_LOAD_XF_REGS(x, n)			\
60 	do {								\
61 		wgPipe->U8 = 0x10;				\
62 		asm volatile ("" ::: "memory" ); \
63 		wgPipe->U32 = (u32)(((((n)&0xffff)-1)<<16)|((x)&0xffff));				\
64 		asm volatile ("" ::: "memory" ); \
65 	} while(0)
66 
67 #define XY(x, y)   (((y) << 10) | (x))
68 
69 #define GX_DEFAULT_BG	{64,64,64,255}
70 #define BLACK			{0,0,0,0}
71 #define WHITE			{255,255,255,255}
72 
73 WGPipe* const wgPipe = (WGPipe*)0xCC008000;
74 
75 static GXFifoObj _gpfifo;
76 static GXFifoObj _cpufifo;
77 static GXFifoObj _gxfifoobj;
78 static GXFifoObj _gx_dl_fifoobj;
79 static GXFifoObj _gx_old_cpufifo;
80 static void *_gxcurrbp = NULL;
81 static lwp_t _gxcurrentlwp = LWP_THREAD_NULL;
82 
83 static u32 _gxcpufifoready = 0;
84 static u32 _gxgpfifoready = 0;
85 static u32 _cpgplinked = 0;
86 static u16 _gxgpstatus = 0;
87 static vu32 _gxoverflowsuspend = 0;
88 static vu32 _gxoverflowcount = 0;
89 static vu32 _gxfinished = 0;
90 static lwpq_t _gxwaitfinish;
91 
92 static GXBreakPtCallback breakPtCB = NULL;
93 static GXDrawDoneCallback drawDoneCB = NULL;
94 static GXDrawSyncCallback tokenCB = NULL;
95 
96 static GXTexRegionCallback regionCB = NULL;
97 static GXTlutRegionCallback tlut_regionCB = NULL;
98 
99 static vu32* const _piReg = (u32*)0xCC003000;
100 static vu16* const _cpReg = (u16*)0xCC000000;
101 static vu16* const _peReg = (u16*)0xCC001000;
102 static vu16* const _memReg = (u16*)0xCC004000;
103 
104 static u8 _gxtevcolid[9] = {0,1,0,1,0,1,7,5,6};
105 static u8 _gxtexmode0ids[8] = {0x80,0x81,0x82,0x83,0xA0,0xA1,0xA2,0xA3};
106 static u8 _gxtexmode1ids[8] = {0x84,0x85,0x86,0x87,0xA4,0xA5,0xA6,0xA7};
107 static u8 _gxteximg0ids[8] = {0x88,0x89,0x8A,0x8B,0xA8,0xA9,0xAA,0xAB};
108 static u8 _gxteximg1ids[8] = {0x8C,0x8D,0x8E,0x8F,0xAC,0xAD,0xAE,0xAF};
109 static u8 _gxteximg2ids[8] = {0x90,0x91,0x92,0x93,0xB0,0xB1,0xB2,0xB3};
110 static u8 _gxteximg3ids[8] = {0x94,0x95,0x96,0x97,0xB4,0xB5,0xB6,0xB7};
111 static u8 _gxtextlutids[8] = {0x98,0x99,0x9A,0x9B,0xB8,0xB9,0xBA,0xBB};
112 
113 #if defined(HW_RVL)
114 static u32 _gxtexregionaddrtable[48] =
115 {
116 	0x00000000,0x00010000,0x00020000,0x00030000,
117 	0x00040000,0x00050000,0x00060000,0x00070000,
118 	0x00008000,0x00018000,0x00028000,0x00038000,
119 	0x00048000,0x00058000,0x00068000,0x00078000,
120 	0x00000000,0x00090000,0x00020000,0x000B0000,
121 	0x00040000,0x00098000,0x00060000,0x000B8000,
122 	0x00080000,0x00010000,0x000A0000,0x00030000,
123 	0x00088000,0x00050000,0x000A8000,0x00070000,
124 	0x00000000,0x00090000,0x00020000,0x000B0000,
125 	0x00040000,0x00090000,0x00060000,0x000B0000,
126 	0x00080000,0x00010000,0x000A0000,0x00030000,
127 	0x00080000,0x00050000,0x000A0000,0x00070000
128 };
129 #endif
130 
131 extern u8 __gxregs[];
132 static struct __gx_regdef *__gx = (struct __gx_regdef*)__gxregs;
133 static u8 _gx_saved_data[STRUCT_REGDEF_SIZE] ATTRIBUTE_ALIGN(32);
134 
135 static s32 __gx_onreset(s32 final);
136 
137 static sys_resetinfo __gx_resetinfo = {
138 	{},
139 	__gx_onreset,
140 	127
141 };
142 
IsWriteGatherBufferEmpty()143 static __inline__ BOOL IsWriteGatherBufferEmpty()
144 {
145 	return !(mfwpar()&1);
146 }
147 
DisableWriteGatherPipe()148 static __inline__ void DisableWriteGatherPipe()
149 {
150 	mthid2((mfhid2()&~0x40000000));
151 }
152 
EnableWriteGatherPipe()153 static __inline__ void EnableWriteGatherPipe()
154 {
155 	mtwpar(0x0C008000);
156 	mthid2((mfhid2()|0x40000000));
157 }
158 
__GX_ResetWriteGatherPipe()159 static __inline__ void __GX_ResetWriteGatherPipe()
160 {
161 	while(mfwpar()&1);
162 	mtwpar(0x0C008000);
163 }
164 
__GX_FifoLink(u8 enable)165 static __inline__ void __GX_FifoLink(u8 enable)
166 {
167 	__gx->cpCRreg = ((__gx->cpCRreg&~0x10)|(_SHIFTL(enable,4,1)));
168 	_cpReg[1] = __gx->cpCRreg;
169 }
170 
__GX_WriteFifoIntReset(u8 inthi,u8 intlo)171 static __inline__ void __GX_WriteFifoIntReset(u8 inthi,u8 intlo)
172 {
173 	__gx->cpCLreg = ((__gx->cpCLreg&~0x03)|(_SHIFTL(intlo,1,1))|(inthi&1));
174 	_cpReg[2] = __gx->cpCLreg;
175 }
176 
__GX_WriteFifoIntEnable(u8 inthi,u8 intlo)177 static __inline__ void __GX_WriteFifoIntEnable(u8 inthi, u8 intlo)
178 {
179 	__gx->cpCRreg = ((__gx->cpCRreg&~0x0C)|(_SHIFTL(intlo,3,1))|(_SHIFTL(inthi,2,1)));
180 	_cpReg[1] = __gx->cpCRreg;
181 }
182 
__GX_FifoReadEnable()183 static __inline__ void __GX_FifoReadEnable()
184 {
185 	__gx->cpCRreg = ((__gx->cpCRreg&~0x01)|1);
186 	_cpReg[1] = __gx->cpCRreg;
187 }
188 
__GX_FifoReadDisable()189 static __inline__ void __GX_FifoReadDisable()
190 {
191 	__gx->cpCRreg = ((__gx->cpCRreg&~0x01)|0);
192 	_cpReg[1] = __gx->cpCRreg;
193 }
194 
__gx_onreset(s32 final)195 static s32 __gx_onreset(s32 final)
196 {
197 	if(final==FALSE) {
198 		GX_Flush();
199 		GX_AbortFrame();
200 	}
201 	return 1;
202 }
203 
__GX_IsGPFifoReady()204 static u32 __GX_IsGPFifoReady()
205 {
206 	return _gxgpfifoready;
207 }
208 
__GX_CPGPLinkCheck()209 static u32 __GX_CPGPLinkCheck()
210 {
211 	struct __gxfifo *gpfifo = (struct __gxfifo*)&_gpfifo;
212 	struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
213 
214 	if(!_gxcpufifoready || !_gxgpfifoready) return 0;
215 
216 	if((cpufifo->buf_start==gpfifo->buf_start)&&(cpufifo->buf_end==gpfifo->buf_end)) return 1;
217 
218 	return 0;
219 }
220 
__GX_InitRevBits()221 static void __GX_InitRevBits()
222 {
223 	s32 i;
224 
225 	i=0;
226 	while(i<8) {
227 		__gx->VAT0reg[i] = 0x40000000;
228 		__gx->VAT1reg[i] = 0x80000000;
229 		GX_LOAD_CP_REG((0x0080|i),__gx->VAT1reg[i]);
230 		i++;
231 	}
232 
233 	GX_LOAD_XF_REG(0x1000,0x3f);
234 	GX_LOAD_XF_REG(0x1012,0x01);
235 
236 	GX_LOAD_BP_REG(0x5800000f);
237 
238 }
239 
__GX_WaitAbort(u32 delay)240 static void __GX_WaitAbort(u32 delay)
241 {
242 	u64 start,end;
243 
244 	start = gettime();
245 	while(1) {
246 		end = gettime();
247 		if(diff_ticks(start,end)>=(u64)delay) break;
248 	};
249 }
250 
251 #ifdef HW_RVL
__GX_ReadMemCounterU32(u32 reg)252 static u32 __GX_ReadMemCounterU32(u32 reg)
253 {
254 	u16 lcnt,ucnt,tmp;
255 
256 	tmp = _memReg[reg];
257 	do {
258 		ucnt = tmp;
259 		lcnt = _memReg[reg+1];
260 		tmp = _memReg[reg];
261 	} while(tmp!=ucnt);
262 	return (u32)((ucnt<<16)|lcnt);
263 }
264 
__GX_WaitAbortPixelEngine()265 static void __GX_WaitAbortPixelEngine()
266 {
267 	u32 cnt,tmp;
268 
269 	cnt = __GX_ReadMemCounterU32(39);
270 	do {
271 		tmp = cnt;
272 		__GX_WaitAbort(8);
273 		cnt = __GX_ReadMemCounterU32(39);
274 	} while(cnt!=tmp);
275 }
276 
__GX_Abort()277 static void __GX_Abort()
278 {
279 	if(__gx->gxFifoInited && __GX_IsGPFifoReady())
280 		__GX_WaitAbortPixelEngine();
281 
282 	_piReg[6] = 1;
283 	__GX_WaitAbort(50);
284 
285 	_piReg[6] = 0;
286 	__GX_WaitAbort(5);
287 }
288 #endif
289 
__GX_SaveFifo()290 static void __GX_SaveFifo()
291 {
292 	s32 rdwt_dst;
293 	u32 level,val;
294 	struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
295 	struct __gxfifo *gpfifo = (struct __gxfifo*)&_gpfifo;
296 
297 	_CPU_ISR_Disable(level);
298 
299 	if(_gxcpufifoready) {
300 		val = _piReg[0x05];
301 		cpufifo->wt_ptr = (u32)MEM_PHYSICAL_TO_K0((val&0x1FFFFFE0));
302 		cpufifo->fifo_wrap = ((val&0x20000000)==0x20000000);
303 	}
304 
305 	if(_gxgpfifoready) {
306 		gpfifo->rd_ptr = (u32)MEM_PHYSICAL_TO_K0(_SHIFTL(_cpReg[29],16,16)|(_cpReg[28]&0xffff));
307 		gpfifo->rdwt_dst = (_SHIFTL(_cpReg[25],16,16)|(_cpReg[24]&0xffff));
308 	}
309 
310 	if(_cpgplinked) {
311 		cpufifo->rd_ptr = gpfifo->rd_ptr;
312 		cpufifo->rdwt_dst = gpfifo->rdwt_dst;
313 		gpfifo->wt_ptr = cpufifo->wt_ptr;
314 	} else if(_gxcpufifoready) {
315 		rdwt_dst = (cpufifo->wt_ptr - cpufifo->rd_ptr);
316 		if(rdwt_dst<0) cpufifo->rdwt_dst = (cpufifo->rdwt_dst + cpufifo->size);
317 		else cpufifo->rdwt_dst = rdwt_dst;
318 	}
319 
320 	_CPU_ISR_Restore(level);
321 }
322 
__GX_CleanGPFifo()323 static void __GX_CleanGPFifo()
324 {
325 	u32 level;
326 	struct __gxfifo *gpfifo = (struct __gxfifo*)&_gpfifo;
327 	struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
328 
329 	if(!_gxgpfifoready) return;
330 
331 	_CPU_ISR_Disable(level);
332 	__GX_FifoReadDisable();
333 	__GX_WriteFifoIntEnable(FALSE,FALSE);
334 
335 	gpfifo->rd_ptr = gpfifo->wt_ptr;
336 	gpfifo->rdwt_dst = 0;
337 
338 	/* setup rd<->wd dist */
339 	_cpReg[24] = _SHIFTL(gpfifo->rdwt_dst,0,16);
340 	_cpReg[25] = _SHIFTR(gpfifo->rdwt_dst,16,16);
341 
342 	/* setup wt ptr */
343 	_cpReg[26] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->wt_ptr),0,16);
344 	_cpReg[27] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->wt_ptr),16,16);
345 
346 	/* setup rd ptr */
347 	_cpReg[28] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->rd_ptr),0,16);
348 	_cpReg[29] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->rd_ptr),16,16);
349 	ppcsync();
350 
351 	if(_cpgplinked) {
352 		cpufifo->rd_ptr = gpfifo->rd_ptr;
353 		cpufifo->wt_ptr = gpfifo->wt_ptr;
354 		cpufifo->rdwt_dst = gpfifo->rdwt_dst;
355 
356 		_piReg[5] = (cpufifo->wt_ptr&0x1FFFFFE0);
357 		__GX_WriteFifoIntEnable(TRUE,FALSE);
358 		__GX_FifoLink(TRUE);
359 	}
360 	__gx->cpCRreg &= ~0x22;
361 	_cpReg[1] = __gx->cpCRreg;
362 	breakPtCB = NULL;
363 
364 	__GX_WriteFifoIntReset(TRUE,TRUE);
365 	__GX_FifoReadEnable();
366 	_CPU_ISR_Restore(level);
367 }
368 
__GXOverflowHandler()369 static void __GXOverflowHandler()
370 {
371 	if(!_gxoverflowsuspend) {
372 		_gxoverflowsuspend = 1;
373 		_gxoverflowcount++;
374 		__GX_WriteFifoIntEnable(GX_DISABLE,GX_ENABLE);
375 		__GX_WriteFifoIntReset(GX_TRUE,GX_FALSE);
376 		LWP_SuspendThread(_gxcurrentlwp);
377 	}
378 }
379 
__GXUnderflowHandler()380 static void __GXUnderflowHandler()
381 {
382 	if(_gxoverflowsuspend) {
383 		_gxoverflowsuspend = 0;
384 		LWP_ResumeThread(_gxcurrentlwp);
385 		__GX_WriteFifoIntReset(GX_TRUE,GX_TRUE);
386 		__GX_WriteFifoIntEnable(GX_ENABLE,GX_DISABLE);
387 	}
388 }
389 
__GXCPInterruptHandler(u32 irq,void * ctx)390 static void __GXCPInterruptHandler(u32 irq,void *ctx)
391 {
392 	__gx->cpSRreg = _cpReg[0];
393 
394 	if((__gx->cpCRreg&0x08) && (__gx->cpSRreg&0x02))
395 		__GXUnderflowHandler();
396 
397 	if((__gx->cpCRreg&0x04) && (__gx->cpSRreg&0x01))
398 		__GXOverflowHandler();
399 
400 	if((__gx->cpCRreg&0x20) && (__gx->cpSRreg&0x10)) {
401 		__gx->cpCRreg &= ~0x20;
402 		_cpReg[1] = __gx->cpCRreg;
403 		if(breakPtCB)
404 			breakPtCB();
405 	}
406 }
407 
__GXTokenInterruptHandler(u32 irq,void * ctx)408 static void __GXTokenInterruptHandler(u32 irq,void *ctx)
409 {
410 	u16 token = _peReg[7];
411 
412 	if(tokenCB)
413 		tokenCB(token);
414 
415 	_peReg[5] = (_peReg[5]&~0x04)|0x04;
416 }
417 
__GXFinishInterruptHandler(u32 irq,void * ctx)418 static void __GXFinishInterruptHandler(u32 irq,void *ctx)
419 {
420 	_peReg[5] = (_peReg[5]&~0x08)|0x08;
421 	_gxfinished = 1;
422 
423 	if(drawDoneCB)
424 		drawDoneCB();
425 
426 	LWP_ThreadBroadcast(_gxwaitfinish);
427 }
428 
__GX_PEInit()429 static void __GX_PEInit()
430 {
431 	IRQ_Request(IRQ_PI_PETOKEN,__GXTokenInterruptHandler,NULL);
432 	__UnmaskIrq(IRQMASK(IRQ_PI_PETOKEN));
433 
434 	IRQ_Request(IRQ_PI_PEFINISH,__GXFinishInterruptHandler,NULL);
435 	__UnmaskIrq(IRQMASK(IRQ_PI_PEFINISH));
436 
437 	_peReg[5] = 0x0F;
438 }
439 
__GX_FifoInit()440 static void __GX_FifoInit()
441 {
442 	IRQ_Request(IRQ_PI_CP,__GXCPInterruptHandler,NULL);
443 	__UnmaskIrq(IRQMASK(IRQ_PI_CP));
444 
445 	memset(&_cpufifo,0,sizeof(GXFifoObj));
446 	memset(&_gpfifo,0,sizeof(GXFifoObj));
447 
448 	_gxcpufifoready = 0;
449 	_gxgpfifoready = 0;
450 	_cpgplinked = 0;
451 	_gxoverflowsuspend = 0;
452 	_gxcurrentlwp = LWP_GetSelf();
453 }
454 
__GX_SetTmemConfig(u8 nr)455 static void __GX_SetTmemConfig(u8 nr)
456 {
457 	if(nr==0) {
458 		//  Set_TextureImage0-3, GXTexMapID=0-3 tmem_offset=00000000, cache_width=32 kb, cache_height=32 kb, image_type=cached
459 		GX_LOAD_BP_REG(0x8c0d8000);
460 		GX_LOAD_BP_REG(0x900dc000);
461 		GX_LOAD_BP_REG(0x8d0d8400);
462 		GX_LOAD_BP_REG(0x910dc400);
463 		GX_LOAD_BP_REG(0x8e0d8800);
464 		GX_LOAD_BP_REG(0x920dc800);
465 		GX_LOAD_BP_REG(0x8f0d8c00);
466 		GX_LOAD_BP_REG(0x930dcc00);
467 
468 		//  Set_TextureImage0-3, GXTexMapID=4-7 tmem_offset=00010000, cache_width=32 kb, cache_height=32 kb, image_type=cached
469 		GX_LOAD_BP_REG(0xac0d9000);
470 		GX_LOAD_BP_REG(0xb00dd000);
471 		GX_LOAD_BP_REG(0xad0d9400);
472 		GX_LOAD_BP_REG(0xb10dd400);
473 		GX_LOAD_BP_REG(0xae0d9800);
474 		GX_LOAD_BP_REG(0xb20dd800);
475 		GX_LOAD_BP_REG(0xaf0d9c00);
476 		GX_LOAD_BP_REG(0xb30ddc00);
477 
478 		return;
479 	}
480 
481 	if(nr==1) {
482 		//  Set_TextureImage0-3, GXTexMapID=0-3 tmem_offset=00000000, cache_width=32 kb, cache_height=32 kb, image_type=cached
483 		GX_LOAD_BP_REG(0x8c0d8000);
484 		GX_LOAD_BP_REG(0x900dc000);
485 		GX_LOAD_BP_REG(0x8d0d8800);
486 		GX_LOAD_BP_REG(0x910dc800);
487 		GX_LOAD_BP_REG(0x8e0d9000);
488 		GX_LOAD_BP_REG(0x920dd000);
489 		GX_LOAD_BP_REG(0x8f0d9800);
490 		GX_LOAD_BP_REG(0x930dd800);
491 
492 		//  Set_TextureImage0-3, GXTexMapID=4-7 tmem_offset=00010000, cache_width=32 kb, cache_height=32 kb, image_type=cached
493 		GX_LOAD_BP_REG(0xac0da000);
494 		GX_LOAD_BP_REG(0xb00de000);
495 		GX_LOAD_BP_REG(0xad0da800);
496 		GX_LOAD_BP_REG(0xb10de800);
497 		GX_LOAD_BP_REG(0xae0db000);
498 		GX_LOAD_BP_REG(0xb20df000);
499 		GX_LOAD_BP_REG(0xaf0db800);
500 		GX_LOAD_BP_REG(0xb30df800);
501 
502 		return;
503 	}
504 
505 	if(nr==2) {
506 		//  Set_TextureImage0-3, GXTexMapID=0-3 tmem_offset=00000000, cache_width=32 kb, cache_height=32 kb, image_type=cached
507 		GX_LOAD_BP_REG(0x8c0d8000);
508 		GX_LOAD_BP_REG(0x900dc000);
509 		GX_LOAD_BP_REG(0x8d0d8800);
510 		GX_LOAD_BP_REG(0x910dc800);
511 		GX_LOAD_BP_REG(0x8e0d9000);
512 		GX_LOAD_BP_REG(0x920dd000);
513 		GX_LOAD_BP_REG(0x8f0d9800);
514 		GX_LOAD_BP_REG(0x930dd800);
515 
516 		//  Set_TextureImage0-3, GXTexMapID=4-7 tmem_offset=00010000, cache_width=32 kb, cache_height=32 kb, image_type=cached
517 		GX_LOAD_BP_REG(0xac0da000);
518 		GX_LOAD_BP_REG(0xb00dc400);
519 		GX_LOAD_BP_REG(0xad0da800);
520 		GX_LOAD_BP_REG(0xb10dcc00);
521 		GX_LOAD_BP_REG(0xae0db000);
522 		GX_LOAD_BP_REG(0xb20dd400);
523 		GX_LOAD_BP_REG(0xaf0db800);
524 		GX_LOAD_BP_REG(0xb30ddc00);
525 
526 		return;
527 	}
528 }
529 
530 #if defined(HW_RVL)
__GXDefTexRegionCallback(GXTexObj * obj,u8 mapid)531 static GXTexRegion* __GXDefTexRegionCallback(GXTexObj *obj,u8 mapid)
532 {
533 	u32 fmt,mipmap;
534 	GXTexRegion *ret = NULL;
535 
536 	fmt = GX_GetTexObjFmt(obj);
537 	mipmap = GX_GetTexObjMipMap(obj);
538 	if(fmt>=GX_TF_CI4 && fmt<=GX_TF_CI14)
539 		return &__gx->texRegion[mapid];
540 	else if(fmt==GX_TF_CMPR)
541 		ret = &__gx->texRegion[mapid];
542 	else
543 		ret = &__gx->texRegion[mapid+8];
544 
545 	if(mipmap) ret = &__gx->texRegion[mapid+16];
546 
547 	return ret;
548 }
549 #else
__GXDefTexRegionCallback(GXTexObj * obj,u8 mapid)550 static GXTexRegion* __GXDefTexRegionCallback(GXTexObj *obj,u8 mapid)
551 {
552 	u32 fmt;
553 	u32 idx;
554 	static u32 regionA = 0;
555 	static u32 regionB = 0;
556 	GXTexRegion *ret = NULL;
557 
558 	fmt = GX_GetTexObjFmt(obj);
559 	if(fmt==0x0008 || fmt==0x0009 || fmt==0x000a) {
560 		idx = regionB++;
561 		ret = &__gx->texRegion[(idx&3)+8];
562 	} else {
563 		idx = regionA++;
564 		ret = &__gx->texRegion[(idx&7)];
565 	}
566 	return ret;
567 }
568 #endif
569 
__GXDefTlutRegionCallback(u32 tlut_name)570 static GXTlutRegion* __GXDefTlutRegionCallback(u32 tlut_name)
571 {
572 	return &__gx->tlutRegion[tlut_name];
573 }
574 
__GX_InitGX()575 static void __GX_InitGX()
576 {
577 	s32 i;
578 	u32 flag;
579 	GXRModeObj *rmode;
580 	Mtx identity_matrix =
581 	{
582 		{1,0,0,0},
583 		{0,1,0,0},
584 		{0,0,1,0}
585 	};
586 
587 	rmode = VIDEO_GetPreferredMode(NULL);
588 
589 	GX_SetCopyClear((GXColor)BLACK,0xffffff);
590 	GX_SetTexCoordGen(GX_TEXCOORD0,GX_TG_MTX2x4,GX_TG_TEX0,GX_IDENTITY);
591 	GX_SetTexCoordGen(GX_TEXCOORD1,GX_TG_MTX2x4,GX_TG_TEX1,GX_IDENTITY);
592 	GX_SetTexCoordGen(GX_TEXCOORD2,GX_TG_MTX2x4,GX_TG_TEX2,GX_IDENTITY);
593 	GX_SetTexCoordGen(GX_TEXCOORD3,GX_TG_MTX2x4,GX_TG_TEX3,GX_IDENTITY);
594 	GX_SetTexCoordGen(GX_TEXCOORD4,GX_TG_MTX2x4,GX_TG_TEX4,GX_IDENTITY);
595 	GX_SetTexCoordGen(GX_TEXCOORD5,GX_TG_MTX2x4,GX_TG_TEX5,GX_IDENTITY);
596 	GX_SetTexCoordGen(GX_TEXCOORD6,GX_TG_MTX2x4,GX_TG_TEX6,GX_IDENTITY);
597 	GX_SetTexCoordGen(GX_TEXCOORD7,GX_TG_MTX2x4,GX_TG_TEX7,GX_IDENTITY);
598 	GX_SetNumTexGens(1);
599 	GX_ClearVtxDesc();
600 	GX_InvVtxCache();
601 
602 	GX_SetLineWidth(6,GX_TO_ZERO);
603 	GX_SetPointSize(6,GX_TO_ZERO);
604 
605 	GX_EnableTexOffsets(GX_TEXCOORD0,GX_DISABLE,GX_DISABLE);
606 	GX_EnableTexOffsets(GX_TEXCOORD1,GX_DISABLE,GX_DISABLE);
607 	GX_EnableTexOffsets(GX_TEXCOORD2,GX_DISABLE,GX_DISABLE);
608 	GX_EnableTexOffsets(GX_TEXCOORD3,GX_DISABLE,GX_DISABLE);
609 	GX_EnableTexOffsets(GX_TEXCOORD4,GX_DISABLE,GX_DISABLE);
610 	GX_EnableTexOffsets(GX_TEXCOORD5,GX_DISABLE,GX_DISABLE);
611 	GX_EnableTexOffsets(GX_TEXCOORD6,GX_DISABLE,GX_DISABLE);
612 	GX_EnableTexOffsets(GX_TEXCOORD7,GX_DISABLE,GX_DISABLE);
613 
614 	GX_LoadPosMtxImm(identity_matrix,GX_PNMTX0);
615 	GX_LoadNrmMtxImm(identity_matrix,GX_PNMTX0);
616 	GX_SetCurrentMtx(GX_PNMTX0);
617 	GX_LoadTexMtxImm(identity_matrix,GX_IDENTITY,GX_MTX3x4);
618 	GX_LoadTexMtxImm(identity_matrix,GX_DTTIDENTITY,GX_MTX3x4);
619 
620 	GX_SetViewport(0,0,rmode->fbWidth,rmode->efbHeight,0,1);
621 	GX_SetCoPlanar(GX_DISABLE);
622 	GX_SetCullMode(GX_CULL_BACK);
623 	GX_SetClipMode(GX_CLIP_ENABLE);
624 
625 	GX_SetScissor(0,0,rmode->fbWidth,rmode->efbHeight);
626 	GX_SetScissorBoxOffset(0,0);
627 
628 	GX_SetNumChans(0);
629 
630 	GX_SetChanCtrl(GX_COLOR0A0,GX_DISABLE,GX_SRC_REG,GX_SRC_VTX,GX_LIGHTNULL,GX_DF_NONE,GX_AF_NONE);
631 	GX_SetChanAmbColor(GX_COLOR0A0,(GXColor)BLACK);
632 	GX_SetChanMatColor(GX_COLOR0A0,(GXColor)WHITE);
633 
634 	GX_SetChanCtrl(GX_COLOR1A1,GX_DISABLE,GX_SRC_REG,GX_SRC_VTX,GX_LIGHTNULL,GX_DF_NONE,GX_AF_NONE);
635 	GX_SetChanAmbColor(GX_COLOR1A1,(GXColor)BLACK);
636 	GX_SetChanMatColor(GX_COLOR1A1,(GXColor)WHITE);
637 
638 	GX_InvalidateTexAll();
639 	GX_SetTexRegionCallback(__GXDefTexRegionCallback);
640 	GX_SetTlutRegionCallback(__GXDefTlutRegionCallback);
641 
642 	GX_SetTevOrder(GX_TEVSTAGE0,GX_TEXCOORD0,GX_TEXMAP0,GX_COLOR0A0);
643 	GX_SetTevOrder(GX_TEVSTAGE1,GX_TEXCOORD1,GX_TEXMAP1,GX_COLOR0A0);
644 	GX_SetTevOrder(GX_TEVSTAGE2,GX_TEXCOORD2,GX_TEXMAP2,GX_COLOR0A0);
645 	GX_SetTevOrder(GX_TEVSTAGE3,GX_TEXCOORD3,GX_TEXMAP3,GX_COLOR0A0);
646 	GX_SetTevOrder(GX_TEVSTAGE4,GX_TEXCOORD4,GX_TEXMAP4,GX_COLOR0A0);
647 	GX_SetTevOrder(GX_TEVSTAGE5,GX_TEXCOORD5,GX_TEXMAP5,GX_COLOR0A0);
648 	GX_SetTevOrder(GX_TEVSTAGE6,GX_TEXCOORD6,GX_TEXMAP6,GX_COLOR0A0);
649 	GX_SetTevOrder(GX_TEVSTAGE7,GX_TEXCOORD7,GX_TEXMAP7,GX_COLOR0A0);
650 	GX_SetTevOrder(GX_TEVSTAGE8,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
651 	GX_SetTevOrder(GX_TEVSTAGE9,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
652 	GX_SetTevOrder(GX_TEVSTAGE10,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
653 	GX_SetTevOrder(GX_TEVSTAGE11,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
654 	GX_SetTevOrder(GX_TEVSTAGE12,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
655 	GX_SetTevOrder(GX_TEVSTAGE13,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
656 	GX_SetTevOrder(GX_TEVSTAGE14,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
657 	GX_SetTevOrder(GX_TEVSTAGE15,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
658 	GX_SetNumTevStages(1);
659 	GX_SetTevOp(GX_TEVSTAGE0,GX_REPLACE);
660 	GX_SetAlphaCompare(GX_ALWAYS,0,GX_AOP_AND,GX_ALWAYS,0);
661 	GX_SetZTexture(GX_ZT_DISABLE,GX_TF_Z8,0);
662 	for(i=0;i<GX_MAX_TEVSTAGE;i++) {
663 		GX_SetTevKColorSel(i,GX_TEV_KCSEL_1_4);
664 		GX_SetTevKAlphaSel(i,GX_TEV_KASEL_1);
665 		GX_SetTevSwapMode(i,GX_TEV_SWAP0,GX_TEV_SWAP0);
666 	}
667 
668 	GX_SetTevSwapModeTable(GX_TEV_SWAP0,GX_CH_RED,GX_CH_GREEN,GX_CH_BLUE,GX_CH_ALPHA);
669 	GX_SetTevSwapModeTable(GX_TEV_SWAP1,GX_CH_RED,GX_CH_RED,GX_CH_RED,GX_CH_ALPHA);
670 	GX_SetTevSwapModeTable(GX_TEV_SWAP2,GX_CH_GREEN,GX_CH_GREEN,GX_CH_GREEN,GX_CH_ALPHA);
671 	GX_SetTevSwapModeTable(GX_TEV_SWAP3,GX_CH_BLUE,GX_CH_BLUE,GX_CH_BLUE,GX_CH_ALPHA);
672 	for(i=0;i<GX_MAX_TEVSTAGE;i++) {
673 		GX_SetTevDirect(i);
674 	}
675 
676 	GX_SetNumIndStages(0);
677 	GX_SetIndTexCoordScale(GX_INDTEXSTAGE0,GX_ITS_1,GX_ITS_1);
678 	GX_SetIndTexCoordScale(GX_INDTEXSTAGE1,GX_ITS_1,GX_ITS_1);
679 	GX_SetIndTexCoordScale(GX_INDTEXSTAGE2,GX_ITS_1,GX_ITS_1);
680 	GX_SetIndTexCoordScale(GX_INDTEXSTAGE3,GX_ITS_1,GX_ITS_1);
681 
682 	GX_SetFog(GX_FOG_NONE,0,1,0.1,1,(GXColor)BLACK);
683 	GX_SetFogRangeAdj(GX_DISABLE,0,NULL);
684 
685 	GX_SetBlendMode(GX_BM_NONE,GX_BL_SRCALPHA,GX_BL_INVSRCALPHA,GX_LO_CLEAR);
686 	GX_SetColorUpdate(GX_ENABLE);
687 	GX_SetAlphaUpdate(GX_ENABLE);
688 	GX_SetZMode(GX_ENABLE,GX_LEQUAL,GX_TRUE);
689 	GX_SetZCompLoc(GX_TRUE);
690 	GX_SetDither(GX_ENABLE);
691 	GX_SetDstAlpha(GX_DISABLE,0);
692 	GX_SetPixelFmt(GX_PF_RGB8_Z24,GX_ZC_LINEAR);
693 
694 	GX_SetFieldMask(GX_ENABLE,GX_ENABLE);
695 
696 	flag = 0;
697 	if(rmode->viHeight==(rmode->xfbHeight<<1)) flag = 1;
698 	GX_SetFieldMode(rmode->field_rendering,flag);
699 
700 	GX_SetCopyClear((GXColor)GX_DEFAULT_BG,0x00ffffff);
701 	GX_SetDispCopySrc(0,0,rmode->fbWidth,rmode->efbHeight);
702 	GX_SetDispCopyDst(rmode->fbWidth,rmode->efbHeight);
703 	GX_SetDispCopyYScale(1.0);
704 	GX_SetCopyClamp(GX_CLAMP_TOP|GX_CLAMP_BOTTOM);
705 	GX_SetCopyFilter(GX_FALSE,NULL,GX_FALSE,NULL);
706 	GX_SetDispCopyGamma(GX_GM_1_0);
707 	GX_SetDispCopyFrame2Field(GX_COPY_PROGRESSIVE);
708 	GX_ClearBoundingBox();
709 
710 	GX_PokeColorUpdate(GX_TRUE);
711 	GX_PokeAlphaUpdate(GX_TRUE);
712 	GX_PokeDither(GX_FALSE);
713 	GX_PokeBlendMode(GX_BM_NONE,GX_BL_ZERO,GX_BL_ONE,GX_LO_SET);
714 	GX_PokeAlphaMode(GX_ALWAYS,0);
715 	GX_PokeAlphaRead(GX_READ_FF);
716 	GX_PokeDstAlpha(GX_DISABLE,0);
717 	GX_PokeZMode(GX_TRUE,GX_ALWAYS,GX_TRUE);
718 
719 	GX_SetGPMetric(GX_PERF0_NONE,GX_PERF1_NONE);
720 	GX_ClearGPMetric();
721 }
722 
__GX_FlushTextureState()723 static void __GX_FlushTextureState()
724 {
725 	GX_LOAD_BP_REG(__gx->tevIndMask);
726 }
727 
__GX_XfVtxSpecs()728 static void __GX_XfVtxSpecs()
729 {
730 	u32 xfvtxspecs = 0;
731 	u32 nrms,texs,cols;
732 
733 	cols = 0;
734 	if(__gx->vcdLo&0x6000) cols++;
735 	if(__gx->vcdLo&0x18000) cols++;
736 
737 	nrms = 0;
738 	if(__gx->vcdNrms==1) nrms = 1;
739 	else if(__gx->vcdNrms==2) nrms = 2;
740 
741 	texs = 0;
742 	if(__gx->vcdHi&0x3) texs++;
743 	if(__gx->vcdHi&0xc) texs++;
744 	if(__gx->vcdHi&0x30) texs++;
745 	if(__gx->vcdHi&0xc0) texs++;
746 	if(__gx->vcdHi&0x300) texs++;
747 	if(__gx->vcdHi&0xc00) texs++;
748 	if(__gx->vcdHi&0x3000) texs++;
749 	if(__gx->vcdHi&0xc000) texs++;
750 
751 	xfvtxspecs = (_SHIFTL(texs,4,4))|(_SHIFTL(nrms,2,2))|(cols&0x3);
752 	GX_LOAD_XF_REG(0x1008,xfvtxspecs);
753 }
754 
__GX_SetMatrixIndex(u32 mtx)755 static void __GX_SetMatrixIndex(u32 mtx)
756 {
757 	if(mtx<5) {
758 		GX_LOAD_CP_REG(0x30,__gx->mtxIdxLo);
759 		GX_LOAD_XF_REG(0x1018,__gx->mtxIdxLo);
760 	} else {
761 		GX_LOAD_CP_REG(0x40,__gx->mtxIdxHi);
762 		GX_LOAD_XF_REG(0x1019,__gx->mtxIdxHi);
763 	}
764 }
765 
__GX_SendFlushPrim()766 static void __GX_SendFlushPrim()
767 {
768 	u32 tmp,tmp2,cnt;
769 
770 	tmp = (__gx->xfFlush*__gx->xfFlushExp);
771 
772 	wgPipe->U8 = 0x98;
773 	wgPipe->U16 = __gx->xfFlush;
774 
775 	tmp2 = (tmp+3)/4;
776 	if(tmp>0) {
777 		cnt = tmp2/8;
778 		while(cnt) {
779 			wgPipe->U32 = 0;
780 					wgPipe->U32 = 0;
781 					wgPipe->U32 = 0;
782 					wgPipe->U32 = 0;
783 					wgPipe->U32 = 0;
784 					wgPipe->U32 = 0;
785 					wgPipe->U32 = 0;
786 					wgPipe->U32 = 0;
787 					cnt--;
788 		}
789 		tmp2 &= 0x0007;
790 		if(tmp2) {
791 			while(tmp2) {
792 				wgPipe->U32 = 0;
793 							tmp2--;
794 			}
795 		}
796 	}
797 	__gx->xfFlush = 1;
798 }
799 
__GX_SetVCD()800 static void __GX_SetVCD()
801 {
802 	GX_LOAD_CP_REG(0x50,__gx->vcdLo);
803 	GX_LOAD_CP_REG(0x60,__gx->vcdHi);
804 	__GX_XfVtxSpecs();
805 }
806 
__GX_SetVAT()807 static void __GX_SetVAT()
808 {
809 	u8 setvtx = 0;
810 	s32 i;
811 
812 	for(i=0;i<8;i++) {
813 		setvtx = (1<<i);
814 		if(__gx->VATTable&setvtx) {
815 			GX_LOAD_CP_REG((0x70+(i&7)),__gx->VAT0reg[i]);
816 			GX_LOAD_CP_REG((0x80+(i&7)),__gx->VAT1reg[i]);
817 			GX_LOAD_CP_REG((0x90+(i&7)),__gx->VAT2reg[i]);
818 		}
819 	}
820 	__gx->VATTable = 0;
821 }
822 
__SetSURegs(u8 texmap,u8 texcoord)823 static void __SetSURegs(u8 texmap,u8 texcoord)
824 {
825 	u32 reg;
826 	u16 wd,ht;
827 	u8 wrap_s,wrap_t;
828 
829 	wd = __gx->texMapSize[texmap]&0x3ff;
830 	ht = _SHIFTR(__gx->texMapSize[texmap],10,10);
831 	wrap_s = __gx->texMapWrap[texmap]&3;
832 	wrap_t = _SHIFTR(__gx->texMapWrap[texmap],2,2);
833 
834 	reg = (texcoord&0x7);
835 	__gx->suSsize[reg] = (__gx->suSsize[reg]&~0x0000ffff)|wd;
836 	__gx->suTsize[reg] = (__gx->suTsize[reg]&~0x0000ffff)|ht;
837 	__gx->suSsize[reg] = (__gx->suSsize[reg]&~0x00010000)|(_SHIFTL(wrap_s,16,1));
838 	__gx->suTsize[reg] = (__gx->suTsize[reg]&~0x00010000)|(_SHIFTL(wrap_t,16,1));
839 
840 	GX_LOAD_BP_REG(__gx->suSsize[reg]);
841 	GX_LOAD_BP_REG(__gx->suTsize[reg]);
842 }
843 
__GX_SetSUTexRegs()844 static void __GX_SetSUTexRegs()
845 {
846 	u32 i;
847 	u32 indtev,dirtev;
848 	u8 texcoord,texmap;
849 	u32 tevreg,tevm,texcm;
850 
851 	dirtev = (_SHIFTR(__gx->genMode,10,4))+1;
852 	indtev = _SHIFTR(__gx->genMode,16,3);
853 
854 	//indirect texture order
855 	for(i=0;i<indtev;i++) {
856 		switch(i) {
857 			case GX_INDTEXSTAGE0:
858 				texmap = __gx->tevRasOrder[2]&7;
859 				texcoord = _SHIFTR(__gx->tevRasOrder[2],3,3);
860 				break;
861 			case GX_INDTEXSTAGE1:
862 				texmap = _SHIFTR(__gx->tevRasOrder[2],6,3);
863 				texcoord = _SHIFTR(__gx->tevRasOrder[2],9,3);
864 				break;
865 			case GX_INDTEXSTAGE2:
866 				texmap = _SHIFTR(__gx->tevRasOrder[2],12,3);
867 				texcoord = _SHIFTR(__gx->tevRasOrder[2],15,3);
868 				break;
869 			case GX_INDTEXSTAGE3:
870 				texmap = _SHIFTR(__gx->tevRasOrder[2],18,3);
871 				texcoord = _SHIFTR(__gx->tevRasOrder[2],21,3);
872 				break;
873 			default:
874 				texmap = 0;
875 				texcoord = 0;
876 				break;
877 		}
878 
879 		texcm = _SHIFTL(1,texcoord,1);
880 		if(!(__gx->texCoordManually&texcm))
881 			__SetSURegs(texmap,texcoord);
882 	}
883 
884 	//direct texture order
885 	for(i=0;i<dirtev;i++) {
886 		tevreg = 3+(_SHIFTR(i,1,3));
887 		texmap = (__gx->tevTexMap[i]&0xff);
888 
889 		if(i&1) texcoord = _SHIFTR(__gx->tevRasOrder[tevreg],15,3);
890 		else texcoord = _SHIFTR(__gx->tevRasOrder[tevreg],3,3);
891 
892 		tevm = _SHIFTL(1,i,1);
893 		texcm = _SHIFTL(1,texcoord,1);
894 		if(texmap!=0xff && (__gx->tevTexCoordEnable&tevm) && !(__gx->texCoordManually&texcm)) {
895 			__SetSURegs(texmap,texcoord);
896 		}
897 	}
898 }
899 
__GX_SetGenMode()900 static void __GX_SetGenMode()
901 {
902 	GX_LOAD_BP_REG(__gx->genMode);
903 	__gx->xfFlush = 0;
904 }
905 
__GX_UpdateBPMask()906 static void __GX_UpdateBPMask()
907 {
908 #if defined(HW_DOL)
909 	u32 i;
910 	u32 nbmp,nres;
911 	u8 ntexmap;
912 
913 	nbmp = _SHIFTR(__gx->genMode,16,3);
914 
915 	nres = 0;
916 	for(i=0;i<nbmp;i++) {
917 		switch(i) {
918 			case GX_INDTEXSTAGE0:
919 				ntexmap = __gx->tevRasOrder[2]&7;
920 				break;
921 			case GX_INDTEXSTAGE1:
922 				ntexmap = _SHIFTR(__gx->tevRasOrder[2],6,3);
923 				break;
924 			case GX_INDTEXSTAGE2:
925 				ntexmap = _SHIFTR(__gx->tevRasOrder[2],12,3);
926 				break;
927 			case GX_INDTEXSTAGE3:
928 				ntexmap = _SHIFTR(__gx->tevRasOrder[2],18,3);
929 				break;
930 			default:
931 				ntexmap = 0;
932 				break;
933 		}
934 		nres |= (1<<ntexmap);
935 	}
936 
937 	if((__gx->tevIndMask&0xff)!=nres) {
938 		__gx->tevIndMask = (__gx->tevIndMask&~0xff)|(nres&0xff);
939 		GX_LOAD_BP_REG(__gx->tevIndMask);
940 	}
941 #endif
942 }
943 
__GX_SetIndirectMask(u32 mask)944 static void __GX_SetIndirectMask(u32 mask)
945 {
946 	__gx->tevIndMask = ((__gx->tevIndMask&~0xff)|(mask&0xff));
947 	GX_LOAD_BP_REG(__gx->tevIndMask);
948 }
949 
__GX_SetTexCoordGen()950 static void __GX_SetTexCoordGen()
951 {
952 	u32 i,mask;
953 	u32 texcoord;
954 
955 	if(__gx->dirtyState&0x02000000) GX_LOAD_XF_REG(0x103f,(__gx->genMode&0xf));
956 
957 	i = 0;
958 	texcoord = 0x1040;
959 	mask = _SHIFTR(__gx->dirtyState,16,8);
960 	while(mask) {
961 		if(mask&0x0001) {
962 			GX_LOAD_XF_REG(texcoord,__gx->texCoordGen[i]);
963 			GX_LOAD_XF_REG((texcoord+0x10),__gx->texCoordGen2[i]);
964 		}
965 		mask >>= 1;
966 		texcoord++;
967 		i++;
968 	}
969 }
970 
__GX_SetChanColor()971 static void __GX_SetChanColor()
972 {
973 	if(__gx->dirtyState&0x0100)
974 		GX_LOAD_XF_REG(0x100a,__gx->chnAmbColor[0]);
975 	if(__gx->dirtyState&0x0200)
976 		GX_LOAD_XF_REG(0x100b,__gx->chnAmbColor[1]);
977 	if(__gx->dirtyState&0x0400)
978 		GX_LOAD_XF_REG(0x100c,__gx->chnMatColor[0]);
979 	if(__gx->dirtyState&0x0800)
980 		GX_LOAD_XF_REG(0x100d,__gx->chnMatColor[1]);
981 }
982 
__GX_SetChanCntrl()983 static void __GX_SetChanCntrl()
984 {
985 	u32 i,chan,mask;
986 
987 	if(__gx->dirtyState&0x01000000) GX_LOAD_XF_REG(0x1009,(_SHIFTR(__gx->genMode,4,3)));
988 
989 	i = 0;
990 	chan = 0x100e;
991 	mask = _SHIFTR(__gx->dirtyState,12,4);
992 	while(mask) {
993 		if(mask&0x0001) GX_LOAD_XF_REG(chan,__gx->chnCntrl[i]);
994 
995 		mask >>= 1;
996 		chan++;
997 		i++;
998 	}
999 }
1000 
__GX_SetDirtyState()1001 static void __GX_SetDirtyState()
1002 {
1003 	if(__gx->dirtyState&0x0001) {
1004 		__GX_SetSUTexRegs();
1005 	}
1006 	if(__gx->dirtyState&0x0002) {
1007 		__GX_UpdateBPMask();
1008 	}
1009 	if(__gx->dirtyState&0x0004) {
1010 		__GX_SetGenMode();
1011 	}
1012 	if(__gx->dirtyState&0x0008) {
1013 		__GX_SetVCD();
1014 	}
1015 	if(__gx->dirtyState&0x0010) {
1016 		__GX_SetVAT();
1017 	}
1018 	if(__gx->dirtyState&~0xff) {
1019 		if(__gx->dirtyState&0x0f00) {
1020 			__GX_SetChanColor();
1021 		}
1022 		if(__gx->dirtyState&0x0100f000) {
1023 			__GX_SetChanCntrl();
1024 		}
1025 		if(__gx->dirtyState&0x02ff0000) {
1026 			__GX_SetTexCoordGen();
1027 		}
1028 		if(__gx->dirtyState&0x04000000) {
1029 			__GX_SetMatrixIndex(0);
1030 			__GX_SetMatrixIndex(5);
1031 		}
1032 	}
1033 	__gx->dirtyState = 0;
1034 }
1035 
__GX_GetNumXfbLines(u16 efbHeight,u32 yscale)1036 static u32 __GX_GetNumXfbLines(u16 efbHeight,u32 yscale)
1037 {
1038 	u32 tmp,tmp1;
1039 
1040 	tmp = (((efbHeight-1)<<8)/yscale)+1;
1041 	if(yscale>128 && yscale<256) {
1042 		while(yscale&0x01) yscale >>= 1;
1043 		tmp1 = yscale*(efbHeight/yscale);
1044 		if(!(efbHeight-tmp1)) tmp++;
1045 	}
1046 	if(tmp>1024) tmp = 1024;
1047 
1048 	return tmp;
1049 }
1050 
GX_Init(void * base,u32 size)1051 GXFifoObj* GX_Init(void *base,u32 size)
1052 {
1053 	s32 i,re0,re1;
1054 #if defined(HW_RVL)
1055 	u32 tmem;
1056 #else
1057 	u32 tmem_even,tmem_odd;
1058 #endif
1059 	u32 divis,res;
1060 	u32 divid = TB_BUS_CLOCK;
1061 	GXTexRegion *region = NULL;
1062 	GXTlutRegion *tregion = NULL;
1063 
1064 	LWP_InitQueue(&_gxwaitfinish);
1065 	SYS_RegisterResetFunc(&__gx_resetinfo);
1066 
1067 	memset(__gxregs,0,STRUCT_REGDEF_SIZE);
1068 
1069 	__GX_FifoInit();
1070 	GX_InitFifoBase(&_gxfifoobj,base,size);
1071 	GX_SetCPUFifo(&_gxfifoobj);
1072 	GX_SetGPFifo(&_gxfifoobj);
1073 	__GX_PEInit();
1074 	EnableWriteGatherPipe();
1075 
1076 	__gx->gxFifoInited = 1;
1077 
1078 	__gx->tevIndMask = 0xff;
1079 	__gx->tevIndMask = (__gx->tevIndMask&~0xff000000)|(_SHIFTL(0x0f,24,8));
1080 
1081 	i=0;
1082 	re0 = 0xc0;
1083 	re1 = 0xc1;
1084 	while(i<16) {
1085 		__gx->tevColorEnv[i] = (__gx->tevColorEnv[i]&~0xff000000)|(_SHIFTL(re0,24,8));
1086 		__gx->tevAlphaEnv[i] = (__gx->tevAlphaEnv[i]&~0xff000000)|(_SHIFTL(re1,24,8));
1087 		re0 += 2; re1 += 2; i++;
1088 	}
1089 
1090 	__gx->texCoordManually = 0;
1091 	__gx->dirtyState = 0;
1092 
1093 	__gx->saveDLctx = 1;
1094 	__gx->gxFifoUnlinked = 0;
1095 
1096 	__gx->sciTLcorner = (__gx->sciTLcorner&~0xff000000)|(_SHIFTL(0x20,24,8));
1097 	__gx->sciBRcorner = (__gx->sciBRcorner&~0xff000000)|(_SHIFTL(0x21,24,8));
1098 	__gx->lpWidth = (__gx->lpWidth&~0xff000000)|(_SHIFTL(0x22,24,8));
1099 	__gx->genMode = (__gx->genMode&~0xff000000)|(_SHIFTL(0x00,24,8));
1100 
1101 	i=0;
1102 	re0 = 0x30;
1103 	re1 = 0x31;
1104 	while(i<8) {
1105 		__gx->suSsize[i] = (__gx->suSsize[i]&~0xff000000)|(_SHIFTL(re0,24,8));
1106 		__gx->suTsize[i] = (__gx->suTsize[i]&~0xff000000)|(_SHIFTL(re1,24,8));
1107 		re0 += 2; re1 += 2; i++;
1108 	}
1109 
1110 	__gx->peZMode = (__gx->peZMode&~0xff000000)|(_SHIFTL(0x40,24,8));
1111 	__gx->peCMode0 = (__gx->peCMode0&~0xff000000)|(_SHIFTL(0x41,24,8));
1112 	__gx->peCMode1 = (__gx->peCMode1&~0xff000000)|(_SHIFTL(0x42,24,8));
1113 	__gx->peCntrl = (__gx->peCntrl&~0xff000000)|(_SHIFTL(0x43,24,8));
1114 
1115 	i=0;
1116 	re0 = 0x25;
1117 	while(i<11) {
1118 		__gx->tevRasOrder[i] = (__gx->tevRasOrder[i]&~0xff000000)|(_SHIFTL(re0,24,8));
1119 		re0++; i++;
1120 	}
1121 
1122 	divis = 500;
1123 	res = (u32)(divid/divis);
1124 	__GX_FlushTextureState();
1125 	GX_LOAD_BP_REG(0x69000000|((_SHIFTR(res,11,24))|0x0400));
1126 
1127 	divis = 4224;
1128 	res = (u32)(res/divis);
1129 	__GX_FlushTextureState();
1130 	GX_LOAD_BP_REG(0x46000000|(res|0x0200));
1131 
1132 	i=0;
1133 	re0 = 0xf6;
1134 	while(i<8) {
1135 		__gx->tevSwapModeTable[i] = (__gx->tevSwapModeTable[i]&~0xff000000)|(_SHIFTL(re0,24,8));
1136 		re0++; i++;
1137 	}
1138 
1139 	__gx->tevTexCoordEnable = 0;
1140 	__gx->perf0Mode = GX_PERF0_NONE;
1141 	__gx->perf1Mode = GX_PERF1_NONE;
1142 	__gx->cpPerfMode = 0;
1143 
1144 	__GX_InitRevBits();
1145 
1146 	i=0;
1147 	while(i<16) {
1148 		__gx->tevTexMap[i] = 0xff;
1149 		i++;
1150 	}
1151 
1152 #if defined(HW_RVL)
1153 	i = 0;
1154 	while(i<8) {
1155 		region = &__gx->texRegion[i];
1156 		GX_InitTexCacheRegion(region,GX_FALSE,_gxtexregionaddrtable[i+0],GX_TEXCACHE_32K,_gxtexregionaddrtable[i+8],GX_TEXCACHE_32K);
1157 
1158 		region = &__gx->texRegion[i+8];
1159 		GX_InitTexCacheRegion(region,GX_FALSE,_gxtexregionaddrtable[i+16],GX_TEXCACHE_32K,_gxtexregionaddrtable[i+24],GX_TEXCACHE_32K);
1160 
1161 		region = &__gx->texRegion[i+16];
1162 		GX_InitTexCacheRegion(region,GX_TRUE,_gxtexregionaddrtable[i+32],GX_TEXCACHE_32K,_gxtexregionaddrtable[i+40],GX_TEXCACHE_32K);
1163 
1164 		i++;
1165 	}
1166 
1167 	i=0;
1168 	while(i<16) {
1169 		tmem = 0x000C0000+(i<<13);
1170 		tregion = &__gx->tlutRegion[i];
1171 		GX_InitTlutRegion(tregion,tmem,GX_TLUT_256);
1172 		i++;
1173 	}
1174 
1175 	i=0;
1176 	while(i<4) {
1177 		tmem = 0x000E0000+(i<<15);
1178 		tregion = &__gx->tlutRegion[i+16];
1179 		GX_InitTlutRegion(tregion,tmem,GX_TLUT_1K);
1180 		i++;
1181 	}
1182 #else
1183 	for(i=0;i<8;i++) {
1184 		tmem_even = tmem_odd = (i<<15);
1185 		region = &__gx->texRegion[i];
1186 		GX_InitTexCacheRegion(region,GX_FALSE,tmem_even,GX_TEXCACHE_32K,(tmem_odd+0x00080000),GX_TEXCACHE_32K);
1187 	}
1188 	for(i=0;i<4;i++) {
1189 		tmem_even = ((0x08+(i<<1))<<15);
1190 		tmem_odd = ((0x09+(i<<1))<<15);
1191 		region = &__gx->texRegion[i+8];
1192 		GX_InitTexCacheRegion(region,GX_FALSE,tmem_even,GX_TEXCACHE_32K,tmem_odd,GX_TEXCACHE_32K);
1193 	}
1194 	for(i=0;i<16;i++) {
1195 		tmem_even = (i<<13)+0x000C0000;
1196 		tregion = &__gx->tlutRegion[i];
1197 		GX_InitTlutRegion(tregion,tmem_even,GX_TLUT_256);
1198 	}
1199 	for(i=0;i<4;i++) {
1200 		tmem_even = (i<<15)+0x000E0000;
1201 		tregion = &__gx->tlutRegion[i+16];
1202 		GX_InitTlutRegion(tregion,tmem_even,GX_TLUT_1K);
1203 	}
1204 #endif
1205 	_cpReg[3] = 0;
1206 	GX_LOAD_CP_REG(0x20,0x00000000);
1207 	GX_LOAD_XF_REG(0x1006,0x0);
1208 
1209 	GX_LOAD_BP_REG(0x23000000);
1210 	GX_LOAD_BP_REG(0x24000000);
1211 	GX_LOAD_BP_REG(0x67000000);
1212 
1213 	__GX_SetIndirectMask(0);
1214 #if defined(HW_RVL)
1215 	__GX_SetTmemConfig(2);
1216 #else
1217 	__GX_SetTmemConfig(0);
1218 #endif
1219 	__GX_InitGX();
1220 
1221 	return &_gxfifoobj;
1222 }
1223 
GX_InitFifoBase(GXFifoObj * fifo,void * base,u32 size)1224 void GX_InitFifoBase(GXFifoObj *fifo,void *base,u32 size)
1225 {
1226 	struct __gxfifo *ptr = (struct __gxfifo*)fifo;
1227 
1228 	if(!ptr || size<GX_FIFO_MINSIZE) return;
1229 
1230 	ptr->buf_start = (u32)base;
1231 	ptr->buf_end = (u32)base + size - 4;
1232 	ptr->size = size;
1233 	ptr->rdwt_dst = 0;
1234 
1235 	GX_InitFifoLimits(fifo,(size-GX_FIFO_HIWATERMARK),((size>>1)&0x7fffffe0));
1236 	GX_InitFifoPtrs(fifo,base,base);
1237 }
1238 
GX_InitFifoLimits(GXFifoObj * fifo,u32 hiwatermark,u32 lowatermark)1239 void GX_InitFifoLimits(GXFifoObj *fifo,u32 hiwatermark,u32 lowatermark)
1240 {
1241 	struct __gxfifo *ptr = (struct __gxfifo*)fifo;
1242 
1243 	ptr->hi_mark = hiwatermark;
1244 	ptr->lo_mark = lowatermark;
1245 }
1246 
GX_InitFifoPtrs(GXFifoObj * fifo,void * rd_ptr,void * wt_ptr)1247 void GX_InitFifoPtrs(GXFifoObj *fifo,void *rd_ptr,void *wt_ptr)
1248 {
1249 	u32 level;
1250 	s32 rdwt_dst;
1251 	struct __gxfifo *ptr = (struct __gxfifo*)fifo;
1252 
1253 	_CPU_ISR_Disable(level);
1254 	rdwt_dst =  wt_ptr-rd_ptr;
1255 	ptr->rd_ptr = (u32)rd_ptr;
1256 	ptr->wt_ptr = (u32)wt_ptr;
1257 	ptr->rdwt_dst = rdwt_dst;
1258 	if(rdwt_dst<0) {
1259 		rdwt_dst += ptr->size;
1260 		ptr->rd_ptr = rdwt_dst;
1261 	}
1262 	_CPU_ISR_Restore(level);
1263 }
1264 
GX_GetFifoPtrs(GXFifoObj * fifo,void ** rd_ptr,void ** wt_ptr)1265 void GX_GetFifoPtrs(GXFifoObj *fifo,void **rd_ptr,void **wt_ptr)
1266 {
1267 	struct __gxfifo *ptr = (struct __gxfifo*)fifo;
1268 	*rd_ptr = (void*)ptr->rd_ptr;
1269 	*wt_ptr = (void*)ptr->wt_ptr;
1270 }
1271 
GX_SetCPUFifo(GXFifoObj * fifo)1272 void GX_SetCPUFifo(GXFifoObj *fifo)
1273 {
1274 	u32 level;
1275 	struct __gxfifo *ptr = (struct __gxfifo*)fifo;
1276 	struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
1277 
1278 	_CPU_ISR_Disable(level);
1279 	if(!fifo) {
1280 		_gxcpufifoready = 0;
1281 		_cpgplinked = 0;
1282 		cpufifo->gpfifo_ready = 0;
1283 		cpufifo->cpufifo_ready = 0;
1284 		_CPU_ISR_Restore(level);
1285 		return;
1286 	}
1287 
1288 	cpufifo->buf_start = ptr->buf_start;
1289 	cpufifo->buf_end = ptr->buf_end;
1290 	cpufifo->size = ptr->size;
1291 	cpufifo->hi_mark = ptr->hi_mark;
1292 	cpufifo->lo_mark = ptr->lo_mark;
1293 	cpufifo->rd_ptr = ptr->rd_ptr;
1294 	cpufifo->wt_ptr = ptr->wt_ptr;
1295 	cpufifo->rdwt_dst = ptr->rdwt_dst;
1296 	cpufifo->fifo_wrap = ptr->fifo_wrap;
1297 	cpufifo->gpfifo_ready = ptr->gpfifo_ready;
1298 	cpufifo->cpufifo_ready = 1;
1299 
1300 	_gxcpufifoready = 1;
1301 	if(__GX_CPGPLinkCheck()) {
1302 		_cpgplinked = 1;
1303 		cpufifo->gpfifo_ready = 1;
1304 
1305 		_piReg[3] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_start);
1306 		_piReg[4] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_end);
1307 		_piReg[5] = (cpufifo->wt_ptr&0x1FFFFFE0);
1308 
1309 		__GX_WriteFifoIntReset(GX_TRUE,GX_TRUE);
1310 		__GX_WriteFifoIntEnable(GX_ENABLE,GX_DISABLE);
1311 		__GX_FifoLink(GX_TRUE);
1312 
1313 		_CPU_ISR_Restore(level);
1314 		return;
1315 	}
1316 
1317 	if(_cpgplinked) {
1318 		__GX_FifoLink(GX_FALSE);
1319 		_cpgplinked = 0;
1320 	}
1321 
1322 	__GX_WriteFifoIntEnable(GX_DISABLE,GX_DISABLE);
1323 
1324 	_piReg[3] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_start);
1325 	_piReg[4] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_end);
1326 	_piReg[5] = (cpufifo->wt_ptr&0x1FFFFFE0);
1327 	ppcsync();
1328 
1329 	_CPU_ISR_Restore(level);
1330 }
1331 
GX_GetCPUFifo(GXFifoObj * fifo)1332 void GX_GetCPUFifo(GXFifoObj *fifo)
1333 {
1334 	struct __gxfifo* ptr = (struct __gxfifo*)fifo;
1335 	struct __gxfifo* cpufifo = (struct __gxfifo*)&_cpufifo;
1336 
1337 	if(!_gxcpufifoready) return;
1338 
1339 	GX_Flush();
1340 	__GX_SaveFifo();
1341 
1342 	ptr->buf_start = cpufifo->buf_start;
1343 	ptr->buf_end = cpufifo->buf_end;
1344 	ptr->size = cpufifo->size;
1345 	ptr->rd_ptr = cpufifo->rd_ptr;
1346 	ptr->wt_ptr = cpufifo->wt_ptr;
1347 	ptr->rdwt_dst = cpufifo->rdwt_dst;
1348 	ptr->hi_mark = cpufifo->hi_mark;
1349 	ptr->lo_mark = cpufifo->lo_mark;
1350 	ptr->fifo_wrap = cpufifo->fifo_wrap;
1351 	ptr->cpufifo_ready = cpufifo->cpufifo_ready;
1352 	ptr->gpfifo_ready = cpufifo->gpfifo_ready;
1353 }
1354 
GX_SetGPFifo(GXFifoObj * fifo)1355 void GX_SetGPFifo(GXFifoObj *fifo)
1356 {
1357 	u32 level;
1358 	struct __gxfifo *ptr = (struct __gxfifo*)fifo;
1359 	struct __gxfifo *gpfifo = (struct __gxfifo*)&_gpfifo;
1360 
1361 	_CPU_ISR_Disable(level);
1362 	__GX_FifoReadDisable();
1363 	__GX_WriteFifoIntEnable(GX_DISABLE,GX_DISABLE);
1364 
1365 	if(!fifo) {
1366 		_gxgpfifoready = 0;
1367 		_cpgplinked = 0;
1368 		gpfifo->cpufifo_ready = 0;
1369 		gpfifo->gpfifo_ready = 0;
1370 		__GX_FifoLink(GX_FALSE);
1371 		_CPU_ISR_Restore(level);
1372 		return;
1373 	}
1374 
1375 	gpfifo->buf_start = ptr->buf_start;
1376 	gpfifo->buf_end = ptr->buf_end;
1377 	gpfifo->size = ptr->size;
1378 	gpfifo->hi_mark = ptr->hi_mark;
1379 	gpfifo->lo_mark = ptr->lo_mark;
1380 	gpfifo->rd_ptr = ptr->rd_ptr;
1381 	gpfifo->wt_ptr = ptr->wt_ptr;
1382 	gpfifo->rdwt_dst = ptr->rdwt_dst;
1383 	gpfifo->fifo_wrap = ptr->fifo_wrap;
1384 	gpfifo->cpufifo_ready = ptr->cpufifo_ready;
1385 	gpfifo->gpfifo_ready = 1;
1386 	_gxgpfifoready = 1;
1387 
1388 	/* setup fifo base */
1389 	_cpReg[16] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->buf_start),0,16);
1390 	_cpReg[17] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->buf_start),16,16);
1391 
1392 	/* setup fifo end */
1393 	_cpReg[18] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->buf_end),0,16);
1394 	_cpReg[19] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->buf_end),16,16);
1395 
1396 	/* setup hiwater mark */
1397 	_cpReg[20] = _SHIFTL(gpfifo->hi_mark,0,16);
1398 	_cpReg[21] = _SHIFTR(gpfifo->hi_mark,16,16);
1399 
1400 	/* setup lowater mark */
1401 	_cpReg[22] = _SHIFTL(gpfifo->lo_mark,0,16);
1402 	_cpReg[23] = _SHIFTR(gpfifo->lo_mark,16,16);
1403 
1404 	/* setup rd<->wd dist */
1405 	_cpReg[24] = _SHIFTL(gpfifo->rdwt_dst,0,16);
1406 	_cpReg[25] = _SHIFTR(gpfifo->rdwt_dst,16,16);
1407 
1408 	/* setup wt ptr */
1409 	_cpReg[26] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->wt_ptr),0,16);
1410 	_cpReg[27] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->wt_ptr),16,16);
1411 
1412 	/* setup rd ptr */
1413 	_cpReg[28] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->rd_ptr),0,16);
1414 	_cpReg[29] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->rd_ptr),16,16);
1415 	ppcsync();
1416 
1417 	if(__GX_CPGPLinkCheck()) {
1418 		_cpgplinked = 1;
1419 		gpfifo->cpufifo_ready = 1;
1420 		__GX_WriteFifoIntEnable(GX_ENABLE,GX_DISABLE);
1421 		__GX_FifoLink(GX_TRUE);
1422 	} else {
1423 		_cpgplinked = 0;
1424 		gpfifo->cpufifo_ready = 0;
1425 		__GX_WriteFifoIntEnable(GX_DISABLE,GX_DISABLE);
1426 		__GX_FifoLink(GX_FALSE);
1427 	}
1428 
1429 	__GX_WriteFifoIntReset(GX_TRUE,GX_TRUE);
1430 	__GX_FifoReadEnable();
1431 	_CPU_ISR_Restore(level);
1432 }
1433 
GX_GetGPFifo(GXFifoObj * fifo)1434 void GX_GetGPFifo(GXFifoObj *fifo)
1435 {
1436 	struct __gxfifo* ptr = (struct __gxfifo*)fifo;
1437 	struct __gxfifo* gpfifo = (struct __gxfifo*)&_gpfifo;
1438 
1439 	if(!_gxgpfifoready) return;
1440 
1441 	__GX_SaveFifo();
1442 
1443 	ptr->buf_start = gpfifo->buf_start;
1444 	ptr->buf_end = gpfifo->buf_end;
1445 	ptr->size = gpfifo->size;
1446 	ptr->rd_ptr = gpfifo->rd_ptr;
1447 	ptr->wt_ptr = gpfifo->wt_ptr;
1448 	ptr->rdwt_dst = gpfifo->rdwt_dst;
1449 	ptr->hi_mark = gpfifo->hi_mark;
1450 	ptr->lo_mark = gpfifo->lo_mark;
1451 	ptr->fifo_wrap = gpfifo->fifo_wrap;
1452 	ptr->gpfifo_ready = gpfifo->gpfifo_ready;
1453 	ptr->cpufifo_ready = gpfifo->cpufifo_ready;
1454 }
1455 
GX_GetFifoBase(GXFifoObj * fifo)1456 void* GX_GetFifoBase(GXFifoObj *fifo)
1457 {
1458 	return (void*)((struct __gxfifo*)fifo)->buf_start;
1459 }
1460 
GX_GetFifoSize(GXFifoObj * fifo)1461 u32 GX_GetFifoSize(GXFifoObj *fifo)
1462 {
1463 	return ((struct __gxfifo*)fifo)->size;
1464 }
1465 
GX_GetFifoCount(GXFifoObj * fifo)1466 u32 GX_GetFifoCount(GXFifoObj *fifo)
1467 {
1468 	return ((struct __gxfifo*)fifo)->rdwt_dst;
1469 }
1470 
GX_GetFifoWrap(GXFifoObj * fifo)1471 u8 GX_GetFifoWrap(GXFifoObj *fifo)
1472 {
1473 	return ((struct __gxfifo*)fifo)->fifo_wrap;
1474 }
1475 
GX_GetOverflowCount()1476 u32 GX_GetOverflowCount()
1477 {
1478 	return _gxoverflowcount;
1479 }
1480 
GX_ResetOverflowCount()1481 u32 GX_ResetOverflowCount()
1482 {
1483 	u32 ret = _gxoverflowcount;
1484 	_gxoverflowcount = 0;
1485 	return ret;
1486 }
1487 
GX_GetCurrentGXThread()1488 lwp_t GX_GetCurrentGXThread()
1489 {
1490 	return _gxcurrentlwp;
1491 }
1492 
GX_SetCurrentGXThread()1493 lwp_t GX_SetCurrentGXThread()
1494 {
1495 	u32 level;
1496 
1497 	_CPU_ISR_Disable(level);
1498 	lwp_t ret = _gxcurrentlwp;
1499 	_gxcurrentlwp = LWP_GetSelf();
1500 	_CPU_ISR_Restore(level);
1501 
1502 	return ret;
1503 }
1504 
GX_RedirectWriteGatherPipe(void * ptr)1505 volatile void* GX_RedirectWriteGatherPipe(void *ptr)
1506 {
1507 	u32 level;
1508 	struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
1509 
1510 	_CPU_ISR_Disable(level);
1511 	GX_Flush();
1512 	while(!IsWriteGatherBufferEmpty());
1513 
1514 	mtwpar(0x0C008000);
1515 	if(_cpgplinked) {
1516 		__GX_FifoLink(GX_FALSE);
1517 		__GX_WriteFifoIntEnable(GX_DISABLE,GX_DISABLE);
1518 	}
1519 	cpufifo->wt_ptr = (u32)MEM_PHYSICAL_TO_K0(_piReg[5]&~0x04000000);
1520 
1521 	_piReg[3] = 0;
1522 	_piReg[4] = 0x04000000;
1523 	_piReg[5] = (((u32)ptr&0x3FFFFFE0)&~0x04000000);
1524 	_sync();
1525 
1526 	_CPU_ISR_Restore(level);
1527 
1528 	return (volatile void*)0x0C008000;
1529 }
1530 
GX_RestoreWriteGatherPipe()1531 void GX_RestoreWriteGatherPipe()
1532 {
1533 	u32 level;
1534 	struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
1535 
1536 	_CPU_ISR_Disable(level);
1537 
1538 	wgPipe->U32 = 0;
1539 	wgPipe->U32 = 0;
1540 	wgPipe->U32 = 0;
1541 	wgPipe->U32 = 0;
1542 	wgPipe->U32 = 0;
1543 	wgPipe->U32 = 0;
1544 	wgPipe->U32 = 0;
1545 	wgPipe->U32 = 0;
1546 
1547 	ppcsync();
1548 	while(!IsWriteGatherBufferEmpty());
1549 
1550 	mtwpar(0x0C008000);
1551 	_piReg[3] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_start);
1552 	_piReg[4] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_end);
1553 	_piReg[5] = (((u32)cpufifo->wt_ptr&0x3FFFFFE0)&~0x04000000);
1554 	if(_cpgplinked) {
1555 		__GX_WriteFifoIntReset(GX_TRUE,GX_TRUE);
1556 		__GX_WriteFifoIntEnable(GX_ENABLE,GX_DISABLE);
1557 		__GX_FifoLink(GX_TRUE);
1558 	}
1559 	_CPU_ISR_Restore(level);
1560 }
1561 
GX_Flush()1562 void GX_Flush()
1563 {
1564 	if(__gx->dirtyState)
1565 		__GX_SetDirtyState();
1566 
1567 	wgPipe->U32 = 0;
1568 	wgPipe->U32 = 0;
1569 	wgPipe->U32 = 0;
1570 	wgPipe->U32 = 0;
1571 	wgPipe->U32 = 0;
1572 	wgPipe->U32 = 0;
1573 	wgPipe->U32 = 0;
1574 	wgPipe->U32 = 0;
1575 
1576 	ppcsync();
1577 }
1578 
GX_EnableBreakPt(void * break_pt)1579 void GX_EnableBreakPt(void *break_pt)
1580 {
1581 	u32 level = 0;
1582 	_CPU_ISR_Disable(level);
1583 	__GX_FifoReadDisable();
1584 	_cpReg[30] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(break_pt),0,16);
1585 	_cpReg[31] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(break_pt),16,16);
1586 	__gx->cpCRreg = (__gx->cpCRreg&~0x22)|0x22;
1587 	_cpReg[1] = __gx->cpCRreg;
1588 	_gxcurrbp = break_pt;
1589 	__GX_FifoReadEnable();
1590  	_CPU_ISR_Restore(level);
1591 }
1592 
GX_DisableBreakPt()1593 void GX_DisableBreakPt()
1594 {
1595 	u32 level = 0;
1596 	_CPU_ISR_Disable(level);
1597 	__gx->cpCRreg = (__gx->cpCRreg&~0x22);
1598 	_cpReg[1] = __gx->cpCRreg;
1599 	_gxcurrbp = NULL;
1600 	_CPU_ISR_Restore(level);
1601 }
1602 
1603 #if defined(HW_DOL)
GX_AbortFrame()1604 void GX_AbortFrame()
1605 {
1606 	_piReg[6] = 1;
1607 	__GX_WaitAbort(50);
1608 	_piReg[6] = 0;
1609 	__GX_WaitAbort(5);
1610 
1611 	if(__GX_IsGPFifoReady())
1612 		__GX_CleanGPFifo();
1613 }
1614 #elif defined(HW_RVL)
GX_AbortFrame()1615 void GX_AbortFrame()
1616 {
1617 	__GX_Abort();
1618 	if(__GX_IsGPFifoReady()) {
1619 		__GX_CleanGPFifo();
1620 		__GX_InitRevBits();
1621 
1622 		__gx->dirtyState = 0;
1623 		GX_Flush();
1624 	}
1625 }
1626 #endif
1627 
GX_SetDrawSync(u16 token)1628 void GX_SetDrawSync(u16 token)
1629 {
1630 	u32 level = 0;
1631 	_CPU_ISR_Disable(level);
1632 	GX_LOAD_BP_REG(0x48000000 | token);
1633 	GX_LOAD_BP_REG(0x47000000 | token);
1634 	GX_Flush();
1635 	_CPU_ISR_Restore(level);
1636 }
1637 
GX_GetDrawSync()1638 u16 GX_GetDrawSync()
1639 {
1640 	return _peReg[7];
1641 }
1642 
GX_SetDrawDone()1643 void GX_SetDrawDone()
1644 {
1645 	u32 level;
1646 	_CPU_ISR_Disable(level);
1647 	GX_LOAD_BP_REG(0x45000002); // set draw done!
1648 	GX_Flush();
1649 	_gxfinished = 0;
1650 	_CPU_ISR_Restore(level);
1651 }
1652 
GX_WaitDrawDone()1653 void GX_WaitDrawDone()
1654 {
1655 	u32 level;
1656 	_CPU_ISR_Disable(level);
1657 	while(!_gxfinished)
1658 		LWP_ThreadSleep(_gxwaitfinish);
1659 	_CPU_ISR_Restore(level);
1660 }
1661 
GX_DrawDone()1662 void GX_DrawDone()
1663 {
1664 	u32 level;
1665 
1666 	_CPU_ISR_Disable(level);
1667 	GX_LOAD_BP_REG(0x45000002); // set draw done!
1668 	GX_Flush();
1669 
1670 	_gxfinished = 0;
1671 	_CPU_ISR_Flash(level);
1672 
1673 	while(!_gxfinished)
1674 		LWP_ThreadSleep(_gxwaitfinish);
1675 	_CPU_ISR_Restore(level);
1676 }
1677 
GX_SetDrawDoneCallback(GXDrawDoneCallback cb)1678 GXDrawDoneCallback GX_SetDrawDoneCallback(GXDrawDoneCallback cb)
1679 {
1680 	u32 level;
1681 
1682 	_CPU_ISR_Disable(level);
1683 	GXDrawDoneCallback ret = drawDoneCB;
1684 	drawDoneCB = cb;
1685 	_CPU_ISR_Restore(level);
1686 	return ret;
1687 }
1688 
GX_SetDrawSyncCallback(GXDrawSyncCallback cb)1689 GXDrawSyncCallback GX_SetDrawSyncCallback(GXDrawSyncCallback cb)
1690 {
1691 	u32 level;
1692 
1693 	_CPU_ISR_Disable(level);
1694 	GXDrawSyncCallback ret = tokenCB;
1695 	tokenCB = cb;
1696 	_CPU_ISR_Restore(level);
1697 	return ret;
1698 }
1699 
GX_SetBreakPtCallback(GXBreakPtCallback cb)1700 GXBreakPtCallback GX_SetBreakPtCallback(GXBreakPtCallback cb)
1701 {
1702 	u32 level;
1703 
1704 	_CPU_ISR_Disable(level);
1705 	GXBreakPtCallback ret = breakPtCB;
1706 	breakPtCB = cb;
1707 	_CPU_ISR_Restore(level);
1708 	return ret;
1709 }
1710 
GX_PixModeSync()1711 void GX_PixModeSync()
1712 {
1713 	GX_LOAD_BP_REG(__gx->peCntrl);
1714 }
1715 
GX_TexModeSync()1716 void GX_TexModeSync()
1717 {
1718 	GX_LOAD_BP_REG(0x63000000);
1719 }
1720 
GX_SetMisc(u32 token,u32 value)1721 void GX_SetMisc(u32 token,u32 value)
1722 {
1723 	u32 cnt;
1724 
1725 	if(token==GX_MT_XF_FLUSH) {
1726 		__gx->xfFlushSafe = value;
1727 		cnt = cntlzw(__gx->xfFlushSafe);
1728 		__gx->xfFlushExp = _SHIFTR(cnt,5,16);
1729 
1730 		__gx->xfFlush = 1;
1731 		if(!__gx->xfFlushSafe) return;
1732 
1733 		__gx->dirtyState |= 0x0008;
1734 	} else if(token==GX_MT_DL_SAVE_CTX) {
1735 		__gx->saveDLctx = (value&0xff);
1736 	}
1737 	return;
1738 }
1739 
GX_SetViewportJitter(f32 xOrig,f32 yOrig,f32 wd,f32 ht,f32 nearZ,f32 farZ,u32 field)1740 void GX_SetViewportJitter(f32 xOrig,f32 yOrig,f32 wd,f32 ht,f32 nearZ,f32 farZ,u32 field)
1741 {
1742 	f32 x0,y0,x1,y1,n,f,z;
1743 	static f32 Xfactor = 0.5;
1744 	static f32 Yfactor = 342.0;
1745 	static f32 Zfactor = 16777215.0;
1746 
1747 	if(!field) yOrig -= Xfactor;
1748 
1749 	x0 = wd*Xfactor;
1750 	y0 = (-ht)*Xfactor;
1751 	x1 = (xOrig+(wd*Xfactor))+Yfactor;
1752 	y1 = (yOrig+(ht*Xfactor))+Yfactor;
1753 	n = Zfactor*nearZ;
1754 	f = Zfactor*farZ;
1755 	z = f-n;
1756 
1757 	GX_LOAD_XF_REGS(0x101a,6);
1758 	wgPipe->F32 = x0;
1759 	wgPipe->F32 = y0;
1760 	wgPipe->F32 = z;
1761 	wgPipe->F32 = x1;
1762 	wgPipe->F32 = y1;
1763 	wgPipe->F32 = f;
1764 }
1765 
GX_SetViewport(f32 xOrig,f32 yOrig,f32 wd,f32 ht,f32 nearZ,f32 farZ)1766 void GX_SetViewport(f32 xOrig,f32 yOrig,f32 wd,f32 ht,f32 nearZ,f32 farZ)
1767 {
1768 	GX_SetViewportJitter(xOrig,yOrig,wd,ht,nearZ,farZ,1);
1769 }
1770 
GX_LoadProjectionMtx(Mtx44 mt,u8 type)1771 void GX_LoadProjectionMtx(Mtx44 mt,u8 type)
1772 {
1773 	f32 tmp[7];
1774 
1775 	((u32*)((void*)tmp))[6] = (u32)type;
1776 	tmp[0] = mt[0][0];
1777 	tmp[2] = mt[1][1];
1778 	tmp[4] = mt[2][2];
1779 	tmp[5] = mt[2][3];
1780 
1781 	switch(type) {
1782 		case GX_PERSPECTIVE:
1783 			tmp[1] = mt[0][2];
1784 			tmp[3] = mt[1][2];
1785 			break;
1786 		case GX_ORTHOGRAPHIC:
1787 			tmp[1] = mt[0][3];
1788 			tmp[3] = mt[1][3];
1789 			break;
1790 		default:
1791 			tmp[1] = 0.0;
1792 			tmp[3] = 0.0;
1793 			break;
1794 	}
1795 
1796 	GX_LOAD_XF_REGS(0x1020,7);
1797 	wgPipe->F32 = tmp[0];
1798 	wgPipe->F32 = tmp[1];
1799 	wgPipe->F32 = tmp[2];
1800 	wgPipe->F32 = tmp[3];
1801 	wgPipe->F32 = tmp[4];
1802 	wgPipe->F32 = tmp[5];
1803 	wgPipe->F32 = tmp[6];
1804 }
1805 
__GetImageTileCount(u32 fmt,u16 wd,u16 ht,u32 * xtiles,u32 * ytiles,u32 * zplanes)1806 static void __GetImageTileCount(u32 fmt,u16 wd,u16 ht,u32 *xtiles,u32 *ytiles,u32 *zplanes)
1807 {
1808 	u32 xshift,yshift,tile;
1809 
1810 	switch(fmt) {
1811 		case GX_TF_I4:
1812 		case GX_TF_IA4:
1813 		case GX_CTF_R4:
1814 		case GX_CTF_RA4:
1815 		case GX_CTF_Z4:
1816 			xshift = 3;
1817 			yshift = 3;
1818 			break;
1819 		case GX_TF_Z8:
1820 		case GX_TF_I8:
1821 		case GX_CTF_A8:
1822 		case GX_CTF_R8:
1823 		case GX_CTF_G8:
1824 		case GX_CTF_B8:
1825 		case GX_CTF_Z8M:
1826 		case GX_CTF_Z8L:
1827 			xshift = 3;
1828 			yshift = 2;
1829 			break;
1830 		case GX_TF_IA8:
1831 		case GX_CTF_RA8:
1832 		case GX_CTF_RG8:
1833 		case GX_CTF_GB8:
1834 		case GX_TF_Z16:
1835 		case GX_TF_Z24X8:
1836 		case GX_CTF_Z16L:
1837 		case GX_TF_RGB565:
1838 		case GX_TF_RGB5A3:
1839 		case GX_TF_RGBA8:
1840 			xshift = 2;
1841 			yshift = 2;
1842 			break;
1843 		default:
1844 			xshift = 0;
1845 			yshift = 0;
1846 			break;
1847 	}
1848 
1849 	if(!(wd&0xffff)) wd = 1;
1850 	if(!(ht&0xffff)) ht = 1;
1851 
1852 	wd &= 0xffff;
1853 	tile = (wd+((1<<xshift)-1))>>xshift;
1854 	*xtiles = tile;
1855 
1856 	ht &= 0xffff;
1857 	tile = (ht+((1<<yshift)-1))>>yshift;
1858 	*ytiles = tile;
1859 
1860 	*zplanes = 1;
1861 	if(fmt==GX_TF_RGBA8 || fmt==GX_TF_Z24X8) *zplanes = 2;
1862 }
1863 
GX_SetCopyClear(GXColor color,u32 zvalue)1864 void GX_SetCopyClear(GXColor color,u32 zvalue)
1865 {
1866 	u32 val;
1867 
1868 	val = (_SHIFTL(color.a,8,8))|(color.r&0xff);
1869 	GX_LOAD_BP_REG(0x4f000000|val);
1870 
1871 	val = (_SHIFTL(color.g,8,8))|(color.b&0xff);
1872 	GX_LOAD_BP_REG(0x50000000|val);
1873 
1874 	val = zvalue&0x00ffffff;
1875 	GX_LOAD_BP_REG(0x51000000|val);
1876 }
1877 
GX_SetCopyClamp(u8 clamp)1878 void GX_SetCopyClamp(u8 clamp)
1879 {
1880 	__gx->dispCopyCntrl = (__gx->dispCopyCntrl&~1)|(clamp&1);
1881 	__gx->dispCopyCntrl = (__gx->dispCopyCntrl&~2)|(clamp&2);
1882 }
1883 
GX_SetDispCopyGamma(u8 gamma)1884 void GX_SetDispCopyGamma(u8 gamma)
1885 {
1886 	__gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0x180)|(_SHIFTL(gamma,7,2));
1887 }
1888 
GX_SetCopyFilter(u8 aa,u8 sample_pattern[12][2],u8 vf,u8 vfilter[7])1889 void GX_SetCopyFilter(u8 aa,u8 sample_pattern[12][2],u8 vf,u8 vfilter[7])
1890 {
1891 	u32 reg01=0,reg02=0,reg03=0,reg04=0,reg53=0,reg54=0;
1892 
1893 	if(aa) {
1894 		reg01 = sample_pattern[0][0]&0xf;
1895 		reg01 = (reg01&~0xf0)|(_SHIFTL(sample_pattern[0][1],4,4));
1896 		reg01 = (reg01&~0xf00)|(_SHIFTL(sample_pattern[1][0],8,4));
1897 		reg01 = (reg01&~0xf000)|(_SHIFTL(sample_pattern[1][1],12,4));
1898 		reg01 = (reg01&~0xf0000)|(_SHIFTL(sample_pattern[2][0],16,4));
1899 		reg01 = (reg01&~0xf00000)|(_SHIFTL(sample_pattern[2][1],20,4));
1900 		reg01 = (reg01&~0xff000000)|(_SHIFTL(0x01,24,8));
1901 
1902 		reg02 = sample_pattern[3][0]&0xf;
1903 		reg02 = (reg02&~0xf0)|(_SHIFTL(sample_pattern[3][1],4,4));
1904 		reg02 = (reg02&~0xf00)|(_SHIFTL(sample_pattern[4][0],8,4));
1905 		reg02 = (reg02&~0xf000)|(_SHIFTL(sample_pattern[4][1],12,4));
1906 		reg02 = (reg02&~0xf0000)|(_SHIFTL(sample_pattern[5][0],16,4));
1907 		reg02 = (reg02&~0xf00000)|(_SHIFTL(sample_pattern[5][1],20,4));
1908 		reg02 = (reg02&~0xff000000)|(_SHIFTL(0x02,24,8));
1909 
1910 		reg03 = sample_pattern[6][0]&0xf;
1911 		reg03 = (reg03&~0xf0)|(_SHIFTL(sample_pattern[6][1],4,4));
1912 		reg03 = (reg03&~0xf00)|(_SHIFTL(sample_pattern[7][0],8,4));
1913 		reg03 = (reg03&~0xf000)|(_SHIFTL(sample_pattern[7][1],12,4));
1914 		reg03 = (reg03&~0xf0000)|(_SHIFTL(sample_pattern[8][0],16,4));
1915 		reg03 = (reg03&~0xf00000)|(_SHIFTL(sample_pattern[8][1],20,4));
1916 		reg03 = (reg03&~0xff000000)|(_SHIFTL(0x03,24,8));
1917 
1918 		reg04 = sample_pattern[9][0]&0xf;
1919 		reg04 = (reg04&~0xf0)|(_SHIFTL(sample_pattern[9][1],4,4));
1920 		reg04 = (reg04&~0xf00)|(_SHIFTL(sample_pattern[10][0],8,4));
1921 		reg04 = (reg04&~0xf000)|(_SHIFTL(sample_pattern[10][1],12,4));
1922 		reg04 = (reg04&~0xf0000)|(_SHIFTL(sample_pattern[11][0],16,4));
1923 		reg04 = (reg04&~0xf00000)|(_SHIFTL(sample_pattern[11][1],20,4));
1924 		reg04 = (reg04&~0xff000000)|(_SHIFTL(0x04,24,8));
1925 	} else {
1926 		reg01 = 0x01666666;
1927 		reg02 = 0x02666666;
1928 		reg03 = 0x03666666;
1929 		reg04 = 0x04666666;
1930 	}
1931 	GX_LOAD_BP_REG(reg01);
1932 	GX_LOAD_BP_REG(reg02);
1933 	GX_LOAD_BP_REG(reg03);
1934 	GX_LOAD_BP_REG(reg04);
1935 
1936 	reg53 = 0x53595000;
1937 	reg54 = 0x54000015;
1938 	if(vf) {
1939 		reg53 = 0x53000000|(vfilter[0]&0x3f);
1940 		reg53 = (reg53&~0xfc0)|(_SHIFTL(vfilter[1],6,6));
1941 		reg53 = (reg53&~0x3f000)|(_SHIFTL(vfilter[2],12,6));
1942 		reg53 = (reg53&~0xfc0000)|(_SHIFTL(vfilter[3],18,6));
1943 
1944 		reg54 = 0x54000000|(vfilter[4]&0x3f);
1945 		reg54 = (reg54&~0xfc0)|(_SHIFTL(vfilter[5],6,6));
1946 		reg54 = (reg54&~0x3f000)|(_SHIFTL(vfilter[6],12,6));
1947 	}
1948 	GX_LOAD_BP_REG(reg53);
1949 	GX_LOAD_BP_REG(reg54);
1950 }
1951 
GX_SetDispCopyFrame2Field(u8 mode)1952 void GX_SetDispCopyFrame2Field(u8 mode)
1953 {
1954 	__gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0x3000)|(_SHIFTL(mode,12,2));
1955 }
1956 
GX_SetDispCopyYScale(f32 yscale)1957 u32 GX_SetDispCopyYScale(f32 yscale)
1958 {
1959 	u32 ht,yScale = 0;
1960 
1961 	yScale = ((u32)(256.0f/yscale))&0x1ff;
1962 	GX_LOAD_BP_REG(0x4e000000|yScale);
1963 
1964 	__gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0x400)|(_SHIFTL(((256-yScale)>0),10,1));
1965 	ht = _SHIFTR(__gx->dispCopyWH,12,10)+1;
1966 	return __GX_GetNumXfbLines(ht,yScale);
1967 }
1968 
GX_SetDispCopyDst(u16 wd,u16 ht)1969 void GX_SetDispCopyDst(u16 wd,u16 ht)
1970 {
1971 	__gx->dispCopyDst = (__gx->dispCopyDst&~0x3ff)|(_SHIFTR(wd,4,10));
1972 	__gx->dispCopyDst = (__gx->dispCopyDst&~0xff000000)|(_SHIFTL(0x4d,24,8));
1973 }
1974 
GX_SetDispCopySrc(u16 left,u16 top,u16 wd,u16 ht)1975 void GX_SetDispCopySrc(u16 left,u16 top,u16 wd,u16 ht)
1976 {
1977 	__gx->dispCopyTL = (__gx->dispCopyTL&~0x00ffffff)|XY(left,top);
1978 	__gx->dispCopyTL = (__gx->dispCopyTL&~0xff000000)|(_SHIFTL(0x49,24,8));
1979 	__gx->dispCopyWH = (__gx->dispCopyWH&~0x00ffffff)|XY((wd-1),(ht-1));
1980 	__gx->dispCopyWH = (__gx->dispCopyWH&~0xff000000)|(_SHIFTL(0x4a,24,8));
1981 }
1982 
GX_CopyDisp(void * dest,u8 clear)1983 void GX_CopyDisp(void *dest,u8 clear)
1984 {
1985 	u8 clflag;
1986 	u32 val;
1987 
1988 	if(clear) {
1989 		val= (__gx->peZMode&~0xf)|0xf;
1990 		GX_LOAD_BP_REG(val);
1991 		val = (__gx->peCMode0&~0x3);
1992 		GX_LOAD_BP_REG(val);
1993 	}
1994 
1995 	clflag = 0;
1996 	if(clear || (__gx->peCntrl&0x7)==0x0003) {
1997 		if(__gx->peCntrl&0x40) {
1998 			clflag = 1;
1999 			val = (__gx->peCntrl&~0x40);
2000 			GX_LOAD_BP_REG(val);
2001 		}
2002 	}
2003 
2004 	GX_LOAD_BP_REG(__gx->dispCopyTL);  // set source top
2005 	GX_LOAD_BP_REG(__gx->dispCopyWH);
2006 
2007 	GX_LOAD_BP_REG(__gx->dispCopyDst);
2008 
2009 	val = 0x4b000000|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(dest),5,24));
2010 	GX_LOAD_BP_REG(val);
2011 
2012 	__gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0x800)|(_SHIFTL(clear,11,1));
2013 	__gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0x4000)|0x4000;
2014 	__gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0xff000000)|(_SHIFTL(0x52,24,8));
2015 
2016 	GX_LOAD_BP_REG(__gx->dispCopyCntrl);
2017 
2018 	if(clear) {
2019 		GX_LOAD_BP_REG(__gx->peZMode);
2020 		GX_LOAD_BP_REG(__gx->peCMode0);
2021 	}
2022 	if(clflag) GX_LOAD_BP_REG(__gx->peCntrl);
2023 }
2024 
GX_CopyTex(void * dest,u8 clear)2025 void GX_CopyTex(void *dest,u8 clear)
2026 {
2027 	u8 clflag;
2028 	u32 val;
2029 
2030 	if(clear) {
2031 		val = (__gx->peZMode&~0xf)|0xf;
2032 		GX_LOAD_BP_REG(val);
2033 		val = (__gx->peCMode0&~0x3);
2034 		GX_LOAD_BP_REG(val);
2035 	}
2036 
2037 	clflag = 0;
2038 	val = __gx->peCntrl;
2039 	if(__gx->texCopyZTex && (val&0x7)!=0x0003) {
2040 		clflag = 1;
2041 		val = (val&~0x7)|0x0003;
2042 	}
2043 	if(clear || (val&0x7)==0x0003) {
2044 		if(val&0x40) {
2045 			clflag = 1;
2046 			val = (val&~0x40);
2047 		}
2048 	}
2049 	if(clflag) GX_LOAD_BP_REG(val);
2050 
2051 	val = 0x4b000000|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(dest),5,24));
2052 
2053 	GX_LOAD_BP_REG(__gx->texCopyTL);
2054 	GX_LOAD_BP_REG(__gx->texCopyWH);
2055 	GX_LOAD_BP_REG(__gx->texCopyDst);
2056 	GX_LOAD_BP_REG(val);
2057 
2058 	__gx->texCopyCntrl = (__gx->texCopyCntrl&~0x800)|(_SHIFTL(clear,11,1));
2059 	__gx->texCopyCntrl = (__gx->texCopyCntrl&~0x4000);
2060 	__gx->texCopyCntrl = (__gx->texCopyCntrl&~0xff000000)|(_SHIFTL(0x52,24,8));
2061 	GX_LOAD_BP_REG(__gx->texCopyCntrl);
2062 
2063 	if(clear) {
2064 		GX_LOAD_BP_REG(__gx->peZMode);
2065 		GX_LOAD_BP_REG(__gx->peCMode0);
2066 	}
2067 	if(clflag) GX_LOAD_BP_REG(__gx->peCntrl);
2068 }
2069 
GX_SetTexCopySrc(u16 left,u16 top,u16 wd,u16 ht)2070 void GX_SetTexCopySrc(u16 left,u16 top,u16 wd,u16 ht)
2071 {
2072 	__gx->texCopyTL = (__gx->texCopyTL&~0x00ffffff)|XY(left,top);
2073 	__gx->texCopyTL = (__gx->texCopyTL&~0xff000000)|(_SHIFTL(0x49,24,8));
2074 	__gx->texCopyWH = (__gx->texCopyWH&~0x00ffffff)|XY((wd-1),(ht-1));
2075 	__gx->texCopyWH = (__gx->texCopyWH&~0xff000000)|(_SHIFTL(0x4a,24,8));
2076 }
2077 
GX_SetTexCopyDst(u16 wd,u16 ht,u32 fmt,u8 mipmap)2078 void GX_SetTexCopyDst(u16 wd,u16 ht,u32 fmt,u8 mipmap)
2079 {
2080 	u8 lfmt = fmt&0xf;
2081 	u32 xtiles,ytiles,zplanes;
2082 
2083 	__GetImageTileCount(fmt,wd,ht,&xtiles,&ytiles,&zplanes);
2084 	__gx->texCopyDst = (__gx->texCopyDst&~0x3ff)|((xtiles*zplanes)&0x3ff);
2085 
2086 	if(fmt==GX_TF_Z16) lfmt = 11;
2087 	if(fmt==GX_CTF_YUVA8 || (fmt>=GX_TF_I4 && fmt<GX_TF_RGB565)) __gx->texCopyCntrl = (__gx->texCopyCntrl&~0x18000)|0x18000;
2088 	else __gx->texCopyCntrl = (__gx->texCopyCntrl&~0x18000)|0x10000;
2089 
2090 	__gx->texCopyCntrl = (__gx->texCopyCntrl&~0x8)|(lfmt&0x8);
2091 	__gx->texCopyCntrl = (__gx->texCopyCntrl&~0x200)|(_SHIFTL(mipmap,9,1));
2092 	__gx->texCopyCntrl = (__gx->texCopyCntrl&~0x70)|(_SHIFTL(lfmt,4,3));
2093 
2094 	__gx->texCopyDst = (__gx->texCopyDst&~0xff000000)|(_SHIFTL(0x4d,24,8));
2095 
2096 	__gx->texCopyZTex = ((fmt&_GX_TF_ZTF)==_GX_TF_ZTF);
2097 }
2098 
GX_ClearBoundingBox()2099 void GX_ClearBoundingBox()
2100 {
2101 	GX_LOAD_BP_REG(0x550003ff);
2102 	GX_LOAD_BP_REG(0x560003ff);
2103 }
2104 
GX_BeginDispList(void * list,u32 size)2105 void GX_BeginDispList(void *list,u32 size)
2106 {
2107 	struct __gxfifo *fifo;
2108 
2109 	if(__gx->dirtyState)
2110 		__GX_SetDirtyState();
2111 
2112 	if(__gx->saveDLctx)
2113 		memcpy(_gx_saved_data,__gxregs,STRUCT_REGDEF_SIZE);
2114 
2115 	fifo = (struct __gxfifo*)&_gx_dl_fifoobj;
2116 	fifo->buf_start = (u32)list;
2117 	fifo->buf_end = (u32)list + size - 4;
2118 	fifo->size = size;
2119 
2120 	fifo->rd_ptr = (u32)list;
2121 	fifo->wt_ptr = (u32)list;
2122 	fifo->rdwt_dst = 0;
2123 
2124 	__gx->gxFifoUnlinked = 1;
2125 
2126 	GX_GetCPUFifo(&_gx_old_cpufifo);
2127 	GX_SetCPUFifo(&_gx_dl_fifoobj);
2128 	__GX_ResetWriteGatherPipe();
2129 }
2130 
GX_EndDispList()2131 u32 GX_EndDispList()
2132 {
2133 	u32 level;
2134 	u8 wrap = 0;
2135 
2136 	GX_GetCPUFifo(&_gx_dl_fifoobj);
2137 	GX_SetCPUFifo(&_gx_old_cpufifo);
2138 
2139 	if(__gx->saveDLctx) {
2140 		_CPU_ISR_Disable(level);
2141 		memcpy(__gxregs,_gx_saved_data,STRUCT_REGDEF_SIZE);
2142 		_CPU_ISR_Restore(level);
2143 	}
2144 
2145 	__gx->gxFifoUnlinked = 0;
2146 
2147 	wrap = GX_GetFifoWrap(&_gx_dl_fifoobj);
2148 	if(wrap) return 0;
2149 
2150 	return GX_GetFifoCount(&_gx_dl_fifoobj);
2151 }
2152 
GX_CallDispList(void * list,u32 nbytes)2153 void GX_CallDispList(void *list,u32 nbytes)
2154 {
2155 	if(__gx->dirtyState)
2156 		__GX_SetDirtyState();
2157 
2158 	if(!__gx->vcdClear)
2159 		__GX_SendFlushPrim();
2160 
2161 	wgPipe->U8 = 0x40;		//call displaylist
2162 	wgPipe->U32 = MEM_VIRTUAL_TO_PHYSICAL(list);
2163 	wgPipe->U32 = nbytes;
2164 }
2165 
GX_SetChanCtrl(s32 channel,u8 enable,u8 ambsrc,u8 matsrc,u8 litmask,u8 diff_fn,u8 attn_fn)2166 void GX_SetChanCtrl(s32 channel,u8 enable,u8 ambsrc,u8 matsrc,u8 litmask,u8 diff_fn,u8 attn_fn)
2167 {
2168 	u32 reg,difffn = (attn_fn==GX_AF_SPEC)?GX_DF_NONE:diff_fn;
2169 	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>0),10,1))|(_SHIFTL((_SHIFTR(litmask,4,4)),11,4));
2170 
2171 	reg = (channel&0x03);
2172 	__gx->chnCntrl[reg] = val;
2173 	__gx->dirtyState |= (0x1000<<reg);
2174 
2175 	if(channel==GX_COLOR0A0) {
2176 		__gx->chnCntrl[2] = val;
2177 		__gx->dirtyState |= 0x5000;
2178 	} else {
2179 		__gx->chnCntrl[3] = val;
2180 		__gx->dirtyState |= 0xa000;
2181 	}
2182 }
2183 
GX_SetChanAmbColor(s32 channel,GXColor color)2184 void GX_SetChanAmbColor(s32 channel,GXColor color)
2185 {
2186 	u32 reg,val = (_SHIFTL(color.r,24,8))|(_SHIFTL(color.g,16,8))|(_SHIFTL(color.b,8,8))|0x00;
2187 	switch(channel) {
2188 		case GX_COLOR0:
2189 			reg = 0;
2190 			val |= (__gx->chnAmbColor[0]&0xff);
2191 			break;
2192 		case GX_COLOR1:
2193 			reg = 1;
2194 			val |= (__gx->chnAmbColor[1]&0xff);
2195 			break;
2196 		case GX_ALPHA0:
2197 			reg = 0;
2198 			val = ((__gx->chnAmbColor[0]&~0xff)|(color.a&0xff));
2199 			break;
2200 		case GX_ALPHA1:
2201 			reg = 1;
2202 			val = ((__gx->chnAmbColor[1]&~0xff)|(color.a&0xff));
2203 			break;
2204 		case GX_COLOR0A0:
2205 			reg = 0;
2206 			val |= (color.a&0xFF);
2207 			break;
2208 		case GX_COLOR1A1:
2209 			reg = 1;
2210 			val |= (color.a&0xFF);
2211 			break;
2212 		default:
2213 			return;
2214 	}
2215 
2216 	__gx->chnAmbColor[reg] = val;
2217 	__gx->dirtyState |= (0x0100<<reg);
2218 }
2219 
GX_SetChanMatColor(s32 channel,GXColor color)2220 void GX_SetChanMatColor(s32 channel,GXColor color)
2221 {
2222 	u32 reg,val = (_SHIFTL(color.r,24,8))|(_SHIFTL(color.g,16,8))|(_SHIFTL(color.b,8,8))|0x00;
2223 	switch(channel) {
2224 		case GX_COLOR0:
2225 			reg = 0;
2226 			val |= (__gx->chnMatColor[0]&0xff);
2227 			break;
2228 		case GX_COLOR1:
2229 			reg = 1;
2230 			val |= (__gx->chnMatColor[1]&0xff);
2231 			break;
2232 		case GX_ALPHA0:
2233 			reg = 0;
2234 			val = ((__gx->chnMatColor[0]&~0xff)|(color.a&0xff));
2235 			break;
2236 		case GX_ALPHA1:
2237 			reg = 1;
2238 			val = ((__gx->chnMatColor[1]&~0xff)|(color.a&0xff));
2239 			break;
2240 		case GX_COLOR0A0:
2241 			reg = 0;
2242 			val |= (color.a&0xFF);
2243 			break;
2244 		case GX_COLOR1A1:
2245 			reg = 1;
2246 			val |= (color.a&0xFF);
2247 			break;
2248 		default:
2249 			return;
2250 	}
2251 
2252 	__gx->chnMatColor[reg] = val;
2253 	__gx->dirtyState |= (0x0400<<reg);
2254 }
2255 
GX_SetArray(u32 attr,void * ptr,u8 stride)2256 void GX_SetArray(u32 attr,void *ptr,u8 stride)
2257 {
2258 	u32 idx = 0;
2259 
2260 	if(attr==GX_VA_NBT) attr = GX_VA_NRM;
2261 	if(attr>=GX_VA_POS && attr<=GX_LIGHTARRAY) {
2262 		idx = attr-GX_VA_POS;
2263 		GX_LOAD_CP_REG((0xA0+idx),(u32)MEM_VIRTUAL_TO_PHYSICAL(ptr));
2264 		GX_LOAD_CP_REG((0xB0+idx),(u32)stride);
2265 	}
2266 }
2267 
__SETVCDATTR(u8 attr,u8 type)2268 static __inline__ void __SETVCDATTR(u8 attr,u8 type)
2269 {
2270 	switch(attr) {
2271 		case GX_VA_PTNMTXIDX:
2272 			__gx->vcdLo = (__gx->vcdLo&~0x1)|(type&0x1);
2273 			break;
2274 		case GX_VA_TEX0MTXIDX:
2275 			__gx->vcdLo = (__gx->vcdLo&~0x2)|(_SHIFTL(type,1,1));
2276 			break;
2277 		case GX_VA_TEX1MTXIDX:
2278 			__gx->vcdLo = (__gx->vcdLo&~0x4)|(_SHIFTL(type,2,1));
2279 			break;
2280 		case GX_VA_TEX2MTXIDX:
2281 			__gx->vcdLo = (__gx->vcdLo&~0x8)|(_SHIFTL(type,3,1));
2282 			break;
2283 		case GX_VA_TEX3MTXIDX:
2284 			__gx->vcdLo = (__gx->vcdLo&~0x10)|(_SHIFTL(type,4,1));
2285 			break;
2286 		case GX_VA_TEX4MTXIDX:
2287 			__gx->vcdLo = (__gx->vcdLo&~0x20)|(_SHIFTL(type,5,1));
2288 			break;
2289 		case GX_VA_TEX5MTXIDX:
2290 			__gx->vcdLo = (__gx->vcdLo&~0x40)|(_SHIFTL(type,6,1));
2291 			break;
2292 		case GX_VA_TEX6MTXIDX:
2293 			__gx->vcdLo = (__gx->vcdLo&~0x80)|(_SHIFTL(type,7,1));
2294 			break;
2295 		case GX_VA_TEX7MTXIDX:
2296 			__gx->vcdLo = (__gx->vcdLo&~0x100)|(_SHIFTL(type,8,1));
2297 			break;
2298 		case GX_VA_POS:
2299 			__gx->vcdLo = (__gx->vcdLo&~0x600)|(_SHIFTL(type,9,2));
2300 			break;
2301 		case GX_VA_NRM:
2302 			__gx->vcdLo = (__gx->vcdLo&~0x1800)|(_SHIFTL(type,11,2));
2303 			__gx->vcdNrms = 1;
2304 			break;
2305 		case GX_VA_NBT:
2306 			__gx->vcdLo = (__gx->vcdLo&~0x1800)|(_SHIFTL(type,11,2));
2307 			__gx->vcdNrms = 2;
2308 			break;
2309 		case GX_VA_CLR0:
2310 			__gx->vcdLo = (__gx->vcdLo&~0x6000)|(_SHIFTL(type,13,2));
2311 			break;
2312 		case GX_VA_CLR1:
2313 			__gx->vcdLo = (__gx->vcdLo&~0x18000)|(_SHIFTL(type,15,2));
2314 			break;
2315 		case GX_VA_TEX0:
2316 			__gx->vcdHi = (__gx->vcdHi&~0x3)|(type&0x3);
2317 			break;
2318 		case GX_VA_TEX1:
2319 			__gx->vcdHi = (__gx->vcdHi&~0xc)|(_SHIFTL(type,2,2));
2320 			break;
2321 		case GX_VA_TEX2:
2322 			__gx->vcdHi = (__gx->vcdHi&~0x30)|(_SHIFTL(type,4,2));
2323 			break;
2324 		case GX_VA_TEX3:
2325 			__gx->vcdHi = (__gx->vcdHi&~0xc0)|(_SHIFTL(type,6,2));
2326 			break;
2327 		case GX_VA_TEX4:
2328 			__gx->vcdHi = (__gx->vcdHi&~0x300)|(_SHIFTL(type,8,2));
2329 			break;
2330 		case GX_VA_TEX5:
2331 			__gx->vcdHi = (__gx->vcdHi&~0xc00)|(_SHIFTL(type,10,2));
2332 			break;
2333 		case GX_VA_TEX6:
2334 			__gx->vcdHi = (__gx->vcdHi&~0x3000)|(_SHIFTL(type,12,2));
2335 			break;
2336 		case GX_VA_TEX7:
2337 			__gx->vcdHi = (__gx->vcdHi&~0xc000)|(_SHIFTL(type,14,2));
2338 			break;
2339 	}
2340 }
2341 
GX_SetVtxDesc(u8 attr,u8 type)2342 void GX_SetVtxDesc(u8 attr,u8 type)
2343 {
2344 	__SETVCDATTR(attr,type);
2345 	__gx->dirtyState |= 0x0008;
2346 }
2347 
GX_SetVtxDescv(GXVtxDesc * attr_list)2348 void GX_SetVtxDescv(GXVtxDesc *attr_list)
2349 {
2350 	u32 i;
2351 
2352 	if(!attr_list) return;
2353 
2354 	for(i=0;i<GX_MAX_VTXDESC_LISTSIZE;i++){
2355 		if(attr_list[i].attr==GX_VA_NULL) break;
2356 
2357 		__SETVCDATTR(attr_list[i].attr,attr_list[i].type);
2358 	}
2359 	__gx->dirtyState |= 0x0008;
2360 }
2361 
GX_GetVtxDescv(GXVtxDesc * attr_list)2362 void GX_GetVtxDescv(GXVtxDesc *attr_list)
2363 {
2364 	u32 count;
2365 
2366 	// Clear everything first
2367 	for(count=0;count<GX_MAX_VTXDESC_LISTSIZE;count++) {
2368 		attr_list[count].attr = GX_VA_NULL;
2369 		attr_list[count].type = 0;
2370 	}
2371 
2372 	count = 0;
2373 	if(__gx->vcdLo&0x1) {
2374 		attr_list[count].attr = GX_VA_PTNMTXIDX;
2375 		attr_list[count].type = __gx->vcdLo&0x1;
2376 		count++;
2377 	}
2378 
2379 	if(__gx->vcdLo&0x2) {
2380 		attr_list[count].attr = GX_VA_TEX0MTXIDX;
2381 		attr_list[count].type = _SHIFTR(__gx->vcdLo&0x2,1,1);
2382 		count++;
2383 	}
2384 
2385 	if(__gx->vcdLo&0x4) {
2386 		attr_list[count].attr = GX_VA_TEX1MTXIDX;
2387 		attr_list[count].type = _SHIFTR(__gx->vcdLo&0x4,2,1);
2388 		count++;
2389 	}
2390 
2391 	if(__gx->vcdLo&0x8) {
2392 		attr_list[count].attr = GX_VA_TEX2MTXIDX;
2393 		attr_list[count].type = _SHIFTR(__gx->vcdLo&0x8,3,1);
2394 		count++;
2395 	}
2396 
2397 	if(__gx->vcdLo&0x10) {
2398 		attr_list[count].attr = GX_VA_TEX3MTXIDX;
2399 		attr_list[count].type = _SHIFTR(__gx->vcdLo&0x10,4,1);
2400 		count++;
2401 	}
2402 
2403 	if(__gx->vcdLo&0x20) {
2404 		attr_list[count].attr = GX_VA_TEX4MTXIDX;
2405 		attr_list[count].type = _SHIFTR(__gx->vcdLo&0x20,5,1);
2406 		count++;
2407 	}
2408 
2409 	if(__gx->vcdLo&0x40) {
2410 		attr_list[count].attr = GX_VA_TEX5MTXIDX;
2411 		attr_list[count].type = _SHIFTR(__gx->vcdLo&0x40,6,1);
2412 		count++;
2413 	}
2414 
2415 	if(__gx->vcdLo&0x80) {
2416 		attr_list[count].attr = GX_VA_TEX6MTXIDX;
2417 		attr_list[count].type = _SHIFTR(__gx->vcdLo&0x80,7,1);
2418 		count++;
2419 	}
2420 
2421 	if(__gx->vcdLo&0x100) {
2422 		attr_list[count].attr = GX_VA_TEX7MTXIDX;
2423 		attr_list[count].type = _SHIFTR(__gx->vcdLo&0x100,8,1);
2424 		count++;
2425 	}
2426 
2427 	if(__gx->vcdLo&0x600) {
2428 		attr_list[count].attr = GX_VA_POS;
2429 		attr_list[count].type = _SHIFTR(__gx->vcdLo&0x600,9,2);
2430 		count++;
2431 	}
2432 
2433 	if(__gx->vcdLo&0x1800) {
2434 		if(__gx->vcdNrms==1) {
2435 			attr_list[count].attr = GX_VA_NRM;
2436 			attr_list[count].type = _SHIFTR(__gx->vcdLo&0x1800,11,2);
2437 			count++;
2438 		} else if(__gx->vcdNrms==2){
2439 			attr_list[count].attr = GX_VA_NBT;
2440 			attr_list[count].type = _SHIFTR(__gx->vcdLo&0x1800,11,2);
2441 			count++;
2442 		}
2443 	}
2444 
2445 	if(__gx->vcdLo&0x6000) {
2446 		attr_list[count].attr = GX_VA_CLR0;
2447 		attr_list[count].type = _SHIFTR(__gx->vcdLo&0x6000,13,2);
2448 		count++;
2449 	}
2450 
2451 	if(__gx->vcdLo&0x18000) {
2452 		attr_list[count].attr = GX_VA_CLR1;
2453 		attr_list[count].type = _SHIFTR(__gx->vcdLo&0x18000,15,2);
2454 		count++;
2455 	}
2456 
2457 	if(__gx->vcdHi&0x3) {
2458 		attr_list[count].attr = GX_VA_TEX0;
2459 		attr_list[count].type = __gx->vcdHi&0x3;
2460 		count++;
2461 	}
2462 
2463 	if(__gx->vcdHi&0xc) {
2464 		attr_list[count].attr = GX_VA_TEX1;
2465 		attr_list[count].type = _SHIFTR(__gx->vcdHi&0xc,2,2);
2466 		count++;
2467 	}
2468 
2469 	if(__gx->vcdHi&0x30) {
2470 		attr_list[count].attr = GX_VA_TEX2;
2471 		attr_list[count].type = _SHIFTR(__gx->vcdHi&0x30,4,2);
2472 		count++;
2473 	}
2474 
2475 	if(__gx->vcdHi&0xc0) {
2476 		attr_list[count].attr = GX_VA_TEX3;
2477 		attr_list[count].type = _SHIFTR(__gx->vcdHi&0xc0,6,2);
2478 		count++;
2479 	}
2480 
2481 	if(__gx->vcdHi&0x300) {
2482 		attr_list[count].attr = GX_VA_TEX4;
2483 		attr_list[count].type = _SHIFTR(__gx->vcdHi&0x300,8,2);
2484 		count++;
2485 	}
2486 
2487 	if(__gx->vcdHi&0xc00) {
2488 		attr_list[count].attr = GX_VA_TEX5;
2489 		attr_list[count].type = _SHIFTR(__gx->vcdHi&0xc00,10,2);
2490 		count++;
2491 	}
2492 
2493 	if(__gx->vcdHi&0x3000) {
2494 		attr_list[count].attr = GX_VA_TEX6;
2495 		attr_list[count].type = _SHIFTR(__gx->vcdHi&0x3000,12,2);
2496 		count++;
2497 	}
2498 
2499 	if(__gx->vcdHi&0xc000) {
2500 		attr_list[count].attr = GX_VA_TEX7;
2501 		attr_list[count].type = _SHIFTR(__gx->vcdHi&0xc000,14,2);
2502 		count++;
2503 	}
2504 }
2505 
__SETVCDFMT(u8 vtxfmt,u32 vtxattr,u32 comptype,u32 compsize,u32 frac)2506 static __inline__ void __SETVCDFMT(u8 vtxfmt,u32 vtxattr,u32 comptype,u32 compsize,u32 frac)
2507 {
2508 	u8 vat = (vtxfmt&7);
2509 
2510 	if(vtxattr==GX_VA_POS && (comptype==GX_POS_XY || comptype==GX_POS_XYZ)
2511 		&& (compsize>=GX_U8 && compsize<=GX_F32)) {
2512 		__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1)|(comptype&1);
2513 		__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0xe)|(_SHIFTL(compsize,1,3));
2514 		__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1f0)|(_SHIFTL(frac,4,5));
2515 		if(frac)
2516 			__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2517 	} else if(vtxattr==GX_VA_NRM && comptype==GX_NRM_XYZ
2518 		&& (compsize==GX_S8 || compsize==GX_S16 || compsize==GX_F32)) {
2519 		__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x200);
2520 		__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1C00)|(_SHIFTL(compsize,10,3));
2521 		__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x80000000);
2522 	} else if(vtxattr==GX_VA_NBT && (comptype==GX_NRM_NBT || comptype==GX_NRM_NBT3)
2523 		&& (compsize==GX_S8 || compsize==GX_S16 || compsize==GX_F32)) {
2524 		__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x200)|0x200;
2525 		__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1C00)|(_SHIFTL(compsize,10,3));
2526 		if(comptype==GX_NRM_NBT3)
2527 			__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x80000000)|0x80000000;
2528 	} else if(vtxattr==GX_VA_CLR0 && (comptype==GX_CLR_RGB || comptype==GX_CLR_RGBA)
2529 		&& (compsize>=GX_RGB565 && compsize<=GX_RGBA8)) {
2530 		__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x2000)|(_SHIFTL(comptype,13,1));
2531 		__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1C000)|(_SHIFTL(compsize,14,3));
2532 	} else if(vtxattr==GX_VA_CLR1 && (comptype==GX_CLR_RGB || comptype==GX_CLR_RGBA)
2533 		&& (compsize>=GX_RGB565 && compsize<=GX_RGBA8)) {
2534 		__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x20000)|(_SHIFTL(comptype,17,1));
2535 		__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1C0000)|(_SHIFTL(compsize,18,3));
2536 	} else if(vtxattr==GX_VA_TEX0 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2537 		&& (compsize>=GX_U8 && compsize<=GX_F32)) {
2538 		__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x200000)|(_SHIFTL(comptype,21,1));
2539 		__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1C00000)|(_SHIFTL(compsize,22,3));
2540 		__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x3E000000)|(_SHIFTL(frac,25,5));
2541 		if(frac)
2542 			__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2543 	} else if(vtxattr==GX_VA_TEX1 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2544 		&& (compsize>=GX_U8 && compsize<=GX_F32)) {
2545 		__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x1)|(comptype&1);
2546 		__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0xe)|(_SHIFTL(compsize,1,3));
2547 		__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x1F0)|(_SHIFTL(frac,4,5));
2548 		if(frac)
2549 			__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2550 	} else if(vtxattr==GX_VA_TEX2 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2551 		&& (compsize>=GX_U8 && compsize<=GX_F32)) {
2552 		__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x200)|(_SHIFTL(comptype,9,1));
2553 		__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x1C00)|(_SHIFTL(compsize,10,3));
2554 		__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x3E000)|(_SHIFTL(frac,13,5));
2555 		if(frac)
2556 			__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2557 	} else if(vtxattr==GX_VA_TEX3 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2558 		&& (compsize>=GX_U8 && compsize<=GX_F32)) {
2559 		__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x40000)|(_SHIFTL(comptype,18,1));
2560 		__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x380000)|(_SHIFTL(compsize,19,3));
2561 		__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x7C00000)|(_SHIFTL(frac,22,5));
2562 		if(frac)
2563 			__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2564 	} else if(vtxattr==GX_VA_TEX4 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2565 		&& (compsize>=GX_U8 && compsize<=GX_F32)) {
2566 		__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x8000000)|(_SHIFTL(comptype,27,1));
2567 		__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x70000000)|(_SHIFTL(compsize,28,3));
2568 		__gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x1f)|(frac&0x1f);
2569 		if(frac)
2570 			__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2571 	} else if(vtxattr==GX_VA_TEX5 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2572 		&& (compsize>=GX_U8 && compsize<=GX_F32)) {
2573 		__gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x20)|(_SHIFTL(comptype,5,1));
2574 		__gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x1C0)|(_SHIFTL(compsize,6,3));
2575 		__gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x3E00)|(_SHIFTL(frac,9,5));
2576 		if(frac)
2577 			__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2578 	} else if(vtxattr==GX_VA_TEX6 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2579 		&& (compsize>=GX_U8 && compsize<=GX_F32)) {
2580 		__gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x4000)|(_SHIFTL(comptype,14,1));
2581 		__gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x38000)|(_SHIFTL(compsize,15,3));
2582 		__gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x7C0000)|(_SHIFTL(frac,18,5));
2583 		if(frac)
2584 			__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2585 	} else if(vtxattr==GX_VA_TEX7 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
2586 		&& (compsize>=GX_U8 && compsize<=GX_F32)) {
2587 		__gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x800000)|(_SHIFTL(comptype,23,1));
2588 		__gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x7000000)|(_SHIFTL(compsize,24,3));
2589 		__gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0xF8000000)|(_SHIFTL(frac,27,5));
2590 		if(frac)
2591 			__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
2592 	}
2593 }
2594 
GX_SetVtxAttrFmt(u8 vtxfmt,u32 vtxattr,u32 comptype,u32 compsize,u32 frac)2595 void GX_SetVtxAttrFmt(u8 vtxfmt,u32 vtxattr,u32 comptype,u32 compsize,u32 frac)
2596 {
2597 	__SETVCDFMT(vtxfmt,vtxattr,comptype,compsize,frac);
2598 	__gx->VATTable |= (1<<vtxfmt);
2599 	__gx->dirtyState |= 0x0010;
2600 }
2601 
GX_SetVtxAttrFmtv(u8 vtxfmt,GXVtxAttrFmt * attr_list)2602 void GX_SetVtxAttrFmtv(u8 vtxfmt,GXVtxAttrFmt *attr_list)
2603 {
2604 	u32 i;
2605 
2606 	for(i=0;i<GX_MAX_VTXATTRFMT_LISTSIZE;i++) {
2607 		if(attr_list[i].vtxattr==GX_VA_NULL) break;
2608 
2609 		__SETVCDFMT(vtxfmt,attr_list[i].vtxattr,attr_list[i].comptype,attr_list[i].compsize,attr_list[i].frac);
2610 	}
2611 	__gx->VATTable |= (1<<vtxfmt);
2612 	__gx->dirtyState |= 0x0010;
2613 }
2614 
GX_Begin(u8 primitve,u8 vtxfmt,u16 vtxcnt)2615 void GX_Begin(u8 primitve,u8 vtxfmt,u16 vtxcnt)
2616 {
2617 	u8 reg = primitve|(vtxfmt&7);
2618 
2619 	if(__gx->dirtyState)
2620 		__GX_SetDirtyState();
2621 
2622 	wgPipe->U8 = reg;
2623 	wgPipe->U16 = vtxcnt;
2624 }
2625 
GX_SetTexCoordGen(u16 texcoord,u32 tgen_typ,u32 tgen_src,u32 mtxsrc)2626 void GX_SetTexCoordGen(u16 texcoord,u32 tgen_typ,u32 tgen_src,u32 mtxsrc)
2627 {
2628 		GX_SetTexCoordGen2(texcoord,tgen_typ,tgen_src,mtxsrc,GX_FALSE,GX_DTTIDENTITY);
2629 }
2630 
GX_SetTexCoordGen2(u16 texcoord,u32 tgen_typ,u32 tgen_src,u32 mtxsrc,u32 normalize,u32 postmtx)2631 void GX_SetTexCoordGen2(u16 texcoord,u32 tgen_typ,u32 tgen_src,u32 mtxsrc,u32 normalize,u32 postmtx)
2632 {
2633 	u32 txc;
2634 	u32 texcoords;
2635 	u8 vtxrow,stq;
2636 
2637 	if(texcoord>=GX_MAXCOORD) return;
2638 
2639 	stq = 0;
2640 	switch(tgen_src) {
2641 		case GX_TG_POS:
2642 			vtxrow = 0;
2643 			stq = 1;
2644 			break;
2645 		case GX_TG_NRM:
2646 			vtxrow = 1;
2647 			stq = 1;
2648 			break;
2649 		case GX_TG_BINRM:
2650 			vtxrow = 3;
2651 			stq = 1;
2652 			break;
2653 		case GX_TG_TANGENT:
2654 			vtxrow = 4;
2655 			stq = 1;
2656 			break;
2657 		case GX_TG_COLOR0:
2658 			vtxrow = 2;
2659 			break;
2660 		case GX_TG_COLOR1:
2661 			vtxrow = 2;
2662 			break;
2663 		case GX_TG_TEX0:
2664 			vtxrow = 5;
2665 			break;
2666 		case GX_TG_TEX1:
2667 			vtxrow = 6;
2668 			break;
2669 		case GX_TG_TEX2:
2670 			vtxrow = 7;
2671 			break;
2672 		case GX_TG_TEX3:
2673 			vtxrow = 8;
2674 			break;
2675 		case GX_TG_TEX4:
2676 			vtxrow = 9;
2677 			break;
2678 		case GX_TG_TEX5:
2679 			vtxrow = 10;
2680 			break;
2681 		case GX_TG_TEX6:
2682 			vtxrow = 11;
2683 			break;
2684 		case GX_TG_TEX7:
2685 			vtxrow = 12;
2686 			break;
2687 		default:
2688 			vtxrow = 5;
2689 			break;
2690 	}
2691 
2692 	texcoords = 0;
2693 	txc = (texcoord&7);
2694 	if((tgen_typ==GX_TG_MTX3x4 || tgen_typ==GX_TG_MTX2x4))
2695 	{
2696 		if(tgen_typ==GX_TG_MTX3x4) texcoords = 0x02;
2697 
2698 		texcoords |= (_SHIFTL(stq,2,1));
2699 		texcoords |= (_SHIFTL(vtxrow,7,5));
2700 	} else if((tgen_typ>=GX_TG_BUMP0 && tgen_typ<=GX_TG_BUMP7))
2701 	{
2702 		tgen_src -= GX_TG_TEXCOORD0;
2703 		tgen_typ -= GX_TG_BUMP0;
2704 
2705 		texcoords = 0x10;
2706 		texcoords |= (_SHIFTL(stq,2,1));
2707 		texcoords |= (_SHIFTL(vtxrow,7,5));
2708 		texcoords |= (_SHIFTL(tgen_src,12,3));
2709 		texcoords |= (_SHIFTL(tgen_typ,15,3));
2710 	} else if(tgen_typ==GX_TG_SRTG) {
2711 		if(tgen_src==GX_TG_COLOR0) texcoords = 0x20;
2712 		else if(tgen_src==GX_TG_COLOR1) texcoords = 0x30;
2713 		texcoords |= (_SHIFTL(stq,2,1));
2714 		texcoords |= (_SHIFTL(2,7,5));
2715 	}
2716 
2717 	postmtx -= GX_DTTMTX0;
2718 	__gx->texCoordGen[txc] = texcoords;
2719 	__gx->texCoordGen2[txc] = ((_SHIFTL(normalize,8,1))|(postmtx&0x3f));
2720 
2721 	switch(texcoord) {
2722 		case GX_TEXCOORD0:
2723 			__gx->mtxIdxLo = (__gx->mtxIdxLo&~0xfc0)|(_SHIFTL(mtxsrc,6,6));
2724 			break;
2725 		case GX_TEXCOORD1:
2726 			__gx->mtxIdxLo = (__gx->mtxIdxLo&~0x3f000)|(_SHIFTL(mtxsrc,12,6));
2727 			break;
2728 		case GX_TEXCOORD2:
2729 			__gx->mtxIdxLo = (__gx->mtxIdxLo&~0xfc0000)|(_SHIFTL(mtxsrc,18,6));
2730 			break;
2731 		case GX_TEXCOORD3:
2732 			__gx->mtxIdxLo = (__gx->mtxIdxLo&~0x3f000000)|(_SHIFTL(mtxsrc,24,6));
2733 			break;
2734 		case GX_TEXCOORD4:
2735 			__gx->mtxIdxHi = (__gx->mtxIdxHi&~0x3f)|(mtxsrc&0x3f);
2736 			break;
2737 		case GX_TEXCOORD5:
2738 			__gx->mtxIdxHi = (__gx->mtxIdxHi&~0xfc0)|(_SHIFTL(mtxsrc,6,6));
2739 			break;
2740 		case GX_TEXCOORD6:
2741 			__gx->mtxIdxHi = (__gx->mtxIdxHi&~0x3f000)|(_SHIFTL(mtxsrc,12,6));
2742 			break;
2743 		case GX_TEXCOORD7:
2744 			__gx->mtxIdxHi = (__gx->mtxIdxHi&~0xfc0000)|(_SHIFTL(mtxsrc,18,6));
2745 			break;
2746 	}
2747 	__gx->dirtyState |= (0x04000000|(0x00010000<<texcoord));
2748 }
2749 
GX_SetZTexture(u8 op,u8 fmt,u32 bias)2750 void GX_SetZTexture(u8 op,u8 fmt,u32 bias)
2751 {
2752 	u32 val = 0;
2753 
2754 	if(fmt==GX_TF_Z8) fmt = 0;
2755 	else if(fmt==GX_TF_Z16) fmt = 1;
2756 	else fmt = 2;
2757 
2758 	val = (u32)(_SHIFTL(op,2,2))|(fmt&3);
2759 	GX_LOAD_BP_REG(0xF4000000|(bias&0x00FFFFFF));
2760 	GX_LOAD_BP_REG(0xF5000000|(val&0x00FFFFFF));
2761 }
2762 
WriteMtxPS4x3(register Mtx mt,register void * wgpipe)2763 static inline void WriteMtxPS4x3(register Mtx mt,register void *wgpipe)
2764 {
2765 	register f32 tmp0,tmp1,tmp2,tmp3,tmp4,tmp5;
2766 	__asm__ __volatile__ (
2767 		 "psq_l %0,0(%6),0,0\n\
2768 		  psq_l %1,8(%6),0,0\n\
2769 		  psq_l %2,16(%6),0,0\n\
2770 		  psq_l %3,24(%6),0,0\n\
2771 		  psq_l %4,32(%6),0,0\n\
2772 		  psq_l %5,40(%6),0,0\n\
2773 		  psq_st %0,0(%7),0,0\n\
2774 		  psq_st %1,0(%7),0,0\n\
2775 		  psq_st %2,0(%7),0,0\n\
2776 		  psq_st %3,0(%7),0,0\n\
2777 		  psq_st %4,0(%7),0,0\n\
2778 		  psq_st %5,0(%7),0,0"
2779 		  : "=&f"(tmp0),"=&f"(tmp1),"=&f"(tmp2),"=&f"(tmp3),"=&f"(tmp4),"=&f"(tmp5)
2780 		  : "b"(mt), "b"(wgpipe)
2781 		  : "memory"
2782 	);
2783 }
2784 
WriteMtxPS3x3from4x3(register Mtx mt,register void * wgpipe)2785 static inline void WriteMtxPS3x3from4x3(register Mtx mt,register void *wgpipe)
2786 {
2787 	register f32 tmp0,tmp1,tmp2,tmp3,tmp4,tmp5;
2788 	__asm__ __volatile__
2789 		("psq_l %0,0(%6),0,0\n\
2790 		  lfs	%1,8(%6)\n\
2791 		  psq_l %2,16(%6),0,0\n\
2792 		  lfs	%3,24(%6)\n\
2793 		  psq_l %4,32(%6),0,0\n\
2794 		  lfs	%5,40(%6)\n\
2795 		  psq_st %0,0(%7),0,0\n\
2796 		  stfs	 %1,0(%7)\n\
2797 		  psq_st %2,0(%7),0,0\n\
2798 		  stfs	 %3,0(%7)\n\
2799 		  psq_st %4,0(%7),0,0\n\
2800 		  stfs	 %5,0(%7)"
2801 		  : "=&f"(tmp0),"=&f"(tmp1),"=&f"(tmp2),"=&f"(tmp3),"=&f"(tmp4),"=&f"(tmp5)
2802 		  : "b"(mt), "b"(wgpipe)
2803 		  : "memory"
2804 	);
2805 }
2806 
WriteMtxPS3x3(register Mtx33 mt,register void * wgpipe)2807 static inline void WriteMtxPS3x3(register Mtx33 mt,register void *wgpipe)
2808 {
2809 	register f32 tmp0,tmp1,tmp2,tmp3,tmp4;
2810 	__asm__ __volatile__
2811 		("psq_l %0,0(%5),0,0\n\
2812 		  psq_l %1,8(%5),0,0\n\
2813 		  psq_l %2,16(%5),0,0\n\
2814 		  psq_l %3,24(%5),0,0\n\
2815 		  lfs	%4,32(%5)\n\
2816 		  psq_st %0,0(%6),0,0\n\
2817 		  psq_st %1,0(%6),0,0\n\
2818 		  psq_st %2,0(%6),0,0\n\
2819 		  psq_st %3,0(%6),0,0\n\
2820 		  stfs	 %4,0(%6)"
2821 		  : "=&f"(tmp0),"=&f"(tmp1),"=&f"(tmp2),"=&f"(tmp3),"=&f"(tmp4)
2822 		  : "b"(mt), "b"(wgpipe)
2823 		  : "memory"
2824 	);
2825 }
2826 
WriteMtxPS4x2(register Mtx mt,register void * wgpipe)2827 static inline void WriteMtxPS4x2(register Mtx mt,register void *wgpipe)
2828 {
2829 	register f32 tmp0,tmp1,tmp2,tmp3;
2830 	__asm__ __volatile__
2831 		("psq_l %0,0(%4),0,0\n\
2832 		  psq_l %1,8(%4),0,0\n\
2833 		  psq_l %2,16(%4),0,0\n\
2834 		  psq_l %3,24(%4),0,0\n\
2835 		  psq_st %0,0(%5),0,0\n\
2836 		  psq_st %1,0(%5),0,0\n\
2837 		  psq_st %2,0(%5),0,0\n\
2838 		  psq_st %3,0(%5),0,0"
2839 		  : "=&f"(tmp0),"=&f"(tmp1),"=&f"(tmp2),"=&f"(tmp3)
2840 		  : "b"(mt), "b"(wgpipe)
2841 		  : "memory"
2842 	);
2843 }
2844 
GX_LoadPosMtxImm(Mtx mt,u32 pnidx)2845 void GX_LoadPosMtxImm(Mtx mt,u32 pnidx)
2846 {
2847 	GX_LOAD_XF_REGS((0x0000|(_SHIFTL(pnidx,2,8))),12);
2848 	WriteMtxPS4x3(mt,(void*)wgPipe);
2849 }
2850 
GX_LoadPosMtxIdx(u16 mtxidx,u32 pnidx)2851 void GX_LoadPosMtxIdx(u16 mtxidx,u32 pnidx)
2852 {
2853 	wgPipe->U8 = 0x20;
2854 	wgPipe->U32 = ((_SHIFTL(mtxidx,16,16))|0xb000|(_SHIFTL(pnidx,2,8)));
2855 }
2856 
GX_LoadNrmMtxImm(Mtx mt,u32 pnidx)2857 void GX_LoadNrmMtxImm(Mtx mt,u32 pnidx)
2858 {
2859 	GX_LOAD_XF_REGS((0x0400|(pnidx*3)),9);
2860 	WriteMtxPS3x3from4x3(mt,(void*)wgPipe);
2861 }
2862 
GX_LoadNrmMtxImm3x3(Mtx33 mt,u32 pnidx)2863 void GX_LoadNrmMtxImm3x3(Mtx33 mt,u32 pnidx)
2864 {
2865 	GX_LOAD_XF_REGS((0x0400|(pnidx*3)),9);
2866 	WriteMtxPS3x3(mt,(void*)wgPipe);
2867 }
2868 
GX_LoadNrmMtxIdx3x3(u16 mtxidx,u32 pnidx)2869 void GX_LoadNrmMtxIdx3x3(u16 mtxidx,u32 pnidx)
2870 {
2871 	wgPipe->U8 = 0x28;
2872 	wgPipe->U32 = ((_SHIFTL(mtxidx,16,16))|0x8000|(0x0400|(pnidx*3)));
2873 }
2874 
GX_LoadTexMtxImm(Mtx mt,u32 texidx,u8 type)2875 void GX_LoadTexMtxImm(Mtx mt,u32 texidx,u8 type)
2876 {
2877 	u32 addr = 0;
2878 	u32 rows = (type==GX_MTX2x4)?2:3;
2879 
2880 	if(texidx<GX_DTTMTX0) addr = (_SHIFTL(texidx,2,8));
2881 	else {
2882 		texidx -= GX_DTTMTX0;
2883 		addr = 0x0500 + (_SHIFTL(texidx,2,8));
2884 	}
2885 
2886 	GX_LOAD_XF_REGS(addr,(rows*4));
2887 	if(type==GX_MTX2x4)
2888 		WriteMtxPS4x2(mt,(void*)wgPipe);
2889 	else
2890 		WriteMtxPS4x3(mt,(void*)wgPipe);
2891 }
2892 
GX_LoadTexMtxIdx(u16 mtxidx,u32 texidx,u8 type)2893 void GX_LoadTexMtxIdx(u16 mtxidx,u32 texidx,u8 type)
2894 {
2895 	u32 addr,size = (type==GX_MTX2x4)?7:11;
2896 
2897 	if(texidx<GX_DTTMTX0) addr = 0x0000|(_SHIFTL(texidx,2,8));
2898 	else addr = 0x0500|(_SHIFTL((texidx-GX_DTTMTX0),2,8));
2899 
2900 	wgPipe->U8 = 0x30;
2901 	wgPipe->U32 = ((_SHIFTL(mtxidx,16,16))|(_SHIFTL(size,12,4))|addr);
2902 }
2903 
GX_SetCurrentMtx(u32 mtx)2904 void GX_SetCurrentMtx(u32 mtx)
2905 {
2906 	__gx->mtxIdxLo = (__gx->mtxIdxLo&~0x3f)|(mtx&0x3f);
2907 	__gx->dirtyState |= 0x04000000;
2908 }
2909 
GX_SetNumTexGens(u32 nr)2910 void GX_SetNumTexGens(u32 nr)
2911 {
2912 	__gx->genMode = (__gx->genMode&~0xf)|(nr&0xf);
2913 	__gx->dirtyState |= 0x02000004;
2914 }
2915 
GX_InvVtxCache()2916 void GX_InvVtxCache()
2917 {
2918 	wgPipe->U8 = 0x48; // vertex cache weg
2919 }
2920 
GX_SetZMode(u8 enable,u8 func,u8 update_enable)2921 void GX_SetZMode(u8 enable,u8 func,u8 update_enable)
2922 {
2923 	__gx->peZMode = (__gx->peZMode&~0x1)|(enable&1);
2924 	__gx->peZMode = (__gx->peZMode&~0xe)|(_SHIFTL(func,1,3));
2925 	__gx->peZMode = (__gx->peZMode&~0x10)|(_SHIFTL(update_enable,4,1));
2926 	GX_LOAD_BP_REG(__gx->peZMode);
2927 }
2928 
GX_GetTexObjFmt(GXTexObj * obj)2929 u32 GX_GetTexObjFmt(GXTexObj *obj)
2930 {
2931 	return ((struct __gx_texobj*)obj)->tex_fmt;
2932 }
2933 
GX_GetTexObjMipMap(GXTexObj * obj)2934 u32 GX_GetTexObjMipMap(GXTexObj *obj)
2935 {
2936 	return (((struct __gx_texobj*)obj)->tex_flag&0x01);
2937 }
GX_GetTexObjData(GXTexObj * obj)2938 void* GX_GetTexObjData(GXTexObj *obj)
2939 {
2940 	return (void*)(_SHIFTL(((struct __gx_texobj*)obj)->tex_maddr & 0x00ffffff,5,24));
2941 }
2942 
GX_GetTexObjWrapS(GXTexObj * obj)2943 u8 GX_GetTexObjWrapS(GXTexObj* obj)
2944 {
2945 	return ((struct __gx_texobj*)obj)->tex_filt & 0x03;
2946 }
2947 
GX_GetTexObjWrapT(GXTexObj * obj)2948 u8 GX_GetTexObjWrapT(GXTexObj* obj)
2949 {
2950 	return _SHIFTR(((struct __gx_texobj*)obj)->tex_filt & 0x0c, 2, 2);
2951 }
2952 
GX_GetTexObjHeight(GXTexObj * obj)2953 u16 GX_GetTexObjHeight(GXTexObj* obj)
2954 {
2955 	return _SHIFTR(((struct __gx_texobj*)obj)->tex_size & 0xffc00, 10, 10) + 1;
2956 }
2957 
GX_GetTexObjWidth(GXTexObj * obj)2958 u16 GX_GetTexObjWidth(GXTexObj* obj)
2959 {
2960 	return (((struct __gx_texobj*)obj)->tex_size & 0x3ff) + 1;
2961 }
2962 
GX_GetTexObjAll(GXTexObj * obj,void ** image_ptr,u16 * width,u16 * height,u8 * format,u8 * wrap_s,u8 * wrap_t,u8 * mipmap)2963 void GX_GetTexObjAll(GXTexObj* obj, void** image_ptr, u16* width, u16* height,
2964                      u8* format, u8* wrap_s, u8* wrap_t, u8* mipmap)
2965 {
2966 	struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
2967 	*image_ptr = (void*)(_SHIFTL(ptr->tex_maddr & 0x00ffffff,5,24));
2968 	*width = (ptr->tex_size & 0x3ff) + 1;
2969 	*height = _SHIFTR(ptr->tex_size & 0xffc00, 10, 10) + 1;
2970 	*format = ptr->tex_fmt;
2971 	*wrap_s = ptr->tex_filt & 0x03;
2972 	*wrap_t = _SHIFTR(ptr->tex_filt & 0x0c, 2, 2);
2973 	*mipmap = ptr->tex_flag & 0x01;
2974 }
GX_GetTexBufferSize(u16 wd,u16 ht,u32 fmt,u8 mipmap,u8 maxlod)2975 u32 GX_GetTexBufferSize(u16 wd,u16 ht,u32 fmt,u8 mipmap,u8 maxlod)
2976 {
2977 	u32 xshift,yshift,xtiles,ytiles,bitsize,size;
2978 
2979 	switch(fmt) {
2980 		case GX_TF_I4:
2981 		case GX_TF_CMPR:
2982 		case GX_CTF_R4:
2983 		case GX_CTF_RA4:
2984 		case GX_CTF_Z4:
2985 			xshift = 3;
2986 			yshift = 3;
2987 			break;
2988 		case GX_TF_Z8:
2989 		case GX_TF_I8:
2990 		case GX_TF_IA4:
2991 		case GX_CTF_A8:
2992 		case GX_CTF_R8:
2993 		case GX_CTF_G8:
2994 		case GX_CTF_B8:
2995 		case GX_CTF_RG8:
2996 		case GX_CTF_GB8:
2997 		case GX_CTF_Z8M:
2998 		case GX_CTF_Z8L:
2999 			xshift = 3;
3000 			yshift = 2;
3001 			break;
3002 		case GX_TF_IA8:
3003 		case GX_TF_Z16:
3004 		case GX_TF_Z24X8:
3005 		case GX_TF_RGB565:
3006 		case GX_TF_RGB5A3:
3007 		case GX_TF_RGBA8:
3008 		case GX_CTF_Z16L:
3009 		case GX_CTF_RA8:
3010 			xshift = 2;
3011 			yshift = 2;
3012 			break;
3013 		default:
3014 			xshift = 2;
3015 			yshift = 2;
3016 			break;
3017 	}
3018 
3019 	bitsize = 32;
3020 	if(fmt==GX_TF_RGBA8 || fmt==GX_TF_Z24X8) bitsize = 64;
3021 
3022 	size = 0;
3023 	if(mipmap) {
3024 		u32 cnt = (maxlod&0xff);
3025 		while(cnt) {
3026 			u32 w = wd&0xffff;
3027 			u32 h = ht&0xffff;
3028 			xtiles = ((w+(1<<xshift))-1)>>xshift;
3029 			ytiles = ((h+(1<<yshift))-1)>>yshift;
3030 			if(cnt==0) return size;
3031 
3032 			size += ((xtiles*ytiles)*bitsize);
3033 			if(w==0x0001 && h==0x0001) return size;
3034 			if(wd>0x0001) wd = (w>>1);
3035 			else wd = 0x0001;
3036 			if(ht>0x0001) ht = (h>>1);
3037 			else ht = 0x0001;
3038 
3039 			--cnt;
3040 		}
3041 		return size;
3042 	}
3043 
3044 	wd &= 0xffff;
3045 	xtiles = (wd+((1<<xshift)-1))>>xshift;
3046 
3047 	ht &= 0xffff;
3048 	ytiles = (ht+((1<<yshift)-1))>>yshift;
3049 
3050 	size = ((xtiles*ytiles)*bitsize);
3051 
3052 	return size;
3053 }
3054 
GX_InitTexCacheRegion(GXTexRegion * region,u8 is32bmipmap,u32 tmem_even,u8 size_even,u32 tmem_odd,u8 size_odd)3055 void GX_InitTexCacheRegion(GXTexRegion *region,u8 is32bmipmap,u32 tmem_even,u8 size_even,u32 tmem_odd,u8 size_odd)
3056 {
3057 	u32 sze = 0;
3058 	struct __gx_texregion *ptr = (struct __gx_texregion*)region;
3059 
3060 	switch(size_even) {
3061 		case GX_TEXCACHE_32K:
3062 			sze = 3;
3063 			break;
3064 		case GX_TEXCACHE_128K:
3065 			sze = 4;
3066 			break;
3067 		case GX_TEXCACHE_512K:
3068 			sze = 5;
3069 			break;
3070 		default:
3071 			sze = 3;
3072 			break;
3073 	}
3074 	ptr->tmem_even = 0;
3075 	ptr->tmem_even = (ptr->tmem_even&~0x7fff)|(_SHIFTR(tmem_even,5,15));
3076 	ptr->tmem_even = (ptr->tmem_even&~0x38000)|(_SHIFTL(sze,15,3));
3077 	ptr->tmem_even = (ptr->tmem_even&~0x1C0000)|(_SHIFTL(sze,18,3));
3078 
3079 	switch(size_odd) {
3080 		case GX_TEXCACHE_32K:
3081 			sze = 3;
3082 			break;
3083 		case GX_TEXCACHE_128K:
3084 			sze = 4;
3085 			break;
3086 		case GX_TEXCACHE_512K:
3087 			sze = 5;
3088 			break;
3089 		default:
3090 			sze = 3;
3091 			break;
3092 	}
3093 	ptr->tmem_odd = 0;
3094 	ptr->tmem_odd = (ptr->tmem_odd&~0x7fff)|(_SHIFTR(tmem_odd,5,15));
3095 	ptr->tmem_odd = (ptr->tmem_odd&~0x38000)|(_SHIFTL(sze,15,3));
3096 	ptr->tmem_odd = (ptr->tmem_odd&~0x1C0000)|(_SHIFTL(sze,18,3));
3097 
3098 	ptr->ismipmap = is32bmipmap;
3099 	ptr->iscached = 1;
3100 }
3101 
GX_InitTexPreloadRegion(GXTexRegion * region,u32 tmem_even,u32 size_even,u32 tmem_odd,u32 size_odd)3102 void GX_InitTexPreloadRegion(GXTexRegion *region,u32 tmem_even,u32 size_even,u32 tmem_odd,u32 size_odd)
3103 {
3104 	struct __gx_texregion *ptr = (struct __gx_texregion*)region;
3105 
3106 	ptr->tmem_even = 0;
3107 	ptr->tmem_even = (ptr->tmem_even&~0x7FFF)|(_SHIFTR(tmem_even,5,15));
3108 	ptr->tmem_even = (ptr->tmem_even&~0x200000)|0x200000;
3109 
3110 	ptr->tmem_odd = 0;
3111 	ptr->tmem_odd = (ptr->tmem_odd&~0x7FFF)|(_SHIFTR(tmem_odd,5,15));
3112 
3113 	ptr->size_even = _SHIFTR(size_even,5,16);
3114 	ptr->size_odd = _SHIFTR(size_odd,5,16);
3115 
3116 	ptr->ismipmap = 0;
3117 	ptr->iscached = 0;
3118 }
3119 
GX_InitTlutRegion(GXTlutRegion * region,u32 tmem_addr,u8 tlut_sz)3120 void GX_InitTlutRegion(GXTlutRegion *region,u32 tmem_addr,u8 tlut_sz)
3121 {
3122 	struct __gx_tlutregion *ptr = (struct __gx_tlutregion*)region;
3123 
3124 	tmem_addr -= 0x80000;
3125 
3126 	ptr->tmem_addr_conf = 0;
3127 	ptr->tmem_addr_conf = (ptr->tmem_addr_conf&~0x3ff)|(_SHIFTR(tmem_addr,9,10));
3128 	ptr->tmem_addr_conf = (ptr->tmem_addr_conf&~0x1FFC00)|(_SHIFTL(tlut_sz,10,10));
3129 	ptr->tmem_addr_conf = (ptr->tmem_addr_conf&~0xff000000)|(_SHIFTL(0x65,24,8));
3130 }
3131 
GX_InitTexObj(GXTexObj * obj,void * img_ptr,u16 wd,u16 ht,u8 fmt,u8 wrap_s,u8 wrap_t,u8 mipmap)3132 void GX_InitTexObj(GXTexObj *obj,void *img_ptr,u16 wd,u16 ht,u8 fmt,u8 wrap_s,u8 wrap_t,u8 mipmap)
3133 {
3134 	u32 nwd,nht;
3135 	u32 xshift,yshift;
3136 	struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3137 
3138 	if(!obj) return;
3139 
3140 	memset(obj,0,sizeof(GXTexObj));
3141 
3142 	ptr->tex_filt = (ptr->tex_filt&~0x03)|(wrap_s&3);
3143 	ptr->tex_filt = (ptr->tex_filt&~0x0c)|(_SHIFTL(wrap_t,2,2));
3144 	ptr->tex_filt = (ptr->tex_filt&~0x10)|0x10;
3145 
3146 	if(mipmap) {
3147 		ptr->tex_flag |= 0x01;
3148 		if(fmt==GX_TF_CI4 || fmt==GX_TF_CI8 || fmt==GX_TF_CI14)
3149 			ptr->tex_filt = (ptr->tex_filt&~0xe0)|0x00a0;
3150 		else
3151 			ptr->tex_filt = (ptr->tex_filt&~0xe0)|0x00c0;
3152 	} else
3153 		ptr->tex_filt= (ptr->tex_filt&~0xE0)|0x0080;
3154 
3155 	ptr->tex_fmt = fmt;
3156 	ptr->tex_size = (ptr->tex_size&~0x3ff)|((wd-1)&0x3ff);
3157 	ptr->tex_size = (ptr->tex_size&~0xFFC00)|(_SHIFTL((ht-1),10,10));
3158 	ptr->tex_size = (ptr->tex_size&~0xF00000)|(_SHIFTL(fmt,20,4));
3159 	ptr->tex_maddr = (ptr->tex_maddr&~0x00ffffff)|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(img_ptr),5,24));
3160 
3161 	switch(fmt) {
3162 		case GX_TF_I4:
3163 		case GX_TF_CI4:
3164 			xshift = 3;
3165 			yshift = 3;
3166 			ptr->tex_tile_type = 1;
3167 			break;
3168 		case GX_TF_I8:
3169 		case GX_TF_IA4:
3170 		case GX_TF_CI8:
3171 			xshift = 3;
3172 			yshift = 2;
3173 			ptr->tex_tile_type = 2;
3174 			break;
3175 		case GX_TF_IA8:
3176 		case GX_TF_RGB565:
3177 		case GX_TF_RGB5A3:
3178 		case GX_TF_RGBA8:
3179 			xshift = 2;
3180 			yshift = 2;
3181 			ptr->tex_tile_type = 2;
3182 			break;
3183 		case GX_TF_CI14:
3184 			xshift = 2;
3185 			yshift = 2;
3186 			ptr->tex_tile_type = 3;
3187 			break;
3188 		case GX_TF_CMPR:
3189 			xshift = 3;
3190 			yshift = 3;
3191 			ptr->tex_tile_type = 0;
3192 			break;
3193 		default:
3194 			xshift = 2;
3195 			yshift = 2;
3196 			ptr->tex_tile_type = 2;
3197 			break;
3198 	}
3199 
3200 	nwd = ((wd+(1<<xshift))-1)>>xshift;
3201 	nht = ((ht+(1<<yshift))-1)>>yshift;
3202 	ptr->tex_tile_cnt = (nwd*nht)&0x7fff;
3203 
3204 	ptr->tex_flag |= 0x0002;
3205 }
3206 
GX_InitTexObjCI(GXTexObj * obj,void * img_ptr,u16 wd,u16 ht,u8 fmt,u8 wrap_s,u8 wrap_t,u8 mipmap,u32 tlut_name)3207 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)
3208 {
3209 	struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3210 
3211 	GX_InitTexObj(obj,img_ptr,wd,ht,fmt,wrap_s,wrap_t,mipmap);
3212 	ptr->tex_flag &= ~0x02;
3213 	ptr->tex_tlut = tlut_name;
3214 }
3215 
GX_InitTexObjLOD(GXTexObj * obj,u8 minfilt,u8 magfilt,f32 minlod,f32 maxlod,f32 lodbias,u8 biasclamp,u8 edgelod,u8 maxaniso)3216 void GX_InitTexObjLOD(GXTexObj *obj,u8 minfilt,u8 magfilt,f32 minlod,f32 maxlod,f32 lodbias,u8 biasclamp,u8 edgelod,u8 maxaniso)
3217 {
3218 	struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3219 	static u8 GX2HWFiltConv[] = {0x00,0x04,0x01,0x05,0x02,0x06,0x00,0x00};
3220 	//static u8 HW2GXFiltConv[] = {0x00,0x02,0x04,0x00,0x01,0x03,0x05,0x00};
3221 
3222 	if(lodbias<-4.0f) lodbias = -4.0f;
3223 	else if(lodbias==4.0f) lodbias = 3.99f;
3224 
3225 	ptr->tex_filt = (ptr->tex_filt&~0x1fe00)|(_SHIFTL(((u32)(32.0f*lodbias)),9,8));
3226 	ptr->tex_filt = (ptr->tex_filt&~0x10)|(_SHIFTL((magfilt==GX_LINEAR?1:0),4,1));
3227 	ptr->tex_filt = (ptr->tex_filt&~0xe0)|(_SHIFTL(GX2HWFiltConv[minfilt],5,3));
3228 	ptr->tex_filt = (ptr->tex_filt&~0x100)|(_SHIFTL(!(edgelod&0xff),8,1));
3229 	ptr->tex_filt = (ptr->tex_filt&~0x180000)|(_SHIFTL(maxaniso,19,2));
3230 	ptr->tex_filt = (ptr->tex_filt&~0x200000)|(_SHIFTL(biasclamp,21,1));
3231 
3232 	if(minlod<0.0f) minlod = 0.0f;
3233 	else if(minlod>10.0f) minlod = 10.0f;
3234 
3235 	if(maxlod<0.0f) maxlod = 0.0f;
3236 	else if(maxlod>10.0f) maxlod = 10.0f;
3237 
3238 	ptr->tex_lod = (ptr->tex_lod&~0xff)|(((u32)(16.0f*minlod))&0xff);
3239 	ptr->tex_lod = (ptr->tex_lod&~0xff00)|(_SHIFTL(((u32)(16.0f*maxlod)),8,8));
3240 }
3241 
GX_InitTexObjData(GXTexObj * obj,void * img_ptr)3242 void GX_InitTexObjData(GXTexObj *obj,void *img_ptr)
3243 {
3244 	struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3245 	ptr->tex_maddr = (ptr->tex_maddr&~0x00ffffff)|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(img_ptr),5,24));
3246 }
3247 
GX_InitTexObjTlut(GXTexObj * obj,u32 tlut_name)3248 void GX_InitTexObjTlut(GXTexObj *obj,u32 tlut_name)
3249 {
3250 	((struct __gx_texobj*)obj)->tex_tlut = tlut_name;
3251 }
3252 
GX_InitTexObjWrapMode(GXTexObj * obj,u8 wrap_s,u8 wrap_t)3253 void GX_InitTexObjWrapMode(GXTexObj *obj,u8 wrap_s,u8 wrap_t)
3254 {
3255 	struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3256 
3257 	ptr->tex_filt = (ptr->tex_filt&~0x03)|(wrap_s&3);
3258 	ptr->tex_filt = (ptr->tex_filt&~0x0c)|(_SHIFTL(wrap_t,2,2));
3259 }
3260 
GX_InitTexObjFilterMode(GXTexObj * obj,u8 minfilt,u8 magfilt)3261 void GX_InitTexObjFilterMode(GXTexObj *obj,u8 minfilt,u8 magfilt)
3262 {
3263 	struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3264 	static u8 GX2HWFiltConv[] = {0x00,0x04,0x01,0x05,0x02,0x06,0x00,0x00};
3265 
3266 	ptr->tex_filt = (ptr->tex_filt&~0x10)|(_SHIFTL((magfilt==GX_LINEAR?1:0),4,1));
3267 	ptr->tex_filt = (ptr->tex_filt&~0xe0)|(_SHIFTL(GX2HWFiltConv[minfilt],5,3));
3268 }
3269 
GX_InitTexObjMinLOD(GXTexObj * obj,f32 minlod)3270 void GX_InitTexObjMinLOD(GXTexObj *obj,f32 minlod)
3271 {
3272 	struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3273 
3274 	if(minlod<0.0f) minlod = 0.0f;
3275 	else if(minlod>10.0f) minlod = 10.0f;
3276 
3277 	ptr->tex_lod = (ptr->tex_lod&~0xff)|(((u32)(16.0f*minlod))&0xff);
3278 }
3279 
GX_InitTexObjMaxLOD(GXTexObj * obj,f32 maxlod)3280 void GX_InitTexObjMaxLOD(GXTexObj *obj,f32 maxlod)
3281 {
3282 	struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3283 
3284 	if(maxlod<0.0f) maxlod = 0.0f;
3285 	else if(maxlod>10.0f) maxlod = 10.0f;
3286 
3287 	ptr->tex_lod = (ptr->tex_lod&~0xff00)|(_SHIFTL(((u32)(16.0f*maxlod)),8,8));
3288 }
3289 
GX_InitTexObjLODBias(GXTexObj * obj,f32 lodbias)3290 void GX_InitTexObjLODBias(GXTexObj *obj,f32 lodbias)
3291 {
3292 	struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3293 
3294 	if(lodbias<-4.0f) lodbias = -4.0f;
3295 	else if(lodbias==4.0f) lodbias = 3.99f;
3296 
3297 	ptr->tex_filt = (ptr->tex_filt&~0x1fe00)|(_SHIFTL(((u32)(32.0f*lodbias)),9,8));
3298 }
3299 
GX_InitTexObjBiasClamp(GXTexObj * obj,u8 biasclamp)3300 void GX_InitTexObjBiasClamp(GXTexObj *obj,u8 biasclamp)
3301 {
3302 	struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3303 	ptr->tex_filt = (ptr->tex_filt&~0x200000)|(_SHIFTL(biasclamp,21,1));
3304 }
3305 
GX_InitTexObjEdgeLOD(GXTexObj * obj,u8 edgelod)3306 void GX_InitTexObjEdgeLOD(GXTexObj *obj,u8 edgelod)
3307 {
3308 	struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3309 	ptr->tex_filt = (ptr->tex_filt&~0x100)|(_SHIFTL(!(edgelod&0xff),8,1));
3310 }
3311 
GX_InitTexObjMaxAniso(GXTexObj * obj,u8 maxaniso)3312 void GX_InitTexObjMaxAniso(GXTexObj *obj,u8 maxaniso)
3313 {
3314 	struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3315 	ptr->tex_filt = (ptr->tex_filt&~0x180000)|(_SHIFTL(maxaniso,19,2));
3316 }
3317 
GX_InitTexObjUserData(GXTexObj * obj,void * userdata)3318 void GX_InitTexObjUserData(GXTexObj *obj,void *userdata)
3319 {
3320 	struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3321 	ptr->usr_data = (u32)userdata;
3322 }
3323 
GX_GetTexObjUserData(GXTexObj * obj)3324 void* GX_GetTexObjUserData(GXTexObj *obj)
3325 {
3326 	struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3327 	return (void*)ptr->usr_data;
3328 }
3329 
GX_InitTlutObj(GXTlutObj * obj,void * lut,u8 fmt,u16 entries)3330 void GX_InitTlutObj(GXTlutObj *obj,void *lut,u8 fmt,u16 entries)
3331 {
3332 	struct __gx_tlutobj *ptr = (struct __gx_tlutobj*)obj;
3333 
3334 	memset(obj,0,sizeof(GXTlutObj));
3335 
3336 	ptr->tlut_fmt = _SHIFTL(fmt,10,2);
3337 	ptr->tlut_maddr = (ptr->tlut_maddr&~0x00ffffff)|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(lut),5,24));
3338 	ptr->tlut_maddr = (ptr->tlut_maddr&~0xff000000)|(_SHIFTL(0x64,24,8));
3339 	ptr->tlut_nentries = entries;
3340 }
3341 
GX_LoadTexObj(GXTexObj * obj,u8 mapid)3342 void GX_LoadTexObj(GXTexObj *obj,u8 mapid)
3343 {
3344 	GXTexRegion *region = NULL;
3345 
3346 	if(regionCB)
3347 		region = regionCB(obj,mapid);
3348 
3349 	GX_LoadTexObjPreloaded(obj,region,mapid);
3350 }
3351 
GX_LoadTexObjPreloaded(GXTexObj * obj,GXTexRegion * region,u8 mapid)3352 void GX_LoadTexObjPreloaded(GXTexObj *obj,GXTexRegion *region,u8 mapid)
3353 {
3354 	u8 type;
3355 	struct __gx_tlutregion *tlut = NULL;
3356 	struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3357 	struct __gx_texregion *reg = (struct __gx_texregion*)region;
3358 
3359 	ptr->tex_filt = (ptr->tex_filt&~0xff000000)|(_SHIFTL(_gxtexmode0ids[mapid],24,8));
3360 	ptr->tex_lod = (ptr->tex_lod&~0xff000000)|(_SHIFTL(_gxtexmode1ids[mapid],24,8));
3361 	ptr->tex_size = (ptr->tex_size&~0xff000000)|(_SHIFTL(_gxteximg0ids[mapid],24,8));
3362 	ptr->tex_maddr = (ptr->tex_maddr&~0xff000000)|(_SHIFTL(_gxteximg3ids[mapid],24,8));
3363 
3364 	reg->tmem_even = (reg->tmem_even&~0xff000000)|(_SHIFTL(_gxteximg1ids[mapid],24,8));
3365 	reg->tmem_odd = (reg->tmem_odd&~0xff000000)|(_SHIFTL(_gxteximg2ids[mapid],24,8));
3366 
3367 	GX_LOAD_BP_REG(ptr->tex_filt);
3368 	GX_LOAD_BP_REG(ptr->tex_lod);
3369 	GX_LOAD_BP_REG(ptr->tex_size);
3370 
3371 	GX_LOAD_BP_REG(reg->tmem_even);
3372 	GX_LOAD_BP_REG(reg->tmem_odd);
3373 
3374 	GX_LOAD_BP_REG(ptr->tex_maddr);
3375 
3376 	type = ptr->tex_flag;
3377 	if(!(type&0x02)) {
3378 		if(tlut_regionCB)
3379 			tlut = (struct __gx_tlutregion*)tlut_regionCB(ptr->tex_tlut);
3380 		tlut->tmem_addr_base = (tlut->tmem_addr_base&~0xff000000)|(_SHIFTL(_gxtextlutids[mapid],24,8));
3381 		GX_LOAD_BP_REG(tlut->tmem_addr_base);
3382 	}
3383 
3384 	__gx->texMapSize[mapid] = ptr->tex_size;
3385 	__gx->texMapWrap[mapid] = ptr->tex_filt;
3386 
3387 	__gx->dirtyState |= 0x0001;
3388 }
3389 
GX_PreloadEntireTexture(GXTexObj * obj,GXTexRegion * region)3390 void GX_PreloadEntireTexture(GXTexObj *obj,GXTexRegion *region)
3391 {
3392 	u32 i,fmt;
3393 	s32 wd,ht;
3394 	u16 cnt = 0;
3395 	u32 regA = 0;
3396 	u32 regB = 0;
3397 	u32 regC = 0;
3398 	u32 regD = 0;
3399 	struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
3400 	struct __gx_texregion *reg = (struct __gx_texregion*)region;
3401 
3402 	regA = (regA&~0xff000000)|(_SHIFTL(0x60,24,8));
3403 	regA = (regA&~0x00ffffff)|(ptr->tex_maddr&~0xff000000);
3404 
3405 	regB = (regB&~0xff000000)|(_SHIFTL(0x61,24,8));
3406 	regB = (regB&~0x00007fff)|(reg->tmem_even&0x00007fff);
3407 
3408 	regC = (regC&~0xff000000)|(_SHIFTL(0x62,24,8));
3409 	regC = (regC&~0x00007fff)|(reg->tmem_odd&0x00007fff);
3410 
3411 	regD = (regD&~0xff000000)|(_SHIFTL(0x63,24,8));
3412 	regD = (regD&~0x00007fff)|(ptr->tex_tile_cnt&0x00007fff);
3413 	regD = (regD&~0x00018000)|(_SHIFTL(ptr->tex_tile_type,15,2));
3414 
3415 	fmt = _SHIFTR(ptr->tex_size,20,4);
3416 
3417 	__GX_FlushTextureState();
3418 	GX_LOAD_BP_REG(regA);
3419 	GX_LOAD_BP_REG(regB);
3420 	GX_LOAD_BP_REG(regC);
3421 	GX_LOAD_BP_REG(regD);
3422 
3423 	if(ptr->tex_flag&0x01) {
3424 		wd = (ptr->tex_size&0x3ff)+1;
3425 		ht = _SHIFTR(ptr->tex_size,10,10)+1;
3426 		if(wd>ht)
3427 			cnt = (31 - (cntlzw(wd)));
3428 		else
3429 			cnt = (31 - (cntlzw(ht)));
3430 	}
3431 
3432 	if(cnt>0) {
3433 		u32 tmem_even,tmem_odd,maddr;
3434 		u32 tile_cnt = ptr->tex_tile_cnt;
3435 
3436 		tmem_even = (reg->tmem_even&0xffff);
3437 		tmem_odd = (reg->tmem_odd&0xffff);
3438 		maddr = (ptr->tex_maddr&~0xff000000);
3439 
3440 		i = 0;
3441 		while(cnt) {
3442 			u32 w,h;
3443 			u32 te,to;
3444 			u32 xshift,yshift;
3445 
3446 			if(fmt==GX_TF_RGBA8) {
3447 				tmem_even += tile_cnt;
3448 				tmem_odd += tile_cnt;
3449 				maddr += (tile_cnt<<1);
3450 			} else {
3451 				maddr += tile_cnt;
3452 				if(i&1) tmem_odd += tile_cnt;
3453 				else tmem_even += tile_cnt;
3454 			}
3455 
3456 			te = tmem_even;
3457 			to = tmem_odd;
3458 			if(i&1) {
3459 				te = tmem_odd;
3460 				to = tmem_even;
3461 			}
3462 
3463 			w = wd>>(i+1);
3464 			h = wd>>(i+1);
3465 			switch(ptr->tex_fmt) {
3466 				case GX_TF_I4:
3467 				case GX_TF_IA4:
3468 				case GX_TF_CI4:
3469 				case GX_TF_CMPR:
3470 					xshift = 3;
3471 					yshift = 3;
3472 					break;
3473 				case GX_TF_I8:
3474 				case GX_TF_CI8:
3475 					xshift = 3;
3476 					yshift = 2;
3477 					break;
3478 				case GX_TF_IA8:
3479 				case GX_TF_RGB5A3:
3480 				case GX_TF_RGB565:
3481 				case GX_TF_CI14:
3482 					xshift = 2;
3483 					yshift = 2;
3484 					break;
3485 				default:
3486 					xshift = 0;
3487 					yshift = 0;
3488 					break;
3489 			}
3490 
3491 			if(!w) w = 1;
3492 			if(!h) h = 1;
3493 
3494 			regA = ((regA&~0x00ffffff)|(maddr&0x00ffffff));
3495 			GX_LOAD_BP_REG(regA);
3496 
3497 			regB = ((regB&~0x00007fff)|(te&0x00007fff));
3498 			GX_LOAD_BP_REG(regB);
3499 
3500 			regC = ((regC&~0x00007fff)|(to&0x00007fff));
3501 			GX_LOAD_BP_REG(regC);
3502 
3503 			tile_cnt = (((w+(1<<xshift))-1)>>xshift)*(((h+(1<<yshift))-1)>>yshift);
3504 			regD = ((regD&~0x00007fff)|(tile_cnt&0x00007fff));
3505 			GX_LOAD_BP_REG(regD);
3506 
3507 			++i;
3508 			--cnt;
3509 		}
3510 	}
3511 	__GX_FlushTextureState();
3512 }
3513 
GX_InvalidateTexAll()3514 void GX_InvalidateTexAll()
3515 {
3516 	__GX_FlushTextureState();
3517 	GX_LOAD_BP_REG(0x66001000);
3518 	GX_LOAD_BP_REG(0x66001100);
3519 	__GX_FlushTextureState();
3520 }
3521 
GX_InvalidateTexRegion(GXTexRegion * region)3522 void GX_InvalidateTexRegion(GXTexRegion *region)
3523 {
3524 	u8 ismipmap;
3525 	s32 cw_e,ch_e,cw_o,ch_o;
3526 	u32 size,tmp,regvalA = 0,regvalB = 0;
3527 	struct __gx_texregion *ptr = (struct __gx_texregion*)region;
3528 
3529 	cw_e = (_SHIFTR(ptr->tmem_even,15,3))-1;
3530 	ch_e = (_SHIFTR(ptr->tmem_even,18,3))-1;
3531 
3532 	cw_o = (_SHIFTR(ptr->tmem_odd,15,3))-1;
3533 	ch_o = (_SHIFTR(ptr->tmem_odd,18,3))-1;
3534 
3535 	if(cw_e<0) cw_e = 0;
3536 	if(ch_e<0) ch_e = 0;
3537 	if(cw_o<0) cw_o = 0;
3538 	if(ch_o<0) ch_o = 0;
3539 
3540 	ismipmap = ptr->ismipmap;
3541 
3542 	tmp = size = cw_e+ch_e;
3543 	if(ismipmap) size = (tmp+cw_o+ch_o)-2;
3544 	regvalA = _SHIFTR((ptr->tmem_even&0x7fff),6,9)|(_SHIFTL(size,9,4))|(_SHIFTL(0x66,24,8));
3545 
3546 	if(cw_o!=0) {
3547 		size = cw_o+ch_o;
3548 		if(ismipmap) size += (tmp-2);
3549 		regvalB = _SHIFTR((ptr->tmem_odd&0x7fff),6,9)|(_SHIFTL(size,9,4))|(_SHIFTL(0x66,24,8));
3550 	}
3551 	__GX_FlushTextureState();
3552 	GX_LOAD_BP_REG(regvalA);
3553 	if(cw_o!=0) GX_LOAD_BP_REG(regvalB);
3554 	__GX_FlushTextureState();
3555 }
3556 
GX_LoadTlut(GXTlutObj * obj,u32 tlut_name)3557 void GX_LoadTlut(GXTlutObj *obj,u32 tlut_name)
3558 {
3559 	struct __gx_tlutregion *region = NULL;
3560 	struct __gx_tlutobj *ptr = (struct __gx_tlutobj*)obj;
3561 
3562 	if(tlut_regionCB)
3563 		region = (struct __gx_tlutregion*)tlut_regionCB(tlut_name);
3564 
3565 	__GX_FlushTextureState();
3566 	GX_LOAD_BP_REG(ptr->tlut_maddr);
3567 	GX_LOAD_BP_REG(region->tmem_addr_conf);
3568 	__GX_FlushTextureState();
3569 
3570 	region->tmem_addr_base = (ptr->tlut_fmt&~0x3ff)|(region->tmem_addr_conf&0x3ff);
3571 	region->tlut_maddr = ptr->tlut_maddr;
3572 	region->tlut_nentries = ptr->tlut_nentries;
3573 }
3574 
GX_SetTexCoordScaleManually(u8 texcoord,u8 enable,u16 ss,u16 ts)3575 void GX_SetTexCoordScaleManually(u8 texcoord,u8 enable,u16 ss,u16 ts)
3576 {
3577 	u32 reg;
3578 
3579 	__gx->texCoordManually = (__gx->texCoordManually&~(_SHIFTL(1,texcoord,1)))|(_SHIFTL(enable,texcoord,1));
3580 	if(!enable) return;
3581 
3582 	reg = (texcoord&0x7);
3583 	__gx->suSsize[reg] = (__gx->suSsize[reg]&~0xffff)|((ss-1)&0xffff);
3584 	__gx->suTsize[reg] = (__gx->suTsize[reg]&~0xffff)|((ts-1)&0xffff);
3585 
3586 	GX_LOAD_BP_REG(__gx->suSsize[reg]);
3587 	GX_LOAD_BP_REG(__gx->suTsize[reg]);
3588 }
3589 
GX_SetTexCoordCylWrap(u8 texcoord,u8 s_enable,u8 t_enable)3590 void GX_SetTexCoordCylWrap(u8 texcoord,u8 s_enable,u8 t_enable)
3591 {
3592 	u32 reg;
3593 
3594 	reg = (texcoord&0x7);
3595 	__gx->suSsize[reg] = (__gx->suSsize[reg]&~0x20000)|(_SHIFTL(s_enable,17,1));
3596 	__gx->suTsize[reg] = (__gx->suTsize[reg]&~0x20000)|(_SHIFTL(t_enable,17,1));
3597 
3598 	if(!(__gx->texCoordManually&(_SHIFTL(1,texcoord,1)))) return;
3599 
3600 	GX_LOAD_BP_REG(__gx->suSsize[reg]);
3601 	GX_LOAD_BP_REG(__gx->suTsize[reg]);
3602 }
3603 
GX_SetTexCoordBias(u8 texcoord,u8 s_enable,u8 t_enable)3604 void GX_SetTexCoordBias(u8 texcoord,u8 s_enable,u8 t_enable)
3605 {
3606 	u32 reg;
3607 
3608 	reg = (texcoord&0x7);
3609 	__gx->suSsize[reg] = (__gx->suSsize[reg]&~0x10000)|(_SHIFTL(s_enable,16,1));
3610 	__gx->suTsize[reg] = (__gx->suTsize[reg]&~0x10000)|(_SHIFTL(t_enable,16,1));
3611 
3612 	if(!(__gx->texCoordManually&(_SHIFTL(1,texcoord,1)))) return;
3613 
3614 	GX_LOAD_BP_REG(__gx->suSsize[reg]);
3615 	GX_LOAD_BP_REG(__gx->suTsize[reg]);
3616 }
3617 
GX_SetTexRegionCallback(GXTexRegionCallback cb)3618 GXTexRegionCallback GX_SetTexRegionCallback(GXTexRegionCallback cb)
3619 {
3620 	u32 level;
3621 	GXTexRegionCallback ret;
3622 
3623 	_CPU_ISR_Disable(level);
3624 	ret = regionCB;
3625 	regionCB = cb;
3626 	_CPU_ISR_Restore(level);
3627 
3628 	return ret;
3629 }
3630 
GX_SetTlutRegionCallback(GXTlutRegionCallback cb)3631 GXTlutRegionCallback GX_SetTlutRegionCallback(GXTlutRegionCallback cb)
3632 {
3633 	u32 level;
3634 	GXTlutRegionCallback ret;
3635 
3636 	_CPU_ISR_Disable(level);
3637 	ret = tlut_regionCB;
3638 	tlut_regionCB = cb;
3639 	_CPU_ISR_Restore(level);
3640 
3641 	return ret;
3642 }
3643 
GX_SetBlendMode(u8 type,u8 src_fact,u8 dst_fact,u8 op)3644 void GX_SetBlendMode(u8 type,u8 src_fact,u8 dst_fact,u8 op)
3645 {
3646 	__gx->peCMode0 = (__gx->peCMode0&~0x1);
3647 	if(type==GX_BM_BLEND || type==GX_BM_SUBTRACT) __gx->peCMode0 |= 0x1;
3648 
3649 	__gx->peCMode0 = (__gx->peCMode0&~0x800);
3650 	if(type==GX_BM_SUBTRACT) __gx->peCMode0 |= 0x800;
3651 
3652 	__gx->peCMode0 = (__gx->peCMode0&~0x2);
3653 	if(type==GX_BM_LOGIC) __gx->peCMode0 |= 0x2;
3654 
3655 	__gx->peCMode0 = (__gx->peCMode0&~0xF000)|(_SHIFTL(op,12,4));
3656 	__gx->peCMode0 = (__gx->peCMode0&~0xE0)|(_SHIFTL(dst_fact,5,3));
3657 	__gx->peCMode0 = (__gx->peCMode0&~0x700)|(_SHIFTL(src_fact,8,3));
3658 
3659 	GX_LOAD_BP_REG(__gx->peCMode0);
3660 }
3661 
GX_ClearVtxDesc()3662 void GX_ClearVtxDesc()
3663 {
3664 	__gx->vcdNrms = 0;
3665 	__gx->vcdClear = ((__gx->vcdClear&~0x0600)|0x0200);
3666 	__gx->vcdLo = __gx->vcdHi = 0;
3667 	__gx->dirtyState |= 0x0008;
3668 }
3669 
GX_SetLineWidth(u8 width,u8 fmt)3670 void GX_SetLineWidth(u8 width,u8 fmt)
3671 {
3672 	__gx->lpWidth = (__gx->lpWidth&~0xff)|(width&0xff);
3673 	__gx->lpWidth = (__gx->lpWidth&~0x70000)|(_SHIFTL(fmt,16,3));
3674 	GX_LOAD_BP_REG(__gx->lpWidth);
3675 }
3676 
GX_SetPointSize(u8 width,u8 fmt)3677 void GX_SetPointSize(u8 width,u8 fmt)
3678 {
3679 	__gx->lpWidth = (__gx->lpWidth&~0xFF00)|(_SHIFTL(width,8,8));
3680 	__gx->lpWidth = (__gx->lpWidth&~0x380000)|(_SHIFTL(fmt,19,3));
3681 	GX_LOAD_BP_REG(__gx->lpWidth);
3682 }
3683 
GX_SetTevColor(u8 tev_regid,GXColor color)3684 void GX_SetTevColor(u8 tev_regid,GXColor color)
3685 {
3686 	u32 reg;
3687 
3688 	reg = (_SHIFTL((0xe0+(tev_regid<<1)),24,8)|(_SHIFTL(color.a,12,8))|(color.r&0xff));
3689 	GX_LOAD_BP_REG(reg);
3690 
3691 	reg = (_SHIFTL((0xe1+(tev_regid<<1)),24,8)|(_SHIFTL(color.g,12,8))|(color.b&0xff));
3692 	GX_LOAD_BP_REG(reg);
3693 
3694 	//this two calls should obviously flush the Write Gather Pipe.
3695 	GX_LOAD_BP_REG(reg);
3696 	GX_LOAD_BP_REG(reg);
3697 }
3698 
GX_SetTevColorS10(u8 tev_regid,GXColorS10 color)3699 void GX_SetTevColorS10(u8 tev_regid,GXColorS10 color)
3700 {
3701 	u32 reg;
3702 
3703 	reg = (_SHIFTL((0xe0+(tev_regid<<1)),24,8)|(_SHIFTL(color.a,12,11))|(color.r&0x7ff));
3704 	GX_LOAD_BP_REG(reg);
3705 
3706 	reg = (_SHIFTL((0xe1+(tev_regid<<1)),24,8)|(_SHIFTL(color.g,12,11))|(color.b&0x7ff));
3707 	GX_LOAD_BP_REG(reg);
3708 
3709 	//this two calls should obviously flush the Write Gather Pipe.
3710 	GX_LOAD_BP_REG(reg);
3711 	GX_LOAD_BP_REG(reg);
3712 }
3713 
GX_SetTevKColor(u8 tev_kregid,GXColor color)3714 void GX_SetTevKColor(u8 tev_kregid,GXColor color)
3715 {
3716 	u32 reg;
3717 
3718 	reg = (_SHIFTL((0xe0+(tev_kregid<<1)),24,8)|(_SHIFTL(1,23,1))|(_SHIFTL(color.a,12,8))|(color.r&0xff));
3719 	GX_LOAD_BP_REG(reg);
3720 
3721 	reg = (_SHIFTL((0xe1+(tev_kregid<<1)),24,8)|(_SHIFTL(1,23,1))|(_SHIFTL(color.g,12,8))|(color.b&0xff));
3722 	GX_LOAD_BP_REG(reg);
3723 
3724 	//this two calls should obviously flush the Write Gather Pipe.
3725 	GX_LOAD_BP_REG(reg);
3726 	GX_LOAD_BP_REG(reg);
3727 }
3728 
GX_SetTevKColorS10(u8 tev_kregid,GXColorS10 color)3729 void GX_SetTevKColorS10(u8 tev_kregid,GXColorS10 color)
3730 {
3731 	u32 reg;
3732 
3733 	reg = (_SHIFTL((0xe0+(tev_kregid<<1)),24,8)|(_SHIFTL(1,23,1))|(_SHIFTL(color.a,12,11))|(color.r&0x7ff));
3734 	GX_LOAD_BP_REG(reg);
3735 
3736 	reg = (_SHIFTL((0xe1+(tev_kregid<<1)),24,8)|(_SHIFTL(1,23,1))|(_SHIFTL(color.g,12,11))|(color.b&0x7ff));
3737 	GX_LOAD_BP_REG(reg);
3738 
3739 	//this two calls should obviously flush the Write Gather Pipe.
3740 	GX_LOAD_BP_REG(reg);
3741 	GX_LOAD_BP_REG(reg);
3742 }
3743 
GX_SetTevOp(u8 tevstage,u8 mode)3744 void GX_SetTevOp(u8 tevstage,u8 mode)
3745 {
3746 	u8 defcolor = GX_CC_RASC;
3747 	u8 defalpha = GX_CA_RASA;
3748 
3749 	if(tevstage!=GX_TEVSTAGE0) {
3750 		defcolor = GX_CC_CPREV;
3751 		defalpha = GX_CA_APREV;
3752 	}
3753 
3754 	switch(mode) {
3755 		case GX_MODULATE:
3756 			GX_SetTevColorIn(tevstage,GX_CC_ZERO,GX_CC_TEXC,defcolor,GX_CC_ZERO);
3757 			GX_SetTevAlphaIn(tevstage,GX_CA_ZERO,GX_CA_TEXA,defalpha,GX_CA_ZERO);
3758 			break;
3759 		case GX_DECAL:
3760 			GX_SetTevColorIn(tevstage,defcolor,GX_CC_TEXC,GX_CC_TEXA,GX_CC_ZERO);
3761 			GX_SetTevAlphaIn(tevstage,GX_CA_ZERO,GX_CA_ZERO,GX_CA_ZERO,defalpha);
3762 			break;
3763 		case GX_BLEND:
3764 			GX_SetTevColorIn(tevstage,defcolor,GX_CC_ONE,GX_CC_TEXC,GX_CC_ZERO);
3765 			GX_SetTevAlphaIn(tevstage,GX_CA_ZERO,GX_CA_TEXA,defalpha,GX_CA_RASA);
3766 			break;
3767 		case GX_REPLACE:
3768 			GX_SetTevColorIn(tevstage,GX_CC_ZERO,GX_CC_ZERO,GX_CC_ZERO,GX_CC_TEXC);
3769 			GX_SetTevAlphaIn(tevstage,GX_CA_ZERO,GX_CA_ZERO,GX_CA_ZERO,GX_CA_TEXA);
3770 			break;
3771 		case GX_PASSCLR:
3772 			GX_SetTevColorIn(tevstage,GX_CC_ZERO,GX_CC_ZERO,GX_CC_ZERO,defcolor);
3773 			GX_SetTevAlphaIn(tevstage,GX_CC_A2,GX_CC_A2,GX_CC_A2,defalpha);
3774 			break;
3775 	}
3776 	GX_SetTevColorOp(tevstage,GX_TEV_ADD,GX_TB_ZERO,GX_CS_SCALE_1,GX_TRUE,GX_TEVPREV);
3777 	GX_SetTevAlphaOp(tevstage,GX_TEV_ADD,GX_TB_ZERO,GX_CS_SCALE_1,GX_TRUE,GX_TEVPREV);
3778 }
3779 
GX_SetTevColorIn(u8 tevstage,u8 a,u8 b,u8 c,u8 d)3780 void GX_SetTevColorIn(u8 tevstage,u8 a,u8 b,u8 c,u8 d)
3781 {
3782 	u32 reg = (tevstage&0xf);
3783 	__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0xF000)|(_SHIFTL(a,12,4));
3784 	__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0xF00)|(_SHIFTL(b,8,4));
3785 	__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0xF0)|(_SHIFTL(c,4,4));
3786 	__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0xf)|(d&0xf);
3787 
3788 	GX_LOAD_BP_REG(__gx->tevColorEnv[reg]);
3789 }
3790 
GX_SetTevAlphaIn(u8 tevstage,u8 a,u8 b,u8 c,u8 d)3791 void GX_SetTevAlphaIn(u8 tevstage,u8 a,u8 b,u8 c,u8 d)
3792 {
3793 	u32 reg = (tevstage&0xf);
3794 	__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0xE000)|(_SHIFTL(a,13,3));
3795 	__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x1C00)|(_SHIFTL(b,10,3));
3796 	__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x380)|(_SHIFTL(c,7,3));
3797 	__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x70)|(_SHIFTL(d,4,3));
3798 
3799 	GX_LOAD_BP_REG(__gx->tevAlphaEnv[reg]);
3800 }
3801 
GX_SetTevColorOp(u8 tevstage,u8 tevop,u8 tevbias,u8 tevscale,u8 clamp,u8 tevregid)3802 void GX_SetTevColorOp(u8 tevstage,u8 tevop,u8 tevbias,u8 tevscale,u8 clamp,u8 tevregid)
3803 {
3804 	/* set tev op add/sub*/
3805 	u32 reg = (tevstage&0xf);
3806 	__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x40000)|(_SHIFTL(tevop,18,1));
3807 	if(tevop<=GX_TEV_SUB) {
3808 		__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x300000)|(_SHIFTL(tevscale,20,2));
3809 		__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x30000)|(_SHIFTL(tevbias,16,2));
3810 	} else {
3811 		__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x300000)|((_SHIFTL(tevop,19,4))&0x300000);
3812 		__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x30000)|0x30000;
3813 	}
3814 	__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x80000)|(_SHIFTL(clamp,19,1));
3815 	__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0xC00000)|(_SHIFTL(tevregid,22,2));
3816 
3817 	GX_LOAD_BP_REG(__gx->tevColorEnv[reg]);
3818 }
3819 
GX_SetTevAlphaOp(u8 tevstage,u8 tevop,u8 tevbias,u8 tevscale,u8 clamp,u8 tevregid)3820 void GX_SetTevAlphaOp(u8 tevstage,u8 tevop,u8 tevbias,u8 tevscale,u8 clamp,u8 tevregid)
3821 {
3822 	/* set tev op add/sub*/
3823 	u32 reg = (tevstage&0xf);
3824 	__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x40000)|(_SHIFTL(tevop,18,1));
3825 	if(tevop<=GX_TEV_SUB) {
3826 		__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x300000)|(_SHIFTL(tevscale,20,2));
3827 		__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x30000)|(_SHIFTL(tevbias,16,2));
3828 	} else {
3829 		__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x300000)|((_SHIFTL(tevop,19,4))&0x300000);
3830 		__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x30000)|0x30000;
3831 	}
3832 	__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x80000)|(_SHIFTL(clamp,19,1));
3833 	__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0xC00000)|(_SHIFTL(tevregid,22,2));
3834 
3835 	GX_LOAD_BP_REG(__gx->tevAlphaEnv[reg]);
3836 }
3837 
GX_SetCullMode(u8 mode)3838 void GX_SetCullMode(u8 mode)
3839 {
3840     static u8 cm2hw[] = { 0, 2, 1, 3 };
3841 
3842 	__gx->genMode = (__gx->genMode&~0xC000)|(_SHIFTL(cm2hw[mode],14,2));
3843 	__gx->dirtyState |= 0x0004;
3844 }
3845 
GX_SetCoPlanar(u8 enable)3846 void GX_SetCoPlanar(u8 enable)
3847 {
3848 	__gx->genMode = (__gx->genMode&~0x80000)|(_SHIFTL(enable,19,1));
3849 	GX_LOAD_BP_REG(0xFE080000);
3850 	GX_LOAD_BP_REG(__gx->genMode);
3851 }
3852 
GX_EnableTexOffsets(u8 coord,u8 line_enable,u8 point_enable)3853 void GX_EnableTexOffsets(u8 coord,u8 line_enable,u8 point_enable)
3854 {
3855 	u32 reg = (coord&0x7);
3856 	__gx->suSsize[reg] = (__gx->suSsize[reg]&~0x40000)|(_SHIFTL(line_enable,18,1));
3857 	__gx->suSsize[reg] = (__gx->suSsize[reg]&~0x80000)|(_SHIFTL(point_enable,19,1));
3858 	GX_LOAD_BP_REG(__gx->suSsize[reg]);
3859 }
3860 
GX_SetClipMode(u8 mode)3861 void GX_SetClipMode(u8 mode)
3862 {
3863 	GX_LOAD_XF_REG(0x1005,(mode&1));
3864 }
3865 
GX_SetScissor(u32 xOrigin,u32 yOrigin,u32 wd,u32 ht)3866 void GX_SetScissor(u32 xOrigin,u32 yOrigin,u32 wd,u32 ht)
3867 {
3868 	u32 xo = xOrigin+0x156;
3869 	u32 yo = yOrigin+0x156;
3870 	u32 nwd = xo+(wd-1);
3871 	u32 nht = yo+(ht-1);
3872 
3873 	__gx->sciTLcorner = (__gx->sciTLcorner&~0x7ff)|(yo&0x7ff);
3874 	__gx->sciTLcorner = (__gx->sciTLcorner&~0x7FF000)|(_SHIFTL(xo,12,11));
3875 
3876 	__gx->sciBRcorner = (__gx->sciBRcorner&~0x7ff)|(nht&0xfff);
3877 	__gx->sciBRcorner = (__gx->sciBRcorner&~0x7FF000)|(_SHIFTL(nwd,12,11));
3878 
3879 	GX_LOAD_BP_REG(__gx->sciTLcorner);
3880 	GX_LOAD_BP_REG(__gx->sciBRcorner);
3881 }
3882 
GX_SetScissorBoxOffset(s32 xoffset,s32 yoffset)3883 void GX_SetScissorBoxOffset(s32 xoffset,s32 yoffset)
3884 {
3885 	s32 xoff = _SHIFTR((xoffset+0x156),1,24);
3886 	s32 yoff = _SHIFTR((yoffset+0x156),1,24);
3887 
3888 	GX_LOAD_BP_REG((0x59000000|(_SHIFTL(yoff,10,10))|(xoff&0x3ff)));
3889 }
3890 
GX_SetNumChans(u8 num)3891 void GX_SetNumChans(u8 num)
3892 {
3893 	__gx->genMode = (__gx->genMode&~0x70)|(_SHIFTL(num,4,3));
3894 	__gx->dirtyState |= 0x01000004;
3895 }
3896 
GX_SetTevOrder(u8 tevstage,u8 texcoord,u32 texmap,u8 color)3897 void GX_SetTevOrder(u8 tevstage,u8 texcoord,u32 texmap,u8 color)
3898 {
3899 	u8 colid;
3900 	u32 texm,texc,tmp;
3901 	u32 reg = 3+(_SHIFTR(tevstage,1,3));
3902 
3903 	__gx->tevTexMap[(tevstage&0xf)] = texmap;
3904 
3905 	texm = (texmap&~0x100);
3906 	if(texm>=GX_MAX_TEXMAP) texm = 0;
3907 	if(texcoord>=GX_MAXCOORD) {
3908 		texc = 0;
3909 		__gx->tevTexCoordEnable &= ~(_SHIFTL(1,tevstage,1));
3910 	} else {
3911 		texc = texcoord;
3912 		__gx->tevTexCoordEnable |= (_SHIFTL(1,tevstage,1));
3913 	}
3914 
3915 	if(tevstage&1) {
3916 		__gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x7000)|(_SHIFTL(texm,12,3));
3917 		__gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x38000)|(_SHIFTL(texc,15,3));
3918 
3919 		colid = GX_ALPHA_BUMP;
3920 		if(color!=GX_COLORNULL) colid = _gxtevcolid[color];
3921 		__gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x380000)|(_SHIFTL(colid,19,3));
3922 
3923 		tmp = 1;
3924 		if(texmap==GX_TEXMAP_NULL || texmap&0x100) tmp = 0;
3925 		__gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x40000)|(_SHIFTL(tmp,18,1));
3926 	} else {
3927 		__gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x7)|(texm&0x7);
3928 		__gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x38)|(_SHIFTL(texc,3,3));
3929 
3930 		colid = GX_ALPHA_BUMP;
3931 		if(color!=GX_COLORNULL) colid = _gxtevcolid[color];
3932 		__gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x380)|(_SHIFTL(colid,7,3));
3933 
3934 		tmp = 1;
3935 		if(texmap==GX_TEXMAP_NULL || texmap&0x100) tmp = 0;
3936 		__gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x40)|(_SHIFTL(tmp,6,1));
3937 	}
3938 	GX_LOAD_BP_REG(__gx->tevRasOrder[reg]);
3939 	__gx->dirtyState |= 0x0001;
3940 }
3941 
GX_SetNumTevStages(u8 num)3942 void GX_SetNumTevStages(u8 num)
3943 {
3944 	__gx->genMode = (__gx->genMode&~0x3C00)|(_SHIFTL((num-1),10,4));
3945 	__gx->dirtyState |= 0x0004;
3946 }
3947 
GX_SetAlphaCompare(u8 comp0,u8 ref0,u8 aop,u8 comp1,u8 ref1)3948 void GX_SetAlphaCompare(u8 comp0,u8 ref0,u8 aop,u8 comp1,u8 ref1)
3949 {
3950 	u32 val = 0;
3951 	val = (_SHIFTL(aop,22,2))|(_SHIFTL(comp1,19,3))|(_SHIFTL(comp0,16,3))|(_SHIFTL(ref1,8,8))|(ref0&0xff);
3952 	GX_LOAD_BP_REG(0xf3000000|val);
3953 }
3954 
GX_SetTevKColorSel(u8 tevstage,u8 sel)3955 void GX_SetTevKColorSel(u8 tevstage,u8 sel)
3956 {
3957 	u32 reg = (_SHIFTR(tevstage,1,3));
3958 
3959 	if(tevstage&1)
3960 		__gx->tevSwapModeTable[reg] = (__gx->tevSwapModeTable[reg]&~0x7C000)|(_SHIFTL(sel,14,5));
3961 	else
3962 		__gx->tevSwapModeTable[reg] = (__gx->tevSwapModeTable[reg]&~0x1F0)|(_SHIFTL(sel,4,5));
3963 	GX_LOAD_BP_REG(__gx->tevSwapModeTable[reg]);
3964 }
3965 
GX_SetTevKAlphaSel(u8 tevstage,u8 sel)3966 void GX_SetTevKAlphaSel(u8 tevstage,u8 sel)
3967 {
3968 	u32 reg = (_SHIFTR(tevstage,1,3));
3969 
3970 	if(tevstage&1)
3971 		__gx->tevSwapModeTable[reg] = (__gx->tevSwapModeTable[reg]&~0xF80000)|(_SHIFTL(sel,19,5));
3972 	else
3973 		__gx->tevSwapModeTable[reg] = (__gx->tevSwapModeTable[reg]&~0x3E00)|(_SHIFTL(sel,9,5));
3974 	GX_LOAD_BP_REG(__gx->tevSwapModeTable[reg]);
3975 }
3976 
GX_SetTevSwapMode(u8 tevstage,u8 ras_sel,u8 tex_sel)3977 void GX_SetTevSwapMode(u8 tevstage,u8 ras_sel,u8 tex_sel)
3978 {
3979 	u32 reg = (tevstage&0xf);
3980 	__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x3)|(ras_sel&0x3);
3981 	__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0xC)|(_SHIFTL(tex_sel,2,2));
3982 	GX_LOAD_BP_REG(__gx->tevAlphaEnv[reg]);
3983 }
3984 
GX_SetTevSwapModeTable(u8 swapid,u8 r,u8 g,u8 b,u8 a)3985 void GX_SetTevSwapModeTable(u8 swapid,u8 r,u8 g,u8 b,u8 a)
3986 {
3987 	u32 regA = 0+(_SHIFTL(swapid,1,3));
3988 	u32 regB = 1+(_SHIFTL(swapid,1,3));
3989 
3990 	__gx->tevSwapModeTable[regA] = (__gx->tevSwapModeTable[regA]&~0x3)|(r&0x3);
3991 	__gx->tevSwapModeTable[regA] = (__gx->tevSwapModeTable[regA]&~0xC)|(_SHIFTL(g,2,2));
3992 	GX_LOAD_BP_REG(__gx->tevSwapModeTable[regA]);
3993 
3994 	__gx->tevSwapModeTable[regB] = (__gx->tevSwapModeTable[regB]&~0x3)|(b&0x3);
3995 	__gx->tevSwapModeTable[regB] = (__gx->tevSwapModeTable[regB]&~0xC)|(_SHIFTL(a,2,2));
3996 	GX_LOAD_BP_REG(__gx->tevSwapModeTable[regB]);
3997 }
3998 
GX_SetTevIndirect(u8 tevstage,u8 indtexid,u8 format,u8 bias,u8 mtxid,u8 wrap_s,u8 wrap_t,u8 addprev,u8 utclod,u8 a)3999 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)
4000 {
4001 	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));
4002 	GX_LOAD_BP_REG(val);
4003 }
4004 
GX_SetTevDirect(u8 tevstage)4005 void GX_SetTevDirect(u8 tevstage)
4006 {
4007 	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);
4008 }
4009 
GX_SetNumIndStages(u8 nstages)4010 void GX_SetNumIndStages(u8 nstages)
4011 {
4012 	__gx->genMode = (__gx->genMode&~0x70000)|(_SHIFTL(nstages,16,3));
4013 	__gx->dirtyState |= 0x0006;
4014 }
4015 
GX_SetIndTexMatrix(u8 indtexmtx,f32 offset_mtx[2][3],s8 scale_exp)4016 void GX_SetIndTexMatrix(u8 indtexmtx,f32 offset_mtx[2][3],s8 scale_exp)
4017 {
4018 	u32 ma,mb;
4019 	u32 val,s,idx;
4020 
4021 	if(indtexmtx>0x00 && indtexmtx<0x04) indtexmtx -= 0x01;
4022 	else if(indtexmtx>0x04 && indtexmtx<0x08) indtexmtx -= 0x05;
4023 	else if(indtexmtx>0x08 && indtexmtx<0x0C) indtexmtx -= 0x09;
4024 	else indtexmtx = 0x00;
4025 
4026 	s = (scale_exp+17);
4027 	idx = ((indtexmtx<<2)-indtexmtx);
4028 
4029 	ma = (u32)(offset_mtx[0][0]*1024.0F);
4030 	mb = (u32)(offset_mtx[1][0]*1024.0F);
4031 	val = (_SHIFTL((0x06+idx),24,8)|_SHIFTL(s,22,2)|_SHIFTL(mb,11,11)|_SHIFTL(ma,0,11));
4032 	GX_LOAD_BP_REG(val);
4033 
4034 	ma = (u32)(offset_mtx[0][1]*1024.0F);
4035 	mb = (u32)(offset_mtx[1][1]*1024.0F);
4036 	val = (_SHIFTL((0x07+idx),24,8)|_SHIFTL((s>>2),22,2)|_SHIFTL(mb,11,11)|_SHIFTL(ma,0,11));
4037 	GX_LOAD_BP_REG(val);
4038 
4039 	ma = (u32)(offset_mtx[0][2]*1024.0F);
4040 	mb = (u32)(offset_mtx[1][2]*1024.0F);
4041 	val = (_SHIFTL((0x08+idx),24,8)|_SHIFTL((s>>4),22,2)|_SHIFTL(mb,11,11)|_SHIFTL(ma,0,11));
4042 	GX_LOAD_BP_REG(val);
4043 }
4044 
GX_SetTevIndBumpST(u8 tevstage,u8 indstage,u8 mtx_sel)4045 void GX_SetTevIndBumpST(u8 tevstage,u8 indstage,u8 mtx_sel)
4046 {
4047 	u8 sel_s,sel_t;
4048 
4049 	switch(mtx_sel) {
4050 		case GX_ITM_0:
4051 			sel_s = GX_ITM_S0;
4052 			sel_t = GX_ITM_T0;
4053 			break;
4054 		case GX_ITM_1:
4055 			sel_s = GX_ITM_S1;
4056 			sel_t = GX_ITM_T1;
4057 			break;
4058 		case GX_ITM_2:
4059 			sel_s = GX_ITM_S2;
4060 			sel_t = GX_ITM_T2;
4061 			break;
4062 		default:
4063 			sel_s = GX_ITM_OFF;
4064 			sel_t = GX_ITM_OFF;
4065 			break;
4066 	}
4067 
4068 	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);
4069 	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);
4070 	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);
4071 }
4072 
GX_SetTevIndBumpXYZ(u8 tevstage,u8 indstage,u8 mtx_sel)4073 void GX_SetTevIndBumpXYZ(u8 tevstage,u8 indstage,u8 mtx_sel)
4074 {
4075 	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);
4076 }
4077 
GX_SetTevIndRepeat(u8 tevstage)4078 void GX_SetTevIndRepeat(u8 tevstage)
4079 {
4080 	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);
4081 }
4082 
GX_SetIndTexCoordScale(u8 indtexid,u8 scale_s,u8 scale_t)4083 void GX_SetIndTexCoordScale(u8 indtexid,u8 scale_s,u8 scale_t)
4084 {
4085 	switch(indtexid) {
4086 		case GX_INDTEXSTAGE0:
4087 			__gx->tevRasOrder[0] = (__gx->tevRasOrder[0]&~0x0f)|(scale_s&0x0f);
4088 			__gx->tevRasOrder[0] = (__gx->tevRasOrder[0]&~0xF0)|(_SHIFTL(scale_t,4,4));
4089 			GX_LOAD_BP_REG(__gx->tevRasOrder[0]);
4090 			break;
4091 		case GX_INDTEXSTAGE1:
4092 			__gx->tevRasOrder[0] = (__gx->tevRasOrder[0]&~0xF00)|(_SHIFTL(scale_s,8,4));
4093 			__gx->tevRasOrder[0] = (__gx->tevRasOrder[0]&~0xF000)|(_SHIFTL(scale_t,12,4));
4094 			GX_LOAD_BP_REG(__gx->tevRasOrder[0]);
4095 			break;
4096 		case GX_INDTEXSTAGE2:
4097 			__gx->tevRasOrder[1] = (__gx->tevRasOrder[1]&~0x0f)|(scale_s&0x0f);
4098 			__gx->tevRasOrder[1] = (__gx->tevRasOrder[1]&~0xF0)|(_SHIFTL(scale_t,4,4));
4099 			GX_LOAD_BP_REG(__gx->tevRasOrder[1]);
4100 			break;
4101 		case GX_INDTEXSTAGE3:
4102 			__gx->tevRasOrder[1] = (__gx->tevRasOrder[1]&~0xF00)|(_SHIFTL(scale_s,8,4));
4103 			__gx->tevRasOrder[1] = (__gx->tevRasOrder[1]&~0xF000)|(_SHIFTL(scale_t,12,4));
4104 			GX_LOAD_BP_REG(__gx->tevRasOrder[1]);
4105 			break;
4106 	}
4107 }
4108 
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)4109 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)
4110 {
4111 	s32 wrap_s,wrap_t;
4112 	f32 offset_mtx[2][3];
4113 	f64 fdspace_x,fdspace_y;
4114 	u32 fbuf_x[2] = { 0x43300000,tilespacing_x };
4115 	u32 fbuf_y[2] = { 0x43300000,tilespacing_y };
4116 
4117 	wrap_s = GX_ITW_OFF;
4118 	if(tilesize_x==0x0010) wrap_s = GX_ITW_16;
4119 	else if(tilesize_x==0x0020) wrap_s = GX_ITW_32;
4120 	else if(tilesize_x==0x0040) wrap_s = GX_ITW_64;
4121 	else if(tilesize_x==0x0080) wrap_s = GX_ITW_128;
4122 	else if(tilesize_x==0x0100) wrap_s = GX_ITW_256;
4123 
4124 	wrap_t = GX_ITW_OFF;
4125 	if(tilesize_y==0x0010) wrap_t = GX_ITW_16;
4126 	else if(tilesize_y==0x0020) wrap_t = GX_ITW_32;
4127 	else if(tilesize_y==0x0040) wrap_t = GX_ITW_64;
4128 	else if(tilesize_y==0x0080) wrap_t = GX_ITW_128;
4129 	else if(tilesize_y==0x0100) wrap_t = GX_ITW_256;
4130 
4131 	fdspace_x = *(f64*)((void*)fbuf_x);
4132 	fdspace_y = *(f64*)((void*)fbuf_y);
4133 
4134 	offset_mtx[0][0] = (f32)((fdspace_x - 4503599627370496.0F)*0.00097656250F);
4135 	offset_mtx[0][1] = 0.0F;
4136 	offset_mtx[0][2] = 0.0F;
4137 	offset_mtx[1][0] = 0.0F;
4138 	offset_mtx[1][1] = (f32)((fdspace_y - 4503599627370496.0F)*0.00097656250F);
4139 	offset_mtx[1][2] = 0.0F;
4140 
4141 	GX_SetIndTexMatrix(indtexmtx,offset_mtx,10);
4142 	GX_SetTevIndirect(tevstage,indtexid,indtexfmt,bias_sel,indtexmtx,wrap_s,wrap_t,GX_FALSE,GX_TRUE,alpha_sel);
4143 }
4144 
GX_SetFog(u8 type,f32 startz,f32 endz,f32 nearz,f32 farz,GXColor col)4145 void GX_SetFog(u8 type,f32 startz,f32 endz,f32 nearz,f32 farz,GXColor col)
4146 {
4147     f32 A, B, B_mant, C, A_f;
4148     u32 b_expn, b_m, a_hex, c_hex,val,proj = 0;
4149 	union ieee32 { f32 f; u32 i; } v;
4150 
4151   	proj = _SHIFTR(type,3,1);
4152 
4153 	// Calculate constants a, b, and c (TEV HW requirements).
4154 	if(proj) { // Orthographic Fog Type
4155 		if((farz==nearz) || (endz==startz)) {
4156 			// take care of the odd-ball case.
4157 			A_f = 0.0f;
4158 			C = 0.0f;
4159 		} else {
4160 			A = 1.0f/(endz-startz);
4161 			A_f = (farz-nearz) * A;
4162 			C = (startz-nearz) * A;
4163 		}
4164 
4165 		b_expn	= 0;
4166 		b_m		= 0;
4167 	} else { // Perspective Fog Type
4168 	  // Calculate constants a, b, and c (TEV HW requirements).
4169 		if((farz==nearz) || (endz==startz)) {
4170 			// take care of the odd-ball case.
4171 			A = 0.0f;
4172 			B = 0.5f;
4173 			C = 0.0f;
4174 		} else {
4175 			A = (farz*nearz)/((farz-nearz)*(endz-startz));
4176 			B = farz/(farz-nearz);
4177 			C = startz/(endz-startz);
4178 		}
4179 
4180 		B_mant = B;
4181 		b_expn = 1;
4182 		while(B_mant>1.0f) {
4183 			B_mant /= 2.0f;
4184 			b_expn++;
4185 		}
4186 
4187 		while((B_mant>0.0f) && (B_mant<0.5f)) {
4188 			B_mant *= 2.0f;
4189 			b_expn--;
4190 		}
4191 
4192 		A_f   = A/(1<<(b_expn));
4193 		b_m   = (u32)(B_mant * 8388638.0f);
4194 	}
4195 	v.f = A_f;
4196     a_hex = v.i;
4197 
4198 	v.f = C;
4199     c_hex = v.i;
4200 
4201 	val = 0xee000000|(_SHIFTR(a_hex,12,20));
4202 	GX_LOAD_BP_REG(val);
4203 
4204 	val = 0xef000000|(b_m&0x00ffffff);
4205 	GX_LOAD_BP_REG(val);
4206 
4207 	val = 0xf0000000|(b_expn&0x1f);
4208 	GX_LOAD_BP_REG(val);
4209 
4210 	val = 0xf1000000|(_SHIFTL(type,21,3))|(_SHIFTL(proj,20,1))|(_SHIFTR(c_hex,12,20));
4211 	GX_LOAD_BP_REG(val);
4212 
4213 	val = 0xf2000000|(_SHIFTL(col.r,16,8))|(_SHIFTL(col.g,8,8))|(col.b&0xff);
4214 	GX_LOAD_BP_REG(val);
4215 }
4216 
GX_InitFogAdjTable(GXFogAdjTbl * table,u16 width,f32 projmtx[4][4])4217 void GX_InitFogAdjTable(GXFogAdjTbl *table,u16 width,f32 projmtx[4][4])
4218 {
4219 	u32 i,val7;
4220 	f32 val0,val1,val2,val4,val5,val6;
4221 
4222 	if(projmtx[3][3]==0.0f) {
4223 		val0 = projmtx[2][3]/(projmtx[2][2] - 1.0f);
4224 		val1 = val0/projmtx[0][0];
4225 	} else {
4226 		val1 = 1.0f/projmtx[0][0];
4227 		val0 = val1*1.7320499f;
4228 	}
4229 
4230 	val2 = val0*val0;
4231 	val4 = 2.0f/(f32)width;
4232 	for(i=0;i<10;i++) {
4233 		val5 = (i+1)*32.0f;
4234 		val5 *= val4;
4235 		val5 *= val1;
4236 		val5 *= val5;
4237 		val5 /= val2;
4238 		val6 = sqrtf(val5 + 1.0f);
4239 		val7 = (u32)(val6*256.0f);
4240 		table->r[i] = (val7&0x0fff);
4241 	}
4242 }
4243 
GX_SetFogRangeAdj(u8 enable,u16 center,GXFogAdjTbl * table)4244 void GX_SetFogRangeAdj(u8 enable,u16 center,GXFogAdjTbl *table)
4245 {
4246 	u32 val;
4247 
4248 	if(enable) {
4249 		val = 0xe9000000|(_SHIFTL(table->r[1],12,12))|(table->r[0]&0x0fff);
4250 		GX_LOAD_BP_REG(val);
4251 
4252 		val = 0xea000000|(_SHIFTL(table->r[3],12,12))|(table->r[2]&0x0fff);
4253 		GX_LOAD_BP_REG(val);
4254 
4255 		val = 0xeb000000|(_SHIFTL(table->r[5],12,12))|(table->r[4]&0x0fff);
4256 		GX_LOAD_BP_REG(val);
4257 
4258 		val = 0xec000000|(_SHIFTL(table->r[7],12,12))|(table->r[6]&0x0fff);
4259 		GX_LOAD_BP_REG(val);
4260 
4261 		val = 0xed000000|(_SHIFTL(table->r[9],12,12))|(table->r[8]&0x0fff);
4262 		GX_LOAD_BP_REG(val);
4263 	}
4264 	val = 0xe8000000|(_SHIFTL(enable,10,1))|((center + 342)&0x03ff);
4265 	GX_LOAD_BP_REG(val);
4266 }
4267 
GX_SetFogColor(GXColor color)4268 void GX_SetFogColor(GXColor color)
4269 {
4270 	GX_LOAD_BP_REG(0xf2000000|(_SHIFTL(color.r,16,8)|_SHIFTL(color.g,8,8)|(color.b&0xff)));
4271 }
4272 
GX_SetColorUpdate(u8 enable)4273 void GX_SetColorUpdate(u8 enable)
4274 {
4275 	__gx->peCMode0 = (__gx->peCMode0&~0x8)|(_SHIFTL(enable,3,1));
4276 	GX_LOAD_BP_REG(__gx->peCMode0);
4277 }
4278 
GX_SetAlphaUpdate(u8 enable)4279 void GX_SetAlphaUpdate(u8 enable)
4280 {
4281 	__gx->peCMode0 = (__gx->peCMode0&~0x10)|(_SHIFTL(enable,4,1));
4282 	GX_LOAD_BP_REG(__gx->peCMode0);
4283 }
4284 
GX_SetZCompLoc(u8 before_tex)4285 void GX_SetZCompLoc(u8 before_tex)
4286 {
4287 	__gx->peCntrl = (__gx->peCntrl&~0x40)|(_SHIFTL(before_tex,6,1));
4288 	GX_LOAD_BP_REG(__gx->peCntrl);
4289 }
4290 
GX_SetPixelFmt(u8 pix_fmt,u8 z_fmt)4291 void GX_SetPixelFmt(u8 pix_fmt,u8 z_fmt)
4292 {
4293 	u8 ms_en = 0;
4294 	u32 realfmt[8] = {0,1,2,3,4,4,4,5};
4295 
4296 	__gx->peCntrl = (__gx->peCntrl&~0x7)|(realfmt[pix_fmt]&0x7);
4297 	__gx->peCntrl = (__gx->peCntrl&~0x38)|(_SHIFTL(z_fmt,3,3));
4298 	GX_LOAD_BP_REG(__gx->peCntrl);
4299 	__gx->dirtyState |= 0x0004;
4300 
4301 	if(pix_fmt==GX_PF_RGB565_Z16) ms_en = 1;
4302 	__gx->genMode = (__gx->genMode&~0x200)|(_SHIFTL(ms_en,9,1));
4303 
4304 	if(realfmt[pix_fmt]==GX_PF_Y8) {
4305 		pix_fmt -= GX_PF_Y8;
4306 		__gx->peCMode1 = (__gx->peCMode1&~0xC00)|(_SHIFTL(pix_fmt,10,2));
4307 		GX_LOAD_BP_REG(__gx->peCMode1);
4308 	}
4309 }
4310 
GX_SetDither(u8 dither)4311 void GX_SetDither(u8 dither)
4312 {
4313 	__gx->peCMode0 = (__gx->peCMode0&~0x4)|(_SHIFTL(dither,2,1));
4314 	GX_LOAD_BP_REG(__gx->peCMode0);
4315 }
4316 
GX_SetDstAlpha(u8 enable,u8 a)4317 void GX_SetDstAlpha(u8 enable,u8 a)
4318 {
4319 	__gx->peCMode1 = (__gx->peCMode1&~0xff)|(a&0xff);
4320 	__gx->peCMode1 = (__gx->peCMode1&~0x100)|(_SHIFTL(enable,8,1));
4321 	GX_LOAD_BP_REG(__gx->peCMode1);
4322 }
4323 
GX_SetFieldMask(u8 even_mask,u8 odd_mask)4324 void GX_SetFieldMask(u8 even_mask,u8 odd_mask)
4325 {
4326 	u32 val = 0;
4327 
4328 	val = (_SHIFTL(even_mask,1,1))|(odd_mask&1);
4329 	GX_LOAD_BP_REG(0x44000000|val);
4330 }
4331 
GX_SetFieldMode(u8 field_mode,u8 half_aspect_ratio)4332 void GX_SetFieldMode(u8 field_mode,u8 half_aspect_ratio)
4333 {
4334 	__gx->lpWidth = (__gx->lpWidth&~0x400000)|(_SHIFTL(half_aspect_ratio,22,1));
4335 	GX_LOAD_BP_REG(__gx->lpWidth);
4336 
4337 	__GX_FlushTextureState();
4338 	GX_LOAD_BP_REG(0x68000000|(field_mode&1));
4339 	__GX_FlushTextureState();
4340 }
4341 
GX_PokeAlphaMode(u8 func,u8 threshold)4342 void GX_PokeAlphaMode(u8 func,u8 threshold)
4343 {
4344 	_peReg[3] = (_SHIFTL(func,8,8))|(threshold&0xFF);
4345 }
4346 
GX_PokeAlphaRead(u8 mode)4347 void GX_PokeAlphaRead(u8 mode)
4348 {
4349 	_peReg[4] = (mode&~0x4)|0x4;
4350 }
4351 
GX_PokeDstAlpha(u8 enable,u8 a)4352 void GX_PokeDstAlpha(u8 enable,u8 a)
4353 {
4354 	_peReg[2] = (_SHIFTL(enable,8,1))|(a&0xff);
4355 }
4356 
GX_PokeAlphaUpdate(u8 update_enable)4357 void GX_PokeAlphaUpdate(u8 update_enable)
4358 {
4359 	_peReg[1] = (_peReg[1]&~0x10)|(_SHIFTL(update_enable,4,1));
4360 }
4361 
GX_PokeColorUpdate(u8 update_enable)4362 void GX_PokeColorUpdate(u8 update_enable)
4363 {
4364 	_peReg[1] = (_peReg[1]&~0x8)|(_SHIFTL(update_enable,3,1));
4365 }
4366 
GX_PokeDither(u8 dither)4367 void GX_PokeDither(u8 dither)
4368 {
4369 	_peReg[1] = (_peReg[1]&~0x4)|(_SHIFTL(dither,2,1));
4370 }
4371 
GX_PokeBlendMode(u8 type,u8 src_fact,u8 dst_fact,u8 op)4372 void GX_PokeBlendMode(u8 type,u8 src_fact,u8 dst_fact,u8 op)
4373 {
4374 	u32 regval = _peReg[1];
4375 
4376 	regval = (regval&~0x1);
4377 	if(type==GX_BM_BLEND || type==GX_BM_SUBTRACT) regval |= 0x1;
4378 
4379 	regval = (regval&~0x800);
4380 	if(type==GX_BM_SUBTRACT) regval |= 0x800;
4381 
4382 	regval = (regval&~0x2);
4383 	if(type==GX_BM_LOGIC) regval |= 0x2;
4384 
4385 	regval = (regval&~0xF000)|(_SHIFTL(op,12,4));
4386 	regval = (regval&~0xE0)|(_SHIFTL(dst_fact,5,3));
4387 	regval = (regval&~0x700)|(_SHIFTL(src_fact,8,3));
4388 
4389 	regval |= 0x41000000;
4390 	_peReg[1] = (u16)regval;
4391 }
4392 
GX_PokeARGB(u16 x,u16 y,GXColor color)4393 void GX_PokeARGB(u16 x,u16 y,GXColor color)
4394 {
4395 	u32 regval;
4396 
4397 	regval = 0xc8000000|(_SHIFTL(x,2,10));
4398 	regval = (regval&~0x3FF000)|(_SHIFTL(y,12,10));
4399 	*(u32*)regval = _SHIFTL(color.a,24,8)|_SHIFTL(color.r,16,8)|_SHIFTL(color.g,8,8)|(color.b&0xff);
4400 }
4401 
GX_PeekARGB(u16 x,u16 y,GXColor * color)4402 void GX_PeekARGB(u16 x,u16 y,GXColor *color)
4403 {
4404 	u32 regval,val;
4405 
4406 	regval = 0xc8000000|(_SHIFTL(x,2,10));
4407 	regval = (regval&~0x3FF000)|(_SHIFTL(y,12,10));
4408 	val = *(u32*)regval;
4409 	color->a = _SHIFTR(val,24,8);
4410 	color->r = _SHIFTR(val,16,8);
4411 	color->g = _SHIFTR(val,8,8);
4412 	color->b = val&0xff;
4413 }
4414 
GX_PokeZ(u16 x,u16 y,u32 z)4415 void GX_PokeZ(u16 x,u16 y,u32 z)
4416 {
4417 	u32 regval;
4418 
4419 	regval = 0xc8000000|(_SHIFTL(x,2,10));
4420 	regval = (regval&~0x3FF000)|(_SHIFTL(y,12,10));
4421 	regval = (regval&~0xC00000)|0x400000;
4422 	*(u32*)regval = z;
4423 }
4424 
GX_PeekZ(u16 x,u16 y,u32 * z)4425 void GX_PeekZ(u16 x,u16 y,u32 *z)
4426 {
4427 	u32 regval;
4428 
4429 	regval = 0xc8000000|(_SHIFTL(x,2,10));
4430 	regval = (regval&~0x3FF000)|(_SHIFTL(y,12,10));
4431 	regval = (regval&~0xC00000)|0x400000;
4432 	*z = *(u32*)regval;
4433 }
4434 
GX_PokeZMode(u8 comp_enable,u8 func,u8 update_enable)4435 void GX_PokeZMode(u8 comp_enable,u8 func,u8 update_enable)
4436 {
4437 	u16 regval;
4438 	regval = comp_enable&0x1;
4439 	regval = (regval&~0xE)|(_SHIFTL(func,1,3));
4440 	regval = (regval&0x10)|(_SHIFTL(update_enable,4,1));
4441 	_peReg[0] = regval;
4442 }
4443 
GX_SetIndTexOrder(u8 indtexstage,u8 texcoord,u8 texmap)4444 void GX_SetIndTexOrder(u8 indtexstage,u8 texcoord,u8 texmap)
4445 {
4446 	switch(indtexstage) {
4447 		case GX_INDTEXSTAGE0:
4448 			__gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x7)|(texmap&0x7);
4449 			__gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x38)|(_SHIFTL(texcoord,3,3));
4450 			break;
4451 		case GX_INDTEXSTAGE1:
4452 			__gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x1C0)|(_SHIFTL(texmap,6,3));
4453 			__gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0xE00)|(_SHIFTL(texcoord,9,3));
4454 			break;
4455 		case GX_INDTEXSTAGE2:
4456 			__gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x7000)|(_SHIFTL(texmap,12,3));
4457 			__gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x38000)|(_SHIFTL(texcoord,15,3));
4458 			break;
4459 		case GX_INDTEXSTAGE3:
4460 			__gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x1C0000)|(_SHIFTL(texmap,18,3));
4461 			__gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0xE00000)|(_SHIFTL(texcoord,21,3));
4462 			break;
4463 	}
4464 	GX_LOAD_BP_REG(__gx->tevRasOrder[2]);
4465 	__gx->dirtyState |= 0x0003;
4466 }
4467 
GX_InitLightPos(GXLightObj * lit_obj,f32 x,f32 y,f32 z)4468 void GX_InitLightPos(GXLightObj *lit_obj,f32 x,f32 y,f32 z)
4469 {
4470 	struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4471 
4472 	lit->px = x;
4473 	lit->py = y;
4474 	lit->pz = z;
4475 }
4476 
GX_InitLightColor(GXLightObj * lit_obj,GXColor col)4477 void GX_InitLightColor(GXLightObj *lit_obj,GXColor col)
4478 {
4479 	struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4480 	lit->col = ((_SHIFTL(col.r,24,8))|(_SHIFTL(col.g,16,8))|(_SHIFTL(col.b,8,8))|(col.a&0xff));
4481 }
4482 
GX_LoadLightObj(GXLightObj * lit_obj,u8 lit_id)4483 void GX_LoadLightObj(GXLightObj *lit_obj,u8 lit_id)
4484 {
4485 	u32 id;
4486 	u16 reg;
4487 	struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4488 
4489 	switch(lit_id) {
4490 		case GX_LIGHT0:
4491 			id = 0;
4492 			break;
4493 		case GX_LIGHT1:
4494 			id = 1;
4495 			break;
4496 		case GX_LIGHT2:
4497 			id = 2;
4498 			break;
4499 		case GX_LIGHT3:
4500 			id = 3;
4501 			break;
4502 		case GX_LIGHT4:
4503 			id = 4;
4504 			break;
4505 		case GX_LIGHT5:
4506 			id = 5;
4507 			break;
4508 		case GX_LIGHT6:
4509 			id = 6;
4510 			break;
4511 		case GX_LIGHT7:
4512 			id = 7;
4513 			break;
4514 		default:
4515 			id = 0;
4516 			break;
4517 	}
4518 
4519 	reg = 0x600|(_SHIFTL(id,4,8));
4520 	GX_LOAD_XF_REGS(reg,16);
4521 	wgPipe->U32 = 0;
4522 	wgPipe->U32 = 0;
4523 	wgPipe->U32 = 0;
4524 	wgPipe->U32 = lit->col;
4525 	wgPipe->F32 = lit->a0;
4526 	wgPipe->F32 = lit->a1;
4527 	wgPipe->F32 = lit->a2;
4528 	wgPipe->F32 = lit->k0;
4529 	wgPipe->F32 = lit->k1;
4530 	wgPipe->F32 = lit->k2;
4531 	wgPipe->F32 = lit->px;
4532 	wgPipe->F32 = lit->py;
4533 	wgPipe->F32 = lit->pz;
4534 	wgPipe->F32 = lit->nx;
4535 	wgPipe->F32 = lit->ny;
4536 	wgPipe->F32 = lit->nz;
4537 }
4538 
GX_LoadLightObjIdx(u32 litobjidx,u8 litid)4539 void GX_LoadLightObjIdx(u32 litobjidx,u8 litid)
4540 {
4541 	u32 reg;
4542 	u32 idx = 0;
4543 
4544 	switch(litid) {
4545 		case GX_LIGHT0:
4546 			idx = 0;
4547 			break;
4548 		case GX_LIGHT1:
4549 			idx = 1;
4550 			break;
4551 		case GX_LIGHT2:
4552 			idx = 2;
4553 			break;
4554 		case GX_LIGHT3:
4555 			idx = 3;
4556 			break;
4557 		case GX_LIGHT4:
4558 			idx = 4;
4559 			break;
4560 		case GX_LIGHT5:
4561 			idx = 5;
4562 			break;
4563 		case GX_LIGHT6:
4564 			idx = 6;
4565 			break;
4566 		case GX_LIGHT7:
4567 			idx = 7;
4568 			break;
4569 		default:
4570 			idx = 0;
4571 			break;
4572 
4573 	}
4574 
4575 	reg = 0xf600|(_SHIFTL(idx,4,8));
4576 	reg = (reg&~0xffff0000)|(_SHIFTL(litobjidx,16,16));
4577 
4578 	wgPipe->U8 = 0x38;
4579 	wgPipe->U32 = reg;
4580 }
4581 
GX_InitLightDir(GXLightObj * lit_obj,f32 nx,f32 ny,f32 nz)4582 void GX_InitLightDir(GXLightObj *lit_obj,f32 nx,f32 ny,f32 nz)
4583 {
4584 	struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4585 
4586 	lit->nx = -(nx);
4587 	lit->ny = -(ny);
4588 	lit->nz = -(nz);
4589 }
4590 
GX_InitLightDistAttn(GXLightObj * lit_obj,f32 ref_dist,f32 ref_brite,u8 dist_fn)4591 void GX_InitLightDistAttn(GXLightObj *lit_obj,f32 ref_dist,f32 ref_brite,u8 dist_fn)
4592 {
4593 	f32 k0,k1,k2;
4594 	struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4595 
4596 	if(ref_dist<0.0f ||
4597 		ref_brite<0.0f || ref_brite>=1.0f) dist_fn = GX_DA_OFF;
4598 
4599 	switch(dist_fn) {
4600 		case GX_DA_GENTLE:
4601 			k0 = 1.0f;
4602 			k1 = (1.0f-ref_brite)/(ref_brite*ref_dist);
4603 			k2 = 0.0f;
4604 			break;
4605 		case GX_DA_MEDIUM:
4606 			k0 = 1.0f;
4607 			k1 = 0.5f*(1.0f-ref_brite)/(ref_brite*ref_dist);
4608 			k2 = 0.5f*(1.0f-ref_brite)/(ref_brite*ref_dist*ref_dist);
4609 			break;
4610 		case GX_DA_STEEP:
4611 			k0 = 1.0f;
4612 			k1 = 0.0f;
4613 			k2 = (1.0f-ref_brite)/(ref_brite*ref_dist*ref_dist);
4614 			break;
4615 		case GX_DA_OFF:
4616 		default:
4617 			k0 = 1.0f;
4618 			k1 = 0.0f;
4619 			k2 = 0.0f;
4620 			break;
4621 	}
4622 
4623 	lit->k0 = k0;
4624 	lit->k1 = k1;
4625 	lit->k2 = k2;
4626 }
4627 
GX_InitLightAttn(GXLightObj * lit_obj,f32 a0,f32 a1,f32 a2,f32 k0,f32 k1,f32 k2)4628 void GX_InitLightAttn(GXLightObj *lit_obj,f32 a0,f32 a1,f32 a2,f32 k0,f32 k1,f32 k2)
4629 {
4630 	struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4631 
4632 	lit->a0 = a0;
4633 	lit->a1 = a1;
4634 	lit->a2 = a2;
4635 	lit->k0 = k0;
4636 	lit->k1 = k1;
4637 	lit->k2 = k2;
4638 }
4639 
GX_InitLightAttnA(GXLightObj * lit_obj,f32 a0,f32 a1,f32 a2)4640 void GX_InitLightAttnA(GXLightObj *lit_obj,f32 a0,f32 a1,f32 a2)
4641 {
4642 	struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4643 
4644 	lit->a0 = a0;
4645 	lit->a1 = a1;
4646 	lit->a2 = a2;
4647 }
4648 
GX_InitLightAttnK(GXLightObj * lit_obj,f32 k0,f32 k1,f32 k2)4649 void GX_InitLightAttnK(GXLightObj *lit_obj,f32 k0,f32 k1,f32 k2)
4650 {
4651 	struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4652 
4653 	lit->k0 = k0;
4654 	lit->k1 = k1;
4655 	lit->k2 = k2;
4656 }
4657 
GX_InitSpecularDirHA(GXLightObj * lit_obj,f32 nx,f32 ny,f32 nz,f32 hx,f32 hy,f32 hz)4658 void GX_InitSpecularDirHA(GXLightObj *lit_obj,f32 nx,f32 ny,f32 nz,f32 hx,f32 hy,f32 hz)
4659 {
4660     f32 px, py, pz;
4661 	struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4662 
4663     px = (nx * LARGE_NUMBER);
4664     py = (ny * LARGE_NUMBER);
4665     pz = (nz * LARGE_NUMBER);
4666 
4667 	lit->px = px;
4668 	lit->py = py;
4669 	lit->pz = pz;
4670 	lit->nx = hx;
4671 	lit->ny = hy;
4672 	lit->nz = hz;
4673 }
4674 
GX_InitSpecularDir(GXLightObj * lit_obj,f32 nx,f32 ny,f32 nz)4675 void GX_InitSpecularDir(GXLightObj *lit_obj,f32 nx,f32 ny,f32 nz)
4676 {
4677     f32 px, py, pz;
4678     f32 hx, hy, hz, mag;
4679 	struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4680 
4681     // Compute half-angle vector
4682     hx  = -nx;
4683     hy  = -ny;
4684     hz  = (-nz + 1.0f);
4685 	mag = ((hx * hx) + (hy * hy) + (hz * hz));
4686 	if(mag!=0.0f) mag = 1.0f / sqrtf(mag);
4687 
4688     hx *= mag;
4689     hy *= mag;
4690     hz *= mag;
4691 
4692     px  = (nx * LARGE_NUMBER);
4693     py  = (ny * LARGE_NUMBER);
4694     pz  = (nz * LARGE_NUMBER);
4695 
4696 	lit->px = px;
4697 	lit->py = py;
4698 	lit->pz = pz;
4699 	lit->nx = hx;
4700 	lit->ny = hy;
4701 	lit->nz = hz;
4702 }
4703 
GX_InitLightSpot(GXLightObj * lit_obj,f32 cut_off,u8 spotfn)4704 void GX_InitLightSpot(GXLightObj *lit_obj,f32 cut_off,u8 spotfn)
4705 {
4706 	f32 r,d,cr,a0,a1,a2;
4707 	struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
4708 
4709 	if(cut_off<0.0f ||	cut_off>90.0f) spotfn = GX_SP_OFF;
4710 
4711 	r = (cut_off*M_PI)/180.0f;
4712 	cr = cosf(r);
4713 
4714 	switch(spotfn) {
4715 		case GX_SP_FLAT:
4716 			a0 = -1000.0f*cr;
4717 			a1 = 1000.0f;
4718 			a2 = 0.0f;
4719 			break;
4720 		case GX_SP_COS:
4721 			a0 = -cr/(1.0f-cr);
4722 			a1 = 1.0f/(1.0f-cr);
4723 			a2 = 0.0f;
4724 			break;
4725 		case GX_SP_COS2:
4726 			a0 = 0.0f;
4727 			a1 = -cr/(1.0f-cr);
4728 			a2 = 1.0f/(1.0f-cr);
4729 			break;
4730 		case GX_SP_SHARP:
4731 			d = (1.0f-cr)*(1.0f-cr);
4732 			a0 = cr*(cr-2.0f);
4733 			a1 = 2.0f/d;
4734 			a2 = -1.0/d;
4735 			break;
4736 		case GX_SP_RING1:
4737 			d = (1.0f-cr)*(1.0f-cr);
4738 			a0 = -4.0f*cr/d;
4739 			a1 = 4.0f*(1.0f+cr)/d;
4740 			a2 = -4.0f/d;
4741 			break;
4742 		case GX_SP_RING2:
4743 			d = (1.0f-cr)*(1.0f-cr);
4744 			a0 = 1.0f-2.0f*cr*cr/d;
4745 			a1 = 4.0f*cr/d;
4746 			a2 = -2.0f/d;
4747 			break;
4748 		case GX_SP_OFF:
4749 		default:
4750 			a0 = 1.0f;
4751 			a1 = 0.0f;
4752 			a2 = 0.0f;
4753 			break;
4754 	}
4755 
4756 	lit->a0 = a0;
4757 	lit->a1 = a1;
4758 	lit->a2 = a2;
4759 }
4760 
GX_SetGPMetric(u32 perf0,u32 perf1)4761 void GX_SetGPMetric(u32 perf0,u32 perf1)
4762 {
4763 	// check last setted perf0 counters
4764 	if(__gx->perf0Mode>=GX_PERF0_TRIANGLES && __gx->perf0Mode<GX_PERF0_QUAD_0CVG)
4765 		GX_LOAD_BP_REG(0x23000000);
4766 	else if(__gx->perf0Mode>=GX_PERF0_QUAD_0CVG && __gx->perf0Mode<GX_PERF0_CLOCKS)
4767 		GX_LOAD_BP_REG(0x24000000);
4768 	else if(__gx->perf0Mode>=GX_PERF0_VERTICES && __gx->perf0Mode<=GX_PERF0_CLOCKS)
4769 		GX_LOAD_XF_REG(0x1006,0);
4770 
4771 	// check last setted perf1 counters
4772 	if(__gx->perf1Mode>=GX_PERF1_VC_ELEMQ_FULL && __gx->perf1Mode<GX_PERF1_FIFO_REQ) {
4773 		__gx->cpPerfMode = (__gx->cpPerfMode&~0xf0);
4774 		GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4775 	} else if(__gx->perf1Mode>=GX_PERF1_FIFO_REQ && __gx->perf1Mode<GX_PERF1_CLOCKS) {
4776 		_cpReg[3] = 0;
4777 	} else if(__gx->perf1Mode>=GX_PERF1_TEXELS && __gx->perf1Mode<=GX_PERF1_CLOCKS) {
4778 		GX_LOAD_BP_REG(0x67000000);
4779 	}
4780 
4781 	__gx->perf0Mode = perf0;
4782 	switch(__gx->perf0Mode) {
4783 		case GX_PERF0_CLOCKS:
4784 			GX_LOAD_XF_REG(0x1006,0x00000273);
4785 			break;
4786 		case GX_PERF0_VERTICES:
4787 			GX_LOAD_XF_REG(0x1006,0x0000014a);
4788 			break;
4789 		case GX_PERF0_CLIP_VTX:
4790 			GX_LOAD_XF_REG(0x1006,0x0000016b);
4791 			break;
4792 		case GX_PERF0_CLIP_CLKS:
4793 			GX_LOAD_XF_REG(0x1006,0x00000084);
4794 			break;
4795 		case GX_PERF0_XF_WAIT_IN:
4796 			GX_LOAD_XF_REG(0x1006,0x000000c6);
4797 			break;
4798 		case GX_PERF0_XF_WAIT_OUT:
4799 			GX_LOAD_XF_REG(0x1006,0x00000210);
4800 			break;
4801 		case GX_PERF0_XF_XFRM_CLKS:
4802 			GX_LOAD_XF_REG(0x1006,0x00000252);
4803 			break;
4804 		case GX_PERF0_XF_LIT_CLKS:
4805 			GX_LOAD_XF_REG(0x1006,0x00000231);
4806 			break;
4807 		case GX_PERF0_XF_BOT_CLKS:
4808 			GX_LOAD_XF_REG(0x1006,0x000001ad);
4809 			break;
4810 		case GX_PERF0_XF_REGLD_CLKS:
4811 			GX_LOAD_XF_REG(0x1006,0x000001ce);
4812 			break;
4813 		case GX_PERF0_XF_REGRD_CLKS:
4814 			GX_LOAD_XF_REG(0x1006,0x00000021);
4815 			break;
4816 		case GX_PERF0_CLIP_RATIO:
4817 			GX_LOAD_XF_REG(0x1006,0x00000153);
4818 			break;
4819 		case GX_PERF0_TRIANGLES:
4820 			GX_LOAD_BP_REG(0x2300AE7F);
4821 			break;
4822 		case GX_PERF0_TRIANGLES_CULLED:
4823 			GX_LOAD_BP_REG(0x23008E7F);
4824 			break;
4825 		case GX_PERF0_TRIANGLES_PASSED:
4826 			GX_LOAD_BP_REG(0x23009E7F);
4827 			break;
4828 		case GX_PERF0_TRIANGLES_SCISSORED:
4829 			GX_LOAD_BP_REG(0x23001E7F);
4830 			break;
4831 		case GX_PERF0_TRIANGLES_0TEX:
4832 			GX_LOAD_BP_REG(0x2300AC3F);
4833 			break;
4834 		case GX_PERF0_TRIANGLES_1TEX:
4835 			GX_LOAD_BP_REG(0x2300AC7F);
4836 			break;
4837 		case GX_PERF0_TRIANGLES_2TEX:
4838 			GX_LOAD_BP_REG(0x2300ACBF);
4839 			break;
4840 		case GX_PERF0_TRIANGLES_3TEX:
4841 			GX_LOAD_BP_REG(0x2300ACFF);
4842 			break;
4843 		case GX_PERF0_TRIANGLES_4TEX:
4844 			GX_LOAD_BP_REG(0x2300AD3F);
4845 			break;
4846 		case GX_PERF0_TRIANGLES_5TEX:
4847 			GX_LOAD_BP_REG(0x2300AD7F);
4848 			break;
4849 		case GX_PERF0_TRIANGLES_6TEX:
4850 			GX_LOAD_BP_REG(0x2300ADBF);
4851 			break;
4852 		case GX_PERF0_TRIANGLES_7TEX:
4853 			GX_LOAD_BP_REG(0x2300ADFF);
4854 			break;
4855 		case GX_PERF0_TRIANGLES_8TEX:
4856 			GX_LOAD_BP_REG(0x2300AE3F);
4857 			break;
4858 		case GX_PERF0_TRIANGLES_0CLR:
4859 			GX_LOAD_BP_REG(0x2300A27F);
4860 			break;
4861 		case GX_PERF0_TRIANGLES_1CLR:
4862 			GX_LOAD_BP_REG(0x2300A67F);
4863 			break;
4864 		case GX_PERF0_TRIANGLES_2CLR:
4865 			GX_LOAD_BP_REG(0x2300AA7F);
4866 			break;
4867 		case GX_PERF0_QUAD_0CVG:
4868 			GX_LOAD_BP_REG(0x2402C0C6);
4869 			break;
4870 		case GX_PERF0_QUAD_NON0CVG:
4871 			GX_LOAD_BP_REG(0x2402C16B);
4872 			break;
4873 		case GX_PERF0_QUAD_1CVG:
4874 			GX_LOAD_BP_REG(0x2402C0E7);
4875 			break;
4876 		case GX_PERF0_QUAD_2CVG:
4877 			GX_LOAD_BP_REG(0x2402C108);
4878 			break;
4879 		case GX_PERF0_QUAD_3CVG:
4880 			GX_LOAD_BP_REG(0x2402C129);
4881 			break;
4882 		case GX_PERF0_QUAD_4CVG:
4883 			GX_LOAD_BP_REG(0x2402C14A);
4884 			break;
4885 		case GX_PERF0_AVG_QUAD_CNT:
4886 			GX_LOAD_BP_REG(0x2402C1AD);
4887 			break;
4888 		case GX_PERF0_NONE:
4889 			break;
4890 	}
4891 
4892 	__gx->perf1Mode = perf1;
4893 	switch(__gx->perf1Mode) {
4894 		case GX_PERF1_CLOCKS:
4895 			GX_LOAD_BP_REG(0x67000042);
4896 			break;
4897 		case GX_PERF1_TEXELS:
4898 			GX_LOAD_BP_REG(0x67000084);
4899 			break;
4900 		case GX_PERF1_TX_IDLE:
4901 			GX_LOAD_BP_REG(0x67000063);
4902 			break;
4903 		case GX_PERF1_TX_REGS:
4904 			GX_LOAD_BP_REG(0x67000129);
4905 			break;
4906 		case GX_PERF1_TX_MEMSTALL:
4907 			GX_LOAD_BP_REG(0x67000252);
4908 			break;
4909 		case GX_PERF1_TC_CHECK1_2:
4910 			GX_LOAD_BP_REG(0x67000021);
4911 			break;
4912 		case GX_PERF1_TC_CHECK3_4:
4913 			GX_LOAD_BP_REG(0x6700014b);
4914 			break;
4915 		case GX_PERF1_TC_CHECK5_6:
4916 			GX_LOAD_BP_REG(0x6700018d);
4917 			break;
4918 		case GX_PERF1_TC_CHECK7_8:
4919 			GX_LOAD_BP_REG(0x670001cf);
4920 			break;
4921 		case GX_PERF1_TC_MISS:
4922 			GX_LOAD_BP_REG(0x67000211);
4923 			break;
4924 		case GX_PERF1_VC_ELEMQ_FULL:
4925 			__gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x20;
4926 			GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4927 			break;
4928 		case GX_PERF1_VC_MISSQ_FULL:
4929 			__gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x30;
4930 			GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4931 			break;
4932 		case GX_PERF1_VC_MEMREQ_FULL:
4933 			__gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x40;
4934 			GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4935 			break;
4936 		case GX_PERF1_VC_STATUS7:
4937 			__gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x50;
4938 			GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4939 			break;
4940 		case GX_PERF1_VC_MISSREP_FULL:
4941 			__gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x60;
4942 			GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4943 			break;
4944 		case GX_PERF1_VC_STREAMBUF_LOW:
4945 			__gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x70;
4946 			GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4947 			break;
4948 		case GX_PERF1_VC_ALL_STALLS:
4949 			__gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x90;
4950 			GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4951 			break;
4952 		case GX_PERF1_VERTICES:
4953 			__gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x80;
4954 			GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
4955 			break;
4956 		case GX_PERF1_FIFO_REQ:
4957 			_cpReg[3] = 2;
4958 			break;
4959 		case GX_PERF1_CALL_REQ:
4960 			_cpReg[3] = 3;
4961 			break;
4962 		case GX_PERF1_VC_MISS_REQ:
4963 			_cpReg[3] = 4;
4964 			break;
4965 		case GX_PERF1_CP_ALL_REQ:
4966 			_cpReg[3] = 5;
4967 			break;
4968 		case GX_PERF1_NONE:
4969 			break;
4970 	}
4971 
4972 }
4973 
GX_ClearGPMetric()4974 void GX_ClearGPMetric()
4975 {
4976 	_cpReg[2] = 4;
4977 }
4978 
GX_InitXfRasMetric()4979 void GX_InitXfRasMetric()
4980 {
4981 	GX_LOAD_BP_REG(0x2402C022);
4982 	GX_LOAD_XF_REG(0x1006,0x31000);
4983 }
4984 
GX_ReadXfRasMetric(u32 * xfwaitin,u32 * xfwaitout,u32 * rasbusy,u32 * clks)4985 void GX_ReadXfRasMetric(u32 *xfwaitin,u32 *xfwaitout,u32 *rasbusy,u32 *clks)
4986 {
4987 	*rasbusy = _SHIFTL(_cpReg[33],16,16)|(_cpReg[32]&0xffff);
4988 	*clks = _SHIFTL(_cpReg[35],16,16)|(_cpReg[34]&0xffff);
4989 	*xfwaitin = _SHIFTL(_cpReg[37],16,16)|(_cpReg[36]&0xffff);
4990 	*xfwaitout = _SHIFTL(_cpReg[39],16,16)|(_cpReg[38]&0xffff);
4991 }
4992 
GX_ReadClksPerVtx()4993 u32 GX_ReadClksPerVtx()
4994 {
4995 	GX_DrawDone();
4996 	_cpReg[49] = 0x1007;
4997 	_cpReg[48] = 0x1007;
4998 	return (_cpReg[50]<<8);
4999 }
5000 
GX_ClearVCacheMetric()5001 void GX_ClearVCacheMetric()
5002 {
5003 	GX_LOAD_CP_REG(0,0);
5004 }
5005 
GX_ReadVCacheMetric(u32 * check,u32 * miss,u32 * stall)5006 void GX_ReadVCacheMetric(u32 *check,u32 *miss,u32 *stall)
5007 {
5008 	*check = _SHIFTL(_cpReg[41],16,16)|(_cpReg[40]&0xffff);
5009 	*miss = _SHIFTL(_cpReg[43],16,16)|(_cpReg[42]&0xffff);
5010 	*stall = _SHIFTL(_cpReg[45],16,16)|(_cpReg[44]&0xffff);
5011 }
5012 
GX_SetVCacheMetric(u32 attr)5013 void GX_SetVCacheMetric(u32 attr)
5014 {
5015 }
5016 
GX_GetGPStatus(u8 * overhi,u8 * underlow,u8 * readIdle,u8 * cmdIdle,u8 * brkpt)5017 void GX_GetGPStatus(u8 *overhi,u8 *underlow,u8 *readIdle,u8 *cmdIdle,u8 *brkpt)
5018 {
5019 	_gxgpstatus = _cpReg[0];
5020 	*overhi = !!(_gxgpstatus&1);
5021 	*underlow = !!(_gxgpstatus&2);
5022 	*readIdle = !!(_gxgpstatus&4);
5023 	*cmdIdle = !!(_gxgpstatus&8);
5024 	*brkpt = !!(_gxgpstatus&16);
5025 }
5026 
GX_ReadGPMetric(u32 * cnt0,u32 * cnt1)5027 void GX_ReadGPMetric(u32 *cnt0,u32 *cnt1)
5028 {
5029 	u32 tmp,reg1,reg2;
5030 
5031 	reg1 = (_SHIFTL(_cpReg[33],16,16))|(_cpReg[32]&0xffff);
5032 	reg2 = (_SHIFTL(_cpReg[35],16,16))|(_cpReg[34]&0xffff);
5033 	//reg3 = (_SHIFTL(_cpReg[37],16,16))|(_cpReg[36]&0xffff);
5034 	//reg4 = (_SHIFTL(_cpReg[39],16,16))|(_cpReg[38]&0xffff);
5035 
5036 	*cnt0 = 0;
5037 	if(__gx->perf0Mode==GX_PERF0_CLIP_RATIO) {
5038 		tmp = reg2*1000;
5039 		*cnt0 = tmp/reg1;
5040 	} else if(__gx->perf0Mode>=GX_PERF0_VERTICES && __gx->perf0Mode<GX_PERF0_NONE) *cnt0 = reg1;
5041 
5042 	//further implementation needed.....
5043 	// cnt1 fails....
5044 }
5045 
GX_AdjustForOverscan(GXRModeObj * rmin,GXRModeObj * rmout,u16 hor,u16 ver)5046 void GX_AdjustForOverscan(GXRModeObj *rmin,GXRModeObj *rmout,u16 hor,u16 ver)
5047 {
5048 	if(rmin!=rmout) memcpy(rmout,rmin,sizeof(GXRModeObj));
5049 
5050 	rmout->fbWidth = rmin->fbWidth-(hor<<1);
5051 	rmout->efbHeight = rmin->efbHeight-((rmin->efbHeight*(ver<<1))/rmin->xfbHeight);
5052 	if(rmin->xfbMode==VI_XFBMODE_SF && !(rmin->viTVMode&VI_PROGRESSIVE)) rmout->xfbHeight = rmin->xfbHeight-ver;
5053 	else rmout->xfbHeight = rmin->xfbHeight-(ver<<1);
5054 
5055 	rmout->viWidth = rmin->viWidth-(hor<<1);
5056 	if(rmin->viTVMode&VI_PROGRESSIVE) rmout->viHeight = rmin->viHeight-(ver<<2);
5057 	else rmout->viHeight = rmin->viHeight-(ver<<1);
5058 
5059 	rmout->viXOrigin += hor;
5060 	rmout->viYOrigin += ver;
5061 }
5062 
GX_GetYScaleFactor(u16 efbHeight,u16 xfbHeight)5063 f32 GX_GetYScaleFactor(u16 efbHeight,u16 xfbHeight)
5064 {
5065 	u32 yScale,xfblines,cnt;
5066 	f32 yscale;
5067 
5068 	yscale = (f32)efbHeight/(f32)xfbHeight;
5069 	yScale = (u32)((f32)256.0/yscale)&0x1ff;
5070 
5071 	cnt = xfbHeight;
5072 	xfblines = __GX_GetNumXfbLines(efbHeight,yScale);
5073 	while(xfblines>=xfbHeight) {
5074 		yscale = (f32)(cnt--)/(f32)efbHeight;
5075 		yScale = (u32)((f32)256.0/yscale)&0x1ff;
5076 		xfblines = __GX_GetNumXfbLines(efbHeight,yScale);
5077 	}
5078 
5079 	while(xfblines<xfbHeight) {
5080 		yscale = (f32)(cnt++)/(f32)efbHeight;
5081 		yScale = (u32)((f32)256.0/yscale)&0x1ff;
5082 		xfblines = __GX_GetNumXfbLines(efbHeight,yScale);
5083 	}
5084 	return yscale;
5085 }
5086 
GX_ReadBoundingBox(u16 * top,u16 * bottom,u16 * left,u16 * right)5087 void GX_ReadBoundingBox(u16 *top,u16 *bottom,u16 *left,u16 *right)
5088 {
5089 	*left = _peReg[8];
5090 	*right = _peReg[9];
5091 	*top = _peReg[10];
5092 	*bottom = _peReg[11];
5093 }
5094 
5095 #undef LARGE_NUMBER
5096