Starship/src/main/main.c

565 lines
18 KiB
C
Raw Normal View History

#include "global.h"
2023-10-07 09:29:38 +03:00
s32 sGammaMode = 1;
#ifdef BSS_IMPORT
SPTask* gCurrentTask;
SPTask* sAudioTasks[1];
SPTask* sGfxTasks[2];
SPTask* sNewAudioTasks[1];
// 0x4 gap here
SPTask* sNewGfxTasks[2];
u32 gSegments[16]; // 800E1FD0
OSMesgQueue gPiMgrCmdQueue; // 800E2010
OSMesg sPiMgrCmdBuff[50]; // 800E2028
OSMesgQueue gDmaMsgQueue;
void* sDmaMsgBuff[1];
OSIoMesg gDmaIOMsg;
OSMesgQueue gSerialEventQueue;
void* sSerialEventBuff[1];
OSMesgQueue gMainThreadMsgQueue;
void* sMainThreadMsgBuff[32];
OSMesgQueue gTaskMsgQueue;
void* sTaskMsgBuff[16];
OSMesgQueue gAudioVImsgQueue;
void* sAudioVImsgBuff[1];
OSMesgQueue gAudioTaskMsgQueue;
void* sAudioTaskMsgBuff[1];
OSMesgQueue gGfxVImsgQueue;
void* sGfxVImsgBuff[4];
OSMesgQueue gGfxTaskMsgQueue;
void* sGfxTaskMsgBuff[2];
OSMesgQueue gSerialThreadMsgQueue;
void* sSerialThreadMsgBuff[8];
OSMesgQueue gControllerMsgQueue;
void* sControllerMsgBuff[1];
OSMesgQueue gSaveMsgQueue;
void* sSaveMsgBuff[1];
OSMesgQueue gTimerTaskMsgQueue;
void* sTimerTaskMsgBuff[16];
OSMesgQueue gTimerWaitMsgQueue;
void* sTimerWaitMsgBuff[1];
GfxPool gGfxPools[2];
GfxPool* gGfxPool;
SPTask* gGfxTask;
Vp* gViewport;
Mtx* gGfxMtx;
Gfx* gUnkDisp1;
Gfx* gMasterDisp;
Gfx* gUnkDisp2;
Lightsn* gLight;
FrameBuffer* gFrameBuffer;
u16* D_80137E74;
u8 D_80137E78;
u32 gFrameCounter;
u8 gStartNMI;
u8 gStopTasks;
u8 D_80137E84[4];
u16 gFillScreenColor;
u16 gFillScreen;
u8 gUnusedStack[0x1000];
OSThread sIdleThread; // 80138E90
u8 sIdleThreadStack[0x1000]; // 801390A0
OSThread gMainThread; // 8013A040
u8 sMainThreadStack[0x1000]; // 8013A1F0
OSThread gAudioThread; // 8013B1F0
u8 gAudioThreadStack[0x1000]; // 800DDAA0
OSThread gGraphicsThread; // 800DEAA0
u8 gGraphicsThreadStack[0x1000]; // 800DEC50
OSThread gTimerThread; // 800DFC50
u8 gTimerThreadStack[0x1000]; // 800DFE00
OSThread gSerialThread; // 800E0E00
u8 gSerialThreadStack[0x1000]; // 800E0FB0
#else
extern u8 gAudioThreadStack[0x1000]; // 800DDAA0
extern OSThread gGraphicsThread; // 800DEAA0
extern u8 gGraphicsThreadStack[0x1000]; // 800DEC50
extern OSThread gTimerThread; // 800DFC50
extern u8 gTimerThreadStack[0x1000]; // 800DFE00
extern OSThread gSerialThread; // 800E0E00
extern u8 gSerialThreadStack[0x1000]; // 800E0FB0
extern SPTask* gCurrentTask;
extern SPTask* sAudioTasks[1];
extern SPTask* sGfxTasks[2];
extern SPTask* sNewAudioTasks[1];
// 0x4 gap here
extern SPTask* sNewGfxTasks[2];
extern u32 gSegments[16]; // 800E1FD0
extern OSMesgQueue gPiMgrCmdQueue; // 800E2010
extern OSMesg sPiMgrCmdBuff[50]; // 800E2028
extern OSMesgQueue gDmaMsgQueue;
extern void* sDmaMsgBuff[1];
extern OSIoMesg gDmaIOMsg;
extern OSMesgQueue gSerialEventQueue;
extern void* sSerialEventBuff[1];
extern OSMesgQueue gMainThreadMsgQueue;
extern void* sMainThreadMsgBuff[32];
extern OSMesgQueue gTaskMsgQueue;
extern void* sTaskMsgBuff[16];
extern OSMesgQueue gAudioVImsgQueue;
extern void* sAudioVImsgBuff[1];
extern OSMesgQueue gAudioTaskMsgQueue;
extern void* sAudioTaskMsgBuff[1];
extern OSMesgQueue gGfxVImsgQueue;
extern void* sGfxVImsgBuff[4];
extern OSMesgQueue gGfxTaskMsgQueue;
extern void* sGfxTaskMsgBuff[2];
extern OSMesgQueue gSerialThreadMsgQueue;
extern void* sSerialThreadMsgBuff[8];
extern OSMesgQueue gControllerMsgQueue;
extern void* sControllerMsgBuff[1];
extern OSMesgQueue gSaveMsgQueue;
extern void* sSaveMsgBuff[1];
extern OSMesgQueue gTimerTaskMsgQueue;
extern void* sTimerTaskMsgBuff[16];
extern OSMesgQueue gTimerWaitMsgQueue;
extern void* sTimerWaitMsgBuff[1];
extern GfxPool gGfxPools[2];
extern GfxPool* gGfxPool;
extern SPTask* gGfxTask;
extern Vp* gViewport;
extern Mtx* gGfxMtx;
extern Gfx* gUnkDisp1;
extern Gfx* gMasterDisp;
extern Gfx* gUnkDisp2;
extern Lightsn* gLight;
extern FrameBuffer* gFrameBuffer;
extern u16* D_80137E74;
extern u8 D_80137E78;
extern u32 gFrameCounter;
extern u8 gStartNMI;
extern u8 gStopTasks;
extern u8 D_80137E84[4];
extern u16 gFillScreenColor;
extern u16 gFillScreen;
extern u8 gUnusedStack[0x1000];
extern OSThread sIdleThread; // 80138E90
extern u8 sIdleThreadStack[0x1000]; // 801390A0
extern OSThread gMainThread; // 8013A040
extern u8 sMainThreadStack[0x1000]; // 8013A1F0
extern OSThread gAudioThread; // 8013B1F0
#endif
void Main_Initialize(void) {
u8 i;
2023-10-06 15:57:30 +03:00
D_80137E78 = 0;
gFrameCounter = 0;
gStartNMI = false;
gStopTasks = false;
gFillScreenColor = 0;
gFillScreen = false;
gCurrentTask = NULL;
2023-10-06 15:57:30 +03:00
for (i = 0; i < ARRAY_COUNT(sAudioTasks); i += 1) {
sAudioTasks[i] = NULL;
}
for (i = 0; i < ARRAY_COUNT(sGfxTasks); i += 1) {
sGfxTasks[i] = NULL;
}
for (i = 0; i < ARRAY_COUNT(sNewAudioTasks); i += 1) {
sNewAudioTasks[i] = NULL;
}
for (i = 0; i < ARRAY_COUNT(sNewGfxTasks); i += 1) {
sNewGfxTasks[i] = NULL;
}
}
void Audio_ThreadEntry(void* arg0) {
SPTask* task;
func_8000FFCC();
func_8001DCE0();
task = func_8001DF50();
if (task != NULL) {
task->msgQueue = &gAudioTaskMsgQueue;
task->msg = (OSMesg) TASK_MESG_1;
osWritebackDCacheAll();
osSendMesg(&gTaskMsgQueue, task, OS_MESG_PRI_NORMAL);
}
while (1) {
task = func_8001DF50();
if (task != NULL) {
task->msgQueue = &gAudioTaskMsgQueue;
task->msg = (OSMesg) TASK_MESG_1;
osWritebackDCacheAll();
}
osRecvMesg(&gAudioTaskMsgQueue, NULL, OS_MESG_NOBLOCK);
if (task != NULL) {
osSendMesg(&gTaskMsgQueue, task, OS_MESG_PRI_NORMAL);
}
osRecvMesg(&gAudioVImsgQueue, NULL, OS_MESG_BLOCK);
}
}
void Graphics_SetTask(void) {
gGfxTask->msgQueue = &gGfxTaskMsgQueue;
gGfxTask->msg = (OSMesg) TASK_MESG_2;
gGfxTask->task.t.type = M_GFXTASK;
gGfxTask->task.t.flags = 0;
gGfxTask->task.t.ucode_boot = __rspboot_start;
gGfxTask->task.t.ucode_boot_size = (uintptr_t) __rspboot_end - (uintptr_t) __rspboot_start;
gGfxTask->task.t.ucode = __f3dex_start;
gGfxTask->task.t.ucode_size = 0x1000;
gGfxTask->task.t.ucode_data = (u64*) &gF3dexData;
gGfxTask->task.t.ucode_data_size = 0x800;
gGfxTask->task.t.dram_stack = (u64*) &D_80281000;
gGfxTask->task.t.dram_stack_size = 0x400;
gGfxTask->task.t.output_buff = (u64*) &D_802A7800;
gGfxTask->task.t.output_buff_size = (u64*) &D_802D7800;
gGfxTask->task.t.data_ptr = (u64*) gGfxPool->masterDL;
gGfxTask->task.t.data_size = (gMasterDisp - gGfxPool->masterDL) * sizeof(Gfx);
gGfxTask->task.t.yield_data_ptr = (u64*) &D_80281400;
gGfxTask->task.t.yield_data_size = OS_YIELD_DATA_SIZE;
osWritebackDCacheAll();
osSendMesg(&gTaskMsgQueue, gGfxTask, OS_MESG_PRI_NORMAL);
}
2023-10-06 15:57:30 +03:00
void Graphics_InitializeTask(u32 frameCount) {
gGfxPool = &gGfxPools[frameCount % 2];
2023-10-06 15:57:30 +03:00
gGfxTask = &gGfxPool->task;
gViewport = gGfxPool->viewports;
gGfxMtx = gGfxPool->mtx;
gUnkDisp1 = gGfxPool->unkDL1;
gMasterDisp = gGfxPool->masterDL;
gUnkDisp2 = gGfxPool->unkDL2;
gLight = gGfxPool->lights;
2023-10-06 15:57:30 +03:00
gFrameBuffer = &gFrameBuffers[frameCount % 3];
D_80137E74 = &D_80387800;
2023-10-06 15:57:30 +03:00
gGfxMatrix = &sGfxMatrixStack[0];
gCalcMatrix = &sCalcMatrixStack[0];
2023-10-06 15:57:30 +03:00
D_80178710 = &D_80178580;
}
2023-10-06 15:57:30 +03:00
void Main_SetVIMode(void) {
if ((gCurrentInput[0].button & D_JPAD) && (gCurrentInput[1].button & D_JPAD) &&
(gCurrentInput[2].button & D_JPAD) && (gCurrentInput[3].button & L_TRIG) &&
(gCurrentInput[3].button & R_TRIG) && (gCurrentInput[3].button & Z_TRIG)) {
sGammaMode = 1 - sGammaMode;
}
switch (osTvType) {
case OS_TV_PAL:
osViSetMode(&osViModePalLan1);
break;
case OS_TV_MPAL:
osViSetMode(&osViModeMpalLan1);
break;
default:
case OS_TV_NTSC:
osViSetMode(&osViModeNtscLan1);
break;
}
if (sGammaMode != 0) {
osViSetSpecialFeatures(OS_VI_DITHER_FILTER_ON | OS_VI_DIVOT_OFF | OS_VI_GAMMA_ON | OS_VI_GAMMA_DITHER_ON);
} else {
osViSetSpecialFeatures(OS_VI_DITHER_FILTER_ON | OS_VI_DIVOT_OFF | OS_VI_GAMMA_OFF | OS_VI_GAMMA_DITHER_OFF);
}
}
2023-10-06 15:57:30 +03:00
void SerialInterface_ThreadEntry(void* arg0) {
OSMesg sp34;
Controller_Init();
while (1) {
osRecvMesg(&gSerialThreadMsgQueue, &sp34, OS_MESG_BLOCK);
switch ((s32) sp34) {
case SI_READ_CONTROLLER:
Controller_ReadData();
break;
case SI_READ_SAVE:
Save_ReadData();
break;
case SI_WRITE_SAVE:
Save_WriteData();
break;
case SI_RUMBLE:
Controller_Rumble();
break;
}
}
}
2023-10-06 15:57:30 +03:00
void Timer_ThreadEntry(void* arg0) {
void* sp24;
while (1) {
osRecvMesg(&gTimerTaskMsgQueue, &sp24, OS_MESG_BLOCK);
Timer_CompleteTask(sp24);
}
}
void Graphics_ThreadEntry(void* arg0) {
u8 i;
u8 var_v1;
u8 var_v2;
func_800A18B0();
osSendMesg(&gSerialThreadMsgQueue, (OSMesg) SI_READ_CONTROLLER, OS_MESG_PRI_NORMAL);
Graphics_InitializeTask(gFrameCounter);
{
gSPSegment(gUnkDisp1++, 0, 0);
gSPDisplayList(gMasterDisp++, gGfxPool->unkDL1);
func_800A26C0();
gSPEndDisplayList(gUnkDisp1++);
gSPEndDisplayList(gUnkDisp2++);
gSPDisplayList(gMasterDisp++, gGfxPool->unkDL2);
gDPFullSync(gMasterDisp++);
gSPEndDisplayList(gMasterDisp++);
}
Graphics_SetTask();
while (1) {
gFrameCounter++;
Graphics_InitializeTask(gFrameCounter);
osRecvMesg(&gControllerMsgQueue, NULL, OS_MESG_BLOCK);
osSendMesg(&gSerialThreadMsgQueue, (OSMesg) SI_RUMBLE, OS_MESG_PRI_NORMAL);
Controller_UpdateInput();
osSendMesg(&gSerialThreadMsgQueue, (OSMesg) SI_READ_CONTROLLER, OS_MESG_PRI_NORMAL);
if (gChangedInput[3].button & U_JPAD) {
Main_SetVIMode();
}
{
gSPSegment(gUnkDisp1++, 0, 0);
gSPDisplayList(gMasterDisp++, gGfxPool->unkDL1);
func_800A26C0();
if (gStartNMI == 1) {
Graphics_NMIWipe();
}
gSPEndDisplayList(gUnkDisp1++);
gSPEndDisplayList(gUnkDisp2++);
gSPDisplayList(gMasterDisp++, gGfxPool->unkDL2);
gDPFullSync(gMasterDisp++);
gSPEndDisplayList(gMasterDisp++);
}
osRecvMesg(&gGfxTaskMsgQueue, NULL, OS_MESG_BLOCK);
Graphics_SetTask();
if (gFillScreen == 0) {
osViSwapBuffer(&gFrameBuffers[(gFrameCounter - 1) % 3]);
}
func_80007FE4(&gFrameBuffers[(gFrameCounter - 1) % 3], 320, 16);
var_v1 = MIN(D_80137E78, 4);
var_v2 = MAX(var_v1, gGfxVImsgQueue.validCount + 1);
for (i = 0; i < var_v2; i += 1) { // Can't be ++
osRecvMesg(&gGfxVImsgQueue, NULL, OS_MESG_BLOCK);
}
func_8001DECC();
}
}
void Main_InitMesgQueues(void) {
osCreateMesgQueue(&gDmaMsgQueue, sDmaMsgBuff, ARRAY_COUNT(sDmaMsgBuff));
osCreateMesgQueue(&gTaskMsgQueue, sTaskMsgBuff, ARRAY_COUNT(sTaskMsgBuff));
osCreateMesgQueue(&gAudioVImsgQueue, sAudioVImsgBuff, ARRAY_COUNT(sAudioVImsgBuff));
osCreateMesgQueue(&gAudioTaskMsgQueue, sAudioTaskMsgBuff, ARRAY_COUNT(sAudioTaskMsgBuff));
osCreateMesgQueue(&gGfxVImsgQueue, sGfxVImsgBuff, ARRAY_COUNT(sGfxVImsgBuff));
osCreateMesgQueue(&gGfxTaskMsgQueue, sGfxTaskMsgBuff, ARRAY_COUNT(sGfxTaskMsgBuff));
osCreateMesgQueue(&gSerialEventQueue, sSerialEventBuff, ARRAY_COUNT(sSerialEventBuff));
osSetEventMesg(OS_EVENT_SI, &gSerialEventQueue, NULL);
osCreateMesgQueue(&gMainThreadMsgQueue, sMainThreadMsgBuff, ARRAY_COUNT(sMainThreadMsgBuff));
osViSetEvent(&gMainThreadMsgQueue, (OSMesg) EVENT_MESG_VI, 1);
osSetEventMesg(OS_EVENT_SP, &gMainThreadMsgQueue, (OSMesg) EVENT_MESG_SP);
osSetEventMesg(OS_EVENT_DP, &gMainThreadMsgQueue, (OSMesg) EVENT_MESG_DP);
osSetEventMesg(OS_EVENT_PRENMI, &gMainThreadMsgQueue, (OSMesg) EVENT_MESG_PRENMI);
osCreateMesgQueue(&gTimerTaskMsgQueue, sTimerTaskMsgBuff, ARRAY_COUNT(sTimerTaskMsgBuff));
osCreateMesgQueue(&gTimerWaitMsgQueue, sTimerWaitMsgBuff, ARRAY_COUNT(sTimerWaitMsgBuff));
osCreateMesgQueue(&gSerialThreadMsgQueue, sSerialThreadMsgBuff, ARRAY_COUNT(sSerialThreadMsgBuff));
osCreateMesgQueue(&gControllerMsgQueue, sControllerMsgBuff, ARRAY_COUNT(sControllerMsgBuff));
osCreateMesgQueue(&gSaveMsgQueue, sSaveMsgBuff, ARRAY_COUNT(sSaveMsgBuff));
}
2023-10-06 15:57:30 +03:00
void Main_HandleRDP(void) {
SPTask** var_v1 = sGfxTasks;
u8 i;
if ((*var_v1)->msgQueue != NULL) {
osSendMesg((*var_v1)->msgQueue, (*var_v1)->msg, OS_MESG_PRI_NORMAL);
}
(*var_v1)->state = SPTASK_STATE_FINISHED_DP;
for (i = 0; i < ARRAY_COUNT(sGfxTasks) - 1; i += 1, var_v1++) {
*var_v1 = *(var_v1 + 1);
}
*var_v1 = NULL;
}
void Main_HandleRSP(void) {
SPTask* task = gCurrentTask;
gCurrentTask = NULL;
if (task->state == SPTASK_STATE_INTERRUPTED) {
if (osSpTaskYielded(&task->task) == 0) {
task->state = SPTASK_STATE_FINISHED;
}
} else {
task->state = SPTASK_STATE_FINISHED;
if (task->task.t.type == M_AUDTASK) {
if (task->msgQueue != NULL) {
osSendMesg(task->msgQueue, task->msg, OS_MESG_PRI_NORMAL);
}
sAudioTasks[0] = NULL;
}
}
}
void Main_GetNewTasks(void) {
u8 i;
SPTask** var_a0;
SPTask** var_a1;
SPTask** var_s0_2;
SPTask** var_s1_2;
OSMesg sp40;
SPTask* sp3C;
var_s0_2 = sNewAudioTasks;
var_s1_2 = sNewGfxTasks;
for (i = 0; i < ARRAY_COUNT(sNewAudioTasks); i += 1) {
*(var_s0_2++) = NULL;
}
for (i = 0; i < ARRAY_COUNT(sNewGfxTasks); i += 1) {
*(var_s1_2++) = NULL;
}
var_s0_2 = sNewAudioTasks;
var_s1_2 = sNewGfxTasks;
while (osRecvMesg(&gTaskMsgQueue, &sp40, OS_MESG_NOBLOCK) != MSG_QUEUE_EMPTY) {
sp3C = (SPTask*) sp40;
sp3C->state = SPTASK_STATE_NOT_STARTED;
switch (sp3C->task.t.type) {
case M_AUDTASK:
*(var_s0_2++) = sp3C;
break;
case M_GFXTASK:
*(var_s1_2++) = sp3C;
break;
}
}
var_s0_2 = sNewAudioTasks;
var_s1_2 = sNewGfxTasks;
var_a0 = sAudioTasks;
var_a1 = sGfxTasks;
for (i = 0; i < ARRAY_COUNT(sAudioTasks); i += 1, var_a0++) {
if (*var_a0 == NULL) {
break;
}
}
for (i; i < ARRAY_COUNT(sAudioTasks); i += 1) {
*(var_a0++) = *(var_s0_2++);
}
for (i = 0; i < ARRAY_COUNT(sGfxTasks); i += 1, var_a1++) {
if (*var_a1 == NULL) {
break;
}
}
for (i; i < ARRAY_COUNT(sGfxTasks); i += 1) {
*(var_a1++) = *(var_s1_2++);
}
}
void Main_StartNextTask(void) {
if (sAudioTasks[0] != NULL) {
if (gCurrentTask != NULL) {
if (gCurrentTask->task.t.type == M_GFXTASK) {
gCurrentTask->state = SPTASK_STATE_INTERRUPTED;
osSpTaskYield();
}
} else {
gCurrentTask = sAudioTasks[0];
osSpTaskLoad(&gCurrentTask->task);
osSpTaskStartGo(&gCurrentTask->task);
gCurrentTask->state = SPTASK_STATE_RUNNING;
}
} else if ((gCurrentTask == NULL) && (sGfxTasks[0] != NULL) && (sGfxTasks[0]->state != SPTASK_STATE_FINISHED)) {
gCurrentTask = sGfxTasks[0];
osDpSetStatus(DPC_CLR_TMEM_CTR | DPC_CLR_PIPE_CTR | DPC_CLR_CMD_CTR | DPC_CLR_CLOCK_CTR);
osSpTaskLoad(&gCurrentTask->task);
osSpTaskStartGo(&gCurrentTask->task);
gCurrentTask->state = SPTASK_STATE_RUNNING;
}
}
void Main_ThreadEntry(void* arg0) {
OSMesg ogMsg;
u8 mesg;
osCreateThread(&gAudioThread, THREAD_ID_AUDIO, Audio_ThreadEntry, arg0,
gAudioThreadStack + sizeof(gAudioThreadStack), 80);
osStartThread(&gAudioThread);
osCreateThread(&gGraphicsThread, THREAD_ID_GRAPHICS, Graphics_ThreadEntry, arg0,
gGraphicsThreadStack + sizeof(gGraphicsThreadStack), 40);
osStartThread(&gGraphicsThread);
osCreateThread(&gTimerThread, THREAD_ID_7, Timer_ThreadEntry, arg0, gTimerThreadStack + sizeof(gTimerThreadStack),
60);
osStartThread(&gTimerThread);
osCreateThread(&gSerialThread, THREAD_ID_SERIAL, SerialInterface_ThreadEntry, arg0,
gSerialThreadStack + sizeof(gSerialThreadStack), 20);
osStartThread(&gSerialThread);
Main_InitMesgQueues();
while (true) {
osRecvMesg(&gMainThreadMsgQueue, &ogMsg, OS_MESG_BLOCK);
mesg = (u32) ogMsg;
switch (mesg) {
case EVENT_MESG_VI:
osSendMesg(&gAudioVImsgQueue, (OSMesg) EVENT_MESG_VI, OS_MESG_PRI_NORMAL);
osSendMesg(&gGfxVImsgQueue, (OSMesg) EVENT_MESG_VI, OS_MESG_PRI_NORMAL);
Main_GetNewTasks();
break;
case EVENT_MESG_SP:
Main_HandleRSP();
break;
case EVENT_MESG_DP:
Main_HandleRDP();
break;
case EVENT_MESG_PRENMI:
gStartNMI = 1;
break;
}
if (gStopTasks == 0) {
Main_StartNextTask();
}
}
}
2023-10-06 15:57:30 +03:00
void Idle_ThreadEntry(void* arg0) {
osCreateViManager(OS_PRIORITY_VIMGR);
Main_SetVIMode();
Lib_FillScreen(1);
osCreatePiMgr(OS_PRIORITY_PIMGR, &gPiMgrCmdQueue, sPiMgrCmdBuff, ARRAY_COUNT(sPiMgrCmdBuff));
osCreateThread(&gMainThread, THREAD_ID_MAIN, &Main_ThreadEntry, arg0, sMainThreadStack + sizeof(sMainThreadStack),
100);
osStartThread(&gMainThread);
Fault_Init();
osSetThreadPri(NULL, OS_PRIORITY_IDLE);
2023-10-07 14:43:15 +03:00
loop_1:
goto loop_1;
}
2023-10-06 15:57:30 +03:00
2023-10-07 09:29:38 +03:00
void bootproc(void) {
RdRam_CheckIPL3();
osInitialize();
Main_Initialize();
osCreateThread(&sIdleThread, THREAD_ID_IDLE, &Idle_ThreadEntry, NULL, sIdleThreadStack + sizeof(sIdleThreadStack),
255);
osStartThread(&sIdleThread);
2023-10-07 09:29:38 +03:00
}