IC10
From Unofficial Stationeers Wiki
Contents
MIPS scripting language for IC10 housings / chips
# Text after a # will be ignored to the end of the line. The amount of white # space between arguments isn't important, but new lines start a new command.
Registers
The IC contains 16 registers, numbered r0-r15. Think of these as variables in other programming languages. In fact, you can name them with the alias command (see below).
To set a register directly (such as r0=2), use the move command. To read a value from a device, use l (load). To write a value back to a device, use s (set). Note that like most machine languages, the destination goes first, so instructions always look like: action destination source.
There are two more registers. One called ra (return address) and one called sp (stack pointer). The ra is used by certain jump and branching instructions (those ending with -al) to remember which line in the script it should return to. The sp tracks the next index within the stack (a memory that can store up to 512 values) to be pushed (written) to or popped (read) from. Neither ra or sp is protected, their values can be changed by instructions like any other register.
move r0 10
Sets r0 to the value 10
move r0 r1
Copies the value of r1 to r0
l r0 d0
Reads from device 0 and places the value in r0
s d0 r0
Writes the value from register 0 out to device 0
Device Ports
ICs can interact with up to 6 other devices via d0 - d5, as well as the device it's attached to via db. To change or set a device, use a screwdriver and adjust the device in the IC housing. You can read or set any of the device's properties, so it is possible to do things like read the pressure and oxygen content of a room on the same Device port.
The l (load) and s (set) instructions let you read and set values on a device.
l r0 d0 Temperature
#Reads the temperature from an atmosphere sensor into r0.
s d1 Setting r0
# Writes r0 to the device on port 1 to the Setting variable.
Labels
Lables are used to make it easier to jump between lines in the script. The label will have a numerical value that is the same as its line number. Even though it's possible to use a labels value for calculations, doing so is a bad idea since any changes to the code can change the line numbers of the labels.
main:
j main
Constants
Instead of using a register to store a fixed value, a constant can be made. Using this name will refer to the assigned value.
define pi 3.14159
move r0 pi
Indirect referencing
This is a way of accessing a register by using another register as a pointer. Adding an additional r infront of the register turns on this behaviour. The value stored in the register being used as the pointer must be between 0 to 15, this will then point to a register from r0 to r15, higher or lower values will cause an error.
move r0 5
stores the value 5 in r0
move rr0 10
is now the same as move r5 10
since r0 has the value 5, rr0 points at the register r5
Additional r's can be added to do indirect referencing multiple times in a row.
move r1 2
move r2 3
move rrr1 4
is now the same as move r3 4
since r1 points at r2 which points at r3
This also works with devices
move r0 2
stores the value 2 in r0
s dr0 On 1
is now the same as s d2 On 1
, r0 has the value 2 so dr0 points at d2
Debugging advice
A registers value can easily be checked by writing it to the Setting parameter of its IC housing, this has no sideeffects, too see the value just stand close and look directly at the housing (s db Setting r0
).
The configuration card can be used to manually check the data values of all devices.
Coding mistakes such as unfinished lines can only be detected by first exporting the code followed by looking directly at the chip (bug: laptops do not show these errors).
Instructions
- alias
- alias str r? d? # labels register or device reference with name. When alias is applied to a device, it will affect what shows on the screws in the IC base. (housing)
alias vTemperature r0
alias dAutoHydro1 d0
- move
- d s # stores the value of s in d
move r0 42 # Store 42 in register 0
- l (load)
- l r# d# parameter
Reads from a device (d#) and stores the value in a register (r#)
l r0 d0 Setting
Read from the device on d0 into register 0
l r1 d5 Pressure
Read the pressure from a sensor
This also works with aliases. For example:
alias Sensor d0
l r0 Sensor Temperature
- ls (load slot)
- ls r# d# slotNum parameter
Reads from a slot (slotNum) of a device (d#) and stores the value in a register (r#)
ls r0 d0 2 Occupied
Read from the second slot of device on d0, stores 1 in r0 if it's occupied, 0 otherwise.
And here is the code to read the charge of an AIMeE:
alias robot d0
alias charge r0
ls charge robot 0 Charge
- s (set)
- s d# parameter r#
Writes a setting to a device.
s d0 Setting r0
- add
- d s t # calculates s + t and stores the result in d
add r0 r1 1 # add 1 to r1 and store the result as r0
add r0 r0 1 # increment r0 by one
- sub
- d s t # calculates s - t and stores the result in d
- mul
- d s t # calculates s * t and stores the result in d
- div
- d s t # calculates s / t and stores the result in d
- mod
- d s t
- calculates s mod t and stores the result in d. Note this
- doesn't behave like the % operator - the result will be
- positive even if the either of the operands are negative
- slt
- d s t # stores 1 in d if s < t, 0 otherwise
- sqrt
- d s # calculates sqrt(s) and stores the result in d
- round
- d s # finds the rounded value of s and stores the result in d
- trunc
- d s # finds the truncated value of s and stores the result in d
- ceil
- d s # calculates the ceiling of s and stores the result in d
- floor
- d s # calculates the floor of s and stores the result in d
- max
- d s t # calculates the maximum of s and t and stores the result in d
- min
- d s t # calculates the minimum of s and t and stores the result in d
- abs
- d s # calculates the absolute value of s and stores the result in d
- log
- d s # calculates the natural logarithm of s and stores the result
- in d
- exp
- d s # calculates the exponential of s and stores the result in d
- rand
- d # selects a random number uniformly at random between 0 and 1
- inclusive and stores the result in d
- boolean arithmetic uses the C convention that 0 is false and any non-zero
- value is true.
- and
- d s t # stores 1 in d if both s and t have non-zero values,
- 0 otherwise
- or
- d s t # stores 1 in d if either s or t have non-zero values,
- 0 otherwise
- xor
- d s t # stores 1 in d if exactly one of s and t are non-zero,
- 0 otherwise
- nor
- d s t # stores 1 in d if both s and t equal zero, 0 otherwise
- Lines are numbered starting at zero
- j
- a # jumps to line a.
- bltz
- s a # jumps to line a if s < 0
- blez
- s a # jumps to line a if s <= 0
- bgez
- s a # jumps to line a if s >= 0
- bgtz
- s a # jumps to line a if s > 0
- beq
- s t a # jumps to line a if s == t
- bne
- s t a # jumps to line a if s != t
- bdseal
- d? a(r?|num) # Jump execution to line a and store current line number if device d? is set.
bdseal d0 32 #Store line number and jump to line 32 if d0 is assigned.
bdseal dThisVictim HarvestCrop #Store line in ra and jump to sub HarvestCrop if device dThisVictim is assigned.
- yield
- # ceases code execution for this power tick
- lb
- r? typeHash var batchMode # Loads var from all output network devices with provided typeHash using provided batchMode: Average(0), Sum (1), Minimum (2), Maximum (3). Can be used word or number. Result store into r?
- sb
- typeHash var r? # Store register r? to var on all output network devices with provided typeHash
- #
- # The following text will be ignored during compiling; use this to create comments.
Conditional functions cheatsheet
suffix | description | branch to line | branch and store return address | relative jump to line | set register |
---|---|---|---|---|---|
prefix: | b- | b-al | br- | s- | |
unconditional | j | jal | jr | ||
-eq | if a == b | beq | beqal | breq | seq |
-eqz | if a == 0 | beqz | beqzal | breqz | seqz |
-ge | if a >= b | bge | bgeal | brge | sge |
-gez | if a >= 0 | bgez | bgezal | brgez | sgez |
-gt | if a > b | bgt | bgtal | brgt | sgt |
-gtz | if a > 0 | bgtz | bgtzal | brgtz | sgtz |
-le | if a <= b | ble | bleal | brle | sle |
-lez | if a <= 0 | blez | blezal | brlez | slez |
-lt | if a < b | blt | bltal | brlt | slt |
-ltz | if a < 0 | bltz | bltzal | brltz | sltz |
-ne | if a != b | bne | bneal | brne | sne |
-nez | if a != 0 | bnez | bnezal | brnez | snez |
-dns | if device d is not set | bdns | bdnsal | brdns | sdns |
-dse | if device d is set | bdse | bdseal | brdse | sdse |
-ap | if a approximately equals b | bap | bapal | brap | sap |
-apz | if a approximately equals 0 | bapz | bapzal | brapz | sapz |
-na | if a not approximately equals b | bna | bnaal | brna | sna |
-naz | if a not approximately equals 0 | bnaz | bnazal | brnaz | snaz |
All b-
commands require target line as last argument, all s-
commands require register to store result as first argument. All br-
commands require number to jump relatively as last argument. e.g. breq a b 3
means if a=b then jump to 3 lines after.
All approximate functions require additional argument denoting how close two numbers need to be considered equal. E.g.: sap r0 100 101 0.01
will consider 100 and 101 almost equal (not more than 1%=0.01 different) and will set r0 to 1. The exact formula is if abs(a - b) <= max(c * max(abs(a), abs(b)), float.epsilon * 8)
for -ap
and is similar for other approximate functions.
Device Variables
- Activate
- 1 if device is activated (usually means running), otherwise 0
l r0 d0 Activate # sets r0 to 1 if on or 0 if off
- AirRelease
- Charge
- The current charge the device has.
- CLearMemory
- When set to 1, clears the counter memory (e.g. ExportCount). Will set itself back to 0 when triggered.
- Color
- 0 (or lower) = Blue
- 1 = Grey
- 2 = Green
- 3 = Orange
- 4 = Red
- 5 = Yellow
- 6 = White
- 7 = Black
- 8 = Brown
- 9 = Khaki
- 10 = Pink
- 11 (or higher) = Purple
- CompletionRatio
- ElevatorLevel
- ElevatorSpeed
- Error
- 1 if device is in error state, otherwise 0
- ExportCount
- How many items exporfted since last ClearMemory.
- Filtration
- The current state of the filtration system. For example filtration = 1 for a Hardsuit when filtration is On.
- Harvest
- Performs the harvesting action for any plant based machinery.
-
s d0 Harvest 1 # Performs 1 harvest action on device d0
- Horizontal
- HorizontalRatio
- Idle
- ImportCount
- Lock
- Maximum
- Mode
- On
- Open
- Output
- Plant
- Performs the planting operation for any plant based machinery.
-
s d0 Plant 1 # Plants one crop in device d0
- PositionX
- PositionY
- PositionZ
- Power
- PowerActual
- PowerPotential
- PowerRequired
- Pressure
- PressureExternal
- PressureInteral
- PressureSetting
- Quantity
- Total quantity in the device.
- Ratio
- Context specific value depending on device, 0 to 1 based ratio.
- RatioCarbonDioxide
- RatioNitrogen
- The ratio of nitrogen in device atmosphere.
- RatioOxygen
- The ratio of oxygen in device atmosphere.
- RatioPollutant
- The ratio of pollutant in device atmosphere.
- RatioVolatiles
- The ratio of volatiles in device atmosphere.
- RatioWater
- The ratio of water in device atmosphere.
- Reagents
- RecipeHash
- RequestHash
- RequiredPower
- Setting
- SolarAngle
- Solar angle of the device.
-
l r0 d0 SolarAngle # Sets r0 to the solar angle of d0.
- Temperature
- TemperatureSettings
- TotalMoles
- VelocityMagnitude
- VelocityRelativeX
- VelocityRelativeY
- VelocityRelativeZ
- Vertical
- Vertical setting of the device.
- VerticalRatio
- Ratio of vertical setting for device.
- Volume
- Returns the device atmosphere volume
Slot Variables
In general (always?) slots are assigned as follows.
- Slot 0: Import
- Slot 1: Export
- Slot 2: Inside Machine
- Occupied
ls r0 d0 2 Occupied #Stores 1 in r0 if d0 has more seeds
ls vOccupied dThisVictim 2 Occupied #stores 1 in vOccupied if dThisVictim has more seeds
- OccupantHash
- Quantity
- Damage
- Efficiency
- Health
- Growth
ls r0 d0 0 Growth # Store the numerical growth stage of d0 in r0
- Pressure
- Temperature
- Charge
- ChargeRatio
- Class
- PressureWaste
- PressureAir
- MaxQuantity
- Mature
ls r0 d0 0 Mature # Store 1 in r0 if d0 has a mature crop
ls vMature dThisVictim 0 Mature # Store 1 in vMature if dThisVictim has a mature crop
Examples
This example script automates autohydro units and powers the lights off during the day when they're not needed. (Hit Expand)
Uses aliases, sub-routines and comments to minimize lines of code and adaptability.
alias vMature r0 alias vOccupied r1 alias isDayLight r2 alias isOccupied r3 alias dSensor d5 #start of Program Loop start: l isDayLight dSensor Activate #Check if it's daytime or not. # For each device, harvest, plant, powerdown, then power on depending on conditions. alias dThisVictim d0 #Begin processing device 0 bdseal dThisVictim HarvestCrop bdseal dThisVictim PlantCrop bgtzal isDayLight PowerDown blezal isDayLight TurnitOn alias dThisVictim d1 #Begin processing device 1 bdseal dThisVictim HarvestCrop bdseal dThisVictim PlantCrop bgtzal isDayLight PowerDown blezal isDayLight TurnitOn alias dThisVictim d2 #Begin processing device 2 bdseal dThisVictim HarvestCrop bdseal dThisVictim PlantCrop bgtzal isDayLight PowerDown blezal isDayLight TurnitOn alias dThisVictim d3 #Begin processing device 3 bdseal dThisVictim HarvestCrop bdseal dThisVictim PlantCrop bgtzal isDayLight PowerDown blezal isDayLight TurnitOn alias dThisVictim d4 #Begin processing device 4 bdseal dThisVictim HarvestCrop bdseal dThisVictim PlantCrop bgtzal isDayLight PowerDown blezal isDayLight TurnitOn #Can't do a D5 because that's our sensor. j start #Return to the beginning of the program loop. (Yields here may save processing power) HarvestCrop: ls vMature dThisVictim 0 Mature blez vMature ra #If the crop is not mature, return s dThisVictim Harvest 1 #If the crop is mature, harvest it (one). j ra #return PlantCrop: ls vOccupied dThisVictim 2 Occupied #seeds to plant blez vOccupied ra #If the machine has no seeds to plant, return. ls vOccupied dThisVictim 0 Occupied #something growing bgtz vOccupied ra # If the crop plot is occupied, return. s dThisVictim Plant 1 # if we made it this far, plant the crop j ra #return PowerDown: s dThisVictim On 0 #Power the machine down. j ra #Jump to line we came from TurnitOn: s dThisVictim On 1 #Power the machine up j ra ########## #### End Script ##########
This is a sample timer command set, alternating between 1 for 1 tick (0.5s), then off for 2 ticks (1s).
move r0 0 # Line 0: move the value 0 to register0 sub r1 r0 3 # Line 1: subtract 3 from the value in r0 and write it to r1 bltz r1 4 # Line 2: jump to line 4 if r1 < 0 (skip the next line) move r0 0 # Line 3: move the value 0 to register0 slt o r0 1 # Line 4: if r0 < 1 write 1 to the output, otherwise 0. add r0 r0 1 # Line 5: increment r0 by 1 yield # Line 6: wait until next power tick (0.5s) j 1 # Line 7: jump back to line 1 ########## #### End Script ##########
Example:
so you will do l r0 d0 SolarAngle Sorry had last args swapped That would read in the value while, s d1 Vertical r0 Would write the contents of r0 into the devices 1's Vertical property additionally you can make some aliases alias SolarSensor d0 l r0 SolarSensor SolarAngle ########## #### End Script ##########
Another example:
Now the IC is inserted into the housing. The screws D0-D5 can be adjusted directly to the equipment (sensor, console, solar panel, etc.). The ports 'o' and 'i0-i2' have been removed. Instead, commands that directly read and write hardware parameters are added. l <register> <data_channel> <parameter> reads the value of the parameter s <data_channel> <parameter> <register_or_value> writes the value of the parameter ls <register> <data_channel> <slot_number> <parameter> reads the parameter value from the slot For example, l r0 d0 Horizontal s d5 Activate 1 ls r3 db 0 OccupantHash ########## #### End Script ##########
Links
- [1] Stationeering.com offers a programmable circuits simulator so you can develop your code without repeatedly dying in game!
- [2]
- [3]
- [4] syntax highlighting for IC10 MIPS for KDE kwrite/kate text editor
- [5] syntax highlighting for IC10 MIPS for Notepad++
- [6] syntax highlighting for IC10 MIPS for Notepad++ (updated: 05/05/2021)