Introduction
In this publication, I talk about gbaunix, an amusing experiment, during which I launched an ancient version of the UNIX operating system in a simulator on the popular
(at the time of publication, in 2004, a comment of the portable console
) portable console. Namely, UNIX 5th edition (released in 1974, 39 years ago) on the Nintendo Game Boy Advance. This may be of interest to homebrew developers for Gameboy, IT students with specialization in operating systems, emulators or compilers, and geeks-unicsoids.

Nintendo has been on the gaming market since 1889 (sic!). Gameboy is a brand of a whole line of portable consoles, which is very successfully sold to this day. Since its release in 1989, 175 million units have been sold. This article discusses the Game Boy Advance, abbreviated GBA, and its equivalent GBA SP.
Iron:
- 32-bit ARM processor (RISC), clocked at 16.78 MHz
- 32-bit ARM processor (RISC), clocked at 16.78 MHz
- 8-bit processor Z80 (CISC), the frequency of 4.2 or 8.4 MHz. Added for compatibility with old Gameboys, it had a central processor
- 4 16-bit timers
- 4 DMA channels
- Color TFT screen, resolution 240x160
- Stereo sound through headphones
- 10 buttons
- Serial port
- Interface for GamePak Cartridge
There are several memory blocks in the console:
- 16 KB BIOS ROM
- 256 KB external RAM soldered to PCB (EWRAM)
- 32 KB internal RAM, on-chip CPU (IWRAM)
- 1 KB RAM for background and sprites palette
- 96 KB Video RAM
- 1 KB RAM for object attributes
- Up to 32 MB ROM cartridge
- Up to 64 KB SRAM cartridge, optional
')
It should be noted that the ROM cartridge has two additional displays in the address space of the console. In addition, the cartridge may contain several banks of memory with different volume or timings.
GBA can be loaded from a regular cartridge, a rewritable flash cartridge, another GBA in master mode, or even from a computer via cable. This functionality is wired in the BIOS.
Console iron is mostly available through a well-documented address space. Different I / O registers are mapped to memory addresses. In addition to this, the BIOS contains many functions available through software interrupts.
Lyrical digression about ARM architectureARM
Nintendo is the market leader in consoles, and ARM is the market leader in RISC processors. Now ARMs are present in almost all electronics. Intel drives on desktops, yes. But processors for the PC make up a very small fraction of the total production. In 2003, 782 million devices were produced at the AWP. In general, the share of this architecture is around 75%.
Most often, AWPs are used in the same sentence with the words “built-in”, “productive”, “cheap”, “low-roughing”, “RISC”. AWS licenses the architecture directly to processor manufacturers, including as large as Intel, Apple, Samsung.
The first AWP was developed at Acorn Computers Limited in the mid-80s. Then it was deciphered as "Acorn RISC Machine". The very first version of the ARM architecture, ARMv1, supported 26-bit addressing and was very slow. The first processor of this architecture, ARM1, was a peripheral processor in the Air Force microcomputer and the prototype Archimedes workstation. And it was one of the first processors of the RISC architecture. Main features: deferred branching, register windows, each instruction is executed in one clock cycle.
Apple tried to use the automated workplace in the early 90s. In collaboration with Acorn, they launched a new company, Advanced RISC Machines, Limited. VLSI Technology was another accomplice. The abbreviation has changed. The new processor was called ARM6, architecture - ARMv3. There is a full 32-bit addressing. This processor was used in the Apple Newton.
Gameboy uses the ARM7TDMI processor, an ARMv4T version architecture.
ARM in Geymboe
ARM7TDMI is a popular embedded 32-bit processor with slightly limited functionality. It does not have a cache and MMU. The designation stands for:
ARM7 processorSupports a set of 16-bit instructions
T humb
Supports
D ebug right in the hardware
It has a built-in 32-bit block at the
M hopping, the result is 64-bit
There are Embedded
I CE for debugging
The ARM7TDMI core has one 32-bit bus for data and instructions. The data can be 8, 16, 32 bits. Only loading, saving, and sharing instructions can access memory. There are 31 32-bit general-purpose registers, 6 status registers, a shift register, arithmetic and multiplication blocks. Not all registers are available at the same time. For example, in ARM mode, 16 common and 1 or 2 status registers are available. There are 7 modes of operation of the processor: normal for program execution, and 6 special ones. These are quick interrupt, interrupt, supervisor, stop, undefined state and system mode. Also supported are two sets of instructions - ARM and Thumb.
Gameboy supports 4 DMA channels. The processor can do two types of interrupts - regular IRQs and fast FIQs, but only normal ones are used in the console.
ARM7 has a simple three-stage pipeline:
The command is retrieved from memory and placed in a queue.
Command decoded
The command is executed. When this happens, reading from registers, calculating results and writing from to registers takes place.
Thus, at any time one command is executed, the next one is decoded, and one command is retrieved.
Thumb
The relative disadvantage of RISC processors is a relatively large code. This increases the volume of the program and leads to loss of cache efficiency, excessive memory traffic and energy consumption. For embedded applications, this is especially bad. To compact the code we developed the architecture of Thumb.
Thumb is a system of 32-bit ARM commands compressed to 16 bits. A set of the most popular instructions is supported. They work with the same 32-bit registers. Processors with Thumb support are equipped with a decoder in the pipeline that converts them into ordinary ARM instructions. The difference is like this:
- 35% of the code is saved
- It takes 40% more teams
- Code is 40% slower for 32-bit memory
- But 60% faster for 16-bit
- 30% less power consumption
A mixture of ARM and Thumb commands is commonly used. The type of command being executed is indicated by a special flag. In Geymboe there are 32 KB of fast memory right on the chip. Normally, a speed-critical code is executed from there. Everything else is appropriate to compile into Thumb and run from the slow memory of the cartridge.
habrahabr.ru/post/92494 - useful reading matter in general about ARM. - approx. trans. Gbaunix high-level architecture
gbaunix is a UNIX 5 edition running on Gameboe. SIMH is used for this, a simulator of various antique computers written in C. SIMH can emulate a lot more, but only PDP-11 is used here. For Gameboy, there are several tulcheynov C, so it turned out a little blood to port SIMH to Gameboy. The architecture of the resulting system is shown below:

The gbaunix cartridge is a concatenation of the simulator runtime and the OS disk image. The rest of the place can be left empty, or take something useful.
The simulator is a minimally modified SIMH. Gameboy-specific features are implemented in a separate level of abstraction.
Tty output
gbaunix simulates a text terminal for SIMH. The output is redirected to a procedure executed on Gameboy, which formats it and displays it on the screen. Supported scrolling.
printf()
split into
sprintf()
into a buffer and display it on the screen.
Tty input.
Now there is no sane input support at all. You can only execute a sequence of shell commands defined upon compilation. It is set in the
gba/gba_kbd.h
. When UNIX is running, the Start button gives the following command from the list for execution. It is possible to monitor button presses, polling, or through an interrupt. Example:
const char *gba_kbdinput[] = { "unix\r", "root\r", "chdir /work\r", "ls -l\r", "./fact 100\r", "cat hanoi.c\r", "./hanoi\r", "./hanoi 3\r", "chdir /tmp\r", "echo 'main() { printf(\"Hello, World!\\n\"); }' \ > hello.c\r", "cc hello.c\r", "./a.out\r", ... NULL, };
File system.
The disk image takes 2.5 MB, it fits only in the ROM cartridge. Although this memory is read-only, it is necessary to somehow handle the write to it. To do this, each write operation creates a buffer in RAM. All read and write operations are first checked for a buffer. As the number of such buffers grows, they merge. Simulator slips virtual stdio.
Memory.
The simulated PDP-11 is available 128 KB of memory available in hardware 256 KB EWRAM. There is some memory optimization like using DMA.
Other
Here any code like initialization of the execution environment, TTY, interrupts, file system, etc.
Development
gbaunix works on both the Gameboy emulator and the iron console. To run in the gland you will need a flash cartridge and a programmer for it.
It is much more convenient to use the Gemiboy emulator, especially if you want to tinker with the source code. gbaunix is very conditionally optimized for the time being, and it works very slowly on the iron console. The emulator will allow you to work with the maximum available speed, and this will save a lot of nerves.
My development environment is deployed under Mac OS X. It uses the Boycott Advance emulator and devkitARM toolchain compiled from raw materials. Checked on a real console with a flash cartridge.
Lyrical digression about the history of UNIX
Here was a large text that had no direct relation to the subject of the article, but was too curious to get rid of it. Delivered to a separate post -
habrahabr.ru/post/194160Demonstration of work gbaunix, with comments
Fifth Edition, June 1974
I use the fifth edition because it is the oldest version for which there are electronically downloadable images of the system and kernel source code. We will try to recompile it, because it is true.
When you turn on the power, gbaunix will show some information about the PDP-11 hardware and the bootloader prompt -
@
. If you click
Start
, the command queue will give the name of the kernel to boot -
unix
. Loading on the iron Geimboe takes about two minutes. After downloading, you are prompted to login.

The semicolon in the invitation (
; login is also a paper magazine issued by the USENIX Association) is necessary for the
Teletype model 37
terminal,
Teletype model 37
popular in the early 1970s. It translates it into full duplex mode. All other terminals, including our GBA TTY, simply display the symbol on the screen.
Even such an early version of UNIX has block and character device files.
RK0
is the first disk,
/dev/mem
- mapping system memory for debugging with debugger and patching hot.

glob
, short for
global
, is a command external to the shell for expanding the metacharacters
*
and
?
in command arguments.
glob
opens metacharacters and invokes the desired command. If there is no match, the traditional error
No match
is issued.

It is curious that some commands like
mkfs
hidden in
/etc
, away from a random call with curved hands.
dc
is a calculator with reverse Polish notation. This is the first program running on the PDP-11, even before the creation of a UNIX version for this computer.
The typical core of the fifth edition is less than 26 Kb. Shell occupies 5738 bytes, and
/init
- only 1972 bytes. There is also a minimally decent script
/etc/rc
.
/etc/update
updates the file system superblock every 30 seconds, to reduce crash losses. The detailed output of the
ls
includes access rights, the number of links, the owner, the size in bytes, the last modification time, and the name.

By the era of the fifth edition, a rich development infrastructure had already been created with support for many programming languages. For example, Algol-68, APL, Assembler, BASIC, C, FORTRAN, M6, PASCAL, Snobol, TMG. In principle, gbaunix allows programming in several languages directly on Gamemboe (this is in theory, in reality it is at least inconvenient due to the lack of a keyboard). The package includes compilers / interpreters for C, PDP-11 assembler, BASIC, shell and Fortran. I also tried algol, but did not add it to the disk image. For example, showing the towers of Hanoi.



More screenshots can be viewed on a
special page with screenshots.Subsequent editions
The sixth edition (May 1975) left its mark on history, because BSD and Xenix originated from it. John Lyons wrote his famous "
Lyons Comments on UNIX Version 6, with Source Code ." It is also the earliest fully preserved version of UNIX. Documentation for the fifth edition is lost, from the fourth and earlier there is almost nothing. Since the sixth edition, the development of UNIX-systems has noticeably quickened. Then there were the seventh edition in January 1979, the eighth in February 1985, the ninth in September 1986, and the tenth in October 1989.
BSD
You can run several more systems supported by SIMH on Gameboy. But it is more and more difficult, and rests on the available RAM. A couple of screenshots from BSD 2.9:


Gbaunix optimization
Gbaunix has prerequisites for experiments that affect the speed of work. But this will require recompilation.
Credit Code in IWRAM
In gbaunix, there are examples of compiling code for ARM and storing it in IWRAM. This will probably be most useful for the processor simulation code.
DMA
Gameboy allows you to work with memory in several ways, with different performance and limitations. gbaunix uses DMA3 (general purpose) for
memcpy()
and
memset()
functions. Moreover, the BIOS contains functions for copying and filling memory through software interrupts. In general, gbaunix supports fine tuning of work with memory.
Caching
As I said, gbaunix emulates stdio and a virtual disk, representing the cartridge memory as a UNIX file. Since iron does not allow writing to ROM, it is necessary to get by with buffers, as mentioned above. gbaunix can preload disk fragments into buffers. This allows you to significantly speed up the boot system.
Recompiling the UNIX kernel
Recompiling the kernel does not give any noticeable advantages for gbaunix, but this is interesting in any case. At least for comparison with the same procedure for modern systems. We can limit iron support to the core and thereby save some space.
Estimate the size of the source code of the fifth edition.
Headers: 418 lines in 13 files
C: 7222 lines in 43 files (including drivers for peripherals)
Assembler: 1080 lines in 2 files
I didn’t even try to compile the kernel directly on Gameboe. It will take an indefinite long time, and we will run out of memory for buffers. And in general, the equipment for such a task is too weak.
The next sequence of commands assumes that there is a working installation of the fifth edition, on real hardware or on the simulator, and the kernel source in the default directory is
/usr/sys
Remove libraries, possibly remaining from the previous compilation:
Before starting the compilation, it is necessary to study and correctly specify the parameters in the
/usr/sys/param.h
file.
If the compiler produces the error "
undefined KISA0
", add the definition to
/usr/sys/seg.h
:
Actually compilation:
Compiling drivers and other things. You can partially disable:
System configuration and linking. The output is a kernel binary:
rkunix
is the
rkunix
kernel. If you put it in the root directory
/rkunix
, and when booting give the command
rkunix
instead of
unix
, then it will load.
Ideas and suggestions
A short list of promising ideas. Interest is mostly academic
Native UNIX port on Gameboy
Porting UNIX to Gameboy would be a good exercise for students in a course on operating systems. Productivity should increase dramatically. Ancient operating systems are small enough to fit in the head of one person. The sixth edition consists of 44 files:
14 C headings
28 files with C code
2 files with assembler.
All together contains less than 9000 lines of code. This is with device drivers. Assembler there is about 10%.
In my opinion, the task is quite feasible. There may be difficulties with assembly code and compiler porting.
Performance improvement
Although I tried to speed up work where it is possible, but it is still far from a final solution to the issue. You can start with the processor simulation code (
pdp11_cpu.c
) - it runs the largest fraction of the time.
Input mechanism
Now gbaunix simply executes the command queue sewn up when compiled. To get closer to reality, a user input method is required. Alternatively, you can offer a virtual keyboard that normally works with the terminal.
Emulation of the original Macintosh on Gameboe
The first Macintosh was not very advanced iron: 8-MHz 16-bit processor, 128 KB RAM, 64 KB ROM, no cache, no interrupts, 400 KB floppy disk, monochrome screen with 512x342 resolution. For Gameboy, iron is still more powerful than the screen. In principle, you can create or port a lightweight Macintosh emulator. The lack of screen can be compensated by scrolling, simulate writing to disk by buffers, etc.
Another option is to port the 8088 emulator to run the old version of DOS.
Where can I download
gbaunix-0.0.tar.bz2It should be noted that to run, you must have a disk image RK05. It is not included in the kit, but you can download it from the PDP Unix Preservation Society website, if you accept the terms of the license agreement.
http://minnie.tuhs.org/PUPS/Using
If you just want to see, you can do without recompiling and stitching the runtime simulator and disk image into one heap:
% cat unixv5.tmp disks/unixv5.dsk > unixv5.gba
unixv5.gba
is a ready-to-run image of a cartridge. It can be used with an emulator, and with an iron console.
If you want to recompile gbaunix (highly recommended, this is actually the only way to get fun from the process), then you will need a cross-compilation environment for the ARM architecture. You may need to fix the Makefile. The RK05 image should be named
disks/unixv5.dsk
. After that, theoretically, a
make
command should suffice.
What else to read on this topic
Sources, binaries and documentation for older UNIX versions
Texts by Dennis Ritchie
SIMH documentation