From 665353f3446db43d0efe0e9c6a9c80d16684da7a Mon Sep 17 00:00:00 2001 From: Derek Hensley Date: Sat, 20 Jan 2024 15:47:00 -0800 Subject: [PATCH] Irqmgr + scheduler Docs (#1527) * irqmgr docs * Sched_FlushTaskQueue * scheduler docs --- include/audiomgr.h | 4 +- include/functions.h | 38 --- include/irqmgr.h | 26 +- include/main.h | 2 +- include/scheduler.h | 65 +++-- spec | 2 +- src/boot/idle.c | 4 +- src/boot/irqmgr.c | 248 +++++++++++------- src/boot/z_std_dma.c | 2 +- src/code/audio_thread_manager.c | 6 +- src/code/code_8010C1B0.c | 20 -- src/code/graph.c | 12 +- src/code/main.c | 7 +- src/code/sched.c | 241 ++++++++++------- src/code/z_jpeg.c | 6 +- src/code/z_nulltask.c | 30 +++ src/code/z_play.c | 13 +- .../ovl_kaleido_scope/z_kaleido_scope_NES.c | 2 +- tools/disasm/files.txt | 2 +- tools/disasm/functions.txt | 26 +- tools/disasm/variables.txt | 2 +- tools/sizes/boot_functions.csv | 6 +- tools/sizes/code_functions.csv | 18 +- 23 files changed, 442 insertions(+), 340 deletions(-) delete mode 100644 src/code/code_8010C1B0.c create mode 100644 src/code/z_nulltask.c diff --git a/include/audiomgr.h b/include/audiomgr.h index 4bed0e095f..23a6ef7bfc 100644 --- a/include/audiomgr.h +++ b/include/audiomgr.h @@ -9,7 +9,7 @@ typedef struct { /* 0x000 */ IrqMgr* irqMgr; - /* 0x004 */ SchedContext* sched; + /* 0x004 */ Scheduler* sched; /* 0x008 */ OSScTask audioTask; /* 0x060 */ AudioTask* rspTask; /* 0x064 */ OSMesgQueue interruptQueue; @@ -24,6 +24,6 @@ typedef struct { void AudioMgr_StopAllSfxExceptSystem(void); void AudioMgr_Unlock(AudioMgr* audioMgr); -void AudioMgr_Init(AudioMgr* audioMgr, void* stack, OSPri pri, OSId id, SchedContext* sched, IrqMgr* irqMgr); +void AudioMgr_Init(AudioMgr* audioMgr, void* stack, OSPri pri, OSId id, Scheduler* sched, IrqMgr* irqMgr); #endif diff --git a/include/functions.h b/include/functions.h index 3d77f9ef0b..c8f2bd4190 100644 --- a/include/functions.h +++ b/include/functions.h @@ -3,20 +3,6 @@ #include "z64.h" -void IrqMgr_AddClient(IrqMgr* irqmgr, IrqMgrClient* client, OSMesgQueue* msgQueue); -void IrqMgr_RemoveClient(IrqMgr* irqmgr, IrqMgrClient* remove); -void IrqMgr_SendMesgForClient(IrqMgr* irqmgr, OSMesg msg); -void IrqMgr_JamMesgForClient(IrqMgr* irqmgr, OSMesg msg); -void IrqMgr_HandlePreNMI(IrqMgr* irqmgr); -void IrqMgr_CheckStack(void); -void IrqMgr_HandlePRENMI450(IrqMgr* irqmgr); -void IrqMgr_HandlePRENMI480(IrqMgr* irqmgr); -void IrqMgr_HandlePRENMI500(IrqMgr* irqmgr); -void IrqMgr_HandleRetrace(IrqMgr* irqmgr); -void IrqMgr_ThreadEntry(IrqMgr* irqmgr); -void IrqMgr_Init(IrqMgr* irqmgr, void* stack, OSPri pri, u8 retraceCount); - - // void EnItem00_SetObject(EnItem00* this, PlayState* play, f32* shadowOffset, f32* shadowScale); // void EnItem00_Init(Actor* thisx, PlayState* play); // void EnItem00_Destroy(Actor* thisx, PlayState* play); @@ -490,7 +476,6 @@ s32 func_8010BF58(Actor* actor, PlayState* play, void* param_3, UNK_PTR param_4, void Nmi_Init(void); void Nmi_SetPrenmiStart(void); // s32 Nmi_GetPrenmiHasStarted(void); -void MsgEvent_SendNullTask(void); f32 OLib_Vec3fDist(Vec3f* a, Vec3f* b); f32 OLib_Vec3fDistOutDiff(Vec3f* a, Vec3f* b, Vec3f* dest); f32 OLib_Vec3fDistXZ(Vec3f* a, Vec3f* b); @@ -614,29 +599,6 @@ Gfx* Graph_GfxPlusOne(Gfx* gfx); Gfx* Graph_BranchDlist(Gfx* gfx, Gfx* dst); void* Graph_DlistAlloc(Gfx** gfx, size_t size); -void Sched_SwapFramebuffer(CfbInfo* cfbInfo); -void Sched_RetraceUpdateFramebuffer(SchedContext* sched, CfbInfo* cfbInfo); -void Sched_HandleReset(SchedContext* sched); -void Sched_HandleStop(SchedContext* sched); -void Sched_HandleAudioCancel(SchedContext* sched); -void Sched_HandleGfxCancel(SchedContext* sched); -void Sched_QueueTask(SchedContext* sched, OSScTask* task); -void Sched_Yield(SchedContext* sched); -s32 Sched_Schedule(SchedContext* sched, OSScTask** spTask, OSScTask** dpTask, s32 state); -void Sched_TaskUpdateFramebuffer(SchedContext* sched, OSScTask* task); -void Sched_NotifyDone(SchedContext* sched, OSScTask* task); -void Sched_RunTask(SchedContext* sched, OSScTask* spTask, OSScTask* dpTask); -void Sched_HandleEntry(SchedContext* sched); -void Sched_HandleRetrace(SchedContext* sched); -void Sched_HandleRSPDone(SchedContext* sched); -void Sched_HandleRDPDone(SchedContext* sched); -void Sched_SendEntryMsg(SchedContext* sched); -void Sched_SendAudioCancelMsg(SchedContext* sched); -void Sched_SendGfxCancelMsg(SchedContext* sched); -void Sched_FaultClient(void* param1, void* param2); -void Sched_ThreadEntry(void* arg); -void Sched_Init(SchedContext* sched, void* stack, OSPri pri, u8 viModeType, UNK_TYPE arg4, IrqMgr* irqMgr); - void Mtx_SetTranslateScaleMtx(Mtx* mtx, f32 scaleX, f32 scaleY, f32 scaleZ, f32 translateX, f32 translateY, f32 translateZ); void Mtx_SetRotationMtx(Mtx* mtx, s32 angle, f32 axisX, f32 axisY, f32 axisZ); void Mtx_SetTranslationRotationScaleMtx(Mtx* mtx, f32 scaleX, f32 scaleY, f32 scaleZ, s32 angle, f32 axisX, f32 axisY, f32 axisZ,f32 translateX, f32 translateY, f32 translateZ); diff --git a/include/irqmgr.h b/include/irqmgr.h index 203281aabe..576f390bf5 100644 --- a/include/irqmgr.h +++ b/include/irqmgr.h @@ -4,23 +4,29 @@ #include "ultra64.h" #include "PR/sched.h" +typedef enum { + /* 0 */ IRQ_RESET_STATUS_IDLE, + /* 1 */ IRQ_RESET_STATUS_PRENMI, + /* 2 */ IRQ_RESET_STATUS_NMI +} IrqResetStatus; + typedef struct IrqMgrClient { /* 0x0 */ struct IrqMgrClient* next; /* 0x4 */ OSMesgQueue* queue; } IrqMgrClient; // size = 0x8 typedef struct { - /* 0x000 */ OSScMsg verticalRetraceMesg; + /* 0x000 */ OSScMsg retraceMsg; /* 0x020 */ OSScMsg prenmiMsg; /* 0x040 */ OSScMsg nmiMsg; - /* 0x060 */ OSMesgQueue irqQueue; - /* 0x078 */ OSMesg irqBuffer[8]; + /* 0x060 */ OSMesgQueue queue; + /* 0x078 */ OSMesg msgBuf[8]; /* 0x098 */ OSThread thread; - /* 0x248 */ IrqMgrClient* callbacks; - /* 0x24C */ u8 prenmiStage; - /* 0x250 */ OSTime lastPrenmiTime; - /* 0x258 */ OSTimer prenmiTimer; - /* 0x278 */ OSTime lastFrameTime; + /* 0x248 */ IrqMgrClient* clients; + /* 0x24C */ u8 resetStatus; + /* 0x250 */ OSTime resetTime; + /* 0x258 */ OSTimer timer; + /* 0x278 */ OSTime retraceTime; } IrqMgr; // size = 0x280 extern vs32 gIrqMgrResetStatus; @@ -28,4 +34,8 @@ extern volatile OSTime sIrqMgrResetTime; extern volatile OSTime gIrqMgrRetraceTime; extern s32 sIrqMgrRetraceCount; +void IrqMgr_AddClient(IrqMgr* irqMgr, IrqMgrClient* client, OSMesgQueue* msgQueue); +void IrqMgr_RemoveClient(IrqMgr* irqMgr, IrqMgrClient* client); +void IrqMgr_Init(IrqMgr* irqMgr, void* stack, OSPri pri, u8 retraceCount); + #endif diff --git a/include/main.h b/include/main.h index 796faece05..be32328e50 100644 --- a/include/main.h +++ b/include/main.h @@ -10,7 +10,7 @@ extern s32 gScreenHeight; extern size_t gSystemHeapSize; extern uintptr_t gSegments[NUM_SEGMENTS]; -extern SchedContext gSchedContext; +extern Scheduler gScheduler; extern OSThread gGraphThread; extern PadMgr gPadMgr; diff --git a/include/scheduler.h b/include/scheduler.h index 1aeae07ecb..f8ee9c9a67 100644 --- a/include/scheduler.h +++ b/include/scheduler.h @@ -7,41 +7,50 @@ #include "PR/sptask.h" #include "irqmgr.h" +#include "unk.h" + #define TASK_FRAMEBUFFER(task) ((CfbInfo*)(task)->framebuffer) typedef struct { - /* 0x00 */ u16* fb1; - /* 0x04 */ u16* swapBuffer; + /* 0x00 */ u16* framebuffer; // current framebuffer + /* 0x04 */ u16* swapBuffer; // framebuffer to swap to /* 0x08 */ OSViMode* viMode; - /* 0x0C */ u32 features; - /* 0x10 */ u8 unk_10; - /* 0x11 */ s8 updateRate; - /* 0x12 */ s8 updateRate2; - /* 0x13 */ u8 unk_13; - /* 0x14 */ f32 xScale; - /* 0x18 */ f32 yScale; + /* 0x0C */ u32 viFeatures; + /* 0x10 */ u8 unk_10; // set to 0, never read + /* 0x11 */ s8 updateRate; // how many VIs should elapse before next swap + /* 0x12 */ s8 updateTimer; // counts down (in VIs) from updateRate to 0, swaps the framebuffer at 0 + /* 0x14 */ f32 xScale; + /* 0x18 */ f32 yScale; } CfbInfo; // size = 0x1C typedef struct { - /* 0x000 */ OSMesgQueue interruptQ; - /* 0x018 */ OSMesg intBuf[64]; - /* 0x118 */ OSMesgQueue cmdQ; - /* 0x130 */ OSMesg cmdMsgBuf[8]; - /* 0x150 */ OSThread thread; - /* 0x300 */ OSScTask* audioListHead; - /* 0x304 */ OSScTask* gfxListHead; - /* 0x308 */ OSScTask* audioListTail; - /* 0x30C */ OSScTask* gfxListTail; - /* 0x310 */ OSScTask* curRSPTask; - /* 0x314 */ OSScTask* curRDPTask; - /* 0x318 */ s32 retraceCount; - /* 0x318 */ s32 doAudio; - /* 0x320 */ CfbInfo* curBuf; - /* 0x324 */ CfbInfo* pendingSwapBuf1; - /* 0x328 */ CfbInfo* pendingSwapBuf2; - /* 0x32C */ char unk_32C[0x3]; - /* 0x32F */ u8 shouldUpdateVi; + /* 0x000 */ OSMesgQueue interruptQueue; + /* 0x018 */ OSMesg interruptMsgBuf[64]; + /* 0x118 */ OSMesgQueue cmdQueue; + /* 0x130 */ OSMesg cmdMsgBuf[8]; + /* 0x150 */ OSThread thread; + /* 0x300 */ OSScTask* audioListHead; + /* 0x304 */ OSScTask* gfxListHead; + /* 0x308 */ OSScTask* audioListTail; + /* 0x30C */ OSScTask* gfxListTail; + /* 0x310 */ OSScTask* curRSPTask; + /* 0x314 */ OSScTask* curRDPTask; + /* 0x318 */ s32 retraceCount; + /* 0x318 */ s32 doAudio; + /* 0x320 */ CfbInfo* curBuf; // current framebuffer (taken from buffer 1) + /* 0x324 */ CfbInfo* pendingSwapBuf1; // buffer 1 (next buffer) + /* 0x328 */ CfbInfo* pendingSwapBuf2; // buffer 2 (always NULL) + /* 0x32C */ UNK_TYPE1 unk_32C[0x3]; + /* 0x32F */ u8 isFirstSwap; /* 0x330 */ IrqMgrClient irqClient; -} SchedContext; // size = 0x338 +} Scheduler; // size = 0x338 + +void Sched_FlushTaskQueue(void); + +void Sched_SendNotifyMsg(Scheduler* sched); +void Sched_SendAudioCancelMsg(Scheduler* sched); +void Sched_SendGfxCancelMsg(Scheduler* sched); + +void Sched_Init(Scheduler* sched, void* stack, OSPri pri, u8 viModeType, UNK_TYPE arg4, IrqMgr* irqMgr); #endif diff --git a/spec b/spec index 743c0700d3..5bded15b06 100644 --- a/spec +++ b/spec @@ -500,7 +500,7 @@ beginseg include "build/src/code/z_msgevent.o" include "build/data/code/z_msgevent.data.o" include "build/src/code/z_nmi_buff.o" - include "build/src/code/code_8010C1B0.o" + include "build/src/code/z_nulltask.o" include "build/src/code/z_olib.o" pad_text include "build/src/code/z_parameter.o" diff --git a/src/boot/idle.c b/src/boot/idle.c index de93241a77..7e96241c2c 100644 --- a/src/boot/idle.c +++ b/src/boot/idle.c @@ -2,9 +2,11 @@ #include "buffers.h" #include "irqmgr.h" #include "main.h" +#include "segment_symbols.h" #include "stack.h" #include "stackcheck.h" #include "viconfig.h" +#include "z64dma.h" #include "z64thread.h" // Variables are put before most headers as a hacky way to bypass bss reordering @@ -19,8 +21,6 @@ OSMesgQueue gPiMgrCmdQueue; OSViMode gViConfigMode; u8 gViConfigModeType; -#include "global.h" -#include "buffers.h" #include "idle.h" u8 D_80096B20 = 1; diff --git a/src/boot/irqmgr.c b/src/boot/irqmgr.c index 172eabec8e..4085e57b9b 100644 --- a/src/boot/irqmgr.c +++ b/src/boot/irqmgr.c @@ -1,47 +1,94 @@ -#include "global.h" +/** + * @file irqMgr.c + * + * This file implements a manager for forwarding three key system interrupt events to + * registered clients. + * Together with sched.c, these systems implement the libultra video and task scheduling + * model from the libultra "sched" module, with improved functionality in the handling of + * Pre-NMI related events. + * + * The interrupts the IRQ manager deals with are: + * - Vertical Retrace + * This event is sent to the IRQ manager by the OS VI manager which only supports + * the forwarding of VI events to a single message queue. The IRQ manager will + * forward these events to every registered client. Vertical retrace events are + * received when the Video Interface has reached the start of the vertical blanking + * interval, happening at approximately 60Hz on NTSC and 50Hz on PAL. Many threads + * sit idle until a vertical retrace event wakes them up, at which point they will + * perform their task and then return to idle to await the next retrace. + * + * - Pre-NMI + * This event is sent to the IRQ manager by the OS Interrupt Handler when the reset + * button on the N64 control deck is pressed. This event is forwarded to clients to + * inform them that a reset will occur in at least 0.5s / 500ms so they may begin any + * shutdown procedures. + * + * - NMI + * This event is sent at 450ms into the Pre-NMI phase, informing clients that the + * mandatory 0.5s of Pre-NMI is almost over and a reset may be imminent. This event + * is not to be confused with the hardware NMI interrupt signalled when the CPU is + * to fully reset, as by the time that interrupt is received there is no time left + * to do anything. + * + * @see sched.c + */ +#include "irqmgr.h" + +#include "libc/stdbool.h" +#include "macros.h" #include "stackcheck.h" #include "z64thread.h" -vs32 gIrqMgrResetStatus = 0; +vs32 gIrqMgrResetStatus = IRQ_RESET_STATUS_IDLE; volatile OSTime sIrqMgrResetTime = 0; volatile OSTime gIrqMgrRetraceTime = 0; s32 sIrqMgrRetraceCount = 0; -void IrqMgr_AddClient(IrqMgr* irqmgr, IrqMgrClient* client, OSMesgQueue* msgQueue) { - u32 saveMask; +// Internal messages +#define IRQ_RETRACE_MSG 666 +#define IRQ_PRENMI_MSG 669 +#define IRQ_PRENMI450_MSG 671 +#define IRQ_PRENMI480_MSG 672 +#define IRQ_PRENMI500_MSG 673 - saveMask = osSetIntMask(1); +/** + * Registers a client and an associated message queue with the IRQ manager. When an + * interrupt event is received by the IRQ manager, these clients will be notified of + * the event. + * + * @param irqMgr the IrqMgr instance to register with. + * @param client client to register. + * @param msgQueue message queue to send notifications of interrupts to, associated with the client. + */ +void IrqMgr_AddClient(IrqMgr* irqMgr, IrqMgrClient* client, OSMesgQueue* msgQueue) { + u32 saveMask = osSetIntMask(OS_IM_NONE); client->queue = msgQueue; - client->next = irqmgr->callbacks; - irqmgr->callbacks = client; + client->next = irqMgr->clients; + irqMgr->clients = client; osSetIntMask(saveMask); - if (irqmgr->prenmiStage > 0) { - osSendMesg(client->queue, &irqmgr->prenmiMsg.type, OS_MESG_NOBLOCK); + if (irqMgr->resetStatus >= IRQ_RESET_STATUS_PRENMI) { + osSendMesg(client->queue, (OSMesg)&irqMgr->prenmiMsg, OS_MESG_NOBLOCK); } - if (irqmgr->prenmiStage > 1) { - osSendMesg(client->queue, &irqmgr->nmiMsg.type, OS_MESG_NOBLOCK); + + if (irqMgr->resetStatus >= IRQ_RESET_STATUS_NMI) { + osSendMesg(client->queue, (OSMesg)&irqMgr->nmiMsg, OS_MESG_NOBLOCK); } } -void IrqMgr_RemoveClient(IrqMgr* irqmgr, IrqMgrClient* remove) { - IrqMgrClient* iter; - IrqMgrClient* last; - u32 saveMask; - - iter = irqmgr->callbacks; - last = NULL; - - saveMask = osSetIntMask(1); +void IrqMgr_RemoveClient(IrqMgr* irqMgr, IrqMgrClient* client) { + IrqMgrClient* iter = irqMgr->clients; + IrqMgrClient* last = NULL; + u32 saveMask = osSetIntMask(OS_IM_NONE); while (iter != NULL) { - if (iter == remove) { + if (iter == client) { if (last != NULL) { - last->next = remove->next; + last->next = client->next; } else { - irqmgr->callbacks = remove->next; + irqMgr->clients = client->next; } break; } @@ -52,119 +99,142 @@ void IrqMgr_RemoveClient(IrqMgr* irqmgr, IrqMgrClient* remove) { osSetIntMask(saveMask); } -void IrqMgr_SendMesgForClient(IrqMgr* irqmgr, OSMesg msg) { - IrqMgrClient* iter = irqmgr->callbacks; +/** + * Send `msg` to every registered client if the message queue is not full. The message is + * appended to the back of the queue. + */ +void IrqMgr_SendMesgToClients(IrqMgr* irqMgr, OSMesg msg) { + IrqMgrClient* client = irqMgr->clients; - while (iter != NULL) { - osSendMesg(iter->queue, msg, OS_MESG_NOBLOCK); - iter = iter->next; + while (client != NULL) { + osSendMesg(client->queue, msg, OS_MESG_NOBLOCK); + client = client->next; } } -void IrqMgr_JamMesgForClient(IrqMgr* irqmgr, OSMesg msg) { - IrqMgrClient* iter = irqmgr->callbacks; +/** + * Send `msg` to every registered client if the message queue is not full. This appears to be for + * high-priority messages that should be jammed to the front of the queue, however a bug prevents + * this from working in this way and the message is appended to the back of the queue as in + * `IrqMgr_SendMesgToClients`. + * + * @see IrqMgr_SendMesgToClients + */ +void IrqMgr_JamMesgToClients(IrqMgr* irqMgr, OSMesg msg) { + IrqMgrClient* client = irqMgr->clients; - while (iter != NULL) { - if (iter->queue->validCount < iter->queue->msgCount) { - osSendMesg(iter->queue, msg, OS_MESG_NOBLOCK); + while (client != NULL) { + if (!MQ_IS_FULL(client->queue)) { + //! @bug The function's name suggests this would use osJamMesg rather than osSendMesg, using the + //! latter makes this function no different than IrqMgr_SendMesgToClients. + osSendMesg(client->queue, msg, OS_MESG_NOBLOCK); } - iter = iter->next; + client = client->next; } } -void IrqMgr_HandlePreNMI(IrqMgr* irqmgr) { - gIrqMgrResetStatus = 1; - irqmgr->prenmiStage = 1; +/** + * Runs when the Pre-NMI OS Event is received. This indicates that the console will reset in at least + * 0.5s / 500ms. Updates the reset status and time before forwarding the Pre-NMI message to registered + * clients so they may begin shutting down in advance of the reset. + */ +void IrqMgr_HandlePreNMI(IrqMgr* irqMgr) { + gIrqMgrResetStatus = IRQ_RESET_STATUS_PRENMI; + irqMgr->resetStatus = IRQ_RESET_STATUS_PRENMI; - sIrqMgrResetTime = irqmgr->lastPrenmiTime = osGetTime(); + sIrqMgrResetTime = irqMgr->resetTime = osGetTime(); // Wait .45 seconds then generate a stage 2 prenmi interrupt - osSetTimer(&irqmgr->prenmiTimer, OS_USEC_TO_CYCLES(450000), 0, &irqmgr->irqQueue, (OSMesg)0x29F); + osSetTimer(&irqMgr->timer, OS_MSEC_TO_CYCLES(450), 0, &irqMgr->queue, (OSMesg)IRQ_PRENMI450_MSG); - IrqMgr_JamMesgForClient(irqmgr, &irqmgr->prenmiMsg.type); + IrqMgr_JamMesgToClients(irqMgr, (OSMesg)&irqMgr->prenmiMsg); } -void IrqMgr_CheckStack(void) { +void IrqMgr_CheckStacks(void) { StackCheck_Check(NULL); } -void IrqMgr_HandlePRENMI450(IrqMgr* irqmgr) { - gIrqMgrResetStatus = 2; - irqmgr->prenmiStage = 2; +void IrqMgr_HandlePRENMI450(IrqMgr* irqMgr) { + gIrqMgrResetStatus = IRQ_RESET_STATUS_NMI; + irqMgr->resetStatus = IRQ_RESET_STATUS_NMI; // Wait .03 seconds then generate a stage 3 prenmi interrupt - osSetTimer(&irqmgr->prenmiTimer, OS_USEC_TO_CYCLES(30000), 0, &irqmgr->irqQueue, (OSMesg)0x2A0); + osSetTimer(&irqMgr->timer, OS_MSEC_TO_CYCLES(30), 0, &irqMgr->queue, (OSMesg)IRQ_PRENMI480_MSG); - IrqMgr_SendMesgForClient(irqmgr, &irqmgr->nmiMsg.type); + IrqMgr_SendMesgToClients(irqMgr, (OSMesg)&irqMgr->nmiMsg); } -void IrqMgr_HandlePRENMI480(IrqMgr* irqmgr) { +void IrqMgr_HandlePRENMI480(IrqMgr* irqMgr) { // Wait .52 seconds. After this we will have waited an entire second - osSetTimer(&irqmgr->prenmiTimer, OS_USEC_TO_CYCLES(520000), 0, &irqmgr->irqQueue, (OSMesg)0x2A1); + osSetTimer(&irqMgr->timer, OS_MSEC_TO_CYCLES(520), 0, &irqMgr->queue, (OSMesg)IRQ_PRENMI500_MSG); osAfterPreNMI(); } -void IrqMgr_HandlePRENMI500(IrqMgr* irqmgr) { - IrqMgr_CheckStack(); +void IrqMgr_HandlePRENMI500(IrqMgr* irqMgr) { + IrqMgr_CheckStacks(); } -void IrqMgr_HandleRetrace(IrqMgr* irqmgr) { + +void IrqMgr_HandleRetrace(IrqMgr* irqMgr) { if (gIrqMgrRetraceTime == 0) { - if (irqmgr->lastFrameTime == 0) { - irqmgr->lastFrameTime = osGetTime(); + if (irqMgr->retraceTime == 0) { + irqMgr->retraceTime = osGetTime(); } else { - gIrqMgrRetraceTime = osGetTime() - irqmgr->lastFrameTime; + gIrqMgrRetraceTime = osGetTime() - irqMgr->retraceTime; } } - sIrqMgrRetraceCount += 1; - IrqMgr_SendMesgForClient(irqmgr, irqmgr); + sIrqMgrRetraceCount++; + IrqMgr_SendMesgToClients(irqMgr, (OSMesg)&irqMgr->retraceMsg); } -void IrqMgr_ThreadEntry(IrqMgr* irqmgr) { - u32 interrupt; - u32 stop; +void IrqMgr_ThreadEntry(void* arg) { + s32 msg = 0; + IrqMgr* irqMgr = (IrqMgr*)arg; + s32 exit = false; - interrupt = 0; - stop = 0; - while (stop == 0) { - if (stop) { - ; - } + while (!exit) { + osRecvMesg(&irqMgr->queue, (OSMesg*)&msg, OS_MESG_BLOCK); - osRecvMesg(&irqmgr->irqQueue, (OSMesg*)&interrupt, OS_MESG_BLOCK); - switch (interrupt) { - case 0x29A: - IrqMgr_HandleRetrace(irqmgr); + switch (msg) { + case IRQ_RETRACE_MSG: + IrqMgr_HandleRetrace(irqMgr); break; - case 0x29D: - IrqMgr_HandlePreNMI(irqmgr); + + case IRQ_PRENMI_MSG: + IrqMgr_HandlePreNMI(irqMgr); break; - case 0x29F: - IrqMgr_HandlePRENMI450(irqmgr); + + case IRQ_PRENMI450_MSG: + IrqMgr_HandlePRENMI450(irqMgr); break; - case 0x2A0: - IrqMgr_HandlePRENMI480(irqmgr); + + case IRQ_PRENMI480_MSG: + IrqMgr_HandlePRENMI480(irqMgr); break; - case 0x2A1: - IrqMgr_HandlePRENMI500(irqmgr); + + case IRQ_PRENMI500_MSG: + IrqMgr_HandlePRENMI500(irqMgr); + break; + + default: break; } } } -void IrqMgr_Init(IrqMgr* irqmgr, void* stack, OSPri pri, u8 retraceCount) { - irqmgr->callbacks = NULL; - irqmgr->verticalRetraceMesg.type = 1; - irqmgr->prenmiMsg.type = 4; - irqmgr->nmiMsg.type = 3; - irqmgr->prenmiStage = 0; - irqmgr->lastPrenmiTime = 0; +void IrqMgr_Init(IrqMgr* irqMgr, void* stack, OSPri pri, u8 retraceCount) { + irqMgr->clients = NULL; + irqMgr->retraceMsg.type = OS_SC_RETRACE_MSG; + irqMgr->prenmiMsg.type = OS_SC_PRE_NMI_MSG; + irqMgr->nmiMsg.type = OS_SC_NMI_MSG; + irqMgr->resetStatus = IRQ_RESET_STATUS_IDLE; + irqMgr->resetTime = 0; - osCreateMesgQueue(&irqmgr->irqQueue, (OSMesg*)irqmgr->irqBuffer, ARRAY_COUNT(irqmgr->irqBuffer)); - osSetEventMesg(OS_EVENT_PRENMI, &irqmgr->irqQueue, (OSMesg)0x29D); - osViSetEvent(&irqmgr->irqQueue, (OSMesg)0x29A, retraceCount); + osCreateMesgQueue(&irqMgr->queue, irqMgr->msgBuf, ARRAY_COUNT(irqMgr->msgBuf)); + osSetEventMesg(OS_EVENT_PRENMI, &irqMgr->queue, (OSMesg)IRQ_PRENMI_MSG); + osViSetEvent(&irqMgr->queue, (OSMesg)IRQ_RETRACE_MSG, retraceCount); - osCreateThread(&irqmgr->thread, Z_THREAD_ID_IRQMGR, IrqMgr_ThreadEntry, irqmgr, stack, pri); - osStartThread(&irqmgr->thread); + osCreateThread(&irqMgr->thread, Z_THREAD_ID_IRQMGR, IrqMgr_ThreadEntry, irqMgr, stack, pri); + osStartThread(&irqMgr->thread); } diff --git a/src/boot/z_std_dma.c b/src/boot/z_std_dma.c index 8661fe02c9..d15da65182 100644 --- a/src/boot/z_std_dma.c +++ b/src/boot/z_std_dma.c @@ -240,7 +240,7 @@ void DmaMgr_ThreadEntry(void* arg) { */ s32 DmaMgr_RequestAsync(DmaRequest* req, void* ram, uintptr_t vrom, size_t size, UNK_TYPE4 unused, OSMesgQueue* queue, OSMesg msg) { - if (gIrqMgrResetStatus >= 2) { + if (gIrqMgrResetStatus >= IRQ_RESET_STATUS_NMI) { return -2; } diff --git a/src/code/audio_thread_manager.c b/src/code/audio_thread_manager.c index dd74c5a32e..d6661b700d 100644 --- a/src/code/audio_thread_manager.c +++ b/src/code/audio_thread_manager.c @@ -33,8 +33,8 @@ void AudioMgr_HandleRetrace(AudioMgr* audioMgr) { audioMgr->audioTask.msgQ = &audioMgr->cmdQueue; audioMgr->audioTask.msg = NULL; - osSendMesg(&audioMgr->sched->cmdQ, &audioMgr->audioTask, OS_MESG_BLOCK); - Sched_SendEntryMsg(audioMgr->sched); + osSendMesg(&audioMgr->sched->cmdQueue, &audioMgr->audioTask, OS_MESG_BLOCK); + Sched_SendNotifyMsg(audioMgr->sched); } if (SREG(20) >= 2) { @@ -125,7 +125,7 @@ void AudioMgr_Unlock(AudioMgr* audioMgr) { osRecvMesg(&audioMgr->lockQueue, NULL, OS_MESG_BLOCK); } -void AudioMgr_Init(AudioMgr* audioMgr, void* stack, OSPri pri, OSId id, SchedContext* sched, IrqMgr* irqMgr) { +void AudioMgr_Init(AudioMgr* audioMgr, void* stack, OSPri pri, OSId id, Scheduler* sched, IrqMgr* irqMgr) { bzero(audioMgr, sizeof(AudioMgr)); audioMgr->sched = sched; diff --git a/src/code/code_8010C1B0.c b/src/code/code_8010C1B0.c deleted file mode 100644 index 2c1fd410f7..0000000000 --- a/src/code/code_8010C1B0.c +++ /dev/null @@ -1,20 +0,0 @@ -#include "global.h" - -// Blocks the current thread until all currently queued scheduler tasks have been completed -void MsgEvent_SendNullTask(void) { - OSScTask task; - OSMesgQueue queue; - OSMesg msg; - - task.next = NULL; - task.flags = OS_SC_RCP_MASK; - task.msgQ = &queue; - task.msg = NULL; - task.framebuffer = NULL; - task.list.t.type = M_NULTASK; - - osCreateMesgQueue(task.msgQ, &msg, 1); - osSendMesg(&gSchedContext.cmdQ, &task, OS_MESG_BLOCK); - Sched_SendEntryMsg(&gSchedContext); - osRecvMesg(&queue, NULL, OS_MESG_BLOCK); -} diff --git a/src/code/graph.c b/src/code/graph.c index eb0277f3af..e13a6ea77b 100644 --- a/src/code/graph.c +++ b/src/code/graph.c @@ -154,7 +154,7 @@ retry: osSyncPrintf("GRAPH SP TIMEOUT\n"); if (retryCount >= 0) { retryCount--; - Sched_SendGfxCancelMsg(&gSchedContext); + Sched_SendGfxCancelMsg(&gScheduler); goto retry; } else { // graph.c: No more! die! @@ -202,13 +202,13 @@ retry: cfb = &sGraphCfbInfos[cfbIdx]; cfbIdx = (cfbIdx + 1) % ARRAY_COUNT(sGraphCfbInfos); - cfb->fb1 = gfxCtx->curFrameBuffer; + cfb->framebuffer = gfxCtx->curFrameBuffer; cfb->swapBuffer = gfxCtx->curFrameBuffer; if (gfxCtx->updateViMode) { gfxCtx->updateViMode = false; cfb->viMode = gfxCtx->viMode; - cfb->features = gfxCtx->viConfigFeatures; + cfb->viFeatures = gfxCtx->viConfigFeatures; cfb->xScale = gfxCtx->xScale; cfb->yScale = gfxCtx->yScale; } else { @@ -223,9 +223,9 @@ retry: osRecvMesg(&gfxCtx->queue, NULL, OS_MESG_NOBLOCK); } - gfxCtx->schedMsgQ = &gSchedContext.cmdQ; - osSendMesg(&gSchedContext.cmdQ, scTask, OS_MESG_BLOCK); - Sched_SendEntryMsg(&gSchedContext); + gfxCtx->schedMsgQ = &gScheduler.cmdQueue; + osSendMesg(&gScheduler.cmdQueue, (OSMesg)scTask, OS_MESG_BLOCK); + Sched_SendNotifyMsg(&gScheduler); } void Graph_UpdateGame(GameState* gameState) { diff --git a/src/code/main.c b/src/code/main.c index 83df663961..09b750dd28 100644 --- a/src/code/main.c +++ b/src/code/main.c @@ -12,7 +12,7 @@ OSMesgQueue sSerialEventQueue; OSMesg sSerialMsgBuf[1]; u32 gSegments[NUM_SEGMENTS]; -SchedContext gSchedContext; +Scheduler gScheduler; IrqMgrClient sIrqClient; OSMesgQueue sIrqMgrMsgQueue; OSMesg sIrqMgrMsgBuf[60]; @@ -68,15 +68,14 @@ void Main(void* arg) { osCreateMesgQueue(&sIrqMgrMsgQueue, sIrqMgrMsgBuf, ARRAY_COUNT(sIrqMgrMsgBuf)); StackCheck_Init(&sSchedStackInfo, sSchedStack, STACK_TOP(sSchedStack), 0, 0x100, "sched"); - Sched_Init(&gSchedContext, STACK_TOP(sSchedStack), Z_PRIORITY_SCHED, gViConfigModeType, 1, &gIrqMgr); + Sched_Init(&gScheduler, STACK_TOP(sSchedStack), Z_PRIORITY_SCHED, gViConfigModeType, 1, &gIrqMgr); CIC6105_AddRomInfoFaultPage(); IrqMgr_AddClient(&gIrqMgr, &sIrqClient, &sIrqMgrMsgQueue); StackCheck_Init(&sAudioStackInfo, sAudioStack, STACK_TOP(sAudioStack), 0, 0x100, "audio"); - AudioMgr_Init(&sAudioMgr, STACK_TOP(sAudioStack), Z_PRIORITY_AUDIOMGR, Z_THREAD_ID_AUDIOMGR, &gSchedContext, - &gIrqMgr); + AudioMgr_Init(&sAudioMgr, STACK_TOP(sAudioStack), Z_PRIORITY_AUDIOMGR, Z_THREAD_ID_AUDIOMGR, &gScheduler, &gIrqMgr); StackCheck_Init(&sPadMgrStackInfo, sPadMgrStack, STACK_TOP(sPadMgrStack), 0, 0x100, "padmgr"); PadMgr_Init(&sSerialEventQueue, &gIrqMgr, Z_THREAD_ID_PADMGR, Z_PRIORITY_PADMGR, STACK_TOP(sPadMgrStack)); diff --git a/src/code/sched.c b/src/code/sched.c index 6c77ffd52a..77822e27e8 100644 --- a/src/code/sched.c +++ b/src/code/sched.c @@ -1,8 +1,9 @@ +#include "scheduler.h" #include "fault.h" #include "idle.h" #include "libc64/sleep.h" +#include "macros.h" #include "viconfig.h" -#include "z64.h" // Variables are put before most headers as a hacky way to bypass bss reordering FaultClient sSchedFaultClient; @@ -16,26 +17,28 @@ u64* gAudioSPDataPtr; u32 gAudioSPDataSize; #include "functions.h" -#include "variables.h" #include "stackcheck.h" #include "z64speed_meter.h" #include "z64thread.h" #define RSP_DONE_MSG 667 #define RDP_DONE_MSG 668 -#define ENTRY_MSG 670 +#define NOTIFY_MSG 670 #define RDP_AUDIO_CANCEL_MSG 671 #define RSP_GFX_CANCEL_MSG 672 -void Sched_SwapFramebuffer(CfbInfo* cfbInfo) { +/** + * Set the current framebuffer to the swapbuffer pointed to by the provided cfb + */ +void Sched_SwapFramebufferImpl(CfbInfo* cfbInfo) { if (cfbInfo->swapBuffer != NULL) { osViSwapBuffer(cfbInfo->swapBuffer); - cfbInfo->updateRate2 = cfbInfo->updateRate; + cfbInfo->updateTimer = cfbInfo->updateRate; if ((SREG(62) == 0) && (cfbInfo->viMode != NULL)) { D_80096B20 = 1; osViSetMode(cfbInfo->viMode); - osViSetSpecialFeatures(cfbInfo->features); + osViSetSpecialFeatures(cfbInfo->viFeatures); osViSetXScale(cfbInfo->xScale); osViSetYScale(cfbInfo->yScale); cfbInfo->viMode = NULL; @@ -44,21 +47,21 @@ void Sched_SwapFramebuffer(CfbInfo* cfbInfo) { cfbInfo->unk_10 = 0; } -void Sched_RetraceUpdateFramebuffer(SchedContext* sched, CfbInfo* cfbInfo) { - if (sched->shouldUpdateVi) { - sched->shouldUpdateVi = false; +void Sched_SwapFramebuffer(Scheduler* sched, CfbInfo* cfbInfo) { + if (sched->isFirstSwap) { + sched->isFirstSwap = false; - if (gIrqMgrResetStatus == 0) { + if (gIrqMgrResetStatus == IRQ_RESET_STATUS_IDLE) { ViConfig_UpdateVi(false); } } - Sched_SwapFramebuffer(cfbInfo); + Sched_SwapFramebufferImpl(cfbInfo); } -void Sched_HandleReset(SchedContext* sched) { +void Sched_HandlePreNMI(Scheduler* sched) { } -void Sched_HandleStop(SchedContext* sched) { +void Sched_HandleNMI(Scheduler* sched) { ViConfig_UpdateVi(true); } @@ -69,7 +72,7 @@ void Sched_HandleStop(SchedContext* sched) { * If there was no currently running audio task, it will dequeue the currently waiting * audio task and notify the sender if the task is associated with a message queue. */ -void Sched_HandleAudioCancel(SchedContext* sched) { +void Sched_HandleAudioCancel(Scheduler* sched) { s32 i; // AUDIO SP Cancel @@ -99,7 +102,7 @@ void Sched_HandleAudioCancel(SchedContext* sched) { } send_mesg: - osSendMesg(&sched->interruptQ, (OSMesg)RSP_DONE_MSG, OS_MESG_NOBLOCK); + osSendMesg(&sched->interruptQueue, (OSMesg)RSP_DONE_MSG, OS_MESG_NOBLOCK); return; } @@ -132,7 +135,7 @@ void Sched_HandleAudioCancel(SchedContext* sched) { * If there is an RDP task, the output buffer will be cleared and the scheduler will send * an RDP_DONE_MSG back to itself. */ -void Sched_HandleGfxCancel(SchedContext* sched) { +void Sched_HandleGfxCancel(Scheduler* sched) { s32 i; // GRAPH SP Cancel @@ -162,7 +165,7 @@ void Sched_HandleGfxCancel(SchedContext* sched) { } send_mesg: - osSendMesg(&sched->interruptQ, (OSMesg)RSP_DONE_MSG, OS_MESG_NOBLOCK); + osSendMesg(&sched->interruptQueue, (OSMesg)RSP_DONE_MSG, OS_MESG_NOBLOCK); goto halt_rdp; } @@ -191,15 +194,15 @@ halt_rdp: // Try to stop DP osSyncPrintf("DP止めようとします\n"); bzero(dpTask->outputBuff, (uintptr_t)dpTask->outputBuffSize - (uintptr_t)dpTask->outputBuff); - osSendMesg(&sched->interruptQ, (OSMesg)RDP_DONE_MSG, OS_MESG_NOBLOCK); + osSendMesg(&sched->interruptQueue, (OSMesg)RDP_DONE_MSG, OS_MESG_NOBLOCK); } } } /** - * Adds a scheduler task to the appropriate linked list. + * Enqueue a task to either the audio task list or the gfx task list */ -void Sched_QueueTask(SchedContext* sched, OSScTask* task) { +void Sched_QueueTask(Scheduler* sched, OSScTask* task) { s32 type = task->list.t.type; if (type == M_AUDTASK) { @@ -221,7 +224,7 @@ void Sched_QueueTask(SchedContext* sched, OSScTask* task) { task->state = task->flags & OS_SC_RCP_MASK; } -void Sched_Yield(SchedContext* sched) { +void Sched_Yield(Scheduler* sched) { // Don't yield audio tasks if (sched->curRSPTask->list.t.type == M_AUDTASK) { // A new audio task has been entered even though the previous audio task has not been completed yet @@ -232,46 +235,56 @@ void Sched_Yield(SchedContext* sched) { } } -s32 Sched_TaskCheckFramebuffers(SchedContext* sched, OSScTask* task) { +/** + * Check if the framebuffer the task wants to use is allowed + */ +s32 Sched_TaskFramebuffersValid(Scheduler* sched, OSScTask* task) { void* nextFB = osViGetNextFramebuffer(); void* curFB = osViGetCurrentFramebuffer(); if ((task == NULL) || (sched->pendingSwapBuf1 != NULL) || - ((curFB == TASK_FRAMEBUFFER(task)->fb1) && (curFB != nextFB))) { - return 0; + ((curFB == TASK_FRAMEBUFFER(task)->framebuffer) && (curFB != nextFB))) { + return false; } - return 1; + + return true; } /** - * Pops the next task from the appropriate linked list and returns it through spTask and dpTask. + * Schedules the next tasks to run on the RSP and RDP + * + * @param sc Scheduler + * @param spTaskOut Next task to run on the RSP + * @param dpTaskOut Next task to run on the RDP + * @param state Bits containing whether the RSP and RDP are currently in use + * @return Bits containing whether the RSP and RDP will be in use after starting the next tasks */ -s32 Sched_Schedule(SchedContext* sched, OSScTask** spTask, OSScTask** dpTask, s32 state) { - s32 ret = state; +s32 Sched_Schedule(Scheduler* sched, OSScTask** spTask, OSScTask** dpTask, s32 state) { + s32 nextState = state; OSScTask* gfxTask = sched->gfxListHead; OSScTask* audioTask = sched->audioListHead; - if ((ret & OS_SC_SP) && (sched->audioListHead != NULL)) { + if ((state & OS_SC_SP) && (sched->audioListHead != NULL)) { *spTask = audioTask; - ret &= ~OS_SC_SP; + nextState &= ~OS_SC_SP; sched->audioListHead = sched->audioListHead->next; if (sched->audioListHead == NULL) { sched->audioListTail = NULL; } } else if (gfxTask != NULL) { if ((gfxTask->state & OS_SC_YIELDED) || !(gfxTask->flags & OS_SC_NEEDS_RDP)) { - if (ret & OS_SC_SP) { + if (state & OS_SC_SP) { *spTask = gfxTask; - ret &= ~OS_SC_SP; + nextState &= ~OS_SC_SP; sched->gfxListHead = sched->gfxListHead->next; if (sched->gfxListHead == NULL) { sched->gfxListTail = NULL; } } - } else if (ret == (OS_SC_SP | OS_SC_DP)) { - if ((TASK_FRAMEBUFFER(gfxTask) == NULL) || Sched_TaskCheckFramebuffers(sched, gfxTask)) { + } else if (state == (OS_SC_SP | OS_SC_DP)) { + if ((TASK_FRAMEBUFFER(gfxTask) == NULL) || Sched_TaskFramebuffersValid(sched, gfxTask)) { *spTask = *dpTask = gfxTask; - ret &= ~(OS_SC_SP | OS_SC_DP); + nextState &= ~(OS_SC_SP | OS_SC_DP); sched->gfxListHead = sched->gfxListHead->next; if (sched->gfxListHead == NULL) { sched->gfxListTail = NULL; @@ -279,36 +292,49 @@ s32 Sched_Schedule(SchedContext* sched, OSScTask** spTask, OSScTask** dpTask, s3 } } } - return ret; -} - -void Sched_TaskUpdateFramebuffer(SchedContext* sched, OSScTask* task) { - sched->pendingSwapBuf1 = TASK_FRAMEBUFFER(task); - - if ((sched->curBuf != NULL) && (sched->curBuf->updateRate2 > 0)) { - return; - } - Sched_RetraceUpdateFramebuffer(sched, sched->pendingSwapBuf1); + return nextState; } /** - * If the task has been marked as completed, notify the sender through the task's - * associated message queue (if it has one) that the task has been completed. If the task - * flags dictate it should swap the framebuffer, do so. + * Sets the next framebuffer to the framebuffer associated to `task`. + * If there is no current buffer or it is time to swap, this buffer will be swapped to + * immediately, otherwise it will be swapped to later in Sched_HandleRetrace. + * + * @see Sched_HandleRetrace */ -void Sched_NotifyDone(SchedContext* sched, OSScTask* task) { +void Sched_SetNextFramebufferFromTask(Scheduler* sched, OSScTask* task) { + sched->pendingSwapBuf1 = TASK_FRAMEBUFFER(task); + + if ((sched->curBuf != NULL) && (sched->curBuf->updateTimer > 0)) { + return; + } + + Sched_SwapFramebuffer(sched, sched->pendingSwapBuf1); +} + +/** + * Checks if the task is done, i.e. it is no longer running on either the RSP or RDP. + * If so, send a message to the task's message queue if there is one, and swap the framebuffer + * if required. + */ +void Sched_TaskComplete(Scheduler* sched, OSScTask* task) { if (!(task->state & (OS_SC_DP | OS_SC_SP))) { if (task->msgQ != NULL) { osSendMesg(task->msgQ, task->msg, OS_MESG_BLOCK); } if (task->flags & OS_SC_SWAPBUFFER) { - Sched_TaskUpdateFramebuffer(sched, task); + Sched_SetNextFramebufferFromTask(sched, task); } } } -void Sched_RunTask(SchedContext* sched, OSScTask* spTask, OSScTask* dpTask) { - u64 time; +/** + * Runs the next tasks. The scheduler doesn't support running RDP tasks without + * passthrough via the RSP, if there is no RSP task to run then the RDP task will + * also do nothing. + */ +void Sched_RunTask(Scheduler* sched, OSScTask* spTask, OSScTask* dpTask) { + OSTime time; if (spTask != NULL) { if (spTask->list.t.type == M_NULTASK) { @@ -320,7 +346,7 @@ void Sched_RunTask(SchedContext* sched, OSScTask* spTask, OSScTask* dpTask) { spTask->state &= ~OS_SC_DP; sched->curRDPTask = NULL; } - Sched_NotifyDone(sched, spTask); + Sched_TaskComplete(sched, spTask); return; } // Write back the data cache to ensure imminent SP DMA does not miss anything @@ -365,18 +391,21 @@ void Sched_RunTask(SchedContext* sched, OSScTask* spTask, OSScTask* dpTask) { } /** - * Enqueues any tasks that have been sent to the scheduler down the command queue. + * Runs when the scheduler has received a notification, either from another thread or + * on VI Retrace. Tasks that have been sent to it will be enqueued onto the audio or + * gfx task queue and one may be ran if the RSP is available. */ -void Sched_HandleEntry(SchedContext* sched) { - OSScTask* spTask = NULL; - OSScTask* dpTask = NULL; - OSMesg msg = NULL; +void Sched_HandleNotify(Scheduler* sched) { + OSScTask* nextRSP = NULL; + OSScTask* nextRDP = NULL; + OSScTask* task = NULL; s32 state; // Fetch and enqueue waiting tasks - while (osRecvMesg(&sched->cmdQ, &msg, OS_MESG_NOBLOCK) != -1) { - Sched_QueueTask(sched, msg); + while (osRecvMesg(&sched->cmdQueue, (OSMesg*)&task, OS_MESG_NOBLOCK) != -1) { + Sched_QueueTask(sched, task); } + // If there is an audio task pending and an RSP task is running, yield the current task. if ((sched->audioListHead != NULL) && (sched->curRSPTask != NULL)) { Sched_Yield(sched); @@ -384,12 +413,12 @@ void Sched_HandleEntry(SchedContext* sched) { } // Schedule and run the next task state = ((sched->curRSPTask == NULL) << 1) | (sched->curRDPTask == NULL); - if (Sched_Schedule(sched, &spTask, &dpTask, state) != state) { - Sched_RunTask(sched, spTask, dpTask); + if (Sched_Schedule(sched, &nextRSP, &nextRDP, state) != state) { + Sched_RunTask(sched, nextRSP, nextRDP); } } -void Sched_HandleRetrace(SchedContext* sched) { +void Sched_HandleRetrace(Scheduler* sched) { ViConfig_UpdateBlack(); sched->retraceCount++; @@ -404,23 +433,29 @@ void Sched_HandleRetrace(SchedContext* sched) { sched->curBuf = sched->pendingSwapBuf1; sched->pendingSwapBuf1 = NULL; } + if (sched->curBuf != NULL) { - if (sched->curBuf->updateRate2 > 0) { - sched->curBuf->updateRate2--; + if (sched->curBuf->updateTimer > 0) { + sched->curBuf->updateTimer--; } - if ((sched->curBuf->updateRate2 <= 0) && (sched->pendingSwapBuf1 != NULL)) { - Sched_RetraceUpdateFramebuffer(sched, sched->pendingSwapBuf1); + if ((sched->curBuf->updateTimer <= 0) && (sched->pendingSwapBuf1 != NULL)) { + Sched_SwapFramebuffer(sched, sched->pendingSwapBuf1); } } - Sched_HandleEntry(sched); + + // Run the notification handler to enqueue any waiting tasks and possibly run one + Sched_HandleNotify(sched); } -void Sched_HandleRSPDone(SchedContext* sched) { +/** + * RSP has signalled that the task has either completed or yielded. + */ +void Sched_HandleRSPDone(Scheduler* sched) { OSScTask* curRSP; OSScTask* nextRSP = NULL; OSScTask* nextRDP = NULL; s32 state; - u64 time; + OSTime time; if (sched->curRSPTask == NULL) { osSyncPrintf("__scHandleRSP:sc->curRSPTask == NULL\n"); @@ -464,7 +499,7 @@ void Sched_HandleRSPDone(SchedContext* sched) { } else { // Mark task completed curRSP->state &= ~OS_SC_SP; - Sched_NotifyDone(sched, curRSP); + Sched_TaskComplete(sched, curRSP); } // Schedule and run next task @@ -474,7 +509,10 @@ void Sched_HandleRSPDone(SchedContext* sched) { } } -void Sched_HandleRDPDone(SchedContext* sched) { +/** + * RDP has signalled task done upon reaching a DPFullSync command + */ +void Sched_HandleRDPDone(Scheduler* sched) { OSScTask* curRDP; OSScTask* nextRSP = NULL; OSScTask* nextRDP = NULL; @@ -493,7 +531,7 @@ void Sched_HandleRDPDone(SchedContext* sched) { sched->curRDPTask = NULL; curRDP->state &= ~OS_SC_DP; - Sched_NotifyDone(sched, curRDP); + Sched_TaskComplete(sched, curRDP); // Schedule and run next task state = ((sched->curRSPTask == NULL) << 1) | (sched->curRDPTask == NULL); @@ -503,35 +541,38 @@ void Sched_HandleRDPDone(SchedContext* sched) { } /** - * Sends a message to the scheduler to inform it that a new task has - * been sent down the command queue. + * Called by other threads in order to wake the scheduler up immediately to enqueue and + * possibly run a task that has been sent to the task queue. Otherwise, any pending tasks + * will be enqueued on next vertical retrace. + * + * Original name: osScKickEntryMsg */ -void Sched_SendEntryMsg(SchedContext* sched) { - osSendMesg(&sched->interruptQ, (OSMesg)ENTRY_MSG, OS_MESG_BLOCK); +void Sched_SendNotifyMsg(Scheduler* sched) { + osSendMesg(&sched->interruptQueue, (OSMesg)NOTIFY_MSG, OS_MESG_BLOCK); } /** * Sends a message to the scheduler to inform it that it should attempt * to stop the last dispatched audio task. */ -void Sched_SendAudioCancelMsg(SchedContext* sched) { - osSendMesg(&sched->interruptQ, (OSMesg)RDP_AUDIO_CANCEL_MSG, OS_MESG_BLOCK); +void Sched_SendAudioCancelMsg(Scheduler* sched) { + osSendMesg(&sched->interruptQueue, (OSMesg)RDP_AUDIO_CANCEL_MSG, OS_MESG_BLOCK); } /** * Sends a message to the scheduler to inform it that it should attempt * to stop the last dispatched gfx task. */ -void Sched_SendGfxCancelMsg(SchedContext* sched) { - osSendMesg(&sched->interruptQ, (OSMesg)RSP_GFX_CANCEL_MSG, OS_MESG_BLOCK); +void Sched_SendGfxCancelMsg(Scheduler* sched) { + osSendMesg(&sched->interruptQueue, (OSMesg)RSP_GFX_CANCEL_MSG, OS_MESG_BLOCK); } /** * Fault Client for the scheduler. Reports information about the state of the scheduler * and any current tasks in the crash debugger. */ -void Sched_FaultClient(void* param1, void* param2) { - SchedContext* sched = (SchedContext*)param1; +void Sched_FaultClient(void* arg0, void* arg1) { + Scheduler* sched = (Scheduler*)arg0; OSScTask* spTask; OSScTask* dpTask; @@ -559,10 +600,10 @@ void Sched_FaultClient(void* param1, void* param2) { */ void Sched_ThreadEntry(void* arg) { s32 msg = 0; - SchedContext* sched = (SchedContext*)arg; + Scheduler* sched = (Scheduler*)arg; while (true) { - osRecvMesg(&sched->interruptQ, (OSMesg*)&msg, OS_MESG_BLOCK); + osRecvMesg(&sched->interruptQueue, (OSMesg*)&msg, OS_MESG_BLOCK); // Check if it's a message from another thread or the OS switch (msg) { @@ -574,8 +615,8 @@ void Sched_ThreadEntry(void* arg) { Sched_HandleGfxCancel(sched); continue; - case ENTRY_MSG: - Sched_HandleEntry(sched); + case NOTIFY_MSG: + Sched_HandleNotify(sched); continue; case RSP_DONE_MSG: @@ -594,31 +635,31 @@ void Sched_ThreadEntry(void* arg) { continue; case OS_SC_PRE_NMI_MSG: - Sched_HandleReset(sched); + Sched_HandlePreNMI(sched); continue; case OS_SC_NMI_MSG: - Sched_HandleStop(sched); + Sched_HandleNMI(sched); continue; } } } /** - * Initializes the SchedContext and scheduler thread. - * Registers an IrqClient for the thread and fault client for the SchedContext. - * Directs the OS to send SP and DP OS messages to interruptQ when the RSP or RDP signal task completion. + * Initializes the Scheduler and scheduler thread. + * Registers an IrqClient for the thread and fault client for the Scheduler. + * Directs the OS to send SP and DP OS messages to interruptQueue when the RSP or RDP signal task completion. */ -void Sched_Init(SchedContext* sched, void* stack, OSPri pri, u8 viModeType, UNK_TYPE arg4, IrqMgr* irqMgr) { - bzero(sched, sizeof(SchedContext)); +void Sched_Init(Scheduler* sched, void* stack, OSPri pri, u8 viModeType, UNK_TYPE arg4, IrqMgr* irqMgr) { + bzero(sched, sizeof(Scheduler)); - sched->shouldUpdateVi = true; + sched->isFirstSwap = true; - osCreateMesgQueue(&sched->interruptQ, sched->intBuf, ARRAY_COUNT(sched->intBuf)); - osCreateMesgQueue(&sched->cmdQ, sched->cmdMsgBuf, ARRAY_COUNT(sched->cmdMsgBuf)); - osSetEventMesg(OS_EVENT_SP, &sched->interruptQ, (OSMesg)RSP_DONE_MSG); - osSetEventMesg(OS_EVENT_DP, &sched->interruptQ, (OSMesg)RDP_DONE_MSG); - IrqMgr_AddClient(irqMgr, &sched->irqClient, &sched->interruptQ); + osCreateMesgQueue(&sched->interruptQueue, sched->interruptMsgBuf, ARRAY_COUNT(sched->interruptMsgBuf)); + osCreateMesgQueue(&sched->cmdQueue, sched->cmdMsgBuf, ARRAY_COUNT(sched->cmdMsgBuf)); + osSetEventMesg(OS_EVENT_SP, &sched->interruptQueue, (OSMesg)RSP_DONE_MSG); + osSetEventMesg(OS_EVENT_DP, &sched->interruptQueue, (OSMesg)RDP_DONE_MSG); + IrqMgr_AddClient(irqMgr, &sched->irqClient, &sched->interruptQueue); Fault_AddClient(&sSchedFaultClient, Sched_FaultClient, sched, NULL); osCreateThread(&sched->thread, Z_THREAD_ID_SCHED, Sched_ThreadEntry, sched, stack, pri); osStartThread(&sched->thread); diff --git a/src/code/z_jpeg.c b/src/code/z_jpeg.c index 5ccc5987d0..a571e4d9df 100644 --- a/src/code/z_jpeg.c +++ b/src/code/z_jpeg.c @@ -65,8 +65,8 @@ void Jpeg_ScheduleDecoderTask(JpegContext* jpegCtx) { jpegCtx->scTask.framebuffer = NULL; jpegCtx->scTask.list.t = sJpegTask; - osSendMesg(&gSchedContext.cmdQ, (OSMesg*)&jpegCtx->scTask, OS_MESG_BLOCK); - Sched_SendEntryMsg(&gSchedContext); // osScKickEntryMsg + osSendMesg(&gScheduler.cmdQueue, (OSMesg*)&jpegCtx->scTask, OS_MESG_BLOCK); + Sched_SendNotifyMsg(&gScheduler); // osScKickEntryMsg osRecvMesg(&jpegCtx->mq, NULL, OS_MESG_BLOCK); } @@ -223,7 +223,7 @@ s32 Jpeg_Decode(void* data, void* zbuffer, void* work, u32 workSize) { } osCreateMesgQueue(&jpegCtx.mq, &jpegCtx.msg, 1); - MsgEvent_SendNullTask(); + Sched_FlushTaskQueue(); jpegCtx.workBuf = workBuff; diff --git a/src/code/z_nulltask.c b/src/code/z_nulltask.c new file mode 100644 index 0000000000..b060e06393 --- /dev/null +++ b/src/code/z_nulltask.c @@ -0,0 +1,30 @@ +#include "scheduler.h" + +#include "macros.h" +#include "main.h" + +/** + * Blocks the current thread until all queued scheduler tasks have completed. + */ +void Sched_FlushTaskQueue(void) { + OSScTask task; + OSMesgQueue queue; + OSMesg msg[1]; + + // Prepare a "NULL" task + task.next = NULL; + task.flags = OS_SC_NEEDS_RDP | OS_SC_NEEDS_RSP; + task.msgQ = &queue; + task.msg = NULL; + task.framebuffer = NULL; + task.list.t.type = M_NULTASK; + osCreateMesgQueue(task.msgQ, msg, ARRAY_COUNT(msg)); + + // Send it to and wake up the scheduler + osSendMesg(&gScheduler.cmdQueue, (OSMesg)&task, OS_MESG_BLOCK); + Sched_SendNotifyMsg(&gScheduler); + + // Wait until the task has been processed, indicating that no task is + // running and the task queue is now empty. + osRecvMesg(&queue, NULL, OS_MESG_BLOCK); +} diff --git a/src/code/z_play.c b/src/code/z_play.c index 83b932b28e..38a9ede2aa 100644 --- a/src/code/z_play.c +++ b/src/code/z_play.c @@ -371,7 +371,7 @@ void Play_Destroy(GameState* thisx) { GraphicsContext* gfxCtx = this->state.gfxCtx; if (sBombersNotebookOpen) { - MsgEvent_SendNullTask(); + Sched_FlushTaskQueue(); SysCfb_SetLoResMode(); gfxCtx->curFrameBuffer = SysCfb_GetFramebuffer(gfxCtx->framebufferIndex % 2); gfxCtx->zbuffer = SysCfb_GetZBuffer(); @@ -928,7 +928,7 @@ void Play_UpdateMain(PlayState* this) { if (R_PICTO_PHOTO_STATE == PICTO_PHOTO_STATE_PROCESS) { R_PICTO_PHOTO_STATE = PICTO_PHOTO_STATE_READY; - MsgEvent_SendNullTask(); + Sched_FlushTaskQueue(); Play_TakePictoPhoto(&this->pauseBgPreRender); R_PICTO_PHOTO_STATE = PICTO_PHOTO_STATE_OFF; } @@ -1067,7 +1067,8 @@ void Play_Update(PlayState* this) { } } else if (CHECK_BTN_ALL(CONTROLLER1(&this->state)->press.button, BTN_L) || CHECK_BTN_ALL(CONTROLLER1(&this->state)->press.button, BTN_B) || - CHECK_BTN_ALL(CONTROLLER1(&this->state)->press.button, BTN_START) || (gIrqMgrResetStatus != 0)) { + CHECK_BTN_ALL(CONTROLLER1(&this->state)->press.button, BTN_START) || + (gIrqMgrResetStatus != IRQ_RESET_STATUS_IDLE)) { sBombersNotebookOpen = false; this->pauseCtx.bombersNotebookOpen = false; sBombersNotebook.loadState = BOMBERS_NOTEBOOK_LOAD_STATE_NONE; @@ -1253,7 +1254,7 @@ void Play_DrawMain(PlayState* this) { PreRender_SetValues(&this->pauseBgPreRender, gCfbWidth, gCfbHeight, gfxCtx->curFrameBuffer, gfxCtx->zbuffer); if (R_PAUSE_BG_PRERENDER_STATE == PAUSE_BG_PRERENDER_PROCESS) { - MsgEvent_SendNullTask(); + Sched_FlushTaskQueue(); if (!gSaveContext.screenScaleFlag) { PreRender_ApplyFiltersSlowlyInit(&this->pauseBgPreRender); } @@ -1448,7 +1449,7 @@ void Play_Draw(PlayState* this) { if (sBombersNotebookOpen) { if (gSysCfbHiResEnabled != 1) { - MsgEvent_SendNullTask(); + Sched_FlushTaskQueue(); SysCfb_SetHiResMode(); gfxCtx2->curFrameBuffer = SysCfb_GetFramebuffer(gfxCtx2->framebufferIndex % 2); gfxCtx2->zbuffer = SysCfb_GetZBuffer(); @@ -1460,7 +1461,7 @@ void Play_Draw(PlayState* this) { } } else { if (gSysCfbHiResEnabled != 0) { - MsgEvent_SendNullTask(); + Sched_FlushTaskQueue(); SysCfb_SetLoResMode(); gfxCtx2->curFrameBuffer = SysCfb_GetFramebuffer(gfxCtx2->framebufferIndex % 2); gfxCtx2->zbuffer = SysCfb_GetZBuffer(); diff --git a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c index 502912da6b..a23a73a809 100644 --- a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c +++ b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c @@ -3599,7 +3599,7 @@ void KaleidoScope_Update(PlayState* play) { Interface_UpdateButtonsPart2(play); gSaveContext.hudVisibility = HUD_VISIBILITY_IDLE; Interface_SetHudVisibility(HUD_VISIBILITY_ALL); - MsgEvent_SendNullTask(); + Sched_FlushTaskQueue(); Skybox_Reload(play, &play->skyboxCtx, play->skyboxId); if ((msgCtx->msgMode != MSGMODE_NONE) && (msgCtx->currentTextId == 0xFF)) { diff --git a/tools/disasm/files.txt b/tools/disasm/files.txt index afcc49e747..cf4c6ecc39 100644 --- a/tools/disasm/files.txt +++ b/tools/disasm/files.txt @@ -403,7 +403,7 @@ 0x8010A000 : "z_map_exp", 0x8010A760 : "z_msgevent", 0x8010C0C0 : "z_nmi_buff", - 0x8010C1B0 : "code_8010C1B0", + 0x8010C1B0 : "z_nulltask", 0x8010C230 : "z_olib", 0x8010CB70 : "[PADDING]", 0x8010CB80 : "z_parameter", diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index dd6406a380..e3f55e876e 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -30,10 +30,10 @@ 0x80081178:("Yaz0_Decompress",), 0x80081250:("IrqMgr_AddClient",), 0x800812DC:("IrqMgr_RemoveClient",), - 0x80081368:("IrqMgr_SendMesgForClient",), - 0x800813B8:("IrqMgr_JamMesgForClient",), + 0x80081368:("IrqMgr_SendMesgToClients",), + 0x800813B8:("IrqMgr_JamMesgToClients",), 0x8008141C:("IrqMgr_HandlePreNMI",), - 0x800814B4:("IrqMgr_CheckStack",), + 0x800814B4:("IrqMgr_CheckStacks",), 0x800814D4:("IrqMgr_HandlePRENMI450",), 0x80081550:("IrqMgr_HandlePRENMI480",), 0x800815A8:("IrqMgr_HandlePRENMI500",), @@ -2064,7 +2064,7 @@ 0x8010C0C0:("Nmi_Init",), 0x8010C164:("Nmi_SetPrenmiStart",), 0x8010C19C:("Nmi_GetPrenmiHasStarted",), - 0x8010C1B0:("MsgEvent_SendNullTask",), + 0x8010C1B0:("Sched_FlushTaskQueue",), 0x8010C230:("OLib_Vec3fDist",), 0x8010C274:("OLib_Vec3fDistOutDiff",), 0x8010C2D0:("OLib_Vec3fDistXZ",), @@ -3192,24 +3192,24 @@ 0x80175FD4:("PadMgr_GetInput2",), 0x80176010:("PadMgr_ThreadEntry",), 0x80176194:("PadMgr_Init",), - 0x80176280:("Sched_SwapFramebuffer",), - 0x80176314:("Sched_RetraceUpdateFramebuffer",), - 0x80176364:("Sched_HandleReset",), - 0x80176370:("Sched_HandleStop",), + 0x80176280:("Sched_SwapFramebufferImpl",), + 0x80176314:("Sched_SwapFramebuffer",), + 0x80176364:("Sched_HandlePreNMI",), + 0x80176370:("Sched_HandleNMI",), 0x80176394:("Sched_HandleAudioCancel",), 0x801764F0:("Sched_HandleGfxCancel",), 0x8017668C:("Sched_QueueTask",), 0x801766F0:("Sched_Yield",), - 0x80176748:("Sched_TaskCheckFramebuffers",), + 0x80176748:("Sched_CheckTaskFramebuffers",), 0x801767B8:("Sched_Schedule",), - 0x801768E0:("Sched_TaskUpdateFramebuffer",), - 0x8017691C:("Sched_NotifyDone",), + 0x801768E0:("Sched_SetNextFramebufferFromTask",), + 0x8017691C:("Sched_TaskComplete",), 0x80176988:("Sched_RunTask",), - 0x80176B34:("Sched_HandleEntry",), + 0x80176B34:("Sched_HandleNotify",), 0x80176C24:("Sched_HandleRetrace",), 0x80176CF4:("Sched_HandleRSPDone",), 0x80176F2C:("Sched_HandleRDPDone",), - 0x80177018:("Sched_SendEntryMsg",), + 0x80177018:("Sched_SendNotifyMsg",), 0x8017703C:("Sched_SendAudioCancelMsg",), 0x80177060:("Sched_SendGfxCancelMsg",), 0x80177084:("Sched_FaultClient",), diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt index 02ffddbc7e..b2bf6393d0 100644 --- a/tools/disasm/variables.txt +++ b/tools/disasm/variables.txt @@ -3996,7 +3996,7 @@ 0x801F8160:("sSerialEventQueue","OSMesgQueue","",0x18), 0x801F8178:("sSerialMsgBuf","OSMesg","[1]",0x4), 0x801F8180:("gSegments","u32","[16]",0x40), - 0x801F81C0:("gSchedContext","SchedContext","",0x338), + 0x801F81C0:("gScheduler","Scheduler","",0x338), 0x801F84F8:("sIrqClient","IrqMgrClient","",0x8), 0x801F8500:("sIrqMgrMsgQueue","OSMesgQueue","",0x18), 0x801F8518:("sIrqMgrMsgBuf","OSMesg","[60]",0xf0), diff --git a/tools/sizes/boot_functions.csv b/tools/sizes/boot_functions.csv index 8f38ae37a5..07494101b5 100644 --- a/tools/sizes/boot_functions.csv +++ b/tools/sizes/boot_functions.csv @@ -27,10 +27,10 @@ asm/non_matchings/boot/yaz0/Yaz0_DecompressImpl.s,Yaz0_DecompressImpl,0x80080FF0 asm/non_matchings/boot/yaz0/Yaz0_Decompress.s,Yaz0_Decompress,0x80081178,0x36 asm/non_matchings/boot/irqmgr/IrqMgr_AddClient.s,IrqMgr_AddClient,0x80081250,0x23 asm/non_matchings/boot/irqmgr/IrqMgr_RemoveClient.s,IrqMgr_RemoveClient,0x800812DC,0x23 -asm/non_matchings/boot/irqmgr/IrqMgr_SendMesgForClient.s,IrqMgr_SendMesgForClient,0x80081368,0x14 -asm/non_matchings/boot/irqmgr/IrqMgr_JamMesgForClient.s,IrqMgr_JamMesgForClient,0x800813B8,0x19 +asm/non_matchings/boot/irqmgr/IrqMgr_SendMesgToClients.s,IrqMgr_SendMesgToClients,0x80081368,0x14 +asm/non_matchings/boot/irqmgr/IrqMgr_JamMesgToClients.s,IrqMgr_JamMesgToClients,0x800813B8,0x19 asm/non_matchings/boot/irqmgr/IrqMgr_HandlePreNMI.s,IrqMgr_HandlePreNMI,0x8008141C,0x26 -asm/non_matchings/boot/irqmgr/IrqMgr_CheckStack.s,IrqMgr_CheckStack,0x800814B4,0x8 +asm/non_matchings/boot/irqmgr/IrqMgr_CheckStacks.s,IrqMgr_CheckStacks,0x800814B4,0x8 asm/non_matchings/boot/irqmgr/IrqMgr_HandlePRENMI450.s,IrqMgr_HandlePRENMI450,0x800814D4,0x1F asm/non_matchings/boot/irqmgr/IrqMgr_HandlePRENMI480.s,IrqMgr_HandlePRENMI480,0x80081550,0x16 asm/non_matchings/boot/irqmgr/IrqMgr_HandlePRENMI500.s,IrqMgr_HandlePRENMI500,0x800815A8,0x9 diff --git a/tools/sizes/code_functions.csv b/tools/sizes/code_functions.csv index fbf83d6454..6084b14eba 100644 --- a/tools/sizes/code_functions.csv +++ b/tools/sizes/code_functions.csv @@ -1578,7 +1578,7 @@ asm/non_matchings/code/z_msgevent/func_8010BF58.s,func_8010BF58,0x8010BF58,0x5A asm/non_matchings/code/z_nmi_buff/Nmi_Init.s,Nmi_Init,0x8010C0C0,0x29 asm/non_matchings/code/z_nmi_buff/Nmi_SetPrenmiStart.s,Nmi_SetPrenmiStart,0x8010C164,0xE asm/non_matchings/code/z_nmi_buff/Nmi_GetPrenmiHasStarted.s,Nmi_GetPrenmiHasStarted,0x8010C19C,0x5 -asm/non_matchings/code/z_nmi_buff/MsgEvent_SendNullTask.s,MsgEvent_SendNullTask,0x8010C1B0,0x20 +asm/non_matchings/code/z_nmi_buff/Sched_FlushTaskQueue.s,Sched_FlushTaskQueue,0x8010C1B0,0x20 asm/non_matchings/code/z_olib/OLib_Vec3fDist.s,OLib_Vec3fDist,0x8010C230,0x11 asm/non_matchings/code/z_olib/OLib_Vec3fDistOutDiff.s,OLib_Vec3fDistOutDiff,0x8010C274,0x17 asm/non_matchings/code/z_olib/OLib_Vec3fDistXZ.s,OLib_Vec3fDistXZ,0x8010C2D0,0xD @@ -2707,23 +2707,23 @@ asm/non_matchings/code/padmgr/PadMgr_GetInput2.s,PadMgr_GetInput2,0x80175FD4,0xF asm/non_matchings/code/padmgr/PadMgr_ThreadEntry.s,PadMgr_ThreadEntry,0x80176010,0x61 asm/non_matchings/code/padmgr/PadMgr_Init.s,PadMgr_Init,0x80176194,0x3B asm/non_matchings/code/sched/Sched_SwapFramebuffer.s,Sched_SwapFramebuffer,0x80176280,0x25 -asm/non_matchings/code/sched/Sched_RetraceUpdateFramebuffer.s,Sched_RetraceUpdateFramebuffer,0x80176314,0x14 -asm/non_matchings/code/sched/Sched_HandleReset.s,Sched_HandleReset,0x80176364,0x3 -asm/non_matchings/code/sched/Sched_HandleStop.s,Sched_HandleStop,0x80176370,0x9 +asm/non_matchings/code/sched/Sched_SwapFramebuffer.s,Sched_SwapFramebuffer,0x80176314,0x14 +asm/non_matchings/code/sched/Sched_HandlePreNMI.s,Sched_HandlePreNMI,0x80176364,0x3 +asm/non_matchings/code/sched/Sched_HandleNMI.s,Sched_HandleNMI,0x80176370,0x9 asm/non_matchings/code/sched/Sched_HandleAudioCancel.s,Sched_HandleAudioCancel,0x80176394,0x57 asm/non_matchings/code/sched/Sched_HandleGfxCancel.s,Sched_HandleGfxCancel,0x801764F0,0x67 asm/non_matchings/code/sched/Sched_QueueTask.s,Sched_QueueTask,0x8017668C,0x19 asm/non_matchings/code/sched/Sched_Yield.s,Sched_Yield,0x801766F0,0x16 -asm/non_matchings/code/sched/Sched_TaskCheckFramebuffers.s,Sched_TaskCheckFramebuffers,0x80176748,0x1C +asm/non_matchings/code/sched/Sched_CheckTaskFramebuffers.s,Sched_CheckTaskFramebuffers,0x80176748,0x1C asm/non_matchings/code/sched/Sched_Schedule.s,Sched_Schedule,0x801767B8,0x4A -asm/non_matchings/code/sched/Sched_TaskUpdateFramebuffer.s,Sched_TaskUpdateFramebuffer,0x801768E0,0xF -asm/non_matchings/code/sched/Sched_NotifyDone.s,Sched_NotifyDone,0x8017691C,0x1B +asm/non_matchings/code/sched/Sched_SetNextFramebufferFromTask.s,Sched_SetNextFramebufferFromTask,0x801768E0,0xF +asm/non_matchings/code/sched/Sched_TaskComplete.s,Sched_TaskComplete,0x8017691C,0x1B asm/non_matchings/code/sched/Sched_RunTask.s,Sched_RunTask,0x80176988,0x6B -asm/non_matchings/code/sched/Sched_HandleEntry.s,Sched_HandleEntry,0x80176B34,0x3C +asm/non_matchings/code/sched/Sched_HandleNotify.s,Sched_HandleNotify,0x80176B34,0x3C asm/non_matchings/code/sched/Sched_HandleRetrace.s,Sched_HandleRetrace,0x80176C24,0x34 asm/non_matchings/code/sched/Sched_HandleRSPDone.s,Sched_HandleRSPDone,0x80176CF4,0x8E asm/non_matchings/code/sched/Sched_HandleRDPDone.s,Sched_HandleRDPDone,0x80176F2C,0x3B -asm/non_matchings/code/sched/Sched_SendEntryMsg.s,Sched_SendEntryMsg,0x80177018,0x9 +asm/non_matchings/code/sched/Sched_SendNotifyMsg.s,Sched_SendNotifyMsg,0x80177018,0x9 asm/non_matchings/code/sched/Sched_SendAudioCancelMsg.s,Sched_SendAudioCancelMsg,0x8017703C,0x9 asm/non_matchings/code/sched/Sched_SendGfxCancelMsg.s,Sched_SendGfxCancelMsg,0x80177060,0x9 asm/non_matchings/code/sched/Sched_FaultClient.s,Sched_FaultClient,0x80177084,0x36