diff --git a/BanjoRecompSyms b/BanjoRecompSyms index b0cbdde..89a18b8 160000 --- a/BanjoRecompSyms +++ b/BanjoRecompSyms @@ -1 +1 @@ -Subproject commit b0cbdde5c0c029e2190adaa76c779723d0c172af +Subproject commit 89a18b861f092ff578a121c290dc80aa2e6bac4c diff --git a/patches/graphics_patches.c b/patches/graphics_patches.c new file mode 100644 index 0000000..47ad2fc --- /dev/null +++ b/patches/graphics_patches.c @@ -0,0 +1,123 @@ +#include "patches.h" +#include "misc_funcs.h" + +extern struct { + s32 unk0; + s32 game_mode; //game_mode + f32 unk8; + s32 unkC; //freeze_scene_flag (used for pause menu) + f32 unk10; + u8 transition; + u8 map; + u8 exit; + u8 unk17; //reset_on_map_load + u8 unk18; + u8 unk19; + u8 unk1A; + u8 unk1B; + u8 unk1C; +} D_8037E8E0; + +void scissorBox_setDefault(void); +void getGraphicsStacks(Gfx **gfx, Mtx **mtx, Vtx **vtx); +s32 getActiveFramebuffer(void); +void func_802E39D0(Gfx **gdl, Mtx **mptr, Vtx **vptr, s32 framebuffer_idx, s32 arg4); +void viMgr_func_8024C1DC(void); +void func_80253EC4(Gfx *arg0, Gfx *arg1); +void dummy_func_80254464(); + +// 10x the original sizes. +#define GFX_BUFFER_COUNT 37000 +#define MTX_BUFFER_COUNT 7000 +#define VTX_BUFFER_COUNT 4300 + +struct { + Gfx gfx[2][GFX_BUFFER_COUNT]; + Mtx mtx[2][MTX_BUFFER_COUNT]; + Vtx vtx[2][VTX_BUFFER_COUNT]; +} ExtendedBuffers; + +extern Gfx *sGfxStack[2]; +extern Mtx *sMtxStack[2]; +extern Vtx *sVtxStack[2]; +extern s32 sStackSelector; +extern s32 gTextureFilterPoint; +extern u32 heap_occupiedBytes; + +// @recomp Patched to not free anything. +RECOMP_PATCH void graphicsCache_release(void) { + if (sGfxStack[0]) { + // @recomp Nothing to free, as the extended buffers are statically allocated. + sGfxStack[0] = NULL; + } +} + +// @recomp Patched to use the extended buffers for the graphics stacks. +RECOMP_PATCH void graphicsCache_init(void){ + if(sGfxStack[0] == NULL){ + // @recomp Point the stacks to the extended buffers. + sGfxStack[0] = ExtendedBuffers.gfx[0]; + sGfxStack[1] = ExtendedBuffers.gfx[1]; + sMtxStack[0] = ExtendedBuffers.mtx[0]; + sMtxStack[1] = ExtendedBuffers.mtx[1]; + sVtxStack[0] = ExtendedBuffers.vtx[0]; + sVtxStack[1] = ExtendedBuffers.vtx[1]; + dummy_func_80254464(); + } + sStackSelector = 0; + gTextureFilterPoint = 0; +} + +// @recomp Patched to check for graphics stack overflow after processing a frame. +RECOMP_PATCH void game_draw(s32 arg0){ + Gfx *gfx; + Gfx *gfx_start; + Gfx *sp2C; + Mtx *mtx; + Vtx *vtx; + + if(arg0) { + scissorBox_setDefault(); + } + + getGraphicsStacks(&gfx, &mtx, &vtx); + + if(D_8037E8E0.unkC == 1){ + getGraphicsStacks(&gfx, &mtx, &vtx); + } + // @recomp Track the original values. + Mtx* mtx_start = mtx; + Vtx* vtx_start = vtx; + + gfx_start = gfx; + func_802E39D0(&gfx, &mtx, &vtx, getActiveFramebuffer(), arg0); + + // @recomp Check for graphics stack overflow + u32 gfx_count = gfx - gfx_start; + u32 mtx_count = mtx - mtx_start; + u32 vtx_count = vtx - vtx_start; + + // recomp_printf("gfx: %-5u mtx: %-5u vtx: %-5u (%06X / %06X)\n", gfx_count, mtx_count, vtx_count, heap_occupiedBytes, 0x210520); + + if (gfx_count >= GFX_BUFFER_COUNT) { + recomp_error("Gfx buffer overflow\n"); + } + + if (mtx_count >= MTX_BUFFER_COUNT) { + recomp_error("Mtx buffer overflow\n"); + } + + if (vtx_count >= VTX_BUFFER_COUNT) { + recomp_error("Vtx buffer overflow\n"); + } + + if(D_8037E8E0.unkC == 0){ + sp2C = gfx; + viMgr_func_8024C1DC(); + func_80253EC4(gfx_start, sp2C); + + if(arg0) { + scissorBox_setDefault(); + } + } +} diff --git a/patches/misc_funcs.h b/patches/misc_funcs.h index ac79feb..1780c2c 100644 --- a/patches/misc_funcs.h +++ b/patches/misc_funcs.h @@ -6,5 +6,6 @@ DECLARE_FUNC(void, recomp_load_overlays, u32 rom, void* ram, u32 size); DECLARE_FUNC(void, recomp_puts, const char* data, u32 size); DECLARE_FUNC(void, recomp_exit); +DECLARE_FUNC(void, recomp_error, const char* str); #endif diff --git a/patches/patches.h b/patches/patches.h index 6de2186..1ca025a 100644 --- a/patches/patches.h +++ b/patches/patches.h @@ -25,11 +25,16 @@ void osWriteBackDCacheAll(void); #define free free_recomp #define realloc realloc_recomp #define memcpy memcpy_recomp +#define strchr strchr_recomp +#define strlen strlen_recomp #include "ultra64.h" typedef int bool; +typedef unsigned size_t; +void memcpy(void * dst, void *src, int size); +char* strchr(const char* s, int c); int recomp_printf(const char* fmt, ...); #endif diff --git a/patches/print.c b/patches/print.c new file mode 100644 index 0000000..3e1db83 --- /dev/null +++ b/patches/print.c @@ -0,0 +1,19 @@ +#include "patches.h" +#include "xstdio.h" +#include "misc_funcs.h" + +void* proutPrintf(void* dst, const char* fmt, size_t size) { + recomp_puts(fmt, size); + return (void*)1; +} + +RECOMP_EXPORT int recomp_printf(const char* fmt, ...) { + va_list args; + va_start(args, fmt); + + int ret = _Printf(&proutPrintf, NULL, fmt, args); + + va_end(args); + + return ret; +} diff --git a/patches/syms.ld b/patches/syms.ld index 269a63c..ad42f78 100644 --- a/patches/syms.ld +++ b/patches/syms.ld @@ -25,3 +25,9 @@ recomp_create_actor_data = 0x8F000050; recomp_destroy_actor_data = 0x8F000054; recomp_get_actor_data = 0x8F000058; recomp_get_actor_spawn_index = 0x8F00005C; +recomp_error = 0x8F000060; +memcpy_recomp = 0x8F000064; +__divdi3_recomp = 0x8F000068; +__udivdi3_recomp = 0x8F00006C; +__umoddi3_recomp = 0x8F000070; +strlen_recomp = 0x8F000074; diff --git a/patches/xldtob.c b/patches/xldtob.c new file mode 100644 index 0000000..293554d --- /dev/null +++ b/patches/xldtob.c @@ -0,0 +1,322 @@ +#include "patches.h" +#include "string.h" +#include "xstdio.h" + +typedef struct LDIV_T { + long quot; + long rem; +} ldiv_t; + +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 += 1; + ret.rem -= denom; + } + + return ret; +} + +#define BUFF_LEN 0x20 + +static short _Ldunscale(short* pex, ldouble* px); +static void _Genld(_Pft* px, char code, unsigned char* p, short nsig, short xexp); + +static const ldouble pows[] = {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 +#define _D1 1 // big-endian order +#define _D2 2 +#define _D3 3 + +#define ALIGN(s, align) (((unsigned int)(s) + ((align)-1)) & ~((align)-1)) + +void _Ldtob(_Pft* px, char code) { + char buff[BUFF_LEN]; + char *p; + ldouble ldval; + short err; + short nsig; + short xexp; + + p = buff; + ldval = px->v.ld; + + if (px->prec < 0) { + px->prec = 6; + } else if (px->prec == 0 && (code == 'g' || code == 'G')) { + px->prec = 1; + } + + err = _Ldunscale(&xexp, &px->v.ld); + if (err > 0) { + memcpy(px->s, err == 2 ? "NaN" : "Inf", px->n1 = 3); + return; + } else if (err == 0) { + nsig = 0; + xexp = 0; + } else { + { + int i; + int n; + + if (ldval < 0) { + ldval = -ldval; + } + + // what + if ((xexp = xexp * 30103 / 100000 - 4) < 0) { + n = ALIGN(-xexp, 4), xexp = -n; + + for (i = 0; n > 0; n >>= 1, i++) { + if (n & 1) { + ldval *= pows[i]; + } + } + } else if (xexp > 0) { + ldouble factor = 1; + + xexp &= ~3; + + for (n = xexp, i = 0; n > 0; n >>= 1, i++) { + if (n & 1) { + factor *= pows[i]; + } + } + + ldval /= factor; + } + } + { + int gen = px->prec + ((code == 'f') ? 10 + xexp : 6); + + if (gen > 0x13) { + gen = 0x13; + } + + for (*p++ = '0'; gen > 0 && 0 < ldval; p += 8) { + int j; + long lo = ldval; + + if ((gen -= 8) > 0) { + ldval = (ldval - lo) * 1e8; + } + + for (p += 8, j = 8; lo > 0 && --j >= 0;) { + ldiv_t qr; + qr = ldiv(lo, 10); + *--p = qr.rem + '0', lo = qr.quot; + } + + while (--j >= 0) { + *--p = '0'; + } + } + + gen = p - &buff[1]; + + for (p = &buff[1], xexp += 7; *p == '0'; p++) { + --gen, --xexp; + } + + nsig = px->prec + ((code == 'f') ? xexp + 1 : ((code == 'e' || code == 'E') ? 1 : 0)); + + if (gen < nsig) { + nsig = gen; + } + + if (nsig > 0) { + const char drop = nsig < gen && '5' <= p[nsig] ? '9' : '0'; + int n; + + for (n = nsig; p[--n] == drop;) { + --nsig; + } + + if (drop == '9') { + ++p[n]; + } + + if (n < 0) { + --p, ++nsig, ++xexp; + } + } + } + } + + _Genld(px, code, p, nsig, xexp); +} + +short _Ldunscale(short* pex, ldouble* px) { + unsigned short* ps = (unsigned short*)px; + short xchar = (ps[_D0] & _DMASK) >> _DOFF; + + + if (xchar == _DMAX) { + *pex = 0; + + return (ps[_D0] & _DFRAC) || ps[_D1] || ps[_D2] || ps[_D3] ? 2 : 1; + } else if (xchar > 0) { + ps[_D0] = (ps[_D0] & ~_DMASK) | 0x3FF0; + *pex = xchar - 0x3FE; + return -1; + } else if (xchar < 0) { + return 2; + } else { + *pex = 0; + return 0; + } +} + +void _Genld(_Pft* px, char code, unsigned char* p, short nsig, short xexp) { + const unsigned char point = '.'; + + if (nsig <= 0) { + nsig = 1, p = "0"; + } + + if (code == 'f' || (code == 'g' || code == 'G') && xexp >= -4 && xexp < px->prec) { + xexp++; + if (code != 'f') { + if (((px->flags & 8) == 0) && nsig < px->prec) { + px->prec = nsig; + } + + if ((px->prec -= xexp) < 0) { + px->prec = 0; + } + } + + if (xexp <= 0) { + px->s[px->n1++] = '0'; + + if (px->prec > 0 || (px->flags & 8)) { + 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) { + memcpy(&px->s[px->n1], p, nsig); + px->n1 += nsig; + px->nz1 = xexp - nsig; + if (px->prec > 0 || (px->flags & 8)) { + px->s[px->n1] = point; + px->n2++; + } + + px->nz2 = px->prec; + } else { + memcpy(&px->s[px->n1], p, xexp); + px->n1 += xexp; + nsig -= xexp; + + if (px->prec > 0 || (px->flags & 8)) { + 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 { + if (code == 'g' || code == '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 (px->prec > 0 || (px->flags & 8)) { + px->s[px->n1++] = point; + } + + if (px->prec > 0) { + if (px->prec < --nsig) { + nsig = px->prec; + } + + memcpy(&px->s[px->n1], p, nsig); + px->n1 += nsig; + px->nz1 = px->prec - nsig; + } + + p = &px->s[px->n1]; + *p++ = code; + + if (xexp >= 0) { + *p++ = '+'; + } else { + *p++ = '-'; + xexp = -xexp; + } + + if (xexp >= 100) { + if (xexp >= 1000) { + *p++ = (xexp / 1000) + '0', xexp %= 1000; + } + *p++ = (xexp / 100) + '0', xexp %= 100; + } + *p++ = (xexp / 10) + '0', xexp %= 10; + + *p++ = xexp + '0'; + px->n2 = (size_t)p - ((size_t)px->s + px->n1); + } + + if ((px->flags & 0x14) == 0x10) { + int n = px->n0 + px->n1 + px->nz1 + px->n2 + px->nz2; + + if (n < px->width) { + px->nz0 = px->width - n; + } + } +} + diff --git a/patches/xlitob.c b/patches/xlitob.c new file mode 100644 index 0000000..16bd8ef --- /dev/null +++ b/patches/xlitob.c @@ -0,0 +1,78 @@ +#include "patches.h" +#include "string.h" +#include "xstdio.h" + +typedef struct lldiv_t +{ + long long quot; + long long rem; +} lldiv_t; + +extern long long __divdi3_recomp(long long num, long long denom); +extern unsigned long long __udivdi3_recomp(unsigned long long num, unsigned long long denom); +extern unsigned long long __umoddi3_recomp(unsigned long long num, unsigned long long denom); + +__attribute__((noinline)) +lldiv_t lldiv(long long num, long long denom) { + lldiv_t ret; + + ret.quot = __divdi3_recomp(num, denom); + ret.rem = num - denom * ret.quot; + + if (ret.quot < 0 && ret.rem > 0) { + ret.quot += 1; + ret.rem -= denom; + } + + return ret; +} + +#define BUFF_LEN 0x18 + +static char ldigs[] = "0123456789abcdef"; +static char udigs[] = "0123456789ABCDEF"; + +void _Litob(_Pft *px, char code) { + char buff[BUFF_LEN]; + const char *digs; + int base; + int i; + unsigned long long ullval; + + digs = (code == 'X') ? udigs : ldigs; + + base = (code == 'o') ? 8 : ((code != 'x' && code != 'X') ? 10 : 16); + i = BUFF_LEN; + ullval = px->v.ll; + + if ((code == 'd' || code == 'i') && px->v.ll < 0) { + ullval = -ullval; + } + + if (ullval != 0 || px->prec != 0) { + buff[--i] = digs[__umoddi3_recomp(ullval, base)]; + } + + px->v.ll = (long long)__udivdi3_recomp(ullval, base); + + while (px->v.ll > 0 && i > 0) { + lldiv_t qr = lldiv(px->v.ll, base); + + px->v.ll = qr.quot; + buff[--i] = digs[qr.rem]; + } + + px->n1 = BUFF_LEN - i; + + memcpy(px->s, buff + i, px->n1); + + if (px->n1 < px->prec) { + px->nz0 = px->prec - px->n1; + } + + if (px->prec < 0 && (px->flags & (FLAGS_ZERO | FLAGS_MINUS)) == FLAGS_ZERO) { + if ((i = px->width - px->n0 - px->nz0 - px->n1) > 0) { + px->nz0 += i; + } + } +} diff --git a/patches/xprintf.c b/patches/xprintf.c new file mode 100644 index 0000000..1dd5602 --- /dev/null +++ b/patches/xprintf.c @@ -0,0 +1,262 @@ +#include "patches.h" +#include "string.h" +#include "stdarg.h" +#include "xstdio.h" + +char* strchr(const char* s, int c) { + const char ch = c; + while (*s != ch) { + if (*s == 0) { + return NULL; + } + s++; + } + return (char*)s; +} + +#define isdigit(x) ((x >= '0' && x <= '9')) +#define LDSIGN(x) (((unsigned short *)&(x))[0] & 0x8000) + +#define ATOI(dst, src) \ + for (dst = 0; isdigit(*src); ++src) \ + { \ + if (dst < 999) \ + dst = dst * 10 + *src - '0'; \ + } + +#define MAX_PAD ((sizeof(spaces) - 1)) +#define PAD(s, n) \ + if (0 < (n)) \ + { \ + int i, j = (n); \ + for (; 0 < j; j -= i) \ + { \ + i = MAX_PAD < (unsigned int)j ? (int)MAX_PAD : j; \ + PUT(s, i); \ + } \ + } +#define PUT(s, n) \ + if (0 < (n)) \ + { \ + if ((arg = (*pfn)(arg, s, n)) != NULL) \ + x.nchar += (n); \ + else \ + return x.nchar; \ + } +static char spaces[] = " "; +static char zeroes[] = "00000000000000000000000000000000"; + +static void _Putfld(_Pft *px, va_list *pap, char code, char *ac); + +int _Printf(void* pfn(void*,const char*,size_t), void *arg, const char *fmt, va_list ap) { + _Pft x; + + x.nchar = 0; + + while (1) { + const char *s; + char c; + const char *t; + static const char fchar[] = {' ', '+', '-', '#', '0', '\0'}; + static const unsigned int fbit[] = {FLAGS_SPACE, FLAGS_PLUS, FLAGS_MINUS, FLAGS_HASH, FLAGS_ZERO, 0}; + char ac[32]; + s = fmt; + + for (c = *s; c != 0 && c != '%';) { + c = *++s; + } + + PUT(fmt, s - fmt); + + if (c == 0) { + return x.nchar; + } + + fmt = ++s; + + for (x.flags = 0; (t = strchr(fchar, *s)) != NULL; s++) { + x.flags |= fbit[t - fchar]; + } + + if (*s == '*') { + x.width = va_arg(ap, int); + + if (x.width < 0) { + x.width = -x.width; + x.flags |= FLAGS_MINUS; + } + s++; + } else + ATOI(x.width, s); + + + if (*s != '.') { + x.prec = -1; + } else if (*++s == '*') { + x.prec = va_arg(ap, int); + ++s; + } else + for (x.prec = 0; isdigit(*s); s++) { + if (x.prec < 999) + x.prec = x.prec * 10 + *s - '0'; + } + + + x.qual = strchr("hlL", *s) ? *s++ : '\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; + + { + + if (!(x.flags & FLAGS_MINUS)) { + int i, j; + if (0 < (x.width)) + { + i, j = x.width; + for (; 0 < j; j -= i) + { + i = MAX_PAD < (unsigned int)j ? (int)MAX_PAD : j; + PUT(spaces, i); + } + } + } + + PUT(ac, x.n0); + PAD(zeroes, x.nz0) + + PUT(x.s, x.n1); + PAD(zeroes, x.nz1); + + PUT(x.s + x.n1, x.n2); + PAD(zeroes, x.nz2); + + if (x.flags & FLAGS_MINUS) { + PAD(spaces, x.width); + } + } + fmt = s + 1; + } + return 0; +} + +static void _Putfld(_Pft *px, va_list *pap, char code, char *ac) { + px->n0 = px->nz0 = px->n1 = px->nz1 = px->n2 = + px->nz2 = 0; + + switch (code) { + case 'c': + ac[px->n0++] = va_arg(*pap, int); + break; + case 'd': + case 'i': + if (px->qual == 'l') { + px->v.ll = va_arg(*pap, long); + } else if (px->qual == 'L') { + px->v.ll = va_arg(*pap, long long); + } else { + px->v.ll = va_arg(*pap, int); + } + + if (px->qual == 'h') { + px->v.ll = (short)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, long); + } else if (px->qual == 'L') { + px->v.ll = va_arg(*pap, long long); + } else { + px->v.ll = va_arg(*pap, int); + } + + if (px->qual == 'h') { + px->v.ll = (unsigned short)px->v.ll; + } else if (px->qual == 0) { + px->v.ll = (unsigned int)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, ldouble) : va_arg(*pap, double); + + if (LDSIGN(px->v.ld)) + 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, unsigned short *) = px->nchar; + } else if (px->qual == 'l') { + *va_arg(*pap, unsigned long *) = px->nchar; + } else if (px->qual == 'L') { + *va_arg(*pap, unsigned long long *) = px->nchar; + } else { + *va_arg(*pap, unsigned int *) = 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->prec < px->n1) { + px->n1 = px->prec; + } + + break; + case '%': + ac[px->n0++] = '%'; + break; + default: + ac[px->n0++] = code; + break; + } +} diff --git a/patches/xstdio.h b/patches/xstdio.h new file mode 100644 index 0000000..b5006a5 --- /dev/null +++ b/patches/xstdio.h @@ -0,0 +1,41 @@ +#ifndef _XSTDIO_H +#define _XSTDIO_H + +#include "stdarg.h" + +#ifdef __sgi +typedef double ldouble; // IDO does not support long doubles +#else +typedef long double ldouble; +#endif + +typedef struct { + /* 0x0 */ union { + /* 0x0 */ long long ll; + /* 0x0 */ ldouble ld; + } v; + /* 0x8 */ unsigned char* s; + /* 0xC */ int n0; + /* 0x10 */ int nz0; + /* 0x14 */ int n1; + /* 0x18 */ int nz1; + /* 0x1C */ int n2; + /* 0x20 */ int nz2; + /* 0x24 */ int prec; + /* 0x28 */ int width; + /* 0x2C */ size_t nchar; + /* 0x30 */ unsigned int flags; + /* 0x34 */ char qual; +} _Pft; + +#define FLAGS_SPACE 1 +#define FLAGS_PLUS 2 +#define FLAGS_MINUS 4 +#define FLAGS_HASH 8 +#define FLAGS_ZERO 16 + +int _Printf(void* pfn(void*,const char*,size_t), void *arg, const char *fmt, va_list ap); +void _Litob(_Pft *px, char code); +void _Ldtob(_Pft* px, char code); + +#endif diff --git a/src/game/recomp_api.cpp b/src/game/recomp_api.cpp index e0c6fb1..45b151b 100644 --- a/src/game/recomp_api.cpp +++ b/src/game/recomp_api.cpp @@ -32,6 +32,19 @@ extern "C" void recomp_exit(uint8_t* rdram, recomp_context* ctx) { ultramodern::quit(); } +extern "C" void recomp_error(uint8_t* rdram, recomp_context* ctx) { + std::string str{}; + PTR(u8) str_ptr = _arg<0, PTR(u8)>(rdram, ctx); + + for (size_t i = 0; MEM_B(str_ptr, i) != '\x00'; i++) { + str += (char)MEM_B(str_ptr, i); + } + + recompui::message_box(str.c_str()); + assert(false); + ultramodern::error_handling::quick_exit(__FILE__, __LINE__, __FUNCTION__); +} + extern "C" void recomp_get_gyro_deltas(uint8_t* rdram, recomp_context* ctx) { float* x_out = _arg<0, float*>(rdram, ctx); float* y_out = _arg<1, float*>(rdram, ctx); diff --git a/src/game/rom_decompression.cpp b/src/game/rom_decompression.cpp index 11f4ee9..6282f86 100644 --- a/src/game/rom_decompression.cpp +++ b/src/game/rom_decompression.cpp @@ -4,7 +4,6 @@ #include "librecomp/game.hpp" #include "banjo_game.h" -#include "recomp_data.h" #ifdef _MSC_VER inline uint32_t byteswap(uint32_t val) { @@ -121,5 +120,4 @@ std::vector banjo::decompress_bk(std::span compressed_ro void banjo::bk_on_init(uint8_t* rdram, recomp_context* ctx) { MEM_W(0, (int32_t)0x80000310) = 6103; recomp::do_rom_read(rdram, (int32_t)0x80000000, 0x100004C0, 0x2A4); - recomp::init_extended_actor_data(); } diff --git a/src/main/main.cpp b/src/main/main.cpp index 1ebb580..6752be8 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -26,6 +26,7 @@ #include "banjo_sound.h" #include "banjo_render.h" #include "banjo_game.h" +#include "recomp_data.h" #include "ovl_patches.hpp" #include "librecomp/game.hpp" #include "librecomp/mods.hpp" @@ -586,6 +587,7 @@ int main(int argc, char** argv) { banjo::register_bk_overlays(); banjo::register_bk_patches(); + recomp::init_extended_actor_data(); banjo::load_config(); recomp::rsp::callbacks_t rsp_callbacks{