From 0005bbbd6a91483467f58c8c79b59e7020c3ec52 Mon Sep 17 00:00:00 2001 From: arthurtilly <32559225+arthurtilly@users.noreply.github.com> Date: Mon, 22 Apr 2024 12:40:47 +1200 Subject: [PATCH] Save up to 130KB of RAM at literally zero cost (#786) --- src/engine/math_util.c | 16 ++++++++-------- src/engine/surface_collision.c | 28 ++++++++++++++-------------- src/engine/surface_load.c | 31 +++++++++++++++++++------------ src/engine/surface_load.h | 2 +- src/game/debug_box.c | 32 ++++++++++++++++---------------- 5 files changed, 58 insertions(+), 51 deletions(-) diff --git a/src/engine/math_util.c b/src/engine/math_util.c index bcaca282..cab62565 100644 --- a/src/engine/math_util.c +++ b/src/engine/math_util.c @@ -921,20 +921,20 @@ void find_surface_on_ray_cell(s32 cellX, s32 cellZ, Vec3f orig, Vec3f normalized if ((cellX >= 0) && (cellX <= (NUM_CELLS - 1)) && (cellZ >= 0) && (cellZ <= (NUM_CELLS - 1))) { // Iterate through each surface in this partition if ((normalized_dir[1] > -NEAR_ONE) && (flags & RAYCAST_FIND_CEIL)) { - find_surface_on_ray_list( gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS ].next, orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); - find_surface_on_ray_list(gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS ].next, orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); + find_surface_on_ray_list( gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS ], orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); + find_surface_on_ray_list(gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS ], orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); } if ((normalized_dir[1] < NEAR_ONE) && (flags & RAYCAST_FIND_FLOOR)) { - find_surface_on_ray_list( gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next, orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); - find_surface_on_ray_list(gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next, orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); + find_surface_on_ray_list( gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS], orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); + find_surface_on_ray_list(gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS], orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); } if (flags & RAYCAST_FIND_WALL) { - find_surface_on_ray_list( gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS ].next, orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); - find_surface_on_ray_list(gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS ].next, orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); + find_surface_on_ray_list( gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS ], orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); + find_surface_on_ray_list(gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS ], orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); } if (flags & RAYCAST_FIND_WATER) { - find_surface_on_ray_list( gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WATER ].next, orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); - find_surface_on_ray_list(gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WATER ].next, orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); + find_surface_on_ray_list( gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WATER ], orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); + find_surface_on_ray_list(gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WATER ], orig, normalized_dir, dir_length, hit_surface, hit_pos, max_length); } } } diff --git a/src/engine/surface_collision.c b/src/engine/surface_collision.c index 8b54ef8a..f87a386e 100644 --- a/src/engine/surface_collision.c +++ b/src/engine/surface_collision.c @@ -220,12 +220,12 @@ s32 find_wall_collisions(struct WallCollisionData *colData) { for (s32 cellZ = minCellZ; cellZ <= maxCellZ; cellZ++) { if (!(gCollisionFlags & COLLISION_FLAG_EXCLUDE_DYNAMIC)) { // Check for surfaces belonging to objects. - node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS].next; + node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS]; numCollisions += find_wall_collisions_from_list(node, colData); } // Check for surfaces that are a part of level geometry. - node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS].next; + node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS]; numCollisions += find_wall_collisions_from_list(node, colData); } } @@ -376,7 +376,7 @@ f32 find_ceil(f32 posX, f32 posY, f32 posZ, struct Surface **pceil) { if (includeDynamic) { // Check for surfaces belonging to objects. - surfaceList = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS].next; + surfaceList = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS]; dynamicCeil = find_ceil_from_list(surfaceList, x, y, z, &dynamicHeight); // In the next check, only check for ceilings lower than the previous check. @@ -384,7 +384,7 @@ f32 find_ceil(f32 posX, f32 posY, f32 posZ, struct Surface **pceil) { } // Check for surfaces that are a part of level geometry. - surfaceList = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS].next; + surfaceList = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS]; ceil = find_ceil_from_list(surfaceList, x, y, z, &height); // Use the lower ceiling. @@ -573,7 +573,7 @@ f32 unused_find_dynamic_floor(f32 xPos, f32 yPos, f32 zPos, struct Surface **pfl s32 cellX = GET_CELL_COORD(x); s32 cellZ = GET_CELL_COORD(z); - struct SurfaceNode *surfaceList = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next; + struct SurfaceNode *surfaceList = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS]; *pfloor = find_floor_from_list(surfaceList, x, y, z, &floorHeight); @@ -615,7 +615,7 @@ f32 find_floor(f32 xPos, f32 yPos, f32 zPos, struct Surface **pfloor) { if (includeDynamic) { // Check for surfaces belonging to objects. - surfaceList = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next; + surfaceList = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS]; dynamicFloor = find_floor_from_list(surfaceList, x, y, z, &dynamicHeight); // In the next check, only check for floors higher than the previous check. @@ -623,7 +623,7 @@ f32 find_floor(f32 xPos, f32 yPos, f32 zPos, struct Surface **pfloor) { } // Check for surfaces that are a part of level geometry. - surfaceList = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next; + surfaceList = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS]; floor = find_floor_from_list(surfaceList, x, y, z, &height); // Use the higher floor. @@ -690,7 +690,7 @@ f32 find_water_floor(s32 xPos, s32 yPos, s32 zPos, struct Surface **pfloor) { s32 cellZ = GET_CELL_COORD(z); // Check for surfaces that are a part of level geometry. - struct SurfaceNode *surfaceList = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WATER].next; + struct SurfaceNode *surfaceList = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WATER]; struct Surface *floor = find_water_floor_from_list(surfaceList, x, y, z, &height); if (floor == NULL) { @@ -856,22 +856,22 @@ void debug_surface_list_info(f32 xPos, f32 zPos) { s32 cellX = GET_CELL_COORD(xPos); s32 cellZ = GET_CELL_COORD(zPos); - list = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next; + list = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS]; numFloors += surface_list_length(list); - list = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next; + list = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS]; numFloors += surface_list_length(list); - list = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS].next; + list = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS]; numWalls += surface_list_length(list); - list = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS].next; + list = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS]; numWalls += surface_list_length(list); - list = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS].next; + list = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS]; numCeils += surface_list_length(list); - list = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS].next; + list = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS]; numCeils += surface_list_length(list); print_debug_top_down_mapinfo("area %x", cellZ * NUM_CELLS + cellX); diff --git a/src/engine/surface_load.c b/src/engine/surface_load.c index a68362d6..344fbc5f 100644 --- a/src/engine/surface_load.c +++ b/src/engine/surface_load.c @@ -94,10 +94,10 @@ static void clear_spatial_partition(SpatialPartitionCell *cells) { register s32 i = sqr(NUM_CELLS); while (i--) { - (*cells)[SPATIAL_PARTITION_FLOORS].next = NULL; - (*cells)[SPATIAL_PARTITION_CEILS].next = NULL; - (*cells)[SPATIAL_PARTITION_WALLS].next = NULL; - (*cells)[SPATIAL_PARTITION_WATER].next = NULL; + (*cells)[SPATIAL_PARTITION_FLOORS] = NULL; + (*cells)[SPATIAL_PARTITION_CEILS] = NULL; + (*cells)[SPATIAL_PARTITION_WALLS] = NULL; + (*cells)[SPATIAL_PARTITION_WATER] = NULL; cells++; } @@ -119,7 +119,7 @@ static void clear_static_surfaces(void) { * @param surface The surface to add */ static void add_surface_to_cell(s32 dynamic, s32 cellX, s32 cellZ, struct Surface *surface) { - struct SurfaceNode *list; + struct SurfaceNode **list; s32 priority; s32 sortDir = 1; // highest to lowest, then insertion order (water and floors) s32 listIndex; @@ -146,7 +146,7 @@ static void add_surface_to_cell(s32 dynamic, s32 cellX, s32 cellZ, struct Surfac if (sNumCellsUsed >= sizeof(sCellsUsed) / sizeof(struct CellCoords)) { sClearAllCells = TRUE; } else { - if (list->next == NULL) { + if (*list == NULL) { sCellsUsed[sNumCellsUsed].z = cellZ; sCellsUsed[sNumCellsUsed].x = cellX; sCellsUsed[sNumCellsUsed].partition = listIndex; @@ -157,19 +157,26 @@ static void add_surface_to_cell(s32 dynamic, s32 cellX, s32 cellZ, struct Surfac list = &gStaticSurfacePartition[cellZ][cellX][listIndex]; } + if (*list == NULL) { + *list = newNode; + return; + } + + struct SurfaceNode *curNode = *list; + // Loop until we find the appropriate place for the surface in the list. - while (list->next != NULL) { - priority = list->next->surface->upperY * sortDir; + while (curNode->next != NULL) { + priority = curNode->next->surface->upperY * sortDir; if (surfacePriority > priority) { break; } - list = list->next; + curNode = curNode->next; } - newNode->next = list->next; - list->next = newNode; + newNode->next = curNode->next; + curNode->next = newNode; } /** @@ -563,7 +570,7 @@ void clear_dynamic_surfaces(void) { clear_spatial_partition(&gDynamicSurfacePartition[0][0]); } else { for (u32 i = 0; i < sNumCellsUsed; i++) { - gDynamicSurfacePartition[sCellsUsed[i].z][sCellsUsed[i].x][sCellsUsed[i].partition].next = NULL; + gDynamicSurfacePartition[sCellsUsed[i].z][sCellsUsed[i].x][sCellsUsed[i].partition] = NULL; } } sNumCellsUsed = 0; diff --git a/src/engine/surface_load.h b/src/engine/surface_load.h index fcfc3c7f..52a20f6a 100644 --- a/src/engine/surface_load.h +++ b/src/engine/surface_load.h @@ -29,7 +29,7 @@ enum SpatialPartitions { NUM_SPATIAL_PARTITIONS }; -typedef struct SurfaceNode SpatialPartitionCell[NUM_SPATIAL_PARTITIONS]; +typedef struct SurfaceNode *SpatialPartitionCell[NUM_SPATIAL_PARTITIONS]; extern SpatialPartitionCell gStaticSurfacePartition[NUM_CELLS][NUM_CELLS]; extern SpatialPartitionCell gDynamicSurfacePartition[NUM_CELLS][NUM_CELLS]; diff --git a/src/game/debug_box.c b/src/game/debug_box.c index 9281625f..a8a44929 100644 --- a/src/game/debug_box.c +++ b/src/game/debug_box.c @@ -210,14 +210,14 @@ void iterate_surfaces_visual(s32 x, s32 z, Vtx *verts) { for (i = 0; i < (2 * NUM_SPATIAL_PARTITIONS); i++) { switch (i) { - case 0: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS ].next; colorRGB_copy(col, (ColorRGB)COLOR_RGB_GREEN ); break; - case 1: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS ].next; colorRGB_copy(col, (ColorRGB)COLOR_RGB_GREEN ); break; - case 2: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next; colorRGB_copy(col, (ColorRGB)COLOR_RGB_BLUE ); break; - case 3: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next; colorRGB_copy(col, (ColorRGB)COLOR_RGB_BLUE ); break; - case 4: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS ].next; colorRGB_copy(col, (ColorRGB)COLOR_RGB_RED ); break; - case 5: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS ].next; colorRGB_copy(col, (ColorRGB)COLOR_RGB_RED ); break; - case 6: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WATER ].next; colorRGB_copy(col, (ColorRGB)COLOR_RGB_YELLOW); break; - case 7: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WATER ].next; colorRGB_copy(col, (ColorRGB)COLOR_RGB_YELLOW); break; + case 0: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS ]; colorRGB_copy(col, (ColorRGB)COLOR_RGB_GREEN ); break; + case 1: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS ]; colorRGB_copy(col, (ColorRGB)COLOR_RGB_GREEN ); break; + case 2: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS]; colorRGB_copy(col, (ColorRGB)COLOR_RGB_BLUE ); break; + case 3: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS]; colorRGB_copy(col, (ColorRGB)COLOR_RGB_BLUE ); break; + case 4: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS ]; colorRGB_copy(col, (ColorRGB)COLOR_RGB_RED ); break; + case 5: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS ]; colorRGB_copy(col, (ColorRGB)COLOR_RGB_RED ); break; + case 6: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WATER ]; colorRGB_copy(col, (ColorRGB)COLOR_RGB_YELLOW); break; + case 7: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WATER ]; colorRGB_copy(col, (ColorRGB)COLOR_RGB_YELLOW); break; } while (node != NULL) { @@ -318,14 +318,14 @@ s32 iterate_surface_count(s32 x, s32 z) { for (i = 0; i < (2 * NUM_SPATIAL_PARTITIONS); i++) { switch (i) { - case 0: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS ].next; break; - case 1: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS ].next; break; - case 2: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next; break; - case 3: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS].next; break; - case 4: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS ].next; break; - case 5: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS ].next; break; - case 6: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WATER ].next; break; - case 7: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WATER ].next; break; + case 0: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS ]; break; + case 1: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WALLS ]; break; + case 2: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS]; break; + case 3: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_FLOORS]; break; + case 4: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS ]; break; + case 5: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_CEILS ]; break; + case 6: node = gDynamicSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WATER ]; break; + case 7: node = gStaticSurfacePartition[cellZ][cellX][SPATIAL_PARTITION_WATER ]; break; } while (node != NULL) {