It is currently Tue Mar 28, 2017 8:53 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 1 post ] 
Author Message
PostPosted: Sat Mar 11, 2017 11:24 am 
Offline
User avatar

Joined: Wed Apr 07, 2010 1:14 am
Posts: 459
Location: Iran
Code:
;NES Programming Tutorial
;Level 7 : Sprite
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Constants
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Variables
L_byte         = $0000
H_byte         = $0001
bg_X_pos       = $0002
bg_Y_pos       = $0003
NMI_index      = $0004

sprite_Y       = $0200
sprite_tile    = $0201
sprite_att     = $0202
sprite_X       = $0203

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;iNES header data (16bytes)
;32KB PRG + 8KB CHR + NROM-256 + Vertical Mirroring
  .db $4E,$45,$53,$1A,$02,$01,$01,$00
  .db $00,$00,$00,$00,$00,$00,$00,$00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;PRG codes $8000 ~ $FFFF (32KB)
  .base $8000

RESET:
   SEI
   CLD

;Turn off NMI and rendering
   LDA #%00000000
   STA $2000
   LDA #%00000000
   STA $2001

;PPU warm up
   LDA $2002
vBlank_wait1:
   BIT $2002
   BPL vBlank_wait1
vBlank_wait2:
   BIT $2002
   BPL vBlank_wait2

;Clear RAM
   LDA #$00
   LDX #$00
clear_loop:
   STA $0000, X
   STA $0100, X
   STA $0200, X
   STA $0300, X
   STA $0400, X
   STA $0500, X
   STA $0600, X
   STA $0700, X
   INX
   CPX #$00
   BNE clear_loop

;Name table + Attribute
   LDA $2002
   LDA #$20
   STA $2006
   LDA #$00
   STA $2006
   LDA #<nam_att
   STA L_byte
   LDA #>nam_att
   STA H_byte
   LDX #$00
   LDY #$00
nam_loop:
   LDA ($00), Y
   STA $2007
   INY
   CPY #$00
   BNE nam_loop
   INC H_byte
   INX
   CPX #$04
   BNE nam_loop

;Name table + Attribute 2
   LDA $2002
   LDA #$24
   STA $2006
   LDA #$00
   STA $2006
   LDA #<nam_att_2
   STA L_byte
   LDA #>nam_att_2
   STA H_byte
   LDX #$00
   LDY #$00
nam_loop_2:
   LDA ($00), Y
   STA $2007
   INY
   CPY #$00
   BNE nam_loop_2
   INC H_byte
   INX
   CPX #$04
   BNE nam_loop_2

;Background color setup
   LDA $2002
   LDA #$3F
   STA $2006
   LDA #$00
   STA $2006
   LDX #$00
bg_pal_loop:
   LDA bg_pal, X
   STA $2007
   INX
   CPX #$10
   BNE bg_pal_loop

;Sprites color setup
   LDA $2002
   LDA #$3F
   STA $2006
   LDA #$10
   STA $2006
   LDX #$00
spt_pal_loop:
   LDA spt_pal, X
   STA $2007
   INX
   CPX #$10
   BNE spt_pal_loop
 
;Sprites data to ram
LoadSprites:
   LDX #$00
LoadSpritesLoop:
   LDA sprites, X
   STA $0200, X
   INX
   CPX #$04
   BNE LoadSpritesLoop
 
;Reset Scroll
   LDA #$00
   STA $2005
   LDA #$00
   STA $2005
   
;Turn on NMI and rendering
   LDA #%10001000
   STA $2000
   LDA #%00011010
   STA $2001

;Infinite loop
Forever:

;Move background
   JSR vblank_wait
   INC bg_X_pos
   LDA bg_X_pos
   STA $2005
   LDA #$00
   STA $2005

;Give effect to sprite
   INC sprite_Y
   
;Sprites data to OAM
   JSR vblank_wait
   LDA #$00
   STA $2003
   LDA sprite_Y
   STA $2004
   LDA sprite_tile
   STA $2004
   LDA sprite_att
   STA $2004
   LDA sprite_X
   STA $2004

   JMP Forever
;---------------------------;
vblank_wait:
   LDA NMI_index
not_yet:
   CMP NMI_index
   BEQ not_yet
   RTS   
;---------------------------;
NMI:
   INC NMI_index
   RTI
;---------------------------;
IRQ:
   RTI
;---------------------------;
nam_att:
  .incbin "mario_bg.nam"

nam_att_2:
  .incbin "mario_bg_2.nam"

bg_pal:
  .incbin "mario_bg.pal"
 
spt_pal:
  .incbin "mario_spt.pal"

sprites:
  .db $80,$65,%00000000,$80
;---------------------------; 
  .pad $FFFA,$FF 
;Vectors
  .org $FFFA
  .dw NMI
  .dw RESET
  .dw IRQ
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;CHR data $0000 ~ $1FFF (8KB)
  .base $0000
  .incbin "mario_bg.chr"
  .incbin "mario_spt.chr"
  .pad $2000,$FF


Output :

Image


Explanation :

* Enable NMI, use left pattern table for background, use right pattern table for sprites

Code:
   LDA #%10001000
   STA $2000


* Show background, show sprites

Code:
   LDA #%00011010
   STA $2001


* The data of sprites tiles is stored in the PPU memory from $0000 to $0FFF (4KB)

* The data of sprites color is stored in the PPU memory from $3F10 to $3F1F (16Bytes)

* Extract those data from "Super Mario Bros. (W) [!].nes" and save them as : mario_spt.chr, mario_spt.pal

* Attach them to the source code

Code:
spt_pal:
  .incbin "mario_spt.pal"


Code:
  .incbin "mario_spt.chr"


* The codes of ;Sprites color setup actually transfers a total of 16 bytes (= 10 bytes in hex) data of sprites color to PPU memory ($3F10 ~ $3F1F)

* Each tile of sprite need 4 byte-info to be able to appear on the screen

* Y coordinate of the sprite on the screen

* One byte for tile number from sprites pattern table

* One byte for the attribute of the sprite, this byte is bit wise

* X coordinate of the sprite on the screen

Code:
sprites:
  .db $80,$65,%00000000,$80


* With this code we take those 4 bytes and save them into ram

Code:
;Sprites data to ram
LoadSprites:
   LDX #$00
LoadSpritesLoop:
   LDA sprites, X
   STA $0200, X
   INX
   CPX #$04
   BNE LoadSpritesLoop


* OAM is a special memory for holding sprites info, it has its own memory space starting from $00 to $FF (256bytes)

* To show a sprite on the screen you have to write its 4byte-info to OAM memory

* Every sprite needs 4 bytes of info, right? So OAM can hold up to 64 sprites at the same time

* We can't write directly to OAM memory, we have to use ports : $2003 and $2004

* With $2003 we declare what address of OAM want to write, then we use $2004 to write the desired value to that address

* Each time we write a value to $2004, the OAM address is automatically adjusted to the next address, so we don't need to declare the OAM address again

Code:
;Give effect to sprite
   INC sprite_Y
   
;Sprites data to OAM
   JSR vblank_wait
   LDA #$00
   STA $2003
   LDA sprite_Y
   STA $2004
   LDA sprite_tile
   STA $2004
   LDA sprite_att
   STA $2004
   LDA sprite_X
   STA $2004


* In the game engine we increase the Y coordinate of the sprite and it seems that sprite is falling

* Need more info about sprites and OAM memory? then read this : PPU OAM

/////////////////////////////////////////////////////////////////////////////////////////////////

Exercise :

Make another sprite on the screen.

/////////////////////////////////////////////////////////////////////////////////////////////////

Files :
asm6.exe
Assembler.bat
Game.asm
name.exe
Bg_Editor.bat
alleg42.dll
mario_bg.nam
mario_bg_2.nam
mario_bg.pal
mario_spt.pal
mario_bg.chr
mario_spt.chr

/////////////////////////////////////////////////////////////////////////////////////////////////

Former Level : NES Programming Tutorial : Move Background
Next Level : NES Programming Tutorial : Multiple Sprites


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 1 post ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group