Actions

Editing MIPS

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.
Latest revision Your text
Line 1: Line 1:
 
[[Category:MIPS Programming]]
 
[[Category:MIPS Programming]]
 
=MIPS scripting language for IC10 housings / chips=
 
=MIPS scripting language for IC10 housings / chips=
MIPS is [[Stationeers]]' inspiration for the in-game scripting language called IC10. It runs on [[Integrated Circuit (IC10)|IC10 chips]] crafted at the [[Electronics Printer]].  
+
 
 +
<pre>
 +
# 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.
 +
</pre>
  
 
==Registers==
 
==Registers==
Internal registers '''r?''': The IC contains 16 CPU registers, numbered '''r0''' to '''r15'''. From now on referred to as '''r?'''.
+
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).
  
Device registers '''d? logicType''': Device registers are written to and from the IC. A device register is numbered '''d0''' to '''d5''' (select via screw), or '''db''' (connected device). From now on referred to as '''d?'''.
+
To set a register directly (such as r0=2), use the <b>move</b> 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 <i>destination</i> goes first, so instructions always look like: action destination source.
  
=== Logic and algorithmic with '''Internal registers''' ===
+
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.
All calculations are exclusively performed to and from '''r?''' registers, or generally more understood as variables in programming. You can use aliases to give convenient names with the <code>alias string r?|d?</code>command (see below).  
 
  
Internal registers can be manipulated in various ways.
+
<code>move r0 10</code><br>Sets r0 to the value 10
* Write constant values <code>move r? (r?|num)</code>: Example: <code>move r0 2</code> sets r0 to the number 2.
 
* Calculate: Calculations are done to- and from these registers, like <code>add r? a(r?|num) b(r?|num)</code>. Example: <code>add r1 r0 3</code> adds 3 to r0, and writes to r1.
 
  
Note, for any kind of if statements or loop behaviours, knowing about labels, branching, and jumps is essential knowledge. See below.
+
<code>move r0 r1</code><br>Copies the value of r1 to r0
  
=== IO to '''Device registers''' ===
+
<code>l r0 d0</code><br>Reads from device 0 and places the value in r0
Acronym '''d?''' stands for device, where ? is a number corresponding to the screw device selector on the socket.
 
You can also read/write to the device where the IC is planted in using device '''db'''.
 
  
Generally, there are up to 6 devices which can be set using the screwdriver '''d0''' to '''d5'''. A special device register '''db''' is the device wherever the IC is mounted upon. Very convenient for atmospheric devices where no separate IC socket is required.
+
<code>s d0 r0</code><br>Writes the value from register 0 out to device 0
  
Note, the IC is completely unaware where d? is actually connected to. So if you get a logicType error, check d? number, or check if the screw has been set opn the socket. An alias is only convenient to convey what is expected to be set on the d? screw, it does not actually set or program the screq.
+
==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.  
  
* Read from device (load) <code>l r? d? logicType</code>: Reads logicType, like Pressure from a [[Sensors|gas sensor]], from device d? to register r?. Values can be read from connected devices and put into the register using the '''l''' (load) command. For example, if you want to load the state of a door. <br> Example: <code>l r0 Door Open</code> reads the 'Open' field of an object named 'Door', that would be connected to the IC housing of the chip.
+
The l (load) and s (set) instructions let you read and set values on a device.
* Write to a device (set) <code>s d? logicType r?</code>: Write a value from a register back to a device using the command <code>s d? logicType r?</code>. For example, if d0 is set to a door using the screwdriver, <code>s d0 Open 0</code> sets the 'Open' status of the d0 (a door) to 0, effectively closing the door.
 
  
=== batch IO to - '''Device registers''' ===
+
<code>l r0 d0 Temperature</code> #Reads the temperature from an atmosphere sensor into r0.
'''Batch writing''' needs to be done to a specific '''deviceHash''' instead of d?. Is unique per device type, which you can find in the [[Stationpedia]] entries.
 
* <code>lb r? deviceHash logicType batchMode</code>
 
* <code>sb deviceHash logicType r?</code>
 
Additionally, using the following batch commands, a '''nameHash''' can be provided to only modify devices with a certain name.
 
* <code>lbn r? deviceHash nameHash logicType batchMode </code>
 
* <code>sbn deviceHash nameHash logicType r?</code>
 
  
'''batchMode''' is a parameter equal to 0, 1, 2, or 3. These are also defined as the constants '''Average''', '''Sum''', '''Minimum''', and '''Maximum''' respectively. The word or number can be used.
+
<code>s d1 Setting r0 </code> # Writes r0 to the device on port 1 to the Setting variable.
  
Combining one of these functions with the <code>HASH()</code> function can be advantageous:
+
==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.
<code>lbn r0 HASH("StructureGasSensor") HASH("Sensor 1") Temperature Average</code>
+
<br><code>main:</code>
 
+
<br><code>j main</code>
This code will load the average temperature of all gas sensors on the network named "Sensor 1" onto register '''r0'''
 
 
 
If the batch read (lb/lbn) is done on a network without any matching devices the results will be as specified in the table:
 
{| class="wikitable"
 
|+ Batch read with no devices
 
|-
 
! Batch Mode !! Result
 
|-
 
| Average (0) || nan
 
|-
 
| Sum (1) || 0
 
|-
 
| Minimum (2) || 0
 
|-
 
| Maximum (3) || ninf
 
|}
 
 
 
=== Examples ===
 
 
 
Here are some examples demonstrating all three operations:
 
 
 
<code>move r0 10</code><br>Sets register '''r0''' to the value 10
 
 
 
<code>move r0 r1</code><br>Copies the value of register '''r1''' to register '''r0'''
 
 
 
<code>l r0 d0 Temperature</code><br>Reads the Temperature parameter from device '''d0''' and places the value in register '''r0'''.
 
Note: not all devices have a Temperature parameter, check the in-game stationpedia.
 
 
 
To set a device specific value (like '''On'''), you can write into this value.
 
 
 
<code>s d0 On r0</code><br>Writes the value from register '''r0''' out to '''On''' parameter of device '''d0'''. In this example the device will be turned On, if valve of register r0 equals 1, otherwise (register r0 equals 0) it will turned off. See section [[MIPS#Device_Variables|Device Variables]].
 
 
 
It's recommended to use labels (like: ''someVariable'') instead of a direct reference to the register. See '''alias''' in section [[MIPS#Instructions|Instructions]].
 
 
 
=== Special registers ===
 
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.
 
 
 
==Stack Memory==
 
;push r?: adds the value  '''r?''' and increments the '''sp''' by 1.
 
;pop r?: loads the value in the stack memory at index <code>sp-1</code> into register '''r?''' and decrements the '''sp''' by 1.
 
;peek r?: loads the value in the stack memory at index <code>sp-1</code> into register '''r?'''.
 
;get r? d? address(r?|num): loads the value in the stack memory at index <code>address</code> on provided device into register '''r?'''.
 
;getd r? id(r?|num) address(r?|num): loads the value in the stack memory at index <code>address</code> on provided device id into register '''r?'''.
 
;put d? address(r?|num) value(r?|num): adds the value to the stack memory off the provided device at index <code>address</code>.
 
;putd id(r?|num) address(r?|num) value(r?|num) : adds the value to the stack memory off the provided device id at index <code>address</code>.
 
 
 
As mentioned previously, '''sp''' can be both written to and read from any time. When reading ('''peek''' or '''pop'''), '''sp''' must be between 1 and 512, inclusive. While writing ('''push'''), '''sp''' must be between 0 and 511, inclusive.
 
 
 
Stack memory is persistent on logic chips. This means that if you have a logic chip and push values to the stack, the code that pushes those values can be removed and the stack will retain those values.
 
 
 
Note that this does not carry over to any other logic chips which receive the program of the original; They will need to have their stack memories programmed individually.
 
 
 
'''Stack Traversing'''
 
 
 
Traversing the stack can be done similarly to how an array would be traversed in some other languages:
 
{{MIPSCode|
 
#this will traverse indices {min value} through {max value}-1
 
move sp {min value}
 
loop:
 
add sp sp 1
 
peek r0
 
 
 
#do something here with your stack values (loaded into r0)
 
 
 
blt sp {max value} loop
 
 
 
#continue on
 
}}
 
  
Alternatively, you can use the pop function's decrementing to make a more efficient loop:
 
{{MIPSCode|
 
move sp {max value}
 
add sp sp 1
 
loop:
 
pop r0
 
 
#do something here with your stack values (loaded into r0)
 
 
bgt sp {min value} loop
 
 
#continue on
 
 
}}
 
 
==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 or oxygen content of a room on the same Device port.
 
 
Additionally, is possible to set other IC housings as devices, allowing you to create programs that run across multiple ICs together. For example, an Gas Mixing IC could check the ''' Setting'''  field of a Atmosphere Sensor IC and act based on the value of the sensor chip.
 
 
The '''l''' (load) or '''s''' (set) instructions you have to read or set these values to your device. Examples:
 
{{MIPSCode|
 
#Reads the 'Temperature' from an atmosphere sensor
 
# at device port 'd0' into register 'r0'.
 
l r0 d0 Temperature
 
}}
 
{{MIPSCode|
 
# Writes the value of the register 'r0' to the
 
# device on port 'd1' into the variable 'Setting'.
 
s d1 Setting r0
 
}}
 
 
==Labels==
 
Labels 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.
 
{{MIPSCode|
 
main: # define a jump mark with label 'main'
 
j main # jumps back to 'main'
 
}}
 
 
==Constants==
 
==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. With the help of Constants you can save register places.
+
Instead of using a register to store a fixed value, a constant can be made. Using this name will refer to the assigned value.
{{MIPSCode|
+
<br><code>define pi 3.14159</code>
# defines a Constant with name 'pi'
+
<br><code>move r0 pi</code>
# and set its value to 3.14159
 
define pi 3.14159
 
}}
 
  
You can use these constants like any other variables (see: alias in section [[MIPS#Instructions|Instructions]]). Example:
+
==Indirect referencing==
{{MIPSCode|
+
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.
# set the value of register 'r0' to the value of constant named 'pi'.
 
move r0 pi
 
}}
 
  
==Indirect referencing==
+
<code>move r0 5</code> stores the value 5 in r0
This is a way of accessing a register by using another register as a pointer. Adding an additional r in front 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.
+
<br><code>move rr0 10</code> is now the same as <code>move r5 10</code> since r0 has the value 5, rr0 points at the register r5
{{MIPSCode|
 
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.
 
Additional r's can be added to do indirect referencing multiple times in a row.
{{MIPSCode|
+
<br><code>move r1 2</code>
move r1 2
+
<br><code>move r2 3</code>
move r2 3
+
<br><code>move rrr1 4</code> is now the same as <code>move r3 4</code> since r1 points at r2 which points at r3
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
 
This also works with devices
{{MIPSCode|
+
<br><code>move r0 2</code> stores the value 2 in r0
move r0 2 # stores the value 2 in r0
+
<br><code>s dr0 On 1</code> is now the same as <code>s d2 On 1</code>, r0 has the value 2 so dr0 points at d2
s dr0 On 1  
 
# is now the same as 's d2 On 1'
 
# r0 has the value 2 so dr0 points at d2
 
}}
 
  
==Network Referencing / Channels==
 
  
All cable networks have 8 Channels which can have data loaded from/stored to via a device and connection reference. Connections for each supported device are listed in the stationpedia. All 'connections' a device can make are a connection (pipe, chute, cable), but only cable networks have channels.
+
==Instructions==
 +
----
  
The 8 channels (Channel0 to Channel7) are however volatile, in that data is destroyed if any part of the cable network is changed, removed, or added to, and also whenever the world is exited. All these channels default to NaN. Strictly speaking, they default to what we would call "quiet NaN", in that its not an error it simply means its not a number yet. Recommend you use these channels for reading and writing between networks, rather than as a data store. This effectively means an IC can read all the networks for all devices to connected to it, so not just their own local network, but any networks any device they can reference is connected to.
+
<div id="alias"></div>
{{MIPSCode|
+
;alias
# d0 is device zero, and the :0 refers
+
: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)
# to that device's 0 connection
+
<code>alias vTemperature r0</code>
l r0 d0:0 Channel0}}
+
<br>
 +
<code>alias dAutoHydro1 d0</code>
  
For example: on an IC Housing, the 0 connection is the data port and 1 is power, so you could write out r0 to Channel0 of the power network of the Housing using <code>s db:1 Channel0 r0</code>
+
<div id="move"></div>
 +
;move   
 +
:d s    # stores the value of s in d
 +
<code>move r0 42 # Store 42 in register 0</code>
  
==Comments==
+
<div id="l"></div>
Comments can be placed using a '''#''' symbol. All comments are ignored by the game when it reads commands. Below is an example of valid code with two comments.
+
<div id="load"></div>
{{MIPSCode|
+
;l (load)
alias MyAlias r0 # Text after the hash tag will be ignored to the end of the line.
+
:l r# d# parameter
# You can also write comments on their own lines, like this.
+
Reads from a device (d#) and stores the value in a register (r#)
}}
 
  
==Debugging advices==
+
<code>l r0 d0 Setting</code><br>Read from the device on d0 into register 0
The value stored in a register or variable can easily be displayed by writing it to the Setting parameter of the IC housing. This has no side effects. To see the value, just stand close to the IC housing and look directly at the housing.<br>
 
<code>s db Setting r0</code>. # sets/writes the value of register '''r0''' into the parameter '''Setting''' of the IC Housing('''db''')
 
  
To check if a certain block of code is executed, use the above trick but with a random number that you choose, like the line number.<br> This example will display the number 137 on the IC housing.<br>
+
<code>l r1 d5 Pressure</code><br>Read the pressure from a sensor
<code>s db Setting 137</code> # sets/writes the number 137 into the parameter '''Setting''' of the IC Housing('''db''')
 
  
Always use unique names for labels. When a label is named after a MIPS keyword like "Temperature:" or "Setting:" the original meaning of the keyword is overwritten, so when an instruction tries to use it an error will occur.
+
This also works with aliases. For example:
 +
<code>
 +
alias Sensor d0
 +
l r0 Sensor Temperature
 +
</code>
  
A [[Cartridge#Configuration|configuration cartridge]] installed in a [[Handheld_Tablet|tablet]]  can be used to see all available values and configuration parameter for all devices you focus on.
+
<div id="s"></div>
 +
<div id="set"></div>
 +
;s (set)
 +
:s d# parameter r#
 +
Writes a setting to a device.  
  
==Learning MIPS==
+
<code>s d0 Setting r0</code>
MIPS can be difficult to get started with. So here is a list of instructions that are useful for beginners. These can be used to write many different scripts.
 
  
General:
 
* <code>alias</code> make the script easier to read by assigning a name to a register or device, example: <code>alias rTemperature r15</code>
 
* <code>label:</code> where "label" can be replaced with almost any word, jump and branch instructions can use these in place of line numbers, example: <code>start:</code>
 
* <code>yield</code> pause for 1-tick and then resume, if not used the script will automatically pause for 1-tick after 128 lines
 
 
 
<br>Jumps:
 
*<code>j someLabelName</code> jump to line with '''someLabelName'''
 
*<code>jal someLabelName</code> stores the next line number into the register ra (return address) and then jump to '''someLabelName'''
 
*<code>j ra</code> jump to register ra (return address)
 
  
 +
<div id="add"></div>
 +
;add   
 +
:d s t  # calculates s + t and stores the result in d
 +
<code>add r0 r1 1 # add 1 to r1 and store the result as r0</code>
 +
<br>
 +
<code>add r0 r0 1 # increment r0 by one</code>
 +
<div id="sub"></div>
 +
;sub   
 +
:d s t  # calculates s - t and stores the result in d
 +
<div id="mul"></div>
 +
;mul   
 +
:d s t  # calculates s * t and stores the result in d
 +
<div id="div"></div>
 +
;div   
 +
:d s t  # calculates s / t and stores the result in d
 +
<div id="mod"></div>
 +
;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
  
<br>Branching (jump-if):<br>
+
<div id="slt"></div>
<code>beq a(r?|num) b(r?|num) c(r?|num)</code> if '''a''' is equal to '''b''' goto '''c'''  (label or linenumber) <br>
+
;slt   
<code>bne a(r?|num) b(r?|num) c(r?|num)</code> if  '''a''' not-equal '''b''' goto  '''c''' (label or linenumber) <br>
+
:d s t   # stores 1 in d if s < t, 0 otherwise
<code>bgt a(r?|num) b(r?|num) c(r?|num)</code> if  '''a''' greater than '''b''' goto   '''c''' (label or linenumber) <br>
 
<code>blt a(r?|num) b(r?|num) c(r?|num)</code> if '''a''' less than '''b''' goto '''c''' (label or linenumber) <br>
 
The suffix -al can be added to each of these (example: beqal) to save the '''next''' line number into the "return address" register. this is called using <code>j ra</code>
 
  
<br>Device interactions:
+
<div id="sqrt"></div>
<pre>
+
;sqrt   
l (load)
+
:d s    # calculates sqrt(s) and stores the result in d
lb (load batch, requires one of the following: 0(Average) / 1(Sum) / 2(Minimum) / 3(Maximum))
+
<div id="round"></div>
ls (load slot)
+
;round 
s (store)
+
:d s    # finds the rounded value of s and stores the result in d
sb (store batch)
+
<div id="trunc"></div>
</pre>
+
;trunc 
 +
:d s    # finds the truncated value of s and stores the result in d
 +
<div id="ceil"></div>
 +
;ceil 
 +
: d s     # calculates the ceiling of s and stores the result in d
 +
<div id="floor"></div>
 +
;floor 
 +
: d s    # calculates the floor of s and stores the result in d
  
<br>Logic and Math:
+
<div id="max"></div>
<pre>
+
;max   
seqz (common NOT-gate: turns 0 into 1, and all other values into 0)
+
: d s t  # calculates the maximum of s and t and stores the result in d
move
+
<div id="min"></div>
add (addition)
+
;min   
sub (subtraction)
+
: d s t  # calculates the minimum of s and t and stores the result in d
mul (multiplication)
+
<div id="abs"></div>
div (division)
+
;abs   
</pre>
+
: d s    # calculates the absolute value of s and stores the result in d
 +
<div id="log"></div>
 +
;log   
 +
: d s    # calculates the natural logarithm of s and stores the result
 +
::# in d
 +
<div id="exp"></div>
 +
;exp   
 +
: d s    # calculates the exponential of s and stores the result in d
 +
<div id="rand"></div>
 +
;rand 
 +
: d      # selects a random number uniformly at random between 0 and 1
 +
::# inclusive and stores the result in d
  
<br>Common device variables:
+
::# boolean arithmetic uses the C convention that 0 is false and any non-zero
<pre>
+
::# value is true.
On (1 is on, 0 is off)
+
<div id="and"></div>
Open (1 is open, 0 is closed)
+
;and   
Setting (meaning varies between devices, example: a LED display(console) will show this value)
+
: d s t  # stores 1 in d if both s and t have non-zero values,
Activate (1 usually means running, example: a Daylight sensor is 1 when the sun shines on it)
+
::# 0 otherwise
Temperature (in Kelvin, Celsius - 273.15)
+
<div id="or"></div>
Pressure (in kPa)
+
;or   
</pre>
+
: d s t  # stores 1 in d if either s or t have non-zero values,
 +
::# 0 otherwise
 +
<div id="xor"></div>
 +
;xor   
 +
: d s t  # stores 1 in d if exactly one of s and t are non-zero,
 +
::# 0 otherwise
 +
<div id="nor"></div>
 +
;nor
 +
:    d s t  # stores 1 in d if both s and t equal zero, 0 otherwise
 +
::# Lines are numbered starting at zero
 +
<div id="j"></div>
 +
;j
 +
:             a # jumps to line a.
 +
<div id="bltz"></div>
 +
;bltz
 +
:      s  a # jumps to line a if s <  0
 +
<div id="blez"></div>
 +
;blez
 +
:    s  a # jumps to line a if s <= 0
  
<br>Notes:
+
<div id="bgez"></div>
<br>-All instructions and variables can be seen in-game in the MIPS editor window by clicking the "f", "x" and "s(x)" buttons on the top right.
+
;bgez
<br>-The stationpedia is the best source to see which variables are available to each device.
+
:     s  a # jumps to line a if s >= 0
<br>-Most scripts are loops, they end with a jump instruction that leads back up to the start. Otherwise they will just run once and then stop.
+
<div id="bgtz"></div>
 +
;bgtz
 +
:      s  a # jumps to line a if s > 0
 +
<div id="beq"></div>
 +
;beq
 +
:      s t a # jumps to line a if s == t
 +
<div id="bne"></div>
 +
;bne
 +
:      s t a # jumps to line a if s != t
 +
<div id="bdseal"></div>
 +
;bdseal
 +
:    d? a(r?|num) # Jump execution to line a and store current line number if device d? is set.
 +
<code>bdseal d0 32 #Store line number and jump to line 32 if d0 is assigned.</code>
 +
<BR>
 +
<code>bdseal dThisVictim HarvestCrop #Store line in ra and jump to sub HarvestCrop if device dThisVictim is assigned.</code>
  
Two practice scripts:
+
<div id="yield"></div>
<br>Automatic Night Light: Load "Activate" from a Daylight sensor, flip the value with a NOT-gate, store the value to the "On" variable of one or more lights.
+
;yield         
<br>Automatic Wall Cooler: Read "Temperature" from a Gas Sensor. Branch if the value is greater than X, turn on the cooler. Branch if the value is less than Y, turn off the cooler. (Wall coolers need a minimum of 12.5 kPa pressure in the connected pipe)
+
: # ceases code execution for this power tick
  
 +
<div id="lb"></div>
 +
;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?
  
----
+
<div id="sb"></div>
 +
;sb
 +
:      typeHash var r? # Store register r? to var on all output network devices with provided typeHash
  
=Instructions=
+
<div id="#"></div>
----
+
; #
 
+
:     # The following text will be ignored during compiling; use this to create comments.
See [[MIPS/instructions]]
 
 
 
{{:MIPS/instructions}}
 
  
 
[https://www.cs.tufts.edu/comp/140/lectures/Day_3/mips_summary.pdf Other examples]
 
[https://www.cs.tufts.edu/comp/140/lectures/Day_3/mips_summary.pdf Other examples]
Line 323: Line 258:
 
|-
 
|-
 
| -nez || if a != 0 || bnez || bnezal || brnez || snez
 
| -nez || if a != 0 || bnez || bnezal || brnez || snez
|-
 
| -nan || if a == NaN || bnan ||  || brnan || snan
 
|-
 
| -nan || if a != NaN ||  ||  || || snanz
 
 
|-
 
|-
 
| -dns || if device d is not set          || bdns || bdnsal || brdns || sdns
 
| -dns || if device d is not set          || bdns || bdnsal || brdns || sdns
Line 344: Line 275:
  
 
All approximate functions require additional argument denoting how close two numbers need to be considered equal. E.g.: <code>sap r0 100 101 0.01</code> will consider 100 and 101 almost equal (not more than 1%=0.01 different) and will set r0 to 1. The exact formula is <code>if abs(a - b) <= max(c * max(abs(a), abs(b)), float.epsilon * 8)</code> for <code>-ap</code> and is similar for other approximate functions.
 
All approximate functions require additional argument denoting how close two numbers need to be considered equal. E.g.: <code>sap r0 100 101 0.01</code> will consider 100 and 101 almost equal (not more than 1%=0.01 different) and will set r0 to 1. The exact formula is <code>if abs(a - b) <= max(c * max(abs(a), abs(b)), float.epsilon * 8)</code> for <code>-ap</code> and is similar for other approximate functions.
 
https://en.wikipedia.org/wiki/Machine_epsilon
 
<br/>
 
'''Example:'''
 
  FLT_EPSILON = 2^(−23) ≈ 1.19e−07;        <span style="color:blue;">float (32 bit)</span>
 
  DBL_EPSILON = 2^(−52) ≈ 2.20e−16;        <span style="color:#4c9700;">double (64 bit)</span>
 
<br/>
 
  <code>if abs(100 - 101) <= max(0.01 * max(abs(100), abs(101)), float.epsilon * 8)</code>
 
  <code>if abs(-1) <= max(0.01 * 101), float.epsilon * 8)</code>
 
  <code>if 1 <= max(0.01 * 101, float.epsilon * 8)</code>
 
<br/>
 
  if 1 <= max(1.01, FLT_EPSILON * 8)
 
  if 1 <= max(1.01, DBL_EPSILON * 8)
 
<br/>
 
  <span style="color:blue;">if 1 <= max(1.01, 1.19e−07 * 8)</span>
 
  <span style="color:#4c9700;">if 1 <= max(1.01, 2.20e−16 * 8)</span>
 
<br/>
 
  <span style="color:blue;">if 1 <= max(1.01, 0.000000952)</span>
 
  <span style="color:#4c9700;">if 1 <= max(1.01, 0.00000000000000176)</span>
 
<br/>
 
  <span style="color:blue;">if 1 <= 1.01  TRUE  1</span>
 
  <span style="color:#4c9700;">if 1 <= 1.01  TRUE  1</span>
 
  
 
==Device Variables==
 
==Device Variables==
Line 381: Line 290:
 
:    The current charge the device has.
 
:    The current charge the device has.
 
<div id="CLearMemory"></div>
 
<div id="CLearMemory"></div>
;ClearMemory
+
;CLearMemory
 
:    When set to 1, clears the counter memory (e.g. ExportCount).  Will set itself back to 0 when triggered.
 
:    When set to 1, clears the counter memory (e.g. ExportCount).  Will set itself back to 0 when triggered.
 
<div id="Color"></div>
 
<div id="Color"></div>
 
;Color
 
;Color
:    <div style="display: inline-block; height: 20px; width: 20px; border: 1px solid black; margin-right: 5px; background-color:#212AA5;"></div>&nbsp;0 (or lower) = Blue
+
:    0 (or lower) = Blue
:    <div style="display: inline-block; height: 20px; width: 20px; border: 1px solid black; margin-right: 5px; background-color:#7B7B7B;"></div>&nbsp;1 = Grey  
+
:    1 = Grey
:    <div style="display: inline-block; height: 20px; width: 20px; border: 1px solid black; margin-right: 5px; background-color:#3F9B39;"></div>&nbsp;2 = Green  
+
:    2 = Green
:    <div style="display: inline-block; height: 20px; width: 20px; border: 1px solid black; margin-right: 5px; background-color:#FF662B;"></div>&nbsp;3 = Orange  
+
:    3 = Orange
:    <div style="display: inline-block; height: 20px; width: 20px; border: 1px solid black; margin-right: 5px; background-color:#E70200;"></div>&nbsp;4 = Red  
+
:    4 = Red
:    <div style="display: inline-block; height: 20px; width: 20px; border: 1px solid black; margin-right: 5px; background-color:#FFBC1B;"></div>&nbsp;5 = Yellow  
+
:    5 = Yellow
:    <div style="display: inline-block; height: 20px; width: 20px; border: 1px solid black; margin-right: 5px; background-color:#E7E7E7;"></div>&nbsp;6 = White  
+
:    6 = White
:    <div style="display: inline-block; height: 20px; width: 20px; border: 1px solid black; margin-right: 5px; background-color:#080908;"></div>&nbsp;7 = Black  
+
:    7 = Black
:    <div style="display: inline-block; height: 20px; width: 20px; border: 1px solid black; margin-right: 5px; background-color:#633C2B;"></div>&nbsp;8 = Brown  
+
:    8 = Brown
:    <div style="display: inline-block; height: 20px; width: 20px; border: 1px solid black; margin-right: 5px; background-color:#63633F;"></div>&nbsp;9 = Khaki  
+
:    9 = Khaki
:    <div style="display: inline-block; height: 20px; width: 20px; border: 1px solid black; margin-right: 5px; background-color:#E41C99;"></div>&nbsp;10 = Pink  
+
:    10 = Pink
:    <div style="display: inline-block; height: 20px; width: 20px; border: 1px solid black; margin-right: 5px; background-color:#732CA7;"></div>&nbsp;11 (or higher) = Purple  
+
:    11 (or higher) = Purple
 
<div id="CompletionRatio"></div>
 
<div id="CompletionRatio"></div>
 
;CompletionRatio
 
;CompletionRatio
Line 490: Line 399:
 
;RecipeHash
 
;RecipeHash
 
<div id="RequestHash"></div>
 
<div id="RequestHash"></div>
;ReferenceId
 
:    Unique Identifier of a Device, this value is different for every device in a save.
 
<div id="ReferenceId"></div>
 
 
;RequestHash
 
;RequestHash
 
<div id="RequiredPower"></div>
 
<div id="RequiredPower"></div>
Line 572: Line 478:
 
:<code>ls r0 d0 0 Mature # Store 1 in r0 if d0 has a mature crop</code>
 
:<code>ls r0 d0 0 Mature # Store 1 in r0 if d0 has a mature crop</code>
 
:<code>ls vMature dThisVictim 0 Mature # Store 1 in vMature if dThisVictim has a mature crop</code>
 
:<code>ls vMature dThisVictim 0 Mature # Store 1 in vMature if dThisVictim has a mature crop</code>
;ReferenceId
 
:    Unique Identifier of a Device, this value is different for every device in a save.
 
<div id="ReferenceId"></div>
 
----
 
  
=Examples=
+
==Examples==
Previous examples were obsolete due to game changes, or confusing, they have been moved into the Discussions section
+
-----
----
 
  
===Harvie automation===
 
This script uses the batch instruction <code>sb ...</code> to control all Harvie devices on the network. But only one Harvie and one Tray will be the ''master'' and have their values read, the rest of the Harvies will repeat exactly what this unit does. Some problems with this design is that different types of crops mature at different speeds, and if seeds were manually planted and the master unit recieved the first seed, the harvesting action will be performed too early on all the other plants since they are growing a few seconds slower.
 
  
<div class="mw-collapsible mw-collapsed" data-expandtext="{{int:Expand, Automated Harvie Script}}" data-collapsetext="{{int:Collapse, Automated Harvie Script}}">
+
====This example script automates autohydro units and powers the lights off during the day when they're not needed.  (Hit Expand)====
{{MIPSCode|
+
Uses aliases, sub-routines and comments to minimize lines of code and adaptability.
alias dHarvie d0
+
<div class="mw-collapsible mw-collapsed" data-expandtext="{{int:Expand Sample AutoHydro Script}}" data-collapsetext="{{int:Collapse Sample AutoHydro Script}}">
alias dTray d1
+
<pre>
 +
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
 +
  
alias rHarvieHash r8
+
PlantCrop:​
alias rTrayHash r9
+
ls vOccupied dThisVictim 2 Occupied #seeds to plant​
l rHarvieHash dHarvie PrefabHash
+
blez vOccupied ra​ #If the machine has no seeds to plant, return.
l rTrayHash dTray PrefabHash
+
ls vOccupied dThisVictim 0 Occupied #something growin​g
 +
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
  
main:
+
##########
yield
+
#### End Script
#read plant data from the Tray
+
##########
ls r0 dTray 0 Mature
+
</pre>
#harvestable plants return 1, young plants return 0
 
#nothing planted returns -1
 
beq r0 -1 plantCrop
 
beq r0 1 harvestCrop
 
ls r0 dTray 0 Seeding
 
#seeds available returns 1, all seeds picked returns 0
 
#plants too young or old for seeds returns -1
 
beq r0 1 harvestCrop
 
j main
 
 
 
plantCrop:
 
#stop the planting if no seeds available
 
#otherwise it will plant nothing repeatedly
 
ls r0 dHarvie 0 Occupied
 
beq r0 0 main
 
sb rHarvieHash Plant 1
 
j main
 
 
 
harvestCrop:
 
sb rHarvieHash Harvest 1
 
j main
 
 
 
### End Script ###
 
 
 
}}
 
 
</div>
 
</div>
 
<br>
 
<br>
 
-----
 
-----
  
===Solar Panel 2-axis tracking===
+
<BR>
<div class="mw-collapsible mw-collapsed" data-expandtext="{{int:Expand, Solar Panel 2-axis tracking}}" data-collapsetext="{{int:Collapse, Solar Panel 2-axis tracking}}">
+
This is a sample timer command set, alternating between 1 for 1 tick (0.5s), then off for 2 ticks (1s).
{{MIPSCode|
 
#2 Axis Solar Tracking adapted from CowsAreEvil.
 
#Place all panels in uniform manner.
 
#Set one to 15 Vertical(Min value). 0 Horizontal.
 
#Take note direction panel faces.
 
#Place daylight sensor flat pointing in the direction
 
#the panel now faces. (Cable port facing opposite)
 
  
#Alias the sensor to d0
+
<pre>
alias sensor d0
+
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
  
# define the Panel variants
+
##########
define Heavy -934345724
+
#### End Script
define HeavyDual -1545574413
+
##########
define Solar -2045627372
+
</pre>
define SolarDual -539224550
+
-----
  
start:
+
Example:
yield
 
#Check for daylight.
 
l r0 sensor Activate
 
beqz r0 reset
 
#Read the Horizontal data.
 
l r0 sensor Horizontal
 
#Set batch to the panels.
 
sb Heavy Horizontal r0
 
sb HeavyDual Horizontal r0
 
sb Solar Horizontal r0
 
sb SolarDual Horizontal r0
 
#Read the Vertical data and subtract 90
 
l r0 sensor Vertical
 
sub r0 90 r0
 
#Set batch to the panels.
 
sb Heavy Vertical r0
 
sb HeavyDual Vertical r0
 
sb Solar Vertical r0
 
sb SolarDual Vertical r0
 
j start
 
  
reset:
+
<pre>
yield
+
so you will do l r0 d0 SolarAngle
sb Heavy Horizontal 270 #Edit this to face sunrise.
+
Sorry had last args swapped
sb HeavyDual Horizontal 270 #Edit this
+
That would read in the value
sb Solar Horizontal 270 #Edit this
+
while,
sb SolarDual Horizontal 270 #Edit this
+
s d1 Vertical r0
sb Heavy Vertical 0
+
Would write the contents of r0 into the devices 1's Vertical property
sb HeavyDual Vertical 0
+
additionally you can make some aliases
sb Solar Vertical 0
+
alias SolarSensor d0
sb SolarDual Vertical 0
+
l r0 SolarSensor SolarAngle
sleep 10
+
 
j start
+
##########
}}
+
#### End Script
</div>
+
##########
<br>
+
</pre>
 
-----
 
-----
 +
Another example:
  
===Example experiment: how many lines of code are executed each tick?===
+
<pre>
To determine this, a script without <code>yield</code> will be used. It should have as few lines as possible (so no labels are used, but a reset value at the top will be needed) and count the number of lines, the IC Housing will be used to display the result.
+
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.
{{MIPSCode|
+
l <register> <data_channel> <parameter>
move r0 1  #the first line has number 0
+
reads the value of the parameter
add r0 r0 3
+
s <data_channel> <parameter> <register_or_value>
s db Setting r0
+
writes the value of the parameter
j 1
+
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
 +
##########
 +
</pre>
  
Result (the numbers appears every 0.5 seconds):
+
==Links==
<br>127
+
-----
<br>256 (+129)
+
* [https://stationeering.com/tools/ic] Stationeering.com offers a programmable circuits simulator so you can develop your code without repeatedly dying in game!
<br>385 (+129)
+
* [https://hastebin.com/uwuhidozun.md]
<br>511 (+126)
+
* [http://www.easy68k.com/]
<br>640 (+129)
 
<br>769 (+129)
 
<br>895 (+126)
 
<br>1024 (+129)
 
<br>1153 (+129)
 
 
 
There is a repeating +129, +129, +126 sequence, a hint that the real value is 128. Which also happens to be the number of lines in a script, which makes sense. A variation of this experiment will show that empty rows are also counted towards this number.
 
 
 
----
 
=Links=
 
----
 
* Stationeers online IC10 Emulators so you can develop your code without repeatedly dying in game
 
** [https://ic10.dev/] Stationeers Code Simulator
 
** [https://ic10emu.dev] Stationeers IC10 Editor & Emulator - A feature packed code editor for Stationeers IC10 code, paired with a robust debugger and emulator. Edit, test, and share code.
 
** [https://stationeering.com/tools/ic] Stationeering provides a simulation of the IC10 chip inside Stationeers. IDE with error checking, full visibility of stack and registers.
 
* [http://www.easy68k.com/] EASy68K is a 68000 Structured Assembly Language IDE.
 
* [https://marketplace.visualstudio.com/items?itemName=Traineratwot.stationeers-ic10] syntax highlighting for IC10 MIPS for Visual Studio Code (updated Feb 10th 2022)
 
 
* [https://pastebin.com/6Uw1KSRN] syntax highlighting for IC10 MIPS for KDE kwrite/kate text editor
 
* [https://pastebin.com/6Uw1KSRN] syntax highlighting for IC10 MIPS for KDE kwrite/kate text editor
 
* [https://drive.google.com/file/d/1yEsJ-u94OkuMQ8K6fY7Ja1HNpLcAdjo_/view] syntax highlighting for IC10 MIPS for Notepad++
 
* [https://drive.google.com/file/d/1yEsJ-u94OkuMQ8K6fY7Ja1HNpLcAdjo_/view] syntax highlighting for IC10 MIPS for Notepad++
* [https://drive.google.com/file/d/1Xrv5U0ZI5jDcPv7yX7EAAxaGk5hKP0xO/view?usp=sharing] syntax highlighting for IC10 MIPS for Notepad++ (updated: 11/08/2022)
+
* [https://pastebin.com/3kmGy0NN] syntax highlighting for IC10 MIPS for Notepad++ (updated: 05/05/2021)
* [https://pastebin.com/3kmGy0NN] syntax highlighting for IC10 MIPS for Notepad++ (updated: 23/03/2024)
 
  
----
+
==Index==
 
+
-----
=Index=
 
----
 
  
 
{|
 
{|

Please note that all contributions to Unofficial Stationeers Wiki may be edited, altered, or removed by other contributors. If you do not want your writing to be edited mercilessly, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource (see Unofficial Stationeers Wiki:Copyrights for details). Do not submit copyrighted work without permission!

To edit this page, please answer the question that appears below (more info):

Cancel | Editing help (opens in new window)