mirror of https://github.com/zeldaret/tp.git
368 lines
11 KiB
C
368 lines
11 KiB
C
#include "dolphin/gx/GXFifo.h"
|
|
#include "dolphin/gx.h"
|
|
#include "dolphin/os.h"
|
|
|
|
static void GXInitFifoLimits(GXFifoObj* fifo, u32 hi_watermark, u32 lo_watermark);
|
|
|
|
/* 80451948-8045194C 000E48 0004+00 4/3 0/0 0/0 .sbss CPUFifo */
|
|
static GXFifoObj* CPUFifo;
|
|
|
|
/* 8045194C-80451950 000E4C 0004+00 4/3 0/0 0/0 .sbss GPFifo */
|
|
static GXFifoObj* GPFifo;
|
|
|
|
/* 80451950-80451954 000E50 0004+00 4/3 0/0 0/0 .sbss __GXCurrentThread */
|
|
static OSThread* __GXCurrentThread;
|
|
|
|
/* 80451954-80451958 000E54 0004+00 3/3 0/0 0/0 .sbss None */
|
|
static GXBool data_80451954;
|
|
|
|
/* 80451958-8045195C 000E58 0004+00 2/2 0/0 0/0 .sbss GXOverflowSuspendInProgress */
|
|
static u32 GXOverflowSuspendInProgress;
|
|
|
|
/* 8045195C-80451960 000E5C 0004+00 2/2 0/0 0/0 .sbss BreakPointCB */
|
|
static GXBreakPtCallback BreakPointCB;
|
|
|
|
/* 80451960-80451968 000E60 0004+04 1/1 0/0 0/0 .sbss __GXOverflowCount */
|
|
static u32 __GXOverflowCount;
|
|
|
|
static void GXOverflowHandler() {
|
|
__GXOverflowCount += 1;
|
|
__GXWriteFifoIntEnable(0, 1);
|
|
__GXWriteFifoIntReset(1, 0);
|
|
GXOverflowSuspendInProgress = TRUE;
|
|
OSSuspendThread(__GXCurrentThread);
|
|
}
|
|
|
|
static void GXUnderflowHandler() {
|
|
OSResumeThread(__GXCurrentThread);
|
|
GXOverflowSuspendInProgress = FALSE;
|
|
__GXWriteFifoIntReset(1, 1);
|
|
__GXWriteFifoIntEnable(1, 0);
|
|
}
|
|
|
|
static void GXBreakPointHandler(OSContext* context) {
|
|
OSContext bpContext;
|
|
|
|
FAST_FLAG_SET(__GXData->cpEnable, 0, 5, 1);
|
|
GX_SET_CP_REG(1, __GXData->cpEnable);
|
|
|
|
if (BreakPointCB) {
|
|
OSClearContext(&bpContext);
|
|
OSSetCurrentContext(&bpContext);
|
|
BreakPointCB();
|
|
OSClearContext(&bpContext);
|
|
OSSetCurrentContext(context);
|
|
}
|
|
}
|
|
|
|
/* 8035A5A8-8035A6DC 354EE8 0134+00 1/1 0/0 0/0 .text GXCPInterruptHandler */
|
|
static void GXCPInterruptHandler(s16 p1, OSContext* context) {
|
|
__GXData->cpStatus = GX_GET_CP_REG(0);
|
|
|
|
if ((__GXData->cpEnable >> 3 & 1) && (__GXData->cpStatus >> 1 & 1)) {
|
|
GXUnderflowHandler();
|
|
}
|
|
|
|
if ((__GXData->cpEnable >> 2 & 1) && (__GXData->cpStatus >> 0 & 1)) {
|
|
GXOverflowHandler();
|
|
}
|
|
|
|
if ((__GXData->cpEnable >> 5 & 1) && (__GXData->cpStatus >> 4 & 1)) {
|
|
GXBreakPointHandler(context);
|
|
}
|
|
}
|
|
|
|
/* 8035A6DC-8035A748 35501C 006C+00 0/0 2/2 0/0 .text GXInitFifoBase */
|
|
void GXInitFifoBase(GXFifoObj* fifo, void* base, u32 size) {
|
|
fifo->base = base;
|
|
fifo->end = (void*)((u32)base + size - 4);
|
|
fifo->size = size;
|
|
fifo->rw_dst = 0;
|
|
GXInitFifoLimits(fifo, size - 0x4000, OSRoundDown32B(size / 2));
|
|
GXInitFifoPtrs(fifo, base, base);
|
|
}
|
|
|
|
/* 8035A748-8035A7B8 355088 0070+00 1/1 1/1 0/0 .text GXInitFifoPtrs */
|
|
void GXInitFifoPtrs(GXFifoObj* fifo, void* readPtr, void* writePtr) {
|
|
int interrupts = OSDisableInterrupts();
|
|
fifo->read_ptr = readPtr;
|
|
fifo->write_ptr = writePtr;
|
|
fifo->rw_dst = (u32)writePtr - (u32)readPtr;
|
|
if (fifo->rw_dst < 0) {
|
|
fifo->rw_dst += fifo->size;
|
|
}
|
|
OSRestoreInterrupts(interrupts);
|
|
}
|
|
|
|
/* 8035A7B8-8035A7C4 3550F8 000C+00 1/1 0/0 0/0 .text GXInitFifoLimits */
|
|
static void GXInitFifoLimits(GXFifoObj* fifo, u32 hi_watermark, u32 lo_watermark) {
|
|
fifo->high_wtrmark = hi_watermark;
|
|
fifo->low_wtrmark = lo_watermark;
|
|
}
|
|
|
|
/* 8035A7C4-8035A8EC 355104 0128+00 1/1 1/1 0/0 .text GXSetCPUFifo */
|
|
void GXSetCPUFifo(GXFifoObj* fifo) {
|
|
BOOL interrupts;
|
|
interrupts = OSDisableInterrupts();
|
|
|
|
CPUFifo = fifo;
|
|
|
|
if (fifo == GPFifo) {
|
|
u32 reg;
|
|
GX_SET_PI_REG(3, (u32)fifo->base & 0x3FFFFFFF);
|
|
GX_SET_PI_REG(4, (u32)fifo->end & 0x3FFFFFFF);
|
|
reg = 0;
|
|
GX_BITFIELD_SET(reg, 6, 21, (u32)fifo->write_ptr >> 5);
|
|
GX_BITFIELD_SET(reg, 5, 1, 0);
|
|
GX_SET_PI_REG(5, reg);
|
|
|
|
data_80451954 = GX_TRUE;
|
|
|
|
__GXWriteFifoIntReset(1, 1);
|
|
__GXWriteFifoIntEnable(1, 0);
|
|
__GXFifoLink(1);
|
|
} else {
|
|
u32 reg;
|
|
if (data_80451954) {
|
|
__GXFifoLink(0);
|
|
data_80451954 = GX_FALSE;
|
|
}
|
|
__GXWriteFifoIntEnable(0, 0);
|
|
|
|
GX_SET_PI_REG(3, (u32)fifo->base & 0x3FFFFFFF);
|
|
GX_SET_PI_REG(4, (u32)fifo->end & 0x3FFFFFFF);
|
|
reg = 0;
|
|
GX_BITFIELD_SET(reg, 6, 21, (u32)fifo->write_ptr >> 5);
|
|
GX_BITFIELD_SET(reg, 5, 1, 0);
|
|
GX_SET_PI_REG(5, reg);
|
|
}
|
|
|
|
PPCSync();
|
|
|
|
OSRestoreInterrupts(interrupts);
|
|
}
|
|
|
|
/* 8035A8EC-8035AA8C 35522C 01A0+00 1/1 1/1 0/0 .text GXSetGPFifo */
|
|
void GXSetGPFifo(GXFifoObj* fifo) {
|
|
int interrupts = OSDisableInterrupts();
|
|
u32 reg;
|
|
__GXFifoReadDisable();
|
|
__GXWriteFifoIntEnable(0, 0);
|
|
GPFifo = fifo;
|
|
GX_SET_CP_REG(16, (u16)fifo->base);
|
|
GX_SET_CP_REG(18, (u16)fifo->end);
|
|
GX_SET_CP_REG(24, (u16)fifo->rw_dst);
|
|
GX_SET_CP_REG(26, (u16)fifo->write_ptr);
|
|
GX_SET_CP_REG(28, (u16)fifo->read_ptr);
|
|
GX_SET_CP_REG(20, (u16)fifo->high_wtrmark);
|
|
GX_SET_CP_REG(22, (u16)fifo->low_wtrmark);
|
|
|
|
GX_SET_CP_REG(17, ((u32)fifo->base & 0x3FFFFFFF) >> 16);
|
|
GX_SET_CP_REG(19, ((u32)fifo->end & 0x3FFFFFFF) >> 16);
|
|
GX_SET_CP_REG(25, (fifo->rw_dst) >> 16);
|
|
GX_SET_CP_REG(27, ((u32)fifo->write_ptr & 0x3FFFFFFF) >> 16);
|
|
GX_SET_CP_REG(29, ((u32)fifo->read_ptr & 0x3FFFFFFF) >> 16);
|
|
GX_SET_CP_REG(21, (fifo->high_wtrmark) >> 16);
|
|
GX_SET_CP_REG(23, (fifo->low_wtrmark) >> 16);
|
|
|
|
PPCSync();
|
|
|
|
if (CPUFifo == GPFifo) {
|
|
data_80451954 = 1;
|
|
__GXWriteFifoIntEnable(1, 0);
|
|
__GXFifoLink(1);
|
|
} else {
|
|
data_80451954 = 0;
|
|
__GXWriteFifoIntEnable(0, 0);
|
|
__GXFifoLink(0);
|
|
}
|
|
reg = __GXData->cpEnable;
|
|
GX_BITFIELD_SET(reg, 0x1e, 1, 0);
|
|
GX_BITFIELD_SET(reg, 0x1a, 1, 0);
|
|
GX_SET_CP_REG(1, reg);
|
|
GX_SET_CP_REG(1, __GXData->cpEnable);
|
|
__GXWriteFifoIntReset(1, 1);
|
|
__GXFifoReadEnable();
|
|
OSRestoreInterrupts(interrupts);
|
|
}
|
|
|
|
/* 8035AA8C-8035AAC0 3553CC 0034+00 0/0 1/1 0/0 .text GXSaveCPUFifo */
|
|
void GXSaveCPUFifo(GXFifoObj* fifo) {
|
|
GXFlush();
|
|
__GXSaveCPUFifoAux(fifo);
|
|
}
|
|
|
|
/* 8035AAC0-8035AB88 355400 00C8+00 1/1 0/0 0/0 .text __GXSaveCPUFifoAux */
|
|
void __GXSaveCPUFifoAux(GXFifoObj* fifo) {
|
|
int interrupts = OSDisableInterrupts();
|
|
fifo->base = OSPhysicalToCached(GX_GET_PI_REG(3));
|
|
fifo->end = OSPhysicalToCached(GX_GET_PI_REG(4));
|
|
fifo->write_ptr = OSPhysicalToCached(GX_GET_PI_REG(5) & ~0x4000000);
|
|
if (data_80451954 != 0) {
|
|
u32 reg2 = GX_GET_CP_REG(28) | (GX_GET_CP_REG(29) << 16);
|
|
fifo->read_ptr = (void*)(reg2 + -0x80000000);
|
|
fifo->rw_dst = (((u32)GX_GET_CP_REG(24) | (GX_GET_CP_REG(25) << 16)));
|
|
} else {
|
|
fifo->rw_dst = (u32)fifo->write_ptr - (u32)fifo->read_ptr;
|
|
if (fifo->rw_dst < 0) {
|
|
fifo->rw_dst += fifo->size;
|
|
}
|
|
}
|
|
OSRestoreInterrupts(interrupts);
|
|
}
|
|
|
|
/* 8035AB88-8035ABD8 3554C8 0050+00 0/0 2/2 0/0 .text GXGetGPStatus */
|
|
void GXGetGPStatus(GXBool* overhi, GXBool* underlow, GXBool* readIdle, GXBool* cmdIdle,
|
|
GXBool* brkpt) {
|
|
__GXData->cpStatus = GX_GET_CP_REG(0);
|
|
*overhi = __GXData->cpStatus & 1;
|
|
*underlow = (__GXData->cpStatus >> 1) & 1;
|
|
*readIdle = (__GXData->cpStatus >> 2) & 1;
|
|
*cmdIdle = (__GXData->cpStatus >> 3) & 1;
|
|
*brkpt = (__GXData->cpStatus >> 4) & 1;
|
|
}
|
|
|
|
/* 8035ABD8-8035ABE0 355518 0008+00 0/0 1/1 0/0 .text GXGetFifoBase */
|
|
void* GXGetFifoBase(GXFifoObj* fifo) {
|
|
return fifo->base;
|
|
}
|
|
|
|
/* 8035ABE0-8035ABE8 355520 0008+00 0/0 1/1 0/0 .text GXGetFifoSize */
|
|
u32 GXGetFifoSize(GXFifoObj* fifo) {
|
|
return fifo->size;
|
|
}
|
|
|
|
/* 8035ABE8-8035AC2C 355528 0044+00 0/0 1/1 0/0 .text GXSetBreakPtCallback */
|
|
GXBreakPtCallback GXSetBreakPtCallback(GXBreakPtCallback cb) {
|
|
GXBreakPtCallback oldCallback = BreakPointCB;
|
|
int interrupts = OSDisableInterrupts();
|
|
BreakPointCB = cb;
|
|
OSRestoreInterrupts(interrupts);
|
|
return oldCallback;
|
|
}
|
|
|
|
/* 8035AC2C-8035AC78 35556C 004C+00 0/0 1/1 0/0 .text __GXFifoInit */
|
|
void __GXFifoInit(void) {
|
|
__OSSetInterruptHandler(0x11, GXCPInterruptHandler);
|
|
__OSUnmaskInterrupts(0x4000);
|
|
__GXCurrentThread = OSGetCurrentThread();
|
|
GXOverflowSuspendInProgress = 0;
|
|
CPUFifo = NULL;
|
|
GPFifo = NULL;
|
|
}
|
|
|
|
/* 8035AC78-8035AC9C 3555B8 0024+00 1/1 0/0 0/0 .text __GXFifoReadEnable */
|
|
void __GXFifoReadEnable(void) {
|
|
FAST_FLAG_SET(__GXData->cpEnable, 1, 0, 1);
|
|
GX_SET_CP_REG(1, __GXData->cpEnable);
|
|
}
|
|
|
|
/* 8035AC9C-8035ACC0 3555DC 0024+00 1/1 0/0 0/0 .text __GXFifoReadDisable */
|
|
void __GXFifoReadDisable(void) {
|
|
FAST_FLAG_SET(__GXData->cpEnable, 0, 0, 1);
|
|
GX_SET_CP_REG(1, __GXData->cpEnable);
|
|
}
|
|
|
|
/* 8035ACC0-8035ACF4 355600 0034+00 2/2 0/0 0/0 .text __GXFifoLink */
|
|
void __GXFifoLink(u8 link) {
|
|
u32 b;
|
|
if (link) {
|
|
b = 1;
|
|
} else {
|
|
b = 0;
|
|
}
|
|
FAST_FLAG_SET(__GXData->cpEnable, b, 4, 1);
|
|
GX_SET_CP_REG(1, __GXData->cpEnable);
|
|
}
|
|
|
|
/* 8035ACF4-8035AD24 355634 0030+00 3/3 0/0 0/0 .text __GXWriteFifoIntEnable */
|
|
void __GXWriteFifoIntEnable(u32 p1, u32 p2) {
|
|
FAST_FLAG_SET(__GXData->cpEnable, p1, 2, 1);
|
|
FAST_FLAG_SET(__GXData->cpEnable, (u8)p2, 3, 1);
|
|
GX_SET_CP_REG(1, __GXData->cpEnable);
|
|
}
|
|
|
|
/* 8035AD24-8035AD54 355664 0030+00 3/3 0/0 0/0 .text __GXWriteFifoIntReset */
|
|
void __GXWriteFifoIntReset(u32 p1, u32 p2) {
|
|
FAST_FLAG_SET(__GXData->cpClr, p1, 0, 1);
|
|
FAST_FLAG_SET(__GXData->cpClr, (u8)p2, 1, 1);
|
|
GX_SET_CP_REG(2, __GXData->cpClr);
|
|
}
|
|
|
|
/* 8035AD54-8035AE54 355694 0100+00 0/0 1/1 0/0 .text __GXCleanGPFifo */
|
|
void __GXCleanGPFifo(void) {
|
|
BOOL interrupts;
|
|
GXFifoObj tempObj; // 0x14
|
|
u32 i, j, k; // stack alloc
|
|
GXFifoObj* gpFifo; // r31
|
|
GXFifoObj* cpuFifo; // r30
|
|
void* tempPtr; // r29
|
|
|
|
gpFifo = GXGetGPFifo();
|
|
if (!gpFifo) {
|
|
return;
|
|
}
|
|
|
|
cpuFifo = GXGetCPUFifo();
|
|
tempPtr = gpFifo->base;
|
|
|
|
tempObj = *gpFifo;
|
|
|
|
interrupts = OSDisableInterrupts();
|
|
|
|
tempObj.read_ptr = tempPtr;
|
|
tempObj.write_ptr = tempPtr;
|
|
tempObj.rw_dst = 0;
|
|
if (tempObj.rw_dst < 0) {
|
|
tempObj.rw_dst += tempObj.size;
|
|
}
|
|
|
|
OSRestoreInterrupts(interrupts);
|
|
|
|
GXSetGPFifo(&tempObj);
|
|
|
|
if (cpuFifo == gpFifo) {
|
|
GXSetCPUFifo(&tempObj);
|
|
}
|
|
|
|
interrupts = OSDisableInterrupts();
|
|
|
|
gpFifo->read_ptr = tempPtr;
|
|
gpFifo->write_ptr = tempPtr;
|
|
gpFifo->rw_dst = 0;
|
|
|
|
if (gpFifo->rw_dst < 0) {
|
|
gpFifo->rw_dst += gpFifo->size;
|
|
}
|
|
OSRestoreInterrupts(interrupts);
|
|
|
|
GXSetGPFifo(gpFifo);
|
|
if (cpuFifo == gpFifo) {
|
|
GXSetCPUFifo(cpuFifo);
|
|
}
|
|
}
|
|
|
|
/* 8035AE54-8035AEA0 355794 004C+00 0/0 1/1 0/0 .text GXSetCurrentGXThread */
|
|
OSThread* GXSetCurrentGXThread(void) {
|
|
BOOL interrupts = OSDisableInterrupts();
|
|
OSThread* prevThread = __GXCurrentThread;
|
|
__GXCurrentThread = OSGetCurrentThread();
|
|
OSRestoreInterrupts(interrupts);
|
|
return prevThread;
|
|
}
|
|
|
|
/* 8035AEA0-8035AEA8 -00001 0008+00 0/0 0/0 0/0 .text GXGetCurrentGXThread */
|
|
OSThread* GXGetCurrentGXThread(void) {
|
|
return *(OSThread**)(&__GXCurrentThread);
|
|
}
|
|
|
|
/* 8035AEA8-8035AEB0 -00001 0008+00 0/0 0/0 0/0 .text GXGetCPUFifo */
|
|
GXFifoObj* GXGetCPUFifo(void) {
|
|
return *(GXFifoObj**)(&CPUFifo);
|
|
}
|
|
|
|
/* 8035AEB0-8035AEB8 -00001 0008+00 0/0 0/0 0/0 .text GXGetGPFifo */
|
|
GXFifoObj* GXGetGPFifo(void) {
|
|
return GPFifo;
|
|
}
|