<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Programming the Atari VCS in Assembly</title><link>https://cdeever.github.io/atari-vcs/</link><description>Recent content on Programming the Atari VCS in Assembly</description><generator>Hugo</generator><language>en-us</language><atom:link href="https://cdeever.github.io/atari-vcs/index.xml" rel="self" type="application/rss+xml"/><item><title>Introduction</title><link>https://cdeever.github.io/atari-vcs/docs/introduction/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/introduction/</guid><description>&lt;h1 id="introduction"&gt;Introduction&lt;a class="anchor" href="#introduction"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;If you arrive here from modern software development, much of your hard-won instinct will work &lt;em&gt;against&lt;/em&gt; you. The things a career is built on — rich standard libraries, layers of hardware abstraction, portable code that runs anywhere — none of it exists on the VCS. There is no operating system to call, no driver sitting between you and the silicon, and nothing you write will run on any machine but this one. As a certain Jedi master would put it:&lt;/p&gt;</description></item><item><title>Pong (a minimal teardown)</title><link>https://cdeever.github.io/atari-vcs/docs/game-analysis/pong/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/game-analysis/pong/</guid><description>&lt;h1 id="pong-a-minimal-teardown"&gt;Pong (a minimal teardown)&lt;a class="anchor" href="#pong-a-minimal-teardown"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Where &lt;a href="https://cdeever.github.io/atari-vcs/docs/game-analysis/combat/"&gt;Combat&lt;/a&gt; and &lt;a href="https://cdeever.github.io/atari-vcs/docs/game-analysis/pitfall/"&gt;Pitfall!&lt;/a&gt; are feats of &lt;em&gt;compression&lt;/em&gt; — huge games squeezed into tiny ROMs — this Pong is the opposite lesson: the &lt;strong&gt;irreducible minimum&lt;/strong&gt;, the smallest thing that is still a complete VCS game. It&amp;rsquo;s a clean, modern implementation by &lt;strong&gt;Lucas Avanço&lt;/strong&gt;, built on Kirk Israel&amp;rsquo;s &amp;ldquo;thin red line&amp;rdquo; tutorial and the Stella Programmer&amp;rsquo;s Guide — not Atari&amp;rsquo;s 1977 cartridge, but all the better for reading, because there&amp;rsquo;s nothing in it that isn&amp;rsquo;t essential.&lt;/p&gt;</description></item><item><title>Combat (1977)</title><link>https://cdeever.github.io/atari-vcs/docs/game-analysis/combat/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/game-analysis/combat/</guid><description>&lt;h1 id="combat-1977"&gt;Combat (1977)&lt;a class="anchor" href="#combat-1977"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;Combat&lt;/em&gt; shipped in the box with the original console — for millions of people it &lt;em&gt;was&lt;/em&gt; the Atari. Written by &lt;strong&gt;Larry Wagner&lt;/strong&gt; with hardware help from &lt;strong&gt;Joe DeCuir&lt;/strong&gt;, it packs &lt;strong&gt;27 game variations&lt;/strong&gt; (tanks, tank-pong, invisible tanks, biplanes, jets) into a &lt;strong&gt;2 KB&lt;/strong&gt; ROM. It&amp;rsquo;s also one of the most thoroughly annotated programs in 2600 history: the commented disassembly this teardown follows runs from Harry Dodgson&amp;rsquo;s original through Nick Bensema&amp;rsquo;s notes (1997) to Roger Williams&amp;rsquo; full overhaul (2002).&lt;/p&gt;</description></item><item><title>Cosmic Ark's Star Field</title><link>https://cdeever.github.io/atari-vcs/docs/hardware-quirks/cosmic-ark-starfield/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/hardware-quirks/cosmic-ark-starfield/</guid><description>&lt;h1 id="cosmic-arks-star-field"&gt;Cosmic Ark&amp;rsquo;s Star Field&lt;a class="anchor" href="#cosmic-arks-star-field"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Imagic&amp;rsquo;s &lt;em&gt;Cosmic Ark&lt;/em&gt; (1982) opens with a starfield so clean it looks impossible on a machine that can show &lt;a href="https://cdeever.github.io/atari-vcs/docs/sprites/"&gt;two sprites and a ball&lt;/a&gt;. Crisp white stars, evenly spaced, drifting smoothly — far more points of light than the TIA has objects to draw them with. The secret is the most celebrated &lt;strong&gt;bug&lt;/strong&gt; in Atari history.&lt;/p&gt;
&lt;h2 id="a-glitch-nobody-ordered"&gt;A glitch nobody ordered&lt;a class="anchor" href="#a-glitch-nobody-ordered"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The effect is a single &lt;strong&gt;missile&lt;/strong&gt; misbehaving. As &lt;a href="https://cdeever.github.io/atari-vcs/docs/sprites/horizontal-positioning/"&gt;Horizontal Positioning&lt;/a&gt; explained, an object&amp;rsquo;s position is retimed by strobing &lt;code&gt;HMOVE&lt;/code&gt; — and that retiming is delicate, built on the TIA&amp;rsquo;s and CPU&amp;rsquo;s clocks lining up just so. Strobe &lt;code&gt;HMOVE&lt;/code&gt; &lt;em&gt;the wrong way&lt;/em&gt; — at the wrong point in the line, or an extra time — and the missile&amp;rsquo;s position logic comes unglued: instead of moving once, the missile gets redrawn again and again across the scanline, scattering a row of evenly-spaced dots. Point that at the screen every frame and you have a starfield, conjured from one object the TIA never meant to clone.&lt;/p&gt;</description></item><item><title>Counting Cycles</title><link>https://cdeever.github.io/atari-vcs/docs/kernel-techniques/counting-cycles/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/kernel-techniques/counting-cycles/</guid><description>&lt;h1 id="counting-cycles"&gt;Counting Cycles&lt;a class="anchor" href="#counting-cycles"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Every other platform lets you write code and measure it later. On the VCS you must know the cost &lt;em&gt;before&lt;/em&gt; you run it, because a &lt;a href="https://cdeever.github.io/atari-vcs/docs/6502-basics/cycles-and-timing/"&gt;visible scanline is 76 CPU cycles&lt;/a&gt; and there is no &amp;ldquo;a little slow&amp;rdquo; — a kernel line that needs 77 doesn&amp;rsquo;t lag, it corrupts the picture. Counting cycles is the habit that makes everything else in this chapter possible.&lt;/p&gt;
&lt;h2 id="budget-from-wsync-to-wsync"&gt;Budget from WSYNC to WSYNC&lt;a class="anchor" href="#budget-from-wsync-to-wsync"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A kernel is a loop, and the unit you budget is &lt;strong&gt;one pass: the cycles between one &lt;code&gt;STA WSYNC&lt;/code&gt; and the next.&lt;/strong&gt; Add up the cost of every instruction in that span — using the &lt;a href="https://cdeever.github.io/atari-vcs/docs/6502-basics/cycles-and-timing/"&gt;per-instruction costs&lt;/a&gt; — and confirm the total fits under 76 (minus whatever the visible drawing already spends).&lt;/p&gt;</description></item><item><title>Drawing a Player</title><link>https://cdeever.github.io/atari-vcs/docs/sprites/drawing-a-player/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/sprites/drawing-a-player/</guid><description>&lt;h1 id="drawing-a-player"&gt;Drawing a Player&lt;a class="anchor" href="#drawing-a-player"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The two &lt;strong&gt;players&lt;/strong&gt; (P0 and P1) are the TIA&amp;rsquo;s real sprites: 8-pixel-wide bitmaps you can move anywhere and color independently. A player is how you draw the tank, the spaceship, the character. Drawing one is, like everything on the VCS, a matter of feeding the right register at the right scanline.&lt;/p&gt;
&lt;h2 id="one-byte-one-row"&gt;One byte, one row&lt;a class="anchor" href="#one-byte-one-row"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A player&amp;rsquo;s shape lives in a single register — &lt;code&gt;GRP0&lt;/code&gt; for player 0, &lt;code&gt;GRP1&lt;/code&gt; for player 1. Its &lt;strong&gt;8 bits are 8 pixels&lt;/strong&gt;: a &lt;code&gt;1&lt;/code&gt; lights a pixel in the player&amp;rsquo;s color (&lt;a href="https://cdeever.github.io/atari-vcs/docs/tia-racing-the-beam/color/"&gt;&lt;code&gt;COLUP0&lt;/code&gt; / &lt;code&gt;COLUP1&lt;/code&gt;&lt;/a&gt;), a &lt;code&gt;0&lt;/code&gt; is transparent. But a register holds only &lt;em&gt;one row&lt;/em&gt;, so — exactly like the &lt;a href="https://cdeever.github.io/atari-vcs/docs/playfield/symmetry/"&gt;playfield kernel&lt;/a&gt; — you rewrite &lt;code&gt;GRP0&lt;/code&gt; on each scanline the sprite occupies, walking down a bitmap table:&lt;/p&gt;</description></item><item><title>How a Television Works</title><link>https://cdeever.github.io/atari-vcs/docs/prerequisites/how-the-tv-works/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/prerequisites/how-the-tv-works/</guid><description>&lt;h1 id="how-a-television-works"&gt;How a Television Works&lt;a class="anchor" href="#how-a-television-works"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Before the VCS makes sense, the &lt;em&gt;television&lt;/em&gt; has to. Every concept in this book — the frame loop, sync signals, &amp;ldquo;Racing the Beam,&amp;rdquo; the cycle budget — is a direct consequence of how a cathode-ray-tube TV paints a picture. You don&amp;rsquo;t need a broadcast-engineering course; you need the handful of facts the hardware forces you to care about.&lt;/p&gt;
&lt;h2 id="the-beam-paints-one-line-at-a-time"&gt;The beam paints one line at a time&lt;a class="anchor" href="#the-beam-paints-one-line-at-a-time"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A CRT television draws its image with a single &lt;strong&gt;electron beam&lt;/strong&gt; that sweeps across the screen from behind. It moves in a fixed pattern:&lt;/p&gt;</description></item><item><title>Programming Across Banks</title><link>https://cdeever.github.io/atari-vcs/docs/cartridge-hardware/bankswitching/programming-across-banks/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/cartridge-hardware/bankswitching/programming-across-banks/</guid><description>&lt;h1 id="programming-across-banks"&gt;Programming Across Banks&lt;a class="anchor" href="#programming-across-banks"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://cdeever.github.io/atari-vcs/docs/cartridge-hardware/bankswitching/"&gt;Bankswitching&lt;/a&gt; hands you the hardware: several 4 KB banks and a few hotspot addresses that swap which one the &lt;a href="https://cdeever.github.io/atari-vcs/docs/architecture/rom/"&gt;window&lt;/a&gt; shows. That much is simple. The hard part is &lt;em&gt;living&lt;/em&gt; there — writing code that keeps working while the bytes underneath it change. Because the swap is a silent side effect of touching an address, the program counter doesn&amp;rsquo;t move when a bank flips; only the contents under it do. Two facts follow, and both shape how you lay out a banked game.&lt;/p&gt;</description></item><item><title>Registers &amp; Status Flags</title><link>https://cdeever.github.io/atari-vcs/docs/6502-basics/registers/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/6502-basics/registers/</guid><description>&lt;h1 id="registers--status-flags"&gt;Registers &amp;amp; Status Flags&lt;a class="anchor" href="#registers--status-flags"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The 6502 has astonishingly few places to keep data — &lt;strong&gt;three 8-bit working registers&lt;/strong&gt;, and that scarcity shapes how every program is written. You can&amp;rsquo;t spread work across a bank of registers the way you would on a bigger CPU; values are constantly shuttled between these three and &lt;a href="https://cdeever.github.io/atari-vcs/docs/prerequisites/memory-mapped/"&gt;memory&lt;/a&gt;.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Register&lt;/th&gt;
 &lt;th&gt;Width&lt;/th&gt;
 &lt;th&gt;Role&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;A&lt;/strong&gt; (accumulator)&lt;/td&gt;
 &lt;td&gt;8-bit&lt;/td&gt;
 &lt;td&gt;The workhorse. The &lt;em&gt;only&lt;/em&gt; register that does arithmetic and logic (&lt;code&gt;ADC&lt;/code&gt;, &lt;code&gt;SBC&lt;/code&gt;, &lt;code&gt;AND&lt;/code&gt;, &lt;code&gt;ORA&lt;/code&gt;, &lt;code&gt;EOR&lt;/code&gt;). Almost all data flows through it.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;X&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;8-bit&lt;/td&gt;
 &lt;td&gt;Index/counter. Used to offset addresses (&lt;code&gt;LDA table,X&lt;/code&gt;) and to count loops. Also the bridge to the stack pointer (&lt;code&gt;TXS&lt;/code&gt;/&lt;code&gt;TSX&lt;/code&gt;).&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Y&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;8-bit&lt;/td&gt;
 &lt;td&gt;The other index/counter. Similar to X, with its own indexed modes.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;S&lt;/strong&gt; (stack pointer)&lt;/td&gt;
 &lt;td&gt;8-bit&lt;/td&gt;
 &lt;td&gt;Points at the top of the &lt;a href="https://cdeever.github.io/atari-vcs/docs/6502-basics/stack-and-subroutines/"&gt;stack&lt;/a&gt;.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;PC&lt;/strong&gt; (program counter)&lt;/td&gt;
 &lt;td&gt;16-bit&lt;/td&gt;
 &lt;td&gt;Address of the next instruction to execute.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;P&lt;/strong&gt; (status)&lt;/td&gt;
 &lt;td&gt;8-bit&lt;/td&gt;
 &lt;td&gt;The processor flags — see below.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A, X, and Y are &lt;em&gt;not&lt;/em&gt; interchangeable: only A computes, only X and Y index, and each has instructions the others lack. Choosing which value lives in which register is a real part of writing tight 6502 code.&lt;/p&gt;</description></item><item><title>The Audio Registers</title><link>https://cdeever.github.io/atari-vcs/docs/sound/the-audio-registers/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/sound/the-audio-registers/</guid><description>&lt;h1 id="the-audio-registers"&gt;The Audio Registers&lt;a class="anchor" href="#the-audio-registers"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The TIA gives you &lt;strong&gt;two independent audio channels&lt;/strong&gt;, and that&amp;rsquo;s the whole orchestra — two voices, no more. Each channel is described by exactly &lt;strong&gt;three registers&lt;/strong&gt;, and a sound is whatever you get by setting them and changing them over time.&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Register&lt;/th&gt;
 &lt;th&gt;Width&lt;/th&gt;
 &lt;th&gt;Sets&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;&lt;code&gt;AUDC0&lt;/code&gt; / &lt;code&gt;AUDC1&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;4 bits&lt;/td&gt;
 &lt;td&gt;the &lt;strong&gt;waveform&lt;/strong&gt; — which tone or noise shape this channel makes&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;&lt;code&gt;AUDF0&lt;/code&gt; / &lt;code&gt;AUDF1&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;5 bits&lt;/td&gt;
 &lt;td&gt;the &lt;strong&gt;frequency&lt;/strong&gt; — a divisor, so 32 steps, higher value = lower pitch&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;&lt;code&gt;AUDV0&lt;/code&gt; / &lt;code&gt;AUDV1&lt;/code&gt;&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;4 bits&lt;/td&gt;
 &lt;td&gt;the &lt;strong&gt;volume&lt;/strong&gt; — 0 (silent) to 15 (loudest)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The three combine in a fixed signal path: &lt;code&gt;AUDC&lt;/code&gt; and &lt;code&gt;AUDF&lt;/code&gt; feed a tone/noise generator, whose output is scaled by &lt;code&gt;AUDV&lt;/code&gt;, and the two channels mix to the single output:&lt;/p&gt;</description></item><item><title>The Blue Box, Reborn</title><link>https://cdeever.github.io/atari-vcs/docs/appendix/the-blue-box-reborn/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/appendix/the-blue-box-reborn/</guid><description>&lt;h1 id="the-blue-box-reborn"&gt;The Blue Box, Reborn&lt;a class="anchor" href="#the-blue-box-reborn"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The rest of this book hands you a 2026 toolchain: write 6502 in a text editor, run &lt;a href="https://cdeever.github.io/atari-vcs/docs/getting-started/toolchain/"&gt;DASM&lt;/a&gt;, and watch the result in Stella a fraction of a second later. It works, it&amp;rsquo;s free, and it would have looked like science fiction to the people who actually invented these games. In 1979 there was no Stella, no DASM, no PC on the desk. There was a refrigerator-sized minicomputer down the hall, a serial cable, and — for David Crane at Activision — a blue sheet-metal box wired into the cartridge slot of a real console.&lt;/p&gt;</description></item><item><title>The Collision Registers</title><link>https://cdeever.github.io/atari-vcs/docs/collisions/the-collision-registers/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/collisions/the-collision-registers/</guid><description>&lt;h1 id="the-collision-registers"&gt;The Collision Registers&lt;a class="anchor" href="#the-collision-registers"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The TIA tracks collisions between its six drawable objects — the two &lt;a href="https://cdeever.github.io/atari-vcs/docs/sprites/drawing-a-player/"&gt;players&lt;/a&gt;, two &lt;a href="https://cdeever.github.io/atari-vcs/docs/sprites/missiles-and-ball/"&gt;missiles, the ball&lt;/a&gt;, and the &lt;a href="https://cdeever.github.io/atari-vcs/docs/playfield/"&gt;playfield&lt;/a&gt;. Six objects make &lt;strong&gt;15 possible pairs&lt;/strong&gt;, and the chip reports them across &lt;strong&gt;eight read-only registers&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="detection-is-geometric-and-it-latches"&gt;Detection is geometric, and it latches&lt;a class="anchor" href="#detection-is-geometric-and-it-latches"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As the beam paints each visible pixel, the TIA asks a simple question: are two objects &lt;em&gt;both lit here&lt;/em&gt;? If so, it sets the corresponding collision bit. Two things follow from that:&lt;/p&gt;</description></item><item><title>The Joystick</title><link>https://cdeever.github.io/atari-vcs/docs/input/the-joystick/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/input/the-joystick/</guid><description>&lt;h1 id="the-joystick"&gt;The Joystick&lt;a class="anchor" href="#the-joystick"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The standard CX40 joystick is the simplest input on the system: five switches — four directions and a fire button — and nothing analog. The four &lt;em&gt;directions&lt;/em&gt; of both joysticks are read from a single &lt;a href="https://cdeever.github.io/atari-vcs/docs/architecture/riot/"&gt;RIOT&lt;/a&gt; port, &lt;code&gt;SWCHA&lt;/code&gt;; the fire button comes in elsewhere (see &lt;a href="https://cdeever.github.io/atari-vcs/docs/input/buttons-and-switches/"&gt;Buttons &amp;amp; Console Switches&lt;/a&gt;).&lt;/p&gt;
&lt;h2 id="one-byte-two-joysticks"&gt;One byte, two joysticks&lt;a class="anchor" href="#one-byte-two-joysticks"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;SWCHA&lt;/code&gt; packs both controllers into its eight bits — &lt;strong&gt;player 0 in the high nibble, player 1 in the low nibble&lt;/strong&gt; — each nibble holding right/left/down/up:&lt;/p&gt;</description></item><item><title>Toolchain: DASM &amp; Stella</title><link>https://cdeever.github.io/atari-vcs/docs/getting-started/toolchain/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/getting-started/toolchain/</guid><description>&lt;h1 id="toolchain-dasm--stella"&gt;Toolchain: DASM &amp;amp; Stella&lt;a class="anchor" href="#toolchain-dasm--stella"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Two tools cover the entire development loop for this book: &lt;strong&gt;DASM&lt;/strong&gt; assembles your &lt;code&gt;.asm&lt;/code&gt; source into a cartridge image, and &lt;strong&gt;Stella&lt;/strong&gt; runs that image as if it were a real console.&lt;/p&gt;
&lt;h2 id="installing"&gt;Installing&lt;a class="anchor" href="#installing"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;On macOS with Homebrew:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;brew install dasm
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;brew install --cask stella&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;DASM is the de-facto assembler for the VCS; Stella is the reference emulator and an excellent debugger.&lt;/p&gt;
&lt;h2 id="assembling-a-rom"&gt;Assembling a ROM&lt;a class="anchor" href="#assembling-a-rom"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The canonical build command (from the repository&amp;rsquo;s &lt;code&gt;xmas/Makefile&lt;/code&gt;) is:&lt;/p&gt;</description></item><item><title>Anatomy of a Minimal ROM</title><link>https://cdeever.github.io/atari-vcs/docs/getting-started/minimal-rom/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/getting-started/minimal-rom/</guid><description>&lt;h1 id="anatomy-of-a-minimal-rom"&gt;Anatomy of a Minimal ROM&lt;a class="anchor" href="#anatomy-of-a-minimal-rom"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Every program in this book shares the same skeleton. Understanding these few lines means understanding what a VCS ROM fundamentally &lt;em&gt;is&lt;/em&gt;.&lt;/p&gt;
&lt;h2 id="the-header"&gt;The header&lt;a class="anchor" href="#the-header"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;processor&lt;/span&gt; &lt;span class="mi"&gt;6502&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;include&lt;/span&gt; &lt;span class="err"&gt;&amp;#34;&lt;/span&gt;&lt;span class="no"&gt;vcs.h&lt;/span&gt;&lt;span class="err"&gt;&amp;#34;&lt;/span&gt; &lt;span class="c1"&gt;; TIA / RIOT register names (COLUBK, PF0, WSYNC, ...)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;include&lt;/span&gt; &lt;span class="err"&gt;&amp;#34;&lt;/span&gt;&lt;span class="no"&gt;macro.h&lt;/span&gt;&lt;span class="err"&gt;&amp;#34;&lt;/span&gt; &lt;span class="err"&gt;;&lt;/span&gt; &lt;span class="no"&gt;helper&lt;/span&gt; &lt;span class="no"&gt;macros&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;e.g.&lt;/span&gt; &lt;span class="no"&gt;CLEAN_START&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;vcs.h&lt;/code&gt; gives readable names to the hardware registers so you can write &lt;code&gt;sta COLUBK&lt;/code&gt; instead of &lt;code&gt;sta $09&lt;/code&gt;. &lt;code&gt;macro.h&lt;/code&gt; provides convenience macros. In this repository both live in a shared top-level &lt;code&gt;include/&lt;/code&gt; directory that every game reaches via DASM&amp;rsquo;s &lt;a href="https://cdeever.github.io/atari-vcs/docs/getting-started/toolchain/"&gt;&lt;code&gt;-I../include&lt;/code&gt;&lt;/a&gt; flag — a single source of truth rather than a copy per game.&lt;/p&gt;</description></item><item><title>Reading 6502 Assembly</title><link>https://cdeever.github.io/atari-vcs/docs/prerequisites/reading-assembly/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/prerequisites/reading-assembly/</guid><description>&lt;h1 id="reading-6502-assembly"&gt;Reading 6502 Assembly&lt;a class="anchor" href="#reading-6502-assembly"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Every line of code in this book is &lt;strong&gt;6502 assembly language&lt;/strong&gt; — human-readable names for the numeric machine code the 6507 actually executes. &lt;a href="https://cdeever.github.io/atari-vcs/docs/getting-started/toolchain/"&gt;DASM&lt;/a&gt; translates it into the bytes that go on the cartridge. You don&amp;rsquo;t need to &lt;em&gt;write&lt;/em&gt; it fluently yet, but you do need to &lt;em&gt;read&lt;/em&gt; it, because every concept here is demonstrated in it. This page is just enough to follow along; the CPU&amp;rsquo;s full instruction set and addressing modes are the &lt;a href="https://cdeever.github.io/atari-vcs/docs/6502-basics/"&gt;6502 Basics&lt;/a&gt; chapter.&lt;/p&gt;</description></item><item><title>The Processor (CPU)</title><link>https://cdeever.github.io/atari-vcs/docs/architecture/cpu/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/architecture/cpu/</guid><description>&lt;h1 id="the-processor-cpu--a-6507"&gt;The Processor (CPU) — a 6507&lt;a class="anchor" href="#the-processor-cpu--a-6507"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The CPU runs your program. On most computers that makes it the star; on the VCS it&amp;rsquo;s deliberately the &lt;em&gt;least&lt;/em&gt; special of the four chips — a small, ordinary processor whose whole job is to operate the other three at exactly the right moments.&lt;/p&gt;
&lt;h2 id="a-6502-with-its-wings-clipped"&gt;A 6502 with its wings clipped&lt;a class="anchor" href="#a-6502-with-its-wings-clipped"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The 6507 is a cost-reduced version of the well-known &lt;a href="https://cdeever.github.io/atari-vcs/docs/6502-basics/"&gt;6502&lt;/a&gt;: the same instruction set, the same registers, the same programming model — but in a cheaper package with two consequential omissions:&lt;/p&gt;</description></item><item><title>The Video &amp; Sound Chip (TIA)</title><link>https://cdeever.github.io/atari-vcs/docs/architecture/programming-the-television/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/architecture/programming-the-television/</guid><description>&lt;h1 id="the-tia-programming-the-television"&gt;The TIA: Programming the Television&lt;a class="anchor" href="#the-tia-programming-the-television"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Every console has a graphics chip. What makes the TIA — the Television Interface Adapter — and therefore the VCS different is what it &lt;em&gt;doesn&amp;rsquo;t&lt;/em&gt; have: a frame buffer. That single absence is the source of both the machine&amp;rsquo;s notorious difficulty and its peculiar charm, and it&amp;rsquo;s why the right mental model is not &amp;ldquo;drawing graphics&amp;rdquo; but &lt;strong&gt;programming the television itself.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="what-the-tia-handles"&gt;What the TIA handles&lt;a class="anchor" href="#what-the-tia-handles"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For one chip, it does a lot — and all of it in real time, in step with the beam:&lt;/p&gt;</description></item><item><title>Memory, I/O &amp; Timer (RIOT)</title><link>https://cdeever.github.io/atari-vcs/docs/architecture/riot/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/architecture/riot/</guid><description>&lt;h1 id="the-memory-io--timer-chip-riot--a-6532"&gt;The Memory, I/O &amp;amp; Timer chip (RIOT) — a 6532&lt;a class="anchor" href="#the-memory-io--timer-chip-riot--a-6532"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The RIOT (the 6532) — sometimes called the PIA — is the unglamorous but essential housekeeping chip. While the &lt;a href="https://cdeever.github.io/atari-vcs/docs/architecture/programming-the-television/"&gt;TIA&lt;/a&gt; gets the glory, the RIOT quietly provides the three things every program needs but the TIA doesn&amp;rsquo;t supply. Its name is an inventory of those jobs: &lt;strong&gt;R&lt;/strong&gt;AM, &lt;strong&gt;I&lt;/strong&gt;/&lt;strong&gt;O&lt;/strong&gt;, and &lt;strong&gt;T&lt;/strong&gt;imer.&lt;/p&gt;
&lt;h2 id="ram--your-128-bytes"&gt;RAM — your 128 bytes&lt;a class="anchor" href="#ram--your-128-bytes"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The RIOT holds the VCS&amp;rsquo;s &lt;em&gt;entire&lt;/em&gt; read/write memory: &lt;strong&gt;128 bytes&lt;/strong&gt;, at addresses &lt;code&gt;$80&lt;/code&gt;–&lt;code&gt;$FF&lt;/code&gt;. Every variable your game keeps — score, positions, velocities, game state — lives here, and nowhere else. Internalize how little that is: a single screen&amp;rsquo;s worth of modern data structures would not come close to fitting. Tight memory discipline isn&amp;rsquo;t an advanced topic on the VCS; it&amp;rsquo;s the baseline.&lt;/p&gt;</description></item><item><title>The Program ROM</title><link>https://cdeever.github.io/atari-vcs/docs/architecture/rom/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/architecture/rom/</guid><description>&lt;h1 id="the-program-rom--your-cartridge"&gt;The Program ROM — your cartridge&lt;a class="anchor" href="#the-program-rom--your-cartridge"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Three of the four chips are inside the console. The &lt;strong&gt;ROM is the one you supply&lt;/strong&gt; — it&amp;rsquo;s the cartridge — and it holds your program and all of its constant data: code, sprite bitmaps, lookup tables, music.&lt;/p&gt;
&lt;h2 id="where-it-lives"&gt;Where it lives&lt;a class="anchor" href="#where-it-lives"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The CPU maps the cartridge into the &lt;strong&gt;top of the address space&lt;/strong&gt;, the &lt;code&gt;$F000&lt;/code&gt;–&lt;code&gt;$FFFF&lt;/code&gt; window, with the all-important &lt;strong&gt;reset vectors at &lt;code&gt;$FFFC&lt;/code&gt;&lt;/strong&gt;. When the console powers on, the 6507 reads that vector and jumps to it — so the very top of your ROM is where execution begins. The mechanics of that startup are in &lt;strong&gt;&lt;a href="https://cdeever.github.io/atari-vcs/docs/getting-started/minimal-rom/"&gt;Anatomy of a Minimal ROM&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;</description></item><item><title>Addressing Modes</title><link>https://cdeever.github.io/atari-vcs/docs/6502-basics/addressing-modes/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/6502-basics/addressing-modes/</guid><description>&lt;h1 id="addressing-modes"&gt;Addressing Modes&lt;a class="anchor" href="#addressing-modes"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;An instruction like &lt;code&gt;LDA&lt;/code&gt; doesn&amp;rsquo;t just load — it loads &lt;em&gt;from somewhere&lt;/em&gt;, and the &lt;strong&gt;addressing mode&lt;/strong&gt; is how that somewhere is specified. The same &lt;code&gt;LDA&lt;/code&gt; comes in several forms, and they differ in both what they can reach and &lt;strong&gt;how many cycles they cost&lt;/strong&gt; — which, on the VCS, is the part you care about most. &lt;a href="https://cdeever.github.io/atari-vcs/docs/prerequisites/reading-assembly/"&gt;Reading 6502 Assembly&lt;/a&gt; introduced the &lt;code&gt;#&lt;/code&gt;/&lt;code&gt;$&lt;/code&gt;/&lt;code&gt;,X&lt;/code&gt; notation; here is what each mode actually does.&lt;/p&gt;</description></item><item><title>Buttons &amp; Console Switches</title><link>https://cdeever.github.io/atari-vcs/docs/input/buttons-and-switches/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/input/buttons-and-switches/</guid><description>&lt;h1 id="buttons--console-switches"&gt;Buttons &amp;amp; Console Switches&lt;a class="anchor" href="#buttons--console-switches"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The &lt;a href="https://cdeever.github.io/atari-vcs/docs/input/the-joystick/"&gt;joystick directions&lt;/a&gt; come from &lt;code&gt;SWCHA&lt;/code&gt;, but the &lt;strong&gt;fire buttons&lt;/strong&gt; and the &lt;strong&gt;console switches&lt;/strong&gt; live elsewhere — and they introduce the one idea that separates &amp;ldquo;input that works&amp;rdquo; from &amp;ldquo;input that feels right&amp;rdquo;: telling a &lt;em&gt;held&lt;/em&gt; button from a &lt;em&gt;just-pressed&lt;/em&gt; one.&lt;/p&gt;
&lt;h2 id="fire-buttons-inpt4--inpt5"&gt;Fire buttons (INPT4 / INPT5)&lt;a class="anchor" href="#fire-buttons-inpt4--inpt5"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A joystick&amp;rsquo;s fire button is read not from the RIOT but from two &lt;strong&gt;TIA&lt;/strong&gt; registers: &lt;code&gt;INPT4&lt;/code&gt; for player 0, &lt;code&gt;INPT5&lt;/code&gt; for player 1. The state is in &lt;strong&gt;bit 7&lt;/strong&gt;, and like everything else it&amp;rsquo;s &lt;a href="https://cdeever.github.io/atari-vcs/docs/input/the-joystick/"&gt;active-low&lt;/a&gt; — pressed reads &lt;code&gt;0&lt;/code&gt;. Because the flag is in bit 7, &lt;a href="https://cdeever.github.io/atari-vcs/docs/6502-basics/registers/"&gt;&lt;code&gt;BIT&lt;/code&gt;&lt;/a&gt; is the natural test:&lt;/p&gt;</description></item><item><title>Extra RAM</title><link>https://cdeever.github.io/atari-vcs/docs/cartridge-hardware/extra-ram/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/cartridge-hardware/extra-ram/</guid><description>&lt;h1 id="extra-ram"&gt;Extra RAM&lt;a class="anchor" href="#extra-ram"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The console gives you &lt;strong&gt;128 bytes&lt;/strong&gt; of &lt;a href="https://cdeever.github.io/atari-vcs/docs/architecture/riot/"&gt;RAM&lt;/a&gt;, and that pool is shared with the &lt;a href="https://cdeever.github.io/atari-vcs/docs/6502-basics/stack-and-subroutines/"&gt;stack&lt;/a&gt;. It is brutally little — a few sprite positions, a score, some counters, and it&amp;rsquo;s gone. The way past it is the same as for &lt;a href="https://cdeever.github.io/atari-vcs/docs/cartridge-hardware/bankswitching/"&gt;ROM&lt;/a&gt;: put more memory &lt;em&gt;on the cartridge.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id="cartridge-ram-and-the-two-port-trick"&gt;Cartridge RAM, and the two-port trick&lt;a class="anchor" href="#cartridge-ram-and-the-two-port-trick"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The best-known add-on is Atari&amp;rsquo;s &lt;strong&gt;&amp;ldquo;Superchip&amp;rdquo;&lt;/strong&gt; — 128 extra bytes (some carts more) of RAM riding on the cartridge, mapped into the bottom of the &lt;a href="https://cdeever.github.io/atari-vcs/docs/architecture/rom/"&gt;cart window&lt;/a&gt;. Atari shipped it in a run of mid-1980s titles — &lt;em&gt;Dig Dug&lt;/em&gt;, &lt;em&gt;Crystal Castles&lt;/em&gt;, &lt;em&gt;Off the Wall&lt;/em&gt;, &lt;em&gt;Secret Quest&lt;/em&gt; — most of which &lt;a href="https://cdeever.github.io/atari-vcs/docs/cartridge-hardware/bankswitching/"&gt;bankswitch&lt;/a&gt; as well. But cartridge RAM has a wrinkle the console RAM doesn&amp;rsquo;t: the cartridge connector has &lt;strong&gt;no clean read/write signal&lt;/strong&gt; the chip can use to tell a load from a store in time. So cartridge RAM is split across &lt;strong&gt;two address ranges — a write port and a read port:&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Horizontal Positioning</title><link>https://cdeever.github.io/atari-vcs/docs/sprites/horizontal-positioning/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/sprites/horizontal-positioning/</guid><description>&lt;h1 id="horizontal-positioning"&gt;Horizontal Positioning&lt;a class="anchor" href="#horizontal-positioning"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This is the technique that defines VCS sprite work, and the first place every beginner hits the cycle wall. A player has &lt;strong&gt;no X-coordinate register.&lt;/strong&gt; You cannot write &amp;ldquo;put P0 at column 40.&amp;rdquo; Instead you position it by &lt;em&gt;timing&lt;/em&gt; — and then nudge it into place.&lt;/p&gt;
&lt;h2 id="step-one-strobe-to-a-coarse-position"&gt;Step one: strobe to a coarse position&lt;a class="anchor" href="#step-one-strobe-to-a-coarse-position"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Writing to &lt;code&gt;RESP0&lt;/code&gt; is a &lt;a href="https://cdeever.github.io/atari-vcs/docs/prerequisites/memory-mapped/"&gt;strobe&lt;/a&gt;: the value doesn&amp;rsquo;t matter, the &lt;em&gt;act&lt;/em&gt; of writing does. It snaps player 0&amp;rsquo;s horizontal position to &lt;strong&gt;wherever the beam happens to be&lt;/strong&gt; at the moment the store executes. So you move a sprite by choosing &lt;em&gt;when&lt;/em&gt; in the scanline to run &lt;code&gt;STA RESP0&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Pitfall! (1982)</title><link>https://cdeever.github.io/atari-vcs/docs/game-analysis/pitfall/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/game-analysis/pitfall/</guid><description>&lt;h1 id="pitfall-1982"&gt;Pitfall! (1982)&lt;a class="anchor" href="#pitfall-1982"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;Pitfall!&lt;/em&gt; — &lt;strong&gt;David Crane&lt;/strong&gt;, Activision, 1982 — sent Pitfall Harry running through a &lt;strong&gt;255-room jungle&lt;/strong&gt; of logs, vines, crocodiles, scorpions, and quicksand, and became one of the best-selling games on the system. It did all that on a &lt;strong&gt;4 KB&lt;/strong&gt; cartridge, which raises an obvious question: where do 255 rooms &lt;em&gt;fit&lt;/em&gt;? The answer is the most famous idea in 2600 programming, and it&amp;rsquo;s the reason this game is worth taking apart. (The disassembly here is Thomas Jentzsch&amp;rsquo;s.)&lt;/p&gt;</description></item><item><title>Reading &amp; Clearing</title><link>https://cdeever.github.io/atari-vcs/docs/collisions/reading-collisions/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/collisions/reading-collisions/</guid><description>&lt;h1 id="reading--clearing"&gt;Reading &amp;amp; Clearing&lt;a class="anchor" href="#reading--clearing"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The TIA does the detecting; your job is two small, regular acts: &lt;strong&gt;read&lt;/strong&gt; the &lt;a href="https://cdeever.github.io/atari-vcs/docs/collisions/the-collision-registers/"&gt;latches&lt;/a&gt; once the frame has been drawn, and &lt;strong&gt;clear&lt;/strong&gt; them before the next one. Get that rhythm right and collisions are nearly free; get it wrong and they either never fire or never stop.&lt;/p&gt;
&lt;h2 id="testing-a-latch-with-bit"&gt;Testing a latch with &lt;code&gt;BIT&lt;/code&gt;&lt;a class="anchor" href="#testing-a-latch-with-bit"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Each collision flag sits in bit 7 (and bit 6) of its register, which is exactly where &lt;code&gt;BIT&lt;/code&gt; is most useful: it copies a memory location&amp;rsquo;s bit 7 into the &lt;strong&gt;N&lt;/strong&gt; flag and bit 6 into the &lt;strong&gt;V&lt;/strong&gt; flag, without changing any register (&lt;a href="https://cdeever.github.io/atari-vcs/docs/6502-basics/registers/"&gt;see Registers &amp;amp; Flags&lt;/a&gt;). So one &lt;code&gt;BIT&lt;/code&gt; tests both pairs at once:&lt;/p&gt;</description></item><item><title>Thinking in Bits</title><link>https://cdeever.github.io/atari-vcs/docs/prerequisites/bits/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/prerequisites/bits/</guid><description>&lt;h1 id="thinking-in-bits"&gt;Thinking in Bits&lt;a class="anchor" href="#thinking-in-bits"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;On the VCS, almost every hardware register is a bag of individual switches — one bit turns on playfield reflection, one bit is the fire button, a group of bits picks a sound waveform. There is no high-level API; you set and clear bits directly. This page is the bit literacy the rest of the book assumes. Its companion, &lt;a href="https://cdeever.github.io/atari-vcs/docs/prerequisites/memory-mapped/"&gt;The Memory-Mapped Interface&lt;/a&gt;, covers &lt;em&gt;where&lt;/em&gt; those bits live and how you reach them.&lt;/p&gt;</description></item><item><title>Tones, Noise &amp; Pitch</title><link>https://cdeever.github.io/atari-vcs/docs/sound/tones-noise-and-pitch/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/sound/tones-noise-and-pitch/</guid><description>&lt;h1 id="tones-noise--pitch"&gt;Tones, Noise &amp;amp; Pitch&lt;a class="anchor" href="#tones-noise--pitch"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Two registers shape &lt;em&gt;what a channel sounds like&lt;/em&gt;: &lt;code&gt;AUDC&lt;/code&gt; picks the waveform, and &lt;code&gt;AUDF&lt;/code&gt; picks the pitch. Together they&amp;rsquo;re the source of both the VCS&amp;rsquo;s distinctive voice and its most infamous flaw — it can&amp;rsquo;t play in tune.&lt;/p&gt;
&lt;h2 id="audc-pick-a-voice"&gt;AUDC: pick a voice&lt;a class="anchor" href="#audc-pick-a-voice"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;AUDC&lt;/code&gt; is a 4-bit selector (0–15) that routes the channel through different internal divider and polynomial-counter combinations. The result isn&amp;rsquo;t 16 evenly-graded timbres but a handful of distinct &lt;em&gt;families&lt;/em&gt; — pure tones, buzzy/reedy tones, and noise. The ones you&amp;rsquo;ll reach for most:&lt;/p&gt;</description></item><item><title>Waiting Precisely</title><link>https://cdeever.github.io/atari-vcs/docs/kernel-techniques/waiting-precisely/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/kernel-techniques/waiting-precisely/</guid><description>&lt;h1 id="waiting-precisely"&gt;Waiting Precisely&lt;a class="anchor" href="#waiting-precisely"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Half of kernel work is making things happen; the other half is making them happen &lt;em&gt;at the right cycle&lt;/em&gt;. &lt;a href="https://cdeever.github.io/atari-vcs/docs/6502-basics/cycles-and-timing/"&gt;&lt;code&gt;WSYNC&lt;/code&gt;&lt;/a&gt; handles the coarse case — it parks you at the start of the next line — but it can only round &lt;em&gt;up&lt;/em&gt; to a line boundary. When you need to land on an exact cycle &lt;em&gt;within&lt;/em&gt; a line (positioning a sprite, &lt;a href="https://cdeever.github.io/atari-vcs/docs/playfield/asymmetric/"&gt;rewriting a playfield register mid-line&lt;/a&gt;), or to wait out a whole region of the frame, you need finer and coarser tools than &lt;code&gt;WSYNC&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Yars' Revenge's Neutral Zone</title><link>https://cdeever.github.io/atari-vcs/docs/hardware-quirks/yars-revenge-neutral-zone/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/hardware-quirks/yars-revenge-neutral-zone/</guid><description>&lt;h1 id="yars-revenges-neutral-zone"&gt;Yars&amp;rsquo; Revenge&amp;rsquo;s Neutral Zone&lt;a class="anchor" href="#yars-revenges-neutral-zone"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Down the middle of &lt;em&gt;Yars&amp;rsquo; Revenge&lt;/em&gt; (Atari, 1982 — the best-selling original Atari-made VCS game) runs the &lt;strong&gt;neutral zone&lt;/strong&gt;: a shimmering, churning band of multicolored static the player&amp;rsquo;s insect hero can hide in. It looks like deliberate visual noise. It is something stranger: you are looking directly at &lt;strong&gt;the game&amp;rsquo;s own program&lt;/strong&gt;.&lt;/p&gt;
&lt;h2 id="the-picture-is-the-code"&gt;The picture is the code&lt;a class="anchor" href="#the-picture-is-the-code"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Howard Scott Warshaw had no spare &lt;a href="https://cdeever.github.io/atari-vcs/docs/architecture/rom/"&gt;ROM&lt;/a&gt; for a dedicated graphic — a &lt;a href="https://cdeever.github.io/atari-vcs/docs/burning-eprom/preparing-the-image/"&gt;4 KB cartridge&lt;/a&gt; leaves nothing to waste. So instead of &lt;em&gt;storing&lt;/em&gt; a pattern, he pointed the display at memory the program already contained: the neutral zone reads its bytes straight from the &lt;strong&gt;section of ROM that holds the game&amp;rsquo;s code&lt;/strong&gt;, cycling through it so the bytes scroll and shimmer rather than sit still. The instructions that run the game do double duty as the texture on screen.&lt;/p&gt;</description></item><item><title>Numbers &amp; Arithmetic</title><link>https://cdeever.github.io/atari-vcs/docs/prerequisites/numbers/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/prerequisites/numbers/</guid><description>&lt;h1 id="numbers--arithmetic"&gt;Numbers &amp;amp; Arithmetic&lt;a class="anchor" href="#numbers--arithmetic"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://cdeever.github.io/atari-vcs/docs/prerequisites/bits/"&gt;Thinking in Bits&lt;/a&gt; covered a byte as a pattern of switches. This page is about a byte as a &lt;em&gt;number&lt;/em&gt; — and the surprising limits of doing math on a 1977 processor. The big ones: there are only 256 possible values, negative numbers are a convention rather than a feature, and &lt;strong&gt;the 6502 cannot multiply or divide at all.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id="a-byte-is-0255--or-128-to-127"&gt;A byte is 0–255 — or −128 to 127&lt;a class="anchor" href="#a-byte-is-0255--or-128-to-127"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;An 8-bit byte holds 256 distinct values. Read as &lt;strong&gt;unsigned&lt;/strong&gt;, that&amp;rsquo;s 0 to 255. But the CPU has no separate &amp;ldquo;signed&amp;rdquo; type; instead, by convention, the &lt;strong&gt;top bit is treated as a sign&lt;/strong&gt; using &lt;strong&gt;two&amp;rsquo;s complement&lt;/strong&gt;:&lt;/p&gt;</description></item><item><title>A Grab Bag of Clever Abuses</title><link>https://cdeever.github.io/atari-vcs/docs/hardware-quirks/more-quirks/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/hardware-quirks/more-quirks/</guid><description>&lt;h1 id="a-grab-bag-of-clever-abuses"&gt;A Grab Bag of Clever Abuses&lt;a class="anchor" href="#a-grab-bag-of-clever-abuses"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Not every exploited quirk got its own legend like &lt;a href="https://cdeever.github.io/atari-vcs/docs/hardware-quirks/cosmic-ark-starfield/"&gt;Cosmic Ark&lt;/a&gt; or &lt;a href="https://cdeever.github.io/atari-vcs/docs/hardware-quirks/yars-revenge-neutral-zone/"&gt;Yars&amp;rsquo; Revenge&lt;/a&gt;. Many became everyday tools — techniques born from a limitation that programmers simply learned to live inside. A sampler.&lt;/p&gt;
&lt;h2 id="flicker-more-objects-than-the-hardware-has"&gt;Flicker: more objects than the hardware has&lt;a class="anchor" href="#flicker-more-objects-than-the-hardware-has"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The TIA gives you exactly &lt;a href="https://cdeever.github.io/atari-vcs/docs/sprites/"&gt;two players&lt;/a&gt;. Plenty of games need to show three, four, or a dozen moving things — the ghosts chasing Pac-Man, a field of asteroids, a wall of &lt;em&gt;Warlords&lt;/em&gt; bricks. The answer is &lt;strong&gt;flicker&lt;/strong&gt;: draw some objects on even frames and the rest on odd frames, reusing the same two players for different things each pass. At 60 frames a second, each object appears only 30 times a second, and the eye mostly fuses them into a steady crowd.&lt;/p&gt;</description></item><item><title>Adventure (1980)</title><link>https://cdeever.github.io/atari-vcs/docs/game-analysis/adventure/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/game-analysis/adventure/</guid><description>&lt;h1 id="adventure-1980"&gt;Adventure (1980)&lt;a class="anchor" href="#adventure-1980"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;Adventure&lt;/em&gt; — &lt;strong&gt;Warren Robinett&lt;/strong&gt;, Atari — put an entire &lt;strong&gt;explorable world&lt;/strong&gt; on the console: roughly thirty connected rooms, items you carry one at a time, three dragons that hunt you, a thieving bat, and locked castles opened with keys. It was the first action-adventure game on a home console, packing an astonishingly rich world into a 4 KB cartridge. It&amp;rsquo;s also famous for its hidden &lt;strong&gt;&amp;ldquo;Created by Warren Robinett&amp;rdquo; room&lt;/strong&gt; — widely regarded as the first &lt;em&gt;famous&lt;/em&gt; Easter egg in a video game, and the one that popularized the tradition of hiding secrets for players to find.&lt;/p&gt;</description></item><item><title>Multi-Line Kernels</title><link>https://cdeever.github.io/atari-vcs/docs/kernel-techniques/multi-line-kernels/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/kernel-techniques/multi-line-kernels/</guid><description>&lt;h1 id="multi-line-kernels"&gt;Multi-Line Kernels&lt;a class="anchor" href="#multi-line-kernels"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://cdeever.github.io/atari-vcs/docs/kernel-techniques/counting-cycles/"&gt;Counting cycles&lt;/a&gt; eventually delivers bad news: there are jobs that simply don&amp;rsquo;t fit in one &lt;a href="https://cdeever.github.io/atari-vcs/docs/6502-basics/cycles-and-timing/"&gt;76-cycle line&lt;/a&gt;. Updating &lt;em&gt;both&lt;/em&gt; &lt;a href="https://cdeever.github.io/atari-vcs/docs/sprites/drawing-a-player/"&gt;players&lt;/a&gt;, fetching their colors, advancing their counters, and still leaving room for the draw — added up, it overflows. When a single line can&amp;rsquo;t hold the work, you stop trying to do it in one.&lt;/p&gt;
&lt;h2 id="spread-the-work-across-two-lines"&gt;Spread the work across two lines&lt;a class="anchor" href="#spread-the-work-across-two-lines"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A &lt;strong&gt;two-line kernel&lt;/strong&gt; runs its loop body once for every &lt;em&gt;two&lt;/em&gt; scanlines. The TIA still draws every line — the beam doesn&amp;rsquo;t slow down — but your code now has roughly &lt;strong&gt;two lines&amp;rsquo; worth of cycles&lt;/strong&gt; to prepare what those lines show. You split the work: some on the first line, the rest on the second.&lt;/p&gt;</description></item><item><title>Paddles</title><link>https://cdeever.github.io/atari-vcs/docs/input/paddles/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/input/paddles/</guid><description>&lt;h1 id="paddles"&gt;Paddles&lt;a class="anchor" href="#paddles"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Everything so far has been a switch: on or off, one bit. &lt;strong&gt;Paddles&lt;/strong&gt; are different — they&amp;rsquo;re &lt;em&gt;analog&lt;/em&gt;, a knob that turns through a continuous range — and the VCS has no analog-to-digital converter. Reading one is a small, clever piece of analog timing, and it&amp;rsquo;s the most unusual input on the machine.&lt;/p&gt;
&lt;h2 id="reading-time-not-voltage"&gt;Reading time, not voltage&lt;a class="anchor" href="#reading-time-not-voltage"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A paddle is a &lt;strong&gt;potentiometer&lt;/strong&gt;: turning the knob changes a resistance. The TIA reads it by charging a capacitor &lt;em&gt;through&lt;/em&gt; that resistance and &lt;strong&gt;timing how long the charge takes&lt;/strong&gt; — a low resistance charges fast, a high resistance slowly. The charge time is the knob position.&lt;/p&gt;</description></item><item><title>Playing Music</title><link>https://cdeever.github.io/atari-vcs/docs/sound/playing-music/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/sound/playing-music/</guid><description>&lt;h1 id="playing-music"&gt;Playing Music&lt;a class="anchor" href="#playing-music"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;A steady tone is just six registers holding their values. &lt;strong&gt;Music&lt;/strong&gt; is what happens when you change them on a schedule — and the schedule is the &lt;a href="https://cdeever.github.io/atari-vcs/docs/prerequisites/how-the-tv-works/"&gt;frame&lt;/a&gt;. A small routine, run once per frame, reads a song out of a data table and updates the &lt;a href="https://cdeever.github.io/atari-vcs/docs/sound/the-audio-registers/"&gt;audio registers&lt;/a&gt;; that routine is a &lt;em&gt;sound engine&lt;/em&gt;, and even a tiny one carries a whole tune.&lt;/p&gt;
&lt;h2 id="a-song-is-a-data-table"&gt;A song is a data table&lt;a class="anchor" href="#a-song-is-a-data-table"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The simplest useful format is a list of &lt;strong&gt;(note, duration)&lt;/strong&gt; pairs — which is exactly what the &lt;code&gt;Song&lt;/code&gt; table in &lt;code&gt;xmas/xmas.asm&lt;/code&gt; is: a note index and a length in frames, terminated by a zero:&lt;/p&gt;</description></item><item><title>Size &amp; Copies (NUSIZ)</title><link>https://cdeever.github.io/atari-vcs/docs/sprites/size-and-copies/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/sprites/size-and-copies/</guid><description>&lt;h1 id="size--copies-nusiz"&gt;Size &amp;amp; Copies (NUSIZ)&lt;a class="anchor" href="#size--copies-nusiz"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;There are only &lt;a href="https://cdeever.github.io/atari-vcs/docs/sprites/drawing-a-player/"&gt;two players&lt;/a&gt;, but a single register stretches what they can do. &lt;code&gt;NUSIZ0&lt;/code&gt; and &lt;code&gt;NUSIZ1&lt;/code&gt; (one per player) set a player&amp;rsquo;s &lt;strong&gt;width&lt;/strong&gt; &lt;em&gt;and&lt;/em&gt; let the TIA stamp out &lt;strong&gt;multiple copies&lt;/strong&gt; of it across the line — and the same register sizes that player&amp;rsquo;s missile. It&amp;rsquo;s the cheapest way to get more than two objects on screen at once.&lt;/p&gt;
&lt;h2 id="player-width-and-copies"&gt;Player width and copies&lt;a class="anchor" href="#player-width-and-copies"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The low three bits of &lt;code&gt;NUSIZ&lt;/code&gt; choose one of eight modes:&lt;/p&gt;</description></item><item><title>The DPC: A Coprocessor in the Cartridge</title><link>https://cdeever.github.io/atari-vcs/docs/cartridge-hardware/dpc/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/cartridge-hardware/dpc/</guid><description>&lt;h1 id="the-dpc-a-coprocessor-in-the-cartridge"&gt;The DPC: A Coprocessor in the Cartridge&lt;a class="anchor" href="#the-dpc-a-coprocessor-in-the-cartridge"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://cdeever.github.io/atari-vcs/docs/cartridge-hardware/bankswitching/"&gt;Bankswitching&lt;/a&gt; adds ROM and the &lt;a href="https://cdeever.github.io/atari-vcs/docs/cartridge-hardware/extra-ram/"&gt;Superchip&lt;/a&gt; adds RAM, but both are still just &lt;em&gt;memory&lt;/em&gt; — passive storage the CPU does all the work against. &lt;em&gt;Pitfall II: Lost Caverns&lt;/em&gt; (1984) took the idea to its conclusion: &lt;strong&gt;David Crane&lt;/strong&gt; designed a custom chip, the &lt;strong&gt;DPC&lt;/strong&gt; — officially the &lt;em&gt;Display Processor Chip&lt;/em&gt;, though the initials are also his own (David Patrick Crane) — and built it into the cartridge. It was the first — and in the commercial 2600 era, essentially the only — game cartridge with a coprocessor of its own. The console did nothing new; the cart did the new thing.&lt;/p&gt;</description></item><item><title>The Instruction Set</title><link>https://cdeever.github.io/atari-vcs/docs/6502-basics/instruction-set/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/6502-basics/instruction-set/</guid><description>&lt;h1 id="the-instruction-set"&gt;The Instruction Set&lt;a class="anchor" href="#the-instruction-set"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The 6502&amp;rsquo;s instruction set is small — about 56 mnemonics — and you can write whole games with maybe two dozen of them. This page is a grouped tour, not an exhaustive datasheet: enough to recognize what you read and reach for what you need. Cycle counts live in &lt;a href="https://cdeever.github.io/atari-vcs/docs/6502-basics/cycles-and-timing/"&gt;Cycles &amp;amp; Timing&lt;/a&gt;; flag effects are in &lt;a href="https://cdeever.github.io/atari-vcs/docs/6502-basics/registers/"&gt;Registers &amp;amp; Status Flags&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="moving-data"&gt;Moving data&lt;a class="anchor" href="#moving-data"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The most common instructions by far — nothing computes until data is in a register.&lt;/p&gt;</description></item><item><title>The Memory-Mapped Interface</title><link>https://cdeever.github.io/atari-vcs/docs/prerequisites/memory-mapped/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/prerequisites/memory-mapped/</guid><description>&lt;h1 id="the-memory-mapped-interface"&gt;The Memory-Mapped Interface&lt;a class="anchor" href="#the-memory-mapped-interface"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;On the VCS you talk to hardware by reading and writing memory addresses. The chips that make sound, draw pixels, and read the joystick live &lt;em&gt;in the same address space as RAM&lt;/em&gt;, so a &lt;code&gt;sta&lt;/code&gt; to the right address isn&amp;rsquo;t storing data — it&amp;rsquo;s operating a chip. This page assumes the bit literacy from &lt;a href="https://cdeever.github.io/atari-vcs/docs/prerequisites/bits/"&gt;Thinking in Bits&lt;/a&gt;; here we cover &lt;em&gt;where&lt;/em&gt; those bits go.&lt;/p&gt;
&lt;h2 id="registers-are-just-addresses"&gt;Registers are just addresses&lt;a class="anchor" href="#registers-are-just-addresses"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The 6502/6507 has exactly one kind of &amp;ldquo;talk to the outside world&amp;rdquo; instruction — the same loads and stores it uses for RAM. There is &lt;strong&gt;no separate I/O instruction&lt;/strong&gt;. Instead, the TIA (graphics/sound), the RIOT (RAM, timer, and joystick/switch ports), and the cartridge ROM are all wired to &lt;em&gt;respond to specific addresses&lt;/em&gt;. This is &lt;strong&gt;memory-mapped I/O&lt;/strong&gt;: the chip behind an address decides what reading or writing it actually does.&lt;/p&gt;</description></item><item><title>The Frame Structure</title><link>https://cdeever.github.io/atari-vcs/docs/tia-racing-the-beam/frame-structure/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/tia-racing-the-beam/frame-structure/</guid><description>&lt;h1 id="the-frame-structure"&gt;The Frame Structure&lt;a class="anchor" href="#the-frame-structure"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The TIA produces no picture on its own — your code defines the frame by toggling the &lt;code&gt;VSYNC&lt;/code&gt; and &lt;code&gt;VBLANK&lt;/code&gt; signals at the right times and spending the right number of scanlines in each region. An NTSC frame is &lt;strong&gt;262 scanlines&lt;/strong&gt;, conventionally divided as:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Region&lt;/th&gt;
 &lt;th&gt;Lines&lt;/th&gt;
 &lt;th&gt;Purpose&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;VSYNC&lt;/td&gt;
 &lt;td&gt;3&lt;/td&gt;
 &lt;td&gt;Tells the TV &amp;ldquo;new frame starts here.&amp;rdquo;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;VBLANK&lt;/td&gt;
 &lt;td&gt;37&lt;/td&gt;
 &lt;td&gt;Top blanking. The picture isn&amp;rsquo;t visible yet — do game logic here.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Visible&lt;/td&gt;
 &lt;td&gt;192&lt;/td&gt;
 &lt;td&gt;The kernel. Everything the player sees is drawn here, one line at a time.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Overscan&lt;/td&gt;
 &lt;td&gt;30&lt;/td&gt;
 &lt;td&gt;Bottom blanking. Read input and collisions, update state.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;


&lt;figure class="vcs-anim-figure"&gt;
 &lt;div class="vcs-anim"
 data-scene="beam"
 &gt;&lt;/div&gt;
 &lt;figcaption&gt;The beam paints 262 lines top-to-bottom; only the 192 visible lines carry picture. Press play, then scrub to freeze any moment.&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id="vertical-sync"&gt;Vertical sync&lt;a class="anchor" href="#vertical-sync"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A frame begins by turning on &lt;code&gt;VBLANK&lt;/code&gt; and &lt;code&gt;VSYNC&lt;/code&gt;, then holding &lt;code&gt;VSYNC&lt;/code&gt; for exactly three scanlines:&lt;/p&gt;</description></item><item><title>Color: Hue &amp; Luminance</title><link>https://cdeever.github.io/atari-vcs/docs/tia-racing-the-beam/color/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/tia-racing-the-beam/color/</guid><description>&lt;h1 id="color-hue--luminance"&gt;Color: Hue &amp;amp; Luminance&lt;a class="anchor" href="#color-hue--luminance"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The TIA holds exactly four color registers, one for each thing it can draw:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Register&lt;/th&gt;
 &lt;th&gt;Colors&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;COLUBK&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;the background&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;COLUPF&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;the playfield (and the ball, which borrows it)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;COLUP0&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;player 0 (and missile 0)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;code&gt;COLUP1&lt;/code&gt;&lt;/td&gt;
 &lt;td&gt;player 1 (and missile 1)&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Each takes a single byte, and each is &lt;strong&gt;latched&lt;/strong&gt; — write it once and it sticks until you overwrite it. Set &lt;code&gt;COLUBK&lt;/code&gt; during startup and the background stays that color for the whole game without you ever touching it again. That, and the fact that you &lt;em&gt;can&lt;/em&gt; rewrite a color register mid-frame, are the two facts the rest of this page rests on.&lt;/p&gt;</description></item><item><title>The Three Registers</title><link>https://cdeever.github.io/atari-vcs/docs/playfield/registers/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/playfield/registers/</guid><description>&lt;h1 id="the-three-registers-pf0-pf1-pf2"&gt;The Three Registers: PF0, PF1, PF2&lt;a class="anchor" href="#the-three-registers-pf0-pf1-pf2"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Everything the playfield does starts with three 8-bit registers — &lt;code&gt;PF0&lt;/code&gt;, &lt;code&gt;PF1&lt;/code&gt;, &lt;code&gt;PF2&lt;/code&gt; — and the &lt;strong&gt;20 bits&lt;/strong&gt; of them the TIA actually draws. This page lays out exactly which bit lights which pixel. We will stay on the &lt;strong&gt;left half of the screen&lt;/strong&gt; the whole way; the other half turns out to be a story of its own.&lt;/p&gt;
&lt;h2 id="what-one-pixel-is"&gt;What one &amp;ldquo;pixel&amp;rdquo; is&lt;a class="anchor" href="#what-one-pixel-is"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First, what these bits paint. A playfield pixel is a &lt;em&gt;virtual&lt;/em&gt; block, generated on the fly by the TIA as the beam passes — not a dot in any frame buffer. Each is &lt;strong&gt;4 color clocks wide&lt;/strong&gt; and exactly &lt;strong&gt;one scanline tall&lt;/strong&gt;. The playfield has no vertical resolution of its own: a pixel is one scanline high, and a &lt;em&gt;taller&lt;/em&gt; block is just the same bits held unchanged across consecutive lines — exactly how the Christmas-tree kernel grows its shape.&lt;/p&gt;</description></item><item><title>ARM Cartridges</title><link>https://cdeever.github.io/atari-vcs/docs/cartridge-hardware/arm-cartridges/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/cartridge-hardware/arm-cartridges/</guid><description>&lt;h1 id="arm-cartridges"&gt;ARM Cartridges&lt;a class="anchor" href="#arm-cartridges"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The &lt;a href="https://cdeever.github.io/atari-vcs/docs/cartridge-hardware/dpc/"&gt;DPC&lt;/a&gt; put one small custom chip on the cartridge and let it do a few jobs the 6507 couldn&amp;rsquo;t spare cycles for. Modern homebrew takes that exact idea and pushes it as far as it will go.&lt;/p&gt;
&lt;p&gt;Today&amp;rsquo;s &lt;strong&gt;Harmony&lt;/strong&gt; and &lt;strong&gt;Melody&lt;/strong&gt; cartridges, together with the &lt;strong&gt;DPC+&lt;/strong&gt; and &lt;strong&gt;CDF&lt;/strong&gt; programming models, take exactly the same idea to its conclusion. Hidden behind the cartridge edge connector is a modern &lt;strong&gt;ARM microcontroller&lt;/strong&gt; running at hundreds of megahertz. To the Atari, it still appears to be an ordinary ROM with a handful of special registers. Behind the scenes, however, the ARM is decompressing graphics, streaming music, copying data, calculating game logic, and emulating the original DPC hardware — all while &lt;strong&gt;the humble 1.19 MHz 6507 remains blissfully unaware.&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Cycles &amp; Timing</title><link>https://cdeever.github.io/atari-vcs/docs/6502-basics/cycles-and-timing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/6502-basics/cycles-and-timing/</guid><description>&lt;h1 id="cycles--timing"&gt;Cycles &amp;amp; Timing&lt;a class="anchor" href="#cycles--timing"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;On most computers an instruction&amp;rsquo;s cycle count is trivia. On the VCS it is the &lt;strong&gt;central fact of the craft&lt;/strong&gt;: every visible scanline is &lt;a href="https://cdeever.github.io/atari-vcs/docs/tia-racing-the-beam/"&gt;76 CPU cycles&lt;/a&gt;, and a kernel that needs 77 doesn&amp;rsquo;t run slow — it tears the picture. This page is the reference for counting them.&lt;/p&gt;
&lt;p&gt;A &amp;ldquo;machine cycle&amp;rdquo; is one tick of the 6507&amp;rsquo;s ~1.19 MHz clock; the TIA runs at three times that, so &lt;strong&gt;one CPU cycle = three color clocks (three pixels)&lt;/strong&gt;. You budget in CPU cycles and the picture pays out in pixels.&lt;/p&gt;</description></item><item><title>Driving &amp; Keyboard Controllers</title><link>https://cdeever.github.io/atari-vcs/docs/input/other-controllers/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/input/other-controllers/</guid><description>&lt;h1 id="driving--keyboard-controllers"&gt;Driving &amp;amp; Keyboard Controllers&lt;a class="anchor" href="#driving--keyboard-controllers"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The joystick, paddle, and console switches are the common cases — but the same controller ports accept stranger devices, and two are worth knowing because they show how flexible the VCS&amp;rsquo;s I/O really is. The &lt;strong&gt;driving controller&lt;/strong&gt; is a paddle look-alike that isn&amp;rsquo;t analog at all, and the &lt;strong&gt;keyboard controller&lt;/strong&gt; is a twelve-key matrix. Both are built entirely from the &lt;code&gt;SWCHA&lt;/code&gt; and &lt;code&gt;INPT&lt;/code&gt; registers you&amp;rsquo;ve already met.&lt;/p&gt;</description></item><item><title>Front-Loading &amp; Tables</title><link>https://cdeever.github.io/atari-vcs/docs/kernel-techniques/front-loading-and-tables/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/kernel-techniques/front-loading-and-tables/</guid><description>&lt;h1 id="front-loading--tables"&gt;Front-Loading &amp;amp; Tables&lt;a class="anchor" href="#front-loading--tables"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The last way to fit work into a &lt;a href="https://cdeever.github.io/atari-vcs/docs/6502-basics/cycles-and-timing/"&gt;76-cycle line&lt;/a&gt; is to &lt;strong&gt;not do it on that line.&lt;/strong&gt; Two habits push work out of the hot path: &lt;em&gt;front-loading&lt;/em&gt; — computing a line&amp;rsquo;s data before the line needs it — and &lt;em&gt;tables&lt;/em&gt; — computing it before the program even runs. Both trade something plentiful (earlier time, ROM) for something scarce (cycles in the critical window).&lt;/p&gt;
&lt;h2 id="front-loading-be-early"&gt;Front-loading: be early&lt;a class="anchor" href="#front-loading-be-early"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the moment the beam reaches a sprite, you have just a few cycles to put the right byte in &lt;code&gt;GRP0&lt;/code&gt;. If those cycles are also spent &lt;em&gt;deciding&lt;/em&gt; which byte — fetching a pointer, adding an offset, looking up a color — you&amp;rsquo;ll overflow. So you do that deciding &lt;strong&gt;earlier&lt;/strong&gt;, during the slack of the &lt;em&gt;previous&lt;/em&gt; line, and leave only a fast store for the critical instant.&lt;/p&gt;</description></item><item><title>Missiles &amp; the Ball</title><link>https://cdeever.github.io/atari-vcs/docs/sprites/missiles-and-ball/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/sprites/missiles-and-ball/</guid><description>&lt;h1 id="missiles--the-ball"&gt;Missiles &amp;amp; the Ball&lt;a class="anchor" href="#missiles--the-ball"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The other three movable objects — two &lt;strong&gt;missiles&lt;/strong&gt; and one &lt;strong&gt;ball&lt;/strong&gt; — are the TIA&amp;rsquo;s single-bit shapes. They have no bitmap; each is just a solid colored rectangle whose only graphic choice is its &lt;a href="https://cdeever.github.io/atari-vcs/docs/sprites/size-and-copies/"&gt;width&lt;/a&gt;. That makes them cheap to position and toggle, which is exactly what you want for bullets, balls, and small markers.&lt;/p&gt;
&lt;h2 id="the-missiles"&gt;The missiles&lt;a class="anchor" href="#the-missiles"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Missile 0 and missile 1 are turned on by &lt;code&gt;ENAM0&lt;/code&gt; / &lt;code&gt;ENAM1&lt;/code&gt; and positioned with the same &lt;a href="https://cdeever.github.io/atari-vcs/docs/sprites/horizontal-positioning/"&gt;strobe-and-&lt;code&gt;HMOVE&lt;/code&gt;&lt;/a&gt; dance as the players (&lt;code&gt;RESM0&lt;/code&gt;/&lt;code&gt;RESM1&lt;/code&gt;, &lt;code&gt;HMM0&lt;/code&gt;/&lt;code&gt;HMM1&lt;/code&gt;). The catch — and the convenience — is &lt;strong&gt;color&lt;/strong&gt;: a missile has none of its own. &lt;strong&gt;M0 always draws in player 0&amp;rsquo;s color (&lt;code&gt;COLUP0&lt;/code&gt;), M1 in player 1&amp;rsquo;s.&lt;/strong&gt; A missile is, by design, &lt;em&gt;this player&amp;rsquo;s&lt;/em&gt; projectile.&lt;/p&gt;</description></item><item><title>River Raid (1982)</title><link>https://cdeever.github.io/atari-vcs/docs/game-analysis/riverraid/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/game-analysis/riverraid/</guid><description>&lt;h1 id="river-raid-1982"&gt;River Raid (1982)&lt;a class="anchor" href="#river-raid-1982"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;River Raid&lt;/em&gt; — &lt;strong&gt;Carol Shaw&lt;/strong&gt;, Activision — flies a jet up a winding river that never ends: shoot the ships, helicopters, and jets, blow the bridges, and watch the fuel gauge, because the banks keep narrowing. It was one of the best-selling and most acclaimed games of the era, and a landmark for another reason — Shaw was among the first women to design and program a commercial video game, and River Raid is her masterpiece. The disassembly here is Thomas Jentzsch&amp;rsquo;s.&lt;/p&gt;</description></item><item><title>Symmetry: Reflection &amp; Repetition</title><link>https://cdeever.github.io/atari-vcs/docs/playfield/symmetry/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/playfield/symmetry/</guid><description>&lt;h1 id="symmetry-reflection--repetition"&gt;Symmetry: Reflection &amp;amp; Repetition&lt;a class="anchor" href="#symmetry-reflection--repetition"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The &lt;a href="https://cdeever.github.io/atari-vcs/docs/playfield/registers/"&gt;three registers&lt;/a&gt; gave you 20 bits — the &lt;strong&gt;left 20 pixels&lt;/strong&gt; of a 40-pixel-wide screen. You never wrote the other 20. This page is where they come from.&lt;/p&gt;
&lt;p&gt;The TIA &lt;strong&gt;generates the right half automatically&lt;/strong&gt; from those same 20 bits, and a single flag decides whether it does so as a copy or a mirror. That is why the playfield is &lt;em&gt;inherently&lt;/em&gt; symmetric: one write of &lt;code&gt;PF0&lt;/code&gt;/&lt;code&gt;PF1&lt;/code&gt;/&lt;code&gt;PF2&lt;/code&gt; per line paints the whole 40-pixel width, but both halves are built from the same bits.&lt;/p&gt;</description></item><item><title>The Asymmetric Playfield</title><link>https://cdeever.github.io/atari-vcs/docs/playfield/asymmetric/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/playfield/asymmetric/</guid><description>&lt;h1 id="the-asymmetric-playfield"&gt;The Asymmetric Playfield&lt;a class="anchor" href="#the-asymmetric-playfield"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://cdeever.github.io/atari-vcs/docs/playfield/symmetry/"&gt;Symmetry&lt;/a&gt; is the playfield&amp;rsquo;s default because its 20 bits describe only the left half and the TIA mirrors or copies them onto the right. To show two &lt;em&gt;different&lt;/em&gt; things on the two halves — a genuinely &lt;strong&gt;asymmetric playfield&lt;/strong&gt; — you have to break that deal. The escape hatch is timing.&lt;/p&gt;
&lt;h2 id="the-tia-reads-the-registers-as-it-goes"&gt;The TIA reads the registers as it goes&lt;a class="anchor" href="#the-tia-reads-the-registers-as-it-goes"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The crucial fact: the TIA does &lt;strong&gt;not&lt;/strong&gt; snapshot &lt;code&gt;PF0&lt;/code&gt;/&lt;code&gt;PF1&lt;/code&gt;/&lt;code&gt;PF2&lt;/code&gt; at the start of the line. It &lt;strong&gt;reads them continuously as the beam sweeps across&lt;/strong&gt;, consulting each register at the exact moment the beam reaches the pixels it controls. So if you &lt;strong&gt;rewrite the registers partway across the line&lt;/strong&gt; — after the beam has drawn the left half, but before it reaches the right half — the right half is built from the &lt;em&gt;new&lt;/em&gt; values. The two halves now differ.&lt;/p&gt;</description></item><item><title>Building a Scoreboard</title><link>https://cdeever.github.io/atari-vcs/docs/playfield/scoreboard/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/playfield/scoreboard/</guid><description>&lt;h1 id="building-a-scoreboard"&gt;Building a Scoreboard&lt;a class="anchor" href="#building-a-scoreboard"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;A two-player scoreboard is the textbook use of an &lt;a href="https://cdeever.github.io/atari-vcs/docs/playfield/asymmetric/"&gt;asymmetric playfield&lt;/a&gt; — two &lt;em&gt;different&lt;/em&gt; numbers, one on each half of the screen — and it pulls together nearly everything in this chapter: digit graphics drawn from the playfield, bit masking to pack two digits into a byte, the no-multiply &lt;a href="https://cdeever.github.io/atari-vcs/docs/prerequisites/numbers/"&gt;×5 index trick&lt;/a&gt;, and &lt;a href="https://cdeever.github.io/atari-vcs/docs/prerequisites/numbers/"&gt;BCD&lt;/a&gt; arithmetic to keep the count in decimal.&lt;/p&gt;
&lt;blockquote class='book-hint '&gt;
&lt;p&gt;The code here is &lt;strong&gt;illustrative&lt;/strong&gt; — the repository doesn&amp;rsquo;t ship a scoreboard project yet. Treat the snippets as sketches of the technique, not a drop-in kernel.&lt;/p&gt;</description></item><item><title>Object Priority</title><link>https://cdeever.github.io/atari-vcs/docs/sprites/priority/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/sprites/priority/</guid><description>&lt;h1 id="object-priority"&gt;Object Priority&lt;a class="anchor" href="#object-priority"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;When two objects cover the same pixel, one of them has to win — and which one shows in front is &lt;strong&gt;object priority&lt;/strong&gt;. This is a separate question from &lt;a href="https://cdeever.github.io/atari-vcs/docs/collisions/"&gt;collisions&lt;/a&gt;: collision detection only tells you &lt;em&gt;that&lt;/em&gt; two objects overlapped, never which was drawn on top. Priority is what decides the picture.&lt;/p&gt;
&lt;h2 id="the-default-order"&gt;The default order&lt;a class="anchor" href="#the-default-order"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The TIA ranks the six things it can draw in a fixed order. Highest priority is drawn in front:&lt;/p&gt;</description></item><item><title>Should You Extend at All?</title><link>https://cdeever.github.io/atari-vcs/docs/cartridge-hardware/should-you-extend/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/cartridge-hardware/should-you-extend/</guid><description>&lt;h1 id="should-you-extend-at-all"&gt;Should You Extend at All?&lt;a class="anchor" href="#should-you-extend-at-all"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This chapter has watched a cartridge grow from a slab of read-only memory into a machine carrying &lt;a href="https://cdeever.github.io/atari-vcs/docs/cartridge-hardware/arm-cartridges/"&gt;its own ARM computer&lt;/a&gt;. Which leaves an honest question hanging over all of it: &lt;em&gt;just because you can put a supercomputer in the slot, should you?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The clearest way to think about it is to follow one game through three lives.&lt;/p&gt;
&lt;h2 id="three-pac-mans"&gt;Three Pac-Mans&lt;a class="anchor" href="#three-pac-mans"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;1982 — the original.&lt;/strong&gt; Atari handed &lt;em&gt;Pac-Man&lt;/em&gt; to &lt;strong&gt;Tod Frye&lt;/strong&gt; — a capable programmer who&amp;rsquo;d actually wanted &lt;em&gt;Defender&lt;/em&gt; and got Pac-Man by default — under enormous corporate pressure: ship the most-wanted arcade game of the year in time for the holidays, on the cheapest cartridge the company would pay for (a single 4 KB chip), against a deadline that left no room to refine it. The result became the best-selling game on the entire system &lt;em&gt;and&lt;/em&gt; a byword for &lt;em&gt;disappointment&lt;/em&gt; — the ghosts flickered relentlessly, the colors looked nothing like the arcade, the whole thing played like a rough sketch of the real game. Atari pressed something like twelve million copies — more carts than there were consoles to play them — and it turns up in nearly every story told about the 1983 crash. The lesson everyone drew at the time was simple, and wrong: &lt;em&gt;the 2600 just can&amp;rsquo;t do Pac-Man.&lt;/em&gt; The fault was never the programmer&amp;rsquo;s talent; it was the calendar and the boardroom — the very same pressure that, that same year, gave &lt;strong&gt;Howard Scott Warshaw&lt;/strong&gt; about five weeks to make &lt;em&gt;E.T.&lt;/em&gt; and turned the designer of the brilliant &lt;em&gt;Yars&amp;rsquo; Revenge&lt;/em&gt; into the other name blamed for the 1983 crash.&lt;/p&gt;</description></item><item><title>Space Invaders (1980)</title><link>https://cdeever.github.io/atari-vcs/docs/game-analysis/spaceinvaders/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/game-analysis/spaceinvaders/</guid><description>&lt;h1 id="space-invaders-1980"&gt;Space Invaders (1980)&lt;a class="anchor" href="#space-invaders-1980"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;Space Invaders&lt;/em&gt; — &lt;strong&gt;Rick Maurer&lt;/strong&gt;, Atari — was the first officially &lt;strong&gt;licensed arcade game&lt;/strong&gt; to land on a home console, and it changed everything. It was the 2600&amp;rsquo;s &lt;strong&gt;killer app&lt;/strong&gt;: the cartridge people bought the &lt;em&gt;console&lt;/em&gt; in order to play, widely credited with roughly quadrupling hardware sales in 1980 and turning the VCS from a curiosity into a phenomenon. Maurer&amp;rsquo;s port is also a quiet masterclass in TIA economy — it fills the screen with marching aliens using astonishingly little hardware. The disassembly here was produced from the cartridge with &lt;a href="https://cdeever.github.io/atari-vcs/docs/getting-started/toolchain/"&gt;DiStella&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>The Stack &amp; Subroutines</title><link>https://cdeever.github.io/atari-vcs/docs/6502-basics/stack-and-subroutines/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/6502-basics/stack-and-subroutines/</guid><description>&lt;h1 id="the-stack--subroutines"&gt;The Stack &amp;amp; Subroutines&lt;a class="anchor" href="#the-stack--subroutines"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The &lt;strong&gt;stack&lt;/strong&gt; is the 6502&amp;rsquo;s scratch area for return addresses and saved values, and subroutines (&lt;code&gt;JSR&lt;/code&gt;/&lt;code&gt;RTS&lt;/code&gt;) are built on it. On most 6502 systems it&amp;rsquo;s an afterthought. On the VCS it deserves real care, because the stack and your variables &lt;strong&gt;share the same 128 bytes of RAM&lt;/strong&gt; — and can run into each other.&lt;/p&gt;
&lt;h2 id="how-the-stack-works"&gt;How the stack works&lt;a class="anchor" href="#how-the-stack-works"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The stack pointer &lt;strong&gt;S&lt;/strong&gt; is an 8-bit offset into a fixed region, and it grows &lt;em&gt;downward&lt;/em&gt;:&lt;/p&gt;</description></item><item><title>Sprite Multiplexing</title><link>https://cdeever.github.io/atari-vcs/docs/sprites/sprite-multiplexing/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/sprites/sprite-multiplexing/</guid><description>&lt;h1 id="sprite-multiplexing"&gt;Sprite Multiplexing&lt;a class="anchor" href="#sprite-multiplexing"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The TIA gives you &lt;strong&gt;two &lt;a href="https://cdeever.github.io/atari-vcs/docs/sprites/drawing-a-player/"&gt;players&lt;/a&gt;&lt;/strong&gt;, and — unlike ROM or RAM — &lt;em&gt;no &lt;a href="https://cdeever.github.io/atari-vcs/docs/cartridge-hardware/"&gt;cartridge hardware&lt;/a&gt; adds more.&lt;/em&gt; The two-sprite limit is one you beat in &lt;strong&gt;software&lt;/strong&gt;. Yet games routinely show a screen full of enemies, shots, and characters; they do it by &lt;strong&gt;time-sharing&lt;/strong&gt; the two players — reusing each one to be several different things, either down the screen or across frames.&lt;/p&gt;
&lt;h2 id="reuse-down-the-screen"&gt;Reuse down the screen&lt;a class="anchor" href="#reuse-down-the-screen"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The key realization: a player only occupies the scanlines you actually draw it on. If two objects never share a scanline, &lt;strong&gt;one player can be both of them&lt;/strong&gt; — enemy A in the top third of the screen, enemy B in the middle, enemy C at the bottom, all drawn by the &lt;em&gt;same&lt;/em&gt; player 0 in a single kernel.&lt;/p&gt;</description></item><item><title>Video Chess (1979)</title><link>https://cdeever.github.io/atari-vcs/docs/game-analysis/videochess/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/game-analysis/videochess/</guid><description>&lt;h1 id="video-chess-1979"&gt;Video Chess (1979)&lt;a class="anchor" href="#video-chess-1979"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;Video Chess&lt;/em&gt; — &lt;strong&gt;Larry Wagner&lt;/strong&gt; (the chess engine) and &lt;strong&gt;Bob Whitehead&lt;/strong&gt; (the kernel and display), Atari — is the one that shouldn&amp;rsquo;t fit. It is a &lt;strong&gt;real chess program&lt;/strong&gt;: it knows the legal moves, it looks ahead, it plays a whole game against you at eight levels of strength. And it does all of that in &lt;strong&gt;4 KB of ROM and 128 bytes of RAM&lt;/strong&gt; — less working memory than a single line of this paragraph. By legend it almost didn&amp;rsquo;t ship: Atari had advertised a chess cartridge in its earliest VCS catalog, couldn&amp;rsquo;t deliver for a year or two, and — the often-told story goes — a customer&amp;rsquo;s threatened lawsuit over the no-show product is what finally pushed it out the door in 1979.&lt;/p&gt;</description></item><item><title>Cosmic Ark (1982)</title><link>https://cdeever.github.io/atari-vcs/docs/game-analysis/cosmicark/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/game-analysis/cosmicark/</guid><description>&lt;h1 id="cosmic-ark-1982"&gt;Cosmic Ark (1982)&lt;a class="anchor" href="#cosmic-ark-1982"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;Cosmic Ark&lt;/em&gt; — &lt;strong&gt;Rob Fulop&lt;/strong&gt;, Imagic — casts you as a sort of Noah in orbit: a great ark sweeping the galaxy to rescue pairs of animals from dying worlds. It plays in two alternating acts — fend off a meteor storm from the center of the screen, then drop to a planet and lift creatures aboard with a tractor beam. It&amp;rsquo;s a fine game. But it is &lt;em&gt;remembered&lt;/em&gt; for four instructions.&lt;/p&gt;</description></item><item><title>Breakout (1978)</title><link>https://cdeever.github.io/atari-vcs/docs/game-analysis/breakout/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/game-analysis/breakout/</guid><description>&lt;h1 id="breakout-1978"&gt;Breakout (1978)&lt;a class="anchor" href="#breakout-1978"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;Breakout&lt;/em&gt; is where the VCS came from. The 1976 arcade machine was conceived by &lt;strong&gt;Nolan Bushnell&lt;/strong&gt; and &lt;strong&gt;Steve Bristow&lt;/strong&gt; as a one-player &lt;em&gt;Pong&lt;/em&gt; with a wall to chip away at, and the prototype was built — famously, over a few sleepless nights — by &lt;strong&gt;Steve Wozniak&lt;/strong&gt;, with &lt;strong&gt;Steve Jobs&lt;/strong&gt; handling the deal with Atari (and, the story goes, the bonus). The 1978 cartridge brought it home. It is &lt;em&gt;Pong&lt;/em&gt;&amp;rsquo;s child: a ball, a paddle, and a wall of bricks.&lt;/p&gt;</description></item><item><title>Choosing the Chip</title><link>https://cdeever.github.io/atari-vcs/docs/burning-eprom/choosing-the-chip/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/burning-eprom/choosing-the-chip/</guid><description>&lt;h1 id="choosing-the-chip"&gt;Choosing the Chip&lt;a class="anchor" href="#choosing-the-chip"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;&amp;ldquo;EPROM&amp;rdquo; is the traditional name, but you have a few families to pick from, and the choice mostly comes down to &lt;em&gt;how painful it is to reprogram when you find a bug&lt;/em&gt; — and you will find bugs.&lt;/p&gt;
&lt;h2 id="the-three-families"&gt;The three families&lt;a class="anchor" href="#the-three-families"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Family&lt;/th&gt;
 &lt;th&gt;Examples&lt;/th&gt;
 &lt;th&gt;Erase method&lt;/th&gt;
 &lt;th&gt;Reusable?&lt;/th&gt;
 &lt;th&gt;Notes&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;UV EPROM (windowed)&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;2716, 2732, 2764, 27256, 27512&lt;/td&gt;
 &lt;td&gt;UV light (~15–20 min in a UV eraser box)&lt;/td&gt;
 &lt;td&gt;Yes, many times&lt;/td&gt;
 &lt;td&gt;The classic. The quartz window over the die lets a UV eraser box wipe it clean for reuse. Just keep the window covered with a sticker in normal use, or ambient UV slowly corrupts it.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;OTP EPROM (no window)&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;same part numbers, plastic package&lt;/td&gt;
 &lt;td&gt;—&lt;/td&gt;
 &lt;td&gt;&lt;strong&gt;No — one shot&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;Electrically identical die, but the plastic package has &lt;em&gt;no window&lt;/em&gt;, so there&amp;rsquo;s no way to get UV to it. Programs once, then it&amp;rsquo;s permanent. Cheap for production; avoid while iterating.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;EEPROM&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;28C16, 28C64, 28C256&lt;/td&gt;
 &lt;td&gt;Electrically, in the programmer&lt;/td&gt;
 &lt;td&gt;Yes, instantly&lt;/td&gt;
 &lt;td&gt;No UV lamp. Slightly pricier, sometimes slower write, very convenient for iteration.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;&lt;strong&gt;Flash / &amp;ldquo;electrically-erasable EPROM&amp;rdquo;&lt;/strong&gt;&lt;/td&gt;
 &lt;td&gt;W27C512, W27C020 (Winbond), SST39SF&lt;/td&gt;
 &lt;td&gt;Electrically, in the programmer&lt;/td&gt;
 &lt;td&gt;Yes, instantly&lt;/td&gt;
 &lt;td&gt;Cheap, reusable, no UV — the modern homebrew favorite. The Winbond W27C512 is a drop-in-ish 27512 replacement that erases in the programmer.&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;For iterating on a game, pick something electrically erasable&lt;/strong&gt; (EEPROM or a Winbond/SST flash part). Reserve UV EPROMs for when you specifically want the vintage experience or already own a stack of them — the burn → test → &amp;ldquo;oops&amp;rdquo; → 20-minute-erase cycle gets old fast.&lt;/p&gt;</description></item><item><title>Preparing the ROM Image</title><link>https://cdeever.github.io/atari-vcs/docs/burning-eprom/preparing-the-image/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/burning-eprom/preparing-the-image/</guid><description>&lt;h1 id="preparing-the-rom-image"&gt;Preparing the ROM Image&lt;a class="anchor" href="#preparing-the-rom-image"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;The bytes you send to the programmer are not always the bytes DASM emitted. Two things have to be right: the &lt;strong&gt;reset vectors&lt;/strong&gt; must land at the very top of the address the console fetches from, and the image must &lt;strong&gt;fill the chip&lt;/strong&gt; in a way the cartridge wiring expects.&lt;/p&gt;
&lt;h2 id="the-reset-vectors-must-be-at-the-top"&gt;The reset vectors must be at the top&lt;a class="anchor" href="#the-reset-vectors-must-be-at-the-top"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When the console powers on, the 6507 reads its program-counter start address from the reset vector at &lt;code&gt;$FFFC&lt;/code&gt;/&lt;code&gt;$FFFD&lt;/code&gt;. On the cartridge that is the &lt;strong&gt;last two bytes of ROM space&lt;/strong&gt;. Every ROM in this book ends with:&lt;/p&gt;</description></item><item><title>Wiring the Cartridge</title><link>https://cdeever.github.io/atari-vcs/docs/burning-eprom/wiring-the-cartridge/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/burning-eprom/wiring-the-cartridge/</guid><description>&lt;h1 id="wiring-the-cartridge"&gt;Wiring the Cartridge&lt;a class="anchor" href="#wiring-the-cartridge"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;Once the chip is programmed it has to be wired into something the console&amp;rsquo;s cartridge slot can read. This is where the project leaves software and becomes electronics — and where the mistakes stop being syntax errors and start being &lt;em&gt;bus contention&lt;/em&gt; and &lt;em&gt;floating address lines&lt;/em&gt;.&lt;/p&gt;
&lt;blockquote class='book-hint '&gt;
&lt;p&gt;&lt;strong&gt;Strong recommendation:&lt;/strong&gt; copy the connections from a &lt;strong&gt;proven, published cartridge schematic or reproduction PCB&lt;/strong&gt; (AtariAge has well-documented designs) rather than improvising them. The pin-level details below are to help you &lt;em&gt;understand and verify&lt;/em&gt; such a design, not to reverse-engineer one from scratch. This is the one part of the pipeline where &amp;ldquo;close enough&amp;rdquo; produces hardware that intermittently works, which is worse than hardware that never works.&lt;/p&gt;</description></item><item><title>Gotchas: Works in Stella, Dies on Hardware</title><link>https://cdeever.github.io/atari-vcs/docs/burning-eprom/gotchas/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/burning-eprom/gotchas/</guid><description>&lt;h1 id="gotchas-works-in-stella-dies-on-hardware"&gt;Gotchas: Works in Stella, Dies on Hardware&lt;a class="anchor" href="#gotchas-works-in-stella-dies-on-hardware"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This is the page worth bookmarking. The bugs here share a signature: &lt;strong&gt;the game is perfect in the emulator and wrong on the console.&lt;/strong&gt; That signature is diagnostic — it means the fault is in an assumption the emulator papers over, not in your game logic.&lt;/p&gt;
&lt;h2 id="ram-is-not-zero-on-real-hardware"&gt;RAM is not zero on real hardware&lt;a class="anchor" href="#ram-is-not-zero-on-real-hardware"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Stella conveniently clears the 128 bytes of RAM at startup. &lt;strong&gt;A real 6507 powers on with RAM full of random garbage.&lt;/strong&gt; If any of your code reads a variable before writing it — a counter, a flag, a sprite position — it works in Stella (where it read 0) and does something random on hardware.&lt;/p&gt;</description></item><item><title>Further Reading</title><link>https://cdeever.github.io/atari-vcs/docs/further-reading/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://cdeever.github.io/atari-vcs/docs/further-reading/</guid><description>&lt;h1 id="further-reading"&gt;Further Reading&lt;a class="anchor" href="#further-reading"&gt;#&lt;/a&gt;&lt;/h1&gt;
&lt;p&gt;This book aims to be the &lt;em&gt;accessible&lt;/em&gt; path into the VCS — the explanation you read first. For exhaustive, bit-level reference, and for the wider community that keeps this machine alive, these are the sources to reach for next.&lt;/p&gt;
&lt;h2 id="the-stella-programmers-guide"&gt;The Stella Programmer&amp;rsquo;s Guide&lt;a class="anchor" href="#the-stella-programmers-guide"&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The definitive low-level reference: Atari&amp;rsquo;s own internal manual for the TIA and RIOT, written by &lt;strong&gt;Steve Wright in 1979&lt;/strong&gt; (&amp;ldquo;Stella&amp;rdquo; was the VCS&amp;rsquo;s development codename). It is the primary source behind the hardware behavior described throughout this book — and where to turn when you need the things a how-to deliberately leaves out: the complete register address-summary table, the exact &lt;code&gt;AUDC&lt;/code&gt; waveform values, the numeric color/luminance chart, and PAL/SECAM conversion details.&lt;/p&gt;</description></item></channel></rss>