|
| 1 | +#pragma once |
| 2 | + |
| 3 | +/// @brief Class representing a cheat or a cheat category. |
| 4 | +class CheatEntry |
| 5 | +{ |
| 6 | +public: |
| 7 | + /// @brief Dummy empty constructor. |
| 8 | + CheatEntry() |
| 9 | + : _isCheatCategory(false), _flagsPointer(nullptr), _cheatData(nullptr), _cheatDataLength(0) { } |
| 10 | + |
| 11 | + /// @brief Constructor for a cheat. |
| 12 | + CheatEntry(const char* name, const char* description, u32* flagsPointer, const void* cheatData, u32 cheatDataLength) |
| 13 | + : _name(name), _description(description), _isCheatCategory(false), _flagsPointer(flagsPointer) |
| 14 | + , _cheatData(cheatData), _cheatDataLength(cheatDataLength) { } |
| 15 | + |
| 16 | + /// @brief Constructor for a category. |
| 17 | + CheatEntry(const char* name, const char* description, bool isMaxOneCheatActive, CheatEntry* subEntries, u32 numberOfSubEntries) |
| 18 | + : _name(name), _description(description), _isCheatCategory(true), _isMaxOneCheatActive(isMaxOneCheatActive) |
| 19 | + , _subEntries(subEntries), _numberOfSubEntries(numberOfSubEntries) { } |
| 20 | + |
| 21 | + CheatEntry(const CheatEntry& other) = delete; |
| 22 | + |
| 23 | + CheatEntry(CheatEntry&& other) |
| 24 | + : _isCheatCategory(false), _flagsPointer(nullptr), _cheatData(nullptr), _cheatDataLength(0) |
| 25 | + { |
| 26 | + *this = std::move(other); |
| 27 | + } |
| 28 | + |
| 29 | + ~CheatEntry() |
| 30 | + { |
| 31 | + if (_isCheatCategory && _subEntries != nullptr) |
| 32 | + { |
| 33 | + delete[] _subEntries; |
| 34 | + } |
| 35 | + } |
| 36 | + |
| 37 | + CheatEntry& operator=(const CheatEntry& other) = delete; |
| 38 | + |
| 39 | + CheatEntry& operator=(CheatEntry&& other) |
| 40 | + { |
| 41 | + if (_isCheatCategory && _subEntries != nullptr) |
| 42 | + { |
| 43 | + delete[] _subEntries; |
| 44 | + _subEntries = nullptr; |
| 45 | + } |
| 46 | + |
| 47 | + _name = other._name; |
| 48 | + other._name = nullptr; |
| 49 | + _description = other._description; |
| 50 | + other._description = nullptr; |
| 51 | + _isCheatCategory = other.IsCheatCategory(); |
| 52 | + if (_isCheatCategory) |
| 53 | + { |
| 54 | + _isMaxOneCheatActive = other._isMaxOneCheatActive; |
| 55 | + _subEntries = other._subEntries; |
| 56 | + other._subEntries = nullptr; |
| 57 | + _numberOfSubEntries = other._numberOfSubEntries; |
| 58 | + other._numberOfSubEntries = 0; |
| 59 | + } |
| 60 | + else |
| 61 | + { |
| 62 | + _flagsPointer = other._flagsPointer; |
| 63 | + other._flagsPointer = nullptr; |
| 64 | + _cheatData = other._cheatData; |
| 65 | + other._cheatData = nullptr; |
| 66 | + _cheatDataLength = other._cheatDataLength; |
| 67 | + other._cheatDataLength = 0; |
| 68 | + } |
| 69 | + |
| 70 | + return *this; |
| 71 | + } |
| 72 | + |
| 73 | + /// @brief Gets the name of this cheat entry. |
| 74 | + /// @return A pointer to the name of this cheat entry. |
| 75 | + const char* GetName() const |
| 76 | + { |
| 77 | + return _name; |
| 78 | + } |
| 79 | + |
| 80 | + /// @brief Gets the description of this cheat entry. |
| 81 | + /// @return A pointer to the description of this cheat entry. |
| 82 | + const char* GetDescription() const |
| 83 | + { |
| 84 | + return _description; |
| 85 | + } |
| 86 | + |
| 87 | + /// @brief When this entry is a cheat, gets a pointer to the cheat data. |
| 88 | + /// @param cheatDataLength The length of the cheat data is returned in this reference. |
| 89 | + /// @return A pointer to the cheat data. |
| 90 | + /// This pointer is only valid for the lifetime of the \see GameCheats instance this cheat belongs to. |
| 91 | + /// If this entry is not a cheat, \c nullptr is returned. |
| 92 | + const void* GetCheatData(u32& cheatDataLength) const |
| 93 | + { |
| 94 | + if (_isCheatCategory) |
| 95 | + { |
| 96 | + cheatDataLength = 0; |
| 97 | + return nullptr; |
| 98 | + } |
| 99 | + else |
| 100 | + { |
| 101 | + cheatDataLength = _cheatDataLength; |
| 102 | + return _cheatData; |
| 103 | + } |
| 104 | + } |
| 105 | + |
| 106 | + /// @brief Gets whether this entry is an active (enabled) cheat or not. |
| 107 | + /// @return \c true when this entry is an active cheat, or \c false otherwise. |
| 108 | + bool GetIsCheatActive() const |
| 109 | + { |
| 110 | + if (_isCheatCategory) |
| 111 | + { |
| 112 | + return false; |
| 113 | + } |
| 114 | + else |
| 115 | + { |
| 116 | + return ((*_flagsPointer >> 24) & 1) == 1; |
| 117 | + } |
| 118 | + } |
| 119 | + |
| 120 | + /// @brief If this entry is a cheat, sets whether this cheat is active (enabled) or not. |
| 121 | + /// @param isCheatActive \c true to enable this cheat, or \c false to disable this cheat. |
| 122 | + void SetIsCheatActive(bool isCheatActive) const |
| 123 | + { |
| 124 | + if (!_isCheatCategory) |
| 125 | + { |
| 126 | + u32 flags = *_flagsPointer; |
| 127 | + flags &= ~(1 << 24); |
| 128 | + if (isCheatActive) |
| 129 | + { |
| 130 | + flags |= 1 << 24; |
| 131 | + } |
| 132 | + *_flagsPointer = flags; |
| 133 | + } |
| 134 | + } |
| 135 | + |
| 136 | + /// @brief Indicates if this entry is a cheat category or not. |
| 137 | + /// @return \c true when this entry is a cheat category, or \c false when this entry is a cheat. |
| 138 | + bool IsCheatCategory() const |
| 139 | + { |
| 140 | + return _isCheatCategory; |
| 141 | + } |
| 142 | + |
| 143 | + /// @brief Indicates if this entry is a cheat category in which only one cheat is allowed to be on at a time or not. |
| 144 | + /// @return \c true when this entry is a cheat category in which only one cheat is allowed |
| 145 | + /// to be active at a time, or \c false otherwise. |
| 146 | + bool GetIsMaxOneCheatActive() const |
| 147 | + { |
| 148 | + return _isCheatCategory && _isMaxOneCheatActive; |
| 149 | + } |
| 150 | + |
| 151 | + /// @brief Gets the sub-entries of this entry. |
| 152 | + /// @param numberOfSubEntries The number of sub-entries is returned through this reference. |
| 153 | + /// @return A pointer to an array of entries. This may be \c nullptr when \p numberOfSubEntries is 0. |
| 154 | + const CheatEntry* GetSubEntries(u32& numberOfSubEntries) const |
| 155 | + { |
| 156 | + if (_isCheatCategory) |
| 157 | + { |
| 158 | + numberOfSubEntries = _numberOfSubEntries; |
| 159 | + return _subEntries; |
| 160 | + } |
| 161 | + else |
| 162 | + { |
| 163 | + numberOfSubEntries = 0; |
| 164 | + return nullptr; |
| 165 | + } |
| 166 | + } |
| 167 | + |
| 168 | +private: |
| 169 | + const char* _name = nullptr; |
| 170 | + const char* _description = nullptr; |
| 171 | + bool _isCheatCategory; |
| 172 | + |
| 173 | + union |
| 174 | + { |
| 175 | + struct |
| 176 | + { |
| 177 | + // For cheat |
| 178 | + u32* _flagsPointer; |
| 179 | + const void* _cheatData; |
| 180 | + u32 _cheatDataLength; |
| 181 | + }; |
| 182 | + struct |
| 183 | + { |
| 184 | + // For category |
| 185 | + bool _isMaxOneCheatActive; |
| 186 | + CheatEntry* _subEntries; |
| 187 | + u32 _numberOfSubEntries; |
| 188 | + }; |
| 189 | + }; |
| 190 | +}; |
0 commit comments