most of shieldD revo sdk matching (#2951)

* shieldD revo wpad done

* shieldD revo hio2 done

* shieldD revo aralt, ppcarch, gf done

* shieldD revo exi done

* shieldD revo SI done

* shieldD revo vi done

* shieldD revo mtx done

* shieldD revo GX mostly done

* shieldD revo ai/dsp done

* shieldD revo sc mostly done

* shieldD revo esp/euart/wenc mostly done

* build fixes
This commit is contained in:
TakaRikka
2025-12-13 08:21:32 -08:00
committed by GitHub
parent 25dfef320b
commit 4e6dffff5a
103 changed files with 33893 additions and 85 deletions
+2 -2
View File
@@ -147,8 +147,8 @@ void dHomeButton_c::initCursorPos() {
void dHomeButton_c::calcCursorPos() {
for (u32 i = 0; i < 4; i++) {
WPADDeviceType sp8;
WPADResult result = WPADProbe(i, &sp8);
u32 sp8;
s32 result = WPADProbe(i, &sp8);
if (result == -2 || result == -3 || result == 0) {
m_controllerData.wiiCon[i].kpad = &mReCPd::m_pad[i].field_0x4[0];
+1 -1
View File
@@ -338,7 +338,7 @@ static bool data_80450BE8;
void mDoGph_gInf_c::beginRender() {
#if PLATFORM_WII || PLATFORM_SHIELD
VISetTrapFilter(fapGmHIO_getTrapFilter() ? 1 : 0);
VISetGamma(fapGmHIO_getGamma());
VISetGamma((VIGamma)fapGmHIO_getGamma());
#endif
if (data_80450BE8) {
+273
View File
@@ -0,0 +1,273 @@
#include <revolution/ai.h>
#include <revolution/gx.h>
#include <revolution/os.h>
#include <revolution/hw_regs.h>
#include "__gx.h"
#ifdef SDK_AUG2010
#define BUILD_DATE "Aug 23 2010"
#if DEBUG
#define BUILD_TIME "17:24:31"
#else
#define BUILD_TIME "17:33:06"
#endif
#elif SDK_SEP2006
#define BUILD_DATE "Sep 21 2006"
#define BUILD_TIME "14:32:13"
#endif
#ifdef SDK_AUG2010
#if DEBUG
const char* __AIVersion = "<< RVL_SDK - AI \tdebug build: "BUILD_DATE" "BUILD_TIME" (0x4302_145) >>";
#else
const char* __AIVersion = "<< RVL_SDK - AI \trelease build: "BUILD_DATE" "BUILD_TIME" (0x4302_145) >>";
#endif
#elif SDK_SEP2006
const char* __AIVersion = "<< RVL_SDK - AI \trelease build: "BUILD_DATE" "BUILD_TIME" (0x4200_60422) >>";
#endif
static AIDCallback __AID_Callback;
static u8* __CallbackStack;
static u8* __OldStack;
static BOOL __AI_init_flag;
static BOOL __AID_Active;
static OSTime bound_32KHz;
static OSTime bound_48KHz;
static OSTime min_wait;
static OSTime max_wait;
static OSTime buffer;
typedef struct {
OSTime t_start;
OSTime t1;
OSTime t2;
OSTime t3;
OSTime t4;
OSTime t_end;
} STRUCT_TIMELOG;
STRUCT_TIMELOG __AIprofile;
OSTime __ai_src_time_start;
OSTime __ai_src_time_end;
// prototypes
STRUCT_TIMELOG* __ai_src_get_time(void);
static void __AIDHandler(__OSInterrupt interrupt, OSContext* context);
static void __AICallbackStackSwitch(void* cb);
static void __AI_SRC_INIT(void);
AIDCallback AIRegisterDMACallback(AIDCallback callback) {
AIDCallback old_callback;
BOOL old;
old_callback = __AID_Callback;
old = OSDisableInterrupts();
__AID_Callback = callback;
OSRestoreInterrupts(old);
return old_callback;
}
void AIInitDMA(u32 start_addr, u32 length) {
BOOL old;
old = OSDisableInterrupts();
__DSPRegs[24] = (__DSPRegs[24] & ~0x1FFF) | (start_addr >> 16);
__DSPRegs[25] = (__DSPRegs[25] & ~0xFFE0) | (start_addr & 0xFFFF);
ASSERTMSGLINE(342, (length & 0x1F) == 0, "AIStartDMA: length must be multiple of 32 bytes");
__DSPRegs[27] = (__DSPRegs[27] & ~0x7FFF) | (u16)((length >> 5) & 0xFFFF);
OSRestoreInterrupts(old);
}
BOOL AIGetDMAEnableFlag(void) {
return (__DSPRegs[27] & (1 << 15)) >> 15;
}
void AIStartDMA(void) {
__DSPRegs[27] = __DSPRegs[27] | 0x8000;
}
void AIStopDMA(void) {
__DSPRegs[27] = __DSPRegs[27] & ~0x8000;
}
u32 AIGetDMABytesLeft(void) {
return (__DSPRegs[29] & 0x7FFF) << 5;
}
u32 AIGetDMAStartAddr(void) {
return (((__DSPRegs[24] & 0x1FFF) << 16) | (__DSPRegs[25] & 0xFFE0));
}
u32 AIGetDMALength(void) {
return (__DSPRegs[27] & 0x7FFF) << 5;
}
BOOL AICheckInit(void) {
return __AI_init_flag;
}
void AISetDSPSampleRate(u32 rate) {
BOOL old;
if (rate != AIGetDSPSampleRate()) {
__AIRegs[0] = (__AIRegs[0] & ~0x40);
if (rate == AI_SAMPLERATE_32KHZ) {
old = OSDisableInterrupts();
__AI_SRC_INIT();
__AIRegs[0] |= 0x40;
OSRestoreInterrupts(old);
}
}
}
u32 AIGetDSPSampleRate(void) {
return GET_REG_FIELD(__AIRegs[0], 1, 6) ^ 1;
}
void AIInit(u8* stack) {
u32 reg;
if (__AI_init_flag != TRUE) {
OSRegisterVersion(__AIVersion);
bound_32KHz = OSNanosecondsToTicks(31524);
bound_48KHz = OSNanosecondsToTicks(42024);
min_wait = OSNanosecondsToTicks(42000);
max_wait = OSNanosecondsToTicks(63000);
buffer = OSNanosecondsToTicks(3000);
reg = __AIRegs[0];
reg &= ~(0x1 | 0x4 | 0x10);
__AIRegs[0] = reg;
__AIRegs[1] = 0;
__AIRegs[3] = 0;
__AIRegs[0] = (__AIRegs[0] & ~0x20) | (0x1 << 5);
AISetDSPSampleRate(AI_SAMPLERATE_32KHZ);
#if DEBUG
OSReport("AIInit(): DSP is 32KHz\n");
#endif
__AID_Callback = NULL;
__CallbackStack = stack;
ASSERTMSGLINE(663, !stack || ((u32)stack & 7) == 0, "AIInit: stack must be 8-byte aligned");
__OSSetInterruptHandler(5, __AIDHandler);
__OSUnmaskInterrupts(0x04000000);
__AI_init_flag = TRUE;
}
}
void AIReset(void) {
__AI_init_flag = FALSE;
}
static void __AIDHandler(__OSInterrupt interrupt, OSContext* context) {
OSContext exceptionContext;
u16 tmp;
tmp = __DSPRegs[5];
tmp = (tmp & ~0xA0) | 8;
__DSPRegs[5] = tmp;
OSClearContext(&exceptionContext);
OSSetCurrentContext(&exceptionContext);
if (__AID_Callback && !__AID_Active) {
__AID_Active = TRUE;
if (__CallbackStack) {
__AICallbackStackSwitch(__AID_Callback);
} else {
__AID_Callback();
}
__AID_Active = FALSE;
}
OSClearContext(&exceptionContext);
OSSetCurrentContext(context);
}
static asm void __AICallbackStackSwitch(__REGISTER void* cb) {
fralloc
lis r5, __OldStack@ha
addi r5, r5, __OldStack@l
stw r1, 0x0(r5)
lis r5, __CallbackStack@ha
addi r5, r5, __CallbackStack@l
lwz r1, 0x0(r5)
subi r1, r1, 0x8
mtlr cb
blrl
lis r5, __OldStack@ha
addi r5, r5, __OldStack@l
lwz r1, 0x0(r5)
frfree
blr
}
void __AI_SRC_INIT(void) {
OSTime rising_32khz = 0;
OSTime rising_48khz = 0;
OSTime diff = 0;
OSTime t1 = 0;
OSTime temp;
u32 temp0;
u32 temp1;
u32 done = 0;
u32 volume = 0;
u32 Init_Cnt = 0;
u32 walking = 0;
walking = 0;
Init_Cnt = 0;
temp = 0;
#if DEBUG
__AIprofile.t_start = OSGetTime();
#endif
while (!done) {
OLD_SET_REG_FIELD(0, __AIRegs[0], 1, 5, 1);
OLD_SET_REG_FIELD(0, __AIRegs[0], 1, 1, 0);
OLD_SET_REG_FIELD(0, __AIRegs[0], 1, 0, AI_STREAM_START);
temp0 = __AIRegs[2] & 0x7FFFFFFF;
while (temp0 == (__AIRegs[2] & 0x7FFFFFFF)) {
}
rising_32khz = OSGetTime();
OLD_SET_REG_FIELD(0, __AIRegs[0], 1, 1, 1);
OLD_SET_REG_FIELD(0, __AIRegs[0], 1, 0, AI_STREAM_START);
temp1 = __AIRegs[2] & 0x7FFFFFFF;
while (temp1 == (__AIRegs[2] & 0x7FFFFFFF)) {
}
rising_48khz = OSGetTime();
diff = rising_48khz - rising_32khz;
OLD_SET_REG_FIELD(0, __AIRegs[0], 1, 1, 0);
OLD_SET_REG_FIELD(0, __AIRegs[0], 1, 0, AI_STREAM_STOP);
if (diff < bound_32KHz - buffer) {
temp = min_wait;
done = 1;
Init_Cnt++;
} else if (diff >= bound_32KHz + buffer && diff < bound_48KHz - buffer) {
temp = max_wait;
done = 1;
Init_Cnt++;
} else {
done = 0;
walking = 1;
Init_Cnt++;
}
}
while (rising_48khz + temp > OSGetTime()) {
}
#if DEBUG
__AIprofile.t_end = OSGetTime();
#endif
}
STRUCT_TIMELOG* __ai_src_get_time(void) {
#if DEBUG
return &__AIprofile;
#else
return NULL;
#endif
}
+18
View File
@@ -0,0 +1,18 @@
#ifndef _REVOLUTION_AR_INTERNAL_H_
#define _REVOLUTION_AR_INTERNAL_H_
#include <revolution/aralt.h>
#ifdef __cplusplus
extern "C" {
#endif
void __ARQPopTaskQueueHi(void);
void __ARQServiceQueueLo(void);
void __ARQInterruptServiceRoutine(u32);
#ifdef __cplusplus
}
#endif
#endif // _REVOLUTION_AR_INTERNAL_H_
+175
View File
@@ -0,0 +1,175 @@
#include <revolution.h>
#include <revolution/aralt.h>
#include "fake_tgmath.h"
#include <string.h>
#include "__ar.h"
static void (*__AR_Callback)();
static u32 __AR_Size;
static u32 __AR_InternalSize;
static u32 __ARH_BaseAdr;
static ARQRequest* __ARQRequestQueueHi;
static ARQRequest* __ARQRequestQueueLo;
static ARQRequest* __ARQRequestPendingHi;
static ARQRequest* __ARQRequestPendingLo;
static ARQCallback __ARQCallbackHi;
static ARQCallback __ARQCallbackLo;
static u32 __ARQChunkSize;
static BOOL __ARQ_init_flag;
static BOOL __AR_init_flag;
static u32 __ARALT_AramStartAdr = 0x90000000;
static u32 __ARH_MemoryTop = 0x90000000;
ARQCallback ARRegisterDMACallback(ARQCallback callback) {
ARQCallback old_callback;
BOOL old;
old_callback = __AR_Callback;
old = OSDisableInterrupts();
__AR_Callback = callback;
OSRestoreInterrupts(old);
return old_callback;
}
void ARStartDMA(u32 type, u32 mainmem_addr, u32 aram_addr, u32 length) {
OSDisableScheduler();
if (type == 0) {
aram_addr += __ARH_BaseAdr;
DCInvalidateRange((u32*)mainmem_addr, length);
memcpy((u32*)aram_addr, (u32*)mainmem_addr, length);
DCFlushRange((u32*)aram_addr, length);
} else if (type == 1) {
mainmem_addr += __ARH_BaseAdr;
DCFlushRange((u32*)mainmem_addr, length);
memcpy((u32*)aram_addr, (u32*)mainmem_addr, length);
DCFlushRange((u32*)aram_addr, length);
}
OSEnableScheduler();
if (__AR_Callback != NULL) {
(*__AR_Callback)();
}
}
u32 ARAlloc(u32 length) {
u32 tmp;
BOOL old;
old = OSDisableInterrupts();
tmp = __ARH_MemoryTop;
OSRestoreInterrupts(old);
__ARH_MemoryTop += length;
return tmp - __ARH_BaseAdr;
}
u32 ARInit(u32* stack_index_addr, u32 num_entries) {
BOOL old;
if (__AR_init_flag) {
return ARGetBaseAddress();
}
old = OSDisableInterrupts();
__AR_Callback = NULL;
__AR_init_flag = TRUE;
OSRestoreInterrupts(old);
{
u32 start;
u32 end;
start = __ARALT_AramStartAdr;
end = start + 0x1100000;
__ARH_MemoryTop = ARGetBaseAddress() + start;
__ARH_BaseAdr = start;
OSReport("ARInit : Dummy ARAM enabled (RVL), area %p -> %p (size 0x%x)\n", start, end, end - start);
__AR_Size = end - start;
__AR_InternalSize = __AR_Size;
}
return ARGetBaseAddress();
}
u32 ARGetBaseAddress(void) {
return 0x4000;
}
u32 ARGetSize(void) {
return __AR_Size;
}
void __ARQPopTaskQueueHi(void) {
if (__ARQRequestQueueHi) {
if (__ARQRequestQueueHi->type == 0) {
ARStartDMA(__ARQRequestQueueHi->type, __ARQRequestQueueHi->source, __ARQRequestQueueHi->dest, __ARQRequestQueueHi->length);
} else {
ARStartDMA(__ARQRequestQueueHi->type, __ARQRequestQueueHi->dest, __ARQRequestQueueHi->source, __ARQRequestQueueHi->length);
}
__ARQCallbackHi = __ARQRequestQueueHi->callback;
__ARQRequestPendingHi = __ARQRequestQueueHi;
__ARQRequestQueueHi = __ARQRequestQueueHi->next;
}
}
void __ARQServiceQueueLo(void) {
if (__ARQRequestPendingLo == NULL && __ARQRequestQueueLo) {
__ARQRequestPendingLo = __ARQRequestQueueLo;
__ARQRequestQueueLo = __ARQRequestQueueLo->next;
}
if (__ARQRequestPendingLo) {
if (__ARQRequestPendingLo->length <= __ARQChunkSize) {
if (__ARQRequestPendingLo->type == 0) {
ARStartDMA(__ARQRequestPendingLo->type, __ARQRequestPendingLo->source, __ARQRequestPendingLo->dest, __ARQRequestPendingLo->length);
} else {
ARStartDMA(__ARQRequestPendingLo->type, __ARQRequestPendingLo->dest, __ARQRequestPendingLo->source, __ARQRequestPendingLo->length);
}
__ARQCallbackLo = __ARQRequestPendingLo->callback;
} else if (__ARQRequestPendingLo->type == 0) {
ARStartDMA(__ARQRequestPendingLo->type, __ARQRequestPendingLo->source, __ARQRequestPendingLo->dest, __ARQChunkSize);
} else {
ARStartDMA(__ARQRequestPendingLo->type, __ARQRequestPendingLo->dest, __ARQRequestPendingLo->source, __ARQChunkSize);
}
__ARQRequestPendingLo->length -= __ARQChunkSize;
__ARQRequestPendingLo->source += __ARQChunkSize;
__ARQRequestPendingLo->dest += __ARQChunkSize;
}
}
void __ARQInterruptServiceRoutine(u32) {
if (__ARQCallbackHi) {
__ARQCallbackHi((u32)__ARQRequestPendingHi);
__ARQRequestPendingHi = NULL;
__ARQCallbackHi = NULL;
} else if (__ARQCallbackLo) {
__ARQCallbackLo((u32)__ARQRequestPendingLo);
__ARQRequestPendingLo = NULL;
__ARQCallbackLo = NULL;
}
__ARQPopTaskQueueHi();
if (__ARQRequestPendingHi == NULL) {
__ARQServiceQueueLo();
}
}
void ARQInit(void) {
if (__ARQ_init_flag != TRUE) {
__ARQRequestQueueHi = __ARQRequestQueueLo = NULL;
__ARQChunkSize = 0x1000;
ARRegisterDMACallback(__ARQInterruptServiceRoutine);
__ARQRequestPendingHi = NULL;
__ARQRequestPendingLo = NULL;
__ARQCallbackHi = NULL;
__ARQCallbackLo = NULL;
__ARQ_init_flag = TRUE;
}
}
+306
View File
@@ -0,0 +1,306 @@
#include <revolution.h>
#include <revolution/base/PPCArch.h>
asm u32 PPCMfmsr() {
nofralloc
mfmsr r3
blr
}
asm void PPCMtmsr(__REGISTER u32 newMSR) {
nofralloc
mtmsr newMSR
blr
}
asm u32 PPCOrMsr(__REGISTER u32 value) {
nofralloc
mfmsr r4
or value, r4, value
blr
}
asm u32 PPCAndMsr(__REGISTER u32 value) {
nofralloc
mfmsr r4
and value, r4, value
blr
}
asm u32 PPCAndCMsr(__REGISTER u32 value) {
nofralloc
mfmsr r4
andc value, r4, value
blr
}
asm u32 PPCMfhid0() {
nofralloc
mfspr r3, HID0
blr
}
asm void PPCMthid0(__REGISTER u32 newHID0) {
nofralloc
mtspr HID0, newHID0
blr
}
asm u32 PPCMfhid1() {
nofralloc
mfspr r3, HID1
blr
}
asm u32 PPCMfl2cr() {
nofralloc
mfspr r3, L2CR
blr
}
asm void PPCMtl2cr(__REGISTER u32 newL2cr) {
nofralloc
mtspr L2CR, newL2cr
blr
}
asm void PPCMtdec(__REGISTER u32 newDec) {
nofralloc
mtdec newDec
blr
}
asm u32 PPCMfdec() {
nofralloc
mfdec r3
blr
}
asm void PPCSync() {
nofralloc
sc
blr
}
asm void PPCEieio() {
nofralloc
mfmsr r5
rlwinm r6, r5, 0, 17, 15
mtmsr r6
mfspr r3, HID0
ori r4, r3, 0x8
mtspr HID0, r4
isync
eieio
isync
mtspr HID0, r3
mtmsr r5
isync
blr
}
asm void PPCHalt() {
nofralloc
sync
loop:
nop
li r3, 0
nop
b loop
}
asm u32 PPCMfmmcr0() {
nofralloc
mfspr r3, MMCR0
blr
}
asm void PPCMtmmcr0(__REGISTER u32 newMmcr0) {
nofralloc
mtspr MMCR0, newMmcr0
blr
}
asm u32 PPCMfmmcr1() {
nofralloc
mfspr r3, MMCR1
blr
}
asm void PPCMtmmcr1(__REGISTER u32 newMmcr1) {
nofralloc
mtspr MMCR1, newMmcr1
blr
}
asm u32 PPCMfpmc1() {
nofralloc
mfspr r3, PMC1
blr
}
asm void PPCMtpmc1(__REGISTER u32 newPmc1) {
nofralloc
mtspr PMC1, newPmc1
blr
}
asm u32 PPCMfpmc2() {
nofralloc
mfspr r3, PMC2
blr
}
asm void PPCMtpmc2(__REGISTER u32 newPmc2) {
nofralloc
mtspr PMC2, newPmc2
blr
}
asm u32 PPCMfpmc3() {
nofralloc
mfspr r3, PMC3
blr
}
asm void PPCMtpmc3(__REGISTER u32 newPmc3) {
nofralloc
mtspr PMC3, newPmc3
blr
}
asm u32 PPCMfpmc4() {
nofralloc
mfspr r3, PMC4
blr
}
asm void PPCMtpmc4(__REGISTER u32 newPmc4) {
nofralloc
mtspr PMC4, newPmc4
blr
}
asm u32 PPCMfsia() {
nofralloc
mfspr r3, SIA
blr
}
asm void PPCMtsia(__REGISTER u32 newSia) {
nofralloc
mtspr SIA, newSia
blr
}
u32 PPCMffpscr() {
union FpscrUnion m;
asm {
mffs fp31
stfd fp31, m.f;
}
return m.u.fpscr;
}
void PPCMtfpscr(__REGISTER u32 newFPSCR) {
union FpscrUnion m;
asm {
li r4, 0
stw r4, m.u.fpscr_pad;
stw newFPSCR, m.u.fpscr
lfd fp31, m.f
mtfsf 0xff, fp31
}
}
asm u32 PPCMfhid2() {
nofralloc
mfspr r3, HID2
blr
}
asm void PPCMthid2(__REGISTER u32 newhid2) {
nofralloc
mtspr HID2, newhid2
blr
}
asm u32 PPCMfwpar() {
nofralloc
sync
mfspr r3, WPAR
blr
}
asm void PPCMtwpar(__REGISTER u32 newwpar) {
nofralloc
mtspr WPAR, newwpar
blr
}
asm u32 PPCMfdmaU() {
nofralloc
mfspr r3, DMA_U
blr
}
asm u32 PPCMfdmaL() {
nofralloc
mfspr r3, DMA_L
blr
}
asm void PPCMtdmaU(__REGISTER u32 newdmau) {
nofralloc
mtspr DMA_U, newdmau
blr
}
asm void PPCMtdmaL(__REGISTER u32 newdmal) {
nofralloc
mtspr DMA_L, newdmal
blr
}
asm u32 PPCMfpvr() {
nofralloc
mfspr r3, PVR
blr
}
void PPCEnableSpeculation(void) {
PPCMthid0(PPCMfhid0() & ~HID0_SPD);
}
void PPCDisableSpeculation(void) {
PPCMthid0(PPCMfhid0() | HID0_SPD);
}
asm void PPCSetFpIEEEMode() {
nofralloc
mtfsb0 29
blr
}
asm void PPCSetFpNonIEEEMode() {
nofralloc
mtfsb1 29
blr
}
void PPCMthid4(__REGISTER u32 newhid4) {
if (newhid4 & 0x80000000) {
asm {
mtspr 1011, newhid4
}
} else {
OSReport("H4A should not be cleared because of Broadway errata.\n");
asm {
oris newhid4, newhid4, 0x8000
mtspr 1011, newhid4
}
}
}
+34
View File
@@ -0,0 +1,34 @@
#include <revolution.h>
#include <revolution/base/PPCArch.h>
void PMBegin(void) {
PPCMtmmcr0(0);
PPCMtmmcr1(0);
PPCMtpmc1(0);
PPCMtpmc2(0);
PPCMtpmc3(0);
PPCMtpmc4(0);
PPCMtmmcr0(0x4F);
PPCMtmmcr1(0x78800000);
}
void PMEnd(void) {
PPCMtmmcr0(0);
PPCMtmmcr1(0);
}
void PMCycles(void) {
PPCMfpmc1();
}
void PML1FetchMisses(void) {
PPCMfpmc2();
}
void PML1MissCycles(void) {
PPCMfpmc3();
}
void PMInstructions(void) {
PPCMfpmc4();
}
+27
View File
@@ -0,0 +1,27 @@
#ifndef _REVOLUTION_DSP_INTERNAL_H_
#define _REVOLUTION_DSP_INTERNAL_H_
#include <revolution/dsp.h>
#ifdef __cplusplus
extern "C" {
#endif
extern DSPTaskInfo* __DSP_first_task;
extern DSPTaskInfo* __DSP_last_task;
extern DSPTaskInfo* __DSP_curr_task;
extern DSPTaskInfo* __DSP_tmp_task;
DECL_WEAK void __DSPHandler(__OSInterrupt, OSContext*);
void __DSP_exec_task(DSPTaskInfo*, DSPTaskInfo*);
void __DSP_boot_task(DSPTaskInfo*);
void __DSP_insert_task(DSPTaskInfo*);
void __DSP_add_task(DSPTaskInfo* task);
void __DSP_remove_task(DSPTaskInfo* task);
void __DSP_debug_printf(const char* fmt, ...);
#ifdef __cplusplus
}
#endif
#endif
+194
View File
@@ -0,0 +1,194 @@
#include <stddef.h>
#include <revolution.h>
#include <revolution/hw_regs.h>
#include "__dsp.h"
#ifdef SDK_AUG2010
#define BUILD_DATE "Aug 23 2010"
#if DEBUG
#define BUILD_TIME "17:24:48"
#else
#define BUILD_TIME "17:33:06"
#endif
#elif SDK_SEP2006
#define BUILD_DATE "Sep 21 2006"
#define BUILD_TIME "14:32:13"
#endif
#ifdef SDK_AUG2010
#if DEBUG
const char* __DSPVersion = "<< RVL_SDK - DSP \tdebug build: "BUILD_DATE" "BUILD_TIME" (0x4302_145) >>";
#else
const char* __DSPVersion = "<< RVL_SDK - DSP \trelease build: "BUILD_DATE" "BUILD_TIME" (0x4302_145) >>";
#endif
#elif SDK_SEP2006
const char* __DSPVersion = "<< RVL_SDK - DSP \trelease build: "BUILD_DATE" "BUILD_TIME" (0x4200_60422) >>";
#endif
extern DSPTaskInfo* __DSP_rude_task;
extern int __DSP_rude_task_pending;
static BOOL __DSP_init_flag;
u32 DSPCheckMailToDSP(void) {
return (__DSPRegs[0] & (1 << 15)) >> 15;
}
u32 DSPCheckMailFromDSP(void) {
return (__DSPRegs[2] & (1 << 15)) >> 15;
}
u32 DSPReadCPUToDSPMbox(void) {
return (__DSPRegs[0] << 16) | __DSPRegs[1];
}
u32 DSPReadMailFromDSP(void) {
return (__DSPRegs[2] << 16) | __DSPRegs[3];
}
void DSPSendMailToDSP(u32 mail) {
__DSPRegs[0] = mail >> 16;
__DSPRegs[1] = mail & 0xFFFF;
}
void DSPAssertInt(void) {
BOOL old;
u16 tmp;
old = OSDisableInterrupts();
tmp = __DSPRegs[5];
tmp = (tmp & ~0xA8) | 2;
__DSPRegs[5] = tmp;
OSRestoreInterrupts(old);
}
void DSPInit(void) {
BOOL old;
u16 tmp;
__DSP_debug_printf("DSPInit(): Build Date: %s %s\n", BUILD_DATE, BUILD_TIME);
if (__DSP_init_flag == 1)
return;
OSRegisterVersion(__DSPVersion);
old = OSDisableInterrupts();
__OSSetInterruptHandler(7, __DSPHandler);
__OSUnmaskInterrupts(OS_INTERRUPTMASK_DSP_DSP);
tmp = __DSPRegs[5];
tmp = (tmp & ~0xA8) | 0x800;
__DSPRegs[5] = tmp;
tmp = __DSPRegs[5];
__DSPRegs[5] = tmp = tmp & ~0xAC;
__DSP_first_task = __DSP_last_task = __DSP_curr_task = __DSP_tmp_task = NULL;
__DSP_init_flag = 1;
OSRestoreInterrupts(old);
}
BOOL DSPCheckInit(void) {
return __DSP_init_flag;
}
void DSPReset(void) {
BOOL old;
u16 tmp;
old = OSDisableInterrupts();
tmp = __DSPRegs[5];
tmp = (tmp & ~0xA8) | 0x800 | 1;
__DSPRegs[5] = tmp;
__DSP_init_flag = 0;
OSRestoreInterrupts(old);
}
void DSPHalt(void) {
BOOL old;
u16 tmp;
old = OSDisableInterrupts();
tmp = __DSPRegs[5];
tmp = (tmp & ~0xA8) | 4;
__DSPRegs[5] = tmp;
OSRestoreInterrupts(old);
}
void DSPUnhalt(void) {
BOOL old;
u16 tmp;
old = OSDisableInterrupts();
tmp = __DSPRegs[5];
tmp = (tmp & ~0xAC);
__DSPRegs[5] = tmp;
OSRestoreInterrupts(old);
}
u32 DSPGetDMAStatus(void) {
return (__DSPRegs[5] & (1 << 9));
}
DSPTaskInfo* DSPAddTask(DSPTaskInfo* task) {
BOOL old;
ASSERTMSGLINE(556, __DSP_init_flag == 1, "DSPAddTask(): DSP driver not initialized!\n");
old = OSDisableInterrupts();
__DSP_insert_task(task);
task->state = 0;
task->flags = 1;
OSRestoreInterrupts(old);
if (task == __DSP_first_task)
__DSP_boot_task(task);
return task;
}
DSPTaskInfo* DSPCancelTask(DSPTaskInfo* task) {
BOOL old;
ASSERTMSGLINE(592, __DSP_init_flag == 1, "DSPCancelTask(): DSP driver not initialized!\n");
old = OSDisableInterrupts();
task->flags |= 2;
OSRestoreInterrupts(old);
return task;
}
DSPTaskInfo* DSPAssertTask(DSPTaskInfo* task) {
s32 old;
ASSERTMSGLINE(623, __DSP_init_flag == 1, "DSPAssertTask(): DSP driver not initialized!\n");
ASSERTMSGLINE(624, task->flags & 1, "DSPAssertTask(): Specified task not in active task list!\n");
old = OSDisableInterrupts();
if (__DSP_curr_task == task) {
__DSP_rude_task = task;
__DSP_rude_task_pending = 1;
OSRestoreInterrupts(old);
return task;
}
if (task->priority < __DSP_curr_task->priority) {
__DSP_rude_task = task;
__DSP_rude_task_pending = 1;
if (__DSP_curr_task->state == 1) {
DSPAssertInt();
}
OSRestoreInterrupts(old);
return task;
}
OSRestoreInterrupts(old);
return NULL;
}
+9
View File
@@ -0,0 +1,9 @@
#include <revolution/dsp.h>
#include "__dsp.h"
void __DSP_debug_printf(const char* fmt, ...) {}
DSPTaskInfo* __DSPGetCurrentTask(void) {
return __DSP_curr_task;
}
+363
View File
@@ -0,0 +1,363 @@
#include <stddef.h>
#include <revolution.h>
#include <revolution/hw_regs.h>
#include "__dsp.h"
static u32 t0, t1, t2; // unused
DSPTaskInfo* __DSP_curr_task;
DSPTaskInfo* __DSP_first_task;
DSPTaskInfo* __DSP_last_task;
DSPTaskInfo* __DSP_tmp_task;
DSPTaskInfo* __DSP_rude_task;
int __DSP_rude_task_pending;
void __DSPHandler(__OSInterrupt intr, OSContext* context) {
u8 unused[4];
OSContext exceptionContext;
u16 tmp;
u32 mail;
tmp = __DSPRegs[5];
tmp = (tmp & ~0x28) | 0x80;
__DSPRegs[5] = tmp;
OSClearContext(&exceptionContext);
OSSetCurrentContext(&exceptionContext);
ASSERTMSGLINE(143, __DSP_curr_task != NULL, "__DSPHandler(): No current task! Someone set us up the bomb!\n");
while (DSPCheckMailFromDSP() == 0)
;
mail = DSPReadMailFromDSP();
if ((__DSP_curr_task->flags & (1<<(31-0x1E))) && (mail + 0x232F0000) == 2)
mail = 0xDCD10003;
switch (mail) {
case 0xDCD10000:
__DSP_curr_task->state = 1;
if (__DSP_curr_task->init_cb != NULL)
__DSP_curr_task->init_cb(__DSP_curr_task);
break;
case 0xDCD10001:
__DSP_curr_task->state = 1;
if (__DSP_curr_task->res_cb != NULL)
__DSP_curr_task->res_cb(__DSP_curr_task);
break;
case 0xDCD10002:
if (__DSP_rude_task_pending) {
if (__DSP_curr_task == __DSP_rude_task) {
DSPSendMailToDSP(0xCDD10003);
while (DSPCheckMailToDSP() != 0)
;
__DSP_rude_task = NULL;
__DSP_rude_task_pending = 0;
if (__DSP_curr_task->res_cb != NULL)
__DSP_curr_task->res_cb(__DSP_curr_task);
} else {
DSPSendMailToDSP(0xCDD10001);
while (DSPCheckMailToDSP() != 0)
;
__DSP_exec_task(__DSP_curr_task, __DSP_rude_task);
__DSP_curr_task->state = 2;
__DSP_curr_task = __DSP_rude_task;
__DSP_rude_task = NULL;
__DSP_rude_task_pending = 0;
}
} else {
if (__DSP_curr_task->next == NULL) {
if (__DSP_curr_task == __DSP_first_task) {
DSPSendMailToDSP(0xCDD10003);
while (DSPCheckMailToDSP() != 0)
;
if (__DSP_curr_task->res_cb != NULL)
__DSP_curr_task->res_cb(__DSP_curr_task);
} else {
DSPSendMailToDSP(0xCDD10001);
while (DSPCheckMailToDSP() != 0)
;
__DSP_exec_task(__DSP_curr_task, __DSP_first_task);
__DSP_curr_task->state = 2;
__DSP_curr_task = __DSP_first_task;
}
} else {
DSPSendMailToDSP(0xCDD10001);
while (DSPCheckMailToDSP() != 0)
;
__DSP_exec_task(__DSP_curr_task, __DSP_curr_task->next);
__DSP_curr_task->state = 2;
__DSP_curr_task = __DSP_curr_task->next;
}
}
break;
case 0xDCD10003:
if (__DSP_rude_task_pending) {
if (__DSP_curr_task->done_cb != NULL)
__DSP_curr_task->done_cb(__DSP_curr_task);
DSPSendMailToDSP(0xCDD10001);
while (DSPCheckMailToDSP() != 0)
;
__DSP_exec_task(NULL, __DSP_rude_task);
__DSP_remove_task(__DSP_curr_task);
__DSP_curr_task = __DSP_rude_task;
__DSP_rude_task = NULL;
__DSP_rude_task_pending = 0;
} else {
if (__DSP_curr_task->next == NULL) {
if (__DSP_curr_task == __DSP_first_task) {
if (__DSP_curr_task->done_cb != NULL)
__DSP_curr_task->done_cb(__DSP_curr_task);
DSPSendMailToDSP(0xCDD10002);
while (DSPCheckMailToDSP() != 0)
;
__DSP_curr_task->state = 3;
__DSP_remove_task(__DSP_curr_task);
} else {
if (__DSP_curr_task->done_cb != NULL)
__DSP_curr_task->done_cb(__DSP_curr_task);
DSPSendMailToDSP(0xCDD10001);
while (DSPCheckMailToDSP() != 0)
;
__DSP_curr_task->state = 3;
__DSP_exec_task(NULL, __DSP_first_task);
__DSP_curr_task = __DSP_first_task;
__DSP_remove_task(__DSP_last_task);
}
} else {
if (__DSP_curr_task->done_cb != NULL)
__DSP_curr_task->done_cb(__DSP_curr_task);
DSPSendMailToDSP(0xCDD10001);
while (DSPCheckMailToDSP() != 0)
;
__DSP_curr_task->state = 3;
__DSP_exec_task(NULL, __DSP_curr_task->next);
__DSP_curr_task = __DSP_curr_task->next;
__DSP_remove_task(__DSP_curr_task->prev);
}
}
break;
case 0xDCD10004:
if (__DSP_curr_task->req_cb != NULL)
__DSP_curr_task->req_cb(__DSP_curr_task);
break;
default:
ASSERTMSGLINEV(519, 0, "__DSPHandler(): Unknown msg from DSP 0x%08X - task sync failed!\n", mail);
}
OSClearContext(&exceptionContext);
OSSetCurrentContext(context);
}
void __DSP_exec_task(DSPTaskInfo* curr, DSPTaskInfo* next) {
ASSERTMSGLINE(555, next != NULL, "__DSP_exec_task(): NULL task. It is to weep.\n");
if (curr != NULL) {
DSPSendMailToDSP((u32)curr->dram_mmem_addr);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP(curr->dram_length);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP(curr->dram_addr);
while (DSPCheckMailToDSP() != 0)
;
} else {
DSPSendMailToDSP(0);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP(0);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP(0);
while (DSPCheckMailToDSP() != 0)
;
}
DSPSendMailToDSP((u32)next->iram_mmem_addr);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP(next->iram_length);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP(next->iram_addr);
while (DSPCheckMailToDSP() != 0)
;
if (next->state == 0) {
DSPSendMailToDSP(next->dsp_init_vector);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP(0);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP(0);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP(0);
while (DSPCheckMailToDSP() != 0)
;
} else {
DSPSendMailToDSP(next->dsp_resume_vector);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP((u32)next->dram_mmem_addr);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP(next->dram_length);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP(next->dram_addr);
while (DSPCheckMailToDSP() != 0)
;
}
}
void __DSP_boot_task(DSPTaskInfo* task) {
volatile u32 mail;
ASSERTMSGLINE(637, task != NULL, "__DSP_boot_task(): NULL task!\n");
while (DSPCheckMailFromDSP() == 0)
;
mail = DSPReadMailFromDSP();
ASSERTMSGLINEV(643, mail == 0x8071FEED, "__DSP_boot_task(): Failed to sync DSP on boot! (0x%08X)\n", mail);
DSPSendMailToDSP(0x80F3A001);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP((u32)task->iram_mmem_addr);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP(0x80F3C002);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP(task->iram_addr & 0xFFFF);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP(0x80F3A002);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP(task->iram_length);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP(0x80F3B002);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP(0);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP(0x80F3D001);
while (DSPCheckMailToDSP() != 0)
;
DSPSendMailToDSP(task->dsp_init_vector & 0xFFFF);
while (DSPCheckMailToDSP() != 0)
;
__DSP_debug_printf("DSP is booting task: 0x%08X\n", (u32)task);
__DSP_debug_printf("__DSP_boot_task() : IRAM MMEM ADDR: 0x%08X\n", (u32)task->iram_mmem_addr);
__DSP_debug_printf("__DSP_boot_task() : IRAM DSP ADDR : 0x%08X\n", task->iram_addr);
__DSP_debug_printf("__DSP_boot_task() : IRAM LENGTH : 0x%08X\n", task->iram_length);
__DSP_debug_printf("__DSP_boot_task() : DRAM MMEM ADDR: 0x%08X\n", task->dram_length);
__DSP_debug_printf("__DSP_boot_task() : Start Vector : 0x%08X\n", task->dsp_init_vector);
}
void __DSP_insert_task(DSPTaskInfo* task) {
DSPTaskInfo* temp;
if (__DSP_first_task == NULL) {
__DSP_curr_task = task;
__DSP_first_task = __DSP_last_task = task;
task->next = task->prev = NULL;
return;
}
temp = __DSP_first_task;
while (temp != NULL) {
if (task->priority < temp->priority) {
task->prev = temp->prev;
temp->prev = task;
task->next = temp;
if (task->prev == NULL)
__DSP_first_task = task;
else
task->prev->next = task;
break;
}
temp = temp->next;
}
if (temp == NULL) {
__DSP_last_task->next = task;
task->next = NULL;
task->prev = __DSP_last_task;
__DSP_last_task = task;
}
}
void __DSP_add_task(DSPTaskInfo* task) {
ASSERTMSGLINE(771, task != NULL, "__DSP_add_task(): Why are you adding a NULL task?\n");
if (__DSP_last_task == NULL) {
__DSP_curr_task = task;
__DSP_last_task = task;
__DSP_first_task = task;
task->next = task->prev = NULL;
} else {
__DSP_last_task->next = task;
task->next = NULL;
task->prev = __DSP_last_task;
__DSP_last_task = task;
}
task->state = 0;
__DSP_debug_printf("__DSP_add_task() : Added task : 0x%08X\n", (u32)task);
}
void __DSP_remove_task(DSPTaskInfo* task) {
ASSERTMSGLINE(816, task != NULL, "__DSP_remove_task(): NULL task! Why? WHY?!?!\n");
task->flags = 0;
task->state = 3;
if (__DSP_first_task == task) {
if (task->next != NULL) {
__DSP_first_task = task->next;
task->next->prev = NULL;
return;
}
__DSP_first_task = __DSP_last_task = __DSP_curr_task = NULL;
return;
}
if (__DSP_last_task == task) {
__DSP_last_task = task->prev;
task->prev->next = NULL;
__DSP_curr_task = __DSP_first_task;
return;
}
__DSP_curr_task = task->next;
task->prev->next = task->next;
task->next->prev = task->prev;
}
+320
View File
@@ -0,0 +1,320 @@
#include <revolution/esp.h>
#include <revolution/ipc/ipcclt.h>
#include <revolution/private/iosrestypes.h>
static s32 __esFd = -1;
s32 ESP_InitLib(void) {
s32 ret = 0;
if (__esFd < 0) {
__esFd = IOS_Open("/dev/es", 0);
if (__esFd < 0) {
ret = __esFd;
}
}
return ret;
}
s32 ESP_CloseLib(void) {
s32 ret = 0;
if (__esFd >= 0) {
ret = IOS_Close(__esFd);
if (ret == 0) {
__esFd = -1;
}
}
return ret;
}
s32 ESP_LaunchTitle(u64 titleID, ESTicketView* pTicketView) {
s32 ret = 0;
u8 buf[256] ATTRIBUTE_ALIGN(32);
IOSIoVector* vec = (IOSIoVector*)(buf + 208);
u64* id = (u64*)buf;
if (__esFd < 0) {
ret = -0x3F9;
goto out;
}
// check if ptr is aligned to 0x20
if ((u32)pTicketView & 31) {
ret = -0x3F9;
goto out;
}
*id = titleID;
vec[0].base = (u8*)id;
vec[0].length = 8;
vec[1].base = (u8*)pTicketView;
vec[1].length = 0xD8;
ret = IOS_IoctlvReboot(__esFd, 8, 2, 0, vec);
__esFd = -1;
out:
return ret;
}
s32 ESP_GetTicketViews(ESTitleId titleId, ESTicketView* ticketViewList, u32* ticketViewCnt) {
s32 rv = 0;
u8 __esBuf[256] ATTRIBUTE_ALIGN(32);
IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector));
ESTitleId* p1 = (ESTitleId*)__esBuf;
u32* p2 = (u32*)(__esBuf + 32);
if (__esFd < 0 || ticketViewCnt == NULL) {
rv = -1017;
goto out;
}
if (((u32)ticketViewList & 31)) {
rv = -1017;
goto out;
}
*p1 = titleId;
if (ticketViewList == NULL) {
v[0].base = (u8*)p1;
v[0].length = sizeof(ESTitleId);
v[1].base = (u8*)p2;
v[1].length = 4;
rv = IOS_Ioctlv(__esFd, 18, 1, 1, v);
if (rv == 0) {
*ticketViewCnt = *p2;
}
} else {
if (*ticketViewCnt == 0) {
rv = -1017;
goto out;
}
*p2 = *ticketViewCnt;
v[0].base = (u8*)p1;
v[0].length = sizeof(ESTitleId);
v[1].base = (u8*)p2;
v[1].length = 4;
v[2].base = (u8*)ticketViewList;
v[2].length = sizeof(ESTicketView) * (*ticketViewCnt);
rv = IOS_Ioctlv(__esFd, 19, 2, 1, v);
}
out:
return rv;
}
s32 ESP_DiGetTicketView(const void* ticket, ESTicketView* ticketView) {
s32 rv = 0;
u8 __esBuf[256] ATTRIBUTE_ALIGN(32);
IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector));
if (__esFd < 0 || ticketView == NULL) {
rv = -1017;
goto out;
}
if (((u32)ticket & 31) || ((u32)ticketView & 31)) {
rv = -1017;
goto out;
}
v[0].base = (u8*)ticket;
if (ticket == NULL) {
v[0].length = 0;
} else {
v[0].length = sizeof(ESTicket);
}
v[1].base = (u8*)ticketView;
v[1].length = sizeof(ESTicketView);
rv = IOS_Ioctlv(__esFd, 27, 1, 1, v);
out:
return rv;
}
s32 ESP_DiGetTmd(ESTitleMeta* tmd, u32* tmdSize) {
s32 rv = 0;
u8 __esBuf[256] ATTRIBUTE_ALIGN(32);
IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector));
u32* p1 = (u32*)__esBuf;
if (__esFd < 0 || tmdSize == NULL) {
rv = -1017;
goto out;
}
if (((u32)tmd & 31)) {
rv = -1017;
goto out;
}
if (tmd == NULL) {
v[0].base = (u8*)p1;
v[0].length = 4;
rv = IOS_Ioctlv(__esFd, 57, 0, 1, v);
if (rv == 0) {
*tmdSize = *p1;
}
} else {
if (*tmdSize == 0) {
rv = -1017;
goto out;
}
*p1 = *tmdSize;
v[0].base = (u8*)p1;
v[0].length = 4;
v[1].base = (u8*)tmd;
v[1].length = *tmdSize;
rv = IOS_Ioctlv(__esFd, 58, 1, 1, v);
}
out:
return rv;
}
s32 ESP_GetTmdView(ESTitleId titleId, ESTmdView* tmdView, u32* size) {
s32 rv = 0;
u8 __esBuf[256] ATTRIBUTE_ALIGN(32);
IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector));
ESTitleId* p1 = (ESTitleId*)__esBuf;
u32* p2 = (u32*)(__esBuf + 32);
if (__esFd < 0 || size == NULL) {
rv = -1017;
goto out;
}
if (((u32)tmdView & 31)) {
rv = -1017;
goto out;
}
*p1 = titleId;
if (tmdView == NULL) {
v[0].base = (u8*)p1;
v[0].length = sizeof(ESTitleId);
v[1].base = (u8*)p2;
v[1].length = 4;
rv = IOS_Ioctlv(__esFd, 20, 1, 1, v);
if (rv == 0) {
*size = *p2;
}
} else {
if (*size == 0) {
rv = -1017;
goto out;
}
*p2 = *size;
v[0].base = (u8*)p1;
v[0].length = sizeof(ESTitleId);
v[1].base = (u8*)p2;
v[1].length = 4;
v[2].base = (u8*)tmdView;
v[2].length = *size;
rv = IOS_Ioctlv(__esFd, 21, 2, 1, v);
}
out:
return rv;
}
s32 ESP_GetDataDir(ESTitleId titleId, char* dataDir) {
s32 rv = 0;
u8 __esBuf[256] ATTRIBUTE_ALIGN(32);
IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector));
ESTitleId* p1 = (ESTitleId*)__esBuf;
if (__esFd < 0 || dataDir == NULL) {
rv = -1017;
goto out;
}
if (((u32)dataDir & 31)) {
rv = -1017;
goto out;
}
*p1 = titleId;
v[0].base = (u8*)p1;
v[0].length = sizeof(ESTitleId);
v[1].base = (u8*)dataDir;
v[1].length = 0x1E;
rv = IOS_Ioctlv(__esFd, 29, 1, 1, v);
out:
return rv;
}
s32 ESP_GetTitleId(ESTitleId* titleId) {
s32 rv = 0;
u8 __esBuf[256] ATTRIBUTE_ALIGN(32);
IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector));
if (__esFd < 0 || titleId == NULL) {
rv = -1017;
goto out;
}
v[0].base = __esBuf;
v[0].length = sizeof(ESTitleId);
rv = IOS_Ioctlv(__esFd, 32, 0, 1, v);
if (rv == 0) {
*titleId = *(ESTitleId*)__esBuf;
}
out:
return rv;
}
s32 ESP_GetConsumption(ESTicketId ticketId, ESLpEntry* entries, u32* nEntries) {
s32 rv = 0;
u8 __esBuf[256] ATTRIBUTE_ALIGN(32);
IOSIoVector* v = (IOSIoVector*)(__esBuf + 256 - 6 * sizeof(IOSIoVector));
ESTicketId* p1 = (ESTicketId*)__esBuf;
u32* p2 = (u32*)(__esBuf + 32);
if (__esFd < 0) {
rv = -1017;
goto out;
}
if (((u32)entries & 31)) {
rv = -1017;
goto out;
}
*p1 = ticketId;
v[0].base = (u8*)p1;
v[0].length = sizeof(ESTicketId);
if (entries == NULL) {
v[1].base = NULL;
v[1].length = 0;
} else {
v[1].base = (u8*)entries;
v[1].length = sizeof(ESLpEntry) * (*nEntries);
*p2 = *nEntries;
}
v[2].base = (u8*)p2;
v[2].length = 4;
rv = IOS_Ioctlv(__esFd, 22, 1, 2, v);
*nEntries = *p2;
out:
return rv;
}
+148
View File
@@ -0,0 +1,148 @@
#include <revolution/euart.h>
#include <revolution/exi.h>
#include <revolution/os.h>
static BOOL __EUARTInitialized = FALSE;
static EUARTError __EUARTLastErrorCode = EUART_ERROR_NONE;
static BOOL __EUARTSendStop = FALSE;
static u32 Enabled = 0;
BOOL EUARTInit(void) {
BOOL enabled;
u8 val;
if (__EUARTInitialized) {
return TRUE;
}
if (!(OSGetConsoleType() & 0x10000000)) {
__EUARTLastErrorCode = EUART_ERROR_CANNOT_USE;
return FALSE;
}
enabled = OSDisableInterrupts();
val = -14;
if (!EXIWriteReg(0, 1, 0xB0000000, &val, 1)) {
__EUARTLastErrorCode = EUART_ERROR_INTERNAL;
OSRestoreInterrupts(enabled);
return FALSE;
}
val = -13;
if (!EXIWriteReg(0, 1, 0xB0000000, &val, 1)) {
__EUARTLastErrorCode = EUART_ERROR_INTERNAL;
OSRestoreInterrupts(enabled);
return FALSE;
}
OSRestoreInterrupts(enabled);
__EUARTInitialized = TRUE;
__EUARTLastErrorCode = EUART_ERROR_NONE;
__EUARTSendStop = FALSE;
return TRUE;
}
UARTError InitializeUART(UARTBaudRate rate) {
if (!(OSGetConsoleType() & 0x10000000)) {
Enabled = 0;
return kUARTConfigurationError;
} else {
Enabled = 0xA5FF005A;
return kUARTNoError;
}
}
static int QueueLength(void) {
u32 cmd, txCnt;
if (!EXISelect(0, 1, __EXIFreq)) {
return -1;
}
cmd = 0x30000100;
EXIImm(0, &cmd, 4, 1, NULL);
EXISync(0);
EXIImm(0, &txCnt, sizeof(txCnt), 0, NULL);
EXISync(0);
EXIDeselect(0);
return 32 - (u8)((txCnt >> 24) & 0x3F);
}
UARTError WriteUARTN(const void* buf, unsigned long len) {
u32 cmd;
int qLen;
UARTError error;
char* sendData = (char*)buf;
u32 uart_txd;
if (Enabled != 0xA5FF005A) {
return kUARTConfigurationError;
}
if (!__EUARTInitialized) {
if (!EUARTInit()) {
return kUARTConfigurationError;
}
}
if (!__EUARTInitialized) {
__EUARTLastErrorCode = EUART_ERROR_UNINITIALIZED;
return kUARTConfigurationError;
}
if (!EXILock(0, 1, 0)) {
return kUARTNoError;
}
{
char* p;
for (p = sendData; (p - buf) < len; p++) {
if (*p == '\n') {
*p = '\r';
}
}
}
error = kUARTNoError;
cmd = 0xB0000100;
while (len != 0) {
qLen = QueueLength();
if (qLen < 0) {
error = kUARTBufferOverflow;
break;
}
if (qLen != 32) {
continue;
}
if (!EXISelect(0, 1, __EXIFreq)) {
error = kUARTBufferOverflow;
break;
}
EXIImm(0, &cmd, 4, 1, NULL);
EXISync(0);
while ((qLen > 0) && (len > 0)) {
uart_txd = (u32)((*sendData & 0xFF) << 24);
EXIImm(0, &uart_txd, 4, 1, NULL);
EXISync(0);
sendData++;
qLen--;
len--;
}
EXIDeselect(0);
}
EXIUnlock(0);
return error;
}
+876
View File
@@ -0,0 +1,876 @@
#include <revolution.h>
#define REG_MAX 5
#define REG(chan, idx) (__EXIRegs[((chan) * REG_MAX) + (idx)])
#define STATE_IDLE 0
#define STATE_DMA 1
#define STATE_IMM 2
#define STATE_BUSY 3
#define STATE_SELECTED 4
#define STATE_ATTACHED 8
#define STATE_LOCKED 16
#define MAX_CHAN 3
#define MAX_IMM 4
#define MAX_TYPE 3
#define MAX_DEV 3
#define MAX_FREQ 6
#define EXI_0LENGTH_EXILENGTH_MASK 0xFFFFFFE0
#ifdef SDK_AUG2010
#define BUILD_DATE "Aug 23 2010"
#if DEBUG
#define BUILD_TIME "17:24:52"
#else
#define BUILD_TIME "17:33:06"
#endif
#elif SDK_SEP2006
#define BUILD_DATE "Sep 21 2006"
#define BUILD_TIME "14:32:13"
#endif
#ifdef SDK_AUG2010
#if DEBUG
const char* __EXIVersion = "<< RVL_SDK - EXI \tdebug build: "BUILD_DATE" "BUILD_TIME" (0x4302_145) >>";
#else
const char* __EXIVersion = "<< RVL_SDK - EXI \trelease build: "BUILD_DATE" "BUILD_TIME" (0x4302_145) >>";
#endif
#elif SDK_SEP2006
const char* __EXIVersion = "<< RVL_SDK - EXI \trelease build: "BUILD_DATE" "BUILD_TIME" (0x4200_60422) >>";
#endif
static EXIControl Ecb[3];
static u32 IDSerialPort1;
// external functions
extern void __OSEnableBarnacle(s32 chan, u32 dev);
// prototypes
u32 EXIClearInterrupts(s32 chan, int exi, int tc, int ext);
static int __EXIProbe(s32 chan);
static void SetExiInterruptMask(s32 chan, EXIControl* exi) {
EXIControl* exi2;
exi2 = &Ecb[2];
switch (chan) {
case 0:
if ((exi->exiCallback == 0 && exi2->exiCallback == 0) || (exi->state & STATE_LOCKED)) {
__OSMaskInterrupts(OS_INTERRUPTMASK_EXI_0_EXI | OS_INTERRUPTMASK_EXI_2_EXI);
} else {
__OSUnmaskInterrupts(OS_INTERRUPTMASK_EXI_0_EXI | OS_INTERRUPTMASK_EXI_2_EXI);
}
break;
case 1:
if (exi->exiCallback == 0 || (exi->state & STATE_LOCKED)) {
__OSMaskInterrupts(OS_INTERRUPTMASK_EXI_1_EXI);
} else {
__OSUnmaskInterrupts(OS_INTERRUPTMASK_EXI_1_EXI);
}
break;
case 2:
if (__OSGetInterruptHandler(__OS_INTERRUPT_PI_DEBUG) == 0 || (exi->state & STATE_LOCKED)) {
__OSMaskInterrupts(OS_INTERRUPTMASK_PI_DEBUG);
} else {
__OSUnmaskInterrupts(OS_INTERRUPTMASK_PI_DEBUG);
}
break;
}
}
static void CompleteTransfer(s32 chan) {
EXIControl* exi;
u8* buf;
u32 data;
int i;
int len;
exi = &Ecb[chan];
ASSERTLINE(395, 0 <= chan && chan < MAX_CHAN);
if (exi->state & STATE_BUSY) {
if (exi->state & STATE_IMM) {
if (exi->immLen != 0) {
len = exi->immLen;
buf = exi->immBuf;
data = __EXIRegs[(chan * 5) + 4];
for(i = 0; i < len; i++) {
*buf++ = data >> ((3 - i) * 8);
}
}
}
exi->state &= ~STATE_BUSY;
}
}
int EXIImm(s32 chan, void* buf, s32 len, u32 type, EXICallback callback) {
EXIControl* exi;
BOOL enabled;
exi = &Ecb[chan];
ASSERTLINE(434, exi->state & STATE_SELECTED);
ASSERTLINE(435, 0 <= chan && chan < MAX_CHAN);
ASSERTLINE(436, 0 < len && len <= MAX_IMM);
ASSERTLINE(437, type < MAX_TYPE);
enabled = OSDisableInterrupts();
if ((exi->state & STATE_BUSY) || !(exi->state & STATE_SELECTED)) {
OSRestoreInterrupts(enabled);
return 0;
}
exi->tcCallback = callback;
if (exi->tcCallback) {
EXIClearInterrupts(chan, 0, 1, 0);
__OSUnmaskInterrupts(0x200000U >> (chan * 3));
}
exi->state |= STATE_IMM;
if (type != 0) {
u32 data;
int i;
data = 0;
for(i = 0; i < len; i++) {
data |= ((u8*)buf)[i] << ((3 - i) * 8);
}
__EXIRegs[(chan * 5) + 4] = data;
}
exi->immBuf = buf;
exi->immLen = (type != 1) ? len : 0;
__EXIRegs[(chan * 5) + 3] = (type << 2) | 1 | ((len - 1) << 4);
OSRestoreInterrupts(enabled);
return 1;
}
int EXIImmEx(s32 chan, void* buf, s32 len, u32 mode) {
s32 xLen;
while (len) {
xLen = (len < 4) ? len : 4;
if (EXIImm(chan, buf, xLen, mode, 0) == 0) {
return 0;
}
if (EXISync(chan) == 0) {
return 0;
}
((u8*)buf) += xLen;
len -= xLen;
}
return 1;
}
int EXIDma(s32 chan, void* buf, s32 len, u32 type, EXICallback callback) {
EXIControl* exi;
BOOL enabled;
exi = &Ecb[chan];
ASSERTLINE(539, exi->state & STATE_SELECTED);
ASSERTLINE(540, OFFSET(buf, 32) == 0);
ASSERTLINE(541, 0 < len && OFFSET(len, 32) == 0);
ASSERTLINE(543, ((u32) len & ~EXI_0LENGTH_EXILENGTH_MASK) == 0);
ASSERTLINE(545, type == EXI_READ || type == EXI_WRITE);
enabled = OSDisableInterrupts();
if ((exi->state & STATE_BUSY) || !(exi->state & STATE_SELECTED)) {
OSRestoreInterrupts(enabled);
return 0;
}
exi->tcCallback = callback;
if ((u32)exi->tcCallback) {
EXIClearInterrupts(chan, 0, 1, 0);
__OSUnmaskInterrupts(0x200000U >> (chan * 3));
}
exi->state |= STATE_DMA;
__EXIRegs[(chan * 5) + 1] = (u32)buf & EXI_0LENGTH_EXILENGTH_MASK;
__EXIRegs[(chan * 5) + 2] = len;
__EXIRegs[(chan * 5) + 3] = (type * 4) | 3;
OSRestoreInterrupts(enabled);
return 1;
}
int EXISync(s32 chan) {
EXIControl* exi;
int rc;
BOOL enabled;
exi = &Ecb[chan];
rc = 0;
ASSERTLINE(595, 0 <= chan && chan < MAX_CHAN);
while ((exi->state & STATE_SELECTED)) {
if (!(__EXIRegs[(chan * 5) + 3] & 1)) {
enabled = OSDisableInterrupts();
if (exi->state & STATE_SELECTED) {
CompleteTransfer(chan);
if (__OSGetDIConfig() != 0xFF || (OSGetConsoleType() & 0xf0000000) == 0x20000000 || exi->immLen != 4 || (__EXIRegs[chan * 5] & 0x70) || (__EXIRegs[(chan * 5) + 4] != 0x01010000 && __EXIRegs[(chan * 5) + 4] != 0x05070000 && __EXIRegs[(chan * 5) + 4] != 0x04220001) || __OSDeviceCode == 0x8200) {
rc = 1;
}
}
OSRestoreInterrupts(enabled);
break;
}
}
ASSERTLINE(623, !(exi->state & STATE_BUSY));
return rc;
}
u32 EXIClearInterrupts(s32 chan, int exi, int tc, int ext) {
u32 cpr;
u32 prev;
ASSERTLINE(644, 0 <= chan && chan < MAX_CHAN);
cpr = prev = __EXIRegs[(chan * 5)];
prev &= 0x7F5;
if (exi != 0) {
prev |= 2;
}
if (tc != 0) {
prev |= 8;
}
if (ext != 0) {
prev |= 0x800;
}
__EXIRegs[(chan * 5)] = prev;
return cpr;
}
EXICallback EXISetExiCallback(s32 chan, EXICallback exiCallback) {
EXIControl* exi;
EXICallback prev;
BOOL enabled;
exi = &Ecb[chan];
ASSERTLINE(678, 0 <= chan && chan < MAX_CHAN);
enabled = OSDisableInterrupts();
prev = exi->exiCallback;
exi->exiCallback = exiCallback;
if (chan != 2) {
SetExiInterruptMask(chan, exi);
} else {
SetExiInterruptMask(0, &Ecb[0]);
}
OSRestoreInterrupts(enabled);
return prev;
}
void EXIProbeReset() {
__gUnknown800030C0[0] = __gUnknown800030C0[1] = 0;
Ecb[0].idTime = Ecb[1].idTime = 0;
__EXIProbe(0);
__EXIProbe(1);
}
static int __EXIProbe(s32 chan) {
EXIControl* exi;
BOOL enabled;
int rc;
u32 cpr;
s32 t;
exi = &Ecb[chan];
ASSERTLINE(733, 0 <= chan && chan < MAX_CHAN);
if (chan == 2) {
return 1;
}
rc = 1;
enabled = OSDisableInterrupts();
cpr = __EXIRegs[(chan * 5)];
if (!(exi->state & STATE_ATTACHED)) {
if (cpr & 0x800) {
EXIClearInterrupts(chan, 0, 0, 1);
__gUnknown800030C0[chan] = exi->idTime = 0;
}
if (cpr & 0x1000) {
t = ((s32)(OSTicksToMilliseconds(OSGetTime()) / 100) + 1);
if (__gUnknown800030C0[chan] == 0) {
__gUnknown800030C0[chan] = t;
}
if (t - (s32)__gUnknown800030C0[chan] < 3) {
rc = 0;
}
} else {
__gUnknown800030C0[chan] = exi->idTime = 0;
rc = 0;
}
} else if(!(cpr & 0x1000) || (cpr & 0x800)) {
__gUnknown800030C0[chan] = exi->idTime = 0;
rc = 0;
}
OSRestoreInterrupts(enabled);
return rc;
}
int EXIProbe(s32 chan) {
EXIControl* exi = &Ecb[chan];
int rc;
u32 id;
rc = __EXIProbe(chan);
if (rc && !exi->idTime) {
rc = EXIGetID(chan, 0, &id) ? 1 : 0;
}
return rc;
}
s32 EXIProbeEx(s32 chan) {
if (EXIProbe(chan)) {
return 1;
}
if (__gUnknown800030C0[chan]) {
return 0;
}
return -1;
}
static int __EXIAttach(s32 chan, EXICallback extCallback) {
EXIControl* exi;
BOOL enabled;
exi = &Ecb[chan];
ASSERTLINE(838, 0 <= chan && chan < 2);
enabled = OSDisableInterrupts();
if ((exi->state & STATE_ATTACHED) || !__EXIProbe(chan)) {
OSRestoreInterrupts(enabled);
return 0;
}
EXIClearInterrupts(chan, 1, 0, 0);
exi->extCallback = extCallback;
__OSUnmaskInterrupts(0x100000U >> (chan * 3));
exi->state |= STATE_ATTACHED;
OSRestoreInterrupts(enabled);
return 1;
}
int EXIAttach(s32 chan, EXICallback extCallback) {
EXIControl* exi;
BOOL enabled;
int rc;
exi = &Ecb[chan];
ASSERTLINE(864, 0 <= chan && chan < 2);
EXIProbe(chan);
enabled = OSDisableInterrupts();
if (exi->idTime == 0) {
OSRestoreInterrupts(enabled);
return 0;
}
rc = __EXIAttach(chan, extCallback);
OSRestoreInterrupts(enabled);
return rc;
}
int EXIDetach(s32 chan) {
EXIControl* exi;
BOOL enabled;
exi = &Ecb[chan];
ASSERTLINE(898, 0 <= chan && chan < 2);
enabled = OSDisableInterrupts();
if (!(exi->state & STATE_ATTACHED)) {
OSRestoreInterrupts(enabled);
return 1;
}
if ((exi->state & STATE_LOCKED) && (exi->dev == 0)) {
OSRestoreInterrupts(enabled);
return 0;
}
exi->state &= ~STATE_ATTACHED;
__OSMaskInterrupts(0x500000U >> (chan * 3));
OSRestoreInterrupts(enabled);
return 1;
}
int EXISelectSD(s32 chan, u32 dev, u32 freq) {
EXIControl* exi;
u32 cpr;
BOOL enabled;
exi = &Ecb[chan];
ASSERTLINE(908, 0 <= chan && chan < MAX_CHAN);
ASSERTLINE(909, chan == 0 && dev < MAX_DEV || dev == 0);
ASSERTLINE(910, freq < MAX_FREQ);
ASSERTLINE(911, !(exi->state & STATE_SELECTED));
enabled = OSDisableInterrupts();
if ((exi->state & STATE_SELECTED) || ((chan != 2) && (((dev == 0) && !(exi->state & STATE_ATTACHED) && (EXIProbe(chan) == 0)) || !(exi->state & STATE_LOCKED) || (exi->dev != dev)))) {
OSRestoreInterrupts(enabled);
return 0;
}
exi->state |= STATE_SELECTED;
cpr = __EXIRegs[(chan * 5)];
cpr &= 0x405;
cpr |= freq * 0x10;
__EXIRegs[(chan * 5)] = cpr;
if (exi->state & STATE_ATTACHED) {
switch (chan) {
case 0:
__OSMaskInterrupts(0x100000U);
break;
case 1:
__OSMaskInterrupts(0x20000U);
break;
}
}
OSRestoreInterrupts(enabled);
return 1;
}
int EXISelect(s32 chan, u32 dev, u32 freq) {
EXIControl* exi;
u32 cpr;
BOOL enabled;
exi = &Ecb[chan];
ASSERTLINE(996, 0 <= chan && chan < MAX_CHAN);
ASSERTLINE(997, chan == 0 && dev < MAX_DEV || dev == 0);
ASSERTLINE(998, freq < MAX_FREQ);
ASSERTLINE(999, !(exi->state & STATE_SELECTED));
enabled = OSDisableInterrupts();
if ((exi->state & STATE_SELECTED) || ((chan != 2) && (((dev == 0) && !(exi->state & STATE_ATTACHED) && (__EXIProbe(chan) == 0)) || !(exi->state & STATE_LOCKED) || (exi->dev != dev)))) {
OSRestoreInterrupts(enabled);
return 0;
}
exi->state |= STATE_SELECTED;
cpr = __EXIRegs[(chan * 5)];
cpr &= 0x405;
cpr |= (((1 << dev) << 7) | (freq * 0x10));
__EXIRegs[(chan * 5)] = cpr;
if (exi->state & STATE_ATTACHED) {
switch (chan) {
case 0:
__OSMaskInterrupts(0x100000U);
break;
case 1:
__OSMaskInterrupts(0x20000U);
break;
}
}
OSRestoreInterrupts(enabled);
return 1;
}
int EXIDeselect(s32 chan) {
EXIControl* exi;
u32 cpr;
BOOL enabled;
exi = &Ecb[chan];
ASSERTLINE(1077, 0 <= chan && chan < MAX_CHAN);
enabled = OSDisableInterrupts();
if (!(exi->state & STATE_SELECTED)) {
OSRestoreInterrupts(enabled);
return 0;
}
exi->state &= ~STATE_SELECTED;
cpr = __EXIRegs[(chan * 5)];
__EXIRegs[(chan * 5)] = cpr & 0x405;
if (exi->state & STATE_ATTACHED) {
switch (chan) {
case 0:
__OSUnmaskInterrupts(0x100000U);
break;
case 1:
__OSUnmaskInterrupts(0x20000U);
break;
}
}
OSRestoreInterrupts(enabled);
if ((chan != 2) && (cpr & 0x80)) {
return __EXIProbe(chan) ? TRUE : FALSE;
}
return 1;
}
static void EXIIntrruptHandler(__OSInterrupt interrupt, OSContext* context) {
s32 chan;
EXIControl* exi;
EXICallback callback;
chan = (interrupt - 9) / 3;
ASSERTLINE(1150, 0 <= chan && chan < MAX_CHAN);
exi = &Ecb[chan];
EXIClearInterrupts(chan, 1, 0, 0);
callback = exi->exiCallback;
if (callback) {
OSContext exceptionContext;
OSClearContext(&exceptionContext);
OSSetCurrentContext(&exceptionContext);
callback(chan, context);
OSClearContext(&exceptionContext);
OSSetCurrentContext(context);
}
}
static void TCIntrruptHandler(__OSInterrupt interrupt, OSContext* context) {
s32 chan;
EXIControl* exi;
EXICallback callback;
chan = (interrupt - 10) / 3;
ASSERTLINE(1186, 0 <= chan && chan < MAX_CHAN);
exi = &Ecb[chan];
__OSMaskInterrupts(0x80000000U >> interrupt);
EXIClearInterrupts(chan, 0, 1, 0);
callback = exi->tcCallback;
if (callback) {
OSContext exceptionContext;
exi->tcCallback = NULL;
CompleteTransfer(chan);
OSClearContext(&exceptionContext);
OSSetCurrentContext(&exceptionContext);
callback(chan, context);
OSClearContext(&exceptionContext);
OSSetCurrentContext(context);
}
}
static void EXTIntrruptHandler(__OSInterrupt interrupt, OSContext* context) {
s32 chan;
EXIControl* exi;
EXICallback callback;
chan = (interrupt - 11) / 3;
ASSERTLINE(1226, 0 <= chan && chan < 2);
__OSMaskInterrupts(0x500000U >> (chan * 3));
exi = &Ecb[chan];
callback = exi->extCallback;
exi->state &= ~STATE_ATTACHED;
if (callback) {
OSContext exceptionContext;
OSClearContext(&exceptionContext);
OSSetCurrentContext(&exceptionContext);
exi->extCallback = NULL;
callback(chan, context);
OSClearContext(&exceptionContext);
OSSetCurrentContext(context);
}
}
void EXIInit() {
u32 id;
while (((REG(0, 3) & 1) == 1) || ((REG(1, 3) & 1) == 1) || ((REG(2, 3) & 1) == 1)) {}
__OSMaskInterrupts(0x7F8000U);
__EXIRegs[0] = 0;
__EXIRegs[5] = 0;
__EXIRegs[10] = 0;
__EXIRegs[0] = 0x2000;
__OSSetInterruptHandler(9, EXIIntrruptHandler);
__OSSetInterruptHandler(10, TCIntrruptHandler);
__OSSetInterruptHandler(11, EXTIntrruptHandler);
__OSSetInterruptHandler(12, EXIIntrruptHandler);
__OSSetInterruptHandler(13, TCIntrruptHandler);
__OSSetInterruptHandler(14, EXTIntrruptHandler);
__OSSetInterruptHandler(15, EXIIntrruptHandler);
__OSSetInterruptHandler(16, TCIntrruptHandler);
EXIGetID(0, 2, &IDSerialPort1);
if (__OSInIPL) {
EXIProbeReset();
} else if (EXIGetID(0, 0, &id) && id == 0x7010000) {
__OSEnableBarnacle(1, 0);
} else if (EXIGetID(1, 0, &id) && id == 0x7010000) {
__OSEnableBarnacle(0, 2);
}
OSRegisterVersion(__EXIVersion);
}
int EXILock(s32 chan, u32 dev, EXICallback unlockedCallback) {
EXIControl* exi;
BOOL enabled;
int i;
exi = &Ecb[chan];
ASSERTLINE(1338, 0 <= chan && chan < MAX_CHAN);
ASSERTLINE(1339, chan == 0 && dev < MAX_DEV || dev == 0);
enabled = OSDisableInterrupts();
if (exi->state & STATE_LOCKED) {
if (unlockedCallback) {
ASSERTLINE(1345, chan == 0 && exi->items < (MAX_DEV - 1) || exi->items == 0);
for(i = 0; i < exi->items; i++) {
if (exi->queue[i].dev == dev) {
OSRestoreInterrupts(enabled);
return 0;
}
}
exi->queue[exi->items].callback = unlockedCallback;
exi->queue[exi->items].dev = dev;
exi->items++;
}
OSRestoreInterrupts(enabled);
return 0;
}
ASSERTLINE(1361, exi->items == 0);
exi->state |= STATE_LOCKED;
exi->dev = dev;
SetExiInterruptMask(chan, exi);
OSRestoreInterrupts(enabled);
return 1;
}
int EXIUnlock(s32 chan) {
EXIControl* exi;
BOOL enabled;
EXICallback unlockedCallback;
exi = &Ecb[chan];
ASSERTLINE(1385, 0 <= chan && chan < MAX_CHAN);
enabled = OSDisableInterrupts();
if (!(exi->state & STATE_LOCKED)) {
OSRestoreInterrupts(enabled);
return 0;
}
exi->state &= ~STATE_LOCKED;
SetExiInterruptMask(chan, exi);
if (exi->items > 0) {
unlockedCallback = exi->queue[0].callback;
if (--exi->items > 0) {
memmove(&exi->queue[0], &exi->queue[1], exi->items * 8);
}
unlockedCallback(chan, 0);
}
OSRestoreInterrupts(enabled);
return 1;
}
u32 EXIGetState(s32 chan) {
EXIControl* exi;
exi = &Ecb[chan];
ASSERTLINE(1343, 0 <= chan && chan < MAX_CHAN);
return exi->state;
}
static void UnlockedHandler(s32 chan, OSContext* context) {
u32 id;
EXIGetID(chan, 0, &id);
}
s32 EXIGetID(s32 chan, u32 dev, u32* id) {
EXIControl* exi = &Ecb[chan];
int err;
u32 cmd;
s32 startTime;
BOOL enabled;
ASSERTLINE(1459, 0 <= chan && chan < MAX_CHAN);
if (chan == 0 && dev == 2 && IDSerialPort1 != 0) {
*id = IDSerialPort1;
return 1;
}
if ((chan < 2) && (dev == 0)) {
if ((__EXIProbe(chan) == 0)) {
return 0;
}
if (exi->idTime == __gUnknown800030C0[chan]) {
*id = exi->id;
return exi->idTime;
}
if (!__EXIAttach(chan, NULL)) {
return 0;
}
startTime = __gUnknown800030C0[chan];
}
enabled = OSDisableInterrupts();
err = !EXILock(chan, dev, (chan < 2 && dev == 0) ? &UnlockedHandler : NULL);
if (err == 0) {
err = !EXISelect(chan, dev, 0);
if (err == 0) {
cmd = 0;
err |= !EXIImm(chan, &cmd, 2, 1, 0);
err |= !EXISync(chan);
err |= !EXIImm(chan, id, 4, 0, 0);
err |= !EXISync(chan);
err |= !EXIDeselect(chan);
}
EXIUnlock(chan);
}
OSRestoreInterrupts(enabled);
if ((chan < 2) && (dev == 0)) {
EXIDetach(chan);
enabled = OSDisableInterrupts();
err |= __gUnknown800030C0[chan] != startTime;
if (!err) {
exi->id = *id;
exi->idTime = startTime;
}
OSRestoreInterrupts(enabled);
return err ? 0 : exi->idTime;
}
return err ? 0 : 1;
}
s32 EXIGetType(s32 chan, u32 dev, u32* type) {
u32 _type;
s32 probe;
probe = EXIGetID(chan, dev, &_type);
if (!probe) {
return probe;
}
switch (_type & ~0xFF) {
case 0x04020300:
case EXI_ETHER:
case 0x04020100:
case EXI_MIC:
*type = (_type & ~0xFF);
return probe;
default:
switch (_type & ~0xFFFF) {
case 0x00000000:
if (!(_type & 0x3803)) {
switch (_type & 0xFC) {
case EXI_MEMORY_CARD_59:
case EXI_MEMORY_CARD_123:
case EXI_MEMORY_CARD_251:
case EXI_MEMORY_CARD_507:
case EXI_MEMORY_CARD_1019:
case EXI_MEMORY_CARD_2043:
*type = _type & 0xFC;
return probe;
}
}
break;
case EXI_IS_VIEWER:
*type = EXI_IS_VIEWER;
return probe;
}
*type = _type;
return probe;
}
}
char* EXIGetTypeString(u32 type) {
switch (type) {
case EXI_MEMORY_CARD_59:
return "Memory Card 59";
case EXI_MEMORY_CARD_123:
return "Memory Card 123";
case EXI_MEMORY_CARD_251:
return "Memory Card 251";
case EXI_MEMORY_CARD_507:
return "Memory Card 507";
case EXI_MEMORY_CARD_1019:
return "Memory Card 1019";
case EXI_MEMORY_CARD_2043:
return "Memory Card 2043";
case EXI_USB_ADAPTER:
return "USB Adapter";
case EXI_NPDP_GDEV:
return "GDEV";
case EXI_MODEM:
return "Modem";
case EXI_MARLIN:
return "Marlin";
case EXI_AD16:
return "AD16";
case EXI_RS232C:
return "RS232C";
case 0x80000020:
case 0x80000080:
case 0x80000040:
case 0x80000008:
case 0x80000010:
case 0x80000004:
return "Net Card";
case EXI_ETHER_VIEWER:
return "Artist Ether";
case 0x4020100:
case 0x4020300:
case EXI_ETHER:
case 0x4220000:
return "Broadband Adapter";
case EXI_MIC:
return "Mic";
case EXI_STREAM_HANGER:
return "Stream Hanger";
case EXI_IS_VIEWER:
return "IS-DOL-VIEWER";
default:
return "Unknown";
}
}
+113
View File
@@ -0,0 +1,113 @@
#include <revolution/types.h>
#include <revolution/os.h>
#include <revolution/exi.h>
const u32 __EXIFreq = 4;
s32 EXIGetConsoleType(void) {
return 1;
}
void EXIWait(void) {
while (__OSDeviceCode == 0) {}
}
static u32 __EXISwap32(u32 val) {
return val >> 24 & 0x000000FF | val >> 8 & 0x0000FF00 | val << 8 & 0x00FF0000 | val << 24 & 0xFF000000;
}
BOOL EXIWriteReg(s32 chan, u32 dev, u32 exiCmd, void* reg, s32 size) {
BOOL ret = FALSE;
u32 reg32;
switch (size) {
case 1:
reg32 = (u32)((*((u8*)reg) & 0xFF) << 24);
break;
case 2:
reg32 = (u32)(((*((u16*)reg) & 0xFF) << 24) | ((*((u16*)reg) & 0xFF00) << 8));
break;
default:
reg32 = __EXISwap32(*((u32*)reg));
break;
}
ret |= !EXILock(chan, dev, 0);
if (ret) {
return FALSE;
}
ret |= !EXISelect(chan, dev, 4);
if (ret) {
EXIUnlock(chan);
return FALSE;
}
ret |= !EXIImm(chan, &exiCmd, 4, 1, NULL);
ret |= !EXISync(chan);
ret |= !EXIImm(chan, &reg32, 4, 1, NULL);
ret |= !EXISync(chan);
ret |= !EXIDeselect(chan);
ret |= !EXIUnlock(chan);
return !ret;
}
BOOL EXIReadRam(s32 chan, u32 dev, u32 exiCmd, void* buffer, s32 size, EXICallback callback) {
BOOL ret = FALSE;
ret |= !EXILock(chan, dev, NULL);
if (ret) {
return FALSE;
}
ret |= !EXISelect(chan, dev, 4);
if (ret) {
EXIUnlock(chan);
return FALSE;
}
ret |= !EXIImm(chan, &exiCmd, 4, 1, NULL);
ret |= !EXISync(chan);
ret |= !EXIDma(chan, buffer, size, EXI_READ, callback);
if (callback == NULL) {
ret |= !EXISync(chan);
ret |= !EXIDeselect(chan);
ret |= !EXIUnlock(chan);
}
return !ret;
}
BOOL EXIWriteRam(s32 chan, u32 dev, u32 exiCmd, void* buffer, s32 size, EXICallback callback) {
BOOL ret = FALSE;
ret |= !EXILock(chan, dev, NULL);
if (ret) {
return FALSE;
}
ret |= !EXISelect(chan, dev, 4);
if (ret) {
EXIUnlock(chan);
return FALSE;
}
ret |= !EXIImm(chan, &exiCmd, 4, 1, NULL);
ret |= !EXISync(chan);
ret |= !EXIDma(chan, buffer, size, EXI_WRITE, callback);
if (callback == NULL) {
ret |= !EXISync(chan);
ret |= !EXIDeselect(chan);
ret |= !EXIUnlock(chan);
}
return !ret;
}
+190
View File
@@ -0,0 +1,190 @@
#include <revolution/exi.h>
#include <revolution/os.h>
#include "__os.h"
static s32 Chan;
static u32 Dev;
static u32 BarnacleEnabled;
static u32 Enabled;
// prototypes
int InitializeUART(void);
int ReadUARTN(void);
int WriteUARTN(void *buf, u32 len);
void __OSEnableBarnacle(s32 chan, u32 dev);
static BOOL ProbeBarnacle(s32 chan, u32 dev, u32* revision) {
int err;
u32 cmd;
if (chan != 2 && dev == 0 && !EXIAttach(chan, NULL)) {
return FALSE;
}
err = !EXILock(chan, dev, NULL);
if (!err) {
err = !EXISelect(chan, dev, EXI_FREQ_1M);
if (!err) {
cmd = 0x20011300;
err = FALSE;
err |= !EXIImm(chan, &cmd, sizeof(cmd), EXI_WRITE, NULL);
err |= !EXISync(chan);
err |= !EXIImm(chan, revision, sizeof(revision), EXI_READ, NULL);
err |= !EXISync(chan);
err |= !EXIDeselect(chan);
}
EXIUnlock(chan);
}
if (chan != 2 && dev == 0) {
EXIDetach(chan);
}
if (err) {
return FALSE;
}
return (*revision != 0xFFFFFFFF) ? TRUE : FALSE;
}
void __OSEnableBarnacle(s32 chan, u32 dev) {
u32 id;
if (!EXIGetID(chan, dev, &id)) {
return;
}
switch (id) {
case EXI_MEMORY_CARD_59:
case EXI_MEMORY_CARD_123:
case EXI_MEMORY_CARD_251:
case EXI_MEMORY_CARD_507:
case EXI_USB_ADAPTER:
case EXI_NPDP_GDEV:
case EXI_MODEM:
case 0x03010000:
case 0x04020100:
case EXI_ETHER:
case 0x04020300:
case 0x04220000:
case EXI_RS232C:
case EXI_MIC:
case EXI_AD16:
case EXI_STREAM_HANGER:
case 0x80000004:
case 0x80000008:
case 0x80000010:
case 0x80000020:
case 0xFFFFFFFF:
break;
default:
if (ProbeBarnacle(chan, dev, &id)) {
Chan = chan;
Dev = dev;
Enabled = BarnacleEnabled = 0xA5FF005A;
break;
}
}
}
int InitializeUART(void) {
if (BarnacleEnabled == 0xA5FF005A) {
return 0;
}
if ((OSGetConsoleType() & 0x10000000) == 0) {
Enabled = 0;
return 2;
}
Chan = 0;
Dev = 1;
Enabled = 0xA5FF005A;
return 0;
}
int ReadUARTN(void) {
return 4;
}
static int QueueLength(void) {
u32 cmd;
if (EXISelect(Chan, Dev, 3) == 0) {
return -1;
}
cmd = 0x20010000;
EXIImm(Chan, &cmd, sizeof(cmd), EXI_WRITE, 0);
EXISync(Chan);
EXIImm(Chan, &cmd, 1, EXI_READ, 0);
EXISync(Chan);
EXIDeselect(Chan);
return 0x10 - (cmd >> 0x18);
}
int WriteUARTN(void *buf, u32 len) {
u32 cmd;
s32 xLen;
int qLen;
char* ptr;
int locked;
int error;
if ((Enabled - 0xA5FF0000) != 0x5A) {
return 2;
}
locked = EXILock(Chan, Dev, 0);
if (locked == 0) {
return 0;
} else {
ptr = (char*)buf;
}
while ((u32)ptr - (u32)buf < len) {
if (*(s8*)ptr == 0xA) {
*ptr = 0xD;
}
ptr++;
}
error = 0;
cmd = 0xA0010000;
while (len != 0) {
qLen = QueueLength();
if (qLen < 0) {
error = 3;
break;
}
if ((qLen >= 0xC) || (qLen >= len)) {
if (EXISelect(Chan, Dev, EXI_FREQ_8M) == 0) {
error = 3;
break;
}
EXIImm(Chan, &cmd, sizeof(cmd), EXI_WRITE, 0);
EXISync(Chan);
while((qLen != 0) && (len != 0)) {
if ((qLen < 4) && (qLen < len)) {
break;
}
xLen = len < 4 ? (long)len : 4;
EXIImm(Chan, buf, xLen, EXI_WRITE, 0);
(char*)buf += xLen;
len -= xLen;
qLen -= xLen;
EXISync(Chan);
}
EXIDeselect(Chan);
}
}
EXIUnlock(Chan);
return error;
}
+45
View File
@@ -0,0 +1,45 @@
#include <revolution/gd.h>
#include <revolution/os.h>
GDLObj* __GDCurrentDL = NULL;
static GDOverflowCb overflowcb = NULL;
void GDInitGDLObj(GDLObj* dl, void* start, u32 length) {
ASSERTMSGLINE(49, !((u32)start & 0x1F), "start must be aligned to 32 bytes");
ASSERTMSGLINE(50, !((u32)length & 0x1F), "length must be aligned to 32 bytes");
dl->start = start;
dl->ptr = start;
dl->top = (u8*)start + length;
dl->length = length;
}
void GDFlushCurrToMem(void) {
DCFlushRange(__GDCurrentDL->start, __GDCurrentDL->length);
}
void GDPadCurr32(void) {
u32 n;
n = (u32)__GDCurrentDL->ptr & 0x1F;
if (n != 0) {
for (; n < 32; n = n + 1) {
__GDWrite(0);
}
}
}
void GDOverflowed(void) {
if (overflowcb) {
(*overflowcb)();
} else {
ASSERTMSGLINE(86, 0, "GDWrite: display list overflowed");
}
}
void GDSetOverflowCallback(GDOverflowCb callback) {
overflowcb = callback;
}
GDOverflowCb GDGetOverflowCallback(void) {
return overflowcb;
}
+64
View File
@@ -0,0 +1,64 @@
#include <revolution/gd.h>
#include <revolution/os.h>
#define ROUND(n, a) (((u32)(n) + (a)-1) & ~((a)-1))
s32 GDReadDLFile(const char* fName, u32* numDLs, u32* numPLs, GDGList** DLDescArray, GDGList** PLDescArray) {
DVDFileInfo finfo;
u32 length;
u32 i;
u8* buf;
GDFileHeader* hdr;
*numDLs = *numPLs = 0;
*DLDescArray = *PLDescArray = NULL;
if (!DVDOpen(fName, &finfo)) {
OSReport("Can't open file %s\n", fName);
return -3;
}
length = finfo.length;
if (NULL == (buf = OSAlloc(ROUND(length, 0x20)))) {
OSReport("Alloc failed\n");
DVDClose(&finfo);
return -5;
}
if (DVDReadPrio(&finfo, buf, ROUND(length, 0x20), 0, 2) != ROUND(length, 0x20)) {
OSReport("Error occurred when reading %s\n", fName);
DVDClose(&finfo);
OSFree(buf);
return -2;
}
DVDClose(&finfo);
hdr = (GDFileHeader*)buf;
if (hdr->versionNumber != GD_FILE_VERSION_NUMBER) {
OSReport("Bad version number for GDL file %s\n", fName);
OSFree(buf);
return -4;
}
*numDLs = hdr->numDLs;
*numPLs = hdr->numPLs;
// Loaded pointers are relative to disc start, remap
// them to be relative to RAM start
*DLDescArray = (GDGList*)((u32)hdr->DLDescArray + (u32)hdr);
*PLDescArray = (GDGList*)((u32)hdr->PLDescArray + (u32)hdr);
// And internal pointers too
for (i = 0; i < *numDLs; ++i) {
(*DLDescArray)[i].ptr = (void*)((u32)hdr + (u32)(*DLDescArray)[i].ptr);
}
for (i = 0; i < *numPLs; ++i) {
(*PLDescArray)[i].ptr = (void*)((u32)hdr + (u32)(*PLDescArray)[i].ptr);
}
return 0;
}
+418
View File
@@ -0,0 +1,418 @@
#include <revolution/gd.h>
#include <revolution/os.h>
void GDSetVtxDescv(const GXVtxDescList* attrPtr) {
u32 nnorms = 0;
u32 ncols = 0;
u32 ntexs = 0;
u32 pnMtxIdx = GX_NONE;
u32 txMtxIdxMask = 0;
u32 posn = GX_DIRECT;
u32 norm = GX_NONE;
u32 col0 = GX_NONE;
u32 col1 = GX_NONE;
u32 tex0 = GX_NONE;
u32 tex1 = GX_NONE;
u32 tex2 = GX_NONE;
u32 tex3 = GX_NONE;
u32 tex4 = GX_NONE;
u32 tex5 = GX_NONE;
u32 tex6 = GX_NONE;
u32 tex7 = GX_NONE;
for (; attrPtr->attr != GX_VA_NULL; ++attrPtr) {
ASSERTMSGLINE(103, attrPtr->attr >= GX_VA_PNMTXIDX && attrPtr->attr <= GX_VA_MAX_ATTR, "GDSetVtxDescv: invalid attribute");
ASSERTMSGLINE(107, attrPtr->type >= GX_NONE && attrPtr->type <= GX_INDEX16, "GDSetVtxDescv: invalid type");
ASSERTMSGLINE(113, attrPtr->attr >= GX_VA_PNMTXIDX && attrPtr->attr <= GX_VA_TEX7MTXIDX ? (attrPtr->type == 0 || attrPtr->type == 1) : TRUE, "GDSetVtxDescv: invalid type for given attribute");
switch (attrPtr->attr) {
case GX_VA_PNMTXIDX:
pnMtxIdx = attrPtr->type;
break;
case GX_VA_TEX0MTXIDX:
txMtxIdxMask = (txMtxIdxMask & ~0x1) | (attrPtr->type << 0);
break;
case GX_VA_TEX1MTXIDX:
txMtxIdxMask = (txMtxIdxMask & ~0x2) | (attrPtr->type << 1);
break;
case GX_VA_TEX2MTXIDX:
txMtxIdxMask = (txMtxIdxMask & ~0x4) | (attrPtr->type << 2);
break;
case GX_VA_TEX3MTXIDX:
txMtxIdxMask = (txMtxIdxMask & ~0x8) | (attrPtr->type << 3);
break;
case GX_VA_TEX4MTXIDX:
txMtxIdxMask = (txMtxIdxMask & ~0x10) | (attrPtr->type << 4);
break;
case GX_VA_TEX5MTXIDX:
txMtxIdxMask = (txMtxIdxMask & ~0x20) | (attrPtr->type << 5);
break;
case GX_VA_TEX6MTXIDX:
txMtxIdxMask = (txMtxIdxMask & ~0x40) | (attrPtr->type << 6);
break;
case GX_VA_TEX7MTXIDX:
txMtxIdxMask = (txMtxIdxMask & ~0x80) | (attrPtr->type << 7);
break;
case GX_VA_POS:
posn = attrPtr->type;
break;
case GX_VA_NRM:
if (attrPtr->type != GX_NONE) {
norm = attrPtr->type;
nnorms = 1;
}
break;
case GX_VA_NBT:
if (attrPtr->type != GX_NONE) {
norm = attrPtr->type;
nnorms = 2;
}
break;
case GX_VA_CLR0:
col0 = attrPtr->type;
ncols += (col0 != GX_NONE);
break;
case GX_VA_CLR1:
col1 = attrPtr->type;
ncols += (col1 != GX_NONE);
break;
case GX_VA_TEX0:
tex0 = attrPtr->type;
ntexs += (tex0 != GX_NONE);
break;
case GX_VA_TEX1:
tex1 = attrPtr->type;
ntexs += (tex1 != GX_NONE);
break;
case GX_VA_TEX2:
tex2 = attrPtr->type;
ntexs += (tex2 != GX_NONE);
break;
case GX_VA_TEX3:
tex3 = attrPtr->type;
ntexs += (tex3 != GX_NONE);
break;
case GX_VA_TEX4:
tex4 = attrPtr->type;
ntexs += (tex4 != GX_NONE);
break;
case GX_VA_TEX5:
tex5 = attrPtr->type;
ntexs += (tex5 != GX_NONE);
break;
case GX_VA_TEX6:
tex6 = attrPtr->type;
ntexs += (tex6 != GX_NONE);
break;
case GX_VA_TEX7:
tex7 = attrPtr->type;
ntexs += (tex7 != GX_NONE);
break;
}
}
GDWriteCPCmd(CP_REG_VCD_LO_ID, CP_REG_VCD_LO(pnMtxIdx, txMtxIdxMask, posn, norm, col0, col1));
GDWriteCPCmd(CP_REG_VCD_HI_ID, CP_REG_VCD_HI(tex0, tex1, tex2, tex3, tex4, tex5, tex6, tex7));
GDWriteXFCmd(XF_REG_INVERTEXSPEC_ID, XF_REG_INVTXSPEC(ncols, nnorms, ntexs));
}
void GDSetVtxAttrFmtv(GXVtxFmt vtxfmt, const GXVtxAttrFmtList* list) {
u32 posCnt = GX_POS_XYZ;
u32 posType = GX_F32;
u32 posFrac = 0;
u32 nrmCnt = GX_NRM_XYZ;
u32 nrmType = GX_F32;
u32 nrmIdx3 = 0;
u32 c0Cnt = GX_CLR_RGBA;
u32 c0Type = GX_RGBA8;
u32 c1Cnt = GX_CLR_RGBA;
u32 c1Type = GX_RGBA8;
u32 tx0Cnt = GX_TEX_ST;
u32 tx0Type = GX_F32;
u32 tx0Frac = 0;
u32 tx1Cnt = GX_TEX_ST;
u32 tx1Type = GX_F32;
u32 tx1Frac = 0;
u32 tx2Cnt = GX_TEX_ST;
u32 tx2Type = GX_F32;
u32 tx2Frac = 0;
u32 tx3Cnt = GX_TEX_ST;
u32 tx3Type = GX_F32;
u32 tx3Frac = 0;
u32 tx4Cnt = GX_TEX_ST;
u32 tx4Type = GX_F32;
u32 tx4Frac = 0;
u32 tx5Cnt = GX_TEX_ST;
u32 tx5Type = GX_F32;
u32 tx5Frac = 0;
u32 tx6Cnt = GX_TEX_ST;
u32 tx6Type = GX_F32;
u32 tx6Frac = 0;
u32 tx7Cnt = GX_TEX_ST;
u32 tx7Type = GX_F32;
u32 tx7Frac = 0;
ASSERTMSGLINE(233, vtxfmt < GX_MAX_VTXFMT, "GDSetVtxAttrFmtv: invalid vtx fmt");
for (; list->attr != GX_VA_NULL; ++list) {
ASSERTMSGLINE(239, (list->attr >= GX_VA_POS && list->attr <= GX_VA_TEX7) || list->attr == GX_VA_NBT, "GDSetVtxAttrFmtv: invalid attribute");
ASSERTMSGLINE(240, list->frac < 32, "GDSetVtxAttrFmtv: invalid frac value");
switch (list->attr) {
case GX_VA_POS:
posCnt = list->cnt;
posType = list->type;
posFrac = list->frac;
break;
case GX_VA_NRM:
case GX_VA_NBT:
nrmType = list->type;
if (list->cnt == GX_NRM_NBT3) {
nrmCnt = GX_NRM_NBT;
nrmIdx3 = 1;
} else {
nrmCnt = list->cnt;
nrmIdx3 = 0;
}
break;
case GX_VA_CLR0:
c0Cnt = list->cnt;
c0Type = list->type;
break;
case GX_VA_CLR1:
c1Cnt = list->cnt;
c1Type = list->type;
break;
case GX_VA_TEX0:
tx0Cnt = list->cnt;
tx0Type = list->type;
tx0Frac = list->frac;
break;
case GX_VA_TEX1:
tx1Cnt = list->cnt;
tx1Type = list->type;
tx1Frac = list->frac;
break;
case GX_VA_TEX2:
tx2Cnt = list->cnt;
tx2Type = list->type;
tx2Frac = list->frac;
break;
case GX_VA_TEX3:
tx3Cnt = list->cnt;
tx3Type = list->type;
tx3Frac = list->frac;
break;
case GX_VA_TEX4:
tx4Cnt = list->cnt;
tx4Type = list->type;
tx4Frac = list->frac;
break;
case GX_VA_TEX5:
tx5Cnt = list->cnt;
tx5Type = list->type;
tx5Frac = list->frac;
break;
case GX_VA_TEX6:
tx6Cnt = list->cnt;
tx6Type = list->type;
tx6Frac = list->frac;
break;
case GX_VA_TEX7:
tx7Cnt = list->cnt;
tx7Type = list->type;
tx7Frac = list->frac;
}
}
GDWriteCPCmd(vtxfmt + CP_REG_VAT_GRP0_ID, CP_REG_VAT_GRP0(posCnt, posType, posFrac, nrmCnt, nrmType, c0Cnt, c0Type, c1Cnt, c1Type, tx0Cnt, tx0Type, tx0Frac, 1, nrmIdx3));
GDWriteCPCmd(vtxfmt + CP_REG_VAT_GRP1_ID, CP_REG_VAT_GRP1(tx1Cnt, tx1Type, tx1Frac, tx2Cnt, tx2Type, tx2Frac, tx3Cnt, tx3Type, tx3Frac, tx4Cnt, tx4Type, 1));
GDWriteCPCmd(vtxfmt + CP_REG_VAT_GRP2_ID, CP_REG_VAT_GRP2(tx4Frac, tx5Cnt, tx5Type, tx5Frac, tx6Cnt, tx6Type, tx6Frac, tx7Cnt, tx7Type, tx7Frac));
}
void GDSetArray(GXAttr attr, void* base_ptr, u8 stride) {
s32 cpAttr = attr == GX_VA_NBT ? GX_VA_TEX0MTXIDX : attr - GX_VA_POS;
GDWriteCPCmd(cpAttr + CP_REG_ARRAYBASE_ID, OSCachedToPhysical(base_ptr));
GDWriteCPCmd(cpAttr + CP_REG_ARRAYSTRIDE_ID, stride);
}
void GDSetArrayRaw(GXAttr attr, u32 base_ptr_raw, u8 stride) {
s32 cpAttr = attr == GX_VA_NBT ? GX_VA_TEX0MTXIDX : attr - GX_VA_POS;
GDWriteCPCmd(cpAttr + CP_REG_ARRAYBASE_ID, base_ptr_raw);
GDWriteCPCmd(cpAttr + CP_REG_ARRAYSTRIDE_ID, stride);
}
void GDPatchArrayPtr(void* base_ptr) {
GDWrite_u32(OSCachedToPhysical(base_ptr));
}
void GDSetTexCoordGen(GXTexCoordID dst_coord, GXTexGenType func, GXTexGenSrc src_param, u8 normalize, u32 postmtx) {
u32 form;
u32 tgType;
u32 proj;
u32 row;
u32 embossRow;
u32 embossLit;
form = 0;
proj = 0;
row = 5;
embossRow = 5;
embossLit = 0;
ASSERTMSGLINE(445, dst_coord < GX_MAX_TEXCOORD, "GDSetTexCoordGen: invalid texcoord ID");
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:
embossRow = 0;
break;
case GX_TG_TEXCOORD1:
embossRow = 1;
break;
case GX_TG_TEXCOORD2:
embossRow = 2;
break;
case GX_TG_TEXCOORD3:
embossRow = 3;
break;
case GX_TG_TEXCOORD4:
embossRow = 4;
break;
case GX_TG_TEXCOORD5:
embossRow = 5;
break;
case GX_TG_TEXCOORD6:
embossRow = 6;
break;
default:
ASSERTMSGLINE(470, 0, "GDSetTexCoordGen: invalid texgen source");
break;
}
switch (func) {
case GX_TG_MTX2x4:
tgType = 0;
break;
case GX_TG_MTX3x4:
tgType = 0;
proj = 1;
break;
case GX_TG_BUMP0:
case GX_TG_BUMP1:
case GX_TG_BUMP2:
case GX_TG_BUMP3:
case GX_TG_BUMP4:
case GX_TG_BUMP5:
case GX_TG_BUMP6:
case GX_TG_BUMP7:
ASSERTMSGLINE(494, src_param >= GX_TG_TEXCOORD0 && src_param <= GX_TG_TEXCOORD6, "GDSetTexCoordGen: invalid emboss source");
tgType = 1;
embossLit = func - GX_TG_BUMP0;
break;
case GX_TG_SRTG:
if (src_param == GX_TG_COLOR0) {
tgType = 2;
} else {
tgType = 3;
}
break;
default:
ASSERTMSGLINE(508, 0, "GDSetTexCoordGen: invalid texgen function");
break;
}
GDWriteXFCmd(dst_coord + XF_REG_TEX0_ID, XF_REG_TEX(proj, form, tgType, row, embossRow, embossLit));
GDWriteXFCmd(dst_coord + XF_REG_DUALTEX0_ID, XF_REG_DUALTEX(postmtx - 0x40, normalize));
}
void GDSetCullMode(GXCullMode mode) {
static u8 cm2hw[4] = { 0, 2, 1, 3 };
GDWriteBPCmd(0xFE00C000);
GDWriteBPCmd(cm2hw[mode] << 14);
}
void GDSetGenMode(u8 nTexGens, u8 nChans, u8 nTevs) {
GDWriteBPCmd(0xFE003C3F);
GDWriteBPCmd(BP_GEN_MODE(nTexGens, nChans, nTevs - 1, 0, 0));
GDWriteXFCmd(XF_REG_NUMCOLORS_ID, nChans);
GDWriteXFCmd(XF_REG_NUMTEX_ID, nTexGens);
}
void GDSetGenMode2(u8 nTexGens, u8 nChans, u8 nTevs, u8 nInds, GXCullMode cm) {
static u8 cm2hw[4] = { 0, 2, 1, 3 };
GDWriteBPCmd(0xFE07FC3F);
GDWriteBPCmd(BP_GEN_MODE(nTexGens, nChans, nTevs - 1, cm2hw[cm], nInds));
GDWriteXFCmd(XF_REG_NUMCOLORS_ID, nChans);
GDWriteXFCmd(XF_REG_NUMTEX_ID, nTexGens);
}
void GDSetLPSize(u8 lineWidth, u8 pointSize, GXTexOffset lineOffset, GXTexOffset pointOffset, u8 lineHalfAspect) {
GDWriteBPCmd(BP_LP_SIZE(lineWidth, pointSize, lineOffset, pointOffset, lineHalfAspect, 0x22));
}
void GDSetCoPlanar(u8 enable) {
GDWriteBPCmd(0xFE080000);
GDWriteBPCmd(enable << 19);
}
+270
View File
@@ -0,0 +1,270 @@
#include <revolution/gd.h>
#include <revolution/os.h>
void GDSetTevIndirect(GXTevStageID tev_stage, GXIndTexStageID ind_stage,
GXIndTexFormat format, GXIndTexBiasSel bias_sel,
GXIndTexMtxID matrix_sel, GXIndTexWrap wrap_s,
GXIndTexWrap wrap_t, u8 add_prev, u8 utc_lod,
GXIndTexAlphaSel alpha_sel) {
GDWriteBPCmd(BP_TEV_INDIRECT(
ind_stage & 3,
format & 3,
bias_sel & 7,
alpha_sel & 3,
matrix_sel & 0xF,
wrap_s & 7,
wrap_t & 7,
utc_lod & 1,
add_prev & 1,
0x10 + (tev_stage & 0xF)
));
}
void GDSetIndTexMtx(GXIndTexMtxID mtx_id, const f32 offset[2][3], s8 scale_exp) {
u32 id_offset;
switch (mtx_id) {
case GX_ITM_0:
id_offset = 0;
break;
case GX_ITM_1:
id_offset = 3;
break;
case GX_ITM_2:
id_offset = 6;
break;
default:
ASSERTMSGLINE(111, 0, "GDSetIndTexMtx: Invalid matrix id");
break;
}
scale_exp += 17;
GDWriteBPCmd(BP_IND_MTX(
(s32)(offset[0][0] * 0x400) & 0x7FF,
(s32)(offset[1][0] * 0x400) & 0x7FF,
scale_exp & 3,
6 + id_offset
));
GDWriteBPCmd(BP_IND_MTX(
(s32)(offset[0][1] * 0x400) & 0x7FF,
(s32)(offset[1][1] * 0x400) & 0x7FF,
(scale_exp >> 2) & 3,
7 + id_offset
));
GDWriteBPCmd(BP_IND_MTX(
(s32)(offset[0][2] * 0x400) & 0x7FF,
(s32)(offset[1][2] * 0x400) & 0x7FF,
(scale_exp >> 4) & 3,
8 + id_offset
));
}
void GDSetIndTexCoordScale(GXIndTexStageID indStageEven, GXIndTexScale scaleS0,
GXIndTexScale scaleT0, GXIndTexScale scaleS1,
GXIndTexScale scaleT1) {
GDWriteBPCmd(BP_IND_TEXCOORD_SCALE(
scaleS0 & 0xF,
scaleT0 & 0xF,
scaleS1 & 0xF,
scaleT1 & 0xF,
0x25 + ((indStageEven >> 1) & 1)
));
}
void GDSetIndTexOrder(GXTexCoordID texCoord0, GXTexMapID texMap0,
GXTexCoordID texCoord1, GXTexMapID texMap1,
GXTexCoordID texCoord2, GXTexMapID texMap2,
GXTexCoordID texCoord3, GXTexMapID texMap3) {
GDWriteBPCmd(BP_IND_TEX_ORDER(
texMap0 & 7,
texCoord0 & 7,
texMap1 & 7,
texCoord1 & 7,
texMap2 & 7,
texCoord2 & 7,
texMap3 & 7,
texCoord3 & 7,
0x27
));
}
void GDSetTevDirect(GXTevStageID tev_stage) {
GDSetTevIndirect(tev_stage, GX_INDTEXSTAGE0, GX_ITF_8, GX_ITB_NONE, GX_ITM_OFF, GX_ITW_OFF, GX_ITW_OFF, 0, 0, GX_ITBA_OFF);
}
void GDSetTevIndWarp(GXTevStageID tev_stage, GXIndTexStageID ind_stage, u8 signed_offset, u8 replace_mode, GXIndTexMtxID matrix_sel) {
GXIndTexWrap wrap;
wrap = replace_mode ? GX_ITW_0 : GX_ITW_OFF;
GDSetTevIndirect(tev_stage,
ind_stage,
GX_ITF_8,
signed_offset ? GX_ITB_STU : GX_ITB_NONE,
matrix_sel,
wrap,
wrap,
0,
0,
GX_ITBA_OFF);
}
void GDSetTevIndTile(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];
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(268, 0, "GDSetTevIndTile: 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(280, 0, "GDSetTevIndTile: Invalid tilesize for T coordinate");
wrap_t = GX_ITW_OFF;
break;
}
mtx[0][0] = (f32)tilespacing_s / 0x400;
mtx[0][1] = mtx[0][2] = 0.0f;
mtx[1][1] = (f32)tilespacing_t / 0x400;
mtx[1][0] = mtx[1][2] = 0.0f;
GDSetIndTexMtx(matrix_sel, mtx, 10);
GDSetTevIndirect(tev_stage,
ind_stage,
format,
bias_sel,
matrix_sel,
wrap_s,
wrap_t,
0,
1,
alpha_sel);
}
void GDSetTevIndBumpST(GXTevStageID tev_stage, GXIndTexStageID ind_stage, GXIndTexMtxID matrix_sel) {
GXIndTexMtxID sm;
GXIndTexMtxID tm;
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(332, 0, "GDSetTevIndBumpST: Invalid matrix selection");
break;
}
GDSetTevIndirect(tev_stage,
ind_stage,
GX_ITF_8,
GX_ITB_ST,
sm,
GX_ITW_0,
GX_ITW_0,
0,
0,
GX_ITBA_OFF);
GDSetTevIndirect(tev_stage + 1,
ind_stage,
GX_ITF_8,
GX_ITB_ST,
tm,
GX_ITW_0,
GX_ITW_0,
1,
0,
GX_ITBA_OFF);
GDSetTevIndirect(tev_stage + 2,
ind_stage,
GX_ITF_8,
GX_ITB_NONE,
GX_ITM_OFF,
GX_ITW_OFF,
GX_ITW_OFF,
1,
0,
GX_ITBA_OFF);
}
void GDSetTevIndBumpXYZ(GXTevStageID tev_stage, GXIndTexStageID ind_stage, GXIndTexMtxID matrix_sel) {
GDSetTevIndirect(tev_stage,
ind_stage,
GX_ITF_8,
GX_ITB_STU,
matrix_sel,
GX_ITW_OFF,
GX_ITW_OFF,
0,
0,
GX_ITBA_OFF);
}
void GDSetTevIndRepeat(GXTevStageID tev_stage) {
GDSetTevIndirect(tev_stage,
GX_INDTEXSTAGE0,
GX_ITF_8,
GX_ITB_NONE,
GX_ITM_OFF,
GX_ITW_0,
GX_ITW_0,
1,
0,
GX_ITBA_OFF);
}
void __GDSetIndTexMask(u32 mask) {
GDWriteBPCmd(BP_IND_MASK(mask & 0xFF, 0xF));
}
+206
View File
@@ -0,0 +1,206 @@
#include <revolution/gd.h>
#include <math.h>
void GDSetLightAttn(GXLightID light, f32 a0, f32 a1, f32 a2, f32 k0, f32 k1, f32 k2) {
GDWriteXFCmdHdr(__GDLightID2Offset(light) + XF_LIGHT_ATTN_ID, 6);
GDWrite_f32(a0);
GDWrite_f32(a1);
GDWrite_f32(a2);
GDWrite_f32(k0);
GDWrite_f32(k1);
GDWrite_f32(k2);
}
void GDSetLightSpot(GXLightID light, f32 cutoff, GXSpotFn spot_func) {
f32 a0;
f32 a1;
f32 a2;
f32 r;
f32 d;
f32 cr;
if (cutoff <= 0.0f || cutoff > 90.0f) {
spot_func = 0;
}
r = M_PI * cutoff / 180.0f;
cr = cosf(r);
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;
}
GDWriteXFCmdHdr(__GDLightID2Offset(light) + XF_LIGHT_ATTN_ID, 3);
GDWrite_f32(a0);
GDWrite_f32(a1);
GDWrite_f32(a2);
}
void GDSetLightDistAttn(GXLightID light, f32 ref_dist, f32 ref_br, GXDistAttnFn dist_func) {
f32 k0;
f32 k1;
f32 k2;
if (ref_dist < 0.0f || ref_br <= 0.0f || ref_br >= 1.0f) {
dist_func = 0;
}
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_dist * (ref_br * ref_dist));
break;
case GX_DA_STEEP:
k0 = 1.0f;
k1 = 0.0f;
k2 = (1.0f - ref_br) / (ref_dist * (ref_br * ref_dist));
break;
case GX_DA_OFF:
default:
k0 = 1.0f;
k1 = 0.0f;
k2 = 0.0f;
break;
}
GDWriteXFCmdHdr(__GDLightID2Offset(light) + XF_LIGHT_DISTATTN_ID, 3);
GDWrite_f32(k0);
GDWrite_f32(k1);
GDWrite_f32(k2);
}
void GDSetLightColor(GXLightID light, GXColor color) {
GDWriteXFCmd(__GDLightID2Offset(light) + XF_LIGHT_COLOR_ID, color.r << 24 | color.g << 16 | color.b << 8 | color.a);
}
void GDSetLightPos(GXLightID light, f32 x, f32 y, f32 z) {
GDWriteXFCmdHdr(__GDLightID2Offset(light) + XF_LIGHT_POS_ID, 3);
GDWrite_f32(x);
GDWrite_f32(y);
GDWrite_f32(z);
}
void GDSetLightDir(GXLightID light, f32 nx, f32 ny, f32 nz) {
GDWriteXFCmdHdr(__GDLightID2Offset(light) + XF_LIGHT_DIR_ID, 3);
GDWrite_f32(nx);
GDWrite_f32(ny);
GDWrite_f32(nz);
}
void GDSetSpecularDirHA(GXLightID light, f32 nx, f32 ny, f32 nz, f32 hx, f32 hy, f32 hz) {
f32 px;
f32 py;
f32 pz;
px = 1000000000000000000.0f * -nx;
py = 1000000000000000000.0f * -ny;
pz = 1000000000000000000.0f * -nz;
GDWriteXFCmdHdr(__GDLightID2Offset(light) + XF_LIGHT_SPEC_DIR_ID, 6);
GDWrite_f32(px);
GDWrite_f32(py);
GDWrite_f32(pz);
GDWrite_f32(hx);
GDWrite_f32(hy);
GDWrite_f32(hz);
}
void GDSetSpecularDir(GXLightID light, f32 nx, f32 ny, f32 nz) {
f32 px;
f32 py;
f32 pz;
f32 hx;
f32 hy;
f32 hz;
f32 mag;
hx = -nx;
hy = -ny;
hz = 1.0f + -nz;
mag = hx * hx + hy * hy + hz * hz;
if (mag != 0.0f) {
mag = 1.0f / sqrtf(mag);
}
hx = hx * mag;
hy = hy * mag;
hz = hz * mag;
px = 1000000000000000000.0f * -nx;
py = 1000000000000000000.0f * -ny;
pz = 1000000000000000000.0f * -nz;
GDWriteXFCmdHdr(__GDLightID2Offset(light) + XF_LIGHT_SPEC_DIR_ID, 6);
GDWrite_f32(px);
GDWrite_f32(py);
GDWrite_f32(pz);
GDWrite_f32(hx);
GDWrite_f32(hy);
GDWrite_f32(hz);
}
void GDLoadLightObjIndx(u32 lt_obj_indx, GXLightID light) {
GDWriteXFIndxDCmd(__GDLightID2Offset(light) + XF_LIGHT_ID, 0x10, lt_obj_indx);
}
void GDSetChanAmbColor(GXChannelID chan, GXColor color) {
GDWriteXFCmd((chan & 1) + XF_REG_AMBIENT0_ID, color.r << 24 | color.g << 16 | color.b << 8 | color.a);
}
void GDSetChanMatColor(GXChannelID chan, GXColor color) {
GDWriteXFCmd((chan & 1) + XF_REG_MATERIAL0_ID, color.r << 24 | color.g << 16 | color.b << 8 | color.a);
}
void GDSetChanCtrl(GXChannelID chan, u8 enable, GXColorSrc amb_src, GXColorSrc mat_src, u32 light_mask, GXDiffuseFn diff_fn, GXAttnFn attn_fn) {
u32 reg;
reg = XF_REG_CHAN_CTRL(mat_src, enable, light_mask & 0xF, amb_src, attn_fn == GX_AF_SPEC ? GX_DF_NONE : diff_fn, attn_fn != GX_AF_NONE, attn_fn != GX_AF_SPEC, (light_mask >> 4) & 0xF);
GDWriteXFCmd((chan & 3) + XF_REG_COLOR0CNTRL_ID, reg);
if (chan == 4 || chan == 5) {
GDWriteXFCmd(chan + XF_REG_MATERIAL0_ID, reg);
}
}
+118
View File
@@ -0,0 +1,118 @@
#include <revolution/gd.h>
#include <revolution/os.h>
void GDSetFog(GXFogType type, f32 startz, f32 endz, f32 nearz, f32 farz, GXColor color) {
f32 A;
f32 B;
f32 B_mant;
f32 C;
f32 A_f;
u32 b_expn;
u32 b_m;
u32 a_hex;
u32 c_hex;
u32 fsel;
u32 proj;
ASSERTMSGLINE(62, farz >= 0.0f, "GDSetFog: The farz should be positive value");
ASSERTMSGLINE(63, farz >= nearz, "GDSetFog: The farz should be larger than nearz");
fsel = type & 7;
proj = (type >> 3) & 1;
if (proj != 0) {
if (farz == nearz || endz == startz) {
A_f = 0.0f;
C = 0.0f;
} else {
A = 1.0f / (endz - startz);
A_f = (farz - nearz) * A;
C = (startz - nearz) * A;
}
b_expn = 0;
b_m = 0;
} else {
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 = 1;
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_f = A / (1 << b_expn);
b_m = (u32) (8388638.0f * B_mant);
}
a_hex = *(u32*)&A_f;
c_hex = *(u32*)&C;
GDWriteBPCmd(BP_FOG_UNK0(a_hex >> 12, 0xEE));
GDWriteBPCmd(BP_FOG_UNK1(b_m, 0xEF));
GDWriteBPCmd(BP_FOG_UNK2(b_expn, 0xF0));
GDWriteBPCmd(BP_FOG_UNK3(c_hex >> 12, proj, fsel, 0xF1));
GDWriteBPCmd(BP_FOG_COLOR(color.r, color.g, color.b, 0xF2));
}
void GDSetBlendMode(GXBlendMode type, GXBlendFactor src_factor, GXBlendFactor dst_factor, GXLogicOp logic_op) {
GDWriteBPCmd(0xFE00FFE3);
GDWriteBPCmd(BP_BLEND_MODE(
type == GX_BM_BLEND || type == GX_BM_SUBTRACT,
type == GX_BM_LOGIC,
0,
0,
0,
dst_factor,
src_factor,
type == GX_BM_SUBTRACT,
logic_op,
0x41
));
}
void GDSetBlendModeEtc(GXBlendMode type, GXBlendFactor src_factor,
GXBlendFactor dst_factor, GXLogicOp logic_op,
u8 color_update_enable, u8 alpha_update_enable,
u8 dither_enable) {
GDWriteBPCmd(BP_BLEND_MODE(
type == GX_BM_BLEND || type == GX_BM_SUBTRACT,
type == GX_BM_LOGIC,
dither_enable,
color_update_enable,
alpha_update_enable,
dst_factor,
src_factor,
type == GX_BM_SUBTRACT,
logic_op,
0x41
));
}
void GDSetZMode(u8 compare_enable, GXCompare func, u8 update_enable) {
GDWriteBPCmd(BP_Z_MODE(compare_enable, func, update_enable, 0x40));
}
void GDSetDstAlpha(u8 enable, u8 alpha) {
GDWriteBPCmd(BP_DST_ALPHA(alpha, enable, 0x42));
}
void GDSetDrawSync(u16 token) {
GDWriteBPCmd(BP_TOKEN(token, 0x48));
GDWriteBPCmd(BP_TOKEN(token, 0x47));
}
+159
View File
@@ -0,0 +1,159 @@
#include <revolution/gd.h>
#include <revolution/os.h>
void GDSetTevOp(GXTevStageID stage, GXTevMode mode) {
GXTevColorArg carg = GX_CC_RASC;
GXTevAlphaArg aarg = GX_CA_RASA;
if (stage != GX_TEVSTAGE0) {
carg = GX_CC_CPREV;
aarg = GX_CA_APREV;
}
switch (mode) {
case GX_MODULATE:
GDSetTevColorCalc(stage, GX_CC_ZERO, GX_CC_TEXC, carg, GX_CC_ZERO, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV);
GDSetTevAlphaCalcAndSwap(stage, GX_CA_ZERO, GX_CA_TEXA, aarg, GX_CA_ZERO, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV, GX_TEV_SWAP0, GX_TEV_SWAP0);
break;
case GX_DECAL:
GDSetTevColorCalc(stage, carg, GX_CC_TEXC, GX_CC_TEXA, GX_CC_ZERO, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV);
GDSetTevAlphaCalcAndSwap(stage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, aarg, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV, GX_TEV_SWAP0, GX_TEV_SWAP0);
break;
case GX_BLEND:
GDSetTevColorCalc(stage, carg, GX_CC_ONE, GX_CC_TEXC, GX_CC_ZERO, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV);
GDSetTevAlphaCalcAndSwap(stage, GX_CA_ZERO, GX_CA_TEXA, aarg, GX_CA_ZERO, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV, GX_TEV_SWAP0, GX_TEV_SWAP0);
break;
case GX_REPLACE:
GDSetTevColorCalc(stage, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_TEXC, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV);
GDSetTevAlphaCalcAndSwap(stage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_TEXA, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV, GX_TEV_SWAP0, GX_TEV_SWAP0);
break;
case GX_PASSCLR:
GDSetTevColorCalc(stage, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, carg, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV);
GDSetTevAlphaCalcAndSwap(stage, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, aarg, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV, GX_TEV_SWAP0, GX_TEV_SWAP0);
break;
default:
ASSERTMSGLINE(110, 0, "GDSetTevOp: Invalid Tev Mode");
break;
}
}
void GDSetTevColorCalc(GXTevStageID stage, GXTevColorArg a, GXTevColorArg b,
GXTevColorArg c, GXTevColorArg d, GXTevOp op,
GXTevBias bias, GXTevScale scale, u8 clamp,
GXTevRegID out_reg) {
if (op <= GX_TEV_SUB) {
GDWriteBPCmd(BP_TEV_COLOR(d, c, b, a, bias, op & 1, clamp, scale, out_reg, stage * 2 + 0xC0));
} else {
GDWriteBPCmd(BP_TEV_COLOR(d, c, b, a, 3, op & 1, clamp, (op >> 1) & 3, out_reg, stage * 2 + 0xC0));
}
}
void GDSetTevAlphaCalcAndSwap(GXTevStageID stage, GXTevAlphaArg a,
GXTevAlphaArg b, GXTevAlphaArg c, GXTevAlphaArg d,
GXTevOp op, GXTevBias bias, GXTevScale scale,
u8 clamp, GXTevRegID out_reg,
GXTevSwapSel ras_sel, GXTevSwapSel tex_sel) {
if (op <= GX_TEV_SUB) {
GDWriteBPCmd(BP_TEV_ALPHA(ras_sel, tex_sel, d, c, b, a, bias, op & 1, clamp, scale, out_reg, stage * 2 + 0xC1));
} else {
GDWriteBPCmd(BP_TEV_ALPHA(ras_sel, tex_sel, d, c, b, a, 3, op & 1, clamp, (op >> 1) & 3, out_reg, stage * 2 + 0xC1));
}
}
void GDSetTevColor(GXTevRegID reg, GXColor color) {
u32 regRA;
u32 regBG;
regRA = BP_TEV_COLOR_REG_RA(color.r, color.a, 0, 0xE0 + reg * 2);
regBG = BP_TEV_COLOR_REG_BG(color.b, color.g, 0, 0xE1 + reg * 2);
GDWriteBPCmd(regRA);
GDWriteBPCmd(regBG);
GDWriteBPCmd(regBG);
GDWriteBPCmd(regBG);
}
void GDSetTevColorS10(GXTevRegID reg, GXColorS10 color) {
u32 regRA;
u32 regBG;
regRA = BP_TEV_COLOR_REG_RA(color.r & 0x7FF, color.a & 0x7FF, 0, 0xE0 + reg * 2);
regBG = BP_TEV_COLOR_REG_BG(color.b & 0x7FF, color.g & 0x7FF, 0, 0xE1 + reg * 2);
GDWriteBPCmd(regRA);
GDWriteBPCmd(regBG);
GDWriteBPCmd(regBG);
GDWriteBPCmd(regBG);
}
void GDSetTevKColor(GXTevKColorID reg, GXColor color) {
u32 regRA;
u32 regBG;
regRA = BP_TEV_COLOR_REG_RA(color.r, color.a, 1, 0xE0 + reg * 2);
regBG = BP_TEV_COLOR_REG_BG(color.b, color.g, 1, 0xE1 + reg * 2);
GDWriteBPCmd(regRA);
GDWriteBPCmd(regBG);
}
void GDSetTevKonstantSel(GXTevStageID evenStage, GXTevKColorSel kcsel0,
GXTevKAlphaSel kasel0, GXTevKColorSel kcsel1,
GXTevKAlphaSel kasel1) {
GDWriteBPCmd(0xFEFFFFF0);
GDWriteBPCmd(BP_TEV_KSEL(0, 0, kcsel0, kasel0, kcsel1, kasel1, evenStage / 2 + 0xF6));
}
void GDSetTevSwapModeTable(GXTevSwapSel table, GXTevColorChan red,
GXTevColorChan green, GXTevColorChan blue,
GXTevColorChan alpha) {
GDWriteBPCmd(0xFE00000F);
GDWriteBPCmd(BP_TEV_KSEL(red, green, 0, 0, 0, 0, table * 2 + 0xF6));
GDWriteBPCmd(0xFE00000F);
GDWriteBPCmd(BP_TEV_KSEL(blue, alpha, 0, 0, 0, 0, table * 2 + 0xF7));
}
void GDSetAlphaCompare(GXCompare comp0, u8 ref0, GXAlphaOp op, GXCompare comp1, u8 ref1) {
GDWriteBPCmd(BP_ALPHA_COMPARE(ref0, ref1, comp0, comp1, op, 0xF3));
}
void GDSetZTexture(GXZTexOp op, GXTexFmt fmt, u32 bias) {
u32 zfmt;
switch (fmt) {
case GX_TF_Z8:
zfmt = 0;
break;
case GX_TF_Z16:
zfmt = 1;
break;
case GX_TF_Z24X8:
zfmt = 2;
break;
default:
ASSERTMSGLINE(399, 0, "GDSetZTexture: Invalid format");
zfmt = 2;
break;
}
GDWriteBPCmd(BP_ZTEX_PARAMS_0(bias, 0xF4));
GDWriteBPCmd(BP_ZTEX_PARAMS_1(zfmt, op, 0xF5));
}
void GDSetTevOrder(GXTevStageID evenStage, GXTexCoordID coord0, GXTexMapID map0,
GXChannelID color0, GXTexCoordID coord1, GXTexMapID map1,
GXChannelID color1) {
static u8 c2r[] = { 0, 1, 0, 1, 0, 1, 7, 5, 6, 0, 0, 0, 0, 0, 0, 7 };
GDWriteBPCmd(BP_TEV_ORDER(
map0 & 7,
coord0 & 7,
map0 != GX_TEXMAP_NULL && !(map0 & GX_TEX_DISABLE),
c2r[color0 & 0xF],
map1 & 7,
coord1 & 7,
map1 != GX_TEXMAP_NULL && !(map1 & GX_TEX_DISABLE),
c2r[color1 & 0xF],
evenStage / 2 + 0x28
));
}
+104
View File
@@ -0,0 +1,104 @@
#include <revolution/gd.h>
#include <revolution/os.h>
u8 GD2HWFiltConv[] = {0, 4, 1, 5, 2, 6};
u8 GDTexMode0Ids[8] = {128, 129, 130, 131, 160, 161, 162, 163};
u8 GDTexMode1Ids[8] = {132, 133, 134, 135, 164, 165, 166, 167};
u8 GDTexImage0Ids[8] = {136, 137, 138, 139, 168, 169, 170, 171};
u8 GDTexImage1Ids[8] = {140, 141, 142, 143, 172, 173, 174, 175};
u8 GDTexImage2Ids[8] = {144, 145, 146, 147, 176, 177, 178, 179};
u8 GDTexImage3Ids[8] = {148, 149, 150, 151, 180, 181, 182, 183};
u8 GDTexTlutIds[8] = {152, 153, 154, 155, 184, 185, 186, 187};
void GDSetTexLookupMode(GXTexMapID id, GXTexWrapMode wrap_s,
GXTexWrapMode wrap_t, GXTexFilter min_filt,
GXTexFilter mag_filt, f32 min_lod, f32 max_lod,
f32 lod_bias, u8 bias_clamp, u8 do_edge_lod,
GXAnisotropy max_aniso) {
GDWriteBPCmd(BP_TEX_MODE0(wrap_s, wrap_t, mag_filt == TRUE, GD2HWFiltConv[min_filt], !do_edge_lod, (u8)(32.0f * lod_bias), max_aniso, bias_clamp, GDTexMode0Ids[id]));
GDWriteBPCmd(BP_TEX_MODE1((u8)(16.0f * min_lod), (u8)(16.0f * max_lod), GDTexMode1Ids[id]));
}
void GDSetTexImgAttr(GXTexMapID id, u16 width, u16 height, GXTexFmt format) {
GDWriteBPCmd(BP_IMAGE_ATTR(width - 1, height - 1, format, GDTexImage0Ids[id]));
}
void GDSetTexImgPtr(GXTexMapID id, void* image_ptr) {
GDWriteBPCmd(BP_IMAGE_PTR(OSCachedToPhysical(image_ptr) >> 5, GDTexImage3Ids[id]));
}
void GDSetTexImgPtrRaw(GXTexMapID id, u32 image_ptr_raw) {
GDWriteBPCmd(BP_IMAGE_PTR(image_ptr_raw, GDTexImage3Ids[id]));
}
void GDPatchTexImgPtr(void* image_ptr) {
GDWrite_u24(OSCachedToPhysical(image_ptr) >> 5);
}
void GDSetTexCached(GXTexMapID id, u32 tmem_even, GXTexCacheSize size_even,
u32 tmem_odd, GXTexCacheSize size_odd) {
GDWriteBPCmd(BP_TEX_CACHE_EVEN(tmem_even >> 5, size_even + 3, size_even + 3, 0, GDTexImage1Ids[id]));
if (size_odd != 3 && tmem_odd < 0x100000) {
GDWriteBPCmd(BP_TEX_CACHE_ODD(tmem_odd >> 5, size_odd + 3, size_odd + 3, GDTexImage2Ids[id]));
}
}
void GDSetTexPreLoaded(GXTexMapID id, u32 tmem_even, u32 tmem_odd) {
GDWriteBPCmd(BP_TEX_CACHE_EVEN(tmem_even >> 5, 0, 0, 1, GDTexImage1Ids[id]));
if (tmem_odd < 0x100000) {
GDWriteBPCmd(BP_TEX_CACHE_ODD(tmem_odd >> 5, 0, 0, GDTexImage2Ids[id]));
}
}
void GDSetTexTlut(GXTexMapID id, u32 tmem_addr, GXTlutFmt format) {
GDWriteBPCmd(BP_TEX_TLUT((tmem_addr - 0x80000) >> 9, format, GDTexTlutIds[id]));
}
void GDSetTexCoordScale(GXTexCoordID coord, u16 s_scale, u16 t_scale) {
GDWriteBPCmd(0xFE00FFFF);
GDWriteBPCmd(BP_TEXCOORD_S_SCALE(s_scale - 1, 0, 0, 0, 0, coord * 2 + 0x30));
GDWriteBPCmd(0xFE00FFFF);
GDWriteBPCmd(BP_TEXCOORD_T_SCALE(t_scale - 1, 0, 0, coord * 2 + 0x31));
}
void GDSetTexCoordScale2(GXTexCoordID coord, u16 s_scale, u8 s_bias,
u8 s_wrap, u16 t_scale, u8 t_bias, u8 t_wrap) {
GDWriteBPCmd(0xFE03FFFF);
GDWriteBPCmd(BP_TEXCOORD_S_SCALE(s_scale - 1, s_bias, s_wrap, 0, 0, coord * 2 + 0x30));
GDWriteBPCmd(BP_TEXCOORD_T_SCALE(t_scale - 1, t_bias, t_wrap, coord * 2 + 0x31));
}
void GDSetTexCoordScaleAndTOEs(GXTexCoordID coord, u16 s_scale, u8 s_bias,
u8 s_wrap, u16 t_scale, u8 t_bias, u8 t_wrap,
u8 line_offset, u8 point_offset) {
GDWriteBPCmd(BP_TEXCOORD_S_SCALE(s_scale - 1, s_bias, s_wrap, line_offset, point_offset, coord * 2 + 0x30));
GDWriteBPCmd(BP_TEXCOORD_T_SCALE(t_scale - 1, t_bias, t_wrap, coord * 2 + 0x31));
}
void GDLoadTlut(void* tlut_ptr, u32 tmem_addr, GXTlutSize size) {
ASSERTMSGLINE(488, !(tmem_addr & 0x1ff), "GDLoadTlut: invalid TMEM pointer");
ASSERTMSGLINE(489, size <= 0x400, "GDLoadTlut: invalid TLUT size");
GDWriteBPCmd(0xFEFFFF00);
GDWriteBPCmd(0xF000000);
GDWriteBPCmd(BP_LOAD_TLUT0(OSCachedToPhysical(tlut_ptr) >> 5, 0x64));
GDWriteBPCmd(BP_LOAD_TLUT1((tmem_addr - 0x80000) >> 9, size, 0x65));
GDWriteBPCmd(0xFEFFFF00);
GDWriteBPCmd(0xF000000);
}
void GDLoadTlutRaw(u32 tlut_ptr_raw, u32 tmem_addr, GXTlutSize size) {
ASSERTMSGLINE(527, size <= 0x400, "GDLoadTlut: invalid TLUT size");
GDWriteBPCmd(0xFEFFFF00);
GDWriteBPCmd(0xF000000);
GDWriteBPCmd(BP_LOAD_TLUT0(tlut_ptr_raw, 0x64));
GDWriteBPCmd(BP_LOAD_TLUT1((tmem_addr - 0x80000) >> 9, size, 0x65));
GDWriteBPCmd(0xFEFFFF00);
GDWriteBPCmd(0xF000000);
}
+127
View File
@@ -0,0 +1,127 @@
#include <revolution/gd.h>
#include <revolution/os.h>
void GDLoadPosMtxImm(const Mtx mtx, u32 id) {
GDWriteXFCmdHdr(4 * id, 12);
GDWrite_f32(mtx[0][0]);
GDWrite_f32(mtx[0][1]);
GDWrite_f32(mtx[0][2]);
GDWrite_f32(mtx[0][3]);
GDWrite_f32(mtx[1][0]);
GDWrite_f32(mtx[1][1]);
GDWrite_f32(mtx[1][2]);
GDWrite_f32(mtx[1][3]);
GDWrite_f32(mtx[2][0]);
GDWrite_f32(mtx[2][1]);
GDWrite_f32(mtx[2][2]);
GDWrite_f32(mtx[2][3]);
}
void GDLoadPosMtxIndx(u16 mtx_indx, u32 id) {
GDWriteXFIndxACmd(4 * id, 12, mtx_indx);
}
void GDLoadNrmMtxImm(const Mtx mtx, u32 id) {
GDWriteXFCmdHdr(id * 3 + 0x400, 9);
GDWrite_f32(mtx[0][0]);
GDWrite_f32(mtx[0][1]);
GDWrite_f32(mtx[0][2]);
GDWrite_f32(mtx[1][0]);
GDWrite_f32(mtx[1][1]);
GDWrite_f32(mtx[1][2]);
GDWrite_f32(mtx[2][0]);
GDWrite_f32(mtx[2][1]);
GDWrite_f32(mtx[2][2]);
}
void GDLoadNrmMtxImm3x3(const f32 mtx[3][3], u32 id) {
GDWriteXFCmdHdr(id * 3 + 0x400, 9);
GDWrite_f32(mtx[0][0]);
GDWrite_f32(mtx[0][1]);
GDWrite_f32(mtx[0][2]);
GDWrite_f32(mtx[1][0]);
GDWrite_f32(mtx[1][1]);
GDWrite_f32(mtx[1][2]);
GDWrite_f32(mtx[2][0]);
GDWrite_f32(mtx[2][1]);
GDWrite_f32(mtx[2][2]);
}
void GDLoadNrmMtxIndx3x3(u16 mtx_indx, u32 id) {
GDWriteXFIndxBCmd(id * 3 + 0x400, 9, mtx_indx);
}
void GDLoadTexMtxImm(const Mtx mtx, u32 id, GXTexMtxType type) {
u16 addr;
u8 count;
if (id >= 0x40) {
ASSERTMSGLINE(178, type == GX_MTX3x4, "GDLoadTexMtxImm: invalid matrix type");
addr = ((id - 0x40) << 2) + 0x500;
count = 12;
} else {
addr = 4 * id;
count = type == GX_MTX2x4 ? 8 : 12;
}
GDWriteXFCmdHdr(addr,count);
GDWrite_f32(mtx[0][0]);
GDWrite_f32(mtx[0][1]);
GDWrite_f32(mtx[0][2]);
GDWrite_f32(mtx[0][3]);
GDWrite_f32(mtx[1][0]);
GDWrite_f32(mtx[1][1]);
GDWrite_f32(mtx[1][2]);
GDWrite_f32(mtx[1][3]);
if (type == GX_MTX3x4) {
GDWrite_f32(mtx[2][0]);
GDWrite_f32(mtx[2][1]);
GDWrite_f32(mtx[2][2]);
GDWrite_f32(mtx[2][3]);
}
}
void GDLoadTexMtxIndx(u16 mtx_indx, u32 id, GXTexMtxType type) {
u16 addr;
u8 count;
if (id >= 0x40) {
ASSERTMSGLINE(227, type == GX_MTX3x4, "GDLoadTexMtxIndx: invalid matrix type");
addr = ((id - 0x40) << 2) + 0x500;
count = 12;
} else {
addr = 4 * id;
count = type == GX_MTX2x4 ? 8 : 12;
}
GDWriteXFIndxCCmd(addr, count, mtx_indx);
}
void GDSetCurrentMtx(u32 pn, u32 t0, u32 t1, u32 t2, u32 t3, u32 t4, u32 t5, u32 t6, u32 t7) {
u32 regA;
u32 regB;
regA = CP_MTX_REG_A(pn, t0, t1, t2, t3);
regB = CP_MTX_REG_B(t4, t5, t6, t7);
GDWriteCPCmd(CP_MTX_REG_A_ID, regA);
GDWriteCPCmd(CP_MTX_REG_B_ID, regB);
GDWriteXFCmdHdr(XF_REG_MATRIXINDEX0_ID, 2);
GDWrite_u32(regA);
GDWrite_u32(regB);
}
void GDSetProjection(const Mtx44 mtx, GXProjectionType type) {
u32 c;
c = type == GX_ORTHOGRAPHIC ? 3 : 2;
GDWriteXFCmdHdr(XF_REG_PROJECTIONA_ID, 7);
GDWrite_f32(mtx[0][0]);
GDWrite_f32(mtx[0][c]);
GDWrite_f32(mtx[1][1]);
GDWrite_f32(mtx[1][c]);
GDWrite_f32(mtx[2][2]);
GDWrite_f32(mtx[2][3]);
GDWrite_u32(type);
}
+10
View File
@@ -0,0 +1,10 @@
#include <revolution/gf.h>
#include <revolution/gd.h>
void GFSetGenMode2(u8 nTexGens, u8 nChans, u8 nTevs, u8 nInds, GXCullMode cm) {
static u8 cm2hw[4] = {0, 2, 1, 3};
GFWriteBPCmd(0xFE07FC3F);
GFWriteBPCmd(GF_GEN_MODE(nTexGens, nChans, nTevs - 1, cm2hw[cm], nInds));
GFWriteXFCmd(XF_REG_NUMCOLORS_ID, nChans);
GFWriteXFCmd(XF_REG_NUMTEX_ID, nTexGens);
}
+6
View File
@@ -0,0 +1,6 @@
#include <revolution/gf.h>
#include <revolution/gd.h>
void GFSetChanAmbColor(GXChannelID chan, GXColor color) {
GFWriteXFCmd((chan & 1) + XF_REG_AMBIENT0_ID, color.r << 0x18 | color.g << 0x10 | color.b << 8 | color.a);
}
+74
View File
@@ -0,0 +1,74 @@
#include <revolution/gf.h>
#include <revolution/gd.h>
void GFSetFog(GXFogType type, f32 startz, f32 endz, f32 nearz, f32 farz, GXColor color) {
f32 A;
f32 B;
f32 B_mant;
f32 C;
f32 A_f;
u32 b_expn;
u32 b_m;
u32 a_hex;
u32 c_hex;
ASSERTMSGLINE(62, farz >= 0.0f, "GFSetFog: The farz should be positive value");
ASSERTMSGLINE(63, farz >= nearz, "GFSetFog: 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 = 1;
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_f = A / (1 << b_expn);
b_m = (u32) (8388638.0f * B_mant);
a_hex = *(u32*)&A_f;
c_hex = *(u32*)&C;
GFWriteBPCmd(BP_FOG_UNK0(a_hex >> 12, 0xEE));
GFWriteBPCmd(BP_FOG_UNK1(b_m, 0xEF));
GFWriteBPCmd(BP_FOG_UNK2(b_expn, 0xF0));
GFWriteBPCmd(BP_FOG_UNK3(c_hex >> 12, 0, type, 0xF1));
GFWriteBPCmd(BP_FOG_COLOR(color.r, color.g, color.b, 0xF2));
}
void GFSetBlendModeEtc(GXBlendMode type, GXBlendFactor src_factor,
GXBlendFactor dst_factor, GXLogicOp logic_op,
u8 color_update_enable, u8 alpha_update_enable,
u8 dither_enable) {
GFWriteBPCmd(BP_BLEND_MODE(
type == GX_BM_BLEND || type == GX_BM_SUBTRACT,
type == GX_BM_LOGIC,
dither_enable,
color_update_enable,
alpha_update_enable,
dst_factor,
src_factor,
type == GX_BM_SUBTRACT,
logic_op,
0x41
));
}
void GFSetZMode(u8 compare_enable, GXCompare func, u8 update_enable) {
GFWriteBPCmd(BP_Z_MODE(compare_enable, func, update_enable, 0x40));
}
+15
View File
@@ -0,0 +1,15 @@
#include <revolution/gf.h>
#include <revolution/gd.h>
void GFSetTevColorS10(GXTevRegID reg, GXColorS10 color) {
u32 regRA;
u32 regBG;
regRA = BP_TEV_COLOR_REG_RA(color.r & 0x7FF, color.a & 0x7FF, 0, 0xE0 + reg * 2);
regBG = BP_TEV_COLOR_REG_BG(color.b & 0x7FF, color.g & 0x7FF, 0, 0xE1 + reg * 2);
GFWriteBPCmd(regRA);
GFWriteBPCmd(regBG);
GFWriteBPCmd(regBG);
GFWriteBPCmd(regBG);
}
+637
View File
@@ -0,0 +1,637 @@
#include <revolution/gx.h>
#include <revolution/os.h>
#include "__gx.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, "GXSetVtxDesc: Invalid vertex attribute name")
#define CHECK_ATTRNAME2(line, attr) ASSERTMSGLINE(line, (attr) <= GX_VA_TEX7 || (attr) == GX_VA_NBT, "GXSetVtxDesc: Invalid vertex attribute name")
#define CHECK_ATTRNAME3(line, attr) ASSERTMSGLINE(line, (attr) >= GX_VA_PNMTXIDX && (attr) < GX_VA_MAX_ATTR, "GXSetVtxDesc: Invalid vertex attribute name")
#define CHECK_ATTRNAME4(line, attr) ASSERTMSGLINE(line, ((attr) >= GX_VA_POS && (attr) <= GX_VA_TEX7) || (attr) == GX_VA_NBT, "GXSetVtxAttrFmt: Invalid vertex attribute name")
#define CHECK_ATTRNAME5(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")
#define CHECK_MTXIDX(line, attr, type) ASSERTMSGLINE(line, (attr) > GX_VA_TEX7MTXIDX || (type) <= GX_VA_TEX0MTXIDX, "GXSetVtxDesc: GX_VA_*MTXIDX accepts GX_NONE or GX_DIRECT only")
static void __GXXfVtxSpecs(void) {
u32 nCols;
u32 nNrm;
u32 nTex;
u32 reg;
nNrm = __GXData->hasBiNrms ? 2 : __GXData->hasNrms ? 1 : 0;
#if DEBUG
nCols = CP_VCD_REG_LO_GET_COL0(__GXData->vcdLo) ? 1 : 0;
nCols += CP_VCD_REG_LO_GET_COL1(__GXData->vcdLo) ? 1 : 0;
#else
nCols = (u32)__cntlzw((__GXData->vcdLo & CP_VCD_REG_LO_COLALL_MASK)>>CP_VCD_REG_LO_COLALL_SHIFT);
nCols = (33 - nCols) >> 1;
#endif
#if DEBUG
nTex = 0;
nTex += CP_VCD_REG_HI_GET_TEX0(__GXData->vcdHi) ? 1 : 0;
nTex += CP_VCD_REG_HI_GET_TEX1(__GXData->vcdHi) ? 1 : 0;
nTex += CP_VCD_REG_HI_GET_TEX2(__GXData->vcdHi) ? 1 : 0;
nTex += CP_VCD_REG_HI_GET_TEX3(__GXData->vcdHi) ? 1 : 0;
nTex += CP_VCD_REG_HI_GET_TEX4(__GXData->vcdHi) ? 1 : 0;
nTex += CP_VCD_REG_HI_GET_TEX5(__GXData->vcdHi) ? 1 : 0;
nTex += CP_VCD_REG_HI_GET_TEX6(__GXData->vcdHi) ? 1 : 0;
nTex += CP_VCD_REG_HI_GET_TEX7(__GXData->vcdHi) ? 1 : 0;
#else
nTex = (u32)__cntlzw((__GXData->vcdHi & CP_VCD_REG_HI_TEXALL_MASK)>>CP_VCD_REG_HI_TEXALL_SHIFT);
nTex = (33 - nTex) >> 1;
#endif
reg = XF_INVERTEXSPEC_F(nCols, nNrm, nTex);
GX_WRITE_XF_REG(0x1008, reg, 0);
__GXData->bpSentNot = 1;
}
static inline void SETVCDATTR(GXAttr Attr, GXAttrType Type) {
switch (Attr) {
case GX_VA_PNMTXIDX: SC_CP_VCD_REG_LO_SET_PMIDX(219, __GXData->vcdLo, Type); break;
case GX_VA_TEX0MTXIDX: SC_CP_VCD_REG_LO_SET_T0MIDX(220, __GXData->vcdLo, Type); break;
case GX_VA_TEX1MTXIDX: SC_CP_VCD_REG_LO_SET_T1MIDX(221, __GXData->vcdLo, Type); break;
case GX_VA_TEX2MTXIDX: SC_CP_VCD_REG_LO_SET_T2MIDX(222, __GXData->vcdLo, Type); break;
case GX_VA_TEX3MTXIDX: SC_CP_VCD_REG_LO_SET_T3MIDX(223, __GXData->vcdLo, Type); break;
case GX_VA_TEX4MTXIDX: SC_CP_VCD_REG_LO_SET_T4MIDX(224, __GXData->vcdLo, Type); break;
case GX_VA_TEX5MTXIDX: SC_CP_VCD_REG_LO_SET_T5MIDX(225, __GXData->vcdLo, Type); break;
case GX_VA_TEX6MTXIDX: SC_CP_VCD_REG_LO_SET_T6MIDX(226, __GXData->vcdLo, Type); break;
case GX_VA_TEX7MTXIDX: SC_CP_VCD_REG_LO_SET_T7MIDX(227, __GXData->vcdLo, Type); break;
case GX_VA_POS: SC_CP_VCD_REG_LO_SET_POS(228, __GXData->vcdLo, Type); break;
case GX_VA_NRM:
if (Type != GX_NONE) {
__GXData->hasNrms = 1;
__GXData->hasBiNrms = 0;
__GXData->nrmType = Type;
} else {
__GXData->hasNrms = 0;
}
break;
case GX_VA_NBT:
if (Type != GX_NONE) {
__GXData->hasBiNrms = 1;
__GXData->hasNrms = 0;
__GXData->nrmType = Type;
} else {
__GXData->hasBiNrms = 0;
}
break;
case GX_VA_CLR0: SC_CP_VCD_REG_LO_SET_COL0(253, __GXData->vcdLo, Type); break;
case GX_VA_CLR1: SC_CP_VCD_REG_LO_SET_COL1(254, __GXData->vcdLo, Type); break;
case GX_VA_TEX0: SC_CP_VCD_REG_HI_SET_TEX0(255, __GXData->vcdHi, Type); break;
case GX_VA_TEX1: SC_CP_VCD_REG_HI_SET_TEX1(256, __GXData->vcdHi, Type); break;
case GX_VA_TEX2: SC_CP_VCD_REG_HI_SET_TEX2(257, __GXData->vcdHi, Type); break;
case GX_VA_TEX3: SC_CP_VCD_REG_HI_SET_TEX3(258, __GXData->vcdHi, Type); break;
case GX_VA_TEX4: SC_CP_VCD_REG_HI_SET_TEX4(259, __GXData->vcdHi, Type); break;
case GX_VA_TEX5: SC_CP_VCD_REG_HI_SET_TEX5(260, __GXData->vcdHi, Type); break;
case GX_VA_TEX6: SC_CP_VCD_REG_HI_SET_TEX6(261, __GXData->vcdHi, Type); break;
case GX_VA_TEX7: SC_CP_VCD_REG_HI_SET_TEX7(262, __GXData->vcdHi, Type); break;
}
}
void GXSetVtxDesc(GXAttr attr, GXAttrType type) {
CHECK_GXBEGIN(271, "GXSetVtxDesc");
CHECK_ATTRNAME(274, attr);
CHECK_ATTRNAME2(276, attr);
CHECK_ATTRTYPE(278, type);
CHECK_MTXIDX(281, attr, type);
SETVCDATTR(attr, type);
if (__GXData->hasNrms || __GXData->hasBiNrms) {
SC_CP_VCD_REG_LO_SET_NRM(287, __GXData->vcdLo, __GXData->nrmType);
} else {
SC_CP_VCD_REG_LO_SET_NRM(0, __GXData->vcdLo, 0);
}
__GXData->dirtyState |= 8;
}
void GXSetVtxDescv(const GXVtxDescList *attrPtr) {
CHECK_GXBEGIN(313, "GXSetVtxDescv");
CHECK_ATTRPTR(314, attrPtr);
while (attrPtr->attr != GX_VA_NULL) {
CHECK_ATTRNAME(318, attrPtr->attr);
CHECK_ATTRNAME2(321, attrPtr->attr);
CHECK_ATTRTYPE(324, attrPtr->type);
SETVCDATTR(attrPtr->attr, attrPtr->type);
attrPtr++;
}
if (__GXData->hasNrms || __GXData->hasBiNrms) {
SC_CP_VCD_REG_LO_SET_NRM(333, __GXData->vcdLo, __GXData->nrmType);
} else {
SC_CP_VCD_REG_LO_SET_NRM(0, __GXData->vcdLo, 0);
}
__GXData->dirtyState |= 8;
}
void __GXSetVCD(void) {
GX_WRITE_CP_STRM_REG_alt(CP_VCD_LO, 0, __GXData->vcdLo, -12);
GX_WRITE_CP_STRM_REG_alt(CP_VCD_HI, 0, __GXData->vcdHi, -12);
__GXXfVtxSpecs();
}
void __GXCalculateVLim(void) {
static u8 tbl1[] = { 0, 4, 1, 2 };
static u8 tbl2[] = { 0, 8, 1, 2 };
static u8 tbl3[] = { 0, 12, 1, 2 };
if (__GXData->vNum != 0) {
GXCompCnt nc;
u32 vlm;
u32 b;
u32 vl;
u32 vh;
u32 va;
vl = __GXData->vcdLo;
vh = __GXData->vcdHi;
va = __GXData->vatA[0];
nc = CP_VAT_REG_A_GET_NRMCNT(va);
vlm = ((vl >> 0) & 0x1);
vlm += ((vl >> 1) & 0x1);
vlm += ((vl >> 2) & 0x1);
vlm += ((vl >> 3) & 0x1);
vlm += ((vl >> 4) & 0x1);
vlm += ((vl >> 5) & 0x1);
vlm += ((vl >> 6) & 0x1);
vlm += ((vl >> 7) & 0x1);
vlm += ((vl >> 8) & 0x1);
vlm += tbl3[((vl >> 9) & 0x3)];
b = (u32)((nc == GX_NRM_NBT) ? 3 : 1);
vlm += tbl3[((vl >> 11) & 0x3)] * b;
vlm += tbl1[((vl >> 13) & 0x3)];
vlm += tbl1[((vl >> 15) & 0x3)];
vlm += tbl2[((vh >> (0*2)) & 0x3)];
vlm += tbl2[((vh >> (1*2)) & 0x3)];
vlm += tbl2[((vh >> (2*2)) & 0x3)];
vlm += tbl2[((vh >> (3*2)) & 0x3)];
vlm += tbl2[((vh >> (4*2)) & 0x3)];
vlm += tbl2[((vh >> (5*2)) & 0x3)];
vlm += tbl2[((vh >> (6*2)) & 0x3)];
vlm += tbl2[((vh >> (7*2)) & 0x3)];
__GXData->vLim = (u16)vlm;
}
}
void GXGetVtxDesc(GXAttr attr, GXAttrType* type) {
u32 cpType;
CHECK_GXBEGIN(465, "GXGetVtxDesc");
CHECK_ATTRNAME3(467, attr);
switch (attr) {
case GX_VA_PNMTXIDX: cpType = CP_VCD_REG_LO_GET_PMIDX(__GXData->vcdLo); break;
case GX_VA_TEX0MTXIDX: cpType = CP_VCD_REG_LO_GET_T0MIDX(__GXData->vcdLo); break;
case GX_VA_TEX1MTXIDX: cpType = CP_VCD_REG_LO_GET_T1MIDX(__GXData->vcdLo); break;
case GX_VA_TEX2MTXIDX: cpType = CP_VCD_REG_LO_GET_T2MIDX(__GXData->vcdLo); break;
case GX_VA_TEX3MTXIDX: cpType = CP_VCD_REG_LO_GET_T3MIDX(__GXData->vcdLo); break;
case GX_VA_TEX4MTXIDX: cpType = CP_VCD_REG_LO_GET_T4MIDX(__GXData->vcdLo); break;
case GX_VA_TEX5MTXIDX: cpType = CP_VCD_REG_LO_GET_T5MIDX(__GXData->vcdLo); break;
case GX_VA_TEX6MTXIDX: cpType = CP_VCD_REG_LO_GET_T6MIDX(__GXData->vcdLo); break;
case GX_VA_TEX7MTXIDX: cpType = CP_VCD_REG_LO_GET_T7MIDX(__GXData->vcdLo); break;
case GX_VA_POS: cpType = CP_VCD_REG_LO_GET_POS(__GXData->vcdLo); break;
case GX_VA_NRM: cpType = __GXData->hasNrms ? CP_VCD_REG_LO_GET_NRM(__GXData->vcdLo) : 0; break;
case GX_VA_NBT: cpType = __GXData->hasBiNrms ? CP_VCD_REG_LO_GET_NRM(__GXData->vcdLo) : 0; break;
case GX_VA_CLR0: cpType = CP_VCD_REG_LO_GET_COL0(__GXData->vcdLo); break;
case GX_VA_CLR1: cpType = CP_VCD_REG_LO_GET_COL1(__GXData->vcdLo); break;
case GX_VA_TEX0: cpType = CP_VCD_REG_HI_GET_TEX0(__GXData->vcdHi); break;
case GX_VA_TEX1: cpType = CP_VCD_REG_HI_GET_TEX1(__GXData->vcdHi); break;
case GX_VA_TEX2: cpType = CP_VCD_REG_HI_GET_TEX2(__GXData->vcdHi); break;
case GX_VA_TEX3: cpType = CP_VCD_REG_HI_GET_TEX3(__GXData->vcdHi); break;
case GX_VA_TEX4: cpType = CP_VCD_REG_HI_GET_TEX4(__GXData->vcdHi); break;
case GX_VA_TEX5: cpType = CP_VCD_REG_HI_GET_TEX5(__GXData->vcdHi); break;
case GX_VA_TEX6: cpType = CP_VCD_REG_HI_GET_TEX6(__GXData->vcdHi); break;
case GX_VA_TEX7: cpType = CP_VCD_REG_HI_GET_TEX7(__GXData->vcdHi); break;
default: cpType = 0; break;
}
*type = cpType;
}
void GXGetVtxDescv(GXVtxDescList* vcd) {
GXAttr attr;
CHECK_GXBEGIN(518, "GXGetVtxDescv");
CHECK_ATTRPTR(520, vcd);
for (attr = GX_VA_PNMTXIDX; attr <= GX_VA_TEX7; attr++) {
vcd[attr].attr = attr;
GXGetVtxDesc(attr, &vcd[attr].type);
}
vcd[attr].attr = GX_VA_NBT;
GXGetVtxDesc(GX_VA_NBT, &vcd[attr].type);
attr++;
vcd[attr].attr = GX_VA_NULL;
}
void GXClearVtxDesc(void) {
CHECK_GXBEGIN(550, "GXClearVtxDesc");
__GXData->vcdLo = 0;
SC_CP_VCD_REG_LO_SET_POS(0, __GXData->vcdLo, GX_DIRECT);
__GXData->vcdHi = 0;
__GXData->hasNrms = 0;
__GXData->hasBiNrms = 0;
__GXData->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:
SC_CP_VAT_REG_A_SET_POSCNT(590, *va, cnt);
SC_CP_VAT_REG_A_SET_POSFMT(591, *va, type);
SC_CP_VAT_REG_A_SET_POSSHFT(592, *va, shft);
break;
case GX_VA_NRM:
case GX_VA_NBT:
SC_CP_VAT_REG_A_SET_NRMFMT(600, *va, type);
if (cnt == GX_NRM_NBT3) {
SC_CP_VAT_REG_A_SET_NRMCNT(0, *va, 1);
SC_CP_VAT_REG_A_SET_NORMALINDEX3(0, *va, 1);
} else {
SC_CP_VAT_REG_A_SET_NRMCNT(606, *va, cnt);
SC_CP_VAT_REG_A_SET_NORMALINDEX3(606, *va, 0);
}
break;
case GX_VA_CLR0:
SC_CP_VAT_REG_A_SET_COL0CNT(612, *va, cnt);
SC_CP_VAT_REG_A_SET_COL0FMT(613, *va, type);
break;
case GX_VA_CLR1:
SC_CP_VAT_REG_A_SET_COL1CNT(616, *va, cnt);
SC_CP_VAT_REG_A_SET_COL1FMT(617, *va, type);
break;
case GX_VA_TEX0:
SC_CP_VAT_REG_A_SET_TEX0CNT(620, *va, cnt);
SC_CP_VAT_REG_A_SET_TEX0FMT(621, *va, type);
SC_CP_VAT_REG_A_SET_TEX0SHFT(622, *va, shft);
break;
case GX_VA_TEX1:
SC_CP_VAT_REG_B_SET_TEX1CNT(625, *vb, cnt);
SC_CP_VAT_REG_B_SET_TEX1FMT(626, *vb, type);
SC_CP_VAT_REG_B_SET_TEX1SHFT(627, *vb, shft);
break;
case GX_VA_TEX2:
SC_CP_VAT_REG_B_SET_TEX2CNT(630, *vb, cnt);
SC_CP_VAT_REG_B_SET_TEX2FMT(631, *vb, type);
SC_CP_VAT_REG_B_SET_TEX2SHFT(632, *vb, shft);
break;
case GX_VA_TEX3:
SC_CP_VAT_REG_B_SET_TEX3CNT(635, *vb, cnt);
SC_CP_VAT_REG_B_SET_TEX3FMT(636, *vb, type);
SC_CP_VAT_REG_B_SET_TEX3SHFT(637, *vb, shft);
break;
case GX_VA_TEX4:
SC_CP_VAT_REG_B_SET_TEX4CNT(640, *vb, cnt);
SC_CP_VAT_REG_B_SET_TEX4FMT(641, *vb, type);
SC_CP_VAT_REG_C_SET_TEX4SHFT(642, *vc, shft);
break;
case GX_VA_TEX5:
SC_CP_VAT_REG_C_SET_TEX5CNT(645, *vc, cnt);
SC_CP_VAT_REG_C_SET_TEX5FMT(646, *vc, type);
SC_CP_VAT_REG_C_SET_TEX5SHFT(647, *vc, shft);
break;
case GX_VA_TEX6:
SC_CP_VAT_REG_C_SET_TEX6CNT(650, *vc, cnt);
SC_CP_VAT_REG_C_SET_TEX6FMT(651, *vc, type);
SC_CP_VAT_REG_C_SET_TEX6SHFT(652, *vc, shft);
break;
case GX_VA_TEX7:
SC_CP_VAT_REG_C_SET_TEX7CNT(655, *vc, cnt);
SC_CP_VAT_REG_C_SET_TEX7FMT(656, *vc, type);
SC_CP_VAT_REG_C_SET_TEX7SHFT(657, *vc, shft);
break;
}
}
void GXSetVtxAttrFmt(GXVtxFmt vtxfmt, GXAttr attr, GXCompCnt cnt, GXCompType type, u8 frac) {
u32* va;
u32* vb;
u32* vc;
CHECK_GXBEGIN(673, "GXSetVtxAttrFmt");
CHECK_VTXFMT(674, vtxfmt);
CHECK_ATTRNAME4(678, attr);
CHECK_FRAC(679, frac);
va = &__GXData->vatA[vtxfmt];
vb = &__GXData->vatB[vtxfmt];
vc = &__GXData->vatC[vtxfmt];
SETVAT(va, vb, vc, attr, cnt, type, frac);
#if DEBUG
__GXVerifyVATImm(attr, cnt, type, frac);
#endif
__GXData->dirtyState |= 0x10;
__GXData->dirtyVAT |= (u8)(1 << (u8)vtxfmt);
}
void GXSetVtxAttrFmtv(GXVtxFmt vtxfmt, const GXVtxAttrFmtList* list) {
u32* va;
u32* vb;
u32* vc;
CHECK_GXBEGIN(720, "GXSetVtxAttrFmtv");
CHECK_LISTPTR(721, list);
CHECK_VTXFMT(722, vtxfmt);
va = &__GXData->vatA[vtxfmt];
vb = &__GXData->vatB[vtxfmt];
vc = &__GXData->vatC[vtxfmt];
while (list->attr != GX_VA_NULL) {
CHECK_ATTRNAME4(732, list->attr);
CHECK_FRAC(733, list->frac);
SETVAT(va, vb, vc, list->attr, list->cnt, list->type, list->frac);
#if DEBUG
__GXVerifyVATImm(list->attr, list->cnt, list->type, list->frac);
#endif
list++;
}
__GXData->dirtyState |= 0x10;
__GXData->dirtyVAT |= (u8)(1 << (u8)vtxfmt);
}
void __GXSetVAT(void) {
s32 i;
u32 dirty = __GXData->dirtyVAT;
i = 0;
do {
if (dirty & 1) {
GX_WRITE_SOME_REG4(8, i | 0x70, __GXData->vatA[i], i - 12);
GX_WRITE_SOME_REG4(8, i | 0x80, __GXData->vatB[i], i - 12);
GX_WRITE_SOME_REG4(8, i | 0x90, __GXData->vatC[i], i - 12);
}
dirty >>= 1;
i++;
} while (dirty != 0);
GX_WRITE_U8(0);
__GXData->dirtyVAT = 0;
}
static inline u8 GetFracForNrm(GXCompType type) {
u8 frac;
switch (type) {
case GX_S8:
frac = 6;
break;
case GX_S16:
frac = 14;
break;
default:
case GX_U16:
frac = 0;
break;
}
return frac;
}
void GXGetVtxAttrFmt(GXVtxFmt fmt, GXAttr attr, GXCompCnt* cnt, GXCompType* type, u8* frac) {
u32* va;
u32* vb;
u32* vc;
CHECK_GXBEGIN(844, "GXGetVtxAttrFmt");
CHECK_VTXFMT(845, fmt);
va = &__GXData->vatA[fmt];
vb = &__GXData->vatB[fmt];
vc = &__GXData->vatC[fmt];
switch (attr) {
case GX_VA_POS:
*cnt = CP_VAT_REG_A_GET_POSCNT(*va);
*type = CP_VAT_REG_A_GET_POSFMT(*va);
*frac = CP_VAT_REG_A_GET_POSSHFT(*va);
return;
case GX_VA_NRM:
case GX_VA_NBT:
*cnt = CP_VAT_REG_A_GET_NRMCNT(*va);
if (*cnt == GX_TEX_ST && CP_VAT_REG_A_GET_NORMALINDEX3(*va)) {
*cnt = GX_NRM_NBT3;
}
*type = CP_VAT_REG_A_GET_NRMFMT(*va);
*frac = GetFracForNrm(*type);
return;
case GX_VA_CLR0:
*cnt = CP_VAT_REG_A_GET_COL0CNT(*va);
*type = CP_VAT_REG_A_GET_COL0FMT(*va);
*frac = 0;
return;
case GX_VA_CLR1:
*cnt = CP_VAT_REG_A_GET_COL1CNT(*va);
*type = CP_VAT_REG_A_GET_COL1FMT(*va);
*frac = 0;
return;
case GX_VA_TEX0:
*cnt = CP_VAT_REG_A_GET_TEX0CNT(*va);
*type = CP_VAT_REG_A_GET_TEX0FMT(*va);
*frac = CP_VAT_REG_A_GET_TEX0SHFT(*va);
return;
case GX_VA_TEX1:
*cnt = CP_VAT_REG_B_GET_TEX1CNT(*vb);
*type = CP_VAT_REG_B_GET_TEX1FMT(*vb);
*frac = CP_VAT_REG_B_GET_TEX1SHFT(*vb);
return;
case GX_VA_TEX2:
*cnt = CP_VAT_REG_B_GET_TEX2CNT(*vb);
*type = CP_VAT_REG_B_GET_TEX2FMT(*vb);
*frac = CP_VAT_REG_B_GET_TEX2SHFT(*vb);
return;
case GX_VA_TEX3:
*cnt = CP_VAT_REG_B_GET_TEX3CNT(*vb);
*type = CP_VAT_REG_B_GET_TEX3FMT(*vb);
*frac = CP_VAT_REG_B_GET_TEX3SHFT(*vb);
return;
case GX_VA_TEX4:
*cnt = CP_VAT_REG_B_GET_TEX4CNT(*vb);
*type = CP_VAT_REG_B_GET_TEX4FMT(*vb);
*frac = CP_VAT_REG_C_GET_TEX4SHFT(*vc);
return;
case GX_VA_TEX5:
*cnt = CP_VAT_REG_C_GET_TEX5CNT(*vc);
*type = CP_VAT_REG_C_GET_TEX5FMT(*vc);
*frac = CP_VAT_REG_C_GET_TEX5SHFT(*vc);
return;
case GX_VA_TEX6:
*cnt = CP_VAT_REG_C_GET_TEX6CNT(*vc);
*type = CP_VAT_REG_C_GET_TEX6FMT(*vc);
*frac = CP_VAT_REG_C_GET_TEX6SHFT(*vc);
return;
case GX_VA_TEX7:
*cnt = CP_VAT_REG_C_GET_TEX7CNT(*vc);
*type = CP_VAT_REG_C_GET_TEX7FMT(*vc);
*frac = CP_VAT_REG_C_GET_TEX7SHFT(*vc);
return;
default:
*cnt = GX_POS_XYZ;
*type = GX_U8;
*frac = 0;
return;
}
}
void GXGetVtxAttrFmtv(GXVtxFmt fmt, GXVtxAttrFmtList* vat) {
GXAttr attr;
CHECK_GXBEGIN(941, "GXGetVtxAttrFmtv");
CHECK_LISTPTR(942, vat);
CHECK_VTXFMT(943, fmt);
for (attr = GX_VA_POS; attr <= GX_VA_TEX7; attr++) {
vat->attr = attr;
GXGetVtxAttrFmt(fmt, attr, &vat->cnt, &vat->type, &vat->frac);
vat++;
}
vat->attr = GX_VA_NULL;
}
void GXSetArray(GXAttr attr, void* base_ptr, u8 stride) {
GXAttr cpAttr;
u32 phyAddr;
CHECK_GXBEGIN(974, "GXSetArray");
attr = (attr == GX_VA_NBT) ? GX_VA_NRM : attr;
CHECK_ATTRNAME5(977, attr);
cpAttr = (GXAttr)(attr - GX_VA_POS);
phyAddr = GX_PHY_ADDR(base_ptr);
GX_WRITE_CP_STRM_REG_alt2(CP_ARRAY_BASE, cpAttr, phyAddr, cpAttr - 12);
GX_WRITE_CP_STRM_REG_alt3(CP_ARRAY_STRIDE, cpAttr, (u32)stride, cpAttr - 12);
}
void GXInvalidateVtxCache(void) {
CHECK_GXBEGIN(999, "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;
u32 form;
GXAttr mtxIdAttr;
CHECK_GXBEGIN(1041, "GXSetTexCoordGen");
ASSERTMSGLINE(1042, dst_coord < GX_MAX_TEXCOORD, "GXSetTexCoordGen: Invalid coordinate Id");
form = 0;
row = bumprow = 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 = 5; break;
case GX_TG_TEXCOORD1: bumprow = 6; break;
case GX_TG_TEXCOORD2: bumprow = 7; break;
case GX_TG_TEXCOORD3: bumprow = 8; break;
case GX_TG_TEXCOORD4: bumprow = 9; break;
case GX_TG_TEXCOORD5: bumprow = 10; break;
case GX_TG_TEXCOORD6: bumprow = 11; break;
default:
ASSERTMSGLINE(1070, 0, "GXSetTexCoordGen: Invalid source parameter");
break;
}
switch (func) {
case GX_TG_MTX2x4:
SC_XF_TEX_SET_PROJECTION(1080, reg, 0);
SC_XF_TEX_SET_INPUT_FORM(1080, reg, form);
SC_XF_TEX_SET_TEXGEN_TYPE(1082, reg, 0);
SC_XF_TEX_SET_SOURCE_ROW(1082, reg, row);
break;
case GX_TG_MTX3x4:
SC_XF_TEX_SET_PROJECTION(1087, reg, 1);
SC_XF_TEX_SET_INPUT_FORM(1087, reg, form);
SC_XF_TEX_SET_TEXGEN_TYPE(1087, reg, 0);
SC_XF_TEX_SET_SOURCE_ROW(1089, reg, row);
break;
case GX_TG_BUMP0:
case GX_TG_BUMP1:
case GX_TG_BUMP2:
case GX_TG_BUMP3:
case GX_TG_BUMP4:
case GX_TG_BUMP5:
case GX_TG_BUMP6:
case GX_TG_BUMP7:
ASSERTMSGLINE(1102, src_param >= 12 && src_param <= 18, "GXSetTexCoordGen: Bump source texture value is invalid");
SC_XF_TEX_SET_PROJECTION(1104, reg, 0);
SC_XF_TEX_SET_INPUT_FORM(1104, reg, form);
SC_XF_TEX_SET_TEXGEN_TYPE(1106, reg, 1);
SC_XF_TEX_SET_SOURCE_ROW(1106, reg, row);
SC_XF_TEX_SET_BUMP_MAP_SOURCE(1107, reg, src_param - 12);
SC_XF_TEX_SET_BUMP_MAP_LIGHT(1108, reg, func - 2);
break;
case GX_TG_SRTG:
SC_XF_TEX_SET_PROJECTION(1113, reg, 0);
SC_XF_TEX_SET_INPUT_FORM(1113, reg, form);
if (src_param == GX_TG_COLOR0) {
SC_XF_TEX_SET_TEXGEN_TYPE(0, reg, 2);
} else {
SC_XF_TEX_SET_TEXGEN_TYPE(0, reg, 3);
}
SC_XF_TEX_SET_SOURCE_ROW(0, reg, 2);
break;
default:
ASSERTMSGLINE(1124, 0, "GXSetTexCoordGen: Invalid function");
break;
}
__GXData->texGenCtrl[dst_coord] = reg;
__GXData->dirtyState |= (0x10000 << dst_coord);
reg = 0;
SC_XF_DUALTEX_F_SET_DUALMATRIX_ADRS(1143, reg, pt_texmtx - 64);
SC_XF_DUALTEX_F_SET_NORMAL_ENABLE(1144, reg, normalize);
__GXData->texGenCtrl2[dst_coord] = reg;
switch (dst_coord) {
case GX_TEXCOORD0: SC_CP_MATIDX_REG_A_SET_TEX0IDX(1158, __GXData->matIdxA, mtx); break;
case GX_TEXCOORD1: SC_CP_MATIDX_REG_A_SET_TEX1IDX(1159, __GXData->matIdxA, mtx); break;
case GX_TEXCOORD2: SC_CP_MATIDX_REG_A_SET_TEX2IDX(1160, __GXData->matIdxA, mtx); break;
case GX_TEXCOORD3: SC_CP_MATIDX_REG_A_SET_TEX3IDX(1161, __GXData->matIdxA, mtx); break;
case GX_TEXCOORD4: SC_CP_MATIDX_REG_B_SET_TEX4IDX(1162, __GXData->matIdxB, mtx); break;
case GX_TEXCOORD5: SC_CP_MATIDX_REG_B_SET_TEX5IDX(1163, __GXData->matIdxB, mtx); break;
case GX_TEXCOORD6: SC_CP_MATIDX_REG_B_SET_TEX6IDX(1164, __GXData->matIdxB, mtx); break;
default: SC_CP_MATIDX_REG_B_SET_TEX7IDX(1165, __GXData->matIdxB, mtx); break;
}
mtxIdAttr = dst_coord + 1;
__GXData->dirtyState |= 0x4000000;
}
void GXSetNumTexGens(u8 nTexGens) {
CHECK_GXBEGIN(1183, "GXSetNumTexGens");
SC_GEN_MODE_SET_NTEX(1185, __GXData->genMode, nTexGens);
__GXData->dirtyState |= 0x2000004;
}
+308
View File
@@ -0,0 +1,308 @@
#include <revolution/gx.h>
#include <revolution/os.h>
#include "__gx.h"
#if DEBUG
#define GX_WRITE_SOME_REG5(a, b) \
do { \
GX_WRITE_U8(a); \
GX_WRITE_U32(b); \
__gxVerif->rasRegs[(b & 0xFF000000) >> 24] = 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(150, "GXInitIndTexture");
reg = 0;
SC_BP_CMD_SET_BT(152, reg, ind_stage);
SC_BP_CMD_SET_FMT(153, reg, format);
SC_BP_CMD_SET_BIAS(154, reg, bias_sel);
SC_BP_CMD_SET_BS(155, reg, alpha_sel);
SC_BP_CMD_SET_M(156, reg, matrix_sel);
SC_BP_CMD_SET_SW(157, reg, wrap_s);
SC_BP_CMD_SET_TW(158, reg, wrap_t);
SC_BP_CMD_SET_LB(159, reg, utc_lod);
SC_BP_CMD_SET_FB(160, reg, add_prev);
SC_BP_CMD_SET_RID(161, reg, (0x10 + tev_stage));
GX_WRITE_SOME_REG5(GX_LOAD_BP_REG, reg);
__GXData->bpSentNot = 0;
}
void GXSetIndTexMtx(GXIndTexMtxID mtx_id, const f32 offset[2][3], s8 scale_exp) {
s32 mtx[6];
u32 reg;
u32 id;
CHECK_GXBEGIN(190, "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 += 17;
reg = 0;
SC_BP_MTXA_SET_MA(212, reg, mtx[0]);
SC_BP_MTXA_SET_MB(213, reg, mtx[1]);
SC_BP_MTXA_SET_S(214, reg, scale_exp & 3);
SC_BP_MTXA_SET_RID(215, reg, id * 3 + 6);
GX_WRITE_SOME_REG5(GX_LOAD_BP_REG, reg);
mtx[2] = (int)(1024.0f * offset[0][1]) & 0x7FF;
mtx[3] = (int)(1024.0f * offset[1][1]) & 0x7FF;
reg = 0;
SC_BP_MTXB_SET_MC(221, reg, mtx[2]);
SC_BP_MTXB_SET_MD(222, reg, mtx[3]);
SC_BP_MTXB_SET_S(223, reg, (scale_exp >> 2) & 3);
SC_BP_MTXB_SET_RID(224, reg, id * 3 + 7);
GX_WRITE_SOME_REG5(GX_LOAD_BP_REG, reg);
mtx[4] = (int)(1024.0f * offset[0][2]) & 0x7FF;
mtx[5] = (int)(1024.0f * offset[1][2]) & 0x7FF;
reg = 0;
SC_BP_MTXC_SET_ME(230, reg, mtx[4]);
SC_BP_MTXC_SET_MF(231, reg, mtx[5]);
SC_BP_MTXC_SET_S(232, reg, (scale_exp >> 4) & 3);
SC_BP_MTXC_SET_RID(233, reg, id * 3 + 8);
GX_WRITE_SOME_REG5(GX_LOAD_BP_REG, reg);
__GXData->bpSentNot = 0;
}
void GXSetIndTexCoordScale(GXIndTexStageID ind_state, GXIndTexScale scale_s, GXIndTexScale scale_t) {
CHECK_GXBEGIN(253, "GXSetIndTexScale");
switch (ind_state) {
case GX_INDTEXSTAGE0:
SET_REG_FIELD(257, __GXData->IndTexScale0, 4, 0, scale_s);
SET_REG_FIELD(258, __GXData->IndTexScale0, 4, 4, scale_t);
SET_REG_FIELD(258, __GXData->IndTexScale0, 8, 24, 0x25);
GX_WRITE_SOME_REG5(GX_LOAD_BP_REG, __GXData->IndTexScale0);
break;
case GX_INDTEXSTAGE1:
SET_REG_FIELD(263, __GXData->IndTexScale0, 4, 8, scale_s);
SET_REG_FIELD(264, __GXData->IndTexScale0, 4, 12, scale_t);
SET_REG_FIELD(264, __GXData->IndTexScale0, 8, 24, 0x25);
GX_WRITE_SOME_REG5(GX_LOAD_BP_REG, __GXData->IndTexScale0);
break;
case GX_INDTEXSTAGE2:
SET_REG_FIELD(269, __GXData->IndTexScale1, 4, 0, scale_s);
SET_REG_FIELD(270, __GXData->IndTexScale1, 4, 4, scale_t);
SET_REG_FIELD(270, __GXData->IndTexScale1, 8, 24, 0x26);
GX_WRITE_SOME_REG5(GX_LOAD_BP_REG, __GXData->IndTexScale1);
break;
case GX_INDTEXSTAGE3:
SET_REG_FIELD(275, __GXData->IndTexScale1, 4, 8, scale_s);
SET_REG_FIELD(276, __GXData->IndTexScale1, 4, 12, scale_t);
SET_REG_FIELD(276, __GXData->IndTexScale1, 8, 24, 0x26);
GX_WRITE_SOME_REG5(GX_LOAD_BP_REG, __GXData->IndTexScale1);
break;
default:
ASSERTMSGLINE(281, 0, "GXSetIndTexCoordScale: Invalid Indirect Stage Id");
break;
}
__GXData->bpSentNot = 0;
}
void GXSetIndTexOrder(GXIndTexStageID ind_stage, GXTexCoordID tex_coord, GXTexMapID tex_map) {
CHECK_GXBEGIN(306, "GXSetIndTexOrder");
if (tex_map == GX_TEXMAP_NULL) {
tex_map = GX_TEXMAP0;
}
if (tex_coord == GX_TEXCOORD_NULL) {
tex_coord = GX_TEXCOORD0;
}
ASSERTMSGLINE(318, tex_map < GX_MAX_TEXMAP, "GXSetIndTexOrder: Invalid direct texture Id");
ASSERTMSGLINE(319, tex_coord < GX_MAX_TEXCOORD, "GXSetIndTexOrder: Invalid texture coord");
switch (ind_stage) {
case GX_INDTEXSTAGE0:
SET_REG_FIELD(323, __GXData->iref, 3, 0, tex_map);
SET_REG_FIELD(324, __GXData->iref, 3, 3, tex_coord);
break;
case GX_INDTEXSTAGE1:
SET_REG_FIELD(327, __GXData->iref, 3, 6, tex_map);
SET_REG_FIELD(328, __GXData->iref, 3, 9, tex_coord);
break;
case GX_INDTEXSTAGE2:
SET_REG_FIELD(331, __GXData->iref, 3, 12, tex_map);
SET_REG_FIELD(332, __GXData->iref, 3, 15, tex_coord);
break;
case GX_INDTEXSTAGE3:
SET_REG_FIELD(335, __GXData->iref, 3, 18, tex_map);
SET_REG_FIELD(336, __GXData->iref, 3, 21, tex_coord);
break;
default:
ASSERTMSGLINE(339, 0, "GXSetIndTexOrder: Invalid Indirect Stage Id");
break;
}
GX_WRITE_SOME_REG5(GX_LOAD_BP_REG, __GXData->iref);
__GXData->dirtyState |= 3;
__GXData->bpSentNot = 0;
}
void GXSetNumIndStages(u8 nIndStages) {
CHECK_GXBEGIN(357, "GXSetNumIndStages");
ASSERTMSGLINE(359, nIndStages <= 4, "GXSetNumIndStages: Exceeds max. number of indirect texture stages");
SET_REG_FIELD(360, __GXData->genMode, 3, 16, nIndStages);
__GXData->dirtyState |= 6;
}
void GXSetTevDirect(GXTevStageID tev_stage) {
CHECK_GXBEGIN(377, "GXSetTevDirect");
GXSetTevIndirect(tev_stage, GX_INDTEXSTAGE0, GX_ITF_8, GX_ITB_NONE, GX_ITM_OFF, GX_ITW_OFF, GX_ITW_OFF, GX_FALSE, GX_FALSE, GX_ITBA_OFF);
}
void 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(395, "GXSetTevIndWarp");
GXSetTevIndirect(tev_stage, ind_stage, GX_ITF_8, (signed_offset != 0) ? GX_ITB_STU : GX_ITB_NONE, matrix_sel, wrap, wrap, GX_FALSE, GX_FALSE, GX_ITBA_OFF);
}
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(429, "GXSetTevIndTile");
ASSERTMSGLINE(430, tev_stage < GX_MAX_TEVSTAGE, "GXSetTevIndTile: Invalid tev stage id");
ASSERTMSGLINE(431, ind_stage < GX_MAX_INDTEXSTAGE, "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(440, 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(452, 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, 10);
GXSetTevIndirect(tev_stage, ind_stage, format, bias_sel, matrix_sel, wrap_s, wrap_t, GX_FALSE, GX_TRUE, alpha_sel);
}
void GXSetTevIndBumpST(GXTevStageID tev_stage, GXIndTexStageID ind_stage, GXIndTexMtxID matrix_sel) {
GXIndTexMtxID sm;
GXIndTexMtxID tm;
CHECK_GXBEGIN(492, "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(509, 0, "GXSetTevIndBumpST: Invalid matrix selection");
break;
}
GXSetTevIndirect(tev_stage, ind_stage, GX_ITF_8, GX_ITB_ST, sm, GX_ITW_0, GX_ITW_0, GX_FALSE, GX_FALSE, GX_ITBA_OFF);
GXSetTevIndirect(tev_stage + 1, ind_stage, GX_ITF_8, GX_ITB_ST, tm, GX_ITW_0, GX_ITW_0, GX_TRUE, GX_FALSE, GX_ITBA_OFF);
GXSetTevIndirect(tev_stage + 2, ind_stage, GX_ITF_8, GX_ITB_NONE, GX_ITM_OFF, GX_ITW_OFF, GX_ITW_OFF, GX_TRUE, GX_FALSE, GX_ITBA_OFF);
}
void GXSetTevIndBumpXYZ(GXTevStageID tev_stage, GXIndTexStageID ind_stage, GXIndTexMtxID matrix_sel) {
CHECK_GXBEGIN(561, "GXSetTevIndBumpXYZ");
GXSetTevIndirect(tev_stage, ind_stage, GX_ITF_8, GX_ITB_STU, matrix_sel, GX_ITW_OFF, GX_ITW_OFF, GX_FALSE, GX_FALSE, GX_ITBA_OFF);
}
void GXSetTevIndRepeat(GXTevStageID tev_stage) {
CHECK_GXBEGIN(590, "GXSetTevIndRepeat");
GXSetTevIndirect(tev_stage, GX_INDTEXSTAGE0, GX_ITF_8, GX_ITB_NONE, GX_ITM_OFF, GX_ITW_0, GX_ITW_0, GX_TRUE, GX_FALSE, GX_ITBA_OFF);
}
void __GXUpdateBPMask(void) {}
void __GXSetIndirectMask(u32 mask) {
SET_REG_FIELD(668, __GXData->bpMask, 8, ~0xFF, mask);
GX_WRITE_SOME_REG5(GX_LOAD_BP_REG, __GXData->bpMask);
__GXData->bpSentNot = 0;
}
void __GXFlushTextureState(void) {
GX_WRITE_SOME_REG5(GX_LOAD_BP_REG, __GXData->bpMask);
__GXData->bpSentNot = 0;
}
+99
View File
@@ -0,0 +1,99 @@
#include <string.h>
#include <revolution/gx.h>
#include <revolution/os.h>
#include "__gx.h"
static __GXFifoObj DisplayListFifo;
static volatile __GXFifoObj* OldCPUFifo;
static GXData __savedGXdata;
void GXBeginDisplayList(void* list, u32 size) {
__GXFifoObj* CPUFifo = (__GXFifoObj*)GXGetCPUFifo();
CHECK_GXBEGIN(137, "GXBeginDisplayList");
ASSERTMSGLINE(138, !__GXData->inDispList, "GXBeginDisplayList: display list already in progress");
ASSERTMSGLINE(139, (size & 0x1F) == 0, "GXBeginDisplayList: size is not 32 byte aligned");
ASSERTMSGLINE(140, ((u32)list & 0x1F) == 0, "GXBeginDisplayList: list is not 32 byte aligned");
if (__GXData->dirtyState != 0) {
__GXSetDirtyState();
}
if (__GXData->dlSaveContext != 0) {
memcpy(&__savedGXdata, __GXData, sizeof(__savedGXdata));
}
DisplayListFifo.base = (u8*)list;
DisplayListFifo.top = (u8*)list + size - 4;
DisplayListFifo.size = size;
DisplayListFifo.count = 0;
DisplayListFifo.rdPtr = list;
DisplayListFifo.wrPtr = list;
__GXData->inDispList = 1;
GXSaveCPUFifo((GXFifoObj*)CPUFifo);
OldCPUFifo = CPUFifo;
GXSetCPUFifo((GXFifoObj*)&DisplayListFifo);
GXResetWriteGatherPipe();
}
u32 GXEndDisplayList(void) {
u32 ov;
#if DEBUG
u32 reg;
#endif
BOOL enabled;
u32 cpenable;
CHECK_GXBEGIN(195, "GXEndDisplayList");
ASSERTMSGLINE(196, __GXData->inDispList == TRUE, "GXEndDisplayList: no display list in progress");
GXFlush();
#if DEBUG
reg = GX_GET_PI_REG(5);
ov = (reg >> 26) & 1;
#else
ov = (GX_GET_PI_REG(5) >> 26) & 1;
#endif
__GXSaveCPUFifoAux(&DisplayListFifo);
ASSERTMSGLINE(213, !ov, "GXEndDisplayList: display list commands overflowed buffer");
GXSetCPUFifo((GXFifoObj*)OldCPUFifo);
if (__GXData->dlSaveContext != 0) {
enabled = OSDisableInterrupts();
cpenable = __GXData->cpEnable;
memcpy(__GXData, &__savedGXdata, sizeof(*__GXData));
__GXData->cpEnable = cpenable;
OSRestoreInterrupts(enabled);
}
__GXData->inDispList = 0;
if (!ov) {
return DisplayListFifo.count;
}
return 0;
}
void GXCallDisplayList(void* list, u32 nbytes) {
CHECK_GXBEGIN(272, "GXCallDisplayList");
ASSERTMSGLINE(273, !__GXData->inDispList, "GXCallDisplayList: display list already in progress");
ASSERTMSGLINE(274, (nbytes & 0x1F) == 0, "GXCallDisplayList: nbytes is not 32 byte aligned");
ASSERTMSGLINE(275, ((u32)list & 0x1F) == 0, "GXCallDisplayList: list is not 32 byte aligned");
if (__GXData->dirtyState != 0) {
__GXSetDirtyState();
}
#if DEBUG
__GXShadowDispList(list, nbytes);
#endif
if (*(u32*)&__GXData->vNumNot == 0) { // checks both vNum and bpSent
__GXSendFlushPrim();
}
GX_WRITE_U8(GX_CMD_CALL_DL);
GX_WRITE_U32(list);
GX_WRITE_U32(nbytes);
}
+551
View File
@@ -0,0 +1,551 @@
#include <math.h>
#include <revolution/gx.h>
#include <revolution/os.h>
#include "__gx.h"
static GXVtxDescList vcd[27];
static GXVtxAttrFmtList vat[27];
static void GetVertState(void) {
GXGetVtxDescv(vcd);
GXGetVtxAttrFmtv(GX_VTXFMT3, vat);
GXClearVtxDesc();
GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
GXSetVtxDesc(GX_VA_NRM, GX_DIRECT);
GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0);
}
static void RestoreVertState(void) {
GXSetVtxDescv(vcd);
GXSetVtxAttrFmtv(GX_VTXFMT3, vat);
}
static void vsub(f32 p1[3], f32 p2[3], f32 u[3]) {
u32 i;
for (i = 0; i < 3; i++) {
u[i] = p2[i] - p1[i];
}
}
static void vcross(f32 u[3], f32 v[3], f32 n[3]) {
f32 n1[3];
n1[0] = (u[1] * v[2]) - (u[2] * v[1]);
n1[1] = (u[2] * v[0]) - (u[0] * v[2]);
n1[2] = (u[0] * v[1]) - (u[1] * v[0]);
n[0] = n1[0];
n[1] = n1[1];
n[2] = n1[2];
}
static void normalize(f32 v[3]) {
f32 d = sqrtf((v[0] * v[0]) + (v[1] * v[1]) + (v[2] * v[2]));
ASSERTMSGLINE(137, d != 0.0f, "normalize: zero length vector");
v[0] /= d;
v[1] /= d;
v[2] /= d;
}
static void myvertex(f32 v[3], f32 n[3]) {
GXPosition3f32(v[0], v[1], v[2]);
GXNormal3f32(n[0], n[1], n[2]);
}
static void DumpTriangle(f32 v0[3], f32 v1[3], f32 v2[3]) {
GXBegin(GX_TRIANGLES, GX_VTXFMT3, 3);
myvertex(v0, v0);
myvertex(v1, v1);
myvertex(v2, v2);
GXEnd();
}
static void Subdivide(u8 depth, f32 v0[3], f32 v1[3], f32 v2[3]) {
f32 v01[3];
f32 v12[3];
f32 v20[3];
u32 i;
if (depth == 0) {
DumpTriangle(v0, v1, v2);
return;
}
for (i = 0; i < 3; i++) {
v01[i] = v0[i] + v1[i];
v12[i] = v1[i] + v2[i];
v20[i] = v2[i] + v0[i];
}
normalize(v01);
normalize(v12);
normalize(v20);
Subdivide(depth - 1, v0, v01, v20);
Subdivide(depth - 1, v1, v12, v01);
Subdivide(depth - 1, v2, v20, v12);
Subdivide(depth - 1, v01, v12, v20);
}
static void SubDivTriangle(u8 depth, u8 i, f32 (*data)[3], u8 (*ndx)[3]) {
f32 *x0 = data[ndx[i][0]];
f32 *x1 = data[ndx[i][1]];
f32 *x2 = data[ndx[i][2]];
Subdivide(depth, x0, x1, x2);
}
void GXDrawCylinder(u8 numEdges) {
s32 i;
f32 top;
f32 bottom;
f32 x[100];
f32 y[100];
f32 angle;
top = 1.0f;
bottom = -top;
ASSERTMSGLINE(222, numEdges <= 99, "GXDrawCylinder: too many edges");
GetVertState();
for (i = 0; i <= numEdges; i++) {
angle = (3.1415927f * (2.0f * i)) / numEdges;
x[i] = cosf(angle);
y[i] = sinf(angle);
}
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT3, (numEdges + 1) * 2);
for (i = 0; i <= numEdges; i++) {
GXPosition3f32(x[i], y[i], bottom);
GXNormal3f32(x[i], y[i], 0.0f);
GXPosition3f32(x[i], y[i], top);
GXNormal3f32(x[i], y[i], 0.0f);
}
GXEnd();
GXBegin(GX_TRIANGLEFAN, GX_VTXFMT3, numEdges + 2);
GXPosition3f32(0.0f, 0.0f, top);
GXNormal3f32(0.0f, 0.0f, 1.0f);
for (i = 0; i <= numEdges; i++) {
GXPosition3f32(x[i], -y[i], top);
GXNormal3f32(0.0f, 0.0f, 1.0f);
}
GXEnd();
GXBegin(GX_TRIANGLEFAN, GX_VTXFMT3, numEdges + 2);
GXPosition3f32(0.0f, 0.0f, bottom);
GXNormal3f32(0.0f, 0.0f, -1.0f);
for (i = 0; i <= numEdges; i++) {
GXPosition3f32(x[i], y[i], bottom);
GXNormal3f32(0.0f, 0.0f, -1.0f);
}
GXEnd();
RestoreVertState();
}
void GXDrawTorus(f32 rc, u8 numc, u8 numt) {
GXAttrType ttype;
s32 i, j, k;
f32 s, t;
f32 x, y, z;
f32 twopi = 6.2831855f;
f32 rt;
ASSERTMSGLINE(316, rc < 1.0f, "GXDrawTorus: doughnut too fat");
rt = 1.0f - rc;
GXGetVtxDesc(GX_VA_TEX0, &ttype);
GetVertState();
if (ttype != GX_NONE) {
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
}
for (i = 0; i < numc; i++) {
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT3, (numt + 1) * 2);
for (j = 0; j <= numt; j++) {
for (k = 1; k >= 0; k--) {
s = (i + k) % numc;
t = j % numt;
x = (rt - rc * cosf(s * twopi / numc)) * cosf(t * twopi / numt);
y = (rt - rc * cosf(s * twopi / numc)) * sinf(t * twopi / numt);
z = rc * sinf(s * twopi / numc);
GXPosition3f32(x, y, z);
x = -cosf(t * twopi / numt) * cosf(s * twopi / numc);
y = -sinf(t * twopi / numt) * cosf(s * twopi / numc);
z = sinf(s * twopi / numc);
GXNormal3f32(x, y, z);
if (ttype != GX_NONE) {
GXTexCoord2f32((i + k) / (f32)numc, j / (f32)numt);
}
}
}
GXEnd();
}
RestoreVertState();
}
void GXDrawSphere(u8 numMajor, u8 numMinor) {
GXAttrType ttype;
f32 radius = 1.0f;
f32 majorStep = 3.1415927f / numMajor;
f32 minorStep = 6.2831855f / numMinor;
s32 i, j;
f32 a, b;
f32 r0, r1;
f32 z0, z1;
f32 c;
GXGetVtxDesc(GX_VA_TEX0, &ttype);
GetVertState();
if (ttype != GX_NONE) {
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_TEX0, GX_TEX_ST, GX_RGBA6, 0);
}
for (i = 0; i < numMajor; i++) {
a = i * majorStep;
b = a + majorStep;
r0 = radius * sinf(a);
r1 = radius * sinf(b);
z0 = radius * cosf(a);
z1 = radius * cosf(b);
GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT3, (numMinor + 1) * 2);
for (j = 0; j <= numMinor; j++) {
f32 x, y;
c = j * minorStep;
x = cosf(c);
y = sinf(c);
GXPosition3f32(x * r1, y * r1, z1);
GXNormal3f32((x * r1) / radius, (y * r1) / radius, z1 / radius);
if (ttype != GX_NONE) {
GXTexCoord2f32((f32)j / (f32)numMinor, (f32)(i + 1) / (f32)numMajor);
}
GXPosition3f32(x * r0, y * r0, z0);
GXNormal3f32((x * r0) / radius, (y * r0) / radius, z0 / radius);
if (ttype != GX_NONE) {
GXTexCoord2f32((f32)j / (f32)numMinor, (f32)i / (f32)numMajor);
}
}
GXEnd();
}
RestoreVertState();
}
static void GXDrawCubeFace(f32 nx, f32 ny, f32 nz, f32 tx, f32 ty, f32 tz, f32 bx, f32 by, f32 bz, GXAttrType binormal, GXAttrType texture) {
GXPosition3f32(0.57735026f * (nx + tx + bx), 0.57735026f * (ny + ty + by), 0.57735026f * (nz + tz + bz));
GXNormal3f32(nx, ny, nz);
if (binormal != GX_NONE) {
GXNormal3f32(tx, ty, tz);
GXNormal3f32(bx, by, bz);
}
if (texture != GX_NONE) {
GXTexCoord2s8(1, 1);
}
GXPosition3f32(0.57735026f * (nx - tx + bx), 0.57735026f * (ny - ty + by), 0.57735026f * (nz - tz + bz));
GXNormal3f32(nx, ny, nz);
if (binormal != GX_NONE) {
GXNormal3f32(tx, ty, tz);
GXNormal3f32(bx, by, bz);
}
if (texture != GX_NONE) {
GXTexCoord2s8(0, 1);
}
GXPosition3f32(0.57735026f * (nx - tx - bx), 0.57735026f * (ny - ty - by), 0.57735026f * (nz - tz - bz));
GXNormal3f32(nx, ny, nz);
if (binormal != GX_NONE) {
GXNormal3f32(tx, ty, tz);
GXNormal3f32(bx, by, bz);
}
if (texture != GX_NONE) {
GXTexCoord2s8(0, 0);
}
GXPosition3f32(0.57735026f * (nx + tx - bx), 0.57735026f * (ny + ty - by), 0.57735026f * (nz + tz - bz));
GXNormal3f32(nx, ny, nz);
if (binormal != GX_NONE) {
GXNormal3f32(tx, ty, tz);
GXNormal3f32(bx, by, bz);
}
if (texture != GX_NONE) {
GXTexCoord2s8(1, 0);
}
}
void GXDrawCube(void) {
GXAttrType ntype;
GXAttrType ttype;
GXGetVtxDesc(GX_VA_NBT, &ntype);
GXGetVtxDesc(GX_VA_TEX0, &ttype);
GetVertState();
if (ntype != GX_NONE) {
GXSetVtxDesc(GX_VA_NBT, GX_DIRECT);
GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_NBT, GX_TEX_ST, GX_RGBA6, 0);
}
if (ttype != GX_NONE) {
GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GXSetVtxAttrFmt(GX_VTXFMT3, GX_VA_TEX0, GX_TEX_ST, GX_RGB8, 0);
}
GXBegin(GX_QUADS, GX_VTXFMT3, 24);
GXDrawCubeFace(-1.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, ntype, ttype);
GXDrawCubeFace(1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, -1.0f, ntype, ttype);
GXDrawCubeFace(0.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, ntype, ttype);
GXDrawCubeFace(0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, 0.0f, ntype, ttype);
GXDrawCubeFace(0.0f, 0.0f, -1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, ntype, ttype);
GXDrawCubeFace(0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, -1.0f, 0.0f, ntype, ttype);
GXEnd();
RestoreVertState();
}
static u32 polygons[12][5] = {
{ 0, 12, 10, 11, 16 },
{ 1, 17, 8, 9, 13 },
{ 2, 14, 9, 8, 18 },
{ 3, 19, 11, 10, 15 },
{ 4, 14, 2, 3, 15 },
{ 5, 12, 0, 1, 13 },
{ 6, 17, 1, 0, 16 },
{ 7, 19, 3, 2, 18 },
{ 8, 17, 6, 7, 18 },
{ 9, 14, 4, 5, 13 },
{ 10, 12, 5, 4, 15 },
{ 11, 19, 7, 6, 16 },
};
static f32 verts[20][3] = {
{ -0.809015f, 0.0f, 0.309015f },
{ -0.809015f, 0.0f, -0.309015f },
{ 0.809015f, 0.0f, -0.309015f },
{ 0.809015f, 0.0f, 0.309015f },
{ 0.309015f, -0.809015f, 0.0f },
{ -0.309015f, -0.809015f, 0.0f },
{ -0.309015f, 0.809015f, 0 },
{ 0.309015f, 0.809015f, 0 },
{ 0.0f, 0.309015f, -0.809015f },
{ 0.0f, -0.309015f, -0.809015f },
{ 0.0f, -0.309015f, 0.809015f },
{ 0.0f, 0.309015f, 0.809015f },
{ -0.5f, -0.5f, 0.5 },
{ -0.5f, -0.5f, -0.5 },
{ 0.5f, -0.5f, -0.5 },
{ 0.5f, -0.5f, 0.5 },
{ -0.5f, 0.5f, 0.5 },
{ -0.5f, 0.5f, -0.5 },
{ 0.5f, 0.5f, -0.5 },
{ 0.5f, 0.5f, 0.5 },
};
void GXDrawDodeca(void) {
u32 i;
f32 *p0;
f32 *p1;
f32 *p2;
f32 u[3];
f32 v[3];
f32 n[3];
GetVertState();
for (i = 0; i < 12; i++) {
p0 = verts[polygons[i][0]];
p1 = verts[polygons[i][1]];
p2 = verts[polygons[i][2]];
vsub(p1, p2, u);
vsub(p1, p0, v);
vcross(u, v, n);
normalize(n);
GXBegin(GX_TRIANGLEFAN, GX_VTXFMT3, 5);
myvertex(verts[polygons[i][4]], n);
myvertex(verts[polygons[i][3]], n);
myvertex(p2, n);
myvertex(p1, n);
myvertex(p0, n);
GXEnd();
}
RestoreVertState();
}
static f32 odata[6][3] = {
{ 1.0f, 0.0f, 0.0f },
{ -1.0f, 0.0f, 0.0f },
{ 0.0f, 1.0f, 0.0f },
{ 0.0f, -1.0f, 0.0f },
{ 0.0f, 0.0f, 1.0f },
{ 0.0f, 0.0f, -1.0f },
};
static u8 ondex[8][3] = {
{ 0, 4, 2 },
{ 1, 2, 4 },
{ 0, 3, 4 },
{ 1, 4, 3 },
{ 0, 2, 5 },
{ 1, 5, 2 },
{ 0, 5, 3 },
{ 1, 3, 5 },
};
void GXDrawOctahedron(void) {
s32 i;
GetVertState();
for (i = 7; i >= 0; i--) {
SubDivTriangle(0, i, odata, ondex);
}
RestoreVertState();
}
static f32 idata[12][3] = {
{ -0.5257311f, 0.0f, 0.8506508f },
{ 0.5257311f, 0.0f, 0.8506508f },
{ -0.5257311f, 0.0f, -0.8506508f },
{ 0.5257311f, 0.0f, -0.8506508f },
{ 0.0f, 0.8506508f, 0.5257311f },
{ 0.0f, 0.8506508f, -0.5257311f },
{ 0.0f, -0.8506508f, 0.5257311f },
{ 0.0f, -0.8506508f, -0.5257311f },
{ 0.8506508f, 0.5257311f, 0.0f },
{ -0.8506508f, 0.5257311f, 0.0f },
{ 0.8506508f, -0.5257311f, 0.0f },
{ -0.8506508f, -0.5257311f, 0.0f },
};
static u8 index[20][3] = {
{ 0, 4, 1 },
{ 0, 9, 4 },
{ 9, 5, 4 },
{ 4, 5, 8 },
{ 4, 8, 1 },
{ 8, 10, 1 },
{ 8, 3, 10 },
{ 5, 3, 8 },
{ 5, 2, 3 },
{ 2, 7, 3 },
{ 7, 10, 3 },
{ 7, 6, 10 },
{ 7, 11, 6 },
{ 11, 0, 6 },
{ 0, 1, 6 },
{ 6, 1, 10 },
{ 9, 0, 11 },
{ 9, 11, 2 },
{ 9, 2, 5 },
{ 7, 2, 11 },
};
void GXDrawIcosahedron(void) {
s32 i;
GetVertState();
for (i = 19; i >= 0; i--) {
SubDivTriangle(0, i, idata, index);
}
RestoreVertState();
}
void GXDrawSphere1(u8 depth) {
s32 i;
GetVertState();
for (i = 19; i >= 0; i--) {
SubDivTriangle(depth, i, idata, index);
}
RestoreVertState();
}
static u32 CmpNormal32(f32 n1[3], f32 n2[3]) {
u32 i;
for (i = 0; i < 3; i++) {
if (n1[i] != n2[i])
return FALSE;
}
return TRUE;
}
static u32 nrm_cnt;
static f32* nrm_tab;
static void AddNormal(f32 n[3]) {
u32 indx;
u32 i;
for (i = 0; i < nrm_cnt; i++) {
if (CmpNormal32(n, &nrm_tab[i * 3]))
return;
}
indx = nrm_cnt * 3;
nrm_tab[indx + 0] = n[0];
nrm_tab[indx + 1] = n[1];
nrm_tab[indx + 2] = n[2];
nrm_cnt++;
}
static void SubdivideNrm(u8 depth, f32 v0[3], f32 v1[3], f32 v2[3]) {
f32 v01[3];
f32 v12[3];
f32 v20[3];
u32 i;
if (depth == 0) {
AddNormal(v0);
AddNormal(v1);
AddNormal(v2);
return;
}
for (i = 0; i < 3; i++) {
v01[i] = v0[i] + v1[i];
v12[i] = v1[i] + v2[i];
v20[i] = v2[i] + v0[i];
}
normalize(v01);
normalize(v12);
normalize(v20);
SubdivideNrm(depth - 1, v0, v01, v20);
SubdivideNrm(depth - 1, v1, v12, v01);
SubdivideNrm(depth - 1, v2, v20, v12);
SubdivideNrm(depth - 1, v01, v12, v20);
}
static void SubDivNrm(u8 depth, u8 i, f32 (*data)[3], u8 (*ndx)[3]) {
f32* x0 = data[ndx[i][0]];
f32* x1 = data[ndx[i][1]];
f32* x2 = data[ndx[i][2]];
SubdivideNrm(depth, x0, x1, x2);
}
u32 GXGenNormalTable(u8 depth, f32* table) {
s32 i;
nrm_cnt = 0;
nrm_tab = table;
for (i = 7; i >= 0; i--) {
SubDivNrm(depth, i, odata, ondex);
}
return nrm_cnt;
}
+614
View File
@@ -0,0 +1,614 @@
#include <revolution/base/PPCArch.h>
#include <revolution/gx.h>
#include <revolution/os.h>
#include "__gx.h"
#define TOPHYSICAL(a) (((u32)a) & 0x3FFFFFFF)
static __GXFifoObj CPUFifo;
static __GXFifoObj GPFifo;
static GXBool CPUFifoReady = FALSE;
static GXBool GPFifoReady = FALSE;
static GXBool CPGPLinked;
static OSThread* __GXCurrentThread;
static BOOL GXOverflowSuspendInProgress;
static GXBreakPtCallback BreakPointCB;
void* __GXCurrentBP;
static u32 __GXOverflowCount;
#if DEBUG
static BOOL IsWGPipeRedirected;
#endif
static void __GXFifoReadEnable(void);
static void __GXFifoReadDisable(void);
static void __GXFifoLink(u8 en);
static void __GXWriteFifoIntEnable(u8 hiWatermarkEn, u8 loWatermarkEn);
static void __GXWriteFifoIntReset(u8 hiWatermarkClr, u8 loWatermarkClr);
GXBool CPGPLinkCheck(void);
static void GXOverflowHandler(__OSInterrupt interrupt, OSContext* context) {
#if DEBUG
if (__gxVerif->verifyLevel > GX_WARN_SEVERE) {
OSReport("[GXOverflowHandler]");
}
#endif
ASSERTLINE(417, !GXOverflowSuspendInProgress);
__GXOverflowCount++;
__GXWriteFifoIntEnable(0, 1);
__GXWriteFifoIntReset(1, 0);
GXOverflowSuspendInProgress = TRUE;
#if DEBUG
if (__gxVerif->verifyLevel > GX_WARN_SEVERE) {
OSReport("[GXOverflowHandler Sleeping]");
}
#endif
OSSuspendThread(__GXCurrentThread);
}
static void GXUnderflowHandler(s16 interrupt, OSContext* context) {
#if DEBUG
if (__gxVerif->verifyLevel > GX_WARN_SEVERE) {
OSReport("[GXUnderflowHandler]");
}
#endif
ASSERTLINE(459, GXOverflowSuspendInProgress);
OSResumeThread(__GXCurrentThread);
GXOverflowSuspendInProgress = FALSE;
__GXWriteFifoIntReset(1, 1);
__GXWriteFifoIntEnable(1, 0);
}
static void GXBreakPointHandler(__OSInterrupt interrupt, OSContext* context) {
OSContext exceptionContext;
SC_CP_REG_ENABLE_SET_FIFOBRKINT(0, __GXData->cpEnable, 0);
GX_CP_REG_WRITE_U16(CP_ENABLE, __GXData->cpEnable);
if (BreakPointCB != 0) {
OSClearContext(&exceptionContext);
OSSetCurrentContext(&exceptionContext);
BreakPointCB();
OSClearContext(&exceptionContext);
OSSetCurrentContext(context);
}
}
static void GXCPInterruptHandler(__OSInterrupt interrupt, OSContext* context) {
__GXData->cpStatus = GX_GET_CP_REG(0);
if (CP_REG_ENABLE_GET_UNFLINT(__GXData->cpEnable) && CP_REG_STATUS_GET_UNFL(__GXData->cpStatus)) {
GXUnderflowHandler(interrupt, context);
}
if (CP_REG_ENABLE_GET_OVFLINT(__GXData->cpEnable) && CP_REG_STATUS_GET_OVFL(__GXData->cpStatus)) {
GXOverflowHandler(interrupt, context);
}
if (CP_REG_ENABLE_GET_FIFOBRKINT(__GXData->cpEnable) && CP_REG_STATUS_GET_FIFOBRK(__GXData->cpStatus)) {
GXBreakPointHandler(interrupt, context);
}
}
void GXInitFifoBase(GXFifoObj* fifo, void* base, u32 size) {
__GXFifoObj* realFifo = (__GXFifoObj*)fifo;
ASSERTMSGLINE(582, ((u32)base & 0x1F) == 0, "GXInitFifoBase: base must be 32B aligned");
ASSERTMSGLINE(584, base != 0, "GXInitFifoBase: base pointer is NULL");
ASSERTMSGLINE(586, (size & 0x1F) == 0, "GXInitFifoBase: size must be 32B aligned");
ASSERTMSGLINE(588, 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) {
__GXFifoObj* realFifo = (__GXFifoObj *)fifo;
BOOL enabled;
ASSERTMSGLINE(628, ((u32)readPtr & 0x1F) == 0, "GXInitFifoPtrs: readPtr not 32B aligned");
ASSERTMSGLINE(630, ((u32)writePtr & 0x1F) == 0, "GXInitFifoPtrs: writePtr not 32B aligned");
ASSERTMSGLINE(633, realFifo->base <= readPtr && readPtr < realFifo->top, "GXInitFifoPtrs: readPtr not in fifo range");
ASSERTMSGLINE(636, 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) {
__GXFifoObj* realFifo = (__GXFifoObj*)fifo;
ASSERTMSGLINE(674, (hiWatermark & 0x1F) == 0, "GXInitFifoLimits: hiWatermark not 32B aligned");
ASSERTMSGLINE(676, (loWatermark & 0x1F) == 0, "GXInitFifoLimits: loWatermark not 32B aligned");
ASSERTMSGLINE(678, hiWatermark < realFifo->top - realFifo->base, "GXInitFifoLimits: hiWatermark too large");
ASSERTMSGLINE(680, loWatermark < hiWatermark, "GXInitFifoLimits: hiWatermark below lo watermark");
realFifo->hiWatermark = hiWatermark;
realFifo->loWatermark = loWatermark;
}
GXBool CPGPLinkCheck(void) {
u32 check = 0;
s32 range1, range2, overlap;
if (!CPUFifoReady || !GPFifoReady) {
return GX_FALSE;
}
if (CPUFifo.base == GPFifo.base) {
++check;
}
if (CPUFifo.top == GPFifo.top) {
++check;
}
if (check == 2) {
if (CPUFifo.hiWatermark == GPFifo.hiWatermark) {
++check;
}
if (CPUFifo.loWatermark == GPFifo.loWatermark) {
++check;
}
ASSERTMSGLINE(722, check == 4, "GXSetGPFifo/GXSetCPUFifo: mismatch of watermark parameter");
return GX_TRUE;
}
range1 = (s32)((u8*)CPUFifo.top - (u8*)GPFifo.base);
range2 = (s32)((u8*)GPFifo.top - (u8*)CPUFifo.base);
overlap = ((range1 > 0) && (range2 > 0) || (range1 < 0 && (range2 < 0)));
if (overlap) {
OSReport("CPUFifo: %08X - %08X\n", (u32)CPUFifo.base, (u32)CPUFifo.top);
OSReport("GP Fifo: %08X - %08X\n", (u32)GPFifo.base, (u32)GPFifo.top);
}
ASSERTMSGLINE(736, !overlap, "GXSetGPFifo/GXSetCPUFifo: invalid overlap of both buffers");
return GX_FALSE;
}
// NONMATCHING DEBUG
void GXSetCPUFifo(GXFifoObj* fifo) {
__GXFifoObj* realFifo = (__GXFifoObj*)fifo;
BOOL enabled = OSDisableInterrupts();
u32 reg;
if (fifo == NULL) {
CPUFifoReady = GX_FALSE;
CPGPLinked = GX_FALSE;
CPUFifo.bind_cpu = CPUFifo.bind_gp = GX_FALSE;
OSRestoreInterrupts(enabled);
return;
}
CPUFifo = *realFifo;
CPUFifoReady = GX_TRUE;
CPUFifo.bind_cpu = GX_TRUE;
if (CPGPLinkCheck()) {
CPGPLinked = GX_TRUE;
CPUFifo.bind_gp = GX_TRUE;
reg = 0;
GX_PI_REG_WRITE_U32(PI_REG_CPBAS, TOPHYSICAL(CPUFifo.base));
GX_PI_REG_WRITE_U32(PI_REG_CPTOP, TOPHYSICAL(CPUFifo.top));
SC_PI_CPWRT_REG_SET_CPWRT(787, reg, (GX_PHY_ADDR(TOPHYSICAL(CPUFifo.wrPtr)) >> 5));
SC_PI_CPWRT_REG_SET_CPWRAP(0, reg, 0);
GX_PI_REG_WRITE_U32(PI_REG_CPWRT, reg);
__GXWriteFifoIntReset(1, 1);
__GXWriteFifoIntEnable(1, 0);
__GXFifoLink(1);
} else {
CPUFifo.bind_gp = GX_FALSE;
if (CPGPLinked) {
__GXFifoLink(0);
CPGPLinked = GX_FALSE;
}
__GXWriteFifoIntEnable(0, 0);
reg = 0;
GX_PI_REG_WRITE_U32(PI_REG_CPBAS, TOPHYSICAL(CPUFifo.base));
GX_PI_REG_WRITE_U32(PI_REG_CPTOP, TOPHYSICAL(CPUFifo.top));
SC_PI_CPWRT_REG_SET_CPWRT(819, reg, (GX_PHY_ADDR(TOPHYSICAL(CPUFifo.wrPtr)) >> 5));
SC_PI_CPWRT_REG_SET_CPWRAP(0, reg, 0);
GX_PI_REG_WRITE_U32(PI_REG_CPWRT, reg);
}
PPCSync();
OSRestoreInterrupts(enabled);
}
void GXSetGPFifo(GXFifoObj* fifo) {
__GXFifoObj* realFifo = (__GXFifoObj*)fifo;
BOOL enabled;
u32 stbtmp;
ASSERTMSGLINE(850, ((u32)realFifo->base & 0x30000000) == 0, "GXSetGPFifo: GX Fifo should be located on MEM1 memory region");
enabled = OSDisableInterrupts();
__GXFifoReadDisable();
__GXWriteFifoIntEnable(0, 0);
if (fifo == NULL) {
GPFifoReady = GX_FALSE;
CPGPLinked = GX_FALSE;
__GXFifoLink(GX_FALSE);
GPFifo.bind_gp = GPFifo.bind_cpu = GX_FALSE;
OSRestoreInterrupts(enabled);
return;
}
GPFifo = *realFifo;
GPFifoReady = GX_TRUE;
GPFifo.bind_gp = GX_TRUE;
GX_CP_REG_WRITE_U16(CP_FIFO_BASEL, TOPHYSICAL(GPFifo.base));
GX_CP_REG_WRITE_U16(CP_FIFO_TOPL, TOPHYSICAL(GPFifo.top));
GX_CP_REG_WRITE_U16(CP_FIFO_COUNTL, GPFifo.count);
GX_CP_REG_WRITE_U16(CP_FIFO_WPTRL, TOPHYSICAL(GPFifo.wrPtr));
GX_CP_REG_WRITE_U16(CP_FIFO_RPTRL, TOPHYSICAL(GPFifo.rdPtr));
GX_CP_REG_WRITE_U16(CP_FIFO_HICNTL, GPFifo.hiWatermark);
GX_CP_REG_WRITE_U16(CP_FIFO_LOCNTL, GPFifo.loWatermark);
GX_CP_REG_WRITE_U16(CP_FIFO_BASEH, TOPHYSICAL(GPFifo.base) >> 16);
GX_CP_REG_WRITE_U16(CP_FIFO_TOPH, TOPHYSICAL(GPFifo.top) >> 16);
GX_CP_REG_WRITE_U16(CP_FIFO_COUNTH, GPFifo.count >> 16);
GX_CP_REG_WRITE_U16(CP_FIFO_WPTRH, TOPHYSICAL(GPFifo.wrPtr) >> 16);
GX_CP_REG_WRITE_U16(CP_FIFO_RPTRH, TOPHYSICAL(GPFifo.rdPtr) >> 16);
GX_CP_REG_WRITE_U16(CP_FIFO_HICNTH, GPFifo.hiWatermark >> 16);
GX_CP_REG_WRITE_U16(CP_FIFO_LOCNTH, GPFifo.loWatermark >> 16);
PPCSync();
if (CPGPLinkCheck()) {
CPGPLinked = GX_TRUE;
GPFifo.bind_cpu = GX_TRUE;
__GXWriteFifoIntEnable(GX_TRUE, GX_FALSE);
__GXFifoLink(GX_TRUE);
} else {
CPGPLinked = GX_FALSE;
GPFifo.bind_cpu = GX_FALSE;
__GXWriteFifoIntEnable(GX_FALSE, GX_FALSE);
__GXFifoLink(GX_FALSE);
}
stbtmp = __GXData->cpEnable;
SC_CP_REG_ENABLE_SET_FIFOBRK(0, stbtmp, 0);
SC_CP_REG_ENABLE_SET_FIFOBRKINT(0, stbtmp, 0);
GX_CP_REG_WRITE_U16(CP_ENABLE, stbtmp);
GX_CP_REG_WRITE_U16(CP_ENABLE, __GXData->cpEnable);
__GXWriteFifoIntReset(GX_TRUE, GX_TRUE);
__GXFifoReadEnable();
OSRestoreInterrupts(enabled);
}
#define CP_READ_2U16(dest,reg,type) \
{\
u32 temp; \
temp = (u32)GX_CP_REG_READ_U16(reg##H)<<16; \
temp |= (u32)GX_CP_REG_READ_U16(reg##L); \
dest = (type)OSPhysicalToCached(temp); \
}
#define CP_READ_2U16_INT(dest,reg,type) \
{\
u32 temp; \
temp = (u32)GX_CP_REG_READ_U16(reg##H)<<16; \
temp |= (u32)GX_CP_REG_READ_U16(reg##L); \
dest = (type)temp; \
}
static void __GXSaveFifoCPStat(void) {
CP_READ_2U16(GPFifo.rdPtr, CP_FIFO_RPTR, void*);
CP_READ_2U16_INT(GPFifo.count, CP_FIFO_COUNT, s32);
}
static void __GXSaveFifoPIStat(void) {
u32 reg = GX_PI_REG_READ_U32(PI_REG_CPWRT);
CPUFifo.wrPtr = OSPhysicalToCached(reg & PI_CPWRT_REG_CPWRT_MASK);
CPUFifo.wrap = (GXBool)((reg & PI_CPWRT_REG_CPWRAP_MASK) ? GX_TRUE : GX_FALSE);
}
void __GXSaveFifo(void) {
BOOL enabled = OSDisableInterrupts();
if (CPUFifoReady) {
__GXSaveFifoPIStat();
}
if (GPFifoReady) {
__GXSaveFifoCPStat();
}
if (CPGPLinked) {
CPUFifo.rdPtr = GPFifo.rdPtr;
CPUFifo.count = GPFifo.count;
GPFifo.wrPtr = CPUFifo.wrPtr;
GPFifo.wrap = CPUFifo.wrap;
} else if (CPUFifoReady) {
CPUFifo.count = (s32)CPUFifo.wrPtr - (s32)CPUFifo.rdPtr;
if (CPUFifo.count < 0) {
CPUFifo.count += CPUFifo.size;
}
}
OSRestoreInterrupts(enabled);
}
GXBool __GXIsGPFifoReady(void) {
return GPFifoReady;
}
void GXGetGPStatus(GXBool* overhi, GXBool* underlow, GXBool* readIdle, GXBool* cmdIdle, GXBool* brkpt) {
__GXData->cpStatus = GX_CP_REG_READ_U16(CP_STATUS);
*overhi = (u8)CP_REG_STATUS_GET_OVFL(__GXData->cpStatus);
*underlow = (u8)CP_REG_STATUS_GET_UNFL(__GXData->cpStatus);
*readIdle = (u8)CP_REG_STATUS_GET_FIFO_RDIDLE(__GXData->cpStatus);
*cmdIdle = (u8)CP_REG_STATUS_GET_CPIDLE(__GXData->cpStatus);
*brkpt = (u8)CP_REG_STATUS_GET_FIFOBRK(__GXData->cpStatus);
}
void GXGetFifoPtrs(GXFifoObj* fifo, void** readPtr, void** writePtr) {
__GXFifoObj* realFifo = (__GXFifoObj*)fifo;
*readPtr = realFifo->rdPtr;
*writePtr = realFifo->wrPtr;
}
void* GXGetFifoBase(const GXFifoObj* fifo) {
__GXFifoObj* realFifo = (__GXFifoObj*)fifo;
return realFifo->base;
}
u32 GXGetFifoSize(const GXFifoObj* fifo) {
__GXFifoObj* realFifo = (__GXFifoObj*)fifo;
return realFifo->size;
}
void GXGetFifoLimits(const GXFifoObj* fifo, u32* hi, u32* lo) {
__GXFifoObj* realFifo = (__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_CP_REG_WRITE_U16(CP_FIFO_BRKL, TOPHYSICAL(break_pt));
GX_CP_REG_WRITE_U16(CP_FIFO_BRKH, TOPHYSICAL(break_pt) >> 16);
SC_CP_REG_ENABLE_SET_FIFOBRK(0, __GXData->cpEnable, 0);
SC_CP_REG_ENABLE_SET_FIFOBRKINT(0, __GXData->cpEnable, 0);
GX_CP_REG_WRITE_U16(CP_ENABLE, __GXData->cpEnable);
SC_CP_REG_ENABLE_SET_FIFOBRK(0, __GXData->cpEnable, 1);
SC_CP_REG_ENABLE_SET_FIFOBRKINT(0, __GXData->cpEnable, 1);
GX_CP_REG_WRITE_U16(CP_ENABLE, __GXData->cpEnable);
__GXCurrentBP = break_pt;
__GXFifoReadEnable();
OSRestoreInterrupts(enabled);
}
void GXDisableBreakPt(void) {
BOOL enabled = OSDisableInterrupts();
SC_CP_REG_ENABLE_SET_FIFOBRK(0, __GXData->cpEnable, 0);
SC_CP_REG_ENABLE_SET_FIFOBRKINT(0, __GXData->cpEnable, 0);
GX_CP_REG_WRITE_U16(CP_ENABLE, __GXData->cpEnable);
__GXCurrentBP = NULL;
OSRestoreInterrupts(enabled);
}
void __GXFifoInit(void) {
__OSSetInterruptHandler(0x11, GXCPInterruptHandler);
__OSUnmaskInterrupts(0x4000);
__GXCurrentThread = OSGetCurrentThread();
GXOverflowSuspendInProgress = FALSE;
memset(&CPUFifo, 0, sizeof(__GXFifoObj));
memset(&GPFifo, 0, sizeof(__GXFifoObj));
CPUFifoReady = GX_FALSE;
GPFifoReady = GX_FALSE;
}
static void __GXFifoReadEnable(void) {
SC_CP_REG_ENABLE_SET_FIFORD(0, __GXData->cpEnable, 1);
GX_CP_REG_WRITE_U16(CP_ENABLE, (u16)__GXData->cpEnable);
}
static void __GXFifoReadDisable(void) {
SC_CP_REG_ENABLE_SET_FIFORD(0, __GXData->cpEnable, 0);
GX_CP_REG_WRITE_U16(CP_ENABLE, (u16)__GXData->cpEnable);
}
static void __GXFifoLink(u8 en) {
SC_CP_REG_ENABLE_SET_WRPTRINC(1385, __GXData->cpEnable, (en ? 0x1 : 0));
GX_CP_REG_WRITE_U16(CP_ENABLE, (u16)__GXData->cpEnable);
}
static void __GXWriteFifoIntEnable(u8 hiWatermarkEn, u8 loWatermarkEn) {
SC_CP_REG_ENABLE_SET_OVFLINT(1407, __GXData->cpEnable, hiWatermarkEn);
SC_CP_REG_ENABLE_SET_UNFLINT(1408, __GXData->cpEnable, loWatermarkEn);
GX_CP_REG_WRITE_U16(CP_ENABLE, (u16)__GXData->cpEnable);
}
static void __GXWriteFifoIntReset(u8 hiWatermarkClr, u8 loWatermarkClr) {
SC_CP_REG_CLR_SET_OVFLINT(1431, __GXData->cpClr, hiWatermarkClr);
SC_CP_REG_CLR_SET_UNFLINT(1432, __GXData->cpClr, loWatermarkClr);
GX_CP_REG_WRITE_U16(CP_CLR, (u16)__GXData->cpClr);
}
void __GXCleanGPFifo(void) {
BOOL enabled;
if ( !GPFifoReady) {
return;
}
enabled = OSDisableInterrupts();
__GXFifoReadDisable();
__GXWriteFifoIntEnable(GX_FALSE, GX_FALSE);
GPFifo.rdPtr = GPFifo.wrPtr;
GPFifo.count = 0;
GX_CP_REG_WRITE_U16(CP_FIFO_COUNTL, GPFifo.count);
GX_CP_REG_WRITE_U16(CP_FIFO_WPTRL, TOPHYSICAL(GPFifo.wrPtr));
GX_CP_REG_WRITE_U16(CP_FIFO_RPTRL, TOPHYSICAL(GPFifo.rdPtr));
GX_CP_REG_WRITE_U16(CP_FIFO_COUNTH, GPFifo.count>>16);
GX_CP_REG_WRITE_U16(CP_FIFO_WPTRH, TOPHYSICAL(GPFifo.wrPtr)>>16);
GX_CP_REG_WRITE_U16(CP_FIFO_RPTRH, TOPHYSICAL(GPFifo.rdPtr)>>16);
PPCSync();
if (CPGPLinked) {
u32 reg = 0;
CPUFifo.rdPtr = GPFifo.rdPtr;
CPUFifo.wrPtr = GPFifo.wrPtr;
CPUFifo.count = GPFifo.count;
SC_PI_CPWRT_REG_SET_CPWRT(1501, reg, (GX_PHY_ADDR(TOPHYSICAL(CPUFifo.wrPtr)) >> 5));
SC_PI_CPWRT_REG_SET_CPWRAP(0, reg, 0);
GX_PI_REG_WRITE_U32(PI_REG_CPWRT, reg);
__GXWriteFifoIntEnable(GX_TRUE, GX_FALSE);
__GXFifoLink(GX_TRUE);
}
SC_CP_REG_ENABLE_SET_FIFOBRK(0, __GXData->cpEnable, 0);
SC_CP_REG_ENABLE_SET_FIFOBRKINT(0, __GXData->cpEnable, 0);
GX_CP_REG_WRITE_U16(CP_ENABLE, __GXData->cpEnable);
__GXCurrentBP = 0;
__GXWriteFifoIntReset(GX_TRUE, GX_TRUE);
__GXFifoReadEnable();
OSRestoreInterrupts(enabled);
}
OSThread* GXSetCurrentGXThread(void) {
BOOL enabled;
OSThread* prev;
enabled = OSDisableInterrupts();
prev = __GXCurrentThread;
ASSERTMSGLINE(1541, !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(0, "GXRedirectWriteGatherPipe");
ASSERTLINE(0, OFFSET(ptr, 32) == 0);
ASSERTLINE(0, !IsWGPipeRedirected);
#if DEBUG
IsWGPipeRedirected = TRUE;
#endif
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(0, 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;
u32 i;
BOOL enabled;
ASSERTLINE(1552, IsWGPipeRedirected);
#if DEBUG
IsWGPipeRedirected = FALSE;
#endif
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(1578, 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);
}
+677
View File
@@ -0,0 +1,677 @@
#include <revolution/gx.h>
#include <revolution/os.h>
#include "__gx.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 GXMpal480Prog = {
10,
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 GXMpal480ProgSoft = {
10,
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 GXMpal480ProgAa = {
10,
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 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 GXEurgb60Hz480Prog = {
22,
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 GXEurgb60Hz480ProgSoft = {
22,
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 GXEurgb60Hz480ProgAa = {
22,
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 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(const 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 && mode == 0) {
rmout->xfbHeight = rmin->xfbHeight - ver2 / 2;
} else {
rmout->xfbHeight = rmin->xfbHeight - ver2;
}
rmout->viWidth = rmin->viWidth - hor2;
if (mode == 1) {
rmout->viHeight = rmin->viHeight - (ver2 * 2);
} else {
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(1510, "GXSetDispCopySrc");
__GXData->cpDispSrc = 0;
SET_REG_FIELD(1513, __GXData->cpDispSrc, 10, 0, left);
SET_REG_FIELD(1514, __GXData->cpDispSrc, 10, 10, top);
SET_REG_FIELD(1514, __GXData->cpDispSrc, 8, 24, 0x49);
__GXData->cpDispSize = 0;
SET_REG_FIELD(1518, __GXData->cpDispSize, 10, 0, wd - 1);
SET_REG_FIELD(1519, __GXData->cpDispSize, 10, 10, ht - 1);
SET_REG_FIELD(1519, __GXData->cpDispSize, 8, 24, 0x4A);
}
void GXSetTexCopySrc(u16 left, u16 top, u16 wd, u16 ht) {
CHECK_GXBEGIN(1538, "GXSetTexCopySrc");
__GXData->cpTexSrc = 0;
SET_REG_FIELD(1541, __GXData->cpTexSrc, 10, 0, left);
SET_REG_FIELD(1542, __GXData->cpTexSrc, 10, 10, top);
SET_REG_FIELD(1542, __GXData->cpTexSrc, 8, 24, 0x49);
__GXData->cpTexSize = 0;
SET_REG_FIELD(1546, __GXData->cpTexSize, 10, 0, wd - 1);
SET_REG_FIELD(1547, __GXData->cpTexSize, 10, 10, ht - 1);
SET_REG_FIELD(1547, __GXData->cpTexSize, 8, 24, 0x4A);
}
void GXSetDispCopyDst(u16 wd, u16 ht) {
u16 stride;
ASSERTMSGLINE(1568, (wd & 15) == 0, "GXSetDispCopyDst: Width must be a multiple of 16");
CHECK_GXBEGIN(1569, "GXSetDispCopyDst");
stride = (int)wd * 2;
__GXData->cpDispStride = 0;
SET_REG_FIELD(1575, __GXData->cpDispStride, 10, 0, (stride >> 5) );
SET_REG_FIELD(1575, __GXData->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(1602, "GXSetTexCopyDst");
__GXData->cpTexZ = 0;
peTexFmt = fmt & 0xF;
ASSERTMSGLINEV(1633, 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, __GXData->cpTex, 2, 15, 3);
break;
default:
SET_REG_FIELD(0, __GXData->cpTex, 2, 15, 2);
break;
}
__GXData->cpTexZ = (fmt & _GX_TF_ZTF) == _GX_TF_ZTF;
peTexFmtH = (peTexFmt & 8) >> 3;
SET_REG_FIELD(1656, __GXData->cpTex, 1, 3, peTexFmtH);
peTexFmt = peTexFmt & 7;
__GetImageTileCount(fmt, wd, ht, &rowTiles, &colTiles, &cmpTiles);
__GXData->cpTexStride = 0;
SET_REG_FIELD(1665, __GXData->cpTexStride, 10, 0, rowTiles * cmpTiles);
SET_REG_FIELD(1667, __GXData->cpTexStride, 8, 24, 0x4D);
SET_REG_FIELD(1667, __GXData->cpTex, 1, 9, mipmap);
SET_REG_FIELD(1668, __GXData->cpTex, 3, 4, peTexFmt);
}
void GXSetDispCopyFrame2Field(GXCopyMode mode) {
CHECK_GXBEGIN(1685, "GXSetDispCopyFrame2Field");
SET_REG_FIELD(1686, __GXData->cpDisp, 2, 12, mode);
SET_REG_FIELD(1686, __GXData->cpTex, 2, 12, 0);
}
void GXSetCopyClamp(GXFBClamp clamp) {
u8 clmpB;
u8 clmpT;
CHECK_GXBEGIN(1706, "GXSetCopyClamp");
clmpT = (clamp & GX_CLAMP_TOP) == 1;
clmpB = (clamp & GX_CLAMP_BOTTOM) == 2;
SET_REG_FIELD(1710, __GXData->cpDisp, 1, 0, clmpT);
SET_REG_FIELD(1711, __GXData->cpDisp, 1, 1, clmpB);
SET_REG_FIELD(1713, __GXData->cpTex, 1, 0, clmpT);
SET_REG_FIELD(1714, __GXData->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(1761, 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(1785, xfbHeight <= 1024, "GXGetYScaleFactor: Display copy only supports up to 1024 lines.\n");
ASSERTMSGLINE(1787, 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(1832, "GXSetDispCopyYScale");
ASSERTMSGLINE(1834, vscale >= 1.0f, "GXSetDispCopyYScale: Vertical scale must be >= 1.0");
iScale = (u32) (256.0f / vscale) & 0x1FF;
enable = (iScale != 256);
reg = 0;
SET_REG_FIELD(1841, reg, 9, 0, iScale);
SET_REG_FIELD(1841, reg, 8, 24, 0x4E);
GX_WRITE_RAS_REG(reg);
__GXData->bpSentNot = 0;
SET_REG_FIELD(1846, __GXData->cpDisp, 1, 10, enable);
ht = (u32)GET_REG_FIELD(__GXData->cpDispSize, 10, 10) + 1;
return __GXGetNumXfbLines(ht, iScale);
}
void GXSetCopyClear(GXColor clear_clr, u32 clear_z) {
u32 reg;
CHECK_GXBEGIN(1871, "GXSetCopyClear");
ASSERTMSGLINE(1873, clear_z <= 0xFFFFFF, "GXSetCopyClear: Z clear value is out of range");
reg = 0;
SET_REG_FIELD(1876, reg, 8, 0, clear_clr.r);
SET_REG_FIELD(1877, reg, 8, 8, clear_clr.a);
SET_REG_FIELD(1877, reg, 8, 24, 0x4F);
GX_WRITE_RAS_REG(reg);
reg = 0;
SET_REG_FIELD(1882, reg, 8, 0, clear_clr.b);
SET_REG_FIELD(1883, reg, 8, 8, clear_clr.g);
SET_REG_FIELD(1883, reg, 8, 24, 0x50);
GX_WRITE_RAS_REG(reg);
reg = 0;
SET_REG_FIELD(1888, reg, 24, 0, clear_z);
SET_REG_FIELD(1888, reg, 8, 24, 0x51);
GX_WRITE_RAS_REG(reg);
__GXData->bpSentNot = 0;
}
void GXSetCopyFilter(GXBool aa, const u8 sample_pattern[12][2], GXBool vf, const u8 vfilter[7]) {
u32 msLoc[4];
u32 coeff0;
u32 coeff1;
CHECK_GXBEGIN(1916, "GXSetCopyFilter");
if (aa != 0) {
msLoc[0] = 0;
SET_REG_FIELD(1920, msLoc[0], 4, 0, sample_pattern[0][0]);
SET_REG_FIELD(1921, msLoc[0], 4, 4, sample_pattern[0][1]);
SET_REG_FIELD(1922, msLoc[0], 4, 8, sample_pattern[1][0]);
SET_REG_FIELD(1923, msLoc[0], 4, 12, sample_pattern[1][1]);
SET_REG_FIELD(1924, msLoc[0], 4, 16, sample_pattern[2][0]);
SET_REG_FIELD(1925, msLoc[0], 4, 20, sample_pattern[2][1]);
SET_REG_FIELD(1926, msLoc[0], 8, 24, 1);
msLoc[1] = 0;
SET_REG_FIELD(1929, msLoc[1], 4, 0, sample_pattern[3][0]);
SET_REG_FIELD(1930, msLoc[1], 4, 4, sample_pattern[3][1]);
SET_REG_FIELD(1931, msLoc[1], 4, 8, sample_pattern[4][0]);
SET_REG_FIELD(1932, msLoc[1], 4, 12, sample_pattern[4][1]);
SET_REG_FIELD(1933, msLoc[1], 4, 16, sample_pattern[5][0]);
SET_REG_FIELD(1934, msLoc[1], 4, 20, sample_pattern[5][1]);
SET_REG_FIELD(1935, msLoc[1], 8, 24, 2);
msLoc[2] = 0;
SET_REG_FIELD(1938, msLoc[2], 4, 0, sample_pattern[6][0]);
SET_REG_FIELD(1939, msLoc[2], 4, 4, sample_pattern[6][1]);
SET_REG_FIELD(1940, msLoc[2], 4, 8, sample_pattern[7][0]);
SET_REG_FIELD(1941, msLoc[2], 4, 12, sample_pattern[7][1]);
SET_REG_FIELD(1942, msLoc[2], 4, 16, sample_pattern[8][0]);
SET_REG_FIELD(1943, msLoc[2], 4, 20, sample_pattern[8][1]);
SET_REG_FIELD(1944, msLoc[2], 8, 24, 3);
msLoc[3] = 0;
SET_REG_FIELD(1947, msLoc[3], 4, 0, sample_pattern[9][0]);
SET_REG_FIELD(1948, msLoc[3], 4, 4, sample_pattern[9][1]);
SET_REG_FIELD(1949, msLoc[3], 4, 8, sample_pattern[10][0]);
SET_REG_FIELD(1950, msLoc[3], 4, 12, sample_pattern[10][1]);
SET_REG_FIELD(1951, msLoc[3], 4, 16, sample_pattern[11][0]);
SET_REG_FIELD(1952, msLoc[3], 4, 20, sample_pattern[11][1]);
SET_REG_FIELD(1953, 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(1977, coeff0, 6, 0, vfilter[0]);
SET_REG_FIELD(1978, coeff0, 6, 6, vfilter[1]);
SET_REG_FIELD(1979, coeff0, 6, 12, vfilter[2]);
SET_REG_FIELD(1980, coeff0, 6, 18, vfilter[3]);
SET_REG_FIELD(1981, coeff1, 6, 0, vfilter[4]);
SET_REG_FIELD(1982, coeff1, 6, 6, vfilter[5]);
SET_REG_FIELD(1983, 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);
__GXData->bpSentNot = 0;
}
void GXSetDispCopyGamma(GXGamma gamma) {
CHECK_GXBEGIN(2016, "GXSetDispCopyGamma");
SET_REG_FIELD(2017, __GXData->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(2037, "GXCopyDisp");
clmpT = GET_REG_FIELD(__GXData->cpDisp, 1, 0);
clmpB = (u32)GET_REG_FIELD(__GXData->cpDisp, 1, 1);
x0 = GET_REG_FIELD(__GXData->cpDispSrc, 10, 0);
dx = GET_REG_FIELD(__GXData->cpDispSize, 10, 0) + 1;
y0 = GET_REG_FIELD(__GXData->cpDispSrc, 10, 10);
dy = GET_REG_FIELD(__GXData->cpDispSize, 10, 10) + 1;
ASSERTMSGLINE(2047, clmpT || y0 != 0, "GXCopy: Have to set GX_CLAMP_TOP if source top == 0");
ASSERTMSGLINE(2049, clmpB || y0 + dy <= 528, "GXCopy: Have to set GX_CLAMP_BOTTOM if source bottom > 528");
ASSERTMSGLINE(2054, (__GXData->peCtrl & 7) != 3 || clear == 0, "GXCopy: Can not do clear while pixel type is Z");
if ((u32) (__GXData->peCtrl & 7) == 5) {
ASSERTMSGLINE(2060, clear == 0, "GXCopy: Can not clear YUV framebuffer");
ASSERTMSGLINE(2062, (x0 & 3) == 0, "GXCopy: Source x is not multiple of 4 for YUV copy");
ASSERTMSGLINE(2064, (y0 & 3) == 0, "GXCopy: Source y is not multiple of 4 for YUV copy");
ASSERTMSGLINE(2066, (dx & 3) == 0, "GXCopy: Source width is not multiple of 4 for YUV copy");
ASSERTMSGLINE(2068, (dy & 3) == 0, "GXCopy: Source height is not multiple of 4 for YUV copy");
} else {
ASSERTMSGLINE(2072, (x0 & 1) == 0, "GXCopy: Source x is not multiple of 2 for RGB copy");
ASSERTMSGLINE(2074, (y0 & 1) == 0, "GXCopy: Source y is not multiple of 2 for RGB copy");
ASSERTMSGLINE(2076, (dx & 1) == 0, "GXCopy: Source width is not multiple of 2 for RGB copy");
ASSERTMSGLINE(2078, (dy & 1) == 0, "GXCopy: Source height is not multiple of 2 for RGB copy");
}
ASSERTMSGLINE(2082, ((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(2108, "GXCopyDisp");
#if DEBUG
__GXVerifCopy(dest, clear);
#endif
if (clear) {
reg = __GXData->zmode;
SET_REG_FIELD(0, reg, 1, 0, 1);
SET_REG_FIELD(0, reg, 3, 1, 7);
GX_WRITE_RAS_REG(reg);
reg = __GXData->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(__GXData->peCtrl, 3, 0) == 3) && (u32)GET_REG_FIELD(__GXData->peCtrl, 1, 6) == 1) {
changePeCtrl = TRUE;
tempPeCtrl = __GXData->peCtrl;
SET_REG_FIELD(0, tempPeCtrl, 1, 6, 0);
GX_WRITE_RAS_REG(tempPeCtrl);
}
GX_WRITE_RAS_REG(__GXData->cpDispSrc);
GX_WRITE_RAS_REG(__GXData->cpDispSize);
GX_WRITE_RAS_REG(__GXData->cpDispStride);
phyAddr = (u32)dest & 0x3FFFFFFF;
reg = 0;
SET_REG_FIELD(2147, reg, 24, 0, phyAddr >> 5);
SET_REG_FIELD(2147, reg, 8, 24, 0x4B);
GX_WRITE_RAS_REG(reg);
SET_REG_FIELD(2151, __GXData->cpDisp, 1, 11, clear);
SET_REG_FIELD(2151, __GXData->cpDisp, 1, 14, 1);
SET_REG_FIELD(2151, __GXData->cpDisp, 8, 24, 0x52);
GX_WRITE_RAS_REG(__GXData->cpDisp);
if (clear) {
GX_WRITE_RAS_REG(__GXData->zmode);
GX_WRITE_RAS_REG(__GXData->cmode0);
}
if (changePeCtrl) {
GX_WRITE_RAS_REG(__GXData->peCtrl);
}
__GXData->bpSentNot = 0;
}
void GXCopyTex(void* dest, GXBool clear) {
u32 reg;
u32 tempPeCtrl;
u32 phyAddr;
u8 changePeCtrl;
CHECK_GXBEGIN(2191, "GXCopyTex");
#if DEBUG
__GXVerifCopy(dest, clear);
#endif
if (clear) {
reg = __GXData->zmode;
SET_REG_FIELD(0, reg, 1, 0, 1);
SET_REG_FIELD(0, reg, 3, 1, 7);
GX_WRITE_RAS_REG(reg);
reg = __GXData->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 = __GXData->peCtrl;
if (__GXData->cpTexZ && ((tempPeCtrl & 7) != 3)) {
changePeCtrl = 1;
SET_REG_FIELD(0, tempPeCtrl, 3, 0, 3);
}
if ((clear || ((u32) (tempPeCtrl & 7) == 3)) && ((u32) ((tempPeCtrl & 0x40) >> 6) == 1)) {
changePeCtrl = 1;
SET_REG_FIELD(0, tempPeCtrl, 1, 6, 0);
}
if (changePeCtrl) {
GX_WRITE_RAS_REG(tempPeCtrl);
}
GX_WRITE_RAS_REG(__GXData->cpTexSrc);
GX_WRITE_RAS_REG(__GXData->cpTexSize);
GX_WRITE_RAS_REG(__GXData->cpTexStride);
phyAddr = (u32)dest & 0x3FFFFFFF;
reg = 0;
SET_REG_FIELD(2240, reg, 24, 0, phyAddr >> 5);
SET_REG_FIELD(2240, reg, 8, 24, 0x4B);
GX_WRITE_RAS_REG(reg);
SET_REG_FIELD(2244, __GXData->cpTex, 1, 11, clear);
SET_REG_FIELD(2244, __GXData->cpTex, 1, 14, 0);
SET_REG_FIELD(2244, __GXData->cpTex, 8, 24, 0x52);
GX_WRITE_RAS_REG(__GXData->cpTex);
if (clear) {
GX_WRITE_RAS_REG(__GXData->zmode);
GX_WRITE_RAS_REG(__GXData->cmode0);
}
if (changePeCtrl) {
GX_WRITE_RAS_REG(__GXData->peCtrl);
}
__GXData->bpSentNot = 0;
}
void GXClearBoundingBox(void) {
u32 reg;
CHECK_GXBEGIN(2278, "GXClearBoundingBox");
reg = 0x550003FF;
GX_WRITE_RAS_REG(reg);
reg = 0x560003FF;
GX_WRITE_RAS_REG(reg);
__GXData->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);
}
+267
View File
@@ -0,0 +1,267 @@
#include <stddef.h>
#include <revolution/gx.h>
#include <revolution/os.h>
#include "__gx.h"
static void __GXSetTexGen(u32 tgState);
static void __GXSetLightChan(u32 chState);
static void __GXSetAmbMat(u32 amState);
void __GXSetDirtyState(void) {
u32 dState = __GXData->dirtyState;
if (dState & 1) {
__GXSetSUTexRegs();
}
if (dState & 2) {
__GXUpdateBPMask();
}
if (dState & 4) {
__GXSetGenMode();
}
if (dState & 8) {
__GXSetVCD();
}
if (dState & 0x10) {
__GXSetVAT();
}
if (dState & 0x18) {
__GXCalculateVLim();
}
dState &= 0xFFFFFF00;
if (dState) {
u32 dStateLocal;
dStateLocal = dState & 0x00000F00;
if (dStateLocal) {
__GXSetAmbMat(dStateLocal);
}
dStateLocal = dState & (0x01000000|0x0000F000);
if (dStateLocal) {
__GXSetLightChan(dStateLocal);
}
dStateLocal = dState & (0x02000000|0x00FF0000);
if (dStateLocal) {
__GXSetTexGen(dStateLocal);
}
dStateLocal = dState & 0x04000000;
if (dStateLocal) {
__GXSetMatrixIndex(GX_VA_PNMTXIDX);
__GXSetMatrixIndex(GX_VA_TEX4MTXIDX);
}
dStateLocal = dState & 0x10000000;
if (dStateLocal) {
__GXSetViewport();
}
dStateLocal = dState & 0x8000000;
if (dStateLocal) {
__GXSetProjection();
}
__GXData->bpSentNot = GX_TRUE;
}
__GXData->dirtyState = 0;
}
static void __GXSetTexGen(u32 tgState) {
u32 d, i, tgIndx = 0x1040;
u32 dtgIndx = 0x1050;
if (tgState & 0x2000000) {
d = __GXData->genMode & 0xF;
GX_WRITE_XF_REG(0x103F, d, 0);
}
d = (tgState & 0xFF0000) >> 16;
i = 0;
while (d) {
if (d & 0x1) {
GX_WRITE_XF_REG(tgIndx, __GXData->texGenCtrl[i], 0);
GX_WRITE_XF_REG(dtgIndx, __GXData->texGenCtrl2[i], 0);
}
dtgIndx++;
tgIndx++;
i++;
d >>= 1;
}
}
static void __GXSetLightChan(u32 chState) {
u32 d, i, chIndx = 0x100E;
if (chState & 0x1000000) {
d = ((__GXData->genMode & 0x70) >> 4);
GX_WRITE_XF_REG(0x1009, d, 0);
}
d = (chState & 0xF000) >> 12;
i = 0;
while (d) {
if (d & 0x1) {
GX_WRITE_XF_REG(chIndx, __GXData->chanCtrl[i], 0);
}
i++;
chIndx++;
d >>= 1;
}
}
static void __GXSetAmbMat(u32 amState) {
if (amState & 0x100) {
GX_WRITE_XF_REG(0x100A, __GXData->ambColor[0], 0);
}
if (amState & 0x200) {
GX_WRITE_XF_REG(0x100B, __GXData->ambColor[1], 0);
}
if (amState & 0x400) {
GX_WRITE_XF_REG(0x100C, __GXData->matColor[0], 0);
}
if (amState & 0x800) {
GX_WRITE_XF_REG(0x100D, __GXData->matColor[1], 0);
}
}
void GXBegin(GXPrimitive type, GXVtxFmt vtxfmt, u16 nverts) {
ASSERTMSGLINE(368, vtxfmt < GX_MAX_VTXFMT, "GXBegin: Format Index is out of range");
ASSERTMSGLINE(369, !__GXinBegin, "GXBegin: called inside another GXBegin/GXEnd");
if (__GXData->dirtyState != 0) {
__GXSetDirtyState();
}
#if DEBUG
if (!__GXData->inDispList) {
__GXVerifyState(vtxfmt);
}
__GXinBegin = 1;
#endif
if (*(u32*)&__GXData->vNumNot == 0) { // checks both vNum and bpSentNot
__GXSendFlushPrim();
}
GX_WRITE_U8(vtxfmt | type);
GX_WRITE_U16(nverts);
}
void __GXSendFlushPrim(void) {
u32 i;
u32 numD = __GXData->vNum * __GXData->vLim;
GX_WRITE_U8(0x98);
GX_WRITE_U16(__GXData->vNum);
for (i = 0; i < numD; i += 4) {
GX_WRITE_U32(0);
}
__GXData->bpSentNot = 1;
}
void GXSetLineWidth(u8 width, GXTexOffset texOffsets) {
CHECK_GXBEGIN(447, "GXSetLineWidth");
SC_SU_LPSIZE_SET_LSIZE(448, __GXData->lpSize, width);
SC_SU_LPSIZE_SET_LTOFF(449, __GXData->lpSize, texOffsets);
GX_WRITE_RAS_REG(__GXData->lpSize);
__GXData->bpSentNot = 0;
}
void GXGetLineWidth(u8* width, GXTexOffset* texOffsets) {
ASSERTMSGLINE(463, width != NULL && texOffsets != NULL, "GXGet*: invalid null pointer");
*width = SU_LPSIZE_GET_LSIZE(__GXData->lpSize);
*texOffsets = SU_LPSIZE_GET_LTOFF(__GXData->lpSize);
}
void GXSetPointSize(u8 pointSize, GXTexOffset texOffsets) {
CHECK_GXBEGIN(491, "GXSetPointSize");
SC_SU_LPSIZE_SET_PSIZE(492, __GXData->lpSize, pointSize);
SC_SU_LPSIZE_SET_PTOFF(493, __GXData->lpSize, texOffsets);
GX_WRITE_RAS_REG(__GXData->lpSize);
__GXData->bpSentNot = 0;
}
void GXGetPointSize(u8* pointSize, GXTexOffset* texOffsets) {
ASSERTMSGLINE(507, pointSize != NULL && texOffsets != NULL, "GXGet*: invalid null pointer");
*pointSize = SU_LPSIZE_GET_PSIZE(__GXData->lpSize);
*texOffsets = SU_LPSIZE_GET_PTOFF(__GXData->lpSize);
}
void GXEnableTexOffsets(GXTexCoordID coord, u8 line_enable, u8 point_enable) {
CHECK_GXBEGIN(536, "GXEnableTexOffsets");
ASSERTMSGLINE(538, coord < GX_MAX_TEXCOORD, "GXEnableTexOffsets: Invalid coordinate Id");
SC_SU_TS0_SET_LF(540, __GXData->suTs0[coord], line_enable);
SC_SU_TS0_SET_PF(541, __GXData->suTs0[coord], point_enable);
GX_WRITE_RAS_REG(__GXData->suTs0[coord]);
__GXData->bpSentNot = 0;
}
void GXSetCullMode(GXCullMode mode) {
GXCullMode hwMode;
CHECK_GXBEGIN(564, "GXSetCullMode");
#if DEBUG
switch (mode) {
case GX_CULL_FRONT: hwMode = GX_CULL_BACK; break;
case GX_CULL_BACK: hwMode = GX_CULL_FRONT; break;
default: hwMode = mode; break;
}
#else
hwMode = (mode >> 1) & 1;
__rlwimi(hwMode, mode, 1, 30, 30);
#endif
SC_GEN_MODE_SET_REJECT_EN(577, __GXData->genMode, hwMode);
__GXData->dirtyState |= 4;
}
void GXGetCullMode(GXCullMode* mode) {
#if DEBUG
GXCullMode hwMode = GEN_MODE_GET_REJECT_EN(__GXData->genMode);
switch (hwMode) {
case GX_CULL_FRONT: *mode = GX_CULL_BACK; break;
case GX_CULL_BACK: *mode = GX_CULL_FRONT; break;
default: *mode = hwMode; break;
}
#else
// fake match?
GXCullMode hwMode = __GXData->genMode;
*mode = ((hwMode >> 0xD) & 0x2) | (((((int)hwMode >> 0xE) & 0x2) >> 0x1));
#endif
}
void GXSetCoPlanar(GXBool enable) {
u32 reg;
CHECK_GXBEGIN(620, "GXSetCoPlanar");
SC_GEN_MODE_SET_ZFREEZE(622, __GXData->genMode, enable);
reg = 0xFE080000;
GX_WRITE_RAS_REG(reg);
GX_WRITE_RAS_REG(__GXData->genMode);
__GXData->bpSentNot = 0;
}
void __GXSetGenMode(void) {
GX_WRITE_RAS_REG(__GXData->genMode);
__GXData->bpSentNot = 0;
}
+567
View File
@@ -0,0 +1,567 @@
#include <string.h>
#include <revolution/base/PPCArch.h>
#include <revolution/gx.h>
#include <revolution/os.h>
#include <revolution/vi.h>
#include "__gx.h"
#ifdef SDK_AUG2010
#define BUILD_DATE "Aug 23 2010"
#if DEBUG
#define BUILD_TIME "17:27:30"
#else
#define BUILD_TIME "17:33:06"
#endif
#elif SDK_SEP2006
#define BUILD_DATE "Sep 21 2006"
#define BUILD_TIME "14:32:13"
#endif
#ifdef SDK_AUG2010
#if DEBUG
const char* __GXVersion = "<< RVL_SDK - GX \tdebug build: "BUILD_DATE" "BUILD_TIME" (0x4302_145) >>";
#else
const char* __GXVersion = "<< RVL_SDK - GX \trelease build: "BUILD_DATE" "BUILD_TIME" (0x4302_145) >>";
#endif
#elif SDK_SEP2006
const char* __GXVersion = "<< RVL_SDK - GX \trelease build: "BUILD_DATE" "BUILD_TIME" (0x4200_60422) >>";
#endif
static GXFifoObj FifoObj;
static GXData gxData;
GXData* const __GXData = &gxData;
// these are supposed to be in-function static, but it messed up sbss order
u32 shutdownFuncRegistered;
u32 calledOnce;
OSTime time;
u32 peCount;
volatile void* __memReg;
volatile void* __peReg;
volatile void* __cpReg;
volatile void* __piReg;
#if DEBUG
GXBool __GXinBegin;
#endif
static u16 DefaultTexData[] ATTRIBUTE_ALIGN(32) = {
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
};
static GXVtxAttrFmtList GXDefaultVATList[] = {
{GX_VA_POS, GX_POS_XYZ, GX_F32, 0},
{GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0},
{GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0},
{GX_VA_CLR1, GX_CLR_RGBA, GX_RGBA8, 0},
{GX_VA_TEX0, GX_TEX_ST, GX_F32, 0},
{GX_VA_TEX1, GX_TEX_ST, GX_F32, 0},
{GX_VA_TEX2, GX_TEX_ST, GX_F32, 0},
{GX_VA_TEX3, GX_TEX_ST, GX_F32, 0},
{GX_VA_TEX4, GX_TEX_ST, GX_F32, 0},
{GX_VA_TEX5, GX_TEX_ST, GX_F32, 0},
{GX_VA_TEX6, GX_TEX_ST, GX_F32, 0},
{GX_VA_TEX7, GX_TEX_ST, GX_F32, 0},
{GX_VA_NULL, 0, 0, 0},
};
static f32 GXDefaultProjData[] = {1.0f, 0.0f, 1.0f, 0.0f, -1.0f, -2.0f, 0.0f};
static u32 GXTexRegionAddrTable[] = {
0x00000, 0x10000, 0x20000, 0x30000, 0x40000, 0x50000, 0x60000, 0x70000, 0x08000, 0x18000,
0x28000, 0x38000, 0x48000, 0x58000, 0x68000, 0x78000, 0x00000, 0x90000, 0x20000, 0xB0000,
0x40000, 0x98000, 0x60000, 0xB8000, 0x80000, 0x10000, 0xA0000, 0x30000, 0x88000, 0x50000,
0xA8000, 0x70000, 0x00000, 0x90000, 0x20000, 0xB0000, 0x40000, 0x90000, 0x60000, 0xB0000,
0x80000, 0x10000, 0xA0000, 0x30000, 0x80000, 0x50000, 0xA0000, 0x70000,
};
// prototypes
static int __GXShutdown(int final, u32);
static OSShutdownFunctionInfo GXShutdownFuncInfo = {__GXShutdown, 0x7F, NULL, NULL};
asm BOOL IsWriteGatherBufferEmpty(void) {
sync
mfspr r3, WPAR
andi. r3, r3, 1
}
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(const GXTexObj* t_obj, GXTexMapID id) {
GXTexFmt fmt;
u8 mm;
fmt = GXGetTexObjFmt(t_obj);
mm = GXGetTexObjMipMap(t_obj);
id = (GXTexMapID)(id % GX_MAX_TEXMAP);
switch (fmt) {
case GX_TF_RGBA8:
if (mm) {
return &__GXData->TexRegions2[id];
}
return &__GXData->TexRegions1[id];
case GX_TF_C4:
case GX_TF_C8:
case GX_TF_C14X2:
return &__GXData->TexRegions0[id];
default:
if (mm) {
return &__GXData->TexRegions1[id];
}
return &__GXData->TexRegions0[id];
}
}
static GXTlutRegion* __GXDefaultTlutRegionCallback(u32 idx) {
if (idx >= 20) {
return NULL;
}
return &__GXData->TlutRegions[idx];
}
#if DEBUG
static void __GXDefaultVerifyCallback(GXWarningLevel level, u32 id, const char* msg) {
OSReport("Level %1d, Warning %3d: %s\n", level, id, msg);
}
#endif
static int __GXShutdown(BOOL final, u32) {
u32 reg;
u32 peCountNew;
OSTime timeNew;
if (!final) {
if (!calledOnce) {
peCount = __GXReadMEMCounterU32(0x28, 0x27);
time = OSGetTime();
calledOnce = 1;
return 0;
}
timeNew = OSGetTime();
peCountNew = __GXReadMEMCounterU32(0x28, 0x27);
if (timeNew - time < 10) {
return 0;
}
if (peCountNew != peCount) {
peCount = peCountNew;
time = timeNew;
return 0;
}
} else {
GXSetBreakPtCallback(NULL);
GXSetDrawSyncCallback(NULL);
GXSetDrawDoneCallback(NULL);
GX_WRITE_U32(0);
GX_WRITE_U32(0);
GX_WRITE_U32(0);
GX_WRITE_U32(0);
GX_WRITE_U32(0);
GX_WRITE_U32(0);
GX_WRITE_U32(0);
GX_WRITE_U32(0);
PPCSync();
reg = CP_REG_ENABLE(0, 0, 0, 0, 0, 0);
GX_CP_REG_WRITE_U16(CP_ENABLE, (u16)reg);
reg = CP_REG_CLR(1, 1, 0);
GX_CP_REG_WRITE_U16(CP_CLR, (u16)reg);
__GXData->abtWaitPECopy = 1;
__GXAbort();
}
return 1;
}
#define SOME_SET_REG_MACRO(reg, size, shift, val) \
do { \
(reg) = (u32)__rlwimi((u32)(reg), (val), (shift), (32 - (shift) - (size)), (31 - (shift))); \
} while (0);
void __GXInitRevisionBits(void) {
u32 i;
for (i = 0; i < 8; i++) {
s32 regAddr;
SC_CP_VAT_REG_A_SET_BYTEDEQUANT(0, __GXData->vatA[i], 1);
SC_CP_VAT_REG_B_SET_VCACHE_ENHANCE(0, __GXData->vatB[i], 1);
GX_WRITE_CP_STRM_REG(CP_VAT_B, (s32) i, __GXData->vatB[i]);
regAddr = i - 12;
}
{
u32 reg1 = 0;
u32 reg2 = 0;
SC_XF_ERROR_F_SET_CTEX_BUG_ENABLE(0, reg1, 1);
SC_XF_ERROR_F_SET_TFAN4_BUG_ENABLE(0, reg1, 1);
SC_XF_ERROR_F_SET_TFAN16_BUG_ENABLE(0, reg1, 1);
SC_XF_ERROR_F_SET_DUALTRAN_REG_ENABLE(0, reg1, 1);
SC_XF_ERROR_F_SET_BYPASS_BUG_ENABLE(0, reg1, 1);
SC_XF_ERROR_F_SET_FAST_MATRIX_ENABLE(0, reg1, 1);
GX_WRITE_XF_REG(0x1000, reg1, 0);
SC_XF_DUALTEXTRAN_F_SET_DUALTEXTRAN_ENABLE(0, reg2, 1);
GX_WRITE_XF_REG(0x1012, reg2, 0);
#if DEBUG
__gxVerif->xfRegsDirty[0] = 0;
#endif
}
{
u32 reg = 0;
SC_PE_CHICKEN_SET_PIWR(0, reg, 1);
SC_PE_CHICKEN_SET_TXCPY_FMT(0, reg, 1);
SC_PE_CHICKEN_SET_TXCPY_CCV(0, reg, 1);
SC_PE_CHICKEN_SET_BLENDOP(0, reg, 1);
SC_PE_CHICKEN_SET_RID(0, reg, 0x58);
GX_WRITE_RA_REG(reg);
}
}
GXFifoObj* GXInit(void* base, u32 size) {
u32 i;
u32 reg;
u32 freqBase;
OSRegisterVersion(__GXVersion);
__GXData->inDispList = FALSE;
__GXData->dlSaveContext = TRUE;
__GXData->abtWaitPECopy = 1;
#if DEBUG
__GXinBegin = FALSE;
#endif
__GXData->tcsManEnab = FALSE;
__GXData->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 (!shutdownFuncRegistered) {
OSRegisterShutdownFunction(&GXShutdownFuncInfo);
shutdownFuncRegistered = 1;
}
__GXPEInit();
EnableWriteGatherPipe();
__GXData->genMode = 0;
SC_GEN_MODE_SET_RID(0, __GXData->genMode, 0);
__GXData->bpMask = 255;
SC_BP_IMASK_SET_RID(0, __GXData->bpMask, 0xF);
__GXData->lpSize = 0;
SC_SU_LPSIZE_SET_RID(0, __GXData->lpSize, 0x22);
for (i = 0; i < 16; ++i) {
__GXData->tevc[i] = 0;
__GXData->teva[i] = 0;
__GXData->tref[i / 2] = 0;
__GXData->texmapId[i] = GX_TEXMAP_NULL;
SC_TEV_COLOR_ENV_SET_RID(970, __GXData->tevc[i], (0xC0 + i * 2));
SC_TEV_ALPHA_ENV_SET_RID(971, __GXData->teva[i], (0xC1 + i * 2));
SC_TEV_KSEL_SET_RID(973, __GXData->tevKsel[i/2], (0xF6 + i / 2));
SC_RAS1_TREF_SET_RID(975, __GXData->tref[i/2], (0x28 + i / 2));
}
__GXData->iref = 0;
SC_RAS1_IREF_SET_RID(0, __GXData->iref, 0x27);
for (i = 0; i < 8; ++i) {
__GXData->suTs0[i] = 0;
__GXData->suTs1[i] = 0;
SC_SU_TS0_SET_RID(984, __GXData->suTs0[i], 0x30 + i * 2);
SC_SU_TS1_SET_RID(985, __GXData->suTs1[i], 0x31 + i * 2);
}
SC_SU_SCIS0_SET_RID(0, __GXData->suScis0, 0x20);
SC_SU_SCIS1_SET_RID(0, __GXData->suScis1, 0x21);
SC_PE_CMODE0_SET_RID(0, __GXData->cmode0, 0x41);
SC_PE_CMODE1_SET_RID(0, __GXData->cmode1, 0x42);
SC_PE_ZMODE_SET_RID(0, __GXData->zmode, 0x40);
SC_PE_CONTROL_SET_RID(0, __GXData->peCtrl, 0x43);
SC_PE_COPY_CMD_SET_GAMMA(0, __GXData->cpTex, 0);
__GXData->zScale = (f32)(0xFFFFFF + 1);
__GXData->zOffset = 0.0f;
__GXData->dirtyState = 0;
__GXData->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(&__GXData->TexRegions0[i], GX_FALSE, GXTexRegionAddrTable[i],
GX_TEXCACHE_32K, GXTexRegionAddrTable[i + 8], GX_TEXCACHE_32K);
GXInitTexCacheRegion(&__GXData->TexRegions1[i], GX_FALSE, GXTexRegionAddrTable[i + 16],
GX_TEXCACHE_32K, GXTexRegionAddrTable[i + 24], GX_TEXCACHE_32K);
GXInitTexCacheRegion(&__GXData->TexRegions2[i], GX_TRUE, GXTexRegionAddrTable[i + 32],
GX_TEXCACHE_32K, GXTexRegionAddrTable[i + 40], GX_TEXCACHE_32K);
}
for (i = 0; i < 16; i++) {
GXInitTlutRegion(&__GXData->TlutRegions[i], 0xC0000 + 0x2000 * i, GX_TLUT_256);
}
for (i = 0; i < 4; i++) {
GXInitTlutRegion(&__GXData->TlutRegions[i + 16], 0xE0000 + 0x8000 * i, GX_TLUT_1K);
}
{
u32 reg = CP_REG_MEMPERFSEL(MEMPERF_ZERO);
#if DEBUG
s32 regAddr;
#endif
GX_CP_REG_WRITE_U16(CP_MEMPERF_SEL, reg);
SC_CP_STAT_SEL_REG_SET_STALLPERF_SEL(0, __GXData->perfSel, STALLPERF_ZERO);
GX_WRITE_CP_STRM_REG(CP_STAT_SEL, 0, __GXData->perfSel);
#if DEBUG
regAddr = -12;
#endif
reg = XF_PERF0_F(0, 0, 0, 0);
GX_WRITE_XF_REG(0x1006, reg, 0);
reg = SU_PERF(0, 0, 0, 0, 0, 0, 0, 0, 0, 0x23);
GX_WRITE_RA_REG(reg);
reg = RAS_PERF(0, 0, 0, 0, 0, 0x24);
GX_WRITE_RA_REG(reg);
reg = TX_PERFMODE(0, 0, 0, 0, 0x67);
GX_WRITE_RA_REG(reg);
}
__GXSetIndirectMask(0);
__GXSetTmemConfig(2);
__GXInitGX();
return &FifoObj;
}
void __GXInitGX(void) {
GXRenderModeObj* rmode;
GXTexObj tex_obj;
float 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 VI_NTSC: rmode = &GXNtsc480IntDf; break;
case VI_PAL: rmode = &GXPal528IntDf; break;
case VI_EURGB60: rmode = &GXEurgb60Hz480IntDf; break;
case VI_MPAL: rmode = &GXMpal480IntDf; break;
default:
ASSERTMSGLINE(1177, 0, "GXInit: invalid TV format");
rmode = &GXNtsc480IntDf;
break;
}
GXSetCopyClear(clear, 0xFFFFFF);
GXSetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3C);
GXSetTexCoordGen(GX_TEXCOORD1, GX_TG_MTX2x4, GX_TG_TEX1, 0x3C);
GXSetTexCoordGen(GX_TEXCOORD2, GX_TG_MTX2x4, GX_TG_TEX2, 0x3C);
GXSetTexCoordGen(GX_TEXCOORD3, GX_TG_MTX2x4, GX_TG_TEX3, 0x3C);
GXSetTexCoordGen(GX_TEXCOORD4, GX_TG_MTX2x4, GX_TG_TEX4, 0x3C);
GXSetTexCoordGen(GX_TEXCOORD5, GX_TG_MTX2x4, GX_TG_TEX5, 0x3C);
GXSetTexCoordGen(GX_TEXCOORD6, GX_TG_MTX2x4, GX_TG_TEX6, 0x3C);
GXSetTexCoordGen(GX_TEXCOORD7, GX_TG_MTX2x4, GX_TG_TEX7, 0x3C);
GXSetNumTexGens(1);
GXClearVtxDesc();
GXInvalidateVtxCache();
for (i = GX_VA_POS; i <= GX_LIGHT_ARRAY; i++) {
GXSetArray(i, __GXData, 0);
}
for (i = GX_VTXFMT0; i < GX_MAX_VTXFMT; i++) {
GXSetVtxAttrFmtv(i, GXDefaultVATList);
}
GXSetLineWidth(6, GX_TO_ZERO);
GXSetPointSize(6, GX_TO_ZERO);
GXEnableTexOffsets(GX_TEXCOORD0, 0, 0);
GXEnableTexOffsets(GX_TEXCOORD1, 0, 0);
GXEnableTexOffsets(GX_TEXCOORD2, 0, 0);
GXEnableTexOffsets(GX_TEXCOORD3, 0, 0);
GXEnableTexOffsets(GX_TEXCOORD4, 0, 0);
GXEnableTexOffsets(GX_TEXCOORD5, 0, 0);
GXEnableTexOffsets(GX_TEXCOORD6, 0, 0);
GXEnableTexOffsets(GX_TEXCOORD7, 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);
GXSetProjectionv(GXDefaultProjData);
__GXSetGenMode();
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();
GXSetTexRegionCallback((GXTexRegionCallback)__GXDefaultTexRegionCallback);
GXSetTlutRegionCallback(__GXDefaultTlutRegionCallback);
GXInitTexObj(&tex_obj, DefaultTexData, 4, 4, GX_TF_IA8, GX_CLAMP, GX_CLAMP, 0);
GXLoadTexObj(&tex_obj, GX_TEXMAP0);
GXLoadTexObj(&tex_obj, GX_TEXMAP1);
GXLoadTexObj(&tex_obj, GX_TEXMAP2);
GXLoadTexObj(&tex_obj, GX_TEXMAP3);
GXLoadTexObj(&tex_obj, GX_TEXMAP4);
GXLoadTexObj(&tex_obj, GX_TEXMAP5);
GXLoadTexObj(&tex_obj, GX_TEXMAP6);
GXLoadTexObj(&tex_obj, GX_TEXMAP7);
GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD1, GX_TEXMAP1, GX_COLOR0A0);
GXSetTevOrder(GX_TEVSTAGE2, GX_TEXCOORD2, GX_TEXMAP2, GX_COLOR0A0);
GXSetTevOrder(GX_TEVSTAGE3, GX_TEXCOORD3, GX_TEXMAP3, GX_COLOR0A0);
GXSetTevOrder(GX_TEVSTAGE4, GX_TEXCOORD4, GX_TEXMAP4, GX_COLOR0A0);
GXSetTevOrder(GX_TEVSTAGE5, GX_TEXCOORD5, GX_TEXMAP5, GX_COLOR0A0);
GXSetTevOrder(GX_TEVSTAGE6, GX_TEXCOORD6, GX_TEXMAP6, GX_COLOR0A0);
GXSetTevOrder(GX_TEVSTAGE7, GX_TEXCOORD7, GX_TEXMAP7, GX_COLOR0A0);
GXSetTevOrder(GX_TEVSTAGE8, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);
GXSetTevOrder(GX_TEVSTAGE9, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);
GXSetTevOrder(GX_TEVSTAGE10, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);
GXSetTevOrder(GX_TEVSTAGE11, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);
GXSetTevOrder(GX_TEVSTAGE12, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);
GXSetTevOrder(GX_TEVSTAGE13, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);
GXSetTevOrder(GX_TEVSTAGE14, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);
GXSetTevOrder(GX_TEVSTAGE15, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR_NULL);
GXSetNumTevStages(1);
GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE);
GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_AND, GX_ALWAYS, 0);
GXSetZTexture(GX_ZT_DISABLE, GX_TF_Z8, 0);
for (i = GX_TEVSTAGE0; 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, NULL);
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((u8)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();
}
+571
View File
@@ -0,0 +1,571 @@
#include <math.h>
#include <revolution/gx.h>
#include <revolution/os.h>
#include "__gx.h"
// GXLightObj private data
typedef struct {
u32 reserved[3];
u32 Color;
f32 a[3];
f32 k[3];
f32 lpos[3];
f32 ldir[3];
} __GXLightObjInt_struct;
void GXInitLightAttn(GXLightObj* lt_obj, f32 a0, f32 a1, f32 a2, f32 k0, f32 k1, f32 k2) {
__GXLightObjInt_struct* obj;
ASSERTMSGLINE(135, lt_obj != NULL, "Light Object Pointer is null");
obj = (__GXLightObjInt_struct*)lt_obj;
CHECK_GXBEGIN(136, "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) {
__GXLightObjInt_struct* obj;
ASSERTMSGLINE(143, lt_obj != NULL, "Light Object Pointer is null");
obj = (__GXLightObjInt_struct*)lt_obj;
CHECK_GXBEGIN(144, "GXInitLightAttnA");
obj->a[0] = a0;
obj->a[1] = a1;
obj->a[2] = a2;
}
void GXGetLightAttnA(const GXLightObj* lt_obj, f32* a0, f32* a1, f32* a2) {
__GXLightObjInt_struct* obj;
ASSERTMSGLINE(153, lt_obj != NULL, "Light Object Pointer is null");
obj = (__GXLightObjInt_struct*)lt_obj;
CHECK_GXBEGIN(154, "GXGetLightAttnA");
*a0 = obj->a[0];
*a1 = obj->a[1];
*a2 = obj->a[2];
}
void GXInitLightAttnK(GXLightObj* lt_obj, f32 k0, f32 k1, f32 k2) {
__GXLightObjInt_struct* obj;
ASSERTMSGLINE(163, lt_obj != NULL, "Light Object Pointer is null");
obj = (__GXLightObjInt_struct*)lt_obj;
CHECK_GXBEGIN(164, "GXInitLightAttnK");
obj->k[0] = k0;
obj->k[1] = k1;
obj->k[2] = k2;
}
void GXGetLightAttnK(const GXLightObj* lt_obj, f32* k0, f32* k1, f32* k2) {
__GXLightObjInt_struct* obj;
ASSERTMSGLINE(173, lt_obj != NULL, "Light Object Pointer is null");
obj = (__GXLightObjInt_struct*)lt_obj;
CHECK_GXBEGIN(174, "GXGetLightAttnK");
*k0 = obj->k[0];
*k1 = obj->k[1];
*k2 = obj->k[2];
}
void GXInitLightSpot(GXLightObj* lt_obj, f32 cutoff, GXSpotFn spot_func) {
f32 a0, a1, a2;
f32 r;
f32 d;
f32 cr;
__GXLightObjInt_struct* obj;
ASSERTMSGLINE(204, lt_obj != NULL, "Light Object Pointer is null");
obj = (__GXLightObjInt_struct*)lt_obj;
CHECK_GXBEGIN(206, "GXInitLightSpot");
if (cutoff <= 0.0f || cutoff > 90.0f)
spot_func = GX_SP_OFF;
r = (3.1415927f * cutoff) / 180.0f;
cr = cosf(r);
switch (spot_func) {
case GX_SP_FLAT:
a0 = -1000.0f * cr;
a1 = 1000.0f;
a2 = 0.0f;
break;
case GX_SP_COS:
a1 = 1.0f / (1.0f - cr);
a0 = -cr * a1;
a2 = 0.0f;
break;
case GX_SP_COS2:
a2 = 1.0f / (1.0f - cr);
a0 = 0.0f;
a1 = -cr * a2;
break;
case GX_SP_SHARP:
d = 1.0f / ((1.0f - cr) * (1.0f - cr));
a0 = (cr * (cr - 2.0f)) * d;
a1 = 2.0f * d;
a2 = -d;
break;
case GX_SP_RING1:
d = 1.0f / ((1.0f - cr) * (1.0f - cr));
a2 = -4.0f * d;
a0 = a2 * cr;
a1 = (4.0f * (1.0f + cr)) * d;
break;
case GX_SP_RING2:
d = 1.0f / ((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;
__GXLightObjInt_struct* obj;
ASSERTMSGLINE(279, lt_obj != NULL, "Light Object Pointer is null");
obj = (__GXLightObjInt_struct*)lt_obj;
CHECK_GXBEGIN(281, "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) {
__GXLightObjInt_struct* obj;
ASSERTMSGLINE(334, lt_obj != NULL, "Light Object Pointer is null");
obj = (__GXLightObjInt_struct*)lt_obj;
CHECK_GXBEGIN(336, "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) {
__GXLightObjInt_struct* obj;
ASSERTMSGLINE(339, lt_obj != NULL, "Light Object Pointer is null");
obj = (__GXLightObjInt_struct*)lt_obj;
CHECK_GXBEGIN(341, "GXGetLightPos");
*x = obj->lpos[0];
*y = obj->lpos[1];
*z = obj->lpos[2];
}
void GXInitLightDir(GXLightObj* lt_obj, f32 nx, f32 ny, f32 nz) {
__GXLightObjInt_struct* obj;
ASSERTMSGLINE(366, lt_obj != NULL, "Light Object Pointer is null");
obj = (__GXLightObjInt_struct*)lt_obj;
obj->ldir[0] = -nx;
obj->ldir[1] = -ny;
obj->ldir[2] = -nz;
}
void GXGetLightDir(const GXLightObj* lt_obj, f32* nx, f32* ny, f32* nz) {
__GXLightObjInt_struct* obj;
ASSERTMSGLINE(372, lt_obj != NULL, "Light Object Pointer is null");
obj = (__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) {
f32 mag;
f32 vx;
f32 vy;
f32 vz;
__GXLightObjInt_struct* obj;
ASSERTMSGLINE(398, lt_obj != NULL, "Light Object Pointer is null");
obj = (__GXLightObjInt_struct*)lt_obj;
CHECK_GXBEGIN(399, "GXInitSpecularDir");
vx = -nx;
vy = -ny;
vz = -nz + 1.0f;
mag = (vx * vx) + (vy * vy) + (vz * vz);
if (mag != 0.0f) {
mag = 1.0f / sqrtf(mag);
}
obj->ldir[0] = vx * mag;
obj->ldir[1] = vy * mag;
obj->ldir[2] = vz * mag;
obj->lpos[0] = nx * -1000000000000000000.0f;
obj->lpos[1] = ny * -1000000000000000000.0f;
obj->lpos[2] = nz * -1000000000000000000.0f;
}
void GXInitSpecularDirHA(GXLightObj* lt_obj, f32 nx, f32 ny, f32 nz, f32 hx, f32 hy, f32 hz) {
__GXLightObjInt_struct* obj;
ASSERTMSGLINE(436, lt_obj != NULL, "Light Object Pointer is null");
obj = (__GXLightObjInt_struct*)lt_obj;
CHECK_GXBEGIN(437, "GXInitSpecularHA");
obj->ldir[0] = hx;
obj->ldir[1] = hy;
obj->ldir[2] = hz;
obj->lpos[0] = nx * -1000000000000000000.0f;
obj->lpos[1] = ny * -1000000000000000000.0f;
obj->lpos[2] = nz * -1000000000000000000.0f;
}
void GXInitLightColor(GXLightObj* lt_obj, GXColor color) {
__GXLightObjInt_struct* obj;
ASSERTMSGLINE(468, lt_obj != NULL, "Light Object Pointer is null");
obj = (__GXLightObjInt_struct*)lt_obj;
CHECK_GXBEGIN(469, "GXInitLightColor");
obj->Color = *(u32*)&color;
}
void GXGetLightColor(const GXLightObj* lt_obj, GXColor* color) {
__GXLightObjInt_struct* obj;
ASSERTMSGLINE(476, lt_obj != NULL, "Light Object Pointer is null");
obj = (__GXLightObjInt_struct*)lt_obj;
CHECK_GXBEGIN(477, "GXGetLightColor");
*(u32*)color = *(u32*)&obj->Color;
}
#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
static inline u32 ConvLightID2Num(GXLightID id) {
switch (id) {
case GX_LIGHT0: return 0;
case GX_LIGHT1: return 1;
case GX_LIGHT2: return 2;
case GX_LIGHT3: return 3;
case GX_LIGHT4: return 4;
case GX_LIGHT5: return 5;
case GX_LIGHT6: return 6;
case GX_LIGHT7: return 7;
default: return 8;
}
}
static inline void PushLight(const __REGISTER GXLightObj* lt_obj, __REGISTER void* dest) {
__REGISTER u32 zero, color;
__REGISTER f32 a0_a1, a2_k0, k1_k2;
__REGISTER f32 px_py, pz_dx, dy_dz;
#ifdef __MWERKS__ // clang-format off
asm {
lwz color, 12(lt_obj)
xor zero, zero, zero
psq_l a0_a1, 16(lt_obj), 0, 0
psq_l a2_k0, 24(lt_obj), 0, 0
psq_l k1_k2, 32(lt_obj), 0, 0
psq_l px_py, 40(lt_obj), 0, 0
psq_l pz_dx, 48(lt_obj), 0, 0
psq_l dy_dz, 56(lt_obj), 0, 0
stw zero, 0(dest)
stw zero, 0(dest)
stw zero, 0(dest)
stw color, 0(dest)
psq_st a0_a1, 0(dest), 0, 0
psq_st a2_k0, 0(dest), 0, 0
psq_st k1_k2, 0(dest), 0, 0
psq_st px_py, 0(dest), 0, 0
psq_st pz_dx, 0(dest), 0, 0
psq_st dy_dz, 0(dest), 0, 0
}
#endif // clang-format on
}
void GXLoadLightObjImm(const GXLightObj* lt_obj, GXLightID light) {
u32 addr;
u32 idx;
__GXLightObjInt_struct* obj;
ASSERTMSGLINE(579, lt_obj != NULL, "Light Object Pointer is null");
obj = (__GXLightObjInt_struct*)lt_obj;
CHECK_GXBEGIN(580, "GXLoadLightObjImm");
#if DEBUG
idx = ConvLightID2Num(light);
#else
idx = 31 - __cntlzw(light);
#endif
ASSERTMSGLINE(586, idx < 8, "GXLoadLightObjImm: Invalid Light Id");
idx &= 7;
addr = idx * 0x10 + 0x600;
GX_WRITE_U8(0x10);
GX_WRITE_U32(addr | 0xF0000);
#if DEBUG
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);
#else
PushLight(lt_obj, (void*)GXFIFO_ADDR);
#endif
__GXData->bpSentNot = 1;
}
void GXLoadLightObjIndx(u32 lt_obj_indx, GXLightID light) {
u32 reg;
u32 addr;
u32 idx;
CHECK_GXBEGIN(624, "GXLoadLightObjIndx");
#if DEBUG
idx = ConvLightID2Num(light);
#else
idx = 31 - __cntlzw(light);
#endif
ASSERTMSGLINE(627, idx < 8, "GXLoadLightObjIndx: Invalid Light Id");
idx &= 7;
addr = idx * 0x10 + 0x600;
reg = 0;
SET_REG_FIELD(632, reg, 12, 0, addr);
SET_REG_FIELD(634, reg, 4, 12, 0xF);
SET_REG_FIELD(634, reg, 16, 16, lt_obj_indx);
GX_WRITE_U8(0x38);
GX_WRITE_U32(reg);
#if DEBUG
__GXShadowIndexState(7, reg);
#endif
__GXData->bpSentNot = 1;
}
#define GXCOLOR_AS_U32(color) (*((u32*)&(color)))
void GXSetChanAmbColor(GXChannelID chan, GXColor amb_color) {
u32 reg = 0;
u32 rgb;
u32 colIdx;
CHECK_GXBEGIN(675, "GXSetChanAmbColor");
switch (chan) {
case GX_COLOR0:
reg = __GXData->ambColor[GX_COLOR0];
rgb = GXCOLOR_AS_U32(amb_color) >> 8;
SC_XF_AMBIENT0_F_SET_RGB(689, reg, rgb);
colIdx = 0;
break;
case GX_COLOR1:
reg = __GXData->ambColor[GX_COLOR1];
rgb = GXCOLOR_AS_U32(amb_color) >> 8;
SC_XF_AMBIENT1_F_SET_RGB(704, reg, rgb);
colIdx = 1;
break;
case GX_ALPHA0:
reg = __GXData->ambColor[GX_COLOR0];
SC_XF_AMBIENT0_F_SET_ALPHA(710, reg, amb_color.a);
colIdx = 0;
break;
case GX_ALPHA1:
reg = __GXData->ambColor[GX_COLOR1];
SC_XF_AMBIENT1_F_SET_ALPHA(716, reg, amb_color.a);
colIdx = 1;
break;
case GX_COLOR0A0:
reg = GXCOLOR_AS_U32(amb_color);
colIdx = 0;
break;
case GX_COLOR1A1:
reg = GXCOLOR_AS_U32(amb_color);
colIdx = 1;
break;
default:
ASSERTMSGLINE(745, 0, "GXSetChanAmbColor: Invalid Channel Id");
return;
}
__GXData->dirtyState |= (0x100 << colIdx);
__GXData->ambColor[colIdx] = reg;
}
void GXSetChanMatColor(GXChannelID chan, GXColor mat_color) {
u32 reg = 0;
u32 rgb;
u32 colIdx;
CHECK_GXBEGIN(776, "GXSetChanMatColor");
switch (chan) {
case GX_COLOR0:
reg = __GXData->matColor[GX_COLOR0];
rgb = GXCOLOR_AS_U32(mat_color) >> 8;
SC_XF_MATERIAL0_F_SET_RGB(790, reg, rgb);
colIdx = 0;
break;
case GX_COLOR1:
reg = __GXData->matColor[GX_COLOR1];
rgb = GXCOLOR_AS_U32(mat_color) >> 8;
SC_XF_MATERIAL1_F_SET_RGB(805, reg, rgb);
colIdx = 1;
break;
case GX_ALPHA0:
reg = __GXData->matColor[GX_COLOR0];
SC_XF_MATERIAL0_F_SET_ALPHA(811, reg, mat_color.a);
colIdx = 0;
break;
case GX_ALPHA1:
reg = __GXData->matColor[GX_COLOR1];
SC_XF_MATERIAL1_F_SET_ALPHA(817, reg, mat_color.a);
colIdx = 1;
break;
case GX_COLOR0A0:
reg = GXCOLOR_AS_U32(mat_color);
colIdx = 0;
break;
case GX_COLOR1A1:
reg = GXCOLOR_AS_U32(mat_color);
colIdx = 1;
break;
default:
ASSERTMSGLINE(846, 0, "GXSetChanMatColor: Invalid Channel Id");
return;
}
__GXData->dirtyState |= (0x400 << colIdx);
__GXData->matColor[colIdx] = reg;
}
void GXSetNumChans(u8 nChans) {
CHECK_GXBEGIN(871, "GXSetNumChans");
ASSERTMSGLINE(872, nChans <= 2, "GXSetNumChans: nChans > 2");
SC_GEN_MODE_SET_NCOL(874, __GXData->genMode, nChans);
__GXData->dirtyState |= 0x1000004;
}
void GXSetChanCtrl(GXChannelID chan, GXBool enable, GXColorSrc amb_src, GXColorSrc mat_src, u32 light_mask, GXDiffuseFn diff_fn, GXAttnFn attn_fn) {
u32 reg;
u32 idx;
CHECK_GXBEGIN(906, "GXSetChanCtrl");
ASSERTMSGLINE(909, chan >= GX_COLOR0 && chan <= GX_COLOR1A1, "GXSetChanCtrl: Invalid Channel Id");
#if DEBUG
if (chan == GX_COLOR0A0)
idx = 0;
else if (chan == GX_COLOR1A1)
idx = 1;
else
idx = chan;
#else
idx = chan & 0x3;
#endif
reg = 0;
SC_XF_COLOR0CNTRL_F_SET_LIGHTFUNC(921, reg, enable);
SC_XF_COLOR0CNTRL_F_SET_MATERIAL_SRC(922, reg, mat_src);
SC_XF_COLOR0CNTRL_F_SET_AMBIENT_SRC(923, reg, amb_src);
SC_XF_COLOR0CNTRL_F_SET_DIFFUSEATTEN(925, reg, (attn_fn == 0) ? 0 : diff_fn);
SC_XF_COLOR0CNTRL_F_SET_ATTENENABLE(926, reg, (attn_fn != 2));
SC_XF_COLOR0CNTRL_F_SET_ATTENSELECT(927, reg, (attn_fn != 0));
SC_XF_COLOR0CNTRL_F_SET_LIGHT0123(939, reg, light_mask & 0xF);
SC_XF_COLOR0CNTRL_F_SET_LIGHT4567(940, reg, (light_mask & 0xF0) >> 4);
__GXData->chanCtrl[idx] = reg;
__GXData->dirtyState |= (0x1000<<idx);
if (chan == GX_COLOR0A0) {
__GXData->chanCtrl[GX_ALPHA0] = reg;
__GXData->dirtyState |= (0x00001000|0x00004000);
} else if (chan == GX_COLOR1A1) {
__GXData->chanCtrl[GX_ALPHA1] = reg;
__GXData->dirtyState |= (0x00002000|0x00008000);
}
}
+482
View File
@@ -0,0 +1,482 @@
#include <stddef.h>
#include <revolution/base/PPCArch.h>
#include <revolution/gx.h>
#include <revolution/os.h>
#include "__gx.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:
__GXData->vNum = val;
__GXData->vNumNot = !__GXData->vNum;
__GXData->bpSentNot = 1;
if (__GXData->vNum != 0) {
__GXData->dirtyState |= 8;
}
break;
case GX_MT_DL_SAVE_CONTEXT:
ASSERTMSGLINE(235, !__GXData->inDispList, "GXSetMisc: Cannot change DL context setting while making a display list");
__GXData->dlSaveContext = (val != 0);
break;
case GX_MT_ABORT_WAIT_COPYOUT:
__GXData->abtWaitPECopy = (val != 0);
break;
case GX_MT_NULL:
break;
default:
#if DEBUG
OSReport("GXSetMisc: bad token %d (val %d)\n", token, val);
#endif
break;
}
}
void GXFlush(void) {
CHECK_GXBEGIN(284, "GXFlush");
if (__GXData->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 void __GXAbortWait(u32 clocks) {
OSTime time0;
OSTime time1;
time0 = OSGetTime();
do {
time1 = OSGetTime();
} while (time1 - time0 <= (clocks / 4));
}
static void __GXAbortWaitPECopyDone(void) {
u32 peCnt0;
u32 peCnt1;
peCnt0 = __GXReadMEMCounterU32(0x28, 0x27);
do {
peCnt1 = peCnt0;
__GXAbortWait(32);
peCnt0 = __GXReadMEMCounterU32(0x28, 0x27);
} while (peCnt0 != peCnt1);
}
void __GXAbort(void) {
if (__GXData->abtWaitPECopy && __GXIsGPFifoReady()) {
__GXAbortWaitPECopyDone();
}
__PIRegs[0x18 / 4] = 1;
__GXAbortWait(200);
__PIRegs[0x18 / 4] = 0;
__GXAbortWait(20);
}
void GXAbortFrame(void) {
__GXAbort();
if (__GXIsGPFifoReady()) {
__GXCleanGPFifo();
__GXInitRevisionBits();
__GXData->dirtyState = 0;
GXFlush();
}
}
void GXSetDrawSync(u16 token) {
BOOL enabled;
u32 reg;
CHECK_GXBEGIN(489, "GXSetDrawSync");
enabled = OSDisableInterrupts();
reg = token | 0x48000000;
GX_WRITE_RA_REG(reg);
SC_PE_TOKEN_SET_TOKEN(443, reg, token);
SC_PE_TOKEN_SET_RID(443, reg, 0x47);
GX_WRITE_RA_REG(reg);
GXFlush();
OSRestoreInterrupts(enabled);
__GXData->bpSentNot = 0;
}
u16 GXReadDrawSync(void) {
u16 token = GX_GET_PE_REG(7);
return token;
}
void GXSetDrawDone(void) {
u32 reg;
BOOL enabled;
CHECK_GXBEGIN(489, "GXSetDrawDone");
enabled = OSDisableInterrupts();
reg = 0x45000002;
GX_WRITE_RA_REG(reg);
GXFlush();
DrawDone = GX_FALSE;
OSRestoreInterrupts(enabled);
__GXData->bpSentNot = GX_FALSE;
}
void GXWaitDrawDone(void) {
BOOL enabled;
CHECK_GXBEGIN(527, "GXWaitDrawDone");
enabled = OSDisableInterrupts();
while (!DrawDone) {
OSSleepThread(&FinishQueue);
}
OSRestoreInterrupts(enabled);
}
void GXDrawDone(void) {
CHECK_GXBEGIN(558, "GXDrawDone");
GXSetDrawDone();
GXWaitDrawDone();
}
void GXPixModeSync(void) {
CHECK_GXBEGIN(580, "GXPixModeSync");
GX_WRITE_RA_REG(__GXData->peCtrl);
__GXData->bpSentNot = 0;
}
void GXTexModeSync(void) {
u32 reg;
CHECK_GXBEGIN(625, "GXTexModeSync");
reg = 0x63000000;
GX_WRITE_RA_REG(reg);
__GXData->bpSentNot = 0;
}
#if DEBUG
void __GXBypass(u32 reg) {
CHECK_GXBEGIN(647, "__GXBypass");
GX_WRITE_RA_REG(reg);
__GXData->bpSentNot = 0;
}
u16 __GXReadPEReg(u32 reg) {
return GX_GET_PE_REG(reg);
}
#endif
void GXPokeAlphaMode(GXCompare func, u8 threshold) {
u32 reg;
reg = (func << 8) | threshold;
GX_SET_PE_REG(3, reg);
}
void GXPokeAlphaRead(GXAlphaReadMode mode) {
u32 reg;
reg = 0;
SC_PE_PI_CTL_SET_AFMT(672, reg, mode);
SC_PE_PI_CTL_SET_ZFMT(672, reg, 1);
GX_SET_PE_REG(4, reg);
}
void GXPokeAlphaUpdate(GXBool update_enable) {
u32 reg;
reg = GX_GET_PE_REG(1);
SC_PE_CMODE0_SET_ALPHA_MASK(683, reg, update_enable);
GX_SET_PE_REG(1, reg);
}
void GXPokeBlendMode(GXBlendMode type, GXBlendFactor src_factor, GXBlendFactor dst_factor, GXLogicOp op) {
u32 reg;
reg = GX_GET_PE_REG(1);
SC_PE_CMODE0_SET_BLEND_ENABLE(699, reg, ((type == GX_BM_BLEND) || (type == GX_BM_SUBTRACT)));
SC_PE_CMODE0_SET_BLENDOP(700, reg, (type == GX_BM_SUBTRACT));
SC_PE_CMODE0_SET_LOGICOP_ENABLE(702, reg, (type == GX_BM_LOGIC));
SC_PE_CMODE0_SET_LOGICOP(703, reg, op);
SC_PE_CMODE0_SET_SFACTOR(704, reg, src_factor);
SC_PE_CMODE0_SET_DFACTOR(705, reg, dst_factor);
SC_PE_CMODE0_SET_RID(706, reg, 0x41);
GX_SET_PE_REG(1, reg);
}
void GXPokeColorUpdate(GXBool update_enable) {
u32 reg;
reg = GX_GET_PE_REG(1);
SC_PE_CMODE0_SET_COLOR_MASK(717, reg, update_enable);
GX_SET_PE_REG(1, reg);
}
void GXPokeDstAlpha(GXBool enable, u8 alpha) {
u32 reg = 0;
SC_PE_CMODE1_SET_CONSTANT_ALPHA(726, reg, alpha);
SC_PE_CMODE1_SET_CONSTANT_ALPHA_ENABLE(727, reg, enable);
GX_SET_PE_REG(2, reg);
}
void GXPokeDither(GXBool dither) {
u32 reg;
reg = GX_GET_PE_REG(1);
SC_PE_CMODE0_SET_DITHER_ENABLE(737, reg, dither);
GX_SET_PE_REG(1, reg);
}
void GXPokeZMode(GXBool compare_enable, GXCompare func, GXBool update_enable) {
u32 reg = 0;
SC_PE_ZMODE_SET_ENABLE(746, reg, compare_enable);
SC_PE_ZMODE_SET_FUNC(747, reg, func);
SC_PE_ZMODE_SET_MASK(748, reg, update_enable);
GX_SET_PE_REG(0, reg);
}
void GXPeekARGB(u16 x, u16 y, u32* color) {
u32 addr = (u32)OSPhysicalToUncached(0x08000000);
SC_PE_PI_EFB_ADDR_SET_X(771, addr, x);
SC_PE_PI_EFB_ADDR_SET_Y(772, addr, y);
SC_PE_PI_EFB_ADDR_SET_TYPE(773, addr, 0);
*color = *(u32*)addr;
}
void GXPokeARGB(u16 x, u16 y, u32 color) {
u32 addr = (u32)OSPhysicalToUncached(0x08000000);
SC_PE_PI_EFB_ADDR_SET_X(771, addr, x);
SC_PE_PI_EFB_ADDR_SET_Y(772, addr, y);
SC_PE_PI_EFB_ADDR_SET_TYPE(773, addr, 0);
*(u32*)addr = color;
}
void GXPeekZ(u16 x, u16 y, u32* z) {
u32 addr = (u32)OSPhysicalToUncached(0x08000000);
SC_PE_PI_EFB_ADDR_SET_X(791, addr, x);
SC_PE_PI_EFB_ADDR_SET_Y(792, addr, y);
SC_PE_PI_EFB_ADDR_SET_TYPE(793, addr, 1);
*z = *(u32*)addr;
}
void GXPokeZ(u16 x, u16 y, u32 z) {
u32 addr = (u32)OSPhysicalToUncached(0x08000000);
SC_PE_PI_EFB_ADDR_SET_X(791, addr, x);
SC_PE_PI_EFB_ADDR_SET_Y(792, addr, y);
SC_PE_PI_EFB_ADDR_SET_TYPE(793, addr, 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 = GX_GET_PE_REG(7);
if (TokenCB != NULL) {
OSClearContext(&exceptionContext);
OSSetCurrentContext(&exceptionContext);
TokenCB(token);
OSClearContext(&exceptionContext);
OSSetCurrentContext(context);
}
reg = GX_GET_PE_REG(5);
SC_PE_INTRCTL_SET_INT0CLR(0, reg, 1);
GX_SET_PE_REG(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 = 0;
reg = GX_GET_PE_REG(5);
SC_PE_INTRCTL_SET_INT1CLR(0, reg, 1);
GX_SET_PE_REG(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 = GX_GET_PE_REG(5);
SC_PE_INTRCTL_SET_INT0CLR(0, reg, 1);
SC_PE_INTRCTL_SET_INT1CLR(0, reg, 1);
SC_PE_INTRCTL_SET_INT0EN(0, reg, 1);
SC_PE_INTRCTL_SET_INT1EN(0, reg, 1);
GX_SET_PE_REG(5, reg);
}
u32 GXCompressZ16(u32 z24, GXZFmt16 zfmt) {
u32 z16;
u32 z24n;
s32 exp;
s32 shift;
#if DEBUG
#define temp exp
#else
s32 temp;
u8 unused[4];
#endif
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__, 1004, "GXCompressZ16: Invalid Z format\n");
break;
}
return z16;
}
u32 GXDecompressZ16(u32 z16, GXZFmt16 zfmt) {
u32 z24;
u32 cb1;
s32 exp;
s32 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__, 1054, "GXDecompressZ16: Invalid Z format\n");
break;
}
return z24;
}
+431
View File
@@ -0,0 +1,431 @@
#include <revolution/gx.h>
#include <revolution/os.h>
#include "__gx.h"
void GXSetGPMetric(GXPerf0 perf0, GXPerf1 perf1) {
u32 reg;
CHECK_GXBEGIN(142, "GXSetGPMetric");
switch (__GXData->perf0) {
case GX_PERF0_VERTICES:
case GX_PERF0_CLIP_VTX:
case GX_PERF0_CLIP_CLKS:
case GX_PERF0_XF_WAIT_IN:
case GX_PERF0_XF_WAIT_OUT:
case GX_PERF0_XF_XFRM_CLKS:
case GX_PERF0_XF_LIT_CLKS:
case GX_PERF0_XF_BOT_CLKS:
case GX_PERF0_XF_REGLD_CLKS:
case GX_PERF0_XF_REGRD_CLKS:
case GX_PERF0_CLIP_RATIO:
case GX_PERF0_CLOCKS:
reg = 0;
GX_WRITE_XF_REG(0x1006, reg, 0);
break;
case GX_PERF0_TRIANGLES:
case GX_PERF0_TRIANGLES_CULLED:
case GX_PERF0_TRIANGLES_PASSED:
case GX_PERF0_TRIANGLES_SCISSORED:
case GX_PERF0_TRIANGLES_0TEX:
case GX_PERF0_TRIANGLES_1TEX:
case GX_PERF0_TRIANGLES_2TEX:
case GX_PERF0_TRIANGLES_3TEX:
case GX_PERF0_TRIANGLES_4TEX:
case GX_PERF0_TRIANGLES_5TEX:
case GX_PERF0_TRIANGLES_6TEX:
case GX_PERF0_TRIANGLES_7TEX:
case GX_PERF0_TRIANGLES_8TEX:
case GX_PERF0_TRIANGLES_0CLR:
case GX_PERF0_TRIANGLES_1CLR:
case GX_PERF0_TRIANGLES_2CLR:
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(202, 0, "GXSetGPMetric: Invalid GXPerf0 metric name");
break;
}
switch (__GXData->perf1) {
case GX_PERF1_TEXELS:
case GX_PERF1_TX_IDLE:
case GX_PERF1_TX_REGS:
case GX_PERF1_TX_MEMSTALL:
case GX_PERF1_TC_CHECK1_2:
case GX_PERF1_TC_CHECK3_4:
case GX_PERF1_TC_CHECK5_6:
case GX_PERF1_TC_CHECK7_8:
case GX_PERF1_TC_MISS:
case GX_PERF1_CLOCKS:
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, __GXData->perfSel, 4, 4, 0);
GX_WRITE_SOME_REG4(8, 0x20, __GXData->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(252, 0, "GXSetGPMetric: Invalid GXPerf1 metric name");
break;
}
__GXData->perf0 = perf0;
switch (__GXData->perf0) {
case GX_PERF0_VERTICES:
ASSERTMSGLINE(266, 0, "The use of GX_PERF0_VERTICES is prohibited. Use GX_PERF1_VERTICES instead.\n");
reg = 0x273;
GX_WRITE_XF_REG(0x1006, reg, 0);
break;
case GX_PERF0_CLIP_VTX: reg = 0x14A; GX_WRITE_XF_REG(0x1006, reg, 0); break;
case GX_PERF0_CLIP_CLKS: reg = 0x16B; GX_WRITE_XF_REG(0x1006, reg, 0); break;
case GX_PERF0_XF_WAIT_IN: reg = 0x84; GX_WRITE_XF_REG(0x1006, reg, 0); break;
case GX_PERF0_XF_WAIT_OUT: reg = 0xC6; GX_WRITE_XF_REG(0x1006, reg, 0); break;
case GX_PERF0_XF_XFRM_CLKS: reg = 0x210; GX_WRITE_XF_REG(0x1006, reg, 0); break;
case GX_PERF0_XF_LIT_CLKS: reg = 0x252; GX_WRITE_XF_REG(0x1006, reg, 0); break;
case GX_PERF0_XF_BOT_CLKS: reg = 0x231; GX_WRITE_XF_REG(0x1006, reg, 0); break;
case GX_PERF0_XF_REGLD_CLKS: reg = 0x1AD; GX_WRITE_XF_REG(0x1006, reg, 0); break;
case GX_PERF0_XF_REGRD_CLKS: reg = 0x1CE; GX_WRITE_XF_REG(0x1006, reg, 0); break;
case GX_PERF0_CLOCKS: reg = 0x21; GX_WRITE_XF_REG(0x1006, reg, 0); break;
case GX_PERF0_CLIP_RATIO: reg = 0x153; GX_WRITE_XF_REG(0x1006, reg, 0); 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(512, 0, "GXSetGPMetric: Invalid GXPerf0 metric name");
break;
}
__GXData->perf1 = perf1;
switch (__GXData->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, __GXData->perfSel, 4, 4, 2); GX_WRITE_SOME_REG4(8, 0x20, __GXData->perfSel, -12); break;
case GX_PERF1_VC_MISSQ_FULL: SET_REG_FIELD(0, __GXData->perfSel, 4, 4, 3); GX_WRITE_SOME_REG4(8, 0x20, __GXData->perfSel, -12); break;
case GX_PERF1_VC_MEMREQ_FULL: SET_REG_FIELD(0, __GXData->perfSel, 4, 4, 4); GX_WRITE_SOME_REG4(8, 0x20, __GXData->perfSel, -12); break;
case GX_PERF1_VC_STATUS7: SET_REG_FIELD(0, __GXData->perfSel, 4, 4, 5); GX_WRITE_SOME_REG4(8, 0x20, __GXData->perfSel, -12); break;
case GX_PERF1_VC_MISSREP_FULL: SET_REG_FIELD(0, __GXData->perfSel, 4, 4, 6); GX_WRITE_SOME_REG4(8, 0x20, __GXData->perfSel, -12); break;
case GX_PERF1_VC_STREAMBUF_LOW: SET_REG_FIELD(0, __GXData->perfSel, 4, 4, 7); GX_WRITE_SOME_REG4(8, 0x20, __GXData->perfSel, -12); break;
case GX_PERF1_VC_ALL_STALLS: SET_REG_FIELD(0, __GXData->perfSel, 4, 4, 9); GX_WRITE_SOME_REG4(8, 0x20, __GXData->perfSel, -12); break;
case GX_PERF1_VERTICES: SET_REG_FIELD(0, __GXData->perfSel, 4, 4, 8); GX_WRITE_SOME_REG4(8, 0x20, __GXData->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(657, 0, "GXSetGPMetric: Invalid GXPerf1 metric name");
break;
}
__GXData->bpSentNot = 0;
}
#pragma scheduling off
void GXReadGPMetric(u32* cnt0, u32* cnt1) {
u32 cpCtr0, cpCtr1, cpCtr2, cpCtr3;
cpCtr0 = __GXReadCPCounterU32(32, 33);
cpCtr1 = __GXReadCPCounterU32(34, 35);
cpCtr2 = __GXReadCPCounterU32(36, 37);
cpCtr3 = __GXReadCPCounterU32(38, 39);
switch (__GXData->perf0) {
case GX_PERF0_CLIP_RATIO:
*cnt0 = cpCtr1 * 1000 / 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(765, 0, "GXReadGPMetric: Invalid GXPerf0 metric name");
*cnt0 = 0;
break;
}
switch (__GXData->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(824, 0, "GXReadGPMetric: Invalid GXPerf1 metric name");
*cnt1 = 0;
break;
}
}
#pragma scheduling reset
void GXClearGPMetric(void) {
u32 reg;
reg = 4;
GX_SET_CP_REG(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) {
*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) {
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(1163, "GXClearPixMetric");
reg = 0x57000000;
GX_WRITE_RAS_REG(reg);
reg = 0x57000AAA;
GX_WRITE_RAS_REG(reg);
__GXData->bpSentNot = 0;
}
void GXSetVCacheMetric(GXVCachePerf attr) {
u32 reg;
SET_REG_FIELD(1194, __GXData->perfSel, 4, 0, attr);
GX_WRITE_SOME_REG4(8, 0x20, __GXData->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 reset
void GXClearVCacheMetric(void) {
GX_WRITE_SOME_REG4(8, 0, 0, -12);
}
void GXInitXfRasMetric(void) {
u32 reg;
CHECK_GXBEGIN(1293, "GXInitXfRasMetric");
reg = 0x2402C022;
GX_WRITE_RAS_REG(reg);
reg = 0x31000;
GX_WRITE_XF_REG(6, reg, 0);
__GXData->bpSentNot = 1;
}
#pragma scheduling off
void GXReadXfRasMetric(u32* xf_wait_in, u32* xf_wait_out, u32* ras_busy, u32* clocks) {
*ras_busy = __GXReadCPCounterU32(32, 33);
*clocks = __GXReadCPCounterU32(34, 35);
*xf_wait_in = __GXReadCPCounterU32(36, 37);
*xf_wait_out = __GXReadCPCounterU32(38, 39);
}
#pragma scheduling reset
u32 GXReadClksPerVtx(void) {
u32 perfCnt;
u32 ctrh;
GXDrawDone();
GX_SET_CP_REG(49, 0x1007);
GX_SET_CP_REG(48, 0x1007);
ctrh = GX_GET_CP_REG(50);
perfCnt = ctrh >> 8;
return perfCnt;
}
void __GXSetBWDials(u16 cpDial, u16 tcDial, u16 peDial, u16 cpuRdDial, u16 cpuWrDial) {
__MEMRegs[9] = cpDial;
__MEMRegs[10] = tcDial;
__MEMRegs[11] = peDial;
__MEMRegs[12] = cpuRdDial;
__MEMRegs[13] = cpuWrDial;
}
+332
View File
@@ -0,0 +1,332 @@
#include <math.h>
#include <revolution/gx.h>
#include <revolution/os.h>
#include "__gx.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;
u32 fsel;
u32 proj;
u32 rgba;
fogclr = 0;
fog0 = 0;
fog1 = 0;
fog2 = 0;
fog3 = 0;
CHECK_GXBEGIN(152, "GXSetFog");
ASSERTMSGLINE(154, farz >= 0.0f, "GXSetFog: The farz should be positive value");
ASSERTMSGLINE(155, farz >= nearz, "GXSetFog: The farz should be larger than nearz");
fsel = type & 7;
proj = (type >> 3) & 1;
if (proj) {
if (farz == nearz || endz == startz) {
a = 0.0f;
c = 0.0f;
} else {
A = (1.0f / (endz - startz));
a = A * (farz - nearz);
c = A * (startz - nearz);
}
} else {
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 /= 2.0f;
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;
SET_REG_FIELD(212, fog1, 24, 0, b_m);
SET_REG_FIELD(212, fog1, 8, 24, 0xEF);
SET_REG_FIELD(215, fog2, 5, 0, b_s);
SET_REG_FIELD(215, fog2, 8, 24, 0xF0);
GX_WRITE_RAS_REG(fog1);
GX_WRITE_RAS_REG(fog2);
}
a_hex = *(u32*)&a;
c_hex = *(u32*)&c;
SET_REG_FIELD(226, fog0, 11, 0, (a_hex >> 12) & 0x7FF);
SET_REG_FIELD(227, fog0, 8, 11, (a_hex >> 23) & 0xFF);
SET_REG_FIELD(228, fog0, 1, 19, (a_hex >> 31));
SET_REG_FIELD(228, fog0, 8, 24, 0xEE);
SET_REG_FIELD(231, fog3, 11, 0, (c_hex >> 12) & 0x7FF);
SET_REG_FIELD(232, fog3, 8, 11, (c_hex >> 23) & 0xFF);
SET_REG_FIELD(233, fog3, 1, 19, (c_hex >> 31));
SET_REG_FIELD(234, fog3, 1, 20, proj);
SET_REG_FIELD(235, fog3, 3, 21, fsel);
SET_REG_FIELD(236, fog3, 8, 24, 0xF1);
rgba = *(u32*)&color;
SET_REG_FIELD(239, fogclr, 24, 0, rgba >> 8);
SET_REG_FIELD(240, fogclr, 8, 24, 0xF2);
GX_WRITE_RAS_REG(fog0);
GX_WRITE_RAS_REG(fog3);
GX_WRITE_RAS_REG(fogclr);
__GXData->bpSentNot = 0;
}
void GXSetFogColor(GXColor color) {
u32 rgba;
u32 fogclr = 0xF2000000;
rgba = *(u32*)&color;
SET_REG_FIELD(250, fogclr, 24, 0, rgba >> 8);
GX_WRITE_RAS_REG(fogclr);
__GXData->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(275, "GXInitFogAdjTable");
ASSERTMSGLINE(276, table != NULL, "GXInitFogAdjTable: table pointer is null");
ASSERTMSGLINE(277, 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(347, "GXSetFogRangeAdj");
if (enable) {
ASSERTMSGLINE(350, table != NULL, "GXSetFogRangeAdj: table pointer is null");
for (i = 0; i < 10; i += 2) {
range_adj = 0;
SET_REG_FIELD(354, range_adj, 12, 0, table->r[i]);
SET_REG_FIELD(355, range_adj, 12, 12, table->r[i + 1]);
SET_REG_FIELD(356, range_adj, 8, 24, (i >> 1) + 0xE9);
GX_WRITE_RAS_REG(range_adj);
}
}
range_c = 0;
SET_REG_FIELD(362, range_c, 10, 0, center + 342);
SET_REG_FIELD(363, range_c, 1, 10, enable);
SET_REG_FIELD(364, range_c, 8, 24, 0xE8);
GX_WRITE_RAS_REG(range_c);
__GXData->bpSentNot = 0;
}
void GXSetBlendMode(GXBlendMode type, GXBlendFactor src_factor, GXBlendFactor dst_factor, GXLogicOp op) {
u32 reg;
u32 blend_en;
CHECK_GXBEGIN(391, "GXSetBlendMode");
reg = __GXData->cmode0;
#if DEBUG
blend_en = type == GX_BM_BLEND || type == GX_BM_SUBTRACT;
#endif
SET_REG_FIELD(405, reg, 1, 11, (type == GX_BM_SUBTRACT));
#if DEBUG
SET_REG_FIELD(408, reg, 1, 0, blend_en);
#else
SET_REG_FIELD(408, reg, 1, 0, type);
#endif
SET_REG_FIELD(409, reg, 1, 1, (type == GX_BM_LOGIC));
SET_REG_FIELD(410, reg, 4, 12, op);
SET_REG_FIELD(411, reg, 3, 8, src_factor);
SET_REG_FIELD(412, reg, 3, 5, dst_factor);
GX_WRITE_RAS_REG(reg);
__GXData->cmode0 = reg;
__GXData->bpSentNot = 0;
}
void GXSetColorUpdate(GXBool update_enable) {
u32 reg;
CHECK_GXBEGIN(435, "GXSetColorUpdate");
reg = __GXData->cmode0;
SET_REG_FIELD(437, reg, 1, 3, update_enable);
GX_WRITE_RAS_REG(reg);
__GXData->cmode0 = reg;
__GXData->bpSentNot = 0;
}
void GXSetAlphaUpdate(GXBool update_enable) {
u32 reg;
CHECK_GXBEGIN(474, "GXSetAlphaUpdate");
reg = __GXData->cmode0;
SET_REG_FIELD(476, reg, 1, 4, update_enable);
GX_WRITE_RAS_REG(reg);
__GXData->cmode0 = reg;
__GXData->bpSentNot = 0;
}
void GXSetZMode(GXBool compare_enable, GXCompare func, GXBool update_enable) {
u32 reg;
CHECK_GXBEGIN(517, "GXSetZMode");
reg = __GXData->zmode;
SET_REG_FIELD(520, reg, 1, 0, compare_enable);
SET_REG_FIELD(521, reg, 3, 1, func);
SET_REG_FIELD(522, reg, 1, 4, update_enable);
GX_WRITE_RAS_REG(reg);
__GXData->zmode = reg;
__GXData->bpSentNot = 0;
}
void GXSetZCompLoc(GXBool before_tex) {
CHECK_GXBEGIN(532, "GXSetZCompLoc");
SET_REG_FIELD(533, __GXData->peCtrl, 1, 6, before_tex);
GX_WRITE_RAS_REG(__GXData->peCtrl);
__GXData->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(569, "GXSetPixelFmt");
oldPeCtrl = __GXData->peCtrl;
ASSERTMSGLINE(573, pix_fmt >= GX_PF_RGB8_Z24 && pix_fmt <= GX_PF_YUV420, "Invalid Pixel format");
SET_REG_FIELD(575, __GXData->peCtrl, 3, 0, p2f[pix_fmt]);
SET_REG_FIELD(576, __GXData->peCtrl, 3, 3, z_fmt);
if (oldPeCtrl != __GXData->peCtrl) {
GX_WRITE_RAS_REG(__GXData->peCtrl);
aa = ((pix_fmt == GX_PF_RGB565_Z16) ? GX_TRUE : GX_FALSE);
SET_REG_FIELD(585, __GXData->genMode, 1, 9, aa);
__GXData->dirtyState |= 4;
}
if (p2f[pix_fmt] == 4) {
SET_REG_FIELD(592, __GXData->cmode1, 2, 9, (pix_fmt - 4) & 0x3);
SET_REG_FIELD(592, __GXData->cmode1, 8, 24, 0x42);
GX_WRITE_RAS_REG(__GXData->cmode1);
}
__GXData->bpSentNot = 0;
}
void GXSetDither(GXBool dither) {
u32 reg;
CHECK_GXBEGIN(634, "GXSetDither");
reg = __GXData->cmode0;
SET_REG_FIELD(637, reg, 1, 2, dither);
GX_WRITE_RAS_REG(reg);
__GXData->cmode0 = reg;
__GXData->bpSentNot = 0;
}
void GXSetDstAlpha(GXBool enable, u8 alpha) {
u32 reg;
CHECK_GXBEGIN(675, "GXSetDstAlpha");
reg = __GXData->cmode1;
SET_REG_FIELD(678, reg, 8, 0, alpha);
SET_REG_FIELD(679, reg, 1, 8, enable);
GX_WRITE_RAS_REG(reg);
__GXData->cmode1 = reg;
__GXData->bpSentNot = 0;
}
void GXSetFieldMask(GXBool odd_mask, GXBool even_mask) {
u32 reg;
CHECK_GXBEGIN(702, "GXSetFieldMask");
reg = 0;
SET_REG_FIELD(704, reg, 1, 0, even_mask);
SET_REG_FIELD(705, reg, 1, 1, odd_mask);
SET_REG_FIELD(705, reg, 8, 24, 0x44);
GX_WRITE_RAS_REG(reg);
__GXData->bpSentNot = 0;
}
void GXSetFieldMode(GXBool field_mode, GXBool half_aspect_ratio) {
u32 reg;
CHECK_GXBEGIN(731, "GXSetFieldMode");
SET_REG_FIELD(735, __GXData->lpSize, 1, 22, half_aspect_ratio);
GX_WRITE_RAS_REG(__GXData->lpSize);
__GXFlushTextureState();
reg = field_mode | 0x68000000;
GX_WRITE_RAS_REG(reg);
__GXFlushTextureState();
}
+528
View File
@@ -0,0 +1,528 @@
#if DEBUG
#include <revolution/gx.h>
#include <revolution/os.h>
#include "__gx.h"
static const u8* dlist;
static u32 dlistSize;
static u32 bytesRead;
// prototypes
void __GXShadowIndexState(u32 idx_reg, u32 reg_data);
static u8 __ReadMem(void* ptr, u32 sz) {
const u8* src;
u8* dst;
u32 i;
if (sz > dlistSize - bytesRead) {
return FALSE;
}
src = dlist;
dst = ptr;
for (i = 0; i < sz; i++) {
*dst++ = *src++;
}
bytesRead += sz;
dlist += sz;
return TRUE;
}
inline void DPF(char*, ...) {
u8 unused[4];
}
static void __SaveCPRegs(u8 reg, u8 vatIdx, u32 data) {
s32 idx;
DPF("\tCP Stream Reg[0x%x] = 0x%x\n", reg, data);
switch (reg) {
case 0:
case 1:
case 2:
case 3:
case 4:
break;
case 5:
__GXData->vcdLo = data;
break;
case 6:
__GXData->vcdHi = data;
break;
case 7:
__GXData->vatA[vatIdx] = data;
break;
case 8:
__GXData->vatB[vatIdx] = data;
break;
case 9:
__GXData->vatC[vatIdx] = data;
break;
case 10:
idx = vatIdx - 0x15;
if ((idx >= 0) && (idx < 4)) {
__GXData->indexBase[idx] = data;
}
break;
case 11:
idx = vatIdx - 0x15;
if ((idx >= 0) && (idx < 4)) {
__GXData->indexStride[idx] = data;
}
break;
default:
if (__gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_DL_INV_CMD]) {
__GX_WARN(GXWARN_DL_INV_CMD);
}
OSReport("[Invalid CP Stream Register Address 0x%x\n]", reg);
break;
}
}
static void __ReconstVtxStatus(u8 vatIdx) {
u32 vat;
if (GET_REG_FIELD(__GXData->vcdLo, 2, 11) & 3) {
vat = __GXData->vatA[vatIdx];
if ((vat >> 9) & 1) {
__GXData->hasNrms = 0;
__GXData->hasBiNrms = 1;
} else {
__GXData->hasNrms = 1;
__GXData->hasBiNrms = 0;
}
}
}
static u32 vtxCompSize[5] = { 1, 1, 2, 2, 4 };
static int clrCompSize[6] = { 2, 3, 4, 2, 3, 4 };
static u32 GetAttrSize(u8 vatIdx, u32 attrIdx) {
u32 vcd;
u32 vat;
u32 nc;
switch (attrIdx) {
case 0:
return GET_REG_FIELD(__GXData->vcdLo, 1, 0) ? 1 : 0;
case 1:
return GET_REG_FIELD(__GXData->vcdLo, 1, 1) ? 1 : 0;
case 2:
return GET_REG_FIELD(__GXData->vcdLo, 1, 2) ? 1 : 0;
case 3:
return GET_REG_FIELD(__GXData->vcdLo, 1, 3) ? 1 : 0;
case 4:
return GET_REG_FIELD(__GXData->vcdLo, 1, 4) ? 1 : 0;
case 5:
return GET_REG_FIELD(__GXData->vcdLo, 1, 5) ? 1 : 0;
case 6:
return GET_REG_FIELD(__GXData->vcdLo, 1, 6) ? 1 : 0;
case 7:
return GET_REG_FIELD(__GXData->vcdLo, 1, 7) ? 1 : 0;
case 8:
return GET_REG_FIELD(__GXData->vcdLo, 1, 8) ? 1 : 0;
case 9:
vcd = __GXData->vcdLo;
vat = __GXData->vatA[vatIdx & 0xFF];
switch (GET_REG_FIELD(vcd, 2, 9)) {
case 0:
return 0;
case 2:
return 1;
case 3:
return 2;
case 1:
return ((vat & 1) + 2) * vtxCompSize[(vat >> 1) & 7];
}
break;
case 10:
vcd = __GXData->vcdLo;
vat = __GXData->vatA[vatIdx & 0xFF];
switch (GET_REG_FIELD(vcd, 2, 11)) {
case 0:
return 0;
case 2:
if ((vat >> 9) & 1 && vat >> 31) {
nc = 3;
} else {
nc = 1;
}
return nc;
case 3:
if ((vat >> 9) & 1 && vat >> 31) {
nc = 6;
} else {
nc = 2;
}
return nc;
case 1:
if ((vat >> 9) & 1) {
nc = 9;
} else {
nc = 3;
}
return nc * vtxCompSize[(vat >> 10) & 7];
}
break;
case 11:
switch (GET_REG_FIELD(__GXData->vcdLo, 2, 13)) {
case 0:
return 0;
case 2:
return 1;
case 3:
return 2;
case 1:
vat = __GXData->vatA[vatIdx];
return clrCompSize[(vat >> 14) & 7];
}
break;
case 12:
switch (GET_REG_FIELD(__GXData->vcdLo, 2, 15)) {
case 0:
return 0;
case 2:
return 1;
case 3:
return 2;
case 1:
vat = __GXData->vatA[vatIdx];
return clrCompSize[(vat >> 18) & 7];
}
break;
case 13:
vcd = __GXData->vcdHi;
vat = __GXData->vatA[vatIdx & 0xFF];
switch (GET_REG_FIELD(vcd, 2, 0)) {
case 0:
return 0;
case 2:
return 1;
case 3:
return 2;
case 1:
return (((vat >> 21) & 1) + 1) * vtxCompSize[(vat >> 22) & 7];
}
break;
case 14:
vcd = __GXData->vcdHi;
vat = __GXData->vatB[vatIdx & 0xFF];
switch (GET_REG_FIELD(vcd, 2, 2)) {
case 0:
return 0;
case 2:
return 1;
case 3:
return 2;
case 1:
return (((vat >> 0) & 1) + 1) * vtxCompSize[(vat >> 1) & 7];
}
break;
case 15:
vcd = __GXData->vcdHi;
vat = __GXData->vatB[vatIdx & 0xFF];
switch (GET_REG_FIELD(vcd, 2, 4)) {
case 0:
return 0;
case 2:
return 1;
case 3:
return 2;
case 1:
return (((vat >> 9) & 1) + 1) * vtxCompSize[(vat >> 10) & 7];
}
break;
case 16:
vcd = __GXData->vcdHi;
vat = __GXData->vatB[vatIdx & 0xFF];
switch (GET_REG_FIELD(vcd, 2, 6)) {
case 0:
return 0;
case 2:
return 1;
case 3:
return 2;
case 1:
return (((vat >> 18) & 1) + 1) * vtxCompSize[(vat >> 19) & 7];
}
break;
case 17:
vcd = __GXData->vcdHi;
vat = __GXData->vatB[vatIdx & 0xFF];
switch (GET_REG_FIELD(vcd, 2, 8)) {
case 0:
return 0;
case 2:
return 1;
case 3:
return 2;
case 1:
return (((vat >> 27) & 1) + 1) * vtxCompSize[(vat >> 28) & 7];
}
break;
case 18:
vcd = __GXData->vcdHi;
vat = __GXData->vatC[vatIdx & 0xFF];
switch (GET_REG_FIELD(vcd, 2, 10)) {
case 0:
return 0;
case 2:
return 1;
case 3:
return 2;
case 1:
return (((vat >> 5) & 1) + 1) * vtxCompSize[(vat >> 6) & 7];
}
break;
case 19:
vcd = __GXData->vcdHi;
vat = __GXData->vatC[vatIdx & 0xFF];
switch (GET_REG_FIELD(vcd, 2, 12)) {
case 0:
return 0;
case 2:
return 1;
case 3:
return 2;
case 1:
return (((vat >> 14) & 1) + 1) * vtxCompSize[(vat >> 15) & 7];
}
break;
case 20:
vcd = __GXData->vcdHi;
vat = __GXData->vatC[vatIdx & 0xFF];
switch (GET_REG_FIELD(vcd, 2, 14)) {
case 0:
return 0;
case 2:
return 1;
case 3:
return 2;
case 1:
return (((vat >> 23) & 1) + 1) * vtxCompSize[(vat >> 24) & 7];
}
break;
}
return 0;
}
static void __ParseVertexData(u8 vatIdx) {
u16 vcnt;
GXAttr attrIdx;
u32 vsize;
if (__ReadMem(&vcnt, 2)) {
vsize = 0;
for (attrIdx = 0; attrIdx < GX_VA_MAX_ATTR; attrIdx++) {
if (attrIdx != GX_VA_NBT) {
vsize += GetAttrSize(vatIdx, attrIdx);
}
}
vsize *= vcnt;
dlist += vsize;
bytesRead += vsize;
}
}
void __GXShadowDispList(void* list, u32 nbytes) {
u8 cmd;
u8 cmdOp;
u8 vatIdx;
u32 reg32;
u32 d32;
u8 reg8;
u8 cpAddr;
u32 i;
u32 addr;
u32 cnt;
if (__gxVerif->verifyLevel == GX_WARN_NONE) {
return;
}
dlist = list;
dlistSize = nbytes;
bytesRead = 0;
DPF("Displaylist IN\n");
while (dlistSize > bytesRead) {
if (!__ReadMem(&cmd, 1)) {
break;
}
cmdOp = (u32)GET_REG_FIELD((u32)cmd, 5, 3);
vatIdx = cmd & 7;
switch (cmdOp) {
case 0:
case 9:
break;
case 16:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
__ReconstVtxStatus(vatIdx);
__GXVerifyState(vatIdx);
__ParseVertexData(vatIdx);
break;
case 1:
if (__ReadMem(&reg8, 1) && __ReadMem(&d32, 4)) {
vatIdx = reg8 & 0xF;
cpAddr = (reg8& 0xF0) >> 4;
__SaveCPRegs(cpAddr, vatIdx, d32);
}
break;
case 2:
if (__ReadMem(&reg32, 4)) {
cnt = GET_REG_FIELD(reg32, 4, 16) + 1;
addr = (u16)reg32;
DPF("\tXFReg = 0x%x, Cnt = %d\n", addr, cnt);
for (i = 0; i < cnt; i++) {
if (__ReadMem(&d32, 4)) {
DPF("\tXFData = 0x%x\n", d32);
VERIF_MTXLIGHT(addr, d32);
addr++;
}
}
}
break;
case 4:
case 5:
case 6:
case 7:
if (__ReadMem(&reg32, 4)) {
DPF("\tXF_INDEX_LOAD: = 0x%x\n", reg32);
__GXShadowIndexState(cmdOp, reg32);
}
break;
case 8:
if (__gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_DL_NESTED]) {
__GX_WARN(GXWARN_DL_NESTED);
}
return;
case 12:
case 13:
if (__ReadMem(&reg32, 4)) {
DPF("\tSU Bypass = 0x%x\n", reg32);
__gxVerif->rasRegs[(reg32 >> 24) & 0xFF] = reg32;
}
break;
default:
if (__gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_DL_INV_CMD]) {
__GX_WARN(GXWARN_DL_INV_CMD);
}
OSReport("[Bad Display List Command: 0x%02X\n]", cmdOp);
break;
}
}
DPF("Displaylist OUT\n");
}
void __GXShadowIndexState(u32 idx_reg, u32 reg_data) {
u32* basePtr;
u32* memAddr;
u32 cnt;
u32 stride;
u32 addr;
u32 data;
u32 index;
u32 i;
i = idx_reg - 4;
basePtr = OSPhysicalToCached(__GXData->indexBase[i]);
stride = __GXData->indexStride[i];
addr = reg_data & 0xFFF;
cnt = (reg_data >> 12) & 0xF;
index = reg_data >> 16;
memAddr = (u32*)((u8*)basePtr + (index * stride));
cnt++;
while (cnt-- != 0) {
data = *memAddr;
VERIF_MTXLIGHT(addr, data);
memAddr = (u32*)((u8*)memAddr + stride);
addr++;
}
&data; // needed to match
}
void __GXPrintShadowState(void) {
u32 i;
u32 j;
OSReport("CP State:\n");
OSReport("\tvcdLo = 0x%x\n", __GXData->vcdLo);
OSReport("\tvcdHi = 0x%x\n", __GXData->vcdHi);
OSReport("\thasBiNrms = 0x%x\n", __GXData->hasBiNrms);
for (i = 0; i < 8; i++) {
OSReport("\tVertex Format %d:\n", i);
OSReport("\t\tvatA = 0x%x\n", __GXData->vatA[i]);
OSReport("\t\tvatB = 0x%x\n", __GXData->vatB[i]);
OSReport("\t\tvatC = 0x%x\n", __GXData->vatC[i]);
}
OSReport("\n-------------------------------------\n");
OSReport("XF Pos/Tex Matrix State:\n");
for (i = 0; i < 256; i += 4) {
if (__gxVerif->xfMtxDirty[i]) {
OSReport("\tXF_MATRIX[%d] = ", i);
OSReport("%f, %f, %f, %f\n", *(f32*)&__gxVerif->xfMtx[i], *(f32*)&__gxVerif->xfMtx[i + 1], *(f32*)&__gxVerif->xfMtx[i + 2], *(f32*)&__gxVerif->xfMtx[i + 3]);
}
}
OSReport("\n-------------------------------------\n");
OSReport("XF Normal Matrix State:\n");
for (i = 0; i < 96; i += 3) {
if (__gxVerif->xfNrmDirty[i]) {
OSReport("\tXF_NRM_MTX[%d] = ", i);
OSReport("%f, %f, %f\n", *(f32*)&__gxVerif->xfMtx[i], *(f32*)&__gxVerif->xfMtx[i + 1], *(f32*)&__gxVerif->xfMtx[i + 2]);
}
}
OSReport("\n-------------------------------------\n");
OSReport("XF Light State:\n");
for (i = 0; i < 128; i += 16) {
if (__gxVerif->xfLightDirty[i]) {
OSReport("\tXF_LIGHT[%d]:\n", i >> 4);
for (j = 0; j < 4; j++) {
OSReport("\t\tparam[%d] = 0x%x\n", j, __gxVerif->xfLight[i + j]);
}
for (j = 4; j < 16; j++) {
OSReport("\t\tparam[%d] = %Lg\n", j, *(f32*)&__gxVerif->xfLight[i + j]);
}
}
}
OSReport("\n-------------------------------------\n");
OSReport("XF Register State:\n");
for (i = 0; i < 80; i++) {
if (__gxVerif->xfRegsDirty[i]) {
OSReport("\tXF_REG[0x%x] = 0x%x (%f)\n", i, __gxVerif->xfRegs[i], *(f32*)&__gxVerif->xfRegs[i]);
}
}
OSReport("\n-------------------------------------\n");
OSReport("Raster Registers State:\n");
for (i = 0; i < 256; i++) {
OSReport("\tRAS_REG[0x%x] = 0x%x\n", i, __gxVerif->rasRegs[i]);
}
OSReport("\n-------------------------------------\n");
}
#endif
+5
View File
@@ -0,0 +1,5 @@
#include <revolution/gx.h>
#include "__gx.h"
void __GXSetRange(f32 nearz, f32 fgSideX) {}
+465
View File
@@ -0,0 +1,465 @@
#include <revolution/gx.h>
#include <revolution/os.h>
#include "__gx.h"
static struct {
u32 rid : 8;
u32 dest : 2;
u32 shift : 2;
u32 clamp : 1;
u32 sub : 1;
u32 bias : 2;
u32 sela : 4;
u32 selb : 4;
u32 selc : 4;
u32 seld : 4;
} TEVCOpTableST0[5] = {
{192, 0, 0, 1, 0, 0, 15, 8, 10, 15}, // modulate
{192, 0, 0, 1, 0, 0, 10, 8, 9, 15}, // decal
{192, 0, 0, 1, 0, 0, 10, 12, 8, 15}, // blend
{192, 0, 0, 1, 0, 0, 15, 15, 15, 8}, // replace
{192, 0, 0, 1, 0, 0, 15, 15, 15, 10}, // passclr
};
static struct {
u32 rid : 8;
u32 dest : 2;
u32 shift : 2;
u32 clamp : 1;
u32 sub : 1;
u32 bias : 2;
u32 sela : 4;
u32 selb : 4;
u32 selc : 4;
u32 seld : 4;
} TEVCOpTableST1[5] = {
{192, 0, 0, 1, 0, 0, 15, 8, 0, 15}, // modulate
{192, 0, 0, 1, 0, 0, 0, 8, 9, 15}, // decal
{192, 0, 0, 1, 0, 0, 0, 12, 8, 15}, // blend
{192, 0, 0, 1, 0, 0, 15, 15, 15, 8}, // replace
{192, 0, 0, 1, 0, 0, 15, 15, 15, 0}, // passclr
};
static struct {
u32 rid : 8;
u32 dest : 2;
u32 shift : 2;
u32 clamp : 1;
u32 sub : 1;
u32 bias : 2;
u32 sela : 3;
u32 selb : 3;
u32 selc : 3;
u32 seld : 3;
u32 swap : 2;
u32 mode : 2;
} TEVAOpTableST0[5] = {
{193, 0, 0, 1, 0, 0, 7, 4, 5, 7, 0, 0}, // modulate
{193, 0, 0, 1, 0, 0, 7, 7, 7, 5, 0, 0}, // decal
{193, 0, 0, 1, 0, 0, 7, 4, 5, 7, 0, 0}, // blend
{193, 0, 0, 1, 0, 0, 7, 7, 7, 4, 0, 0}, // replace
{193, 0, 0, 1, 0, 0, 7, 7, 7, 5, 0, 0}, // passclr
};
static struct {
u32 rid : 8;
u32 dest : 2;
u32 shift : 2;
u32 clamp : 1;
u32 sub : 1;
u32 bias : 2;
u32 sela : 3;
u32 selb : 3;
u32 selc : 3;
u32 seld : 3;
u32 swap : 2;
u32 mode : 2;
} TEVAOpTableST1[5] = {
{193, 0, 0, 1, 0, 0, 7, 4, 0, 7, 0, 0}, // modulate
{193, 0, 0, 1, 0, 0, 7, 7, 7, 0, 0, 0}, // decal
{193, 0, 0, 1, 0, 0, 7, 4, 0, 7, 0, 0}, // blend
{193, 0, 0, 1, 0, 0, 7, 7, 7, 4, 0, 0}, // replace
{193, 0, 0, 1, 0, 0, 7, 7, 7, 0, 0, 0}, // passclr
};
void GXSetTevOp(GXTevStageID id, GXTevMode mode) {
u32* ctmp;
u32* atmp;
u32 tevReg;
CHECK_GXBEGIN(425, "GXSetTevOp");
ASSERTMSGLINE(426, id < GX_MAX_TEVSTAGE, "GXSetTevColor*: Invalid Tev Stage Index");
ASSERTMSGLINE(427, mode <= GX_PASSCLR, "GXSetTevOp: Invalid Tev Mode");
if (id == GX_TEVSTAGE0) {
ctmp = (u32*)TEVCOpTableST0 + mode;
atmp = (u32*)TEVAOpTableST0 + mode;
} else {
ctmp = (u32*)TEVCOpTableST1 + mode;
atmp = (u32*)TEVAOpTableST1 + mode;
}
tevReg = __GXData->tevc[id];
tevReg = (*ctmp & ~0xFF000000) | (tevReg & 0xFF000000);
GX_WRITE_RAS_REG(tevReg);
__GXData->tevc[id] = tevReg;
tevReg = __GXData->teva[id];
tevReg = (*atmp & ~0xFF00000F) | (tevReg & 0xFF00000F);
GX_WRITE_RAS_REG(tevReg);
__GXData->teva[id] = tevReg;
__GXData->bpSentNot = 0;
}
void GXSetTevColorIn(GXTevStageID stage, GXTevColorArg a, GXTevColorArg b, GXTevColorArg c, GXTevColorArg d) {
u32 tevReg;
CHECK_GXBEGIN(583, "GXSetTevColorIn");
ASSERTMSGLINE(584, stage < GX_MAX_TEVSTAGE, "GXSetTevColor*: Invalid Tev Stage Index");
ASSERTMSGLINE(585, a <= GX_CC_ZERO, "GXSetTev*In: A/B/C/D argument out of range");
ASSERTMSGLINE(586, b <= GX_CC_ZERO, "GXSetTev*In: A/B/C/D argument out of range");
ASSERTMSGLINE(587, c <= GX_CC_ZERO, "GXSetTev*In: A/B/C/D argument out of range");
ASSERTMSGLINE(588, d <= GX_CC_ZERO, "GXSetTev*In: A/B/C/D argument out of range");
tevReg = __GXData->tevc[stage];
SC_TEV_COLOR_ENV_SET_SELA(591, tevReg, a);
SC_TEV_COLOR_ENV_SET_SELB(592, tevReg, b);
SC_TEV_COLOR_ENV_SET_SELC(593, tevReg, c);
SC_TEV_COLOR_ENV_SET_SELD(594, tevReg, d);
GX_WRITE_RAS_REG(tevReg);
__GXData->tevc[stage] = tevReg;
__GXData->bpSentNot = 0;
}
void GXSetTevAlphaIn(GXTevStageID stage, GXTevAlphaArg a, GXTevAlphaArg b, GXTevAlphaArg c, GXTevAlphaArg d) {
u32 tevReg;
CHECK_GXBEGIN(619, "GXSetTevAlphaIn");
ASSERTMSGLINE(620, stage < GX_MAX_TEVSTAGE, "GXSetTevAlpha*: Invalid Tev Stage Index");
ASSERTMSGLINE(621, a <= GX_CA_ZERO, "GXSetTev*In: A/B/C/D argument out of range");
ASSERTMSGLINE(622, b <= GX_CA_ZERO, "GXSetTev*In: A/B/C/D argument out of range");
ASSERTMSGLINE(623, c <= GX_CA_ZERO, "GXSetTev*In: A/B/C/D argument out of range");
ASSERTMSGLINE(624, d <= GX_CA_ZERO, "GXSetTev*In: A/B/C/D argument out of range");
tevReg = __GXData->teva[stage];
SC_TEV_ALPHA_ENV_SET_SELA(627, tevReg, a);
SC_TEV_ALPHA_ENV_SET_SELB(628, tevReg, b);
SC_TEV_ALPHA_ENV_SET_SELC(629, tevReg, c);
SC_TEV_ALPHA_ENV_SET_SELD(630, tevReg, d);
GX_WRITE_RAS_REG(tevReg);
__GXData->teva[stage] = tevReg;
__GXData->bpSentNot = 0;
}
void GXSetTevColorOp(GXTevStageID stage, GXTevOp op, GXTevBias bias, GXTevScale scale, GXBool clamp, GXTevRegID out_reg) {
u32 tevReg;
CHECK_GXBEGIN(658, "GXSetTevColorOp");
ASSERTMSGLINE(659, stage < GX_MAX_TEVSTAGE, "GXSetTevColor*: Invalid Tev Stage Index");
tevReg = __GXData->tevc[stage];
SC_TEV_COLOR_ENV_SET_SUB(668, tevReg, op & 1);
if (op <= 1) {
SC_TEV_COLOR_ENV_SET_SHIFT(670, tevReg, scale);
SC_TEV_COLOR_ENV_SET_BIAS(671, tevReg, bias);
} else {
SC_TEV_COLOR_ENV_SET_SHIFT(673, tevReg, (op >> 1) & 3);
SC_TEV_COLOR_ENV_SET_BIAS(674, tevReg, 3);
}
SC_TEV_COLOR_ENV_SET_CLAMP(677, tevReg, clamp);
SC_TEV_COLOR_ENV_SET_DEST(678, tevReg, out_reg);
GX_WRITE_RAS_REG(tevReg);
__GXData->tevc[stage] = tevReg;
__GXData->bpSentNot = 0;
}
void GXSetTevAlphaOp(GXTevStageID stage, GXTevOp op, GXTevBias bias, GXTevScale scale, GXBool clamp, GXTevRegID out_reg) {
u32 tevReg;
CHECK_GXBEGIN(704, "GXSetTevAlphaOp");
ASSERTMSGLINE(705, stage < GX_MAX_TEVSTAGE, "GXSetTevAlpha*: Invalid Tev Stage Index");
tevReg = __GXData->teva[stage];
SC_TEV_ALPHA_ENV_SET_SUB(713, tevReg, op & 1);
if (op <= 1) {
SC_TEV_ALPHA_ENV_SET_SHIFT(715, tevReg, scale);
SC_TEV_ALPHA_ENV_SET_BIAS(716, tevReg, bias);
} else {
SC_TEV_ALPHA_ENV_SET_SHIFT(718, tevReg, (op >> 1) & 3);
SC_TEV_ALPHA_ENV_SET_BIAS(719, tevReg, 3);
}
SC_TEV_ALPHA_ENV_SET_CLAMP(722, tevReg, clamp);
SC_TEV_ALPHA_ENV_SET_DEST(723, tevReg, out_reg);
GX_WRITE_RAS_REG(tevReg);
__GXData->teva[stage] = tevReg;
__GXData->bpSentNot = 0;
}
void GXSetTevColor(GXTevRegID id, GXColor color) {
u32 rgba;
u32 regRA;
u32 regBG;
CHECK_GXBEGIN(745, "GXSetTevColor");
rgba = *(u32*)&color;
regRA = (0xE0 + id * 2) << 24;
SC_TEV_REGISTERL_SET_R8(750, regRA, rgba >> 24);
SC_TEV_REGISTERL_SET_A8(751, regRA, rgba & 0xFF);
regBG = (0xE1 + id * 2) << 24;
SC_TEV_REGISTERH_SET_B8(754, regBG, (rgba >> 8) & 0xFF);
SC_TEV_REGISTERH_SET_G8(755, regBG, (rgba >> 16) & 0xFF);
GX_WRITE_RAS_REG(regRA);
GX_WRITE_RAS_REG(regBG);
GX_WRITE_RAS_REG(regBG);
GX_WRITE_RAS_REG(regBG);
__GXData->bpSentNot = 0;
}
void GXSetTevColorS10(GXTevRegID id, GXColorS10 color) {
u32 sRG;
u32 sBA;
u32 regRA;
u32 regBG;
ASSERTMSGLINE(782, color.r >= -1024 && color.r < 1024, "GXSetTevColorS10: Color not in range -1024 to +1023");
ASSERTMSGLINE(783, color.g >= -1024 && color.g < 1024, "GXSetTevColorS10: Color not in range -1024 to +1023");
ASSERTMSGLINE(784, color.b >= -1024 && color.b < 1024, "GXSetTevColorS10: Color not in range -1024 to +1023");
ASSERTMSGLINE(785, color.a >= -1024 && color.a < 1024, "GXSetTevColorS10: Color not in range -1024 to +1023");
CHECK_GXBEGIN(787, "GXSetTevColorS10");
sRG = *(u32*)&color;
sBA = *((u32*)&color + 1);
regRA = (0xE0 + id * 2) << 24;
SC_TEV_REGISTERL_SET_R(794, regRA, (sRG >> 16) & 0x7FF);
SC_TEV_REGISTERL_SET_A(795, regRA, sBA & 0x7FF);
regBG = (0xE1 + id * 2) << 24;
SC_TEV_REGISTERH_SET_B(798, regBG, (sBA >> 16) & 0x7FF);
SC_TEV_REGISTERH_SET_G(799, regBG, sRG & 0x7FF);
GX_WRITE_RAS_REG(regRA);
GX_WRITE_RAS_REG(regBG);
GX_WRITE_RAS_REG(regBG);
GX_WRITE_RAS_REG(regBG);
__GXData->bpSentNot = 0;
}
void GXSetTevKColor(GXTevKColorID id, GXColor color) {
u32 rgba;
u32 regRA;
u32 regBG;
CHECK_GXBEGIN(838, "GXSetTevKColor");
rgba = *(u32*)&color;
regRA = (0xE0 + id * 2) << 24;
SC_TEV_KREGISTERL_SET_R(843, regRA, rgba >> 24);
SC_TEV_KREGISTERL_SET_A(844, regRA, rgba & 0xFF);
SC_TEV_KREGISTERL_SET_PAD1(845, regRA, 8);
regBG = (0xE1 + id * 2) << 24;
SC_TEV_KREGISTERH_SET_B(848, regBG, (rgba >> 8) & 0xFF);
SC_TEV_KREGISTERH_SET_G(849, regBG, (rgba >> 16) & 0xFF);
SC_TEV_KREGISTERH_SET_PAD1(850, regBG, 8);
GX_WRITE_RAS_REG(regRA);
GX_WRITE_RAS_REG(regBG);
__GXData->bpSentNot = 0;
}
void GXSetTevKColorSel(GXTevStageID stage, GXTevKColorSel sel) {
u32* Kreg;
CHECK_GXBEGIN(877, "GXSetTevKColorSel");
ASSERTMSGLINE(878, stage < GX_MAX_TEVSTAGE, "GXSetTevKColor*: Invalid Tev Stage Index");
Kreg = &__GXData->tevKsel[stage >> 1];
if (stage & 1) {
SC_TEV_KSEL_SET_KCSEL1(883, *Kreg, sel);
} else {
SC_TEV_KSEL_SET_KCSEL0(885, *Kreg, sel);
}
GX_WRITE_RAS_REG(*Kreg);
__GXData->bpSentNot = 0;
}
void GXSetTevKAlphaSel(GXTevStageID stage, GXTevKAlphaSel sel) {
u32* Kreg;
CHECK_GXBEGIN(910, "GXSetTevKAlphaSel");
ASSERTMSGLINE(911, stage < GX_MAX_TEVSTAGE, "GXSetTevKColor*: Invalid Tev Stage Index");
Kreg = &__GXData->tevKsel[stage >> 1];
if (stage & 1) {
SC_TEV_KSEL_SET_KASEL1(916, *Kreg, sel);
} else {
SC_TEV_KSEL_SET_KASEL0(918, *Kreg, sel);
}
GX_WRITE_RAS_REG(*Kreg);
__GXData->bpSentNot = 0;
}
void GXSetTevSwapMode(GXTevStageID stage, GXTevSwapSel ras_sel, GXTevSwapSel tex_sel) {
u32* pTevReg;
CHECK_GXBEGIN(947, "GXSetTevSwapMode");
ASSERTMSGLINE(948, stage < GX_MAX_TEVSTAGE, "GXSetTevSwapMode: Invalid Tev Stage Index");
pTevReg = &__GXData->teva[stage];
SC_TEV_ALPHA_ENV_SET_MODE(951, *pTevReg, ras_sel);
SC_TEV_ALPHA_ENV_SET_SWAP(952, *pTevReg, tex_sel);
GX_WRITE_RAS_REG(*pTevReg);
__GXData->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(983, "GXSetTevSwapModeTable");
ASSERTMSGLINE(984, table < GX_MAX_TEVSWAP, "GXSetTevSwapModeTable: Invalid Swap Selection Index");
#if DEBUG
Kreg = &__GXData->tevKsel[table * 2];
#else
Kreg = &__GXData->tevKsel[index];
#endif
SC_TEV_KSEL_SET_XRB(987, *Kreg, red);
SC_TEV_KSEL_SET_XGA(988, *Kreg, green);
GX_WRITE_RAS_REG(*Kreg);
Kreg = &__GXData->tevKsel[table * 2 + 1];
SC_TEV_KSEL_SET_XRB(992, *Kreg, blue);
SC_TEV_KSEL_SET_XGA(993, *Kreg, alpha);
GX_WRITE_RAS_REG(*Kreg);
__GXData->bpSentNot = 0;
}
void GXSetTevClampMode(void) {
ASSERTMSGLINE(1012, 0, "GXSetTevClampMode: not available on this hardware");
}
void GXSetAlphaCompare(GXCompare comp0, u8 ref0, GXAlphaOp op, GXCompare comp1, u8 ref1) {
u32 reg;
CHECK_GXBEGIN(1051, "GXSetAlphaCompare");
reg = 0xF3000000;
SC_TEV_ALPHAFUNC_SET_A0(1054, reg, ref0);
SC_TEV_ALPHAFUNC_SET_A1(1055, reg, ref1);
SC_TEV_ALPHAFUNC_SET_OP0(1056, reg, comp0);
SC_TEV_ALPHAFUNC_SET_OP1(1057, reg, comp1);
SC_TEV_ALPHAFUNC_SET_LOGIC(1058, reg, op);
GX_WRITE_RAS_REG(reg);
__GXData->bpSentNot = 0;
}
void GXSetZTexture(GXZTexOp op, GXTexFmt fmt, u32 bias) {
u32 zenv0;
u32 zenv1;
u32 type;
CHECK_GXBEGIN(1082, "GXSetZTexture");
zenv0 = 0;
SC_TEV_Z_ENV_0_SET_ZOFF(1085, zenv0, bias);
SC_TEV_Z_ENV_0_SET_RID(1086, zenv0, 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(1094, 0, "GXSetZTexture: Invalid z-texture format");
type = 2;
break;
}
SC_TEV_Z_ENV_1_SET_TYPE(1097, zenv1, type);
SC_TEV_Z_ENV_1_SET_OP(1098, zenv1, op);
SC_TEV_Z_ENV_1_SET_RID(1099, zenv1, 0xF5);
GX_WRITE_RAS_REG(zenv0);
GX_WRITE_RAS_REG(zenv1);
__GXData->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(1136, "GXSetTevOrder");
ASSERTMSGLINE(1137, stage < GX_MAX_TEVSTAGE, "GXSetTevOrder: Invalid Tev Stage Index");
ASSERTMSGLINE(1139, coord < GX_MAX_TEXCOORD || coord == GX_TEXCOORD_NULL, "GXSetTevOrder: Invalid Texcoord");
ASSERTMSGLINE(1141, (map & ~GX_TEX_DISABLE) < GX_MAX_TEXMAP || map == GX_TEXMAP_NULL, "GXSetTevOrder: Invalid Tex Map");
ASSERTMSGLINE(1143, color >= GX_COLOR0A0 && color <= GX_COLOR_NULL, "GXSetTevOrder: Invalid Color Channel ID");
ptref = &__GXData->tref[stage / 2];
__GXData->texmapId[stage] = map;
tmap = map & ~GX_TEX_DISABLE;
tmap = (tmap >= GX_MAX_TEXMAP) ? GX_TEXMAP0 : tmap;
if (coord >= GX_MAX_TEXCOORD) {
tcoord = GX_TEXCOORD0;
__GXData->tevTcEnab = __GXData->tevTcEnab & ~(1 << stage);
} else {
tcoord = coord;
__GXData->tevTcEnab = __GXData->tevTcEnab | (1 << stage);
}
if (stage & 1) {
SC_RAS1_TREF_SET_TI1(1163, *ptref, tmap);
SC_RAS1_TREF_SET_TC1(1164, *ptref, tcoord);
SC_RAS1_TREF_SET_CC1(1166, *ptref, (color == GX_COLOR_NULL) ? 7 : c2r[color]);
SC_RAS1_TREF_SET_TE1(1168, *ptref, (map != GX_TEXMAP_NULL && !(map & GX_TEX_DISABLE)));
} else {
SC_RAS1_TREF_SET_TI0(1171, *ptref, tmap);
SC_RAS1_TREF_SET_TC0(1172, *ptref, tcoord);
SC_RAS1_TREF_SET_CC0(1174, *ptref, (color == GX_COLOR_NULL) ? 7 : c2r[color]);
SC_RAS1_TREF_SET_TE0(1176, *ptref, (map != GX_TEXMAP_NULL && !(map & GX_TEX_DISABLE)));
}
GX_WRITE_RAS_REG(*ptref);
__GXData->bpSentNot = 0;
__GXData->dirtyState |= 1;
}
void GXSetNumTevStages(u8 nStages) {
CHECK_GXBEGIN(1192, "GXSetNumTevStages");
ASSERTMSGLINE(1194, nStages != 0 && nStages <= 16, "GXSetNumTevStages: Exceed max number of tex stages");
SC_GEN_MODE_SET_NTEV(1195, __GXData->genMode, nStages - 1);
__GXData->dirtyState |= 4;
}
File diff suppressed because it is too large Load Diff
+607
View File
@@ -0,0 +1,607 @@
#include <revolution/gx.h>
#include <revolution/mtx.h>
#include <revolution/os.h>
#include "__gx.h"
void GXProject(f32 x, f32 y, f32 z, const Mtx mtx, const f32* pm, const f32* vp, f32* sx, f32* sy, f32* sz) {
Vec peye;
f32 xc;
f32 yc;
f32 zc;
f32 wc;
ASSERTMSGLINE(181, 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;
#ifdef __MWERKS__
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
}
#endif
}
static void Copy6Floats(const __REGISTER f32 src[6], __REGISTER volatile f32* dest) {
__REGISTER f32 ps01, ps23, ps45;
asm {
psq_l ps01, 0(src), 0, 0
psq_l ps23, 8(src), 0, 0
psq_l ps45, 16(src), 0, 0
psq_st ps01, 0(dest), 0, 0
psq_st ps23, 8(dest), 0, 0
psq_st ps45, 16(dest), 0, 0
}
}
void __GXSetProjection(void) {
u32 reg = 0x00061020;
GX_WRITE_U8(0x10);
GX_WRITE_U32(reg);
#if DEBUG
GX_WRITE_XF_REG_F(32, __GXData->projMtx[0]);
GX_WRITE_XF_REG_F(33, __GXData->projMtx[1]);
GX_WRITE_XF_REG_F(34, __GXData->projMtx[2]);
GX_WRITE_XF_REG_F(35, __GXData->projMtx[3]);
GX_WRITE_XF_REG_F(36, __GXData->projMtx[4]);
GX_WRITE_XF_REG_F(37, __GXData->projMtx[5]);
GX_WRITE_XF_REG_2(38, __GXData->projType);
#else
WriteProjPS(__GXData->projMtx, (volatile void*)GXFIFO_ADDR);
GX_WRITE_U32(__GXData->projType);
#endif
}
void GXSetProjection(const Mtx44 mtx, GXProjectionType type) {
CHECK_GXBEGIN(307, "GXSetProjection");
__GXData->projType = type;
__GXData->projMtx[0] = mtx[0][0];
__GXData->projMtx[2] = mtx[1][1];
__GXData->projMtx[4] = mtx[2][2];
__GXData->projMtx[5] = mtx[2][3];
if (type == GX_ORTHOGRAPHIC) {
__GXData->projMtx[1] = mtx[0][3];
__GXData->projMtx[3] = mtx[1][3];
} else {
__GXData->projMtx[1] = mtx[0][2];
__GXData->projMtx[3] = mtx[1][2];
}
__GXData->dirtyState |= 0x8000000;
}
void GXSetProjectionv(const f32* ptr) {
CHECK_GXBEGIN(351, "GXSetProjectionv");
__GXData->projType = ptr[0] == 0.0f ? GX_PERSPECTIVE : GX_ORTHOGRAPHIC;
#if DEBUG
__GXData->projMtx[0] = ptr[1];
__GXData->projMtx[1] = ptr[2];
__GXData->projMtx[2] = ptr[3];
__GXData->projMtx[3] = ptr[4];
__GXData->projMtx[4] = ptr[5];
__GXData->projMtx[5] = ptr[6];
#else
Copy6Floats(&ptr[1], __GXData->projMtx);
#endif
__GXData->dirtyState |= 0x8000000;
}
#define qr0 0
void GXGetProjectionv(f32* ptr) {
ASSERTMSGLINE(382, ptr, "GXGet*: invalid null pointer");
ptr[0] = (u32)__GXData->projType != GX_PERSPECTIVE ? 1.0f : 0.0f;
#if DEBUG
ptr[1] = __GXData->projMtx[0];
ptr[2] = __GXData->projMtx[1];
ptr[3] = __GXData->projMtx[2];
ptr[4] = __GXData->projMtx[3];
ptr[5] = __GXData->projMtx[4];
ptr[6] = __GXData->projMtx[5];
#else
Copy6Floats(__GXData->projMtx, &ptr[1]);
#endif
}
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 WriteMTXPS3x3(__REGISTER f32 mtx[3][3], __REGISTER volatile f32* dest) {
__REGISTER f32 a00_a01;
__REGISTER f32 a02_a10;
__REGISTER f32 a11_a12;
__REGISTER f32 a20_a21;
__REGISTER f32 a22_nnn;
asm {
psq_l a00_a01, 0x00(mtx), 0, qr0
psq_l a02_a10, 0x08(mtx), 0, qr0
psq_l a11_a12, 0x10(mtx), 0, qr0
psq_l a20_a21, 0x18(mtx), 0, qr0
lfs a22_nnn, 0x20(mtx)
psq_st a00_a01, 0(dest), 0, qr0
psq_st a02_a10, 0(dest), 0, qr0
psq_st a11_a12, 0(dest), 0, qr0
psq_st a20_a21, 0(dest), 0, qr0
stfs a22_nnn, 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
}
}
#define GX_WRITE_MTX_ELEM(addr, value) \
do { \
f32 xfData = (value); \
GX_WRITE_F32(value); \
VERIF_MTXLIGHT((addr), *(u32 *)&xfData); \
} while (0)
void GXLoadPosMtxImm(const Mtx mtx, u32 id) {
u32 reg;
u32 addr;
CHECK_GXBEGIN(516, "GXLoadPosMtxImm");
addr = id * 4;
reg = addr | 0xB0000;
GX_WRITE_U8(0x10);
GX_WRITE_U32(reg);
#if DEBUG
GX_WRITE_MTX_ELEM(addr + 0, mtx[0][0]);
GX_WRITE_MTX_ELEM(addr + 1, mtx[0][1]);
GX_WRITE_MTX_ELEM(addr + 2, mtx[0][2]);
GX_WRITE_MTX_ELEM(addr + 3, mtx[0][3]);
GX_WRITE_MTX_ELEM(addr + 4, mtx[1][0]);
GX_WRITE_MTX_ELEM(addr + 5, mtx[1][1]);
GX_WRITE_MTX_ELEM(addr + 6, mtx[1][2]);
GX_WRITE_MTX_ELEM(addr + 7, mtx[1][3]);
GX_WRITE_MTX_ELEM(addr + 8, mtx[2][0]);
GX_WRITE_MTX_ELEM(addr + 9, mtx[2][1]);
GX_WRITE_MTX_ELEM(addr + 10, mtx[2][2]);
GX_WRITE_MTX_ELEM(addr + 11, mtx[2][3]);
#else
WriteMTXPS4x3(mtx, &GXWGFifo.f32);
#endif
}
void GXLoadPosMtxIndx(u16 mtx_indx, u32 id) {
u32 offset;
u32 reg;
CHECK_GXBEGIN(555, "GXLoadPosMtxIndx");
offset = id * 4;
reg = 0;
SET_REG_FIELD(561, reg, 12, 0, offset);
SET_REG_FIELD(563, reg, 4, 12, 11);
SET_REG_FIELD(563, reg, 16, 16, mtx_indx);
GX_WRITE_U8(0x20);
GX_WRITE_U32(reg);
#if DEBUG
__GXShadowIndexState(4, reg);
#endif
}
void GXLoadNrmMtxImm(const Mtx mtx, u32 id) {
u32 reg;
u32 addr;
CHECK_GXBEGIN(597, "GXLoadNrmMtxImm");
addr = id * 3 + 0x400;
reg = addr | 0x80000;
GX_WRITE_U8(0x10);
GX_WRITE_U32(reg);
#if DEBUG
GX_WRITE_MTX_ELEM(addr + 0, mtx[0][0]);
GX_WRITE_MTX_ELEM(addr + 1, mtx[0][1]);
GX_WRITE_MTX_ELEM(addr + 2, mtx[0][2]);
GX_WRITE_MTX_ELEM(addr + 3, mtx[1][0]);
GX_WRITE_MTX_ELEM(addr + 4, mtx[1][1]);
GX_WRITE_MTX_ELEM(addr + 5, mtx[1][2]);
GX_WRITE_MTX_ELEM(addr + 6, mtx[2][0]);
GX_WRITE_MTX_ELEM(addr + 7, mtx[2][1]);
GX_WRITE_MTX_ELEM(addr + 8, mtx[2][2]);
#else
WriteMTXPS3x3from3x4((void*)mtx, &GXWGFifo.f32);
#endif
}
void GXLoadNrmMtxImm3x3(const f32 mtx[3][3], u32 id) {
u32 reg;
u32 addr;
CHECK_GXBEGIN(633, "GXLoadNrmMtxImm3x3");
addr = id * 3 + 0x400;
reg = addr | 0x80000;
GX_WRITE_U8(0x10);
GX_WRITE_U32(reg);
#if DEBUG
GX_WRITE_MTX_ELEM(addr + 0, mtx[0][0]);
GX_WRITE_MTX_ELEM(addr + 1, mtx[0][1]);
GX_WRITE_MTX_ELEM(addr + 2, mtx[0][2]);
GX_WRITE_MTX_ELEM(addr + 3, mtx[1][0]);
GX_WRITE_MTX_ELEM(addr + 4, mtx[1][1]);
GX_WRITE_MTX_ELEM(addr + 5, mtx[1][2]);
GX_WRITE_MTX_ELEM(addr + 6, mtx[2][0]);
GX_WRITE_MTX_ELEM(addr + 7, mtx[2][1]);
GX_WRITE_MTX_ELEM(addr + 8, mtx[2][2]);
#else
WriteMTXPS3x3((void*)mtx, &GXWGFifo.f32);
#endif
}
void GXLoadNrmMtxIndx3x3(u16 mtx_indx, u32 id) {
u32 offset;
u32 reg;
CHECK_GXBEGIN(679, "GXLoadNrmMtxIndx3x3");
offset = id * 3 + 0x400;
reg = 0;
SET_REG_FIELD(685, reg, 12, 0, offset);
SET_REG_FIELD(687, reg, 4, 12, 8);
SET_REG_FIELD(687, reg, 16, 16, mtx_indx);
GX_WRITE_U8(0x28);
GX_WRITE_U32(reg);
#if DEBUG
__GXShadowIndexState(5, reg);
#endif
}
void GXSetCurrentMtx(u32 id) {
CHECK_GXBEGIN(717, "GXSetCurrentMtx");
SET_REG_FIELD(721, __GXData->matIdxA, 6, 0, id);
__GXData->dirtyState |= 0x4000000;
}
void GXLoadTexMtxImm(const f32 mtx[][4], u32 id, GXTexMtxType type) {
u32 reg;
u32 addr;
u32 count;
CHECK_GXBEGIN(750, "GXLoadTexMtxImm");
if (id >= GX_PTTEXMTX0) {
addr = (id - GX_PTTEXMTX0) * 4 + 0x500;
ASSERTMSGLINE(760, 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 DEBUG
GX_WRITE_MTX_ELEM(addr + 0, mtx[0][0]);
GX_WRITE_MTX_ELEM(addr + 1, mtx[0][1]);
GX_WRITE_MTX_ELEM(addr + 2, mtx[0][2]);
GX_WRITE_MTX_ELEM(addr + 3, mtx[0][3]);
GX_WRITE_MTX_ELEM(addr + 4, mtx[1][0]);
GX_WRITE_MTX_ELEM(addr + 5, mtx[1][1]);
GX_WRITE_MTX_ELEM(addr + 6, mtx[1][2]);
GX_WRITE_MTX_ELEM(addr + 7, mtx[1][3]);
if (type == GX_MTX3x4) {
GX_WRITE_MTX_ELEM(addr + 8, mtx[2][0]);
GX_WRITE_MTX_ELEM(addr + 9, mtx[2][1]);
GX_WRITE_MTX_ELEM(addr + 10, mtx[2][2]);
GX_WRITE_MTX_ELEM(addr + 11, mtx[2][3]);
}
#else
if (type == GX_MTX3x4) {
WriteMTXPS4x3(mtx, &GXWGFifo.f32);
} else {
WriteMTXPS4x2(mtx, &GXWGFifo.f32);
}
#endif
}
void GXLoadTexMtxIndx(u16 mtx_indx, u32 id, GXTexMtxType type) {
u32 offset;
u32 reg;
u32 count;
CHECK_GXBEGIN(813, "GXLoadTexMtxIndx");
if (id >= GX_PTTEXMTX0) {
offset = (id - GX_PTTEXMTX0) * 4 + 0x500;
ASSERTMSGLINE(0x337, type == GX_MTX3x4, "GXLoadTexMtx: Invalid matrix type");
} else {
offset = id * 4;
}
count = (type == GX_MTX2x4) ? 8 : 12;
reg = 0;
SET_REG_FIELD(830, reg, 12, 0, offset);
SET_REG_FIELD(831, reg, 4, 12, (count - 1));
SET_REG_FIELD(832, reg, 16, 16, mtx_indx);
GX_WRITE_U8(0x30);
GX_WRITE_U32(reg);
#if DEBUG
__GXShadowIndexState(6, reg);
#endif
}
void __GXSetViewport(void) {
f32 sx;
f32 sy;
f32 sz;
f32 ox;
f32 oy;
f32 oz;
f32 zmin;
f32 zmax;
u32 reg;
sx = __GXData->vpWd / 2.0f;
sy = -__GXData->vpHt / 2.0f;
ox = 342.0f + (__GXData->vpLeft + (__GXData->vpWd / 2.0f));
oy = 342.0f + (__GXData->vpTop + (__GXData->vpHt / 2.0f));
zmin = __GXData->vpNearz * __GXData->zScale;
zmax = __GXData->vpFarz * __GXData->zScale;
sz = zmax - zmin;
oz = zmax + __GXData->zOffset;
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);
}
void GXSetViewportJitter(f32 left, f32 top, f32 wd, f32 ht, f32 nearz, f32 farz, u32 field) {
CHECK_GXBEGIN(912, "GXSetViewport"); // not the correct function name
if (field == 0) {
top -= 0.5f;
}
__GXData->vpLeft = left;
__GXData->vpTop = top;
__GXData->vpWd = wd;
__GXData->vpHt = ht;
__GXData->vpNearz = nearz;
__GXData->vpFarz = farz;
__GXData->dirtyState |= 0x10000000;
}
void GXSetViewport(f32 left, f32 top, f32 wd, f32 ht, f32 nearz, f32 farz) {
GXSetViewportJitter(left, top, wd, ht, nearz, farz, 1);
}
void GXGetViewportv(f32* vp) {
ASSERTMSGLINE(977, vp, "GXGet*: invalid null pointer");
#if DEBUG
vp[0] = __GXData->vpLeft;
vp[1] = __GXData->vpTop;
vp[2] = __GXData->vpWd;
vp[3] = __GXData->vpHt;
vp[4] = __GXData->vpNearz;
vp[5] = __GXData->vpFarz;
#else
Copy6Floats(&__GXData->vpLeft, vp);
#endif
}
#define GX_WRITE_XF_REG_F_(addr, value) \
do { \
GX_WRITE_U8(0x10); \
GX_WRITE_U32(0x1000 + (addr)); \
{ \
f32 xfData = (value); \
GX_WRITE_F32(value); \
VERIF_XF_REG_alt(addr, *(u32 *)&xfData); \
} \
} while (0)
void GXSetZScaleOffset(f32 scale, f32 offset) {
f32 sz;
f32 oz;
f32 zmin;
f32 zmax;
CHECK_GXBEGIN(996, "GXSetZScaleOffset");
oz = offset * 1.6777215e7f;
__GXData->zOffset = oz;
sz = (scale * 1.6777215e7f) + 1.0f;
__GXData->zScale = sz;
zmin = __GXData->vpNearz * sz;
zmax = __GXData->vpFarz * sz;
sz = zmax - zmin;
oz = oz + zmax;
GX_WRITE_XF_REG_F_(0x1C, sz);
GX_WRITE_XF_REG_F_(0x1F, oz);
__GXData->bpSentNot = 1;
}
void GXSetScissor(u32 left, u32 top, u32 wd, u32 ht) {
u32 tp;
u32 lf;
u32 bm;
u32 rt;
CHECK_GXBEGIN(1057, "GXSetScissor");
ASSERTMSGLINE(1058, left < 1706, "GXSetScissor: Left origin > 1708");
ASSERTMSGLINE(1059, top < 1706, "GXSetScissor: top origin > 1708");
ASSERTMSGLINE(1060, left + wd < 1706, "GXSetScissor: right edge > 1708");
ASSERTMSGLINE(1061, top + ht < 1706, "GXSetScissor: bottom edge > 1708");
tp = top + 342;
lf = left + 342;
bm = tp + ht - 1;
rt = lf + wd - 1;
SET_REG_FIELD(1068, __GXData->suScis0, 11, 0, tp);
SET_REG_FIELD(1069, __GXData->suScis0, 11, 12, lf);
SET_REG_FIELD(1071, __GXData->suScis1, 11, 0, bm);
SET_REG_FIELD(1072, __GXData->suScis1, 11, 12, rt);
GX_WRITE_RAS_REG(__GXData->suScis0);
GX_WRITE_RAS_REG(__GXData->suScis1);
__GXData->bpSentNot = 0;
}
void GXGetScissor(u32* left, u32* top, u32* wd, u32* ht) {
u32 tp;
u32 lf;
u32 bm;
u32 rt;
ASSERTMSGLINE(1098, left && top && wd && ht, "GXGet*: invalid null pointer");
tp = __GXData->suScis0 & 0x7FF;
lf = (__GXData->suScis0 & 0x7FF000) >> 12;
bm = __GXData->suScis1 & 0x7FF;
rt = (__GXData->suScis1 & 0x7FF000) >> 12;
*left = lf - 342;
*top = tp - 342;
*wd = rt - lf + 1;
*ht = bm - tp + 1;
}
void GXSetScissorBoxOffset(s32 x_off, s32 y_off) {
u32 reg = 0;
u32 hx;
u32 hy;
CHECK_GXBEGIN(1128, "GXSetScissorBoxOffset");
ASSERTMSGLINE(1131, !!((u32)(x_off + 342) < 2048), "GXSetScissorBoxOffset: Invalid X offset");
ASSERTMSGLINE(1133, !!((u32)(y_off + 342) < 2048), "GXSetScissorBoxOffset: Invalid Y offset");
hx = (u32)(x_off + 342) >> 1;
hy = (u32)(y_off + 342) >> 1;
SET_REG_FIELD(1138, reg, 10, 0, hx);
SET_REG_FIELD(1139, reg, 10, 10, hy);
SET_REG_FIELD(1131, reg, 8, 24, 0x59);
GX_WRITE_RAS_REG(reg);
__GXData->bpSentNot = 0;
}
void GXSetClipMode(GXClipMode mode) {
CHECK_GXBEGIN(1160, "GXSetClipMode");
GX_WRITE_XF_REG(0x1005, mode, 0);
__GXData->bpSentNot = 1;
}
void __GXSetMatrixIndex(GXAttr matIdxAttr) {
if (matIdxAttr < GX_VA_TEX4MTXIDX) {
GX_WRITE_SOME_REG4(8, 0x30, __GXData->matIdxA, -12);
GX_WRITE_XF_REG(0x1018, __GXData->matIdxA, 0);
} else {
GX_WRITE_SOME_REG4(8, 0x40, __GXData->matIdxB, -12);
GX_WRITE_XF_REG(0x1019, __GXData->matIdxB, 0);
}
__GXData->bpSentNot = 1;
}
+628
View File
@@ -0,0 +1,628 @@
#if DEBUG
#include <stdio.h>
#include <revolution/gx.h>
#include "__gx.h"
static char __data_0[] = "RGB multisample";
static char _305[] = "GX_TEVPREV(color)";
static char _306[] = "GX_TEVPREV(alpha)";
static char _307[] = "GX_TEVREG0(color)";
static char _308[] = "GX_TEVREG0(alpha)";
static char _309[] = "GX_TEVREG1(color)";
static char _310[] = "GX_TEVREG1(alpha)";
static char _311[] = "GX_TEVREG2(color)";
static char _312[] = "GX_TEVREG2(alpha)";
static char* TevRegNames[8] = {0};
#define SOME_GET_REG_MACRO(reg, size, shift) ((u32)((reg) << (shift)) & ((1 << (size)) - 2))
#define SOME_GET_REG_MACRO2(reg, size, shift) ((u32)((reg) >> (shift)) & ((1 << (size)) - 2))
void __GXVerifySU(void) {
s32 scis_l;
s32 scis_r;
s32 scis_t;
s32 scis_b;
scis_l = (u32)GET_REG_FIELD(__gxVerif->rasRegs[32], 11, 12);
scis_t = (u32)GET_REG_FIELD(__gxVerif->rasRegs[32], 11, 0);
scis_r = (u32)GET_REG_FIELD(__gxVerif->rasRegs[33], 11, 12);
scis_b = (u32)GET_REG_FIELD(__gxVerif->rasRegs[33], 11, 0);
scis_l = scis_l - (u32)SOME_GET_REG_MACRO(__gxVerif->rasRegs[89], 11, 1);
scis_r = scis_r - (u32)SOME_GET_REG_MACRO(__gxVerif->rasRegs[89], 11, 1);
scis_t = scis_t - (u32)SOME_GET_REG_MACRO2(__gxVerif->rasRegs[89], 11, 9);
scis_b = scis_b - (u32)SOME_GET_REG_MACRO2(__gxVerif->rasRegs[89], 11, 9);
if (scis_l < 0 && __gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_SCISSOR_RECT_LEFT]) {
__GX_WARNF(GXWARN_SCISSOR_RECT_LEFT, 0);
}
if (scis_t < 0 && __gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_SCISSOR_RECT_TOP]) {
__GX_WARNF(GXWARN_SCISSOR_RECT_TOP, 0);
}
switch (__gxVerif->rasRegs[67] & 7) {
case 4:
case 5:
if (scis_r > 719 && __gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_SCISSOR_RECT_RIGHT]) {
__GX_WARNF(GXWARN_SCISSOR_RECT_RIGHT, 719, "YUV");
}
if (scis_b > 575 && __gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_SCISSOR_RECT_BOT]) {
__GX_WARNF(GXWARN_SCISSOR_RECT_BOT, 575, "YUV");
}
break;
case 0:
case 1:
case 3:
if (scis_r > 639 && __gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_SCISSOR_RECT_RIGHT]) {
__GX_WARNF(GXWARN_SCISSOR_RECT_RIGHT, 639, "RGB");
}
if (scis_b > 527 && __gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_SCISSOR_RECT_BOT]) {
__GX_WARNF(GXWARN_SCISSOR_RECT_BOT, 527, "RGB");
}
break;
case 2:
if (scis_r > 639 && __gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_SCISSOR_RECT_RIGHT]) {
__GX_WARNF(GXWARN_SCISSOR_RECT_RIGHT, 639, __data_0);
}
if (scis_b > 263 && __gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_SCISSOR_RECT_BOT]) {
__GX_WARNF(GXWARN_SCISSOR_RECT_BOT, 263, __data_0);
}
break;
}
}
void __GXVerifyBUMP(void) {
u32 i;
u32 nBmp;
u32 nTev;
u32 nTex;
u32 matrix;
nBmp = GET_REG_FIELD(__gxVerif->rasRegs[0], 3, 16);
nTex = GET_REG_FIELD(__gxVerif->rasRegs[0], 4, 0);
nTev = GET_REG_FIELD(__gxVerif->rasRegs[0], 4, 10) + 1;
for (i = 0; i < nTev; i++) {
matrix = GET_REG_FIELD(__gxVerif->rasRegs[16 + i], 4, 9);
if (__gxVerif->verifyLevel >= GX_WARN_SEVERE) {
if ((u32)(__gxVerif->rasRegs[16 + i] & 0xFF000000) + 0x01000000 == 0U && __gxVerif->verifyLevel >= __gxvWarnLev[7]) {
sprintf(__gxvDummyStr, __gxvWarnings[7], i);
__gxVerif->cb(__gxvWarnLev[7], 7U, __gxvDummyStr);
}
if ((GET_REG_FIELD(__gxVerif->rasRegs[16 + i], 2, 7) != 0 || matrix != 0)
&& GET_REG_FIELD(__gxVerif->rasRegs[16 + i], 2, 0) >= nBmp && __gxVerif->verifyLevel >= __gxvWarnLev[8]) {
sprintf(__gxvDummyStr, __gxvWarnings[8], i);
__gxVerif->cb(__gxvWarnLev[8], 8U, __gxvDummyStr);
}
if (matrix != 0) {
matrix = (matrix & 3) - 1;
if (((u32)(__gxVerif->rasRegs[(matrix * 3) + 6] & 0xFF000000) + 0x01000000 == 0
|| (u32)(__gxVerif->rasRegs[(matrix * 3) + 7] & 0xFF000000) + 0x01000000 == 0U
|| (u32)(__gxVerif->rasRegs[(matrix * 3) + 8] & 0xFF000000) + 0x01000000 == 0U) && __gxVerif->verifyLevel >= __gxvWarnLev[9]) {
sprintf(__gxvDummyStr, __gxvWarnings[9], matrix, i);
__gxVerif->cb(__gxvWarnLev[9], 9U, __gxvDummyStr);
}
}
}
}
if (__gxVerif->verifyLevel >= GX_WARN_SEVERE) {
if (nBmp != 0 && (u32)(__gxVerif->rasRegs[0x27] & 0xFF000000) + 0x01000000 == 0 && __gxVerif->verifyLevel >= __gxvWarnLev[10]) {
__gxVerif->cb(__gxvWarnLev[10], 0xAU, __gxvWarnings[10]);
}
if (nBmp != 0 && (u32)(__gxVerif->rasRegs[0x25] & 0xFF000000) + 0x01000000 == 0 && __gxVerif->verifyLevel >= __gxvWarnLev[11]) {
sprintf(__gxvDummyStr, __gxvWarnings[11], 0U, 1);
__gxVerif->cb(__gxvWarnLev[11], 0xBU, __gxvDummyStr);
}
if (nBmp > 2U && (u32)(__gxVerif->rasRegs[0x26] & 0xFF000000) + 0x01000000 == 0 && __gxVerif->verifyLevel >= __gxvWarnLev[11]) {
sprintf(__gxvDummyStr, __gxvWarnings[11], 2U, 3);
__gxVerif->cb(__gxvWarnLev[11], 0xBU, __gxvDummyStr);
}
if (nBmp != 0 && GET_REG_FIELD(__gxVerif->rasRegs[0x27], 3, 3) >= nTex && __gxVerif->verifyLevel >= __gxvWarnLev[12]) {
sprintf(__gxvDummyStr, __gxvWarnings[12], 0U);
__gxVerif->cb(__gxvWarnLev[12], 0xCU, __gxvDummyStr);
}
if (nBmp > 1U && GET_REG_FIELD(__gxVerif->rasRegs[0x27], 3, 9) >= nTex && __gxVerif->verifyLevel >= __gxvWarnLev[12]) {
sprintf(__gxvDummyStr, __gxvWarnings[12], 1U);
__gxVerif->cb(__gxvWarnLev[12], 0xCU, __gxvDummyStr);
}
if (nBmp > 2U && GET_REG_FIELD(__gxVerif->rasRegs[0x27], 3, 15) >= nTex && __gxVerif->verifyLevel >= __gxvWarnLev[12]) {
sprintf(__gxvDummyStr, __gxvWarnings[12], 2U);
__gxVerif->cb(__gxvWarnLev[12], 0xCU, __gxvDummyStr);
}
if (nBmp > 3U && GET_REG_FIELD(__gxVerif->rasRegs[0x27], 3, 21) >= nTex && __gxVerif->verifyLevel >= __gxvWarnLev[12]) {
sprintf(__gxvDummyStr, __gxvWarnings[12], 3U);
__gxVerif->cb(__gxvWarnLev[12], 0xCU, __gxvDummyStr);
}
if (nBmp != 0 && GET_REG_FIELD(__gxVerif->rasRegs[0x10], 1, 20) && __gxVerif->verifyLevel >= __gxvWarnLev[13]) {
__gxVerif->cb(__gxvWarnLev[13], 0xDU, __gxvWarnings[13]);
}
if (nBmp != 0 && GET_REG_FIELD(__gxVerif->rasRegs[0x10], 2, 7) != 0 && __gxVerif->verifyLevel >= __gxvWarnLev[14]) {
__gxVerif->cb(__gxvWarnLev[14], 0xEU, __gxvWarnings[14]);
}
if ((u32)(__gxVerif->rasRegs[0xF] & 0xFF000000) + 0x01000000 == 0 && (nTex != 0 || nBmp != 0) && __gxVerif->verifyLevel >= __gxvWarnLev[15]) {
__gxVerif->cb(__gxvWarnLev[15], 0xFU, __gxvWarnings[15]);
}
}
}
#define SOMEINDEX(index) (index & 3) + ((index * 8) & ~0x1F)
#define MAX(a, b) ((a) > (b) ? (a) : (b))
void __GXVerifyTEX(void) {
u32 i;
u32 nBmp;
u32 nTev;
u32 nTex;
u32 enabled;
u32 texId;
u32 direct[8];
u32 indirect[8];
u32 h2;
u32 w2;
u32 nlevels;
nBmp = GET_REG_FIELD(__gxVerif->rasRegs[0], 3, 16);
nTex = GET_REG_FIELD(__gxVerif->rasRegs[0], 4, 0);
nTev = GET_REG_FIELD(__gxVerif->rasRegs[0], 4, 10) + 1;
for (i = 0; i < 8; i++) {
direct[i] = 0;
indirect[i] = 0;
}
for (i = 0; i < nTev + nBmp; i++) {
if (i < nTev) {
if (__gxVerif->verifyLevel >= 1) {
if ((__gxVerif->rasRegs[(i >> 1U) + 0x28] & 0xFF000000) + 0x01000000 == 0U && __gxVerif->verifyLevel >= __gxvWarnLev[16]) {
sprintf(__gxvDummyStr, __gxvWarnings[16], i);
__gxVerif->cb(__gxvWarnLev[16], 16, __gxvDummyStr);
}
if (i & 1) {
enabled = GET_REG_FIELD(__gxVerif->rasRegs[(i >> 1U) + 0x28], 1, 18);
if (enabled && (GET_REG_FIELD(__gxVerif->rasRegs[(i >> 1U) + 0x28], 3, 15) >= nTex) && __gxVerif->verifyLevel >= __gxvWarnLev[17]) {
sprintf(__gxvDummyStr, __gxvWarnings[17], i);
__gxVerif->cb(__gxvWarnLev[17], 17, __gxvDummyStr);
}
texId = GET_REG_FIELD(__gxVerif->rasRegs[(i >> 1U) + 0x28], 3, 12);
} else {
enabled = GET_REG_FIELD(__gxVerif->rasRegs[(i >> 1U) + 0x28], 1, 6);
if (enabled && (GET_REG_FIELD(__gxVerif->rasRegs[(i >> 1U) + 0x28], 3, 3) >= nTex) && __gxVerif->verifyLevel >= __gxvWarnLev[17]) {
sprintf(__gxvDummyStr, __gxvWarnings[17], i);
__gxVerif->cb(__gxvWarnLev[17], 17, __gxvDummyStr);
}
texId = GET_REG_FIELD(__gxVerif->rasRegs[(i >> 1U) + 0x28], 3, 0);
}
if (enabled) {
direct[texId] = 1;
}
}
} else {
enabled = 1;
if ((i - nTev) == 0) {
texId = GET_REG_FIELD(__gxVerif->rasRegs[0x27], 3, 0);
} else if ((i - nTev) == 1U) {
texId = GET_REG_FIELD(__gxVerif->rasRegs[0x27], 3, 6);
} else if ((i - nTev) == 2U) {
texId = GET_REG_FIELD(__gxVerif->rasRegs[0x27], 3, 12);
} else {
texId = GET_REG_FIELD(__gxVerif->rasRegs[0x27], 3, 18);
}
if (!indirect[texId] && direct[texId] && __gxVerif->verifyLevel >= __gxvWarnLev[18]) {
sprintf(__gxvDummyStr, __gxvWarnings[18], texId);
__gxVerif->cb(__gxvWarnLev[18], 18, __gxvDummyStr);
}
indirect[texId] = 1;
}
if (enabled) {
if (__gxVerif->verifyLevel >= GX_WARN_SEVERE) {
if (((u32)(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)] & 0xFF000000) + 0x01000000 == 0
|| (u32)(__gxVerif->rasRegs[0x84 + SOMEINDEX(texId)] & 0xFF000000) + 0x01000000 == 0
|| (u32)(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)] & 0xFF000000) + 0x01000000 == 0
|| (u32)(__gxVerif->rasRegs[0x8C + SOMEINDEX(texId)] & 0xFF000000) + 0x01000000 == 0
|| (u32)(__gxVerif->rasRegs[0x90 + SOMEINDEX(texId)] & 0xFF000000) + 0x01000000 == 0) && __gxVerif->verifyLevel >= __gxvWarnLev[19]) {
sprintf(__gxvDummyStr, __gxvWarnings[19], texId);
__gxVerif->cb(__gxvWarnLev[19], 19, __gxvDummyStr);
}
if (GET_REG_FIELD(__gxVerif->rasRegs[0x8C + SOMEINDEX(texId)], 1, 21) == 0
&& (u32)(__gxVerif->rasRegs[0x94 + SOMEINDEX(texId)] & 0xFF000000) + 0x01000000 == 0 && __gxVerif->verifyLevel >= __gxvWarnLev[20]) {
sprintf(__gxvDummyStr, __gxvWarnings[20], texId);
__gxVerif->cb(__gxvWarnLev[20], 20, __gxvDummyStr);
}
if (((u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 8
|| (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 9
|| (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 10)
&& (__gxVerif->rasRegs[0x98 + SOMEINDEX(texId)] & 0xFF000000) + 0x01000000 == 0U && __gxVerif->verifyLevel >= __gxvWarnLev[21]) {
sprintf(__gxvDummyStr, __gxvWarnings[21], texId);
__gxVerif->cb(__gxvWarnLev[21], 21, __gxvDummyStr);
}
if (GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 10, 0) + 1 == 0) {
w2 = 1;
} else {
w2 = 1;
while (!(w2 & (GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 10, 0) + 1))) {
w2 *= 2;
}
w2 = (GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 10, 0) + 1) == w2;
}
if (GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 10, 10) + 1 == 0) {
h2 = 1;
} else {
h2 = 1;
while (!(h2 & (GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 10, 10) + 1))) {
h2 *= 2;
}
h2 = (GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 10, 10) + 1) == h2;
}
if (GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)] & 0xFFFF, 2, 5) && !w2 && __gxVerif->verifyLevel >= __gxvWarnLev[22]) {
sprintf(__gxvDummyStr, __gxvWarnings[22], "Width", texId);
__gxVerif->cb(__gxvWarnLev[22], 22, __gxvDummyStr);
}
if (GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)] & 0xFFFF, 2, 5) && !h2 && __gxVerif->verifyLevel >= __gxvWarnLev[22]) {
sprintf(__gxvDummyStr, __gxvWarnings[22], "Height", texId);
__gxVerif->cb(__gxvWarnLev[22], 22, __gxvDummyStr);
}
if (GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 2, 0) && !w2 && __gxVerif->verifyLevel >= __gxvWarnLev[23]) {
sprintf(__gxvDummyStr, __gxvWarnings[23], "S", texId);
__gxVerif->cb(__gxvWarnLev[23], 23, __gxvDummyStr);
}
if (GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 2, 2) && !h2 && __gxVerif->verifyLevel >= __gxvWarnLev[23]) {
sprintf(__gxvDummyStr, __gxvWarnings[23], "T", texId);
__gxVerif->cb(__gxvWarnLev[23], 23, __gxvDummyStr);
}
if (GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)] & 0xFFFF, 2, 5) != 0
&& ((u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 8
|| (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 9
|| (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 10)
&& (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 3, 5) != 1
&& (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 3, 5) != 5 && __gxVerif->verifyLevel >= __gxvWarnLev[24]) {
sprintf(__gxvDummyStr, __gxvWarnings[24], texId);
__gxVerif->cb(__gxvWarnLev[24], 24, __gxvDummyStr);
}
if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[0x84 + SOMEINDEX(texId)], 8, 0) > (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x84 + SOMEINDEX(texId)], 8, 8) && __gxVerif->verifyLevel >= __gxvWarnLev[25]) {
sprintf(__gxvDummyStr, __gxvWarnings[25], texId);
__gxVerif->cb(__gxvWarnLev[25], 25, __gxvDummyStr);
}
for (
nlevels = 0;
(
MAX((u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 10, 0) + 1,
(u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 10, 10) + 1) >> nlevels
) != 0;
nlevels++) {
}
if (GET_REG_FIELD(__gxVerif->rasRegs[0x84 + SOMEINDEX(texId)], 8, 8) > (nlevels - 1) * 16 && __gxVerif->verifyLevel >= __gxvWarnLev[26]) {
sprintf(__gxvDummyStr, __gxvWarnings[26], texId);
__gxVerif->cb(__gxvWarnLev[26], 26, __gxvDummyStr);
}
if (GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 1, 21) && GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 1, 8) && __gxVerif->verifyLevel >= __gxvWarnLev[27]) {
sprintf(__gxvDummyStr, __gxvWarnings[27], texId);
__gxVerif->cb(__gxvWarnLev[27], 27, __gxvDummyStr);
}
if (GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 2, 19)
&& (GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)] & 0xFFFF, 2, 5) == 0
|| (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 3, 5) != 6
|| (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 1, 4) != 1
|| (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 8
|| (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 9
|| (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 10
|| (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 1, 8) != 0
|| (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 1, 21)) && __gxVerif->verifyLevel >= __gxvWarnLev[28]) {
sprintf(__gxvDummyStr, __gxvWarnings[28], texId);
__gxVerif->cb(__gxvWarnLev[28], 28, __gxvDummyStr);
}
}
if (GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 1, 18) != 0) {
if (((u32)GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 3, 5) != 4 || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 1, 4) != 1) && __gxVerif->verifyLevel >= __gxvWarnLev[29]) {
sprintf(__gxvDummyStr, __gxvWarnings[29], texId);
__gxVerif->cb(__gxvWarnLev[29], 29, __gxvDummyStr);
}
if ((!GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 1, 17) || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) != 1 || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 2, 19) != 0) && __gxVerif->verifyLevel >= __gxvWarnLev[30]) {
sprintf(__gxvDummyStr, __gxvWarnings[30], texId);
__gxVerif->cb(__gxvWarnLev[30], 30, __gxvDummyStr);
}
}
if (GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 1, 17) != 0) {
if (((u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 8 || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 9 || (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x88 + SOMEINDEX(texId)], 4, 20) == 10) && __gxVerif->verifyLevel >= __gxvWarnLev[31]) {
sprintf(__gxvDummyStr, __gxvWarnings[31], texId);
__gxVerif->cb(__gxvWarnLev[31], 31, __gxvDummyStr);
}
if ((!GET_REG_FIELD(__gxVerif->rasRegs[0x80 + SOMEINDEX(texId)], 1, 18) || 0) && __gxVerif->verifyLevel >= __gxvWarnLev[30]) {
sprintf(__gxvDummyStr, __gxvWarnings[30], texId);
__gxVerif->cb(__gxvWarnLev[30], 30, __gxvDummyStr);
}
}
}
}
}
void __GXVerifyTEV(void) {
u32 i; // r31
u32 nTev; // r29
u32 nCol; // r28
u32 enabled; // r30
u32 color; // r27
u32 Clh[4]; // r1+0x38
u32 Alh[4]; // r1+0x28
u32 Cwritten[4]; // r1+0x18
u32 Awritten[4]; // r1+0x8
nTev = GET_REG_FIELD(__gxVerif->rasRegs[0], 4, 10) + 1;
nCol = GET_REG_FIELD(__gxVerif->rasRegs[0], 3, 4);
nCol;
for (i = 0; i < 4; i++) {
Clh[i] = 0;
Alh[i] = 0;
Cwritten[i] = 0;
Awritten[i] = 0;
}
for (i = 0; i < nTev; i++) {
if (__gxVerif->verifyLevel >= GX_WARN_SEVERE
&& (((u32) ((__gxVerif->rasRegs[(i * 2) + 0xC0] & 0xFF000000) + 0x01000000) == 0U) || ((u32) ((__gxVerif->rasRegs[(i * 2) + 0xC1] & 0xFF000000) + 0x01000000) == 0U))) {
sprintf(__gxvDummyStr, __gxvWarnings[32], i);
__gxVerif->cb(1, 0x20U, __gxvDummyStr);
}
if (i & 1) {
color = GET_REG_FIELD(__gxVerif->rasRegs[(i >> 1U) + 0x28], 3, 19);
} else {
color = GET_REG_FIELD(__gxVerif->rasRegs[(i >> 1U) + 0x28], 3, 7);
}
if (__gxVerif->verifyLevel >= GX_WARN_MEDIUM && ((color == 0 && nCol < 1) || (color == 1 && nCol < 2))) {
sprintf(__gxvDummyStr, __gxvWarnings[33], i);
__gxVerif->cb(1, 0x21U, __gxvDummyStr);
}
if (i & 1) {
enabled = GET_REG_FIELD(__gxVerif->rasRegs[(i >> 1U) + 0x28], 1, 18);
} else {
enabled = GET_REG_FIELD(__gxVerif->rasRegs[(i >> 1U) + 0x28], 1, 6);
}
if (__gxVerif->verifyLevel >= GX_WARN_SEVERE) {
if (!enabled && ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 12) == 8 || (u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 12) == 9)) {
sprintf(__gxvDummyStr, __gxvWarnings[0x22], "A", i);
__gxVerif->cb(1, 0x22U, __gxvDummyStr);
}
if (!enabled && ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 8) == 8 || (u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 8) == 9)) {
sprintf(__gxvDummyStr, __gxvWarnings[0x22], "B", i);
__gxVerif->cb(1, 0x22U, __gxvDummyStr);
}
if (!enabled && ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 4) == 8 || (u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 4) == 9)) {
sprintf(__gxvDummyStr, __gxvWarnings[0x22], "C", i);
__gxVerif->cb(1, 0x22U, __gxvDummyStr);
}
if (!enabled && ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 0) == 8 || (u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 0) == 9)) {
sprintf(__gxvDummyStr, __gxvWarnings[0x22], "D", i);
__gxVerif->cb(1, 0x22U, __gxvDummyStr);
}
if (!enabled && (u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 13) == 4) {
sprintf(__gxvDummyStr, __gxvWarnings[0x23], "A", i);
__gxVerif->cb(1, 0x23U, __gxvDummyStr);
}
if (!enabled && (u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 10) == 4) {
sprintf(__gxvDummyStr, __gxvWarnings[0x23], "B", i);
__gxVerif->cb(1, 0x23U, __gxvDummyStr);
}
if (!enabled && (u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 7) == 4) {
sprintf(__gxvDummyStr, __gxvWarnings[0x23], "C", i);
__gxVerif->cb(1, 0x23U, __gxvDummyStr);
}
if (!enabled && (u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 4) == 4) {
sprintf(__gxvDummyStr, __gxvWarnings[0x23], "D", i);
__gxVerif->cb(1, 0x23U, __gxvDummyStr);
}
if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 12) <= 7 && ((__gxVerif->rasRegs[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 12) + 0xE1] & 0xFF000000) + 0x01000000) == 0U) {
if (GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 12) ? !Awritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 13)] : !Cwritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 13)]) {
sprintf(__gxvDummyStr, __gxvWarnings[0x24], "A", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 0xCU) ? "alpha" : "color", (__gxVerif->rasRegs[(i * 2) + 0xC0] >> 0xDU) & 7);
__gxVerif->cb(1, 0x24U, __gxvDummyStr);
}
}
if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 8) <= 7 && ((__gxVerif->rasRegs[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 8) + 0xE1] & 0xFF000000) + 0x01000000) == 0U) {
if (GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 8) ? !Awritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 9)] : !Cwritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 9)]) {
sprintf(__gxvDummyStr, __gxvWarnings[0x24], "B", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 8U) ? "alpha" : "color", (__gxVerif->rasRegs[(i * 2) + 0xC0] >> 9U) & 7);
__gxVerif->cb(1, 0x24U, __gxvDummyStr);
}
}
if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 4) <= 7 && ((__gxVerif->rasRegs[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 4) + 0xE1] & 0xFF000000) + 0x01000000) == 0U) {
if (GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 4) ? !Awritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 5)] : !Cwritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 5)]) {
sprintf(__gxvDummyStr, __gxvWarnings[0x24], "C", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 4U) ? "alpha" : "color", (__gxVerif->rasRegs[(i * 2) + 0xC0] >> 5U) & 7);
__gxVerif->cb(1, 0x24U, __gxvDummyStr);
}
}
if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 0) <= 7 && ((__gxVerif->rasRegs[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 0) + 0xE1] & 0xFF000000) + 0x01000000) == 0U) {
if (GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 0) ? !Awritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 1)] : !Cwritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 1)]) {
sprintf(__gxvDummyStr, __gxvWarnings[0x24], "D", i, (__gxVerif->rasRegs[(i * 2) + 0xC0] & 1) ? "alpha" : "color", (__gxVerif->rasRegs[(i * 2) + 0xC0] >> 1U) & 7);
__gxVerif->cb(1, 0x24U, __gxvDummyStr);
}
}
if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 13) <= 3 && ((__gxVerif->rasRegs[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 4, 14) + 0xE0] & 0xFF000000) + 0x01000000) == 0U && Awritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 13)] == 0U) {
sprintf(__gxvDummyStr, __gxvWarnings[0x25], "A", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 13));
__gxVerif->cb(1, 0x25U, __gxvDummyStr);
}
if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 10) <= 3 && ((__gxVerif->rasRegs[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 11) + 0xE0] & 0xFF000000) + 0x01000000) == 0U && Awritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 10)] == 0U) {
sprintf(__gxvDummyStr, __gxvWarnings[0x25], "B", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 10));
__gxVerif->cb(1, 0x25U, __gxvDummyStr);
}
if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 7) <= 3 && ((__gxVerif->rasRegs[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 8) + 0xE0] & 0xFF000000) + 0x01000000) == 0U && Awritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 7)] == 0U) {
sprintf(__gxvDummyStr, __gxvWarnings[0x25], "C", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 7));
__gxVerif->cb(1, 0x25U, __gxvDummyStr);
}
if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 4) <= 3 && ((__gxVerif->rasRegs[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 3) + 0xE0] & 0xFF000000) + 0x01000000) == 0U && Awritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 4)] == 0U) {
sprintf(__gxvDummyStr, __gxvWarnings[0x25], "D", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 4));
__gxVerif->cb(1, 0x25U, __gxvDummyStr);
}
}
if (__gxVerif->verifyLevel >= GX_WARN_ALL) {
if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 12) <= 7) {
if (GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 12) ? Alh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 13)] : Clh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 13)]) {
sprintf(__gxvDummyStr, __gxvWarnings[0x26], "A", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 12) ? "alpha" : "color", GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 13));
__gxVerif->cb(3, 0x26U, __gxvDummyStr);
}
}
if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 8) <= 7) {
if (GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 8) ? Alh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 9)] : Clh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 9)]) {
sprintf(__gxvDummyStr, __gxvWarnings[0x26], "B", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 8) ? "alpha" : "color", GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 9));
__gxVerif->cb(3, 0x26U, __gxvDummyStr);
}
}
if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 4, 4) <= 7) {
if (GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 4) ? Alh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 5)] : Clh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 5)]) {
sprintf(__gxvDummyStr, __gxvWarnings[0x26], "C", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 4) ? "alpha" : "color", GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 3, 5));
__gxVerif->cb(3, 0x26U, __gxvDummyStr);
}
}
if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 13) <= 3 && (u32)Alh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 13)] != 0) {
sprintf(__gxvDummyStr, __gxvWarnings[0x27], "A", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 0xDU));
__gxVerif->cb(3, 0x27U, __gxvDummyStr);
}
if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 10) <= 3 && (u32)Alh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 10)] != 0) {
sprintf(__gxvDummyStr, __gxvWarnings[0x27], "B", i, ((__gxVerif->rasRegs[(i * 2) + 0xC1] >> 0xAU) & 7));
__gxVerif->cb(3, 0x27U, __gxvDummyStr);
}
if ((u32)GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 7) <= 3 && (u32)Alh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 7)] != 0) {
sprintf(__gxvDummyStr, __gxvWarnings[0x27], "C", i, GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 3, 7U));
__gxVerif->cb(3, 0x27U, __gxvDummyStr);
}
}
Cwritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 2, 22)] = 1;
Awritten[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 2, 22)] = 1;
Clh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 2, 22)] = (!GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 2, 0) && !GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC0], 1, 19));
Alh[GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 2, 22)] = (!GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 2, 0) && !GET_REG_FIELD(__gxVerif->rasRegs[(i * 2) + 0xC1], 1, 19));
}
for (i = 0; i < 4; i++) {
if (Cwritten[i] != 0U) {
__gxVerif->rasRegs[(i * 2) + 0xE1] = (__gxVerif->rasRegs[(i * 2) + 0xE1] & 0xFFFFFF) | 0xFF000000;
}
if (Awritten[i] != 0U) {
__gxVerif->rasRegs[(i * 2) + 0xE0] = (__gxVerif->rasRegs[(i * 2) + 0xE0] & 0xFFFFFF) | 0xFF000000;
}
}
if (GET_REG_FIELD(__gxVerif->rasRegs[0xF5], 2, 2) && __gxVerif->verifyLevel >= 1) {
if ((u32) ((__gxVerif->rasRegs[0xF4] & 0xFF000000) + 0x01000000) == 0U) {
__gxVerif->cb(1, 0x28U, __gxvWarnings[0x28]);
}
if (!enabled) {
__gxVerif->cb(1, 0x29U, __gxvWarnings[0x29]);
}
}
if (__gxVerif->verifyLevel >= GX_WARN_MEDIUM) {
if (GET_REG_FIELD(__gxVerif->rasRegs[((nTev - 1) * 2) + 0xC0], 2, 22)) {
__gxVerif->cb(2, 0x2AU, __gxvWarnings[0x2A]);
}
if (GET_REG_FIELD(__gxVerif->rasRegs[((nTev - 1) * 2) + 0xC1], 2, 22)) {
__gxVerif->cb(2, 0x2BU, __gxvWarnings[0x2B]);
}
}
if (__gxVerif->verifyLevel >= GX_WARN_ALL) {
if (!GET_REG_FIELD(__gxVerif->rasRegs[((nTev - 1) * 2) + 0xC1], 2, 0) && !GET_REG_FIELD(__gxVerif->rasRegs[((nTev - 1) * 2) + 0xC0], 1, 19)) {
__gxVerif->cb(3, 0x2CU, __gxvWarnings[0x2C]);
}
if (!GET_REG_FIELD(__gxVerif->rasRegs[((nTev - 1) * 2) + 0xC1], 2, 0) && !GET_REG_FIELD(__gxVerif->rasRegs[((nTev - 1) * 2) + 0xC1], 1, 19)) {
__gxVerif->cb(3, 0x2DU, __gxvWarnings[0x2D]);
}
}
if (__gxVerif->verifyLevel >= GX_WARN_MEDIUM && GET_REG_FIELD(__gxVerif->rasRegs[0x43], 1, 6) && (GET_REG_FIELD(__gxVerif->rasRegs[0xF3], 2, 22) || ((u32) GET_REG_FIELD(__gxVerif->rasRegs[0xF3], 3, 16) != 7) || ((u32) GET_REG_FIELD(__gxVerif->rasRegs[0xF3], 3, 19) != 7))) {
__gxVerif->cb(2, 0x2EU, __gxvWarnings[0x2E]);
}
}
void __GXVerifyPE(void) {
u32 i;
if (__gxVerif->verifyLevel >= GX_WARN_SEVERE && GET_REG_FIELD(__gxVerif->rasRegs[0x41], 1, 0) && GET_REG_FIELD(__gxVerif->rasRegs[0x41], 1, 1) && __gxVerif->verifyLevel >= __gxvWarnLev[0x2F]) {
__gxVerif->cb(__gxvWarnLev[0x2F], 0x2FU, __gxvWarnings[0x2F]);
}
if (__gxVerif->verifyLevel >= GX_WARN_MEDIUM) {
if (GET_REG_FIELD(__gxVerif->rasRegs[0], 1, 9) && (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x43], 3, 0) != 2 && __gxVerif->verifyLevel >= __gxvWarnLev[0x31]) {
__gxVerif->cb(__gxvWarnLev[0x31], 0x31U, __gxvWarnings[0x31]);
}
if (!GET_REG_FIELD(__gxVerif->rasRegs[0], 1, 9) && (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x43], 3, 0) == 2 && __gxVerif->verifyLevel >= __gxvWarnLev[0x32]) {
__gxVerif->cb(__gxvWarnLev[0x32], 0x32U, __gxvWarnings[0x32]);
}
}
if (__gxVerif->verifyLevel >= GX_WARN_ALL) {
for (i = 0; i < 4; i++) {
if (((u32)GET_REG_FIELD(__gxVerif->rasRegs[i + 1], 4, 4) > GET_REG_FIELD(__gxVerif->rasRegs[i + 1], 4, 12) || (u32)GET_REG_FIELD(__gxVerif->rasRegs[i + 1], 4, 12) > (u32)GET_REG_FIELD(__gxVerif->rasRegs[i + 1], 4, 20))
&& (u32)GET_REG_FIELD(__gxVerif->rasRegs[0x43], 3, 0) == 2 && __gxVerif->verifyLevel >= __gxvWarnLev[0x33]) {
sprintf(__gxvDummyStr, __gxvWarnings[0x33], i);
__gxVerif->cb(__gxvWarnLev[0x33], 0x33U, __gxvDummyStr);
}
}
}
}
#endif
+946
View File
@@ -0,0 +1,946 @@
#if DEBUG
#include <stdio.h>
#include <revolution/gx.h>
#include "__gx.h"
static u32 DumpCount;
static s8 XFBuf[128];
static u32 numRegularTextures;
static u32 numBumpmapTextures;
static u32 numColor0Textures;
static u32 numColor1Textures;
static u32 numColorTextures;
static s32 XFChannel = -1;
static GXAttr TextureEnums[8] = {
GX_VA_TEX0,
GX_VA_TEX1,
GX_VA_TEX2,
GX_VA_TEX3,
GX_VA_TEX4,
GX_VA_TEX5,
GX_VA_TEX6,
GX_VA_TEX7,
};
static GXAttr MtxIdxEnums[9] = {
GX_VA_PNMTXIDX,
GX_VA_TEX0MTXIDX,
GX_VA_TEX1MTXIDX,
GX_VA_TEX2MTXIDX,
GX_VA_TEX3MTXIDX,
GX_VA_TEX4MTXIDX,
GX_VA_TEX5MTXIDX,
GX_VA_TEX6MTXIDX,
GX_VA_TEX7MTXIDX,
};
static u8 lightRegisterNames[13][256] = {
"Light Color RGBA",
"Cosine Attenuation A0",
"Cosine Attenuation A1",
"Cosine Attenuation A2",
"Distance Attenuation K0",
"Distance Attenuation K1",
"Distance Attenuation K2",
"X Light Position / Infinite Light X Direction",
"Y Light Position / Infinite Light Y Direction",
"Z Light Position / Infinite Light Z Direction",
"X Light Direction / Half Angle X Component",
"Y Light Direction / Half Angle Y Component",
"Z Light Direction / Half Angle Z Component",
};
#define LOWORD(var) (((u16 *)&(var))[0])
#define HIWORD(var) (((u16 *)&(var))[1])
#define BYTE0(var) (((u8 *)&(var))[0])
#define BYTE1(var) (((u8 *)&(var))[1])
#define BYTE2(var) (((u8 *)&(var))[2])
#define BYTE3(var) (((u8 *)&(var))[3])
static void CountTextureTypes(void) {
u32 i;
u32 texgen_type;
numRegularTextures = 0;
numBumpmapTextures = 0;
numColor0Textures = 0;
numColor1Textures = 0;
for (i = 0; i < __gxVerif->xfRegs[0x3F]; i++) {
texgen_type = (__gxVerif->xfRegs[i + 64] >> 4) & 7;
if (texgen_type == 0) {
numRegularTextures++;
} else if (texgen_type == 1) {
numBumpmapTextures++;
} else if (texgen_type == 2) {
numColor0Textures++;
} else if (texgen_type == 3) {
numColor1Textures++;
} else {
if (__gxVerif->verifyLevel >= __gxvWarnLev[52]) {
__GX_WARNF(GXWARN_INVALID_TG_TYPE, texgen_type, i);
}
}
}
numColorTextures = numColor0Textures + numColor1Textures;
}
static void InitializeXFVerifyData(void) {
CountTextureTypes();
}
static void CheckDirty(u32 index, const char* name) {
if (!__gxVerif->xfRegsDirty[index - 0x1000] && __gxVerif->verifyLevel >= __gxvWarnLev[53]) {
__GX_WARNF(GXWARN_XF_CTRL_UNINIT, index, name);
}
}
static void CheckClean(u32 index, const char* name) {
if (__gxVerif->xfRegsDirty[index - 0x1000] && __gxVerif->verifyLevel >= __gxvWarnLev[54]) {
__GX_WARNF(GXWARN_XF_CTRL_INIT, index, name);
}
}
static void CheckCTGColors(void) {
if ((u32)(__gxVerif->xfRegs[9] & 3) > 2 && __gxVerif->verifyLevel >= __gxvWarnLev[121]) {
__GX_WARNF(121, __gxVerif->xfRegs[9] & 3);
}
}
static GXBool __GXVertexPacketHas(GXAttr attr) {
switch (attr) {
case GX_VA_POS: return GET_REG_FIELD(__GXData->vcdLo, 2, 9) != 0;
case GX_VA_NRM: return __GXData->hasNrms ? GET_REG_FIELD(__GXData->vcdLo, 2, 11) != 0 : GX_FALSE;
case GX_VA_NBT: return __GXData->hasBiNrms ? GET_REG_FIELD(__GXData->vcdLo, 2, 11) != 0 : GX_FALSE;
case GX_VA_CLR0: return GET_REG_FIELD(__GXData->vcdLo, 2, 13) != 0;
case GX_VA_CLR1: return GET_REG_FIELD(__GXData->vcdLo, 2, 15) != 0;
case GX_VA_TEX0: return GET_REG_FIELD(__GXData->vcdHi, 2, 0) != 0;
case GX_VA_TEX1: return GET_REG_FIELD(__GXData->vcdHi, 2, 2) != 0;
case GX_VA_TEX2: return GET_REG_FIELD(__GXData->vcdHi, 2, 4) != 0;
case GX_VA_TEX3: return GET_REG_FIELD(__GXData->vcdHi, 2, 6) != 0;
case GX_VA_TEX4: return GET_REG_FIELD(__GXData->vcdHi, 2, 8) != 0;
case GX_VA_TEX5: return GET_REG_FIELD(__GXData->vcdHi, 2, 10) != 0;
case GX_VA_TEX6: return GET_REG_FIELD(__GXData->vcdHi, 2, 12) != 0;
case GX_VA_TEX7: return GET_REG_FIELD(__GXData->vcdHi, 2, 14) != 0;
case GX_VA_PNMTXIDX: return GET_REG_FIELD(__GXData->vcdLo, 1, 0) != 0;
case GX_VA_TEX0MTXIDX: return GET_REG_FIELD(__GXData->vcdLo, 1, 1) != 0;
case GX_VA_TEX1MTXIDX: return GET_REG_FIELD(__GXData->vcdLo, 1, 2) != 0;
case GX_VA_TEX2MTXIDX: return GET_REG_FIELD(__GXData->vcdLo, 1, 3) != 0;
case GX_VA_TEX3MTXIDX: return GET_REG_FIELD(__GXData->vcdLo, 1, 4) != 0;
case GX_VA_TEX4MTXIDX: return GET_REG_FIELD(__GXData->vcdLo, 1, 5) != 0;
case GX_VA_TEX5MTXIDX: return GET_REG_FIELD(__GXData->vcdLo, 1, 6) != 0;
case GX_VA_TEX6MTXIDX: return GET_REG_FIELD(__GXData->vcdLo, 1, 7) != 0;
case GX_VA_TEX7MTXIDX: return GET_REG_FIELD(__GXData->vcdLo, 1, 8) != 0;
default:
return GX_FALSE;
}
}
static void CheckVertexPacket(void) {
u32 numHostTextures;
u32 numHostTexAbsent;
u32 i;
if (!__GXVertexPacketHas(GX_VA_POS) && __gxVerif->verifyLevel >= __gxvWarnLev[57]) {
__GX_WARN(GXWARN_VTX_NO_GEOM);
}
if (__GXVertexPacketHas(GX_VA_CLR1) && !__GXVertexPacketHas(GX_VA_CLR0) &&__gxVerif->verifyLevel >= __gxvWarnLev[70]) {
__GX_WARN(GXWARN_VCD_CLR_ORDER);
}
numHostTextures = 0;
numHostTexAbsent = 0;
for (i = 0; i < 8; i++) {
if (__GXVertexPacketHas(TextureEnums[i])) {
numHostTextures += 1;
numHostTexAbsent = 0;
} else {
numHostTexAbsent += 1;
}
}
if (numHostTextures + numHostTexAbsent != 8 && __gxVerif->verifyLevel >= __gxvWarnLev[71]) {
__GX_WARN(GXWARN_VCD_TEX_ORDER);
}
if ((__gxVerif->xfRegs[8] & 3) == 0 && ((__gxVerif->xfRegs[8] >> 2) & 3) == 0 && (u32)((__gxVerif->xfRegs[8] >> 4) & 0xF) == 0) {
u32 numMatrixIndices = 0;
for (i = 0; i <= 8; i++) {
if (__GXVertexPacketHas(MtxIdxEnums[i])) {
numMatrixIndices += 1;
}
}
if (numMatrixIndices != 0 && __gxVerif->verifyLevel >= __gxvWarnLev[69]) {
__GX_WARN(GXWARN_VCD_FMT_UNSUP);
}
}
}
static void CheckSourceRows(void) {
u32 i;
for (i = 0; i < numRegularTextures; i++) {
switch ((__gxVerif->xfRegs[i + 64] >> 7) & 0x1F) {
case 0:
if (!__GXVertexPacketHas(GX_VA_POS) && __gxVerif->verifyLevel >= __gxvWarnLev[72]) {
__GX_WARNF(GXWARN_TEX_SRC_NPOS, i);
}
break;
case 1:
if (!__GXVertexPacketHas(GX_VA_NRM) && !__GXVertexPacketHas(GX_VA_NBT)&& __gxVerif->verifyLevel >= __gxvWarnLev[73]) {
__GX_WARNF(GXWARN_TEX_SRC_NNRM, i);
}
break;
case 2:
if (!__GXVertexPacketHas(GX_VA_CLR0) && __gxVerif->verifyLevel >= __gxvWarnLev[74]) {
__GX_WARNF(GXWARN_TEX_SRC_NCLR0, i);
}
if (!__GXVertexPacketHas(GX_VA_CLR1) && __gxVerif->verifyLevel >= __gxvWarnLev[75]) {
__GX_WARNF(GXWARN_TEX_SRC_NCLR1, i);
}
break;
case 3:
case 4:
if (!__GXVertexPacketHas(GX_VA_NBT) && __gxVerif->verifyLevel >= __gxvWarnLev[76]) {
__GX_WARNF(GXWARN_TEX_SRC_NNBT, i);
}
break;
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
if (!__GXVertexPacketHas(TextureEnums[((__gxVerif->xfRegs[i + 64] >> 7) & 0x1F) - 5]) && __gxVerif->verifyLevel >= __gxvWarnLev[77]) {
__GX_WARNF(GXWARN_TEX_SRC_NTEX, i, ((__gxVerif->xfRegs[i + 64] >> 7) & 0x1F) - 5);
}
break;
default:
if (__gxVerif->verifyLevel >= __gxvWarnLev[78]) {
__GX_WARNF(GXWARN_INV_TEX_SRC, i, (__gxVerif->xfRegs[i + 64] >> 7) & 0x1F);
}
break;
}
}
}
static void CheckTextureOrder(void) {
u8 done = 0;
u32 count = 0;
while (!done) {
if (count == __gxVerif->xfRegs[0x3F] || ((__gxVerif->xfRegs[count + 64] >> 4) & 7)) {
done = 1;
} else {
count += 1;
}
}
done = 0;
while (done == 0) {
if (count == __gxVerif->xfRegs[0x3F]) {
done = 1;
} else if ((u32)((__gxVerif->xfRegs[count + 64] >> 4) & 7) != 1) {
if (!((__gxVerif->xfRegs[count + 64] >> 4) & 7) && __gxVerif->verifyLevel >= __gxvWarnLev[79]) {
__GX_WARN(GXWARN_INV_TG_ORDER);
}
done = 1;
} else {
count += 1;
}
}
done = 0;
while (done == 0) {
if (count == __gxVerif->xfRegs[0x3F]) {
done = 1;
} else if (!((__gxVerif->xfRegs[count + 64] >> 4) & 7) || (u32)((__gxVerif->xfRegs[count + 64] >> 4) & 7) == 1) {
if (__gxVerif->verifyLevel >= __gxvWarnLev[79]) {
__GX_WARN(GXWARN_INV_TG_ORDER);
}
done = 1;
} else {
count += 1;
}
}
}
static void CheckRAM(u8 Normal, u32 StartingAddress, u32 Count, GXWarnID WarnID, char* Str) {
u32 i;
u8 printedPreamble;
u8 dirtyBit;
printedPreamble = 0;
for (i = StartingAddress; i < StartingAddress + Count; i++) {
dirtyBit = Normal != 0 ? __gxVerif->xfMtxDirty[i - 0x300] : __gxVerif->xfMtxDirty[i];
if (dirtyBit == 0) {
if (printedPreamble == 0) {
if (__gxVerif->verifyLevel >= __gxvWarnLev[WarnID]) {
__gxVerif->cb(__gxvWarnLev[WarnID], WarnID, Str);
}
printedPreamble = 1;
}
}
}
}
static void CheckBumpmapTextures(void) {
u32 i;
u32 BumpMapSource;
u32 BumpMapLight;
u32 lightRAMOffset;
char Preamble[256];
if (!__GXVertexPacketHas(GX_VA_PNMTXIDX)) {
if ((u32)(__gxVerif->xfRegs[24] & 0x3F) > 30 && __gxVerif->verifyLevel >= __gxvWarnLev[0x50]) {
__GX_WARNF(0x50, __gxVerif->xfRegs[24] & 0x3F);
}
sprintf(Preamble, __gxvWarnings[0x6A], __gxVerif->xfRegs[24] & 0x3F);
CheckRAM(1, ((__gxVerif->xfRegs[24] & 0x3F) * 3) + 0x400, 9U, 0x6A, Preamble);
}
for (i = 0; i < numBumpmapTextures; i++) {
BumpMapSource = (__gxVerif->xfRegs[numRegularTextures + i + 64] >> 12) & 7;
if ((__gxVerif->xfRegs[BumpMapSource + 64] >> 4) & 7 && __gxVerif->verifyLevel >= __gxvWarnLev[0x51]) {
__GX_WARNF(0x51, i + numRegularTextures, BumpMapSource);
}
BumpMapLight = (__gxVerif->xfRegs[numRegularTextures + i + 0x40] >> 15) & 7;
lightRAMOffset = (BumpMapLight * 0x10) + 0x60A;
if (!__gxVerif->xfLightDirty[lightRAMOffset - 0x600 + 0] && __gxVerif->verifyLevel >= __gxvWarnLev[0x52]) {
__GX_WARNF(0x52, i + numRegularTextures, BumpMapLight, "X");
}
if (!__gxVerif->xfLightDirty[lightRAMOffset - 0x600 + 1] && __gxVerif->verifyLevel >= __gxvWarnLev[0x52]) {
__GX_WARNF(0x52, i + numRegularTextures, BumpMapLight, "Y");
}
if (!__gxVerif->xfLightDirty[lightRAMOffset - 0x600 + 2] && __gxVerif->verifyLevel >= __gxvWarnLev[0x52]) {
__GX_WARNF(0x52, i + numRegularTextures, BumpMapLight, "Z");
}
if (!__GXVertexPacketHas(GX_VA_NBT) && __gxVerif->verifyLevel >= __gxvWarnLev[0x53]) {
__GX_WARNF(0x53, i);
}
}
lightRAMOffset; lightRAMOffset; // needed to match
}
static void CheckTextureTransformMatrices(void) {
u32 i;
u32 StartingAddress;
u8 MtxIndexInVertexPacket;
char Preamble[256];
u32 Val;
for (i = 0; i < numRegularTextures; i++) {
MtxIndexInVertexPacket = 0;
switch (i) {
case 0:
StartingAddress = ((__gxVerif->xfRegs[0x18] >> 6U) & 0x3F) << 2;
Val = (__gxVerif->xfRegs[0x18] >> 6) & 0x3F;
MtxIndexInVertexPacket = __GXVertexPacketHas(GX_VA_TEX0MTXIDX);
break;
case 1:
StartingAddress = ((__gxVerif->xfRegs[0x18] >> 12) & 0x3F) << 2;
Val = (__gxVerif->xfRegs[0x18] >> 12) & 0x3F;
MtxIndexInVertexPacket = __GXVertexPacketHas(GX_VA_TEX1MTXIDX);
break;
case 2:
StartingAddress = ((__gxVerif->xfRegs[0x18] >> 18) & 0x3F) << 2;
Val = (__gxVerif->xfRegs[0x18] >> 18) & 0x3F;
MtxIndexInVertexPacket = __GXVertexPacketHas(GX_VA_TEX2MTXIDX);
break;
case 3:
StartingAddress = ((__gxVerif->xfRegs[0x18] >> 24) & 0x3F) << 2;
Val = (__gxVerif->xfRegs[0x18] >> 24) & 0x3F;
MtxIndexInVertexPacket = __GXVertexPacketHas(GX_VA_TEX3MTXIDX);
break;
case 4:
StartingAddress = (__gxVerif->xfRegs[0x19] & 0x3F) << 2;
Val = __gxVerif->xfRegs[0x19] & 0x3F;
MtxIndexInVertexPacket = __GXVertexPacketHas(GX_VA_TEX4MTXIDX);
break;
case 5:
StartingAddress = ((__gxVerif->xfRegs[0x19] >> 6) & 0x3F) << 2;
Val = (__gxVerif->xfRegs[0x19] >> 6) & 0x3F;
MtxIndexInVertexPacket = __GXVertexPacketHas(GX_VA_TEX5MTXIDX);
break;
case 6:
StartingAddress = ((__gxVerif->xfRegs[0x19] >> 12) & 0x3F) << 2;
Val = (__gxVerif->xfRegs[0x19] >> 12) & 0x3F;
MtxIndexInVertexPacket = __GXVertexPacketHas(GX_VA_TEX6MTXIDX);
break;
case 7:
StartingAddress = ((__gxVerif->xfRegs[0x19] >> 18) & 0x3F) << 2;
Val = (__gxVerif->xfRegs[0x19] >> 18) & 0x3F;
MtxIndexInVertexPacket = __GXVertexPacketHas(GX_VA_TEX7MTXIDX);
break;
default:
if (__gxVerif->verifyLevel >= __gxvWarnLev[0x54]) {
__GX_WARNF(0x54, i);
}
break;
}
if (MtxIndexInVertexPacket == 0) {
u32 Size;
sprintf(Preamble, __gxvWarnings[0x6B], i, i, Val);
Size = !((__gxVerif->xfRegs[i + 64] >> 1) & 1) ? 8 : 12;
CheckRAM(0U, StartingAddress, Size, 0x6B, Preamble);
}
}
}
static void CheckInputForms(void) {
u32 i;
for (i = 0; i < numRegularTextures; i++) {
switch ((__gxVerif->xfRegs[i + 64] >> 7) & 0x1F) {
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
if ((__gxVerif->xfRegs[i + 64] >> 2) & 1 && __gxVerif->verifyLevel >= __gxvWarnLev[122]) {
__GX_WARNF(122, i, (__gxVerif->xfRegs[i + 64] >> 7) & 0x1F);
}
}
}
}
static void CheckLight(u32 lightSource) {
u32 lightRAMOffset;
u8 printedPreamble;
u32 i;
printedPreamble = 0;
lightRAMOffset = (lightSource * 0x10) + 0x603;
for (i = 0; i < 13; i++) {
if (!__gxVerif->xfLightDirty[lightRAMOffset + i - 0x600]) {
if (!printedPreamble) {
if (__gxVerif->verifyLevel >= __gxvWarnLev[0x6C]) {
__GX_WARNF(0x6C, lightSource);
}
printedPreamble = 1;
}
}
}
}
// NONMATCHING
static void CheckColor0(void) {
char Preamble[256];
u8 haveLight;
u32 i;
u8 lightUsed;
if ((u8)(BYTE3(__gxVerif->xfRegs[9]) & 3) || numColorTextures != 0) {
if (!__gxVerif->xfRegsDirty[14] && __gxVerif->verifyLevel >= __gxvWarnLev[0x7A]) {
__GX_WARNF(0x7A, 0x100E, "Color 0 control register");
}
if (!__gxVerif->xfRegsDirty[16] && __gxVerif->verifyLevel >= __gxvWarnLev[0x7A]) {
__GX_WARNF(0x7A, 0x1010, "Alpha 0 control register");
}
if (!(BYTE3(__gxVerif->xfRegs[14]) & 1) && !__gxVerif->xfRegsDirty[12] && __gxVerif->verifyLevel >= __gxvWarnLev[0x7B]) {
__GX_WARNF(0x7B, 0, 0, 0x100C);
}
if (!((BYTE3(__gxVerif->xfRegs[14]) >> 6) & 1) && !__gxVerif->xfRegsDirty[10] && __gxVerif->verifyLevel >= __gxvWarnLev[0x7C]) {
__GX_WARNF(0x7C, 0, 0, 0x100A);
}
if ((u32)((BYTE3(__gxVerif->xfRegs[14]) >> 1) & 1) == 1 || (u32)((BYTE3(__gxVerif->xfRegs[16]) >> 1) & 1) == 1) {
haveLight = 0;
for (i = 0; i < 8; i++) {
lightUsed = 0;
switch (i) {
case 0:
if ((u8)((BYTE3(__gxVerif->xfRegs[14]) >> 2) & 1) || (u8)((BYTE3(__gxVerif->xfRegs[16]) >> 2) & 1)) {
lightUsed = 1;
}
break;
case 1:
if ((u8)((BYTE3(__gxVerif->xfRegs[14]) >> 3) & 1) || (u8)((BYTE3(__gxVerif->xfRegs[16]) >> 3) & 1)) {
lightUsed = 1;
}
break;
case 2:
if ((u8)((BYTE3(__gxVerif->xfRegs[14]) >> 4) & 1) || (u8)((BYTE3(__gxVerif->xfRegs[16]) >> 4) & 1)) {
lightUsed = 1;
}
break;
case 3:
if ((u8)((BYTE3(__gxVerif->xfRegs[14]) >> 5) & 1) || (u8)((BYTE3(__gxVerif->xfRegs[16]) >> 5) & 1)) {
lightUsed = 1;
}
break;
case 4:
if ((u8)((BYTE2(__gxVerif->xfRegs[14]) >> 3) & 1) || (u8)((BYTE2(__gxVerif->xfRegs[16]) >> 3) & 1)) {
lightUsed = 1;
}
break;
case 5:
if ((u8)((BYTE2(__gxVerif->xfRegs[14]) >> 4) & 1) || (u8)((BYTE2(__gxVerif->xfRegs[16]) >> 4) & 1)) {
lightUsed = 1;
}
break;
case 6:
if ((u8)((BYTE2(__gxVerif->xfRegs[14]) >> 5) & 1) || (u8)((BYTE2(__gxVerif->xfRegs[16]) >> 5) & 1)) {
lightUsed = 1;
}
break;
case 7:
if ((u8)((BYTE2(__gxVerif->xfRegs[14]) >> 6) & 1) || (u8)((BYTE2(__gxVerif->xfRegs[16]) >> 6) & 1)) {
lightUsed = 1;
}
break;
}
if (lightUsed != 0) {
CheckLight(i);
haveLight = 1;
}
}
if (haveLight != 0) {
if (!((BYTE2(__gxVerif->xfRegs[14]) >> 2) & 1) && ((HIWORD(__gxVerif->xfRegs[14]) >> 7) & 3) && __gxVerif->verifyLevel >= __gxvWarnLev[0x59]) {
__GX_WARNF(0x59, "COLOR0", "COLOR0");
}
if (!((BYTE2(__gxVerif->xfRegs[16]) >> 2) & 1) && ((HIWORD(__gxVerif->xfRegs[16]) >> 7) & 3) && __gxVerif->verifyLevel >= __gxvWarnLev[0x59]) {
__GX_WARNF(0x59, "ALPHA0", "ALPHA0");
}
if (((HIWORD(__gxVerif->xfRegs[14]) >> 7) & 3)
|| ((u8)((BYTE2(__gxVerif->xfRegs[14]) >> 1) & 1) && ((u32)((BYTE2(__gxVerif->xfRegs[14]) >> 2) & 1) == 1))
|| ((HIWORD(__gxVerif->xfRegs[16]) >> 7) & 3)
|| ((u8)((BYTE2(__gxVerif->xfRegs[16]) >> 1) & 1) && ((u32)((BYTE2(__gxVerif->xfRegs[16]) >> 2) & 1) == 1))) {
if ((__GXVertexPacketHas(GX_VA_NRM) == 0) && (__GXVertexPacketHas(GX_VA_NBT) == 0) && __gxVerif->verifyLevel >= __gxvWarnLev[0x5A]) {
__GX_WARNF(0x5A, 0);
}
if (__GXVertexPacketHas(GX_VA_PNMTXIDX) == 0) {
if ((u32)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F) > 30 && __gxVerif->verifyLevel >= __gxvWarnLev[0x5B]) {
__GX_WARNF(0x5B, 0, (BYTE3(__gxVerif->xfRegs[24]) & 0x3F));
}
sprintf(Preamble, __gxvWarnings[0x6D], 0, (u8)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F));
CheckRAM(1, ((BYTE3(__gxVerif->xfRegs[24]) & 0x3F) * 3) + 0x400, 9, 0x6D, Preamble);
}
}
}
}
}
}
// NONMATCHING
static void CheckColor1(void) {
u8 usingColor1;
char Preamble[256];
u8 haveLight;
u32 i;
u8 lightUsed;
if (numColorTextures > 1 && ((u32)((BYTE3(__gxVerif->xfRegs[numRegularTextures + numBumpmapTextures + 1 + 64]) >> 4) & 7) == 3)) {
usingColor1 = 1;
} else {
usingColor1 = 0;
}
if ((u32)(BYTE3(__gxVerif->xfRegs[9]) & 3) == 2 || usingColor1) {
if (!__gxVerif->xfRegsDirty[15] && __gxVerif->verifyLevel >= __gxvWarnLev[0x7A]) {
__GX_WARNF(0x7A, 0x100F, "Color 1 control register");
}
if (!__gxVerif->xfRegsDirty[17] && __gxVerif->verifyLevel >= __gxvWarnLev[0x7A]) {
__GX_WARNF(0x7A, 0x1011, "Alpha 1 control register");
}
if (!(BYTE3(__gxVerif->xfRegs[15]) & 1) && !__gxVerif->xfRegsDirty[13] && __gxVerif->verifyLevel >= __gxvWarnLev[0x7B]) {
__GX_WARNF(0x7B, 1, 1, 0x100D);
}
if (!((BYTE3(__gxVerif->xfRegs[15]) >> 6) & 1) && !__gxVerif->xfRegsDirty[11] && __gxVerif->verifyLevel >= __gxvWarnLev[0x7C]) {
__GX_WARNF(0x7C, 1, 1, 0x100B);
}
if ((u32)((BYTE3(__gxVerif->xfRegs[15]) >> 1) & 1) == 1 || (u32)((BYTE3(__gxVerif->xfRegs[17]) >> 1) & 1) == 1) {
haveLight = 0;
for (i = 0; i < 8; i++) {
lightUsed = 0;
switch (i) {
case 0:
if ((u8)((BYTE3(__gxVerif->xfRegs[15]) >> 2) & 1) || (u8)((BYTE3(__gxVerif->xfRegs[17]) >> 2) & 1)) {
lightUsed = 1;
}
break;
case 1:
if ((u8)((BYTE3(__gxVerif->xfRegs[15]) >> 3) & 1) || (u8)((BYTE3(__gxVerif->xfRegs[17]) >> 3) & 1)) {
lightUsed = 1;
}
break;
case 2:
if ((u8)((BYTE3(__gxVerif->xfRegs[15]) >> 4) & 1) || (u8)((BYTE3(__gxVerif->xfRegs[17]) >> 4) & 1)) {
lightUsed = 1;
}
break;
case 3:
if ((u8)((BYTE3(__gxVerif->xfRegs[15]) >> 5) & 1) || (u8)((BYTE3(__gxVerif->xfRegs[17]) >> 5) & 1)) {
lightUsed = 1;
}
break;
case 4:
if ((u8)((BYTE2(__gxVerif->xfRegs[15]) >> 3) & 1) || (u8)((BYTE2(__gxVerif->xfRegs[17]) >> 3) & 1)) {
lightUsed = 1;
}
break;
case 5:
if ((u8)((BYTE2(__gxVerif->xfRegs[15]) >> 4) & 1) || (u8)((BYTE2(__gxVerif->xfRegs[17]) >> 4) & 1)) {
lightUsed = 1;
}
break;
case 6:
if ((u8)((BYTE2(__gxVerif->xfRegs[15]) >> 5) & 1) || (u8)((BYTE2(__gxVerif->xfRegs[17]) >> 5) & 1)) {
lightUsed = 1;
}
break;
case 7:
if ((u8)((BYTE2(__gxVerif->xfRegs[15]) >> 6) & 1) || (u8)((BYTE2(__gxVerif->xfRegs[17]) >> 6) & 1)) {
lightUsed = 1;
}
break;
}
if (lightUsed != 0) {
CheckLight(i);
haveLight = 1;
}
}
if (haveLight != 0) {
if (!((BYTE2(__gxVerif->xfRegs[15]) >> 2) & 1) && ((HIWORD(__gxVerif->xfRegs[15]) >> 7) & 3) && __gxVerif->verifyLevel >= __gxvWarnLev[0x59]) {
__GX_WARNF(0x59, "COLOR1", "COLOR1");
}
if (!((BYTE2(__gxVerif->xfRegs[17]) >> 2) & 1) && ((HIWORD(__gxVerif->xfRegs[17]) >> 7) & 3) && __gxVerif->verifyLevel >= __gxvWarnLev[0x59]) {
__GX_WARNF(0x59, "ALPHA1", "ALPHA1");
}
if (((HIWORD(__gxVerif->xfRegs[15]) >> 7) & 3)
|| ((u8)((BYTE2(__gxVerif->xfRegs[15]) >> 1) & 1) && ((u32)((BYTE2(__gxVerif->xfRegs[15]) >> 2) & 1) == 1))
|| ((HIWORD(__gxVerif->xfRegs[17]) >> 7) & 3)
|| ((u8)((BYTE2(__gxVerif->xfRegs[17]) >> 1) & 1) && ((u32)((BYTE2(__gxVerif->xfRegs[17]) >> 2) & 1) == 1))) {
if ((__GXVertexPacketHas(GX_VA_NRM) == 0) && (__GXVertexPacketHas(GX_VA_NBT) == 0) && __gxVerif->verifyLevel >= __gxvWarnLev[0x5A]) {
__GX_WARNF(0x5A, 1);
}
if (__GXVertexPacketHas(GX_VA_PNMTXIDX) == 0) {
if ((u32)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F) > 30 && __gxVerif->verifyLevel >= __gxvWarnLev[0x5B]) {
__GX_WARNF(0x5B, 1, (u8)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F));
}
sprintf(Preamble, __gxvWarnings[0x6D], 1, (u8)(BYTE3(__gxVerif->xfRegs[24]) & 0x3F));
CheckRAM(1, ((BYTE3(__gxVerif->xfRegs[24]) & 0x3F) * 3) + 0x400, 9, 0x6D, Preamble);
}
}
}
}
}
}
static void CheckViewport(void) {
f32 vl;
f32 vr;
f32 vt;
f32 vb;
vl = (*(f32*)&__gxVerif->xfRegs[29] - *(f32*)&__gxVerif->xfRegs[26]) - 342.0f;
vt = (*(f32*)&__gxVerif->xfRegs[30] + *(f32*)&__gxVerif->xfRegs[27]) - 342.0f;
vr = (*(f32*)&__gxVerif->xfRegs[29] + *(f32*)&__gxVerif->xfRegs[26]) - 342.0f;
vb = (*(f32*)&__gxVerif->xfRegs[30] - *(f32*)&__gxVerif->xfRegs[27]) - 342.0f;
if ((vt < -0.5f || vt > 528.0f) && __gxVerif->verifyLevel >= __gxvWarnLev[0x55]) {
__GX_WARNF(0x55, vt);
}
if ((vb < 0.0f || vb > 528.0f) && __gxVerif->verifyLevel >= __gxvWarnLev[0x56]) {
__GX_WARNF(0x56, vb);
}
if ((vl < 0.0f || vl > 640.0f) && __gxVerif->verifyLevel >= __gxvWarnLev[0x57]) {
__GX_WARNF(0x57, vl);
}
if ((vr < 0.0f || vr > 640.0f) && __gxVerif->verifyLevel >= __gxvWarnLev[0x58]) {
__GX_WARNF(0x58, vr);
}
}
static void ComputeSignExponentMantissa(f32 floatVal, u32* sign, u32* exponent, u32* mantissa) {
u32 intVal = *(u32*)&floatVal;
*sign = (intVal >> 31) & 1;
*exponent = (intVal >> 23) & 0xFF;
*mantissa = intVal & 0x7FFFFF;
}
static void CheckFloatingPointValue(u8 dirtyBit, u32 value, char* label) {
u32 sign;
u32 exponent;
u32 mantissa;
f32 valuef;
&valuef;
if ((dirtyBit == 0)) {
return;
}
valuef = *(f32 *)&value;
ComputeSignExponentMantissa(valuef, &sign, &exponent, &mantissa);
if (exponent == 0 && mantissa == 0) {
return;
}
if (exponent == 0xFF) {
if (__gxVerif->verifyLevel >= 2) {
if (mantissa == 0) {
if (sign != 0) {
if (__gxVerif->verifyLevel >= __gxvWarnLev[0x5C]) {
__GX_WARNF(0x5C, label, "-", *(u32 *)&valuef);
}
} else {
if (__gxVerif->verifyLevel >= __gxvWarnLev[0x5C]) {
__GX_WARNF(0x5C, label, "+", *(u32 *)&valuef);
}
}
} else {
if (__gxVerif->verifyLevel >= __gxvWarnLev[0x5D]) {
__GX_WARNF(0x5D, label, *(u32 *)&valuef);
}
}
}
} else if (__gxVerif->verifyLevel >= 3) {
if (exponent < 0x6BU) {
if (__gxVerif->verifyLevel >= __gxvWarnLev[0x5E]) {
__GX_WARNF(0x5E, label, valuef, *(u32 *)&valuef);
}
} else if (exponent > 0x96U) {
if (__gxVerif->verifyLevel >= __gxvWarnLev[0x5F]) {
__GX_WARNF(0x5F, label, valuef, *(u32 *)&valuef);
}
}
}
}
static void CheckMatrixRAMRanges(void) {
u32 i;
char label[256];
for (i = 0; i <= 255; i++) {
sprintf(label, "Geometry/Texture Matrix ram address 0x%04x", i);
CheckFloatingPointValue(__gxVerif->xfMtxDirty[i], __gxVerif->xfMtx[i], label);
}
}
static void CheckNormalRAMRanges(void) {
u32 i;
char label[256];
for (i = 1024; i <= 1119; i++) {
sprintf(label, "Normal Matrix ram address 0x%04x", i);
CheckFloatingPointValue(__gxVerif->xfNrmDirty[i - 1024], __gxVerif->xfNrm[i - 1024], label);
}
}
static void CheckDMatrixRAMRanges(void) {
u32 i;
char label[256];
for (i = 1280; i <= 1535; i++) {
sprintf(label, "Dual Texture Matrix ram address 0x%04x", i);
CheckFloatingPointValue(__gxVerif->xfDMtxDirty[i - 1280], __gxVerif->xfDMtx[i - 1280], label);
}
}
static void CheckLightRAMRanges(void) {
u32 lightSource;
u32 lightRAMOffset;
char label[256];
u32 i;
for (lightSource = 0; lightSource < 8; lightSource++) {
for (i = 1; i < 13; i++) {
lightRAMOffset = ((lightSource << 4) + i) + 0x603;
sprintf(label, "Light %d %s (address 0x%04x)", lightSource, lightRegisterNames[i], lightRAMOffset);
CheckFloatingPointValue(__gxVerif->xfLightDirty[lightRAMOffset - 0x600], __gxVerif->xfLight[(s32) (lightRAMOffset - 0x600)], label);
}
}
i; lightSource; // needed to match
}
static void CheckControlRAMRanges(void) {
CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x1A], __gxVerif->xfRegs[0x1A], "Viewport Scale X");
CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x1B], __gxVerif->xfRegs[0x1B], "Viewport Scale Y");
CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x1C], __gxVerif->xfRegs[0x1C], "Viewport Scale Z");
CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x1D], __gxVerif->xfRegs[0x1D], "Viewport Offset X");
CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x1E], __gxVerif->xfRegs[0x1E], "Viewport Offset Y");
CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x1F], __gxVerif->xfRegs[0x1F], "Viewport Offset Z");
CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x20], __gxVerif->xfRegs[0x20], "Projection Matrix A Value");
CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x21], __gxVerif->xfRegs[0x21], "Projection Matrix B Value");
CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x22], __gxVerif->xfRegs[0x22], "Projection Matrix C Value");
CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x23], __gxVerif->xfRegs[0x23], "Projection Matrix D Value");
CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x24], __gxVerif->xfRegs[0x24], "Projection Matrix E Value");
CheckFloatingPointValue(__gxVerif->xfRegsDirty[0x25], __gxVerif->xfRegs[0x25], "Projection Matrix F Value");
}
static void CheckFloatingPointRanges(void) {
CheckMatrixRAMRanges();
CheckNormalRAMRanges();
CheckDMatrixRAMRanges();
CheckLightRAMRanges();
CheckControlRAMRanges();
}
static void CheckMatrixIndices(void) {
if (!__GXVertexPacketHas(GX_VA_PNMTXIDX)
|| !__GXVertexPacketHas(GX_VA_TEX0MTXIDX)
|| !__GXVertexPacketHas(GX_VA_TEX1MTXIDX)
|| !__GXVertexPacketHas(GX_VA_TEX2MTXIDX)
|| !__GXVertexPacketHas(GX_VA_TEX3MTXIDX))
{
CheckDirty(0x1018U, "Geometry & Textures [0-3] transform matrix indices");
}
if (__gxVerif->verifyLevel >= 1 && !__GXVertexPacketHas(GX_VA_PNMTXIDX)) {
CheckRAM(0U, (__gxVerif->xfRegs[24] * 4) & 0xFC, 0xCU, 0x6E, __gxvWarnings[0x6E]);
}
if ((!__GXVertexPacketHas(GX_VA_TEX4MTXIDX)
|| !__GXVertexPacketHas(GX_VA_TEX5MTXIDX)
|| !__GXVertexPacketHas(GX_VA_TEX6MTXIDX)
|| !__GXVertexPacketHas(GX_VA_TEX7MTXIDX))
&& numRegularTextures > 4
&& __gxVerif->verifyLevel >= 1
&& !__gxVerif->xfRegsDirty[0x19] && __gxVerif->verifyLevel >= __gxvWarnLev[0x60]) {
__GX_WARNF(0x60, numRegularTextures, 0x1019U);
}
}
static void CheckErrors(void) {
u32 i;
char registerName[80];
CheckDirty(0x103FU, "Number of XF output textures");
CheckDirty(0x1009U, "Number of XF output colors");
CheckDirty(0x1008U, "InVertexSpec");
CheckDirty(0x101AU, "Viewport ScaleX");
CheckDirty(0x101BU, "Viewport ScaleY");
CheckDirty(0x101CU, "Viewport ScaleZ");
CheckDirty(0x101DU, "Viewport OffsetX");
CheckDirty(0x101EU, "Viewport OffsetY");
CheckDirty(0x101FU, "Viewport OffsetZ");
CheckDirty(0x1020U, "Projection matrix 'A' value");
CheckDirty(0x1021U, "Projection matrix 'B' value");
CheckDirty(0x1022U, "Projection matrix 'C' value");
CheckDirty(0x1023U, "Projection matrix 'D' value");
CheckDirty(0x1024U, "Projection matrix 'E' value");
CheckDirty(0x1025U, "Projection matrix 'F' value");
CheckDirty(0x1026U, "Projection matrix orthographic/perspective select");
CheckMatrixIndices();
if (__gxVerif->verifyLevel >= 1) {
if (!(u32)(BYTE3(__gxVerif->xfRegs[9]) & 3) && !__gxVerif->xfRegs[0x3F] && __gxVerif->verifyLevel >= __gxvWarnLev[0x38]) {
__GX_WARN(0x38);
}
CheckCTGColors();
if (__gxVerif->xfRegs[0x3F] > 8 && __gxVerif->verifyLevel >= __gxvWarnLev[0x64]) {
__GX_WARNF(0x64, __gxVerif->xfRegs[0x3F], 8);
}
if (numRegularTextures > 8 && __gxVerif->verifyLevel >= __gxvWarnLev[0x65]) {
__GX_WARNF(0x65, numRegularTextures, 8);
}
if (numBumpmapTextures > 3 && __gxVerif->verifyLevel >= __gxvWarnLev[0x66]) {
__GX_WARNF(0x66, numBumpmapTextures, 3);
}
if (numColorTextures > 2 && __gxVerif->verifyLevel >= __gxvWarnLev[0x67]) {
__GX_WARNF(0x67, numColorTextures, 2);
}
if (numColor0Textures > 1 && __gxVerif->verifyLevel >= __gxvWarnLev[0x69]) {
__GX_WARNF(0x69, 0);
}
if (numColor1Textures > 1 && __gxVerif->verifyLevel >= __gxvWarnLev[0x69]) {
__GX_WARNF(0x69, 1);
}
CheckVertexPacket();
for (i = 0; i < __gxVerif->xfRegs[0x3F]; i++) {
sprintf(registerName, "Texture %d settings", i);
CheckDirty(i + 0x1040, registerName);
}
CheckSourceRows();
CheckTextureOrder();
if (numBumpmapTextures != 0) {
CheckBumpmapTextures();
}
CheckTextureTransformMatrices();
if (numColorTextures != 0 && (u32)((BYTE3(__gxVerif->xfRegs[numRegularTextures + numBumpmapTextures + 64]) >> 4) & 7) != 2 && __gxVerif->verifyLevel >= __gxvWarnLev[0x68]) {
__GX_WARN(0x68U);
}
CheckColor0();
CheckColor1();
CheckViewport();
}
}
static void CheckWarnings(void) {
if (__gxVerif->verifyLevel >= 1) {
CheckInputForms();
}
CheckClean(0x1000U, "Internal error register");
CheckClean(0x1001U, "Internal diagnostic register");
CheckClean(0x1002U, "Internal state register 0");
CheckClean(0x1003U, "Internal state register 1");
CheckClean(0x1004U, "Power savings register");
if (__gxVerif->verifyLevel >= 2) {
CheckFloatingPointRanges();
}
}
static void DumpXFRegisters(void) {
static u8 firstTime = 1;
}
void __GXVerifyXF(void) {
InitializeXFVerifyData();
CheckErrors();
CheckWarnings();
DumpCount++;
}
#endif
+372
View File
@@ -0,0 +1,372 @@
#if DEBUG
#include <revolution/gx.h>
#include "__gx.h"
static __GXVerifyData __gxVerifData;
struct __GXVerifyData* __gxVerif = &__gxVerifData;
char* __gxvWarnings[126] = {
"Invalid Vertex Format. Normal count must be set to %s.",
"Texture size %ld not initialized.",
"Left edge of scissor rectangle is less than %d.",
"Top edge of scissor rectangle is less than %d.",
"Right edge of scissor rectangle is greater than %d in %s mode.",
"Bottom edge of scissor rectangle is greater than %d in %s mode.",
"%s value for subsample %d in pixel %ld is not 6 when single-sampling.",
"Indirect texture command for stage %ld is not set.",
"Invalid indirect texture request in TEV stage %ld.",
"Indirect matrix %ld requested in stage %d not set.",
"Requested indirect textures never initialized.",
"Indirect texture coordinate scales %d and %d not set.",
"Invalid texture coordinate specified for indirect stage %d.",
"Indirect texture feedback accumulation is on in TEV stage 0.",
"Indirect bump alpha is enabled in TEV stage 0.",
"Indirect vs. direct mask byte never set.",
"Texture reference never written for TEV stage %ld.",
"Invalid texture coordinate specified for TEV stage %ld.",
"Texture %ld is used as both indirect and direct.",
"Texture %ld not configured.",
"Base pointer for cached texture %ld is not specified.",
"TLUT for indexed texture %ld was never set up.",
"%s is not a power of 2 for mipmapped texture %ld.",
"%s is not GX_CLAMP for non-power-of-2 width in texture %ld.",
"Minification filter for texture %ld is not compatible with color index texture format.",
"Minimum LOD is greater than maximum LOD in texture %ld.",
"Maximum LOD is greater than image's maximum LOD for texture %ld.",
"LOD bias clamp shold be used with edge LOD for texture %ld.",
"Texture %ld does not meet requirements for anisotropic mipmapping.",
"Filters are not linear for field prediction in texture %ld.",
"Incomplete rounding mode configuration for texture %ld.",
"Rounding color indexed texture %ld.",
"Environment for TEV stage %ld not fully set up.",
"Invalid color channel selected in TEV stage %ld.",
"Argument %s selects null texture in TEV color stage %ld.",
"Argument %s selects null texture in TEV alpha stage %ld.",
"Color arg %s in TEV stage %ld accesses register %s, which may be dirty.",
"Alpha arg %s in TEV stage %ld accesses register %s, which may be dirty.",
"Color arg %s in TEV stage %ld accesses register %s, which was last unclamped. Possible wrap-around effect.",
"Alpha arg %s in TEV stage %ld accesses register %s, which was last unclamped. Possible wrap-around effect.",
"Z texturing enabled, but no Z offset specified.",
"Z texturing enabled, but no texture specified for final TEV stage.",
"Final TEV stage doesn't write color to register GX_TEVPREV.",
"Final TEV stage doesn't write alpha to register GX_TEVPREV.",
"Final TEV color stage has no clamping. Possible color wrap-around effect.",
"Final TEV alpha stage has no clamping. Possible alpha wrap-around effect.",
"Z buffering is before texture, but alpha compare operation is active.",
"PE blend and logicop are both on.",
"Selected pixel format does not support dithering.",
"Multisample enabled but pixel type is not RGB565.",
"Pixel type is RGB565 but multisample is not enabled.",
"Multisample locations for pixel %ld are not ordered correctly for antialias filter.",
"Invalid texgen_type %d for texture %d.",
"Register address 0x%04x uninitialized (%s).",
"Register address 0x%04x modified (%s), probably should not be.",
"Invalid combination of %d output color channels and %d color texgen textures.",
"Number of color channels and number of texgens are both zero.",
"Vertex packet does not contain position values.",
"Mismatched argument setting in vertex attribute. %s should be used with %s.",
"GXSetVtxAttrFmt: Normals only support signed types.",
"GXSetVtxAttrFmt: Number of fractional bits is fixed for normals. %s uses %d. Your setting will be ignored.",
"GXSetVtxAttrFmt: GX_F32 type doesn't refer the frac argument. Your setting will be ignored.",
"GXSetVtxAttrFmt: Colors don't refer the frac argument. Your setting will be ignored.",
"Invalid value (%d) for INVERTEXSPEC_REG.host_colors.",
"XF is not expecting host normals but cp is sending them.",
"XF is not expecting host normals, binormals and tangents but cp is sending them.",
"XF is expecting host normals but cp is not sending them.",
"XF is expecting host normals but cp is sending normals, binormals, and tangents.",
"XF is expecting host normals, binormals and tangents but cp is only sending normals.",
"This vertex format (Position + Matrix Indices only) is not supported.",
"VCD for GX_VA_CLR1 is activated though GX_VA_CLR0 is set to GX_NONE. GX_VA_CLR0 should be used first.",
"VCDs for input texture coordinates are not used sequentially from smaller IDs.",
"GX_TEXCOORD%d specifies source row of position, but this is not getting sent.",
"GX_TEXCOORD%d specifies source row of normal, but this is not getting sent.",
"GX_TEXCOORD%d specifies source row of color0, but color0 is not getting sent.",
"GX_TEXCOORD%d specifies source row of color1, but color1 is not getting sent.",
"GX_TEXCOORD%d specifies source row of binormal or tangent, but this is not getting sent.",
"GX_TEXCOORD%d specifies source row of input texture coordinate %d, but this is not getting sent.",
"GX_TEXCOORD%d is specifying an invalid source row of %d.",
"TexCoordGen types are out of order. GX_TG_MTX2x4/3x4 should come first (if any), followed by GX_TG_BUMP (if any), then GX_TG_SRTG (if any).",
"Bumpmap texgen is defined, which requires that binormals and tangents be transformed by a normal matrix, but current matrix index is set to an invalid value (%d) for normal transform.",
"GX_TEXCOORD%d (texgen type bumpmap) is referencing texture %d as a source texture, which is not of texgen type regular.",
"GX_TEXCOORD%d (texgen type bumpmap) using light source %d, but light's %c position is not defined.",
"GX_TEXCOORD%d is defined as texgen type bumpmap, but binormals and tangents are not getting sent.",
"Invalid regular texture number (%d)",
"Top edge of viewport (%f) is out of recommended range. It may cause incorrect clipping.",
"Bottom edge of viewport (%f) is out of recommended range. It may cause incorrect clipping.",
"Left edge of viewport (%f) is out of recommended range. It may cause incorrect clipping.",
"Right edge of viewport (%f) is out of recommended range. It may cause incorrect clipping.",
"Channel %s uses specular function (GX_AF_SPEC), but diffuse function is not GX_DF_NONE.",
"Channel %d performs lighting which requires a normal, but this is not getting sent.",
"Channel %d performs lighting which requires the normal to be transformed by a normal matrix, but current matrix index is (%d), which may be invalid.",
"%s has a value of %sinfinity (%08x), which is probably not intended.",
"%s has a value of NaN (%08x), which is probably not intended.",
"%s has a value of (%f 0x%08x), which might be unintentionally small.",
"%s has a value of (%f 0x%08x), which might be unintentionally large.",
"%d regular textures active, but MatrixIndex1 register (0x%04x) uninitialized.",
"gen_mode register not initialized.",
"Number of XF output textures does not match what downstream units are expecting.",
"Number of XF output colors does not match what downstream units are expecting.",
"Number of all texgens (%d) > max allowed %d.",
"Number of regular(2x4/3x4) type texgens (%d) > max allowed %d.",
"Number of bumpmap type texgens (%d) > max allowed %d.",
"Number of color texgens (%d) > max allowed %d.",
"First color texgen is not referencing COLOR0.",
"Color texgen from COLOR%d is used more than once.",
"Bumpmap texgen is defined, which requires the normal matrix values pointed by current matrix index (%d) to be loaded, however it may not be loaded yet.",
"GX_TEXCOORD%d requires the matrix values pointed by current texture matrix index %d (%d), however it may not be loaded yet.",
"GX_LIGHT%d is being referenced, however it may not be loaded yet.",
"Channel %d performs lighting which requires the normal matrix values pointed to by the current matrix index (%d), however these values may not be loaded yet.",
"Position matrix values pointed to by the current matrix index must be loaded, however they may not be loaded yet.",
"Address 0x%04x is uninitialized.",
"Register (0x%04x) (%s) is not initialized.",
"Display list contains invalid command.",
"Nested display list.",
"GXGetCPUFifo/GXGetGPFifo: GP FIFO read pointer is not idle. Value may be unstable.",
"XF is not expecting host colors but cp is sending some.",
"XF is expecting a host color but cp is not sending one.",
"XF is expecting a single host color but cp is sending two.",
"XF is expecting two host colors but cp is not sending first color.",
"XF is expecting two host colors but cp is not sending second color.",
"Invalid number of output colors, %d.",
"Regular texture %d specifying a source row of %d which only has 2 elements, but an input form of ABC1.",
"Output XF colors or color textures enabled, but register address 0x%04x uninitialized (%s).",
"Output XF colors or color textures enabled, COLOR%dCNTRL_REG.material_src == REGISTER, but Material %d register (0x%04x) is not initialized.",
"Output XF colors or color textures enabled, COLOR%dCNTRL_REG.ambient_src == REGISTER, but Ambient %d register (0x%04x) is not initialized."
};
GXWarningLevel __gxvWarnLev[126] = {
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
4,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
4,
4,
GX_WARN_SEVERE,
GX_WARN_ALL,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
4,
4,
4,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_ALL,
GX_WARN_ALL,
4,
GX_WARN_SEVERE,
GX_WARN_MEDIUM,
GX_WARN_MEDIUM,
GX_WARN_ALL,
GX_WARN_ALL,
GX_WARN_MEDIUM,
4,
4,
4,
4,
GX_WARN_ALL,
4,
4,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_ALL,
GX_WARN_ALL,
GX_WARN_ALL,
4,
4,
4,
4,
4,
4,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
4,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
4,
GX_WARN_MEDIUM,
GX_WARN_MEDIUM,
GX_WARN_MEDIUM,
GX_WARN_MEDIUM,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_MEDIUM,
GX_WARN_MEDIUM,
GX_WARN_MEDIUM,
GX_WARN_ALL,
GX_WARN_ALL,
GX_WARN_SEVERE,
4,
4,
4,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_MEDIUM,
GX_WARN_MEDIUM,
GX_WARN_MEDIUM,
GX_WARN_MEDIUM,
GX_WARN_MEDIUM,
GX_WARN_MEDIUM,
GX_WARN_MEDIUM,
GX_WARN_SEVERE,
GX_WARN_SEVERE,
GX_WARN_MEDIUM,
4,
4,
4,
4,
4,
4,
4,
4,
4,
4,
};
char __gxvDummyStr[256];
static void __GXVerifyGlobal(void) {}
static void __GXVerifyCP(GXVtxFmt fmt) {
u32 nrmCnt = GET_REG_FIELD(__GXData->vatA[fmt], 1, 9);
if (__gxVerif->verifyLevel >= GX_WARN_SEVERE) {
if (__GXData->hasNrms && nrmCnt != 0) {
if (__gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_INVALID_VTX_FMT]) {
__GX_WARNF(GXWARN_INVALID_VTX_FMT, "GX_NRM_XYZ");
}
}
else if (__GXData->hasBiNrms && nrmCnt != 1) {
if (__gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_INVALID_VTX_FMT]) {
__GX_WARNF(GXWARN_INVALID_VTX_FMT, "GX_NRM_NBT or GX_NRM_NBT3");
}
}
}
}
void __GXVerifyState(GXVtxFmt vtxfmt) {
if (__gxVerif->verifyLevel != GX_WARN_NONE) {
__GXVerifyGlobal();
__GXVerifyCP(vtxfmt);
__GXVerifyXF();
__GXVerifySU();
__GXVerifyBUMP();
__GXVerifyTEX();
__GXVerifyTEV();
__GXVerifyPE();
}
}
void __GXVerifyVATImm(GXAttr attr, GXCompCnt cnt, GXCompType type, u8 frac) {
if (__gxVerif->verifyLevel != GX_WARN_NONE) {
if (attr == GX_VA_CLR0 || attr == GX_VA_CLR1) {
switch (type) {
case GX_RGB565:
case GX_RGB8:
case GX_RGBX8:
if (cnt != GX_CLR_RGB && __gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_VAT_MISMATCH]) {
__GX_WARNF(GXWARN_VAT_MISMATCH, "RGB format type", "GX_CLR_RGB");
}
break;
case GX_RGBA4:
case GX_RGBA6:
case GX_RGBA8:
if (cnt != GX_CLR_RGBA && __gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_VAT_MISMATCH]) {
__GX_WARNF(GXWARN_VAT_MISMATCH, "RGBA format type", "GX_CLR_RGBA");
}
break;
}
}
if (frac != 0) {
if (attr == GX_VA_CLR0 || attr == GX_VA_CLR1) {
if (__gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_VAT_CLR_FRAC]) {
__GX_WARN(GXWARN_VAT_CLR_FRAC);
}
} else if (type == GX_F32) {
if (__gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_VAT_F32_FRAC]) {
__GX_WARN(GXWARN_VAT_F32_FRAC);
}
}
}
if (attr == GX_VA_NRM || attr == GX_VA_NBT) {
switch (type) {
case GX_S8:
if (frac != 6 && __gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_VAT_NRM_FRAC]) {
__GX_WARNF(GXWARN_VAT_NRM_FRAC, "GX_S8", 6);
}
break;
case GX_S16:
if (frac != 14 && __gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_VAT_NRM_FRAC]) {
__GX_WARNF(GXWARN_VAT_NRM_FRAC, "GX_S16", 14);
}
break;
case GX_F32:
break;
default:
if (__gxVerif->verifyLevel >= __gxvWarnLev[GXWARN_VAT_NRM_TYPE]) {
__GX_WARN(GXWARN_VAT_NRM_TYPE);
}
break;
}
}
}
}
void GXSetVerifyLevel(GXWarningLevel level) {
__gxVerif->verifyLevel = level;
}
GXVerifyCallback GXSetVerifyCallback(GXVerifyCallback cb) {
GXVerifyCallback old_cb = __gxVerif->cb;
__gxVerif->cb = cb;
return old_cb;
}
#endif // DEBUG
+86
View File
@@ -0,0 +1,86 @@
#if DEBUG
#include <revolution/gx.h>
#include "__gx.h"
#define FUNC_1PARAM(name, T) \
void name##1##T(T x) { GXWGFifo.T = x; }
#define FUNC_2PARAM(name, T) \
void name##2##T(T x, T y) { GXWGFifo.T = x; GXWGFifo.T = y; }
#define FUNC_3PARAM(name, T) \
void name##3##T(T x, T y, T z) { GXWGFifo.T = x; GXWGFifo.T = y; GXWGFifo.T = z; }
#define FUNC_4PARAM(name, T) \
void name##4##T(T x, T y, T z, T w) { GXWGFifo.T = x; GXWGFifo.T = y; GXWGFifo.T = z; GXWGFifo.T = w; }
#define FUNC_INDEX8(name) \
void name##1x8(u8 x) { GXWGFifo.u8 = x; }
#define FUNC_INDEX16(name) \
void name##1x16(u16 x) { GXWGFifo.u16 = x; }
// GXCmd
FUNC_1PARAM(GXCmd, u8)
FUNC_1PARAM(GXCmd, u16)
FUNC_1PARAM(GXCmd, u32)
// GXParam
FUNC_1PARAM(GXParam, u8)
FUNC_1PARAM(GXParam, u16)
FUNC_1PARAM(GXParam, u32)
FUNC_1PARAM(GXParam, s8)
FUNC_1PARAM(GXParam, s16)
FUNC_1PARAM(GXParam, s32)
FUNC_1PARAM(GXParam, f32)
FUNC_3PARAM(GXParam, f32)
FUNC_4PARAM(GXParam, f32)
// GXPosition
FUNC_3PARAM(GXPosition, f32)
FUNC_3PARAM(GXPosition, u8)
FUNC_3PARAM(GXPosition, s8)
FUNC_3PARAM(GXPosition, u16)
FUNC_3PARAM(GXPosition, s16)
FUNC_2PARAM(GXPosition, f32)
FUNC_2PARAM(GXPosition, u8)
FUNC_2PARAM(GXPosition, s8)
FUNC_2PARAM(GXPosition, u16)
FUNC_2PARAM(GXPosition, s16)
FUNC_INDEX16(GXPosition)
FUNC_INDEX8(GXPosition)
// GXNormal
FUNC_3PARAM(GXNormal, f32)
FUNC_3PARAM(GXNormal, s16)
FUNC_3PARAM(GXNormal, s8)
FUNC_INDEX16(GXNormal)
FUNC_INDEX8(GXNormal)
// GXColor
FUNC_4PARAM(GXColor, u8)
FUNC_1PARAM(GXColor, u32)
FUNC_3PARAM(GXColor, u8)
FUNC_1PARAM(GXColor, u16)
FUNC_INDEX16(GXColor)
FUNC_INDEX8(GXColor)
// GXTexCoord
FUNC_2PARAM(GXTexCoord, f32)
FUNC_2PARAM(GXTexCoord, s16)
FUNC_2PARAM(GXTexCoord, u16)
FUNC_2PARAM(GXTexCoord, s8)
FUNC_2PARAM(GXTexCoord, u8)
FUNC_1PARAM(GXTexCoord, f32)
FUNC_1PARAM(GXTexCoord, s16)
FUNC_1PARAM(GXTexCoord, u16)
FUNC_1PARAM(GXTexCoord, s8)
FUNC_1PARAM(GXTexCoord, u8)
FUNC_INDEX16(GXTexCoord)
FUNC_INDEX8(GXTexCoord)
// GXMatrixIndex
FUNC_1PARAM(GXMatrixIndex, u8)
#endif // DEBUG
+573
View File
@@ -0,0 +1,573 @@
#ifndef _REVOLUTION_GX_INTERNAL_H_
#define _REVOLUTION_GX_INTERNAL_H_
#include <revolution/gx.h>
#include <revolution/private/GXRegs.h>
#include "global.h" // IWYU pragma: export
#ifdef __cplusplus
extern "C" {
#endif
#define PHY_ADDR_MASK ~((~0x3FFF) << 16)
#define GX_PHY_ADDR(a) ((u32)a & PHY_ADDR_MASK)
// REG VERIF
#if DEBUG
#define VERIF_XF_REG(addr, value) \
do { \
s32 regAddr = (addr - 0x1000); \
if (regAddr >= 0 && regAddr < 0x50) { \
__gxVerif->xfRegs[regAddr] = (value); \
__gxVerif->xfRegsDirty[regAddr] = 1; \
} \
} while (0)
#define VERIF_XF_REG_alt(addr, value) \
do { \
s32 xfAddr = (addr); \
if (xfAddr >= 0 && xfAddr < 0x50) { \
__gxVerif->xfRegs[xfAddr] = (value); \
__gxVerif->xfRegsDirty[xfAddr] = 1; \
} \
} while (0)
#define VERIF_RAS_REG(value) (__gxVerif->rasRegs[((value) & 0xFF000000) >> 24] = value)
#define VERIF_MTXLIGHT(addr, data) \
do { \
s32 xfAddr; \
if (addr < 0x400U) { \
__gxVerif->xfMtx[addr] = data; \
__gxVerif->xfMtxDirty[addr] = 1; \
} else if (addr < 0x500U) { \
xfAddr = addr - 0x400; \
__gxVerif->xfNrm[xfAddr] = data; \
__gxVerif->xfNrmDirty[xfAddr] = 1; \
} else if (addr < 0x600U) { \
xfAddr = addr - 0x500; \
__gxVerif->xfDMtx[xfAddr] = data; \
__gxVerif->xfDMtxDirty[xfAddr] = 1; \
} else if (addr < 0x680U) { \
xfAddr = addr - 0x600; \
__gxVerif->xfLight[xfAddr] = data; \
__gxVerif->xfLightDirty[xfAddr] = 1; \
} else { \
xfAddr = addr - 0x1000; \
if ((xfAddr >= 0) && (xfAddr < 0x50)) { \
__gxVerif->xfRegs[xfAddr] = data; \
__gxVerif->xfRegsDirty[xfAddr] = 1; \
} \
} \
} while (0)
#else
#define VERIF_XF_REG(addr, value) ((void)0)
#define VERIF_XF_REG_alt(addr, value) ((void)0)
#define VERIF_RAS_REG(value) ((void)0)
#endif
// WRITE REG
#if DEBUG
#define GX_WRITE_XF_REG_2(addr, value) \
do { \
u32 xfData = (value); &xfData; \
GX_WRITE_U32(value); \
VERIF_XF_REG_alt(addr, xfData); \
} while (0)
#define GX_WRITE_XF_REG_F(addr, value) \
do { \
f32 xfData = (value); \
GX_WRITE_F32(value); \
VERIF_XF_REG_alt(addr, *(u32 *)&xfData); \
} while (0)
#else
#define GX_WRITE_XF_REG_2(addr, value) \
do { \
GX_WRITE_U32(value); \
} while (0)
#define GX_WRITE_XF_REG_F(addr, value) \
do { \
GX_WRITE_F32(value); \
} while (0)
#endif
#define GX_WRITE_RAS_REG(value) \
do { \
GX_WRITE_U8(0x61); \
GX_WRITE_U32(value); \
VERIF_RAS_REG(value); \
} while (0)
#if DEBUG
#define GX_WRITE_SOME_REG2(a, b, c, addr) \
do { \
long regAddr; \
GX_WRITE_U8(a); \
GX_WRITE_U8(b); \
GX_WRITE_U32(c); \
regAddr = addr; \
if (regAddr >= 0 && regAddr < 4) { \
__GXData->indexBase[regAddr] = c; \
} \
} while (0)
#else
#define GX_WRITE_SOME_REG2(a, b, c, addr) \
do { \
GX_WRITE_U8(a); \
GX_WRITE_U8(b); \
GX_WRITE_U32(c); \
} while (0)
#endif
#if DEBUG
#define GX_WRITE_SOME_REG3(a, b, c, addr) \
do { \
long regAddr; \
GX_WRITE_U8(a); \
GX_WRITE_U8(b); \
GX_WRITE_U32(c); \
regAddr = addr; \
if (regAddr >= 0 && regAddr < 4) { \
__GXData->indexStride[regAddr] = c; \
} \
} while (0)
#else
#define GX_WRITE_SOME_REG3(a, b, c, addr) \
do { \
GX_WRITE_U8(a); \
GX_WRITE_U8(b); \
GX_WRITE_U32(c); \
} while (0)
#endif
#define GX_WRITE_SOME_REG4(a, b, c, addr) \
do { \
long regAddr; \
GX_WRITE_U8(a); \
GX_WRITE_U8(b); \
GX_WRITE_U32(c); \
regAddr = addr; \
} while (0)
// REG MACROS
#define GET_REG_FIELD(reg, size, shift) ((((unsigned long)(reg)) & (((1 << (size)) - 1) << (shift))) >> (shift))
// TODO: reconcile reg macro differences
// this one is needed to match non GX libs
#define OLD_SET_REG_FIELD(line, reg, size, shift, val) \
do { \
ASSERTMSGLINE(line, ((u32)(val) & ~((1 << (size)) - 1)) == 0, "GX Internal: Register field out of range"); \
(reg) = ((u32)(reg) & ~(((1 << (size)) - 1) << (shift))) | ((u32)(val) << (shift)); \
} while (0)
// above doesn't seem to work with GX, only can get it to work with this
#define SET_REG_FIELD(line, reg, size, shift, val) \
do { \
ASSERTMSGLINE(line, ((u32)(val) & ~((1 << (size)) - 1)) == 0, "GX Internal: Register field out of range"); \
(reg) = ((u32)__rlwimi((u32)(reg), (val), (shift), 32 - (shift) - (size), 31 - (shift))); \
} while (0)
#define CHECK_GXBEGIN(line, name) ASSERTMSGLINE(line, !__GXinBegin, "'" name "' is not allowed between GXBegin/GXEnd")
/* GXAttr */
void __GXSetVCD(void);
void __GXSetVAT(void);
/* GXBump */
void __GXUpdateBPMask(void);
void __GXFlushTextureState(void);
/* GXFifo */
// GXFifoObj private data
typedef struct __GXFifoObj {
u8* base;
u8* top;
u32 size;
u32 hiWatermark;
u32 loWatermark;
void* rdPtr;
void* wrPtr;
s32 count;
u8 wrap;
u8 bind_cpu;
u8 bind_gp;
} __GXFifoObj;
void __GXFifoInit(void);
void __GXCleanGPFifo(void);
GXBool __GXIsGPFifoReady(void);
/* GXGeometry */
void __GXSetDirtyState(void);
void __GXSendFlushPrim(void);
void __GXSetGenMode(void);
/* GXInit */
void __GXInitGX();
void __GXInitRevisionBits(void);
typedef struct __GXData_struct {
u16 vNumNot;
u16 bpSentNot;
u16 vNum;
u16 vLim;
u32 cpEnable;
u32 cpStatus;
u32 cpClr;
u32 vcdLo;
u32 vcdHi;
u32 vatA[8];
u32 vatB[8];
u32 vatC[8];
u32 lpSize;
u32 matIdxA;
u32 matIdxB;
u32 indexBase[4];
u32 indexStride[4];
u32 ambColor[2];
u32 matColor[2];
u32 chanCtrl[4];
u32 texGenCtrl[8];
u32 texGenCtrl2[8];
u32 suTs0[8];
u32 suTs1[8];
u32 suScis0;
u32 suScis1;
u32 tref[8];
u32 iref;
u32 bpMask;
u32 IndTexScale0;
u32 IndTexScale1;
u32 tevc[16];
u32 teva[16];
u32 tevKsel[8];
u32 cmode0;
u32 cmode1;
u32 zmode;
u32 peCtrl;
u32 cpDispSrc;
u32 cpDispSize;
u32 cpDispStride;
u32 cpDisp;
u32 cpTexSrc;
u32 cpTexSize;
u32 cpTexStride;
u32 cpTex;
u8 cpTexZ;
u32 genMode;
GXTexRegion TexRegions0[8];
GXTexRegion TexRegions1[8];
GXTexRegion TexRegions2[8];
GXTlutRegion TlutRegions[20];
GXTexRegion* (*texRegionCallback)(GXTexObj*, GXTexMapID);
GXTlutRegion* (*tlutRegionCallback)(u32);
GXAttrType nrmType;
u8 hasNrms;
u8 hasBiNrms;
u32 projType;
f32 projMtx[6];
f32 vpLeft;
f32 vpTop;
f32 vpWd;
f32 vpHt;
f32 vpNearz;
f32 vpFarz;
f32 zOffset;
f32 zScale;
u32 tImage0[8];
u32 tMode0[8];
u32 texmapId[16];
u32 tcsManEnab;
u32 tevTcEnab;
GXPerf0 perf0;
GXPerf1 perf1;
u32 perfSel;
u8 inDispList;
u8 dlSaveContext;
u8 abtWaitPECopy;
u8 dirtyVAT;
u32 dirtyState;
} GXData;
extern GXData* const __GXData;
#if DEBUG
extern GXBool __GXinBegin;
#endif
#define GX_GET_MEM_REG(offset) (*(volatile u16*)((volatile u16*)(__memReg) + (offset)))
#define GX_GET_CP_REG(offset) (*(volatile u16*)((volatile u16*)(__cpReg) + (offset)))
#define GX_GET_PE_REG(offset) (*(volatile u16*)((volatile u16*)(__peReg) + (offset)))
#define GX_GET_PI_REG(offset) (*(volatile u32*)((volatile u32*)(__piReg) + (offset)))
#define GX_SET_MEM_REG(offset, val) (*(volatile u16*)((volatile u16*)(__memReg) + (offset)) = val)
#define GX_SET_CP_REG(offset, val) (*(volatile u16*)((volatile u16*)(__cpReg) + (offset)) = val)
#define GX_SET_PE_REG(offset, val) (*(volatile u16*)((volatile u16*)(__peReg) + (offset)) = val)
#define GX_SET_PI_REG(offset, val) (*(volatile u32*)((volatile u32*)(__piReg) + (offset)) = val)
/* GXMisc */
void __GXBypass(u32 reg);
u16 __GXReadPEReg(u32 reg);
void __GXPEInit(void);
void __GXAbort();
/* GXPerf */
void __GXSetBWDials(u16 cpDial, u16 tcDial, u16 peDial, u16 cpuRdDial, u16 cpuWrDial);
static inline u32 __GXReadCPCounterU32(u32 regAddrL, u32 regAddrH) {
u32 ctrH0;
u32 ctrH1;
u32 ctrL;
ctrH0 = GX_GET_CP_REG(regAddrH);
do {
ctrH1 = ctrH0;
ctrL = GX_GET_CP_REG(regAddrL);
ctrH0 = GX_GET_CP_REG(regAddrH);
} while (ctrH0 != ctrH1);
return (ctrH0 << 0x10) | ctrL;
}
static inline u32 __GXReadMEMCounterU32(u32 regAddrL, u32 regAddrH) {
u32 ctrH0;
u32 ctrH1;
u32 ctrL;
ctrH0 = GX_GET_MEM_REG(regAddrH);
do {
ctrH1 = ctrH0;
ctrL = GX_GET_MEM_REG(regAddrL);
ctrH0 = GX_GET_MEM_REG(regAddrH);
} while (ctrH0 != ctrH1);
return (ctrH0 << 0x10) | ctrL;
}
static inline u32 __GXReadPECounterU32(u32 regAddrL, u32 regAddrH) {
u32 ctrH0;
u32 ctrH1;
u32 ctrL;
ctrH0 = GX_GET_PE_REG(regAddrH);
do {
ctrH1 = ctrH0;
ctrL = GX_GET_PE_REG(regAddrL);
ctrH0 = GX_GET_PE_REG(regAddrH);
} while (ctrH0 != ctrH1);
return (ctrH0 << 0x10) | ctrL;
}
/* GXSave */
void __GXShadowDispList(void* list, u32 nbytes);
void __GXShadowIndexState(u32 idx_reg, u32 reg_data);
void __GXPrintShadowState(void);
/* GXStubs */
void __GXSetRange(f32 nearz, f32 fgSideX);
/* GXTexture */
void __GetImageTileCount(GXTexFmt fmt, u16 wd, u16 ht, u32* rowTiles, u32* colTiles, u32* cmpTiles);
void __GXSetSUTexRegs(void);
void __GXGetSUTexSize(GXTexCoordID coord, u16* width, u16* height);
void __GXSetTmemConfig(u32 config);
/* GXTransform */
void __GXSetMatrixIndex(GXAttr matIdxAttr);
void __GXSetProjection(void);
void __GXSetViewport();
/* GXVerifRAS */
void __GXVerifySU(void);
void __GXVerifyBUMP(void);
void __GXVerifyTEX(void);
void __GXVerifyTEV(void);
void __GXVerifyPE(void);
/* GXVerif */
typedef enum {
GXWARN_INVALID_VTX_FMT = 0,
GXWARN_TEX_SIZE_INIT = 1,
GXWARN_SCISSOR_RECT_LEFT = 2,
GXWARN_SCISSOR_RECT_TOP = 3,
GXWARN_SCISSOR_RECT_RIGHT = 4,
GXWARN_SCISSOR_RECT_BOT = 5,
GXWARN_SAMPLE_VALUE = 6,
GXWARN_BUMP_CMD = 7,
GXWARN_INVALID_INDIRECT = 8,
GXWARN_INDIRECT_MTX = 9,
GXWARN_IND_TEX_NO_INIT = 10,
GXWARN_IND_TEX_NO_SCALE = 11,
GXWARN_IND_TEX_BUMP = 12,
GXWARN_BUMP_ACCUMULATION = 13,
GXWARN_BUMP_ALPHA_EN = 14,
GXWARN_IND_DIR_MASK = 15,
GXWARN_TEV_TEX_REF = 16,
GXWARN_TEV_INV_TEX_COORD = 17,
GXWARN_IND_DIR_BOTH = 18,
GXWARN_TEX_CONFIG = 19,
GXWARN_TEX_BASE = 20,
GXWARN_TLUT_CONFIG = 21,
GXWARN_TEX_POW2 = 22,
GXWARN_TEX_CLAMP = 23,
GXWARN_TEX_MIN_FILT = 24,
GXWARN_MIN_LOD = 25,
GXWARN_MAX_LOD = 26,
GXWARN_DIAG_LOD = 27,
GXWARN_TEX_ANISO = 28,
GXWARN_TEX_FIELD = 29,
GXWARN_TEX_RND_FP = 30,
GXWARN_RND_CLR_INDX = 31,
GXWARN_TEV_ENV = 32,
GXWARN_TEV_INV_CHAN = 33,
GXWARN_TEV_NULL_TEX = 34,
GXWARN_TEV_NULL_TEX_A = 35,
GXWARN_TEV_DIRTY_REG = 36,
GXWARN_TEV_DIRTY_REG_A = 37,
GXWARN_TEV_CLR_CLAMP = 38,
GXWARN_TEV_A_CLAMP = 39,
GXWARN_ZTEX_OFFSET = 40,
GXWARN_ZTEX_INVALID = 41,
GXWARN_TEV_LAST_CLR = 42,
GXWARN_TEV_LAST_A = 43,
GXWARN_TEV_LAST_CLR_WRAP = 44,
GXWARN_TEV_LAST_A_WRAP = 45,
GXWARN_Z_BEFORE_T_A = 46,
GXWARN_BLEND_LOGICOP = 47,
GXWARN_DITHER_MODE = 48,
GXWARN_MULTISAMP0 = 49,
GXWARN_MULTISAMP1 = 50,
GXWARN_SAMP_ORDER = 51,
GXWARN_INVALID_TG_TYPE = 52,
GXWARN_XF_CTRL_UNINIT = 53,
GXWARN_XF_CTRL_INIT = 54,
GXWARN_INV_COLOR_TG_COMB = 55,
GXWARN_XF_NO_CLR_TEX = 56,
GXWARN_VTX_NO_GEOM = 57,
GXWARN_VAT_MISMATCH = 58,
GXWARN_VAT_NRM_TYPE = 59,
GXWARN_VAT_NRM_FRAC = 60,
GXWARN_VAT_F32_FRAC = 61,
GXWARN_VAT_CLR_FRAC = 62,
GXWARN_INV_IVS_CLR = 63,
GXWARN_NRM_XF0_CP1 = 64,
GXWARN_NRM_XF0_CP3 = 65,
GXWARN_NRM_XF1_CP0 = 66,
GXWARN_NRM_XF1_CP3 = 67,
GXWARN_NRM_XF3_CP1 = 68,
GXWARN_VCD_FMT_UNSUP = 69,
GXWARN_VCD_CLR_ORDER = 70,
GXWARN_VCD_TEX_ORDER = 71,
GXWARN_TEX_SRC_NPOS = 72,
GXWARN_TEX_SRC_NNRM = 73,
GXWARN_TEX_SRC_NCLR0 = 74,
GXWARN_TEX_SRC_NCLR1 = 75,
GXWARN_TEX_SRC_NNBT = 76,
GXWARN_TEX_SRC_NTEX = 77,
GXWARN_INV_TEX_SRC = 78,
GXWARN_INV_TG_ORDER = 79,
GXWARN_BM_INV_MTX_NDX = 80,
GXWARN_BM_INV_TEX = 81,
GXWARN_BM_INV_LIT_POS = 82,
GXWARN_BM_NO_NBT = 83,
GXWARN_INV_TEX_NUM = 84,
GXWARN_VIEWPORT_TOP = 85,
GXWARN_VIEWPORT_BOTTOM = 86,
GXWARN_VIEWPORT_LEFT = 87,
GXWARN_VIEWPORT_RIGHT = 88,
GXWARN_CLR_INV_SPEC = 89,
GXWARN_CLR_NO_NRM = 90,
GXWARN_CLR_INV_MTX_NDX = 91,
GXWARN_VAL_INFINITY = 92,
GXWARN_VAL_NAN = 93,
GXWARN_VAL_SMALL = 94,
GXWARN_VAL_LARGE = 95,
GXWARN_MTX1_UNINIT = 96,
GXWARN_GM_UNINIT = 97,
GXWARN_TEX_XFN_SUM = 98,
GXWARN_CLR_XFN_SUM = 99,
GXWARN_INV_NUM_ANY_TEX = 100,
GXWARN_INV_NUM_REG_TEX = 101,
GXWARN_INV_NUM_BM_TEX = 102,
GXWARN_INV_NUM_CLR_TEX = 103,
GXWARN_INV_CLR_TEX = 104,
GXWARN_DUP_CLR_TEX = 105,
GXWARN_BM_INV_MTX_VAL = 106,
GXWARN_TEX_INV_MTX_VAL = 107,
GXWARN_LIT_INV_REG = 108,
GXWARN_CLR_INV_MTX_VAL = 109,
GXWARN_INV_MTX_VAL = 110,
GXWARN_ADDR_UNINIT = 111,
GXWARN_REG_UNINIT = 112,
GXWARN_DL_INV_CMD = 113,
GXWARN_DL_NESTED = 114,
GXWARN_CLR_XF0_CP1 = 115,
GXWARN_CLR_XF1_CP0 = 116,
GXWARN_CLR_XF1_CP2 = 117,
GXWARN_CLR_XF2_CPN1 = 118,
GXWARN_CLR_XF2_CPN2 = 119,
GXWARN_INV_NUM_COLORS = 120,
GXWARN_INV_TG_SRC = 121,
GXWARN_CLR_ADDR_UNINIT = 122,
GXWARN_CLR_MAT_UNINIT = 123,
GXWARN_CLR_AMB_UNINIT = 124,
GXWARN_MAX = 125,
} GXWarnID;
#define __GX_WARN(id) (__gxVerif->cb(__gxvWarnLev[(id)], (id), __gxvWarnings[(id)]))
#define __GX_WARNF(id, ...) \
do { \
sprintf(__gxvDummyStr, __gxvWarnings[(id)], __VA_ARGS__); \
__gxVerif->cb(__gxvWarnLev[(id)], (id), __gxvDummyStr); \
} while (0)
#define __GX_WARN2(level, id) (__gxVerif->cb(level, (id), __gxvWarnings[(id)]))
#define __GX_WARN2F(level, id, ...) \
do { \
sprintf(__gxvDummyStr, __gxvWarnings[(id)], __VA_ARGS__); \
__gxVerif->cb(level, (id), __gxvDummyStr); \
} while (0)
typedef struct __GXVerifyData {
GXVerifyCallback cb;
GXWarningLevel verifyLevel;
u32 xfRegs[80];
u32 xfMtx[256];
u32 xfNrm[96];
u32 xfDMtx[256];
u32 xfLight[128];
u32 rasRegs[256];
u8 xfRegsDirty[80];
u8 xfMtxDirty[256];
u8 xfNrmDirty[96];
u8 xfDMtxDirty[256];
u8 xfLightDirty[128];
} __GXVerifyData;
extern __GXVerifyData* __gxVerif;
extern char* __gxvWarnings[126];
extern char __gxvDummyStr[256];
extern GXWarningLevel __gxvWarnLev[];
void __GXVerifyGlobal(void);
void __GXVerifyCP(GXVtxFmt fmt);
void __GXVerifyState(GXVtxFmt vtxfmt);
/* GXVerifXF */
void __GXVerifyXF(void);
#ifdef __cplusplus
}
#endif
#endif
+273
View File
@@ -0,0 +1,273 @@
#include <revolution/types.h>
#include <revolution/os.h>
#include <revolution/exi.h>
#include <revolution/hio2.h>
#include <revolution/hw_regs.h>
#ifdef SDK_AUG2010
#define BUILD_DATE "Aug 23 2010"
#if DEBUG
#define BUILD_TIME "17:28:30"
#else
#define BUILD_TIME "17:33:06"
#endif
#elif SDK_SEP2006
#define BUILD_DATE "Sep 21 2006"
#define BUILD_TIME "14:32:13"
#endif
#ifdef SDK_AUG2010
#if DEBUG
const char* __HIO2Version = "<< RVL_SDK - HIO2 \tdebug build: "BUILD_DATE" "BUILD_TIME" (0x4302_145) >>";
#else
const char* __HIO2Version = "<< RVL_SDK - HIO2 \trelease build: "BUILD_DATE" "BUILD_TIME" (0x4302_145) >>";
#endif
#elif SDK_SEP2006
const char* __HIO2Version = "<< RVL_SDK - HIO2 \trelease build: "BUILD_DATE" "BUILD_TIME" (0x4200_60422) >>";
#endif
HIO2Control __HIO2Control[2] = {
{HIO2_DEVICE_INVALID, -1, 0, NULL, NULL, NULL, NULL},
{HIO2_DEVICE_INVALID, -1, 0, NULL, NULL, NULL, NULL},
};
static u32 __HIO2ConsoleType;
static BOOL __HIO2Initialized;
static int __HIO2LastErrorCode;
static BOOL __HIO2IsInitialized();
static void __HIO2ClearChanInfo(s32 chan) {
__HIO2Control[chan].type = HIO2_DEVICE_INVALID;
__HIO2Control[chan].chan = -1;
__HIO2Control[chan]._0x8 = 0;
__HIO2Control[chan].exiCallback =
__HIO2Control[chan]._0x10 =
__HIO2Control[chan]._0x14 =
__HIO2Control[chan].disconnectCb = NULL;
}
static void __HIO2ExtHandler(s32 chan, OSContext* context) {
if (__HIO2Control[chan].disconnectCb != NULL) {
__HIO2Control[chan].disconnectCb(chan);
}
__HIO2ClearChanInfo(chan);
EXISetExiCallback(chan, NULL);
}
static void __HIO2ExiHandler(s32 chan, OSContext* context) {
if (chan == 2) {
chan = 0;
}
if (__HIO2Control[chan].exiCallback != NULL) {
__HIO2Control[chan].exiCallback(chan);
}
}
BOOL HIO2Init(void) {
if (__HIO2Initialized) {
HIO2Exit();
}
EXIWait();
__HIO2ConsoleType = EXIGetConsoleType();
if (!(__HIO2ConsoleType & 7)) {
__HIO2LastErrorCode = 6;
return FALSE;
}
__HIO2LastErrorCode = 0;
OSRegisterVersion(__HIO2Version);
return __HIO2Initialized = TRUE;
}
BOOL HIO2EnumDevices(HIO2EnumCallback callback) {
s32 chan;
u32 id;
ASSERTLINE(275, callback != NULL);
if (!__HIO2IsInitialized()) {
return FALSE;
}
if (__HIO2Control[0].chan != -1 && __HIO2Control[1].chan != -1) {
__HIO2LastErrorCode = 5;
return FALSE;
}
for (chan = 0; chan < 2; chan++) {
while (EXIProbeEx(chan) == 0) {}
if (EXIGetID(chan, 0, &id) != 0 && id == 0 && !callback(chan)) {
return TRUE;
}
}
if (__HIO2ConsoleType & 1) {
callback(2);
}
return TRUE;
}
static BOOL __HIO2IsInitialized(void) {
if (!__HIO2Initialized) {
__HIO2LastErrorCode = 1;
}
return __HIO2Initialized;
}
s32 HIO2Open(HIO2DeviceType type, HIO2UnkCallback exiCb, HIO2DisconnectCallback disconnectCb) {
s32 chan;
s32 device;
BOOL enabled;
u8 reg;
if (!__HIO2IsInitialized()) {
return -1;
}
switch (type) {
case HIO2_DEVICE_UNK_0:
case HIO2_DEVICE_UNK_1:
chan = type;
device = 0;
break;
case HIO2_DEVICE_UNK_2:
if (__HIO2ConsoleType & 1) {
chan = 0;
device = 1;
} else {
__HIO2LastErrorCode = 6;
return -1;
}
break;
default:
__HIO2LastErrorCode = 3;
return -1;
}
if (__HIO2Control[chan].chan != -1) {
__HIO2LastErrorCode = 4;
return -1;
}
if (device == 0) {
u32 id = 0;
while (EXIProbeEx(chan) == 0) {}
if (!EXIAttach(chan, __HIO2ExtHandler) || EXIGetID(chan, 0, &id) == 0 || id != 0) {
__HIO2LastErrorCode = 7;
return -1;
}
}
reg = 0xD8;
enabled = OSDisableInterrupts();
if (!EXIWriteReg(chan, device, 0xB4000000, &reg, 1)) {
if (device == 0) {
EXIDetach(chan);
}
__HIO2LastErrorCode = 8;
OSRestoreInterrupts(enabled);
return -1;
}
OSRestoreInterrupts(enabled);
__HIO2Control[chan].type = type;
__HIO2Control[chan]._0x8 = device;
__HIO2Control[chan].chan = chan;
__HIO2Control[chan].exiCallback = exiCb;
__HIO2Control[chan]._0x10 = NULL;
__HIO2Control[chan]._0x14 = NULL;
__HIO2Control[chan].disconnectCb = disconnectCb;
if (exiCb != NULL) {
if (type == HIO2_DEVICE_UNK_2) {
EXISetExiCallback(2, __HIO2ExiHandler);
} else {
EXISetExiCallback(chan, __HIO2ExiHandler);
}
}
return chan;
}
BOOL __HIO2IsValidHandle(s32 handle) {
if ((handle == 0 || handle == 1) && __HIO2Control[handle].chan != -1) {
return TRUE;
}
__HIO2LastErrorCode = 2;
return FALSE;
}
BOOL HIO2Close(s32 handle) {
if (!__HIO2IsInitialized() || !__HIO2IsValidHandle(handle)) {
return FALSE;
}
EXISetExiCallback(__HIO2Control[handle].chan, NULL);
if (__HIO2Control[handle]._0x8 == 0) {
EXIDetach(__HIO2Control[handle].chan);
}
__HIO2ClearChanInfo(handle);
return TRUE;
}
BOOL HIO2Read(s32 handle, u32 addr, void* buffer, s32 size) {
BOOL rt;
if (!__HIO2IsInitialized() || !__HIO2IsValidHandle(handle)) {
return FALSE;
}
ASSERTLINE(564, (addr & 3) == 0);
rt = EXIReadRam(handle, __HIO2Control[handle]._0x8, ((addr + 0xD10000) << 6) & 0x3FFFFF00, buffer, size, NULL);
if (rt == 0) {
__HIO2LastErrorCode = 8;
}
return rt;
}
BOOL HIO2Write(s32 handle, u32 addr, void* buffer, s32 size) {
BOOL rt;
if (!__HIO2IsInitialized() || !__HIO2IsValidHandle(handle)) {
return FALSE;
}
ASSERTLINE(593, (addr & 3) == 0);
rt = EXIWriteRam(handle, __HIO2Control[handle]._0x8, (((addr + 0xD10000) << 6) & 0x3FFFFF00) | 0x80000000, buffer, size, NULL);
if (rt == 0) {
__HIO2LastErrorCode = 8;
}
return rt;
}
void HIO2Exit(void) {
s32 handle;
for (handle = 0; handle < 2; handle++) {
if (__HIO2Control[handle].chan != -1) {
HIO2Close(handle);
}
}
__HIO2Initialized = FALSE;
__HIO2ConsoleType = 0;
}
File diff suppressed because it is too large Load Diff
+888
View File
@@ -0,0 +1,888 @@
#include <revolution.h>
#include <revolution/mtx.h>
#include <math.h>
f32 mtxUnit[] = {0.0f, 1.0f, 0.5f, 3.0f};
void C_MTXFrustum(Mtx44 m, f32 t, f32 b, f32 l, f32 r, f32 n, f32 f) {
f32 tmp;
ASSERTMSGLINE(105, m, "MTXFrustum(): NULL Mtx44Ptr 'm' ");
ASSERTMSGLINE(106, t != b, "MTXFrustum(): 't' and 'b' clipping planes are equal ");
ASSERTMSGLINE(107, l != r, "MTXFrustum(): 'l' and 'r' clipping planes are equal ");
ASSERTMSGLINE(108, n != f, "MTXFrustum(): 'n' and 'f' clipping planes are equal ");
tmp = 1 / (r - l);
m[0][0] = (2 * n * tmp);
m[0][1] = 0;
m[0][2] = (tmp * (r + l));
m[0][3] = 0;
tmp = 1 / (t - b);
m[1][0] = 0;
m[1][1] = (2 * n * tmp);
m[1][2] = (tmp * (t + b));
m[1][3] = 0;
m[2][0] = 0;
m[2][1] = 0;
tmp = 1 / (f - n);
m[2][2] = (-n * tmp);
m[2][3] = (tmp * -(f * n));
m[3][0] = 0;
m[3][1] = 0;
m[3][2] = -1;
m[3][3] = 0;
}
void C_MTXPerspective(Mtx44 m, f32 fovY, f32 aspect, f32 n, f32 f) {
f32 angle;
f32 cot;
f32 tmp;
ASSERTMSGLINE(184, m, "MTXPerspective(): NULL Mtx44Ptr 'm' ");
ASSERTMSGLINE(185, (fovY > 0.0) && (fovY < 180.0), "MTXPerspective(): 'fovY' out of range ");
ASSERTMSGLINE(186, 0.0f != aspect, "MTXPerspective(): 'aspect' is 0 ");
angle = (0.5f * fovY);
angle = MTXDegToRad(angle);
cot = 1 / tanf(angle);
m[0][0] = (cot / aspect);
m[0][1] = 0;
m[0][2] = 0;
m[0][3] = 0;
m[1][0] = 0;
m[1][1] = (cot);
m[1][2] = 0;
m[1][3] = 0;
m[2][0] = 0;
m[2][1] = 0;
tmp = 1 / (f - n);
m[2][2] = (-n * tmp);
m[2][3] = (tmp * -(f * n));
m[3][0] = 0;
m[3][1] = 0;
m[3][2] = -1;
m[3][3] = 0;
}
void C_MTXOrtho(Mtx44 m, f32 t, f32 b, f32 l, f32 r, f32 n, f32 f) {
f32 tmp;
ASSERTMSGLINE(254, m, "MTXOrtho(): NULL Mtx44Ptr 'm' ");
ASSERTMSGLINE(255, t != b, "MTXOrtho(): 't' and 'b' clipping planes are equal ");
ASSERTMSGLINE(256, l != r, "MTXOrtho(): 'l' and 'r' clipping planes are equal ");
ASSERTMSGLINE(257, n != f, "MTXOrtho(): 'n' and 'f' clipping planes are equal ");
tmp = 1 / (r - l);
m[0][0] = 2 * tmp;
m[0][1] = 0;
m[0][2] = 0;
m[0][3] = (tmp * -(r + l));
tmp = 1 / (t - b);
m[1][0] = 0;
m[1][1] = 2 * tmp;
m[1][2] = 0;
m[1][3] = (tmp * -(t + b));
m[2][0] = 0;
m[2][1] = 0;
tmp = 1 / (f - n);
m[2][2] = (-1 * tmp);
m[2][3] = (-f * tmp);
m[3][0] = 0;
m[3][1] = 0;
m[3][2] = 0;
m[3][3] = 1;
}
void C_MTX44Identity(Mtx44 m) {
ASSERTMSGLINE(324, m != 0, "MTX44Identity(): NULL Mtx44 'm' ");
m[0][0] = 1.0f;
m[0][1] = 0.0f;
m[0][2] = 0.0f;
m[0][3] = 0.0f;
m[1][0] = 0.0f;
m[1][1] = 1.0f;
m[1][2] = 0.0f;
m[1][3] = 0.0f;
m[2][0] = 0.0f;
m[2][1] = 0.0f;
m[2][2] = 1.0f;
m[2][3] = 0.0f;
m[3][0] = 0.0f;
m[3][1] = 0.0f;
m[3][2] = 0.0f;
m[3][3] = 1.0f;
}
void PSMTX44Identity(__REGISTER Mtx44 m) {
__REGISTER f32 c1 = 1.0f;
__REGISTER f32 c0 = 0.0f;
asm {
stfs c1, 0x0(m)
psq_st c0, 0x4(m), 0, 0
psq_st c0, 0xc(m), 0, 0
stfs c1, 0x14(m)
psq_st c0, 0x18(m), 0, 0
psq_st c0, 0x20(m), 0, 0
stfs c1, 0x28(m)
psq_st c0, 0x2c(m), 0, 0
psq_st c0, 0x34(m), 0, 0
stfs c1, 0x3c(m)
}
}
void C_MTX44Copy(const Mtx44 src, Mtx44 dst) {
ASSERTMSGLINE(382, src != 0, "MTX44Copy(): NULL Mtx44Ptr 'src' ");
ASSERTMSGLINE(383, dst != 0, "MTX44Copy(): NULL Mtx44Ptr 'dst' ");
if (src != dst) {
dst[0][0] = src[0][0];
dst[0][1] = src[0][1];
dst[0][2] = src[0][2];
dst[0][3] = src[0][3];
dst[1][0] = src[1][0];
dst[1][1] = src[1][1];
dst[1][2] = src[1][2];
dst[1][3] = src[1][3];
dst[2][0] = src[2][0];
dst[2][1] = src[2][1];
dst[2][2] = src[2][2];
dst[2][3] = src[2][3];
dst[3][0] = src[3][0];
dst[3][1] = src[3][1];
dst[3][2] = src[3][2];
dst[3][3] = src[3][3];
}
}
asm void PSMTX44Copy(const __REGISTER Mtx44 src, __REGISTER Mtx44 dst) {
nofralloc
psq_l f1, 0x0(src), 0, 0
psq_st f1, 0x0(dst), 0, 0
psq_l f1, 0x8(src), 0, 0
psq_st f1, 0x8(dst), 0, 0
psq_l f1, 0x10(src), 0, 0
psq_st f1, 0x10(dst), 0, 0
psq_l f1, 0x18(src), 0, 0
psq_st f1, 0x18(dst), 0, 0
psq_l f1, 0x20(src), 0, 0
psq_st f1, 0x20(dst), 0, 0
psq_l f1, 0x28(src), 0, 0
psq_st f1, 0x28(dst), 0, 0
psq_l f1, 0x30(src), 0, 0
psq_st f1, 0x30(dst), 0, 0
psq_l f1, 0x38(src), 0, 0
psq_st f1, 0x38(dst), 0, 0
blr
}
void C_MTX44Concat(const Mtx44 a, const Mtx44 b, Mtx44 ab) {
Mtx44 mTmp;
Mtx44Ptr m;
ASSERTMSGLINE(454, a, "MTX44Concat(): NULL Mtx44Ptr 'a' ");
ASSERTMSGLINE(455, b, "MTX44Concat(): NULL Mtx44Ptr 'b' ");
ASSERTMSGLINE(456, ab, "MTX44Concat(): NULL Mtx44Ptr 'ab' ");
if (ab == a || ab == b) {
m = mTmp;
} else {
m = ab;
}
m[0][0] = (a[0][0] * b[0][0]) + (a[0][1] * b[1][0]) + (a[0][2] * b[2][0]) + (a[0][3] * b[3][0]);
m[0][1] = (a[0][0] * b[0][1]) + (a[0][1] * b[1][1]) + (a[0][2] * b[2][1]) + (a[0][3] * b[3][1]);
m[0][2] = (a[0][0] * b[0][2]) + (a[0][1] * b[1][2]) + (a[0][2] * b[2][2]) + (a[0][3] * b[3][2]);
m[0][3] = (a[0][0] * b[0][3]) + (a[0][1] * b[1][3]) + (a[0][2] * b[2][3]) + (a[0][3] * b[3][3]);
m[1][0] = (a[1][0] * b[0][0]) + (a[1][1] * b[1][0]) + (a[1][2] * b[2][0]) + (a[1][3] * b[3][0]);
m[1][1] = (a[1][0] * b[0][1]) + (a[1][1] * b[1][1]) + (a[1][2] * b[2][1]) + (a[1][3] * b[3][1]);
m[1][2] = (a[1][0] * b[0][2]) + (a[1][1] * b[1][2]) + (a[1][2] * b[2][2]) + (a[1][3] * b[3][2]);
m[1][3] = (a[1][0] * b[0][3]) + (a[1][1] * b[1][3]) + (a[1][2] * b[2][3]) + (a[1][3] * b[3][3]);
m[2][0] = (a[2][0] * b[0][0]) + (a[2][1] * b[1][0]) + (a[2][2] * b[2][0]) + (a[2][3] * b[3][0]);
m[2][1] = (a[2][0] * b[0][1]) + (a[2][1] * b[1][1]) + (a[2][2] * b[2][1]) + (a[2][3] * b[3][1]);
m[2][2] = (a[2][0] * b[0][2]) + (a[2][1] * b[1][2]) + (a[2][2] * b[2][2]) + (a[2][3] * b[3][2]);
m[2][3] = (a[2][0] * b[0][3]) + (a[2][1] * b[1][3]) + (a[2][2] * b[2][3]) + (a[2][3] * b[3][3]);
m[3][0] = (a[3][0] * b[0][0]) + (a[3][1] * b[1][0]) + (a[3][2] * b[2][0]) + (a[3][3] * b[3][0]);
m[3][1] = (a[3][0] * b[0][1]) + (a[3][1] * b[1][1]) + (a[3][2] * b[2][1]) + (a[3][3] * b[3][1]);
m[3][2] = (a[3][0] * b[0][2]) + (a[3][1] * b[1][2]) + (a[3][2] * b[2][2]) + (a[3][3] * b[3][2]);
m[3][3] = (a[3][0] * b[0][3]) + (a[3][1] * b[1][3]) + (a[3][2] * b[2][3]) + (a[3][3] * b[3][3]);
if (m == mTmp) {
C_MTX44Copy(mTmp, ab);
}
}
asm void PSMTX44Concat(const __REGISTER Mtx44 a, const __REGISTER Mtx44 b, __REGISTER Mtx44 ab) {
nofralloc
psq_l f0, 0x0(a), 0, 0
psq_l f2, 0x0(b), 0, 0
ps_muls0 f6, f2, f0
psq_l f3, 0x10(b), 0, 0
psq_l f4, 0x20(b), 0, 0
ps_madds1 f6, f3, f0, f6
psq_l f1, 0x8(a), 0, 0
psq_l f5, 0x30(b), 0, 0
ps_madds0 f6, f4, f1, f6
psq_l f0, 0x10(a), 0, 0
ps_madds1 f6, f5, f1, f6
psq_l f1, 0x18(a), 0, 0
ps_muls0 f8, f2, f0
ps_madds1 f8, f3, f0, f8
psq_l f0, 0x20(a), 0, 0
ps_madds0 f8, f4, f1, f8
ps_madds1 f8, f5, f1, f8
psq_l f1, 0x28(a), 0, 0
ps_muls0 f10, f2, f0
ps_madds1 f10, f3, f0, f10
psq_l f0, 0x30(a), 0, 0
ps_madds0 f10, f4, f1, f10
ps_madds1 f10, f5, f1, f10
psq_l f1, 0x38(a), 0, 0
ps_muls0 f12, f2, f0
psq_l f2, 0x8(b), 0, 0
ps_madds1 f12, f3, f0, f12
psq_l f0, 0x0(a), 0, 0
ps_madds0 f12, f4, f1, f12
psq_l f3, 0x18(b), 0, 0
ps_madds1 f12, f5, f1, f12
psq_l f1, 0x8(a), 0, 0
ps_muls0 f7, f2, f0
psq_l f4, 0x28(b), 0, 0
ps_madds1 f7, f3, f0, f7
psq_l f5, 0x38(b), 0, 0
ps_madds0 f7, f4, f1, f7
psq_l f0, 0x10(a), 0, 0
ps_madds1 f7, f5, f1, f7
psq_l f1, 0x18(a), 0, 0
ps_muls0 f9, f2, f0
psq_st f6, 0x0(ab), 0, 0
ps_madds1 f9, f3, f0, f9
psq_l f0, 0x20(a), 0, 0
ps_madds0 f9, f4, f1, f9
psq_st f8, 0x10(ab), 0, 0
ps_madds1 f9, f5, f1, f9
psq_l f1, 0x28(a), 0, 0
ps_muls0 f11, f2, f0
psq_st f10, 0x20(ab), 0, 0
ps_madds1 f11, f3, f0, f11
psq_l f0, 0x30(a), 0, 0
ps_madds0 f11, f4, f1, f11
psq_st f12, 0x30(ab), 0, 0
ps_madds1 f11, f5, f1, f11
psq_l f1, 0x38(a), 0, 0
ps_muls0 f13, f2, f0
psq_st f7, 0x8(ab), 0, 0
ps_madds1 f13, f3, f0, f13
psq_st f9, 0x18(ab), 0, 0
ps_madds0 f13, f4, f1, f13
psq_st f11, 0x28(ab), 0, 0
ps_madds1 f13, f5, f1, f13
psq_st f13, 0x38(ab), 0, 0
blr
}
void C_MTX44Transpose(const Mtx44 src, Mtx44 xPose) {
Mtx44 mTmp;
Mtx44Ptr m;
ASSERTMSGLINE(637, src, "MTX44Transpose(): NULL Mtx44Ptr 'src' ");
ASSERTMSGLINE(638, xPose, "MTX44Transpose(): NULL Mtx44Ptr 'xPose' ");
if (src == xPose) {
m = mTmp;
} else {
m = xPose;
}
m[0][0] = src[0][0];
m[0][1] = src[1][0];
m[0][2] = src[2][0];
m[0][3] = src[3][0];
m[1][0] = src[0][1];
m[1][1] = src[1][1];
m[1][2] = src[2][1];
m[1][3] = src[3][1];
m[2][0] = src[0][2];
m[2][1] = src[1][2];
m[2][2] = src[2][2];
m[2][3] = src[3][2];
m[3][0] = src[0][3];
m[3][1] = src[1][3];
m[3][2] = src[2][3];
m[3][3] = src[3][3];
if (m == mTmp) {
MTX44Copy(mTmp, xPose);
}
}
asm void PSMTX44Transpose(const __REGISTER Mtx44 src, __REGISTER Mtx44 xPose) {
nofralloc
psq_l f0, 0x0(src), 0, 0
psq_l f1, 0x10(src), 0, 0
ps_merge00 f4, f0, f1
psq_l f2, 0x8(src), 0, 0
psq_st f4, 0x0(xPose), 0, 0
ps_merge11 f5, f0, f1
psq_l f3, 0x18(src), 0, 0
psq_st f5, 0x10(xPose), 0, 0
ps_merge00 f4, f2, f3
psq_l f0, 0x20(src), 0, 0
psq_st f4, 0x20(xPose), 0, 0
ps_merge11 f5, f2, f3
psq_l f1, 0x30(src), 0, 0
psq_st f5, 0x30(xPose), 0, 0
ps_merge00 f4, f0, f1
psq_l f2, 0x28(src), 0, 0
psq_st f4, 0x8(xPose), 0, 0
ps_merge11 f5, f0, f1
psq_l f3, 0x38(src), 0, 0
psq_st f5, 0x18(xPose), 0, 0
ps_merge00 f4, f2, f3
psq_st f4, 0x28(xPose), 0, 0
ps_merge11 f5, f2, f3
psq_st f5, 0x38(xPose), 0, 0
blr
}
#define SWAP(a, b) \
{ \
f32 tmp; \
tmp = a; \
a = b; \
b = tmp; \
}
u32 C_MTX44Inverse(const Mtx44 src, Mtx44 inv) {
Mtx44 gjm;
s32 i;
s32 j;
s32 k;
f32 w;
f32 max;
s32 swp;
f32 ftmp;
ASSERTMSGLINE(734, src, "MTX44Inverse(): NULL Mtx44Ptr 'src' ");
ASSERTMSGLINE(735, inv, "MTX44Inverse(): NULL Mtx44Ptr 'inv' ");
MTX44Copy(src, gjm);
MTX44Identity(inv);
for (i = 0; i < 4; i++) {
max = 0.0f;
swp = i;
for (k = i; k < 4; k++) {
ftmp = fabsf(gjm[k][i]);
if (ftmp > max) {
max = ftmp;
swp = k;
}
}
if (max == 0.0f) {
return 0;
}
if (swp != i) {
for (k = 0; k < 4; k++) {
SWAP(gjm[i][k], gjm[swp][k]);
SWAP(inv[i][k], inv[swp][k]);
}
}
w = 1.0f / gjm[i][i];
for (j = 0; j < 4; j++) {
gjm[i][j] *= w;
inv[i][j] *= w;
}
for (k = 0; k < 4; k++) {
if (k != i) {
w = gjm[k][i];
for (j = 0; j < 4; j++) {
gjm[k][j] -= gjm[i][j] * w;
inv[k][j] -= inv[i][j] * w;
}
}
}
}
return 1;
}
void C_MTX44Trans(Mtx44 m, f32 xT, f32 yT, f32 zT) {
ASSERTMSGLINE(835, m, "MTX44Trans(): NULL Mtx44Ptr 'm' ");
m[0][0] = 1.0f;
m[0][1] = 0.0f;
m[0][2] = 0.0f;
m[0][3] = xT;
m[1][0] = 0.0f;
m[1][1] = 1.0f;
m[1][2] = 0.0f;
m[1][3] = yT;
m[2][0] = 0.0f;
m[2][1] = 0.0f;
m[2][2] = 1.0f;
m[2][3] = zT;
m[3][0] = 0.0f;
m[3][1] = 0.0f;
m[3][2] = 0.0f;
m[3][3] = 1.0f;
}
void PSMTX44Trans(__REGISTER Mtx44 m, __REGISTER f32 xT, __REGISTER f32 yT, __REGISTER f32 zT) {
__REGISTER f32 c_zero = 0.0f;
__REGISTER f32 c_one = 1.0f;
__REGISTER f32 c_01;
asm {
stfs xT, 0xc(m)
stfs yT, 0x1c(m)
ps_merge00 c_01, c_zero, c_one
stfs zT, 0x2c(m)
psq_st c_one, 0x0(m), 1, 0
psq_st c_zero, 0x4(m), 0, 0
psq_st c_01, 0x10(m), 0, 0
psq_st c_zero, 0x18(m), 1, 0
psq_st c_zero, 0x20(m), 0, 0
psq_st c_one, 0x28(m), 1, 0
psq_st c_zero, 0x30(m), 0, 0
psq_st c_01, 0x38(m), 0, 0
}
}
void C_MTX44TransApply(const Mtx44 src, Mtx44 dst, f32 xT, f32 yT, f32 zT) {
ASSERTMSGLINE(899, src, "MTX44TransApply(): NULL Mtx44Ptr 'src' ");
ASSERTMSGLINE(900, dst, "MTX44TransApply(): NULL Mtx44Ptr 'src' "); //! wrong assert string
if (src != dst) {
dst[0][0] = src[0][0];
dst[0][1] = src[0][1];
dst[0][2] = src[0][2];
dst[1][0] = src[1][0];
dst[1][1] = src[1][1];
dst[1][2] = src[1][2];
dst[2][0] = src[2][0];
dst[2][1] = src[2][1];
dst[2][2] = src[2][2];
dst[3][0] = src[3][0];
dst[3][1] = src[3][1];
dst[3][2] = src[3][2];
dst[3][3] = src[3][3];
}
dst[0][3] = (src[0][3] + xT);
dst[1][3] = (src[1][3] + yT);
dst[2][3] = (src[2][3] + zT);
}
asm void PSMTX44TransApply(const __REGISTER Mtx44 src, __REGISTER Mtx44 dst, __REGISTER f32 xT, __REGISTER f32 yT, __REGISTER f32 zT) {
nofralloc
psq_l f4, 0x0(src), 0, 0
frsp xT, xT
psq_l f5, 0x8(src), 0, 0
frsp yT, yT
psq_l f6, 0x10(src), 0, 0
frsp zT, zT
psq_l f7, 0x18(src), 0, 0
psq_st f4, 0x0(dst), 0, 0
ps_sum1 f5, xT, f5, f5
psq_l f4, 0x28(src), 0, 0
psq_st f6, 0x10(dst), 0, 0
ps_sum1 f7, yT, f7, f7
psq_l f8, 0x20(src), 0, 0
psq_st f5, 0x8(dst), 0, 0
ps_sum1 f4, zT, f4, f4
psq_st f7, 0x18(dst), 0, 0
psq_st f8, 0x20(dst), 0, 0
psq_l f5, 0x30(src), 0, 0
psq_l f6, 0x38(src), 0, 0
psq_st f4, 0x28(dst), 0, 0
psq_st f5, 0x30(dst), 0, 0
psq_st f6, 0x38(dst), 0, 0
blr
}
void C_MTX44Scale(Mtx44 m, f32 xS, f32 yS, f32 zS) {
ASSERTMSGLINE(976, m, "MTX44Scale(): NULL Mtx44Ptr 'm' ");
m[0][0] = xS;
m[0][1] = 0.0f;
m[0][2] = 0.0f;
m[0][3] = 0.0f;
m[1][0] = 0.0f;
m[1][1] = yS;
m[1][2] = 0.0f;
m[1][3] = 0.0f;
m[2][0] = 0.0f;
m[2][1] = 0.0f;
m[2][2] = zS;
m[2][3] = 0.0f;
m[3][0] = 0.0f;
m[3][1] = 0.0f;
m[3][2] = 0.0f;
m[3][3] = 1.0f;
}
void PSMTX44Scale(__REGISTER Mtx44 m, __REGISTER f32 xS, __REGISTER f32 yS, __REGISTER f32 zS) {
__REGISTER f32 c_zero = 0.0f;
__REGISTER f32 c_one = 1.0f;
asm {
stfs xS, 0x0(m)
psq_st c_zero, 0x4(m), 0, 0
psq_st c_zero, 0xc(m), 0, 0
stfs yS, 0x14(m)
psq_st c_zero, 0x18(m), 0, 0
psq_st c_zero, 0x20(m), 0, 0
stfs zS, 0x28(m)
psq_st c_zero, 0x2c(m), 0, 0
psq_st c_zero, 0x34(m), 0, 0
stfs c_one, 0x3c(m)
}
}
void C_MTX44ScaleApply(const Mtx44 src, Mtx44 dst, f32 xS, f32 yS, f32 zS) {
ASSERTMSGLINE(1036, src, "MTX44ScaleApply(): NULL Mtx44Ptr 'src' ");
ASSERTMSGLINE(1037, dst, "MTX44ScaleApply(): NULL Mtx44Ptr 'dst' ");
dst[0][0] = (src[0][0] * xS);
dst[0][1] = (src[0][1] * xS);
dst[0][2] = (src[0][2] * xS);
dst[0][3] = (src[0][3] * xS);
dst[1][0] = (src[1][0] * yS);
dst[1][1] = (src[1][1] * yS);
dst[1][2] = (src[1][2] * yS);
dst[1][3] = (src[1][3] * yS);
dst[2][0] = (src[2][0] * zS);
dst[2][1] = (src[2][1] * zS);
dst[2][2] = (src[2][2] * zS);
dst[2][3] = (src[2][3] * zS);
dst[3][0] = src[3][0];
dst[3][1] = src[3][1];
dst[3][2] = src[3][2];
dst[3][3] = src[3][3];
}
asm void PSMTX44ScaleApply(const __REGISTER Mtx44 src, __REGISTER Mtx44 dst, __REGISTER f32 xS, __REGISTER f32 yS, __REGISTER f32 zS) {
nofralloc
psq_l f4, 0x0(src), 0, 0
frsp xS, xS
psq_l f5, 0x8(src), 0, 0
frsp yS, yS
psq_l f6, 0x10(src), 0, 0
ps_muls0 f4, f4, xS
psq_l f7, 0x18(src), 0, 0
ps_muls0 f5, f5, xS
psq_l f8, 0x20(src), 0, 0
frsp zS, zS
psq_st f4, 0x0(dst), 0, 0
ps_muls0 f6, f6, yS
psq_l f9, 0x28(src), 0, 0
psq_st f5, 0x8(dst), 0, 0
ps_muls0 f7, f7, yS
psq_l f10, 0x30(src), 0, 0
psq_st f6, 0x10(dst), 0, 0
ps_muls0 f8, f8, zS
psq_l f11, 0x38(src), 0, 0
psq_st f7, 0x18(dst), 0, 0
ps_muls0 f9, f9, zS
psq_st f8, 0x20(dst), 0, 0
psq_st f9, 0x28(dst), 0, 0
psq_st f10, 0x30(dst), 0, 0
psq_st f11, 0x38(dst), 0, 0
blr
}
void C_MTX44RotRad(Mtx44 m, char axis, f32 rad) {
f32 sinA;
f32 cosA;
ASSERTMSGLINE(1118, m, "MTX44RotRad(): NULL Mtx44Ptr 'm' ");
sinA = sinf(rad);
cosA = cosf(rad);
C_MTX44RotTrig(m, axis, sinA, cosA);
}
void PSMTX44RotRad(Mtx44 m, char axis, f32 rad) {
f32 sinA;
f32 cosA;
sinA = sinf(rad);
cosA = cosf(rad);
PSMTX44RotTrig(m, axis, sinA, cosA);
}
void C_MTX44RotTrig(Mtx44 m, char axis, f32 sinA, f32 cosA) {
ASSERTMSGLINE(1163, m, "MTX44RotTrig(): NULL Mtx44Ptr 'm' ");
axis |= 0x20;
switch(axis) {
case 'x':
m[0][0] = 1.0f;
m[0][1] = 0.0f;
m[0][2] = 0.0f;
m[0][3] = 0.0f;
m[1][0] = 0.0f;
m[1][1] = cosA;
m[1][2] = -sinA;
m[1][3] = 0.0f;
m[2][0] = 0.0f;
m[2][1] = sinA;
m[2][2] = cosA;
m[2][3] = 0.0f;
m[3][0] = 0.0f;
m[3][1] = 0.0f;
m[3][2] = 0.0f;
m[3][3] = 1.0f;
break;
case 'y':
m[0][0] = cosA;
m[0][1] = 0.0f;
m[0][2] = sinA;
m[0][3] = 0.0f;
m[1][0] = 0.0f;
m[1][1] = 1.0f;
m[1][2] = 0.0f;
m[1][3] = 0.0f;
m[2][0] = -sinA;
m[2][1] = 0.0f;
m[2][2] = cosA;
m[2][3] = 0.0f;
m[3][0] = 0.0f;
m[3][1] = 0.0f;
m[3][2] = 0.0f;
m[3][3] = 1.0f;
break;
case 'z':
m[0][0] = cosA;
m[0][1] = -sinA;
m[0][2] = 0.0f;
m[0][3] = 0.0f;
m[1][0] = sinA;
m[1][1] = cosA;
m[1][2] = 0.0f;
m[1][3] = 0.0f;
m[2][0] = 0.0f;
m[2][1] = 0.0f;
m[2][2] = 1.0f;
m[2][3] = 0.0f;
m[3][0] = 0.0f;
m[3][1] = 0.0f;
m[3][2] = 0.0f;
m[3][3] = 1.0f;
break;
default:
ASSERTMSGLINE(1191, FALSE, "MTX44RotTrig(): invalid 'axis' value ");
break;
}
}
void PSMTX44RotTrig(__REGISTER Mtx44 m, __REGISTER char axis, __REGISTER f32 sinA, __REGISTER f32 cosA) {
__REGISTER f32 ftmp0;
__REGISTER f32 ftmp1;
__REGISTER f32 ftmp2;
__REGISTER f32 ftmp3;
__REGISTER f32 ftmp4;
__REGISTER f32 c_zero = 0.0f;
__REGISTER f32 c_one = 1.0f;
asm {
frsp sinA, sinA
ori axis, axis, 0x20
frsp cosA, cosA
cmplwi axis, 'x'
beq L_00001AB4
cmplwi axis, 'y'
beq L_00001AE8
cmplwi axis, 'z'
beq L_00001B20
b L_00001B54
L_00001AB4:
psq_st c_one, 0x0(m), 1, 0
psq_st c_zero, 0x4(m), 0, 0
ps_neg ftmp0, sinA
psq_st c_zero, 0xc(m), 0, 0
ps_merge00 ftmp1, sinA, cosA
psq_st c_zero, 0x1c(m), 0, 0
ps_merge00 ftmp0, cosA, ftmp0
psq_st c_zero, 0x2c(m), 0, 0
psq_st c_zero, 0x34(m), 0, 0
psq_st ftmp1, 0x24(m), 0, 0
psq_st ftmp0, 0x14(m), 0, 0
psq_st c_one, 0x3c(m), 1, 0
b L_00001B54
L_00001AE8:
ps_merge00 ftmp1, cosA, c_zero
psq_st c_zero, 0x30(m), 0, 0
ps_neg ftmp0, sinA
psq_st c_zero, 0x18(m), 0, 0
ps_merge00 ftmp3, c_zero, c_one
psq_st ftmp1, 0x0(m), 0, 0
ps_merge00 ftmp4, ftmp0, c_zero
ps_merge00 ftmp2, sinA, c_zero
psq_st ftmp3, 0x10(m), 0, 0
psq_st ftmp2, 0x8(m), 0, 0
psq_st ftmp4, 0x20(m), 0, 0
psq_st ftmp1, 0x28(m), 0, 0
psq_st ftmp3, 0x38(m), 0, 0
b L_00001B54
L_00001B20:
psq_st c_zero, 0x8(m), 0, 0
ps_neg ftmp0, sinA
psq_st c_zero, 0x18(m), 0, 0
ps_merge00 ftmp1, sinA, cosA
psq_st c_zero, 0x20(m), 0, 0
ps_merge00 ftmp2, c_one, c_zero
psq_st c_zero, 0x30(m), 0, 0
ps_merge00 ftmp3, c_zero, c_one
psq_st ftmp1, 0x10(m), 0, 0
ps_merge00 ftmp4, cosA, ftmp0
psq_st ftmp2, 0x28(m), 0, 0
psq_st ftmp3, 0x38(m), 0, 0
psq_st ftmp4, 0x0(m), 0, 0
L_00001B54:
}
}
void C_MTX44RotAxisRad(Mtx44 m, const Vec* axis, f32 rad) {
Vec vN;
f32 s;
f32 c;
f32 t;
f32 x;
f32 y;
f32 z;
f32 xSq;
f32 ySq;
f32 zSq;
ASSERTMSGLINE(1300, m, "MTX44RotAxisRad(): NULL Mtx44Ptr 'm' ");
ASSERTMSGLINE(1301, axis, "MTX44RotAxisRad(): NULL VecPtr 'axis' ");
s = sinf(rad);
c = cosf(rad);
t = 1 - c;
C_VECNormalize(axis, &vN);
x = vN.x;
y = vN.y;
z = vN.z;
xSq = (x * x);
ySq = (y * y);
zSq = (z * z);
m[0][0] = (c + (t * xSq));
m[0][1] = (y * (t * x)) - (s * z);
m[0][2] = (z * (t * x)) + (s * y);
m[0][3] = 0.0f;
m[1][0] = ((y * (t * x)) + (s * z));
m[1][1] = (c + (t * ySq));
m[1][2] = ((z * (t * y)) - (s * x));
m[1][3] = 0.0f;
m[2][0] = ((z * (t * x)) - (s * y));
m[2][1] = ((z * (t * y)) + (s * x));
m[2][2] = (c + (t * zSq));
m[2][3] = 0.0f;
m[3][0] = 0.0f;
m[3][1] = 0.0f;
m[3][2] = 0.0f;
m[3][3] = 1.0f;
}
static void __PSMTX44RotAxisRadInternal(__REGISTER Mtx44 m, const __REGISTER Vec* axis, __REGISTER f32 sT, __REGISTER f32 cT) {
__REGISTER f32 tT;
__REGISTER f32 fc0;
__REGISTER f32 tmp0;
__REGISTER f32 tmp1;
__REGISTER f32 tmp2;
__REGISTER f32 tmp3;
__REGISTER f32 tmp4;
__REGISTER f32 tmp5;
__REGISTER f32 tmp6;
__REGISTER f32 tmp7;
__REGISTER f32 tmp8;
__REGISTER f32 tmp9;
tmp9 = 0.5f;
tmp8 = 3.0f;
asm {
frsp cT, cT
psq_l tmp0, 0x0(axis), 0, 0
frsp sT, sT
lfs tmp1, 0x8(axis)
ps_mul tmp2, tmp0, tmp0
fadds tmp7, tmp9, tmp9
ps_madd tmp3, tmp1, tmp1, tmp2
fsubs fc0, tmp9, tmp9
ps_sum0 tmp4, tmp3, tmp1, tmp2
fsubs tT, tmp7, cT
frsqrte tmp5, tmp4
ps_merge00 tmp7, fc0, tmp7
fmuls tmp2, tmp5, tmp5
fmuls tmp3, tmp5, tmp9
psq_st fc0, 0x30(m), 0, 0
fnmsubs tmp2, tmp2, tmp4, tmp8
fmuls tmp5, tmp2, tmp3
psq_st tmp7, 0x38(m), 0, 0
ps_merge00 cT, cT, cT
ps_muls0 tmp0, tmp0, tmp5
ps_muls0 tmp1, tmp1, tmp5
ps_muls0 tmp4, tmp0, tT
ps_muls0 tmp9, tmp0, sT
ps_muls0 tmp5, tmp1, tT
ps_muls1 tmp3, tmp4, tmp0
ps_muls0 tmp2, tmp4, tmp0
ps_muls0 tmp4, tmp4, tmp1
fnmsubs tmp6, tmp1, sT, tmp3
fmadds tmp7, tmp1, sT, tmp3
ps_neg tmp0, tmp9
ps_sum0 tmp8, tmp4, fc0, tmp9
ps_sum0 tmp2, tmp2, tmp6, cT
ps_sum1 tmp3, cT, tmp7, tmp3
ps_sum0 tmp6, tmp0, fc0, tmp4
psq_st tmp8, 0x8(m), 0, 0
ps_sum0 tmp0, tmp4, tmp4, tmp0
psq_st tmp2, 0x0(m), 0, 0
ps_muls0 tmp5, tmp5, tmp1
psq_st tmp3, 0x10(m), 0, 0
ps_sum1 tmp4, tmp9, tmp0, tmp4
psq_st tmp6, 0x18(m), 0, 0
ps_sum0 tmp5, tmp5, fc0, cT
psq_st tmp4, 0x20(m), 0, 0
psq_st tmp5, 0x28(m), 0, 0
}
}
void PSMTX44RotAxisRad(Mtx44 m, const Vec* axis, f32 rad) {
f32 sinT, cosT;
sinT = sinf(rad);
cosT = cosf(rad);
__PSMTX44RotAxisRadInternal(m, axis, sinT, cosT);
}
+247
View File
@@ -0,0 +1,247 @@
#include <revolution.h>
#include <revolution/mtx.h>
#include "fake_tgmath.h"
void C_MTX44MultVec(const Mtx44 m, const Vec* src, Vec* dst) {
Vec vTmp;
f32 w;
ASSERTMSGLINE(67, m, "MTX44MultVec(): NULL Mtx44Ptr 'm' ");
ASSERTMSGLINE(68, src, "MTX44MultVec(): NULL VecPtr 'src' ");
ASSERTMSGLINE(69, dst, "MTX44MultVec(): NULL VecPtr 'dst' ");
vTmp.x = m[0][0] * src->x + m[0][1] * src->y + m[0][2] * src->z + m[0][3];
vTmp.y = m[1][0] * src->x + m[1][1] * src->y + m[1][2] * src->z + m[1][3];
vTmp.z = m[2][0] * src->x + m[2][1] * src->y + m[2][2] * src->z + m[2][3];
w = m[3][0] * src->x + m[3][1] * src->y + m[3][2] * src->z + m[3][3];
w = 1.0f / w;
dst->x = vTmp.x * w;
dst->y = vTmp.y * w;
dst->z = vTmp.z * w;
}
asm void PSMTX44MultVec(const __REGISTER Mtx44 m, const __REGISTER Vec* src, __REGISTER Vec* dst) {
nofralloc
psq_l f0, 0x0(src), 0, 0
psq_l f2, 0x30(m), 0, 0
psq_l f1, 0x8(src), 1, 0
ps_mul f4, f0, f2
psq_l f3, 0x38(m), 0, 0
ps_madd f5, f1, f3, f4
ps_merge11 f12, f1, f1
ps_sum0 f13, f5, f5, f5
psq_l f4, 0x0(m), 0, 0
ps_merge00 f13, f13, f13
psq_l f5, 0x8(m), 0, 0
ps_div f13, f12, f13
psq_l f6, 0x10(m), 0, 0
psq_l f7, 0x18(m), 0, 0
psq_l f8, 0x20(m), 0, 0
psq_l f9, 0x28(m), 0, 0
ps_mul f4, f0, f4
ps_madd f2, f1, f5, f4
ps_mul f6, f0, f6
ps_madd f3, f1, f7, f6
ps_mul f8, f0, f8
ps_sum0 f2, f2, f2, f2
ps_madd f9, f1, f9, f8
ps_sum1 f2, f3, f2, f3
ps_sum0 f3, f9, f9, f9
ps_mul f2, f2, f13
psq_st f2, 0x0(dst), 0, 0
ps_mul f3, f3, f13
psq_st f3, 0x8(dst), 1, 0
blr
}
void C_MTX44MultVecArray(const Mtx44 m, const Vec* srcBase, Vec* dstBase, u32 count) {
u32 i;
Vec vTmp;
f32 w;
ASSERTMSGLINE(154, m, "MTX44MultVecArray(): NULL Mtx44Ptr 'm' ");
ASSERTMSGLINE(155, srcBase, "MTX44MultVecArray(): NULL VecPtr 'srcBase' ");
ASSERTMSGLINE(156, dstBase, "MTX44MultVecArray(): NULL VecPtr 'dstBase' ");
for(i = 0; i < count; i++) {
vTmp.x = m[0][0] * srcBase->x + m[0][1] * srcBase->y + m[0][2] * srcBase->z + m[0][3];
vTmp.y = m[1][0] * srcBase->x + m[1][1] * srcBase->y + m[1][2] * srcBase->z + m[1][3];
vTmp.z = m[2][0] * srcBase->x + m[2][1] * srcBase->y + m[2][2] * srcBase->z + m[2][3];
w = m[3][0] * srcBase->x + m[3][1] * srcBase->y + m[3][2] * srcBase->z + m[3][3];
w = 1.0f / w;
dstBase->x = vTmp.x * w;
dstBase->y = vTmp.y * w;
dstBase->z = vTmp.z * w;
srcBase++;
dstBase++;
}
}
asm void PSMTX44MultVecArray(const __REGISTER Mtx44 m, const __REGISTER Vec* srcBase, __REGISTER Vec* dstBase, __REGISTER u32 count) {
nofralloc
stwu r1, -0x10(r1)
subi count, count, 0x1
psq_l f6, 0x30(m), 0, 0
mtctr count
psq_l f8, 0x0(srcBase), 0, 0
subi dstBase, dstBase, 0x4
psq_l f7, 0x38(m), 0, 0
psq_lu f9, 0x8(srcBase), 1, 0
ps_mul f13, f6, f8
psq_l f0, 0x0(m), 0, 0
stfd f14, 0x8(r1)
ps_madd f13, f7, f9, f13
psq_l f2, 0x10(m), 0, 0
ps_merge11 f14, f9, f9
ps_mul f10, f0, f8
psq_l f4, 0x20(m), 0, 0
ps_mul f11, f2, f8
psq_l f1, 0x8(m), 0, 0
ps_mul f12, f4, f8
psq_l f3, 0x18(m), 0, 0
ps_sum0 f13, f13, f13, f13
psq_l f5, 0x28(m), 0, 0
L_00000468:
ps_madd f10, f1, f9, f10
ps_madd f11, f3, f9, f11
ps_madd f12, f5, f9, f12
ps_sum0 f10, f10, f10, f10
ps_sum0 f11, f11, f11, f11
ps_sum0 f12, f12, f12, f12
ps_div f13, f14, f13
psq_lu f8, 0x4(srcBase), 0, 0
psq_lu f9, 0x8(srcBase), 1, 0
ps_mul f10, f10, f13
psq_stu f10, 0x4(dstBase), 1, 0
ps_mul f11, f11, f13
psq_stu f11, 0x4(dstBase), 1, 0
ps_mul f12, f12, f13
psq_stu f12, 0x4(dstBase), 1, 0
ps_mul f13, f6, f8
ps_mul f10, f0, f8
ps_mul f11, f2, f8
ps_madd f13, f7, f9, f13
ps_mul f12, f4, f8
ps_sum0 f13, f13, f13, f13
bdnz L_00000468
ps_madd f10, f1, f9, f10
ps_madd f11, f3, f9, f11
ps_madd f12, f5, f9, f12
ps_sum0 f10, f10, f10, f10
ps_sum0 f11, f11, f11, f11
ps_sum0 f12, f12, f12, f12
ps_div f13, f14, f13
ps_mul f10, f10, f13
psq_st f10, 0x4(dstBase), 1, 0
ps_mul f11, f11, f13
psq_st f11, 0x8(dstBase), 1, 0
ps_mul f12, f12, f13
psq_st f12, 0xc(dstBase), 1, 0
lfd f14, 0x8(r1)
addi r1, r1, 0x10
blr
}
void C_MTX44MultVecSR(const Mtx44 m, const Vec* src, Vec* dst) {
Vec vTmp;
ASSERTMSGLINE(288, m, "MTX44MultVecSR(): NULL Mtx44Ptr 'm' ");
ASSERTMSGLINE(289, src, "MTX44MultVecSR(): NULL VecPtr 'src' ");
ASSERTMSGLINE(290, dst, "MTX44MultVecSR(): NULL VecPtr 'dst' ");
vTmp.x = (m[0][2] * src->z) + ((m[0][0] * src->x) + (m[0][1] * src->y));
vTmp.y = (m[1][2] * src->z) + ((m[1][0] * src->x) + (m[1][1] * src->y));
vTmp.z = (m[2][2] * src->z) + ((m[2][0] * src->x) + (m[2][1] * src->y));
dst->x = vTmp.x;
dst->y = vTmp.y;
dst->z = vTmp.z;
}
asm void PSMTX44MultVecSR(const __REGISTER Mtx m, const __REGISTER Vec* src, __REGISTER Vec* dst) {
nofralloc
psq_l f0, 0x0(m), 0, 0
psq_l f6, 0x0(src), 0, 0
psq_l f2, 0x10(m), 0, 0
ps_mul f8, f0, f6
psq_l f4, 0x20(m), 0, 0
ps_mul f10, f2, f6
psq_l f7, 0x8(src), 1, 0
ps_mul f12, f4, f6
psq_l f3, 0x18(m), 0, 0
ps_sum0 f8, f8, f8, f8
psq_l f5, 0x28(m), 0, 0
ps_sum0 f10, f10, f10, f10
psq_l f1, 0x8(m), 0, 0
ps_sum0 f12, f12, f12, f12
ps_madd f9, f1, f7, f8
psq_st f9, 0x0(dst), 1, 0
ps_madd f11, f3, f7, f10
psq_st f11, 0x4(dst), 1, 0
ps_madd f13, f5, f7, f12
psq_st f13, 0x8(dst), 1, 0
blr
}
void C_MTX44MultVecArraySR(const Mtx44 m, const Vec* srcBase, Vec* dstBase, u32 count) {
u32 i;
Vec vTmp;
ASSERTMSGLINE(379, m, "MTX44MultVecArraySR(): NULL Mtx44Ptr 'm' ");
ASSERTMSGLINE(380, srcBase, "MTX44MultVecArraySR(): NULL VecPtr 'srcBase' ");
ASSERTMSGLINE(381, dstBase, "MTX44MultVecArraySR(): NULL VecPtr 'dstBase' ");
for(i = 0; i < count; i++) {
vTmp.x = (m[0][2] * srcBase->z) + ((m[0][0] * srcBase->x) + (m[0][1] * srcBase->y));
vTmp.y = (m[1][2] * srcBase->z) + ((m[1][0] * srcBase->x) + (m[1][1] * srcBase->y));
vTmp.z = (m[2][2] * srcBase->z) + ((m[2][0] * srcBase->x) + (m[2][1] * srcBase->y));
dstBase->x = vTmp.x;
dstBase->y = vTmp.y;
dstBase->z = vTmp.z;
srcBase++;
dstBase++;
}
}
asm void PSMTX44MultVecArraySR(const __REGISTER Mtx44 m, const __REGISTER Vec* srcBase, __REGISTER Vec* dstBase, __REGISTER u32 count) {
nofralloc
psq_l f0, 0x0(m), 0, 0
subi count, count, 0x1
psq_l f6, 0x0(srcBase), 0, 0
ps_mul f8, f0, f6
psq_l f2, 0x10(m), 0, 0
ps_mul f9, f2, f6
psq_l f4, 0x20(m), 0, 0
psq_lu f7, 0x8(srcBase), 1, 0
ps_mul f10, f4, f6
psq_l f1, 0x8(m), 1, 0
mtctr count
psq_l f3, 0x18(m), 1, 0
subi dstBase, dstBase, 0x4
psq_l f5, 0x28(m), 1, 0
L_00000890:
ps_madd f11, f1, f7, f8
psq_lu f6, 0x4(srcBase), 0, 0
ps_madd f12, f3, f7, f9
ps_madd f13, f5, f7, f10
psq_lu f7, 0x8(srcBase), 1, 0
ps_sum0 f11, f11, f8, f8
psq_stu f11, 0x4(dstBase), 1, 0
ps_sum0 f12, f12, f9, f9
psq_stu f12, 0x4(dstBase), 1, 0
ps_sum0 f13, f13, f10, f10
psq_stu f13, 0x4(dstBase), 1, 0
ps_mul f8, f0, f6
ps_mul f9, f2, f6
ps_mul f10, f4, f6
bdnz L_00000890
ps_madd f11, f1, f7, f8
ps_madd f12, f3, f7, f9
ps_madd f13, f5, f7, f10
ps_sum0 f11, f11, f8, f8
psq_stu f11, 0x4(dstBase), 1, 0
ps_sum0 f12, f12, f9, f9
psq_stu f12, 0x4(dstBase), 1, 0
ps_sum0 f13, f13, f10, f10
psq_stu f13, 0x4(dstBase), 1, 0
blr
}
+108
View File
@@ -0,0 +1,108 @@
#include <revolution.h>
#include <revolution/mtx.h>
#include "fake_tgmath.h"
void MTXInitStack(MTXStack* sPtr, u32 numMtx) {
ASSERTMSGLINE(74, sPtr, "MTXInitStack(): NULL MtxStackPtr 'sPtr' ");
ASSERTMSGLINE(75, sPtr->stackBase, "MTXInitStack(): 'sPtr' contains a NULL ptr to stack memory ");
ASSERTMSGLINE(76, numMtx, "MTXInitStack(): 'numMtx' is 0 ");
sPtr->numMtx = numMtx;
sPtr->stackPtr = 0;
}
MtxPtr MTXPush(MTXStack* sPtr, const Mtx m) {
ASSERTMSGLINE(104, sPtr, "MTXPush(): NULL MtxStackPtr 'sPtr' ");
ASSERTMSGLINE(105, sPtr->stackBase, "MTXPush(): 'sPtr' contains a NULL ptr to stack memory ");
ASSERTMSGLINE(106, m, "MTXPush(): NULL MtxPtr 'm' ");
if (sPtr->stackPtr == NULL) {
sPtr->stackPtr = sPtr->stackBase;
MTXCopy(m, sPtr->stackPtr);
} else {
ASSERTMSGLINE(121, ((((s32)sPtr->stackPtr - (s32)sPtr->stackBase) / 16) / 3) < (sPtr->numMtx - 1), "MTXPush(): stack overflow ");
MTXCopy(m, sPtr->stackPtr + 3);
sPtr->stackPtr += 3;
}
return sPtr->stackPtr;
}
MtxPtr MTXPushFwd(MTXStack* sPtr, const Mtx m) {
ASSERTMSGLINE(157, sPtr, "MTXPushFwd(): NULL MtxStackPtr 'sPtr' ");
ASSERTMSGLINE(158, sPtr->stackBase, "MTXPushFwd(): 'sPtr' contains a NULL ptr to stack memory ");
ASSERTMSGLINE(159, m, "MTXPushFwd(): NULL MtxPtr 'm' ");
if (sPtr->stackPtr == NULL) {
sPtr->stackPtr = sPtr->stackBase;
MTXCopy(m, sPtr->stackPtr);
} else {
ASSERTMSGLINE(174, ((((s32)sPtr->stackPtr - (s32)sPtr->stackBase) / 16) / 3) < (sPtr->numMtx - 1), "MTXPushFwd(): stack overflow");
MTXConcat(sPtr->stackPtr, m, sPtr->stackPtr + 3);
sPtr->stackPtr += 3;
}
return sPtr->stackPtr;
}
MtxPtr MTXPushInv(MTXStack* sPtr, const Mtx m) {
Mtx mInv;
ASSERTMSGLINE(216, sPtr, "MTXPushInv(): NULL MtxStackPtr 'sPtr' ");
ASSERTMSGLINE(217, sPtr->stackBase, "MTXPushInv(): 'sPtr' contains a NULL ptr to stack memory ");
ASSERTMSGLINE(218, m, "MTXPushInv(): NULL MtxPtr 'm' ");
MTXInverse(m, mInv);
if (sPtr->stackPtr == NULL) {
sPtr->stackPtr = sPtr->stackBase;
MTXCopy(mInv, sPtr->stackPtr);
} else {
ASSERTMSGLINE(236, ((((s32)sPtr->stackPtr - (s32)sPtr->stackBase) / 16) / 3) < (sPtr->numMtx - 1), "MTXPushInv(): stack overflow");
MTXConcat(mInv, sPtr->stackPtr, sPtr->stackPtr + 3);
sPtr->stackPtr += 3;
}
return sPtr->stackPtr;
}
MtxPtr MTXPushInvXpose(MTXStack* sPtr, const Mtx m) {
Mtx mIT;
ASSERTMSGLINE(279, sPtr, "MTXPushInvXpose(): NULL MtxStackPtr 'sPtr' ");
ASSERTMSGLINE(280, sPtr->stackBase, "MTXPushInvXpose(): 'sPtr' contains a NULL ptr to stack memory ");
ASSERTMSGLINE(281, m, "MTXPushInvXpose(): NULL MtxPtr 'm' ");
MTXInverse(m, mIT);
MTXTranspose(mIT, mIT);
if (sPtr->stackPtr == NULL) {
sPtr->stackPtr = sPtr->stackBase;
MTXCopy(mIT, sPtr->stackPtr);
} else {
ASSERTMSGLINE(300, ((((s32)sPtr->stackPtr - (s32)sPtr->stackBase) / 16) / 3) < (sPtr->numMtx - 1), "MTXPushInvXpose(): stack overflow ");
MTXConcat(sPtr->stackPtr, mIT, sPtr->stackPtr + 3);
sPtr->stackPtr += 3;
}
return sPtr->stackPtr;
}
MtxPtr MTXPop(MTXStack* sPtr) {
ASSERTMSGLINE(328, sPtr, "MTXPop(): NULL MtxStackPtr 'sPtr' ");
ASSERTMSGLINE(329, sPtr->stackBase, "MTXPop(): 'sPtr' contains a NULL ptr to stack memory ");
if (sPtr->stackPtr == NULL) {
return NULL;
}
if (sPtr->stackBase == sPtr->stackPtr) {
sPtr->stackPtr = NULL;
return NULL;
}
sPtr->stackPtr -= 3;
return sPtr->stackPtr;
}
MtxPtr MTXGetStackPtr(const MTXStack* sPtr) {
ASSERTMSGLINE(366, sPtr, "MTXGetStackPtr(): NULL MtxStackPtr 'sPtr' ");
ASSERTMSGLINE(367, sPtr->stackBase, "MTXGetStackPtr(): 'sPtr' contains a NULL ptr to stack memory ");
return sPtr->stackPtr;
}
+204
View File
@@ -0,0 +1,204 @@
#include <revolution.h>
#include <revolution/mtx.h>
#include <math.h>
void C_MTXMultVec(const Mtx m, const Vec* src, Vec* dst) {
Vec vTmp;
ASSERTMSGLINE(72, m, "MTXMultVec(): NULL MtxPtr 'm' ");
ASSERTMSGLINE(73, src, "MTXMultVec(): NULL VecPtr 'src' ");
ASSERTMSGLINE(74, dst, "MTXMultVec(): NULL VecPtr 'dst' ");
vTmp.x = m[0][3] + ((m[0][2] * src->z) + ((m[0][0] * src->x) + (m[0][1] * src->y)));
vTmp.y = m[1][3] + ((m[1][2] * src->z) + ((m[1][0] * src->x) + (m[1][1] * src->y)));
vTmp.z = m[2][3] + ((m[2][2] * src->z) + ((m[2][0] * src->x) + (m[2][1] * src->y)));
dst->x = vTmp.x;
dst->y = vTmp.y;
dst->z = vTmp.z;
}
asm void PSMTXMultVec(const __REGISTER Mtx m, const __REGISTER Vec* src, __REGISTER Vec* dst) {
nofralloc
psq_l f0, Vec.x(src), 0, 0
psq_l f2, 0(m), 0, 0
psq_l f1, Vec.z(src), 1, 0
ps_mul f4, f2, f0
psq_l f3, 8(m), 0, 0
ps_madd f5, f3, f1, f4
psq_l f8, 16(m), 0, 0
ps_sum0 f6, f5, f6, f5
psq_l f9, 24(m), 0, 0
ps_mul f10, f8, f0
psq_st f6, Vec.x(dst), 1, 0
ps_madd f11, f9, f1, f10
psq_l f2, 32(m), 0, 0
ps_sum0 f12, f11, f12, f11
psq_l f3, 40(m), 0, 0
ps_mul f4, f2, f0
psq_st f12, Vec.y(dst), 1, 0
ps_madd f5, f3, f1, f4
ps_sum0 f6, f5, f6, f5
psq_st f6, Vec.z(dst), 1, 0
blr
}
void C_MTXMultVecArray(const Mtx m, const Vec* srcBase, Vec* dstBase, u32 count) {
u32 i;
Vec vTmp;
ASSERTMSGLINE(168, m, "MTXMultVecArray(): NULL MtxPtr 'm' ");
ASSERTMSGLINE(169, srcBase, "MTXMultVecArray(): NULL VecPtr 'srcBase' ");
ASSERTMSGLINE(170, dstBase, "MTXMultVecArray(): NULL VecPtr 'dstBase' ");
ASSERTMSGLINE(171, count > 1, "MTXMultVecArray(): count must be greater than 1.");
for(i = 0; i < count; i++) {
vTmp.x = m[0][3] + ((m[0][2] * srcBase->z) + ((m[0][0] * srcBase->x) + (m[0][1] * srcBase->y)));
vTmp.y = m[1][3] + ((m[1][2] * srcBase->z) + ((m[1][0] * srcBase->x) + (m[1][1] * srcBase->y)));
vTmp.z = m[2][3] + ((m[2][2] * srcBase->z) + ((m[2][0] * srcBase->x) + (m[2][1] * srcBase->y)));
dstBase->x = vTmp.x;
dstBase->y = vTmp.y;
dstBase->z = vTmp.z;
srcBase++;
dstBase++;
}
}
asm void PSMTXMultVecArray(const __REGISTER Mtx m, const __REGISTER Vec* srcBase, __REGISTER Vec* dstBase, __REGISTER u32 count) {
nofralloc
psq_l f13, 0x0(m), 0, 0
psq_l f12, 0x10(m), 0, 0
subi count, count, 0x1
psq_l f11, 0x8(m), 0, 0
ps_merge00 f0, f13, f12
subi dstBase, dstBase, 0x4
psq_l f10, 0x18(m), 0, 0
ps_merge11 f1, f13, f12
mtctr count
psq_l f4, 0x20(m), 0, 0
ps_merge00 f2, f11, f10
psq_l f5, 0x28(m), 0, 0
ps_merge11 f3, f11, f10
psq_l f6, 0x0(srcBase), 0, 0
psq_lu f7, 0x8(srcBase), 1, 0
ps_madds0 f8, f0, f6, f3
ps_mul f9, f4, f6
ps_madds1 f8, f1, f6, f8
ps_madd f10, f5, f7, f9
L_000003C4:
psq_lu f6, 0x4(srcBase), 0, 0
ps_madds0 f12, f2, f7, f8
psq_lu f7, 0x8(srcBase), 1, 0
ps_sum0 f13, f10, f9, f10
ps_madds0 f8, f0, f6, f3
ps_mul f9, f4, f6
psq_stu f12, 0x4(dstBase), 0, 0
ps_madds1 f8, f1, f6, f8
psq_stu f13, 0x8(dstBase), 1, 0
ps_madd f10, f5, f7, f9
bdnz L_000003C4
ps_madds0 f12, f2, f7, f8
ps_sum0 f13, f10, f9, f10
psq_stu f12, 0x4(dstBase), 0, 0
psq_stu f13, 0x8(dstBase), 1, 0
blr
}
void C_MTXMultVecSR(const Mtx m, const Vec* src, Vec* dst) {
Vec vTmp;
ASSERTMSGLINE(319, m, "MTXMultVecSR(): NULL MtxPtr 'm' ");
ASSERTMSGLINE(320, src, "MTXMultVecSR(): NULL VecPtr 'src' ");
ASSERTMSGLINE(321, dst, "MTXMultVecSR(): NULL VecPtr 'dst' ");
vTmp.x = (m[0][2] * src->z) + ((m[0][0] * src->x) + (m[0][1] * src->y));
vTmp.y = (m[1][2] * src->z) + ((m[1][0] * src->x) + (m[1][1] * src->y));
vTmp.z = (m[2][2] * src->z) + ((m[2][0] * src->x) + (m[2][1] * src->y));
dst->x = vTmp.x;
dst->y = vTmp.y;
dst->z = vTmp.z;
}
asm void PSMTXMultVecSR(const __REGISTER Mtx m, const __REGISTER Vec* src, __REGISTER Vec* dst) {
nofralloc
psq_l f0, 0x0(m), 0, 0
psq_l f6, 0x0(src), 0, 0
psq_l f2, 0x10(m), 0, 0
ps_mul f8, f0, f6
psq_l f4, 0x20(m), 0, 0
ps_mul f10, f2, f6
psq_l f7, 0x8(src), 1, 0
ps_mul f12, f4, f6
psq_l f3, 0x18(m), 0, 0
ps_sum0 f8, f8, f8, f8
psq_l f5, 0x28(m), 0, 0
ps_sum0 f10, f10, f10, f10
psq_l f1, 0x8(m), 0, 0
ps_sum0 f12, f12, f12, f12
ps_madd f9, f1, f7, f8
psq_st f9, 0x0(dst), 1, 0
ps_madd f11, f3, f7, f10
psq_st f11, 0x4(dst), 1, 0
ps_madd f13, f5, f7, f12
psq_st f13, 0x8(dst), 1, 0
blr
}
void C_MTXMultVecArraySR(const Mtx m, const Vec* srcBase, Vec* dstBase, u32 count) {
u32 i;
Vec vTmp;
ASSERTMSGLINE(416, m, "MTXMultVecArraySR(): NULL MtxPtr 'm' ");
ASSERTMSGLINE(417, srcBase, "MTXMultVecArraySR(): NULL VecPtr 'srcBase' ");
ASSERTMSGLINE(418, dstBase, "MTXMultVecArraySR(): NULL VecPtr 'dstBase' ");
ASSERTMSGLINE(419, count > 1, "MTXMultVecArraySR(): count must be greater than 1.");
for(i = 0; i < count; i++) {
vTmp.x = (m[0][2] * srcBase->z) + ((m[0][0] * srcBase->x) + (m[0][1] * srcBase->y));
vTmp.y = (m[1][2] * srcBase->z) + ((m[1][0] * srcBase->x) + (m[1][1] * srcBase->y));
vTmp.z = (m[2][2] * srcBase->z) + ((m[2][0] * srcBase->x) + (m[2][1] * srcBase->y));
dstBase->x = vTmp.x;
dstBase->y = vTmp.y;
dstBase->z = vTmp.z;
srcBase++;
dstBase++;
}
}
asm void PSMTXMultVecArraySR(const __REGISTER Mtx m, const __REGISTER Vec* srcBase, __REGISTER Vec* dstBase, __REGISTER u32 count) {
nofralloc
psq_l f13, 0x0(m), 0, 0
psq_l f12, 0x10(m), 0, 0
subi count, count, 0x1
psq_l f11, 0x8(m), 1, 0
ps_merge00 f0, f13, f12
subi dstBase, dstBase, 0x4
psq_l f10, 0x18(m), 1, 0
ps_merge11 f1, f13, f12
mtctr count
psq_l f3, 0x20(m), 0, 0
ps_merge00 f2, f11, f10
psq_l f4, 0x28(m), 1, 0
psq_l f6, 0x0(srcBase), 0, 0
psq_lu f7, 0x8(srcBase), 1, 0
ps_muls0 f8, f0, f6
ps_mul f9, f3, f6
ps_madds1 f8, f1, f6, f8
ps_madd f10, f4, f7, f9
L_000007D0:
psq_lu f6, 0x4(srcBase), 0, 0
ps_madds0 f12, f2, f7, f8
psq_lu f7, 0x8(srcBase), 1, 0
ps_sum0 f13, f10, f9, f9
ps_muls0 f8, f0, f6
ps_mul f9, f3, f6
psq_stu f12, 0x4(dstBase), 0, 0
ps_madds1 f8, f1, f6, f8
psq_stu f13, 0x8(dstBase), 1, 0
ps_madd f10, f4, f7, f9
bdnz L_000007D0
ps_madds0 f12, f2, f7, f8
ps_sum0 f13, f10, f9, f9
psq_stu f12, 0x4(dstBase), 0, 0
psq_stu f13, 0x8(dstBase), 1, 0
blr
}
+336
View File
@@ -0,0 +1,336 @@
#include <revolution.h>
#include <revolution/mtx.h>
#include "fake_tgmath.h"
asm void PSMTXReorder(const __REGISTER Mtx src, __REGISTER ROMtx dest) {
psq_l f0, 0(src), 0, 0
psq_l f2, 16(src), 0, 0
psq_l f4, 32(src), 0, 0
psq_l f1, 8(src), 0, 0
ps_merge00 f6, f0, f2
psq_l f3, 24(src), 0, 0
ps_merge01 f12, f4, f0
psq_l f5, 40(src), 0, 0
ps_merge11 f7, f2, f4
psq_st f6, 0(dest), 0, 0
ps_merge00 f8, f1, f3
psq_st f12, 8(dest), 0, 0
ps_merge01 f9, f5, f1
psq_st f7, 16(dest), 0, 0
ps_merge11 f10, f3, f5
psq_st f8, 24(dest), 0, 0
psq_st f9, 32(dest), 0, 0
psq_st f10, 40(dest), 0, 0
}
asm void PSMTXROMultVecArray(const __REGISTER ROMtx m, const __REGISTER Vec* srcBase, __REGISTER Vec* dstBase, __REGISTER u32 count) {
nofralloc
stwu r1, -64(r1)
stfd f14, 8(r1)
subi r7, count, 1
stfd f15, 16(r1)
srwi r7, r7, 1
stfd f16, 24(r1)
stfd f17, 32(r1)
stfd f18, 40(r1)
mtctr r7
psq_l f0, 0(m), 0, 0
subi srcBase, srcBase, 8
psq_l f1, 8(m), 1, 0
subi dstBase, dstBase, 4
psq_l f6, 36(m), 0, 0
psq_lu f8, 8(srcBase), 0, 0
psq_l f7, 44(m), 1, 0
psq_lu f9, 8(srcBase), 0, 0
ps_madds0 f11, f0, f8, f6
psq_l f2, 12(m), 0, 0
ps_madds0 f12, f1, f8, f7
psq_l f3, 20(m), 1, 0
ps_madds1 f13, f0, f9, f6
psq_lu f10, 8(srcBase), 0, 0
ps_madds1 f14, f1, f9, f7
psq_l f5, 32(m), 1, 0
ps_madds1 f11, f2, f8, f11
ps_madds1 f12, f3, f8, f12
psq_l f4, 24(m), 0, 0
ps_madds0 f13, f2, f10, f13
psq_lu f8, 8(srcBase), 0, 0
ps_madds0 f14, f3, f10, f14
ps_madds0 f15, f4, f9, f11
ps_madds0 f16, f5, f9, f12
psq_lu f9, 8(srcBase), 0, 0
ps_madds1 f17, f4, f10, f13
ps_madds1 f18, f5, f10, f14
psq_lu f10, 8(srcBase), 0, 0
loop:
ps_madds0 f11, f0, f8, f6
psq_stu f15, 4(dstBase), 0, 0
ps_madds0 f12, f1, f8, f7
psq_stu f16, 8(dstBase), 1, 0
ps_madds1 f13, f0, f9, f6
psq_stu f17, 4(dstBase), 0, 0
ps_madds1 f14, f1, f9, f7
psq_stu f18, 8(dstBase), 1, 0
ps_madds1 f11, f2, f8, f11
ps_madds1 f12, f3, f8, f12
psq_lu f8, 8(srcBase), 0, 0
ps_madds0 f13, f2, f10, f13
ps_madds0 f14, f3, f10, f14
ps_madds0 f15, f4, f9, f11
ps_madds0 f16, f5, f9, f12
psq_lu f9, 8(srcBase), 0, 0
ps_madds1 f17, f4, f10, f13
ps_madds1 f18, f5, f10, f14
psq_lu f10, 8(srcBase), 0, 0
bdnz loop
psq_stu f15, 4(dstBase), 0, 0
clrlwi. r7, count, 31
psq_stu f16, 8(dstBase), 1, 0
bne exit
psq_stu f17, 4(dstBase), 0, 0
psq_stu f18, 8(dstBase), 1, 0
exit:
lfd f14, 8(r1)
lfd f15, 16(r1)
lfd f16, 24(r1)
lfd f17, 32(r1)
lfd f18, 40(r1)
addi r1, r1, 64
blr
}
asm void PSMTXROSkin2VecArray(const __REGISTER ROMtx m0, const __REGISTER ROMtx m1, const __REGISTER f32* wtBase, const __REGISTER Vec* srcBase, __REGISTER Vec* dstBase, __REGISTER u32 count) {
nofralloc
stwu r1, -160(r1)
stfd f14, 8(r1)
stfd f15, 16(r1)
stfd f16, 24(r1)
stfd f17, 32(r1)
stfd f18, 40(r1)
stfd f19, 48(r1)
stfd f20, 56(r1)
stfd f21, 64(r1)
stfd f22, 72(r1)
stfd f23, 80(r1)
stfd f24, 88(r1)
stfd f25, 96(r1)
stfd f26, 104(r1)
stfd f27, 112(r1)
stfd f28, 120(r1)
stfd f29, 128(r1)
stfd f30, 136(r1)
subi r9, r8, 1
mtctr r9
subi srcBase, srcBase, 4
subi dstBase, dstBase, 4
subi wtBase, wtBase, 4
psq_l f14, 0(m0), 0, 0
psq_l f22, 0(m1), 0, 0
psq_l f15, 8(m0), 1, 0
psq_l f23, 8(m1), 1, 0
psq_l f16, 12(m0), 0, 0
psq_l f24, 12(m1), 0, 0
ps_sub f22, f22, f14
psq_l f17, 20(m0), 1, 0
psq_l f25, 20(m1), 1, 0
ps_sub f23, f23, f15
psq_l f18, 24(m0), 0, 0
psq_l f26, 24(m1), 0, 0
ps_sub f24, f24, f16
psq_l f19, 32(m0), 1, 0
psq_l f27, 32(m1), 1, 0
ps_sub f25, f25, f17
psq_l f20, 36(m0), 0, 0
psq_l f28, 36(m1), 0, 0
ps_sub f26, f26, f18
psq_l f21, 44(m0), 1, 0
psq_l f29, 44(m1), 1, 0
ps_sub f27, f27, f19
ps_sub f28, f28, f20
ps_sub f29, f29, f21
psq_lu f30, 4(wtBase), 1, 0
psq_lu f8, 4(srcBase), 0, 0
psq_lu f9, 8(srcBase), 1, 0
ps_madds0 f0, f22, f30, f14
ps_madds0 f1, f23, f30, f15
ps_madds0 f2, f24, f30, f16
ps_madds0 f3, f25, f30, f17
ps_madds0 f4, f26, f30, f18
ps_madds0 f5, f27, f30, f19
ps_madds0 f6, f28, f30, f20
ps_madds0 f7, f29, f30, f21
ps_madds0 f12, f0, f8, f6
ps_madds0 f13, f1, f8, f7
psq_lu f30, 4(wtBase), 1, 0
loop:
ps_madds1 f12, f2, f8, f12
ps_madds1 f13, f3, f8, f13
psq_lu f8, 4(srcBase), 0, 0
ps_madds0 f10, f4, f9, f12
ps_madds0 f11, f5, f9, f13
psq_lu f9, 8(srcBase), 1, 0
ps_madds0 f0, f22, f30, f14
ps_madds0 f1, f23, f30, f15
ps_madds0 f2, f24, f30, f16
ps_madds0 f3, f25, f30, f17
ps_madds0 f4, f26, f30, f18
ps_madds0 f5, f27, f30, f19
ps_madds0 f6, f28, f30, f20
ps_madds0 f7, f29, f30, f21
psq_stu f10, 4(dstBase), 0, 0
ps_madds0 f12, f0, f8, f6
ps_madds0 f13, f1, f8, f7
psq_stu f11, 8(dstBase), 1, 0
psq_lu f30, 4(wtBase), 1, 0
bdnz loop
ps_madds1 f12, f2, f8, f12
ps_madds1 f13, f3, f8, f13
ps_madds0 f10, f4, f9, f12
psq_stu f10, 4(dstBase), 0, 0
ps_madds0 f11, f5, f9, f13
psq_stu f11, 8(dstBase), 1, 0
lfd f14, 8(r1)
lfd f15, 16(r1)
lfd f16, 24(r1)
lfd f17, 32(r1)
lfd f18, 40(r1)
lfd f19, 48(r1)
lfd f20, 56(r1)
lfd f21, 64(r1)
lfd f22, 72(r1)
lfd f23, 80(r1)
lfd f24, 88(r1)
lfd f25, 96(r1)
lfd f26, 104(r1)
lfd f27, 112(r1)
lfd f28, 120(r1)
lfd f29, 128(r1)
lfd f30, 136(r1)
addi r1, r1, 160
blr
}
asm void PSMTXROMultS16VecArray(const __REGISTER Mtx m, const __REGISTER S16Vec* srcBase, __REGISTER Vec* dstBase, __REGISTER u32 count) {
nofralloc
stwu r1, -64(r1)
stfd f14, 8(r1)
subi r7, count, 1
stfd f15, 16(r1)
srwi r7, r7, 1
stfd f16, 24(r1)
lis r8, 7
stfd f17, 32(r1)
mtspr GQR6, r8
stfd f18, 40(r1)
mtctr r7
psq_l f0, 0(m), 0, 0
subi srcBase, srcBase, 4
psq_l f1, 8(m), 1, 0
subi dstBase, dstBase, 4
psq_l f6, 36(m), 0, 0
psq_lu f8, 4(srcBase), 0, 6
psq_l f7, 44(m), 1, 0
psq_lu f9, 4(srcBase), 0, 6
ps_madds0 f11, f0, f8, f6
psq_l f2, 12(m), 0, 0
ps_madds0 f12, f1, f8, f7
psq_l f3, 20(m), 1, 0
ps_madds1 f13, f0, f9, f6
psq_lu f10, 4(srcBase), 0, 6
ps_madds1 f14, f1, f9, f7
psq_l f5, 32(m), 1, 0
ps_madds1 f11, f2, f8, f11
ps_madds1 f12, f3, f8, f12
psq_l f4, 24(m), 0, 0
ps_madds0 f13, f2, f10, f13
psq_lu f8, 4(srcBase), 0, 6
ps_madds0 f14, f3, f10, f14
ps_madds0 f15, f4, f9, f11
ps_madds0 f16, f5, f9, f12
psq_lu f9, 4(srcBase), 0, 6
ps_madds1 f17, f4, f10, f13
ps_madds1 f18, f5, f10, f14
psq_lu f10, 4(srcBase), 0, 6
loop:
ps_madds0 f11, f0, f8, f6
psq_stu f15, 4(dstBase), 0, 0
ps_madds0 f12, f1, f8, f7
psq_stu f16, 8(dstBase), 1, 0
ps_madds1 f13, f0, f9, f6
psq_stu f17, 4(dstBase), 0, 0
ps_madds1 f14, f1, f9, f7
psq_stu f18, 8(dstBase), 1, 0
ps_madds1 f11, f2, f8, f11
ps_madds1 f12, f3, f8, f12
psq_lu f8, 4(srcBase), 0, 6
ps_madds0 f13, f2, f10, f13
ps_madds0 f14, f3, f10, f14
ps_madds0 f15, f4, f9, f11
ps_madds0 f16, f5, f9, f12
psq_lu f9, 4(srcBase), 0, 6
ps_madds1 f17, f4, f10, f13
ps_madds1 f18, f5, f10, f14
psq_lu f10, 4(srcBase), 0, 6
bdnz loop
psq_stu f15, 4(dstBase), 0, 0
clrlwi. r7, count, 31
psq_stu f16, 8(dstBase), 1, 0
bne exit
psq_stu f17, 4(dstBase), 0, 0
psq_stu f18, 8(dstBase), 1, 0
exit:
lfd f14, 8(r1)
lfd f15, 16(r1)
lfd f16, 24(r1)
lfd f17, 32(r1)
lfd f18, 40(r1)
addi r1, r1, 64
blr
}
asm void PSMTXMultS16VecArray(const __REGISTER ROMtx* m, const __REGISTER S16Vec* srcBase, __REGISTER Vec* dstBase, __REGISTER u32 count) {
psq_l f0, 0(m), 0, 0
lis r7, 7
mtspr GQR6, r7
psq_l f6, 0(srcBase), 0, 6
subi count, count, 1
psq_l f7, 4(srcBase), 1, 6
mtctr count
psq_l f1, 8(m), 0, 0
addi srcBase, srcBase, 4
psq_l f2, 16(m), 0, 0
subi dstBase, dstBase, 4
psq_l f3, 24(m), 0, 0
ps_mul f8, f0, f6
psq_l f4, 32(m), 0, 0
ps_mul f10, f2, f6
psq_l f5, 40(m), 0, 0
ps_mul f12, f4, f6
psq_lu f6, 2(srcBase), 0, 6
ps_madd f8, f1, f7, f8
ps_madd f10, f3, f7, f10
ps_madd f12, f5, f7, f12
psq_lu f7, 4(srcBase), 1, 6
ps_sum0 f9, f8, f8, f8
loop:
ps_sum0 f11, f10, f10, f10
ps_mul f8, f0, f6
ps_sum0 f13, f12, f12, f12
ps_mul f10, f2, f6
psq_stu f9, 4(dstBase), 1, 0
ps_mul f12, f4, f6
psq_stu f11, 4(dstBase), 1, 0
ps_madd f8, f1, f7, f8
psq_stu f13, 4(dstBase), 1, 0
ps_madd f10, f3, f7, f10
psq_lu f6, 2(srcBase), 0, 6
ps_madd f12, f5, f7, f12
psq_lu f7, 4(srcBase), 1, 6
ps_sum0 f9, f8, f8, f8
bdnz loop
ps_sum0 f11, f10, f10, f10
ps_sum0 f13, f12, f12, f12
psq_stu f9, 4(dstBase), 1, 0
psq_stu f11, 4(dstBase), 1, 0
psq_stu f13, 4(dstBase), 1, 0
}
+486
View File
@@ -0,0 +1,486 @@
#include <revolution.h>
#include <revolution/mtx.h>
#include <math.h>
void C_QUATAdd(const Quaternion* p, const Quaternion* q, Quaternion* r) {
ASSERTMSGLINE(77, p, "QUATAdd(): NULL QuaternionPtr 'p' ");
ASSERTMSGLINE(78, q, "QUATAdd(): NULL QuaternionPtr 'q' ");
ASSERTMSGLINE(79, r, "QUATAdd(): NULL QuaternionPtr 'r' ");
r->x = p->x + q->x;
r->y = p->y + q->y;
r->z = p->z + q->z;
r->w = p->w + q->w;
}
void PSQUATAdd(const __REGISTER Quaternion* p, const __REGISTER Quaternion* q, __REGISTER Quaternion* r) {
__REGISTER f32 pxy, qxy, rxy, pzw, qzw, rzw;
asm {
psq_l pxy, 0(p), 0, 0
psq_l qxy, 0(q), 0, 0
ps_add rxy, pxy, qxy
psq_st rxy, 0(r), 0, 0
psq_l pzw, 8(p), 0, 0
psq_l qzw, 8(q), 0, 0
ps_add rzw, pzw, qzw
psq_st rzw, 8(r), 0, 0
}
}
void C_QUATSubtract(const Quaternion* p, const Quaternion* q, Quaternion* r) {
ASSERTMSGLINE(133, p, "QUATSubtract(): NULL QuaternionPtr 'p' ");
ASSERTMSGLINE(134, q, "QUATSubtract(): NULL QuaternionPtr 'q' ");
ASSERTMSGLINE(135, r, "QUATSubtract(): NULL QuaternionPtr 'r' ");
r->x = p->x - q->x;
r->y = p->y - q->y;
r->z = p->z - q->z;
r->w = p->w - q->w;
}
void PSQUATSubtract(const __REGISTER Quaternion* p, const __REGISTER Quaternion* q, __REGISTER Quaternion* r) {
__REGISTER f32 pxy, qxy, rxy, pzw, qzw, rzw;
asm {
psq_l pxy, 0(p), 0, 0
psq_l qxy, 0(q), 0, 0
ps_sub rxy, pxy, qxy
psq_st rxy, 0(r), 0, 0
psq_l pzw, 8(p), 0, 0
psq_l qzw, 8(q), 0, 0
ps_sub rzw, pzw, qzw
psq_st rzw, 8(r), 0, 0
}
}
void C_QUATMultiply(const Quaternion* p, const Quaternion* q, Quaternion* pq) {
Quaternion* r;
Quaternion pqTmp;
ASSERTMSGLINE(193, p, "QUATMultiply(): NULL QuaternionPtr 'p' ");
ASSERTMSGLINE(194, q, "QUATMultiply(): NULL QuaternionPtr 'q' ");
ASSERTMSGLINE(195, pq, "QUATMultiply(): NULL QuaternionPtr 'pq' ");
if (p == pq || q == pq){
r = &pqTmp;
} else {
r = pq;
}
r->w = (p->w * q->w) - (p->x * q->x) - (p->y * q->y) - (p->z * q->z);
r->x = (p->w * q->x) + (p->x * q->w) + (p->y * q->z) - (p->z * q->y);
r->y = (p->w * q->y) + (p->y * q->w) + (p->z * q->x) - (p->x * q->z);
r->z = (p->w * q->z) + (p->z * q->w) + (p->x * q->y) - (p->y * q->x);
if (r == &pqTmp) {
*pq = pqTmp;
}
}
void PSQUATMultiply(const __REGISTER Quaternion* p, const __REGISTER Quaternion* q, __REGISTER Quaternion* pq) {
__REGISTER f32 pxy, pzw;
__REGISTER f32 qxy, qzw;
__REGISTER f32 pnxy, pnzw, pnxny, pnznw;
__REGISTER f32 rxy, rzw;
__REGISTER f32 sxy, szw;
asm {
psq_l pxy, 0x0(p), 0, 0
psq_l pzw, 0x8(p), 0, 0
psq_l qxy, 0x0(q), 0, 0
ps_neg pnxny, pxy
psq_l qzw, 0x8(q), 0, 0
ps_neg pnznw, pzw
ps_merge01 pnxy, pnxny, pxy
ps_muls0 rxy, pzw, qxy
ps_muls0 rzw, pnxny, qxy
ps_merge01 pnzw, pnznw, pzw
ps_muls1 szw, pnxy, qxy
ps_madds0 rxy, pnxy, qzw, rxy
ps_muls1 sxy, pnzw, qxy
ps_madds0 rzw, pnzw, qzw, rzw
ps_madds1 szw, pnznw, qzw, szw
ps_merge10 rxy, rxy, rxy
ps_madds1 sxy, pxy, qzw, sxy
ps_merge10 rzw, rzw, rzw
ps_add rxy, rxy, sxy
psq_st rxy, 0x0(pq), 0, 0
ps_sub rzw, rzw, szw
psq_st rzw, 0x8(pq), 0, 0
}
}
void C_QUATScale(const Quaternion* q, Quaternion* r, f32 scale) {
ASSERTMSGLINE(306, q, "QUATScale(): NULL QuaternionPtr 'q' ");
ASSERTMSGLINE(307, r, "QUATScale(): NULL QuaternionPtr 'r' ");
r->x = q->x * scale;
r->y = q->y * scale;
r->z = q->z * scale;
r->w = q->w * scale;
}
void PSQUATScale(const __REGISTER Quaternion* q, __REGISTER Quaternion* r, __REGISTER f32 scale) {
__REGISTER f32 rxy, rzw;
asm {
psq_l rxy, 0(q), 0, 0
psq_l rzw, 8(q), 0, 0
ps_muls0 rxy, rxy, scale
psq_st rxy, 0(r), 0, 0
ps_muls0 rzw, rzw, scale
psq_st rzw, 8(r), 0, 0
}
}
f32 C_QUATDotProduct(const Quaternion* p, const Quaternion* q) {
ASSERTMSGLINE(357, p, "QUATDotProduct(): NULL QuaternionPtr 'p' ");
ASSERTMSGLINE(358, q, "QUATDotProduct(): NULL QuaternionPtr 'q' ");
return (q->x * p->x) + (q->y * p->y) + (q->z * p->z) + (q->w * p->w);
}
f32 PSQUATDotProduct(const __REGISTER Quaternion* p, const __REGISTER Quaternion* q) {
__REGISTER f32 pxy, pzw, qxy, qzw, dp;
asm {
psq_l pxy, 0(p), 0, 0
psq_l qxy, 0(q), 0, 0
ps_mul dp, pxy, qxy
psq_l pzw, 8(p), 0, 0
psq_l qzw, 8(q), 0, 0
ps_madd dp, pzw, qzw, dp
ps_sum0 dp, dp, dp, dp
}
return dp;
}
void C_QUATNormalize(const Quaternion* src, Quaternion* unit) {
f32 mag;
ASSERTMSGLINE(407, src, "QUATNormalize(): NULL QuaternionPtr 'src' ");
ASSERTMSGLINE(408, unit, "QUATNormalize(): NULL QuaternionPtr 'unit' ");
mag = (src->x * src->x) + (src->y * src->y) + (src->z * src->z) + (src->w * src->w);
if (mag >= 0.00001f) {
mag = 1.0f / sqrtf(mag);
unit->x = src->x * mag;
unit->y = src->y * mag;
unit->z = src->z * mag;
unit->w = src->w * mag;
} else {
unit->x = unit->y = unit->z = unit->w = 0.0f;
}
}
void PSQUATNormalize(const __REGISTER Quaternion* src, __REGISTER Quaternion* unit) {
__REGISTER f32 sxy, szw;
__REGISTER f32 mag, rsqmag;
__REGISTER f32 diff;
__REGISTER f32 c_zero;
__REGISTER f32 nwork0, nwork1;
__REGISTER f32 epsilon = 0.00001f;
__REGISTER f32 c_half = 0.5f;
__REGISTER f32 c_three = 3.0f;
asm {
psq_l sxy, 0x0(src), 0, 0
ps_mul mag, sxy, sxy
psq_l szw, 0x8(src), 0, 0
ps_sub c_zero, epsilon, epsilon
ps_madd mag, szw, szw, mag
ps_sum0 mag, mag, mag, mag
frsqrte rsqmag, mag
ps_sub diff, mag, epsilon
fmul nwork0, rsqmag, rsqmag
fmul nwork1, rsqmag, c_half
fnmsub nwork0, nwork0, mag, c_three
fmul rsqmag, nwork0, nwork1
ps_sel rsqmag, diff, rsqmag, c_zero
ps_muls0 sxy, sxy, rsqmag
ps_muls0 szw, szw, rsqmag
psq_st sxy, 0x0(unit), 0, 0
psq_st szw, 0x8(unit), 0, 0
}
}
void C_QUATInverse(const Quaternion* src, Quaternion* inv) {
f32 mag, norminv;
ASSERTMSGLINE(498, src, "QUATInverse(): NULL QuaternionPtr 'src' ");
ASSERTMSGLINE(499, inv, "QUATInverse(): NULL QuaternionPtr 'inv' ");
mag = (src->x * src->x) + (src->y * src->y) + (src->z * src->z) + (src->w * src->w);
if (mag == 0.0f) {
mag = 1.0f;
}
norminv = 1.0f / mag;
inv->x = -src->x * norminv;
inv->y = -src->y * norminv;
inv->z = -src->z * norminv;
inv->w = src->w * norminv;
}
void PSQUATInverse(const __REGISTER Quaternion* src, __REGISTER Quaternion* inv) {
__REGISTER f32 sxy, szw;
__REGISTER f32 izz, iww;
__REGISTER f32 mag, nmag;
__REGISTER f32 norminv, nninv;
__REGISTER f32 nwork0;
__REGISTER f32 c_two;
__REGISTER f32 c_zero;
__REGISTER f32 c_one = 1.0f;
asm {
psq_l sxy, 0x0(src), 0, 0
ps_mul mag, sxy, sxy
ps_sub c_zero, c_one, c_one
psq_l szw, 0x8(src), 0, 0
ps_madd mag, szw, szw, mag
ps_add c_two, c_one, c_one
ps_sum0 mag, mag, mag, mag
fcmpu cr0, mag, c_zero
beq L_00000948
fres norminv, mag
ps_neg nmag, mag
ps_nmsub nwork0, mag, norminv, c_two
ps_mul norminv, norminv, nwork0
b L_0000094C
L_00000948:
fmr norminv, c_one
L_0000094C:
ps_neg nninv, norminv
ps_muls1 iww, norminv, szw
ps_muls0 sxy, sxy, nninv
psq_st iww, 0xc(inv), 1, 0
ps_muls0 izz, szw, nninv
psq_st sxy, 0x0(inv), 0, 0
psq_st izz, 0x8(inv), 1, 0
}
}
void C_QUATDivide(const Quaternion* p, const Quaternion* q, Quaternion* r) {
Quaternion qtmp;
ASSERTMSGLINE(606, p, "QUATDivide(): NULL QuaternionPtr 'p' ");
ASSERTMSGLINE(607, q, "QUATDivide(): NULL QuaternionPtr 'q' ");
ASSERTMSGLINE(608, r, "QUATDivide(): NULL QuaternionPtr 'r' ");
C_QUATInverse(q, &qtmp);
C_QUATMultiply(&qtmp, p, r);
}
void PSQUATDivide(const Quaternion* p, const Quaternion* q, Quaternion* r) {
Quaternion qtmp;
PSQUATInverse(q, &qtmp);
PSQUATMultiply(&qtmp, p, r);
}
void C_QUATExp(const Quaternion* q, Quaternion* r) {
f32 theta, scale;
ASSERTMSGLINE(643, q, "QUATExp(): NULL QuaternionPtr 'q' ");
ASSERTMSGLINE(644, r, "QUATExp(): NULL QuaternionPtr 'r' ");
ASSERTMSGLINE(647, q->w == 0.0f, "QUATExp(): 'q' is not a pure quaternion. ");
theta = sqrtf((q->x * q->x) + (q->y * q->y) + (q->z * q->z));
scale = 1.0f;
if (theta > 0.00001f) {
scale = sinf(theta) / theta;
}
r->x = scale * q->x;
r->y = scale * q->y;
r->z = scale * q->z;
r->w = cosf(theta);
}
void C_QUATLogN(const Quaternion* q, Quaternion* r) {
f32 theta, scale, mag;
ASSERTMSGLINE(676, q, "QUATLogN(): NULL QuaternionPtr 'q' ");
ASSERTMSGLINE(677, r, "QUATLogN(): NULL QuaternionPtr 'r' ");
scale = (q->x * q->x) + (q->y * q->y) + (q->z * q->z);
#if DEBUG
mag = scale + (q->z * q->z);
if (mag < 1.0f - 0.00001f || mag > 1.0f + 0.00001f || mag > 1.00001f) {}
#endif
scale = sqrtf(scale);
theta = atan2f(scale, q->w);
if (scale > 0.0f) {
scale = theta / scale;
}
r->x = scale * q->x;
r->y = scale * q->y;
r->z = scale * q->z;
r->w = 0.0f;
}
void C_QUATMakeClosest(const Quaternion* q, const Quaternion* qto, Quaternion* r) {
f32 dot;
ASSERTMSGLINE(722, q, "QUATMakeClosest(): NULL QuaternionPtr 'q' ");
ASSERTMSGLINE(723, qto, "QUATMakeClosest(): NULL QuaternionPtr 'qto' ");
ASSERTMSGLINE(724, r, "QUATMakeClosest(): NULL QuaternionPtr 'r' ");
dot = (q->x * qto->x) + (q->y * qto->y) + (q->z * qto->z) + (q->w * qto->w);
if (dot < 0.0f) {
r->x = -q->x;
r->y = -q->y;
r->z = -q->z;
r->w = -q->w;
} else {
*r = *q;
}
}
void C_QUATRotAxisRad(Quaternion* r, const Vec* axis, f32 rad) {
f32 half, sh, ch;
Vec nAxis;
ASSERTMSGLINE(763, r, "QUATRotAxisRad(): NULL QuaternionPtr 'r' ");
ASSERTMSGLINE(764, axis, "QUATRotAxisRad(): NULL VecPtr 'axis' ");
VECNormalize(axis, &nAxis);
half = rad * 0.5f;
sh = sinf(half);
ch = cosf(half);
r->x = sh * nAxis.x;
r->y = sh * nAxis.y;
r->z = sh * nAxis.z;
r->w = ch;
}
void C_QUATMtx(Quaternion* r, const Mtx m) {
f32 tr,s;
s32 i, j, k;
s32 nxt[3] = {1, 2, 0};
f32 q[3];
ASSERTMSGLINE(791, r, "QUATMtx(): NULL QuaternionPtr 'r' ");
ASSERTMSGLINE(792, m, "QUATMtx(): NULL MtxPtr 'm' ");
tr = m[0][0] + m[1][1] + m[2][2];
if (tr > 0.0f) {
s = sqrtf(tr + 1.0f);
r->w = s * 0.5f;
s = 0.5f / s;
r->x = (m[2][1] - m[1][2]) * s;
r->y = (m[0][2] - m[2][0]) * s;
r->z = (m[1][0] - m[0][1]) * s;
} else {
i = 0;
if (m[1][1] > m[0][0]) {
i = 1;
}
if (m[2][2] > m[i][i]) {
i = 2;
}
j = nxt[i];
k = nxt[j];
s = sqrtf((m[i][i] - (m[j][j] + m[k][k])) + 1.0f);
q[i] = s * 0.5f;
if (s != 0.0f) {
s = 0.5f / s;
}
r->w = (m[k][j] - m[j][k]) * s;
q[j] = (m[i][j] + m[j][i]) * s;
q[k] = (m[i][k] + m[k][i]) * s;
r->x = q[0];
r->y = q[1];
r->z = q[2];
}
}
void C_QUATLerp(const Quaternion* p, const Quaternion* q, Quaternion* r, f32 t) {
ASSERTMSGLINE(842, p, "QUATLerp(): NULL QuaternionPtr 'p' ");
ASSERTMSGLINE(843, q, "QUATLerp(): NULL QuaternionPtr 'q' ");
ASSERTMSGLINE(844, r, "QUATLerp(): NULL QuaternionPtr 'r' ");
r->x = t * (q->x - p->x) + p->x;
r->y = t * (q->y - p->y) + p->y;
r->z = t * (q->z - p->z) + p->z;
r->w = t * (q->w - p->w) + p->w;
}
void C_QUATSlerp(const Quaternion* p, const Quaternion* q, Quaternion* r, f32 t) {
f32 theta, sin_th, cos_th;
f32 tp, tq;
ASSERTMSGLINE(874, p, "QUATSlerp(): NULL QuaternionPtr 'p' ");
ASSERTMSGLINE(875, q, "QUATSlerp(): NULL QuaternionPtr 'q' ");
ASSERTMSGLINE(876, r, "QUATSlerp(): NULL QuaternionPtr 'r' ");
cos_th = p->x * q->x + p->y * q->y + p->z * q->z + p->w * q->w;
tq = 1.0f;
if (cos_th < 0.0f) {
cos_th = -cos_th;
tq = -tq;
}
if (cos_th <= 0.99999f) {
theta = acosf(cos_th);
sin_th = sinf(theta);
tp = sinf((1.0f - t) * theta) / sin_th;
tq *= sinf(t * theta) / sin_th;
} else {
tp = 1.0f - t;
tq *= t;
}
r->x = (tp * p->x) + (tq * q->x);
r->y = (tp * p->y) + (tq * q->y);
r->z = (tp * p->z) + (tq * q->z);
r->w = (tp * p->w) + (tq * q->w);
}
void C_QUATSquad(const Quaternion* p, const Quaternion* a, const Quaternion* b, const Quaternion* q, Quaternion* r, f32 t) {
Quaternion pq, ab;
f32 t2;
ASSERTMSGLINE(927, p, "QUATSquad(): NULL QuaternionPtr 'p' ");
ASSERTMSGLINE(928, a, "QUATSquad(): NULL QuaternionPtr 'a' ");
ASSERTMSGLINE(929, b, "QUATSquad(): NULL QuaternionPtr 'b' ");
ASSERTMSGLINE(930, q, "QUATSquad(): NULL QuaternionPtr 'q' ");
ASSERTMSGLINE(931, r, "QUATSquad(): NULL QuaternionPtr 'r' ");
t2 = 2.0f * t * (1.0f - t);
C_QUATSlerp(p, q, &pq, t);
C_QUATSlerp(a, b, &ab, t);
C_QUATSlerp(&pq, &ab, r, t2);
}
void C_QUATCompA(const Quaternion* qprev, const Quaternion* q, const Quaternion* qnext, Quaternion* a) {
Quaternion qm, qp, lqm, lqp, qpqm, exq;
ASSERTMSGLINE(958, qprev, "QUATCompA(): NULL QuaternionPtr 'qprev' ");
ASSERTMSGLINE(959, q, "QUATCompA(): NULL QuaternionPtr 'q' ");
ASSERTMSGLINE(960, qnext, "QUATCompA(): NULL QuaternionPtr 'qnext' ");
ASSERTMSGLINE(961, a, "QUATCompA(): NULL QuaternionPtr 'a' ");
C_QUATDivide(qprev, q, &qm);
C_QUATLogN(&qm, &lqm);
C_QUATDivide(qnext, q, &qp);
C_QUATLogN(&qp, &lqp);
C_QUATAdd(&lqp, &lqm, &qpqm);
C_QUATScale(&qpqm, &qpqm, -0.25f);
C_QUATExp(&qpqm, &exq);
C_QUATMultiply(q, &exq, a);
}
+344
View File
@@ -0,0 +1,344 @@
#include <revolution.h>
#include <revolution/mtx.h>
#include <math.h>
void C_VECAdd(const Vec* a, const Vec* b, Vec* ab) {
ASSERTMSGLINE(114, a, "VECAdd(): NULL VecPtr 'a' ");
ASSERTMSGLINE(115, b, "VECAdd(): NULL VecPtr 'b' ");
ASSERTMSGLINE(116, ab, "VECAdd(): NULL VecPtr 'ab' ");
ab->x = a->x + b->x;
ab->y = a->y + b->y;
ab->z = a->z + b->z;
}
asm void PSVECAdd(const __REGISTER Vec* a, const __REGISTER Vec* b, __REGISTER Vec* ab) {
psq_l f2, Vec.x(a), 0, 0
psq_l f4, Vec.x(b), 0, 0
ps_add f6, f2, f4
psq_st f6, Vec.x(ab), 0, 0
psq_l f3, Vec.z(a), 1, 0
psq_l f5, Vec.z(b), 1, 0
ps_add f7, f3, f5
psq_st f7, Vec.z(ab), 1, 0
}
void C_VECSubtract(const Vec* a, const Vec* b, Vec* a_b) {
ASSERTMSGLINE(183, a, "VECSubtract(): NULL VecPtr 'a' ");
ASSERTMSGLINE(184, b, "VECSubtract(): NULL VecPtr 'b' ");
ASSERTMSGLINE(185, a_b, "VECSubtract(): NULL VecPtr 'a_b' ");
a_b->x = a->x - b->x;
a_b->y = a->y - b->y;
a_b->z = a->z - b->z;
}
asm void PSVECSubtract(const __REGISTER Vec* a, const __REGISTER Vec* b, __REGISTER Vec* a_b) {
psq_l f2, Vec.x(a), 0, 0
psq_l f4, Vec.x(b), 0, 0
ps_sub f6, f2, f4
psq_st f6, Vec.x(a_b), 0, 0
psq_l f3, Vec.z(a), 1, 0
psq_l f5, Vec.z(b), 1, 0
ps_sub f7, f3, f5
psq_st f7, Vec.z(a_b), 1, 0
}
void C_VECScale(const Vec* src, Vec* dst, f32 scale) {
ASSERTMSGLINE(253, src, "VECScale(): NULL VecPtr 'src' ");
ASSERTMSGLINE(254, dst, "VECScale(): NULL VecPtr 'dst' ");
dst->x = (src->x * scale);
dst->y = (src->y * scale);
dst->z = (src->z * scale);
}
void PSVECScale(const __REGISTER Vec* src, __REGISTER Vec* dst, __REGISTER f32 scale) {
__REGISTER f32 vxy, vz, rxy, rz;
asm {
psq_l vxy, 0x0(src), 0, 0
psq_l vz, 0x8(src), 1, 0
ps_muls0 rxy, vxy, scale
psq_st rxy, 0x0(dst), 0, 0
ps_muls0 rz, vz, scale
psq_st rz, 0x8(dst), 1, 0
}
}
void C_VECNormalize(const Vec* src, Vec* unit) {
f32 mag;
ASSERTMSGLINE(321, src, "VECNormalize(): NULL VecPtr 'src' ");
ASSERTMSGLINE(322, unit, "VECNormalize(): NULL VecPtr 'unit' ");
mag = (src->z * src->z) + ((src->x * src->x) + (src->y * src->y));
ASSERTMSGLINE(327, 0.0f != mag, "VECNormalize(): zero magnitude vector ");
mag = 1.0f/ sqrtf(mag);
unit->x = src->x * mag;
unit->y = src->y * mag;
unit->z = src->z * mag;
}
void PSVECNormalize(const __REGISTER Vec* src, __REGISTER Vec* unit) {
__REGISTER float c_half = 0.5f;
__REGISTER float c_three = 3.0f;
__REGISTER float v1_xy;
__REGISTER float v1_z;
__REGISTER float xx_zz;
__REGISTER float xx_yy;
__REGISTER float sqsum;
__REGISTER float rsqrt;
__REGISTER float nwork0;
__REGISTER float nwork1;
asm {
psq_l v1_xy, 0x0(src), 0, 0
ps_mul xx_yy, v1_xy, v1_xy
psq_l v1_z, 0x8(src), 1, 0
ps_madd xx_zz, v1_z, v1_z, xx_yy
ps_sum0 sqsum, xx_zz, v1_z, xx_yy
frsqrte rsqrt, sqsum
fmuls nwork0, rsqrt, rsqrt
fmuls nwork1, rsqrt, c_half
fnmsubs nwork0, nwork0, sqsum, c_three
fmuls rsqrt, nwork0, nwork1
ps_muls0 v1_xy, v1_xy, rsqrt
psq_st v1_xy, 0x0(unit), 0, 0
ps_muls0 v1_z, v1_z, rsqrt
psq_st v1_z, 0x8(unit), 1, 0
}
}
f32 C_VECSquareMag(const Vec* v) {
f32 sqmag;
ASSERTMSGLINE(411, v, "VECMag(): NULL VecPtr 'v' ");
sqmag = v->z * v->z + ((v->x * v->x) + (v->y * v->y));
return sqmag;
}
f32 PSVECSquareMag(const __REGISTER Vec* v) {
__REGISTER f32 vxy, vzz, sqmag;
asm {
psq_l vxy, 0x0(v), 0, 0
ps_mul vxy, vxy, vxy
lfs vzz, 0x8(v)
ps_madd sqmag, vzz, vzz, vxy
ps_sum0 sqmag, sqmag, vxy, vxy
}
return sqmag;
}
f32 C_VECMag(const Vec* v) {
return sqrtf(C_VECSquareMag(v));
}
f32 PSVECMag(const __REGISTER Vec* v) {
__REGISTER f32 vxy, vzz;
__REGISTER f32 sqmag, rmag;
__REGISTER f32 nwork0, nwork1;
__REGISTER f32 c_three, c_half, c_zero;
c_half = 0.5f;
asm {
psq_l vxy, 0x0(v), 0, 0
ps_mul vxy, vxy, vxy
lfs vzz, 0x8(v)
fsubs c_zero, c_half, c_half
ps_madd sqmag, vzz, vzz, vxy
ps_sum0 sqmag, sqmag, vxy, vxy
fcmpu cr0, sqmag, c_zero
beq L_000005F0
frsqrte rmag, sqmag
}
c_three = 3.0f;
asm {
fmuls nwork0, rmag, rmag
fmuls nwork1, rmag, c_half
fnmsubs nwork0, nwork0, sqmag, c_three
fmuls rmag, nwork0, nwork1
fmuls sqmag, sqmag, rmag
L_000005F0:
}
return sqmag;
}
f32 C_VECDotProduct(const Vec* a, const Vec* b) {
f32 dot;
ASSERTMSGLINE(546, a, "VECDotProduct(): NULL VecPtr 'a' ");
ASSERTMSGLINE(547, b, "VECDotProduct(): NULL VecPtr 'b' ");
dot = (a->z * b->z) + ((a->x * b->x) + (a->y * b->y));
return dot;
}
asm f32 PSVECDotProduct(const __REGISTER Vec* a, const __REGISTER Vec* b) {
psq_l f2, Vec.y(a), 0, 0
psq_l f3, Vec.y(b), 0, 0
ps_mul f2, f2, f3
psq_l f5, Vec.x(a), 0, 0
psq_l f4, Vec.x(b), 0, 0
ps_madd f3, f5, f4, f2
ps_sum0 f1, f3, f2, f2
}
void C_VECCrossProduct(const Vec* a, const Vec* b, Vec* axb) {
Vec vTmp;
ASSERTMSGLINE(608, a, "VECCrossProduct(): NULL VecPtr 'a' ");
ASSERTMSGLINE(609, b, "VECCrossProduct(): NULL VecPtr 'b' ");
ASSERTMSGLINE(610, axb, "VECCrossProduct(): NULL VecPtr 'axb' ");
vTmp.x = (a->y * b->z) - (a->z * b->y);
vTmp.y = (a->z * b->x) - (a->x * b->z);
vTmp.z = (a->x * b->y) - (a->y * b->x);
axb->x = vTmp.x;
axb->y = vTmp.y;
axb->z = vTmp.z;
}
asm void PSVECCrossProduct(const __REGISTER Vec* a, const __REGISTER Vec* b, __REGISTER Vec* axb) {
psq_l f1, Vec.x(b), 0, 0
lfs f2, Vec.z(a)
psq_l f0, Vec.x(a), 0, 0
ps_merge10 f6, f1, f1
lfs f3, Vec.z(b)
ps_mul f4, f1, f2
ps_muls0 f7, f1, f0
ps_msub f5, f0, f3, f4
ps_msub f8, f0, f6, f7
ps_merge11 f9, f5, f5
ps_merge01 f10, f5, f8
psq_st f9, Vec.x(axb), 1, 0
ps_neg f10, f10
psq_st f10, Vec.y(axb), 0, 0
}
void C_VECHalfAngle(const Vec* a, const Vec* b, Vec* half) {
Vec aTmp;
Vec bTmp;
Vec hTmp;
ASSERTMSGLINE(713, a, "VECHalfAngle(): NULL VecPtr 'a' ");
ASSERTMSGLINE(714, b, "VECHalfAngle(): NULL VecPtr 'b' ");
ASSERTMSGLINE(715, half, "VECHalfAngle(): NULL VecPtr 'half' ");
aTmp.x = -a->x;
aTmp.y = -a->y;
aTmp.z = -a->z;
bTmp.x = -b->x;
bTmp.y = -b->y;
bTmp.z = -b->z;
VECNormalize(&aTmp, &aTmp);
VECNormalize(&bTmp, &bTmp);
VECAdd(&aTmp, &bTmp, &hTmp);
if (VECDotProduct(&hTmp, &hTmp) > 0.0f) {
VECNormalize(&hTmp, half);
return;
}
*half = hTmp;
}
void C_VECReflect(const Vec* src, const Vec* normal, Vec* dst) {
f32 cosA;
Vec uI;
Vec uN;
ASSERTMSGLINE(769, src, "VECReflect(): NULL VecPtr 'src' ");
ASSERTMSGLINE(770, normal, "VECReflect(): NULL VecPtr 'normal' ");
ASSERTMSGLINE(771, dst, "VECReflect(): NULL VecPtr 'dst' ");
uI.x = -src->x;
uI.y = -src->y;
uI.z = -src->z;
VECNormalize(&uI, &uI);
VECNormalize(normal, &uN);
cosA = VECDotProduct(&uI, &uN);
dst->x = (2.0f * uN.x * cosA) - uI.x;
dst->y = (2.0f * uN.y * cosA) - uI.y;
dst->z = (2.0f * uN.z * cosA) - uI.z;
VECNormalize(dst, dst);
}
f32 C_VECSquareDistance(const Vec* a, const Vec* b) {
Vec diff;
diff.x = a->x - b->x;
diff.y = a->y - b->y;
diff.z = a->z - b->z;
return (diff.z * diff.z) + ((diff.x * diff.x) + (diff.y * diff.y));
}
f32 PSVECSquareDistance(const __REGISTER Vec* a, const __REGISTER Vec* b) {
__REGISTER f32 v0yz, v1yz, v0xy, v1xy, dyz, dxy;
__REGISTER f32 sqdist;
asm {
psq_l v0yz, 0x4(a), 0, 0
psq_l v1yz, 0x4(b), 0, 0
ps_sub dyz, v0yz, v1yz
psq_l v0xy, 0x0(a), 0, 0
psq_l v1xy, 0x0(b), 0, 0
ps_mul dyz, dyz, dyz
ps_sub dxy, v0xy, v1xy
ps_madd sqdist, dxy, dxy, dyz
ps_sum0 sqdist, sqdist, dyz, dyz
}
return sqdist;
}
f32 C_VECDistance(const Vec* a, const Vec* b) {
return sqrtf(C_VECSquareDistance(a, b));
}
f32 PSVECDistance(const __REGISTER Vec* a, const __REGISTER Vec* b) {
__REGISTER f32 v0yz, v1yz, v0xy, v1xy, dyz, dxy;
__REGISTER f32 sqdist, rdist;
__REGISTER f32 nwork0, nwork1;
__REGISTER f32 c_half, c_three, c_zero;
asm {
psq_l v0yz, 0x4(a), 0, 0
psq_l v1yz, 0x4(b), 0, 0
ps_sub dyz, v0yz, v1yz
psq_l v0xy, 0x0(a), 0, 0
psq_l v1xy, 0x0(b), 0, 0
ps_mul dyz, dyz, dyz
ps_sub dxy, v0xy, v1xy
}
c_half = 0.5f;
asm {
ps_madd sqdist, dxy, dxy, dyz
fsubs c_zero, c_half, c_half
ps_sum0 sqdist, sqdist, dyz, dyz
fcmpu cr0, c_zero, sqdist
beq L_00000CBC
}
c_three = 3.0f;
asm {
frsqrte rdist, sqdist
fmuls nwork0, rdist, rdist
fmuls nwork1, rdist, c_half
fnmsubs nwork0, nwork0, sqdist, c_three
fmuls rdist, nwork0, nwork1
fmuls sqdist, sqdist, rdist
L_00000CBC:
}
return sqdist;
}
+123
View File
@@ -0,0 +1,123 @@
#include <revolution/sc.h>
u8 SCGetAspectRatio(void) {
u8 aspect;
if (!SCFindU8Item(&aspect, SC_ITEM_ID_IPL_ASPECT_RATIO)) {
aspect = 0;
} else {
if (aspect != 1) {
aspect = 0;
}
}
return aspect;
}
s8 SCGetDisplayOffsetH(void) {
s8 offset;
if (!SCFindS8Item(&offset, SC_ITEM_ID_IPL_DISPLAY_OFFSET_H)) {
offset = 0;
} else {
if (offset < -32) {
offset = -32;
} else if (offset > 32) {
offset = 32;
}
}
offset &= ~1;
return offset;
}
u8 SCGetEuRgb60Mode(void) {
u8 mode;
if (!SCFindU8Item(&mode, SC_ITEM_ID_IPL_EURGB60_MODE)) {
mode = 0;
} else {
if (mode != 1) {
mode = 0;
}
}
return mode;
}
BOOL SCGetIdleMode(SCIdleModeInfo* info) {
return SCFindByteArrayItem(info, sizeof(*info), SC_ITEM_ID_IPL_IDLE_MODE);
}
u8 SCGetLanguage(void) {
u8 lang;
s8 area;
if (!SCFindU8Item(&lang, SC_ITEM_ID_IPL_LANGUAGE)) {
area = SCGetProductArea();
if (area == 0) {
lang = SC_LANG_JAPANESE;
} else {
lang = SC_LANG_ENGLISH;
}
} else {
if (lang > SC_LANG_KOREAN) {
lang = SC_LANG_ENGLISH;
}
}
return lang;
}
u8 SCGetProgressiveMode(void) {
u8 mode;
if (!SCFindU8Item(&mode, SC_ITEM_ID_IPL_PROGRESSIVE_MODE)) {
mode = 0;
} else {
if (mode != 1) {
mode = 0;
}
}
return mode;
}
u8 SCGetScreenSaverMode(void) {
u8 mode;
if (!SCFindU8Item(&mode, SC_ITEM_ID_IPL_SCREEN_SAVER_MODE)) {
mode = 1;
} else {
if (mode != 1) {
mode = 0;
}
}
return mode;
}
u8 SCGetSoundMode(void) {
u8 mode;
if (!SCFindU8Item(&mode, SC_ITEM_ID_IPL_SOUND_MODE)) {
mode = 1;
} else {
if (mode != 0 && mode != 1 && mode != 2) {
mode = 1;
}
}
return mode;
}
u32 SCGetCounterBias(void) {
u32 bias;
if (!SCFindU32Item(&bias, SC_ITEM_ID_IPL_COUNTER_BIAS)) {
bias = 189388800;
}
return bias;
}
+136
View File
@@ -0,0 +1,136 @@
#include <revolution/sc.h>
#include <revolution/os.h>
#include <string.h>
typedef struct {
s8 area;
char string[4];
} SCProductAreaAndString;
static SCProductAreaAndString ProductAreaAndStringTbl[] = {
0, "JPN",
1, "USA",
2, "EUR",
3, "AUS",
4, "BRA",
5, "TWN",
5, "ROC",
6, "KOR",
7, "HKG",
8, "ASI",
9, "LTN",
10, "SAF",
11, "CHN",
-1
};
BOOL __SCF1(const char* keyword, char* buf, u32 bufSize) {
BOOL result = FALSE;
u8* p = (u8*)OSPhysicalToCached(0x3800);
u32 size = 0x100, i, seed = 0x73b5dbfa, kwOffset = 0;
u8 data;
u32 bufOffset = 0;
for (i = 0; i < size; i++) {
data = p[i];
if (data != 0) {
data ^= seed;
if (keyword[kwOffset] == '\0') {
if (data == '=') {
result = TRUE;
break;
}
}
if (((keyword[kwOffset] ^ data) & 0xDF) == 0) {
kwOffset++;
}
else {
kwOffset = 0;
}
}
seed = (u32)((seed >> 31) | (seed << 1));
}
if (result) {
i++;
while (i < size && bufOffset < bufSize) {
seed = (u32)((seed >> 31) | (seed << 1));
data = p[i];
if (data != 0) {
data ^= seed;
if (data == '\x0d' || data == '\x0a') {
data = 0;
}
}
buf[bufOffset] = (char)data;
bufOffset++;
if (data == 0) {
return TRUE;
}
i++;
}
}
return FALSE;
}
BOOL SCGetProductAreaString(char* buf, u32 bufSize) {
return __SCF1("AREA", buf, bufSize);
}
s8 SCGetProductArea(void) {
char buf[4];
SCProductAreaAndString* p = ProductAreaAndStringTbl;
if (SCGetProductAreaString(buf, sizeof(buf))) {
while (p->area != -1) {
if (strcmp(p->string, buf) == 0) {
return p->area;
}
p++;
}
}
return -1;
}
typedef struct {
s8 game;
char string[3];
} SCProductGameRegionAndString;
static SCProductGameRegionAndString ProductGameRegionAndStringTbl[] = {
0, "JP",
1, "US",
2, "EU",
4, "KR",
5, "CN",
-1
};
s8 SCGetProductGameRegion(void) {
char buf[3];
SCProductGameRegionAndString* p = ProductGameRegionAndStringTbl;
if (__SCF1("GAME", buf, sizeof(buf))) {
while (p->game != -1) {
if (strcmp(p->string, buf) == 0) {
return p->game;
}
p++;
}
}
return -1;
}
+996
View File
@@ -0,0 +1,996 @@
#include <revolution/types.h>
#include <revolution/sc.h>
#include <string.h>
// #include <mem.h>
#ifdef SDK_AUG2010
#define BUILD_DATE "Aug 23 2010"
#if DEBUG
#define BUILD_TIME "17:28:26"
#else
#define BUILD_TIME "17:33:06"
#endif
#elif SDK_SEP2006
#define BUILD_DATE "Sep 21 2006"
#define BUILD_TIME "14:32:13"
#endif
#ifdef SDK_AUG2010
#if DEBUG
const char* __SCVersion = "<< RVL_SDK - SC \tdebug build: " BUILD_DATE " " BUILD_TIME " (0x4302_145) >>";
#else
const char* __SCVersion = "<< RVL_SDK - SC \trelease build: " BUILD_DATE " " BUILD_TIME " (0x4302_145) >>";
#endif
#elif SDK_SEP2006
const char* __SCVersion = "<< RVL_SDK - SC \trelease build: " BUILD_DATE " " BUILD_TIME " (0x4200_60422) >>";
#endif
typedef struct {
char* name;
SCItemID id;
} NameAndID;
static NameAndID NameAndIDTbl[38] = {
"IPL.CB", SC_ITEM_ID_IPL_COUNTER_BIAS,
"IPL.AR", SC_ITEM_ID_IPL_ASPECT_RATIO,
"IPL.ARN", SC_ITEM_ID_IPL_AUTORUN_MODE,
"IPL.CD", SC_ITEM_ID_IPL_CONFIG_DONE,
"IPL.CD2", SC_ITEM_ID_IPL_CONFIG_DONE2,
"IPL.DH", SC_ITEM_ID_IPL_DISPLAY_OFFSET_H,
"IPL.E60", SC_ITEM_ID_IPL_EURGB60_MODE,
"IPL.EULA", SC_ITEM_ID_IPL_EULA,
"IPL.FRC", SC_ITEM_ID_IPL_FREE_CHANNEL_APP_COUNT,
"IPL.IDL", SC_ITEM_ID_IPL_IDLE_MODE,
"IPL.INC", SC_ITEM_ID_IPL_INSTALLED_CHANNEL_APP_COUNT,
"IPL.LNG", SC_ITEM_ID_IPL_LANGUAGE,
"IPL.NIK", SC_ITEM_ID_IPL_OWNER_NICKNAME,
"IPL.PC", SC_ITEM_ID_IPL_PARENTAL_CONTROL,
"IPL.PGS", SC_ITEM_ID_IPL_PROGRESSIVE_MODE,
"IPL.SSV", SC_ITEM_ID_IPL_SCREEN_SAVER_MODE,
"IPL.SADR", SC_ITEM_ID_IPL_SIMPLE_ADDRESS,
"IPL.SND", SC_ITEM_ID_IPL_SOUND_MODE,
"IPL.UPT", SC_ITEM_ID_IPL_UPDATE_TYPE,
"NET.CNF", SC_ITEM_ID_NET_CONFIG,
"NET.CTPC", SC_ITEM_ID_NET_CONTENT_RESTRICTIONS,
"NET.PROF", SC_ITEM_ID_NET_PROFILE,
"NET.WCPC", SC_ITEM_ID_NET_WC_RESTRICTION,
"NET.WCFG", SC_ITEM_ID_NET_WC_FLAGS,
"DEV.BTM", SC_ITEM_ID_DEV_BOOT_MODE,
"DEV.VIM", SC_ITEM_ID_DEV_VIDEO_MODE,
"DEV.CTC", SC_ITEM_ID_DEV_COUNTRY_CODE,
"DEV.DSM", SC_ITEM_ID_DEV_DRIVESAVING_MODE,
"BT.DINF", SC_ITEM_ID_BT_DEVICE_INFO,
"BT.CDIF", SC_ITEM_ID_BT_CMPDEV_INFO,
"BT.SENS", SC_ITEM_ID_BT_DPD_SENSIBILITY,
"BT.SPKV", SC_ITEM_ID_BT_SPEAKER_VOLUME,
"BT.MOT", SC_ITEM_ID_BT_MOTOR_MODE,
"BT.BAR", SC_ITEM_ID_BT_SENSOR_BAR_POSITION,
"DVD.CNF", SC_ITEM_ID_DVD_CONFIG,
"WWW.RST", SC_ITEM_ID_WWW_RESTRICTION,
"MPLS.MOVIE", SC_ITEM_ID_MOTION_PLUS_MOVIE,
"IPL.TID", SC_ITEM_ID_TEMPORARY_TITLE_ID,
};
static const char ConfDirName[] = "/shared2/sys";
static const char ConfFileName[] = "/shared2/sys/SYSCONF";
static const char ProductInfoFileName[] = "/title/00000001/00000002/data/setting.txt";
static u8 ConfBuf[0x4000] ATTRIBUTE_ALIGN(32);
static u8 ConfBufForFlush[0x4000] ATTRIBUTE_ALIGN(32);
static u8 Initialized;
static u8 DirtyFlag;
static u8 IsDevKit;
static vu8 BgJobStatus = 0;
static u32 ItemIDOffsetTblOffset;
static u32 ItemIDMaxPlus1;
static u32 ItemNumTotal;
static u32 ItemRestSize;
static SCControl Control;
static void SetBgJobStatus(u32 status);
static u32 ParseConfBuf(u8* bufp, u32 bufSize);
static void ClearConfBuf(u8* bufp);
static BOOL ParseGetBEValue(const u8* bufp, const u8* bufEndp, u32* varp, u32 varSize);
static void OpenCallbackFromReload(s32, NANDCommandBlock*);
static void ReadCallbackFromReload(s32 result, NANDCommandBlock* block);
static void CloseCallbackFromReloadError(s32 result, NANDCommandBlock* block);
static void CloseCallbackFromReload(s32 result, NANDCommandBlock* block);
static void ErrorFromReload(s32 result);
static void FinishFromReload(void);
static BOOL UnpackItem(const u8*, SCItem*);
static void MyNandCallback(s32, NANDCommandBlock* block);
static void FinishFromFlush(void);
static void ErrorFromFlush(void);
static BOOL __SCIsDirty(void);
static void __SCSetDirtyFlag(void);
static void __SCClearDirtyFlag(void);
static u8* __SCGetConfBuf(void);
static u32 __SCGetConfBufSize(void);
void SCInit(void) {
BOOL enabled = OSDisableInterrupts();
if (Initialized) {
OSRestoreInterrupts(enabled);
return;
}
Initialized = TRUE;
SetBgJobStatus(1);
OSRestoreInterrupts(enabled);
OSRegisterVersion(__SCVersion);
OSInitThreadQueue(&Control.threadQueue);
if (OSGetConsoleType() & 0x10000000) {
IsDevKit = TRUE;
}
if (NANDInit() != 0 || SCReloadConfFileAsync(__SCGetConfBuf(), __SCGetConfBufSize(), NULL) != 0) {
SetBgJobStatus(2);
}
}
static void SetBgJobStatus(u32 status) {
BgJobStatus = (u8)status;
}
u32 SCCheckStatus(void) {
BOOL enabled;
u32 ret;
enabled = OSDisableInterrupts();
ret = BgJobStatus;
if (ret == 3) {
SetBgJobStatus(1);
OSRestoreInterrupts(enabled);
if (ParseConfBuf(Control.reloadBufp[0], Control.reloadedSize[0]) == 0) {
enabled = OSDisableInterrupts();
if (__SCGetConfBuf() != Control.reloadBufp[0]) {
memcpy(__SCGetConfBuf(), Control.reloadBufp[0], __SCGetConfBufSize());
}
__SCClearDirtyFlag();
OSRestoreInterrupts(enabled);
} else {
enabled = OSDisableInterrupts();
ClearConfBuf(Control.reloadBufp[0]);
__SCClearDirtyFlag();
OSRestoreInterrupts(enabled);
}
ret = 0;
SetBgJobStatus(ret);
} else {
OSRestoreInterrupts(enabled);
}
return ret;
}
s32 SCReloadConfFileAsync(u8* bufp, u32 bufSize, SCReloadConfFileCallback callback) {
u32 i;
ASSERTLINE(392, bufp != NULL);
ASSERTLINE(393, ((u32)bufp & 0x1f) == 0);
if (bufSize < __SCGetConfBufSize()) {
return -128;
}
SetBgJobStatus(1);
Control.reloadCallback = callback;
Control.reloadResult = 0;
Control.reloadFileCount = 0;
for (i = 0; i < 2; i++) {
Control.reloadedSize[i] = 0;
}
Control.reloadFileName[0] = ConfFileName;
Control.reloadFileName[1] = ProductInfoFileName;
Control.reloadBufp[0] = bufp;
Control.reloadBufp[1] = (u8*)OSPhysicalToCached(0x3800);
Control.reloadSizeExpected[0] = __SCGetConfBufSize();
Control.reloadSizeExpected[1] = 0x100;
ClearConfBuf(bufp);
ItemIDOffsetTblOffset = 0;
ItemNumTotal = 0;
ItemRestSize = 0;
Control.nandNeedClose = FALSE;
return NANDPrivateOpenAsync(Control.reloadFileName[Control.reloadFileCount],
&Control.nandFileInfo, 1, OpenCallbackFromReload,
&Control.nandCommandBlock);
}
static void OpenCallbackFromReload(s32 result, NANDCommandBlock* block) {
if (result == 0) {
Control.nandNeedClose = TRUE;
if (NANDReadAsync(&Control.nandFileInfo, Control.reloadBufp[Control.reloadFileCount],
Control.reloadSizeExpected[Control.reloadFileCount],
ReadCallbackFromReload, &Control.nandCommandBlock) == 0)
{
return;
}
}
ErrorFromReload(result);
}
static void ReadCallbackFromReload(s32 result, NANDCommandBlock* block) {
if (result == Control.reloadSizeExpected[Control.reloadFileCount]) {
Control.reloadedSize[Control.reloadFileCount] = (u32)result;
Control.nandNeedClose = FALSE;
if (NANDCloseAsync(&Control.nandFileInfo, CloseCallbackFromReload,
&Control.nandCommandBlock) == 0)
{
return;
}
}
ErrorFromReload((s32)((result == 0) ? -128 : result));
}
static void CloseCallbackFromReload(s32 result, NANDCommandBlock* block) {
if (result == 0) {
FinishFromReload();
return;
}
ErrorFromReload(result);
}
void FinishFromReload(void) {
u32 status;
nextFile:
Control.reloadFileCount++;
if (Control.reloadFileCount < 2) {
Control.nandNeedClose = FALSE;
if (NANDPrivateOpenAsync(Control.reloadFileName[Control.reloadFileCount],
&Control.nandFileInfo, 1, OpenCallbackFromReload,
&Control.nandCommandBlock) == 0)
{
return;
}
goto nextFile;
}
switch (Control.reloadResult) {
case 0:
status = 3;
break;
default:
case -12:
ClearConfBuf(Control.reloadBufp[0]);
Control.reloadedSize[0] = Control.reloadSizeExpected[0];
status = 3;
break;
}
*(u8*)((u8*)OSPhysicalToCached(0x3800) + 0x100 - 1) = '\0';
if (Control.reloadCallback) {
Control.reloadCallback(Control.reloadResult);
Control.reloadCallback = NULL;
}
SetBgJobStatus(status);
}
static void ErrorFromReload(s32 result) {
if (Control.reloadFileCount == 0) {
Control.reloadResult = result;
}
Control.reloadedSize[Control.reloadFileCount] = 0;
if (Control.nandNeedClose) {
if (NANDCloseAsync(&Control.nandFileInfo, CloseCallbackFromReloadError,
&Control.nandCommandBlock) == 0)
{
return;
}
}
FinishFromReload();
}
static void CloseCallbackFromReloadError(s32 result, NANDCommandBlock* block) {
FinishFromReload();
}
static void ClearConfBuf(u8* bufp) {
u32 size = __SCGetConfBufSize();
memset(bufp, 0, size);
if (size > 12) {
memcpy(bufp, "SCv0", 4);
memcpy(bufp + (size - 4), "SCed", 4);
*((u16*)bufp + 3) = 8;
}
}
u32 ParseConfBuf(u8* bufp, u32 bufSize) {
u8 *bufTop, *bufEndp;
u32 numItems, loopItem;
SCItem item;
u32 itemOffset;
u16* itemOfsp;
u16* runtimeRefp;
u32 restSize;
NameAndID* tblp = NameAndIDTbl;
NameAndID* tblEndp;
char* name;
ASSERTLINE(576, bufp != NULL);
ASSERTLINE(577, ((u32)bufp & 0x1f) == 0);
if ((bufSize < 12) || (bufSize > __SCGetConfBufSize())) {
goto error;
}
bufTop = bufp;
bufEndp = bufp + bufSize - 4;
ItemIDMaxPlus1 = SC_ITEM_ID_MAX_PLUS1;
if (memcmp(bufp, "SCv0", 4) || memcmp(bufEndp, "SCed", 4)) {
goto error;
}
bufp += 4;
if (bufSize < __SCGetConfBufSize()) {
u32 expandSize = __SCGetConfBufSize() - bufSize;
memset(bufEndp, 0, expandSize);
bufEndp += expandSize;
memcpy(bufEndp, "SCed", 4);
}
if (ParseGetBEValue(bufp, bufEndp, &numItems, 2) == FALSE) {
goto error;
}
bufp += 2;
itemOfsp = (u16*)bufp;
itemOffset = ((u8*)(itemOfsp + numItems + 1) - bufTop);
for (loopItem = 0; loopItem < numItems; loopItem++) {
if (itemOffset > bufSize || ((u8*)&itemOfsp[loopItem] - bufTop) > bufSize) {
goto error;
}
if (itemOffset != itemOfsp[loopItem] || UnpackItem(bufTop + itemOffset, &item) == FALSE) {
goto error;
}
itemOffset += item.packedSize;
}
if (itemOffset > bufSize) {
goto error;
}
if (itemOffset != itemOfsp[loopItem]) {
goto error;
}
runtimeRefp = (u16*)(bufEndp - 2 * (SC_ITEM_ID_MAX_PLUS1));
if ((u8*)(bufTop + itemOffset) > (u8*)runtimeRefp) {
goto error;
}
restSize = (u32)((u8*)runtimeRefp - (u8*)(bufTop + itemOffset));
memset(runtimeRefp, 0, (u32)(bufEndp - (u8*)runtimeRefp));
runtimeRefp = (u16*)(bufEndp - 2);
tblEndp = tblp + ItemIDMaxPlus1;
while (tblp < tblEndp && (name = tblp->name) != NULL) {
u32 nameLen;
u8* p;
nameLen = strlen(name);
for (loopItem = 0; loopItem < numItems; loopItem++) {
p = bufTop + itemOfsp[loopItem];
if (nameLen == (u32)(((*p) & 0x1F) + 1) &&
memcmp(name, p + sizeof(SCType), nameLen) == 0)
{
runtimeRefp[-tblp->id] = (u16)((u8*)(&itemOfsp[loopItem]) - bufTop);
break;
}
}
tblp++;
}
ItemIDOffsetTblOffset = (u32)((u8*)runtimeRefp - bufTop);
ItemNumTotal = numItems;
ItemRestSize = restSize;
return 0;
error:
return 2;
}
static BOOL ParseGetBEValue(const u8* bufp, const u8* bufEndp, u32* varp, u32 varSize) {
u32 value = 0;
if ((bufp + varSize) > bufEndp) {
return FALSE;
}
while (varSize) {
value = (value << 8) | *bufp;
bufp++;
varSize--;
}
*varp = value;
return TRUE;
}
static BOOL UnpackItem(const u8* bufp, SCItem* itemp) {
SCType type;
ASSERTLINE(698, bufp != NULL);
ASSERTLINE(699, itemp != NULL);
memset(itemp, 0, sizeof(SCItem));
type = (u8)(*bufp & 0xE0);
itemp->name = (char*)(bufp + sizeof(SCType));
itemp->nameLen = (u32)((*bufp & 0x1F) + 1);
itemp->data = (u8*)(bufp + sizeof(SCType) + itemp->nameLen);
switch (type) {
case 0x60:
case 0xE0:
itemp->dataSize = sizeof(u8);
break;
case 0x80:
itemp->dataSize = sizeof(u16);
break;
case 0xA0:
itemp->dataSize = sizeof(u32);
break;
case 0xC0:
itemp->dataSize = sizeof(u64);
break;
case 0x40:
itemp->dataSize = (u32)(*(itemp->data) + 1);
itemp->data++;
itemp->packedSize++;
break;
case 0x20:
itemp->dataSize = (u32)((((*(itemp->data)) << 8) | (*(itemp->data + 1))) + 1);
itemp->data += 2;
itemp->packedSize += 2;
break;
default:
goto err;
}
if (type == 0x40 || type == 0x20) {
itemp->typeByteArray = 0x40;
} else {
itemp->typeInteger = type;
memcpy(&itemp->integer, itemp->data, itemp->dataSize);
}
itemp->packedSize += sizeof(SCType) + itemp->nameLen + itemp->dataSize;
{
const char* typeString;
switch (type) {
case 0x60:
typeString = "U8/S8";
break;
case 0xE0:
typeString = "BOOL";
break;
case 0x80:
typeString = "U16/S16";
break;
case 0xA0:
typeString = "U32/S32";
break;
case 0xC0:
typeString = "U64/S64";
break;
case 0x40:
case 0x20:
typeString = "ARRAY";
break;
default:
typeString = "UNKNOWN";
}
}
err:
return (itemp->dataSize != 0);
}
static BOOL FindItemByID(SCItemID id, SCItem* itemp) {
u8* conf = __SCGetConfBuf();
u16* refp;
if (id < ItemIDMaxPlus1 && ItemIDOffsetTblOffset != 0) {
refp = (u16*)(conf + ItemIDOffsetTblOffset);
if (refp[-id] != 0) {
return UnpackItem(conf + *(u16*)(conf + refp[-id]), itemp);
}
}
return FALSE;
}
void DeleteItemByID(SCItemID id) {
u8* conf = __SCGetConfBuf();
u32 targetRef, initialTopOfFreeSpace, moveSize, shrinkSize, i;
u16 *refp, *itemOfsTop, *itemOfsTargetp, *itemOfsEndp, *itemOfsp;
if (id < ItemIDMaxPlus1 && ItemIDOffsetTblOffset != 0) {
refp = (u16*)(conf + ItemIDOffsetTblOffset);
targetRef = refp[-id];
if (targetRef != 0 && ItemNumTotal != 0) {
itemOfsTop = (u16*)(conf + 4);
itemOfsTargetp = (u16*)(conf + targetRef);
itemOfsEndp = itemOfsTop + ItemNumTotal;
initialTopOfFreeSpace = *itemOfsEndp;
shrinkSize = 2 + (itemOfsTargetp[1] - itemOfsTargetp[0]);
moveSize = *itemOfsTargetp - (targetRef + 4);
memmove(conf + targetRef, conf + targetRef + 4, moveSize);
for (itemOfsp = itemOfsEndp - 1; itemOfsp >= itemOfsTop; itemOfsp--) {
if (itemOfsp < itemOfsTargetp) {
*itemOfsp -= 2;
} else {
*itemOfsp -= shrinkSize;
}
}
memmove(conf + itemOfsTargetp[0], conf + (itemOfsTargetp[0] + shrinkSize),
initialTopOfFreeSpace - (itemOfsTargetp[0] + shrinkSize));
memset(conf + (initialTopOfFreeSpace - shrinkSize), 0, shrinkSize);
for (i = 0; i < ItemIDMaxPlus1; i++) {
if (refp[-i] < targetRef) {
// empty branch?
} else if (refp[-i] > targetRef) {
refp[-i] -= 2;
} else {
refp[-i] = 0;
}
}
ItemRestSize += shrinkSize;
ItemNumTotal--;
*(u16*)(conf + 4) = (u16)ItemNumTotal;
__SCSetDirtyFlag();
}
}
}
BOOL CreateItemByID(SCItemID id, SCType type, const u8* data, u32 size) {
u8* conf = __SCGetConfBuf();
u8* p;
u32 nameLen;
u32 packedSize = sizeof(SCType);
NameAndID* tblp = NameAndIDTbl;
char* name;
u32 topOfFreeSpace;
u16* refp;
u16* itemOfsTop;
u16* itemOfsEndp;
u16* itemOfsp;
if (id < ItemIDMaxPlus1 && data != NULL && ItemNumTotal < 0xFFFF && ItemIDOffsetTblOffset != 0) {
switch (type) {
case 0xE0:
case 0x60:
size = 1;
break;
case 0x80:
size = 2;
break;
case 0xA0:
size = 4;
break;
case 0xC0:
size = 8;
break;
case 0x40:
if (size == 0 || size > 65536) {
goto error;
}
if (size > 256) {
packedSize += 2;
type = 0x20;
} else {
packedSize += 1;
}
break;
default:
goto error;
}
packedSize += size;
while ((name = tblp->name) != NULL) {
if (tblp->id == id) {
break;
}
tblp++;
}
if (name == NULL) {
goto error;
}
nameLen = strlen(name);
if (nameLen > 32) {
goto error;
}
packedSize += nameLen;
if (ItemRestSize < (2 + packedSize)) {
goto error;
}
itemOfsTop = (u16*)(conf + 6);
itemOfsEndp = itemOfsTop + ItemNumTotal;
topOfFreeSpace = *itemOfsEndp;
memmove(conf + (itemOfsTop[0] + 2), conf + itemOfsTop[0], topOfFreeSpace - itemOfsTop[0]);
itemOfsp = itemOfsTop;
do {
*itemOfsp += 2;
itemOfsp++;
} while (itemOfsp <= itemOfsEndp);
topOfFreeSpace = *itemOfsEndp;
p = (u8*)(conf + topOfFreeSpace);
*p = (SCType)(type | (nameLen - 1));
memcpy(p + sizeof(SCType), name, nameLen);
p += sizeof(SCType) + nameLen;
if (type == 0x40) {
*p++ = (u8)(size - 1);
} else if (type == 0x20) {
*p++ = (u8)((size - 1) >> 8);
*p++ = (u8)(size - 1);
}
memcpy(p, data, size);
p += size;
refp = (u16*)(conf + ItemIDOffsetTblOffset);
refp[-id] = (u16)((u8*)itemOfsEndp - conf);
itemOfsEndp[1] = (u16)(itemOfsEndp[0] + packedSize);
ItemRestSize -= 2 + packedSize;
ItemNumTotal++;
*(u16*)(conf + 4) = (u16)ItemNumTotal;
__SCSetDirtyFlag();
return TRUE;
}
error:
return FALSE;
}
BOOL SCFindByteArrayItem(void* data, u32 size, SCItemID id) {
SCItem item;
BOOL result = FALSE;
BOOL enabled = OSDisableInterrupts();
if (data != NULL && FindItemByID(id, &item) && item.typeByteArray != 0 && item.dataSize == size) {
memcpy(data, item.data, size);
result = TRUE;
}
OSRestoreInterrupts(enabled);
return result;
}
BOOL SCReplaceByteArrayItem(const void* data, u32 size, SCItemID id) {
SCItem item;
BOOL result = FALSE;
BOOL enabled = OSDisableInterrupts();
if (data != NULL) {
if (FindItemByID(id, &item)) {
if (item.typeByteArray != 0 && item.dataSize == size) {
if (memcmp(item.data, data, size) != 0) {
memcpy(item.data, data, size);
__SCSetDirtyFlag();
}
result = TRUE;
goto finish;
} else {
DeleteItemByID(id);
}
}
result = CreateItemByID(id, 0x40, data, size);
}
finish:
OSRestoreInterrupts(enabled);
return result;
}
BOOL SCFindIntegerItem(void* data, SCItemID id, SCType type) {
SCItem item;
BOOL result = FALSE;
BOOL enabled = OSDisableInterrupts();
ASSERTLINE(1126, data != NULL);
ASSERTLINE(1127, type != 0);
if (FindItemByID(id, &item) && item.typeInteger == type) {
memcpy(data, item.data, item.dataSize);
result = TRUE;
}
OSRestoreInterrupts(enabled);
return result;
}
BOOL SCReplaceIntegerItem(const void* data, SCItemID id, SCType type) {
SCItem item;
BOOL result = FALSE;
BOOL enabled = OSDisableInterrupts();
if (FindItemByID(id, &item)) {
if (item.typeInteger == type) {
if (memcmp(item.data, data, item.dataSize) != 0) {
memcpy(item.data, data, item.dataSize);
__SCSetDirtyFlag();
}
result = TRUE;
goto finish;
} else {
DeleteItemByID(id);
}
}
result = CreateItemByID(id, type, data, 0);
finish:
OSRestoreInterrupts(enabled);
return result;
}
BOOL SCFindU8Item(u8* data, SCItemID id) {
return SCFindIntegerItem(data, id, 0x60);
}
BOOL SCFindS8Item(s8* data, SCItemID id) {
return SCFindIntegerItem(data, id, 0x60);
}
BOOL SCFindU32Item(u32* data, SCItemID id) {
return SCFindIntegerItem(data, id, 0xA0);
}
BOOL SCReplaceU8Item(u8 data, SCItemID id) {
return SCReplaceIntegerItem(&data, id, 0x60);
}
static void __SCFlushSyncCallback(u32 status) {
OSWakeupThread(&Control.threadQueue);
}
void SCFlushAsync(SCFlushCallback callback) {
SCControl* ctrl;
BOOL enabled;
u8 status;
ctrl = &Control;
enabled = OSDisableInterrupts();
status = BgJobStatus;
if (status == 0) {
SetBgJobStatus(1);
if (callback == NULL) {
callback = __SCFlushSyncCallback;
}
ctrl->flushCallback = callback;
ctrl->flushResult = 0;
ctrl->nandNeedClose = FALSE;
ctrl->flushSize = __SCGetConfBufSize();
if (!__SCIsDirty()) {
OSRestoreInterrupts(enabled);
FinishFromFlush();
} else {
__SCClearDirtyFlag();
memcpy(ConfBufForFlush, __SCGetConfBuf(), __SCGetConfBufSize());
OSRestoreInterrupts(enabled);
ctrl->nandStep = 0;
if (NANDPrivateGetTypeAsync(ConfFileName, &ctrl->u.nandType, MyNandCallback, &ctrl->nandCommandBlock) != NAND_RESULT_OK) {
ErrorFromFlush();
}
}
} else {
if (callback != NULL) {
callback(status == 1 ? status : 2);
}
OSRestoreInterrupts(enabled);
}
}
void MyNandCallback(s32 result, NANDCommandBlock* block) {
SCControl* ctrl = &Control;
switch (ctrl->nandStep) {
case 0:
if (result == NAND_RESULT_OK && ctrl->u.nandType == 1) {
ctrl->nandStep = 1;
if (NANDPrivateGetStatusAsync(ConfFileName, &ctrl->u.nandStatus, MyNandCallback, &ctrl->nandCommandBlock) != NAND_RESULT_OK) {
break;
}
} else {
goto _case_1_lbl;
}
return;
case 1:
if (result == NAND_RESULT_OK && ctrl->u.nandStatus.permission == NAND_PERM_RWALL) {
goto _case_5_lbl;
}
_case_1_lbl:
ctrl->nandStep = 2;
if (NANDPrivateDeleteAsync(ConfFileName, MyNandCallback, &ctrl->nandCommandBlock) != NAND_RESULT_OK) {
break;
}
return;
case 2:
ctrl->nandStep = 3;
if (NANDPrivateGetTypeAsync(ConfDirName, &ctrl->u.nandType, MyNandCallback, &ctrl->nandCommandBlock) != NAND_RESULT_OK) {
break;
}
return;
case 3:
if (result == NAND_RESULT_OK && ctrl->u.nandType == 2) {
goto _case_4_lbl;
}
ctrl->nandStep = 4;
if (NANDPrivateCreateDirAsync(ConfDirName, NAND_PERM_RWALL, 0, MyNandCallback, &ctrl->nandCommandBlock) != NAND_RESULT_OK) {
break;
}
return;
case 4:
_case_4_lbl:
ctrl->nandStep = 5;
if (NANDPrivateCreateAsync(ConfFileName, NAND_PERM_RWALL, 0, MyNandCallback, &ctrl->nandCommandBlock) != NAND_RESULT_OK) {
break;
}
return;
case 5:
_case_5_lbl:
ctrl->nandStep = 6;
if (NANDPrivateOpenAsync(ConfFileName, &ctrl->nandFileInfo, NAND_ACCESS_WRITE, MyNandCallback, &ctrl->nandCommandBlock) != NAND_RESULT_OK) {
break;
}
return;
case 6:
if (result != NAND_RESULT_OK) {
break;
}
ctrl->nandNeedClose = TRUE;
ctrl->nandStep = 7;
if (NANDWriteAsync(&ctrl->nandFileInfo, ConfBufForFlush, ctrl->flushSize, MyNandCallback, &ctrl->nandCommandBlock) != NAND_RESULT_OK) {
break;
}
return;
case 7:
if (result != ctrl->flushSize) {
break;
}
ctrl->nandNeedClose = FALSE;
ctrl->nandStep = 8;
if (NANDCloseAsync(&ctrl->nandFileInfo, MyNandCallback, &ctrl->nandCommandBlock) != NAND_RESULT_OK) {
break;
}
return;
case 8:
if (result != NAND_RESULT_OK) {
break;
}
case 9:
FinishFromFlush();
default:
return;
}
ErrorFromFlush();
}
static void FinishFromFlush(void) {
SCControl* ctrl;
SCFlushCallback callback;
ctrl = &Control;
if (ctrl->flushResult != 0) {
__SCSetDirtyFlag();
}
callback = ctrl->flushCallback;
if (callback) {
ctrl->flushCallback = NULL;
callback(ctrl->flushResult);
if (ctrl->threadQueue.head != NULL) {
OSWakeupThread(&ctrl->threadQueue);
}
}
SetBgJobStatus(ctrl->flushResult);
}
static void ErrorFromFlush(void) {
SCControl* ctrl;
ctrl = &Control;
ctrl->flushResult = 2;
if (ctrl->nandNeedClose) {
ctrl->nandStep = 9;
if (NANDCloseAsync(&ctrl->nandFileInfo, MyNandCallback, &ctrl->nandCommandBlock) == NAND_RESULT_OK) {
return;
}
}
FinishFromFlush();
}
static BOOL __SCIsDirty(void) {
return DirtyFlag ? TRUE : FALSE;
}
static void __SCSetDirtyFlag(void) {
DirtyFlag = TRUE;
}
static void __SCClearDirtyFlag(void) {
DirtyFlag = FALSE;
}
static u8* __SCGetConfBuf(void) {
return ConfBuf;
}
static u32 __SCGetConfBufSize(void) {
return sizeof(ConfBuf);
}
+821
View File
@@ -0,0 +1,821 @@
#include <revolution/si.h>
#include <revolution/vi.h>
#include "__os.h"
#define ROUND(n, a) (((u32)(n) + (a)-1) & ~((a)-1))
#ifdef SDK_AUG2010
#define BUILD_DATE "Aug 23 2010"
#if DEBUG
#define BUILD_TIME "17:27:56"
#else
#define BUILD_TIME "17:33:06"
#endif
#elif SDK_SEP2006
#define BUILD_DATE "Sep 21 2006"
#define BUILD_TIME "14:32:13"
#endif
#ifdef SDK_AUG2010
#if DEBUG
const char* __SIVersion = "<< RVL_SDK - SI \tdebug build: "BUILD_DATE" "BUILD_TIME" (0x4302_145) >>";
#else
const char* __SIVersion = "<< RVL_SDK - SI \trelease build: "BUILD_DATE" "BUILD_TIME" (0x4302_145) >>";
#endif
#elif SDK_SEP2006
const char* __SIVersion = "<< RVL_SDK - SI \trelease build: "BUILD_DATE" "BUILD_TIME" (0x4200_60422) >>";
#endif
static SIControl Si = {
/* chan */ -1,
/* poll */ 0,
/* inputBytes */ 0,
/* input */ NULL,
/* callback */ NULL
};
static SIPacket Packet[4];
static OSAlarm Alarm[4];
static u32 Type[4] = { SI_ERROR_NO_RESPONSE, SI_ERROR_NO_RESPONSE, SI_ERROR_NO_RESPONSE, SI_ERROR_NO_RESPONSE };
static OSTime TypeTime[4];
static OSTime XferTime[4];
static SITypeCallback TypeCallback[4][4];
static __OSInterruptHandler RDSTHandler[4];
static BOOL InputBufferValid[4];
static u32 InputBuffer[4][2];
static volatile u32 InputBufferVcount[4];
u32 __PADFixBits;
// prototypes
static u32 CompleteTransfer();
static void SITransferNext(s32 chan);
static void SIInterruptHandler(__OSInterrupt interrupt, OSContext* context);
static int __SITransfer(s32 chan, void* output, u32 outputBytes, void* input, u32 inputBytes, SICallback callback);
static void AlarmHandler(OSAlarm* alarm, OSContext* context);
static void GetTypeCallback(s32 chan, u32 error, OSContext* context);
static int SIGetResponseRaw(s32 chan);
BOOL SIBusy(void) {
return (Si.chan != -1) ? TRUE : FALSE;
}
BOOL SIIsChanBusy(s32 chan) {
return Packet[chan].chan != -1 || Si.chan == chan;
}
static void SIClearTCInterrupt(void) {
u32 reg;
reg = __SIRegs[SI_COMCSR_IDX];
reg |= SI_COMCSR_TCINT_MASK;
reg &= ~SI_COMCSR_TSTART_MASK;
__SIRegs[SI_COMCSR_IDX] = reg;
}
static u32 CompleteTransfer(void) {
u32 sr;
u32 i;
u32 rLen;
u8* input;
sr = __SIRegs[SI_STATUS_IDX];
SIClearTCInterrupt();
if (Si.chan != -1) {
XferTime[Si.chan] = __OSGetSystemTime();
input = Si.input;
rLen = Si.inputBytes / sizeof(u32);
for (i = 0; i < rLen; i++) {
*(u32*)input = __SIRegs[0x20 + i];
input += 4;
}
rLen = Si.inputBytes & 3;
if (rLen != 0) {
u32 temp = __SIRegs[i + 32];
for (i = 0; i < rLen; i++) {
*(input++) = temp >> ((3 - i) * 8);
}
}
if (__SIRegs[SI_COMCSR_IDX] & SI_COMCSR_COMERR_MASK) {
sr >>= (3 - Si.chan) * 8;
sr &= 0xF;
if ((sr & 8) != 0 && (Type[Si.chan] & 0x80) == 0) {
Type[Si.chan] = 8;
}
if (sr == 0) {
sr = 4;
}
} else {
TypeTime[Si.chan] = __OSGetSystemTime();
sr = 0;
}
Si.chan = -1;
}
return sr;
}
static void SITransferNext(s32 chan) {
int i;
SIPacket* packet;
for (i = 0; i < 4; i++) {
chan++;
chan %= 4;
packet = &Packet[chan];
if (packet->chan != -1) {
if (packet->fire <= __OSGetSystemTime()) {
if (__SITransfer(packet->chan, packet->output, packet->outputBytes, packet->input, packet->inputBytes, packet->callback) != 0) {
OSCancelAlarm(&Alarm[chan]);
packet->chan = -1;
}
break;
}
}
}
}
#define CHAN_NONE -1
static void SIInterruptHandler(__OSInterrupt interrupt, OSContext* context) {
u32 reg;
s32 chan;
u32 sr;
SICallback callback;
int i;
u32 vcount;
u32 x;
reg = __SIRegs[SI_COMCSR_IDX];
if ((reg & (SI_COMCSR_TCINT_MASK | SI_COMCSR_TCINTMSK_MASK)) == (SI_COMCSR_TCINT_MASK | SI_COMCSR_TCINTMSK_MASK)) {
ASSERTLINE(384, Si.chan != CHAN_NONE);
chan = Si.chan;
sr = CompleteTransfer();
callback = Si.callback;
Si.callback = NULL;
SITransferNext(chan);
if (callback) {
callback(chan, sr, context);
}
sr = __SIRegs[SI_STATUS_IDX];
sr &= 0x0F000000 >> (chan << 3);
__SIRegs[SI_STATUS_IDX] = sr;
if (Type[chan] == SI_ERROR_BUSY && !SIIsChanBusy(chan)) {
static u32 cmdTypeAndStatus;
SITransfer(chan, &cmdTypeAndStatus, 1, &Type[chan], 3, &GetTypeCallback, OSMicrosecondsToTicks(65));
}
}
if ((reg & (SI_COMCSR_RDSTINT_MASK | SI_COMCSR_RDSTINTMSK_MASK)) == (SI_COMCSR_RDSTINT_MASK | SI_COMCSR_RDSTINTMSK_MASK)) {
vcount = 1 + VIGetCurrentLine();
x = (Si.poll & (0x3FF << 16)) >> 16;
for (i = 0; i < 4; i++) {
if (SIGetResponseRaw(i)) {
InputBufferVcount[i] = vcount;
}
}
for (i = 0; i < 4; i++) {
if ((Si.poll & (0x80000000 >> (24 + i))) != 0) {
if (InputBufferVcount[i] == 0 || ((x >> 1) + InputBufferVcount[i]) < vcount) {
return;
}
}
}
for (i = 0; i < 4; i++) {
InputBufferVcount[i] = 0;
}
for (i = 0; i < 4; i++) {
if (RDSTHandler[i] != 0) {
(*RDSTHandler[i])(interrupt, context);
}
}
}
}
static BOOL SIEnablePollingInterrupt(BOOL enable) {
BOOL enabled;
BOOL rc;
u32 reg;
int i;
enabled = OSDisableInterrupts();
reg = __SIRegs[SI_COMCSR_IDX];
rc = ((reg & SI_COMCSR_RDSTINTMSK_MASK) != 0) ? TRUE : FALSE;
if (enable) {
reg |= SI_COMCSR_RDSTINTMSK_MASK;
for (i = 0; i < 4; i++) {
InputBufferVcount[i] = 0;
}
} else {
reg &= ~SI_COMCSR_RDSTINTMSK_MASK;
}
reg &= ~(SI_COMCSR_TCINT_MASK | SI_COMCSR_TSTART_MASK);
__SIRegs[SI_COMCSR_IDX] = reg;
OSRestoreInterrupts(enabled);
return rc;
}
BOOL SIRegisterPollingHandler(__OSInterruptHandler handler) {
BOOL enabled;
int i;
enabled = OSDisableInterrupts();
for (i = 0; i < 4; i++) {
if (RDSTHandler[i] == handler) {
OSRestoreInterrupts(enabled);
return TRUE;
}
}
for (i = 0; i < 4; i++) {
if (RDSTHandler[i] == 0) {
RDSTHandler[i] = handler;
SIEnablePollingInterrupt(TRUE);
OSRestoreInterrupts(enabled);
return TRUE;
}
}
OSRestoreInterrupts(enabled);
return FALSE;
}
BOOL SIUnregisterPollingHandler(__OSInterruptHandler handler) {
BOOL enabled;
int i;
enabled = OSDisableInterrupts();
for (i = 0; i < 4; i++) {
if (RDSTHandler[i] == handler) {
RDSTHandler[i] = 0;
for (i = 0; i < 4; i++) {
if (RDSTHandler[i] != 0) {
break;
}
}
if (i == 4) {
SIEnablePollingInterrupt(FALSE);
}
OSRestoreInterrupts(enabled);
return TRUE;
}
}
OSRestoreInterrupts(enabled);
return FALSE;
}
void SIInit(void) {
static BOOL Initialized = FALSE;
if (Initialized) {
return;
}
OSRegisterVersion(__SIVersion);
Packet[0].chan = Packet[1].chan = Packet[2].chan = Packet[3].chan = -1;
Si.poll = 0;
SISetSamplingRate(0);
do {} while(__SIRegs[SI_COMCSR_IDX] & SI_COMCSR_TSTART_MASK);
__SIRegs[SI_COMCSR_IDX] = SI_COMCSR_TCINT_MASK;
__OSSetInterruptHandler(0x14, SIInterruptHandler);
__OSUnmaskInterrupts(0x800);
SIGetType(0);
SIGetType(1);
SIGetType(2);
SIGetType(3);
Initialized = TRUE;
}
static int __SITransfer(s32 chan, void* output, u32 outputBytes, void* input, u32 inputBytes, SICallback callback) {
BOOL enabled;
u32 rLen;
u32 i;
u32 sr;
union {
u32 val;
struct {
u32 tcint : 1;
u32 tcintmsk : 1;
u32 comerr : 1;
u32 rdstint : 1;
u32 rdstintmsk : 1;
u32 pad2 : 4;
u32 outlngth : 7;
u32 pad1 : 1;
u32 inlngth : 7;
u32 pad0 : 5;
u32 channel : 2;
u32 tstart : 1;
} f;
} comcsr;
ASSERTMSGLINE(645, (chan >= 0) && (chan < 4), "SITransfer(): invalid channel.");
ASSERTMSGLINE(647, (outputBytes != 0) && (outputBytes <= 128), "SITransfer(): output size is out of range (must be 1 to 128).");
ASSERTMSGLINE(649, (inputBytes != 0) && (inputBytes <= 128), "SITransfer(): input size is out of range (must be 1 to 128).");
enabled = OSDisableInterrupts();
if (Si.chan != -1) {
OSRestoreInterrupts(enabled);
return 0;
}
ASSERTLINE(659, (__SIRegs[SI_COMCSR_IDX] & (SI_COMCSR_TSTART_MASK | SI_COMCSR_TCINT_MASK)) == 0);
sr = __SIRegs[SI_STATUS_IDX];
sr &= (0x0F000000 >> (chan* 8));
__SIRegs[SI_STATUS_IDX] = sr;
Si.chan = chan;
Si.callback = callback;
Si.inputBytes = inputBytes;
Si.input = input;
rLen = ROUND(outputBytes, 4) / 4;
for (i = 0; i < rLen; i++) {
__SIRegs[i + 0x20] = ((u32*)output)[i];
}
comcsr.val = __SIRegs[SI_COMCSR_IDX];
comcsr.f.tcint = 1;
comcsr.f.tcintmsk = callback ? 1 : 0;
comcsr.f.outlngth = outputBytes == 0x80 ? 0 : outputBytes;
comcsr.f.inlngth = inputBytes == 0x80 ? 0 : inputBytes;
comcsr.f.channel = chan;
comcsr.f.tstart = 1;
__SIRegs[SI_COMCSR_IDX] = comcsr.val;
OSRestoreInterrupts(enabled);
return 1;
}
u32 SISync(void) {
BOOL enabled;
u32 sr;
do {} while(__SIRegs[SI_COMCSR_IDX] & SI_COMCSR_TSTART_MASK);
enabled = OSDisableInterrupts();
sr = CompleteTransfer();
SITransferNext(4);
OSRestoreInterrupts(enabled);
return sr;
}
u32 SIGetStatus(s32 chan) {
BOOL enabled;
u32 sr;
int chanShift;
enabled = OSDisableInterrupts();
sr = __SIRegs[SI_STATUS_IDX];
chanShift = (3 - chan) * 8;
sr >>= chanShift;
if ((sr & 8) != 0) {
if ((Type[chan] & SI_ERROR_BUSY) == 0) {
Type[chan] = 8;
}
}
OSRestoreInterrupts(enabled);
return sr;
}
void SISetCommand(s32 chan, u32 command) {
ASSERTMSGLINE(770, (chan >= 0) && (chan < 4), "SISetCommand(): invalid channel.");
__SIRegs[chan* 3] = command;
}
u32 SIGetCommand(s32 chan) {
ASSERTMSGLINE(770, (chan >= 0) && (chan < 4), "SIGetCommand(): invalid channel.");
return __SIRegs[chan* 3];
}
void SITransferCommands(void) {
__SIRegs[SI_STATUS_IDX] = SI_COMCSR_TCINT_MASK;
}
u32 SISetXY(u32 x, u32 y) {
u32 poll;
BOOL enabled;
ASSERTMSGLINE(821, x >= 8, "SISetXY(): x is out of range (8 <= x <= 1023).");
ASSERTMSGLINE(822, x <= 1023, "SISetXY(): x is out of range (8 <= x <= 1023).");
ASSERTMSGLINE(823, y <= 255, "SISetXY(): y is out of range (0 <= y <= 255).");
poll = x << 0x10;
poll |= y << 8;
enabled = OSDisableInterrupts();
Si.poll &= 0xFC0000FF;
Si.poll |= poll;
poll = Si.poll;
__SIRegs[0x30 / 4] = poll;
OSRestoreInterrupts(enabled);
return poll;
}
u32 SIEnablePolling(u32 poll) {
BOOL enabled;
u32 en;
ASSERTMSGLINE(852, (poll & 0x0FFFFFFF) == 0, "SIEnablePolling(): invalid chan bit(s).");
if (poll == 0) {
return Si.poll;
}
enabled = OSDisableInterrupts();
poll = poll >> 24;
en = poll & 0xF0;
ASSERTLINE(883, en);
poll &= ((en >> 4) | 0x03FFFFF0);
poll &= 0xFC0000FF;
Si.poll &= ~(en >> 4);
Si.poll |= poll;
poll = Si.poll;
SITransferCommands();
__SIRegs[0x30 / 4] = poll;
OSRestoreInterrupts(enabled);
return poll;
}
u32 SIDisablePolling(u32 poll) {
BOOL enabled;
ASSERTMSGLINE(926, (poll & 0x0FFFFFFF) == 0, "SIDisablePolling(): invalid chan bit(s).");
if (poll == 0) {
return Si.poll;
}
enabled = OSDisableInterrupts();
poll = poll >> 24;
poll &= 0xF0;
ASSERTLINE(939, poll);
poll = Si.poll & ~poll;
__SIRegs[0x30 / 4] = poll;
Si.poll = poll;
OSRestoreInterrupts(enabled);
return poll;
}
static BOOL SIGetResponseRaw(s32 chan) {
u32 sr;
sr = SIGetStatus(chan);
if (sr & 0x20) {
InputBuffer[chan][0] = __SIRegs[1 + chan * 3];
InputBuffer[chan][1] = __SIRegs[2 + chan * 3];
InputBufferValid[chan] = TRUE;
return TRUE;
}
return FALSE;
}
BOOL SIGetResponse(s32 chan, void* data) {
BOOL rc;
BOOL enabled;
ASSERTMSGLINE(989, ((chan >= 0) && (chan < 4)), "SIGetResponse(): invalid channel.");
enabled = OSDisableInterrupts();
SIGetResponseRaw(chan);
rc = InputBufferValid[chan];
InputBufferValid[chan] = FALSE;
if (rc) {
((u32*)data)[0] = InputBuffer[chan][0];
((u32*)data)[1] = InputBuffer[chan][1];
}
OSRestoreInterrupts(enabled);
return rc;
}
static void AlarmHandler(OSAlarm* alarm, OSContext* context) {
s32 chan;
SIPacket* packet;
chan = (s32)(alarm - Alarm);
ASSERTLINE(1020, 0 <= chan && chan < SI_MAX_CHAN);
packet = &Packet[chan];
if (packet->chan != -1) {
ASSERTLINE(1024, packet->fire <= __OSGetSystemTime());
if (__SITransfer(packet->chan, packet->output, packet->outputBytes, packet->input, packet->inputBytes, packet->callback)) {
packet->chan = -1;
}
}
}
BOOL SITransfer(s32 chan, void* output, u32 outputBytes, void* input, u32 inputBytes,
SICallback callback, OSTime delay) {
BOOL enabled;
SIPacket* packet;
OSTime now;
OSTime fire;
packet = &Packet[chan];
enabled = OSDisableInterrupts();
if (packet->chan != -1 || Si.chan == chan) {
OSRestoreInterrupts(enabled);
return FALSE;
}
now = __OSGetSystemTime();
if (delay == 0) {
fire = now;
} else {
fire = delay + XferTime[chan];
}
if (now < fire) {
delay = fire - now;
OSSetAlarm(&Alarm[chan], delay, AlarmHandler);
} else if (__SITransfer(chan, output, outputBytes, input, inputBytes, callback)) {
OSRestoreInterrupts(enabled);
return TRUE;
}
packet->chan = chan;
packet->output = output;
packet->outputBytes = outputBytes;
packet->input = input;
packet->inputBytes = inputBytes;
packet->callback = callback;
packet->fire = fire;
OSRestoreInterrupts(enabled);
return TRUE;
}
static void CallTypeAndStatusCallback(s32 chan, u32 type) {
SITypeCallback callback;
int i;
for (i = 0; i < 4; i++) {
callback = TypeCallback[chan][i];
if (callback != 0) {
TypeCallback[chan][i] = 0;
(*callback)(chan, type);
}
}
}
static void GetTypeCallback(s32 chan, u32 error, OSContext* context) {
static u32 cmdFixDevice[4];
u32 type;
u32 chanBit;
int fix;
u32 id;
ASSERTLINE(1155, 0 <= chan && chan < SI_MAX_CHAN);
ASSERTLINE(1157, (Type[chan] & 0xff) == SI_ERROR_BUSY);
Type[chan] &= ~SI_ERROR_BUSY;
Type[chan] |= error;
TypeTime[chan] = __OSGetSystemTime();
type = Type[chan];
chanBit = 0x80000000 >> chan;
fix = __PADFixBits & chanBit;
__PADFixBits &= ~chanBit;
if ((error & 0xF) != 0 || (type & 0x18000000) != 0x08000000 || (type & 0x80000000) == 0 || (type & 0x04000000) != 0) {
OSSetWirelessID(chan, 0);
CallTypeAndStatusCallback(chan, Type[chan]);
} else {
id = OSGetWirelessID(chan) << 8;
if (fix != 0 && (id & 0x100000) != 0) {
cmdFixDevice[chan] = 0x4E000000 | (id & 0xCFFF00) | 0x100000;
Type[chan] = SI_ERROR_BUSY;
SITransfer(chan, &cmdFixDevice[chan], 3, &Type[chan], 3, &GetTypeCallback, 0);
return;
}
if ((type & 0x00100000) != 0) {
if ((id & 0xCFFF00) != (type & 0xCFFF00)) {
if ((id & 0x100000) == 0) {
id = type & 0xCFFF00;
id |= 0x100000;
OSSetWirelessID(chan, (id >> 8) & 0xFFFF);
}
cmdFixDevice[chan] = 0x4E000000 | id;
Type[chan] = SI_ERROR_BUSY;
SITransfer(chan, &cmdFixDevice[chan], 3, &Type[chan], 3, &GetTypeCallback, 0);
return;
}
} else {
if ((type & 0x40000000) != 0) {
id = type & 0xCFFF00;
id |= 0x100000;
OSSetWirelessID(chan, (id >> 8) & 0xFFFF);
cmdFixDevice[chan] = 0x4E000000 | id;
Type[chan] = SI_ERROR_BUSY;
SITransfer(chan, &cmdFixDevice[chan], 3, &Type[chan], 3, &GetTypeCallback, 0);
return;
}
OSSetWirelessID(chan, 0);
}
CallTypeAndStatusCallback(chan, Type[chan]);
}
}
u32 SIGetType(s32 chan) {
static u32 cmdTypeAndStatus;
BOOL enabled;
u32 type;
OSTime diff;
enabled = OSDisableInterrupts();
ASSERTLINE(1261, 0 <= chan && chan < SI_MAX_CHAN);
type = Type[chan];
diff = __OSGetSystemTime() - TypeTime[chan];
if ((Si.poll & (0x80 >> chan)) != 0) {
if (type != 8) {
TypeTime[chan] = __OSGetSystemTime();
OSRestoreInterrupts(enabled);
return type;
}
type = Type[chan] = SI_ERROR_BUSY;
} else {
if (diff <= OSMillisecondsToTicks(50) && type != 8) {
OSRestoreInterrupts(enabled);
return type;
}
if (diff <= OSMillisecondsToTicks(75)) {
Type[chan] = SI_ERROR_BUSY;
} else {
type = Type[chan] = SI_ERROR_BUSY;
}
}
TypeTime[chan] = __OSGetSystemTime();
SITransfer(chan, &cmdTypeAndStatus, 1, &Type[chan], 3, &GetTypeCallback, OSMicrosecondsToTicks(65));
OSRestoreInterrupts(enabled);
return type;
}
u32 SIGetTypeAsync(s32 chan, SITypeCallback callback) {
BOOL enabled;
u32 type;
enabled = OSDisableInterrupts();
type = SIGetType(chan);
if ((Type[chan] & SI_ERROR_BUSY) != 0) {
int i;
for (i = 0; i < SI_MAX_TYPE; i++) {
if (TypeCallback[chan][i] == callback) {
break;
}
if (TypeCallback[chan][i] == 0) {
TypeCallback[chan][i] = callback;
break;
}
}
ASSERTLINE(1342, i < SI_MAX_TYPE);
} else {
(*callback)(chan, type);
}
OSRestoreInterrupts(enabled);
return type;
}
u32 SIDecodeType(u32 type) {
u32 error;
error = type & 0xFF;
type &= ~0xFF;
if (error & SI_ERROR_NO_RESPONSE) {
return SI_ERROR_NO_RESPONSE;
}
if (error & (SI_ERROR_UNKNOWN | SI_ERROR_COLLISION | SI_ERROR_OVER_RUN | SI_ERROR_UNDER_RUN)) {
return SI_ERROR_UNKNOWN;
}
if (error != 0) {
ASSERTLINE(1371, error == SI_ERROR_BUSY);
return SI_ERROR_BUSY;
}
if ((type & SI_TYPE_MASK) == SI_TYPE_N64) {
switch (type & 0xFFFF0000) {
case SI_N64_MIC:
case SI_N64_KEYBOARD:
case SI_GBA:
case SI_N64_MOUSE:
case SI_N64_CONTROLLER:
return type & 0xFFFF0000;
default:
return SI_ERROR_UNKNOWN;
}
}
if ((type & SI_TYPE_MASK) != SI_TYPE_DOLPHIN) {
return SI_ERROR_UNKNOWN;
}
switch (type & 0xFFFF0000) {
case SI_GC_STEERING:
case SI_GC_CONTROLLER:
return type & 0xFFFF0000;
}
if ((type & 0xFFE00000) == SI_GC_KEYBOARD) {
return SI_GC_KEYBOARD;
}
if ((type & SI_GC_WIRELESS) != 0 && (type & SI_WIRELESS_IR) == 0) {
if ((type & SI_GC_WAVEBIRD) == SI_GC_WAVEBIRD) {
return SI_GC_WAVEBIRD;
}
if ((type & SI_WIRELESS_STATE) == 0) {
return SI_GC_RECEIVER;
}
}
if ((type & SI_GC_CONTROLLER) == SI_GC_CONTROLLER) {
return SI_GC_CONTROLLER;
}
return SI_ERROR_UNKNOWN;
}
u32 SIProbe(s32 chan) {
return SIDecodeType(SIGetType(chan));
}
char* SIGetTypeString(u32 type) {
switch (SIDecodeType(type)) {
case SI_ERROR_NO_RESPONSE:
return "No response";
case SI_ERROR_BUSY:
return "Busy";
case SI_N64_CONTROLLER:
return "N64 controller";
case SI_N64_MIC:
return "N64 microphone";
case SI_N64_KEYBOARD:
return "N64 keyboard";
case SI_N64_MOUSE:
return "N64 mouse";
case SI_GBA:
return "GameBoy Advance";
case SI_GC_CONTROLLER:
return "Standard controller";
case SI_GC_RECEIVER:
return "Wireless receiver";
case SI_GC_WAVEBIRD:
return "WaveBird controller";
case SI_GC_KEYBOARD:
return "Keyboard";
case SI_GC_STEERING:
return "Steering";
case SI_ERROR_UNKNOWN:
default:
return "Unknown";
}
}
+125
View File
@@ -0,0 +1,125 @@
#include <revolution.h>
#include <revolution/si.h>
#include "__os.h"
#define LATENCY 8
static u32 SamplingRate = 0;
typedef struct XY {
u16 line;
u8 count;
} XY;
static XY XYNTSC[12] = {
{0x00F6, 0x02},
{0x000E, 0x13},
{0x001E, 0x09},
{0x002C, 0x06},
{0x0034, 0x05},
{0x0041, 0x04},
{0x0057, 0x03},
{0x0057, 0x03},
{0x0057, 0x03},
{0x0083, 0x02},
{0x0083, 0x02},
{0x0083, 0x02},
};
static XY XYPAL[12] = {
{0x0128, 0x02},
{0x000F, 0x15},
{0x001D, 0x0B},
{0x002D, 0x07},
{0x0034, 0x06},
{0x003F, 0x05},
{0x004E, 0x04},
{0x0068, 0x03},
{0x0068, 0x03},
{0x0068, 0x03},
{0x0068, 0x03},
{0x009C, 0x02},
};
void SISetSamplingRate(u32 msec) {
XY* xy;
BOOL progressive;
BOOL enabled;
ASSERTMSGLINE(387, msec <= 11, "SISetSamplingRate(): out of rage (0 <= msec <= 11)");
if (msec > 11) {
msec = 11;
}
enabled = OSDisableInterrupts();
SamplingRate = msec;
switch (VIGetTvFormat()) {
case VI_NTSC:
case VI_MPAL:
case VI_EURGB60:
xy = XYNTSC;
break;
case VI_PAL:
xy = XYPAL;
break;
default:
OSReport("SISetSamplingRate: unknown TV format. Use default.");
msec = 0;
xy = XYNTSC;
break;
}
progressive = __VIRegs[VI_CLOCK_SEL] & 1;
SISetXY((progressive ? 2 : 1) * xy[msec].line, xy[msec].count);
OSRestoreInterrupts(enabled);
}
void SIRefreshSamplingRate(void) {
SISetSamplingRate(SamplingRate);
}
#if DEBUG
void __SITestSamplingRate(u32 tvmode) {
u32 msec;
u32 line;
u32 count;
XY* xy;
switch (tvmode) {
case VI_NTSC:
case VI_MPAL:
xy = XYNTSC;
for (msec = 0; msec <= 11; msec++) {
line = xy[msec].line;
count = xy[msec].count;
OSReport("%2d[msec]: count %3d, line %3d, last %3d, diff0 %2d.%03d, diff1 %2d.%03d\n",
msec, count, line, line * (count - 1) + LATENCY, (line * 636) / 10000, (line * 636) % 10000,
((263 - line * (count - 1)) * 636) / 10000, ((263 - line * (count - 1)) * 636) % 10000);
ASSERTLINE(446, line * (count - 1) + LATENCY < 263);
if (msec != 0) {
ASSERTLINE(449, 636 * line < msec * 10000);
ASSERTLINE(450, 636 * (263 - line * (count - 1)) < msec * 10000);
}
}
break;
case VI_PAL:
xy = XYPAL;
for (msec = 0; msec <= 11; msec++) {
line = xy[msec].line;
count = xy[msec].count;
OSReport("%2d[msec]: count %3d, line %3d, last %3d, diff0 %2d.%03d, diff1 %2d.%03d\n",
msec, count, line, line * (count - 1) + LATENCY, (line * 640) / 10000, (line * 640) % 10000,
((313 - line * (count - 1)) * 640) / 10000, ((313 - line * (count - 1)) * 640) % 10000);
ASSERTLINE(470, line * (count - 1) + LATENCY < 313);
if (msec != 0) {
ASSERTLINE(473, 640 * line < msec * 10000);
ASSERTLINE(474, 640 * (313 - line * (count - 1)) < msec * 10000);
}
}
break;
}
}
#endif
+40
View File
@@ -0,0 +1,40 @@
#ifndef _REVOLUTION_VI_INTERNAL_H_
#define _REVOLUTION_VI_INTERNAL_H_
#include <revolution/vi.h>
#ifdef __cplusplus
extern "C" {
#endif
/* i2c.c */
int __VISendI2CData(u8 slaveAddr, u8* pData, int nBytes);
/* vi.c */
void __VIInit(VITVMode mode);
void __VISetAdjustingValues(s16 x, s16 y);
void __VIGetAdjustingValues(s16* x, s16* y);
void __VIGetCurrentPosition(s16* x, s16* y);
BOOL __VIResetDev0Idle();
/* vi3in1.c */
void __VISetFilter4EURGB60(VIBool enable);
void __VISetGamma1_0(void);
void __VISetYUVSEL(VIBool outsel);
void __VISetCGMS(void);
void __VISetWSS(void);
void __VISetClosedCaption(void);
void __VISetMacrovision(void);
void __VISetGamma(void);
void __VISetTrapFilter(void);
void __VISetRGBOverDrive(void);
void __VISetRGBModeImm(void);
void __VISetRevolutionModeSimple(void);
#ifdef __cplusplus
}
#endif
#endif
+230
View File
@@ -0,0 +1,230 @@
#include <revolution/vi.h>
#include <revolution/os.h>
#include "__vi.h"
static volatile u32 __i2c_ident_flag = 1;
static volatile u32 __i2c_ident_first = 0;
#define busRd32(addr) (*(volatile u32 *)(addr))
#define busWrt32(addr, val) (*(volatile u32 *)(addr)) = (val)
void WaitMicroTime(s32 usec) {
OSTime t = __OSGetSystemTime();
while (((__OSGetSystemTime() - t) * 8) / 486 < usec);
}
static void VICheckI2C(void) {
__i2c_ident_flag = 1;
}
static BOOL __VISetSCL(u32 value) {
u32 reg;
value &= 1;
reg = busRd32(0xCD8000C0);
reg &= ~(1 << 14);
reg = (u32)(reg | (value << 14));
busWrt32(0xCD8000C0, reg);
return TRUE;
}
static BOOL __VISetSDA(u32 value) {
u32 reg;
value &= 1;
reg = busRd32(0xCD8000C0);
reg &= ~(1 << 15);
reg = (u32)(reg | (value << 15));
busWrt32(0xCD8000C0, reg);
return TRUE;
}
static u32 __VIGetSDA(void) {
u32 reg = busRd32(0xCD8000C8);
return (u32)((reg >> 15) & 1);
}
static void __VIOpenI2C(u32 dir) {
u32 reg = busRd32(0xCD8000C4);
reg = (u32)(reg & ~(1 << 15));
reg = (u32)(reg | (1 << 14) | (dir << 15));
busWrt32(0xCD8000C4, reg);
}
static int wait4ClkHigh(void) {
WaitMicroTime(2);
return 1;
}
static int sendSlaveAddr(u8 slaveAddr) {
int i;
if (0 == __i2c_ident_flag) {
__VISetSDA(1);
} else {
__VISetSDA(0);
}
WaitMicroTime(2);
__VISetSCL(0);
for (i = 0; i < 8; i++) {
if (slaveAddr & 0x80) {
if (0 == __i2c_ident_flag) {
__VISetSDA(0);
} else {
__VISetSDA(1);
}
} else {
if (0 == __i2c_ident_flag) {
__VISetSDA(1);
} else {
__VISetSDA(0);
}
}
WaitMicroTime(2);
__VISetSCL(1);
if (wait4ClkHigh() == 0) {
return 0;
}
__VISetSCL(0);
slaveAddr <<= 1;
}
__VIOpenI2C(0);
WaitMicroTime(2);
__VISetSCL(1);
if (wait4ClkHigh() == 0) {
return 0;
}
if (1 == __i2c_ident_flag) {
if (__VIGetSDA() != 0) {
return 0;
}
}
if (0 == __i2c_ident_flag) {
__VISetSDA(1);
} else {
__VISetSDA(0);
}
__VIOpenI2C(1);
__VISetSCL(0);
return 1;
}
int __VISendI2CData(u8 slaveAddr, u8* pData, int nBytes) {
s32 i;
u8 data;
BOOL enabled;
if (__i2c_ident_first == 0) {
VICheckI2C();
__i2c_ident_first = 1;
}
enabled = OSDisableInterrupts();
__VIOpenI2C(1);
__VISetSCL(1);
if (0 == __i2c_ident_flag) {
__VISetSDA(0);
} else {
__VISetSDA(1);
}
WaitMicroTime(2);
WaitMicroTime(2);
if (sendSlaveAddr(slaveAddr) == 0) {
OSRestoreInterrupts(enabled);
return 0;
}
__VIOpenI2C(1);
while (nBytes != 0) {
data = *pData++;
for (i = 0; i < 8; i++) {
if (data & 0x80) {
if (0 == __i2c_ident_flag) {
__VISetSDA(0);
} else {
__VISetSDA(1);
}
} else {
if (0 == __i2c_ident_flag) {
__VISetSDA(1);
} else {
__VISetSDA(0);
}
}
WaitMicroTime(2);
__VISetSCL(1);
if (wait4ClkHigh() == 0) {
OSRestoreInterrupts(enabled);
return 0;
}
__VISetSCL(0);
data <<= 1;
}
__VIOpenI2C(0);
WaitMicroTime(2);
__VISetSCL(1);
if (wait4ClkHigh() == 0) {
OSRestoreInterrupts(enabled);
return 0;
}
if (1 == __i2c_ident_flag) {
if (__VIGetSDA() != 0) {
OSRestoreInterrupts(enabled);
return 0;
}
}
if (0 == __i2c_ident_flag) {
__VISetSDA(1);
} else {
__VISetSDA(0);
}
__VIOpenI2C(1);
__VISetSCL(0);
nBytes--;
}
__VIOpenI2C(1);
if (0 == __i2c_ident_flag) {
__VISetSDA(1);
} else {
__VISetSDA(0);
}
WaitMicroTime(2);
__VISetSCL(1);
WaitMicroTime(2);
if (0 == __i2c_ident_flag) {
__VISetSDA(0);
} else {
__VISetSDA(1);
}
OSRestoreInterrupts(enabled);
return 1;
}
File diff suppressed because it is too large Load Diff
+501
View File
@@ -0,0 +1,501 @@
#include <revolution/os.h>
#include <revolution/vi.h>
static VIVideo Vdac_Flag_Region;
volatile u32 Vdac_Flag_Changed = 0;
static u32 __current_3in1_video_mode = 0;
static VIACPType __type;
static u32 __tvType = 0xFF;
static VIGammaObj gammaSet[] = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0030,
0x0397, 0x3B49, 0x0010, 0x001D, 0x0036, 0x0058, 0x0082, 0x00B3, 0x00EB, 0x1000, 0x1000, 0x1000,
0x1000, 0x1080, 0x1B80, 0xEB00, 0x0000, 0x0028, 0x005A, 0x02DB, 0x0D8D, 0x3049, 0x0010, 0x001D,
0x0036, 0x0058, 0x0082, 0x00B3, 0x00EB, 0x1000, 0x1000, 0x1040, 0x1100, 0x1880, 0x4200, 0xEB00,
0x0000, 0x007A, 0x023C, 0x076D, 0x129C, 0x2724, 0x0010, 0x001D, 0x0036, 0x0058, 0x0082, 0x00B3,
0x00EB, 0x1000, 0x1000, 0x10C0, 0x1580, 0x2900, 0x6200, 0xEB00, 0x004E, 0x0199, 0x052D, 0x0B24,
0x1429, 0x20A4, 0x0010, 0x001D, 0x0036, 0x0058, 0x0082, 0x00B3, 0x00EB, 0x1000, 0x1040, 0x12C0,
0x1DC0, 0x3B00, 0x78C0, 0xEB00, 0x00EC, 0x03D7, 0x0800, 0x0D9E, 0x143E, 0x1BDB, 0x0010, 0x001D,
0x0036, 0x0058, 0x0082, 0x00B3, 0x00EB, 0x1000, 0x10C0, 0x16C0, 0x27C0, 0x4B80, 0x8980, 0xEB00,
0x0276, 0x0666, 0x0A96, 0x0EF3, 0x13AC, 0x1849, 0x0010, 0x001D, 0x0036, 0x0058, 0x0082, 0x00B3,
0x00EB, 0x1000, 0x1200, 0x1C00, 0x3280, 0x59C0, 0x9600, 0xEB00, 0x04EC, 0x08F5, 0x0C96, 0x0FCF,
0x12C6, 0x1580, 0x0010, 0x001D, 0x0036, 0x0058, 0x0082, 0x00B3, 0x00EB, 0x1000, 0x1400, 0x2200,
0x3CC0, 0x6640, 0x9FC0, 0xEB00, 0x0800, 0x0BAE, 0x0E00, 0x1030, 0x11CB, 0x1349, 0x0010, 0x001D,
0x0036, 0x0058, 0x0082, 0x00B3, 0x00EB, 0x1000, 0x1680, 0x28C0, 0x4680, 0x7100, 0xA780, 0xEB00,
0x0BB1, 0x0E14, 0x0F2D, 0x1018, 0x10E5, 0x1180, 0x0010, 0x001D, 0x0036, 0x0058, 0x0082, 0x00B3,
0x00EB, 0x1000, 0x1980, 0x2F80, 0x4FC0, 0x7A00, 0xADC0, 0xEB00, 0x1000, 0x1000, 0x1000, 0x1000,
0x1000, 0x1000, 0x10, 0x20, 0x40, 0x60, 0x80, 0xA0, 0xEB, 0x1000, 0x2000, 0x4000,
0x6000, 0x8000, 0xA000, 0xEB00, 0x14EC, 0x11C2, 0x1078, 0x0FB6, 0x0F2F, 0x0EB6, 0x0010, 0x001D,
0x0036, 0x0058, 0x0082, 0x00B3, 0x00EB, 0x1000, 0x2100, 0x3CC0, 0x5FC0, 0x8900, 0xB780, 0xEB00,
0x19D8, 0x1333, 0x10D2, 0x0F6D, 0x0E5E, 0x0DA4, 0x0010, 0x001D, 0x0036, 0x0058, 0x0082, 0x00B3,
0x00EB, 0x1000, 0x2500, 0x4300, 0x66C0, 0x8F40, 0xBB40, 0xEB00, 0x1EC4, 0x147A, 0x110F, 0x0F0C,
0x0DA1, 0x0CB6, 0x0010, 0x001D, 0x0036, 0x0058, 0x0082, 0x00B3, 0x00EB, 0x1000, 0x2900, 0x4900,
0x6D40, 0x94C0, 0xBE80, 0xEB00, 0x2400, 0x1570, 0x110F, 0x0EAA, 0x0D0F, 0x0BDB, 0x0010, 0x001D,
0x0036, 0x0058, 0x0082, 0x00B3, 0x00EB, 0x1000, 0x2D40, 0x4EC0, 0x7300, 0x9980, 0xC180, 0xEB00,
0x293B, 0x163D, 0x110F, 0x0E30, 0x0C7D, 0x0B24, 0x0010, 0x001D, 0x0036, 0x0058, 0x0082, 0x00B3,
0x00EB, 0x1000, 0x3180, 0x5440, 0x7880, 0x9DC0, 0xC400, 0xEB00, 0x2E27, 0x170A, 0x10D2, 0x0DE7,
0x0BEB, 0x0A80, 0x0010, 0x001D, 0x0036, 0x0058, 0x0082, 0x00B3, 0x00EB, 0x1000, 0x3580, 0x5980,
0x7D40, 0xA1C0, 0xC640, 0xEB00, 0x3362, 0x175C, 0x10D2, 0x0D6D, 0x0B6D, 0x09ED, 0x0010, 0x001D,
0x0036, 0x0058, 0x0082, 0x00B3, 0x00EB, 0x1000, 0x39C0, 0x5E40, 0x8200, 0xA540, 0xC840, 0xEB00,
0x384E, 0x17AE, 0x10B4, 0x0D0C, 0x0AF0, 0x096D, 0x0010, 0x001D, 0x0036, 0x0058, 0x0082, 0x00B3,
0x00EB, 0x1000, 0x3DC0, 0x62C0, 0x8640, 0xA880, 0xCA00, 0xEB00, 0x3D3B, 0x1800, 0x105A, 0x0CC3,
0x0A72, 0x0900, 0x0010, 0x001D, 0x0036, 0x0058, 0x0082, 0x00B3, 0x00EB, 0x1000, 0x41C0, 0x6740,
0x8A00, 0xAB80, 0xCB80, 0xEB00, 0x41D8, 0x1828, 0x103C, 0x0C49, 0x0A1F, 0x0892, 0x0010, 0x001D,
0x0036, 0x0058, 0x0082, 0x00B3, 0x00EB, 0x1000, 0x4580, 0x6B40, 0x8DC0, 0xAE00, 0xCD00, 0xEB00,
0x4676, 0x1851, 0x0FE1, 0x0C00, 0x09B6, 0x0836, 0x0010, 0x001D, 0x0036, 0x0058, 0x0082, 0x00B3,
0x00EB, 0x1000, 0x4940, 0x6F40, 0x9100, 0xB080, 0xCE40, 0xEB00, 0x4AC4, 0x187A, 0x0FA5, 0x0B9E,
0x0963, 0x07DB, 0x0010, 0x001D, 0x0036, 0x0058, 0x0082, 0x00B3, 0x00EB, 0x1000, 0x4CC0, 0x7300,
0x9440, 0xB2C0, 0xCF80, 0xEB00, 0x4F13, 0x1851, 0x0F69, 0x0B6D, 0x090F, 0x0780, 0x0010, 0x001D,
0x0036, 0x0058, 0x0082, 0x00B3, 0x00EB, 0x1000, 0x5040, 0x7640, 0x9700, 0xB500, 0xD0C0, 0xEB00,
0x5313, 0x187A, 0x0F0F, 0x0B24, 0x08BC, 0x0736, 0x0010, 0x001D, 0x0036, 0x0058, 0x0082, 0x00B3,
0x00EB, 0x1000, 0x5380, 0x79C0, 0x99C0, 0xB700, 0xD1C0, 0xEB00, 0x5713, 0x1851, 0x0EF0, 0x0AC3,
0x087D, 0x06ED, 0x0010, 0x001D, 0x0036, 0x0058, 0x0082, 0x00B3, 0x00EB, 0x1000, 0x56C0, 0x7CC0,
0x9C80, 0xB8C0, 0xD2C0, 0xEB00, 0x5B13, 0x1828, 0x0E96, 0x0A92, 0x0829, 0x06B6, 0x0010, 0x001D,
0x0036, 0x0058, 0x0082, 0x00B3, 0x00EB, 0x1000, 0x5A00, 0x7FC0, 0x9EC0, 0xBA80, 0xD380, 0xEB00,
0x5EC4, 0x1800, 0x0E78, 0x0A30, 0x0800, 0x066D, 0x0010, 0x001D, 0x0036, 0x0058, 0x0082, 0x00B3,
0x00EB, 0x1000, 0x5D00, 0x8280, 0xA140, 0xBC00, 0xD480, 0xEB00, 0x6276, 0x17D7, 0x0E1E, 0x0A00,
0x07C1, 0x0636, 0x0010, 0x001D, 0x0036, 0x0058, 0x0082, 0x00B3, 0x00EB, 0x1000, 0x6000, 0x8540,
0xA340, 0xBD80, 0xD540, 0xEB00, 0x65D8, 0x17AE, 0x0DE1, 0x09CF, 0x0782, 0x0600, 0x0010, 0x001D,
0x0036, 0x0058, 0x0082, 0x00B3, 0x00EB, 0x1000, 0x62C0, 0x87C0, 0xA540, 0xBF00, 0xD600, 0xEB00,
0x693B, 0x1785, 0x0DA5, 0x0986, 0x0743, 0x05DB, 0x0010, 0x001D, 0x0036, 0x0058, 0x0082, 0x00B3,
0x00EB, 0x1000, 0x6580, 0x8A40, 0xA740, 0xC040, 0xD680, 0xEB00};
VIMacroVisionObj VINtscACPType1 = {0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B,
0x1B, 0x24, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0x0F, 0x60,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
VIMacroVisionObj VINtscACPType2 = {0x3E, 0x1D, 0x11, 0x25, 0x11, 0x01, 0x07, 0x00, 0x1B,
0x1B, 0x24, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0x0F, 0x60,
0x01, 0x0A, 0x00, 0x05, 0x04, 0x03, 0xFF, 0x00};
VIMacroVisionObj VINtscACPType3 = {0x3E, 0x17, 0x15, 0x21, 0x15, 0x05, 0x05, 0x02, 0x1B,
0x1B, 0x24, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0x0F, 0x60,
0x01, 0x0A, 0x00, 0x05, 0x04, 0x03, 0xFF, 0x00};
VIMacroVisionObj VIPalACPType1 = {0x36, 0x1A, 0x22, 0x2A, 0x22, 0x05, 0x02, 0x00, 0x1C,
0x3D, 0x14, 0x03, 0xFE, 0x01, 0x54, 0xFE, 0x7E, 0x60,
0x00, 0x08, 0x00, 0x04, 0x07, 0x01, 0x55, 0x01};
VIMacroVisionObj VIPalACPType2 = {0x36, 0x1A, 0x22, 0x2A, 0x22, 0x05, 0x02, 0x00, 0x1C,
0x3D, 0x14, 0x03, 0xFE, 0x01, 0x54, 0xFE, 0x7E, 0x60,
0x00, 0x08, 0x00, 0x04, 0x07, 0x01, 0x55, 0x01};
VIMacroVisionObj VIPalACPType3 = {0x36, 0x1A, 0x22, 0x2A, 0x22, 0x05, 0x02, 0x00, 0x1C,
0x3D, 0x14, 0x03, 0xFE, 0x01, 0x54, 0xFE, 0x7E, 0x60,
0x00, 0x08, 0x00, 0x04, 0x07, 0x01, 0x55, 0x01};
VIMacroVisionObj VIEurgb60ACPType1 = {0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B,
0x1B, 0x24, 0x07, 0xF8, 0x00, 0x00, 0x1E, 0x1E, 0x60,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
VIMacroVisionObj VIEurgb60ACPType2 = {0x36, 0x1D, 0x11, 0x25, 0x11, 0x01, 0x07, 0x00, 0x1B,
0x1B, 0x24, 0x07, 0xF8, 0x00, 0x00, 0x1E, 0x1E, 0x60,
0x01, 0x0A, 0x00, 0x05, 0x04, 0x03, 0xFF, 0x01};
VIMacroVisionObj VIEurgb60ACPType3 = {0x36, 0x17, 0x15, 0x21, 0x15, 0x05, 0x05, 0x02, 0x1B,
0x1B, 0x24, 0x07, 0xF8, 0x00, 0x00, 0x1E, 0x1E, 0x60,
0x01, 0x0A, 0x00, 0x05, 0x04, 0x03, 0xFF, 0x01};
VIMacroVisionObj VIMpalACPType1 = {0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B,
0x1B, 0x24, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0x0F, 0x60,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
VIMacroVisionObj VIMpalACPType2 = {0x36, 0x1D, 0x11, 0x25, 0x11, 0x01, 0x07, 0x00, 0x1B,
0x1B, 0x24, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0x0F, 0x60,
0x01, 0x0A, 0x00, 0x05, 0x04, 0x03, 0xFF, 0x00};
VIMacroVisionObj VIMpalACPType3 = {0x36, 0x17, 0x15, 0x21, 0x15, 0x05, 0x05, 0x02, 0x1B,
0x1B, 0x24, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0x0F, 0x60,
0x01, 0x0A, 0x00, 0x05, 0x04, 0x03, 0xFF, 0x00};
VIMacroVisionObj VIProgressiveACPType = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
VIMacroVisionObj VIZeroACPType = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
extern s32 __VISendI2CData(u8, u8*, s32);
extern void WaitMicroTime(s32);
static void __VISetVideoMode(VIVideo vmode, VIBool outsel) {
u8 buffer[2];
Vdac_Flag_Region = vmode;
buffer[0] = 1;
buffer[1] = (u8)((outsel << 5) | Vdac_Flag_Region);
__VISendI2CData(0xE0, buffer, 2);
WaitMicroTime(2);
}
static void __VISetCCSEL(VIBool ccsel) {
u8 buffer[2];
buffer[0] = 0x6A;
buffer[1] = VI_ENABLE;
__VISendI2CData((u8)0xE0, buffer, 2);
WaitMicroTime(2);
}
static void __VISetOverSampling(VIBool os) {
u8 buffer[2];
buffer[0] = 0x65;
buffer[1] = VI_ENABLE;
__VISendI2CData((u8)0xE0, buffer, 2);
WaitMicroTime(2);
}
void __VISetVolume(u8 volumeL, u8 volumeR) {
u8 buffer[3];
buffer[0] = 0x71;
buffer[1] = volumeL;
buffer[2] = volumeR;
__VISendI2CData((u8)0xE0, buffer, 3);
WaitMicroTime(2);
}
void __VISetYUVSEL(VIBool outsel) {
u8 buffer[2];
u32 tv;
tv = *(u32*)OSPhysicalToCached(0xCC);
switch (tv) {
case VI_PAL:
case VI_EURGB60:
Vdac_Flag_Region = VI_VMODE_PAL;
break;
case VI_MPAL:
Vdac_Flag_Region = VI_VMODE_MPAL;
break;
case VI_NTSC:
Vdac_Flag_Region = VI_VMODE_NTSC;
break;
default:
ASSERTMSGLINE(919, FALSE, "Unkwon TV mode!! TV mode is set to NTSC mode.\n");
Vdac_Flag_Region = VI_VMODE_NTSC;
break;
}
buffer[0] = 0x1;
buffer[1] = (u8)((outsel << 5) | Vdac_Flag_Region);
__VISendI2CData((u8)0xE0, buffer, 2);
WaitMicroTime(2);
}
void __VISetTiming(VITiming timing) {
u8 buffer[2];
buffer[0] = 0x0;
buffer[1] = timing;
__VISendI2CData((u8)0xE0, buffer, 2);
WaitMicroTime(2);
}
void __VISetFilter4EURGB60(VIBool enable) {
u8 buffer[2];
buffer[0] = 0x6E;
buffer[1] = (u8)enable;
__VISendI2CData((u8)0xE0, buffer, 2);
WaitMicroTime(2);
}
void __VISetVBICtrl(VIBool cgms, VIBool wss, VIBool cc) {
u8 buffer[2];
buffer[0] = 0x2;
buffer[1] = (u8)(((~wss & 0x1) << 2) | ((~cgms & 0x1) << 1) | (~cc & 0x1));
__VISendI2CData((u8)0xE0, buffer, 2);
WaitMicroTime(2);
}
static u8 __wd0 = 0xFF;
static u8 __wd1 = 0xFF;
static u8 __wd2 = 0xFF;
void __VISetCGMS(void) {
u8 buffer[3];
buffer[0] = 5;
buffer[1] = (u8)(((__wd1 & 0xF) << 2) | (__wd0 & 3));
buffer[2] = __wd2;
__VISendI2CData((u8)0xE0, buffer, 3);
WaitMicroTime(2);
}
void __VISetCGMSClear(void) {
__wd0 = 0;
__wd1 = 0;
__wd2 = 0;
__VISetCGMS();
}
// NOTE: function doesn't exist in TP debug, needed for string data
void VISetCGMS(void) {
OSReport("VISetCGMS(): Tried to set APS Trigger bit(WORD2[3:2]) \nwhen the scan is progressive in DTV mode, which is forbidden\n");
}
static u8 __gp1 = 0xFF;
static u8 __gp2 = 0xFF;
static u8 __gp3 = 0xFF;
static u8 __gp4 = 0xFF;
void __VISetWSS(void) {
u8 buffer[3];
buffer[0] = 0x8;
buffer[1] = (u8)(((__gp2 & 0xf) << 4) | (__gp1 & 0xf));
buffer[2] = (u8)(((__gp4 & 0x7) << 3) | (__gp3 & 0x7));
__VISendI2CData((u8)0xE0, buffer, 3);
WaitMicroTime(2);
}
void VISetWSS(u8 gp1, u8 gp2, u8 gp3, u8 gp4) {
if ((__gp1 == gp1) && (__gp2 == gp2) && (__gp3 == gp3) && (__gp4 == gp4)) {
return;
}
__gp1 = gp1;
__gp2 = gp2;
__gp3 = gp3;
__gp4 = gp4;
Vdac_Flag_Changed |= 2;
}
static u8 __cc1 = 0xFF;
static u8 __cc2 = 0xFF;
static u8 __cc3 = 0xFF;
static u8 __cc4 = 0xFF;
void __VISetClosedCaption(void) {
u8 buffer[5];
buffer[0] = 0x7A;
buffer[1] = (u8)(__cc1 & 0x7F);
buffer[2] = (u8)(__cc2 & 0x7F);
buffer[3] = (u8)(__cc3 & 0x7F);
buffer[4] = (u8)(__cc4 & 0x7F);
__VISendI2CData((u8)0xE0, buffer, 5);
WaitMicroTime(2);
}
void VISetClosedCaption(u8 cc1, u8 cc2, u8 cc3, u8 cc4) {
if ((__cc1 == cc1) && (__cc2 == cc2) && (__cc3 == cc3) && (__cc4 == cc4)) {
return;
}
__cc1 = cc1;
__cc2 = cc2;
__cc3 = cc3;
__cc4 = cc4;
Vdac_Flag_Changed |= 4;
}
void __VISetMacrovisionImm(VIMacroVisionObj* mparam) {
u8 i;
u8 buffer[27];
buffer[0] = 0x40;
for (i = 1; i < 27; i++) {
buffer[i] = mparam->m[i - 1];
}
__VISendI2CData((u8)0xE0, buffer, 27);
WaitMicroTime(2);
}
void __VISetMacrovision(void) {
switch (__type) {
case 2:
switch (__tvType) {
case VI_NTSC:
__VISetMacrovisionImm(&VINtscACPType1);
break;
case VI_PAL:
__VISetMacrovisionImm(&VIPalACPType1);
break;
case VI_MPAL:
__VISetMacrovisionImm(&VIMpalACPType1);
break;
case VI_EURGB60:
__VISetMacrovisionImm(&VIEurgb60ACPType1);
break;
}
break;
case 3:
switch (__tvType) {
case VI_NTSC:
__VISetMacrovisionImm(&VINtscACPType2);
break;
case VI_PAL:
__VISetMacrovisionImm(&VIPalACPType2);
break;
case VI_MPAL:
__VISetMacrovisionImm(&VIMpalACPType2);
break;
case VI_EURGB60:
__VISetMacrovisionImm(&VIEurgb60ACPType2);
break;
}
break;
case 4:
switch (__tvType) {
case VI_NTSC:
__VISetMacrovisionImm(&VINtscACPType3);
break;
case VI_PAL:
__VISetMacrovisionImm(&VIPalACPType3);
break;
case VI_MPAL:
__VISetMacrovisionImm(&VIMpalACPType3);
break;
case VI_EURGB60:
__VISetMacrovisionImm(&VIEurgb60ACPType3);
break;
}
break;
case 1:
__VISetMacrovisionImm(&VIZeroACPType);
break;
}
}
void __VISetGammaImm(VIGammaObj* gamma) {
u8 i, j;
u8 buffer[34];
buffer[0] = 0x10;
i = 1;
for (j = 0; j < 6; j++) {
buffer[i] = (u8)((gamma->a[j] >> 8) & 0xFF);
buffer[i + 1] = (u8)(gamma->a[j] & 0xFF);
i += 2;
}
for (j = 0; j < 7; j++) {
buffer[i] = gamma->yin[j];
i++;
}
for (j = 0; j < 7; j++) {
buffer[i] = (u8)((gamma->yout[j] >> 8) & 0xFF);
buffer[i + 1] = (u8)(gamma->yout[j] & 0xC0);
i += 2;
}
__VISendI2CData((u8)0xE0, buffer, 34);
WaitMicroTime(2);
}
void __VISetGamma1_0(void) {
__VISetGammaImm(&gammaSet[10]);
}
static VIGamma __gamma;
void __VISetGamma(void) {
__VISetGammaImm(&gammaSet[__gamma]);
}
void VISetGamma(VIGamma gamma) {
if (__gamma != gamma) {
__gamma = gamma;
Vdac_Flag_Changed |= 0x10;
}
}
static VIBool __filter = 0xFF;
void __VISetTrapFilterImm(VIBool filter) {
u8 buffer[2];
buffer[0] = 0x3;
if (filter == VI_TRUE) {
buffer[1] = VI_FALSE;
} else {
buffer[1] = VI_TRUE;
}
__VISendI2CData((u8)0xE0, buffer, 2);
WaitMicroTime(2);
}
void __VISetTrapFilter(void) {
u8 buffer[2];
buffer[0] = 0x3;
if (__filter == VI_TRUE) {
buffer[1] = VI_FALSE;
} else {
buffer[1] = VI_TRUE;
}
__VISendI2CData((u8)0xE0, buffer, 2);
WaitMicroTime(2);
}
void VISetTrapFilter(VIBool filter) {
if (__filter == filter) {
return;
}
__filter = filter;
Vdac_Flag_Changed |= 0x20;
}
static VIOverDrive __level;
void __VISetRGBOverDrive(void) {
u8 buffer[2];
if (Vdac_Flag_Region == VI_VMODE_RGB) {
buffer[0] = 0xA;
buffer[1] = (u8)((__level << 1) | VI_ENABLE);
__VISendI2CData((u8)0xE0, buffer, 2);
WaitMicroTime(2);
} else {
buffer[0] = 0xA;
buffer[1] = VI_DISABLE;
__VISendI2CData((u8)0xE0, buffer, 2);
WaitMicroTime(2);
}
}
void VISetRGBOverDrive(VIOverDrive level) {
if (__level == level) {
return;
}
__level = level;
Vdac_Flag_Changed |= 0x40;
}
void VISetRGBModeImm(void) {
Vdac_Flag_Changed |= 0x80;
}
void __VISetRGBModeImm(void) {
__VISetVideoMode(VI_VMODE_RGB, VI_DISABLE);
}
void __VISetRevolutionModeSimple(void) {
u32 dtv;
__VISetCCSEL(VI_TRUE);
__VISetOverSampling(VI_TRUE);
dtv = VIGetDTVStatus();
__VISetYUVSEL((VIBool)dtv);
__VISetTiming(VI_TMG_GAME);
__VISetVolume(0x8E, 0x8E);
__VISetVBICtrl(VI_DISABLE, VI_DISABLE, VI_DISABLE);
__VISetCGMSClear();
VISetWSS(0, 0, 0, 0);
__VISetWSS();
VISetClosedCaption(0, 0, 0, 0);
__VISetClosedCaption();
__VISetMacrovisionImm(&VIZeroACPType);
VISetRGBOverDrive(VI_ODV_L1);
__VISetRGBOverDrive();
__VISetTrapFilterImm(VI_DISABLE);
__VISetGammaImm(&gammaSet[VI_GM_1_0]);
__current_3in1_video_mode = 0;
}
+117
View File
@@ -0,0 +1,117 @@
#include <revolution/wenc.h>
#include <string.h>
s32 WENCGetEncodeData(WENCInfo* info, u32 flag, const s16* pcmData, s32 samples, u8* adpcmData) {
const f64 table[] = {0.89843750, 0.89843750, 0.89843750, 0.89843750,
1.19921875, 1.59765625, 2.00000000, 2.39843750};
u8* dst;
const s16* src;
s32 i;
s32 da;
s32 l3, l2, l1, l0;
s32 dlx;
s32 xnc;
s32 offset;
s32 index;
s32 encodeSize;
s32 xn;
s32 dl;
s32 qn;
s32 dn;
s32 dlh;
s32 dlq;
u8 by;
encodeSize = (samples + 1) / 2;
memset(adpcmData, 0, encodeSize);
src = pcmData;
dst = adpcmData;
if ((flag & WENC_FLAG_USER_INFO) == 0) {
xn = 0;
dl = 127;
qn = 0;
dn = 0;
dlh = 0;
dlq = 0;
} else {
xn = info->xn;
dl = info->dl;
qn = info->qn;
dn = info->dn;
dlh = info->dlh;
dlq = info->dlq;
}
for (i = 0; i < samples; i++) {
l3 = l2 = l1 = l0 = 0;
da = *src++;
if (da < xn) {
l3 = 1;
}
dn = __abs(da - xn);
if (dn >= dl) {
l2 = 1;
dn -= dl;
}
dlh = dl / 2;
if (dn >= dlh) {
l1 = 1;
dn -= dlh;
}
dlq = dlh / 2;
if (dn >= dlq) {
l0 = 1;
dn -= dlq;
}
dlx = dlq / 2;
qn = (1 - l3 * 2) * (dl * l2 + dlh * l1 + dlq * l0 + dlx);
if (qn > 0xFFFF) {
qn = 0xFFFF;
}
if (qn < -0x10000) {
qn = -0x10000;
}
xnc = xn + qn;
if (xnc > 0x7FFF) {
xnc = 0x7FFF;
}
if (xnc < -0x8000) {
xnc = -0x8000;
}
xn = xnc;
offset = (i & 1) == 0 ? 4 : 0;
by = l3 * 8 + l2 * 4 + l1 * 2 + l0;
dst[i / 2] |= by << offset;
index = l2 * 4 + l1 * 2 + l0;
dl *= table[index];
if (dl <= 127) {
dl = 127;
}
if (dl >= 0x6000) {
dl = 0x6000;
}
}
info->xn = xn;
info->dl = dl;
info->qn = qn;
info->dn = dn;
info->dlh = dlh;
info->dlq = dlq;
return samples;
}
+434
View File
@@ -0,0 +1,434 @@
#include <revolution/os.h>
#include <revolution/wpad.h>
#include <revolution/wpad/wud.h>
#include <string.h>
#include "__wpad.h"
wpad_cb_st* __rvl_p_wpadcb[WPAD_MAX_CONTROLLERS];
static u8 _wpadSpeakerVol;
static s8 __wpadGetQueueSize(struct WPADCmdQueue* cmdQueue);
static u16 __wpadGetBTEBufferStatus(s32 chan);
static u16 __wpadGetBTMBufferStatus(s32 chan);
static BOOL __wpadPushCommand(struct WPADCmdQueue* cmdQueue, struct WPADCmd cmdBlk);
void dummyString(void* p_buf) {
ASSERTLINE(0, p_buf != NULL);
}
static u32 __wpadFmt2Size(u32 fmt) {
u32 fmtSize;
switch (fmt) {
case WPAD_FMT_FS_BTN:
case WPAD_FMT_FS_BTN_ACC:
case WPAD_FMT_FS_BTN_ACC_DPD:
fmtSize = sizeof(WPADFSStatus);
break;
case WPAD_FMT_CLASSIC_BTN:
case WPAD_FMT_CLASSIC_BTN_ACC:
case WPAD_FMT_CLASSIC_BTN_ACC_DPD:
case WPAD_FMT_GUITAR:
case WPAD_FMT_DRUM:
case WPAD_FMT_TAIKO:
case WPAD_FMT_TURNTABLE:
fmtSize = sizeof(WPADCLStatus);
break;
case WPAD_FMT_BULK:
fmtSize = sizeof(WPADBKStatus);
break;
case WPAD_FMT_TRAIN:
fmtSize = sizeof(WPADTRStatus);
break;
case 20:
fmtSize = 0x32;
break;
case WPAD_FMT_BALANCE_CHECKER:
fmtSize = sizeof(WPADBLStatus);
break;
case WPAD_FMT_VSM:
fmtSize = sizeof(WPADVSStatus);
break;
case WPAD_FMT_BTN_ACC_DPD_EXTENDED:
fmtSize = sizeof(WPADStatusEx);
break;
case WPAD_FMT_MOTION_PLUS:
fmtSize = sizeof(WPADMPStatus);
break;
default:
fmtSize = sizeof(WPADStatus);
break;
}
return fmtSize;
}
u8 WPADGetRadioSensitivity(s32 chan) {
wpad_cb_st* p_wpd = __rvl_p_wpadcb[chan];
BOOL intrStatus = OSDisableInterrupts();
u8 radioSensitivity = p_wpd->radioSensitivity;
OSRestoreInterrupts(intrStatus);
return radioSensitivity;
}
void WPADRead(s32 chan, WPADStatus* status) {
wpad_cb_st* p_wpd = __rvl_p_wpadcb[chan];
BOOL intrStatus;
u8 rxBufIndex;
WPADStatus* rxStatus;
u32 fmtSize;
ASSERTLINE(4013, (0 <= chan) && (chan < WPAD_MAX_CONTROLLERS));
ASSERTLINE(4014, status != NULL);
intrStatus = OSDisableInterrupts();
rxBufIndex = p_wpd->rxBufIndex != 0 ? 0 : 1;
rxStatus = (WPADStatus*)p_wpd->rxBufs[rxBufIndex];
fmtSize = __wpadFmt2Size(p_wpd->dataFormat);
if (rxStatus->err != WPAD_ESUCCESS)
fmtSize = sizeof(WPADStatus);
memcpy(status, rxStatus, fmtSize);
OSRestoreInterrupts(intrStatus);
}
BOOL WPADIsSpeakerEnabled(s32 chan) {
BOOL enabled;
wpad_cb_st* p_wpd = __rvl_p_wpadcb[chan];
BOOL intrStatus = OSDisableInterrupts();
enabled = p_wpd->info.speaker;
OSRestoreInterrupts(intrStatus);
return enabled;
}
s32 WPADControlSpeaker(s32 chan, u32 command, WPADCallback* cb) {
u8 data[7] = {0x00, 0x00, 0xd0, 0x07, 0x40, 0x0c, 0x0e};
wpad_cb_st* p_wpd = __rvl_p_wpadcb[chan];
BOOL intrStatus = OSDisableInterrupts();
BOOL speakerEnabled = p_wpd->info.speaker;
BOOL handshakeFinished;
s32 status = p_wpd->status;
handshakeFinished = p_wpd->handshakeFinished;
OSRestoreInterrupts(intrStatus);
if (status == WPAD_ENODEV)
goto end;
if (!handshakeFinished) {
status = WPAD_EBUSY;
goto end;
}
if (command == WPAD_SPEAKER_DISABLE) {
if (!speakerEnabled) {
status = WPAD_ESUCCESS;
goto end;
}
intrStatus = OSDisableInterrupts();
if (WPADiIsAvailableCmdQueue(&p_wpd->stdCmdQueue, 5)) {
WPADiSendMuteSpeaker(&p_wpd->stdCmdQueue, TRUE, NULL);
WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, 0x01, WM_REG_SPEAKER_01, NULL);
WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, 0x00, WM_REG_SPEAKER_09, NULL);
WPADiSendEnableSpeaker(&p_wpd->stdCmdQueue, FALSE, NULL);
WPADiSendGetContStat(&p_wpd->stdCmdQueue, NULL, cb);
OSRestoreInterrupts(intrStatus);
return WPAD_ESUCCESS;
}
status = WPAD_EBUSY;
OSRestoreInterrupts(intrStatus);
} else {
switch (command) {
case WPAD_SPEAKER_ENABLE:
case WPAD_SPEAKER_CMD_05:
intrStatus = OSDisableInterrupts();
if (WPADiIsAvailableCmdQueue(&p_wpd->stdCmdQueue, 7)) {
WPADiSendEnableSpeaker(&p_wpd->stdCmdQueue, TRUE, NULL);
WPADiSendMuteSpeaker(&p_wpd->stdCmdQueue, TRUE, NULL);
WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, 0x01, WM_REG_SPEAKER_09, NULL);
// sends 0x80 instead of 0x08?
WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, 0x80, WM_REG_SPEAKER_01, NULL);
data[4] = _wpadSpeakerVol;
WPADiSendWriteData(&p_wpd->stdCmdQueue, &data, sizeof data, WM_REG_SPEAKER_01,
NULL);
WPADiSendMuteSpeaker(&p_wpd->stdCmdQueue, FALSE, NULL);
WPADiSendGetContStat(&p_wpd->stdCmdQueue, NULL, cb);
OSRestoreInterrupts(intrStatus);
return WPAD_ESUCCESS;
}
status = WPAD_EBUSY;
OSRestoreInterrupts(intrStatus);
break;
case WPAD_SPEAKER_MUTE:
if (!WPADiSendMuteSpeaker(&p_wpd->stdCmdQueue, TRUE, cb)) {
status = WPAD_EBUSY;
goto end;
}
return WPAD_ESUCCESS;
case WPAD_SPEAKER_UNMUTE:
if (!WPADiSendMuteSpeaker(&p_wpd->stdCmdQueue, FALSE, cb)) {
status = WPAD_EBUSY;
goto end;
}
return WPAD_ESUCCESS;
case WPAD_SPEAKER_PLAY:
if (!WPADiSendWriteDataCmd(&p_wpd->stdCmdQueue, 0x01, WM_REG_SPEAKER_08, cb)) {
status = WPAD_EBUSY;
goto end;
}
return WPAD_ESUCCESS;
}
}
end:
if (cb)
(*cb)(chan, status);
return status;
}
BOOL __wpadIsBusyStream(s32 chan) {
BOOL intrStatus;
wpad_cb_st* p_wpd = __rvl_p_wpadcb[chan];
u8 radioQuality;
u32 devType;
u8 bufferStatus;
u16 bteBufferStatus;
u16 btmBufferStatus;
u8 audioFrames;
s8 queueSize;
u8 linkNumber;
intrStatus = OSDisableInterrupts();
radioQuality = p_wpd->radioQuality;
devType = p_wpd->devType;
bufferStatus = WUDGetBufferStatus();
queueSize = __wpadGetQueueSize(&p_wpd->stdCmdQueue);
bteBufferStatus = __wpadGetBTEBufferStatus(chan);
btmBufferStatus = __wpadGetBTMBufferStatus(chan);
audioFrames = p_wpd->audioFrames;
linkNumber = _WUDGetLinkNumber();
OSRestoreInterrupts(intrStatus);
if (radioQuality != WPAD_RADIO_QUALITY_GOOD || btmBufferStatus > 3 || bufferStatus == 10 ||
bufferStatus >= linkNumber * 2 + 2 || devType == WPAD_DEV_INITIALIZING || queueSize >= 21 ||
audioFrames >= 1)
{
return TRUE;
} else {
return FALSE;
}
}
s32 WPADSendStreamData(s32 chan, void* p_buf, u16 len) {
wpad_cb_st* p_wpd = __rvl_p_wpadcb[chan];
BOOL intrStatus;
BOOL handshakeFinished;
s32 status;
ASSERTLINE(4528, p_buf != NULL);
ASSERTLINE(4529, len >= 0 && len <= 20);
intrStatus = OSDisableInterrupts();
status = p_wpd->status;
handshakeFinished = p_wpd->handshakeFinished;
OSRestoreInterrupts(intrStatus);
if (status == WPAD_ENODEV)
return WPAD_ENODEV;
if (!handshakeFinished)
return WPAD_EBUSY;
if (__wpadIsBusyStream(chan))
return WPAD_EBUSY;
if (!WPADiSendStreamData(&p_wpd->stdCmdQueue, p_buf, len))
return WPAD_EBUSY;
intrStatus = OSDisableInterrupts();
++p_wpd->audioFrames;
OSRestoreInterrupts(intrStatus);
return WPAD_ESUCCESS;
}
BOOL WPADiSendEnableSpeaker(struct WPADCmdQueue* cmdQueue, BOOL enabled, WPADCallback* cb) {
BOOL success;
struct WPADCmd cmdBlk;
cmdBlk.reportID = RPTID_ENABLE_SPEAKER;
cmdBlk.dataLength = RPT14_SIZE;
cmdBlk.dataBuf[RPT14_SPEAKER_ENABLE] = enabled ? 4 : 0;
cmdBlk.cmdCB = cb;
success = __wpadPushCommand(cmdQueue, cmdBlk);
return success;
}
BOOL WPADiSendGetContStat(struct WPADCmdQueue* cmdQueue, WPADInfo* infoOut, WPADCallback* cb) {
BOOL success;
struct WPADCmd cmdBlk;
cmdBlk.reportID = RPTID_REQUEST_STATUS;
cmdBlk.dataLength = RPT15_SIZE;
cmdBlk.dataBuf[0] = 0;
cmdBlk.cmdCB = cb;
cmdBlk.statusReportOut = infoOut;
success = __wpadPushCommand(cmdQueue, cmdBlk);
return success;
}
BOOL WPADiSendWriteDataCmd(struct WPADCmdQueue* cmdQueue, u8 cmd, u32 address, WPADCallback* cb) {
return WPADiSendWriteData(cmdQueue, &cmd, sizeof(cmd), address, cb);
}
BOOL WPADiSendWriteData(struct WPADCmdQueue* cmdQueue, void const* p_buf, u16 len, u32 address,
WPADCallback* cb) {
BOOL success;
u8 packedLen = len & 0x1f;
struct WPADCmd cmdBlk;
ASSERTLINE(5830, len > 0 && len <= 16);
ASSERTLINE(5831, p_buf != NULL);
cmdBlk.reportID = RPTID_WRITE_DATA;
cmdBlk.dataLength = RPT16_SIZE;
cmdBlk.cmdCB = cb;
memcpy(&cmdBlk.dataBuf[RPT16_DATA_DST_ADDRESS], &address, sizeof address);
memcpy(&cmdBlk.dataBuf[RPT16_DATA_LENGTH], &packedLen, sizeof packedLen);
memcpy(&cmdBlk.dataBuf[RPT16_DATA], p_buf, len);
success = __wpadPushCommand(cmdQueue, cmdBlk);
return success;
}
BOOL WPADiSendStreamData(struct WPADCmdQueue* cmdQueue, void const* p_buf, u16 len) {
BOOL success;
u8 packedLen = len << 3;
struct WPADCmd cmdBlk;
ASSERTLINE(5873, len > 0 && len <= 20);
cmdBlk.reportID = RPTID_SEND_SPEAKER_DATA;
cmdBlk.dataLength = sizeof cmdBlk.dataBuf;
cmdBlk.dataBuf[RPT18_DATA_LENGTH] = packedLen;
cmdBlk.cmdCB = NULL;
memcpy(&cmdBlk.dataBuf[RPT18_DATA], p_buf, len);
success = __wpadPushCommand(cmdQueue, cmdBlk);
return success;
}
BOOL WPADiSendMuteSpeaker(struct WPADCmdQueue* cmdQueue, BOOL muted, WPADCallback* cb) {
BOOL success;
struct WPADCmd cmdBlk;
cmdBlk.reportID = RPTID_MUTE_SPEAKER;
cmdBlk.dataLength = RPT19_SIZE;
cmdBlk.dataBuf[RPT19_SPEAKER_MUTE] = muted ? 4 : 0;
cmdBlk.cmdCB = cb;
success = __wpadPushCommand(cmdQueue, cmdBlk);
return success;
}
BOOL WPADiIsAvailableCmdQueue(struct WPADCmdQueue* cmdQueue, s8 num) {
s8 queueSize = __wpadGetQueueSize(cmdQueue);
if ((u32)(queueSize + num) <= cmdQueue->length - 1)
return TRUE;
else
return FALSE;
}
static s8 __wpadGetQueueSize(struct WPADCmdQueue* cmdQueue) {
BOOL intrStatus = OSDisableInterrupts();
s8 queueRemaining = cmdQueue->indexIn - cmdQueue->indexOut;
if (queueRemaining < 0)
queueRemaining += cmdQueue->length;
OSRestoreInterrupts(intrStatus);
return queueRemaining;
}
static BOOL __wpadPushCommand(struct WPADCmdQueue* cmdQueue, struct WPADCmd cmdBlk) {
BOOL intrStatus = OSDisableInterrupts();
if (cmdQueue->length - 1 == (u32)__wpadGetQueueSize(cmdQueue)) {
OSRestoreInterrupts(intrStatus);
return FALSE;
}
memset(&cmdQueue->queue[cmdQueue->indexIn], 0, sizeof cmdQueue->queue[cmdQueue->indexIn]);
memcpy(&cmdQueue->queue[cmdQueue->indexIn], &cmdBlk, sizeof cmdQueue->queue[cmdQueue->indexIn]);
cmdQueue->indexIn = (u32)cmdQueue->indexIn == ((cmdQueue->length) - 1) ? 0 : cmdQueue->indexIn + 1;
OSRestoreInterrupts(intrStatus);
return TRUE;
}
static u16 __wpadGetBTEBufferStatus(s32 chan) {
wpad_cb_st* p_wpd = __rvl_p_wpadcb[chan];
BOOL intrStatus = OSDisableInterrupts();
s32 status = p_wpd->status;
s8 dev_handle = p_wpd->devHandle;
OSRestoreInterrupts(intrStatus);
if (status == WPAD_ENODEV)
return 0;
return _WUDGetQueuedSize(dev_handle);
}
static u16 __wpadGetBTMBufferStatus(s32 chan) {
wpad_cb_st* p_wpd = __rvl_p_wpadcb[chan];
BOOL intrStatus = OSDisableInterrupts();
s32 status = p_wpd->status;
s8 dev_handle = p_wpd->devHandle;
OSRestoreInterrupts(intrStatus);
if (status == WPAD_ENODEV)
return 0;
return _WUDGetNotAckedSize(dev_handle);
}
+63
View File
@@ -0,0 +1,63 @@
#include <revolution/os.h>
#include <revolution/wpad/wud.h>
#include "__wud.h"
wud_cb_st __rvl_wudcb;
static u16 _dev_handle_queue_size[WUD_MAX_DEV_ENTRY];
static u16 _dev_handle_notack_num[WUD_MAX_DEV_ENTRY];
u8 WUDGetBufferStatus(void) {
wud_cb_st* p_wcb = &__rvl_wudcb;
u8 ret;
BOOL intrStatus = OSDisableInterrupts();
ret = p_wcb->bufferStatus1 - p_wcb->bufferStatus0;
OSRestoreInterrupts(intrStatus);
return ret;
}
u16 _WUDGetQueuedSize(s8 dev_handle) {
u16 queuedSize;
BOOL intrStatus = OSDisableInterrupts();
if (dev_handle >= 0 && dev_handle < WUD_MAX_DEV_ENTRY)
queuedSize = WUDiGetQueueSizeForHandle(dev_handle);
else
queuedSize = 0;
OSRestoreInterrupts(intrStatus);
return queuedSize;
}
u16 _WUDGetNotAckedSize(s8 dev_handle) {
u16 notAckedSize;
BOOL intrStatus = OSDisableInterrupts();
if (dev_handle >= 0 && dev_handle < WUD_MAX_DEV_ENTRY)
notAckedSize = WUDiGetNotAckNumForHandle(dev_handle);
else
notAckedSize = 0;
OSRestoreInterrupts(intrStatus);
return notAckedSize;
}
u8 _WUDGetLinkNumber(void) {
wud_cb_st* p_wcb = &__rvl_wudcb;
BOOL intrStatus = OSDisableInterrupts();
u8 linkedNum = p_wcb->linkedNum;
OSRestoreInterrupts(intrStatus);
return linkedNum;
}
u16 WUDiGetQueueSizeForHandle(u8 dev_handle) {
return _dev_handle_queue_size[dev_handle];
}
u16 WUDiGetNotAckNumForHandle(u8 dev_handle) {
return _dev_handle_notack_num[dev_handle];
}
+538
View File
@@ -0,0 +1,538 @@
#ifndef _REVOLUTION_WPAD_PRIVATE_H_
#define _REVOLUTION_WPAD_PRIVATE_H_
#include <revolution/os.h>
#include <revolution/wpad.h>
#ifdef __cplusplus
extern "C" {
#endif
#define RPT_REPORT_ID 0
#define RPT_MAX_SIZE 21
// Limits
#define RPTID_OUT_LO RPTID_SET_RUMBLE
#define RPTID_OUT_HI RPTID_SET_DPD_CSB
#define RPTID_IN_LO RPTID_STATUS
#define RPTID_IN_HI RPTID_DATA_BTN_ACC_DPD18_2
// All outgoing reports
#define RPT_OUT_FLAGS 1
#define RPT_OUT_FLAG_ENABLE_FEATURE 2
#define RPT_OUT_FLAG_REQUEST_ACK_RPT 1
#define RPT_OUT_FLAG_RUMBLE 0
// All incoming reports with Button data (all except 0x3d)
#define RPT_BTN0 1
#define RPT_BTN1 2
// All incoming reports with Accelerometer (Standard) data (0x31, 0x33, 0x35, 0x37)
#define RPT_ACC_OFFSET 1
#define RPT_ACC_SIZE 3
/*
* Outgoing reports (from POV of the host)
*/
// Report 0x10: Set rumble status
#define RPTID_SET_RUMBLE 0x10
#define RPT10_SIZE 1
#define RPT10_RUMBLE 0
// Report 0x11: Set LED lights
#define RPTID_SET_PORT 0x11 // internally called SetPort
#define RPT11_SIZE 1
#define RPT11_LED 0
// Report 0x12: Set data reporting mode
#define RPTID_SET_DATA_REPORT_MODE 0x12
#define RPT12_SIZE 2
#define RPT12_CONT_REPORT 0
#define RPT12_DATA_REPORT_MODE 1
// Report 0x13: Enable IR camera
#define RPTID_ENABLE_DPD 0x13 // internally called the DPD
#define RPT13_SIZE 1
#define RPT13_DPD_ENABLE 0
// Report 0x14: Enable IR camera
#define RPTID_ENABLE_SPEAKER 0x14
#define RPT14_SIZE 1
#define RPT14_SPEAKER_ENABLE 0
// Report 0x15: Request status report
#define RPTID_REQUEST_STATUS 0x15
#define RPT15_SIZE 1
// Report 0x16: Write data
#define RPTID_WRITE_DATA 0x16
#define RPT16_SIZE RPT_MAX_SIZE
#define RPT16_DATA_DST_ADDRESS 0
#define RPT16_DATA_LENGTH 4
#define RPT16_DATA 5
// Report 0x17: Read data
#define RPTID_READ_DATA 0x17
#define RPT17_SIZE 6
#define RPT17_DATA_SRC_ADDRESS 0
#define RPT17_DATA_LENGTH 4
// Report 0x18: Send speaker data
#define RPTID_SEND_SPEAKER_DATA 0x18
#define RPT18_SIZE RPT_MAX_SIZE
#define RPT18_DATA_LENGTH 0
#define RPT18_DATA 1
// Report 0x19: Mute speaker
#define RPTID_MUTE_SPEAKER 0x19
#define RPT19_SIZE 1
#define RPT19_SPEAKER_MUTE 0
// Report 0x19: WPADiSendDPDCSB (?)
#define RPTID_SEND_DPD_CSB 0x1a
#define RPT1A_SIZE 1
#define RPT1A_DPD_CSB 0
/*
* Incoming reports (from POV of the host)
*/
// Report 0x20: Status report
#define RPTID_STATUS 0x20
#define RPT20_FLAGS 3
#define RPT20_PROTO_FW 5
#define RPT20_BATTERY 6
// Report 0x21: Read Wiimote data
#define RPTID_DATA_READ 0x21
#define RPT21_SIZE_ERR 3
#define RPT21_ADDR0 4
#define RPT21_ADDR1 5
#define RPT21_DATA 6
// Report 0x22: Acknowledgement and request result
#define RPTID_ACK 0x22
#define RPT22_ACKED_RPT_ID 3
#define RPT22_ERR_CODE 4
// Reports 0x23-0x2f: Unused
// Report 0x30: Buttons
#define RPTID_DATA_BTN 0x30
// Report 0x31: Buttons, Accelerometer (Standard)
#define RPTID_DATA_BTN_ACC 0x31
// Report 0x32: Buttons, Extension (8 bytes)
#define RPTID_DATA_BTN_EXT8 0x32
#define RPT32_EXT_OFFSET 3
#define RPT32_EXT_LENGTH 8
/* Report 0x33: Buttons, Accelerometer (Standard), IR Camera (Standard, 12
* bytes)
*/
#define RPTID_DATA_BTN_ACC_DPD12 0x33
#define RPT33_DPD_OFFSET 6
#define RPT33_DPD_LENGTH 12
// Report 0x34: Buttons, Extension (19 bytes)
#define RPTID_DATA_BTN_EXT19 0x34
#define RPT34_EXT_OFFSET 3
#define RPT34_EXT_LENGTH 19
// Report 0x35: Buttons, Accelerometer (Standard), Extension (16 bytes)
#define RPTID_DATA_BTN_ACC_EXT16 0x35
#define RPT35_EXT_OFFSET 6
#define RPT35_EXT_LENGTH 16
// Report 0x36: Buttons, IR Camera (Basic, 10 bytes), Extension (9 bytes)
#define RPTID_DATA_BTN_DPD10_EXT9 0x36
#define RPT36_DPD_OFFSET 3
#define RPT36_DPD_LENGTH 10
#define RPT36_EXT_OFFSET 13
#define RPT36_EXT_LENGTH 9
/* Report 0x37: Buttons, Accelerometer (Standard), IR Camera (Basic, 10
* bytes), Extension (6 bytes)
*/
#define RPTID_DATA_BTN_ACC_DPD10_EXT9 0x37
#define RPT37_DPD_OFFSET 6
#define RPT37_DPD_LENGTH 10
#define RPT37_EXT_OFFSET 16
#define RPT37_EXT_LENGTH 6
// Report 0x38-0x3c: Unused
// Report 0x3d: Extension (21 bytes)
#define RPTID_DATA_EXT21 0x3d
#define RPT3D_EXT_OFFSET 1
#define RPT3D_EXT_LENGTH 21
/* Report 0x3e: Buttons, Accelerometer (Interleaved 1), IR Camera (Full 1,
* 18 bytes)
*/
#define RPTID_DATA_BTN_ACC_DPD18_1 0x3e
#define RPT3E_DPD0 0
#define RPT3E_DPD0_OFFSET 4
#define RPT3E_DPD1 1
#define RPT3E_DPD1_OFFSET 13
/* Report 0x3e: Buttons, Accelerometer (Interleaved 2), IR Camera (Full 2,
* 18 bytes)
*/
#define RPTID_DATA_BTN_ACC_DPD18_2 0x3f
#define RPT3F_DPD2 2
#define RPT3F_DPD2_OFFSET 4
#define RPT3F_DPD3 3
#define RPT3F_DPD3_OFFSET 13
#define WPAD_EXT_REG_SPEAKER 0xa2
#define WPAD_EXT_REG_EXTENSION 0xa4
#define WPAD_EXT_REG_MOTION_PLUS 0xa6
#define WPAD_EXT_REG_DPD 0xb0
#define RX_BUFFER_SIZE OSRoundUp32B(sizeof(WPADStatusEx))
#define LINT_NUM_MAX_LENGTH 64
#define LINT_NUM_MAX_BUFSIZ (1 + LINT_NUM_MAX_LENGTH + 1)
#define WM_MEM_ADDR(addr_) ((addr_) & 0xffff)
#define WM_EXT_REG_ADDR(type_, addr_) \
(((addr_) & 0xffff) | ((WPAD_EXT_REG_##type_) << 16) | (1 << 26))
// https://wiibrew.org/wiki/Wiimote#EEPROM_Memory
#define WM_ADDR_MEM_DEV_CONFIG_0 WM_MEM_ADDR(0x0000)
#define WM_ADDR_MEM_GAME_INFO_0 WM_MEM_ADDR(0x002a)
#define WM_ADDR_MEM_GAME_INFO_1 WM_MEM_ADDR(0x0062)
// out of range??? wiibrew says the wiimote only has 0x1600 bytes of memory
#define WM_ADDR_MEM_176C WM_MEM_ADDR(0x176c)
#define WM_ADDR_MEM_1770 WM_MEM_ADDR(0x1770)
/*
* Wiimote extension register addresses
*/
// Speaker register addresses
#define WM_REG_SPEAKER_01 WM_EXT_REG_ADDR(SPEAKER, 0x01)
#define WM_REG_SPEAKER_08 WM_EXT_REG_ADDR(SPEAKER, 0x08)
#define WM_REG_SPEAKER_09 WM_EXT_REG_ADDR(SPEAKER, 0x09)
// Extension register addresses
#define WM_REG_EXTENSION_CONFIG WM_EXT_REG_ADDR(EXTENSION, 0x20)
#define WM_REG_EXTENSION_40 WM_EXT_REG_ADDR(EXTENSION, 0x40)
#define WM_REG_EXTENSION_CERT_PARAM WM_EXT_REG_ADDR(EXTENSION, 0x50)
#define WM_REG_EXTENSION_F0 WM_EXT_REG_ADDR(EXTENSION, 0xf0)
#define WM_REG_EXTENSION_CERT_CHALLENGE WM_EXT_REG_ADDR(EXTENSION, 0xf1)
#define WM_REG_EXTENSION_F2 WM_EXT_REG_ADDR(EXTENSION, 0xf2)
#define WM_REG_EXTENSION_F3 WM_EXT_REG_ADDR(EXTENSION, 0xf3)
#define WM_REG_EXTENSION_EXT_TYPE_2 WM_EXT_REG_ADDR(EXTENSION, 0xf6)
#define WM_REG_EXTENSION_CERT_PROBE WM_EXT_REG_ADDR(EXTENSION, 0xf7)
#define WM_REG_EXTENSION_FA WM_EXT_REG_ADDR(EXTENSION, 0xfa)
#define WM_REG_EXTENSION_FB WM_EXT_REG_ADDR(EXTENSION, 0xfb)
#define WM_REG_EXTENSION_DEV_MODE WM_EXT_REG_ADDR(EXTENSION, 0xfe)
#define WM_REG_EXTENSION_ID_BYTE WM_EXT_REG_ADDR(EXTENSION, 0xff)
#define WM_EXTENSION_CONFIG_SIZE 0x20 // 0xa40020 - 0xa4003f
#define WM_EXTENSION_CERT_PARAM_SIZE 0x40 // 0xa40050 - 0xa4008f
// Wiimote Motion Plus register addresses
#define WM_REG_MPLS_F0 WM_EXT_REG_ADDR(MOTION_PLUS, 0xf0)
#define WM_REG_MPLS_DEV_MODE WM_EXT_REG_ADDR(MOTION_PLUS, 0xfe)
#define WM_REG_MPLS_ID_BYTE WM_EXT_REG_ADDR(MOTION_PLUS, 0xff)
// IR camera register addresses
#define WM_REG_DPD_CONFIG_BLOCK_1 WM_EXT_REG_ADDR(DPD, 0x00)
#define WM_REG_DPD_CONFIG_BLOCK_2 WM_EXT_REG_ADDR(DPD, 0x1a)
#define WM_REG_DPD_30 WM_EXT_REG_ADDR(DPD, 0x30)
#define WM_REG_DPD_DATA_FORMAT WM_EXT_REG_ADDR(DPD, 0x33)
#define WPAD_NZFILTER_ACC 0
#define WPAD_NZFILTER_DPD 1
#define WPAD_NZFILTER_EXT 2
#define WPAD_NZFILTER_MPLS 3
#define WPAD_MAX_NZFILTERS 4
#define WPAD_RADIO_QUALITY_GOOD 0 // 80+
#define WPAD_RADIO_QUALITY_BAD 1 // 80-
#define WPAD_DEV_CORE 0
#define WPAD_DEV_FS 1
#define WPAD_DEV_CLASSIC 2
#define WPAD_DEV_BALANCE_CHECKER 3
#define WPAD_DEV_VSM 4
#define WPAD_DEV_MOTION_PLUS 5
#define WPAD_DEV_MPLS_PT_FS 6
#define WPAD_DEV_MPLS_PT_CLASSIC 7
#define WPAD_DEV_TRAIN 16
#define WPAD_DEV_GUITAR 17
#define WPAD_DEV_DRUM 18
#define WPAD_DEV_TAIKO 19
#define WPAD_DEV_TURNTABLE 20
// seems to be like maybe general purpose non-specific device types
// maybe this was for testing or something? idk
#define WPAD_DEV_BULK_1 21
#define WPAD_DEV_BULK_2 22
#define WPAD_DEV_BULK_3 23
#define WPAD_DEV_BULK_4 24
#define WPAD_DEV_BULK_5 25
#define WPAD_DEV_BULK_6 26
#define WPAD_DEV_BULK_7 27
#define WPAD_DEV_BULK_8 28
#define WPAD_DEV_MPLS_PT_UNKNOWN 250
#define WPAD_DEV_251 251
#define WPAD_DEV_252 252 // invalid device mode?
#define WPAD_DEV_NONE 253 // sort of like WPAD_ENODEV (see __wpadAbortInitExtension in WPADHIDParser.c)
#define WPAD_DEV_INITIALIZING 255 // see __a1_20_status_report
struct WPADCmd {
/* 0x00 */ u32 reportID;
/* 0x04 */ u8 dataBuf[RPT_MAX_SIZE];
/* 0x1a */ u16 dataLength;
/* 0x1c */ void* dstBuf;
/* 0x20 */ u16 readLength;
/* 0x24 */ u32 readAddress;
/* 0x28 */ WPADInfo* statusReportOut;
/* 0x2c */ WPADCallback* cmdCB;
}; // size 0x30
struct WPADCmdQueue {
/* 0x00 */ s8 indexOut;
/* 0x01 */ s8 indexIn;
/* 0x04 */ struct WPADCmd* queue;
/* 0x08 */ u32 length;
}; // size 0x0c
struct WPADDevConfig {
/* 0x00 */ DPDObject dpd[WPAD_MAX_DPD_OBJECTS];
/* 0x20 */ s16 accX0g;
/* 0x22 */ s16 accY0g;
/* 0x24 */ s16 accZ0g;
/* 0x26 */ s16 accX1g;
/* 0x28 */ s16 accY1g;
/* 0x2a */ s16 accZ1g;
/* 0x2c */ u8 motor;
/* 0x2d */ u8 volume;
/* 0x30 */ u8 pad0_[2];
};
typedef struct WPADMplsCalibration {
/* 0x00 */ f32 pitchZero;
/* 0x04 */ f32 pitchScale;
/* 0x08 */ f32 yawZero;
/* 0x0c */ f32 yawScale;
/* 0x10 */ f32 rollZero;
/* 0x14 */ f32 rollScale;
/* 0x18 */ s32 degrees;
} WPADMplsCalibration;
struct WPADExtConfig {
union {
struct WPADFSConfig {
/* 0x00 */ s16 stickXCenter;
/* 0x02 */ s16 at_0x02;
/* 0x04 */ s16 at_0x04;
/* 0x06 */ s16 stickYCenter;
/* 0x08 */ s16 at_0x08;
/* 0x0a */ s16 at_0x0a;
/* 0x0c */ s16 accX0g;
/* 0x0e */ s16 accY0g;
/* 0x10 */ s16 accZ0g;
/* 0x12 */ s16 accX1g;
/* 0x14 */ s16 accY1g;
/* 0x16 */ s16 accZ1g;
} fs; // size 0x1a
struct WPADCLConfig {
/* 0x00 */ s16 lStickXCenter;
/* 0x02 */ s16 at_0x02;
/* 0x04 */ s16 at_0x04;
/* 0x06 */ s16 lStickYCenter;
/* 0x08 */ s16 at_0x08;
/* 0x0a */ s16 at_0x0a;
/* 0x0c */ s16 rStickXCenter;
/* 0x0e */ s16 at_0x0e;
/* 0x10 */ s16 at_0x10;
/* 0x12 */ s16 rStickYCenter;
/* 0x14 */ s16 at_0x14;
/* 0x16 */ s16 at_0x16;
/* 0x18 */ u8 triggerLZero;
/* 0x19 */ u8 triggerRZero;
} cl; // size 0x1a
u8 forceUnionSize_[0x1c]; // alignment?
}; // size 0x1c
struct WPADMplsConfig {
/* 0x00 */ WPADMplsCalibration high;
/* 0x1c */ WPADMplsCalibration low;
/* 0x38 */ u32 calibCRC;
/* 0x3c */ u16 calibID;
} /* 0x1a */ mpls;
}; // size 0x5c
typedef struct WPADGameInfo {
/* 0x00 */ OSTime timestamp;
/* 0x08 */ u16 gameTitle[16 + 1];
/* 0x2a */ char gameCode[4];
/* 0x2e */ u8 gameType;
/* 0x2f */ u8 checksum;
u8 _pad0[8];
} WPADGameInfo; // size 0x38
struct WPADMemBlock {
/* 0x00 */ BOOL busy;
/* 0x04 */ u8 const* data;
/* 0x08 */ u16 len;
/* 0x0c */ u32 addr;
/* 0x10 */ WPADCallback* cb;
}; // size 0x14
typedef struct /* possibly untagged, like kpad */ {
/* 0x000 */ WPADGameInfo gameInfo;
/* 0x038 */ s32 at_0x038[2]; /* unknown */ // WPADResult[2]? see __wpadGetGameInfo
/* 0x040 */ u8 rxBufMain[RX_BUFFER_SIZE];
/* 0x0a0 */ u8 rxBufs[2][RX_BUFFER_SIZE];
/* 0x160 */ struct WPADCmdQueue stdCmdQueue;
/* 0x16c */ struct WPADCmd stdCmdQueueList[24];
/* 0x5ec */ struct WPADCmdQueue extCmdQueue;
/* 0x16c */ struct WPADCmd extCmdQueueList[12];
/* 0x838 */ WPADInfo info;
/* 0x850 */ WPADInfo* infoOut;
/* 0x854 */ struct WPADDevConfig devConfig;
/* 0x884 */ struct WPADExtConfig extConfig;
/* 0x8e0 */ WPADCallback* cmdBlkCB;
/* 0x8e4 */ WPADExtensionCallback* extensionCB;
/* 0x8e8 */ WPADConnectCallback* connectCB;
/* 0x8ec */ WPADSamplingCallback* samplingCB;
/* 0x8f0 */ void* samplingBuf;
/* 0x8f4 */ u32 samplingBufIndex;
/* 0x8f8 */ u32 samplingBufSize;
/* 0x8fc */ u32 dataFormat;
/* 0x900 */ s32 status;
/* 0x904 */ u8 statusReqBusy;
/* 0x905 */ u8 devType;
/* 0x906 */ u8 devMode;
/* 0x907 */ s8 devHandle;
/* 0x908 */ int at_0x908; /* unknown */
/* 0x90c */ u8 rxBufIndex;
/* 0x90d */ s8 at_0x90d; /* unknown */
/* 0x90e */ u8 defaultDpdSize; // maybe?
/* 0x90f */ u8 currentDpdCommand;
/* 0x910 */ u8 pendingDpdCommand;
/* 0x911 */ u8 radioQuality;
/* 0x912 */ u8 radioQualityOkMs; // see __wpadCalcRadioQuality
/* 0x913 */ u8 audioFrames;
/* 0x914 */ u32 motorBusy;
/* 0x918 */ BOOL motorRunning;
/* 0x91c */ BOOL used;
/* 0x920 */ BOOL handshakeFinished;
/* 0x924 */ int configIndex;
/* 0x928 */ OSThreadQueue threadQueue; /* purpose unknown */
/* 0x930 */ WPADCallback* vsmCallback;
/* 0x934 */ u8 controlMplsBusy;
/* 0x935 */ u8 mplsCBReadBuf[2];
/* 0x937 */ u8 mplsCBCounter; // idk???
/* 0x938 */ u8 pendingMplsCommand;
/* 0x939 */ u8 noParseMplsCount;
/* 0x93a */ u8 isInitingMpls; // maybe?
/* 0x93b */ u8 hasReadExtType2; // maybe?
/* 0x93c */ u8 at_0x93c; /* unknown */
/* 0x93d */ u8 parseMPState;
/* 0x93e */ u8 wmParamOffset;
/* 0x93f */ u8 certWorkCounter; // idk???
/* 0x940 */ u16 certWorkMs;
/* 0x942 */ s16 certStateWorkMs;
/* 0x944 */ s8 certChallengeRandomBit;
/* 0x945 */ u8 certWorkBusy;
/* 0x946 */ s8 certValidityStatus;
/* 0x947 */ s8 certState;
/* 0x948 */ u32* certParamPtr;
/* 0x94c */ u32 certLintX[1 + 16 + 1];
/* 0x994 */ u32 certLintY[1 + 16 + 1];
/* 0x994 */ u32 certLintBig[LINT_NUM_MAX_BUFSIZ];
/* 0xae4 */ int at_0xae4; /* unknown */
/* 0xae8 */ OSTime lastControllerDataUpdate;
/* 0xaf0 */ u16 filterDiff[WPAD_MAX_NZFILTERS];
/* 0xaf8 */ u16 filterSame[WPAD_MAX_NZFILTERS];
/* 0xb00 */ OSTime lastReportSendTime;
/* 0xb08 */ u8 at_0xb08; /* unknown */
/* 0xb09 */ u8 calibrated;
/* 0xb0a */ u16 recalibHoldMs;
/* 0xb0c */ u8 encryptionKey[16];
/* 0xb1c */ u8 decryptAddTable[8];
/* 0xb24 */ u8 decryptXorTable[8];
/* 0xb2c */ u8 wmReadDataBuf[64];
/* 0xb6c */ u8* wmReadDataPtr;
/* 0xb70 */ u32 wmReadAddress;
/* 0xb74 */ int wmReadHadError;
/* 0xb78 */ u16 wmReadLength;
/* 0xb7a */ s8 at_0xb7a; /* unknown */
/* 0xb7b */ u8 radioSensitivity;
/* 0xb7c */ u16 copyOutCount;
/* 0xb7e */ u8 sleeping;
/* 0xb7f */ u8 lastReportID;
/* 0xb80 */ WPADCallback* getInfoCB;
/* 0xb84 */ u8 getInfoBusy;
/* 0xb85 */ u8 extState;
/* 0xb86 */ u8 savePower;
/* 0xb87 */ u8 blcBattery;
/* 0xb88 */ u8 savedDevType; // maybe?
/* 0xb89 */ u8 extWasDisconnected;
/* 0xb8a */ s16 reconnectExtMs;
/* 0xb8c */ struct WPADMemBlock memBlock;
/* 0xba0 */ WPADCallback* controlMplsCB;
/* 0xba4 */ u8 parseMPBuf;
/* 0xba5 */ u8 certProbeByte;
/* 0xba6 */ u8 dpdBusy;
/* 0xba7 */ u8 interleaveFlags;
/* 0xba8 */ u32 mplsCBReadAddress;
/* 0xbac */ u8 mplsCBState;
/* 0xbad */ u8 mplsUptimeMs;
/* 0xbae */ s8 certMayVerifyByCalibBlock;
u8 pad0_[2]; /* unknown (can't be alignment) */
/* 0xbb1 */ u8 certProbeStartingValue;
/* 0xbb2 */ u16 lastMplsCalibID;
/* 0xbb4 */ u32 lastMplsCalibCRC;
/* 0xbb8 */ u8 noParseExtCount;
/* 0xbb9 */ s8 extErr;
/* 0xbba */ u8 extDataLength;
/* 0xbbb */ u8 extDevType;
/* 0xbbc */ u8 currPwmDuty;
/* 0xbbd */ u8 pendingPwmDuty;
u8 pad1_[2]; /* unknown (can't be alignment) */
/* 0xbc0 */ u8 extDataBuf[32];
} ATTRIBUTE_ALIGN(32) wpad_cb_st; // size 0xbe0
BOOL WPADiIsAvailableCmdQueue(struct WPADCmdQueue* cmdQueue, s8 num);
BOOL WPADiSendWriteDataCmd(struct WPADCmdQueue* cmdQueue, u8 cmd, u32 address, WPADCallback* cb);
BOOL WPADiSendWriteData(struct WPADCmdQueue* cmdQueue, void const* p_buf, u16 len, u32 address, WPADCallback* cb);
BOOL WPADiSendStreamData(struct WPADCmdQueue* cmdQueue, void const* p_buf, u16 len);
BOOL WPADiSendMuteSpeaker(struct WPADCmdQueue* cmdQueue, BOOL muted, WPADCallback* cb);
BOOL WPADiSendEnableSpeaker(struct WPADCmdQueue* cmdQueue, BOOL enabled, WPADCallback* cb);
BOOL WPADiSendGetContStat(struct WPADCmdQueue* cmdQueue, WPADInfo* infoOut, WPADCallback* cb);
#ifdef __cplusplus
}
#endif
#endif // _REVOLUTION_WPAD_PRIVATE_H_
+79
View File
@@ -0,0 +1,79 @@
#ifndef _REVOLUTION_WUD_PRIVATE_H_
#define _REVOLUTION_WUD_PRIVATE_H_
#include <revolution/os.h>
#include <revolution/wpad/bte.h>
#include <revolution/wpad/wud.h>
#ifdef __cplusplus
extern "C" {
#endif
#define WUD_MAX_DEV_ENTRY_FOR_STD 10
#define WUD_MAX_DEV_ENTRY_FOR_SMP 6
#define WUD_MAX_DEV_ENTRY 16
#define WUD_DEV_HANDLE_INVALID (-1)
struct WUDDevInfoList {
/* 0x00 */ WUDDevInfo* devInfo;
/* 0x04 */ struct WUDDevInfoList* prev;
/* 0x08 */ struct WUDDevInfoList* next;
}; // size 0x0c
typedef struct /* possibly untagged, like kpad */ {
/* 0x000 */ WUDSyncDeviceCallback* syncStdCB;
/* 0x004 */ WUDSyncDeviceCallback* syncSmpCB;
/* 0x008 */ WUDClearDeviceCallback* clearDevCB;
/* 0x00c */ u8 syncState;
/* 0x00d */ u8 deleteState;
/* 0x00e */ u8 linkKeyState;
/* 0x00f */ u8 stackState;
/* 0x010 */ u8 initState;
/* 0x011 */ u8 shutdownState;
/* 0x012 */ u8 devNums;
/* 0x013 */ u8 devSmpNums;
/* 0x014 */ struct WUDDevInfoList* smpListHead;
/* 0x018 */ struct WUDDevInfoList* smpListTail;
/* 0x01c */ struct WUDDevInfoList smpList[WUD_MAX_DEV_ENTRY_FOR_SMP];
/* 0x064 */ struct WUDDevInfoList* stdListHead;
/* 0x068 */ struct WUDDevInfoList* stdListTail;
/* 0x06c */ struct WUDDevInfoList stdList[WUD_MAX_DEV_ENTRY_FOR_STD];
/* 0x0e4 */ WUDDevInfo stdDevs[WUD_MAX_DEV_ENTRY_FOR_STD];
/* 0x4a4 */ WUDDevInfo smpDevs[WUD_MAX_DEV_ENTRY_FOR_SMP];
/* 0x6e4 */ u8 connectedNum;
/* 0x6e5 */ u8 linkedNum;
/* 0x6e6 */ u8 syncedNum;
/* 0x6e7 */ u8 syncSkipChecks;
/* 0x6e8 */ s8 syncLoopNum;
/* 0x6e9 */ u8 syncType;
/* 0x6ea */ u8 connectable;
/* 0x6eb */ u8 discoverable;
/* 0x6ec */ WUDHidReceiveCallback* hidRecvCB;
/* 0x6f0 */ WUDHidConnectCallback* hidConnCB;
/* 0x6f4 */ WUDAllocFunc* allocFunc;
/* 0x6f8 */ WUDFreeFunc* freeFunc;
/* 0x6fc */ BD_ADDR pairAddr;
/* 0x702 */ BD_ADDR hostAddr;
/* 0x708 */ s8 libStatus;
/* 0x709 */ u8 siPortStatus;
/* 0x70a */ u8 pmID;
/* 0x70b */ s8 syncRssi;
/* 0x710 */ OSAlarm alarm;
/* 0x740 */ u32 hhFlags; // some flags maybe?
/* 0x744 */ u16 bufferStatus0;
/* 0x746 */ u16 bufferStatus1;
/* 0x748 */ s8 initWaitDeviceUpFrames;
/* 0x749 */ s8 waitStartSearchFrames;
/* 0x74a */ s16 waitIncomingFrames;
} wud_cb_st; // size 0x750
u16 WUDiGetQueueSizeForHandle(u8 dev_handle);
u16 WUDiGetNotAckNumForHandle(u8 dev_handle);
#ifdef __cplusplus
}
#endif
#endif // _REVOLUTION_WUD_PRIVATE_H_