Skip to content

Commit

Permalink
0.9.3 release
Browse files Browse the repository at this point in the history
  • Loading branch information
x87 committed Apr 22, 2022
1 parent 59cc45a commit 66687f8
Show file tree
Hide file tree
Showing 15 changed files with 167 additions and 70 deletions.
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,32 @@
### 0.9.3 - Apr 22, 2022

- CLEO can be [embedded](https://re.cleo.li/docs/en/embedding.html) and run on unknown hosts via the self-hosted mode [See demo](https://www.youtube.com/watch?v=rk2LvDt7UkI)
- new installer that automatically downloads extra dependencies such as Ultimate ASI Loader and plugins (dylib, IniFiles, or ImGuiRedux)
- support for organizing scripts and its dependencies in sub-directories inside the CLEO folder. See https://re.cleo.li/docs/en/script-lifecycle.html#organizing-scripts
- automatically download the latest `enums.js` file from Sanny Builder Library along with the command definitions. You can import enums in JS with `import * as enums from './.config/enums';`
- memory access operations can run on an unknown host (previously they had a dependency on the `op` command which itself can only run in GTA games)
- `Memory.CallFunctionReturnFloat` and `Memory.CallMethodReturnFloat` are now available for 32-bit hosts. `CallFunctionReturnFloat` has been previously added for 64-bit hosts.

**SDK AND PLUGINS**
- SDK's method `ResolvePath` now resolves paths starting with `./` or `.\` relative to the script directory. You can use them in commands like `READ_INT_FROM_INI_FILE` or `LOAD_DYNAMIC_LIBRARY`
- new SDK methods `GetHostName`, `SetHostName`, `RuntimeInit`, `RuntimeNextTick`. SDK version is now 2.
- IniFiles plugin updated to 1.2: increased max length of the INI file path
- Dylib plugin updated to 1.1: increased max length of the DLL file path

**BREAKING CHANGES**
- delete previously deprecated command `op`. Use `native` instead.
- rename `GAME` variable to `HOST` (`GAME` is still available for use but it's recommended to update older scripts)

| Game | File | Minimum Required Version |
| ----------------------------------- | ---------------------------------------------------------------------------------------------------- | ------------------------ |
| GTA III, re3 | [gta3.json](https://github.com/sannybuilder/library/blob/master/gta3/gta3.json) | `0.218` |
| GTA VC, reVC | [vc.json](https://github.com/sannybuilder/library/blob/master/vc/vc.json) | `0.220` |
| GTA San Andreas (Classic) 1.0 | [sa.json](https://github.com/sannybuilder/library/blob/master/sa/sa.json) | `0.236` |
| GTA III: The Definitive Edition | [gta3_unreal.json](https://github.com/sannybuilder/library/blob/master/gta3_unreal/gta3_unreal.json) | `0.213` |
| Vice City: The Definitive Edition | [vc_unreal.json](https://github.com/sannybuilder/library/blob/master/vc_unreal/vc_unreal.json) | `0.215` |
| San Andreas: The Definitive Edition | [sa_unreal.json](https://github.com/sannybuilder/library/blob/master/sa_unreal/sa_unreal.json) | `0.220` |


### 0.9.2 - Mar 04, 2022

- add support for The Definitive Edition Title Update 1.04 (GTA III DE 1.0.0.15284, VC DE 1.0.0.15399, SA DE 1.0.0.15483)
Expand Down
26 changes: 2 additions & 24 deletions docs/en/deprecated-bindings.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,6 @@

Usage of the following commands is not recommended.

# op
## GAME

`op(opcode_id, ...input_args)` - a low-level function to execute any in-game command with opcode `{opcode_id}`.

For the commands that return a single value, the result is this value.

For the commands that return multiple values, the result is an object where each key corresponds to a returned value. The key names match the output names given in the command definition

For the conditional commands the result is the boolean value `true` or `false`

```js
op(0x00c0, 12, 30); // sets the time of day to 12:30
```

```js
var pos = op(0x0054, 0); // returns player 0 coordinates vector {x, y, z}
showTextBox("Player pos:", " x = ", pos.x, " y = ", pos.y, " z = ", pos.z);
```

```js
if (op(0x0248, 101)) {
// checks the condition
showTextBox("Model with id 101 has been loaded");
}
```
`GAME` variable has been renamed to [HOST](./js-bindings.md#host).
2 changes: 1 addition & 1 deletion docs/en/embedding.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ CLEO Redux can be embedded and run JS scripts on an unknown (i.e. not [supported

## Loading into custom process

There are multiple ways of loading ASI file into the target process. [Ultimate ASI Loader](https://github.com/ThirteenAG/Ultimate-ASI-Loader/releases) is one of them. The host can load CLEO ASI file as a dynamic library when needed.
There are multiple ways of loading ASI file into the target process. [Ultimate ASI Loader](https://github.com/ThirteenAG/Ultimate-ASI-Loader/releases) is one of them. Or use any [DLL injector](https://github.com/search?q=dll+injector) available on GitHub. The host can load CLEO ASI file as a dynamic library when needed.

## Launching the CLEO runtime

Expand Down
42 changes: 33 additions & 9 deletions docs/en/js-bindings.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,27 @@ The following variables and functions are only available in JavaScript code.

## Variables

### GAME
### HOST

current game id. Possible values: `gta3`, `vc`, `re3`, `reVC`, `sa`, `gta3_unreal`, `vc_unreal`, `sa_unreal`
the host name (previously available as `GAME` variable). Possible values include `gta3`, `vc`, `re3`, `reVC`, `sa`, `gta3_unreal`, `vc_unreal`, `sa_unreal`, `unknown`.

CLEO plugins can use SDK to customize the name for their needs.

```js
if (GAME === "gta3") {
if (HOST === "gta3") {
showTextBox("This is GTA III");
}
if (GAME === "sa") {
if (HOST === "sa") {
showTextBox("This is San Andreas");
}
if (GAME === "sa_unreal") {
showTextBox("This is San Andreas: The Definitive Edition");
if (HOST === "unknown") {
showTextBox("This host is not natively supported");
}
```

### ONMISSION

global flag controlling whether the player is on a mission now.
the global flag controlling whether the player is on a mission now. Not available on an `unknown` host.

```js
if (!ONMISSION) {
Expand Down Expand Up @@ -75,7 +77,7 @@ while (true) {

### showTextBox

`showTextBox(text)` displays `{text}` in the black rectangular box
`showTextBox(text)` displays `{text}` in the black rectangular box. Not available on an `unknown` host.

```js
showTextBox("Hello, world!");
Expand All @@ -91,12 +93,34 @@ exit("Script ended");

### native

`native(command_name, ...input_args)` is a low-level function to execute any in-game command using its name `{command_name}`
`native(command_name, ...input_args)` is a low-level function to execute a command using its name `{command_name}`. The command name matches `name` property in a JSON file provided by Sanny Builder Library.

```js
native("SET_TIME_OF_DAY", 12, 30); // sets the time of day to 12:30
```

For the commands that return a single value, the result is this value.

```js
const progress = native("GET_PROGRESS_PERCENTAGE");
showTextBox(`Progress is ${progress}`);
```

For the commands that return multiple values, the result is an object where each key corresponds to a returned value. The key names match the output names given in the command definition

```js
var pos = native("GET_CHAR_COORDINATES", char); // returns char's coordinates vector {x, y, z}
showTextBox(`Character pos: x ${pos.x} y ${pos.y} z ${pos.z}`);
```

For the conditional commands the result is the boolean value `true` or `false`
```js
if (native("HAS_MODEL_LOADED", 101)) {
// checks the condition
showTextBox("Model with id 101 has been loaded");
}
```

## Static Objects


Expand Down
29 changes: 17 additions & 12 deletions docs/en/using-memory.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
> This guide is for the classic era games. For the information on using the Memory class in the definitive editions [click here](./using-memory-64.md).
> This guide is for x86 hosts (such as classic era games). For the information on using the Memory class on x64 hosts (such as the Definitive edition) [click here](./using-memory-64.md).
# Memory Object

Expand Down Expand Up @@ -36,8 +36,11 @@ interface Memory {

CallFunction(address: int, numParams: int, pop: int, ...funcParams: int[]): void;
CallFunctionReturn(address: int, numParams: int, pop: int, ...funcParams: int[]): int;
CallFunctionReturnFloat(address: int, numParams: int, pop: int, ...funcParams: int[]): float;
CallMethod(address: int, struct: int, numParams: int, pop: int, ...funcParams: int[]): void;
CallMethodReturn(address: int, struct: int, numParams: int, pop: int, ...funcParams: int[]): int;
CallMethodReturnFloat(address: int, struct: int, numParams: int, pop: int, ...funcParams: int[]): float;

Fn: {
Cdecl(address: int): (...funcParams: int[]) => int;
CdeclFloat(address: int): (...funcParams: int[]) => float;
Expand Down Expand Up @@ -130,24 +133,26 @@ Alternatively, use appropriate methods to read/write the value as a float (`Read

`Memory` object allows to invoke a foreign (native) function by its address using one of the following methods:

- `Memory.CallFunction` - binds to [0AA5 CALL_FUNCTION](https://library.sannybuilder.com/#/gta3/CLEO/0AA5)
- `Memory.CallFunctionReturn` - binds to [0AA7 CALL_FUNCTION_RETURN](https://library.sannybuilder.com/#/gta3/CLEO/0AA7)
- `Memory.CallMethod` - binds to [CALL_METHOD](https://library.sannybuilder.com/#/gta3/CLEO/0AA6)
- `Memory.CallMethodReturn` - binds to [CALL_METHOD_RETURN](https://library.sannybuilder.com/#/gta3/CLEO/0AA8)
- `Memory.CallFunction` - calls a function at the address and discards the returned value
- `Memory.CallFunctionReturn` - calls a function and at the address and returns an integer value
- `Memory.CallFunctionReturnFloat` - calls a function and at the address and returns a floating-point value

- `Memory.CallMethod` - calls a class instance method and discards the returned value
- `Memory.CallMethodReturn` - calls a class instance method and returns an integer value
- `Memory.CallMethodReturnFloat` - calls a class instance method and returns a floating-point value


```js
Memory.CallFunction(0x1234567, 2, 0, 1000, 2000)
```
where `0x1234567` is the address of the function, `2` is the number of arguments, `0` is the `pop` parameter (see below), `1000` and `2000` are the two arguments passed into the function.

Note that legacy SCM implementation of the call commands require the arguments of the invoked function to be listed in reverse order. That's it, you would see the same call in SCM as:

```
0AA5: call 0x1234567 num_params 2 pop 0 2000 1000
```
where `2000` is the second argument passed to the function located at 0x1234567 and `1000` is the first one.

> Legacy SCM implementation of the call commands require the arguments of the invoked function to be listed in reverse order. That's it, you would see the same call in SCM as:
>
>```
>0AA5: call 0x1234567 num_params 2 pop 0 2000 1000
>```
>where `2000` is the second argument passed to the function located at 0x1234567 and `1000` is the first one. In JS code all input arguments go in the direct order.
The third parameter (`pop`) in `Memory.CallFunction` defines the calling convention. When it is set to `0`, the function is called using the [stdcall](https://en.wikipedia.org/wiki/X86_calling_conventions#stdcall) convention. When it is set to the same value as `numParam`, the function is called using the [cdecl](https://en.wikipedia.org/wiki/X86_calling_conventions#cdecl) convention. Any other value breaks the code.
Expand Down
8 changes: 4 additions & 4 deletions docs/en/using-sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@ Commands that use low-level WinAPI and can potentially damage user environment m

### Command interface

CLEO Redux uses [Sanny Builder Library](https://library.sannybuilder.com) to know an interface of any command. For a new command to become available in the scripts, the JSON file (`gta3.json`, `vc.json`, `sa.json`) must have the command definition, including the name that matches with the value that the plugin uses `RegisterCommand` with. E.g. if the plugin registers `SHOW_MESSAGE` command, the JSON file must have a command with the name property set to `SHOW_MESSAGE`. The number and order of the input and output parameters in the definition must match the order of methods used by the plugin (i.e. `GetXXXParam` for each input argument and `SetXXXParam` for each output argument).
CLEO Redux uses [Sanny Builder Library](https://library.sannybuilder.com) to know an interface of any command. For a new command to become available in the scripts, the JSON file (`gta3.json`, `vc.json`, `sa.json`) must have the command definition, including the name that matches with the value that the plugin uses `RegisterCommand` with. E.g. if the plugin registers `SHOW_MESSAGE` command, the JSON file must have a command with the `name` property set to `SHOW_MESSAGE`. The number and order of the input and output parameters in the definition must match the order of methods used by the plugin (i.e. `GetXXXParam` for each input argument and `SetXXXParam` for each output argument).

#### Claiming Opcodes

Opcodes get assigned to new commands in Sanny Builder Library based on the availability, similarity with existing commands in other games, and other factors. To claim an opcode reach out to Sanny Builder Library maintainers on GitHub https://github.com/sannybuilder/library/issues
Opcodes get assigned to new commands in Sanny Builder Library based on the availability, similarity with existing commands in other games, and other factors. To claim an opcode reach out to Sanny Builder Library maintainers [on GitHub](https://github.com/sannybuilder/library/issues).

#### Why use command names and not an id for the command lookup?

One of the common issues with CLEO Library plugins was that commands authored by different people often had id collisions. If two plugins add commands with the same id, it is impossible to use them both. Using string names minimizes the collisions with custom plugins as well as with native opcodes. The library's definitions will ensure each command claims only available id. Also it helps to track and document plugins in one single place.
One of the common issues with CLEO Library plugins was that commands authored by different people often had id collisions. If two plugins add commands with the same id, it is impossible to use them both. Using string names minimizes the collisions with custom plugins as well as with native opcodes. The library's definitions ensure each command claims only an available id. Also it helps to track and document plugins in a single place.

### SDK Version

The current version is `1`. Changes to SDK will advance this number by one.
The current version is `2`. Changes to SDK advance this number by one.

### Path Resolution Convention

Expand Down
6 changes: 3 additions & 3 deletions plugins/Dylib/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions plugins/Dylib/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "dylib"
version = "1.0.2"
version = "1.1.0"
edition = "2021"
authors = ["Seemann <[email protected]>"]

Expand All @@ -12,4 +12,4 @@ crate-type = ["cdylib"]
[dependencies]
ctor = "0.1.21"
libloading = "0.7.3"
cleo_redux_sdk = "0.0.4"
cleo_redux_sdk = "0.0.7"
6 changes: 3 additions & 3 deletions plugins/Dylib/src/impl.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use cleo_redux_sdk::*;
use libloading;

/// https://library.sannybuilder.com/#/sa/CLEO/0AA2?p=1&v=1
/// https://library.sannybuilder.com/#/unknown_x86/dylib/LOAD_DYNAMIC_LIBRARY
pub extern "C" fn load_dynamic_library(ctx: Context) -> HandlerResult {
let libname = get_string_param(ctx);

Expand Down Expand Up @@ -30,7 +30,7 @@ pub extern "C" fn load_dynamic_library(ctx: Context) -> HandlerResult {
HandlerResult::CONTINUE
}

/// https://library.sannybuilder.com/#/sa/CLEO/0AA3?p=1&v=1
/// https://library.sannybuilder.com/#/unknown_x86/dylib/FREE_DYNAMIC_LIBRARY
pub extern "C" fn free_dynamic_library(ctx: Context) -> HandlerResult {
log(format!("disposing dynamic library"));

Expand All @@ -41,7 +41,7 @@ pub extern "C" fn free_dynamic_library(ctx: Context) -> HandlerResult {
HandlerResult::CONTINUE
}

/// https://library.sannybuilder.com/#/sa/CLEO/0AA4?p=1&v=1
/// https://library.sannybuilder.com/#/unknown_x86/dylib/GET_DYNAMIC_LIBRARY_PROCEDURE
pub extern "C" fn find_procedure(ctx: Context) -> HandlerResult {
let symbol = get_string_param(ctx);
let lib = get_int_param(ctx) as *mut libloading::Library;
Expand Down
2 changes: 1 addition & 1 deletion plugins/Dylib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn init() {
use cleo_redux_sdk::{log, register_command};
use r#impl::{find_procedure, free_dynamic_library, load_dynamic_library};

log("Dylib plugin 1.0.2");
log("Dylib plugin 1.1");

register_command("LOAD_DYNAMIC_LIBRARY", load_dynamic_library, Some("dll"));
register_command("FREE_DYNAMIC_LIBRARY", free_dynamic_library, Some("dll"));
Expand Down
18 changes: 9 additions & 9 deletions plugins/IniFiles/dllmain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
class IniFilesPlugin {
public:
IniFilesPlugin() {
Log("IniFiles plugin 1.1");
Log("IniFiles plugin 1.2");
RegisterCommand("READ_INT_FROM_INI_FILE", IniFileReadInt, "fs");
RegisterCommand("WRITE_INT_TO_INI_FILE", IniFileWriteInt, "fs");
RegisterCommand("READ_FLOAT_FROM_INI_FILE", IniFileReadFloat, "fs");
Expand All @@ -24,7 +24,7 @@ class IniFilesPlugin {
0AF0=4,%4d% = get_int_from_ini_file %1s% section %2s% key %3s%
****************************************************************/
{
wchar_t iniPath[STR_MAX_LEN];
wchar_t iniPath[MAX_PATH];
wchar_t sectionName[STR_MAX_LEN];
wchar_t key[STR_MAX_LEN];

Expand All @@ -45,7 +45,7 @@ class IniFilesPlugin {
0AF1=4,write_int %1d% to_ini_file %2s% section %3s% key %4s%
****************************************************************/
{
wchar_t iniPath[STR_MAX_LEN];
wchar_t iniPath[MAX_PATH];
wchar_t sectionName[STR_MAX_LEN];
wchar_t key[STR_MAX_LEN];
wchar_t strValue[STR_MAX_LEN];
Expand All @@ -67,7 +67,7 @@ class IniFilesPlugin {
0AF2=4,%4d% = get_float_from_ini_file %1s% section %2s% key %3s%
****************************************************************/
{
wchar_t iniPath[STR_MAX_LEN];
wchar_t iniPath[MAX_PATH];
wchar_t sectionName[STR_MAX_LEN];
wchar_t key[STR_MAX_LEN];
wchar_t strValue[STR_MAX_LEN];
Expand Down Expand Up @@ -98,7 +98,7 @@ class IniFilesPlugin {
0AF3=4,write_float %1d% to_ini_file %2s% section %3s% key %4s%
****************************************************************/
{
wchar_t iniPath[STR_MAX_LEN];
wchar_t iniPath[MAX_PATH];
wchar_t sectionName[STR_MAX_LEN];
wchar_t key[STR_MAX_LEN];
wchar_t strValue[STR_MAX_LEN];
Expand All @@ -120,7 +120,7 @@ class IniFilesPlugin {
0AF4=4,%4d% = read_string_from_ini_file %1s% section %2s% key %3s%
****************************************************************/
{
wchar_t iniPath[STR_MAX_LEN];
wchar_t iniPath[MAX_PATH];
wchar_t sectionName[STR_MAX_LEN];
wchar_t key[STR_MAX_LEN];
wchar_t strValue[STR_MAX_LEN];
Expand All @@ -145,7 +145,7 @@ class IniFilesPlugin {
0AF5=4,write_string %1s% to_ini_file %2s% section %3s% key %4s%
****************************************************************/
{
wchar_t iniPath[STR_MAX_LEN];
wchar_t iniPath[MAX_PATH];
wchar_t sectionName[STR_MAX_LEN];
wchar_t key[STR_MAX_LEN];
wchar_t strValue[STR_MAX_LEN];
Expand Down Expand Up @@ -179,10 +179,10 @@ class IniFilesPlugin {

static void GetPath(Context ctx, wchar_t* res) {
char buf[STR_MAX_LEN];
char path[STR_MAX_LEN];
char path[MAX_PATH];
GetStringParam(ctx, buf, sizeof(buf));
ResolvePath(buf, path);
MultiByteToWideChar(CP_UTF8, 0, path, -1, res, STR_MAX_LEN);
MultiByteToWideChar(CP_UTF8, 0, path, -1, res, MAX_PATH);
}

static BOOL ReadStringFromIni(wchar_t* iniPath, wchar_t* sectionName, wchar_t* key, wchar_t* strValue) {
Expand Down
Binary file modified plugins/SDK/cleo_redux.lib
Binary file not shown.
Binary file modified plugins/SDK/cleo_redux64.lib
Binary file not shown.
Loading

0 comments on commit 66687f8

Please sign in to comment.