Skip to content

INI Language Extensions

SpectrumQT edited this page Jul 1, 2026 · 6 revisions

XXMI DLL script language additions (on top of 3dmigoto base version).


Operators

For Bitwise & Bitshift operators precedence is the same as in C++.

Bitwise Operators

  1. NOT ~
  2. AND &
  3. XOR ^
  4. OR |

Bitshift Operators

  1. Left Shift <<
  2. Right Shift >>

Usage Example

In particular, it enables the efficient way to handle flags, which allow to store up to 24 distinct 1 or 0 states in a single INI variable:

; ID of current flag (from 0 to23)
local $flag_id = 0

; Flags storage
local $flags = 0

; Bitwise mask for the calculations below
local $flag = 1 << $flag_id

; Check if $flag_id has `0` state in $flags
if (($flags & $flag) == 0)
    ; Store `1` state for $flag_id in $flags
    $flags = $flags | $flag
endif

; Check if $flag_id has `1` state in $flags
if (($flags & $flag) != 0)
    ; Store `0` state for $flag_id in $flags
    $flags = $flags & ~$flag
endif

Identity Operator

Operator @ returns a resource identity value.

  • Can be used with any "ResourceCopyTarget" entity (e.g. @ResourceCustom, @vs-t0, etc.).
  • Returns 0 if resource does not exist (aka nullptr).

Resource Identity

$resource_id_custom = @ResourceFoo
$resource_id_d3d11 = @vs-t0

Pool Resource Identity

When used with a pool resource, the operator returns the identity of the resolved pool entry.

$pool_resource_id_static = @PoolFoo[0]
$pool_resource_id_dynamic = @PoolFoo[$index]

See Resource Pools → Identity Operator (@) for details.

Produces a 24-bit integer value derived from the underlying resource pointer and safely representable in float32.

Index Operator

Operator # provides additional metadata for pools.

Pool Resource Index

$fifo_pool_resource_index_static = #PoolFooFIFO[123.456]
$fifo_pool_resource_index_dynamic = #PoolFooFIFO[$resource_uid]

Pool Size

$pool_size = #PoolFoo

See Resource Pools → Index Operator (@) for details.


Resource Attribute Getters

  1. Size - Returns resource size in bytes.
$size = ResourceFoo->Size
  1. Stride - Returns resource stride in bytes.
$stride = ResourceFoo->Stride
  1. SourceStride - Returns stride of resource that was copied into ResourceFoo. Slots are not supported (e.g. vb0).
[ResourceBar]
type = Buffer
stride = 42
filename = Bar.buf

[PoolFoo]
pool_size = 2
type = Buffer
format = R32_FLOAT

PoolFoo[0] = copy ResourceBar

$bar_stride = PoolFoo[0]->SourceStride ; 42
$foo_stride = PoolFoo[0]->Stride       ; 4

Using -> on custom resources (e.g ResourceFoo->Size) is almost CPU cost free (~1ns), while slots (e.g. vb0->Size) perform slightly slower (~10-100ns).

Error Codes

Getters return specific values when data retrieval fails:

UNKNOWN             = -1.0f; // All data sources returned `0` (getters are looking for mutiple semantically similar properties)
RESOURCE_NOT_FOUND  = -2.0f; // No buffer is found for target
NOT_A_BUFFER        = -3.0f; // Target is not a D3D11_RESOURCE_DIMENSION_BUFFER

Resource Pool Section

A Resource Pool is a collection of resources that share the same configuration and can be accessed through an index or UID.

Pools are declared using a dedicated [Pool] section and behave similarly to regular [Resource] sections, while allowing indexed access to multiple resource instances.

Pool Declaration

[PoolFoo]
pool_size = 4

A pool supports all standard [Resource] parameters:

[PoolFoo]
pool_size = 4

type = Buffer
format = R32_FLOAT
stride = 4

Template Resource

When a pool is parsed:

  1. A hidden template custom resource is created internally.
  2. The template stores all resource parameters and optional initial data.
  3. Individual pool resources are instantiated from this template on demand.

For example:

[PoolFoo]
pool_size = 4
type = Buffer
data = "Hello World!"

Every resource created within the pool inherits the template configuration and initial data.


Pool Access

Pool resources can be accessed using either static or dynamic indexing and used anywhere a custom resource is accepted.

Static Access

The pool resource is resolved during INI parsing.

PoolFoo[0] = ref ResourceText

Statically accessed resources are being instantiated at parsing time (data structs, not D3D buffer COM objects).

Dynamic Access

The pool resource is resolved at runtime.

local $index = 0
PoolFoo[$index] = ref ResourceText

Dynamically accessed resources are being instantiated at runtime. That's where D3D buffer instantiation also happens.

Unused pool entries consume no custom resource allocations.


Pool Indexing Modes

Pools support two indexing strategies, Ring and FIFO.


Ring Indexing (Default)

Ring indexing treats the pool as a circular array.

[PoolFoo]
pool_size = 4
pool_index_type = ring

Since this is the default mode, the following is equivalent:

[PoolFoo]
pool_size = 4

Negative Indices

Negative indices wrap from the end of the pool.

PoolFoo[-1]

returns the last resource.

For a pool of size 4:

Expression Pool Index
PoolFoo[-1] 3
PoolFoo[-2] 2
PoolFoo[-3] 1
PoolFoo[-4] 0

Index Overflow

Indices automatically wrap around the pool size.

For a pool of size 4:

Expression Pool Index
PoolFoo[0] 0
PoolFoo[1] 1
PoolFoo[2] 2
PoolFoo[3] 3
PoolFoo[4] 0
PoolFoo[5] 1
PoolFoo[8] 0

This allows continuous cyclic access without manual modulo operations.

Usage Example

For example, we want to keep results of shapekeys calculations for certain object from last 2 frames, and our game processes them all in single batch. Assuming shapekeys compute shader hash is 0123456789absdef and cs-u0 hash for our object is 12345678, we can do the following:

[Constants]
global $frame = 0

[PoolHistory]
pool_size = 2
max_copies_per_frame = 1

[Present]
$frame = $frame + 1

[ShaderOverrideShapeKeyCS]
hash = 0123456789absdef
allow_duplicate_hash = true
CheckTextureOverride = cs-u0

[TextureOverrideCSU0]
hash = 12345678
post PoolHistory[$frame] = copy cs-u0

Resource copies will land like this:

Frame 0 -> PoolHistory[0]
Frame 1 -> PoolHistory[1]
Frame 2 -> PoolHistory[0]
Frame 3 -> PoolHistory[1]

and PoolHistory[0] and PoolHistory[1] will become available to use as inputs for some custom Compute Shader. For example, to calculate movement vectors of each vertex.


FIFO Indexing

Unlike Ring mode, the value inside brackets is treated as a user-defined key (UID), rather than a direct pool index.

[PoolFooFIFO]
pool_index_type = fifo
pool_size = 4

Any floating point value or INI variable can be used as a UID:

PoolFooFIFO[123]
PoolFooFIFO[-987.654]
PoolFooFIFO[$object_id]

The same UID always resolves to the same pool resource until its assignment slot is recycled.

Assignment Rules

When a UID is encountered:

  1. If the UID already exists, its previously assigned slot is returned.
  2. If the UID is new, the next available slot is assigned.
  3. When the pool is full, the oldest assignment is replaced.

Example

Initial accesses:

PoolFooFIFO[10]
PoolFooFIFO[20]
PoolFooFIFO[30]
PoolFooFIFO[40]

produce:

UID Pool Index
10 0
20 1
30 2
40 3

Subsequent lookups return the same assignments:

PoolFooFIFO[10] ; index 0
PoolFooFIFO[20] ; index 1

Adding another UID:

PoolFooFIFO[50]

overwrites the oldest slot assignment:

UID Pool Index
20 1
30 2
40 3
50 0

UID 10 is no longer mapped.


Pool Operators

Pools extend both the @ and # operators.

Identity Operator (@)

Returns the compacted identity of a resource.

Pool Resource Identity

$resource_id = @PoolFoo[0]

Dynamic form:

$resource_id = @PoolFoo[$index]

The returned value uniquely identifies the underlying resource buffer and can be compared with other identities.

Example:

if @PoolFoo[0] == @PoolFoo[1]
    ; Do something
endif

This condition is true when both resources reference the same buffer.


Index Operator (#)

The meaning depends on the operand.

Pool Resource Index

For Ring pools:

#PoolFoo[7]

returns the normalized pool index.

For a pool size of 4:

#PoolFoo[7] ; returns 3

For FIFO pools:

#PoolFooFIFO[123.456]

returns the slot currently assigned to the specified UID.

Dynamic form:

#PoolFooFIFO[$uid]

This is useful when a script needs to determine which actual pool resource was selected by FIFO assignment.

Pool Size

When applied directly to the pool:

#PoolFoo

returns the configured pool capacity.

local $size = #PoolFoo

Equivalent to:

local $size = 4

for:

[PoolFoo]
pool_size = 4

Complete Example

[PoolFoo]
pool_size = 2

[ResourceText]
type = Buffer
data = "Text"

[Present]
PoolFoo[0] = ref ResourceText

local $src = 0
local $dst = 1

PoolFoo[$dst] = ref PoolFoo[$src]

local $pool_size = #PoolFoo

local $resource_text_id = @ResourceText
local $pool_resource_0_id = @PoolFoo[0]
local $pool_resource_1_id = @PoolFoo[1]

local $same_buffer = $resource_text_id == $pool_resource_0_id && $pool_resource_0_id == $pool_resource_1_id

; The more direct way also works:
local $same_buffer = @ResourceText == @PoolFoo[0] && @PoolFoo[0] == @PoolFoo[1]

After execution, ResourceText, PoolFoo[0], and PoolFoo[1] all reference the same underlying resource buffer, causing all identity comparisons above to evaluate as true.