From 7604ef9297f9cc789ce04a4cf6bc08a991b186bd Mon Sep 17 00:00:00 2001 From: PeachyPeachSM64 <72323920+PeachyPeachSM64@users.noreply.github.com> Date: Sun, 29 Mar 2026 20:05:29 +0200 Subject: [PATCH] check surface type and special object preset type in dynos collision validation --- data/dynos_bin_col.cpp | 132 ++++++++++++++++++++++++++++++----------- 1 file changed, 97 insertions(+), 35 deletions(-) diff --git a/data/dynos_bin_col.cpp b/data/dynos_bin_col.cpp index cd5a58e50..331cbb130 100644 --- a/data/dynos_bin_col.cpp +++ b/data/dynos_bin_col.cpp @@ -3,7 +3,9 @@ extern "C" { #include "include/surface_terrains.h" #include "include/level_misc_macros.h" +#include "include/special_presets.h" #include "include/special_preset_names.h" +#include "src/engine/surface_load.h" } // Free data pointers, but keep nodes and tokens intact @@ -34,12 +36,32 @@ struct CollisionValidationData { u32 vtxCount; u32 triAlloc; u32 triCount; + s16 surfaceType; u32 specialAlloc; u32 specialCount; u32 waterBoxAlloc; u32 waterBoxCount; }; +static u8 GetSpecialObjectType(u8 preset) { + for (s32 i = 0; i < ARRAY_COUNT(SpecialObjectPresets); ++i) { + if (SpecialObjectPresets[i].preset_id == preset) { + return SpecialObjectPresets[i].type; + } + } + return SPTYPE_UNKNOWN; +} + +static const char *GetCorrectSpecialObjectCommand(u8 presetType) { + switch (presetType) { + case SPTYPE_NO_YROT_OR_PARAMS: return "SPECIAL_OBJECT"; + case SPTYPE_YROT_NO_PARAMS: return "SPECIAL_OBJECT_WITH_YAW"; + case SPTYPE_PARAMS_AND_YROT: return "SPECIAL_OBJECT_WITH_YAW_AND_PARAM"; + case SPTYPE_DEF_PARAM_AND_YROT: return "SPECIAL_OBJECT_WITH_YAW"; + default: return ""; + } +} + static void ValidateColSectionChange(GfxData* aGfxData, struct CollisionValidationData& aColValData, u8 section) { if (aColValData.section == COL_SECTION_END) { PrintDataError("Found new col section after COL_END"); @@ -67,51 +89,70 @@ static void ValidateColInit(GfxData* aGfxData, struct CollisionValidationData& a ValidateColSectionChange(aGfxData, aColValData, COL_SECTION_VTX); } -static void ValidateColVertexInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0) { +static void ValidateColVertexInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 vertexCount) { if (strcmp(aColValData.lastSymbol, "COL_INIT") != 0) { PrintDataError("COL_VERTEX_INIT found outside of vertex section"); } - if (arg0 < 0) { - PrintDataError("COL_VERTEX_INIT with a negative count: %d", arg0); + if (vertexCount < 0) { + PrintDataError("COL_VERTEX_INIT with a negative count: %d", vertexCount); } - aColValData.vtxAlloc = arg0; + aColValData.vtxAlloc = vertexCount; aColValData.vtxCount = 0; } -static void ValidateColVertex(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2) { +static void ValidateColVertex(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 x, s16 y, s16 z) { if (aColValData.section != COL_SECTION_VTX) { PrintDataError("COL_VERTEX found outside of vertex section"); } aColValData.vtxCount++; } -static void ValidateColTriInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1) { - if (arg1 < 0) { - PrintDataError("COL_TRI_INIT with a negative count: %d", arg1); +static void ValidateColTriInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 surfaceType, s16 triangleCount) { + if (triangleCount < 0) { + PrintDataError("COL_TRI_INIT with a negative count: %d", triangleCount); } ValidateColSectionChange(aGfxData, aColValData, COL_SECTION_TRI); - aColValData.triAlloc = arg1; + aColValData.triAlloc = triangleCount; aColValData.triCount = 0; + aColValData.surfaceType = surfaceType; } -static void ValidateColTri(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2) { +static void ValidateColTri(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 vertex0, s16 vertex1, s16 vertex2) { if (aColValData.section != COL_SECTION_TRI) { PrintDataError("COL_TRI found outside of triangle section"); } - if (arg0 < 0 || arg0 > aColValData.vtxCount) { - PrintDataError("COL_TRI used vertex outside of known range for first param: %d", arg0); + if (surface_has_force(aColValData.surfaceType)) { + PrintDataError("COL_TRI cannot be used by surface types with a force parameter: %d (use COL_TRI_SPECIAL instead)", aColValData.surfaceType); } - if (arg1 < 0 || arg1 > aColValData.vtxCount) { - PrintDataError("COL_TRI used vertex outside of known range for second param: %d", arg1); + if (vertex0 < 0 || vertex0 > aColValData.vtxCount) { + PrintDataError("COL_TRI used vertex outside of known range for first param: %d", vertex0); } - if (arg2 < 0 || arg2 > aColValData.vtxCount) { - PrintDataError("COL_TRI used vertex outside of known range for third param: %d", arg2); + if (vertex1 < 0 || vertex1 > aColValData.vtxCount) { + PrintDataError("COL_TRI used vertex outside of known range for second param: %d", vertex1); + } + if (vertex2 < 0 || vertex2 > aColValData.vtxCount) { + PrintDataError("COL_TRI used vertex outside of known range for third param: %d", vertex2); } aColValData.triCount++; } -static void ValidateColTriSpecial(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2, s16 arg3) { - ValidateColTri(aGfxData, aColValData, arg0, arg1, arg2); +static void ValidateColTriSpecial(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 vertex0, s16 vertex1, s16 vertex2, s16 force) { + if (aColValData.section != COL_SECTION_TRI) { + PrintDataError("COL_TRI_SPECIAL found outside of triangle section"); + } + if (!surface_has_force(aColValData.surfaceType)) { + PrintDataError("COL_TRI_SPECIAL cannot be used by surface types with no force parameter: %d (use COL_TRI instead)", aColValData.surfaceType); + } + if (vertex0 < 0 || vertex0 > aColValData.vtxCount) { + PrintDataError("COL_TRI_SPECIAL used vertex outside of known range for first param: %d", vertex0); + } + if (vertex1 < 0 || vertex1 > aColValData.vtxCount) { + PrintDataError("COL_TRI_SPECIAL used vertex outside of known range for second param: %d", vertex1); + } + if (vertex2 < 0 || vertex2 > aColValData.vtxCount) { + PrintDataError("COL_TRI_SPECIAL used vertex outside of known range for third param: %d", vertex2); + } + aColValData.triCount++; } static void ValidateColStop(GfxData* aGfxData, struct CollisionValidationData& aColValData) { @@ -122,49 +163,70 @@ static void ValidateColEnd(GfxData* aGfxData, struct CollisionValidationData& aC ValidateColSectionChange(aGfxData, aColValData, COL_SECTION_END); } -static void ValidateColSpecialInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0) { - if (arg0 < 0) { - PrintDataError("COL_SPECIAL_INIT with a negative count: %d", arg0); +static void ValidateColSpecialInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 specialCount) { + if (specialCount < 0) { + PrintDataError("COL_SPECIAL_INIT with a negative count: %d", specialCount); } ValidateColSectionChange(aGfxData, aColValData, COL_SECTION_SPECIAL); - aColValData.specialAlloc = arg0; + aColValData.specialAlloc = specialCount; aColValData.specialCount = 0; } -static void ValidateColWaterBoxInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0) { - if (arg0 < 0) { - PrintDataError("COL_WATER_BOX_INIT with a negative count: %d", arg0); +static void ValidateColWaterBoxInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 waterBoxCount) { + if (waterBoxCount < 0) { + PrintDataError("COL_WATER_BOX_INIT with a negative count: %d", waterBoxCount); } ValidateColSectionChange(aGfxData, aColValData, COL_SECTION_WATER_BOX); - aColValData.waterBoxAlloc = arg0; + aColValData.waterBoxAlloc = waterBoxCount; aColValData.waterBoxCount = 0; } -static void ValidateColWaterBox(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2, s16 arg3, s16 arg4, s16 arg5) { +static void ValidateColWaterBox(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 id, s16 x1, s16 z1, s16 x2, s16 z2, s16 y) { if (aColValData.section != COL_SECTION_WATER_BOX) { PrintDataError("COL_WATER_BOX found outside of water box section"); } aColValData.waterBoxCount++; } -static void ValidateColSpecialObject(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2, s16 arg3) { +static void ValidateColSpecialObject(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 preset, s16 posX, s16 posY, s16 posZ) { if (aColValData.section != COL_SECTION_SPECIAL) { PrintDataError("SPECIAL_OBJECT found outside of special section"); } - aColValData.specialCount++; -} - -static void ValidateColSpecialObjectWithYaw(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2, s16 arg3, s16 arg4) { - if (aColValData.section != COL_SECTION_SPECIAL) { - PrintDataError("SPECIAL_OBJECT_WITH_YAW found outside of special section"); + u8 presetType = GetSpecialObjectType(preset); + if (presetType == SPTYPE_UNKNOWN) { + PrintDataError("SPECIAL_OBJECT has invalid preset: %d", preset); + } + if (presetType != SPTYPE_NO_YROT_OR_PARAMS) { + PrintDataError("SPECIAL_OBJECT cannot be used with preset: %d (use %s instead)", preset, GetCorrectSpecialObjectCommand(presetType)); } aColValData.specialCount++; } -static void ValidateColSpecialObjectWithYawAndParam(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2, s16 arg3, s16 arg4, s16 arg5) { +static void ValidateColSpecialObjectWithYaw(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 preset, s16 posX, s16 posY, s16 posZ, s16 yaw) { + if (aColValData.section != COL_SECTION_SPECIAL) { + PrintDataError("SPECIAL_OBJECT_WITH_YAW found outside of special section"); + } + u8 presetType = GetSpecialObjectType(preset); + if (presetType == SPTYPE_UNKNOWN) { + PrintDataError("SPECIAL_OBJECT_WITH_YAW has invalid preset: %d", preset); + } + if (presetType != SPTYPE_YROT_NO_PARAMS && presetType != SPTYPE_DEF_PARAM_AND_YROT) { + PrintDataError("SPECIAL_OBJECT_WITH_YAW cannot be used with preset: %d (use %s instead)", preset, GetCorrectSpecialObjectCommand(presetType)); + } + aColValData.specialCount++; +} + +static void ValidateColSpecialObjectWithYawAndParam(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 preset, s16 posX, s16 posY, s16 posZ, s16 yaw, s16 param) { if (aColValData.section != COL_SECTION_SPECIAL) { PrintDataError("SPECIAL_OBJECT_WITH_YAW_AND_PARAM found outside of special section"); } + u8 presetType = GetSpecialObjectType(preset); + if (presetType == SPTYPE_UNKNOWN) { + PrintDataError("SPECIAL_OBJECT_WITH_YAW_AND_PARAM has invalid preset: %d", preset); + } + if (presetType != SPTYPE_PARAMS_AND_YROT) { + PrintDataError("SPECIAL_OBJECT_WITH_YAW_AND_PARAM cannot be used with preset: %d (use %s instead)", preset, GetCorrectSpecialObjectCommand(presetType)); + } aColValData.specialCount++; }