Results 1 to 11 of 11

Thread: Atari 2600 Programming Tutorial 1 - Getting started, Learning the 6502 Assembler

  1. #1

    Thread Starter
    College Grad!!! Jacob Roman's Avatar
    Join Date
    Aug 2004
    Location
    Miami Beach, FL
    Posts
    5,339

    Atari 2600 Programming Tutorial 1 - Getting started, Learning the 6502 Assembler




    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.

    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,

    Code:
    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:

    Code:
    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:

    Code:
    LDA #$01
    ADC #$02
    The accumulator will now be 3. But if you do this:

    Code:
    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!:

    Code:
    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:

    Code:
    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?

    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.

    Code:
    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.

    Code:
    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:

    Code:
    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

  2. #2
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Atari 2600 Programming Tutorial 1 - Getting started, Learning the 6502 Assembler

    Quote Originally Posted by Jacob Roman View Post
    ...
    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).

  3. #3

    Thread Starter
    College Grad!!! Jacob Roman's Avatar
    Join Date
    Aug 2004
    Location
    Miami Beach, FL
    Posts
    5,339

    Re: Atari 2600 Programming Tutorial 1 - Getting started, Learning the 6502 Assembler

    God I miss my Amiga.

  4. #4
    Smooth Moperator techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,531

    Re: Atari 2600 Programming Tutorial 1 - Getting started, Learning the 6502 Assembler

    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
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  5. #5
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Atari 2600 Programming Tutorial 1 - Getting started, Learning the 6502 Assembler

    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.

  6. #6
    coder. Lord Orwell's Avatar
    Join Date
    Feb 2001
    Location
    Elberfeld, IN
    Posts
    7,621

    Re: Atari 2600 Programming Tutorial 1 - Getting started, Learning the 6502 Assembler

    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.
    My light show youtube page (it's made the news) www.youtube.com/@artnet2twinkly
    Contact me on the socials www.facebook.com/lordorwell

  7. #7
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: Atari 2600 Programming Tutorial 1 - Getting started, Learning the 6502 Assembler

    Quote Originally Posted by Lord Orwell View Post
    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.

  8. #8
    A SQL Server fool GaryMazzone's Avatar
    Join Date
    Aug 2005
    Location
    Dover,NH
    Posts
    7,495

    Re: Atari 2600 Programming Tutorial 1 - Getting started, Learning the 6502 Assembler

    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
    Sometimes the Programmer
    Sometimes the DBA

    Mazz1

  9. #9
    coder. Lord Orwell's Avatar
    Join Date
    Feb 2001
    Location
    Elberfeld, IN
    Posts
    7,621

    Re: Atari 2600 Programming Tutorial 1 - Getting started, Learning the 6502 Assembler

    i mistyped actually. I meant registers.
    My light show youtube page (it's made the news) www.youtube.com/@artnet2twinkly
    Contact me on the socials www.facebook.com/lordorwell

  10. #10
    New Member
    Join Date
    Sep 2020
    Location
    USA
    Posts
    4

    Re: Atari 2600 Programming Tutorial 1 - Getting started, Learning the 6502 Assembler

    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

  11. #11
    Addicted Member habenero's Avatar
    Join Date
    Aug 2015
    Posts
    224

    Re: Atari 2600 Programming Tutorial 1 - Getting started, Learning the 6502 Assembler

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

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width