Commodore logo
(last updated 2025-06-07)
Commodore logo
GeckOS console

GeckOS is under active development; André recently released version 2.2, so by now this page is quite out of date. You can find the latest source in André's repo on GitHub. In the source, you'll find a directory named doc/ with thorough documentation in AsciiDoc.


GeckOS is a Unix-like 6502 operating system by André Fachat with preemptive multi-tasking, signals, semaphores, redirection, a standard library, and its own relocatable file format. It runs on the Commodore 64, PET, and 8296 machines, as well as a 6502 machine that André built himself. I gave a talk about it at VCFMW 2019; here are the slides and the video. I gave another talk at the World of Commodore show in Toronto (December 2019), highlighting some of the recent enhancements in GeckOS. Here are those slides and the video.

Building GeckOS is straightforward. The xa cross-assembler is used to build the operating system and to create relocatable binaries for it. Its documentation includes usage instructions as well as a description of the relocatable file format. If you don't feel up to building GeckOS yourself, here's a D64 image built from the master branch of the Commodore 64 version as of 2020-07-15.

If you're interested in the internals of GeckOS, I've been working on an analysis of the source code, which is quite detailed (although still incomplete). Note that the analysis refers mostly to the 2.0.9 version; at some point I'll update it for the 2.2 version.

Tips for exploring GeckOS
Debugging GeckOS Programs
Using SLIP with GeckOS

Tips for exploring GeckOS

Debugging GeckOS Programs

Here's how to find the addresses of code or variable labels in your GeckOS program. If you need to know an address before the program starts, you could wait for a keystroke at the beginning of your program like this:

#include "lib6502.i65"
#include "apps/common.a65" ;for strout

hitakey .(
  lda #hitkey
  jsr strout
  ldx #STDIN
  sec        ;wait for keystroke
  jsr fgetc
  rts
).

hitkey   .asc $0a,$0d,"hit a key...",$0d,0

First, you have to assemble your program with the -l flag to get a label listing. Run the file65 utility (part of the xa distribution) against the executable to find the segment sizes. Here is the output for the examples I'll be showing:

arch/c64/test/uiitest: o65 version 0 executable file
 mode: 0000 =[executable][16bit][byte relocation][CPU 6502][align 1]
 text segment @ $1000 - $11fc [$01fc bytes]
 data segment @ $0400 - $0535 [$0135 bytes]
 bss  segment @ $4000 - $4228 [$0228 bytes]
 zero segment @ $0004 - $0008 [$0004 bytes]

This program waits for a keystroke on startup, so I switched to a different console and ran the ps command, which told me that the program starts at $2C33. Bear in mind that ps shows you the execution address, not the load address. If you have a main label and it's not at the start of the program, you'll have to do a little more arithmetic to get the load address.

The segments are contiguous in memory, so you can add the size of each one in turn to the load address, giving these numbers:

text:        $2C33
text length: $01FC
data:        $2E2F
data length: $0135
bss:         $2F64

Note the (arbitrary) offset for each segment: you'll have to subtract it from the label's address, then add it to the segment address:

text: $1000
data: $0400
bss:  $4000

I'll show how to find a label from the text (code), data, and bss segments. First, the goahead label, near the start of the code (I have main at the beginning). The label file shows us this:

goahead, 0x102d, 1, 0x0002
subtract offset: $102D - $1000 = $002D
add to start of text segment: $2C33 + $2D = $2C60
The banner label, in the data segment:
banner, 0x04cc, 1, 0x0003
subtract offset: $04cc - $0400 - $00cc
add to start of data segment: $2E2F + $00cc = $2EFB
The message label, in the bss segment:
message, 0x4200, 1, 0x0004
subtract offset: $4200 - $4000 = $0200
add to start of bss segment: $2f64 + 0200 = $3164

For zero-page variables, check the output of the GeckOS build, which runs file65 against the ROM image (note that these are absolute addresses):

c64rom.o65: o65 version 0 executable file
 mode: 0000 =[executable][16bit][byte relocation][CPU 6502][align 1]
 text segment @ $83fe - $10000 [$7c02 bytes]
 data segment @ $0300 - $0b13 [$0813 bytes]
 bss  segment @ $0b30 - $1675 [$0b45 bytes]
 zero segment @ $0008 - $0067 [$005f bytes]
You can see that zero-page variables start at $0008; add that to the zero segment offset in your program's file65 output ($0004 in the example above), then add the label's address to that. This may get more complicated; see the discussion of zalloc in my commentary.

Using SLIP with GeckOS

GeckOS has TCP/IP networking using SLIP, but it doesn't always behave (hint: testing would be appreciated!). André reports that it can be run in the VICE emulator:

If you use the commands below, you can run GeckOS in VICE and provide an sl0 network interface to talk to it without any hardware requirements! Simply run
x64sc -rsuser -rsuserdev 2 -rsuserbaud 9600 -rsdev3 "|socat - PTY,link=/tmp/viceser"  -autostart osa.d64
and the following csaip script as
sudo ./csaip -d /tmp/viceser
You can actually run VICE without any USB/serial hardware and still have it provide an sl0 network interface.

At least that's how it works on Linux. socat's PTY option creates a "master pseudo terminal" that slattach can then use to attach to the client side and create a network interface. Because socat uses "-" for STDIO, I can pipe in/out the RS232 emulation of VICE by specifying the VICE RS232 output device name with the "|".

The "link" option to socat just creates a symlink to the real pty file (as the name is not deterministic it seems), and the "readlink -f" command translates the symlink to that actual device file, as slattach does not follow symlinks.

Here's the csaip script.