NES Programming Tutorial : iNES Header

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 : iNES Header

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

Code: Select all

;NES Programming Tutorial
;Level 2 : iNES Header
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;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
  ;user codes
  .pad $10000,$FF
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;CHR data $0000 ~ $1FFF (8KB)
  .base $0000
  ;graphic data
  .pad $2000,$FF
Explanation :

* The first 16KB of a nes game is header info which is used just by emulators to run the game. It gives information about PRG size, CHR size, Mapper number, Mirroring, etc.

* I setup the header to : 32KB PRG + 8KB CHR + NROM-256 + Vertical Mirroring.

* Need more info about iNES header? then read this : INES

* lines starting with . are directive commands of assembler

* .db puts a value in the file directly.

* .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

* .pad $10000,$FF is another directive command. It fills the remaining empty space of memory up to $10000 with the value of #$FF

* We need an assembler (ASM6) to convert the source code of assembly language (Game.asm) to object code of machine language (Game.nes) so that you can run it on Emulator

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

How to use ASM6 :

* Download ASM6

* Make a new text file

* Write this inside of it :

Code: Select all

ASM6 Game.asm Game.nes
pause
* Save it with this name : Assembler.bat

* Make sure these files are in the same folder :

Code: Select all

asm6.exe
Assembler.bat
Game.asm
* Run Assembler.bat to make your FIRST NES GAME!

Image

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

How to use Hex Editor :

* Sometimes we need to see the exact values of 0 and 1 inside of a file (object code of machine language), so we use a Hex Editor program like HxD

* Download HxD

* Open Game.NES with HxD

* You can see the header data on the first line, they should match to the values which you used inside of the Game.asm

Image

* Note that values are in Hexadecimal system

* Each value is one byte

* Each byte has it's own address

* Their address starts from zero, so first byte is in the $0 address second byte is in the $01 address, and so on

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

Exercise :

Find out which byte of iNES data controls Mirroring and then set it to Horizontal (Vertical Arrangement).

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

Files :
asm6.exe
Assembler.bat
Game.asm

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

Former Level : NES Programming Tutorial : Source Code Structure
Next Level : NES Programming Tutorial : Interrupts
Last edited by FARID on Fri Mar 17, 2017 10:37 pm, edited 17 times in total.

User avatar
rainwarrior
Posts: 8016
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: NES Programming Tutorial : iNES Header

Post by rainwarrior » Sun Mar 12, 2017 10:39 am

I might suggest writing it out in a way that makes it easier to change and see where the bits are going and what they mean, instead of just making it a block of mysterious hex numbers. In my example program I did it like this:

Code: Select all

INES_MAPPER = 0 ; 0 = NROM
INES_MIRROR = 1 ; 0 = horizontal mirroring, 1 = vertical mirroring
INES_SRAM   = 0 ; 1 = battery backed SRAM at $6000-7FFF

.byte 'N', 'E', 'S', $1A ; ID
.byte $02 ; 16k PRG bank count
.byte $01 ; 8k CHR bank count
.byte INES_MIRROR | (INES_SRAM << 1) | ((INES_MAPPER & $f) << 4)
.byte (INES_MAPPER & %11110000)
.byte $0, $0, $0, $0, $0, $0, $0, $0 ; padding

Pokun
Posts: 1813
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: NES Programming Tutorial : iNES Header

Post by Pokun » Sun Mar 12, 2017 11:02 am

You forgot byte 8 and 9: PRG-RAM size and PAL flag respectively.

User avatar
rainwarrior
Posts: 8016
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: NES Programming Tutorial : iNES Header

Post by rainwarrior » Sun Mar 12, 2017 11:23 am

I didn't forget those. Those two bytes are late extensions by Marat, never really adopted by anyone else, and were also both reclaimed by iNES 2.

Most emulators ignore both of those bytes. Most ROMs that require PRG-RAM have 0 in byte 8, and most PAL ROMs have 0 in byte 9 as well, so emulators have to expect this anyway.

Implementing these in my example header would give the user an unrealistic expectation that either of these bytes is supposed to do something (which they won't, in most emulators), and set them up for a future incompatibility if they ever switch to iNES 2. The safest and most compatible thing is to leave them both as 0.

Pokun
Posts: 1813
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: NES Programming Tutorial : iNES Header

Post by Pokun » Sun Mar 12, 2017 6:05 pm

I see, I thought they where in the official specifications. I guess it's better to use NES 2.0 for the NTSC/PAL setting.

User avatar
rainwarrior
Posts: 8016
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: NES Programming Tutorial : iNES Header

Post by rainwarrior » Sun Mar 12, 2017 6:44 pm

Pokun wrote:I see, I thought they where in the official specifications.
They are, if Marat's spec is the "official" one. He invented the format, and he's the one that made those additions.

If you want the "de facto" standard, though, those bytes aren't really used, probably because it was easier to support the handful of games that needed them through other means (hash, filename, heuristics, etc.), and/or trying to cope with ROMs with garbage in the header's padding area?

Pokun
Posts: 1813
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: NES Programming Tutorial : iNES Header

Post by Pokun » Mon Mar 13, 2017 4:30 pm

Yeah I guess it's what the ROMs use that is the real standard.

Post Reply