Skip to content

Commit

Permalink
0.6.0 release
Browse files Browse the repository at this point in the history
  • Loading branch information
x87 committed Oct 8, 2021
1 parent 220451c commit 15ade7c
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 19 deletions.
23 changes: 17 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
### 0.6.0 - Oct 08, 2021

- add [INT_ADD](https://library.sannybuilder.com/#/gta3/CLEO/0A8E), [INT_SUB](https://library.sannybuilder.com/#/gta3/CLEO/0A8F), [INT_MUL](https://library.sannybuilder.com/#/gta3/CLEO/0A90), [INT_DIV](https://library.sannybuilder.com/#/gta3/CLEO/0A91) commands
- math operations are now available through the native JavaScript `Math` object where possible ([see documentation](using-math.md)).
- new static methods in `Memory` class. See [documentation](using-memory.md) for more info

#### BREAKING CHANGES
- `asFloat` has been removed in favor of `Memory.toFloat`
- class `Object` has been renamed to `ScriptObject` to avoid conflicts with native JavaScript Object.
- deprecated command `isKeyPressed` has been deleted. Use `Pad.isKeyPressed` instead

### 0.5.3 - Oct 02, 2021

- add a new built-in JavaScript function `asFloat` to cast an integer value returned by the `Memory.Read` command to a floating point number ([IEEE 754](https://en.wikipedia.org/wiki/IEEE_754))

```
```js
var gravity = asFloat(Memory.Read(gravityAddress, 4, false)); // the gravity var now holds a floating-point value
```

Expand Down Expand Up @@ -36,13 +47,13 @@ var gravity = asFloat(Memory.Read(gravityAddress, 4, false)); // the gravity var
### 0.4.0 - Sep 02, 2021

- add bindings for all opcodes in JS scripts
- CLEO can now generate a \*.d.ts file for autocomplete in VS Code
- add hot reload for \*.js files
- fix an issue with the opcodes not being logged in the cleo.log even with LogOpcodes=1
- CLEO can now generate a `*.d.ts` file for autocomplete in VS Code
- add hot reload for `*.js` files
- fix: opcodes log did not work even with `LogOpcodes=1`

### 0.3.1 - Aug 21, 2021

- add `op` binding to execute any opcode from JavaScript code
- add `op` function to execute any opcode from JavaScript code
- add `GAME` constant to check the current host game
- CLEO now keeps its settings in `CLEO/.config/cleo.ini` created on the first run
- JavaScript support can be disabled using `AllowJs=0` setting
Expand All @@ -53,7 +64,7 @@ var gravity = asFloat(Memory.Read(gravityAddress, 4, false)); // the gravity var

### 0.2.1 - Aug 14, 2021

- watch CLEO directory and start/stop scripts if the CS file got removed
- watch the CLEO directory and start/stop scripts if a CS file has been added or deleted

### 0.2.0 - Aug 13, 2021

Expand Down
37 changes: 25 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,14 @@ JavaScript is enabled by default. To disable it open up `CLEO\.config\cleo.ini`

### Custom Commands

- 0A93
[TERMINATE_THIS_CUSTOM_SCRIPT](https://library.sannybuilder.com/#/sa/CLEO/0A93)
- 0AB0 [IS_KEY_PRESSED](https://library.sannybuilder.com/#/sa/CLEO/0AB0)
- 0A8D [READ_MEMORY](https://library.sannybuilder.com/#/gta3/CLEO/0A8D) (**UNSAFE** - requires `mem` permission)
- 0A8C [WRITE_MEMORY](https://library.sannybuilder.com/#/gta3/CLEO/0A8C) (**UNSAFE** - requires `mem` permission)
- 0A8E [INT_ADD](https://library.sannybuilder.com/#/gta3/CLEO/0A8E)
- 0A8F [INT_SUB](https://library.sannybuilder.com/#/gta3/CLEO/0A8F)
- 0A90 [INT_MUL](https://library.sannybuilder.com/#/gta3/CLEO/0A90)
- 0A91 [INT_DIV](https://library.sannybuilder.com/#/gta3/CLEO/0A91)
- 0A93 [TERMINATE_THIS_CUSTOM_SCRIPT](https://library.sannybuilder.com/#/gta3/CLEO/0A93)
- 0AB0 [IS_KEY_PRESSED](https://library.sannybuilder.com/#/gta3/CLEO/0AB0)

### Writing CS scripts

Expand Down Expand Up @@ -179,6 +182,24 @@ while (true) {

CLEO Redux supports all in-game commands (opcodes) in the class form as defined in Sanny Builder Library. Keywords and custom extensions are not supported.

#### Class ScriptObject vs Object

Sanny Builder Library defines a static class `Object` to group commands allowing to create and manipulate 3D objects in-game. At the same time JavaScript has the [native Object class](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) with its own methods.

To avoid mixing the two, CLEO Redux uses `ScriptObject` class instead of the Library's `Object` with [the same interface](https://library.sannybuilder.com/#/gta3/classes/Object).

```js
var x = ScriptObject.Create(modelId, x, y, z) // opcode 0107, creates a new object in the game

var x = Object.create(null) // native JavaScript code, creates a new object in JS memory
```

#### Class Math

Similarly to the `Object` class (see above), both the Library and native JavaScript runtime use the same name for mathematical utilities: class `Math`. In this case however, the decision was made to keep both native and script methods under the same class name.

The priority was given to the native code in those cases where it provides the same functionality as script opcodes. For example, to calculate the absolute value of a number, use native [Math.abs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/abs), not [Math.Abs](https://library.sannybuilder.com/#/gta3?q=%22abs%22). See [Using Math](using-math.md) for more detailed information.

#### Examples

If you were to change the time of day to 22:00, run the following command
Expand Down Expand Up @@ -263,7 +284,7 @@ while (true) {
showTextBox("Hello, world!");
```

- `asFloat(value)` - casts an integer `value` returned by the `Memory.Read` command to a floating point number ([IEEE 754](https://en.wikipedia.org/wiki/IEEE_754)).
- family of static methods in the `Memory` class for manipulating different data types. See the [Memory guide](using-memory.md) for more information.

### Deprecated

Expand Down Expand Up @@ -293,14 +314,6 @@ if (op(0x0248, 101)) {
}
```

- `isKeyPressed(vk_id)` - returns `true` if the key with the [code](https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes) `{vk_id}` is pressed. Deprecated since 0.5.2, use [Pad.IsKeyPressed](https://library.sannybuilder.com/#/gta3/CLEO/0AB0) instead.

```js
if (isKeyPressed(0x74)) {
log("F5 is pressed");
}
```

## Dev Features

### SCM Log
Expand Down
54 changes: 54 additions & 0 deletions using-math.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
## Using Math Object

JavaScript has a built-in `Math` object that provides common mathematical operations, such as `abs`, `sin`, `cos`, `random`, `pow`, `sqr`, etc. CLEO Redux extends this object to include extra operations supported by the game. The interface of `Math` looks as follows:

```ts
declare class Math {
// native code
static readonly E: number;
static readonly LN10: number;
static readonly LN2: number;
static readonly LOG2E: number;
static readonly LOG10E: number;
static readonly PI: number;
static readonly SQRT1_2: number;
static readonly SQRT2: number;
static abs(x: number): number;
static acos(x: number): number;
static asin(x: number): number;
static atan(x: number): number;
static atan2(y: number, x: number): number;
static ceil(x: number): number;
static cos(x: number): number;
static exp(x: number): number;
static floor(x: number): number;
static log(x: number): number;
static max(...values: number[]): number;
static min(...values: number[]): number;
static pow(x: number, y: number): number;
static random(): number;
static round(x: number): number;
static sin(x: number): number;
static sqrt(x: number): number;
static tan(x: number): number;

// GTA III and GTA Vice City commands
static ConvertMetresToFeet(metres: int): int;
static RandomFloatInRange(min: float, max: float): float;
static RandomIntInRange(min: int, max: int): int;
// GTA Vice City-only commands
static GetDistanceBetweenCoords2D(fromX: float, fromY: float, toX: float, toZ: float): float;
static GetDistanceBetweenCoords3D(fromX: float, fromY: float, fromZ: float, toX: float, toY: float, toZ: float): float;
}
```

The first group includes the native constants and methods provided by the JavaScript runtime. They start with a lowercase letter, e.g. `Math.abs`. You can find the detailed documentation for these methods [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math).

The second group includes the game-specific methods (in this case those of GTA III). Following the naming convention, each method that is bound to a script opcode starts with a capital letter, e.g. `Math.RandomIntInRange` (opcode 0209). You can find the documentation in [Sanny Builder Library](https://library.sannybuilder.com/).


```js
var x = Math.abs(-1); // x = 1
var f = Math.ConvertMetresToFeet(10) // f = 32
var pi = Math.floor(Math.PI) // pi = 3
```
89 changes: 89 additions & 0 deletions using-memory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
## Using Memory class

Static class `Memory` provides methods for accessing and manipulating the data or code in the current process. It has the following interface:

```ts
class Memory {
static ReadFloat(address: int, vp: boolean): float;
static WriteFloat(address: int, value: float, vp: boolean): void;
static ReadI8(address: int, vp: boolean): int;
static ReadI16(address: int, vp: boolean): int;
static ReadI32(address: int, vp: boolean): int;
static ReadU8(address: int, vp: boolean): int;
static ReadU16(address: int, vp: boolean): int;
static ReadU32(address: int, vp: boolean): int;
static WriteI8(address: int, value: int, vp: boolean): void;
static WriteI16(address: int, value: int, vp: boolean): void;
static WriteI32(address: int, value: int, vp: boolean): void;
static WriteU8(address: int, value: int, vp: boolean): void;
static WriteU16(address: int, value: int, vp: boolean): void;
static WriteU32(address: int, value: int, vp: boolean): void;
static Read(address: int, size: int, vp: boolean): int;
static Write(address: int, size: int, value: int, vp: boolean): void;

static ToFloat(value: int): float;
static FromFloat(value: float): int;
static ToU8(value: int): int;
static ToU16(value: int): int;
static ToU32(value: int): int;
static ToI8(value: int): int;
static ToI16(value: int): int;
static ToI32(value: int): int;
}
```

### Reading and Writing Values

First group of methods (`ReadXXX`/`WriteXXX`) can be used for changing values stored in the memory. Each method is designed for a particular data type. To change a floating-point value (which occupies 4 bytes in the original game) use `Memory.WriteFloat`, e.g.:

```js
Memory.WriteFloat(address, 1.0, false)
```

where `address` is a variable storing the memory location, `1.0` is the value to write and `false` means it's not necessary to change the memory protection with `VirtualProtect` (the address is already writable).

Similarly, to read a value from the memory, use one of the `ReadXXX` methods, depending on what data type the memory address contains. For example, to read a 8-bit signed integer (also known as a `char` or `uint8`) use `Memory.ReadI8`, e.g.:

```js
var x = Memory.ReadI8(address, true)
```

variable `x` now holds a 8-bit integer value in the range (0..255). For the sake of showing possible options, this example uses `true` as the last argument, which means the default protection attribute for this address will be changed to `PAGE_EXECUTE_READWRITE` before the read.

```js
var gravity = Memory.ReadFloat(gravityAddress, false);
gravity += 0.05;
Memory.WriteFloat(gravityAddress, gravity, false);
```

Finally, last two methods `Read` and `Write` is what other methods use under the hood. They have direct binding to opcodes [0A8D READ_MEMORY](https://library.sannybuilder.com/#/gta3/CLEO/0A8D) and [0A8C WRITE_MEMORY](https://library.sannybuilder.com/#/gta3/CLEO/0A8C) and produce the same result.

The `size` parameter in the `Read` method can only be `1`, `2` or `4`. CLEO treats the `value` as a signed integer stored in the little-endian format.

In the `Write` method any `size` larger than `0` is allowed. Sizes `3` and `5` onwards can only be used together with a single byte `value`. CLEO uses them to fill a continious block of memory starting at the `address` with the given `value` (think of it as `memset` in C++).

```js
Memory.Write(addr, 0x90, 10, true) // "noping" 10 bytes of code starting from addr
```

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


### Casting methods

By default `Read` and `Write` methods treat data as signed integer values. It can be inconvinient if the memory holds a floating-point value in IEEE 754 format or a large 32-bit signed integer (e.g. a pointer). In this case use casting methods `ToXXX`/`FromXXX`. They act similarly to [reinterpret_cast](https://docs.microsoft.com/en-us/cpp/cpp/reinterpret-cast-operator?view=msvc-160) operator in C++.

To get a quick idea what to expect from those methods see the following examples:

```js
Memory.FromFloat(1.0) => 1065353216
Memory.ToFloat(1065353216) => 1.0
Memory.ToU8(-1) => 255
Memory.ToU16(-1) => 65535
Memory.ToU32(-1) => 4294967295
Memory.ToI8(255) => -1
Memory.ToI16(65535) => -1
Memory.ToI32(4294967295) => -1
```

Alternatively, use appropriate methods to read/write the value as a float (`ReadFloat`/`WriteFloat`) or as an unsigned integer (`ReadUXXX`/`WriteUXXX`).
2 changes: 1 addition & 1 deletion website/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,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.5.3 | Oct 02, 2021</small>
<small class="pt-1 text-muted">v0.6.0 | Oct 08, 2021</small>
</div>
</div>
</div>
Expand Down

0 comments on commit 15ade7c

Please sign in to comment.