mirror of
https://github.com/libretro/RetroArch
synced 2025-03-24 04:44:02 +00:00
5100 lines
127 KiB
C
5100 lines
127 KiB
C
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <math.h>
|
|
#include "asm.h"
|
|
#include "processor.h"
|
|
#include "irq.h"
|
|
#include "lwp.h"
|
|
#include "system.h"
|
|
#include "video.h"
|
|
#include "video_types.h"
|
|
#include "lwp_watchdog.h"
|
|
#include "gx.h"
|
|
#include "gx_regdef.h"
|
|
|
|
#define TEXCACHE_TESTING
|
|
|
|
|
|
#define GX_FINISH 2
|
|
|
|
#if defined(HW_DOL)
|
|
#define LARGE_NUMBER (-1048576.0f)
|
|
#elif defined(HW_RVL)
|
|
#define LARGE_NUMBER (-1.0e+18f)
|
|
#endif
|
|
|
|
#define _SHIFTL(v, s, w) \
|
|
((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
|
|
#define _SHIFTR(v, s, w) \
|
|
((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
|
|
|
|
#define GX_LOAD_BP_REG(x) \
|
|
do { \
|
|
wgPipe->U8 = 0x61; \
|
|
asm volatile ("" ::: "memory" ); \
|
|
wgPipe->U32 = (u32)(x); \
|
|
asm volatile ("" ::: "memory" ); \
|
|
} while(0)
|
|
|
|
#define GX_LOAD_CP_REG(x, y) \
|
|
do { \
|
|
wgPipe->U8 = 0x08; \
|
|
asm volatile ("" ::: "memory" ); \
|
|
wgPipe->U8 = (u8)(x); \
|
|
asm volatile ("" ::: "memory" ); \
|
|
wgPipe->U32 = (u32)(y); \
|
|
asm volatile ("" ::: "memory" ); \
|
|
} while(0)
|
|
|
|
#define GX_LOAD_XF_REG(x, y) \
|
|
do { \
|
|
wgPipe->U8 = 0x10; \
|
|
asm volatile ("" ::: "memory" ); \
|
|
wgPipe->U32 = (u32)((x)&0xffff); \
|
|
asm volatile ("" ::: "memory" ); \
|
|
wgPipe->U32 = (u32)(y); \
|
|
asm volatile ("" ::: "memory" ); \
|
|
} while(0)
|
|
|
|
#define GX_LOAD_XF_REGS(x, n) \
|
|
do { \
|
|
wgPipe->U8 = 0x10; \
|
|
asm volatile ("" ::: "memory" ); \
|
|
wgPipe->U32 = (u32)(((((n)&0xffff)-1)<<16)|((x)&0xffff)); \
|
|
asm volatile ("" ::: "memory" ); \
|
|
} while(0)
|
|
|
|
#define XY(x, y) (((y) << 10) | (x))
|
|
|
|
#define GX_DEFAULT_BG {64,64,64,255}
|
|
#define BLACK {0,0,0,0}
|
|
#define WHITE {255,255,255,255}
|
|
|
|
WGPipe* const wgPipe = (WGPipe*)0xCC008000;
|
|
|
|
static GXFifoObj _gpfifo;
|
|
static GXFifoObj _cpufifo;
|
|
static GXFifoObj _gxfifoobj;
|
|
static GXFifoObj _gx_dl_fifoobj;
|
|
static GXFifoObj _gx_old_cpufifo;
|
|
static void *_gxcurrbp = NULL;
|
|
static lwp_t _gxcurrentlwp = LWP_THREAD_NULL;
|
|
|
|
static u32 _gxcpufifoready = 0;
|
|
static u32 _gxgpfifoready = 0;
|
|
static u32 _cpgplinked = 0;
|
|
static u16 _gxgpstatus = 0;
|
|
static vu32 _gxoverflowsuspend = 0;
|
|
static vu32 _gxoverflowcount = 0;
|
|
static vu32 _gxfinished = 0;
|
|
static lwpq_t _gxwaitfinish;
|
|
|
|
static GXBreakPtCallback breakPtCB = NULL;
|
|
static GXDrawDoneCallback drawDoneCB = NULL;
|
|
static GXDrawSyncCallback tokenCB = NULL;
|
|
|
|
static GXTexRegionCallback regionCB = NULL;
|
|
static GXTlutRegionCallback tlut_regionCB = NULL;
|
|
|
|
static vu32* const _piReg = (u32*)0xCC003000;
|
|
static vu16* const _cpReg = (u16*)0xCC000000;
|
|
static vu16* const _peReg = (u16*)0xCC001000;
|
|
static vu16* const _memReg = (u16*)0xCC004000;
|
|
|
|
static u8 _gxtevcolid[9] = {0,1,0,1,0,1,7,5,6};
|
|
static u8 _gxtexmode0ids[8] = {0x80,0x81,0x82,0x83,0xA0,0xA1,0xA2,0xA3};
|
|
static u8 _gxtexmode1ids[8] = {0x84,0x85,0x86,0x87,0xA4,0xA5,0xA6,0xA7};
|
|
static u8 _gxteximg0ids[8] = {0x88,0x89,0x8A,0x8B,0xA8,0xA9,0xAA,0xAB};
|
|
static u8 _gxteximg1ids[8] = {0x8C,0x8D,0x8E,0x8F,0xAC,0xAD,0xAE,0xAF};
|
|
static u8 _gxteximg2ids[8] = {0x90,0x91,0x92,0x93,0xB0,0xB1,0xB2,0xB3};
|
|
static u8 _gxteximg3ids[8] = {0x94,0x95,0x96,0x97,0xB4,0xB5,0xB6,0xB7};
|
|
static u8 _gxtextlutids[8] = {0x98,0x99,0x9A,0x9B,0xB8,0xB9,0xBA,0xBB};
|
|
|
|
#if defined(HW_RVL)
|
|
static u32 _gxtexregionaddrtable[48] =
|
|
{
|
|
0x00000000,0x00010000,0x00020000,0x00030000,
|
|
0x00040000,0x00050000,0x00060000,0x00070000,
|
|
0x00008000,0x00018000,0x00028000,0x00038000,
|
|
0x00048000,0x00058000,0x00068000,0x00078000,
|
|
0x00000000,0x00090000,0x00020000,0x000B0000,
|
|
0x00040000,0x00098000,0x00060000,0x000B8000,
|
|
0x00080000,0x00010000,0x000A0000,0x00030000,
|
|
0x00088000,0x00050000,0x000A8000,0x00070000,
|
|
0x00000000,0x00090000,0x00020000,0x000B0000,
|
|
0x00040000,0x00090000,0x00060000,0x000B0000,
|
|
0x00080000,0x00010000,0x000A0000,0x00030000,
|
|
0x00080000,0x00050000,0x000A0000,0x00070000
|
|
};
|
|
#endif
|
|
|
|
|
|
extern u8 __gxregs[];
|
|
static struct __gx_regdef *__gx = (struct __gx_regdef*)__gxregs;
|
|
static u8 _gx_saved_data[STRUCT_REGDEF_SIZE] ATTRIBUTE_ALIGN(32);
|
|
|
|
static s32 __gx_onreset(s32 final);
|
|
|
|
static sys_resetinfo __gx_resetinfo = {
|
|
{},
|
|
__gx_onreset,
|
|
127
|
|
};
|
|
|
|
static __inline__ BOOL IsWriteGatherBufferEmpty()
|
|
{
|
|
return !(mfwpar()&1);
|
|
}
|
|
|
|
static __inline__ void DisableWriteGatherPipe()
|
|
{
|
|
mthid2((mfhid2()&~0x40000000));
|
|
}
|
|
|
|
static __inline__ void EnableWriteGatherPipe()
|
|
{
|
|
mtwpar(0x0C008000);
|
|
mthid2((mfhid2()|0x40000000));
|
|
}
|
|
|
|
static __inline__ void __GX_ResetWriteGatherPipe()
|
|
{
|
|
while(mfwpar()&1);
|
|
mtwpar(0x0C008000);
|
|
}
|
|
|
|
static __inline__ void __GX_FifoLink(u8 enable)
|
|
{
|
|
__gx->cpCRreg = ((__gx->cpCRreg&~0x10)|(_SHIFTL(enable,4,1)));
|
|
_cpReg[1] = __gx->cpCRreg;
|
|
}
|
|
|
|
static __inline__ void __GX_WriteFifoIntReset(u8 inthi,u8 intlo)
|
|
{
|
|
__gx->cpCLreg = ((__gx->cpCLreg&~0x03)|(_SHIFTL(intlo,1,1))|(inthi&1));
|
|
_cpReg[2] = __gx->cpCLreg;
|
|
}
|
|
|
|
static __inline__ void __GX_WriteFifoIntEnable(u8 inthi, u8 intlo)
|
|
{
|
|
__gx->cpCRreg = ((__gx->cpCRreg&~0x0C)|(_SHIFTL(intlo,3,1))|(_SHIFTL(inthi,2,1)));
|
|
_cpReg[1] = __gx->cpCRreg;
|
|
}
|
|
|
|
static __inline__ void __GX_FifoReadEnable()
|
|
{
|
|
__gx->cpCRreg = ((__gx->cpCRreg&~0x01)|1);
|
|
_cpReg[1] = __gx->cpCRreg;
|
|
}
|
|
|
|
static __inline__ void __GX_FifoReadDisable()
|
|
{
|
|
__gx->cpCRreg = ((__gx->cpCRreg&~0x01)|0);
|
|
_cpReg[1] = __gx->cpCRreg;
|
|
}
|
|
|
|
static s32 __gx_onreset(s32 final)
|
|
{
|
|
if(final==FALSE) {
|
|
GX_Flush();
|
|
GX_AbortFrame();
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
static u32 __GX_IsGPFifoReady()
|
|
{
|
|
return _gxgpfifoready;
|
|
}
|
|
|
|
static u32 __GX_CPGPLinkCheck()
|
|
{
|
|
struct __gxfifo *gpfifo = (struct __gxfifo*)&_gpfifo;
|
|
struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
|
|
|
|
if(!_gxcpufifoready || !_gxgpfifoready) return 0;
|
|
|
|
if((cpufifo->buf_start==gpfifo->buf_start)&&(cpufifo->buf_end==gpfifo->buf_end)) return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void __GX_InitRevBits()
|
|
{
|
|
s32 i;
|
|
|
|
i=0;
|
|
while(i<8) {
|
|
__gx->VAT0reg[i] = 0x40000000;
|
|
__gx->VAT1reg[i] = 0x80000000;
|
|
GX_LOAD_CP_REG((0x0080|i),__gx->VAT1reg[i]);
|
|
i++;
|
|
}
|
|
|
|
GX_LOAD_XF_REG(0x1000,0x3f);
|
|
GX_LOAD_XF_REG(0x1012,0x01);
|
|
|
|
GX_LOAD_BP_REG(0x5800000f);
|
|
|
|
}
|
|
|
|
static void __GX_WaitAbort(u32 delay)
|
|
{
|
|
u64 start,end;
|
|
|
|
start = gettime();
|
|
while(1) {
|
|
end = gettime();
|
|
if(diff_ticks(start,end)>=(u64)delay) break;
|
|
};
|
|
}
|
|
|
|
#ifdef HW_RVL
|
|
static u32 __GX_ReadMemCounterU32(u32 reg)
|
|
{
|
|
u16 lcnt,ucnt,tmp;
|
|
|
|
tmp = _memReg[reg];
|
|
do {
|
|
ucnt = tmp;
|
|
lcnt = _memReg[reg+1];
|
|
tmp = _memReg[reg];
|
|
} while(tmp!=ucnt);
|
|
return (u32)((ucnt<<16)|lcnt);
|
|
}
|
|
|
|
static void __GX_WaitAbortPixelEngine()
|
|
{
|
|
u32 cnt,tmp;
|
|
|
|
cnt = __GX_ReadMemCounterU32(39);
|
|
do {
|
|
tmp = cnt;
|
|
__GX_WaitAbort(8);
|
|
cnt = __GX_ReadMemCounterU32(39);
|
|
} while(cnt!=tmp);
|
|
}
|
|
|
|
static void __GX_Abort()
|
|
{
|
|
if(__gx->gxFifoInited && __GX_IsGPFifoReady())
|
|
__GX_WaitAbortPixelEngine();
|
|
|
|
_piReg[6] = 1;
|
|
__GX_WaitAbort(50);
|
|
|
|
_piReg[6] = 0;
|
|
__GX_WaitAbort(5);
|
|
}
|
|
#endif
|
|
|
|
static void __GX_SaveFifo()
|
|
{
|
|
s32 rdwt_dst;
|
|
u32 level,val;
|
|
struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
|
|
struct __gxfifo *gpfifo = (struct __gxfifo*)&_gpfifo;
|
|
|
|
_CPU_ISR_Disable(level);
|
|
|
|
if(_gxcpufifoready) {
|
|
val = _piReg[0x05];
|
|
cpufifo->wt_ptr = (u32)MEM_PHYSICAL_TO_K0((val&0x1FFFFFE0));
|
|
cpufifo->fifo_wrap = ((val&0x20000000)==0x20000000);
|
|
}
|
|
|
|
if(_gxgpfifoready) {
|
|
gpfifo->rd_ptr = (u32)MEM_PHYSICAL_TO_K0(_SHIFTL(_cpReg[29],16,16)|(_cpReg[28]&0xffff));
|
|
gpfifo->rdwt_dst = (_SHIFTL(_cpReg[25],16,16)|(_cpReg[24]&0xffff));
|
|
}
|
|
|
|
if(_cpgplinked) {
|
|
cpufifo->rd_ptr = gpfifo->rd_ptr;
|
|
cpufifo->rdwt_dst = gpfifo->rdwt_dst;
|
|
gpfifo->wt_ptr = cpufifo->wt_ptr;
|
|
} else if(_gxcpufifoready) {
|
|
rdwt_dst = (cpufifo->wt_ptr - cpufifo->rd_ptr);
|
|
if(rdwt_dst<0) cpufifo->rdwt_dst = (cpufifo->rdwt_dst + cpufifo->size);
|
|
else cpufifo->rdwt_dst = rdwt_dst;
|
|
}
|
|
|
|
_CPU_ISR_Restore(level);
|
|
}
|
|
|
|
static void __GX_CleanGPFifo()
|
|
{
|
|
u32 level;
|
|
struct __gxfifo *gpfifo = (struct __gxfifo*)&_gpfifo;
|
|
struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
|
|
|
|
if(!_gxgpfifoready) return;
|
|
|
|
_CPU_ISR_Disable(level);
|
|
__GX_FifoReadDisable();
|
|
__GX_WriteFifoIntEnable(FALSE,FALSE);
|
|
|
|
gpfifo->rd_ptr = gpfifo->wt_ptr;
|
|
gpfifo->rdwt_dst = 0;
|
|
|
|
/* setup rd<->wd dist */
|
|
_cpReg[24] = _SHIFTL(gpfifo->rdwt_dst,0,16);
|
|
_cpReg[25] = _SHIFTR(gpfifo->rdwt_dst,16,16);
|
|
|
|
/* setup wt ptr */
|
|
_cpReg[26] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->wt_ptr),0,16);
|
|
_cpReg[27] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->wt_ptr),16,16);
|
|
|
|
/* setup rd ptr */
|
|
_cpReg[28] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->rd_ptr),0,16);
|
|
_cpReg[29] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->rd_ptr),16,16);
|
|
ppcsync();
|
|
|
|
if(_cpgplinked) {
|
|
cpufifo->rd_ptr = gpfifo->rd_ptr;
|
|
cpufifo->wt_ptr = gpfifo->wt_ptr;
|
|
cpufifo->rdwt_dst = gpfifo->rdwt_dst;
|
|
|
|
_piReg[5] = (cpufifo->wt_ptr&0x1FFFFFE0);
|
|
__GX_WriteFifoIntEnable(TRUE,FALSE);
|
|
__GX_FifoLink(TRUE);
|
|
}
|
|
__gx->cpCRreg &= ~0x22;
|
|
_cpReg[1] = __gx->cpCRreg;
|
|
breakPtCB = NULL;
|
|
|
|
__GX_WriteFifoIntReset(TRUE,TRUE);
|
|
__GX_FifoReadEnable();
|
|
_CPU_ISR_Restore(level);
|
|
}
|
|
|
|
static void __GXOverflowHandler()
|
|
{
|
|
if(!_gxoverflowsuspend) {
|
|
_gxoverflowsuspend = 1;
|
|
_gxoverflowcount++;
|
|
__GX_WriteFifoIntEnable(GX_DISABLE,GX_ENABLE);
|
|
__GX_WriteFifoIntReset(GX_TRUE,GX_FALSE);
|
|
LWP_SuspendThread(_gxcurrentlwp);
|
|
}
|
|
}
|
|
|
|
static void __GXUnderflowHandler()
|
|
{
|
|
if(_gxoverflowsuspend) {
|
|
_gxoverflowsuspend = 0;
|
|
LWP_ResumeThread(_gxcurrentlwp);
|
|
__GX_WriteFifoIntReset(GX_TRUE,GX_TRUE);
|
|
__GX_WriteFifoIntEnable(GX_ENABLE,GX_DISABLE);
|
|
}
|
|
}
|
|
|
|
static void __GXCPInterruptHandler(u32 irq,void *ctx)
|
|
{
|
|
__gx->cpSRreg = _cpReg[0];
|
|
|
|
if((__gx->cpCRreg&0x08) && (__gx->cpSRreg&0x02))
|
|
__GXUnderflowHandler();
|
|
|
|
if((__gx->cpCRreg&0x04) && (__gx->cpSRreg&0x01))
|
|
__GXOverflowHandler();
|
|
|
|
if((__gx->cpCRreg&0x20) && (__gx->cpSRreg&0x10)) {
|
|
__gx->cpCRreg &= ~0x20;
|
|
_cpReg[1] = __gx->cpCRreg;
|
|
if(breakPtCB)
|
|
breakPtCB();
|
|
}
|
|
}
|
|
|
|
static void __GXTokenInterruptHandler(u32 irq,void *ctx)
|
|
{
|
|
u16 token = _peReg[7];
|
|
|
|
if(tokenCB)
|
|
tokenCB(token);
|
|
|
|
_peReg[5] = (_peReg[5]&~0x04)|0x04;
|
|
}
|
|
|
|
static void __GXFinishInterruptHandler(u32 irq,void *ctx)
|
|
{
|
|
_peReg[5] = (_peReg[5]&~0x08)|0x08;
|
|
_gxfinished = 1;
|
|
|
|
if(drawDoneCB)
|
|
drawDoneCB();
|
|
|
|
LWP_ThreadBroadcast(_gxwaitfinish);
|
|
}
|
|
|
|
static void __GX_PEInit()
|
|
{
|
|
IRQ_Request(IRQ_PI_PETOKEN,__GXTokenInterruptHandler,NULL);
|
|
__UnmaskIrq(IRQMASK(IRQ_PI_PETOKEN));
|
|
|
|
IRQ_Request(IRQ_PI_PEFINISH,__GXFinishInterruptHandler,NULL);
|
|
__UnmaskIrq(IRQMASK(IRQ_PI_PEFINISH));
|
|
|
|
_peReg[5] = 0x0F;
|
|
}
|
|
|
|
static void __GX_FifoInit()
|
|
{
|
|
IRQ_Request(IRQ_PI_CP,__GXCPInterruptHandler,NULL);
|
|
__UnmaskIrq(IRQMASK(IRQ_PI_CP));
|
|
|
|
memset(&_cpufifo,0,sizeof(GXFifoObj));
|
|
memset(&_gpfifo,0,sizeof(GXFifoObj));
|
|
|
|
_gxcpufifoready = 0;
|
|
_gxgpfifoready = 0;
|
|
_cpgplinked = 0;
|
|
_gxoverflowsuspend = 0;
|
|
_gxcurrentlwp = LWP_GetSelf();
|
|
}
|
|
|
|
static void __GX_SetTmemConfig(u8 nr)
|
|
{
|
|
if(nr==0) {
|
|
// Set_TextureImage0-3, GXTexMapID=0-3 tmem_offset=00000000, cache_width=32 kb, cache_height=32 kb, image_type=cached
|
|
GX_LOAD_BP_REG(0x8c0d8000);
|
|
GX_LOAD_BP_REG(0x900dc000);
|
|
GX_LOAD_BP_REG(0x8d0d8400);
|
|
GX_LOAD_BP_REG(0x910dc400);
|
|
GX_LOAD_BP_REG(0x8e0d8800);
|
|
GX_LOAD_BP_REG(0x920dc800);
|
|
GX_LOAD_BP_REG(0x8f0d8c00);
|
|
GX_LOAD_BP_REG(0x930dcc00);
|
|
|
|
// Set_TextureImage0-3, GXTexMapID=4-7 tmem_offset=00010000, cache_width=32 kb, cache_height=32 kb, image_type=cached
|
|
GX_LOAD_BP_REG(0xac0d9000);
|
|
GX_LOAD_BP_REG(0xb00dd000);
|
|
GX_LOAD_BP_REG(0xad0d9400);
|
|
GX_LOAD_BP_REG(0xb10dd400);
|
|
GX_LOAD_BP_REG(0xae0d9800);
|
|
GX_LOAD_BP_REG(0xb20dd800);
|
|
GX_LOAD_BP_REG(0xaf0d9c00);
|
|
GX_LOAD_BP_REG(0xb30ddc00);
|
|
|
|
return;
|
|
}
|
|
|
|
if(nr==1) {
|
|
// Set_TextureImage0-3, GXTexMapID=0-3 tmem_offset=00000000, cache_width=32 kb, cache_height=32 kb, image_type=cached
|
|
GX_LOAD_BP_REG(0x8c0d8000);
|
|
GX_LOAD_BP_REG(0x900dc000);
|
|
GX_LOAD_BP_REG(0x8d0d8800);
|
|
GX_LOAD_BP_REG(0x910dc800);
|
|
GX_LOAD_BP_REG(0x8e0d9000);
|
|
GX_LOAD_BP_REG(0x920dd000);
|
|
GX_LOAD_BP_REG(0x8f0d9800);
|
|
GX_LOAD_BP_REG(0x930dd800);
|
|
|
|
// Set_TextureImage0-3, GXTexMapID=4-7 tmem_offset=00010000, cache_width=32 kb, cache_height=32 kb, image_type=cached
|
|
GX_LOAD_BP_REG(0xac0da000);
|
|
GX_LOAD_BP_REG(0xb00de000);
|
|
GX_LOAD_BP_REG(0xad0da800);
|
|
GX_LOAD_BP_REG(0xb10de800);
|
|
GX_LOAD_BP_REG(0xae0db000);
|
|
GX_LOAD_BP_REG(0xb20df000);
|
|
GX_LOAD_BP_REG(0xaf0db800);
|
|
GX_LOAD_BP_REG(0xb30df800);
|
|
|
|
return;
|
|
}
|
|
|
|
if(nr==2) {
|
|
// Set_TextureImage0-3, GXTexMapID=0-3 tmem_offset=00000000, cache_width=32 kb, cache_height=32 kb, image_type=cached
|
|
GX_LOAD_BP_REG(0x8c0d8000);
|
|
GX_LOAD_BP_REG(0x900dc000);
|
|
GX_LOAD_BP_REG(0x8d0d8800);
|
|
GX_LOAD_BP_REG(0x910dc800);
|
|
GX_LOAD_BP_REG(0x8e0d9000);
|
|
GX_LOAD_BP_REG(0x920dd000);
|
|
GX_LOAD_BP_REG(0x8f0d9800);
|
|
GX_LOAD_BP_REG(0x930dd800);
|
|
|
|
// Set_TextureImage0-3, GXTexMapID=4-7 tmem_offset=00010000, cache_width=32 kb, cache_height=32 kb, image_type=cached
|
|
GX_LOAD_BP_REG(0xac0da000);
|
|
GX_LOAD_BP_REG(0xb00dc400);
|
|
GX_LOAD_BP_REG(0xad0da800);
|
|
GX_LOAD_BP_REG(0xb10dcc00);
|
|
GX_LOAD_BP_REG(0xae0db000);
|
|
GX_LOAD_BP_REG(0xb20dd400);
|
|
GX_LOAD_BP_REG(0xaf0db800);
|
|
GX_LOAD_BP_REG(0xb30ddc00);
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
#if defined(HW_RVL)
|
|
static GXTexRegion* __GXDefTexRegionCallback(GXTexObj *obj,u8 mapid)
|
|
{
|
|
u32 fmt,mipmap;
|
|
GXTexRegion *ret = NULL;
|
|
|
|
fmt = GX_GetTexObjFmt(obj);
|
|
mipmap = GX_GetTexObjMipMap(obj);
|
|
if(fmt>=GX_TF_CI4 && fmt<=GX_TF_CI14)
|
|
return &__gx->texRegion[mapid];
|
|
else if(fmt==GX_TF_CMPR)
|
|
ret = &__gx->texRegion[mapid];
|
|
else
|
|
ret = &__gx->texRegion[mapid+8];
|
|
|
|
if(mipmap) ret = &__gx->texRegion[mapid+16];
|
|
|
|
return ret;
|
|
}
|
|
#else
|
|
static GXTexRegion* __GXDefTexRegionCallback(GXTexObj *obj,u8 mapid)
|
|
{
|
|
u32 fmt;
|
|
u32 idx;
|
|
static u32 regionA = 0;
|
|
static u32 regionB = 0;
|
|
GXTexRegion *ret = NULL;
|
|
|
|
fmt = GX_GetTexObjFmt(obj);
|
|
if(fmt==0x0008 || fmt==0x0009 || fmt==0x000a) {
|
|
idx = regionB++;
|
|
ret = &__gx->texRegion[(idx&3)+8];
|
|
} else {
|
|
idx = regionA++;
|
|
ret = &__gx->texRegion[(idx&7)];
|
|
}
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
static GXTlutRegion* __GXDefTlutRegionCallback(u32 tlut_name)
|
|
{
|
|
return &__gx->tlutRegion[tlut_name];
|
|
}
|
|
|
|
static void __GX_InitGX()
|
|
{
|
|
s32 i;
|
|
u32 flag;
|
|
GXRModeObj *rmode;
|
|
Mtx identity_matrix =
|
|
{
|
|
{1,0,0,0},
|
|
{0,1,0,0},
|
|
{0,0,1,0}
|
|
};
|
|
|
|
rmode = VIDEO_GetPreferredMode(NULL);
|
|
|
|
GX_SetCopyClear((GXColor)BLACK,0xffffff);
|
|
GX_SetTexCoordGen(GX_TEXCOORD0,GX_TG_MTX2x4,GX_TG_TEX0,GX_IDENTITY);
|
|
GX_SetTexCoordGen(GX_TEXCOORD1,GX_TG_MTX2x4,GX_TG_TEX1,GX_IDENTITY);
|
|
GX_SetTexCoordGen(GX_TEXCOORD2,GX_TG_MTX2x4,GX_TG_TEX2,GX_IDENTITY);
|
|
GX_SetTexCoordGen(GX_TEXCOORD3,GX_TG_MTX2x4,GX_TG_TEX3,GX_IDENTITY);
|
|
GX_SetTexCoordGen(GX_TEXCOORD4,GX_TG_MTX2x4,GX_TG_TEX4,GX_IDENTITY);
|
|
GX_SetTexCoordGen(GX_TEXCOORD5,GX_TG_MTX2x4,GX_TG_TEX5,GX_IDENTITY);
|
|
GX_SetTexCoordGen(GX_TEXCOORD6,GX_TG_MTX2x4,GX_TG_TEX6,GX_IDENTITY);
|
|
GX_SetTexCoordGen(GX_TEXCOORD7,GX_TG_MTX2x4,GX_TG_TEX7,GX_IDENTITY);
|
|
GX_SetNumTexGens(1);
|
|
GX_ClearVtxDesc();
|
|
GX_InvVtxCache();
|
|
|
|
GX_SetLineWidth(6,GX_TO_ZERO);
|
|
GX_SetPointSize(6,GX_TO_ZERO);
|
|
|
|
GX_EnableTexOffsets(GX_TEXCOORD0,GX_DISABLE,GX_DISABLE);
|
|
GX_EnableTexOffsets(GX_TEXCOORD1,GX_DISABLE,GX_DISABLE);
|
|
GX_EnableTexOffsets(GX_TEXCOORD2,GX_DISABLE,GX_DISABLE);
|
|
GX_EnableTexOffsets(GX_TEXCOORD3,GX_DISABLE,GX_DISABLE);
|
|
GX_EnableTexOffsets(GX_TEXCOORD4,GX_DISABLE,GX_DISABLE);
|
|
GX_EnableTexOffsets(GX_TEXCOORD5,GX_DISABLE,GX_DISABLE);
|
|
GX_EnableTexOffsets(GX_TEXCOORD6,GX_DISABLE,GX_DISABLE);
|
|
GX_EnableTexOffsets(GX_TEXCOORD7,GX_DISABLE,GX_DISABLE);
|
|
|
|
GX_LoadPosMtxImm(identity_matrix,GX_PNMTX0);
|
|
GX_LoadNrmMtxImm(identity_matrix,GX_PNMTX0);
|
|
GX_SetCurrentMtx(GX_PNMTX0);
|
|
GX_LoadTexMtxImm(identity_matrix,GX_IDENTITY,GX_MTX3x4);
|
|
GX_LoadTexMtxImm(identity_matrix,GX_DTTIDENTITY,GX_MTX3x4);
|
|
|
|
GX_SetViewport(0,0,rmode->fbWidth,rmode->efbHeight,0,1);
|
|
GX_SetCoPlanar(GX_DISABLE);
|
|
GX_SetCullMode(GX_CULL_BACK);
|
|
GX_SetClipMode(GX_CLIP_ENABLE);
|
|
|
|
GX_SetScissor(0,0,rmode->fbWidth,rmode->efbHeight);
|
|
GX_SetScissorBoxOffset(0,0);
|
|
|
|
GX_SetNumChans(0);
|
|
|
|
GX_SetChanCtrl(GX_COLOR0A0,GX_DISABLE,GX_SRC_REG,GX_SRC_VTX,GX_LIGHTNULL,GX_DF_NONE,GX_AF_NONE);
|
|
GX_SetChanAmbColor(GX_COLOR0A0,(GXColor)BLACK);
|
|
GX_SetChanMatColor(GX_COLOR0A0,(GXColor)WHITE);
|
|
|
|
GX_SetChanCtrl(GX_COLOR1A1,GX_DISABLE,GX_SRC_REG,GX_SRC_VTX,GX_LIGHTNULL,GX_DF_NONE,GX_AF_NONE);
|
|
GX_SetChanAmbColor(GX_COLOR1A1,(GXColor)BLACK);
|
|
GX_SetChanMatColor(GX_COLOR1A1,(GXColor)WHITE);
|
|
|
|
GX_InvalidateTexAll();
|
|
GX_SetTexRegionCallback(__GXDefTexRegionCallback);
|
|
GX_SetTlutRegionCallback(__GXDefTlutRegionCallback);
|
|
|
|
GX_SetTevOrder(GX_TEVSTAGE0,GX_TEXCOORD0,GX_TEXMAP0,GX_COLOR0A0);
|
|
GX_SetTevOrder(GX_TEVSTAGE1,GX_TEXCOORD1,GX_TEXMAP1,GX_COLOR0A0);
|
|
GX_SetTevOrder(GX_TEVSTAGE2,GX_TEXCOORD2,GX_TEXMAP2,GX_COLOR0A0);
|
|
GX_SetTevOrder(GX_TEVSTAGE3,GX_TEXCOORD3,GX_TEXMAP3,GX_COLOR0A0);
|
|
GX_SetTevOrder(GX_TEVSTAGE4,GX_TEXCOORD4,GX_TEXMAP4,GX_COLOR0A0);
|
|
GX_SetTevOrder(GX_TEVSTAGE5,GX_TEXCOORD5,GX_TEXMAP5,GX_COLOR0A0);
|
|
GX_SetTevOrder(GX_TEVSTAGE6,GX_TEXCOORD6,GX_TEXMAP6,GX_COLOR0A0);
|
|
GX_SetTevOrder(GX_TEVSTAGE7,GX_TEXCOORD7,GX_TEXMAP7,GX_COLOR0A0);
|
|
GX_SetTevOrder(GX_TEVSTAGE8,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
|
|
GX_SetTevOrder(GX_TEVSTAGE9,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
|
|
GX_SetTevOrder(GX_TEVSTAGE10,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
|
|
GX_SetTevOrder(GX_TEVSTAGE11,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
|
|
GX_SetTevOrder(GX_TEVSTAGE12,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
|
|
GX_SetTevOrder(GX_TEVSTAGE13,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
|
|
GX_SetTevOrder(GX_TEVSTAGE14,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
|
|
GX_SetTevOrder(GX_TEVSTAGE15,GX_TEXCOORDNULL,GX_TEXMAP_NULL,GX_COLORNULL);
|
|
GX_SetNumTevStages(1);
|
|
GX_SetTevOp(GX_TEVSTAGE0,GX_REPLACE);
|
|
GX_SetAlphaCompare(GX_ALWAYS,0,GX_AOP_AND,GX_ALWAYS,0);
|
|
GX_SetZTexture(GX_ZT_DISABLE,GX_TF_Z8,0);
|
|
for(i=0;i<GX_MAX_TEVSTAGE;i++) {
|
|
GX_SetTevKColorSel(i,GX_TEV_KCSEL_1_4);
|
|
GX_SetTevKAlphaSel(i,GX_TEV_KASEL_1);
|
|
GX_SetTevSwapMode(i,GX_TEV_SWAP0,GX_TEV_SWAP0);
|
|
}
|
|
|
|
GX_SetTevSwapModeTable(GX_TEV_SWAP0,GX_CH_RED,GX_CH_GREEN,GX_CH_BLUE,GX_CH_ALPHA);
|
|
GX_SetTevSwapModeTable(GX_TEV_SWAP1,GX_CH_RED,GX_CH_RED,GX_CH_RED,GX_CH_ALPHA);
|
|
GX_SetTevSwapModeTable(GX_TEV_SWAP2,GX_CH_GREEN,GX_CH_GREEN,GX_CH_GREEN,GX_CH_ALPHA);
|
|
GX_SetTevSwapModeTable(GX_TEV_SWAP3,GX_CH_BLUE,GX_CH_BLUE,GX_CH_BLUE,GX_CH_ALPHA);
|
|
for(i=0;i<GX_MAX_TEVSTAGE;i++) {
|
|
GX_SetTevDirect(i);
|
|
}
|
|
|
|
GX_SetNumIndStages(0);
|
|
GX_SetIndTexCoordScale(GX_INDTEXSTAGE0,GX_ITS_1,GX_ITS_1);
|
|
GX_SetIndTexCoordScale(GX_INDTEXSTAGE1,GX_ITS_1,GX_ITS_1);
|
|
GX_SetIndTexCoordScale(GX_INDTEXSTAGE2,GX_ITS_1,GX_ITS_1);
|
|
GX_SetIndTexCoordScale(GX_INDTEXSTAGE3,GX_ITS_1,GX_ITS_1);
|
|
|
|
GX_SetFog(GX_FOG_NONE,0,1,0.1,1,(GXColor)BLACK);
|
|
GX_SetFogRangeAdj(GX_DISABLE,0,NULL);
|
|
|
|
GX_SetBlendMode(GX_BM_NONE,GX_BL_SRCALPHA,GX_BL_INVSRCALPHA,GX_LO_CLEAR);
|
|
GX_SetColorUpdate(GX_ENABLE);
|
|
GX_SetAlphaUpdate(GX_ENABLE);
|
|
GX_SetZMode(GX_ENABLE,GX_LEQUAL,GX_TRUE);
|
|
GX_SetZCompLoc(GX_TRUE);
|
|
GX_SetDither(GX_ENABLE);
|
|
GX_SetDstAlpha(GX_DISABLE,0);
|
|
GX_SetPixelFmt(GX_PF_RGB8_Z24,GX_ZC_LINEAR);
|
|
|
|
GX_SetFieldMask(GX_ENABLE,GX_ENABLE);
|
|
|
|
flag = 0;
|
|
if(rmode->viHeight==(rmode->xfbHeight<<1)) flag = 1;
|
|
GX_SetFieldMode(rmode->field_rendering,flag);
|
|
|
|
GX_SetCopyClear((GXColor)GX_DEFAULT_BG,0x00ffffff);
|
|
GX_SetDispCopySrc(0,0,rmode->fbWidth,rmode->efbHeight);
|
|
GX_SetDispCopyDst(rmode->fbWidth,rmode->efbHeight);
|
|
GX_SetDispCopyYScale(1.0);
|
|
GX_SetCopyClamp(GX_CLAMP_TOP|GX_CLAMP_BOTTOM);
|
|
GX_SetCopyFilter(GX_FALSE,NULL,GX_FALSE,NULL);
|
|
GX_SetDispCopyGamma(GX_GM_1_0);
|
|
GX_SetDispCopyFrame2Field(GX_COPY_PROGRESSIVE);
|
|
GX_ClearBoundingBox();
|
|
|
|
GX_PokeColorUpdate(GX_TRUE);
|
|
GX_PokeAlphaUpdate(GX_TRUE);
|
|
GX_PokeDither(GX_FALSE);
|
|
GX_PokeBlendMode(GX_BM_NONE,GX_BL_ZERO,GX_BL_ONE,GX_LO_SET);
|
|
GX_PokeAlphaMode(GX_ALWAYS,0);
|
|
GX_PokeAlphaRead(GX_READ_FF);
|
|
GX_PokeDstAlpha(GX_DISABLE,0);
|
|
GX_PokeZMode(GX_TRUE,GX_ALWAYS,GX_TRUE);
|
|
|
|
GX_SetGPMetric(GX_PERF0_NONE,GX_PERF1_NONE);
|
|
GX_ClearGPMetric();
|
|
}
|
|
|
|
static void __GX_FlushTextureState()
|
|
{
|
|
GX_LOAD_BP_REG(__gx->tevIndMask);
|
|
}
|
|
|
|
static void __GX_XfVtxSpecs()
|
|
{
|
|
u32 xfvtxspecs = 0;
|
|
u32 nrms,texs,cols;
|
|
|
|
cols = 0;
|
|
if(__gx->vcdLo&0x6000) cols++;
|
|
if(__gx->vcdLo&0x18000) cols++;
|
|
|
|
nrms = 0;
|
|
if(__gx->vcdNrms==1) nrms = 1;
|
|
else if(__gx->vcdNrms==2) nrms = 2;
|
|
|
|
texs = 0;
|
|
if(__gx->vcdHi&0x3) texs++;
|
|
if(__gx->vcdHi&0xc) texs++;
|
|
if(__gx->vcdHi&0x30) texs++;
|
|
if(__gx->vcdHi&0xc0) texs++;
|
|
if(__gx->vcdHi&0x300) texs++;
|
|
if(__gx->vcdHi&0xc00) texs++;
|
|
if(__gx->vcdHi&0x3000) texs++;
|
|
if(__gx->vcdHi&0xc000) texs++;
|
|
|
|
xfvtxspecs = (_SHIFTL(texs,4,4))|(_SHIFTL(nrms,2,2))|(cols&0x3);
|
|
GX_LOAD_XF_REG(0x1008,xfvtxspecs);
|
|
}
|
|
|
|
static void __GX_SetMatrixIndex(u32 mtx)
|
|
{
|
|
if(mtx<5) {
|
|
GX_LOAD_CP_REG(0x30,__gx->mtxIdxLo);
|
|
GX_LOAD_XF_REG(0x1018,__gx->mtxIdxLo);
|
|
} else {
|
|
GX_LOAD_CP_REG(0x40,__gx->mtxIdxHi);
|
|
GX_LOAD_XF_REG(0x1019,__gx->mtxIdxHi);
|
|
}
|
|
}
|
|
|
|
static void __GX_SendFlushPrim()
|
|
{
|
|
u32 tmp,tmp2,cnt;
|
|
|
|
tmp = (__gx->xfFlush*__gx->xfFlushExp);
|
|
|
|
wgPipe->U8 = 0x98;
|
|
wgPipe->U16 = __gx->xfFlush;
|
|
|
|
tmp2 = (tmp+3)/4;
|
|
if(tmp>0) {
|
|
cnt = tmp2/8;
|
|
while(cnt) {
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
cnt--;
|
|
}
|
|
tmp2 &= 0x0007;
|
|
if(tmp2) {
|
|
while(tmp2) {
|
|
wgPipe->U32 = 0;
|
|
tmp2--;
|
|
}
|
|
}
|
|
}
|
|
__gx->xfFlush = 1;
|
|
}
|
|
|
|
static void __GX_SetVCD()
|
|
{
|
|
GX_LOAD_CP_REG(0x50,__gx->vcdLo);
|
|
GX_LOAD_CP_REG(0x60,__gx->vcdHi);
|
|
__GX_XfVtxSpecs();
|
|
}
|
|
|
|
static void __GX_SetVAT()
|
|
{
|
|
u8 setvtx = 0;
|
|
s32 i;
|
|
|
|
for(i=0;i<8;i++) {
|
|
setvtx = (1<<i);
|
|
if(__gx->VATTable&setvtx) {
|
|
GX_LOAD_CP_REG((0x70+(i&7)),__gx->VAT0reg[i]);
|
|
GX_LOAD_CP_REG((0x80+(i&7)),__gx->VAT1reg[i]);
|
|
GX_LOAD_CP_REG((0x90+(i&7)),__gx->VAT2reg[i]);
|
|
}
|
|
}
|
|
__gx->VATTable = 0;
|
|
}
|
|
|
|
static void __SetSURegs(u8 texmap,u8 texcoord)
|
|
{
|
|
u32 reg;
|
|
u16 wd,ht;
|
|
u8 wrap_s,wrap_t;
|
|
|
|
wd = __gx->texMapSize[texmap]&0x3ff;
|
|
ht = _SHIFTR(__gx->texMapSize[texmap],10,10);
|
|
wrap_s = __gx->texMapWrap[texmap]&3;
|
|
wrap_t = _SHIFTR(__gx->texMapWrap[texmap],2,2);
|
|
|
|
reg = (texcoord&0x7);
|
|
__gx->suSsize[reg] = (__gx->suSsize[reg]&~0x0000ffff)|wd;
|
|
__gx->suTsize[reg] = (__gx->suTsize[reg]&~0x0000ffff)|ht;
|
|
__gx->suSsize[reg] = (__gx->suSsize[reg]&~0x00010000)|(_SHIFTL(wrap_s,16,1));
|
|
__gx->suTsize[reg] = (__gx->suTsize[reg]&~0x00010000)|(_SHIFTL(wrap_t,16,1));
|
|
|
|
GX_LOAD_BP_REG(__gx->suSsize[reg]);
|
|
GX_LOAD_BP_REG(__gx->suTsize[reg]);
|
|
}
|
|
|
|
static void __GX_SetSUTexRegs()
|
|
{
|
|
u32 i;
|
|
u32 indtev,dirtev;
|
|
u8 texcoord,texmap;
|
|
u32 tevreg,tevm,texcm;
|
|
|
|
dirtev = (_SHIFTR(__gx->genMode,10,4))+1;
|
|
indtev = _SHIFTR(__gx->genMode,16,3);
|
|
|
|
//indirect texture order
|
|
for(i=0;i<indtev;i++) {
|
|
switch(i) {
|
|
case GX_INDTEXSTAGE0:
|
|
texmap = __gx->tevRasOrder[2]&7;
|
|
texcoord = _SHIFTR(__gx->tevRasOrder[2],3,3);
|
|
break;
|
|
case GX_INDTEXSTAGE1:
|
|
texmap = _SHIFTR(__gx->tevRasOrder[2],6,3);
|
|
texcoord = _SHIFTR(__gx->tevRasOrder[2],9,3);
|
|
break;
|
|
case GX_INDTEXSTAGE2:
|
|
texmap = _SHIFTR(__gx->tevRasOrder[2],12,3);
|
|
texcoord = _SHIFTR(__gx->tevRasOrder[2],15,3);
|
|
break;
|
|
case GX_INDTEXSTAGE3:
|
|
texmap = _SHIFTR(__gx->tevRasOrder[2],18,3);
|
|
texcoord = _SHIFTR(__gx->tevRasOrder[2],21,3);
|
|
break;
|
|
default:
|
|
texmap = 0;
|
|
texcoord = 0;
|
|
break;
|
|
}
|
|
|
|
texcm = _SHIFTL(1,texcoord,1);
|
|
if(!(__gx->texCoordManually&texcm))
|
|
__SetSURegs(texmap,texcoord);
|
|
}
|
|
|
|
//direct texture order
|
|
for(i=0;i<dirtev;i++) {
|
|
tevreg = 3+(_SHIFTR(i,1,3));
|
|
texmap = (__gx->tevTexMap[i]&0xff);
|
|
|
|
if(i&1) texcoord = _SHIFTR(__gx->tevRasOrder[tevreg],15,3);
|
|
else texcoord = _SHIFTR(__gx->tevRasOrder[tevreg],3,3);
|
|
|
|
tevm = _SHIFTL(1,i,1);
|
|
texcm = _SHIFTL(1,texcoord,1);
|
|
if(texmap!=0xff && (__gx->tevTexCoordEnable&tevm) && !(__gx->texCoordManually&texcm)) {
|
|
__SetSURegs(texmap,texcoord);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void __GX_SetGenMode()
|
|
{
|
|
GX_LOAD_BP_REG(__gx->genMode);
|
|
__gx->xfFlush = 0;
|
|
}
|
|
|
|
static void __GX_UpdateBPMask()
|
|
{
|
|
#if defined(HW_DOL)
|
|
u32 i;
|
|
u32 nbmp,nres;
|
|
u8 ntexmap;
|
|
|
|
nbmp = _SHIFTR(__gx->genMode,16,3);
|
|
|
|
nres = 0;
|
|
for(i=0;i<nbmp;i++) {
|
|
switch(i) {
|
|
case GX_INDTEXSTAGE0:
|
|
ntexmap = __gx->tevRasOrder[2]&7;
|
|
break;
|
|
case GX_INDTEXSTAGE1:
|
|
ntexmap = _SHIFTR(__gx->tevRasOrder[2],6,3);
|
|
break;
|
|
case GX_INDTEXSTAGE2:
|
|
ntexmap = _SHIFTR(__gx->tevRasOrder[2],12,3);
|
|
break;
|
|
case GX_INDTEXSTAGE3:
|
|
ntexmap = _SHIFTR(__gx->tevRasOrder[2],18,3);
|
|
break;
|
|
default:
|
|
ntexmap = 0;
|
|
break;
|
|
}
|
|
nres |= (1<<ntexmap);
|
|
}
|
|
|
|
if((__gx->tevIndMask&0xff)!=nres) {
|
|
__gx->tevIndMask = (__gx->tevIndMask&~0xff)|(nres&0xff);
|
|
GX_LOAD_BP_REG(__gx->tevIndMask);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static void __GX_SetIndirectMask(u32 mask)
|
|
{
|
|
__gx->tevIndMask = ((__gx->tevIndMask&~0xff)|(mask&0xff));
|
|
GX_LOAD_BP_REG(__gx->tevIndMask);
|
|
}
|
|
|
|
static void __GX_SetTexCoordGen()
|
|
{
|
|
u32 i,mask;
|
|
u32 texcoord;
|
|
|
|
if(__gx->dirtyState&0x02000000) GX_LOAD_XF_REG(0x103f,(__gx->genMode&0xf));
|
|
|
|
i = 0;
|
|
texcoord = 0x1040;
|
|
mask = _SHIFTR(__gx->dirtyState,16,8);
|
|
while(mask) {
|
|
if(mask&0x0001) {
|
|
GX_LOAD_XF_REG(texcoord,__gx->texCoordGen[i]);
|
|
GX_LOAD_XF_REG((texcoord+0x10),__gx->texCoordGen2[i]);
|
|
}
|
|
mask >>= 1;
|
|
texcoord++;
|
|
i++;
|
|
}
|
|
}
|
|
|
|
static void __GX_SetChanColor()
|
|
{
|
|
if(__gx->dirtyState&0x0100)
|
|
GX_LOAD_XF_REG(0x100a,__gx->chnAmbColor[0]);
|
|
if(__gx->dirtyState&0x0200)
|
|
GX_LOAD_XF_REG(0x100b,__gx->chnAmbColor[1]);
|
|
if(__gx->dirtyState&0x0400)
|
|
GX_LOAD_XF_REG(0x100c,__gx->chnMatColor[0]);
|
|
if(__gx->dirtyState&0x0800)
|
|
GX_LOAD_XF_REG(0x100d,__gx->chnMatColor[1]);
|
|
}
|
|
|
|
static void __GX_SetChanCntrl()
|
|
{
|
|
u32 i,chan,mask;
|
|
|
|
if(__gx->dirtyState&0x01000000) GX_LOAD_XF_REG(0x1009,(_SHIFTR(__gx->genMode,4,3)));
|
|
|
|
i = 0;
|
|
chan = 0x100e;
|
|
mask = _SHIFTR(__gx->dirtyState,12,4);
|
|
while(mask) {
|
|
if(mask&0x0001) GX_LOAD_XF_REG(chan,__gx->chnCntrl[i]);
|
|
|
|
mask >>= 1;
|
|
chan++;
|
|
i++;
|
|
}
|
|
}
|
|
|
|
static void __GX_SetDirtyState()
|
|
{
|
|
if(__gx->dirtyState&0x0001) {
|
|
__GX_SetSUTexRegs();
|
|
}
|
|
if(__gx->dirtyState&0x0002) {
|
|
__GX_UpdateBPMask();
|
|
}
|
|
if(__gx->dirtyState&0x0004) {
|
|
__GX_SetGenMode();
|
|
}
|
|
if(__gx->dirtyState&0x0008) {
|
|
__GX_SetVCD();
|
|
}
|
|
if(__gx->dirtyState&0x0010) {
|
|
__GX_SetVAT();
|
|
}
|
|
if(__gx->dirtyState&~0xff) {
|
|
if(__gx->dirtyState&0x0f00) {
|
|
__GX_SetChanColor();
|
|
}
|
|
if(__gx->dirtyState&0x0100f000) {
|
|
__GX_SetChanCntrl();
|
|
}
|
|
if(__gx->dirtyState&0x02ff0000) {
|
|
__GX_SetTexCoordGen();
|
|
}
|
|
if(__gx->dirtyState&0x04000000) {
|
|
__GX_SetMatrixIndex(0);
|
|
__GX_SetMatrixIndex(5);
|
|
}
|
|
}
|
|
__gx->dirtyState = 0;
|
|
}
|
|
|
|
static u32 __GX_GetNumXfbLines(u16 efbHeight,u32 yscale)
|
|
{
|
|
u32 tmp,tmp1;
|
|
|
|
tmp = (((efbHeight-1)<<8)/yscale)+1;
|
|
if(yscale>128 && yscale<256) {
|
|
while(yscale&0x01) yscale >>= 1;
|
|
tmp1 = yscale*(efbHeight/yscale);
|
|
if(!(efbHeight-tmp1)) tmp++;
|
|
}
|
|
if(tmp>1024) tmp = 1024;
|
|
|
|
return tmp;
|
|
}
|
|
|
|
GXFifoObj* GX_Init(void *base,u32 size)
|
|
{
|
|
s32 i,re0,re1;
|
|
#if defined(HW_RVL)
|
|
u32 tmem;
|
|
#else
|
|
u32 tmem_even,tmem_odd;
|
|
#endif
|
|
u32 divis,res;
|
|
u32 divid = TB_BUS_CLOCK;
|
|
GXTexRegion *region = NULL;
|
|
GXTlutRegion *tregion = NULL;
|
|
|
|
LWP_InitQueue(&_gxwaitfinish);
|
|
SYS_RegisterResetFunc(&__gx_resetinfo);
|
|
|
|
memset(__gxregs,0,STRUCT_REGDEF_SIZE);
|
|
|
|
__GX_FifoInit();
|
|
GX_InitFifoBase(&_gxfifoobj,base,size);
|
|
GX_SetCPUFifo(&_gxfifoobj);
|
|
GX_SetGPFifo(&_gxfifoobj);
|
|
__GX_PEInit();
|
|
EnableWriteGatherPipe();
|
|
|
|
__gx->gxFifoInited = 1;
|
|
|
|
__gx->tevIndMask = 0xff;
|
|
__gx->tevIndMask = (__gx->tevIndMask&~0xff000000)|(_SHIFTL(0x0f,24,8));
|
|
|
|
i=0;
|
|
re0 = 0xc0;
|
|
re1 = 0xc1;
|
|
while(i<16) {
|
|
__gx->tevColorEnv[i] = (__gx->tevColorEnv[i]&~0xff000000)|(_SHIFTL(re0,24,8));
|
|
__gx->tevAlphaEnv[i] = (__gx->tevAlphaEnv[i]&~0xff000000)|(_SHIFTL(re1,24,8));
|
|
re0 += 2; re1 += 2; i++;
|
|
}
|
|
|
|
__gx->texCoordManually = 0;
|
|
__gx->dirtyState = 0;
|
|
|
|
__gx->saveDLctx = 1;
|
|
__gx->gxFifoUnlinked = 0;
|
|
|
|
__gx->sciTLcorner = (__gx->sciTLcorner&~0xff000000)|(_SHIFTL(0x20,24,8));
|
|
__gx->sciBRcorner = (__gx->sciBRcorner&~0xff000000)|(_SHIFTL(0x21,24,8));
|
|
__gx->lpWidth = (__gx->lpWidth&~0xff000000)|(_SHIFTL(0x22,24,8));
|
|
__gx->genMode = (__gx->genMode&~0xff000000)|(_SHIFTL(0x00,24,8));
|
|
|
|
i=0;
|
|
re0 = 0x30;
|
|
re1 = 0x31;
|
|
while(i<8) {
|
|
__gx->suSsize[i] = (__gx->suSsize[i]&~0xff000000)|(_SHIFTL(re0,24,8));
|
|
__gx->suTsize[i] = (__gx->suTsize[i]&~0xff000000)|(_SHIFTL(re1,24,8));
|
|
re0 += 2; re1 += 2; i++;
|
|
}
|
|
|
|
__gx->peZMode = (__gx->peZMode&~0xff000000)|(_SHIFTL(0x40,24,8));
|
|
__gx->peCMode0 = (__gx->peCMode0&~0xff000000)|(_SHIFTL(0x41,24,8));
|
|
__gx->peCMode1 = (__gx->peCMode1&~0xff000000)|(_SHIFTL(0x42,24,8));
|
|
__gx->peCntrl = (__gx->peCntrl&~0xff000000)|(_SHIFTL(0x43,24,8));
|
|
|
|
i=0;
|
|
re0 = 0x25;
|
|
while(i<11) {
|
|
__gx->tevRasOrder[i] = (__gx->tevRasOrder[i]&~0xff000000)|(_SHIFTL(re0,24,8));
|
|
re0++; i++;
|
|
}
|
|
|
|
divis = 500;
|
|
res = (u32)(divid/divis);
|
|
__GX_FlushTextureState();
|
|
GX_LOAD_BP_REG(0x69000000|((_SHIFTR(res,11,24))|0x0400));
|
|
|
|
divis = 4224;
|
|
res = (u32)(res/divis);
|
|
__GX_FlushTextureState();
|
|
GX_LOAD_BP_REG(0x46000000|(res|0x0200));
|
|
|
|
i=0;
|
|
re0 = 0xf6;
|
|
while(i<8) {
|
|
__gx->tevSwapModeTable[i] = (__gx->tevSwapModeTable[i]&~0xff000000)|(_SHIFTL(re0,24,8));
|
|
re0++; i++;
|
|
}
|
|
|
|
__gx->tevTexCoordEnable = 0;
|
|
__gx->perf0Mode = GX_PERF0_NONE;
|
|
__gx->perf1Mode = GX_PERF1_NONE;
|
|
__gx->cpPerfMode = 0;
|
|
|
|
__GX_InitRevBits();
|
|
|
|
i=0;
|
|
while(i<16) {
|
|
__gx->tevTexMap[i] = 0xff;
|
|
i++;
|
|
}
|
|
|
|
#if defined(HW_RVL)
|
|
i = 0;
|
|
while(i<8) {
|
|
region = &__gx->texRegion[i];
|
|
GX_InitTexCacheRegion(region,GX_FALSE,_gxtexregionaddrtable[i+0],GX_TEXCACHE_32K,_gxtexregionaddrtable[i+8],GX_TEXCACHE_32K);
|
|
|
|
region = &__gx->texRegion[i+8];
|
|
GX_InitTexCacheRegion(region,GX_FALSE,_gxtexregionaddrtable[i+16],GX_TEXCACHE_32K,_gxtexregionaddrtable[i+24],GX_TEXCACHE_32K);
|
|
|
|
region = &__gx->texRegion[i+16];
|
|
GX_InitTexCacheRegion(region,GX_TRUE,_gxtexregionaddrtable[i+32],GX_TEXCACHE_32K,_gxtexregionaddrtable[i+40],GX_TEXCACHE_32K);
|
|
|
|
i++;
|
|
}
|
|
|
|
i=0;
|
|
while(i<16) {
|
|
tmem = 0x000C0000+(i<<13);
|
|
tregion = &__gx->tlutRegion[i];
|
|
GX_InitTlutRegion(tregion,tmem,GX_TLUT_256);
|
|
i++;
|
|
}
|
|
|
|
i=0;
|
|
while(i<4) {
|
|
tmem = 0x000E0000+(i<<15);
|
|
tregion = &__gx->tlutRegion[i+16];
|
|
GX_InitTlutRegion(tregion,tmem,GX_TLUT_1K);
|
|
i++;
|
|
}
|
|
#else
|
|
for(i=0;i<8;i++) {
|
|
tmem_even = tmem_odd = (i<<15);
|
|
region = &__gx->texRegion[i];
|
|
GX_InitTexCacheRegion(region,GX_FALSE,tmem_even,GX_TEXCACHE_32K,(tmem_odd+0x00080000),GX_TEXCACHE_32K);
|
|
}
|
|
for(i=0;i<4;i++) {
|
|
tmem_even = ((0x08+(i<<1))<<15);
|
|
tmem_odd = ((0x09+(i<<1))<<15);
|
|
region = &__gx->texRegion[i+8];
|
|
GX_InitTexCacheRegion(region,GX_FALSE,tmem_even,GX_TEXCACHE_32K,tmem_odd,GX_TEXCACHE_32K);
|
|
}
|
|
for(i=0;i<16;i++) {
|
|
tmem_even = (i<<13)+0x000C0000;
|
|
tregion = &__gx->tlutRegion[i];
|
|
GX_InitTlutRegion(tregion,tmem_even,GX_TLUT_256);
|
|
}
|
|
for(i=0;i<4;i++) {
|
|
tmem_even = (i<<15)+0x000E0000;
|
|
tregion = &__gx->tlutRegion[i+16];
|
|
GX_InitTlutRegion(tregion,tmem_even,GX_TLUT_1K);
|
|
}
|
|
#endif
|
|
_cpReg[3] = 0;
|
|
GX_LOAD_CP_REG(0x20,0x00000000);
|
|
GX_LOAD_XF_REG(0x1006,0x0);
|
|
|
|
GX_LOAD_BP_REG(0x23000000);
|
|
GX_LOAD_BP_REG(0x24000000);
|
|
GX_LOAD_BP_REG(0x67000000);
|
|
|
|
__GX_SetIndirectMask(0);
|
|
#if defined(HW_RVL)
|
|
__GX_SetTmemConfig(2);
|
|
#else
|
|
__GX_SetTmemConfig(0);
|
|
#endif
|
|
__GX_InitGX();
|
|
|
|
return &_gxfifoobj;
|
|
}
|
|
|
|
void GX_InitFifoBase(GXFifoObj *fifo,void *base,u32 size)
|
|
{
|
|
struct __gxfifo *ptr = (struct __gxfifo*)fifo;
|
|
|
|
if(!ptr || size<GX_FIFO_MINSIZE) return;
|
|
|
|
ptr->buf_start = (u32)base;
|
|
ptr->buf_end = (u32)base + size - 4;
|
|
ptr->size = size;
|
|
ptr->rdwt_dst = 0;
|
|
|
|
GX_InitFifoLimits(fifo,(size-GX_FIFO_HIWATERMARK),((size>>1)&0x7fffffe0));
|
|
GX_InitFifoPtrs(fifo,base,base);
|
|
}
|
|
|
|
void GX_InitFifoLimits(GXFifoObj *fifo,u32 hiwatermark,u32 lowatermark)
|
|
{
|
|
struct __gxfifo *ptr = (struct __gxfifo*)fifo;
|
|
|
|
ptr->hi_mark = hiwatermark;
|
|
ptr->lo_mark = lowatermark;
|
|
}
|
|
|
|
void GX_InitFifoPtrs(GXFifoObj *fifo,void *rd_ptr,void *wt_ptr)
|
|
{
|
|
u32 level;
|
|
s32 rdwt_dst;
|
|
struct __gxfifo *ptr = (struct __gxfifo*)fifo;
|
|
|
|
_CPU_ISR_Disable(level);
|
|
rdwt_dst = wt_ptr-rd_ptr;
|
|
ptr->rd_ptr = (u32)rd_ptr;
|
|
ptr->wt_ptr = (u32)wt_ptr;
|
|
ptr->rdwt_dst = rdwt_dst;
|
|
if(rdwt_dst<0) {
|
|
rdwt_dst += ptr->size;
|
|
ptr->rd_ptr = rdwt_dst;
|
|
}
|
|
_CPU_ISR_Restore(level);
|
|
}
|
|
|
|
void GX_GetFifoPtrs(GXFifoObj *fifo,void **rd_ptr,void **wt_ptr)
|
|
{
|
|
struct __gxfifo *ptr = (struct __gxfifo*)fifo;
|
|
*rd_ptr = (void*)ptr->rd_ptr;
|
|
*wt_ptr = (void*)ptr->wt_ptr;
|
|
}
|
|
|
|
void GX_SetCPUFifo(GXFifoObj *fifo)
|
|
{
|
|
u32 level;
|
|
struct __gxfifo *ptr = (struct __gxfifo*)fifo;
|
|
struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
|
|
|
|
_CPU_ISR_Disable(level);
|
|
if(!fifo) {
|
|
_gxcpufifoready = 0;
|
|
_cpgplinked = 0;
|
|
cpufifo->gpfifo_ready = 0;
|
|
cpufifo->cpufifo_ready = 0;
|
|
_CPU_ISR_Restore(level);
|
|
return;
|
|
}
|
|
|
|
cpufifo->buf_start = ptr->buf_start;
|
|
cpufifo->buf_end = ptr->buf_end;
|
|
cpufifo->size = ptr->size;
|
|
cpufifo->hi_mark = ptr->hi_mark;
|
|
cpufifo->lo_mark = ptr->lo_mark;
|
|
cpufifo->rd_ptr = ptr->rd_ptr;
|
|
cpufifo->wt_ptr = ptr->wt_ptr;
|
|
cpufifo->rdwt_dst = ptr->rdwt_dst;
|
|
cpufifo->fifo_wrap = ptr->fifo_wrap;
|
|
cpufifo->gpfifo_ready = ptr->gpfifo_ready;
|
|
cpufifo->cpufifo_ready = 1;
|
|
|
|
_gxcpufifoready = 1;
|
|
if(__GX_CPGPLinkCheck()) {
|
|
_cpgplinked = 1;
|
|
cpufifo->gpfifo_ready = 1;
|
|
|
|
_piReg[3] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_start);
|
|
_piReg[4] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_end);
|
|
_piReg[5] = (cpufifo->wt_ptr&0x1FFFFFE0);
|
|
|
|
__GX_WriteFifoIntReset(GX_TRUE,GX_TRUE);
|
|
__GX_WriteFifoIntEnable(GX_ENABLE,GX_DISABLE);
|
|
__GX_FifoLink(GX_TRUE);
|
|
|
|
_CPU_ISR_Restore(level);
|
|
return;
|
|
}
|
|
|
|
if(_cpgplinked) {
|
|
__GX_FifoLink(GX_FALSE);
|
|
_cpgplinked = 0;
|
|
}
|
|
|
|
__GX_WriteFifoIntEnable(GX_DISABLE,GX_DISABLE);
|
|
|
|
_piReg[3] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_start);
|
|
_piReg[4] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_end);
|
|
_piReg[5] = (cpufifo->wt_ptr&0x1FFFFFE0);
|
|
ppcsync();
|
|
|
|
_CPU_ISR_Restore(level);
|
|
}
|
|
|
|
void GX_GetCPUFifo(GXFifoObj *fifo)
|
|
{
|
|
struct __gxfifo* ptr = (struct __gxfifo*)fifo;
|
|
struct __gxfifo* cpufifo = (struct __gxfifo*)&_cpufifo;
|
|
|
|
if(!_gxcpufifoready) return;
|
|
|
|
GX_Flush();
|
|
__GX_SaveFifo();
|
|
|
|
ptr->buf_start = cpufifo->buf_start;
|
|
ptr->buf_end = cpufifo->buf_end;
|
|
ptr->size = cpufifo->size;
|
|
ptr->rd_ptr = cpufifo->rd_ptr;
|
|
ptr->wt_ptr = cpufifo->wt_ptr;
|
|
ptr->rdwt_dst = cpufifo->rdwt_dst;
|
|
ptr->hi_mark = cpufifo->hi_mark;
|
|
ptr->lo_mark = cpufifo->lo_mark;
|
|
ptr->fifo_wrap = cpufifo->fifo_wrap;
|
|
ptr->cpufifo_ready = cpufifo->cpufifo_ready;
|
|
ptr->gpfifo_ready = cpufifo->gpfifo_ready;
|
|
}
|
|
|
|
void GX_SetGPFifo(GXFifoObj *fifo)
|
|
{
|
|
u32 level;
|
|
struct __gxfifo *ptr = (struct __gxfifo*)fifo;
|
|
struct __gxfifo *gpfifo = (struct __gxfifo*)&_gpfifo;
|
|
|
|
_CPU_ISR_Disable(level);
|
|
__GX_FifoReadDisable();
|
|
__GX_WriteFifoIntEnable(GX_DISABLE,GX_DISABLE);
|
|
|
|
if(!fifo) {
|
|
_gxgpfifoready = 0;
|
|
_cpgplinked = 0;
|
|
gpfifo->cpufifo_ready = 0;
|
|
gpfifo->gpfifo_ready = 0;
|
|
__GX_FifoLink(GX_FALSE);
|
|
_CPU_ISR_Restore(level);
|
|
return;
|
|
}
|
|
|
|
gpfifo->buf_start = ptr->buf_start;
|
|
gpfifo->buf_end = ptr->buf_end;
|
|
gpfifo->size = ptr->size;
|
|
gpfifo->hi_mark = ptr->hi_mark;
|
|
gpfifo->lo_mark = ptr->lo_mark;
|
|
gpfifo->rd_ptr = ptr->rd_ptr;
|
|
gpfifo->wt_ptr = ptr->wt_ptr;
|
|
gpfifo->rdwt_dst = ptr->rdwt_dst;
|
|
gpfifo->fifo_wrap = ptr->fifo_wrap;
|
|
gpfifo->cpufifo_ready = ptr->cpufifo_ready;
|
|
gpfifo->gpfifo_ready = 1;
|
|
_gxgpfifoready = 1;
|
|
|
|
/* setup fifo base */
|
|
_cpReg[16] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->buf_start),0,16);
|
|
_cpReg[17] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->buf_start),16,16);
|
|
|
|
/* setup fifo end */
|
|
_cpReg[18] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->buf_end),0,16);
|
|
_cpReg[19] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->buf_end),16,16);
|
|
|
|
/* setup hiwater mark */
|
|
_cpReg[20] = _SHIFTL(gpfifo->hi_mark,0,16);
|
|
_cpReg[21] = _SHIFTR(gpfifo->hi_mark,16,16);
|
|
|
|
/* setup lowater mark */
|
|
_cpReg[22] = _SHIFTL(gpfifo->lo_mark,0,16);
|
|
_cpReg[23] = _SHIFTR(gpfifo->lo_mark,16,16);
|
|
|
|
/* setup rd<->wd dist */
|
|
_cpReg[24] = _SHIFTL(gpfifo->rdwt_dst,0,16);
|
|
_cpReg[25] = _SHIFTR(gpfifo->rdwt_dst,16,16);
|
|
|
|
/* setup wt ptr */
|
|
_cpReg[26] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->wt_ptr),0,16);
|
|
_cpReg[27] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->wt_ptr),16,16);
|
|
|
|
/* setup rd ptr */
|
|
_cpReg[28] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->rd_ptr),0,16);
|
|
_cpReg[29] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(gpfifo->rd_ptr),16,16);
|
|
ppcsync();
|
|
|
|
if(__GX_CPGPLinkCheck()) {
|
|
_cpgplinked = 1;
|
|
gpfifo->cpufifo_ready = 1;
|
|
__GX_WriteFifoIntEnable(GX_ENABLE,GX_DISABLE);
|
|
__GX_FifoLink(GX_TRUE);
|
|
} else {
|
|
_cpgplinked = 0;
|
|
gpfifo->cpufifo_ready = 0;
|
|
__GX_WriteFifoIntEnable(GX_DISABLE,GX_DISABLE);
|
|
__GX_FifoLink(GX_FALSE);
|
|
}
|
|
|
|
__GX_WriteFifoIntReset(GX_TRUE,GX_TRUE);
|
|
__GX_FifoReadEnable();
|
|
_CPU_ISR_Restore(level);
|
|
}
|
|
|
|
void GX_GetGPFifo(GXFifoObj *fifo)
|
|
{
|
|
struct __gxfifo* ptr = (struct __gxfifo*)fifo;
|
|
struct __gxfifo* gpfifo = (struct __gxfifo*)&_gpfifo;
|
|
|
|
if(!_gxgpfifoready) return;
|
|
|
|
__GX_SaveFifo();
|
|
|
|
ptr->buf_start = gpfifo->buf_start;
|
|
ptr->buf_end = gpfifo->buf_end;
|
|
ptr->size = gpfifo->size;
|
|
ptr->rd_ptr = gpfifo->rd_ptr;
|
|
ptr->wt_ptr = gpfifo->wt_ptr;
|
|
ptr->rdwt_dst = gpfifo->rdwt_dst;
|
|
ptr->hi_mark = gpfifo->hi_mark;
|
|
ptr->lo_mark = gpfifo->lo_mark;
|
|
ptr->fifo_wrap = gpfifo->fifo_wrap;
|
|
ptr->gpfifo_ready = gpfifo->gpfifo_ready;
|
|
ptr->cpufifo_ready = gpfifo->cpufifo_ready;
|
|
}
|
|
|
|
void* GX_GetFifoBase(GXFifoObj *fifo)
|
|
{
|
|
return (void*)((struct __gxfifo*)fifo)->buf_start;
|
|
}
|
|
|
|
u32 GX_GetFifoSize(GXFifoObj *fifo)
|
|
{
|
|
return ((struct __gxfifo*)fifo)->size;
|
|
}
|
|
|
|
u32 GX_GetFifoCount(GXFifoObj *fifo)
|
|
{
|
|
return ((struct __gxfifo*)fifo)->rdwt_dst;
|
|
}
|
|
|
|
u8 GX_GetFifoWrap(GXFifoObj *fifo)
|
|
{
|
|
return ((struct __gxfifo*)fifo)->fifo_wrap;
|
|
}
|
|
|
|
u32 GX_GetOverflowCount()
|
|
{
|
|
return _gxoverflowcount;
|
|
}
|
|
|
|
u32 GX_ResetOverflowCount()
|
|
{
|
|
u32 ret = _gxoverflowcount;
|
|
_gxoverflowcount = 0;
|
|
return ret;
|
|
}
|
|
|
|
lwp_t GX_GetCurrentGXThread()
|
|
{
|
|
return _gxcurrentlwp;
|
|
}
|
|
|
|
lwp_t GX_SetCurrentGXThread()
|
|
{
|
|
u32 level;
|
|
|
|
_CPU_ISR_Disable(level);
|
|
lwp_t ret = _gxcurrentlwp;
|
|
_gxcurrentlwp = LWP_GetSelf();
|
|
_CPU_ISR_Restore(level);
|
|
|
|
return ret;
|
|
}
|
|
|
|
volatile void* GX_RedirectWriteGatherPipe(void *ptr)
|
|
{
|
|
u32 level;
|
|
struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
|
|
|
|
_CPU_ISR_Disable(level);
|
|
GX_Flush();
|
|
while(!IsWriteGatherBufferEmpty());
|
|
|
|
mtwpar(0x0C008000);
|
|
if(_cpgplinked) {
|
|
__GX_FifoLink(GX_FALSE);
|
|
__GX_WriteFifoIntEnable(GX_DISABLE,GX_DISABLE);
|
|
}
|
|
cpufifo->wt_ptr = (u32)MEM_PHYSICAL_TO_K0(_piReg[5]&~0x04000000);
|
|
|
|
_piReg[3] = 0;
|
|
_piReg[4] = 0x04000000;
|
|
_piReg[5] = (((u32)ptr&0x3FFFFFE0)&~0x04000000);
|
|
_sync();
|
|
|
|
_CPU_ISR_Restore(level);
|
|
|
|
return (volatile void*)0x0C008000;
|
|
}
|
|
|
|
void GX_RestoreWriteGatherPipe()
|
|
{
|
|
u32 level;
|
|
struct __gxfifo *cpufifo = (struct __gxfifo*)&_cpufifo;
|
|
|
|
_CPU_ISR_Disable(level);
|
|
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
|
|
ppcsync();
|
|
while(!IsWriteGatherBufferEmpty());
|
|
|
|
mtwpar(0x0C008000);
|
|
_piReg[3] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_start);
|
|
_piReg[4] = MEM_VIRTUAL_TO_PHYSICAL(cpufifo->buf_end);
|
|
_piReg[5] = (((u32)cpufifo->wt_ptr&0x3FFFFFE0)&~0x04000000);
|
|
if(_cpgplinked) {
|
|
__GX_WriteFifoIntReset(GX_TRUE,GX_TRUE);
|
|
__GX_WriteFifoIntEnable(GX_ENABLE,GX_DISABLE);
|
|
__GX_FifoLink(GX_TRUE);
|
|
}
|
|
_CPU_ISR_Restore(level);
|
|
}
|
|
|
|
void GX_Flush()
|
|
{
|
|
if(__gx->dirtyState)
|
|
__GX_SetDirtyState();
|
|
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
|
|
ppcsync();
|
|
}
|
|
|
|
void GX_EnableBreakPt(void *break_pt)
|
|
{
|
|
u32 level = 0;
|
|
_CPU_ISR_Disable(level);
|
|
__GX_FifoReadDisable();
|
|
_cpReg[30] = _SHIFTL(MEM_VIRTUAL_TO_PHYSICAL(break_pt),0,16);
|
|
_cpReg[31] = _SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(break_pt),16,16);
|
|
__gx->cpCRreg = (__gx->cpCRreg&~0x22)|0x22;
|
|
_cpReg[1] = __gx->cpCRreg;
|
|
_gxcurrbp = break_pt;
|
|
__GX_FifoReadEnable();
|
|
_CPU_ISR_Restore(level);
|
|
}
|
|
|
|
void GX_DisableBreakPt()
|
|
{
|
|
u32 level = 0;
|
|
_CPU_ISR_Disable(level);
|
|
__gx->cpCRreg = (__gx->cpCRreg&~0x22);
|
|
_cpReg[1] = __gx->cpCRreg;
|
|
_gxcurrbp = NULL;
|
|
_CPU_ISR_Restore(level);
|
|
}
|
|
|
|
#if defined(HW_DOL)
|
|
void GX_AbortFrame()
|
|
{
|
|
_piReg[6] = 1;
|
|
__GX_WaitAbort(50);
|
|
_piReg[6] = 0;
|
|
__GX_WaitAbort(5);
|
|
|
|
if(__GX_IsGPFifoReady())
|
|
__GX_CleanGPFifo();
|
|
}
|
|
#elif defined(HW_RVL)
|
|
void GX_AbortFrame()
|
|
{
|
|
__GX_Abort();
|
|
if(__GX_IsGPFifoReady()) {
|
|
__GX_CleanGPFifo();
|
|
__GX_InitRevBits();
|
|
|
|
__gx->dirtyState = 0;
|
|
GX_Flush();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void GX_SetDrawSync(u16 token)
|
|
{
|
|
u32 level = 0;
|
|
_CPU_ISR_Disable(level);
|
|
GX_LOAD_BP_REG(0x48000000 | token);
|
|
GX_LOAD_BP_REG(0x47000000 | token);
|
|
GX_Flush();
|
|
_CPU_ISR_Restore(level);
|
|
}
|
|
|
|
u16 GX_GetDrawSync()
|
|
{
|
|
return _peReg[7];
|
|
}
|
|
|
|
void GX_SetDrawDone()
|
|
{
|
|
u32 level;
|
|
_CPU_ISR_Disable(level);
|
|
GX_LOAD_BP_REG(0x45000002); // set draw done!
|
|
GX_Flush();
|
|
_gxfinished = 0;
|
|
_CPU_ISR_Restore(level);
|
|
}
|
|
|
|
|
|
void GX_WaitDrawDone()
|
|
{
|
|
u32 level;
|
|
_CPU_ISR_Disable(level);
|
|
while(!_gxfinished)
|
|
LWP_ThreadSleep(_gxwaitfinish);
|
|
_CPU_ISR_Restore(level);
|
|
}
|
|
|
|
void GX_DrawDone()
|
|
{
|
|
u32 level;
|
|
|
|
_CPU_ISR_Disable(level);
|
|
GX_LOAD_BP_REG(0x45000002); // set draw done!
|
|
GX_Flush();
|
|
|
|
_gxfinished = 0;
|
|
_CPU_ISR_Flash(level);
|
|
|
|
while(!_gxfinished)
|
|
LWP_ThreadSleep(_gxwaitfinish);
|
|
_CPU_ISR_Restore(level);
|
|
}
|
|
|
|
GXDrawDoneCallback GX_SetDrawDoneCallback(GXDrawDoneCallback cb)
|
|
{
|
|
u32 level;
|
|
|
|
_CPU_ISR_Disable(level);
|
|
GXDrawDoneCallback ret = drawDoneCB;
|
|
drawDoneCB = cb;
|
|
_CPU_ISR_Restore(level);
|
|
return ret;
|
|
}
|
|
|
|
GXDrawSyncCallback GX_SetDrawSyncCallback(GXDrawSyncCallback cb)
|
|
{
|
|
u32 level;
|
|
|
|
_CPU_ISR_Disable(level);
|
|
GXDrawSyncCallback ret = tokenCB;
|
|
tokenCB = cb;
|
|
_CPU_ISR_Restore(level);
|
|
return ret;
|
|
}
|
|
|
|
GXBreakPtCallback GX_SetBreakPtCallback(GXBreakPtCallback cb)
|
|
{
|
|
u32 level;
|
|
|
|
_CPU_ISR_Disable(level);
|
|
GXBreakPtCallback ret = breakPtCB;
|
|
breakPtCB = cb;
|
|
_CPU_ISR_Restore(level);
|
|
return ret;
|
|
}
|
|
|
|
void GX_PixModeSync()
|
|
{
|
|
GX_LOAD_BP_REG(__gx->peCntrl);
|
|
}
|
|
|
|
void GX_TexModeSync()
|
|
{
|
|
GX_LOAD_BP_REG(0x63000000);
|
|
}
|
|
|
|
void GX_SetMisc(u32 token,u32 value)
|
|
{
|
|
u32 cnt;
|
|
|
|
if(token==GX_MT_XF_FLUSH) {
|
|
__gx->xfFlushSafe = value;
|
|
cnt = cntlzw(__gx->xfFlushSafe);
|
|
__gx->xfFlushExp = _SHIFTR(cnt,5,16);
|
|
|
|
__gx->xfFlush = 1;
|
|
if(!__gx->xfFlushSafe) return;
|
|
|
|
__gx->dirtyState |= 0x0008;
|
|
} else if(token==GX_MT_DL_SAVE_CTX) {
|
|
__gx->saveDLctx = (value&0xff);
|
|
}
|
|
return;
|
|
}
|
|
|
|
void GX_SetViewportJitter(f32 xOrig,f32 yOrig,f32 wd,f32 ht,f32 nearZ,f32 farZ,u32 field)
|
|
{
|
|
f32 x0,y0,x1,y1,n,f,z;
|
|
static f32 Xfactor = 0.5;
|
|
static f32 Yfactor = 342.0;
|
|
static f32 Zfactor = 16777215.0;
|
|
|
|
if(!field) yOrig -= Xfactor;
|
|
|
|
x0 = wd*Xfactor;
|
|
y0 = (-ht)*Xfactor;
|
|
x1 = (xOrig+(wd*Xfactor))+Yfactor;
|
|
y1 = (yOrig+(ht*Xfactor))+Yfactor;
|
|
n = Zfactor*nearZ;
|
|
f = Zfactor*farZ;
|
|
z = f-n;
|
|
|
|
GX_LOAD_XF_REGS(0x101a,6);
|
|
wgPipe->F32 = x0;
|
|
wgPipe->F32 = y0;
|
|
wgPipe->F32 = z;
|
|
wgPipe->F32 = x1;
|
|
wgPipe->F32 = y1;
|
|
wgPipe->F32 = f;
|
|
}
|
|
|
|
void GX_SetViewport(f32 xOrig,f32 yOrig,f32 wd,f32 ht,f32 nearZ,f32 farZ)
|
|
{
|
|
GX_SetViewportJitter(xOrig,yOrig,wd,ht,nearZ,farZ,1);
|
|
}
|
|
|
|
void GX_LoadProjectionMtx(Mtx44 mt,u8 type)
|
|
{
|
|
f32 tmp[7];
|
|
|
|
((u32*)((void*)tmp))[6] = (u32)type;
|
|
tmp[0] = mt[0][0];
|
|
tmp[2] = mt[1][1];
|
|
tmp[4] = mt[2][2];
|
|
tmp[5] = mt[2][3];
|
|
|
|
switch(type) {
|
|
case GX_PERSPECTIVE:
|
|
tmp[1] = mt[0][2];
|
|
tmp[3] = mt[1][2];
|
|
break;
|
|
case GX_ORTHOGRAPHIC:
|
|
tmp[1] = mt[0][3];
|
|
tmp[3] = mt[1][3];
|
|
break;
|
|
default:
|
|
tmp[1] = 0.0;
|
|
tmp[3] = 0.0;
|
|
break;
|
|
}
|
|
|
|
GX_LOAD_XF_REGS(0x1020,7);
|
|
wgPipe->F32 = tmp[0];
|
|
wgPipe->F32 = tmp[1];
|
|
wgPipe->F32 = tmp[2];
|
|
wgPipe->F32 = tmp[3];
|
|
wgPipe->F32 = tmp[4];
|
|
wgPipe->F32 = tmp[5];
|
|
wgPipe->F32 = tmp[6];
|
|
}
|
|
|
|
static void __GetImageTileCount(u32 fmt,u16 wd,u16 ht,u32 *xtiles,u32 *ytiles,u32 *zplanes)
|
|
{
|
|
u32 xshift,yshift,tile;
|
|
|
|
switch(fmt) {
|
|
case GX_TF_I4:
|
|
case GX_TF_IA4:
|
|
case GX_CTF_R4:
|
|
case GX_CTF_RA4:
|
|
case GX_CTF_Z4:
|
|
xshift = 3;
|
|
yshift = 3;
|
|
break;
|
|
case GX_TF_Z8:
|
|
case GX_TF_I8:
|
|
case GX_CTF_A8:
|
|
case GX_CTF_R8:
|
|
case GX_CTF_G8:
|
|
case GX_CTF_B8:
|
|
case GX_CTF_Z8M:
|
|
case GX_CTF_Z8L:
|
|
xshift = 3;
|
|
yshift = 2;
|
|
break;
|
|
case GX_TF_IA8:
|
|
case GX_CTF_RA8:
|
|
case GX_CTF_RG8:
|
|
case GX_CTF_GB8:
|
|
case GX_TF_Z16:
|
|
case GX_TF_Z24X8:
|
|
case GX_CTF_Z16L:
|
|
case GX_TF_RGB565:
|
|
case GX_TF_RGB5A3:
|
|
case GX_TF_RGBA8:
|
|
xshift = 2;
|
|
yshift = 2;
|
|
break;
|
|
default:
|
|
xshift = 0;
|
|
yshift = 0;
|
|
break;
|
|
}
|
|
|
|
if(!(wd&0xffff)) wd = 1;
|
|
if(!(ht&0xffff)) ht = 1;
|
|
|
|
wd &= 0xffff;
|
|
tile = (wd+((1<<xshift)-1))>>xshift;
|
|
*xtiles = tile;
|
|
|
|
ht &= 0xffff;
|
|
tile = (ht+((1<<yshift)-1))>>yshift;
|
|
*ytiles = tile;
|
|
|
|
*zplanes = 1;
|
|
if(fmt==GX_TF_RGBA8 || fmt==GX_TF_Z24X8) *zplanes = 2;
|
|
}
|
|
|
|
void GX_SetCopyClear(GXColor color,u32 zvalue)
|
|
{
|
|
u32 val;
|
|
|
|
val = (_SHIFTL(color.a,8,8))|(color.r&0xff);
|
|
GX_LOAD_BP_REG(0x4f000000|val);
|
|
|
|
val = (_SHIFTL(color.g,8,8))|(color.b&0xff);
|
|
GX_LOAD_BP_REG(0x50000000|val);
|
|
|
|
val = zvalue&0x00ffffff;
|
|
GX_LOAD_BP_REG(0x51000000|val);
|
|
}
|
|
|
|
void GX_SetCopyClamp(u8 clamp)
|
|
{
|
|
__gx->dispCopyCntrl = (__gx->dispCopyCntrl&~1)|(clamp&1);
|
|
__gx->dispCopyCntrl = (__gx->dispCopyCntrl&~2)|(clamp&2);
|
|
}
|
|
|
|
void GX_SetDispCopyGamma(u8 gamma)
|
|
{
|
|
__gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0x180)|(_SHIFTL(gamma,7,2));
|
|
}
|
|
|
|
void GX_SetCopyFilter(u8 aa,u8 sample_pattern[12][2],u8 vf,u8 vfilter[7])
|
|
{
|
|
u32 reg01=0,reg02=0,reg03=0,reg04=0,reg53=0,reg54=0;
|
|
|
|
if(aa) {
|
|
reg01 = sample_pattern[0][0]&0xf;
|
|
reg01 = (reg01&~0xf0)|(_SHIFTL(sample_pattern[0][1],4,4));
|
|
reg01 = (reg01&~0xf00)|(_SHIFTL(sample_pattern[1][0],8,4));
|
|
reg01 = (reg01&~0xf000)|(_SHIFTL(sample_pattern[1][1],12,4));
|
|
reg01 = (reg01&~0xf0000)|(_SHIFTL(sample_pattern[2][0],16,4));
|
|
reg01 = (reg01&~0xf00000)|(_SHIFTL(sample_pattern[2][1],20,4));
|
|
reg01 = (reg01&~0xff000000)|(_SHIFTL(0x01,24,8));
|
|
|
|
reg02 = sample_pattern[3][0]&0xf;
|
|
reg02 = (reg02&~0xf0)|(_SHIFTL(sample_pattern[3][1],4,4));
|
|
reg02 = (reg02&~0xf00)|(_SHIFTL(sample_pattern[4][0],8,4));
|
|
reg02 = (reg02&~0xf000)|(_SHIFTL(sample_pattern[4][1],12,4));
|
|
reg02 = (reg02&~0xf0000)|(_SHIFTL(sample_pattern[5][0],16,4));
|
|
reg02 = (reg02&~0xf00000)|(_SHIFTL(sample_pattern[5][1],20,4));
|
|
reg02 = (reg02&~0xff000000)|(_SHIFTL(0x02,24,8));
|
|
|
|
reg03 = sample_pattern[6][0]&0xf;
|
|
reg03 = (reg03&~0xf0)|(_SHIFTL(sample_pattern[6][1],4,4));
|
|
reg03 = (reg03&~0xf00)|(_SHIFTL(sample_pattern[7][0],8,4));
|
|
reg03 = (reg03&~0xf000)|(_SHIFTL(sample_pattern[7][1],12,4));
|
|
reg03 = (reg03&~0xf0000)|(_SHIFTL(sample_pattern[8][0],16,4));
|
|
reg03 = (reg03&~0xf00000)|(_SHIFTL(sample_pattern[8][1],20,4));
|
|
reg03 = (reg03&~0xff000000)|(_SHIFTL(0x03,24,8));
|
|
|
|
reg04 = sample_pattern[9][0]&0xf;
|
|
reg04 = (reg04&~0xf0)|(_SHIFTL(sample_pattern[9][1],4,4));
|
|
reg04 = (reg04&~0xf00)|(_SHIFTL(sample_pattern[10][0],8,4));
|
|
reg04 = (reg04&~0xf000)|(_SHIFTL(sample_pattern[10][1],12,4));
|
|
reg04 = (reg04&~0xf0000)|(_SHIFTL(sample_pattern[11][0],16,4));
|
|
reg04 = (reg04&~0xf00000)|(_SHIFTL(sample_pattern[11][1],20,4));
|
|
reg04 = (reg04&~0xff000000)|(_SHIFTL(0x04,24,8));
|
|
} else {
|
|
reg01 = 0x01666666;
|
|
reg02 = 0x02666666;
|
|
reg03 = 0x03666666;
|
|
reg04 = 0x04666666;
|
|
}
|
|
GX_LOAD_BP_REG(reg01);
|
|
GX_LOAD_BP_REG(reg02);
|
|
GX_LOAD_BP_REG(reg03);
|
|
GX_LOAD_BP_REG(reg04);
|
|
|
|
reg53 = 0x53595000;
|
|
reg54 = 0x54000015;
|
|
if(vf) {
|
|
reg53 = 0x53000000|(vfilter[0]&0x3f);
|
|
reg53 = (reg53&~0xfc0)|(_SHIFTL(vfilter[1],6,6));
|
|
reg53 = (reg53&~0x3f000)|(_SHIFTL(vfilter[2],12,6));
|
|
reg53 = (reg53&~0xfc0000)|(_SHIFTL(vfilter[3],18,6));
|
|
|
|
reg54 = 0x54000000|(vfilter[4]&0x3f);
|
|
reg54 = (reg54&~0xfc0)|(_SHIFTL(vfilter[5],6,6));
|
|
reg54 = (reg54&~0x3f000)|(_SHIFTL(vfilter[6],12,6));
|
|
}
|
|
GX_LOAD_BP_REG(reg53);
|
|
GX_LOAD_BP_REG(reg54);
|
|
}
|
|
|
|
void GX_SetDispCopyFrame2Field(u8 mode)
|
|
{
|
|
__gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0x3000)|(_SHIFTL(mode,12,2));
|
|
}
|
|
|
|
u32 GX_SetDispCopyYScale(f32 yscale)
|
|
{
|
|
u32 ht,yScale = 0;
|
|
|
|
yScale = ((u32)(256.0f/yscale))&0x1ff;
|
|
GX_LOAD_BP_REG(0x4e000000|yScale);
|
|
|
|
__gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0x400)|(_SHIFTL(((256-yScale)>0),10,1));
|
|
ht = _SHIFTR(__gx->dispCopyWH,12,10)+1;
|
|
return __GX_GetNumXfbLines(ht,yScale);
|
|
}
|
|
|
|
void GX_SetDispCopyDst(u16 wd,u16 ht)
|
|
{
|
|
__gx->dispCopyDst = (__gx->dispCopyDst&~0x3ff)|(_SHIFTR(wd,4,10));
|
|
__gx->dispCopyDst = (__gx->dispCopyDst&~0xff000000)|(_SHIFTL(0x4d,24,8));
|
|
}
|
|
|
|
void GX_SetDispCopySrc(u16 left,u16 top,u16 wd,u16 ht)
|
|
{
|
|
__gx->dispCopyTL = (__gx->dispCopyTL&~0x00ffffff)|XY(left,top);
|
|
__gx->dispCopyTL = (__gx->dispCopyTL&~0xff000000)|(_SHIFTL(0x49,24,8));
|
|
__gx->dispCopyWH = (__gx->dispCopyWH&~0x00ffffff)|XY((wd-1),(ht-1));
|
|
__gx->dispCopyWH = (__gx->dispCopyWH&~0xff000000)|(_SHIFTL(0x4a,24,8));
|
|
}
|
|
|
|
void GX_CopyDisp(void *dest,u8 clear)
|
|
{
|
|
u8 clflag;
|
|
u32 val;
|
|
|
|
if(clear) {
|
|
val= (__gx->peZMode&~0xf)|0xf;
|
|
GX_LOAD_BP_REG(val);
|
|
val = (__gx->peCMode0&~0x3);
|
|
GX_LOAD_BP_REG(val);
|
|
}
|
|
|
|
clflag = 0;
|
|
if(clear || (__gx->peCntrl&0x7)==0x0003) {
|
|
if(__gx->peCntrl&0x40) {
|
|
clflag = 1;
|
|
val = (__gx->peCntrl&~0x40);
|
|
GX_LOAD_BP_REG(val);
|
|
}
|
|
}
|
|
|
|
GX_LOAD_BP_REG(__gx->dispCopyTL); // set source top
|
|
GX_LOAD_BP_REG(__gx->dispCopyWH);
|
|
|
|
GX_LOAD_BP_REG(__gx->dispCopyDst);
|
|
|
|
val = 0x4b000000|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(dest),5,24));
|
|
GX_LOAD_BP_REG(val);
|
|
|
|
__gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0x800)|(_SHIFTL(clear,11,1));
|
|
__gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0x4000)|0x4000;
|
|
__gx->dispCopyCntrl = (__gx->dispCopyCntrl&~0xff000000)|(_SHIFTL(0x52,24,8));
|
|
|
|
GX_LOAD_BP_REG(__gx->dispCopyCntrl);
|
|
|
|
if(clear) {
|
|
GX_LOAD_BP_REG(__gx->peZMode);
|
|
GX_LOAD_BP_REG(__gx->peCMode0);
|
|
}
|
|
if(clflag) GX_LOAD_BP_REG(__gx->peCntrl);
|
|
}
|
|
|
|
void GX_CopyTex(void *dest,u8 clear)
|
|
{
|
|
u8 clflag;
|
|
u32 val;
|
|
|
|
if(clear) {
|
|
val = (__gx->peZMode&~0xf)|0xf;
|
|
GX_LOAD_BP_REG(val);
|
|
val = (__gx->peCMode0&~0x3);
|
|
GX_LOAD_BP_REG(val);
|
|
}
|
|
|
|
clflag = 0;
|
|
val = __gx->peCntrl;
|
|
if(__gx->texCopyZTex && (val&0x7)!=0x0003) {
|
|
clflag = 1;
|
|
val = (val&~0x7)|0x0003;
|
|
}
|
|
if(clear || (val&0x7)==0x0003) {
|
|
if(val&0x40) {
|
|
clflag = 1;
|
|
val = (val&~0x40);
|
|
}
|
|
}
|
|
if(clflag) GX_LOAD_BP_REG(val);
|
|
|
|
val = 0x4b000000|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(dest),5,24));
|
|
|
|
GX_LOAD_BP_REG(__gx->texCopyTL);
|
|
GX_LOAD_BP_REG(__gx->texCopyWH);
|
|
GX_LOAD_BP_REG(__gx->texCopyDst);
|
|
GX_LOAD_BP_REG(val);
|
|
|
|
__gx->texCopyCntrl = (__gx->texCopyCntrl&~0x800)|(_SHIFTL(clear,11,1));
|
|
__gx->texCopyCntrl = (__gx->texCopyCntrl&~0x4000);
|
|
__gx->texCopyCntrl = (__gx->texCopyCntrl&~0xff000000)|(_SHIFTL(0x52,24,8));
|
|
GX_LOAD_BP_REG(__gx->texCopyCntrl);
|
|
|
|
if(clear) {
|
|
GX_LOAD_BP_REG(__gx->peZMode);
|
|
GX_LOAD_BP_REG(__gx->peCMode0);
|
|
}
|
|
if(clflag) GX_LOAD_BP_REG(__gx->peCntrl);
|
|
}
|
|
|
|
void GX_SetTexCopySrc(u16 left,u16 top,u16 wd,u16 ht)
|
|
{
|
|
__gx->texCopyTL = (__gx->texCopyTL&~0x00ffffff)|XY(left,top);
|
|
__gx->texCopyTL = (__gx->texCopyTL&~0xff000000)|(_SHIFTL(0x49,24,8));
|
|
__gx->texCopyWH = (__gx->texCopyWH&~0x00ffffff)|XY((wd-1),(ht-1));
|
|
__gx->texCopyWH = (__gx->texCopyWH&~0xff000000)|(_SHIFTL(0x4a,24,8));
|
|
}
|
|
|
|
void GX_SetTexCopyDst(u16 wd,u16 ht,u32 fmt,u8 mipmap)
|
|
{
|
|
u8 lfmt = fmt&0xf;
|
|
u32 xtiles,ytiles,zplanes;
|
|
|
|
__GetImageTileCount(fmt,wd,ht,&xtiles,&ytiles,&zplanes);
|
|
__gx->texCopyDst = (__gx->texCopyDst&~0x3ff)|((xtiles*zplanes)&0x3ff);
|
|
|
|
if(fmt==GX_TF_Z16) lfmt = 11;
|
|
if(fmt==GX_CTF_YUVA8 || (fmt>=GX_TF_I4 && fmt<GX_TF_RGB565)) __gx->texCopyCntrl = (__gx->texCopyCntrl&~0x18000)|0x18000;
|
|
else __gx->texCopyCntrl = (__gx->texCopyCntrl&~0x18000)|0x10000;
|
|
|
|
__gx->texCopyCntrl = (__gx->texCopyCntrl&~0x8)|(lfmt&0x8);
|
|
__gx->texCopyCntrl = (__gx->texCopyCntrl&~0x200)|(_SHIFTL(mipmap,9,1));
|
|
__gx->texCopyCntrl = (__gx->texCopyCntrl&~0x70)|(_SHIFTL(lfmt,4,3));
|
|
|
|
__gx->texCopyDst = (__gx->texCopyDst&~0xff000000)|(_SHIFTL(0x4d,24,8));
|
|
|
|
__gx->texCopyZTex = ((fmt&_GX_TF_ZTF)==_GX_TF_ZTF);
|
|
}
|
|
|
|
void GX_ClearBoundingBox()
|
|
{
|
|
GX_LOAD_BP_REG(0x550003ff);
|
|
GX_LOAD_BP_REG(0x560003ff);
|
|
}
|
|
|
|
void GX_BeginDispList(void *list,u32 size)
|
|
{
|
|
struct __gxfifo *fifo;
|
|
|
|
if(__gx->dirtyState)
|
|
__GX_SetDirtyState();
|
|
|
|
if(__gx->saveDLctx)
|
|
memcpy(_gx_saved_data,__gxregs,STRUCT_REGDEF_SIZE);
|
|
|
|
fifo = (struct __gxfifo*)&_gx_dl_fifoobj;
|
|
fifo->buf_start = (u32)list;
|
|
fifo->buf_end = (u32)list + size - 4;
|
|
fifo->size = size;
|
|
|
|
fifo->rd_ptr = (u32)list;
|
|
fifo->wt_ptr = (u32)list;
|
|
fifo->rdwt_dst = 0;
|
|
|
|
__gx->gxFifoUnlinked = 1;
|
|
|
|
GX_GetCPUFifo(&_gx_old_cpufifo);
|
|
GX_SetCPUFifo(&_gx_dl_fifoobj);
|
|
__GX_ResetWriteGatherPipe();
|
|
}
|
|
|
|
u32 GX_EndDispList()
|
|
{
|
|
u32 level;
|
|
u8 wrap = 0;
|
|
|
|
GX_GetCPUFifo(&_gx_dl_fifoobj);
|
|
GX_SetCPUFifo(&_gx_old_cpufifo);
|
|
|
|
if(__gx->saveDLctx) {
|
|
_CPU_ISR_Disable(level);
|
|
memcpy(__gxregs,_gx_saved_data,STRUCT_REGDEF_SIZE);
|
|
_CPU_ISR_Restore(level);
|
|
}
|
|
|
|
__gx->gxFifoUnlinked = 0;
|
|
|
|
wrap = GX_GetFifoWrap(&_gx_dl_fifoobj);
|
|
if(wrap) return 0;
|
|
|
|
return GX_GetFifoCount(&_gx_dl_fifoobj);
|
|
}
|
|
|
|
void GX_CallDispList(void *list,u32 nbytes)
|
|
{
|
|
if(__gx->dirtyState)
|
|
__GX_SetDirtyState();
|
|
|
|
if(!__gx->vcdClear)
|
|
__GX_SendFlushPrim();
|
|
|
|
wgPipe->U8 = 0x40; //call displaylist
|
|
wgPipe->U32 = MEM_VIRTUAL_TO_PHYSICAL(list);
|
|
wgPipe->U32 = nbytes;
|
|
}
|
|
|
|
void GX_SetChanCtrl(s32 channel,u8 enable,u8 ambsrc,u8 matsrc,u8 litmask,u8 diff_fn,u8 attn_fn)
|
|
{
|
|
u32 reg,difffn = (attn_fn==GX_AF_SPEC)?GX_DF_NONE:diff_fn;
|
|
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));
|
|
|
|
reg = (channel&0x03);
|
|
__gx->chnCntrl[reg] = val;
|
|
__gx->dirtyState |= (0x1000<<reg);
|
|
|
|
if(channel==GX_COLOR0A0) {
|
|
__gx->chnCntrl[2] = val;
|
|
__gx->dirtyState |= 0x5000;
|
|
} else {
|
|
__gx->chnCntrl[3] = val;
|
|
__gx->dirtyState |= 0xa000;
|
|
}
|
|
}
|
|
|
|
void GX_SetChanAmbColor(s32 channel,GXColor color)
|
|
{
|
|
u32 reg,val = (_SHIFTL(color.r,24,8))|(_SHIFTL(color.g,16,8))|(_SHIFTL(color.b,8,8))|0x00;
|
|
switch(channel) {
|
|
case GX_COLOR0:
|
|
reg = 0;
|
|
val |= (__gx->chnAmbColor[0]&0xff);
|
|
break;
|
|
case GX_COLOR1:
|
|
reg = 1;
|
|
val |= (__gx->chnAmbColor[1]&0xff);
|
|
break;
|
|
case GX_ALPHA0:
|
|
reg = 0;
|
|
val = ((__gx->chnAmbColor[0]&~0xff)|(color.a&0xff));
|
|
break;
|
|
case GX_ALPHA1:
|
|
reg = 1;
|
|
val = ((__gx->chnAmbColor[1]&~0xff)|(color.a&0xff));
|
|
break;
|
|
case GX_COLOR0A0:
|
|
reg = 0;
|
|
val |= (color.a&0xFF);
|
|
break;
|
|
case GX_COLOR1A1:
|
|
reg = 1;
|
|
val |= (color.a&0xFF);
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
__gx->chnAmbColor[reg] = val;
|
|
__gx->dirtyState |= (0x0100<<reg);
|
|
}
|
|
|
|
void GX_SetChanMatColor(s32 channel,GXColor color)
|
|
{
|
|
u32 reg,val = (_SHIFTL(color.r,24,8))|(_SHIFTL(color.g,16,8))|(_SHIFTL(color.b,8,8))|0x00;
|
|
switch(channel) {
|
|
case GX_COLOR0:
|
|
reg = 0;
|
|
val |= (__gx->chnMatColor[0]&0xff);
|
|
break;
|
|
case GX_COLOR1:
|
|
reg = 1;
|
|
val |= (__gx->chnMatColor[1]&0xff);
|
|
break;
|
|
case GX_ALPHA0:
|
|
reg = 0;
|
|
val = ((__gx->chnMatColor[0]&~0xff)|(color.a&0xff));
|
|
break;
|
|
case GX_ALPHA1:
|
|
reg = 1;
|
|
val = ((__gx->chnMatColor[1]&~0xff)|(color.a&0xff));
|
|
break;
|
|
case GX_COLOR0A0:
|
|
reg = 0;
|
|
val |= (color.a&0xFF);
|
|
break;
|
|
case GX_COLOR1A1:
|
|
reg = 1;
|
|
val |= (color.a&0xFF);
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
__gx->chnMatColor[reg] = val;
|
|
__gx->dirtyState |= (0x0400<<reg);
|
|
}
|
|
|
|
void GX_SetArray(u32 attr,void *ptr,u8 stride)
|
|
{
|
|
u32 idx = 0;
|
|
|
|
if(attr==GX_VA_NBT) attr = GX_VA_NRM;
|
|
if(attr>=GX_VA_POS && attr<=GX_LIGHTARRAY) {
|
|
idx = attr-GX_VA_POS;
|
|
GX_LOAD_CP_REG((0xA0+idx),(u32)MEM_VIRTUAL_TO_PHYSICAL(ptr));
|
|
GX_LOAD_CP_REG((0xB0+idx),(u32)stride);
|
|
}
|
|
}
|
|
|
|
static __inline__ void __SETVCDATTR(u8 attr,u8 type)
|
|
{
|
|
switch(attr) {
|
|
case GX_VA_PTNMTXIDX:
|
|
__gx->vcdLo = (__gx->vcdLo&~0x1)|(type&0x1);
|
|
break;
|
|
case GX_VA_TEX0MTXIDX:
|
|
__gx->vcdLo = (__gx->vcdLo&~0x2)|(_SHIFTL(type,1,1));
|
|
break;
|
|
case GX_VA_TEX1MTXIDX:
|
|
__gx->vcdLo = (__gx->vcdLo&~0x4)|(_SHIFTL(type,2,1));
|
|
break;
|
|
case GX_VA_TEX2MTXIDX:
|
|
__gx->vcdLo = (__gx->vcdLo&~0x8)|(_SHIFTL(type,3,1));
|
|
break;
|
|
case GX_VA_TEX3MTXIDX:
|
|
__gx->vcdLo = (__gx->vcdLo&~0x10)|(_SHIFTL(type,4,1));
|
|
break;
|
|
case GX_VA_TEX4MTXIDX:
|
|
__gx->vcdLo = (__gx->vcdLo&~0x20)|(_SHIFTL(type,5,1));
|
|
break;
|
|
case GX_VA_TEX5MTXIDX:
|
|
__gx->vcdLo = (__gx->vcdLo&~0x40)|(_SHIFTL(type,6,1));
|
|
break;
|
|
case GX_VA_TEX6MTXIDX:
|
|
__gx->vcdLo = (__gx->vcdLo&~0x80)|(_SHIFTL(type,7,1));
|
|
break;
|
|
case GX_VA_TEX7MTXIDX:
|
|
__gx->vcdLo = (__gx->vcdLo&~0x100)|(_SHIFTL(type,8,1));
|
|
break;
|
|
case GX_VA_POS:
|
|
__gx->vcdLo = (__gx->vcdLo&~0x600)|(_SHIFTL(type,9,2));
|
|
break;
|
|
case GX_VA_NRM:
|
|
__gx->vcdLo = (__gx->vcdLo&~0x1800)|(_SHIFTL(type,11,2));
|
|
__gx->vcdNrms = 1;
|
|
break;
|
|
case GX_VA_NBT:
|
|
__gx->vcdLo = (__gx->vcdLo&~0x1800)|(_SHIFTL(type,11,2));
|
|
__gx->vcdNrms = 2;
|
|
break;
|
|
case GX_VA_CLR0:
|
|
__gx->vcdLo = (__gx->vcdLo&~0x6000)|(_SHIFTL(type,13,2));
|
|
break;
|
|
case GX_VA_CLR1:
|
|
__gx->vcdLo = (__gx->vcdLo&~0x18000)|(_SHIFTL(type,15,2));
|
|
break;
|
|
case GX_VA_TEX0:
|
|
__gx->vcdHi = (__gx->vcdHi&~0x3)|(type&0x3);
|
|
break;
|
|
case GX_VA_TEX1:
|
|
__gx->vcdHi = (__gx->vcdHi&~0xc)|(_SHIFTL(type,2,2));
|
|
break;
|
|
case GX_VA_TEX2:
|
|
__gx->vcdHi = (__gx->vcdHi&~0x30)|(_SHIFTL(type,4,2));
|
|
break;
|
|
case GX_VA_TEX3:
|
|
__gx->vcdHi = (__gx->vcdHi&~0xc0)|(_SHIFTL(type,6,2));
|
|
break;
|
|
case GX_VA_TEX4:
|
|
__gx->vcdHi = (__gx->vcdHi&~0x300)|(_SHIFTL(type,8,2));
|
|
break;
|
|
case GX_VA_TEX5:
|
|
__gx->vcdHi = (__gx->vcdHi&~0xc00)|(_SHIFTL(type,10,2));
|
|
break;
|
|
case GX_VA_TEX6:
|
|
__gx->vcdHi = (__gx->vcdHi&~0x3000)|(_SHIFTL(type,12,2));
|
|
break;
|
|
case GX_VA_TEX7:
|
|
__gx->vcdHi = (__gx->vcdHi&~0xc000)|(_SHIFTL(type,14,2));
|
|
break;
|
|
}
|
|
}
|
|
|
|
void GX_SetVtxDesc(u8 attr,u8 type)
|
|
{
|
|
__SETVCDATTR(attr,type);
|
|
__gx->dirtyState |= 0x0008;
|
|
}
|
|
|
|
void GX_SetVtxDescv(GXVtxDesc *attr_list)
|
|
{
|
|
u32 i;
|
|
|
|
if(!attr_list) return;
|
|
|
|
for(i=0;i<GX_MAX_VTXDESC_LISTSIZE;i++){
|
|
if(attr_list[i].attr==GX_VA_NULL) break;
|
|
|
|
__SETVCDATTR(attr_list[i].attr,attr_list[i].type);
|
|
}
|
|
__gx->dirtyState |= 0x0008;
|
|
}
|
|
|
|
void GX_GetVtxDescv(GXVtxDesc *attr_list)
|
|
{
|
|
u32 count;
|
|
|
|
// Clear everything first
|
|
for(count=0;count<GX_MAX_VTXDESC_LISTSIZE;count++) {
|
|
attr_list[count].attr = GX_VA_NULL;
|
|
attr_list[count].type = 0;
|
|
}
|
|
|
|
count = 0;
|
|
if(__gx->vcdLo&0x1) {
|
|
attr_list[count].attr = GX_VA_PTNMTXIDX;
|
|
attr_list[count].type = __gx->vcdLo&0x1;
|
|
count++;
|
|
}
|
|
|
|
if(__gx->vcdLo&0x2) {
|
|
attr_list[count].attr = GX_VA_TEX0MTXIDX;
|
|
attr_list[count].type = _SHIFTR(__gx->vcdLo&0x2,1,1);
|
|
count++;
|
|
}
|
|
|
|
if(__gx->vcdLo&0x4) {
|
|
attr_list[count].attr = GX_VA_TEX1MTXIDX;
|
|
attr_list[count].type = _SHIFTR(__gx->vcdLo&0x4,2,1);
|
|
count++;
|
|
}
|
|
|
|
if(__gx->vcdLo&0x8) {
|
|
attr_list[count].attr = GX_VA_TEX2MTXIDX;
|
|
attr_list[count].type = _SHIFTR(__gx->vcdLo&0x8,3,1);
|
|
count++;
|
|
}
|
|
|
|
if(__gx->vcdLo&0x10) {
|
|
attr_list[count].attr = GX_VA_TEX3MTXIDX;
|
|
attr_list[count].type = _SHIFTR(__gx->vcdLo&0x10,4,1);
|
|
count++;
|
|
}
|
|
|
|
if(__gx->vcdLo&0x20) {
|
|
attr_list[count].attr = GX_VA_TEX4MTXIDX;
|
|
attr_list[count].type = _SHIFTR(__gx->vcdLo&0x20,5,1);
|
|
count++;
|
|
}
|
|
|
|
if(__gx->vcdLo&0x40) {
|
|
attr_list[count].attr = GX_VA_TEX5MTXIDX;
|
|
attr_list[count].type = _SHIFTR(__gx->vcdLo&0x40,6,1);
|
|
count++;
|
|
}
|
|
|
|
if(__gx->vcdLo&0x80) {
|
|
attr_list[count].attr = GX_VA_TEX6MTXIDX;
|
|
attr_list[count].type = _SHIFTR(__gx->vcdLo&0x80,7,1);
|
|
count++;
|
|
}
|
|
|
|
if(__gx->vcdLo&0x100) {
|
|
attr_list[count].attr = GX_VA_TEX7MTXIDX;
|
|
attr_list[count].type = _SHIFTR(__gx->vcdLo&0x100,8,1);
|
|
count++;
|
|
}
|
|
|
|
if(__gx->vcdLo&0x600) {
|
|
attr_list[count].attr = GX_VA_POS;
|
|
attr_list[count].type = _SHIFTR(__gx->vcdLo&0x600,9,2);
|
|
count++;
|
|
}
|
|
|
|
if(__gx->vcdLo&0x1800) {
|
|
if(__gx->vcdNrms==1) {
|
|
attr_list[count].attr = GX_VA_NRM;
|
|
attr_list[count].type = _SHIFTR(__gx->vcdLo&0x1800,11,2);
|
|
count++;
|
|
} else if(__gx->vcdNrms==2){
|
|
attr_list[count].attr = GX_VA_NBT;
|
|
attr_list[count].type = _SHIFTR(__gx->vcdLo&0x1800,11,2);
|
|
count++;
|
|
}
|
|
}
|
|
|
|
if(__gx->vcdLo&0x6000) {
|
|
attr_list[count].attr = GX_VA_CLR0;
|
|
attr_list[count].type = _SHIFTR(__gx->vcdLo&0x6000,13,2);
|
|
count++;
|
|
}
|
|
|
|
if(__gx->vcdLo&0x18000) {
|
|
attr_list[count].attr = GX_VA_CLR1;
|
|
attr_list[count].type = _SHIFTR(__gx->vcdLo&0x18000,15,2);
|
|
count++;
|
|
}
|
|
|
|
if(__gx->vcdHi&0x3) {
|
|
attr_list[count].attr = GX_VA_TEX0;
|
|
attr_list[count].type = __gx->vcdHi&0x3;
|
|
count++;
|
|
}
|
|
|
|
if(__gx->vcdHi&0xc) {
|
|
attr_list[count].attr = GX_VA_TEX1;
|
|
attr_list[count].type = _SHIFTR(__gx->vcdHi&0xc,2,2);
|
|
count++;
|
|
}
|
|
|
|
if(__gx->vcdHi&0x30) {
|
|
attr_list[count].attr = GX_VA_TEX2;
|
|
attr_list[count].type = _SHIFTR(__gx->vcdHi&0x30,4,2);
|
|
count++;
|
|
}
|
|
|
|
if(__gx->vcdHi&0xc0) {
|
|
attr_list[count].attr = GX_VA_TEX3;
|
|
attr_list[count].type = _SHIFTR(__gx->vcdHi&0xc0,6,2);
|
|
count++;
|
|
}
|
|
|
|
if(__gx->vcdHi&0x300) {
|
|
attr_list[count].attr = GX_VA_TEX4;
|
|
attr_list[count].type = _SHIFTR(__gx->vcdHi&0x300,8,2);
|
|
count++;
|
|
}
|
|
|
|
if(__gx->vcdHi&0xc00) {
|
|
attr_list[count].attr = GX_VA_TEX5;
|
|
attr_list[count].type = _SHIFTR(__gx->vcdHi&0xc00,10,2);
|
|
count++;
|
|
}
|
|
|
|
if(__gx->vcdHi&0x3000) {
|
|
attr_list[count].attr = GX_VA_TEX6;
|
|
attr_list[count].type = _SHIFTR(__gx->vcdHi&0x3000,12,2);
|
|
count++;
|
|
}
|
|
|
|
if(__gx->vcdHi&0xc000) {
|
|
attr_list[count].attr = GX_VA_TEX7;
|
|
attr_list[count].type = _SHIFTR(__gx->vcdHi&0xc000,14,2);
|
|
count++;
|
|
}
|
|
}
|
|
|
|
static __inline__ void __SETVCDFMT(u8 vtxfmt,u32 vtxattr,u32 comptype,u32 compsize,u32 frac)
|
|
{
|
|
u8 vat = (vtxfmt&7);
|
|
|
|
if(vtxattr==GX_VA_POS && (comptype==GX_POS_XY || comptype==GX_POS_XYZ)
|
|
&& (compsize>=GX_U8 && compsize<=GX_F32)) {
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1)|(comptype&1);
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0xe)|(_SHIFTL(compsize,1,3));
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1f0)|(_SHIFTL(frac,4,5));
|
|
if(frac)
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
|
|
} else if(vtxattr==GX_VA_NRM && comptype==GX_NRM_XYZ
|
|
&& (compsize==GX_S8 || compsize==GX_S16 || compsize==GX_F32)) {
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x200);
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1C00)|(_SHIFTL(compsize,10,3));
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x80000000);
|
|
} else if(vtxattr==GX_VA_NBT && (comptype==GX_NRM_NBT || comptype==GX_NRM_NBT3)
|
|
&& (compsize==GX_S8 || compsize==GX_S16 || compsize==GX_F32)) {
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x200)|0x200;
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1C00)|(_SHIFTL(compsize,10,3));
|
|
if(comptype==GX_NRM_NBT3)
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x80000000)|0x80000000;
|
|
} else if(vtxattr==GX_VA_CLR0 && (comptype==GX_CLR_RGB || comptype==GX_CLR_RGBA)
|
|
&& (compsize>=GX_RGB565 && compsize<=GX_RGBA8)) {
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x2000)|(_SHIFTL(comptype,13,1));
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1C000)|(_SHIFTL(compsize,14,3));
|
|
} else if(vtxattr==GX_VA_CLR1 && (comptype==GX_CLR_RGB || comptype==GX_CLR_RGBA)
|
|
&& (compsize>=GX_RGB565 && compsize<=GX_RGBA8)) {
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x20000)|(_SHIFTL(comptype,17,1));
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1C0000)|(_SHIFTL(compsize,18,3));
|
|
} else if(vtxattr==GX_VA_TEX0 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
|
|
&& (compsize>=GX_U8 && compsize<=GX_F32)) {
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x200000)|(_SHIFTL(comptype,21,1));
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x1C00000)|(_SHIFTL(compsize,22,3));
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x3E000000)|(_SHIFTL(frac,25,5));
|
|
if(frac)
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
|
|
} else if(vtxattr==GX_VA_TEX1 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
|
|
&& (compsize>=GX_U8 && compsize<=GX_F32)) {
|
|
__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x1)|(comptype&1);
|
|
__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0xe)|(_SHIFTL(compsize,1,3));
|
|
__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x1F0)|(_SHIFTL(frac,4,5));
|
|
if(frac)
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
|
|
} else if(vtxattr==GX_VA_TEX2 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
|
|
&& (compsize>=GX_U8 && compsize<=GX_F32)) {
|
|
__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x200)|(_SHIFTL(comptype,9,1));
|
|
__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x1C00)|(_SHIFTL(compsize,10,3));
|
|
__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x3E000)|(_SHIFTL(frac,13,5));
|
|
if(frac)
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
|
|
} else if(vtxattr==GX_VA_TEX3 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
|
|
&& (compsize>=GX_U8 && compsize<=GX_F32)) {
|
|
__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x40000)|(_SHIFTL(comptype,18,1));
|
|
__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x380000)|(_SHIFTL(compsize,19,3));
|
|
__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x7C00000)|(_SHIFTL(frac,22,5));
|
|
if(frac)
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
|
|
} else if(vtxattr==GX_VA_TEX4 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
|
|
&& (compsize>=GX_U8 && compsize<=GX_F32)) {
|
|
__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x8000000)|(_SHIFTL(comptype,27,1));
|
|
__gx->VAT1reg[vat] = (__gx->VAT1reg[vat]&~0x70000000)|(_SHIFTL(compsize,28,3));
|
|
__gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x1f)|(frac&0x1f);
|
|
if(frac)
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
|
|
} else if(vtxattr==GX_VA_TEX5 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
|
|
&& (compsize>=GX_U8 && compsize<=GX_F32)) {
|
|
__gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x20)|(_SHIFTL(comptype,5,1));
|
|
__gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x1C0)|(_SHIFTL(compsize,6,3));
|
|
__gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x3E00)|(_SHIFTL(frac,9,5));
|
|
if(frac)
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
|
|
} else if(vtxattr==GX_VA_TEX6 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
|
|
&& (compsize>=GX_U8 && compsize<=GX_F32)) {
|
|
__gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x4000)|(_SHIFTL(comptype,14,1));
|
|
__gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x38000)|(_SHIFTL(compsize,15,3));
|
|
__gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x7C0000)|(_SHIFTL(frac,18,5));
|
|
if(frac)
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
|
|
} else if(vtxattr==GX_VA_TEX7 && (comptype==GX_TEX_S || comptype==GX_TEX_ST)
|
|
&& (compsize>=GX_U8 && compsize<=GX_F32)) {
|
|
__gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x800000)|(_SHIFTL(comptype,23,1));
|
|
__gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0x7000000)|(_SHIFTL(compsize,24,3));
|
|
__gx->VAT2reg[vat] = (__gx->VAT2reg[vat]&~0xF8000000)|(_SHIFTL(frac,27,5));
|
|
if(frac)
|
|
__gx->VAT0reg[vat] = (__gx->VAT0reg[vat]&~0x40000000)|0x40000000;
|
|
}
|
|
}
|
|
|
|
void GX_SetVtxAttrFmt(u8 vtxfmt,u32 vtxattr,u32 comptype,u32 compsize,u32 frac)
|
|
{
|
|
__SETVCDFMT(vtxfmt,vtxattr,comptype,compsize,frac);
|
|
__gx->VATTable |= (1<<vtxfmt);
|
|
__gx->dirtyState |= 0x0010;
|
|
}
|
|
|
|
void GX_SetVtxAttrFmtv(u8 vtxfmt,GXVtxAttrFmt *attr_list)
|
|
{
|
|
u32 i;
|
|
|
|
for(i=0;i<GX_MAX_VTXATTRFMT_LISTSIZE;i++) {
|
|
if(attr_list[i].vtxattr==GX_VA_NULL) break;
|
|
|
|
__SETVCDFMT(vtxfmt,attr_list[i].vtxattr,attr_list[i].comptype,attr_list[i].compsize,attr_list[i].frac);
|
|
}
|
|
__gx->VATTable |= (1<<vtxfmt);
|
|
__gx->dirtyState |= 0x0010;
|
|
}
|
|
|
|
void GX_Begin(u8 primitve,u8 vtxfmt,u16 vtxcnt)
|
|
{
|
|
u8 reg = primitve|(vtxfmt&7);
|
|
|
|
if(__gx->dirtyState)
|
|
__GX_SetDirtyState();
|
|
|
|
wgPipe->U8 = reg;
|
|
wgPipe->U16 = vtxcnt;
|
|
}
|
|
|
|
void GX_SetTexCoordGen(u16 texcoord,u32 tgen_typ,u32 tgen_src,u32 mtxsrc)
|
|
{
|
|
GX_SetTexCoordGen2(texcoord,tgen_typ,tgen_src,mtxsrc,GX_FALSE,GX_DTTIDENTITY);
|
|
}
|
|
|
|
void GX_SetTexCoordGen2(u16 texcoord,u32 tgen_typ,u32 tgen_src,u32 mtxsrc,u32 normalize,u32 postmtx)
|
|
{
|
|
u32 txc;
|
|
u32 texcoords;
|
|
u8 vtxrow,stq;
|
|
|
|
if(texcoord>=GX_MAXCOORD) return;
|
|
|
|
stq = 0;
|
|
switch(tgen_src) {
|
|
case GX_TG_POS:
|
|
vtxrow = 0;
|
|
stq = 1;
|
|
break;
|
|
case GX_TG_NRM:
|
|
vtxrow = 1;
|
|
stq = 1;
|
|
break;
|
|
case GX_TG_BINRM:
|
|
vtxrow = 3;
|
|
stq = 1;
|
|
break;
|
|
case GX_TG_TANGENT:
|
|
vtxrow = 4;
|
|
stq = 1;
|
|
break;
|
|
case GX_TG_COLOR0:
|
|
vtxrow = 2;
|
|
break;
|
|
case GX_TG_COLOR1:
|
|
vtxrow = 2;
|
|
break;
|
|
case GX_TG_TEX0:
|
|
vtxrow = 5;
|
|
break;
|
|
case GX_TG_TEX1:
|
|
vtxrow = 6;
|
|
break;
|
|
case GX_TG_TEX2:
|
|
vtxrow = 7;
|
|
break;
|
|
case GX_TG_TEX3:
|
|
vtxrow = 8;
|
|
break;
|
|
case GX_TG_TEX4:
|
|
vtxrow = 9;
|
|
break;
|
|
case GX_TG_TEX5:
|
|
vtxrow = 10;
|
|
break;
|
|
case GX_TG_TEX6:
|
|
vtxrow = 11;
|
|
break;
|
|
case GX_TG_TEX7:
|
|
vtxrow = 12;
|
|
break;
|
|
default:
|
|
vtxrow = 5;
|
|
break;
|
|
}
|
|
|
|
texcoords = 0;
|
|
txc = (texcoord&7);
|
|
if((tgen_typ==GX_TG_MTX3x4 || tgen_typ==GX_TG_MTX2x4))
|
|
{
|
|
if(tgen_typ==GX_TG_MTX3x4) texcoords = 0x02;
|
|
|
|
texcoords |= (_SHIFTL(stq,2,1));
|
|
texcoords |= (_SHIFTL(vtxrow,7,5));
|
|
} else if((tgen_typ>=GX_TG_BUMP0 && tgen_typ<=GX_TG_BUMP7))
|
|
{
|
|
tgen_src -= GX_TG_TEXCOORD0;
|
|
tgen_typ -= GX_TG_BUMP0;
|
|
|
|
texcoords = 0x10;
|
|
texcoords |= (_SHIFTL(stq,2,1));
|
|
texcoords |= (_SHIFTL(vtxrow,7,5));
|
|
texcoords |= (_SHIFTL(tgen_src,12,3));
|
|
texcoords |= (_SHIFTL(tgen_typ,15,3));
|
|
} else if(tgen_typ==GX_TG_SRTG) {
|
|
if(tgen_src==GX_TG_COLOR0) texcoords = 0x20;
|
|
else if(tgen_src==GX_TG_COLOR1) texcoords = 0x30;
|
|
texcoords |= (_SHIFTL(stq,2,1));
|
|
texcoords |= (_SHIFTL(2,7,5));
|
|
}
|
|
|
|
postmtx -= GX_DTTMTX0;
|
|
__gx->texCoordGen[txc] = texcoords;
|
|
__gx->texCoordGen2[txc] = ((_SHIFTL(normalize,8,1))|(postmtx&0x3f));
|
|
|
|
switch(texcoord) {
|
|
case GX_TEXCOORD0:
|
|
__gx->mtxIdxLo = (__gx->mtxIdxLo&~0xfc0)|(_SHIFTL(mtxsrc,6,6));
|
|
break;
|
|
case GX_TEXCOORD1:
|
|
__gx->mtxIdxLo = (__gx->mtxIdxLo&~0x3f000)|(_SHIFTL(mtxsrc,12,6));
|
|
break;
|
|
case GX_TEXCOORD2:
|
|
__gx->mtxIdxLo = (__gx->mtxIdxLo&~0xfc0000)|(_SHIFTL(mtxsrc,18,6));
|
|
break;
|
|
case GX_TEXCOORD3:
|
|
__gx->mtxIdxLo = (__gx->mtxIdxLo&~0x3f000000)|(_SHIFTL(mtxsrc,24,6));
|
|
break;
|
|
case GX_TEXCOORD4:
|
|
__gx->mtxIdxHi = (__gx->mtxIdxHi&~0x3f)|(mtxsrc&0x3f);
|
|
break;
|
|
case GX_TEXCOORD5:
|
|
__gx->mtxIdxHi = (__gx->mtxIdxHi&~0xfc0)|(_SHIFTL(mtxsrc,6,6));
|
|
break;
|
|
case GX_TEXCOORD6:
|
|
__gx->mtxIdxHi = (__gx->mtxIdxHi&~0x3f000)|(_SHIFTL(mtxsrc,12,6));
|
|
break;
|
|
case GX_TEXCOORD7:
|
|
__gx->mtxIdxHi = (__gx->mtxIdxHi&~0xfc0000)|(_SHIFTL(mtxsrc,18,6));
|
|
break;
|
|
}
|
|
__gx->dirtyState |= (0x04000000|(0x00010000<<texcoord));
|
|
}
|
|
|
|
void GX_SetZTexture(u8 op,u8 fmt,u32 bias)
|
|
{
|
|
u32 val = 0;
|
|
|
|
if(fmt==GX_TF_Z8) fmt = 0;
|
|
else if(fmt==GX_TF_Z16) fmt = 1;
|
|
else fmt = 2;
|
|
|
|
val = (u32)(_SHIFTL(op,2,2))|(fmt&3);
|
|
GX_LOAD_BP_REG(0xF4000000|(bias&0x00FFFFFF));
|
|
GX_LOAD_BP_REG(0xF5000000|(val&0x00FFFFFF));
|
|
}
|
|
|
|
static inline void WriteMtxPS4x3(register Mtx mt,register void *wgpipe)
|
|
{
|
|
register f32 tmp0,tmp1,tmp2,tmp3,tmp4,tmp5;
|
|
__asm__ __volatile__ (
|
|
"psq_l %0,0(%6),0,0\n\
|
|
psq_l %1,8(%6),0,0\n\
|
|
psq_l %2,16(%6),0,0\n\
|
|
psq_l %3,24(%6),0,0\n\
|
|
psq_l %4,32(%6),0,0\n\
|
|
psq_l %5,40(%6),0,0\n\
|
|
psq_st %0,0(%7),0,0\n\
|
|
psq_st %1,0(%7),0,0\n\
|
|
psq_st %2,0(%7),0,0\n\
|
|
psq_st %3,0(%7),0,0\n\
|
|
psq_st %4,0(%7),0,0\n\
|
|
psq_st %5,0(%7),0,0"
|
|
: "=&f"(tmp0),"=&f"(tmp1),"=&f"(tmp2),"=&f"(tmp3),"=&f"(tmp4),"=&f"(tmp5)
|
|
: "b"(mt), "b"(wgpipe)
|
|
: "memory"
|
|
);
|
|
}
|
|
|
|
static inline void WriteMtxPS3x3from4x3(register Mtx mt,register void *wgpipe)
|
|
{
|
|
register f32 tmp0,tmp1,tmp2,tmp3,tmp4,tmp5;
|
|
__asm__ __volatile__
|
|
("psq_l %0,0(%6),0,0\n\
|
|
lfs %1,8(%6)\n\
|
|
psq_l %2,16(%6),0,0\n\
|
|
lfs %3,24(%6)\n\
|
|
psq_l %4,32(%6),0,0\n\
|
|
lfs %5,40(%6)\n\
|
|
psq_st %0,0(%7),0,0\n\
|
|
stfs %1,0(%7)\n\
|
|
psq_st %2,0(%7),0,0\n\
|
|
stfs %3,0(%7)\n\
|
|
psq_st %4,0(%7),0,0\n\
|
|
stfs %5,0(%7)"
|
|
: "=&f"(tmp0),"=&f"(tmp1),"=&f"(tmp2),"=&f"(tmp3),"=&f"(tmp4),"=&f"(tmp5)
|
|
: "b"(mt), "b"(wgpipe)
|
|
: "memory"
|
|
);
|
|
}
|
|
|
|
static inline void WriteMtxPS3x3(register Mtx33 mt,register void *wgpipe)
|
|
{
|
|
register f32 tmp0,tmp1,tmp2,tmp3,tmp4;
|
|
__asm__ __volatile__
|
|
("psq_l %0,0(%5),0,0\n\
|
|
psq_l %1,8(%5),0,0\n\
|
|
psq_l %2,16(%5),0,0\n\
|
|
psq_l %3,24(%5),0,0\n\
|
|
lfs %4,32(%5)\n\
|
|
psq_st %0,0(%6),0,0\n\
|
|
psq_st %1,0(%6),0,0\n\
|
|
psq_st %2,0(%6),0,0\n\
|
|
psq_st %3,0(%6),0,0\n\
|
|
stfs %4,0(%6)"
|
|
: "=&f"(tmp0),"=&f"(tmp1),"=&f"(tmp2),"=&f"(tmp3),"=&f"(tmp4)
|
|
: "b"(mt), "b"(wgpipe)
|
|
: "memory"
|
|
);
|
|
}
|
|
|
|
static inline void WriteMtxPS4x2(register Mtx mt,register void *wgpipe)
|
|
{
|
|
register f32 tmp0,tmp1,tmp2,tmp3;
|
|
__asm__ __volatile__
|
|
("psq_l %0,0(%4),0,0\n\
|
|
psq_l %1,8(%4),0,0\n\
|
|
psq_l %2,16(%4),0,0\n\
|
|
psq_l %3,24(%4),0,0\n\
|
|
psq_st %0,0(%5),0,0\n\
|
|
psq_st %1,0(%5),0,0\n\
|
|
psq_st %2,0(%5),0,0\n\
|
|
psq_st %3,0(%5),0,0"
|
|
: "=&f"(tmp0),"=&f"(tmp1),"=&f"(tmp2),"=&f"(tmp3)
|
|
: "b"(mt), "b"(wgpipe)
|
|
: "memory"
|
|
);
|
|
}
|
|
|
|
void GX_LoadPosMtxImm(Mtx mt,u32 pnidx)
|
|
{
|
|
GX_LOAD_XF_REGS((0x0000|(_SHIFTL(pnidx,2,8))),12);
|
|
WriteMtxPS4x3(mt,(void*)wgPipe);
|
|
}
|
|
|
|
void GX_LoadPosMtxIdx(u16 mtxidx,u32 pnidx)
|
|
{
|
|
wgPipe->U8 = 0x20;
|
|
wgPipe->U32 = ((_SHIFTL(mtxidx,16,16))|0xb000|(_SHIFTL(pnidx,2,8)));
|
|
}
|
|
|
|
void GX_LoadNrmMtxImm(Mtx mt,u32 pnidx)
|
|
{
|
|
GX_LOAD_XF_REGS((0x0400|(pnidx*3)),9);
|
|
WriteMtxPS3x3from4x3(mt,(void*)wgPipe);
|
|
}
|
|
|
|
void GX_LoadNrmMtxImm3x3(Mtx33 mt,u32 pnidx)
|
|
{
|
|
GX_LOAD_XF_REGS((0x0400|(pnidx*3)),9);
|
|
WriteMtxPS3x3(mt,(void*)wgPipe);
|
|
}
|
|
|
|
void GX_LoadNrmMtxIdx3x3(u16 mtxidx,u32 pnidx)
|
|
{
|
|
wgPipe->U8 = 0x28;
|
|
wgPipe->U32 = ((_SHIFTL(mtxidx,16,16))|0x8000|(0x0400|(pnidx*3)));
|
|
}
|
|
|
|
void GX_LoadTexMtxImm(Mtx mt,u32 texidx,u8 type)
|
|
{
|
|
u32 addr = 0;
|
|
u32 rows = (type==GX_MTX2x4)?2:3;
|
|
|
|
if(texidx<GX_DTTMTX0) addr = (_SHIFTL(texidx,2,8));
|
|
else {
|
|
texidx -= GX_DTTMTX0;
|
|
addr = 0x0500 + (_SHIFTL(texidx,2,8));
|
|
}
|
|
|
|
GX_LOAD_XF_REGS(addr,(rows*4));
|
|
if(type==GX_MTX2x4)
|
|
WriteMtxPS4x2(mt,(void*)wgPipe);
|
|
else
|
|
WriteMtxPS4x3(mt,(void*)wgPipe);
|
|
}
|
|
|
|
void GX_LoadTexMtxIdx(u16 mtxidx,u32 texidx,u8 type)
|
|
{
|
|
u32 addr,size = (type==GX_MTX2x4)?7:11;
|
|
|
|
if(texidx<GX_DTTMTX0) addr = 0x0000|(_SHIFTL(texidx,2,8));
|
|
else addr = 0x0500|(_SHIFTL((texidx-GX_DTTMTX0),2,8));
|
|
|
|
wgPipe->U8 = 0x30;
|
|
wgPipe->U32 = ((_SHIFTL(mtxidx,16,16))|(_SHIFTL(size,12,4))|addr);
|
|
}
|
|
|
|
void GX_SetCurrentMtx(u32 mtx)
|
|
{
|
|
__gx->mtxIdxLo = (__gx->mtxIdxLo&~0x3f)|(mtx&0x3f);
|
|
__gx->dirtyState |= 0x04000000;
|
|
}
|
|
|
|
void GX_SetNumTexGens(u32 nr)
|
|
{
|
|
__gx->genMode = (__gx->genMode&~0xf)|(nr&0xf);
|
|
__gx->dirtyState |= 0x02000004;
|
|
}
|
|
|
|
void GX_InvVtxCache()
|
|
{
|
|
wgPipe->U8 = 0x48; // vertex cache weg
|
|
}
|
|
|
|
void GX_SetZMode(u8 enable,u8 func,u8 update_enable)
|
|
{
|
|
__gx->peZMode = (__gx->peZMode&~0x1)|(enable&1);
|
|
__gx->peZMode = (__gx->peZMode&~0xe)|(_SHIFTL(func,1,3));
|
|
__gx->peZMode = (__gx->peZMode&~0x10)|(_SHIFTL(update_enable,4,1));
|
|
GX_LOAD_BP_REG(__gx->peZMode);
|
|
}
|
|
|
|
u32 GX_GetTexObjFmt(GXTexObj *obj)
|
|
{
|
|
return ((struct __gx_texobj*)obj)->tex_fmt;
|
|
}
|
|
|
|
u32 GX_GetTexObjMipMap(GXTexObj *obj)
|
|
{
|
|
return (((struct __gx_texobj*)obj)->tex_flag&0x01);
|
|
}
|
|
void* GX_GetTexObjData(GXTexObj *obj)
|
|
{
|
|
return (void*)(_SHIFTL(((struct __gx_texobj*)obj)->tex_maddr & 0x00ffffff,5,24));
|
|
}
|
|
|
|
u8 GX_GetTexObjWrapS(GXTexObj* obj)
|
|
{
|
|
return ((struct __gx_texobj*)obj)->tex_filt & 0x03;
|
|
}
|
|
|
|
u8 GX_GetTexObjWrapT(GXTexObj* obj)
|
|
{
|
|
return _SHIFTR(((struct __gx_texobj*)obj)->tex_filt & 0x0c, 2, 2);
|
|
}
|
|
|
|
u16 GX_GetTexObjHeight(GXTexObj* obj)
|
|
{
|
|
return _SHIFTR(((struct __gx_texobj*)obj)->tex_size & 0xffc00, 10, 10) + 1;
|
|
}
|
|
|
|
u16 GX_GetTexObjWidth(GXTexObj* obj)
|
|
{
|
|
return (((struct __gx_texobj*)obj)->tex_size & 0x3ff) + 1;
|
|
}
|
|
|
|
|
|
void GX_GetTexObjAll(GXTexObj* obj, void** image_ptr, u16* width, u16* height,
|
|
u8* format, u8* wrap_s, u8* wrap_t, u8* mipmap)
|
|
{
|
|
struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
|
|
*image_ptr = (void*)(_SHIFTL(ptr->tex_maddr & 0x00ffffff,5,24));
|
|
*width = (ptr->tex_size & 0x3ff) + 1;
|
|
*height = _SHIFTR(ptr->tex_size & 0xffc00, 10, 10) + 1;
|
|
*format = ptr->tex_fmt;
|
|
*wrap_s = ptr->tex_filt & 0x03;
|
|
*wrap_t = _SHIFTR(ptr->tex_filt & 0x0c, 2, 2);
|
|
*mipmap = ptr->tex_flag & 0x01;
|
|
}
|
|
u32 GX_GetTexBufferSize(u16 wd,u16 ht,u32 fmt,u8 mipmap,u8 maxlod)
|
|
{
|
|
u32 xshift,yshift,xtiles,ytiles,bitsize,size;
|
|
|
|
switch(fmt) {
|
|
case GX_TF_I4:
|
|
case GX_TF_CMPR:
|
|
case GX_CTF_R4:
|
|
case GX_CTF_RA4:
|
|
case GX_CTF_Z4:
|
|
xshift = 3;
|
|
yshift = 3;
|
|
break;
|
|
case GX_TF_Z8:
|
|
case GX_TF_I8:
|
|
case GX_TF_IA4:
|
|
case GX_CTF_A8:
|
|
case GX_CTF_R8:
|
|
case GX_CTF_G8:
|
|
case GX_CTF_B8:
|
|
case GX_CTF_RG8:
|
|
case GX_CTF_GB8:
|
|
case GX_CTF_Z8M:
|
|
case GX_CTF_Z8L:
|
|
xshift = 3;
|
|
yshift = 2;
|
|
break;
|
|
case GX_TF_IA8:
|
|
case GX_TF_Z16:
|
|
case GX_TF_Z24X8:
|
|
case GX_TF_RGB565:
|
|
case GX_TF_RGB5A3:
|
|
case GX_TF_RGBA8:
|
|
case GX_CTF_Z16L:
|
|
case GX_CTF_RA8:
|
|
xshift = 2;
|
|
yshift = 2;
|
|
break;
|
|
default:
|
|
xshift = 2;
|
|
yshift = 2;
|
|
break;
|
|
}
|
|
|
|
bitsize = 32;
|
|
if(fmt==GX_TF_RGBA8 || fmt==GX_TF_Z24X8) bitsize = 64;
|
|
|
|
size = 0;
|
|
if(mipmap) {
|
|
u32 cnt = (maxlod&0xff);
|
|
while(cnt) {
|
|
u32 w = wd&0xffff;
|
|
u32 h = ht&0xffff;
|
|
xtiles = ((w+(1<<xshift))-1)>>xshift;
|
|
ytiles = ((h+(1<<yshift))-1)>>yshift;
|
|
if(cnt==0) return size;
|
|
|
|
size += ((xtiles*ytiles)*bitsize);
|
|
if(w==0x0001 && h==0x0001) return size;
|
|
if(wd>0x0001) wd = (w>>1);
|
|
else wd = 0x0001;
|
|
if(ht>0x0001) ht = (h>>1);
|
|
else ht = 0x0001;
|
|
|
|
--cnt;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
wd &= 0xffff;
|
|
xtiles = (wd+((1<<xshift)-1))>>xshift;
|
|
|
|
ht &= 0xffff;
|
|
ytiles = (ht+((1<<yshift)-1))>>yshift;
|
|
|
|
size = ((xtiles*ytiles)*bitsize);
|
|
|
|
return size;
|
|
}
|
|
|
|
void GX_InitTexCacheRegion(GXTexRegion *region,u8 is32bmipmap,u32 tmem_even,u8 size_even,u32 tmem_odd,u8 size_odd)
|
|
{
|
|
u32 sze = 0;
|
|
struct __gx_texregion *ptr = (struct __gx_texregion*)region;
|
|
|
|
switch(size_even) {
|
|
case GX_TEXCACHE_32K:
|
|
sze = 3;
|
|
break;
|
|
case GX_TEXCACHE_128K:
|
|
sze = 4;
|
|
break;
|
|
case GX_TEXCACHE_512K:
|
|
sze = 5;
|
|
break;
|
|
default:
|
|
sze = 3;
|
|
break;
|
|
}
|
|
ptr->tmem_even = 0;
|
|
ptr->tmem_even = (ptr->tmem_even&~0x7fff)|(_SHIFTR(tmem_even,5,15));
|
|
ptr->tmem_even = (ptr->tmem_even&~0x38000)|(_SHIFTL(sze,15,3));
|
|
ptr->tmem_even = (ptr->tmem_even&~0x1C0000)|(_SHIFTL(sze,18,3));
|
|
|
|
switch(size_odd) {
|
|
case GX_TEXCACHE_32K:
|
|
sze = 3;
|
|
break;
|
|
case GX_TEXCACHE_128K:
|
|
sze = 4;
|
|
break;
|
|
case GX_TEXCACHE_512K:
|
|
sze = 5;
|
|
break;
|
|
default:
|
|
sze = 3;
|
|
break;
|
|
}
|
|
ptr->tmem_odd = 0;
|
|
ptr->tmem_odd = (ptr->tmem_odd&~0x7fff)|(_SHIFTR(tmem_odd,5,15));
|
|
ptr->tmem_odd = (ptr->tmem_odd&~0x38000)|(_SHIFTL(sze,15,3));
|
|
ptr->tmem_odd = (ptr->tmem_odd&~0x1C0000)|(_SHIFTL(sze,18,3));
|
|
|
|
ptr->ismipmap = is32bmipmap;
|
|
ptr->iscached = 1;
|
|
}
|
|
|
|
void GX_InitTexPreloadRegion(GXTexRegion *region,u32 tmem_even,u32 size_even,u32 tmem_odd,u32 size_odd)
|
|
{
|
|
struct __gx_texregion *ptr = (struct __gx_texregion*)region;
|
|
|
|
ptr->tmem_even = 0;
|
|
ptr->tmem_even = (ptr->tmem_even&~0x7FFF)|(_SHIFTR(tmem_even,5,15));
|
|
ptr->tmem_even = (ptr->tmem_even&~0x200000)|0x200000;
|
|
|
|
ptr->tmem_odd = 0;
|
|
ptr->tmem_odd = (ptr->tmem_odd&~0x7FFF)|(_SHIFTR(tmem_odd,5,15));
|
|
|
|
ptr->size_even = _SHIFTR(size_even,5,16);
|
|
ptr->size_odd = _SHIFTR(size_odd,5,16);
|
|
|
|
ptr->ismipmap = 0;
|
|
ptr->iscached = 0;
|
|
}
|
|
|
|
void GX_InitTlutRegion(GXTlutRegion *region,u32 tmem_addr,u8 tlut_sz)
|
|
{
|
|
struct __gx_tlutregion *ptr = (struct __gx_tlutregion*)region;
|
|
|
|
tmem_addr -= 0x80000;
|
|
|
|
ptr->tmem_addr_conf = 0;
|
|
ptr->tmem_addr_conf = (ptr->tmem_addr_conf&~0x3ff)|(_SHIFTR(tmem_addr,9,10));
|
|
ptr->tmem_addr_conf = (ptr->tmem_addr_conf&~0x1FFC00)|(_SHIFTL(tlut_sz,10,10));
|
|
ptr->tmem_addr_conf = (ptr->tmem_addr_conf&~0xff000000)|(_SHIFTL(0x65,24,8));
|
|
}
|
|
|
|
void GX_InitTexObj(GXTexObj *obj,void *img_ptr,u16 wd,u16 ht,u8 fmt,u8 wrap_s,u8 wrap_t,u8 mipmap)
|
|
{
|
|
u32 nwd,nht;
|
|
u32 xshift,yshift;
|
|
struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
|
|
|
|
if(!obj) return;
|
|
|
|
memset(obj,0,sizeof(GXTexObj));
|
|
|
|
ptr->tex_filt = (ptr->tex_filt&~0x03)|(wrap_s&3);
|
|
ptr->tex_filt = (ptr->tex_filt&~0x0c)|(_SHIFTL(wrap_t,2,2));
|
|
ptr->tex_filt = (ptr->tex_filt&~0x10)|0x10;
|
|
|
|
if(mipmap) {
|
|
ptr->tex_flag |= 0x01;
|
|
if(fmt==GX_TF_CI4 || fmt==GX_TF_CI8 || fmt==GX_TF_CI14)
|
|
ptr->tex_filt = (ptr->tex_filt&~0xe0)|0x00a0;
|
|
else
|
|
ptr->tex_filt = (ptr->tex_filt&~0xe0)|0x00c0;
|
|
} else
|
|
ptr->tex_filt= (ptr->tex_filt&~0xE0)|0x0080;
|
|
|
|
ptr->tex_fmt = fmt;
|
|
ptr->tex_size = (ptr->tex_size&~0x3ff)|((wd-1)&0x3ff);
|
|
ptr->tex_size = (ptr->tex_size&~0xFFC00)|(_SHIFTL((ht-1),10,10));
|
|
ptr->tex_size = (ptr->tex_size&~0xF00000)|(_SHIFTL(fmt,20,4));
|
|
ptr->tex_maddr = (ptr->tex_maddr&~0x00ffffff)|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(img_ptr),5,24));
|
|
|
|
switch(fmt) {
|
|
case GX_TF_I4:
|
|
case GX_TF_CI4:
|
|
xshift = 3;
|
|
yshift = 3;
|
|
ptr->tex_tile_type = 1;
|
|
break;
|
|
case GX_TF_I8:
|
|
case GX_TF_IA4:
|
|
case GX_TF_CI8:
|
|
xshift = 3;
|
|
yshift = 2;
|
|
ptr->tex_tile_type = 2;
|
|
break;
|
|
case GX_TF_IA8:
|
|
case GX_TF_RGB565:
|
|
case GX_TF_RGB5A3:
|
|
case GX_TF_RGBA8:
|
|
xshift = 2;
|
|
yshift = 2;
|
|
ptr->tex_tile_type = 2;
|
|
break;
|
|
case GX_TF_CI14:
|
|
xshift = 2;
|
|
yshift = 2;
|
|
ptr->tex_tile_type = 3;
|
|
break;
|
|
case GX_TF_CMPR:
|
|
xshift = 3;
|
|
yshift = 3;
|
|
ptr->tex_tile_type = 0;
|
|
break;
|
|
default:
|
|
xshift = 2;
|
|
yshift = 2;
|
|
ptr->tex_tile_type = 2;
|
|
break;
|
|
}
|
|
|
|
nwd = ((wd+(1<<xshift))-1)>>xshift;
|
|
nht = ((ht+(1<<yshift))-1)>>yshift;
|
|
ptr->tex_tile_cnt = (nwd*nht)&0x7fff;
|
|
|
|
ptr->tex_flag |= 0x0002;
|
|
}
|
|
|
|
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)
|
|
{
|
|
struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
|
|
|
|
GX_InitTexObj(obj,img_ptr,wd,ht,fmt,wrap_s,wrap_t,mipmap);
|
|
ptr->tex_flag &= ~0x02;
|
|
ptr->tex_tlut = tlut_name;
|
|
}
|
|
|
|
void GX_InitTexObjLOD(GXTexObj *obj,u8 minfilt,u8 magfilt,f32 minlod,f32 maxlod,f32 lodbias,u8 biasclamp,u8 edgelod,u8 maxaniso)
|
|
{
|
|
struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
|
|
static u8 GX2HWFiltConv[] = {0x00,0x04,0x01,0x05,0x02,0x06,0x00,0x00};
|
|
//static u8 HW2GXFiltConv[] = {0x00,0x02,0x04,0x00,0x01,0x03,0x05,0x00};
|
|
|
|
if(lodbias<-4.0f) lodbias = -4.0f;
|
|
else if(lodbias==4.0f) lodbias = 3.99f;
|
|
|
|
ptr->tex_filt = (ptr->tex_filt&~0x1fe00)|(_SHIFTL(((u32)(32.0f*lodbias)),9,8));
|
|
ptr->tex_filt = (ptr->tex_filt&~0x10)|(_SHIFTL((magfilt==GX_LINEAR?1:0),4,1));
|
|
ptr->tex_filt = (ptr->tex_filt&~0xe0)|(_SHIFTL(GX2HWFiltConv[minfilt],5,3));
|
|
ptr->tex_filt = (ptr->tex_filt&~0x100)|(_SHIFTL(!(edgelod&0xff),8,1));
|
|
ptr->tex_filt = (ptr->tex_filt&~0x180000)|(_SHIFTL(maxaniso,19,2));
|
|
ptr->tex_filt = (ptr->tex_filt&~0x200000)|(_SHIFTL(biasclamp,21,1));
|
|
|
|
if(minlod<0.0f) minlod = 0.0f;
|
|
else if(minlod>10.0f) minlod = 10.0f;
|
|
|
|
if(maxlod<0.0f) maxlod = 0.0f;
|
|
else if(maxlod>10.0f) maxlod = 10.0f;
|
|
|
|
ptr->tex_lod = (ptr->tex_lod&~0xff)|(((u32)(16.0f*minlod))&0xff);
|
|
ptr->tex_lod = (ptr->tex_lod&~0xff00)|(_SHIFTL(((u32)(16.0f*maxlod)),8,8));
|
|
}
|
|
|
|
void GX_InitTexObjData(GXTexObj *obj,void *img_ptr)
|
|
{
|
|
struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
|
|
ptr->tex_maddr = (ptr->tex_maddr&~0x00ffffff)|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(img_ptr),5,24));
|
|
}
|
|
|
|
void GX_InitTexObjTlut(GXTexObj *obj,u32 tlut_name)
|
|
{
|
|
((struct __gx_texobj*)obj)->tex_tlut = tlut_name;
|
|
}
|
|
|
|
void GX_InitTexObjWrapMode(GXTexObj *obj,u8 wrap_s,u8 wrap_t)
|
|
{
|
|
struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
|
|
|
|
ptr->tex_filt = (ptr->tex_filt&~0x03)|(wrap_s&3);
|
|
ptr->tex_filt = (ptr->tex_filt&~0x0c)|(_SHIFTL(wrap_t,2,2));
|
|
}
|
|
|
|
void GX_InitTexObjFilterMode(GXTexObj *obj,u8 minfilt,u8 magfilt)
|
|
{
|
|
struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
|
|
static u8 GX2HWFiltConv[] = {0x00,0x04,0x01,0x05,0x02,0x06,0x00,0x00};
|
|
|
|
ptr->tex_filt = (ptr->tex_filt&~0x10)|(_SHIFTL((magfilt==GX_LINEAR?1:0),4,1));
|
|
ptr->tex_filt = (ptr->tex_filt&~0xe0)|(_SHIFTL(GX2HWFiltConv[minfilt],5,3));
|
|
}
|
|
|
|
void GX_InitTexObjMinLOD(GXTexObj *obj,f32 minlod)
|
|
{
|
|
struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
|
|
|
|
if(minlod<0.0f) minlod = 0.0f;
|
|
else if(minlod>10.0f) minlod = 10.0f;
|
|
|
|
ptr->tex_lod = (ptr->tex_lod&~0xff)|(((u32)(16.0f*minlod))&0xff);
|
|
}
|
|
|
|
void GX_InitTexObjMaxLOD(GXTexObj *obj,f32 maxlod)
|
|
{
|
|
struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
|
|
|
|
if(maxlod<0.0f) maxlod = 0.0f;
|
|
else if(maxlod>10.0f) maxlod = 10.0f;
|
|
|
|
ptr->tex_lod = (ptr->tex_lod&~0xff00)|(_SHIFTL(((u32)(16.0f*maxlod)),8,8));
|
|
}
|
|
|
|
void GX_InitTexObjLODBias(GXTexObj *obj,f32 lodbias)
|
|
{
|
|
struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
|
|
|
|
if(lodbias<-4.0f) lodbias = -4.0f;
|
|
else if(lodbias==4.0f) lodbias = 3.99f;
|
|
|
|
ptr->tex_filt = (ptr->tex_filt&~0x1fe00)|(_SHIFTL(((u32)(32.0f*lodbias)),9,8));
|
|
}
|
|
|
|
void GX_InitTexObjBiasClamp(GXTexObj *obj,u8 biasclamp)
|
|
{
|
|
struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
|
|
ptr->tex_filt = (ptr->tex_filt&~0x200000)|(_SHIFTL(biasclamp,21,1));
|
|
}
|
|
|
|
void GX_InitTexObjEdgeLOD(GXTexObj *obj,u8 edgelod)
|
|
{
|
|
struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
|
|
ptr->tex_filt = (ptr->tex_filt&~0x100)|(_SHIFTL(!(edgelod&0xff),8,1));
|
|
}
|
|
|
|
void GX_InitTexObjMaxAniso(GXTexObj *obj,u8 maxaniso)
|
|
{
|
|
struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
|
|
ptr->tex_filt = (ptr->tex_filt&~0x180000)|(_SHIFTL(maxaniso,19,2));
|
|
}
|
|
|
|
void GX_InitTexObjUserData(GXTexObj *obj,void *userdata)
|
|
{
|
|
struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
|
|
ptr->usr_data = (u32)userdata;
|
|
}
|
|
|
|
void* GX_GetTexObjUserData(GXTexObj *obj)
|
|
{
|
|
struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
|
|
return (void*)ptr->usr_data;
|
|
}
|
|
|
|
void GX_InitTlutObj(GXTlutObj *obj,void *lut,u8 fmt,u16 entries)
|
|
{
|
|
struct __gx_tlutobj *ptr = (struct __gx_tlutobj*)obj;
|
|
|
|
memset(obj,0,sizeof(GXTlutObj));
|
|
|
|
ptr->tlut_fmt = _SHIFTL(fmt,10,2);
|
|
ptr->tlut_maddr = (ptr->tlut_maddr&~0x00ffffff)|(_SHIFTR(MEM_VIRTUAL_TO_PHYSICAL(lut),5,24));
|
|
ptr->tlut_maddr = (ptr->tlut_maddr&~0xff000000)|(_SHIFTL(0x64,24,8));
|
|
ptr->tlut_nentries = entries;
|
|
}
|
|
|
|
void GX_LoadTexObj(GXTexObj *obj,u8 mapid)
|
|
{
|
|
GXTexRegion *region = NULL;
|
|
|
|
if(regionCB)
|
|
region = regionCB(obj,mapid);
|
|
|
|
GX_LoadTexObjPreloaded(obj,region,mapid);
|
|
}
|
|
|
|
void GX_LoadTexObjPreloaded(GXTexObj *obj,GXTexRegion *region,u8 mapid)
|
|
{
|
|
u8 type;
|
|
struct __gx_tlutregion *tlut = NULL;
|
|
struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
|
|
struct __gx_texregion *reg = (struct __gx_texregion*)region;
|
|
|
|
ptr->tex_filt = (ptr->tex_filt&~0xff000000)|(_SHIFTL(_gxtexmode0ids[mapid],24,8));
|
|
ptr->tex_lod = (ptr->tex_lod&~0xff000000)|(_SHIFTL(_gxtexmode1ids[mapid],24,8));
|
|
ptr->tex_size = (ptr->tex_size&~0xff000000)|(_SHIFTL(_gxteximg0ids[mapid],24,8));
|
|
ptr->tex_maddr = (ptr->tex_maddr&~0xff000000)|(_SHIFTL(_gxteximg3ids[mapid],24,8));
|
|
|
|
reg->tmem_even = (reg->tmem_even&~0xff000000)|(_SHIFTL(_gxteximg1ids[mapid],24,8));
|
|
reg->tmem_odd = (reg->tmem_odd&~0xff000000)|(_SHIFTL(_gxteximg2ids[mapid],24,8));
|
|
|
|
GX_LOAD_BP_REG(ptr->tex_filt);
|
|
GX_LOAD_BP_REG(ptr->tex_lod);
|
|
GX_LOAD_BP_REG(ptr->tex_size);
|
|
|
|
GX_LOAD_BP_REG(reg->tmem_even);
|
|
GX_LOAD_BP_REG(reg->tmem_odd);
|
|
|
|
GX_LOAD_BP_REG(ptr->tex_maddr);
|
|
|
|
type = ptr->tex_flag;
|
|
if(!(type&0x02)) {
|
|
if(tlut_regionCB)
|
|
tlut = (struct __gx_tlutregion*)tlut_regionCB(ptr->tex_tlut);
|
|
tlut->tmem_addr_base = (tlut->tmem_addr_base&~0xff000000)|(_SHIFTL(_gxtextlutids[mapid],24,8));
|
|
GX_LOAD_BP_REG(tlut->tmem_addr_base);
|
|
}
|
|
|
|
__gx->texMapSize[mapid] = ptr->tex_size;
|
|
__gx->texMapWrap[mapid] = ptr->tex_filt;
|
|
|
|
__gx->dirtyState |= 0x0001;
|
|
}
|
|
|
|
void GX_PreloadEntireTexture(GXTexObj *obj,GXTexRegion *region)
|
|
{
|
|
u32 i,fmt;
|
|
s32 wd,ht;
|
|
u16 cnt = 0;
|
|
u32 regA = 0;
|
|
u32 regB = 0;
|
|
u32 regC = 0;
|
|
u32 regD = 0;
|
|
struct __gx_texobj *ptr = (struct __gx_texobj*)obj;
|
|
struct __gx_texregion *reg = (struct __gx_texregion*)region;
|
|
|
|
regA = (regA&~0xff000000)|(_SHIFTL(0x60,24,8));
|
|
regA = (regA&~0x00ffffff)|(ptr->tex_maddr&~0xff000000);
|
|
|
|
regB = (regB&~0xff000000)|(_SHIFTL(0x61,24,8));
|
|
regB = (regB&~0x00007fff)|(reg->tmem_even&0x00007fff);
|
|
|
|
regC = (regC&~0xff000000)|(_SHIFTL(0x62,24,8));
|
|
regC = (regC&~0x00007fff)|(reg->tmem_odd&0x00007fff);
|
|
|
|
regD = (regD&~0xff000000)|(_SHIFTL(0x63,24,8));
|
|
regD = (regD&~0x00007fff)|(ptr->tex_tile_cnt&0x00007fff);
|
|
regD = (regD&~0x00018000)|(_SHIFTL(ptr->tex_tile_type,15,2));
|
|
|
|
fmt = _SHIFTR(ptr->tex_size,20,4);
|
|
|
|
__GX_FlushTextureState();
|
|
GX_LOAD_BP_REG(regA);
|
|
GX_LOAD_BP_REG(regB);
|
|
GX_LOAD_BP_REG(regC);
|
|
GX_LOAD_BP_REG(regD);
|
|
|
|
if(ptr->tex_flag&0x01) {
|
|
wd = (ptr->tex_size&0x3ff)+1;
|
|
ht = _SHIFTR(ptr->tex_size,10,10)+1;
|
|
if(wd>ht)
|
|
cnt = (31 - (cntlzw(wd)));
|
|
else
|
|
cnt = (31 - (cntlzw(ht)));
|
|
}
|
|
|
|
if(cnt>0) {
|
|
u32 tmem_even,tmem_odd,maddr;
|
|
u32 tile_cnt = ptr->tex_tile_cnt;
|
|
|
|
tmem_even = (reg->tmem_even&0xffff);
|
|
tmem_odd = (reg->tmem_odd&0xffff);
|
|
maddr = (ptr->tex_maddr&~0xff000000);
|
|
|
|
i = 0;
|
|
while(cnt) {
|
|
u32 w,h;
|
|
u32 te,to;
|
|
u32 xshift,yshift;
|
|
|
|
if(fmt==GX_TF_RGBA8) {
|
|
tmem_even += tile_cnt;
|
|
tmem_odd += tile_cnt;
|
|
maddr += (tile_cnt<<1);
|
|
} else {
|
|
maddr += tile_cnt;
|
|
if(i&1) tmem_odd += tile_cnt;
|
|
else tmem_even += tile_cnt;
|
|
}
|
|
|
|
te = tmem_even;
|
|
to = tmem_odd;
|
|
if(i&1) {
|
|
te = tmem_odd;
|
|
to = tmem_even;
|
|
}
|
|
|
|
w = wd>>(i+1);
|
|
h = wd>>(i+1);
|
|
switch(ptr->tex_fmt) {
|
|
case GX_TF_I4:
|
|
case GX_TF_IA4:
|
|
case GX_TF_CI4:
|
|
case GX_TF_CMPR:
|
|
xshift = 3;
|
|
yshift = 3;
|
|
break;
|
|
case GX_TF_I8:
|
|
case GX_TF_CI8:
|
|
xshift = 3;
|
|
yshift = 2;
|
|
break;
|
|
case GX_TF_IA8:
|
|
case GX_TF_RGB5A3:
|
|
case GX_TF_RGB565:
|
|
case GX_TF_CI14:
|
|
xshift = 2;
|
|
yshift = 2;
|
|
break;
|
|
default:
|
|
xshift = 0;
|
|
yshift = 0;
|
|
break;
|
|
}
|
|
|
|
if(!w) w = 1;
|
|
if(!h) h = 1;
|
|
|
|
regA = ((regA&~0x00ffffff)|(maddr&0x00ffffff));
|
|
GX_LOAD_BP_REG(regA);
|
|
|
|
regB = ((regB&~0x00007fff)|(te&0x00007fff));
|
|
GX_LOAD_BP_REG(regB);
|
|
|
|
regC = ((regC&~0x00007fff)|(to&0x00007fff));
|
|
GX_LOAD_BP_REG(regC);
|
|
|
|
tile_cnt = (((w+(1<<xshift))-1)>>xshift)*(((h+(1<<yshift))-1)>>yshift);
|
|
regD = ((regD&~0x00007fff)|(tile_cnt&0x00007fff));
|
|
GX_LOAD_BP_REG(regD);
|
|
|
|
++i;
|
|
--cnt;
|
|
}
|
|
}
|
|
__GX_FlushTextureState();
|
|
}
|
|
|
|
void GX_InvalidateTexAll()
|
|
{
|
|
__GX_FlushTextureState();
|
|
GX_LOAD_BP_REG(0x66001000);
|
|
GX_LOAD_BP_REG(0x66001100);
|
|
__GX_FlushTextureState();
|
|
}
|
|
|
|
void GX_InvalidateTexRegion(GXTexRegion *region)
|
|
{
|
|
u8 ismipmap;
|
|
s32 cw_e,ch_e,cw_o,ch_o;
|
|
u32 size,tmp,regvalA = 0,regvalB = 0;
|
|
struct __gx_texregion *ptr = (struct __gx_texregion*)region;
|
|
|
|
cw_e = (_SHIFTR(ptr->tmem_even,15,3))-1;
|
|
ch_e = (_SHIFTR(ptr->tmem_even,18,3))-1;
|
|
|
|
cw_o = (_SHIFTR(ptr->tmem_odd,15,3))-1;
|
|
ch_o = (_SHIFTR(ptr->tmem_odd,18,3))-1;
|
|
|
|
if(cw_e<0) cw_e = 0;
|
|
if(ch_e<0) ch_e = 0;
|
|
if(cw_o<0) cw_o = 0;
|
|
if(ch_o<0) ch_o = 0;
|
|
|
|
ismipmap = ptr->ismipmap;
|
|
|
|
tmp = size = cw_e+ch_e;
|
|
if(ismipmap) size = (tmp+cw_o+ch_o)-2;
|
|
regvalA = _SHIFTR((ptr->tmem_even&0x7fff),6,9)|(_SHIFTL(size,9,4))|(_SHIFTL(0x66,24,8));
|
|
|
|
if(cw_o!=0) {
|
|
size = cw_o+ch_o;
|
|
if(ismipmap) size += (tmp-2);
|
|
regvalB = _SHIFTR((ptr->tmem_odd&0x7fff),6,9)|(_SHIFTL(size,9,4))|(_SHIFTL(0x66,24,8));
|
|
}
|
|
__GX_FlushTextureState();
|
|
GX_LOAD_BP_REG(regvalA);
|
|
if(cw_o!=0) GX_LOAD_BP_REG(regvalB);
|
|
__GX_FlushTextureState();
|
|
}
|
|
|
|
void GX_LoadTlut(GXTlutObj *obj,u32 tlut_name)
|
|
{
|
|
struct __gx_tlutregion *region = NULL;
|
|
struct __gx_tlutobj *ptr = (struct __gx_tlutobj*)obj;
|
|
|
|
if(tlut_regionCB)
|
|
region = (struct __gx_tlutregion*)tlut_regionCB(tlut_name);
|
|
|
|
__GX_FlushTextureState();
|
|
GX_LOAD_BP_REG(ptr->tlut_maddr);
|
|
GX_LOAD_BP_REG(region->tmem_addr_conf);
|
|
__GX_FlushTextureState();
|
|
|
|
region->tmem_addr_base = (ptr->tlut_fmt&~0x3ff)|(region->tmem_addr_conf&0x3ff);
|
|
region->tlut_maddr = ptr->tlut_maddr;
|
|
region->tlut_nentries = ptr->tlut_nentries;
|
|
}
|
|
|
|
void GX_SetTexCoordScaleManually(u8 texcoord,u8 enable,u16 ss,u16 ts)
|
|
{
|
|
u32 reg;
|
|
|
|
__gx->texCoordManually = (__gx->texCoordManually&~(_SHIFTL(1,texcoord,1)))|(_SHIFTL(enable,texcoord,1));
|
|
if(!enable) return;
|
|
|
|
reg = (texcoord&0x7);
|
|
__gx->suSsize[reg] = (__gx->suSsize[reg]&~0xffff)|((ss-1)&0xffff);
|
|
__gx->suTsize[reg] = (__gx->suTsize[reg]&~0xffff)|((ts-1)&0xffff);
|
|
|
|
GX_LOAD_BP_REG(__gx->suSsize[reg]);
|
|
GX_LOAD_BP_REG(__gx->suTsize[reg]);
|
|
}
|
|
|
|
void GX_SetTexCoordCylWrap(u8 texcoord,u8 s_enable,u8 t_enable)
|
|
{
|
|
u32 reg;
|
|
|
|
reg = (texcoord&0x7);
|
|
__gx->suSsize[reg] = (__gx->suSsize[reg]&~0x20000)|(_SHIFTL(s_enable,17,1));
|
|
__gx->suTsize[reg] = (__gx->suTsize[reg]&~0x20000)|(_SHIFTL(t_enable,17,1));
|
|
|
|
if(!(__gx->texCoordManually&(_SHIFTL(1,texcoord,1)))) return;
|
|
|
|
GX_LOAD_BP_REG(__gx->suSsize[reg]);
|
|
GX_LOAD_BP_REG(__gx->suTsize[reg]);
|
|
}
|
|
|
|
void GX_SetTexCoordBias(u8 texcoord,u8 s_enable,u8 t_enable)
|
|
{
|
|
u32 reg;
|
|
|
|
reg = (texcoord&0x7);
|
|
__gx->suSsize[reg] = (__gx->suSsize[reg]&~0x10000)|(_SHIFTL(s_enable,16,1));
|
|
__gx->suTsize[reg] = (__gx->suTsize[reg]&~0x10000)|(_SHIFTL(t_enable,16,1));
|
|
|
|
if(!(__gx->texCoordManually&(_SHIFTL(1,texcoord,1)))) return;
|
|
|
|
GX_LOAD_BP_REG(__gx->suSsize[reg]);
|
|
GX_LOAD_BP_REG(__gx->suTsize[reg]);
|
|
}
|
|
|
|
GXTexRegionCallback GX_SetTexRegionCallback(GXTexRegionCallback cb)
|
|
{
|
|
u32 level;
|
|
GXTexRegionCallback ret;
|
|
|
|
_CPU_ISR_Disable(level);
|
|
ret = regionCB;
|
|
regionCB = cb;
|
|
_CPU_ISR_Restore(level);
|
|
|
|
return ret;
|
|
}
|
|
|
|
GXTlutRegionCallback GX_SetTlutRegionCallback(GXTlutRegionCallback cb)
|
|
{
|
|
u32 level;
|
|
GXTlutRegionCallback ret;
|
|
|
|
_CPU_ISR_Disable(level);
|
|
ret = tlut_regionCB;
|
|
tlut_regionCB = cb;
|
|
_CPU_ISR_Restore(level);
|
|
|
|
return ret;
|
|
}
|
|
|
|
void GX_SetBlendMode(u8 type,u8 src_fact,u8 dst_fact,u8 op)
|
|
{
|
|
__gx->peCMode0 = (__gx->peCMode0&~0x1);
|
|
if(type==GX_BM_BLEND || type==GX_BM_SUBTRACT) __gx->peCMode0 |= 0x1;
|
|
|
|
__gx->peCMode0 = (__gx->peCMode0&~0x800);
|
|
if(type==GX_BM_SUBTRACT) __gx->peCMode0 |= 0x800;
|
|
|
|
__gx->peCMode0 = (__gx->peCMode0&~0x2);
|
|
if(type==GX_BM_LOGIC) __gx->peCMode0 |= 0x2;
|
|
|
|
__gx->peCMode0 = (__gx->peCMode0&~0xF000)|(_SHIFTL(op,12,4));
|
|
__gx->peCMode0 = (__gx->peCMode0&~0xE0)|(_SHIFTL(dst_fact,5,3));
|
|
__gx->peCMode0 = (__gx->peCMode0&~0x700)|(_SHIFTL(src_fact,8,3));
|
|
|
|
GX_LOAD_BP_REG(__gx->peCMode0);
|
|
}
|
|
|
|
void GX_ClearVtxDesc()
|
|
{
|
|
__gx->vcdNrms = 0;
|
|
__gx->vcdClear = ((__gx->vcdClear&~0x0600)|0x0200);
|
|
__gx->vcdLo = __gx->vcdHi = 0;
|
|
__gx->dirtyState |= 0x0008;
|
|
}
|
|
|
|
void GX_SetLineWidth(u8 width,u8 fmt)
|
|
{
|
|
__gx->lpWidth = (__gx->lpWidth&~0xff)|(width&0xff);
|
|
__gx->lpWidth = (__gx->lpWidth&~0x70000)|(_SHIFTL(fmt,16,3));
|
|
GX_LOAD_BP_REG(__gx->lpWidth);
|
|
}
|
|
|
|
void GX_SetPointSize(u8 width,u8 fmt)
|
|
{
|
|
__gx->lpWidth = (__gx->lpWidth&~0xFF00)|(_SHIFTL(width,8,8));
|
|
__gx->lpWidth = (__gx->lpWidth&~0x380000)|(_SHIFTL(fmt,19,3));
|
|
GX_LOAD_BP_REG(__gx->lpWidth);
|
|
}
|
|
|
|
void GX_SetTevColor(u8 tev_regid,GXColor color)
|
|
{
|
|
u32 reg;
|
|
|
|
reg = (_SHIFTL((0xe0+(tev_regid<<1)),24,8)|(_SHIFTL(color.a,12,8))|(color.r&0xff));
|
|
GX_LOAD_BP_REG(reg);
|
|
|
|
reg = (_SHIFTL((0xe1+(tev_regid<<1)),24,8)|(_SHIFTL(color.g,12,8))|(color.b&0xff));
|
|
GX_LOAD_BP_REG(reg);
|
|
|
|
//this two calls should obviously flush the Write Gather Pipe.
|
|
GX_LOAD_BP_REG(reg);
|
|
GX_LOAD_BP_REG(reg);
|
|
}
|
|
|
|
void GX_SetTevColorS10(u8 tev_regid,GXColorS10 color)
|
|
{
|
|
u32 reg;
|
|
|
|
reg = (_SHIFTL((0xe0+(tev_regid<<1)),24,8)|(_SHIFTL(color.a,12,11))|(color.r&0x7ff));
|
|
GX_LOAD_BP_REG(reg);
|
|
|
|
reg = (_SHIFTL((0xe1+(tev_regid<<1)),24,8)|(_SHIFTL(color.g,12,11))|(color.b&0x7ff));
|
|
GX_LOAD_BP_REG(reg);
|
|
|
|
//this two calls should obviously flush the Write Gather Pipe.
|
|
GX_LOAD_BP_REG(reg);
|
|
GX_LOAD_BP_REG(reg);
|
|
}
|
|
|
|
void GX_SetTevKColor(u8 tev_kregid,GXColor color)
|
|
{
|
|
u32 reg;
|
|
|
|
reg = (_SHIFTL((0xe0+(tev_kregid<<1)),24,8)|(_SHIFTL(1,23,1))|(_SHIFTL(color.a,12,8))|(color.r&0xff));
|
|
GX_LOAD_BP_REG(reg);
|
|
|
|
reg = (_SHIFTL((0xe1+(tev_kregid<<1)),24,8)|(_SHIFTL(1,23,1))|(_SHIFTL(color.g,12,8))|(color.b&0xff));
|
|
GX_LOAD_BP_REG(reg);
|
|
|
|
//this two calls should obviously flush the Write Gather Pipe.
|
|
GX_LOAD_BP_REG(reg);
|
|
GX_LOAD_BP_REG(reg);
|
|
}
|
|
|
|
void GX_SetTevKColorS10(u8 tev_kregid,GXColorS10 color)
|
|
{
|
|
u32 reg;
|
|
|
|
reg = (_SHIFTL((0xe0+(tev_kregid<<1)),24,8)|(_SHIFTL(1,23,1))|(_SHIFTL(color.a,12,11))|(color.r&0x7ff));
|
|
GX_LOAD_BP_REG(reg);
|
|
|
|
reg = (_SHIFTL((0xe1+(tev_kregid<<1)),24,8)|(_SHIFTL(1,23,1))|(_SHIFTL(color.g,12,11))|(color.b&0x7ff));
|
|
GX_LOAD_BP_REG(reg);
|
|
|
|
//this two calls should obviously flush the Write Gather Pipe.
|
|
GX_LOAD_BP_REG(reg);
|
|
GX_LOAD_BP_REG(reg);
|
|
}
|
|
|
|
void GX_SetTevOp(u8 tevstage,u8 mode)
|
|
{
|
|
u8 defcolor = GX_CC_RASC;
|
|
u8 defalpha = GX_CA_RASA;
|
|
|
|
if(tevstage!=GX_TEVSTAGE0) {
|
|
defcolor = GX_CC_CPREV;
|
|
defalpha = GX_CA_APREV;
|
|
}
|
|
|
|
switch(mode) {
|
|
case GX_MODULATE:
|
|
GX_SetTevColorIn(tevstage,GX_CC_ZERO,GX_CC_TEXC,defcolor,GX_CC_ZERO);
|
|
GX_SetTevAlphaIn(tevstage,GX_CA_ZERO,GX_CA_TEXA,defalpha,GX_CA_ZERO);
|
|
break;
|
|
case GX_DECAL:
|
|
GX_SetTevColorIn(tevstage,defcolor,GX_CC_TEXC,GX_CC_TEXA,GX_CC_ZERO);
|
|
GX_SetTevAlphaIn(tevstage,GX_CA_ZERO,GX_CA_ZERO,GX_CA_ZERO,defalpha);
|
|
break;
|
|
case GX_BLEND:
|
|
GX_SetTevColorIn(tevstage,defcolor,GX_CC_ONE,GX_CC_TEXC,GX_CC_ZERO);
|
|
GX_SetTevAlphaIn(tevstage,GX_CA_ZERO,GX_CA_TEXA,defalpha,GX_CA_RASA);
|
|
break;
|
|
case GX_REPLACE:
|
|
GX_SetTevColorIn(tevstage,GX_CC_ZERO,GX_CC_ZERO,GX_CC_ZERO,GX_CC_TEXC);
|
|
GX_SetTevAlphaIn(tevstage,GX_CA_ZERO,GX_CA_ZERO,GX_CA_ZERO,GX_CA_TEXA);
|
|
break;
|
|
case GX_PASSCLR:
|
|
GX_SetTevColorIn(tevstage,GX_CC_ZERO,GX_CC_ZERO,GX_CC_ZERO,defcolor);
|
|
GX_SetTevAlphaIn(tevstage,GX_CC_A2,GX_CC_A2,GX_CC_A2,defalpha);
|
|
break;
|
|
}
|
|
GX_SetTevColorOp(tevstage,GX_TEV_ADD,GX_TB_ZERO,GX_CS_SCALE_1,GX_TRUE,GX_TEVPREV);
|
|
GX_SetTevAlphaOp(tevstage,GX_TEV_ADD,GX_TB_ZERO,GX_CS_SCALE_1,GX_TRUE,GX_TEVPREV);
|
|
}
|
|
|
|
void GX_SetTevColorIn(u8 tevstage,u8 a,u8 b,u8 c,u8 d)
|
|
{
|
|
u32 reg = (tevstage&0xf);
|
|
__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0xF000)|(_SHIFTL(a,12,4));
|
|
__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0xF00)|(_SHIFTL(b,8,4));
|
|
__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0xF0)|(_SHIFTL(c,4,4));
|
|
__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0xf)|(d&0xf);
|
|
|
|
GX_LOAD_BP_REG(__gx->tevColorEnv[reg]);
|
|
}
|
|
|
|
void GX_SetTevAlphaIn(u8 tevstage,u8 a,u8 b,u8 c,u8 d)
|
|
{
|
|
u32 reg = (tevstage&0xf);
|
|
__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0xE000)|(_SHIFTL(a,13,3));
|
|
__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x1C00)|(_SHIFTL(b,10,3));
|
|
__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x380)|(_SHIFTL(c,7,3));
|
|
__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x70)|(_SHIFTL(d,4,3));
|
|
|
|
GX_LOAD_BP_REG(__gx->tevAlphaEnv[reg]);
|
|
}
|
|
|
|
void GX_SetTevColorOp(u8 tevstage,u8 tevop,u8 tevbias,u8 tevscale,u8 clamp,u8 tevregid)
|
|
{
|
|
/* set tev op add/sub*/
|
|
u32 reg = (tevstage&0xf);
|
|
__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x40000)|(_SHIFTL(tevop,18,1));
|
|
if(tevop<=GX_TEV_SUB) {
|
|
__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x300000)|(_SHIFTL(tevscale,20,2));
|
|
__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x30000)|(_SHIFTL(tevbias,16,2));
|
|
} else {
|
|
__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x300000)|((_SHIFTL(tevop,19,4))&0x300000);
|
|
__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x30000)|0x30000;
|
|
}
|
|
__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0x80000)|(_SHIFTL(clamp,19,1));
|
|
__gx->tevColorEnv[reg] = (__gx->tevColorEnv[reg]&~0xC00000)|(_SHIFTL(tevregid,22,2));
|
|
|
|
GX_LOAD_BP_REG(__gx->tevColorEnv[reg]);
|
|
}
|
|
|
|
void GX_SetTevAlphaOp(u8 tevstage,u8 tevop,u8 tevbias,u8 tevscale,u8 clamp,u8 tevregid)
|
|
{
|
|
/* set tev op add/sub*/
|
|
u32 reg = (tevstage&0xf);
|
|
__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x40000)|(_SHIFTL(tevop,18,1));
|
|
if(tevop<=GX_TEV_SUB) {
|
|
__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x300000)|(_SHIFTL(tevscale,20,2));
|
|
__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x30000)|(_SHIFTL(tevbias,16,2));
|
|
} else {
|
|
__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x300000)|((_SHIFTL(tevop,19,4))&0x300000);
|
|
__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x30000)|0x30000;
|
|
}
|
|
__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x80000)|(_SHIFTL(clamp,19,1));
|
|
__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0xC00000)|(_SHIFTL(tevregid,22,2));
|
|
|
|
GX_LOAD_BP_REG(__gx->tevAlphaEnv[reg]);
|
|
}
|
|
|
|
void GX_SetCullMode(u8 mode)
|
|
{
|
|
static u8 cm2hw[] = { 0, 2, 1, 3 };
|
|
|
|
__gx->genMode = (__gx->genMode&~0xC000)|(_SHIFTL(cm2hw[mode],14,2));
|
|
__gx->dirtyState |= 0x0004;
|
|
}
|
|
|
|
void GX_SetCoPlanar(u8 enable)
|
|
{
|
|
__gx->genMode = (__gx->genMode&~0x80000)|(_SHIFTL(enable,19,1));
|
|
GX_LOAD_BP_REG(0xFE080000);
|
|
GX_LOAD_BP_REG(__gx->genMode);
|
|
}
|
|
|
|
void GX_EnableTexOffsets(u8 coord,u8 line_enable,u8 point_enable)
|
|
{
|
|
u32 reg = (coord&0x7);
|
|
__gx->suSsize[reg] = (__gx->suSsize[reg]&~0x40000)|(_SHIFTL(line_enable,18,1));
|
|
__gx->suSsize[reg] = (__gx->suSsize[reg]&~0x80000)|(_SHIFTL(point_enable,19,1));
|
|
GX_LOAD_BP_REG(__gx->suSsize[reg]);
|
|
}
|
|
|
|
void GX_SetClipMode(u8 mode)
|
|
{
|
|
GX_LOAD_XF_REG(0x1005,(mode&1));
|
|
}
|
|
|
|
void GX_SetScissor(u32 xOrigin,u32 yOrigin,u32 wd,u32 ht)
|
|
{
|
|
u32 xo = xOrigin+0x156;
|
|
u32 yo = yOrigin+0x156;
|
|
u32 nwd = xo+(wd-1);
|
|
u32 nht = yo+(ht-1);
|
|
|
|
__gx->sciTLcorner = (__gx->sciTLcorner&~0x7ff)|(yo&0x7ff);
|
|
__gx->sciTLcorner = (__gx->sciTLcorner&~0x7FF000)|(_SHIFTL(xo,12,11));
|
|
|
|
__gx->sciBRcorner = (__gx->sciBRcorner&~0x7ff)|(nht&0xfff);
|
|
__gx->sciBRcorner = (__gx->sciBRcorner&~0x7FF000)|(_SHIFTL(nwd,12,11));
|
|
|
|
GX_LOAD_BP_REG(__gx->sciTLcorner);
|
|
GX_LOAD_BP_REG(__gx->sciBRcorner);
|
|
}
|
|
|
|
void GX_SetScissorBoxOffset(s32 xoffset,s32 yoffset)
|
|
{
|
|
s32 xoff = _SHIFTR((xoffset+0x156),1,24);
|
|
s32 yoff = _SHIFTR((yoffset+0x156),1,24);
|
|
|
|
GX_LOAD_BP_REG((0x59000000|(_SHIFTL(yoff,10,10))|(xoff&0x3ff)));
|
|
}
|
|
|
|
void GX_SetNumChans(u8 num)
|
|
{
|
|
__gx->genMode = (__gx->genMode&~0x70)|(_SHIFTL(num,4,3));
|
|
__gx->dirtyState |= 0x01000004;
|
|
}
|
|
|
|
void GX_SetTevOrder(u8 tevstage,u8 texcoord,u32 texmap,u8 color)
|
|
{
|
|
u8 colid;
|
|
u32 texm,texc,tmp;
|
|
u32 reg = 3+(_SHIFTR(tevstage,1,3));
|
|
|
|
__gx->tevTexMap[(tevstage&0xf)] = texmap;
|
|
|
|
texm = (texmap&~0x100);
|
|
if(texm>=GX_MAX_TEXMAP) texm = 0;
|
|
if(texcoord>=GX_MAXCOORD) {
|
|
texc = 0;
|
|
__gx->tevTexCoordEnable &= ~(_SHIFTL(1,tevstage,1));
|
|
} else {
|
|
texc = texcoord;
|
|
__gx->tevTexCoordEnable |= (_SHIFTL(1,tevstage,1));
|
|
}
|
|
|
|
if(tevstage&1) {
|
|
__gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x7000)|(_SHIFTL(texm,12,3));
|
|
__gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x38000)|(_SHIFTL(texc,15,3));
|
|
|
|
colid = GX_ALPHA_BUMP;
|
|
if(color!=GX_COLORNULL) colid = _gxtevcolid[color];
|
|
__gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x380000)|(_SHIFTL(colid,19,3));
|
|
|
|
tmp = 1;
|
|
if(texmap==GX_TEXMAP_NULL || texmap&0x100) tmp = 0;
|
|
__gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x40000)|(_SHIFTL(tmp,18,1));
|
|
} else {
|
|
__gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x7)|(texm&0x7);
|
|
__gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x38)|(_SHIFTL(texc,3,3));
|
|
|
|
colid = GX_ALPHA_BUMP;
|
|
if(color!=GX_COLORNULL) colid = _gxtevcolid[color];
|
|
__gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x380)|(_SHIFTL(colid,7,3));
|
|
|
|
tmp = 1;
|
|
if(texmap==GX_TEXMAP_NULL || texmap&0x100) tmp = 0;
|
|
__gx->tevRasOrder[reg] = (__gx->tevRasOrder[reg]&~0x40)|(_SHIFTL(tmp,6,1));
|
|
}
|
|
GX_LOAD_BP_REG(__gx->tevRasOrder[reg]);
|
|
__gx->dirtyState |= 0x0001;
|
|
}
|
|
|
|
void GX_SetNumTevStages(u8 num)
|
|
{
|
|
__gx->genMode = (__gx->genMode&~0x3C00)|(_SHIFTL((num-1),10,4));
|
|
__gx->dirtyState |= 0x0004;
|
|
}
|
|
|
|
void GX_SetAlphaCompare(u8 comp0,u8 ref0,u8 aop,u8 comp1,u8 ref1)
|
|
{
|
|
u32 val = 0;
|
|
val = (_SHIFTL(aop,22,2))|(_SHIFTL(comp1,19,3))|(_SHIFTL(comp0,16,3))|(_SHIFTL(ref1,8,8))|(ref0&0xff);
|
|
GX_LOAD_BP_REG(0xf3000000|val);
|
|
}
|
|
|
|
void GX_SetTevKColorSel(u8 tevstage,u8 sel)
|
|
{
|
|
u32 reg = (_SHIFTR(tevstage,1,3));
|
|
|
|
if(tevstage&1)
|
|
__gx->tevSwapModeTable[reg] = (__gx->tevSwapModeTable[reg]&~0x7C000)|(_SHIFTL(sel,14,5));
|
|
else
|
|
__gx->tevSwapModeTable[reg] = (__gx->tevSwapModeTable[reg]&~0x1F0)|(_SHIFTL(sel,4,5));
|
|
GX_LOAD_BP_REG(__gx->tevSwapModeTable[reg]);
|
|
}
|
|
|
|
void GX_SetTevKAlphaSel(u8 tevstage,u8 sel)
|
|
{
|
|
u32 reg = (_SHIFTR(tevstage,1,3));
|
|
|
|
if(tevstage&1)
|
|
__gx->tevSwapModeTable[reg] = (__gx->tevSwapModeTable[reg]&~0xF80000)|(_SHIFTL(sel,19,5));
|
|
else
|
|
__gx->tevSwapModeTable[reg] = (__gx->tevSwapModeTable[reg]&~0x3E00)|(_SHIFTL(sel,9,5));
|
|
GX_LOAD_BP_REG(__gx->tevSwapModeTable[reg]);
|
|
}
|
|
|
|
void GX_SetTevSwapMode(u8 tevstage,u8 ras_sel,u8 tex_sel)
|
|
{
|
|
u32 reg = (tevstage&0xf);
|
|
__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0x3)|(ras_sel&0x3);
|
|
__gx->tevAlphaEnv[reg] = (__gx->tevAlphaEnv[reg]&~0xC)|(_SHIFTL(tex_sel,2,2));
|
|
GX_LOAD_BP_REG(__gx->tevAlphaEnv[reg]);
|
|
}
|
|
|
|
void GX_SetTevSwapModeTable(u8 swapid,u8 r,u8 g,u8 b,u8 a)
|
|
{
|
|
u32 regA = 0+(_SHIFTL(swapid,1,3));
|
|
u32 regB = 1+(_SHIFTL(swapid,1,3));
|
|
|
|
__gx->tevSwapModeTable[regA] = (__gx->tevSwapModeTable[regA]&~0x3)|(r&0x3);
|
|
__gx->tevSwapModeTable[regA] = (__gx->tevSwapModeTable[regA]&~0xC)|(_SHIFTL(g,2,2));
|
|
GX_LOAD_BP_REG(__gx->tevSwapModeTable[regA]);
|
|
|
|
__gx->tevSwapModeTable[regB] = (__gx->tevSwapModeTable[regB]&~0x3)|(b&0x3);
|
|
__gx->tevSwapModeTable[regB] = (__gx->tevSwapModeTable[regB]&~0xC)|(_SHIFTL(a,2,2));
|
|
GX_LOAD_BP_REG(__gx->tevSwapModeTable[regB]);
|
|
}
|
|
|
|
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)
|
|
{
|
|
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));
|
|
GX_LOAD_BP_REG(val);
|
|
}
|
|
|
|
void GX_SetTevDirect(u8 tevstage)
|
|
{
|
|
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);
|
|
}
|
|
|
|
void GX_SetNumIndStages(u8 nstages)
|
|
{
|
|
__gx->genMode = (__gx->genMode&~0x70000)|(_SHIFTL(nstages,16,3));
|
|
__gx->dirtyState |= 0x0006;
|
|
}
|
|
|
|
void GX_SetIndTexMatrix(u8 indtexmtx,f32 offset_mtx[2][3],s8 scale_exp)
|
|
{
|
|
u32 ma,mb;
|
|
u32 val,s,idx;
|
|
|
|
if(indtexmtx>0x00 && indtexmtx<0x04) indtexmtx -= 0x01;
|
|
else if(indtexmtx>0x04 && indtexmtx<0x08) indtexmtx -= 0x05;
|
|
else if(indtexmtx>0x08 && indtexmtx<0x0C) indtexmtx -= 0x09;
|
|
else indtexmtx = 0x00;
|
|
|
|
s = (scale_exp+17);
|
|
idx = ((indtexmtx<<2)-indtexmtx);
|
|
|
|
ma = (u32)(offset_mtx[0][0]*1024.0F);
|
|
mb = (u32)(offset_mtx[1][0]*1024.0F);
|
|
val = (_SHIFTL((0x06+idx),24,8)|_SHIFTL(s,22,2)|_SHIFTL(mb,11,11)|_SHIFTL(ma,0,11));
|
|
GX_LOAD_BP_REG(val);
|
|
|
|
ma = (u32)(offset_mtx[0][1]*1024.0F);
|
|
mb = (u32)(offset_mtx[1][1]*1024.0F);
|
|
val = (_SHIFTL((0x07+idx),24,8)|_SHIFTL((s>>2),22,2)|_SHIFTL(mb,11,11)|_SHIFTL(ma,0,11));
|
|
GX_LOAD_BP_REG(val);
|
|
|
|
ma = (u32)(offset_mtx[0][2]*1024.0F);
|
|
mb = (u32)(offset_mtx[1][2]*1024.0F);
|
|
val = (_SHIFTL((0x08+idx),24,8)|_SHIFTL((s>>4),22,2)|_SHIFTL(mb,11,11)|_SHIFTL(ma,0,11));
|
|
GX_LOAD_BP_REG(val);
|
|
}
|
|
|
|
void GX_SetTevIndBumpST(u8 tevstage,u8 indstage,u8 mtx_sel)
|
|
{
|
|
u8 sel_s,sel_t;
|
|
|
|
switch(mtx_sel) {
|
|
case GX_ITM_0:
|
|
sel_s = GX_ITM_S0;
|
|
sel_t = GX_ITM_T0;
|
|
break;
|
|
case GX_ITM_1:
|
|
sel_s = GX_ITM_S1;
|
|
sel_t = GX_ITM_T1;
|
|
break;
|
|
case GX_ITM_2:
|
|
sel_s = GX_ITM_S2;
|
|
sel_t = GX_ITM_T2;
|
|
break;
|
|
default:
|
|
sel_s = GX_ITM_OFF;
|
|
sel_t = GX_ITM_OFF;
|
|
break;
|
|
}
|
|
|
|
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);
|
|
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);
|
|
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);
|
|
}
|
|
|
|
void GX_SetTevIndBumpXYZ(u8 tevstage,u8 indstage,u8 mtx_sel)
|
|
{
|
|
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);
|
|
}
|
|
|
|
void GX_SetTevIndRepeat(u8 tevstage)
|
|
{
|
|
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);
|
|
}
|
|
|
|
void GX_SetIndTexCoordScale(u8 indtexid,u8 scale_s,u8 scale_t)
|
|
{
|
|
switch(indtexid) {
|
|
case GX_INDTEXSTAGE0:
|
|
__gx->tevRasOrder[0] = (__gx->tevRasOrder[0]&~0x0f)|(scale_s&0x0f);
|
|
__gx->tevRasOrder[0] = (__gx->tevRasOrder[0]&~0xF0)|(_SHIFTL(scale_t,4,4));
|
|
GX_LOAD_BP_REG(__gx->tevRasOrder[0]);
|
|
break;
|
|
case GX_INDTEXSTAGE1:
|
|
__gx->tevRasOrder[0] = (__gx->tevRasOrder[0]&~0xF00)|(_SHIFTL(scale_s,8,4));
|
|
__gx->tevRasOrder[0] = (__gx->tevRasOrder[0]&~0xF000)|(_SHIFTL(scale_t,12,4));
|
|
GX_LOAD_BP_REG(__gx->tevRasOrder[0]);
|
|
break;
|
|
case GX_INDTEXSTAGE2:
|
|
__gx->tevRasOrder[1] = (__gx->tevRasOrder[1]&~0x0f)|(scale_s&0x0f);
|
|
__gx->tevRasOrder[1] = (__gx->tevRasOrder[1]&~0xF0)|(_SHIFTL(scale_t,4,4));
|
|
GX_LOAD_BP_REG(__gx->tevRasOrder[1]);
|
|
break;
|
|
case GX_INDTEXSTAGE3:
|
|
__gx->tevRasOrder[1] = (__gx->tevRasOrder[1]&~0xF00)|(_SHIFTL(scale_s,8,4));
|
|
__gx->tevRasOrder[1] = (__gx->tevRasOrder[1]&~0xF000)|(_SHIFTL(scale_t,12,4));
|
|
GX_LOAD_BP_REG(__gx->tevRasOrder[1]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
s32 wrap_s,wrap_t;
|
|
f32 offset_mtx[2][3];
|
|
f64 fdspace_x,fdspace_y;
|
|
u32 fbuf_x[2] = { 0x43300000,tilespacing_x };
|
|
u32 fbuf_y[2] = { 0x43300000,tilespacing_y };
|
|
|
|
wrap_s = GX_ITW_OFF;
|
|
if(tilesize_x==0x0010) wrap_s = GX_ITW_16;
|
|
else if(tilesize_x==0x0020) wrap_s = GX_ITW_32;
|
|
else if(tilesize_x==0x0040) wrap_s = GX_ITW_64;
|
|
else if(tilesize_x==0x0080) wrap_s = GX_ITW_128;
|
|
else if(tilesize_x==0x0100) wrap_s = GX_ITW_256;
|
|
|
|
wrap_t = GX_ITW_OFF;
|
|
if(tilesize_y==0x0010) wrap_t = GX_ITW_16;
|
|
else if(tilesize_y==0x0020) wrap_t = GX_ITW_32;
|
|
else if(tilesize_y==0x0040) wrap_t = GX_ITW_64;
|
|
else if(tilesize_y==0x0080) wrap_t = GX_ITW_128;
|
|
else if(tilesize_y==0x0100) wrap_t = GX_ITW_256;
|
|
|
|
fdspace_x = *(f64*)((void*)fbuf_x);
|
|
fdspace_y = *(f64*)((void*)fbuf_y);
|
|
|
|
offset_mtx[0][0] = (f32)((fdspace_x - 4503599627370496.0F)*0.00097656250F);
|
|
offset_mtx[0][1] = 0.0F;
|
|
offset_mtx[0][2] = 0.0F;
|
|
offset_mtx[1][0] = 0.0F;
|
|
offset_mtx[1][1] = (f32)((fdspace_y - 4503599627370496.0F)*0.00097656250F);
|
|
offset_mtx[1][2] = 0.0F;
|
|
|
|
GX_SetIndTexMatrix(indtexmtx,offset_mtx,10);
|
|
GX_SetTevIndirect(tevstage,indtexid,indtexfmt,bias_sel,indtexmtx,wrap_s,wrap_t,GX_FALSE,GX_TRUE,alpha_sel);
|
|
}
|
|
|
|
void GX_SetFog(u8 type,f32 startz,f32 endz,f32 nearz,f32 farz,GXColor col)
|
|
{
|
|
f32 A, B, B_mant, C, A_f;
|
|
u32 b_expn, b_m, a_hex, c_hex,val,proj = 0;
|
|
union ieee32 { f32 f; u32 i; } v;
|
|
|
|
proj = _SHIFTR(type,3,1);
|
|
|
|
// Calculate constants a, b, and c (TEV HW requirements).
|
|
if(proj) { // Orthographic Fog Type
|
|
if((farz==nearz) || (endz==startz)) {
|
|
// take care of the odd-ball case.
|
|
A_f = 0.0f;
|
|
C = 0.0f;
|
|
} else {
|
|
A = 1.0f/(endz-startz);
|
|
A_f = (farz-nearz) * A;
|
|
C = (startz-nearz) * A;
|
|
}
|
|
|
|
b_expn = 0;
|
|
b_m = 0;
|
|
} else { // Perspective Fog Type
|
|
// Calculate constants a, b, and c (TEV HW requirements).
|
|
if((farz==nearz) || (endz==startz)) {
|
|
// take care of the odd-ball case.
|
|
A = 0.0f;
|
|
B = 0.5f;
|
|
C = 0.0f;
|
|
} else {
|
|
A = (farz*nearz)/((farz-nearz)*(endz-startz));
|
|
B = farz/(farz-nearz);
|
|
C = startz/(endz-startz);
|
|
}
|
|
|
|
B_mant = B;
|
|
b_expn = 1;
|
|
while(B_mant>1.0f) {
|
|
B_mant /= 2.0f;
|
|
b_expn++;
|
|
}
|
|
|
|
while((B_mant>0.0f) && (B_mant<0.5f)) {
|
|
B_mant *= 2.0f;
|
|
b_expn--;
|
|
}
|
|
|
|
A_f = A/(1<<(b_expn));
|
|
b_m = (u32)(B_mant * 8388638.0f);
|
|
}
|
|
v.f = A_f;
|
|
a_hex = v.i;
|
|
|
|
v.f = C;
|
|
c_hex = v.i;
|
|
|
|
val = 0xee000000|(_SHIFTR(a_hex,12,20));
|
|
GX_LOAD_BP_REG(val);
|
|
|
|
val = 0xef000000|(b_m&0x00ffffff);
|
|
GX_LOAD_BP_REG(val);
|
|
|
|
val = 0xf0000000|(b_expn&0x1f);
|
|
GX_LOAD_BP_REG(val);
|
|
|
|
val = 0xf1000000|(_SHIFTL(type,21,3))|(_SHIFTL(proj,20,1))|(_SHIFTR(c_hex,12,20));
|
|
GX_LOAD_BP_REG(val);
|
|
|
|
val = 0xf2000000|(_SHIFTL(col.r,16,8))|(_SHIFTL(col.g,8,8))|(col.b&0xff);
|
|
GX_LOAD_BP_REG(val);
|
|
}
|
|
|
|
void GX_InitFogAdjTable(GXFogAdjTbl *table,u16 width,f32 projmtx[4][4])
|
|
{
|
|
u32 i,val7;
|
|
f32 val0,val1,val2,val4,val5,val6;
|
|
|
|
if(projmtx[3][3]==0.0f) {
|
|
val0 = projmtx[2][3]/(projmtx[2][2] - 1.0f);
|
|
val1 = val0/projmtx[0][0];
|
|
} else {
|
|
val1 = 1.0f/projmtx[0][0];
|
|
val0 = val1*1.7320499f;
|
|
}
|
|
|
|
val2 = val0*val0;
|
|
val4 = 2.0f/(f32)width;
|
|
for(i=0;i<10;i++) {
|
|
val5 = (i+1)*32.0f;
|
|
val5 *= val4;
|
|
val5 *= val1;
|
|
val5 *= val5;
|
|
val5 /= val2;
|
|
val6 = sqrtf(val5 + 1.0f);
|
|
val7 = (u32)(val6*256.0f);
|
|
table->r[i] = (val7&0x0fff);
|
|
}
|
|
}
|
|
|
|
void GX_SetFogRangeAdj(u8 enable,u16 center,GXFogAdjTbl *table)
|
|
{
|
|
u32 val;
|
|
|
|
if(enable) {
|
|
val = 0xe9000000|(_SHIFTL(table->r[1],12,12))|(table->r[0]&0x0fff);
|
|
GX_LOAD_BP_REG(val);
|
|
|
|
val = 0xea000000|(_SHIFTL(table->r[3],12,12))|(table->r[2]&0x0fff);
|
|
GX_LOAD_BP_REG(val);
|
|
|
|
val = 0xeb000000|(_SHIFTL(table->r[5],12,12))|(table->r[4]&0x0fff);
|
|
GX_LOAD_BP_REG(val);
|
|
|
|
val = 0xec000000|(_SHIFTL(table->r[7],12,12))|(table->r[6]&0x0fff);
|
|
GX_LOAD_BP_REG(val);
|
|
|
|
val = 0xed000000|(_SHIFTL(table->r[9],12,12))|(table->r[8]&0x0fff);
|
|
GX_LOAD_BP_REG(val);
|
|
}
|
|
val = 0xe8000000|(_SHIFTL(enable,10,1))|((center + 342)&0x03ff);
|
|
GX_LOAD_BP_REG(val);
|
|
}
|
|
|
|
void GX_SetFogColor(GXColor color)
|
|
{
|
|
GX_LOAD_BP_REG(0xf2000000|(_SHIFTL(color.r,16,8)|_SHIFTL(color.g,8,8)|(color.b&0xff)));
|
|
}
|
|
|
|
void GX_SetColorUpdate(u8 enable)
|
|
{
|
|
__gx->peCMode0 = (__gx->peCMode0&~0x8)|(_SHIFTL(enable,3,1));
|
|
GX_LOAD_BP_REG(__gx->peCMode0);
|
|
}
|
|
|
|
void GX_SetAlphaUpdate(u8 enable)
|
|
{
|
|
__gx->peCMode0 = (__gx->peCMode0&~0x10)|(_SHIFTL(enable,4,1));
|
|
GX_LOAD_BP_REG(__gx->peCMode0);
|
|
}
|
|
|
|
void GX_SetZCompLoc(u8 before_tex)
|
|
{
|
|
__gx->peCntrl = (__gx->peCntrl&~0x40)|(_SHIFTL(before_tex,6,1));
|
|
GX_LOAD_BP_REG(__gx->peCntrl);
|
|
}
|
|
|
|
void GX_SetPixelFmt(u8 pix_fmt,u8 z_fmt)
|
|
{
|
|
u8 ms_en = 0;
|
|
u32 realfmt[8] = {0,1,2,3,4,4,4,5};
|
|
|
|
__gx->peCntrl = (__gx->peCntrl&~0x7)|(realfmt[pix_fmt]&0x7);
|
|
__gx->peCntrl = (__gx->peCntrl&~0x38)|(_SHIFTL(z_fmt,3,3));
|
|
GX_LOAD_BP_REG(__gx->peCntrl);
|
|
__gx->dirtyState |= 0x0004;
|
|
|
|
if(pix_fmt==GX_PF_RGB565_Z16) ms_en = 1;
|
|
__gx->genMode = (__gx->genMode&~0x200)|(_SHIFTL(ms_en,9,1));
|
|
|
|
if(realfmt[pix_fmt]==GX_PF_Y8) {
|
|
pix_fmt -= GX_PF_Y8;
|
|
__gx->peCMode1 = (__gx->peCMode1&~0xC00)|(_SHIFTL(pix_fmt,10,2));
|
|
GX_LOAD_BP_REG(__gx->peCMode1);
|
|
}
|
|
}
|
|
|
|
void GX_SetDither(u8 dither)
|
|
{
|
|
__gx->peCMode0 = (__gx->peCMode0&~0x4)|(_SHIFTL(dither,2,1));
|
|
GX_LOAD_BP_REG(__gx->peCMode0);
|
|
}
|
|
|
|
void GX_SetDstAlpha(u8 enable,u8 a)
|
|
{
|
|
__gx->peCMode1 = (__gx->peCMode1&~0xff)|(a&0xff);
|
|
__gx->peCMode1 = (__gx->peCMode1&~0x100)|(_SHIFTL(enable,8,1));
|
|
GX_LOAD_BP_REG(__gx->peCMode1);
|
|
}
|
|
|
|
void GX_SetFieldMask(u8 even_mask,u8 odd_mask)
|
|
{
|
|
u32 val = 0;
|
|
|
|
val = (_SHIFTL(even_mask,1,1))|(odd_mask&1);
|
|
GX_LOAD_BP_REG(0x44000000|val);
|
|
}
|
|
|
|
void GX_SetFieldMode(u8 field_mode,u8 half_aspect_ratio)
|
|
{
|
|
__gx->lpWidth = (__gx->lpWidth&~0x400000)|(_SHIFTL(half_aspect_ratio,22,1));
|
|
GX_LOAD_BP_REG(__gx->lpWidth);
|
|
|
|
__GX_FlushTextureState();
|
|
GX_LOAD_BP_REG(0x68000000|(field_mode&1));
|
|
__GX_FlushTextureState();
|
|
}
|
|
|
|
void GX_PokeAlphaMode(u8 func,u8 threshold)
|
|
{
|
|
_peReg[3] = (_SHIFTL(func,8,8))|(threshold&0xFF);
|
|
}
|
|
|
|
void GX_PokeAlphaRead(u8 mode)
|
|
{
|
|
_peReg[4] = (mode&~0x4)|0x4;
|
|
}
|
|
|
|
void GX_PokeDstAlpha(u8 enable,u8 a)
|
|
{
|
|
_peReg[2] = (_SHIFTL(enable,8,1))|(a&0xff);
|
|
}
|
|
|
|
void GX_PokeAlphaUpdate(u8 update_enable)
|
|
{
|
|
_peReg[1] = (_peReg[1]&~0x10)|(_SHIFTL(update_enable,4,1));
|
|
}
|
|
|
|
void GX_PokeColorUpdate(u8 update_enable)
|
|
{
|
|
_peReg[1] = (_peReg[1]&~0x8)|(_SHIFTL(update_enable,3,1));
|
|
}
|
|
|
|
void GX_PokeDither(u8 dither)
|
|
{
|
|
_peReg[1] = (_peReg[1]&~0x4)|(_SHIFTL(dither,2,1));
|
|
}
|
|
|
|
void GX_PokeBlendMode(u8 type,u8 src_fact,u8 dst_fact,u8 op)
|
|
{
|
|
u32 regval = _peReg[1];
|
|
|
|
regval = (regval&~0x1);
|
|
if(type==GX_BM_BLEND || type==GX_BM_SUBTRACT) regval |= 0x1;
|
|
|
|
regval = (regval&~0x800);
|
|
if(type==GX_BM_SUBTRACT) regval |= 0x800;
|
|
|
|
regval = (regval&~0x2);
|
|
if(type==GX_BM_LOGIC) regval |= 0x2;
|
|
|
|
regval = (regval&~0xF000)|(_SHIFTL(op,12,4));
|
|
regval = (regval&~0xE0)|(_SHIFTL(dst_fact,5,3));
|
|
regval = (regval&~0x700)|(_SHIFTL(src_fact,8,3));
|
|
|
|
regval |= 0x41000000;
|
|
_peReg[1] = (u16)regval;
|
|
}
|
|
|
|
void GX_PokeARGB(u16 x,u16 y,GXColor color)
|
|
{
|
|
u32 regval;
|
|
|
|
regval = 0xc8000000|(_SHIFTL(x,2,10));
|
|
regval = (regval&~0x3FF000)|(_SHIFTL(y,12,10));
|
|
*(u32*)regval = _SHIFTL(color.a,24,8)|_SHIFTL(color.r,16,8)|_SHIFTL(color.g,8,8)|(color.b&0xff);
|
|
}
|
|
|
|
void GX_PeekARGB(u16 x,u16 y,GXColor *color)
|
|
{
|
|
u32 regval,val;
|
|
|
|
regval = 0xc8000000|(_SHIFTL(x,2,10));
|
|
regval = (regval&~0x3FF000)|(_SHIFTL(y,12,10));
|
|
val = *(u32*)regval;
|
|
color->a = _SHIFTR(val,24,8);
|
|
color->r = _SHIFTR(val,16,8);
|
|
color->g = _SHIFTR(val,8,8);
|
|
color->b = val&0xff;
|
|
}
|
|
|
|
void GX_PokeZ(u16 x,u16 y,u32 z)
|
|
{
|
|
u32 regval;
|
|
|
|
regval = 0xc8000000|(_SHIFTL(x,2,10));
|
|
regval = (regval&~0x3FF000)|(_SHIFTL(y,12,10));
|
|
regval = (regval&~0xC00000)|0x400000;
|
|
*(u32*)regval = z;
|
|
}
|
|
|
|
void GX_PeekZ(u16 x,u16 y,u32 *z)
|
|
{
|
|
u32 regval;
|
|
|
|
regval = 0xc8000000|(_SHIFTL(x,2,10));
|
|
regval = (regval&~0x3FF000)|(_SHIFTL(y,12,10));
|
|
regval = (regval&~0xC00000)|0x400000;
|
|
*z = *(u32*)regval;
|
|
}
|
|
|
|
void GX_PokeZMode(u8 comp_enable,u8 func,u8 update_enable)
|
|
{
|
|
u16 regval;
|
|
regval = comp_enable&0x1;
|
|
regval = (regval&~0xE)|(_SHIFTL(func,1,3));
|
|
regval = (regval&0x10)|(_SHIFTL(update_enable,4,1));
|
|
_peReg[0] = regval;
|
|
}
|
|
|
|
void GX_SetIndTexOrder(u8 indtexstage,u8 texcoord,u8 texmap)
|
|
{
|
|
switch(indtexstage) {
|
|
case GX_INDTEXSTAGE0:
|
|
__gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x7)|(texmap&0x7);
|
|
__gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x38)|(_SHIFTL(texcoord,3,3));
|
|
break;
|
|
case GX_INDTEXSTAGE1:
|
|
__gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x1C0)|(_SHIFTL(texmap,6,3));
|
|
__gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0xE00)|(_SHIFTL(texcoord,9,3));
|
|
break;
|
|
case GX_INDTEXSTAGE2:
|
|
__gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x7000)|(_SHIFTL(texmap,12,3));
|
|
__gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x38000)|(_SHIFTL(texcoord,15,3));
|
|
break;
|
|
case GX_INDTEXSTAGE3:
|
|
__gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0x1C0000)|(_SHIFTL(texmap,18,3));
|
|
__gx->tevRasOrder[2] = (__gx->tevRasOrder[2]&~0xE00000)|(_SHIFTL(texcoord,21,3));
|
|
break;
|
|
}
|
|
GX_LOAD_BP_REG(__gx->tevRasOrder[2]);
|
|
__gx->dirtyState |= 0x0003;
|
|
}
|
|
|
|
void GX_InitLightPos(GXLightObj *lit_obj,f32 x,f32 y,f32 z)
|
|
{
|
|
struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
|
|
|
|
lit->px = x;
|
|
lit->py = y;
|
|
lit->pz = z;
|
|
}
|
|
|
|
void GX_InitLightColor(GXLightObj *lit_obj,GXColor col)
|
|
{
|
|
struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
|
|
lit->col = ((_SHIFTL(col.r,24,8))|(_SHIFTL(col.g,16,8))|(_SHIFTL(col.b,8,8))|(col.a&0xff));
|
|
}
|
|
|
|
void GX_LoadLightObj(GXLightObj *lit_obj,u8 lit_id)
|
|
{
|
|
u32 id;
|
|
u16 reg;
|
|
struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
|
|
|
|
switch(lit_id) {
|
|
case GX_LIGHT0:
|
|
id = 0;
|
|
break;
|
|
case GX_LIGHT1:
|
|
id = 1;
|
|
break;
|
|
case GX_LIGHT2:
|
|
id = 2;
|
|
break;
|
|
case GX_LIGHT3:
|
|
id = 3;
|
|
break;
|
|
case GX_LIGHT4:
|
|
id = 4;
|
|
break;
|
|
case GX_LIGHT5:
|
|
id = 5;
|
|
break;
|
|
case GX_LIGHT6:
|
|
id = 6;
|
|
break;
|
|
case GX_LIGHT7:
|
|
id = 7;
|
|
break;
|
|
default:
|
|
id = 0;
|
|
break;
|
|
}
|
|
|
|
reg = 0x600|(_SHIFTL(id,4,8));
|
|
GX_LOAD_XF_REGS(reg,16);
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = 0;
|
|
wgPipe->U32 = lit->col;
|
|
wgPipe->F32 = lit->a0;
|
|
wgPipe->F32 = lit->a1;
|
|
wgPipe->F32 = lit->a2;
|
|
wgPipe->F32 = lit->k0;
|
|
wgPipe->F32 = lit->k1;
|
|
wgPipe->F32 = lit->k2;
|
|
wgPipe->F32 = lit->px;
|
|
wgPipe->F32 = lit->py;
|
|
wgPipe->F32 = lit->pz;
|
|
wgPipe->F32 = lit->nx;
|
|
wgPipe->F32 = lit->ny;
|
|
wgPipe->F32 = lit->nz;
|
|
}
|
|
|
|
void GX_LoadLightObjIdx(u32 litobjidx,u8 litid)
|
|
{
|
|
u32 reg;
|
|
u32 idx = 0;
|
|
|
|
switch(litid) {
|
|
case GX_LIGHT0:
|
|
idx = 0;
|
|
break;
|
|
case GX_LIGHT1:
|
|
idx = 1;
|
|
break;
|
|
case GX_LIGHT2:
|
|
idx = 2;
|
|
break;
|
|
case GX_LIGHT3:
|
|
idx = 3;
|
|
break;
|
|
case GX_LIGHT4:
|
|
idx = 4;
|
|
break;
|
|
case GX_LIGHT5:
|
|
idx = 5;
|
|
break;
|
|
case GX_LIGHT6:
|
|
idx = 6;
|
|
break;
|
|
case GX_LIGHT7:
|
|
idx = 7;
|
|
break;
|
|
default:
|
|
idx = 0;
|
|
break;
|
|
|
|
}
|
|
|
|
reg = 0xf600|(_SHIFTL(idx,4,8));
|
|
reg = (reg&~0xffff0000)|(_SHIFTL(litobjidx,16,16));
|
|
|
|
wgPipe->U8 = 0x38;
|
|
wgPipe->U32 = reg;
|
|
}
|
|
|
|
void GX_InitLightDir(GXLightObj *lit_obj,f32 nx,f32 ny,f32 nz)
|
|
{
|
|
struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
|
|
|
|
lit->nx = -(nx);
|
|
lit->ny = -(ny);
|
|
lit->nz = -(nz);
|
|
}
|
|
|
|
void GX_InitLightDistAttn(GXLightObj *lit_obj,f32 ref_dist,f32 ref_brite,u8 dist_fn)
|
|
{
|
|
f32 k0,k1,k2;
|
|
struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
|
|
|
|
if(ref_dist<0.0f ||
|
|
ref_brite<0.0f || ref_brite>=1.0f) dist_fn = GX_DA_OFF;
|
|
|
|
switch(dist_fn) {
|
|
case GX_DA_GENTLE:
|
|
k0 = 1.0f;
|
|
k1 = (1.0f-ref_brite)/(ref_brite*ref_dist);
|
|
k2 = 0.0f;
|
|
break;
|
|
case GX_DA_MEDIUM:
|
|
k0 = 1.0f;
|
|
k1 = 0.5f*(1.0f-ref_brite)/(ref_brite*ref_dist);
|
|
k2 = 0.5f*(1.0f-ref_brite)/(ref_brite*ref_dist*ref_dist);
|
|
break;
|
|
case GX_DA_STEEP:
|
|
k0 = 1.0f;
|
|
k1 = 0.0f;
|
|
k2 = (1.0f-ref_brite)/(ref_brite*ref_dist*ref_dist);
|
|
break;
|
|
case GX_DA_OFF:
|
|
default:
|
|
k0 = 1.0f;
|
|
k1 = 0.0f;
|
|
k2 = 0.0f;
|
|
break;
|
|
}
|
|
|
|
lit->k0 = k0;
|
|
lit->k1 = k1;
|
|
lit->k2 = k2;
|
|
}
|
|
|
|
void GX_InitLightAttn(GXLightObj *lit_obj,f32 a0,f32 a1,f32 a2,f32 k0,f32 k1,f32 k2)
|
|
{
|
|
struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
|
|
|
|
lit->a0 = a0;
|
|
lit->a1 = a1;
|
|
lit->a2 = a2;
|
|
lit->k0 = k0;
|
|
lit->k1 = k1;
|
|
lit->k2 = k2;
|
|
}
|
|
|
|
void GX_InitLightAttnA(GXLightObj *lit_obj,f32 a0,f32 a1,f32 a2)
|
|
{
|
|
struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
|
|
|
|
lit->a0 = a0;
|
|
lit->a1 = a1;
|
|
lit->a2 = a2;
|
|
}
|
|
|
|
void GX_InitLightAttnK(GXLightObj *lit_obj,f32 k0,f32 k1,f32 k2)
|
|
{
|
|
struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
|
|
|
|
lit->k0 = k0;
|
|
lit->k1 = k1;
|
|
lit->k2 = k2;
|
|
}
|
|
|
|
void GX_InitSpecularDirHA(GXLightObj *lit_obj,f32 nx,f32 ny,f32 nz,f32 hx,f32 hy,f32 hz)
|
|
{
|
|
f32 px, py, pz;
|
|
struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
|
|
|
|
px = (nx * LARGE_NUMBER);
|
|
py = (ny * LARGE_NUMBER);
|
|
pz = (nz * LARGE_NUMBER);
|
|
|
|
lit->px = px;
|
|
lit->py = py;
|
|
lit->pz = pz;
|
|
lit->nx = hx;
|
|
lit->ny = hy;
|
|
lit->nz = hz;
|
|
}
|
|
|
|
void GX_InitSpecularDir(GXLightObj *lit_obj,f32 nx,f32 ny,f32 nz)
|
|
{
|
|
f32 px, py, pz;
|
|
f32 hx, hy, hz, mag;
|
|
struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
|
|
|
|
// Compute half-angle vector
|
|
hx = -nx;
|
|
hy = -ny;
|
|
hz = (-nz + 1.0f);
|
|
mag = ((hx * hx) + (hy * hy) + (hz * hz));
|
|
if(mag!=0.0f) mag = 1.0f / sqrtf(mag);
|
|
|
|
hx *= mag;
|
|
hy *= mag;
|
|
hz *= mag;
|
|
|
|
px = (nx * LARGE_NUMBER);
|
|
py = (ny * LARGE_NUMBER);
|
|
pz = (nz * LARGE_NUMBER);
|
|
|
|
lit->px = px;
|
|
lit->py = py;
|
|
lit->pz = pz;
|
|
lit->nx = hx;
|
|
lit->ny = hy;
|
|
lit->nz = hz;
|
|
}
|
|
|
|
void GX_InitLightSpot(GXLightObj *lit_obj,f32 cut_off,u8 spotfn)
|
|
{
|
|
f32 r,d,cr,a0,a1,a2;
|
|
struct __gx_litobj *lit = (struct __gx_litobj*)lit_obj;
|
|
|
|
if(cut_off<0.0f || cut_off>90.0f) spotfn = GX_SP_OFF;
|
|
|
|
r = (cut_off*M_PI)/180.0f;
|
|
cr = cosf(r);
|
|
|
|
switch(spotfn) {
|
|
case GX_SP_FLAT:
|
|
a0 = -1000.0f*cr;
|
|
a1 = 1000.0f;
|
|
a2 = 0.0f;
|
|
break;
|
|
case GX_SP_COS:
|
|
a0 = -cr/(1.0f-cr);
|
|
a1 = 1.0f/(1.0f-cr);
|
|
a2 = 0.0f;
|
|
break;
|
|
case GX_SP_COS2:
|
|
a0 = 0.0f;
|
|
a1 = -cr/(1.0f-cr);
|
|
a2 = 1.0f/(1.0f-cr);
|
|
break;
|
|
case GX_SP_SHARP:
|
|
d = (1.0f-cr)*(1.0f-cr);
|
|
a0 = cr*(cr-2.0f);
|
|
a1 = 2.0f/d;
|
|
a2 = -1.0/d;
|
|
break;
|
|
case GX_SP_RING1:
|
|
d = (1.0f-cr)*(1.0f-cr);
|
|
a0 = -4.0f*cr/d;
|
|
a1 = 4.0f*(1.0f+cr)/d;
|
|
a2 = -4.0f/d;
|
|
break;
|
|
case GX_SP_RING2:
|
|
d = (1.0f-cr)*(1.0f-cr);
|
|
a0 = 1.0f-2.0f*cr*cr/d;
|
|
a1 = 4.0f*cr/d;
|
|
a2 = -2.0f/d;
|
|
break;
|
|
case GX_SP_OFF:
|
|
default:
|
|
a0 = 1.0f;
|
|
a1 = 0.0f;
|
|
a2 = 0.0f;
|
|
break;
|
|
}
|
|
|
|
lit->a0 = a0;
|
|
lit->a1 = a1;
|
|
lit->a2 = a2;
|
|
}
|
|
|
|
void GX_SetGPMetric(u32 perf0,u32 perf1)
|
|
{
|
|
// check last setted perf0 counters
|
|
if(__gx->perf0Mode>=GX_PERF0_TRIANGLES && __gx->perf0Mode<GX_PERF0_QUAD_0CVG)
|
|
GX_LOAD_BP_REG(0x23000000);
|
|
else if(__gx->perf0Mode>=GX_PERF0_QUAD_0CVG && __gx->perf0Mode<GX_PERF0_CLOCKS)
|
|
GX_LOAD_BP_REG(0x24000000);
|
|
else if(__gx->perf0Mode>=GX_PERF0_VERTICES && __gx->perf0Mode<=GX_PERF0_CLOCKS)
|
|
GX_LOAD_XF_REG(0x1006,0);
|
|
|
|
// check last setted perf1 counters
|
|
if(__gx->perf1Mode>=GX_PERF1_VC_ELEMQ_FULL && __gx->perf1Mode<GX_PERF1_FIFO_REQ) {
|
|
__gx->cpPerfMode = (__gx->cpPerfMode&~0xf0);
|
|
GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
|
|
} else if(__gx->perf1Mode>=GX_PERF1_FIFO_REQ && __gx->perf1Mode<GX_PERF1_CLOCKS) {
|
|
_cpReg[3] = 0;
|
|
} else if(__gx->perf1Mode>=GX_PERF1_TEXELS && __gx->perf1Mode<=GX_PERF1_CLOCKS) {
|
|
GX_LOAD_BP_REG(0x67000000);
|
|
}
|
|
|
|
__gx->perf0Mode = perf0;
|
|
switch(__gx->perf0Mode) {
|
|
case GX_PERF0_CLOCKS:
|
|
GX_LOAD_XF_REG(0x1006,0x00000273);
|
|
break;
|
|
case GX_PERF0_VERTICES:
|
|
GX_LOAD_XF_REG(0x1006,0x0000014a);
|
|
break;
|
|
case GX_PERF0_CLIP_VTX:
|
|
GX_LOAD_XF_REG(0x1006,0x0000016b);
|
|
break;
|
|
case GX_PERF0_CLIP_CLKS:
|
|
GX_LOAD_XF_REG(0x1006,0x00000084);
|
|
break;
|
|
case GX_PERF0_XF_WAIT_IN:
|
|
GX_LOAD_XF_REG(0x1006,0x000000c6);
|
|
break;
|
|
case GX_PERF0_XF_WAIT_OUT:
|
|
GX_LOAD_XF_REG(0x1006,0x00000210);
|
|
break;
|
|
case GX_PERF0_XF_XFRM_CLKS:
|
|
GX_LOAD_XF_REG(0x1006,0x00000252);
|
|
break;
|
|
case GX_PERF0_XF_LIT_CLKS:
|
|
GX_LOAD_XF_REG(0x1006,0x00000231);
|
|
break;
|
|
case GX_PERF0_XF_BOT_CLKS:
|
|
GX_LOAD_XF_REG(0x1006,0x000001ad);
|
|
break;
|
|
case GX_PERF0_XF_REGLD_CLKS:
|
|
GX_LOAD_XF_REG(0x1006,0x000001ce);
|
|
break;
|
|
case GX_PERF0_XF_REGRD_CLKS:
|
|
GX_LOAD_XF_REG(0x1006,0x00000021);
|
|
break;
|
|
case GX_PERF0_CLIP_RATIO:
|
|
GX_LOAD_XF_REG(0x1006,0x00000153);
|
|
break;
|
|
case GX_PERF0_TRIANGLES:
|
|
GX_LOAD_BP_REG(0x2300AE7F);
|
|
break;
|
|
case GX_PERF0_TRIANGLES_CULLED:
|
|
GX_LOAD_BP_REG(0x23008E7F);
|
|
break;
|
|
case GX_PERF0_TRIANGLES_PASSED:
|
|
GX_LOAD_BP_REG(0x23009E7F);
|
|
break;
|
|
case GX_PERF0_TRIANGLES_SCISSORED:
|
|
GX_LOAD_BP_REG(0x23001E7F);
|
|
break;
|
|
case GX_PERF0_TRIANGLES_0TEX:
|
|
GX_LOAD_BP_REG(0x2300AC3F);
|
|
break;
|
|
case GX_PERF0_TRIANGLES_1TEX:
|
|
GX_LOAD_BP_REG(0x2300AC7F);
|
|
break;
|
|
case GX_PERF0_TRIANGLES_2TEX:
|
|
GX_LOAD_BP_REG(0x2300ACBF);
|
|
break;
|
|
case GX_PERF0_TRIANGLES_3TEX:
|
|
GX_LOAD_BP_REG(0x2300ACFF);
|
|
break;
|
|
case GX_PERF0_TRIANGLES_4TEX:
|
|
GX_LOAD_BP_REG(0x2300AD3F);
|
|
break;
|
|
case GX_PERF0_TRIANGLES_5TEX:
|
|
GX_LOAD_BP_REG(0x2300AD7F);
|
|
break;
|
|
case GX_PERF0_TRIANGLES_6TEX:
|
|
GX_LOAD_BP_REG(0x2300ADBF);
|
|
break;
|
|
case GX_PERF0_TRIANGLES_7TEX:
|
|
GX_LOAD_BP_REG(0x2300ADFF);
|
|
break;
|
|
case GX_PERF0_TRIANGLES_8TEX:
|
|
GX_LOAD_BP_REG(0x2300AE3F);
|
|
break;
|
|
case GX_PERF0_TRIANGLES_0CLR:
|
|
GX_LOAD_BP_REG(0x2300A27F);
|
|
break;
|
|
case GX_PERF0_TRIANGLES_1CLR:
|
|
GX_LOAD_BP_REG(0x2300A67F);
|
|
break;
|
|
case GX_PERF0_TRIANGLES_2CLR:
|
|
GX_LOAD_BP_REG(0x2300AA7F);
|
|
break;
|
|
case GX_PERF0_QUAD_0CVG:
|
|
GX_LOAD_BP_REG(0x2402C0C6);
|
|
break;
|
|
case GX_PERF0_QUAD_NON0CVG:
|
|
GX_LOAD_BP_REG(0x2402C16B);
|
|
break;
|
|
case GX_PERF0_QUAD_1CVG:
|
|
GX_LOAD_BP_REG(0x2402C0E7);
|
|
break;
|
|
case GX_PERF0_QUAD_2CVG:
|
|
GX_LOAD_BP_REG(0x2402C108);
|
|
break;
|
|
case GX_PERF0_QUAD_3CVG:
|
|
GX_LOAD_BP_REG(0x2402C129);
|
|
break;
|
|
case GX_PERF0_QUAD_4CVG:
|
|
GX_LOAD_BP_REG(0x2402C14A);
|
|
break;
|
|
case GX_PERF0_AVG_QUAD_CNT:
|
|
GX_LOAD_BP_REG(0x2402C1AD);
|
|
break;
|
|
case GX_PERF0_NONE:
|
|
break;
|
|
}
|
|
|
|
__gx->perf1Mode = perf1;
|
|
switch(__gx->perf1Mode) {
|
|
case GX_PERF1_CLOCKS:
|
|
GX_LOAD_BP_REG(0x67000042);
|
|
break;
|
|
case GX_PERF1_TEXELS:
|
|
GX_LOAD_BP_REG(0x67000084);
|
|
break;
|
|
case GX_PERF1_TX_IDLE:
|
|
GX_LOAD_BP_REG(0x67000063);
|
|
break;
|
|
case GX_PERF1_TX_REGS:
|
|
GX_LOAD_BP_REG(0x67000129);
|
|
break;
|
|
case GX_PERF1_TX_MEMSTALL:
|
|
GX_LOAD_BP_REG(0x67000252);
|
|
break;
|
|
case GX_PERF1_TC_CHECK1_2:
|
|
GX_LOAD_BP_REG(0x67000021);
|
|
break;
|
|
case GX_PERF1_TC_CHECK3_4:
|
|
GX_LOAD_BP_REG(0x6700014b);
|
|
break;
|
|
case GX_PERF1_TC_CHECK5_6:
|
|
GX_LOAD_BP_REG(0x6700018d);
|
|
break;
|
|
case GX_PERF1_TC_CHECK7_8:
|
|
GX_LOAD_BP_REG(0x670001cf);
|
|
break;
|
|
case GX_PERF1_TC_MISS:
|
|
GX_LOAD_BP_REG(0x67000211);
|
|
break;
|
|
case GX_PERF1_VC_ELEMQ_FULL:
|
|
__gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x20;
|
|
GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
|
|
break;
|
|
case GX_PERF1_VC_MISSQ_FULL:
|
|
__gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x30;
|
|
GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
|
|
break;
|
|
case GX_PERF1_VC_MEMREQ_FULL:
|
|
__gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x40;
|
|
GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
|
|
break;
|
|
case GX_PERF1_VC_STATUS7:
|
|
__gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x50;
|
|
GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
|
|
break;
|
|
case GX_PERF1_VC_MISSREP_FULL:
|
|
__gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x60;
|
|
GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
|
|
break;
|
|
case GX_PERF1_VC_STREAMBUF_LOW:
|
|
__gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x70;
|
|
GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
|
|
break;
|
|
case GX_PERF1_VC_ALL_STALLS:
|
|
__gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x90;
|
|
GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
|
|
break;
|
|
case GX_PERF1_VERTICES:
|
|
__gx->cpPerfMode = (__gx->cpPerfMode&~0xf0)|0x80;
|
|
GX_LOAD_CP_REG(0x20,__gx->cpPerfMode);
|
|
break;
|
|
case GX_PERF1_FIFO_REQ:
|
|
_cpReg[3] = 2;
|
|
break;
|
|
case GX_PERF1_CALL_REQ:
|
|
_cpReg[3] = 3;
|
|
break;
|
|
case GX_PERF1_VC_MISS_REQ:
|
|
_cpReg[3] = 4;
|
|
break;
|
|
case GX_PERF1_CP_ALL_REQ:
|
|
_cpReg[3] = 5;
|
|
break;
|
|
case GX_PERF1_NONE:
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
void GX_ClearGPMetric()
|
|
{
|
|
_cpReg[2] = 4;
|
|
}
|
|
|
|
void GX_InitXfRasMetric()
|
|
{
|
|
GX_LOAD_BP_REG(0x2402C022);
|
|
GX_LOAD_XF_REG(0x1006,0x31000);
|
|
}
|
|
|
|
void GX_ReadXfRasMetric(u32 *xfwaitin,u32 *xfwaitout,u32 *rasbusy,u32 *clks)
|
|
{
|
|
*rasbusy = _SHIFTL(_cpReg[33],16,16)|(_cpReg[32]&0xffff);
|
|
*clks = _SHIFTL(_cpReg[35],16,16)|(_cpReg[34]&0xffff);
|
|
*xfwaitin = _SHIFTL(_cpReg[37],16,16)|(_cpReg[36]&0xffff);
|
|
*xfwaitout = _SHIFTL(_cpReg[39],16,16)|(_cpReg[38]&0xffff);
|
|
}
|
|
|
|
u32 GX_ReadClksPerVtx()
|
|
{
|
|
GX_DrawDone();
|
|
_cpReg[49] = 0x1007;
|
|
_cpReg[48] = 0x1007;
|
|
return (_cpReg[50]<<8);
|
|
}
|
|
|
|
void GX_ClearVCacheMetric()
|
|
{
|
|
GX_LOAD_CP_REG(0,0);
|
|
}
|
|
|
|
void GX_ReadVCacheMetric(u32 *check,u32 *miss,u32 *stall)
|
|
{
|
|
*check = _SHIFTL(_cpReg[41],16,16)|(_cpReg[40]&0xffff);
|
|
*miss = _SHIFTL(_cpReg[43],16,16)|(_cpReg[42]&0xffff);
|
|
*stall = _SHIFTL(_cpReg[45],16,16)|(_cpReg[44]&0xffff);
|
|
}
|
|
|
|
void GX_SetVCacheMetric(u32 attr)
|
|
{
|
|
}
|
|
|
|
void GX_GetGPStatus(u8 *overhi,u8 *underlow,u8 *readIdle,u8 *cmdIdle,u8 *brkpt)
|
|
{
|
|
_gxgpstatus = _cpReg[0];
|
|
*overhi = !!(_gxgpstatus&1);
|
|
*underlow = !!(_gxgpstatus&2);
|
|
*readIdle = !!(_gxgpstatus&4);
|
|
*cmdIdle = !!(_gxgpstatus&8);
|
|
*brkpt = !!(_gxgpstatus&16);
|
|
}
|
|
|
|
void GX_ReadGPMetric(u32 *cnt0,u32 *cnt1)
|
|
{
|
|
u32 tmp,reg1,reg2;
|
|
|
|
reg1 = (_SHIFTL(_cpReg[33],16,16))|(_cpReg[32]&0xffff);
|
|
reg2 = (_SHIFTL(_cpReg[35],16,16))|(_cpReg[34]&0xffff);
|
|
//reg3 = (_SHIFTL(_cpReg[37],16,16))|(_cpReg[36]&0xffff);
|
|
//reg4 = (_SHIFTL(_cpReg[39],16,16))|(_cpReg[38]&0xffff);
|
|
|
|
*cnt0 = 0;
|
|
if(__gx->perf0Mode==GX_PERF0_CLIP_RATIO) {
|
|
tmp = reg2*1000;
|
|
*cnt0 = tmp/reg1;
|
|
} else if(__gx->perf0Mode>=GX_PERF0_VERTICES && __gx->perf0Mode<GX_PERF0_NONE) *cnt0 = reg1;
|
|
|
|
//further implementation needed.....
|
|
// cnt1 fails....
|
|
}
|
|
|
|
void GX_AdjustForOverscan(GXRModeObj *rmin,GXRModeObj *rmout,u16 hor,u16 ver)
|
|
{
|
|
if(rmin!=rmout) memcpy(rmout,rmin,sizeof(GXRModeObj));
|
|
|
|
rmout->fbWidth = rmin->fbWidth-(hor<<1);
|
|
rmout->efbHeight = rmin->efbHeight-((rmin->efbHeight*(ver<<1))/rmin->xfbHeight);
|
|
if(rmin->xfbMode==VI_XFBMODE_SF && !(rmin->viTVMode&VI_PROGRESSIVE)) rmout->xfbHeight = rmin->xfbHeight-ver;
|
|
else rmout->xfbHeight = rmin->xfbHeight-(ver<<1);
|
|
|
|
rmout->viWidth = rmin->viWidth-(hor<<1);
|
|
if(rmin->viTVMode&VI_PROGRESSIVE) rmout->viHeight = rmin->viHeight-(ver<<2);
|
|
else rmout->viHeight = rmin->viHeight-(ver<<1);
|
|
|
|
rmout->viXOrigin += hor;
|
|
rmout->viYOrigin += ver;
|
|
}
|
|
|
|
f32 GX_GetYScaleFactor(u16 efbHeight,u16 xfbHeight)
|
|
{
|
|
u32 yScale,xfblines,cnt;
|
|
f32 yscale;
|
|
|
|
yscale = (f32)efbHeight/(f32)xfbHeight;
|
|
yScale = (u32)((f32)256.0/yscale)&0x1ff;
|
|
|
|
cnt = xfbHeight;
|
|
xfblines = __GX_GetNumXfbLines(efbHeight,yScale);
|
|
while(xfblines>=xfbHeight) {
|
|
yscale = (f32)(cnt--)/(f32)efbHeight;
|
|
yScale = (u32)((f32)256.0/yscale)&0x1ff;
|
|
xfblines = __GX_GetNumXfbLines(efbHeight,yScale);
|
|
}
|
|
|
|
while(xfblines<xfbHeight) {
|
|
yscale = (f32)(cnt++)/(f32)efbHeight;
|
|
yScale = (u32)((f32)256.0/yscale)&0x1ff;
|
|
xfblines = __GX_GetNumXfbLines(efbHeight,yScale);
|
|
}
|
|
return yscale;
|
|
}
|
|
|
|
void GX_ReadBoundingBox(u16 *top,u16 *bottom,u16 *left,u16 *right)
|
|
{
|
|
*left = _peReg[8];
|
|
*right = _peReg[9];
|
|
*top = _peReg[10];
|
|
*bottom = _peReg[11];
|
|
}
|
|
|
|
#undef LARGE_NUMBER
|