How computers and devices run code
Before starting to write code it is helpful to have a good understanding of how the hardware runs the code. This helps us to decide what approach to take when designing programs, choosing programming languages, and making programming decisions.
Let’s take a look at the popular platforms and devices that we might target for game development.
Windows is the most popular operating system (OS) in the world and is of course installed on PC’s, laptops, and some tablet-style devices. The hardware is usually based on Intel or AMD central processing units (CPUs).
The CPU contains multiple cores that allow processes to run in parallel with instructions being represented by 32 bit or 64 bit words in modern devices. This word size impacts how many instruction cycles are needed to complete operations on data.
Much of the data will be numbers or memory addresses. Integer numbers are limited in size by the number of bits or bytes used to represent them. But, for fractional and large numbers, floating point format is used. And, a dedicated floating point processor is provided to crunch these numbers at high speed.
The CPU has a maximum clock speed that determines how fast instructions may be processed. As the speed increases, the power consumption increases and heat is produced. This isn’t too much of a concern with a PC since the system is designed with efficient cooling in mind, and it is mains powered.
Graphics are taken care of by a separate sub-system using a Graphics processor (GPU). This may be inside of the CPU chip in Intel devices allowing for the onboard graphics capability of the motherboard to be used. But gamers often demand high frame rates at high resolution requiring a dedicated GPU board.
Shader code is run on the GPU. This is a specialized language used to determine how the triangles of a mesh are manipulated, how color pixels are presented, and how light interacts with the view.
The OS takes control of the PC after the BIOS of the computer runs a boot loader program. When the machine has booted into Windows it is ready to run Applications (Apps). Apps may run in windowed mode, in the background, or from the command line in a simple text screen mode.
Application code is either compiled into an executable file, compiled into a simplified form each time it is run, or interpreted line by line in order to execute the code. With each increment in these methods of execution, the execution speed is slower. But this is not necessarily a problem for a game if the execution speed is fast enough to have an adequate video frame rate and responsiveness to user input.
Executable files contain machine code that the CPU understands. The instructions for this code is considered very low level and is specified in the data sheet for the CPU. It is very efficient (fast), taking a few clock cycles to execute instructions, but difficult to code since the instructions are primitive such as for adding a byte of data to the value stored in a hardware location. So the programmer needs detailed knowledge of the hardware architecture to code with it.
Most low level coding will be done to write device drivers to connect the hardware devices to an abstraction layer of code that interfaces with the OS. And the programming is likely to be done in C or C++ which have optimized compilers to produce the machine code. The lower-level way to code would be to use assembly language as specified in the CPU data sheet; or even more hard-core, add inline bytes of data to a source code file that equate with the processor instructions.
So you can see that there is a trade-off between ease of coding with higher-level languages and speed of execution with low-level programming.
There are many compiled programming languages that produce the same kind of machine code, but with widely varying syntax to write the program code. When the programs are executed, they may have a list of input parameters, then the program runs from a main method and interacts with the application programming interface (API) of the operating system. Finally, the program will be terminated by code or by an interruption, and exit with an integer error code.
The compiler may be configured to build a command line application, a Windows app, or a library of code (DLL).
Interpreted languages (or scripting languages) sit on top of an interpreter program that scans the code to first check for syntax errors, and then translates the code into a simplified form that runs pre-compiled modules of code.
In this website we will be mostly dealing with GDScript, the source-code of which is compiled to bytecode for fast interpretation by the engine at run time.
Windows has the DOT NET framework that supports various interpreted languages that get compiled into a common intermediate language.
A Linux computer has the same hardware as a Windows computer, the difference is only in the installed operating system.
A MAC computer uses proprietary hardware and has it’s own OS based on a Unix operating system.
Android devices are often small and mobile, so they need a more energy efficient CPU than is found in a PC. This is often based on an ARM core which is a design of a processor that is licensed out to hardware manufacturers to incorporate into their devices. The ARM core has it’s own instruction set different to that of a PC. So different compilers are needed to produce the executable code.
IOS devices are also based on the ARM core.
Computing devices run code in much the same way with differences in speed and power consumption. Low-level languages get close to the hardware and run the fastest but are the most difficult to develop with.
High-level compiled languages are generally fast enough for most applications since they produce machine code, but are harder to learn, and require more steps in order to compile and use than Scripting languages.
Scripting languages are easier to learn, and more convenient to use (shortening development time), but are slower due to the need to interpret intermediate tokens of code. However, they can leverage pre-compiled modules of code that provide high-level API access to functionality.