Cronus Zen Guide
GPC Scripting 4 min read

GPC scripting 101: your first Cronus Zen script

Learn GPC from zero: how main runs, get_val and set_val, int variables, event_press, combos and wait(), then build and program a working rapid-fire script with a toggle in Zen Studio Live.

Updated
GPC script code on a dark editor

Quick answer

GPC is the C-like language the Cronus Zen runs. Every script needs a main block, which the Zen executes top to bottom once per input cycle. Read inputs with get_val, write outputs with set_val, react to a single press with event_press, and build timed sequences with a combo that uses wait(). Compile in Zen Studio Live.

What is GPC and how does a script run?

GPC is a small C-like language. You write it in Zen Studio, the compiler turns it into bytecode, and the Zen's virtual machine runs that bytecode on the device. No computer is involved once the slot is programmed.

The mental model that matters most: the Zen reads the controller, runs your main block from top to bottom, and sends the resulting report to the console. Then it does it again, many times per second. Anything you set_val inside one run applies to that one outgoing report; the next cycle starts fresh from the real controller input. This is why "state" needs variables, which we get to shortly.

The smallest useful script

Straight from the official guide:

gpc
main {
    if(get_val(PS5_L2)) {
        set_val(PS5_R1, 100);
    }
}

Every cycle this reads L2. If it is non-zero (pressed at all), it writes a fully pressed R1 into the outgoing report. Release L2 and R1 goes back to whatever the controller says. Four lines, and it already demonstrates read, evaluate, write, send.

What values do inputs have?

ControlRangeMeaning
Digital button0 or 100Released or pressed
Analog trigger0..100How far pressed
Stick axis-100..100Centre is 0

So get_val(PS5_R2) might return 37 for a half-pulled trigger, and get_val(PS5_RX) returns a negative number when the right stick is pushed left. Any non-zero value counts as true in an if.

How do I remember something between cycles?

Declare an int at the top level. Globals keep their value across cycles.

gpc
int shots;

main {
    if(event_press(PS5_R2)) {
        shots = shots + 1;
    }
}

event_press is the important detail. get_val(PS5_R2) is true for every cycle the trigger is held, which could be dozens per second. event_press(PS5_R2) is true only on the single cycle where the trigger goes from released to pressed. Use get_val for "while held" behaviour and event_press for "when pressed" behaviour.

What is init for?

init runs once when the slot loads, before the first main. Use it to load saved settings or set starting values. Both blocks see the same global variables.

gpc
int enabled;

init {
    enabled = 1;
}

main {
    if(event_press(PS5_TRIANGLE)) {
        enabled = !enabled;
    }
}

How do I make a timed sequence?

Use a combo. A combo is a block of set_val and wait calls that runs on its own schedule without blocking main. Start it with combo_run, and it steps through its lines over successive cycles, holding each set_val for the duration of the following wait in milliseconds.

gpc
main {
    if(event_press(PS5_CROSS)) combo_run(TapSquare);
    if(event_press(PS5_CIRCLE)) combo_stop(TapSquare);
}

combo TapSquare {
    set_val(PS5_SQUARE, 100);
    wait(80);
    set_val(PS5_SQUARE, 0);
    wait(80);
}

wait is combo-only and must sit at the root of the combo. combo_run will not restart a combo that is already running; use combo_restart if that is what you want.

Putting it together: rapid fire with a toggle

This script taps R2 repeatedly while you hold it, and lets you switch the feature on and off with Triangle. It uses everything above.

gpc
// Rapid fire on R2 with an enable toggle on TRIANGLE.
int enabled = 1;      // 1 = on, 0 = off

main {
    // Toggle once per press, not once per cycle.
    if(event_press(PS5_TRIANGLE)) {
        enabled = !enabled;
        set_val(PS5_TRIANGLE, 0);   // swallow the press so the game does not see it
    }

    // While enabled and R2 is held, run the tapping combo.
    if(enabled && get_val(PS5_R2)) {
        combo_run(RapidFire);
    }

    // Show state in Device Monitor's trace window.
    set_val(TRACE_1, enabled);
}

combo RapidFire {
    set_val(PS5_R2, 100);
    wait(40);
    set_val(PS5_R2, 0);
    wait(30);
}

A few notes on why it is written this way:

  • set_val(PS5_TRIANGLE, 0) after the toggle stops the game from also receiving the Triangle press. This "current-cycle suppression" pattern appears throughout the official examples.
  • The combo re-runs as long as get_val(PS5_R2) stays true because combo_run is called every cycle; once the combo finishes it is started again.
  • TRACE_1 is a debug output visible in Zen Studio Legacy's Device Monitor. It has no effect on the game.
  • The 40 ms / 30 ms timings are a starting point. Games cap fire rates differently; tune with the device in hand. Our rapid fire guide goes deeper.

How do I compile and program it?

  1. Open Zen Studio Live in Chrome or Edge and connect the Zen via the PROG port.
  2. Open the Editor tab, paste the script, and click Compile. Fix any line the output pane flags.
  3. Drag the compiled script to a slot and click Program Slots.
  4. Unplug PROG, connect to your console or PC, and select the slot on the OLED.
  5. Test in a controller tester or a game's settings screen before trusting it in play.

What are the first mistakes to expect?

  • Toggling with get_val. Covered above; use event_press.
  • Forgetting main. Every script needs one. Zen Studio Live will merge multiple main blocks, but one is easier to read.
  • wait outside a combo. The compiler rejects it.
  • Values out of range. The compiler checks constants; if you compute a value, clamp it before set_val.
  • Compiling for the wrong platform. Use the identifiers that match your output protocol, or the cross-platform identifiers from the official guide.

Where next?

A reminder before you take any of this online: automating inputs is exactly what Epic and Activision prohibit and detect. Read Is the Cronus Zen allowed? first.

Frequently asked questions

Do I need programming experience?
No. GPC has a small surface: a handful of blocks, integer variables, if statements and built-in functions. If you can follow the examples on this page you can write useful scripts.
Which button names do I use?
Zen Studio Live's guide uses PS5_ prefixed identifiers such as PS5_R2 and PS5_CROSS. Cross-platform identifiers exist so a script written for PlayStation names still works on Xbox output; see the official guide's cross-platform identifiers page.
Why does my toggle flip randomly?
You toggled inside get_val, which is true on every cycle the button is held. Use event_press, which is true only on the cycle the button goes from released to pressed.
Where can I read more scripts?
The official GPC library inside Zen Studio Legacy holds thousands of free community scripts, and the official GPC Script Guide on guide.cronuszen.com has graded examples from beginner to advanced.

Sources

Every link was live when this guide was last updated.

  1. 01The smallest useful script (official GPC guide)guide.cronuszen.com
  2. 02init and main (official GPC guide)guide.cronuszen.com
  3. 03Combos and fcombo (official GPC guide)guide.cronuszen.com
  4. 04Toggle state without repeat firing (official GPC guide)guide.cronuszen.com
  5. 05Control value ranges (official GPC guide)guide.cronuszen.com

This guide is independent and unofficial; product names belong to their owners. Found an error? Use the contact page and we will correct it and note the change.