A library to create mods for REDengine 4 (Cyberpunk 2077), independently of RED4ext.

Overview

RED4ext.SDK

A library to create mods for REDengine 4 (Cyberpunk 2077).

What is this library?

RED4ext.SDK is a library that extends REDengine 4. It will allow modders to add new features, modify the game behavior, add new scripting functions or call existing ones in your own mods.

This library is similar to:

Usage

Header only version

Include the header files in your project and use a C++17 compiler.

Static library version

Add the header files and the source files to your project, define RED4EXT_STATIC_LIB and use a C++17 compiler.

Build instructions

  1. Download and install Visual Studio 2019 Community Edition or a higher version.
  2. Clone this repository.
  3. Go to the premake directory and run generate_projects.bat.
  4. Open the solution (RED4ext.SDK.sln) located in projects directory.
  5. Build the projects.

Contributing

Do you want to contribute? Community feedback and contributions are highly appreciated!

For general rules and guidelines see CONTRIBUTING.md.

Comments
  • Background jobs and callbacks

    Background jobs and callbacks

    • Added support for callbacks
    auto loader = RED4ext::ResourceLoader::Get();
    auto token = loader->LoadAsync(R"(base\vehicles\sport\v_sport1_herrera_outlaw_basic_01.ent)");
    token->OnLoaded([](RED4ext::Handle<RED4ext::CResource>& aResource) {
        Log("Resource is loaded");
    });
    
    auto rtti = RED4ext::CRTTISystem::Get();
    rtti->AddRegisterCallback([&rtti] {
        Log("RTTI Type Registration");
    });
    
    • Added support for background jobs
    auto loader = RED4ext::ResourceLoader::Get();
    auto token = loader->LoadAsync(R"(base\vehicles\sport\v_sport1_herrera_outlaw_basic_01.ent)");
    {
        RED4ext::JobQueue queue; // Jobs in one queue are sequential
        queue.Dispatch([]{ Log("Job A-1"); });
        queue.Dispatch([]{ Log("Job A-2"); });
        queue.Dispatch([]{ Log("Job A-3"); });
        Log("Checkpoint A");
    }
    {
        RED4ext::JobQueue queue;
        queue.Dispatch([]{ Log("Job B-1"); });
        queue.Wait(token->job); // Suspends jobs in the queue
        queue.Dispatch([]{ Log("Job B-2"); });
        queue.Dispatch([]{ Log("Job B-3"); });
        Log("Checkpoint B");
    }
    
    [0.420] Checkpoint A
    [0.420] Job A-1
    [0.420] Job B-1 <-- job can start immediately, even before checkpoint B
    [0.420] Checkpoint B
    [0.420] Job A-2
    [0.420] Job A-3 <-- all previous jobs executed at the same timestamp
    [0.462] Job B-2 <-- continues when the resource is ready
    [0.462] Job B-3
    
    • Refactored memory utils and resource references
    opened by psiberx 2
  • TweakDB and some other small things

    TweakDB and some other small things

    • Fixed Hashmap

    1. [Removed] HashMapBase was missing a u64 allocator at the end
    2. [Fixed] HashMap had an extra u64 at the beginning which should have been at the end
    3. Adjusted offsets in classes/structs that used HashMap and HashMapBase
    4. Added HashMap::GetAllocator()
    5. Added custom hasher to HashMap<Key, Value, Hasher>. defaults to casting to u32 if possible

    • TweakDB

    Currently missing 2 classes for unk08 and unk10, will do them eventually if they're useful Experimental design, any changes are welcome :)

    auto* tdb = TweakDB::Get();
    
    // Read
    {
      TweakDBID dbid;
      dbid.name_hash = 0x68D39470;
      dbid.name_length = 52;
      auto* unitCount = tdb->GetVal<int32_t>(dbid);
      printf("unitsCount: %d\n", *unitCount);
    }
    
    // Read - 2
    {
      TweakDBID dbid;
      dbid.name_hash = 0x68D39470;
      dbid.name_length = 52;
      auto* tweakVal = tdb->GetTweakVal(dbid);
      IRTTIType* rttiType = tweakVal->type;
      auto* unitCount = (int32_t*)tweakVal->value;
      printf("unitsCount: %d\n", *unitCount);
    }
    
    // Write
    {
      TweakDBID dbid;
      dbid.name_hash = 0x68D39470;
      dbid.name_length = 52;
      auto* tweakVal = tdb->GetTweakVal(dbid);
      if (tweakVal == nullptr)
      {
        puts("tweakVal was null");
        return;
      }
      int newUnitCount = 10;
      tweakVal->SetValue(&newUnitCount); // Or you can pass CStackType which will do "IsExact" type checking
    }
    
    // tdb->GetRecord(...)
    // tdb->GetRecordsByType(...)
    // tdb->GetPackage(...)
    

    • Other

    1. Added begin/end to DynArray as a QoL to allow range based iteration
    2. Renamed some fields in TweakDBID, added a union and some operators
    3. Added script_ref type for scripting
    opened by 0xSombra 2
  • Resource depot and small fixes

    Resource depot and small fixes

    • Added resource depot
    • Renamed AllocInstance to CreateInstance
    • Added proper IScriptable ctor (value holder pointer can be garbage instead of nullptr depending on how the instance was allocated or initialized, which could cause a crash in dtor since we destroy the value holder now)
    opened by psiberx 1
  • Various updates

    Various updates

    • Properly release value holder for owned IScriptables
    • Decoded some CBaseEngine and ISerializable properties
    • Decoded event listeners for CClass
    • Decoded default values for CClass
    • Added new scripting related functions to CClass
    • Updated CProperty flags
    opened by psiberx 1
  • Small fixes

    Small fixes

    • Added missing RED4EXT_INLINE specifiers
    • Fixed return value of SortedArray::Merge()
    • Adjusted memory concepts to be more accurate (and for better clang compatibility)
    opened by psiberx 1
  • Optimized sorted array merging

    Optimized sorted array merging

    The main reason for this optimization is editing TweakDB. Flats are stored in a sorted unique array with over 2M entries. Flat insertion is expensive and adds up quickly when creating/cloning records with many properties.

    The new method allows batch insertions. The bigger the batch, the bigger the gain.

    | N of insertions | Avg. boost | |---|---| | 10 | 8x | | 100 | 25x | | 1000 | 170x |

    With this optimization applied to creating/cloning records, a real mod that adds items shows around 20x faster load times (each item record has 80-110 properties).

    opened by psiberx 1
  • Scripting and resource improvements

    Scripting and resource improvements

    • Add ResourcePath with sanitations
    • Decode more ResourceReference and ResourceAsyncReference
    • Decode more CStackFrame
    • Update GetParameter helper so it can be used for "out" params (gives direct ptr to the scripted value so that it can be modified from native function)
    • Decode some IRTTISystem members
    • Fix CEnum members
    opened by psiberx 1
  • Native func support

    Native func support

    Added a hook to the RTTIRegistrator constructor to add callback functions that are called before the final.redscripts is loaded, allowing for new native methods to be defined in RED4ext and called from Redscript.

    RTTIRegistrator::Add() can be called immediately after the dll attaches:

    RED4EXT_C_EXPORT void RED4EXT_CALL RegisterTypes() {}
    RED4EXT_C_EXPORT void RED4EXT_CALL PostRegisterTypes() {}
    
    BOOL APIENTRY DllMain(HMODULE aModule, DWORD aReason, LPVOID aReserved)
    {
        switch (aReason)
        {
        case DLL_PROCESS_ATTACH:
            DisableThreadLibraryCalls(aModule);
            RED4ext::RTTIRegistrator::Add(RegisterTypes, PostRegisterTypes);
            break;
        }
    
        return TRUE;
    }
    

    Also fleshed out one of the unknown chunks in the CBaseFunction class: a DataBuffer to the compiled redscript bytecode

    opened by flibX0r 1
  • Added some Get methods to RTTISystem

    Added some Get methods to RTTISystem

    Filled out several of the RTTISystem methods that return lists of specific types.

    The Enum and Bitfield variants take a boolean that checks the first bit of their flags byte, which filters whether they are scripted or native. I've tested that it works that way for Enums, but Bitfields are only implemented as native code and the redscript compiler doesn't currently support bitfields, so it's purely conjecture on my part (they are treated identically though).

    There are a few differences between IRTTISystem::GetClasses() and IRTTISystem::GetDerivedClasses():

    • GetClasses() will call CClass::IsA(aIsAClass) on each class if aIsAClass is not null.
    • GetClasses() has an optional filter function that is called on each matching class
    • GetDerivedClasses() will check each class to see if class.parent == aBaseClass
    opened by flibX0r 1
  • Improve Variant

    Improve Variant

    Modified structure according to what was discussed before. Added some extra checks in regards to placement of things.

    These should be working ToVariant/FromVariant functions we have in CET, needs testing... I could include them if you want, just tell me where to put them and I'll remake them for this x)

        aLuaGlobal["ToVariant"] = [this](Type& aInstance) -> sol::object {
            auto* pType = aInstance.GetType();
            auto* pHandle = aInstance.GetHandle();
    
            if (!pType || !pHandle)
                return sol::nil;
    
            auto lockedState = m_lua.Lock();
            auto& luaState = lockedState.Get();
    
            return sol::object(luaState, sol::in_place, Variant(pType, pHandle));
        };
    
        aLuaGlobal["FromVariant"] = [this](Variant& aVariant) -> sol::object {
            if (aVariant.type == 0)
                return sol::nil;
    
            RED4ext::CStackType result;
            if ((aVariant.type & 1) == 0)
            {
                result.type = reinterpret_cast<RED4ext::IRTTIType*>(aVariant.type); 
                result.value = aVariant.instance;
            }
            else
            {
                result.type = reinterpret_cast<RED4ext::IRTTIType*>(aVariant.type & (~1ull));
                result.value = &aVariant.inlinedBuf;
            }
    
            auto lockedState = m_lua.Lock();
            
            return Scripting::ToLua(lockedState, result);
        };
    
    opened by WSSDude 1
  • Define Variant structure

    Define Variant structure

    We had Variant known in CET for some time... Trying to get rid of local CET definitions of same things.

    Dont know if this is correct for you or not, but this should be it for Variant x)

    opened by WSSDude 1
  • Generate methods for script classes

    Generate methods for script classes

    Is your feature request related to a problem? Please describe. Currently the methods are missing from the auto generated classes. The only way to call those methods currently are using ExecuteFunction.

    Describe the solution you'd like See https://gist.github.com/martonp96/bf93a51d07da27caf065cc5ea2e1a853 or the discussion on discord https://discord.com/channels/717692382849663036/839400251680227339/1033367170979217438

    Describe alternatives you've considered I'm using manually created wrapper classes.

    enhancement 
    opened by martonp96 0
  • Zoltan typedefs

    Zoltan typedefs

    this is just a demo header that can be used with zoltan clang frontend the command to run on this is:

    zoltan-clang '.\include\RED4ext\Typedefs.hpp' 'C:\Games\Cyberpunk 2077\bin\x64\Cyberpunk2077.exe' -f 'std=c++20' -f 'I.\include' --dwarf-output '.\debug-symbols' --c-output '.\addresses.h'
    

    it generates a header with addresses like:

    #define CBASEFUNCTION_EXECUTE_ADDR 0x140206A70
    #define CGLOBALFUNCTION_CTOR_ADDR 0x140206380
    ...
    

    and symbols that can be loaded into IDA: image

    opened by jac3km4 5
  • Improve pattern finding

    Improve pattern finding

    Is your feature request related to a problem? Please describe. The current pattern finding script only support patterns for function prologues or pointers.

    Describe the solution you'd like An improved version of the pattern finding should support the following additional features:

    • Get the function address from a call instruction
    • Finding virtual function table and getting addresses from it
    enhancement 
    opened by WopsS 0
  • Reverse engineering the scripting events

    Reverse engineering the scripting events

    Is your feature request related to a problem? Please describe. Currently there is no method to hook game event's gamePuppet::OnDamageReceived, gamePuppet::OnHit, etc..

    Describe the solution you'd like The best solution would be to reverse and hook into events natively, without additional dependencies, allowing modders to hook these function from C++.

    Describe alternatives you've considered An alternative to this would be to do like yamashi did it for Cyber Engine Tweaks, but that would require to have additional libraries added as dependencies for the SDK which I would not like to. If there is no other solution than this, a plugin API can be added so that the main loader can take care of hooking.

    enhancement 
    opened by WopsS 1
Owner
Octavian Dima
Octavian Dima
Do u wanna create more than one trial account on exitlag? This 'spoofer' is for you!

ExitLag HWID Bypass Do you wanna create more than one trial account on exitlag? So this 'spoofer' is for you! Why? Exitlag limit the trial account cre

Benjamin 10 Mar 6, 2021
Isocline is a pure C library that can be used as an alternative to the GNU readline library

Isocline: a portable readline alternative. Isocline is a pure C library that can be used as an alternative to the GNU readline library (latest release

Daan 136 Dec 30, 2022
A linux library to get the file path of the currently running shared library. Emulates use of Win32 GetModuleHandleEx/GetModuleFilename.

whereami A linux library to get the file path of the currently running shared library. Emulates use of Win32 GetModuleHandleEx/GetModuleFilename. usag

Blackle Morisanchetto 3 Sep 24, 2022
Command-line arguments parsing library.

argparse argparse - A command line arguments parsing library in C (compatible with C++). Description This module is inspired by parse-options.c (git)

Yecheng Fu 533 Dec 26, 2022
A cross platform C99 library to get cpu features at runtime.

cpu_features A cross-platform C library to retrieve CPU features (such as available instructions) at runtime. Table of Contents Design Rationale Code

Google 2.2k Dec 22, 2022
Library that solves the exact cover problem using Dancing Links, also known as DLX.

The DLX Library The DLX library The DLX library solves instances of the exact cover problem, using Dancing Links (Knuth’s Algorithm X). Also included

Ben Lynn 44 Dec 18, 2022
Standards compliant, fast, secure markdown processing library in C

Hoedown Hoedown is a revived fork of Sundown, the Markdown parser based on the original code of the Upskirt library by Natacha Porté. Features Fully s

Hoedown 923 Dec 27, 2022
CommonMark parsing and rendering library and program in C

cmark cmark is the C reference implementation of CommonMark, a rationalized version of Markdown syntax with a spec. (For the JavaScript reference impl

CommonMark 1.4k Jan 4, 2023
A cross-platform protocol library to communicate with iOS devices

libimobiledevice A library to communicate with services on iOS devices using native protocols. Features libimobiledevice is a cross-platform software

libimobiledevice 5.4k Dec 30, 2022
Platform independent Near Field Communication (NFC) library

*- * Free/Libre Near Field Communication (NFC) library * * Libnfc historical contributors: * Copyright (C) 2009 Roel Verdult * Copyright (C) 2009

null 1.4k Jan 5, 2023
A C library for parsing/normalizing street addresses around the world. Powered by statistical NLP and open geo data.

libpostal: international street address NLP libpostal is a C library for parsing/normalizing street addresses around the world using statistical NLP a

openvenues 3.6k Dec 27, 2022
Your friendly e-mail address validation library.

libvldmail Your friendly e-mail address validation library. Why? Did you know that parentheses, spaces and - according to the RFC 6531 document - emoj

Cthulhux 47 Sep 28, 2022
A protocol buffers library for C

PBC PBC is a google protocol buffers library for C without code generation. Quick Example package tutorial; message Person { required string name =

云风 1.6k Dec 28, 2022
An easy-to-use C library for displaying text progress bars.

What is this thing? progressbar is a C-class (it's a convention, dammit) for displaying attractive progress bars on the command line. It's heavily inf

Trevor Fountain 440 Dec 27, 2022
Library for writing text-based user interfaces

IMPORTANT This library is no longer maintained. It's pretty small if you have a big project that relies on it, just maintain it yourself. Or look for

null 1.9k Dec 22, 2022
Locate the current executable and the current module/library on the file system

Where Am I? A drop-in two files library to locate the current executable and the current module on the file system. Supported platforms: Windows Linux

Gregory Pakosz 382 Dec 27, 2022
A small and portable INI file library with read/write support

minIni minIni is a portable and configurable library for reading and writing ".INI" files. At just below 900 lines of commented source code, minIni tr

Thiadmer Riemersma 293 Dec 29, 2022
Small configuration file parser library for C.

libConfuse Introduction Documentation Examples Build & Install Origin & References Introduction libConfuse is a configuration file parser library writ

null 419 Dec 14, 2022
Libelf is a simple library to read ELF files

libelf Libelf is a simple library which provides functions to read ELF files. Headers #include <stdint.h> #include <elf.h> Structures typedef struct

David du Colombier 44 Aug 7, 2022