mirror of https://github.com/zeldaret/mm.git
Irqmgr + scheduler Docs (#1527)
* irqmgr docs * Sched_FlushTaskQueue * scheduler docs
This commit is contained in:
parent
732455fdef
commit
665353f344
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* 0x000 */ IrqMgr* irqMgr;
|
/* 0x000 */ IrqMgr* irqMgr;
|
||||||
/* 0x004 */ SchedContext* sched;
|
/* 0x004 */ Scheduler* sched;
|
||||||
/* 0x008 */ OSScTask audioTask;
|
/* 0x008 */ OSScTask audioTask;
|
||||||
/* 0x060 */ AudioTask* rspTask;
|
/* 0x060 */ AudioTask* rspTask;
|
||||||
/* 0x064 */ OSMesgQueue interruptQueue;
|
/* 0x064 */ OSMesgQueue interruptQueue;
|
||||||
|
@ -24,6 +24,6 @@ typedef struct {
|
||||||
|
|
||||||
void AudioMgr_StopAllSfxExceptSystem(void);
|
void AudioMgr_StopAllSfxExceptSystem(void);
|
||||||
void AudioMgr_Unlock(AudioMgr* audioMgr);
|
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
|
#endif
|
||||||
|
|
|
@ -3,20 +3,6 @@
|
||||||
|
|
||||||
#include "z64.h"
|
#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_SetObject(EnItem00* this, PlayState* play, f32* shadowOffset, f32* shadowScale);
|
||||||
// void EnItem00_Init(Actor* thisx, PlayState* play);
|
// void EnItem00_Init(Actor* thisx, PlayState* play);
|
||||||
// void EnItem00_Destroy(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_Init(void);
|
||||||
void Nmi_SetPrenmiStart(void);
|
void Nmi_SetPrenmiStart(void);
|
||||||
// s32 Nmi_GetPrenmiHasStarted(void);
|
// s32 Nmi_GetPrenmiHasStarted(void);
|
||||||
void MsgEvent_SendNullTask(void);
|
|
||||||
f32 OLib_Vec3fDist(Vec3f* a, Vec3f* b);
|
f32 OLib_Vec3fDist(Vec3f* a, Vec3f* b);
|
||||||
f32 OLib_Vec3fDistOutDiff(Vec3f* a, Vec3f* b, Vec3f* dest);
|
f32 OLib_Vec3fDistOutDiff(Vec3f* a, Vec3f* b, Vec3f* dest);
|
||||||
f32 OLib_Vec3fDistXZ(Vec3f* a, Vec3f* b);
|
f32 OLib_Vec3fDistXZ(Vec3f* a, Vec3f* b);
|
||||||
|
@ -614,29 +599,6 @@ Gfx* Graph_GfxPlusOne(Gfx* gfx);
|
||||||
Gfx* Graph_BranchDlist(Gfx* gfx, Gfx* dst);
|
Gfx* Graph_BranchDlist(Gfx* gfx, Gfx* dst);
|
||||||
void* Graph_DlistAlloc(Gfx** gfx, size_t size);
|
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_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_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);
|
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);
|
||||||
|
|
|
@ -4,23 +4,29 @@
|
||||||
#include "ultra64.h"
|
#include "ultra64.h"
|
||||||
#include "PR/sched.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 {
|
typedef struct IrqMgrClient {
|
||||||
/* 0x0 */ struct IrqMgrClient* next;
|
/* 0x0 */ struct IrqMgrClient* next;
|
||||||
/* 0x4 */ OSMesgQueue* queue;
|
/* 0x4 */ OSMesgQueue* queue;
|
||||||
} IrqMgrClient; // size = 0x8
|
} IrqMgrClient; // size = 0x8
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* 0x000 */ OSScMsg verticalRetraceMesg;
|
/* 0x000 */ OSScMsg retraceMsg;
|
||||||
/* 0x020 */ OSScMsg prenmiMsg;
|
/* 0x020 */ OSScMsg prenmiMsg;
|
||||||
/* 0x040 */ OSScMsg nmiMsg;
|
/* 0x040 */ OSScMsg nmiMsg;
|
||||||
/* 0x060 */ OSMesgQueue irqQueue;
|
/* 0x060 */ OSMesgQueue queue;
|
||||||
/* 0x078 */ OSMesg irqBuffer[8];
|
/* 0x078 */ OSMesg msgBuf[8];
|
||||||
/* 0x098 */ OSThread thread;
|
/* 0x098 */ OSThread thread;
|
||||||
/* 0x248 */ IrqMgrClient* callbacks;
|
/* 0x248 */ IrqMgrClient* clients;
|
||||||
/* 0x24C */ u8 prenmiStage;
|
/* 0x24C */ u8 resetStatus;
|
||||||
/* 0x250 */ OSTime lastPrenmiTime;
|
/* 0x250 */ OSTime resetTime;
|
||||||
/* 0x258 */ OSTimer prenmiTimer;
|
/* 0x258 */ OSTimer timer;
|
||||||
/* 0x278 */ OSTime lastFrameTime;
|
/* 0x278 */ OSTime retraceTime;
|
||||||
} IrqMgr; // size = 0x280
|
} IrqMgr; // size = 0x280
|
||||||
|
|
||||||
extern vs32 gIrqMgrResetStatus;
|
extern vs32 gIrqMgrResetStatus;
|
||||||
|
@ -28,4 +34,8 @@ extern volatile OSTime sIrqMgrResetTime;
|
||||||
extern volatile OSTime gIrqMgrRetraceTime;
|
extern volatile OSTime gIrqMgrRetraceTime;
|
||||||
extern s32 sIrqMgrRetraceCount;
|
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
|
#endif
|
||||||
|
|
|
@ -10,7 +10,7 @@ extern s32 gScreenHeight;
|
||||||
extern size_t gSystemHeapSize;
|
extern size_t gSystemHeapSize;
|
||||||
|
|
||||||
extern uintptr_t gSegments[NUM_SEGMENTS];
|
extern uintptr_t gSegments[NUM_SEGMENTS];
|
||||||
extern SchedContext gSchedContext;
|
extern Scheduler gScheduler;
|
||||||
extern OSThread gGraphThread;
|
extern OSThread gGraphThread;
|
||||||
extern PadMgr gPadMgr;
|
extern PadMgr gPadMgr;
|
||||||
|
|
||||||
|
|
|
@ -7,41 +7,50 @@
|
||||||
#include "PR/sptask.h"
|
#include "PR/sptask.h"
|
||||||
#include "irqmgr.h"
|
#include "irqmgr.h"
|
||||||
|
|
||||||
|
#include "unk.h"
|
||||||
|
|
||||||
#define TASK_FRAMEBUFFER(task) ((CfbInfo*)(task)->framebuffer)
|
#define TASK_FRAMEBUFFER(task) ((CfbInfo*)(task)->framebuffer)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* 0x00 */ u16* fb1;
|
/* 0x00 */ u16* framebuffer; // current framebuffer
|
||||||
/* 0x04 */ u16* swapBuffer;
|
/* 0x04 */ u16* swapBuffer; // framebuffer to swap to
|
||||||
/* 0x08 */ OSViMode* viMode;
|
/* 0x08 */ OSViMode* viMode;
|
||||||
/* 0x0C */ u32 features;
|
/* 0x0C */ u32 viFeatures;
|
||||||
/* 0x10 */ u8 unk_10;
|
/* 0x10 */ u8 unk_10; // set to 0, never read
|
||||||
/* 0x11 */ s8 updateRate;
|
/* 0x11 */ s8 updateRate; // how many VIs should elapse before next swap
|
||||||
/* 0x12 */ s8 updateRate2;
|
/* 0x12 */ s8 updateTimer; // counts down (in VIs) from updateRate to 0, swaps the framebuffer at 0
|
||||||
/* 0x13 */ u8 unk_13;
|
/* 0x14 */ f32 xScale;
|
||||||
/* 0x14 */ f32 xScale;
|
/* 0x18 */ f32 yScale;
|
||||||
/* 0x18 */ f32 yScale;
|
|
||||||
} CfbInfo; // size = 0x1C
|
} CfbInfo; // size = 0x1C
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* 0x000 */ OSMesgQueue interruptQ;
|
/* 0x000 */ OSMesgQueue interruptQueue;
|
||||||
/* 0x018 */ OSMesg intBuf[64];
|
/* 0x018 */ OSMesg interruptMsgBuf[64];
|
||||||
/* 0x118 */ OSMesgQueue cmdQ;
|
/* 0x118 */ OSMesgQueue cmdQueue;
|
||||||
/* 0x130 */ OSMesg cmdMsgBuf[8];
|
/* 0x130 */ OSMesg cmdMsgBuf[8];
|
||||||
/* 0x150 */ OSThread thread;
|
/* 0x150 */ OSThread thread;
|
||||||
/* 0x300 */ OSScTask* audioListHead;
|
/* 0x300 */ OSScTask* audioListHead;
|
||||||
/* 0x304 */ OSScTask* gfxListHead;
|
/* 0x304 */ OSScTask* gfxListHead;
|
||||||
/* 0x308 */ OSScTask* audioListTail;
|
/* 0x308 */ OSScTask* audioListTail;
|
||||||
/* 0x30C */ OSScTask* gfxListTail;
|
/* 0x30C */ OSScTask* gfxListTail;
|
||||||
/* 0x310 */ OSScTask* curRSPTask;
|
/* 0x310 */ OSScTask* curRSPTask;
|
||||||
/* 0x314 */ OSScTask* curRDPTask;
|
/* 0x314 */ OSScTask* curRDPTask;
|
||||||
/* 0x318 */ s32 retraceCount;
|
/* 0x318 */ s32 retraceCount;
|
||||||
/* 0x318 */ s32 doAudio;
|
/* 0x318 */ s32 doAudio;
|
||||||
/* 0x320 */ CfbInfo* curBuf;
|
/* 0x320 */ CfbInfo* curBuf; // current framebuffer (taken from buffer 1)
|
||||||
/* 0x324 */ CfbInfo* pendingSwapBuf1;
|
/* 0x324 */ CfbInfo* pendingSwapBuf1; // buffer 1 (next buffer)
|
||||||
/* 0x328 */ CfbInfo* pendingSwapBuf2;
|
/* 0x328 */ CfbInfo* pendingSwapBuf2; // buffer 2 (always NULL)
|
||||||
/* 0x32C */ char unk_32C[0x3];
|
/* 0x32C */ UNK_TYPE1 unk_32C[0x3];
|
||||||
/* 0x32F */ u8 shouldUpdateVi;
|
/* 0x32F */ u8 isFirstSwap;
|
||||||
/* 0x330 */ IrqMgrClient irqClient;
|
/* 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
|
#endif
|
||||||
|
|
2
spec
2
spec
|
@ -500,7 +500,7 @@ beginseg
|
||||||
include "build/src/code/z_msgevent.o"
|
include "build/src/code/z_msgevent.o"
|
||||||
include "build/data/code/z_msgevent.data.o"
|
include "build/data/code/z_msgevent.data.o"
|
||||||
include "build/src/code/z_nmi_buff.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"
|
include "build/src/code/z_olib.o"
|
||||||
pad_text
|
pad_text
|
||||||
include "build/src/code/z_parameter.o"
|
include "build/src/code/z_parameter.o"
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
#include "buffers.h"
|
#include "buffers.h"
|
||||||
#include "irqmgr.h"
|
#include "irqmgr.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
#include "segment_symbols.h"
|
||||||
#include "stack.h"
|
#include "stack.h"
|
||||||
#include "stackcheck.h"
|
#include "stackcheck.h"
|
||||||
#include "viconfig.h"
|
#include "viconfig.h"
|
||||||
|
#include "z64dma.h"
|
||||||
#include "z64thread.h"
|
#include "z64thread.h"
|
||||||
|
|
||||||
// Variables are put before most headers as a hacky way to bypass bss reordering
|
// Variables are put before most headers as a hacky way to bypass bss reordering
|
||||||
|
@ -19,8 +21,6 @@ OSMesgQueue gPiMgrCmdQueue;
|
||||||
OSViMode gViConfigMode;
|
OSViMode gViConfigMode;
|
||||||
u8 gViConfigModeType;
|
u8 gViConfigModeType;
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
#include "buffers.h"
|
|
||||||
#include "idle.h"
|
#include "idle.h"
|
||||||
|
|
||||||
u8 D_80096B20 = 1;
|
u8 D_80096B20 = 1;
|
||||||
|
|
|
@ -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 "stackcheck.h"
|
||||||
#include "z64thread.h"
|
#include "z64thread.h"
|
||||||
|
|
||||||
vs32 gIrqMgrResetStatus = 0;
|
vs32 gIrqMgrResetStatus = IRQ_RESET_STATUS_IDLE;
|
||||||
volatile OSTime sIrqMgrResetTime = 0;
|
volatile OSTime sIrqMgrResetTime = 0;
|
||||||
volatile OSTime gIrqMgrRetraceTime = 0;
|
volatile OSTime gIrqMgrRetraceTime = 0;
|
||||||
s32 sIrqMgrRetraceCount = 0;
|
s32 sIrqMgrRetraceCount = 0;
|
||||||
|
|
||||||
void IrqMgr_AddClient(IrqMgr* irqmgr, IrqMgrClient* client, OSMesgQueue* msgQueue) {
|
// Internal messages
|
||||||
u32 saveMask;
|
#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->queue = msgQueue;
|
||||||
client->next = irqmgr->callbacks;
|
client->next = irqMgr->clients;
|
||||||
irqmgr->callbacks = client;
|
irqMgr->clients = client;
|
||||||
|
|
||||||
osSetIntMask(saveMask);
|
osSetIntMask(saveMask);
|
||||||
|
|
||||||
if (irqmgr->prenmiStage > 0) {
|
if (irqMgr->resetStatus >= IRQ_RESET_STATUS_PRENMI) {
|
||||||
osSendMesg(client->queue, &irqmgr->prenmiMsg.type, OS_MESG_NOBLOCK);
|
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) {
|
void IrqMgr_RemoveClient(IrqMgr* irqMgr, IrqMgrClient* client) {
|
||||||
IrqMgrClient* iter;
|
IrqMgrClient* iter = irqMgr->clients;
|
||||||
IrqMgrClient* last;
|
IrqMgrClient* last = NULL;
|
||||||
u32 saveMask;
|
u32 saveMask = osSetIntMask(OS_IM_NONE);
|
||||||
|
|
||||||
iter = irqmgr->callbacks;
|
|
||||||
last = NULL;
|
|
||||||
|
|
||||||
saveMask = osSetIntMask(1);
|
|
||||||
|
|
||||||
while (iter != NULL) {
|
while (iter != NULL) {
|
||||||
if (iter == remove) {
|
if (iter == client) {
|
||||||
if (last != NULL) {
|
if (last != NULL) {
|
||||||
last->next = remove->next;
|
last->next = client->next;
|
||||||
} else {
|
} else {
|
||||||
irqmgr->callbacks = remove->next;
|
irqMgr->clients = client->next;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -52,119 +99,142 @@ void IrqMgr_RemoveClient(IrqMgr* irqmgr, IrqMgrClient* remove) {
|
||||||
osSetIntMask(saveMask);
|
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) {
|
while (client != NULL) {
|
||||||
osSendMesg(iter->queue, msg, OS_MESG_NOBLOCK);
|
osSendMesg(client->queue, msg, OS_MESG_NOBLOCK);
|
||||||
iter = iter->next;
|
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) {
|
while (client != NULL) {
|
||||||
if (iter->queue->validCount < iter->queue->msgCount) {
|
if (!MQ_IS_FULL(client->queue)) {
|
||||||
osSendMesg(iter->queue, msg, OS_MESG_NOBLOCK);
|
//! @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;
|
* Runs when the Pre-NMI OS Event is received. This indicates that the console will reset in at least
|
||||||
irqmgr->prenmiStage = 1;
|
* 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
|
// 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);
|
StackCheck_Check(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrqMgr_HandlePRENMI450(IrqMgr* irqmgr) {
|
void IrqMgr_HandlePRENMI450(IrqMgr* irqMgr) {
|
||||||
gIrqMgrResetStatus = 2;
|
gIrqMgrResetStatus = IRQ_RESET_STATUS_NMI;
|
||||||
irqmgr->prenmiStage = 2;
|
irqMgr->resetStatus = IRQ_RESET_STATUS_NMI;
|
||||||
|
|
||||||
// Wait .03 seconds then generate a stage 3 prenmi interrupt
|
// 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
|
// 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();
|
osAfterPreNMI();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrqMgr_HandlePRENMI500(IrqMgr* irqmgr) {
|
void IrqMgr_HandlePRENMI500(IrqMgr* irqMgr) {
|
||||||
IrqMgr_CheckStack();
|
IrqMgr_CheckStacks();
|
||||||
}
|
}
|
||||||
void IrqMgr_HandleRetrace(IrqMgr* irqmgr) {
|
|
||||||
|
void IrqMgr_HandleRetrace(IrqMgr* irqMgr) {
|
||||||
if (gIrqMgrRetraceTime == 0) {
|
if (gIrqMgrRetraceTime == 0) {
|
||||||
if (irqmgr->lastFrameTime == 0) {
|
if (irqMgr->retraceTime == 0) {
|
||||||
irqmgr->lastFrameTime = osGetTime();
|
irqMgr->retraceTime = osGetTime();
|
||||||
} else {
|
} else {
|
||||||
gIrqMgrRetraceTime = osGetTime() - irqmgr->lastFrameTime;
|
gIrqMgrRetraceTime = osGetTime() - irqMgr->retraceTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sIrqMgrRetraceCount += 1;
|
sIrqMgrRetraceCount++;
|
||||||
IrqMgr_SendMesgForClient(irqmgr, irqmgr);
|
IrqMgr_SendMesgToClients(irqMgr, (OSMesg)&irqMgr->retraceMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrqMgr_ThreadEntry(IrqMgr* irqmgr) {
|
void IrqMgr_ThreadEntry(void* arg) {
|
||||||
u32 interrupt;
|
s32 msg = 0;
|
||||||
u32 stop;
|
IrqMgr* irqMgr = (IrqMgr*)arg;
|
||||||
|
s32 exit = false;
|
||||||
|
|
||||||
interrupt = 0;
|
while (!exit) {
|
||||||
stop = 0;
|
osRecvMesg(&irqMgr->queue, (OSMesg*)&msg, OS_MESG_BLOCK);
|
||||||
while (stop == 0) {
|
|
||||||
if (stop) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
osRecvMesg(&irqmgr->irqQueue, (OSMesg*)&interrupt, OS_MESG_BLOCK);
|
switch (msg) {
|
||||||
switch (interrupt) {
|
case IRQ_RETRACE_MSG:
|
||||||
case 0x29A:
|
IrqMgr_HandleRetrace(irqMgr);
|
||||||
IrqMgr_HandleRetrace(irqmgr);
|
|
||||||
break;
|
break;
|
||||||
case 0x29D:
|
|
||||||
IrqMgr_HandlePreNMI(irqmgr);
|
case IRQ_PRENMI_MSG:
|
||||||
|
IrqMgr_HandlePreNMI(irqMgr);
|
||||||
break;
|
break;
|
||||||
case 0x29F:
|
|
||||||
IrqMgr_HandlePRENMI450(irqmgr);
|
case IRQ_PRENMI450_MSG:
|
||||||
|
IrqMgr_HandlePRENMI450(irqMgr);
|
||||||
break;
|
break;
|
||||||
case 0x2A0:
|
|
||||||
IrqMgr_HandlePRENMI480(irqmgr);
|
case IRQ_PRENMI480_MSG:
|
||||||
|
IrqMgr_HandlePRENMI480(irqMgr);
|
||||||
break;
|
break;
|
||||||
case 0x2A1:
|
|
||||||
IrqMgr_HandlePRENMI500(irqmgr);
|
case IRQ_PRENMI500_MSG:
|
||||||
|
IrqMgr_HandlePRENMI500(irqMgr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IrqMgr_Init(IrqMgr* irqmgr, void* stack, OSPri pri, u8 retraceCount) {
|
void IrqMgr_Init(IrqMgr* irqMgr, void* stack, OSPri pri, u8 retraceCount) {
|
||||||
irqmgr->callbacks = NULL;
|
irqMgr->clients = NULL;
|
||||||
irqmgr->verticalRetraceMesg.type = 1;
|
irqMgr->retraceMsg.type = OS_SC_RETRACE_MSG;
|
||||||
irqmgr->prenmiMsg.type = 4;
|
irqMgr->prenmiMsg.type = OS_SC_PRE_NMI_MSG;
|
||||||
irqmgr->nmiMsg.type = 3;
|
irqMgr->nmiMsg.type = OS_SC_NMI_MSG;
|
||||||
irqmgr->prenmiStage = 0;
|
irqMgr->resetStatus = IRQ_RESET_STATUS_IDLE;
|
||||||
irqmgr->lastPrenmiTime = 0;
|
irqMgr->resetTime = 0;
|
||||||
|
|
||||||
osCreateMesgQueue(&irqmgr->irqQueue, (OSMesg*)irqmgr->irqBuffer, ARRAY_COUNT(irqmgr->irqBuffer));
|
osCreateMesgQueue(&irqMgr->queue, irqMgr->msgBuf, ARRAY_COUNT(irqMgr->msgBuf));
|
||||||
osSetEventMesg(OS_EVENT_PRENMI, &irqmgr->irqQueue, (OSMesg)0x29D);
|
osSetEventMesg(OS_EVENT_PRENMI, &irqMgr->queue, (OSMesg)IRQ_PRENMI_MSG);
|
||||||
osViSetEvent(&irqmgr->irqQueue, (OSMesg)0x29A, retraceCount);
|
osViSetEvent(&irqMgr->queue, (OSMesg)IRQ_RETRACE_MSG, retraceCount);
|
||||||
|
|
||||||
osCreateThread(&irqmgr->thread, Z_THREAD_ID_IRQMGR, IrqMgr_ThreadEntry, irqmgr, stack, pri);
|
osCreateThread(&irqMgr->thread, Z_THREAD_ID_IRQMGR, IrqMgr_ThreadEntry, irqMgr, stack, pri);
|
||||||
osStartThread(&irqmgr->thread);
|
osStartThread(&irqMgr->thread);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
s32 DmaMgr_RequestAsync(DmaRequest* req, void* ram, uintptr_t vrom, size_t size, UNK_TYPE4 unused, OSMesgQueue* queue,
|
||||||
OSMesg msg) {
|
OSMesg msg) {
|
||||||
if (gIrqMgrResetStatus >= 2) {
|
if (gIrqMgrResetStatus >= IRQ_RESET_STATUS_NMI) {
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,8 +33,8 @@ void AudioMgr_HandleRetrace(AudioMgr* audioMgr) {
|
||||||
audioMgr->audioTask.msgQ = &audioMgr->cmdQueue;
|
audioMgr->audioTask.msgQ = &audioMgr->cmdQueue;
|
||||||
|
|
||||||
audioMgr->audioTask.msg = NULL;
|
audioMgr->audioTask.msg = NULL;
|
||||||
osSendMesg(&audioMgr->sched->cmdQ, &audioMgr->audioTask, OS_MESG_BLOCK);
|
osSendMesg(&audioMgr->sched->cmdQueue, &audioMgr->audioTask, OS_MESG_BLOCK);
|
||||||
Sched_SendEntryMsg(audioMgr->sched);
|
Sched_SendNotifyMsg(audioMgr->sched);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SREG(20) >= 2) {
|
if (SREG(20) >= 2) {
|
||||||
|
@ -125,7 +125,7 @@ void AudioMgr_Unlock(AudioMgr* audioMgr) {
|
||||||
osRecvMesg(&audioMgr->lockQueue, NULL, OS_MESG_BLOCK);
|
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));
|
bzero(audioMgr, sizeof(AudioMgr));
|
||||||
|
|
||||||
audioMgr->sched = sched;
|
audioMgr->sched = sched;
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -154,7 +154,7 @@ retry:
|
||||||
osSyncPrintf("GRAPH SP TIMEOUT\n");
|
osSyncPrintf("GRAPH SP TIMEOUT\n");
|
||||||
if (retryCount >= 0) {
|
if (retryCount >= 0) {
|
||||||
retryCount--;
|
retryCount--;
|
||||||
Sched_SendGfxCancelMsg(&gSchedContext);
|
Sched_SendGfxCancelMsg(&gScheduler);
|
||||||
goto retry;
|
goto retry;
|
||||||
} else {
|
} else {
|
||||||
// graph.c: No more! die!
|
// graph.c: No more! die!
|
||||||
|
@ -202,13 +202,13 @@ retry:
|
||||||
cfb = &sGraphCfbInfos[cfbIdx];
|
cfb = &sGraphCfbInfos[cfbIdx];
|
||||||
cfbIdx = (cfbIdx + 1) % ARRAY_COUNT(sGraphCfbInfos);
|
cfbIdx = (cfbIdx + 1) % ARRAY_COUNT(sGraphCfbInfos);
|
||||||
|
|
||||||
cfb->fb1 = gfxCtx->curFrameBuffer;
|
cfb->framebuffer = gfxCtx->curFrameBuffer;
|
||||||
cfb->swapBuffer = gfxCtx->curFrameBuffer;
|
cfb->swapBuffer = gfxCtx->curFrameBuffer;
|
||||||
|
|
||||||
if (gfxCtx->updateViMode) {
|
if (gfxCtx->updateViMode) {
|
||||||
gfxCtx->updateViMode = false;
|
gfxCtx->updateViMode = false;
|
||||||
cfb->viMode = gfxCtx->viMode;
|
cfb->viMode = gfxCtx->viMode;
|
||||||
cfb->features = gfxCtx->viConfigFeatures;
|
cfb->viFeatures = gfxCtx->viConfigFeatures;
|
||||||
cfb->xScale = gfxCtx->xScale;
|
cfb->xScale = gfxCtx->xScale;
|
||||||
cfb->yScale = gfxCtx->yScale;
|
cfb->yScale = gfxCtx->yScale;
|
||||||
} else {
|
} else {
|
||||||
|
@ -223,9 +223,9 @@ retry:
|
||||||
osRecvMesg(&gfxCtx->queue, NULL, OS_MESG_NOBLOCK);
|
osRecvMesg(&gfxCtx->queue, NULL, OS_MESG_NOBLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
gfxCtx->schedMsgQ = &gSchedContext.cmdQ;
|
gfxCtx->schedMsgQ = &gScheduler.cmdQueue;
|
||||||
osSendMesg(&gSchedContext.cmdQ, scTask, OS_MESG_BLOCK);
|
osSendMesg(&gScheduler.cmdQueue, (OSMesg)scTask, OS_MESG_BLOCK);
|
||||||
Sched_SendEntryMsg(&gSchedContext);
|
Sched_SendNotifyMsg(&gScheduler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graph_UpdateGame(GameState* gameState) {
|
void Graph_UpdateGame(GameState* gameState) {
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
OSMesgQueue sSerialEventQueue;
|
OSMesgQueue sSerialEventQueue;
|
||||||
OSMesg sSerialMsgBuf[1];
|
OSMesg sSerialMsgBuf[1];
|
||||||
u32 gSegments[NUM_SEGMENTS];
|
u32 gSegments[NUM_SEGMENTS];
|
||||||
SchedContext gSchedContext;
|
Scheduler gScheduler;
|
||||||
IrqMgrClient sIrqClient;
|
IrqMgrClient sIrqClient;
|
||||||
OSMesgQueue sIrqMgrMsgQueue;
|
OSMesgQueue sIrqMgrMsgQueue;
|
||||||
OSMesg sIrqMgrMsgBuf[60];
|
OSMesg sIrqMgrMsgBuf[60];
|
||||||
|
@ -68,15 +68,14 @@ void Main(void* arg) {
|
||||||
osCreateMesgQueue(&sIrqMgrMsgQueue, sIrqMgrMsgBuf, ARRAY_COUNT(sIrqMgrMsgBuf));
|
osCreateMesgQueue(&sIrqMgrMsgQueue, sIrqMgrMsgBuf, ARRAY_COUNT(sIrqMgrMsgBuf));
|
||||||
|
|
||||||
StackCheck_Init(&sSchedStackInfo, sSchedStack, STACK_TOP(sSchedStack), 0, 0x100, "sched");
|
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();
|
CIC6105_AddRomInfoFaultPage();
|
||||||
|
|
||||||
IrqMgr_AddClient(&gIrqMgr, &sIrqClient, &sIrqMgrMsgQueue);
|
IrqMgr_AddClient(&gIrqMgr, &sIrqClient, &sIrqMgrMsgQueue);
|
||||||
|
|
||||||
StackCheck_Init(&sAudioStackInfo, sAudioStack, STACK_TOP(sAudioStack), 0, 0x100, "audio");
|
StackCheck_Init(&sAudioStackInfo, sAudioStack, STACK_TOP(sAudioStack), 0, 0x100, "audio");
|
||||||
AudioMgr_Init(&sAudioMgr, STACK_TOP(sAudioStack), Z_PRIORITY_AUDIOMGR, Z_THREAD_ID_AUDIOMGR, &gSchedContext,
|
AudioMgr_Init(&sAudioMgr, STACK_TOP(sAudioStack), Z_PRIORITY_AUDIOMGR, Z_THREAD_ID_AUDIOMGR, &gScheduler, &gIrqMgr);
|
||||||
&gIrqMgr);
|
|
||||||
|
|
||||||
StackCheck_Init(&sPadMgrStackInfo, sPadMgrStack, STACK_TOP(sPadMgrStack), 0, 0x100, "padmgr");
|
StackCheck_Init(&sPadMgrStackInfo, sPadMgrStack, STACK_TOP(sPadMgrStack), 0, 0x100, "padmgr");
|
||||||
PadMgr_Init(&sSerialEventQueue, &gIrqMgr, Z_THREAD_ID_PADMGR, Z_PRIORITY_PADMGR, STACK_TOP(sPadMgrStack));
|
PadMgr_Init(&sSerialEventQueue, &gIrqMgr, Z_THREAD_ID_PADMGR, Z_PRIORITY_PADMGR, STACK_TOP(sPadMgrStack));
|
||||||
|
|
241
src/code/sched.c
241
src/code/sched.c
|
@ -1,8 +1,9 @@
|
||||||
|
#include "scheduler.h"
|
||||||
#include "fault.h"
|
#include "fault.h"
|
||||||
#include "idle.h"
|
#include "idle.h"
|
||||||
#include "libc64/sleep.h"
|
#include "libc64/sleep.h"
|
||||||
|
#include "macros.h"
|
||||||
#include "viconfig.h"
|
#include "viconfig.h"
|
||||||
#include "z64.h"
|
|
||||||
|
|
||||||
// Variables are put before most headers as a hacky way to bypass bss reordering
|
// Variables are put before most headers as a hacky way to bypass bss reordering
|
||||||
FaultClient sSchedFaultClient;
|
FaultClient sSchedFaultClient;
|
||||||
|
@ -16,26 +17,28 @@ u64* gAudioSPDataPtr;
|
||||||
u32 gAudioSPDataSize;
|
u32 gAudioSPDataSize;
|
||||||
|
|
||||||
#include "functions.h"
|
#include "functions.h"
|
||||||
#include "variables.h"
|
|
||||||
#include "stackcheck.h"
|
#include "stackcheck.h"
|
||||||
#include "z64speed_meter.h"
|
#include "z64speed_meter.h"
|
||||||
#include "z64thread.h"
|
#include "z64thread.h"
|
||||||
|
|
||||||
#define RSP_DONE_MSG 667
|
#define RSP_DONE_MSG 667
|
||||||
#define RDP_DONE_MSG 668
|
#define RDP_DONE_MSG 668
|
||||||
#define ENTRY_MSG 670
|
#define NOTIFY_MSG 670
|
||||||
#define RDP_AUDIO_CANCEL_MSG 671
|
#define RDP_AUDIO_CANCEL_MSG 671
|
||||||
#define RSP_GFX_CANCEL_MSG 672
|
#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) {
|
if (cfbInfo->swapBuffer != NULL) {
|
||||||
osViSwapBuffer(cfbInfo->swapBuffer);
|
osViSwapBuffer(cfbInfo->swapBuffer);
|
||||||
cfbInfo->updateRate2 = cfbInfo->updateRate;
|
cfbInfo->updateTimer = cfbInfo->updateRate;
|
||||||
|
|
||||||
if ((SREG(62) == 0) && (cfbInfo->viMode != NULL)) {
|
if ((SREG(62) == 0) && (cfbInfo->viMode != NULL)) {
|
||||||
D_80096B20 = 1;
|
D_80096B20 = 1;
|
||||||
osViSetMode(cfbInfo->viMode);
|
osViSetMode(cfbInfo->viMode);
|
||||||
osViSetSpecialFeatures(cfbInfo->features);
|
osViSetSpecialFeatures(cfbInfo->viFeatures);
|
||||||
osViSetXScale(cfbInfo->xScale);
|
osViSetXScale(cfbInfo->xScale);
|
||||||
osViSetYScale(cfbInfo->yScale);
|
osViSetYScale(cfbInfo->yScale);
|
||||||
cfbInfo->viMode = NULL;
|
cfbInfo->viMode = NULL;
|
||||||
|
@ -44,21 +47,21 @@ void Sched_SwapFramebuffer(CfbInfo* cfbInfo) {
|
||||||
cfbInfo->unk_10 = 0;
|
cfbInfo->unk_10 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sched_RetraceUpdateFramebuffer(SchedContext* sched, CfbInfo* cfbInfo) {
|
void Sched_SwapFramebuffer(Scheduler* sched, CfbInfo* cfbInfo) {
|
||||||
if (sched->shouldUpdateVi) {
|
if (sched->isFirstSwap) {
|
||||||
sched->shouldUpdateVi = false;
|
sched->isFirstSwap = false;
|
||||||
|
|
||||||
if (gIrqMgrResetStatus == 0) {
|
if (gIrqMgrResetStatus == IRQ_RESET_STATUS_IDLE) {
|
||||||
ViConfig_UpdateVi(false);
|
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);
|
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
|
* 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.
|
* 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;
|
s32 i;
|
||||||
|
|
||||||
// AUDIO SP Cancel
|
// AUDIO SP Cancel
|
||||||
|
@ -99,7 +102,7 @@ void Sched_HandleAudioCancel(SchedContext* sched) {
|
||||||
}
|
}
|
||||||
|
|
||||||
send_mesg:
|
send_mesg:
|
||||||
osSendMesg(&sched->interruptQ, (OSMesg)RSP_DONE_MSG, OS_MESG_NOBLOCK);
|
osSendMesg(&sched->interruptQueue, (OSMesg)RSP_DONE_MSG, OS_MESG_NOBLOCK);
|
||||||
return;
|
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
|
* If there is an RDP task, the output buffer will be cleared and the scheduler will send
|
||||||
* an RDP_DONE_MSG back to itself.
|
* an RDP_DONE_MSG back to itself.
|
||||||
*/
|
*/
|
||||||
void Sched_HandleGfxCancel(SchedContext* sched) {
|
void Sched_HandleGfxCancel(Scheduler* sched) {
|
||||||
s32 i;
|
s32 i;
|
||||||
|
|
||||||
// GRAPH SP Cancel
|
// GRAPH SP Cancel
|
||||||
|
@ -162,7 +165,7 @@ void Sched_HandleGfxCancel(SchedContext* sched) {
|
||||||
}
|
}
|
||||||
|
|
||||||
send_mesg:
|
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;
|
goto halt_rdp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,15 +194,15 @@ halt_rdp:
|
||||||
// Try to stop DP
|
// Try to stop DP
|
||||||
osSyncPrintf("DP止めようとします\n");
|
osSyncPrintf("DP止めようとします\n");
|
||||||
bzero(dpTask->outputBuff, (uintptr_t)dpTask->outputBuffSize - (uintptr_t)dpTask->outputBuff);
|
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;
|
s32 type = task->list.t.type;
|
||||||
|
|
||||||
if (type == M_AUDTASK) {
|
if (type == M_AUDTASK) {
|
||||||
|
@ -221,7 +224,7 @@ void Sched_QueueTask(SchedContext* sched, OSScTask* task) {
|
||||||
task->state = task->flags & OS_SC_RCP_MASK;
|
task->state = task->flags & OS_SC_RCP_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sched_Yield(SchedContext* sched) {
|
void Sched_Yield(Scheduler* sched) {
|
||||||
// Don't yield audio tasks
|
// Don't yield audio tasks
|
||||||
if (sched->curRSPTask->list.t.type == M_AUDTASK) {
|
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
|
// 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* nextFB = osViGetNextFramebuffer();
|
||||||
void* curFB = osViGetCurrentFramebuffer();
|
void* curFB = osViGetCurrentFramebuffer();
|
||||||
|
|
||||||
if ((task == NULL) || (sched->pendingSwapBuf1 != NULL) ||
|
if ((task == NULL) || (sched->pendingSwapBuf1 != NULL) ||
|
||||||
((curFB == TASK_FRAMEBUFFER(task)->fb1) && (curFB != nextFB))) {
|
((curFB == TASK_FRAMEBUFFER(task)->framebuffer) && (curFB != nextFB))) {
|
||||||
return 0;
|
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 Sched_Schedule(Scheduler* sched, OSScTask** spTask, OSScTask** dpTask, s32 state) {
|
||||||
s32 ret = state;
|
s32 nextState = state;
|
||||||
OSScTask* gfxTask = sched->gfxListHead;
|
OSScTask* gfxTask = sched->gfxListHead;
|
||||||
OSScTask* audioTask = sched->audioListHead;
|
OSScTask* audioTask = sched->audioListHead;
|
||||||
|
|
||||||
if ((ret & OS_SC_SP) && (sched->audioListHead != NULL)) {
|
if ((state & OS_SC_SP) && (sched->audioListHead != NULL)) {
|
||||||
*spTask = audioTask;
|
*spTask = audioTask;
|
||||||
ret &= ~OS_SC_SP;
|
nextState &= ~OS_SC_SP;
|
||||||
sched->audioListHead = sched->audioListHead->next;
|
sched->audioListHead = sched->audioListHead->next;
|
||||||
if (sched->audioListHead == NULL) {
|
if (sched->audioListHead == NULL) {
|
||||||
sched->audioListTail = NULL;
|
sched->audioListTail = NULL;
|
||||||
}
|
}
|
||||||
} else if (gfxTask != NULL) {
|
} else if (gfxTask != NULL) {
|
||||||
if ((gfxTask->state & OS_SC_YIELDED) || !(gfxTask->flags & OS_SC_NEEDS_RDP)) {
|
if ((gfxTask->state & OS_SC_YIELDED) || !(gfxTask->flags & OS_SC_NEEDS_RDP)) {
|
||||||
if (ret & OS_SC_SP) {
|
if (state & OS_SC_SP) {
|
||||||
*spTask = gfxTask;
|
*spTask = gfxTask;
|
||||||
ret &= ~OS_SC_SP;
|
nextState &= ~OS_SC_SP;
|
||||||
sched->gfxListHead = sched->gfxListHead->next;
|
sched->gfxListHead = sched->gfxListHead->next;
|
||||||
if (sched->gfxListHead == NULL) {
|
if (sched->gfxListHead == NULL) {
|
||||||
sched->gfxListTail = NULL;
|
sched->gfxListTail = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (ret == (OS_SC_SP | OS_SC_DP)) {
|
} else if (state == (OS_SC_SP | OS_SC_DP)) {
|
||||||
if ((TASK_FRAMEBUFFER(gfxTask) == NULL) || Sched_TaskCheckFramebuffers(sched, gfxTask)) {
|
if ((TASK_FRAMEBUFFER(gfxTask) == NULL) || Sched_TaskFramebuffersValid(sched, gfxTask)) {
|
||||||
*spTask = *dpTask = gfxTask;
|
*spTask = *dpTask = gfxTask;
|
||||||
ret &= ~(OS_SC_SP | OS_SC_DP);
|
nextState &= ~(OS_SC_SP | OS_SC_DP);
|
||||||
sched->gfxListHead = sched->gfxListHead->next;
|
sched->gfxListHead = sched->gfxListHead->next;
|
||||||
if (sched->gfxListHead == NULL) {
|
if (sched->gfxListHead == NULL) {
|
||||||
sched->gfxListTail = NULL;
|
sched->gfxListTail = NULL;
|
||||||
|
@ -279,36 +292,49 @@ s32 Sched_Schedule(SchedContext* sched, OSScTask** spTask, OSScTask** dpTask, s3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return nextState;
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the task has been marked as completed, notify the sender through the task's
|
* Sets the next framebuffer to the framebuffer associated to `task`.
|
||||||
* associated message queue (if it has one) that the task has been completed. If the task
|
* If there is no current buffer or it is time to swap, this buffer will be swapped to
|
||||||
* flags dictate it should swap the framebuffer, do so.
|
* 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->state & (OS_SC_DP | OS_SC_SP))) {
|
||||||
if (task->msgQ != NULL) {
|
if (task->msgQ != NULL) {
|
||||||
osSendMesg(task->msgQ, task->msg, OS_MESG_BLOCK);
|
osSendMesg(task->msgQ, task->msg, OS_MESG_BLOCK);
|
||||||
}
|
}
|
||||||
if (task->flags & OS_SC_SWAPBUFFER) {
|
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 != NULL) {
|
||||||
if (spTask->list.t.type == M_NULTASK) {
|
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;
|
spTask->state &= ~OS_SC_DP;
|
||||||
sched->curRDPTask = NULL;
|
sched->curRDPTask = NULL;
|
||||||
}
|
}
|
||||||
Sched_NotifyDone(sched, spTask);
|
Sched_TaskComplete(sched, spTask);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Write back the data cache to ensure imminent SP DMA does not miss anything
|
// 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) {
|
void Sched_HandleNotify(Scheduler* sched) {
|
||||||
OSScTask* spTask = NULL;
|
OSScTask* nextRSP = NULL;
|
||||||
OSScTask* dpTask = NULL;
|
OSScTask* nextRDP = NULL;
|
||||||
OSMesg msg = NULL;
|
OSScTask* task = NULL;
|
||||||
s32 state;
|
s32 state;
|
||||||
|
|
||||||
// Fetch and enqueue waiting tasks
|
// Fetch and enqueue waiting tasks
|
||||||
while (osRecvMesg(&sched->cmdQ, &msg, OS_MESG_NOBLOCK) != -1) {
|
while (osRecvMesg(&sched->cmdQueue, (OSMesg*)&task, OS_MESG_NOBLOCK) != -1) {
|
||||||
Sched_QueueTask(sched, msg);
|
Sched_QueueTask(sched, task);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is an audio task pending and an RSP task is running, yield the current 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)) {
|
if ((sched->audioListHead != NULL) && (sched->curRSPTask != NULL)) {
|
||||||
Sched_Yield(sched);
|
Sched_Yield(sched);
|
||||||
|
@ -384,12 +413,12 @@ void Sched_HandleEntry(SchedContext* sched) {
|
||||||
}
|
}
|
||||||
// Schedule and run the next task
|
// Schedule and run the next task
|
||||||
state = ((sched->curRSPTask == NULL) << 1) | (sched->curRDPTask == NULL);
|
state = ((sched->curRSPTask == NULL) << 1) | (sched->curRDPTask == NULL);
|
||||||
if (Sched_Schedule(sched, &spTask, &dpTask, state) != state) {
|
if (Sched_Schedule(sched, &nextRSP, &nextRDP, state) != state) {
|
||||||
Sched_RunTask(sched, spTask, dpTask);
|
Sched_RunTask(sched, nextRSP, nextRDP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sched_HandleRetrace(SchedContext* sched) {
|
void Sched_HandleRetrace(Scheduler* sched) {
|
||||||
ViConfig_UpdateBlack();
|
ViConfig_UpdateBlack();
|
||||||
sched->retraceCount++;
|
sched->retraceCount++;
|
||||||
|
|
||||||
|
@ -404,23 +433,29 @@ void Sched_HandleRetrace(SchedContext* sched) {
|
||||||
sched->curBuf = sched->pendingSwapBuf1;
|
sched->curBuf = sched->pendingSwapBuf1;
|
||||||
sched->pendingSwapBuf1 = NULL;
|
sched->pendingSwapBuf1 = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sched->curBuf != NULL) {
|
if (sched->curBuf != NULL) {
|
||||||
if (sched->curBuf->updateRate2 > 0) {
|
if (sched->curBuf->updateTimer > 0) {
|
||||||
sched->curBuf->updateRate2--;
|
sched->curBuf->updateTimer--;
|
||||||
}
|
}
|
||||||
if ((sched->curBuf->updateRate2 <= 0) && (sched->pendingSwapBuf1 != NULL)) {
|
if ((sched->curBuf->updateTimer <= 0) && (sched->pendingSwapBuf1 != NULL)) {
|
||||||
Sched_RetraceUpdateFramebuffer(sched, sched->pendingSwapBuf1);
|
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* curRSP;
|
||||||
OSScTask* nextRSP = NULL;
|
OSScTask* nextRSP = NULL;
|
||||||
OSScTask* nextRDP = NULL;
|
OSScTask* nextRDP = NULL;
|
||||||
s32 state;
|
s32 state;
|
||||||
u64 time;
|
OSTime time;
|
||||||
|
|
||||||
if (sched->curRSPTask == NULL) {
|
if (sched->curRSPTask == NULL) {
|
||||||
osSyncPrintf("__scHandleRSP:sc->curRSPTask == NULL\n");
|
osSyncPrintf("__scHandleRSP:sc->curRSPTask == NULL\n");
|
||||||
|
@ -464,7 +499,7 @@ void Sched_HandleRSPDone(SchedContext* sched) {
|
||||||
} else {
|
} else {
|
||||||
// Mark task completed
|
// Mark task completed
|
||||||
curRSP->state &= ~OS_SC_SP;
|
curRSP->state &= ~OS_SC_SP;
|
||||||
Sched_NotifyDone(sched, curRSP);
|
Sched_TaskComplete(sched, curRSP);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schedule and run next task
|
// 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* curRDP;
|
||||||
OSScTask* nextRSP = NULL;
|
OSScTask* nextRSP = NULL;
|
||||||
OSScTask* nextRDP = NULL;
|
OSScTask* nextRDP = NULL;
|
||||||
|
@ -493,7 +531,7 @@ void Sched_HandleRDPDone(SchedContext* sched) {
|
||||||
sched->curRDPTask = NULL;
|
sched->curRDPTask = NULL;
|
||||||
curRDP->state &= ~OS_SC_DP;
|
curRDP->state &= ~OS_SC_DP;
|
||||||
|
|
||||||
Sched_NotifyDone(sched, curRDP);
|
Sched_TaskComplete(sched, curRDP);
|
||||||
|
|
||||||
// Schedule and run next task
|
// Schedule and run next task
|
||||||
state = ((sched->curRSPTask == NULL) << 1) | (sched->curRDPTask == NULL);
|
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
|
* Called by other threads in order to wake the scheduler up immediately to enqueue and
|
||||||
* been sent down the command queue.
|
* 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) {
|
void Sched_SendNotifyMsg(Scheduler* sched) {
|
||||||
osSendMesg(&sched->interruptQ, (OSMesg)ENTRY_MSG, OS_MESG_BLOCK);
|
osSendMesg(&sched->interruptQueue, (OSMesg)NOTIFY_MSG, OS_MESG_BLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a message to the scheduler to inform it that it should attempt
|
* Sends a message to the scheduler to inform it that it should attempt
|
||||||
* to stop the last dispatched audio task.
|
* to stop the last dispatched audio task.
|
||||||
*/
|
*/
|
||||||
void Sched_SendAudioCancelMsg(SchedContext* sched) {
|
void Sched_SendAudioCancelMsg(Scheduler* sched) {
|
||||||
osSendMesg(&sched->interruptQ, (OSMesg)RDP_AUDIO_CANCEL_MSG, OS_MESG_BLOCK);
|
osSendMesg(&sched->interruptQueue, (OSMesg)RDP_AUDIO_CANCEL_MSG, OS_MESG_BLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a message to the scheduler to inform it that it should attempt
|
* Sends a message to the scheduler to inform it that it should attempt
|
||||||
* to stop the last dispatched gfx task.
|
* to stop the last dispatched gfx task.
|
||||||
*/
|
*/
|
||||||
void Sched_SendGfxCancelMsg(SchedContext* sched) {
|
void Sched_SendGfxCancelMsg(Scheduler* sched) {
|
||||||
osSendMesg(&sched->interruptQ, (OSMesg)RSP_GFX_CANCEL_MSG, OS_MESG_BLOCK);
|
osSendMesg(&sched->interruptQueue, (OSMesg)RSP_GFX_CANCEL_MSG, OS_MESG_BLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fault Client for the scheduler. Reports information about the state of the scheduler
|
* Fault Client for the scheduler. Reports information about the state of the scheduler
|
||||||
* and any current tasks in the crash debugger.
|
* and any current tasks in the crash debugger.
|
||||||
*/
|
*/
|
||||||
void Sched_FaultClient(void* param1, void* param2) {
|
void Sched_FaultClient(void* arg0, void* arg1) {
|
||||||
SchedContext* sched = (SchedContext*)param1;
|
Scheduler* sched = (Scheduler*)arg0;
|
||||||
OSScTask* spTask;
|
OSScTask* spTask;
|
||||||
OSScTask* dpTask;
|
OSScTask* dpTask;
|
||||||
|
|
||||||
|
@ -559,10 +600,10 @@ void Sched_FaultClient(void* param1, void* param2) {
|
||||||
*/
|
*/
|
||||||
void Sched_ThreadEntry(void* arg) {
|
void Sched_ThreadEntry(void* arg) {
|
||||||
s32 msg = 0;
|
s32 msg = 0;
|
||||||
SchedContext* sched = (SchedContext*)arg;
|
Scheduler* sched = (Scheduler*)arg;
|
||||||
|
|
||||||
while (true) {
|
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
|
// Check if it's a message from another thread or the OS
|
||||||
switch (msg) {
|
switch (msg) {
|
||||||
|
@ -574,8 +615,8 @@ void Sched_ThreadEntry(void* arg) {
|
||||||
Sched_HandleGfxCancel(sched);
|
Sched_HandleGfxCancel(sched);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case ENTRY_MSG:
|
case NOTIFY_MSG:
|
||||||
Sched_HandleEntry(sched);
|
Sched_HandleNotify(sched);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case RSP_DONE_MSG:
|
case RSP_DONE_MSG:
|
||||||
|
@ -594,31 +635,31 @@ void Sched_ThreadEntry(void* arg) {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case OS_SC_PRE_NMI_MSG:
|
case OS_SC_PRE_NMI_MSG:
|
||||||
Sched_HandleReset(sched);
|
Sched_HandlePreNMI(sched);
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case OS_SC_NMI_MSG:
|
case OS_SC_NMI_MSG:
|
||||||
Sched_HandleStop(sched);
|
Sched_HandleNMI(sched);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the SchedContext and scheduler thread.
|
* Initializes the Scheduler and scheduler thread.
|
||||||
* Registers an IrqClient for the thread and fault client for the SchedContext.
|
* Registers an IrqClient for the thread and fault client for the Scheduler.
|
||||||
* Directs the OS to send SP and DP OS messages to interruptQ when the RSP or RDP signal task completion.
|
* 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) {
|
void Sched_Init(Scheduler* sched, void* stack, OSPri pri, u8 viModeType, UNK_TYPE arg4, IrqMgr* irqMgr) {
|
||||||
bzero(sched, sizeof(SchedContext));
|
bzero(sched, sizeof(Scheduler));
|
||||||
|
|
||||||
sched->shouldUpdateVi = true;
|
sched->isFirstSwap = true;
|
||||||
|
|
||||||
osCreateMesgQueue(&sched->interruptQ, sched->intBuf, ARRAY_COUNT(sched->intBuf));
|
osCreateMesgQueue(&sched->interruptQueue, sched->interruptMsgBuf, ARRAY_COUNT(sched->interruptMsgBuf));
|
||||||
osCreateMesgQueue(&sched->cmdQ, sched->cmdMsgBuf, ARRAY_COUNT(sched->cmdMsgBuf));
|
osCreateMesgQueue(&sched->cmdQueue, sched->cmdMsgBuf, ARRAY_COUNT(sched->cmdMsgBuf));
|
||||||
osSetEventMesg(OS_EVENT_SP, &sched->interruptQ, (OSMesg)RSP_DONE_MSG);
|
osSetEventMesg(OS_EVENT_SP, &sched->interruptQueue, (OSMesg)RSP_DONE_MSG);
|
||||||
osSetEventMesg(OS_EVENT_DP, &sched->interruptQ, (OSMesg)RDP_DONE_MSG);
|
osSetEventMesg(OS_EVENT_DP, &sched->interruptQueue, (OSMesg)RDP_DONE_MSG);
|
||||||
IrqMgr_AddClient(irqMgr, &sched->irqClient, &sched->interruptQ);
|
IrqMgr_AddClient(irqMgr, &sched->irqClient, &sched->interruptQueue);
|
||||||
Fault_AddClient(&sSchedFaultClient, Sched_FaultClient, sched, NULL);
|
Fault_AddClient(&sSchedFaultClient, Sched_FaultClient, sched, NULL);
|
||||||
osCreateThread(&sched->thread, Z_THREAD_ID_SCHED, Sched_ThreadEntry, sched, stack, pri);
|
osCreateThread(&sched->thread, Z_THREAD_ID_SCHED, Sched_ThreadEntry, sched, stack, pri);
|
||||||
osStartThread(&sched->thread);
|
osStartThread(&sched->thread);
|
||||||
|
|
|
@ -65,8 +65,8 @@ void Jpeg_ScheduleDecoderTask(JpegContext* jpegCtx) {
|
||||||
jpegCtx->scTask.framebuffer = NULL;
|
jpegCtx->scTask.framebuffer = NULL;
|
||||||
jpegCtx->scTask.list.t = sJpegTask;
|
jpegCtx->scTask.list.t = sJpegTask;
|
||||||
|
|
||||||
osSendMesg(&gSchedContext.cmdQ, (OSMesg*)&jpegCtx->scTask, OS_MESG_BLOCK);
|
osSendMesg(&gScheduler.cmdQueue, (OSMesg*)&jpegCtx->scTask, OS_MESG_BLOCK);
|
||||||
Sched_SendEntryMsg(&gSchedContext); // osScKickEntryMsg
|
Sched_SendNotifyMsg(&gScheduler); // osScKickEntryMsg
|
||||||
osRecvMesg(&jpegCtx->mq, NULL, OS_MESG_BLOCK);
|
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);
|
osCreateMesgQueue(&jpegCtx.mq, &jpegCtx.msg, 1);
|
||||||
MsgEvent_SendNullTask();
|
Sched_FlushTaskQueue();
|
||||||
|
|
||||||
jpegCtx.workBuf = workBuff;
|
jpegCtx.workBuf = workBuff;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -371,7 +371,7 @@ void Play_Destroy(GameState* thisx) {
|
||||||
GraphicsContext* gfxCtx = this->state.gfxCtx;
|
GraphicsContext* gfxCtx = this->state.gfxCtx;
|
||||||
|
|
||||||
if (sBombersNotebookOpen) {
|
if (sBombersNotebookOpen) {
|
||||||
MsgEvent_SendNullTask();
|
Sched_FlushTaskQueue();
|
||||||
SysCfb_SetLoResMode();
|
SysCfb_SetLoResMode();
|
||||||
gfxCtx->curFrameBuffer = SysCfb_GetFramebuffer(gfxCtx->framebufferIndex % 2);
|
gfxCtx->curFrameBuffer = SysCfb_GetFramebuffer(gfxCtx->framebufferIndex % 2);
|
||||||
gfxCtx->zbuffer = SysCfb_GetZBuffer();
|
gfxCtx->zbuffer = SysCfb_GetZBuffer();
|
||||||
|
@ -928,7 +928,7 @@ void Play_UpdateMain(PlayState* this) {
|
||||||
|
|
||||||
if (R_PICTO_PHOTO_STATE == PICTO_PHOTO_STATE_PROCESS) {
|
if (R_PICTO_PHOTO_STATE == PICTO_PHOTO_STATE_PROCESS) {
|
||||||
R_PICTO_PHOTO_STATE = PICTO_PHOTO_STATE_READY;
|
R_PICTO_PHOTO_STATE = PICTO_PHOTO_STATE_READY;
|
||||||
MsgEvent_SendNullTask();
|
Sched_FlushTaskQueue();
|
||||||
Play_TakePictoPhoto(&this->pauseBgPreRender);
|
Play_TakePictoPhoto(&this->pauseBgPreRender);
|
||||||
R_PICTO_PHOTO_STATE = PICTO_PHOTO_STATE_OFF;
|
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) ||
|
} 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_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;
|
sBombersNotebookOpen = false;
|
||||||
this->pauseCtx.bombersNotebookOpen = false;
|
this->pauseCtx.bombersNotebookOpen = false;
|
||||||
sBombersNotebook.loadState = BOMBERS_NOTEBOOK_LOAD_STATE_NONE;
|
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);
|
PreRender_SetValues(&this->pauseBgPreRender, gCfbWidth, gCfbHeight, gfxCtx->curFrameBuffer, gfxCtx->zbuffer);
|
||||||
|
|
||||||
if (R_PAUSE_BG_PRERENDER_STATE == PAUSE_BG_PRERENDER_PROCESS) {
|
if (R_PAUSE_BG_PRERENDER_STATE == PAUSE_BG_PRERENDER_PROCESS) {
|
||||||
MsgEvent_SendNullTask();
|
Sched_FlushTaskQueue();
|
||||||
if (!gSaveContext.screenScaleFlag) {
|
if (!gSaveContext.screenScaleFlag) {
|
||||||
PreRender_ApplyFiltersSlowlyInit(&this->pauseBgPreRender);
|
PreRender_ApplyFiltersSlowlyInit(&this->pauseBgPreRender);
|
||||||
}
|
}
|
||||||
|
@ -1448,7 +1449,7 @@ void Play_Draw(PlayState* this) {
|
||||||
|
|
||||||
if (sBombersNotebookOpen) {
|
if (sBombersNotebookOpen) {
|
||||||
if (gSysCfbHiResEnabled != 1) {
|
if (gSysCfbHiResEnabled != 1) {
|
||||||
MsgEvent_SendNullTask();
|
Sched_FlushTaskQueue();
|
||||||
SysCfb_SetHiResMode();
|
SysCfb_SetHiResMode();
|
||||||
gfxCtx2->curFrameBuffer = SysCfb_GetFramebuffer(gfxCtx2->framebufferIndex % 2);
|
gfxCtx2->curFrameBuffer = SysCfb_GetFramebuffer(gfxCtx2->framebufferIndex % 2);
|
||||||
gfxCtx2->zbuffer = SysCfb_GetZBuffer();
|
gfxCtx2->zbuffer = SysCfb_GetZBuffer();
|
||||||
|
@ -1460,7 +1461,7 @@ void Play_Draw(PlayState* this) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (gSysCfbHiResEnabled != 0) {
|
if (gSysCfbHiResEnabled != 0) {
|
||||||
MsgEvent_SendNullTask();
|
Sched_FlushTaskQueue();
|
||||||
SysCfb_SetLoResMode();
|
SysCfb_SetLoResMode();
|
||||||
gfxCtx2->curFrameBuffer = SysCfb_GetFramebuffer(gfxCtx2->framebufferIndex % 2);
|
gfxCtx2->curFrameBuffer = SysCfb_GetFramebuffer(gfxCtx2->framebufferIndex % 2);
|
||||||
gfxCtx2->zbuffer = SysCfb_GetZBuffer();
|
gfxCtx2->zbuffer = SysCfb_GetZBuffer();
|
||||||
|
|
|
@ -3599,7 +3599,7 @@ void KaleidoScope_Update(PlayState* play) {
|
||||||
Interface_UpdateButtonsPart2(play);
|
Interface_UpdateButtonsPart2(play);
|
||||||
gSaveContext.hudVisibility = HUD_VISIBILITY_IDLE;
|
gSaveContext.hudVisibility = HUD_VISIBILITY_IDLE;
|
||||||
Interface_SetHudVisibility(HUD_VISIBILITY_ALL);
|
Interface_SetHudVisibility(HUD_VISIBILITY_ALL);
|
||||||
MsgEvent_SendNullTask();
|
Sched_FlushTaskQueue();
|
||||||
Skybox_Reload(play, &play->skyboxCtx, play->skyboxId);
|
Skybox_Reload(play, &play->skyboxCtx, play->skyboxId);
|
||||||
|
|
||||||
if ((msgCtx->msgMode != MSGMODE_NONE) && (msgCtx->currentTextId == 0xFF)) {
|
if ((msgCtx->msgMode != MSGMODE_NONE) && (msgCtx->currentTextId == 0xFF)) {
|
||||||
|
|
|
@ -403,7 +403,7 @@
|
||||||
0x8010A000 : "z_map_exp",
|
0x8010A000 : "z_map_exp",
|
||||||
0x8010A760 : "z_msgevent",
|
0x8010A760 : "z_msgevent",
|
||||||
0x8010C0C0 : "z_nmi_buff",
|
0x8010C0C0 : "z_nmi_buff",
|
||||||
0x8010C1B0 : "code_8010C1B0",
|
0x8010C1B0 : "z_nulltask",
|
||||||
0x8010C230 : "z_olib",
|
0x8010C230 : "z_olib",
|
||||||
0x8010CB70 : "[PADDING]",
|
0x8010CB70 : "[PADDING]",
|
||||||
0x8010CB80 : "z_parameter",
|
0x8010CB80 : "z_parameter",
|
||||||
|
|
|
@ -30,10 +30,10 @@
|
||||||
0x80081178:("Yaz0_Decompress",),
|
0x80081178:("Yaz0_Decompress",),
|
||||||
0x80081250:("IrqMgr_AddClient",),
|
0x80081250:("IrqMgr_AddClient",),
|
||||||
0x800812DC:("IrqMgr_RemoveClient",),
|
0x800812DC:("IrqMgr_RemoveClient",),
|
||||||
0x80081368:("IrqMgr_SendMesgForClient",),
|
0x80081368:("IrqMgr_SendMesgToClients",),
|
||||||
0x800813B8:("IrqMgr_JamMesgForClient",),
|
0x800813B8:("IrqMgr_JamMesgToClients",),
|
||||||
0x8008141C:("IrqMgr_HandlePreNMI",),
|
0x8008141C:("IrqMgr_HandlePreNMI",),
|
||||||
0x800814B4:("IrqMgr_CheckStack",),
|
0x800814B4:("IrqMgr_CheckStacks",),
|
||||||
0x800814D4:("IrqMgr_HandlePRENMI450",),
|
0x800814D4:("IrqMgr_HandlePRENMI450",),
|
||||||
0x80081550:("IrqMgr_HandlePRENMI480",),
|
0x80081550:("IrqMgr_HandlePRENMI480",),
|
||||||
0x800815A8:("IrqMgr_HandlePRENMI500",),
|
0x800815A8:("IrqMgr_HandlePRENMI500",),
|
||||||
|
@ -2064,7 +2064,7 @@
|
||||||
0x8010C0C0:("Nmi_Init",),
|
0x8010C0C0:("Nmi_Init",),
|
||||||
0x8010C164:("Nmi_SetPrenmiStart",),
|
0x8010C164:("Nmi_SetPrenmiStart",),
|
||||||
0x8010C19C:("Nmi_GetPrenmiHasStarted",),
|
0x8010C19C:("Nmi_GetPrenmiHasStarted",),
|
||||||
0x8010C1B0:("MsgEvent_SendNullTask",),
|
0x8010C1B0:("Sched_FlushTaskQueue",),
|
||||||
0x8010C230:("OLib_Vec3fDist",),
|
0x8010C230:("OLib_Vec3fDist",),
|
||||||
0x8010C274:("OLib_Vec3fDistOutDiff",),
|
0x8010C274:("OLib_Vec3fDistOutDiff",),
|
||||||
0x8010C2D0:("OLib_Vec3fDistXZ",),
|
0x8010C2D0:("OLib_Vec3fDistXZ",),
|
||||||
|
@ -3192,24 +3192,24 @@
|
||||||
0x80175FD4:("PadMgr_GetInput2",),
|
0x80175FD4:("PadMgr_GetInput2",),
|
||||||
0x80176010:("PadMgr_ThreadEntry",),
|
0x80176010:("PadMgr_ThreadEntry",),
|
||||||
0x80176194:("PadMgr_Init",),
|
0x80176194:("PadMgr_Init",),
|
||||||
0x80176280:("Sched_SwapFramebuffer",),
|
0x80176280:("Sched_SwapFramebufferImpl",),
|
||||||
0x80176314:("Sched_RetraceUpdateFramebuffer",),
|
0x80176314:("Sched_SwapFramebuffer",),
|
||||||
0x80176364:("Sched_HandleReset",),
|
0x80176364:("Sched_HandlePreNMI",),
|
||||||
0x80176370:("Sched_HandleStop",),
|
0x80176370:("Sched_HandleNMI",),
|
||||||
0x80176394:("Sched_HandleAudioCancel",),
|
0x80176394:("Sched_HandleAudioCancel",),
|
||||||
0x801764F0:("Sched_HandleGfxCancel",),
|
0x801764F0:("Sched_HandleGfxCancel",),
|
||||||
0x8017668C:("Sched_QueueTask",),
|
0x8017668C:("Sched_QueueTask",),
|
||||||
0x801766F0:("Sched_Yield",),
|
0x801766F0:("Sched_Yield",),
|
||||||
0x80176748:("Sched_TaskCheckFramebuffers",),
|
0x80176748:("Sched_CheckTaskFramebuffers",),
|
||||||
0x801767B8:("Sched_Schedule",),
|
0x801767B8:("Sched_Schedule",),
|
||||||
0x801768E0:("Sched_TaskUpdateFramebuffer",),
|
0x801768E0:("Sched_SetNextFramebufferFromTask",),
|
||||||
0x8017691C:("Sched_NotifyDone",),
|
0x8017691C:("Sched_TaskComplete",),
|
||||||
0x80176988:("Sched_RunTask",),
|
0x80176988:("Sched_RunTask",),
|
||||||
0x80176B34:("Sched_HandleEntry",),
|
0x80176B34:("Sched_HandleNotify",),
|
||||||
0x80176C24:("Sched_HandleRetrace",),
|
0x80176C24:("Sched_HandleRetrace",),
|
||||||
0x80176CF4:("Sched_HandleRSPDone",),
|
0x80176CF4:("Sched_HandleRSPDone",),
|
||||||
0x80176F2C:("Sched_HandleRDPDone",),
|
0x80176F2C:("Sched_HandleRDPDone",),
|
||||||
0x80177018:("Sched_SendEntryMsg",),
|
0x80177018:("Sched_SendNotifyMsg",),
|
||||||
0x8017703C:("Sched_SendAudioCancelMsg",),
|
0x8017703C:("Sched_SendAudioCancelMsg",),
|
||||||
0x80177060:("Sched_SendGfxCancelMsg",),
|
0x80177060:("Sched_SendGfxCancelMsg",),
|
||||||
0x80177084:("Sched_FaultClient",),
|
0x80177084:("Sched_FaultClient",),
|
||||||
|
|
|
@ -3996,7 +3996,7 @@
|
||||||
0x801F8160:("sSerialEventQueue","OSMesgQueue","",0x18),
|
0x801F8160:("sSerialEventQueue","OSMesgQueue","",0x18),
|
||||||
0x801F8178:("sSerialMsgBuf","OSMesg","[1]",0x4),
|
0x801F8178:("sSerialMsgBuf","OSMesg","[1]",0x4),
|
||||||
0x801F8180:("gSegments","u32","[16]",0x40),
|
0x801F8180:("gSegments","u32","[16]",0x40),
|
||||||
0x801F81C0:("gSchedContext","SchedContext","",0x338),
|
0x801F81C0:("gScheduler","Scheduler","",0x338),
|
||||||
0x801F84F8:("sIrqClient","IrqMgrClient","",0x8),
|
0x801F84F8:("sIrqClient","IrqMgrClient","",0x8),
|
||||||
0x801F8500:("sIrqMgrMsgQueue","OSMesgQueue","",0x18),
|
0x801F8500:("sIrqMgrMsgQueue","OSMesgQueue","",0x18),
|
||||||
0x801F8518:("sIrqMgrMsgBuf","OSMesg","[60]",0xf0),
|
0x801F8518:("sIrqMgrMsgBuf","OSMesg","[60]",0xf0),
|
||||||
|
|
|
@ -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/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_AddClient.s,IrqMgr_AddClient,0x80081250,0x23
|
||||||
asm/non_matchings/boot/irqmgr/IrqMgr_RemoveClient.s,IrqMgr_RemoveClient,0x800812DC,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_SendMesgToClients.s,IrqMgr_SendMesgToClients,0x80081368,0x14
|
||||||
asm/non_matchings/boot/irqmgr/IrqMgr_JamMesgForClient.s,IrqMgr_JamMesgForClient,0x800813B8,0x19
|
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_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_HandlePRENMI450.s,IrqMgr_HandlePRENMI450,0x800814D4,0x1F
|
||||||
asm/non_matchings/boot/irqmgr/IrqMgr_HandlePRENMI480.s,IrqMgr_HandlePRENMI480,0x80081550,0x16
|
asm/non_matchings/boot/irqmgr/IrqMgr_HandlePRENMI480.s,IrqMgr_HandlePRENMI480,0x80081550,0x16
|
||||||
asm/non_matchings/boot/irqmgr/IrqMgr_HandlePRENMI500.s,IrqMgr_HandlePRENMI500,0x800815A8,0x9
|
asm/non_matchings/boot/irqmgr/IrqMgr_HandlePRENMI500.s,IrqMgr_HandlePRENMI500,0x800815A8,0x9
|
||||||
|
|
|
|
@ -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_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_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/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_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_Vec3fDistOutDiff.s,OLib_Vec3fDistOutDiff,0x8010C274,0x17
|
||||||
asm/non_matchings/code/z_olib/OLib_Vec3fDistXZ.s,OLib_Vec3fDistXZ,0x8010C2D0,0xD
|
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_ThreadEntry.s,PadMgr_ThreadEntry,0x80176010,0x61
|
||||||
asm/non_matchings/code/padmgr/PadMgr_Init.s,PadMgr_Init,0x80176194,0x3B
|
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_SwapFramebuffer.s,Sched_SwapFramebuffer,0x80176280,0x25
|
||||||
asm/non_matchings/code/sched/Sched_RetraceUpdateFramebuffer.s,Sched_RetraceUpdateFramebuffer,0x80176314,0x14
|
asm/non_matchings/code/sched/Sched_SwapFramebuffer.s,Sched_SwapFramebuffer,0x80176314,0x14
|
||||||
asm/non_matchings/code/sched/Sched_HandleReset.s,Sched_HandleReset,0x80176364,0x3
|
asm/non_matchings/code/sched/Sched_HandlePreNMI.s,Sched_HandlePreNMI,0x80176364,0x3
|
||||||
asm/non_matchings/code/sched/Sched_HandleStop.s,Sched_HandleStop,0x80176370,0x9
|
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_HandleAudioCancel.s,Sched_HandleAudioCancel,0x80176394,0x57
|
||||||
asm/non_matchings/code/sched/Sched_HandleGfxCancel.s,Sched_HandleGfxCancel,0x801764F0,0x67
|
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_QueueTask.s,Sched_QueueTask,0x8017668C,0x19
|
||||||
asm/non_matchings/code/sched/Sched_Yield.s,Sched_Yield,0x801766F0,0x16
|
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_Schedule.s,Sched_Schedule,0x801767B8,0x4A
|
||||||
asm/non_matchings/code/sched/Sched_TaskUpdateFramebuffer.s,Sched_TaskUpdateFramebuffer,0x801768E0,0xF
|
asm/non_matchings/code/sched/Sched_SetNextFramebufferFromTask.s,Sched_SetNextFramebufferFromTask,0x801768E0,0xF
|
||||||
asm/non_matchings/code/sched/Sched_NotifyDone.s,Sched_NotifyDone,0x8017691C,0x1B
|
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_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_HandleRetrace.s,Sched_HandleRetrace,0x80176C24,0x34
|
||||||
asm/non_matchings/code/sched/Sched_HandleRSPDone.s,Sched_HandleRSPDone,0x80176CF4,0x8E
|
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_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_SendAudioCancelMsg.s,Sched_SendAudioCancelMsg,0x8017703C,0x9
|
||||||
asm/non_matchings/code/sched/Sched_SendGfxCancelMsg.s,Sched_SendGfxCancelMsg,0x80177060,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
|
asm/non_matchings/code/sched/Sched_FaultClient.s,Sched_FaultClient,0x80177084,0x36
|
||||||
|
|
|
Loading…
Reference in New Issue