NES Programming Tutorial : Interrupts

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
User avatar
FARID
Posts: 499
Joined: Wed Apr 07, 2010 1:14 am
Location: Iran
Contact:

NES Programming Tutorial : Interrupts

Post by FARID » Sat Mar 11, 2017 11:24 am

CPU & PPU Memory Map :

* CPU Memory address starts from $0000 to $FFFF :

Image

* Need more info about CPU memory map? then check this : CPU memory map

* PPU Memory address starts from $0000 to $3FFF :

Image

* Need more info about PPU memory map? then check this : PPU memory map

* Here is the structure of a NES file (NROM-256 Mapper 0) :

Image

* When the game runs PRG of the game ($0010 to $8010) is loaded into CPU memory ($8000 to $10000)

* CHR of the game ($$8010 to $A010) is loaded into PPU memory ($0000 to $2000)

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

How to separate PRG and CHR of a nes game :

* PRG and CHR are stored inside of two separated EPROM memories :

Image

* To make the cartridge we have to remove the iNES header and binary files of PRG and CHR separately

* We can use HxD to do it but a better way is to use famiROM :

Image

* Just load the desired game and click on split

* PRG.bin and CHR.bin of the game are generated and ready to use

* These files must be trasfered to EPROM memories by using programmer

* Need more info about making a nes cartridge? then check ROM Laboratory : Link1 Link2

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

Code: Select all

;NES Programming Tutorial
;Level 3 : Interrupts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Constants
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Variables
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;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:

;Infinite loop
Forever:
   JMP Forever
;---------------------------;
NMI:
   RTI
;---------------------------;
IRQ:
   RTI
;---------------------------;
  .pad $FFFA,$FF
;Vectors
  .org $FFFA
  .dw NMI
  .dw RESET
  .dw IRQ
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;CHR data $0000 ~ $1FFF (8KB)
  .base $0000
  ;graphic data
  .pad $2000,$FF
Explanation :

* .base $8000 is another directive command. It tells the assembler that the following commands will be loaded into $8000 of CPU. So labels addresses are adjusted according to $8000

* RESET: is just a label. Name a label anything you want. After assembling the code, labels are translated to an address

* JMP is a 6502 opcode. It tells the CPU to jump to a label and continue the execution from there. In the example I made an infinite loop by using JMP and a label to prevent CPU from executing other irrelevant opcodes

* RTI tells the CPU to go back to the normal routine after finishing an interrupt

* .org $FFFA puts its following code exactly in the mentioned address

* A Label's address is 16bit, .dw breaks the address of the Label into two bytes and put them in two offset. NES CPU is little endian, it means the Low byte of the address must be stored first and then the High byte of the address must be stored, so that NES CPU can read and use that address correctly

* There are three interrupts in NES :
1) Reset : when the console turns on, the cpu execute the codes from this address
2) NMI : Before showing a new frame of picture on TV there is a period called vBlank or vertical blank to clean the screen, when vBlank starts NMI interrupt happens. During vBlank we can change the graphic of the new frame
3) Some advanced games use this interrupt. I don't know how to use it yet so let's ignore it for now!

* Need More info about interrupts? then read this : CPU interrupts

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

Exercise :

Put NMI label in the address of $9000.

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

Files :
asm6.exe
Assembler.bat
Game.asm

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

Former Level : NES Programming Tutorial : iNES Header
Next Level : NES Programming Tutorial : Init Code
Last edited by FARID on Fri Mar 31, 2017 10:34 am, edited 19 times in total.

Garth
Posts: 208
Joined: Wed Nov 30, 2016 4:45 pm
Location: Southern California
Contact:

Re: NES Programming Tutorial : Interrupts

Post by Garth » Sat Mar 11, 2017 8:14 pm

I have a 6502 interrupts primer at http://wilsonminesco.com/6502interrupts/ . It's not NES-specific (or even game-specific), but pretty detailed. Enjoy my outdated cartoons!
http://WilsonMinesCo.com/ lots of 6502 resources

User avatar
za909
Posts: 226
Joined: Fri Jan 24, 2014 9:05 am
Location: Hungary

Re: NES Programming Tutorial : Interrupts

Post by za909 » Fri Mar 31, 2017 6:39 am

Two things that stood out to me:
- $2007 is the PPU_DATA register, your table makes it look like it is part of the mirorred address space.
- The iNES header is 16 bytes, not 256 (but the rest of the tutorial with the ROM addresses actually considers it 16 bytes).

User avatar
Quietust
Posts: 1710
Joined: Sun Sep 19, 2004 10:59 pm
Contact:

Re: NES Programming Tutorial : Interrupts

Post by Quietust » Sat Apr 01, 2017 7:17 am

za909 wrote:Two things that stood out to me:
- $2007 is the PPU_DATA register, your table makes it look like it is part of the mirorred address space.
The same is true of "Sound & Joypad Ports" - the "unused" section following it should begin at $4018, not $4017.

Also, most of the "unused" areas aren't really unused - they're mirrors of the regions preceding them. The only exception is $4018-$5FFF, which really is unused (and is used by some cartridges for ROM/RAM or I/O registers).

Also also, $0200-$02FF isn't formally defined as Sprite Data - most games just happen to use it that way because it's adjacent to the Stack, an area which does have a special meaning (and which typically won't be used for general-purpose variables).
Quietust, QMT Productions
P.S. If you don't get this note, let me know and I'll write you another.

Post Reply