mirror of
https://github.com/HarbourMasters/Starship
synced 2026-08-12 12:18:36 -04:00
@@ -0,0 +1,335 @@
|
||||
#include "sys.h"
|
||||
#include "PR/os_internal.h"
|
||||
|
||||
FaultMgr gFaultMgr;
|
||||
|
||||
u8 sFaultCharIndex[0x80] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x29, 0xFF, 0xFF, 0xFF, 0x2B,
|
||||
0xFF, 0xFF, 0x25, 0x26, 0xFF, 0x2A, 0xFF, 0x27, 0x2C, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
|
||||
0x09, 0x24, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
|
||||
0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A,
|
||||
0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
};
|
||||
|
||||
s32 sFaultCharPixelFlags[0x40] = {
|
||||
0x70871C30, 0x8988A250, 0x88808290, 0x88831C90, 0x888402F8, 0x88882210, 0x71CF9C10, 0xF9CF9C70,
|
||||
0x8228A288, 0xF200A288, 0x0BC11C78, 0x0A222208, 0x8A222288, 0x71C21C70, 0x23C738F8, 0x5228A480,
|
||||
0x8A282280, 0x8BC822F0, 0xFA282280, 0x8A28A480, 0x8BC738F8, 0xF9C89C08, 0x82288808, 0x82088808,
|
||||
0xF2EF8808, 0x82288888, 0x82288888, 0x81C89C70, 0x8A08A270, 0x920DA288, 0xA20AB288, 0xC20AAA88,
|
||||
0xA208A688, 0x9208A288, 0x8BE8A270, 0xF1CF1CF8, 0x8A28A220, 0x8A28A020, 0xF22F1C20, 0x82AA0220,
|
||||
0x82492220, 0x81A89C20, 0x8A28A288, 0x8A28A288, 0x8A289488, 0x8A2A8850, 0x894A9420, 0x894AA220,
|
||||
0x70852220, 0xF8011000, 0x08020800, 0x10840400, 0x20040470, 0x40840400, 0x80020800, 0xF8011000,
|
||||
0x70800000, 0x88822200, 0x08820400, 0x108F8800, 0x20821000, 0x00022200, 0x20800020, 0x00000000,
|
||||
};
|
||||
|
||||
const char* sFaultCauses[18] = {
|
||||
"Interrupt",
|
||||
"TLB modification",
|
||||
"TLB exception on load",
|
||||
"TLB exception on store",
|
||||
"Address error on load",
|
||||
"Address error on store",
|
||||
"Bus error on inst.",
|
||||
"Bus error on data",
|
||||
"System call exception",
|
||||
"Breakpoint exception",
|
||||
"Reserved instruction",
|
||||
"Coprocessor unusable",
|
||||
"Arithmetic overflow",
|
||||
"Trap exception",
|
||||
"Virtual coherency on inst.",
|
||||
"Floating point exception",
|
||||
"Watchpoint exception",
|
||||
"Virtual coherency on data",
|
||||
};
|
||||
|
||||
const char* sFloatExceptions[6] = {
|
||||
"Unimplemented operation", "Invalid operation", "Division by zero", "Overflow", "Underflow", "Inexact operation",
|
||||
};
|
||||
|
||||
void func_800073C0(s32 arg0, s32 arg1, s32 arg2, s32 arg3) {
|
||||
u16* var_v0;
|
||||
s32 i;
|
||||
s32 j;
|
||||
|
||||
var_v0 = gFaultMgr.width * arg1 + gFaultMgr.fb->data + arg0;
|
||||
for (i = 0; i < arg3; i++) {
|
||||
for (j = 0; j < arg2; j++, var_v0++) {
|
||||
*var_v0 = ((*var_v0 & 0xE738) >> 2) | 1;
|
||||
}
|
||||
var_v0 += gFaultMgr.width - arg2;
|
||||
}
|
||||
}
|
||||
|
||||
void func_800074AC(s32 arg0, s32 arg1, s32 arg2) {
|
||||
s32* var_v0;
|
||||
u16* var_v1;
|
||||
s32 i;
|
||||
s32 j;
|
||||
|
||||
var_v0 = &sFaultCharPixelFlags[(arg2 / 5) * 7];
|
||||
var_v1 = gFaultMgr.width * arg1 + gFaultMgr.fb->data + arg0;
|
||||
|
||||
for (i = 0; i < 7; i++) {
|
||||
u32 temp_t1 = 0x80000000 >> ((arg2 % 5) * 6);
|
||||
u32 temp_a3 = *var_v0++;
|
||||
|
||||
for (j = 0; j < 6; j++) {
|
||||
if (temp_t1 & temp_a3) {
|
||||
*var_v1 = -1;
|
||||
} else {
|
||||
*var_v1 = 1;
|
||||
}
|
||||
var_v1++;
|
||||
temp_t1 >>= 1;
|
||||
}
|
||||
var_v1 += gFaultMgr.width - 6;
|
||||
}
|
||||
}
|
||||
|
||||
void* func_80007604(void* arg0, const char* arg1, size_t arg2) {
|
||||
return (char*) memcpy(arg0, arg1, arg2) + arg2;
|
||||
}
|
||||
|
||||
void func_8000762C(s32 arg0, s32 arg1, const char* fmt, ...) {
|
||||
u8* var_s0;
|
||||
s32 i;
|
||||
u8 sp40[0x100];
|
||||
s32 temp_a2;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
for (i = 0; i < 0x100; i++) {
|
||||
sp40[i] = 0;
|
||||
}
|
||||
|
||||
if (_Printf((outfun*) func_80007604, sp40, fmt, args) <= 0) {
|
||||
return;
|
||||
}
|
||||
for (var_s0 = sp40; *var_s0 != 0; var_s0++) {
|
||||
temp_a2 = sFaultCharIndex[*var_s0 & 0x7F];
|
||||
|
||||
if (temp_a2 != 0xFF) {
|
||||
func_800074AC(arg0, arg1, temp_a2);
|
||||
}
|
||||
arg0 += 6;
|
||||
label:; // fake, probably
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void func_8000770C(s32 time) {
|
||||
u64 time64 = MSEC_TO_CYCLES(time);
|
||||
|
||||
osSetTime(0);
|
||||
while (osGetTime() < time64) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void func_800077F8(s32 arg0, s32 arg1, s32 arg2, f32* arg3) {
|
||||
u32 temp_v0 = *(u32*) arg3;
|
||||
s32 temp_v1 = ((temp_v0 & 0x7F800000) >> 0x17) - 0x7F;
|
||||
|
||||
if (((-0x7F < temp_v1) && (temp_v1 < 0x80)) || (temp_v0 == 0)) {
|
||||
func_8000762C(arg0, arg1, "F%02d:%.3e", arg2, *arg3);
|
||||
} else {
|
||||
func_8000762C(arg0, arg1, "F%02d:---------", arg2);
|
||||
}
|
||||
}
|
||||
|
||||
void func_80007880(u32 arg0) {
|
||||
s32 var_v0;
|
||||
u32 var_v1 = 0x20000;
|
||||
|
||||
func_8000762C(0x1E, 0xA0, "FPCSR:%08XH", arg0);
|
||||
for (var_v0 = 0; var_v0 < 6; var_v0++, var_v1 >>= 1) {
|
||||
if (arg0 & var_v1) {
|
||||
func_8000762C(0x84, 0xA0, "(%s)", sFloatExceptions[var_v0]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define CAUSE_INDEX(cause) ((cause >> CAUSE_EXCSHIFT) & (CAUSE_EXCMASK >> CAUSE_EXCSHIFT))
|
||||
|
||||
void func_80007910(OSThread* thread) {
|
||||
__OSThreadContext* context = &thread->context;
|
||||
s16 var_s0 = CAUSE_INDEX(context->cause);
|
||||
|
||||
if (var_s0 == CAUSE_INDEX(EXC_WATCH)) {
|
||||
var_s0 = 16;
|
||||
}
|
||||
if (var_s0 == CAUSE_INDEX(EXC_VCED)) {
|
||||
var_s0 = 17;
|
||||
}
|
||||
func_8000770C(3000);
|
||||
func_800073C0(15, 15, 290, 210);
|
||||
func_8000762C(30, 40, "THREAD:%d (%s)", thread->id, sFaultCauses[var_s0]);
|
||||
func_8000762C(30, 50, "PC:%08XH SR:%08XH\tVA:%08XH", context->pc, context->sr, context->badvaddr);
|
||||
osWritebackDCacheAll();
|
||||
func_8000762C(30, 60, "AT:%08XH V0:%08XH\tV1:%08XH", (s32) context->at, (s32) context->v0, (s32) context->v1);
|
||||
func_8000762C(30, 70, "A0:%08XH A1:%08XH\tA2:%08XH", (s32) context->a0, (s32) context->a1, (s32) context->a2);
|
||||
func_8000762C(30, 80, "A3:%08XH T0:%08XH\tT1:%08XH", (s32) context->a3, (s32) context->t0, (s32) context->t1);
|
||||
func_8000762C(30, 90, "T2:%08XH T3:%08XH\tT4:%08XH", (s32) context->t2, (s32) context->t3, (s32) context->t4);
|
||||
func_8000762C(30, 100, "T5:%08XH T6:%08XH\tT7:%08XH", (s32) context->t5, (s32) context->t6, (s32) context->t7);
|
||||
func_8000762C(30, 110, "S0:%08XH S1:%08XH\tS2:%08XH", (s32) context->s0, (s32) context->s1, (s32) context->s2);
|
||||
func_8000762C(30, 120, "S3:%08XH S4:%08XH\tS5:%08XH", (s32) context->s3, (s32) context->s4, (s32) context->s5);
|
||||
func_8000762C(30, 130, "S6:%08XH S7:%08XH\tT8:%08XH", (s32) context->s6, (s32) context->s7, (s32) context->t8);
|
||||
func_8000762C(30, 140, "T9:%08XH GP:%08XH\tSP:%08XH", (s32) context->t9, (s32) context->gp, (s32) context->sp);
|
||||
func_8000762C(30, 150, "S8:%08XH RA:%08XH", (s32) context->s8, (s32) context->ra);
|
||||
func_80007880(context->fpcsr);
|
||||
osWritebackDCacheAll();
|
||||
func_800077F8(30, 170, 0, &context->fp0.f.f_even);
|
||||
func_800077F8(120, 170, 2, &context->fp2.f.f_even);
|
||||
func_800077F8(210, 170, 4, &context->fp4.f.f_even);
|
||||
func_800077F8(30, 180, 6, &context->fp6.f.f_even);
|
||||
func_800077F8(120, 180, 8, &context->fp8.f.f_even);
|
||||
func_800077F8(210, 180, 10, &context->fp10.f.f_even);
|
||||
func_800077F8(30, 190, 12, &context->fp12.f.f_even);
|
||||
func_800077F8(120, 190, 14, &context->fp14.f.f_even);
|
||||
func_800077F8(210, 190, 16, &context->fp16.f.f_even);
|
||||
func_800077F8(30, 200, 18, &context->fp18.f.f_even);
|
||||
func_800077F8(120, 200, 20, &context->fp20.f.f_even);
|
||||
func_800077F8(210, 200, 22, &context->fp22.f.f_even);
|
||||
func_800077F8(30, 210, 24, &context->fp24.f.f_even);
|
||||
func_800077F8(120, 210, 26, &context->fp26.f.f_even);
|
||||
func_800077F8(210, 210, 28, &context->fp28.f.f_even);
|
||||
func_800077F8(30, 220, 30, &context->fp30.f.f_even);
|
||||
osWritebackDCacheAll();
|
||||
osViBlack(0);
|
||||
osViRepeatLine(0);
|
||||
osViSwapBuffer(gFaultMgr.fb);
|
||||
}
|
||||
|
||||
OSThread* func_80007CEC(void) {
|
||||
OSThread* var_v1;
|
||||
|
||||
var_v1 = __osGetActiveQueue();
|
||||
|
||||
while (var_v1->priority != -1) {
|
||||
if ((var_v1->priority > 0) && (var_v1->priority < 0x7F) && (var_v1->flags & 3)) {
|
||||
return var_v1;
|
||||
}
|
||||
var_v1 = var_v1->tlnext;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void Fault_ThreadEntry(void* arg0) {
|
||||
OSMesg sp44;
|
||||
OSThread* sp40;
|
||||
s32 var_s2;
|
||||
s32 var_s5;
|
||||
u32 var_s0;
|
||||
|
||||
sp44 = NULL;
|
||||
var_s5 = 0;
|
||||
var_s0 = 0;
|
||||
var_s2 = 0;
|
||||
|
||||
osSetEventMesg(OS_EVENT_CPU_BREAK, &gFaultMgr.msgQueue, (OSMesg) FAULT_MESG_BREAK);
|
||||
osSetEventMesg(OS_EVENT_FAULT, &gFaultMgr.msgQueue, (OSMesg) FAULT_MESG_FAULT);
|
||||
|
||||
sp40 = NULL;
|
||||
while (sp40 == NULL) {
|
||||
osRecvMesg(&gFaultMgr.msgQueue, &sp44, OS_MESG_BLOCK);
|
||||
sp40 = func_80007CEC();
|
||||
}
|
||||
|
||||
func_8000762C(300, 10, "-");
|
||||
gControllerPlugged[0] = 1;
|
||||
while (var_s5 == 0) {
|
||||
osSendMesg(&gSerialThreadMsgQueue, (OSMesg) SI_READ_CONTROLLER, OS_MESG_PRI_NORMAL);
|
||||
osRecvMesg(&gControllerMsgQueue, NULL, OS_MESG_BLOCK);
|
||||
Controller_UpdateInput();
|
||||
switch (var_s0) {
|
||||
case 0:
|
||||
if (gControllerHold[0].button == (R_TRIG | D_CBUTTONS | L_CBUTTONS)) {
|
||||
var_s0++;
|
||||
var_s2 = 4000;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 7:
|
||||
if (gControllerHold[0].button & R_TRIG) {
|
||||
if (gControllerPress[0].button == A_BUTTON) {
|
||||
var_s0++;
|
||||
var_s2 = 3000;
|
||||
} else if (gControllerPress[0].button != 0) {
|
||||
var_s0 = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
case 8:
|
||||
if (gControllerHold[0].button & R_TRIG) {
|
||||
if (gControllerPress[0].button == B_BUTTON) {
|
||||
var_s0++;
|
||||
var_s2 = 3000;
|
||||
} else if (gControllerPress[0].button != 0) {
|
||||
var_s0 = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
if (gControllerHold[0].button & R_TRIG) {
|
||||
if (gControllerPress[0].button == L_CBUTTONS) {
|
||||
var_s0++;
|
||||
var_s2 = 3000;
|
||||
} else if (gControllerPress[0].button != 0) {
|
||||
var_s0 = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 14:
|
||||
if (gControllerHold[0].button & R_TRIG) {
|
||||
if (gControllerPress[0].button == START_BUTTON) {
|
||||
var_s0++;
|
||||
var_s2 = 3000;
|
||||
} else if (gControllerPress[0].button != 0) {
|
||||
var_s0 = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 15:
|
||||
var_s5 = 1;
|
||||
break;
|
||||
}
|
||||
if (var_s2 != 0) {
|
||||
var_s2 -= 1;
|
||||
} else {
|
||||
var_s0 = 0;
|
||||
}
|
||||
}
|
||||
func_80007910(sp40);
|
||||
while (1) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void func_80007FE4(FrameBuffer* arg0, u16 arg1, u16 arg2) {
|
||||
gFaultMgr.fb = arg0;
|
||||
gFaultMgr.width = arg1;
|
||||
gFaultMgr.height = arg2;
|
||||
}
|
||||
|
||||
void Fault_Init(void) {
|
||||
gFaultMgr.fb = (FrameBuffer*) (PHYS_TO_K0(osMemSize) - sizeof(FrameBuffer));
|
||||
gFaultMgr.width = SCREEN_WIDTH;
|
||||
gFaultMgr.height = SCREEN_HEIGHT;
|
||||
osCreateMesgQueue(&gFaultMgr.msgQueue, &gFaultMgr.msg, 1);
|
||||
osCreateThread(&gFaultMgr.thread, THREAD_ID_FAULT, Fault_ThreadEntry, 0, gFaultMgr.stack + sizeof(gFaultMgr.stack),
|
||||
127);
|
||||
osStartThread(&gFaultMgr.thread);
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
#include "sys.h"
|
||||
|
||||
OSContPad gControllerHold[4];
|
||||
OSContPad gControllerPress[4];
|
||||
u8 gControllerPlugged[4];
|
||||
u32 gControllerLock;
|
||||
u8 gControllerRumble[4];
|
||||
OSContPad sNextController[4]; //
|
||||
OSContPad sPrevController[4]; //
|
||||
OSContStatus sControllerStatus[4]; //
|
||||
OSPfs sControllerMotor[4]; //
|
||||
|
||||
void Controller_AddDeadZone(s32 contrNum) {
|
||||
s32 temp_v0 = gControllerHold[contrNum].stick_x;
|
||||
s32 temp_a2 = gControllerHold[contrNum].stick_y;
|
||||
s32 var_a0;
|
||||
s32 var_v0;
|
||||
|
||||
if ((temp_v0 >= -16) && (temp_v0 <= 16)) {
|
||||
var_a0 = 0;
|
||||
} else if (temp_v0 > 16) {
|
||||
var_a0 = temp_v0 - 16;
|
||||
} else {
|
||||
var_a0 = temp_v0 + 16;
|
||||
}
|
||||
|
||||
if ((temp_a2 >= -16) && (temp_a2 <= 16)) {
|
||||
var_v0 = 0;
|
||||
} else if (temp_a2 > 16) {
|
||||
var_v0 = temp_a2 - 16;
|
||||
} else {
|
||||
var_v0 = temp_a2 + 16;
|
||||
}
|
||||
|
||||
if (var_a0 > 60) {
|
||||
var_a0 = 60;
|
||||
}
|
||||
if (var_a0 < -60) {
|
||||
var_a0 = -60;
|
||||
}
|
||||
if (var_v0 > 60) {
|
||||
var_v0 = 60;
|
||||
}
|
||||
if (var_v0 < -60) {
|
||||
var_v0 = -60;
|
||||
}
|
||||
gControllerPress[contrNum].stick_x = var_a0;
|
||||
gControllerPress[contrNum].stick_y = var_v0;
|
||||
}
|
||||
|
||||
void Controller_Init(void) {
|
||||
u8 sp1F;
|
||||
s32 i;
|
||||
|
||||
osContInit(&gSerialEventQueue, &sp1F, sControllerStatus);
|
||||
for (i = 0; i < 4; i++) {
|
||||
gControllerPlugged[i] = (sp1F >> i) & 1;
|
||||
gControllerRumble[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Controller_UpdateInput(void) {
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (gControllerPlugged[i] == 1 && sNextController[i].errno == 0) {
|
||||
sPrevController[i] = gControllerHold[i];
|
||||
gControllerHold[i] = sNextController[i];
|
||||
gControllerPress[i].button =
|
||||
(gControllerHold[i].button ^ sPrevController[i].button) & gControllerHold[i].button;
|
||||
Controller_AddDeadZone(i);
|
||||
} else {
|
||||
gControllerHold[i].button = gControllerHold[i].stick_x = gControllerHold[i].stick_y =
|
||||
gControllerHold[i].errno = gControllerPress[i].button = gControllerPress[i].stick_x =
|
||||
gControllerPress[i].stick_y = gControllerPress[i].errno = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Controller_ReadData(void) {
|
||||
s32 i;
|
||||
|
||||
if (gControllerLock != 0) {
|
||||
gControllerLock--;
|
||||
for (i = 0; i < 4; i++) {
|
||||
sNextController[i].button = sNextController[i].stick_x = sNextController[i].stick_y =
|
||||
sNextController[i].errno = 0;
|
||||
}
|
||||
} else {
|
||||
osContStartReadData(&gSerialEventQueue);
|
||||
osRecvMesg(&gSerialEventQueue, NULL, OS_MESG_BLOCK);
|
||||
osContGetReadData(sNextController);
|
||||
}
|
||||
osSendMesg(&gControllerMsgQueue, (OSMesg) SI_CONT_READ_DONE, OS_MESG_PRI_NORMAL);
|
||||
}
|
||||
|
||||
void Save_ReadData(void) {
|
||||
if ((gStartNMI == 0) && (Save_ReadEeprom(&gSaveIOBuffer) == 0)) {
|
||||
osSendMesg(&gSaveMsgQueue, (OSMesg) SI_SAVE_SUCCESS, OS_MESG_PRI_NORMAL);
|
||||
return;
|
||||
}
|
||||
osSendMesg(&gSaveMsgQueue, (OSMesg) SI_SAVE_FAILED, OS_MESG_PRI_NORMAL);
|
||||
}
|
||||
|
||||
void Save_WriteData(void) {
|
||||
if ((gStartNMI == 0) && (Save_WriteEeprom(&gSaveIOBuffer) == 0)) {
|
||||
osSendMesg(&gSaveMsgQueue, (OSMesg) SI_SAVE_SUCCESS, OS_MESG_PRI_NORMAL);
|
||||
return;
|
||||
}
|
||||
osSendMesg(&gSaveMsgQueue, (OSMesg) SI_SAVE_FAILED, OS_MESG_PRI_NORMAL);
|
||||
}
|
||||
|
||||
void Controller_Rumble(void) {
|
||||
s32 i;
|
||||
|
||||
osContStartQuery(&gSerialEventQueue);
|
||||
osRecvMesg(&gSerialEventQueue, NULL, OS_MESG_BLOCK);
|
||||
osContGetQuery(sControllerStatus);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if ((gControllerPlugged[i] != 0) && (sControllerStatus[i].errno == 0)) {
|
||||
if (sControllerStatus[i].status & 1) {
|
||||
if (gControllerRumble[i] == 0) {
|
||||
if (osMotorInit(&gSerialEventQueue, &sControllerMotor[i], i)) {
|
||||
gControllerRumble[i] = 0;
|
||||
} else {
|
||||
gControllerRumble[i] = 1;
|
||||
}
|
||||
}
|
||||
if (gControllerRumble[i] == 1) {
|
||||
if (D_80137E84[i] != 0) {
|
||||
if (osMotorStart(&sControllerMotor[i])) {
|
||||
gControllerRumble[i] = 0;
|
||||
}
|
||||
} else {
|
||||
if (osMotorStop(&sControllerMotor[i])) {
|
||||
gControllerRumble[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
gControllerRumble[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < 4; i++) {
|
||||
D_80137E84[i] = 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
#include "sys.h"
|
||||
|
||||
s32 Lib_vsPrintf(char* dst, const char* fmt, va_list args) {
|
||||
return vsprintf(dst, fmt, args);
|
||||
}
|
||||
|
||||
void Lib_vTable(s32 index, void (**table)(s32, s32), s32 arg0, s32 arg1) {
|
||||
void (*func)(s32, s32) = table[index];
|
||||
|
||||
func(arg0, arg1);
|
||||
}
|
||||
|
||||
void Lib_SwapBuffers(u8* buf1, u8* buf2, s32 len) {
|
||||
s32 i;
|
||||
u8 temp;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
temp = buf2[i];
|
||||
buf2[i] = buf1[i];
|
||||
buf1[i] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void Lib_QuickSort(u8* first, u32 length, u32 size, CompareFunc cFunc) {
|
||||
u32 splitIdx;
|
||||
u8* last;
|
||||
u8* right;
|
||||
u8* left;
|
||||
|
||||
while (1) {
|
||||
last = first + (length - 1) * size;
|
||||
|
||||
if (length == 2) {
|
||||
if (cFunc(first, last) > 0) {
|
||||
Lib_SwapBuffers(first, last, size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (size && size && size) {} //! FAKE: must be here with at least 3 && operands.
|
||||
left = first;
|
||||
right = last - size;
|
||||
|
||||
while (1) {
|
||||
while (cFunc(left, last) < 0) {
|
||||
left += size;
|
||||
}
|
||||
while ((cFunc(right, last) >= 0) && (left < right)) {
|
||||
right -= size;
|
||||
}
|
||||
if (left >= right) {
|
||||
break;
|
||||
}
|
||||
Lib_SwapBuffers(left, right, size);
|
||||
left += size;
|
||||
right -= size;
|
||||
}
|
||||
Lib_SwapBuffers(last, left, size);
|
||||
splitIdx = (left - first) / size;
|
||||
if (length / 2 < splitIdx) {
|
||||
if ((length - splitIdx) > 2) {
|
||||
Lib_QuickSort(left + size, length - splitIdx - 1, size, cFunc);
|
||||
}
|
||||
|
||||
if (splitIdx < 2) {
|
||||
return;
|
||||
}
|
||||
left = first;
|
||||
length = splitIdx;
|
||||
} else {
|
||||
if (splitIdx >= 2) {
|
||||
Lib_QuickSort(first, splitIdx, size, cFunc);
|
||||
}
|
||||
|
||||
if ((length - splitIdx) <= 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
first = left + size;
|
||||
length -= splitIdx + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Lib_Perspective(Gfx** dList) {
|
||||
u16 norm;
|
||||
|
||||
guPerspective(gGfxMtx, &norm, D_game_80161A3C, (f32) SCREEN_WIDTH / SCREEN_HEIGHT, D_game_80161A40, D_game_80161A44,
|
||||
1.0f);
|
||||
gSPPerspNormalize((*dList)++, norm);
|
||||
gSPMatrix((*dList)++, gGfxMtx++, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
|
||||
guLookAt(gGfxMtx, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -12800.0f, 0.0f, 1.0f, 0.0f);
|
||||
gSPMatrix((*dList)++, gGfxMtx++, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
|
||||
Matrix_Copy(gGfxMatrix, &gIdentityMatrix);
|
||||
}
|
||||
|
||||
void Lib_Ortho(Gfx** dList) {
|
||||
guOrtho(gGfxMtx, -160.0f, 160.0f, -120.0f, 120.0f, D_game_80161A40, D_game_80161A44, 1.0f);
|
||||
gSPMatrix((*dList)++, gGfxMtx++, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
|
||||
guLookAt(gGfxMtx, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -12800.0f, 0.0f, 1.0f, 0.0f);
|
||||
gSPMatrix((*dList)++, gGfxMtx++, G_MTX_NOPUSH | G_MTX_MUL | G_MTX_PROJECTION);
|
||||
Matrix_Copy(gGfxMatrix, &gIdentityMatrix);
|
||||
}
|
||||
|
||||
void Lib_DmaRead(void* src, void* dst, ptrdiff_t size) {
|
||||
osInvalICache(dst, size);
|
||||
osInvalDCache(dst, size);
|
||||
while (size > 0x100) {
|
||||
osPiStartDma(&gDmaIOMsg, 0, 0, (uintptr_t) src, dst, 0x100, &gDmaMsgQueue);
|
||||
size -= 0x100;
|
||||
src = (void*) ((uintptr_t) src + 0x100);
|
||||
dst = (void*) ((uintptr_t) dst + 0x100);
|
||||
osRecvMesg(&gDmaMsgQueue, NULL, OS_MESG_BLOCK);
|
||||
}
|
||||
if (size != 0) {
|
||||
osPiStartDma(&gDmaIOMsg, 0, 0, (uintptr_t) src, dst, size, &gDmaMsgQueue);
|
||||
osRecvMesg(&gDmaMsgQueue, NULL, OS_MESG_BLOCK);
|
||||
}
|
||||
}
|
||||
|
||||
void Lib_FillScreen(u8 setFill) {
|
||||
s32 i;
|
||||
|
||||
gFillScreenColor |= 1;
|
||||
if (setFill == true) {
|
||||
if (gFillScreen == false) {
|
||||
if (gFillScreenColor == 1) {
|
||||
osViBlack(1);
|
||||
} else {
|
||||
for (i = 0; i < 3 * SCREEN_WIDTH; i++) {
|
||||
gFillBuffer[i] = gFillScreenColor;
|
||||
}
|
||||
osWritebackDCacheAll();
|
||||
osViSwapBuffer(&gFillBuffer[SCREEN_WIDTH]);
|
||||
osViRepeatLine(1);
|
||||
}
|
||||
gFillScreen = true;
|
||||
}
|
||||
} else if (gFillScreen == true) {
|
||||
osViRepeatLine(0);
|
||||
osViBlack(0);
|
||||
gFillScreen = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
#include "sys.h"
|
||||
|
||||
void Lights_AddLight(Gfx** dList) {
|
||||
gSPNumLights((*dList)++, 7);
|
||||
gSPLight((*dList)++, &gLight->l[0], 1);
|
||||
gSPLight((*dList)++, &gLight->l[1], 2);
|
||||
gSPLight((*dList)++, &gLight->l[2], 3);
|
||||
gSPLight((*dList)++, &gLight->l[3], 4);
|
||||
gSPLight((*dList)++, &gLight->l[4], 5);
|
||||
gSPLight((*dList)++, &gLight->l[5], 6);
|
||||
gSPLight((*dList)++, &gLight->l[6], 7);
|
||||
gSPLight((*dList)++, &gLight->a, 8);
|
||||
gLight++;
|
||||
}
|
||||
|
||||
void Lights_SetOneLight(Gfx** dList, s32 dirX, s32 dirY, s32 dirZ, s32 colR, s32 colG, s32 colB, s32 ambR, s32 ambG,
|
||||
s32 ambB) {
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
gLight->l[i].l.dir[0] = dirX;
|
||||
gLight->l[i].l.dir[1] = dirY;
|
||||
gLight->l[i].l.dir[2] = dirZ;
|
||||
gLight->l[i].l.col[0] = colR;
|
||||
gLight->l[i].l.col[1] = colG;
|
||||
gLight->l[i].l.col[2] = colB;
|
||||
gLight->l[i].l.colc[0] = colR;
|
||||
gLight->l[i].l.colc[1] = colG;
|
||||
gLight->l[i].l.colc[2] = colB;
|
||||
}
|
||||
for (i = 4; i < 7; i++) {
|
||||
gLight->l[i].l.dir[0] = dirX;
|
||||
gLight->l[i].l.dir[1] = dirY;
|
||||
gLight->l[i].l.dir[2] = dirZ;
|
||||
gLight->l[i].l.col[0] = 0;
|
||||
gLight->l[i].l.col[1] = 0;
|
||||
gLight->l[i].l.col[2] = 0;
|
||||
gLight->l[i].l.colc[0] = 0;
|
||||
gLight->l[i].l.colc[1] = 0;
|
||||
gLight->l[i].l.colc[2] = 0;
|
||||
}
|
||||
gLight->a.l.col[0] = ambR;
|
||||
gLight->a.l.col[1] = ambG;
|
||||
gLight->a.l.col[2] = ambB;
|
||||
gLight->a.l.colc[0] = ambR;
|
||||
gLight->a.l.colc[1] = ambG;
|
||||
gLight->a.l.colc[2] = ambB;
|
||||
Lights_AddLight(dList);
|
||||
}
|
||||
|
||||
void Lights_SetTwoLights(Gfx** dList, s32 dir1x, s32 dir1y, s32 dir1z, s32 dir2x, s32 dir2y, s32 dir2z, s32 col1r,
|
||||
s32 col1g, s32 col1b, s32 col2r, s32 col2g, s32 col2b, s32 ambR, s32 ambG, s32 ambB) {
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
gLight->l[i].l.dir[0] = dir1x;
|
||||
gLight->l[i].l.dir[1] = dir1y;
|
||||
gLight->l[i].l.dir[2] = dir1z;
|
||||
gLight->l[i].l.col[0] = col1r;
|
||||
gLight->l[i].l.col[1] = col1g;
|
||||
gLight->l[i].l.col[2] = col1b;
|
||||
gLight->l[i].l.colc[0] = col1r;
|
||||
gLight->l[i].l.colc[1] = col1g;
|
||||
gLight->l[i].l.colc[2] = col1b;
|
||||
}
|
||||
for (i = 4; i < 7; i++) {
|
||||
gLight->l[i].l.dir[0] = dir2x;
|
||||
gLight->l[i].l.dir[1] = dir2y;
|
||||
gLight->l[i].l.dir[2] = dir2z;
|
||||
gLight->l[i].l.col[0] = col2r;
|
||||
gLight->l[i].l.col[1] = col2g;
|
||||
gLight->l[i].l.col[2] = col2b;
|
||||
gLight->l[i].l.colc[0] = col2r;
|
||||
gLight->l[i].l.colc[1] = col2g;
|
||||
gLight->l[i].l.colc[2] = col2b;
|
||||
}
|
||||
gLight->a.l.col[0] = ambR;
|
||||
gLight->a.l.col[1] = ambG;
|
||||
gLight->a.l.col[2] = ambB;
|
||||
gLight->a.l.colc[0] = ambR;
|
||||
gLight->a.l.colc[1] = ambG;
|
||||
gLight->a.l.colc[2] = ambB;
|
||||
Lights_AddLight(dList);
|
||||
}
|
||||
@@ -0,0 +1,493 @@
|
||||
#include "sys.h"
|
||||
|
||||
void AudioLoad_Init(void);
|
||||
SPTask* AudioThread_CreateTask(void);
|
||||
void Audio_InitSounds(void);
|
||||
void Audio_Update(void);
|
||||
|
||||
s32 sGammaMode = 1;
|
||||
|
||||
SPTask* gCurrentTask;
|
||||
SPTask* sAudioTasks[1];
|
||||
SPTask* sGfxTasks[2];
|
||||
SPTask* sNewAudioTasks[1];
|
||||
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* gTextureRender;
|
||||
|
||||
u8 D_80137E78;
|
||||
u32 gSysFrameCount;
|
||||
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
|
||||
|
||||
void Main_Initialize(void) {
|
||||
u8 i;
|
||||
|
||||
D_80137E78 = 0;
|
||||
gSysFrameCount = 0;
|
||||
gStartNMI = false;
|
||||
gStopTasks = false;
|
||||
gFillScreenColor = 0;
|
||||
gFillScreen = false;
|
||||
gCurrentTask = NULL;
|
||||
|
||||
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;
|
||||
|
||||
AudioLoad_Init();
|
||||
Audio_InitSounds();
|
||||
task = AudioThread_CreateTask();
|
||||
if (task != NULL) {
|
||||
task->msgQueue = &gAudioTaskMsgQueue;
|
||||
task->msg = (OSMesg) TASK_MESG_1;
|
||||
osWritebackDCacheAll();
|
||||
osSendMesg(&gTaskMsgQueue, task, OS_MESG_PRI_NORMAL);
|
||||
}
|
||||
while (1) {
|
||||
task = AudioThread_CreateTask();
|
||||
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 = rspbootTextStart;
|
||||
gGfxTask->task.t.ucode_boot_size = (uintptr_t) rspbootTextEnd - (uintptr_t) rspbootTextStart;
|
||||
gGfxTask->task.t.ucode = gspF3DEX_fifoTextStart;
|
||||
gGfxTask->task.t.ucode_size = SP_UCODE_SIZE;
|
||||
gGfxTask->task.t.ucode_data = (u64*) &gspF3DEX_fifoDataStart;
|
||||
gGfxTask->task.t.ucode_data_size = SP_UCODE_DATA_SIZE;
|
||||
gGfxTask->task.t.dram_stack = gDramStack;
|
||||
gGfxTask->task.t.dram_stack_size = SP_DRAM_STACK_SIZE8;
|
||||
gGfxTask->task.t.output_buff = (u64*) gTaskOutputBuffer;
|
||||
gGfxTask->task.t.output_buff_size = (u64*) gAudioHeap;
|
||||
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*) &gOSYieldData;
|
||||
gGfxTask->task.t.yield_data_size = OS_YIELD_DATA_SIZE;
|
||||
osWritebackDCacheAll();
|
||||
osSendMesg(&gTaskMsgQueue, gGfxTask, OS_MESG_PRI_NORMAL);
|
||||
}
|
||||
|
||||
void Graphics_InitializeTask(u32 frameCount) {
|
||||
gGfxPool = &gGfxPools[frameCount % 2];
|
||||
|
||||
gGfxTask = &gGfxPool->task;
|
||||
gViewport = gGfxPool->viewports;
|
||||
gGfxMtx = gGfxPool->mtx;
|
||||
gUnkDisp1 = gGfxPool->unkDL1;
|
||||
gMasterDisp = gGfxPool->masterDL;
|
||||
gUnkDisp2 = gGfxPool->unkDL2;
|
||||
gLight = gGfxPool->lights;
|
||||
|
||||
gFrameBuffer = &gFrameBuffers[frameCount % 3];
|
||||
gTextureRender = &gTextureRenderBuffer[0];
|
||||
|
||||
gGfxMatrix = &sGfxMatrixStack[0];
|
||||
gCalcMatrix = &sCalcMatrixStack[0];
|
||||
|
||||
D_80178710 = &D_80178580[0];
|
||||
}
|
||||
|
||||
void Main_SetVIMode(void) {
|
||||
if ((gControllerHold[0].button & D_JPAD) && (gControllerHold[1].button & D_JPAD) &&
|
||||
(gControllerHold[2].button & D_JPAD) && (gControllerHold[3].button & L_TRIG) &&
|
||||
(gControllerHold[3].button & R_TRIG) && (gControllerHold[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);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
Game_Initialize();
|
||||
osSendMesg(&gSerialThreadMsgQueue, (OSMesg) SI_READ_CONTROLLER, OS_MESG_PRI_NORMAL);
|
||||
Graphics_InitializeTask(gSysFrameCount);
|
||||
{
|
||||
gSPSegment(gUnkDisp1++, 0, 0);
|
||||
gSPDisplayList(gMasterDisp++, gGfxPool->unkDL1);
|
||||
Game_Update();
|
||||
gSPEndDisplayList(gUnkDisp1++);
|
||||
gSPEndDisplayList(gUnkDisp2++);
|
||||
gSPDisplayList(gMasterDisp++, gGfxPool->unkDL2);
|
||||
gDPFullSync(gMasterDisp++);
|
||||
gSPEndDisplayList(gMasterDisp++);
|
||||
}
|
||||
Graphics_SetTask();
|
||||
while (1) {
|
||||
gSysFrameCount++;
|
||||
Graphics_InitializeTask(gSysFrameCount);
|
||||
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 (gControllerPress[3].button & U_JPAD) {
|
||||
Main_SetVIMode();
|
||||
}
|
||||
{
|
||||
gSPSegment(gUnkDisp1++, 0, 0);
|
||||
gSPDisplayList(gMasterDisp++, gGfxPool->unkDL1);
|
||||
Game_Update();
|
||||
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[(gSysFrameCount - 1) % 3]);
|
||||
}
|
||||
func_80007FE4(&gFrameBuffers[(gSysFrameCount - 1) % 3], SCREEN_WIDTH, 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);
|
||||
}
|
||||
|
||||
Audio_Update();
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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_TIMER, 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Idle_ThreadEntry(void* arg0) {
|
||||
osCreateViManager(OS_PRIORITY_VIMGR);
|
||||
Main_SetVIMode();
|
||||
Lib_FillScreen(1);
|
||||
osCreatePiManager(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);
|
||||
loop_1:
|
||||
goto loop_1;
|
||||
}
|
||||
|
||||
void bootproc(void) {
|
||||
RdRam_CheckIPL3();
|
||||
osInitialize();
|
||||
Main_Initialize();
|
||||
osCreateThread(&sIdleThread, THREAD_ID_IDLE, &Idle_ThreadEntry, NULL, sIdleThreadStack + sizeof(sIdleThreadStack),
|
||||
255);
|
||||
osStartThread(&sIdleThread);
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
#include "sys.h"
|
||||
|
||||
s32 sSeededRandSeed3;
|
||||
s32 sRandSeed1;
|
||||
s32 sRandSeed2;
|
||||
s32 sRandSeed3;
|
||||
s32 sSeededRandSeed1;
|
||||
s32 sSeededRandSeed2;
|
||||
|
||||
f32 Math_ModF(f32 value, f32 mod) {
|
||||
return value - ((s32) (value / mod) * mod);
|
||||
}
|
||||
|
||||
void Rand_Init(void) {
|
||||
sRandSeed1 = (s32) osGetTime() % 30000;
|
||||
sRandSeed2 = (s32) osGetTime() % 30000;
|
||||
sRandSeed3 = (s32) osGetTime() % 30000;
|
||||
}
|
||||
|
||||
f32 Rand_ZeroOne(void) {
|
||||
sRandSeed1 = (sRandSeed1 * 171) % 30269;
|
||||
sRandSeed2 = (sRandSeed2 * 172) % 30307;
|
||||
sRandSeed3 = (sRandSeed3 * 170) % 30323;
|
||||
|
||||
return fabsf(Math_ModF((sRandSeed1 / 30269.0f) + (sRandSeed2 / 30307.0f) + (sRandSeed3 / 30323.0f), 1.0f));
|
||||
}
|
||||
|
||||
void Rand_SetSeed(s32 seed1, s32 seed2, s32 seed3) {
|
||||
sSeededRandSeed1 = seed1;
|
||||
sSeededRandSeed2 = seed2;
|
||||
sSeededRandSeed3 = seed3;
|
||||
}
|
||||
|
||||
f32 Rand_ZeroOneSeeded(void) {
|
||||
sSeededRandSeed1 = (sSeededRandSeed1 * 171) % 30269;
|
||||
sSeededRandSeed2 = (sSeededRandSeed2 * 172) % 30307;
|
||||
sSeededRandSeed3 = (sSeededRandSeed3 * 170) % 30323;
|
||||
|
||||
return fabsf(
|
||||
Math_ModF((sSeededRandSeed1 / 30269.0f) + (sSeededRandSeed2 / 30307.0f) + (sSeededRandSeed3 / 30323.0f), 1.0f));
|
||||
}
|
||||
|
||||
f32 Math_Atan2F(f32 y, f32 x) {
|
||||
if ((y == 0.0f) && (x == 0.0f)) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (x == 0.0f) {
|
||||
if (y < 0.0f) {
|
||||
return -M_PI / 2.0f;
|
||||
} else {
|
||||
return M_PI / 2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (x < 0.0f) {
|
||||
if (y < 0.0f) {
|
||||
return -(M_PI - Math_FAtanF(fabs(y / x)));
|
||||
} else {
|
||||
return M_PI - Math_FAtanF(fabs(y / x));
|
||||
}
|
||||
} else {
|
||||
return Math_FAtanF(y / x);
|
||||
}
|
||||
}
|
||||
|
||||
f32 Math_Atan2F_XY(f32 x, f32 y) {
|
||||
if ((x == 0.0f) && (y == 0.0f)) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (x == 0.0f) {
|
||||
if (y < 0.0f) {
|
||||
return -M_PI / 2.0f;
|
||||
} else {
|
||||
return M_PI / 2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (y == 0.0f) {
|
||||
if (x > 0.0f) {
|
||||
return 0.0f;
|
||||
} else {
|
||||
return M_PI;
|
||||
}
|
||||
}
|
||||
|
||||
if (x < 0.0f) {
|
||||
if (y < 0.0f) {
|
||||
return -(M_PI - Math_FAtanF(fabs(x / y)));
|
||||
} else {
|
||||
return M_PI - Math_FAtanF(fabs(x / y));
|
||||
}
|
||||
} else {
|
||||
return Math_FAtanF(x / y);
|
||||
}
|
||||
}
|
||||
|
||||
f32 Math_Atan2F_XYAlt(f32 x, f32 y) {
|
||||
if ((x == 0.0f) && (y == 0.0f)) {
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (x == 0.0f) {
|
||||
if (y < 0.0f) {
|
||||
return -M_PI / 2.0f;
|
||||
}
|
||||
return M_PI / 2.0f;
|
||||
}
|
||||
|
||||
if (y == 0.0f) {
|
||||
return 0.0f;
|
||||
}
|
||||
return -Math_FAtanF(x / y);
|
||||
}
|
||||
|
||||
f32 Math_FactorialF(f32 n) {
|
||||
f32 out = 1.0f;
|
||||
s32 i;
|
||||
|
||||
for (i = (s32) n; i > 1; i--) {
|
||||
out *= i;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
f32 D_800C45E0[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600 };
|
||||
|
||||
f32 Math_Factorial(s32 n) {
|
||||
f32 out;
|
||||
s32 i;
|
||||
|
||||
if (n > 12) {
|
||||
out = 1.0f;
|
||||
|
||||
for (i = n; i > 1; i--) {
|
||||
out *= i;
|
||||
}
|
||||
} else {
|
||||
out = D_800C45E0[n];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
f32 Math_PowF(f32 base, s32 exp) {
|
||||
f32 out = 1.0f;
|
||||
|
||||
while (exp > 0) {
|
||||
exp--;
|
||||
out *= base;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void Math_MinMax(s32* min, s32* max, s32 val1, s32 val2, s32 val3) {
|
||||
if (val1 < val2) {
|
||||
if (val2 < val3) {
|
||||
*min = val1;
|
||||
*max = val3;
|
||||
return;
|
||||
}
|
||||
*max = val2;
|
||||
|
||||
if (val1 < val3) {
|
||||
*min = val1;
|
||||
return;
|
||||
}
|
||||
*min = val3;
|
||||
return;
|
||||
}
|
||||
|
||||
if (val1 < val3) {
|
||||
*min = val2;
|
||||
*max = val3;
|
||||
return;
|
||||
}
|
||||
*max = val1;
|
||||
|
||||
if (val2 < val3) {
|
||||
*min = val2;
|
||||
return;
|
||||
}
|
||||
*min = val3;
|
||||
}
|
||||
@@ -0,0 +1,513 @@
|
||||
#include "sys.h"
|
||||
|
||||
Mtx gIdentityMtx = { {
|
||||
{
|
||||
{ 1, 0, 0, 0 },
|
||||
{ 0, 1, 0, 0 },
|
||||
{ 0, 0, 1, 0 },
|
||||
{ 0, 0, 0, 1 },
|
||||
},
|
||||
{
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0 },
|
||||
{ 0, 0, 0, 0 },
|
||||
},
|
||||
} };
|
||||
|
||||
Matrix gIdentityMatrix = { {
|
||||
{ 1.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 1.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 1.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 1.0f },
|
||||
} };
|
||||
|
||||
Matrix* gGfxMatrix;
|
||||
Matrix sGfxMatrixStack[0x20];
|
||||
Matrix* gCalcMatrix;
|
||||
Matrix sCalcMatrixStack[0x20];
|
||||
|
||||
// Copies src Matrix into dst
|
||||
void Matrix_Copy(Matrix* dst, Matrix* src) {
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
dst->m[i][0] = src->m[i][0];
|
||||
dst->m[i][1] = src->m[i][1];
|
||||
dst->m[i][2] = src->m[i][2];
|
||||
dst->m[i][3] = src->m[i][3];
|
||||
}
|
||||
}
|
||||
|
||||
// Makes a copy of the stack's current matrix and puts it on the top of the stack
|
||||
void Matrix_Push(Matrix** mtxStack) {
|
||||
Matrix_Copy(*mtxStack + 1, *mtxStack);
|
||||
*mtxStack += 1;
|
||||
}
|
||||
|
||||
// Removes the top matrix of the stack
|
||||
void Matrix_Pop(Matrix** mtxStack) {
|
||||
*mtxStack -= 1;
|
||||
}
|
||||
|
||||
// Copies tf into mtx (MTXMODE_NEW) or applies it to mtx (MTXMODE_APPLY)
|
||||
void Matrix_Mult(Matrix* mtx, Matrix* tf, u8 mode) {
|
||||
f32 rx;
|
||||
f32 ry;
|
||||
f32 rz;
|
||||
f32 rw;
|
||||
s32 i0;
|
||||
s32 i1;
|
||||
s32 i2;
|
||||
s32 i3;
|
||||
|
||||
if (mode == 1) {
|
||||
rx = mtx->m[0][0];
|
||||
ry = mtx->m[1][0];
|
||||
rz = mtx->m[2][0];
|
||||
rw = mtx->m[3][0];
|
||||
|
||||
for (i0 = 0; i0 < 4; i0++) {
|
||||
mtx->m[i0][0] = (rx * tf->m[i0][0]) + (ry * tf->m[i0][1]) + (rz * tf->m[i0][2]) + (rw * tf->m[i0][3]);
|
||||
}
|
||||
|
||||
rx = mtx->m[0][1];
|
||||
ry = mtx->m[1][1];
|
||||
rz = mtx->m[2][1];
|
||||
rw = mtx->m[3][1];
|
||||
|
||||
for (i1 = 0; i1 < 4; i1++) {
|
||||
mtx->m[i1][1] = (rx * tf->m[i1][0]) + (ry * tf->m[i1][1]) + (rz * tf->m[i1][2]) + (rw * tf->m[i1][3]);
|
||||
}
|
||||
|
||||
rx = mtx->m[0][2];
|
||||
ry = mtx->m[1][2];
|
||||
rz = mtx->m[2][2];
|
||||
rw = mtx->m[3][2];
|
||||
|
||||
for (i2 = 0; i2 < 4; i2++) {
|
||||
mtx->m[i2][2] = (rx * tf->m[i2][0]) + (ry * tf->m[i2][1]) + (rz * tf->m[i2][2]) + (rw * tf->m[i2][3]);
|
||||
}
|
||||
|
||||
rx = mtx->m[0][3];
|
||||
ry = mtx->m[1][3];
|
||||
rz = mtx->m[2][3];
|
||||
rw = mtx->m[3][3];
|
||||
|
||||
for (i3 = 0; i3 < 4; i3++) {
|
||||
mtx->m[i3][3] = (rx * tf->m[i3][0]) + (ry * tf->m[i3][1]) + (rz * tf->m[i3][2]) + (rw * tf->m[i3][3]);
|
||||
}
|
||||
} else {
|
||||
Matrix_Copy(mtx, tf);
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a translation matrix in mtx (MTXMODE_NEW) or applies one to mtx (MTXMODE_APPLY)
|
||||
void Matrix_Translate(Matrix* mtx, f32 x, f32 y, f32 z, u8 mode) {
|
||||
f32 rx;
|
||||
f32 ry;
|
||||
s32 i;
|
||||
|
||||
if (mode == 1) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
rx = mtx->m[0][i];
|
||||
ry = mtx->m[1][i];
|
||||
|
||||
mtx->m[3][i] += (rx * x) + (ry * y) + (mtx->m[2][i] * z);
|
||||
}
|
||||
} else {
|
||||
mtx->m[3][0] = x;
|
||||
mtx->m[3][1] = y;
|
||||
mtx->m[3][2] = z;
|
||||
mtx->m[0][1] = mtx->m[0][2] = mtx->m[0][3] = mtx->m[1][0] = mtx->m[1][2] = mtx->m[1][3] = mtx->m[2][0] =
|
||||
mtx->m[2][1] = mtx->m[2][3] = 0.0f;
|
||||
mtx->m[0][0] = mtx->m[1][1] = mtx->m[2][2] = mtx->m[3][3] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a scale matrix in mtx (MTXMODE_NEW) or applies one to mtx (MTXMODE_APPLY)
|
||||
void Matrix_Scale(Matrix* mtx, f32 xScale, f32 yScale, f32 zScale, u8 mode) {
|
||||
f32 rx;
|
||||
f32 ry;
|
||||
s32 i;
|
||||
|
||||
if (mode == 1) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
rx = mtx->m[0][i];
|
||||
ry = mtx->m[1][i];
|
||||
|
||||
mtx->m[0][i] = rx * xScale;
|
||||
mtx->m[1][i] = ry * yScale;
|
||||
mtx->m[2][i] *= zScale;
|
||||
}
|
||||
} else {
|
||||
mtx->m[0][0] = xScale;
|
||||
mtx->m[1][1] = yScale;
|
||||
mtx->m[2][2] = zScale;
|
||||
mtx->m[0][1] = mtx->m[0][2] = mtx->m[0][3] = mtx->m[1][0] = mtx->m[1][2] = mtx->m[1][3] = mtx->m[2][0] =
|
||||
mtx->m[2][1] = mtx->m[2][3] = mtx->m[3][0] = mtx->m[3][1] = mtx->m[3][2] = 0.0f;
|
||||
mtx->m[3][3] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Creates rotation matrix about the X axis in mtx (MTXMODE_NEW) or applies one to mtx (MTXMODE_APPLY)
|
||||
void Matrix_RotateX(Matrix* mtx, f32 angle, u8 mode) {
|
||||
f32 cs;
|
||||
f32 sn;
|
||||
f32 ry;
|
||||
f32 rz;
|
||||
s32 i;
|
||||
|
||||
sn = __sinf(angle);
|
||||
cs = __cosf(angle);
|
||||
if (mode == 1) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
ry = mtx->m[1][i];
|
||||
rz = mtx->m[2][i];
|
||||
|
||||
mtx->m[1][i] = (ry * cs) + (rz * sn);
|
||||
mtx->m[2][i] = (rz * cs) - (ry * sn);
|
||||
}
|
||||
} else {
|
||||
mtx->m[1][1] = mtx->m[2][2] = cs;
|
||||
mtx->m[1][2] = sn;
|
||||
mtx->m[2][1] = -sn;
|
||||
mtx->m[0][0] = mtx->m[3][3] = 1.0f;
|
||||
mtx->m[0][1] = mtx->m[0][2] = mtx->m[0][3] = mtx->m[1][0] = mtx->m[1][3] = mtx->m[2][0] = mtx->m[2][3] =
|
||||
mtx->m[3][0] = mtx->m[3][1] = mtx->m[3][2] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Creates rotation matrix about the Y axis in mtx (MTXMODE_NEW) or applies one to mtx (MTXMODE_APPLY)
|
||||
void Matrix_RotateY(Matrix* mtx, f32 angle, u8 mode) {
|
||||
f32 cs;
|
||||
f32 sn;
|
||||
f32 rx;
|
||||
f32 rz;
|
||||
s32 i;
|
||||
|
||||
sn = __sinf(angle);
|
||||
cs = __cosf(angle);
|
||||
if (mode == 1) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
rx = mtx->m[0][i];
|
||||
rz = mtx->m[2][i];
|
||||
|
||||
mtx->m[0][i] = (rx * cs) - (rz * sn);
|
||||
mtx->m[2][i] = (rx * sn) + (rz * cs);
|
||||
}
|
||||
} else {
|
||||
mtx->m[0][0] = mtx->m[2][2] = cs;
|
||||
mtx->m[0][2] = -sn;
|
||||
mtx->m[2][0] = sn;
|
||||
mtx->m[1][1] = mtx->m[3][3] = 1.0f;
|
||||
mtx->m[0][1] = mtx->m[0][3] = mtx->m[1][0] = mtx->m[1][2] = mtx->m[1][3] = mtx->m[2][1] = mtx->m[2][3] =
|
||||
mtx->m[3][0] = mtx->m[3][1] = mtx->m[3][2] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Creates rotation matrix about the Z axis in mtx (MTXMODE_NEW) or applies one to mtx (MTXMODE_APPLY)
|
||||
void Matrix_RotateZ(Matrix* mtx, f32 angle, u8 mode) {
|
||||
f32 cs;
|
||||
f32 sn;
|
||||
f32 rx;
|
||||
f32 ry;
|
||||
s32 i;
|
||||
|
||||
sn = __sinf(angle);
|
||||
cs = __cosf(angle);
|
||||
if (mode == 1) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
rx = mtx->m[0][i];
|
||||
ry = mtx->m[1][i];
|
||||
|
||||
mtx->m[0][i] = (rx * cs) + (ry * sn);
|
||||
mtx->m[1][i] = (ry * cs) - (rx * sn);
|
||||
}
|
||||
} else {
|
||||
mtx->m[0][0] = mtx->m[1][1] = cs;
|
||||
mtx->m[0][1] = sn;
|
||||
mtx->m[1][0] = -sn;
|
||||
mtx->m[2][2] = mtx->m[3][3] = 1.0f;
|
||||
mtx->m[0][2] = mtx->m[0][3] = mtx->m[1][2] = mtx->m[1][3] = mtx->m[2][0] = mtx->m[2][1] = mtx->m[2][3] =
|
||||
mtx->m[3][0] = mtx->m[3][1] = mtx->m[3][2] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
// Creates rotation matrix about a given vector axis in mtx (MTXMODE_NEW) or applies one to mtx (MTXMODE_APPLY).
|
||||
// The vector specifying the axis does not need to be a unit vector.
|
||||
void Matrix_RotateAxis(Matrix* mtx, f32 angle, f32 axisX, f32 axisY, f32 axisZ, u8 mode) {
|
||||
f32 rx;
|
||||
f32 ry;
|
||||
f32 rz;
|
||||
f32 norm;
|
||||
f32 cxx;
|
||||
f32 cyx;
|
||||
f32 czx;
|
||||
f32 cxy;
|
||||
f32 cyy;
|
||||
f32 czy;
|
||||
f32 cxz;
|
||||
f32 cyz;
|
||||
f32 czz;
|
||||
f32 xx;
|
||||
f32 yy;
|
||||
f32 zz;
|
||||
f32 xy;
|
||||
f32 yz;
|
||||
f32 xz;
|
||||
f32 sinA;
|
||||
f32 cosA;
|
||||
|
||||
norm = sqrtf((axisX * axisX) + (axisY * axisY) + (axisZ * axisZ));
|
||||
if (norm != 0.0) {
|
||||
axisX /= norm;
|
||||
axisY /= norm;
|
||||
axisZ /= norm;
|
||||
sinA = __sinf(angle);
|
||||
cosA = __cosf(angle);
|
||||
xx = axisX * axisX;
|
||||
yy = axisY * axisY;
|
||||
zz = axisZ * axisZ;
|
||||
xy = axisX * axisY;
|
||||
yz = axisY * axisZ;
|
||||
xz = axisX * axisZ;
|
||||
|
||||
if (mode == 1) {
|
||||
cxx = (1.0f - xx) * cosA + xx;
|
||||
cyx = (1.0f - cosA) * xy + axisZ * sinA;
|
||||
czx = (1.0f - cosA) * xz - axisY * sinA;
|
||||
|
||||
cxy = (1.0f - cosA) * xy - axisZ * sinA;
|
||||
cyy = (1.0f - yy) * cosA + yy;
|
||||
czy = (1.0f - cosA) * yz + axisX * sinA;
|
||||
|
||||
cxz = (1.0f - cosA) * xz + axisY * sinA;
|
||||
cyz = (1.0f - cosA) * yz - axisX * sinA;
|
||||
czz = (1.0f - zz) * cosA + zz;
|
||||
|
||||
// loop doesn't seem to work here.
|
||||
rx = mtx->m[0][0];
|
||||
ry = mtx->m[0][1];
|
||||
rz = mtx->m[0][2];
|
||||
mtx->m[0][0] = (rx * cxx) + (ry * cxy) + (rz * cxz);
|
||||
mtx->m[0][1] = (rx * cyx) + (ry * cyy) + (rz * cyz);
|
||||
mtx->m[0][2] = (rx * czx) + (ry * czy) + (rz * czz);
|
||||
|
||||
rx = mtx->m[1][0];
|
||||
ry = mtx->m[1][1];
|
||||
rz = mtx->m[1][2];
|
||||
mtx->m[1][0] = (rx * cxx) + (ry * cxy) + (rz * cxz);
|
||||
mtx->m[1][1] = (rx * cyx) + (ry * cyy) + (rz * cyz);
|
||||
mtx->m[1][2] = (rx * czx) + (ry * czy) + (rz * czz);
|
||||
|
||||
rx = mtx->m[2][0];
|
||||
ry = mtx->m[2][1];
|
||||
rz = mtx->m[2][2];
|
||||
mtx->m[2][0] = (rx * cxx) + (ry * cxy) + (rz * cxz);
|
||||
mtx->m[2][1] = (rx * cyx) + (ry * cyy) + (rz * cyz);
|
||||
mtx->m[2][2] = (rx * czx) + (ry * czy) + (rz * czz);
|
||||
} else {
|
||||
mtx->m[0][0] = (1.0f - xx) * cosA + xx;
|
||||
mtx->m[0][1] = (1.0f - cosA) * xy + axisZ * sinA;
|
||||
mtx->m[0][2] = (1.0f - cosA) * xz - axisY * sinA;
|
||||
mtx->m[0][3] = 0.0f;
|
||||
|
||||
mtx->m[1][0] = (1.0f - cosA) * xy - axisZ * sinA;
|
||||
mtx->m[1][1] = (1.0f - yy) * cosA + yy;
|
||||
mtx->m[1][2] = (1.0f - cosA) * yz + axisX * sinA;
|
||||
mtx->m[1][3] = 0.0f;
|
||||
|
||||
mtx->m[2][0] = (1.0f - cosA) * xz + axisY * sinA;
|
||||
mtx->m[2][1] = (1.0f - cosA) * yz - axisX * sinA;
|
||||
mtx->m[2][2] = (1.0f - zz) * cosA + zz;
|
||||
mtx->m[2][3] = 0.0f;
|
||||
|
||||
mtx->m[3][0] = mtx->m[3][1] = mtx->m[3][2] = 0.0f;
|
||||
mtx->m[3][3] = 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Converts the current Gfx matrix to a Mtx
|
||||
void Matrix_ToMtx(Mtx* dest) {
|
||||
s32 intVal;
|
||||
u16(*iPart)[4] = dest->u.i;
|
||||
u16(*fPart)[4] = dest->u.f;
|
||||
Matrix* src = gGfxMatrix;
|
||||
|
||||
intVal = src->m[0][0] * 0x10000;
|
||||
iPart[0][0] = intVal >> 0x10;
|
||||
fPart[0][0] = intVal % 0x10000U;
|
||||
|
||||
intVal = src->m[0][1] * 0x10000;
|
||||
iPart[0][1] = intVal >> 0x10;
|
||||
fPart[0][1] = intVal % 0x10000U;
|
||||
|
||||
intVal = src->m[0][2] * 0x10000;
|
||||
iPart[0][2] = intVal >> 0x10;
|
||||
fPart[0][2] = intVal % 0x10000U;
|
||||
|
||||
intVal = src->m[0][3] * 0x10000;
|
||||
iPart[0][3] = intVal >> 0x10;
|
||||
fPart[0][3] = intVal % 0x10000U;
|
||||
|
||||
intVal = src->m[1][0] * 0x10000;
|
||||
iPart[1][0] = intVal >> 0x10;
|
||||
fPart[1][0] = intVal % 0x10000U;
|
||||
|
||||
intVal = src->m[1][1] * 0x10000;
|
||||
iPart[1][1] = intVal >> 0x10;
|
||||
fPart[1][1] = intVal % 0x10000U;
|
||||
|
||||
intVal = src->m[1][2] * 0x10000;
|
||||
iPart[1][2] = intVal >> 0x10;
|
||||
fPart[1][2] = intVal % 0x10000U;
|
||||
|
||||
intVal = src->m[1][3] * 0x10000;
|
||||
iPart[1][3] = intVal >> 0x10;
|
||||
fPart[1][3] = intVal % 0x10000U;
|
||||
|
||||
intVal = src->m[2][0] * 0x10000;
|
||||
iPart[2][0] = intVal >> 0x10;
|
||||
fPart[2][0] = intVal % 0x10000U;
|
||||
|
||||
intVal = src->m[2][1] * 0x10000;
|
||||
iPart[2][1] = intVal >> 0x10;
|
||||
fPart[2][1] = intVal % 0x10000U;
|
||||
|
||||
intVal = src->m[2][2] * 0x10000;
|
||||
iPart[2][2] = intVal >> 0x10;
|
||||
fPart[2][2] = intVal % 0x10000U;
|
||||
|
||||
intVal = src->m[2][3] * 0x10000;
|
||||
iPart[2][3] = intVal >> 0x10;
|
||||
fPart[2][3] = intVal % 0x10000U;
|
||||
|
||||
intVal = src->m[3][0] * 0x10000;
|
||||
iPart[3][0] = intVal >> 0x10;
|
||||
fPart[3][0] = intVal % 0x10000U;
|
||||
|
||||
intVal = src->m[3][1] * 0x10000;
|
||||
iPart[3][1] = intVal >> 0x10;
|
||||
fPart[3][1] = intVal % 0x10000U;
|
||||
|
||||
intVal = src->m[3][2] * 0x10000;
|
||||
iPart[3][2] = intVal >> 0x10;
|
||||
fPart[3][2] = intVal % 0x10000U;
|
||||
|
||||
intVal = src->m[3][3] * 0x10000;
|
||||
iPart[3][3] = intVal >> 0x10;
|
||||
fPart[3][3] = intVal % 0x10000U;
|
||||
}
|
||||
|
||||
// Converts the Mtx src to a Matrix, putting the result in dest
|
||||
void Matrix_FromMtx(Mtx* src, Matrix* dest) {
|
||||
dest->m[0][0] = ((src->u.i[0][0] << 0x10) | src->u.f[0][0]) * (1.0f / 0x10000);
|
||||
dest->m[0][1] = ((src->u.i[0][1] << 0x10) | src->u.f[0][1]) * (1.0f / 0x10000);
|
||||
dest->m[0][2] = ((src->u.i[0][2] << 0x10) | src->u.f[0][2]) * (1.0f / 0x10000);
|
||||
dest->m[0][3] = ((src->u.i[0][3] << 0x10) | src->u.f[0][3]) * (1.0f / 0x10000);
|
||||
dest->m[1][0] = ((src->u.i[1][0] << 0x10) | src->u.f[1][0]) * (1.0f / 0x10000);
|
||||
dest->m[1][1] = ((src->u.i[1][1] << 0x10) | src->u.f[1][1]) * (1.0f / 0x10000);
|
||||
dest->m[1][2] = ((src->u.i[1][2] << 0x10) | src->u.f[1][2]) * (1.0f / 0x10000);
|
||||
dest->m[1][3] = ((src->u.i[1][3] << 0x10) | src->u.f[1][3]) * (1.0f / 0x10000);
|
||||
dest->m[2][0] = ((src->u.i[2][0] << 0x10) | src->u.f[2][0]) * (1.0f / 0x10000);
|
||||
dest->m[2][1] = ((src->u.i[2][1] << 0x10) | src->u.f[2][1]) * (1.0f / 0x10000);
|
||||
dest->m[2][2] = ((src->u.i[2][2] << 0x10) | src->u.f[2][2]) * (1.0f / 0x10000);
|
||||
dest->m[2][3] = ((src->u.i[2][3] << 0x10) | src->u.f[2][3]) * (1.0f / 0x10000);
|
||||
dest->m[3][0] = ((src->u.i[3][0] << 0x10) | src->u.f[3][0]) * (1.0f / 0x10000);
|
||||
dest->m[3][1] = ((src->u.i[3][1] << 0x10) | src->u.f[3][1]) * (1.0f / 0x10000);
|
||||
dest->m[3][2] = ((src->u.i[3][2] << 0x10) | src->u.f[3][2]) * (1.0f / 0x10000);
|
||||
dest->m[3][3] = ((src->u.i[3][3] << 0x10) | src->u.f[3][3]) * (1.0f / 0x10000);
|
||||
}
|
||||
|
||||
// Applies the transform matrix mtx to the vector src, putting the result in dest
|
||||
void Matrix_MultVec3f(Matrix* mtx, Vec3f* src, Vec3f* dest) {
|
||||
dest->x = (mtx->m[0][0] * src->x) + (mtx->m[1][0] * src->y) + (mtx->m[2][0] * src->z) + mtx->m[3][0];
|
||||
dest->y = (mtx->m[0][1] * src->x) + (mtx->m[1][1] * src->y) + (mtx->m[2][1] * src->z) + mtx->m[3][1];
|
||||
dest->z = (mtx->m[0][2] * src->x) + (mtx->m[1][2] * src->y) + (mtx->m[2][2] * src->z) + mtx->m[3][2];
|
||||
}
|
||||
|
||||
// Applies the linear part of the transformation matrix mtx to the vector src, ignoring any translation that mtx might
|
||||
// have. Puts the result in dest.
|
||||
void Matrix_MultVec3fNoTranslate(Matrix* mtx, Vec3f* src, Vec3f* dest) {
|
||||
dest->x = (mtx->m[0][0] * src->x) + (mtx->m[1][0] * src->y) + (mtx->m[2][0] * src->z);
|
||||
dest->y = (mtx->m[0][1] * src->x) + (mtx->m[1][1] * src->y) + (mtx->m[2][1] * src->z);
|
||||
dest->z = (mtx->m[0][2] * src->x) + (mtx->m[1][2] * src->y) + (mtx->m[2][2] * src->z);
|
||||
}
|
||||
|
||||
// Expresses the rotational part of the transform mtx as Tait-Bryan angles, in the yaw-pitch-roll (intrinsic YXZ)
|
||||
// convention used in worldspace calculations
|
||||
void Matrix_GetYRPAngles(Matrix* mtx, Vec3f* rot) {
|
||||
Matrix invYP;
|
||||
Vec3f origin = { 0.0f, 0.0f, 0.0f };
|
||||
Vec3f originP;
|
||||
Vec3f zHat = { 0.0f, 0.0f, 1.0f };
|
||||
Vec3f zHatP;
|
||||
Vec3f xHat = { 1.0f, 0.0f, 0.0f };
|
||||
Vec3f xHatP;
|
||||
|
||||
Matrix_MultVec3fNoTranslate(mtx, &origin, &originP);
|
||||
Matrix_MultVec3fNoTranslate(mtx, &zHat, &zHatP);
|
||||
Matrix_MultVec3fNoTranslate(mtx, &xHat, &xHatP);
|
||||
zHatP.x -= originP.x;
|
||||
zHatP.y -= originP.y;
|
||||
zHatP.z -= originP.z;
|
||||
xHatP.x -= originP.x;
|
||||
xHatP.y -= originP.y;
|
||||
xHatP.z -= originP.z;
|
||||
rot->y = Math_Atan2F(zHatP.x, zHatP.z);
|
||||
rot->x = -Math_Atan2F(zHatP.y, sqrtf(SQ(zHatP.x) + SQ(zHatP.z)));
|
||||
Matrix_RotateX(&invYP, -rot->x, 0);
|
||||
Matrix_RotateY(&invYP, -rot->y, 1);
|
||||
Matrix_MultVec3fNoTranslate(&invYP, &xHatP, &xHat);
|
||||
rot->x *= M_RTOD;
|
||||
rot->y *= M_RTOD;
|
||||
rot->z = Math_Atan2F(xHat.y, xHat.x) * M_RTOD;
|
||||
}
|
||||
|
||||
// Expresses the rotational part of the transform mtx as Tait-Bryan angles, in the extrinsic XYZ convention used in
|
||||
// modelspace calculations
|
||||
void Matrix_GetXYZAngles(Matrix* mtx, Vec3f* rot) {
|
||||
Matrix invYZ;
|
||||
Vec3f origin = { 0.0f, 0.0f, 0.0f };
|
||||
Vec3f originP;
|
||||
Vec3f xHat = { 1.0f, 0.0f, 0.0f };
|
||||
Vec3f xHatP;
|
||||
Vec3f yHat = { 0.0f, 1.0f, 0.0f };
|
||||
Vec3f yHatP;
|
||||
|
||||
Matrix_MultVec3fNoTranslate(mtx, &origin, &originP);
|
||||
Matrix_MultVec3fNoTranslate(mtx, &xHat, &xHatP);
|
||||
Matrix_MultVec3fNoTranslate(mtx, &yHat, &yHatP);
|
||||
xHatP.x -= originP.x;
|
||||
xHatP.y -= originP.y;
|
||||
xHatP.z -= originP.z;
|
||||
yHatP.x -= originP.x;
|
||||
yHatP.y -= originP.y;
|
||||
yHatP.z -= originP.z;
|
||||
rot->z = Math_Atan2F(xHatP.y, xHatP.x);
|
||||
rot->y = -Math_Atan2F(xHatP.z, sqrtf(SQ(xHatP.x) + SQ(xHatP.y)));
|
||||
Matrix_RotateY(&invYZ, -rot->y, 0);
|
||||
Matrix_RotateZ(&invYZ, -rot->z, 1);
|
||||
Matrix_MultVec3fNoTranslate(&invYZ, &yHatP, &yHat);
|
||||
rot->x = Math_Atan2F(yHat.z, yHat.y) * M_RTOD;
|
||||
rot->y *= M_RTOD;
|
||||
rot->z *= M_RTOD;
|
||||
}
|
||||
|
||||
// Creates a look-at matrix from Eye, At, and Up in mtx (MTXMODE_NEW) or applies one to mtx (MTXMODE_APPLY).
|
||||
// A look-at matrix is a rotation-translation matrix that maps y to Up, z to (At - Eye), and translates to Eye
|
||||
void Matrix_LookAt(Matrix* mtx, f32 xEye, f32 yEye, f32 zEye, f32 xAt, f32 yAt, f32 zAt, f32 xUp, f32 yUp, f32 zUp,
|
||||
u8 mode) {
|
||||
Matrix lookAt;
|
||||
|
||||
guLookAtF(lookAt.m, xEye, yEye, zEye, xAt, yAt, zAt, xUp, yUp, zUp);
|
||||
Matrix_Mult(mtx, &lookAt, mode);
|
||||
}
|
||||
|
||||
// Converts the current Gfx matrix to a Mtx and sets it to the display list
|
||||
void Matrix_SetGfxMtx(Gfx** gfx) {
|
||||
Matrix_ToMtx(gGfxMtx);
|
||||
gSPMatrix((*gfx)++, gGfxMtx++, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "sys.h"
|
||||
|
||||
s32 sMemoryBuffer[0x2200];
|
||||
s32* sMemoryPtr;
|
||||
|
||||
void Memory_FreeAll(void) {
|
||||
sMemoryPtr = sMemoryBuffer;
|
||||
}
|
||||
|
||||
void* Memory_Allocate(s32 size) {
|
||||
void* addr = sMemoryPtr;
|
||||
|
||||
sMemoryPtr = (void*) (((size + 0xF) & ~0xF) + (uintptr_t) sMemoryPtr);
|
||||
return addr;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
|
||||
|
||||
#include "sys.h"
|
||||
|
||||
SaveFile gSaveIOBuffer;
|
||||
SaveFile sPrevSaveData;
|
||||
|
||||
s32 Save_ReadBlock(s32 arg0, u8* arg1) {
|
||||
if (osEepromRead(&gSerialEventQueue, arg0, arg1)) {
|
||||
(void) "EEPROM インターフェース回路反応なし (READ)\n";
|
||||
return -1;
|
||||
}
|
||||
(void) "EEPROM READ %02X: %02X %02X %02X %02X %02X %02X %02X %02X\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 Save_WriteBlock(s32 arg0, u8* arg1) {
|
||||
if (osEepromWrite(&gSerialEventQueue, arg0, arg1)) {
|
||||
(void) "EEPROM インターフェース回路反応なし (WRITE)\n";
|
||||
return -1;
|
||||
}
|
||||
Timer_Wait(MSEC_TO_CYCLES(15));
|
||||
(void) "EEPROM WRITE %02X: %02X %02X %02X %02X %02X %02X %02X %02X\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 Save_WriteEeprom(SaveFile* arg0) {
|
||||
s32 var_a2;
|
||||
s32 i;
|
||||
s32 j;
|
||||
|
||||
if (osEepromProbe(&gSerialEventQueue) != 1) {
|
||||
(void) "EEPROM が ありません\n";
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < EEPROM_MAXBLOCKS; i++) {
|
||||
var_a2 = 0;
|
||||
for (j = 0; j < EEPROM_BLOCK_SIZE; j++) {
|
||||
if (((char*) &sPrevSaveData)[EEPROM_BLOCK_SIZE * i + j] != ((char*) arg0)[EEPROM_BLOCK_SIZE * i + j]) {
|
||||
((char*) &sPrevSaveData)[EEPROM_BLOCK_SIZE * i + j] = ((char*) arg0)[EEPROM_BLOCK_SIZE * i + j];
|
||||
var_a2 = 1;
|
||||
}
|
||||
}
|
||||
if ((var_a2 == 1) && Save_WriteBlock(i, &((char*) arg0)[EEPROM_BLOCK_SIZE * i])) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 Save_ReadEeprom(SaveFile* arg0) {
|
||||
s32 i;
|
||||
|
||||
if (osEepromProbe(&gSerialEventQueue) != 1) {
|
||||
(void) "EEPROM が ありません\n";
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < EEPROM_MAXBLOCKS; i++) {
|
||||
if (Save_ReadBlock(i, &((char*) arg0)[EEPROM_BLOCK_SIZE * i]) != 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
sPrevSaveData = *arg0;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#include "sys.h"
|
||||
|
||||
TimerTask sTimerTasks[0x10];
|
||||
|
||||
TimerTask* Timer_AllocateTask(void) {
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < 0x10; i++) {
|
||||
if (!sTimerTasks[i].active) {
|
||||
return &sTimerTasks[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s32 Timer_CreateTask(u64 time, TimerAction action, s32* address, s32 value) {
|
||||
TimerTask* task = Timer_AllocateTask();
|
||||
|
||||
if (task == NULL) {
|
||||
return -1;
|
||||
}
|
||||
task->active = true;
|
||||
task->action = action;
|
||||
task->address = address;
|
||||
task->value = value;
|
||||
return osSetTimer(&task->timer, time, 0, &gTimerTaskMsgQueue, task);
|
||||
}
|
||||
|
||||
void Timer_Increment(s32* address, s32 value) {
|
||||
*address += value;
|
||||
}
|
||||
|
||||
void Timer_SetValue(s32* address, s32 value) {
|
||||
*address = value;
|
||||
}
|
||||
|
||||
void Timer_CompleteTask(TimerTask* task) {
|
||||
if (task->action != NULL) {
|
||||
task->action(task->address, task->value);
|
||||
}
|
||||
task->active = false;
|
||||
}
|
||||
|
||||
void Timer_Wait(u64 time) {
|
||||
OSTimer timer;
|
||||
OSMesg dummy;
|
||||
|
||||
osSetTimer(&timer, time, 0, &gTimerWaitMsgQueue, NULL);
|
||||
osRecvMesg(&gTimerWaitMsgQueue, &dummy, OS_MESG_BLOCK);
|
||||
}
|
||||
Reference in New Issue
Block a user