Merge branch 'main' of https://github.com/abnormalhare/marioparty4
This commit is contained in:
commit
140544b3b1
36 changed files with 13418 additions and 652 deletions
|
|
@ -206,19 +206,19 @@ void fn_1_C164(unkStruct8* arg0) {
|
|||
}
|
||||
GXClearVtxDesc();
|
||||
GXSetVtxDesc(GX_VA_POS, GX_INDEX16);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_TEX_ST, GX_RGBA6, 0);
|
||||
GXSetArray(GX_VA_POS, var_r31->unk40, 0xC);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
|
||||
GXSetArray(GX_VA_POS, var_r31->unk40, 12);
|
||||
GXSetVtxDesc(GX_VA_CLR0, GX_INDEX16);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_TEX_ST, GX_RGBA8, 0);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
|
||||
GXSetArray(GX_VA_CLR0, var_r31->unk44, 4);
|
||||
for (var_r26 = 0; var_r26 < var_r31->unk32; var_r26++) {
|
||||
GXSetVtxDesc(var_r26 + GX_VA_TEX0, GX_INDEX16);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, var_r26 + GX_VA_TEX0, GX_TEX_ST, GX_RGBA6, 0);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, var_r26 + GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
|
||||
GXSetArray(var_r26 + GX_VA_TEX0, var_r31->unk54[var_r26].unk4, 8);
|
||||
}
|
||||
GXSetVtxDesc(GX_VA_NRM, GX_INDEX16);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_TEX_S, GX_RGBA6, 0);
|
||||
GXSetArray(GX_VA_NRM, var_r31->unk48, 0xC);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
|
||||
GXSetArray(GX_VA_NRM, var_r31->unk48, 12);
|
||||
GXCallDisplayList(var_r31->unk3C, var_r31->unk38);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1376,13 +1376,13 @@ void fn_1_602C(ModelData *arg0, f32 (*arg1)[4])
|
|||
}
|
||||
GXClearVtxDesc();
|
||||
GXSetVtxDesc(GX_VA_POS, GX_INDEX16);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_TEX_ST, GX_RGBA6, 0);
|
||||
GXSetArray(GX_VA_POS, temp_r30->unk1C, 0xC);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
|
||||
GXSetArray(GX_VA_POS, temp_r30->unk1C, 12);
|
||||
GXSetVtxDesc(GX_VA_CLR0, GX_INDEX16);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_TEX_ST, GX_RGBA8, 0);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
|
||||
GXSetArray(GX_VA_CLR0, temp_r30->unk24, 4);
|
||||
GXSetVtxDesc(GX_VA_TEX0, GX_INDEX16);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_RGBA6, 0);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
|
||||
GXSetArray(GX_VA_TEX0, temp_r30->unk20, 8);
|
||||
fn_1_40A4(arg1, sp128);
|
||||
PSMTXReorder(sp128, spF8);
|
||||
|
|
|
|||
|
|
@ -230,20 +230,20 @@ void fn_1_88B8(unkSubStruct2* arg0) {
|
|||
}
|
||||
GXClearVtxDesc();
|
||||
GXSetVtxDesc(GX_VA_POS, GX_INDEX16);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_TEX_ST, GX_RGBA6, 0);
|
||||
GXSetArray(GX_VA_POS, var_r31->unk40, 0xC);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
|
||||
GXSetArray(GX_VA_POS, var_r31->unk40, 12);
|
||||
GXSetVtxDesc(GX_VA_CLR0, GX_INDEX16);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_TEX_ST, GX_RGBA8, 0);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
|
||||
GXSetArray(GX_VA_CLR0, var_r31->unk44, 4);
|
||||
|
||||
for (var_r27 = 0; var_r27 < var_r31->unk33; var_r27++) {
|
||||
GXSetVtxDesc(var_r27 + GX_VA_TEX0, GX_INDEX16);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, var_r27 + GX_VA_TEX0, GX_TEX_ST, GX_RGBA6, 0);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, var_r27 + GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
|
||||
GXSetArray(var_r27 + GX_VA_TEX0, var_r31->unk54[var_r27].unk4, 8);
|
||||
}
|
||||
GXSetVtxDesc(GX_VA_NRM, GX_INDEX16);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_RGBA6, 0);
|
||||
GXSetArray(GX_VA_NRM, var_r31->unk48, 0xC);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
|
||||
GXSetArray(GX_VA_NRM, var_r31->unk48, 12);
|
||||
GXCallDisplayList(var_r31->unk3C, var_r31->unk38);
|
||||
}
|
||||
}
|
||||
|
|
@ -1433,4 +1433,4 @@ void fn_1_C81C(s16 arg0, u8 arg1) {
|
|||
var_r31 = &lbl_1_bss_36C.unk3C[arg0];
|
||||
var_r31->unk4 = arg1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
5648
src/REL/m423Dll/main.c
Executable file
5648
src/REL/m423Dll/main.c
Executable file
File diff suppressed because it is too large
Load diff
|
|
@ -3170,7 +3170,7 @@ void fn_1_88B4(ModelData *arg0, Mtx arg1)
|
|||
GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_NOOP);
|
||||
GXClearVtxDesc();
|
||||
GXSetVtxDesc(GX_VA_POS, GX_INDEX16);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_TEX_ST, GX_F32, 0);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
|
||||
GXSetArray(GX_VA_POS, lbl_1_data_27C, 12);
|
||||
GXSetVtxDesc(GX_VA_CLR0, GX_INDEX16);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
|
||||
|
|
|
|||
|
|
@ -1875,11 +1875,11 @@ void fn_1_806C(ModelData *arg0, Mtx arg1)
|
|||
GXSetChanMatColor(GX_COLOR0A0, sp10);
|
||||
GXClearVtxDesc();
|
||||
GXSetVtxDesc(GX_VA_POS, GX_INDEX16);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_TEX_ST, GX_RGBA6, 0);
|
||||
GXSetArray(GX_VA_POS, temp_r31->unkC, 0xC);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
|
||||
GXSetArray(GX_VA_POS, temp_r31->unkC, 12);
|
||||
GXSetVtxDesc(GX_VA_NRM, GX_INDEX16);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_TEX_S, GX_RGBA6, 0);
|
||||
GXSetArray(GX_VA_NRM, temp_r31->unk14, 0xC);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
|
||||
GXSetArray(GX_VA_NRM, temp_r31->unk14, 12);
|
||||
lbl_1_bss_C = temp_r31->unk3C;
|
||||
if (temp_r31->unk28->unk34 == 0) {
|
||||
GXSetNumTevStages(1);
|
||||
|
|
@ -1893,7 +1893,7 @@ void fn_1_806C(ModelData *arg0, Mtx arg1)
|
|||
}
|
||||
else {
|
||||
GXSetVtxDesc(GX_VA_TEX0, GX_INDEX16);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_RGBA6, 0);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
|
||||
GXSetArray(GX_VA_TEX0, temp_r31->unk1C, 8);
|
||||
temp_r29 = &temp_r31->unk2C[temp_r31->unk28->unk38[0]];
|
||||
fn_1_7D60(temp_r29->unk80, temp_r29, 0);
|
||||
|
|
@ -2600,7 +2600,7 @@ void fn_1_A390(ModelData *arg0, Mtx arg1)
|
|||
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
|
||||
GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_TEX_ST, GX_RGBA8, 0);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
|
||||
GXSetNumTevStages(1);
|
||||
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
|
||||
GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_RASC, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO);
|
||||
|
|
|
|||
|
|
@ -220,11 +220,11 @@ void fn_1_4FC(ModelData *model, Mtx matrix)
|
|||
GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0);
|
||||
GXClearVtxDesc();
|
||||
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_RGBA6, 0);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
|
||||
GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
|
||||
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_RGBA6, 0);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
|
||||
for (i = 0; i < 0; i++) {
|
||||
s32 sp84[5] = { 0, 1, 1, 0, 1 };
|
||||
float sp70[5] = { 1.0f, 2.0f, 2.5f, 0.0f, 0.0f };
|
||||
|
|
|
|||
|
|
@ -775,13 +775,13 @@ void fn_1_2B68(ModelData *mdl, Mtx arg1)
|
|||
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
|
||||
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
|
||||
GXSetVtxDesc(GX_VA_NRM, GX_DIRECT);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0U);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_RGBA6, 0U);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0U);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
|
||||
GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
|
||||
GXSetCullMode(GX_CULL_NONE);
|
||||
GXSetZMode(GX_FALSE, GX_ALWAYS, GX_FALSE);
|
||||
GXSetNumTexGens(1);
|
||||
GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3CU, 0U, 0x7DU);
|
||||
GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY);
|
||||
GXSetNumTevStages(1);
|
||||
|
||||
sp17.r = sp17.g = sp17.b = sp17.a = 255;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "dolphin/hw_regs.h"
|
||||
#include "dolphin/os.h"
|
||||
#include "dolphin/os/OSCache.h"
|
||||
|
||||
static ARCallback __AR_Callback;
|
||||
static u32 __AR_Size;
|
||||
|
|
@ -10,242 +11,333 @@ static u32 __AR_ExpansionSize;
|
|||
|
||||
static u32 __AR_StackPointer;
|
||||
static u32 __AR_FreeBlocks;
|
||||
static u32* __AR_BlockLength;
|
||||
static u32 *__AR_BlockLength;
|
||||
|
||||
static volatile BOOL __AR_init_flag = FALSE;
|
||||
|
||||
static void __ARHandler(__OSInterrupt interrupt, OSContext* context);
|
||||
static void __ARHandler(__OSInterrupt interrupt, OSContext *context);
|
||||
static void __ARChecksize(void);
|
||||
static void __ARClearArea(u32 start_addr, u32 length);
|
||||
|
||||
ARCallback ARRegisterDMACallback(ARCallback callback) {
|
||||
ARCallback oldCb;
|
||||
BOOL enabled;
|
||||
oldCb = __AR_Callback;
|
||||
enabled = OSDisableInterrupts();
|
||||
__AR_Callback = callback;
|
||||
OSRestoreInterrupts(enabled);
|
||||
return oldCb;
|
||||
}
|
||||
// TODO import defines for magic numbers from other repos
|
||||
|
||||
u32 ARGetDMAStatus() {
|
||||
BOOL enabled;
|
||||
u32 val;
|
||||
enabled = OSDisableInterrupts();
|
||||
val = __DSPRegs[5] & 0x0200;
|
||||
OSRestoreInterrupts(enabled);
|
||||
return val;
|
||||
}
|
||||
|
||||
void ARStartDMA(u32 type, u32 mainmem_addr, u32 aram_addr, u32 length) {
|
||||
BOOL enabled;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
|
||||
__DSPRegs[16] = (u16)(__DSPRegs[16] & ~0x3ff) | (u16)(mainmem_addr >> 16);
|
||||
__DSPRegs[17] = (u16)(__DSPRegs[17] & ~0xffe0) | (u16)(mainmem_addr & 0xffff);
|
||||
__DSPRegs[18] = (u16)(__DSPRegs[18] & ~0x3ff) | (u16)(aram_addr >> 16);
|
||||
__DSPRegs[19] = (u16)(__DSPRegs[19] & ~0xffe0) | (u16)(aram_addr & 0xffff);
|
||||
__DSPRegs[20] = (u16)((__DSPRegs[20] & ~0x8000) | (type << 15));
|
||||
__DSPRegs[20] = (u16)(__DSPRegs[20] & ~0x3ff) | (u16)(length >> 16);
|
||||
__DSPRegs[21] = (u16)(__DSPRegs[21] & ~0xffe0) | (u16)(length & 0xffff);
|
||||
OSRestoreInterrupts(enabled);
|
||||
}
|
||||
|
||||
u32 ARAlloc(u32 length) {
|
||||
u32 tmp;
|
||||
BOOL enabled;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
tmp = __AR_StackPointer;
|
||||
__AR_StackPointer += length;
|
||||
*__AR_BlockLength = length;
|
||||
__AR_BlockLength++;
|
||||
__AR_FreeBlocks--;
|
||||
OSRestoreInterrupts(enabled);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
#if NONMATCHING
|
||||
u32 ARFree(u32* length) {
|
||||
BOOL old;
|
||||
|
||||
old = OSDisableInterrupts();
|
||||
|
||||
__AR_BlockLength--;
|
||||
|
||||
if (length) {
|
||||
*length = *__AR_BlockLength;
|
||||
}
|
||||
|
||||
__AR_StackPointer -= *__AR_BlockLength;
|
||||
|
||||
__AR_FreeBlocks++;
|
||||
|
||||
OSRestoreInterrupts(old);
|
||||
|
||||
return __AR_StackPointer;
|
||||
}
|
||||
#else
|
||||
/* clang-format off */
|
||||
#pragma push
|
||||
#pragma optimization_level 0
|
||||
#pragma optimizewithasm off
|
||||
asm u32 ARFree(u32* length) {
|
||||
nofralloc
|
||||
mflr r0
|
||||
stw r0, 4(r1)
|
||||
stwu r1, -0x18(r1)
|
||||
stw r31, 0x14(r1)
|
||||
mr r31, r3
|
||||
bl OSDisableInterrupts
|
||||
lwz r4, __AR_BlockLength
|
||||
cmplwi r31, 0
|
||||
addi r0, r4, -4
|
||||
stw r0, __AR_BlockLength
|
||||
beq lbl_8036DAB4
|
||||
lwz r4, __AR_BlockLength
|
||||
lwz r0, 0(r4)
|
||||
stw r0, 0(r31)
|
||||
lbl_8036DAB4:
|
||||
lwz r5, __AR_BlockLength
|
||||
lwz r4, __AR_FreeBlocks
|
||||
lwz r6, 0(r5)
|
||||
addi r0, r4, 1
|
||||
lwz r5, __AR_StackPointer
|
||||
stw r0, __AR_FreeBlocks
|
||||
subf r0, r6, r5
|
||||
stw r0, __AR_StackPointer
|
||||
bl OSRestoreInterrupts
|
||||
lwz r3, __AR_StackPointer
|
||||
lwz r0, 0x1c(r1)
|
||||
lwz r31, 0x14(r1)
|
||||
addi r1, r1, 0x18
|
||||
mtlr r0
|
||||
blr
|
||||
}
|
||||
#pragma pop
|
||||
/* clang-format on */
|
||||
#endif
|
||||
|
||||
BOOL ARCheckInit() { return __AR_init_flag; }
|
||||
|
||||
u32 ARInit(u32* stack_index_addr, u32 num_entries) {
|
||||
|
||||
BOOL old;
|
||||
u16 refresh;
|
||||
|
||||
if (__AR_init_flag == TRUE) {
|
||||
return 0x4000;
|
||||
}
|
||||
|
||||
old = OSDisableInterrupts();
|
||||
|
||||
__AR_Callback = NULL;
|
||||
|
||||
__OSSetInterruptHandler(__OS_INTERRUPT_DSP_ARAM, __ARHandler);
|
||||
__OSUnmaskInterrupts(OS_INTERRUPTMASK_DSP_ARAM);
|
||||
|
||||
__AR_StackPointer = 0x4000;
|
||||
__AR_FreeBlocks = num_entries;
|
||||
__AR_BlockLength = stack_index_addr;
|
||||
|
||||
refresh = (u16)(__DSPRegs[13] & 0x000000ff);
|
||||
|
||||
__DSPRegs[13] = (u16)((__DSPRegs[13] & ~0x000000ff) | (refresh & 0x000000ff));
|
||||
|
||||
__ARChecksize();
|
||||
|
||||
__AR_init_flag = TRUE;
|
||||
|
||||
OSRestoreInterrupts(old);
|
||||
|
||||
return __AR_StackPointer;
|
||||
}
|
||||
|
||||
u32 ARGetBaseAddress(void) { return 0x4000; }
|
||||
|
||||
void ARSetSize(void)
|
||||
ARCallback ARRegisterDMACallback(ARCallback callback)
|
||||
{
|
||||
|
||||
ARCallback oldCb;
|
||||
BOOL enabled;
|
||||
oldCb = __AR_Callback;
|
||||
enabled = OSDisableInterrupts();
|
||||
__AR_Callback = callback;
|
||||
OSRestoreInterrupts(enabled);
|
||||
return oldCb;
|
||||
}
|
||||
|
||||
u32 ARGetSize() { return __AR_Size; }
|
||||
u32 ARGetDMAStatus()
|
||||
{
|
||||
BOOL enabled;
|
||||
u32 val;
|
||||
enabled = OSDisableInterrupts();
|
||||
val = __DSPRegs[5] & 0x0200;
|
||||
OSRestoreInterrupts(enabled);
|
||||
return val;
|
||||
}
|
||||
|
||||
static void __ARHandler(__OSInterrupt interrupt, OSContext* context) {
|
||||
void ARStartDMA(u32 type, u32 mainmem_addr, u32 aram_addr, u32 length)
|
||||
{
|
||||
BOOL enabled;
|
||||
|
||||
OSContext exceptionContext;
|
||||
u16 tmp;
|
||||
enabled = OSDisableInterrupts();
|
||||
|
||||
tmp = __DSPRegs[5];
|
||||
tmp = (u16)((tmp & ~0x00000088) | 0x20);
|
||||
__DSPRegs[5] = tmp;
|
||||
__DSPRegs[16] = (u16)(__DSPRegs[16] & ~0x3ff) | (u16)(mainmem_addr >> 16);
|
||||
__DSPRegs[17] = (u16)(__DSPRegs[17] & ~0xffe0) | (u16)(mainmem_addr & 0xffff);
|
||||
__DSPRegs[18] = (u16)(__DSPRegs[18] & ~0x3ff) | (u16)(aram_addr >> 16);
|
||||
__DSPRegs[19] = (u16)(__DSPRegs[19] & ~0xffe0) | (u16)(aram_addr & 0xffff);
|
||||
__DSPRegs[20] = (u16)((__DSPRegs[20] & ~0x8000) | (type << 15));
|
||||
__DSPRegs[20] = (u16)(__DSPRegs[20] & ~0x3ff) | (u16)(length >> 16);
|
||||
__DSPRegs[21] = (u16)(__DSPRegs[21] & ~0xffe0) | (u16)(length & 0xffff);
|
||||
OSRestoreInterrupts(enabled);
|
||||
}
|
||||
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(&exceptionContext);
|
||||
u32 ARAlloc(u32 length)
|
||||
{
|
||||
u32 tmp;
|
||||
BOOL enabled;
|
||||
|
||||
if (__AR_Callback) {
|
||||
(*__AR_Callback)();
|
||||
}
|
||||
enabled = OSDisableInterrupts();
|
||||
tmp = __AR_StackPointer;
|
||||
__AR_StackPointer += length;
|
||||
*__AR_BlockLength = length;
|
||||
__AR_BlockLength++;
|
||||
__AR_FreeBlocks--;
|
||||
OSRestoreInterrupts(enabled);
|
||||
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(context);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
u32 ARFree(u32 *length)
|
||||
{
|
||||
BOOL old;
|
||||
|
||||
old = OSDisableInterrupts();
|
||||
|
||||
__AR_BlockLength--;
|
||||
|
||||
if (length) {
|
||||
*length = *__AR_BlockLength;
|
||||
}
|
||||
|
||||
__AR_StackPointer -= *__AR_BlockLength;
|
||||
|
||||
__AR_FreeBlocks++;
|
||||
|
||||
OSRestoreInterrupts(old);
|
||||
|
||||
return __AR_StackPointer;
|
||||
}
|
||||
|
||||
BOOL ARCheckInit()
|
||||
{
|
||||
return __AR_init_flag;
|
||||
}
|
||||
|
||||
u32 ARInit(u32 *stack_index_addr, u32 num_entries)
|
||||
{
|
||||
|
||||
BOOL old;
|
||||
u16 refresh;
|
||||
|
||||
if (__AR_init_flag == TRUE) {
|
||||
return 0x4000;
|
||||
}
|
||||
|
||||
old = OSDisableInterrupts();
|
||||
|
||||
__AR_Callback = NULL;
|
||||
|
||||
__OSSetInterruptHandler(__OS_INTERRUPT_DSP_ARAM, __ARHandler);
|
||||
__OSUnmaskInterrupts(OS_INTERRUPTMASK_DSP_ARAM);
|
||||
|
||||
__AR_StackPointer = 0x4000;
|
||||
__AR_FreeBlocks = num_entries;
|
||||
__AR_BlockLength = stack_index_addr;
|
||||
|
||||
refresh = (u16)(__DSPRegs[13] & 0x000000ff);
|
||||
|
||||
__DSPRegs[13] = (u16)((__DSPRegs[13] & ~0x000000ff) | (refresh & 0x000000ff));
|
||||
|
||||
__ARChecksize();
|
||||
|
||||
__AR_init_flag = TRUE;
|
||||
|
||||
OSRestoreInterrupts(old);
|
||||
|
||||
return __AR_StackPointer;
|
||||
}
|
||||
|
||||
void ARSetSize(void) { }
|
||||
|
||||
u32 ARGetBaseAddress(void)
|
||||
{
|
||||
return 0x4000;
|
||||
}
|
||||
|
||||
u32 ARGetSize()
|
||||
{
|
||||
return __AR_Size;
|
||||
}
|
||||
|
||||
static void __ARHandler(__OSInterrupt interrupt, OSContext *context)
|
||||
{
|
||||
|
||||
OSContext exceptionContext;
|
||||
u16 tmp;
|
||||
|
||||
tmp = __DSPRegs[5];
|
||||
tmp = (u16)((tmp & ~0x00000088) | 0x20);
|
||||
__DSPRegs[5] = tmp;
|
||||
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(&exceptionContext);
|
||||
|
||||
if (__AR_Callback) {
|
||||
(*__AR_Callback)();
|
||||
}
|
||||
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(context);
|
||||
}
|
||||
|
||||
#define RoundUP32(x) (((u32)(x) + 32 - 1) & ~(32 - 1))
|
||||
|
||||
void __ARClearInterrupt(void) {
|
||||
void __ARClearInterrupt(void)
|
||||
{
|
||||
|
||||
u16 tmp;
|
||||
tmp = __DSPRegs[5];
|
||||
tmp = (u16)((tmp & ~(0x00000080 | 0x00000008)) | 0x00000020);
|
||||
__DSPRegs[5] = tmp;
|
||||
u16 tmp;
|
||||
tmp = __DSPRegs[5];
|
||||
tmp = (u16)((tmp & ~(0x00000080 | 0x00000008)) | 0x00000020);
|
||||
__DSPRegs[5] = tmp;
|
||||
}
|
||||
u16 __ARGetInterruptStatus(void) { return ((u16)(__DSPRegs[5] & 0x0200)); }
|
||||
|
||||
static void __ARWaitForDMA(void) {
|
||||
|
||||
while (__DSPRegs[5] & 0x0200) {
|
||||
}
|
||||
u16 __ARGetInterruptStatus(void)
|
||||
{
|
||||
return ((u16)(__DSPRegs[5] & 0x0200));
|
||||
}
|
||||
|
||||
static void __ARWriteDMA(u32 mmem_addr, u32 aram_addr, u32 length) {
|
||||
static void __ARWaitForDMA(void)
|
||||
{
|
||||
|
||||
__DSPRegs[16] = (u16)((__DSPRegs[16] & ~0x03ff) | (u16)(mmem_addr >> 16));
|
||||
__DSPRegs[16 + 1] = (u16)((__DSPRegs[16 + 1] & ~0xffe0) | (u16)(mmem_addr & 0xffff));
|
||||
|
||||
__DSPRegs[18] = (u16)((__DSPRegs[18] & ~0x03ff) | (u16)(aram_addr >> 16));
|
||||
__DSPRegs[18 + 1] = (u16)((__DSPRegs[18 + 1] & ~0xffe0) | (u16)(aram_addr & 0xffff));
|
||||
|
||||
__DSPRegs[20] = (u16)(__DSPRegs[20] & ~0x8000);
|
||||
|
||||
__DSPRegs[20] = (u16)((__DSPRegs[20] & ~0x03ff) | (u16)(length >> 16));
|
||||
__DSPRegs[20 + 1] = (u16)((__DSPRegs[20 + 1] & ~0xffe0) | (u16)(length & 0xffff));
|
||||
|
||||
__ARWaitForDMA();
|
||||
|
||||
__ARClearInterrupt();
|
||||
while (__DSPRegs[5] & 0x0200) { }
|
||||
}
|
||||
|
||||
static void __ARReadDMA(u32 mmem_addr, u32 aram_addr, u32 length) {
|
||||
static void __ARWriteDMA(u32 mmem_addr, u32 aram_addr, u32 length)
|
||||
{
|
||||
|
||||
__DSPRegs[16] = (u16)((__DSPRegs[16] & ~0x03ff) | (u16)(mmem_addr >> 16));
|
||||
__DSPRegs[16 + 1] = (u16)((__DSPRegs[16 + 1] & ~0xffe0) | (u16)(mmem_addr & 0xffff));
|
||||
__DSPRegs[16] = (u16)((__DSPRegs[16] & ~0x03ff) | (u16)(mmem_addr >> 16));
|
||||
__DSPRegs[16 + 1] = (u16)((__DSPRegs[16 + 1] & ~0xffe0) | (u16)(mmem_addr & 0xffff));
|
||||
|
||||
__DSPRegs[18] = (u16)((__DSPRegs[18] & ~0x03ff) | (u16)(aram_addr >> 16));
|
||||
__DSPRegs[18 + 1] = (u16)((__DSPRegs[18 + 1] & ~0xffe0) | (u16)(aram_addr & 0xffff));
|
||||
__DSPRegs[18] = (u16)((__DSPRegs[18] & ~0x03ff) | (u16)(aram_addr >> 16));
|
||||
__DSPRegs[18 + 1] = (u16)((__DSPRegs[18 + 1] & ~0xffe0) | (u16)(aram_addr & 0xffff));
|
||||
|
||||
__DSPRegs[20] = (u16)(__DSPRegs[20] | 0x8000);
|
||||
__DSPRegs[20] = (u16)(__DSPRegs[20] & ~0x8000);
|
||||
|
||||
__DSPRegs[20] = (u16)((__DSPRegs[20] & ~0x03ff) | (u16)(length >> 16));
|
||||
__DSPRegs[20 + 1] = (u16)((__DSPRegs[20 + 1] & ~0xffe0) | (u16)(length & 0xffff));
|
||||
__DSPRegs[20] = (u16)((__DSPRegs[20] & ~0x03ff) | (u16)(length >> 16));
|
||||
__DSPRegs[20 + 1] = (u16)((__DSPRegs[20 + 1] & ~0xffe0) | (u16)(length & 0xffff));
|
||||
|
||||
__ARWaitForDMA();
|
||||
__ARWaitForDMA();
|
||||
|
||||
__ARClearInterrupt();
|
||||
__ARClearInterrupt();
|
||||
}
|
||||
|
||||
static void __ARChecksize(void) {
|
||||
//TODO: Implement for this SDK version
|
||||
}
|
||||
static void __ARReadDMA(u32 mmem_addr, u32 aram_addr, u32 length)
|
||||
{
|
||||
|
||||
__DSPRegs[16] = (u16)((__DSPRegs[16] & ~0x03ff) | (u16)(mmem_addr >> 16));
|
||||
__DSPRegs[16 + 1] = (u16)((__DSPRegs[16 + 1] & ~0xffe0) | (u16)(mmem_addr & 0xffff));
|
||||
|
||||
__DSPRegs[18] = (u16)((__DSPRegs[18] & ~0x03ff) | (u16)(aram_addr >> 16));
|
||||
__DSPRegs[18 + 1] = (u16)((__DSPRegs[18 + 1] & ~0xffe0) | (u16)(aram_addr & 0xffff));
|
||||
|
||||
__DSPRegs[20] = (u16)(__DSPRegs[20] | 0x8000);
|
||||
|
||||
__DSPRegs[20] = (u16)((__DSPRegs[20] & ~0x03ff) | (u16)(length >> 16));
|
||||
__DSPRegs[20 + 1] = (u16)((__DSPRegs[20 + 1] & ~0xffe0) | (u16)(length & 0xffff));
|
||||
|
||||
__ARWaitForDMA();
|
||||
|
||||
__ARClearInterrupt();
|
||||
}
|
||||
|
||||
void __ARChecksize(void)
|
||||
{
|
||||
u8 test_data_pad[0x20 + 31];
|
||||
u8 dummy_data_pad[0x20 + 31];
|
||||
u8 buffer_pad[0x20 + 31];
|
||||
|
||||
u32 *test_data;
|
||||
u32 *dummy_data;
|
||||
u32 *buffer;
|
||||
|
||||
u16 ARAM_mode;
|
||||
u32 ARAM_size;
|
||||
|
||||
u32 i;
|
||||
|
||||
while (!(__DSPRegs[11] & 1))
|
||||
;
|
||||
|
||||
ARAM_mode = 3;
|
||||
ARAM_size = __AR_InternalSize = 0x1000000;
|
||||
__DSPRegs[9] = (u16)((__DSPRegs[9] & ~(0x00000007 | 0x00000038)) | 0x20 | 2 | 1);
|
||||
|
||||
test_data = (u32 *)(RoundUP32((u32)(test_data_pad)));
|
||||
dummy_data = (u32 *)(RoundUP32((u32)(dummy_data_pad)));
|
||||
buffer = (u32 *)(RoundUP32((u32)(buffer_pad)));
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
*(test_data + i) = 0xdeadbeef;
|
||||
*(dummy_data + i) = 0xbad0bad0;
|
||||
}
|
||||
|
||||
DCFlushRange((void *)test_data, 0x20);
|
||||
DCFlushRange((void *)dummy_data, 0x20);
|
||||
|
||||
__AR_ExpansionSize = 0;
|
||||
|
||||
__ARWriteDMA((u32)dummy_data, ARAM_size, 0x20U);
|
||||
__ARWriteDMA((u32)dummy_data, ARAM_size + 0x200000, 0x20U);
|
||||
__ARWriteDMA((u32)dummy_data, ARAM_size + 0x01000000, 0x20U);
|
||||
__ARWriteDMA((u32)dummy_data, ARAM_size + 0x200, 0x20U);
|
||||
__ARWriteDMA((u32)dummy_data, ARAM_size + 0x400000, 0x20U);
|
||||
|
||||
memset((void *)buffer, 0, 0x20);
|
||||
DCFlushRange((void *)buffer, 0x20);
|
||||
|
||||
__ARWriteDMA((u32)test_data, ARAM_size + 0x0000000, 0x20);
|
||||
|
||||
DCInvalidateRange((void *)buffer, 0x20);
|
||||
|
||||
__ARReadDMA((u32)buffer, ARAM_size + 0x0000000, 0x20);
|
||||
PPCSync();
|
||||
|
||||
if (buffer[0] == test_data[0]) {
|
||||
memset((void *)buffer, 0, 0x20);
|
||||
DCFlushRange((void *)buffer, 0x20);
|
||||
|
||||
__ARReadDMA((u32)buffer, ARAM_size + 0x0200000, 0x20);
|
||||
PPCSync();
|
||||
|
||||
if (buffer[0] == test_data[0]) {
|
||||
ARAM_mode |= 0 << 1;
|
||||
ARAM_size += 0x0200000;
|
||||
__AR_ExpansionSize = 0x0200000;
|
||||
}
|
||||
else {
|
||||
memset((void *)buffer, 0, 0x20);
|
||||
DCFlushRange((void *)buffer, 0x20);
|
||||
|
||||
__ARReadDMA((u32)buffer, ARAM_size + 0x1000000, 0x20);
|
||||
PPCSync();
|
||||
|
||||
if (buffer[0] == test_data[0]) {
|
||||
ARAM_mode |= 4 << 1;
|
||||
ARAM_size += 0x0400000;
|
||||
__AR_ExpansionSize = 0x0400000;
|
||||
}
|
||||
else {
|
||||
memset((void *)buffer, 0, 0x20);
|
||||
DCFlushRange((void *)buffer, 0x20);
|
||||
|
||||
__ARReadDMA((u32)buffer, ARAM_size + 0x0000200, 0x20);
|
||||
PPCSync();
|
||||
|
||||
if (buffer[0] == test_data[0]) {
|
||||
ARAM_mode |= 8 << 1;
|
||||
ARAM_size += 0x800000;
|
||||
__AR_ExpansionSize = 0x0800000;
|
||||
}
|
||||
else {
|
||||
memset((void *)buffer, 0, 0x20);
|
||||
DCFlushRange((void *)buffer, 0x20);
|
||||
|
||||
__ARReadDMA((u32)buffer, ARAM_size + 0x0400000, 0x20);
|
||||
PPCSync();
|
||||
|
||||
if (buffer[0] == test_data[0]) {
|
||||
ARAM_mode |= 12 << 1;
|
||||
ARAM_size += 0x1000000;
|
||||
__AR_ExpansionSize = 0x1000000;
|
||||
}
|
||||
else {
|
||||
ARAM_mode |= 16 << 1;
|
||||
ARAM_size += 0x2000000;
|
||||
__AR_ExpansionSize = 0x2000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
__DSPRegs[9] = (u16)((__DSPRegs[9] & ~(0x07 | 0x38)) | ARAM_mode);
|
||||
}
|
||||
|
||||
*(u32 *)OSPhysicalToUncached(0x00D0) = ARAM_size;
|
||||
|
||||
__AR_Size = ARAM_size;
|
||||
}
|
||||
|
|
|
|||
586
src/dolphin/gx/GXAttr.c
Normal file
586
src/dolphin/gx/GXAttr.c
Normal file
|
|
@ -0,0 +1,586 @@
|
|||
#include <dolphin/gx.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <dolphin/gx/GXPriv.h>
|
||||
|
||||
#define CHECK_ATTRPTR(line, attrPtr) ASSERTMSGLINE(line, (attrPtr) != NULL, "GXSetVtxDescv: attrPtr is NULL")
|
||||
#define CHECK_ATTRNAME(line, attr) ASSERTMSGLINE(line, (attr) >= GX_VA_PNMTXIDX && (attr) < GX_VA_MAX_ATTR, "GXSetVtxDesc: Invalid vertex attribute name")
|
||||
#define CHECK_ATTRNAME2(line, attr) ASSERTMSGLINE(line, (attr) >= GX_VA_POS && (attr) <= GX_VA_MAX_ATTR, "GXSetVtxAttrFmt: Invalid vertex attribute name")
|
||||
#define CHECK_ATTRNAME3(line, attr) ASSERTMSGLINE(line, (attr) >= GX_VA_POS && (attr) <= GX_LIGHT_ARRAY, "GXSetArray: Invalid vertex attribute name")
|
||||
#define CHECK_ATTRTYPE(line, type) ASSERTMSGLINE(line, (type) >= GX_NONE && (type) <= GX_INDEX16, "GXSetVtxDesc: Invalid vertex attribute type")
|
||||
#define CHECK_VTXFMT(line, vtxfmt) ASSERTMSGLINE(line, (vtxfmt) < GX_MAX_VTXFMT, "GXSetVtxAttrFmt: Format Index is out of range")
|
||||
#define CHECK_FRAC(line, frac) ASSERTMSGLINE(line, (frac) < 32, "GXSetVtxAttrFmt: Frac value is >= 32")
|
||||
#define CHECK_LISTPTR(line, list) ASSERTMSGLINE(line, (list) != NULL, "GXSetVtxAttrFmt: list pointer is NULL")
|
||||
|
||||
static void __GXXfVtxSpecs(void)
|
||||
{
|
||||
u32 nCols = 0;
|
||||
u32 nNrm;
|
||||
u32 nTex;
|
||||
u32 reg;
|
||||
|
||||
nCols = GET_REG_FIELD(gx->vcdLo, 2, 13) ? 1 : 0;
|
||||
nCols += GET_REG_FIELD(gx->vcdLo, 2, 15) ? 1 : 0;
|
||||
nNrm = gx->hasBiNrms ? 2 : gx->hasNrms ? 1 : 0;
|
||||
nTex = 0;
|
||||
nTex += GET_REG_FIELD(gx->vcdHi, 2, 0) ? 1 : 0;
|
||||
nTex += GET_REG_FIELD(gx->vcdHi, 2, 2) ? 1 : 0;
|
||||
nTex += GET_REG_FIELD(gx->vcdHi, 2, 4) ? 1 : 0;
|
||||
nTex += GET_REG_FIELD(gx->vcdHi, 2, 6) ? 1 : 0;
|
||||
nTex += GET_REG_FIELD(gx->vcdHi, 2, 8) ? 1 : 0;
|
||||
nTex += GET_REG_FIELD(gx->vcdHi, 2, 10) ? 1 : 0;
|
||||
nTex += GET_REG_FIELD(gx->vcdHi, 2, 12) ? 1 : 0;
|
||||
nTex += GET_REG_FIELD(gx->vcdHi, 2, 14) ? 1 : 0;
|
||||
reg = (nCols) | (nNrm << 2) | (nTex << 4);
|
||||
GX_WRITE_XF_REG(8, reg);
|
||||
gx->bpSentNot = 1;
|
||||
}
|
||||
|
||||
static inline void SETVCDATTR(GXAttr Attr, GXAttrType Type)
|
||||
{
|
||||
switch (Attr) {
|
||||
case GX_VA_PNMTXIDX: SET_REG_FIELD(0xD4, gx->vcdLo, 1, 0, Type); break;
|
||||
case GX_VA_TEX0MTXIDX: SET_REG_FIELD(0xD5, gx->vcdLo, 1, 1, Type); break;
|
||||
case GX_VA_TEX1MTXIDX: SET_REG_FIELD(0xD6, gx->vcdLo, 1, 2, Type); break;
|
||||
case GX_VA_TEX2MTXIDX: SET_REG_FIELD(0xD7, gx->vcdLo, 1, 3, Type); break;
|
||||
case GX_VA_TEX3MTXIDX: SET_REG_FIELD(0xD8, gx->vcdLo, 1, 4, Type); break;
|
||||
case GX_VA_TEX4MTXIDX: SET_REG_FIELD(0xD9, gx->vcdLo, 1, 5, Type); break;
|
||||
case GX_VA_TEX5MTXIDX: SET_REG_FIELD(0xDA, gx->vcdLo, 1, 6, Type); break;
|
||||
case GX_VA_TEX6MTXIDX: SET_REG_FIELD(0xDB, gx->vcdLo, 1, 7, Type); break;
|
||||
case GX_VA_TEX7MTXIDX: SET_REG_FIELD(0xDC, gx->vcdLo, 1, 8, Type); break;
|
||||
case GX_VA_POS: SET_REG_FIELD(0xDD, gx->vcdLo, 2, 9, Type); break;
|
||||
case GX_VA_NRM:
|
||||
if (Type != GX_NONE) {
|
||||
gx->hasNrms = 1;
|
||||
gx->hasBiNrms = 0;
|
||||
gx->nrmType = Type;
|
||||
} else {
|
||||
gx->hasNrms = 0;
|
||||
}
|
||||
break;
|
||||
case GX_VA_NBT:
|
||||
if (Type != GX_NONE) {
|
||||
gx->hasBiNrms = 1;
|
||||
gx->hasNrms = 0;
|
||||
gx->nrmType = Type;
|
||||
} else {
|
||||
gx->hasBiNrms = 0;
|
||||
}
|
||||
break;
|
||||
case GX_VA_CLR0: SET_REG_FIELD(0xF6, gx->vcdLo, 2, 13, Type); break;
|
||||
case GX_VA_CLR1: SET_REG_FIELD(0xF7, gx->vcdLo, 2, 15, Type); break;
|
||||
case GX_VA_TEX0: SET_REG_FIELD(0xF8, gx->vcdHi, 2, 0, Type); break;
|
||||
case GX_VA_TEX1: SET_REG_FIELD(0xF9, gx->vcdHi, 2, 2, Type); break;
|
||||
case GX_VA_TEX2: SET_REG_FIELD(0xFA, gx->vcdHi, 2, 4, Type); break;
|
||||
case GX_VA_TEX3: SET_REG_FIELD(0xFB, gx->vcdHi, 2, 6, Type); break;
|
||||
case GX_VA_TEX4: SET_REG_FIELD(0xFC, gx->vcdHi, 2, 8, Type); break;
|
||||
case GX_VA_TEX5: SET_REG_FIELD(0xFD, gx->vcdHi, 2, 10, Type); break;
|
||||
case GX_VA_TEX6: SET_REG_FIELD(0xFE, gx->vcdHi, 2, 12, Type); break;
|
||||
case GX_VA_TEX7: SET_REG_FIELD(0xFF, gx->vcdHi, 2, 14, Type); break;
|
||||
}
|
||||
}
|
||||
|
||||
void GXSetVtxDesc(GXAttr attr, GXAttrType type)
|
||||
{
|
||||
CHECK_GXBEGIN(0xCC, "GXSetVtxDesc");
|
||||
CHECK_ATTRNAME(0xCF, attr);
|
||||
CHECK_ATTRTYPE(0xD1, type);
|
||||
|
||||
SETVCDATTR(attr, type);
|
||||
if (gx->hasNrms || gx->hasBiNrms) {
|
||||
SET_REG_FIELD(0xD7, gx->vcdLo, 2, 11, gx->nrmType);
|
||||
} else {
|
||||
SET_REG_FIELD(0x00, gx->vcdLo, 2, 11, 0);
|
||||
}
|
||||
gx->dirtyState |= 8;
|
||||
}
|
||||
|
||||
void GXSetVtxDescv(GXVtxDescList *attrPtr)
|
||||
{
|
||||
CHECK_GXBEGIN(0xF5, "GXSetVtxDescv");
|
||||
CHECK_ATTRPTR(0xF6, attrPtr);
|
||||
while (attrPtr->attr != 0xFF) {
|
||||
CHECK_ATTRNAME(0xFB, attrPtr->attr);
|
||||
CHECK_ATTRTYPE(0xFE, attrPtr->type);
|
||||
SETVCDATTR(attrPtr->attr, attrPtr->type);
|
||||
attrPtr++;
|
||||
}
|
||||
if (gx->hasNrms || gx->hasBiNrms) {
|
||||
SET_REG_FIELD(0x107, gx->vcdLo, 2, 11, gx->nrmType);
|
||||
} else {
|
||||
SET_REG_FIELD(0x107, gx->vcdLo, 2, 11, 0);
|
||||
}
|
||||
gx->dirtyState |= 8;
|
||||
}
|
||||
|
||||
void __GXSetVCD(void)
|
||||
{
|
||||
GX_WRITE_SOME_REG4(8, 0x50, gx->vcdLo, -12);
|
||||
GX_WRITE_SOME_REG4(8, 0x60, gx->vcdHi, -12);
|
||||
__GXXfVtxSpecs();
|
||||
}
|
||||
|
||||
void __GXCalculateVLim() {
|
||||
static u8 tbl1[] = { 0, 4, 1, 2 };
|
||||
static u8 tbl2[] = { 0, 8, 1, 2 };
|
||||
static u8 tbl3[] = { 0, 12, 1, 2 };
|
||||
|
||||
GXCompCnt nc = 0;
|
||||
unsigned long vlm;
|
||||
unsigned long b;
|
||||
unsigned long vl;
|
||||
unsigned long vh;
|
||||
unsigned long va;
|
||||
|
||||
if (gx->vNum != 0) {
|
||||
vl = gx->vcdLo;
|
||||
vh = gx->vcdHi;
|
||||
va = gx->vatA[0];
|
||||
nc = GET_REG_FIELD(va, 1, 9);
|
||||
|
||||
vlm = GET_REG_FIELD(vl, 1, 0);
|
||||
vlm += (u8)GET_REG_FIELD(vl, 1, 1);
|
||||
vlm += (u8)GET_REG_FIELD(vl, 1, 2);
|
||||
vlm += (u8)GET_REG_FIELD(vl, 1, 3);
|
||||
vlm += (u8)GET_REG_FIELD(vl, 1, 4);
|
||||
vlm += (u8)GET_REG_FIELD(vl, 1, 5);
|
||||
vlm += (u8)GET_REG_FIELD(vl, 1, 6);
|
||||
vlm += (u8)GET_REG_FIELD(vl, 1, 7);
|
||||
vlm += (u8)GET_REG_FIELD(vl, 1, 8);
|
||||
vlm += tbl3[(u8)GET_REG_FIELD(vl, 2, 9)];
|
||||
|
||||
if (nc == 1) {
|
||||
b = 3;
|
||||
} else {
|
||||
b = 1;
|
||||
}
|
||||
|
||||
vlm += tbl3[(u8)GET_REG_FIELD(vl, 2, 11)] * b;
|
||||
vlm += tbl1[(u8)GET_REG_FIELD(vl, 2, 13)];
|
||||
vlm += tbl1[(u8)GET_REG_FIELD(vl, 2, 15)];
|
||||
vlm += tbl2[(u8)GET_REG_FIELD(vh, 2, 0)];
|
||||
vlm += tbl2[(u8)GET_REG_FIELD(vh, 2, 2)];
|
||||
vlm += tbl2[(u8)GET_REG_FIELD(vh, 2, 4)];
|
||||
vlm += tbl2[(u8)GET_REG_FIELD(vh, 2, 6)];
|
||||
vlm += tbl2[(u8)GET_REG_FIELD(vh, 2, 8)];
|
||||
vlm += tbl2[(u8)GET_REG_FIELD(vh, 2, 10)];
|
||||
vlm += tbl2[(u8)GET_REG_FIELD(vh, 2, 12)];
|
||||
vlm += tbl2[(u8)GET_REG_FIELD(vh, 2, 14)];
|
||||
gx->vLim = vlm;
|
||||
}
|
||||
}
|
||||
|
||||
void GXGetVtxDesc(GXAttr attr, GXAttrType *type)
|
||||
{
|
||||
u32 cpType;
|
||||
|
||||
CHECK_GXBEGIN(0x185, "GXGetVtxDesc");
|
||||
CHECK_ATTRNAME(0x187, attr);
|
||||
|
||||
switch (attr) {
|
||||
case GX_VA_PNMTXIDX: cpType = GET_REG_FIELD(gx->vcdLo, 1, 0); break;
|
||||
case GX_VA_TEX0MTXIDX: cpType = GET_REG_FIELD(gx->vcdLo, 1, 1); break;
|
||||
case GX_VA_TEX1MTXIDX: cpType = GET_REG_FIELD(gx->vcdLo, 1, 2); break;
|
||||
case GX_VA_TEX2MTXIDX: cpType = GET_REG_FIELD(gx->vcdLo, 1, 3); break;
|
||||
case GX_VA_TEX3MTXIDX: cpType = GET_REG_FIELD(gx->vcdLo, 1, 4); break;
|
||||
case GX_VA_TEX4MTXIDX: cpType = GET_REG_FIELD(gx->vcdLo, 1, 5); break;
|
||||
case GX_VA_TEX5MTXIDX: cpType = GET_REG_FIELD(gx->vcdLo, 1, 6); break;
|
||||
case GX_VA_TEX6MTXIDX: cpType = GET_REG_FIELD(gx->vcdLo, 1, 7); break;
|
||||
case GX_VA_TEX7MTXIDX: cpType = GET_REG_FIELD(gx->vcdLo, 1, 8); break;
|
||||
case GX_VA_POS: cpType = GET_REG_FIELD(gx->vcdLo, 2, 9); break;
|
||||
case GX_VA_NRM: cpType = gx->hasNrms ? GET_REG_FIELD(gx->vcdLo, 2, 11) : 0; break;
|
||||
case GX_VA_NBT: cpType = gx->hasBiNrms ? GET_REG_FIELD(gx->vcdLo, 2, 11) : 0; break;
|
||||
case GX_VA_CLR0: cpType = GET_REG_FIELD(gx->vcdLo, 2, 13); break;
|
||||
case GX_VA_CLR1: cpType = GET_REG_FIELD(gx->vcdLo, 2, 15); break;
|
||||
case GX_VA_TEX0: cpType = GET_REG_FIELD(gx->vcdHi, 2, 0); break;
|
||||
case GX_VA_TEX1: cpType = GET_REG_FIELD(gx->vcdHi, 2, 2); break;
|
||||
case GX_VA_TEX2: cpType = GET_REG_FIELD(gx->vcdHi, 2, 4); break;
|
||||
case GX_VA_TEX3: cpType = GET_REG_FIELD(gx->vcdHi, 2, 6); break;
|
||||
case GX_VA_TEX4: cpType = GET_REG_FIELD(gx->vcdHi, 2, 8); break;
|
||||
case GX_VA_TEX5: cpType = GET_REG_FIELD(gx->vcdHi, 2, 10); break;
|
||||
case GX_VA_TEX6: cpType = GET_REG_FIELD(gx->vcdHi, 2, 12); break;
|
||||
case GX_VA_TEX7: cpType = GET_REG_FIELD(gx->vcdHi, 2, 14); break;
|
||||
default: cpType = 0; break;
|
||||
}
|
||||
*type = cpType;
|
||||
}
|
||||
|
||||
void GXGetVtxDescv(GXVtxDescList *vcd)
|
||||
{
|
||||
GXAttr attr;
|
||||
|
||||
CHECK_GXBEGIN(0x1BA, "GXGetVtxDescv");
|
||||
CHECK_ATTRPTR(0x1BC, vcd);
|
||||
for (attr = 0; attr < GX_VA_MAX_ATTR; attr++) {
|
||||
vcd[attr].attr = attr;
|
||||
GXGetVtxDesc(attr, &vcd[attr].type);
|
||||
}
|
||||
vcd[attr].attr = 0xFF;
|
||||
}
|
||||
|
||||
void GXClearVtxDesc(void)
|
||||
{
|
||||
CHECK_GXBEGIN(0x1D3, "GXClearVtxDesc");
|
||||
gx->vcdLo = 0;
|
||||
SET_REG_FIELD(0x00, gx->vcdLo, 2, 9, 1);
|
||||
gx->vcdHi = 0;
|
||||
gx->hasNrms = 0;
|
||||
gx->hasBiNrms = 0;
|
||||
gx->dirtyState |= 8;
|
||||
}
|
||||
|
||||
static inline void SETVAT(u32 *va, u32 *vb, u32 *vc, GXAttr attr, GXCompCnt cnt, GXCompType type, u8 shft)
|
||||
{
|
||||
switch (attr) {
|
||||
case GX_VA_POS:
|
||||
SET_REG_FIELD(511, *va, 1, 0, cnt);
|
||||
SET_REG_FIELD(512, *va, 3, 1, type);
|
||||
SET_REG_FIELD(513, *va, 5, 4, shft);
|
||||
break;
|
||||
case GX_VA_NRM:
|
||||
case GX_VA_NBT:
|
||||
SET_REG_FIELD(521, *va, 3, 10, type);
|
||||
if (cnt == GX_NRM_NBT3) {
|
||||
SET_REG_FIELD(0, *va, 1, 9, 1);
|
||||
SET_REG_FIELD(0, *va, 1, 31, 1);
|
||||
} else {
|
||||
SET_REG_FIELD(527, *va, 1, 9, cnt);
|
||||
SET_REG_FIELD(528, *va, 1, 31, 0);
|
||||
}
|
||||
break;
|
||||
case GX_VA_CLR0:
|
||||
SET_REG_FIELD(0x215, *va, 1, 13, cnt);
|
||||
SET_REG_FIELD(0x216, *va, 3, 14, type);
|
||||
break;
|
||||
case GX_VA_CLR1:
|
||||
SET_REG_FIELD(0x219, *va, 1, 0x11, cnt);
|
||||
SET_REG_FIELD(0x21A, *va, 3, 18, type);
|
||||
break;
|
||||
case GX_VA_TEX0:
|
||||
SET_REG_FIELD(0x21D, *va, 1, 0x15, cnt);
|
||||
SET_REG_FIELD(0x21E, *va, 3, 0x16, type);
|
||||
SET_REG_FIELD(0x21F, *va, 5, 0x19, shft);
|
||||
break;
|
||||
case GX_VA_TEX1:
|
||||
SET_REG_FIELD(0x222, *vb, 1, 0, cnt);
|
||||
SET_REG_FIELD(0x223, *vb, 3, 1, type);
|
||||
SET_REG_FIELD(0x224, *vb, 5, 4, shft);
|
||||
break;
|
||||
case GX_VA_TEX2:
|
||||
SET_REG_FIELD(0x227, *vb, 1, 9, cnt);
|
||||
SET_REG_FIELD(0x228, *vb, 3, 10, type);
|
||||
SET_REG_FIELD(0x229, *vb, 5, 13, shft);
|
||||
break;
|
||||
case GX_VA_TEX3:
|
||||
SET_REG_FIELD(0x22C, *vb, 1, 18, cnt);
|
||||
SET_REG_FIELD(0x22D, *vb, 3, 19, type);
|
||||
SET_REG_FIELD(0x22E, *vb, 5, 22, shft);
|
||||
break;
|
||||
case GX_VA_TEX4:
|
||||
SET_REG_FIELD(0x231, *vb, 1, 27, cnt);
|
||||
SET_REG_FIELD(0x232, *vb, 3, 28, type);
|
||||
SET_REG_FIELD(0x233, *vc, 5, 0, shft);
|
||||
break;
|
||||
case GX_VA_TEX5:
|
||||
SET_REG_FIELD(0x236, *vc, 1, 5, cnt);
|
||||
SET_REG_FIELD(0x237, *vc, 3, 6, type);
|
||||
SET_REG_FIELD(0x238, *vc, 5, 9, shft);
|
||||
break;
|
||||
case GX_VA_TEX6:
|
||||
SET_REG_FIELD(0x23B, *vc, 1, 14, cnt);
|
||||
SET_REG_FIELD(0x23C, *vc, 3, 15, type);
|
||||
SET_REG_FIELD(0x23D, *vc, 5, 18, shft);
|
||||
break;
|
||||
case GX_VA_TEX7:
|
||||
SET_REG_FIELD(0x240, *vc, 1, 23, cnt);
|
||||
SET_REG_FIELD(0x241, *vc, 3, 24, type);
|
||||
SET_REG_FIELD(0x242, *vc, 5, 27, shft);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GXSetVtxAttrFmt(GXVtxFmt vtxfmt, GXAttr attr, GXCompCnt cnt, GXCompType type, u8 frac)
|
||||
{
|
||||
u32 *va;
|
||||
u32 *vb;
|
||||
u32 *vc;
|
||||
|
||||
CHECK_GXBEGIN(0x252, "GXSetVtxAttrFmt");
|
||||
CHECK_VTXFMT(0x253, vtxfmt);
|
||||
CHECK_ATTRNAME2(0x255, attr);
|
||||
CHECK_FRAC(0x256, frac);
|
||||
va = &gx->vatA[vtxfmt];
|
||||
vb = &gx->vatB[vtxfmt];
|
||||
vc = &gx->vatC[vtxfmt];
|
||||
SETVAT(va, vb, vc, attr, cnt, type, frac);
|
||||
gx->dirtyState |= 0x10;
|
||||
gx->dirtyVAT |= (u8)(1 << (u8)vtxfmt);
|
||||
}
|
||||
|
||||
void GXSetVtxAttrFmtv(GXVtxFmt vtxfmt, const GXVtxAttrFmtList *list)
|
||||
{
|
||||
u32 *va;
|
||||
u32 *vb;
|
||||
u32 *vc;
|
||||
|
||||
CHECK_GXBEGIN(0x27B, "GXSetVtxAttrFmtv");
|
||||
CHECK_LISTPTR(0x27C, list);
|
||||
CHECK_VTXFMT(0x27D, vtxfmt);
|
||||
va = &gx->vatA[vtxfmt];
|
||||
vb = &gx->vatB[vtxfmt];
|
||||
vc = &gx->vatC[vtxfmt];
|
||||
while (list->attr != GX_VA_NULL) {
|
||||
CHECK_ATTRNAME2(0x286, list->attr);
|
||||
CHECK_FRAC(0x287, list->frac);
|
||||
SETVAT(va, vb, vc, list->attr, list->cnt, list->type, list->frac);
|
||||
list++;
|
||||
}
|
||||
gx->dirtyState |= 0x10;
|
||||
gx->dirtyVAT |= (u8)(1 << (u8)vtxfmt);
|
||||
}
|
||||
|
||||
void __GXSetVAT(void)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (gx->dirtyVAT & (1 << (u8)i)) {
|
||||
GX_WRITE_SOME_REG4(8, i | 0x70, gx->vatA[i], i - 12);
|
||||
GX_WRITE_SOME_REG4(8, i | 0x80, gx->vatB[i], i - 12);
|
||||
GX_WRITE_SOME_REG4(8, i | 0x90, gx->vatC[i], i - 12);
|
||||
}
|
||||
}
|
||||
gx->dirtyVAT = 0;
|
||||
}
|
||||
|
||||
void GXGetVtxAttrFmt(GXVtxFmt fmt, GXAttr attr, GXCompCnt *cnt, GXCompType *type, u8 *frac)
|
||||
{
|
||||
u32 *va;
|
||||
u32 *vb;
|
||||
u32 *vc;
|
||||
|
||||
CHECK_GXBEGIN(0x2CF, "GXGetVtxAttrFmt");
|
||||
CHECK_VTXFMT(0x2D0, fmt);
|
||||
va = &gx->vatA[fmt];
|
||||
vb = &gx->vatB[fmt];
|
||||
vc = &gx->vatC[fmt];
|
||||
switch (attr) {
|
||||
case GX_VA_POS:
|
||||
*cnt = GET_REG_FIELD(*va, 1, 0);
|
||||
*type = GET_REG_FIELD(*va, 3, 1);
|
||||
*frac = (u8)(*va >> 4) & 0x1F; // GET_REG_FIELD(*va, 5, 4)
|
||||
return;
|
||||
case GX_VA_NRM:
|
||||
case GX_VA_NBT:
|
||||
*cnt = GET_REG_FIELD(*va, 1, 9);
|
||||
if (*cnt == GX_TEX_ST && (u8)(*va >> 0x1F) != 0) {
|
||||
*cnt = GX_NRM_NBT3;
|
||||
}
|
||||
*type = GET_REG_FIELD(*va, 3, 10);
|
||||
*frac = 0;
|
||||
return;
|
||||
case GX_VA_CLR0:
|
||||
*cnt = GET_REG_FIELD(*va, 1, 13);
|
||||
*type = GET_REG_FIELD(*va, 3, 14);
|
||||
*frac = 0;
|
||||
return;
|
||||
case GX_VA_CLR1:
|
||||
*cnt = GET_REG_FIELD(*va, 1, 17);
|
||||
*type = GET_REG_FIELD(*va, 3, 18);
|
||||
*frac = 0;
|
||||
return;
|
||||
case GX_VA_TEX0:
|
||||
*cnt = GET_REG_FIELD(*va, 1, 21);
|
||||
*type = GET_REG_FIELD(*va, 3, 22);
|
||||
*frac = (u8)(*va >> 0x19U) & 0x1F;
|
||||
return;
|
||||
case GX_VA_TEX1:
|
||||
*cnt = GET_REG_FIELD(*vb, 1, 0);
|
||||
*type = GET_REG_FIELD(*vb, 3, 1);
|
||||
*frac = (u8)(*vb >> 4U) & 0x1F;
|
||||
return;
|
||||
case GX_VA_TEX2:
|
||||
*cnt = GET_REG_FIELD(*vb, 1, 9);
|
||||
*type = GET_REG_FIELD(*vb, 3, 10);
|
||||
*frac = (u8)(*vb >> 0xDU) & 0x1F;
|
||||
return;
|
||||
case GX_VA_TEX3:
|
||||
*cnt = GET_REG_FIELD(*vb, 1, 18);
|
||||
*type = GET_REG_FIELD(*vb, 3, 19);
|
||||
*frac = (u8)(*vb >> 0x16U) & 0x1F;
|
||||
return;
|
||||
case GX_VA_TEX4:
|
||||
*cnt = GET_REG_FIELD(*vb, 1, 27);
|
||||
*type = GET_REG_FIELD(*vb, 3, 28);
|
||||
*frac = GET_REG_FIELD(*vc, 5, 0);
|
||||
return;
|
||||
case GX_VA_TEX5:
|
||||
*cnt = GET_REG_FIELD(*vc, 1, 5);
|
||||
*type = GET_REG_FIELD(*vc, 3, 6);
|
||||
*frac = (u8)(*vc >> 9U) & 0x1F;
|
||||
return;
|
||||
case GX_VA_TEX6:
|
||||
*cnt = GET_REG_FIELD(*vc, 1, 14);
|
||||
*type = GET_REG_FIELD(*vc, 3, 15);
|
||||
*frac = (u8)(*vc >> 0x12) & 0x1F;
|
||||
return;
|
||||
case GX_VA_TEX7:
|
||||
*cnt = GET_REG_FIELD(*vc, 1, 23);
|
||||
*type = GET_REG_FIELD(*vc, 3, 24);
|
||||
*frac = (int)(*vc >> 0x1BU);
|
||||
return;
|
||||
default:
|
||||
*cnt = GX_TEX_ST;
|
||||
*type = GX_RGB565;
|
||||
*frac = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void GXGetVtxAttrFmtv(GXVtxFmt fmt, GXVtxAttrFmtList *vat)
|
||||
{
|
||||
GXAttr attr;
|
||||
|
||||
CHECK_GXBEGIN(0x330, "GXGetVtxAttrFmtv");
|
||||
CHECK_LISTPTR(0x331, vat);
|
||||
CHECK_VTXFMT(0x332, fmt);
|
||||
for (attr = GX_VA_POS; attr < GX_VA_MAX_ATTR; attr++) {
|
||||
vat->attr = attr;
|
||||
GXGetVtxAttrFmt(fmt, attr, &vat->cnt, &vat->type, &vat->frac);
|
||||
vat++;
|
||||
}
|
||||
vat->attr = GX_VA_NULL;
|
||||
}
|
||||
|
||||
void GXSetArray(GXAttr attr, const void *base_ptr, u8 stride)
|
||||
{
|
||||
GXAttr cpAttr;
|
||||
unsigned long phyAddr;
|
||||
|
||||
attr; // needed to match
|
||||
|
||||
CHECK_GXBEGIN(0x34F, "GXSetArray");
|
||||
if (attr == GX_VA_NBT) {
|
||||
attr = GX_VA_NRM;
|
||||
}
|
||||
CHECK_ATTRNAME3(0x352, attr);
|
||||
cpAttr = attr - GX_VA_POS;
|
||||
phyAddr = (u32)base_ptr & 0x3FFFFFFF;
|
||||
GX_WRITE_SOME_REG2(8, cpAttr | 0xA0, phyAddr, cpAttr - 12);
|
||||
GX_WRITE_SOME_REG3(8, cpAttr | 0xB0, stride, cpAttr - 12);
|
||||
}
|
||||
|
||||
void GXInvalidateVtxCache(void)
|
||||
{
|
||||
CHECK_GXBEGIN(0x368, "GXInvalidateVtxCache");
|
||||
GX_WRITE_U8(0x48);
|
||||
}
|
||||
|
||||
void GXSetTexCoordGen2(GXTexCoordID dst_coord, GXTexGenType func, GXTexGenSrc src_param, u32 mtx, GXBool normalize, u32 pt_texmtx)
|
||||
{
|
||||
u32 reg = 0;
|
||||
u32 row;
|
||||
u32 bumprow; // unused
|
||||
u32 form;
|
||||
GXAttr mtxIdAttr;
|
||||
|
||||
CHECK_GXBEGIN(0x392, "GXSetTexCoordGen");
|
||||
ASSERTMSGLINE(0x393, dst_coord < 8, "GXSetTexCoordGen: Invalid coordinate Id");
|
||||
form = 0;
|
||||
row = 5;
|
||||
switch (src_param) {
|
||||
case GX_TG_POS: row = 0; form = 1; break;
|
||||
case GX_TG_NRM: row = 1; form = 1; break;
|
||||
case GX_TG_BINRM: row = 3; form = 1; break;
|
||||
case GX_TG_TANGENT: row = 4; form = 1; break;
|
||||
case GX_TG_COLOR0: row = 2; break;
|
||||
case GX_TG_COLOR1: row = 2; break;
|
||||
case GX_TG_TEX0: row = 5; break;
|
||||
case GX_TG_TEX1: row = 6; break;
|
||||
case GX_TG_TEX2: row = 7; break;
|
||||
case GX_TG_TEX3: row = 8; break;
|
||||
case GX_TG_TEX4: row = 9; break;
|
||||
case GX_TG_TEX5: row = 10; break;
|
||||
case GX_TG_TEX6: row = 11; break;
|
||||
case GX_TG_TEX7: row = 12; break;
|
||||
case GX_TG_TEXCOORD0: bumprow; break;
|
||||
case GX_TG_TEXCOORD1: bumprow; break;
|
||||
case GX_TG_TEXCOORD2: bumprow; break;
|
||||
case GX_TG_TEXCOORD3: bumprow; break;
|
||||
case GX_TG_TEXCOORD4: bumprow; break;
|
||||
case GX_TG_TEXCOORD5: bumprow; break;
|
||||
case GX_TG_TEXCOORD6: bumprow; break;
|
||||
default:
|
||||
ASSERTMSGLINE(0x3AF, 0, "GXSetTexCoordGen: Invalid source parameter");
|
||||
break;
|
||||
}
|
||||
switch (func)
|
||||
{
|
||||
case GX_TG_MTX2x4:
|
||||
SET_REG_FIELD(0x3B8, reg, 1, 1, 0);
|
||||
SET_REG_FIELD(0x3B9, reg, 1, 2, form);
|
||||
SET_REG_FIELD(0x3BA, reg, 3, 4, 0);
|
||||
SET_REG_FIELD(0x3BB, reg, 5, 7, row);
|
||||
break;
|
||||
case GX_TG_MTX3x4:
|
||||
SET_REG_FIELD(0x3BF, reg, 1, 1, 1);
|
||||
SET_REG_FIELD(0x3C0, reg, 1, 2, form);
|
||||
SET_REG_FIELD(0x3C1, reg, 3, 4, 0);
|
||||
SET_REG_FIELD(0x3C2, reg, 5, 7, row);
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
ASSERTMSGLINE(0x3CF, src_param >= 12 && src_param <= 18, "GXSetTexCoordGen: Bump source texture value is invalid");
|
||||
SET_REG_FIELD(0x3D0, reg, 1, 1, 0);
|
||||
SET_REG_FIELD(0x3D1, reg, 1, 2, form);
|
||||
SET_REG_FIELD(0x3D2, reg, 3, 4, 1);
|
||||
SET_REG_FIELD(0x3D3, reg, 5, 7, row);
|
||||
SET_REG_FIELD(0x3D4, reg, 3, 12, src_param - 12);
|
||||
SET_REG_FIELD(0x3D5, reg, 3, 15, func - 2);
|
||||
break;
|
||||
case GX_TG_SRTG:
|
||||
SET_REG_FIELD(0x3D9, reg, 1, 1, 0);
|
||||
SET_REG_FIELD(0x3DA, reg, 1, 2, form);
|
||||
if (src_param == GX_TG_COLOR0) {
|
||||
SET_REG_FIELD(0, reg, 3, 4, 2);
|
||||
} else {
|
||||
SET_REG_FIELD(0, reg, 3, 4, 3);
|
||||
}
|
||||
SET_REG_FIELD(0, reg, 5, 7, 2);
|
||||
break;
|
||||
default:
|
||||
ASSERTMSGLINE(0x3E5, 0, "GXSetTexCoordGen: Invalid function");
|
||||
break;
|
||||
}
|
||||
GX_WRITE_XF_REG(dst_coord + 0x40, reg);
|
||||
reg = 0;
|
||||
SET_REG_FIELD(0x3F8, reg, 6, 0, pt_texmtx - 64);
|
||||
SET_REG_FIELD(0x3F9, reg, 1, 8, normalize);
|
||||
GX_WRITE_XF_REG(dst_coord + 0x50, reg);
|
||||
switch (dst_coord) {
|
||||
case GX_TEXCOORD0: SET_REG_FIELD(0x402, gx->matIdxA, 6, 6, mtx); break;
|
||||
case GX_TEXCOORD1: SET_REG_FIELD(0x403, gx->matIdxA, 6, 12, mtx); break;
|
||||
case GX_TEXCOORD2: SET_REG_FIELD(0x404, gx->matIdxA, 6, 18, mtx); break;
|
||||
case GX_TEXCOORD3: SET_REG_FIELD(0x405, gx->matIdxA, 6, 24, mtx); break;
|
||||
case GX_TEXCOORD4: SET_REG_FIELD(0x406, gx->matIdxB, 6, 0, mtx); break;
|
||||
case GX_TEXCOORD5: SET_REG_FIELD(0x407, gx->matIdxB, 6, 6, mtx); break;
|
||||
case GX_TEXCOORD6: SET_REG_FIELD(0x408, gx->matIdxB, 6, 12, mtx); break;
|
||||
default: SET_REG_FIELD(0x409, gx->matIdxB, 6, 18, mtx); break;
|
||||
}
|
||||
mtxIdAttr = dst_coord + 1;
|
||||
__GXSetMatrixIndex(mtxIdAttr);
|
||||
}
|
||||
|
||||
void GXSetNumTexGens(u8 nTexGens)
|
||||
{
|
||||
CHECK_GXBEGIN(0x41B, "GXSetNumTexGens");
|
||||
SET_REG_FIELD(0x41D, gx->genMode, 4, 0, nTexGens);
|
||||
GX_WRITE_XF_REG(0x3F, nTexGens);
|
||||
gx->dirtyState |= 4;
|
||||
}
|
||||
335
src/dolphin/gx/GXBump.c
Normal file
335
src/dolphin/gx/GXBump.c
Normal file
|
|
@ -0,0 +1,335 @@
|
|||
#include <dolphin/gx.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <dolphin/gx/GXPriv.h>
|
||||
|
||||
#if DEBUG
|
||||
#define GX_WRITE_SOME_REG5(a, b) \
|
||||
do { \
|
||||
GX_WRITE_U8(a); \
|
||||
GX_WRITE_U32(b); \
|
||||
__gxVerif->rasRegs[(b >> 24) & 0xFF] = b; \
|
||||
} while (0)
|
||||
#else
|
||||
#define GX_WRITE_SOME_REG5(a, b) \
|
||||
do { \
|
||||
GX_WRITE_U8(a); \
|
||||
GX_WRITE_U32(b); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
void GXSetTevIndirect(GXTevStageID tev_stage, GXIndTexStageID ind_stage, GXIndTexFormat format, GXIndTexBiasSel bias_sel, GXIndTexMtxID matrix_sel,
|
||||
GXIndTexWrap wrap_s, GXIndTexWrap wrap_t, GXBool add_prev, GXBool utc_lod, GXIndTexAlphaSel alpha_sel)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
CHECK_GXBEGIN(0x92, "GXInitIndTexture");
|
||||
reg = 0;
|
||||
SET_REG_FIELD(0x81, reg, 2, 0, ind_stage);
|
||||
SET_REG_FIELD(0x82, reg, 2, 2, format);
|
||||
SET_REG_FIELD(0x83, reg, 3, 4, bias_sel);
|
||||
SET_REG_FIELD(0x84, reg, 2, 7, alpha_sel);
|
||||
SET_REG_FIELD(0x85, reg, 4, 9, matrix_sel);
|
||||
SET_REG_FIELD(0x86, reg, 3, 13, wrap_s);
|
||||
SET_REG_FIELD(0x87, reg, 3, 16, wrap_t);
|
||||
SET_REG_FIELD(0x88, reg, 1, 19, utc_lod);
|
||||
SET_REG_FIELD(0x89, reg, 1, 20, add_prev);
|
||||
SET_REG_FIELD(0x8A, reg, 8, 24, tev_stage + 16);
|
||||
GX_WRITE_SOME_REG5(0x61, reg);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetIndTexMtx(GXIndTexMtxID mtx_id, f32 offset[2][3], s8 scale_exp)
|
||||
{
|
||||
s32 mtx[6];
|
||||
u32 reg;
|
||||
u32 id;
|
||||
|
||||
CHECK_GXBEGIN(0xBA, "GXSetIndTexMtx");
|
||||
|
||||
switch (mtx_id) {
|
||||
case GX_ITM_0:
|
||||
case GX_ITM_1:
|
||||
case GX_ITM_2:
|
||||
id = mtx_id - 1;
|
||||
break;
|
||||
case GX_ITM_S0:
|
||||
case GX_ITM_S1:
|
||||
case GX_ITM_S2:
|
||||
id = mtx_id - 5;
|
||||
break;
|
||||
case GX_ITM_T0:
|
||||
case GX_ITM_T1:
|
||||
case GX_ITM_T2:
|
||||
id = mtx_id - 9;
|
||||
break;
|
||||
default:
|
||||
id = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
mtx[0] = (int)(1024.0f * offset[0][0]) & 0x7FF;
|
||||
mtx[1] = (int)(1024.0f * offset[1][0]) & 0x7FF;
|
||||
scale_exp += 0x11;
|
||||
reg = 0;
|
||||
SET_REG_FIELD(0xBD, reg, 11, 0, mtx[0]);
|
||||
SET_REG_FIELD(0xBE, reg, 11, 11, mtx[1]);
|
||||
SET_REG_FIELD(0xBF, reg, 2, 22, scale_exp & 3);
|
||||
SET_REG_FIELD(0xC0, reg, 8, 24, id * 3 + 6);
|
||||
GX_WRITE_SOME_REG5(0x61, reg);
|
||||
|
||||
mtx[2] = (int)(1024.0f * offset[0][1]) & 0x7FF;
|
||||
mtx[3] = (int)(1024.0f * offset[1][1]) & 0x7FF;
|
||||
reg = 0;
|
||||
SET_REG_FIELD(0xC6, reg, 11, 0, mtx[2]);
|
||||
SET_REG_FIELD(0xC7, reg, 11, 11, mtx[3]);
|
||||
SET_REG_FIELD(0xC8, reg, 2, 22, (scale_exp >> 2) & 3);
|
||||
SET_REG_FIELD(0xC9, reg, 8, 24, id * 3 + 7);
|
||||
GX_WRITE_SOME_REG5(0x61, reg);
|
||||
|
||||
mtx[4] = (int)(1024.0f * offset[0][2]) & 0x7FF;
|
||||
mtx[5] = (int)(1024.0f * offset[1][2]) & 0x7FF;
|
||||
reg = 0;
|
||||
SET_REG_FIELD(0xCF, reg, 11, 0, mtx[4]);
|
||||
SET_REG_FIELD(0xD0, reg, 11, 11, mtx[5]);
|
||||
SET_REG_FIELD(0xD1, reg, 2, 22, (scale_exp >> 4) & 3);
|
||||
SET_REG_FIELD(0xD2, reg, 8, 24, id * 3 + 8);
|
||||
GX_WRITE_SOME_REG5(0x61, reg);
|
||||
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetIndTexCoordScale(GXIndTexStageID ind_state, GXIndTexScale scale_s, GXIndTexScale scale_t)
|
||||
{
|
||||
CHECK_GXBEGIN(0xF9, "GXSetIndTexScale");
|
||||
|
||||
switch (ind_state) {
|
||||
case GX_INDTEXSTAGE0:
|
||||
SET_REG_FIELD(0xEA, gx->IndTexScale0, 4, 0, scale_s);
|
||||
SET_REG_FIELD(0xEB, gx->IndTexScale0, 4, 4, scale_t);
|
||||
SET_REG_FIELD(0xEC, gx->IndTexScale0, 8, 24, 0x25);
|
||||
GX_WRITE_SOME_REG5(0x61, gx->IndTexScale0);
|
||||
break;
|
||||
case GX_INDTEXSTAGE1:
|
||||
SET_REG_FIELD(0xF0, gx->IndTexScale0, 4, 8, scale_s);
|
||||
SET_REG_FIELD(0xF1, gx->IndTexScale0, 4, 12, scale_t);
|
||||
SET_REG_FIELD(0xF2, gx->IndTexScale0, 8, 24, 0x25);
|
||||
GX_WRITE_SOME_REG5(0x61, gx->IndTexScale0);
|
||||
break;
|
||||
case GX_INDTEXSTAGE2:
|
||||
SET_REG_FIELD(0xF6, gx->IndTexScale1, 4, 0, scale_s);
|
||||
SET_REG_FIELD(0xF7, gx->IndTexScale1, 4, 4, scale_t);
|
||||
SET_REG_FIELD(0xF8, gx->IndTexScale1, 8, 24, 0x26);
|
||||
GX_WRITE_SOME_REG5(0x61, gx->IndTexScale1);
|
||||
break;
|
||||
case GX_INDTEXSTAGE3:
|
||||
SET_REG_FIELD(0xFC, gx->IndTexScale1, 4, 8, scale_s);
|
||||
SET_REG_FIELD(0xFD, gx->IndTexScale1, 4, 12, scale_t);
|
||||
SET_REG_FIELD(0xFE, gx->IndTexScale1, 8, 24, 0x26);
|
||||
GX_WRITE_SOME_REG5(0x61, gx->IndTexScale1);
|
||||
break;
|
||||
default:
|
||||
ASSERTMSGLINE(0x115, 0, "GXSetIndTexCoordScale: Invalid Indirect Stage Id");
|
||||
break;
|
||||
}
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetIndTexOrder(GXIndTexStageID ind_stage, GXTexCoordID tex_coord, GXTexMapID tex_map)
|
||||
{
|
||||
CHECK_GXBEGIN(0x12E, "GXSetIndTexOrder");
|
||||
|
||||
ASSERTMSGLINE(0x11D, tex_map < 8, "GXSetIndTexOrder: Invalid direct texture Id");
|
||||
ASSERTMSGLINE(0x11E, tex_coord < 8, "GXSetIndTexOrder: Invalid texture coord");
|
||||
switch (ind_stage) {
|
||||
case GX_INDTEXSTAGE0:
|
||||
SET_REG_FIELD(0x122, gx->iref, 3, 0, tex_map);
|
||||
SET_REG_FIELD(0x123, gx->iref, 3, 3, tex_coord);
|
||||
break;
|
||||
case GX_INDTEXSTAGE1:
|
||||
SET_REG_FIELD(0x126, gx->iref, 3, 6, tex_map);
|
||||
SET_REG_FIELD(0x127, gx->iref, 3, 9, tex_coord);
|
||||
break;
|
||||
case GX_INDTEXSTAGE2:
|
||||
SET_REG_FIELD(0x12A, gx->iref, 3, 12, tex_map);
|
||||
SET_REG_FIELD(0x12B, gx->iref, 3, 15, tex_coord);
|
||||
break;
|
||||
case GX_INDTEXSTAGE3:
|
||||
SET_REG_FIELD(0x12E, gx->iref, 3, 18, tex_map);
|
||||
SET_REG_FIELD(0x12F, gx->iref, 3, 21, tex_coord);
|
||||
break;
|
||||
default:
|
||||
ASSERTMSGLINE(0x132, 0, "GXSetIndTexOrder: Invalid Indirect Stage Id");
|
||||
break;
|
||||
}
|
||||
GX_WRITE_SOME_REG5(0x61, gx->iref);
|
||||
gx->dirtyState |= 3;
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetNumIndStages(u8 nIndStages)
|
||||
{
|
||||
CHECK_GXBEGIN(0x144, "GXSetNumIndStages");
|
||||
ASSERTMSGLINE(0x146, nIndStages <= 4, "GXSetNumIndStages: Exceeds max. number of indirect texture stages");
|
||||
SET_REG_FIELD(0x147, gx->genMode, 3, 16, nIndStages);
|
||||
gx->dirtyState |= 6;
|
||||
}
|
||||
|
||||
#pragma dont_inline on
|
||||
void GXSetTevDirect(GXTevStageID tev_stage)
|
||||
{
|
||||
CHECK_GXBEGIN(0x158, "GXSetTevDirect");
|
||||
GXSetTevIndirect(tev_stage, GX_INDTEXSTAGE0, GX_ITF_8, GX_ITB_NONE, GX_ITM_OFF, GX_ITW_OFF, GX_ITW_OFF, 0U, 0, 0);
|
||||
}
|
||||
|
||||
void GXSetTevIndWarp(GXTevStageID tev_stage, GXIndTexStageID ind_stage, u8 signed_offset, u8 replace_mode, GXIndTexMtxID matrix_sel)
|
||||
{
|
||||
GXIndTexWrap wrap = (replace_mode != 0) ? GX_ITW_0 : GX_ITW_OFF;
|
||||
|
||||
CHECK_GXBEGIN(0x16E, "GXSetTevIndWarp");
|
||||
GXSetTevIndirect(tev_stage, ind_stage, GX_ITF_8, (signed_offset != 0) ? GX_ITB_STU : GX_ITB_NONE, matrix_sel, wrap, wrap, 0U, 0, 0);
|
||||
}
|
||||
|
||||
void GXSetTevIndTile(GXTevStageID tev_stage, GXIndTexStageID ind_stage, u16 tilesize_s, u16 tilesize_t, u16 tilespacing_s, u16 tilespacing_t,
|
||||
GXIndTexFormat format, GXIndTexMtxID matrix_sel, GXIndTexBiasSel bias_sel, GXIndTexAlphaSel alpha_sel)
|
||||
{
|
||||
GXIndTexWrap wrap_s;
|
||||
GXIndTexWrap wrap_t;
|
||||
f32 mtx[2][3];
|
||||
|
||||
CHECK_GXBEGIN(0x190, "GXSetTevIndTile");
|
||||
ASSERTMSGLINE(0x191, tev_stage < 16, "GXSetTevIndTile: Invalid tev stage id");
|
||||
ASSERTMSGLINE(0x192, ind_stage < 4, "GXSetTevIndTile: Invalid indirect stage id");
|
||||
switch (tilesize_s) {
|
||||
case 256:
|
||||
wrap_s = GX_ITW_256;
|
||||
break;
|
||||
case 128:
|
||||
wrap_s = GX_ITW_128;
|
||||
break;
|
||||
case 64:
|
||||
wrap_s = GX_ITW_64;
|
||||
break;
|
||||
case 32:
|
||||
wrap_s = GX_ITW_32;
|
||||
break;
|
||||
case 16:
|
||||
wrap_s = GX_ITW_16;
|
||||
break;
|
||||
default:
|
||||
ASSERTMSGLINE(0x19B, 0, "GXSetTevIndTile: Invalid tilesize for S coordinate");
|
||||
wrap_s = GX_ITW_OFF;
|
||||
break;
|
||||
}
|
||||
switch (tilesize_t) {
|
||||
case 256:
|
||||
wrap_t = GX_ITW_256;
|
||||
break;
|
||||
case 128:
|
||||
wrap_t = GX_ITW_128;
|
||||
break;
|
||||
case 64:
|
||||
wrap_t = GX_ITW_64;
|
||||
break;
|
||||
case 32:
|
||||
wrap_t = GX_ITW_32;
|
||||
break;
|
||||
case 16:
|
||||
wrap_t = GX_ITW_16;
|
||||
break;
|
||||
default:
|
||||
ASSERTMSGLINE(0x1A7, 0, "GXSetTevIndTile: Invalid tilesize for T coordinate");
|
||||
wrap_t = GX_ITW_OFF;
|
||||
break;
|
||||
}
|
||||
mtx[0][0] = tilespacing_s / 1024.0f;
|
||||
mtx[0][1] = mtx[0][2] = 0.0f;
|
||||
mtx[1][1] = tilespacing_t / 1024.0f;
|
||||
mtx[1][0] = mtx[1][2] = 0.0f;
|
||||
GXSetIndTexMtx(matrix_sel, mtx, 0xA);
|
||||
GXSetTevIndirect(tev_stage, ind_stage, format, bias_sel, matrix_sel, wrap_s, wrap_t, 0U, 1, alpha_sel);
|
||||
}
|
||||
#pragma dont_inline off
|
||||
|
||||
void GXSetTevIndBumpST(GXTevStageID tev_stage, GXIndTexStageID ind_stage, GXIndTexMtxID matrix_sel)
|
||||
{
|
||||
GXIndTexMtxID sm;
|
||||
GXIndTexMtxID tm;
|
||||
|
||||
CHECK_GXBEGIN(0x1CF, "GXSetTevIndBumpST");
|
||||
switch (matrix_sel) {
|
||||
case GX_ITM_0:
|
||||
sm = GX_ITM_S0;
|
||||
tm = GX_ITM_T0;
|
||||
break;
|
||||
case GX_ITM_1:
|
||||
sm = GX_ITM_S1;
|
||||
tm = GX_ITM_T1;
|
||||
break;
|
||||
case GX_ITM_2:
|
||||
sm = GX_ITM_S2;
|
||||
tm = GX_ITM_T2;
|
||||
break;
|
||||
default:
|
||||
ASSERTMSGLINE(0x1E0, 0, "GXSetTevIndBumpST: Invalid matrix selection");
|
||||
break;
|
||||
}
|
||||
GXSetTevIndirect(tev_stage, ind_stage, GX_ITF_8, GX_ITB_ST, sm, GX_ITW_0, GX_ITW_0, 0U, 0, 0);
|
||||
GXSetTevIndirect(tev_stage + 1, ind_stage, GX_ITF_8, GX_ITB_ST, tm, GX_ITW_0, GX_ITW_0, 1U, 0, 0);
|
||||
GXSetTevIndirect(tev_stage + 2, ind_stage, GX_ITF_8, GX_ITB_NONE, GX_ITM_OFF, GX_ITW_OFF, GX_ITW_OFF, 1U, 0, 0);
|
||||
}
|
||||
|
||||
void GXSetTevIndBumpXYZ(GXTevStageID tev_stage, GXIndTexStageID ind_stage, GXIndTexMtxID matrix_sel)
|
||||
{
|
||||
CHECK_GXBEGIN(0x214, "GXSetTevIndBumpXYZ");
|
||||
GXSetTevIndirect(tev_stage, ind_stage, GX_ITF_8, GX_ITB_STU, matrix_sel, GX_ITW_OFF, GX_ITW_OFF, 0U, 0, 0);
|
||||
}
|
||||
|
||||
void GXSetTevIndRepeat(GXTevStageID tev_stage)
|
||||
{
|
||||
CHECK_GXBEGIN(0x231, "GXSetTevIndRepeat");
|
||||
GXSetTevIndirect(tev_stage, GX_INDTEXSTAGE0, GX_ITF_8, GX_ITB_NONE, GX_ITM_OFF, GX_ITW_0, GX_ITW_0, 1U, 0, 0);
|
||||
}
|
||||
|
||||
void __GXUpdateBPMask(void)
|
||||
{
|
||||
u32 nIndStages;
|
||||
u32 i;
|
||||
u32 tmap;
|
||||
u32 new_imask;
|
||||
u32 nStages;
|
||||
u32 new_dmask;
|
||||
|
||||
new_imask = 0;
|
||||
new_dmask = 0;
|
||||
nIndStages = GET_REG_FIELD(gx->genMode, 3, 16);
|
||||
for (i = 0; i < nIndStages; i++) {
|
||||
switch (i) {
|
||||
case 0:
|
||||
tmap = GET_REG_FIELD(gx->iref, 3, 0);
|
||||
break;
|
||||
case 1:
|
||||
tmap = GET_REG_FIELD(gx->iref, 3, 6);
|
||||
break;
|
||||
case 2:
|
||||
tmap = GET_REG_FIELD(gx->iref, 3, 12);
|
||||
break;
|
||||
case 3:
|
||||
tmap = GET_REG_FIELD(gx->iref, 3, 18);
|
||||
break;
|
||||
}
|
||||
new_imask |= 1 << tmap;
|
||||
}
|
||||
|
||||
if ((u8)gx->bpMask != new_imask) {
|
||||
SET_REG_FIELD(0x26E, gx->bpMask, 8, 0, new_imask);
|
||||
GX_WRITE_SOME_REG5(0x61, gx->bpMask);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void __GXFlushTextureState(void)
|
||||
{
|
||||
GX_WRITE_SOME_REG5(0x61, gx->bpMask);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
83
src/dolphin/gx/GXDisplayList.c
Normal file
83
src/dolphin/gx/GXDisplayList.c
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <dolphin/gx.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <dolphin/gx/GXPriv.h>
|
||||
|
||||
static struct __GXFifoObj DisplayListFifo;
|
||||
static volatile struct __GXFifoObj *OldCPUFifo;
|
||||
static struct __GXData_struct __savedGXdata;
|
||||
|
||||
void GXBeginDisplayList(void *list, u32 size)
|
||||
{
|
||||
struct __GXFifoObj *CPUFifo = (struct __GXFifoObj *)GXGetCPUFifo();
|
||||
|
||||
CHECK_GXBEGIN(0x89, "GXBeginDisplayList");
|
||||
ASSERTMSGLINE(0x8A, !__GXData->inDispList, "GXBeginDisplayList: display list already in progress");
|
||||
ASSERTMSGLINE(0x8B, (size & 0x1F) == 0, "GXBeginDisplayList: size is not 32 byte aligned");
|
||||
ASSERTMSGLINE(0x8C, ((u32)list & 0x1F) == 0, "GXBeginDisplayList: list is not 32 byte aligned");
|
||||
if (gx->dirtyState != 0) {
|
||||
__GXSetDirtyState();
|
||||
}
|
||||
if (gx->dlSaveContext != 0) {
|
||||
memcpy(&__savedGXdata, gx, sizeof(__savedGXdata));
|
||||
}
|
||||
DisplayListFifo.base = (u8 *)list;
|
||||
DisplayListFifo.top = (u8 *)list + size - 4;
|
||||
DisplayListFifo.size = size;
|
||||
DisplayListFifo.count = 0;
|
||||
DisplayListFifo.rdPtr = list;
|
||||
DisplayListFifo.wrPtr = list;
|
||||
gx->inDispList = 1;
|
||||
GXSaveCPUFifo((GXFifoObj *)CPUFifo);
|
||||
OldCPUFifo = CPUFifo;
|
||||
GXSetCPUFifo((GXFifoObj *)&DisplayListFifo);
|
||||
}
|
||||
|
||||
unsigned long GXEndDisplayList(void)
|
||||
{
|
||||
u32 ov;
|
||||
BOOL enabled;
|
||||
u32 cpenable;
|
||||
|
||||
CHECK_GXBEGIN(0xB5, "GXEndDisplayList");
|
||||
ASSERTMSGLINE(0xB6, gx->inDispList == TRUE, "GXEndDisplayList: no display list in progress");
|
||||
if (gx->dirtyState != 0) {
|
||||
__GXSetDirtyState();
|
||||
}
|
||||
ov = (__piReg[5] >> 26) & 1;
|
||||
__GXSaveCPUFifoAux(&DisplayListFifo);
|
||||
ASSERTMSGLINE(0xC3, !ov, "GXEndDisplayList: display list commands overflowed buffer");
|
||||
GXSetCPUFifo((GXFifoObj *)OldCPUFifo);
|
||||
if (gx->dlSaveContext != 0) {
|
||||
enabled = OSDisableInterrupts();
|
||||
cpenable = gx->cpEnable;
|
||||
memcpy(gx, &__savedGXdata, sizeof(*gx));
|
||||
gx->cpEnable = cpenable;
|
||||
OSRestoreInterrupts(enabled);
|
||||
}
|
||||
gx->inDispList = 0;
|
||||
if (!ov) {
|
||||
return DisplayListFifo.count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GXCallDisplayList(const void *list, u32 nbytes)
|
||||
{
|
||||
CHECK_GXBEGIN(0xEC, "GXCallDisplayList");
|
||||
ASSERTMSGLINE(0xED, !gx->inDispList, "GXCallDisplayList: display list already in progress");
|
||||
ASSERTMSGLINE(0xEE, (nbytes & 0x1F) == 0, "GXCallDisplayList: nbytes is not 32 byte aligned");
|
||||
ASSERTMSGLINE(0xEF, ((u32)list & 0x1F) == 0, "GXCallDisplayList: list is not 32 byte aligned");
|
||||
|
||||
if (gx->dirtyState != 0) {
|
||||
__GXSetDirtyState();
|
||||
}
|
||||
if (*(u32 *)&gx->vNumNot == 0) { // checks both vNum and bpSent
|
||||
__GXSendFlushPrim();
|
||||
}
|
||||
GX_WRITE_U8(0x40);
|
||||
GX_WRITE_U32((u32)list);
|
||||
GX_WRITE_U32(nbytes);
|
||||
}
|
||||
559
src/dolphin/gx/GXFifo.c
Normal file
559
src/dolphin/gx/GXFifo.c
Normal file
|
|
@ -0,0 +1,559 @@
|
|||
#include <dolphin/PPCArch.h>
|
||||
#include <dolphin/gx.h>
|
||||
#include <dolphin/os.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
#include <dolphin/gx/GXPriv.h>
|
||||
|
||||
static OSThread *__GXCurrentThread;
|
||||
static GXBool CPGPLinked;
|
||||
static BOOL GXOverflowSuspendInProgress;
|
||||
static GXBreakPtCallback BreakPointCB;
|
||||
static u32 __GXOverflowCount;
|
||||
|
||||
struct __GXFifoObj *CPUFifo;
|
||||
struct __GXFifoObj *GPFifo;
|
||||
void *__GXCurrentBP;
|
||||
|
||||
static void __GXFifoReadEnable(void);
|
||||
static void __GXFifoReadDisable(void);
|
||||
static void __GXFifoLink(u8 arg0);
|
||||
static void __GXWriteFifoIntEnable(u8 arg0, u8 arg1);
|
||||
static void __GXWriteFifoIntReset(u8 arg0, u8 arg1);
|
||||
|
||||
static void GXOverflowHandler(s16 interrupt, OSContext *context)
|
||||
{
|
||||
ASSERTLINE(0x179, !GXOverflowSuspendInProgress);
|
||||
|
||||
__GXOverflowCount++;
|
||||
__GXWriteFifoIntEnable(0, 1);
|
||||
__GXWriteFifoIntReset(1, 0);
|
||||
GXOverflowSuspendInProgress = TRUE;
|
||||
|
||||
OSSuspendThread(__GXCurrentThread);
|
||||
}
|
||||
|
||||
static void GXUnderflowHandler(s16 interrupt, OSContext *context)
|
||||
{
|
||||
ASSERTLINE(0x1A3, GXOverflowSuspendInProgress);
|
||||
|
||||
OSResumeThread(__GXCurrentThread);
|
||||
GXOverflowSuspendInProgress = FALSE;
|
||||
__GXWriteFifoIntReset(1U, 1U);
|
||||
__GXWriteFifoIntEnable(1U, 0U);
|
||||
}
|
||||
|
||||
#define SOME_SET_REG_MACRO(reg, size, shift, val) \
|
||||
do { \
|
||||
(reg) = (u32)__rlwimi((u32)(reg), (val), (shift), (32 - (shift) - (size)), (31 - (shift))); \
|
||||
} while (0);
|
||||
|
||||
static void GXBreakPointHandler(s16 interrupt, OSContext *context)
|
||||
{
|
||||
OSContext exceptionContext;
|
||||
|
||||
SOME_SET_REG_MACRO(gx->cpEnable, 1, 5, 0);
|
||||
GX_SET_CP_REG(1, gx->cpEnable);
|
||||
if (BreakPointCB != NULL) {
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(&exceptionContext);
|
||||
BreakPointCB();
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
static void GXCPInterruptHandler(s16 interrupt, OSContext *context)
|
||||
{
|
||||
gx->cpStatus = GX_GET_CP_REG(0);
|
||||
if (GET_REG_FIELD(gx->cpEnable, 1, 3) && GET_REG_FIELD(gx->cpStatus, 1, 1)) {
|
||||
GXUnderflowHandler(interrupt, context);
|
||||
}
|
||||
if (GET_REG_FIELD(gx->cpEnable, 1, 2) && GET_REG_FIELD(gx->cpStatus, 1, 0)) {
|
||||
GXOverflowHandler(interrupt, context);
|
||||
}
|
||||
if (GET_REG_FIELD(gx->cpEnable, 1, 5) && GET_REG_FIELD(gx->cpStatus, 1, 4)) {
|
||||
GXBreakPointHandler(interrupt, context);
|
||||
}
|
||||
}
|
||||
|
||||
void GXInitFifoBase(GXFifoObj *fifo, void *base, u32 size)
|
||||
{
|
||||
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
||||
|
||||
ASSERTMSGLINE(0x21E, realFifo != CPUFifo, "GXInitFifoBase: fifo is attached to CPU");
|
||||
ASSERTMSGLINE(0x220, realFifo != GPFifo, "GXInitFifoBase: fifo is attached to GP");
|
||||
ASSERTMSGLINE(0x222, ((u32)base & 0x1F) == 0, "GXInitFifoBase: base must be 32B aligned");
|
||||
ASSERTMSGLINE(0x224, base != NULL, "GXInitFifoBase: base pointer is NULL");
|
||||
ASSERTMSGLINE(0x226, (size & 0x1F) == 0, "GXInitFifoBase: size must be 32B aligned");
|
||||
ASSERTMSGLINE(0x228, size >= 0x10000, "GXInitFifoBase: fifo is not large enough");
|
||||
|
||||
realFifo->base = base;
|
||||
realFifo->top = (u8 *)base + size - 4;
|
||||
realFifo->size = size;
|
||||
realFifo->count = 0;
|
||||
GXInitFifoLimits(fifo, size - 0x4000, (size >> 1) & ~0x1F);
|
||||
GXInitFifoPtrs(fifo, base, base);
|
||||
}
|
||||
|
||||
void GXInitFifoPtrs(GXFifoObj *fifo, void *readPtr, void *writePtr)
|
||||
{
|
||||
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
||||
BOOL enabled;
|
||||
|
||||
ASSERTMSGLINE(0x250, realFifo != CPUFifo, "GXInitFifoPtrs: fifo is attached to CPU");
|
||||
ASSERTMSGLINE(0x252, realFifo != GPFifo, "GXInitFifoPtrs: fifo is attached to GP");
|
||||
ASSERTMSGLINE(0x254, ((u32)readPtr & 0x1F) == 0, "GXInitFifoPtrs: readPtr not 32B aligned");
|
||||
ASSERTMSGLINE(0x256, ((u32)writePtr & 0x1F) == 0, "GXInitFifoPtrs: writePtr not 32B aligned");
|
||||
ASSERTMSGLINE(0x259, realFifo->base <= readPtr && readPtr < realFifo->top, "GXInitFifoPtrs: readPtr not in fifo range");
|
||||
ASSERTMSGLINE(0x25C, realFifo->base <= writePtr && writePtr < realFifo->top, "GXInitFifoPtrs: writePtr not in fifo range");
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
realFifo->rdPtr = readPtr;
|
||||
realFifo->wrPtr = writePtr;
|
||||
realFifo->count = (u8 *)writePtr - (u8 *)readPtr;
|
||||
if (realFifo->count < 0) {
|
||||
realFifo->count += realFifo->size;
|
||||
}
|
||||
OSRestoreInterrupts(enabled);
|
||||
}
|
||||
|
||||
void GXInitFifoLimits(GXFifoObj *fifo, u32 hiWatermark, u32 loWatermark)
|
||||
{
|
||||
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
||||
|
||||
ASSERTMSGLINE(0x281, realFifo != GPFifo, "GXInitFifoLimits: fifo is attached to GP");
|
||||
ASSERTMSGLINE(0x283, (hiWatermark & 0x1F) == 0, "GXInitFifoLimits: hiWatermark not 32B aligned");
|
||||
ASSERTMSGLINE(0x285, (loWatermark & 0x1F) == 0, "GXInitFifoLimits: loWatermark not 32B aligned");
|
||||
ASSERTMSGLINE(0x287, hiWatermark < realFifo->top - realFifo->base, "GXInitFifoLimits: hiWatermark too large");
|
||||
ASSERTMSGLINE(0x289, loWatermark < hiWatermark, "GXInitFifoLimits: hiWatermark below lo watermark");
|
||||
|
||||
realFifo->hiWatermark = hiWatermark;
|
||||
realFifo->loWatermark = loWatermark;
|
||||
}
|
||||
|
||||
void GXSetCPUFifo(GXFifoObj *fifo)
|
||||
{
|
||||
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
||||
BOOL enabled = OSDisableInterrupts();
|
||||
|
||||
CPUFifo = realFifo;
|
||||
if (CPUFifo == GPFifo)
|
||||
{
|
||||
u32 reg = 0;
|
||||
|
||||
__piReg[3] = (u32)realFifo->base & 0x3FFFFFFF;
|
||||
__piReg[4] = (u32)realFifo->top & 0x3FFFFFFF;
|
||||
SET_REG_FIELD(0x294, reg, 21, 5, ((u32)realFifo->wrPtr & 0x3FFFFFFF) >> 5);
|
||||
SET_REG_FIELD(0x295, reg, 1, 26, 0);
|
||||
__piReg[5] = reg;
|
||||
CPGPLinked = GX_TRUE;
|
||||
__GXWriteFifoIntReset(1, 1);
|
||||
__GXWriteFifoIntEnable(1, 0);
|
||||
__GXFifoLink(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
if (CPGPLinked)
|
||||
{
|
||||
__GXFifoLink(0);
|
||||
CPGPLinked = GX_FALSE;
|
||||
}
|
||||
__GXWriteFifoIntEnable(0, 0);
|
||||
reg = 0;
|
||||
__piReg[3] = (u32)realFifo->base & 0x3FFFFFFF;
|
||||
__piReg[4] = (u32)realFifo->top & 0x3FFFFFFF;
|
||||
SET_REG_FIELD(0x2B7, reg, 21, 5, ((u32)realFifo->wrPtr & 0x3FFFFFFF) >> 5);
|
||||
SET_REG_FIELD(0x2B8, reg, 1, 26, 0);
|
||||
__piReg[5] = reg;
|
||||
}
|
||||
|
||||
__sync();
|
||||
|
||||
OSRestoreInterrupts(enabled);
|
||||
}
|
||||
|
||||
void GXSetGPFifo(GXFifoObj *fifo)
|
||||
{
|
||||
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
||||
BOOL enabled = OSDisableInterrupts();
|
||||
|
||||
__GXFifoReadDisable();
|
||||
__GXWriteFifoIntEnable(0, 0);
|
||||
GPFifo = realFifo;
|
||||
|
||||
GX_SET_CP_REG(16, (u32)realFifo->base & 0xFFFF);
|
||||
GX_SET_CP_REG(18, (u32)realFifo->top & 0xFFFF);
|
||||
GX_SET_CP_REG(24, realFifo->count & 0xFFFF);
|
||||
GX_SET_CP_REG(26, (u32)realFifo->wrPtr & 0xFFFF);
|
||||
GX_SET_CP_REG(28, (u32)realFifo->rdPtr & 0xFFFF);
|
||||
GX_SET_CP_REG(20, (u32)realFifo->hiWatermark & 0xFFFF);
|
||||
GX_SET_CP_REG(22, (u32)realFifo->loWatermark & 0xFFFF);
|
||||
GX_SET_CP_REG(17, ((u32)realFifo->base & 0x3FFFFFFF) >> 16);
|
||||
GX_SET_CP_REG(19, ((u32)realFifo->top & 0x3FFFFFFF) >> 16);
|
||||
GX_SET_CP_REG(25, realFifo->count >> 16);
|
||||
GX_SET_CP_REG(27, ((u32)realFifo->wrPtr & 0x3FFFFFFF) >> 16);
|
||||
GX_SET_CP_REG(29, ((u32)realFifo->rdPtr & 0x3FFFFFFF) >> 16);
|
||||
GX_SET_CP_REG(21, (u32)realFifo->hiWatermark >> 16);
|
||||
GX_SET_CP_REG(23, (u32)realFifo->loWatermark >> 16);
|
||||
|
||||
__sync();
|
||||
|
||||
if (CPUFifo == GPFifo) {
|
||||
CPGPLinked = GX_TRUE;
|
||||
__GXWriteFifoIntEnable(1, 0);
|
||||
__GXFifoLink(1);
|
||||
}
|
||||
else {
|
||||
CPGPLinked = GX_FALSE;
|
||||
__GXWriteFifoIntEnable(0, 0);
|
||||
__GXFifoLink(0);
|
||||
}
|
||||
__GXWriteFifoIntReset(1, 1);
|
||||
__GXFifoReadEnable();
|
||||
OSRestoreInterrupts(enabled);
|
||||
}
|
||||
|
||||
void GXSaveCPUFifo(GXFifoObj *fifo)
|
||||
{
|
||||
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
||||
ASSERTMSGLINE(0x343, realFifo == CPUFifo, "GXSaveCPUFifo: fifo is not attached to CPU");
|
||||
__GXSaveCPUFifoAux(realFifo);
|
||||
}
|
||||
|
||||
#define SOME_MACRO1(fifo) \
|
||||
do { \
|
||||
u32 temp = GX_GET_CP_REG(29) << 16; \
|
||||
temp |= GX_GET_CP_REG(28); \
|
||||
fifo->rdPtr = OSPhysicalToCached(temp); \
|
||||
} while (0)
|
||||
|
||||
#define SOME_MACRO2(fifo) \
|
||||
do { \
|
||||
u32 temp = GX_GET_CP_REG(25) << 16; \
|
||||
temp |= GX_GET_CP_REG(24); \
|
||||
fifo->count = temp; \
|
||||
} while (0)
|
||||
|
||||
void __GXSaveCPUFifoAux(struct __GXFifoObj *realFifo)
|
||||
{
|
||||
BOOL enabled = OSDisableInterrupts();
|
||||
|
||||
GXFlush();
|
||||
realFifo->base = OSPhysicalToCached(__piReg[3]);
|
||||
realFifo->top = OSPhysicalToCached(__piReg[4]);
|
||||
realFifo->wrPtr = OSPhysicalToCached(__piReg[5] & 0xFBFFFFFF);
|
||||
if (CPGPLinked) {
|
||||
SOME_MACRO1(realFifo);
|
||||
SOME_MACRO2(realFifo);
|
||||
} else {
|
||||
realFifo->count = (u8 *)realFifo->wrPtr - (u8 *)realFifo->rdPtr;
|
||||
if (realFifo->count < 0)
|
||||
realFifo->count += realFifo->size;
|
||||
}
|
||||
OSRestoreInterrupts(enabled);
|
||||
}
|
||||
|
||||
void GXSaveGPFifo(GXFifoObj *fifo)
|
||||
{
|
||||
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
||||
unsigned long cpStatus;
|
||||
unsigned char readIdle;
|
||||
unsigned long temp;
|
||||
|
||||
ASSERTMSGLINE(0x38C, realFifo == GPFifo, "GXSaveGPFifo: fifo is not attached to GP");
|
||||
cpStatus = GX_GET_CP_REG(0);
|
||||
readIdle = GET_REG_FIELD(cpStatus, 1, 2);
|
||||
ASSERTMSGLINE(0x393, readIdle, "GXSaveGPFifo: GP is not idle");
|
||||
|
||||
SOME_MACRO1(realFifo);
|
||||
SOME_MACRO2(realFifo);
|
||||
}
|
||||
|
||||
void GXGetGPStatus(GXBool *overhi, GXBool *underlow, GXBool *readIdle, GXBool *cmdIdle, GXBool *brkpt)
|
||||
{
|
||||
gx->cpStatus = GX_GET_CP_REG(0);
|
||||
*overhi = GET_REG_FIELD(gx->cpStatus, 1, 0);
|
||||
*underlow = (int)GET_REG_FIELD(gx->cpStatus, 1, 1);
|
||||
*readIdle = (int)GET_REG_FIELD(gx->cpStatus, 1, 2);
|
||||
*cmdIdle = (int)GET_REG_FIELD(gx->cpStatus, 1, 3);
|
||||
*brkpt = (int)GET_REG_FIELD(gx->cpStatus, 1, 4);
|
||||
}
|
||||
|
||||
void GXGetFifoStatus(GXFifoObj *fifo, GXBool *overhi, GXBool *underflow, u32 *fifoCount, GXBool *cpuWrite, GXBool *gpRead, GXBool *fifowrap)
|
||||
{
|
||||
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
||||
|
||||
*underflow = GX_FALSE;
|
||||
*overhi = GX_FALSE;
|
||||
*fifoCount = 0;
|
||||
*fifowrap = GX_FALSE;
|
||||
if (realFifo == GPFifo) {
|
||||
SOME_MACRO1(realFifo);
|
||||
SOME_MACRO2(realFifo);
|
||||
}
|
||||
if (realFifo == CPUFifo) {
|
||||
GXFlush();
|
||||
__GXSaveCPUFifoAux(realFifo);
|
||||
*fifowrap = (int)GET_REG_FIELD(GX_GET_PI_REG(5), 1, 26);
|
||||
}
|
||||
*overhi = (realFifo->count > realFifo->hiWatermark);
|
||||
*underflow = (realFifo->count < realFifo->loWatermark);
|
||||
*fifoCount = (realFifo->count);
|
||||
*cpuWrite = (CPUFifo == realFifo);
|
||||
*gpRead = (GPFifo == realFifo);
|
||||
}
|
||||
|
||||
void GXGetFifoPtrs(GXFifoObj *fifo, void **readPtr, void **writePtr)
|
||||
{
|
||||
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
||||
|
||||
if (realFifo == CPUFifo) {
|
||||
realFifo->wrPtr = OSPhysicalToCached(GX_GET_PI_REG(5) & 0xFBFFFFFF);
|
||||
}
|
||||
if (realFifo == GPFifo) {
|
||||
SOME_MACRO1(realFifo);
|
||||
SOME_MACRO2(realFifo);
|
||||
}
|
||||
else {
|
||||
realFifo->count = (u8 *)realFifo->wrPtr - (u8 *)realFifo->rdPtr;
|
||||
if (realFifo->count < 0) {
|
||||
realFifo->count += realFifo->size;
|
||||
}
|
||||
}
|
||||
*readPtr = realFifo->rdPtr;
|
||||
*writePtr = realFifo->wrPtr;
|
||||
}
|
||||
|
||||
void *GXGetFifoBase(const GXFifoObj *fifo)
|
||||
{
|
||||
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
||||
|
||||
return realFifo->base;
|
||||
}
|
||||
|
||||
u32 GXGetFifoSize(const GXFifoObj *fifo)
|
||||
{
|
||||
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
||||
|
||||
return realFifo->size;
|
||||
}
|
||||
|
||||
void GXGetFifoLimits(const GXFifoObj *fifo, u32 *hi, u32 *lo)
|
||||
{
|
||||
struct __GXFifoObj *realFifo = (struct __GXFifoObj *)fifo;
|
||||
|
||||
*hi = realFifo->hiWatermark;
|
||||
*lo = realFifo->loWatermark;
|
||||
}
|
||||
|
||||
GXBreakPtCallback GXSetBreakPtCallback(GXBreakPtCallback cb)
|
||||
{
|
||||
GXBreakPtCallback oldcb = BreakPointCB;
|
||||
BOOL enabled = OSDisableInterrupts();
|
||||
|
||||
BreakPointCB = cb;
|
||||
OSRestoreInterrupts(enabled);
|
||||
return oldcb;
|
||||
}
|
||||
|
||||
void *__GXCurrentBP;
|
||||
|
||||
void GXEnableBreakPt(void *break_pt)
|
||||
{
|
||||
BOOL enabled = OSDisableInterrupts();
|
||||
|
||||
__GXFifoReadDisable();
|
||||
GX_SET_CP_REG(30, (u32)break_pt);
|
||||
GX_SET_CP_REG(31, ((u32)break_pt >> 16) & 0x3FFF);
|
||||
SOME_SET_REG_MACRO(gx->cpEnable, 1, 1, 1);
|
||||
SOME_SET_REG_MACRO(gx->cpEnable, 1, 5, 1);
|
||||
GX_SET_CP_REG(1, gx->cpEnable);
|
||||
__GXCurrentBP = break_pt;
|
||||
__GXFifoReadEnable();
|
||||
OSRestoreInterrupts(enabled);
|
||||
}
|
||||
|
||||
void GXDisableBreakPt(void)
|
||||
{
|
||||
BOOL enabled = OSDisableInterrupts();
|
||||
|
||||
SOME_SET_REG_MACRO(gx->cpEnable, 1, 1, 0);
|
||||
SOME_SET_REG_MACRO(gx->cpEnable, 1, 5, 0);
|
||||
GX_SET_CP_REG(1, gx->cpEnable);
|
||||
__GXCurrentBP = NULL;
|
||||
OSRestoreInterrupts(enabled);
|
||||
}
|
||||
|
||||
void __GXFifoInit(void)
|
||||
{
|
||||
__OSSetInterruptHandler(0x11, GXCPInterruptHandler);
|
||||
__OSUnmaskInterrupts(0x4000);
|
||||
__GXCurrentThread = OSGetCurrentThread();
|
||||
GXOverflowSuspendInProgress = FALSE;
|
||||
CPUFifo = NULL;
|
||||
GPFifo = NULL;
|
||||
}
|
||||
|
||||
static void __GXFifoReadEnable(void)
|
||||
{
|
||||
SET_REG_FIELD(0, gx->cpEnable, 1, 0, 1);
|
||||
GX_SET_CP_REG(1, gx->cpEnable);
|
||||
}
|
||||
|
||||
static void __GXFifoReadDisable(void)
|
||||
{
|
||||
SET_REG_FIELD(0, gx->cpEnable, 1, 0, 0);
|
||||
GX_SET_CP_REG(1, gx->cpEnable);
|
||||
}
|
||||
|
||||
static void __GXFifoLink(u8 en)
|
||||
{
|
||||
SET_REG_FIELD(0x4DA, gx->cpEnable, 1, 4, (en != 0) ? 1 : 0);
|
||||
GX_SET_CP_REG(1, gx->cpEnable);
|
||||
}
|
||||
|
||||
static void __GXWriteFifoIntEnable(u8 hiWatermarkEn, u8 loWatermarkEn)
|
||||
{
|
||||
SET_REG_FIELD(0x4F0, gx->cpEnable, 1, 2, hiWatermarkEn);
|
||||
SET_REG_FIELD(0x4F1, gx->cpEnable, 1, 3, loWatermarkEn);
|
||||
GX_SET_CP_REG(1, gx->cpEnable);
|
||||
}
|
||||
|
||||
static void __GXWriteFifoIntReset(u8 hiWatermarkClr, u8 loWatermarkClr)
|
||||
{
|
||||
SET_REG_FIELD(0x508, gx->cpClr, 1, 0, hiWatermarkClr);
|
||||
SET_REG_FIELD(0x509, gx->cpClr, 1, 1, loWatermarkClr);
|
||||
GX_SET_CP_REG(2, gx->cpClr);
|
||||
}
|
||||
|
||||
void __GXInsaneWatermark(void)
|
||||
{
|
||||
struct __GXFifoObj *realFifo = GPFifo;
|
||||
|
||||
realFifo->hiWatermark = realFifo->loWatermark + 512;
|
||||
GX_SET_CP_REG(20, (realFifo->hiWatermark & 0x3FFFFFFF) & 0xFFFF);
|
||||
GX_SET_CP_REG(21, (realFifo->hiWatermark & 0x3FFFFFFF) >> 16);
|
||||
}
|
||||
|
||||
void __GXCleanGPFifo(void)
|
||||
{
|
||||
GXFifoObj dummyFifo;
|
||||
GXFifoObj *gpFifo = GXGetGPFifo();
|
||||
GXFifoObj *cpuFifo = GXGetCPUFifo();
|
||||
void *base = GXGetFifoBase(gpFifo);
|
||||
|
||||
dummyFifo = *gpFifo;
|
||||
GXInitFifoPtrs(&dummyFifo, base, base);
|
||||
GXSetGPFifo(&dummyFifo);
|
||||
if (cpuFifo == gpFifo) {
|
||||
GXSetCPUFifo(&dummyFifo);
|
||||
}
|
||||
GXInitFifoPtrs(gpFifo, base, base);
|
||||
GXSetGPFifo(gpFifo);
|
||||
if (cpuFifo == gpFifo) {
|
||||
GXSetCPUFifo(cpuFifo);
|
||||
}
|
||||
}
|
||||
|
||||
OSThread *GXSetCurrentGXThread(void)
|
||||
{
|
||||
BOOL enabled;
|
||||
struct OSThread *prev;
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
prev = __GXCurrentThread;
|
||||
ASSERTMSGLINE(0x561, !GXOverflowSuspendInProgress, "GXSetCurrentGXThread: Two threads cannot generate GX commands at the same time!");
|
||||
__GXCurrentThread = OSGetCurrentThread();
|
||||
OSRestoreInterrupts(enabled);
|
||||
return prev;
|
||||
}
|
||||
|
||||
OSThread *GXGetCurrentGXThread(void)
|
||||
{
|
||||
return __GXCurrentThread;
|
||||
}
|
||||
|
||||
GXFifoObj *GXGetCPUFifo(void)
|
||||
{
|
||||
return (GXFifoObj *)CPUFifo;
|
||||
}
|
||||
|
||||
GXFifoObj *GXGetGPFifo(void)
|
||||
{
|
||||
return (GXFifoObj *)GPFifo;
|
||||
}
|
||||
|
||||
u32 GXGetOverflowCount(void)
|
||||
{
|
||||
return __GXOverflowCount;
|
||||
}
|
||||
|
||||
u32 GXResetOverflowCount(void)
|
||||
{
|
||||
u32 oldcount;
|
||||
|
||||
oldcount = __GXOverflowCount;
|
||||
__GXOverflowCount = 0;
|
||||
return oldcount;
|
||||
}
|
||||
|
||||
// NONMATCHING
|
||||
volatile void *GXRedirectWriteGatherPipe(void *ptr)
|
||||
{
|
||||
u32 reg = 0;
|
||||
BOOL enabled = OSDisableInterrupts();
|
||||
|
||||
CHECK_GXBEGIN(0x5D5, "GXRedirectWriteGatherPipe");
|
||||
ASSERTLINE(0x5D6, OFFSET(ptr, 32) == 0);
|
||||
ASSERTLINE(0x5D8, !IsWGPipeRedirected);
|
||||
|
||||
GXFlush();
|
||||
while (PPCMfwpar() & 1) { }
|
||||
PPCMtwpar((u32)OSUncachedToPhysical((void *)GXFIFO_ADDR));
|
||||
if (CPGPLinked) {
|
||||
__GXFifoLink(0);
|
||||
__GXWriteFifoIntEnable(0, 0);
|
||||
}
|
||||
CPUFifo->wrPtr = OSPhysicalToCached(GX_GET_PI_REG(5) & 0xFBFFFFFF);
|
||||
GX_SET_PI_REG(3, 0);
|
||||
GX_SET_PI_REG(4, 0x04000000);
|
||||
SET_REG_FIELD(0x5F7, reg, 21, 5, ((u32)ptr & 0x3FFFFFFF) >> 5);
|
||||
reg &= 0xFBFFFFFF;
|
||||
GX_SET_PI_REG(5, reg);
|
||||
PPCSync();
|
||||
OSRestoreInterrupts(enabled);
|
||||
return (volatile void *)GXFIFO_ADDR;
|
||||
}
|
||||
|
||||
// NONMATCHING
|
||||
void GXRestoreWriteGatherPipe(void)
|
||||
{
|
||||
u32 reg = 0; // r31
|
||||
u32 i; // r29
|
||||
BOOL enabled; // r28
|
||||
|
||||
ASSERTLINE(0x610, IsWGPipeRedirected);
|
||||
enabled = OSDisableInterrupts();
|
||||
for (i = 0; i < 31; i++) {
|
||||
GXWGFifo.u8 = 0;
|
||||
}
|
||||
PPCSync();
|
||||
while (PPCMfwpar() & 1) { }
|
||||
PPCMtwpar((u32)OSUncachedToPhysical((void *)GXFIFO_ADDR));
|
||||
GX_SET_PI_REG(3, (u32)CPUFifo->base & 0x3FFFFFFF);
|
||||
GX_SET_PI_REG(4, (u32)CPUFifo->top & 0x3FFFFFFF);
|
||||
SET_REG_FIELD(0x62A, reg, 21, 5, ((u32)CPUFifo->wrPtr & 0x3FFFFFFF) >> 5);
|
||||
reg &= 0xFBFFFFFF;
|
||||
GX_SET_PI_REG(5, reg);
|
||||
if (CPGPLinked) {
|
||||
__GXWriteFifoIntReset(1, 1);
|
||||
__GXWriteFifoIntEnable(1, 0);
|
||||
__GXFifoLink(1);
|
||||
}
|
||||
PPCSync();
|
||||
OSRestoreInterrupts(enabled);
|
||||
}
|
||||
604
src/dolphin/gx/GXFrameBuf.c
Normal file
604
src/dolphin/gx/GXFrameBuf.c
Normal file
|
|
@ -0,0 +1,604 @@
|
|||
#include <dolphin/gx.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <dolphin/gx/GXPriv.h>
|
||||
|
||||
GXRenderModeObj GXNtsc240Ds = { 1, 640, 240, 240, 40, 0, 640, 480, 0, 0, 0,
|
||||
{ 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 GXNtsc240DsAa = { 1, 640, 240, 240, 40, 0, 640, 480, 0, 0, 1,
|
||||
{ 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 0, 0, 21, 22, 21, 0, 0 } };
|
||||
|
||||
GXRenderModeObj GXNtsc240Int = { 0, 640, 240, 240, 40, 0, 640, 480, 0, 1, 0,
|
||||
{ 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 GXNtsc240IntAa = { 0, 640, 240, 240, 40, 0, 640, 480, 0, 1, 1,
|
||||
{ 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 0, 0, 21, 22, 21, 0, 0 } };
|
||||
|
||||
GXRenderModeObj GXNtsc480IntDf = { 0, 640, 480, 480, 40, 0, 640, 480, 1, 0, 0,
|
||||
{ 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 = { 0, 640, 480, 480, 40, 0, 640, 480, 1, 0, 0,
|
||||
{ 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 GXNtsc480IntAa = { 0, 640, 242, 480, 40, 0, 640, 480, 1, 0, 1,
|
||||
{ 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 4, 8, 12, 16, 12, 8, 4 } };
|
||||
|
||||
GXRenderModeObj GXNtsc480Prog = { 2, 640, 480, 480, 40, 0, 640, 480, 0, 0, 0,
|
||||
{ 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 GXNtsc480ProgSoft = { 2, 640, 480, 480, 40, 0, 640, 480, 0, 0, 0,
|
||||
{ 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 GXNtsc480ProgAa = { 2, 640, 242, 480, 40, 0, 640, 480, 0, 0, 1,
|
||||
{ 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 4, 8, 12, 16, 12, 8, 4 } };
|
||||
|
||||
GXRenderModeObj GXMpal240Ds = { 9, 640, 240, 240, 40, 0, 640, 480, 0, 0, 0,
|
||||
{ 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 GXMpal240DsAa = { 9, 640, 240, 240, 40, 0, 640, 480, 0, 0, 1,
|
||||
{ 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 0, 0, 21, 22, 21, 0, 0 } };
|
||||
GXRenderModeObj GXMpal240Int = { 8, 640, 240, 240, 40, 0, 640, 480, 0, 1, 0,
|
||||
{ 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 GXMpal240IntAa = { 8, 640, 240, 240, 40, 0, 640, 480, 0, 1, 1,
|
||||
{ 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 0, 0, 21, 22, 21, 0, 0 } };
|
||||
GXRenderModeObj GXMpal480IntDf = { 8, 640, 480, 480, 40, 0, 640, 480, 1, 0, 0,
|
||||
{ 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 GXMpal480Int = { 8, 640, 480, 480, 40, 0, 640, 480, 1, 0, 0,
|
||||
{ 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 GXMpal480IntAa = { 8, 640, 242, 480, 40, 0, 640, 480, 1, 0, 1,
|
||||
{ 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 4, 8, 12, 16, 12, 8, 4 } };
|
||||
GXRenderModeObj GXPal264Ds = { 5, 640, 264, 264, 40, 11, 640, 528, 0, 0, 0,
|
||||
{ 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 GXPal264DsAa = { 5, 640, 264, 264, 40, 11, 640, 528, 0, 0, 1,
|
||||
{ 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 0, 0, 21, 22, 21, 0, 0 } };
|
||||
GXRenderModeObj GXPal264Int = { 4, 640, 264, 264, 40, 23, 640, 528, 0, 1, 0,
|
||||
{ 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 GXPal264IntAa = { 4, 640, 264, 264, 40, 23, 640, 528, 0, 1, 1,
|
||||
{ 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 0, 0, 21, 22, 21, 0, 0 } };
|
||||
GXRenderModeObj GXPal528IntDf = { 4, 640, 528, 528, 40, 23, 640, 528, 1, 0, 0,
|
||||
{ 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 GXPal528Int = { 4, 640, 528, 528, 40, 23, 640, 528, 1, 0, 0,
|
||||
{ 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 GXPal524IntAa = { 4, 640, 264, 524, 40, 23, 640, 524, 1, 0, 1,
|
||||
{ 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 4, 8, 12, 16, 12, 8, 4 } };
|
||||
GXRenderModeObj GXEurgb60Hz240Ds = { 21, 640, 240, 240, 40, 0, 640, 480, 0, 0, 0,
|
||||
{ 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 GXEurgb60Hz240DsAa = { 21, 640, 240, 240, 40, 0, 640, 480, 0, 0, 1,
|
||||
{ 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 0, 0, 21, 22, 21, 0, 0 } };
|
||||
GXRenderModeObj GXEurgb60Hz240Int = { 20, 640, 240, 240, 40, 0, 640, 480, 0, 1, 0,
|
||||
{ 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 GXEurgb60Hz240IntAa = { 20, 640, 240, 240, 40, 0, 640, 480, 0, 1, 1,
|
||||
{ 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 0, 0, 21, 22, 21, 0, 0 } };
|
||||
GXRenderModeObj GXEurgb60Hz480IntDf = { 20, 640, 480, 480, 40, 0, 640, 480, 1, 0, 0,
|
||||
{ 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 GXEurgb60Hz480Int = { 20, 640, 480, 480, 40, 0, 640, 480, 1, 0, 0,
|
||||
{ 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 GXEurgb60Hz480IntAa = { 20, 640, 242, 480, 40, 0, 640, 480, 1, 0, 1,
|
||||
{ 3, 2, 9, 6, 3, 10, 3, 2, 9, 6, 3, 10, 9, 2, 3, 6, 9, 10, 9, 2, 3, 6, 9, 10 }, { 4, 8, 12, 16, 12, 8, 4 } };
|
||||
GXRenderModeObj GXRmHW = { 1, 320, 240, 240, 40, 0, 640, 480, 0, 0, 0, { 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 } };
|
||||
|
||||
void GXAdjustForOverscan(GXRenderModeObj *rmin, GXRenderModeObj *rmout, u16 hor, u16 ver)
|
||||
{
|
||||
u16 hor2 = hor * 2;
|
||||
u16 ver2 = ver * 2;
|
||||
u32 verf;
|
||||
u32 mode;
|
||||
|
||||
if (rmin != rmout) {
|
||||
*rmout = *rmin;
|
||||
}
|
||||
|
||||
mode = rmin->viTVmode & 3;
|
||||
rmout->fbWidth = rmin->fbWidth - hor2;
|
||||
verf = (ver2 * rmin->efbHeight) / (u32)rmin->xfbHeight;
|
||||
rmout->efbHeight = rmin->efbHeight - verf;
|
||||
if (rmin->xFBmode == VI_XFBMODE_SF && ((rmin->viTVmode & 2) != 2)) {
|
||||
rmout->xfbHeight = rmin->xfbHeight - ver;
|
||||
}
|
||||
else {
|
||||
rmout->xfbHeight = rmin->xfbHeight - ver2;
|
||||
}
|
||||
|
||||
rmout->viWidth = rmin->viWidth - hor2;
|
||||
rmout->viHeight = rmin->viHeight - ver2;
|
||||
rmout->viXOrigin = rmin->viXOrigin + hor;
|
||||
rmout->viYOrigin = rmin->viYOrigin + ver;
|
||||
}
|
||||
|
||||
void GXSetDispCopySrc(u16 left, u16 top, u16 wd, u16 ht)
|
||||
{
|
||||
CHECK_GXBEGIN(0x4D3, "GXSetDispCopySrc");
|
||||
|
||||
gx->cpDispSrc = 0;
|
||||
SET_REG_FIELD(0x4D6, gx->cpDispSrc, 10, 0, left);
|
||||
SET_REG_FIELD(0x4D7, gx->cpDispSrc, 10, 10, top);
|
||||
SET_REG_FIELD(0x4D7, gx->cpDispSrc, 8, 24, 0x49);
|
||||
|
||||
gx->cpDispSize = 0;
|
||||
SET_REG_FIELD(0x4DB, gx->cpDispSize, 10, 0, wd - 1);
|
||||
SET_REG_FIELD(0x4DC, gx->cpDispSize, 10, 10, ht - 1);
|
||||
SET_REG_FIELD(0x4DC, gx->cpDispSize, 8, 24, 0x4A);
|
||||
}
|
||||
|
||||
void GXSetTexCopySrc(u16 left, u16 top, u16 wd, u16 ht)
|
||||
{
|
||||
CHECK_GXBEGIN(0x4EF, "GXSetTexCopySrc");
|
||||
|
||||
gx->cpTexSrc = 0;
|
||||
SET_REG_FIELD(0x4F2, gx->cpTexSrc, 10, 0, left);
|
||||
SET_REG_FIELD(0x4F3, gx->cpTexSrc, 10, 10, top);
|
||||
SET_REG_FIELD(0x4F3, gx->cpTexSrc, 8, 24, 0x49);
|
||||
|
||||
gx->cpTexSize = 0;
|
||||
SET_REG_FIELD(0x4F7, gx->cpTexSize, 10, 0, wd - 1);
|
||||
SET_REG_FIELD(0x4F8, gx->cpTexSize, 10, 10, ht - 1);
|
||||
SET_REG_FIELD(0x4F8, gx->cpTexSize, 8, 24, 0x4A);
|
||||
}
|
||||
|
||||
void GXSetDispCopyDst(u16 wd, u16 ht)
|
||||
{
|
||||
u16 stride;
|
||||
|
||||
ASSERTMSGLINE(0x50D, (wd & 0xF) == 0, "GXSetDispCopyDst: Width must be a multiple of 16");
|
||||
CHECK_GXBEGIN(0x50E, "GXSetDispCopyDst");
|
||||
|
||||
stride = (int)wd * 2;
|
||||
gx->cpDispStride = 0;
|
||||
SET_REG_FIELD(0x514, gx->cpDispStride, 10, 0, (stride >> 5));
|
||||
SET_REG_FIELD(0x514, gx->cpDispStride, 8, 24, 0x4D);
|
||||
}
|
||||
|
||||
void GXSetTexCopyDst(u16 wd, u16 ht, GXTexFmt fmt, GXBool mipmap)
|
||||
{
|
||||
u32 rowTiles;
|
||||
u32 colTiles;
|
||||
u32 cmpTiles;
|
||||
u32 peTexFmt;
|
||||
u32 peTexFmtH;
|
||||
|
||||
CHECK_GXBEGIN(0x52F, "GXSetTexCopyDst");
|
||||
|
||||
gx->cpTexZ = 0;
|
||||
peTexFmt = fmt & 0xF;
|
||||
ASSERTMSGLINEV(0x54E, peTexFmt < 13, "%s: invalid texture format", "GXSetTexCopyDst");
|
||||
|
||||
if (fmt == GX_TF_Z16) {
|
||||
peTexFmt = 0xB;
|
||||
}
|
||||
switch (fmt) {
|
||||
case GX_TF_I4:
|
||||
case GX_TF_I8:
|
||||
case GX_TF_IA4:
|
||||
case GX_TF_IA8:
|
||||
case GX_CTF_YUVA8:
|
||||
SET_REG_FIELD(0, gx->cpTex, 2, 15, 3);
|
||||
break;
|
||||
default:
|
||||
SET_REG_FIELD(0, gx->cpTex, 2, 15, 2);
|
||||
break;
|
||||
}
|
||||
|
||||
gx->cpTexZ = (fmt & _GX_TF_ZTF) == _GX_TF_ZTF;
|
||||
peTexFmtH = (peTexFmt >> 3) & 1;
|
||||
!peTexFmt;
|
||||
SET_REG_FIELD(0x565, gx->cpTex, 1, 3, peTexFmtH);
|
||||
peTexFmt = peTexFmt & 7;
|
||||
__GetImageTileCount(fmt, wd, ht, &rowTiles, &colTiles, &cmpTiles);
|
||||
|
||||
gx->cpTexStride = 0;
|
||||
SET_REG_FIELD(0x56E, gx->cpTexStride, 10, 0, rowTiles * cmpTiles);
|
||||
SET_REG_FIELD(0x570, gx->cpTexStride, 8, 24, 0x4D);
|
||||
SET_REG_FIELD(0x570, gx->cpTex, 1, 9, mipmap);
|
||||
SET_REG_FIELD(0x571, gx->cpTex, 3, 4, peTexFmt);
|
||||
}
|
||||
|
||||
void GXSetDispCopyFrame2Field(GXCopyMode mode)
|
||||
{
|
||||
CHECK_GXBEGIN(0x582, "GXSetDispCopyFrame2Field");
|
||||
SET_REG_FIELD(0x583, gx->cpDisp, 2, 12, mode);
|
||||
SET_REG_FIELD(0x583, gx->cpTex, 2, 12, 0);
|
||||
}
|
||||
|
||||
void GXSetCopyClamp(GXFBClamp clamp)
|
||||
{
|
||||
u8 clmpB;
|
||||
u8 clmpT;
|
||||
|
||||
CHECK_GXBEGIN(0x597, "GXSetCopyClamp");
|
||||
|
||||
clmpT = (clamp & 1) == 1;
|
||||
clmpB = (clamp & 2) == 2;
|
||||
|
||||
SET_REG_FIELD(0x59B, gx->cpDisp, 1, 0, clmpT);
|
||||
SET_REG_FIELD(0x59C, gx->cpDisp, 1, 1, clmpB);
|
||||
|
||||
SET_REG_FIELD(0x59E, gx->cpTex, 1, 0, clmpT);
|
||||
SET_REG_FIELD(0x59F, gx->cpTex, 1, 1, clmpB);
|
||||
}
|
||||
|
||||
static u32 __GXGetNumXfbLines(u32 efbHt, u32 iScale)
|
||||
{
|
||||
u32 count;
|
||||
u32 realHt;
|
||||
u32 iScaleD;
|
||||
|
||||
count = (efbHt - 1) * 0x100;
|
||||
realHt = (count / iScale) + 1;
|
||||
|
||||
iScaleD = iScale;
|
||||
|
||||
if (iScaleD > 0x80 && iScaleD < 0x100) {
|
||||
while (iScaleD % 2 == 0) {
|
||||
iScaleD /= 2;
|
||||
}
|
||||
|
||||
if (efbHt % iScaleD == 0) {
|
||||
realHt++;
|
||||
}
|
||||
}
|
||||
|
||||
if (realHt > 0x400) {
|
||||
realHt = 0x400;
|
||||
}
|
||||
|
||||
return realHt;
|
||||
}
|
||||
|
||||
u16 GXGetNumXfbLines(u16 efbHeight, f32 yScale)
|
||||
{
|
||||
u32 iScale;
|
||||
ASSERTMSGLINE(0x5CE, yScale >= 1.0f, "GXGetNumXfbLines: Vertical scale must be >= 1.0");
|
||||
|
||||
iScale = (u32)(256.0f / yScale) & 0x1FF;
|
||||
return __GXGetNumXfbLines(efbHeight, iScale);
|
||||
}
|
||||
|
||||
f32 GXGetYScaleFactor(u16 efbHeight, u16 xfbHeight)
|
||||
{
|
||||
f32 fScale;
|
||||
f32 yScale;
|
||||
u32 iScale;
|
||||
u32 tgtHt;
|
||||
u32 realHt;
|
||||
|
||||
ASSERTMSGLINE(0x5E6, xfbHeight <= 1024, "GXGetYScaleFactor: Display copy only supports up to 1024 lines.\n");
|
||||
ASSERTMSGLINE(0x5E8, efbHeight <= xfbHeight, "GXGetYScaleFactor: EFB height should not be greater than XFB height.\n");
|
||||
|
||||
tgtHt = xfbHeight;
|
||||
yScale = (f32)xfbHeight / (f32)efbHeight;
|
||||
iScale = (u32)(256.0f / yScale) & 0x1FF;
|
||||
realHt = __GXGetNumXfbLines(efbHeight, iScale);
|
||||
|
||||
while (realHt > xfbHeight) {
|
||||
tgtHt--;
|
||||
yScale = (f32)tgtHt / (f32)efbHeight;
|
||||
iScale = (u32)(256.0f / yScale) & 0x1FF;
|
||||
realHt = __GXGetNumXfbLines(efbHeight, iScale);
|
||||
}
|
||||
|
||||
fScale = yScale;
|
||||
while (realHt < xfbHeight) {
|
||||
fScale = yScale;
|
||||
tgtHt++;
|
||||
yScale = (f32)tgtHt / (f32)efbHeight;
|
||||
iScale = (u32)(256.0f / yScale) & 0x1FF;
|
||||
realHt = __GXGetNumXfbLines(efbHeight, iScale);
|
||||
}
|
||||
|
||||
return fScale;
|
||||
}
|
||||
|
||||
u32 GXSetDispCopyYScale(f32 vscale)
|
||||
{
|
||||
u8 enable;
|
||||
u32 iScale;
|
||||
u32 ht;
|
||||
u32 reg;
|
||||
|
||||
CHECK_GXBEGIN(0x615, "GXSetDispCopyYScale");
|
||||
|
||||
ASSERTMSGLINE(0x617, vscale >= 1.0f, "GXSetDispCopyYScale: Vertical scale must be >= 1.0");
|
||||
|
||||
iScale = (u32)(256.0f / vscale) & 0x1FF;
|
||||
enable = (iScale != 256);
|
||||
|
||||
reg = 0;
|
||||
SET_REG_FIELD(0x61E, reg, 9, 0, iScale);
|
||||
SET_REG_FIELD(0x61E, reg, 8, 24, 0x4E);
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
gx->bpSentNot = 0;
|
||||
SET_REG_FIELD(0x623, gx->cpDisp, 1, 10, enable);
|
||||
ht = GET_REG_FIELD(gx->cpDispSize, 10, 10) + 1;
|
||||
return __GXGetNumXfbLines(ht, iScale);
|
||||
}
|
||||
|
||||
void GXSetCopyClear(GXColor clear_clr, u32 clear_z)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
CHECK_GXBEGIN(0x63C, "GXSetCopyClear");
|
||||
ASSERTMSGLINE(0x63E, clear_z <= 0xFFFFFF, "GXSetCopyClear: Z clear value is out of range");
|
||||
|
||||
reg = 0;
|
||||
SET_REG_FIELD(0x641, reg, 8, 0, clear_clr.r);
|
||||
SET_REG_FIELD(0x642, reg, 8, 8, clear_clr.a);
|
||||
SET_REG_FIELD(0x642, reg, 8, 24, 0x4F);
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
|
||||
reg = 0;
|
||||
SET_REG_FIELD(0x647, reg, 8, 0, clear_clr.b);
|
||||
SET_REG_FIELD(0x648, reg, 8, 8, clear_clr.g);
|
||||
SET_REG_FIELD(0x648, reg, 8, 24, 0x50);
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
|
||||
reg = 0;
|
||||
SET_REG_FIELD(0x64D, reg, 24, 0, clear_z);
|
||||
SET_REG_FIELD(0x64D, reg, 8, 24, 0x51);
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetCopyFilter(GXBool aa, u8 sample_pattern[12][2], GXBool vf, u8 vfilter[7])
|
||||
{
|
||||
u32 msLoc[4];
|
||||
u32 coeff0;
|
||||
u32 coeff1;
|
||||
|
||||
CHECK_GXBEGIN(0x669, "GXSetCopyFilter");
|
||||
|
||||
if (aa != 0) {
|
||||
msLoc[0] = 0;
|
||||
SET_REG_FIELD(0x66D, msLoc[0], 4, 0, sample_pattern[0][0]);
|
||||
SET_REG_FIELD(0x66E, msLoc[0], 4, 4, sample_pattern[0][1]);
|
||||
SET_REG_FIELD(0x66F, msLoc[0], 4, 8, sample_pattern[1][0]);
|
||||
SET_REG_FIELD(0x670, msLoc[0], 4, 12, sample_pattern[1][1]);
|
||||
SET_REG_FIELD(0x671, msLoc[0], 4, 16, sample_pattern[2][0]);
|
||||
SET_REG_FIELD(0x672, msLoc[0], 4, 20, sample_pattern[2][1]);
|
||||
SET_REG_FIELD(0x673, msLoc[0], 8, 24, 1);
|
||||
|
||||
msLoc[1] = 0;
|
||||
SET_REG_FIELD(0x676, msLoc[1], 4, 0, sample_pattern[3][0]);
|
||||
SET_REG_FIELD(0x677, msLoc[1], 4, 4, sample_pattern[3][1]);
|
||||
SET_REG_FIELD(0x678, msLoc[1], 4, 8, sample_pattern[4][0]);
|
||||
SET_REG_FIELD(0x679, msLoc[1], 4, 12, sample_pattern[4][1]);
|
||||
SET_REG_FIELD(0x67A, msLoc[1], 4, 16, sample_pattern[5][0]);
|
||||
SET_REG_FIELD(0x67B, msLoc[1], 4, 20, sample_pattern[5][1]);
|
||||
SET_REG_FIELD(0x67C, msLoc[1], 8, 24, 2);
|
||||
|
||||
msLoc[2] = 0;
|
||||
SET_REG_FIELD(0x67F, msLoc[2], 4, 0, sample_pattern[6][0]);
|
||||
SET_REG_FIELD(0x680, msLoc[2], 4, 4, sample_pattern[6][1]);
|
||||
SET_REG_FIELD(0x681, msLoc[2], 4, 8, sample_pattern[7][0]);
|
||||
SET_REG_FIELD(0x682, msLoc[2], 4, 12, sample_pattern[7][1]);
|
||||
SET_REG_FIELD(0x683, msLoc[2], 4, 16, sample_pattern[8][0]);
|
||||
SET_REG_FIELD(0x684, msLoc[2], 4, 20, sample_pattern[8][1]);
|
||||
SET_REG_FIELD(0x685, msLoc[2], 8, 24, 3);
|
||||
|
||||
msLoc[3] = 0;
|
||||
SET_REG_FIELD(0x688, msLoc[3], 4, 0, sample_pattern[9][0]);
|
||||
SET_REG_FIELD(0x689, msLoc[3], 4, 4, sample_pattern[9][1]);
|
||||
SET_REG_FIELD(0x68A, msLoc[3], 4, 8, sample_pattern[10][0]);
|
||||
SET_REG_FIELD(0x68B, msLoc[3], 4, 12, sample_pattern[10][1]);
|
||||
SET_REG_FIELD(0x68C, msLoc[3], 4, 16, sample_pattern[11][0]);
|
||||
SET_REG_FIELD(0x68D, msLoc[3], 4, 20, sample_pattern[11][1]);
|
||||
SET_REG_FIELD(0x68E, msLoc[3], 8, 24, 4);
|
||||
}
|
||||
else {
|
||||
msLoc[0] = 0x01666666;
|
||||
msLoc[1] = 0x02666666;
|
||||
msLoc[2] = 0x03666666;
|
||||
msLoc[3] = 0x04666666;
|
||||
}
|
||||
GX_WRITE_RAS_REG(msLoc[0]);
|
||||
GX_WRITE_RAS_REG(msLoc[1]);
|
||||
GX_WRITE_RAS_REG(msLoc[2]);
|
||||
GX_WRITE_RAS_REG(msLoc[3]);
|
||||
|
||||
coeff0 = 0;
|
||||
SET_REG_FIELD(0, coeff0, 8, 24, 0x53);
|
||||
coeff1 = 0;
|
||||
SET_REG_FIELD(0, coeff1, 8, 24, 0x54);
|
||||
if (vf != 0) {
|
||||
SET_REG_FIELD(0x6A6, coeff0, 6, 0, vfilter[0]);
|
||||
SET_REG_FIELD(0x6A7, coeff0, 6, 6, vfilter[1]);
|
||||
SET_REG_FIELD(0x6A8, coeff0, 6, 12, vfilter[2]);
|
||||
SET_REG_FIELD(0x6A9, coeff0, 6, 18, vfilter[3]);
|
||||
SET_REG_FIELD(0x6AA, coeff1, 6, 0, vfilter[4]);
|
||||
SET_REG_FIELD(0x6AB, coeff1, 6, 6, vfilter[5]);
|
||||
SET_REG_FIELD(0x6AC, coeff1, 6, 12, vfilter[6]);
|
||||
}
|
||||
else {
|
||||
SET_REG_FIELD(0, coeff0, 6, 0, 0);
|
||||
SET_REG_FIELD(0, coeff0, 6, 6, 0);
|
||||
SET_REG_FIELD(0, coeff0, 6, 12, 21);
|
||||
SET_REG_FIELD(0, coeff0, 6, 18, 22);
|
||||
SET_REG_FIELD(0, coeff1, 6, 0, 21);
|
||||
SET_REG_FIELD(0, coeff1, 6, 6, 0);
|
||||
SET_REG_FIELD(0, coeff1, 6, 12, 0);
|
||||
}
|
||||
GX_WRITE_RAS_REG(coeff0);
|
||||
GX_WRITE_RAS_REG(coeff1);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetDispCopyGamma(GXGamma gamma)
|
||||
{
|
||||
CHECK_GXBEGIN(0x6CD, "GXSetDispCopyGamma");
|
||||
SET_REG_FIELD(0x6CE, gx->cpDisp, 2, 7, gamma);
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
static void __GXVerifCopy(void *dest, u8 clear)
|
||||
{
|
||||
u8 clmpT;
|
||||
u8 clmpB;
|
||||
u32 x0;
|
||||
u32 y0;
|
||||
u32 dx;
|
||||
u32 dy;
|
||||
|
||||
CHECK_GXBEGIN(0x6E2, "GXCopyDisp");
|
||||
|
||||
clmpT = GET_REG_FIELD(gx->cpDisp, 1, 0);
|
||||
clmpB = (u32)GET_REG_FIELD(gx->cpDisp, 1, 1);
|
||||
x0 = GET_REG_FIELD(gx->cpDispSrc, 10, 0);
|
||||
dx = GET_REG_FIELD(gx->cpDispSize, 10, 0) + 1;
|
||||
y0 = GET_REG_FIELD(gx->cpDispSrc, 10, 10);
|
||||
dy = GET_REG_FIELD(gx->cpDispSize, 10, 10) + 1;
|
||||
|
||||
ASSERTMSGLINE(0x6EC, clmpT || y0 != 0, "GXCopy: Have to set GX_CLAMP_TOP if source top == 0");
|
||||
ASSERTMSGLINE(0x6EE, clmpB || y0 + dy <= 528, "GXCopy: Have to set GX_CLAMP_BOTTOM if source bottom > 528");
|
||||
ASSERTMSGLINE(0x6F3, (gx->peCtrl & 7) != 3 || clear == 0, "GXCopy: Can not do clear while pixel type is Z");
|
||||
if ((u32)(gx->peCtrl & 7) == 5) {
|
||||
ASSERTMSGLINE(0x6F9, clear == 0, "GXCopy: Can not clear YUV framebuffer");
|
||||
ASSERTMSGLINE(0x6FB, (x0 & 3) == 0, "GXCopy: Source x is not multiple of 4 for YUV copy");
|
||||
ASSERTMSGLINE(0x6FD, (y0 & 3) == 0, "GXCopy: Source y is not multiple of 4 for YUV copy");
|
||||
ASSERTMSGLINE(0x6FF, (dx & 3) == 0, "GXCopy: Source width is not multiple of 4 for YUV copy");
|
||||
ASSERTMSGLINE(0x701, (dy & 3) == 0, "GXCopy: Source height is not multiple of 4 for YUV copy");
|
||||
}
|
||||
else {
|
||||
ASSERTMSGLINE(0x705, (x0 & 1) == 0, "GXCopy: Source x is not multiple of 2 for RGB copy");
|
||||
ASSERTMSGLINE(0x707, (y0 & 1) == 0, "GXCopy: Source y is not multiple of 2 for RGB copy");
|
||||
ASSERTMSGLINE(0x709, (dx & 1) == 0, "GXCopy: Source width is not multiple of 2 for RGB copy");
|
||||
ASSERTMSGLINE(0x70B, (dy & 1) == 0, "GXCopy: Source height is not multiple of 2 for RGB copy");
|
||||
}
|
||||
ASSERTMSGLINE(0x70F, ((u32)dest & 0x1F) == 0, "GXCopy: Display destination address not 32B aligned");
|
||||
}
|
||||
#endif
|
||||
|
||||
void GXCopyDisp(void *dest, GXBool clear)
|
||||
{
|
||||
u32 reg;
|
||||
u32 tempPeCtrl;
|
||||
u32 phyAddr;
|
||||
u8 changePeCtrl;
|
||||
|
||||
CHECK_GXBEGIN(0x729, "GXCopyDisp");
|
||||
|
||||
#if DEBUG
|
||||
__GXVerifCopy(dest, clear);
|
||||
#endif
|
||||
if (clear) {
|
||||
reg = gx->zmode;
|
||||
SET_REG_FIELD(0, reg, 1, 0, 1);
|
||||
SET_REG_FIELD(0, reg, 3, 1, 7);
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
|
||||
reg = gx->cmode0;
|
||||
SET_REG_FIELD(0, reg, 1, 0, 0);
|
||||
SET_REG_FIELD(0, reg, 1, 1, 0);
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
}
|
||||
changePeCtrl = FALSE;
|
||||
if ((clear || (u32)GET_REG_FIELD(gx->peCtrl, 3, 0) == 3) && (u32)GET_REG_FIELD(gx->peCtrl, 1, 6) == 1) {
|
||||
changePeCtrl = TRUE;
|
||||
tempPeCtrl = gx->peCtrl;
|
||||
SET_REG_FIELD(0, tempPeCtrl, 1, 6, 0);
|
||||
GX_WRITE_RAS_REG(tempPeCtrl);
|
||||
}
|
||||
GX_WRITE_RAS_REG(gx->cpDispSrc);
|
||||
GX_WRITE_RAS_REG(gx->cpDispSize);
|
||||
GX_WRITE_RAS_REG(gx->cpDispStride);
|
||||
|
||||
phyAddr = (u32)dest & 0x3FFFFFFF;
|
||||
reg = 0;
|
||||
SET_REG_FIELD(0x750, reg, 21, 0, phyAddr >> 5);
|
||||
SET_REG_FIELD(0x754, reg, 8, 24, 0x4B);
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
|
||||
SET_REG_FIELD(0x754, gx->cpDisp, 1, 11, clear);
|
||||
SET_REG_FIELD(0x754, gx->cpDisp, 1, 14, 1);
|
||||
SET_REG_FIELD(0x754, gx->cpDisp, 8, 24, 0x52);
|
||||
GX_WRITE_RAS_REG(gx->cpDisp);
|
||||
|
||||
if (clear) {
|
||||
GX_WRITE_RAS_REG(gx->zmode);
|
||||
GX_WRITE_RAS_REG(gx->cmode0);
|
||||
}
|
||||
if (changePeCtrl) {
|
||||
GX_WRITE_RAS_REG(gx->peCtrl);
|
||||
}
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXCopyTex(void *dest, GXBool clear)
|
||||
{
|
||||
u32 reg;
|
||||
u32 tempPeCtrl;
|
||||
u32 phyAddr;
|
||||
u8 changePeCtrl;
|
||||
|
||||
CHECK_GXBEGIN(0x77C, "GXCopyTex");
|
||||
|
||||
#if DEBUG
|
||||
__GXVerifCopy(dest, clear);
|
||||
#endif
|
||||
if (clear) {
|
||||
reg = gx->zmode;
|
||||
SET_REG_FIELD(0, reg, 1, 0, 1);
|
||||
SET_REG_FIELD(0, reg, 3, 1, 7);
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
|
||||
reg = gx->cmode0;
|
||||
SET_REG_FIELD(0, reg, 1, 0, 0);
|
||||
SET_REG_FIELD(0, reg, 1, 1, 0);
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
}
|
||||
changePeCtrl = 0;
|
||||
tempPeCtrl = gx->peCtrl;
|
||||
if (gx->cpTexZ && ((tempPeCtrl & 7) != 3)) {
|
||||
changePeCtrl = 1;
|
||||
SET_REG_FIELD(0, tempPeCtrl, 3, 0, 3);
|
||||
}
|
||||
if (((clear != 0) || ((u32)(tempPeCtrl & 7) == 3)) && ((u32)((tempPeCtrl >> 6U) & 1) == 1)) {
|
||||
changePeCtrl = 1;
|
||||
SET_REG_FIELD(0, tempPeCtrl, 1, 6, 0);
|
||||
}
|
||||
if (changePeCtrl) {
|
||||
GX_WRITE_RAS_REG(tempPeCtrl);
|
||||
}
|
||||
GX_WRITE_RAS_REG(gx->cpTexSrc);
|
||||
GX_WRITE_RAS_REG(gx->cpTexSize);
|
||||
GX_WRITE_RAS_REG(gx->cpTexStride);
|
||||
|
||||
phyAddr = (u32)dest & 0x3FFFFFFF;
|
||||
reg = 0;
|
||||
SET_REG_FIELD(0x7AD, reg, 21, 0, phyAddr >> 5);
|
||||
SET_REG_FIELD(0x7AD, reg, 8, 24, 0x4B);
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
|
||||
SET_REG_FIELD(0x7B1, gx->cpTex, 1, 11, clear);
|
||||
SET_REG_FIELD(0x7B1, gx->cpTex, 1, 14, 0);
|
||||
SET_REG_FIELD(0x7B1, gx->cpTex, 8, 24, 0x52);
|
||||
GX_WRITE_RAS_REG(gx->cpTex);
|
||||
|
||||
if (clear != 0) {
|
||||
GX_WRITE_RAS_REG(gx->zmode);
|
||||
GX_WRITE_RAS_REG(gx->cmode0);
|
||||
}
|
||||
if (changePeCtrl) {
|
||||
GX_WRITE_RAS_REG(gx->peCtrl);
|
||||
}
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXClearBoundingBox(void)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
CHECK_GXBEGIN(0x7D3, "GXClearBoundingBox");
|
||||
reg = 0x550003FF;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
reg = 0x560003FF;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXReadBoundingBox(u16 *left, u16 *top, u16 *right, u16 *bottom)
|
||||
{
|
||||
*left = GX_GET_PE_REG(8);
|
||||
*top = GX_GET_PE_REG(10);
|
||||
*right = GX_GET_PE_REG(9);
|
||||
*bottom = GX_GET_PE_REG(11);
|
||||
}
|
||||
146
src/dolphin/gx/GXGeometry.c
Normal file
146
src/dolphin/gx/GXGeometry.c
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
#include <dolphin/gx.h>
|
||||
#include <dolphin/os.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <dolphin/gx/GXPriv.h>
|
||||
|
||||
void __GXSetDirtyState(void)
|
||||
{
|
||||
if (gx->dirtyState & 1) {
|
||||
__GXSetSUTexRegs();
|
||||
}
|
||||
if (gx->dirtyState & 2) {
|
||||
__GXUpdateBPMask();
|
||||
}
|
||||
if (gx->dirtyState & 4) {
|
||||
__GXSetGenMode();
|
||||
}
|
||||
if (gx->dirtyState & 8) {
|
||||
__GXSetVCD();
|
||||
}
|
||||
if (gx->dirtyState & 0x10) {
|
||||
__GXSetVAT();
|
||||
}
|
||||
if (gx->dirtyState & 0x18) {
|
||||
__GXCalculateVLim();
|
||||
}
|
||||
gx->dirtyState = 0;
|
||||
}
|
||||
|
||||
void GXBegin(GXPrimitive type, GXVtxFmt vtxfmt, u16 nverts)
|
||||
{
|
||||
ASSERTMSGLINE(0x167, vtxfmt < 8, "GXBegin: Format Index is out of range");
|
||||
ASSERTMSGLINE(0x168, !__GXinBegin, "GXBegin: called inside another GXBegin/GXEnd");
|
||||
|
||||
if (gx->dirtyState != 0) {
|
||||
__GXSetDirtyState();
|
||||
}
|
||||
if (*(u32 *)&gx->vNumNot == 0) { // checks both vNum and bpSentNot
|
||||
__GXSendFlushPrim();
|
||||
}
|
||||
GX_WRITE_U8(vtxfmt | type);
|
||||
GX_WRITE_U16(nverts);
|
||||
}
|
||||
|
||||
void __GXSendFlushPrim(void)
|
||||
{
|
||||
u32 i;
|
||||
u32 numD = gx->vNum * gx->vLim;
|
||||
|
||||
GX_WRITE_U8(0x98);
|
||||
GX_WRITE_U16(gx->vNum);
|
||||
for (i = 0; i < numD; i += 4) {
|
||||
GX_WRITE_U32(0);
|
||||
}
|
||||
gx->bpSentNot = 1;
|
||||
}
|
||||
|
||||
void GXSetLineWidth(u8 width, GXTexOffset texOffsets)
|
||||
{
|
||||
CHECK_GXBEGIN(0x1B8, "GXSetLineWidth");
|
||||
SET_REG_FIELD(0x1B9, gx->lpSize, 8, 0, width);
|
||||
SET_REG_FIELD(0x1BA, gx->lpSize, 3, 16, texOffsets);
|
||||
GX_WRITE_RAS_REG(gx->lpSize);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXGetLineWidth(u8 *width, GXTexOffset *texOffsets)
|
||||
{
|
||||
ASSERTMSGLINE(0x1CF, width != NULL && texOffsets != NULL, "GXGet*: invalid null pointer");
|
||||
|
||||
*width = GET_REG_FIELD(gx->lpSize, 8, 0);
|
||||
*texOffsets = GET_REG_FIELD(gx->lpSize, 3, 16);
|
||||
}
|
||||
|
||||
void GXSetPointSize(u8 pointSize, GXTexOffset texOffsets)
|
||||
{
|
||||
CHECK_GXBEGIN(0x1E4, "GXSetPointSize");
|
||||
SET_REG_FIELD(0x1E5, gx->lpSize, 8, 8, pointSize);
|
||||
SET_REG_FIELD(0x1E6, gx->lpSize, 3, 19, texOffsets);
|
||||
GX_WRITE_RAS_REG(gx->lpSize);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXGetPointSize(u8 *pointSize, GXTexOffset *texOffsets)
|
||||
{
|
||||
ASSERTMSGLINE(0x1FB, pointSize != NULL && texOffsets != NULL, "GXGet*: invalid null pointer");
|
||||
|
||||
*pointSize = (int)GET_REG_FIELD(gx->lpSize, 8, 8);
|
||||
*texOffsets = GET_REG_FIELD(gx->lpSize, 3, 19);
|
||||
}
|
||||
|
||||
void GXEnableTexOffsets(GXTexCoordID coord, u8 line_enable, u8 point_enable)
|
||||
{
|
||||
CHECK_GXBEGIN(0x211, "GXEnableTexOffsets");
|
||||
|
||||
ASSERTMSGLINE(0x213, coord < 8, "GXEnableTexOffsets: Invalid coordinate Id");
|
||||
|
||||
SET_REG_FIELD(0x215, gx->suTs0[coord], 1, 18, line_enable);
|
||||
SET_REG_FIELD(0x216, gx->suTs0[coord], 1, 19, point_enable);
|
||||
GX_WRITE_RAS_REG(gx->suTs0[coord]);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetCullMode(GXCullMode mode)
|
||||
{
|
||||
GXCullMode hwMode;
|
||||
|
||||
CHECK_GXBEGIN(0x21D, "GXSetCullMode");
|
||||
switch (mode) {
|
||||
case GX_CULL_FRONT:
|
||||
hwMode = GX_CULL_BACK;
|
||||
break;
|
||||
case GX_CULL_BACK:
|
||||
hwMode = GX_CULL_FRONT;
|
||||
break;
|
||||
default:
|
||||
hwMode = mode;
|
||||
break;
|
||||
}
|
||||
SET_REG_FIELD(0x225, gx->genMode, 2, 14, hwMode);
|
||||
gx->dirtyState |= 4;
|
||||
}
|
||||
|
||||
void GXGetCullMode(GXCullMode *mode)
|
||||
{
|
||||
GXCullMode hwMode = gx->genMode;
|
||||
*mode = ((hwMode >> 0xD) & 0x2) | (((((int)hwMode >> 0xE) & 0x2) >> 0x1));
|
||||
}
|
||||
|
||||
void GXSetCoPlanar(GXBool enable)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
CHECK_GXBEGIN(0x265, "GXSetCoPlanar");
|
||||
|
||||
SET_REG_FIELD(0x267, gx->genMode, 1, 19, enable);
|
||||
reg = 0xFE080000;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
GX_WRITE_RAS_REG(gx->genMode);
|
||||
}
|
||||
|
||||
void __GXSetGenMode(void)
|
||||
{
|
||||
GX_WRITE_RAS_REG(gx->genMode);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
372
src/dolphin/gx/GXInit.c
Normal file
372
src/dolphin/gx/GXInit.c
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
#include <string.h>
|
||||
|
||||
#include <dolphin/PPCArch.h>
|
||||
#include <dolphin/gx.h>
|
||||
#include <dolphin/os.h>
|
||||
#include <dolphin/vi.h>
|
||||
|
||||
#include <dolphin/gx/GXPriv.h>
|
||||
|
||||
void __GXInitGX();
|
||||
|
||||
static struct __GXData_struct gxData;
|
||||
struct __GXData_struct *gx = &gxData;
|
||||
// DWARF info lists all of these as "void *", but these types make more sense.
|
||||
u16 *__memReg;
|
||||
u16 *__peReg;
|
||||
u16 *__cpReg;
|
||||
u32 *__piReg;
|
||||
|
||||
// clang-format off
|
||||
asm BOOL IsWriteGatherBufferEmpty(void)
|
||||
{
|
||||
sync
|
||||
mfspr r3, WPAR
|
||||
andi. r3, r3, 1
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
static void EnableWriteGatherPipe(void)
|
||||
{
|
||||
u32 hid2 = PPCMfhid2();
|
||||
|
||||
PPCMtwpar(OSUncachedToPhysical((void *)GXFIFO_ADDR));
|
||||
hid2 |= 0x40000000;
|
||||
PPCMthid2(hid2);
|
||||
}
|
||||
|
||||
static void DisableWriteGatherPipe(void)
|
||||
{
|
||||
u32 hid2 = PPCMfhid2();
|
||||
|
||||
hid2 &= ~0x40000000;
|
||||
PPCMthid2(hid2);
|
||||
}
|
||||
|
||||
static GXTexRegion *__GXDefaultTexRegionCallback(GXTexObj *t_obj, GXTexMapID unused)
|
||||
{
|
||||
GXTexFmt fmt = GXGetTexObjFmt(t_obj);
|
||||
|
||||
if (fmt != GX_TF_C4 && fmt != GX_TF_C8 && fmt != GX_TF_C14X2) {
|
||||
return &gx->TexRegions[gx->nextTexRgn++ & 7];
|
||||
}
|
||||
else {
|
||||
return &gx->TexRegionsCI[gx->nextTexRgnCI++ & 3];
|
||||
}
|
||||
}
|
||||
|
||||
static GXTlutRegion *__GXDefaultTlutRegionCallback(u32 idx)
|
||||
{
|
||||
if (idx >= 0x14U) {
|
||||
return NULL;
|
||||
}
|
||||
return &gx->TlutRegions[idx];
|
||||
}
|
||||
|
||||
GXFifoObj FifoObj;
|
||||
|
||||
GXFifoObj *GXInit(void *base, u32 size)
|
||||
{
|
||||
u32 i;
|
||||
u32 reg;
|
||||
u32 freqBase;
|
||||
|
||||
// OSRegisterVersion(__GXVersion);
|
||||
|
||||
gx->inDispList = FALSE;
|
||||
gx->dlSaveContext = TRUE;
|
||||
// gx->abtWaitPECopy = 1;
|
||||
#if DEBUG
|
||||
__GXinBegin = FALSE;
|
||||
#endif
|
||||
gx->tcsManEnab = FALSE;
|
||||
gx->tevTcEnab = FALSE;
|
||||
|
||||
GXSetMisc(GX_MT_XF_FLUSH, 0);
|
||||
|
||||
__piReg = OSPhysicalToUncached(0xC003000);
|
||||
__cpReg = OSPhysicalToUncached(0xC000000);
|
||||
__peReg = OSPhysicalToUncached(0xC001000);
|
||||
__memReg = OSPhysicalToUncached(0xC004000);
|
||||
// __GXFifoInit();
|
||||
// GXInitFifoBase(&FifoObj, base, size);
|
||||
// GXSetCPUFifo(&FifoObj);
|
||||
// GXSetGPFifo(&FifoObj);
|
||||
|
||||
// if (!resetFuncRegistered) {
|
||||
// OSRegisterResetFunction(&GXResetFuncInfo);
|
||||
// resetFuncRegistered = 1;
|
||||
// }
|
||||
|
||||
// __GXPEInit();
|
||||
// EnableWriteGatherPipe();
|
||||
|
||||
gx->genMode = 0;
|
||||
SET_REG_FIELD(0, gx->genMode, 8, 24, 0);
|
||||
gx->bpMask = 255;
|
||||
SET_REG_FIELD(0, gx->bpMask, 8, 24, 0x0F);
|
||||
gx->lpSize = 0;
|
||||
SET_REG_FIELD(0, gx->lpSize, 8, 24, 0x22);
|
||||
for (i = 0; i < 16; ++i) {
|
||||
gx->tevc[i] = 0;
|
||||
gx->teva[i] = 0;
|
||||
gx->tref[i / 2] = 0;
|
||||
gx->texmapId[i] = GX_TEXMAP_NULL;
|
||||
SET_REG_FIELD(0x46A, gx->tevc[i], 8, 24, 0xC0 + i * 2);
|
||||
SET_REG_FIELD(0x46B, gx->teva[i], 8, 24, 0xC1 + i * 2);
|
||||
SET_REG_FIELD(0x46D, gx->tevKsel[i / 2], 8, 24, 0xF6 + i / 2);
|
||||
SET_REG_FIELD(0x46F, gx->tref[i / 2], 8, 24, 0x28 + i / 2);
|
||||
}
|
||||
gx->iref = 0;
|
||||
SET_REG_FIELD(0, gx->iref, 8, 24, 0x27);
|
||||
for (i = 0; i < 8; ++i) {
|
||||
gx->suTs0[i] = 0;
|
||||
gx->suTs1[i] = 0;
|
||||
SET_REG_FIELD(0x478, gx->suTs0[i], 8, 24, 0x30 + i * 2);
|
||||
SET_REG_FIELD(0x479, gx->suTs1[i], 8, 24, 0x31 + i * 2);
|
||||
}
|
||||
SET_REG_FIELD(0, gx->suScis0, 8, 24, 0x20);
|
||||
SET_REG_FIELD(0, gx->suScis1, 8, 24, 0x21);
|
||||
SET_REG_FIELD(0, gx->cmode0, 8, 24, 0x41);
|
||||
SET_REG_FIELD(0, gx->cmode1, 8, 24, 0x42);
|
||||
SET_REG_FIELD(0, gx->zmode, 8, 24, 0x40);
|
||||
SET_REG_FIELD(0, gx->peCtrl, 8, 24, 0x43);
|
||||
SET_REG_FIELD(0, gx->cpTex, 2, 7, 0);
|
||||
|
||||
// gx->zScale = 1.6777216E7f;
|
||||
// gx->zOffset = 0.0f;
|
||||
gx->dirtyState = 0;
|
||||
gx->dirtyVAT = FALSE;
|
||||
#if DEBUG
|
||||
__gxVerif->verifyLevel = GX_WARN_NONE;
|
||||
GXSetVerifyCallback((GXVerifyCallback)__GXDefaultVerifyCallback);
|
||||
for (i = 0; i < 256; i++) {
|
||||
SET_REG_FIELD(0, __gxVerif->rasRegs[i], 8, 24, 0xFF);
|
||||
}
|
||||
memset(__gxVerif->xfRegsDirty, 0, 0x50);
|
||||
memset(__gxVerif->xfMtxDirty, 0, 0x100);
|
||||
memset(__gxVerif->xfNrmDirty, 0, 0x60);
|
||||
memset(__gxVerif->xfLightDirty, 0, 0x80);
|
||||
#endif
|
||||
freqBase = __OSBusClock / 500;
|
||||
// __GXFlushTextureState();
|
||||
reg = (freqBase >> 11) | 0x400 | 0x69000000;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
|
||||
// __GXFlushTextureState();
|
||||
reg = (freqBase / 0x1080) | 0x200 | 0x46000000;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
|
||||
// __GXInitRevisionBits();
|
||||
|
||||
// for (i = 0; i < 8; i++) {
|
||||
// GXInitTexCacheRegion(&gx->TexRegions0[i], GX_FALSE, GXTexRegionAddrTable[i],
|
||||
// GX_TEXCACHE_32K, GXTexRegionAddrTable[i + 8], GX_TEXCACHE_32K);
|
||||
// GXInitTexCacheRegion(&gx->TexRegions1[i], GX_FALSE, GXTexRegionAddrTable[i + 16],
|
||||
// GX_TEXCACHE_32K, GXTexRegionAddrTable[i + 24], GX_TEXCACHE_32K);
|
||||
// GXInitTexCacheRegion(&gx->TexRegions2[i], GX_TRUE, GXTexRegionAddrTable[i + 32],
|
||||
// GX_TEXCACHE_32K, GXTexRegionAddrTable[i + 40], GX_TEXCACHE_32K);
|
||||
// }
|
||||
|
||||
// for (i = 0; i < 16; i++) {
|
||||
// GXInitTlutRegion(&gx->TlutRegions[i], 0xC0000 + 0x2000 * i, GX_TLUT_256);
|
||||
// }
|
||||
|
||||
// for (i = 0; i < 4; i++) {
|
||||
// GXInitTlutRegion(&gx->TlutRegions[i + 16], 0xE0000 + 0x8000 * i, GX_TLUT_1K);
|
||||
// }
|
||||
|
||||
{
|
||||
u32 reg = 0;
|
||||
#if DEBUG
|
||||
s32 regAddr;
|
||||
#endif
|
||||
GX_SET_CP_REG(3, reg);
|
||||
|
||||
SET_REG_FIELD(0, gx->perfSel, 4, 4, 0);
|
||||
GX_WRITE_U8(0x8);
|
||||
GX_WRITE_U8(0x20);
|
||||
GX_WRITE_U32(gx->perfSel);
|
||||
#if DEBUG
|
||||
regAddr = -12;
|
||||
#endif
|
||||
|
||||
reg = 0;
|
||||
GX_WRITE_XF_REG(6, reg);
|
||||
|
||||
reg = 0x23000000;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
|
||||
reg = 0x24000000;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
|
||||
reg = 0x67000000;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
}
|
||||
|
||||
__GXSetIndirectMask(0);
|
||||
__GXSetTmemConfig(2);
|
||||
__GXInitGX();
|
||||
|
||||
return &FifoObj;
|
||||
}
|
||||
|
||||
void __GXInitGX()
|
||||
{
|
||||
GXRenderModeObj *rmode;
|
||||
GXAttr var_r30;
|
||||
f32 identity_mtx[3][4];
|
||||
GXColor clear = { 64, 64, 64, 255 };
|
||||
GXColor black = { 0, 0, 0, 0 };
|
||||
GXColor white = { 255, 255, 255, 255 };
|
||||
u32 i;
|
||||
|
||||
switch (VIGetTvFormat()) {
|
||||
case 0:
|
||||
rmode = &GXNtsc480IntDf;
|
||||
break;
|
||||
case 1:
|
||||
rmode = &GXPal528IntDf;
|
||||
break;
|
||||
case 5:
|
||||
rmode = &GXEurgb60Hz480IntDf;
|
||||
break;
|
||||
case 2:
|
||||
rmode = &GXMpal480IntDf;
|
||||
break;
|
||||
default:
|
||||
rmode = &GXNtsc480IntDf;
|
||||
break;
|
||||
}
|
||||
|
||||
GXSetCopyClear(clear, 0xFFFFFF);
|
||||
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3CU);
|
||||
GXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, 0x3CU);
|
||||
GXSetTexCoordGen(GX_TEXCOORD2, GX_TG_MTX2x4, GX_TG_TEX2, 0x3CU);
|
||||
GXSetTexCoordGen(GX_TEXCOORD3, GX_TG_MTX2x4, GX_TG_TEX3, 0x3CU);
|
||||
GXSetTexCoordGen(GX_TEXCOORD4, GX_TG_MTX2x4, GX_TG_TEX4, 0x3CU);
|
||||
GXSetTexCoordGen(GX_TEXCOORD5, GX_TG_MTX2x4, GX_TG_TEX5, 0x3CU);
|
||||
GXSetTexCoordGen(GX_TEXCOORD6, GX_TG_MTX2x4, GX_TG_TEX6, 0x3CU);
|
||||
GXSetTexCoordGen(GX_TEXCOORD7, GX_TG_MTX2x4, GX_TG_TEX7, 0x3CU);
|
||||
GXSetNumTexGens(1);
|
||||
GXClearVtxDesc();
|
||||
GXInvalidateVtxCache();
|
||||
for (var_r30 = GX_VA_POS; (u32)var_r30 <= 0x18; var_r30++) {
|
||||
GXSetArray(var_r30, gx, 0);
|
||||
}
|
||||
GXSetLineWidth(6, 0);
|
||||
GXSetPointSize(6, 0);
|
||||
GXEnableTexOffsets(0, 0, 0);
|
||||
GXEnableTexOffsets(1, 0, 0);
|
||||
GXEnableTexOffsets(2, 0, 0);
|
||||
GXEnableTexOffsets(3, 0, 0);
|
||||
GXEnableTexOffsets(4, 0, 0);
|
||||
GXEnableTexOffsets(5, 0, 0);
|
||||
GXEnableTexOffsets(6, 0, 0);
|
||||
GXEnableTexOffsets(7, 0, 0);
|
||||
identity_mtx[0][0] = 1.0f;
|
||||
identity_mtx[0][1] = 0.0f;
|
||||
identity_mtx[0][2] = 0.0f;
|
||||
identity_mtx[0][3] = 0.0f;
|
||||
identity_mtx[1][0] = 0.0f;
|
||||
identity_mtx[1][1] = 1.0f;
|
||||
identity_mtx[1][2] = 0.0f;
|
||||
identity_mtx[1][3] = 0.0f;
|
||||
identity_mtx[2][0] = 0.0f;
|
||||
identity_mtx[2][1] = 0.0f;
|
||||
identity_mtx[2][2] = 1.0f;
|
||||
identity_mtx[2][3] = 0.0f;
|
||||
GXLoadPosMtxImm(identity_mtx, GX_PNMTX0);
|
||||
GXLoadNrmMtxImm(identity_mtx, GX_PNMTX0);
|
||||
GXSetCurrentMtx(GX_PNMTX0);
|
||||
GXLoadTexMtxImm(identity_mtx, GX_IDENTITY, GX_MTX3x4);
|
||||
GXLoadTexMtxImm(identity_mtx, GX_PTIDENTITY, GX_MTX3x4);
|
||||
GXSetViewport(0.0f, 0.0f, rmode->fbWidth, rmode->xfbHeight, 0.0f, 1.0f);
|
||||
GXSetCoPlanar(GX_DISABLE);
|
||||
GXSetCullMode(GX_CULL_BACK);
|
||||
GXSetClipMode(GX_CLIP_ENABLE);
|
||||
GXSetScissor(0, 0, rmode->fbWidth, rmode->efbHeight);
|
||||
GXSetScissorBoxOffset(0, 0);
|
||||
GXSetNumChans(0);
|
||||
GXSetChanCtrl(GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
|
||||
GXSetChanAmbColor(GX_COLOR0A0, black);
|
||||
GXSetChanMatColor(GX_COLOR0A0, white);
|
||||
GXSetChanCtrl(GX_COLOR1A1, GX_DISABLE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
|
||||
GXSetChanAmbColor(GX_COLOR1A1, black);
|
||||
GXSetChanMatColor(GX_COLOR1A1, white);
|
||||
GXInvalidateTexAll();
|
||||
gx->nextTexRgnCI = gx->nextTexRgn = i = GX_TEVSTAGE0;
|
||||
GXSetTexRegionCallback((void *)__GXDefaultTexRegionCallback);
|
||||
GXSetTlutRegionCallback(__GXDefaultTlutRegionCallback);
|
||||
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 < 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 = GX_TEVSTAGE0; 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, black);
|
||||
GXSetFogRangeAdj(GX_DISABLE, 0, 0);
|
||||
GXSetBlendMode(GX_BM_NONE, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
|
||||
GXSetColorUpdate(GX_ENABLE);
|
||||
GXSetAlphaUpdate(GX_ENABLE);
|
||||
GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE);
|
||||
GXSetZCompLoc(GX_TRUE);
|
||||
GXSetDither(GX_ENABLE);
|
||||
GXSetDstAlpha(GX_DISABLE, 0);
|
||||
GXSetPixelFmt(GX_PF_RGB8_Z24, GX_ZC_LINEAR);
|
||||
GXSetFieldMask(GX_ENABLE, GX_ENABLE);
|
||||
GXSetFieldMode(rmode->field_rendering, ((rmode->viHeight == 2 * rmode->xfbHeight) ? GX_ENABLE : GX_DISABLE));
|
||||
|
||||
GXSetDispCopySrc(0, 0, rmode->fbWidth, rmode->efbHeight);
|
||||
GXSetDispCopyDst(rmode->fbWidth, rmode->efbHeight);
|
||||
GXSetDispCopyYScale((f32)(rmode->xfbHeight) / (f32)(rmode->efbHeight));
|
||||
GXSetCopyClamp((GXFBClamp)(GX_CLAMP_TOP | GX_CLAMP_BOTTOM));
|
||||
GXSetCopyFilter(rmode->aa, rmode->sample_pattern, GX_TRUE, rmode->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_DISABLE, 0);
|
||||
GXPokeZMode(GX_TRUE, GX_ALWAYS, GX_TRUE);
|
||||
GXSetGPMetric(GX_PERF0_NONE, GX_PERF1_NONE);
|
||||
GXClearGPMetric();
|
||||
}
|
||||
620
src/dolphin/gx/GXLight.c
Normal file
620
src/dolphin/gx/GXLight.c
Normal file
|
|
@ -0,0 +1,620 @@
|
|||
#include <dolphin/gx.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <dolphin/gx/GXPriv.h>
|
||||
|
||||
float cosf(float x);
|
||||
inline float sqrtf(float x)
|
||||
{
|
||||
static const double _half = .5;
|
||||
static const double _three = 3.0;
|
||||
volatile float y;
|
||||
if (x > 0.0f)
|
||||
{
|
||||
double guess = __frsqrte((double)x); // returns an approximation to
|
||||
guess = _half*guess*(_three - guess*guess*x); // now have 12 sig bits
|
||||
guess = _half*guess*(_three - guess*guess*x); // now have 24 sig bits
|
||||
guess = _half*guess*(_three - guess*guess*x); // now have 32 sig bits
|
||||
y = (float)(x*guess);
|
||||
return y ;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
// GXLightObj private data
|
||||
struct __GXLightObjInt_struct {
|
||||
u32 reserved[3];
|
||||
u32 Color;
|
||||
f32 a[3];
|
||||
f32 k[3];
|
||||
f32 lpos[3];
|
||||
f32 ldir[3];
|
||||
};
|
||||
|
||||
void GXInitLightAttn(GXLightObj *lt_obj, f32 a0, f32 a1, f32 a2, f32 k0, f32 k1, f32 k2)
|
||||
{
|
||||
struct __GXLightObjInt_struct *obj;
|
||||
|
||||
ASSERTMSGLINE(0x62, lt_obj != NULL, "Light Object Pointer is null");
|
||||
obj = (struct __GXLightObjInt_struct *)lt_obj;
|
||||
CHECK_GXBEGIN(0x63, "GXInitLightAttn");
|
||||
obj->a[0] = a0;
|
||||
obj->a[1] = a1;
|
||||
obj->a[2] = a2;
|
||||
obj->k[0] = k0;
|
||||
obj->k[1] = k1;
|
||||
obj->k[2] = k2;
|
||||
}
|
||||
|
||||
void GXInitLightAttnA(GXLightObj *lt_obj, f32 a0, f32 a1, f32 a2)
|
||||
{
|
||||
struct __GXLightObjInt_struct *obj;
|
||||
|
||||
ASSERTMSGLINE(0x70, lt_obj != NULL, "Light Object Pointer is null");
|
||||
obj = (struct __GXLightObjInt_struct *)lt_obj;
|
||||
CHECK_GXBEGIN(0x71, "GXInitLightAttnA");
|
||||
obj->a[0] = a0;
|
||||
obj->a[1] = a1;
|
||||
obj->a[2] = a2;
|
||||
}
|
||||
|
||||
void GXGetLightAttnA(GXLightObj *lt_obj, f32 *a0, f32 *a1, f32 *a2)
|
||||
{
|
||||
struct __GXLightObjInt_struct *obj;
|
||||
|
||||
ASSERTMSGLINE(0x7A, lt_obj != NULL, "Light Object Pointer is null");
|
||||
obj = (struct __GXLightObjInt_struct *)lt_obj;
|
||||
CHECK_GXBEGIN(0x7B, "GXGetLightAttnA");
|
||||
*a0 = obj->a[0];
|
||||
*a1 = obj->a[1];
|
||||
*a2 = obj->a[2];
|
||||
}
|
||||
|
||||
void GXInitLightAttnK(GXLightObj *lt_obj, f32 k0, f32 k1, f32 k2)
|
||||
{
|
||||
struct __GXLightObjInt_struct *obj;
|
||||
|
||||
ASSERTMSGLINE(0x84, lt_obj != NULL, "Light Object Pointer is null");
|
||||
obj = (struct __GXLightObjInt_struct *)lt_obj;
|
||||
CHECK_GXBEGIN(0x85, "GXInitLightAttnK");
|
||||
obj->k[0] = k0;
|
||||
obj->k[1] = k1;
|
||||
obj->k[2] = k2;
|
||||
}
|
||||
|
||||
void GXGetLightAttnK(GXLightObj *lt_obj, f32 *k0, f32 *k1, f32 *k2)
|
||||
{
|
||||
struct __GXLightObjInt_struct *obj;
|
||||
|
||||
ASSERTMSGLINE(0x8E, lt_obj != NULL, "Light Object Pointer is null");
|
||||
obj = (struct __GXLightObjInt_struct *)lt_obj;
|
||||
CHECK_GXBEGIN(0x8F, "GXGetLightAttnK");
|
||||
*k0 = obj->k[0];
|
||||
*k1 = obj->k[1];
|
||||
*k2 = obj->k[2];
|
||||
}
|
||||
|
||||
void GXInitLightSpot(GXLightObj *lt_obj, f32 cutoff, GXSpotFn spot_func)
|
||||
{
|
||||
float a0, a1, a2;
|
||||
float d;
|
||||
float cr;
|
||||
struct __GXLightObjInt_struct *obj;
|
||||
|
||||
ASSERTMSGLINE(0xA7, lt_obj != NULL, "Light Object Pointer is null");
|
||||
obj = (struct __GXLightObjInt_struct *)lt_obj;
|
||||
CHECK_GXBEGIN(0xA9, "GXInitLightSpot");
|
||||
|
||||
if (cutoff <= 0.0f || cutoff > 90.0f)
|
||||
spot_func = GX_SP_OFF;
|
||||
|
||||
cr = cosf((3.1415927f * cutoff) / 180.0f);
|
||||
switch (spot_func) {
|
||||
case GX_SP_FLAT:
|
||||
a0 = -1000.0f * cr;
|
||||
a1 = 1000.0f;
|
||||
a2 = 0.0f;
|
||||
break;
|
||||
case GX_SP_COS:
|
||||
a0 = -cr / (1.0f - cr);
|
||||
a1 = 1.0f / (1.0f - cr);
|
||||
a2 = 0.0f;
|
||||
break;
|
||||
case GX_SP_COS2:
|
||||
a0 = 0.0f;
|
||||
a1 = -cr / (1.0f - cr);
|
||||
a2 = 1.0f / (1.0f - cr);
|
||||
break;
|
||||
case GX_SP_SHARP:
|
||||
d = (1.0f - cr) * (1.0f - cr);
|
||||
a0 = (cr * (cr - 2.0f)) / d;
|
||||
a1 = 2.0f / d;
|
||||
a2 = -1.0f / d;
|
||||
break;
|
||||
case GX_SP_RING1:
|
||||
d = (1.0f - cr) * (1.0f - cr);
|
||||
a0 = (-4.0f * cr) / d;
|
||||
a1 = (4.0f * (1.0f + cr)) / d;
|
||||
a2 = -4.0f / d;
|
||||
break;
|
||||
case GX_SP_RING2:
|
||||
d = (1.0f - cr) * (1.0f - cr);
|
||||
a0 = 1.0f - ((2.0f * cr * cr) / d);
|
||||
a1 = (4.0f * cr) / d;
|
||||
a2 = -2.0f / d;
|
||||
break;
|
||||
case GX_SP_OFF:
|
||||
default:
|
||||
a0 = 1.0f;
|
||||
a1 = 0.0f;
|
||||
a2 = 0.0f;
|
||||
break;
|
||||
}
|
||||
obj->a[0] = a0;
|
||||
obj->a[1] = a1;
|
||||
obj->a[2] = a2;
|
||||
}
|
||||
|
||||
void GXInitLightDistAttn(GXLightObj *lt_obj, f32 ref_dist, f32 ref_br, GXDistAttnFn dist_func)
|
||||
{
|
||||
f32 k0, k1, k2;
|
||||
struct __GXLightObjInt_struct *obj;
|
||||
|
||||
ASSERTMSGLINE(0xF2, lt_obj != NULL, "Light Object Pointer is null");
|
||||
obj = (struct __GXLightObjInt_struct *)lt_obj;
|
||||
CHECK_GXBEGIN(0xF4, "GXInitLightDistAttn");
|
||||
|
||||
if (ref_dist < 0.0f)
|
||||
dist_func = GX_DA_OFF;
|
||||
if (ref_br <= 0.0f || ref_br >= 1.0f)
|
||||
dist_func = GX_DA_OFF;
|
||||
|
||||
switch (dist_func) {
|
||||
case GX_DA_GENTLE:
|
||||
k0 = 1.0f;
|
||||
k1 = (1.0f - ref_br) / (ref_br * ref_dist);
|
||||
k2 = 0.0f;
|
||||
break;
|
||||
case GX_DA_MEDIUM:
|
||||
k0 = 1.0f;
|
||||
k1 = (0.5f * (1.0f - ref_br)) / (ref_br * ref_dist);
|
||||
k2 = (0.5f * (1.0f - ref_br)) / (ref_br * ref_dist * ref_dist);
|
||||
break;
|
||||
case GX_DA_STEEP:
|
||||
k0 = 1.0f;
|
||||
k1 = 0.0f;
|
||||
k2 = (1.0f - ref_br) / (ref_br * ref_dist * ref_dist);
|
||||
break;
|
||||
case GX_DA_OFF:
|
||||
default:
|
||||
k0 = 1.0f;
|
||||
k1 = 0.0f;
|
||||
k2 = 0.0f;
|
||||
break;
|
||||
}
|
||||
|
||||
obj->k[0] = k0;
|
||||
obj->k[1] = k1;
|
||||
obj->k[2] = k2;
|
||||
}
|
||||
|
||||
void GXInitLightPos(GXLightObj *lt_obj, f32 x, f32 y, f32 z)
|
||||
{
|
||||
struct __GXLightObjInt_struct *obj;
|
||||
|
||||
ASSERTMSGLINE(0x129, lt_obj != NULL, "Light Object Pointer is null");
|
||||
obj = (struct __GXLightObjInt_struct *)lt_obj;
|
||||
CHECK_GXBEGIN(0x12B, "GXInitLightPos");
|
||||
|
||||
obj->lpos[0] = x;
|
||||
obj->lpos[1] = y;
|
||||
obj->lpos[2] = z;
|
||||
}
|
||||
|
||||
void GXGetLightPos(const GXLightObj *lt_obj, f32 *x, f32 *y, f32 *z)
|
||||
{
|
||||
struct __GXLightObjInt_struct *obj;
|
||||
|
||||
ASSERTMSGLINE(0x134, lt_obj != NULL, "Light Object Pointer is null");
|
||||
obj = (struct __GXLightObjInt_struct *)lt_obj;
|
||||
CHECK_GXBEGIN(0x136, "GXGetLightPos");
|
||||
|
||||
*x = obj->lpos[0];
|
||||
*y = obj->lpos[1];
|
||||
*z = obj->lpos[2];
|
||||
}
|
||||
|
||||
void GXInitLightDir(GXLightObj *lt_obj, f32 nx, f32 ny, f32 nz)
|
||||
{
|
||||
struct __GXLightObjInt_struct *obj;
|
||||
|
||||
ASSERTMSGLINE(0x149, lt_obj != NULL, "Light Object Pointer is null");
|
||||
obj = (struct __GXLightObjInt_struct *)lt_obj;
|
||||
|
||||
obj->ldir[0] = -nx;
|
||||
obj->ldir[1] = -ny;
|
||||
obj->ldir[2] = -nz;
|
||||
}
|
||||
|
||||
void GXGetLightDir(GXLightObj *lt_obj, f32 *nx, f32 *ny, f32 *nz)
|
||||
{
|
||||
struct __GXLightObjInt_struct *obj;
|
||||
|
||||
ASSERTMSGLINE(0x155, lt_obj != NULL, "Light Object Pointer is null");
|
||||
obj = (struct __GXLightObjInt_struct *)lt_obj;
|
||||
|
||||
*nx = -obj->ldir[0];
|
||||
*ny = -obj->ldir[1];
|
||||
*nz = -obj->ldir[2];
|
||||
}
|
||||
|
||||
void GXInitSpecularDir(GXLightObj *lt_obj, f32 nx, f32 ny, f32 nz)
|
||||
{
|
||||
float mag;
|
||||
float vx;
|
||||
float vy;
|
||||
float vz;
|
||||
struct __GXLightObjInt_struct *obj;
|
||||
|
||||
ASSERTMSGLINE(0x16F, lt_obj != NULL, "Light Object Pointer is null");
|
||||
obj = (struct __GXLightObjInt_struct *)lt_obj;
|
||||
CHECK_GXBEGIN(0x170, "GXInitSpecularDir");
|
||||
|
||||
vx = -nx;
|
||||
vy = -ny;
|
||||
vz = -nz + 1.0f;
|
||||
mag = 1.0f / sqrtf((vx * vx) + (vy * vy) + (vz * vz));
|
||||
obj->ldir[0] = vx * mag;
|
||||
obj->ldir[1] = vy * mag;
|
||||
obj->ldir[2] = vz * mag;
|
||||
obj->lpos[0] = -nx * 1048576.0f;
|
||||
obj->lpos[1] = -ny * 1048576.0f;
|
||||
obj->lpos[2] = -nz * 1048576.0f;
|
||||
}
|
||||
|
||||
void GXInitSpecularDirHA(GXLightObj *lt_obj, f32 nx, f32 ny, f32 nz, f32 hx, f32 hy, f32 hz)
|
||||
{
|
||||
struct __GXLightObjInt_struct *obj;
|
||||
|
||||
ASSERTMSGLINE(0x18E, lt_obj != NULL, "Light Object Pointer is null");
|
||||
obj = (struct __GXLightObjInt_struct *)lt_obj;
|
||||
CHECK_GXBEGIN(0x18F, "GXInitSpecularHA");
|
||||
|
||||
obj->ldir[0] = hx;
|
||||
obj->ldir[1] = hy;
|
||||
obj->ldir[2] = hz;
|
||||
obj->lpos[0] = -nx * 1048576.0f;
|
||||
obj->lpos[1] = -ny * 1048576.0f;
|
||||
obj->lpos[2] = -nz * 1048576.0f;
|
||||
}
|
||||
|
||||
void GXInitLightColor(GXLightObj *lt_obj, GXColor color)
|
||||
{
|
||||
struct __GXLightObjInt_struct *obj;
|
||||
|
||||
ASSERTMSGLINE(0x1A8, lt_obj != NULL, "Light Object Pointer is null");
|
||||
obj = (struct __GXLightObjInt_struct *)lt_obj;
|
||||
CHECK_GXBEGIN(0x1A9, "GXInitLightColor");
|
||||
|
||||
obj->Color = (color.r << 24) | (color.g << 16) | (color.b << 8) | color.a;
|
||||
}
|
||||
|
||||
void GXGetLightColor(const GXLightObj *lt_obj, GXColor *color)
|
||||
{
|
||||
struct __GXLightObjInt_struct *obj;
|
||||
|
||||
ASSERTMSGLINE(0x1B2, lt_obj != NULL, "Light Object Pointer is null");
|
||||
obj = (struct __GXLightObjInt_struct *)lt_obj;
|
||||
CHECK_GXBEGIN(0x1B3, "GXGetLightColor");
|
||||
|
||||
color->r = (obj->Color >> 24) & 0xFF;
|
||||
color->g = (obj->Color >> 16) & 0xFF;
|
||||
color->b = (obj->Color >> 8) & 0xFF;
|
||||
color->a = obj->Color & 0xFF;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
#define WRITE_SOME_LIGHT_REG1(val, addr) \
|
||||
do { \
|
||||
u32 xfData = val; \
|
||||
GX_WRITE_U32(val); \
|
||||
VERIF_MTXLIGHT(addr, xfData); \
|
||||
} while (0)
|
||||
|
||||
#define WRITE_SOME_LIGHT_REG2(val, addr) \
|
||||
do { \
|
||||
f32 xfData = val; \
|
||||
GX_WRITE_F32(val); \
|
||||
VERIF_MTXLIGHT(addr, *(u32 *)&xfData); \
|
||||
} while (0)
|
||||
#else
|
||||
#define WRITE_SOME_LIGHT_REG1(val, addr) GX_WRITE_U32(val)
|
||||
#define WRITE_SOME_LIGHT_REG2(val, addr) GX_WRITE_F32(val)
|
||||
#endif
|
||||
|
||||
void GXLoadLightObjImm(GXLightObj *lt_obj, GXLightID light)
|
||||
{
|
||||
unsigned long addr;
|
||||
unsigned long idx;
|
||||
struct __GXLightObjInt_struct *obj;
|
||||
|
||||
ASSERTMSGLINE(0x1C9, lt_obj != NULL, "Light Object Pointer is null");
|
||||
obj = (struct __GXLightObjInt_struct *)lt_obj;
|
||||
CHECK_GXBEGIN(0x1CA, "GXLoadLightObjImm");
|
||||
|
||||
switch (light) {
|
||||
case GX_LIGHT0:
|
||||
idx = 0;
|
||||
break;
|
||||
case GX_LIGHT1:
|
||||
idx = 1;
|
||||
break;
|
||||
case GX_LIGHT2:
|
||||
idx = 2;
|
||||
break;
|
||||
case GX_LIGHT3:
|
||||
idx = 3;
|
||||
break;
|
||||
case GX_LIGHT4:
|
||||
idx = 4;
|
||||
break;
|
||||
case GX_LIGHT5:
|
||||
idx = 5;
|
||||
break;
|
||||
case GX_LIGHT6:
|
||||
idx = 6;
|
||||
break;
|
||||
case GX_LIGHT7:
|
||||
idx = 7;
|
||||
break;
|
||||
default:
|
||||
idx = 0;
|
||||
ASSERTMSGLINE(0x1DA, 0, "GXLoadLightStateImm: Invalid Light Id");
|
||||
break;
|
||||
}
|
||||
|
||||
addr = idx * 0x10 + 0x600;
|
||||
GX_WRITE_U8(0x10);
|
||||
GX_WRITE_U32(addr | 0xF0000);
|
||||
|
||||
WRITE_SOME_LIGHT_REG1(0, addr);
|
||||
WRITE_SOME_LIGHT_REG1(0, addr + 1);
|
||||
WRITE_SOME_LIGHT_REG1(0, addr + 2);
|
||||
WRITE_SOME_LIGHT_REG1(obj->Color, addr + 3);
|
||||
WRITE_SOME_LIGHT_REG2(obj->a[0], addr + 4);
|
||||
WRITE_SOME_LIGHT_REG2(obj->a[1], addr + 5);
|
||||
WRITE_SOME_LIGHT_REG2(obj->a[2], addr + 6);
|
||||
WRITE_SOME_LIGHT_REG2(obj->k[0], addr + 7);
|
||||
WRITE_SOME_LIGHT_REG2(obj->k[1], addr + 8);
|
||||
WRITE_SOME_LIGHT_REG2(obj->k[2], addr + 9);
|
||||
WRITE_SOME_LIGHT_REG2(obj->lpos[0], addr + 10);
|
||||
WRITE_SOME_LIGHT_REG2(obj->lpos[1], addr + 11);
|
||||
WRITE_SOME_LIGHT_REG2(obj->lpos[2], addr + 12);
|
||||
WRITE_SOME_LIGHT_REG2(obj->ldir[0], addr + 13);
|
||||
WRITE_SOME_LIGHT_REG2(obj->ldir[1], addr + 14);
|
||||
WRITE_SOME_LIGHT_REG2(obj->ldir[2], addr + 15);
|
||||
|
||||
gx->bpSentNot = 1;
|
||||
}
|
||||
|
||||
void GXLoadLightObjIndx(u32 lt_obj_indx, GXLightID light)
|
||||
{
|
||||
unsigned long reg;
|
||||
unsigned long addr;
|
||||
unsigned long idx;
|
||||
|
||||
CHECK_GXBEGIN(0x209, "GXLoadLightObjIndx");
|
||||
|
||||
switch (light) {
|
||||
case GX_LIGHT0:
|
||||
idx = 0;
|
||||
break;
|
||||
case GX_LIGHT1:
|
||||
idx = 1;
|
||||
break;
|
||||
case GX_LIGHT2:
|
||||
idx = 2;
|
||||
break;
|
||||
case GX_LIGHT3:
|
||||
idx = 3;
|
||||
break;
|
||||
case GX_LIGHT4:
|
||||
idx = 4;
|
||||
break;
|
||||
case GX_LIGHT5:
|
||||
idx = 5;
|
||||
break;
|
||||
case GX_LIGHT6:
|
||||
idx = 6;
|
||||
break;
|
||||
case GX_LIGHT7:
|
||||
idx = 7;
|
||||
break;
|
||||
default:
|
||||
idx = 0;
|
||||
ASSERTMSGLINE(0x216, 0, "GXLoadLightObjIndx: Invalid Light Id");
|
||||
break;
|
||||
}
|
||||
|
||||
addr = idx * 0x10 + 0x600;
|
||||
reg = 0;
|
||||
SET_REG_FIELD(0x21C, reg, 12, 0, addr);
|
||||
SET_REG_FIELD(0x21D, reg, 4, 12, 0xF);
|
||||
SET_REG_FIELD(0x21E, reg, 16, 16, lt_obj_indx);
|
||||
GX_WRITE_U8(0x38);
|
||||
GX_WRITE_U32(reg);
|
||||
#if DEBUG
|
||||
__GXShadowIndexState(7, reg);
|
||||
#endif
|
||||
gx->bpSentNot = 1;
|
||||
}
|
||||
|
||||
void GXSetChanAmbColor(GXChannelID chan, GXColor amb_color)
|
||||
{
|
||||
u32 reg = 0;
|
||||
u32 colIdx;
|
||||
u32 alpha;
|
||||
|
||||
CHECK_GXBEGIN(0x239, "GXSetChanAmbColor");
|
||||
|
||||
switch (chan) {
|
||||
case GX_COLOR0:
|
||||
alpha = gx->ambColor[0] & 0xFF;
|
||||
SET_REG_FIELD(0x23E, reg, 8, 0, alpha);
|
||||
SET_REG_FIELD(0x23F, reg, 8, 8, amb_color.b);
|
||||
SET_REG_FIELD(0x240, reg, 8, 16, amb_color.g);
|
||||
SET_REG_FIELD(0x241, reg, 8, 24, amb_color.r);
|
||||
colIdx = 0;
|
||||
break;
|
||||
case GX_COLOR1:
|
||||
alpha = gx->ambColor[1] & 0xFF;
|
||||
SET_REG_FIELD(0x247, reg, 8, 0, alpha);
|
||||
SET_REG_FIELD(0x248, reg, 8, 8, amb_color.b);
|
||||
SET_REG_FIELD(0x249, reg, 8, 16, amb_color.g);
|
||||
SET_REG_FIELD(0x24A, reg, 8, 24, amb_color.r);
|
||||
colIdx = 1;
|
||||
break;
|
||||
case GX_ALPHA0:
|
||||
reg = gx->ambColor[0];
|
||||
SET_REG_FIELD(0x250, reg, 8, 0, amb_color.a);
|
||||
colIdx = 0;
|
||||
break;
|
||||
case GX_ALPHA1:
|
||||
reg = gx->ambColor[1];
|
||||
SET_REG_FIELD(0x256, reg, 8, 0, amb_color.a);
|
||||
colIdx = 1;
|
||||
break;
|
||||
case GX_COLOR0A0:
|
||||
SET_REG_FIELD(0x25B, reg, 8, 0, amb_color.a);
|
||||
SET_REG_FIELD(0x25C, reg, 8, 8, amb_color.b);
|
||||
SET_REG_FIELD(0x25D, reg, 8, 16, amb_color.g);
|
||||
SET_REG_FIELD(0x25E, reg, 8, 24, amb_color.r);
|
||||
colIdx = 0;
|
||||
break;
|
||||
case GX_COLOR1A1:
|
||||
SET_REG_FIELD(0x263, reg, 8, 0, amb_color.a);
|
||||
SET_REG_FIELD(0x264, reg, 8, 8, amb_color.b);
|
||||
SET_REG_FIELD(0x265, reg, 8, 16, amb_color.g);
|
||||
SET_REG_FIELD(0x266, reg, 8, 24, amb_color.r);
|
||||
colIdx = 1;
|
||||
break;
|
||||
default:
|
||||
ASSERTMSGLINE(0x26B, 0, "GXSetChanAmbColor: Invalid Channel Id");
|
||||
return;
|
||||
}
|
||||
|
||||
GX_WRITE_XF_REG(colIdx + 10, reg);
|
||||
gx->bpSentNot = 1;
|
||||
gx->ambColor[colIdx] = reg;
|
||||
}
|
||||
|
||||
void GXSetChanMatColor(GXChannelID chan, GXColor mat_color)
|
||||
{
|
||||
u32 reg = 0;
|
||||
u32 alpha;
|
||||
u32 colIdx;
|
||||
|
||||
CHECK_GXBEGIN(0x28A, "GXSetChanMatColor");
|
||||
|
||||
switch (chan) {
|
||||
case GX_COLOR0:
|
||||
alpha = gx->matColor[0] & 0xFF;
|
||||
SET_REG_FIELD(0x28F, reg, 8, 0, alpha);
|
||||
SET_REG_FIELD(0x290, reg, 8, 8, mat_color.b);
|
||||
SET_REG_FIELD(0x291, reg, 8, 16, mat_color.g);
|
||||
SET_REG_FIELD(0x292, reg, 8, 24, mat_color.r);
|
||||
colIdx = 0;
|
||||
break;
|
||||
case GX_COLOR1:
|
||||
alpha = gx->matColor[1] & 0xFF;
|
||||
SET_REG_FIELD(0x298, reg, 8, 0, alpha);
|
||||
SET_REG_FIELD(0x299, reg, 8, 8, mat_color.b);
|
||||
SET_REG_FIELD(0x29A, reg, 8, 16, mat_color.g);
|
||||
SET_REG_FIELD(0x29B, reg, 8, 24, mat_color.r);
|
||||
colIdx = 1;
|
||||
break;
|
||||
case GX_ALPHA0:
|
||||
reg = gx->matColor[0];
|
||||
SET_REG_FIELD(0x2A1, reg, 8, 0, mat_color.a);
|
||||
colIdx = 0;
|
||||
break;
|
||||
case GX_ALPHA1:
|
||||
reg = gx->matColor[1];
|
||||
SET_REG_FIELD(0x2A7, reg, 8, 0, mat_color.a);
|
||||
colIdx = 1;
|
||||
break;
|
||||
case GX_COLOR0A0:
|
||||
SET_REG_FIELD(0x2AC, reg, 8, 0, mat_color.a);
|
||||
SET_REG_FIELD(0x2AD, reg, 8, 8, mat_color.b);
|
||||
SET_REG_FIELD(0x2AE, reg, 8, 16, mat_color.g);
|
||||
SET_REG_FIELD(0x2AF, reg, 8, 24, mat_color.r);
|
||||
colIdx = 0;
|
||||
break;
|
||||
case GX_COLOR1A1:
|
||||
SET_REG_FIELD(0x2B4, reg, 8, 0, mat_color.a);
|
||||
SET_REG_FIELD(0x2B5, reg, 8, 8, mat_color.b);
|
||||
SET_REG_FIELD(0x2B6, reg, 8, 16, mat_color.g);
|
||||
SET_REG_FIELD(0x2B7, reg, 8, 24, mat_color.r);
|
||||
colIdx = 1;
|
||||
break;
|
||||
default:
|
||||
ASSERTMSGLINE(0x2BC, 0, "GXSetChanMatColor: Invalid Channel Id");
|
||||
return;
|
||||
}
|
||||
|
||||
GX_WRITE_XF_REG(colIdx + 12, reg);
|
||||
gx->bpSentNot = 1;
|
||||
gx->matColor[colIdx] = reg;
|
||||
}
|
||||
|
||||
void GXSetNumChans(u8 nChans)
|
||||
{
|
||||
CHECK_GXBEGIN(0x2D5, "GXSetNumChans");
|
||||
ASSERTMSGLINE(0x2D6, nChans <= 2, "GXSetNumChans: nChans > 2");
|
||||
|
||||
SET_REG_FIELD(0x2D8, gx->genMode, 3, 4, nChans);
|
||||
GX_WRITE_XF_REG(9, nChans);
|
||||
gx->dirtyState |= 4;
|
||||
}
|
||||
|
||||
void GXSetChanCtrl(GXChannelID chan, GXBool enable, GXColorSrc amb_src, GXColorSrc mat_src, u32 light_mask, GXDiffuseFn diff_fn, GXAttnFn attn_fn)
|
||||
{
|
||||
u32 reg; // r31
|
||||
u32 idx; // r26
|
||||
|
||||
CHECK_GXBEGIN(0x2F8, "GXSetChanCtrl");
|
||||
|
||||
ASSERTMSGLINE(0x2FB, chan >= 0 && chan <= 5, "GXSetChanCtrl: Invalid Channel Id");
|
||||
|
||||
if (chan == 4)
|
||||
idx = 0;
|
||||
else if (chan == 5)
|
||||
idx = 1;
|
||||
else
|
||||
idx = chan;
|
||||
|
||||
reg = 0;
|
||||
SET_REG_FIELD(0x302, reg, 1, 1, enable);
|
||||
SET_REG_FIELD(0x303, reg, 1, 0, mat_src);
|
||||
SET_REG_FIELD(0x304, reg, 1, 6, amb_src);
|
||||
SET_REG_FIELD(0x305, reg, 1, 2, (light_mask & GX_LIGHT0) != 0);
|
||||
SET_REG_FIELD(0x306, reg, 1, 3, (light_mask & GX_LIGHT1) != 0);
|
||||
SET_REG_FIELD(0x307, reg, 1, 4, (light_mask & GX_LIGHT2) != 0);
|
||||
SET_REG_FIELD(0x308, reg, 1, 5, (light_mask & GX_LIGHT3) != 0);
|
||||
SET_REG_FIELD(0x309, reg, 1, 11, (light_mask & GX_LIGHT4) != 0);
|
||||
SET_REG_FIELD(0x30A, reg, 1, 12, (light_mask & GX_LIGHT5) != 0);
|
||||
SET_REG_FIELD(0x30B, reg, 1, 13, (light_mask & GX_LIGHT6) != 0);
|
||||
SET_REG_FIELD(0x30C, reg, 1, 14, (light_mask & GX_LIGHT7) != 0);
|
||||
SET_REG_FIELD(0x30E, reg, 2, 7, (attn_fn == 0) ? 0 : diff_fn);
|
||||
SET_REG_FIELD(0x30F, reg, 1, 9, (attn_fn != 2));
|
||||
SET_REG_FIELD(0x310, reg, 1, 10, (attn_fn != 0));
|
||||
|
||||
GX_WRITE_XF_REG(idx + 14, reg);
|
||||
gx->bpSentNot = 1;
|
||||
if (chan == GX_COLOR0A0) {
|
||||
GX_WRITE_XF_REG(16, reg);
|
||||
}
|
||||
else if (chan == GX_COLOR1A1) {
|
||||
GX_WRITE_XF_REG(17, reg);
|
||||
}
|
||||
}
|
||||
485
src/dolphin/gx/GXMisc.c
Normal file
485
src/dolphin/gx/GXMisc.c
Normal file
|
|
@ -0,0 +1,485 @@
|
|||
#include <dolphin/PPCArch.h>
|
||||
#include <dolphin/gx.h>
|
||||
#include <dolphin/os.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
#include <dolphin/gx/GXPriv.h>
|
||||
|
||||
static GXDrawSyncCallback TokenCB;
|
||||
static GXDrawDoneCallback DrawDoneCB;
|
||||
static u8 DrawDone;
|
||||
static OSThreadQueue FinishQueue;
|
||||
|
||||
void GXSetMisc(GXMiscToken token, u32 val)
|
||||
{
|
||||
switch (token) {
|
||||
case GX_MT_XF_FLUSH:
|
||||
gx->vNum = val;
|
||||
gx->vNumNot = !gx->vNum;
|
||||
gx->bpSentNot = 1;
|
||||
if (gx->vNum != 0) {
|
||||
gx->dirtyState |= 8;
|
||||
}
|
||||
break;
|
||||
case GX_MT_DL_SAVE_CONTEXT:
|
||||
ASSERTMSGLINE(0xC4, !gx->inDispList, "GXSetMisc: Cannot change DL context setting while making a display list");
|
||||
gx->dlSaveContext = (val > 0);
|
||||
break;
|
||||
case GX_MT_NULL:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void GXFlush(void)
|
||||
{
|
||||
CHECK_GXBEGIN(0x10E, "GXFlush");
|
||||
if (gx->dirtyState) {
|
||||
__GXSetDirtyState();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
void GXResetWriteGatherPipe(void)
|
||||
{
|
||||
while (PPCMfwpar() & 1) { }
|
||||
PPCMtwpar(OSUncachedToPhysical((void *)GXFIFO_ADDR));
|
||||
}
|
||||
|
||||
static inline void __GXAbortWait(u32 clocks)
|
||||
{
|
||||
OSTime time0;
|
||||
OSTime time1;
|
||||
|
||||
time0 = OSGetTime();
|
||||
do {
|
||||
time1 = OSGetTime();
|
||||
} while (time1 - time0 <= (clocks / 4));
|
||||
}
|
||||
|
||||
void __GXAbortWaitPECopyDone(void)
|
||||
{
|
||||
__piReg[6] = 1;
|
||||
__GXAbortWait(0xC8U);
|
||||
__piReg[6] = 0;
|
||||
__GXAbortWait(0x14U);
|
||||
__GXCleanGPFifo();
|
||||
}
|
||||
|
||||
void GXSetDrawSync(u16 token)
|
||||
{
|
||||
BOOL enabled;
|
||||
u32 reg;
|
||||
|
||||
CHECK_GXBEGIN(0x162, "GXSetDrawSync");
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
reg = token | 0x48000000;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
SET_REG_FIELD(0x16F, reg, 16, 0, token);
|
||||
SET_REG_FIELD(0x170, reg, 8, 24, 0x47);
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
GXFlush();
|
||||
OSRestoreInterrupts(enabled);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
u16 GXReadDrawSync(void)
|
||||
{
|
||||
u16 token = __peReg[7];
|
||||
return token;
|
||||
}
|
||||
|
||||
void GXSetDrawDone(void)
|
||||
{
|
||||
u32 reg;
|
||||
BOOL enabled;
|
||||
|
||||
CHECK_GXBEGIN(0x19C, "GXSetDrawDone");
|
||||
enabled = OSDisableInterrupts();
|
||||
reg = 0x45000002;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
GXFlush();
|
||||
DrawDone = 0;
|
||||
OSRestoreInterrupts(enabled);
|
||||
}
|
||||
|
||||
void GXWaitDrawDone(void)
|
||||
{
|
||||
BOOL enabled;
|
||||
|
||||
CHECK_GXBEGIN(0x1CA, "GXWaitDrawDone");
|
||||
|
||||
enabled = OSDisableInterrupts();
|
||||
while (!DrawDone) {
|
||||
OSSleepThread(&FinishQueue);
|
||||
}
|
||||
OSRestoreInterrupts(enabled);
|
||||
}
|
||||
|
||||
void GXDrawDone(void)
|
||||
{
|
||||
CHECK_GXBEGIN(0x1EA, "GXDrawDone");
|
||||
GXSetDrawDone();
|
||||
GXWaitDrawDone();
|
||||
}
|
||||
|
||||
void GXPixModeSync(void)
|
||||
{
|
||||
CHECK_GXBEGIN(0x20D, "GXPixModeSync");
|
||||
GX_WRITE_RAS_REG(gx->peCtrl);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXTexModeSync(void)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
CHECK_GXBEGIN(0x225, "GXTexModeSync");
|
||||
reg = 0x63000000;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXPokeAlphaMode(GXCompare func, u8 threshold)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
CHECK_GXBEGIN(0x25F, "GXPokeAlphaMode");
|
||||
reg = (func << 8) | threshold;
|
||||
__peReg[3] = reg;
|
||||
}
|
||||
|
||||
void GXPokeAlphaRead(GXAlphaReadMode mode)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
CHECK_GXBEGIN(0x26A, "GXPokeAlphaRead");
|
||||
reg = 0;
|
||||
SET_REG_FIELD(0x26D, reg, 2, 0, mode);
|
||||
SET_REG_FIELD(0x26E, reg, 1, 2, 1);
|
||||
__peReg[4] = reg;
|
||||
}
|
||||
|
||||
void GXPokeAlphaUpdate(GXBool update_enable)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
CHECK_GXBEGIN(0x277, "GXPokeAlphaUpdate");
|
||||
reg = __peReg[1];
|
||||
SET_REG_FIELD(0x27A, reg, 1, 4, update_enable);
|
||||
__peReg[1] = reg;
|
||||
}
|
||||
|
||||
void GXPokeBlendMode(GXBlendMode type, GXBlendFactor src_factor, GXBlendFactor dst_factor, GXLogicOp op)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
CHECK_GXBEGIN(0x284, "GXPokeBlendUpdate");
|
||||
reg = __peReg[1];
|
||||
SET_REG_FIELD(0x28C, reg, 1, 0, (type == GX_BM_BLEND) || (type == GX_BM_SUBTRACT));
|
||||
SET_REG_FIELD(0x28D, reg, 1, 11, (type == GX_BM_SUBTRACT));
|
||||
SET_REG_FIELD(0x28F, reg, 1, 1, (type == GX_BM_LOGIC));
|
||||
SET_REG_FIELD(0x290, reg, 4, 12, op);
|
||||
SET_REG_FIELD(0x291, reg, 3, 8, src_factor);
|
||||
SET_REG_FIELD(0x292, reg, 3, 5, dst_factor);
|
||||
SET_REG_FIELD(0x293, reg, 8, 24, 0x41);
|
||||
__peReg[1] = reg;
|
||||
}
|
||||
|
||||
void GXPokeColorUpdate(GXBool update_enable)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
CHECK_GXBEGIN(0x29D, "GXPokeColorUpdate");
|
||||
reg = __peReg[1];
|
||||
SET_REG_FIELD(0x2A0, reg, 1, 3, update_enable);
|
||||
__peReg[1] = reg;
|
||||
}
|
||||
|
||||
void GXPokeDstAlpha(GXBool enable, u8 alpha)
|
||||
{
|
||||
u32 reg = 0;
|
||||
|
||||
CHECK_GXBEGIN(0x2A9, "GXPokeDstAlpha");
|
||||
SET_REG_FIELD(0x2AB, reg, 8, 0, alpha);
|
||||
SET_REG_FIELD(0x2AC, reg, 1, 8, enable);
|
||||
__peReg[2] = reg;
|
||||
}
|
||||
|
||||
void GXPokeDither(GXBool dither)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
CHECK_GXBEGIN(0x2B5, "GXPokeDither");
|
||||
reg = __peReg[1];
|
||||
SET_REG_FIELD(0x2B8, reg, 1, 2, dither);
|
||||
__peReg[1] = reg;
|
||||
}
|
||||
|
||||
void GXPokeZMode(GXBool compare_enable, GXCompare func, GXBool update_enable)
|
||||
{
|
||||
u32 reg = 0;
|
||||
|
||||
CHECK_GXBEGIN(0x2C1, "GXPokeZMode");
|
||||
|
||||
SET_REG_FIELD(0x2C3, reg, 1, 0, compare_enable);
|
||||
SET_REG_FIELD(0x2C4, reg, 3, 1, func);
|
||||
SET_REG_FIELD(0x2C5, reg, 1, 4, update_enable);
|
||||
__peReg[0] = reg;
|
||||
}
|
||||
|
||||
void GXPeekARGB(u16 x, u16 y, u32 *color)
|
||||
{
|
||||
u32 addr = (u32)OSPhysicalToUncached(0x08000000);
|
||||
|
||||
SET_REG_FIELD(0x2DC, addr, 10, 2, x);
|
||||
SET_REG_FIELD(0x2DD, addr, 10, 12, y);
|
||||
SET_REG_FIELD(0x2DE, addr, 2, 22, 0);
|
||||
*color = *(u32 *)addr;
|
||||
}
|
||||
|
||||
void GXPokeARGB(u16 x, u16 y, u32 color)
|
||||
{
|
||||
u32 addr = (u32)OSPhysicalToUncached(0x08000000);
|
||||
|
||||
SET_REG_FIELD(0x2E6, addr, 10, 2, x);
|
||||
SET_REG_FIELD(0x2E7, addr, 10, 12, y);
|
||||
SET_REG_FIELD(0x2E8, addr, 2, 22, 0);
|
||||
*(u32 *)addr = color;
|
||||
}
|
||||
|
||||
void GXPeekZ(u16 x, u16 y, u32 *z)
|
||||
{
|
||||
u32 addr = (u32)OSPhysicalToUncached(0x08000000);
|
||||
|
||||
SET_REG_FIELD(0x2F0, addr, 10, 2, x);
|
||||
SET_REG_FIELD(0x2F1, addr, 10, 12, y);
|
||||
SET_REG_FIELD(0x2F2, addr, 2, 22, 1);
|
||||
*z = *(u32 *)addr;
|
||||
}
|
||||
|
||||
void GXPokeZ(u16 x, u16 y, u32 z)
|
||||
{
|
||||
u32 addr = (u32)OSPhysicalToUncached(0x08000000);
|
||||
|
||||
SET_REG_FIELD(0x2FA, addr, 10, 2, x);
|
||||
SET_REG_FIELD(0x2FB, addr, 10, 12, y);
|
||||
SET_REG_FIELD(0x2FC, addr, 2, 22, 1);
|
||||
*(u32 *)addr = z;
|
||||
}
|
||||
|
||||
GXDrawSyncCallback GXSetDrawSyncCallback(GXDrawSyncCallback cb)
|
||||
{
|
||||
GXDrawSyncCallback oldcb;
|
||||
BOOL enabled;
|
||||
|
||||
oldcb = TokenCB;
|
||||
enabled = OSDisableInterrupts();
|
||||
TokenCB = cb;
|
||||
OSRestoreInterrupts(enabled);
|
||||
return oldcb;
|
||||
}
|
||||
|
||||
static void GXTokenInterruptHandler(__OSInterrupt interrupt, OSContext *context)
|
||||
{
|
||||
u16 token;
|
||||
OSContext exceptionContext;
|
||||
u32 reg;
|
||||
|
||||
token = __peReg[7];
|
||||
if (TokenCB != NULL) {
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(&exceptionContext);
|
||||
TokenCB(token);
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(context);
|
||||
}
|
||||
reg = __peReg[5];
|
||||
SET_REG_FIELD(0, reg, 1, 2, 1);
|
||||
__peReg[5] = reg;
|
||||
}
|
||||
|
||||
GXDrawDoneCallback GXSetDrawDoneCallback(GXDrawDoneCallback cb)
|
||||
{
|
||||
GXDrawDoneCallback oldcb;
|
||||
BOOL enabled;
|
||||
|
||||
oldcb = DrawDoneCB;
|
||||
enabled = OSDisableInterrupts();
|
||||
DrawDoneCB = cb;
|
||||
OSRestoreInterrupts(enabled);
|
||||
return oldcb;
|
||||
}
|
||||
|
||||
static void GXFinishInterruptHandler(__OSInterrupt interrupt, OSContext *context)
|
||||
{
|
||||
OSContext exceptionContext;
|
||||
u32 reg;
|
||||
|
||||
reg = __peReg[5];
|
||||
SET_REG_FIELD(0, reg, 1, 3, 1);
|
||||
__peReg[5] = reg;
|
||||
DrawDone = 1;
|
||||
if (DrawDoneCB != NULL) {
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(&exceptionContext);
|
||||
DrawDoneCB();
|
||||
OSClearContext(&exceptionContext);
|
||||
OSSetCurrentContext(context);
|
||||
}
|
||||
OSWakeupThread(&FinishQueue);
|
||||
}
|
||||
|
||||
void __GXPEInit(void)
|
||||
{
|
||||
u32 reg;
|
||||
__OSSetInterruptHandler(0x12, GXTokenInterruptHandler);
|
||||
__OSSetInterruptHandler(0x13, GXFinishInterruptHandler);
|
||||
OSInitThreadQueue(&FinishQueue);
|
||||
__OSUnmaskInterrupts(0x2000);
|
||||
__OSUnmaskInterrupts(0x1000);
|
||||
reg = __peReg[5];
|
||||
SET_REG_FIELD(0, reg, 1, 2, 1);
|
||||
SET_REG_FIELD(0, reg, 1, 3, 1);
|
||||
SET_REG_FIELD(0, reg, 1, 0, 1);
|
||||
SET_REG_FIELD(0, reg, 1, 1, 1);
|
||||
__peReg[5] = reg;
|
||||
}
|
||||
|
||||
u32 GXCompressZ16(u32 z24, GXZFmt16 zfmt)
|
||||
{
|
||||
u32 z16;
|
||||
u32 z24n;
|
||||
s32 exp;
|
||||
s32 shift;
|
||||
s32 temp;
|
||||
u8 unused[4];
|
||||
|
||||
z24n = ~(z24 << 8);
|
||||
temp = __cntlzw(z24n);
|
||||
switch (zfmt) {
|
||||
case GX_ZC_LINEAR:
|
||||
z16 = (z24 >> 8) & 0xFFFF;
|
||||
break;
|
||||
case GX_ZC_NEAR:
|
||||
if (temp > 3) {
|
||||
exp = 3;
|
||||
}
|
||||
else {
|
||||
exp = temp;
|
||||
}
|
||||
if (exp == 3) {
|
||||
shift = 7;
|
||||
}
|
||||
else {
|
||||
shift = 9 - exp;
|
||||
}
|
||||
z16 = ((z24 >> shift) & 0x3FFF & ~0xFFFFC000) | (exp << 14);
|
||||
break;
|
||||
case GX_ZC_MID:
|
||||
if (temp > 7) {
|
||||
exp = 7;
|
||||
}
|
||||
else {
|
||||
exp = temp;
|
||||
}
|
||||
if (exp == 7) {
|
||||
shift = 4;
|
||||
}
|
||||
else {
|
||||
shift = 10 - exp;
|
||||
}
|
||||
z16 = ((z24 >> shift) & 0x1FFF & ~0xFFFFE000) | (exp << 13);
|
||||
break;
|
||||
case GX_ZC_FAR:
|
||||
if (temp > 12) {
|
||||
exp = 12;
|
||||
}
|
||||
else {
|
||||
exp = temp;
|
||||
}
|
||||
if (exp == 12) {
|
||||
shift = 0;
|
||||
}
|
||||
else {
|
||||
shift = 11 - exp;
|
||||
}
|
||||
z16 = ((z24 >> shift) & 0xFFF & ~0xFFFFF000) | (exp << 12);
|
||||
break;
|
||||
default:
|
||||
OSPanic(__FILE__, 0x3B0, "GXCompressZ16: Invalid Z format\n");
|
||||
break;
|
||||
}
|
||||
return z16;
|
||||
}
|
||||
|
||||
u32 GXDecompressZ16(u32 z16, GXZFmt16 zfmt)
|
||||
{
|
||||
u32 z24;
|
||||
u32 cb1;
|
||||
long exp;
|
||||
long shift;
|
||||
|
||||
cb1;
|
||||
cb1;
|
||||
cb1;
|
||||
z16;
|
||||
z16;
|
||||
z16; // needed to match
|
||||
|
||||
switch (zfmt) {
|
||||
case GX_ZC_LINEAR:
|
||||
z24 = (z16 << 8) & 0xFFFF00;
|
||||
break;
|
||||
case GX_ZC_NEAR:
|
||||
exp = (z16 >> 14) & 3;
|
||||
if (exp == 3) {
|
||||
shift = 7;
|
||||
}
|
||||
else {
|
||||
shift = 9 - exp;
|
||||
}
|
||||
cb1 = -1 << (24 - exp);
|
||||
z24 = (cb1 | ((z16 & 0x3FFF) << shift)) & 0xFFFFFF;
|
||||
break;
|
||||
case GX_ZC_MID:
|
||||
exp = (z16 >> 13) & 7;
|
||||
if (exp == 7) {
|
||||
shift = 4;
|
||||
}
|
||||
else {
|
||||
shift = 10 - exp;
|
||||
}
|
||||
cb1 = -1 << (24 - exp);
|
||||
z24 = (cb1 | ((z16 & 0x1FFF) << shift)) & 0xFFFFFF;
|
||||
break;
|
||||
case GX_ZC_FAR:
|
||||
exp = (z16 >> 12) & 0xF;
|
||||
if (exp == 12) {
|
||||
shift = 0;
|
||||
}
|
||||
else {
|
||||
shift = 11 - exp;
|
||||
}
|
||||
cb1 = -1 << (24 - exp);
|
||||
z24 = (cb1 | ((z16 & 0xFFF) << shift)) & 0xFFFFFF;
|
||||
break;
|
||||
default:
|
||||
OSPanic(__FILE__, 0x3E2, "GXDecompressZ16: Invalid Z format\n");
|
||||
break;
|
||||
}
|
||||
return z24;
|
||||
}
|
||||
577
src/dolphin/gx/GXPerf.c
Normal file
577
src/dolphin/gx/GXPerf.c
Normal file
|
|
@ -0,0 +1,577 @@
|
|||
#include <dolphin/gx.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <dolphin/gx/GXPriv.h>
|
||||
|
||||
void GXSetGPMetric(GXPerf0 perf0, GXPerf1 perf1)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
CHECK_GXBEGIN(0x6A, "GXSetGPMetric");
|
||||
|
||||
switch (gx->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:
|
||||
reg = 0;
|
||||
GX_WRITE_XF_REG(6, reg);
|
||||
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:
|
||||
reg = 0x23000000;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
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:
|
||||
reg = 0x24000000;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_NONE:
|
||||
break;
|
||||
default:
|
||||
ASSERTMSGLINE(0xA6, 0, "GXSetGPMetric: Invalid GXPerf0 metric name");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (gx->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:
|
||||
reg = 0x67000000;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
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:
|
||||
SET_REG_FIELD(0, gx->perfSel, 4, 4, 0);
|
||||
GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12);
|
||||
break;
|
||||
case GX_PERF1_FIFO_REQ:
|
||||
case GX_PERF1_CALL_REQ:
|
||||
case GX_PERF1_VC_MISS_REQ:
|
||||
case GX_PERF1_CP_ALL_REQ:
|
||||
reg = 0;
|
||||
GX_SET_CP_REG(3, reg);
|
||||
break;
|
||||
case GX_PERF1_NONE:
|
||||
break;
|
||||
default:
|
||||
ASSERTMSGLINE(0xD8, 0, "GXSetGPMetric: Invalid GXPerf1 metric name");
|
||||
break;
|
||||
}
|
||||
|
||||
gx->perf0 = perf0;
|
||||
switch (gx->perf0) {
|
||||
case GX_PERF0_VERTICES:
|
||||
reg = 0x273;
|
||||
GX_WRITE_XF_REG(6, reg);
|
||||
break;
|
||||
case GX_PERF0_CLIP_VTX:
|
||||
reg = 0x14A;
|
||||
GX_WRITE_XF_REG(6, reg);
|
||||
break;
|
||||
case GX_PERF0_CLIP_CLKS:
|
||||
reg = 0x16B;
|
||||
GX_WRITE_XF_REG(6, reg);
|
||||
break;
|
||||
case GX_PERF0_XF_WAIT_IN:
|
||||
reg = 0x84;
|
||||
GX_WRITE_XF_REG(6, reg);
|
||||
break;
|
||||
case GX_PERF0_XF_WAIT_OUT:
|
||||
reg = 0xC6;
|
||||
GX_WRITE_XF_REG(6, reg);
|
||||
break;
|
||||
case GX_PERF0_XF_XFRM_CLKS:
|
||||
reg = 0x210;
|
||||
GX_WRITE_XF_REG(6, reg);
|
||||
break;
|
||||
case GX_PERF0_XF_LIT_CLKS:
|
||||
reg = 0x252;
|
||||
GX_WRITE_XF_REG(6, reg);
|
||||
break;
|
||||
case GX_PERF0_XF_BOT_CLKS:
|
||||
reg = 0x231;
|
||||
GX_WRITE_XF_REG(6, reg);
|
||||
break;
|
||||
case GX_PERF0_XF_REGLD_CLKS:
|
||||
reg = 0x1AD;
|
||||
GX_WRITE_XF_REG(6, reg);
|
||||
break;
|
||||
case GX_PERF0_XF_REGRD_CLKS:
|
||||
reg = 0x1CE;
|
||||
GX_WRITE_XF_REG(6, reg);
|
||||
break;
|
||||
case GX_PERF0_CLOCKS:
|
||||
reg = 0x21;
|
||||
GX_WRITE_XF_REG(6, reg);
|
||||
break;
|
||||
case GX_PERF0_CLIP_RATIO:
|
||||
reg = 0x153;
|
||||
GX_WRITE_XF_REG(6, reg);
|
||||
break;
|
||||
case GX_PERF0_TRIANGLES:
|
||||
reg = 0x2300AE7F;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_TRIANGLES_CULLED:
|
||||
reg = 0x23008E7F;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_TRIANGLES_PASSED:
|
||||
reg = 0x23009E7F;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_TRIANGLES_SCISSORED:
|
||||
reg = 0x23001E7F;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_TRIANGLES_0TEX:
|
||||
reg = 0x2300AC3F;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_TRIANGLES_1TEX:
|
||||
reg = 0x2300AC7F;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_TRIANGLES_2TEX:
|
||||
reg = 0x2300ACBF;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_TRIANGLES_3TEX:
|
||||
reg = 0x2300ACFF;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_TRIANGLES_4TEX:
|
||||
reg = 0x2300AD3F;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_TRIANGLES_5TEX:
|
||||
reg = 0x2300AD7F;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_TRIANGLES_6TEX:
|
||||
reg = 0x2300ADBF;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_TRIANGLES_7TEX:
|
||||
reg = 0x2300ADFF;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_TRIANGLES_8TEX:
|
||||
reg = 0x2300AE3F;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_TRIANGLES_0CLR:
|
||||
reg = 0x2300A27F;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_TRIANGLES_1CLR:
|
||||
reg = 0x2300A67F;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_TRIANGLES_2CLR:
|
||||
reg = 0x2300AA7F;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_QUAD_0CVG:
|
||||
reg = 0x2402C0C6;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_QUAD_NON0CVG:
|
||||
reg = 0x2402C16B;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_QUAD_1CVG:
|
||||
reg = 0x2402C0E7;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_QUAD_2CVG:
|
||||
reg = 0x2402C108;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_QUAD_3CVG:
|
||||
reg = 0x2402C129;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_QUAD_4CVG:
|
||||
reg = 0x2402C14A;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_AVG_QUAD_CNT:
|
||||
reg = 0x2402C1AD;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF0_NONE:
|
||||
break;
|
||||
default:
|
||||
ASSERTMSGLINE(0x1DA, 0, "GXSetGPMetric: Invalid GXPerf0 metric name");
|
||||
break;
|
||||
}
|
||||
|
||||
gx->perf1 = perf1;
|
||||
switch (gx->perf1) {
|
||||
case GX_PERF1_TEXELS:
|
||||
reg = 0x67000042;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF1_TX_IDLE:
|
||||
reg = 0x67000084;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF1_TX_REGS:
|
||||
reg = 0x67000063;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF1_TX_MEMSTALL:
|
||||
reg = 0x67000129;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF1_TC_MISS:
|
||||
reg = 0x67000252;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF1_CLOCKS:
|
||||
reg = 0x67000021;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF1_TC_CHECK1_2:
|
||||
reg = 0x6700014B;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF1_TC_CHECK3_4:
|
||||
reg = 0x6700018D;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF1_TC_CHECK5_6:
|
||||
reg = 0x670001CF;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF1_TC_CHECK7_8:
|
||||
reg = 0x67000211;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
break;
|
||||
case GX_PERF1_VC_ELEMQ_FULL:
|
||||
SET_REG_FIELD(0, gx->perfSel, 4, 4, 2);
|
||||
GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12);
|
||||
break;
|
||||
case GX_PERF1_VC_MISSQ_FULL:
|
||||
SET_REG_FIELD(0, gx->perfSel, 4, 4, 3);
|
||||
GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12);
|
||||
break;
|
||||
case GX_PERF1_VC_MEMREQ_FULL:
|
||||
SET_REG_FIELD(0, gx->perfSel, 4, 4, 4);
|
||||
GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12);
|
||||
break;
|
||||
case GX_PERF1_VC_STATUS7:
|
||||
SET_REG_FIELD(0, gx->perfSel, 4, 4, 5);
|
||||
GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12);
|
||||
break;
|
||||
case GX_PERF1_VC_MISSREP_FULL:
|
||||
SET_REG_FIELD(0, gx->perfSel, 4, 4, 6);
|
||||
GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12);
|
||||
break;
|
||||
case GX_PERF1_VC_STREAMBUF_LOW:
|
||||
SET_REG_FIELD(0, gx->perfSel, 4, 4, 7);
|
||||
GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12);
|
||||
break;
|
||||
case GX_PERF1_VC_ALL_STALLS:
|
||||
SET_REG_FIELD(0, gx->perfSel, 4, 4, 9);
|
||||
GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12);
|
||||
break;
|
||||
case GX_PERF1_VERTICES:
|
||||
SET_REG_FIELD(0, gx->perfSel, 4, 4, 8);
|
||||
GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12);
|
||||
break;
|
||||
case GX_PERF1_FIFO_REQ:
|
||||
reg = 2;
|
||||
GX_SET_CP_REG(3, reg);
|
||||
break;
|
||||
case GX_PERF1_CALL_REQ:
|
||||
reg = 3;
|
||||
GX_SET_CP_REG(3, reg);
|
||||
break;
|
||||
case GX_PERF1_VC_MISS_REQ:
|
||||
reg = 4;
|
||||
GX_SET_CP_REG(3, reg);
|
||||
break;
|
||||
case GX_PERF1_CP_ALL_REQ:
|
||||
reg = 5;
|
||||
GX_SET_CP_REG(3, reg);
|
||||
break;
|
||||
case GX_PERF1_NONE:
|
||||
break;
|
||||
default:
|
||||
ASSERTMSGLINE(0x26B, 0, "GXSetGPMetric: Invalid GXPerf1 metric name");
|
||||
break;
|
||||
}
|
||||
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
#pragma scheduling off
|
||||
void GXReadGPMetric(u32 *cnt0, u32 *cnt1)
|
||||
{
|
||||
u32 cpCtr0, cpCtr1, cpCtr2, cpCtr3;
|
||||
|
||||
ASSERTMSGLINE(0x286, !gx->inDispList, "GXReadGPMetric: don't use in a display list");
|
||||
|
||||
cpCtr0 = __GXReadCPCounterU32(32, 33);
|
||||
cpCtr1 = __GXReadCPCounterU32(34, 35);
|
||||
cpCtr2 = __GXReadCPCounterU32(36, 37);
|
||||
cpCtr3 = __GXReadCPCounterU32(38, 39);
|
||||
|
||||
switch (gx->perf0) {
|
||||
case GX_PERF0_CLIP_RATIO:
|
||||
*cnt0 = cpCtr1 * 0x3E8 / cpCtr0;
|
||||
break;
|
||||
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_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:
|
||||
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:
|
||||
case GX_PERF0_CLOCKS:
|
||||
*cnt0 = cpCtr0;
|
||||
break;
|
||||
case GX_PERF0_NONE:
|
||||
*cnt0 = 0;
|
||||
break;
|
||||
default:
|
||||
ASSERTMSGLINE(0x2CF, 0, "GXReadGPMetric: Invalid GXPerf0 metric name");
|
||||
*cnt0 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (gx->perf1) {
|
||||
case GX_PERF1_TEXELS:
|
||||
*cnt1 = cpCtr3 * 4;
|
||||
break;
|
||||
case GX_PERF1_TC_CHECK1_2:
|
||||
*cnt1 = cpCtr2 + (cpCtr3 * 2);
|
||||
break;
|
||||
case GX_PERF1_TC_CHECK3_4:
|
||||
*cnt1 = (cpCtr2 * 3) + (cpCtr3 * 4);
|
||||
break;
|
||||
case GX_PERF1_TC_CHECK5_6:
|
||||
*cnt1 = (cpCtr2 * 5) + (cpCtr3 * 6);
|
||||
break;
|
||||
case GX_PERF1_TC_CHECK7_8:
|
||||
*cnt1 = (cpCtr2 * 7) + (cpCtr3 * 8);
|
||||
break;
|
||||
case GX_PERF1_TX_IDLE:
|
||||
case GX_PERF1_TX_REGS:
|
||||
case GX_PERF1_TX_MEMSTALL:
|
||||
case GX_PERF1_TC_MISS:
|
||||
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:
|
||||
case GX_PERF1_CLOCKS:
|
||||
*cnt1 = cpCtr3;
|
||||
break;
|
||||
case GX_PERF1_FIFO_REQ:
|
||||
case GX_PERF1_CALL_REQ:
|
||||
case GX_PERF1_VC_MISS_REQ:
|
||||
case GX_PERF1_CP_ALL_REQ:
|
||||
*cnt1 = cpCtr2;
|
||||
break;
|
||||
case GX_PERF1_NONE:
|
||||
*cnt1 = 0;
|
||||
break;
|
||||
default:
|
||||
ASSERTMSGLINE(0x30A, 0, "GXReadGPMetric: Invalid GXPerf1 metric name");
|
||||
*cnt1 = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
#pragma scheduling reset
|
||||
|
||||
void GXClearGPMetric(void)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
ASSERTMSGLINE(0x322, !gx->inDispList, "GXClearGPMetric: don't use in a display list");
|
||||
reg = 4;
|
||||
__cpReg[2] = reg;
|
||||
}
|
||||
|
||||
u32 GXReadGP0Metric(void)
|
||||
{
|
||||
u32 cnt0, cnt1;
|
||||
|
||||
GXReadGPMetric(&cnt0, &cnt1);
|
||||
return cnt0;
|
||||
}
|
||||
|
||||
u32 GXReadGP1Metric(void)
|
||||
{
|
||||
u32 cnt0, cnt1;
|
||||
|
||||
GXReadGPMetric(&cnt0, &cnt1);
|
||||
return cnt1;
|
||||
}
|
||||
|
||||
#pragma scheduling off
|
||||
void GXReadMemMetric(
|
||||
u32 *cp_req, u32 *tc_req, u32 *cpu_rd_req, u32 *cpu_wr_req, u32 *dsp_req, u32 *io_req, u32 *vi_req, u32 *pe_req, u32 *rf_req, u32 *fi_req)
|
||||
{
|
||||
ASSERTMSGLINE(0x380, !gx->inDispList, "GXReadMemMetric: don't use in a display list");
|
||||
|
||||
*cp_req = __GXReadMEMCounterU32(26, 25);
|
||||
*tc_req = __GXReadMEMCounterU32(28, 27);
|
||||
*cpu_rd_req = __GXReadMEMCounterU32(30, 29);
|
||||
*cpu_wr_req = __GXReadMEMCounterU32(32, 31);
|
||||
*dsp_req = __GXReadMEMCounterU32(34, 33);
|
||||
*io_req = __GXReadMEMCounterU32(36, 35);
|
||||
*vi_req = __GXReadMEMCounterU32(38, 37);
|
||||
*pe_req = __GXReadMEMCounterU32(40, 39);
|
||||
*rf_req = __GXReadMEMCounterU32(42, 41);
|
||||
*fi_req = __GXReadMEMCounterU32(44, 43);
|
||||
}
|
||||
#pragma scheduling reset
|
||||
|
||||
void GXClearMemMetric(void)
|
||||
{
|
||||
ASSERTMSGLINE(0x3B9, !gx->inDispList, "GXClearMemMetric: don't use in a display list");
|
||||
|
||||
GX_SET_MEM_REG(25, 0);
|
||||
GX_SET_MEM_REG(26, 0);
|
||||
GX_SET_MEM_REG(27, 0);
|
||||
GX_SET_MEM_REG(28, 0);
|
||||
GX_SET_MEM_REG(30, 0);
|
||||
GX_SET_MEM_REG(29, 0);
|
||||
GX_SET_MEM_REG(32, 0);
|
||||
GX_SET_MEM_REG(31, 0);
|
||||
GX_SET_MEM_REG(34, 0);
|
||||
GX_SET_MEM_REG(33, 0);
|
||||
GX_SET_MEM_REG(36, 0);
|
||||
GX_SET_MEM_REG(35, 0);
|
||||
GX_SET_MEM_REG(38, 0);
|
||||
GX_SET_MEM_REG(37, 0);
|
||||
GX_SET_MEM_REG(40, 0);
|
||||
GX_SET_MEM_REG(39, 0);
|
||||
GX_SET_MEM_REG(42, 0);
|
||||
GX_SET_MEM_REG(41, 0);
|
||||
GX_SET_MEM_REG(44, 0);
|
||||
GX_SET_MEM_REG(43, 0);
|
||||
}
|
||||
|
||||
#pragma scheduling off
|
||||
void GXReadPixMetric(u32 *top_pixels_in, u32 *top_pixels_out, u32 *bot_pixels_in, u32 *bot_pixels_out, u32 *clr_pixels_in, u32 *copy_clks)
|
||||
{
|
||||
*top_pixels_in = __GXReadPECounterU32(12, 13) * 4;
|
||||
*top_pixels_out = __GXReadPECounterU32(14, 15) * 4;
|
||||
*bot_pixels_in = __GXReadPECounterU32(16, 17) * 4;
|
||||
*bot_pixels_out = __GXReadPECounterU32(18, 19) * 4;
|
||||
*clr_pixels_in = __GXReadPECounterU32(20, 21) * 4;
|
||||
*copy_clks = __GXReadPECounterU32(22, 23);
|
||||
}
|
||||
#pragma scheduling reset
|
||||
|
||||
void GXClearPixMetric(void)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
CHECK_GXBEGIN(0x48B, "GXClearPixMetric");
|
||||
reg = 0x57000000;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
reg = 0x57000AAA;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetVCacheMetric(GXVCachePerf attr)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
SET_REG_FIELD(0x43C, gx->perfSel, 4, 0, attr);
|
||||
GX_WRITE_SOME_REG4(8, 0x20, gx->perfSel, -12);
|
||||
reg = 1;
|
||||
GX_WRITE_SOME_REG4(8, 0x10, reg, -12);
|
||||
}
|
||||
|
||||
#pragma scheduling off
|
||||
void GXReadVCacheMetric(u32 *check, u32 *miss, u32 *stall)
|
||||
{
|
||||
*check = __GXReadCPCounterU32(40, 41);
|
||||
*miss = __GXReadCPCounterU32(42, 43);
|
||||
*stall = __GXReadCPCounterU32(44, 45);
|
||||
}
|
||||
#pragma scheduling on
|
||||
|
||||
void GXClearVCacheMetric(void)
|
||||
{
|
||||
GX_WRITE_SOME_REG4(8, 0, 0, -12);
|
||||
}
|
||||
290
src/dolphin/gx/GXPixel.c
Normal file
290
src/dolphin/gx/GXPixel.c
Normal file
|
|
@ -0,0 +1,290 @@
|
|||
#include <dolphin/gx.h>
|
||||
#include <dolphin/os.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <dolphin/gx/GXPriv.h>
|
||||
|
||||
void GXSetFog(GXFogType type, f32 startz, f32 endz, f32 nearz, f32 farz, GXColor color)
|
||||
{
|
||||
u32 fogclr;
|
||||
u32 fog0;
|
||||
u32 fog1;
|
||||
u32 fog2;
|
||||
u32 fog3;
|
||||
f32 A;
|
||||
f32 B;
|
||||
f32 B_mant;
|
||||
f32 C;
|
||||
f32 a;
|
||||
f32 c;
|
||||
u32 B_expn;
|
||||
u32 b_m;
|
||||
u32 b_s;
|
||||
u32 a_hex;
|
||||
u32 c_hex;
|
||||
|
||||
CHECK_GXBEGIN(0x8A, "GXSetFog");
|
||||
|
||||
ASSERTMSGLINE(0x8C, farz >= 0.0f, "GXSetFog: The farz should be positive value");
|
||||
ASSERTMSGLINE(0x8D, farz >= nearz, "GXSetFog: The farz should be larger than nearz");
|
||||
|
||||
if (farz == nearz || endz == startz) {
|
||||
A = 0.0f;
|
||||
B = 0.5f;
|
||||
C = 0.0f;
|
||||
}
|
||||
else {
|
||||
A = (farz * nearz) / ((farz - nearz) * (endz - startz));
|
||||
B = farz / (farz - nearz);
|
||||
C = startz / (endz - startz);
|
||||
}
|
||||
|
||||
B_mant = B;
|
||||
B_expn = 0;
|
||||
while (B_mant > 1.0) {
|
||||
B_mant *= 0.5f;
|
||||
B_expn++;
|
||||
}
|
||||
while (B_mant > 0.0f && B_mant < 0.5) {
|
||||
B_mant *= 2.0f;
|
||||
B_expn--;
|
||||
}
|
||||
|
||||
a = A / (f32)(1 << (B_expn + 1));
|
||||
b_m = 8.388638e6f * B_mant;
|
||||
b_s = B_expn + 1;
|
||||
c = C;
|
||||
|
||||
fog1 = 0;
|
||||
SET_REG_FIELD(0x94, fog1, 24, 0, b_m);
|
||||
SET_REG_FIELD(0x95, fog1, 8, 24, 0xEF);
|
||||
|
||||
fog2 = 0;
|
||||
SET_REG_FIELD(0x98, fog2, 5, 0, b_s);
|
||||
SET_REG_FIELD(0x99, fog2, 8, 24, 0xF0);
|
||||
|
||||
a_hex = *(u32 *)&a;
|
||||
c_hex = *(u32 *)&c;
|
||||
|
||||
fog0 = 0;
|
||||
SET_REG_FIELD(0xA0, fog0, 11, 0, (a_hex >> 12) & 0x7FF);
|
||||
SET_REG_FIELD(0xA1, fog0, 8, 11, (a_hex >> 23) & 0xFF);
|
||||
SET_REG_FIELD(0xA2, fog0, 1, 19, (a_hex >> 31));
|
||||
SET_REG_FIELD(0xA3, fog0, 8, 24, 0xEE);
|
||||
|
||||
fog3 = 0;
|
||||
SET_REG_FIELD(0xA6, fog3, 11, 0, (c_hex >> 12) & 0x7FF);
|
||||
SET_REG_FIELD(0xA7, fog3, 8, 11, (c_hex >> 23) & 0xFF);
|
||||
SET_REG_FIELD(0xA8, fog3, 1, 19, (c_hex >> 31));
|
||||
SET_REG_FIELD(0xA9, fog3, 1, 20, 0);
|
||||
SET_REG_FIELD(0xAA, fog3, 3, 21, type);
|
||||
SET_REG_FIELD(0xAB, fog3, 8, 24, 0xF1);
|
||||
|
||||
fogclr = 0;
|
||||
SET_REG_FIELD(0xAE, fogclr, 8, 0, color.b);
|
||||
SET_REG_FIELD(0xAF, fogclr, 8, 8, color.g);
|
||||
SET_REG_FIELD(0xB0, fogclr, 8, 16, color.r);
|
||||
SET_REG_FIELD(0xB1, fogclr, 8, 24, 0xF2);
|
||||
|
||||
GX_WRITE_RAS_REG(fog0);
|
||||
GX_WRITE_RAS_REG(fog1);
|
||||
GX_WRITE_RAS_REG(fog2);
|
||||
GX_WRITE_RAS_REG(fog3);
|
||||
GX_WRITE_RAS_REG(fogclr);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetFogColor(GXColor color)
|
||||
{
|
||||
unsigned long rgba;
|
||||
unsigned long fogclr = 0xF2000000;
|
||||
|
||||
rgba = *(u32 *)&color;
|
||||
SET_REG_FIELD(0xFA, fogclr, 24, 0, rgba >> 8);
|
||||
GX_WRITE_RAS_REG(fogclr);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXInitFogAdjTable(GXFogAdjTable *table, u16 width, const f32 projmtx[4][4])
|
||||
{
|
||||
f32 xi;
|
||||
f32 iw;
|
||||
f32 rangeVal;
|
||||
f32 nearZ;
|
||||
f32 sideX;
|
||||
u32 i;
|
||||
|
||||
CHECK_GXBEGIN(0x113, "GXInitFogAdjTable");
|
||||
ASSERTMSGLINE(0x114, table != NULL, "GXInitFogAdjTable: table pointer is null");
|
||||
ASSERTMSGLINE(0x115, width <= 640, "GXInitFogAdjTable: invalid width value");
|
||||
|
||||
if (0.0 == projmtx[3][3]) {
|
||||
nearZ = projmtx[2][3] / (projmtx[2][2] - 1.0f);
|
||||
sideX = nearZ / projmtx[0][0];
|
||||
}
|
||||
else {
|
||||
sideX = 1.0f / projmtx[0][0];
|
||||
nearZ = 1.73205f * sideX;
|
||||
}
|
||||
|
||||
iw = 2.0f / width;
|
||||
for (i = 0; i < 10; i++) {
|
||||
xi = (i + 1) << 5;
|
||||
xi *= iw;
|
||||
xi *= sideX;
|
||||
rangeVal = sqrtf(1.0f + ((xi * xi) / (nearZ * nearZ)));
|
||||
table->r[i] = (u32)(256.0f * rangeVal) & 0xFFF;
|
||||
}
|
||||
}
|
||||
|
||||
void GXSetFogRangeAdj(GXBool enable, u16 center, const GXFogAdjTable *table)
|
||||
{
|
||||
u32 i;
|
||||
u32 range_adj;
|
||||
u32 range_c;
|
||||
|
||||
CHECK_GXBEGIN(0x14B, "GXSetFogRangeAdj");
|
||||
|
||||
if (enable) {
|
||||
ASSERTMSGLINE(0x14E, table != NULL, "GXSetFogRangeAdj: table pointer is null");
|
||||
for (i = 0; i < 10; i += 2) {
|
||||
range_adj = 0;
|
||||
SET_REG_FIELD(0x152, range_adj, 12, 0, table->r[i]);
|
||||
SET_REG_FIELD(0x153, range_adj, 12, 12, table->r[i + 1]);
|
||||
SET_REG_FIELD(0x154, range_adj, 8, 24, (i >> 1) + 0xE9);
|
||||
GX_WRITE_RAS_REG(range_adj);
|
||||
}
|
||||
}
|
||||
range_c = 0;
|
||||
SET_REG_FIELD(0x15A, range_c, 10, 0, center + 342);
|
||||
SET_REG_FIELD(0x15B, range_c, 1, 10, enable);
|
||||
SET_REG_FIELD(0x15C, range_c, 8, 24, 0xE8);
|
||||
GX_WRITE_RAS_REG(range_c);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetBlendMode(GXBlendMode type, GXBlendFactor src_factor, GXBlendFactor dst_factor, GXLogicOp op)
|
||||
{
|
||||
CHECK_GXBEGIN(0x177, "GXSetBlendMode");
|
||||
|
||||
SET_REG_FIELD(0x135, gx->cmode0, 1, 0, (type == GX_BM_BLEND || type == GX_BM_SUBTRACT));
|
||||
SET_REG_FIELD(0x136, gx->cmode0, 1, 11, (type == GX_BM_SUBTRACT));
|
||||
SET_REG_FIELD(0x138, gx->cmode0, 1, 1, (type == GX_BM_LOGIC));
|
||||
SET_REG_FIELD(0x139, gx->cmode0, 4, 12, op);
|
||||
SET_REG_FIELD(0x13A, gx->cmode0, 3, 8, src_factor);
|
||||
SET_REG_FIELD(0x13B, gx->cmode0, 3, 5, dst_factor);
|
||||
SET_REG_FIELD(0x13C, gx->cmode0, 8, 24, 0x41);
|
||||
GX_WRITE_RAS_REG(gx->cmode0);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetColorUpdate(GXBool update_enable)
|
||||
{
|
||||
CHECK_GXBEGIN(0x1A3, "GXSetColorUpdate");
|
||||
|
||||
SET_REG_FIELD(0x150, gx->cmode0, 1, 3, update_enable);
|
||||
GX_WRITE_RAS_REG(gx->cmode0);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetAlphaUpdate(GXBool update_enable)
|
||||
{
|
||||
CHECK_GXBEGIN(0x1B0, "GXSetAlphaUpdate");
|
||||
|
||||
SET_REG_FIELD(0x159, gx->cmode0, 1, 4, update_enable);
|
||||
GX_WRITE_RAS_REG(gx->cmode0);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetZMode(GXBool compare_enable, GXCompare func, GXBool update_enable)
|
||||
{
|
||||
CHECK_GXBEGIN(0x1CB, "GXSetZMode");
|
||||
|
||||
SET_REG_FIELD(0x171, gx->zmode, 1, 0, compare_enable);
|
||||
SET_REG_FIELD(0x172, gx->zmode, 3, 1, func);
|
||||
SET_REG_FIELD(0x173, gx->zmode, 1, 4, update_enable);
|
||||
GX_WRITE_RAS_REG(gx->zmode);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetZCompLoc(GXBool before_tex)
|
||||
{
|
||||
CHECK_GXBEGIN(0x1DA, "GXSetZCompLoc");
|
||||
|
||||
SET_REG_FIELD(0x1DB, gx->peCtrl, 1, 6, before_tex);
|
||||
GX_WRITE_RAS_REG(gx->peCtrl);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetPixelFmt(GXPixelFmt pix_fmt, GXZFmt16 z_fmt)
|
||||
{
|
||||
u32 oldPeCtrl;
|
||||
u8 aa;
|
||||
static u32 p2f[8] = { 0, 1, 2, 3, 4, 4, 4, 5 };
|
||||
|
||||
CHECK_GXBEGIN(0x1FF, "GXSetPixelFmt");
|
||||
oldPeCtrl = gx->peCtrl;
|
||||
ASSERTMSGLINE(0x203, pix_fmt >= 0 && pix_fmt <= 7, "Invalid Pixel format");
|
||||
SET_REG_FIELD(0x205, gx->peCtrl, 3, 0, p2f[pix_fmt]);
|
||||
SET_REG_FIELD(0x206, gx->peCtrl, 3, 3, z_fmt);
|
||||
if (oldPeCtrl != gx->peCtrl) {
|
||||
GX_WRITE_RAS_REG(gx->peCtrl);
|
||||
if (pix_fmt == GX_PF_RGB565_Z16)
|
||||
aa = 1;
|
||||
else
|
||||
aa = 0;
|
||||
SET_REG_FIELD(0x20F, gx->genMode, 1, 9, aa);
|
||||
gx->dirtyState |= 4;
|
||||
}
|
||||
if (p2f[pix_fmt] == 4) {
|
||||
SET_REG_FIELD(0x216, gx->cmode1, 2, 9, (pix_fmt - 4) & 0x3);
|
||||
SET_REG_FIELD(0x216, gx->cmode1, 8, 24, 0x42);
|
||||
GX_WRITE_RAS_REG(gx->cmode1);
|
||||
}
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetDither(GXBool dither)
|
||||
{
|
||||
CHECK_GXBEGIN(0x22C, "GXSetDither");
|
||||
|
||||
SET_REG_FIELD(0x1CE, gx->cmode0, 1, 2, dither);
|
||||
GX_WRITE_RAS_REG(gx->cmode0);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetDstAlpha(GXBool enable, u8 alpha)
|
||||
{
|
||||
CHECK_GXBEGIN(0x245, "GXSetDstAlpha");
|
||||
|
||||
SET_REG_FIELD(0x1E2, gx->cmode1, 8, 0, alpha);
|
||||
SET_REG_FIELD(0x1E3, gx->cmode1, 1, 8, enable);
|
||||
GX_WRITE_RAS_REG(gx->cmode1);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetFieldMask(GXBool odd_mask, GXBool even_mask)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
CHECK_GXBEGIN(0x260, "GXSetFieldMask");
|
||||
reg = 0;
|
||||
SET_REG_FIELD(0x262, reg, 1, 0, even_mask);
|
||||
SET_REG_FIELD(0x263, reg, 1, 1, odd_mask);
|
||||
SET_REG_FIELD(0x263, reg, 8, 24, 0x44);
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetFieldMode(GXBool field_mode, GXBool half_aspect_ratio)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
CHECK_GXBEGIN(0x27D, "GXSetFieldMode");
|
||||
SET_REG_FIELD(0x281, gx->lpSize, 1, 22, half_aspect_ratio);
|
||||
GX_WRITE_RAS_REG(gx->lpSize);
|
||||
__GXFlushTextureState();
|
||||
reg = field_mode | 0x68000000;
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
__GXFlushTextureState();
|
||||
}
|
||||
5
src/dolphin/gx/GXStubs.c
Normal file
5
src/dolphin/gx/GXStubs.c
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#include <dolphin/gx.h>
|
||||
|
||||
#include <dolphin/gx/GXPriv.h>
|
||||
|
||||
void __GXSetRange(float nearz, float fgSideX) {}
|
||||
403
src/dolphin/gx/GXTev.c
Normal file
403
src/dolphin/gx/GXTev.c
Normal file
|
|
@ -0,0 +1,403 @@
|
|||
#include <dolphin/gx.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <dolphin/gx/GXPriv.h>
|
||||
|
||||
void GXSetTevOp(GXTevStageID id, GXTevMode mode)
|
||||
{
|
||||
GXTevColorArg carg = GX_CC_RASC;
|
||||
GXTevAlphaArg aarg = GX_CA_RASA;
|
||||
|
||||
CHECK_GXBEGIN(0x1A4, "GXSetTevOp");
|
||||
ASSERTMSGLINE(0x1A5, id < 16, "GXSetTevColor*: Invalid Tev Stage Index");
|
||||
ASSERTMSGLINE(0x1A6, mode <= 4, "GXSetTevOp: Invalid Tev Mode");
|
||||
|
||||
if (id != GX_TEVSTAGE0) {
|
||||
carg = GX_CC_CPREV;
|
||||
aarg = GX_CA_APREV;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case GX_MODULATE:
|
||||
GXSetTevColorIn(id, GX_CC_ZERO, GX_CC_TEXC, carg, GX_CC_ZERO);
|
||||
GXSetTevAlphaIn(id, GX_CA_ZERO, GX_CA_TEXA, aarg, GX_CA_ZERO);
|
||||
break;
|
||||
case GX_DECAL:
|
||||
GXSetTevColorIn(id, carg, GX_CC_TEXC, GX_CC_TEXA, GX_CC_ZERO);
|
||||
GXSetTevAlphaIn(id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, aarg);
|
||||
break;
|
||||
case GX_BLEND:
|
||||
GXSetTevColorIn(id, carg, GX_CC_ONE, GX_CC_TEXC, GX_CC_ZERO);
|
||||
GXSetTevAlphaIn(id, GX_CA_ZERO, GX_CA_TEXA, aarg, GX_CA_ZERO);
|
||||
break;
|
||||
case GX_REPLACE:
|
||||
GXSetTevColorIn(id, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC);
|
||||
GXSetTevAlphaIn(id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA);
|
||||
break;
|
||||
case GX_PASSCLR:
|
||||
GXSetTevColorIn(id, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, carg);
|
||||
GXSetTevAlphaIn(id, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, aarg);
|
||||
break;
|
||||
}
|
||||
GXSetTevColorOp(id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
|
||||
GXSetTevAlphaOp(id, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
|
||||
}
|
||||
|
||||
void GXSetTevColorIn(GXTevStageID stage, GXTevColorArg a, GXTevColorArg b, GXTevColorArg c, GXTevColorArg d)
|
||||
{
|
||||
u32 *pTevReg;
|
||||
|
||||
CHECK_GXBEGIN(0x242, "GXSetTevColorIn");
|
||||
ASSERTMSGLINE(0x243, stage < 16, "GXSetTevColor*: Invalid Tev Stage Index");
|
||||
ASSERTMSGLINE(0x244, a <= 15, "GXSetTev*In: A/B/C/D argument out of range");
|
||||
ASSERTMSGLINE(0x245, b <= 15, "GXSetTev*In: A/B/C/D argument out of range");
|
||||
ASSERTMSGLINE(0x246, c <= 15, "GXSetTev*In: A/B/C/D argument out of range");
|
||||
ASSERTMSGLINE(0x247, d <= 15, "GXSetTev*In: A/B/C/D argument out of range");
|
||||
|
||||
pTevReg = &gx->tevc[stage];
|
||||
SET_REG_FIELD(0xED, *pTevReg, 4, 12, a);
|
||||
SET_REG_FIELD(0xEE, *pTevReg, 4, 8, b);
|
||||
SET_REG_FIELD(0xEF, *pTevReg, 4, 4, c);
|
||||
SET_REG_FIELD(0xF0, *pTevReg, 4, 0, d);
|
||||
|
||||
GX_WRITE_RAS_REG(*pTevReg);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetTevAlphaIn(GXTevStageID stage, GXTevAlphaArg a, GXTevAlphaArg b, GXTevAlphaArg c, GXTevAlphaArg d)
|
||||
{
|
||||
u32 *pTevReg;
|
||||
|
||||
CHECK_GXBEGIN(0x266, "GXSetTevAlphaIn");
|
||||
ASSERTMSGLINE(0x267, stage < 16, "GXSetTevAlpha*: Invalid Tev Stage Index");
|
||||
ASSERTMSGLINE(0x268, a <= 7, "GXSetTev*In: A/B/C/D argument out of range");
|
||||
ASSERTMSGLINE(0x269, b <= 7, "GXSetTev*In: A/B/C/D argument out of range");
|
||||
ASSERTMSGLINE(0x26A, c <= 7, "GXSetTev*In: A/B/C/D argument out of range");
|
||||
ASSERTMSGLINE(0x26B, d <= 7, "GXSetTev*In: A/B/C/D argument out of range");
|
||||
|
||||
pTevReg = &gx->teva[stage];
|
||||
SET_REG_FIELD(0x110, *pTevReg, 3, 13, a);
|
||||
SET_REG_FIELD(0x111, *pTevReg, 3, 10, b);
|
||||
SET_REG_FIELD(0x112, *pTevReg, 3, 7, c);
|
||||
SET_REG_FIELD(0x113, *pTevReg, 3, 4, d);
|
||||
|
||||
GX_WRITE_RAS_REG(*pTevReg);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetTevColorOp(GXTevStageID stage, GXTevOp op, GXTevBias bias, GXTevScale scale, GXBool clamp, GXTevRegID out_reg)
|
||||
{
|
||||
u32 *pTevReg;
|
||||
|
||||
CHECK_GXBEGIN(0x28D, "GXSetTevColorOp");
|
||||
ASSERTMSGLINE(0x28E, stage < 16, "GXSetTevColor*: Invalid Tev Stage Index");
|
||||
|
||||
pTevReg = &gx->tevc[stage];
|
||||
SET_REG_FIELD(0x137, *pTevReg, 1, 18, op & 1);
|
||||
if (op <= 1) {
|
||||
SET_REG_FIELD(0x139, *pTevReg, 2, 20, scale);
|
||||
SET_REG_FIELD(0x13A, *pTevReg, 2, 16, bias);
|
||||
}
|
||||
else {
|
||||
SET_REG_FIELD(0x13C, *pTevReg, 2, 20, (op >> 1) & 3);
|
||||
SET_REG_FIELD(0x13D, *pTevReg, 2, 16, 3);
|
||||
}
|
||||
SET_REG_FIELD(0x140, *pTevReg, 1, 19, clamp & 0xFF);
|
||||
SET_REG_FIELD(0x141, *pTevReg, 2, 22, out_reg);
|
||||
|
||||
GX_WRITE_RAS_REG(*pTevReg);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetTevAlphaOp(GXTevStageID stage, GXTevOp op, GXTevBias bias, GXTevScale scale, GXBool clamp, GXTevRegID out_reg)
|
||||
{
|
||||
u32 *pTevReg;
|
||||
|
||||
CHECK_GXBEGIN(0x2BB, "GXSetTevAlphaOp");
|
||||
ASSERTMSGLINE(0x2BC, stage < 16, "GXSetTevAlpha*: Invalid Tev Stage Index");
|
||||
|
||||
pTevReg = &gx->teva[stage];
|
||||
SET_REG_FIELD(0x163, *pTevReg, 1, 18, op & 1);
|
||||
if (op <= 1) {
|
||||
SET_REG_FIELD(0x165, *pTevReg, 2, 20, scale);
|
||||
SET_REG_FIELD(0x166, *pTevReg, 2, 16, bias);
|
||||
}
|
||||
else {
|
||||
SET_REG_FIELD(0x168, *pTevReg, 2, 20, (op >> 1) & 3);
|
||||
SET_REG_FIELD(0x169, *pTevReg, 2, 16, 3);
|
||||
}
|
||||
SET_REG_FIELD(0x16C, *pTevReg, 1, 19, clamp & 0xFF);
|
||||
SET_REG_FIELD(0x16D, *pTevReg, 2, 22, out_reg);
|
||||
|
||||
GX_WRITE_RAS_REG(*pTevReg);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetTevColor(GXTevRegID id, GXColor color)
|
||||
{
|
||||
u32 regRA;
|
||||
u32 regBG;
|
||||
|
||||
CHECK_GXBEGIN(0x2E4, "GXSetTevColor");
|
||||
regRA = 0;
|
||||
SET_REG_FIELD(0x185, regRA, 11, 0, color.r);
|
||||
SET_REG_FIELD(0x186, regRA, 11, 12, color.a);
|
||||
SET_REG_FIELD(0x187, regRA, 8, 24, 224 + id * 2);
|
||||
|
||||
regBG = 0;
|
||||
SET_REG_FIELD(0x18A, regBG, 11, 0, color.b);
|
||||
SET_REG_FIELD(0x18B, regBG, 11, 12, color.g);
|
||||
SET_REG_FIELD(0x18C, regBG, 8, 24, 225 + id * 2);
|
||||
|
||||
GX_WRITE_RAS_REG(regRA);
|
||||
GX_WRITE_RAS_REG(regBG);
|
||||
GX_WRITE_RAS_REG(regBG);
|
||||
GX_WRITE_RAS_REG(regBG);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetTevColorS10(GXTevRegID id, GXColorS10 color)
|
||||
{
|
||||
u32 regRA;
|
||||
u32 regBG;
|
||||
|
||||
ASSERTMSGLINE(0x309, color.r >= -1024 && color.r < 1024, "GXSetTevColorS10: Color not in range -1024 to +1023");
|
||||
ASSERTMSGLINE(0x30A, color.g >= -1024 && color.g < 1024, "GXSetTevColorS10: Color not in range -1024 to +1023");
|
||||
ASSERTMSGLINE(0x30B, color.b >= -1024 && color.b < 1024, "GXSetTevColorS10: Color not in range -1024 to +1023");
|
||||
ASSERTMSGLINE(0x30C, color.a >= -1024 && color.a < 1024, "GXSetTevColorS10: Color not in range -1024 to +1023");
|
||||
|
||||
CHECK_GXBEGIN(0x30E, "GXSetTevColorS10");
|
||||
regRA = 0;
|
||||
SET_REG_FIELD(0x1AF, regRA, 11, 0, color.r & 0x7FF);
|
||||
SET_REG_FIELD(0x1B0, regRA, 11, 12, color.a & 0x7FF);
|
||||
SET_REG_FIELD(0x1B1, regRA, 8, 24, 224 + id * 2);
|
||||
|
||||
regBG = 0;
|
||||
SET_REG_FIELD(0x1B4, regBG, 11, 0, color.b & 0x7FF);
|
||||
SET_REG_FIELD(0x1B5, regBG, 11, 12, color.g & 0x7FF);
|
||||
SET_REG_FIELD(0x1B6, regBG, 8, 24, 225 + id * 2);
|
||||
|
||||
GX_WRITE_RAS_REG(regRA);
|
||||
GX_WRITE_RAS_REG(regBG);
|
||||
GX_WRITE_RAS_REG(regBG);
|
||||
GX_WRITE_RAS_REG(regBG);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetTevKColor(GXTevKColorID id, GXColor color)
|
||||
{
|
||||
u32 regRA;
|
||||
u32 regBG;
|
||||
|
||||
CHECK_GXBEGIN(0x341, "GXSetTevKColor");
|
||||
regRA = 0;
|
||||
SET_REG_FIELD(0x1E0, regRA, 8, 0, color.r);
|
||||
SET_REG_FIELD(0x1E1, regRA, 8, 12, color.a);
|
||||
SET_REG_FIELD(0x1E2, regRA, 4, 20, 8);
|
||||
SET_REG_FIELD(0x1E3, regRA, 8, 24, 224 + id * 2);
|
||||
|
||||
regBG = 0;
|
||||
SET_REG_FIELD(0x1E6, regBG, 8, 0, color.b);
|
||||
SET_REG_FIELD(0x1E7, regBG, 8, 12, color.g);
|
||||
SET_REG_FIELD(0x1E8, regBG, 4, 20, 8);
|
||||
SET_REG_FIELD(0x1E9, regBG, 8, 24, 225 + id * 2);
|
||||
|
||||
GX_WRITE_RAS_REG(regRA);
|
||||
GX_WRITE_RAS_REG(regBG);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetTevKColorSel(GXTevStageID stage, GXTevKColorSel sel)
|
||||
{
|
||||
u32 *Kreg;
|
||||
|
||||
CHECK_GXBEGIN(0x368, "GXSetTevKColorSel");
|
||||
ASSERTMSGLINE(0x369, stage < 16, "GXSetTevKColor*: Invalid Tev Stage Index");
|
||||
|
||||
Kreg = &gx->tevKsel[stage >> 1];
|
||||
if (stage & 1) {
|
||||
SET_REG_FIELD(0x20A, *Kreg, 5, 14, sel);
|
||||
}
|
||||
else {
|
||||
SET_REG_FIELD(0x20C, *Kreg, 5, 4, sel);
|
||||
}
|
||||
|
||||
GX_WRITE_RAS_REG(*Kreg);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetTevKAlphaSel(GXTevStageID stage, GXTevKAlphaSel sel)
|
||||
{
|
||||
u32 *Kreg;
|
||||
|
||||
CHECK_GXBEGIN(0x389, "GXSetTevKAlphaSel");
|
||||
ASSERTMSGLINE(0x38A, stage < 16, "GXSetTevKColor*: Invalid Tev Stage Index");
|
||||
|
||||
Kreg = &gx->tevKsel[stage >> 1];
|
||||
if (stage & 1) {
|
||||
SET_REG_FIELD(0x22B, *Kreg, 5, 19, sel);
|
||||
}
|
||||
else {
|
||||
SET_REG_FIELD(0x22D, *Kreg, 5, 9, sel);
|
||||
}
|
||||
|
||||
GX_WRITE_RAS_REG(*Kreg);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetTevSwapMode(GXTevStageID stage, GXTevSwapSel ras_sel, GXTevSwapSel tex_sel)
|
||||
{
|
||||
u32 *pTevReg;
|
||||
|
||||
CHECK_GXBEGIN(0x3AE, "GXSetTevSwapMode");
|
||||
ASSERTMSGLINE(0x3AF, stage < 16, "GXSetTevSwapMode: Invalid Tev Stage Index");
|
||||
|
||||
pTevReg = &gx->teva[stage];
|
||||
SET_REG_FIELD(0x24E, *pTevReg, 2, 0, ras_sel);
|
||||
SET_REG_FIELD(0x24F, *pTevReg, 2, 2, tex_sel);
|
||||
|
||||
GX_WRITE_RAS_REG(*pTevReg);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetTevSwapModeTable(GXTevSwapSel table, GXTevColorChan red, GXTevColorChan green, GXTevColorChan blue, GXTevColorChan alpha)
|
||||
{
|
||||
u32 *Kreg;
|
||||
#if !DEBUG
|
||||
// not a real variable, but needed to match release
|
||||
int index = table * 2;
|
||||
#endif
|
||||
|
||||
CHECK_GXBEGIN(0x3D2, "GXSetTevSwapModeTable");
|
||||
ASSERTMSGLINE(0x3D3, table < 4, "GXSetTevSwapModeTable: Invalid Swap Selection Index");
|
||||
|
||||
#if DEBUG
|
||||
Kreg = &gx->tevKsel[table * 2];
|
||||
#else
|
||||
Kreg = &gx->tevKsel[index];
|
||||
#endif
|
||||
SET_REG_FIELD(0x272, *Kreg, 2, 0, red);
|
||||
SET_REG_FIELD(0x273, *Kreg, 2, 2, green);
|
||||
|
||||
GX_WRITE_RAS_REG(*Kreg);
|
||||
|
||||
Kreg = &gx->tevKsel[table * 2 + 1];
|
||||
SET_REG_FIELD(0x277, *Kreg, 2, 0, blue);
|
||||
SET_REG_FIELD(0x278, *Kreg, 2, 2, alpha);
|
||||
|
||||
GX_WRITE_RAS_REG(*Kreg);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetTevClampMode(void)
|
||||
{
|
||||
ASSERTMSGLINE(0x3F4, 0, "GXSetTevClampMode: not available on this hardware");
|
||||
}
|
||||
|
||||
void GXSetAlphaCompare(GXCompare comp0, u8 ref0, GXAlphaOp op, GXCompare comp1, u8 ref1)
|
||||
{
|
||||
u32 reg = 0;
|
||||
|
||||
CHECK_GXBEGIN(0x416, "GXSetAlphaCompare");
|
||||
SET_REG_FIELD(0x2B4, reg, 8, 0, ref0);
|
||||
SET_REG_FIELD(0x2B5, reg, 8, 8, ref1);
|
||||
SET_REG_FIELD(0x2B6, reg, 3, 16, comp0);
|
||||
SET_REG_FIELD(0x2B7, reg, 3, 19, comp1);
|
||||
SET_REG_FIELD(0x2B8, reg, 2, 22, op);
|
||||
SET_REG_FIELD(0x2B9, reg, 8, 24, 0xF3);
|
||||
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetZTexture(GXZTexOp op, GXTexFmt fmt, u32 bias)
|
||||
{
|
||||
u32 zenv0;
|
||||
u32 zenv1;
|
||||
u32 type;
|
||||
|
||||
CHECK_GXBEGIN(0x435, "GXSetZTexture");
|
||||
|
||||
zenv0 = 0;
|
||||
SET_REG_FIELD(0x2D4, zenv0, 24, 0, bias);
|
||||
SET_REG_FIELD(0x2D5, zenv0, 8, 24, 0xF4);
|
||||
|
||||
zenv1 = 0;
|
||||
switch (fmt) {
|
||||
case GX_TF_Z8:
|
||||
type = 0;
|
||||
break;
|
||||
case GX_TF_Z16:
|
||||
type = 1;
|
||||
break;
|
||||
case GX_TF_Z24X8:
|
||||
type = 2;
|
||||
break;
|
||||
default:
|
||||
ASSERTMSGLINE(0x441, 0, "GXSetZTexture: Invalid z-texture format");
|
||||
type = 2;
|
||||
break;
|
||||
}
|
||||
SET_REG_FIELD(0x2E0, zenv1, 2, 0, type);
|
||||
SET_REG_FIELD(0x2E1, zenv1, 2, 2, op);
|
||||
SET_REG_FIELD(0x2E2, zenv1, 8, 24, 0xF5);
|
||||
|
||||
GX_WRITE_RAS_REG(zenv0);
|
||||
GX_WRITE_RAS_REG(zenv1);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetTevOrder(GXTevStageID stage, GXTexCoordID coord, GXTexMapID map, GXChannelID color)
|
||||
{
|
||||
u32 *ptref;
|
||||
u32 tmap;
|
||||
u32 tcoord;
|
||||
static int c2r[] = { 0, 1, 0, 1, 0, 1, 7, 5, 6 };
|
||||
|
||||
CHECK_GXBEGIN(0x46B, "GXSetTevOrder");
|
||||
ASSERTMSGLINE(0x46C, stage < 16, "GXSetTevOrder: Invalid Tev Stage Index");
|
||||
ASSERTMSGLINE(0x46E, coord < 8 || coord == 0xFF, "GXSetTevOrder: Invalid Texcoord");
|
||||
ASSERTMSGLINE(0x470, (map & ~0x100) < 8 || map == 0xFF, "GXSetTevOrder: Invalid Tex Map");
|
||||
ASSERTMSGLINE(0x472, color >= 4 && color <= 0xFF, "GXSetTevOrder: Invalid Color Channel ID");
|
||||
|
||||
ptref = &gx->tref[stage / 2];
|
||||
gx->texmapId[stage] = map;
|
||||
|
||||
tmap = map & ~0x100;
|
||||
tmap = (tmap >= GX_MAX_TEXMAP) ? GX_TEXMAP0 : tmap;
|
||||
|
||||
if (coord >= GX_MAX_TEXCOORD) {
|
||||
tcoord = GX_TEXCOORD0;
|
||||
gx->tevTcEnab = gx->tevTcEnab & ~(1 << stage);
|
||||
}
|
||||
else {
|
||||
tcoord = coord;
|
||||
gx->tevTcEnab = gx->tevTcEnab | (1 << stage);
|
||||
}
|
||||
|
||||
if (stage & 1) {
|
||||
SET_REG_FIELD(0x486, *ptref, 3, 12, tmap);
|
||||
SET_REG_FIELD(0x487, *ptref, 3, 15, tcoord);
|
||||
SET_REG_FIELD(0x489, *ptref, 3, 19, (color == GX_COLOR_NULL) ? 7 : c2r[color]);
|
||||
SET_REG_FIELD(0x48B, *ptref, 1, 18, (map != GX_TEXMAP_NULL && !(map & 0x100)));
|
||||
}
|
||||
else {
|
||||
SET_REG_FIELD(0x48E, *ptref, 3, 0, tmap);
|
||||
SET_REG_FIELD(0x48F, *ptref, 3, 3, tcoord);
|
||||
SET_REG_FIELD(0x491, *ptref, 3, 7, (color == GX_COLOR_NULL) ? 7 : c2r[color]);
|
||||
SET_REG_FIELD(0x493, *ptref, 1, 6, (map != GX_TEXMAP_NULL && !(map & 0x100)));
|
||||
}
|
||||
|
||||
GX_WRITE_RAS_REG(*ptref);
|
||||
gx->bpSentNot = 0;
|
||||
gx->dirtyState |= 1;
|
||||
}
|
||||
|
||||
void GXSetNumTevStages(u8 nStages)
|
||||
{
|
||||
CHECK_GXBEGIN(0x4A3, "GXSetNumTevStages");
|
||||
|
||||
ASSERTMSGLINE(0x4A5, nStages != 0 && nStages <= 16, "GXSetNumTevStages: Exceed max number of tex stages");
|
||||
SET_REG_FIELD(0x334, gx->genMode, 4, 10, nStages - 1);
|
||||
gx->dirtyState |= 4;
|
||||
}
|
||||
1269
src/dolphin/gx/GXTexture.c
Normal file
1269
src/dolphin/gx/GXTexture.c
Normal file
File diff suppressed because it is too large
Load diff
372
src/dolphin/gx/GXTransform.c
Normal file
372
src/dolphin/gx/GXTransform.c
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
#include <dolphin/gx.h>
|
||||
#include <dolphin/mtx.h>
|
||||
#include <dolphin/os.h>
|
||||
|
||||
#include <dolphin/gx/GXPriv.h>
|
||||
|
||||
void GXProject(f32 x, f32 y, f32 z, const f32 mtx[3][4], const f32 *pm, const f32 *vp, f32 *sx, f32 *sy, f32 *sz)
|
||||
{
|
||||
Vec peye;
|
||||
f32 xc;
|
||||
f32 yc;
|
||||
f32 zc;
|
||||
f32 wc;
|
||||
|
||||
ASSERTMSGLINE(0xA8, pm && vp && sx && sy && sz, "GXGet*: invalid null pointer");
|
||||
|
||||
peye.x = mtx[0][3] + ((mtx[0][2] * z) + ((mtx[0][0] * x) + (mtx[0][1] * y)));
|
||||
peye.y = mtx[1][3] + ((mtx[1][2] * z) + ((mtx[1][0] * x) + (mtx[1][1] * y)));
|
||||
peye.z = mtx[2][3] + ((mtx[2][2] * z) + ((mtx[2][0] * x) + (mtx[2][1] * y)));
|
||||
if (pm[0] == 0.0f) {
|
||||
xc = (peye.x * pm[1]) + (peye.z * pm[2]);
|
||||
yc = (peye.y * pm[3]) + (peye.z * pm[4]);
|
||||
zc = pm[6] + (peye.z * pm[5]);
|
||||
wc = 1.0f / -peye.z;
|
||||
}
|
||||
else {
|
||||
xc = pm[2] + (peye.x * pm[1]);
|
||||
yc = pm[4] + (peye.y * pm[3]);
|
||||
zc = pm[6] + (peye.z * pm[5]);
|
||||
wc = 1.0f;
|
||||
}
|
||||
*sx = (vp[2] / 2.0f) + (vp[0] + (wc * (xc * vp[2] / 2.0f)));
|
||||
*sy = (vp[3] / 2.0f) + (vp[1] + (wc * (-yc * vp[3] / 2.0f)));
|
||||
*sz = vp[5] + (wc * (zc * (vp[5] - vp[4])));
|
||||
}
|
||||
|
||||
static void WriteProjPS(const register f32 proj[6], register volatile void *dest)
|
||||
{
|
||||
register f32 p01, p23, p45;
|
||||
|
||||
asm {
|
||||
psq_l p01, 0(proj), 0, 0
|
||||
psq_l p23, 8(proj), 0, 0
|
||||
psq_l p45, 16(proj), 0, 0
|
||||
psq_st p01, 0(dest), 0, 0
|
||||
psq_st p23, 0(dest), 0, 0
|
||||
psq_st p45, 0(dest), 0, 0
|
||||
}
|
||||
}
|
||||
|
||||
static void __GXSetProjection(void)
|
||||
{
|
||||
u32 reg = 0x00061020;
|
||||
GX_WRITE_U8(0x10);
|
||||
GX_WRITE_U32(reg);
|
||||
GX_WRITE_XF_REG_F(32, gx->projMtx[0]);
|
||||
GX_WRITE_XF_REG_F(33, gx->projMtx[1]);
|
||||
GX_WRITE_XF_REG_F(34, gx->projMtx[2]);
|
||||
GX_WRITE_XF_REG_F(35, gx->projMtx[3]);
|
||||
GX_WRITE_XF_REG_F(36, gx->projMtx[4]);
|
||||
GX_WRITE_XF_REG_F(37, gx->projMtx[5]);
|
||||
GX_WRITE_XF_REG_2(38, gx->projType);
|
||||
}
|
||||
|
||||
void GXSetProjection(f32 mtx[4][4], GXProjectionType type)
|
||||
{
|
||||
CHECK_GXBEGIN(0x127, "GXSetProjection");
|
||||
|
||||
gx->projType = type;
|
||||
gx->projMtx[0] = mtx[0][0];
|
||||
gx->projMtx[2] = mtx[1][1];
|
||||
gx->projMtx[4] = mtx[2][2];
|
||||
gx->projMtx[5] = mtx[2][3];
|
||||
if (type == GX_ORTHOGRAPHIC) {
|
||||
gx->projMtx[1] = mtx[0][3];
|
||||
gx->projMtx[3] = mtx[1][3];
|
||||
}
|
||||
else {
|
||||
gx->projMtx[1] = mtx[0][2];
|
||||
gx->projMtx[3] = mtx[1][2];
|
||||
}
|
||||
|
||||
__GXSetProjection();
|
||||
gx->bpSentNot = 1;
|
||||
}
|
||||
|
||||
#define qr0 0
|
||||
|
||||
void GXGetProjectionv(f32 *ptr)
|
||||
{
|
||||
ASSERTMSGLINE(0x172, ptr, "GXGet*: invalid null pointer");
|
||||
|
||||
ptr[0] = gx->projType;
|
||||
|
||||
ptr[1] = gx->projMtx[0];
|
||||
ptr[2] = gx->projMtx[1];
|
||||
ptr[3] = gx->projMtx[2];
|
||||
ptr[4] = gx->projMtx[3];
|
||||
ptr[5] = gx->projMtx[4];
|
||||
ptr[6] = gx->projMtx[5];
|
||||
}
|
||||
|
||||
static void WriteMTXPS4x3(const register f32 mtx[3][4], register volatile f32 *dest)
|
||||
{
|
||||
register f32 a00_a01;
|
||||
register f32 a02_a03;
|
||||
register f32 a10_a11;
|
||||
register f32 a12_a13;
|
||||
register f32 a20_a21;
|
||||
register f32 a22_a23;
|
||||
|
||||
asm {
|
||||
psq_l a00_a01, 0x00(mtx), 0, qr0
|
||||
psq_l a02_a03, 0x08(mtx), 0, qr0
|
||||
psq_l a10_a11, 0x10(mtx), 0, qr0
|
||||
psq_l a12_a13, 0x18(mtx), 0, qr0
|
||||
psq_l a20_a21, 0x20(mtx), 0, qr0
|
||||
psq_l a22_a23, 0x28(mtx), 0, qr0
|
||||
psq_st a00_a01, 0(dest), 0, qr0
|
||||
psq_st a02_a03, 0(dest), 0, qr0
|
||||
psq_st a10_a11, 0(dest), 0, qr0
|
||||
psq_st a12_a13, 0(dest), 0, qr0
|
||||
psq_st a20_a21, 0(dest), 0, qr0
|
||||
psq_st a22_a23, 0(dest), 0, qr0
|
||||
}
|
||||
}
|
||||
|
||||
static void WriteMTXPS3x3from3x4(register f32 mtx[3][4], register volatile f32 *dest)
|
||||
{
|
||||
register f32 a00_a01;
|
||||
register f32 a02_a03;
|
||||
register f32 a10_a11;
|
||||
register f32 a12_a13;
|
||||
register f32 a20_a21;
|
||||
register f32 a22_a23;
|
||||
|
||||
asm {
|
||||
psq_l a00_a01, 0x00(mtx), 0, qr0
|
||||
lfs a02_a03, 0x08(mtx)
|
||||
psq_l a10_a11, 0x10(mtx), 0, qr0
|
||||
lfs a12_a13, 0x18(mtx)
|
||||
psq_l a20_a21, 0x20(mtx), 0, qr0
|
||||
lfs a22_a23, 0x28(mtx)
|
||||
psq_st a00_a01, 0(dest), 0, qr0
|
||||
stfs a02_a03, 0(dest)
|
||||
psq_st a10_a11, 0(dest), 0, qr0
|
||||
stfs a12_a13, 0(dest)
|
||||
psq_st a20_a21, 0(dest), 0, qr0
|
||||
stfs a22_a23, 0(dest)
|
||||
}
|
||||
}
|
||||
|
||||
static void WriteMTXPS4x2(const register f32 mtx[2][4], register volatile f32 *dest)
|
||||
{
|
||||
register f32 a00_a01;
|
||||
register f32 a02_a03;
|
||||
register f32 a10_a11;
|
||||
register f32 a12_a13;
|
||||
|
||||
asm {
|
||||
psq_l a00_a01, 0x00(mtx), 0, qr0
|
||||
psq_l a02_a03, 0x08(mtx), 0, qr0
|
||||
psq_l a10_a11, 0x10(mtx), 0, qr0
|
||||
psq_l a12_a13, 0x18(mtx), 0, qr0
|
||||
psq_st a00_a01, 0(dest), 0, qr0
|
||||
psq_st a02_a03, 0(dest), 0, qr0
|
||||
psq_st a10_a11, 0(dest), 0, qr0
|
||||
psq_st a12_a13, 0(dest), 0, qr0
|
||||
}
|
||||
}
|
||||
|
||||
#pragma peephole off
|
||||
#pragma dont_inline on
|
||||
void GXLoadPosMtxImm(f32 mtx[3][4], u32 id)
|
||||
{
|
||||
u32 reg;
|
||||
u32 addr;
|
||||
|
||||
CHECK_GXBEGIN(0x1FB, "GXLoadPosMtxImm");
|
||||
|
||||
addr = id * 4;
|
||||
reg = addr | 0xB0000;
|
||||
|
||||
GX_WRITE_U8(0x10);
|
||||
GX_WRITE_U32(reg);
|
||||
WriteMTXPS4x3(mtx, &GXWGFifo.f32);
|
||||
}
|
||||
|
||||
void GXLoadNrmMtxImm(f32 mtx[3][4], u32 id)
|
||||
{
|
||||
u32 reg;
|
||||
u32 addr;
|
||||
|
||||
CHECK_GXBEGIN(0x24C, "GXLoadNrmMtxImm");
|
||||
|
||||
addr = id * 3 + 0x400;
|
||||
reg = addr | 0x80000;
|
||||
|
||||
GX_WRITE_U8(0x10);
|
||||
GX_WRITE_U32(reg);
|
||||
WriteMTXPS3x3from3x4((void *)mtx, &GXWGFifo.f32);
|
||||
}
|
||||
|
||||
void GXSetCurrentMtx(u32 id)
|
||||
{
|
||||
CHECK_GXBEGIN(0x2C4, "GXSetCurrentMtx");
|
||||
SET_REG_FIELD(0x2C8, gx->matIdxA, 6, 0, id);
|
||||
__GXSetMatrixIndex(GX_VA_PNMTXIDX);
|
||||
}
|
||||
|
||||
void GXLoadTexMtxImm(f32 mtx[][4], u32 id, GXTexMtxType type)
|
||||
{
|
||||
u32 reg;
|
||||
u32 addr;
|
||||
u32 count;
|
||||
|
||||
CHECK_GXBEGIN(0x2E5, "GXLoadTexMtxImm");
|
||||
|
||||
if (id >= GX_PTTEXMTX0) {
|
||||
addr = (id - GX_PTTEXMTX0) * 4 + 0x500;
|
||||
ASSERTMSGLINE(0x2EF, type == GX_MTX3x4, "GXLoadTexMtx: Invalid matrix type");
|
||||
}
|
||||
else {
|
||||
addr = id * 4;
|
||||
}
|
||||
count = (type == GX_MTX2x4) ? 8 : 12;
|
||||
reg = addr | ((count - 1) << 16);
|
||||
|
||||
GX_WRITE_U8(0x10);
|
||||
GX_WRITE_U32(reg);
|
||||
if (type == GX_MTX3x4) {
|
||||
WriteMTXPS4x3(mtx, &GXWGFifo.f32);
|
||||
}
|
||||
else {
|
||||
WriteMTXPS4x2(mtx, &GXWGFifo.f32);
|
||||
}
|
||||
}
|
||||
#pragma dont_inline reset
|
||||
|
||||
void GXSetViewportJitter(f32 left, f32 top, f32 wd, f32 ht, f32 nearz, f32 farz, u32 field)
|
||||
{
|
||||
f32 sx;
|
||||
f32 sy;
|
||||
f32 sz;
|
||||
f32 ox;
|
||||
f32 oy;
|
||||
f32 oz;
|
||||
f32 zmin;
|
||||
f32 zmax;
|
||||
u32 reg;
|
||||
|
||||
CHECK_GXBEGIN(0x387, "GXSetViewport"); // not the correct function name
|
||||
|
||||
if (field == 0) {
|
||||
top -= 0.5f;
|
||||
}
|
||||
sx = wd / 2.0f;
|
||||
sy = -ht / 2.0f;
|
||||
ox = 342.0f + (left + (wd / 2.0f));
|
||||
oy = 342.0f + (top + (ht / 2.0f));
|
||||
zmin = 1.6777215e7f * nearz;
|
||||
zmax = 1.6777215e7f * farz;
|
||||
sz = zmax - zmin;
|
||||
oz = zmax;
|
||||
gx->vpLeft = left;
|
||||
gx->vpTop = top;
|
||||
gx->vpWd = wd;
|
||||
gx->vpHt = ht;
|
||||
gx->vpNearz = nearz;
|
||||
gx->vpFarz = farz;
|
||||
if (gx->fgRange != 0) {
|
||||
__GXSetRange(nearz, gx->fgSideX);
|
||||
}
|
||||
reg = 0x5101A;
|
||||
GX_WRITE_U8(0x10);
|
||||
GX_WRITE_U32(reg);
|
||||
GX_WRITE_XF_REG_F(26, sx);
|
||||
GX_WRITE_XF_REG_F(27, sy);
|
||||
GX_WRITE_XF_REG_F(28, sz);
|
||||
GX_WRITE_XF_REG_F(29, ox);
|
||||
GX_WRITE_XF_REG_F(30, oy);
|
||||
GX_WRITE_XF_REG_F(31, oz);
|
||||
gx->bpSentNot = 1;
|
||||
}
|
||||
|
||||
void GXSetViewport(f32 left, f32 top, f32 wd, f32 ht, f32 nearz, f32 farz)
|
||||
{
|
||||
GXSetViewportJitter(left, top, wd, ht, nearz, farz, 1U);
|
||||
}
|
||||
|
||||
void GXGetViewportv(f32 *vp)
|
||||
{
|
||||
ASSERTMSGLINE(0x3C8, vp, "GXGet*: invalid null pointer");
|
||||
|
||||
vp[0] = gx->vpLeft;
|
||||
vp[1] = gx->vpTop;
|
||||
vp[2] = gx->vpWd;
|
||||
vp[3] = gx->vpHt;
|
||||
vp[4] = gx->vpNearz;
|
||||
vp[5] = gx->vpFarz;
|
||||
}
|
||||
|
||||
// maybe get it from melee?
|
||||
void GXSetScissor(u32 left, u32 top, u32 wd, u32 ht)
|
||||
{
|
||||
u32 tp;
|
||||
u32 lf;
|
||||
u32 bm;
|
||||
u32 rt;
|
||||
|
||||
CHECK_GXBEGIN(0x418, "GXSetScissor");
|
||||
ASSERTMSGLINE(0x419, left < 1706, "GXSetScissor: Left origin > 1708");
|
||||
ASSERTMSGLINE(0x41A, top < 1706, "GXSetScissor: top origin > 1708");
|
||||
ASSERTMSGLINE(0x41B, left + wd < 1706, "GXSetScissor: right edge > 1708");
|
||||
ASSERTMSGLINE(0x41C, top + ht < 1706, "GXSetScissor: bottom edge > 1708");
|
||||
|
||||
tp = top + 342;
|
||||
lf = left + 342;
|
||||
bm = tp + ht - 1;
|
||||
rt = lf + wd - 1;
|
||||
|
||||
SET_REG_FIELD(0x423, gx->suScis0, 11, 0, tp);
|
||||
SET_REG_FIELD(0x424, gx->suScis0, 11, 12, lf);
|
||||
SET_REG_FIELD(0x426, gx->suScis1, 11, 0, bm);
|
||||
SET_REG_FIELD(0x427, gx->suScis1, 11, 12, rt);
|
||||
|
||||
GX_WRITE_RAS_REG(gx->suScis0);
|
||||
GX_WRITE_RAS_REG(gx->suScis1);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
|
||||
void GXSetScissorBoxOffset(s32 x_off, s32 y_off)
|
||||
{
|
||||
u32 reg = 0;
|
||||
u32 hx;
|
||||
u32 hy;
|
||||
|
||||
CHECK_GXBEGIN(0x45F, "GXSetScissorBoxOffset");
|
||||
|
||||
ASSERTMSGLINE(0x462, (u32)(x_off + 342) < 2048, "GXSetScissorBoxOffset: Invalid X offset");
|
||||
ASSERTMSGLINE(0x464, (u32)(y_off + 342) < 2048, "GXSetScissorBoxOffset: Invalid Y offset");
|
||||
|
||||
hx = (u32)(x_off + 342) >> 1;
|
||||
hy = (u32)(y_off + 342) >> 1;
|
||||
|
||||
SET_REG_FIELD(0x469, reg, 10, 0, hx);
|
||||
SET_REG_FIELD(0x46A, reg, 10, 10, hy);
|
||||
SET_REG_FIELD(0x46B, reg, 8, 24, 0x59);
|
||||
GX_WRITE_RAS_REG(reg);
|
||||
gx->bpSentNot = 0;
|
||||
}
|
||||
#pragma peephole on
|
||||
|
||||
void GXSetClipMode(GXClipMode mode)
|
||||
{
|
||||
CHECK_GXBEGIN(0x47F, "GXSetClipMode");
|
||||
GX_WRITE_XF_REG(5, mode);
|
||||
gx->bpSentNot = 1;
|
||||
}
|
||||
|
||||
void __GXSetMatrixIndex(GXAttr matIdxAttr)
|
||||
{
|
||||
if (matIdxAttr < GX_VA_TEX4MTXIDX) {
|
||||
GX_WRITE_SOME_REG4(8, 0x30, gx->matIdxA, -12);
|
||||
GX_WRITE_XF_REG(24, gx->matIdxA);
|
||||
}
|
||||
else {
|
||||
GX_WRITE_SOME_REG4(8, 0x40, gx->matIdxB, -12);
|
||||
GX_WRITE_XF_REG(25, gx->matIdxB);
|
||||
}
|
||||
gx->bpSentNot = 1;
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@ void PSQUATNormalize(void);
|
|||
void OSTicksToCalendarTime(void);
|
||||
void GXWaitDrawDone(void);
|
||||
void GXProject(void);
|
||||
void GXSetProjectionv(void);
|
||||
void GXGetProjectionv(void);
|
||||
void GXGetViewportv(void);
|
||||
void GXPixModeSync(void);
|
||||
void GXSetIndTexOrder(void);
|
||||
|
|
@ -1044,7 +1044,7 @@ extern void _kerjmp_PSQUATNormalize(void);
|
|||
extern void _kerjmp_OSTicksToCalendarTime(void);
|
||||
extern void _kerjmp_GXWaitDrawDone(void);
|
||||
extern void _kerjmp_GXProject(void);
|
||||
extern void _kerjmp_GXSetProjectionv(void);
|
||||
extern void _kerjmp_GXGetProjectionv(void);
|
||||
extern void _kerjmp_GXGetViewportv(void);
|
||||
extern void _kerjmp_GXPixModeSync(void);
|
||||
extern void _kerjmp_GXSetIndTexOrder(void);
|
||||
|
|
@ -2093,8 +2093,8 @@ asm void _kerent(void) {
|
|||
b GXWaitDrawDone
|
||||
entry _kerjmp_GXProject
|
||||
b GXProject
|
||||
entry _kerjmp_GXSetProjectionv
|
||||
b GXSetProjectionv
|
||||
entry _kerjmp_GXGetProjectionv
|
||||
b GXGetProjectionv
|
||||
entry _kerjmp_GXGetViewportv
|
||||
b GXGetViewportv
|
||||
entry _kerjmp_GXPixModeSync
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue