2022-04-02 02:19:26 +02:00
|
|
|
#include "dynos.cpp.h"
|
|
|
|
|
2022-04-02 04:50:42 +02:00
|
|
|
//////////
|
|
|
|
// Misc //
|
|
|
|
//////////
|
|
|
|
|
|
|
|
void DynOS_Gfx_Free(GfxData* aGfxData) {
|
|
|
|
if (aGfxData) {
|
|
|
|
for (auto& _Node : aGfxData->mLights) {
|
|
|
|
Delete(_Node->mData);
|
|
|
|
Delete(_Node);
|
|
|
|
}
|
2022-04-05 06:25:40 +02:00
|
|
|
for (auto& _Node : aGfxData->mLightTs) {
|
|
|
|
Delete(_Node->mData);
|
|
|
|
Delete(_Node);
|
|
|
|
}
|
|
|
|
for (auto& _Node : aGfxData->mAmbientTs) {
|
|
|
|
Delete(_Node->mData);
|
|
|
|
Delete(_Node);
|
|
|
|
}
|
2022-04-02 04:50:42 +02:00
|
|
|
for (auto& _Node : aGfxData->mTextures) {
|
|
|
|
Delete(_Node->mData);
|
|
|
|
Delete(_Node);
|
|
|
|
}
|
|
|
|
for (auto& _Node : aGfxData->mVertices) {
|
|
|
|
Delete(_Node->mData);
|
|
|
|
Delete(_Node);
|
|
|
|
}
|
|
|
|
for (auto& _Node : aGfxData->mDisplayLists) {
|
|
|
|
Delete(_Node->mData);
|
|
|
|
Delete(_Node);
|
|
|
|
}
|
|
|
|
for (auto& _Node : aGfxData->mGeoLayouts) {
|
|
|
|
Delete(_Node->mData);
|
|
|
|
Delete(_Node);
|
|
|
|
}
|
|
|
|
for (auto& _Node : aGfxData->mAnimations) {
|
|
|
|
Delete(_Node->mData);
|
|
|
|
Delete(_Node);
|
|
|
|
}
|
|
|
|
for (auto& _Node : aGfxData->mCollisions) {
|
|
|
|
Delete(_Node->mData);
|
|
|
|
Delete(_Node);
|
|
|
|
}
|
|
|
|
for (auto& _Node : aGfxData->mLevelScripts) {
|
|
|
|
Delete(_Node->mData);
|
|
|
|
Delete(_Node);
|
|
|
|
}
|
|
|
|
for (auto& _Node : aGfxData->mMacroObjects) {
|
|
|
|
Delete(_Node->mData);
|
|
|
|
Delete(_Node);
|
|
|
|
}
|
2022-04-03 01:08:19 +02:00
|
|
|
for (auto& _Node : aGfxData->mTrajectories) {
|
|
|
|
Delete(_Node->mData);
|
|
|
|
Delete(_Node);
|
|
|
|
}
|
2022-04-04 07:12:17 +02:00
|
|
|
for (auto& _Node : aGfxData->mMovtexs) {
|
|
|
|
Delete(_Node->mData);
|
|
|
|
Delete(_Node);
|
|
|
|
}
|
|
|
|
for (auto& _Node : aGfxData->mMovtexQCs) {
|
|
|
|
Delete(_Node->mData);
|
|
|
|
Delete(_Node);
|
|
|
|
}
|
2022-04-04 08:42:25 +02:00
|
|
|
for (auto& _Node : aGfxData->mRooms) {
|
|
|
|
Delete(_Node->mData);
|
|
|
|
Delete(_Node);
|
|
|
|
}
|
2022-04-02 04:50:42 +02:00
|
|
|
Delete(aGfxData);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-02 02:19:26 +02:00
|
|
|
///////////////////////
|
|
|
|
// Recursive Descent //
|
|
|
|
///////////////////////
|
|
|
|
|
|
|
|
static char* sRdString = NULL;
|
|
|
|
static bool sRdError = false;
|
|
|
|
|
|
|
|
static s64 ParseExpression();
|
|
|
|
|
|
|
|
static void ParseWhitespace() {
|
|
|
|
while (*sRdString == ' ' || *sRdString == '\t' || *sRdString == '\r' || *sRdString == '\n') {
|
|
|
|
sRdString++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-03 12:30:47 +02:00
|
|
|
static bool IsAlphabetical(char c) {
|
|
|
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool IsAlphaNumeric(char c) {
|
|
|
|
return IsAlphabetical(c) || (c >= '0' && c <= '9');
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool IsIdentifierBeginning(char c) {
|
|
|
|
return IsAlphabetical(c) || (c == '_');
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool IsIdentifierCharacter(char c) {
|
|
|
|
return IsAlphaNumeric(c) || (c == '_');
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool ParseOperator(const char* op) {
|
|
|
|
size_t opLen = strlen(op);
|
|
|
|
if (!strncmp(sRdString, op, opLen)) {
|
|
|
|
sRdString += opLen;
|
|
|
|
ParseWhitespace();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-04-02 02:19:26 +02:00
|
|
|
static s64 ParseNumeric() {
|
|
|
|
String numeric = "";
|
|
|
|
char* c = sRdString;
|
|
|
|
|
|
|
|
// check for hex
|
|
|
|
if (*c == '0' && *(c+1) == 'x') {
|
|
|
|
numeric.Add(*c);
|
|
|
|
c++;
|
|
|
|
numeric.Add(*c);
|
|
|
|
c++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// continue adding to string
|
|
|
|
while (*c >= '0' && *c <= '9') {
|
|
|
|
numeric.Add(*c);
|
|
|
|
c++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// advance parsing
|
|
|
|
sRdString = c;
|
|
|
|
ParseWhitespace();
|
|
|
|
|
|
|
|
// parse
|
|
|
|
return numeric.ParseInt();
|
|
|
|
}
|
|
|
|
|
|
|
|
static s64 ParseFactor() {
|
|
|
|
char* c = sRdString;
|
|
|
|
|
|
|
|
// check for unary op
|
2022-04-03 12:30:47 +02:00
|
|
|
if (ParseOperator("-")) {
|
|
|
|
return -ParseFactor();
|
|
|
|
} else if (ParseOperator("+")) {
|
|
|
|
return +ParseFactor();
|
|
|
|
} else if (ParseOperator("!")) {
|
|
|
|
return !ParseFactor();
|
|
|
|
} else if (ParseOperator("~")) {
|
|
|
|
return ~ParseFactor();
|
2022-04-02 02:19:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// check for numeric
|
|
|
|
if (*c >= '0' && *c <= '9') {
|
|
|
|
return ParseNumeric();
|
2022-04-03 12:30:47 +02:00
|
|
|
}
|
2022-04-02 02:19:26 +02:00
|
|
|
|
|
|
|
// check for sub expression
|
2022-04-03 12:30:47 +02:00
|
|
|
if (ParseOperator("(")) {
|
2022-04-02 02:19:26 +02:00
|
|
|
s64 e1 = ParseExpression();
|
2022-04-03 12:30:47 +02:00
|
|
|
if (ParseOperator(")")) {
|
2022-04-02 02:19:26 +02:00
|
|
|
return e1;
|
2022-04-03 12:30:47 +02:00
|
|
|
} else {
|
|
|
|
sRdError = true;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// check for known identifier
|
|
|
|
if (IsIdentifierBeginning(*c)) {
|
|
|
|
String identifier = "";
|
|
|
|
char* cTmp = c;
|
|
|
|
while (IsIdentifierCharacter(*cTmp)) {
|
|
|
|
identifier.Add(*cTmp);
|
|
|
|
cTmp++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: this was made so that recursive descent can parse the constants...
|
|
|
|
// but RD should really use any function pointer passed to it
|
|
|
|
bool constantFound = false;
|
|
|
|
s64 constantValue = DynOS_Lvl_ParseLevelScriptConstants(identifier, &constantFound);
|
|
|
|
if (constantFound) {
|
|
|
|
sRdString = cTmp;
|
|
|
|
return constantValue;
|
2022-04-02 02:19:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sRdError = true;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static s64 ParseTerm() {
|
|
|
|
s64 f1 = ParseFactor();
|
|
|
|
|
2022-04-03 12:30:47 +02:00
|
|
|
if (ParseOperator("*")) {
|
|
|
|
return f1 * ParseFactor();
|
|
|
|
} else if (ParseOperator("/")) {
|
|
|
|
return f1 / ParseFactor();
|
|
|
|
} else if (ParseOperator("%")) {
|
|
|
|
return f1 % ParseFactor();
|
2022-04-02 02:19:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return f1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static s64 ParseAddSubExpression() {
|
|
|
|
s64 t1 = ParseTerm();
|
|
|
|
|
2022-04-03 12:30:47 +02:00
|
|
|
if (ParseOperator("+")) {
|
|
|
|
return t1 + ParseTerm();
|
|
|
|
} else if (ParseOperator("-")) {
|
|
|
|
return t1 - ParseTerm();
|
2022-04-02 02:19:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return t1;
|
|
|
|
}
|
|
|
|
|
2022-04-03 12:30:47 +02:00
|
|
|
static s64 ParseShiftExpression() {
|
2022-04-02 02:19:26 +02:00
|
|
|
s64 e1 = ParseAddSubExpression();
|
|
|
|
|
2022-04-03 12:30:47 +02:00
|
|
|
if (ParseOperator("<<")) {
|
|
|
|
return e1 << ParseAddSubExpression();
|
|
|
|
} else if (ParseOperator(">>")) {
|
|
|
|
return e1 >> ParseAddSubExpression();
|
|
|
|
}
|
|
|
|
|
|
|
|
return e1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static s64 ParseBitAndExpression() {
|
|
|
|
s64 e1 = ParseShiftExpression();
|
|
|
|
|
|
|
|
if (ParseOperator("&")) {
|
|
|
|
return e1 & ParseShiftExpression();
|
2022-04-02 02:19:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return e1;
|
|
|
|
}
|
|
|
|
|
2022-04-03 12:30:47 +02:00
|
|
|
static s64 ParseBitXorExpression() {
|
|
|
|
s64 e1 = ParseBitAndExpression();
|
|
|
|
|
|
|
|
if (ParseOperator("^")) {
|
|
|
|
return e1 ^ ParseBitAndExpression();
|
|
|
|
}
|
|
|
|
|
|
|
|
return e1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static s64 ParseBitOrExpression() {
|
|
|
|
s64 e1 = ParseBitXorExpression();
|
|
|
|
|
|
|
|
if (ParseOperator("|")) {
|
|
|
|
return e1 | ParseBitXorExpression();
|
|
|
|
}
|
|
|
|
|
|
|
|
return e1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static s64 ParseExpression() {
|
|
|
|
return ParseBitOrExpression();
|
|
|
|
}
|
|
|
|
|
2022-04-02 02:19:26 +02:00
|
|
|
s64 DynOS_RecursiveDescent_Parse(const char* expr, bool* success) {
|
|
|
|
sRdString = (char*)expr;
|
|
|
|
sRdError = false;
|
|
|
|
s64 value = ParseExpression();
|
|
|
|
sRdString = NULL;
|
|
|
|
*success = !sRdError;
|
|
|
|
//Print(">>> PARSING %s == %d :: %u", expr, value, *success);
|
|
|
|
return value;
|
|
|
|
}
|