Post on 19-Jun-2015
description
game program™ATARI 2600
PROGRAMMINGUse with Keyboard Controllers
PROGRAM CONTENTS 2011-2013 CHESTER, INC.
©
What
An overview of the Atari 2600 architecture, covering everything
needed to create a “Hello, World!” program that can run on emulators
or even on a real Atari
http://slideshare.net/chesterbr
Why● Pure nostalgia● Homebrew games● Demoscene● Appreciate masterworks such as Enduro, Pitfall! or River Raid● Feel better about today's tools
and hardware limitations :-)
http://slideshare.net/chesterbr
Atari 2600(Video Computer System)
Over 600 titles...imagem: mitchelaneous.com
but why were they so... “Atari-ish”?
Let's look inside and find out!(Atari 2600 Jr. printed circuit board)
CPU: 6507
CPU: 65076502
(same thing software-wise, and way more info available)
Video: TIA
Everything else: RIOT (6532)
Look ma, no O.S.!
Atari programs talk directly to the hardware – there is no middle man!
Its 6502 CPU only “understands” memory reads and writes, so all the other chips are hard-wired to act as
memory (even those who aren't)
Memory Map(very, very, very simplified*)
0000-002C – TIA (write)0030-003D – TIA (read)0080-00FF – RIOT (RAM)0280-0297 – RIOT (I/O, Timer)F000-FFFF – Cartridge (ROM)
*http://nocash.emubase.de/2k6specs.htm
Memory Map
F000-FFFF – Cartridge (ROM)
(this is not your biggest problem...)
4 KBytes!
Memory Map
0080-00FF – RIOT (RAM)
(and still not your biggest problem)
128 BYTES!!!!!(1/8 of a KB)
VRAM(frame buffer)
Typical video chips translatebit patterns stored on Video RAM
(VRAM) into pixels and colors
VRAMVRAM
VRAM
3844447C4444EE00
VRAM
Screen resolution and color depthare subject to VRAM size limits
Memory was expensive on the 70s/80s, leading to trade-offs
How much VRAM does an Atari have?
Memory Map
0000-002C – TIA (write)0030-003D – TIA (read)0080-00FF – RIOT (RAM)0280-0297 – RIOT (I/O, Timer)F000-FFFF – Cartridge (ROM)
Memory Map
????-???? – VRAM
Memory Map
0 bytes !!!!
????-???? – VRAM
right, now yougot a problem...
Racing the Beam
Since we can't just write pixels to some VRAM frame buffer, our code will need to work a bit closer to
the TV hardware, with a little help from a very unique chip...
TIA(Television Interface Adaptor)
Scanlines
public domain illustration by Ian Harvey
60 framesper second
(NTSCstandard)
TIA is scanline-oriented
As the beam draws each scanline, the game program must set TIA registers to configure the objects drawn on it
Most of this objects have only one color, making multiple colors on the
same scanline theoretically impossible...
...which explains:
vs.
constraints ⇒ creativity
vs.
Screen Objects
● Playfield (PF)● Players (P0, P1)● Missiles/Ball (M0, M1, BL)
Scanlines will be rendered based on how we configure TIA's screen objects:
Playfield (PF)
20-bit pattern with a foreground and a background color, rendered
over the left side of the scanline
The right side will either repeat or refect the same pattern (the later generating a symmetrical image)
PLAYFIELD
PLAYFIELD
PLAYFIELD
PLAYFIELD
Playfield configuration
PF0 = 0000 ←← orderPF1 = 00000000 order →→PF2 = 00000000 ←← orderREFLECT = 0
resulting scanline
Playfield configuration
PF0 = 0001 ←← orderPF1 = 00000000 order →→PF2 = 00000000 ←← orderREFLECT = 0
resulting scanline_ _
Playfield configuration
PF0 = 0011 ←← orderPF1 = 00000000 order →→PF2 = 00000000 ←← orderREFLECT = 0
resulting scanline__ __
Playfield configuration
PF0 = 0111 ←← orderPF1 = 00000000 order →→PF2 = 00000000 ←← orderREFLECT = 0
resulting scanline___ ___
Playfield configuration
PF0 = 1111 ←← orderPF1 = 11110000 order →→PF2 = 00000000 ←← orderREFLECT = 0
resulting scanline________ _______
Playfield configuration
PF0 = 1111 ←← orderPF1 = 11111110 order →→PF2 = 00010101 ←← orderREFLECT = 0
resulting scanline___________ _ _ _ ___________ _ _ _
Playfield configuration
PF0 = 1111 ←← orderPF1 = 11111110 order →→PF2 = 00010101 ←← orderREFLECT = 1
resulting scanline___________ _ _ _ _ _ _ ___________
___________ _ _ _ _ _ _ ___________
Players (P0, P1)Each one is an independent 8 bit pattern (GRP0/GRP1) with a foreground color
(COLUP0 / COLUP1) that can be positioned at any column of the scanline
e.g.: 10100001 → ████████
PLAYERS
PLAYERS
Players
Each player can be horizontally stretched, multiplied or inverted by
setting NUSIZn / REFPn (n=0/1)
(number/size and reflect player)
NUSIZ0 (or NUSIZ1)000001010011100101110111
NU
SIZ
n
With REFP0 (or REFP1) on000001010011100101110111
NU
SIZ
n
NUSIZn
NUSIZn
NUSIZn
NUSIZn
NUSIZn
Missiles/Ball (M0/M1/BL)
Can be positioned just like players, but no bit pattern, just a pixel (although it can be horizontally stretched 2/4/8x)
M0/M1 use P0/P1colors, whileBL uses the PF foreground color
MISSILES
BALL
BALL
BALL
MISSILE
BALL
MISSILE
Master Plan
For each scanline, configure the options for each object before the beam reaches its intended position
The time slot is very short, forcing programmers to pick and choose what to change, reusing as much as they can
How short?
6502 ≈ 1,19Mhz (1.194.720 cycles/sec)NTSC: 60 frames per second
1.194.720/60 ≅ 19.912 cycles per frame
How short?
CPU: 19.912 cyles per frameNTSC: 262 scanlines per frame
19.912 / 262 = 76 cycles per scanline
How short?
CPU: 19.912 cyles per frameNTSC: 262 scanlines per frame
19.912 / 262 = 76 cycles per scanline
and what can we do with 76 cycles?(by the way: WTF is a “cycle”?)
Assembly 6502
6502
6502 (Atari-wise)
Reads a program from the cartridge (ROM) composed of operations that
manipulate and transfer bytes between cartridge, RIOT (RAM, I/O, timers) and TIA, keeping state on internal registers
Operations
Each operation that composes a 6502 program in memory is identified by a1-byte opcode and can be followed
by up to 2 bytes of parameters
An instruction can take up to 6cycles to be executed
Registers
A = Accumulator (8 bits)X, Y= Indexes (8 bits)
S = Stack Pointer (8 bits)P = Status (fags, 8 bits)PC = Program Counter (16 bits)
Example program
“add 2 to a value stored at a memory position; store the result into another memory position”
Implementation
● Read the byte stored on memoryposition 0200 into register A
● Add 2 to register A's value
● Write register A's value into memory position 0201
6502 Machine CodeAD Opcode (Memory → A)00 Last part of “0200”02 First part of “0200”69 Opcode (value + A → A)02 Value to add8D Opcode (A → Memory)01 Last part of “0201”02 First part of “0201”
6502 Assembly Language
Associates the 151 opcodes with 56 mnnemonic instructions
and a notation for their parameters (access mode)
6502 Machine CodeAD Opcode (Memory → A)00 Last part of “0200”02 First part of “0200”69 Opcode (value + A → A)02 Value to add8D Opcode (A → Memory)01 Last part of “0201”02 First part of “0201”
Assembly 6502AD LDA $0200000269 ADC #02028D STA $02010102
AssemblerProgram that reads a text file
written in Assembly language and assembles a binary file with the corresponding machine code
foo.asm
LDA $0200ADC #02STA $0201...
foo.bin
AD000269028D0102...
ASSEMBLER
Macro Assembler
ORG $0100 ; Start @ memory 0100 ... SomeLabel:
LDX #$10 ; No idea where thisDEX ; will be in memory,BNE SomeLabel ; and don't need to!...
DASM
● 6502 Macro Assembler● Includes Atari headers● Multiplataform● Free and open-source (GPLv2)
http://dasm-dillon.sourceforge.net/
Notation (for today)
#... = decimal value #$... = hex value $... = hex address $... , X = hex address + X
http://www.obelisk.demon.co.uk/6502/addressing.html
6502 Instruction Set = most relevant for Atari 2600 programming
Data Transfer
LDA, LDX, LDY = LoadSTA, STX, STY = StoreTAX, TAY, TXA,TYA, TSX, TXS = Transfer
LDA #$10 0x10→A STY $0200 Y→m(0x0200)TXA X→A
ArithmeticADC, SBC = +,- (w/ carry)INC, INX, INY = ++DEC, DEX, DEY = --
ADC $0100 m(0x100)+A→A INC $0200 m(0x200)+1→
m(0x200)DEX X-1→X
Bit Operations
AND, ORA, EOR = &, |, ^ (A) ASL, LSR = Arithmetic shiftROL, ROR = “Rotating” shift
AND #$11 A&0x11→ALSR A>>1→A (A/2→A)ROR A>>1 (bit 7=carry)
Comparing / Branching
CMP, CPX, CPY = compare A/X/Y (-)BCS, BCC = ⇗ if carry set / clearBEQ, BNE = ⇗ if equal / not equalBVS, BVC = ⇗ if overfow set / clearBMI, BPL = ⇗ if minus / plus
CPY $1234 if y=m(0x1234),BEQ $0200 0x0200→PC
Stack and Subroutines
JSR, RTS = call/return subroutinePHA, PLA = push / pull APHP, PLP = push / pull status (P)
JSR $1234 PC(+3)→stack,0x1234→PC
RTS stack→PC
Everything else...
NOP = No OperationJMP = Direct Jump (GOTO)SEC, CLC = Set/Clear CarrySEV, CLV = Set/Clear oVerfowSEI, CLI = Set/Clear Interrupt-offSED, CLD = Set/Clear DecimalRTI = Return from InterruptBRK = Break
Neo: “I know kung fu.”Morpheus: “Show me.”
© 1999 Warner Bros
Hello, World!
Hello, World!
Horizontal writing is hard(too many pixels per scanline)
Hello, World!
Vertical writingis the way →
(less pixels/scanline)
We can use a playeror the playfield
Hello, World!
Our display kernel will configure each pair of visible scanlines with a byte
from a “hello world” bitmap (stored on the cart, just after the code)
Let's find which are visible, and how we need to deal with TV timings
Source: Stella Programmers Guide, Steve Wright, 1979
GA
ME
LOG
IC(3
+37
+30
).76
= 5
320
cycl
esK
ERN
E L
Program structureVertical Sync
Vertical Blank
Overscan
Playfield
main loop
(infinite)Kernel
X: count 0 to 191(192 scanlines)
Program structureVertical Sync
Vertical Blank
Overscan
11 chars *8 bytes *
2 scanlines per byte =
176 scanlines
Program structure
Vertical Sync
Vertical Blank
Kernel
Overscan
Let's begin!
PROCESSOR 6502INCLUDE "vcs.h"
ORG $F000 ; Cart begins here
Vertical Sync
Vertical Blank
Kernel
Overscan
Frame (main loop) start
StartFrame:lda #%00000010 ; Signal VSYNC start bysta VSYNC ; setting bit 1REPEAT 3 ; lasts 3 scanlines
sta WSYNC ; (WSYNC = wait until REPEND ; scanline is finished)lda #0 ; Signal VSYNC end (and sta VSYNC ; VBLANK start)
Vertical Sync
Vertical Blank
Kernel
Overscan
Vertical Blank
PreparePlayfield:lda #$00
sta ENABL ; Disable ball sta ENAM0 ; Disable missiles sta ENAM1 sta GRP0 ; Disable players sta GRP1 ; (with a 0s-only shape)
Vertical Sync
Vertical Blank
Kernel
Overscan
Vertical Blank
sta COLUBK ; Background (0=preto) sta PF0 ; PF0 and PF2 stay off sta PF2 lda #$FF ; Playfield color sta COLUPF ; (yellow-ish) lda #$00 ; Clear CTRLPF bit 0 to sta CTRLPF ; repeat playfield ldx #0 ; X: scanline counter
Vertical Sync
Vertical Blank
Kernel
Overscan
Finish Vertical Blank
REPEAT 37 ; VBLANK lasts 37 scanlinessta WSYNC ; (useful for game logic)
REPEND ; lda #0 ; Signals VBLANK end (willsta VBLANK ; “turn on the beam”)
Vertical Sync
Vertical Blank
Kernel
Overscan
Scanline (inner loop)
Scanline:cpx #174 ; Phrase over? bcs ScanlineEnd; if so, skip
txa ; Y=X÷2 (logic shift →lsr ; divides A by 2)tay ; lda Phrase,y ; label,Y = mem[label+Y] sta PF1 ; PF1 = playfield (bits
; 4 to 11)Vertical Sync
Vertical Blank
Kernel
Overscan
Scanline (close inner loop)
ScanlineEnd:sta WSYNC ; Finish current scanline inx ; X=line counter cpx #191 ; last visible scanline? bne Scanline ; unless so, repeat!
Vertical Sync
Vertical Blank
Kernel
Overscan
Overscan (close main loop)
Overscan:lda #%00000010 ; “turn off” beam againsta VBLANK ; 30 scanlines ofREPEAT 30 ; overscan...
sta WSYNCREPENDjmp StartFrame ; ...and start it over,
; forever and ever!Vertical Sync
Vertical Blank
Kernel
Overscan
Hello...
Phrase:.BYTE %00000000 ; H.BYTE %01000010.BYTE %01111110.BYTE %01000010.BYTE %01000010.BYTE %01000010.BYTE %00000000.BYTE %00000000 ; E.BYTE %01111110
...
...world
....BYTE %00000000 ; D.BYTE %01111000.BYTE %01000100.BYTE %01000010.BYTE %01000010.BYTE %01000100.BYTE %01111000.BYTE %00000000 ; PF1 last value (!)
6502 configuration
ORG $FFFA ; Located at the end; of ROM (cart)
.WORD FrameStart ; NMI address
.WORD FrameStart ; BOOT address
.WORD FrameStart ; BRK address
END
Assemble!dasm source.asm -ocart.bin -f3
http://stella.sourceforge.net/
Advanced Tricks
Playfield-based score
Playfield-based score
The PF color can be replaced with player colors (P0 = left side; P1 = right side) by turning CTRLPF's
score mode bit on
PLAYERS' COLORS
(how could this improve our Hello World?)
(how could this improve our Hello World?)
Playfield-based score
Q: How can different patterns be shown at each side of the playfield?
A: Change the pattern when the beam is halfway through the scanline
(“race the beam”)
beam
...and you have a different shapeat the other half!
Large worlds
Pitfall!
http://pitfallharry.tripod.com/MapRoom/PitfallMap.html
Pitfall!
Screen configuration (logs, vines, trees, stairs, crocs) was squeezedinto a single byte, but 255 screens(bytes) are still a huge ROM table
(for Atari standards)
http://pitfallharry.tripod.com/MapRoom/PitfallMap.html
Pitfall!
David Crane implemented a sequence generator (LFSR), which, for a given value, would give the previous/next ones, replacing the 255-byte table
with a 50-byte piece of code
http://en.wikipedia.org/wiki/Linear_feedback_shift_register
River Raid
River Raid
Carol Shaw had used a 16-bit generator, resulting in thousands of non-repeating river sectors (tweaking the interpreter
to make the first few ones easier)
When a player loses a life, rendering restarts from the last generated number,
that is, back on the last bridge
Horizontal positioning
Horizontal positioning
The horizontal position of a player / missile / ball is not a writable register
Games must sync to with the beam and write to the appropriate strobe register
when it is on the desired location
STROBE TARGETS(in theory)
You can calculate...
1 CPU cycle = 3 “color clocks” (pixels)Horizontal Blank = 22.6 cycles
horiz. position ≈ (cycles – 22.6) * 3
...but it is an estimate, because TIA only reads its registers every 5 CPU cycles
Smooth ↔ movement is also hard
AlternativesA 4-bit register allows moving a player, missile or ball relative to its previous
position (adding -7 to +8 pixels)
The missile can also be reset to the middle of its player, making it easy to
“fire” it over and over
STROBE TARGETS
VERTICAL MOVEMENTJust start on a different scanline at each frame
HORIZONTAL MOVEMENTstrobe registers HMP0/1 e HMM0/1
Multi-digit score
Multi-digit score
The trick is the same of the playfield-based score (change the registers while the beam is drawing the scanline), but timing is much more of an issue here
Let's say the score is 456789...
Multi-digit scoreBegin the scanline with the bits for 4 on GRP0 and those for 5 on GRP1
Configure NUSIZ0 and NUSIZ1 fora triple repetition:
4 4 4 5 5 5
Player 0 Player 1
Multi-digit score
Set player 1 position just to the right of player 0, overlapping the triplets
454545
Player 0
Player 1
Multi-digit score
Change the patterns (GRP0/GRP1) syncing with the beam, like this:
BEAM
454545
Multi-digit score
When the beam is about to finish player 1's 1st copy, change player 0 to
6 and player 1 to 7:
BEAM
454545
Multi-digit score
Repeat the trick after the 2nd player 2 copy, this time changing player 0 to 8
and player 1 to 9
BEAM
456767
Multi-digit score
Repeat it for each scanline.Easy! #not
BEAM
456789
Multi-digit score
There are other hurdles: we can't load replaced digits from memory, and we
only have 3 memory-writable registers to store 6 bit patterns...
...and that is why it is fun!
Final Words
A new look to the old school
Knowing what the Atari 2600 was designed to do, we can appreciate
games that push it beyond its limitsby identifying “impossible” things
It is just the beginning!
The Atari homebrew scene is alive and kicking, and these are the basics you
need to create your own games/demos
There are several uncovered topics (sound, timers, collision, I/O...), but with
time and dedication, you can do it!
To learn moreHello, World: https://gist.github.com/chesterbr/5864935 Sorteio 2600 http://github.com/chesterbr/sorteio2600Racing The Beam (book): http://bit.ly/dSqhjS David Crane's talk: http://youtu.be/MBT1OK6VAIU David Crane's iOS tutorials: http://bit.ly/9pwYHs and http://bit.ly/qWBciZ Stella Programmer's Guide: http://emu-docs.org/?page=Atari%202600Classic games disassembled: http://classicdev.org/wiki/2600/Source_Code Atari 2600 specs: http://nocash.emubase.de/2k6specs.htm 6502 reference: http://bit.ly/hxG5c6 In-browser emulator: http://jogosdeatari.com.br/ Andrew Dave's tutorial: http://bit.ly/ptQDdA (the whole site is great)Harmony (SD-reader cart): http://harmony.atariage.com/BAtari (BASIC compiler): http://bataribasic.comTIA sound examples: http://bit.ly/tnbPrp Bankswitching (more ROM/RAM): http://bit.ly/tqhLZk
Questions?Thank you!
@chesterbr
http://slideshare.net/chesterbrhttp://chester.me
Credits and LicenseThis presentation is available under the licença Creative Commons “by-nc” 3.0 l,
noticing the exceptions below
Images from third parties were included (with due credits) underfair use assumption and/or under their respective licenses.
These are excluded from the license above.
Atari™, Adventure™, Donkey Kong™, Pitfall™, Super Mario™ and likewise characters/games/systems are mentioned uniquely for
illustrative purposes, also under fair use assumption. They are property of their rights holders, and are also excluded from the license above.