Rechenwerk · Fundstücke · 2. Juli 2026

Retro-Notizen — die C64-Wissensbasis im Überblick

Dies ist der öffentliche Spaziergang durch die kuratierte Wissensbasis des wintermute-c64-Projekts — das Wissen, mit dem der Agent Dope arbeitet, kondensiert für Menschen. Alles hier ist in VICE verifiziert oder an dokumentierte Quellen rückgebunden; wo öffentliche Referenzen existieren, sind sie verlinkt.

Prozessor: 6510 & Opcodes

Adressierungsarten und Opcodes

Der 6510 im C64 ist für alle dokumentierten Opcodes 6502-kompatibel und ergänzt den CPU-I/O-Port bei $00/$01. Seine 13 Adressierungsarten unterscheiden sich vor allem in einem: was sie kosten.

Zyklenkosten der Adressierungsarten

An den Lücken der Befehlsmatrix verhebt sich generierter wie handgeschriebener Code gleichermaßen gern:

  • STA kennt kein Immediate, STX kein absolute,Y, STY kein absolute,X
  • BIT gibt es nur Zero Page und Absolute
  • Read-Modify-Write-Befehle (INC, ASL, …) haben kein Immediate

Dazu zwei NMOS-Fallen mit Tradition: Zero-Page-Indizierung wickelt modulo 256 (lda $80,x mit X=$FF liest $007F, nicht $017F) — und jmp ($xxFF) holt das High-Byte fälschlich von $xx00. Indirekte Vektoren also nie auf ein Seitenende legen.

Quellen: Oxyron-Opcode-Matrix · c64os.com · pagetable c64ref

Speicher & Banking

Memory Map und Zero Page

Der 6510 sieht 64 KB — aber ROM und I/O liegen als schaltbare Schichten über dem RAM. Die goldene Regel: Schreibzugriffe treffen immer das RAM darunter, nur Lesezugriffe sehen das eingeblendete Gerät.

Die C64-Speicherkarte mit Banking-Schichten

Wer unter laufendem BASIC/KERNAL eigene Routinen schreibt, hat erstaunlich wenig garantiert freien Platz:

  • Zero Page: offiziell nur $FB–$FE (vier Bytes!)
  • $0334–$033B und der 192-Byte-Kassettenpuffer $033C–$03FB (solange kein Tape-I/O läuft)
  • der klassische 4-KB-Block $C000–$CFFF

Quelle: pagetable.com/c64ref/c64mem

VIC-II: der Grafikchip

Die Register-Referenz

Die 47 VIC-II-Register liegen bei $D000–$D02E. Das Steuerzentrum bilden zwei Register, deren Bits man irgendwann auswendig kennt:

Bitbelegung von $D011 und $D016

Dazu die Eckdaten, auf denen alles Weitere aufbaut:

  • $D018 wählt Video-Matrix (1-KB-Schritte) und Zeichensatz (2-KB-Schritte) innerhalb der aktiven 16-KB-VIC-Bank; die Bank selbst schaltet CIA 2 ($DD00)
  • Raster-IRQs: aktivieren über $D01A Bit 0, quittieren durch Schreiben von $01 nach $D019
  • PAL: 312 Rasterzeilen à 63 Zyklen
  • Badline: wenn im sichtbaren Bereich (Rasterzeile & 7) == YSCROLL gilt, stoppt der VIC die CPU für rund 40 Zyklen, um Zeichendaten zu holen

Sprites

Acht Hardware-Sprites à 24×21 Pixel. Ihre Daten (63 Bytes + 1 Füllbyte) liegen auf 64-Byte-Grenzen, adressiert über Pointer, die keine Register sind, sondern die letzten 8 Bytes der Video-Matrix:

Sprite-Datenlayout und Pointer-Mechanik

Die drei Regeln, die man nicht in Registerlisten findet:

  • Die Kollisionslatches $D01E (Sprite–Sprite) und $D01F (Sprite–Grafik) löschen sich beim Lesen — einmal lesen, Ergebnis speichern
  • Multicolor ($D01C) halbiert die Auflösung auf 12 Doppelpixel: 00 = transparent, 01/11 = gemeinsame Farben $D025/$D026, 10 = Einzelfarbe
  • Multiplexing geht vertikal (Sprite nach Displayende wiederverwenden), aber nie horizontal in derselben Rasterzeile — das Schieberegister wird nicht neu gefüllt

Bitmap-Modi

Hires-Bitmap ($D011 Bit 5) liefert 320×200 Pixel in 8.000 Bytes; Multicolor (zusätzlich $D016 Bit 4) tauscht die halbe horizontale Auflösung gegen vier Farbquellen pro Zelle:

Hires- und Multicolor-Bitmap im Vergleich

Das Referenz-Layout des Projekts: VIC-Bank 0, Screen $0400, Bitmap $2000, $D018 = $18.

Visuelle Grundlagen

Ein „A", vier Welten

Die häufigste Fehlerquelle bei C64-Textausgabe ist keine Technik, sondern eine Verwechslung — dasselbe Zeichen existiert in vier Kodierungen:

ASCII, PETSCII, Screen-Code und Glyph im Vergleich

Dazu das Drumherum:

  • Der Textbildschirm ist 40×25, Offset = Zeile × 40 + Spalte
  • Das parallele Farb-RAM $D800 speichert nur das Low-Nibble — niemals Flags im High-Nibble ablegen
  • Eigene Zeichensätze gehören auf 2-KB-Grenzen der VIC-Bank (Screen $0400 + Charset $3000$D018 = $1C)
  • Die 16 VIC-Farben haben keine lineare Helligkeitsordnung — Farbrampen (Feuer: $00 $09 $02 $08 $0A $07 $01) lebt man als Tabellen aus

Quellen: c64ref/charset · c64ref/colors

SID: der Soundchip

Die SID-Referenz

Drei Stimmen, ein Filter, ein Lautstärkeregler — der ganze Chip in einem Bild:

SID-Signalfluss von den Oszillatoren zum Ausgang

Die Regeln, die beim ersten eigenen Player Nerven sparen:

  • ADSR und Frequenz vor dem GATE-Bit setzen; GATE löschen startet die Release-Phase
  • Fast alles ist write-only — lesbar sind nur Paddles, OSC3 und ENV3 ($D419–$D41C)
  • Musik-Player folgen der Konvention init = $1000, play = $1003, einmal pro Frame aus dem IRQ
  • 6581 und 8580 klingen beim Filter und bei $D418-Volume-Digis deutlich verschieden

Quellen: Oxyron SID-Register · C64-Wiki · Codebase64

Von der Note zum Registerwert

SID-Frequenzformel mit Beispielwerten

In der Praxis lebt das als vorberechnete Lo/Hi-Tabelle im Quelltext, indiziert über die Notennummer. Unterhalb von C-1 werden die Registerschritte hörbar grob; oben deckelt $FFFF bei B-7.

Demo-Techniken

Das Herzstück der Wissensbasis — hier steckt das meiste gemessene Wissen.

IRQ-Grundlagen

Der C64 kennt zwei IRQ-Routing-Modelle, und sie zu mischen ist der Klassiker unter den Anfängerfehlern:

Die zwei IRQ-Routing-Modelle des C64

Für Demo-Code ist der direkte Vektor mit Banking $01 = $35 die erste Wahl — das Timing bleibt explizit. Und nicht vergessen: sei maskiert nur IRQs, keine NMIs. Die RESTORE-Taste läuft über $FFFA/$FFFB und muss in timing-kritischen Produktionen separat gezähmt werden.

Stabile Raster-IRQs

Jeder naive Raster-IRQ jittert um einige Zyklen, weil die CPU ihre laufende Instruktion erst beendet — sichtbar als zitternde Balkenkante. Die Demoszene-Antwort ist der Double-IRQ-Stabilizer:

Der Double-IRQ-Stabilizer auf der Zeitachse

Einmal pro IRQ-Kette stabilisieren genügt, solange danach jeder Pfad feste Zyklenzahl hat. Und ein hübsch obskures Messergebnis aus dem Projekt: Ein $D021-Write auf einer Badline erzeugt ein Ein-Pixel-Artefakt — die Rasterbar-Farbtabelle dupliziert dort schlicht die Vorzeile.

CIA-Timer-IRQs

Die zweite Interrupt-Quelle des C64 — mit einer Quittierungs-Asymmetrie, die immer wieder Bugs produziert:

VIC-Ack durch Schreiben, CIA-Ack durch Lesen

Cycle-Budget-Planung

Timing plant man rückwärts: Ziel-Rasterzeile → Fixpunkte → Overhead → Trigger-Zeile. Das Budget dafür ist endlich, und der VIC nimmt sich seinen Teil zuerst:

Das PAL-Frame-Budget und seine Abzüge

Die Fixpunkte im Kopf:

  • IRQ-Latenz des 6510: 7–14 Zyklen
  • Ein stabilisierter Handler verbraucht mit Save/Restore schnell eine ganze Rasterzeile
  • sta abs,x kostet immer 5 Zyklen (kein Page-Cross-Rabatt), Branches über Seitengrenzen +1 — zeitkritische Tabellen deshalb per !align auf Seitenanfänge legen

Effekte kombinieren

Rasterbar, Scroller, Musik und Logo teilen sich einen Frame über eine kaskadierende IRQ-Kette — nicht über je einen eigenen Interrupt:

Eine IRQ-Kette choreografiert den ganzen Frame

Stabilisiert wird nur einmal oben im Frame; die Folge-Splits erben das Timing. Musik gehört als fester Posten in einen unkritischen Split — nicht in einen freilaufenden CIA-IRQ, der den Stabilizer mitten in der Korrektur unterbrechen kann.

Scroller

Ein pixelglatter Textscroller ist ein Zwei-Phasen-Uhrwerk:

Fine-Scroll und Coarse-Wrap im Zusammenspiel

Wer eigene Zeichensätze will, kopiert das ROM-Charset mit dem Banking-Trick $01 = $33 (Zeichen-ROM sichtbar, I/O weg) nach RAM. Und der Klassiker unter den Fehlbildern: lda #$08 / sta $D016 jeden Frame ist kein Scrolling — das ist nur der 40-Spalten-Modus mit X-Scroll 0.

Sprite-Multiplexing

Mehr als acht Sprites heißt: Hardware-Sprites nach ihrem Displayende im selben Frame wiederverwenden — mit Y-Sortierung und einem IRQ-Fahrplan:

Y-sortierte Segmente und die fire_line-Regel

Ein gemessenes Detail mit Praxiswert: Rasterzeile 251 ist kein sicherer VBlank-Punkt für die Plan-Übergabe — ein Sprite bei Y = $EA wird dort noch angezeigt. Sicher ist Zeile 0.

FLD & FLI

Beide Techniken manipulieren den Zeichenzeilen-Zyklus des VIC-II — die eine dehnt das Bild, die andere vervielfacht die Farben:

FLD schiebt Zeilen, FLI wechselt Matrizen

Der Preis von FLI ist die berüchtigte Bug-Spalte am linken Rand, die man mit Sprites oder Artwork versteckt. Die maschinensensitiven Verwandten VSP/AGSP bleiben im Projekt bewusst außen vor — Kompatibilitätsrisiko auf echter Hardware.

Die Systematik der Visual-Math-Effekte

Vor jedem Effekt stehen dieselben vier Fragen:

  1. Wohin schreiben? Screen-RAM, Farb-RAM, Bitmap oder Sprites
  2. Welche Tabelle treibt? Farbrampe, Sinustabelle, LFSR, Heat-Buffer
  3. Was taktet? VBlank-Poll, Raster-IRQ oder CIA-Timer
  4. PAL oder NTSC?

Das kleinste Beispiel ist Color-Cycling (Phasenzähler plus Farbtabelle auf $D020/$D021); das größte sind volle 40×25-Updates mit 1.000 Stores pro Frame, die ohne Speedcode kein Frame-Budget der Welt hergibt.

Plasma & Speedcode

Plasma ist Tabellen-Mixing — und das beste Anschauungsbeispiel dafür, warum Speedcode existiert:

Die Plasma-Pipeline und der Zyklen-Vergleich

Die Speedcode-Variante cached 16 Achsenwerte pro Frame und lässt den Assembler feste STA abs-Ketten generieren: ~3,7 KB Code statt einer Schleife, dafür viermal schneller. Dazu die eisernen Regeln für selbstmodifizierenden Code: nur Operanden patchen, nie Opcodes — und nie patchen, während ein IRQ die Routine ausführen könnte.

Starfields

Sternenhimmel gibt es in drei Preisklassen:

  • Screen-RAM-Sterne — Dutzende Punkte in Zeichenauflösung, fast gratis
  • Sprite-Sterne — pixelgenau, aber maximal acht (und Sprite-DMA stiehlt Buszyklen)
  • Bitmap-Sterne — radiale Perspektive à la C=Hacking #16: x' = x + dx/Tiefe in Fixed-Point

Der schönste Trick der Notiz: Ein animiertes Charset-Sternfeld rotiert einfach vier Zeichensatz-Pages per $D018 durch ($18/$1A/$1C/$1E) — kostet 8 KB RAM und fast keine CPU. Als Zufallsquelle dient ein 8-Bit-LFSR mit XOR-Maske $B8, und die Tiefen-Helligkeit wählt man explizit ($0B $0C $0F $01), denn VIC-Farbnummern sind keine Helligkeitsskala.

Feuer & Farbrampen

Das klassische Feuer ist ein Heat-Buffer mit Faltung — die Update-Reihenfolge ist dabei Teil der Physik:

Heat-Buffer, Faltungskernel und Farbrampe

Die Projekt-Messung: 220 Zellen Simulation plus 960 Farb-RAM-Stores ≈ 12.500–13.000 Zyklen — passt in einen PAL-Frame. Die Abkühlung läuft über eine branchlose Cooling-Tabelle, die den Underflow $00 → $FF verhindert.

Sinus-Tabellen

Der 6510 rechnet nie zur Laufzeit sin() — der Assembler tut es zur Assemblierzeit:

Die 256er-Sinustabelle und ihre Kardinalpunkte

Geschwindigkeit ist schlicht das Phaseninkrement (+1 sanft, +3 flott), und zwei Zähler mit verschiedenen Inkrementen ergeben die typischen gekoppelten Pendelbewegungen.

Twister, Rotatoren, Waving Carpets

Deformationen rotieren nichts zur Laufzeit — sie mappen jede Zeile durch vorberechnete Tabellen:

Der Twister als drei Tabellen-Lookups pro Zeile

Rasterline-Deformationen schreiben stattdessen getimte VIC-Register ($D016 für horizontale Wellen, $D011 vertikal, $D020/$D021 für reine Farbtiefe) — und brauchen dann die volle Stabilizer-Disziplin. Beim X-Rotator gilt: vorgeschobene Glyphs im Zeichensatz sind billiger als Pixelrotation.

Vektor-Grundlagen

Das Fundament aller Vektor-Effekte ist die Pixel-Adressrechnung im Hires-Bitmap:

Die Bitmap-Adressformel, visuell zerlegt

Darauf bauen die Klassiker auf: Bresenham-Linien ohne Multiplikation (Fehlerterm halbieren, pro Schritt addieren/subtrahieren), der Midpoint-Kreis mit einem Oktanten achtfach gespiegelt, und die 3D-Pipeline mit signiertem Fixed-Point, Sinustabellen und der Projektion screen_x = cx + x·scale/z. Die Grundhaltung überall: RAM gegen Rechenzeit tauschen, wo immer eine Tabelle passt.

Das C=Hacking-Archiv

Die Effekt-Notizen sind systematisch im C=Hacking-Magazin geerdet — dem technischen Fachblatt der Szene (1992–2002). Die Landkarte für Einsteiger:

  • Timing: Issue 3 „Missing Cycles", Issue 10 „Making stable raster routines"
  • Ränder öffnen: Issue 6 „Opening the Borders"
  • Display-Tricks: Issues 4/9/10 zu FLI, AFLI und BFLI
  • 3D: Issues 8–12, die Serie „A Different Perspective"
  • Sound: Issue 20 „The C64 Digi" über $D418-Sample-Playback

Diskette & Speicherung

1541 & D64

Ein D64 ist das sektorweise Abbild einer 1541-Diskette — und Track 18 ist ihr Nervensystem:

D64-Zonenlayout mit Directory-Track 18

Dateien sind Track/Sektor-Ketten: Die ersten zwei Bytes jedes Sektors zeigen auf den nächsten, 254 Nutzbytes bleiben. Und die 1541 selbst ist ein vollwertiger Computer mit eigener 6502-CPU und 2 KB RAM — die Grundlage aller Fastloader, die das lahme serielle IEC-Protokoll durch eigenen Code im Laufwerk ersetzen. Praktisch baut man D64s heute mit c1541 aus dem VICE-Paket.

Toolchain

Packing & Crunching

Auf dem C64 wird fast nichts unkomprimiert ausgeliefert. Die goldene Reihenfolge dabei:

Die Build-Pipeline: bauen, testen, crunchen, nochmal testen

Exomizer erzeugt mit sfx sys selbststartende PRGs (-n schaltet den Decrunch-Effekt ab — gut für deterministische Tests); Pucrunch ist der LZ77/RLE-Klassiker mit eingebettetem Entpacker.

Der kanonische BASIC-Start

Jedes ACME-Projekt beginnt mit demselben Ritual bei * = $0801 — einem BASIC-Einzeiler als Bytes:

Byte-Layout des BASIC-Starters

Der häufigste Stolperstein steckt mittendrin: Das SYS-Argument ist Dezimaltext, kein Binärwert. Die PRG-Ladeadresse selbst steht nie im Quelltext — sie kommt von -f cbm beim Assemblieren.


Alle Angaben stammen aus der kuratierten, quellen-rückgebundenen Wissensbasis von wintermute-c64 — jede Notiz dort dokumentiert Herkunft, Lizenz und Vertrauensstufe ihrer Quellen, und die Timing-Aussagen sind in VICE (x64sc) gemessen. Wie diese Wissensbasis entstand, steht im Projektartikel; die übergreifende Methodik — jede Behauptung hat eine Fundstelle — kennt ihr aus der Denkmaschinen-Serie.