diff --git a/levels/thi/areas/2/collision.inc.c b/levels/thi/areas/2/collision.inc.c index dce7d94a0..71f500740 100644 --- a/levels/thi/areas/2/collision.inc.c +++ b/levels/thi/areas/2/collision.inc.c @@ -355,10 +355,10 @@ const Collision thi_seg7_area_2_collision[] = { COL_VERTEX(-2457, -3788, -2457), COL_VERTEX(2458, -3788, 2458), COL_VERTEX(-2457, -3788, 2458), - COL_VERTEX(2335, -3788, 61), - COL_VERTEX(2335, -3788, -859), - COL_VERTEX(1690, -3788, -859), - COL_VERTEX(1690, -3788, 61), + COL_VERTEX(2335, -3789, 61), + COL_VERTEX(2335, -3789, -859), + COL_VERTEX(1690, -3789, -859), + COL_VERTEX(1690, -3789, 61), COL_VERTEX(1997, -921, 2458), COL_VERTEX(-1535, -921, -2457), COL_VERTEX(-2457, -921, -2457), diff --git a/src/boot/main.c b/src/boot/main.c index c4d5b9e6c..b22639b76 100644 --- a/src/boot/main.c +++ b/src/boot/main.c @@ -333,6 +333,33 @@ void check_cache_emulation() { __osRestoreInt(saved); } +/** + * Increment the first and last values of the stack. + * If they're different, that means an error has occured, so trigger a crash. +*/ +#ifdef DEBUG +void check_stack_validity(void) { + gIdleThreadStack[0]++; + gIdleThreadStack[THREAD1_STACK - 1]++; + assert(gIdleThreadStack[0] == gIdleThreadStack[THREAD1_STACK - 1], "Thread 1 stack overflow.") + gThread3Stack[0]++; + gThread3Stack[THREAD3_STACK - 1]++; + assert(gThread3Stack[0] == gThread3Stack[THREAD3_STACK - 1], "Thread 3 stack overflow.") + gThread4Stack[0]++; + gThread4Stack[THREAD4_STACK - 1]++; + assert(gThread4Stack[0] == gThread4Stack[THREAD4_STACK - 1], "Thread 4 stack overflow.") + gThread5Stack[0]++; + gThread5Stack[THREAD5_STACK - 1]++; + assert(gThread5Stack[0] == gThread5Stack[THREAD5_STACK - 1], "Thread 5 stack overflow.") +#if ENABLE_RUMBLE + gThread6Stack[0]++; + gThread6Stack[THREAD6_STACK - 1]++; + assert(gThread6Stack[0] == gThread6Stack[THREAD6_STACK - 1], "Thread 6 stack overflow.") +#endif +} +#endif + + extern void crash_screen_init(void); extern OSViMode VI; void thread3_main(UNUSED void *arg) { @@ -376,16 +403,33 @@ void thread3_main(UNUSED void *arg) { gIsConsole = TRUE; gBorderHeight = BORDER_HEIGHT_CONSOLE; } +#ifdef DEBUG + gIdleThreadStack[0] = 0; + gIdleThreadStack[THREAD1_STACK - 1] = 0; + gThread3Stack[0] = 0; + gThread3Stack[THREAD3_STACK - 1] = 0; + gThread4Stack[0] = 0; + gThread4Stack[THREAD4_STACK - 1] = 0; + gThread5Stack[0] = 0; + gThread5Stack[THREAD5_STACK - 1] = 0; +#if ENABLE_RUMBLE + gThread6Stack[0] = 0; + gThread6Stack[THREAD6_STACK - 1] = 0; +#endif +#endif - create_thread(&gSoundThread, THREAD_4_SOUND, thread4_sound, NULL, gThread4Stack + 0x2000, 20); + create_thread(&gSoundThread, THREAD_4_SOUND, thread4_sound, NULL, gThread4Stack + THREAD4_STACK, 20); osStartThread(&gSoundThread); - create_thread(&gGameLoopThread, THREAD_5_GAME_LOOP, thread5_game_loop, NULL, gThread5Stack + 0x2000, 10); + create_thread(&gGameLoopThread, THREAD_5_GAME_LOOP, thread5_game_loop, NULL, gThread5Stack + THREAD5_STACK, 10); osStartThread(&gGameLoopThread); while (TRUE) { OSMesg msg; osRecvMesg(&gIntrMesgQueue, &msg, OS_MESG_BLOCK); +#ifdef DEBUG + check_stack_validity(); +#endif switch ((uintptr_t) msg) { case MESG_VI_VBLANK: handle_vblank(); @@ -526,7 +570,7 @@ void thread1_idle(UNUSED void *arg) { osViSetSpecialFeatures(OS_VI_DITHER_FILTER_ON); osViSetSpecialFeatures(OS_VI_GAMMA_OFF); osCreatePiManager(OS_PRIORITY_PIMGR, &gPIMesgQueue, gPIMesgBuf, ARRAY_COUNT(gPIMesgBuf)); - create_thread(&gMainThread, THREAD_3_MAIN, thread3_main, NULL, gThread3Stack + 0x2000, 100); + create_thread(&gMainThread, THREAD_3_MAIN, thread3_main, NULL, gThread3Stack + THREAD3_STACK, 100); osStartThread(&gMainThread); osSetThreadPri(NULL, 0); @@ -564,6 +608,6 @@ void main_func(void) { #ifdef ISVPRINT osInitialize_fakeisv(); #endif - create_thread(&gIdleThread, THREAD_1_IDLE, thread1_idle, NULL, gIdleThreadStack + 0x800, 100); + create_thread(&gIdleThread, THREAD_1_IDLE, thread1_idle, NULL, gIdleThreadStack + THREAD1_STACK, 100); osStartThread(&gIdleThread); } diff --git a/src/buffers/buffers.c b/src/buffers/buffers.c index 5d382702f..5a8eefa2d 100644 --- a/src/buffers/buffers.c +++ b/src/buffers/buffers.c @@ -12,12 +12,12 @@ ALIGNED8 u8 gDecompressionHeap[0xD000]; ALIGNED16 u8 gAudioHeap[DOUBLE_SIZE_ON_64_BIT(AUDIO_HEAP_SIZE)]; -ALIGNED8 u8 gIdleThreadStack[0x800]; -ALIGNED8 u8 gThread3Stack[0x2000]; -ALIGNED8 u8 gThread4Stack[0x2000]; -ALIGNED8 u8 gThread5Stack[0x2000]; +ALIGNED8 u8 gIdleThreadStack[THREAD1_STACK]; +ALIGNED8 u8 gThread3Stack[THREAD3_STACK]; +ALIGNED8 u8 gThread4Stack[THREAD4_STACK]; +ALIGNED8 u8 gThread5Stack[THREAD5_STACK]; #if ENABLE_RUMBLE -ALIGNED8 u8 gThread6Stack[0x2000]; +ALIGNED8 u8 gThread6Stack[THREAD6_STACK]; #endif // 0x400 bytes #if UNF diff --git a/src/buffers/buffers.h b/src/buffers/buffers.h index f063a023c..82b54b4eb 100644 --- a/src/buffers/buffers.h +++ b/src/buffers/buffers.h @@ -8,16 +8,23 @@ #include "game/game_init.h" #include "config.h" +#define THREAD1_STACK 0x100 +#define THREAD2_STACK 0x800 +#define THREAD3_STACK 0x200 +#define THREAD4_STACK 0x2000 +#define THREAD5_STACK 0x2000 +#define THREAD6_STACK 0x400 + extern u8 gDecompressionHeap[]; extern u8 gAudioHeap[]; -extern u8 gIdleThreadStack[]; -extern u8 gThread3Stack[]; -extern u8 gThread4Stack[]; -extern u8 gThread5Stack[]; +extern u8 gIdleThreadStack[THREAD1_STACK]; +extern u8 gThread3Stack[THREAD3_STACK]; +extern u8 gThread4Stack[THREAD4_STACK]; +extern u8 gThread5Stack[THREAD5_STACK]; #if ENABLE_RUMBLE -extern u8 gThread6Stack[]; +extern u8 gThread6Stack[THREAD6_STACK]; #endif extern u8 gGfxSPTaskYieldBuffer[]; diff --git a/src/buffers/gfx_output_buffer.c b/src/buffers/gfx_output_buffer.c index 770c4725e..08675bb10 100644 --- a/src/buffers/gfx_output_buffer.c +++ b/src/buffers/gfx_output_buffer.c @@ -1,4 +1,4 @@ #include #include "gfx_output_buffer.h" -u64 gGfxSPTaskOutputBuffer[0x2fc0]; +u64 gGfxSPTaskOutputBuffer[0x2000]; diff --git a/src/buffers/gfx_output_buffer.h b/src/buffers/gfx_output_buffer.h index 8f6ded2f9..abf08afb6 100644 --- a/src/buffers/gfx_output_buffer.h +++ b/src/buffers/gfx_output_buffer.h @@ -3,6 +3,6 @@ #include -extern u64 gGfxSPTaskOutputBuffer[0x2fc0]; +extern u64 gGfxSPTaskOutputBuffer[0x2000]; #endif // GFX_OUTPUT_BUFFER_H diff --git a/src/engine/surface_load.c b/src/engine/surface_load.c index aca97f52a..e4a505b9e 100644 --- a/src/engine/surface_load.c +++ b/src/engine/surface_load.c @@ -119,7 +119,6 @@ static void clear_static_surfaces(void) { */ static void add_surface_to_cell(s32 dynamic, s32 cellX, s32 cellZ, struct Surface *surface) { struct SurfaceNode *list; - s32 priority; s32 sortDir = 1; // highest to lowest, then insertion order (water and floors) s32 listIndex; @@ -135,7 +134,6 @@ static void add_surface_to_cell(s32 dynamic, s32 cellX, s32 cellZ, struct Surfac sortDir = 0; // insertion order } - s32 surfacePriority = surface->upperY * sortDir; struct SurfaceNode *newNode = alloc_surface_node(dynamic); newNode->surface = surface; @@ -157,14 +155,18 @@ static void add_surface_to_cell(s32 dynamic, s32 cellX, s32 cellZ, struct Surfac } // Loop until we find the appropriate place for the surface in the list. - while (list->next != NULL) { - priority = list->next->surface->upperY * sortDir; + if (listIndex == SPATIAL_PARTITION_WATER) { + s32 surfacePriority = surface->upperY * sortDir; + s32 priority; + while (list->next != NULL) { + priority = list->next->surface->upperY * sortDir; - if (surfacePriority > priority) { - break; + if (surfacePriority > priority) { + break; + } + + list = list->next; } - - list = list->next; } newNode->next = list->next; @@ -269,7 +271,15 @@ static struct Surface *read_surface_data(TerrainData *vertexData, TerrainData ** find_vector_perpendicular_to_plane(n, v[0], v[1], v[2]); - vec3f_normalize(n); + f32 mag = (sqr(n[0]) + sqr(n[1]) + sqr(n[2])); + // This will never need to be run for custom levels because Fast64 does this step before exporting. +#ifdef ENABLE_VANILLA_LEVEL_SPECIFIC_CHECKS + if (mag < NEAR_ZERO) { + return NULL; + } +#endif + mag = 1.0f / sqrtf(mag); + vec3_mul_val(n, mag); struct Surface *surface = alloc_surface(dynamic); diff --git a/src/game/crash_screen.c b/src/game/crash_screen.c index 0913e6bae..3690b32f8 100644 --- a/src/game/crash_screen.c +++ b/src/game/crash_screen.c @@ -11,6 +11,7 @@ #include "main.h" #include "debug.h" #include "rumble_init.h" +#include "buffers/buffers.h" #include "sm64.h" @@ -80,7 +81,7 @@ extern far char *find_function_in_stack(u32 *sp); struct { OSThread thread; - u64 stack[0x800 / sizeof(u64)]; + u64 stack[THREAD2_STACK / sizeof(u64)]; OSMesgQueue mesgQueue; OSMesg mesg; u16 *framebuffer; diff --git a/src/game/rumble_init.c b/src/game/rumble_init.c index b164798e0..2ebf75d0e 100644 --- a/src/game/rumble_init.c +++ b/src/game/rumble_init.c @@ -261,7 +261,7 @@ void cancel_rumble(void) { void create_thread_6(void) { osCreateMesgQueue(&gRumbleThreadVIMesgQueue, gRumbleThreadVIMesgBuf, 1); - osCreateThread(&gRumblePakThread, THREAD_6_RUMBLE, thread6_rumble_loop, NULL, gThread6Stack + 0x2000, 30); + osCreateThread(&gRumblePakThread, THREAD_6_RUMBLE, thread6_rumble_loop, NULL, gThread6Stack + 0x400, 30); osStartThread(&gRumblePakThread); }