mirror of
https://github.com/BanjoRecomp/BanjoRecomp
synced 2026-05-23 22:45:12 -04:00
Extend graphics stacks (fixes OOM crashes) and add recomp_printf
This commit is contained in:
+1
-1
Submodule BanjoRecompSyms updated: b0cbdde5c0...89a18b861f
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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);
|
||||
|
||||
@@ -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<uint8_t> banjo::decompress_bk(std::span<const uint8_t> 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();
|
||||
}
|
||||
|
||||
@@ -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{
|
||||
|
||||
Reference in New Issue
Block a user