#ifndef CS2_CHEAT_MEMORY_HPP #define CS2_CHEAT_MEMORY_HPP #include #include #include #include #include namespace Core::Memory { struct Address_t { constexpr Address_t() noexcept = default; constexpr ~Address_t() noexcept = default; explicit constexpr Address_t(std::uintptr_t uAddress) noexcept : m_uAddress(uAddress) { } explicit Address_t(const void* pAddress) noexcept : m_uAddress(reinterpret_cast(pAddress)) { } constexpr operator std::uintptr_t() const noexcept { return m_uAddress; } constexpr operator bool() const noexcept { return m_uAddress; } operator void* () const noexcept { return reinterpret_cast(m_uAddress); } template< typename tReturn = Address_t > [[nodiscard]] constexpr tReturn Offset(std::ptrdiff_t iOffset) const noexcept { return tReturn(m_uAddress + iOffset); } template< typename tReturn = Address_t > [[nodiscard]] inline tReturn Get(std::uint32_t iDereferenceCount = 1) const noexcept { std::uintptr_t uOutAddress = m_uAddress; while (iDereferenceCount-- && uOutAddress) uOutAddress = *reinterpret_cast(uOutAddress); return tReturn(uOutAddress); } template< typename tReturn = Address_t > [[nodiscard]] inline tReturn Jump(std::ptrdiff_t iOffset = 0x1) const noexcept { std::uintptr_t uOutAddress = m_uAddress + iOffset; uOutAddress += *reinterpret_cast(uOutAddress); // @note / xnxkzeu: those could be negative. uOutAddress += 4; return tReturn(uOutAddress); } template< typename tReturn = std::uintptr_t > [[nodiscard]] constexpr tReturn Cast() const noexcept { return tReturn(m_uAddress); } private: std::uintptr_t m_uAddress = { }; }; [[nodiscard]] Address_t GetModuleBaseAddress(std::string_view szModuleName) noexcept; [[nodiscard]] Address_t GetModuleBaseAddress(std::wstring_view szModuleName) noexcept; [[nodiscard]] Address_t GetExportAddress(Address_t uModuleBaseAddress, std::string_view szProcedureName) noexcept; [[nodiscard]] bool GetSectionInfo(Address_t uModuleAddress, std::string_view szSectionName, Address_t* pOutSectionAddress, std::size_t* pOutSectionSize) noexcept; [[nodiscard]] Address_t FindPattern(std::string_view szModuleName, std::string_view szPattern) noexcept; [[nodiscard]] Address_t FindPattern(Address_t uRegionAddress, std::size_t uRegionSize, std::string_view szPattern) noexcept; [[nodiscard]] std::vector< std::optional< std::byte > > PatternToBytes(std::string_view szPattern) noexcept; template< typename tReturn, std::size_t uIndex, typename... tArgs > constexpr inline tReturn CallVFunc(void* pInstance, tArgs... argList) noexcept { using fnVirtual_t = tReturn(__thiscall*)(void*, tArgs...) noexcept; return (*static_cast(pInstance))[uIndex](pInstance, argList...); } } // namespace Core::Memory #define VFUNC( uIndex, fnVirtual, tArgs, tReturn, ... ) \ auto fnVirtual noexcept \ { \ return Core::Memory::CallVFunc< tReturn __VA_OPT__(, ) __VA_ARGS__, uIndex > tArgs; \ } #define OFFSET( iOffset, fnVariable, tReturn, ... ) \ [[nodiscard]] std::add_lvalue_reference_t< tReturn __VA_OPT__(, ) __VA_ARGS__ > fnVariable( ) noexcept \ { \ return *reinterpret_cast< std::add_pointer_t< tReturn __VA_OPT__(, ) __VA_ARGS__ > >( reinterpret_cast< std::uintptr_t >( this ) + iOffset ); \ } \ [[nodiscard]] std::add_lvalue_reference_t< std::add_const_t< tReturn __VA_OPT__(, ) __VA_ARGS__ > > fnVariable( ) const noexcept \ { \ return *reinterpret_cast< std::add_pointer_t< std::add_const_t< tReturn __VA_OPT__(, ) __VA_ARGS__ > > >( reinterpret_cast< std::uintptr_t >( this ) + iOffset ); \ } #endif // CS2_CHEAT_MEMORY_HPP