# Visual Basic > Games and Graphics Programming > Game Demos >  Atari 2600 Programming Tutorial 1 - Getting started, Learning the 6502 Assembler

## Jacob Roman

Welcome to my ultimate 2600 Atari 2600 programming tutorial with a sample example that would work not only on an Atari 2600 emulator such as Stella, but also work on a real Atari 2600 if you have the right tools to extract onto a real cartridge.

Now before you begin. You would need to learn basic 6502 assembly. Now before you walk away and be like "screw that", it's actually easier than you think. Much easier. Just looks a wee bit different than what you commonly program on. I too was turned off into learning it as well until I grew some balls and dived into it, only to find it was a lot of fun. So without further a due, lets dive in shall we.  :big yellow: 

*History:*
6502 assembly, believe it or not, was designed for the MOS6502 chip found commonly in old hardware, such as the Apple II, Commodor 64, the Amiga 500, Atari 2600, the Nintendo Entertainment System, etc. It was invented in 1975 and is still used today by hobbyist and homebrewers. At the time, the MOS6502 chip was considered to be the cheapest CPU, and as a result was widely used by computer manufacturers to cut costs. The language itself consists of 56 opcodes and 13 address modes. It also has built in registers such as A (which is an Accumulator), X, and Y. A is commonly used for arithmetic, whereas X and Y is used for counting.

*What is an opcode?:*
An opcode is an instruction, or to be more precise, a built in method. For example, if you want to load the value of 1 into the A register (which looks like this A = 1 in plain English), you would use the instruction *LDA* #1. *LDA* stands for Load Accumulator with a value. The # symbol means you are putting a number there. If you use *LDA* #$01, it would load 1 as a hexidecimal number. If you use *LDA* #%00000001, it would load 1 as a binary number. The accumulator (A) is only 8 bits wide. Which means you can only use values between 0 - 255 or 0 - FF or 00000000 - 11111111. This is considered loading the accumulator immediately, and uses the immediate address mode.

Another thing you can do with *LDA* is load the accumulator with a value from memory. For example you can do *LDA* $80. Assuming theres a value at that memory location, you are storing the accumulator (A) with a value from the memory address $0080. The amount of memory you can access is 64k wide or $0000 to $FFFF. Some are reserved for certain effects depending on the hardware or even software. So you can load important information such as a random number generated, or what pixel color is being stored, etc. $00-$FF is considered to be a zero page address, where as using $0100-$FFFF is considered to be an absolute address.

*Wow thats a lot of information on just one opcode! Are there anymore?:*
Yes there are. 55 more to be exact, but we are only gonna use commonly 10 with these tutorials. Another important opcode would be *STA*, which means to Store the accumulator value to a particular memory address. For example, 



```
LDA #$01
STA $0200
```

This means you are loading the accumulator with the value of 1, and storing that value into the memory location $0200. Now you get to play with these two opcodes on a particular website! Because this will actually plot a white pixel onto the screen. Address $0200 to $05FF will be the entire screen. Their built in assembler has a killer debugger as well so you can see whats going on line by line.

https://skilldrick.github.io/easy6502/

This website will introduce you to more opcodes, and more address modes to those opcodes. But like I said before, you will commonly be using 10 commonly.

*How the heck do I create 16 bit numbers if I'm only limited to 8 bits?:*
This is when things get interesting. You would have to use 2 memory addresses next to each other in order to create bigger numbers. For example, if you want to create the number in hex #$500 and make it into a memory address where you can store a value into, you would do this:



```
LDA #$00       ;Store the value #$00 into the accumulator
STA $00         ;Store the accumulator's value into memory location $00
LDA #$05       ;Store the value #$05 into the accumulator
STA $01         ;Store the accumulator's value into memory location $01

LDY #00        ;Store the value #$00 into the Y register
LDA #$01      ;Load the value #$01 into the accumulator (color white)
STA ($00), Y  ;Indirectly store #$01 into the memory location $0500 we
                     ;created earlier on top!
```

This will plot a pixel at $0500 on screen. But whats this indirect part mean? Indirect Addressing is a little different, but it was a way to access the 16 bit world. We actually just converted a 16 bit number into a real memory address by combing two 8 bit numbers (lower and upper) and put a value there so a pixel appears on screen. With this, you have to wrap the address with parenthesis () if you are using Indirect Addressing Y. If it's X, you would wrap the whole thing. For example *STA* ($00, X). If you were to just use *STA* $00 instead of *STA* ($00), Y, it would do nothing because $00 is still an 8 bit zero page address location. Not the 16 bit location we just created. See for yourself on the emulator on the website. 

You also noticed there's another new opcode you see here such as *LDY*. And it pretty much does the same thing as *LDA* only it loads the Y register with a value. And you can guess there's also a *LDX*. But did you know there's also a *STX* $(memory location) and a *STY* $(memory location)? You guessed it! *STX* stores the value of X into a given memory location and *STY* stores the value of Y into a given memory location. Way to go! You just learned *LDA*, *LDX*, *LDY*, *STA*, *STX*, and *STY*. Now for some arithmetic functions!

*Seriously, how do I do math stuff!*
There are a very limited number of math functions in the 6502 assembly unfortunately, as you can only add, subtract, increment, decrement, and, and or. If you want multiplication, division, square root, sin, cos, etc., they would need to be manually programmed. And theres plently of code online that shows you how.

*ADC* is a commonly used opcode for addition, and stands for add with carry. Carry is one of the flags of the 6502 processor and is only set if the accumulator is over 255. For example, if you do this on this website:



```
LDA #$01
ADC #$02
```

The accumulator will now be 3. But if you do this:



```
LDA #$FF
ADC #$02
```

The accumulator would be 1, yet the carry flag is set. Because it exceeded 255 and started back at the beginning.

*SBC* does the same thing only it subtracts instead of adds.

*INX* increments X by one.

*INY* increments Y by one.

*DEX* decrements X by one.

*DEY* decrements Y by one.

*TAX* transfers the value of A into X. Like X = A

*TAY* transfers the value of A into Y. Like Y = A

*TXA* transfers the value of X into A. Like A = X

*TYA* transfers the value of Y into A. Like A = Y

Now that you understand that, its time to learn sub routines!

*How do I make subs?:*
A sub label is needed to make a sub, and marks a program counter location that can be jumped into any time. For example. Lets take a look at our funky indirect addressing example again, only this time were gonna make a loop!:



```
LDY #00        ;Store the value #$00 into the Y register

MyLoop:
LDA #$00
STA $00
LDA #$05
STA $01

LDA #$01
STA ($00), Y
INY
JMP MyLoop
```

Now run the code on the website. Whoa!!! Did you see that?!! You flooded a good part of the screen from $0500 to $05FF over and over again. You notice there is a *JMP* command there that jumps to any sub routine label you desire. This comes in handy for placing multiple subs into a loop like so:



```

LDX #$00
LDY #$00
JMP MyLoop

MySub1:
;Do stuff here
INX

MySub2:
;Do stuff here
INY

MyLoop:
JMP MySub1
JMP MySub2
JMP MyLoop
```

Pretty cool isn't it?  :big yellow: 

*Ok, but what about IF statements ?:*
Now you are gonna learn about a couple compare commands and branch commands. Compare commands compare if the value matches a specific register, and branch commands act on it whether they are equal, not equal, less than, or greater than. Think of the compare command as the IF, and the branch command as the act, which is a jump to a particular sub routine.

*CMP* compares the value to the accumulator. For example, CMP #$05. You can also compare memory address values, such as CMP $0200.

*CPX* compares the value to the X register. Pretty much nearly the same as above with the X register.

*CPY* compares the value to the Y register. Pretty much nearly the same as above with the Y register.

*BEQ (Sub Label)* jumps to a particular sub if the previous compare statement is equal to the value from the compare statement.



```
LDX #$00
MySub:
INX
CPX #05
BEQ MyOtherSub
JMP MySub

MyOtherSub:
TXA
```

*BNE (Sub Label)* jumps to a particular sub if the previous compare statement is NOT equal to the value from the compare statement.



```
LDX #$00
MySub:
INX
CPX #05
BNE MySub

MyOtherSub:
TXA
```

Now things are bout to get weird. Cause there are signed and unsigned numbers in 6502 believe it or not, but the combination of certain opcodes will test if they are less than, greater than, less than or equal to, and greater than or equal to. Assuming you have two subs HERE and THERE, here is how to do these using other branch opcodes:



```
For unsigned numbers
--------------------------
Operator < : 	
BCC THERE

Operator = : 	
BEQ THERE

Operator > : 	
BEQ HERE
BCS THERE

Operator <= : 	
BCC THERE
BEQ THERE

Operator >= :	
BCS THERE


For signed numbers
--------------------------
Operator < : 	
BMI THERE

Operator = : 	
BEQ THERE

Operator > : 	
BEQ HERE
BPL THERE 

Operator <= : 	
BMI THERE
BEQ THERE

Operator >= :	
BPL THERE
```

Thats it for the basics!!! You are just nearly a step away from making Atari 2600 games! The next examples in later tutorials will be the actual demos well be making, which is why this is located in the Demos page!

For more information on all 56 opcodes: http://www.6502.org/tutorials/6502opcodes.html
Really cool 6502 demos here, including real games!: http://www.6502asm.com/

*Exercise:* Write a program that allows you to plot the X and Y position of a pixel anywhere on screen!

Next tutorial will be your first colored background on the Atari 2600 with a demo  :Wink:

----------


## passel

> ...
> 6502 assembly, believe it or not, was designed for the MOS6502 chip found commonly in old hardware, such as the Apple II, Commodor 64, the Amiga 500, Atari 2600, the Nintendo Entertainment System, etc. ...


The Commodore64 was technically a 6510 cpu, which was a slightly enhanced version of the 6502.
I'm pretty sure the Amiga 500 was a Motorola 68000, which is a much more powerful CPU, with its 24-bit address register (could access 16MB of memory, vs 64K for the 6502), and had 32-bit registers and instructions, so was ahead of its time compared to the other 16-bit processors of the same vintage (i.e. the Zilog Z8000 and Intel 8086).

----------


## Jacob Roman

God I miss my Amiga.  :Frown:

----------


## techgnome

Amigas were the best... way ahead of their time... 

The title sequence, in fact may of their CGI effects, of one of my favorite shows, Bablyon 5, was done on an Amiga-based TV-Toaster...



> In anticipation of future HDTV broadcasts and Laserdisc releases, rather than the usual 4:3 format, the series was shot in 16:9, with the image cropped to 4:3 for initial television transmissions.[77] Babylon 5 also distinguished itself at a time when models and miniature were still standard by becoming one of the first television shows to use computer technology in creating visual effects. This was achieved using Amiga-based Video Toasters at first, and later Pentium, Macs, and Alpha-based systems.[78] It also attempted to respect Newtonian physics in its effects sequences, with particular emphasis on the effects of inertia.[79]


https://en.wikipedia.org/wiki/Babylon_5#Visuals

-tg

----------


## passel

If I hadn't been married I would have bought one for sure.  As it was, I got very close to buying it anyway, so without that consideration it would have been a done deal. I think it probably would have been an Amiga 2000 though as I recall, as it was the latest thing when I was looking at it in 1987.

----------


## Lord Orwell

i used to program in assembly on the commodore 64.  I don't remember there being heaps but then again i was using an assembler and it may have been making things easier.  Side note:  Babylon 5's cgi scenes, all of them, were created on the Video Toaster (not tv toaster) by NewTek.  Newtek had some really horrid graphics demos that ran off of floppy but which encouraged me to buy my amiga 500.  Man i had a lot of crap for that 6-64.  three floppy drives, a replacement vented metal power supply, an expansion port switcher, atari joysticks, about 500 floppies, and my pride and joy, the Final Cartridge III, which had various functions including an alternate graphical desktop (useless really), and 80 column word processor, a two-way scroll for basic, a fast-load for the floppy drives (8x), a dump to disk button on the cartridge (save-state anywhere and copy anything this way), and most importantly, a disassembler/assembler.  Not bad for one cartridge.

----------


## passel

> i used to program in assembly on the commodore 64.  I don't remember there being heaps but then again i was using an assembler and it may have been making things easier. ...


I'm not sure why you brought up the topic of heaps. It wasn't mentioned earlier in the thread.
A heap is a memory allocation scheme that is a higher level concept, so would be implemented as part of a language like C.
You could write a heap manager in assembly as part of your program or perhaps use some support library someone has written to give your assembly code higher level (more abstract) memory access, but a heap is not part of the design of the processor itself.

----------


## GaryMazzone

I loved my old Amiga....  Meet some of the designers once pretty interesting guys.  Best computer I ever owned I still think. Wish more was written for it

----------


## Lord Orwell

i mistyped actually.  I meant registers.

----------


## SheriGoddart75

God, I miss my old AMIGA, its interface and quality. the best I've ever had. and now I don't know such good computer. sadly

----------


## habenero

I guess for me seeing that console - so simple back then so simple right now but really golden Rosetta stone memories

----------

