mirror of
https://github.com/ACreTeam/ac-decomp
synced 2026-05-23 14:41:38 -04:00
Implement irqmgr
This commit is contained in:
@@ -52,6 +52,10 @@ graph.c:
|
||||
.text: [0x80405518, 0x80405EC8]
|
||||
.data: [0x8065ECA8, 0x8065ECB0]
|
||||
.bss: [0x812F31E8, 0x812F3560]
|
||||
#irqmgr.c:
|
||||
# .text: [0x80405EC8, 0x80406480]
|
||||
# .data: [0x8065ECB0, 0x8065ECD0]
|
||||
# .bss: [0x812F3560, 0x812F4CB0]
|
||||
lb_rtc.c:
|
||||
.text: [0x80406480, 0x8040752C]
|
||||
.rodata: [0x806436F8, 0x806437A0]
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "types.h"
|
||||
#include "dolphin/os/OSAlarm.h"
|
||||
#include "dolphin/os/OSMessage.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
+21
-3
@@ -4,6 +4,7 @@
|
||||
#include "types.h"
|
||||
#include "dolphin/os/OSTime.h"
|
||||
#include "dolphin/os/OSTimer.h"
|
||||
#include "dolphin/os/OSMessage.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -31,16 +32,33 @@ typedef struct {
|
||||
irqmgr_mesg_t msgDelayPreNMI;
|
||||
OSMessageQueue _msgQueue;
|
||||
OSMessage _msgBuf[IRQMGR_MESSAGES_MAX];
|
||||
OSThread thread;
|
||||
irqmgr_client_t* clients;
|
||||
u8 prenmi;
|
||||
|
||||
union {
|
||||
OSThread thread;
|
||||
struct {
|
||||
u8 unused[sizeof(OSThread) - 2 * sizeof(void*)];
|
||||
irqmgr_client_t* clients;
|
||||
u8 prenmi;
|
||||
};
|
||||
};
|
||||
|
||||
OSTime prenmi_time;
|
||||
OSTimer timer;
|
||||
OSTime retraceTime;
|
||||
} irqmgr_t;
|
||||
|
||||
extern void irqmgr_AddClient(irqmgr_client_t* client, OSMessageQueue* msgqueue);
|
||||
/* @unused extern void irqmgr_RemoveClient(irqmgr_client_t* client) */
|
||||
extern void CreateIRQManager(void* stack, size_t stack_size, int priority, u8 retracecount);
|
||||
|
||||
/* probably declared in os_vi.h */
|
||||
extern void osViSetEvent(OSMessageQueue* mesgq, OSMessage msg, u32 retcount);
|
||||
|
||||
extern volatile int ResetStatus;
|
||||
extern volatile OSTime ResetTime;
|
||||
extern volatile OSTime RetraceTime;
|
||||
extern volatile int RetraceCount;
|
||||
extern irqmgr_t irqmgr_class;
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef LIBULTRA_OS_THREAD_H
|
||||
#define LIBULTRA_OS_THREAD_H
|
||||
|
||||
#include "types.h"
|
||||
#include "dolphin/os/OSThread.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void osCreateThread2(OSThread* t, int id, void(*entry)(void*), void* arg, void* stack_pointer, size_t stack_size, OSPriority priority);
|
||||
extern void osStartThread(OSThread* t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
#include "irqmgr.h"
|
||||
#include "libultra/os_thread.h"
|
||||
#include "dolphin/os.h"
|
||||
#include "dolphin/os/OSMessage.h"
|
||||
#include "dolphin/os/OSTime.h"
|
||||
|
||||
#define MSEC(x) OSMicrosecondsToTicks((x) * (OSTime)1000)
|
||||
|
||||
volatile int ResetStatus; // 0x00
|
||||
volatile OSTime ResetTime; // 0x08
|
||||
volatile OSTime RetraceTime; // 0x10
|
||||
volatile int RetraceCount; // 0x18
|
||||
static irqmgr_t* this; // 0x1C
|
||||
irqmgr_t irqmgr_class;
|
||||
|
||||
#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
|
||||
|
||||
/**
|
||||
* @brief Adds anew client to the IRQ manager with a callback message queue.
|
||||
*
|
||||
* @param client The new client to add
|
||||
* @param msgqueue The callback message queue
|
||||
**/
|
||||
extern void irqmgr_AddClient(irqmgr_client_t* client, OSMessageQueue* msgqueue) {
|
||||
BOOL enable = OSDisableInterrupts();
|
||||
client->msgQueue = msgqueue;
|
||||
client->next = this->clients;
|
||||
this->clients = client;
|
||||
OSRestoreInterrupts(enable);
|
||||
|
||||
if (this->prenmi >= 1) {
|
||||
osSendMesg(client->msgQueue, &this->msgPreNMI, 0);
|
||||
}
|
||||
if (this->prenmi >= 2) {
|
||||
osSendMesg(client->msgQueue, &this->msgDelayPreNMI, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* @unused extern void irqmgr_RemoveClient(irqmgr_client_t* client) */
|
||||
|
||||
/**
|
||||
* @brief Sends a new message to all active IRQ clients.
|
||||
*
|
||||
* @param msg The message which will be sent
|
||||
**/
|
||||
static void irqmgr_SendMesgForClient(irqmgr_mesg_t* msg) {
|
||||
irqmgr_client_t* i;
|
||||
OSMessageQueue* mesgq;
|
||||
for (i = this->clients; i != NULL; i = i->next) {
|
||||
mesgq = i->msgQueue;
|
||||
if (mesgq->usedCount < mesgq->msgCount) {
|
||||
osSendMesg(mesgq, msg, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends a new message to all active IRQ clients. Duplicate of above.
|
||||
*
|
||||
* @param msg The message which will be sent
|
||||
**/
|
||||
static void irqmgr_JamMesgForClient(irqmgr_mesg_t* msg) {
|
||||
irqmgr_client_t* i;
|
||||
OSMessageQueue* mesgq;
|
||||
for (i = this->clients; i != NULL; i = i->next) {
|
||||
mesgq = i->msgQueue;
|
||||
if (mesgq->usedCount < mesgq->msgCount) {
|
||||
osSendMesg(mesgq, msg, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma pool_data on
|
||||
/**
|
||||
* @brief Handler function for pre-NMI message.
|
||||
**/
|
||||
static void irqmgr_HandlePreNMI() {
|
||||
ResetStatus = 1;
|
||||
this->prenmi = 1;
|
||||
ResetTime = this->prenmi_time = osGetTime();
|
||||
|
||||
osSetTimer(&this->timer, MSEC(400), 0, &this->_msgQueue, (OSMessage)IRQ_PRENMI450_MSG);
|
||||
irqmgr_JamMesgForClient(&this->msgPreNMI);
|
||||
}
|
||||
#pragma pool_data reset
|
||||
|
||||
/**
|
||||
* @brief Handler for pre-NMI message (post 400ms).
|
||||
**/
|
||||
static void irqmgr_HandlePreNMI450() {
|
||||
ResetStatus = 2;
|
||||
this->prenmi = 2;
|
||||
osSetTimer(&this->timer, MSEC(50), 0, &this->_msgQueue, (OSMessage)IRQ_PRENMI480_MSG);
|
||||
irqmgr_SendMesgForClient(&this->msgDelayPreNMI);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handler for pre-NMI message (post 450ms).
|
||||
**/
|
||||
static void irqmgr_HandlePreNMI480() {
|
||||
osSetTimer(&this->timer, MSEC(50), 0, &this->_msgQueue, (OSMessage)IRQ_PRENMI500_MSG);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handler for pre-NMI message (post 500ms).
|
||||
**/
|
||||
static void irqmgr_HandlePreNMI500() {}
|
||||
|
||||
#pragma pool_data on
|
||||
/**
|
||||
* @brief Handler for retrace message.
|
||||
**/
|
||||
static void irqmgr_HandleRetrace() {
|
||||
OSTime time;
|
||||
if (RetraceTime == 0) {
|
||||
if (this->retraceTime == 0) {
|
||||
time = osGetTime();
|
||||
this->retraceTime = time;
|
||||
}
|
||||
else {
|
||||
time = osGetTime();
|
||||
RetraceTime = time - this->retraceTime;
|
||||
}
|
||||
}
|
||||
RetraceCount++;
|
||||
irqmgr_SendMesgForClient(&this->msgRetrace);
|
||||
}
|
||||
#pragma pool_data reset
|
||||
|
||||
/**
|
||||
* @brief Main IRQ manager handler.
|
||||
*
|
||||
* @param arg unused OSThread func arg
|
||||
**/
|
||||
static void irqmgr_Main(void* arg) {
|
||||
OSMessage msg = (OSMessage)0;
|
||||
|
||||
while (TRUE) {
|
||||
osRecvMesg(&this->_msgQueue, &msg, 1);
|
||||
switch ((u32)msg) {
|
||||
case IRQ_RETRACE_MSG:
|
||||
irqmgr_HandleRetrace();
|
||||
break;
|
||||
case IRQ_PRENMI_MSG:
|
||||
irqmgr_HandlePreNMI();
|
||||
break;
|
||||
case IRQ_PRENMI450_MSG:
|
||||
irqmgr_HandlePreNMI450();
|
||||
break;
|
||||
case IRQ_PRENMI480_MSG:
|
||||
irqmgr_HandlePreNMI480();
|
||||
break;
|
||||
case IRQ_PRENMI500_MSG:
|
||||
irqmgr_HandlePreNMI500();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Creates a new IRQ manager.
|
||||
*
|
||||
* @param stack The IRQ manager's stack
|
||||
* @param stack_size The IRQ manager's stack size
|
||||
* @param priority The thread's priority
|
||||
* @param retracecount Taken by osViSetEvent, unused
|
||||
**/
|
||||
extern void CreateIRQManager(void* stack, size_t stack_size, int priority, u8 retracecount) {
|
||||
this = &irqmgr_class;
|
||||
this->clients = NULL;
|
||||
this->msgRetrace.type = 1;
|
||||
this->msgPreNMI.type = 4;
|
||||
this->msgDelayPreNMI.type = 3;
|
||||
this->prenmi = 0;
|
||||
this->prenmi_time = 0;
|
||||
|
||||
osCreateMesgQueue(&this->_msgQueue, this->_msgBuf, 8);
|
||||
osViSetEvent(&this->_msgQueue, (OSMessage)IRQ_RETRACE_MSG, retracecount);
|
||||
osCreateThread2(&this->thread, 9, irqmgr_Main, NULL, stack, stack_size, priority);
|
||||
osStartThread(&this->thread);
|
||||
}
|
||||
|
||||
/* these were probably written in a header directly and included here */
|
||||
|
||||
#define VI_STACK_SIZE 0x1000
|
||||
|
||||
static OSMessage vc_msg;
|
||||
static OSMessageQueue* vc_msgq;
|
||||
static u16 vc_retraceCount;
|
||||
static u16 retrace; /* this probably belongs in one of the unused vi functions below */
|
||||
static u8 viThreadStack[VI_STACK_SIZE];
|
||||
static OSThread viThread;
|
||||
|
||||
/* @unused ? viMgrMain(?) */
|
||||
|
||||
/* @unused ? osCreateViManager(?) */
|
||||
|
||||
#pragma pool_data on
|
||||
/**
|
||||
* @brief Sets the VI event info. Stubbed outside this functionality.
|
||||
*
|
||||
* @param msgq The OSMessageQueue which would be notified upon event invocation
|
||||
* @param msg The OSMessage which would be sent upon event invocation
|
||||
* @param retcount The retrace count before invoking the event
|
||||
**/
|
||||
extern void osViSetEvent(OSMessageQueue* mesgq, OSMessage msg, u32 retcount) {
|
||||
vc_msgq = mesgq;
|
||||
vc_msg = msg;
|
||||
vc_retraceCount = retcount;
|
||||
}
|
||||
#pragma pool_data reset
|
||||
Reference in New Issue
Block a user