Actions

Advanced IC10 Programming

From Unofficial Stationeers Wiki

Revision as of 01:48, 22 February 2026 by TK421 (talk | contribs) (Using syntax highlighting module instead)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

VS code extension[edit]

For convenient operation, there is an extension for the visual studio code IDE Link

Web version: https://ic10.dev/

and compiler ICX

Flow Control And Data Manipulation[edit]

NOTE: This level of coding is NOT needed to play the game to it's full extent. it's aimed at people looking for custom, self-inspired challenges.

Devices By Register[edit]

You can use a register to access the device based on pin number.

move r0 0 next: s dr0 Horizontal 0 s dr0 Vertical 0 s dr0 On 0 add r0 r0 1 blt r0 6 next

Functions[edit]

main: jal MyFunction j main MyFunction: ... j ra

A function is just a label we jump to, but using the -al version of branch instructions (jal, beqzal) as they store the return address into the special ra register. When calling a function from another function (or from itself), ra will be overwritten so we have to store it in the stack and take it out when the function completes:

main: jal _MyFunction j main _MyFunction: push ra jal _MySecondFunction pop ra j ra _MySecondFunction: ... j ra

If we hadn't used the stack, the jump at the end of _MyFunction would take us to the call of _MySecondFunction instead of the main section.

Loops[edit]

alias rIterator r0 
 main: 
move rIterator 0 
 Loop: 
 ... 
add rIterator rIterator 1 
blt rIterator 4 Loop 

j main 

The challenge with loops is to keep them clean. Relative jumps are a great way to save lines but they can quickly turn code messy because adding lines might break them if you don't adjust the relative jump. If code length is not an issue, stick to labels where possible.

Indexing With Relative Jump[edit]

alias rIndex r0
alias rTemp r1
alias rValue r2

main:
move rIndex 1
mul rTemp rIndex 2
add rTemp rTemp 1
jr rTemp
move rValue 123 #Index 0
j Select_end
move rValue 456 #Index 1
j Select_end
move rValue 789 #Index 2
j Select_end
...
Select_end:
j main

Use this to set one or more parameters or call functions using an index number you calculated (or read from a dial button). We multiply it by 2 because we need space for a jump after each move command so we don't run the subsequent ones and we add 1 because for a 0 index "jr 0" would lock up our IC.

Indexing With Comparison[edit]

alias rIndex r0
alias rValue r1

main:
move rIndex 1</span>
move rValue  123 #Index 0
sub rIndex rIndex 1
select rValue rIndex rValue 456 #Index 1
sub rIndex rIndex 1
select rValue rIndex rValue 789 #Index 2
j main

In most programming languages, you can do the same thing in different ways. A third way would be to use the stack.

Redefining Aliases[edit]

Say you have a complex function that manipulates a device (reads/writes multiple parameters, controls timing etc) and you want to reuse it for multiple devices. You could copy paste the whole function, or you could redefine the alias you used and point it to another device, like this:

main:
alias dCurrent d0
jal _MyFunction
alias dCurrent d1
jal _MyFunction
j main

NOTE: This wouldn't work in real languages since aliases and defines are just directives for the (pre)compiler, they're not evaluated during runtime by the CPU

You can combine this with a loop and indexing to run your function on multiple devices automatically.

alias rIterator r0
alias rTemp r1
main:
move rIterator 0
Loop:
jal _UpdateReference
jal _FunctionForDevice
add rIterator rIterator 1
bgt rIterator 3 Loop_End
j Loop
Loop_End:
j main

_UpdateReference:
mul rTemp rIterator 2
add rTemp rTemp 1
jr rTemp
alias dCurrentDevice d0 #Index 0
j Select_end
alias dCurrentDevice d1 #Index 1
j Select_end
alias dCurrentDevice d2 #Index 2
j Select_end
alias dCurrentDevice d3 #Index 3
j Select_end
Select_end:
j ra

_FunctionForDevice:
#Manipulate dCurrentDevice
j ra

Device Manipulation[edit]

Timing And Parameters[edit]

Some devices don't react well to having parameters changed while they're performing an action such as import or export. Notable mentions are the stacker, sorter and the vending machine. You can avoid them locking up (or getting jammed with items) either by adding delays (yield, sleep) or by actively waiting for their slots to become unoccupied, or their Activation to become 0.

WaitForDevices:
yield
ls rBusy dSorter 0 Occupied
bgtz rBusy WaitForDevices
ls rBusy dSorter 1 Occupied
bgtz rBusy WaitForDevices
ls rBusy dSorter 2 Occupied
bgtz rBusy WaitForDevices
ls rBusy dVender 0 Occupied
bgtz rBusy WaitForDevices
ls rBusy dVender 1 Occupied
bgtz rBusy WaitForDevices
j ra

NOTE: The slot reader labels slots from 1 but in the IC they start at 0. It is also a good idea to check any device involved in your solution with both a logical and slot reader as the current databases may not list all existing slots or parameters. You should always make use of all data available from devices as they may greatly simplify your project.

Using delays is convenient, but has downsides. You're giving up real-time control over the process and may miss certain events or react too late and cause a device to jam. You also need to consider that code takes time to run, and for example if you have a complicated condition for setting the output of a sorter depending on the item that entered it, it may be better to leave it OFF by default and only turn it on once the output is correctly set. (Devices react differently to being fed items while powered down. ie the stacker will keep it in the Import slot but the vending machine will completely import it, so make sure to manually test everything you can prior to automating it)

Detecting devices on a network[edit]

Sometimes it is convenient to use code to detect the devices connected to the data network, instead of using pins on the housing, or via usage of the batch commands (such as lbn or sbn). The current way to detect attached devices is via a get command, passing in a network id: get r0 db:0 3.

What the above snippet does is to run the get command, addressed to the network connection (network 0 in db:0) attached to the housing of the chip (db). The get command normally accesses the stack of the device being addressed (such as the chip itself, or a sorter), but if the address being passed to the get command is a network reference (with the colon and number indicating which connection), then the getcommand will return the ReferenceId of the device at the given index (3 in the example above - if there is no such a device at the index, then -1 is returned). The order is not determined by anything specific (even though it seems to remain the same until the network itself is changed, so write your code accordingly).

With a ReferenceId being returned (in the example above it is saved in r0), this can be used in a later command to obtain information about the device - such as their PrefabHash to detect the device type (and/or any other LogicProperty it has available).

One scenario where this is useful is in dynamically detecting newly attached structures without a priori having their device name(s), or even a count of how many, and being able to control them individually (rather than as a batch like one would for solar tracking) - centrifuges is one such type of device where this is helpful, since their cycle times are not synced up, you cannot use a batch command to control them (without losing efficiency). Below is reproduced some code from various reddit posts that discuss this scenario:

alias refid r14
alias index r15
alias devicecount r13
alias ticks r12
define centrifuge HASH("StructureCentrifuge")

discoveryinit:
yield
move sp 0
lb r0 centrifuge PrefabHash Sum
div devicecount r0 centrifuge
move index 0

discovery:
get refid db:0 index
l r0 refid PrefabHash
bne r0 centrifuge wrongid
push refid
s refid On 1

wrongid:
beq devicecount sp maininit
add index index 1
j discovery

maininit:
move ticks 0
beqz sp discoveryinit

main:
bge ticks 120 discoveryinit
add ticks ticks 1
move sp devicecount
yield

loop:
beqz sp main
pop refid
bdns refid discoveryinit
l r0 refid Error
beqz r0 loop                  
l r0 refid Reagents
sge r0 r0 5
s refid Open r0
j loop

Sample Projects[edit]

Vending Machine Exporter[edit]

Vending_Machine_Export_IC10