Useful
Inventions
Favorite
Quotes
Game
Design
Atari
Memories
Personal
Pages

Atari 2600 Programming for Newbies

Session 21: Sprites

By Andrew Davie (adapted by Duane Alan Hahn)

Table of Contents

Original Session

It's time to begin our understanding of sprites.

 

What are sprites? By now, sprites are well-known in the gaming industry. They are small, independently movable objects which are drawn by hardware anywhere over the top of playfield graphics. The Atari 2600 was the first console to introduce general-purpose spritesback in the day they were called 'player missile graphics'. It was the Commodore 64 which introduced the term 'sprites', which we know and love.

 

The Atari 2600 has two 'players', two 'missiles' and a 'ball'all of these are sprites, and each has various parameters which can be adjusted by the programmer (position, size, color, shape, etc). We're going to concentrate, this session, on the 'players' and how they work.

 

Player graphics have much finer resolution than playfield graphics. Each player is 8 pixels wide, and each pixel in a player is just a single TIA color-clock in width. In other words, the pixels in player graphics are a quarter of the width of the pixels in playfield graphics. The graphics of each player are controlled by a single 8-bit TIA register. The register for player 0 (the first player) is GRP0 (standing for 'Graphics, Player 0') and the register for the second player is GRP1. When you write data to either of these registers you change the visuals of the relevant player sprite being drawn on the screen.

 

Just like playfield graphics, the player graphics registers only hold a single 'line' of data. If you do not modify the data on-the-fly (that is, changing it every scanline), then the TIA just displays the same data on every scanline. So kernels using sprite graphics typically modify these player graphics registers constantly.

 

Surprisingly, though player sprites can be (effectively) positioned anywhere on the screen, they do NOT have position registers. Most more modern machines (Nintendo, C64, etc.) provided an x,y coordinate which was used to position a sprite on the screen. The Atari 2600 is a much more primitive beast.

 

The horizontal position of a player sprite is controlled by writing to a 'reset position' register (RESP0 for sprite 0 and RESP1 for sprite 1). When you write to these registers, you cause the hardware to begin drawing the relevant sprite . . . immediately! This is very strange and a bit hard to get used to at first. To move a sprite horizontally to any x-position on a scanline, one has to make sure that the RESP0 write happens just before the position on the scanline at which you want the sprite to appear. Since the 6502 is running at 1/3 of the clock speed of the TIA, this makes it incredibly difficult to write to RESP0 at exactly the right time. For every cycle of 6502 time, three pixels (cycles of TIA time) pass. So it's only possible to position sprites (through RESPx writes) with an accuracy of 1 6502 clock period, or in other words three TIA pixels.

 

To facilitate fine-positioning of sprites, the TIA has additional registers which allow the sprite to be adjusted in position by a few pixels. We are not going to cover that this sessionbut instead we'll have a look at how sprite graphics are written, how the course RESPx registers are used, and how sprite colors are controlled. Fine positioning of sprites is an art in itself, and many solutions have been proposed on the [stella] list. We'll get to that in a session or two, but for now, let's stick with the basics.

 

The sample kernel shows a fully working sprite demo.

 

There are very few additions from our earlier playfield demos. . .


                lda #$56

                sta COLUP0

                lda #$67

                sta COLUP1

In our initialization (before the main frame loop) the above code is initializing the colors of the two player sprites. These are random purplish colors. You may also change the color on-the-fly by rewriting it every scanline. Remember, thoughyou only have 76 cycles per scanlineso there's only so much you can cram into a single line before you run out of 'space'.


MiddleLines     



                SLEEP 20



                sta RESP0



                SLEEP 10

                sta RESP1



                stx GRP0               ; modify sprite 0 shape

                stx GRP1



                sta WSYNC

                inx



                cpx #184

                bne MiddleLines

The above code sample is the 'guts' of our sprite demo. It doesn't do a lot of new stuff. You should already be familiar with the SLEEP macroit just causes a delay of a certain number of 6502 cycles. The purpose of the SLEEP macros here is to delay to a position somewhere in the middle of the scanlineyou may play with the values and see the effect on the positioning of the sprites.

 

Immediately after each SLEEP, there's a write to RESPx for each of the player sprites. This causes the TIA to begin drawing the appropriate player sprite immediately. And what will it draw?


                stx GRP0               ; modify sprite 0 shape

                stx GRP1

Since, in this kernel, the x register is counting the scanline number, that is also the value written to both of the graphics registers (GRPx) for the player sprites. So the graphics we see will change on each scanline, and it will represent a visual image of the scanline counter. This should be pretty evident by the image below:

Here's the sample kernel:

kernel_21.zip

 

 

 

 

 

Summary

That's pretty much all there is to getting sprites up and running. There are a few interesting things we need to cover in the coming sessions, including sprite size, sprite repeating, priorities, buffered sprite drawing, drawing specific images/shapes and lots of other stuff. But now you have the basics, and you should be able to do some experimenting with what you see here.

 

See you next time!

 

 

 

 

 

Exercises

  1. Modify the kernel so that the color of the sprite is changed every scanline. How many cycles does this add to your kernel? How many cycles total is each of your lines taking now?
  2. It takes 3 cycles per write to a color register (eg: stx COLUP1), but it takes two or more additional cycles if you want to load a specific color. The variation in time depends on the addressing mode you use to load the color (eg: an immediate value = 2 cycles, but loading indirectly through a zero page pointer to a memory location, indexed by the y register, would take 6 cycles!).

    
        lda #34         ; 2
    
        sta COLUP1      ; 3
    
    
    
    
    
        lda (colour),y  ; 6
    
        sta COLUP1      ; 3
    
    
  3. Instead of using the scanline to write the shape of the sprite, load the shape from a table. Can you think how it would be possible to draw (say) a Mario-shaped sprite anywhere on the screen? This is tricky, so we'll devote a session or more to vertical positioning.
  4. This really is too tricky to answer here. Future sessions will cover this problem thoroughly, as its fundamental to drawing sprites in your game.

  5. What happens when you use more than 76 cycles on a linehow will this code misbehave?
  6. Remember that the TIA and the TV beam are in synch. The timing is such that precisely 76 cycles of 6502 time, or 228 cycles of TIA time, correspond to *exactly* one scanline on the TV. Currently we've been using "sta WSYNC" to synchronize our kernel to the start of every scanline. This isn't necessary IF our code makes sure that our kernel lines take EXACTLY 76 cycles to execute.

     

    But since the above code DOES use "sta WSYNC", a 3 cycle instruction, we really only have 73 cycles per line available for other processing. If we exceed these 73 cycles, then that pushes the "sta WSYNC" past the point at which it's on the current scanline and onto the point where it's really on the NEXT scanline. And if it happens on the NEXT scanline, it will operate as expected (and that, as we know, is by halting the 6502 until the start of the NEXT scanline).

     

    So essentially, if our code exceeds 76 cycles, then each scanline will actually be two scanlines deep! And instead of sending, say, 262 scanlines per frame, we'd be sending 524. Most TVs cannot cope with this and they will, as noted, 'roll'. I just wanted you to understand WHY.

  7. The picture shows sprites over the 'border' areas at top and bottom, yet the code which draws sprites is only active for the middle section. Why is this happening? How would you prevent it?
  8. A good lesson in how the TIA works. The TIA registers hold whatever you put into them, until you next put something in to them. So after our last write to the sprite registers, the TIA keeps displaying the same shape for sprites, on each scanline, until we write again. So what we're really seeing in those border areas is the last write (which is actually at the bottom of the changing shape area of sprites) repeated on the bottom, and then on the top again, until we start writing sprite shapes again.

     

    The solution is to write 0 to GRP0 and GRP1 when we've finished drawing our spritesand, of course, on initialization of the system.

  9. Move the SLEEP and RESPx code outside the middle loopplace this code BEFORE the loop. What differences would you expect to see? Is the result surprising?
  10. Barring minor timing changes which will cause the positions to shift slightly, the effect I was trying to show was that it is not necessary to rewrite the RESPx registers every scanline. You only need to position your sprites once each, and they will remain in that position until you reposition them. By moving the reposition outside the loop, we've freed up extra cycles in the kernel code for each scanline.

     

    Positioning sprites to any arbitrary horizontal position is quite complex, and usually takes at least one whole scanline to do in a generic fashion. This is why games which use multiple sprites rarely allow those sprites to cross over each other, and also the reason why you see distinct 'bands' of sprites in other gamesthe gaps between the bands is where the horizontal movement code is doing its stuff.

 

 

 

Other Assembly Language Tutorials

Be sure to check out the other assembly language tutorials and the general programming pages on this web site.

 

 

< Previous Session

 

 

Next Session >

 

 

 

 

Session Links

Session 1: Start Here

Session 2: Television Display Basics

Sessions 3 & 6: The TIA and the 6502

Session 4: The TIA

Session 5: Memory Architecture

Session 7: The TV and our Kernel

Session 8: Our First Kernel

Session 9: 6502 and DASM - Assembling the Basics

Session 10: Orgasm

Session 11: Colorful Colors

Session 12: Initialization

Session 13: Playfield Basics

Session 14: Playfield Weirdness

Session 15: Playfield Continued

Session 16: Letting the Assembler do the Work

Sessions 17 & 18: Asymmetrical Playfields (Parts 1 & 2)

Session 19: Addressing Modes

Session 20: Asymmetrical Playfields (Part 3)

Session 21: Sprites

Session 22: Sprites, Horizontal Positioning (Part 1)

Session 23: Moving Sprites Vertically

Session 24: Some Nice Code

Session 25: Advanced Timeslicing

 

 

 

 

Useful Links

Easy 6502 by Nick Morgan

How to get started writing 6502 assembly language. Includes a JavaScript 6502 assembler and simulator.

 

 

Atari Roots by Mark Andrews (Online Book)

This book was written in English, not computerese. It's written for Atari users, not for professional programmers (though they might find it useful).

 

 

Machine Language For Beginners by Richard Mansfield (Online Book)

This book only assumes a working knowledge of BASIC. It was designed to speak directly to the amateur programmer, the part-time computerist. It should help you make the transition from BASIC to machine language with relative ease.

 

 

The Second Book Of Machine Language by Richard Mansfield (Online Book)

This book shows how to put together a large machine language program. All of the fundamentals were covered in Machine Language for Beginners. What remains is to put the rules to use by constructing a working program, to take the theory into the field and show how machine language is done.

 

 

6502 Instruction Set with Examples

A useful page from Assembly Language Programming for the Atari Computers.

 

 

6502.org

Continually strives to remain the largest and most complete source for 6502-related information in the world.

 

 

Guide to 6502 Assembly Language Programming by Andrew Jacobs

Below are direct links to the most important pages.

 

 

Stella Programmer's Guide

HTMLified version.

 

 

Nick Bensema's Guide to Cycle Counting on the Atari 2600

Cycle counting is an important aspect of Atari 2600 programming. It makes possible the positioning of sprites, the drawing of six-digit scores, non-mirrored playfield graphics and many other cool TIA tricks that keep every game from looking like Combat.

 

 

How to Draw A Playfield by Nick Bensema

Atari 2600 programming is different from any other kind of programming in many ways. Just one of these ways is the flow of the program.

 

 

Cart Sizes and Bankswitching Methods by Kevin Horton

The "bankswitching bible." Also check out the Atari 2600 Fun Facts and Information Guide and this post about bankswitching by SeaGtGruff at AtariAge.

 

 

Atari 2600 Specifications

Atari 2600 programming specs (HTML version).

 

 

Atari 2600 Programming Page (AtariAge)

Links to useful information, tools, source code, and documentation.

 

 

MiniDig

Atari 2600 programming site based on Garon's "The Dig," which is now dead.

 

 

TIA Color Charts and Tools

Includes interactive color charts, an NTSC/PAL color conversion tool, and Atari 2600 color compatibility tools that can help you quickly find colors that go great together.

 

 

The Atari 2600 Music and Sound Page

Adapted information and charts related to Atari 2600 music and sound.

 

 

Game Standards and Procedures

A guide and a check list for finished carts.

 

 

Stella

A multi-platform Atari 2600 VCS emulator. It has a built-in debugger to help you with your works in progress or you can use it to study classic games.

 

 

JAVATARI

A very good emulator that can also be embedded on your own web site so people can play the games you make online. It's much better than JStella.

 

 

batari Basic Commands

If assembly language seems a little too hard, don't worry. You can always try to make Atari 2600 games the faster, easier way with batari Basic.

 

 

Atari 2600 BASIC

If assembly language is too hard for you, try batari Basic. It's a BASIC-like language for creating Atari 2600 games. It's the faster, easier way to make Atari 2600 games.

Try batari Basic

Back to Top

 

Disclaimer

View this page and any external web sites at your own risk. I am not responsible for any possible spiritual, emotional, physical, financial or any other damage to you, your friends, family, ancestors, or descendants in the past, present, or future, living or dead, in this dimension or any other.

 

Use any example programs at your own risk. I am not responsible if they blow up your computer or melt your Atari 2600. Use assembly language at your own risk. I am not responsible if assembly language makes you cry or gives you brain damage.

 

Home Inventions Quotations Game Design Atari Memories Personal Pages About Site Map Contact Privacy Policy Tip Jar