It is currently Sat Sep 23, 2017 8:15 pm

All times are UTC - 7 hours





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

Joined: Wed Apr 07, 2010 1:14 am
Posts: 483
Location: Iran
Code:
;NES Programming Tutorial
;Level 6 : Move Background
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Constants
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Variables
L_byte         = $0000
H_byte         = $0001
bg_X_pos       = $0002
bg_Y_pos       = $0003
NMI_index      = $0004
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;iNES header data
;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
  .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 #<bg_nam
   STA L_byte
   LDA #>bg_nam
   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 #<bg_nam_2
   STA L_byte
   LDA #>bg_nam_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

;Reset Scroll
   LDA #$00
   STA $2005
   LDA #$00
   STA $2005
   
;Turn on NMI and rendering
   LDA #%10000000
   STA $2000
   LDA #%00001010
   STA $2001

;Infinite loop
Forever:

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

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

bg_nam_2:
  .incbin "mario_bg_2.nam"

bg_pal:
  .incbin "mario_bg.pal"
;---------------------------; 
  .pad $FFFA,$FF   
;Vectors
  .org $FFFA
  .dw NMI
  .dw RESET
  .dw IRQ
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;CHR data $0000 ~ $1FFF
  .base $0000
  .incbin "mario_bg.chr"
  .pad $2000,$FF


Explanation :

* We enable NMI by setting the 7th bit of $2000

Code:
   LDA #%10000000
   STA $2000


* In this level we are going to use another background

* The data of second background (name table) is stored in the PPU memory from $2400 to $2800 (1KB)

* Extract its data from "Super Mario Bros. (W) [!].nes" and save it as mario_bg_2.nam

* Attach its data to the source code

Code:
bg_nam_2:
  .incbin "mario_bg_2.nam"


* With ;Name table + Attribute 2 codes we transfer the second background data to PPU memory (from $2400 to $2800)

* At first this background is outside of screen and is not visible

* We have to scroll the screen to show the second background

* By scrolling the background actually we are updating the graphic on screen, right? So we have to do it in vBlank period

* So we have to detect when vblank happens

Code:
NMI:
   INC NMI_index
   RTI


* We use a variable, each time vblank happens this variable increase

Code:
vblank_wait:
   LDA NMI_index
not_yet:
   CMP NMI_index
   BEQ not_yet
   RTS 


* With this code we check the variable, we keep looping until it changes which shows a vblank period just has happened

* Need more info about this method? then read this : NMI

* By using JSR ... RTS we make a subroutine. JSR jumps to a label, runs a block of code until it finds RTS then it goes back to its original code

* This loops is infinite and we call it game engine. Here it is very simple.

Code:
;Infinite loop
Forever:

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

   JMP Forever


* Each time it waits for a new vblank period to start.

* Then X coordinate increase by one, so first background moves one pixel to left and the second background appears from right side of screen

Image

* With Vertical Mirroring we can scroll the background horizontally

* With Horizontal Mirroring we can scroll the background vertically

* Need more info? then read this : PPU scrolling

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

Exercise :

Scroll the screen backward or from up to down.

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

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_bg.chr

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

Former Level : NES Programming Tutorial : Background
Next Level : NES Programming Tutorial : Sprite


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 1 guest


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