Initial commit

This commit is contained in:
Pocakking
2019-03-21 20:18:31 +01:00
commit d65c694d22
100 changed files with 95579 additions and 0 deletions

65
src/gta/array.hpp Normal file
View File

@ -0,0 +1,65 @@
#pragma once
#include <cstdint>
#include "fwddec.hpp"
namespace rage
{
template <typename T>
class atArray
{
public:
T *begin()
{
return m_data;
}
T *end()
{
return m_data + m_size;
}
const T *begin() const
{
return m_data;
}
const T *end() const
{
return m_data + m_size;
}
T *data()
{
return m_data;
}
const T *data() const
{
return m_data;
}
std::uint16_t size() const
{
return m_size;
}
std::uint16_t capacity() const
{
return m_capacity;
}
T &operator[](std::uint16_t index)
{
return m_data[index];
}
const T &operator[](std::uint16_t index) const
{
return m_data[index];
}
private:
T *m_data;
std::uint16_t m_size;
std::uint16_t m_capacity;
};
}

18
src/gta/base.hpp Normal file
View File

@ -0,0 +1,18 @@
#pragma once
namespace rage
{
class datBase
{
public:
virtual ~datBase() = default;
};
class pgBase
{
public:
virtual ~pgBase() = default;
private:
void *m_pgunk;
};
}

19
src/gta/color.hpp Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#include <cstdint>
namespace rage
{
struct rgbaColor
{
rgbaColor(std::uint8_t r = 0, std::uint8_t g = 0, std::uint8_t b = 0, std::uint8_t a = 255) :
r(r), g(g), b(b), a(a)
{}
std::uint8_t r;
std::uint8_t g;
std::uint8_t b;
std::uint8_t a;
};
static_assert(sizeof(rgbaColor) == sizeof(std::uint8_t) * 4);
}

7
src/gta/enums.hpp Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#include <cstdint>
enum eGameState : std::uint32_t
{
Playing = 0
};

44
src/gta/extensible.hpp Normal file
View File

@ -0,0 +1,44 @@
#pragma once
#include <cstdint>
#include "ref_aware.hpp"
namespace rage
{
class fwExtension
{
public:
virtual ~fwExtension() = default;
virtual void unk_0x08() = 0;
virtual void unk_0x10() = 0;
virtual std::uint32_t get_id() = 0;
};
class fwExtensionContainer
{
public:
fwExtension *m_entry;
fwExtensionContainer* m_next;
};
class fwExtensibleBase : public fwRefAwareBase
{
public:
virtual bool is_of_type(std::uint32_t hash) = 0;
virtual std::uint32_t const &get_type() = 0;
public:
fwExtensionContainer* m_extension_container; // 0x10
private:
void *m_extensible_unk; // 0x18
public:
template <typename T>
bool is_of_type()
{
static auto name = (typeid(T).name()) + 6; // Skip "class "
static auto name_hash = util::joaat(name);
return is_of_type(name_hash);
}
};
static_assert(sizeof(fwExtensibleBase) == 0x20);
}

68
src/gta/fwddec.hpp Normal file
View File

@ -0,0 +1,68 @@
#pragma once
namespace rage
{
template <typename T>
class atArray;
class datBitBuffer;
class sysMemAllocator;
class scriptIdBase;
class scriptId;
class scriptHandler;
class scriptHandlerNetComponent;
class scriptHandlerObject;
class scriptHandlerMgr;
class scrProgram;
class scrProgramTable;
class scrThreadContext;
class scrThread;
class tlsContext;
class netLoggingInterface;
class netLogStub;
class netPlayer;
class netPlayerMgr;
class netGameEvent;
class netEventMgr;
class netObject;
class netObjectMgrBase;
class scrNativeCallContext;
class scrNativeRegistration;
class scrNativeRegistrationTable;
class fwRefAwareBase;
class fwExtensibleBase;
class fwEntity;
class fwArchetype;
}
class GtaThread;
class CGameScriptId;
class CGameScriptHandler;
class CGameScriptHandlerNetwork;
class CGameScriptHandlerMgr;
class CEntity;
class CDynamicEntity;
class CPhysical;
class CPed;
class CVehicle;
class CObject;
class CPickup;
class CPedFactory;
class CVehicleFactory;
class CNetGamePlayer;
class CNetworkPlayerMgr;
class CPlayerInfo;

84
src/gta/joaat.hpp Normal file
View File

@ -0,0 +1,84 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <string_view>
#include <type_traits>
namespace rage
{
using joaat_t = std::uint32_t;
inline constexpr char joaat_to_lower(char c)
{
return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
}
template <std::size_t CharCount>
struct constexpr_joaat
{
char data[CharCount];
template <std::size_t... Indices>
constexpr constexpr_joaat(const char *str, std::index_sequence<Indices...>) :
data{ (str[Indices])... }
{
}
constexpr joaat_t operator()()
{
joaat_t hash = 0;
for (std::size_t i = 0; i < CharCount; ++i)
{
hash += joaat_to_lower(data[i]);
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
};
inline joaat_t joaat(std::string_view str)
{
joaat_t hash = 0;
for (char c : str)
{
hash += joaat_to_lower(c);
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
inline joaat_t joaat(const char *str)
{
joaat_t hash = 0;
while (*str)
{
hash += joaat_to_lower(*(str++));
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
}
#define RAGE_JOAAT_IMPL(str) (::rage::constexpr_joaat<sizeof(str) - 1>((str), std::make_index_sequence<sizeof(str) - 1>())())
#define RAGE_JOAAT(str) (std::integral_constant<rage::joaat_t, RAGE_JOAAT_IMPL(str)>::value)

22
src/gta/matrix.hpp Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include "vector.hpp"
namespace rage
{
class matrix4x4
{
public:
union
{
struct
{
vector4 _1;
vector4 _2;
vector4 _3;
vector4 _4;
};
float raw[4 * 4] = {};
};
};
}

89
src/gta/natives.hpp Normal file
View File

@ -0,0 +1,89 @@
#pragma once
#include <cstdint>
#include <utility>
#include "fwddec.hpp"
#include "vector.hpp"
namespace rage
{
class scrNativeCallContext
{
public:
void reset()
{
m_arg_count = 0;
m_data_count = 0;
}
template <typename T>
void push_arg(T &&value)
{
static_assert(sizeof(T) <= sizeof(std::uint64_t));
*reinterpret_cast<std::remove_cv_t<std::remove_reference_t<T>>*>(reinterpret_cast<std::uint64_t*>(m_args) + (m_arg_count++)) = std::forward<T>(value);
}
template <typename T>
T &get_arg(std::size_t index)
{
static_assert(sizeof(T) <= sizeof(std::uint64_t));
return *reinterpret_cast<T*>(reinterpret_cast<std::uint64_t*>(m_args) + index);
}
template <typename T>
void set_arg(std::size_t index, T &&value)
{
static_assert(sizeof(T) <= sizeof(std::uint64_t));
*reinterpret_cast<std::remove_cv_t<std::remove_reference_t<T>>*>(reinterpret_cast<std::uint64_t*>(m_args) + index) = std::forward<T>(value);
}
template <typename T>
T *get_return_value()
{
return reinterpret_cast<T*>(m_return_value);
}
template <typename T>
void set_return_value(T &&value)
{
*reinterpret_cast<std::remove_cv_t<std::remove_reference_t<T>>*>(m_return_value) = std::forward<T>(value);
}
protected:
void *m_return_value;
std::uint32_t m_arg_count;
void *m_args;
std::int32_t m_data_count;
std::uint32_t m_data[48];
};
using scrNativeHash = std::uint64_t;
using scrNativeMapping = std::pair<scrNativeHash, scrNativeHash>;
using scrNativeHandler = void(*)(scrNativeCallContext*);
class scrNativeRegistration;
#pragma pack(push, 1)
class scrNativeRegistrationTable
{
scrNativeRegistration *m_entries[0xFF];
std::uint32_t m_unk;
bool m_initialized;
};
#pragma pack(pop)
static_assert(sizeof(scrNativeCallContext) == 0xE0);
}
using Void = void;
using Any = std::uint32_t;
using Hash = std::uint32_t;
using Entity = std::int32_t;
using Player = std::int32_t;
using Ped = Entity;
using Vehicle = Entity;
using Cam = std::int32_t;
using Object = Entity;
using Pickup = Object;
using Blip = std::int32_t;
using Camera = Entity;
using ScrHandle = Entity;
using Vector3 = rage::scrVector;

View File

@ -0,0 +1,58 @@
#pragma once
#include <cstdint>
#include "fwddec.hpp"
#pragma pack(push, 1)
namespace rage
{
class netGameEvent
{
public:
virtual ~netGameEvent() = default;
virtual const char *get_name() const = 0;
virtual bool is_applicable_to_player(netPlayer *player) = 0;
virtual bool time_to_resend(std::uint32_t time) = 0;
virtual bool needs_reply() = 0;
virtual void serialize(datBitBuffer *buffer, netPlayer* source_player, netPlayer* target_player) = 0;
virtual void deserialize(datBitBuffer *buffer, netPlayer* source_player, netPlayer* target_player) = 0;
virtual bool handle(netPlayer* source_player, netPlayer* target_player) = 0;
virtual void deserialize_reply(datBitBuffer *buffer, netPlayer* reply_player) = 0;
virtual void serialize_reply(datBitBuffer *buffer, netPlayer* souce_player) = 0;
virtual void deserialize_extra_data(datBitBuffer *buffer, bool is_reply, netPlayer *player, netPlayer *player2) = 0;
virtual void serialize_extra_data(datBitBuffer *buffer, bool is_reply, netPlayer *player, netPlayer *player2) = 0;
virtual void _0x60() = 0;
virtual void _0x68() = 0;
virtual void _0x70() = 0;
virtual void _0x78() = 0;
virtual bool operator==(netGameEvent const& other) = 0;
virtual bool operator!=(netGameEvent const& other) = 0;
virtual bool must_persist() = 0;
virtual bool must_persist_when_out_of_scope() = 0;
virtual bool has_timed_out() = 0;
public:
std::uint16_t m_id; // 0x08
bool m_requires_reply; // 0x0A
private:
char m_padding1[0x05]; // 0x0B
public:
netPlayer* m_source_player; // 0x10
netPlayer* m_target_player; // 0x18
std::uint32_t m_resend_time; // 0x20
std::uint16_t m_0x24; // 0x24
std::uint8_t m_0x26; // 0x26
std::uint8_t m_0x27; // 0x27
std::uint32_t m_0x28; // 0x28
char m_padding2[0x04]; // 0x2C
};
static_assert(sizeof(netGameEvent) == 0x30);
}
#pragma pack(pop)

23
src/gta/node_list.hpp Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#include "fwddec.hpp"
#include "base.hpp"
namespace rage
{
template <typename T, typename Base = datBase>
class atDNode : public Base
{
public:
T m_data;
void *m_unk;
atDNode<T, Base> *m_next;
};
template <typename Node>
class atDList
{
public:
Node *m_head;
Node *m_tail;
};
}

18
src/gta/ped_factory.hpp Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include "fwddec.hpp"
#pragma pack(push, 1)
class CPed
{
public:
char m_padding[0x10B8];
CPlayerInfo *m_playerinfo;
};
#pragma pack(pop)
class CPedFactory
{
public:
virtual ~CPedFactory() = default;
CPed *m_local_ped;
};

112
src/gta/player.hpp Normal file
View File

@ -0,0 +1,112 @@
#pragma once
#include <cstdint>
#include "fwddec.hpp"
#include "extensible.hpp"
#include "vector.hpp"
#pragma pack(push, 1)
namespace rage
{
# pragma warning(push)
# pragma warning(disable : 4201) // nonstandard extension used: nameless struct/union
union netAddress
{
std::uint32_t m_raw;
struct
{
std::uint8_t m_field4;
std::uint8_t m_field3;
std::uint8_t m_field2;
std::uint8_t m_field1;
};
};
# pragma warning(pop)
class netPlayerData
{
public:
std::uint64_t m_unk1; // 0x00
std::uint64_t m_unk2; // 0x08
std::uint32_t m_sec_key_time; // 0x10
netAddress m_lan_ip; // 0x14
std::uint16_t m_lan_port; // 0x18
char m_pad1[0x02]; // 0x1A
netAddress m_relay_ip; // 0x1C
std::uint16_t m_relay_port; // 0x20
char m_pad2[0x02]; // 0x22
netAddress m_online_ip; // 0x24
std::uint16_t m_online_port; // 0x26
char m_pad3[0x1E]; // 0x28
std::uint64_t m_rockstar_id; // 0x48
bool m_id_flag; // 0x50
char m_pad4[0x0B]; // 0x51
char m_name[0x14]; // 0x5C
};
class nonPhysicalPlayerDataBase
{
public:
virtual ~nonPhysicalPlayerDataBase() = default; // 0 (0x00)
virtual void unk_0x08() = 0; // 1 (0x08)
virtual void unk_0x10() = 0; // 2 (0x10)
virtual void unk_0x18() = 0; // 3 (0x18)
virtual void log(netLoggingInterface* logger) = 0; // 4 (0x20)
};
class netPlayer
{
public:
virtual ~netPlayer() = default; // 0 (0x00)
virtual void reset() = 0; // 1 (0x08)
virtual bool is_valid() const = 0; // 2 (0x10)
virtual const char *get_name() const = 0; // 3 (0x18)
virtual void _0x20() = 0; // 4 (0x20)
virtual bool is_host() = 0; // 5 (0x28)
virtual netPlayerData *get_net_data() = 0; // 6 (0x30)
virtual void _0x38() = 0; // 7 (0x38)
};
class netPlayerMgrBase
{
public:
virtual ~netPlayerMgrBase() = default; // 0 (0x00)
};
}
namespace gta
{
inline constexpr auto num_players = 32;
}
class CNonPhysicalPlayerData : public rage::nonPhysicalPlayerDataBase
{
public:
std::int32_t m_bubble_id; // 0x08
std::int32_t m_player_id; // 0x0C
rage::vector3 m_position; // 0x10
};
class CNetGamePlayer : public rage::netPlayer
{
public:
};
class CWantedData
{
public:
char m_padding[0x98];
std::int32_t m_wanted_level;
};
class CPlayerInfo : public rage::fwExtensibleBase
{
public:
char m_padding1[0x1D8]; // 0x20
std::uint32_t m_frame_flags; // 0x1F8
char m_padding2[0x584]; // 0x1FC
CWantedData m_wanted_data; // 0x780
};
static_assert(sizeof(CNonPhysicalPlayerData) == 0x1C);
#pragma pack(pop)

18
src/gta/ref_aware.hpp Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include "base.hpp"
namespace rage
{
template <typename T>
class fwRefAwareBaseImpl : public T
{
private:
void *m_ref; // 0x08
};
class fwRefAwareBase : public fwRefAwareBaseImpl<datBase>
{
};
static_assert(sizeof(fwRefAwareBase) == 0x10);
}

185
src/gta/script_handler.hpp Normal file
View File

@ -0,0 +1,185 @@
#pragma once
#include <cstdint>
#include "fwddec.hpp"
#include "node_list.hpp"
#include "script_id.hpp"
#pragma pack(push, 1)
namespace rage
{
class scriptResource
{
public:
virtual ~scriptResource() = default;
};
class scriptResourceEntry
{
public:
scriptResource *m_data; // 0x00
std::uint32_t m_unk; // 0x04
char m_padding[0x0C]; // 0x0C
scriptResourceEntry *m_next; // 0x18
};
class scriptHandlerNetComponent
{
public:
virtual ~scriptHandlerNetComponent() = default;
public:
scriptHandler *m_script_handler; // 0x08
};
class scriptHandler
{
public:
class atDScriptObjectNode : public atDNode<scriptHandlerObject*>
{
};
public:
virtual ~scriptHandler() = default; // 0 (0x00)
virtual bool _0x08() = 0; // 1 (0x08)
virtual void _0x10() = 0; // 2 (0x10)
virtual void cleanup_objects() = 0; // 3 (0x18)
virtual scriptId *_0x20() = 0; // 4 (0x20)
virtual scriptId *get_id() = 0; // 5 (0x28)
// Returns whether the script handler belongs to a networked script.
virtual bool is_networked() = 0; // 6 (0x30)
// Initializes the network component for the script handler.
virtual void init_net_component() = 0; // 7 (0x38)
// Deletes the script handler's network component, if it exists.
virtual void reset_net_component() = 0; // 8 (0x40)
// Destroys the script handler.
virtual bool destroy() = 0; // 9 (0x48)
// Adds the object to the script handler's list of objects.
virtual void add_object(scriptHandlerObject*, bool is_network, bool is_network_and_scriptcheck) = 0; // 10 (0x50)
// Something related to reservations.
virtual void _0x58(void*) = 0; // 11 (0x58)
virtual void register_resource(scriptResource*, void*) = 0; // 12 (0x60)
virtual void _0x68() = 0; // 13 (0x68)
virtual void _0x70() = 0; // 14 (0x70)
virtual void _0x78() = 0; // 15 (0x78)
virtual void _0x80() = 0; // 16 (0x80)
virtual void _0x88() = 0; // 17 (0x88)
virtual void _0x90() = 0; // 18 (0x90)
virtual void _0x98() = 0; // 19 (0x98)
public:
void *m_0x08; // 0x08
void *m_0x10; // 0x10
scrThread *m_script_thread; // 0x18
atDList<atDScriptObjectNode> m_objects; // 0x20
scriptResource *m_resource_list_head; // 0x30
scriptResource *m_resource_list_tail; // 0x38
void *m_0x40; // 0x40
scriptHandlerNetComponent *m_net_component; // 0x48
std::uint32_t m_0x50; // 0x50
std::uint32_t m_0x54; // 0x54
std::uint32_t m_0x58; // 0x58
std::uint32_t m_0x60; // 0x5C
};
class scriptHandlerMgr
{
public:
virtual ~scriptHandlerMgr() = default;
// Initializes some scripting-related pools.
virtual bool initialize() = 0; // 1 (0x08)
// Called every tick.
virtual void _0x10() = 0; // 2 (0x10)
// Frees some scripting-related pools.
virtual void shutdown() = 0; // 3 (0x18)
virtual void _0x20() = 0; // 4 (0x20)
virtual void _0x28() = 0; // 5 (0x28)
virtual void _0x30() = 0; // 6 (0x30)
// Generates a rage::scriptId from the thread and copies it over to a global structure.
virtual void _0x38(scrThread*) = 0; // 7 (0x38)
// Allocates and constructs a script handler.
virtual scriptHandler *create_script_handler() = 0; // 8 (0x40)
// Finds the script handler for a given script id.
virtual scriptHandler *get_script_handler(scriptId*) = 0; // 9 (0x48)
// Attaches a script thread.
virtual void attach_thread(scrThread*) = 0; // 10 (0x50)
// Detaches a script thread.
virtual void detach_thread(scrThread*) = 0; // 11 (0x58)
// Called when a player joins.
virtual void on_player_join(netPlayer*) = 0; // 12 (0x60)
// Called when a player leaves.
virtual void on_player_left(netPlayer*) = 0; // 13 (0x68)
virtual std::int32_t _0x70() = 0; // 14 (0x70)
virtual void *_0x78() = 0; // 15 (0x78)
public:
char m_padding1[0x28]; // 0x08
bool m_initialized; // 0x30
bool m_initialized2; // 0x31
char m_padding2[0x0E]; // 0x32
rage::netLoggingInterface *m_logger; // 0x40
};
}
class CGameScriptHandler : public rage::scriptHandler
{
public:
CGameScriptId m_script_id; // 0x60
};
class CGameScriptHandlerNetwork : public CGameScriptHandler
{
public:
std::uint8_t m_0xA0; // 0xA0
std::uint8_t m_0xA1; // 0xA1
std::uint8_t m_0xA2; // 0xA2
std::uint8_t m_0xA3; // 0xA3
std::uint8_t m_num_players; // 0xA4
std::uint8_t m_0xA5; // 0xA5
std::uint8_t m_0xA6; // 0xA6
std::uint8_t m_0xA7; // 0xA7
std::uint8_t m_0xA8; // 0xA8
std::uint8_t m_0xA9; // 0xA9
std::uint8_t m_0xAA; // 0xAA
std::uint8_t m_0xAB; // 0xAB
std::uint8_t m_0xAC; // 0xAC
std::uint8_t m_0xAD; // 0xAD
std::uint8_t m_0xAE; // 0xAE
std::uint8_t m_0xAF; // 0xAF
};
class CGameScriptHandlerMgr : public rage::scriptHandlerMgr
{
};
static_assert(sizeof(rage::scriptHandler) == 0x60);
static_assert(sizeof(CGameScriptHandler) == 0xA0);
static_assert(sizeof(CGameScriptHandlerNetwork) == 0xB0);
#pragma pack(pop)

72
src/gta/script_id.hpp Normal file
View File

@ -0,0 +1,72 @@
#pragma once
#include <cstdint>
#include "fwddec.hpp"
#include "joaat.hpp"
#pragma pack(push, 1)
namespace rage
{
class scriptIdBase
{
public:
virtual ~scriptIdBase() = default; // 0 (0x00)
// Assumes the script thread's identity.
virtual void assume_thread_identity(scrThread*) {}; // 1 (0x08)
// Returns whether the hash of the script id is valid.
virtual bool is_valid() {}; // 2 (0x10)
// Gets the hash of the script id.
virtual joaat_t *get_hash(joaat_t *out) {}; // 3 (0x18)
// Gets an unknown value from the script id.
virtual std::uint32_t *get_hash2(std::uint32_t *out) {}; // 4 (0x20)
// Gets the name of the script id.
virtual const char *get_name() {}; // 5 (0x28)
// Serializes the script id from the buffer.
virtual void deserialize(datBitBuffer* buffer) {}; // 6 (0x30)
// Serializes the script id to the buffer.
virtual void serialize(datBitBuffer* buffer) {}; // 7 (0x38)
// Calculates some information with the position hash & instance id.
virtual std::uint32_t _0x40() {}; // 8 (0x40)
// Calls _0x40 and returns it's value added to another value.
virtual std::uint32_t _0x48() {}; // 9 (0x48)
// Logs some information about the script id.
virtual void log_information(netLoggingInterface* logger) {}; // 10 (0x50)
// Copies the information of other to this object.
virtual void copy_data(scriptIdBase *other) {} // 11 (0x58)
// Returns whether the other script id is equal.
virtual bool operator==(scriptIdBase*) {}; // 12 (0x60)
virtual bool _0x68(void*) {}; // 13 (0x68)
};
class scriptId : public scriptIdBase
{
public:
joaat_t m_hash; // 0x08
char m_name[0x20]; // 0x0C
};
}
class CGameScriptId : public rage::scriptId
{
public:
char m_padding[0x04]; // 0x2C
std::int32_t m_timestamp; // 0x30
std::int32_t m_position_hash; // 0x34
std::int32_t m_instance_id; // 0x38
std::int32_t m_unk; // 0x3C
};
static_assert(sizeof(CGameScriptId) == 0x40);
#pragma pack(pop)

145
src/gta/script_program.hpp Normal file
View File

@ -0,0 +1,145 @@
#pragma once
#include <cstdint>
#include "fwddec.hpp"
#include "base.hpp"
#include "joaat.hpp"
#include "script_id.hpp"
#pragma pack(push, 1)
namespace rage
{
class scrProgram : public pgBase
{
public:
std::uint8_t** m_code_blocks; // 0x10
std::uint32_t m_hash; // 0x18
std::uint32_t m_code_size; // 0x1C
std::uint32_t m_arg_count; // 0x20
std::uint32_t m_local_count; // 0x24
std::uint32_t m_global_count; // 0x28
std::uint32_t m_native_count; // 0x2C
void *m_local_data; // 0x30
std::int64_t **m_global_data; // 0x38
void **m_native_entrypoints; // 0x40
char m_padding6[0x10]; // 0x48
std::uint32_t m_name_hash; // 0x58
char m_padding7[0x04]; // 0x5C
const char* m_name; // 0x60
const char** m_strings_data; // 0x68
std::uint32_t m_strings_count; // 0x70
char m_padding8[0x0C]; // 0x74
bool is_valid() const
{
return m_code_size != 0;
}
std::uint32_t get_num_code_pages() const
{
return (m_code_size + 0x3FFF) >> 14;
}
std::uint32_t get_code_page_size(std::uint32_t page) const
{
auto num = get_num_code_pages();
if (page < num)
{
if (page == num - 1)
return m_code_size & 0x3FFF;
return 0x4000;
}
return 0;
}
std::uint32_t get_full_code_size() const
{
auto numPages = get_num_code_pages();
if (!numPages)
return 0;
if (numPages == 1)
--numPages;
return (numPages * 0x4000) + (m_code_size & 0x3FFF);
}
std::uint8_t* get_code_page(std::uint32_t page) const
{
return m_code_blocks[page];
}
std::uint8_t* get_code_address(std::uint32_t index) const
{
if (index < m_code_size)
return &m_code_blocks[index >> 14][index & 0x3FFF];
return nullptr;
}
const char* get_string(std::uint32_t index) const
{
if (index < m_strings_count)
return &m_strings_data[index >> 14][index & 0x3FFF];
return nullptr;
}
void** get_address_of_native_entrypoint(void* entrypoint)
{
for (std::uint32_t i = 0; i < m_native_count; ++i)
{
if (m_native_entrypoints[i] == entrypoint)
{
return m_native_entrypoints + i;
}
}
return nullptr;
}
};
class scrProgramTableEntry
{
public:
scrProgram* m_program; // 0x00
char m_Pad1[0x04]; // 0x08
joaat_t m_hash; // 0x0C
};
class scrProgramTable
{
public:
scrProgramTableEntry* m_data; // 0x00
char m_padding[0x10]; // 0x08
std::uint32_t m_size; // 0x18
scrProgram* find_script(joaat_t hash)
{
for (std::uint32_t i = 0; i < m_size; ++i)
{
if (m_data[i].m_hash == hash)
{
return m_data[i].m_program;
}
}
return nullptr;
}
scrProgramTableEntry* begin()
{
return m_data;
}
scrProgramTableEntry* end()
{
return m_data + m_size;
}
};
static_assert(sizeof(scrProgram) == 0x80);
static_assert(sizeof(scrProgramTableEntry) == 0x10);
static_assert(sizeof(scrProgramTable) == 0x1C);
}
#pragma pack(pop)

83
src/gta/script_thread.hpp Normal file
View File

@ -0,0 +1,83 @@
#pragma once
#include <cstdint>
#include "fwddec.hpp"
#include "joaat.hpp"
#include "tls_context.hpp"
namespace rage
{
enum class eThreadState : std::uint32_t
{
idle,
running,
killed,
unk_3,
unk_4,
};
class scrThreadContext
{
public:
std::uint32_t m_thread_id; // 0x00
joaat_t m_script_hash; // 0x04
eThreadState m_state; // 0x08
std::uint32_t m_instruction_pointer; // 0x0C
std::uint32_t m_frame_pointer; // 0x10
std::uint32_t m_stack_pointer; // 0x14
float m_timer_a; // 0x18
float m_timer_b; // 0x1C
float m_timer_c; // 0x20
char m_padding1[0x2C]; // 0x24
std::uint32_t m_stack_size; // 0x50
char m_padding2[0x54]; // 0x54
static scrThread *get()
{
return rage::tlsContext::get()->m_script_thread;
}
};
class scrThread
{
public:
virtual ~scrThread() = default; // 0 (0x00)
virtual eThreadState reset(std::uint32_t script_hash, void *args, std::uint32_t arg_count) = 0; // 1 (0x08)
virtual eThreadState run() = 0; // 2 (0x10)
virtual eThreadState tick(std::uint32_t ops_to_execute) = 0; // 3 (0x18)
virtual void kill() = 0; // 4 (0x20)
public:
scrThreadContext m_context; // 0x08
void *m_stack; // 0xB0
char m_padding[0x10]; // 0xB8
const char *m_exit_message; // 0xC8
char m_name[0x40]; // 0xD0
scriptHandler *m_handler; // 0x110
scriptHandlerNetComponent *m_net_component; // 0x118
};
static_assert(sizeof(scrThreadContext) == 0xA8);
static_assert(sizeof(scrThread) == 0x120);
}
class GtaThread : public rage::scrThread
{
public:
rage::joaat_t m_script_hash; // 0x120
char m_padding3[0x14]; // 0x124
std::int32_t m_instance_id; // 0x138
char m_padding4[0x04]; // 0x13C
std::uint8_t m_flag1; // 0x140
bool m_safe_for_network_game; // 0x141
char m_padding5[0x05]; // 0x142
bool m_can_be_paused; // 0x147
bool m_can_remove_blips_from_other_scripts; // 0x148
char m_padding6[0x0F]; // 0x149
};
enum
{
auejk = FIELD_OFFSET(GtaThread, m_can_be_paused),
s9tifgjwkosmldxc = sizeof(GtaThread)
};
static_assert(sizeof(GtaThread) == 0x158);

23
src/gta/tls_context.hpp Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#include <intrin.h>
#include "fwddec.hpp"
namespace rage
{
class tlsContext
{
public:
char m_padding1[0xC8]; // 0x00
sysMemAllocator *m_allocator; // 0xC8
char m_padding2[0x760]; // 0xD0
scrThread *m_script_thread; // 0x830
bool m_is_script_thread_active; // 0x838
static tlsContext *get()
{
return *reinterpret_cast<tlsContext**>(__readgsqword(0x58));
}
};
static_assert(sizeof(tlsContext) == 0x840);
}

49
src/gta/vector.hpp Normal file
View File

@ -0,0 +1,49 @@
#pragma once
namespace rage
{
struct vector2
{
float x{};
float y{};
};
struct vector3
{
float x{};
float y{};
float z{};
};
struct vector4
{
float x{};
float y{};
float z{};
float w{};
};
#pragma pack(push, 1)
class scrVector
{
public:
scrVector() = default;
scrVector(float x, float y, float z) :
x(x), y(y), z(z)
{}
public:
float x{};
private:
char m_padding1[0x04];
public:
float y{};
private:
char m_padding2[0x04];
public:
float z{};
private:
char m_padding3[0x04];
};
#pragma pack(pop)
}