summaryrefslogtreecommitdiff
path: root/src/libultra_boot_O2
diff options
context:
space:
mode:
authorJack Walker <7463599+Jack-Walker@users.noreply.github.com>2020-03-17 00:31:30 -0400
committerJack Walker <7463599+Jack-Walker@users.noreply.github.com>2020-03-17 00:31:30 -0400
commit087f561f7786a812c815b9198f24e6acd0477497 (patch)
tree8e8b1efeb798ff0b341d39de024d7b8554013c4a /src/libultra_boot_O2
parentbe78236d36a5eb4ef80acef6188751f6b5d176ae (diff)
First proper commit.
Diffstat (limited to 'src/libultra_boot_O2')
-rw-r--r--src/libultra_boot_O2/_Ldtob.c286
-rw-r--r--src/libultra_boot_O2/_Litob.c54
-rw-r--r--src/libultra_boot_O2/_Printf.c230
-rw-r--r--src/libultra_boot_O2/__osDevMgrMain.c102
-rw-r--r--src/libultra_boot_O2/__osEPiRawReadIo.c54
-rw-r--r--src/libultra_boot_O2/__osEPiRawStartDma.c69
-rw-r--r--src/libultra_boot_O2/__osEPiRawWriteIo.c54
-rw-r--r--src/libultra_boot_O2/__osPiRawStartDma.c30
-rw-r--r--src/libultra_boot_O2/__osSiDeviceBusy.c12
-rw-r--r--src/libultra_boot_O2/__osSiRawReadIo.c10
-rw-r--r--src/libultra_boot_O2/__osSiRawWriteIo.c10
-rw-r--r--src/libultra_boot_O2/__osViGetCurrentContext.c6
-rw-r--r--src/libultra_boot_O2/__osViInit.c34
-rw-r--r--src/libultra_boot_O2/__osViSwapContext.c64
-rw-r--r--src/libultra_boot_O2/ldiv.c28
-rw-r--r--src/libultra_boot_O2/osCartRomInit.c64
-rw-r--r--src/libultra_boot_O2/osDriveRomInit.c60
-rw-r--r--src/libultra_boot_O2/osEPiReadIo.c12
-rw-r--r--src/libultra_boot_O2/osEPiStartDma.c21
-rw-r--r--src/libultra_boot_O2/osEPiWriteIo.c12
-rw-r--r--src/libultra_boot_O2/osPiGetCmdQueue.c9
-rw-r--r--src/libultra_boot_O2/osViBlack.c13
-rw-r--r--src/libultra_boot_O2/osViGetNextFramebuffer.c9
-rw-r--r--src/libultra_boot_O2/osViModeFpalLan1.c33
-rw-r--r--src/libultra_boot_O2/osViModeMpalLan1.c33
-rw-r--r--src/libultra_boot_O2/osViModeNtscLan1.c33
-rw-r--r--src/libultra_boot_O2/osViSetMode.c10
-rw-r--r--src/libultra_boot_O2/osViSetSpecialFeatures.c37
-rw-r--r--src/libultra_boot_O2/osViSetXScale.c18
-rw-r--r--src/libultra_boot_O2/osViSetYScale.c11
-rw-r--r--src/libultra_boot_O2/osViSwapBuffer.c9
-rw-r--r--src/libultra_boot_O2/pimgr.c60
-rw-r--r--src/libultra_boot_O2/sprintf.c26
-rw-r--r--src/libultra_boot_O2/string.c33
-rw-r--r--src/libultra_boot_O2/vimgr.c125
35 files changed, 1671 insertions, 0 deletions
diff --git a/src/libultra_boot_O2/_Ldtob.c b/src/libultra_boot_O2/_Ldtob.c
new file mode 100644
index 000000000..4a72dfd33
--- /dev/null
+++ b/src/libultra_boot_O2/_Ldtob.c
@@ -0,0 +1,286 @@
+#include <global.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ultra64/printf.h>
+
+#define BUFF_LEN 0x20
+
+s16 _Ldunscale(s16 *, _Pft *);
+void _Genld(_Pft *, u8, u8 *, s16, s16);
+
+const double D_800122E0[] = { 10e0L, 10e1L, 10e3L, 10e7L, 10e15L, 10e31L, 10e63L, 10e127L, 10e255L };
+
+/* float properties */
+#define _D0 0
+#define _DBIAS 0x3ff
+#define _DLONG 1
+#define _DOFF 4
+#define _FBIAS 0x7e
+#define _FOFF 7
+#define _FRND 1
+#define _LBIAS 0x3ffe
+#define _LOFF 15
+/* integer properties */
+#define _C2 1
+#define _CSIGN 1
+#define _ILONG 0
+#define _MBMAX 8
+#define NAN 2
+#define INF 1
+#define FINITE -1
+#define _DFRAC ((1 << _DOFF) - 1)
+#define _DMASK (0x7fff & ~_DFRAC)
+#define _DMAX ((1 << (15 - _DOFF)) - 1)
+#define _DNAN (0x8000 | _DMAX << _DOFF | 1 << (_DOFF - 1))
+#define _DSIGN 0x8000
+#if _D0 == 3
+#define _D1 2 /* little-endian order */
+#define _D2 1
+#define _D3 0
+#else
+#define _D1 1 /* big-endian order */
+#define _D2 2
+#define _D3 3
+#endif
+
+void _Ldtob(_Pft *args, u8 type) {
+ u8 buff[BUFF_LEN];
+ u8 *ptr;
+ u32 sp70;
+ f64 val;
+ /* maybe struct? */
+ s16 err;
+ s16 nsig;
+ s16 exp;
+
+ s32 i;
+ s32 n;
+ f64 factor;
+ s32 gen;
+ s32 j;
+ s32 lo;
+ ldiv_t qr;
+ u8 drop;
+ s32 n2;
+
+ ptr = buff;
+ val = args->v.ld;
+ if (args->prec < 0) {
+ args->prec = 6;
+ } else {
+ if (args->prec == 0 && (type == 'g' || type == 'G')) {
+ args->prec = 1;
+ }
+ }
+ err = _Ldunscale(&exp, (_Pft*)args);
+ if (err > 0) {
+ memcpy(args->s, err == 2 ? "NaN" : "Inf", args->n1 = 3);
+ return;
+ }
+ if (err == 0) {
+ nsig = 0;
+ exp = 0;
+ } else {
+ if (val < 0) {
+ val = -val;
+ }
+ exp = exp * 30103 / 0x000186A0 - 4;
+ if (exp < 0) {
+ n = (3 - exp) & ~3;
+ exp = -n;
+ for (i = 0; n > 0; n >>= 1, i++) {
+ if ((n & 1) != 0) {
+ val *= D_800122E0[i];
+ }
+ }
+ } else {
+ if (exp > 0) {
+ factor = 1;
+ exp &= ~3;
+
+ for (n = exp, i = 0; n > 0; n >>= 1, i++) {
+ if ((n & 1) != 0) {
+ factor *= D_800122E0[i];
+ }
+ }
+ val /= factor;
+ }
+ }
+ gen = ((type == 'f') ? exp + 10 : 6) + args->prec;
+ if (gen > 0x13) {
+ gen = 0x13;
+ }
+ *ptr++ = '0';
+ while (gen > 0 && 0 < val) {
+ lo = val;
+ if ((gen -= 8) > 0) {
+ val = (val - lo) * 1.0e8;
+ }
+ ptr = ptr + 8;
+ for (j = 8; lo > 0 && --j >= 0;) {
+ qr = ldiv(lo, 10);
+ *--ptr = qr.rem + '0';
+ lo = qr.quot;
+ }
+ while (--j >= 0) {
+ ptr--;
+ *ptr = '0';
+ }
+ ptr += 8;
+ }
+
+ gen = ptr - &buff[1];
+ for (ptr = &buff[1], exp += 7; *ptr == '0'; ptr++) {
+ --gen, --exp;
+ }
+
+ nsig = ((type == 'f') ? exp + 1 : ((type == 'e' || type == 'E') ? 1 : 0)) + args->prec;
+ if (gen < nsig) {
+ nsig = gen;
+ }
+ if (nsig > 0) {
+ if (nsig < gen && ptr[nsig] > '4') {
+ drop = '9';
+ } else {
+ drop = '0';
+ }
+
+ for (n2 = nsig; ptr[--n2] == drop;) {
+ nsig--;
+ }
+ if (drop == '9') {
+ ptr[n2]++;
+ }
+ if (n2 < 0) {
+ --ptr, ++nsig, ++exp;
+ }
+ }
+ }
+ _Genld((_Pft*)args, type, ptr, nsig, exp);
+}
+
+s16 _Ldunscale(s16 *pex, _Pft *px) {
+
+ unsigned short *ps = (unsigned short *) px;
+ short xchar = (ps[_D0] & _DMASK) >> _DOFF;
+ if (xchar == _DMAX) { /* NaN or INF */
+ *pex = 0;
+ return (s16)(ps[_D0] & _DFRAC || ps[_D1] || ps[_D2] || ps[_D3] ? NAN : INF);
+ } else if (0 < xchar) {
+ ps[_D0] = (ps[_D0] & ~_DMASK) | (_DBIAS << _DOFF);
+ *pex = xchar - (_DBIAS - 1);
+ return (FINITE);
+ }
+ if (0 > xchar) {
+ return NAN;
+ } else {
+ *pex = 0;
+ return (0);
+ }
+}
+
+void _Genld(_Pft *px, u8 code, u8 *p, s16 nsig, s16 xexp) {
+ u8 point = '.';
+ if (nsig <= 0) {
+ nsig = 1,
+
+ p = (u8 *) "0";
+ }
+
+ if (code == 'f'
+ || ((code == 'g' || code == 'G') && (-4 <= xexp) && (xexp < px->prec))) { /* 'f' format */
+ ++xexp; /* change to leading digit count */
+ if (code != 'f') { /* fixup for 'g' */
+ if (!(px->flags & FLAGS_HASH) && nsig < px->prec) {
+ px->prec = nsig;
+ }
+ if ((px->prec -= xexp) < 0) {
+ px->prec = 0;
+ }
+ }
+ if (xexp <= 0) { /* digits only to right of point */
+ px->s[px->n1++] = '0';
+ if (0 < px->prec || px->flags & FLAGS_HASH) {
+ px->s[px->n1++] = point;
+ }
+ if (px->prec < -xexp) {
+ xexp = -px->prec;
+ }
+ px->nz1 = -xexp;
+ px->prec += xexp;
+ if (px->prec < nsig) {
+ nsig = px->prec;
+ }
+ memcpy(&px->s[px->n1], p, px->n2 = nsig);
+ px->nz2 = px->prec - nsig;
+ } else if (nsig < xexp) { /* zeros before point */
+ memcpy(&px->s[px->n1], p, nsig);
+ px->n1 += nsig;
+ px->nz1 = xexp - nsig;
+ if (0 < px->prec || px->flags & FLAGS_HASH) {
+ px->s[px->n1] = point, ++px->n2;
+ }
+ px->nz2 = px->prec;
+ } else { /* enough digits before point */
+ memcpy(&px->s[px->n1], p, xexp);
+ px->n1 += xexp;
+ nsig -= xexp;
+ if (0 < px->prec || px->flags & FLAGS_HASH) {
+ px->s[px->n1++] = point;
+ }
+ if (px->prec < nsig) {
+ nsig = px->prec;
+ }
+ memcpy(&px->s[px->n1], p + xexp, nsig);
+ px->n1 += nsig;
+ px->nz1 = px->prec - nsig;
+ }
+ } else { /* 'e' format */
+ if (code == 'g' || code == 'G') { /* fixup for 'g' */
+ if (nsig < px->prec) {
+ px->prec = nsig;
+ }
+ if (--px->prec < 0) {
+ px->prec = 0;
+ }
+ code = code == 'g' ? 'e' : 'E';
+ }
+ px->s[px->n1++] = *p++;
+ if (0 < px->prec || px->flags & FLAGS_HASH) {
+ px->s[px->n1++] = point;
+ }
+ if (0 < px->prec) { /* put fraction digits */
+ if (px->prec < --nsig) {
+ nsig = px->prec;
+ }
+ memcpy(&px->s[px->n1], p, nsig);
+ px->n1 += nsig;
+ px->nz1 = px->prec - nsig;
+ }
+ p = (u8 *) &px->s[px->n1]; /* put exponent */
+ *p++ = code;
+ if (0 <= xexp) {
+ *p++ = '+';
+ } else { /* negative exponent */
+ *p++ = '-';
+ xexp = -xexp;
+ }
+ if (100 <= xexp) { /* put oversize exponent */
+ if (1000 <= xexp) {
+ *p++ = xexp / 1000 + '0', xexp %= 1000;
+ }
+ *p++ = xexp / 100 + '0', xexp %= 100;
+ }
+ *p++ = xexp / 10 + '0', xexp %= 10;
+ *p++ = xexp + '0';
+ px->n2 = p - (u8 *) &px->s[px->n1];
+ }
+ if ((px->flags & (FLAGS_ZERO | FLAGS_MINUS)) == FLAGS_ZERO) { /* pad with leading zeros */
+ int n =
+ px->n0 + px->n1 + px->nz1 + px->n2 + px->nz2;
+
+ if (n < px->width) {
+ px->nz0 = px->width - n;
+ }
+ }
+}
diff --git a/src/libultra_boot_O2/_Litob.c b/src/libultra_boot_O2/_Litob.c
new file mode 100644
index 000000000..15206217c
--- /dev/null
+++ b/src/libultra_boot_O2/_Litob.c
@@ -0,0 +1,54 @@
+#include <global.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ultra64/printf.h>
+
+#define BUFF_LEN 0x18
+
+u8 D_8000AF70[] = "0123456789abcdef";
+u8 D_8000AF84[] = "0123456789ABCDEF";
+
+void _Litob(_Pft *args, u8 type) {
+ u8 buff[BUFF_LEN];
+ const u8 *num_map;
+ s32 base;
+ s32 buff_ind;
+ u64 num;
+ lldiv_t quotrem;
+
+ if (type == 'X')
+ num_map = D_8000AF84;
+ else
+ num_map = D_8000AF70;
+
+ base = (type == 'o') ? 8 : ((type != 'x' && type != 'X') ? 10 : 16);
+ buff_ind = BUFF_LEN;
+ num = args->v.ll;
+
+ if ((type == 'd' || type == 'i') && args->v.ll < 0)
+ num = -num;
+
+ if (num != 0 || args->prec != 0)
+ buff[--buff_ind] = num_map[num % base];
+
+ args->v.ll = num / base;
+
+ while (args->v.ll > 0 && buff_ind > 0) {
+ quotrem = lldiv(args->v.ll, base);
+ args->v.ll = quotrem.quot;
+ buff[--buff_ind] = num_map[quotrem.rem];
+ }
+
+ args->n1 = BUFF_LEN - buff_ind;
+
+ memcpy(args->s, buff + buff_ind, args->n1);
+
+ if (args->n1 < args->prec)
+ args->nz0 = args->prec - args->n1;
+
+ if (args->prec < 0 && (args->flags & (FLAGS_ZERO | FLAGS_MINUS)) == FLAGS_ZERO) {
+ buff_ind = args->width - args->n0 - args->nz0 - args->n1;
+ if (buff_ind > 0)
+ args->nz0 += buff_ind;
+ }
+}
diff --git a/src/libultra_boot_O2/_Printf.c b/src/libultra_boot_O2/_Printf.c
new file mode 100644
index 000000000..cbb803bbd
--- /dev/null
+++ b/src/libultra_boot_O2/_Printf.c
@@ -0,0 +1,230 @@
+#include <ultra64.h>
+#include <ultra64/printf.h>
+#include <stdarg.h>
+#include <string.h>
+
+#define ATOI(i, a) \
+ for (i = 0; *a >= '0' && *a <= '9'; a++) \
+ if (i < 999) \
+ i = *a + i * 10 - '0';
+#define _PROUT(fmt, _size) \
+ if (_size > 0) { \
+ arg = (void*)pfn(arg, fmt, _size); \
+ if (arg != 0) \
+ x.nchar += _size; \
+ else \
+ return x.nchar; \
+ }
+#define _PAD(m, src, extracond) \
+ if (extracond && m > 0) { \
+ int i; \
+ int j; \
+ for (j = m; j > 0; j -= i) { \
+ if ((u32) j > 32) \
+ i = 32; \
+ else \
+ i = j; \
+ _PROUT(src, i); \
+ } \
+ }
+
+char spaces[] = " ";
+char zeroes[] = "00000000000000000000000000000000";
+
+void _Putfld(_Pft *, va_list *, u8, u8 *);
+
+s32 _Printf(char *(*pfn)(char *, const char *, size_t), char *arg, const char *fmt, va_list ap)
+{
+ _Pft x;
+ x.nchar = 0;
+ while (1) {
+ const u8* s;
+ u8 c;
+ u8* t;
+
+ static const u8 fchar[] = " +-#0";
+ static const u32 fbit[] = { FLAGS_SPACE, FLAGS_PLUS, FLAGS_MINUS, FLAGS_HASH, FLAGS_ZERO, 0 };
+
+ u8 ac[0x20];
+
+ s = (u8 *)fmt;
+ while ((c = *s) != 0 && c != '%') {
+ s++;
+ }
+ _PROUT(fmt, s - (u8 *)fmt);
+ if (c == 0) {
+ return x.nchar;
+ }
+ fmt = (char *) ++s;
+ x.flags = 0;
+ for (; (t = strchr(fchar, *s)) != NULL; s++) {
+ x.flags |= fbit[t - fchar];
+ }
+ if (*s == '*') {
+ x.width = va_arg(ap, s32);
+ if (x.width < 0) {
+ x.width = -x.width;
+ x.flags |= FLAGS_MINUS;
+ }
+ s++;
+ } else {
+ ATOI(x.width, s);
+ }
+ if (*s != '.') {
+ x.prec = -1;
+ } else {
+ s++;
+ if (*s == '*') {
+ x.prec = va_arg(ap, s32);
+ s++;
+ } else {
+ ATOI(x.prec, s);
+ }
+ }
+ if (strchr("hlL", *s) != NULL) {
+ x.qual = *s++;
+ } else {
+ x.qual = 0;
+ }
+
+ if (x.qual == 'l' && *s == 'l') {
+ x.qual = 'L';
+ s++;
+ }
+ _Putfld(&x, &ap, *s, ac);
+ x.width -= x.n0 + x.nz0 + x.n1 + x.nz1
+ + x.n2 + x.nz2;
+ _PAD(x.width, spaces, !(x.flags & FLAGS_MINUS));
+ _PROUT((char *) ac, x.n0);
+ _PAD(x.nz0, zeroes, 1);
+ _PROUT(x.s, x.n1);
+ _PAD(x.nz1, zeroes, 1);
+ _PROUT((char *) (&x.s[x.n1]), x.n2)
+ _PAD(x.nz2, zeroes, 1);
+ _PAD(x.width, spaces, x.flags & FLAGS_MINUS);
+ fmt = (char *) s + 1;
+ }
+}
+
+void _Putfld(_Pft* px, va_list* pap, u8 code, u8* ac) {
+ px->n0 = px->nz0 = px->n1 = px->nz1 = px->n2 =
+ px->nz2 = 0;
+
+ switch (code) {
+
+ case 'c':
+ ac[px->n0++] = va_arg(*pap, u32);
+ break;
+
+ case 'd':
+ case 'i':
+ if (px->qual == 'l') {
+ px->v.ll = va_arg(*pap, s32);
+ } else if (px->qual == 'L') {
+ px->v.ll = va_arg(*pap, s64);
+ } else {
+ px->v.ll = va_arg(*pap, s32);
+ }
+
+ if (px->qual == 'h') {
+ px->v.ll = (s16) px->v.ll;
+ }
+
+ if (px->v.ll < 0) {
+ ac[px->n0++] = '-';
+ } else if (px->flags & FLAGS_PLUS) {
+ ac[px->n0++] = '+';
+ } else if (px->flags & FLAGS_SPACE) {
+ ac[px->n0++] = ' ';
+ }
+
+ px->s = (char *) &ac[px->n0];
+
+ _Litob(px, code);
+ break;
+
+ case 'x':
+ case 'X':
+ case 'u':
+ case 'o':
+ if (px->qual == 'l') {
+ px->v.ll = va_arg(*pap, s32);
+ } else if (px->qual == 'L') {
+ px->v.ll = va_arg(*pap, s64);
+ } else {
+ px->v.ll = va_arg(*pap, s32);
+ }
+
+ if (px->qual == 'h') {
+ px->v.ll = (u16) px->v.ll;
+ } else if (px->qual == 0) {
+ px->v.ll = (u32) px->v.ll;
+ }
+
+ if (px->flags & FLAGS_HASH) {
+ ac[px->n0++] = '0';
+ if (code == 'x' || code == 'X') {
+
+ ac[px->n0++] = code;
+ }
+ }
+ px->s = (char *) &ac[px->n0];
+ _Litob(px, code);
+ break;
+
+ case 'e':
+ case 'f':
+ case 'g':
+ case 'E':
+ case 'G':
+ px->v.ld = px->qual == 'L' ? va_arg(*pap, f64) : va_arg(*pap, f64);
+
+ if (*(u16*)&px->v.ll & 0x8000) {
+ ac[px->n0++] = '-';
+ } else {
+ if (px->flags & FLAGS_PLUS) {
+ ac[px->n0++] = '+';
+ } else if (px->flags & FLAGS_SPACE) {
+ ac[px->n0++] = ' ';
+ }
+ }
+
+ px->s = (char *) &ac[px->n0];
+ _Ldtob(px, code);
+ break;
+
+ case 'n':
+ if (px->qual == 'h') {
+ *(va_arg(*pap, u16 *)) = px->nchar;
+ } else if (px->qual == 'l') {
+ *va_arg(*pap, u32 *) = px->nchar;
+ } else if (px->qual == 'L') {
+ *va_arg(*pap, u64 *) = px->nchar;
+ } else {
+ *va_arg(*pap, u32 *) = px->nchar;
+ }
+ break;
+
+ case 'p':
+ px->v.ll = (long) va_arg(*pap, void *);
+ px->s = (char *) &ac[px->n0];
+ _Litob(px, 'x');
+ break;
+
+ case 's':
+ px->s = va_arg(*pap, char *);
+ px->n1 = strlen(px->s);
+ if (px->prec >= 0 && px->n1 > px->prec) {
+ px->n1 = px->prec;
+ }
+ break;
+
+ case '%':
+ ac[px->n0++] = '%';
+ break;
+
+ default:
+ ac[px->n0++] = code;
+ break;
+ }
+} \ No newline at end of file
diff --git a/src/libultra_boot_O2/__osDevMgrMain.c b/src/libultra_boot_O2/__osDevMgrMain.c
new file mode 100644
index 000000000..b3d8cd971
--- /dev/null
+++ b/src/libultra_boot_O2/__osDevMgrMain.c
@@ -0,0 +1,102 @@
+#include <global.h>
+#include <ultra64/hardware.h>
+
+void __osDevMgrMain(void* arg)
+{
+ OSIoMesg* ioMesg;
+ OSMesg sp70;
+ OSMesg sp6C;
+ OSMgrArgs* arg0;
+ __OSTranxInfo* transfer;
+ __OSBlockInfo* block;
+ s32 phi_s2;
+ s32 phi_s0;
+ u32 sp54;
+
+ arg0 = (OSMgrArgs*)arg;
+ ioMesg = NULL;
+
+ while (true)
+ {
+ osRecvMesg(arg0->cmdQueue, (OSMesg)&ioMesg, OS_MESG_BLOCK);
+ if ((ioMesg->piHandle != NULL) && (ioMesg->piHandle->type == DEVICE_TYPE_64DD) &&
+ ((ioMesg->piHandle->transferInfo.cmdType == 0) || (ioMesg->piHandle->transferInfo.cmdType == 1)))
+ {
+ transfer = &ioMesg->piHandle->transferInfo;
+ block = &transfer->block[transfer->blockNum];
+ transfer->sectorNum = -1;
+ if (transfer->transferMode != 3)
+ block->dramAddr = (void*)((u32)block->dramAddr - block->sectorSize);
+
+ phi_s2 = ((transfer->transferMode == 2) && (ioMesg->piHandle->transferInfo.cmdType == 0)) ? 1 : 0;
+
+ osRecvMesg(arg0->acccessQueue, &sp6C, OS_MESG_BLOCK);
+ __osResetGlobalIntMask(0x00100401);
+ __osEPiRawWriteIo(ioMesg->piHandle, 0x05000510, transfer->bmCtlShadow | 0x80000000);
+
+ while (true)
+ {
+ osRecvMesg(arg0->eventQueue, &sp70, OS_MESG_BLOCK);
+ transfer = &ioMesg->piHandle->transferInfo;
+ block = &transfer->block[transfer->blockNum];
+ if (block->errStatus == 0x1D)
+ {
+ __osEPiRawWriteIo(ioMesg->piHandle, 0x05000510, transfer->bmCtlShadow | 0x10000000);
+ __osEPiRawWriteIo(ioMesg->piHandle, 0x05000510, transfer->bmCtlShadow);
+ __osEPiRawReadIo(ioMesg->piHandle, 0x05000508, &sp54);
+ if (sp54 & 0x02000000)
+ __osEPiRawWriteIo(ioMesg->piHandle, 0x05000510, transfer->bmCtlShadow | 0x1000000);
+ block->errStatus = 4;
+ HW_REG(PI_STATUS_REG, u32) = PI_STATUS_CLEAR_INTR;
+ __osSetGlobalIntMask(0x00100C01);
+ }
+ osSendMesg(ioMesg->hdr.retQueue, ioMesg, OS_MESG_NOBLOCK);
+
+ if ((phi_s2 != 1) || (ioMesg->piHandle->transferInfo.block[0].errStatus != 0))
+ break;
+
+ phi_s2 = 0;
+ }
+
+ osSendMesg(arg0->acccessQueue, 0, OS_MESG_NOBLOCK);
+ if (ioMesg->piHandle->transferInfo.blockNum == 1)
+ osYieldThread();
+ }
+ else
+ {
+ switch (ioMesg->hdr.type)
+ {
+ case 11:
+ osRecvMesg(arg0->acccessQueue, &sp6C, OS_MESG_BLOCK);
+ phi_s0 = arg0->piDmaCallback(OS_READ, ioMesg->devAddr, ioMesg->dramAddr, ioMesg->size);
+ break;
+ case 12:
+ osRecvMesg(arg0->acccessQueue, &sp6C, OS_MESG_BLOCK);
+ phi_s0 = arg0->piDmaCallback(OS_WRITE, ioMesg->devAddr, ioMesg->dramAddr, ioMesg->size);
+ break;
+ case 15:
+ osRecvMesg(arg0->acccessQueue, &sp6C, OS_MESG_BLOCK);
+ phi_s0 = arg0->epiDmaCallback(ioMesg->piHandle, OS_READ, ioMesg->devAddr, ioMesg->dramAddr, ioMesg->size);
+ break;
+ case 16:
+ osRecvMesg(arg0->acccessQueue, &sp6C, OS_MESG_BLOCK);
+ phi_s0 = arg0->epiDmaCallback(ioMesg->piHandle, OS_WRITE, ioMesg->devAddr, ioMesg->dramAddr, ioMesg->size);
+ break;
+ case 10:
+ osSendMesg(ioMesg->hdr.retQueue, ioMesg, OS_MESG_NOBLOCK);
+ phi_s0 = -1;
+ break;
+ default:
+ phi_s0 = -1;
+ break;
+ }
+
+ if (phi_s0 == 0)
+ {
+ osRecvMesg(arg0->eventQueue, &sp70, OS_MESG_BLOCK);
+ osSendMesg(ioMesg->hdr.retQueue, ioMesg, OS_MESG_NOBLOCK);
+ osSendMesg(arg0->acccessQueue, NULL, OS_MESG_NOBLOCK);
+ }
+ }
+ }
+}
diff --git a/src/libultra_boot_O2/__osEPiRawReadIo.c b/src/libultra_boot_O2/__osEPiRawReadIo.c
new file mode 100644
index 000000000..d44881015
--- /dev/null
+++ b/src/libultra_boot_O2/__osEPiRawReadIo.c
@@ -0,0 +1,54 @@
+#include <global.h>
+#include <ultra64/hardware.h>
+
+s32 __osEPiRawReadIo(OSPiHandle* handle, u32 devAddr, u32* data)
+{
+ s32 status;
+ OSPiHandle* curHandle;
+
+ while (status = HW_REG(PI_STATUS_REG, u32), status & (PI_STATUS_BUSY | PI_STATUS_IOBUSY | PI_STATUS_ERROR))
+ ;
+
+ if (__osCurrentHandle[handle->domain]->type != handle->type)
+ {
+ curHandle = __osCurrentHandle[handle->domain];
+
+ if (handle->domain == 0)
+ {
+ if (curHandle->latency != handle->latency)
+ HW_REG(PI_BSD_DOM1_LAT_REG, u32) = handle->latency;
+
+ if (curHandle->pageSize != handle->pageSize)
+ HW_REG(PI_BSD_DOM1_PGS_REG, u32) = handle->pageSize;
+
+ if (curHandle->relDuration != handle->relDuration)
+ HW_REG(PI_BSD_DOM1_RLS_REG, u32) = handle->relDuration;
+
+ if (curHandle->pulse != handle->pulse)
+ HW_REG(PI_BSD_DOM1_PWD_REG, u32) = handle->pulse;
+ }
+ else
+ {
+ if (curHandle->latency != handle->latency)
+ HW_REG(PI_BSD_DOM2_LAT_REG, u32) = handle->latency;
+
+ if (curHandle->pageSize != handle->pageSize)
+ HW_REG(PI_BSD_DOM2_PGS_REG, u32) = handle->pageSize;
+
+ if (curHandle->relDuration != handle->relDuration)
+ HW_REG(PI_BSD_DOM2_RLS_REG, u32) = handle->relDuration;
+
+ if (curHandle->pulse != handle->pulse)
+ HW_REG(PI_BSD_DOM2_PWD_REG, u32) = handle->pulse;
+ }
+
+ curHandle->type = handle->type;
+ curHandle->latency = handle->latency;
+ curHandle->pageSize = handle->pageSize;
+ curHandle->relDuration = handle->relDuration;
+ curHandle->pulse = handle->pulse;
+ }
+
+ *data = HW_REG(handle->baseAddress | devAddr | 0, u32);
+ return 0;
+}
diff --git a/src/libultra_boot_O2/__osEPiRawStartDma.c b/src/libultra_boot_O2/__osEPiRawStartDma.c
new file mode 100644
index 000000000..dcd5f44d9
--- /dev/null
+++ b/src/libultra_boot_O2/__osEPiRawStartDma.c
@@ -0,0 +1,69 @@
+#include <global.h>
+#include <ultra64/hardware.h>
+
+s32 __osEPiRawStartDma(OSPiHandle* handle, s32 direction, u32 cartAddr, void* dramAddr, size_t size)
+{
+ s32 status;
+ OSPiHandle* curHandle;
+
+ while (status = HW_REG(PI_STATUS_REG, u32), status & (PI_STATUS_BUSY | PI_STATUS_IOBUSY | PI_STATUS_ERROR))
+ ;
+
+ if (__osCurrentHandle[handle->domain]->type != handle->type)
+ {
+ curHandle = __osCurrentHandle[handle->domain];
+
+ if (handle->domain == 0)
+ {
+ if (curHandle->latency != handle->latency)
+ HW_REG(PI_BSD_DOM1_LAT_REG, u32) = handle->latency;
+
+ if (curHandle->pageSize != handle->pageSize)
+ HW_REG(PI_BSD_DOM1_PGS_REG, u32) = handle->pageSize;
+
+ if (curHandle->relDuration != handle->relDuration)
+ HW_REG(PI_BSD_DOM1_RLS_REG, u32) = handle->relDuration;
+
+ if (curHandle->pulse != handle->pulse)
+ HW_REG(PI_BSD_DOM1_PWD_REG, u32) = handle->pulse;
+ }
+ else
+ {
+ if (curHandle->latency != handle->latency)
+ HW_REG(PI_BSD_DOM2_LAT_REG, u32) = handle->latency;
+
+ if (curHandle->pageSize != handle->pageSize)
+ HW_REG(PI_BSD_DOM2_PGS_REG, u32) = handle->pageSize;
+
+ if (curHandle->relDuration != handle->relDuration)
+ HW_REG(PI_BSD_DOM2_RLS_REG, u32) = handle->relDuration;
+
+ if (curHandle->pulse != handle->pulse)
+ HW_REG(PI_BSD_DOM2_PWD_REG, u32) = handle->pulse;
+ }
+
+ curHandle->type = handle->type;
+ curHandle->latency = handle->latency;
+ curHandle->pageSize = handle->pageSize;
+ curHandle->relDuration = handle->relDuration;
+ curHandle->pulse = handle->pulse;
+ }
+
+ HW_REG(PI_DRAM_ADDR_REG, void*) = (void*)osVirtualToPhysical(dramAddr);
+ HW_REG(PI_CART_ADDR_REG, void*) = (void*)((handle->baseAddress | cartAddr) & 0x1fffffff);
+
+ switch (direction)
+ {
+ case OS_READ:
+ HW_REG(PI_WR_LEN_REG, u32) = size - 1;
+ break;
+ case OS_WRITE:
+ HW_REG(PI_RD_LEN_REG, u32) = size - 1;
+ break;
+ default:
+ return -1;
+ break;
+ }
+
+ return 0;
+}
diff --git a/src/libultra_boot_O2/__osEPiRawWriteIo.c b/src/libultra_boot_O2/__osEPiRawWriteIo.c
new file mode 100644
index 000000000..517c7397a
--- /dev/null
+++ b/src/libultra_boot_O2/__osEPiRawWriteIo.c
@@ -0,0 +1,54 @@
+#include <global.h>
+#include <ultra64/hardware.h>
+
+s32 __osEPiRawWriteIo(OSPiHandle* handle, u32 devAddr, u32 data)
+{
+ s32 status;
+ OSPiHandle* curHandle;
+
+ while (status = HW_REG(PI_STATUS_REG, u32), status & (PI_STATUS_BUSY | PI_STATUS_IOBUSY | PI_STATUS_ERROR))
+ ;
+
+ if (__osCurrentHandle[handle->domain]->type != handle->type)
+ {
+ curHandle = __osCurrentHandle[handle->domain];
+
+ if (handle->domain == 0)
+ {
+ if (curHandle->latency != handle->latency)
+ HW_REG(PI_BSD_DOM1_LAT_REG, u32) = handle->latency;
+
+ if (curHandle->pageSize != handle->pageSize)
+ HW_REG(PI_BSD_DOM1_PGS_REG, u32) = handle->pageSize;
+
+ if (curHandle->relDuration != handle->relDuration)
+ HW_REG(PI_BSD_DOM1_RLS_REG, u32) = handle->relDuration;
+
+ if (curHandle->pulse != handle->pulse)
+ HW_REG(PI_BSD_DOM1_PWD_REG, u32) = handle->pulse;
+ }
+ else
+ {
+ if (curHandle->latency != handle->latency)
+ HW_REG(PI_BSD_DOM2_LAT_REG, u32) = handle->latency;
+
+ if (curHandle->pageSize != handle->pageSize)
+ HW_REG(PI_BSD_DOM2_PGS_REG, u32) = handle->pageSize;
+
+ if (curHandle->relDuration != handle->relDuration)
+ HW_REG(PI_BSD_DOM2_RLS_REG, u32) = handle->relDuration;
+
+ if (curHandle->pulse != handle->pulse)
+ HW_REG(PI_BSD_DOM2_PWD_REG, u32) = handle->pulse;
+ }
+
+ curHandle->type = handle->type;
+ curHandle->latency = handle->latency;
+ curHandle->pageSize = handle->pageSize;
+ curHandle->relDuration = handle->relDuration;
+ curHandle->pulse = handle->pulse;
+ }
+
+ HW_REG(handle->baseAddress | devAddr, u32) = data;
+ return 0;
+}
diff --git a/src/libultra_boot_O2/__osPiRawStartDma.c b/src/libultra_boot_O2/__osPiRawStartDma.c
new file mode 100644
index 000000000..0957a0ebc
--- /dev/null
+++ b/src/libultra_boot_O2/__osPiRawStartDma.c
@@ -0,0 +1,30 @@
+#include <global.h>
+#include <ultra64/hardware.h>
+
+s32 __osPiRawStartDma(s32 dir, u32 cart_addr, void *dram_addr, size_t size)
+{
+ register int status;
+ status = HW_REG(PI_STATUS_REG, u32);
+ while (status & (PI_STATUS_BUSY | PI_STATUS_IOBUSY | PI_STATUS_ERROR))
+ {
+ status = HW_REG(PI_STATUS_REG, u32);
+ }
+
+ HW_REG(PI_DRAM_ADDR_REG, void *) = (void *)osVirtualToPhysical(dram_addr);
+
+ HW_REG(PI_CART_ADDR_REG, void *) = (void *)((osRomBase | cart_addr) & 0x1fffffff);
+
+ switch (dir)
+ {
+ case OS_READ:
+ HW_REG(PI_WR_LEN_REG, u32) = size - 1;
+ break;
+ case OS_WRITE:
+ HW_REG(PI_RD_LEN_REG, u32) = size - 1;
+ break;
+ default:
+ return -1;
+ break;
+ }
+ return 0;
+} \ No newline at end of file
diff --git a/src/libultra_boot_O2/__osSiDeviceBusy.c b/src/libultra_boot_O2/__osSiDeviceBusy.c
new file mode 100644
index 000000000..983bd071d
--- /dev/null
+++ b/src/libultra_boot_O2/__osSiDeviceBusy.c
@@ -0,0 +1,12 @@
+#include <global.h>
+#include <ultra64/hardware.h>
+
+u32 __osSiDeviceBusy()
+{
+ register u32 status;
+ status = HW_REG(SI_STATUS_REG, u32);
+ if (status & (SI_STATUS_DMA_BUSY | SI_STATUS_IO_READ_BUSY))
+ return true;
+ else
+ return false;
+}
diff --git a/src/libultra_boot_O2/__osSiRawReadIo.c b/src/libultra_boot_O2/__osSiRawReadIo.c
new file mode 100644
index 000000000..c3bb394f0
--- /dev/null
+++ b/src/libultra_boot_O2/__osSiRawReadIo.c
@@ -0,0 +1,10 @@
+#include <global.h>
+#include <ultra64/hardware.h>
+
+s32 __osSiRawReadIo(void *a0, u32 *a1)
+{
+ if (__osSiDeviceBusy())
+ return -1;
+ *a1 = HW_REG((u32)a0, u32);
+ return 0;
+} \ No newline at end of file
diff --git a/src/libultra_boot_O2/__osSiRawWriteIo.c b/src/libultra_boot_O2/__osSiRawWriteIo.c
new file mode 100644
index 000000000..c7ff8eab7
--- /dev/null
+++ b/src/libultra_boot_O2/__osSiRawWriteIo.c
@@ -0,0 +1,10 @@
+#include <global.h>
+#include <ultra64/hardware.h>
+
+s32 __osSiRawWriteIo(void *a0, u32 a1)
+{
+ if (__osSiDeviceBusy())
+ return -1;
+ HW_REG((u32)a0, u32) = a1;
+ return 0;
+} \ No newline at end of file
diff --git a/src/libultra_boot_O2/__osViGetCurrentContext.c b/src/libultra_boot_O2/__osViGetCurrentContext.c
new file mode 100644
index 000000000..b629c77f7
--- /dev/null
+++ b/src/libultra_boot_O2/__osViGetCurrentContext.c
@@ -0,0 +1,6 @@
+#include <global.h>
+
+OSViContext* __osViGetCurrentContext()
+{
+ return __osViCurr;
+}
diff --git a/src/libultra_boot_O2/__osViInit.c b/src/libultra_boot_O2/__osViInit.c
new file mode 100644
index 000000000..a660a1de2
--- /dev/null
+++ b/src/libultra_boot_O2/__osViInit.c
@@ -0,0 +1,34 @@
+#include <global.h>
+#include <ultra64/hardware.h>
+
+OSViContext vi[2] = {0};
+OSViContext* __osViCurr = &vi[0];
+OSViContext* __osViNext = &vi[1];
+
+void __osViInit()
+{
+ bzero(vi, sizeof(vi));
+ __osViCurr = &vi[0];
+ __osViNext = &vi[1];
+
+ __osViNext->retraceCount = 1;
+ __osViCurr->retraceCount = 1;
+ __osViNext->buffer = (void*)0x80000000;
+ __osViCurr->buffer = (void*)0x80000000;
+
+ if (osTvType == 0)
+ __osViNext->modep = &osViModePalLan1;
+ else if (osTvType == 2)
+ __osViNext->modep = &osViModeMpalLan1;
+ else
+ __osViNext->modep = &osViModeNtscLan1;
+
+ __osViNext->state = 0x20;
+ __osViNext->features = __osViNext->modep->comRegs.ctrl;
+
+ while (HW_REG(VI_CURRENT_REG, u32) > 10)
+ ;
+
+ HW_REG(VI_CONTROL_REG, u32) = 0;
+ __osViSwapContext();
+}
diff --git a/src/libultra_boot_O2/__osViSwapContext.c b/src/libultra_boot_O2/__osViSwapContext.c
new file mode 100644
index 000000000..93f8ede35
--- /dev/null
+++ b/src/libultra_boot_O2/__osViSwapContext.c
@@ -0,0 +1,64 @@
+#include <global.h>
+#include <ultra64/hardware.h>
+
+void __osViSwapContext()
+{
+ register OSViMode *s0;
+ register OSViContext *s1;
+ u32 origin;
+ u32 hStart;
+ u32 vstart;
+ u32 sp34;
+ u32 field;
+ register u32 s2;
+
+ field = 0;
+ s1 = __osViNext;
+ s0 = s1->modep;
+ field = HW_REG(VI_V_CURRENT_LINE_REG, u32) & 1;
+ s2 = osVirtualToPhysical(s1->buffer);
+ origin = (s0->fldRegs[field].origin) + s2;
+ if (s1->state & 2) {
+ s1->x.scale |= s0->comRegs.xScale & ~0xfff;
+ } else {
+ s1->x.scale = s0->comRegs.xScale;
+ }
+ if (s1->state & 4) {
+ sp34 = (u32)(s0->fldRegs[field].yScale & 0xfff);
+ s1->y.scale = s1->y.factor * sp34;
+ s1->y.scale |= s0->fldRegs[field].yScale & ~0xfff;
+ } else {
+ s1->y.scale = s0->fldRegs[field].yScale;
+ }
+
+ vstart = (s0->fldRegs[field].vStart - (__additional_scanline << 0x10)) + __additional_scanline;
+ hStart = s0->comRegs.hStart;
+
+ if (s1->state & 0x20) {
+ hStart = 0;
+ }
+ if (s1->state & 0x40) {
+ s1->y.scale = 0;
+ origin = osVirtualToPhysical(s1->buffer);
+ }
+ if (s1->state & 0x80) {
+ s1->y.scale = (s1->y.offset << 0x10) & 0x3ff0000;
+ origin = osVirtualToPhysical(s1->buffer);
+ }
+ HW_REG(VI_ORIGIN_REG, u32) = origin;
+ HW_REG(VI_WIDTH_REG, u32) = s0->comRegs.width;
+ HW_REG(VI_BURST_REG, u32) = s0->comRegs.burst;
+ HW_REG(VI_V_SYNC_REG, u32) = s0->comRegs.vSync;
+ HW_REG(VI_H_SYNC_REG, u32) = s0->comRegs.hSync;
+ HW_REG(VI_LEAP_REG, u32) = s0->comRegs.leap;
+ HW_REG(VI_H_START_REG, u32) = hStart;
+ HW_REG(VI_V_START_REG, u32) = vstart;
+ HW_REG(VI_V_BURST_REG, u32) = s0->fldRegs[field].vBurst;
+ HW_REG(VI_INTR_REG, u32) = s0->fldRegs[field].vIntr;
+ HW_REG(VI_X_SCALE_REG, u32) = s1->x.scale;
+ HW_REG(VI_Y_SCALE_REG, u32) = s1->y.scale;
+ HW_REG(VI_CONTROL_REG, u32) = s1->features;
+ __osViNext = __osViCurr;
+ __osViCurr = s1;
+ *__osViNext = *__osViCurr;
+}
diff --git a/src/libultra_boot_O2/ldiv.c b/src/libultra_boot_O2/ldiv.c
new file mode 100644
index 000000000..391fe79c4
--- /dev/null
+++ b/src/libultra_boot_O2/ldiv.c
@@ -0,0 +1,28 @@
+#include <global.h>
+#include <stdlib.h>
+
+ldiv_t ldiv(long num, long denom) {
+ ldiv_t ret;
+
+ ret.quot = num / denom;
+ ret.rem = num - denom * ret.quot;
+ if (ret.quot < 0 && ret.rem > 0) {
+ ret.quot++;
+ ret.rem -= denom;
+ }
+
+ return ret;
+}
+
+lldiv_t lldiv(long long num, long long denom) {
+ lldiv_t ret;
+
+ ret.quot = num / denom;
+ ret.rem = num - denom * ret.quot;
+ if (ret.quot < 0 && ret.rem > 0) {
+ ret.quot++;
+ ret.rem -= denom;
+ }
+
+ return ret;
+}
diff --git a/src/libultra_boot_O2/osCartRomInit.c b/src/libultra_boot_O2/osCartRomInit.c
new file mode 100644
index 000000000..5492a61f5
--- /dev/null
+++ b/src/libultra_boot_O2/osCartRomInit.c
@@ -0,0 +1,64 @@
+#include <global.h>
+#include <ultra64/hardware.h>
+
+OSPiHandle __CartRomHandle;
+
+OSPiHandle* osCartRomInit()
+{
+ register u32 a;
+ register s32 status;
+ register u32 prevInt;
+ register u32 lastLatency;
+ register u32 lastPageSize;
+ register u32 lastRelDuration;
+ register u32 lastPulse;
+
+ static u32 D_8000AF10 = 1;
+
+ __osPiGetAccess();
+
+ if (!D_8000AF10)
+ {
+ __osPiRelAccess();
+ return &__CartRomHandle;
+ }
+
+ D_8000AF10 = 0;
+ __CartRomHandle.type = DEVICE_TYPE_CART;
+ __CartRomHandle.baseAddress = 0xb0000000;
+ __CartRomHandle.domain = 0;
+ __CartRomHandle.speed = 0;
+ bzero(&__CartRomHandle.transferInfo, sizeof(__OSTranxInfo));
+
+ while (status = HW_REG(PI_STATUS_REG, u32), status & PI_STATUS_ERROR)
+ ;
+
+ lastLatency = HW_REG(PI_BSD_DOM1_LAT_REG, u32);
+ lastPageSize = HW_REG(PI_BSD_DOM1_PGS_REG, u32);
+ lastRelDuration = HW_REG(PI_BSD_DOM1_RLS_REG, u32);
+ lastPulse = HW_REG(PI_BSD_DOM1_PWD_REG, u32);
+
+ HW_REG(PI_BSD_DOM1_LAT_REG, u32) = 0xff;
+ HW_REG(PI_BSD_DOM1_PGS_REG, u32) = 0;
+ HW_REG(PI_BSD_DOM1_RLS_REG, u32) = 3;
+ HW_REG(PI_BSD_DOM1_PWD_REG, u32) = 0xff;
+
+ a = HW_REG(__CartRomHandle.baseAddress, u32);
+ __CartRomHandle.latency = a & 0xFF;
+ __CartRomHandle.pageSize = (a >> 0x10) & 0xF;
+ __CartRomHandle.relDuration = (a >> 0x14) & 0xF;
+ __CartRomHandle.pulse = (a >> 8) & 0xFF;
+
+ HW_REG(PI_BSD_DOM1_LAT_REG, u32) = lastLatency;
+ HW_REG(PI_BSD_DOM1_PGS_REG, u32) = lastPageSize;
+ HW_REG(PI_BSD_DOM1_RLS_REG, u32) = lastRelDuration;
+ HW_REG(PI_BSD_DOM1_PWD_REG, u32) = lastPulse;
+
+ prevInt = __osDisableInt();
+ __CartRomHandle.next = __osPiTable;
+ __osPiTable = &__CartRomHandle;
+ __osRestoreInt(prevInt);
+ __osPiRelAccess();
+
+ return &__CartRomHandle;
+}
diff --git a/src/libultra_boot_O2/osDriveRomInit.c b/src/libultra_boot_O2/osDriveRomInit.c
new file mode 100644
index 000000000..2428161e8
--- /dev/null
+++ b/src/libultra_boot_O2/osDriveRomInit.c
@@ -0,0 +1,60 @@
+#include <global.h>
+#include <ultra64/hardware.h>
+
+OSPiHandle __DriveRomHandle;
+
+OSPiHandle* osDriveRomInit()
+{
+ register s32 status;
+ register u32 a;
+ register s32 prevInt;
+ static u32 D_8000AC70 = 1;
+
+ __osPiGetAccess();
+
+ if (!D_8000AC70)
+ {
+ __osPiRelAccess();
+ return &__DriveRomHandle;
+ }
+
+ D_8000AC70 = 0;
+ __DriveRomHandle.type = DEVICE_TYPE_BULK;
+ __DriveRomHandle.baseAddress = 0xa6000000;
+ __DriveRomHandle.domain = 0;
+ __DriveRomHandle.speed = 0;
+ bzero(&__DriveRomHandle.transferInfo, sizeof(__OSTranxInfo));
+
+ while (status = HW_REG(PI_STATUS_REG, u32), status & PI_STATUS_ERROR)
+ ;
+
+ HW_REG(PI_BSD_DOM1_LAT_REG, u32) = 0xff;
+ HW_REG(PI_BSD_DOM1_PGS_REG, u32) = 0;
+ HW_REG(PI_BSD_DOM1_RLS_REG, u32) = 3;
+ HW_REG(PI_BSD_DOM1_PWD_REG, u32) = 0xff;
+
+ a = HW_REG(__DriveRomHandle.baseAddress, u32);
+ __DriveRomHandle.latency = a & 0xFF;
+ __DriveRomHandle.pulse = (a >> 8) & 0xFF;
+ __DriveRomHandle.pageSize = (a >> 0x10) & 0xF;
+ __DriveRomHandle.relDuration = (a >> 0x14) & 0xF;
+
+ HW_REG(PI_BSD_DOM1_LAT_REG, u32) = (u8)a;
+ HW_REG(PI_BSD_DOM1_PGS_REG, u32) = __DriveRomHandle.pageSize;
+ HW_REG(PI_BSD_DOM1_RLS_REG, u32) = __DriveRomHandle.relDuration;
+ HW_REG(PI_BSD_DOM1_PWD_REG, u32) = __DriveRomHandle.pulse;
+
+ __osCurrentHandle[__DriveRomHandle.domain]->type = __DriveRomHandle.type;
+ __osCurrentHandle[__DriveRomHandle.domain]->latency = __DriveRomHandle.latency;
+ __osCurrentHandle[__DriveRomHandle.domain]->pageSize = __DriveRomHandle.pageSize;
+ __osCurrentHandle[__DriveRomHandle.domain]->relDuration = __DriveRomHandle.relDuration;
+ __osCurrentHandle[__DriveRomHandle.domain]->pulse = __DriveRomHandle.pulse;
+
+ prevInt = __osDisableInt();
+ __DriveRomHandle.next = __osPiTable;
+ __osPiTable = &__DriveRomHandle;
+ __osRestoreInt(prevInt);
+ __osPiRelAccess();
+
+ return &__DriveRomHandle;
+}
diff --git a/src/libultra_boot_O2/osEPiReadIo.c b/src/libultra_boot_O2/osEPiReadIo.c
new file mode 100644
index 000000000..9953c8529
--- /dev/null
+++ b/src/libultra_boot_O2/osEPiReadIo.c
@@ -0,0 +1,12 @@
+#include <global.h>
+
+s32 osEPiReadIo(OSPiHandle* handle, u32 devAddr, u32* data)
+{
+ register s32 ret;
+
+ __osPiGetAccess();
+ ret = __osEPiRawReadIo(handle, devAddr, data);
+ __osPiRelAccess();
+
+ return ret;
+} \ No newline at end of file
diff --git a/src/libultra_boot_O2/osEPiStartDma.c b/src/libultra_boot_O2/osEPiStartDma.c
new file mode 100644
index 000000000..a2c2b8d5a
--- /dev/null
+++ b/src/libultra_boot_O2/osEPiStartDma.c
@@ -0,0 +1,21 @@
+#include <global.h>
+
+s32 osEPiStartDma(OSPiHandle* handle, OSIoMesg* mb, s32 direction)
+{
+ s32 ret;
+ if (!__osPiDevMgr.initialized)
+ return -1;
+
+ mb->piHandle = handle;
+ if (direction == OS_READ)
+ mb->hdr.type = 0xf;
+ else
+ mb->hdr.type = 0x10;
+
+ if (mb->hdr.pri == 1)
+ ret = osJamMesg(osPiGetCmdQueue(), (OSMesg)mb, 0);
+ else
+ ret = osSendMesg(osPiGetCmdQueue(), (OSMesg)mb, 0);
+
+ return ret;
+} \ No newline at end of file
diff --git a/src/libultra_boot_O2/osEPiWriteIo.c b/src/libultra_boot_O2/osEPiWriteIo.c
new file mode 100644
index 000000000..ef1cc385f
--- /dev/null
+++ b/src/libultra_boot_O2/osEPiWriteIo.c
@@ -0,0 +1,12 @@
+#include <global.h>
+
+s32 osEPiWriteIo(OSPiHandle* handle, u32 devAddr, u32 data)
+{
+ register s32 ret;
+
+ __osPiGetAccess();
+ ret = __osEPiRawWriteIo(handle, devAddr, data);
+ __osPiRelAccess();
+
+ return ret;
+}
diff --git a/src/libultra_boot_O2/osPiGetCmdQueue.c b/src/libultra_boot_O2/osPiGetCmdQueue.c
new file mode 100644
index 000000000..159c42378
--- /dev/null
+++ b/src/libultra_boot_O2/osPiGetCmdQueue.c
@@ -0,0 +1,9 @@
+#include <global.h>
+
+OSMesgQueue* osPiGetCmdQueue()
+{
+ if (!__osPiDevMgr.initialized)
+ return NULL;
+
+ return __osPiDevMgr.cmdQueue;
+}
diff --git a/src/libultra_boot_O2/osViBlack.c b/src/libultra_boot_O2/osViBlack.c
new file mode 100644
index 000000000..4a122496c
--- /dev/null
+++ b/src/libultra_boot_O2/osViBlack.c
@@ -0,0 +1,13 @@
+#include <global.h>
+
+// TODO: name magic constants
+void osViBlack(u8 active)
+{
+ register u32 int_disabled = __osDisableInt();
+ if (active) {
+ __osViNext->state |= 0x20;
+ } else {
+ __osViNext->state &= ~0x20;
+ }
+ __osRestoreInt(int_disabled);
+}
diff --git a/src/libultra_boot_O2/osViGetNextFramebuffer.c b/src/libultra_boot_O2/osViGetNextFramebuffer.c
new file mode 100644
index 000000000..83eaa2705
--- /dev/null
+++ b/src/libultra_boot_O2/osViGetNextFramebuffer.c
@@ -0,0 +1,9 @@
+#include <global.h>
+
+void* osViGetNextFramebuffer()
+{
+ s32 prevInt = __osDisableInt();
+ void* buff = __osViNext->buffer;
+ __osRestoreInt(prevInt);
+ return buff;
+} \ No newline at end of file
diff --git a/src/libultra_boot_O2/osViModeFpalLan1.c b/src/libultra_boot_O2/osViModeFpalLan1.c
new file mode 100644
index 000000000..c620ad53d
--- /dev/null
+++ b/src/libultra_boot_O2/osViModeFpalLan1.c
@@ -0,0 +1,33 @@
+#include <global.h>
+
+OSViMode osViModeFpalLan1 =
+{
+ 0x2C, //type
+ { //comRegs
+ 0x311E, //ctrl
+ 0x140, //width
+ 0x4541E3A, //burst
+ 0x271, //vSync
+ 0x170C69, //hSync
+ 0xC6F0C6D, //leap
+ 0x800300, //hStart
+ 0x200, //xScale
+ 0 //vCurrent
+ },
+ { //fldRegs
+ {
+ 0x280, //origin
+ 0x400, //yScale
+ 0x2F0269, //vStart
+ 0x9026B, //vBurst
+ 2, //vIntr
+ },
+ {
+ 0x280, //origin
+ 0x400, //yScale
+ 0x2F0269, //vStart
+ 0x9026B, //vBurst
+ 2 //vIntr
+ }
+ }
+};
diff --git a/src/libultra_boot_O2/osViModeMpalLan1.c b/src/libultra_boot_O2/osViModeMpalLan1.c
new file mode 100644
index 000000000..805cd450b
--- /dev/null
+++ b/src/libultra_boot_O2/osViModeMpalLan1.c
@@ -0,0 +1,33 @@
+#include <global.h>
+
+OSViMode osViModeMpalLan1 =
+{
+ 0x1E, //type
+ { //comRegs
+ 0x311E, //ctrl
+ 0x140, //width
+ 0x4651E39, //burst
+ 0x20D, //vSync
+ 0x40C11, //hSync
+ 0xC190C1A, //leap
+ 0x6C02EC, //hStart
+ 0x200, //xScale
+ 0, //vCurrent
+ },
+ { //fldRegs
+ { //[0]
+ 0x280, //origin
+ 0x400, //yScale
+ 0x2501FF, //vStart
+ 0xE0204, //vBurst
+ 2, //vIntr
+ },
+ { //[1]
+ 0x280, //origin
+ 0x400, //yScale
+ 0x2501FF, //vStart
+ 0xE0204, //vBurst
+ 2, //vIntr
+ }
+ }
+};
diff --git a/src/libultra_boot_O2/osViModeNtscLan1.c b/src/libultra_boot_O2/osViModeNtscLan1.c
new file mode 100644
index 000000000..99573758e
--- /dev/null
+++ b/src/libultra_boot_O2/osViModeNtscLan1.c
@@ -0,0 +1,33 @@
+#include <global.h>
+
+OSViMode osViModeNtscLan1 =
+{
+ 2, //type
+ { //comRegs
+ 0x311E, //ctrl
+ 0x140, //width
+ 0x3E52239, //burst
+ 0x20D, //vSync
+ 0xC15, //hSync
+ 0xC150C15, //leap
+ 0x6C02EC, //hStart
+ 0x200, //xScale
+ 0, //vCurrent
+ },
+ { //fldRegs
+ { //[0]
+ 0x280, //origin
+ 0x400, //yScale
+ 0x2501FF, //vStart
+ 0xE0204, //vBurst
+ 2, //vIntr
+ },
+ { //[1]
+ 0x280, //origin
+ 0x400, //yScale
+ 0x2501FF, //vStart
+ 0xE0204, //vBurst
+ 2, //vIntr
+ }
+ }
+};
diff --git a/src/libultra_boot_O2/osViSetMode.c b/src/libultra_boot_O2/osViSetMode.c
new file mode 100644
index 000000000..5d29da826
--- /dev/null
+++ b/src/libultra_boot_O2/osViSetMode.c
@@ -0,0 +1,10 @@
+#include <global.h>
+
+void osViSetMode(OSViMode *mode)
+{
+ register u32 int_disabled = __osDisableInt();
+ __osViNext->modep = mode;
+ __osViNext->state = 1;
+ __osViNext->features = __osViNext->modep->comRegs.ctrl;
+ __osRestoreInt(int_disabled);
+}
diff --git a/src/libultra_boot_O2/osViSetSpecialFeatures.c b/src/libultra_boot_O2/osViSetSpecialFeatures.c
new file mode 100644
index 000000000..06d040a51
--- /dev/null
+++ b/src/libultra_boot_O2/osViSetSpecialFeatures.c
@@ -0,0 +1,37 @@
+#include <global.h>
+
+void osViSetSpecialFeatures(u32 func)
+{
+ register u32 int_disabled = __osDisableInt();
+ if (func & OS_VI_GAMMA_ON) {
+ __osViNext->features |= OS_VI_GAMMA;
+ }
+ if (func & OS_VI_GAMMA_OFF) {
+ __osViNext->features &= ~OS_VI_GAMMA;
+ }
+ if (func & OS_VI_GAMMA_DITHER_ON) {
+ __osViNext->features |= OS_VI_GAMMA_DITHER;
+ }
+ if (func & OS_VI_GAMMA_DITHER_OFF) {
+
+ __osViNext->features &= ~OS_VI_GAMMA_DITHER;
+ }
+ if (func & OS_VI_DIVOT_ON) {
+
+ __osViNext->features |= OS_VI_DIVOT;
+ }
+ if (func & OS_VI_DIVOT_OFF) {
+
+ __osViNext->features &= ~OS_VI_DIVOT;
+ }
+ if (func & OS_VI_DITHER_FILTER_ON) {
+ __osViNext->features |= OS_VI_DITHER_FILTER;
+ __osViNext->features &= ~(OS_VI_UNK200 | OS_VI_UNK100);
+ }
+ if (func & OS_VI_DITHER_FILTER_OFF) {
+ __osViNext->features &= ~OS_VI_DITHER_FILTER;
+ __osViNext->features |= __osViNext->modep->comRegs.ctrl & (OS_VI_UNK200 | OS_VI_UNK100);
+ }
+ __osViNext->state |= 8;
+ __osRestoreInt(int_disabled);
+}
diff --git a/src/libultra_boot_O2/osViSetXScale.c b/src/libultra_boot_O2/osViSetXScale.c
new file mode 100644
index 000000000..128b64c99
--- /dev/null
+++ b/src/libultra_boot_O2/osViSetXScale.c
@@ -0,0 +1,18 @@
+#include <global.h>
+
+void osViSetXScale(f32 value)
+{
+ register u32 nomValue;
+ register u32 saveMask;
+
+ saveMask = __osDisableInt();
+
+ __osViNext->x.factor = value;
+
+ __osViNext->state |= 0x2;
+
+ nomValue = __osViNext->modep->comRegs.xScale & 0xfff;
+ __osViNext->x.scale = (u32)(__osViNext->x.factor * nomValue) & 0xFFF;
+
+ __osRestoreInt(saveMask);
+}
diff --git a/src/libultra_boot_O2/osViSetYScale.c b/src/libultra_boot_O2/osViSetYScale.c
new file mode 100644
index 000000000..bf34f28e1
--- /dev/null
+++ b/src/libultra_boot_O2/osViSetYScale.c
@@ -0,0 +1,11 @@
+#include <global.h>
+
+void osViSetYScale(float scale)
+{
+ register s32 prevInt;
+
+ prevInt = __osDisableInt();
+ __osViNext->y.factor = scale;
+ __osViNext->state |= 4;
+ __osRestoreInt(prevInt);
+}
diff --git a/src/libultra_boot_O2/osViSwapBuffer.c b/src/libultra_boot_O2/osViSwapBuffer.c
new file mode 100644
index 000000000..eb6b05d31
--- /dev/null
+++ b/src/libultra_boot_O2/osViSwapBuffer.c
@@ -0,0 +1,9 @@
+#include <global.h>
+
+void osViSwapBuffer(void *vaddr)
+{
+ u32 int_disabled = __osDisableInt();
+ __osViNext->buffer = vaddr;
+ __osViNext->state |= 0x10; // TODO: figure out what this flag means
+ __osRestoreInt(int_disabled);
+}
diff --git a/src/libultra_boot_O2/pimgr.c b/src/libultra_boot_O2/pimgr.c
new file mode 100644
index 000000000..c15d7b919
--- /dev/null
+++ b/src/libultra_boot_O2/pimgr.c
@@ -0,0 +1,60 @@
+#include <global.h>
+
+OSMgrArgs __osPiDevMgr = {0};
+
+OSPiHandle __Dom1SpeedParam;
+OSPiHandle __Dom2SpeedParam;
+OSThread piThread;
+u8 piStackThread[0x1000];
+OSMesgQueue piEventQueue;
+OSMesg piEventBuf[2];
+OSThread __osThreadSave;
+
+OSPiHandle* __osPiTable = NULL;
+OSPiHandle* __osCurrentHandle[] =
+{
+ &__Dom1SpeedParam,
+ &__Dom2SpeedParam,
+};
+
+
+void osCreatePiManager(OSPri pri, OSMesgQueue *cmdQ, OSMesg *cmdBuf, s32 cmdMsgCnt)
+{
+ u32 int_disabled;
+ OSPri newPri;
+ OSPri currentPri;
+
+ if (!__osPiDevMgr.initialized)
+ {
+ osCreateMesgQueue(cmdQ, cmdBuf, cmdMsgCnt);
+ osCreateMesgQueue(&piEventQueue, piEventBuf, 1);
+ if (!__osPiAccessQueueEnabled)
+ __osPiCreateAccessQueue();
+
+ osSetEventMesg(OS_EVENT_PI, &piEventQueue, (OSMesg)0x22222222);
+ newPri = -1;
+ currentPri = osGetThreadPri(NULL);
+ if (currentPri < pri)
+ {
+ newPri = currentPri;
+ osSetThreadPri(NULL, pri);
+ }
+ int_disabled = __osDisableInt();
+
+ __osPiDevMgr.initialized = true;
+ __osPiDevMgr.cmdQueue = cmdQ;
+ __osPiDevMgr.mgrThread = &piThread;
+ __osPiDevMgr.eventQueue = &piEventQueue;
+ __osPiDevMgr.acccessQueue = &__osPiAccessQueue;
+ __osPiDevMgr.piDmaCallback = __osPiRawStartDma;
+ __osPiDevMgr.epiDmaCallback = __osEPiRawStartDma;
+
+ osCreateThread(&piThread, 0, __osDevMgrMain, (void *)&__osPiDevMgr, piStackThread + sizeof(piStackThread), pri);
+ osStartThread(&piThread);
+
+ __osRestoreInt(int_disabled);
+
+ if (newPri != -1)
+ osSetThreadPri(NULL, newPri);
+ }
+}
diff --git a/src/libultra_boot_O2/sprintf.c b/src/libultra_boot_O2/sprintf.c
new file mode 100644
index 000000000..58510a35c
--- /dev/null
+++ b/src/libultra_boot_O2/sprintf.c
@@ -0,0 +1,26 @@
+#include <global.h>
+
+char* proutSprintf(char* dst, const char *fmt, size_t size)
+{
+ return (char*)memcpy(dst, fmt, size) + size;
+}
+
+s32 vsprintf(char* dst, const char* fmt, va_list args)
+{
+ s32 ret = _Printf(&proutSprintf, dst, fmt, args);
+ if (ret > -1)
+ dst[ret] = 0;
+ return ret;
+}
+
+s32 sprintf(char* dst, const char* fmt, ...)
+{
+ s32 ret;
+ va_list args;
+ va_start(args, fmt);
+
+ ret = _Printf(&proutSprintf, dst, fmt, args);
+ if (ret > -1)
+ dst[ret] = 0;
+ return ret;
+}
diff --git a/src/libultra_boot_O2/string.c b/src/libultra_boot_O2/string.c
new file mode 100644
index 000000000..771caf1a3
--- /dev/null
+++ b/src/libultra_boot_O2/string.c
@@ -0,0 +1,33 @@
+#include <global.h>
+
+const u8 *strchr(const u8 *str, s32 ch)
+{
+ u8 c = ch;
+ while (*str != c)
+ {
+ if (*str == 0)
+ return NULL;
+ str++;
+ }
+ return str;
+}
+
+size_t strlen(const u8 *str)
+{
+ const u8 *ptr = str;
+ while (*ptr)
+ ptr++;
+ return ptr - str;
+}
+
+void *memcpy(void *dst, const void *src, size_t size)
+{
+ u8 *_dst = dst;
+ const u8 *_src = src;
+ while (size > 0)
+ {
+ *_dst++ = *_src++;
+ size--;
+ }
+ return dst;
+} \ No newline at end of file
diff --git a/src/libultra_boot_O2/vimgr.c b/src/libultra_boot_O2/vimgr.c
new file mode 100644
index 000000000..de54494f9
--- /dev/null
+++ b/src/libultra_boot_O2/vimgr.c
@@ -0,0 +1,125 @@
+#include <global.h>
+
+typedef struct
+{
+ u16 unk00;
+ u8 unk02;
+ u32 unk04;
+ u8 pad[0xc];
+ u16 unk14;
+ u16 unk16;
+} viMesgStruct;
+
+OSThread viThread;
+u8 viThreadStack[0x1000];
+OSMesgQueue viEventQueue;
+OSMesg viEventBuf[6];
+viMesgStruct viRetraceMsg;
+viMesgStruct viCounterMsg;
+OSMgrArgs __osViDevMgr = {0};
+u32 __additional_scanline = 0;
+
+void viMgrMain(void*);
+
+void osCreateViManager(OSPri pri)
+{
+ u32 int_disabled;
+ OSPri newPri;
+ OSPri currentPri;
+ if (!__osViDevMgr.initialized)
+ {
+ __osTimerServicesInit();
+ __additional_scanline = 0;
+ osCreateMesgQueue(&viEventQueue, viEventBuf, 5);
+ viRetraceMsg.unk00 = 13;
+ viRetraceMsg.unk02 = 0;
+ viRetraceMsg.unk04 = 0;
+ viCounterMsg.unk00 = 14;
+ viCounterMsg.unk02 = 0;
+ viCounterMsg.unk04 = 0;
+ osSetEventMesg(OS_EVENT_VI, &viEventQueue, &viRetraceMsg);
+ osSetEventMesg(OS_EVENT_COUNTER, &viEventQueue, &viCounterMsg);
+ newPri = -1;
+ currentPri = osGetThreadPri(NULL);
+ if (currentPri < pri)
+ {
+ newPri = currentPri;
+ osSetThreadPri(NULL, pri);
+ }
+
+ int_disabled = __osDisableInt();
+ __osViDevMgr.initialized = true;
+ __osViDevMgr.mgrThread = &viThread;
+ __osViDevMgr.cmdQueue = &viEventQueue;
+ __osViDevMgr.eventQueue = &viEventQueue;
+ __osViDevMgr.acccessQueue = NULL;
+ __osViDevMgr.piDmaCallback = NULL;
+ __osViDevMgr.epiDmaCallback = NULL;
+
+ osCreateThread(&viThread, 0, &viMgrMain, &__osViDevMgr, viThreadStack+sizeof(viThreadStack), pri);
+ __osViInit();
+ osStartThread(&viThread);
+ __osRestoreInt(int_disabled);
+ if (newPri != -1)
+ {
+ osSetThreadPri(NULL, newPri);
+ }
+ }
+}
+
+void viMgrMain(void* vargs)
+{
+ OSMgrArgs* args;
+ static u16 viRetrace;
+ u32 addTime;
+ viMesgStruct* mesg;
+ u32 temp; // always 0
+
+ temp = 0;
+ mesg = NULL;
+ viRetrace = __osViGetCurrentContext()->retraceCount;
+ if (viRetrace == 0)
+ viRetrace = 1;
+
+ args = (OSMgrArgs*)vargs;
+
+ while (1)
+ {
+ osRecvMesg(args->eventQueue, (OSMesg)&mesg, OS_MESG_BLOCK);
+ switch (mesg->unk00)
+ {
+ case 13:
+ __osViSwapContext();
+ viRetrace--;
+ if (!viRetrace)
+ {
+ OSViContext* ctx = __osViGetCurrentContext();
+ if (ctx->mq)
+ osSendMesg(ctx->mq, ctx->msg, OS_MESG_NOBLOCK);
+ viRetrace = ctx->retraceCount;
+ }
+
+ __osViIntrCount++;
+
+ // block optimized out since temp is always 0,
+ // but it changes register allocation and ordering for __osCurrentTime
+ if (temp != 0)
+ {
+ addTime = osGetCount();
+ __osCurrentTime = addTime;
+ temp = 0;
+ }
+
+ addTime = __osBaseCounter;
+ __osBaseCounter = osGetCount();
+ addTime = __osBaseCounter - addTime;
+ __osCurrentTime = __osCurrentTime + addTime;
+
+ break;
+
+ case 14:
+ __osTimerInterrupt();
+ break;
+ }
+ }
+}