For convenience, it's better to download this entire repository and work with it as a local folder.
There are two main ways to use it:
- Download the map file and place it in your game folder. As of writing this documentation, the path is
GAME_FOLDER\Factorio_Space_Age\saves\ - Use the blueprint - copy the content of the file to your clipboard and import it into the game using the "import string" button on the main map panel
The first option is preferable because the second option requires manually adding one item each to the joystick chests. You can examine their contents in the map from the first option.
Using the circuit typically involves 5 steps:
- Building the circuit (using one of the 2 methods above)
- Writing the program (Asm/FPas)
- Debugging the program (emu.exe)
- Porting the program to the circuit (fsimEncoder.exe)
- Running
As you read the instructions, you will encounter explicit links to the necessary files. Nevertheless, for convenience, their purpose is listed here again.
- ⚙️Binaries
- emu.exe - Asm/FPas language emulator. Allows emulating written programs before running them on the Factorio circuit.
- fsimEncoder.exe - Translator for Asm/FPas programs into a format understandable by the Factorio map.
- 📦Assets
- fsim-V2.zip - Map with the FCPU built.
- fsim-V2-blueprint.txt - FCPU build identical to fsim-V2.zip, but as a blueprint.
- factorio-cpu_1.0.0.zip - FCPU plugin. Note that this is an alternative to fsim-V2.zip, and its use is optional.
- fsim-mod-V1.zip - Map with the FCPU built using the plugin.
- notepad_fpas.xml - Syntax highlighting template for the Notepad++ program, used for programming in FPas.
- 💾ProgramSamples
- Asm - Sample programs written in low-level Asm.
- FPas - Sample programs written in FPas. Using this language is more convenient.
Build:
| Parameter | Value |
|---|---|
| Width | 184 |
| Height | 61 |
| Power Consumption | ~1.3MW |
Combinator Composition (including screen and joystick):
| Type | Count |
|---|---|
| Decider | 501 |
| Arithmetic | 281 |
| Constant | 103 |
Capabilities:
| Parameter | Value |
|---|---|
| EPROM | 1200 instructions |
| RAM | 100 numbers |
| Instruction Set Size | 26 |
| Speed (circuit) | 1.5 cycles/sec |
| Speed (plugin) | 60 cycles/sec |
You can write your program in a reduced version of assembly, consisting of 26 instructions.
There are 4 general-purpose 32-bit registers: eax, ebx, ecx, edx. There are hidden registers: eip, pointing to the current instruction; esp - pointing to the top of the stack (the stack in FCPU grows "upwards"); flags - stores the comparison flags from the last cmp.
Notations for the instruction table:
| Notation | Meaning |
|---|---|
| reg | General-purpose register - eax, ebx, ecx, edx |
| esp | Stack address register |
| [reg] | General-purpose register, whose value in RAM points to the desired cell |
| num | Integer from -16777215 to 16777215 |
| label | Label in the program. Denoted in the format <LABEL_NAME>: |
| pin | I/O pin number, integer from 0 to 3 |
Supported Instructions:
| Instruction | Meaning | Example |
|---|---|---|
| Data Movement | ||
mov reg, num |
Writes a constant to the register | mov eax, 5Now register eax contains the number 5 |
mov reg, reg |
Copies the value from one register to another | mov eax, ebxNow register eax contains the value of register ebx |
mov [reg|esp], reg |
Writes to RAM at the address stored in the first register the value stored in the second register | mov [eax], ebxIf register eax = 5, then the value of register ebx is now stored in RAM at address 5 |
mov reg, [reg|esp] |
Writes to the register the value stored in RAM at the address stored in the second register | mov eax, [ebx]If register ebx = 5, then eax now contains the value from RAM cell 5 |
| Arithmetic | ||
add reg1, reg2 |
Register reg1 = reg1 + reg2 | add eax, ebx |
add esp, num |
Register esp = esp + num | add esp, -2 |
sub reg1, reg2 |
Register reg1 = reg1 - reg2 | sub eax, ebx |
mul reg1, reg2 |
Register reg1 = reg1 * reg2 | mul eax, ebx |
div reg1, reg2 |
Register reg1 = reg1 / reg2. Integer division with floor rounding | div eax, ebx |
mod reg1, reg2 |
Register reg1 = reg1 % reg2. Remainder of division | mod eax, ebx |
and reg1, reg2 |
Register reg1 = reg1 & reg2. Bitwise AND | and eax, ebx |
or reg1, reg2 |
Register reg1 = reg1 | reg2. Bitwise OR | or eax, ebx |
xor reg1, reg2 |
Register reg1 = reg1 ^ reg2. Bitwise EXCLUSIVE OR | xor eax, ebx |
| Unary Operations | ||
neg reg |
reg = ~reg. Bitwise inversion | neg eax |
inc reg |
reg = reg + 1 | inc eax |
dec reg |
reg = reg - 1 | dec eax |
| Comparison Operations | ||
cmp reg1, reg2 |
Compares the values of registers reg1 and reg2 and writes the result to the flags register | cmp eax, ebx |
cmp reg, num |
Compares the value of register reg and constant num and writes the result to the flags register | cmp eax, 5 |
jmp label |
Unconditional jump to the label | jmp loop |
je label |
Jump to label if the numbers in the last cmp were equal | je skip |
jne label |
Jump to label if the numbers in the last cmp were not equal | jne skip |
jb label |
Jump to label if the first number in the last cmp was greater than the second | jb skip |
jl label |
Jump to label if the first number in the last cmp was less than the second | jl skip |
sete reg |
Set register to 1 if the numbers in the last cmp were equal | sete eax |
setne reg |
Set register to 1 if the numbers in the last cmp were not equal | setne eax |
setb reg |
Set register to 1 if the first number in the last cmp was greater than the second | setb eax |
setl reg |
Set register to 1 if the first number in the last cmp was less than the second | setl eax |
| Stack | ||
push reg |
Push the register value onto the stack (RAM) and increment the stack pointer by 1 | push eax |
pop reg |
Pop a value from the stack into the register and decrement the stack pointer by 1 | pop eax |
| Calls | ||
call label |
Call the function label | call pow |
ret num (offset) |
Return from the function + remove the number of its call parameters (value from register) | ret 2 |
| Input/Output - Learn more about devices | ||
io_mode num (mode) |
Set the I/O mode (continuous/pulse) for each pin | io_mode 255All pins in pulse mode |
out pin, reg |
Send a signal from the register to the specified pin | out 0, eax |
in reg, pin |
Read a signal from the pin into the specified register | in eax, 3 |
| Interrupts | ||
halt |
Stop program execution | halt |
ticks reg |
Put the number of executed instructions into the register (can be used as a clock) | ticks eax |
Example of a simple program that adds two numbers and stores the result in eax:
; Adds two numbers: 2 + 3. Stores result in eax
mov eax, 2
mov ebx, 3
add eax, ebx
halt
Main sample programs in assembly can be found in the ProgramSamples\Asm folder of this repository.
Writing large programs in assembly for FCPU can be too labor-intensive, so for greater convenience, you can use a higher-level language - FPas. As you probably guessed from the name, it's a Pascal-like language)
Example of a simple FPas program to calculate the area of a circle:
const Pi = 3
int main() r, PiR
r = 5
PiR = r r * Pi *
return PiR
The syntax of this language was intentionally created to be as simple as possible. You can study its constructs in more detail here.
Main sample programs in FPas can be found in the ProgramSamples\FPas folder of this repository. And the file ProgramSamples\FPas\12_snakeGame.fpas contains FPAS-written mini-libraries for working with the "screen" and "joystick" devices (located at the end of the file as functions).
During program development, testing the written logic is often necessary, and it's good if each such test doesn't require loading the program into FCPU, because firstly, FCPU itself is slow, and secondly, it's simply inconvenient.
For such purposes, there is an emulator where you can run and test your program in a few seconds. It is located in the Binaries folder, file emu.exe.
After writing the program, it is enough to pass its filename as a parameter to emu.exe (for example, by dragging and dropping in Explorer) to run it. Also, for convenience, the debugger remembers the name of the last program, so to run it again, it will be enough to just run emu.exe, without re-dragging the program file.
For example, if you run the previously described program for calculating the area of a circle this way, you will see on the screen Halted - 15 ticks, 75 eax, out. The first part of the message - 15 ticks, shows how many cycles FCPU took to complete its work. The next part 75 eax shows the value that was in the eax register before finishing. In the case of FPas, this is always the return value from the main function, specifically in our program it's 75, i.e., the result of the formula 3 * 5 * 5. The 'out' part relates to the internal number queue, from which you can read/write values for debugging purposes. We'll look at that later.
As you may have already noticed, the debugger emulates not only the FCPU itself but also its main devices - the screen (gray rectangle above) and the joystick (via buttons W, A, S, D, Q, E).
To use them, you can try running a more complex program - the "snake" game, file ProgramSamples\FPas\12_snakeGame.fpas.
In addition, the debugger has 2 additional debugging devices - the console (pin 4) and the number queue (pin 1).
Let's look at using the console - let's write a program that takes a number as input from the console, squares it, and outputs the result to the number queue.
; shows debugger console
debug
int main() num, res
; read number from console
num = _in4
; calc square
res = num num *
; output result to console
res _out1
You will be able to see the calculation result in the output part 49 out. Note that you can output several numbers to the number queue during program execution. Note that virtual devices are only available in the debugger program; they are not present in the actual FCPU.
Sometimes you may need to stop the program in the middle and examine the state of memory/registers. For such purposes, you can set breakpoints.
To add one, use the instruction .ret 55555. Let's consider the previous example with a breakpoint:
debug
int main() num, res
num = _in4
res = num num *
.ret 55555
res _out1
return 0
When you run the program in the emulator, it will stop at line 6 and you will see a separate debugger window with register/memory cell values. The entire Asm code of the program will be shown on the left, and you can control its execution progress using the separate buttons on the right.
After writing and debugging the program, it's time to run it in Factorio! For this, the translator in Binaries\fsimEncoder.exe is used. Similar to emu.exe, you need to pass the filename of the Asm/FPas program to the translator.
File - <YOUR_FILE_PATH>
Which form of output you want?
1. output program for scheme
2. output for mod component
There are two translation options - for the FCPU map (option 1) and for the FCPU plugin map (option 2). In the normal case, we are interested in option 1, so enter 1 in the console and press Enter. A blueprint consisting of 30 constant combinators, representing your written program code in a format understandable by FCPU, will be copied to your clipboard.
Open the previously downloaded Factorio map and paste the blueprint using the "Import string" button on the panel. Depending on the size of your program, you will get several (or one) constant combinators. Their placement order is in three rows from top to bottom. The program area itself in FCPU is located in the upper left corner of the circuit. There you will notice 30 constant combinators already placed; your task is to replace the existing combinators with the new imported ones. You should only replace the first combinators. If you got 3 combinators upon import, then you need to remove exactly the first three combinators (counting from the top left), place the combinators from the import in their place, and remember to connect them with a red wire to the decider combinator on the right. For greater convenience, before inserting your combinators, you can delete all 30 previous ones at once; this won't break anything.

After replacing the FCPU program memory, you can start/stop your program by turning on/off the constant combinator below the memory circuit - next to it there will be a speaker with the label "on/off switch". If the program has finished execution, to restart it, you can turn off and then turn on this constant combinator again.

In the case of the test program above, calculating the area of the circle 01_helloWorld.fpas, we remember that after its completion the value of register eax was 75. Its value can be seen in the special register area:
For a more detailed introduction to the internal structure of the circuit, refer to the separate documentation.
The FCPU itself is built as a kind of guide for studying the principles of computing technology in Factorio; it does not provide high operating speed, but clearly shows its internal structure. Remember that the initial speed of FCPU is only 1.5 cycles per second. On one hand, this drawback can be compensated by writing a program that runs in the background while you play Factorio. This helps if the program doesn't require fast output of results. But if speed is critical, the limitation can be overcome in two ways:
- Speeding up the entire map - command
/c game.speed=64. Increases the speed of the entire map by 64 times. There is a convenient alternative - time acceleration mod - Using the FCPU mod. The FCPU speed will be increased to 60 cycles per second, while the rest of the game remains unaffected.
First of all, we should thank the creator of the MicroController mod. The FCPU mod was made following his example.
Using the mod has three advantages and one significant disadvantage. Advantages:
- Program execution speed increases by 60 times
- The circuit takes up significantly less space
- Updating the program is easier
Disadvantage - the clarity of FCPU operation is lost, as in the mod it is represented by one solid component. If the original FCPU circuit is a working computer built from fundamental combinators, then the mod is more like the previously discussed emu.exe ported to Factorio, and it is not suitable for educational purposes. But it is well suited exclusively for running programs.
Using the mod:
- Install the mod itself from the file
Assets\Files\factorio-cpu_1.0.0.zip. To do this, simply extract the archive contents to the game folderFactorio_Space_Age\mods\factorio-cpu_1.0.0 - Download the map version for the mod and copy it to the game's
savesfolder - At the stage of running the translator
fsimEncoder.exe, use option2. The text for interpretation by the mod will be placed in the clipboard - Load the map, left-click on the mod block; it is located on the left, for clarity, it has a yellow-black floor underneath it. The mod window will open, paste the text obtained in step 3 into it. Use the "start" button at the top left to run

All necessary steps, from writing the program, then debugging and running, are presented in a short video to eliminate possible misunderstandings when reading.
