mirror of
https://github.com/zeldaret/oot.git
synced 2025-05-09 18:43:45 +00:00
110 lines
3.3 KiB
C
110 lines
3.3 KiB
C
#include "ultra64/internal.h"
|
|
#include "array_count.h"
|
|
#include "stack.h"
|
|
#include "ultra64.h"
|
|
|
|
#include "macros.h"
|
|
|
|
static OSThread viThread;
|
|
static STACK(viThreadStack, 0x1000);
|
|
static OSMesgQueue viEventQueue;
|
|
static OSMesg viEventBuf[5];
|
|
static OSIoMesg viRetraceMsg;
|
|
static OSIoMesg viCounterMsg;
|
|
OSDevMgr __osViDevMgr = { 0 };
|
|
u32 __additional_scanline = 0;
|
|
|
|
void viMgrMain(void*);
|
|
|
|
void osCreateViManager(OSPri pri) {
|
|
u32 prevInt;
|
|
OSPri newPri;
|
|
OSPri currentPri;
|
|
|
|
if (!__osViDevMgr.active) {
|
|
__osTimerServicesInit();
|
|
__additional_scanline = 0;
|
|
osCreateMesgQueue(&viEventQueue, viEventBuf, ARRAY_COUNT(viEventBuf));
|
|
viRetraceMsg.hdr.type = OS_MESG_TYPE_VRETRACE;
|
|
viRetraceMsg.hdr.pri = OS_MESG_PRI_NORMAL;
|
|
viRetraceMsg.hdr.retQueue = NULL;
|
|
viCounterMsg.hdr.type = OS_MESG_TYPE_COUNTER;
|
|
viCounterMsg.hdr.pri = OS_MESG_PRI_NORMAL;
|
|
viCounterMsg.hdr.retQueue = NULL;
|
|
osSetEventMesg(OS_EVENT_VI, &viEventQueue, &viRetraceMsg);
|
|
osSetEventMesg(OS_EVENT_COUNTER, &viEventQueue, &viCounterMsg);
|
|
newPri = -1;
|
|
currentPri = osGetThreadPri(NULL);
|
|
if (currentPri < pri) {
|
|
newPri = currentPri;
|
|
osSetThreadPri(NULL, pri);
|
|
}
|
|
|
|
prevInt = __osDisableInt();
|
|
__osViDevMgr.active = true;
|
|
__osViDevMgr.thread = &viThread;
|
|
__osViDevMgr.cmdQueue = &viEventQueue;
|
|
__osViDevMgr.evtQueue = &viEventQueue;
|
|
__osViDevMgr.acsQueue = NULL;
|
|
__osViDevMgr.dma = NULL;
|
|
__osViDevMgr.edma = NULL;
|
|
|
|
osCreateThread(&viThread, 0, &viMgrMain, &__osViDevMgr, STACK_TOP(viThreadStack), pri);
|
|
__osViInit();
|
|
osStartThread(&viThread);
|
|
__osRestoreInt(prevInt);
|
|
if (newPri != -1) {
|
|
osSetThreadPri(NULL, newPri);
|
|
}
|
|
}
|
|
}
|
|
|
|
void viMgrMain(void* arg) {
|
|
static u16 viRetrace;
|
|
OSDevMgr* dm;
|
|
u32 addTime;
|
|
OSIoMesg* mb = NULL;
|
|
u32 first = 0;
|
|
|
|
viRetrace = __osViGetCurrentContext()->retraceCount;
|
|
if (viRetrace == 0) {
|
|
viRetrace = 1;
|
|
}
|
|
|
|
dm = (OSDevMgr*)arg;
|
|
|
|
while (true) {
|
|
osRecvMesg(dm->evtQueue, (OSMesg*)&mb, OS_MESG_BLOCK);
|
|
switch (mb->hdr.type) {
|
|
case OS_MESG_TYPE_VRETRACE:
|
|
__osViSwapContext();
|
|
viRetrace--;
|
|
if (viRetrace == 0) {
|
|
OSViContext* ctx = __osViGetCurrentContext();
|
|
if (ctx->mq) {
|
|
osSendMesg(ctx->mq, ctx->msg, OS_MESG_NOBLOCK);
|
|
}
|
|
viRetrace = ctx->retraceCount;
|
|
}
|
|
|
|
__osViIntrCount++;
|
|
|
|
// block optimized out since first is always 0,
|
|
// but it changes register allocation and ordering for __osCurrentTime
|
|
if (first != 0) {
|
|
addTime = osGetCount();
|
|
__osCurrentTime = addTime;
|
|
first = 0;
|
|
}
|
|
|
|
addTime = __osBaseCounter;
|
|
__osBaseCounter = osGetCount();
|
|
addTime = __osBaseCounter - addTime;
|
|
__osCurrentTime = __osCurrentTime + addTime;
|
|
break;
|
|
case OS_MESG_TYPE_COUNTER:
|
|
__osTimerInterrupt();
|
|
break;
|
|
}
|
|
}
|
|
}
|