diff --git a/port/fast3d/gfx_pc.cpp b/port/fast3d/gfx_pc.cpp index 54dd3fd9..e53d4ad9 100644 --- a/port/fast3d/gfx_pc.cpp +++ b/port/fast3d/gfx_pc.cpp @@ -1039,6 +1039,21 @@ static void gfx_matrix_mul(float res[4][4], const float a[4][4], const float b[4 static void gfx_sp_matrix(uint8_t parameters, const int32_t* addr) { float matrix[4][4]; + /* D144: a front-end 3D model (MISSION COMPLETE dossier, mode-select + * wallets - the D75 family) can emit a gSPMatrix whose pointer field was + * never resolved: w1 comes through as 0xFFFF... or another non-canonical + * value, and seg_addr() then hands us a wild pointer -> AV reading addr[]. + * A real N64 matrix pointer always lands in mapped memory. Rather than + * crash the menu transition, substitute identity for an unmapped source + * (the model draws with the wrong transform - already a parked D75 + * cosmetic - but the screen and its "Next" -> menu path work). */ + const bool addr_bad = ((uintptr_t)addr < 0x10000 || + (uintptr_t)addr >= 0x0000800000000000ULL); + + if (addr_bad) { + memset(matrix, 0, sizeof(matrix)); + matrix[0][0] = matrix[1][1] = matrix[2][2] = matrix[3][3] = 1.0f; + } else #ifndef GBI_FLOATS // Original GBI where fixed point matrices are used for (int i = 0; i < 4; i++) { diff --git a/src/game/textrelated.c b/src/game/textrelated.c index 1d173437..46c26352 100644 --- a/src/game/textrelated.c +++ b/src/game/textrelated.c @@ -420,7 +420,19 @@ Gfx *textRender(Gfx *gdl, s32 *x, s32 *y, char *text, s32 stack3; s32 stack4; //s32 stack5; - + +#ifdef PORT + /* D143: langGet() returns NULL for a string slot the current flow has not + * loaded (non-DEBUG builds; DEBUG substitutes a placeholder). The N64 + * retail flow guarantees every front-end string is resident before it is + * drawn; the PC menu flow does not yet, so a missing briefing/objective + * string reaches textRender as NULL and faults in the `*text` scan. + * Degrade to "draw nothing" like an empty string would. */ + if (text == NULL) { + return gdl; + } +#endif + g_JpnTextTlutNeedsLoad = 1; savedx = *x; @@ -683,7 +695,13 @@ Gfx *textRenderOutlined(Gfx *gdl, s32 *x, s32 *y, s32 savedx; struct fontchar sp74; s32 prevchar; - + +#ifdef PORT + if (text == NULL) { /* D143 - see textRender */ + return gdl; + } +#endif + g_JpnTextTlutNeedsLoad = 1; savedx = *x; @@ -757,6 +775,12 @@ void textMeasure(s32 *textheight, s32 *textwidth, char *text, struct fontchar *f *textheight = 0; *textwidth = 0; +#ifdef PORT + if (text == NULL) { /* D143 - see textRender */ + return; + } +#endif + if (lineheight == 0) { lineheight = font1['['].baseline + font1['['].height; @@ -834,6 +858,15 @@ void textWrap(s32 wrapwidth, char *src, char *dst, struct fontchar *chars, struc u32 stack; char curword[32]; +#ifdef PORT + if (src == NULL) { /* D143 - see textRender */ + if (dst != NULL) { + dst[0] = '\0'; + } + return; + } +#endif + while (more == 1) { // Load the next word wordwidth = 0;