mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2025-10-30 08:01:01 +00:00
They dug me out of my grave and told me `configSkipPackGeneration`. My heart sank. This feature would have been fine if it was off by default and if it wasn't then people caught it before the version was officially released and the option was promptly disabled without a massive pool of people having this option turned on by default. So I will say, Coolio wasn't really in the wrong by adding this, it should have never been changed to be on by default.
722 lines
29 KiB
C++
722 lines
29 KiB
C++
#include "dynos.cpp.h"
|
|
|
|
extern "C" {
|
|
#include "include/surface_terrains.h"
|
|
#include "include/level_misc_macros.h"
|
|
#include "include/special_preset_names.h"
|
|
}
|
|
|
|
// Free data pointers, but keep nodes and tokens intact
|
|
// Delete nodes generated from GfxDynCmds
|
|
template <typename T>
|
|
void ClearGfxDataNodes(DataNodes<T> &aDataNodes) {
|
|
for (s32 i = aDataNodes.Count(); i != 0; --i) {
|
|
Delete(aDataNodes[i - 1]->mData);
|
|
}
|
|
}
|
|
|
|
////////////////
|
|
// Validation //
|
|
////////////////
|
|
|
|
#define COL_SECTION_UNKNOWN 0
|
|
#define COL_SECTION_VTX 1
|
|
#define COL_SECTION_TRI 2
|
|
#define COL_SECTION_SPECIAL 3
|
|
#define COL_SECTION_WATER_BOX 4
|
|
#define COL_SECTION_END 5
|
|
|
|
struct CollisionValidationData {
|
|
u32 tokenIndex;
|
|
u8 section;
|
|
const char* lastSymbol;
|
|
u32 vtxAlloc;
|
|
u32 vtxCount;
|
|
u32 triAlloc;
|
|
u32 triCount;
|
|
u32 specialAlloc;
|
|
u32 specialCount;
|
|
u32 waterBoxAlloc;
|
|
u32 waterBoxCount;
|
|
};
|
|
|
|
static void ValidateColSectionChange(GfxData* aGfxData, struct CollisionValidationData& aColValData, u8 section) {
|
|
if (aColValData.section == COL_SECTION_END) {
|
|
PrintDataError("Found new col section after COL_END");
|
|
}
|
|
|
|
if (aColValData.section != section) {
|
|
if (aColValData.vtxAlloc != aColValData.vtxCount) {
|
|
PrintDataError("Improper vtx count found in section. Allocated: %u, Defined: %u", aColValData.vtxAlloc, aColValData.vtxCount);
|
|
}
|
|
if (aColValData.triAlloc != aColValData.triCount) {
|
|
PrintDataError("Improper triangle count found in section. Allocated: %u, Defined: %u", aColValData.triAlloc, aColValData.triCount);
|
|
}
|
|
if (aColValData.specialAlloc != aColValData.specialCount) {
|
|
PrintDataError("Improper special count found in section. Allocated: %u, Defined: %u", aColValData.triAlloc, aColValData.triCount);
|
|
}
|
|
if (aColValData.waterBoxAlloc != aColValData.waterBoxCount) {
|
|
PrintDataError("Improper water box count found in section. Allocated: %u, Defined: %u", aColValData.waterBoxAlloc, aColValData.waterBoxCount);
|
|
}
|
|
}
|
|
|
|
aColValData.section = section;
|
|
}
|
|
|
|
static void ValidateColInit(GfxData* aGfxData, struct CollisionValidationData& aColValData) {
|
|
if (aColValData.tokenIndex != 0) {
|
|
PrintDataError("COL_INIT found after the first token");
|
|
}
|
|
ValidateColSectionChange(aGfxData, aColValData, COL_SECTION_VTX);
|
|
}
|
|
|
|
static void ValidateColVertexInit(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0) {
|
|
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);
|
|
}
|
|
aColValData.vtxAlloc = arg0;
|
|
aColValData.vtxCount = 0;
|
|
}
|
|
|
|
static void ValidateColVertex(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2) {
|
|
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);
|
|
}
|
|
ValidateColSectionChange(aGfxData, aColValData, COL_SECTION_TRI);
|
|
aColValData.triAlloc = arg1;
|
|
aColValData.triCount = 0;
|
|
}
|
|
|
|
static void ValidateColTri(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2) {
|
|
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 (arg1 < 0 || arg1 > aColValData.vtxCount) {
|
|
PrintDataError("COL_TRI used vertex outside of known range for second param: %d", arg1);
|
|
}
|
|
if (arg2 < 0 || arg2 > aColValData.vtxCount) {
|
|
PrintDataError("COL_TRI used vertex outside of known range for third param: %d", arg2);
|
|
}
|
|
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 ValidateColStop(GfxData* aGfxData, struct CollisionValidationData& aColValData) {
|
|
ValidateColSectionChange(aGfxData, aColValData, COL_SECTION_UNKNOWN);
|
|
}
|
|
|
|
static void ValidateColEnd(GfxData* aGfxData, struct CollisionValidationData& aColValData) {
|
|
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);
|
|
}
|
|
ValidateColSectionChange(aGfxData, aColValData, COL_SECTION_SPECIAL);
|
|
aColValData.specialAlloc = arg0;
|
|
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);
|
|
}
|
|
ValidateColSectionChange(aGfxData, aColValData, COL_SECTION_WATER_BOX);
|
|
aColValData.waterBoxAlloc = arg0;
|
|
aColValData.waterBoxCount = 0;
|
|
}
|
|
|
|
static void ValidateColWaterBox(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2, s16 arg3, s16 arg4, s16 arg5) {
|
|
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) {
|
|
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");
|
|
}
|
|
aColValData.specialCount++;
|
|
}
|
|
|
|
static void ValidateColSpecialObjectWithYawAndParam(GfxData* aGfxData, struct CollisionValidationData& aColValData, s16 arg0, s16 arg1, s16 arg2, s16 arg3, s16 arg4, s16 arg5) {
|
|
if (aColValData.section != COL_SECTION_SPECIAL) {
|
|
PrintDataError("SPECIAL_OBJECT_WITH_YAW_AND_PARAM found outside of special section");
|
|
}
|
|
aColValData.specialCount++;
|
|
}
|
|
|
|
/////////////
|
|
// Parsing //
|
|
/////////////
|
|
|
|
#define COLLISION_SIZE_PER_TOKEN 4
|
|
|
|
#define col_constant(x) if (_Arg == #x) { return (s16) (x); }
|
|
|
|
static s64 DynOS_Col_ParseConstants(const String& _Arg, bool* found) {
|
|
*found = true;
|
|
|
|
// Surface constants
|
|
col_constant(SURFACE_DEFAULT);
|
|
col_constant(SURFACE_BURNING);
|
|
col_constant(SURFACE_RAYCAST);
|
|
col_constant(SURFACE_0004);
|
|
col_constant(SURFACE_HANGABLE);
|
|
col_constant(SURFACE_SLOW);
|
|
col_constant(SURFACE_DEATH_PLANE);
|
|
col_constant(SURFACE_CLOSE_CAMERA);
|
|
col_constant(SURFACE_WATER);
|
|
col_constant(SURFACE_FLOWING_WATER);
|
|
col_constant(SURFACE_INTANGIBLE);
|
|
col_constant(SURFACE_VERY_SLIPPERY);
|
|
col_constant(SURFACE_SLIPPERY);
|
|
col_constant(SURFACE_NOT_SLIPPERY);
|
|
col_constant(SURFACE_TTM_VINES);
|
|
col_constant(SURFACE_MGR_MUSIC);
|
|
col_constant(SURFACE_INSTANT_WARP_1B);
|
|
col_constant(SURFACE_INSTANT_WARP_1C);
|
|
col_constant(SURFACE_INSTANT_WARP_1D);
|
|
col_constant(SURFACE_INSTANT_WARP_1E);
|
|
col_constant(SURFACE_SHALLOW_QUICKSAND);
|
|
col_constant(SURFACE_DEEP_QUICKSAND);
|
|
col_constant(SURFACE_INSTANT_QUICKSAND);
|
|
col_constant(SURFACE_DEEP_MOVING_QUICKSAND);
|
|
col_constant(SURFACE_SHALLOW_MOVING_QUICKSAND);
|
|
col_constant(SURFACE_QUICKSAND);
|
|
col_constant(SURFACE_MOVING_QUICKSAND);
|
|
col_constant(SURFACE_WALL_MISC);
|
|
col_constant(SURFACE_NOISE_DEFAULT);
|
|
col_constant(SURFACE_NOISE_SLIPPERY);
|
|
col_constant(SURFACE_HORIZONTAL_WIND);
|
|
col_constant(SURFACE_INSTANT_MOVING_QUICKSAND);
|
|
col_constant(SURFACE_ICE);
|
|
col_constant(SURFACE_LOOK_UP_WARP);
|
|
col_constant(SURFACE_HARD);
|
|
col_constant(SURFACE_WARP);
|
|
col_constant(SURFACE_TIMER_START);
|
|
col_constant(SURFACE_TIMER_END);
|
|
col_constant(SURFACE_HARD_SLIPPERY);
|
|
col_constant(SURFACE_HARD_VERY_SLIPPERY);
|
|
col_constant(SURFACE_HARD_NOT_SLIPPERY);
|
|
col_constant(SURFACE_VERTICAL_WIND);
|
|
col_constant(SURFACE_BOSS_FIGHT_CAMERA);
|
|
col_constant(SURFACE_CAMERA_FREE_ROAM);
|
|
col_constant(SURFACE_THI3_WALLKICK);
|
|
col_constant(SURFACE_CAMERA_8_DIR);
|
|
col_constant(SURFACE_CAMERA_MIDDLE);
|
|
col_constant(SURFACE_CAMERA_ROTATE_RIGHT);
|
|
col_constant(SURFACE_CAMERA_ROTATE_LEFT);
|
|
col_constant(SURFACE_CAMERA_BOUNDARY);
|
|
col_constant(SURFACE_NOISE_VERY_SLIPPERY_73);
|
|
col_constant(SURFACE_NOISE_VERY_SLIPPERY_74);
|
|
col_constant(SURFACE_NOISE_VERY_SLIPPERY);
|
|
col_constant(SURFACE_NO_CAM_COLLISION);
|
|
col_constant(SURFACE_NO_CAM_COLLISION_77);
|
|
col_constant(SURFACE_NO_CAM_COL_VERY_SLIPPERY);
|
|
col_constant(SURFACE_NO_CAM_COL_SLIPPERY);
|
|
col_constant(SURFACE_SWITCH);
|
|
col_constant(SURFACE_VANISH_CAP_WALLS);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_A6);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_A7);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_A8);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_A9);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_AA);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_AB);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_AC);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_AD);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_AE);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_AF);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_B0);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_B1);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_B2);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_B3);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_B4);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_B5);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_B6);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_B7);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_B8);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_B9);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_BA);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_BB);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_BC);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_BD);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_BE);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_BF);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_C0);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_C1);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_C2);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_C3);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_C4);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_C5);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_C6);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_C7);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_C8);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_C9);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_CA);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_CB);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_CC);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_CD);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_CE);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_CF);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_D0);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_D1);
|
|
col_constant(SURFACE_PAINTING_WOBBLE_D2);
|
|
col_constant(SURFACE_PAINTING_WARP_D3);
|
|
col_constant(SURFACE_PAINTING_WARP_D4);
|
|
col_constant(SURFACE_PAINTING_WARP_D5);
|
|
col_constant(SURFACE_PAINTING_WARP_D6);
|
|
col_constant(SURFACE_PAINTING_WARP_D7);
|
|
col_constant(SURFACE_PAINTING_WARP_D8);
|
|
col_constant(SURFACE_PAINTING_WARP_D9);
|
|
col_constant(SURFACE_PAINTING_WARP_DA);
|
|
col_constant(SURFACE_PAINTING_WARP_DB);
|
|
col_constant(SURFACE_PAINTING_WARP_DC);
|
|
col_constant(SURFACE_PAINTING_WARP_DD);
|
|
col_constant(SURFACE_PAINTING_WARP_DE);
|
|
col_constant(SURFACE_PAINTING_WARP_DF);
|
|
col_constant(SURFACE_PAINTING_WARP_E0);
|
|
col_constant(SURFACE_PAINTING_WARP_E1);
|
|
col_constant(SURFACE_PAINTING_WARP_E2);
|
|
col_constant(SURFACE_PAINTING_WARP_E3);
|
|
col_constant(SURFACE_PAINTING_WARP_E4);
|
|
col_constant(SURFACE_PAINTING_WARP_E5);
|
|
col_constant(SURFACE_PAINTING_WARP_E6);
|
|
col_constant(SURFACE_PAINTING_WARP_E7);
|
|
col_constant(SURFACE_PAINTING_WARP_E8);
|
|
col_constant(SURFACE_PAINTING_WARP_E9);
|
|
col_constant(SURFACE_PAINTING_WARP_EA);
|
|
col_constant(SURFACE_PAINTING_WARP_EB);
|
|
col_constant(SURFACE_PAINTING_WARP_EC);
|
|
col_constant(SURFACE_PAINTING_WARP_ED);
|
|
col_constant(SURFACE_PAINTING_WARP_EE);
|
|
col_constant(SURFACE_PAINTING_WARP_EF);
|
|
col_constant(SURFACE_PAINTING_WARP_F0);
|
|
col_constant(SURFACE_PAINTING_WARP_F1);
|
|
col_constant(SURFACE_PAINTING_WARP_F2);
|
|
col_constant(SURFACE_PAINTING_WARP_F3);
|
|
col_constant(SURFACE_TTC_PAINTING_1);
|
|
col_constant(SURFACE_TTC_PAINTING_2);
|
|
col_constant(SURFACE_TTC_PAINTING_3);
|
|
col_constant(SURFACE_PAINTING_WARP_F7);
|
|
col_constant(SURFACE_PAINTING_WARP_F8);
|
|
col_constant(SURFACE_PAINTING_WARP_F9);
|
|
col_constant(SURFACE_PAINTING_WARP_FA);
|
|
col_constant(SURFACE_PAINTING_WARP_FB);
|
|
col_constant(SURFACE_PAINTING_WARP_FC);
|
|
col_constant(SURFACE_WOBBLING_WARP);
|
|
col_constant(SURFACE_TRAPDOOR);
|
|
|
|
// Surface class constants
|
|
col_constant(SURFACE_CLASS_DEFAULT);
|
|
col_constant(SURFACE_CLASS_VERY_SLIPPERY);
|
|
col_constant(SURFACE_CLASS_SLIPPERY);
|
|
col_constant(SURFACE_CLASS_NOT_SLIPPERY);
|
|
|
|
// Surface flag constants
|
|
col_constant(SURFACE_FLAG_DYNAMIC);
|
|
col_constant(SURFACE_FLAG_NO_CAM_COLLISION);
|
|
col_constant(SURFACE_FLAG_X_PROJECTION);
|
|
|
|
// Specials
|
|
col_constant(special_null_start);
|
|
col_constant(special_yellow_coin);
|
|
col_constant(special_yellow_coin_2);
|
|
col_constant(special_unknown_3);
|
|
col_constant(special_boo);
|
|
col_constant(special_unknown_5);
|
|
col_constant(special_lll_moving_octagonal_mesh_platform);
|
|
col_constant(special_snow_ball);
|
|
col_constant(special_lll_drawbridge_spawner);
|
|
col_constant(special_empty_9);
|
|
col_constant(special_lll_rotating_block_with_fire_bars);
|
|
col_constant(special_lll_floating_wood_bridge);
|
|
col_constant(special_tumbling_platform);
|
|
col_constant(special_lll_rotating_hexagonal_ring);
|
|
col_constant(special_lll_sinking_rectangular_platform);
|
|
col_constant(special_lll_sinking_square_platforms);
|
|
col_constant(special_lll_tilting_square_platform);
|
|
col_constant(special_lll_bowser_puzzle);
|
|
col_constant(special_mr_i);
|
|
col_constant(special_small_bully);
|
|
col_constant(special_big_bully);
|
|
col_constant(special_empty_21);
|
|
col_constant(special_empty_22);
|
|
col_constant(special_empty_23);
|
|
col_constant(special_empty_24);
|
|
col_constant(special_empty_25);
|
|
col_constant(special_moving_blue_coin);
|
|
col_constant(special_jrb_chest);
|
|
col_constant(special_water_ring);
|
|
col_constant(special_mine);
|
|
col_constant(special_empty_30);
|
|
col_constant(special_empty_31);
|
|
col_constant(special_butterfly);
|
|
col_constant(special_bowser);
|
|
col_constant(special_wf_rotating_wooden_platform);
|
|
col_constant(special_small_bomp);
|
|
col_constant(special_wf_sliding_platform);
|
|
col_constant(special_tower_platform_group);
|
|
col_constant(special_rotating_counter_clockwise);
|
|
col_constant(special_wf_tumbling_bridge);
|
|
col_constant(special_large_bomp);
|
|
col_constant(special_level_geo_03);
|
|
col_constant(special_level_geo_04);
|
|
col_constant(special_level_geo_05);
|
|
col_constant(special_level_geo_06);
|
|
col_constant(special_level_geo_07);
|
|
col_constant(special_level_geo_08);
|
|
col_constant(special_level_geo_09);
|
|
col_constant(special_level_geo_0A);
|
|
col_constant(special_level_geo_0B);
|
|
col_constant(special_level_geo_0C);
|
|
col_constant(special_level_geo_0D);
|
|
col_constant(special_level_geo_0E);
|
|
col_constant(special_level_geo_0F);
|
|
col_constant(special_level_geo_10);
|
|
col_constant(special_level_geo_11);
|
|
col_constant(special_level_geo_12);
|
|
col_constant(special_level_geo_13);
|
|
col_constant(special_level_geo_14);
|
|
col_constant(special_level_geo_15);
|
|
col_constant(special_level_geo_16);
|
|
col_constant(special_bubble_tree);
|
|
col_constant(special_spiky_tree);
|
|
col_constant(special_snow_tree);
|
|
col_constant(special_unknown_tree);
|
|
col_constant(special_palm_tree);
|
|
col_constant(special_wooden_door);
|
|
col_constant(special_haunted_door);
|
|
col_constant(special_unknown_door);
|
|
col_constant(special_metal_door);
|
|
col_constant(special_hmc_door);
|
|
col_constant(special_unknown2_door);
|
|
col_constant(special_wooden_door_warp);
|
|
col_constant(special_unknown1_door_warp);
|
|
col_constant(special_metal_door_warp);
|
|
col_constant(special_unknown2_door_warp);
|
|
col_constant(special_unknown3_door_warp);
|
|
col_constant(special_castle_door_warp);
|
|
col_constant(special_castle_door);
|
|
col_constant(special_0stars_door);
|
|
col_constant(special_1star_door);
|
|
col_constant(special_3star_door);
|
|
col_constant(special_key_door);
|
|
col_constant(special_null_end);
|
|
|
|
*found = false;
|
|
return 0;
|
|
}
|
|
|
|
static s16 ParseColSymbolArg(GfxData* aGfxData, DataNode<Collision>* aNode, u64& aTokenIndex) {
|
|
const String& _Arg = aNode->mTokens[aTokenIndex++];
|
|
|
|
// Integers
|
|
bool integerFound = false;
|
|
s64 integerValue = DynOS_Misc_ParseInteger(_Arg, &integerFound);
|
|
if (integerFound) {
|
|
return integerValue;
|
|
}
|
|
|
|
// Constants
|
|
bool constantFound = false;
|
|
s64 constantValue = DynOS_Col_ParseConstants(_Arg, &constantFound);
|
|
if (constantFound) {
|
|
return constantValue;
|
|
}
|
|
|
|
// Recursive descent parsing
|
|
bool rdSuccess = false;
|
|
s64 rdValue = DynOS_RecursiveDescent_Parse(_Arg.begin(), &rdSuccess, DynOS_Col_ParseConstants);
|
|
if (rdSuccess) {
|
|
return rdValue;
|
|
}
|
|
|
|
// Unknown
|
|
PrintDataError(" ERROR: Unknown col arg: %s", _Arg.begin());
|
|
return 0;
|
|
}
|
|
|
|
#define col_symbol_0(symb, validate) \
|
|
if (_Symbol == #symb) { \
|
|
validate(aGfxData, aColValData); \
|
|
aColValData.lastSymbol = _Symbol.begin(); \
|
|
Collision _Cl[] = { symb() }; \
|
|
memcpy(aHead, _Cl, sizeof(_Cl)); \
|
|
aHead += (sizeof(_Cl) / sizeof(_Cl[0])); \
|
|
return; \
|
|
}
|
|
|
|
#define col_symbol_1(symb, validate) \
|
|
if (_Symbol == #symb) { \
|
|
s16 _Arg0 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
validate(aGfxData, aColValData, _Arg0); \
|
|
aColValData.lastSymbol = _Symbol.begin(); \
|
|
Collision _Cl[] = { symb(_Arg0) }; \
|
|
memcpy(aHead, _Cl, sizeof(_Cl)); \
|
|
aHead += (sizeof(_Cl) / sizeof(_Cl[0])); \
|
|
return; \
|
|
}
|
|
|
|
#define col_symbol_2(symb, validate) \
|
|
if (_Symbol == #symb) { \
|
|
s16 _Arg0 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
s16 _Arg1 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
validate(aGfxData, aColValData, _Arg0, _Arg1); \
|
|
aColValData.lastSymbol = _Symbol.begin(); \
|
|
Collision _Cl[] = { symb(_Arg0, _Arg1) }; \
|
|
memcpy(aHead, _Cl, sizeof(_Cl)); \
|
|
aHead += (sizeof(_Cl) / sizeof(_Cl[0])); \
|
|
return; \
|
|
}
|
|
|
|
#define col_symbol_3(symb, validate) \
|
|
if (_Symbol == #symb) { \
|
|
s16 _Arg0 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
s16 _Arg1 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
s16 _Arg2 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
validate(aGfxData, aColValData, _Arg0, _Arg1, _Arg2); \
|
|
aColValData.lastSymbol = _Symbol.begin(); \
|
|
Collision _Cl[] = { symb(_Arg0, _Arg1, _Arg2) }; \
|
|
memcpy(aHead, _Cl, sizeof(_Cl)); \
|
|
aHead += (sizeof(_Cl) / sizeof(_Cl[0])); \
|
|
return; \
|
|
}
|
|
|
|
#define col_symbol_4(symb, validate) \
|
|
if (_Symbol == #symb) { \
|
|
s16 _Arg0 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
s16 _Arg1 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
s16 _Arg2 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
s16 _Arg3 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
validate(aGfxData, aColValData, _Arg0, _Arg1, _Arg2, _Arg3); \
|
|
aColValData.lastSymbol = _Symbol.begin(); \
|
|
Collision _Cl[] = { symb(_Arg0, _Arg1, _Arg2, _Arg3) }; \
|
|
memcpy(aHead, _Cl, sizeof(_Cl)); \
|
|
aHead += (sizeof(_Cl) / sizeof(_Cl[0])); \
|
|
return; \
|
|
}
|
|
|
|
#define col_symbol_5(symb, validate) \
|
|
if (_Symbol == #symb) { \
|
|
s16 _Arg0 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
s16 _Arg1 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
s16 _Arg2 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
s16 _Arg3 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
s16 _Arg4 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
validate(aGfxData, aColValData, _Arg0, _Arg1, _Arg2, _Arg3, \
|
|
_Arg4); \
|
|
aColValData.lastSymbol = _Symbol.begin(); \
|
|
Collision _Cl[] = { symb(_Arg0, _Arg1, _Arg2, _Arg3, _Arg4) }; \
|
|
memcpy(aHead, _Cl, sizeof(_Cl)); \
|
|
aHead += (sizeof(_Cl) / sizeof(_Cl[0])); \
|
|
return; \
|
|
}
|
|
|
|
#define col_symbol_6(symb, validate) \
|
|
if (_Symbol == #symb) { \
|
|
s16 _Arg0 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
s16 _Arg1 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
s16 _Arg2 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
s16 _Arg3 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
s16 _Arg4 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
s16 _Arg5 = ParseColSymbolArg(aGfxData, aNode, aTokenIndex); \
|
|
validate(aGfxData, aColValData, _Arg0, _Arg1, _Arg2, _Arg3, \
|
|
_Arg4, _Arg5); \
|
|
aColValData.lastSymbol = _Symbol.begin(); \
|
|
Collision _Cl[] = { symb(_Arg0, _Arg1, _Arg2, _Arg3, _Arg4, _Arg5) }; \
|
|
memcpy(aHead, _Cl, sizeof(_Cl)); \
|
|
aHead += (sizeof(_Cl) / sizeof(_Cl[0])); \
|
|
return; \
|
|
}
|
|
|
|
static void ParseCollisionSymbol(GfxData* aGfxData, DataNode<Collision>* aNode, Collision*& aHead, u64& aTokenIndex, Array<u64>& aSwitchNodes, struct CollisionValidationData& aColValData) {
|
|
aColValData.tokenIndex = aTokenIndex;
|
|
const String& _Symbol = aNode->mTokens[aTokenIndex++];
|
|
|
|
col_symbol_0(COL_INIT, ValidateColInit);
|
|
col_symbol_1(COL_VERTEX_INIT, ValidateColVertexInit);
|
|
col_symbol_3(COL_VERTEX, ValidateColVertex);
|
|
col_symbol_2(COL_TRI_INIT, ValidateColTriInit);
|
|
col_symbol_3(COL_TRI, ValidateColTri);
|
|
col_symbol_4(COL_TRI_SPECIAL, ValidateColTriSpecial);
|
|
col_symbol_0(COL_TRI_STOP, ValidateColStop);
|
|
col_symbol_0(COL_END, ValidateColEnd);
|
|
col_symbol_1(COL_SPECIAL_INIT, ValidateColSpecialInit);
|
|
col_symbol_1(COL_WATER_BOX_INIT, ValidateColWaterBoxInit);
|
|
col_symbol_6(COL_WATER_BOX, ValidateColWaterBox);
|
|
col_symbol_4(SPECIAL_OBJECT, ValidateColSpecialObject);
|
|
col_symbol_5(SPECIAL_OBJECT_WITH_YAW, ValidateColSpecialObjectWithYaw);
|
|
col_symbol_6(SPECIAL_OBJECT_WITH_YAW_AND_PARAM, ValidateColSpecialObjectWithYawAndParam);
|
|
|
|
// Unknown
|
|
PrintDataError(" ERROR: Unknown col symbol: %s", _Symbol.begin());
|
|
}
|
|
|
|
DataNode<Collision>* DynOS_Col_Parse(GfxData* aGfxData, DataNode<Collision>* aNode, bool aDisplayPercent) {
|
|
if (aNode->mData) return aNode;
|
|
|
|
// Collision data
|
|
aNode->mData = New<Collision>(aNode->mTokens.Count() * COLLISION_SIZE_PER_TOKEN);
|
|
Collision* _Head = aNode->mData;
|
|
Array<u64> _SwitchNodes;
|
|
|
|
struct CollisionValidationData colValData = { 0 };
|
|
colValData.lastSymbol = aNode->mTokens[0].begin();
|
|
|
|
for (u64 _TokenIndex = 0; _TokenIndex < aNode->mTokens.Count();) { // Don't increment _TokenIndex here!
|
|
ParseCollisionSymbol(aGfxData, aNode, _Head, _TokenIndex, _SwitchNodes, colValData);
|
|
if (aDisplayPercent && aGfxData->mErrorCount == 0) { PrintNoNewLine("%3d%%\b\b\b\b", (s32) (_TokenIndex * 100) / aNode->mTokens.Count()); }
|
|
}
|
|
|
|
if (colValData.section != COL_SECTION_END) {
|
|
PrintDataError("Collision did not end with COL_END");
|
|
}
|
|
|
|
if (aDisplayPercent && aGfxData->mErrorCount == 0) { Print("100%%"); }
|
|
aNode->mSize = (u32)(_Head - aNode->mData);
|
|
aNode->mLoadIndex = aGfxData->mLoadIndex++;
|
|
|
|
if (aGfxData->mErrorCount > 0) {
|
|
PrintDataError("Failed to parse collision: '%s'", aNode->mName.begin());
|
|
}
|
|
|
|
return aNode;
|
|
}
|
|
|
|
/////////////
|
|
// Writing //
|
|
/////////////
|
|
|
|
void DynOS_Col_Write(BinFile* aFile, GfxData* aGfxData, DataNode<Collision> *aNode) {
|
|
if (!aNode->mData) return;
|
|
|
|
// Name
|
|
aFile->Write<u8>(DATA_TYPE_COLLISION);
|
|
aNode->mName.Write(aFile);
|
|
|
|
// Data
|
|
aFile->Write<u32>(aNode->mSize);
|
|
for (u32 i = 0; i != aNode->mSize; ++i) {
|
|
aFile->Write<Collision>(aNode->mData[i]);
|
|
}
|
|
}
|
|
|
|
static bool DynOS_Col_WriteBinary(const SysPath &aOutputFilename, GfxData *aGfxData, DataNode<Collision>* _Node) {
|
|
BinFile *_File = BinFile::OpenW(aOutputFilename.c_str());
|
|
if (!_File) {
|
|
PrintDataError(" ERROR: Unable to create file \"%s\"", aOutputFilename.c_str());
|
|
return false;
|
|
}
|
|
|
|
DynOS_Col_Write(_File, aGfxData, _Node);
|
|
|
|
BinFile::Close(_File);
|
|
return DynOS_Bin_Compress(aOutputFilename);
|
|
}
|
|
|
|
/////////////
|
|
// Loading //
|
|
/////////////
|
|
|
|
DataNode<Collision>* DynOS_Col_Load(BinFile *aFile, GfxData *aGfxData) {
|
|
DataNode<Collision> *_Node = New<DataNode<Collision>>();
|
|
|
|
// Name
|
|
_Node->mName.Read(aFile);
|
|
|
|
// Data
|
|
_Node->mSize = aFile->Read<u32>();
|
|
_Node->mData = New<Collision>(_Node->mSize);
|
|
for (u32 i = 0; i != _Node->mSize; ++i) {
|
|
_Node->mData[i] = aFile->Read<Collision>();
|
|
}
|
|
|
|
// Add it
|
|
if (aGfxData != NULL) {
|
|
aGfxData->mCollisions.Add(_Node);
|
|
}
|
|
|
|
return _Node;
|
|
}
|
|
|
|
DataNode<Collision>* DynOS_Col_LoadFromBinary(const SysPath &aFilename, const char *aCollisionName) {
|
|
// Load data from binary file
|
|
DataNode<Collision>* collisionNode = NULL;
|
|
BinFile *_File = DynOS_Bin_Decompress(aFilename);
|
|
if (_File) {
|
|
u8 type = _File->Read<u8>();
|
|
if (type == DATA_TYPE_COLLISION) {
|
|
collisionNode = DynOS_Col_Load(_File, NULL);
|
|
}
|
|
BinFile::Close(_File);
|
|
}
|
|
|
|
return collisionNode;
|
|
}
|
|
|
|
//////////////
|
|
// Generate //
|
|
//////////////
|
|
|
|
void DynOS_Col_Generate(const SysPath &aPackFolder, Array<Pair<u64, String>> _ActorsFolders, GfxData *_GfxData) {
|
|
for (auto &_ColNode : _GfxData->mCollisions) {
|
|
String _ColRootName = _ColNode->mName;
|
|
|
|
// If there is an existing binary file for this collision, skip and go to the next actor
|
|
SysPath _ColFilename = fstring("%s/%s.col", aPackFolder.c_str(), _ColRootName.begin());
|
|
if (fs_sys_file_exists(_ColFilename.c_str())) {
|
|
|
|
// Compress file to gain some space
|
|
if (configCompressOnStartup && !DynOS_Bin_IsCompressed(_ColFilename)) {
|
|
DynOS_Bin_Compress(_ColFilename);
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
// Init
|
|
_GfxData->mErrorCount = 0;
|
|
_GfxData->mLoadIndex = 0;
|
|
|
|
// Parse data
|
|
PrintNoNewLine("%s.col: Collision identifier: %X - Processing... ", _ColRootName.begin(), _GfxData->mModelIdentifier);
|
|
PrintConsole(CONSOLE_MESSAGE_INFO, "%s.col: Collision identifier: %X - Processing... ", _ColRootName.begin(), _GfxData->mModelIdentifier);
|
|
DynOS_Col_Parse(_GfxData, _ColNode, true);
|
|
|
|
// Write if no error
|
|
if (_GfxData->mErrorCount == 0) {
|
|
DynOS_Col_WriteBinary(_ColFilename, _GfxData, _ColNode);
|
|
} else {
|
|
PrintError(" %u error(s): Unable to parse data", _GfxData->mErrorCount);
|
|
}
|
|
|
|
// Clear data pointers
|
|
ClearGfxDataNodes(_GfxData->mCollisions);
|
|
}
|
|
}
|