Creating the Commodore 64 – The Engineer Story

https://spectrum.ieee.org/commodore-64

In January 1981, a handful of semiconductor engineers at MOS Technology in West Chester, Pa., a subsidiary of Commodore International Ltd., began designing a graphics chip and a sound chip to sell to whoever wanted to make “the world’s best video game.” In January 1982, a home computer incorporating those chips was introduced at the Winter Consumer Electronics Show in Las Vegas, Nev. By using in-house integrated-circuit-fabrication facilities for prototyping, the engineers had cut the design time for each chip to less than nine months, and they had designed and built five prototype computers for the show in less than five weeks. What surprised the rest of the home-computer industry most, however, was the introductory price of the Commodore 64: $595 for a unit incorporating a keyboard, a central processor, the graphics and sound chips, and 64 kilobytes of memory instead of the 16 or 32 that were then considered the norm.

Quick Guide to nawk

Quick Reference Guide

Quick Guide to nawk

nawk (new awk) extends the original awk with more built-in functions, better string handling, and user-defined functions. Most modern systems have both installed; nawk is generally preferred. This guide covers syntax, built-in variables, patterns, string functions, control flow, arrays, and common one-liners.

Note: This guide was originally published in 2006 and has been substantially expanded in May 2026 with full content, with assistance from Claude (Anthropic).

Basic Syntax

nawk reads input line by line and applies rules of the form pattern { action }. If the pattern matches the current line, the action is executed. Either part is optional.

nawk 'pattern { action }' file
nawk -f script.awk file       # read program from a file
nawk -F: '{ print $1 }' file  # set field separator to :

Each input line is automatically split into fields. $0 is the entire line; $1, $2, … are individual fields. The default field separator is whitespace.

Built-in Variables

VariableMeaning
$0The entire current input line
$1, $2, ...$NFIndividual fields (1-based)
NFNumber of fields in the current line
NRTotal number of records (lines) read so far
FNRRecord number within the current file (resets per file)
FSInput field separator (default: whitespace)
OFSOutput field separator (default: space)
RSInput record separator (default: newline)
ORSOutput record separator (default: newline)
FILENAMEName of the file currently being processed

Patterns

Patterns control which lines trigger an action. The four main types:

PatternMeaning
BEGINRuns once before any input is read. Use for initialisation.
ENDRuns once after all input is processed. Use for summaries.
/regex/Matches lines where the regex matches anywhere in $0.
expressionAny comparison or boolean expression, e.g. NF > 3 or $2 == "SG".
BEGIN { print "Start" }
/error/ { print "Found error on line", NR }
NF > 5  { print "Long line:", $0 }
END   { print "Done. Total lines:", NR }

print and printf

print outputs values separated by OFS and terminated by ORS. printf gives C-style formatted output with no automatic newline.

{ print $1, $3 }                      # print fields 1 and 3
{ print $1 > "output.txt" }           # redirect to file
{ print $1 | "sort" }                 # pipe to command
{ printf "%-10s %5d\n", $1, $2 }      # formatted output

Common printf format specifiers:

SpecifierOutput
%sString
%dInteger
%fFloating point
%-10sLeft-aligned string in a field of width 10

String Functions

FunctionDescription
length(s)Length of string s (or $0 if omitted)
substr(s, m, n)Substring of s starting at position m, length n
index(s, t)Position of string t in s (0 if not found)
split(s, a, fs)Split s into array a using separator fs; returns number of fields
sub(r, s)Replace first match of regex r in $0 with s
gsub(r, s)Replace all matches of regex r in $0 with s
match(s, r)Returns position of regex r in s; sets RSTART and RLENGTH
toupper(s)Convert s to uppercase
tolower(s)Convert s to lowercase
sprintf(fmt, ...)Return a formatted string (like printf but returns rather than prints)

Control Flow

# if / else
if ($3 > 100) { print "high" } else { print "low" }

# while loop
{ i = 1; while (i <= NF) { print $i; i++ } }

# for loop
{ for (i = 1; i <= NF; i++) print $i }

# next  -- skip to next line
/^#/ { next }          # skip comment lines

# exit  -- stop processing
NR > 100 { exit }      # stop after 100 lines

Arithmetic operators: + - * / % ^. Comparison: == != < > <= >=. String match: ~ !~.

Arrays

nawk arrays are associative (keyed by string). No declaration is needed.

# count occurrences of each value in field 1
{ count[$1]++ }
END { for (k in count) print k, count[k] }

# delete an element
delete count["key"]

# check if a key exists
if ("key" in count) print "found"

Multi-dimensional arrays use comma-separated keys: arr[i,j].

Common One-liners

TaskCommand
Print field 2 of every linenawk '{ print $2 }' file
Print lines longer than 80 charsnawk 'length > 80' file
Count lines matching a patternnawk '/error/{ c++ } END{ print c }' file
Sum a column of numbersnawk '{ s += $1 } END{ print s }' file
Print unique lines (first occurrence)nawk '!seen[$0]++' file
Print line numbersnawk '{ print NR": "$0 }' file
Print last field of each linenawk '{ print $NF }' file
Replace a string in field 2nawk '{ gsub(/old/, "new", $2); print }' file
Use colon as field separatornawk -F: '{ print $1 }' /etc/passwd
Print lines between two patternsnawk '/START/,/END/' file

For the full specification, see the GNU awk manual. On most Linux systems, man nawk or man awk also gives a concise reference.

Quick Guide to Emacs

Quick Reference Guide

Quick Guide to Emacs

A collection of commonly used keystrokes and configuration tips for GNU Emacs. Covers navigation, editing, buffers, search, and macros.

Note: This guide was originally published in 2006 and has been updated in May 2026 with corrected key notation, additional sections, and improved formatting, with assistance from Claude (Anthropic).

Key Notation

Emacs key bindings are written in a standard shorthand throughout this guide:

NotationMeaningExample
C-xHold Ctrl and press xC-x C-s means hold Ctrl, press x, then press s
M-xHold Meta (Alt/Esc) and press xOn most keyboards, Meta is the Alt key
C-SPCHold Ctrl and press SpacebarSets the mark for region selection

To run the built-in Emacs tutorial at any time: C-h t

Useful Settings for .emacs

Add these to ~/.emacs or ~/.emacs.d/init.el to configure Emacs on startup:

(line-number-mode 1)       ; show line number in mode line
(column-number-mode 1)     ; show column number in mode line
(display-time)             ; show clock in mode line
(load-theme 'deeper-blue t); set colour theme

To reload your config without restarting: M-x load-file RET ~/.emacs RET

File Operations

ActionKeystroke
Open / find fileC-x C-f
Save fileC-x C-s
Save as (write to new file)C-x C-w
Quit EmacsC-x C-c

Navigation

ActionKeystroke
Go to line numberM-g g
Go to beginning of bufferM-<
Go to end of bufferM->
Move between windowsC-x o
Scroll down / upC-v / M-v

Editing

ActionKeystroke
Set mark (start region selection)C-SPC
Exchange mark and pointC-x C-x
Kill (cut) lineC-k
Yank (paste)C-y
UndoC-/ or C-_
Kill (cut) rectangle regionC-x r k
Yank (paste) rectangle regionC-x r y
Toggle comment on regionM-;

Buffers and Windows

ActionKeystroke
List all open buffersC-x C-b
Switch to bufferC-x b
Kill (close) bufferC-x k
Split window horizontallyC-x 2
Split window verticallyC-x 3
Close current windowC-x 0
Close all other windowsC-x 1

Search and Replace

ActionKeystroke
Incremental search forwardC-s
Incremental search backwardC-r
Query replace (interactive find and replace)M-%
Replace all (no prompt)M-x replace-string

During incremental search, press C-s again to jump to the next match, or RET to exit search at the current position.

Keystroke Macros

Macros let you record a sequence of keystrokes and replay them. Useful for repetitive edits across many lines.

ActionKeystroke
Start recording macroC-x (
Stop recording macroC-x )
Playback last macroC-x e

Useful Packages and Modes

Emacs can be extended with packages. These two are easy to install and immediately useful:

PackageWhat it does
FlyspellOn-the-fly spell checking as you type, similar to spell check in word processors
X-SymbolRenders superscript, subscript and Greek characters visually in LaTeX buffers

Modern Emacs (26+) ships with a built-in package manager. To browse and install packages: M-x package-list-packages. For LaTeX grammar checking, convert your document to HTML first and use an online grammar checker, as LaTeX-native grammar tools are limited.

For the complete built-in reference, use C-h k (describe key) or C-h f (describe function) at any time within Emacs. The official manual is available at gnu.org/software/emacs/manual.

Quick Guide to CVS

Quick Reference Guide

Quick Guide to CVS

A practical reference for setting up and using the Concurrent Versions System (CVS). Commands were originally tested on CVS 1.10. Covers setup, import, checkout, commit, branching, tags, and remote repositories.

Note: This guide was originally published in 2006 and has been updated in May 2026 with additional sections and improved formatting, with assistance from Claude (Anthropic).

CVS is a legacy tool. For new projects, Git is strongly recommended. This guide is useful for working with existing CVS repositories.

Setup

Set the CVSROOT environment variable to point to your repository directory, then initialise it:

setenv CVSROOT ~/cvsroot   # csh / tcsh
export CVSROOT=~/cvsroot   # bash
cvs init                   # creates the repository structure

For remote repositories, CVSROOT takes the form :pserver:user@host:/path/to/repo. See the Remote Repositories section below.

Core Workflow

The typical day-to-day CVS cycle for a developer:

StepCommandWhat it does
1. Get latestcvs updatePull changes from the repository into your working copy
2. Edit filesyour editorMake your changes locally
3. Reviewcvs diffSee what you have changed before committing
4. Commitcvs commit -m "message"Save your changes back to the repository

Importing a Project

To place an existing directory of files under CVS control, cd into the project directory and run:

cd ~/project
cvs import -m "Initial import" myproject vendor start
ArgumentMeaning
myprojectRepository name — use this name in future checkout commands
vendorVendor tag — can be any label (e.g. your username or organisation)
startRelease tag — marks this as the initial release

Checking Out a Project

Checkout creates a working copy of the repository in your current directory:

cvs checkout myproject          # full checkout
cvs checkout -r v1.2 myproject  # checkout a specific tag
cvs co myproject                # shorthand

This creates a myproject/ directory. CVS metadata is stored in CVS/ subdirectories — do not delete or edit these.

Updating Your Working Copy

Run cvs update from inside your working copy to pull changes committed by others:

cvs update          # update all files in current directory
cvs update -d       # also create any new directories added to repo
cvs update file.c   # update a single file

Status codes in the output:

CodeMeaning
UFile updated from repository
MFile modified locally (your changes)
CConflict — your changes clash with someone else’s; must be resolved manually
?File exists locally but is not tracked by CVS

Committing Changes

After editing files, commit them back to the repository:

cvs commit -m "Fix off-by-one error in solver"   # commit all changed files
cvs commit -m "Update README" README.md          # commit a specific file

If you omit -m, CVS opens an editor for your log message. To change which editor is used:

setenv EDITOR emacs   # or vim, nano, etc.

Adding and Removing Files

Adding or removing a file is a two-step process: stage the change with add/remove, then make it permanent with commit:

# Add a new file
cvs add newfile.c
cvs commit -m "Add newfile.c"

# Remove a file (delete it first, then remove from CVS)
rm oldfile.c
cvs remove oldfile.c
cvs commit -m "Remove oldfile.c"

# Add a binary file (prevents line-ending conversion)
cvs add -kb image.png

To add an entire new directory: cvs add dirname followed by cvs add dirname/* and then commit.

Status and Diff

cvs status            # show status of all files in working copy
cvs status file.c     # status of a specific file
cvs diff              # show all local changes as a unified diff
cvs diff -u file.c    # unified diff for one file
cvs diff -r 1.3 -r 1.5 file.c  # diff between two specific revisions

Always run cvs diff before committing to review exactly what will be saved.

Log and History

cvs log               # full commit history for all files
cvs log file.c        # history for a specific file
cvs log -r 1.3 file.c # log entry for revision 1.3 only
cvs log -d "2006-01-01<2006-06-01" file.c  # log within a date range

CVS uses dotted revision numbers (e.g. 1.1, 1.2, …) per file. Branch revisions use additional components (e.g. 1.2.2.1).

Tags and Branches

Tags

A tag marks the current state of all files with a symbolic name, useful for marking releases:

cvs tag v1_0_release       # tag the current working copy state
cvs rtag v1_0_release myproject  # tag directly in the repository

Branches

Branches allow parallel lines of development, e.g. a maintenance branch alongside active development:

# Create a branch
cvs tag -b MAINTENANCE_1_0

# Switch your working copy to that branch
cvs update -r MAINTENANCE_1_0

# Switch back to the main trunk
cvs update -A

Changes committed on a branch do not affect the main trunk. Merging branch changes back uses cvs update -j BRANCH_TAG.

Remote Repositories (pserver)

CVS can connect to a remote server over its own pserver protocol. Set CVSROOT to the remote path and log in once:

setenv CVSROOT :pserver:[email protected]:/srv/cvsroot
cvs login                          # prompts for password; stored in ~/.cvspass
cvs checkout myproject
cvs logout                         # when done

SSH-tunnelled access is more secure for production use: set CVSROOT to :ext:username@host:/path and CVS_RSH=ssh.

Quick Command Reference

CommandWhat it does
cvs initInitialise a new repository
cvs importImport a directory into CVS for the first time
cvs checkoutGet a working copy from the repository
cvs updatePull latest changes from the repository
cvs commitSave local changes to the repository
cvs addSchedule a new file for addition (follow with commit)
cvs removeSchedule a file for removal (follow with commit)
cvs statusShow the status of files in the working copy
cvs diffShow differences between local and repository versions
cvs logShow commit history and revision log
cvs tagApply a symbolic tag to the current state
cvs tag -bCreate a branch tag

For a more comprehensive tutorial, see this CVS guide. For new projects, the Quick Guide to Git is a better starting point.