From 102e49b5e7c53333d1e462e6d7018643c0c51cd7 Mon Sep 17 00:00:00 2001 From: Fazana <52551480+FazanaJ@users.noreply.github.com> Date: Tue, 28 Sep 2021 12:41:27 +0100 Subject: [PATCH] Puppytext font support + visual debug colour tweak --- bin/segment2.c | 34 +++++++++++- src/game/debug_box.c | 16 ++++-- src/game/hud.c | 2 +- src/game/puppycam2.c | 4 +- src/game/puppyprint.c | 75 ++++++++++++-------------- src/game/puppyprint.h | 16 ++++-- src/game/rendering_graph_node.c | 6 ++- src/game/segment2.h | 3 ++ textures/segment2/custom_text.i4.png | Bin 16247 -> 2646 bytes textures/segment2/custom_text2.i4.png | Bin 0 -> 16247 bytes 10 files changed, 102 insertions(+), 54 deletions(-) create mode 100644 textures/segment2/custom_text2.i4.png diff --git a/bin/segment2.c b/bin/segment2.c index 23a99516..969f279e 100644 --- a/bin/segment2.c +++ b/bin/segment2.c @@ -10,9 +10,41 @@ // SM64 (US/JP/EU/SH) Segment 02 #ifdef PUPPYPRINT -ALIGNED8 const Texture small_font[] = { +ALIGNED8 static const Texture small_font_1[] = { #include "textures/segment2/custom_text.i4.inc.c" }; +ALIGNED8 static const Texture small_font_2[] = { +#include "textures/segment2/custom_text2.i4.inc.c" +}; + +const Texture *const puppyprint_font_lut[2] = +{ + small_font_1, small_font_2 +}; + +static const u8 small_font_kerning_1[80] = +{ + /*0*/ 7, /*1*/ 7, /*2*/ 7, /*3*/ 7, /*4*/ 7, /*5*/ 7, /*6*/ 7, /*7*/ 7, /*8*/ 7, /*9*/ 7, /*-*/ 7, /*+*/ 7, /*(*/ 4, /*)*/ 4, /*!*/ 5, /*?*/ 6, + /*A*/ 7, /*B*/ 7, /*C*/ 7, /*D*/ 7, /*E*/ 7, /*F*/ 7, /*G*/ 7, /*H*/ 7, /*I*/ 7, /*J*/ 7, /*K*/ 7, /*L*/ 7, /*M*/ 7, /*N*/ 7, /*O*/ 7, /*P*/ 7, + /*Q*/ 7, /*R*/ 7, /*S*/ 7, /*T*/ 7, /*U*/ 7, /*V*/ 7, /*W*/ 7, /*X*/ 7, /*Y*/ 7, /*Z*/ 7, /*"*/ 5, /*'*/ 2, /*:*/ 3, /*;*/ 3, /*.*/ 3, /*,*/ 3, + /*a*/ 6, /*b*/ 6, /*c*/ 6, /*d*/ 6, /*e*/ 6, /*f*/ 6, /*g*/ 6, /*h*/ 6, /*i*/ 2, /*j*/ 6, /*k*/ 6, /*l*/ 3, /*m*/ 6, /*n*/ 6, /*o*/ 6, /*p*/ 6, + /*q*/ 6, /*r*/ 6, /*s*/ 6, /*t*/ 6, /*u*/ 6, /*v*/ 6, /*w*/ 6, /*x*/ 6, /*y*/ 6, /*z*/ 6, /*~*/ 7, /*¨*/ 6, /*^*/ 7, /*/*/ 6, /*%*/ 6, /*&*/ 7, +}; + +static const u8 small_font_kerning_2[80] = +{ + /*0*/ 6, /*1*/ 5, /*2*/ 7, /*3*/ 7, /*4*/ 7, /*5*/ 7, /*6*/ 8, /*7*/ 7, /*8*/ 7, /*9*/ 6, /*-*/ 8, /*+*/ 8, /*(*/ 5, /*)*/ 5, /*!*/ 4, /*?*/ 6, + /*A*/ 7, /*B*/ 7, /*C*/ 7, /*D*/ 7, /*E*/ 6, /*F*/ 5, /*G*/ 8, /*H*/ 6, /*I*/ 6, /*J*/ 5, /*K*/ 7, /*L*/ 6, /*M*/ 7, /*N*/ 7, /*O*/ 7, /*P*/ 6, + /*Q*/ 8, /*R*/ 6, /*S*/ 7, /*T*/ 7, /*U*/ 7, /*V*/ 7, /*W*/ 8, /*X*/ 7, /*Y*/ 7, /*Z*/ 7, /*"*/ 5, /*'*/ 2, /*:*/ 3, /*;*/ 3, /*.*/ 3, /*,*/ 3, + /*a*/ 7, /*b*/ 7, /*c*/ 6, /*d*/ 7, /*e*/ 7, /*f*/ 7, /*g*/ 7, /*h*/ 7, /*i*/ 3, /*j*/ 5, /*k*/ 8, /*l*/ 4, /*m*/ 7, /*n*/ 7, /*o*/ 7, /*p*/ 7, + /*q*/ 7, /*r*/ 6, /*s*/ 6, /*t*/ 6, /*u*/ 6, /*v*/ 7, /*w*/ 8, /*x*/ 6, /*y*/ 8, /*z*/ 7, /*~*/ 8, /*¨*/ 7, /*^*/ 8, /*/*/ 8, /*%*/ 8, /*&*/ 8, +}; + +const u8 *const puppyprint_kerning_lut[2][80] = +{ + small_font_kerning_1, small_font_kerning_2 +}; + #endif ALIGNED8 static const Texture texture_hud_char_0[] = { diff --git a/src/game/debug_box.c b/src/game/debug_box.c index 42fe79ec..1b9ca87f 100644 --- a/src/game/debug_box.c +++ b/src/game/debug_box.c @@ -29,6 +29,7 @@ #include "engine/surface_collision.h" #include "engine/surface_load.h" #include "object_list_processor.h" +#include "behavior_data.h" #include "debug_box.h" @@ -239,9 +240,18 @@ void iterate_surfaces_visual(s32 x, s32 z, Vtx *verts) { surf = node->surface; node = node->next; - make_vertex(verts, gVisualSurfaceCount, surf->vertex1[0], surf->vertex1[1], surf->vertex1[2], 0, 0, col[0], col[1], col[2], 0x80); - make_vertex(verts, gVisualSurfaceCount+1, surf->vertex2[0], surf->vertex2[1], surf->vertex2[2], 0, 0, col[0], col[1], col[2], 0x80); - make_vertex(verts, gVisualSurfaceCount+2, surf->vertex3[0], surf->vertex3[1], surf->vertex3[2], 0, 0, col[0], col[1], col[2], 0x80); + if (surf->type >= SURFACE_INSTANT_WARP_1B && surf->type <= SURFACE_INSTANT_WARP_1E) + { + make_vertex(verts, gVisualSurfaceCount, surf->vertex1[0], surf->vertex1[1], surf->vertex1[2], 0, 0, 0xFF, 0xA0, 0x00, 0x80); + make_vertex(verts, gVisualSurfaceCount+1, surf->vertex2[0], surf->vertex2[1], surf->vertex2[2], 0, 0, 0xFF, 0xA0, 0x00, 0x80); + make_vertex(verts, gVisualSurfaceCount+2, surf->vertex3[0], surf->vertex3[1], surf->vertex3[2], 0, 0, 0xFF, 0xA0, 0x00, 0x80); + } + else + { + make_vertex(verts, gVisualSurfaceCount, surf->vertex1[0], surf->vertex1[1], surf->vertex1[2], 0, 0, col[0], col[1], col[2], 0x80); + make_vertex(verts, gVisualSurfaceCount+1, surf->vertex2[0], surf->vertex2[1], surf->vertex2[2], 0, 0, col[0], col[1], col[2], 0x80); + make_vertex(verts, gVisualSurfaceCount+2, surf->vertex3[0], surf->vertex3[1], surf->vertex3[2], 0, 0, col[0], col[1], col[2], 0x80); + } gVisualSurfaceCount+=3; } diff --git a/src/game/hud.c b/src/game/hud.c index c0403142..1da58cf0 100644 --- a/src/game/hud.c +++ b/src/game/hud.c @@ -71,7 +71,7 @@ void print_fps(s32 x, s32 y) { sprintf(text, "FPS %2.2f", fps); #ifdef PUPPYPRINT - print_small_text(x, y, text, PRINT_TEXT_ALIGN_LEFT, PRINT_ALL); + print_small_text(x, y, text, PRINT_TEXT_ALIGN_LEFT, PRINT_ALL, FONT_OUTLINE); #else print_text(x, y, text); #endif diff --git a/src/game/puppycam2.c b/src/game/puppycam2.c index ec6035bf..10168fb9 100644 --- a/src/game/puppycam2.c +++ b/src/game/puppycam2.c @@ -451,7 +451,7 @@ void puppycam_check_pause_buttons(void) { play_sound(SOUND_MENU_CHANGE_SELECT, gGlobalSoundSource); if (gPlayer1Controller->rawStickX >= 60 || gPlayer1Controller->buttonDown & R_JPAD) { puppycam_change_setting(1); - } else if (gPlayer1Controller->rawStickX <= -60 || gPlayer1Controller->buttonDown & L_JPAD) + } else if (gPlayer1Controller->rawStickX <= -60 || gPlayer1Controller->buttonDown & L_JPAD) { puppycam_change_setting(-1); } } @@ -1079,7 +1079,7 @@ void puppycam_projection_behaviours(void) { gPuppyCam.floorY[1] = 0; gPuppyCam.targetFloorHeight = gPuppyCam.targetObj->oPosY; gPuppyCam.lastTargetFloorHeight = gPuppyCam.targetObj->oPosY; - + gPuppyCam.yawTarget = approach_angle(gPuppyCam.yawTarget, (gMarioState->faceAngle[1] + 0x8000), (1000 * (gMarioState->forwardVel / 32))); if (gMarioState->waterLevel - 100 - gMarioState->pos[1] > 5 && gPuppyCam.flags & PUPPYCAM_BEHAVIOUR_PITCH_ROTATION) { gPuppyCam.swimPitch = approach_f32_asymptotic(gPuppyCam.swimPitch,gMarioState->faceAngle[0] / 10, 0.05f); diff --git a/src/game/puppyprint.c b/src/game/puppyprint.c index 8b88692d..5c3bc265 100644 --- a/src/game/puppyprint.c +++ b/src/game/puppyprint.c @@ -31,7 +31,6 @@ a modern game engine's developer's console. #include "game_init.h" #include "memory.h" #include "print.h" -#include "segment2.h" #include "string.h" #include "stdarg.h" #include "printf.h" @@ -265,7 +264,7 @@ void print_ram_overview(void) { sprintf(textBytes, "Segment %02X: %X", i - nameTable + 2, ramsizeSegment[i]); } print_set_envcolour(colourChart[i][0], colourChart[i][1], colourChart[i][2], 255); - print_small_text(x, y, textBytes, PRINT_TEXT_ALIGN_CENTRE, PRINT_ALL); + print_small_text(x, y, textBytes, PRINT_TEXT_ALIGN_CENTRE, PRINT_ALL, FONT_DEFAULT); y += 12; drawn++; } @@ -306,7 +305,7 @@ void print_which_benchmark(void) { render_blank_box(110, 115, 210, 160, 0, 0, 0, 255); finish_blank_box(); sprintf(textBytes, "Select Option#%s#L: Confirm", benchNames[benchOption]); - print_small_text(160,120, textBytes, PRINT_TEXT_ALIGN_CENTRE, PRINT_ALL); + print_small_text(160,120, textBytes, PRINT_TEXT_ALIGN_CENTRE, PRINT_ALL, FONT_DEFAULT); } char consoleLogTable[LOG_BUFFER_SIZE][255]; @@ -346,7 +345,7 @@ void print_console_log(void) { if (consoleLogTable[i] == NULL) { continue; } - print_small_text(16, (LINE_HEIGHT) - (i * 12), consoleLogTable[i], PRINT_TEXT_ALIGN_LEFT, PRINT_ALL); + print_small_text(16, (LINE_HEIGHT) - (i * 12), consoleLogTable[i], PRINT_TEXT_ALIGN_LEFT, PRINT_ALL, FONT_DEFAULT); } } #undef LINE_HEIGHT @@ -373,7 +372,7 @@ void puppyprint_render_profiler(void) { } sprintf(textBytes, "RAM: %06X /%06X (%d_)", main_pool_available(), mempool, (s32)(((f32)main_pool_available() / (f32)mempool) * 100)); - print_small_text(160, 224, textBytes, PRINT_TEXT_ALIGN_CENTRE, PRINT_ALL); + print_small_text(160, 224, textBytes, PRINT_TEXT_ALIGN_CENTRE, PRINT_ALL, FONT_OUTLINE); if (!ramViewer && !benchViewer && !logViewer) { print_fps(16,40); @@ -382,20 +381,20 @@ void puppyprint_render_profiler(void) { #else sprintf(textBytes, "CPU: %dus (%d_)#RSP: %dus (%d_)#RDP: %dus (%d_)", (s32)cpuCount, (s32)(cpuCount / 333), (s32)OS_CYCLES_TO_USEC(rspTime), (s32)OS_CYCLES_TO_USEC(rspTime) / 333, (s32)OS_CYCLES_TO_USEC(rdpTime), (s32)OS_CYCLES_TO_USEC(rdpTime) / 333); #endif - print_small_text(16, 52, textBytes, PRINT_TEXT_ALIGN_LEFT, PRINT_ALL); + print_small_text(16, 52, textBytes, PRINT_TEXT_ALIGN_LEFT, PRINT_ALL, FONT_OUTLINE); sprintf(textBytes, "OBJ: %d/%d", gObjectCounter, OBJECT_POOL_CAPACITY); - print_small_text(16, 124, textBytes, PRINT_TEXT_ALIGN_LEFT, PRINT_ALL); + print_small_text(16, 124, textBytes, PRINT_TEXT_ALIGN_LEFT, PRINT_ALL, FONT_OUTLINE); // Very little point printing useless info if Mayro doesn't even exist. if (gMarioState->marioObj) { sprintf(textBytes, "Mario Pos#X: %d#Y: %d#Z: %d#D: %X", (s32)(gMarioState->pos[0]), (s32)(gMarioState->pos[1]), (s32)(gMarioState->pos[2]), (u16)(gMarioState->faceAngle[1])); - print_small_text(16, 140, textBytes, PRINT_TEXT_ALIGN_LEFT, PRINT_ALL); + print_small_text(16, 140, textBytes, PRINT_TEXT_ALIGN_LEFT, PRINT_ALL, FONT_OUTLINE); } // Same for the camera, especially so because this will crash otherwise. if (gCamera) { sprintf(textBytes, "Camera Pos#X: %d#Y: %d#Z: %d#D: %X", (s32)(gCamera->pos[0]), (s32)(gCamera->pos[1]), (s32)(gCamera->pos[2]), (u16)(gCamera->yaw)); - print_small_text(304, 140, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL); + print_small_text(304, 140, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL, FONT_OUTLINE); } if (benchmarkTimer > 0) { @@ -408,9 +407,9 @@ void puppyprint_render_profiler(void) { // sprintf(textBytes, "Benchmark: %dus#High: %dus", (s32)OS_CYCLES_TO_USEC(benchMark[NUM_BENCH_ITERATIONS]), (s32)OS_CYCLES_TO_USEC(benchMark[NUM_BENCH_ITERATIONS+1])); sprintf(textBytes, "Done in %0.000f seconds#Benchmark: %dus#High: %dus", (f32)(benchmarkProgramTimer) * 0.000001f, (s32)OS_CYCLES_TO_USEC(benchMark[NUM_BENCH_ITERATIONS]), (s32)OS_CYCLES_TO_USEC(benchMark[NUM_BENCH_ITERATIONS + 1])); #endif - render_blank_box(160 - (get_text_width(textBytes) / 2) - 4, 158, 160 + (get_text_width(textBytes) / 2) + 4, 196, 0, 0, 0, 255); + render_blank_box(160 - (get_text_width(textBytes, FONT_OUTLINE) / 2) - 4, 158, 160 + (get_text_width(textBytes, FONT_OUTLINE) / 2) + 4, 196, 0, 0, 0, 255); print_set_envcolour(255, 255, 255, 255); - print_small_text(160, 160, textBytes, PRINT_TEXT_ALIGN_CENTRE, PRINT_ALL); + print_small_text(160, 160, textBytes, PRINT_TEXT_ALIGN_CENTRE, PRINT_ALL, FONT_OUTLINE); finish_blank_box(); } @@ -424,26 +423,26 @@ void puppyprint_render_profiler(void) { #ifdef PUPPYPRINT_DEBUG_CYCLES sprintf(textBytes, "Collision: %dc", (s32)(collisionTime[NUM_PERF_ITERATIONS])); - print_small_text(304, 40, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL); + print_small_text(304, 40, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL, FONT_OUTLINE); sprintf(textBytes, "Graph: %dc", (s32)(graphTime[NUM_PERF_ITERATIONS])); - print_small_text(304, 52, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL); + print_small_text(304, 52, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL, FONT_OUTLINE); sprintf(textBytes, "Behaviour: %dc", (s32)(behaviourTime[NUM_PERF_ITERATIONS])); - print_small_text(304, 64, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL); + print_small_text(304, 64, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL, FONT_OUTLINE); sprintf(textBytes, "Audio: %dc", (s32)(audioTime[NUM_PERF_ITERATIONS])); - print_small_text(304, 76, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL); + print_small_text(304, 76, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL, FONT_OUTLINE); sprintf(textBytes, "DMA: %dc", (s32)(dmaTime[NUM_PERF_ITERATIONS])); - print_small_text(304, 88, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL); + print_small_text(304, 88, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL, FONT_OUTLINE); #else sprintf(textBytes, "Collision: %dus", (s32)OS_CYCLES_TO_USEC(collisionTime[NUM_PERF_ITERATIONS])); - print_small_text(304, 40, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL); + print_small_text(304, 40, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL, FONT_OUTLINE); sprintf(textBytes, "Graph: %dus", (s32)OS_CYCLES_TO_USEC(graphTime[NUM_PERF_ITERATIONS])); - print_small_text(304, 52, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL); + print_small_text(304, 52, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL, FONT_OUTLINE); sprintf(textBytes, "Behaviour: %dus", (s32)OS_CYCLES_TO_USEC(behaviourTime[NUM_PERF_ITERATIONS])); - print_small_text(304, 64, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL); + print_small_text(304, 64, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL, FONT_OUTLINE); sprintf(textBytes, "Audio: %dus", (s32)OS_CYCLES_TO_USEC(audioTime[NUM_PERF_ITERATIONS])); - print_small_text(304, 76, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL); + print_small_text(304, 76, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL, FONT_OUTLINE); sprintf(textBytes, "DMA: %dus", (s32)OS_CYCLES_TO_USEC(dmaTime[NUM_PERF_ITERATIONS])); - print_small_text(304, 88, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL); + print_small_text(304, 88, textBytes, PRINT_TEXT_ALIGN_RIGHT, PRINT_ALL, FONT_OUTLINE); #endif // Render CPU breakdown bar. @@ -595,7 +594,7 @@ void finish_blank_box(void) { // This does some epic shenanigans to figure out the optimal way to draw this. // If the width is a multiple of 4, then use fillmode (fastest) // Otherwise, if there's transparency, it uses that rendermode, which is slower than using opaque rendermodes. -void render_blank_box(s16 x1, s16 y1, s16 x2, s16 y2, u8 r, u8 g, u8 b, u8 a) { +void render_blank_box(s32 x1, s32 y1, s32 x2, s32 y2, s32 r, s32 g, s32 b, s32 a) { s32 cycleadd = 0; if (ABS(x1 - x2) % 4 == 0 && a == 255) { gDPSetCycleType(gDisplayListHead++, G_CYC_FILL); @@ -616,19 +615,12 @@ void render_blank_box(s16 x1, s16 y1, s16 x2, s16 y2, u8 r, u8 g, u8 b, u8 a) { gDPFillRectangle(gDisplayListHead++, x1, y1, x2-cycleadd, y2-cycleadd); } - -u8 textLen[] = { - /*0*/ 7, /*1*/ 7, /*2*/ 7, /*3*/ 7, /*4*/ 7, /*5*/ 7, /*6*/ 7, /*7*/ 7, /*8*/ 7, /*9*/ 7, /*-*/ 7, /*+*/ 7, /*(*/ 4, /*)*/ 4, /*!*/ 5, /*?*/ 6, - /*A*/ 7, /*B*/ 7, /*C*/ 7, /*D*/ 7, /*E*/ 7, /*F*/ 7, /*G*/ 7, /*H*/ 7, /*I*/ 7, /*J*/ 7, /*K*/ 7, /*L*/ 7, /*M*/ 7, /*N*/ 7, /*O*/ 7, /*P*/ 7, - /*Q*/ 7, /*R*/ 7, /*S*/ 7, /*T*/ 7, /*U*/ 7, /*V*/ 7, /*W*/ 7, /*X*/ 7, /*Y*/ 7, /*Z*/ 7, /*"*/ 5, /*'*/ 2, /*:*/ 3, /*;*/ 3, /*.*/ 3, /*,*/ 3, - /*a*/ 6, /*b*/ 6, /*c*/ 6, /*d*/ 6, /*e*/ 6, /*f*/ 6, /*g*/ 6, /*h*/ 6, /*i*/ 2, /*j*/ 6, /*k*/ 6, /*l*/ 3, /*m*/ 6, /*n*/ 6, /*o*/ 6, /*p*/ 6, - /*q*/ 6, /*r*/ 6, /*s*/ 6, /*t*/ 6, /*u*/ 6, /*v*/ 6, /*w*/ 6, /*x*/ 6, /*y*/ 6, /*z*/ 6, /*~*/ 7, /*¨*/ 6, /*^*/ 7, /*/*/ 6, /*%*/ 6, /*&*/ 7, -}; - #include "level_update.h" -void get_char_from_byte(u8 letter, s32 *textX, s32 *textY, s32 *spaceX, s32 *offsetY) { +void get_char_from_byte(u8 letter, s32 *textX, s32 *textY, s32 *spaceX, s32 *offsetY, s32 font) { *offsetY = 0; + u8 **textKern = segmented_to_virtual(puppyprint_kerning_lut); + u8 *textLen = segmented_to_virtual(textKern[font]); if (letter >= '0' && letter <= '9') { // Line 1 *textX = (letter - '0') * 4; *textY = 0; @@ -680,8 +672,8 @@ void get_char_from_byte(u8 letter, s32 *textX, s32 *textY, s32 *spaceX, s32 *off // This is for the letters that sit differently on the line. It just moves them down a bit. case 'g': *offsetY = 1; break; case 'q': *offsetY = 1; break; - // case 'p': *offsetY = 1; break; - // case 'y': *offsetY = 1; break; + case 'p': if (font == FONT_DEFAULT) *offsetY = 3; break; + case 'y': if (font == FONT_DEFAULT) *offsetY = 1; break; } } @@ -756,7 +748,7 @@ s32 text_iterate_command(const char *str, s32 i, s32 runCMD) { return len; } -s32 get_text_width(const char *str) { +s32 get_text_width(const char *str, s32 font) { s32 i= 0; s32 textPos = 0; s32 wideX = 0; @@ -770,7 +762,7 @@ s32 get_text_width(const char *str) { if (str[i] == '<') { i += text_iterate_command(str, i, FALSE); } - get_char_from_byte(str[i], &textX, &textY, &spaceX, &offsetY); + get_char_from_byte(str[i], &textX, &textY, &spaceX, &offsetY, font); textPos += spaceX + 1; wideX = MAX(textPos, wideX); } @@ -790,7 +782,7 @@ s32 get_text_height(const char *str) { return textPos; } -void print_small_text(s32 x, s32 y, const char *str, s32 align, s32 amount) +void print_small_text(s32 x, s32 y, const char *str, s32 align, s32 amount, s32 font) { s32 textX = 0; s32 textY = 0; @@ -805,6 +797,7 @@ void print_small_text(s32 x, s32 y, const char *str, s32 align, s32 amount) s32 lines = 0; s32 xlu = currEnv[3]; s32 prevxlu = 256; //Set out of bounds, so it will *always* be different at first. + Texture *(*fontTex)[] = segmented_to_virtual(&puppyprint_font_lut); shakeToggle = 0; waveToggle = 0; @@ -825,7 +818,7 @@ void print_small_text(s32 x, s32 y, const char *str, s32 align, s32 amount) if (str[i] == '<') { i += text_iterate_command(str, i, FALSE); } - get_char_from_byte(str[i], &textX, &textY, &spaceX, &offsetY); + get_char_from_byte(str[i], &textX, &textY, &spaceX, &offsetY, font); textPos[0] += spaceX + 1; wideX[lines] = MAX(textPos[0], wideX[lines]); } @@ -842,14 +835,14 @@ void print_small_text(s32 x, s32 y, const char *str, s32 align, s32 amount) if (str[i] == '<') { i += text_iterate_command(str, i, FALSE); } - get_char_from_byte(str[i], &textX, &textY, &spaceX, &offsetY); + get_char_from_byte(str[i], &textX, &textY, &spaceX, &offsetY, font); wideX[lines] = MAX(textPos[0], wideX[lines]); } textPos[0] = -wideX[0]; } lines = 0; - gDPLoadTextureBlock_4b(gDisplayListHead++, segmented_to_virtual(small_font), G_IM_FMT_I, 128, 60, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 0, 0, 0, 0, 0); + gDPLoadTextureBlock_4b(gDisplayListHead++, (*fontTex)[font], G_IM_FMT_I, 128, 60, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 0, 0, 0, 0, 0); for (i = 0; i < tx; i++) { if (str[i] == '#') { i++; @@ -876,7 +869,7 @@ void print_small_text(s32 x, s32 y, const char *str, s32 align, s32 amount) } else { wavePos = 0; } - get_char_from_byte(str[i], &textX, &textY, &spaceX, &offsetY); + get_char_from_byte(str[i], &textX, &textY, &spaceX, &offsetY, font); if (xlu != prevxlu) { prevxlu = xlu; if (xlu > 250) { diff --git a/src/game/puppyprint.h b/src/game/puppyprint.h index 0af3ce0b..ffcd06d9 100644 --- a/src/game/puppyprint.h +++ b/src/game/puppyprint.h @@ -2,6 +2,7 @@ #define PUPPYPRINT_H #ifdef PUPPYPRINT +#include "segment2.h" // This is how many indexes of timers are saved at once. higher creates a smoother average, but naturally uses more RAM. 15's fine. #define NUM_PERF_ITERATIONS 15 @@ -17,7 +18,13 @@ #define PRINT_TEXT_ALIGN_RIGHT 2 #define PRINT_ALL -1 -extern Texture small_font[]; +enum PuppyFont { + FONT_DEFAULT, + FONT_OUTLINE, + FONT_NUM, +}; + +extern u8 gPuppyFont; extern s8 perfIteration; extern s16 benchmarkLoop; extern s32 benchmarkTimer; @@ -62,14 +69,13 @@ extern void puppyprint_profiler_finished(void); extern void print_set_envcolour(s32 r, s32 g, s32 b, s32 a); extern void prepare_blank_box(void); extern void finish_blank_box(void); -extern void render_blank_box(s16 x1, s16 y1, s16 x2, s16 y2, u8 r, u8 g, u8 b, u8 a); -extern void print_small_text(s32 x, s32 y, const char *str, s32 align, s32 amount); +extern void print_small_text(s32 x, s32 y, const char *str, s32 align, s32 amount, s32 font); extern void render_multi_image(Texture *image, s32 x, s32 y, s32 width, s32 height, s32 scaleX, s32 scaleY, s32 mode); extern s32 get_text_height(const char *str); -extern s32 get_text_width(const char *str); +extern s32 get_text_width(const char *str, s32 font); extern void prepare_blank_box(void); extern void finish_blank_box(void); -extern void render_blank_box(s16 x1, s16 y1, s16 x2, s16 y2, u8 r, u8 g, u8 b, u8 a); +extern void render_blank_box(s32 x1, s32 y1, s32 x2, s32 y2, s32 r, s32 g, s32 b, s32 a); extern void append_puppyprint_log(const char *str, ...); extern char consoleLogTable[LOG_BUFFER_SIZE][255]; diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index 50217784..e1a2b343 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -15,6 +15,7 @@ #include "puppyprint.h" #include "debug_box.h" #include "level_update.h" +#include "behavior_data.h" #include "config.h" @@ -965,7 +966,10 @@ void geo_process_object(struct Object *node) { if (node->oIntangibleTimer != -1) { vec3f_set(bnds1, node->oPosX, node->oPosY - node->hitboxDownOffset, node->oPosZ); vec3f_set(bnds2, node->hitboxRadius, node->hitboxHeight-node->hitboxDownOffset, node->hitboxRadius); - debug_box_color(0x800000FF); + if (node->behavior == segmented_to_virtual(bhvWarp) || node->behavior == segmented_to_virtual(bhvDoorWarp) || node->behavior == segmented_to_virtual(bhvFadingWarp)) + debug_box_color(0x80FFA500); + else + debug_box_color(0x800000FF); debug_box(bnds1, bnds2, DEBUG_SHAPE_CYLINDER | DEBUG_UCODE_REJ); vec3f_set(bnds1, node->oPosX, node->oPosY - node->hitboxDownOffset, node->oPosZ); vec3f_set(bnds2, node->hurtboxRadius, node->hurtboxHeight, node->hurtboxRadius); diff --git a/src/game/segment2.h b/src/game/segment2.h index 7eecce54..1d020304 100644 --- a/src/game/segment2.h +++ b/src/game/segment2.h @@ -4,6 +4,9 @@ #include #include +extern void *puppyprint_font_lut[2]; +extern void *puppyprint_kerning_lut[2][80]; + extern u8 seg2_course_name_table[]; extern u8 seg2_act_name_table[]; extern Gfx dl_rgba16_text_begin[]; diff --git a/textures/segment2/custom_text.i4.png b/textures/segment2/custom_text.i4.png index ccecd85f80c1c528ca00be449182fba0ae95a2e6..02dd2d17c379a8fdf962e199cb20fe2e2fc1645a 100644 GIT binary patch delta 2638 zcmexfcTHr1ayb|85lTUd%8G=RK&fV6LVKf0Oj;c%18b;ctddWiprj7jr50FF!xO z+W76;E#>0%>cK1#I)O1gA^ z@zyH&qZ8-Nc;s?>_PeXD$#Zp2C?rnsy!+#b=C+GgI}Q6BkEyg;E&9zmb9!mL+HQ~i z8@BhP&e;iMS=(B^jy6E z#!4yK0Sx&FJ_O>pIJMWsW za3{L?pQeAj(qo|;{dt$JUog%4%Kkm6sDIn9)27S*{_}mHeXywc+UslEYu*2?Kl+zp zk5a|t_)qn#AN*$gaq#2i!(aR4MZ(z|rc2EeoW|bCemXrNyR2vDrRi(8oIEr4Pk@iz zjjuEP4P)NAzF@w)-KWIo`}|+mMBe7Fm^V#5o#X$}bHdIEmN!1B_x~x-Py5t(qhYH1>j?_QjK7|3*R$AccVNz+IqF8o ztt4l&e7o|s@#pmI4gdfB{=RzodDVoyUHkvP6*mfJn(tv>^J7EYe5O}-xW4UNK6CHw z|7#Ea`}=dfeZ1}7`K^05i@kTQXNui$=fu}rKiNA8`T`wm>+na zR4@=-Z2AA!$LB9?yX|JyHdis%RLJ(r6KzBh;E^(p5`AL>l& z_n24z-Yv(#V#F|M%hyly%%csZynkP7JaBLMhn*GY;*SRxEIGgL;_>TpOrJhKGg+qJ zv?bN|cy*MxPPdeN&<5sXKcwdxAI-UW@!o0XV-Ma(3BNU8SoXa6%KU_!*J2|Y%ik?|e5bB+=A%pV%QE&DzHP7GXYMV=dYdt( zAnBIPOSPuH%hSy`cGcb9%lGk2DC z{Iv6X#o2!@F06ey<4yTKot^yWcZ#cja(`UzT(G6F+VIa)lS};HzV!dOKkHh%(r?Q@ zx(S{8tM>0_z3^o3Pt67FpB{KOJ?EGw|3LS@@M-U+bn$upG0er^|DXLM@uWG^?o6kR zOyB(aq5~J^{M&x^JCj^Rt;Y9Phu>B)6fti%TW@aZSo7@gl^ds7=h{DQ>bdBq)80J! zZ0{U9)rPfFw)J{zio^ONuAjJC^L^!8qp!yMYtsw9w(RK8k?KBmI7Z@d>8#1=ey?(m z&Y$Z&!Bl12Hs;T+$DY)zzUPvBnJp^&w0+?IotD@5gOux^$28g%?<`xx@=Ls~@PH2A zL6r?x9fbeKF$ddqu<38Rc5_qnVqOpF7gfU5`3er+%k=-|PG`7#<(%P*KU^*nf}d$E3$AKXgy$tg9?yd0qeR?ZoB5MY^Tx^>T>MeP_U&NvviXxvsJ7b) zt#y_$Ox9WMY4L2z!`-ZmyC%QyS9{HpUjKHxT4`1Ow^wC*k{{TfE<7fA`s<_gNt~Bs zxQ=CiV!q72=|{_%_m(>q{;o{#v5Yac=lsB!`>MP@);adGbhPPwuMMHrxk69wSUlLb zWnQ7|?q4%XHu4-`@9|ui$+x@lO#Zh1m}>SSN7=OzE| zdFyY~tJfcITwQ8wq~jxfL#Q>+BU|O*G`HV5U$URQaLCCl*E!?M^hjd$Wy4nz-!HLD zmVH(=d)@NuTaSJA*B9I2ap7O*k&b%`8&#oT4Z@=PVwrc?Fl$_qX8p!x9?jpR+xso`@Z|cl*+L5z_7z`Gurr&m({qBA z(dWzmCb3MG-F5Aa?3S}PzUXc{fAG-JqN~%Hd>{3+#s)}x+4#soU;QF#eLUj$ z&B+@l`yJ1keWCFFqy+a(hu=9bnY;CwmBi_z|5YQKGMo3Mzmx5;pLB1}$#P{ovwg>U qe}sKG)_i?On!(Nd!{zh;@vHo+dup~&cm)Fk1B0ilpUXO@geCyM@^dl( literal 16247 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 DXE1q! diff --git a/textures/segment2/custom_text2.i4.png b/textures/segment2/custom_text2.i4.png new file mode 100644 index 0000000000000000000000000000000000000000..ccecd85f80c1c528ca00be449182fba0ae95a2e6 GIT binary patch literal 16247 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 DXE1q! literal 0 HcmV?d00001