Skip to content

Commit

Permalink
0.8.6 release
Browse files Browse the repository at this point in the history
  • Loading branch information
x87 committed Jan 12, 2022
1 parent c8ebec3 commit 1a995e7
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 3 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
### 0.8.6 - Jan 12, 2022

- add [CALL_FUNCTION](https://library.sannybuilder.com/#/sa_unreal/CLEO/0C08) and [CALL_FUNCTION_RETURN](https://library.sannybuilder.com/#/sa_unreal/CLEO/0C09) commands in San Andreas: The Definitive Edition
- add `Memory.Fn.X64` convenience methods for [calling functions from JavaScript on the x64 platform](using-memory-64.md#calling-foreign-functions)
- `showTextBox` now works in San Andreas: The Definitive Edition
- fixed an issue with FxtStore object not showing in VS Code autocomplete
- fixed an issue with text draw not working in GTA San Andreas
- fixed an issue in CLEO dev builds causing the game crash on startup while checking for an update

#### BREAKING CHANGE

- minimum required version of `sa_unreal.json` is `0.209`

### 0.8.5 - Jan 1, 2022
- add support for [static FXT files](using-fxt.md#static-fxt-files) in `CLEO_TEXT` folder
- add support for [private FXT storage](using-fxt.md#fxtstore) in each JS script
Expand Down
2 changes: 2 additions & 0 deletions unsupported.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ The following items are known to be not working and there is no specific timelin
- commands implicitly loading models or textures (such as widgets) [Tracking issue](https://github.com/cleolibrary/CLEO-Redux/issues/12). You can circumvent the issue by preloading needed resources, e.g. by calling them in a .CS script first.

- you can't call the game functions that need references to variables to store the result. There is no "take an address of the variable" syntax.

- in x64 games (SA: DE) you can't call game functions that need floating-point values. All input arguments are treated as 64-bit signed integers. You may need to use other means to invoke the native code (e.g. DLL injection)
85 changes: 84 additions & 1 deletion using-memory-64.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,18 @@ interface Memory {
ToI16(value: int): int;
ToI32(value: int): int;

Translate(symbol: string): int;
CallFunction(address: int, ib: boolean, numParams: int, ...funcParams: number[]): void;
CallFunctionReturn(address: int, ib: boolean, numParams: int, ...funcParams: number[]): int;
Fn: {
X64(address: int, ib: boolean): (...funcParams: int[]) => int;
X64I8(address: int): (...funcParams: int[]) => int;
X64I16(address: int): (...funcParams: int[]) => int;
X64I32(address: int): (...funcParams: int[]) => int;
X64U8(address: int): (...funcParams: int[]) => int;
X64U16(address: int): (...funcParams: int[]) => int;
X64U32(address: int): (...funcParams: int[]) => int;
}

}
```

Expand Down Expand Up @@ -114,3 +125,75 @@ To get a quick idea what to expect from those methods see the following examples
```

Alternatively, use appropriate methods to read/write the value as a float (`ReadFloat`/`WriteFloat`) or as an unsigned integer (`ReadUXXX`/`WriteUXXX`).

### Calling Foreign Functions

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

- `Memory.CallFunction` - binds to [00C8 CALL_FUNCTION](https://library.sannybuilder.com/#/sa_unreal/CLEO/0C08)
- `Memory.CallFunctionReturn` - binds to [00C9 CALL_FUNCTION_RETURN](https://library.sannybuilder.com/#/sa_unreal/CLEO/0C09)


```js
Memory.CallFunction(0xEFFB30, true, 1, 13)
```
where `0xEFFB30` is the function offset relative to IMAGE BASE (think of it a randomized start address of the game memory), `true` is the `ib` flag (see below), `1` is the number of input arguments, and `13` are the only argument passed into the function.


The `ib` parameter in `Memory.CallFunction` has the same meaning as in memory read/write commands. When set to `true` CLEO adds the current known address of the image base to the value provided as the first argument to calculate the absolute memory address of the function. When set to `false` no changes to the first argument are made.

`Memory.CallFunctionReturn` has the same interface but additionally it writes the result of the function to a variable.

CLEO Redux supports calling foreign functions with up to 16 parameters.

**Note that usage of any of the call methods requires the `mem` [permission](README.md#Permissions)**.

**KNOWN ISSUE**

Due to implementation details on x64 platform CLEO currently does not support passing floating-point arguments to a callee function. You can only use integer numbers. For the same reason you can't call functions returning a floating-point value with `Memory.CallFunctionReturn`.

#### Convenience methods with Fn object

`Memory.Fn` provides convenient methods for calling different types of foreign functions.

```ts
Fn: {
X64(address: int, ib: boolean): (...funcParams: int[]) => int;
X64I8(address: int): (...funcParams: int[]) => int;
X64I16(address: int): (...funcParams: int[]) => int;
X64I32(address: int): (...funcParams: int[]) => int;
X64U8(address: int): (...funcParams: int[]) => int;
X64U16(address: int): (...funcParams: int[]) => int;
X64U32(address: int): (...funcParams: int[]) => int;
}
```

These methods is designed to cover all supported return types. For example, this code

```js
Memory.CallFunction(0xEFFB30, true, 1, 13)
```

can also be written as

```js
Memory.Fn.X64(0xEFFB30, true)(13)
```

Note a few key differences here. First of all, `Memory.Fn` methods don't invoke a foreign function directly. Instead, they return a new JavaScript function that can be stored in a variable and reused to call the associated foreign function many times with different arguments:

```js
var f = Memory.Fn.X64(0xEFFB30, true);
f(13) // calls function 0xEFFB30 with the argument of 13
f(11) // calls method 0xEFFB30 with the argument of 11
```

The second difference is that there is no `numParams` parameter. Each `Fn` method figures it out automatically.

By default a returned result is considered a 64-bit signed integer value. If the function returns another type (e.g. a boolean), use one of the methods matching the function signature:

```js
var flag = Memory.Fn.X64U8(0x1234567, true)()
```

This code invokes a function at `0x1234567` + IMAGE_BASE with no arguments and stores the result as a 8-bit unsigned integer value.
2 changes: 1 addition & 1 deletion using-memory.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ Note a few key differences here. First of all, `Memory.Fn` methods don't invoke

The second difference is that there are no `numParams` and `pop` parameters. Each `Fn` method figures them out automatically.

By default a returned result is considered a 32-bit signed integer value. If the function something another type (a floating-point value, or a signed integer), use one of the methods matching the function signature, e.g.:
By default a returned result is considered a 32-bit signed integer value. If the function returns another type (a floating-point value, or a signed integer), use one of the methods matching the function signature, e.g.:

```js
var flag = Memory.Fn.CdeclU8(0x1234567)()
Expand Down
2 changes: 1 addition & 1 deletion website/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ <h1 class="font-weight-bold d-flex justify-content-center">
href="https://github.com/cleolibrary/CLEO-Redux/releases/latest"
>Download</a
>
<small class="pt-1 text-muted">v0.8.5 | Jan 01, 2022</small>
<small class="pt-1 text-muted">v0.8.6 | Jan 12, 2022</small>
</div>
</div>
</div>
Expand Down

0 comments on commit 1a995e7

Please sign in to comment.