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 1/6] 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 zcmeAS@N?(olHy`uVBq!ia0y~yU}#`qV6fp}V_;xdXSV4m1B2$8f};Gi z%$!t(lFEWqh1817GzNx>TWjY=mdWfCO8LLBYkSK99v$|_mV2Ay>f)VKf<)3+?NXT- zqGhb~pn2y{hAEN%zyHtqy#N2-^SdItISr?W1n>HxePk-u-c&HcZRnO}bV_x$y@r%d0sAM^iswe{3vr)~fL@|)VMi@z6h;_m%D z^E~X&A8&p2*y-Ng{|WNq8Q(Xp3-PYo+p_Q7`_DU%6#X~+C3Nb3|KE4-C10LBQM;%3 zbaeg4t3QkE8?MV|*F0`N75;qly%Xz?MGMC-u8-qstWjA${lAv~mai)w9yb5Gbn5i^ z_cFBY=iS?LHLRe2`ww#`KmGgmHFt0Pcqaen^xwO$t=m8SIQjSQFRi@${$JdF{o4Fp z=l7bKp<5;hlve4ya?SeH_`Ni5VYK++#Y?q6s~2_F)P>fGuBl4k`YaXx{Q8EgR#&#> zZn$i=`>oaec3GRGg3}fyPv=Ny1n7&Egx__Te2x9@rrW7otZE(SGjFYqE7d=rbUydB z>6x9;56@lx6qdeohOOI&)A7%?%ioAzm#{WvW zojRAAEtuly*y~@`m56R1B zrq3+hmMXq%%b_mqwR=vjTAk~YTfO;kpY_{4r`PS?oAGwxwetOS3r&Atm}NcdlJw{9 zYZa!?pR2BUpyHLTab{-1#foWM1{vyeV~@5ySYr9|%__e29XodPUb?yEl7tjbx51XT z!R5#9N=<$CZ}L4KzWSGE|E_-46Y|~r?B46Q-J@o6IX}*L^UaC#>!*tQ9KWL~cNo+@ z-o0J#>y5BE2OdbNRld8o^F>Y~vzvCCt=DZ+CjaZJl2hd)p1EyX`6=e~r|CDIZM_z^ zS?#^RnK^3LTa>SQNaWZQo?5(ogMiV;)!Sqr-P`)nMf-ELsltpGpMSNU?w>W?G@HM@ z#O=$>-_Nh?E-rksE0#&t`uex*b*HCWR{M9PJUUso@TbtVFNe=Xt{Gv$fi0cxxlQKhJRUEHAB(@=eXFCq_@PYrn}v(+Sw!8v zdhD&$x76kC-&Q7^`yF=gjmG&;H_p!L{I*M4vuA7m(@MKC-FJP8Z)X{(sTfx%#CnIyLEd{Y&o@Hyd>~xV|yWvoW@}Y>o5vRYM$+!Qo zL-wHA^g=J=xl?ZG6)?^AOy2zM6nmdcjdylms^Y2f%+VjcfpJB(#!U7LxzZEj8nZh^3PuPVkVY7-CZO-n$ z*6kxKtn=FBe=ZEsGiQwY(Dpm(WGW9~#(!x6n zXGbLnmkB@rAb4;6(&ig_TifbS>`HtT{p{W2IZSTucUm_KvDMCFwtsFpm(}e<_`Dcx zKKJW_vHU*oPVM!*FjIixf!D=fw&HyHC5<+YEuxn{rYp>}2ohV*qi{d@$O4;d-_6g|_k4Qx z-Qd6BsoDIAcIz%hKFM>BFJ0K!aPitMmCB}%HXL?^b7HJa%Jnzr#+?jja+vQ>Xk8{J z=G~Z}uam=Uu^?*7p~$&<7j|s=z9_FlPIU4v4e^t*6WdPfh5ceqtWo0roSj&s)1CPs zO?J(@jc=IJ1RfvWA~{DzYN;~6ZrhjjA0Bh;xOlEHqK)}iDEC6|y#5W`Q+TCY+WI(+ zk1)-3VwNRUOa4?C@ znPS4UT-S2*CLV3p0Hu#@2^>A2OPOYG-kESZW5@ZnwuKFr>t}RkGB6)HJJBwM`03YUT!?X<0LC0^8T;iy2DeR!_>@a{KRx&?~bPU+;|Ne3aYK{in3iI6>;0 zyb{x+i8}?v_#m;3#=zJsZTOD z`LSDr`Q*Ba9XhL=Zyn9#>|jZ_BYl30p@fN%vc;4zQK?U1({?nwpJ8F@Fp+O8ta2^> zP@|CZ;r3gW$Im8Bz94EWkY>XqWfyVi4@0SLTFd(rtU@9S-#5)%K6|D^z=yQ^hMpg$ zy>5QH;ltF}D3^%~7u?&Bbdjq`&FSgdQ+IB!ye1ovl54=Km#p4*vihM?!ID{eDbqh> z@Cd2-^vJDt-pY{kho8-99h<*$%;bNv+br7;A9L?w%ywUIv*`VzW`Vvthp+Aw$kST# zfkQa@$Pb4vOBEa@ZT#So#L#u<9n&ST{M__~;>Y4bPCxE55Ed4Fu9I<2S(&Hg68lUk z?$sAmXEe3X*vRx}ZCqxb%Dh_}c;%nI+Vou3fm=A8ck&v|2TxC|YgdbM@X{)3IkM@H zxXfu&QLAl9)wje-8VZuXWr*E#+++OWR%g^&-=GFY{gB%p_dQA@HeAw<(2e8oIw0^t z`;g4CgZ&jo8s2Rz$DSsv3Vp~harshynKPwd6Z9h0!nB(?8Ji54rf~5^+QvN=_qfo` zyXbJurJ2&H$qiEyp4gb4VM^&v(taTIGvKRUf=0@VJ9e6hhjcft(_Z#?hu5MDQ3_vI zc_|cVl`JPFbnKxZvoPMZ7Bouj}l)Fr`swp^-^zM4Bk$ zNwwDxE&OU0ik_a@$S*0fCi$h_heJiht%(U4ci2|OwM&Pl++8>GQ=r5LKd)3prqrYh zkqd)7wHhY3pV3HfoHogKa&oX{#2;~UJ(j6TK`I_>Hy3~K>{kA)bU-$aC7;!C_9+?G z=jD8Q!e*IbD|oIQ*qL}ol83p|BWr!rrOT}6toJ-miCMtdcyuz$VP@y`7fOFvy2)Lf zDtYyLOlbU?2`9wf%V4N^!(WAu%u*?T!~exf7arxW|wl! zFoDv(7YZ8_ELHkbzKIAwsAJaN@1u9Gk>#M%gnX@w^Ut>nuKBhlJXQPoPlHbnj>>GX zZRijw67tyeaPpIn30dKbDkjdg6|y_TTVcWB_J=7#@%(Oo)l36X#ef<^$9dEC+`n(8 zvFYyy$Bnl|Qkv~lDqbFDOMU4g^6%e%sL zanXFk2^tSOD}|n%w0w|yN^)Xy*q0SG;fXTu*B>$xS{?6v^S(z~9ZTxNbEo>aPjj7A zW&2g=+*x3)m$SiXiMx(n*pDgq-iC{FP0eF)6bj^g|0C3{b(xpR##Rm8x=C{a3p0=W zQVF}knx>e`!XMLzVsbHepxu&SZ3OQy)Ng?a04T%Odl>!yW% z>!fM%J)#|R*Y}8q$|kRk{=)aHf9s?bbF=#5eYZO77R|n_`MG7?EE$Q#4XzIYdz9v_ zEiH=raUS6qI>e(%dxGr)GaV;zxqe!Npg84)3OYOD=t=?jT^Qk+*-21rs|!_9OM6Ye9oR`GGeQL z$@HM_Q$(m=(8jeIfni}R6RoE!PWhlw>KfyE#<=rj-s2GWH<4F9I0XilewY7nYb6Uy z_34Q>`n3HQ|GOHe=@PSDU-gV{XW-#=iFJ?8>=c*Fty(E^(LqL#-^bi(1=mjbpF+!W z))bWsO({DxAvDt@IeXR4l%-;(6Qd?PntP>5=BV!8{-c^ZGcwb53tN6>`V;B1LFH4z zL8T*Kt#_aB3VS4QGW@T08TVa=$(|m?S+Doq(e|CuuC>o}iT{}wW=c6H_LwRy@L{cV z7g`bZ^2_Ff`xQke##mi%QjHXHY-f&3*m^+hyy|;?rK`3-DnhSHgdT4%n)u?Z*0lWP z3^HHqj!)=``Tn2TIp}jjjE(KCOs(%$nQ>S3MS`YTc+MBDZuq9W!9&2dV4I)3d!Nk@4mM(}p(7+@)MkC*-~MKPzgvW&KH^Gxhd6FU5y=`rf@iLA7|ZY6;tt z(x4qLL+*cZ_^RsTWhk`V<@3~c6Eu@D?oIwM|4|BG&9aCyiL=5)-dh<>%;cZ_@!sMS zGrnB8W0yB|TIBatqF0!||9u*%u`2l8o~bGC*NT}u__xJ$QpWZF4%ZqcoW8}uSo2I` zc6iWggU+?gC#(hCg%cduI8$VPtU6u3plL@}?s7xb?^XIWrBgiG%BLUZKA2p(ylBUy z`l%M##^;NEXcncV%3gn|diDF>7W26*LT%xDSw1hDx!~K|_m?{hQ@*@D@?J;G{hOnW zb4${s^*gJ=J6ak1QkyHhd!DX7RnRi;xh%^$;ooIZ6Z0>#e)j))i2Y?#m5uy zGmJ|tz6Q6hU)0zlSJDzJ)D_0$`stqTmD7t~F$(oOp1^D)RIgH)mb>6yOT*Xc>pHKe zcfV?QwI@$O&YJyAd(x?BZo~a&EbM(P&d%=%E}g#Y*ov;D%bSt{Kl+?6vORfGbK0|H zpdn_Jmb+$5|;Hw6ERJ#=%6z|*_gR+qh( zGbGF>nZxiNqZk**? zVccn$!uuyIJLlBlKYTN4kBG4Rx>n_r+$Cr=vp{@5lVGXhA*1yVo|~`9?X5Kt-M9X} zNWvL?!LOzZ%(y4JO?=fosau3&>8CS$n?g6o$NtbwXkGXATvvg~(-}$fasOU$JlZ_* zo3P%d5F;Ct4v*VR@0!;=whLjJrT6&fkrj5Pnl*2I1@=qNFj}df^rPnae>bXvZ3lv;1kpTEvxGfuUe(HBy#(OlgI6*?K*Wm|LMC><@&Fdj|$Dh_uH>{ z{_C@2==yU?Ujw(YnEd&%)Z}dYqci*UXUv_+VS6Ixui__Nzm|@Z#(i!V)&`&2;K8$V zy45+QcLAkJA5L5Kiv5asc02T6Od?o#V>Bb=*bvg}3$9 z7yR0xz1@7fg{YdIjKUi&!-+FwiWnKXEOr-dnm2vVlRo1Or&y=Yc`0(^>G3XOi>;p~ zon|SreA?{glkmd6`$qobt)cqW^Jjni^X5}k(2E6HH}5_bUD&wpm;3bV!i5H|rIm$k zXPkG$shWR|p5A-Ht1w~T%KJ0^IKms(A8jMNQmtxu)KqvWGvj*6$Znd@^2|5rX8zfy=_lIkQsh1hZu0k@netk2lfVDZmYm)rcWmQ)H#{s* zI4$~c=Qf+j7h=_CDiq9o+s;09XFRO7pL^E!r#;pp>HGBO?VJ2}k00;r_d?TtE^FIr znEG{1@~cpTYAUk%ASdWW)cO*1Q!@y)(%#fWP4$E$Da0@#pXL-)Ga9A z@LJ0CMQ+f~goE{K!*#p2Yq#AHNtaLExb&k5^M1~(aIW8SOE+F(y3l?lu_vIfdPn-} zx1r4rv8h65AAHQ4w`##8nYEGWx<@uP*Cg(@xED14KmX5JN+GWftvj0fq{4N{!=(pu z;zDP{Pk8U!`ZF-$pVXH##qW%t)oZxyUllOxy!Vv%T2o>TLyyfgxYs8bd&-0>;=_!N zCJV-y3DKe7V%5)8er)pynW_@1_GGcyi^a441TJOLUmq$H`|euV+5|JNm%RS+N96QY z3KVdDzUTdq^^@I%JwLs_*spkNuUg-<%I(pVxvP&z^*5C5J+N}^mW2C0n^rv9RdV*u z+mntD!u92|+w1Pmzf^OxCF8FA=1DK?Un**?$B~C6MJ3$eW44i>%Jb+NZk6< zQ*+`~k;Q91JU^^4{aN7^(S5>gO+1IU=KWmx&s%MYYX>h`O?%dZClqSf}a@@ibmMQOW!F}4?55^j6|M9Gt z^KGeNT%$^t=}~iz?P*%G&YOiK?p@8N(z0t_$q$kDhs%4zJ}u={@~zq?uqJaSF@Dl-8;B=?MHzt!iz%}d)2ro{QI9@bPgy&E?U&dihVS!N*VayGe_cND zoQ>1n=Hzur{;St@E);v9`h#2VyjFXaK!tAEsznTX9oz2A+`8@0ohvII+kVdwzED&e z$zdbSCnI}*ueeN(2BXc|^!oOr5vQ;Ix!R((i*Ka{-<6m{iC52lVAgBtU&+JvS?|XJ zkD}z2Ki_zLI5dULKIpQu^D1YXX$)x_b4stL?_U0+e%gUO=i*!5>|ej}VDz5LZ{*gf z-G0`z>}>z9)ibr8EG(?p5p!?piS&glUwZ94n9AP&ct@;A-ejIe>{H_>@BZd5H#@Ukm{FdOrN`~dpKRS{i;u2&Yg=oj`+|#I zHb}6kCtqKgb!E=% zfUGy|IlWWL-nDN$yY5NFIu@qF>CZfsXYabW%6;F=puc$@S8Gg`MkU6zXvyjFiC+)O z|Mcd`q$R?)uIt3aG@5MYpHq27TjFg|V6Z4>?&`IbS(VLoD<+ut&v^CHC;KyFlN7Uj z&=0vy&z}0FOUdUMowz)UZTVk`r4whaHr?ydsqMID#mC}LE={)se7_p!8?OJ@&7;*K zSy8)5;)(whp1m6S-BEqpJURB9V&5wM`K`+};hp=~*5%bTM05PEzF_qK;@9&v+y319 z<9_^n%th^=X17dKG2QxE!5Rs6?W zbi)e$2bVT<{kpY+f#bl;%6klU)jn;hExX0clsG&$Y4x$~iIEM9x={aaoqU*>$6ZxZ zF-Gw-t5Op^bhF(z&7aqPV8IpMww|n#%Ci|e#hKK$dwCr)J+btJDe@Jv)(G+`aa1t-=(^r>+gZv_f424J5IZQ{DgdqXz_8; zdHo(2st@TFCQZ1p(}cBam9Pp&mk>klQLdAkhgO-no_XuKxOT;Q$shC89{hS<+i@+T zaoapI-uCYjk0kpYL$_vpkYIZwy2*dz_m()NYg?}=&YsnEJa@{=)qj-yu1yM3TK@B& z8F%1<^&U#cWak{o;W)IpG%#Gud}^|=_qxhe*-xCq#kYUce=HYh{Q7F8(fm%u2&Elf zB~qQ5EbXu5+pakVJEWi3yL(q8?_a?yUC&mo`jsDhGNLT-yx8HDw)1$}+V9-DzvR&S zu$iBjrhAnw4|daQ+O_u*r$@@B)T2fI@+K96>*v(^NA}BY;T6$2?GQ7CF}crI}IVYw4roL3H{#HZ}bJd!p$sL^h_ojU)ee15AARD)-^;2GZ#@4rw=Ix!$ zn%z~kWp#>d(S)97@BUiY-c|d5y-g-Ge131=s&8DXudFrCl-W&L%h!1EgYNv&y)DzX&XV^($eg6{ z-|)e+w_k33T<^ul)mAyHrEBZqV-ua?SkhG$zRzLxUl6$3TRI~;aTgwOA!jTv~eR znpJVuVdYzF?JA<-f7_z7Z{&y_G@riW#m*K|9G;Pb%7$YL&u`MQb#*4W`56#P3QZ#<@Dpbdi$LNs~+rFB={xvYJq9d(Qs2^ zrG}a1D_>6G|JmNO|4{nrmyPF||2um3y0OII1f4EL^NSY@)RH&oAN$BnX4avu2wP0CC0Jc_r}E7r2HH9A4I1s zMVynEyzQBw$l3|lH%>C1AU?%X=F~Y=kML>VCOnlc^UV^E2~s|o#aH6bxB1S^yCK{; z-AB$JoSr{^Mhtr&YgEuaH_j`_KG5>Q%m+%&028zQKxy!!MHbjigs}{ zMoQl~lD<$ba<=3aO`dfxrk?bFYilHaMDmVX1(Tz+iRa2aF1Hi=e{mk3-ZiIUu2rh- z=cpY4|7RYTJtQFU(rDow-DxME&T+jwb!kSl%EO@8RSkh+67E;nJ}^z1S8OsT=xqoG z(_8}cS-KTa&vcby`ZLwi{yE`1$s3=X_{MNhV(rS*0es6Au=SqpVzw+)htTD<|DoS~~ zT=o35Z3$;Pg&8k&2<=;F;(ZS@8+nR48D3l5bDQ(=Uz4Q{bA15IRT-z% zT<`p5-#zKF?Hua?j=s~}p^kBKmMi5RJ<|xhX{x1Ce*Ig`+(w1y+^0E~7vgewgP5N@ zvE!DA{w^5)ZXJ94Cfzkw*#eQzH^nr%a_m3Rx8O71w}g%Fjc@N_G=Fqnx$=69Wuxow zfA2OHsWkW696NPVz%h+iQ1TIf!q$8XudGTXnl1kT!lscQ|+TA>b#r5sK#u(xChTJNt%MU)-f2_U#q2oPfCArn% zo{o!oR4NNJzv$|^F5eurWp31DK9xW}ULB>?W^-RNo^$S=HR*Hq^9@g!<)3tNJpI8o zJ!r3c^$bzQ4HoKht6RnE*0b0DspxXObG63q=%h#a9P29+_pHv?z0*&9*7-N}a{}Gp z{tqu(UCd-+#cooucS=a+i}d;qrM15-S^j(X9{xQ+nw|Z-l*x@~v$et5@OcNzbfx`jz|a_=p(4{`!2ed_8=8%~>+uJS8; z#UMDl>qT8{MCHDaMYq`O+pq1mDSaomPj-3P>G_AZP2zLAs3#?8EXMX*RXs3D_I>Q4 zkD+G|)a+Wrq<>wrgymK6Th`a-ZhEV%HvYi7DQww1kJ`WmVOwJ}>=H!ZTi#qSX=>B5 z7veTi$K_JXzt1VLVAHw6XS8Yd_54zegVK&`71)bfk9r-xpvfDh9?SS^#anwTjfqd5 z?CSp*z`XA9zH@hzl~`O_OnKcF#VnR9UMr=^Chc-niSyQlLe|C`!TPe>i&y5WttvWN zzLoRyK8uGehpp7wL_97BY+GQFoAya7FT7u>MT6UmZqJ1lvys$#_5$` zWxm2x#)1d0bXP31ea~FAp?pW3zv+YI=`X4!S>!h5u@I1Y4xoubU^98KNS0v8enjmI8v9mh$!?z&YXLcLfI0|Li z5^sl3OP#mu>*B2YnzeDud3ip}6P6drt@#>vc=@dJp{bwv+Ar*#vhGQ%48^*y9#uhz2d$GtWmF7&G&h)-Mm*j zZqJzY{^W8iuN{h)zxui-ALw5eJX__NvHJSYc^h6CnABX?b24&~QeakS@{@m2v(x)` z`s~Rs&ev|3kZqO2l^^U_J|}p|s$&&vKcAiVC3N=dx|F16?AbvFd(S8_N?D!tf6n>n z;O18qGuBS5&7EseEBH24asqSExwt*fcTSx&V|$UmfWzt(pF=}*M5vVqXX&d47dL&g z`|_aYlgSI?z&AO+Z(2=Y5)1dAx!Ek@#6gFGUG10uTeXLUI4<~>xx%467qCZL+ zZ7$55c6@V1K)KhRl;unBFFzV`UiG%sXB&0dc8-Z@4^t;!V7$L;meQs&CqB_UQ{f{) z=a($|0#8*f9w{`SUCmf2^0OjcFa-p<)IxjwA%<&`CCC(NqI5!6?`?RV?K z6VA%a)dy~`{bTU8_`>5oA<3(gBQ`N#Ro=C2_p!?g;mN8ie73FWQ*gGnnQ*T8mBl)HjpCwA-_s{&Yl%PBzb<=DFNKS7xA_b4w_BW|eSdNVsa`DF zJgY`6bn8P_v6Zr$F4%`BF4!C!7W|O+iY*7{idchf6+7O%yuEJQ`F-nKUi6-dDcaP- z`0B#pccNF^g3DKHua;QBIl=b8LOGty(1xUT&Y6cIr?<_HXg#=BYRTDd=GJB1BGWwF zqOLv+5)PVrROV^U?T5EnZ062o)s)NSy*j%he3M#2%%bunkr$W!-wLi^;CgvqQ6yA( z{;K&EKTqC#zN(4I@kfc|)#S@|;fLM-&MfKcsGnD}>sIjTw+*EC^y&O zs^_Y?zmEIe`F!SY>=CoK56e#N)=E&k{35_%Qr6;2>nEuN#Qr{PI*)C#(hFWujR`)x zcDjeedb6!o3I923+p@>Yt+t0r?%a90p!i;`|MjcZ*S6fhazL_D|E5LYiPgJ0tK-t6 ze2#CMsKYrqM6Bu0(`1-oEuL{ue*EOzTgtI&=MN>L)$bw@X*OelI7;aIw=Qd%M_m z+f?_jnde`&u2|>9biT7!>gDY3Q|{^um48+*mX{K6I?MIb^xwAE&J8mEFMSof6371H zoX4rFXIRYl_ObQ|x1IWnW(w>dR-Xxo>uGd~k5=bFq1|@2H#qDYH4I zVDme*_UC4%s}oa0bvqv{dLm(c^?;As>Qe7!@lTe9!nGD3AKHd2I)1L<`s-k3)A`e< z9joD+s3yy~>a&tw)1GP>&Q(p}R~qfU&sh+7m}SKde;3smRnqg-bsaBnOquI@vC6IN z@tjaLdzo7cI2Et@xxJN}QkgaRdeq;^XRpP-*;A?DWrE9*134T)gmb z`R)EHzpl@rYo)KAI-eQya`m;#^Hpbj&o20XAz}3srD*kek8-%)uS%R!-S%|Lebzdw z(^D2OsCArrv>>c0{`bDu_ip)q|Ie^cl3VaU|M&9@42*4=&dvdz&dv(Zg`W%z6?1AQ z+Ik!g5NY)fUaBR^ZrverGC=l7(~6G8AsacwyrLI|vQM7=kHc4Ll8Ctb!L1J-oKL!X z@MvT>d$^;(AI8Gs;-Hd=Lhrq~bd&acsE~htx47cHox_UhGqcKim{+AquB`Am^DOMh z0qtFaZT!v>Q)jGHzr-zBaqYToY0zEQ%4y~I=U-j@#Fy=d%cIC;(qbR2K7LuYwD_Jn z-^NKx1m+9(OO`l3a$k2^Z-1elmClDV6DE3|6>RS~nk0QX_l#GYmyN4TU`X$$)-|WO zp6i~=+Iec$_b2*1&$d1_xt`f7cw9-y!>Of5%PgR+RpYIcrdm*m+~*JcR{vCXrWEBi zOiY#&T`@t%{)haZd21tQ%qf`MWVqn-(QWo^jR*8Dtho8@`^H>zKZgIt1xvU7nQCS5 z*|TcxQrEtQeYp=F?OJ-W`oL2@gAYr*+n#vTML8{G*fam4`O}7f(F@YA&W-*ovz*_d zEp2NFvy2Rrvg@h1&lTn2zwi8en|ba%`~0~@J7>)N9l^lBE0GxzQ4-ZxN)4{^ z3rViZPPR-@vbW>1sj#ZZEyztRNmQuF&B-gas<2f8n`@Ot;j4hQnKSxuqjGOvkG!?gBnqkl4h%vQBqQ1rLSLJUanVete0Pu zu5V~*X{m2uq;F)TTa=QfTU?n}l31aeSF8*&0%C?sYH@N=W(tB0+w{vfnBt zKRGkS3e2=jO-(ekFfi3MF|tV0HAzgg)U`BDHPkgTOHDDdG%_(tF|t51$}_LHBrz{J z6=YOJZh>BAW{Opsp{2P|Qkto*foW=@u8C1nqOPS`a*D38frUXzim{2gk!2E+5&lJ) z>6v+nImoU88I_WmVr6V;nv#^3VxXI7o@%UXl5Aw6YiVqesB37FWSDH4Y+zzxX$Ceb zCE3a?zbH4c#8xRYH!(d`zaTFiECC8|E5`s&TO}hs1B6IGPGU(~eo?NiQg~)wN`84U zLMkLPH#N8<5fq+=X2wPq24+Tv2IgiK1_ns_!%~ZiGxPI6rWzXPL4yPoF;@OXnW=dt ziJ+8ft7Hf^wj#H{%DE^tu_V7JBtJjLRte-N1tUE}18@RYuz^I2M`m$Jeo>_zI8B3d zPH<`=ga^q4IhkN71qE=zwMtBeSW=u=mYM>#NC765oROH9o|WR_yAYiO8~YM7E@Xk=iVifVdsep*R+Vo|DNdTL&Yt&)3Y zZUNXg3L4PB)I?QZo{_6xD+5_K`w4~TsHdPk_c2PK@0?y3be$~c%Y>f3JRl^kQBb7!8ICOB!vJ;ibqq| zXmF7f0wgIOOTm`I2DT(`cNd2LAh=-f^2rPg44efX zk;M!Q+`=Ht$S`Y;1Oo#Ddx@v7EBjMU8CC%!$r$aw3=C|co-U3d6}R5TzMb@1fy38& zU(%-uXPv+O+c8_#>!$_Bw#@MKvNYl5K$auS8>gp6zB{dxum5`2zkmDR@2=jz%H*F= z)Rw-A(m#?*YF}Hfe)BtT+xx9AFS`GlKljh=x7%`Ve+#L<6MsFlX1S?(+<*PoyYBT* zzfe@tV)UXS?e;eHXBl5g1fqUNSsyo^6IRv!^`DOIrT-mm-drx~@j>er#|blJ=1usy z^Hb+jpX*W+W+-1&{(8b%!#3AFYrb*N;?=M0qw==j7M{C&uV`4%tJj6=7xw1dX3GrP z61Pe3R<+9OgsZ`mJGmm$-o9IU*=PTe`uCP8avJ0Kt3ya1h{fedu7az%~ z&-~4~g@5h!BOiZXdSG(U!9?cb46b7?*8*PtjZ~j-&wcNod8rY>4Q(?V@|{%LJFi8* zRrd4i@9Z;5N%<|uyJ?^D*SP%|cMpC)y-DZ$89S@p{_ZAAlji^9l2P8=lD55(BYx@H zN2yAU&m9?;dTwh`-W)xX$zb6FO@_^X6dE`GxqC_J_7pkwlZ)lwru60PPx`Gn^T&zb zMvw1*|63^Du&Cn1y}R7UT$)Tn4=V6Z*m%pmqG6kU<;OcGCvU5b`z`q|UbSZqdy__> zT13;eY)5Gm2@zM(%IZtM*VctLgh@?H(u`#NKU*zPP{+2}E0cNRnT6r+_r@o6UE{kN za>XP%pdy6B=)A%fC6S(%WL?IS(|ke%1ux0H4%qoG{DZnOL(qqnsgfa?Y=XzCs~>7i zo)E!qCC4Qx|L{eJgW{j_T#V1-PtOvtEAWn1{wm0LD(P$78s$rN;!Ry2du9ITdqud- zirdNC<8s z{j@w|B&R~LKEe}AHD z?E%g;2fCI|Opp0~x|TstVv6VQece76-lbnp%5757eOfvt&go)sCC!KwF ze2aCMRu}p2IMX}(rh@qEU+bpKcewbc`f+@joz1UhmM)v;EKhlUcv1P{#;Xx!`PF+n zW_-8XVt*;iZ!6)c5iPy}F3Tu=f|M(?2V` zw|}MLz-GI&C%8u%q}^?OUl)4Sb%wX-d%`XRm3?bmbN`SHzDgU?hS zGnD(e_~T>kONWe~fB)M$sf+bY(DvXBWhScHtXWy z*A;ScEZp_qw;p58-4y6Qhs#Ig>lvj0hewzh6{UyyCp#+5!f zT~S$K);8X&YVoJ4;;xH2GgWVRE~k((#rRm_wG4Zu&dq4W8`lyq3H5IKXK&fqF}<$l;$caL z{=m~ICo-N*(^I~tpB*W;?O96XTV`gj;zh~-v(>jA9yMK(gMDBHcnV4w}8l>}d^>bP0l+XkK 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 From 997d481e3a7b42b6913806f57858b17a12f05db9 Mon Sep 17 00:00:00 2001 From: Fazana <52551480+FazanaJ@users.noreply.github.com> Date: Tue, 28 Sep 2021 13:50:40 +0100 Subject: [PATCH 2/6] Update rendering_graph_node.c --- src/game/rendering_graph_node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/rendering_graph_node.c b/src/game/rendering_graph_node.c index e1a2b343..de90361b 100644 --- a/src/game/rendering_graph_node.c +++ b/src/game/rendering_graph_node.c @@ -427,7 +427,6 @@ void geo_process_perspective(struct GraphNodePerspective *node) { if (gCamera) { // gWorldScale = ((sqr(gCamera->pos[0]) + sqr(gCamera->pos[1]) + sqr(gCamera->pos[2])) / sqr(0x2000)); gWorldScale = (max_3f(ABS(gCamera->pos[0]), ABS(gCamera->pos[1]), ABS(gCamera->pos[2])) / (f32)0x2000); - gWorldScale = MAX(gWorldScale, 1.0f); } else { gWorldScale = 1.0f; } @@ -436,6 +435,7 @@ void geo_process_perspective(struct GraphNodePerspective *node) { farClipDelta /= farClip; gWorldScale *= farClipDelta; } + gWorldScale = MAX(gWorldScale, 1.0f); guPerspective(mtx, &perspNorm, node->fov, sAspectRatio, ((farClip / 300) / gWorldScale), (farClip / gWorldScale), 1.0f); gSPPerspNormalize(gDisplayListHead++, perspNorm); From 4ba22859690fb8a51a0a67205015e7d5d41d9b19 Mon Sep 17 00:00:00 2001 From: Fazana <52551480+FazanaJ@users.noreply.github.com> Date: Tue, 28 Sep 2021 17:39:49 +0100 Subject: [PATCH 3/6] Graph optimisations that actually work now --- Makefile | 12 +- asm/math.s | 46 +++++ sm64.ld | 1 + src/boot/memory.c | 10 +- src/engine/math_util.c | 423 +++++++++++++++++++++++++---------------- 5 files changed, 323 insertions(+), 169 deletions(-) create mode 100644 asm/math.s diff --git a/Makefile b/Makefile index 47259e2e..f8d7885b 100644 --- a/Makefile +++ b/Makefile @@ -153,12 +153,12 @@ LINK_LIBRARIES = $(foreach i,$(LIBRARIES),-l$(i)) ifeq ($(COMPILER),gcc) NON_MATCHING := 1 MIPSISET := -mips3 - OPT_FLAGS := -Os + OPT_FLAGS := -Ofast else ifeq ($(COMPILER),clang) NON_MATCHING := 1 # clang doesn't support ABI 'o32' for 'mips3' MIPSISET := -mips2 - OPT_FLAGS := -Os + OPT_FLAGS := -Ofast endif @@ -197,7 +197,7 @@ UNF ?= 0 $(eval $(call validate-option,UNF,0 1)) ifeq ($(UNF),1) DEFINES += UNF=1 - SRC_DIRS += src/usb + SRC_DIRS += src/usbOfast USE_DEBUG := 1 endif @@ -394,8 +394,8 @@ export LD_LIBRARY_PATH=./tools AS := $(CROSS)as ifeq ($(COMPILER),gcc) CC := $(CROSS)gcc - $(BUILD_DIR)/actors/%.o: OPT_FLAGS := -Os -mlong-calls - $(BUILD_DIR)/levels/%.o: OPT_FLAGS := -Os -mlong-calls + $(BUILD_DIR)/actors/%.o: OPT_FLAGS := -Ofast -mlong-calls + $(BUILD_DIR)/levels/%.o: OPT_FLAGS := -Ofast -mlong-calls else ifeq ($(COMPILER),clang) CC := clang endif @@ -430,7 +430,7 @@ DEF_INC_CFLAGS := $(foreach i,$(INCLUDE_DIRS),-I$(i)) $(C_DEFINES) # C compiler options CFLAGS = -G 0 $(OPT_FLAGS) $(TARGET_CFLAGS) $(MIPSISET) $(DEF_INC_CFLAGS) ifeq ($(COMPILER),gcc) - CFLAGS += -mno-shared -march=vr4300 -mfix4300 -mabi=32 -mhard-float -mdivide-breaks -fno-stack-protector -fno-common -fno-zero-initialized-in-bss -fno-PIC -mno-abicalls -fno-strict-aliasing -fno-inline-functions -ffreestanding -fwrapv -Wall -Wextra -Wno-missing-braces -fno-jump-tables + CFLAGS += -mno-shared -march=vr4300 -mfix4300 -mabi=32 -mhard-float -mdivide-breaks -fno-stack-protector -fno-common -fno-zero-initialized-in-bss -fno-PIC -mno-abicalls -fno-strict-aliasing -fno-inline-functions -ffreestanding -fwrapv -Wall -Wextra -Wno-missing-braces else ifeq ($(COMPILER),clang) CFLAGS += -target mips -mabi=32 -G 0 -mhard-float -fomit-frame-pointer -fno-stack-protector -fno-common -I include -I src/ -I $(BUILD_DIR)/include -fno-PIC -mno-abicalls -fno-strict-aliasing -fno-inline-functions -ffreestanding -fwrapv -Wall -Wextra -Wno-missing-braces -fno-jump-tables else diff --git a/asm/math.s b/asm/math.s new file mode 100644 index 00000000..1649959d --- /dev/null +++ b/asm/math.s @@ -0,0 +1,46 @@ +# assembler directives +.set noat # allow manual use of $at +.set noreorder # don't insert nops after branches +.set gp=64 + +.include "macros.inc" + + +.section .text, "ax" + +.global mtxf_to_mtx_asm +.balign 32 +mtxf_to_mtx_asm: + addiu $v0, $zero, 0x0001 + lui $t2, 0x4780 + mtc1 $t2, $f4 +loop: + lwc1 $f0, 0x0000($a1) + andi $t0, $v0, 0x0002 + mul.s $f0, $f0, $f4 + lwc1 $f2, 0x0004($a1) + trunc.w.s $f0, $f0 + mfc1 $t3, $f0 + addiu $a1, $a1, 0x0008 + sra $t4, $t3, 16 + sh $t4, 0x0000($a0) + sh $t3, 0x0020($a0) + bne $t0, $zero, storezero + addiu $v0, $v0, 0x0002 + mul.s $f2, $f2, $f4 + addiu $t1, $zero, 1 + trunc.w.s $f2, $f2 + mfc1 $t3, $f2 + addiu $v1, $zero, 0x0011 + sra $t4, $t3, 16 + sh $t4, 0x0002($a0) + sh $t3, 0x0022($a0) +loopend: + bne $v0, $v1, loop + addiu $a0, $a0, 0x0004 + jr $ra + sh $t1, -2 ($a0) +storezero: + sh $zero, 0x0002($a0) + j loopend + sh $zero, 0x0022($a0) \ No newline at end of file diff --git a/sm64.ld b/sm64.ld index 28f16fb0..a390d36f 100755 --- a/sm64.ld +++ b/sm64.ld @@ -245,6 +245,7 @@ SECTIONS { BUILD_DIR/src/game*.o(.text); BUILD_DIR/src/engine*.o(.text); + BUILD_DIR/asm/math.o(.text); _engineSegmentTextEnd = .; /* data */ BUILD_DIR/src/game*.o(.*data*); diff --git a/src/boot/memory.c b/src/boot/memory.c index b492fff9..e0914775 100644 --- a/src/boot/memory.c +++ b/src/boot/memory.c @@ -66,7 +66,9 @@ extern struct MainPoolBlock *sPoolListHeadR; */ struct MemoryPool *gEffectsMemoryPool; + uintptr_t sSegmentTable[32]; +uintptr_t sSegmentROMTable[32]; u32 sPoolFreeSpace; u8 *sPoolStart; u8 *sPoolEnd; @@ -337,13 +339,13 @@ void *load_segment(s32 segment, u8 *srcStart, u8 *srcEnd, u32 side, u8 *bssStart addr = dynamic_dma_read(srcStart, srcEnd, side, TLB_PAGE_SIZE, (uintptr_t)bssEnd - (uintptr_t)bssStart); if (addr != NULL) { u8 *realAddr = (u8 *)ALIGN((uintptr_t)addr, TLB_PAGE_SIZE); - set_segment_base_addr(segment, realAddr); + set_segment_base_addr(segment, realAddr); sSegmentROMTable[segment] = (uintptr_t) srcStart; mapTLBPages(segment << 24, VIRTUAL_TO_PHYSICAL(realAddr), (srcEnd - srcStart) + ((uintptr_t)bssEnd - (uintptr_t)bssStart), segment); } } else { addr = dynamic_dma_read(srcStart, srcEnd, side, 0, 0); if (addr != NULL) { - set_segment_base_addr(segment, addr); + set_segment_base_addr(segment, addr); sSegmentROMTable[segment] = (uintptr_t) srcStart; } } #if PUPPYPRINT_DEBUG @@ -418,7 +420,7 @@ void *load_segment_decompress(s32 segment, u8 *srcStart, u8 *srcEnd) { decompress(compressed, dest); #endif osSyncPrintf("end decompress\n"); - set_segment_base_addr(segment, dest); + set_segment_base_addr(segment, dest); sSegmentROMTable[segment] = (uintptr_t) srcStart; main_pool_free(compressed); } } @@ -457,7 +459,7 @@ void *load_segment_decompress_heap(u32 segment, u8 *srcStart, u8 *srcEnd) { #elif MIO0 decompress(compressed, gDecompressionHeap); #endif - set_segment_base_addr(segment, gDecompressionHeap); + set_segment_base_addr(segment, gDecompressionHeap); sSegmentROMTable[segment] = (uintptr_t) srcStart; main_pool_free(compressed); } return gDecompressionHeap; diff --git a/src/engine/math_util.c b/src/engine/math_util.c index 80c3c101..7e4632d6 100644 --- a/src/engine/math_util.c +++ b/src/engine/math_util.c @@ -12,6 +12,10 @@ #include "config.h" +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wreturn-local-addr" +#pragma intrinsic(sqrtf); + /// Returns the lowest of three values. s32 min_3i(s32 a0, s32 a1, s32 a2) { if (a1 < a0) a0 = a1; if (a2 < a0) a0 = a2; return a0; } f32 min_3f(f32 a0, f32 a1, f32 a2) { if (a1 < a0) a0 = a1; if (a2 < a0) a0 = a2; return a0; } @@ -108,36 +112,47 @@ void vec3f_cross(Vec3f dest, Vec3f a, Vec3f b) { /// Scale vector 'dest' so it has length 1 void vec3f_normalize(Vec3f dest) { - f32 invsqrt = sqrtf(sqr(dest[0]) + sqr(dest[1]) + sqr(dest[2])); - if (invsqrt < 0.00001f) return; - invsqrt = 1.0f / invsqrt; - vec3_mul_val(dest, invsqrt); + f32 size = sqrtf(dest[0] * dest[0] + dest[1] * dest[1] + dest[2] * dest[2]); + register f32 invsqrt; + if (size > 0.01f) { + + invsqrt = 1.0f / size; + vec3_mul_val(dest, invsqrt); + /*dest[0] *= invsqrt; + dest[1] *= invsqrt; + dest[2] *= invsqrt;*/ + } else { + dest[0] = 0; + dest[1] = 1; + dest[2] = 0; + } } -/// Copy matrix 'src' to 'dest' -void mtxf_copy(Mat4 dest, Mat4 src) { - register s32 i; - register u32 *d = (u32 *) dest; - register u32 *s = (u32 *) src; +#pragma GCC diagnostic pop +struct CopyMe { + f32 x; f32 y; f32 z; f32 w; + f32 x1; f32 y1; f32 z1; f32 w1; + f32 x2; f32 y2; f32 z2; f32 w2; + f32 x3; f32 y3; f32 z3; f32 w3; +}; - for (i = 0; i < 16; i++) { - *d++ = *s++; - } +/// Copy matrix 'src' to 'dest' +void mtxf_copy(register Mat4 dest, register Mat4 src) { + *((struct CopyMe *) dest) = *((struct CopyMe *) src); } /** * Set mtx to the identity matrix */ -void mtxf_identity(Mat4 mtx) { - register s32 i; - register f32 *dest; - // These loops must be one line to match on -O2 - - // initialize everything except the first and last cells to 0 - for (dest = (f32 *) mtx + 1, i = 0; i < 14; dest++, i++) *dest = 0; - - // initialize the diagonal cells to 1 - for (dest = (f32 *) mtx, i = 0; i < 4; dest += 5, i++) *dest = 1; +void mtxf_identity(register Mat4 mtx) { + s32 i; + f32 *dest; + for (dest = (f32 *) mtx + 1, i = 0; i < 14; dest++, i++) { + *dest = 0; + } + for (dest = (f32 *) mtx, i = 0; i < 4; dest += 5, i++) { + *((u32 *) dest) = 0x3F800000; + } } /** @@ -194,6 +209,14 @@ void mtxf_rot_trans_mul(Vec3s rot, Vec3f trans, Mat4 dest, Mat4 src) { ((u32 *) dest)[15] = 0x3F800000; } +f32 lookAtCalc(f32 sqrtsqrt) { + f32 calc = sqrtf(sqrtsqrt); + if (calc == 0) + calc = 0.00000000001; + + return -1.0 / calc; +} + /** * Set mtx to a look-at matrix for the camera. The resulting transformation * transforms the world as if there exists a camera at position 'from' pointed @@ -201,47 +224,73 @@ void mtxf_rot_trans_mul(Vec3s rot, Vec3f trans, Mat4 dest, Mat4 src) { * angle allows a bank rotation of the camera. */ void mtxf_lookat(Mat4 mtx, Vec3f from, Vec3f to, s32 roll) { - Vec3f colX, colY, colZ; + register f32 invLength; + f32 dx; + f32 dz; + f32 xColY; + f32 yColY; + f32 zColY; + f32 xColZ; + f32 yColZ; + f32 zColZ; + f32 xColX; + f32 yColX; + f32 zColX; + f32 calc; - f32 dx = to[0] - from[0]; - f32 dz = to[2] - from[2]; + dx = to[0] - from[0]; + dz = to[2] - from[2]; - register f32 invLength = -1.0f / MAX(sqrtf(sqr(dx) + sqr(dz)), 0.00001f); + invLength = lookAtCalc(dx * dx + dz * dz); dx *= invLength; dz *= invLength; - colY[1] = coss(roll); - colY[0] = sins(roll) * dz; - colY[2] = -sins(roll) * dx; - vec3_diff(colZ, to, from); + yColY = coss(roll); + xColY = sins(roll) * dz; + zColY = -sins(roll) * dx; - invLength = -1.0f / MAX(sqrtf(sqr(colZ[0]) + sqr(colZ[1]) + sqr(colZ[2])), 0.00001f); - vec3_mul_val(colZ, invLength); + xColZ = to[0] - from[0]; + yColZ = to[1] - from[1]; + zColZ = to[2] - from[2]; - vec3_cross(colX, colY, colZ); + invLength = lookAtCalc(xColZ * xColZ + yColZ * yColZ + zColZ * zColZ); + xColZ *= invLength; + yColZ *= invLength; + zColZ *= invLength; - invLength = 1.0f / MAX(sqrtf(sqr(colX[0]) + sqr(colX[1]) + sqr(colX[2])), 0.00001f); - vec3_mul_val(colX, invLength); + xColX = yColY * zColZ - zColY * yColZ; + yColX = zColY * xColZ - xColY * zColZ; + zColX = xColY * yColZ - yColY * xColZ; - vec3_cross(colY, colZ, colX); + invLength = -lookAtCalc(xColX * xColX + yColX * yColX + zColX * zColX); - invLength = 1.0f / MAX(sqrtf(sqr(colY[0]) + sqr(colY[1]) + sqr(colY[2])), 0.00001f); - vec3_mul_val(colY, invLength); + xColX *= invLength; + yColX *= invLength; + zColX *= invLength; - mtx[0][0] = colX[0]; - mtx[1][0] = colX[1]; - mtx[2][0] = colX[2]; + xColY = yColZ * zColX - zColZ * yColX; + yColY = zColZ * xColX - xColZ * zColX; + zColY = xColZ * yColX - yColZ * xColX; - mtx[0][1] = colY[0]; - mtx[1][1] = colY[1]; - mtx[2][1] = colY[2]; + invLength = -lookAtCalc(xColY * xColY + yColY * yColY + zColY * zColY); + xColY *= invLength; + yColY *= invLength; + zColY *= invLength; - mtx[0][2] = colZ[0]; - mtx[1][2] = colZ[1]; - mtx[2][2] = colZ[2]; - mtx[3][0] = -vec3_dot(from, colX); - mtx[3][1] = -vec3_dot(from, colY); - mtx[3][2] = -vec3_dot(from, colZ); + mtx[0][0] = xColX; + mtx[1][0] = yColX; + mtx[2][0] = zColX; + mtx[3][0] = -(from[0] * xColX + from[1] * yColX + from[2] * zColX); + + mtx[0][1] = xColY; + mtx[1][1] = yColY; + mtx[2][1] = zColY; + mtx[3][1] = -(from[0] * xColY + from[1] * yColY + from[2] * zColY); + + mtx[0][2] = xColZ; + mtx[1][2] = yColZ; + mtx[2][2] = zColZ; + mtx[3][2] = -(from[0] * xColZ + from[1] * yColZ + from[2] * zColZ); mtx[0][3] = 0; mtx[1][3] = 0; @@ -278,8 +327,8 @@ void mtxf_rotate_zxy_and_translate(Mat4 dest, Vec3f translate, Vec3s rotate) { dest[2][2] = cx * cy; dest[3][2] = translate[2]; - dest[0][3] = dest[1][3] = dest[2][3] = 0.0f; - dest[3][3] = 1.0f; + dest[0][3] = dest[1][3] = dest[2][3] = 0.; + ((u32 *) dest)[15] = 0x3F800000; } /** @@ -314,7 +363,7 @@ void mtxf_rotate_xyz_and_translate(Mat4 dest, Vec3f b, Vec3s c) { dest[3][0] = b[0]; dest[3][1] = b[1]; dest[3][2] = b[2]; - dest[3][3] = 1; + ((u32 *) dest)[15] = 0x3F800000; } /** @@ -324,30 +373,28 @@ void mtxf_rotate_xyz_and_translate(Mat4 dest, Vec3f b, Vec3s c) { * 'angle' rotates the object while still facing the camera. */ void mtxf_billboard(Mat4 dest, Mat4 mtx, Vec3f position, s32 angle) { - if (angle == 0x0) { - dest[0][0] = 1; - dest[0][1] = 0; - } else { - dest[0][0] = coss(angle); - dest[0][1] = sins(angle); + register s32 i; + register f32 *temp, *temp2; + temp = dest; + for (i = 0; i < 16; i++) { + *temp = 0; + temp++; } - dest[0][2] = 0; - dest[0][3] = 0; - + dest[0][0] = coss(angle); + dest[0][1] = sins(angle); dest[1][0] = -dest[0][1]; dest[1][1] = dest[0][0]; - dest[1][2] = 0; - dest[1][3] = 0; - - dest[2][0] = 0; - dest[2][1] = 0; - dest[2][2] = 1; + ((u32 *) dest)[10] = 0x3F800000; dest[2][3] = 0; + ((u32 *) dest)[15] = 0x3F800000; - dest[3][0] = mtx[0][0] * position[0] + mtx[1][0] * position[1] + mtx[2][0] * position[2] + mtx[3][0]; - dest[3][1] = mtx[0][1] * position[0] + mtx[1][1] * position[1] + mtx[2][1] * position[2] + mtx[3][1]; - dest[3][2] = mtx[0][2] * position[0] + mtx[1][2] * position[1] + mtx[2][2] * position[2] + mtx[3][2]; - dest[3][3] = 1; + temp = dest; + temp2 = mtx; + for (i = 0; i < 3; i++) { + temp[12] = temp2[0] * position[0] + temp2[4] * position[1] + temp2[8] * position[2] + temp2[12]; + temp++; + temp2++; + } } /** @@ -371,15 +418,25 @@ void mtxf_align_terrain_normal(Mat4 dest, Vec3f upDir, Vec3f pos, s32 yaw) { vec3_cross(forwardDir, leftDir, upDir); vec3f_normalize(forwardDir); - vec3f_copy(dest[0], leftDir); - vec3f_copy(dest[1], upDir); - vec3f_copy(dest[2], forwardDir); - vec3f_copy(dest[3], pos); + dest[0][0] = leftDir[0]; + dest[0][1] = leftDir[1]; + dest[0][2] = leftDir[2]; + dest[3][0] = pos[0]; - dest[0][3] = 0.0f; - dest[1][3] = 0.0f; - dest[2][3] = 0.0f; - dest[3][3] = 1.0f; + dest[1][0] = upDir[0]; + dest[1][1] = upDir[1]; + dest[1][2] = upDir[2]; + dest[3][1] = pos[1]; + + dest[2][0] = forwardDir[0]; + dest[2][1] = forwardDir[1]; + dest[2][2] = forwardDir[2]; + dest[3][2] = pos[2]; + + dest[0][3] = 0; + dest[1][3] = 0; + dest[2][3] = 0; + ((u32 *) dest)[15] = 0x3F800000; } /** @@ -391,10 +448,14 @@ void mtxf_align_terrain_normal(Mat4 dest, Vec3f upDir, Vec3f pos, s32 yaw) { * 'radius' is the distance from each triangle vertex to the center */ void mtxf_align_terrain_triangle(Mat4 mtx, Vec3f pos, s32 yaw, f32 radius) { - struct Surface *floor; - Vec3f point0, point1, point2; + struct Surface *sp74; + Vec3f point0; + Vec3f point1; + Vec3f point2; Vec3f forward; - Vec3f xColumn, yColumn, zColumn; + Vec3f xColumn; + Vec3f yColumn; + Vec3f zColumn; f32 avgY; f32 minY = -radius * 3; @@ -405,9 +466,9 @@ void mtxf_align_terrain_triangle(Mat4 mtx, Vec3f pos, s32 yaw, f32 radius) { point2[0] = pos[0] + radius * sins(yaw + 0xD555); point2[2] = pos[2] + radius * coss(yaw + 0xD555); - point0[1] = find_floor(point0[0], pos[1] + 150, point0[2], &floor); - point1[1] = find_floor(point1[0], pos[1] + 150, point1[2], &floor); - point2[1] = find_floor(point2[0], pos[1] + 150, point2[2], &floor); + point0[1] = find_floor(point0[0], pos[1] + 150, point0[2], &sp74); + point1[1] = find_floor(point1[0], pos[1] + 150, point1[2], &sp74); + point2[1] = find_floor(point2[0], pos[1] + 150, point2[2], &sp74); if (point0[1] - pos[1] < minY) { point0[1] = pos[1]; @@ -421,27 +482,35 @@ void mtxf_align_terrain_triangle(Mat4 mtx, Vec3f pos, s32 yaw, f32 radius) { point2[1] = pos[1]; } - avgY = (point0[1] + point1[1] + point2[1]) / 3; + avgY = (point0[1] + point1[1] + point2[1]) * .3333333333333333333333333333333333333333333333f; - vec3_set(forward, sins(yaw), 0, coss(yaw)); + vec3f_set(forward, sins(yaw), 0, coss(yaw)); find_vector_perpendicular_to_plane(yColumn, point0, point1, point2); vec3f_normalize(yColumn); - vec3_cross(xColumn, yColumn, forward); + vec3f_cross(xColumn, yColumn, forward); vec3f_normalize(xColumn); - vec3_cross(zColumn, xColumn, yColumn); + vec3f_cross(zColumn, xColumn, yColumn); vec3f_normalize(zColumn); - vec3f_copy(mtx[0], xColumn); - vec3f_copy(mtx[1], yColumn); - vec3f_copy(mtx[2], zColumn); + mtx[0][0] = xColumn[0]; + mtx[0][1] = xColumn[1]; + mtx[0][2] = xColumn[2]; mtx[3][0] = pos[0]; + + mtx[1][0] = yColumn[0]; + mtx[1][1] = yColumn[1]; + mtx[1][2] = yColumn[2]; mtx[3][1] = (avgY < pos[1]) ? pos[1] : avgY; + + mtx[2][0] = zColumn[0]; + mtx[2][1] = zColumn[1]; + mtx[2][2] = zColumn[2]; mtx[3][2] = pos[2]; mtx[0][3] = 0; mtx[1][3] = 0; mtx[2][3] = 0; - mtx[3][3] = 1; + ((u32 *) mtx)[15] = 0x3F800000; } /** @@ -453,50 +522,45 @@ void mtxf_align_terrain_triangle(Mat4 mtx, Vec3f pos, s32 yaw, f32 radius) { * then a. */ void mtxf_mul(Mat4 dest, Mat4 a, Mat4 b) { - Mat4 temp; - register Vec3f entry; - - // column 0 - vec3_copy(entry, a[0]); - temp[0][0] = entry[0] * b[0][0] + entry[1] * b[1][0] + entry[2] * b[2][0]; - temp[0][1] = entry[0] * b[0][1] + entry[1] * b[1][1] + entry[2] * b[2][1]; - temp[0][2] = entry[0] * b[0][2] + entry[1] * b[1][2] + entry[2] * b[2][2]; - - // column 1 - vec3_copy(entry, a[1]); - temp[1][0] = entry[0] * b[0][0] + entry[1] * b[1][0] + entry[2] * b[2][0]; - temp[1][1] = entry[0] * b[0][1] + entry[1] * b[1][1] + entry[2] * b[2][1]; - temp[1][2] = entry[0] * b[0][2] + entry[1] * b[1][2] + entry[2] * b[2][2]; - - // column 2 - vec3_copy(entry, a[2]); - temp[2][0] = entry[0] * b[0][0] + entry[1] * b[1][0] + entry[2] * b[2][0]; - temp[2][1] = entry[0] * b[0][1] + entry[1] * b[1][1] + entry[2] * b[2][1]; - temp[2][2] = entry[0] * b[0][2] + entry[1] * b[1][2] + entry[2] * b[2][2]; - - // column 3 - vec3_copy(entry, a[3]); - temp[3][0] = entry[0] * b[0][0] + entry[1] * b[1][0] + entry[2] * b[2][0] + b[3][0]; - temp[3][1] = entry[0] * b[0][1] + entry[1] * b[1][1] + entry[2] * b[2][1] + b[3][1]; - temp[3][2] = entry[0] * b[0][2] + entry[1] * b[1][2] + entry[2] * b[2][2] + b[3][2]; - - temp[0][3] = temp[1][3] = temp[2][3] = 0; - temp[3][3] = 1; - - mtxf_copy(dest, temp); + register f32 entry0; + register f32 entry1; + register f32 entry2; + register f32 *temp = a; + register f32 *temp2 = dest; + register f32 *temp3; + register s32 i; + for (i = 0; i < 16; i++) { + entry0 = temp[0]; + entry1 = temp[1]; + entry2 = temp[2]; + temp3 = b; + for (; (i & 3) !=3; i++) { + *temp2 = entry0 * temp3[0] + entry1 * temp3[4] + entry2 * temp3[8]; + temp2++; + temp3++; + } + *temp2 = 0; + temp += 4; + temp2++; + } + vec3f_add(&dest[3][0], &b[3][0]); + ((u32 *) dest)[15] = 0x3F800000; } /** * Set matrix 'dest' to 'mtx' scaled by vector s */ -void mtxf_scale_vec3f(Mat4 dest, Mat4 mtx, Vec3f s) { +void mtxf_scale_vec3f(Mat4 dest, Mat4 mtx, register Vec3f s) { + register f32 *temp = dest; + register f32 *temp2 = mtx; register s32 i; - for (i = 0; i < 4; i++) { - dest[0][i] = mtx[0][i] * s[0]; - dest[1][i] = mtx[1][i] * s[1]; - dest[2][i] = mtx[2][i] * s[2]; - dest[3][i] = mtx[3][i]; + temp[0] = temp2[0] * s[0]; + temp[4] = temp2[4] * s[1]; + temp[8] = temp2[8] * s[2]; + temp[12] = temp2[12]; + temp++; + temp2++; } } @@ -509,10 +573,14 @@ void mtxf_mul_vec3s(Mat4 mtx, Vec3s b) { register f32 x = b[0]; register f32 y = b[1]; register f32 z = b[2]; - - b[0] = x * mtx[0][0] + y * mtx[1][0] + z * mtx[2][0] + mtx[3][0]; - b[1] = x * mtx[0][1] + y * mtx[1][1] + z * mtx[2][1] + mtx[3][1]; - b[2] = x * mtx[0][2] + y * mtx[1][2] + z * mtx[2][2] + mtx[3][2]; + register f32 *temp2 = mtx; + register s32 i; + register s16 *c = b; + for (i = 0; i < 3; i++) { + c[0] = x * temp2[0] + y * temp2[4] + z * temp2[8] + temp2[12]; + c++; + temp2++; + } } /** @@ -562,14 +630,36 @@ void mtxf_to_mtx(void *dest, void *src) { /** * Set 'mtx' to a transformation matrix that rotates around the z axis. */ +#define MATENTRY(a, b) \ + ((s16 *) mtx)[a] = ((s32) b) >> 16; \ + ((s16 *) mtx)[a + 16] = ((s32) b) & 0xFFFF; void mtxf_rotate_xy(Mtx *mtx, s32 angle) { - Mat4 temp; - mtxf_identity(temp); - temp[0][0] = coss(angle); - temp[0][1] = sins(angle); - temp[1][0] = -temp[0][1]; - temp[1][1] = temp[0][0]; - mtxf_to_mtx(mtx, temp); + register s32 i = coss(angle) * 65536; + register s32 j = sins(angle) * 65536; + register f32 *temp = mtx; + register s32 k; + for (k = 0; k < 16; k++) { + *temp = 0; + temp++; + } + MATENTRY(0, i) + MATENTRY(1, j) + //((s32 *) mtx)[1] = 0; + MATENTRY(4, -j) + MATENTRY(5, i) + /*((s32 *) mtx)[3] = 0; + ((s32 *) mtx)[4] = 0; + ((s32 *) mtx)[5] = 0; + ((s32 *) mtx)[6] = 0; + ((s32 *) mtx)[7] = 0; + ((s32 *) mtx)[9] = 0; + ((s32 *) mtx)[11] = 0; + ((s32 *) mtx)[12] = 0; + ((s32 *) mtx)[13] = 0; + ((s32 *) mtx)[14] = 0; + ((s32 *) mtx)[15] = 0;*/ + ((s16 *) mtx)[10] = 1; + ((s16 *) mtx)[15] = 1; } /** @@ -580,14 +670,27 @@ void mtxf_rotate_xy(Mtx *mtx, s32 angle) { * objMtx back from screen orientation to world orientation, and then subtracting * the camera position. */ -void get_pos_from_transform_mtx(Vec3f dest, Mat4 objMtx, Mat4 camMtx) { - f32 camX = camMtx[3][0] * camMtx[0][0] + camMtx[3][1] * camMtx[0][1] + camMtx[3][2] * camMtx[0][2]; - f32 camY = camMtx[3][0] * camMtx[1][0] + camMtx[3][1] * camMtx[1][1] + camMtx[3][2] * camMtx[1][2]; - f32 camZ = camMtx[3][0] * camMtx[2][0] + camMtx[3][1] * camMtx[2][1] + camMtx[3][2] * camMtx[2][2]; +void get_pos_from_transform_mtx(Vec3f dest, Mat4 objMtx, register Mat4 camMtx) { + register s32 i; + register f32 *temp = dest; + register f32 *temp2 = camMtx; + f32 y[3]; + register f32 *x = y; + register f32 *temp3 = objMtx; + + for (i = 0; i < 3; i++) { + *x = (temp3[12] - temp2[12]); + temp2++; + temp3++; + x = ((u32)x)+4; + } + temp2 -=3;; + for (i = 0; i < 3; i++) { + *temp = x[-3] * temp2[0] + x[-2] * temp2[1] + x[-1] * temp2[2]; + temp++; + temp2 += 4; + } - dest[0] = objMtx[3][0] * camMtx[0][0] + objMtx[3][1] * camMtx[0][1] + objMtx[3][2] * camMtx[0][2] - camX; - dest[1] = objMtx[3][0] * camMtx[1][0] + objMtx[3][1] * camMtx[1][1] + objMtx[3][2] * camMtx[1][2] - camY; - dest[2] = objMtx[3][0] * camMtx[2][0] + objMtx[3][1] * camMtx[2][1] + objMtx[3][2] * camMtx[2][2] - camZ; } @@ -682,12 +785,15 @@ void vec3f_get_lateral_dist_and_angle(Vec3f from, Vec3f to, f32 *lateralDist, An /// Finds the distance and angles between two vectors. void vec3f_get_dist_and_angle(Vec3f from, Vec3f to, f32 *dist, s16 *pitch, s16 *yaw) { - register Vec3f d; - vec3_diff(d, to, from); - register f32 xz = sqr(d[0]) + sqr(d[2]); - *dist = sqrtf(xz + sqr(d[1])); - *pitch = atan2s(sqrtf(xz), d[1]); - *yaw = atan2s(d[2], d[0]); + register f32 x = to[0] - from[0]; + register f32 y = to[1] - from[1]; + register f32 z = to[2] - from[2]; + register f32 xs = x * x; + register f32 zs = z * z; + + *dist = sqrtf(xs + zs); + *pitch = atan2s(sqrtf(xs + zs), y); + *yaw = atan2s(z, x); } void vec3s_get_dist_and_angle(Vec3s from, Vec3s to, s16 *dist, Angle *pitch, Angle *yaw) { Vec3s d; @@ -714,10 +820,9 @@ void vec3f_get_dist_and_lateral_dist_and_angle(Vec3f from, Vec3f to, f32 *dist, * and has the angles pitch and yaw. */ void vec3f_set_dist_and_angle(Vec3f from, Vec3f to, f32 dist, s32 pitch, s32 yaw) { - register f32 dcos = (dist * coss(pitch)); - to[0] = (from[0] + (dcos * sins(yaw ))); - to[1] = (from[1] + (dist * sins(pitch))); - to[2] = (from[2] + (dcos * coss(yaw ))); + to[0] = from[0] + dist * coss(pitch) * sins(yaw); + to[1] = from[1] + dist * sins(pitch); + to[2] = from[2] + dist * coss(pitch) * coss(yaw); } void vec3s_set_dist_and_angle(Vec3s from, Vec3s to, s16 dist, Angle32 pitch, Angle32 yaw) { register f32 dcos = (dist * coss(pitch)); From e562c6543bf74d730c7d4615932333593c9c5776 Mon Sep 17 00:00:00 2001 From: Fazana <52551480+FazanaJ@users.noreply.github.com> Date: Tue, 28 Sep 2021 17:52:42 +0100 Subject: [PATCH 4/6] Remove profiler.c It's in its own commit, so if you for some reason disagree with this, reverting it is super easy. --- src/boot/main.c | 25 --- src/engine/level_script.c | 2 - src/game/area.c | 4 +- src/game/game_init.c | 8 - src/game/level_update.c | 2 +- src/game/main.h | 1 - src/game/object_list_processor.c | 1 - src/game/profiler.c | 306 ------------------------------- src/game/profiler.h | 51 ------ src/game/sound_init.c | 3 - 10 files changed, 4 insertions(+), 399 deletions(-) delete mode 100644 src/game/profiler.c delete mode 100644 src/game/profiler.h diff --git a/src/boot/main.c b/src/boot/main.c index b4b447b9..74ec296b 100644 --- a/src/boot/main.c +++ b/src/boot/main.c @@ -8,7 +8,6 @@ #include "game/game_init.h" #include "game/memory.h" #include "game/sound_init.h" -#include "game/profiler.h" #include "buffers/buffers.h" #include "segments.h" #include "game/main.h" @@ -71,27 +70,14 @@ s8 gDebugLevelSelect = TRUE; s8 gDebugLevelSelect = FALSE; #endif -s8 gShowProfiler = FALSE; s8 gShowDebugText = FALSE; // unused void handle_debug_key_sequences(void) { - static u16 sProfilerKeySequence[] = { - U_JPAD, U_JPAD, D_JPAD, D_JPAD, L_JPAD, R_JPAD, L_JPAD, R_JPAD - }; static u16 sDebugTextKeySequence[] = { D_JPAD, D_JPAD, U_JPAD, U_JPAD, L_JPAD, R_JPAD, L_JPAD, R_JPAD }; - static s16 sProfilerKey = 0; static s16 sDebugTextKey = 0; if (gPlayer3Controller->buttonPressed != 0) { - if (sProfilerKeySequence[sProfilerKey++] == gPlayer3Controller->buttonPressed) { - if (sProfilerKey == ARRAY_COUNT(sProfilerKeySequence)) { - sProfilerKey = 0, gShowProfiler ^= 1; - } - } else { - sProfilerKey = 0; - } - if (sDebugTextKeySequence[sDebugTextKey++] == gPlayer3Controller->buttonPressed) { if (sDebugTextKey == ARRAY_COUNT(sDebugTextKeySequence)) { sDebugTextKey = 0, gShowDebugText ^= 1; @@ -192,7 +178,6 @@ void interrupt_gfx_sptask(void) { void start_gfx_sptask(void) { if (gActiveSPTask == NULL && sCurrentDisplaySPTask != NULL && sCurrentDisplaySPTask->state == SPTASK_STATE_NOT_STARTED) { - profiler_log_gfx_time(TASKS_QUEUED); #if PUPPYPRINT_DEBUG rspDelta = osGetTime(); #endif @@ -224,7 +209,6 @@ void handle_vblank(void) { if (gActiveSPTask != NULL) { interrupt_gfx_sptask(); } else { - profiler_log_vblank_time(); if (sAudioEnabled) { start_sptask(M_AUDTASK); } else { @@ -234,7 +218,6 @@ void handle_vblank(void) { } else { if (gActiveSPTask == NULL && sCurrentDisplaySPTask != NULL && sCurrentDisplaySPTask->state != SPTASK_STATE_FINISHED) { - profiler_log_gfx_time(TASKS_QUEUED); #if PUPPYPRINT_DEBUG rspDelta = osGetTime(); #endif @@ -267,11 +250,9 @@ void handle_sp_complete(void) { #if PUPPYPRINT_DEBUG profiler_update(rspGenTime, rspDelta); #endif - profiler_log_gfx_time(RSP_COMPLETE); } // Start the audio task, as expected by handle_vblank. - profiler_log_vblank_time(); if (sAudioEnabled) { start_sptask(M_AUDTASK); } else { @@ -281,12 +262,8 @@ void handle_sp_complete(void) { curSPTask->state = SPTASK_STATE_FINISHED; if (curSPTask->task.t.type == M_AUDTASK) { // After audio tasks come gfx tasks. - profiler_log_vblank_time(); if (sCurrentDisplaySPTask != NULL && sCurrentDisplaySPTask->state != SPTASK_STATE_FINISHED) { - if (sCurrentDisplaySPTask->state != SPTASK_STATE_INTERRUPTED) { - profiler_log_gfx_time(TASKS_QUEUED); - } start_sptask(M_GFXTASK); } sCurrentAudioSPTask = NULL; @@ -300,7 +277,6 @@ void handle_sp_complete(void) { #if PUPPYPRINT_DEBUG profiler_update(rspGenTime, rspDelta); #endif - profiler_log_gfx_time(RSP_COMPLETE); } } } @@ -310,7 +286,6 @@ void handle_dp_complete(void) { if (sCurrentDisplaySPTask->msgqueue != NULL) { osSendMesg(sCurrentDisplaySPTask->msgqueue, sCurrentDisplaySPTask->msg, OS_MESG_NOBLOCK); } - profiler_log_gfx_time(RDP_COMPLETE); sCurrentDisplaySPTask->state = SPTASK_STATE_FINISHED_DP; sCurrentDisplaySPTask = NULL; } diff --git a/src/engine/level_script.c b/src/engine/level_script.c index bc2df6db..c22544fa 100644 --- a/src/engine/level_script.c +++ b/src/engine/level_script.c @@ -13,7 +13,6 @@ #include "game/memory.h" #include "game/object_helpers.h" #include "game/object_list_processor.h" -#include "game/profiler.h" #include "game/save_file.h" #include "game/sound_init.h" #include "goddard/renderer.h" @@ -961,7 +960,6 @@ struct LevelCommand *level_script_execute(struct LevelCommand *cmd) { LevelScriptJumpTable[sCurrentCmd->type](); } - profiler_log_thread5_time(LEVEL_SCRIPT_EXECUTE); init_rcp(CLEAR_ZBUFFER); render_game(); end_master_display_list(); diff --git a/src/game/area.c b/src/game/area.c index ca298033..88c61e64 100644 --- a/src/game/area.c +++ b/src/game/area.c @@ -369,7 +369,9 @@ void play_transition_after_delay(s16 transType, s16 time, u8 red, u8 green, u8 b void render_game(void) { if (gCurrentArea != NULL && !gWarpTransition.pauseRendering) { - geo_process_root(gCurrentArea->graphNode, gViewportOverride, gViewportClip, gFBSetColor); + if (gCurrentArea->graphNode) { + geo_process_root(gCurrentArea->graphNode, gViewportOverride, gViewportClip, gFBSetColor); + } gSPViewport(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(&gViewport)); diff --git a/src/game/game_init.c b/src/game/game_init.c index 3e192dbe..689aace3 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -11,7 +11,6 @@ #include "game_init.h" #include "main.h" #include "memory.h" -#include "profiler.h" #include "save_file.h" #include "seq_ids.h" #include "sound_init.h" @@ -322,9 +321,6 @@ void init_rcp(s32 resetZB) { */ void end_master_display_list(void) { draw_screen_borders(); - if (gShowProfiler) { - draw_profiler(); - } gDPFullSync(gDisplayListHead++); gSPEndDisplayList(gDisplayListHead++); @@ -415,7 +411,6 @@ void display_and_vsync(void) { gIsConsole = 1; gBorderHeight = BORDER_HEIGHT_CONSOLE; } - profiler_log_thread5_time(BEFORE_DISPLAY_LISTS); //gIsConsole = (IO_READ(DPC_PIPEBUSY_REG)); osRecvMesg(&gGfxVblankQueue, &gMainReceivedMesg, OS_MESG_BLOCK); if (gGoddardVblankCallback != NULL) { @@ -423,10 +418,8 @@ void display_and_vsync(void) { gGoddardVblankCallback = NULL; } exec_display_list(&gGfxPool->spTask); - profiler_log_thread5_time(AFTER_DISPLAY_LISTS); osRecvMesg(&gGameVblankQueue, &gMainReceivedMesg, OS_MESG_BLOCK); osViSwapBuffer((void *) PHYSICAL_TO_VIRTUAL(gPhysicalFrameBuffers[sRenderedFramebuffer])); - profiler_log_thread5_time(THREAD5_END); osRecvMesg(&gGameVblankQueue, &gMainReceivedMesg, OS_MESG_BLOCK); // Skip swapping buffers on emulator so that they display immediately as the Gfx task finishes if (gIsConsole || gIsVC) { // Read RDP Clock Register, has a value of zero on emulators @@ -741,7 +734,6 @@ void thread5_game_loop(UNUSED void *arg) { draw_reset_bars(); continue; } - profiler_log_thread5_time(THREAD5_START); #if PUPPYPRINT_DEBUG while (TRUE) { lastTime = osGetTime(); diff --git a/src/game/level_update.c b/src/game/level_update.c index cc76124b..3036436c 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -1335,7 +1335,7 @@ s32 lvl_set_current_level(UNUSED s16 arg0, s32 levelNum) { return 0; } - if (gDebugLevelSelect && !gShowProfiler) { + if (gDebugLevelSelect) { return 0; } diff --git a/src/game/main.h b/src/game/main.h index e175a768..2eed3225 100644 --- a/src/game/main.h +++ b/src/game/main.h @@ -65,7 +65,6 @@ extern u32 gNumVblanks; extern s8 gResetTimer; extern s8 gNmiResetBarsTimer; extern s8 gDebugLevelSelect; -extern s8 gShowProfiler; extern s8 gShowDebugText; void set_vblank_handler(s32 index, struct VblankHandler *handler, OSMesgQueue *queue, OSMesg *msg); diff --git a/src/game/object_list_processor.c b/src/game/object_list_processor.c index 659be2e2..ebdf8456 100644 --- a/src/game/object_list_processor.c +++ b/src/game/object_list_processor.c @@ -18,7 +18,6 @@ #include "object_helpers.h" #include "object_list_processor.h" #include "platform_displacement.h" -#include "profiler.h" #include "spawn_object.h" #include "puppyprint.h" #include "puppylights.h" diff --git a/src/game/profiler.c b/src/game/profiler.c deleted file mode 100644 index c834d739..00000000 --- a/src/game/profiler.c +++ /dev/null @@ -1,306 +0,0 @@ -#include - -#include "sm64.h" -#include "profiler.h" -#include "game_init.h" - -s16 gProfilerMode = 0; - -// the thread 3 info is logged on the opposite profiler from what is used by -// the thread4 and 5 loggers. It's likely because the sound thread runs at a -// much faster rate and shouldn't be flipping the index for the "slower" game -// threads, which could leave the frame data in a possibly corrupt or incomplete -// state. -s16 gCurrentFrameIndex1 = 1; -s16 gCurrentFrameIndex2 = 0; - -struct ProfilerFrameData gProfilerFrameData[2]; - -// log the current osTime to the appropriate idx for current thread5 processes. -void profiler_log_thread5_time(enum ProfilerGameEvent eventID) { - gProfilerFrameData[gCurrentFrameIndex1].gameTimes[eventID] = osGetTime(); - - // event ID 4 is the last profiler event for after swapping - // buffers: switch the Info after updating. - if (eventID == THREAD5_END) { - gCurrentFrameIndex1 ^= 1; - gProfilerFrameData[gCurrentFrameIndex1].numSoundTimes = 0; - } -} - -// log the audio system before and after osTimes in pairs to the soundTimes array. -void profiler_log_thread4_time(void) { - struct ProfilerFrameData *profiler = &gProfilerFrameData[gCurrentFrameIndex1]; - - if (profiler->numSoundTimes < ARRAY_COUNT(profiler->soundTimes)) { - profiler->soundTimes[profiler->numSoundTimes++] = osGetTime(); - } -} - -// log the times for gfxTimes: RSP completes, and RDP completes. -void profiler_log_gfx_time(enum ProfilerGfxEvent eventID) { - if (eventID == TASKS_QUEUED) { - gCurrentFrameIndex2 ^= 1; - gProfilerFrameData[gCurrentFrameIndex2].numVblankTimes = 0; - } - - gProfilerFrameData[gCurrentFrameIndex2].gfxTimes[eventID] = osGetTime(); -} - -// log the times between vblank started and ended. -void profiler_log_vblank_time(void) { - struct ProfilerFrameData *profiler = &gProfilerFrameData[gCurrentFrameIndex2]; - - if (profiler->numVblankTimes < ARRAY_COUNT(profiler->vblankTimes)) { - profiler->vblankTimes[profiler->numVblankTimes++] = osGetTime(); - } -} - -// draw the specified profiler given the information passed. -void draw_profiler_bar(OSTime clockBase, OSTime clockStart, OSTime clockEnd, s16 posY, u16 color) { - s64 durationStart, durationEnd; - s32 rectX1, rectX2; - - // set the duration to start, and floor to 0 if the result is below 0. - if ((durationStart = clockStart - clockBase) < 0) { - durationStart = 0; - } - // like the above, but with end. - if ((durationEnd = clockEnd - clockBase) < 0) { - durationEnd = 0; - } - - // calculate the x coordinates of where start and end begins, respectively. - rectX1 = ((((durationStart * 1000000) / osClockRate * 3) / 1000) + 30); - rectX2 = ((((durationEnd * 1000000) / osClockRate * 3) / 1000) + 30); - - //! I believe this is supposed to cap rectX1 and rectX2 to 320, but the - // code seems to use the wrong variables... it's possible that the variable - // names were very similar within a single letter. - if (rectX1 > 319) { - clockStart = 319; - } - if (rectX2 > 319) { - clockEnd = 319; - } - - // perform the render if start is less than end. in most cases, it should be. - if (rectX1 < rectX2) { - gDPPipeSync(gDisplayListHead++); - gDPSetFillColor(gDisplayListHead++, color << 16 | color); - gDPFillRectangle(gDisplayListHead++, rectX1, posY, rectX2, posY + 2); - } -} - -void draw_reference_profiler_bars(void) { - // Draws the reference "max" bars underneath the real thing. - - // Blue - gDPPipeSync(gDisplayListHead++); - gDPSetFillColor(gDisplayListHead++, - GPACK_RGBA5551(40, 80, 255, 1) << 16 | GPACK_RGBA5551(40, 80, 255, 1)); - gDPFillRectangle(gDisplayListHead++, 30, 220, 79, 222); - - // Yellow - gDPPipeSync(gDisplayListHead++); - gDPSetFillColor(gDisplayListHead++, - GPACK_RGBA5551(255, 255, 40, 1) << 16 | GPACK_RGBA5551(255, 255, 40, 1)); - gDPFillRectangle(gDisplayListHead++, 79, 220, 128, 222); - - // Orange - gDPPipeSync(gDisplayListHead++); - gDPSetFillColor(gDisplayListHead++, - GPACK_RGBA5551(255, 120, 40, 1) << 16 | GPACK_RGBA5551(255, 120, 40, 1)); - gDPFillRectangle(gDisplayListHead++, 128, 220, 177, 222); - - // Red - gDPPipeSync(gDisplayListHead++); - gDPSetFillColor(gDisplayListHead++, - GPACK_RGBA5551(255, 40, 40, 1) << 16 | GPACK_RGBA5551(255, 40, 40, 1)); - gDPFillRectangle(gDisplayListHead++, 177, 220, 226, 222); -} - -/* - Draw Profiler Mode 1. This mode draws a traditional per-event bar for durations of tasks - recorded by the profiler calls of various threads. - - Information: - - (yellow): Level Scripts Execution - (orange): Rendering - (blue): Display Lists Send - (red): Sound Updates - (yellow): Time from SP tasks queued to RSP complete - (orange): Time from RSP complete to RDP complete (possibly bugged, see //! note below) - (red): VBlank Times -*/ -void draw_profiler_mode_1(void) { - s32 i; - struct ProfilerFrameData *profiler; - OSTime clockBase; - - // the profiler logs 2 frames of data: last frame and current frame. Indexes are used - // to keep track of the current frame, so the index is xor'd to retrieve the last frame's - // data. - profiler = &gProfilerFrameData[gCurrentFrameIndex1 ^ 1]; - - // calculate the clockBase. - clockBase = profiler->soundTimes[0] - (16433 * osClockRate / 1000000); - - // draw the profiler for the time it takes for level scripts to execute. (yellow) - draw_profiler_bar(clockBase, profiler->gameTimes[0], profiler->gameTimes[1], 212, - GPACK_RGBA5551(255, 255, 40, 1)); - - // draw the profiler for the time it takes for the game to render (between level scripts and - // pre-display lists). (orange) - draw_profiler_bar(clockBase, profiler->gameTimes[1], profiler->gameTimes[2], 212, - GPACK_RGBA5551(255, 120, 40, 1)); - - // draw the profiler for the time it takes for the display lists to send. (blue) - draw_profiler_bar(clockBase, profiler->gameTimes[2], profiler->gameTimes[3], 212, - GPACK_RGBA5551(40, 192, 230, 1)); - - // we need to get the amount of finished numSoundTimes pairs, so get rid of the odd bit to get the - // limit of finished pairs. - profiler->numSoundTimes &= 0xFFFE; - - // draw the sound update times. (red) - for (i = 0; i < profiler->numSoundTimes; i += 2) { - draw_profiler_bar(clockBase, profiler->soundTimes[i], profiler->soundTimes[i + 1], 212, - GPACK_RGBA5551(255, 40, 40, 1)); - } - - //! RSP and RDP run in parallel, so while they are not absolutely guaranteed to return in order, - // it is theoretically possible they might not. In all cases, the RDP should finish later than RSP. - // Thus, this is not really a bug in practice, but should still be noted that the C doesn't check - // this. - draw_profiler_bar(clockBase, profiler->gfxTimes[0], profiler->gfxTimes[1], 216, - GPACK_RGBA5551(255, 255, 40, 1)); - // (orange) - draw_profiler_bar(clockBase, profiler->gfxTimes[1], profiler->gfxTimes[2], 216, - GPACK_RGBA5551(255, 120, 40, 1)); - - // like earlier, toss the odd bit. - profiler->numVblankTimes &= 0xFFFE; - - // render the vblank time pairs. (red) - for (i = 0; i < profiler->numVblankTimes; i += 2) { - draw_profiler_bar(clockBase, profiler->vblankTimes[i], profiler->vblankTimes[i + 1], 216, - GPACK_RGBA5551(255, 40, 40, 1)); - } - - draw_reference_profiler_bars(); -} - -/* - Draw Profiler Mode 0. This mode renders bars over each other to make it - easier to see which processes take the longest. - - Information: - - (red): Sound Updates - (yellow): Level Script Execution - (orange): Rendering - (orange): RDP Duration - (yellow): RSP Duration - (red): VBlank Duration -*/ -void draw_profiler_mode_0(void) { - s32 i; - struct ProfilerFrameData *profiler; - - u64 clockStart; - u64 levelScriptDuration; - u64 renderDuration; - u64 taskStart; - u64 rspDuration; - u64 rdpDuration; - u64 vblank; - u64 soundDuration; - - // get the last frame profiler. gCurrentFrameIndex1 has the current frame being processed, so - // xor it to get the last frame profiler. - profiler = &gProfilerFrameData[gCurrentFrameIndex1 ^ 1]; - - // was thread 5 ran before thread 4? set the lower one to be the clockStart. - clockStart = profiler->gameTimes[0] <= profiler->soundTimes[0] ? profiler->gameTimes[0] - : profiler->soundTimes[0]; - - // set variables for duration of tasks. - levelScriptDuration = profiler->gameTimes[1] - clockStart; - renderDuration = profiler->gameTimes[2] - profiler->gameTimes[1]; - taskStart = 0; - rspDuration = profiler->gfxTimes[1] - profiler->gfxTimes[0]; - rdpDuration = profiler->gfxTimes[2] - profiler->gfxTimes[0]; - vblank = 0; - - // like above functions, toss the odd bit. - profiler->numSoundTimes &= 0xFFFE; - - // sound duration seems to be rendered with empty space and not actually drawn. - for (i = 0; i < profiler->numSoundTimes; i += 2) { - // calculate sound duration of max - min - soundDuration = profiler->soundTimes[i + 1] - profiler->soundTimes[i]; - taskStart += soundDuration; - // was the sound time minimum less than level script execution? - if (profiler->soundTimes[i] < profiler->gameTimes[1]) { - // overlay the levelScriptDuration onto the profiler by subtracting the soundDuration. - levelScriptDuration -= soundDuration; - } else if (profiler->soundTimes[i] < profiler->gameTimes[2]) { - // overlay the renderDuration onto the profiler by subtracting the soundDuration. - renderDuration -= soundDuration; - } - } - - // same as above. toss the odd bit. - profiler->numSoundTimes &= 0xFFFE; - - //! wrong index used to retrieve vblankTimes, thus empty pairs can - // potentially be passed to draw_profiler_bar, because it could be sending - // pairs that are beyond the numVblankTimes enforced non-odd limit, due to - // using the wrong num value. - for (i = 0; i < profiler->numSoundTimes; i += 2) { - vblank += (profiler->vblankTimes[i + 1] - profiler->vblankTimes[i]); - } - - // Draw top profilers. - - // draw sound duration as the first bar. (red) - clockStart = 0; - draw_profiler_bar(0, clockStart, clockStart + taskStart, 212, GPACK_RGBA5551(255, 40, 40, 1)); - - // draw level script execution duration. (yellow) - clockStart += taskStart; - draw_profiler_bar(0, clockStart, clockStart + levelScriptDuration, 212, - GPACK_RGBA5551(255, 255, 40, 1)); - - // draw render duration. (orange) - clockStart += levelScriptDuration; - draw_profiler_bar(0, clockStart, clockStart + renderDuration, 212, - GPACK_RGBA5551(255, 120, 40, 1)); - - // Draw bottom profilers. - - // rdp duration (orange) - draw_profiler_bar(0, 0, rdpDuration, 216, GPACK_RGBA5551(255, 120, 40, 1)); - // rsp duration (yellow) - draw_profiler_bar(0, 0, rspDuration, 216, GPACK_RGBA5551(255, 255, 40, 1)); - // vblank duration (red) - draw_profiler_bar(0, 0, vblank, 216, GPACK_RGBA5551(255, 40, 40, 1)); - - draw_reference_profiler_bars(); -} - -// Draw the Profiler per frame. Toggle the mode if the player presses L while this -// renderer is active. -void draw_profiler(void) { - if (gPlayer1Controller->buttonPressed & L_TRIG) { - gProfilerMode ^= 1; - } - - if (gProfilerMode == 0) { - draw_profiler_mode_0(); - } else { - draw_profiler_mode_1(); - } -} diff --git a/src/game/profiler.h b/src/game/profiler.h deleted file mode 100644 index 0bb66a58..00000000 --- a/src/game/profiler.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef PROFILER_H -#define PROFILER_H - -#include -#include - -#include "types.h" - -extern u64 osClockRate; - -struct ProfilerFrameData { - /* 0x00 */ s16 numSoundTimes; - /* 0x02 */ s16 numVblankTimes; - // gameTimes: - // 0: thread 5 start - // 1: level script execution - // 2: render - // 3: display lists - // 4: thread 4 end (0 terminated) - /* 0x08 */ OSTime gameTimes[5]; - // gfxTimes: - // 0: processors queued - // 1: rsp completed - // 2: rdp completed - /* 0x30 */ OSTime gfxTimes[3]; - /* 0x48 */ OSTime soundTimes[8]; - /* 0x88 */ OSTime vblankTimes[8]; -}; - -// thread event IDs -enum ProfilerGameEvent { - THREAD5_START, - LEVEL_SCRIPT_EXECUTE, - BEFORE_DISPLAY_LISTS, - AFTER_DISPLAY_LISTS, - THREAD5_END -}; - -enum ProfilerGfxEvent { - TASKS_QUEUED, - RSP_COMPLETE, - RDP_COMPLETE -}; - -void profiler_log_thread5_time(enum ProfilerGameEvent eventID); -void profiler_log_thread4_time(void); -void profiler_log_gfx_time(enum ProfilerGfxEvent eventID); -void profiler_log_vblank_time(void); -void draw_profiler(void); - -#endif // PROFILER_H diff --git a/src/game/sound_init.c b/src/game/sound_init.c index d8d50d2a..94b4c869 100644 --- a/src/game/sound_init.c +++ b/src/game/sound_init.c @@ -9,7 +9,6 @@ #include "main.h" #include "paintings.h" #include "print.h" -#include "profiler.h" #include "save_file.h" #include "seq_ids.h" #include "sm64.h" @@ -358,12 +357,10 @@ void thread4_sound(UNUSED void *arg) { #endif if (gResetTimer < 25) { struct SPTask *spTask; - profiler_log_thread4_time(); spTask = create_next_audio_frame_task(); if (spTask != NULL) { dispatch_audio_sptask(spTask); } - profiler_log_thread4_time(); #if PUPPYPRINT_DEBUG profiler_update(audioTime, lastTime); audioTime[perfIteration] -= dmaAudioTime[perfIteration]; From 501a0caec0311045afb6d9be0db6d7713be33b11 Mon Sep 17 00:00:00 2001 From: Fazana <52551480+FazanaJ@users.noreply.github.com> Date: Tue, 28 Sep 2021 18:03:24 +0100 Subject: [PATCH 5/6] Update Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f8d7885b..21bf3cfe 100644 --- a/Makefile +++ b/Makefile @@ -197,7 +197,7 @@ UNF ?= 0 $(eval $(call validate-option,UNF,0 1)) ifeq ($(UNF),1) DEFINES += UNF=1 - SRC_DIRS += src/usbOfast + SRC_DIRS += src/usb USE_DEBUG := 1 endif From 6bad22d98cd85285693e5e5d009ec0f8f19634a9 Mon Sep 17 00:00:00 2001 From: Fazana <52551480+FazanaJ@users.noreply.github.com> Date: Tue, 28 Sep 2021 18:44:57 +0100 Subject: [PATCH 6/6] Specific cflags --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 21bf3cfe..3ed89661 100644 --- a/Makefile +++ b/Makefile @@ -576,6 +576,9 @@ $(BUILD_DIR)/src/usb/usb.o: OPT_FLAGS := -O0 $(BUILD_DIR)/src/usb/usb.o: CFLAGS += -Wno-unused-variable -Wno-sign-compare -Wno-unused-function $(BUILD_DIR)/src/usb/debug.o: OPT_FLAGS := -O0 $(BUILD_DIR)/src/usb/debug.o: CFLAGS += -Wno-unused-parameter -Wno-maybe-uninitialized +$(BUILD_DIR)/src/engine/surface_collision.o: OPT_FLAGS := -Os +$(BUILD_DIR)/src/audio/*.o: OPT_FLAGS := -Os -fno-jump-tables +$(BUILD_DIR)/src/game/*.o: OPT_FLAGS := -Ofast ALL_DIRS := $(BUILD_DIR) $(addprefix $(BUILD_DIR)/,$(SRC_DIRS) asm/debug $(GODDARD_SRC_DIRS) $(LIBZ_SRC_DIRS) $(ULTRA_BIN_DIRS) $(BIN_DIRS) $(TEXTURE_DIRS) $(TEXT_DIRS) $(SOUND_SAMPLE_DIRS) $(addprefix levels/,$(LEVEL_DIRS)) rsp include) $(YAY0_DIR) $(addprefix $(YAY0_DIR)/,$(VERSION)) $(SOUND_BIN_DIR) $(SOUND_BIN_DIR)/sequences/$(VERSION) @@ -589,6 +592,7 @@ $(BUILD_DIR)/src/game/ingame_menu.o: $(BUILD_DIR)/include/text_strings.h $(BUILD_DIR)/src/game/puppycam2.o: $(BUILD_DIR)/include/text_strings.h + #==============================================================================# # Texture Generation # #==============================================================================#