#include "Library/Yaml/ByamlData.h" #include namespace al { ByamlData::ByamlData() = default; void ByamlData::set(const ByamlHashPair* hash_pair, bool isRev) { mType = hash_pair->getType(); mValue = hash_pair->getValue(isRev); } void ByamlData::set(u8 type, u32 value, bool isRev) { mType = (ByamlDataType)type; mValue = isRev ? bswap_32(value) : value; } ByamlDataType ByamlData::getType() const { return mType; } u32 ByamlData::getValue() const { return mValue; } s32 ByamlHashPair::getKey(bool isRev) const { return isRev ? bswap_24(mData) : mData & 0xFFFFFF; } ByamlDataType ByamlHashPair::getType() const { return (ByamlDataType)(mData >> 24); } s32 ByamlHashPair::getValue(bool isRev) const { return isRev ? bswap_32(mValue) : mValue; } ByamlHashIter::ByamlHashIter(const u8* data, bool isRev) : mData(data), mIsRev(isRev) {} ByamlHashIter::ByamlHashIter() : mData(nullptr), mIsRev(false) {} const ByamlHashPair* ByamlHashIter::findPair(s32 key) const { const ByamlHashPair* pairTable = getPairTable(); if (!mData) return nullptr; s32 lowerBound = 0; s32 upperBound = getSize(); asm(""); // solves isRev leaking over between getSize() and getKey() while (lowerBound < upperBound) { s32 avg = (lowerBound + upperBound) / 2; const ByamlHashPair* pair = &pairTable[avg]; s32 result = key - pair->getKey(mIsRev); if (result == 0) return pair; if (result > 0) lowerBound = avg + 1; else upperBound = avg; } return nullptr; } bool ByamlHashIter::getDataByIndex(ByamlData* data, s32 index) const { if (!mData) return false; if (((s32)getSize()) < 1) return false; data->set(&getPairTable()[index], mIsRev); return true; } // NON_MATCHING: minor additional instructions, probably not inlined // (https://decomp.me/scratch/5VLcG) bool ByamlHashIter::getDataByKey(ByamlData* data, s32 key) const { if (!mData) return false; if (((s32)getSize()) < 1) return false; // probably inlined from findPair() const ByamlHashPair* pairTable = getPairTable(); if (!mData) return false; s32 lowerBound = 0; s32 upperBound = getSize(); const ByamlHashPair* pair; if (lowerBound >= upperBound) return false; while (true) { s32 avg = (lowerBound + upperBound) / 2; pair = &pairTable[avg]; s32 result = key - pair->getKey(mIsRev); if (result == 0) break; if (result > 0) lowerBound = avg + 1; else upperBound = avg; if (lowerBound >= upperBound) return false; } if (!pair) return false; data->set(pair, mIsRev); return true; } const u8* ByamlHashIter::getOffsetData(u32 off) const { return &mData[off]; } const ByamlHashPair* ByamlHashIter::getPairByIndex(s32 index) const { if (index < 0) return nullptr; if (((s32)getSize()) <= index) return nullptr; return &getPairTable()[index]; } const ByamlHashPair* ByamlHashIter::getPairTable() const { if (!mData) return nullptr; return reinterpret_cast(mData + 4); } u32 ByamlHashIter::getSize() const { if (!mData) return 0; u32 val = *reinterpret_cast(mData); return mIsRev ? bswap_24(val >> 8) : val >> 8; } ByamlArrayIter::ByamlArrayIter(const u8* data, bool isRev) : mData(data), mIsRev(isRev) {} ByamlArrayIter::ByamlArrayIter() : mData(nullptr), mIsRev(false) {} bool ByamlArrayIter::getDataByIndex(ByamlData* data, s32 index) const { if (index < 0) return false; if (((s32)getSize()) <= index) return false; data->set(getTypeTable()[index], getDataTable()[index], mIsRev); return true; } // NON_MATCHING: regalloc (https://decomp.me/scratch/dGFdU) const u32* ByamlArrayIter::getDataTable() const { return reinterpret_cast(getOffsetData((getSize() + 7) & 0xFFFFFFFC)); } const u8* ByamlArrayIter::getOffsetData(u32 off) const { return &mData[off]; } u32 ByamlArrayIter::getSize() const { u32 val = *reinterpret_cast(mData); return mIsRev ? bswap_24(val >> 8) : val >> 8; } const u8* ByamlArrayIter::getTypeTable() const { return mData + 4; } } // namespace al