mirror of
				https://github.com/coop-deluxe/sm64coopdx.git
				synced 2025-10-30 08:01:01 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			379 lines
		
	
	
	
		
			9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			379 lines
		
	
	
	
		
			9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
#include "dynos.cpp.h"
 | 
						|
 | 
						|
  //////////
 | 
						|
 // Misc //
 | 
						|
//////////
 | 
						|
 | 
						|
s64 DynOS_Misc_ParseInteger(const String& _Arg, bool* found) {
 | 
						|
    const char* argStr = _Arg.begin();
 | 
						|
    if (argStr[0] == '0' && argStr[1] == 'x') {
 | 
						|
        // is a hex number
 | 
						|
        argStr += 2;
 | 
						|
        while(*argStr != '\0') {
 | 
						|
            if (*argStr >= '0' && *argStr <= '9') {
 | 
						|
                // good
 | 
						|
            } else if (*argStr >= 'a' && *argStr <= 'f') {
 | 
						|
                // good
 | 
						|
            } else if (*argStr >= 'A' && *argStr <= 'F') {
 | 
						|
                // good
 | 
						|
            } else {
 | 
						|
                // bad character
 | 
						|
                *found = false;
 | 
						|
                return 0;
 | 
						|
            }
 | 
						|
            argStr++;
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        // is a decimal number
 | 
						|
        if (*argStr == '-' || *argStr == '+') {
 | 
						|
            // good
 | 
						|
            argStr++;
 | 
						|
        }
 | 
						|
        while(*argStr != '\0') {
 | 
						|
            if (*argStr >= '0' && *argStr <= '9') {
 | 
						|
                // good
 | 
						|
            } else if (*argStr == '.') {
 | 
						|
                // good
 | 
						|
            } else {
 | 
						|
                // bad character
 | 
						|
                *found = false;
 | 
						|
                return 0;
 | 
						|
            }
 | 
						|
            argStr++;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    *found = true;
 | 
						|
    return _Arg.ParseInt();
 | 
						|
}
 | 
						|
 | 
						|
void DynOS_Gfx_Free(GfxData* aGfxData) {
 | 
						|
    if (aGfxData) {
 | 
						|
        for (auto& _Node : aGfxData->mLights) {
 | 
						|
            Delete(_Node->mData);
 | 
						|
            Delete(_Node);
 | 
						|
        }
 | 
						|
        for (auto& _Node : aGfxData->mLight0s) {
 | 
						|
            Delete(_Node->mData);
 | 
						|
            Delete(_Node);
 | 
						|
        }
 | 
						|
        for (auto& _Node : aGfxData->mLightTs) {
 | 
						|
            Delete(_Node->mData);
 | 
						|
            Delete(_Node);
 | 
						|
        }
 | 
						|
        for (auto& _Node : aGfxData->mAmbientTs) {
 | 
						|
            Delete(_Node->mData);
 | 
						|
            Delete(_Node);
 | 
						|
        }
 | 
						|
        for (auto& _Node : aGfxData->mTextures) {
 | 
						|
            Delete(_Node->mData);
 | 
						|
            Delete(_Node);
 | 
						|
        }
 | 
						|
        for (auto& _Node : aGfxData->mTextureLists) {
 | 
						|
            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->mBehaviorScripts) {
 | 
						|
            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);
 | 
						|
        }
 | 
						|
        for (auto& _Node : aGfxData->mTrajectories) {
 | 
						|
            Delete(_Node->mData);
 | 
						|
            Delete(_Node);
 | 
						|
        }
 | 
						|
        for (auto& _Node : aGfxData->mMovtexs) {
 | 
						|
            Delete(_Node->mData);
 | 
						|
            Delete(_Node);
 | 
						|
        }
 | 
						|
        for (auto& _Node : aGfxData->mMovtexQCs) {
 | 
						|
            Delete(_Node->mData);
 | 
						|
            Delete(_Node);
 | 
						|
        }
 | 
						|
        for (auto& _Node : aGfxData->mRooms) {
 | 
						|
            Delete(_Node->mData);
 | 
						|
            Delete(_Node);
 | 
						|
        }
 | 
						|
        Delete(aGfxData);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
u32 DynOS_Lua_RememberVariable(GfxData* aGfxData, void* aPtr, const String& token) {
 | 
						|
    // remember as lua pointer
 | 
						|
    aGfxData->mLuaPointerList.Add(aPtr);
 | 
						|
 | 
						|
    // find existing token
 | 
						|
    for (u32 i = 0; i < aGfxData->mLuaTokenList.Count(); i++) {
 | 
						|
        if (aGfxData->mLuaTokenList[i] == token) {
 | 
						|
            return i;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // add token
 | 
						|
    aGfxData->mLuaTokenList.Add(token);
 | 
						|
    return aGfxData->mLuaTokenList.Count() - 1;
 | 
						|
}
 | 
						|
 | 
						|
  ///////////////////////
 | 
						|
 // Recursive Descent //
 | 
						|
///////////////////////
 | 
						|
 | 
						|
static char* sRdString = NULL;
 | 
						|
static bool sRdError = false;
 | 
						|
static RDConstantFunc sRdConstantFunc = NULL;
 | 
						|
 | 
						|
static s64 ParseExpression();
 | 
						|
 | 
						|
static void ParseWhitespace() {
 | 
						|
    while (*sRdString == ' ' || *sRdString == '\t' || *sRdString == '\r' || *sRdString == '\n') {
 | 
						|
        sRdString++;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
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;
 | 
						|
}
 | 
						|
 | 
						|
static bool PeekOperator(const char* op) {
 | 
						|
    size_t opLen = strlen(op);
 | 
						|
    return (!strncmp(sRdString, op, opLen));
 | 
						|
}
 | 
						|
 | 
						|
static s64 ParseNumeric() {
 | 
						|
    String numeric = "";
 | 
						|
    char* c = sRdString;
 | 
						|
 | 
						|
    if (*c == '0' && *(c+1) == 'x') {
 | 
						|
        // is hex
 | 
						|
        numeric.Add(*c);
 | 
						|
        c++;
 | 
						|
        numeric.Add(*c);
 | 
						|
        c++;
 | 
						|
        while (true) {
 | 
						|
            if (*c >= '0' && *c <= '9') {
 | 
						|
                // good
 | 
						|
            } else if (*c >= 'a' && *c <= 'f') {
 | 
						|
                // good
 | 
						|
            } else if (*c >= 'A' && *c <= 'F') {
 | 
						|
                // good
 | 
						|
            } else {
 | 
						|
                // bad
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            numeric.Add(*c);
 | 
						|
            c++;
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        // is decimal
 | 
						|
        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
 | 
						|
    if (ParseOperator("-")) {
 | 
						|
        return -ParseFactor();
 | 
						|
    } else if (ParseOperator("+")) {
 | 
						|
        return +ParseFactor();
 | 
						|
    } else if (ParseOperator("!")) {
 | 
						|
        return !ParseFactor();
 | 
						|
    } else if (ParseOperator("~")) {
 | 
						|
        return ~ParseFactor();
 | 
						|
    }
 | 
						|
 | 
						|
    // check for numeric
 | 
						|
    if (*c >= '0' && *c <= '9') {
 | 
						|
        return ParseNumeric();
 | 
						|
    }
 | 
						|
 | 
						|
    // check for sub expression
 | 
						|
    if (ParseOperator("(")) {
 | 
						|
        s64 e1 = ParseExpression();
 | 
						|
        if (ParseOperator(")")) {
 | 
						|
            return e1;
 | 
						|
        } else {
 | 
						|
            sRdError = true;
 | 
						|
            return 0;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // check for known identifier
 | 
						|
    if (IsIdentifierBeginning(*c)) {
 | 
						|
        String identifier = "";
 | 
						|
        char* cTmp = c;
 | 
						|
        while (IsIdentifierCharacter(*cTmp)) {
 | 
						|
            identifier.Add(*cTmp);
 | 
						|
            cTmp++;
 | 
						|
        }
 | 
						|
 | 
						|
        if (sRdConstantFunc != NULL) {
 | 
						|
            bool constantFound = false;
 | 
						|
            s64 constantValue = sRdConstantFunc(identifier, &constantFound);
 | 
						|
            if (constantFound) {
 | 
						|
                sRdString = cTmp;
 | 
						|
                return constantValue;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    sRdError = true;
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
static s64 ParseTerm() {
 | 
						|
    s64 f1 = ParseFactor();
 | 
						|
 | 
						|
    while (PeekOperator("*") || PeekOperator("/") || PeekOperator("%")) {
 | 
						|
        if (ParseOperator("*")) {
 | 
						|
            f1 *= ParseFactor();
 | 
						|
        } else if (ParseOperator("/")) {
 | 
						|
            f1 /= ParseFactor();
 | 
						|
        } else if (ParseOperator("%")) {
 | 
						|
            f1 %= ParseFactor();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return f1;
 | 
						|
}
 | 
						|
 | 
						|
static s64 ParseAddSubExpression() {
 | 
						|
    s64 t1 = ParseTerm();
 | 
						|
 | 
						|
    while (PeekOperator("+") || PeekOperator("-")) {
 | 
						|
        if (ParseOperator("+")) {
 | 
						|
            t1 += ParseTerm();
 | 
						|
        } else if (ParseOperator("-")) {
 | 
						|
            t1 -= ParseTerm();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return t1;
 | 
						|
}
 | 
						|
 | 
						|
static s64 ParseShiftExpression() {
 | 
						|
    s64 e1 = ParseAddSubExpression();
 | 
						|
 | 
						|
    while (PeekOperator("<<") || PeekOperator(">>")) {
 | 
						|
        if (ParseOperator("<<")) {
 | 
						|
            e1 = e1 << ParseAddSubExpression();
 | 
						|
        } else if (ParseOperator(">>")) {
 | 
						|
            e1 = e1 >> ParseAddSubExpression();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return e1;
 | 
						|
}
 | 
						|
 | 
						|
static s64 ParseBitAndExpression() {
 | 
						|
    s64 e1 = ParseShiftExpression();
 | 
						|
 | 
						|
    while (PeekOperator("&")) {
 | 
						|
        if (ParseOperator("&")) {
 | 
						|
            e1 &= ParseShiftExpression();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return e1;
 | 
						|
}
 | 
						|
 | 
						|
static s64 ParseBitXorExpression() {
 | 
						|
    s64 e1 = ParseBitAndExpression();
 | 
						|
 | 
						|
    while (PeekOperator("^")) {
 | 
						|
        if (ParseOperator("^")) {
 | 
						|
            e1 ^= ParseBitAndExpression();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return e1;
 | 
						|
}
 | 
						|
 | 
						|
static s64 ParseBitOrExpression() {
 | 
						|
    s64 e1 = ParseBitXorExpression();
 | 
						|
 | 
						|
    while (PeekOperator("|")) {
 | 
						|
        if (ParseOperator("|")) {
 | 
						|
            e1 |= ParseBitXorExpression();
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return e1;
 | 
						|
}
 | 
						|
 | 
						|
static s64 ParseExpression() {
 | 
						|
    return ParseBitOrExpression();
 | 
						|
}
 | 
						|
 | 
						|
s64 DynOS_RecursiveDescent_Parse(const char* expr, bool* success, RDConstantFunc func) {
 | 
						|
    sRdString = (char*)expr;
 | 
						|
    sRdError = false;
 | 
						|
    sRdConstantFunc = func;
 | 
						|
    s64 value = ParseExpression();
 | 
						|
    if (strlen(sRdString) > 0) {
 | 
						|
        sRdError = true;
 | 
						|
    }
 | 
						|
    sRdString = NULL;
 | 
						|
    *success = !sRdError;
 | 
						|
    return value;
 | 
						|
}
 |