# Visual Basic > Games and Graphics Programming > Game Demos >  NES 6502 Programming Tutorial - Part 3: Drawing a Sprite

## Jacob Roman

Before we get started, I completely forgot to include demos of Tutorials 1 and 2. So I did that if you wanna see for yourself the results in an emulator. Anyways its time for these tutorials to not be so dull and boring just staring at flat colors, and start drawing sprites for once. Makes it more interesting that way. Well...lets get started!!!

The first thing is that well need a color palette for the sprite loaded. So well have to make a small change with our Colored Background demo:



```
  .inesprg 1   ; 1x 16KB PRG code
  .ineschr 1   ; 1x  8KB CHR data
  .inesmap 0   ; mapper 0 = NROM, no bank swapping
  .inesmir 1   ; background mirroring
  
;;;;;;;;;;;;;;;

  .bank 0
  .org $C000 
RESET:
  SEI          ; disable IRQs
  CLD          ; disable decimal mode
  LDX #$40	
  STX $4017    ; disable APU frame IRQ
  LDX #$FF	
  TXS          ; Set up stack
  INX          ; now X = 0
  STX $2000    ; disable NMI
  STX $2001    ; disable rendering
  STX $4010    ; disable DMC IRQs

vblankwait1:       ; First wait for vblank to make sure PPU is ready
  BIT $2002
  BPL vblankwait1

clrmem:
  LDA #$00
  STA $0000, x
  STA $0100, x
  STA $0400, x
  STA $0500, x
  STA $0600, x
  STA $0700, x
  LDA #$FE
  STA $0300, x
  INX
  BNE clrmem
   
vblankwait2:      ; Second wait for vblank, PPU is ready after this
  BIT $2002
  BPL vblankwait2
  
LoadPalette:
  LDA $2002             ; read PPU status to reset the high/low latch
  LDA #$3F
  STA $2006             ; write the high byte of $3F00 address
  LDA #$00
  STA $2006             ; write the low byte of $3F00 address
  LDX #$00              ; start out at 0

LoadBackgroundPaletteLoop:
  LDA background_palette, x        ; load data from address (palette + the value in x)
                          ; 1st time through loop it will load palette+0
                          ; 2nd time through loop it will load palette+1
                          ; 3rd time through loop it will load palette+2
                          ; etc
  STA $2007             ; write to PPU
  INX                   ; X = X + 1
  CPX #$10              ; Compare X to hex $10, decimal 16
  BNE LoadBackgroundPaletteLoop  ; Branch to LoadBackgroundPaletteLoop if compare was Not Equal to zero
  
  LDX #$00  ;reset the x register to zero so we can start loading sprite palette colors.    
        
LoadSpritePaletteLoop:
  LDA sprite_palette, x     ;load palette byte
  STA $2007					;write to PPU
  INX                   	;set index to next byte
  CPX #$10            
  BNE LoadSpritePaletteLoop  ;if x = $10, all done

Foreverloop:
  JMP Foreverloop     ;jump back to Forever, infinite loop

NMI: 
  RTI

;;;;;;;;;;;;;;  

  .bank 1
  .org $E000
background_palette:
  .db $22,$29,$1A,$0F	;background palette 1
  .db $22,$36,$17,$0F	;background palette 2
  .db $22,$30,$21,$0F	;background palette 3
  .db $22,$27,$17,$0F	;background palette 4
  
sprite_palette:
  .db $22,$16,$27,$18	;sprite palette 1
  .db $22,$1A,$30,$27	;sprite palette 2
  .db $22,$16,$30,$27	;sprite palette 3
  .db $22,$0F,$36,$17	;sprite palette 4

;;;;;;;;;;;;;;  

  .org $FFFA     ;first of the three vectors starts here
  .dw NMI        ;when an NMI happens (once per frame if enabled) the 
                   ;processor will jump to the label NMI:
  .dw RESET      ;when the processor first turns on or is reset, it will jump
                   ;to the label RESET:
  .dw 0          ;external interrupt IRQ is not used in this tutorial
  
;;;;;;;;;;;;;;  

  .bank 2
  .org $0000
  .incbin "mario.chr"   ;includes 8KB graphics file from SMB1
```

The next step is to setup some flags for the PPUCTRL register ($2000 write only) and PPUMASK register ($2001 write only) so we can enable sprites and generate an NMI at the start of the VBlank interval. But it's best you learn what each binary number does:



```
Controller ($2000) > write

    Common name: PPUCTRL
    Description: PPU control register
    Access: write

Various flags controlling PPU operation

7  bit  0
---- ----
VPHB SINN
|||| ||||
|||| ||++- Base nametable address
|||| ||    (0 = $2000; 1 = $2400; 2 = $2800; 3 = $2C00)
|||| |+--- VRAM address increment per CPU read/write of PPUDATA
|||| |     (0: add 1, going across; 1: add 32, going down)
|||| +---- Sprite pattern table address for 8x8 sprites
||||       (0: $0000; 1: $1000; ignored in 8x16 mode)
|||+------ Background pattern table address (0: $0000; 1: $1000)
||+------- Sprite size (0: 8x8; 1: 8x16)
|+-------- PPU master/slave select
|          (0: read backdrop from EXT pins; 1: output color on EXT pins)
+--------- Generate an NMI at the start of the
           vertical blanking interval (0: off; 1: on)
```



```
Mask ($2001) > write

    Common name: PPUMASK
    Description: PPU mask register
    Access: write

This register controls the rendering of sprites and backgrounds, as well as colour effects.

7  bit  0
---- ----
BGRs bMmG
|||| ||||
|||| |||+- Greyscale (0: normal color, 1: produce a greyscale display)
|||| ||+-- 1: Show background in leftmost 8 pixels of screen, 0: Hide
|||| |+--- 1: Show sprites in leftmost 8 pixels of screen, 0: Hide
|||| +---- 1: Show background
|||+------ 1: Show sprites
||+------- Emphasize red*
|+-------- Emphasize green*
+--------- Emphasize blue*
```

So now that you know what the registers do, its time to generate the NMI and draw a sprite from Pattern Table 0. Wait whats Pattern Table 0 you ask? Well, remember when I showed you that Super Mario Bros CHR image?



The left half, believe it or not is Pattern Table 0, and the right half is Pattern Table 1. And for this demo we'll only be snagging it from Pattern Table 0 for simplicity. But wait, there is more!. In the PPUMASK register ($2001), we need to enable sprite drawing in general or we won't see the results. So were going to add a couple of lines of code right after loading the palettes:



```
  .inesprg 1   ; 1x 16KB PRG code
  .ineschr 1   ; 1x  8KB CHR data
  .inesmap 0   ; mapper 0 = NROM, no bank swapping
  .inesmir 1   ; background mirroring
  
;;;;;;;;;;;;;;;

  .bank 0
  .org $C000 
RESET:
  SEI          ; disable IRQs
  CLD          ; disable decimal mode
  LDX #$40	
  STX $4017    ; disable APU frame IRQ
  LDX #$FF	
  TXS          ; Set up stack
  INX          ; now X = 0
  STX $2000    ; disable NMI
  STX $2001    ; disable rendering
  STX $4010    ; disable DMC IRQs

vblankwait1:       ; First wait for vblank to make sure PPU is ready
  BIT $2002
  BPL vblankwait1

clrmem:
  LDA #$00
  STA $0000, x
  STA $0100, x
  STA $0400, x
  STA $0500, x
  STA $0600, x
  STA $0700, x
  LDA #$FE
  STA $0300, x
  INX
  BNE clrmem
   
vblankwait2:      ; Second wait for vblank, PPU is ready after this
  BIT $2002
  BPL vblankwait2
  
LoadPalette:
  LDA $2002             ; read PPU status to reset the high/low latch
  LDA #$3F
  STA $2006             ; write the high byte of $3F00 address
  LDA #$00
  STA $2006             ; write the low byte of $3F00 address
  LDX #$00              ; start out at 0
LoadBackgroundPaletteLoop:
  LDA background_palette, x        ; load data from address (palette + the value in x)
                          ; 1st time through loop it will load palette+0
                          ; 2nd time through loop it will load palette+1
                          ; 3rd time through loop it will load palette+2
                          ; etc
  STA $2007             ; write to PPU
  INX                   ; X = X + 1
  CPX #$10              ; Compare X to hex $10, decimal 16
  BNE LoadBackgroundPaletteLoop  ; Branch to LoadBackgroundPaletteLoop if compare was Not Equal to zero
  
  LDX #$00      
        
LoadSpritePaletteLoop:
  LDA sprite_palette, x     ;load palette byte
  STA $2007					;write to PPU
  INX                   	;set index to next byte
  CPX #$10            
  BNE LoadSpritePaletteLoop  ;if x = $10, all done

  LDA #%10000000   ; enable NMI, sprites from Pattern Table 0
  STA $2000
  
  LDA #%00010000   ; enable sprites
  STA $2001

Foreverloop:
  JMP Foreverloop     ;jump back to Forever, infinite loop

NMI: 
  RTI

;;;;;;;;;;;;;;  

  .bank 1
  .org $E000
background_palette:
  .db $22,$29,$1A,$0F	;background palette 1
  .db $22,$36,$17,$0F	;background palette 2
  .db $22,$30,$21,$0F	;background palette 3
  .db $22,$27,$17,$0F	;background palette 4
  
sprite_palette:
  .db $22,$16,$27,$18	;sprite palette 1
  .db $22,$1A,$30,$27	;sprite palette 2
  .db $22,$16,$30,$27	;sprite palette 3
  .db $22,$0F,$36,$17	;sprite palette 4

;;;;;;;;;;;;;;  

  .org $FFFA     ;first of the three vectors starts here
  .dw NMI        ;when an NMI happens (once per frame if enabled) the 
                   ;processor will jump to the label NMI:
  .dw RESET      ;when the processor first turns on or is reset, it will jump
                   ;to the label RESET:
  .dw 0          ;external interrupt IRQ is not used in this tutorial
  
;;;;;;;;;;;;;;  

  .bank 2
  .org $0000
  .incbin "mario.chr"   ;includes 8KB graphics file from SMB1
```

Now, in order to access any sprite tiles from the Pattern Table, we need to setup access to register $0200, because registers $0200, $0201, $0202, and $0203 is our first sprite (4 bytes). The next 4 bytes is the 2nd sprite, and so on until $02FF, giving us a total of a possible 64 sprites. In all reality, their definition of a sprite for the NES is just any 8x8 tile. Because some sprites programmed are actually a group of sprites used as one. Like small Mario in Super Mario Bros consists of 4 sprites, and big Mario consists of 8 sprites. What do the 4 registers do you ask? I'm glad you asked!

$0200 - The Y coordinate of the sprite on screen$0201 - The Tile Index of the sprite from the Pattern Table, allowing you to pick which tile to use for that sprite.$0202 - The Attribute Table of the sprite. Here's what the binary values represent:


```
76543210
||||||||
||||||++- Palette (4 to 7) of sprite
|||+++--- Unimplemented
||+------ Priority (0: in front of background; 1: behind background)
|+------- Flip sprite horizontally
+-------- Flip sprite vertically
```

$0203 - The X coordinate of the sprite on screen

To setup access to register $0200, well need to write it, little endian style, by writing $00 to the OAM Address register ($2003 write only), and write $02 to the OAM DMA Register ($4014) in the very beginning of the NMI. And believe it or not, since we now enabled the NMI, it'll now fire the NMI sub routine. If you were to write anything such as, for the sake of messing around, changing the background color to black:



```
NMI: 
  LDA #$3F
  STA $2006             ; write the high byte of $3F00 address
  LDA #$00
  STA $2006             ; write the low byte of $3F00 address
  LDA #$0F              ; change background to black (was blue)
  STA $2007 
  RTI
```

and you didn't enable NMI in register $2000, this will completely be ignored, and you be stuck in the Foreverloop. Speaking of the loops, did you know that Foreverloop fires every scanline, whereas NMI fires every frame. So you kinda have 2 loops to possibly work with depending on what you wanna do. And like I said in the first tutorial, you don't need to clear the background at all, because the NES does it for you through the NMI (Non Maskable Interrupt). So lets go ahead and have access to the register $0200:



```
  .inesprg 1   ; 1x 16KB PRG code
  .ineschr 1   ; 1x  8KB CHR data
  .inesmap 0   ; mapper 0 = NROM, no bank swapping
  .inesmir 1   ; background mirroring
  
;;;;;;;;;;;;;;;

  .bank 0
  .org $C000 
RESET:
  SEI          ; disable IRQs
  CLD          ; disable decimal mode
  LDX #$40	
  STX $4017    ; disable APU frame IRQ
  LDX #$FF	
  TXS          ; Set up stack
  INX          ; now X = 0
  STX $2000    ; disable NMI
  STX $2001    ; disable rendering
  STX $4010    ; disable DMC IRQs

vblankwait1:       ; First wait for vblank to make sure PPU is ready
  BIT $2002
  BPL vblankwait1

clrmem:
  LDA #$00
  STA $0000, x
  STA $0100, x
  STA $0400, x
  STA $0500, x
  STA $0600, x
  STA $0700, x
  LDA #$FE
  STA $0300, x
  INX
  BNE clrmem
   
vblankwait2:      ; Second wait for vblank, PPU is ready after this
  BIT $2002
  BPL vblankwait2
  
LoadPalette:
  LDA $2002             ; read PPU status to reset the high/low latch
  LDA #$3F
  STA $2006             ; write the high byte of $3F00 address
  LDA #$00
  STA $2006             ; write the low byte of $3F00 address
  LDX #$00              ; start out at 0
LoadBackgroundPaletteLoop:
  LDA background_palette, x        ; load data from address (palette + the value in x)
                          ; 1st time through loop it will load palette+0
                          ; 2nd time through loop it will load palette+1
                          ; 3rd time through loop it will load palette+2
                          ; etc
  STA $2007             ; write to PPU
  INX                   ; X = X + 1
  CPX #$10              ; Compare X to hex $10, decimal 16
  BNE LoadBackgroundPaletteLoop  ; Branch to LoadBackgroundPaletteLoop if compare was Not Equal to zero
  
  LDX #$00      
        
LoadSpritePaletteLoop:
  LDA sprite_palette, x     ;load palette byte
  STA $2007					;write to PPU
  INX                   	;set index to next byte
  CPX #$10            
  BNE LoadSpritePaletteLoop  ;if x = $10, all done
  
  LDA #%10000000   ; enable NMI, sprites from Pattern Table 0
  STA $2000
  
  LDA #%00010000   ; enable sprites
  STA $2001

Foreverloop:
  JMP Foreverloop     ;jump back to Forever, infinite loop

NMI: 

  LDA #$00
  STA $2003       ; set the low byte (00) of the RAM address
  LDA #$02
  STA $4014       ; set the high byte (02) of the RAM address, start the transfer

  RTI

;;;;;;;;;;;;;;  

  .bank 1
  .org $E000
background_palette:
  .db $22,$29,$1A,$0F	;background palette 1
  .db $22,$36,$17,$0F	;background palette 2
  .db $22,$30,$21,$0F	;background palette 3
  .db $22,$27,$17,$0F	;background palette 4
  
sprite_palette:
  .db $22,$16,$27,$18	;sprite palette 1
  .db $22,$1A,$30,$27	;sprite palette 2
  .db $22,$16,$30,$27	;sprite palette 3
  .db $22,$0F,$36,$17	;sprite palette 4

;;;;;;;;;;;;;;  

  .org $FFFA     ;first of the three vectors starts here
  .dw NMI        ;when an NMI happens (once per frame if enabled) the 
                   ;processor will jump to the label NMI:
  .dw RESET      ;when the processor first turns on or is reset, it will jump
                   ;to the label RESET:
  .dw 0          ;external interrupt IRQ is not used in this tutorial
  
;;;;;;;;;;;;;;  

  .bank 2
  .org $0000
  .incbin "mario.chr"   ;includes 8KB graphics file from SMB1
```

Finally the last step, it's time we setup info on $0200, $0201, $0202, and $0203 so we can finally see it! I want to see the top left section of Mario standing still, which is tile number $3A of Pattern Table 0, so let's go ahead and set it up!

$0200 - $00 (Top of the screen)$0201 - $3A (Top Left section of Mario standing still)$0202 - $00 (No attributes, using first sprite palette which is number 0)$0203 - $00 (Left of the screen)



```
NMI: 
  LDA #$00
  STA $2003       ; set the low byte (00) of the RAM address
  LDA #$02
  STA $4014       ; set the high byte (02) of the RAM address, start the transfer
  
DrawSprite:
  LDA #$00      ; Top of the screen
  STA $0200     ; Sprite Y Position   
  LDA #$3A      ; Top Left section of Mario standing still
  STA $0201     ; Sprite Tile Number
  LDA #$00		; No attributes, using first sprite palette which is number 0
  STA $0202     ; Sprite Attributes
  LDA #$00        ; Left of the screen.
  STA $0203     ; Sprite X Position
  
  RTI
```

After adding this new section of code over where the NMI is, go ahead and compile it, and run it through the emulator. DOH! Where did it go? Turns out that it is off screen. The REAL top left for the sprite is actually $08 $08. So lets change the 2 values.



```
NMI: 
  LDA #$00
  STA $2003       ; set the low byte (00) of the RAM address
  LDA #$02
  STA $4014       ; set the high byte (02) of the RAM address, start the transfer
  
DrawSprite:
  LDA #$08      ; Top of the screen
  STA $0200     ; Sprite Y Position
  LDA #$3A      ; Top Left section of Mario standing still
  STA $0201     ; Sprite Tile Number
  LDA #$00		; No attributes, using first sprite palette which is number 0
  STA $0202     ; Sprite Attributes
  LDA #$08        ; Left of the screen.
  STA $0203     ; Sprite X Position
  
  RTI
```

Save, compile, and run it again.  :Eek Boom:  do you see it?!!! You drew a sprite!!! Congratulations! Lets draw the rest of Mario by using not only 3A, but 37, 4F, and a horizontal mirror of 4F. But, some positions of the sprite tiles will need adjusted or all the tiles will overlap.



```
NMI: 
  LDA #$00
  STA $2003       ; set the low byte (00) of the RAM address
  LDA #$02
  STA $4014       ; set the high byte (02) of the RAM address, start the transfer
  
DrawSprite:
  LDA #$08      ; Top of the screen
  STA $0200     ; Sprite 1 Y Position
  LDA #$08
  STA $0204     ; Sprite 2 Y Position
  LDA #$10
  STA $0208     ; Sprite 3 Y Position
  LDA #$10
  STA $020C     ; Sprite 4 Y Position
  LDA #$3A      ; Top Left section of Mario standing still
  STA $0201     ; Sprite 1 Tile Number
  LDA #$37      ; Top Right section of Mario standing still
  STA $0205     ; Sprite 2 Tile Number
  LDA #$4F      ; Bottom Left section of Mario standing still
  STA $0209     ; Sprite 3 Tile Number
  LDA #$4F      ; Bottom Right section of Mario standing still
  STA $020D     ; Sprite 4 Tile Number
  LDA #$00		; No attributes, using first sprite palette which is number 0
  STA $0202     ; Sprite 1 Attributes
  STA $0206     ; Sprite 2 Attributes
  STA $020A     ; Sprite 3 Attributes
  LDA #$40      ; Flip horizontal attribute
  STA $020E     ; Sprite 4 Attributes
  LDA #$08      ; Left of the screen.
  STA $0203     ; Sprite 1 X Position
  LDA #$10
  STA $0207     ; Sprite 2 X Position
  LDA #$08
  STA $020B     ; Sprite 3 X Position
  LDA #$10
  STA $020F     ; Sprite 4 X Position
  
  RTI
```

Save, compile, and run again. Now little Mario is complete! Next time I'm gonna teach you how to create variables and make Mario move on its own. In the mean time, you can go ahead and download my tutorial. Have a good day!  :big yellow:

----------

