Development and creation from scratch of an arcade machine for four players

image

In November 2019, I quit my job and decided to devote several months to learning a new skill that I had long wanted to learn. At that time I worked as a web developer. Before that, I studied software development. And even earlier, as a child, I was constantly experimenting with electronics and programs. Therefore, I felt confident enough in the creation of software.

However, there was always this magic thing called “iron” , which I use daily, but I have no idea how it actually works. A software developer (and especially a web developer) does not need to understand the hardware. Since all web development code is very high-level, it rarely turns out that the problem with our software is hardware related.

Therefore, I never worked on “iron” and did not have any general knowledge about electrical engineering, except for those that were given to us in high school. And I wanted to change this situation. I set myself an absurd goal, which at that time seemed very far from my set of knowledge. And then ... I just started experimenting. I planned to check how far I could go before I run out of motivation. I did not expect to achieve my goal, but somehow I succeeded.

Here is my result:


My incredible goal was to create a four-player arcade game console from scratch. It uses a microcontroller as a brain, and LED strip as a display. Using one joystick and four buttons for each player located at the edges of the table, players control a game that is dynamically loaded into the system from a memory chip. Thanks to this, the gameplay on the device resembles the good old consoles. Only now we do not need to blow on the cartridge to get rid of bugs.

To my surprise ... I really was able to complete the project. It took me about three full working months for cycles of experiments, failures, reading documentation, despair, and retrying. It would be necessary to fix the number of working hours in order to know how much time I spent on this. I will assume that about 800-900 hours. (Assuming that I worked 6/7 days a week for 8–10 hours a day, which is pretty close to the truth.)

I tried to document the process of my experiments from beginning to end, taking photos and recording videos. With this post I will document the project and my experience for myself. I hope that for you it will become a source of inspiration if you also decide to take on an equally incredible project.

Getting to work


As I said at the beginning of the article, when I started the project, I did not have any knowledge of electronics, except for the incorrectly remembered formula of Ohm's law. Therefore, firstly, I needed to study how electronics work in practice, and only then try to assemble a game console. I did not even know how to turn on the LED using the microcontroller. So, my first step: ordering a simple electronics and microcontroller for experiments. To start, I will try to power the LED. I am almost sure that my first attempt to turn on the LED led to its burning. But this was not documented on camera, so let’s pretend it wasn’t.


Experiments with a microcontroller, resistors, a transistor, and an LED.

This was the first major milestone. Now we know how to create code that runs in the microcontroller. We also learned how to use transistors as a simple electrical switch to turn on an LED. Amazing!

Adventure with EEPROM



Fig. 1. Using shift registers to control 16 output lines with just 3 output pins.

Part of the project was the ability to write game logic to memory chips (EEPROM). They should have been read when a cartridge with a player is inserted into the system.

In the long run, it hurt me that I did not learn enough information about what type of EEPROM should be used in this project. I was so passionate that I bought the old parallel EEPROM chips (W27C512).

To write to or read from them, I needed the ability to set a high or low signal on all 16 lines. If I did not want to occupy all the output contacts of the microcontroller, it would be logical to learn how to use shift registers.


Fig. 2. The circuit used in an unsuccessful attempt to read / write data to a parallel EEPROM chip.

With just a couple of contacts, we can separately control all 16 lines.

Now let's apply this knowledge to EEPROM! Yes ... but no. I was not able to stably write data to EEPROM. This type of chip requires 12-14 V to remove or write bytes. I tried to provide them by using transistors as switches to supply increased voltage. And as I understand it, it MUST work. But it didn’t work. I still don’t understand what exactly is the problem. In fig. Figure 2 shows the circuitry that I tried to use to read / write bytes from / to EEPROM.


Fig. 3. A circuit that has successfully managed to read / write bytes to a serial EEPROM chip.

Finally, having studied more information on this topic, I learned that today parallel EEPROMs are not used so often. Usually, developers prefer serial EEPROM I2C, and therefore, it’s much easier to find tutorials on them. (For example, this awesome Sparkfun tutorial ).

In fig. Figure 3 shows my scheme for reading and writing data to serial EEPROMs ... It is MUCH simpler and much more reliable. This taught me that you should not be too happy about ordering parts and trying to develop the project too quickly. We spent about 1–2 weeks on parallel EEPROMs, and ultimately did not use them at all. However, in the process, we learned a lot in electronics and reading specifications (which in itself is a skill). The efforts were not completely wasted.

So how do we do it anyway?


Now we can read and write to the memory chips. What will be the next step? At this stage, it will be logical to describe my console plan in more detail using several drawings as an example.


Overall plan. This will be a game console with controllers for four players. Each player has one joystick and several buttons.

The red circle marks the plug for the game cartridge. This connector will have four metal pins that the console uses to read serial EEPROMs to load games into memory.

Green shows how we planned to create a screen of LED strips. We wanted the screen pixel to be a square, luminous patch of color, not a spot blending in with other spots.

To achieve the desired effect, we used such a scheme to separate light sources from each other. At the same time, it scatters the light falling on top of the screen. (The white stripes below the grille indicate the LED strip)

I decided to make a 42x42 LED display. That is, in total 1764 LEDs are obtained. I chose the number 42, because thanks to this, the size of the table will be just right for four people.

Powering up so many LEDs is a daunting task in itself. At maximum brightness, the RGB LED consumes 60 mA of current. (which gives white with maximum brightness). If we multiply by the total number of LEDs, then we get the maximum current consumption of 105.84 A at 5 V! To get closer to this current, we purchased a power supply SE-600–5 MEAN WELL. It can supply current up to 100 A. Which is less than theoretically possible 105 A. But I do not seek to display fully white screens with maximum brightness in games. In addition, we can limit the brightness programmatically. We will also add fuses to prevent accidentally exceeding this limit of 100 A.


Fig. 4. Cardboard prototype for a 3x3 LED display.

I will return to the assembly of this screen later. First you need to do prototyping. Let's see if we can get a small LED screen to work.

This 3x3 prototype is made up of several pieces of cardboard that separate pixels, and a piece of plain paper for printers that scatters light. It worked great! We have received a wonderful confirmation of the working capacity of the concept.

To control the LEDs using a microcontroller, we used the FastLED library. However, it turned out that if the LEDs are controlled by one data bus, then it is impossible to update 1764 LEDs at a speed sufficient for games. Given a frequency of 800 kHz, we can achieve a frame rate of approximately 17 frames per second. Not exactly what we strive for. Personally, I like to play with at least 60FPS. Fortunately, this is possible. It is enough to use more than one data bus. The 42x42 display can be conveniently divided into 7 equal parts. Each of these parts can be controlled separately, with its own data bus. This is possible thanks to the use of the parallel output function of the FastLED library in the Teensy 4 microcontroller . By using 7 data buses, we can achieve a maximum refresh rate of approximately 120FPS!

I did not plan this, but by pure chance, at the very beginning of the project, I chose this particular microcontroller. It seemed to me that for the smooth operation of the games would require the fast processing time provided by this MK. The prototype in Fig. 4 is already controlled by the parallel output function. However, in this prototype we use only 2 data buses, just to test whether everything will really work as stated.

How will we execute code with EEPROM?


So, at this stage, we can read and write to the EEPROM, and we also have a working proof of the concept of the LED display. What's next?

There are only two serious technical tasks left: the organization of the input method for all players (buttons and joysticks). And we also need to figure out how to execute game logic from EEPROM and display the results of these instructions on the display.

The ordered buttons and joysticks have not arrived yet. Therefore, first we will be engaged in the execution of game logic from EEPROM.

There are many ways to execute instructions (code) from the EEPROM. However, first we need to set certain requirements:

1) The code should be easy to write.

2) The code should be small (file size).

3) The code should be able to interact with ready-made libraries, for example, FastLED, in order to reduce the amount of my work.

4) The code should be able to load into RAM as quickly as possible in order to reduce load time.

5) You need the ability to emulate code on a regular PC for testing games.

6) Our solution must be high-performance (provide at least 60FPS).

7) A solution should not require the purchase of a large number of additional equipment.

8) The solution should work on Teensy 4.0 MK.

9) The solution should be easy to implement.

I came up with four different ways to execute code from EEPROM:

- We write on the EEPROM the usual compiled Arduino code. Then we make the external Arduino programmer read the compiled code from the EEPROM and reprogram the Arduino on the fly every time a new game loads.

- We load the assembler code in RAM and execute it from there.

- We use a ready-made code interpreter, for example, ArduinoBASIC or Bitlash .

- We write our own code interpreter.

Here is a brief comparison of the advantages and disadvantages of the four solutions for our project:


(1) The file size for a solution with an external programmer is terrible. Together with the game logic, all the code libraries that we use in this project should be stored in EEPROM. To display the state of the game, each EEPROM must have its own copy of the FastLED library. This is not great at all. This problem can probably be circumvented by somehow adding the base code to an external programmer, which is then combined with the code in the EEPROM before programming the Arduino. This would be a high-risk task, because it is not so easy to find tutorials on the Internet. We would probably spend too much time on it.

(2) Running assembler from RAM is a great option. That is why I decided to consider it. The complexity of writing code can be reduced by using some high-level language, for example, C, which is then compiled into the correct assembler code. However, it was not clear how easy it would be to get it to interact with other libraries on Arduino, so I decided to abandon it.

(3) Using a ready-made interpreter is also a pretty good solution. However, as far as I know, all these interpreters are executed based on strings of characters. These long lines must be written to the EEPROM. This is not such a big problem, but definitely not the best way to minimize file size. In addition, it was unclear whether these interpreters could interact with Arduino libraries. Therefore, I decided that using ready-made interpreters is not a good idea.

(4) Finally, we have solution 4: creating our own code interpreter. It satisfies all the requirements, because the way the interpreter is implemented depends entirely on me. He willto have high speed if I achieve high speed of the interpreter itself. Yes, the file size will be small and the code will be easy to write ... if I provide this myself. In other words, we will have complete control over everything. And if I make an effort, then everything will turn out perfectly. The only serious drawback of such a solution will be a long development time. You may remember that I spent 800–900 hours on this project. That is, it is obvious that I decided to choose solution 4 - to create my own code interpreter. Time was not a problem for me. I took this opportunity to learn how programming languages ​​are created. I will find out why one or another architectural decision was made in these languages.

The birth of ArcadableScript


The general principle of the interpreter is quite simple. I will not go into details of its internal structure, because at the time of writing, I was planning to completely rewrite the interpreter so that it would become more efficient and it would be easier for him to write code. However, the basics remain the same. The interpreter will execute a simple code loop for each measure of the game:


A big drawback of such a scheme is that the input and state of the game are checked only once per frame. For games that do not require a quick reaction, this is normal. However, in other games, the player will not be able to react between frames. I will solve this problem in the next version of the interpreter.


Fig. 5

In the diagram with fig. Figure 5 shows how I planned to upgrade the interpreter in the near future, creating two separate cycles for the game state and game frames. This will allow us to update the state of the game hundreds of times per second, and the display - only 60 times per second.

Unfortunately, on Teensy 4.0 it is not possible to execute hardware multi-threaded code. Therefore, we will not be able to perform these two cycles in parallel. But I'm sure I’ll come up with something.


After some time, I managed to write two simple programs using my own invented bytecode language. They use raw numbers as input to minimize file size. That is, I completed the writing of these two programs, literally writing down lists of numbers that the interpreter can understand. To give an idea of ​​how readable this bytecode is, I will demonstrate the real instructions used in the example program that moves a dot across the screen:

// TODO: Write/read all untyped... data to/from ROM
  int untypedGamestate[] = {
    0, // Previous time, to keep track of game time/framerate.
    0, // Player position x.
    0, // Player position y.
    0, // Player R color value.
    0, // Player G color value.
    255, // Player B color value.
  };
  int untypedValues[][3] = {
    // ID, Type, Value
    {0, 0, 0}, // Move up button value 
    {1, 0, 1}, // Move right button value
    {2, 0, 2},  // Move down button value
    {3, 0, 3},  // Move left button value
    {4, 3, 1},  // True/1
    {5, 3, 0},  // False/0
    {6, 4, 0},  // Current millis since game start
    {7, 2, 0},  // Gamestate previous time
    {8, 2, 1},  // Gamestate player x
    {9, 2, 2},  // Gamestate player y
    {10, 2, 3}, // Gamestate player r color
    {11, 2, 4}, // Gamestate player g color
    {12, 2, 5}, // Gamestate player b color
    {13, 3, 1}, // Move player up after button press boundary check
    {14, 1, 0}, // System config screen width
    {15, 1, 1}, // System config screen height
    {16, 3, 3}, // Move player down after button press boundary check
    {17, 3, 5}, // Move player left after button press boundary check
    {18, 3, 7}, // Move player right after button press boundary check
  }
  int untypedCalculations[][5] = {
    // ID, ending, valueLeftID, calculationRightID, calculationOperator
    {0, 0, 9, 1, 1}, // Current player y position - 1
    {1, 1, 4, 0, 0}, // True/1
    {2, 1, 0, 0, 0}, // Up button
    {3, 1, 2, 0, 0}, // Down button
    {4, 1, 5, 0, 0}, // False/0
    {5, 1, 9, 0, 0}, // Current player y position
    {6, 0, 15, 1, 1} // screenheight - 1
    {7, 0, 9, 1, 0}, // Current player y position + 1
    {8, 1, 3, 0, 0}, // Left button
    {9, 1, 1, 0, 0}, // Right button
    {10, 1, 8, 0, 0}, // Current player x position
    {11, 0, 8, 1, 0}, // Current player x position + 1
    {12, 0, 8, 1, 1}, // Current player x position - 1
    {13, 0, 14, 1, 1} // screenwidth - 1
  }
  int untypedInstructions[][10] = {
    // ID, rootInstruction, conditionCalculationLeftID, conditionCalculationRightID, conditionOperator, conditionSuccesValueLeftID,
    // conditionSuccessCalculationRightID, hasFailedCondition, conditionFailedValueLeftID, conditionFailedCalculationRightID
    {0, 1, 2, 1, 0, 13, 0, 0, 0, 0}, // move player up when up button is pressed.
    {1, 0, 5, 4, 1, 9, 0, 0, 0, 0}, // move the player up when the boundary is not reached.
    {2, 1, 3, 1, 0, 16, 0, 0, 0, 0}, // move player down when down button is pressed. 
    {3, 0, 5, 6, 1, 9, 7, 0, 0, 0} // move the player down when the boundary is not reached.
    {4, 1, 8, 1, 0, 17, 0, 0, 0, 0}, // move player left when left button is pressed.
    {5, 0, 10, 4, 1, 8, 12, 0, 0, 0}, // move the player left when the boundary is not reached.
    {6, 1, 9, 1, 0, 18, 0, 0, 0, 0}, // move player right when right button is pressed.
    {7, 0, 10, 13, 1, 8, 11, 0, 0, 0}, // move the player right when the boundary is not reached.
  };

If you take the time to carefully study the code, you can understand how the early version of this interpreter worked. The general principle of using “values”, “calculations” and “instructions” is preserved in the current version. However, a lot has changed. We no longer have a fixed list of gamestate values, now they are just part of the regular list of values. In addition, we separated the “conditions” from the instructions. Thanks to this, we can reuse instructions in the code, which reduces the file size.

Let's not go into the details of the interpreter, because in the redesigned version, all this will soon change.

Now we are at the stage when we know how to read / write to the EEPROM, and we can execute instructions based on arrays of ordinary numbers. The next logical step will be to remove hardcoded lists of instructions from the code and write them to the EEPROM. From now on, we will be able to try to read and execute the instructions stored in the EEPROM.


At this stage, we have all the proofs of the working capacity of the concepts that we need to begin to create the final result!

Obviously, each individual part of the prototype we created still requires a lot of work. But, in my opinion, the most difficult tasks have already been solved. All I had to do was develop what I already had. Everything is simple!

LED Display Assembly



It took a lot of work to assemble the display. Very much work. I started by having to solder wires to 42 separate strips. Each strip requires three wires on one side and two on the other. That is, only about 200 wires. Before this project, I did not have much practice in soldering, so you can clearly notice that the more I do soldering, the stronger the quality. Of course, in the end, I had to redo many of the first LED strips, because I did not like the result. All of this is part of the learning process!


The next step: we attach all the LED strips to a large wooden panel. Looking back, I think that perhaps for the sake of better thermal conductivity it was worthwhile to use a metal sheet, because after an hour of operation the display now becomes warm (40-50 ° C). But this still doesn’t happen so often, so it’s not a big problem. However, if I decided to repeat the project, I would correct this aspect.


Next, we attach wires of a larger diameter to the positive and negative conductors of the LED strip strips. We must make sure that the large diameter wires reliably withstand a maximum current of 100 A. For added protection, we also added 15 A fuses to each part of the display.

At this stage, we are ready to make the first attempts to control the display. After many failures and manipulations with software parameters and wires, I finally managed to display a single color on the display without distortion and interference. It took a long time, and the result was still far from perfect. For a long time, I still had problems with distorted signals until I posted a question about it on electronics.stackexchange.com. Great people from this site helped me diagnose the problem. I still didn’t fully understand what it was, but by connecting the negative leads directly along the data buses from the MK ground to the ground terminal near the data input, I was able to solve it. Since then I have not had any problems with distortion on the display.


As we saw from the illustration above, two layers of material are superimposed on the LED strips.

As a material for this coating, we need something strong, transparent, but scattering light. However, I did not want to use glass because it is expensive and fragile. Therefore, I decided to take a standard transparent polystyrene. So that he scattered the light, I treated it with a fine sandpaper to such an extent that it was impossible to look through. Everything is very simple.

Much more time was spent creating a grid that would be located directly on top of the strips. I thought just ordering a grille with the necessary parameters to order, but they called me a price of about 500 euros. In my opinion, she was not worth it. Therefore, I had to collect it ourselves. For this we need thin (no more than 2 mm thick), durable, opaque white plastic strips. Quite a lot of requirements. Therefore, the selection of the right material took a lot of time. As it turned out, stripes from window blinds (lamellas) are ideal.


First, we made a small holder to make uniform, even cuts on wide stripes. In this case, rather small plastic strips were obtained. Then we needed to make incisions to the middle of each strip exactly in the right places. This is necessary to connect the pieces of plastic and assemble the grate. This is what I do in the third photo. Before doing this, you need to make sure that the width of the saw is the same or slightly larger than the width of the strip that you cut. Otherwise, the grate cannot be assembled. In my case, it turned out that a hacksaw for metal has an ideal thickness.

In the fourth photo, the result of assembling all the strips into the grid is visible. It was a very annoying and monotonous job, but the grill turned out to be very durable. In general, it looks like all the cells are the same size. There is not much variation between the cell sizes, otherwise the display would look strange, so everything turned out pretty good. I am pleased with this grill.


Then I enclosed the grate in a wooden frame that performed several tasks. First, she holds a sheet of polystyrene at the top of the grill. It ensures that the grille does not move. In addition, a wooden frame presses all the wires so that they hold more securely and cannot accidentally come off (which happened a couple of times when I moved the display).


This photograph shows a sanded polystyrene sheet laid on a wire rack. Notice that the grill is now barely visible, which is what we wanted.


After spending long hours experimenting with the correct implementation of display control, we finally managed to get it to work. A huge problem was the preservation of the integrity of the signals. But as I said above. The community from electronics.stackexchange helped me with this!

The display is bright, much brighter than I expected. It was necessary to foresee this, ordering a 100 A unit for its power supply.


As I have said several times, we use the FastLED library to control LEDs. But I did not mention the fact that I also use a modified version of the FastLED-GFX library by Jürgen Skrocki (which itself is a port of the Adafruit-GFX-Library ) for simple rendering of figures on the display . The changes in this library are minor, but they were necessary so that the interpreter could communicate with the library in a convenient way.

Brains and ...


One of the last technical tasks that need to be solved to complete this project is the completion of the brains of the console. You need to turn them into one convenient and compact set. But first we need to figure out how to handle all the input signals of the players. Let me remind you that each player has 4 buttons and one joystick. That is a total of 16 digital input signals and 8 analog. MK never has enough contacts for such input; in addition, two data bus pins are already used to read the EEPROM, and 7 parallel data bus pins are needed to control the display.

To solve this problem, we use a pair of shift registers for digital input. And for all analog inputs, we will take an analog multiplexer.


Scheme for simultaneously reading / writing EEOPROM, processing player input and display control.

And then the confusion begins. Let me explain what is happening in this photo, from left to right. At the top of the left breadboard are 7 data buses used to control the display. Below is the area where the EEPROM can be inserted and where it is read.

At the top of the middle breadboard is an analog multiplexer. This multiplexer can receive up to 16 analog input signals, and depending on the input signals on the multiplexer, connect one of the analog signals to the MK. Thus, we only need one analog input pin and a pair of digital input pins to process 16 analog inputs. It looks like no analog input is connected to the multiplexer in this photo.

Under the multiplexer is MK Teensy.

On the right breadboard, we process digital input signals. In this photo, 16 digital signals are simply connected to ground. I was still waiting for the buttons to arrive, so I tested all 16 digital signals this way. Thanks to the shift registers, only 4 pins were required to control all digital signals.

The whole system is a huge unreliable chaos. It is necessary to make it more compact so that it does not fall apart from one careless exhalation. Therefore, I ordered several prototyping boards and started to solder again!



And that turned out to be a difficult task! However, this was an excellent occasion to learn how to accurately solder.

To come up with this circuit, I used as an example the chaos of the wires on the breadboard. Then I tried to come up with a smarter circuit so that the components that should communicate with each other are as close as possible. So I tried to get rid of the need to pull too many wires. Now I think that you could use some modeling tools to design the circuit. But still it turned out pretty well.

I decided to design a two-layer circuit. On the lower prototype board, all input is processed. On each of the 4 input connections, I have 8 input lines (1 - ground, 1 - positive, 4 - digital input, 2 - analog input). MK communicates with the bottom layer using four connections next to the shift registers and four connections next to the multiplexer.

The power supply is located on the upper layer, on the right there are 7 output data buses for the display, and on the bottom there are contacts for reading the EEPROM. And finally, in the center, of course, is the microcontroller.


Between the main control boards and the input of the players, I placed intermediate boards to reduce the number of required wires on both sides from 12 to 8, because it is not necessary to use all 5 ground wires going from the main board to the input board. One grounding is sufficient for all buttons and the joystick. Therefore, there are four such intermediate boards. I like that you can notice an improvement in the quality of each next board you collect.


Having never received the ordered buttons, I ordered another set from another seller and after a couple of days I received it. This allowed us to finally start testing all the buttons.


At this stage, I also wrote the first game that can be played on the console. Yes, now I call it the console.

I succeeded because in the process of working on the display I simultaneously improved the interpreter. In particular, I managed to improve the development process itself when writing code. This process is not so interesting externally, so I decided not to particularly document it.


I created a simple development environment for writing code that can be executed on the console.

This environment works in a browser, and it allows you to write code for the console without messing with the chaotic lists of numbers that we saw above. In addition, I created a console emulator that runs in the same web application.

The ability to emulate games for the console in a web application saved a lot of time, because debugging on a PC is much easier than on a MK.

The emulator is not perfect. There are some bugs that distinguish emulation from playing on a real version of the console. I will try to eliminate them in the future when I write a new version of the interpreter. The need to support two versions of the interpreter (one written in C ++, the other in TS) was a bit annoying, but it was worth it.

Putting it all together


Everything is ready. We can display images based on game logic taken from the EEPROM and process player input from buttons and joysticks. Now we need to combine all this into one durable device.


I started by drilling holes in the aluminum plates that will hold the buttons and joysticks in place. Then it was possible to insert these plates into the grooves of the wooden case in which they were conveniently recessed. Thanks to this, players will not be able to accidentally scratch on metal.



We collect everything around the display and add reliable folding legs (for easy storage). The metal plates painted in black paint look very beautiful. There is a feeling that the project is really moving towards completion.


But of course I was mistaken in believing that the project was almost complete. Here's what the console looked like for about a month.

We collect everything, we understand that the button does not work. We disassemble again, fix the problem with the button. Everything seems to work. We understand that the joystick does not work. Disassemble again. Sooner or later, all buttons and joysticks begin to work. But then the LEDs stop working. To fix them, you need to disassemble the entire console and reassemble from the very beginning. This went on for about a month, until finally everything worked.

Result




Everything is ready! After starting work on the project 3-4 months have already passed. Therefore, it is logical that my motivation to continue to improve the interpreter, paint the tree and develop new games has already dried up. At the time of this writing, a month has already passed, when I was last involved in the project. I finally gained strength to write this documentary post for myself and you, my reader. Although I do not expect that someone in their right mind will actually read everything that I wrote, I hope you enjoyed viewing photos of the gradual development of the project.

But if you read all this, then you may be interested in the Github repository of the project. Of course, all of my code is open source! https://github.com/Arcadable

Further project development plans:

- Firstly, you need to make a more beautiful cartridge for playing Pong for four, which is shown in the last video. While it is a piece of cardboard with curved pieces of aluminum foil, which are used as contact surfaces.

- In addition, I want to better paint the console. Initially, I planned to paint it with very experienced friends who like to paint. However, now because of the pandemic this is not possible.

- Finally, as I said a couple of times, I am going to rewrite the interpreter in a more efficient way. I will also improve the development environment to make games easier. Web app design is currently hindering productivity.


Compensation for recording vertical videos.

All Articles