Skip to content

Latest commit

 

History

History
240 lines (197 loc) · 15.8 KB

File metadata and controls

240 lines (197 loc) · 15.8 KB

How to Use

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:

  1. 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\
  2. 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:

  1. Building the circuit (using one of the 2 methods above)
  2. Writing the program (Asm/FPas)
  3. Debugging the program (emu.exe)
  4. Porting the program to the circuit (fsimEncoder.exe)
  5. Running

Important Files

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.

Circuit Specifications

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

Writing a Program - Assembler

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, 5
Now register eax contains the number 5
mov reg, reg Copies the value from one register to another mov eax, ebx
Now 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], ebx
If 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 255
All 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 a Program - FPas

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).

Debugging the Program

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.

Virtual Devices

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.

Breakpoint

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.

Debug

Running the Program in Factorio

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. Run

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. Run

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: Run 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:

  1. 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
  2. Using the FCPU mod. The FCPU speed will be increased to 60 cycles per second, while the rest of the game remains unaffected.

Running using the FCPU Mod

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:

  1. Program execution speed increases by 60 times
  2. The circuit takes up significantly less space
  3. 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:

  1. 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 folder Factorio_Space_Age\mods\factorio-cpu_1.0.0
  2. Download the map version for the mod and copy it to the game's saves folder
  3. At the stage of running the translator fsimEncoder.exe, use option 2. The text for interpretation by the mod will be placed in the clipboard
  4. 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 Run Mod

HowTo Video

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