Copy dolphin/gx progress from TP

This commit is contained in:
LagoLunatic 2024-09-07 17:31:29 -04:00
parent 340d18c6bc
commit 3e7ece6ff5
34 changed files with 6713 additions and 200 deletions

View File

@ -22,11 +22,25 @@ extern "C" {
// Pack value into bitfield
#define GX_BITFIELD_SET(field, pos, size, value) (field) = __rlwimi((field), (value), 31 - (pos) - (size) + 1, (pos), (pos) + (size)-1)
#define GX_BITFIELD_TRUNC(field, pos, size, value) (__rlwimi((field), (value), 0, (pos), (pos) + (size)-1))
#define GX_BITGET(field, pos, size) ((field) >> (31 - (pos) - (size) + 1) & ((1 << (size)) - 1))
#define GX_GET_REG(reg, st, end) GX_BITGET(reg, st, (end - st + 1))
#define GX_SET_REG(reg, x, st, end) GX_BITFIELD_SET(reg, st, (end - st + 1), x)
#define GX_SET_TRUNC(reg, x, st, end) GX_BITFIELD_TRUNC((reg), (st), ((end) - (st) + 1), (x))
#define GXCOLOR_AS_U32(color) (*((u32*)&(color)))
#define INSERT_FIELD(reg, value, nbits, shift) \
(reg) = ((u32) (reg) & ~(((1 << (nbits)) - 1) << (shift))) | \
((u32) (value) << (shift));
#define FAST_FLAG_SET(regOrg, newFlag, shift, size) \
do { \
(regOrg) = (u32)__rlwimi((int)(regOrg), (int)(newFlag), (shift), (32 - (shift) - (size)), (31 - (shift))); \
} while (0);
#define GX_LOAD_BP_REG 0x61
#define GX_NOP 0
typedef union {
@ -42,7 +56,43 @@ typedef union {
f64 f64;
} PPCWGPipe;
volatile PPCWGPipe GXFIFO AT_ADDRESS(0xCC008000);
#define GXFIFO_ADDR 0xCC008000
volatile PPCWGPipe GXFIFO AT_ADDRESS(GXFIFO_ADDR);
#define GX_CP_LOAD_REG(addr, data) \
GXFIFO.s8 = GX_FIFO_CMD_LOAD_CP_REG; \
GXFIFO.s8 = (addr); \
GXFIFO.s32 = (data);
/**
* Header for an XF register load
*/
#define GX_XF_LOAD_REG_HDR(addr) \
GXFIFO.s8 = GX_FIFO_CMD_LOAD_XF_REG; \
GXFIFO.s32 = (addr);
/**
* Load immediate value into XF register
*/
#define GX_XF_LOAD_REG(addr, data) \
GX_XF_LOAD_REG_HDR(addr); \
GXFIFO.s32 = (data);
/**
* Load immediate value into BP register
*/
#define GX_BP_LOAD_REG(data) \
GXFIFO.s8 = GX_FIFO_CMD_LOAD_BP_REG; \
GXFIFO.s32 = (data);
/**
* Load immediate values into multiple XF registers
*/
#define GX_XF_LOAD_REGS(size, addr) \
{ \
u32 cmd = (size) << 16 | addr; \
GX_XF_LOAD_REG_HDR(cmd); \
}
// Direct
inline void GXPosition2f32(f32 x, f32 z) {

View File

@ -24,7 +24,7 @@ void GXSetVtxDescv(GXVtxDescList* list);
void __GXSetVCD(void);
void __GXCalculateVLim(void);
void GXClearVtxDesc(void);
void GXSetVtxAttrFmt(GXVtxFmt fmt, GXAttr attr, GXCompCnt cnt, GXCompType type, u32);
void GXSetVtxAttrFmt(GXVtxFmt fmt, GXAttr attr, GXCompCnt cnt, GXCompType type, u8 frac);
void GXSetVtxAttrFmtv(GXVtxFmt fmt, GXVtxAttrFmtList* list);
void __GXSetVAT(void);
void GXSetArray(GXAttr attr, void* base, u8);

File diff suppressed because it is too large Load Diff

View File

@ -9,27 +9,29 @@
extern "C" {
#endif
typedef void (*GXBreakPtCallback)(void);
void GXInitFifoBase(GXFifoObj* fifo, void* base, u32 size);
void GXInitFifoPtrs(GXFifoObj* fifo, void* read_ptr, void* write_ptr);
void GXSetCPUFifo(void);
void GXSetGPFifo(void);
void GXSetCPUFifo(GXFifoObj* fifo);
void GXSetGPFifo(GXFifoObj* fifo);
void GXSaveCPUFifo(GXFifoObj* fifo);
void __GXSaveCPUFifoAux(GXFifoObj* fifo);
void GXGetGPStatus(GXBool* overhi, GXBool* underlo, GXBool* read_idle, GXBool* cmd_idle, GXBool* breakpoint);
void* GXGetFifoBase(GXFifoObj* fifo);
u32 GXGetFifoSize(GXFifoObj* fifo);
void GXSetBreakPtCallback(void);
GXBreakPtCallback GXSetBreakPtCallback(GXBreakPtCallback cb);
void __GXFifoInit(void);
void __GXFifoReadEnable(void);
void __GXFifoReadDisable(void);
void __GXFifoLink(u8);
void __GXWriteFifoIntEnable(u8, u8);
void __GXWriteFifoIntReset(u8, u8);
void __GXWriteFifoIntEnable(u32 p1, u32 p2);
void __GXWriteFifoIntReset(u32 p1, u32 p2);
void __GXCleanGPFifo(void);
OSThread* GXSetCurrentGXThread(void);
OSThread* GXGetCurrentGXThread(void);
GXFifoObj* GXGetCPUFifo(void);
u32 GXGetGPFifo(void);
GXFifoObj* GXGetGPFifo(void);
#ifdef __cplusplus
};

View File

@ -17,7 +17,7 @@ extern GXRenderModeObj GXEurgb60Hz480IntDf;
void GXSetDispCopySrc(u16 left, u16 top, u16 width, u16 height);
void GXSetTexCopySrc(u16 left, u16 top, u16 width, u16 height);
void GXSetDispCopyDst(u16 arg0, u16 arg1);
void GXSetTexCopyDst(u16 width, u16 height, s32 fmt, GXBool mipmap);
void GXSetTexCopyDst(u16 width, u16 height, GXTexFmt format, GXBool useMIPmap);
void GXSetDispCopyFrame2Field(GXCopyMode mode);
void GXSetCopyClamp(GXFBClamp clamp);
u16 GXGetNumXfbLines(u16 efb_height, f32 y_scale);

View File

@ -5,112 +5,159 @@
#include "dolphin/gx/GXStruct.h"
#include "dolphin/mtx/mtx.h"
typedef GXTexRegion (*GXTexRegionCallback)(GXTexObj* obj);
typedef GXTlutRegion* (*GXTlutRegionCallback)(u32 name);
typedef GXTexRegion* (*GXTexRegionCallback)(const GXTexObj* t_obj, GXTexMapID id);
typedef GXTlutRegion* (*GXTlutRegionCallback)(u32 idx);
typedef struct _GXData {
/* 0x000 */ u16 field_0x0;
/* 0x002 */ u16 field_0x2;
/* 0x004 */ u16 field_0x4;
/* 0x006 */ u16 field_0x6;
/* 0x008 */ u32 field_0x8;
/* 0x00C */ u32 field_0xc;
/* 0x010 */ u32 field_0x10;
/* 0x014 */ u32 field_0x14;
/* 0x018 */ GXAttrType field_0x18;
/* 0x01C */ GXCompCnt field_0x1c[8];
/* 0x03C */ GXCompCnt field_0x3c[8];
/* 0x05C */ u32 field_0x5c[8];
/* 0x07C */ u32 field_0x7c;
/* 0x080 */ u32 field_0x80;
/* 0x084 */ u32 field_0x84;
/* 0x088 */ u8 field_0x88[0xA8 - 0x88];
/* 0x0A8 */ GXColor ambColors[2];
/* 0x0B0 */ GXColor matColors[2];
/* 0x0B8 */ u32 field_0xb8[8]; // GX_MAX_TEXCOORD
/* 0x0D8 */ u32 field_0xd8[8]; // GX_MAX_TEXCOORD
/* 0x0F8 */ u32 field_0xf8;
/* 0x0FC */ u32 field_0xfc;
/* 0x100 */ u32 field_0x100[GX_MAX_TEVSTAGE / 2];
/* 0x120 */ u32 field_0x120;
/* 0x124 */ u32 field_0x124;
/* 0x128 */ u32 field_0x128;
/* 0x12C */ u32 field_0x12c;
/* 0x130 */ u32 field_0x130[GX_MAX_TEVSTAGE];
/* 0x170 */ u32 field_0x170[GX_MAX_TEVSTAGE];
/* 0x1B0 */ u32 field_0x1b0[GX_MAX_TEVSTAGE / 2];
/* 0x1D0 */ u32 field_0x1d0;
/* 0x1D4 */ u32 field_0x1d4;
/* 0x1D8 */ u32 field_0x1d8;
/* 0x1DC */ u32 field_0x1dc;
/* 0x1E0 */ u32 field_0x1e0;
/* 0x1E4 */ u32 field_0x1e4;
/* 0x1E8 */ u32 field_0x1e8;
/* 0x1EC */ u32 field_0x1ec;
/* 0x1F0 */ u32 field_0x1f0;
/* 0x1F4 */ u32 field_0x1f4;
/* 0x1F8 */ u32 field_0x1f8;
/* 0x1FC */ u32 field_0x1fc;
/* 0x200 */ u8 field_0x200;
/* 0x204 */ u32 field_0x204;
/* 0x208 */ GXTexRegion field_0x208[8];
/* 0x288 */ GXTexRegion field_0x288[8];
/* 0x308 */ GXTexRegion field_0x308[8];
/* 0x388 */ GXTlutRegion field_0x388[16];
/* 0x488 */ GXTlutRegion field_0x488[4];
/* 0x4C8 */ GXTexRegionCallback field_0x4c8;
/* 0x4CC */ GXTlutRegionCallback field_0x4cc;
/* 0x4D0 */ GXAttrType field_0x4d0;
/* 0x4D4 */ u8 field_0x4d4;
/* 0x4D5 */ u8 field_0x4d5;
/* 0x4D8 */ GXProjectionType field_0x4d8;
/* 0x4DC */ Mtx field_0x4dc;
/* 0x50C */ f32 field_0x50c;
/* 0x510 */ f32 field_0x510;
/* 0x514 */ u32 field_0x514[8];
/* 0x534 */ u32 field_0x534[8];
/* 0x554 */ u32 field_0x554;
/* 0x558 */ u32 field_0x558[8];
/* 0x578 */ u8 field_0x578[0x594 - 0x578];
/* 0x594 */ u32 field_0x594;
/* 0x598 */ u32 field_0x598;
/* 0x59C */ u32 field_0x59c;
/* 0x5A0 */ u8 field_0x5a0[4];
/* 0x5A4 */ u32 field_0x5a4;
/* 0x5A8 */ u8 field_0x5a8;
/* 0x5A9 */ u8 field_0x5a9;
/* 0x5AA */ u8 field_0x5aa;
/* 0x5AB */ u8 field_0x5ab;
/* 0x5AC */ u32 field_0x5ac;
// Bypass and vertex info
/* 0x000 */ u16 vNumNot;
/* 0x002 */ u16 bpSentNot;
/* 0x004 */ u16 vNum;
/* 0x006 */ u16 vLim;
// Command process (CP) regs
/* 0x008 */ u32 cpEnable;
/* 0x00C */ u32 cpStatus;
/* 0x010 */ u32 cpClr;
/* 0x014 */ u32 vcdLo;
/* 0x018 */ u32 vcdHi;
/* 0x01C */ u32 vatA[8];
/* 0x03C */ u32 vatB[8];
/* 0x05C */ u32 vatC[8];
/* 0x07C */ u32 lpSize;
/* 0x080 */ u32 matIdxA;
/* 0x084 */ u32 matIdxB;
// Index loading base/stride regs (pos, nrm, tex, light)
/* 0x088 */ u32 indexBase[4];
/* 0x098 */ u32 indexStride[4];
// Transform and lighting regs
/* 0x0A8 */ u32 ambColor[2];
/* 0x0B0 */ u32 matColor[2];
// Setup regs
/* 0x0B8 */ u32 suTs0[8];
/* 0x0D8 */ u32 suTs1[8];
/* 0x0F8 */ u32 suScis0;
/* 0x0FC */ u32 suScis1;
// Raster regs
/* 0x100 */ u32 tref[8];
/* 0x120 */ u32 iref;
// Bump/Indirect texture regs
/* 0x124 */ u32 bpMask;
/* 0x128 */ u32 IndTexScale0;
/* 0x12C */ u32 IndTexScale1;
// Tev regs
/* 0x130 */ u32 tevc[16];
/* 0x170 */ u32 teva[16];
/* 0x1B0 */ u32 tevKsel[8];
// Performance regs
/* 0x1D0 */ u32 cmode0;
/* 0x1D4 */ u32 cmode1;
/* 0x1D8 */ u32 zmode;
/* 0x1DC */ u32 peCtrl;
// Display copy regs
/* 0x1E0 */ u32 cpDispSrc;
/* 0x1E4 */ u32 cpDispSize;
/* 0x1E8 */ u32 cpDispStride;
/* 0x1EC */ u32 cpDisp;
// Texture copy regs
/* 0x1F0 */ u32 cpTexSrc;
/* 0x1F4 */ u32 cpTexSize;
/* 0x1F8 */ u32 cpTexStride;
/* 0x1FC */ u32 cpTex;
/* 0x200 */ GXBool cpTexZ;
// General raster mode
/* 0x204 */ u32 genMode;
// Texture regions
/* 0x208 */ GXTexRegion TexRegions0[GX_MAX_TEXMAP];
/* 0x288 */ GXTexRegion TexRegions1[GX_MAX_TEXMAP];
/* 0x308 */ GXTexRegion TexRegions2[GX_MAX_TEXMAP];
// Texture lookup table regions
/* 0x388 */ GXTlutRegion TlutRegions[GX_MAX_TLUT_ALL];
/* 0x4C8 */ GXTexRegionCallback texRegionCallback;
/* 0x4CC */ GXTlutRegionCallback tlutRegionCallback;
// Command processor vars
/* 0x4D0 */ GXAttrType nrmType;
/* 0x4D4 */ GXBool hasNrms;
/* 0x4D5 */ GXBool hasBiNrms;
/* 0x4D8 */ u32 projType;
/* 0x4DC */ f32 projMtx[6];
// Viewport parms
/* 0x4F4 */ f32 vpLeft;
/* 0x4F8 */ f32 vpTop;
/* 0x4FC */ f32 vpWd;
/* 0x500 */ f32 vpHt;
/* 0x504 */ f32 vpNearz;
/* 0x508 */ f32 vpFarz;
/* 0x50C */ f32 zOffset;
/* 0x510 */ f32 zScale;
// Texture regs
/* 0x514 */ u32 tImage0[8];
/* 0x534 */ u32 tMode0[8];
/* 0x554 */ u32 texmapId[16];
/* 0x594 */ u32 tcsManEnab;
/* 0x598 */ u32 tevTcEnab;
// Performance metrics
/* 0x59C */ GXPerf0 perf0;
/* 0x5A0 */ GXPerf1 perf1;
/* 0x5A4 */ u32 perfSel;
// Flags
/* 0x5A8 */ GXBool inDispList;
/* 0x5A9 */ GXBool dlSaveContext;
/* 0x5AA */ GXBool abtWaitPECopy;
/* 0x5AB */ u8 dirtyVAT;
/* 0x5AC */ u32 dirtyState;
} GXData; // Size: 0x5B0
STATIC_ASSERT(sizeof(GXData) == 0x5B0);
extern GXData* const __GXData;
// Define register addresses.
#define GX_CP_ADDR (0x0C000000)
#define GX_PE_ADDR (0x0C001000)
#define GX_PI_ADDR (0x0C003000)
#define GX_MEM_ADDR (0x0C004000)
extern u32* __piReg;
extern u16* __cpReg;
extern u8 __peReg[4];
extern u8 __memReg[4];
extern u16* __peReg;
extern vu16* __memReg;
inline void GXSetWasteFlags() {
GXData* data = __GXData;
data->field_0x5ac |= 0x3;
data->field_0x2 = 0;
data->dirtyState |= GX_DIRTY_SU_TEX | GX_DIRTY_BP_MASK;
data->bpSentNot = 0;
}
static inline void set_x2(u16 value)
{
__GXData->field_0x2 = value;
__GXData->bpSentNot = value;
}
#ifdef __cplusplus
extern "C" {
#endif
GXTexRegion* __GXDefaultTexRegionCallback(GXTexObj* obj, GXTexMapID mapID);
GXTexRegion* __GXDefaultTexRegionCallback(const GXTexObj* obj, GXTexMapID id);
GXTlutRegion* __GXDefaultTlutRegionCallback(u32 tlut);
void __GXShutdown(s32);
BOOL __GXShutdown(BOOL final);
void __GXInitRevisionBits(void);
GXFifoObj* GXInit(void* base, u32 size);
void __GXInitGX(void);

View File

@ -7,7 +7,7 @@
extern "C" {
#endif
void GXSetMisc(u32 id, u32 value);
void GXSetMisc(GXMiscToken token, u32 val);
void GXFlush(void);
void __GXAbort(void);
void GXAbortFrame(void);
@ -21,7 +21,7 @@ void GXPokeBlendMode(GXBlendMode mode, GXBlendFactor src_factor, GXBlendFactor d
void GXPokeColorUpdate(GXBool enable_update);
void GXPokeDstAlpha(GXBool enable, u8 alpha);
void GXPokeDither(GXBool enable);
void GXPokeZMode(GXBool enable_compare, GXCompare comp);
void GXPokeZMode(GXBool enable_compare, GXCompare comp, GXBool update_enable);
void GXPeekARGB(u16 x, u16 y, u32* color);
void GXPeekZ(u16 x, u16 y, u32* z);
@ -30,7 +30,7 @@ GXDrawSyncCallback GXSetDrawSyncCallback(GXDrawSyncCallback callback);
void GXSetDrawSync(GXBool enable);
typedef void (*GXDrawDoneCallback)(void);
void GXSetDrawDoneCallback(GXDrawDoneCallback callback);
GXDrawDoneCallback GXSetDrawDoneCallback(GXDrawDoneCallback callback);
void __GXPEInit(void);
#ifdef __cplusplus

View File

@ -1,13 +1,13 @@
#ifndef GXPERF_H
#define GXPERF_H
#include "dolphin/types.h"
#include "dolphin/gx/GXEnum.h"
#ifdef __cplusplus
extern "C" {
#endif
void GXSetGPMetric(u32 perf0, u32 perf1);
void GXSetGPMetric(GXPerf0 perf0, GXPerf1 perf1);
void GXClearGPMetric(void);
void GXReadXfRasMetric(u32*, u32*, u32*, u32*);

View File

@ -2,6 +2,8 @@
#define GXSTRUCT_H
#include "global.h"
#include "dolphin/gx/GXEnum.h"
#include "dolphin/vi/vi.h"
typedef struct _GXColor {
/* 0x0 */ u8 r;
@ -72,18 +74,18 @@ typedef struct _GXLightObj {
} GXLightObj;
typedef struct _GXFogAdjTable {
/* 0x0 */ u16 r[10];
/* 0x0 */ u16 fogVals[10];
} GXFogAdjTable;
typedef struct _GXFifoObj {
/* 0x00 */ void* base;
/* 0x04 */ u32 end;
/* 0x04 */ void* end;
/* 0x08 */ u32 size;
/* 0x0C */ u32 high_wtrmark;
/* 0x10 */ u32 low_wtrmark;
/* 0x14 */ void* read_ptr;
/* 0x18 */ void* write_ptr;
/* 0x1C */ void* rw_dst;
/* 0x1C */ s32 rw_dst;
/* 0x20 */ u8 fifo_wrap;
/* 0x21 */ u8 cpu_fifo_ready;
/* 0x22 */ u8 gp_fifo_ready;
@ -91,11 +93,16 @@ typedef struct _GXFifoObj {
} GXFifoObj; // Size: 0x80
typedef struct _GXTexRegion {
/* 0x00 */ u8 dummy[0x10];
u32 unk0; // _00
u32 unk4; // _04
u32 unk8; // _08
u8 unkC; // _0C
u8 unkD; // _0D
} GXTexRegion; // Size: 0x10
typedef struct _GXTlutRegion {
/* 0x00 */ u8 dummy[0x10];
/* 0x00 */ u32 unk0;
/* 0x04 */ GXTlutObj tlutObj;
} GXTlutRegion; // Size: 0x10
#endif /* GXSTRUCT_H */

View File

@ -8,7 +8,7 @@ extern "C" {
#endif
u32 GXGetTexBufferSize(u16 width, u16 height, u32 format, GXBool mipmap, u8 max_lod);
void __GetImageTileCount(u32 arg0, s16 arg1, s16 arg2, s32* arg3, s32* arg4, s32* arg5);
void __GetImageTileCount(GXTexFmt format, u16 width, u16 height, u32* a, u32* b, u32* c);
void GXInitTexObj(GXTexObj* obj, void* image, u16 width, u16 height, GXTexFmt fmt,
GXTexWrapMode wrapS, GXTexWrapMode wrapT, GXBool mipmap);
void GXInitTexObjCI(GXTexObj* obj, void* image, u16 width, u16 height, GXCITexFmt format,
@ -19,10 +19,10 @@ void GXInitTexObjLOD(GXTexObj* obj, GXTexFilter min_filter, GXTexFilter max_filt
void* GXGetTexObjData(GXTexObj* obj);
u16 GXGetTexObjWidth(GXTexObj* obj);
u16 GXGetTexObjHeight(GXTexObj* obj);
GXTexFmt GXGetTexObjFmt(GXTexObj* obj);
GXTexFmt GXGetTexObjFmt(const GXTexObj* obj);
GXTexWrapMode GXGetTexObjWrapS(GXTexObj* obj);
GXTexWrapMode GXGetTexObjWrapT(GXTexObj* obj);
GXBool GXGetTexObjMipMap(GXTexObj* obj);
GXBool GXGetTexObjMipMap(const GXTexObj* obj);
u32 GXGetTexObjTlut(GXTexObj* obj);
void GXLoadTexObj(GXTexObj* obj, GXTexMapID id);
void GXInitTlutObj(GXTlutObj* obj, void* lut, GXTlutFmt fmt, u16 entry_num);

View File

@ -9,18 +9,18 @@ extern "C" {
#endif
void GXProject(f32 model_x, f32 model_y, f32 model_z, Mtx model_mtx, f32* proj, f32* viewpoint, f32* screen_x, f32* screen_y, f32* screen_z);
void GXSetProjection(Mtx44 mtx, GXProjectionType type);
void GXSetProjection(const Mtx44 proj, GXProjectionType type);
void GXSetProjectionv(f32* p);
void GXGetProjectionv(f32* p);
void GXLoadPosMtxImm(Mtx mtx, u32 id);
void GXLoadNrmMtxImm(Mtx mtx, u32 id);
void GXSetCurrentMtx(u32 id);
void GXLoadTexMtxImm(Mtx mtx, u32 id, GXTexMtxType type);
void GXLoadTexMtxImm(const Mtx mtx, u32 id, GXTexMtxType type);
void GXSetViewport(f32 x_orig, f32 y_orig, f32 width, f32 height, f32 near_z, f32 far_z);
void GXGetViewportv(f32* p);
void GXSetScissor(u32 left, u32 top, u32 width, u32 height);
void GXGetScissor(u32* left, u32* top, u32* width, u32* height);
void GXSetScissorBoxOffset(u32 x_offset, u32 y_offset);
void GXSetScissorBoxOffset(s32 x, s32 y);
void GXSetClipMode(GXClipMode mode);
#ifdef __cplusplus

View File

@ -41,7 +41,7 @@ typedef enum {
EXCEPTION_FLOATING_POINT,
EXCEPTION_DECREMENTER,
EXCEPTION_SYSTEM_CALL,
EXCEPTION_TRACE ,
EXCEPTION_TRACE,
EXCEPTION_PERFORMANCE_MONITOR,
EXCEPTION_BREAKPOINT,
EXCEPTION_RESERVED,

View File

@ -10,37 +10,120 @@ extern "C" {
typedef struct _GXRenderModeObj GXRenderModeObj;
#define VI_TVMODE(format, interlace) (((format) << 2) + (interlace))
#define VI_INTERLACE (0)
#define VI_NON_INTERLACE (1)
#define VI_PROGRESSIVE (2)
#define VI_3D (3)
#define VI_INTERLACE 0
#define VI_NON_INTERLACE 1
#define VI_PROGRESSIVE 2
// Video output formats
#define VI_NTSC (0)
#define VI_PAL (1)
#define VI_MPAL (2)
#define VI_DEBUG (3)
#define VI_DEBUG_PAL (4)
#define VI_EURGB60 (5)
#define VI_GCA (6)
#define VI_NTSC 0
#define VI_PAL 1
#define VI_MPAL 2
#define VI_DEBUG 3
#define VI_DEBUG_PAL 4
#define VI_EURGB60 5
// Conversion to TVMode used in enums
#define VI_TVMODE(FMT, INT) (((FMT) << 2) + (INT))
// TV Modes
typedef enum {
VI_TVMODE_NTSC_INT = VI_TVMODE(VI_NTSC, VI_INTERLACE),
VI_TVMODE_NTSC_DS = VI_TVMODE(VI_NTSC, VI_NON_INTERLACE),
VI_TVMODE_NTSC_PROG = VI_TVMODE(VI_NTSC, VI_PROGRESSIVE),
VI_TVMODE_PAL_INT = VI_TVMODE(VI_PAL, VI_INTERLACE),
VI_TVMODE_PAL_DS = VI_TVMODE(VI_PAL, VI_NON_INTERLACE),
VI_TVMODE_EURGB60_INT = VI_TVMODE(VI_EURGB60, VI_INTERLACE),
VI_TVMODE_EURGB60_DS = VI_TVMODE(VI_EURGB60, VI_NON_INTERLACE),
VI_TVMODE_MPAL_INT = VI_TVMODE(VI_MPAL, VI_INTERLACE),
VI_TVMODE_MPAL_DS = VI_TVMODE(VI_MPAL, VI_NON_INTERLACE),
VI_TVMODE_DEBUG_INT = VI_TVMODE(VI_DEBUG, VI_INTERLACE),
VI_TVMODE_DEBUG_PAL_INT = VI_TVMODE(VI_DEBUG_PAL, VI_INTERLACE),
VI_TVMODE_DEBUG_PAL_DS = VI_TVMODE(VI_DEBUG_PAL, VI_NON_INTERLACE)
// NTSC
VI_TVMODE_NTSC_INT = VI_TVMODE(VI_NTSC, VI_INTERLACE), // 0
VI_TVMODE_NTSC_DS = VI_TVMODE(VI_NTSC, VI_NON_INTERLACE), // 1
VI_TVMODE_NTSC_PROG = VI_TVMODE(VI_NTSC, VI_PROGRESSIVE), // 2
VI_TVMODE_NTSC_3D = VI_TVMODE(VI_NTSC, VI_3D), // 3
// PAL
VI_TVMODE_PAL_INT = VI_TVMODE(VI_PAL, VI_INTERLACE), // 4
VI_TVMODE_PAL_DS = VI_TVMODE(VI_PAL, VI_NON_INTERLACE), // 5
// MPAL
VI_TVMODE_MPAL_INT = VI_TVMODE(VI_MPAL, VI_INTERLACE), // 8
VI_TVMODE_MPAL_DS = VI_TVMODE(VI_MPAL, VI_NON_INTERLACE), // 9
// Debug
VI_TVMODE_DEBUG_INT = VI_TVMODE(VI_DEBUG, VI_INTERLACE), // 12
// Debug PAL
VI_TVMODE_DEBUG_PAL_INT = VI_TVMODE(VI_DEBUG_PAL, VI_INTERLACE), // 16
VI_TVMODE_DEBUG_PAL_DS = VI_TVMODE(VI_DEBUG_PAL, VI_NON_INTERLACE), // 17
// EU RGB60
VI_TVMODE_EURGB60_INT = VI_TVMODE(VI_EURGB60, VI_INTERLACE), // 20
VI_TVMODE_EURGB60_DS = VI_TVMODE(VI_EURGB60, VI_NON_INTERLACE), // 21
// GCA
VI_TVMODE_GCA_INT = VI_TVMODE(VI_GCA, VI_INTERLACE), // 24
VI_TVMODE_GCA_DS = VI_TVMODE(VI_GCA, VI_NON_INTERLACE), // 25
VI_TVMODE_GCA_PROG = VI_TVMODE(VI_GCA, VI_PROGRESSIVE), // 26
} VITVMode;
typedef enum { VI_XFBMODE_SF = 0, VI_XFBMODE_DF } VIXFBMode;
typedef void (*VIRetraceCallback)(u32);
typedef void (*VIPositionCallback)(s16 x, s16 y);
typedef struct VITimingInfo {
u8 equ; // _00
u16 acv; // _02
u16 prbOdd; // _04
u16 prbEven; // _06
u16 psbOdd; // _08
u16 psbEven; // _0A
u8 bs1; // _0C
u8 bs2; // _0D
u8 bs3; // _0E
u8 bs4; // _0F
u16 be1; // _10
u16 be2; // _12
u16 be3; // _14
u16 be4; // _16
u16 numHalfLines; // _18
u16 hlw; // _1A
u8 hsy; // _1C
u8 hcs; // _1D
u8 hce; // _1E
u8 hbe640; // _1F
u16 hbs640; // _20
u8 hbeCCIR656; // _24
u16 hbsCCIR656; // _26
} VITimingInfo;
typedef struct VIPositionInfo {
u16 dispPosX; // _00
u16 dispPosY; // _02
u16 dispSizeX; // _04
u16 dispSizeY; // _06
u16 adjDispPosX; // _08
u16 adjDispPosY; // _0A
u16 adjDispSizeY; // _0C
u16 adjPanPosY; // _0E
u16 adjPanSizeY; // _10
u16 fbSizeX; // _12
u16 fbSizeY; // _14
u16 panPosX; // _16
u16 panPosY; // _18
u16 panSizeX; // _1A
u16 panSizeY; // _1C
VIXFBMode xfbMode; // _20
u32 nonInter; // _24
u32 tv; // _28
u8 wordPerLine; // _2C
u8 std; // _2D
u8 wpl; // _2E
u32 bufAddr; // _30
u32 tfbb; // _34
u32 bfbb; // _38
u8 xof; // _3C
BOOL isBlack; // _40
BOOL is3D; // _44
u32 rbufAddr; // _48
u32 rtfbb; // _4C
u32 rbfbb; // _50
VITimingInfo* timing; // _54
} VIPositionInfo;
void VIWaitForRetrace(void);
void VISetNextFrameBuffer(void*);

View File

@ -502,7 +502,7 @@ void J3DGDSetFog(GXFogType type, f32 startZ, f32 endZ, f32 nearZ, f32 farZ, GXCo
void J3DGDSetFogRangeAdj(u8 enabled, u16 center, GXFogAdjTable* pFogAdjTable) {
if (enabled) {
for (s32 i = 0; i < 10; i += 2) {
J3DGDWriteBPCmd((0xe9 + i / 2) << 24 | pFogAdjTable->r[i + 1] << 12 | pFogAdjTable->r[i] << 0);
J3DGDWriteBPCmd((0xe9 + i / 2) << 24 | pFogAdjTable->fogVals[i + 1] << 12 | pFogAdjTable->fogVals[i] << 0);
}
}

View File

@ -148,7 +148,7 @@ void J3DSys::setTexCacheRegion(GXTexCacheSize size) {
/* 802D8EE0-802D956C .text drawInit__6J3DSysFv */
void J3DSys::drawInit() {
GXSetMisc(2, 0);
GXSetMisc(GX_MT_DL_SAVE_CONTEXT, 0);
GXInvalidateVtxCache();
GXSetCurrentMtx(GX_PNMTX0);
GXSetCullMode(GX_CULL_BACK);

View File

@ -822,7 +822,7 @@ void JPADraw::drawParticle() {
GXSetCullMode(GX_CULL_NONE);
if (dc.pbsp->isClipOn()) {
GXSetClipMode(GX_CLIP_ENABLE);
GXSetMisc(1, 8);
GXSetMisc(GX_MT_XF_FLUSH, 8);
} else {
GXSetClipMode(GX_CLIP_DISABLE);
}
@ -845,7 +845,7 @@ void JPADraw::drawParticle() {
}
}
GXSetMisc(1, 0);
GXSetMisc(GX_MT_XF_FLUSH, 0);
}
/* 8026BC2C-8026BF88 .text drawChild__7JPADrawFv */
@ -871,7 +871,7 @@ void JPADraw::drawChild() {
if (dc.pssp->isClipOn()) {
GXSetClipMode(GX_CLIP_ENABLE);
GXSetMisc(1, 8);
GXSetMisc(GX_MT_XF_FLUSH, 8);
} else {
GXSetClipMode(GX_CLIP_DISABLE);
}
@ -894,7 +894,7 @@ void JPADraw::drawChild() {
}
}
GXSetMisc(1, 0);
GXSetMisc(GX_MT_XF_FLUSH, 0);
}
/* 8026BF88-8026C024 .text zDraw__7JPADrawFv */
@ -922,7 +922,7 @@ void JPADraw::zDrawParticle() {
GXSetCullMode(GX_CULL_NONE);
if (dc.pbsp->isClipOn()) {
GXSetClipMode(GX_CLIP_ENABLE);
GXSetMisc(1, 8);
GXSetMisc(GX_MT_XF_FLUSH, 8);
} else {
GXSetClipMode(GX_CLIP_DISABLE);
}
@ -945,7 +945,7 @@ void JPADraw::zDrawParticle() {
}
}
GXSetMisc(1, 0);
GXSetMisc(GX_MT_XF_FLUSH, 0);
}
/* 8026C24C-8026C4DC .text zDrawChild__7JPADrawFv */
@ -971,7 +971,7 @@ void JPADraw::zDrawChild() {
if (dc.pssp->isClipOn()) {
GXSetClipMode(GX_CLIP_ENABLE);
GXSetMisc(1, 8);
GXSetMisc(GX_MT_XF_FLUSH, 8);
} else {
GXSetClipMode(GX_CLIP_DISABLE);
}
@ -994,7 +994,7 @@ void JPADraw::zDrawChild() {
}
}
GXSetMisc(1, 0);
GXSetMisc(GX_MT_XF_FLUSH, 0);
}
/* 8026C4DC-8026C640 .text loadYBBMtx__7JPADrawFPA4_f */

View File

@ -441,7 +441,7 @@ dKyd_Schedule* dKyd_schejule_menu_getp() {
/* 80086F34-80086F74 .text dKyd_xfog_table_set__FUc */
void dKyd_xfog_table_set(u8 i_idx) {
for (int i = 0; i < 10; i++) {
u16 fogAdjTableEntry = S_xfog_table_data[i_idx].r[i];
g_env_light.mFogAdjTable.r[i] = fogAdjTableEntry;
u16 fogAdjTableEntry = S_xfog_table_data[i_idx].fogVals[i];
g_env_light.mFogAdjTable.fogVals[i] = fogAdjTableEntry;
}
}

751
src/dolphin/gx/GXAttr.c Normal file
View File

@ -0,0 +1,751 @@
#include "dolphin/gx/GXAttr.h"
#include "dolphin/gx/GX.h"
static inline void SETVCDATTR(GXAttr name, GXAttrType type) {
switch (name) {
case GX_VA_PNMTXIDX:
GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_POSMTXIDX_ST, GX_CP_VCD_LO_POSMTXIDX_END);
break;
case GX_VA_TEX0MTXIDX:
GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_TEX0MTXIDX_ST,
GX_CP_VCD_LO_TEX0MTXIDX_END);
break;
case GX_VA_TEX1MTXIDX:
GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_TEX1MTXIDX_ST,
GX_CP_VCD_LO_TEX1MTXIDX_END);
break;
case GX_VA_TEX2MTXIDX:
GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_TEX2MTXIDX_ST,
GX_CP_VCD_LO_TEX2MTXIDX_END);
break;
case GX_VA_TEX3MTXIDX:
GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_TEX3MTXIDX_ST,
GX_CP_VCD_LO_TEX3MTXIDX_END);
break;
case GX_VA_TEX4MTXIDX:
GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_TEX4MTXIDX_ST,
GX_CP_VCD_LO_TEX4MTXIDX_END);
break;
case GX_VA_TEX5MTXIDX:
GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_TEX5MTXIDX_ST,
GX_CP_VCD_LO_TEX5MTXIDX_END);
break;
case GX_VA_TEX6MTXIDX:
GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_TEX6MTXIDX_ST,
GX_CP_VCD_LO_TEX6MTXIDX_END);
break;
case GX_VA_TEX7MTXIDX:
GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_TEX7MTXIDX_ST,
GX_CP_VCD_LO_TEX7MTXIDX_END);
break;
case GX_VA_POS:
GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_POS_ST, GX_CP_VCD_LO_POS_END);
break;
case GX_VA_NRM:
if (type != GX_NONE) {
__GXData->hasNrms = TRUE;
__GXData->hasBiNrms = FALSE;
__GXData->nrmType = type;
} else {
__GXData->hasNrms = FALSE;
}
break;
case GX_VA_NBT:
if (type != GX_NONE) {
__GXData->hasBiNrms = TRUE;
__GXData->hasNrms = FALSE;
__GXData->nrmType = type;
} else {
__GXData->hasBiNrms = FALSE;
}
break;
case GX_VA_CLR0:
GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_CLRDIF_ST, GX_CP_VCD_LO_CLRDIF_END);
break;
case GX_VA_CLR1:
GX_SET_REG(__GXData->vcdLo, type, GX_CP_VCD_LO_CLRSPEC_ST, GX_CP_VCD_LO_CLRSPEC_END);
break;
case GX_VA_TEX0:
GX_SET_REG(__GXData->vcdHi, type, GX_CP_VCD_HI_TEX0COORD_ST, GX_CP_VCD_HI_TEX0COORD_END);
break;
case GX_VA_TEX1:
GX_SET_REG(__GXData->vcdHi, type, GX_CP_VCD_HI_TEX1COORD_ST, GX_CP_VCD_HI_TEX1COORD_END);
break;
case GX_VA_TEX2:
GX_SET_REG(__GXData->vcdHi, type, GX_CP_VCD_HI_TEX2COORD_ST, GX_CP_VCD_HI_TEX2COORD_END);
break;
case GX_VA_TEX3:
GX_SET_REG(__GXData->vcdHi, type, GX_CP_VCD_HI_TEX3COORD_ST, GX_CP_VCD_HI_TEX3COORD_END);
break;
case GX_VA_TEX4:
GX_SET_REG(__GXData->vcdHi, type, GX_CP_VCD_HI_TEX4COORD_ST, GX_CP_VCD_HI_TEX4COORD_END);
break;
case GX_VA_TEX5:
GX_SET_REG(__GXData->vcdHi, type, GX_CP_VCD_HI_TEX5COORD_ST, GX_CP_VCD_HI_TEX5COORD_END);
break;
case GX_VA_TEX6:
GX_SET_REG(__GXData->vcdHi, type, GX_CP_VCD_HI_TEX6COORD_ST, GX_CP_VCD_HI_TEX6COORD_END);
break;
case GX_VA_TEX7:
GX_SET_REG(__GXData->vcdHi, type, GX_CP_VCD_HI_TEX7COORD_ST, GX_CP_VCD_HI_TEX7COORD_END);
break;
}
}
void GXSetVtxDesc(GXAttr name, GXAttrType type) {
SETVCDATTR(name, type);
// Set normal data type if enabled
if (__GXData->hasNrms || __GXData->hasBiNrms) {
GX_BITFIELD_SET(__GXData->vcdLo, 19, 2, __GXData->nrmType);
} else {
GX_BITFIELD_SET(__GXData->vcdLo, 19, 2, 0);
}
__GXData->dirtyState |= GX_DIRTY_VCD;
}
void GXSetVtxDescv(GXVtxDescList* list) {
for (; list->attr != GX_VA_NULL; list++) {
SETVCDATTR(list->attr, list->type);
}
// Set normal data type if enabled
if (__GXData->hasNrms || __GXData->hasBiNrms) {
GX_BITFIELD_SET(__GXData->vcdLo, 19, 2, __GXData->nrmType);
} else {
GX_BITFIELD_SET(__GXData->vcdLo, 19, 2, 0);
}
__GXData->dirtyState |= GX_DIRTY_VCD;
}
static void __GXXfVtxSpecs(void) {
u32 normCount, colorCount, texCount;
normCount = __GXData->hasBiNrms ? 2 : (__GXData->hasNrms ? 1 : 0);
// Both fields in one access
colorCount = 33 - __cntlzw((__GXData->vcdLo & (0xf << 0xd)) >> 0xd);
colorCount /= 2; // equivalent to /=2 and >>= 1
// All 16 assigned bits in VCD_Hi
texCount = 33 - __cntlzw((__GXData->vcdHi & (0xffff << 0)) >> 0);
texCount /= 2; // equivalent to /=2 and >>= 1
GX_XF_LOAD_REG(GX_XF_REG_INVERTEXSPEC, (colorCount) | (normCount << 2) | (texCount << 4));
__GXData->bpSentNot = GX_TRUE;
return;
}
void __GXSetVCD(void) {
GX_CP_LOAD_REG(GX_CP_REG_VCD_LO, __GXData->vcdLo);
GX_CP_LOAD_REG(GX_CP_REG_VCD_HI, __GXData->vcdHi);
__GXXfVtxSpecs();
}
void __GXCalculateVLim(void) {
static u8 tbl1[] = {0, 4, 1, 2};
static u8 tbl2[] = {0, 8, 1, 2};
static u8 tbl3[] = {0, 12, 1, 2};
u32 vlim;
u32 vcdLoReg;
u32 vcdHiReg;
s32 compCnt;
if (__GXData->vNum == 0) {
return;
}
vcdLoReg = __GXData->vcdLo;
vcdHiReg = __GXData->vcdHi;
// GXCompCnt bit of normal parameters
compCnt = __GXData->vatA[GX_VTXFMT0];
compCnt = (compCnt & 0x200) >> 9;
vlim = GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_POSMTXIDX_ST, GX_CP_VCD_LO_POSMTXIDX_END);
vlim += GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_TEX0MTXIDX_ST, GX_CP_VCD_LO_TEX0MTXIDX_END);
vlim += GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_TEX1MTXIDX_ST, GX_CP_VCD_LO_TEX1MTXIDX_END);
vlim += GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_TEX2MTXIDX_ST, GX_CP_VCD_LO_TEX2MTXIDX_END);
vlim += GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_TEX3MTXIDX_ST, GX_CP_VCD_LO_TEX3MTXIDX_END);
vlim += GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_TEX4MTXIDX_ST, GX_CP_VCD_LO_TEX4MTXIDX_END);
vlim += GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_TEX5MTXIDX_ST, GX_CP_VCD_LO_TEX5MTXIDX_END);
vlim += GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_TEX6MTXIDX_ST, GX_CP_VCD_LO_TEX6MTXIDX_END);
vlim += GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_TEX7MTXIDX_ST, GX_CP_VCD_LO_TEX7MTXIDX_END);
vlim += tbl3[GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_POS_ST, GX_CP_VCD_LO_POS_END)];
vlim += tbl3[GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_NRM_ST, GX_CP_VCD_LO_NRM_END)] *
(compCnt == GX_NRM_NBT ? 3 : 1);
vlim += tbl1[GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_CLRDIF_ST, GX_CP_VCD_LO_CLRDIF_END)];
vlim += tbl1[GX_GET_REG(vcdLoReg, GX_CP_VCD_LO_CLRSPEC_ST, GX_CP_VCD_LO_CLRSPEC_END)];
vlim += tbl2[GX_GET_REG(vcdHiReg, GX_CP_VCD_HI_TEX0COORD_ST, GX_CP_VCD_HI_TEX0COORD_END)];
vlim += tbl2[GX_GET_REG(vcdHiReg, GX_CP_VCD_HI_TEX1COORD_ST, GX_CP_VCD_HI_TEX1COORD_END)];
vlim += tbl2[GX_GET_REG(vcdHiReg, GX_CP_VCD_HI_TEX2COORD_ST, GX_CP_VCD_HI_TEX2COORD_END)];
vlim += tbl2[GX_GET_REG(vcdHiReg, GX_CP_VCD_HI_TEX3COORD_ST, GX_CP_VCD_HI_TEX3COORD_END)];
vlim += tbl2[GX_GET_REG(vcdHiReg, GX_CP_VCD_HI_TEX4COORD_ST, GX_CP_VCD_HI_TEX4COORD_END)];
vlim += tbl2[GX_GET_REG(vcdHiReg, GX_CP_VCD_HI_TEX5COORD_ST, GX_CP_VCD_HI_TEX5COORD_END)];
vlim += tbl2[GX_GET_REG(vcdHiReg, GX_CP_VCD_HI_TEX6COORD_ST, GX_CP_VCD_HI_TEX6COORD_END)];
vlim += tbl2[GX_GET_REG(vcdHiReg, GX_CP_VCD_HI_TEX7COORD_ST, GX_CP_VCD_HI_TEX7COORD_END)];
__GXData->vLim = vlim;
}
void GXGetVtxDesc(int param_0, GXAttrType* param_1) {
int local_38;
switch (param_0) {
case 0:
local_38 = __GXData->vcdLo & 1;
break;
case 1:
local_38 = (__GXData->vcdLo & 2) >> 1;
break;
case 2:
local_38 = (__GXData->vcdLo & 4) >> 2;
break;
case 3:
local_38 = (__GXData->vcdLo & 8) >> 3;
break;
case 4:
local_38 = (__GXData->vcdLo & 0x10) >> 4;
break;
case 5:
local_38 = (__GXData->vcdLo & 0x20) >> 5;
break;
case 6:
local_38 = (__GXData->vcdLo & 0x40) >> 6;
break;
case 7:
local_38 = (__GXData->vcdLo & 0x80) >> 7;
break;
case 8:
local_38 = (__GXData->vcdLo & 0x100) >> 8;
break;
case 9:
local_38 = (__GXData->vcdLo & 0x600) >> 9;
break;
case 10:
if (__GXData->hasNrms != 0) {
local_38 = (__GXData->vcdLo & 0x1800) >> 11;
} else {
local_38 = 0;
}
break;
case 0x19:
if (__GXData->hasBiNrms != 0) {
local_38 = (__GXData->vcdLo & 0x1800) >> 11;
} else {
local_38 = 0;
}
break;
case 11:
local_38 = (__GXData->vcdLo & 0x6000) >> 13;
break;
case 12:
local_38 = (__GXData->vcdLo & 0x18000) >> 15;
break;
case 13:
local_38 = (__GXData->vcdHi & 3);
break;
case 14:
local_38 = (__GXData->vcdHi & 0xC) >> 2;
break;
case 15:
local_38 = (__GXData->vcdHi & 0x30) >> 4;
break;
case 16:
local_38 = (__GXData->vcdHi & 0xC0) >> 6;
break;
case 17:
local_38 = (__GXData->vcdHi & 0x300) >> 8;
break;
case 18:
local_38 = (__GXData->vcdHi & 0xC00) >> 10;
break;
case 19:
local_38 = (__GXData->vcdHi & 0x3000) >> 12;
break;
case 20:
local_38 = (__GXData->vcdHi & 0xC000) >> 14;
break;
default:
local_38 = 0;
break;
}
*param_1 = local_38;
}
void GXGetVtxDescv(GXVtxDescList* attrPtr) {
int i;
for (i = 0; i <= 0x14; i++) {
attrPtr[i].attr = (GXAttr)i;
GXGetVtxDesc(i, &attrPtr[i].type);
}
attrPtr[i].attr = (GXAttr)0x19;
GXGetVtxDesc(0x19, &attrPtr[i].type);
i++;
attrPtr[i].attr = (GXAttr)0xFF;
}
void GXClearVtxDesc(void) {
__GXData->vcdLo = 0;
GX_BITFIELD_SET(__GXData->vcdLo, 0x15, 2, GX_DIRECT);
__GXData->vcdHi = 0;
__GXData->hasNrms = FALSE;
__GXData->hasBiNrms = FALSE;
__GXData->dirtyState |= GX_DIRTY_VCD;
}
/* ############################################################################################## */
static inline void SETVAT(u32* vatA, u32* vatB, u32* vatC, GXAttr attr, GXCompCnt compCnt,
GXCompType compType, u8 shift) {
switch (attr) {
case GX_VA_POS:
GX_SET_REG(*vatA, compCnt, GX_CP_VAT_GRP0_POS_CNT_ST, GX_CP_VAT_GRP0_POS_CNT_END);
GX_SET_REG(*vatA, compType, GX_CP_VAT_GRP0_POS_TYPE_ST, GX_CP_VAT_GRP0_POS_TYPE_END);
GX_SET_REG(*vatA, shift, GX_CP_VAT_GRP0_POS_SHIFT_ST, GX_CP_VAT_GRP0_POS_SHIFT_END);
break;
case GX_VA_NRM:
case GX_VA_NBT:
GX_SET_REG(*vatA, compType, GX_CP_VAT_GRP0_NRM_TYPE_ST, GX_CP_VAT_GRP0_NRM_TYPE_END);
if (compCnt == GX_NRM_NBT3) {
// Probably because the compCnt can only be one bit?
GX_SET_REG(*vatA, GX_NRM_NBT, GX_CP_VAT_GRP0_NRM_CNT_ST, GX_CP_VAT_GRP0_NRM_CNT_END);
GX_SET_REG(*vatA, TRUE, GX_CP_VAT_GRP0_NRMIDX3_ST, GX_CP_VAT_GRP0_NRMIDX3_END);
} else {
GX_SET_REG(*vatA, compCnt, GX_CP_VAT_GRP0_NRM_CNT_ST, GX_CP_VAT_GRP0_NRM_CNT_END);
GX_SET_REG(*vatA, FALSE, GX_CP_VAT_GRP0_NRMIDX3_ST, GX_CP_VAT_GRP0_NRMIDX3_END);
}
break;
case GX_VA_CLR0:
GX_SET_REG(*vatA, compCnt, GX_CP_VAT_GRP0_CLRDIFF_CNT_ST, GX_CP_VAT_GRP0_CLRDIFF_CNT_END);
GX_SET_REG(*vatA, compType, GX_CP_VAT_GRP0_CLRDIFF_TYPE_ST,
GX_CP_VAT_GRP0_CLRDIFF_TYPE_END);
break;
case GX_VA_CLR1:
GX_SET_REG(*vatA, compCnt, GX_CP_VAT_GRP0_CLRSPEC_CNT_ST, GX_CP_VAT_GRP0_CLRSPEC_CNT_END);
GX_SET_REG(*vatA, compType, GX_CP_VAT_GRP0_CLRSPEC_TYPE_ST,
GX_CP_VAT_GRP0_CLRSPEC_TYPE_END);
break;
case GX_VA_TEX0:
GX_SET_REG(*vatA, compCnt, GX_CP_VAT_GRP0_TXC0_CNT_ST, GX_CP_VAT_GRP0_TXC0_CNT_END);
GX_SET_REG(*vatA, compType, GX_CP_VAT_GRP0_TXC0_TYPE_ST, GX_CP_VAT_GRP0_TXC0_TYPE_END);
GX_SET_REG(*vatA, shift, GX_CP_VAT_GRP0_TXC0_SHIFT_ST, GX_CP_VAT_GRP0_TXC0_SHIFT_END);
break;
case GX_VA_TEX1:
GX_SET_REG(*vatB, compCnt, GX_CP_VAT_GRP1_TXC1_CNT_ST, GX_CP_VAT_GRP1_TXC1_CNT_END);
GX_SET_REG(*vatB, compType, GX_CP_VAT_GRP1_TXC1_TYPE_ST, GX_CP_VAT_GRP1_TXC1_TYPE_END);
GX_SET_REG(*vatB, shift, GX_CP_VAT_GRP1_TXC1_SHIFT_ST, GX_CP_VAT_GRP1_TXC1_SHIFT_END);
break;
case GX_VA_TEX2:
GX_SET_REG(*vatB, compCnt, GX_CP_VAT_GRP1_TXC2_CNT_ST, GX_CP_VAT_GRP1_TXC2_CNT_END);
GX_SET_REG(*vatB, compType, GX_CP_VAT_GRP1_TXC2_TYPE_ST, GX_CP_VAT_GRP1_TXC2_TYPE_END);
GX_SET_REG(*vatB, shift, GX_CP_VAT_GRP1_TXC2_SHIFT_ST, GX_CP_VAT_GRP1_TXC2_SHIFT_END);
break;
case GX_VA_TEX3:
GX_SET_REG(*vatB, compCnt, GX_CP_VAT_GRP1_TXC3_CNT_ST, GX_CP_VAT_GRP1_TXC3_CNT_END);
GX_SET_REG(*vatB, compType, GX_CP_VAT_GRP1_TXC3_TYPE_ST, GX_CP_VAT_GRP1_TXC3_TYPE_END);
GX_SET_REG(*vatB, shift, GX_CP_VAT_GRP1_TXC3_SHIFT_ST, GX_CP_VAT_GRP1_TXC3_SHIFT_END);
break;
case GX_VA_TEX4:
GX_SET_REG(*vatB, compCnt, GX_CP_VAT_GRP1_TXC4_CNT_ST, GX_CP_VAT_GRP1_TXC4_CNT_END);
GX_SET_REG(*vatB, compType, GX_CP_VAT_GRP1_TXC4_TYPE_ST, GX_CP_VAT_GRP1_TXC4_TYPE_END);
GX_SET_REG(*vatC, shift, GX_CP_VAT_GRP2_TXC4_SHIFT_ST, GX_CP_VAT_GRP2_TXC4_SHIFT_END);
break;
case GX_VA_TEX5:
GX_SET_REG(*vatC, compCnt, GX_CP_VAT_GRP2_TXC5_CNT_ST, GX_CP_VAT_GRP2_TXC5_CNT_END);
GX_SET_REG(*vatC, compType, GX_CP_VAT_GRP2_TXC5_TYPE_ST, GX_CP_VAT_GRP2_TXC5_TYPE_END);
GX_SET_REG(*vatC, shift, GX_CP_VAT_GRP2_TXC5_SHIFT_ST, GX_CP_VAT_GRP2_TXC5_SHIFT_END);
break;
case GX_VA_TEX6:
GX_SET_REG(*vatC, compCnt, GX_CP_VAT_GRP2_TXC6_CNT_ST, GX_CP_VAT_GRP2_TXC6_CNT_END);
GX_SET_REG(*vatC, compType, GX_CP_VAT_GRP2_TXC6_TYPE_ST, GX_CP_VAT_GRP2_TXC6_TYPE_END);
GX_SET_REG(*vatC, shift, GX_CP_VAT_GRP2_TXC6_SHIFT_ST, GX_CP_VAT_GRP2_TXC6_SHIFT_END);
break;
case GX_VA_TEX7:
GX_SET_REG(*vatC, compCnt, GX_CP_VAT_GRP2_TXC7_CNT_ST, GX_CP_VAT_GRP2_TXC7_CNT_END);
GX_SET_REG(*vatC, compType, GX_CP_VAT_GRP2_TXC7_TYPE_ST, GX_CP_VAT_GRP2_TXC7_TYPE_END);
GX_SET_REG(*vatC, shift, GX_CP_VAT_GRP2_TXC7_SHIFT_ST, GX_CP_VAT_GRP2_TXC7_SHIFT_END);
break;
}
}
void GXSetVtxAttrFmt(GXVtxFmt format, GXAttr attr, GXCompCnt count, GXCompType type, u8 frac) {
u32* vA = (u32*)&__GXData->vatA[format];
u32* vB = (u32*)&__GXData->vatB[format];
u32* vC = &__GXData->vatC[format];
SETVAT(vA, vB, vC, attr, count, type, frac);
__GXData->dirtyState |= GX_DIRTY_VAT;
__GXData->dirtyVAT |= (u8)(1 << (u8)format);
}
void GXSetVtxAttrFmtv(GXVtxFmt format, GXVtxAttrFmtList* list) {
u32* vatA;
u32* vatB;
u32* vatC;
vatA = (u32*)&__GXData->vatA[format];
vatB = (u32*)&__GXData->vatB[format];
vatC = &__GXData->vatC[format];
for (; list->mAttrib != GX_VA_NULL; list++) {
SETVAT(vatA, vatB, vatC, list->mAttrib, list->mCompCnt, list->mCompType, list->mCompShift);
}
__GXData->dirtyState |= GX_DIRTY_VAT;
__GXData->dirtyVAT |= (u8)(1 << (u8)format);
}
void __GXSetVAT(void) {
u32 i = 0;
u32 dirtyVAT = __GXData->dirtyVAT;
do {
if (dirtyVAT & (1)) {
GX_CP_LOAD_REG(GX_CP_REG_VAT_GRP0 | i, __GXData->vatA[i]);
GX_CP_LOAD_REG(GX_CP_REG_VAT_GRP1 | i, __GXData->vatB[i]);
GX_CP_LOAD_REG(GX_CP_REG_VAT_GRP2 | i, __GXData->vatC[i]);
}
dirtyVAT >>= 1;
i++;
} while (dirtyVAT != 0);
__GXData->dirtyVAT = 0;
}
static u8 GetFracForNrm(int param_0) {
int var_r31;
switch (param_0) {
case 1:
var_r31 = 6;
break;
case 3:
var_r31 = 14;
break;
default:
case 2:
var_r31 = 0;
break;
}
return var_r31;
}
void GXGetVtxAttrFmtv(GXVtxFmt param_0, GXVtxAttrFmtList* param_1) {
s32 tmp;
s32 tmp2;
s32 tmp3;
int i;
#ifdef DEBUG
// not fully matching
/* tmp = 1;
if (data_8074d3c8 != 0) {
OSPanic("GXAttr.c", 941, "\'GXGetVtxAttrFmtv\' is not allowed between GXBegin/GXEnd");
tmp = 0;
}
tmp2 = 1;
if (param_1 == NULL) {
OSPanic("GXAttr.c", 942, "GXSetVtxAttrFmt: list pointer is NULL");
tmp2 = 0;
}
tmp3 = 1;
if (param_0 >= 8) {
OSPanic("GXAttr.c", 943, "GXSetVtxAttrFmt: Format Index is out of range");
tmp3 = 0;
} */
#endif
for (i = 9; i <= 0x14; i++) {
param_1->mAttrib = i;
GXGetVtxAttrFmt(param_0, i, &param_1->mCompCnt, &param_1->mCompType, &param_1->mCompShift);
param_1++;
}
param_1->mAttrib = 0xFF;
}
void GXGetVtxAttrFmt(GXVtxFmt param_0, int param_1, GXCompCnt* param_2, GXCompType* param_3,
u8* param_4) {
s32 tmp;
s32 tmp2;
GXCompCnt* tmp_1;
GXCompCnt* tmp_2;
u32* tmp_3;
#ifdef DEBUG
// not fully matching
/* tmp = 1;
if (data_8074d3c8) {
OSPanic("GXAttr.c", 844, "\'GXGetVtxAttrFmt\' is not allowed between GXBegin/GXEnd");
tmp = 0;
}
tmp2 = 1;
if (param_0 >= 8) {
OSPanic("GXAttr.c", 845, "GXSetVtxAttrFmt: Format Index is out of range");
tmp2 = 0;
} */
#endif
tmp_1 = (GXCompCnt*)&__GXData->vatA[param_0];
tmp_2 = (GXCompCnt*)&__GXData->vatB[param_0];
tmp_3 = &__GXData->vatC[param_0];
switch (param_1) {
case 9:
*param_2 = *tmp_1 & 1;
*param_3 = (*tmp_1 & 0xE) >> 1;
*param_4 = (*tmp_1 & 0x1F0) >> 4;
break;
case 10:
case 0x19:
*param_2 = (*tmp_1 & 0x200) >> 9;
if (*param_2 == 1 && ((*tmp_1 & 0x80000000) >> 31) != 0) {
*param_2 = 2;
}
*param_3 = (*tmp_1 & 0x1C00) >> 10;
*param_4 = GetFracForNrm(*param_3);
break;
case 11:
*param_2 = (*tmp_1 & 0x2000) >> 0xd;
*param_3 = (*tmp_1 & 0x1C000) >> 0xe;
*param_4 = 0;
break;
case 12:
*param_2 = (*tmp_1 & 0x20000) >> 0x11;
*param_3 = (*tmp_1 & 0x1C0000) >> 0x12;
*param_4 = 0;
break;
case 13:
*param_2 = (*tmp_1 & 0x200000) >> 0x15;
*param_3 = (*tmp_1 & 0x1C00000) >> 0x16;
*param_4 = ((*tmp_1 & 0x3e000000)) >> 25;
break;
case 14:
*param_2 = *tmp_2 & 1;
*param_3 = (*tmp_2 & 0xE) >> 1;
*param_4 = (*tmp_2 & 0x1F0) >> 4;
break;
case 15:
*param_2 = (*tmp_2 & 0x200) >> 9;
*param_3 = (*tmp_2 & 0x1C00) >> 10;
*param_4 = (*tmp_2 & 0x3E000) >> 13;
break;
case 16:
*param_2 = (*tmp_2 & 0x40000) >> 0x12;
*param_3 = (*tmp_2 & 0x380000) >> 0x13;
*param_4 = (*tmp_2 & 0x7C00000) >> 0x16;
break;
case 17:
*param_2 = (*tmp_2 & 0x8000000) >> 0x1B;
*param_3 = (*tmp_2 & 0x70000000) >> 0x1C;
*param_4 = (*tmp_3 & 0x1F);
break;
case 18:
*param_2 = (*tmp_3 & 0x20) >> 5;
*param_3 = (*tmp_3 & 0x1C0) >> 6;
*param_4 = (*tmp_3 & 0x3E00) >> 9;
break;
case 19:
*param_2 = (*tmp_3 & 0x4000) >> 0xe;
*param_3 = (*tmp_3 & 0x38000) >> 0xf;
*param_4 = (*tmp_3 & 0x7c0000) >> 0x12;
break;
case 20:
*param_2 = (*tmp_3 & 0x800000) >> 0x17;
*param_3 = (*tmp_3 & 0x7000000) >> 0x18;
*param_4 = (*tmp_3 & 0xF8000000) >> 0x1b;
break;
default:
*param_2 = 1;
*param_3 = 0;
*param_4 = 0;
}
}
void GXSetArray(GXAttr attr, void* basePtr, u8 stride) {
s32 newAttr;
s32 attrReg;
newAttr = attr;
if (newAttr == GX_VA_NBT) {
newAttr = GX_VA_NRM;
}
attrReg = newAttr - GX_VA_POS;
GX_CP_LOAD_REG(GX_BP_REG_SETMODE0_TEX4 | attrReg,
// Address -> offset?
(u32)basePtr & ~0xC0000000);
GX_CP_LOAD_REG(GX_BP_REG_SETIMAGE2_TEX4 | attrReg, stride);
}
void GXInvalidateVtxCache(void) {
GXFIFO.u8 = GX_FIFO_CMD_INVAL_VTX;
}
void GXSetTexCoordGen2(GXTexCoordID id, GXTexGenType type, GXTexGenSrc src, u32 texMtxIdx,
GXBool normalize, u32 dualTexMtxIdx) {
u32 reg;
u32 inputRow;
GXXfTexReg inputForm;
reg = 0;
inputForm = GX_XF_TEX_FORM_AB11;
inputRow = 5;
switch (src) {
case GX_TG_POS:
inputRow = 0;
inputForm = GX_XF_TEX_FORM_ABC1;
break;
case GX_TG_NRM:
inputRow = 1;
inputForm = GX_XF_TEX_FORM_ABC1;
break;
case GX_TG_BINRM:
inputRow = 3;
inputForm = GX_XF_TEX_FORM_ABC1;
break;
case GX_TG_TANGENT:
inputRow = 4;
inputForm = GX_XF_TEX_FORM_ABC1;
break;
case GX_TG_COLOR0:
inputRow = 2;
break;
case GX_TG_COLOR1:
inputRow = 2;
break;
case GX_TG_TEX0:
inputRow = 5;
break;
case GX_TG_TEX1:
inputRow = 6;
break;
case GX_TG_TEX2:
inputRow = 7;
break;
case GX_TG_TEX3:
inputRow = 8;
break;
case GX_TG_TEX4:
inputRow = 9;
break;
case GX_TG_TEX5:
inputRow = 10;
break;
case GX_TG_TEX6:
inputRow = 11;
break;
case GX_TG_TEX7:
inputRow = 12;
break;
}
switch (type) {
case GX_TG_NRM:
GX_SET_REG(reg, GX_XF_TEX_PROJ_ST, GX_XF_TEX_PROJTYPE_ST,
GX_XF_TEX_PROJTYPE_END); // 2x4 projection
GX_SET_REG(reg, inputForm, GX_XF_TEX_INPUTFORM_ST, GX_XF_TEX_INPUTFORM_END);
GX_SET_REG(reg, GX_TG_POS, GX_XF_TEX_TEXGENTYPE_ST, GX_XF_TEX_TEXGENTYPE_END);
GX_SET_REG(reg, inputRow, GX_XF_TEX_SRCROW_ST, GX_XF_TEX_SRCROW_END);
break;
case GX_TG_POS:
GX_SET_REG(reg, GX_XF_TEX_PROJ_STQ, GX_XF_TEX_PROJTYPE_ST,
GX_XF_TEX_PROJTYPE_END); // 3x4 projection
GX_SET_REG(reg, inputForm, GX_XF_TEX_INPUTFORM_ST, GX_XF_TEX_INPUTFORM_END);
GX_SET_REG(reg, GX_TG_POS, GX_XF_TEX_TEXGENTYPE_ST, GX_XF_TEX_TEXGENTYPE_END);
GX_SET_REG(reg, inputRow, GX_XF_TEX_SRCROW_ST, GX_XF_TEX_SRCROW_END);
break;
case GX_TG_BUMP0:
case GX_TG_BUMP1:
case GX_TG_BUMP2:
case GX_TG_BUMP3:
case GX_TG_BUMP4:
case GX_TG_BUMP5:
case GX_TG_BUMP6:
case GX_TG_BUMP7:
GX_SET_REG(reg, GX_XF_TEX_PROJ_ST, GX_XF_TEX_PROJTYPE_ST,
GX_XF_TEX_PROJTYPE_END); // 2x4 projection
GX_SET_REG(reg, inputForm, GX_XF_TEX_INPUTFORM_ST, GX_XF_TEX_INPUTFORM_END);
GX_SET_REG(reg, GX_TG_NRM, GX_XF_TEX_TEXGENTYPE_ST, GX_XF_TEX_TEXGENTYPE_END);
GX_SET_REG(reg, inputRow, GX_XF_TEX_SRCROW_ST, GX_XF_TEX_SRCROW_END);
GX_SET_REG(reg, src - GX_TG_TEXCOORD0, GX_XF_TEX_BUMPSRCTEX_ST, GX_XF_TEX_BUMPSRCTEX_END);
GX_SET_REG(reg, type - GX_TG_BUMP0, GX_XF_TEX_BUMPSRCLIGHT_ST, GX_XF_TEX_BUMPSRCLIGHT_END);
break;
case GX_TG_SRTG:
GX_SET_REG(reg, GX_XF_TEX_PROJ_ST, GX_XF_TEX_PROJTYPE_ST,
GX_XF_TEX_PROJTYPE_END); // 2x4 projection
GX_SET_REG(reg, inputForm, GX_XF_TEX_INPUTFORM_ST, GX_XF_TEX_INPUTFORM_END);
if (src == GX_TG_COLOR0) {
GX_SET_REG(reg, GX_XF_TG_CLR0, GX_XF_TEX_TEXGENTYPE_ST, GX_XF_TEX_TEXGENTYPE_END);
} else {
GX_SET_REG(reg, GX_XF_TG_CLR1, GX_XF_TEX_TEXGENTYPE_ST, GX_XF_TEX_TEXGENTYPE_END);
}
GX_SET_REG(reg, 2, GX_XF_TEX_SRCROW_ST, GX_XF_TEX_SRCROW_END);
break;
default:
break;
}
GX_XF_LOAD_REG(GX_XF_REG_TEX0 + id, reg);
reg = 0;
GX_SET_REG(reg, dualTexMtxIdx - 0x40, GX_XF_MTXIDX0_GEOM_ST, GX_XF_MTXIDX0_GEOM_END);
GX_SET_REG(reg, normalize, GX_XF_DUALTEX_NORMALISE_ST, GX_XF_DUALTEX_NORMALISE_END);
GX_XF_LOAD_REG(GX_XF_REG_DUALTEX0 + id, reg);
switch (id) {
case GX_TEXCOORD0:
GX_SET_REG(__GXData->matIdxA, texMtxIdx, GX_XF_MTXIDX0_TEX0_ST, GX_XF_MTXIDX0_TEX0_END);
break;
case GX_TEXCOORD1:
GX_SET_REG(__GXData->matIdxA, texMtxIdx, GX_XF_MTXIDX0_TEX1_ST, GX_XF_MTXIDX0_TEX1_END);
break;
case GX_TEXCOORD2:
GX_SET_REG(__GXData->matIdxA, texMtxIdx, GX_XF_MTXIDX0_TEX2_ST, GX_XF_MTXIDX0_TEX2_END);
break;
case GX_TEXCOORD3:
GX_SET_REG(__GXData->matIdxA, texMtxIdx, GX_XF_MTXIDX0_TEX3_ST, GX_XF_MTXIDX0_TEX3_END);
break;
case GX_TEXCOORD4:
GX_SET_REG(__GXData->matIdxB, texMtxIdx, GX_XF_MTXIDX1_TEX4_ST, GX_XF_MTXIDX1_TEX4_END);
break;
case GX_TEXCOORD5:
GX_SET_REG(__GXData->matIdxB, texMtxIdx, GX_XF_MTXIDX1_TEX5_ST, GX_XF_MTXIDX1_TEX5_END);
break;
case GX_TEXCOORD6:
GX_SET_REG(__GXData->matIdxB, texMtxIdx, GX_XF_MTXIDX1_TEX6_ST, GX_XF_MTXIDX1_TEX6_END);
break;
default:
GX_SET_REG(__GXData->matIdxB, texMtxIdx, GX_XF_MTXIDX1_TEX7_ST, GX_XF_MTXIDX1_TEX7_END);
break;
}
__GXSetMatrixIndex(id + 1);
}
void GXSetNumTexGens(u8 count) {
GX_SET_REG(__GXData->genMode, count, GX_BP_GENMODE_NUMTEX_ST, GX_BP_GENMODE_NUMTEX_END);
GX_XF_LOAD_REG(GX_XF_REG_NUMTEX, count);
__GXData->dirtyState |= GX_DIRTY_GEN_MODE;
}

194
src/dolphin/gx/GXBump.c Normal file
View File

@ -0,0 +1,194 @@
/**
* GXBump.c
* Description:
*/
#include "dolphin/gx/GXBump.h"
#include "dolphin/gx/GX.h"
void GXSetTevIndirect(GXTevStageID tevStage, GXIndTexStageID texStage, GXIndTexFormat texFmt,
GXIndTexBiasSel biasSel, GXIndTexMtxID mtxID, GXIndTexWrap wrapS,
GXIndTexWrap wrapT, u8 addPrev, u8 utcLod, GXIndTexAlphaSel alphaSel) {
u32 field = 0;
u32 stage = tevStage + 0x10;
GX_BITFIELD_SET(field, 30, 2, texStage);
GX_BITFIELD_SET(field, 28, 2, texFmt);
GX_BITFIELD_SET(field, 25, 3, biasSel);
GX_BITFIELD_SET(field, 23, 2, alphaSel);
GX_BITFIELD_SET(field, 19, 4, mtxID);
GX_BITFIELD_SET(field, 16, 3, wrapS);
GX_BITFIELD_SET(field, 13, 3, wrapT);
GX_BITFIELD_SET(field, 12, 1, utcLod);
GX_BITFIELD_SET(field, 11, 1, addPrev);
GX_BITFIELD_SET(field, 0, 8, stage);
GXFIFO.u8 = 0x61;
GXFIFO.s32 = field;
__GXData->bpSentNot = 0;
}
void GXSetIndTexMtx(GXIndTexMtxID mtxID, f32 offset[6], s8 scale_exp) {
u32 val;
u32 field;
f32 mtx2[6];
scale_exp += 17;
switch (mtxID) {
case GX_ITM_0:
case GX_ITM_1:
case GX_ITM_2:
val = mtxID - 1;
break;
case GX_ITM_S0:
case GX_ITM_S1:
case GX_ITM_S2:
val = mtxID - 5;
break;
case GX_ITM_T0:
case GX_ITM_T1:
case GX_ITM_T2:
val = mtxID - 9;
break;
case GX_ITM_3:
case GX_ITM_S3:
default:
val = 0;
}
field = 0;
GX_BITFIELD_SET(field, 21, 11, 1024.0f * offset[0]);
GX_BITFIELD_SET(field, 10, 11, 1024.0f * offset[3]);
GX_BITFIELD_SET(field, 8, 2, (scale_exp >> 0) & 3);
GX_BITFIELD_SET(field, 0, 8, val * 3 + 6);
GXFIFO.u8 = 0x61;
GXFIFO.s32 = field;
field = 0;
GX_BITFIELD_SET(field, 21, 11, 1024.0f * offset[1]);
GX_BITFIELD_SET(field, 10, 11, 1024.0f * offset[4]);
GX_BITFIELD_SET(field, 8, 2, (scale_exp >> 2) & 3);
GX_BITFIELD_SET(field, 0, 8, val * 3 + 7);
GXFIFO.u8 = 0x61;
GXFIFO.s32 = field;
field = 0;
GX_BITFIELD_SET(field, 21, 11, 1024.0f * offset[2]);
GX_BITFIELD_SET(field, 10, 11, 1024.0f * offset[5]);
GX_BITFIELD_SET(field, 8, 2, (scale_exp >> 4) & 3);
GX_BITFIELD_SET(field, 0, 8, val * 3 + 8);
GXFIFO.u8 = 0x61;
GXFIFO.s32 = field;
__GXData->bpSentNot = 0;
}
void GXSetIndTexCoordScale(GXIndTexStageID texStage, GXIndTexScale scaleS, GXIndTexScale scaleT) {
GXData* data;
switch (texStage) {
case GX_INDTEXSTAGE0:
data = __GXData;
GX_BITFIELD_SET(data->IndTexScale0, 28, 4, scaleS);
GX_BITFIELD_SET(data->IndTexScale0, 24, 4, scaleT);
GX_BITFIELD_SET(data->IndTexScale0, 0, 8, 0x25);
GXFIFO.u8 = 0x61;
GXFIFO.s32 = data->IndTexScale0;
break;
case GX_INDTEXSTAGE1:
data = __GXData;
GX_BITFIELD_SET(data->IndTexScale0, 20, 4, scaleS);
GX_BITFIELD_SET(data->IndTexScale0, 16, 4, scaleT);
GX_BITFIELD_SET(data->IndTexScale0, 0, 8, 0x25);
GXFIFO.u8 = 0x61;
GXFIFO.s32 = data->IndTexScale0;
break;
case GX_INDTEXSTAGE2:
data = __GXData;
GX_BITFIELD_SET(data->IndTexScale1, 28, 4, scaleS);
GX_BITFIELD_SET(data->IndTexScale1, 24, 4, scaleT);
GX_BITFIELD_SET(data->IndTexScale1, 0, 8, 0x26);
GXFIFO.u8 = 0x61;
GXFIFO.s32 = data->IndTexScale1;
break;
case GX_INDTEXSTAGE3:
data = __GXData;
GX_BITFIELD_SET(data->IndTexScale1, 20, 4, scaleS);
GX_BITFIELD_SET(data->IndTexScale1, 16, 4, scaleT);
GX_BITFIELD_SET(data->IndTexScale1, 0, 8, 0x26);
GXFIFO.u8 = 0x61;
GXFIFO.s32 = data->IndTexScale1;
break;
}
__GXData->bpSentNot = 0;
}
void GXSetIndTexOrder(GXIndTexStageID stage, GXTexCoordID coord, GXTexMapID map) {
GXData* data;
if (map == 0xFF) {
map = GX_TEXMAP0;
}
if (coord == 0xFF) {
coord = GX_TEXCOORD0;
}
switch (stage) {
case GX_INDTEXSTAGE0:
data = __GXData;
GX_BITFIELD_SET(data->iref, 29, 3, map);
GX_BITFIELD_SET(data->iref, 26, 3, coord);
break;
case GX_INDTEXSTAGE1:
data = __GXData;
GX_BITFIELD_SET(data->iref, 23, 3, map);
GX_BITFIELD_SET(data->iref, 20, 3, coord);
break;
case GX_INDTEXSTAGE2:
data = __GXData;
GX_BITFIELD_SET(data->iref, 17, 3, map);
GX_BITFIELD_SET(data->iref, 14, 3, coord);
break;
case GX_INDTEXSTAGE3:
data = __GXData;
GX_BITFIELD_SET(data->iref, 11, 3, map);
GX_BITFIELD_SET(data->iref, 8, 3, coord);
break;
}
GXFIFO.u8 = 0x61;
GXFIFO.s32 = __GXData->iref;
GXSetWasteFlags();
}
void GXSetNumIndStages(u8 num) {
GXData* data = __GXData;
GX_BITFIELD_SET(data->genMode, 13, 3, num);
data->dirtyState |= GX_DIRTY_BP_MASK | GX_DIRTY_GEN_MODE;
}
void GXSetTevDirect(GXTevStageID stage) {
GXSetTevIndirect(stage, GX_INDTEXSTAGE0, GX_ITF_8, GX_ITB_NONE, GX_ITM_OFF, GX_ITW_OFF,
GX_ITW_OFF, FALSE, FALSE, GX_ITBA_OFF);
}
void __GXUpdateBPMask(void) {}
void __GXSetIndirectMask(u32 mask) {
GXData* data = __GXData;
GX_BITFIELD_SET(data->bpMask, 24, 8, mask);
GXFIFO.u8 = 0x61;
GXFIFO.s32 = data->bpMask;
data->bpSentNot = 0;
}
void __GXFlushTextureState(void) {
GXFIFO.u8 = 0x61;
GXFIFO.s32 = __GXData->bpMask;
__GXData->bpSentNot = 0;
}

View File

@ -0,0 +1,21 @@
/**
* GXDisplayList.c
* Description:
*/
#include "dolphin/gx/GXDisplayList.h"
#include "dolphin/gx/GX.h"
void GXCallDisplayList(void* list, u32 nbytes) {
if (__GXData->dirtyState != 0) {
__GXSetDirtyState();
}
if (*(u32*)__GXData == 0) {
__GXSendFlushPrim();
}
GXFIFO.u8 = 0x40;
GXFIFO.u32 = (u32)list;
GXFIFO.u32 = nbytes;
}

71
src/dolphin/gx/GXDraw.c Normal file
View File

@ -0,0 +1,71 @@
#include "dolphin/gx/GXDraw.h"
#include "dolphin/gx/GX.h"
static GXVtxDescList vcd[27];
static GXVtxAttrFmtList vat[27];
void GetVertState(void) {
GXGetVtxDescv(vcd);
GXGetVtxAttrFmtv(GX_VTXFMT3, vat);
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_NRM, GX_DIRECT);
GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
}
void RestoreVertState(void) {
GXSetVtxDescv(vcd);
GXSetVtxAttrFmtv(GX_VTXFMT3, vat);
}
// doesn't fully match debug
void GXDrawCylinder(u8 numEdges) {
f32 temp_f29;
f32 temp_f30;
f32 temp_f31;
s32 i;
f32 sp1A0[100];
f32 sp10[100];
temp_f31 = 1.0f;
temp_f30 = -temp_f31;
GetVertState();
for (i = 0; i <= numEdges; i++) {
temp_f29 = (i * 2.0f * 3.141593f) / numEdges;
sp1A0[i] = cosf(temp_f29);
sp10[i] = sinf(temp_f29);
}
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT3, (numEdges + 1) * 2);
for (i = 0; i <= numEdges; i++) {
GXPosition3f32(sp1A0[i], sp10[i], temp_f30);
GXNormal3f32(sp1A0[i], sp10[i], 0.0f);
GXPosition3f32(sp1A0[i], sp10[i], temp_f31);
GXNormal3f32(sp1A0[i], sp10[i], 0.0f);
}
GXEnd();
GXBegin(GX_TRIANGLEFAN, GX_VTXFMT3, numEdges + 2);
GXPosition3f32(0.0f, 0.0f, temp_f31);
GXNormal3f32(0.0f, 0.0f, 1.0f);
for (i = 0; i <= numEdges; i++) {
GXPosition3f32(sp1A0[i], -sp10[i], temp_f31);
GXNormal3f32(0.0f, 0.0f, 1.0f);
}
GXEnd();
GXBegin(GX_TRIANGLEFAN, GX_VTXFMT3, numEdges + 2);
GXPosition3f32(0.0f, 0.0f, temp_f30);
GXNormal3f32(0.0f, 0.0f, -1.0f);
for (i = 0; i <= numEdges; i++) {
GXPosition3f32(sp1A0[i], sp10[i], temp_f30);
GXNormal3f32(0.0f, 0.0f, -1.0f);
}
GXEnd();
RestoreVertState();
}

337
src/dolphin/gx/GXFifo.c Normal file
View File

@ -0,0 +1,337 @@
#include "dolphin/gx/GXFifo.h"
#include "dolphin/gx/GX.h"
#include "dolphin/os/OS.h"
static void GXInitFifoLimits(GXFifoObj* fifo, u32 hi_watermark, u32 lo_watermark);
static GXFifoObj* CPUFifo;
static GXFifoObj* GPFifo;
static OSThread* __GXCurrentThread;
static GXBool data_80451954;
static u32 GXOverflowSuspendInProgress;
static GXBreakPtCallback BreakPointCB;
static u32 __GXOverflowCount;
static void GXOverflowHandler() {
__GXOverflowCount += 1;
__GXWriteFifoIntEnable(0, 1);
__GXWriteFifoIntReset(1, 0);
GXOverflowSuspendInProgress = TRUE;
OSSuspendThread(__GXCurrentThread);
}
static void GXUnderflowHandler() {
OSResumeThread(__GXCurrentThread);
GXOverflowSuspendInProgress = FALSE;
__GXWriteFifoIntReset(1, 1);
__GXWriteFifoIntEnable(1, 0);
}
static void GXBreakPointHandler(OSContext* context) {
OSContext bpContext;
FAST_FLAG_SET(__GXData->cpEnable, 0, 5, 1);
GX_SET_CP_REG(1, __GXData->cpEnable);
if (BreakPointCB) {
OSClearContext(&bpContext);
OSSetCurrentContext(&bpContext);
BreakPointCB();
OSClearContext(&bpContext);
OSSetCurrentContext(context);
}
}
static void GXCPInterruptHandler(s16 p1, OSContext* context) {
__GXData->cpStatus = GX_GET_CP_REG(0);
if ((__GXData->cpEnable >> 3 & 1) && (__GXData->cpStatus >> 1 & 1)) {
GXUnderflowHandler();
}
if ((__GXData->cpEnable >> 2 & 1) && (__GXData->cpStatus >> 0 & 1)) {
GXOverflowHandler();
}
if ((__GXData->cpEnable >> 5 & 1) && (__GXData->cpStatus >> 4 & 1)) {
GXBreakPointHandler(context);
}
}
void GXInitFifoBase(GXFifoObj* fifo, void* base, u32 size) {
fifo->base = base;
fifo->end = (void*)((u32)base + size - 4);
fifo->size = size;
fifo->rw_dst = 0;
GXInitFifoLimits(fifo, size - 0x4000, OSRoundDown32B(size / 2));
GXInitFifoPtrs(fifo, base, base);
}
void GXInitFifoPtrs(GXFifoObj* fifo, void* readPtr, void* writePtr) {
int interrupts = OSDisableInterrupts();
fifo->read_ptr = readPtr;
fifo->write_ptr = writePtr;
fifo->rw_dst = (u32)writePtr - (u32)readPtr;
if (fifo->rw_dst < 0) {
fifo->rw_dst += fifo->size;
}
OSRestoreInterrupts(interrupts);
}
static void GXInitFifoLimits(GXFifoObj* fifo, u32 hi_watermark, u32 lo_watermark) {
fifo->high_wtrmark = hi_watermark;
fifo->low_wtrmark = lo_watermark;
}
void GXSetCPUFifo(GXFifoObj* fifo) {
BOOL interrupts;
interrupts = OSDisableInterrupts();
CPUFifo = fifo;
if (fifo == GPFifo) {
u32 reg;
GX_SET_PI_REG(3, (u32)fifo->base & 0x3FFFFFFF);
GX_SET_PI_REG(4, (u32)fifo->end & 0x3FFFFFFF);
reg = 0;
GX_BITFIELD_SET(reg, 6, 21, (u32)fifo->write_ptr >> 5);
GX_BITFIELD_SET(reg, 5, 1, 0);
GX_SET_PI_REG(5, reg);
data_80451954 = GX_TRUE;
__GXWriteFifoIntReset(1, 1);
__GXWriteFifoIntEnable(1, 0);
__GXFifoLink(1);
} else {
u32 reg;
if (data_80451954) {
__GXFifoLink(0);
data_80451954 = GX_FALSE;
}
__GXWriteFifoIntEnable(0, 0);
GX_SET_PI_REG(3, (u32)fifo->base & 0x3FFFFFFF);
GX_SET_PI_REG(4, (u32)fifo->end & 0x3FFFFFFF);
reg = 0;
GX_BITFIELD_SET(reg, 6, 21, (u32)fifo->write_ptr >> 5);
GX_BITFIELD_SET(reg, 5, 1, 0);
GX_SET_PI_REG(5, reg);
}
PPCSync();
OSRestoreInterrupts(interrupts);
}
void GXSetGPFifo(GXFifoObj* fifo) {
int interrupts = OSDisableInterrupts();
u32 reg;
__GXFifoReadDisable();
__GXWriteFifoIntEnable(0, 0);
GPFifo = fifo;
GX_SET_CP_REG(16, (u16)fifo->base);
GX_SET_CP_REG(18, (u16)fifo->end);
GX_SET_CP_REG(24, (u16)fifo->rw_dst);
GX_SET_CP_REG(26, (u16)fifo->write_ptr);
GX_SET_CP_REG(28, (u16)fifo->read_ptr);
GX_SET_CP_REG(20, (u16)fifo->high_wtrmark);
GX_SET_CP_REG(22, (u16)fifo->low_wtrmark);
GX_SET_CP_REG(17, ((u32)fifo->base & 0x3FFFFFFF) >> 16);
GX_SET_CP_REG(19, ((u32)fifo->end & 0x3FFFFFFF) >> 16);
GX_SET_CP_REG(25, (fifo->rw_dst) >> 16);
GX_SET_CP_REG(27, ((u32)fifo->write_ptr & 0x3FFFFFFF) >> 16);
GX_SET_CP_REG(29, ((u32)fifo->read_ptr & 0x3FFFFFFF) >> 16);
GX_SET_CP_REG(21, (fifo->high_wtrmark) >> 16);
GX_SET_CP_REG(23, (fifo->low_wtrmark) >> 16);
PPCSync();
if (CPUFifo == GPFifo) {
data_80451954 = 1;
__GXWriteFifoIntEnable(1, 0);
__GXFifoLink(1);
} else {
data_80451954 = 0;
__GXWriteFifoIntEnable(0, 0);
__GXFifoLink(0);
}
reg = __GXData->cpEnable;
GX_BITFIELD_SET(reg, 0x1e, 1, 0);
GX_BITFIELD_SET(reg, 0x1a, 1, 0);
GX_SET_CP_REG(1, reg);
GX_SET_CP_REG(1, __GXData->cpEnable);
__GXWriteFifoIntReset(1, 1);
__GXFifoReadEnable();
OSRestoreInterrupts(interrupts);
}
void GXSaveCPUFifo(GXFifoObj* fifo) {
GXFlush();
__GXSaveCPUFifoAux(fifo);
}
void __GXSaveCPUFifoAux(GXFifoObj* fifo) {
int interrupts = OSDisableInterrupts();
fifo->base = OSPhysicalToCached(GX_GET_PI_REG(3));
fifo->end = OSPhysicalToCached(GX_GET_PI_REG(4));
fifo->write_ptr = OSPhysicalToCached(GX_GET_PI_REG(5) & ~0x4000000);
if (data_80451954 != 0) {
u32 reg2 = GX_GET_CP_REG(28) | (GX_GET_CP_REG(29) << 16);
fifo->read_ptr = (void*)(reg2 + -0x80000000);
fifo->rw_dst = (((u32)GX_GET_CP_REG(24) | (GX_GET_CP_REG(25) << 16)));
} else {
fifo->rw_dst = (u32)fifo->write_ptr - (u32)fifo->read_ptr;
if (fifo->rw_dst < 0) {
fifo->rw_dst += fifo->size;
}
}
OSRestoreInterrupts(interrupts);
}
void GXGetGPStatus(GXBool* overhi, GXBool* underlow, GXBool* readIdle, GXBool* cmdIdle,
GXBool* brkpt) {
__GXData->cpStatus = GX_GET_CP_REG(0);
*overhi = __GXData->cpStatus & 1;
*underlow = (__GXData->cpStatus >> 1) & 1;
*readIdle = (__GXData->cpStatus >> 2) & 1;
*cmdIdle = (__GXData->cpStatus >> 3) & 1;
*brkpt = (__GXData->cpStatus >> 4) & 1;
}
void* GXGetFifoBase(GXFifoObj* fifo) {
return fifo->base;
}
u32 GXGetFifoSize(GXFifoObj* fifo) {
return fifo->size;
}
GXBreakPtCallback GXSetBreakPtCallback(GXBreakPtCallback cb) {
GXBreakPtCallback oldCallback = BreakPointCB;
int interrupts = OSDisableInterrupts();
BreakPointCB = cb;
OSRestoreInterrupts(interrupts);
return oldCallback;
}
void __GXFifoInit(void) {
__OSSetInterruptHandler(0x11, GXCPInterruptHandler);
__OSUnmaskInterrupts(0x4000);
__GXCurrentThread = OSGetCurrentThread();
GXOverflowSuspendInProgress = 0;
CPUFifo = NULL;
GPFifo = NULL;
}
void __GXFifoReadEnable(void) {
FAST_FLAG_SET(__GXData->cpEnable, 1, 0, 1);
GX_SET_CP_REG(1, __GXData->cpEnable);
}
void __GXFifoReadDisable(void) {
FAST_FLAG_SET(__GXData->cpEnable, 0, 0, 1);
GX_SET_CP_REG(1, __GXData->cpEnable);
}
void __GXFifoLink(u8 link) {
u32 b;
if (link) {
b = 1;
} else {
b = 0;
}
FAST_FLAG_SET(__GXData->cpEnable, b, 4, 1);
GX_SET_CP_REG(1, __GXData->cpEnable);
}
void __GXWriteFifoIntEnable(u32 p1, u32 p2) {
FAST_FLAG_SET(__GXData->cpEnable, p1, 2, 1);
FAST_FLAG_SET(__GXData->cpEnable, (u8)p2, 3, 1);
GX_SET_CP_REG(1, __GXData->cpEnable);
}
void __GXWriteFifoIntReset(u32 p1, u32 p2) {
FAST_FLAG_SET(__GXData->cpClr, p1, 0, 1);
FAST_FLAG_SET(__GXData->cpClr, (u8)p2, 1, 1);
GX_SET_CP_REG(2, __GXData->cpClr);
}
void __GXCleanGPFifo(void) {
BOOL interrupts;
GXFifoObj tempObj; // 0x14
u32 i, j, k; // stack alloc
GXFifoObj* gpFifo; // r31
GXFifoObj* cpuFifo; // r30
void* tempPtr; // r29
gpFifo = GXGetGPFifo();
if (!gpFifo) {
return;
}
cpuFifo = GXGetCPUFifo();
tempPtr = gpFifo->base;
tempObj = *gpFifo;
interrupts = OSDisableInterrupts();
tempObj.read_ptr = tempPtr;
tempObj.write_ptr = tempPtr;
tempObj.rw_dst = 0;
if (tempObj.rw_dst < 0) {
tempObj.rw_dst += tempObj.size;
}
OSRestoreInterrupts(interrupts);
GXSetGPFifo(&tempObj);
if (cpuFifo == gpFifo) {
GXSetCPUFifo(&tempObj);
}
interrupts = OSDisableInterrupts();
gpFifo->read_ptr = tempPtr;
gpFifo->write_ptr = tempPtr;
gpFifo->rw_dst = 0;
if (gpFifo->rw_dst < 0) {
gpFifo->rw_dst += gpFifo->size;
}
OSRestoreInterrupts(interrupts);
GXSetGPFifo(gpFifo);
if (cpuFifo == gpFifo) {
GXSetCPUFifo(cpuFifo);
}
}
OSThread* GXSetCurrentGXThread(void) {
BOOL interrupts = OSDisableInterrupts();
OSThread* prevThread = __GXCurrentThread;
__GXCurrentThread = OSGetCurrentThread();
OSRestoreInterrupts(interrupts);
return prevThread;
}
OSThread* GXGetCurrentGXThread(void) {
return *(OSThread**)(&__GXCurrentThread);
}
GXFifoObj* GXGetCPUFifo(void) {
return *(GXFifoObj**)(&CPUFifo);
}
GXFifoObj* GXGetGPFifo(void) {
return GPFifo;
}

638
src/dolphin/gx/GXFrameBuf.c Normal file
View File

@ -0,0 +1,638 @@
#include "dolphin/gx/GXFrameBuf.h"
#include "dolphin/gx/GX.h"
GXRenderModeObj GXNtsc480IntDf = {
VI_TVMODE_NTSC_INT,
640,
480,
480,
40,
0,
640,
480,
VI_XFBMODE_DF,
GX_FALSE,
GX_FALSE,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
8,
8,
10,
12,
10,
8,
8,
};
GXRenderModeObj GXNtsc480Int = {
VI_TVMODE_NTSC_INT,
640,
480,
480,
40,
0,
640,
480,
VI_XFBMODE_DF,
GX_FALSE,
GX_FALSE,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
0,
0,
21,
22,
21,
0,
0,
};
GXRenderModeObj GXMpal480IntDf = {
VI_TVMODE_MPAL_INT,
640,
480,
480,
40,
0,
640,
480,
VI_XFBMODE_DF,
GX_FALSE,
GX_FALSE,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
8,
8,
10,
12,
10,
8,
8,
};
GXRenderModeObj GXPal528IntDf = {
VI_TVMODE_PAL_INT,
640,
528,
528,
40,
23,
640,
528,
VI_XFBMODE_DF,
GX_FALSE,
GX_FALSE,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
8,
8,
10,
12,
10,
8,
8,
};
GXRenderModeObj GXEurgb60Hz480IntDf = {
VI_TVMODE_EURGB60_INT,
640,
480,
480,
40,
0,
640,
480,
VI_XFBMODE_DF,
GX_FALSE,
GX_FALSE,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
6,
8,
8,
10,
12,
10,
8,
8,
};
void GXSetDispCopySrc(u16 left, u16 top, u16 width, u16 height) {
__GXData->cpDispSrc = 0;
GX_BITFIELD_SET(__GXData->cpDispSrc, 22, 10, left);
GX_BITFIELD_SET(__GXData->cpDispSrc, 12, 10, top);
GX_BITFIELD_SET(__GXData->cpDispSrc, 0, 8, 73);
__GXData->cpDispSize = 0;
GX_BITFIELD_SET(__GXData->cpDispSize, 22, 10, width - 1);
GX_BITFIELD_SET(__GXData->cpDispSize, 12, 10, height - 1);
GX_BITFIELD_SET(__GXData->cpDispSize, 0, 8, 74);
}
void GXSetTexCopySrc(u16 left, u16 top, u16 width, u16 height) {
__GXData->cpTexSrc = 0;
GX_BITFIELD_SET(__GXData->cpTexSrc, 22, 10, left);
GX_BITFIELD_SET(__GXData->cpTexSrc, 12, 10, top);
GX_BITFIELD_SET(__GXData->cpTexSrc, 0, 8, 0x49);
__GXData->cpTexSize = 0;
GX_BITFIELD_SET(__GXData->cpTexSize, 22, 10, width - 1);
GX_BITFIELD_SET(__GXData->cpTexSize, 12, 10, height - 1);
GX_BITFIELD_SET(__GXData->cpTexSize, 0, 8, 0x4A);
}
void GXSetDispCopyDst(u16 arg0, u16 arg1) {
s32 val = (s32)((arg0 << 1) & 0xFFFE) >> 5;
__GXData->cpDispStride = 0;
GX_BITFIELD_SET(__GXData->cpDispStride, 22, 10, val);
GX_BITFIELD_SET(__GXData->cpDispStride, 0, 8, 0x4D);
}
void GXSetTexCopyDst(u16 width, u16 height, GXTexFmt format, GXBool useMIPmap) {
u32 sp20, sp1C, sp18;
u32 value;
u8 depthRelated;
__GXData->cpTexZ = GX_NONE;
depthRelated = format & 0xf;
if (format == GX_TF_Z16) {
depthRelated = 0xb;
}
switch (format) {
case GX_TF_I4:
case GX_TF_I8:
case GX_TF_IA4:
case GX_TF_IA8:
case GX_CTF_A8:
GX_SET_REG(__GXData->cpTex, 3, 15, 16);
break;
default:
GX_SET_REG(__GXData->cpTex, 2, 15, 16);
break;
}
__GXData->cpTexZ = (format & 0x10) == 0x10;
value = depthRelated >> 3;
GX_SET_REG(__GXData->cpTex, value, 28, 28);
depthRelated &= 7;
__GetImageTileCount(format, width, height, &sp20, &sp1C, &sp18);
__GXData->cpTexStride = GX_NONE;
GX_SET_REG(__GXData->cpTexStride, sp20 * sp18, 22, 31);
GX_SET_REG(__GXData->cpTexStride, 0x4D, 0, 7);
GX_SET_REG(__GXData->cpTex, useMIPmap, 22, 22);
GX_SET_REG(__GXData->cpTex, depthRelated, 25, 27);
}
void GXSetDispCopyFrame2Field(GXCopyMode arg0) {
GX_BITFIELD_SET(__GXData->cpDisp, 18, 2, arg0);
GX_BITFIELD_SET(__GXData->cpTex, 18, 2, 0);
}
// clang-format off
#define INSERT_FIELD(reg, value, nbits, shift) \
(reg) = ((u32) (reg) & ~(((1 << (nbits)) - 1) << (shift))) | \
((u32) (value) << (shift));
// clang-format on
void GXSetCopyClamp(GXFBClamp clamp) {
u8 isTop = (clamp & GX_CLAMP_TOP) == GX_CLAMP_TOP;
u8 isBottom = (clamp & GX_CLAMP_BOTTOM) == GX_CLAMP_BOTTOM;
__GXData->cpDisp = __rlwimi(__GXData->cpDisp, isTop, 0, 31, 31);
__GXData->cpDisp = __rlwimi(__GXData->cpDisp, isBottom, 1, 30, 30);
__GXData->cpTex = __rlwimi(__GXData->cpTex, isTop, 0, 31, 31);
__GXData->cpTex = __rlwimi(__GXData->cpTex, isBottom, 1, 30, 30);
}
static u32 __GXGetNumXfbLines(u32 height, u32 scale) {
u32 numLines;
u32 actualHeight;
u32 newScale;
numLines = (height - 1) * 0x100;
actualHeight = (numLines / scale) + 1;
newScale = scale;
if (newScale > 0x80 && newScale < 0x100) {
while (newScale % 2 == 0) {
newScale /= 2;
}
if (height % newScale == 0) {
actualHeight++;
}
}
if (actualHeight > 0x400) {
actualHeight = 0x400;
}
return actualHeight;
}
u16 GXGetNumXfbLines(const u16 efbHeight, f32 yScale) {
u32 scale = (u32)(256.0f / yScale) & 0x1FF;
return __GXGetNumXfbLines(efbHeight, scale);
}
f32 GXGetYScaleFactor(u16 efbHeight, u16 xfbHeight) {
u32 scale;
u32 height1;
u32 height2;
f32 scale2;
f32 scale1;
height1 = xfbHeight;
scale1 = (f32)xfbHeight / (f32)efbHeight;
scale = (u32)(256.0f / scale1) & 0x1FF;
height2 = __GXGetNumXfbLines(efbHeight, scale);
while (height2 > xfbHeight) {
height1--;
scale1 = (f32)height1 / (f32)efbHeight;
scale = (u32)(256.0f / scale1) & 0x1FF;
height2 = __GXGetNumXfbLines(efbHeight, scale);
}
scale2 = scale1;
while (height2 < xfbHeight) {
scale2 = scale1;
height1++;
scale1 = (f32)height1 / (f32)efbHeight;
scale = (u32)(256.0f / scale1) & 0x1FF;
height2 = __GXGetNumXfbLines(efbHeight, scale);
}
return scale2;
}
u32 GXSetDispCopyYScale(f32 vertScale) {
u32 scale;
GXBool check;
u32 height;
u32 reg;
scale = (u32)(256.0f / vertScale) & 0x1FF;
check = (scale != 0x100);
reg = 0;
GX_SET_REG(reg, scale, 23, 31);
GX_SET_REG(reg, 0x4E, 0, 7);
GX_BP_LOAD_REG(reg);
__GXData->bpSentNot = GX_FALSE;
GX_SET_REG(__GXData->cpDisp, check, 21, 21);
height = (__GXData->cpDispSize >> 10 & 0x3FF) + 1;
return __GXGetNumXfbLines(height, scale);
}
void GXSetCopyClear(GXColor color, u32 clear_z) {
u32 r6 = 0;
GX_BITFIELD_SET(r6, 24, 8, color.r);
GX_BITFIELD_SET(r6, 16, 8, color.a);
GX_BITFIELD_SET(r6, 0, 8, 0x4f);
GXFIFO.u8 = 0x61;
GXFIFO.u32 = r6;
r6 = 0;
GX_BITFIELD_SET(r6, 24, 8, color.b);
GX_BITFIELD_SET(r6, 16, 8, color.g);
GX_BITFIELD_SET(r6, 0, 8, 0x50);
GXFIFO.u8 = 0x61;
GXFIFO.u32 = r6;
r6 = 0;
GX_BITFIELD_SET(r6, 8, 24, clear_z);
GX_BITFIELD_SET(r6, 0, 8, 0x51);
GXFIFO.u8 = 0x61;
GXFIFO.u32 = r6;
__GXData->bpSentNot = 0;
}
void GXSetCopyFilter(GXBool useAA, u8 samplePattern[12][2], GXBool doVertFilt, u8 vFilt[7]) {
u32 vals[4];
u32 unk1;
u32 unk2;
if (useAA) {
vals[0] = 0;
GX_SET_REG(vals[0], samplePattern[0][0], 28, 31);
GX_SET_REG(vals[0], samplePattern[0][1], 24, 27);
GX_SET_REG(vals[0], samplePattern[1][0], 20, 23);
GX_SET_REG(vals[0], samplePattern[1][1], 16, 19);
GX_SET_REG(vals[0], samplePattern[2][0], 12, 15);
GX_SET_REG(vals[0], samplePattern[2][1], 8, 11);
GX_SET_REG(vals[0], 1, 0, 7);
vals[1] = 0;
GX_SET_REG(vals[1], samplePattern[3][0], 28, 31);
GX_SET_REG(vals[1], samplePattern[3][1], 24, 27);
GX_SET_REG(vals[1], samplePattern[4][0], 20, 23);
GX_SET_REG(vals[1], samplePattern[4][1], 16, 19);
GX_SET_REG(vals[1], samplePattern[5][0], 12, 15);
GX_SET_REG(vals[1], samplePattern[5][1], 8, 11);
GX_SET_REG(vals[1], 2, 0, 7);
vals[2] = 0;
GX_SET_REG(vals[2], samplePattern[6][0], 28, 31);
GX_SET_REG(vals[2], samplePattern[6][1], 24, 27);
GX_SET_REG(vals[2], samplePattern[7][0], 20, 23);
GX_SET_REG(vals[2], samplePattern[7][1], 16, 19);
GX_SET_REG(vals[2], samplePattern[8][0], 12, 15);
GX_SET_REG(vals[2], samplePattern[8][1], 8, 11);
GX_SET_REG(vals[2], 3, 0, 7);
vals[3] = 0;
GX_SET_REG(vals[3], samplePattern[9][0], 28, 31);
GX_SET_REG(vals[3], samplePattern[9][1], 24, 27);
GX_SET_REG(vals[3], samplePattern[10][0], 20, 23);
GX_SET_REG(vals[3], samplePattern[10][1], 16, 19);
GX_SET_REG(vals[3], samplePattern[11][0], 12, 15);
GX_SET_REG(vals[3], samplePattern[11][1], 8, 11);
GX_SET_REG(vals[3], 4, 0, 7);
} else {
vals[0] = 0x01666666;
vals[1] = 0x02666666;
vals[2] = 0x03666666;
vals[3] = 0x04666666;
}
GX_BP_LOAD_REG(vals[0]);
GX_BP_LOAD_REG(vals[1]);
GX_BP_LOAD_REG(vals[2]);
GX_BP_LOAD_REG(vals[3]);
unk1 = 0;
GX_SET_REG(unk1, 0x53, 0, 7);
unk2 = 0;
GX_SET_REG(unk2, 0x54, 0, 7);
if (doVertFilt) {
GX_SET_REG(unk1, vFilt[0], 26, 31);
GX_SET_REG(unk1, vFilt[1], 20, 25);
GX_SET_REG(unk1, vFilt[2], 14, 19);
GX_SET_REG(unk1, vFilt[3], 8, 13);
GX_SET_REG(unk2, vFilt[4], 26, 31);
GX_SET_REG(unk2, vFilt[5], 20, 25);
GX_SET_REG(unk2, vFilt[6], 14, 19);
} else {
GX_SET_REG(unk1, 0, 26, 31);
GX_SET_REG(unk1, 0, 20, 25);
GX_SET_REG(unk1, 21, 14, 19);
GX_SET_REG(unk1, 22, 8, 13);
GX_SET_REG(unk2, 21, 26, 31);
GX_SET_REG(unk2, 0, 20, 25);
GX_SET_REG(unk2, 0, 14, 19);
}
GX_BP_LOAD_REG(unk1);
GX_BP_LOAD_REG(unk2);
__GXData->bpSentNot = GX_FALSE;
}
void GXSetDispCopyGamma(GXGamma gamma) {
GX_BITFIELD_SET(__GXData->cpDisp, 23, 2, gamma);
}
void GXCopyDisp(void* dest, GXBool doClear) {
u32 reg;
u32 newDest;
GXBool check;
if (doClear) {
reg = __GXData->zmode;
GX_SET_REG(reg, 1, 31, 31);
GX_SET_REG(reg, 7, 28, 30);
GX_BP_LOAD_REG(reg);
reg = __GXData->cmode0;
GX_SET_REG(reg, 0, 31, 31);
GX_SET_REG(reg, 0, 30, 30);
GX_BP_LOAD_REG(reg);
}
check = GX_FALSE;
if ((doClear || (__GXData->peCtrl & 0x7) == 3) && (__GXData->peCtrl >> 6 & 0x1) == 1) {
check = GX_TRUE;
reg = __GXData->peCtrl;
GX_SET_REG(reg, 0, 25, 25);
GX_BP_LOAD_REG(reg);
}
GX_BP_LOAD_REG(__GXData->cpDispSrc);
GX_BP_LOAD_REG(__GXData->cpDispSize);
GX_BP_LOAD_REG(__GXData->cpDispStride);
newDest = (u32)dest & 0x3FFFFFFF;
reg = 0;
GX_SET_REG(reg, newDest >> 5, 11, 31);
GX_SET_REG(reg, 0x4B, 0, 7);
GX_BP_LOAD_REG(reg);
GX_SET_REG(__GXData->cpDisp, doClear, 20, 20);
GX_SET_REG(__GXData->cpDisp, 1, 17, 17);
GX_SET_REG(__GXData->cpDisp, 0x52, 0, 7);
GX_BP_LOAD_REG(__GXData->cpDisp);
if (doClear) {
GX_BP_LOAD_REG(__GXData->zmode);
GX_BP_LOAD_REG(__GXData->cmode0);
}
if (check) {
GX_BP_LOAD_REG(__GXData->peCtrl);
}
__GXData->bpSentNot = GX_FALSE;
}
void GXCopyTex(void* dest, GXBool doClear) {
u32 reg;
u32 reg2;
u32 newDest;
GXBool check;
if (doClear) {
reg = __GXData->zmode;
GX_SET_REG(reg, 1, 31, 31);
GX_SET_REG(reg, 7, 28, 30);
GX_BP_LOAD_REG(reg);
reg = __GXData->cmode0;
GX_SET_REG(reg, 0, 31, 31);
GX_SET_REG(reg, 0, 30, 30);
GX_BP_LOAD_REG(reg);
}
check = GX_FALSE;
reg2 = __GXData->peCtrl;
if (__GXData->cpTexZ && (reg2 & 0x7) != 3) {
check = GX_TRUE;
GX_SET_REG(reg2, 3, 29, 31);
}
if ((doClear || (reg2 & 0x7) == 3) && (reg2 >> 6 & 0x1) == 1) {
check = GX_TRUE;
GX_SET_REG(reg2, 0, 25, 25);
}
if (check) {
GX_BP_LOAD_REG(reg2);
}
GX_BP_LOAD_REG(__GXData->cpTexSrc);
GX_BP_LOAD_REG(__GXData->cpTexSize);
GX_BP_LOAD_REG(__GXData->cpTexStride);
newDest = (u32)dest & 0x3FFFFFFF;
reg = 0;
GX_SET_REG(reg, newDest >> 5, 11, 31);
GX_SET_REG(reg, 0x4B, 0, 7);
GX_BP_LOAD_REG(reg);
GX_SET_REG(__GXData->cpTex, doClear, 20, 20);
GX_SET_REG(__GXData->cpTex, 0, 17, 17);
GX_SET_REG(__GXData->cpTex, 0x52, 0, 7);
GX_BP_LOAD_REG(__GXData->cpTex);
if (doClear) {
GX_BP_LOAD_REG(__GXData->zmode);
GX_BP_LOAD_REG(__GXData->cmode0);
}
if (check) {
GX_BP_LOAD_REG(__GXData->peCtrl);
}
__GXData->bpSentNot = GX_FALSE;
}
void GXClearBoundingBox(void) {
GXFIFO.u8 = GX_LOAD_BP_REG;
GXFIFO.u32 = 0x550003FF;
GXFIFO.u8 = GX_LOAD_BP_REG;
GXFIFO.u32 = 0x560003FF;
set_x2(GX_FALSE);
}

149
src/dolphin/gx/GXGeometry.c Normal file
View File

@ -0,0 +1,149 @@
/**
* GXGeometry.c
* Description:
*/
#include "dolphin/gx/GXGeometry.h"
#include "dolphin/gx/GX.h"
void __GXSetDirtyState(void) {
u32 dirtyFlags = __GXData->dirtyState;
if (dirtyFlags & GX_DIRTY_SU_TEX) {
__GXSetSUTexRegs();
}
if (dirtyFlags & GX_DIRTY_BP_MASK) {
__GXUpdateBPMask();
}
if (dirtyFlags & GX_DIRTY_GEN_MODE) {
__GXSetGenMode();
}
if (dirtyFlags & GX_DIRTY_VCD) {
__GXSetVCD();
}
if (dirtyFlags & GX_DIRTY_VAT) {
__GXSetVAT();
}
if (dirtyFlags & GX_DIRTY_VLIM) {
__GXCalculateVLim();
}
__GXData->dirtyState = 0;
}
void GXBegin(GXPrimitive type, GXVtxFmt fmt, u16 vert_num) {
GXData* data = __GXData;
u32 dirtyFlags = data->dirtyState;
if (data->dirtyState != 0) {
if (dirtyFlags & GX_DIRTY_SU_TEX) {
__GXSetSUTexRegs();
}
if (dirtyFlags & GX_DIRTY_BP_MASK) {
__GXUpdateBPMask();
}
if (dirtyFlags & GX_DIRTY_GEN_MODE) {
__GXSetGenMode();
}
if (dirtyFlags & GX_DIRTY_VCD) {
__GXSetVCD();
}
if (dirtyFlags & GX_DIRTY_VAT) {
__GXSetVAT();
}
if (dirtyFlags & GX_DIRTY_VLIM) {
__GXCalculateVLim();
}
__GXData->dirtyState = 0;
}
if (*(u32*)__GXData == 0) {
__GXSendFlushPrim();
}
GXFIFO.u8 = fmt | type;
GXFIFO.u16 = vert_num;
}
void __GXSendFlushPrim(void) {
u32 i;
u32 sz = __GXData->vNum * __GXData->vLim;
GXFIFO.u8 = 0x98;
GXFIFO.u16 = __GXData->vNum;
for (i = 0; i < sz; i += 4) {
GXFIFO.s32 = 0;
}
__GXData->bpSentNot = 1;
}
void GXSetLineWidth(u8 width, GXTexOffset offsets) {
GXData* data = __GXData;
GX_BITFIELD_SET(data->lpSize, 24, 8, width);
GX_BITFIELD_SET(data->lpSize, 13, 3, offsets);
GXFIFO.u8 = 0x61;
GXFIFO.u32 = data->lpSize;
data->bpSentNot = 0;
}
void GXSetPointSize(u8 size, GXTexOffset offsets) {
GXData* data = __GXData;
GX_BITFIELD_SET(data->lpSize, 16, 8, size);
GX_BITFIELD_SET(data->lpSize, 10, 3, offsets);
GXFIFO.u8 = 0x61;
GXFIFO.u32 = data->lpSize;
data->bpSentNot = 0;
}
void GXEnableTexOffsets(GXTexCoordID coord, GXBool line, GXBool point) {
GXData* data = __GXData;
GX_BITFIELD_SET(data->suTs0[coord], 13, 1, line);
GX_BITFIELD_SET(data->suTs0[coord], 12, 1, point);
GXFIFO.u8 = 0x61;
GXFIFO.u32 = data->suTs0[coord];
data->bpSentNot = 0;
}
void GXSetCullMode(GXCullMode mode) {
GXData* data;
GXCullMode mode2;
data = __GXData;
mode2 = (mode >> 1) & 1;
GX_BITFIELD_SET(mode2, 30, 1, mode);
GX_BITFIELD_SET(data->genMode, 16, 2, mode2);
data->dirtyState |= GX_DIRTY_GEN_MODE;
}
void GXSetCoPlanar(GXBool enable) {
GXData* data = __GXData;
GX_BITFIELD_SET(data->genMode, 12, 1, enable);
GXFIFO.u8 = 0x61;
GXFIFO.u32 = 0xFE080000;
GXFIFO.u8 = 0x61;
GXFIFO.u32 = data->genMode;
}
void __GXSetGenMode(void) {
GXFIFO.u8 = 0x61;
GXFIFO.u32 = __GXData->genMode;
__GXData->bpSentNot = 0;
}

561
src/dolphin/gx/GXInit.c Normal file
View File

@ -0,0 +1,561 @@
#include "dolphin/gx/GX.h"
#include "dolphin/os/OS.h"
#include "dolphin/vi/vi.h"
char* __GXVersion = "<< Dolphin SDK - GX release build: Nov 10 2004 06:27:12 (0x2301) >>";
static GXFifoObj FifoObj;
static GXData gxData;
GXData* const __GXData = &gxData;
GXTexRegion* __GXDefaultTexRegionCallback(const GXTexObj* obj, GXTexMapID id) {
GXTexFmt format; // r31
GXBool isMipMap; // r3
format = GXGetTexObjFmt(obj);
isMipMap = GXGetTexObjMipMap(obj);
id = (GXTexMapID)(id % GX_MAX_TEXMAP);
switch (format) {
case GX_TF_RGBA8:
if (isMipMap) {
return &__GXData->TexRegions2[id];
}
return &__GXData->TexRegions1[id];
case GX_TF_C4:
case GX_TF_C8:
case GX_TF_C14X2:
return &__GXData->TexRegions0[id];
default:
if (isMipMap) {
return &__GXData->TexRegions1[id];
}
return &__GXData->TexRegions0[id];
}
}
GXTlutRegion* __GXDefaultTlutRegionCallback(u32 tlut) {
if (tlut >= 0x14) {
return NULL;
} else {
return &__GXData->TlutRegions[tlut];
}
}
u32 resetFuncRegistered;
u32 calledOnce;
OSTime time;
u32 peCount;
vu16* __memReg;
u16* __peReg;
u16* __cpReg;
/* ############################################################################################## */
u32* __piReg;
BOOL __GXShutdown(BOOL final) {
u32 val;
u32 newPeCount;
OSTime newTime;
if (!final) {
if (!calledOnce) {
peCount = GXReadMEMReg(0x28, 0x27);
time = OSGetTime();
calledOnce = 1;
return FALSE;
}
newTime = OSGetTime();
newPeCount = GXReadMEMReg(0x28, 0x27);
if (newTime - time < 10) {
return FALSE;
}
if (newPeCount != peCount) {
peCount = newPeCount;
time = newTime;
return FALSE;
}
} else {
GXSetBreakPtCallback(NULL);
GXSetDrawSyncCallback(NULL);
GXSetDrawDoneCallback(NULL);
GX_WRITE_U32(0);
GX_WRITE_U32(0);
GX_WRITE_U32(0);
GX_WRITE_U32(0);
GX_WRITE_U32(0);
GX_WRITE_U32(0);
GX_WRITE_U32(0);
GX_WRITE_U32(0);
PPCSync();
GX_SET_CP_REG(1, 0);
GX_SET_CP_REG(2, 3);
__GXData->abtWaitPECopy = GX_TRUE;
__GXAbort();
}
return TRUE;
}
void __GXInitRevisionBits(void) {
u32 i;
for (i = 0; i < 8; i++) {
FAST_FLAG_SET(__GXData->vatA[i], 1, 30, 33);
FAST_FLAG_SET(__GXData->vatB[i], 1, 31, 33);
GX_WRITE_U8(0x8);
GX_WRITE_U8(i | 0x80);
GX_WRITE_U32(__GXData->vatB[i]);
}
{
u32 reg1 = 0;
u32 reg2 = 0;
FAST_FLAG_SET(reg1, 1, 0, 1);
FAST_FLAG_SET(reg1, 1, 1, 1);
FAST_FLAG_SET(reg1, 1, 2, 1);
FAST_FLAG_SET(reg1, 1, 3, 1);
FAST_FLAG_SET(reg1, 1, 4, 1);
FAST_FLAG_SET(reg1, 1, 5, 1);
GX_WRITE_U8(0x10);
GX_WRITE_U32(0x1000);
GX_WRITE_U32(reg1);
FAST_FLAG_SET(reg2, 1, 0, 1);
GX_WRITE_U8(0x10);
GX_WRITE_U32(0x1012);
GX_WRITE_U32(reg2);
}
{
u32 reg = 0;
FAST_FLAG_SET(reg, 1, 0, 1);
FAST_FLAG_SET(reg, 1, 1, 1);
FAST_FLAG_SET(reg, 1, 2, 1);
FAST_FLAG_SET(reg, 1, 3, 1);
FAST_FLAG_SET(reg, 0x58, 24, 8);
GX_WRITE_U8(0x61);
GX_WRITE_U32(reg);
}
}
static u16 DefaultTexData[] ALIGN_DECL(32) = {
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
};
static GXVtxAttrFmtList GXDefaultVATList[] = {
{GX_VA_POS, GX_POS_XYZ, GX_F32, 0},
{GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0},
{GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0},
{GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0},
{GX_VA_TEX0, GX_TEX_ST, GX_F32, 0},
{GX_VA_TEX1, GX_TEX_ST, GX_F32, 0},
{GX_VA_TEX2, GX_TEX_ST, GX_F32, 0},
{GX_VA_TEX3, GX_TEX_ST, GX_F32, 0},
{GX_VA_TEX4, GX_TEX_ST, GX_F32, 0},
{GX_VA_TEX5, GX_TEX_ST, GX_F32, 0},
{GX_VA_TEX6, GX_TEX_ST, GX_F32, 0},
{GX_VA_TEX7, GX_TEX_ST, GX_F32, 0},
{GX_VA_NULL, GX_COMPCNT_NULL, GX_COMP_NULL, 0},
};
static f32 GXDefaultProjData[] = {1.0f, 0.0f, 1.0f, 0.0f, -1.0f, -2.0f, 0.0f};
static u32 GXTexRegionAddrTable[] = {
0x00000, 0x10000, 0x20000, 0x30000, 0x40000, 0x50000, 0x60000, 0x70000, 0x08000, 0x18000,
0x28000, 0x38000, 0x48000, 0x58000, 0x68000, 0x78000, 0x00000, 0x90000, 0x20000, 0xB0000,
0x40000, 0x98000, 0x60000, 0xB8000, 0x80000, 0x10000, 0xA0000, 0x30000, 0x88000, 0x50000,
0xA8000, 0x70000, 0x00000, 0x90000, 0x20000, 0xB0000, 0x40000, 0x90000, 0x60000, 0xB0000,
0x80000, 0x10000, 0xA0000, 0x30000, 0x80000, 0x50000, 0xA0000, 0x70000,
};
static OSResetFunctionInfo GXResetFuncInfo = {__GXShutdown, OS_RESET_PRIO_GX};
static void EnableWriteGatherPipe() {
u32 hid2; // r31
hid2 = PPCMfhid2();
PPCMtwpar(OSUncachedToPhysical((void*)GXFIFO_ADDR));
hid2 |= 0x40000000;
PPCMthid2(hid2);
}
GXFifoObj* GXInit(void* base, u32 size) {
u32 i;
u32 pad2; // for stack matching
OSRegisterVersion(__GXVersion);
__GXData->inDispList = GX_FALSE;
__GXData->dlSaveContext = GX_TRUE;
__GXData->abtWaitPECopy = GX_TRUE;
__GXData->tcsManEnab = 0;
__GXData->tevTcEnab = 0;
GXSetMisc(GX_MT_XF_FLUSH, 0);
__piReg = (void*)OSPhysicalToUncached(GX_PI_ADDR);
__cpReg = (void*)OSPhysicalToUncached(GX_CP_ADDR);
__peReg = (void*)OSPhysicalToUncached(GX_PE_ADDR);
__memReg = (void*)OSPhysicalToUncached(GX_MEM_ADDR);
__GXFifoInit();
GXInitFifoBase(&FifoObj, base, size);
GXSetCPUFifo(&FifoObj);
GXSetGPFifo(&FifoObj);
if (!resetFuncRegistered) {
OSRegisterResetFunction(&GXResetFuncInfo);
resetFuncRegistered = 1;
}
__GXPEInit();
EnableWriteGatherPipe();
__GXData->genMode = 0;
FAST_FLAG_SET(__GXData->genMode, 0, 24, 8);
__GXData->bpMask = 255;
FAST_FLAG_SET(__GXData->bpMask, 0xF, 24, 8);
__GXData->lpSize = 0;
FAST_FLAG_SET(__GXData->lpSize, 34, 24, 8);
for (i = 0; i < GX_MAX_TEVSTAGE; i++) {
__GXData->tevc[i] = 0;
__GXData->teva[i] = 0;
__GXData->tref[i / 2] = 0;
__GXData->texmapId[i] = GX_TEXMAP_NULL;
FAST_FLAG_SET(__GXData->tevc[i], 0xC0 + i * 2, 24, 8);
FAST_FLAG_SET(__GXData->teva[i], 0xC1 + i * 2, 24, 8);
FAST_FLAG_SET(__GXData->tevKsel[i / 2], 0xF6 + i / 2, 24, 8);
FAST_FLAG_SET(__GXData->tref[i / 2], 0x28 + i / 2, 24, 8);
}
__GXData->iref = 0;
FAST_FLAG_SET(__GXData->iref, 0x27, 24, 8);
for (i = 0; i < GX_MAXCOORD; i++) {
__GXData->suTs0[i] = 0;
__GXData->suTs1[i] = 0;
FAST_FLAG_SET(__GXData->suTs0[i], 0x30 + i * 2, 24, 8);
FAST_FLAG_SET(__GXData->suTs1[i], 0x31 + i * 2, 24, 8);
}
FAST_FLAG_SET(__GXData->suScis0, 0x20, 24, 8);
FAST_FLAG_SET(__GXData->suScis1, 0x21, 24, 8);
FAST_FLAG_SET(__GXData->cmode0, 0x41, 24, 8);
FAST_FLAG_SET(__GXData->cmode1, 0x42, 24, 8);
FAST_FLAG_SET(__GXData->zmode, 0x40, 24, 8);
FAST_FLAG_SET(__GXData->peCtrl, 0x43, 24, 8);
FAST_FLAG_SET(__GXData->cpTex, 0, 7, 2);
__GXData->zScale = 1.6777216E7f;
__GXData->zOffset = 0.0f;
__GXData->dirtyState = 0;
__GXData->dirtyVAT = 0;
{
u32 val1;
u32 val2;
val2 = OS_BUS_CLOCK / 500;
__GXFlushTextureState();
val1 = (val2 / 2048) | 0x69000400;
GX_WRITE_U8(0x61);
GX_WRITE_U32(val1);
__GXFlushTextureState();
val1 = (val2 / 4224) | 0x46000200;
GX_WRITE_U8(0x61);
GX_WRITE_U32(val1);
}
__GXInitRevisionBits();
for (i = 0; i < GX_MAX_TEXMAP; i++) {
GXInitTexCacheRegion(&__GXData->TexRegions0[i], GX_FALSE, GXTexRegionAddrTable[i],
GX_TEXCACHE_32K, GXTexRegionAddrTable[i + 8], GX_TEXCACHE_32K);
GXInitTexCacheRegion(&__GXData->TexRegions1[i], GX_FALSE, GXTexRegionAddrTable[i + 16],
GX_TEXCACHE_32K, GXTexRegionAddrTable[i + 24], GX_TEXCACHE_32K);
GXInitTexCacheRegion(&__GXData->TexRegions2[i], GX_TRUE, GXTexRegionAddrTable[i + 32],
GX_TEXCACHE_32K, GXTexRegionAddrTable[i + 40], GX_TEXCACHE_32K);
}
for (i = 0; i < GX_MAX_TLUT; i++) {
GXInitTlutRegion(&__GXData->TlutRegions[i], 0xC0000 + 0x2000 * i, GX_TLUT_256);
}
for (i = 0; i < GX_MAX_BIGTLUT; i++) {
GXInitTlutRegion(&__GXData->TlutRegions[i + 16], 0xE0000 + 0x8000 * i, GX_TLUT_1K);
}
GX_SET_CP_REG(3, 0);
FAST_FLAG_SET(__GXData->perfSel, 0, 4, 4);
GX_WRITE_U8(0x8);
GX_WRITE_U8(0x20);
GX_WRITE_U32(__GXData->perfSel);
GX_WRITE_U8(0x10);
GX_WRITE_U32(0x1006);
GX_WRITE_U32(0);
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x23000000);
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x24000000);
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x67000000);
__GXSetIndirectMask(0);
__GXSetTmemConfig(2);
__GXInitGX();
return &FifoObj;
}
void __GXInitGX(void) {
GXRenderModeObj* renderObj;
GXTexObj texObj;
Mtx ident;
GXColor clearColor = {64, 64, 64, 255};
GXColor ambColor = {0, 0, 0, 0};
GXColor matColor = {255, 255, 255, 255};
u32 i;
switch (VIGetTvFormat()) {
case VI_NTSC:
renderObj = &GXNtsc480IntDf;
break;
case VI_PAL:
renderObj = &GXPal528IntDf;
break;
case VI_EURGB60:
renderObj = &GXEurgb60Hz480IntDf;
break;
case VI_MPAL:
renderObj = &GXMpal480IntDf;
break;
default:
renderObj = &GXNtsc480IntDf;
break;
}
GXSetCopyClear(clearColor, 0xFFFFFF);
GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY);
GXSetTexCoordGen2(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY);
GXSetTexCoordGen2(GX_TEXCOORD2, GX_TG_MTX2x4, GX_TG_TEX2, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY);
GXSetTexCoordGen2(GX_TEXCOORD3, GX_TG_MTX2x4, GX_TG_TEX3, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY);
GXSetTexCoordGen2(GX_TEXCOORD4, GX_TG_MTX2x4, GX_TG_TEX4, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY);
GXSetTexCoordGen2(GX_TEXCOORD5, GX_TG_MTX2x4, GX_TG_TEX5, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY);
GXSetTexCoordGen2(GX_TEXCOORD6, GX_TG_MTX2x4, GX_TG_TEX6, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY);
GXSetTexCoordGen2(GX_TEXCOORD7, GX_TG_MTX2x4, GX_TG_TEX7, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY);
GXSetNumTexGens(1);
GXClearVtxDesc();
GXInvalidateVtxCache();
for (i = GX_VA_POS; i <= GX_LIGHT_ARRAY; i++) {
GXSetArray((GXAttr)i, __GXData, 0);
}
for (i = 0; i < GX_MAX_VTXFMT; i++) {
GXSetVtxAttrFmtv((GXVtxFmt)i, GXDefaultVATList);
}
GXSetLineWidth(6, GX_TO_ZERO);
GXSetPointSize(6, GX_TO_ZERO);
GXEnableTexOffsets(GX_TEXCOORD0, GX_FALSE, GX_FALSE);
GXEnableTexOffsets(GX_TEXCOORD1, GX_FALSE, GX_FALSE);
GXEnableTexOffsets(GX_TEXCOORD2, GX_FALSE, GX_FALSE);
GXEnableTexOffsets(GX_TEXCOORD3, GX_FALSE, GX_FALSE);
GXEnableTexOffsets(GX_TEXCOORD4, GX_FALSE, GX_FALSE);
GXEnableTexOffsets(GX_TEXCOORD5, GX_FALSE, GX_FALSE);
GXEnableTexOffsets(GX_TEXCOORD6, GX_FALSE, GX_FALSE);
GXEnableTexOffsets(GX_TEXCOORD7, GX_FALSE, GX_FALSE);
ident[0][0] = 1.0f;
ident[0][1] = 0.0f;
ident[0][2] = 0.0f;
ident[0][3] = 0.0f;
ident[1][0] = 0.0f;
ident[1][1] = 1.0f;
ident[1][2] = 0.0f;
ident[1][3] = 0.0f;
ident[2][0] = 0.0f;
ident[2][1] = 0.0f;
ident[2][2] = 1.0f;
ident[2][3] = 0.0f;
GXLoadPosMtxImm(ident, GX_PNMTX0);
GXLoadNrmMtxImm(ident, GX_PNMTX0);
GXSetCurrentMtx(GX_PNMTX0);
GXLoadTexMtxImm(ident, GX_IDENTITY, GX_MTX3x4);
GXLoadTexMtxImm(ident, GX_PTIDENTITY, GX_MTX3x4);
GXSetViewport(0.0f, 0.0f, renderObj->fb_width, renderObj->xfb_height, 0.0f, 1.0f);
GXSetProjectionv(GXDefaultProjData);
GXSetCoPlanar(GX_FALSE);
GXSetCullMode(GX_CULL_BACK);
GXSetClipMode(GX_CLIP_ENABLE);
GXSetScissor(0, 0, renderObj->fb_width, renderObj->efb_height);
GXSetScissorBoxOffset(0, 0);
GXSetNumChans(0);
GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_VTX, 0, GX_DF_NONE, GX_AF_NONE);
GXSetChanAmbColor(GX_COLOR0A0, ambColor);
GXSetChanMatColor(GX_COLOR0A0, matColor);
GXSetChanCtrl(GX_COLOR1A1, GX_FALSE, GX_SRC_REG, GX_SRC_VTX, 0, GX_DF_NONE, GX_AF_NONE);
GXSetChanAmbColor(GX_COLOR1A1, ambColor);
GXSetChanMatColor(GX_COLOR1A1, matColor);
GXInvalidateTexAll();
GXSetTexRegionCallback(__GXDefaultTexRegionCallback);
GXSetTlutRegionCallback(__GXDefaultTlutRegionCallback);
GXInitTexObj(&texObj, DefaultTexData, 4, 4, GX_TF_IA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
GXLoadTexObj(&texObj, GX_TEXMAP0);
GXLoadTexObj(&texObj, GX_TEXMAP1);
GXLoadTexObj(&texObj, GX_TEXMAP2);
GXLoadTexObj(&texObj, GX_TEXMAP3);
GXLoadTexObj(&texObj, GX_TEXMAP4);
GXLoadTexObj(&texObj, GX_TEXMAP5);
GXLoadTexObj(&texObj, GX_TEXMAP6);
GXLoadTexObj(&texObj, GX_TEXMAP7);
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR0A0);
GXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD2, GX_TEXMAP2, GX_COLOR0A0);
GXSetTevOrder(GX_TEVSTAGE3, GX_TEXCOORD3, GX_TEXMAP3, GX_COLOR0A0);
GXSetTevOrder(GX_TEVSTAGE4, GX_TEXCOORD4, GX_TEXMAP4, GX_COLOR0A0);
GXSetTevOrder(GX_TEVSTAGE5, GX_TEXCOORD5, GX_TEXMAP5, GX_COLOR0A0);
GXSetTevOrder(GX_TEVSTAGE6, GX_TEXCOORD6, GX_TEXMAP6, GX_COLOR0A0);
GXSetTevOrder(GX_TEVSTAGE7, GX_TEXCOORD7, GX_TEXMAP7, GX_COLOR0A0);
GXSetTevOrder(GX_TEVSTAGE8, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);
GXSetTevOrder(GX_TEVSTAGE9, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);
GXSetTevOrder(GX_TEVSTAGE10, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);
GXSetTevOrder(GX_TEVSTAGE11, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);
GXSetTevOrder(GX_TEVSTAGE12, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);
GXSetTevOrder(GX_TEVSTAGE13, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);
GXSetTevOrder(GX_TEVSTAGE14, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);
GXSetTevOrder(GX_TEVSTAGE15, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);
GXSetNumTevStages(1);
GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0);
GXSetZTexture(GX_ZT_DISABLE, GX_TF_Z8, 0);
for (i = 0; i < GX_MAX_TEVSTAGE; i++) {
GXSetTevKColorSel((GXTevStageID)i, GX_TEV_KCSEL_1_4);
GXSetTevKAlphaSel((GXTevStageID)i, GX_TEV_KASEL_1);
GXSetTevSwapMode((GXTevStageID)i, GX_TEV_SWAP0, GX_TEV_SWAP0);
}
GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA);
GXSetTevSwapModeTable(GX_TEV_SWAP1, GX_CH_RED, GX_CH_RED, GX_CH_RED, GX_CH_ALPHA);
GXSetTevSwapModeTable(GX_TEV_SWAP2, GX_CH_GREEN, GX_CH_GREEN, GX_CH_GREEN, GX_CH_ALPHA);
GXSetTevSwapModeTable(GX_TEV_SWAP3, GX_CH_BLUE, GX_CH_BLUE, GX_CH_BLUE, GX_CH_ALPHA);
for (i = 0; i < GX_MAX_TEVSTAGE; i++) {
GXSetTevDirect((GXTevStageID)i);
}
GXSetNumIndStages(0);
GXSetIndTexCoordScale(GX_INDTEXSTAGE0, GX_ITS_1, GX_ITS_1);
GXSetIndTexCoordScale(GX_INDTEXSTAGE1, GX_ITS_1, GX_ITS_1);
GXSetIndTexCoordScale(GX_INDTEXSTAGE2, GX_ITS_1, GX_ITS_1);
GXSetIndTexCoordScale(GX_INDTEXSTAGE3, GX_ITS_1, GX_ITS_1);
GXSetFog(GX_FOG_NONE, 0.0f, 1.0f, 0.1f, 1.0f, ambColor);
GXSetFogRangeAdj(GX_FALSE, 0, NULL);
GXSetBlendMode(GX_BM_NONE, GX_BL_SRC_ALPHA, GX_BL_INV_SRC_ALPHA, GX_LO_CLEAR);
GXSetColorUpdate(GX_TRUE);
GXSetAlphaUpdate(GX_TRUE);
GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
GXSetZCompLoc(GX_TRUE);
GXSetDither(GX_TRUE);
GXSetDstAlpha(GX_FALSE, 0);
GXSetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
GXSetFieldMask(GX_TRUE, GX_TRUE);
GXSetFieldMode(
(GXBool)renderObj->field_rendering,
(GXBool)((renderObj->vi_height == 2 * renderObj->xfb_height) ? GX_TRUE : GX_FALSE));
GXSetDispCopySrc(0, 0, renderObj->fb_width, renderObj->efb_height);
GXSetDispCopyDst(renderObj->fb_width, renderObj->efb_height);
GXSetDispCopyYScale((f32)renderObj->xfb_height / (f32)renderObj->efb_height);
GXSetCopyClamp(GX_CLAMP_BOTH);
GXSetCopyFilter(renderObj->antialiasing, renderObj->sample_pattern, GX_TRUE,
renderObj->vfilter);
GXSetDispCopyGamma(GX_GM_1_0);
GXSetDispCopyFrame2Field(GX_COPY_PROGRESSIVE);
GXClearBoundingBox();
GXPokeColorUpdate(GX_TRUE);
GXPokeAlphaUpdate(GX_TRUE);
GXPokeDither(GX_FALSE);
GXPokeBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ONE, GX_LO_SET);
GXPokeAlphaMode(GX_ALWAYS, 0);
GXPokeAlphaRead(GX_READ_FF);
GXPokeDstAlpha(GX_FALSE, 0);
GXPokeZMode(GX_TRUE, GX_ALWAYS, GX_TRUE);
GXSetGPMetric(GX_PERF0_NONE, GX_PERF1_NONE);
GXClearGPMetric();
}

294
src/dolphin/gx/GXLight.c Normal file
View File

@ -0,0 +1,294 @@
/**
* GXLight.c
* Description:
*/
#include "dolphin/gx/GXLight.h"
#include "dolphin/gx/GX.h"
#include "math.h"
void GXInitLightAttn(GXLightObj* obj, f32 a0, f32 a1, f32 a2, f32 k0, f32 k1, f32 k2) {
obj->a0 = a0;
obj->a1 = a1;
obj->a2 = a2;
obj->k0 = k0;
obj->k1 = k1;
obj->k2 = k2;
}
void GXInitLightSpot(GXLightObj* obj, f32 cutoff, GXSpotFn spot_fn) {
f32 rad;
f32 a, b, c, d;
if (cutoff <= 0.0f || cutoff > 90.0f) {
spot_fn = GX_SP_OFF;
}
rad = cosf((3.1415927f * cutoff) / 180.0f);
switch (spot_fn) {
case GX_SP_FLAT:
a = -1000.0f * rad;
b = 1000.0f;
c = 0.0f;
break;
case GX_SP_COS:
b = 1.0f / (1.0f - rad);
a = -rad * b;
c = 0.0f;
break;
case GX_SP_COS2:
c = 1.0f / (1.0f - rad);
a = 0.0f;
b = -rad * c;
break;
case GX_SP_SHARP:
d = 1.0f / ((1.0f - rad) * (1.0f - rad));
a = (rad * (rad - 2.0f)) * d;
b = 2.0f * d;
c = -d;
break;
case GX_SP_RING1:
d = 1.0f / ((1.0f - rad) * (1.0f - rad));
c = -4.0f * d;
a = c * rad;
b = 4.0f * (1.0f + rad) * d;
break;
case GX_SP_RING2:
d = 1.0f / ((1.0f - rad) * (1.0f - rad));
a = 1.0f - 2.0f * rad * rad * d;
b = 4.0f * rad * d;
c = -2.0f * d;
break;
case GX_SP_OFF:
default:
a = 1.0f;
b = 0.0f;
c = 0.0f;
break;
}
obj->a0 = a;
obj->a1 = b;
obj->a2 = c;
}
void GXInitLightDistAttn(GXLightObj* obj, f32 dist, f32 brightness, GXDistAttnFn dist_fn) {
f32 a, b, c;
if (dist < 0.0f) {
dist_fn = GX_DA_OFF;
}
if (brightness <= 0.0f || brightness >= 1.0f) {
dist_fn = GX_DA_OFF;
}
switch (dist_fn) {
case GX_DA_GENTLE:
a = 1.0f;
b = (1.0f - brightness) / (brightness * dist);
c = 0.0f;
break;
case GX_DA_MEDIUM:
a = 1.0f;
b = (0.5f * (1.0f - brightness)) / (brightness * dist);
c = (0.5f * (1.0f - brightness)) / (dist * (brightness * dist));
break;
case GX_DA_STEEP:
a = 1.0f;
b = 0.0f;
c = (1.0f - brightness) / (dist * (brightness * dist));
break;
case GX_DA_OFF:
default:
a = 1.0f;
b = 0.0f;
c = 0.0f;
break;
}
obj->k0 = a;
obj->k1 = b;
obj->k2 = c;
}
void GXInitLightPos(GXLightObj* obj, f32 x, f32 y, f32 z) {
obj->posX = x;
obj->posY = y;
obj->posZ = z;
}
void GXInitLightDir(GXLightObj* obj, f32 x, f32 y, f32 z) {
obj->dirX = -x;
obj->dirY = -y;
obj->dirZ = -z;
}
void GXInitLightColor(GXLightObj* obj, GXColor color) {
*(u32*)&obj->color = *(u32*)&color;
}
static inline void PushLight(const register GXLightObj* lt_obj, register void* dest) {
register u32 zero, color;
register f32 a0_a1, a2_k0, k1_k2;
register f32 px_py, pz_dx, dy_dz;
#ifdef __MWERKS__ // clang-format off
asm {
lwz color, 12(lt_obj)
xor zero, zero, zero
psq_l a0_a1, 16(lt_obj), 0, 0
psq_l a2_k0, 24(lt_obj), 0, 0
psq_l k1_k2, 32(lt_obj), 0, 0
psq_l px_py, 40(lt_obj), 0, 0
psq_l pz_dx, 48(lt_obj), 0, 0
psq_l dy_dz, 56(lt_obj), 0, 0
stw zero, 0(dest)
stw zero, 0(dest)
stw zero, 0(dest)
stw color, 0(dest)
psq_st a0_a1, 0(dest), 0, 0
psq_st a2_k0, 0(dest), 0, 0
psq_st k1_k2, 0(dest), 0, 0
psq_st px_py, 0(dest), 0, 0
psq_st pz_dx, 0(dest), 0, 0
psq_st dy_dz, 0(dest), 0, 0
}
#endif // clang-format on
}
void GXLoadLightObjImm(GXLightObj* obj, GXLightID light) {
u32 addr;
u32 idx;
GXLightObj* pObj = (GXLightObj*)obj;
idx = 31 - __cntlzw(light);
idx &= 7;
addr = 0x600 + idx * 0x10;
GX_XF_LOAD_REG_HDR(addr | (0x10 - 1) << 16);
PushLight(pObj, (void*)GXFIFO_ADDR);
__GXData->bpSentNot = 1;
}
void GXSetChanAmbColor(GXChannelID channel, GXColor color) {
u32 reg;
u32 colorID;
u8 alpha;
switch (channel) {
case GX_COLOR0:
reg = __GXData->ambColor[GX_COLOR0];
reg = GX_SET_TRUNC(reg, GXCOLOR_AS_U32(color), 0, 23);
colorID = GX_COLOR0;
break;
case GX_COLOR1:
reg = __GXData->ambColor[GX_COLOR1];
reg = GX_SET_TRUNC(reg, GXCOLOR_AS_U32(color), 0, 23);
colorID = GX_COLOR1;
break;
case GX_ALPHA0:
reg = __GXData->ambColor[GX_COLOR0];
reg = GX_SET_TRUNC(reg, color.a, 24, 31);
colorID = GX_COLOR0;
break;
case GX_ALPHA1:
reg = __GXData->ambColor[GX_COLOR1];
reg = GX_SET_TRUNC(reg, color.a, 24, 31);
colorID = GX_COLOR1;
break;
case GX_COLOR0A0:
reg = GXCOLOR_AS_U32(color);
colorID = GX_COLOR0;
break;
case GX_COLOR1A1:
reg = GXCOLOR_AS_U32(color);
colorID = GX_COLOR1;
break;
default:
return;
}
GX_XF_LOAD_REG(GX_XF_REG_AMBIENT0 + colorID, reg);
__GXData->bpSentNot = GX_TRUE;
__GXData->ambColor[colorID] = reg;
}
void GXSetChanMatColor(GXChannelID channel, GXColor color) {
u32 reg = 0;
GXChannelID colorID;
switch (channel) {
case GX_COLOR0:
reg = __GXData->matColor[GX_COLOR0];
reg = GX_SET_TRUNC(reg, GXCOLOR_AS_U32(color), 0, 23);
colorID = GX_COLOR0;
break;
case GX_COLOR1:
reg = __GXData->matColor[GX_COLOR1];
reg = GX_SET_TRUNC(reg, GXCOLOR_AS_U32(color), 0, 23);
colorID = GX_COLOR1;
break;
case GX_ALPHA0:
reg = __GXData->matColor[GX_COLOR0];
reg = GX_SET_TRUNC(reg, color.a, 24, 31);
colorID = GX_COLOR0;
break;
case GX_ALPHA1:
reg = __GXData->matColor[GX_COLOR1];
reg = GX_SET_TRUNC(reg, color.a, 24, 31);
colorID = GX_COLOR1;
break;
case GX_COLOR0A0:
reg = GXCOLOR_AS_U32(color);
colorID = GX_COLOR0;
break;
case GX_COLOR1A1:
reg = GXCOLOR_AS_U32(color);
colorID = GX_COLOR1;
break;
default:
return;
}
GX_XF_LOAD_REG(GX_XF_REG_MATERIAL0 + colorID, reg);
__GXData->bpSentNot = GX_TRUE;
__GXData->matColor[colorID] = reg;
}
void GXSetNumChans(u8 count) {
GX_SET_REG(__GXData->genMode, count, 25, 27);
GX_XF_LOAD_REG(GX_XF_REG_NUMCOLORS, count);
__GXData->dirtyState |= GX_DIRTY_GEN_MODE;
}
void GXSetChanCtrl(GXChannelID channel, GXBool doEnable, GXColorSrc ambSrc, GXColorSrc matSrc,
u32 mask, GXDiffuseFn diffFunc, GXAttnFn attnFunc) {
const u32 colorID = (u32)channel & 0x3;
u32 reg = 0;
GX_SET_REG(reg, doEnable, GX_XF_CLR0CTRL_LIGHT_ST, GX_XF_CLR0CTRL_LIGHT_END);
GX_SET_REG(reg, matSrc, GX_XF_CLR0CTRL_MTXSRC_ST, GX_XF_CLR0CTRL_MTXSRC_END);
GX_SET_REG(reg, ambSrc, GX_XF_CLR0CTRL_AMBSRC_ST, GX_XF_CLR0CTRL_AMBSRC_END);
GX_SET_REG(reg, (attnFunc == GX_AF_SPEC ? GX_DF_NONE : diffFunc), GX_XF_CLR0CTRL_DIFATTN_ST,
GX_XF_CLR0CTRL_DIFATTN_END);
GX_SET_REG(reg, (attnFunc != GX_AF_NONE), GX_XF_CLR0CTRL_ATTNENABLE_ST,
GX_XF_CLR0CTRL_ATTNENABLE_END);
GX_SET_REG(reg, (attnFunc != GX_AF_SPEC), GX_XF_CLR0CTRL_ATTNSEL_ST,
GX_XF_CLR0CTRL_ATTNSEL_END);
GX_BITFIELD_SET(reg, 26, 4, (u32)mask);
reg = __rlwimi(reg, (u32)mask, 7, 0x11, 0x14);
GX_XF_LOAD_REG(GX_XF_REG_COLOR0CNTRL + colorID, reg);
if (channel == GX_COLOR0A0) {
GX_XF_LOAD_REG(GX_XF_REG_ALPHA0CNTRL, reg);
} else if (channel == GX_COLOR1A1) {
GX_XF_LOAD_REG(GX_XF_REG_ALPHA1CNTRL, reg);
}
__GXData->bpSentNot = GX_TRUE;
}

266
src/dolphin/gx/GXMisc.c Normal file
View File

@ -0,0 +1,266 @@
#include "dolphin/gx/GXMisc.h"
#include "dolphin/gx/GX.h"
#include "dolphin/os/OSInterrupt.h"
#include "dolphin/os/OSReset.h"
#include "dolphin/os/OSTime.h"
static void GXTokenInterruptHandler(__OSInterrupt interrupt, OSContext* context);
static void GXFinishInterruptHandler(__OSInterrupt interrupt, OSContext* pContext);
void GXSetMisc(GXMiscToken token, u32 val) {
switch (token) {
case GX_MT_NULL:
break;
case GX_MT_XF_FLUSH:
__GXData->vNum = val;
__GXData->vNumNot = !__GXData->vNum;
__GXData->bpSentNot = GX_TRUE;
if (__GXData->vNum) {
__GXData->dirtyState |= GX_DIRTY_VCD;
}
break;
case GX_MT_DL_SAVE_CONTEXT:
__GXData->dlSaveContext = (val != 0);
break;
case GX_MT_ABORT_WAIT_COPYOUT:
__GXData->abtWaitPECopy = (val != 0);
break;
}
}
void GXFlush(void) {
if (__GXData->dirtyState) {
__GXSetDirtyState();
}
GXFIFO.u32 = 0;
GXFIFO.u32 = 0;
GXFIFO.u32 = 0;
GXFIFO.u32 = 0;
GXFIFO.u32 = 0;
GXFIFO.u32 = 0;
GXFIFO.u32 = 0;
GXFIFO.u32 = 0;
PPCSync();
}
static void __GXAbortWait(u32 clocks) {
OSTime time0, time1;
time0 = OSGetTime();
do {
time1 = OSGetTime();
} while (time1 - time0 <= clocks / 4);
}
static void __GXAbortWaitPECopyDone(void) {
u32 peCnt0, peCnt1;
peCnt0 = GXReadMEMReg(0x28, 0x27);
do {
peCnt1 = peCnt0;
__GXAbortWait(32);
peCnt0 = GXReadMEMReg(0x28, 0x27);
} while (peCnt0 != peCnt1);
}
void __GXAbort(void) {
if (__GXData->abtWaitPECopy && GXGetGPFifo()) {
__GXAbortWaitPECopyDone();
}
__PIRegs[0x18 / 4] = 1;
__GXAbortWait(200);
__PIRegs[0x18 / 4] = 0;
__GXAbortWait(20);
}
void GXAbortFrame(void) {
__GXAbort();
if (GXGetGPFifo()) {
__GXCleanGPFifo();
__GXInitRevisionBits();
__GXData->dirtyState = 0;
GXFlush();
}
}
/* ############################################################################################## */
static GXDrawSyncCallback TokenCB;
static GXDrawDoneCallback DrawDoneCB;
static GXBool DrawDone;
void GXSetDrawDone(void) {
u8 padding[8];
BOOL restore = OSDisableInterrupts();
GFWriteBPCmd(0x45000002);
GXFlush();
DrawDone = 0;
OSRestoreInterrupts(restore);
}
/* ############################################################################################## */
static OSThreadQueue FinishQueue;
static void GXWaitDrawDone(void) {
BOOL restore = OSDisableInterrupts();
while (DrawDone == 0) {
OSSleepThread(&FinishQueue);
}
OSRestoreInterrupts(restore);
}
void GXDrawDone(void) {
u8 padding[8];
GXSetDrawDone();
GXWaitDrawDone();
}
void GXPixModeSync(void) {
GXFIFO.u8 = 0x61;
GXFIFO.u32 = __GXData->peCtrl;
__GXData->bpSentNot = 0;
}
void GXPokeAlphaMode(GXCompare comp, u8 threshold) {
__peReg[3] = (comp << 8) | threshold;
}
void GXPokeAlphaRead(GXAlphaReadMode mode) {
u32 val = 0;
GX_BITFIELD_SET(val, 0x1e, 2, mode);
GX_BITFIELD_SET(val, 0x1d, 1, 1);
__peReg[4] = val;
}
void GXPokeAlphaUpdate(GXBool enable_update) {
GX_BITFIELD_SET(__peReg[1], 0x1b, 1, enable_update);
}
void GXPokeBlendMode(GXBlendMode mode, GXBlendFactor srcFactor, GXBlendFactor destFactor,
GXLogicOp op) {
u32 reg;
reg = GX_GET_PE_REG(1);
GX_SET_REG(reg, (mode == GX_BM_BLEND) || (mode == GX_BM_SUBTRACT), 31, 31);
GX_SET_REG(reg, (mode == GX_BM_SUBTRACT), 20, 20);
GX_SET_REG(reg, (mode == GX_BM_LOGIC), 30, 30);
GX_SET_REG(reg, op, 16, 19);
GX_SET_REG(reg, srcFactor, 21, 23);
GX_SET_REG(reg, destFactor, 24, 26);
GX_SET_REG(reg, 0x41, 0, 7);
GX_SET_PE_REG(1, reg);
}
void GXPokeColorUpdate(GXBool enable_update) {
GX_BITFIELD_SET(__peReg[1], 0x1c, 1, enable_update);
}
void GXPokeDstAlpha(GXBool enable, u8 alpha) {
u32 val = 0;
GX_BITFIELD_SET(val, 0x18, 8, alpha);
GX_BITFIELD_SET(val, 0x17, 1, enable);
__peReg[2] = val;
}
void GXPokeDither(GXBool enable) {
GX_BITFIELD_SET(__peReg[1], 0x1d, 1, enable);
}
void GXPokeZMode(GXBool enable_compare, GXCompare comp, GXBool update_enable) {
u32 val = 0;
GX_BITFIELD_SET(val, 0x1f, 1, enable_compare);
GX_BITFIELD_SET(val, 0x1c, 3, comp);
GX_BITFIELD_SET(val, 0x1b, 1, update_enable);
__peReg[0] = val;
}
void GXPeekZ(u16 x, u16 y, u32* z) {
u32 addr = 0xc8000000;
GX_BITFIELD_SET(addr, 0x14, 10, x);
GX_BITFIELD_SET(addr, 0xa, 10, y);
GX_BITFIELD_SET(addr, 8, 2, 1);
*z = *(u32*)addr;
}
GXDrawSyncCallback GXSetDrawSyncCallback(GXDrawSyncCallback callback) {
BOOL restore;
GXDrawSyncCallback prevCb = TokenCB;
restore = OSDisableInterrupts();
TokenCB = callback;
OSRestoreInterrupts(restore);
return prevCb;
}
static void GXTokenInterruptHandler(__OSInterrupt interrupt, OSContext* context) {
u16 token;
OSContext exceptContext;
u32 reg;
token = GX_GET_PE_REG(7);
if (TokenCB) {
OSClearContext(&exceptContext);
OSSetCurrentContext(&exceptContext);
TokenCB(token);
OSClearContext(&exceptContext);
OSSetCurrentContext(context);
}
reg = GX_GET_PE_REG(5);
GX_SET_REG(reg, 1, 29, 29);
GX_SET_PE_REG(5, reg);
}
GXDrawDoneCallback GXSetDrawDoneCallback(GXDrawDoneCallback callback) {
BOOL restore;
GXDrawDoneCallback prevCb = DrawDoneCB;
restore = OSDisableInterrupts();
DrawDoneCB = callback;
OSRestoreInterrupts(restore);
return prevCb;
}
static void GXFinishInterruptHandler(__OSInterrupt interrupt, OSContext* context) {
OSContext exceptContext;
u32 reg;
reg = GX_GET_PE_REG(5);
GX_SET_REG(reg, 1, 28, 28);
GX_SET_PE_REG(5, reg);
DrawDone = GX_TRUE;
if (DrawDoneCB) {
OSClearContext(&exceptContext);
OSSetCurrentContext(&exceptContext);
DrawDoneCB();
OSClearContext(&exceptContext);
OSSetCurrentContext(context);
}
OSWakeupThread(&FinishQueue);
}
void __GXPEInit(void) {
u32 val;
__OSSetInterruptHandler(OS_INTR_PI_PE_TOKEN, GXTokenInterruptHandler);
__OSSetInterruptHandler(OS_INTR_PI_PE_FINISH, GXFinishInterruptHandler);
OSInitThreadQueue(&FinishQueue);
__OSUnmaskInterrupts(OS_INTERRUPTMASK_PI_PE_TOKEN);
__OSUnmaskInterrupts(OS_INTERRUPTMASK_PI_PE_FINISH);
val = __peReg[5];
GX_BITFIELD_SET(val, 0x1d, 1, 1);
GX_BITFIELD_SET(val, 0x1c, 1, 1);
GX_BITFIELD_SET(val, 0x1f, 1, 1);
GX_BITFIELD_SET(val, 0x1e, 1, 1);
__peReg[5] = val;
}

384
src/dolphin/gx/GXPerf.c Normal file
View File

@ -0,0 +1,384 @@
#include "dolphin/gx/GXPerf.h"
#include "dolphin/gx/GX.h"
void GXSetGPMetric(GXPerf0 perf0, GXPerf1 perf1) {
switch (__GXData->perf0) {
case GX_PERF0_VERTICES:
case GX_PERF0_CLIP_VTX:
case GX_PERF0_CLIP_CLKS:
case GX_PERF0_XF_WAIT_IN:
case GX_PERF0_XF_WAIT_OUT:
case GX_PERF0_XF_XFRM_CLKS:
case GX_PERF0_XF_LIT_CLKS:
case GX_PERF0_XF_BOT_CLKS:
case GX_PERF0_XF_REGLD_CLKS:
case GX_PERF0_XF_REGRD_CLKS:
case GX_PERF0_CLIP_RATIO:
case GX_PERF0_CLOCKS:
GX_WRITE_U8(0x10);
GX_WRITE_U32(0x1006);
GX_WRITE_U32(0);
break;
case GX_PERF0_TRIANGLES:
case GX_PERF0_TRIANGLES_CULLED:
case GX_PERF0_TRIANGLES_PASSED:
case GX_PERF0_TRIANGLES_SCISSORED:
case GX_PERF0_TRIANGLES_0TEX:
case GX_PERF0_TRIANGLES_1TEX:
case GX_PERF0_TRIANGLES_2TEX:
case GX_PERF0_TRIANGLES_3TEX:
case GX_PERF0_TRIANGLES_4TEX:
case GX_PERF0_TRIANGLES_5TEX:
case GX_PERF0_TRIANGLES_6TEX:
case GX_PERF0_TRIANGLES_7TEX:
case GX_PERF0_TRIANGLES_8TEX:
case GX_PERF0_TRIANGLES_0CLR:
case GX_PERF0_TRIANGLES_1CLR:
case GX_PERF0_TRIANGLES_2CLR:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x23000000);
break;
case GX_PERF0_QUAD_0CVG:
case GX_PERF0_QUAD_NON0CVG:
case GX_PERF0_QUAD_1CVG:
case GX_PERF0_QUAD_2CVG:
case GX_PERF0_QUAD_3CVG:
case GX_PERF0_QUAD_4CVG:
case GX_PERF0_AVG_QUAD_CNT:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x24000000);
break;
case GX_PERF0_NONE:
break;
}
switch (__GXData->perf1) {
case GX_PERF1_TEXELS:
case GX_PERF1_TX_IDLE:
case GX_PERF1_TX_REGS:
case GX_PERF1_TX_MEMSTALL:
case GX_PERF1_TC_CHECK1_2:
case GX_PERF1_TC_CHECK3_4:
case GX_PERF1_TC_CHECK5_6:
case GX_PERF1_TC_CHECK7_8:
case GX_PERF1_TC_MISS:
case GX_PERF1_CLOCKS:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x67000000);
break;
case GX_PERF1_VC_ELEMQ_FULL:
case GX_PERF1_VC_MISSQ_FULL:
case GX_PERF1_VC_MEMREQ_FULL:
case GX_PERF1_VC_STATUS7:
case GX_PERF1_VC_MISSREP_FULL:
case GX_PERF1_VC_STREAMBUF_LOW:
case GX_PERF1_VC_ALL_STALLS:
case GX_PERF1_VERTICES:
FAST_FLAG_SET(__GXData->perfSel, 0, 4, 4);
GX_WRITE_U8(8);
GX_WRITE_U8(32);
GX_WRITE_U32(__GXData->perfSel);
break;
case GX_PERF1_FIFO_REQ:
case GX_PERF1_CALL_REQ:
case GX_PERF1_VC_MISS_REQ:
case GX_PERF1_CP_ALL_REQ:
GX_SET_CP_REG(3, 0);
break;
case GX_PERF1_NONE:
break;
}
__GXData->perf0 = perf0;
switch (__GXData->perf0) {
case GX_PERF0_VERTICES:
GX_WRITE_U8(0x10);
GX_WRITE_U32(0x1006);
GX_WRITE_U32(0x273);
break;
case GX_PERF0_CLIP_VTX:
GX_WRITE_U8(0x10);
GX_WRITE_U32(0x1006);
GX_WRITE_U32(0x14A);
break;
case GX_PERF0_CLIP_CLKS:
GX_WRITE_U8(0x10);
GX_WRITE_U32(0x1006);
GX_WRITE_U32(0x16B);
break;
case GX_PERF0_XF_WAIT_IN:
GX_WRITE_U8(0x10);
GX_WRITE_U32(0x1006);
GX_WRITE_U32(0x84);
break;
case GX_PERF0_XF_WAIT_OUT:
GX_WRITE_U8(0x10);
GX_WRITE_U32(0x1006);
GX_WRITE_U32(0xC6);
break;
case GX_PERF0_XF_XFRM_CLKS:
GX_WRITE_U8(0x10);
GX_WRITE_U32(0x1006);
GX_WRITE_U32(0x210);
break;
case GX_PERF0_XF_LIT_CLKS:
GX_WRITE_U8(0x10);
GX_WRITE_U32(0x1006);
GX_WRITE_U32(0x252);
break;
case GX_PERF0_XF_BOT_CLKS:
GX_WRITE_U8(0x10);
GX_WRITE_U32(0x1006);
GX_WRITE_U32(0x231);
break;
case GX_PERF0_XF_REGLD_CLKS:
GX_WRITE_U8(0x10);
GX_WRITE_U32(0x1006);
GX_WRITE_U32(0x1AD);
break;
case GX_PERF0_XF_REGRD_CLKS:
GX_WRITE_U8(0x10);
GX_WRITE_U32(0x1006);
GX_WRITE_U32(0x1CE);
break;
case GX_PERF0_CLOCKS:
GX_WRITE_U8(0x10);
GX_WRITE_U32(0x1006);
GX_WRITE_U32(0x21);
break;
case GX_PERF0_CLIP_RATIO:
GX_WRITE_U8(0x10);
GX_WRITE_U32(0x1006);
GX_WRITE_U32(0x153);
break;
case GX_PERF0_TRIANGLES:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x2300AE7F);
break;
case GX_PERF0_TRIANGLES_CULLED:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x23008E7F);
break;
case GX_PERF0_TRIANGLES_PASSED:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x23009E7F);
break;
case GX_PERF0_TRIANGLES_SCISSORED:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x23001E7F);
break;
case GX_PERF0_TRIANGLES_0TEX:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x2300AC3F);
break;
case GX_PERF0_TRIANGLES_1TEX:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x2300AC7F);
break;
case GX_PERF0_TRIANGLES_2TEX:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x2300ACBF);
break;
case GX_PERF0_TRIANGLES_3TEX:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x2300ACFF);
break;
case GX_PERF0_TRIANGLES_4TEX:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x2300AD3F);
break;
case GX_PERF0_TRIANGLES_5TEX:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x2300AD7F);
break;
case GX_PERF0_TRIANGLES_6TEX:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x2300ADBF);
break;
case GX_PERF0_TRIANGLES_7TEX:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x2300ADFF);
break;
case GX_PERF0_TRIANGLES_8TEX:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x2300AE3F);
break;
case GX_PERF0_TRIANGLES_0CLR:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x2300A27F);
break;
case GX_PERF0_TRIANGLES_1CLR:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x2300A67F);
break;
case GX_PERF0_TRIANGLES_2CLR:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x2300AA7F);
break;
case GX_PERF0_QUAD_0CVG:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x2402C0C6);
break;
case GX_PERF0_QUAD_NON0CVG:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x2402C16B);
break;
case GX_PERF0_QUAD_1CVG:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x2402C0E7);
break;
case GX_PERF0_QUAD_2CVG:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x2402C108);
break;
case GX_PERF0_QUAD_3CVG:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x2402C129);
break;
case GX_PERF0_QUAD_4CVG:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x2402C14A);
break;
case GX_PERF0_AVG_QUAD_CNT:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x2402C1AD);
break;
case GX_PERF0_NONE:
break;
}
__GXData->perf1 = perf1;
switch (__GXData->perf1) {
case GX_PERF1_TEXELS:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x67000042);
break;
case GX_PERF1_TX_IDLE:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x67000084);
break;
case GX_PERF1_TX_REGS:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x67000063);
break;
case GX_PERF1_TX_MEMSTALL:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x67000129);
break;
case GX_PERF1_TC_MISS:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x67000252);
break;
case GX_PERF1_CLOCKS:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x67000021);
break;
case GX_PERF1_TC_CHECK1_2:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x6700014B);
break;
case GX_PERF1_TC_CHECK3_4:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x6700018D);
break;
case GX_PERF1_TC_CHECK5_6:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x670001CF);
break;
case GX_PERF1_TC_CHECK7_8:
GX_WRITE_U8(0x61);
GX_WRITE_U32(0x67000211);
break;
case GX_PERF1_VC_ELEMQ_FULL:
FAST_FLAG_SET(__GXData->perfSel, 2, 4, 4);
GX_WRITE_U8(8);
GX_WRITE_U8(32);
GX_WRITE_U32(__GXData->perfSel);
break;
case GX_PERF1_VC_MISSQ_FULL:
FAST_FLAG_SET(__GXData->perfSel, 3, 4, 4);
GX_WRITE_U8(8);
GX_WRITE_U8(32);
GX_WRITE_U32(__GXData->perfSel);
break;
case GX_PERF1_VC_MEMREQ_FULL:
FAST_FLAG_SET(__GXData->perfSel, 4, 4, 4);
GX_WRITE_U8(8);
GX_WRITE_U8(32);
GX_WRITE_U32(__GXData->perfSel);
break;
case GX_PERF1_VC_STATUS7:
FAST_FLAG_SET(__GXData->perfSel, 5, 4, 4);
GX_WRITE_U8(8);
GX_WRITE_U8(32);
GX_WRITE_U32(__GXData->perfSel);
break;
case GX_PERF1_VC_MISSREP_FULL:
FAST_FLAG_SET(__GXData->perfSel, 6, 4, 4);
GX_WRITE_U8(8);
GX_WRITE_U8(32);
GX_WRITE_U32(__GXData->perfSel);
break;
case GX_PERF1_VC_STREAMBUF_LOW:
FAST_FLAG_SET(__GXData->perfSel, 7, 4, 4);
GX_WRITE_U8(8);
GX_WRITE_U8(32);
GX_WRITE_U32(__GXData->perfSel);
break;
case GX_PERF1_VC_ALL_STALLS:
FAST_FLAG_SET(__GXData->perfSel, 9, 4, 4);
GX_WRITE_U8(8);
GX_WRITE_U8(32);
GX_WRITE_U32(__GXData->perfSel);
break;
case GX_PERF1_VERTICES:
FAST_FLAG_SET(__GXData->perfSel, 8, 4, 4);
GX_WRITE_U8(8);
GX_WRITE_U8(32);
GX_WRITE_U32(__GXData->perfSel);
break;
case GX_PERF1_FIFO_REQ:
GX_SET_CP_REG(3, 2);
break;
case GX_PERF1_CALL_REQ:
GX_SET_CP_REG(3, 3);
break;
case GX_PERF1_VC_MISS_REQ:
GX_SET_CP_REG(3, 4);
break;
case GX_PERF1_CP_ALL_REQ:
GX_SET_CP_REG(3, 5);
break;
case GX_PERF1_NONE:
break;
}
__GXData->bpSentNot = GX_FALSE;
}
void GXClearGPMetric(void) {
GX_SET_CP_REG(2, 4);
}
#pragma scheduling off
void GXReadXfRasMetric(u32* xfWaitIn, u32* xfWaitOut, u32* rasBusy, u32* clocks) {
*rasBusy = GXReadCPReg(32, 33);
*clocks = GXReadCPReg(34, 35);
*xfWaitIn = GXReadCPReg(36, 37);
*xfWaitOut = GXReadCPReg(38, 39);
}
#pragma scheduling reset

235
src/dolphin/gx/GXPixel.c Normal file
View File

@ -0,0 +1,235 @@
#include "dolphin/gx/GXPixel.h"
#include "dolphin/gx/GX.h"
void GXSetFog(GXFogType type, f32 startz, f32 endz, f32 nearz, f32 farz, GXColor color) {
f32 a, c;
u32 a_bits, c_bits;
u32 fogColorReg = 0;
u32 fogParamReg0 = 0;
u32 fogParamReg1 = 0;
u32 fogParamReg2 = 0;
u32 fogParamReg3 = 0;
u32 fsel = type & 7;
BOOL isOrtho = (type >> 3) & 1;
u32 col;
if (isOrtho) {
if (farz == nearz || endz == startz) {
a = 0.0f;
c = 0.0f;
} else {
a = (1.0f / (endz - startz)) * (farz - nearz);
c = (1.0f / (endz - startz)) * (startz - nearz);
}
} else {
f32 tmpA, tmpB, tmpC;
u32 expB, magB, shiftB;
if (farz == nearz || endz == startz) {
tmpA = 0.0f;
tmpB = 0.5f;
tmpC = 0.0f;
} else {
tmpA = (farz * nearz) / ((farz - nearz) * (endz - startz));
tmpB = farz / (farz - nearz);
tmpC = startz / (endz - startz);
}
expB = 0;
while (tmpB > 1.0) {
tmpB /= 2.0f;
expB++;
}
while (tmpB > 0.0f && tmpB < 0.5) {
tmpB *= 2.0f;
expB--;
}
a = tmpA / (1 << expB + 1);
magB = 8388638.0f * tmpB;
shiftB = expB + 1;
c = tmpC;
GX_SET_REG(fogParamReg1, magB, GX_BP_FOGPARAM1_B_MAG_ST, GX_BP_FOGPARAM1_B_MAG_END);
GX_SET_REG(fogParamReg2, shiftB, GX_BP_FOGPARAM2_B_SHIFT_ST, GX_BP_FOGPARAM2_B_SHIFT_END);
GX_SET_REG(fogParamReg1, GX_BP_REG_FOGPARAM1, 0, 7);
GX_SET_REG(fogParamReg2, GX_BP_REG_FOGPARAM2, 0, 7);
}
a_bits = *(u32*)&a;
c_bits = *(u32*)&c;
GX_SET_REG(fogParamReg0, a_bits >> 12, GX_BP_FOGPARAM0_A_MANT_ST, GX_BP_FOGPARAM0_A_MANT_END);
GX_SET_REG(fogParamReg0, a_bits >> 23, GX_BP_FOGPARAM0_A_EXP_ST, GX_BP_FOGPARAM0_A_EXP_END);
GX_SET_REG(fogParamReg0, a_bits >> 31, GX_BP_FOGPARAM0_A_SIGN_ST, GX_BP_FOGPARAM0_A_SIGN_END);
GX_SET_REG(fogParamReg0, GX_BP_REG_FOGPARAM0, 0, 7);
GX_SET_REG(fogParamReg3, c_bits >> 12, GX_BP_FOGPARAM3_C_MANT_ST, GX_BP_FOGPARAM3_C_MANT_END);
GX_SET_REG(fogParamReg3, c_bits >> 23, GX_BP_FOGPARAM3_C_EXP_ST, GX_BP_FOGPARAM3_C_EXP_END);
GX_SET_REG(fogParamReg3, c_bits >> 31, GX_BP_FOGPARAM3_C_SIGN_ST, GX_BP_FOGPARAM3_C_SIGN_END);
GX_SET_REG(fogParamReg3, isOrtho, GX_BP_FOGPARAM3_PROJ_ST, GX_BP_FOGPARAM3_PROJ_END);
GX_SET_REG(fogParamReg3, fsel, GX_BP_FOGPARAM3_FSEL_ST, GX_BP_FOGPARAM3_FSEL_END);
GX_SET_REG(fogParamReg3, GX_BP_REG_FOGPARAM3, 0, 7);
col = *(u32*)&color;
GX_SET_REG(fogColorReg, col >> 8, GX_BP_FOGCOLOR_RGB_ST, GX_BP_FOGCOLOR_RGB_END);
GX_SET_REG(fogColorReg, GX_BP_REG_FOGCOLOR, 0, 7);
GX_BP_LOAD_REG(fogParamReg0);
GX_BP_LOAD_REG(fogParamReg1);
GX_BP_LOAD_REG(fogParamReg2);
GX_BP_LOAD_REG(fogParamReg3);
GX_BP_LOAD_REG(fogColorReg);
__GXData->bpSentNot = GX_FALSE;
}
void GXSetFogRangeAdj(GXBool enable, u16 center, GXFogAdjTable* table) {
u32 fogRangeReg;
u32 fogRangeRegK;
u32 i;
if (enable) {
for (i = 0; i < 10; i += 2) {
fogRangeRegK = 0;
GX_SET_REG(fogRangeRegK, table->fogVals[i], GX_BP_FOGRANGEK_HI_ST,
GX_BP_FOGRANGEK_HI_END);
GX_SET_REG(fogRangeRegK, table->fogVals[i + 1], GX_BP_FOGRANGEK_LO_ST,
GX_BP_FOGRANGEK_LO_END);
GX_SET_REG(fogRangeRegK, GX_BP_REG_FOGRANGEK0 + (i / 2), 0, 7);
GX_BP_LOAD_REG(fogRangeRegK);
}
}
fogRangeReg = 0;
GX_SET_REG(fogRangeReg, center + 342, GX_BP_FOGRANGE_CENTER_ST, GX_BP_FOGRANGE_CENTER_END);
GX_SET_REG(fogRangeReg, enable, GX_BP_FOGRANGE_ENABLED_ST, GX_BP_FOGRANGE_ENABLED_END);
GX_SET_REG(fogRangeReg, GX_BP_REG_FOGRANGE, 0, 7);
GX_BP_LOAD_REG(fogRangeReg);
__GXData->bpSentNot = GX_FALSE;
}
void GXSetBlendMode(GXBlendMode type, GXBlendFactor src_factor, GXBlendFactor dst_factor,
GXLogicOp op) {
u32 blendModeReg = __GXData->cmode0;
GX_SET_REG(blendModeReg, type == GX_BM_SUBTRACT, GX_BP_BLENDMODE_SUBTRACT_ST,
GX_BP_BLENDMODE_SUBTRACT_END);
GX_SET_REG(blendModeReg, type, GX_BP_BLENDMODE_ENABLE_ST, GX_BP_BLENDMODE_ENABLE_END);
GX_SET_REG(blendModeReg, type == GX_BM_LOGIC, GX_BP_BLENDMODE_LOGIC_OP_ST,
GX_BP_BLENDMODE_LOGIC_OP_END);
GX_SET_REG(blendModeReg, op, GX_BP_BLENDMODE_LOGICMODE_ST, GX_BP_BLENDMODE_LOGICMODE_END);
GX_SET_REG(blendModeReg, src_factor, GX_BP_BLENDMODE_SRCFACTOR_ST,
GX_BP_BLENDMODE_SRCFACTOR_END);
GX_SET_REG(blendModeReg, dst_factor, GX_BP_BLENDMODE_DSTFACTOR_ST,
GX_BP_BLENDMODE_DSTFACTOR_END);
GX_BP_LOAD_REG(blendModeReg);
__GXData->cmode0 = blendModeReg;
__GXData->bpSentNot = FALSE;
}
void GXSetColorUpdate(GXBool updateEnable) {
u32 blendModeReg = __GXData->cmode0;
GX_SET_REG(blendModeReg, updateEnable, GX_BP_BLENDMODE_COLOR_UPDATE_ST,
GX_BP_BLENDMODE_COLOR_UPDATE_END);
GX_BP_LOAD_REG(blendModeReg);
__GXData->cmode0 = blendModeReg;
__GXData->bpSentNot = GX_FALSE;
}
void GXSetAlphaUpdate(GXBool updateEnable) {
u32 blendModeReg = __GXData->cmode0;
GX_SET_REG(blendModeReg, updateEnable, GX_BP_BLENDMODE_ALPHA_UPDATE_ST,
GX_BP_BLENDMODE_ALPHA_UPDATE_END);
GX_BP_LOAD_REG(blendModeReg);
__GXData->cmode0 = blendModeReg;
__GXData->bpSentNot = GX_FALSE;
}
void GXSetZMode(GXBool compareEnable, GXCompare func, GXBool updateEnable) {
u32 zModeReg = __GXData->zmode;
GX_SET_REG(zModeReg, compareEnable, GX_BP_ZMODE_TEST_ENABLE_ST, GX_BP_ZMODE_TEST_ENABLE_END);
GX_SET_REG(zModeReg, func, GX_BP_ZMODE_COMPARE_ST, GX_BP_ZMODE_COMPARE_END);
GX_SET_REG(zModeReg, updateEnable, GX_BP_ZMODE_UPDATE_ENABLE_ST, GX_BP_ZMODE_UPDATE_ENABLE_END);
GX_BP_LOAD_REG(zModeReg);
__GXData->zmode = zModeReg;
__GXData->bpSentNot = GX_FALSE;
}
void GXSetZCompLoc(GXBool beforeTex) {
GX_SET_REG(__GXData->peCtrl, beforeTex, GX_BP_ZCONTROL_BEFORE_TEX_ST,
GX_BP_ZCONTROL_BEFORE_TEX_END);
GX_BP_LOAD_REG(__GXData->peCtrl);
__GXData->bpSentNot = GX_FALSE;
}
void GXSetPixelFmt(GXPixelFmt pixelFmt, GXZFmt16 zFmt) {
GXBool isZ16;
static u32 p2f[GX_PF_MAX] = {GX_PF_RGB8_Z24, GX_PF_RGBA6_Z24, GX_PF_RGB565_Z16, GX_PF_Z24,
GX_PF_Y8, GX_PF_Y8, GX_PF_Y8, GX_PF_U8};
const u32 zControlRegOld = __GXData->peCtrl;
GX_SET_REG(__GXData->peCtrl, p2f[pixelFmt], GX_BP_ZCONTROL_PIXEL_FMT_ST,
GX_BP_ZCONTROL_PIXEL_FMT_END);
GX_SET_REG(__GXData->peCtrl, zFmt, GX_BP_ZCONTROL_Z_FMT_ST, GX_BP_ZCONTROL_Z_FMT_END);
if (zControlRegOld != __GXData->peCtrl) {
GX_BP_LOAD_REG(__GXData->peCtrl);
isZ16 = (pixelFmt == GX_PF_RGB565_Z16) ? GX_TRUE : GX_FALSE;
GX_SET_REG(__GXData->genMode, isZ16, GX_BP_GENMODE_MULTISAMPLE_ST,
GX_BP_GENMODE_MULTISAMPLE_END);
__GXData->dirtyState |= GX_DIRTY_GEN_MODE;
}
if (p2f[pixelFmt] == GX_PF_Y8) {
GX_SET_REG(__GXData->cmode1, pixelFmt - GX_PF_Y8, GX_BP_DSTALPHA_YUV_FMT_ST,
GX_BP_DSTALPHA_YUV_FMT_END);
GX_SET_REG(__GXData->cmode1, GX_BP_REG_DSTALPHA, 0, 7);
GX_BP_LOAD_REG(__GXData->cmode1);
}
__GXData->bpSentNot = FALSE;
}
void GXSetDither(GXBool dither) {
u32 blendModeReg = __GXData->cmode0;
GX_SET_REG(blendModeReg, dither, GX_BP_BLENDMODE_DITHER_ST, GX_BP_BLENDMODE_DITHER_END);
GX_BP_LOAD_REG(blendModeReg);
__GXData->cmode0 = blendModeReg;
__GXData->bpSentNot = GX_FALSE;
}
void GXSetDstAlpha(GXBool enable, u8 alpha) {
u32 dstAlpha = __GXData->cmode1;
GX_SET_REG(dstAlpha, alpha, GX_BP_DSTALPHA_ALPHA_ST, GX_BP_DSTALPHA_ALPHA_END);
GX_SET_REG(dstAlpha, enable, GX_BP_DSTALPHA_ENABLE_ST, GX_BP_DSTALPHA_ENABLE_END);
GX_BP_LOAD_REG(dstAlpha);
__GXData->cmode1 = dstAlpha;
__GXData->bpSentNot = GX_FALSE;
}
void GXSetFieldMask(GXBool enableEven, GXBool enableOdd) {
u32 fieldMaskReg = 0;
GX_SET_REG(fieldMaskReg, enableOdd, GX_BP_FIELDMASK_ODD_ST, GX_BP_FIELDMASK_ODD_END);
GX_SET_REG(fieldMaskReg, enableEven, GX_BP_FIELDMASK_EVEN_ST, GX_BP_FIELDMASK_EVEN_END);
GX_SET_REG(fieldMaskReg, GX_BP_REG_FIELDMASK, 0, 7);
GX_BP_LOAD_REG(fieldMaskReg);
__GXData->bpSentNot = GX_FALSE;
}
void GXSetFieldMode(GXBool texLOD, GXBool adjustAR) {
GX_SET_REG(__GXData->lpSize, adjustAR, GX_BP_LINEPTWIDTH_ADJUST_ST,
GX_BP_LINEPTWIDTH_ADJUST_END);
GX_BP_LOAD_REG(__GXData->lpSize);
__GXFlushTextureState();
GX_BP_LOAD_REG(GX_BP_REG_FIELDMODE << 24 | texLOD);
__GXFlushTextureState();
}

366
src/dolphin/gx/GXTev.c Normal file
View File

@ -0,0 +1,366 @@
#include "dolphin/gx/GXTev.h"
#include "dolphin/gx/GX.h"
/* ############################################################################################## */
static u32 TEVCOpTableST0[] = {
0xC008F8AF, // modulate
0xC008A89F, // decal
0xC008AC8F, // blend
0xC008FFF8, // replace
0xC008FFFA, // passclr
};
static u32 TEVCOpTableST1[] = {
0xC008F80F, // modulate
0xC008089F, // decal
0xC0080C8F, // blend
0xC008FFF8, // replace
0xC008FFF0, // passclr
};
static u32 TEVAOpTableST0[] = {
0xC108F2F0, // modulate
0xC108FFD0, // decal
0xC108F2F0, // blend
0xC108FFC0, // replace
0xC108FFD0, // passclr
};
static u32 TEVAOpTableST1[] = {
0xC108F070, // modulate
0xC108FF80, // decal
0xC108F070, // blend
0xC108FFC0, // replace
0xC108FF80, // passclr
};
void GXSetTevOp(GXTevStageID stage, GXTevMode mode) {
u32* color;
u32* alpha;
u32 tevReg;
if (stage == GX_TEVSTAGE0) {
color = &TEVCOpTableST0[mode];
alpha = &TEVAOpTableST0[mode];
} else {
color = &TEVCOpTableST1[mode];
alpha = &TEVAOpTableST1[mode];
}
tevReg = __GXData->tevc[stage];
tevReg = (*color & ~0xFF000000) | (tevReg & 0xFF000000);
GX_WRITE_U8(0x61);
GX_WRITE_U32(tevReg);
__GXData->tevc[stage] = tevReg;
tevReg = __GXData->teva[stage];
tevReg = (*alpha & ~0xFF00000F) | (tevReg & 0xFF00000F);
GX_WRITE_U8(0x61);
GX_WRITE_U32(tevReg);
__GXData->teva[stage] = tevReg;
__GXData->bpSentNot = GX_FALSE;
}
void GXSetTevColorIn(GXTevStageID stage, GXTevColorArg a, GXTevColorArg b, GXTevColorArg c,
GXTevColorArg d) {
u32 tevReg;
tevReg = __GXData->tevc[stage];
FAST_FLAG_SET(tevReg, a, 12, 4);
FAST_FLAG_SET(tevReg, b, 8, 4);
FAST_FLAG_SET(tevReg, c, 4, 4);
FAST_FLAG_SET(tevReg, d, 0, 4);
GX_WRITE_U8(0x61);
GX_WRITE_U32(tevReg);
__GXData->tevc[stage] = tevReg;
__GXData->bpSentNot = GX_FALSE;
}
void GXSetTevAlphaIn(GXTevStageID stage, GXTevAlphaArg a, GXTevAlphaArg b, GXTevAlphaArg c,
GXTevAlphaArg d) {
u32 tevReg;
tevReg = __GXData->teva[stage];
FAST_FLAG_SET(tevReg, a, 13, 3);
FAST_FLAG_SET(tevReg, b, 10, 3);
FAST_FLAG_SET(tevReg, c, 7, 3);
FAST_FLAG_SET(tevReg, d, 4, 3);
GX_WRITE_U8(0x61);
GX_WRITE_U32(tevReg);
__GXData->teva[stage] = tevReg;
__GXData->bpSentNot = GX_FALSE;
}
void GXSetTevColorOp(GXTevStageID stage, GXTevOp op, GXTevBias bias, GXTevScale scale,
GXBool doClamp, GXTevRegID outReg) {
u32 tevReg;
tevReg = __GXData->tevc[stage];
FAST_FLAG_SET(tevReg, op & 1, 18, 1);
if (op <= 1) {
FAST_FLAG_SET(tevReg, scale, 20, 2);
FAST_FLAG_SET(tevReg, bias, 16, 2);
} else {
FAST_FLAG_SET(tevReg, (op >> 1) & 3, 20, 2);
FAST_FLAG_SET(tevReg, 3, 16, 2);
}
FAST_FLAG_SET(tevReg, doClamp, 19, 1);
FAST_FLAG_SET(tevReg, outReg, 22, 2);
GX_WRITE_U8(0x61);
GX_WRITE_U32(tevReg);
__GXData->tevc[stage] = tevReg;
__GXData->bpSentNot = GX_FALSE;
}
void GXSetTevAlphaOp(GXTevStageID stage, GXTevOp op, GXTevBias bias, GXTevScale scale,
GXBool doClamp, GXTevRegID outReg) {
u32 tevReg;
tevReg = __GXData->teva[stage];
FAST_FLAG_SET(tevReg, op & 1, 18, 1);
if (op <= 1) {
FAST_FLAG_SET(tevReg, scale, 20, 2);
FAST_FLAG_SET(tevReg, bias, 16, 2);
} else {
FAST_FLAG_SET(tevReg, (op >> 1) & 3, 20, 2);
FAST_FLAG_SET(tevReg, 3, 16, 2);
}
FAST_FLAG_SET(tevReg, doClamp, 19, 1);
FAST_FLAG_SET(tevReg, outReg, 22, 2);
GX_WRITE_U8(0x61);
GX_WRITE_U32(tevReg);
__GXData->teva[stage] = tevReg;
__GXData->bpSentNot = GX_FALSE;
}
void GXSetTevColor(GXTevRegID reg, GXColor color) {
u32 col = *(u32*)&color;
u32 ra = (0xE0 + reg * 2) << 24;
u32 bg = (0xE1 + reg * 2) << 24;
GX_SET_REG(ra, col >> 24, 24, 31);
GX_SET_REG(bg, col >> 8, 24, 31);
GX_SET_REG(bg, col >> 16, 12, 19);
GX_SET_REG(ra, col & 0xFF, 12, 19);
GX_BP_LOAD_REG(ra);
GX_BP_LOAD_REG(bg);
GX_BP_LOAD_REG(bg);
GX_BP_LOAD_REG(bg);
__GXData->bpSentNot = GX_FALSE;
}
void GXSetTevColorS10(GXTevRegID reg, GXColorS10 color) {
u32 col = *(u32*)&color;
u32 col1 = ((u32*)&color)[1];
u32 ra = (0xE0 + reg * 2) << 24;
u32 bg = (0xE1 + reg * 2) << 24;
GX_SET_REG(ra, col >> 16, 21, 31);
GX_SET_REG(bg, col1 >> 16, 21, 31);
GX_SET_REG(bg, col & 0x7FF, 9, 19);
GX_SET_REG(ra, col1 & 0x7FF, 9, 19);
GX_BP_LOAD_REG(ra);
GX_BP_LOAD_REG(bg);
GX_BP_LOAD_REG(bg);
GX_BP_LOAD_REG(bg);
__GXData->bpSentNot = GX_FALSE;
}
void GXSetTevKColor(GXTevKColorID id, GXColor color) {
u32 col = *(u32*)&color;
u32 ra;
u32 bg;
ra = (0xE0 + id * 2) << 24;
GX_SET_REG(ra, col >> 24, 24, 31);
GX_SET_REG(ra, col & 0xFF, 12, 19);
GX_SET_REG(ra, 8, 8, 11);
bg = (0xE1 + id * 2) << 24;
GX_SET_REG(bg, col >> 8, 24, 31);
GX_SET_REG(bg, col >> 16, 12, 19);
GX_SET_REG(bg, 8, 8, 11);
GX_BP_LOAD_REG(ra);
GX_BP_LOAD_REG(bg);
__GXData->bpSentNot = GX_FALSE;
}
void GXSetTevKColorSel(GXTevStageID stage, GXTevKColorSel sel) {
u32* reg;
reg = &__GXData->tevKsel[stage >> 1];
if (stage & 1) {
GX_SET_REG(*reg, sel, 13, 17);
} else {
GX_SET_REG(*reg, sel, 23, 27);
}
GX_BP_LOAD_REG(*reg);
__GXData->bpSentNot = GX_FALSE;
}
void GXSetTevKAlphaSel(GXTevStageID stage, GXTevKAlphaSel sel) {
u32* reg;
reg = &__GXData->tevKsel[stage >> 1];
if (stage & 1) {
GX_SET_REG(*reg, sel, 8, 12);
} else {
GX_SET_REG(*reg, sel, 18, 22);
}
GX_BP_LOAD_REG(*reg);
__GXData->bpSentNot = GX_FALSE;
}
void GXSetTevSwapMode(GXTevStageID stage, GXTevSwapSel rasSel, GXTevSwapSel texSel) {
u32* reg = &__GXData->teva[stage];
GX_SET_REG(*reg, rasSel, 30, 31);
GX_SET_REG(*reg, texSel, 28, 29);
GX_BP_LOAD_REG(*reg);
__GXData->bpSentNot = GX_FALSE;
}
void GXSetTevSwapModeTable(GXTevSwapSel table, GXTevColorChan red, GXTevColorChan green,
GXTevColorChan blue, GXTevColorChan alpha) {
u32* reg;
reg = &__GXData->tevKsel[table << 1];
GX_SET_REG(*reg, red, 30, 31);
GX_SET_REG(*reg, green, 28, 29);
GX_BP_LOAD_REG(*reg);
reg = &__GXData->tevKsel[(table << 1) + 1];
GX_SET_REG(*reg, blue, 30, 31);
GX_SET_REG(*reg, alpha, 28, 29);
GX_BP_LOAD_REG(*reg);
__GXData->bpSentNot = GX_FALSE;
}
void GXSetAlphaCompare(GXCompare comp0, u8 ref0, GXAlphaOp op, GXCompare comp1, u8 ref1) {
u32 reg = 0xF3000000;
GX_SET_REG(reg, ref0, 24, 31);
GX_SET_REG(reg, ref1, 16, 23);
GX_SET_REG(reg, comp0, 13, 15);
GX_SET_REG(reg, comp1, 10, 12);
GX_SET_REG(reg, op, 8, 9);
GX_BP_LOAD_REG(reg);
__GXData->bpSentNot = GX_FALSE;
}
void GXSetZTexture(GXZTexOp op, GXTexFmt format, u32 bias) {
u32 val1;
u32 val2;
u32 val3;
val1 = 0;
GX_SET_REG(val1, bias, 8, 31);
GX_SET_REG(val1, 0xF4, 0, 7);
val2 = 0;
switch (format) {
case GX_TF_Z8:
val3 = 0;
break;
case GX_TF_Z16:
val3 = 1;
break;
case GX_TF_Z24X8:
val3 = 2;
break;
default:
val3 = 2;
break;
}
GX_SET_REG(val2, val3, 30, 31);
GX_SET_REG(val2, op, 28, 29);
GX_SET_REG(val2, 0xF5, 0, 7);
GX_BP_LOAD_REG(val1);
GX_BP_LOAD_REG(val2);
__GXData->bpSentNot = GX_FALSE;
}
void GXSetTevOrder(GXTevStageID stage, GXTexCoordID coord, GXTexMapID map, GXChannelID color) {
static int c2r[] = {0, 1, 0, 1, 0, 1, 7, 5, 6};
u32* reg;
u32 tempMap;
u32 tempCoord;
reg = &__GXData->tref[stage / 2];
__GXData->texmapId[stage] = map;
tempMap = map & ~0x100;
tempMap = (tempMap >= GX_MAX_TEXMAP) ? GX_TEXMAP0 : tempMap;
if (coord >= GX_MAXCOORD) {
tempCoord = GX_TEXCOORD0;
__GXData->tevTcEnab = __GXData->tevTcEnab & ~(1 << stage);
} else {
tempCoord = coord;
__GXData->tevTcEnab = __GXData->tevTcEnab | (1 << stage);
}
if (stage & 1) {
GX_SET_REG(*reg, tempMap, 17, 19);
GX_SET_REG(*reg, tempCoord, 14, 16);
GX_SET_REG(*reg, (color == GX_COLOR_NULL ? 7 : c2r[color]), 10, 12);
GX_SET_REG(*reg, ((map != GX_TEXMAP_NULL) && !(map & 0x100)), 13, 13);
} else {
GX_SET_REG(*reg, tempMap, 29, 31);
GX_SET_REG(*reg, tempCoord, 26, 28);
GX_SET_REG(*reg, (color == GX_COLOR_NULL ? 7 : c2r[color]), 22, 24);
GX_SET_REG(*reg, ((map != GX_TEXMAP_NULL) && !(map & 0x100)), 25, 25);
}
GX_BP_LOAD_REG(*reg);
__GXData->bpSentNot = GX_FALSE;
__GXData->dirtyState |= 1;
}
void GXSetNumTevStages(u8 count) {
GX_SET_REG(__GXData->genMode, count - 1, 18, 21);
__GXData->dirtyState |= 0x4;
}

593
src/dolphin/gx/GXTexture.c Normal file
View File

@ -0,0 +1,593 @@
#include "dolphin/gx/GXTexture.h"
#include "dolphin/gx/GX.h"
#define GET_TILE_COUNT(a, b) (((a) + (1 << (b)) - 1) >> (b))
inline void __GXGetTexTileShift(GXTexFmt format, u32* widthTiles, u32* heightTiles) {
switch (format) {
case GX_TF_I4:
case GX_TF_C4:
case GX_TF_CMPR:
case GX_CTF_R4:
case GX_CTF_Z4:
*widthTiles = 3;
*heightTiles = 3;
break;
case GX_TF_I8:
case GX_TF_IA4:
case GX_TF_C8:
case GX_TF_Z8:
case GX_CTF_RA4:
case GX_CTF_R8:
case GX_CTF_G8:
case GX_CTF_B8:
case GX_CTF_RG8:
case GX_CTF_Z8M:
case GX_CTF_Z8L:
*widthTiles = 3;
*heightTiles = 2;
break;
case GX_TF_IA8:
case GX_TF_RGB565:
case GX_TF_RGB5A3:
case GX_TF_RGBA8:
case GX_TF_C14X2:
case GX_TF_Z16:
case GX_TF_Z24X8:
case GX_CTF_RA8:
case GX_CTF_GB8:
case 44:
case GX_CTF_Z16L:
*widthTiles = 2;
*heightTiles = 2;
break;
default:
*heightTiles = 0;
*widthTiles = 0;
break;
}
}
u32 GXGetTexBufferSize(u16 width, u16 height, u32 format, GXBool mipmap, u8 max_lod) {
u32 widthTiles, heightTiles, tileSize, bufferSize, numX, numY, i;
__GXGetTexTileShift(format, &widthTiles, &heightTiles);
if (format == GX_TF_RGBA8 || format == GX_TF_Z24X8) {
tileSize = 0x40;
} else {
tileSize = 0x20;
}
if (mipmap == GX_TRUE) {
bufferSize = 0;
for (i = 0; i < max_lod; i++) {
numX = GET_TILE_COUNT(width, widthTiles);
numY = GET_TILE_COUNT(height, heightTiles);
bufferSize += numX * numY * tileSize;
if (width == 1 && height == 1) {
break;
}
width = (width > 1) ? (width >> 1) : 1;
height = (height > 1) ? (height >> 1) : 1;
}
} else {
numX = GET_TILE_COUNT(width, widthTiles);
numY = GET_TILE_COUNT(height, heightTiles);
bufferSize = numX * numY * tileSize;
}
return bufferSize;
}
void __GetImageTileCount(GXTexFmt format, u16 width, u16 height, u32* a, u32* b, u32* c) {
u32 widthTiles, heightTiles;
__GXGetTexTileShift(format, &widthTiles, &heightTiles);
if (width <= 0) {
width = 1;
}
if (height <= 0) {
height = 1;
}
*a = GET_TILE_COUNT(width, widthTiles);
*b = GET_TILE_COUNT(height, heightTiles);
*c = (format == GX_TF_RGBA8 || format == GX_TF_Z24X8) ? 2 : 1;
}
void GXInitTexObj(GXTexObj* obj, void* imagePtr, u16 width, u16 height, GXTexFmt format,
GXTexWrapMode sWrap, GXTexWrapMode tWrap, GXBool useMIPmap) {
u32 imageBase;
u16 a, b;
u32 c, d;
GXTexObj* internal = (GXTexObj*)obj;
memset(internal, 0, sizeof(*internal));
GX_SET_REG(internal->texture_filter, sWrap, 30, 31);
GX_SET_REG(internal->texture_filter, tWrap, 28, 29);
GX_SET_REG(internal->texture_filter, GX_TRUE, 27, 27);
if (useMIPmap) {
u32 maxDimSize;
internal->texture_flags |= 1;
if (format == 8 || format == 9 || format == 10) {
GX_SET_REG(internal->texture_filter, 5, 24, 26);
} else {
GX_SET_REG(internal->texture_filter, 6, 24, 26);
}
maxDimSize = width > height ? 31 - __cntlzw(width) : 31 - __cntlzw(height);
GX_SET_REG(internal->texture_lod, (maxDimSize) * 16.f, 16, 23);
} else {
GX_SET_REG(internal->texture_filter, 4, 24, 26);
}
internal->texture_format = format;
GX_SET_REG(internal->texture_size, width - 1, 22, 31);
GX_SET_REG(internal->texture_size, height - 1, 12, 21);
GX_SET_REG(internal->texture_size, format & 0xf, 8, 11);
imageBase = (u32)imagePtr >> 5;
GX_SET_REG(internal->texture_address, imageBase, 11, 31);
switch (format & 0xf) {
case 0:
case 8:
internal->texture_tile_type = 1;
a = 3;
b = 3;
break;
case 1:
case 2:
case 9:
internal->texture_tile_type = 2;
a = 3;
b = 2;
break;
case 3:
case 4:
case 5:
case 10:
internal->texture_tile_type = 2;
a = 2;
b = 2;
break;
case 6:
internal->texture_tile_type = 3;
a = 2;
b = 2;
break;
case 0xe:
internal->texture_tile_type = 0;
a = 3;
b = 3;
break;
default:
internal->texture_tile_type = 2;
a = 2;
b = 2;
break;
}
internal->texture_time_count = (GET_TILE_COUNT(width, a) * GET_TILE_COUNT(height, b)) & 0x7fff;
internal->texture_flags |= 2;
}
void GXInitTexObjCI(GXTexObj* obj, void* imagePtr, u16 width, u16 height, GXCITexFmt format,
GXTexWrapMode sWrap, GXTexWrapMode tWrap, GXBool useMIPmap, u32 tlut_name) {
GXTexObj* internal = (GXTexObj*)obj;
GXInitTexObj(obj, imagePtr, width, height, format, sWrap, tWrap, useMIPmap);
internal->texture_flags &= ~2;
internal->tlut_name = tlut_name;
}
u8 GXTexMode0Ids[8] = {0x80, 0x81, 0x82, 0x83, 0xA0, 0xA1, 0xA2, 0xA3};
u8 GXTexMode1Ids[8] = {0x84, 0x85, 0x86, 0x87, 0xA4, 0xA5, 0xA6, 0xA7};
u8 GXTexImage0Ids[8] = {0x88, 0x89, 0x8a, 0x8b, 0xA8, 0xA9, 0xAa, 0xAb};
u8 GXTexImage1Ids[8] = {0x8c, 0x8d, 0x8e, 0x8f, 0xAc, 0xAd, 0xAe, 0xAf};
u8 GXTexImage2Ids[8] = {0x90, 0x91, 0x92, 0x93, 0xB0, 0xB1, 0xB2, 0xB3};
u8 GXTexImage3Ids[8] = {0x94, 0x95, 0x96, 0x97, 0xB4, 0xB5, 0xB6, 0xB7};
u8 GXTexTlutIds[8] = {0x98, 0x99, 0x9a, 0x9b, 0xB8, 0xB9, 0xBa, 0xBb};
u8 GX2HWFiltConv[6] = {0x00, 0x04, 0x01, 0x05, 0x02, 0x06};
void GXInitTexObjLOD(GXTexObj* obj, GXTexFilter minFilter, GXTexFilter maxFilter, f32 minLOD,
f32 maxLOD, f32 lodBias, GXBool doBiasClamp, GXBool doEdgeLOD,
GXAnisotropy maxAniso) {
GXTexObj* internal = (GXTexObj*)obj;
u8 reg1, reg2;
if (lodBias < -4.0f) {
lodBias = -4.0f;
} else if (lodBias >= 4.0f) {
lodBias = 3.99f;
}
GX_SET_REG(internal->texture_filter, lodBias * 32.0f, 15, 22);
GX_SET_REG(internal->texture_filter, maxFilter == 1 ? 1 : 0, 27, 27);
GX_SET_REG(internal->texture_filter, GX2HWFiltConv[minFilter], 24, 26);
GX_SET_REG(internal->texture_filter, doEdgeLOD ? 0 : 1, 23, 23);
GX_SET_REG(internal->texture_filter, 0, 14, 14);
GX_SET_REG(internal->texture_filter, 0, 13, 13);
GX_SET_REG(internal->texture_filter, maxAniso, 11, 12);
GX_SET_REG(internal->texture_filter, doBiasClamp, 10, 10);
if (minLOD < 0.0f) {
minLOD = 0.0f;
} else if (minLOD > 10.0f) {
minLOD = 10.0f;
}
reg1 = minLOD * 16.0f;
if (maxLOD < 0.0f) {
maxLOD = 0.0f;
} else if (maxLOD > 10.0f) {
maxLOD = 10.0f;
}
reg2 = maxLOD * 16.0f;
GX_SET_REG(internal->texture_lod, reg1, 24, 31);
GX_SET_REG(internal->texture_lod, reg2, 16, 23);
}
u16 GXGetTexObjWidth(GXTexObj* obj) {
return (obj->texture_size & 0x3ff) + 1;
}
u16 GXGetTexObjHeight(GXTexObj* obj) {
return ((obj->texture_size >> 10) & 0x3ff) + 1;
}
GXTexFmt GXGetTexObjFmt(const GXTexObj* obj) {
return obj->texture_format;
}
GXTexWrapMode GXGetTexObjWrapS(GXTexObj* obj) {
return obj->texture_filter & 0x3;
}
GXTexWrapMode GXGetTexObjWrapT(GXTexObj* obj) {
return (obj->texture_filter & 0xc) >> 2;
}
GXBool GXGetTexObjMipMap(const GXTexObj* obj) {
return (obj->texture_flags & 1) == 1;
}
u32 GXGetTexObjTlut(GXTexObj* obj) {
return obj->tlut_name;
}
void GXLoadTexObjPreLoaded(GXTexObj* obj, GXTexRegion* region, GXTexMapID map) {
u8 stackManipulation[0x18];
GXTexObj* internalObj = (GXTexObj*)obj;
GXTexRegion* internalRegion = (GXTexRegion*)region;
GX_SET_REG(internalObj->texture_filter, GXTexMode0Ids[map], 0, 7);
GX_SET_REG(internalObj->texture_lod, GXTexMode1Ids[map], 0, 7);
GX_SET_REG(internalObj->texture_size, GXTexImage0Ids[map], 0, 7);
GX_SET_REG(internalRegion->unk0, GXTexImage1Ids[map], 0, 7);
GX_SET_REG(internalRegion->unk4, GXTexImage2Ids[map], 0, 7);
GX_SET_REG(internalObj->texture_address, GXTexImage3Ids[map], 0, 7);
GX_BP_LOAD_REG(internalObj->texture_filter);
GX_BP_LOAD_REG(internalObj->texture_lod);
GX_BP_LOAD_REG(internalObj->texture_size);
GX_BP_LOAD_REG(internalRegion->unk0);
GX_BP_LOAD_REG(internalRegion->unk4);
GX_BP_LOAD_REG(internalObj->texture_address);
if ((internalObj->texture_flags & 2) == 0) {
GXTlutObj* tlut = (GXTlutObj*)__GXData->tlutRegionCallback(internalObj->tlut_name);
GX_SET_REG(tlut->address, GXTexTlutIds[map], 0, 7);
GX_BP_LOAD_REG(tlut->address);
}
__GXData->tImage0[map] = internalObj->texture_size;
__GXData->tMode0[map] = internalObj->texture_filter;
__GXData->dirtyState |= GX_DIRTY_SU_TEX;
__GXData->bpSentNot = GX_FALSE;
}
void GXLoadTexObj(GXTexObj* obj, GXTexMapID map) {
GXTexRegion* ret = (GXTexRegion*)__GXData->texRegionCallback(obj, map);
GXLoadTexObjPreLoaded(obj, ret, map);
}
void GXInitTlutObj(GXTlutObj* obj, void* table, GXTlutFmt format, u16 numEntries) {
GXTlutObj* internal = (GXTlutObj*)obj;
internal->format = 0;
GX_SET_REG(internal->format, format, 20, 21);
GX_SET_REG(internal->address, (u32)table >> 5, 11, 31);
GX_SET_REG(internal->address, 100, 0, 7);
internal->numEntries = numEntries;
}
void GXLoadTlut(GXTlutObj* obj, u32 tlut_name) {
GXTlutObj* internal = (GXTlutObj*)obj;
GXTlutRegion* ret = (GXTlutRegion*)__GXData->tlutRegionCallback(tlut_name);
u32 reg;
__GXFlushTextureState();
GX_BP_LOAD_REG(internal->address);
GX_BP_LOAD_REG(ret->unk0);
__GXFlushTextureState();
reg = ret->unk0;
GX_SET_REG(internal->format, reg, 22, 31);
ret->tlutObj = *internal;
}
void GXInitTexCacheRegion(GXTexRegion* region, GXBool is32bMIPmap, u32 memEven,
GXTexCacheSize sizeEven, u32 memOdd, GXTexCacheSize sizeOdd) {
GXTexRegion* internal = (GXTexRegion*)region;
u32 reg;
switch (sizeEven) {
case 0:
reg = 3;
break;
case 1:
reg = 4;
break;
case 2:
reg = 5;
break;
}
internal->unk0 = 0;
GX_SET_REG(internal->unk0, memEven >> 5, 17, 31);
GX_SET_REG(internal->unk0, reg, 14, 16);
GX_SET_REG(internal->unk0, reg, 11, 13);
GX_SET_REG(internal->unk0, 0, 10, 10);
switch (sizeOdd) {
case 0:
reg = 3;
break;
case 1:
reg = 4;
break;
case 2:
reg = 5;
break;
case 3:
reg = 0;
break;
}
internal->unk4 = 0;
GX_SET_REG(internal->unk4, memOdd >> 5, 17, 31);
GX_SET_REG(internal->unk4, reg, 14, 16);
GX_SET_REG(internal->unk4, reg, 11, 13);
internal->unkC = is32bMIPmap;
internal->unkD = 1;
}
void GXInitTlutRegion(GXTlutRegion* region, u32 memAddr, GXTlutSize tlutSize) {
GXTlutRegion* internal = (GXTlutRegion*)region;
internal->unk0 = 0;
GX_SET_REG(internal->unk0, (memAddr - 0x80000) >> 9, 22, 31);
GX_SET_REG(internal->unk0, tlutSize, 11, 21);
GX_SET_REG(internal->unk0, 0x65, 0, 7);
}
void GXInvalidateTexAll(void) {
__GXFlushTextureState();
GXFIFO.u8 = 0x61;
GXFIFO.u32 = 0x66001000;
GXFIFO.u8 = 0x61;
GXFIFO.u32 = 0x66001100;
__GXFlushTextureState();
}
GXTexRegionCallback GXSetTexRegionCallback(GXTexRegionCallback callback) {
GXTexRegionCallback prev = __GXData->texRegionCallback;
__GXData->texRegionCallback = callback;
return prev;
}
GXTlutRegionCallback GXSetTlutRegionCallback(GXTlutRegionCallback callback) {
GXTlutRegionCallback prev = __GXData->tlutRegionCallback;
__GXData->tlutRegionCallback = callback;
return prev;
}
void GXSetTexCoordScaleManually(GXTexCoordID coord, GXBool enable, u16 s_scale, u16 t_scale) {
/* Nonmatching */
}
void __SetSURegs(u32 texImgIndex, u32 setUpRegIndex) {
u16 a1, a2;
GXBool b, c;
a1 = GX_GET_REG(__GXData->tImage0[texImgIndex], 22, 31);
a2 = (__GXData->tImage0[texImgIndex] & (0x3ff << 10)) >> 10;
GX_SET_REG(__GXData->suTs0[setUpRegIndex], a1, 16, 31);
GX_SET_REG(__GXData->suTs1[setUpRegIndex], a2, 16, 31);
b = GX_GET_REG(__GXData->tMode0[texImgIndex], 30, 31) == 1;
c = GX_GET_REG(__GXData->tMode0[texImgIndex], 28, 29) == 1;
GX_SET_REG(__GXData->suTs0[setUpRegIndex], b, 15, 15);
GX_SET_REG(__GXData->suTs1[setUpRegIndex], c, 15, 15);
GX_BP_LOAD_REG(__GXData->suTs0[setUpRegIndex]);
GX_BP_LOAD_REG(__GXData->suTs1[setUpRegIndex]);
__GXData->bpSentNot = GX_FALSE;
}
#pragma dont_inline on
void __GXSetSUTexRegs(void) {
u32 i;
u32 b;
u32 a;
u32 c;
u32 d;
u32 stackFiller;
if (__GXData->tcsManEnab != 0xff) {
a = GX_GET_REG(__GXData->genMode, 18, 21) + 1;
b = GX_GET_REG(__GXData->genMode, 13, 15);
for (i = 0; i < b; i++) {
switch (i) {
case 0:
c = GX_GET_REG(__GXData->iref, 29, 31);
d = GX_GET_REG(__GXData->iref, 26, 28);
break;
case 1:
c = GX_GET_REG(__GXData->iref, 23, 25);
d = GX_GET_REG(__GXData->iref, 20, 22);
break;
case 2:
c = GX_GET_REG(__GXData->iref, 17, 19);
d = GX_GET_REG(__GXData->iref, 14, 16);
break;
case 3:
c = GX_GET_REG(__GXData->iref, 11, 13);
d = GX_GET_REG(__GXData->iref, 8, 10);
break;
}
if (!(__GXData->tcsManEnab & (1 << d))) {
__SetSURegs(c, d);
}
}
for (i = 0; i < a; i++) {
u32* g = &__GXData->tref[i / 2];
c = __GXData->texmapId[i] & ~0x100;
if (i & 1) {
d = GX_GET_REG(*g, 14, 16);
} else {
d = GX_GET_REG(*g, 26, 28);
}
if (c != 0xff && !(__GXData->tcsManEnab & (1 << d)) && __GXData->tevTcEnab & (1 << i)) {
__SetSURegs(c, d);
}
}
}
}
#pragma dont_inline reset
void __GXSetTmemConfig(u32 config) {
switch (config) {
case 2:
GX_BP_LOAD_REG(0x8c0d8000);
GX_BP_LOAD_REG(0x900dc000);
GX_BP_LOAD_REG(0x8d0d8800);
GX_BP_LOAD_REG(0x910dc800);
GX_BP_LOAD_REG(0x8e0d9000);
GX_BP_LOAD_REG(0x920dd000);
GX_BP_LOAD_REG(0x8f0d9800);
GX_BP_LOAD_REG(0x930dd800);
GX_BP_LOAD_REG(0xac0da000);
GX_BP_LOAD_REG(0xb00dc400);
GX_BP_LOAD_REG(0xad0da800);
GX_BP_LOAD_REG(0xb10dcc00);
GX_BP_LOAD_REG(0xae0db000);
GX_BP_LOAD_REG(0xb20dd400);
GX_BP_LOAD_REG(0xaf0db800);
GX_BP_LOAD_REG(0xb30ddc00);
break;
case 1:
GX_BP_LOAD_REG(0x8c0d8000);
GX_BP_LOAD_REG(0x900dc000);
GX_BP_LOAD_REG(0x8d0d8800);
GX_BP_LOAD_REG(0x910dc800);
GX_BP_LOAD_REG(0x8e0d9000);
GX_BP_LOAD_REG(0x920dd000);
GX_BP_LOAD_REG(0x8f0d9800);
GX_BP_LOAD_REG(0x930dd800);
GX_BP_LOAD_REG(0xac0da000);
GX_BP_LOAD_REG(0xb00de000);
GX_BP_LOAD_REG(0xad0da800);
GX_BP_LOAD_REG(0xb10de800);
GX_BP_LOAD_REG(0xae0db000);
GX_BP_LOAD_REG(0xb20df000);
GX_BP_LOAD_REG(0xaf0db800);
GX_BP_LOAD_REG(0xb30df800);
break;
case 0:
default:
GX_BP_LOAD_REG(0x8c0d8000);
GX_BP_LOAD_REG(0x900dc000);
GX_BP_LOAD_REG(0x8d0d8400);
GX_BP_LOAD_REG(0x910dc400);
GX_BP_LOAD_REG(0x8e0d8800);
GX_BP_LOAD_REG(0x920dc800);
GX_BP_LOAD_REG(0x8f0d8c00);
GX_BP_LOAD_REG(0x930dcc00);
GX_BP_LOAD_REG(0xac0d9000);
GX_BP_LOAD_REG(0xb00dd000);
GX_BP_LOAD_REG(0xad0d9400);
GX_BP_LOAD_REG(0xb10dd400);
GX_BP_LOAD_REG(0xae0d9800);
GX_BP_LOAD_REG(0xb20dd800);
GX_BP_LOAD_REG(0xaf0d9c00);
GX_BP_LOAD_REG(0xb30ddc00);
break;
}
}

View File

@ -0,0 +1,316 @@
#include "dolphin/gx/GXTransform.h"
#include "dolphin/gx/GX.h"
#include "dolphin/os/OS.h"
void __GXSetMatrixIndex();
static void Copy6Floats(register f32 src[6], register f32 dst[6]) {
register f32 ps_0, ps_1, ps_2;
// clang-format off
asm {
psq_l ps_0, 0(src), 0, 0
psq_l ps_1, 8(src), 0, 0
psq_l ps_2, 16(src), 0, 0
psq_st ps_0, 0(dst), 0, 0
psq_st ps_1, 8(dst), 0, 0
psq_st ps_2, 16(dst), 0, 0
}
// clang-format on
}
static void WriteProjPS(const register f32 src[6], register volatile void* dst) {
register f32 ps_0, ps_1, ps_2;
// clang-format off
asm {
psq_l ps_0, 0(src), 0, 0
psq_l ps_1, 8(src), 0, 0
psq_l ps_2, 16(src), 0, 0
psq_st ps_0, 0(dst), 0, 0
psq_st ps_1, 0(dst), 0, 0
psq_st ps_2, 0(dst), 0, 0
}
// clang-format on
}
void GXProject(f32 model_x, f32 model_y, f32 model_z, Mtx model_mtx, f32* proj_mtx, f32* viewpoint,
f32* screen_x, f32* screen_y, f32* screen_z) {
f32 sp10[3];
f32 var_f30;
f32 var_f29;
f32 var_f28;
f32 var_f31;
ASSERTMSG(proj_mtx != NULL && viewpoint != NULL && screen_x != NULL && screen_y != NULL && screen_z != NULL, "GXGet*: invalid null pointer");
sp10[0] = (model_mtx[0][0] * model_x) + (model_mtx[0][1] * model_y) +
(model_mtx[0][2] * model_z) + model_mtx[0][3];
sp10[1] = (model_mtx[1][0] * model_x) + (model_mtx[1][1] * model_y) +
(model_mtx[1][2] * model_z) + model_mtx[1][3];
sp10[2] = (model_mtx[2][0] * model_x) + (model_mtx[2][1] * model_y) +
(model_mtx[2][2] * model_z) + model_mtx[2][3];
if (proj_mtx[0] == 0.0f) {
var_f30 = (sp10[0] * proj_mtx[1]) + (sp10[2] * proj_mtx[2]);
var_f29 = (sp10[1] * proj_mtx[3]) + (sp10[2] * proj_mtx[4]);
var_f28 = proj_mtx[6] + (sp10[2] * proj_mtx[5]);
var_f31 = 1.0f / -sp10[2];
} else {
var_f30 = proj_mtx[2] + (sp10[0] * proj_mtx[1]);
var_f29 = proj_mtx[4] + (sp10[1] * proj_mtx[3]);
var_f28 = proj_mtx[6] + (sp10[2] * proj_mtx[5]);
var_f31 = 1.0f;
}
*screen_x = (viewpoint[2] / 2) + (viewpoint[0] + (var_f31 * (var_f30 * viewpoint[2] / 2)));
*screen_y = (viewpoint[3] / 2) + (viewpoint[1] + (var_f31 * (-var_f29 * viewpoint[3] / 2)));
*screen_z = viewpoint[5] + (var_f31 * (var_f28 * (viewpoint[5] - viewpoint[4])));
}
void __GXSetProjection(void) {
GX_XF_LOAD_REGS(6, GX_XF_REG_PROJECTIONA);
WriteProjPS(__GXData->projMtx, (volatile void*)GXFIFO_ADDR);
GX_WRITE_U32(__GXData->projType);
}
void GXSetProjection(const Mtx44 proj, GXProjectionType type) {
volatile void* fifo;
__GXData->projType = type;
__GXData->projMtx[0] = proj[0][0];
__GXData->projMtx[2] = proj[1][1];
__GXData->projMtx[4] = proj[2][2];
__GXData->projMtx[5] = proj[2][3];
if (type == GX_ORTHOGRAPHIC) {
__GXData->projMtx[1] = proj[0][3];
__GXData->projMtx[3] = proj[1][3];
} else {
__GXData->projMtx[1] = proj[0][2];
__GXData->projMtx[3] = proj[1][2];
}
__GXSetProjection();
__GXData->bpSentNot = GX_TRUE;
}
void GXSetProjectionv(f32* proj) {
__GXData->projType = proj[0] == 0.0f ? GX_PERSPECTIVE : GX_ORTHOGRAPHIC;
Copy6Floats(&proj[1], __GXData->projMtx);
__GXSetProjection();
__GXData->bpSentNot = GX_TRUE;
}
void GXGetProjectionv(f32* proj) {
*proj = (u32)__GXData->projType != GX_PERSPECTIVE ? 1.0f : 0.0f;
Copy6Floats(__GXData->projMtx, &proj[1]);
}
static void WriteMTXPS4x3(register volatile void* dst, register const Mtx src) {
register f32 ps_0, ps_1, ps_2, ps_3, ps_4, ps_5;
// clang-format off
asm {
psq_l ps_0, 0(src), 0, 0
psq_l ps_1, 8(src), 0, 0
psq_l ps_2, 16(src), 0, 0
psq_l ps_3, 24(src), 0, 0
psq_l ps_4, 32(src), 0, 0
psq_l ps_5, 40(src), 0, 0
psq_st ps_0, 0(dst), 0, 0
psq_st ps_1, 0(dst), 0, 0
psq_st ps_2, 0(dst), 0, 0
psq_st ps_3, 0(dst), 0, 0
psq_st ps_4, 0(dst), 0, 0
psq_st ps_5, 0(dst), 0, 0
}
// clang-format on
}
void GXLoadPosMtxImm(Mtx mtx, u32 id) {
GX_XF_LOAD_REGS(4 * 3 - 1, id * 4 + GX_XF_MEM_POSMTX);
WriteMTXPS4x3(&GXFIFO, mtx);
}
static void WriteMTXPS3x3(register volatile void* dst, register const Mtx src) {
register f32 ps_0, ps_1, ps_2, ps_3, ps_4, ps_5;
// clang-format off
asm {
psq_l ps_0, 0(src), 0, 0
lfs ps_1, 8(src)
psq_l ps_2, 16(src), 0, 0
lfs ps_3, 24(src)
psq_l ps_4, 32(src), 0, 0
lfs ps_5, 40(src)
psq_st ps_0, 0(dst), 0, 0
stfs ps_1, 0(dst)
psq_st ps_2, 0(dst), 0, 0
stfs ps_3, 0(dst)
psq_st ps_4, 0(dst), 0, 0
stfs ps_5, 0(dst)
}
// clang-format on
}
void GXLoadNrmMtxImm(Mtx mtx, u32 id) {
GX_XF_LOAD_REGS(3 * 3 - 1, id * 3 + GX_XF_MEM_NRMMTX);
WriteMTXPS3x3(&GXFIFO, mtx);
}
void GXSetCurrentMtx(u32 id) {
GX_SET_REG(__GXData->matIdxA, id, GX_XF_MTXIDX0_GEOM_ST, GX_XF_MTXIDX0_GEOM_END);
__GXSetMatrixIndex(GX_VA_PNMTXIDX);
}
static void WriteMTXPS4x2(register volatile void* dst, register const Mtx src) {
register f32 ps_0, ps_1, ps_2, ps_3;
// clang-format off
asm {
psq_l ps_0, 0(src), 0, 0
psq_l ps_1, 8(src), 0, 0
psq_l ps_2, 16(src), 0, 0
psq_l ps_3, 24(src), 0, 0
psq_st ps_0, 0(dst), 0, 0
psq_st ps_1, 0(dst), 0, 0
psq_st ps_2, 0(dst), 0, 0
psq_st ps_3, 0(dst), 0, 0
}
// clang-format on
}
void GXLoadTexMtxImm(const Mtx mtx, u32 id, GXTexMtxType type) {
u32 addr;
u32 num;
u32 reg;
// Matrix address in XF memory
addr = id >= GX_PTTEXMTX0 ? (id - GX_PTTEXMTX0) * 4 + GX_XF_MEM_DUALTEXMTX :
id * 4 + (u64)GX_XF_MEM_POSMTX;
// Number of elements in matrix
num = type == GX_MTX2x4 ? (u64)(2 * 4) : 3 * 4;
reg = addr | (num - 1) << 16;
GX_XF_LOAD_REG_HDR(reg);
if (type == GX_MTX3x4) {
WriteMTXPS4x3(&GXFIFO, mtx);
} else {
WriteMTXPS4x2(&GXFIFO, mtx);
}
}
void __GXSetViewport(void) {
f32 a, b, c, d, e, f;
f32 near, far;
a = __GXData->vpWd / 2;
b = -__GXData->vpHt / 2;
d = __GXData->vpLeft + (__GXData->vpWd / 2) + 342.0f;
e = __GXData->vpTop + (__GXData->vpHt / 2) + 342.0f;
near = __GXData->vpNearz * __GXData->zScale;
far = __GXData->vpFarz * __GXData->zScale;
c = far - near;
f = far + __GXData->zOffset;
GX_XF_LOAD_REGS(5, GX_XF_REG_SCALEX);
GX_WRITE_F32(a);
GX_WRITE_F32(b);
GX_WRITE_F32(c);
GX_WRITE_F32(d);
GX_WRITE_F32(e);
GX_WRITE_F32(f);
}
void GXSetViewport(f32 left, f32 top, f32 width, f32 height, f32 nearZ, f32 farZ) {
__GXData->vpLeft = left;
__GXData->vpTop = top;
__GXData->vpWd = width;
__GXData->vpHt = height;
__GXData->vpNearz = nearZ;
__GXData->vpFarz = farZ;
__GXSetViewport();
__GXData->bpSentNot = GX_TRUE;
}
void GXGetViewportv(f32* p) {
Copy6Floats(&__GXData->vpLeft, p);
}
void GXSetScissor(u32 left, u32 top, u32 width, u32 height) {
u32 y1, x1, y2, x2;
u32 reg;
y1 = top + 342;
x1 = left + 342;
GX_SET_REG(__GXData->suScis0, y1, GX_BP_SCISSORTL_TOP_ST, GX_BP_SCISSORTL_TOP_END);
GX_SET_REG(__GXData->suScis0, x1, GX_BP_SCISSORTL_LEFT_ST, GX_BP_SCISSORTL_LEFT_END);
y2 = y1 + height - 1;
x2 = (x1 + width) - 1;
GX_SET_REG(__GXData->suScis1, y2, GX_BP_SCISSORBR_BOT_ST, GX_BP_SCISSORBR_BOT_END);
GX_SET_REG(__GXData->suScis1, x2, GX_BP_SCISSORBR_RIGHT_ST, GX_BP_SCISSORBR_RIGHT_END);
GX_BP_LOAD_REG(__GXData->suScis0);
GX_BP_LOAD_REG(__GXData->suScis1);
__GXData->bpSentNot = FALSE;
}
void GXGetScissor(u32* left, u32* top, u32* width, u32* height) {
u32 y1 = (__GXData->suScis0 & 0x0007FF) >> 0;
u32 x1 = (__GXData->suScis0 & 0x7FF000) >> 12;
u32 y2 = (__GXData->suScis1 & 0x0007FF) >> 0;
u32 x2 = (__GXData->suScis1 & 0x7FF000) >> 12;
*left = x1 - 0x156;
*top = y1 - 0x156;
*width = (x2 - x1) + 1;
*height = (y2 - y1) + 1;
}
void GXSetScissorBoxOffset(s32 x, s32 y) {
u32 cmd = 0;
u32 x1;
u32 y1;
x1 = (u32)(x + 342) / 2;
y1 = (u32)(y + 342) / 2;
GX_SET_REG(cmd, x1, GX_BP_SCISSOROFS_OX_ST, GX_BP_SCISSOROFS_OX_END);
GX_SET_REG(cmd, y1, GX_BP_SCISSOROFS_OY_ST, GX_BP_SCISSOROFS_OY_END);
GX_SET_REG(cmd, GX_BP_REG_SCISSOROFFSET, 0, 7);
GX_BP_LOAD_REG(cmd);
__GXData->bpSentNot = GX_FALSE;
}
void GXSetClipMode(GXClipMode mode) {
GX_XF_LOAD_REG(GX_XF_REG_CLIPDISABLE, mode);
__GXData->bpSentNot = GX_TRUE;
}
void __GXSetMatrixIndex(GXAttr index) {
// Tex4 and after is stored in XF MatrixIndex1
if (index < GX_VA_TEX4MTXIDX) {
GX_CP_LOAD_REG(GX_CP_REG_MTXIDXA, __GXData->matIdxA);
GX_XF_LOAD_REG(GX_XF_REG_MATRIXINDEX0, __GXData->matIdxA);
} else {
GX_CP_LOAD_REG(GX_CP_REG_MTXIDXB, __GXData->matIdxB);
GX_XF_LOAD_REG(GX_XF_REG_MATRIXINDEX1, __GXData->matIdxB);
}
__GXData->bpSentNot = GX_TRUE;
}

View File

@ -522,7 +522,7 @@ void drawDepth(view_class* view, view_port_class* viewport, int depth) {
GXCopyTex(zbuf, GX_FALSE);
GXSetTexCopySrc(x, y, w, h);
GXSetTexCopyDst(hw, hh, mDoGph_gInf_c::getFrameBufferTimg()->format, GX_TRUE);
GXSetTexCopyDst(hw, hh, (GXTexFmt)mDoGph_gInf_c::getFrameBufferTimg()->format, GX_TRUE);
GXCopyTex(fbbuf, GX_FALSE);
GXInitTexObj(mDoGph_gInf_c::getZbufferTexObj(), zbuf, w, h, GX_TF_IA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
@ -933,7 +933,7 @@ bool mDoGph_screenCapture() {
setUpRectangle();
GXSetTexCopySrc(centerX - sizeW, centerY - sizeH, sizeW2, sizeH2);
GXSetTexCopyDst(sizeW, sizeH, mCaptureCaptureFormat, GX_TRUE);
GXSetTexCopyDst(sizeW, sizeH, (_GXTexFmt)mCaptureCaptureFormat, GX_TRUE);
DCInvalidateRange(mCaptureCaptureBuffer, mCaptureCaptureSize);
GXCopyTex(mCaptureCaptureBuffer, GX_FALSE);
GXPixModeSync();