OT: Stationeers - IC10 programming (MIPS assembler) - Page 1
Forum section: electronics / general

author: paulca
author_rank: Super Contributor
timestamp: February 28, 2025, 11:20:31 am
content: Stationeers is a game. A bit like "Kerbal Space Program" it's a "cartoonish" world overlaid onto a pretty decent physics model.It's a "Base building" style game with "Survival" elements. You land on a world of choice with nothing but your space suit and a lander of supplies. From there you build and upgrade. Different worlds different challenges. The moon is hard vacuum, but storm free. Mars has virtual no atmosphere but the storms destroys solar panels and wind turbines try and fry every cable in the place durig storms but produce sod all the rest of the time. Europa is COLD. Venus is HOT and stupid pressure. You can almost smelt steel in the atmosphere. The fictional vulcan has an atmosphere full of "Volatiles" which self ignite on contact with O2.Almost everything in the game starts out "plug and play", you connect things up and they work. Except ... only just. Most things are by default inefficient or just impractical without automation. Most things will permit you to run around after them and micro-manage or manually drive things constantly. Or... automate them instead.This is where is gets relevant. For some reason the game developers decided to introduce automation in terms of "Digital discrete" style building blocks.An example might be a "Logic Reader" pointed at a daylight sensor and reading the vertical angle to the sun, connected to a "Processor" unit with a "Subtract" setting, coupled with a memory unit holding the hardcoded value "90". This might be how you would offset your solar tracking by 90*. Then a "Batch Writer" can be used to send that value to all solar panels "Vertical" register.These "Logic Circuits" are large in the game. Each component uses a quarter grid and when you do all the cabling they quickly cover several square meters of space.Thankfully you progress fairly rapidly to "Integrated circuits" and the IC10.The IC10 is basically a microcontroller to replace those clutterings of circuit modules you lashed together. So you build a housing for one of these bad boys, hook it up and... you need to either use a laptop and physically put the chip into it to flash it, or you connect a computer to the network and run the IC Editor app. Yes, it's nuts. It is almost exactly like you would program an MCU in real world. Either lift the chip (EPROM) into a flasher or connect to the onboard flasher with a dongle.IC10 is assembly language based on MIPS? Anyway, it's basic load/store, 17 register + stack pointer + return address registers. Contact with devices are via "Device registers" which can be manually assigned to one of 6 ports on the device OR you can address any device on the network using it's type hash and name hash. All devices follow the same structure of a set of basic registers you can read, write or both depending. They additionally have indexed "slots" each with their own registers.l aRegister aDevice LogicRegisterWould load the named "LogicRegister" of the device "aDevice" into local register labelled aRegister. If you were so inclined you could rewrite that to not use aliases like:l r0 d0 42As an example, on that "Solar Tracking" problem. Here is how I solved that, while at the same time exporting some data through a single value register to other networks using bit shift encoding.The trouble is that the oritentation you place the panels and the orientation of the day light sensor matter. You can fiddle, trial and error and watch the panels or you can use code to do it 100 times faster than reorientating the sensor or panels repeatedly.The bit shift encoding is because I can only transmit a single word via the means Im bound to here due to distance and the lack of urge to run a cable that far. So "tx" is a logic transmitter.Code:define panelH -1545574413 # type hash for solar paneldefine turbineH -2082355173 # type hash for wind turbinealias daylight d0 # Daylight sensoralias tx d1 # Logic value transmitter# Basic variables and statealias temp r0alias value r1alias horz r2alias vert r3alias windGen r4alias solarGen r5alias totalGen r6begin:# Load solar angles, offset to match sensor to panel orientationl vert daylight Verticall horz daylight Horizontaladd horz horz 90sub vert 90 vert# Batch update all panel positionssb panelH Vertical vertsb panelH Horizontal horz# Batch (aggregate) load total generation on this group.lb solarGen panelH Charge Sumlb windGen turbineH PowerGeneration Sum# rescale to 0.1kW units.div solarGen solarGen 100div windGen windGen 100round solarGen solarGenround windGen windGen# Encode into 2 LS 16 bit wordsmove value 0and temp solarGen $ffffsll value temp 16and temp windGen $ffffor value value temp# Transmit 64 bit word and set debug outputs db Setting values d1 Setting valueend:# Suspend execution until the next game "tick" event.yieldj beginYou can see how the game gets you. Even the way it limits your ability to send and receive data from different networks. There are several ways to do this, but most are via a single 64bit register. That works fine if you want to send one thing. If you want to send a bunch of things then it becomes very clunky, very fast, unless you get your clever socks on and start multiplexing, charlieplexing, async super looping etc. etc.Another challenge is just how slow these things are. 128 instructions (analogous with lines of code, including blanks and comments) per "tick". A tick is 0.5 seconds. Note also your scripts are limited to 128 lines or 4096 bytes including comments and labels.You have no memory, save for 512bytes of stack memory. However, given you have 128 instructions per tick, less than 256 per second for reasons, trying to iterate over anything sizable in the stack and do something with it results in long waits for 5 to 10 seconds.Another example where I hit performance issues and needed to refactor/rewrite and get clever.... go through a "vending machine" which contains 100 "stacks" of materials and totalize them. Display the values on a screen rotating every 2 seconds. I had 10 items in the stack to totalise. To iterate over those ten items and then for each iterate the 100 stack items took 7 seconds. So I "unrolled" the outer loop. Each pass it totals one type and displays it, then yields.There are some cool features which create great "cooperative synchronisation" between devices. For example, any device can read and write any other devices stack. The possibilities for impossible to find bugs are endless. "Concurrency is to be assumed, but nobody really knows if it's parallel, series, interleaved, scheduled or what. Somethings you can do, somethings you can't. Writing to a device and then reading from it in the same tick from the same script seems to produce erroneous results for example, suggesting that a "Write" to a device takes does not take effect until the next tick.Of course it's not real and it's not real ASM nor a real MCU or CPU. That throws even more challenges and curves balls though. The registers are 64bit. However the IC10 does NOT support Integers. Pause and consider the implications of that. When you bit shift a number consider it is a "real number" and a signed one at that. As it turns out the word format is 54bit mantises and 10 bit exponent. So as long as you remain in the sign and least significant 54 bits you will be fine. Put stuff in the exponent and just hope nothing interprets that as a number or all hell will break loose.Anyway, it's a brilliant way to learn basic ASM concepts and solve interesting puzzles using it. Usually involving quite complex logistics, physics etc. Controlling a phase change gas separation rig for example, trying to regulate and balance pressure and temperatures with valves and pumps. Automatically tracking a satellite dish towards a beacon. Solar tracking. Or just displaying "Total Power Generated Yesterday". All give you nice little ASM programming challenges.EVERYTHING can and will be automated! The base must expand, must grow. You are not "surviving" your are thriving.https://store.steampowered.com/app/544550/Stationeers/