Results 1 to 1 of 1

Thread: Atari 2600 Programming Tutorial 3 - The Playfield (Demo Included)

  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 3 - The Playfield (Demo Included)

    Welcome back to another exciting episode of my ultimate Atari 2600 programming tutorial.

    Now things are gonna get interesting because now you are gonna get to plot pixels on the screen! Just one problem though. This one is a pain in the neck because the Atari was designed as a Pong-like system with cutting costs in mind. Even though there are 160 color clocks per visible scanline, there are only 40 pixels across the screen, with every pixel being 4x1 pixels wide. So the dimensions of the draw field pixels are 40x192. Thats why everything in Atari 2600 games looks so wide.

    As for the playfield itself, there are 3 registers. PF0, PF1, and PF2. They only cover half the screen and is mirrored on the other side. PF0 is only 4 pixels wide, PF1 is 8 pixels wide, and PF2 is 8 pixels wide. So if you do the math, 4+8+8 + 4+8+8 = 40 pixels. Even though PF0 is 8 bits, the lower 4 bits are completely ignored by the processor. Any bits that are set will plot the pixels on the screen and mirror it on the other side. But it gets even worse. PF0 and PF2's bits are reveresed! For example if PF0 is 00010000, with the lower 4 bits ignored, and the upper 4 bits reversed, it will draw a pixel on the left side of the screen using 1000. So you can imagine games with scrolling being extremely difficult to program on this beast with not only PF0 and PF2's bits being reversed, but also mirrored on the other side!

    The mirroring can be turned on and off as well with the first bit of CTRLPF.

    Mirroring On:
    Code:
    	lda #%00000001
    	sta CTRLPF

    Mirroring Off:
    Code:
    	lda #%00000000
    	sta CTRLPF
    What that does if the mirroring is on is that the left half of the screen becomes PF0, PF1, PF2 and the right half becomes PF2, PF1, PF0. If the mirroring is off, it becomes PF0, PF1, PF2, and PF0, PF1, PF2.

    But the bits are more than for just mirroring. Take a look at what the other bits do!

    Code:
    CTRLPF
    
         This address is used to write into the playfield control
    
         register (a logic 1 causes action as described below)
    
    
    
         D0 = REF (reflect playfield)
    
    
    
         D1 = SCORE (left half of playfield gets color of player 0,
    
         right half gets color of player 1)
    
    
    
         D2 = PFP (playfield gets priority over players so they can
    
         move behind the playfield)
    
    
    
         D4 & D5 = BALL SIZE
    
                   D5   D4   Width
    
                   0    0    1 clock
    
                   0    1    2 clocks
    
                   1    0    4 clocks
    
                   1    1    8 clocks
    You can also set the color of the playfield through the COLUPF. For example:

    Code:
    	lda #$45
    	sta COLUPF
    This will set the color for the entire playfield to maroon red.

    Now that you got the basics of what a playfield is, it's time to do some code to draw a playfield! In this example we will be drawing a border all around the screen with a blue background:

    Code:
    	processor 6502
    
    	include "vcs.h"
    	include "macro.h"
    	
    
    BLUE         = $9A
    	
    ;------------------------------------------------------------------------------
    	SEG
    	ORG $F000
    	
    Reset
    ; Clear RAM and all TIA registers
    	ldx #0 
    	lda #0 
    Clear           
    	sta 0,x 
    	inx 
    	bne Clear
    ;------------------------------------------------
    ; Once-only initialization. . .
    	lda #BLUE
    	sta COLUBK             ; set the background color
    	
    	lda #$45
    	sta COLUPF
    	
    	lda #%00000001
    	sta CTRLPF
    	
    ;------------------------------------------------
    
    StartOfFrame
    ; Start of new frame
    ; Start of vertical blank processing
    	lda #0
    	sta VBLANK
    	lda #2
    	sta VSYNC
    	sta WSYNC
    	sta WSYNC
    	sta WSYNC               ; 3 scanlines of VSYNC signal
    	lda #0
    	sta VSYNC
    ;------------------------------------------------
    ; 37 scanlines of vertical blank. . .
    	ldx #0
    VerticalBlank   
    	sta WSYNC
    	inx
    	cpx #37
    	bne VerticalBlank
    ;------------------------------------------------
    ; Do 192 scanlines of color-changing (our picture)
          ldx #0                 ; this counts our scanline number
          lda #%11111111
          sta PF0
          sta PF1
          sta PF2
          ; We won't bother rewriting PF0-PF2 every scanline of the top 8 lines - they never change!
    
    Top8Lines       
    	sta WSYNC
        inx
        cpx #8                 ; are we at line 8?
        bne Top8Lines          ; No, so do another
    
        ; Now we want 176 lines of "wall"
        ; Note: 176 (middle) + 8 (top) + 8 (bottom) = 192 lines
    
        lda #%00010000         ; PF0 is mirrored <--- direction, low 4 bits ignored
        sta PF0
        lda #0
        sta PF1
        sta PF2
        ; again, we don't bother writing PF0-PF2 every scanline - they never change!
    
    MiddleLines     
    	sta WSYNC
        inx
        cpx #184
        bne MiddleLines
        ; Finally, our bottom 8 scanlines - the same as the top 8
        ; AGAIN, we aren't going to bother writing PF0-PF2 mid scanline!
        lda #%11111111
        sta PF0
        sta PF1
        sta PF2
    
    Bottom8Lines    
    	sta WSYNC
        inx
        cpx #192
        bne Bottom8Lines
    ;------------------------------------------------
        lda #%01000010
        sta VBLANK          ; end of screen - enter blanking      
    ;------------------------------------------------
    ; 30 scanlines of overscan. . .
    	ldx #0
    Overscan        
    	sta WSYNC
    	inx
    	cpx #30
    	bne Overscan
    	jmp StartOfFrame
    ;------------------------------------------------------------------------------
    
    	ORG $FFFA
    	
    InterruptVectors
    	.word Reset          ; NMI
    	.word Reset          ; RESET
    	.word Reset          ; IRQ
    
    END
    Save the file as playfield.asm, and change the Compile.bat code to this:

    Code:
    @echo off
    dasm playfield.asm -lkernel.txt -f3 -v5 -oplayfield.bin
    Be sure its all in the same folder as the DASM.exe so it can compile! Run the batch file to compile the playfield.asm code. You should have a playfield.bin file created. Run it through Stella and it should look like this:



    And that's how it's done! You can play around with where the pixels are plotted if you'd like, or even change the colors of everything.

    Exercise: Remove the right wall while having the left wall remain!

    Answer to Tutorial 2 exercise:
    Code:
    	processor 6502
    
    	include "vcs.h"
    	include "macro.h"
    
    BLACK         = $00
    	
    ;------------------------------------------------------------------------------
    	SEG
    	ORG $F000
    	
    Reset
    ; Clear RAM and all TIA registers
    	ldx #0 
    	lda #0 
    Clear           
    	sta 0,x 
    	inx 
    	bne Clear
    ;------------------------------------------------
    ; Once-only initialization. . .
    	lda #BLACK
    	sta COLUBK             ; set the background color
    ;------------------------------------------------
    
    StartOfFrame
    ; Start of new frame
    ; Start of vertical blank processing
    	lda #0
    	sta VBLANK
    	lda #2
    	sta VSYNC
    	sta WSYNC
    	sta WSYNC
    	sta WSYNC               ; 3 scanlines of VSYNC signal
    	lda #0
    	sta VSYNC
    ;------------------------------------------------
    ; 37 scanlines of vertical blank. . .
    	ldx #0
    VerticalBlank   
    	sta WSYNC
    	inx
    	cpx #37
    	bne VerticalBlank
    ;------------------------------------------------
    ;192 lines of drawfield
            ldx #0
    DrawField:
    
    	sta WSYNC
            inx
    	stx COLUBK
    	cpx #192
    	bne DrawField
    ;------------------------------------------------
    ; end of screen - enter blanking
            lda #%01000010
            sta VBLANK          
    ;------------------------------------------------
    ; 30 scanlines of overscan. . .
    	ldx #0
    Overscan        
    	sta WSYNC
    	inx
    	cpx #30
    	bne Overscan
    	jmp StartOfFrame
    ;------------------------------------------------
    
    	ORG $FFFA
    	
    InterruptVectors
    	.word Reset          ; NMI
    	.word Reset          ; RESET
    	.word Reset          ; IRQ
    
    END
    Next tutorial I'm gonna show you how to do real graphics through asymmetrical playfields
    Attached Files Attached Files

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